summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorneel <neel@FreeBSD.org>2014-09-27 22:15:50 +0000
committerneel <neel@FreeBSD.org>2014-09-27 22:15:50 +0000
commit09ab9e29373f2b48f72ff71789f6afc0e01c2c91 (patch)
tree946f5a62ce46b853d35291bd0a8f36622d72980b
parent11f176f81434584587aa1973f46fae8948a837b2 (diff)
parent54f38c8738077e829c5528976a3269afc01ff7ee (diff)
downloadFreeBSD-src-09ab9e29373f2b48f72ff71789f6afc0e01c2c91.zip
FreeBSD-src-09ab9e29373f2b48f72ff71789f6afc0e01c2c91.tar.gz
IFC @r272185
-rw-r--r--Makefile.inc18
-rw-r--r--ObsoleteFiles.inc3
-rw-r--r--UPDATING12
-rw-r--r--bin/sh/sh.15
-rw-r--r--cddl/contrib/opensolaris/cmd/dtrace/dtrace.127
-rw-r--r--cddl/contrib/opensolaris/cmd/zpool/zpool_main.c11
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/drti.c14
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c1
-rw-r--r--cddl/usr.sbin/Makefile4
-rw-r--r--contrib/apr-util/CHANGES26
-rw-r--r--contrib/apr-util/NOTICE4
-rw-r--r--contrib/apr-util/apr-util.spec2
-rwxr-xr-xcontrib/apr-util/configure63
-rw-r--r--contrib/apr-util/crypto/apr_crypto.c2
-rw-r--r--contrib/apr-util/crypto/apr_passwd.c10
-rw-r--r--contrib/apr-util/dbd/apr_dbd_mysql.c4
-rw-r--r--contrib/apr-util/dbd/apr_dbd_odbc.c35
-rw-r--r--contrib/apr-util/dbm/NWGNUmakefile2
-rw-r--r--contrib/apr-util/include/apu_version.h4
-rw-r--r--contrib/apr-util/test/Makefile.win2
-rw-r--r--contrib/atf/FREEBSD-upgrade7
-rw-r--r--contrib/atf/atf-c++/atf-c++-api.315
-rw-r--r--contrib/atf/atf-c/atf-c-api.315
-rw-r--r--contrib/atf/atf-sh/atf-check.116
-rw-r--r--contrib/atf/atf-sh/atf-sh-api.315
-rw-r--r--contrib/atf/atf-sh/atf-sh.117
-rw-r--r--contrib/atf/doc/atf-test-case.414
-rw-r--r--contrib/atf/doc/atf-test-program.114
-rw-r--r--contrib/hyperv/tools/hv_kvp_daemon.c53
-rw-r--r--contrib/ipfilter/lib/gethost.c9
-rw-r--r--contrib/ipfilter/lib/printnat.c6
-rw-r--r--contrib/ipfilter/tools/ipf_y.y32
-rw-r--r--contrib/ipfilter/tools/ipnat_y.y38
-rw-r--r--contrib/llvm/patches/patch-r269387-clang-arm-target-cpu.diff34
-rw-r--r--contrib/llvm/patches/patch-r270147-llvm-r197824-r213427-r213960.diff24
-rw-r--r--contrib/llvm/patches/patch-r271024-llvm-r216989-fix-movm-armv6.diff14
-rw-r--r--contrib/llvm/patches/patch-r271024-llvm-r216989-r216990-fix-movw-armv6.diff78
-rw-r--r--contrib/llvm/patches/patch-r271282-clang-r200797-r200798-r200805-debug-info-crash.diff75
-rw-r--r--contrib/llvm/patches/patch-r271432-clang-r205331-debug-info-crash.diff33
-rw-r--r--contrib/llvm/patches/patch-r271597-clang-r217410-i386-garbage-float.diff64
-rw-r--r--contrib/ofed/libibverbs/examples/asyncwatch.c2
-rw-r--r--contrib/ofed/libibverbs/examples/device_list.c3
-rw-r--r--contrib/ofed/libibverbs/examples/devinfo.c2
-rw-r--r--contrib/ofed/libmlx4/src/mlx4-abi.h2
-rw-r--r--contrib/pjdfstest/FREEBSD-upgrade25
-rw-r--r--contrib/pjdfstest/LICENSE (renamed from tools/regression/pjdfstest/LICENSE)4
-rw-r--r--contrib/pjdfstest/Makefile (renamed from tools/regression/pjdfstest/Makefile)2
-rw-r--r--contrib/pjdfstest/README (renamed from tools/regression/pjdfstest/README)4
-rw-r--r--contrib/pjdfstest/pjdfstest.c (renamed from tools/regression/pjdfstest/pjdfstest.c)0
-rw-r--r--contrib/pjdfstest/tests/chflags/00.t (renamed from tools/regression/pjdfstest/tests/chflags/00.t)2
-rw-r--r--contrib/pjdfstest/tests/chflags/01.t (renamed from tools/regression/pjdfstest/tests/chflags/01.t)2
-rw-r--r--contrib/pjdfstest/tests/chflags/02.t (renamed from tools/regression/pjdfstest/tests/chflags/02.t)2
-rw-r--r--contrib/pjdfstest/tests/chflags/03.t (renamed from tools/regression/pjdfstest/tests/chflags/03.t)2
-rw-r--r--contrib/pjdfstest/tests/chflags/04.t (renamed from tools/regression/pjdfstest/tests/chflags/04.t)2
-rw-r--r--contrib/pjdfstest/tests/chflags/05.t (renamed from tools/regression/pjdfstest/tests/chflags/05.t)2
-rw-r--r--contrib/pjdfstest/tests/chflags/06.t (renamed from tools/regression/pjdfstest/tests/chflags/06.t)2
-rw-r--r--contrib/pjdfstest/tests/chflags/07.t (renamed from tools/regression/pjdfstest/tests/chflags/07.t)2
-rw-r--r--contrib/pjdfstest/tests/chflags/08.t (renamed from tools/regression/pjdfstest/tests/chflags/08.t)2
-rw-r--r--contrib/pjdfstest/tests/chflags/09.t (renamed from tools/regression/pjdfstest/tests/chflags/09.t)2
-rw-r--r--contrib/pjdfstest/tests/chflags/10.t (renamed from tools/regression/pjdfstest/tests/chflags/10.t)2
-rw-r--r--contrib/pjdfstest/tests/chflags/11.t (renamed from tools/regression/pjdfstest/tests/chflags/11.t)2
-rw-r--r--contrib/pjdfstest/tests/chflags/12.t (renamed from tools/regression/pjdfstest/tests/chflags/12.t)12
-rw-r--r--contrib/pjdfstest/tests/chflags/13.t (renamed from tools/regression/pjdfstest/tests/chflags/13.t)2
-rw-r--r--contrib/pjdfstest/tests/chmod/00.t (renamed from tools/regression/pjdfstest/tests/chmod/00.t)2
-rw-r--r--contrib/pjdfstest/tests/chmod/01.t (renamed from tools/regression/pjdfstest/tests/chmod/01.t)2
-rw-r--r--contrib/pjdfstest/tests/chmod/02.t (renamed from tools/regression/pjdfstest/tests/chmod/02.t)2
-rw-r--r--contrib/pjdfstest/tests/chmod/03.t (renamed from tools/regression/pjdfstest/tests/chmod/03.t)2
-rw-r--r--contrib/pjdfstest/tests/chmod/04.t (renamed from tools/regression/pjdfstest/tests/chmod/04.t)2
-rw-r--r--contrib/pjdfstest/tests/chmod/05.t (renamed from tools/regression/pjdfstest/tests/chmod/05.t)2
-rw-r--r--contrib/pjdfstest/tests/chmod/06.t (renamed from tools/regression/pjdfstest/tests/chmod/06.t)2
-rw-r--r--contrib/pjdfstest/tests/chmod/07.t (renamed from tools/regression/pjdfstest/tests/chmod/07.t)2
-rw-r--r--contrib/pjdfstest/tests/chmod/08.t (renamed from tools/regression/pjdfstest/tests/chmod/08.t)2
-rw-r--r--contrib/pjdfstest/tests/chmod/09.t (renamed from tools/regression/pjdfstest/tests/chmod/09.t)10
-rw-r--r--contrib/pjdfstest/tests/chmod/10.t (renamed from tools/regression/pjdfstest/tests/chmod/10.t)2
-rw-r--r--contrib/pjdfstest/tests/chmod/11.t (renamed from tools/regression/pjdfstest/tests/chmod/11.t)2
-rw-r--r--contrib/pjdfstest/tests/chmod/12.t (renamed from tools/regression/pjdfstest/tests/chmod/12.t)2
-rwxr-xr-xcontrib/pjdfstest/tests/chmod/foo0
-rw-r--r--contrib/pjdfstest/tests/chown/00.t (renamed from tools/regression/pjdfstest/tests/chown/00.t)2
-rw-r--r--contrib/pjdfstest/tests/chown/01.t (renamed from tools/regression/pjdfstest/tests/chown/01.t)2
-rw-r--r--contrib/pjdfstest/tests/chown/02.t (renamed from tools/regression/pjdfstest/tests/chown/02.t)2
-rw-r--r--contrib/pjdfstest/tests/chown/03.t (renamed from tools/regression/pjdfstest/tests/chown/03.t)2
-rw-r--r--contrib/pjdfstest/tests/chown/04.t (renamed from tools/regression/pjdfstest/tests/chown/04.t)2
-rw-r--r--contrib/pjdfstest/tests/chown/05.t (renamed from tools/regression/pjdfstest/tests/chown/05.t)2
-rw-r--r--contrib/pjdfstest/tests/chown/06.t (renamed from tools/regression/pjdfstest/tests/chown/06.t)2
-rw-r--r--contrib/pjdfstest/tests/chown/07.t (renamed from tools/regression/pjdfstest/tests/chown/07.t)2
-rw-r--r--contrib/pjdfstest/tests/chown/08.t (renamed from tools/regression/pjdfstest/tests/chown/08.t)2
-rw-r--r--contrib/pjdfstest/tests/chown/09.t (renamed from tools/regression/pjdfstest/tests/chown/09.t)10
-rw-r--r--contrib/pjdfstest/tests/chown/10.t (renamed from tools/regression/pjdfstest/tests/chown/10.t)2
-rw-r--r--contrib/pjdfstest/tests/conf (renamed from tools/regression/pjdfstest/tests/conf)2
-rw-r--r--contrib/pjdfstest/tests/ftruncate/00.t (renamed from tools/regression/pjdfstest/tests/ftruncate/00.t)4
-rw-r--r--contrib/pjdfstest/tests/ftruncate/01.t (renamed from tools/regression/pjdfstest/tests/truncate/01.t)2
-rw-r--r--contrib/pjdfstest/tests/ftruncate/02.t (renamed from tools/regression/pjdfstest/tests/truncate/02.t)2
-rw-r--r--contrib/pjdfstest/tests/ftruncate/03.t (renamed from tools/regression/pjdfstest/tests/truncate/03.t)2
-rw-r--r--contrib/pjdfstest/tests/ftruncate/04.t (renamed from tools/regression/pjdfstest/tests/truncate/04.t)2
-rw-r--r--contrib/pjdfstest/tests/ftruncate/05.t (renamed from tools/regression/pjdfstest/tests/truncate/05.t)2
-rw-r--r--contrib/pjdfstest/tests/ftruncate/06.t (renamed from tools/regression/pjdfstest/tests/truncate/06.t)2
-rw-r--r--contrib/pjdfstest/tests/ftruncate/07.t (renamed from tools/regression/pjdfstest/tests/truncate/07.t)2
-rw-r--r--contrib/pjdfstest/tests/ftruncate/08.t (renamed from tools/regression/pjdfstest/tests/truncate/08.t)2
-rw-r--r--contrib/pjdfstest/tests/ftruncate/09.t (renamed from tools/regression/pjdfstest/tests/truncate/09.t)2
-rw-r--r--contrib/pjdfstest/tests/ftruncate/10.t (renamed from tools/regression/pjdfstest/tests/truncate/10.t)10
-rw-r--r--contrib/pjdfstest/tests/ftruncate/11.t (renamed from tools/regression/pjdfstest/tests/truncate/11.t)2
-rw-r--r--contrib/pjdfstest/tests/ftruncate/12.t (renamed from tools/regression/pjdfstest/tests/truncate/12.t)2
-rw-r--r--contrib/pjdfstest/tests/ftruncate/13.t16
-rw-r--r--contrib/pjdfstest/tests/ftruncate/14.t (renamed from tools/regression/pjdfstest/tests/truncate/14.t)2
-rw-r--r--contrib/pjdfstest/tests/granular/00.t (renamed from tools/regression/pjdfstest/tests/granular/00.t)2
-rw-r--r--contrib/pjdfstest/tests/granular/01.t (renamed from tools/regression/pjdfstest/tests/granular/01.t)2
-rw-r--r--contrib/pjdfstest/tests/granular/02.t (renamed from tools/regression/pjdfstest/tests/granular/02.t)2
-rw-r--r--contrib/pjdfstest/tests/granular/03.t (renamed from tools/regression/pjdfstest/tests/granular/03.t)2
-rw-r--r--contrib/pjdfstest/tests/granular/04.t (renamed from tools/regression/pjdfstest/tests/granular/04.t)2
-rw-r--r--contrib/pjdfstest/tests/granular/05.t (renamed from tools/regression/pjdfstest/tests/granular/05.t)2
-rw-r--r--contrib/pjdfstest/tests/link/00.t (renamed from tools/regression/pjdfstest/tests/link/00.t)2
-rw-r--r--contrib/pjdfstest/tests/link/01.t (renamed from tools/regression/pjdfstest/tests/link/01.t)2
-rw-r--r--contrib/pjdfstest/tests/link/02.t (renamed from tools/regression/pjdfstest/tests/link/02.t)2
-rw-r--r--contrib/pjdfstest/tests/link/03.t (renamed from tools/regression/pjdfstest/tests/link/03.t)2
-rw-r--r--contrib/pjdfstest/tests/link/04.t (renamed from tools/regression/pjdfstest/tests/link/04.t)2
-rw-r--r--contrib/pjdfstest/tests/link/05.t (renamed from tools/regression/pjdfstest/tests/link/05.t)10
-rw-r--r--contrib/pjdfstest/tests/link/06.t (renamed from tools/regression/pjdfstest/tests/link/06.t)2
-rw-r--r--contrib/pjdfstest/tests/link/07.t (renamed from tools/regression/pjdfstest/tests/link/07.t)2
-rw-r--r--contrib/pjdfstest/tests/link/08.t (renamed from tools/regression/pjdfstest/tests/link/08.t)2
-rw-r--r--contrib/pjdfstest/tests/link/09.t (renamed from tools/regression/pjdfstest/tests/link/09.t)2
-rw-r--r--contrib/pjdfstest/tests/link/10.t (renamed from tools/regression/pjdfstest/tests/link/10.t)2
-rw-r--r--contrib/pjdfstest/tests/link/11.t (renamed from tools/regression/pjdfstest/tests/link/11.t)2
-rw-r--r--contrib/pjdfstest/tests/link/12.t (renamed from tools/regression/pjdfstest/tests/link/12.t)2
-rw-r--r--contrib/pjdfstest/tests/link/13.t (renamed from tools/regression/pjdfstest/tests/link/13.t)2
-rw-r--r--contrib/pjdfstest/tests/link/14.t (renamed from tools/regression/pjdfstest/tests/link/14.t)10
-rw-r--r--contrib/pjdfstest/tests/link/15.t (renamed from tools/regression/pjdfstest/tests/link/15.t)10
-rw-r--r--contrib/pjdfstest/tests/link/16.t (renamed from tools/regression/pjdfstest/tests/link/16.t)10
-rw-r--r--contrib/pjdfstest/tests/link/17.t (renamed from tools/regression/pjdfstest/tests/link/17.t)2
-rwxr-xr-x[-rw-r--r--]contrib/pjdfstest/tests/misc.sh (renamed from tools/regression/pjdfstest/tests/misc.sh)0
-rw-r--r--contrib/pjdfstest/tests/mkdir/00.t (renamed from tools/regression/pjdfstest/tests/mkdir/00.t)2
-rw-r--r--contrib/pjdfstest/tests/mkdir/01.t (renamed from tools/regression/pjdfstest/tests/mkdir/01.t)2
-rw-r--r--contrib/pjdfstest/tests/mkdir/02.t (renamed from tools/regression/pjdfstest/tests/mkdir/02.t)2
-rw-r--r--contrib/pjdfstest/tests/mkdir/03.t (renamed from tools/regression/pjdfstest/tests/mkdir/03.t)2
-rw-r--r--contrib/pjdfstest/tests/mkdir/04.t (renamed from tools/regression/pjdfstest/tests/mkdir/04.t)2
-rw-r--r--contrib/pjdfstest/tests/mkdir/05.t (renamed from tools/regression/pjdfstest/tests/mkdir/05.t)2
-rw-r--r--contrib/pjdfstest/tests/mkdir/06.t (renamed from tools/regression/pjdfstest/tests/mkdir/06.t)2
-rw-r--r--contrib/pjdfstest/tests/mkdir/07.t (renamed from tools/regression/pjdfstest/tests/mkdir/07.t)2
-rw-r--r--contrib/pjdfstest/tests/mkdir/08.t (renamed from tools/regression/pjdfstest/tests/mkdir/08.t)2
-rw-r--r--contrib/pjdfstest/tests/mkdir/09.t (renamed from tools/regression/pjdfstest/tests/mkdir/09.t)10
-rw-r--r--contrib/pjdfstest/tests/mkdir/10.t (renamed from tools/regression/pjdfstest/tests/mkdir/10.t)2
-rw-r--r--contrib/pjdfstest/tests/mkdir/11.t (renamed from tools/regression/pjdfstest/tests/mkdir/11.t)10
-rw-r--r--contrib/pjdfstest/tests/mkdir/12.t (renamed from tools/regression/pjdfstest/tests/mkdir/12.t)2
-rw-r--r--contrib/pjdfstest/tests/mkfifo/00.t (renamed from tools/regression/pjdfstest/tests/mkfifo/00.t)2
-rw-r--r--contrib/pjdfstest/tests/mkfifo/01.t (renamed from tools/regression/pjdfstest/tests/mkfifo/01.t)2
-rw-r--r--contrib/pjdfstest/tests/mkfifo/02.t (renamed from tools/regression/pjdfstest/tests/mkfifo/02.t)2
-rw-r--r--contrib/pjdfstest/tests/mkfifo/03.t (renamed from tools/regression/pjdfstest/tests/mkfifo/03.t)2
-rw-r--r--contrib/pjdfstest/tests/mkfifo/04.t (renamed from tools/regression/pjdfstest/tests/mkfifo/04.t)2
-rw-r--r--contrib/pjdfstest/tests/mkfifo/05.t (renamed from tools/regression/pjdfstest/tests/mkfifo/05.t)2
-rw-r--r--contrib/pjdfstest/tests/mkfifo/06.t (renamed from tools/regression/pjdfstest/tests/mkfifo/06.t)2
-rw-r--r--contrib/pjdfstest/tests/mkfifo/07.t (renamed from tools/regression/pjdfstest/tests/mkfifo/07.t)2
-rw-r--r--contrib/pjdfstest/tests/mkfifo/08.t (renamed from tools/regression/pjdfstest/tests/mkfifo/08.t)10
-rw-r--r--contrib/pjdfstest/tests/mkfifo/09.t (renamed from tools/regression/pjdfstest/tests/mkfifo/09.t)2
-rw-r--r--contrib/pjdfstest/tests/mkfifo/10.t (renamed from tools/regression/pjdfstest/tests/mkfifo/10.t)2
-rw-r--r--contrib/pjdfstest/tests/mkfifo/11.t (renamed from tools/regression/pjdfstest/tests/mkfifo/11.t)10
-rw-r--r--contrib/pjdfstest/tests/mkfifo/12.t (renamed from tools/regression/pjdfstest/tests/mkfifo/12.t)2
-rw-r--r--contrib/pjdfstest/tests/mknod/00.t (renamed from tools/regression/pjdfstest/tests/mknod/00.t)2
-rw-r--r--contrib/pjdfstest/tests/mknod/01.t (renamed from tools/regression/pjdfstest/tests/mknod/01.t)2
-rw-r--r--contrib/pjdfstest/tests/mknod/02.t (renamed from tools/regression/pjdfstest/tests/mknod/02.t)2
-rw-r--r--contrib/pjdfstest/tests/mknod/03.t (renamed from tools/regression/pjdfstest/tests/mknod/03.t)2
-rw-r--r--contrib/pjdfstest/tests/mknod/04.t (renamed from tools/regression/pjdfstest/tests/mknod/04.t)2
-rw-r--r--contrib/pjdfstest/tests/mknod/05.t (renamed from tools/regression/pjdfstest/tests/mknod/05.t)2
-rw-r--r--contrib/pjdfstest/tests/mknod/06.t (renamed from tools/regression/pjdfstest/tests/mknod/06.t)2
-rw-r--r--contrib/pjdfstest/tests/mknod/07.t (renamed from tools/regression/pjdfstest/tests/mknod/07.t)2
-rw-r--r--contrib/pjdfstest/tests/mknod/08.t (renamed from tools/regression/pjdfstest/tests/mknod/08.t)2
-rw-r--r--contrib/pjdfstest/tests/mknod/09.t (renamed from tools/regression/pjdfstest/tests/mknod/09.t)2
-rw-r--r--contrib/pjdfstest/tests/mknod/10.t (renamed from tools/regression/pjdfstest/tests/mknod/10.t)2
-rw-r--r--contrib/pjdfstest/tests/mknod/11.t (renamed from tools/regression/pjdfstest/tests/mknod/11.t)2
-rw-r--r--contrib/pjdfstest/tests/open/00.t (renamed from tools/regression/pjdfstest/tests/open/00.t)2
-rw-r--r--contrib/pjdfstest/tests/open/01.t (renamed from tools/regression/pjdfstest/tests/open/01.t)2
-rw-r--r--contrib/pjdfstest/tests/open/02.t (renamed from tools/regression/pjdfstest/tests/open/02.t)2
-rw-r--r--contrib/pjdfstest/tests/open/03.t (renamed from tools/regression/pjdfstest/tests/open/03.t)2
-rw-r--r--contrib/pjdfstest/tests/open/04.t (renamed from tools/regression/pjdfstest/tests/open/04.t)2
-rw-r--r--contrib/pjdfstest/tests/open/05.t (renamed from tools/regression/pjdfstest/tests/open/05.t)2
-rw-r--r--contrib/pjdfstest/tests/open/06.t (renamed from tools/regression/pjdfstest/tests/open/06.t)2
-rw-r--r--contrib/pjdfstest/tests/open/07.t (renamed from tools/regression/pjdfstest/tests/open/07.t)2
-rw-r--r--contrib/pjdfstest/tests/open/08.t (renamed from tools/regression/pjdfstest/tests/open/08.t)2
-rw-r--r--contrib/pjdfstest/tests/open/09.t (renamed from tools/regression/pjdfstest/tests/open/09.t)2
-rw-r--r--contrib/pjdfstest/tests/open/10.t (renamed from tools/regression/pjdfstest/tests/open/10.t)2
-rw-r--r--contrib/pjdfstest/tests/open/11.t (renamed from tools/regression/pjdfstest/tests/open/11.t)2
-rw-r--r--contrib/pjdfstest/tests/open/12.t (renamed from tools/regression/pjdfstest/tests/open/12.t)2
-rw-r--r--contrib/pjdfstest/tests/open/13.t (renamed from tools/regression/pjdfstest/tests/open/13.t)2
-rw-r--r--contrib/pjdfstest/tests/open/14.t (renamed from tools/regression/pjdfstest/tests/open/14.t)10
-rw-r--r--contrib/pjdfstest/tests/open/15.t (renamed from tools/regression/pjdfstest/tests/open/15.t)10
-rw-r--r--contrib/pjdfstest/tests/open/16.t27
-rw-r--r--contrib/pjdfstest/tests/open/17.t (renamed from tools/regression/pjdfstest/tests/open/17.t)2
-rw-r--r--contrib/pjdfstest/tests/open/18.t (renamed from tools/regression/pjdfstest/tests/open/18.t)2
-rw-r--r--contrib/pjdfstest/tests/open/19.t (renamed from tools/regression/pjdfstest/tests/open/19.t)10
-rw-r--r--contrib/pjdfstest/tests/open/20.t (renamed from tools/regression/pjdfstest/tests/open/20.t)2
-rw-r--r--contrib/pjdfstest/tests/open/21.t (renamed from tools/regression/pjdfstest/tests/open/21.t)2
-rw-r--r--contrib/pjdfstest/tests/open/22.t (renamed from tools/regression/pjdfstest/tests/open/22.t)2
-rw-r--r--contrib/pjdfstest/tests/open/23.t (renamed from tools/regression/pjdfstest/tests/open/23.t)2
-rw-r--r--contrib/pjdfstest/tests/open/24.t (renamed from tools/regression/pjdfstest/tests/open/24.t)2
-rw-r--r--contrib/pjdfstest/tests/rename/00.t (renamed from tools/regression/pjdfstest/tests/rename/00.t)2
-rw-r--r--contrib/pjdfstest/tests/rename/01.t (renamed from tools/regression/pjdfstest/tests/rename/01.t)2
-rw-r--r--contrib/pjdfstest/tests/rename/02.t (renamed from tools/regression/pjdfstest/tests/rename/02.t)2
-rw-r--r--contrib/pjdfstest/tests/rename/03.t (renamed from tools/regression/pjdfstest/tests/rename/03.t)2
-rw-r--r--contrib/pjdfstest/tests/rename/04.t (renamed from tools/regression/pjdfstest/tests/rename/04.t)2
-rw-r--r--contrib/pjdfstest/tests/rename/05.t (renamed from tools/regression/pjdfstest/tests/rename/05.t)2
-rw-r--r--contrib/pjdfstest/tests/rename/06.t (renamed from tools/regression/pjdfstest/tests/rename/06.t)2
-rw-r--r--contrib/pjdfstest/tests/rename/07.t (renamed from tools/regression/pjdfstest/tests/rename/07.t)2
-rw-r--r--contrib/pjdfstest/tests/rename/08.t (renamed from tools/regression/pjdfstest/tests/rename/08.t)2
-rw-r--r--contrib/pjdfstest/tests/rename/09.t (renamed from tools/regression/pjdfstest/tests/rename/09.t)2
-rw-r--r--contrib/pjdfstest/tests/rename/10.t (renamed from tools/regression/pjdfstest/tests/rename/10.t)2
-rw-r--r--contrib/pjdfstest/tests/rename/11.t (renamed from tools/regression/pjdfstest/tests/rename/11.t)2
-rw-r--r--contrib/pjdfstest/tests/rename/12.t (renamed from tools/regression/pjdfstest/tests/rename/12.t)2
-rw-r--r--contrib/pjdfstest/tests/rename/13.t (renamed from tools/regression/pjdfstest/tests/rename/13.t)2
-rw-r--r--contrib/pjdfstest/tests/rename/14.t (renamed from tools/regression/pjdfstest/tests/rename/14.t)2
-rw-r--r--contrib/pjdfstest/tests/rename/15.t (renamed from tools/regression/pjdfstest/tests/rename/15.t)10
-rw-r--r--contrib/pjdfstest/tests/rename/16.t (renamed from tools/regression/pjdfstest/tests/rename/16.t)10
-rw-r--r--contrib/pjdfstest/tests/rename/17.t (renamed from tools/regression/pjdfstest/tests/rename/17.t)2
-rw-r--r--contrib/pjdfstest/tests/rename/18.t (renamed from tools/regression/pjdfstest/tests/rename/18.t)2
-rw-r--r--contrib/pjdfstest/tests/rename/19.t (renamed from tools/regression/pjdfstest/tests/rename/19.t)2
-rw-r--r--contrib/pjdfstest/tests/rename/20.t (renamed from tools/regression/pjdfstest/tests/rename/20.t)2
-rw-r--r--contrib/pjdfstest/tests/rename/21.t (renamed from tools/regression/pjdfstest/tests/rename/21.t)2
-rw-r--r--contrib/pjdfstest/tests/rmdir/00.t (renamed from tools/regression/pjdfstest/tests/rmdir/00.t)2
-rw-r--r--contrib/pjdfstest/tests/rmdir/01.t (renamed from tools/regression/pjdfstest/tests/rmdir/01.t)2
-rw-r--r--contrib/pjdfstest/tests/rmdir/02.t (renamed from tools/regression/pjdfstest/tests/rmdir/02.t)2
-rw-r--r--contrib/pjdfstest/tests/rmdir/03.t (renamed from tools/regression/pjdfstest/tests/rmdir/03.t)2
-rw-r--r--contrib/pjdfstest/tests/rmdir/04.t (renamed from tools/regression/pjdfstest/tests/rmdir/04.t)2
-rw-r--r--contrib/pjdfstest/tests/rmdir/05.t (renamed from tools/regression/pjdfstest/tests/rmdir/05.t)2
-rw-r--r--contrib/pjdfstest/tests/rmdir/06.t (renamed from tools/regression/pjdfstest/tests/rmdir/06.t)2
-rw-r--r--contrib/pjdfstest/tests/rmdir/07.t (renamed from tools/regression/pjdfstest/tests/rmdir/07.t)2
-rw-r--r--contrib/pjdfstest/tests/rmdir/08.t (renamed from tools/regression/pjdfstest/tests/rmdir/08.t)2
-rw-r--r--contrib/pjdfstest/tests/rmdir/09.t (renamed from tools/regression/pjdfstest/tests/rmdir/09.t)2
-rw-r--r--contrib/pjdfstest/tests/rmdir/10.t (renamed from tools/regression/pjdfstest/tests/rmdir/10.t)2
-rw-r--r--contrib/pjdfstest/tests/rmdir/11.t (renamed from tools/regression/pjdfstest/tests/rmdir/11.t)2
-rw-r--r--contrib/pjdfstest/tests/rmdir/12.t (renamed from tools/regression/pjdfstest/tests/rmdir/12.t)2
-rw-r--r--contrib/pjdfstest/tests/rmdir/13.t (renamed from tools/regression/pjdfstest/tests/rmdir/13.t)10
-rw-r--r--contrib/pjdfstest/tests/rmdir/14.t (renamed from tools/regression/pjdfstest/tests/rmdir/14.t)10
-rw-r--r--contrib/pjdfstest/tests/rmdir/15.t (renamed from tools/regression/pjdfstest/tests/rmdir/15.t)2
-rw-r--r--contrib/pjdfstest/tests/symlink/00.t (renamed from tools/regression/pjdfstest/tests/symlink/00.t)2
-rw-r--r--contrib/pjdfstest/tests/symlink/01.t (renamed from tools/regression/pjdfstest/tests/symlink/01.t)2
-rw-r--r--contrib/pjdfstest/tests/symlink/02.t (renamed from tools/regression/pjdfstest/tests/symlink/02.t)2
-rw-r--r--contrib/pjdfstest/tests/symlink/03.t (renamed from tools/regression/pjdfstest/tests/symlink/03.t)2
-rw-r--r--contrib/pjdfstest/tests/symlink/04.t (renamed from tools/regression/pjdfstest/tests/symlink/04.t)2
-rw-r--r--contrib/pjdfstest/tests/symlink/05.t (renamed from tools/regression/pjdfstest/tests/symlink/05.t)2
-rw-r--r--contrib/pjdfstest/tests/symlink/06.t (renamed from tools/regression/pjdfstest/tests/symlink/06.t)2
-rw-r--r--contrib/pjdfstest/tests/symlink/07.t (renamed from tools/regression/pjdfstest/tests/symlink/07.t)2
-rw-r--r--contrib/pjdfstest/tests/symlink/08.t (renamed from tools/regression/pjdfstest/tests/symlink/08.t)2
-rw-r--r--contrib/pjdfstest/tests/symlink/09.t (renamed from tools/regression/pjdfstest/tests/symlink/09.t)2
-rw-r--r--contrib/pjdfstest/tests/symlink/10.t (renamed from tools/regression/pjdfstest/tests/symlink/10.t)10
-rw-r--r--contrib/pjdfstest/tests/symlink/11.t (renamed from tools/regression/pjdfstest/tests/symlink/11.t)10
-rw-r--r--contrib/pjdfstest/tests/symlink/12.t (renamed from tools/regression/pjdfstest/tests/symlink/12.t)2
-rw-r--r--contrib/pjdfstest/tests/truncate/00.t (renamed from tools/regression/pjdfstest/tests/truncate/00.t)2
-rw-r--r--contrib/pjdfstest/tests/truncate/01.t18
-rw-r--r--contrib/pjdfstest/tests/truncate/02.t18
-rw-r--r--contrib/pjdfstest/tests/truncate/03.t22
-rw-r--r--contrib/pjdfstest/tests/truncate/04.t17
-rw-r--r--contrib/pjdfstest/tests/truncate/05.t32
-rw-r--r--contrib/pjdfstest/tests/truncate/06.t24
-rw-r--r--contrib/pjdfstest/tests/truncate/07.t19
-rw-r--r--contrib/pjdfstest/tests/truncate/08.t78
-rw-r--r--contrib/pjdfstest/tests/truncate/09.t15
-rw-r--r--contrib/pjdfstest/tests/truncate/10.t32
-rw-r--r--contrib/pjdfstest/tests/truncate/11.t18
-rw-r--r--contrib/pjdfstest/tests/truncate/12.t27
-rw-r--r--contrib/pjdfstest/tests/truncate/13.t (renamed from tools/regression/pjdfstest/tests/truncate/13.t)2
-rw-r--r--contrib/pjdfstest/tests/truncate/14.t12
-rw-r--r--contrib/pjdfstest/tests/unlink/00.t (renamed from tools/regression/pjdfstest/tests/unlink/00.t)2
-rw-r--r--contrib/pjdfstest/tests/unlink/01.t (renamed from tools/regression/pjdfstest/tests/unlink/01.t)2
-rw-r--r--contrib/pjdfstest/tests/unlink/02.t (renamed from tools/regression/pjdfstest/tests/unlink/02.t)2
-rw-r--r--contrib/pjdfstest/tests/unlink/03.t (renamed from tools/regression/pjdfstest/tests/unlink/03.t)2
-rw-r--r--contrib/pjdfstest/tests/unlink/04.t (renamed from tools/regression/pjdfstest/tests/unlink/04.t)2
-rw-r--r--contrib/pjdfstest/tests/unlink/05.t (renamed from tools/regression/pjdfstest/tests/unlink/05.t)2
-rw-r--r--contrib/pjdfstest/tests/unlink/06.t (renamed from tools/regression/pjdfstest/tests/unlink/06.t)2
-rw-r--r--contrib/pjdfstest/tests/unlink/07.t (renamed from tools/regression/pjdfstest/tests/unlink/07.t)2
-rw-r--r--contrib/pjdfstest/tests/unlink/08.t (renamed from tools/regression/pjdfstest/tests/unlink/08.t)2
-rw-r--r--contrib/pjdfstest/tests/unlink/09.t (renamed from tools/regression/pjdfstest/tests/unlink/09.t)2
-rw-r--r--contrib/pjdfstest/tests/unlink/10.t (renamed from tools/regression/pjdfstest/tests/unlink/10.t)2
-rw-r--r--contrib/pjdfstest/tests/unlink/11.t (renamed from tools/regression/pjdfstest/tests/unlink/11.t)2
-rw-r--r--contrib/pjdfstest/tests/unlink/12.t (renamed from tools/regression/pjdfstest/tests/unlink/12.t)10
-rw-r--r--contrib/pjdfstest/tests/unlink/13.t (renamed from tools/regression/pjdfstest/tests/unlink/13.t)2
-rw-r--r--etc/defaults/periodic.conf8
-rw-r--r--etc/motd14
-rw-r--r--etc/mtree/BSD.tests.dist4
-rw-r--r--etc/rc.d/Makefile37
-rwxr-xr-xetc/rc.d/syscons2
-rw-r--r--games/factor/factor.68
-rw-r--r--games/primes/Makefile2
-rw-r--r--games/primes/primes.c8
-rw-r--r--games/primes/primes.h9
-rw-r--r--games/primes/spsp.c181
-rw-r--r--lib/libnv/nv.38
-rw-r--r--lib/libproc/Makefile4
-rw-r--r--lib/libproc/proc_sym.c268
-rw-r--r--lib/libproc/test/Makefile5
-rw-r--r--lib/libproc/test/t1-bkpt/Makefile12
-rw-r--r--lib/libproc/test/t1-bkpt/t1-bkpt.c71
-rw-r--r--lib/libproc/test/t2-name2map/Makefile12
-rw-r--r--lib/libproc/test/t3-name2sym/Makefile12
-rw-r--r--lib/libproc/test/t3-name2sym/t3-name2sym.c51
-rw-r--r--lib/libproc/tests/Makefile21
-rw-r--r--lib/libproc/tests/proc_test.c347
-rw-r--r--lib/libproc/tests/target_prog.c (renamed from lib/libproc/test/t2-name2map/t2-name2map.c)89
-rw-r--r--lib/libthr/libthr.3223
-rw-r--r--lib/libthr/thread/thr_init.c7
-rw-r--r--lib/msun/src/e_lgamma_r.c4
-rw-r--r--release/doc/en_US.ISO8859-1/hardware/article.xml4
-rw-r--r--sbin/ping6/Makefile2
-rw-r--r--sbin/ping6/ping6.c402
-rw-r--r--sbin/routed/defs.h1
-rw-r--r--sbin/routed/input.c15
-rw-r--r--sbin/routed/main.c6
-rw-r--r--sbin/routed/output.c2
-rw-r--r--sbin/routed/routed.818
-rw-r--r--sbin/sysctl/sysctl.c186
-rw-r--r--share/man/man4/Makefile4
-rw-r--r--share/man/man4/ada.48
-rw-r--r--share/man/man4/cdce.45
-rw-r--r--share/man/man4/ipheth.493
-rw-r--r--share/man/man4/man4.arm/Makefile6
-rw-r--r--share/man/man4/man4.arm/cgem.4297
-rw-r--r--share/man/man4/miibus.45
-rw-r--r--share/man/man4/smsc.491
-rw-r--r--share/man/man4/urndis.44
-rw-r--r--share/man/man9/Makefile179
-rw-r--r--share/man/man9/sleepqueue.948
-rw-r--r--share/misc/committers-src.dot2
-rw-r--r--share/mk/bsd.progs.mk32
-rw-r--r--sys/Makefile2
-rw-r--r--sys/amd64/amd64/fpu.c21
-rw-r--r--sys/amd64/amd64/machdep.c8
-rw-r--r--sys/amd64/amd64/trap.c4
-rw-r--r--sys/amd64/conf/GENERIC2
-rw-r--r--sys/amd64/conf/NOTES4
-rw-r--r--sys/amd64/vmm/intel/vmx.c7
-rw-r--r--sys/amd64/vmm/io/vlapic.c1
-rw-r--r--sys/amd64/vmm/vmm.c8
-rw-r--r--sys/arm/allwinner/a10_clk.c3
-rw-r--r--sys/arm/altera/socfpga/files.socfpga2
-rw-r--r--sys/arm/arm/machdep.c15
-rw-r--r--sys/arm/arm/mpcore_timer.c289
-rw-r--r--sys/arm/at91/at91rm92reg.h4
-rw-r--r--sys/arm/at91/at91sam9260reg.h4
-rw-r--r--sys/arm/at91/at91sam9g20reg.h2
-rw-r--r--sys/arm/at91/at91sam9g45reg.h8
-rw-r--r--sys/arm/at91/at91sam9x5reg.h6
-rw-r--r--sys/arm/conf/LN2410SBC2
-rw-r--r--sys/arm/conf/NOTES2
-rw-r--r--sys/arm/conf/SOCKIT1
-rw-r--r--sys/arm/s3c2xx0/files.s3c2xx015
-rw-r--r--sys/arm/samsung/s3c2xx0/board_ln2410sbc.c (renamed from sys/arm/s3c2xx0/board_ln2410sbc.c)4
-rw-r--r--sys/arm/samsung/s3c2xx0/files.s3c2xx015
-rw-r--r--sys/arm/samsung/s3c2xx0/s3c2410reg.h (renamed from sys/arm/s3c2xx0/s3c2410reg.h)2
-rw-r--r--sys/arm/samsung/s3c2xx0/s3c2410var.h (renamed from sys/arm/s3c2xx0/s3c2410var.h)2
-rw-r--r--sys/arm/samsung/s3c2xx0/s3c2440reg.h (renamed from sys/arm/s3c2xx0/s3c2440reg.h)2
-rw-r--r--sys/arm/samsung/s3c2xx0/s3c24x0.c (renamed from sys/arm/s3c2xx0/s3c24x0.c)6
-rw-r--r--sys/arm/samsung/s3c2xx0/s3c24x0_clk.c (renamed from sys/arm/s3c2xx0/s3c24x0_clk.c)4
-rw-r--r--sys/arm/samsung/s3c2xx0/s3c24x0_machdep.c (renamed from sys/arm/s3c2xx0/s3c24x0_machdep.c)6
-rw-r--r--sys/arm/samsung/s3c2xx0/s3c24x0_rtc.c (renamed from sys/arm/s3c2xx0/s3c24x0_rtc.c)2
-rw-r--r--sys/arm/samsung/s3c2xx0/s3c24x0reg.h (renamed from sys/arm/s3c2xx0/s3c24x0reg.h)2
-rw-r--r--sys/arm/samsung/s3c2xx0/s3c24x0var.h (renamed from sys/arm/s3c2xx0/s3c24x0var.h)2
-rw-r--r--sys/arm/samsung/s3c2xx0/s3c2xx0_space.c (renamed from sys/arm/s3c2xx0/s3c2xx0_space.c)0
-rw-r--r--sys/arm/samsung/s3c2xx0/s3c2xx0board.h (renamed from sys/arm/s3c2xx0/s3c2xx0board.h)0
-rw-r--r--sys/arm/samsung/s3c2xx0/s3c2xx0reg.h (renamed from sys/arm/s3c2xx0/s3c2xx0reg.h)0
-rw-r--r--sys/arm/samsung/s3c2xx0/s3c2xx0var.h (renamed from sys/arm/s3c2xx0/s3c2xx0var.h)0
-rw-r--r--sys/arm/samsung/s3c2xx0/std.ln2410sbc (renamed from sys/arm/s3c2xx0/std.ln2410sbc)2
-rw-r--r--sys/arm/samsung/s3c2xx0/std.s3c2410 (renamed from sys/arm/s3c2xx0/std.s3c2410)2
-rw-r--r--sys/arm/samsung/s3c2xx0/uart_bus_s3c2410.c (renamed from sys/arm/s3c2xx0/uart_bus_s3c2410.c)2
-rw-r--r--sys/arm/samsung/s3c2xx0/uart_cpu_s3c2410.c (renamed from sys/arm/s3c2xx0/uart_cpu_s3c2410.c)2
-rw-r--r--sys/arm/samsung/s3c2xx0/uart_dev_s3c2410.c (renamed from sys/arm/s3c2xx0/uart_dev_s3c2410.c)8
-rw-r--r--sys/arm/samsung/s3c2xx0/uart_dev_s3c2410.h (renamed from sys/arm/s3c2xx0/uart_dev_s3c2410.h)0
-rw-r--r--sys/boot/efi/include/eficonsctl.h119
-rw-r--r--sys/boot/fdt/dts/arm/socfpga-sockit.dts4
-rw-r--r--sys/boot/fdt/dts/arm/socfpga.dtsi25
-rw-r--r--sys/cam/ctl/ctl.c161
-rw-r--r--sys/cam/ctl/ctl.h2
-rw-r--r--sys/cam/ctl/ctl_cmd_table.c22
-rw-r--r--sys/cam/ctl/ctl_error.c33
-rw-r--r--sys/cam/ctl/ctl_error.h2
-rw-r--r--sys/cam/ctl/ctl_frontend_iscsi.c6
-rw-r--r--sys/cam/ctl/ctl_private.h2
-rw-r--r--sys/compat/freebsd32/freebsd32_misc.c4
-rw-r--r--sys/compat/linux/linux_ioctl.c15
-rw-r--r--sys/compat/linux/linux_mib.c4
-rw-r--r--sys/conf/NOTES7
-rw-r--r--sys/conf/files38
-rw-r--r--sys/conf/files.amd6420
-rw-r--r--sys/conf/files.pc984
-rw-r--r--sys/conf/options2
-rw-r--r--sys/contrib/ipfilter/netinet/ip_dstlist.c4
-rw-r--r--sys/contrib/ipfilter/netinet/ip_frag.c38
-rw-r--r--sys/ddb/db_main.c48
-rw-r--r--sys/ddb/ddb.h8
-rw-r--r--sys/dev/acpica/acpi.c34
-rw-r--r--sys/dev/acpica/acpi_pci.c13
-rw-r--r--sys/dev/alpm/alpm.c (renamed from sys/pci/alpm.c)0
-rw-r--r--sys/dev/amdpm/amdpm.c (renamed from sys/pci/amdpm.c)0
-rw-r--r--sys/dev/amdsmb/amdsmb.c (renamed from sys/pci/amdsmb.c)0
-rw-r--r--sys/dev/asmc/asmc.c127
-rw-r--r--sys/dev/asmc/asmcvar.h118
-rw-r--r--sys/dev/atkbdc/atkbd.c37
-rw-r--r--sys/dev/bce/if_bce.c93
-rw-r--r--sys/dev/bce/if_bcereg.h1
-rw-r--r--sys/dev/cxgbe/t4_main.c10
-rw-r--r--sys/dev/cxgbe/tom/t4_listen.c8
-rw-r--r--sys/dev/dwc/if_dwc.c1324
-rw-r--r--sys/dev/dwc/if_dwc.h262
-rw-r--r--sys/dev/et/if_et.c54
-rw-r--r--sys/dev/fdc/fdc.c257
-rw-r--r--sys/dev/fdc/fdc_cbus.c (renamed from sys/pc98/cbus/fdc_cbus.c)102
-rw-r--r--sys/dev/fdc/fdcvar.h2
-rw-r--r--sys/dev/fdt/fdt_common.c40
-rw-r--r--sys/dev/fdt/fdt_common.h1
-rw-r--r--sys/dev/fdt/simplebus.c33
-rw-r--r--sys/dev/intpm/intpm.c (renamed from sys/pci/intpm.c)2
-rw-r--r--sys/dev/intpm/intpmreg.h (renamed from sys/pci/intpmreg.h)0
-rwxr-xr-xsys/dev/ixl/i40e_common.c8
-rwxr-xr-xsys/dev/ixl/if_ixl.c2
-rw-r--r--sys/dev/ixl/if_ixlv.c2
-rwxr-xr-xsys/dev/ixl/ixl_txrx.c13
-rw-r--r--sys/dev/jme/if_jme.c20
-rw-r--r--sys/dev/lmc/if_lmc.c2554
-rw-r--r--sys/dev/lmc/if_lmc.h288
-rw-r--r--sys/dev/mxge/if_mxge.c577
-rwxr-xr-xsys/dev/ncr/locate.pl (renamed from sys/pci/locate.pl)0
-rw-r--r--sys/dev/ncr/ncr.c (renamed from sys/pci/ncr.c)219
-rw-r--r--sys/dev/ncr/ncrreg.h (renamed from sys/pci/ncrreg.h)0
-rw-r--r--sys/dev/netmap/netmap.c25
-rw-r--r--sys/dev/netmap/netmap_kern.h9
-rw-r--r--sys/dev/nfsmb/nfsmb.c (renamed from sys/pci/nfsmb.c)0
-rw-r--r--sys/dev/oce/oce_if.c4
-rw-r--r--sys/dev/oce/oce_if.h1
-rw-r--r--sys/dev/ofw/ofw_bus_subr.c63
-rw-r--r--sys/dev/ofw/ofw_bus_subr.h3
-rw-r--r--sys/dev/ofw/ofwbus.c34
-rw-r--r--sys/dev/pci/pci.c93
-rw-r--r--sys/dev/pci/pci_private.h3
-rw-r--r--sys/dev/ti/if_ti.c71
-rw-r--r--sys/dev/tws/tws.c14
-rw-r--r--sys/dev/tws/tws.h1
-rw-r--r--sys/dev/tws/tws_cam.c26
-rw-r--r--sys/dev/tws/tws_hdm.c2
-rw-r--r--sys/dev/tws/tws_hdm.h2
-rw-r--r--sys/dev/tws/tws_services.c3
-rw-r--r--sys/dev/txp/if_txp.c41
-rw-r--r--sys/dev/usb/controller/ohci_s3c24x0.c2
-rw-r--r--sys/dev/usb/controller/xhci.c9
-rw-r--r--sys/dev/usb/net/if_smsc.c17
-rw-r--r--sys/dev/usb/usbdevs17
-rw-r--r--sys/dev/viapm/viapm.c (renamed from sys/pci/viapm.c)0
-rw-r--r--sys/dev/vmware/vmxnet3/if_vmx.c99
-rw-r--r--sys/dev/vmware/vmxnet3/if_vmxvar.h2
-rw-r--r--sys/dev/vt/vt_buf.c1
-rw-r--r--sys/dev/vte/if_vte.c40
-rw-r--r--sys/dev/wi/if_wi.c45
-rw-r--r--sys/dev/xen/netfront/netfront.c5
-rw-r--r--sys/fs/autofs/autofs.c12
-rw-r--r--sys/fs/autofs/autofs_vnops.c2
-rw-r--r--sys/fs/devfs/devfs_vnops.c1
-rw-r--r--sys/gnu/fs/reiserfs/reiserfs_fs_i.h2
-rw-r--r--sys/i386/i386/machdep.c10
-rw-r--r--sys/kern/bus_if.m22
-rw-r--r--sys/kern/kern_cons.c10
-rw-r--r--sys/kern/kern_descrip.c873
-rw-r--r--sys/kern/kern_event.c11
-rw-r--r--sys/kern/kern_malloc.c2
-rw-r--r--sys/kern/subr_bus.c45
-rw-r--r--sys/kern/sys_pipe.c18
-rw-r--r--sys/kern/sys_procdesc.c14
-rw-r--r--sys/kern/sys_socket.c65
-rw-r--r--sys/kern/tty_pts.c14
-rw-r--r--sys/kern/uipc_mqueue.c10
-rw-r--r--sys/kern/uipc_sem.c39
-rw-r--r--sys/kern/uipc_shm.c29
-rw-r--r--sys/kern/uipc_sockbuf.c31
-rw-r--r--sys/kern/vfs_syscalls.c85
-rw-r--r--sys/kern/vfs_vnops.c60
-rw-r--r--sys/mips/beri/beri_simplebus.c2
-rw-r--r--sys/mips/mips/machdep.c6
-rw-r--r--sys/modules/Makefile5
-rw-r--r--sys/modules/fdc/Makefile3
-rw-r--r--sys/modules/i2c/controllers/alpm/Makefile2
-rw-r--r--sys/modules/i2c/controllers/amdpm/Makefile2
-rw-r--r--sys/modules/i2c/controllers/amdsmb/Makefile2
-rw-r--r--sys/modules/i2c/controllers/intpm/Makefile2
-rw-r--r--sys/modules/i2c/controllers/nfsmb/Makefile2
-rw-r--r--sys/modules/i2c/controllers/viapm/Makefile2
-rw-r--r--sys/modules/mlx4/Makefile2
-rw-r--r--sys/modules/mlxen/Makefile4
-rw-r--r--sys/modules/ncr/Makefile11
-rw-r--r--sys/modules/netmap/Makefile1
-rw-r--r--sys/net/ieee8023ad_lacp.c42
-rw-r--r--sys/net/ieee8023ad_lacp.h8
-rw-r--r--sys/net/if.c86
-rw-r--r--sys/net/if_gif.c60
-rw-r--r--sys/net/if_gre.c70
-rw-r--r--sys/net/if_gre.h12
-rw-r--r--sys/net/if_lagg.c600
-rw-r--r--sys/net/if_lagg.h43
-rw-r--r--sys/net/if_var.h23
-rw-r--r--sys/net/if_vlan.c6
-rw-r--r--sys/net/route.c10
-rw-r--r--sys/net/route.h6
-rw-r--r--sys/netgraph/bluetooth/include/ng_btsocket_l2cap.h2
-rw-r--r--sys/netgraph/bluetooth/include/ng_btsocket_rfcomm.h2
-rw-r--r--sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c13
-rw-r--r--sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c12
-rw-r--r--sys/netinet/in.c4
-rw-r--r--sys/netinet/ip_gre.c8
-rw-r--r--sys/netinet/ip_ipsec.c13
-rw-r--r--sys/netinet/tcp_input.c2
-rw-r--r--sys/netinet/tcp_output.c107
-rw-r--r--sys/netinet/tcp_subr.c4
-rw-r--r--sys/netinet/tcp_var.h9
-rw-r--r--sys/netinet/toecore.c1
-rw-r--r--sys/netpfil/ipfw/ip_dn_io.c13
-rw-r--r--sys/ofed/drivers/infiniband/hw/mlx4/mad.c6
-rw-r--r--sys/ofed/drivers/infiniband/hw/mlx4/main.c8
-rw-r--r--sys/ofed/drivers/infiniband/hw/mlx4/qp.c18
-rw-r--r--sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_ib.c2
-rw-r--r--sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c4
-rw-r--r--sys/ofed/drivers/net/mlx4/alloc.c16
-rw-r--r--sys/ofed/drivers/net/mlx4/catas.c13
-rw-r--r--sys/ofed/drivers/net/mlx4/cmd.c584
-rw-r--r--sys/ofed/drivers/net/mlx4/cq.c55
-rw-r--r--sys/ofed/drivers/net/mlx4/en_cq.c136
-rw-r--r--sys/ofed/drivers/net/mlx4/en_ethtool.c1440
-rw-r--r--sys/ofed/drivers/net/mlx4/en_main.c202
-rw-r--r--sys/ofed/drivers/net/mlx4/en_netdev.c2524
-rw-r--r--sys/ofed/drivers/net/mlx4/en_port.c679
-rw-r--r--sys/ofed/drivers/net/mlx4/en_port.h54
-rw-r--r--sys/ofed/drivers/net/mlx4/en_resources.c34
-rw-r--r--sys/ofed/drivers/net/mlx4/en_rx.c583
-rw-r--r--sys/ofed/drivers/net/mlx4/en_selftest.c52
-rw-r--r--sys/ofed/drivers/net/mlx4/en_tx.c845
-rw-r--r--sys/ofed/drivers/net/mlx4/eq.c103
-rw-r--r--sys/ofed/drivers/net/mlx4/fw.c268
-rw-r--r--sys/ofed/drivers/net/mlx4/fw.h9
-rw-r--r--sys/ofed/drivers/net/mlx4/icm.c49
-rw-r--r--sys/ofed/drivers/net/mlx4/icm.h7
-rw-r--r--sys/ofed/drivers/net/mlx4/intf.c5
-rw-r--r--sys/ofed/drivers/net/mlx4/main.c1312
-rw-r--r--sys/ofed/drivers/net/mlx4/mcg.c423
-rw-r--r--sys/ofed/drivers/net/mlx4/mlx4.h214
-rw-r--r--sys/ofed/drivers/net/mlx4/mlx4_en.h717
-rw-r--r--sys/ofed/drivers/net/mlx4/mlx4_stats.h184
-rw-r--r--sys/ofed/drivers/net/mlx4/mr.c244
-rw-r--r--sys/ofed/drivers/net/mlx4/pd.c9
-rw-r--r--sys/ofed/drivers/net/mlx4/port.c141
-rw-r--r--sys/ofed/drivers/net/mlx4/profile.c7
-rw-r--r--sys/ofed/drivers/net/mlx4/qp.c23
-rw-r--r--sys/ofed/drivers/net/mlx4/reset.c13
-rw-r--r--sys/ofed/drivers/net/mlx4/resource_tracker.c645
-rw-r--r--sys/ofed/drivers/net/mlx4/sense.c33
-rw-r--r--sys/ofed/drivers/net/mlx4/srq.c23
-rw-r--r--sys/ofed/drivers/net/mlx4/sys_tune.c4
-rw-r--r--sys/ofed/drivers/net/mlx4/utils.c189
-rw-r--r--sys/ofed/drivers/net/mlx4/utils.h44
-rw-r--r--sys/ofed/include/linux/linux_compat.c9
-rw-r--r--sys/ofed/include/linux/mlx4/cmd.h34
-rw-r--r--sys/ofed/include/linux/mlx4/cq.h29
-rw-r--r--sys/ofed/include/linux/mlx4/device.h228
-rw-r--r--sys/ofed/include/linux/mlx4/driver.h66
-rw-r--r--sys/ofed/include/linux/mlx4/qp.h92
-rw-r--r--sys/ofed/include/linux/mlx4/srq.h2
-rw-r--r--sys/opencrypto/cryptodev.c12
-rw-r--r--sys/pc98/cbus/fdc.c2596
-rw-r--r--sys/pc98/cbus/fdcreg.h88
-rw-r--r--sys/pc98/cbus/fdcvar.h167
-rw-r--r--sys/pc98/cbus/olpt.c8
-rw-r--r--sys/pc98/cbus/pckbd.c35
-rw-r--r--sys/pc98/pc98/machdep.c7
-rw-r--r--sys/powerpc/aim/locore64.S1
-rw-r--r--sys/powerpc/aim/machdep.c9
-rw-r--r--sys/powerpc/booke/machdep.c7
-rw-r--r--sys/powerpc/ofw/ofw_pcibus.c25
-rw-r--r--sys/powerpc/pseries/vdevice.c22
-rw-r--r--sys/sparc64/sparc64/machdep.c4
-rw-r--r--sys/sys/bus.h2
-rw-r--r--sys/sys/file.h14
-rw-r--r--sys/sys/filedesc.h7
-rw-r--r--sys/sys/ksem.h5
-rw-r--r--sys/sys/mman.h1
-rw-r--r--sys/sys/sleepqueue.h7
-rw-r--r--sys/sys/sockbuf.h2
-rw-r--r--sys/sys/syscallsubr.h1
-rw-r--r--sys/vm/vm_map.c9
-rw-r--r--sys/vm/vm_pageout.c2
-rw-r--r--sys/x86/xen/pv.c80
-rw-r--r--tools/build/mk/OptionalObsoleteFiles.inc8
-rw-r--r--tools/regression/pjdfstest/tests/open/16.t19
-rw-r--r--tools/test/dtrace/Makefile3
-rw-r--r--usr.bin/calendar/calendars/calendar.freebsd1
-rw-r--r--usr.bin/grep/regex/tre-fastmatch.c2
-rw-r--r--usr.bin/man/man.132
-rw-r--r--usr.bin/mkimg/Makefile7
-rw-r--r--usr.bin/mkimg/qcow.c369
-rw-r--r--usr.bin/mkimg/tests/Makefile19
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-apm.qcow.gz.uu127
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-apm.qcow2.gz.uu22
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-apm.raw.gz.uu12
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-apm.vhd.gz.uu18
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-apm.vhdf.gz.uu15
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-apm.vmdk.gz.uu82
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-bsd.qcow.gz.uu125
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-bsd.qcow2.gz.uu21
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-bsd.raw.gz.uu10
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-bsd.vhd.gz.uu17
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-bsd.vhdf.gz.uu13
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-bsd.vmdk.gz.uu81
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-ebr.qcow.gz.uu127
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-ebr.qcow2.gz.uu22
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-ebr.raw.gz.uu11
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-ebr.vhd.gz.uu18
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-ebr.vhdf.gz.uu14
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-ebr.vmdk.gz.uu82
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-gpt.qcow.gz.uu132
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-gpt.qcow2.gz.uu26
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-gpt.raw.gz.uu15
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-gpt.vhd.gz.uu22
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-gpt.vhdf.gz.uu19
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-gpt.vmdk.gz.uu87
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-mbr.qcow.gz.uu127
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-mbr.qcow2.gz.uu22
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-mbr.raw.gz.uu11
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-mbr.vhd.gz.uu18
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-mbr.vhdf.gz.uu15
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-mbr.vmdk.gz.uu82
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-pc98.qcow.gz.uu127
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-pc98.qcow2.gz.uu21
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-pc98.raw.gz.uu11
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-pc98.vhd.gz.uu18
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-pc98.vhdf.gz.uu14
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-pc98.vmdk.gz.uu82
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-vtoc8.qcow.gz.uu125
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-vtoc8.qcow2.gz.uu21
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-vtoc8.raw.gz.uu10
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vhd.gz.uu17
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vhdf.gz.uu14
-rw-r--r--usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vmdk.gz.uu81
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-apm.qcow.gz.uu127
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-apm.qcow2.gz.uu22
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-apm.raw.gz.uu12
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-apm.vhd.gz.uu18
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-apm.vhdf.gz.uu15
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-apm.vmdk.gz.uu82
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-bsd.qcow.gz.uu125
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-bsd.qcow2.gz.uu21
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-bsd.raw.gz.uu10
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-bsd.vhd.gz.uu17
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-bsd.vhdf.gz.uu13
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-bsd.vmdk.gz.uu81
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-ebr.qcow.gz.uu127
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-ebr.qcow2.gz.uu22
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-ebr.raw.gz.uu11
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-ebr.vhd.gz.uu18
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-ebr.vhdf.gz.uu14
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-ebr.vmdk.gz.uu82
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-gpt.qcow.gz.uu132
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-gpt.qcow2.gz.uu26
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-gpt.raw.gz.uu15
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-gpt.vhd.gz.uu22
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-gpt.vhdf.gz.uu18
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-gpt.vmdk.gz.uu87
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-mbr.qcow.gz.uu127
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-mbr.qcow2.gz.uu22
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-mbr.raw.gz.uu11
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-mbr.vhd.gz.uu18
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-mbr.vhdf.gz.uu15
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-mbr.vmdk.gz.uu82
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-pc98.qcow.gz.uu127
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-pc98.qcow2.gz.uu21
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-pc98.raw.gz.uu11
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-pc98.vhd.gz.uu18
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-pc98.vhdf.gz.uu14
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-pc98.vmdk.gz.uu82
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-vtoc8.qcow.gz.uu125
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-vtoc8.qcow2.gz.uu21
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-vtoc8.raw.gz.uu10
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-vtoc8.vhd.gz.uu17
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-vtoc8.vhdf.gz.uu14
-rw-r--r--usr.bin/mkimg/tests/img-1x1-512-vtoc8.vmdk.gz.uu81
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-apm.qcow.gz.uu127
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-apm.qcow2.gz.uu22
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-apm.raw.gz.uu12
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-apm.vhd.gz.uu18
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-apm.vhdf.gz.uu15
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-apm.vmdk.gz.uu83
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-bsd.qcow.gz.uu126
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-bsd.qcow2.gz.uu21
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-bsd.raw.gz.uu11
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-bsd.vhd.gz.uu17
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-bsd.vhdf.gz.uu14
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-bsd.vmdk.gz.uu81
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-ebr.qcow.gz.uu128
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-ebr.qcow2.gz.uu22
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-ebr.raw.gz.uu12
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-ebr.vhd.gz.uu18
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-ebr.vhdf.gz.uu15
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-ebr.vmdk.gz.uu84
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-gpt.qcow.gz.uu132
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-gpt.qcow2.gz.uu26
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-gpt.raw.gz.uu15
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-gpt.vhd.gz.uu22
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-gpt.vhdf.gz.uu19
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-gpt.vmdk.gz.uu88
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-mbr.qcow.gz.uu128
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-mbr.qcow2.gz.uu23
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-mbr.raw.gz.uu12
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-mbr.vhd.gz.uu18
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-mbr.vhdf.gz.uu15
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-mbr.vmdk.gz.uu84
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-pc98.qcow.gz.uu126
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-pc98.qcow2.gz.uu22
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-pc98.raw.gz.uu12
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-pc98.vhd.gz.uu18
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-pc98.vhdf.gz.uu15
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-pc98.vmdk.gz.uu84
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-vtoc8.qcow.gz.uu127
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-vtoc8.qcow2.gz.uu21
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-vtoc8.raw.gz.uu11
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-vtoc8.vhd.gz.uu18
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-vtoc8.vhdf.gz.uu14
-rw-r--r--usr.bin/mkimg/tests/img-63x255-4096-vtoc8.vmdk.gz.uu83
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-apm.qcow.gz.uu127
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-apm.qcow2.gz.uu22
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-apm.raw.gz.uu12
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-apm.vhd.gz.uu18
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-apm.vhdf.gz.uu15
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-apm.vmdk.gz.uu83
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-bsd.qcow.gz.uu126
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-bsd.qcow2.gz.uu21
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-bsd.raw.gz.uu11
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-bsd.vhd.gz.uu17
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-bsd.vhdf.gz.uu14
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-bsd.vmdk.gz.uu81
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-ebr.qcow.gz.uu128
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-ebr.qcow2.gz.uu22
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-ebr.raw.gz.uu12
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-ebr.vhd.gz.uu18
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-ebr.vhdf.gz.uu15
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-ebr.vmdk.gz.uu84
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-gpt.qcow.gz.uu132
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-gpt.qcow2.gz.uu26
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-gpt.raw.gz.uu15
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-gpt.vhd.gz.uu22
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-gpt.vhdf.gz.uu19
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-gpt.vmdk.gz.uu88
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-mbr.qcow.gz.uu128
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-mbr.qcow2.gz.uu23
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-mbr.raw.gz.uu12
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-mbr.vhd.gz.uu18
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-mbr.vhdf.gz.uu15
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-mbr.vmdk.gz.uu84
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-pc98.qcow.gz.uu126
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-pc98.qcow2.gz.uu22
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-pc98.raw.gz.uu12
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-pc98.vhd.gz.uu18
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-pc98.vhdf.gz.uu15
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-pc98.vmdk.gz.uu84
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-vtoc8.qcow.gz.uu127
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-vtoc8.qcow2.gz.uu21
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-vtoc8.raw.gz.uu11
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-vtoc8.vhd.gz.uu18
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-vtoc8.vhdf.gz.uu14
-rw-r--r--usr.bin/mkimg/tests/img-63x255-512-vtoc8.vmdk.gz.uu83
-rwxr-xr-xusr.bin/mkimg/tests/mkimg.sh164
-rw-r--r--usr.bin/xinstall/xinstall.c15
-rw-r--r--usr.sbin/autofs/common.c12
-rw-r--r--usr.sbin/bhyve/smbiostbl.c2
-rwxr-xr-xusr.sbin/bsdinstall/scripts/services1
-rw-r--r--usr.sbin/newsyslog/newsyslog.83
763 files changed, 25835 insertions, 13170 deletions
diff --git a/Makefile.inc1 b/Makefile.inc1
index b99b4d3..333c734 100644
--- a/Makefile.inc1
+++ b/Makefile.inc1
@@ -911,7 +911,7 @@ packageworld:
# and do a 'make reinstall' on the *client* to install new binaries from the
# most recent server build.
#
-reinstall:
+reinstall: .MAKE
@echo "--------------------------------------------------------------"
@echo ">>> Making hierarchy"
@echo "--------------------------------------------------------------"
@@ -926,7 +926,7 @@ reinstall:
${_+_}cd ${.CURDIR}; ${MAKE} -f Makefile.inc1 install32
.endif
-redistribute:
+redistribute: .MAKE
@echo "--------------------------------------------------------------"
@echo ">>> Distributing everything"
@echo "--------------------------------------------------------------"
@@ -936,7 +936,7 @@ redistribute:
DISTRIBUTION=lib32
.endif
-distrib-dirs distribution:
+distrib-dirs distribution: .MAKE
cd ${.CURDIR}/etc; ${CROSSENV} PATH=${TMPPATH} ${MAKE} \
${IMAKE_INSTALL} ${IMAKE_MTREE} METALOG=${METALOG} ${.TARGET}
@@ -1464,7 +1464,7 @@ native-xtools: .MAKE
#
# hierarchy - ensure that all the needed directories are present
#
-hierarchy hier:
+hierarchy hier: .MAKE
cd ${.CURDIR}/etc && ${HMAKE} distrib-dirs
#
diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc
index e2f4317..95b2e87 100644
--- a/ObsoleteFiles.inc
+++ b/ObsoleteFiles.inc
@@ -38,6 +38,9 @@
# xargs -n1 | sort | uniq -d;
# done
+# 20140922: sleepq_calc_signal_retval.9 and sleepq_catch_signals.9 removed
+OLD_FILES+=usr/share/man/man9/sleepq_calc_signal_retval.9.gz
+OLD_FILES+=usr/share/man/man9/sleepq_catch_signals.9.gz
# 20140917: hv_kvpd rc.d script removed in favor of devd configuration
OLD_FILES+=etc/rc.d/hv_kvpd
# 20140814: libopie version bump
diff --git a/UPDATING b/UPDATING
index cb00e10..04fe7a6 100644
--- a/UPDATING
+++ b/UPDATING
@@ -31,6 +31,18 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 11.x IS SLOW:
disable the most expensive debugging functionality run
"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
+20140923:
+ pjdfstest has been moved from tools/regression/pjdfstest to
+ contrib/pjdfstest .
+
+20140922:
+ At svn r271982, The default linux compat kernel ABI has been adjusted
+ to 2.6.18 in support of the linux-c6 compat ports infrastructure
+ update. If you wish to continue using the linux-f10 compat ports,
+ add compat.linux.osrelease=2.6.16 to your local sysctl.conf. Users are
+ encouraged to update their linux-compat packages to linux-c6 during
+ their next update cycle.
+
20140729:
The ofwfb driver, used to provide a graphics console on PowerPC when
using vt(4), no longer allows mmap() of all of physical memory. This
diff --git a/bin/sh/sh.1 b/bin/sh/sh.1
index 4679d45..47b1b36 100644
--- a/bin/sh/sh.1
+++ b/bin/sh/sh.1
@@ -32,7 +32,7 @@
.\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95
.\" $FreeBSD$
.\"
-.Dd September 4, 2014
+.Dd September 21, 2014
.Dt SH 1
.Os
.Sh NAME
@@ -590,7 +590,8 @@ the following actions:
Leading words of the form
.Dq Li name=value
are stripped off and assigned to the environment of
-the simple command.
+the simple command
+(they do not affect expansions).
Redirection operators and
their arguments (as described below) are stripped
off and saved for processing.
diff --git a/cddl/contrib/opensolaris/cmd/dtrace/dtrace.1 b/cddl/contrib/opensolaris/cmd/dtrace/dtrace.1
index cc3a311..2d210a2 100644
--- a/cddl/contrib/opensolaris/cmd/dtrace/dtrace.1
+++ b/cddl/contrib/opensolaris/cmd/dtrace/dtrace.1
@@ -277,6 +277,19 @@ Generate a header file containing macros that correspond to probes in the
specified provider definitions.
This option should be used to generate a header file that is included by other
source files for later use with the
+.Fl G
+option.
+If the
+.Fl o
+option is present, the header file is saved using the pathname specified as the
+argument for that option.
+If the
+.Fl o
+option is not present and the DTrace program is contained within a file whose
+name is
+.Ar filename.d ,
+then the header file is saved using the name
+.Ar filename.h .
.It Fl H
Print the pathnames of included files when invoking
.Xr cpp 1
@@ -289,20 +302,6 @@ option to each
.Xr cpp 1
invocation, causing it to display the list of pathnames, one for each line, to
standard error.
-.Fl G
-option.
-If the
-.Fl o
-option
-is present, the header file is saved using the pathname specified as the
-argument for that option.
-If the
-.Fl o
-option is not present and the DTrace program is contained with a file whose
-name is
-.Ar filename.d ,
-then the header file is saved using the name
-.Ar filename.h .
.It Fl i Ar probe-id Op Oo Ar predicate Oc Ar action
Specify probe identifier
.Ar ( probe-id )
diff --git a/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c b/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c
index fe73169..8cb8091 100644
--- a/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c
+++ b/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c
@@ -4524,7 +4524,8 @@ is_root_pool(zpool_handle_t *zhp)
}
static void
-root_pool_upgrade_check(zpool_handle_t *zhp, char *poolname, int size) {
+root_pool_upgrade_check(zpool_handle_t *zhp, char *poolname, int size)
+{
if (poolname[0] == '\0' && is_root_pool(zhp))
(void) strlcpy(poolname, zpool_get_name(zhp), size);
@@ -4623,7 +4624,7 @@ upgrade_cb(zpool_handle_t *zhp, void *arg)
#ifdef __FreeBSD__
root_pool_upgrade_check(zhp, cbp->cb_poolname,
sizeof(cbp->cb_poolname));
-#endif /* ___FreeBSD__ */
+#endif /* __FreeBSD__ */
printnl = B_TRUE;
#ifdef illumos
@@ -4647,6 +4648,10 @@ upgrade_cb(zpool_handle_t *zhp, void *arg)
if (count > 0) {
cbp->cb_first = B_FALSE;
printnl = B_TRUE;
+#ifdef __FreeBSD__
+ root_pool_upgrade_check(zhp, cbp->cb_poolname,
+ sizeof(cbp->cb_poolname));
+#endif /* __FreeBSD__ */
/*
* If they did "zpool upgrade -a", then we could
* be doing ioctls to different pools. We need
@@ -4788,7 +4793,7 @@ upgrade_one(zpool_handle_t *zhp, void *data)
#ifdef __FreeBSD__
root_pool_upgrade_check(zhp, cbp->cb_poolname,
sizeof(cbp->cb_poolname));
-#endif /* ___FreeBSD__ */
+#endif /* __FreeBSD__ */
}
if (cbp->cb_version >= SPA_VERSION_FEATURES) {
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c b/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c
index 3c64f87..ccd4f9b 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c
@@ -121,12 +121,12 @@ dtrace_dof_init(void)
#if !defined(sun)
Elf *e;
Elf_Scn *scn = NULL;
- Elf_Data *symtabdata = NULL, *dynsymdata = NULL, *dofdata = NULL;
+ Elf_Data *dofdata = NULL;
dof_hdr_t *dof_next = NULL;
GElf_Shdr shdr;
int efd;
char *s;
- size_t shstridx, symtabidx = 0, dynsymidx = 0;
+ size_t shstridx;
#endif
if (getenv("DTRACE_DOF_INIT_DISABLE") != NULL)
@@ -166,15 +166,9 @@ dtrace_dof_init(void)
dof = NULL;
while ((scn = elf_nextscn(e, scn)) != NULL) {
gelf_getshdr(scn, &shdr);
- if (shdr.sh_type == SHT_SYMTAB) {
- symtabidx = shdr.sh_link;
- symtabdata = elf_getdata(scn, NULL);
- } else if (shdr.sh_type == SHT_DYNSYM) {
- dynsymidx = shdr.sh_link;
- dynsymdata = elf_getdata(scn, NULL);
- } else if (shdr.sh_type == SHT_SUNW_dof) {
+ if (shdr.sh_type == SHT_SUNW_dof) {
s = elf_strptr(e, shstridx, shdr.sh_name);
- if (s != NULL && strcmp(s, ".SUNW_dof") == 0) {
+ if (s != NULL && strcmp(s, ".SUNW_dof") == 0) {
dofdata = elf_getdata(scn, NULL);
dof = dofdata->d_buf;
}
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c
index 106878c..597fef4 100644
--- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c
+++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c
@@ -1819,7 +1819,6 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags,
"failed to write %s: %s", file, strerror(errno)));
}
#else
- (void)close(fd);
if (status != 0)
return (dt_link_error(dtp, NULL, -1, NULL,
"failed to write %s: %s", tfile,
diff --git a/cddl/usr.sbin/Makefile b/cddl/usr.sbin/Makefile
index 537b8e5..0d34afd 100644
--- a/cddl/usr.sbin/Makefile
+++ b/cddl/usr.sbin/Makefile
@@ -5,6 +5,7 @@
SUBDIR= ${_dtrace} \
${_dtruss} \
${_lockstat} \
+ ${_plockstat} \
${_tests} \
${_zdb} \
${_zhack}
@@ -24,6 +25,9 @@ _zhack= zhack
_dtrace= dtrace
_dtruss= dtruss
_lockstat= lockstat
+.if defined(WITH_PLOCKSTAT)
+_plockstat= plockstat
+.endif
.endif
.if ${MACHINE_CPUARCH} == "mips"
diff --git a/contrib/apr-util/CHANGES b/contrib/apr-util/CHANGES
index 7626c50..a0dc378 100644
--- a/contrib/apr-util/CHANGES
+++ b/contrib/apr-util/CHANGES
@@ -1,4 +1,30 @@
-*- coding: utf-8 -*-
+Changes with APR-util 1.5.4
+
+ *) MySQL driver: Fix incorrect handling of bad parameter in the
+ driver support for apr_dbd_transaction_end(). PR 56330.
+ [Weiqiang Li <weiqiang_li hotmail.com>]
+
+ *) apr_crypto_get_driver(): Fix invalid storage reference on error path.
+ [Philip Martin <philip.martin wandisco.com>]
+
+ *) Fix compile failure for Android. PR 56627. [Fredrik Fornwall
+ <fredrik fornwall.net>, Jeff Trawick]
+
+ *) Fix to let ODBC driver build with MSVC6, which does not have intptr_t
+ [Tom Donovan]
+
+ *) Windows cmake build: Fix incompatiblities with Visual Studio
+ generators with all cmake versions, and the NMake Makefile generator
+ with cmake 2.8.12 and later. PR 56616 and other bugs. [Jeff Trawick,
+ Bert Huijben]
+
+ *) Fix detection of Berkeley DB 6.0. PR 55277.
+ [Lars Wendler <polynomial-c gentoo.org>]
+
+ *) Improve platform detection for bundled expat by updating
+ config.guess and config.sub. [Rainer Jung]
+
Changes with APR-util 1.5.3
*) Cygwin: Use correct file extension when loading APR DSOs. PR 55587.
diff --git a/contrib/apr-util/NOTICE b/contrib/apr-util/NOTICE
index aaf9cd0..a107139 100644
--- a/contrib/apr-util/NOTICE
+++ b/contrib/apr-util/NOTICE
@@ -1,7 +1,7 @@
Apache Portable Runtime Utility Library
-Copyright (c) 2011 The Apache Software Foundation.
+Copyright (c) 2000-2014 The Apache Software Foundation.
-This product includes software developed by
+This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
Portions of this software were developed at the National Center
diff --git a/contrib/apr-util/apr-util.spec b/contrib/apr-util/apr-util.spec
index d08400d..e9dc24b 100644
--- a/contrib/apr-util/apr-util.spec
+++ b/contrib/apr-util/apr-util.spec
@@ -3,7 +3,7 @@
Summary: Apache Portable Runtime Utility library
Name: apr-util
-Version: 1.5.3
+Version: 1.5.4
Release: 1
License: Apache Software License
Group: System Environment/Libraries
diff --git a/contrib/apr-util/configure b/contrib/apr-util/configure
index ccfc3e6..8ddd0e8 100755
--- a/contrib/apr-util/configure
+++ b/contrib/apr-util/configure
@@ -11608,19 +11608,34 @@ fi
apu_db_version=0
# Maximum supported version announced in help string.
- # Although we search for all versions up to 5.9,
+ # Although we search for all versions up to 6.9,
# we should only include existing versions in our
# help string.
- db_max_version=53
- db_min_version=41
dbm_list="sdbm, gdbm, ndbm, db, db1, db185, db2, db3, db4"
+ db_max_version=48
+ db_min_version=41
+ db_version="$db_min_version"
+ while [ $db_version -le $db_max_version ]
+ do
+ dbm_list="$dbm_list, db$db_version"
+ db_version=`expr $db_version + 1`
+ done
+ db_max_version=53
+ db_min_version=50
+ db_version="$db_min_version"
+ while [ $db_version -le $db_max_version ]
+ do
+ dbm_list="$dbm_list, db$db_version"
+ db_version=`expr $db_version + 1`
+ done
+ db_max_version=60
+ db_min_version=60
db_version="$db_min_version"
while [ $db_version -le $db_max_version ]
do
dbm_list="$dbm_list, db$db_version"
db_version=`expr $db_version + 1`
done
- dbm_list="$dbm_list, db60"
# Check whether --with-dbm was given.
@@ -12093,8 +12108,8 @@ if test "${with_berkeley_db+set}" = set; then :
all_places="$check_places"
- # Start version search at version 5.9
- db_version=59
+ # Start version search at version 6.9
+ db_version=69
while [ $db_version -ge 40 ]
do
db_major=`echo $db_version | sed -e 's/.$//'`
@@ -12178,7 +12193,7 @@ $as_echo "" >&6; }
ac_fn_c_check_header_mongrel "$LINENO" "$bdb_header" "$as_ac_Header" "$ac_includes_default"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- if test ""${db_major}"" = "3" -o ""${db_major}"" = "4" -o ""${db_major}"" = "5"; then
+ if test ""${db_major}"" = "3" -o ""${db_major}"" = "4" -o ""${db_major}"" = "5" -o ""${db_major}"" = "6"; then
# We generate a separate cache variable for each prefix and libname
# we search under. That way, we avoid caching information that
# changes if the user runs `configure' with a different set of
@@ -12580,7 +12595,7 @@ $as_echo "" >&6; }
ac_fn_c_check_header_mongrel "$LINENO" "$bdb_header" "$as_ac_Header" "$ac_includes_default"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- if test "3" = "3" -o "3" = "4" -o "3" = "5"; then
+ if test "3" = "3" -o "3" = "4" -o "3" = "5" -o "3" = "6"; then
# We generate a separate cache variable for each prefix and libname
# we search under. That way, we avoid caching information that
# changes if the user runs `configure' with a different set of
@@ -12978,7 +12993,7 @@ $as_echo "" >&6; }
ac_fn_c_check_header_mongrel "$LINENO" "$bdb_header" "$as_ac_Header" "$ac_includes_default"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- if test "2" = "3" -o "2" = "4" -o "2" = "5"; then
+ if test "2" = "3" -o "2" = "4" -o "2" = "5" -o "2" = "6"; then
# We generate a separate cache variable for each prefix and libname
# we search under. That way, we avoid caching information that
# changes if the user runs `configure' with a different set of
@@ -13376,7 +13391,7 @@ $as_echo "" >&6; }
ac_fn_c_check_header_mongrel "$LINENO" "$bdb_header" "$as_ac_Header" "$ac_includes_default"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- if test "1" = "3" -o "1" = "4" -o "1" = "5"; then
+ if test "1" = "3" -o "1" = "4" -o "1" = "5" -o "1" = "6"; then
# We generate a separate cache variable for each prefix and libname
# we search under. That way, we avoid caching information that
# changes if the user runs `configure' with a different set of
@@ -13774,7 +13789,7 @@ $as_echo "" >&6; }
ac_fn_c_check_header_mongrel "$LINENO" "$bdb_header" "$as_ac_Header" "$ac_includes_default"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- if test "1" = "3" -o "1" = "4" -o "1" = "5"; then
+ if test "1" = "3" -o "1" = "4" -o "1" = "5" -o "1" = "6"; then
# We generate a separate cache variable for each prefix and libname
# we search under. That way, we avoid caching information that
# changes if the user runs `configure' with a different set of
@@ -14186,7 +14201,7 @@ $as_echo "" >&6; }
ac_fn_c_check_header_mongrel "$LINENO" "$bdb_header" "$as_ac_Header" "$ac_includes_default"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- if test "1" = "3" -o "1" = "4" -o "1" = "5"; then
+ if test "1" = "3" -o "1" = "4" -o "1" = "5" -o "1" = "6"; then
# We generate a separate cache variable for each prefix and libname
# we search under. That way, we avoid caching information that
# changes if the user runs `configure' with a different set of
@@ -14587,7 +14602,7 @@ $as_echo "" >&6; }
ac_fn_c_check_header_mongrel "$LINENO" "$bdb_header" "$as_ac_Header" "$ac_includes_default"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- if test "1" = "3" -o "1" = "4" -o "1" = "5"; then
+ if test "1" = "3" -o "1" = "4" -o "1" = "5" -o "1" = "6"; then
# We generate a separate cache variable for each prefix and libname
# we search under. That way, we avoid caching information that
# changes if the user runs `configure' with a different set of
@@ -14988,7 +15003,7 @@ $as_echo "" >&6; }
ac_fn_c_check_header_mongrel "$LINENO" "$bdb_header" "$as_ac_Header" "$ac_includes_default"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- if test "2" = "3" -o "2" = "4" -o "2" = "5"; then
+ if test "2" = "3" -o "2" = "4" -o "2" = "5" -o "2" = "6"; then
# We generate a separate cache variable for each prefix and libname
# we search under. That way, we avoid caching information that
# changes if the user runs `configure' with a different set of
@@ -15389,7 +15404,7 @@ $as_echo "" >&6; }
ac_fn_c_check_header_mongrel "$LINENO" "$bdb_header" "$as_ac_Header" "$ac_includes_default"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- if test "3" = "3" -o "3" = "4" -o "3" = "5"; then
+ if test "3" = "3" -o "3" = "4" -o "3" = "5" -o "3" = "6"; then
# We generate a separate cache variable for each prefix and libname
# we search under. That way, we avoid caching information that
# changes if the user runs `configure' with a different set of
@@ -15794,7 +15809,7 @@ $as_echo "" >&6; }
ac_fn_c_check_header_mongrel "$LINENO" "$bdb_header" "$as_ac_Header" "$ac_includes_default"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- if test ""${db_major}"" = "3" -o ""${db_major}"" = "4" -o ""${db_major}"" = "5"; then
+ if test ""${db_major}"" = "3" -o ""${db_major}"" = "4" -o ""${db_major}"" = "5" -o ""${db_major}"" = "6"; then
# We generate a separate cache variable for each prefix and libname
# we search under. That way, we avoid caching information that
# changes if the user runs `configure' with a different set of
@@ -16202,7 +16217,7 @@ $as_echo "" >&6; }
ac_fn_c_check_header_mongrel "$LINENO" "$bdb_header" "$as_ac_Header" "$ac_includes_default"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- if test ""${db_major}"" = "3" -o ""${db_major}"" = "4" -o ""${db_major}"" = "5"; then
+ if test ""${db_major}"" = "3" -o ""${db_major}"" = "4" -o ""${db_major}"" = "5" -o ""${db_major}"" = "6"; then
# We generate a separate cache variable for each prefix and libname
# we search under. That way, we avoid caching information that
# changes if the user runs `configure' with a different set of
@@ -16534,8 +16549,8 @@ fi
all_places="$check_places"
- # Start version search at version 5.9
- db_version=59
+ # Start version search at version 6.9
+ db_version=69
while [ $db_version -ge 40 ]
do
db_major=`echo $db_version | sed -e 's/.$//'`
@@ -16619,7 +16634,7 @@ $as_echo "" >&6; }
ac_fn_c_check_header_mongrel "$LINENO" "$bdb_header" "$as_ac_Header" "$ac_includes_default"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- if test ""${db_major}"" = "3" -o ""${db_major}"" = "4" -o ""${db_major}"" = "5"; then
+ if test ""${db_major}"" = "3" -o ""${db_major}"" = "4" -o ""${db_major}"" = "5" -o ""${db_major}"" = "6"; then
# We generate a separate cache variable for each prefix and libname
# we search under. That way, we avoid caching information that
# changes if the user runs `configure' with a different set of
@@ -17021,7 +17036,7 @@ $as_echo "" >&6; }
ac_fn_c_check_header_mongrel "$LINENO" "$bdb_header" "$as_ac_Header" "$ac_includes_default"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- if test "3" = "3" -o "3" = "4" -o "3" = "5"; then
+ if test "3" = "3" -o "3" = "4" -o "3" = "5" -o "3" = "6"; then
# We generate a separate cache variable for each prefix and libname
# we search under. That way, we avoid caching information that
# changes if the user runs `configure' with a different set of
@@ -17419,7 +17434,7 @@ $as_echo "" >&6; }
ac_fn_c_check_header_mongrel "$LINENO" "$bdb_header" "$as_ac_Header" "$ac_includes_default"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- if test "2" = "3" -o "2" = "4" -o "2" = "5"; then
+ if test "2" = "3" -o "2" = "4" -o "2" = "5" -o "2" = "6"; then
# We generate a separate cache variable for each prefix and libname
# we search under. That way, we avoid caching information that
# changes if the user runs `configure' with a different set of
@@ -17817,7 +17832,7 @@ $as_echo "" >&6; }
ac_fn_c_check_header_mongrel "$LINENO" "$bdb_header" "$as_ac_Header" "$ac_includes_default"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- if test "1" = "3" -o "1" = "4" -o "1" = "5"; then
+ if test "1" = "3" -o "1" = "4" -o "1" = "5" -o "1" = "6"; then
# We generate a separate cache variable for each prefix and libname
# we search under. That way, we avoid caching information that
# changes if the user runs `configure' with a different set of
@@ -18215,7 +18230,7 @@ $as_echo "" >&6; }
ac_fn_c_check_header_mongrel "$LINENO" "$bdb_header" "$as_ac_Header" "$ac_includes_default"
if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
- if test "1" = "3" -o "1" = "4" -o "1" = "5"; then
+ if test "1" = "3" -o "1" = "4" -o "1" = "5" -o "1" = "6"; then
# We generate a separate cache variable for each prefix and libname
# we search under. That way, we avoid caching information that
# changes if the user runs `configure' with a different set of
diff --git a/contrib/apr-util/crypto/apr_crypto.c b/contrib/apr-util/crypto/apr_crypto.c
index 35ce375..fe66582 100644
--- a/contrib/apr-util/crypto/apr_crypto.c
+++ b/contrib/apr-util/crypto/apr_crypto.c
@@ -204,7 +204,7 @@ APU_DECLARE(apr_status_t) apr_crypto_get_driver(
if (err && buffer) {
apr_dso_error(dso, buffer, ERROR_SIZE - 1);
err->msg = buffer;
- err->reason = modname;
+ err->reason = apr_pstrdup(pool, modname);
*result = err;
}
}
diff --git a/contrib/apr-util/crypto/apr_passwd.c b/contrib/apr-util/crypto/apr_passwd.c
index 1b4b47b..c961de2 100644
--- a/contrib/apr-util/crypto/apr_passwd.c
+++ b/contrib/apr-util/crypto/apr_passwd.c
@@ -66,6 +66,12 @@ static void crypt_mutex_unlock(void)
#endif
#endif
+#if defined(WIN32) || defined(BEOS) || defined(NETWARE) || defined(__ANDROID__)
+#define CRYPT_MISSING 1
+#else
+#define CRYPT_MISSING 0
+#endif
+
/*
* Validate a plaintext password against a smashed one. Uses either
* crypt() (if available) or apr_md5_encode() or apr_sha1_base64(), depending
@@ -77,7 +83,7 @@ APU_DECLARE(apr_status_t) apr_password_validate(const char *passwd,
const char *hash)
{
char sample[200];
-#if !defined(WIN32) && !defined(BEOS) && !defined(NETWARE)
+#if !CRYPT_MISSING
char *crypt_pw;
#endif
if (hash[0] == '$'
@@ -100,7 +106,7 @@ APU_DECLARE(apr_status_t) apr_password_validate(const char *passwd,
/*
* It's not our algorithm, so feed it to crypt() if possible.
*/
-#if defined(WIN32) || defined(BEOS) || defined(NETWARE)
+#if CRYPT_MISSING
return (strcmp(passwd, hash) == 0) ? APR_SUCCESS : APR_EMISMATCH;
#elif defined(CRYPT_R_CRYPTD)
apr_status_t rv;
diff --git a/contrib/apr-util/dbd/apr_dbd_mysql.c b/contrib/apr-util/dbd/apr_dbd_mysql.c
index 1141c6f..3b8017d 100644
--- a/contrib/apr-util/dbd/apr_dbd_mysql.c
+++ b/contrib/apr-util/dbd/apr_dbd_mysql.c
@@ -1050,9 +1050,9 @@ static int dbd_mysql_end_transaction(apr_dbd_transaction_t *trans)
else {
ret = mysql_commit(trans->handle->conn);
}
+ ret |= mysql_autocommit(trans->handle->conn, 1);
+ trans->handle->trans = NULL;
}
- ret |= mysql_autocommit(trans->handle->conn, 1);
- trans->handle->trans = NULL;
return ret;
}
/* Whether or not transactions work depends on whether the
diff --git a/contrib/apr-util/dbd/apr_dbd_odbc.c b/contrib/apr-util/dbd/apr_dbd_odbc.c
index 6ee8a7d..8a3c0fd 100644
--- a/contrib/apr-util/dbd/apr_dbd_odbc.c
+++ b/contrib/apr-util/dbd/apr_dbd_odbc.c
@@ -47,6 +47,21 @@
#include <odbc/sqlext.h>
#endif
+/*
+* MSVC6 does not support intptr_t (C99)
+* APR does not have a signed inptr type until 2.0 (r1557720)
+*/
+#if defined(_MSC_VER) && _MSC_VER < 1400
+#if APR_SIZEOF_VOIDP == 8
+#define ODBC_INTPTR_T apr_int64_t
+#else
+#define ODBC_INTPTR_T apr_int32_t
+#endif
+#else
+#define ODBC_INTPTR_T intptr_t
+#endif
+
+
/* Driver name is "odbc" and the entry point is 'apr_dbd_odbc_driver'
* unless ODBC_DRIVER_NAME is defined and it is linked with another db library which
* is ODBC source-compatible. e.g. DB2, Informix, TimesTen, mysql.
@@ -114,9 +129,9 @@ struct apr_dbd_t
char lastError[MAX_ERROR_STRING];
int defaultBufferSize; /* used for CLOBs in text mode,
* and when fld size is indeterminate */
- intptr_t transaction_mode;
- intptr_t dboptions; /* driver options re SQLGetData */
- intptr_t default_transaction_mode;
+ ODBC_INTPTR_T transaction_mode;
+ ODBC_INTPTR_T dboptions; /* driver options re SQLGetData */
+ ODBC_INTPTR_T default_transaction_mode;
int can_commit; /* controls end_trans behavior */
};
@@ -359,7 +374,7 @@ static SQLRETURN odbc_set_result_column(int icol, apr_dbd_results_t *res,
SQLHANDLE stmt)
{
SQLRETURN rc;
- intptr_t maxsize, textsize, realsize, type, isunsigned = 1;
+ ODBC_INTPTR_T maxsize, textsize, realsize, type, isunsigned = 1;
/* discover the sql type */
rc = SQLColAttribute(stmt, icol + 1, SQL_DESC_UNSIGNED, NULL, 0, NULL,
@@ -747,7 +762,7 @@ static void *odbc_get(const apr_dbd_row_t *row, const int col,
SQLRETURN rc;
SQLLEN indicator;
int state = row->res->colstate[col];
- intptr_t options = row->res->apr_dbd->dboptions;
+ ODBC_INTPTR_T options = row->res->apr_dbd->dboptions;
switch (state) {
case (COL_UNAVAIL):
@@ -817,13 +832,13 @@ static apr_status_t odbc_parse_params(apr_pool_t *pool, const char *params,
int *connect, SQLCHAR **datasource,
SQLCHAR **user, SQLCHAR **password,
int *defaultBufferSize, int *nattrs,
- int **attrs, intptr_t **attrvals)
+ int **attrs, ODBC_INTPTR_T **attrvals)
{
char *seps, *last, *next, *name[MAX_PARAMS], *val[MAX_PARAMS];
int nparams = 0, i, j;
*attrs = apr_pcalloc(pool, MAX_PARAMS * sizeof(char *));
- *attrvals = apr_pcalloc(pool, MAX_PARAMS * sizeof(intptr_t));
+ *attrvals = apr_pcalloc(pool, MAX_PARAMS * sizeof(ODBC_INTPTR_T));
*nattrs = 0;
seps = DEFAULTSEPS;
name[nparams] = apr_strtok(apr_pstrdup(pool, params), seps, &last);
@@ -1063,7 +1078,7 @@ static apr_dbd_t *odbc_open(apr_pool_t *pool, const char *params, const char **e
SQLCHAR *datasource = (SQLCHAR *)"", *user = (SQLCHAR *)"",
*password = (SQLCHAR *)"";
int nattrs = 0, *attrs = NULL, connect = 0;
- intptr_t *attrvals = NULL;
+ ODBC_INTPTR_T *attrvals = NULL;
err_step = "SQLAllocHandle (SQL_HANDLE_DBC)";
err_htype = SQL_HANDLE_ENV;
@@ -1117,10 +1132,10 @@ static apr_dbd_t *odbc_open(apr_pool_t *pool, const char *params, const char **e
handle->default_transaction_mode = 0;
handle->can_commit = APR_DBD_TRANSACTION_IGNORE_ERRORS;
SQLGetInfo(hdbc, SQL_DEFAULT_TXN_ISOLATION,
- &(handle->default_transaction_mode), sizeof(intptr_t), NULL);
+ &(handle->default_transaction_mode), sizeof(ODBC_INTPTR_T), NULL);
handle->transaction_mode = handle->default_transaction_mode;
SQLGetInfo(hdbc, SQL_GETDATA_EXTENSIONS ,&(handle->dboptions),
- sizeof(intptr_t), NULL);
+ sizeof(ODBC_INTPTR_T), NULL);
apr_pool_cleanup_register(pool, handle, odbc_close_cleanup, apr_pool_cleanup_null);
return handle;
}
diff --git a/contrib/apr-util/dbm/NWGNUmakefile b/contrib/apr-util/dbm/NWGNUmakefile
index 9307b84..7e610fe 100644
--- a/contrib/apr-util/dbm/NWGNUmakefile
+++ b/contrib/apr-util/dbm/NWGNUmakefile
@@ -235,7 +235,7 @@ nlms :: libs $(TARGET_nlm)
# correct place. (See $(AP_WORK)\build\NWGNUhead.inc for examples)
#
install :: nlms $(INSTDIRS) FORCE
- copy $(OBJDIR)\*.nlm $(INSTALLBASE)
+ $(call COPY,$(OBJDIR)/*.nlm,$(INSTALLBASE))
#
# Any specialized rules here
diff --git a/contrib/apr-util/include/apu_version.h b/contrib/apr-util/include/apu_version.h
index a7a5878..8d97629 100644
--- a/contrib/apr-util/include/apu_version.h
+++ b/contrib/apr-util/include/apu_version.h
@@ -38,7 +38,7 @@
*/
-#define APU_COPYRIGHT "Copyright (c) 2013 The Apache Software " \
+#define APU_COPYRIGHT "Copyright (c) 2000-2014 The Apache Software " \
"Foundation or its licensors, as applicable."
/* The numeric compile-time version constants. These constants are the
@@ -62,7 +62,7 @@
* The Patch Level never includes API changes, simply bug fixes.
* Reset to 0 when upgrading APR_MINOR_VERSION
*/
-#define APU_PATCH_VERSION 3
+#define APU_PATCH_VERSION 4
/**
* The symbol APU_IS_DEV_VERSION is only defined for internal,
diff --git a/contrib/apr-util/test/Makefile.win b/contrib/apr-util/test/Makefile.win
index 0305850..a30f39e 100644
--- a/contrib/apr-util/test/Makefile.win
+++ b/contrib/apr-util/test/Makefile.win
@@ -88,6 +88,8 @@ APROUTDIR=$(OUTDIR)
!IF "$(MODEL)" == "static"
PROGRAM_DEPENDENCIES = \
$(APR_PATH)\$(APROUTDIR)\apr-1.lib \
+ $(API_PATH)\$(OUTDIR)\apriconv-1.lib \
+ ..\xml\expat\lib\$(OUTDIR)\xml.lib \
..\$(OUTDIR)\aprutil-1.lib
STATIC_CFLAGS = /D APR_DECLARE_STATIC /D APU_DECLARE_STATIC
STATIC_LIBS = odbc32.lib odbccp32.lib wldap32.lib
diff --git a/contrib/atf/FREEBSD-upgrade b/contrib/atf/FREEBSD-upgrade
index 1b1970f..e9d7a4c 100644
--- a/contrib/atf/FREEBSD-upgrade
+++ b/contrib/atf/FREEBSD-upgrade
@@ -7,10 +7,9 @@ branches and you are supposed to follow those:
http://www.freebsd.org/doc/en/articles/committers-guide/subversion-primer.html
-The ATF source code is hosted on Google Code as a subcomponent of the
-Kyua project:
+The ATF source code is hosted on GitHub:
- http://code.google.com/p/kyua/downloads/list
+ https://github.com/jmmv/atf
and is imported into the atf vendor branch (see base/vendor/atf/).
@@ -42,7 +41,7 @@ the vendor branch as you easily risk committing build products into the
tree.
Lastly, with the list of old and new files in this import, make sure
-to udpate the reachover Makefiles accordingly.
+to update the reachover Makefiles accordingly.
Test the build (keeping in mind the WITH_TESTS/WITHOUT_TESTS knobs) and,
if all looks good, you are ready to commit all the changes in one go.
diff --git a/contrib/atf/atf-c++/atf-c++-api.3 b/contrib/atf/atf-c++/atf-c++-api.3
index c086c90..da1441e 100644
--- a/contrib/atf/atf-c++/atf-c++-api.3
+++ b/contrib/atf/atf-c++/atf-c++-api.3
@@ -26,7 +26,7 @@
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd November 15, 2013
+.Dd March 2, 2014
.Dt ATF-C++-API 3
.Os
.Sh NAME
@@ -330,9 +330,8 @@ If
.Va exitcode
is not
.Sq -1 ,
-.Xr atf-run 1
-will validate that the exit code of the test case matches the one provided
-in this call.
+the runtime engine will validate that the exit code of the test case
+matches the one provided in this call.
Otherwise, the exact value will be ignored.
.It Fn expect_fail "reason"
Any failure (be it fatal or non-fatal) raised in this mode is recorded.
@@ -368,9 +367,8 @@ If
.Va signo
is not
.Sq -1 ,
-.Xr atf-run 1
-will validate that the signal that terminated the test case matches the one
-provided in this call.
+the runtime engine will validate that the signal that terminated the test
+case matches the one provided in this call.
Otherwise, the exact value will be ignored.
.It Fn expect_timeout "reason"
Expects the test case to execute for longer than its timeout.
@@ -631,5 +629,4 @@ ATF_INIT_TEST_CASES(tcs)
.Ed
.Sh SEE ALSO
.Xr atf-test-program 1 ,
-.Xr atf-test-case 4 ,
-.Xr atf 7
+.Xr atf-test-case 4
diff --git a/contrib/atf/atf-c/atf-c-api.3 b/contrib/atf/atf-c/atf-c-api.3
index 366caec..b3b3086 100644
--- a/contrib/atf/atf-c/atf-c-api.3
+++ b/contrib/atf/atf-c/atf-c-api.3
@@ -26,7 +26,7 @@
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd November 15, 2013
+.Dd March 2, 2014
.Dt ATF-C-API 3
.Os
.Sh NAME
@@ -409,9 +409,8 @@ If
.Va exitcode
is not
.Sq -1 ,
-.Xr atf-run 1
-will validate that the exit code of the test case matches the one provided
-in this call.
+the runtime engine will validate that the exit code of the test case
+matches the one provided in this call.
Otherwise, the exact value will be ignored.
.It Fn atf_tc_expect_fail "reason" "..."
Any failure (be it fatal or non-fatal) raised in this mode is recorded.
@@ -443,9 +442,8 @@ If
.Va signo
is not
.Sq -1 ,
-.Xr atf-run 1
-will validate that the signal that terminated the test case matches the one
-provided in this call.
+the runtime engine will validate that the signal that terminated the test
+case matches the one provided in this call.
Otherwise, the exact value will be ignored.
.It Fn atf_tc_expect_timeout "reason" "..."
Expects the test case to execute for longer than its timeout.
@@ -771,5 +769,4 @@ ATF_TP_ADD_TCS(tp)
.Ed
.Sh SEE ALSO
.Xr atf-test-program 1 ,
-.Xr atf-test-case 4 ,
-.Xr atf 7
+.Xr atf-test-case 4
diff --git a/contrib/atf/atf-sh/atf-check.1 b/contrib/atf/atf-sh/atf-check.1
index 06904bc..66f9318 100644
--- a/contrib/atf/atf-sh/atf-check.1
+++ b/contrib/atf/atf-sh/atf-check.1
@@ -26,7 +26,7 @@
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd June 27, 2010
+.Dd March 2, 2014
.Dt ATF-CHECK 1
.Os
.Sh NAME
@@ -118,15 +118,20 @@ Analyzes standard error (syntax identical to above)
Executes
.Ar command
as a shell command line, executing it with the system shell defined by
-.Va ATF_SHELL
-in
-.Xr atf-config 1 .
+.Va ATF_SHELL .
You should avoid using this flag if at all possible to prevent shell quoting
issues.
.El
.Sh EXIT STATUS
.Nm
exits 0 on success, and other (unspecified) value on failure.
+.Sh ENVIRONMENT
+.Bl -tag -width ATFXSHELLXX -compact
+.It Va ATF_SHELL
+Path to the system shell to be used when the
+.Fl x
+is given to run commands.
+.El
.Sh EXAMPLES
.Bd -literal -offset indent
# Exit code 0, nothing on stdout/stderr
@@ -146,6 +151,3 @@ atf-check -s signal:sigsegv my_program
# Combined checks
atf-check -o match:foo -o not-match:bar echo foo baz
.Ed
-.Sh SEE ALSO
-.Xr atf-config 1 ,
-.Xr atf 7
diff --git a/contrib/atf/atf-sh/atf-sh-api.3 b/contrib/atf/atf-sh/atf-sh-api.3
index d63804c..a30aee7 100644
--- a/contrib/atf/atf-sh/atf-sh-api.3
+++ b/contrib/atf/atf-sh/atf-sh-api.3
@@ -26,7 +26,7 @@
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd October 13, 2013
+.Dd March 2, 2014
.Dt ATF-SH-API 3
.Os
.Sh NAME
@@ -224,9 +224,8 @@ If
.Va exitcode
is not
.Sq -1 ,
-.Xr atf-run 1
-will validate that the exit code of the test case matches the one provided
-in this call.
+the runtime engine will validate that the exit code of the test case
+matches the one provided in this call.
Otherwise, the exact value will be ignored.
.It Fn atf_expect_fail "reason"
Any failure raised in this mode is recorded, but such failures do not report
@@ -258,9 +257,8 @@ If
.Va signo
is not
.Sq -1 ,
-.Xr atf-run 1
-will validate that the signal that terminated the test case matches the one
-provided in this call.
+the runtime engine will validate that the signal that terminated the test
+case matches the one provided in this call.
Otherwise, the exact value will be ignored.
.It Fn atf_expect_timeout "reason" "..."
Expects the test case to execute for longer than its timeout.
@@ -339,5 +337,4 @@ atf_check -s exit:0 -o match:"^foo$" -e empty 'ls'
.Sh SEE ALSO
.Xr atf-sh 1 ,
.Xr atf-test-program 1 ,
-.Xr atf-test-case 4 ,
-.Xr atf 7
+.Xr atf-test-case 4
diff --git a/contrib/atf/atf-sh/atf-sh.1 b/contrib/atf/atf-sh/atf-sh.1
index 7578ba0..ad77f04 100644
--- a/contrib/atf/atf-sh/atf-sh.1
+++ b/contrib/atf/atf-sh/atf-sh.1
@@ -26,7 +26,7 @@
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd October 15, 2013
+.Dd March 2, 2014
.Dt ATF-SH 1
.Os
.Sh NAME
@@ -47,10 +47,8 @@ library.
.Pp
.Nm
is not a real interpreter though: it is just a wrapper around
-the system-wide shell defined by the
-.Sq atf_shell
-configuration value in
-.Xr atf-config 1 .
+the system-wide shell defined by
+.Va ATF_SHELL .
.Nm
executes the interpreter, loads the
.Xr atf-sh-api 3
@@ -68,7 +66,10 @@ The following options are available:
.It Fl h
Shows a short summary of all available options and their purpose.
.El
+.Sh ENVIRONMENT
+.Bl -tag -width ATFXSHELLXX -compact
+.It Va ATF_SHELL
+Path to the system shell to be used in the generated scripts.
+.El
.Sh SEE ALSO
-.Xr atf-config 1 ,
-.Xr atf-sh-api 3 ,
-.Xr atf 7
+.Xr atf-sh-api 3
diff --git a/contrib/atf/doc/atf-test-case.4 b/contrib/atf/doc/atf-test-case.4
index c5e9e66..7f253ed 100644
--- a/contrib/atf/doc/atf-test-case.4
+++ b/contrib/atf/doc/atf-test-case.4
@@ -26,7 +26,7 @@
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd January 13, 2011
+.Dd March 2, 2014
.Dt ATF-TEST-CASE 4
.Os
.Sh NAME
@@ -171,9 +171,7 @@ Type: boolean.
Optional.
.Pp
If set to true, specifies that the test case has a cleanup routine that has
-to be executed by
-.Xr atf-run 1
-during the cleanup phase of the execution.
+to be executed by the runtime engine during the cleanup phase of the execution.
This property is automatically set by the framework when defining a test case
with a cleanup routine, so it should never be set by hand.
.It ident
@@ -251,8 +249,7 @@ the test case is
.Pp
If the test case is running as root and this property is
.Sq unprivileged ,
-.Xr atf-run 1
-will automatically drop the privileges if the
+the runtime engine will automatically drop the privileges if the
.Sq unprivileged-user
configuration property is set; otherwise the test case is
.Em skipped .
@@ -314,7 +311,4 @@ Test cases are always executed with a file creation mode mask (umask) of
.Sq 0022 .
The test case's code is free to change this during execution.
.Sh SEE ALSO
-.Xr atf-run 1 ,
-.Xr atf-test-program 1 ,
-.Xr atf-formats 5 ,
-.Xr atf 7
+.Xr atf-test-program 1
diff --git a/contrib/atf/doc/atf-test-program.1 b/contrib/atf/doc/atf-test-program.1
index 49ee12d..c2f7326 100644
--- a/contrib/atf/doc/atf-test-program.1
+++ b/contrib/atf/doc/atf-test-program.1
@@ -26,7 +26,7 @@
.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd February 6, 2011
+.Dd March 2, 2014
.Dt ATF-TEST-PROGRAM 1
.Os
.Sh NAME
@@ -61,16 +61,17 @@ instead of the test case body; see
Note that the test case is
.Em executed without isolation ,
so it can and probably will create and modify files in the current directory.
-To execute test cases in a controller manner, refer to
-.Xr atf-run 1 ,
-which is the preferred way to run test cases.
+To execute test cases in a controller manner, you need a runtime engine
+that understands the ATF interface.
+The recommended runtime engine is
+.Xr kyua 1 .
You should only execute test cases by hand for debugging purposes.
.Pp
In the second synopsis form, the test program will list all available
test cases alongside their meta-data properties in a format that is
machine parseable.
This list is processed by
-.Xr atf-run 1
+.Xr kyua 1
to know how to execute the test cases of a given test program.
.Pp
The following options are available:
@@ -99,5 +100,4 @@ to the value
.Ar value .
.El
.Sh SEE ALSO
-.Xr atf-run 1 ,
-.Xr atf 7
+.Xr kyua 1
diff --git a/contrib/hyperv/tools/hv_kvp_daemon.c b/contrib/hyperv/tools/hv_kvp_daemon.c
index 890ca5b..b0a84d4 100644
--- a/contrib/hyperv/tools/hv_kvp_daemon.c
+++ b/contrib/hyperv/tools/hv_kvp_daemon.c
@@ -284,12 +284,10 @@ kvp_file_init(void)
int i;
int alloc_unit = sizeof(struct kvp_record) * ENTRIES_PER_BLOCK;
- if (access("/var/db/hyperv/pool", F_OK)) {
- if (mkdir("/var/db/hyperv/pool",
- S_IRUSR | S_IWUSR | S_IROTH)) {
- KVP_LOG(LOG_ERR, " Failed to create /var/db/hyperv/pool\n");
- exit(EXIT_FAILURE);
- }
+ if (mkdir("/var/db/hyperv/pool", S_IRUSR | S_IWUSR | S_IROTH) < 0 &&
+ errno != EISDIR) {
+ KVP_LOG(LOG_ERR, " Failed to create /var/db/hyperv/pool\n");
+ exit(EXIT_FAILURE);
}
for (i = 0; i < HV_KVP_POOL_COUNT; i++)
@@ -307,11 +305,13 @@ kvp_file_init(void)
filep = fopen(fname, "r");
if (!filep) {
+ close(fd);
return (1);
}
record = malloc(alloc_unit * num_blocks);
if (record == NULL) {
+ close(fd);
fclose(filep);
return (1);
}
@@ -336,6 +336,7 @@ kvp_file_init(void)
record = realloc(record, alloc_unit *
num_blocks);
if (record == NULL) {
+ close(fd);
fclose(filep);
return (1);
}
@@ -600,8 +601,7 @@ kvp_mac_to_if_name(char *mac)
struct ifaddrs *head_ifaddrs_ptr;
struct sockaddr_dl *sdl;
int status;
- size_t i;
- char *buf_ptr;
+ char *buf_ptr, *p;
status = getifaddrs(&ifaddrs_ptr);
@@ -611,18 +611,17 @@ kvp_mac_to_if_name(char *mac)
sdl = (struct sockaddr_dl *)(uintptr_t)ifaddrs_ptr->ifa_addr;
if (sdl->sdl_type == IFT_ETHER) {
buf_ptr = strdup(ether_ntoa((struct ether_addr *)(LLADDR(sdl))));
- for (i = 0; i < strlen(buf_ptr); i++)
- {
- buf_ptr[i] = toupper(buf_ptr[i]);
- }
-
- if (strncmp(buf_ptr, mac, strlen(mac)) == 0) {
- /* Caller will free the memory */
- if_name = strdup(ifaddrs_ptr->ifa_name);
- free(buf_ptr);
- break;
- }else if (buf_ptr != NULL) {
- free(buf_ptr);
+ if (buf_ptr != NULL) {
+ for (p = buf_ptr; *p != '\0'; p++)
+ *p = toupper(*p);
+
+ if (strncmp(buf_ptr, mac, strlen(mac)) == 0) {
+ /* Caller will free the memory */
+ if_name = strdup(ifaddrs_ptr->ifa_name);
+ free(buf_ptr);
+ break;
+ } else
+ free(buf_ptr);
}
}
} while ((ifaddrs_ptr = ifaddrs_ptr->ifa_next) != NULL);
@@ -1249,7 +1248,7 @@ kvp_op_enumerate(struct hv_kvp_msg *op_msg, void *data __unused)
case IntegrationServicesVersion:
strcpy(key_name, "IntegrationServicesVersion");
- strcpy(key_value, lic_version);
+ strlcpy(key_value, lic_version, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
break;
case NetworkAddressIPv4:
@@ -1265,32 +1264,32 @@ kvp_op_enumerate(struct hv_kvp_msg *op_msg, void *data __unused)
break;
case OSBuildNumber:
- strcpy(key_value, os_build);
+ strlcpy(key_value, os_build, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
strcpy(key_name, "OSBuildNumber");
break;
case OSName:
- strcpy(key_value, os_name);
+ strlcpy(key_value, os_name, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
strcpy(key_name, "OSName");
break;
case OSMajorVersion:
- strcpy(key_value, os_major);
+ strlcpy(key_value, os_major, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
strcpy(key_name, "OSMajorVersion");
break;
case OSMinorVersion:
- strcpy(key_value, os_minor);
+ strlcpy(key_value, os_minor, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
strcpy(key_name, "OSMinorVersion");
break;
case OSVersion:
- strcpy(key_value, os_build);
+ strlcpy(key_value, os_build, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
strcpy(key_name, "OSVersion");
break;
case ProcessorArchitecture:
- strcpy(key_value, processor_arch);
+ strlcpy(key_value, processor_arch, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
strcpy(key_name, "ProcessorArchitecture");
break;
diff --git a/contrib/ipfilter/lib/gethost.c b/contrib/ipfilter/lib/gethost.c
index a11b09b..14099e2 100644
--- a/contrib/ipfilter/lib/gethost.c
+++ b/contrib/ipfilter/lib/gethost.c
@@ -19,16 +19,17 @@ int gethost(family, name, hostp)
struct netent *n;
u_32_t addr;
+ bzero(hostp, sizeof(*hostp));
if (!strcmp(name, "test.host.dots")) {
if (family == AF_INET) {
hostp->in4.s_addr = htonl(0xfedcba98);
}
#ifdef USE_INET6
if (family == AF_INET6) {
- hostp->i6[0] = 0xfe80aa55;
- hostp->i6[1] = 0x12345678;
- hostp->i6[2] = 0x5a5aa5a5;
- hostp->i6[3] = 0xfedcba98;
+ hostp->i6[0] = htonl(0xfe80aa55);
+ hostp->i6[1] = htonl(0x12345678);
+ hostp->i6[2] = htonl(0x5a5aa5a5);
+ hostp->i6[3] = htonl(0xfedcba98);
}
#endif
return 0;
diff --git a/contrib/ipfilter/lib/printnat.c b/contrib/ipfilter/lib/printnat.c
index 37a7e12..a94d4ee 100644
--- a/contrib/ipfilter/lib/printnat.c
+++ b/contrib/ipfilter/lib/printnat.c
@@ -153,7 +153,8 @@ printnat(np, opts)
} else if (np->in_redir & NAT_REWRITE) {
PRINTF(" -> src ");
- if (np->in_nsrc.na_type == IPLT_DSTLIST) {
+ if (np->in_nsrc.na_atype == FRI_LOOKUP &&
+ np->in_nsrc.na_type == IPLT_DSTLIST) {
PRINTF("dstlist/");
if (np->in_nsrc.na_subtype == 0)
PRINTF("%d", np->in_nsrc.na_num);
@@ -174,7 +175,8 @@ printnat(np, opts)
}
}
PRINTF(" dst ");
- if (np->in_ndst.na_type == IPLT_DSTLIST) {
+ if (np->in_ndst.na_atype == FRI_LOOKUP &&
+ np->in_ndst.na_type == IPLT_DSTLIST) {
PRINTF("dstlist/");
if (np->in_ndst.na_subtype == 0)
PRINTF("%d", np->in_nsrc.na_num);
diff --git a/contrib/ipfilter/tools/ipf_y.y b/contrib/ipfilter/tools/ipf_y.y
index 822e9a5..e0dc847 100644
--- a/contrib/ipfilter/tools/ipf_y.y
+++ b/contrib/ipfilter/tools/ipf_y.y
@@ -1020,12 +1020,13 @@ addr: pool '/' YY_NUMBER { pooled = 1;
yyexpectaddr = 0; }
;
-ipaddr: IPFY_ANY { bzero(&($$), sizeof($$));
+ipaddr: IPFY_ANY { memset(&($$), 0, sizeof($$));
$$.type = FRI_NORMAL;
$$.ifpos = -1;
yyexpectaddr = 0;
}
- | hostname { $$.a = $1.adr;
+ | hostname { memset(&($$), 0, sizeof($$));
+ $$.a = $1.adr;
$$.f = $1.f;
if ($1.f == AF_INET6)
fill6bits(128, $$.m.i6);
@@ -1038,7 +1039,8 @@ ipaddr: IPFY_ANY { bzero(&($$), sizeof($$));
| hostname { yyresetdict(); }
maskspace { yysetdict(maskwords);
yyexpectaddr = 2; }
- ipmask { ntomask($1.f, $5, $$.m.i6);
+ ipmask { memset(&($$), 0, sizeof($$));
+ ntomask($1.f, $5, $$.m.i6);
$$.a = $1.adr;
$$.a.i6[0] &= $$.m.i6[0];
$$.a.i6[1] &= $$.m.i6[1];
@@ -1060,7 +1062,8 @@ ipaddr: IPFY_ANY { bzero(&($$), sizeof($$));
yyresetdict();
yyexpectaddr = 0;
}
- | '(' YY_STR ')' { $$.type = FRI_DYNAMIC;
+ | '(' YY_STR ')' { memset(&($$), 0, sizeof($$));
+ $$.type = FRI_DYNAMIC;
ifpflag = FRI_DYNAMIC;
$$.ifpos = addname(&fr, $2);
$$.lif = 0;
@@ -1068,7 +1071,8 @@ ipaddr: IPFY_ANY { bzero(&($$), sizeof($$));
| '(' YY_STR ')' '/'
{ ifpflag = FRI_DYNAMIC; yysetdict(maskwords); }
maskopts
- { $$.type = ifpflag;
+ { memset(&($$), 0, sizeof($$));
+ $$.type = ifpflag;
$$.ifpos = addname(&fr, $2);
$$.lif = 0;
if (frc->fr_family == AF_UNSPEC)
@@ -1083,7 +1087,8 @@ ipaddr: IPFY_ANY { bzero(&($$), sizeof($$));
| '(' YY_STR ':' YY_NUMBER ')' '/'
{ ifpflag = FRI_DYNAMIC; yysetdict(maskwords); }
maskopts
- { $$.type = ifpflag;
+ { memset(&($$), 0, sizeof($$));
+ $$.type = ifpflag;
$$.ifpos = addname(&fr, $2);
$$.lif = $4;
if (frc->fr_family == AF_UNSPEC)
@@ -1142,30 +1147,35 @@ maskopts:
;
hostname:
- ipv4 { $$.adr.in4 = $1;
+ ipv4 { memset(&($$), 0, sizeof($$));
+ $$.adr.in4 = $1;
if (frc->fr_family == AF_INET6)
YYERROR;
$$.f = AF_INET;
yyexpectaddr = 2;
}
- | YY_NUMBER { if (frc->fr_family == AF_INET6)
+ | YY_NUMBER { memset(&($$), 0, sizeof($$));
+ if (frc->fr_family == AF_INET6)
YYERROR;
$$.adr.in4_addr = $1;
$$.f = AF_INET;
yyexpectaddr = 2;
}
- | YY_HEX { if (frc->fr_family == AF_INET6)
+ | YY_HEX { memset(&($$), 0, sizeof($$));
+ if (frc->fr_family == AF_INET6)
YYERROR;
$$.adr.in4_addr = $1;
$$.f = AF_INET;
yyexpectaddr = 2;
}
- | YY_STR { if (lookuphost($1, &$$.adr) == 0)
+ | YY_STR { memset(&($$), 0, sizeof($$));
+ if (lookuphost($1, &$$.adr) == 0)
$$.f = AF_INET;
free($1);
yyexpectaddr = 2;
}
- | YY_IPV6 { if (frc->fr_family == AF_INET)
+ | YY_IPV6 { memset(&($$), 0, sizeof($$));
+ if (frc->fr_family == AF_INET)
YYERROR;
$$.adr = $1;
$$.f = AF_INET6;
diff --git a/contrib/ipfilter/tools/ipnat_y.y b/contrib/ipfilter/tools/ipnat_y.y
index 71fb8ee..8c23403 100644
--- a/contrib/ipfilter/tools/ipnat_y.y
+++ b/contrib/ipfilter/tools/ipnat_y.y
@@ -871,9 +871,9 @@ mapport:
}
free($2);
if ($3.p1 < 0 || $3.p1 > 65535)
- yyerror("invalid ICMP Id number");
+ yyerror("invalid 1st ICMP Id number");
if ($3.p2 < 0 || $3.p2 > 65535)
- yyerror("invalid ICMP Id number");
+ yyerror("invalid 2nd ICMP Id number");
if (strcmp($2, "ipv6-icmp") == 0) {
nat->in_pr[0] = IPPROTO_ICMPV6;
nat->in_pr[1] = IPPROTO_ICMPV6;
@@ -1058,7 +1058,7 @@ hash: IPNY_HASH { if (!(nat->in_flags & IPN_FILTER)) {
;
portstuff:
- compare portspec { $$.pc = $1; $$.p1 = $2; }
+ compare portspec { $$.pc = $1; $$.p1 = $2; $$.p2 = 0; }
| portspec range portspec { $$.pc = $2; $$.p1 = $1; $$.p2 = $3; }
;
@@ -1151,7 +1151,7 @@ proto: YY_NUMBER { $$ = $1;
| YY_STR { $$ = getproto($1);
free($1);
if ($$ == -1)
- yyerror("unknwon protocol");
+ yyerror("unknown protocol");
if ($$ != IPPROTO_TCP &&
$$ != IPPROTO_UDP)
suggest_port = 0;
@@ -1164,17 +1164,20 @@ hexnumber:
hostname:
YY_STR { i6addr_t addr;
+ int family;
- bzero(&$$, sizeof($$));
- if (gethost(AF_INET, $1,
- &addr) == 0) {
- $$.a = addr;
- $$.f = AF_INET;
- } else
- if (gethost(AF_INET6, $1,
+#ifdef USE_INET6
+ if (nat->in_v[0] == 6)
+ family = AF_INET6;
+ else
+#endif
+ family = AF_INET;
+ memset(&($$), 0, sizeof($$));
+ memset(&addr, 0, sizeof(addr));
+ $$.f = family;
+ if (gethost(family, $1,
&addr) == 0) {
$$.a = addr;
- $$.f = AF_INET6;
} else {
FPRINTF(stderr,
"Unknown host '%s'\n",
@@ -1182,17 +1185,17 @@ hostname:
}
free($1);
}
- | YY_NUMBER { bzero(&$$, sizeof($$));
+ | YY_NUMBER { memset(&($$), 0, sizeof($$));
$$.a.in4.s_addr = htonl($1);
if ($$.a.in4.s_addr != 0)
$$.f = AF_INET;
}
| ipv4 { $$ = $1; }
- | YY_IPV6 { bzero(&$$, sizeof($$));
+ | YY_IPV6 { memset(&($$), 0, sizeof($$));
$$.a = $1;
$$.f = AF_INET6;
}
- | YY_NUMBER YY_IPV6 { bzero(&$$, sizeof($$));
+ | YY_NUMBER YY_IPV6 { memset(&($$), 0, sizeof($$));
$$.a = $2;
$$.f = AF_INET6;
}
@@ -1427,6 +1430,9 @@ setnatproto(p)
nat->in_flags |= IPN_UDP;
nat->in_flags &= ~IPN_TCP;
break;
+#ifdef USE_INET6
+ case IPPROTO_ICMPV6 :
+#endif
case IPPROTO_ICMP :
nat->in_flags &= ~IPN_TCPUDP;
if (!(nat->in_flags & IPN_ICMPQUERY) &&
@@ -1506,7 +1512,7 @@ ipnat_addrule(fd, ioctlfunc, ptr)
printnat(ipn, opts);
if (opts & OPT_DEBUG)
- binprint(ipn, sizeof(*ipn));
+ binprint(ipn, ipn->in_size);
if ((opts & OPT_ZERORULEST) != 0) {
if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
diff --git a/contrib/llvm/patches/patch-r269387-clang-arm-target-cpu.diff b/contrib/llvm/patches/patch-r269387-clang-arm-target-cpu.diff
new file mode 100644
index 0000000..fea76a1
--- /dev/null
+++ b/contrib/llvm/patches/patch-r269387-clang-arm-target-cpu.diff
@@ -0,0 +1,34 @@
+Update the ARMv6 core clang targets to be an arm1176jzf-s. This brings us
+in line with gcc in base as this makes llvm generate code for the armv6k
+variant of the instruction set.
+
+Introduced here: http://svnweb.freebsd.org/changeset/base/269387
+
+Index: tools/clang/lib/Driver/ToolChain.cpp
+===================================================================
+--- tools/clang/lib/Driver/ToolChain.cpp (revision 269386)
++++ tools/clang/lib/Driver/ToolChain.cpp (revision 269387)
+@@ -183,7 +183,8 @@ static const char *getARMTargetCPU(const ArgList &
+ MArch = Triple.getArchName();
+ }
+
+- if (Triple.getOS() == llvm::Triple::NetBSD) {
++ if (Triple.getOS() == llvm::Triple::NetBSD ||
++ Triple.getOS() == llvm::Triple::FreeBSD) {
+ if (MArch == "armv6")
+ return "arm1176jzf-s";
+ }
+Index: tools/clang/lib/Driver/Tools.cpp
+===================================================================
+--- tools/clang/lib/Driver/Tools.cpp (revision 269386)
++++ tools/clang/lib/Driver/Tools.cpp (revision 269387)
+@@ -499,7 +499,8 @@ static std::string getARMTargetCPU(const ArgList &
+ MArch = Triple.getArchName();
+ }
+
+- if (Triple.getOS() == llvm::Triple::NetBSD) {
++ if (Triple.getOS() == llvm::Triple::NetBSD ||
++ Triple.getOS() == llvm::Triple::FreeBSD) {
+ if (MArch == "armv6")
+ return "arm1176jzf-s";
+ }
diff --git a/contrib/llvm/patches/patch-r270147-llvm-r197824-r213427-r213960.diff b/contrib/llvm/patches/patch-r270147-llvm-r197824-r213427-r213960.diff
index 024c689..a3bd4c9 100644
--- a/contrib/llvm/patches/patch-r270147-llvm-r197824-r213427-r213960.diff
+++ b/contrib/llvm/patches/patch-r270147-llvm-r197824-r213427-r213960.diff
@@ -1,3 +1,27 @@
+Backport r197824, r213427 and r213960 from LLVM trunk:
+
+ r197824 | rdivacky | 2013-12-20 19:08:54 +0100 (Fri, 20 Dec 2013) | 2 lines
+
+ Implement initial-exec TLS for PPC32.
+
+ r213427 | hfinkel | 2014-07-19 01:29:49 +0200 (Sat, 19 Jul 2014) | 7 lines
+
+ [PowerPC] 32-bit ELF PIC support
+
+ This adds initial support for PPC32 ELF PIC (Position Independent Code; the
+ -fPIC variety), thus rectifying a long-standing deficiency in the PowerPC
+ backend.
+
+ Patch by Justin Hibbits!
+
+ r213960 | hfinkel | 2014-07-25 19:47:22 +0200 (Fri, 25 Jul 2014) | 3 lines
+
+ [PowerPC] Support TLS on PPC32/ELF
+
+ Patch by Justin Hibbits!
+
+Introduced here: http://svnweb.freebsd.org/changeset/base/270147
+
Index: include/llvm/Support/ELF.h
===================================================================
--- include/llvm/Support/ELF.h (revision 270019)
diff --git a/contrib/llvm/patches/patch-r271024-llvm-r216989-fix-movm-armv6.diff b/contrib/llvm/patches/patch-r271024-llvm-r216989-fix-movm-armv6.diff
deleted file mode 100644
index 30577e7..0000000
--- a/contrib/llvm/patches/patch-r271024-llvm-r216989-fix-movm-armv6.diff
+++ /dev/null
@@ -1,14 +0,0 @@
-Index: lib/Target/ARM/ARMInstrInfo.td
-===================================================================
---- lib/Target/ARM/ARMInstrInfo.td (revision 271024)
-+++ lib/Target/ARM/ARMInstrInfo.td (revision 271026)
-@@ -3248,7 +3248,8 @@
- def : ARMPat<(ARMadde GPR:$src, so_imm_not:$imm, CPSR),
- (SBCri GPR:$src, so_imm_not:$imm)>;
- def : ARMPat<(ARMadde GPR:$src, imm0_65535_neg:$imm, CPSR),
-- (SBCrr GPR:$src, (MOVi16 (imm_not_XFORM imm:$imm)))>;
-+ (SBCrr GPR:$src, (MOVi16 (imm_not_XFORM imm:$imm)))>,
-+ Requires<[IsARM, HasV6T2]>;
-
- // Note: These are implemented in C++ code, because they have to generate
- // ADD/SUBrs instructions, which use a complex pattern that a xform function
diff --git a/contrib/llvm/patches/patch-r271024-llvm-r216989-r216990-fix-movw-armv6.diff b/contrib/llvm/patches/patch-r271024-llvm-r216989-r216990-fix-movw-armv6.diff
new file mode 100644
index 0000000..f477390
--- /dev/null
+++ b/contrib/llvm/patches/patch-r271024-llvm-r216989-r216990-fix-movw-armv6.diff
@@ -0,0 +1,78 @@
+Pull in r216989 from upstream llvm trunk (by Renato Golin):
+
+ MFV: Only emit movw on ARMv6T2+
+
+Pull in r216990 from upstream llvm trunk (by Renato Golin):
+
+ Missing test from r216989
+
+Building for the FreeBSD default target ARMv6 was emitting movw ASM on certain
+test cases (found building qmake4/5 for ARM). Don't do that, moreover, the AS
+in base doesn't understand this instruction for this target. One would need
+to use --integrated-as to get this to build if desired.
+
+Introduced here: http://svnweb.freebsd.org/changeset/base/271025
+
+Index: lib/Target/ARM/ARMInstrInfo.td
+===================================================================
+--- lib/Target/ARM/ARMInstrInfo.td
++++ lib/Target/ARM/ARMInstrInfo.td
+@@ -3248,7 +3248,8 @@
+ def : ARMPat<(ARMadde GPR:$src, so_imm_not:$imm, CPSR),
+ (SBCri GPR:$src, so_imm_not:$imm)>;
+ def : ARMPat<(ARMadde GPR:$src, imm0_65535_neg:$imm, CPSR),
+- (SBCrr GPR:$src, (MOVi16 (imm_not_XFORM imm:$imm)))>;
++ (SBCrr GPR:$src, (MOVi16 (imm_not_XFORM imm:$imm)))>,
++ Requires<[IsARM, HasV6T2]>;
+
+ // Note: These are implemented in C++ code, because they have to generate
+ // ADD/SUBrs instructions, which use a complex pattern that a xform function
+Index: test/CodeGen/ARM/carry.ll
+===================================================================
+--- test/CodeGen/ARM/carry.ll
++++ test/CodeGen/ARM/carry.ll
+@@ -1,4 +1,4 @@
+-; RUN: llc < %s -march=arm | FileCheck %s
++; RUN: llc < %s -mtriple=armv6t2-eabi | FileCheck %s
+
+ define i64 @f1(i64 %a, i64 %b) {
+ ; CHECK-LABEL: f1:
+Index: test/CodeGen/ARM/pr18364-movw.ll
+===================================================================
+--- test/CodeGen/ARM/pr18364-movw.ll
++++ test/CodeGen/ARM/pr18364-movw.ll
+@@ -0,0 +1,34 @@
++; RUN: llc < %s -mtriple=armv5te | FileCheck %s --check-prefix=V5
++; RUN: llc < %s -mtriple=armv6 | FileCheck %s --check-prefix=V6
++; RUN: llc < %s -mtriple=armv6t2 | FileCheck %s --check-prefix=V6T2
++; RUN: llc < %s -mtriple=armv7 | FileCheck %s --check-prefix=V7
++; PR18364
++
++define i64 @f() #0 {
++entry:
++; V5-NOT: movw
++; V6-NOT: movw
++; V6T2: movw
++; V7: movw
++ %y = alloca i64, align 8
++ %z = alloca i64, align 8
++ store i64 1, i64* %y, align 8
++ store i64 11579764786944, i64* %z, align 8
++ %0 = load i64* %y, align 8
++ %1 = load i64* %z, align 8
++ %sub = sub i64 %0, %1
++ ret i64 %sub
++}
++
++define i64 @g(i64 %a, i32 %b) #0 {
++entry:
++; V5-NOT: movw
++; V6-NOT: movw
++; V6T2: movw
++; V7: movw
++ %0 = mul i64 %a, 86400000
++ %mul = add i64 %0, -210866803200000
++ %conv = sext i32 %b to i64
++ %add = add nsw i64 %mul, %conv
++ ret i64 %add
++}
diff --git a/contrib/llvm/patches/patch-r271282-clang-r200797-r200798-r200805-debug-info-crash.diff b/contrib/llvm/patches/patch-r271282-clang-r200797-r200798-r200805-debug-info-crash.diff
index be4ce55..4088dbb 100644
--- a/contrib/llvm/patches/patch-r271282-clang-r200797-r200798-r200805-debug-info-crash.diff
+++ b/contrib/llvm/patches/patch-r271282-clang-r200797-r200798-r200805-debug-info-crash.diff
@@ -1,8 +1,17 @@
-diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
-index 59ba47c..dddc7e7 100644
---- a/lib/CodeGen/CGDebugInfo.cpp
-+++ b/lib/CodeGen/CGDebugInfo.cpp
-@@ -2251,9 +2251,10 @@ llvm::DICompositeType CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
+Pull in r200797 from upstream clang trunk (by Adrian Prantl):
+
+ Debug info: fix a crasher when when emitting debug info for
+ not-yet-completed templated types. getTypeSize() needs a complete type.
+
+ rdar://problem/15931354
+
+Introduced here: http://svnweb.freebsd.org/changeset/base/271282
+
+Index: tools/clang/lib/CodeGen/CGDebugInfo.cpp
+===================================================================
+--- tools/clang/lib/CodeGen/CGDebugInfo.cpp
++++ tools/clang/lib/CodeGen/CGDebugInfo.cpp
+@@ -2251,9 +2251,10 @@ llvm::DICompositeType CGDebugInfo::CreateLimitedTy
if (T && (!T.isForwardDecl() || !RD->getDefinition()))
return T;
@@ -16,36 +25,44 @@ index 59ba47c..dddc7e7 100644
return getOrCreateRecordFwdDecl(Ty, RDContext);
uint64_t Size = CGM.getContext().getTypeSize(Ty);
-diff --git a/test/CodeGenCXX/debug-info-template-fwd.cpp b/test/CodeGenCXX/debug-info-template-fwd.cpp
-new file mode 100644
-index 0000000..b2b7073
---- /dev/null
-+++ b/test/CodeGenCXX/debug-info-template-fwd.cpp
-@@ -0,0 +1,27 @@
+Index: tools/clang/test/CodeGenCXX/debug-info-template-fwd.cpp
+===================================================================
+--- tools/clang/test/CodeGenCXX/debug-info-template-fwd.cpp
++++ tools/clang/test/CodeGenCXX/debug-info-template-fwd.cpp
+@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin -g -emit-llvm -o - | FileCheck %s
-+// This test is for a crash when emitting debug info for not-yet-completed
-+// types.
++// This test is for a crash when emitting debug info for not-yet-completed types.
+// Test that we don't actually emit a forward decl for the offending class:
-+// CHECK: [ DW_TAG_structure_type ] [Derived<int>] {{.*}} [def]
++// CHECK: [ DW_TAG_class_type ] [Derived<const __CFString, Foo>] {{.*}} [def]
+// rdar://problem/15931354
-+template <class A> class Derived;
++typedef const struct __CFString * CFStringRef;
++template <class R> class Returner {};
++typedef const __CFString String;
+
-+template <class A> class Base {
-+ static Derived<A> *create();
++template <class A, class B> class Derived;
++
++template <class A, class B>
++class Base
++{
++ static Derived<A, B>* create();
++};
++
++template <class A, class B>
++class Derived : public Base<A, B> {
++public:
++ static void foo();
+};
+
-+template <class A> struct Derived : Base<A> {
++class Foo
++{
++ Foo();
++ static Returner<Base<String,Foo> > all();
+};
+
-+Base<int> *f;
++Foo::Foo(){}
+
-+// During the instantiation of Derived<int>, Base<int> becomes required to be
-+// complete - since the declaration has already been emitted (due to 'f',
-+// above), we immediately try to build debug info for Base<int> which then
-+// requires the (incomplete definition) of Derived<int> which is problematic.
-+//
-+// (if 'f' is not present, the point at which Base<int> becomes required to be
-+// complete during the instantiation of Derived<int> is a no-op because
-+// Base<int> was never emitted so we ignore it and carry on until we
-+// wire up the base class of Derived<int> in the debug info later on)
-+Derived<int> d;
++Returner<Base<String,Foo> > Foo::all()
++{
++ Derived<String,Foo>::foo();
++ return Foo::all();
++}
diff --git a/contrib/llvm/patches/patch-r271432-clang-r205331-debug-info-crash.diff b/contrib/llvm/patches/patch-r271432-clang-r205331-debug-info-crash.diff
index 4bbf8a1..a140206 100644
--- a/contrib/llvm/patches/patch-r271432-clang-r205331-debug-info-crash.diff
+++ b/contrib/llvm/patches/patch-r271432-clang-r205331-debug-info-crash.diff
@@ -1,18 +1,16 @@
-commit 96365aef99ec463375dfdaf6eb260823e0477b6a
-Author: Adrian Prantl <aprantl@apple.com>
-Date: Tue Apr 1 17:52:06 2014 +0000
+Pull in r205331 from upstream clang trunk (by Adrian Prantl):
- Debug info: fix a crash when emitting IndirectFieldDecls, which were
- previously not handled at all.
- rdar://problem/16348575
-
- git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@205331 91177308-0d34-0410-b5e6-96231b3b80d8
+ Debug info: fix a crash when emitting IndirectFieldDecls, which were
+ previously not handled at all.
+ rdar://problem/16348575
-diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
-index 82db942..2556cf9 100644
---- tools/clang/lib/CodeGen/CGDebugInfo.cpp
-+++ tools/clangb/lib/CodeGen/CGDebugInfo.cpp
-@@ -1252,7 +1252,7 @@ CollectTemplateParams(const TemplateParameterList *TPList,
+Introduced here: http://svnweb.freebsd.org/changeset/base/271432
+
+Index: tools/clang/lib/CodeGen/CGDebugInfo.cpp
+===================================================================
+--- tools/clang/lib/CodeGen/CGDebugInfo.cpp (revision 205330)
++++ tools/clang/lib/CodeGen/CGDebugInfo.cpp (revision 205331)
+@@ -1252,7 +1252,7 @@ CollectTemplateParams(const TemplateParameterList
V = CGM.GetAddrOfFunction(FD);
// Member data pointers have special handling too to compute the fixed
// offset within the object.
@@ -21,11 +19,10 @@ index 82db942..2556cf9 100644
// These five lines (& possibly the above member function pointer
// handling) might be able to be refactored to use similar code in
// CodeGenModule::getMemberPointerConstant
-diff --git a/test/CodeGenCXX/debug-info-indirect-field-decl.cpp b/test/CodeGenCXX/debug-info-indirect-field-decl.cpp
-new file mode 100644
-index 0000000..131ceba
---- /dev/null
-+++ tools/clang/test/CodeGenCXX/debug-info-indirect-field-decl.cpp
+Index: tools/clang/test/CodeGenCXX/debug-info-indirect-field-decl.cpp
+===================================================================
+--- tools/clang/test/CodeGenCXX/debug-info-indirect-field-decl.cpp (revision 0)
++++ tools/clang/test/CodeGenCXX/debug-info-indirect-field-decl.cpp (revision 205331)
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -emit-llvm -g -triple x86_64-apple-darwin %s -o - | FileCheck %s
+//
diff --git a/contrib/llvm/patches/patch-r271597-clang-r217410-i386-garbage-float.diff b/contrib/llvm/patches/patch-r271597-clang-r217410-i386-garbage-float.diff
new file mode 100644
index 0000000..c16279a
--- /dev/null
+++ b/contrib/llvm/patches/patch-r271597-clang-r217410-i386-garbage-float.diff
@@ -0,0 +1,64 @@
+Pull in r217410 from upstream llvm trunk (by Bob Wilson):
+
+ Set trunc store action to Expand for all X86 targets.
+
+ When compiling without SSE2, isTruncStoreLegal(F64, F32) would return
+ Legal, whereas with SSE2 it would return Expand. And since the Target
+ doesn't seem to actually handle a truncstore for double -> float, it
+ would just output a store of a full double in the space for a float
+ hence overwriting other bits on the stack.
+
+ Patch by Luqman Aden!
+
+This should fix clang -O0 on i386 assigning garbage to floats, in
+certain scenarios.
+
+Introduced here: http://svnweb.freebsd.org/changeset/base/271597
+
+Index: lib/Target/X86/X86ISelLowering.cpp
+===================================================================
+--- lib/Target/X86/X86ISelLowering.cpp (revision 208032)
++++ lib/Target/X86/X86ISelLowering.cpp (working copy)
+@@ -300,6 +300,8 @@ void X86TargetLowering::resetOperationActions() {
+ setTruncStoreAction(MVT::i32, MVT::i8 , Expand);
+ setTruncStoreAction(MVT::i16, MVT::i8, Expand);
+
++ setTruncStoreAction(MVT::f64, MVT::f32, Expand);
++
+ // SETOEQ and SETUNE require checking two conditions.
+ setCondCodeAction(ISD::SETOEQ, MVT::f32, Expand);
+ setCondCodeAction(ISD::SETOEQ, MVT::f64, Expand);
+@@ -1011,8 +1013,6 @@ void X86TargetLowering::resetOperationActions() {
+ AddPromotedToType (ISD::SELECT, VT, MVT::v2i64);
+ }
+
+- setTruncStoreAction(MVT::f64, MVT::f32, Expand);
+-
+ // Custom lower v2i64 and v2f64 selects.
+ setOperationAction(ISD::LOAD, MVT::v2f64, Legal);
+ setOperationAction(ISD::LOAD, MVT::v2i64, Legal);
+Index: test/CodeGen/X86/dont-trunc-store-double-to-float.ll
+===================================================================
+--- test/CodeGen/X86/dont-trunc-store-double-to-float.ll (revision 0)
++++ test/CodeGen/X86/dont-trunc-store-double-to-float.ll (working copy)
+@@ -0,0 +1,20 @@
++; RUN: llc -march=x86 < %s | FileCheck %s
++
++; CHECK-LABEL: @bar
++; CHECK: movl $1074339512,
++; CHECK: movl $1374389535,
++; CHECK: movl $1078523331,
++define void @bar() unnamed_addr {
++entry-block:
++ %a = alloca double
++ %b = alloca float
++
++ store double 3.140000e+00, double* %a
++ %0 = load double* %a
++
++ %1 = fptrunc double %0 to float
++
++ store float %1, float* %b
++
++ ret void
++}
diff --git a/contrib/ofed/libibverbs/examples/asyncwatch.c b/contrib/ofed/libibverbs/examples/asyncwatch.c
index da7ebd4..0c82dee 100644
--- a/contrib/ofed/libibverbs/examples/asyncwatch.c
+++ b/contrib/ofed/libibverbs/examples/asyncwatch.c
@@ -35,8 +35,6 @@
#endif /* HAVE_CONFIG_H */
#include <stdio.h>
-#include <endian.h>
-#include <byteswap.h>
#include <infiniband/verbs.h>
diff --git a/contrib/ofed/libibverbs/examples/device_list.c b/contrib/ofed/libibverbs/examples/device_list.c
index 70c3af5..d1b8051 100644
--- a/contrib/ofed/libibverbs/examples/device_list.c
+++ b/contrib/ofed/libibverbs/examples/device_list.c
@@ -36,9 +36,6 @@
#include <stdio.h>
-#include <endian.h>
-#include <byteswap.h>
-
#include <infiniband/verbs.h>
#include <infiniband/arch.h>
diff --git a/contrib/ofed/libibverbs/examples/devinfo.c b/contrib/ofed/libibverbs/examples/devinfo.c
index 393ec04..4bcb911 100644
--- a/contrib/ofed/libibverbs/examples/devinfo.c
+++ b/contrib/ofed/libibverbs/examples/devinfo.c
@@ -41,8 +41,6 @@
#include <string.h>
#include <getopt.h>
#include <netinet/in.h>
-#include <endian.h>
-#include <byteswap.h>
#include <infiniband/verbs.h>
#include <infiniband/driver.h>
diff --git a/contrib/ofed/libmlx4/src/mlx4-abi.h b/contrib/ofed/libmlx4/src/mlx4-abi.h
index 1b1253c..cc054e4 100644
--- a/contrib/ofed/libmlx4/src/mlx4-abi.h
+++ b/contrib/ofed/libmlx4/src/mlx4-abi.h
@@ -36,7 +36,7 @@
#include <infiniband/kern-abi.h>
#define MLX4_UVERBS_MIN_ABI_VERSION 2
-#define MLX4_UVERBS_MAX_ABI_VERSION 3
+#define MLX4_UVERBS_MAX_ABI_VERSION 4
struct mlx4_alloc_ucontext_resp {
struct ibv_get_context_resp ibv_resp;
diff --git a/contrib/pjdfstest/FREEBSD-upgrade b/contrib/pjdfstest/FREEBSD-upgrade
new file mode 100644
index 0000000..eff295f
--- /dev/null
+++ b/contrib/pjdfstest/FREEBSD-upgrade
@@ -0,0 +1,25 @@
+$FreeBSD$
+
+This document contains a collection of notes specific to the import
+of pjdfstest into head. These notes are built on the instructions in
+the FreeBSD Subversion Primer that detail how to deal with vendor
+branches and you are supposed to follow those:
+
+ http://www.freebsd.org/doc/en/articles/committers-guide/subversion-primer.html
+
+The pjdfstest source code is hosted on GitHub:
+
+ https://github.com/pjd/pjdfstest
+
+and is imported into the pjdfstest vendor branch (see base/vendor/pjdfstest/).
+
+To merge the vendor branch into head do something like this:
+
+ cd .../base/head/contrib/pjdfstest
+ svn merge --accept=postpone \
+ svn+ssh://svn.freebsd.org/base/vendor/pjdfstest/dist .
+
+and resolve any conflicts that may arise at this point.
+
+Lastly, with the list of old and new files in this import, make sure
+to update the reachover Makefiles accordingly.
diff --git a/tools/regression/pjdfstest/LICENSE b/contrib/pjdfstest/LICENSE
index bde2232..f91e71b 100644
--- a/tools/regression/pjdfstest/LICENSE
+++ b/contrib/pjdfstest/LICENSE
@@ -1,8 +1,8 @@
-$FreeBSD$
+$FreeBSD: head/tools/regression/pjdfstest/LICENSE 211354 2010-08-15 21:29:03Z pjd $
License for all regression tests available with pjdfstest:
-Copyright (c) 2006-2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
+Copyright (c) 2006-2012 Pawel Jakub Dawidek <pawel@dawidek.net>
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/tools/regression/pjdfstest/Makefile b/contrib/pjdfstest/Makefile
index 18f94e9..a3e35f8 100644
--- a/tools/regression/pjdfstest/Makefile
+++ b/contrib/pjdfstest/Makefile
@@ -18,7 +18,7 @@ ${PROG}: ${PROG}.c
echo "Unsupported operating system: ${OSTYPE}."; \
exit 1; \
fi; \
- cmd="cc -Wall $$CFLAGS ${PROG}.c -o ${PROG}"; \
+ cmd="gcc -Wall $$CFLAGS ${PROG}.c -o ${PROG}"; \
echo $$cmd; \
$$cmd
diff --git a/tools/regression/pjdfstest/README b/contrib/pjdfstest/README
index fb1cda5..dcc5a64 100644
--- a/tools/regression/pjdfstest/README
+++ b/contrib/pjdfstest/README
@@ -1,4 +1,4 @@
-$FreeBSD$
+$FreeBSD: head/tools/regression/pjdfstest/README 211354 2010-08-15 21:29:03Z pjd $
Few notes on how to use pjdfstest in short steps:
@@ -19,4 +19,4 @@ Currently supported operating systems: FreeBSD, Solaris.
Currently supported file system types: UFS, ZFS.
--
-Pawel Jakub Dawidek <pjd@FreeBSD.org>
+Pawel Jakub Dawidek <pawel@dawidek.net>
diff --git a/tools/regression/pjdfstest/pjdfstest.c b/contrib/pjdfstest/pjdfstest.c
index 046df49..046df49 100644
--- a/tools/regression/pjdfstest/pjdfstest.c
+++ b/contrib/pjdfstest/pjdfstest.c
diff --git a/tools/regression/pjdfstest/tests/chflags/00.t b/contrib/pjdfstest/tests/chflags/00.t
index b233b8e..4d7b4c9 100644
--- a/tools/regression/pjdfstest/tests/chflags/00.t
+++ b/contrib/pjdfstest/tests/chflags/00.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chflags/00.t 211352 2010-08-15 21:24:17Z pjd $
desc="chflags changes flags"
diff --git a/tools/regression/pjdfstest/tests/chflags/01.t b/contrib/pjdfstest/tests/chflags/01.t
index b71951b..62713fd 100644
--- a/tools/regression/pjdfstest/tests/chflags/01.t
+++ b/contrib/pjdfstest/tests/chflags/01.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chflags/01.t 211474 2010-08-18 22:06:43Z pjd $
desc="chflags returns ENOTDIR if a component of the path prefix is not a directory"
diff --git a/tools/regression/pjdfstest/tests/chflags/02.t b/contrib/pjdfstest/tests/chflags/02.t
index b64345b..d4a0b37 100644
--- a/tools/regression/pjdfstest/tests/chflags/02.t
+++ b/contrib/pjdfstest/tests/chflags/02.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chflags/02.t 211352 2010-08-15 21:24:17Z pjd $
desc="chflags returns ENAMETOOLONG if a component of a pathname exceeded {NAME_MAX} characters"
diff --git a/tools/regression/pjdfstest/tests/chflags/03.t b/contrib/pjdfstest/tests/chflags/03.t
index 9552831..87a6202 100644
--- a/tools/regression/pjdfstest/tests/chflags/03.t
+++ b/contrib/pjdfstest/tests/chflags/03.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chflags/03.t 211352 2010-08-15 21:24:17Z pjd $
desc="chflags returns ENAMETOOLONG if an entire path name exceeded {PATH_MAX} characters"
diff --git a/tools/regression/pjdfstest/tests/chflags/04.t b/contrib/pjdfstest/tests/chflags/04.t
index 591ae69..3d5aa3b 100644
--- a/tools/regression/pjdfstest/tests/chflags/04.t
+++ b/contrib/pjdfstest/tests/chflags/04.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chflags/04.t 211352 2010-08-15 21:24:17Z pjd $
desc="chflags returns ENOENT if the named file does not exist"
diff --git a/tools/regression/pjdfstest/tests/chflags/05.t b/contrib/pjdfstest/tests/chflags/05.t
index 7409798..cc3e04b 100644
--- a/tools/regression/pjdfstest/tests/chflags/05.t
+++ b/contrib/pjdfstest/tests/chflags/05.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chflags/05.t 211352 2010-08-15 21:24:17Z pjd $
desc="chflags returns EACCES when search permission is denied for a component of the path prefix"
diff --git a/tools/regression/pjdfstest/tests/chflags/06.t b/contrib/pjdfstest/tests/chflags/06.t
index ae5973e..e4899eb 100644
--- a/tools/regression/pjdfstest/tests/chflags/06.t
+++ b/contrib/pjdfstest/tests/chflags/06.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chflags/06.t 211352 2010-08-15 21:24:17Z pjd $
desc="chflags returns ELOOP if too many symbolic links were encountered in translating the pathname"
diff --git a/tools/regression/pjdfstest/tests/chflags/07.t b/contrib/pjdfstest/tests/chflags/07.t
index 5d898d8..c2d0af2 100644
--- a/tools/regression/pjdfstest/tests/chflags/07.t
+++ b/contrib/pjdfstest/tests/chflags/07.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chflags/07.t 211352 2010-08-15 21:24:17Z pjd $
desc="chflags returns EPERM when the effective user ID does not match the owner of the file and the effective user ID is not the super-user"
diff --git a/tools/regression/pjdfstest/tests/chflags/08.t b/contrib/pjdfstest/tests/chflags/08.t
index 18d593d..62ed480 100644
--- a/tools/regression/pjdfstest/tests/chflags/08.t
+++ b/contrib/pjdfstest/tests/chflags/08.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chflags/08.t 211352 2010-08-15 21:24:17Z pjd $
desc="chflags returns EPERM when one of SF_IMMUTABLE, SF_APPEND, or SF_NOUNLINK is set and the user is not the super-user"
diff --git a/tools/regression/pjdfstest/tests/chflags/09.t b/contrib/pjdfstest/tests/chflags/09.t
index e40d7a8..e7bd5cc 100644
--- a/tools/regression/pjdfstest/tests/chflags/09.t
+++ b/contrib/pjdfstest/tests/chflags/09.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chflags/09.t 211352 2010-08-15 21:24:17Z pjd $
desc="chflags returns EPERM when one of SF_IMMUTABLE, SF_APPEND, or SF_NOUNLINK is set and securelevel is greater than 0"
diff --git a/tools/regression/pjdfstest/tests/chflags/10.t b/contrib/pjdfstest/tests/chflags/10.t
index 55f0be6..11ce36b 100644
--- a/tools/regression/pjdfstest/tests/chflags/10.t
+++ b/contrib/pjdfstest/tests/chflags/10.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chflags/10.t 211352 2010-08-15 21:24:17Z pjd $
desc="chflags returns EPERM if non-super-user tries to set one of SF_IMMUTABLE, SF_APPEND, or SF_NOUNLINK"
diff --git a/tools/regression/pjdfstest/tests/chflags/11.t b/contrib/pjdfstest/tests/chflags/11.t
index 19af411..33acca7 100644
--- a/tools/regression/pjdfstest/tests/chflags/11.t
+++ b/contrib/pjdfstest/tests/chflags/11.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chflags/11.t 211352 2010-08-15 21:24:17Z pjd $
desc="chflags returns EPERM if a user tries to set or remove the SF_SNAPSHOT flag"
diff --git a/tools/regression/pjdfstest/tests/chflags/12.t b/contrib/pjdfstest/tests/chflags/12.t
index 950458e..794139b 100644
--- a/tools/regression/pjdfstest/tests/chflags/12.t
+++ b/contrib/pjdfstest/tests/chflags/12.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chflags/12.t 211352 2010-08-15 21:24:17Z pjd $
desc="chflags returns EROFS if the named file resides on a read-only file system"
@@ -16,8 +16,8 @@ FreeBSD:UFS)
n1=`namegen`
expect 0 mkdir ${n0} 0755
- n=`mdconfig -a -n -t malloc -s 1m`
- newfs /dev/md${n} >/dev/null
+ n=`mdconfig -a -n -t malloc -s 1m` || exit
+ newfs /dev/md${n} >/dev/null || exit
mount /dev/md${n} ${n0}
expect 0 create ${n0}/${n1} 0644
expect 0 chflags ${n0}/${n1} UF_IMMUTABLE
@@ -34,7 +34,7 @@ FreeBSD:UFS)
expect none stat ${n0}/${n1} flags
expect 0 unlink ${n0}/${n1}
umount /dev/md${n}
- mdconfig -d -u ${n}
+ mdconfig -d -u ${n} || exit
expect 0 rmdir ${n0}
;;
FreeBSD:ZFS)
@@ -43,7 +43,7 @@ FreeBSD:ZFS)
n0=`namegen`
n1=`namegen`
- n=`mdconfig -a -n -t malloc -s 128m`
+ n=`mdconfig -a -n -t malloc -s 128m` || exit
zpool create ${n0} /dev/md${n}
expect 0 create /${n0}/${n1} 0644
expect 0 chflags /${n0}/${n1} UF_NODUMP
@@ -60,7 +60,7 @@ FreeBSD:ZFS)
expect none stat /${n0}/${n1} flags
expect 0 unlink /${n0}/${n1}
zpool destroy ${n0}
- mdconfig -d -u ${n}
+ mdconfig -d -u ${n} || exit
;;
*)
quick_exit
diff --git a/tools/regression/pjdfstest/tests/chflags/13.t b/contrib/pjdfstest/tests/chflags/13.t
index 247246a..981122c 100644
--- a/tools/regression/pjdfstest/tests/chflags/13.t
+++ b/contrib/pjdfstest/tests/chflags/13.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chflags/13.t 211352 2010-08-15 21:24:17Z pjd $
desc="chflags returns EFAULT if the path argument points outside the process's allocated address space"
diff --git a/tools/regression/pjdfstest/tests/chmod/00.t b/contrib/pjdfstest/tests/chmod/00.t
index 311a8c8..d68d0cf 100644
--- a/tools/regression/pjdfstest/tests/chmod/00.t
+++ b/contrib/pjdfstest/tests/chmod/00.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chmod/00.t 211352 2010-08-15 21:24:17Z pjd $
desc="chmod changes permission"
diff --git a/tools/regression/pjdfstest/tests/chmod/01.t b/contrib/pjdfstest/tests/chmod/01.t
index 49164e7..85802fc 100644
--- a/tools/regression/pjdfstest/tests/chmod/01.t
+++ b/contrib/pjdfstest/tests/chmod/01.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chmod/01.t 211474 2010-08-18 22:06:43Z pjd $
desc="chmod returns ENOTDIR if a component of the path prefix is not a directory"
diff --git a/tools/regression/pjdfstest/tests/chmod/02.t b/contrib/pjdfstest/tests/chmod/02.t
index ece2b6c..0cadec2 100644
--- a/tools/regression/pjdfstest/tests/chmod/02.t
+++ b/contrib/pjdfstest/tests/chmod/02.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chmod/02.t 211352 2010-08-15 21:24:17Z pjd $
desc="chmod returns ENAMETOOLONG if a component of a pathname exceeded {NAME_MAX} characters"
diff --git a/tools/regression/pjdfstest/tests/chmod/03.t b/contrib/pjdfstest/tests/chmod/03.t
index 30261d5..fa4580f 100644
--- a/tools/regression/pjdfstest/tests/chmod/03.t
+++ b/contrib/pjdfstest/tests/chmod/03.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chmod/03.t 211352 2010-08-15 21:24:17Z pjd $
desc="chmod returns ENAMETOOLONG if an entire path name exceeded {PATH_MAX} characters"
diff --git a/tools/regression/pjdfstest/tests/chmod/04.t b/contrib/pjdfstest/tests/chmod/04.t
index a125ae2..9386c9a 100644
--- a/tools/regression/pjdfstest/tests/chmod/04.t
+++ b/contrib/pjdfstest/tests/chmod/04.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chmod/04.t 211352 2010-08-15 21:24:17Z pjd $
desc="chmod returns ENOENT if the named file does not exist"
diff --git a/tools/regression/pjdfstest/tests/chmod/05.t b/contrib/pjdfstest/tests/chmod/05.t
index c06895a..5648e46e 100644
--- a/tools/regression/pjdfstest/tests/chmod/05.t
+++ b/contrib/pjdfstest/tests/chmod/05.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chmod/05.t 211352 2010-08-15 21:24:17Z pjd $
desc="chmod returns EACCES when search permission is denied for a component of the path prefix"
diff --git a/tools/regression/pjdfstest/tests/chmod/06.t b/contrib/pjdfstest/tests/chmod/06.t
index c06fe2b..d44b3cb 100644
--- a/tools/regression/pjdfstest/tests/chmod/06.t
+++ b/contrib/pjdfstest/tests/chmod/06.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chmod/06.t 211474 2010-08-18 22:06:43Z pjd $
desc="chmod returns ELOOP if too many symbolic links were encountered in translating the pathname"
diff --git a/tools/regression/pjdfstest/tests/chmod/07.t b/contrib/pjdfstest/tests/chmod/07.t
index 519b7fd..012e59a 100644
--- a/tools/regression/pjdfstest/tests/chmod/07.t
+++ b/contrib/pjdfstest/tests/chmod/07.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chmod/07.t 211352 2010-08-15 21:24:17Z pjd $
desc="chmod returns EPERM if the operation would change the ownership, but the effective user ID is not the super-user"
diff --git a/tools/regression/pjdfstest/tests/chmod/08.t b/contrib/pjdfstest/tests/chmod/08.t
index bf27134..5b37569 100644
--- a/tools/regression/pjdfstest/tests/chmod/08.t
+++ b/contrib/pjdfstest/tests/chmod/08.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chmod/08.t 211352 2010-08-15 21:24:17Z pjd $
desc="chmod returns EPERM if the named file has its immutable or append-only flag set"
diff --git a/tools/regression/pjdfstest/tests/chmod/09.t b/contrib/pjdfstest/tests/chmod/09.t
index 18e4cdc..f4b911e 100644
--- a/tools/regression/pjdfstest/tests/chmod/09.t
+++ b/contrib/pjdfstest/tests/chmod/09.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chmod/09.t 211352 2010-08-15 21:24:17Z pjd $
desc="chmod returns EROFS if the named file resides on a read-only file system"
@@ -14,9 +14,9 @@ n0=`namegen`
n1=`namegen`
expect 0 mkdir ${n0} 0755
-n=`mdconfig -a -n -t malloc -s 1m`
-newfs /dev/md${n} >/dev/null
-mount /dev/md${n} ${n0}
+n=`mdconfig -a -n -t malloc -s 1m` || exit
+newfs /dev/md${n} >/dev/null || exit
+mount /dev/md${n} ${n0} || exit
expect 0 create ${n0}/${n1} 0644
expect 0 chmod ${n0}/${n1} 0640
expect 0640 stat ${n0}/${n1} mode
@@ -33,5 +33,5 @@ expect 0 lchmod ${n0}/${n1} 0640
expect 0640 stat ${n0}/${n1} mode
expect 0 unlink ${n0}/${n1}
umount /dev/md${n}
-mdconfig -d -u ${n}
+mdconfig -d -u ${n} || exit
expect 0 rmdir ${n0}
diff --git a/tools/regression/pjdfstest/tests/chmod/10.t b/contrib/pjdfstest/tests/chmod/10.t
index b75b712..1153429 100644
--- a/tools/regression/pjdfstest/tests/chmod/10.t
+++ b/contrib/pjdfstest/tests/chmod/10.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chmod/10.t 211352 2010-08-15 21:24:17Z pjd $
desc="chmod returns EFAULT if the path argument points outside the process's allocated address space"
diff --git a/tools/regression/pjdfstest/tests/chmod/11.t b/contrib/pjdfstest/tests/chmod/11.t
index 8829896..94c5e5f 100644
--- a/tools/regression/pjdfstest/tests/chmod/11.t
+++ b/contrib/pjdfstest/tests/chmod/11.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chmod/11.t 211352 2010-08-15 21:24:17Z pjd $
desc="chmod returns EFTYPE if the effective user ID is not the super-user, the mode includes the sticky bit (S_ISVTX), and path does not refer to a directory"
diff --git a/tools/regression/pjdfstest/tests/chmod/12.t b/contrib/pjdfstest/tests/chmod/12.t
index affa8de..b7f7d67 100644
--- a/tools/regression/pjdfstest/tests/chmod/12.t
+++ b/contrib/pjdfstest/tests/chmod/12.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chmod/12.t 219463 2011-03-10 20:59:02Z pjd $
desc="verify SUID/SGID bit behaviour"
diff --git a/contrib/pjdfstest/tests/chmod/foo b/contrib/pjdfstest/tests/chmod/foo
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/contrib/pjdfstest/tests/chmod/foo
diff --git a/tools/regression/pjdfstest/tests/chown/00.t b/contrib/pjdfstest/tests/chown/00.t
index a3ccbac..5c6be97 100644
--- a/tools/regression/pjdfstest/tests/chown/00.t
+++ b/contrib/pjdfstest/tests/chown/00.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chown/00.t 228975 2011-12-30 00:04:11Z uqs $
desc="chown changes ownership"
diff --git a/tools/regression/pjdfstest/tests/chown/01.t b/contrib/pjdfstest/tests/chown/01.t
index 249ce4d..1813394 100644
--- a/tools/regression/pjdfstest/tests/chown/01.t
+++ b/contrib/pjdfstest/tests/chown/01.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chown/01.t 211474 2010-08-18 22:06:43Z pjd $
desc="chown returns ENOTDIR if a component of the path prefix is not a directory"
diff --git a/tools/regression/pjdfstest/tests/chown/02.t b/contrib/pjdfstest/tests/chown/02.t
index 2225f64..e110db8 100644
--- a/tools/regression/pjdfstest/tests/chown/02.t
+++ b/contrib/pjdfstest/tests/chown/02.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chown/02.t 211352 2010-08-15 21:24:17Z pjd $
desc="chown returns ENAMETOOLONG if a component of a pathname exceeded ${NAME_MAX} characters"
diff --git a/tools/regression/pjdfstest/tests/chown/03.t b/contrib/pjdfstest/tests/chown/03.t
index 6bb43a2..031a878 100644
--- a/tools/regression/pjdfstest/tests/chown/03.t
+++ b/contrib/pjdfstest/tests/chown/03.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chown/03.t 211352 2010-08-15 21:24:17Z pjd $
desc="chown returns ENAMETOOLONG if an entire path name exceeded {PATH_MAX} characters"
diff --git a/tools/regression/pjdfstest/tests/chown/04.t b/contrib/pjdfstest/tests/chown/04.t
index e66d936..d6eac19 100644
--- a/tools/regression/pjdfstest/tests/chown/04.t
+++ b/contrib/pjdfstest/tests/chown/04.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chown/04.t 211410 2010-08-17 06:08:09Z pjd $
desc="chown returns ENOENT if the named file does not exist"
diff --git a/tools/regression/pjdfstest/tests/chown/05.t b/contrib/pjdfstest/tests/chown/05.t
index ec7cd5c..5a27a9c 100644
--- a/tools/regression/pjdfstest/tests/chown/05.t
+++ b/contrib/pjdfstest/tests/chown/05.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chown/05.t 211410 2010-08-17 06:08:09Z pjd $
desc="chown returns EACCES when search permission is denied for a component of the path prefix"
diff --git a/tools/regression/pjdfstest/tests/chown/06.t b/contrib/pjdfstest/tests/chown/06.t
index 39ccac6..a7ac349 100644
--- a/tools/regression/pjdfstest/tests/chown/06.t
+++ b/contrib/pjdfstest/tests/chown/06.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chown/06.t 211410 2010-08-17 06:08:09Z pjd $
desc="chown returns ELOOP if too many symbolic links were encountered in translating the pathname"
diff --git a/tools/regression/pjdfstest/tests/chown/07.t b/contrib/pjdfstest/tests/chown/07.t
index 7f73cbe..f188080 100644
--- a/tools/regression/pjdfstest/tests/chown/07.t
+++ b/contrib/pjdfstest/tests/chown/07.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chown/07.t 211410 2010-08-17 06:08:09Z pjd $
desc="chown returns EPERM if the operation would change the ownership, but the effective user ID is not the super-user and the process is not an owner of the file"
diff --git a/tools/regression/pjdfstest/tests/chown/08.t b/contrib/pjdfstest/tests/chown/08.t
index 9bff354..a98f873 100644
--- a/tools/regression/pjdfstest/tests/chown/08.t
+++ b/contrib/pjdfstest/tests/chown/08.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chown/08.t 211352 2010-08-15 21:24:17Z pjd $
desc="chown returns EPERM if the named file has its immutable or append-only flag set"
diff --git a/tools/regression/pjdfstest/tests/chown/09.t b/contrib/pjdfstest/tests/chown/09.t
index cc14328..a99751e 100644
--- a/tools/regression/pjdfstest/tests/chown/09.t
+++ b/contrib/pjdfstest/tests/chown/09.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chown/09.t 211352 2010-08-15 21:24:17Z pjd $
desc="chown returns EROFS if the named file resides on a read-only file system"
@@ -14,9 +14,9 @@ n0=`namegen`
n1=`namegen`
expect 0 mkdir ${n0} 0755
-n=`mdconfig -a -n -t malloc -s 1m`
-newfs /dev/md${n} >/dev/null
-mount /dev/md${n} ${n0}
+n=`mdconfig -a -n -t malloc -s 1m` || exit
+newfs /dev/md${n} >/dev/null || exit
+mount /dev/md${n} ${n0} || exit
expect 0 create ${n0}/${n1} 0644
expect 0 chown ${n0}/${n1} 65534 65534
expect 65534,65534 stat ${n0}/${n1} uid,gid
@@ -28,5 +28,5 @@ expect 0 chown ${n0}/${n1} 65533 65533
expect 65533,65533 stat ${n0}/${n1} uid,gid
expect 0 unlink ${n0}/${n1}
umount /dev/md${n}
-mdconfig -d -u ${n}
+mdconfig -d -u ${n} || exit
expect 0 rmdir ${n0}
diff --git a/tools/regression/pjdfstest/tests/chown/10.t b/contrib/pjdfstest/tests/chown/10.t
index 961a5be..e791008 100644
--- a/tools/regression/pjdfstest/tests/chown/10.t
+++ b/contrib/pjdfstest/tests/chown/10.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/chown/10.t 211410 2010-08-17 06:08:09Z pjd $
desc="chown returns EFAULT if the path argument points outside the process's allocated address space"
diff --git a/tools/regression/pjdfstest/tests/conf b/contrib/pjdfstest/tests/conf
index f914941..adb6cd6 100644
--- a/tools/regression/pjdfstest/tests/conf
+++ b/contrib/pjdfstest/tests/conf
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/conf 211354 2010-08-15 21:29:03Z pjd $
# pjdfstest configuration file
# Supported operating systems: FreeBSD, Darwin, SunOS, Linux
diff --git a/tools/regression/pjdfstest/tests/ftruncate/00.t b/contrib/pjdfstest/tests/ftruncate/00.t
index 9028a29..0f25301 100644
--- a/tools/regression/pjdfstest/tests/ftruncate/00.t
+++ b/contrib/pjdfstest/tests/ftruncate/00.t
@@ -1,12 +1,12 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/ftruncate/00.t 219439 2011-03-09 23:11:30Z pjd $
desc="ftruncate descrease/increase file size"
dir=`dirname $0`
. ${dir}/../misc.sh
-echo "1..21"
+echo "1..26"
n0=`namegen`
n1=`namegen`
diff --git a/tools/regression/pjdfstest/tests/truncate/01.t b/contrib/pjdfstest/tests/ftruncate/01.t
index ac504a1..a8e95ac 100644
--- a/tools/regression/pjdfstest/tests/truncate/01.t
+++ b/contrib/pjdfstest/tests/ftruncate/01.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/truncate/01.t 211352 2010-08-15 21:24:17Z pjd $
desc="truncate returns ENOTDIR if a component of the path prefix is not a directory"
diff --git a/tools/regression/pjdfstest/tests/truncate/02.t b/contrib/pjdfstest/tests/ftruncate/02.t
index 3f3590f..83de38d 100644
--- a/tools/regression/pjdfstest/tests/truncate/02.t
+++ b/contrib/pjdfstest/tests/ftruncate/02.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/truncate/02.t 211352 2010-08-15 21:24:17Z pjd $
desc="truncate returns ENAMETOOLONG if a component of a pathname exceeded {NAME_MAX} characters"
diff --git a/tools/regression/pjdfstest/tests/truncate/03.t b/contrib/pjdfstest/tests/ftruncate/03.t
index 0ed60a9..41e9862 100644
--- a/tools/regression/pjdfstest/tests/truncate/03.t
+++ b/contrib/pjdfstest/tests/ftruncate/03.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/truncate/03.t 211352 2010-08-15 21:24:17Z pjd $
desc="truncate returns ENAMETOOLONG if an entire path name exceeded {PATH_MAX} characters"
diff --git a/tools/regression/pjdfstest/tests/truncate/04.t b/contrib/pjdfstest/tests/ftruncate/04.t
index 14f513c..cd1cfc6 100644
--- a/tools/regression/pjdfstest/tests/truncate/04.t
+++ b/contrib/pjdfstest/tests/ftruncate/04.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/truncate/04.t 211352 2010-08-15 21:24:17Z pjd $
desc="truncate returns ENOENT if the named file does not exist"
diff --git a/tools/regression/pjdfstest/tests/truncate/05.t b/contrib/pjdfstest/tests/ftruncate/05.t
index 9aa65c8..f128815 100644
--- a/tools/regression/pjdfstest/tests/truncate/05.t
+++ b/contrib/pjdfstest/tests/ftruncate/05.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/truncate/05.t 211352 2010-08-15 21:24:17Z pjd $
desc="truncate returns EACCES when search permission is denied for a component of the path prefix"
diff --git a/tools/regression/pjdfstest/tests/truncate/06.t b/contrib/pjdfstest/tests/ftruncate/06.t
index 8e0ca5b..1ce516f 100644
--- a/tools/regression/pjdfstest/tests/truncate/06.t
+++ b/contrib/pjdfstest/tests/ftruncate/06.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/truncate/06.t 211352 2010-08-15 21:24:17Z pjd $
desc="truncate returns EACCES if the named file is not writable by the user"
diff --git a/tools/regression/pjdfstest/tests/truncate/07.t b/contrib/pjdfstest/tests/ftruncate/07.t
index 60b8b90..44f87e7 100644
--- a/tools/regression/pjdfstest/tests/truncate/07.t
+++ b/contrib/pjdfstest/tests/ftruncate/07.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/truncate/07.t 211352 2010-08-15 21:24:17Z pjd $
desc="truncate returns ELOOP if too many symbolic links were encountered in translating the pathname"
diff --git a/tools/regression/pjdfstest/tests/truncate/08.t b/contrib/pjdfstest/tests/ftruncate/08.t
index 75d6679..6f205ef 100644
--- a/tools/regression/pjdfstest/tests/truncate/08.t
+++ b/contrib/pjdfstest/tests/ftruncate/08.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/truncate/08.t 211352 2010-08-15 21:24:17Z pjd $
desc="truncate returns EPERM if the named file has its immutable or append-only flag set"
diff --git a/tools/regression/pjdfstest/tests/truncate/09.t b/contrib/pjdfstest/tests/ftruncate/09.t
index 1d95c7f..d7e082d 100644
--- a/tools/regression/pjdfstest/tests/truncate/09.t
+++ b/contrib/pjdfstest/tests/ftruncate/09.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/truncate/09.t 211352 2010-08-15 21:24:17Z pjd $
desc="truncate returns EISDIR if the named file is a directory"
diff --git a/tools/regression/pjdfstest/tests/truncate/10.t b/contrib/pjdfstest/tests/ftruncate/10.t
index 6fcd129..ced3583 100644
--- a/tools/regression/pjdfstest/tests/truncate/10.t
+++ b/contrib/pjdfstest/tests/ftruncate/10.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/truncate/10.t 211352 2010-08-15 21:24:17Z pjd $
desc="truncate returns EROFS if the named file resides on a read-only file system"
@@ -14,9 +14,9 @@ n0=`namegen`
n1=`namegen`
expect 0 mkdir ${n0} 0755
-n=`mdconfig -a -n -t malloc -s 1m`
-newfs /dev/md${n} >/dev/null
-mount /dev/md${n} ${n0}
+n=`mdconfig -a -n -t malloc -s 1m` || exit
+newfs /dev/md${n} >/dev/null || exit
+mount /dev/md${n} ${n0} || exit
expect 0 create ${n0}/${n1} 0644
expect 0 truncate ${n0}/${n1} 123
expect 123 stat ${n0}/${n1} size
@@ -28,5 +28,5 @@ expect 0 truncate ${n0}/${n1} 1234
expect 1234 stat ${n0}/${n1} size
expect 0 unlink ${n0}/${n1}
umount /dev/md${n}
-mdconfig -d -u ${n}
+mdconfig -d -u ${n} || exit
expect 0 rmdir ${n0}
diff --git a/tools/regression/pjdfstest/tests/truncate/11.t b/contrib/pjdfstest/tests/ftruncate/11.t
index 255fd19..b00d7b8 100644
--- a/tools/regression/pjdfstest/tests/truncate/11.t
+++ b/contrib/pjdfstest/tests/ftruncate/11.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/truncate/11.t 211352 2010-08-15 21:24:17Z pjd $
desc="truncate returns ETXTBSY the file is a pure procedure (shared text) file that is being executed"
diff --git a/tools/regression/pjdfstest/tests/truncate/12.t b/contrib/pjdfstest/tests/ftruncate/12.t
index cf6a497..1825456 100644
--- a/tools/regression/pjdfstest/tests/truncate/12.t
+++ b/contrib/pjdfstest/tests/ftruncate/12.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/truncate/12.t 211352 2010-08-15 21:24:17Z pjd $
desc="truncate returns EFBIG or EINVAL if the length argument was greater than the maximum file size"
diff --git a/contrib/pjdfstest/tests/ftruncate/13.t b/contrib/pjdfstest/tests/ftruncate/13.t
new file mode 100644
index 0000000..28307ae
--- /dev/null
+++ b/contrib/pjdfstest/tests/ftruncate/13.t
@@ -0,0 +1,16 @@
+#!/bin/sh
+# $FreeBSD: head/tools/regression/pjdfstest/tests/truncate/13.t 211352 2010-08-15 21:24:17Z pjd $
+
+desc="ftruncate returns EINVAL if the length argument was less than 0"
+
+dir=`dirname $0`
+. ${dir}/../misc.sh
+
+echo "1..4"
+
+n0=`namegen`
+
+expect 0 create ${n0} 0644
+expect EINVAL -- open ${n0} O_RDWR : ftruncate 0 -1
+expect EINVAL -- open ${n0} O_WRONLY : ftruncate 0 -999999
+expect 0 unlink ${n0}
diff --git a/tools/regression/pjdfstest/tests/truncate/14.t b/contrib/pjdfstest/tests/ftruncate/14.t
index 53dca71..a238771 100644
--- a/tools/regression/pjdfstest/tests/truncate/14.t
+++ b/contrib/pjdfstest/tests/ftruncate/14.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/truncate/14.t 211352 2010-08-15 21:24:17Z pjd $
desc="truncate returns EFAULT if the path argument points outside the process's allocated address space"
diff --git a/tools/regression/pjdfstest/tests/granular/00.t b/contrib/pjdfstest/tests/granular/00.t
index 4e04260..629f66e 100644
--- a/tools/regression/pjdfstest/tests/granular/00.t
+++ b/contrib/pjdfstest/tests/granular/00.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/granular/00.t 211352 2010-08-15 21:24:17Z pjd $
desc="NFSv4 granular permissions checking - WRITE_DATA vs APPEND_DATA on directories"
diff --git a/tools/regression/pjdfstest/tests/granular/01.t b/contrib/pjdfstest/tests/granular/01.t
index 1c6b3f3..f6658cc 100644
--- a/tools/regression/pjdfstest/tests/granular/01.t
+++ b/contrib/pjdfstest/tests/granular/01.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/granular/01.t 211352 2010-08-15 21:24:17Z pjd $
desc="NFSv4 granular permissions checking - ACL_READ_ATTRIBUTES and ACL_WRITE_ATTRIBUTES"
diff --git a/tools/regression/pjdfstest/tests/granular/02.t b/contrib/pjdfstest/tests/granular/02.t
index 4a33dad..32a318c 100644
--- a/tools/regression/pjdfstest/tests/granular/02.t
+++ b/contrib/pjdfstest/tests/granular/02.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/granular/02.t 211352 2010-08-15 21:24:17Z pjd $
desc="NFSv4 granular permissions checking - ACL_READ_ACL and ACL_WRITE_ACL"
diff --git a/tools/regression/pjdfstest/tests/granular/03.t b/contrib/pjdfstest/tests/granular/03.t
index 195065f..3b825cc 100644
--- a/tools/regression/pjdfstest/tests/granular/03.t
+++ b/contrib/pjdfstest/tests/granular/03.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/granular/03.t 211352 2010-08-15 21:24:17Z pjd $
desc="NFSv4 granular permissions checking - DELETE and DELETE_CHILD"
diff --git a/tools/regression/pjdfstest/tests/granular/04.t b/contrib/pjdfstest/tests/granular/04.t
index 9c0841d..a06b0d6 100644
--- a/tools/regression/pjdfstest/tests/granular/04.t
+++ b/contrib/pjdfstest/tests/granular/04.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/granular/04.t 211352 2010-08-15 21:24:17Z pjd $
desc="NFSv4 granular permissions checking - ACL_WRITE_OWNER"
diff --git a/tools/regression/pjdfstest/tests/granular/05.t b/contrib/pjdfstest/tests/granular/05.t
index 8abf357..c42f51a 100644
--- a/tools/regression/pjdfstest/tests/granular/05.t
+++ b/contrib/pjdfstest/tests/granular/05.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/granular/05.t 211352 2010-08-15 21:24:17Z pjd $
desc="NFSv4 granular permissions checking - DELETE and DELETE_CHILD with directories"
diff --git a/tools/regression/pjdfstest/tests/link/00.t b/contrib/pjdfstest/tests/link/00.t
index b003d78..1bcb32a 100644
--- a/tools/regression/pjdfstest/tests/link/00.t
+++ b/contrib/pjdfstest/tests/link/00.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/link/00.t 211352 2010-08-15 21:24:17Z pjd $
desc="link creates hardlinks"
diff --git a/tools/regression/pjdfstest/tests/link/01.t b/contrib/pjdfstest/tests/link/01.t
index 9400901..fe05aeb 100644
--- a/tools/regression/pjdfstest/tests/link/01.t
+++ b/contrib/pjdfstest/tests/link/01.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/link/01.t 211474 2010-08-18 22:06:43Z pjd $
desc="link returns ENOTDIR if a component of either path prefix is not a directory"
diff --git a/tools/regression/pjdfstest/tests/link/02.t b/contrib/pjdfstest/tests/link/02.t
index 32f78c4..ca3e092 100644
--- a/tools/regression/pjdfstest/tests/link/02.t
+++ b/contrib/pjdfstest/tests/link/02.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/link/02.t 211352 2010-08-15 21:24:17Z pjd $
desc="link returns ENAMETOOLONG if a component of either pathname exceeded {NAME_MAX} characters"
diff --git a/tools/regression/pjdfstest/tests/link/03.t b/contrib/pjdfstest/tests/link/03.t
index 0ad79c3..22f8e55 100644
--- a/tools/regression/pjdfstest/tests/link/03.t
+++ b/contrib/pjdfstest/tests/link/03.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/link/03.t 211352 2010-08-15 21:24:17Z pjd $
desc="link returns ENAMETOOLONG if an entire length of either path name exceeded {PATH_MAX} characters"
diff --git a/tools/regression/pjdfstest/tests/link/04.t b/contrib/pjdfstest/tests/link/04.t
index d27beef..bb09539 100644
--- a/tools/regression/pjdfstest/tests/link/04.t
+++ b/contrib/pjdfstest/tests/link/04.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/link/04.t 211352 2010-08-15 21:24:17Z pjd $
desc="link returns ENOENT if a component of either path prefix does not exist"
diff --git a/tools/regression/pjdfstest/tests/link/05.t b/contrib/pjdfstest/tests/link/05.t
index ee63ef6..c6f55fa 100644
--- a/tools/regression/pjdfstest/tests/link/05.t
+++ b/contrib/pjdfstest/tests/link/05.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/link/05.t 211352 2010-08-15 21:24:17Z pjd $
desc="link returns EMLINK if the link count of the file named by name1 would exceed 32767"
@@ -15,9 +15,9 @@ n1=`namegen`
n2=`namegen`
expect 0 mkdir ${n0} 0755
-n=`mdconfig -a -n -t malloc -s 1m`
-newfs -i 1 /dev/md${n} >/dev/null
-mount /dev/md${n} ${n0}
+n=`mdconfig -a -n -t malloc -s 1m` || exit
+newfs -i 1 /dev/md${n} >/dev/null || exit
+mount /dev/md${n} ${n0} || exit
expect 0 create ${n0}/${n1} 0644
i=1
while :; do
@@ -32,5 +32,5 @@ test_check $i -eq 32767
expect EMLINK link ${n0}/${n1} ${n0}/${n2}
umount /dev/md${n}
-mdconfig -d -u ${n}
+mdconfig -d -u ${n} || exit
expect 0 rmdir ${n0}
diff --git a/tools/regression/pjdfstest/tests/link/06.t b/contrib/pjdfstest/tests/link/06.t
index 3ce0919..73ab01e 100644
--- a/tools/regression/pjdfstest/tests/link/06.t
+++ b/contrib/pjdfstest/tests/link/06.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/link/06.t 211352 2010-08-15 21:24:17Z pjd $
desc="link returns EACCES when a component of either path prefix denies search permission"
diff --git a/tools/regression/pjdfstest/tests/link/07.t b/contrib/pjdfstest/tests/link/07.t
index f9d35e7..68495dd 100644
--- a/tools/regression/pjdfstest/tests/link/07.t
+++ b/contrib/pjdfstest/tests/link/07.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/link/07.t 211352 2010-08-15 21:24:17Z pjd $
desc="link returns EACCES when the requested link requires writing in a directory with a mode that denies write permission"
diff --git a/tools/regression/pjdfstest/tests/link/08.t b/contrib/pjdfstest/tests/link/08.t
index f9d9445..f4599d5 100644
--- a/tools/regression/pjdfstest/tests/link/08.t
+++ b/contrib/pjdfstest/tests/link/08.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/link/08.t 211352 2010-08-15 21:24:17Z pjd $
desc="link returns ELOOP if too many symbolic links were encountered in translating one of the pathnames"
diff --git a/tools/regression/pjdfstest/tests/link/09.t b/contrib/pjdfstest/tests/link/09.t
index 224395f..5f89655 100644
--- a/tools/regression/pjdfstest/tests/link/09.t
+++ b/contrib/pjdfstest/tests/link/09.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/link/09.t 211352 2010-08-15 21:24:17Z pjd $
desc="link returns ENOENT if the source file does not exist"
diff --git a/tools/regression/pjdfstest/tests/link/10.t b/contrib/pjdfstest/tests/link/10.t
index 725a020..03ebbd2 100644
--- a/tools/regression/pjdfstest/tests/link/10.t
+++ b/contrib/pjdfstest/tests/link/10.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/link/10.t 211474 2010-08-18 22:06:43Z pjd $
desc="link returns EEXIST if the destination file does exist"
diff --git a/tools/regression/pjdfstest/tests/link/11.t b/contrib/pjdfstest/tests/link/11.t
index cf31c9e..260342c 100644
--- a/tools/regression/pjdfstest/tests/link/11.t
+++ b/contrib/pjdfstest/tests/link/11.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/link/11.t 211352 2010-08-15 21:24:17Z pjd $
desc="link returns EPERM if the source file is a directory"
diff --git a/tools/regression/pjdfstest/tests/link/12.t b/contrib/pjdfstest/tests/link/12.t
index 8bf9510..a5408b6 100644
--- a/tools/regression/pjdfstest/tests/link/12.t
+++ b/contrib/pjdfstest/tests/link/12.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/link/12.t 211352 2010-08-15 21:24:17Z pjd $
desc="link returns EPERM if the source file has its immutable or append-only flag set"
diff --git a/tools/regression/pjdfstest/tests/link/13.t b/contrib/pjdfstest/tests/link/13.t
index 9b35a4b..2da8621 100644
--- a/tools/regression/pjdfstest/tests/link/13.t
+++ b/contrib/pjdfstest/tests/link/13.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/link/13.t 211352 2010-08-15 21:24:17Z pjd $
desc="link returns EPERM if the parent directory of the destination file has its immutable flag set"
diff --git a/tools/regression/pjdfstest/tests/link/14.t b/contrib/pjdfstest/tests/link/14.t
index 4eb5a56..aa587e5 100644
--- a/tools/regression/pjdfstest/tests/link/14.t
+++ b/contrib/pjdfstest/tests/link/14.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/link/14.t 211352 2010-08-15 21:24:17Z pjd $
desc="link returns EXDEV if the source and the destination files are on different file systems"
@@ -15,9 +15,9 @@ n1=`namegen`
n2=`namegen`
expect 0 mkdir ${n0} 0755
-n=`mdconfig -a -n -t malloc -s 1m`
-newfs /dev/md${n} >/dev/null
-mount /dev/md${n} ${n0}
+n=`mdconfig -a -n -t malloc -s 1m` || exit
+newfs /dev/md${n} >/dev/null || exit
+mount /dev/md${n} ${n0} || exit
expect 0 create ${n0}/${n1} 0644
expect EXDEV link ${n0}/${n1} ${n2}
expect 0 unlink ${n0}/${n1}
@@ -25,5 +25,5 @@ expect 0 create ${n1} 0644
expect EXDEV link ${n1} ${n0}/${n2}
expect 0 unlink ${n1}
umount /dev/md${n}
-mdconfig -d -u ${n}
+mdconfig -d -u ${n} || exit
expect 0 rmdir ${n0}
diff --git a/tools/regression/pjdfstest/tests/link/15.t b/contrib/pjdfstest/tests/link/15.t
index eea1844..a740126 100644
--- a/tools/regression/pjdfstest/tests/link/15.t
+++ b/contrib/pjdfstest/tests/link/15.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/link/15.t 211352 2010-08-15 21:24:17Z pjd $
desc="link returns ENOSPC if the directory in which the entry for the new link is being placed cannot be extended because there is no space left on the file system containing the directory"
@@ -15,9 +15,9 @@ n1=`namegen`
n2=`namegen`
expect 0 mkdir ${n0} 0755
-n=`mdconfig -a -n -t malloc -s 256k`
-newfs /dev/md${n} >/dev/null
-mount /dev/md${n} ${n0}
+n=`mdconfig -a -n -t malloc -s 512k` || exit
+newfs /dev/md${n} >/dev/null || exit
+mount /dev/md${n} ${n0} || exit
expect 0 create ${n0}/${n1} 0644
i=0
while :; do
@@ -29,5 +29,5 @@ while :; do
done
expect ENOSPC link ${n0}/${n1} ${n0}/${n2}
umount /dev/md${n}
-mdconfig -d -u ${n}
+mdconfig -d -u ${n} || exit
expect 0 rmdir ${n0}
diff --git a/tools/regression/pjdfstest/tests/link/16.t b/contrib/pjdfstest/tests/link/16.t
index df04521..2d67f30 100644
--- a/tools/regression/pjdfstest/tests/link/16.t
+++ b/contrib/pjdfstest/tests/link/16.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/link/16.t 211352 2010-08-15 21:24:17Z pjd $
desc="link returns EROFS if the requested link requires writing in a directory on a read-only file system"
@@ -15,9 +15,9 @@ n1=`namegen`
n2=`namegen`
expect 0 mkdir ${n0} 0755
-n=`mdconfig -a -n -t malloc -s 1m`
-newfs /dev/md${n} >/dev/null
-mount /dev/md${n} ${n0}
+n=`mdconfig -a -n -t malloc -s 1m` || exit
+newfs /dev/md${n} >/dev/null || exit
+mount /dev/md${n} ${n0} || exit
expect 0 create ${n0}/${n1} 0644
expect 0 link ${n0}/${n1} ${n0}/${n2}
@@ -30,5 +30,5 @@ expect 0 unlink ${n0}/${n2}
expect 0 unlink ${n0}/${n1}
umount /dev/md${n}
-mdconfig -d -u ${n}
+mdconfig -d -u ${n} || exit
expect 0 rmdir ${n0}
diff --git a/tools/regression/pjdfstest/tests/link/17.t b/contrib/pjdfstest/tests/link/17.t
index cb56128..9b7e6fc 100644
--- a/tools/regression/pjdfstest/tests/link/17.t
+++ b/contrib/pjdfstest/tests/link/17.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/link/17.t 211352 2010-08-15 21:24:17Z pjd $
desc="link returns EFAULT if one of the pathnames specified is outside the process's allocated address space"
diff --git a/tools/regression/pjdfstest/tests/misc.sh b/contrib/pjdfstest/tests/misc.sh
index 8978b5f..8978b5f 100644..100755
--- a/tools/regression/pjdfstest/tests/misc.sh
+++ b/contrib/pjdfstest/tests/misc.sh
diff --git a/tools/regression/pjdfstest/tests/mkdir/00.t b/contrib/pjdfstest/tests/mkdir/00.t
index d640de9..fa1cbc1 100644
--- a/tools/regression/pjdfstest/tests/mkdir/00.t
+++ b/contrib/pjdfstest/tests/mkdir/00.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mkdir/00.t 211352 2010-08-15 21:24:17Z pjd $
desc="mkdir creates directories"
diff --git a/tools/regression/pjdfstest/tests/mkdir/01.t b/contrib/pjdfstest/tests/mkdir/01.t
index c1de087..c33ce1f 100644
--- a/tools/regression/pjdfstest/tests/mkdir/01.t
+++ b/contrib/pjdfstest/tests/mkdir/01.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mkdir/01.t 211474 2010-08-18 22:06:43Z pjd $
desc="mkdir returns ENOTDIR if a component of the path prefix is not a directory"
diff --git a/tools/regression/pjdfstest/tests/mkdir/02.t b/contrib/pjdfstest/tests/mkdir/02.t
index edb103d..e877f20 100644
--- a/tools/regression/pjdfstest/tests/mkdir/02.t
+++ b/contrib/pjdfstest/tests/mkdir/02.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mkdir/02.t 211352 2010-08-15 21:24:17Z pjd $
desc="mkdir returns ENAMETOOLONG if a component of a pathname exceeded {NAME_MAX} characters"
diff --git a/tools/regression/pjdfstest/tests/mkdir/03.t b/contrib/pjdfstest/tests/mkdir/03.t
index aa3b44c..57ddd20 100644
--- a/tools/regression/pjdfstest/tests/mkdir/03.t
+++ b/contrib/pjdfstest/tests/mkdir/03.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mkdir/03.t 211352 2010-08-15 21:24:17Z pjd $
desc="mkdir returns ENAMETOOLONG if an entire path name exceeded {PATH_MAX} characters"
diff --git a/tools/regression/pjdfstest/tests/mkdir/04.t b/contrib/pjdfstest/tests/mkdir/04.t
index cd65819..0917ef1 100644
--- a/tools/regression/pjdfstest/tests/mkdir/04.t
+++ b/contrib/pjdfstest/tests/mkdir/04.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mkdir/04.t 211352 2010-08-15 21:24:17Z pjd $
desc="mkdir returns ENOENT if a component of the path prefix does not exist"
diff --git a/tools/regression/pjdfstest/tests/mkdir/05.t b/contrib/pjdfstest/tests/mkdir/05.t
index 7e97d9b..de351ca 100644
--- a/tools/regression/pjdfstest/tests/mkdir/05.t
+++ b/contrib/pjdfstest/tests/mkdir/05.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mkdir/05.t 211352 2010-08-15 21:24:17Z pjd $
desc="mkdir returns EACCES when search permission is denied for a component of the path prefix"
diff --git a/tools/regression/pjdfstest/tests/mkdir/06.t b/contrib/pjdfstest/tests/mkdir/06.t
index 79aa539..2d2b8c2 100644
--- a/tools/regression/pjdfstest/tests/mkdir/06.t
+++ b/contrib/pjdfstest/tests/mkdir/06.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mkdir/06.t 211352 2010-08-15 21:24:17Z pjd $
desc="mkdir returns EACCES when write permission is denied on the parent directory of the directory to be created"
diff --git a/tools/regression/pjdfstest/tests/mkdir/07.t b/contrib/pjdfstest/tests/mkdir/07.t
index dbb00df..72ac2b6 100644
--- a/tools/regression/pjdfstest/tests/mkdir/07.t
+++ b/contrib/pjdfstest/tests/mkdir/07.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mkdir/07.t 211352 2010-08-15 21:24:17Z pjd $
desc="mkdir returns ELOOP if too many symbolic links were encountered in translating the pathname"
diff --git a/tools/regression/pjdfstest/tests/mkdir/08.t b/contrib/pjdfstest/tests/mkdir/08.t
index ed6d92e..366f223 100644
--- a/tools/regression/pjdfstest/tests/mkdir/08.t
+++ b/contrib/pjdfstest/tests/mkdir/08.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mkdir/08.t 211352 2010-08-15 21:24:17Z pjd $
desc="mkdir returns EPERM if the parent directory of the directory to be created has its immutable flag set"
diff --git a/tools/regression/pjdfstest/tests/mkdir/09.t b/contrib/pjdfstest/tests/mkdir/09.t
index ce4bc9d..2035b31 100644
--- a/tools/regression/pjdfstest/tests/mkdir/09.t
+++ b/contrib/pjdfstest/tests/mkdir/09.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mkdir/09.t 211352 2010-08-15 21:24:17Z pjd $
desc="mkdir returns EROFS if the named file resides on a read-only file system"
@@ -14,9 +14,9 @@ n0=`namegen`
n1=`namegen`
expect 0 mkdir ${n0} 0755
-n=`mdconfig -a -n -t malloc -s 1m`
-newfs /dev/md${n} >/dev/null
-mount /dev/md${n} ${n0}
+n=`mdconfig -a -n -t malloc -s 1m` || exit
+newfs /dev/md${n} >/dev/null || exit
+mount /dev/md${n} ${n0} || exit
expect 0 mkdir ${n0}/${n1} 0755
expect 0 rmdir ${n0}/${n1}
mount -ur /dev/md${n}
@@ -25,5 +25,5 @@ mount -uw /dev/md${n}
expect 0 mkdir ${n0}/${n1} 0755
expect 0 rmdir ${n0}/${n1}
umount /dev/md${n}
-mdconfig -d -u ${n}
+mdconfig -d -u ${n} || exit
expect 0 rmdir ${n0}
diff --git a/tools/regression/pjdfstest/tests/mkdir/10.t b/contrib/pjdfstest/tests/mkdir/10.t
index f64b8fd..732dcb8 100644
--- a/tools/regression/pjdfstest/tests/mkdir/10.t
+++ b/contrib/pjdfstest/tests/mkdir/10.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mkdir/10.t 211352 2010-08-15 21:24:17Z pjd $
desc="mkdir returns EEXIST if the named file exists"
diff --git a/tools/regression/pjdfstest/tests/mkdir/11.t b/contrib/pjdfstest/tests/mkdir/11.t
index 3943e61..a0c9055 100644
--- a/tools/regression/pjdfstest/tests/mkdir/11.t
+++ b/contrib/pjdfstest/tests/mkdir/11.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mkdir/11.t 211352 2010-08-15 21:24:17Z pjd $
desc="mkdir returns ENOSPC if there are no free inodes on the file system on which the directory is being created"
@@ -14,9 +14,9 @@ n0=`namegen`
n1=`namegen`
expect 0 mkdir ${n0} 0755
-n=`mdconfig -a -n -t malloc -s 256k`
-newfs /dev/md${n} >/dev/null
-mount /dev/md${n} ${n0}
+n=`mdconfig -a -n -t malloc -s 512k` || exit
+newfs /dev/md${n} >/dev/null || exit
+mount /dev/md${n} ${n0} || exit
i=0
while :; do
mkdir ${n0}/${i} >/dev/null 2>&1
@@ -27,5 +27,5 @@ while :; do
done
expect ENOSPC mkdir ${n0}/${n1} 0755
umount /dev/md${n}
-mdconfig -d -u ${n}
+mdconfig -d -u ${n} || exit
expect 0 rmdir ${n0}
diff --git a/tools/regression/pjdfstest/tests/mkdir/12.t b/contrib/pjdfstest/tests/mkdir/12.t
index af322c4..7c27f74 100644
--- a/tools/regression/pjdfstest/tests/mkdir/12.t
+++ b/contrib/pjdfstest/tests/mkdir/12.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mkdir/12.t 211352 2010-08-15 21:24:17Z pjd $
desc="mkdir returns EFAULT if the path argument points outside the process's allocated address space"
diff --git a/tools/regression/pjdfstest/tests/mkfifo/00.t b/contrib/pjdfstest/tests/mkfifo/00.t
index eda7b17..ad88e28 100644
--- a/tools/regression/pjdfstest/tests/mkfifo/00.t
+++ b/contrib/pjdfstest/tests/mkfifo/00.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mkfifo/00.t 211352 2010-08-15 21:24:17Z pjd $
desc="mkfifo creates fifo files"
diff --git a/tools/regression/pjdfstest/tests/mkfifo/01.t b/contrib/pjdfstest/tests/mkfifo/01.t
index 1c6193b..fae5c23 100644
--- a/tools/regression/pjdfstest/tests/mkfifo/01.t
+++ b/contrib/pjdfstest/tests/mkfifo/01.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mkfifo/01.t 211474 2010-08-18 22:06:43Z pjd $
desc="mkfifo returns ENOTDIR if a component of the path prefix is not a directory"
diff --git a/tools/regression/pjdfstest/tests/mkfifo/02.t b/contrib/pjdfstest/tests/mkfifo/02.t
index 8589e9d..e51bcd5 100644
--- a/tools/regression/pjdfstest/tests/mkfifo/02.t
+++ b/contrib/pjdfstest/tests/mkfifo/02.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mkfifo/02.t 211352 2010-08-15 21:24:17Z pjd $
desc="mkfifo returns ENAMETOOLONG if a component of a pathname exceeded {NAME_MAX} characters"
diff --git a/tools/regression/pjdfstest/tests/mkfifo/03.t b/contrib/pjdfstest/tests/mkfifo/03.t
index caf529f..0626529 100644
--- a/tools/regression/pjdfstest/tests/mkfifo/03.t
+++ b/contrib/pjdfstest/tests/mkfifo/03.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mkfifo/03.t 211352 2010-08-15 21:24:17Z pjd $
desc="mkfifo returns ENAMETOOLONG if an entire path name exceeded {PATH_MAX} characters"
diff --git a/tools/regression/pjdfstest/tests/mkfifo/04.t b/contrib/pjdfstest/tests/mkfifo/04.t
index d9ad951..9810158 100644
--- a/tools/regression/pjdfstest/tests/mkfifo/04.t
+++ b/contrib/pjdfstest/tests/mkfifo/04.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mkfifo/04.t 211352 2010-08-15 21:24:17Z pjd $
desc="mkfifo returns ENOENT if a component of the path prefix does not exist"
diff --git a/tools/regression/pjdfstest/tests/mkfifo/05.t b/contrib/pjdfstest/tests/mkfifo/05.t
index d93d568..a9510e2 100644
--- a/tools/regression/pjdfstest/tests/mkfifo/05.t
+++ b/contrib/pjdfstest/tests/mkfifo/05.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mkfifo/05.t 211352 2010-08-15 21:24:17Z pjd $
desc="mkfifo returns EACCES when search permission is denied for a component of the path prefix"
diff --git a/tools/regression/pjdfstest/tests/mkfifo/06.t b/contrib/pjdfstest/tests/mkfifo/06.t
index 47f199b..a1fa761 100644
--- a/tools/regression/pjdfstest/tests/mkfifo/06.t
+++ b/contrib/pjdfstest/tests/mkfifo/06.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mkfifo/06.t 211352 2010-08-15 21:24:17Z pjd $
desc="mkfifo returns EACCES when write permission is denied on the parent directory of the file to be created"
diff --git a/tools/regression/pjdfstest/tests/mkfifo/07.t b/contrib/pjdfstest/tests/mkfifo/07.t
index 44271b6..0ba1ac4 100644
--- a/tools/regression/pjdfstest/tests/mkfifo/07.t
+++ b/contrib/pjdfstest/tests/mkfifo/07.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mkfifo/07.t 211352 2010-08-15 21:24:17Z pjd $
desc="mkfifo returns ELOOP if too many symbolic links were encountered in translating the pathname"
diff --git a/tools/regression/pjdfstest/tests/mkfifo/08.t b/contrib/pjdfstest/tests/mkfifo/08.t
index 0bdf430..8e1bd27 100644
--- a/tools/regression/pjdfstest/tests/mkfifo/08.t
+++ b/contrib/pjdfstest/tests/mkfifo/08.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mkfifo/08.t 211352 2010-08-15 21:24:17Z pjd $
desc="mkfifo returns EROFS if the named file resides on a read-only file system"
@@ -14,9 +14,9 @@ n0=`namegen`
n1=`namegen`
expect 0 mkdir ${n0} 0755
-n=`mdconfig -a -n -t malloc -s 1m`
-newfs /dev/md${n} >/dev/null
-mount /dev/md${n} ${n0}
+n=`mdconfig -a -n -t malloc -s 1m` || exit
+newfs /dev/md${n} >/dev/null || exit
+mount /dev/md${n} ${n0} || exit
expect 0 mkfifo ${n0}/${n1} 0644
expect 0 unlink ${n0}/${n1}
mount -ur /dev/md${n}
@@ -25,5 +25,5 @@ mount -uw /dev/md${n}
expect 0 mkfifo ${n0}/${n1} 0644
expect 0 unlink ${n0}/${n1}
umount /dev/md${n}
-mdconfig -d -u ${n}
+mdconfig -d -u ${n} || exit
expect 0 rmdir ${n0}
diff --git a/tools/regression/pjdfstest/tests/mkfifo/09.t b/contrib/pjdfstest/tests/mkfifo/09.t
index 6b2015e..15af5d1 100644
--- a/tools/regression/pjdfstest/tests/mkfifo/09.t
+++ b/contrib/pjdfstest/tests/mkfifo/09.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mkfifo/09.t 211474 2010-08-18 22:06:43Z pjd $
desc="mkfifo returns EEXIST if the named file exists"
diff --git a/tools/regression/pjdfstest/tests/mkfifo/10.t b/contrib/pjdfstest/tests/mkfifo/10.t
index e6aec44..4c8bcab 100644
--- a/tools/regression/pjdfstest/tests/mkfifo/10.t
+++ b/contrib/pjdfstest/tests/mkfifo/10.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mkfifo/10.t 211352 2010-08-15 21:24:17Z pjd $
desc="mkfifo returns EPERM if the parent directory of the file to be created has its immutable flag set"
diff --git a/tools/regression/pjdfstest/tests/mkfifo/11.t b/contrib/pjdfstest/tests/mkfifo/11.t
index 261a8a7..8b2396f 100644
--- a/tools/regression/pjdfstest/tests/mkfifo/11.t
+++ b/contrib/pjdfstest/tests/mkfifo/11.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mkfifo/11.t 211352 2010-08-15 21:24:17Z pjd $
desc="mkfifo returns ENOSPC if there are no free inodes on the file system on which the file is being created"
@@ -14,9 +14,9 @@ n0=`namegen`
n1=`namegen`
expect 0 mkdir ${n0} 0755
-n=`mdconfig -a -n -t malloc -s 256k`
-newfs /dev/md${n} >/dev/null
-mount /dev/md${n} ${n0}
+n=`mdconfig -a -n -t malloc -s 512k` || exit
+newfs /dev/md${n} >/dev/null || exit
+mount /dev/md${n} ${n0} || exit
i=0
while :; do
mkfifo ${n0}/${i} >/dev/null 2>&1
@@ -27,5 +27,5 @@ while :; do
done
expect ENOSPC mkfifo ${n0}/${n1} 0644
umount /dev/md${n}
-mdconfig -d -u ${n}
+mdconfig -d -u ${n} || exit
expect 0 rmdir ${n0}
diff --git a/tools/regression/pjdfstest/tests/mkfifo/12.t b/contrib/pjdfstest/tests/mkfifo/12.t
index 40c1455..ad044b9 100644
--- a/tools/regression/pjdfstest/tests/mkfifo/12.t
+++ b/contrib/pjdfstest/tests/mkfifo/12.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mkfifo/12.t 211352 2010-08-15 21:24:17Z pjd $
desc="mkfifo returns EFAULT if the path argument points outside the process's allocated address space"
diff --git a/tools/regression/pjdfstest/tests/mknod/00.t b/contrib/pjdfstest/tests/mknod/00.t
index 13f017d..67f4046 100644
--- a/tools/regression/pjdfstest/tests/mknod/00.t
+++ b/contrib/pjdfstest/tests/mknod/00.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mknod/00.t 211352 2010-08-15 21:24:17Z pjd $
desc="mknod creates fifo files"
diff --git a/tools/regression/pjdfstest/tests/mknod/01.t b/contrib/pjdfstest/tests/mknod/01.t
index bc2b658..84a0a97 100644
--- a/tools/regression/pjdfstest/tests/mknod/01.t
+++ b/contrib/pjdfstest/tests/mknod/01.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mknod/01.t 211474 2010-08-18 22:06:43Z pjd $
desc="mknod returns ENOTDIR if a component of the path prefix is not a directory"
diff --git a/tools/regression/pjdfstest/tests/mknod/02.t b/contrib/pjdfstest/tests/mknod/02.t
index 99e607f..4e864fe 100644
--- a/tools/regression/pjdfstest/tests/mknod/02.t
+++ b/contrib/pjdfstest/tests/mknod/02.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mknod/02.t 211352 2010-08-15 21:24:17Z pjd $
desc="mknod returns ENAMETOOLONG if a component of a pathname exceeded {NAME_MAX} characters"
diff --git a/tools/regression/pjdfstest/tests/mknod/03.t b/contrib/pjdfstest/tests/mknod/03.t
index 10776c7..d5c572c 100644
--- a/tools/regression/pjdfstest/tests/mknod/03.t
+++ b/contrib/pjdfstest/tests/mknod/03.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mknod/03.t 211352 2010-08-15 21:24:17Z pjd $
desc="mknod returns ENAMETOOLONG if an entire path name exceeded {PATH_MAX} characters"
diff --git a/tools/regression/pjdfstest/tests/mknod/04.t b/contrib/pjdfstest/tests/mknod/04.t
index 6c30318..4b80208 100644
--- a/tools/regression/pjdfstest/tests/mknod/04.t
+++ b/contrib/pjdfstest/tests/mknod/04.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mknod/04.t 211352 2010-08-15 21:24:17Z pjd $
desc="mkfifo returns ENOENT if a component of the path prefix does not exist"
diff --git a/tools/regression/pjdfstest/tests/mknod/05.t b/contrib/pjdfstest/tests/mknod/05.t
index 8003541..deafda6 100644
--- a/tools/regression/pjdfstest/tests/mknod/05.t
+++ b/contrib/pjdfstest/tests/mknod/05.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mknod/05.t 211352 2010-08-15 21:24:17Z pjd $
desc="mknod returns EACCES when search permission is denied for a component of the path prefix"
diff --git a/tools/regression/pjdfstest/tests/mknod/06.t b/contrib/pjdfstest/tests/mknod/06.t
index 180cb9a..da7a549 100644
--- a/tools/regression/pjdfstest/tests/mknod/06.t
+++ b/contrib/pjdfstest/tests/mknod/06.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mknod/06.t 211352 2010-08-15 21:24:17Z pjd $
desc="mknod returns EACCES when write permission is denied on the parent directory of the file to be created"
diff --git a/tools/regression/pjdfstest/tests/mknod/07.t b/contrib/pjdfstest/tests/mknod/07.t
index 855d990..1b39cc7 100644
--- a/tools/regression/pjdfstest/tests/mknod/07.t
+++ b/contrib/pjdfstest/tests/mknod/07.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mknod/07.t 211352 2010-08-15 21:24:17Z pjd $
desc="mknod returns ELOOP if too many symbolic links were encountered in translating the pathname"
diff --git a/tools/regression/pjdfstest/tests/mknod/08.t b/contrib/pjdfstest/tests/mknod/08.t
index 47d0010..a805562 100644
--- a/tools/regression/pjdfstest/tests/mknod/08.t
+++ b/contrib/pjdfstest/tests/mknod/08.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mknod/08.t 211474 2010-08-18 22:06:43Z pjd $
desc="mknod returns EEXIST if the named file exists"
diff --git a/tools/regression/pjdfstest/tests/mknod/09.t b/contrib/pjdfstest/tests/mknod/09.t
index a12a02c..00c2a2f 100644
--- a/tools/regression/pjdfstest/tests/mknod/09.t
+++ b/contrib/pjdfstest/tests/mknod/09.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mknod/09.t 211352 2010-08-15 21:24:17Z pjd $
desc="mknod returns EPERM if the parent directory of the file to be created has its immutable flag set"
diff --git a/tools/regression/pjdfstest/tests/mknod/10.t b/contrib/pjdfstest/tests/mknod/10.t
index fa6730f..5bf18d3 100644
--- a/tools/regression/pjdfstest/tests/mknod/10.t
+++ b/contrib/pjdfstest/tests/mknod/10.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mknod/10.t 211352 2010-08-15 21:24:17Z pjd $
desc="mknod returns EFAULT if the path argument points outside the process's allocated address space"
diff --git a/tools/regression/pjdfstest/tests/mknod/11.t b/contrib/pjdfstest/tests/mknod/11.t
index da46cb9..309f716 100644
--- a/tools/regression/pjdfstest/tests/mknod/11.t
+++ b/contrib/pjdfstest/tests/mknod/11.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/mknod/11.t 211352 2010-08-15 21:24:17Z pjd $
desc="mknod creates device files"
diff --git a/tools/regression/pjdfstest/tests/open/00.t b/contrib/pjdfstest/tests/open/00.t
index caa24f0..cf11a92 100644
--- a/tools/regression/pjdfstest/tests/open/00.t
+++ b/contrib/pjdfstest/tests/open/00.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/open/00.t 211352 2010-08-15 21:24:17Z pjd $
desc="open opens (and eventually creates) a file"
diff --git a/tools/regression/pjdfstest/tests/open/01.t b/contrib/pjdfstest/tests/open/01.t
index 6dfc6f5..df17590 100644
--- a/tools/regression/pjdfstest/tests/open/01.t
+++ b/contrib/pjdfstest/tests/open/01.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/open/01.t 211474 2010-08-18 22:06:43Z pjd $
desc="open returns ENOTDIR if a component of the path prefix is not a directory"
diff --git a/tools/regression/pjdfstest/tests/open/02.t b/contrib/pjdfstest/tests/open/02.t
index 44ca1d7..adb3bb0 100644
--- a/tools/regression/pjdfstest/tests/open/02.t
+++ b/contrib/pjdfstest/tests/open/02.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/open/02.t 211352 2010-08-15 21:24:17Z pjd $
desc="open returns ENAMETOOLONG if a component of a pathname exceeded {NAME_MAX} characters"
diff --git a/tools/regression/pjdfstest/tests/open/03.t b/contrib/pjdfstest/tests/open/03.t
index c398be1..89e67bb 100644
--- a/tools/regression/pjdfstest/tests/open/03.t
+++ b/contrib/pjdfstest/tests/open/03.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/open/03.t 211352 2010-08-15 21:24:17Z pjd $
desc="open returns ENAMETOOLONG if an entire path name exceeded ${PATH_MAX} characters"
diff --git a/tools/regression/pjdfstest/tests/open/04.t b/contrib/pjdfstest/tests/open/04.t
index 1ce99cb..84b0441 100644
--- a/tools/regression/pjdfstest/tests/open/04.t
+++ b/contrib/pjdfstest/tests/open/04.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/open/04.t 211352 2010-08-15 21:24:17Z pjd $
desc="open returns ENOENT if a component of the path name that must exist does not exist or O_CREAT is not set and the named file does not exist"
diff --git a/tools/regression/pjdfstest/tests/open/05.t b/contrib/pjdfstest/tests/open/05.t
index 25ad7da..1b69c61 100644
--- a/tools/regression/pjdfstest/tests/open/05.t
+++ b/contrib/pjdfstest/tests/open/05.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/open/05.t 211352 2010-08-15 21:24:17Z pjd $
desc="open returns EACCES when search permission is denied for a component of the path prefix"
diff --git a/tools/regression/pjdfstest/tests/open/06.t b/contrib/pjdfstest/tests/open/06.t
index 007e24a..b33e640 100644
--- a/tools/regression/pjdfstest/tests/open/06.t
+++ b/contrib/pjdfstest/tests/open/06.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/open/06.t 211352 2010-08-15 21:24:17Z pjd $
desc="open returns EACCES when the required permissions (for reading and/or writing) are denied for the given flags"
diff --git a/tools/regression/pjdfstest/tests/open/07.t b/contrib/pjdfstest/tests/open/07.t
index a41d193..edc4be1 100644
--- a/tools/regression/pjdfstest/tests/open/07.t
+++ b/contrib/pjdfstest/tests/open/07.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/open/07.t 211352 2010-08-15 21:24:17Z pjd $
desc="open returns EACCES when O_TRUNC is specified and write permission is denied"
diff --git a/tools/regression/pjdfstest/tests/open/08.t b/contrib/pjdfstest/tests/open/08.t
index 22ea29b..f47ff87 100644
--- a/tools/regression/pjdfstest/tests/open/08.t
+++ b/contrib/pjdfstest/tests/open/08.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/open/08.t 211352 2010-08-15 21:24:17Z pjd $
desc="open returns EACCES when O_CREAT is specified, the file does not exist, and the directory in which it is to be created does not permit writing"
diff --git a/tools/regression/pjdfstest/tests/open/09.t b/contrib/pjdfstest/tests/open/09.t
index 106e36f..b76c70d 100644
--- a/tools/regression/pjdfstest/tests/open/09.t
+++ b/contrib/pjdfstest/tests/open/09.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/open/09.t 211352 2010-08-15 21:24:17Z pjd $
desc="O_CREAT is specified, the file does not exist, and the directory in which it is to be created has its immutable flag set"
diff --git a/tools/regression/pjdfstest/tests/open/10.t b/contrib/pjdfstest/tests/open/10.t
index 2cc943f..bd6fdd2 100644
--- a/tools/regression/pjdfstest/tests/open/10.t
+++ b/contrib/pjdfstest/tests/open/10.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/open/10.t 211352 2010-08-15 21:24:17Z pjd $
desc="open returns EPERM when the named file has its immutable flag set and the file is to be modified"
diff --git a/tools/regression/pjdfstest/tests/open/11.t b/contrib/pjdfstest/tests/open/11.t
index c68bb25..e4a3a2d 100644
--- a/tools/regression/pjdfstest/tests/open/11.t
+++ b/contrib/pjdfstest/tests/open/11.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/open/11.t 211352 2010-08-15 21:24:17Z pjd $
desc="open returns EPERM when the named file has its append-only flag set, the file is to be modified, and O_TRUNC is specified or O_APPEND is not specified"
diff --git a/tools/regression/pjdfstest/tests/open/12.t b/contrib/pjdfstest/tests/open/12.t
index 2726dc1..d38309d 100644
--- a/tools/regression/pjdfstest/tests/open/12.t
+++ b/contrib/pjdfstest/tests/open/12.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/open/12.t 211352 2010-08-15 21:24:17Z pjd $
desc="open returns ELOOP if too many symbolic links were encountered in translating the pathname"
diff --git a/tools/regression/pjdfstest/tests/open/13.t b/contrib/pjdfstest/tests/open/13.t
index 77bc4c2..64bb0b8 100644
--- a/tools/regression/pjdfstest/tests/open/13.t
+++ b/contrib/pjdfstest/tests/open/13.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/open/13.t 211352 2010-08-15 21:24:17Z pjd $
desc="open returns EISDIR when trying to open a directory for writing"
diff --git a/tools/regression/pjdfstest/tests/open/14.t b/contrib/pjdfstest/tests/open/14.t
index 3d81f3e..8d90065 100644
--- a/tools/regression/pjdfstest/tests/open/14.t
+++ b/contrib/pjdfstest/tests/open/14.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/open/14.t 211352 2010-08-15 21:24:17Z pjd $
desc="open returns EROFS if the named file resides on a read-only file system, and the file is to be modified"
@@ -14,9 +14,9 @@ n0=`namegen`
n1=`namegen`
expect 0 mkdir ${n0} 0755
-n=`mdconfig -a -n -t malloc -s 1m`
-newfs /dev/md${n} >/dev/null
-mount /dev/md${n} ${n0}
+n=`mdconfig -a -n -t malloc -s 1m` || exit
+newfs /dev/md${n} >/dev/null || exit
+mount /dev/md${n} ${n0} || exit
expect 0 create ${n0}/${n1} 0644
expect 0 open ${n0}/${n1} O_WRONLY
expect 0 open ${n0}/${n1} O_RDWR
@@ -28,5 +28,5 @@ expect EROFS open ${n0}/${n1} O_RDONLY,O_TRUNC
mount -uw /dev/md${n}
expect 0 unlink ${n0}/${n1}
umount /dev/md${n}
-mdconfig -d -u ${n}
+mdconfig -d -u ${n} || exit
expect 0 rmdir ${n0}
diff --git a/tools/regression/pjdfstest/tests/open/15.t b/contrib/pjdfstest/tests/open/15.t
index d90877b..a8230d8 100644
--- a/tools/regression/pjdfstest/tests/open/15.t
+++ b/contrib/pjdfstest/tests/open/15.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/open/15.t 211352 2010-08-15 21:24:17Z pjd $
desc="open returns EROFS when O_CREAT is specified and the named file would reside on a read-only file system"
@@ -14,14 +14,14 @@ n0=`namegen`
n1=`namegen`
expect 0 mkdir ${n0} 0755
-n=`mdconfig -a -n -t malloc -s 1m`
-newfs /dev/md${n} >/dev/null
-mount /dev/md${n} ${n0}
+n=`mdconfig -a -n -t malloc -s 1m` || exit
+newfs /dev/md${n} >/dev/null || exit
+mount /dev/md${n} ${n0} || exit
expect 0 open ${n0}/${n1} O_RDONLY,O_CREAT 0644
expect 0 unlink ${n0}/${n1}
mount -ur /dev/md${n}
expect EROFS open ${n0}/${n1} O_RDONLY,O_CREAT 0644
mount -uw /dev/md${n}
umount /dev/md${n}
-mdconfig -d -u ${n}
+mdconfig -d -u ${n} || exit
expect 0 rmdir ${n0}
diff --git a/contrib/pjdfstest/tests/open/16.t b/contrib/pjdfstest/tests/open/16.t
new file mode 100644
index 0000000..7f796d6
--- /dev/null
+++ b/contrib/pjdfstest/tests/open/16.t
@@ -0,0 +1,27 @@
+#!/bin/sh
+# $FreeBSD: head/tools/regression/pjdfstest/tests/open/16.t 219621 2011-03-13 19:35:13Z pjd $
+
+dir=`dirname $0`
+. ${dir}/../misc.sh
+
+case "${os}" in
+Darwin|Linux)
+ error=ELOOP
+ ;;
+*)
+ error=EMLINK
+ ;;
+esac
+desc="open returns $error when O_NOFOLLOW was specified and the target is a symbolic link"
+
+echo "1..6"
+
+n0=`namegen`
+n1=`namegen`
+
+expect 0 symlink ${n0} ${n1}
+expect $error open ${n1} O_RDONLY,O_CREAT,O_NOFOLLOW 0644
+expect $error open ${n1} O_RDONLY,O_NOFOLLOW
+expect $error open ${n1} O_WRONLY,O_NOFOLLOW
+expect $error open ${n1} O_RDWR,O_NOFOLLOW
+expect 0 unlink ${n1}
diff --git a/tools/regression/pjdfstest/tests/open/17.t b/contrib/pjdfstest/tests/open/17.t
index 2224daf..e5888fc 100644
--- a/tools/regression/pjdfstest/tests/open/17.t
+++ b/contrib/pjdfstest/tests/open/17.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/open/17.t 211352 2010-08-15 21:24:17Z pjd $
desc="open returns ENXIO when O_NONBLOCK is set, the named file is a fifo, O_WRONLY is set, and no process has the file open for reading"
diff --git a/tools/regression/pjdfstest/tests/open/18.t b/contrib/pjdfstest/tests/open/18.t
index bd8eea4..6d0713b 100644
--- a/tools/regression/pjdfstest/tests/open/18.t
+++ b/contrib/pjdfstest/tests/open/18.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/open/18.t 211352 2010-08-15 21:24:17Z pjd $
desc="open returns EWOULDBLOCK when O_NONBLOCK and one of O_SHLOCK or O_EXLOCK is specified and the file is locked"
diff --git a/tools/regression/pjdfstest/tests/open/19.t b/contrib/pjdfstest/tests/open/19.t
index b1c3994..c9d98eb 100644
--- a/tools/regression/pjdfstest/tests/open/19.t
+++ b/contrib/pjdfstest/tests/open/19.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/open/19.t 211352 2010-08-15 21:24:17Z pjd $
desc="open returns ENOSPC when O_CREAT is specified, the file does not exist, and there are no free inodes on the file system on which the file is being created"
@@ -14,9 +14,9 @@ n0=`namegen`
n1=`namegen`
expect 0 mkdir ${n0} 0755
-n=`mdconfig -a -n -t malloc -s 256k`
-newfs /dev/md${n} >/dev/null
-mount /dev/md${n} ${n0}
+n=`mdconfig -a -n -t malloc -s 512k` || exit
+newfs /dev/md${n} >/dev/null || exit
+mount /dev/md${n} ${n0} || exit
i=0
while :; do
touch ${n0}/${i} >/dev/null 2>&1
@@ -27,5 +27,5 @@ while :; do
done
expect ENOSPC open ${n0}/${i} O_RDONLY,O_CREAT 0644
umount /dev/md${n}
-mdconfig -d -u ${n}
+mdconfig -d -u ${n} || exit
expect 0 rmdir ${n0}
diff --git a/tools/regression/pjdfstest/tests/open/20.t b/contrib/pjdfstest/tests/open/20.t
index 736ad72..de80b61 100644
--- a/tools/regression/pjdfstest/tests/open/20.t
+++ b/contrib/pjdfstest/tests/open/20.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/open/20.t 211352 2010-08-15 21:24:17Z pjd $
desc="open returns ETXTBSY when the file is a pure procedure (shared text) file that is being executed and the open() system call requests write access"
diff --git a/tools/regression/pjdfstest/tests/open/21.t b/contrib/pjdfstest/tests/open/21.t
index c43d7fd..4a2422c 100644
--- a/tools/regression/pjdfstest/tests/open/21.t
+++ b/contrib/pjdfstest/tests/open/21.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/open/21.t 211352 2010-08-15 21:24:17Z pjd $
desc="open returns EFAULT if the path argument points outside the process's allocated address space"
diff --git a/tools/regression/pjdfstest/tests/open/22.t b/contrib/pjdfstest/tests/open/22.t
index 464dae7..55d4b9b 100644
--- a/tools/regression/pjdfstest/tests/open/22.t
+++ b/contrib/pjdfstest/tests/open/22.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/open/22.t 211352 2010-08-15 21:24:17Z pjd $
desc="open returns EEXIST when O_CREAT and O_EXCL were specified and the file exists"
diff --git a/tools/regression/pjdfstest/tests/open/23.t b/contrib/pjdfstest/tests/open/23.t
index fc2c6b9..4728c18 100644
--- a/tools/regression/pjdfstest/tests/open/23.t
+++ b/contrib/pjdfstest/tests/open/23.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/open/23.t 211352 2010-08-15 21:24:17Z pjd $
desc="open may return EINVAL when an attempt was made to open a descriptor with an illegal combination of O_RDONLY, O_WRONLY, and O_RDWR"
diff --git a/tools/regression/pjdfstest/tests/open/24.t b/contrib/pjdfstest/tests/open/24.t
index d51d632..ca709f2 100644
--- a/tools/regression/pjdfstest/tests/open/24.t
+++ b/contrib/pjdfstest/tests/open/24.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/open/24.t 211352 2010-08-15 21:24:17Z pjd $
desc="open returns EOPNOTSUPP when trying to open UNIX domain socket"
diff --git a/tools/regression/pjdfstest/tests/rename/00.t b/contrib/pjdfstest/tests/rename/00.t
index 49f7609..2126a86 100644
--- a/tools/regression/pjdfstest/tests/rename/00.t
+++ b/contrib/pjdfstest/tests/rename/00.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rename/00.t 211352 2010-08-15 21:24:17Z pjd $
desc="rename changes file name"
diff --git a/tools/regression/pjdfstest/tests/rename/01.t b/contrib/pjdfstest/tests/rename/01.t
index 291216d..dbb9c06 100644
--- a/tools/regression/pjdfstest/tests/rename/01.t
+++ b/contrib/pjdfstest/tests/rename/01.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rename/01.t 211352 2010-08-15 21:24:17Z pjd $
desc="rename returns ENAMETOOLONG if a component of either pathname exceeded {NAME_MAX} characters"
diff --git a/tools/regression/pjdfstest/tests/rename/02.t b/contrib/pjdfstest/tests/rename/02.t
index 7557e89..23425ba 100644
--- a/tools/regression/pjdfstest/tests/rename/02.t
+++ b/contrib/pjdfstest/tests/rename/02.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rename/02.t 211352 2010-08-15 21:24:17Z pjd $
desc="rename returns ENAMETOOLONG if an entire length of either path name exceeded {PATH_MAX} characters"
diff --git a/tools/regression/pjdfstest/tests/rename/03.t b/contrib/pjdfstest/tests/rename/03.t
index 8404dbe..fb1d16f 100644
--- a/tools/regression/pjdfstest/tests/rename/03.t
+++ b/contrib/pjdfstest/tests/rename/03.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rename/03.t 211352 2010-08-15 21:24:17Z pjd $
desc="rename returns ENOENT if a component of the 'from' path does not exist, or a path prefix of 'to' does not exist"
diff --git a/tools/regression/pjdfstest/tests/rename/04.t b/contrib/pjdfstest/tests/rename/04.t
index af3801f..19d1791 100644
--- a/tools/regression/pjdfstest/tests/rename/04.t
+++ b/contrib/pjdfstest/tests/rename/04.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rename/04.t 211352 2010-08-15 21:24:17Z pjd $
desc="rename returns EACCES when a component of either path prefix denies search permission"
diff --git a/tools/regression/pjdfstest/tests/rename/05.t b/contrib/pjdfstest/tests/rename/05.t
index 39aa28f..52deac1 100644
--- a/tools/regression/pjdfstest/tests/rename/05.t
+++ b/contrib/pjdfstest/tests/rename/05.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rename/05.t 211352 2010-08-15 21:24:17Z pjd $
desc="rename returns EACCES when the requested link requires writing in a directory with a mode that denies write permission"
diff --git a/tools/regression/pjdfstest/tests/rename/06.t b/contrib/pjdfstest/tests/rename/06.t
index 2606c4e..ffcf61e 100644
--- a/tools/regression/pjdfstest/tests/rename/06.t
+++ b/contrib/pjdfstest/tests/rename/06.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rename/06.t 211352 2010-08-15 21:24:17Z pjd $
desc="rename returns EPERM if the file pointed at by the 'from' argument has its immutable, undeletable or append-only flag set"
diff --git a/tools/regression/pjdfstest/tests/rename/07.t b/contrib/pjdfstest/tests/rename/07.t
index 450b653..522e67d 100644
--- a/tools/regression/pjdfstest/tests/rename/07.t
+++ b/contrib/pjdfstest/tests/rename/07.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rename/07.t 211352 2010-08-15 21:24:17Z pjd $
desc="rename returns EPERM if the parent directory of the file pointed at by the 'from' argument has its immutable or append-only flag set"
diff --git a/tools/regression/pjdfstest/tests/rename/08.t b/contrib/pjdfstest/tests/rename/08.t
index 480672f..beffb41 100644
--- a/tools/regression/pjdfstest/tests/rename/08.t
+++ b/contrib/pjdfstest/tests/rename/08.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rename/08.t 211352 2010-08-15 21:24:17Z pjd $
desc="rename returns EPERM if the parent directory of the file pointed at by the 'to' argument has its immutable flag set"
diff --git a/tools/regression/pjdfstest/tests/rename/09.t b/contrib/pjdfstest/tests/rename/09.t
index 91d16a6..299ff64 100644
--- a/tools/regression/pjdfstest/tests/rename/09.t
+++ b/contrib/pjdfstest/tests/rename/09.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rename/09.t 211352 2010-08-15 21:24:17Z pjd $
desc="rename returns EACCES or EPERM if the directory containing 'from' is marked sticky, and neither the containing directory nor 'from' are owned by the effective user ID"
diff --git a/tools/regression/pjdfstest/tests/rename/10.t b/contrib/pjdfstest/tests/rename/10.t
index 3b48d1f..268c3b6 100644
--- a/tools/regression/pjdfstest/tests/rename/10.t
+++ b/contrib/pjdfstest/tests/rename/10.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rename/10.t 211352 2010-08-15 21:24:17Z pjd $
desc="rename returns EACCES or EPERM if the file pointed at by the 'to' argument exists, the directory containing 'to' is marked sticky, and neither the containing directory nor 'to' are owned by the effective user ID"
diff --git a/tools/regression/pjdfstest/tests/rename/11.t b/contrib/pjdfstest/tests/rename/11.t
index 6120e64..3bcd97e 100644
--- a/tools/regression/pjdfstest/tests/rename/11.t
+++ b/contrib/pjdfstest/tests/rename/11.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rename/11.t 211352 2010-08-15 21:24:17Z pjd $
desc="rename returns ELOOP if too many symbolic links were encountered in translating one of the pathnames"
diff --git a/tools/regression/pjdfstest/tests/rename/12.t b/contrib/pjdfstest/tests/rename/12.t
index 4383d84..c8939fe 100644
--- a/tools/regression/pjdfstest/tests/rename/12.t
+++ b/contrib/pjdfstest/tests/rename/12.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rename/12.t 211474 2010-08-18 22:06:43Z pjd $
desc="rename returns ENOTDIR if a component of either path prefix is not a directory"
diff --git a/tools/regression/pjdfstest/tests/rename/13.t b/contrib/pjdfstest/tests/rename/13.t
index 5e39698..00b0bfb 100644
--- a/tools/regression/pjdfstest/tests/rename/13.t
+++ b/contrib/pjdfstest/tests/rename/13.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rename/13.t 211352 2010-08-15 21:24:17Z pjd $
desc="rename returns ENOTDIR when the 'from' argument is a directory, but 'to' is not a directory"
diff --git a/tools/regression/pjdfstest/tests/rename/14.t b/contrib/pjdfstest/tests/rename/14.t
index 8133c91..251a1bd 100644
--- a/tools/regression/pjdfstest/tests/rename/14.t
+++ b/contrib/pjdfstest/tests/rename/14.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rename/14.t 211352 2010-08-15 21:24:17Z pjd $
desc="rename returns EISDIR when the 'to' argument is a directory, but 'from' is not a directory"
diff --git a/tools/regression/pjdfstest/tests/rename/15.t b/contrib/pjdfstest/tests/rename/15.t
index 46927ba..cd2e44b 100644
--- a/tools/regression/pjdfstest/tests/rename/15.t
+++ b/contrib/pjdfstest/tests/rename/15.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rename/15.t 211352 2010-08-15 21:24:17Z pjd $
desc="rename returns EXDEV if the link named by 'to' and the file named by 'from' are on different file systems"
@@ -15,9 +15,9 @@ n1=`namegen`
n2=`namegen`
expect 0 mkdir ${n0} 0755
-n=`mdconfig -a -n -t malloc -s 1m`
-newfs /dev/md${n} >/dev/null
-mount /dev/md${n} ${n0}
+n=`mdconfig -a -n -t malloc -s 1m` || exit
+newfs /dev/md${n} >/dev/null || exit
+mount /dev/md${n} ${n0} || exit
for type in regular dir fifo block char socket symlink; do
create_file ${type} ${n0}/${n1}
@@ -30,5 +30,5 @@ for type in regular dir fifo block char socket symlink; do
done
umount /dev/md${n}
-mdconfig -d -u ${n}
+mdconfig -d -u ${n} || exit
expect 0 rmdir ${n0}
diff --git a/tools/regression/pjdfstest/tests/rename/16.t b/contrib/pjdfstest/tests/rename/16.t
index b327f36..102657d 100644
--- a/tools/regression/pjdfstest/tests/rename/16.t
+++ b/contrib/pjdfstest/tests/rename/16.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rename/16.t 211352 2010-08-15 21:24:17Z pjd $
desc="rename returns EROFS if the requested link requires writing in a directory on a read-only file system"
@@ -15,9 +15,9 @@ n1=`namegen`
n2=`namegen`
expect 0 mkdir ${n0} 0755
-n=`mdconfig -a -n -t malloc -s 1m`
-newfs /dev/md${n} >/dev/null
-mount /dev/md${n} ${n0}
+n=`mdconfig -a -n -t malloc -s 1m` || exit
+newfs /dev/md${n} >/dev/null || exit
+mount /dev/md${n} ${n0} || exit
expect 0 create ${n0}/${n1} 0644
mount -ur /dev/md${n}
@@ -28,5 +28,5 @@ expect EROFS rename ${n2} ${n0}/${n2}
expect 0 unlink ${n2}
umount /dev/md${n}
-mdconfig -d -u ${n}
+mdconfig -d -u ${n} || exit
expect 0 rmdir ${n0}
diff --git a/tools/regression/pjdfstest/tests/rename/17.t b/contrib/pjdfstest/tests/rename/17.t
index a391349..6deb7b7 100644
--- a/tools/regression/pjdfstest/tests/rename/17.t
+++ b/contrib/pjdfstest/tests/rename/17.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rename/17.t 211352 2010-08-15 21:24:17Z pjd $
desc="rename returns EFAULT if one of the pathnames specified is outside the process's allocated address space"
diff --git a/tools/regression/pjdfstest/tests/rename/18.t b/contrib/pjdfstest/tests/rename/18.t
index a69913b..8a9594e 100644
--- a/tools/regression/pjdfstest/tests/rename/18.t
+++ b/contrib/pjdfstest/tests/rename/18.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rename/18.t 211352 2010-08-15 21:24:17Z pjd $
desc="rename returns EINVAL when the 'from' argument is a parent directory of 'to'"
diff --git a/tools/regression/pjdfstest/tests/rename/19.t b/contrib/pjdfstest/tests/rename/19.t
index 7459523..2cd9561 100644
--- a/tools/regression/pjdfstest/tests/rename/19.t
+++ b/contrib/pjdfstest/tests/rename/19.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rename/19.t 211352 2010-08-15 21:24:17Z pjd $
desc="rename returns EINVAL/EBUSY when an attempt is made to rename '.' or '..'"
diff --git a/tools/regression/pjdfstest/tests/rename/20.t b/contrib/pjdfstest/tests/rename/20.t
index 619fea3..8ec37cf 100644
--- a/tools/regression/pjdfstest/tests/rename/20.t
+++ b/contrib/pjdfstest/tests/rename/20.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rename/20.t 211352 2010-08-15 21:24:17Z pjd $
desc="rename returns EEXIST or ENOTEMPTY if the 'to' argument is a directory and is not empty"
diff --git a/tools/regression/pjdfstest/tests/rename/21.t b/contrib/pjdfstest/tests/rename/21.t
index 12d98e3..bba1467 100644
--- a/tools/regression/pjdfstest/tests/rename/21.t
+++ b/contrib/pjdfstest/tests/rename/21.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rename/21.t 211352 2010-08-15 21:24:17Z pjd $
desc="write access to subdirectory is required to move it to another directory"
diff --git a/tools/regression/pjdfstest/tests/rmdir/00.t b/contrib/pjdfstest/tests/rmdir/00.t
index 4381e66..9e75be6 100644
--- a/tools/regression/pjdfstest/tests/rmdir/00.t
+++ b/contrib/pjdfstest/tests/rmdir/00.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rmdir/00.t 211352 2010-08-15 21:24:17Z pjd $
desc="rmdir removes directories"
diff --git a/tools/regression/pjdfstest/tests/rmdir/01.t b/contrib/pjdfstest/tests/rmdir/01.t
index d2d407d..b89ffef 100644
--- a/tools/regression/pjdfstest/tests/rmdir/01.t
+++ b/contrib/pjdfstest/tests/rmdir/01.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rmdir/01.t 211352 2010-08-15 21:24:17Z pjd $
desc="rmdir returns ENOTDIR if a component of the path is not a directory"
diff --git a/tools/regression/pjdfstest/tests/rmdir/02.t b/contrib/pjdfstest/tests/rmdir/02.t
index 3daae4e..eb8a774 100644
--- a/tools/regression/pjdfstest/tests/rmdir/02.t
+++ b/contrib/pjdfstest/tests/rmdir/02.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rmdir/02.t 211352 2010-08-15 21:24:17Z pjd $
desc="rmdir returns ENAMETOOLONG if a component of a pathname exceeded {NAME_MAX} characters"
diff --git a/tools/regression/pjdfstest/tests/rmdir/03.t b/contrib/pjdfstest/tests/rmdir/03.t
index a7259e0..3d5a11a 100644
--- a/tools/regression/pjdfstest/tests/rmdir/03.t
+++ b/contrib/pjdfstest/tests/rmdir/03.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rmdir/03.t 211352 2010-08-15 21:24:17Z pjd $
desc="rmdir returns ENAMETOOLONG if an entire path name exceeded ${PATH_MAX} characters"
diff --git a/tools/regression/pjdfstest/tests/rmdir/04.t b/contrib/pjdfstest/tests/rmdir/04.t
index 77e1d30..d5abc31 100644
--- a/tools/regression/pjdfstest/tests/rmdir/04.t
+++ b/contrib/pjdfstest/tests/rmdir/04.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rmdir/04.t 211352 2010-08-15 21:24:17Z pjd $
desc="rmdir returns ENOENT if the named directory does not exist"
diff --git a/tools/regression/pjdfstest/tests/rmdir/05.t b/contrib/pjdfstest/tests/rmdir/05.t
index fd973a9..eb98453 100644
--- a/tools/regression/pjdfstest/tests/rmdir/05.t
+++ b/contrib/pjdfstest/tests/rmdir/05.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rmdir/05.t 211352 2010-08-15 21:24:17Z pjd $
desc="rmdir returns ELOOP if too many symbolic links were encountered in translating the pathname"
diff --git a/tools/regression/pjdfstest/tests/rmdir/06.t b/contrib/pjdfstest/tests/rmdir/06.t
index 9de34b0..64a6ac8 100644
--- a/tools/regression/pjdfstest/tests/rmdir/06.t
+++ b/contrib/pjdfstest/tests/rmdir/06.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rmdir/06.t 211474 2010-08-18 22:06:43Z pjd $
desc="rmdir returns EEXIST or ENOTEMPTY the named directory contains files other than '.' and '..' in it"
diff --git a/tools/regression/pjdfstest/tests/rmdir/07.t b/contrib/pjdfstest/tests/rmdir/07.t
index 2528245..10a78a7 100644
--- a/tools/regression/pjdfstest/tests/rmdir/07.t
+++ b/contrib/pjdfstest/tests/rmdir/07.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rmdir/07.t 211352 2010-08-15 21:24:17Z pjd $
desc="rmdir returns EACCES when search permission is denied for a component of the path prefix"
diff --git a/tools/regression/pjdfstest/tests/rmdir/08.t b/contrib/pjdfstest/tests/rmdir/08.t
index c1fb819..fe70c86 100644
--- a/tools/regression/pjdfstest/tests/rmdir/08.t
+++ b/contrib/pjdfstest/tests/rmdir/08.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rmdir/08.t 211352 2010-08-15 21:24:17Z pjd $
desc="rmdir returns EACCES when write permission is denied on the directory containing the link to be removed"
diff --git a/tools/regression/pjdfstest/tests/rmdir/09.t b/contrib/pjdfstest/tests/rmdir/09.t
index 240fd5c..8b0276c 100644
--- a/tools/regression/pjdfstest/tests/rmdir/09.t
+++ b/contrib/pjdfstest/tests/rmdir/09.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rmdir/09.t 211352 2010-08-15 21:24:17Z pjd $
desc="rmdir returns EPERM if the named directory has its immutable, undeletable or append-only flag set"
diff --git a/tools/regression/pjdfstest/tests/rmdir/10.t b/contrib/pjdfstest/tests/rmdir/10.t
index 7bdc261..5d2e37e 100644
--- a/tools/regression/pjdfstest/tests/rmdir/10.t
+++ b/contrib/pjdfstest/tests/rmdir/10.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rmdir/10.t 211352 2010-08-15 21:24:17Z pjd $
desc="rmdir returns EPERM if the parent directory of the named file has its immutable or append-only flag set"
diff --git a/tools/regression/pjdfstest/tests/rmdir/11.t b/contrib/pjdfstest/tests/rmdir/11.t
index 6e4b0b1..b8e0591 100644
--- a/tools/regression/pjdfstest/tests/rmdir/11.t
+++ b/contrib/pjdfstest/tests/rmdir/11.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rmdir/11.t 211352 2010-08-15 21:24:17Z pjd $
desc="rmdir returns EACCES or EPERM if the directory containing the directory to be removed is marked sticky, and neither the containing directory nor the directory to be removed are owned by the effective user ID"
diff --git a/tools/regression/pjdfstest/tests/rmdir/12.t b/contrib/pjdfstest/tests/rmdir/12.t
index 9ba45a4..57d144d 100644
--- a/tools/regression/pjdfstest/tests/rmdir/12.t
+++ b/contrib/pjdfstest/tests/rmdir/12.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rmdir/12.t 211352 2010-08-15 21:24:17Z pjd $
desc="rmdir returns EINVAL if the last component of the path is '.' and EEXIST or ENOTEMPTY if the last component of the path is '..'"
diff --git a/tools/regression/pjdfstest/tests/rmdir/13.t b/contrib/pjdfstest/tests/rmdir/13.t
index 6140e7b..4a1a885 100644
--- a/tools/regression/pjdfstest/tests/rmdir/13.t
+++ b/contrib/pjdfstest/tests/rmdir/13.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rmdir/13.t 211352 2010-08-15 21:24:17Z pjd $
desc="rmdir returns EBUSY if the directory to be removed is the mount point for a mounted file system"
@@ -13,10 +13,10 @@ echo "1..3"
n0=`namegen`
expect 0 mkdir ${n0} 0755
-n=`mdconfig -a -n -t malloc -s 1m`
-newfs /dev/md${n} >/dev/null
-mount /dev/md${n} ${n0}
+n=`mdconfig -a -n -t malloc -s 1m` || exit
+newfs /dev/md${n} >/dev/null || exit
+mount /dev/md${n} ${n0} || exit
expect EBUSY rmdir ${n0}
umount /dev/md${n}
-mdconfig -d -u ${n}
+mdconfig -d -u ${n} || exit
expect 0 rmdir ${n0}
diff --git a/tools/regression/pjdfstest/tests/rmdir/14.t b/contrib/pjdfstest/tests/rmdir/14.t
index faa5d5e..bdefeae 100644
--- a/tools/regression/pjdfstest/tests/rmdir/14.t
+++ b/contrib/pjdfstest/tests/rmdir/14.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rmdir/14.t 211352 2010-08-15 21:24:17Z pjd $
desc="rmdir returns EROFS if the named file resides on a read-only file system"
@@ -14,14 +14,14 @@ n0=`namegen`
n1=`namegen`
expect 0 mkdir ${n0} 0755
-n=`mdconfig -a -n -t malloc -s 1m`
-newfs /dev/md${n} >/dev/null
-mount /dev/md${n} ${n0}
+n=`mdconfig -a -n -t malloc -s 1m` || exit
+newfs /dev/md${n} >/dev/null || exit
+mount /dev/md${n} ${n0} || exit
expect 0 mkdir ${n0}/${n1} 0755
mount -ur /dev/md${n}
expect EROFS rmdir ${n0}/${n1}
mount -uw /dev/md${n}
expect 0 rmdir ${n0}/${n1}
umount /dev/md${n}
-mdconfig -d -u ${n}
+mdconfig -d -u ${n} || exit
expect 0 rmdir ${n0}
diff --git a/tools/regression/pjdfstest/tests/rmdir/15.t b/contrib/pjdfstest/tests/rmdir/15.t
index 8bfa149..5390403 100644
--- a/tools/regression/pjdfstest/tests/rmdir/15.t
+++ b/contrib/pjdfstest/tests/rmdir/15.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/rmdir/15.t 211352 2010-08-15 21:24:17Z pjd $
desc="rmdir returns EFAULT if the path argument points outside the process's allocated address space"
diff --git a/tools/regression/pjdfstest/tests/symlink/00.t b/contrib/pjdfstest/tests/symlink/00.t
index 6e6d46d..1f26939 100644
--- a/tools/regression/pjdfstest/tests/symlink/00.t
+++ b/contrib/pjdfstest/tests/symlink/00.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/symlink/00.t 211352 2010-08-15 21:24:17Z pjd $
desc="symlink creates symbolic links"
diff --git a/tools/regression/pjdfstest/tests/symlink/01.t b/contrib/pjdfstest/tests/symlink/01.t
index f19870c..3a40b54 100644
--- a/tools/regression/pjdfstest/tests/symlink/01.t
+++ b/contrib/pjdfstest/tests/symlink/01.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/symlink/01.t 211352 2010-08-15 21:24:17Z pjd $
desc="symlink returns ENOTDIR if a component of the name2 path prefix is not a directory"
diff --git a/tools/regression/pjdfstest/tests/symlink/02.t b/contrib/pjdfstest/tests/symlink/02.t
index e06b936..4b81f16 100644
--- a/tools/regression/pjdfstest/tests/symlink/02.t
+++ b/contrib/pjdfstest/tests/symlink/02.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/symlink/02.t 211352 2010-08-15 21:24:17Z pjd $
desc="symlink returns ENAMETOOLONG if a component of the name2 pathname exceeded {NAME_MAX} characters"
diff --git a/tools/regression/pjdfstest/tests/symlink/03.t b/contrib/pjdfstest/tests/symlink/03.t
index 38ebe5e..68ecfbd 100644
--- a/tools/regression/pjdfstest/tests/symlink/03.t
+++ b/contrib/pjdfstest/tests/symlink/03.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/symlink/03.t 211352 2010-08-15 21:24:17Z pjd $
desc="symlink returns ENAMETOOLONG if an entire length of either path name exceeded {PATH_MAX} characters"
diff --git a/tools/regression/pjdfstest/tests/symlink/04.t b/contrib/pjdfstest/tests/symlink/04.t
index cc5e7b7..ca1c8ee 100644
--- a/tools/regression/pjdfstest/tests/symlink/04.t
+++ b/contrib/pjdfstest/tests/symlink/04.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/symlink/04.t 211352 2010-08-15 21:24:17Z pjd $
desc="symlink returns ENOENT if a component of the name2 path prefix does not exist"
diff --git a/tools/regression/pjdfstest/tests/symlink/05.t b/contrib/pjdfstest/tests/symlink/05.t
index c823a59..801e467 100644
--- a/tools/regression/pjdfstest/tests/symlink/05.t
+++ b/contrib/pjdfstest/tests/symlink/05.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/symlink/05.t 211352 2010-08-15 21:24:17Z pjd $
desc="symlink returns EACCES when a component of the name2 path prefix denies search permission"
diff --git a/tools/regression/pjdfstest/tests/symlink/06.t b/contrib/pjdfstest/tests/symlink/06.t
index 1f27818..db61ad0 100644
--- a/tools/regression/pjdfstest/tests/symlink/06.t
+++ b/contrib/pjdfstest/tests/symlink/06.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/symlink/06.t 211352 2010-08-15 21:24:17Z pjd $
desc="symlink returns EACCES if the parent directory of the file to be created denies write permission"
diff --git a/tools/regression/pjdfstest/tests/symlink/07.t b/contrib/pjdfstest/tests/symlink/07.t
index aa60b77..c6aedc0 100644
--- a/tools/regression/pjdfstest/tests/symlink/07.t
+++ b/contrib/pjdfstest/tests/symlink/07.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/symlink/07.t 211352 2010-08-15 21:24:17Z pjd $
desc="symlink returns ELOOP if too many symbolic links were encountered in translating the name2 path name"
diff --git a/tools/regression/pjdfstest/tests/symlink/08.t b/contrib/pjdfstest/tests/symlink/08.t
index 9d539f1..ef7915d 100644
--- a/tools/regression/pjdfstest/tests/symlink/08.t
+++ b/contrib/pjdfstest/tests/symlink/08.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/symlink/08.t 211474 2010-08-18 22:06:43Z pjd $
desc="symlink returns EEXIST if the name2 argument already exists"
diff --git a/tools/regression/pjdfstest/tests/symlink/09.t b/contrib/pjdfstest/tests/symlink/09.t
index 4807db4..6292aaf 100644
--- a/tools/regression/pjdfstest/tests/symlink/09.t
+++ b/contrib/pjdfstest/tests/symlink/09.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/symlink/09.t 211352 2010-08-15 21:24:17Z pjd $
desc="symlink returns EPERM if the parent directory of the file named by name2 has its immutable flag set"
diff --git a/tools/regression/pjdfstest/tests/symlink/10.t b/contrib/pjdfstest/tests/symlink/10.t
index b43da77..47a6eb4 100644
--- a/tools/regression/pjdfstest/tests/symlink/10.t
+++ b/contrib/pjdfstest/tests/symlink/10.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/symlink/10.t 211352 2010-08-15 21:24:17Z pjd $
desc="symlink returns EROFS if the file name2 would reside on a read-only file system"
@@ -15,9 +15,9 @@ n1=`namegen`
n2=`namegen`
expect 0 mkdir ${n0} 0755
-n=`mdconfig -a -n -t malloc -s 1m`
-newfs /dev/md${n} >/dev/null
-mount /dev/md${n} ${n0}
+n=`mdconfig -a -n -t malloc -s 1m` || exit
+newfs /dev/md${n} >/dev/null || exit
+mount /dev/md${n} ${n0} || exit
expect 0 symlink test ${n0}/${n1}
expect 0 unlink ${n0}/${n1}
@@ -28,5 +28,5 @@ expect 0 symlink test ${n0}/${n1}
expect 0 unlink ${n0}/${n1}
umount /dev/md${n}
-mdconfig -d -u ${n}
+mdconfig -d -u ${n} || exit
expect 0 rmdir ${n0}
diff --git a/tools/regression/pjdfstest/tests/symlink/11.t b/contrib/pjdfstest/tests/symlink/11.t
index 2f04b7b..e9f78e8 100644
--- a/tools/regression/pjdfstest/tests/symlink/11.t
+++ b/contrib/pjdfstest/tests/symlink/11.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/symlink/11.t 211352 2010-08-15 21:24:17Z pjd $
desc="symlink returns ENOSPC if there are no free inodes on the file system on which the symbolic link is being created"
@@ -14,9 +14,9 @@ n0=`namegen`
n1=`namegen`
expect 0 mkdir ${n0} 0755
-n=`mdconfig -a -n -t malloc -s 256k`
-newfs /dev/md${n} >/dev/null
-mount /dev/md${n} ${n0}
+n=`mdconfig -a -n -t malloc -s 512k` || exit
+newfs /dev/md${n} >/dev/null || exit
+mount /dev/md${n} ${n0} || exit
i=0
while :; do
ln -s test ${n0}/${i} >/dev/null 2>&1
@@ -27,5 +27,5 @@ while :; do
done
expect ENOSPC symlink test ${n0}/${n1}
umount /dev/md${n}
-mdconfig -d -u ${n}
+mdconfig -d -u ${n} || exit
expect 0 rmdir ${n0}
diff --git a/tools/regression/pjdfstest/tests/symlink/12.t b/contrib/pjdfstest/tests/symlink/12.t
index 8606a38..2c69905 100644
--- a/tools/regression/pjdfstest/tests/symlink/12.t
+++ b/contrib/pjdfstest/tests/symlink/12.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/symlink/12.t 211352 2010-08-15 21:24:17Z pjd $
desc="symlink returns EFAULT if one of the pathnames specified is outside the process's allocated address space"
diff --git a/tools/regression/pjdfstest/tests/truncate/00.t b/contrib/pjdfstest/tests/truncate/00.t
index c09f068..6a77a8f 100644
--- a/tools/regression/pjdfstest/tests/truncate/00.t
+++ b/contrib/pjdfstest/tests/truncate/00.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/truncate/00.t 211352 2010-08-15 21:24:17Z pjd $
desc="truncate descrease/increase file size"
diff --git a/contrib/pjdfstest/tests/truncate/01.t b/contrib/pjdfstest/tests/truncate/01.t
new file mode 100644
index 0000000..a8e95ac
--- /dev/null
+++ b/contrib/pjdfstest/tests/truncate/01.t
@@ -0,0 +1,18 @@
+#!/bin/sh
+# $FreeBSD: head/tools/regression/pjdfstest/tests/truncate/01.t 211352 2010-08-15 21:24:17Z pjd $
+
+desc="truncate returns ENOTDIR if a component of the path prefix is not a directory"
+
+dir=`dirname $0`
+. ${dir}/../misc.sh
+
+echo "1..5"
+
+n0=`namegen`
+n1=`namegen`
+
+expect 0 mkdir ${n0} 0755
+expect 0 create ${n0}/${n1} 0644
+expect ENOTDIR truncate ${n0}/${n1}/test 123
+expect 0 unlink ${n0}/${n1}
+expect 0 rmdir ${n0}
diff --git a/contrib/pjdfstest/tests/truncate/02.t b/contrib/pjdfstest/tests/truncate/02.t
new file mode 100644
index 0000000..83de38d
--- /dev/null
+++ b/contrib/pjdfstest/tests/truncate/02.t
@@ -0,0 +1,18 @@
+#!/bin/sh
+# $FreeBSD: head/tools/regression/pjdfstest/tests/truncate/02.t 211352 2010-08-15 21:24:17Z pjd $
+
+desc="truncate returns ENAMETOOLONG if a component of a pathname exceeded {NAME_MAX} characters"
+
+dir=`dirname $0`
+. ${dir}/../misc.sh
+
+echo "1..5"
+
+nx=`namegen_max`
+nxx="${nx}x"
+
+expect 0 create ${nx} 0644
+expect 0 truncate ${nx} 123
+expect 123 stat ${nx} size
+expect 0 unlink ${nx}
+expect ENAMETOOLONG truncate ${nxx} 123
diff --git a/contrib/pjdfstest/tests/truncate/03.t b/contrib/pjdfstest/tests/truncate/03.t
new file mode 100644
index 0000000..41e9862
--- /dev/null
+++ b/contrib/pjdfstest/tests/truncate/03.t
@@ -0,0 +1,22 @@
+#!/bin/sh
+# $FreeBSD: head/tools/regression/pjdfstest/tests/truncate/03.t 211352 2010-08-15 21:24:17Z pjd $
+
+desc="truncate returns ENAMETOOLONG if an entire path name exceeded {PATH_MAX} characters"
+
+dir=`dirname $0`
+. ${dir}/../misc.sh
+
+echo "1..5"
+
+nx=`dirgen_max`
+nxx="${nx}x"
+
+mkdir -p "${nx%/*}"
+
+expect 0 create ${nx} 0644
+expect 0 truncate ${nx} 123
+expect regular,123 stat ${nx} type,size
+expect 0 unlink ${nx}
+expect ENAMETOOLONG truncate ${nxx} 123
+
+rm -rf "${nx%%/*}"
diff --git a/contrib/pjdfstest/tests/truncate/04.t b/contrib/pjdfstest/tests/truncate/04.t
new file mode 100644
index 0000000..cd1cfc6
--- /dev/null
+++ b/contrib/pjdfstest/tests/truncate/04.t
@@ -0,0 +1,17 @@
+#!/bin/sh
+# $FreeBSD: head/tools/regression/pjdfstest/tests/truncate/04.t 211352 2010-08-15 21:24:17Z pjd $
+
+desc="truncate returns ENOENT if the named file does not exist"
+
+dir=`dirname $0`
+. ${dir}/../misc.sh
+
+echo "1..4"
+
+n0=`namegen`
+n1=`namegen`
+
+expect 0 mkdir ${n0} 0755
+expect ENOENT truncate ${n0}/${n1}/test 123
+expect ENOENT truncate ${n0}/${n1} 123
+expect 0 rmdir ${n0}
diff --git a/contrib/pjdfstest/tests/truncate/05.t b/contrib/pjdfstest/tests/truncate/05.t
new file mode 100644
index 0000000..f128815
--- /dev/null
+++ b/contrib/pjdfstest/tests/truncate/05.t
@@ -0,0 +1,32 @@
+#!/bin/sh
+# $FreeBSD: head/tools/regression/pjdfstest/tests/truncate/05.t 211352 2010-08-15 21:24:17Z pjd $
+
+desc="truncate returns EACCES when search permission is denied for a component of the path prefix"
+
+dir=`dirname $0`
+. ${dir}/../misc.sh
+
+echo "1..15"
+
+n0=`namegen`
+n1=`namegen`
+n2=`namegen`
+
+expect 0 mkdir ${n0} 0755
+cdir=`pwd`
+cd ${n0}
+expect 0 mkdir ${n1} 0755
+expect 0 chown ${n1} 65534 65534
+expect 0 -u 65534 -g 65534 create ${n1}/${n2} 0644
+expect 0 -u 65534 -g 65534 truncate ${n1}/${n2} 123
+expect 123 -u 65534 -g 65534 stat ${n1}/${n2} size
+expect 0 chmod ${n1} 0644
+expect EACCES -u 65534 -g 65534 truncate ${n1}/${n2} 1234
+expect 0 chmod ${n1} 0755
+expect 123 -u 65534 -g 65534 stat ${n1}/${n2} size
+expect 0 -u 65534 -g 65534 truncate ${n1}/${n2} 1234
+expect 1234 -u 65534 -g 65534 stat ${n1}/${n2} size
+expect 0 -u 65534 -g 65534 unlink ${n1}/${n2}
+expect 0 rmdir ${n1}
+cd ${cdir}
+expect 0 rmdir ${n0}
diff --git a/contrib/pjdfstest/tests/truncate/06.t b/contrib/pjdfstest/tests/truncate/06.t
new file mode 100644
index 0000000..1ce516f
--- /dev/null
+++ b/contrib/pjdfstest/tests/truncate/06.t
@@ -0,0 +1,24 @@
+#!/bin/sh
+# $FreeBSD: head/tools/regression/pjdfstest/tests/truncate/06.t 211352 2010-08-15 21:24:17Z pjd $
+
+desc="truncate returns EACCES if the named file is not writable by the user"
+
+dir=`dirname $0`
+. ${dir}/../misc.sh
+
+echo "1..8"
+
+n0=`namegen`
+n1=`namegen`
+
+expect 0 mkdir ${n0} 0755
+cdir=`pwd`
+cd ${n0}
+expect 0 create ${n1} 0644
+expect EACCES -u 65534 -g 65534 truncate ${n1} 123
+expect 0 chown ${n1} 65534 65534
+expect 0 chmod ${n1} 0444
+expect EACCES -u 65534 -g 65534 truncate ${n1} 123
+expect 0 unlink ${n1}
+cd ${cdir}
+expect 0 rmdir ${n0}
diff --git a/contrib/pjdfstest/tests/truncate/07.t b/contrib/pjdfstest/tests/truncate/07.t
new file mode 100644
index 0000000..44f87e7
--- /dev/null
+++ b/contrib/pjdfstest/tests/truncate/07.t
@@ -0,0 +1,19 @@
+#!/bin/sh
+# $FreeBSD: head/tools/regression/pjdfstest/tests/truncate/07.t 211352 2010-08-15 21:24:17Z pjd $
+
+desc="truncate returns ELOOP if too many symbolic links were encountered in translating the pathname"
+
+dir=`dirname $0`
+. ${dir}/../misc.sh
+
+echo "1..6"
+
+n0=`namegen`
+n1=`namegen`
+
+expect 0 symlink ${n0} ${n1}
+expect 0 symlink ${n1} ${n0}
+expect ELOOP truncate ${n0}/test 123
+expect ELOOP truncate ${n1}/test 123
+expect 0 unlink ${n0}
+expect 0 unlink ${n1}
diff --git a/contrib/pjdfstest/tests/truncate/08.t b/contrib/pjdfstest/tests/truncate/08.t
new file mode 100644
index 0000000..6f205ef
--- /dev/null
+++ b/contrib/pjdfstest/tests/truncate/08.t
@@ -0,0 +1,78 @@
+#!/bin/sh
+# $FreeBSD: head/tools/regression/pjdfstest/tests/truncate/08.t 211352 2010-08-15 21:24:17Z pjd $
+
+desc="truncate returns EPERM if the named file has its immutable or append-only flag set"
+
+dir=`dirname $0`
+. ${dir}/../misc.sh
+
+require chflags
+
+case "${os}:${fs}" in
+FreeBSD:ZFS)
+ echo "1..22"
+ ;;
+FreeBSD:UFS)
+ echo "1..44"
+ ;;
+*)
+ quick_exit
+esac
+
+n0=`namegen`
+
+expect 0 create ${n0} 0644
+expect 0 chflags ${n0} SF_IMMUTABLE
+expect EPERM truncate ${n0} 123
+expect 0 stat ${n0} size
+expect 0 chflags ${n0} none
+expect 0 truncate ${n0} 123
+expect 123 stat ${n0} size
+expect 0 unlink ${n0}
+
+expect 0 create ${n0} 0644
+expect 0 chflags ${n0} SF_NOUNLINK
+expect 0 truncate ${n0} 123
+expect 123 stat ${n0} size
+expect 0 chflags ${n0} none
+expect 0 unlink ${n0}
+
+expect 0 create ${n0} 0644
+expect 0 chflags ${n0} SF_APPEND
+todo FreeBSD:ZFS "Truncating a file protected by SF_APPEND should return EPERM."
+expect EPERM truncate ${n0} 123
+todo FreeBSD:ZFS "Truncating a file protected by SF_APPEND should return EPERM."
+expect 0 stat ${n0} size
+expect 0 chflags ${n0} none
+expect 0 truncate ${n0} 123
+expect 123 stat ${n0} size
+expect 0 unlink ${n0}
+
+case "${os}:${fs}" in
+FreeBSD:UFS)
+ expect 0 create ${n0} 0644
+ expect 0 chflags ${n0} UF_IMMUTABLE
+ expect EPERM truncate ${n0} 123
+ expect 0 stat ${n0} size
+ expect 0 chflags ${n0} none
+ expect 0 truncate ${n0} 123
+ expect 123 stat ${n0} size
+ expect 0 unlink ${n0}
+
+ expect 0 create ${n0} 0644
+ expect 0 chflags ${n0} UF_NOUNLINK
+ expect 0 truncate ${n0} 123
+ expect 123 stat ${n0} size
+ expect 0 chflags ${n0} none
+ expect 0 unlink ${n0}
+
+ expect 0 create ${n0} 0644
+ expect 0 chflags ${n0} UF_APPEND
+ expect EPERM truncate ${n0} 123
+ expect 0 stat ${n0} size
+ expect 0 chflags ${n0} none
+ expect 0 truncate ${n0} 123
+ expect 123 stat ${n0} size
+ expect 0 unlink ${n0}
+ ;;
+esac
diff --git a/contrib/pjdfstest/tests/truncate/09.t b/contrib/pjdfstest/tests/truncate/09.t
new file mode 100644
index 0000000..d7e082d
--- /dev/null
+++ b/contrib/pjdfstest/tests/truncate/09.t
@@ -0,0 +1,15 @@
+#!/bin/sh
+# $FreeBSD: head/tools/regression/pjdfstest/tests/truncate/09.t 211352 2010-08-15 21:24:17Z pjd $
+
+desc="truncate returns EISDIR if the named file is a directory"
+
+dir=`dirname $0`
+. ${dir}/../misc.sh
+
+echo "1..3"
+
+n0=`namegen`
+
+expect 0 mkdir ${n0} 0755
+expect EISDIR truncate ${n0} 123
+expect 0 rmdir ${n0}
diff --git a/contrib/pjdfstest/tests/truncate/10.t b/contrib/pjdfstest/tests/truncate/10.t
new file mode 100644
index 0000000..ced3583
--- /dev/null
+++ b/contrib/pjdfstest/tests/truncate/10.t
@@ -0,0 +1,32 @@
+#!/bin/sh
+# $FreeBSD: head/tools/regression/pjdfstest/tests/truncate/10.t 211352 2010-08-15 21:24:17Z pjd $
+
+desc="truncate returns EROFS if the named file resides on a read-only file system"
+
+dir=`dirname $0`
+. ${dir}/../misc.sh
+
+[ "${os}:${fs}" = "FreeBSD:UFS" ] || quick_exit
+
+echo "1..10"
+
+n0=`namegen`
+n1=`namegen`
+
+expect 0 mkdir ${n0} 0755
+n=`mdconfig -a -n -t malloc -s 1m` || exit
+newfs /dev/md${n} >/dev/null || exit
+mount /dev/md${n} ${n0} || exit
+expect 0 create ${n0}/${n1} 0644
+expect 0 truncate ${n0}/${n1} 123
+expect 123 stat ${n0}/${n1} size
+mount -ur /dev/md${n}
+expect EROFS truncate ${n0}/${n1} 1234
+expect 123 stat ${n0}/${n1} size
+mount -uw /dev/md${n}
+expect 0 truncate ${n0}/${n1} 1234
+expect 1234 stat ${n0}/${n1} size
+expect 0 unlink ${n0}/${n1}
+umount /dev/md${n}
+mdconfig -d -u ${n} || exit
+expect 0 rmdir ${n0}
diff --git a/contrib/pjdfstest/tests/truncate/11.t b/contrib/pjdfstest/tests/truncate/11.t
new file mode 100644
index 0000000..b00d7b8
--- /dev/null
+++ b/contrib/pjdfstest/tests/truncate/11.t
@@ -0,0 +1,18 @@
+#!/bin/sh
+# $FreeBSD: head/tools/regression/pjdfstest/tests/truncate/11.t 211352 2010-08-15 21:24:17Z pjd $
+
+desc="truncate returns ETXTBSY the file is a pure procedure (shared text) file that is being executed"
+
+dir=`dirname $0`
+. ${dir}/../misc.sh
+
+[ "${os}" = "FreeBSD" ] || quick_exit
+
+echo "1..2"
+
+n0=`namegen`
+
+cp -pf `which sleep` ${n0}
+./${n0} 3 &
+expect ETXTBSY truncate ${n0} 123
+expect 0 unlink ${n0}
diff --git a/contrib/pjdfstest/tests/truncate/12.t b/contrib/pjdfstest/tests/truncate/12.t
new file mode 100644
index 0000000..1825456
--- /dev/null
+++ b/contrib/pjdfstest/tests/truncate/12.t
@@ -0,0 +1,27 @@
+#!/bin/sh
+# $FreeBSD: head/tools/regression/pjdfstest/tests/truncate/12.t 211352 2010-08-15 21:24:17Z pjd $
+
+desc="truncate returns EFBIG or EINVAL if the length argument was greater than the maximum file size"
+
+dir=`dirname $0`
+. ${dir}/../misc.sh
+
+echo "1..3"
+
+n0=`namegen`
+
+expect 0 create ${n0} 0644
+r=`${fstest} truncate ${n0} 999999999999999 2>/dev/null`
+case "${r}" in
+EFBIG|EINVAL)
+ expect 0 stat ${n0} size
+ ;;
+0)
+ expect 999999999999999 stat ${n0} size
+ ;;
+*)
+ echo "not ok ${ntest}"
+ ntest=`expr ${ntest} + 1`
+ ;;
+esac
+expect 0 unlink ${n0}
diff --git a/tools/regression/pjdfstest/tests/truncate/13.t b/contrib/pjdfstest/tests/truncate/13.t
index 9e40928..7c9f0d4 100644
--- a/tools/regression/pjdfstest/tests/truncate/13.t
+++ b/contrib/pjdfstest/tests/truncate/13.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/truncate/13.t 211352 2010-08-15 21:24:17Z pjd $
desc="truncate returns EINVAL if the length argument was less than 0"
diff --git a/contrib/pjdfstest/tests/truncate/14.t b/contrib/pjdfstest/tests/truncate/14.t
new file mode 100644
index 0000000..a238771
--- /dev/null
+++ b/contrib/pjdfstest/tests/truncate/14.t
@@ -0,0 +1,12 @@
+#!/bin/sh
+# $FreeBSD: head/tools/regression/pjdfstest/tests/truncate/14.t 211352 2010-08-15 21:24:17Z pjd $
+
+desc="truncate returns EFAULT if the path argument points outside the process's allocated address space"
+
+dir=`dirname $0`
+. ${dir}/../misc.sh
+
+echo "1..2"
+
+expect EFAULT truncate NULL 123
+expect EFAULT truncate DEADCODE 123
diff --git a/tools/regression/pjdfstest/tests/unlink/00.t b/contrib/pjdfstest/tests/unlink/00.t
index 9120a62..0b9b1f1 100644
--- a/tools/regression/pjdfstest/tests/unlink/00.t
+++ b/contrib/pjdfstest/tests/unlink/00.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/unlink/00.t 211352 2010-08-15 21:24:17Z pjd $
desc="unlink removes regular files, symbolic links, fifos and sockets"
diff --git a/tools/regression/pjdfstest/tests/unlink/01.t b/contrib/pjdfstest/tests/unlink/01.t
index 13fa0fe..7e29671 100644
--- a/tools/regression/pjdfstest/tests/unlink/01.t
+++ b/contrib/pjdfstest/tests/unlink/01.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/unlink/01.t 211352 2010-08-15 21:24:17Z pjd $
desc="unlink returns ENOTDIR if a component of the path prefix is not a directory"
diff --git a/tools/regression/pjdfstest/tests/unlink/02.t b/contrib/pjdfstest/tests/unlink/02.t
index 1324ba3..e624d98 100644
--- a/tools/regression/pjdfstest/tests/unlink/02.t
+++ b/contrib/pjdfstest/tests/unlink/02.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/unlink/02.t 211352 2010-08-15 21:24:17Z pjd $
desc="unlink returns ENAMETOOLONG if a component of a pathname exceeded {NAME_MAX} characters"
diff --git a/tools/regression/pjdfstest/tests/unlink/03.t b/contrib/pjdfstest/tests/unlink/03.t
index db4b4a4..f4c939e 100644
--- a/tools/regression/pjdfstest/tests/unlink/03.t
+++ b/contrib/pjdfstest/tests/unlink/03.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/unlink/03.t 211352 2010-08-15 21:24:17Z pjd $
desc="unlink returns ENAMETOOLONG if an entire path name exceeded {PATH_MAX} characters"
diff --git a/tools/regression/pjdfstest/tests/unlink/04.t b/contrib/pjdfstest/tests/unlink/04.t
index 7885f27..0717eaa 100644
--- a/tools/regression/pjdfstest/tests/unlink/04.t
+++ b/contrib/pjdfstest/tests/unlink/04.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/unlink/04.t 211352 2010-08-15 21:24:17Z pjd $
desc="unlink returns ENOENT if the named file does not exist"
diff --git a/tools/regression/pjdfstest/tests/unlink/05.t b/contrib/pjdfstest/tests/unlink/05.t
index c30c353..91dccf9 100644
--- a/tools/regression/pjdfstest/tests/unlink/05.t
+++ b/contrib/pjdfstest/tests/unlink/05.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/unlink/05.t 211352 2010-08-15 21:24:17Z pjd $
desc="unlink returns EACCES when search permission is denied for a component of the path prefix"
diff --git a/tools/regression/pjdfstest/tests/unlink/06.t b/contrib/pjdfstest/tests/unlink/06.t
index 3a64aa2..2937429 100644
--- a/tools/regression/pjdfstest/tests/unlink/06.t
+++ b/contrib/pjdfstest/tests/unlink/06.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/unlink/06.t 211352 2010-08-15 21:24:17Z pjd $
desc="unlink returns EACCES when write permission is denied on the directory containing the link to be removed"
diff --git a/tools/regression/pjdfstest/tests/unlink/07.t b/contrib/pjdfstest/tests/unlink/07.t
index ea9d2a3..e63eafa 100644
--- a/tools/regression/pjdfstest/tests/unlink/07.t
+++ b/contrib/pjdfstest/tests/unlink/07.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/unlink/07.t 211352 2010-08-15 21:24:17Z pjd $
desc="unlink returns ELOOP if too many symbolic links were encountered in translating the pathname"
diff --git a/tools/regression/pjdfstest/tests/unlink/08.t b/contrib/pjdfstest/tests/unlink/08.t
index ac81bd6..666400c 100644
--- a/tools/regression/pjdfstest/tests/unlink/08.t
+++ b/contrib/pjdfstest/tests/unlink/08.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/unlink/08.t 211352 2010-08-15 21:24:17Z pjd $
desc="unlink may return EPERM if the named file is a directory"
diff --git a/tools/regression/pjdfstest/tests/unlink/09.t b/contrib/pjdfstest/tests/unlink/09.t
index f3422a5..dbc202a 100644
--- a/tools/regression/pjdfstest/tests/unlink/09.t
+++ b/contrib/pjdfstest/tests/unlink/09.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/unlink/09.t 211352 2010-08-15 21:24:17Z pjd $
desc="unlink returns EPERM if the named file has its immutable, undeletable or append-only flag set"
diff --git a/tools/regression/pjdfstest/tests/unlink/10.t b/contrib/pjdfstest/tests/unlink/10.t
index 84f3154..9ca1d5b 100644
--- a/tools/regression/pjdfstest/tests/unlink/10.t
+++ b/contrib/pjdfstest/tests/unlink/10.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/unlink/10.t 211352 2010-08-15 21:24:17Z pjd $
desc="unlink returns EPERM if the parent directory of the named file has its immutable or append-only flag set"
diff --git a/tools/regression/pjdfstest/tests/unlink/11.t b/contrib/pjdfstest/tests/unlink/11.t
index b0d27f9..d7d71d8 100644
--- a/tools/regression/pjdfstest/tests/unlink/11.t
+++ b/contrib/pjdfstest/tests/unlink/11.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/unlink/11.t 211352 2010-08-15 21:24:17Z pjd $
desc="unlink returns EACCES or EPERM if the directory containing the file is marked sticky, and neither the containing directory nor the file to be removed are owned by the effective user ID"
diff --git a/tools/regression/pjdfstest/tests/unlink/12.t b/contrib/pjdfstest/tests/unlink/12.t
index b8116d6..ae39724 100644
--- a/tools/regression/pjdfstest/tests/unlink/12.t
+++ b/contrib/pjdfstest/tests/unlink/12.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/unlink/12.t 211352 2010-08-15 21:24:17Z pjd $
desc="unlink returns EROFS if the named file resides on a read-only file system"
@@ -14,14 +14,14 @@ n0=`namegen`
n1=`namegen`
expect 0 mkdir ${n0} 0755
-n=`mdconfig -a -n -t malloc -s 1m`
-newfs /dev/md${n} >/dev/null
-mount /dev/md${n} ${n0}
+n=`mdconfig -a -n -t malloc -s 1m` || exit
+newfs /dev/md${n} >/dev/null || exit
+mount /dev/md${n} ${n0} || exit
expect 0 create ${n0}/${n1} 0644
mount -ur /dev/md${n}
expect EROFS unlink ${n0}/${n1}
mount -uw /dev/md${n}
expect 0 unlink ${n0}/${n1}
umount /dev/md${n}
-mdconfig -d -u ${n}
+mdconfig -d -u ${n} || exit
expect 0 rmdir ${n0}
diff --git a/tools/regression/pjdfstest/tests/unlink/13.t b/contrib/pjdfstest/tests/unlink/13.t
index da5e718..c424b7e 100644
--- a/tools/regression/pjdfstest/tests/unlink/13.t
+++ b/contrib/pjdfstest/tests/unlink/13.t
@@ -1,5 +1,5 @@
#!/bin/sh
-# $FreeBSD$
+# $FreeBSD: head/tools/regression/pjdfstest/tests/unlink/13.t 211352 2010-08-15 21:24:17Z pjd $
desc="unlink returns EFAULT if the path argument points outside the process's allocated address space"
diff --git a/etc/defaults/periodic.conf b/etc/defaults/periodic.conf
index 8520fc5..bbf97d9 100644
--- a/etc/defaults/periodic.conf
+++ b/etc/defaults/periodic.conf
@@ -75,10 +75,6 @@ daily_backup_passwd_enable="YES" # Backup passwd & group
# 210.backup-aliases
daily_backup_aliases_enable="YES" # Backup mail aliases
-# 220.backup-pkgdb
-daily_backup_pkgdb_enable="YES" # Backup /var/db/pkg
-daily_backup_pkgdb_dir="/var/backups"
-
# 300.calendar
daily_calendar_enable="NO" # Run calendar -a
@@ -257,10 +253,6 @@ security_status_passwdless_period="daily"
security_status_logincheck_enable="YES"
security_status_logincheck_period="daily"
-# 460.chkportsum
-security_status_chkportsum_enable="NO" # Check ports w/ wrong checksum
-security_status_chkportsum_period="daily"
-
# 500.ipfwdenied
security_status_ipfwdenied_enable="YES"
security_status_ipfwdenied_period="daily"
diff --git a/etc/motd b/etc/motd
index e616d51..e70e98d 100644
--- a/etc/motd
+++ b/etc/motd
@@ -1,12 +1,13 @@
FreeBSD ?.?.? (UNKNOWN)
-Welcome to FreeBSD! Handy technical support resources:
+Welcome to FreeBSD!
-Security advisories and errata: https://www.FreeBSD.org/releases/
-Handbook: https://www.FreeBSD.org/handbook/
-FAQ: https://www.FreeBSD.org/faq/
-Mailing list: https://lists.FreeBSD.org/mailman/listinfo/freebsd-questions/
-Forums: https://forums.FreeBSD.org/
+Release Notes, Errata: https://www.FreeBSD.org/releases/
+Security Advisories: https://www.FreeBSD.org/security/
+FreeBSD Handbook: https://www.FreeBSD.org/handbook/
+FreeBSD FAQ: https://www.FreeBSD.org/faq/
+Questions List: https://lists.FreeBSD.org/mailman/listinfo/freebsd-questions/
+FreeBSD Forums: https://forums.FreeBSD.org/
Documents installed with the system are in the /usr/local/share/doc/freebsd/
directory, or can be installed later with: pkg install en-freebsd-doc
@@ -14,7 +15,6 @@ For other languages, replace "en" with a language code like de or fr.
Show the version of FreeBSD installed: uname -a
Please include that output and any error messages when posting questions.
-
Introduction to manual pages: man man
FreeBSD directory layout: man hier
diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist
index 5438176..beec7a3 100644
--- a/etc/mtree/BSD.tests.dist
+++ b/etc/mtree/BSD.tests.dist
@@ -89,6 +89,8 @@
..
libnv
..
+ libproc
+ ..
libutil
..
..
@@ -253,6 +255,8 @@
..
m4
..
+ mkimg
+ ..
ncal
..
printf
diff --git a/etc/rc.d/Makefile b/etc/rc.d/Makefile
index 64e83ac..12c87db 100644
--- a/etc/rc.d/Makefile
+++ b/etc/rc.d/Makefile
@@ -44,7 +44,6 @@ FILES= DAEMON \
dumpon \
faith \
fsck \
- ftp-proxy \
ftpd \
gbde \
geli \
@@ -73,7 +72,6 @@ FILES= DAEMON \
jail \
kadmind \
kdc \
- keyserv \
kfd \
kld \
kldxref \
@@ -133,7 +131,6 @@ FILES= DAEMON \
rpcbind \
rtadvd \
rtsold \
- rwho \
savecore \
sdpd \
securelevel \
@@ -169,27 +166,39 @@ FILES= DAEMON \
zfs \
zvol
-.if ${MK_OFED} != "no"
-_opensm= opensm
+.if ${MK_BLUETOOTH} != "no"
+_bluetooth= bluetooth
+_bthidd= bthidd
+_hcsecd= hcsecd
+_ubthidhci= ubthidhci
.endif
-.if ${MK_OPENSSH} != "no"
-_sshd= sshd
+.if ${MK_CASPER} != "no"
+_casperd= casperd
.endif
.if ${MK_NS_CACHING} != "no"
_nscd= nscd
.endif
-.if ${MK_BLUETOOTH} != "no"
-_bluetooth= bluetooth
-_bthidd= bthidd
-_hcsecd= hcsecd
-_ubthidhci= ubthidhci
+.if ${MK_OFED} != "no"
+_opensm= opensm
.endif
-.if ${MK_CASPER} != "no"
-_casperd= casperd
+.if ${MK_OPENSSL} != "no"
+FILES+= keyserv
+.endif
+
+.if ${MK_OPENSSH} != "no"
+_sshd= sshd
+.endif
+
+.if ${MK_PF} != "no"
+FILES+= ftp-proxy
+.endif
+
+.if ${MK_RCMDS} != "no"
+FILES+= rwho
.endif
.if ${MK_UNBOUND} != "no"
diff --git a/etc/rc.d/syscons b/etc/rc.d/syscons
index 0dc41ad..a60ac4c 100755
--- a/etc/rc.d/syscons
+++ b/etc/rc.d/syscons
@@ -167,7 +167,7 @@ syscons_configure_keyboard()
# keymap
#
case ${keymap} in
- [Nn][Oo] | '')
+ NO | '')
;;
*)
sc_init
diff --git a/games/factor/factor.6 b/games/factor/factor.6
index a4d35e9..508a98b 100644
--- a/games/factor/factor.6
+++ b/games/factor/factor.6
@@ -90,7 +90,7 @@ value must not be greater than the maximum.
The default and maximum value of
.Ar stop
is 4294967295 on 32-bit architectures
-and 18446744073709551615 on 64-bit ones.
+and 3825123056546413050 on 64-bit ones.
.Pp
When the
.Nm primes
@@ -120,3 +120,9 @@ cannot handle the
factor list,
.Nm primes
will not get you a world record.
+.Pp
+.Nm primes
+is unable to list primes between 3825123056546413050 and 18446744073709551615
+since it relies on strong pseudoprime tests after sieving, and nobody has
+proven how many strong pseudoprime tests are required to prove primality for
+integers larger than 3825123056546413050.
diff --git a/games/primes/Makefile b/games/primes/Makefile
index 13c9048..bfc4147 100644
--- a/games/primes/Makefile
+++ b/games/primes/Makefile
@@ -2,7 +2,7 @@
# $FreeBSD$
PROG= primes
-SRCS= pattern.c pr_tbl.c primes.c
+SRCS= pattern.c pr_tbl.c primes.c spsp.c
MAN=
DPADD= ${LIBM}
LDADD= -lm
diff --git a/games/primes/primes.c b/games/primes/primes.c
index 33838ee..f5f1faf 100644
--- a/games/primes/primes.c
+++ b/games/primes/primes.c
@@ -111,7 +111,7 @@ main(int argc, char *argv[])
argv += optind;
start = 0;
- stop = BIG;
+ stop = (sizeof(ubig) > 4) ? SPSPMAX : BIG;
/*
* Convert low and high args. Strtoul(3) sets errno to
@@ -138,6 +138,8 @@ main(int argc, char *argv[])
err(1, "%s", argv[1]);
if (*p != '\0')
errx(1, "%s: illegal numeric format.", argv[1]);
+ if ((uint64_t)stop > SPSPMAX)
+ errx(1, "%s: stop value too large.", argv[1]);
break;
case 1:
/* Start on the command line. */
@@ -304,6 +306,10 @@ primes(ubig start, ubig stop)
*/
for (q = table; q < tab_lim; ++q, start+=2) {
if (*q) {
+ if ((uint64_t)start > SIEVEMAX) {
+ if (!isprime(start))
+ continue;
+ }
printf(hflag ? "0x%lx\n" : "%lu\n", start);
}
}
diff --git a/games/primes/primes.h b/games/primes/primes.h
index 0951bbf..7dcef52 100644
--- a/games/primes/primes.h
+++ b/games/primes/primes.h
@@ -57,6 +57,9 @@ typedef unsigned long ubig; /* must be >=32 bit unsigned value */
extern const ubig prime[];
extern const ubig *const pr_limit; /* largest prime in the prime array */
+/* Maximum size sieving alone can handle. */
+#define SIEVEMAX 4295098368ULL
+
/*
* To avoid excessive sieves for small factors, we use the table below to
* setup our sieve blocks. Each element represents an odd number starting
@@ -64,3 +67,9 @@ extern const ubig *const pr_limit; /* largest prime in the prime array */
*/
extern const char pattern[];
extern const size_t pattern_size; /* length of pattern array */
+
+/* Test for primality using strong pseudoprime tests. */
+int isprime(ubig);
+
+/* Maximum value which the SPSP code can handle. */
+#define SPSPMAX 3825123056546413050ULL
diff --git a/games/primes/spsp.c b/games/primes/spsp.c
new file mode 100644
index 0000000..f61acd6
--- /dev/null
+++ b/games/primes/spsp.c
@@ -0,0 +1,181 @@
+/*-
+ * Copyright (c) 2014 Colin Percival
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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$");
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "primes.h"
+
+/* Return a * b % n, where 0 <= a, b < 2^63, 0 < n < 2^63. */
+static uint64_t
+mulmod(uint64_t a, uint64_t b, uint64_t n)
+{
+ uint64_t x = 0;
+
+ while (b != 0) {
+ if (b & 1)
+ x = (x + a) % n;
+ a = (a + a) % n;
+ b >>= 1;
+ }
+
+ return (x);
+}
+
+/* Return a^r % n, where 0 <= a < 2^63, 0 < n < 2^63. */
+static uint64_t
+powmod(uint64_t a, uint64_t r, uint64_t n)
+{
+ uint64_t x = 1;
+
+ while (r != 0) {
+ if (r & 1)
+ x = mulmod(a, x, n);
+ a = mulmod(a, a, n);
+ r >>= 1;
+ }
+
+ return (x);
+}
+
+/* Return non-zero if n is a strong pseudoprime to base p. */
+static int
+spsp(uint64_t n, uint64_t p)
+{
+ uint64_t x;
+ uint64_t r = n - 1;
+ int k = 0;
+
+ /* Compute n - 1 = 2^k * r. */
+ while ((r & 1) == 0) {
+ k++;
+ r >>= 1;
+ }
+
+ /* Compute x = p^r mod n. If x = 1, n is a p-spsp. */
+ x = powmod(p, r, n);
+ if (x == 1)
+ return (1);
+
+ /* Compute x^(2^i) for 0 <= i < n. If any are -1, n is a p-spsp. */
+ while (k > 0) {
+ if (x == n - 1)
+ return (1);
+ x = powmod(x, 2, n);
+ k--;
+ }
+
+ /* Not a p-spsp. */
+ return (0);
+}
+
+/* Test for primality using strong pseudoprime tests. */
+int
+isprime(ubig _n)
+{
+ uint64_t n = _n;
+
+ /*
+ * Values from:
+ * C. Pomerance, J.L. Selfridge, and S.S. Wagstaff, Jr.,
+ * The pseudoprimes to 25 * 10^9, Math. Comp. 35(151):1003-1026, 1980.
+ */
+
+ /* No SPSPs to base 2 less than 2047. */
+ if (!spsp(n, 2))
+ return (0);
+ if (n < 2047ULL)
+ return (1);
+
+ /* No SPSPs to bases 2,3 less than 1373653. */
+ if (!spsp(n, 3))
+ return (0);
+ if (n < 1373653ULL)
+ return (1);
+
+ /* No SPSPs to bases 2,3,5 less than 25326001. */
+ if (!spsp(n, 5))
+ return (0);
+ if (n < 25326001ULL)
+ return (1);
+
+ /* No SPSPs to bases 2,3,5,7 less than 3215031751. */
+ if (!spsp(n, 7))
+ return (0);
+ if (n < 3215031751ULL)
+ return (1);
+
+ /*
+ * Values from:
+ * G. Jaeschke, On strong pseudoprimes to several bases,
+ * Math. Comp. 61(204):915-926, 1993.
+ */
+
+ /* No SPSPs to bases 2,3,5,7,11 less than 2152302898747. */
+ if (!spsp(n, 11))
+ return (0);
+ if (n < 2152302898747ULL)
+ return (1);
+
+ /* No SPSPs to bases 2,3,5,7,11,13 less than 3474749660383. */
+ if (!spsp(n, 13))
+ return (0);
+ if (n < 3474749660383ULL)
+ return (1);
+
+ /* No SPSPs to bases 2,3,5,7,11,13,17 less than 341550071728321. */
+ if (!spsp(n, 17))
+ return (0);
+ if (n < 341550071728321ULL)
+ return (1);
+
+ /* No SPSPs to bases 2,3,5,7,11,13,17,19 less than 341550071728321. */
+ if (!spsp(n, 19))
+ return (0);
+ if (n < 341550071728321ULL)
+ return (1);
+
+ /*
+ * Value from:
+ * Y. Jiang and Y. Deng, Strong pseudoprimes to the first eight prime
+ * bases, Math. Comp. 83(290):2915-2924, 2014.
+ */
+
+ /* No SPSPs to bases 2..23 less than 3825123056546413051. */
+ if (!spsp(n, 23))
+ return (0);
+ if (n < 3825123056546413051)
+ return (1);
+
+ /* We can't handle values larger than this. */
+ assert(n <= SPSPMAX);
+
+ /* UNREACHABLE */
+ return (0);
+}
diff --git a/lib/libnv/nv.3 b/lib/libnv/nv.3
index 63c8e8b..29ba744 100644
--- a/lib/libnv/nv.3
+++ b/lib/libnv/nv.3
@@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 21, 2014
+.Dd September 25, 2014
.Dt NV 3
.Os
.Sh NAME
@@ -150,6 +150,8 @@
.Fn nvlist_get_descriptor "const nvlist_t *nvl" "const char *name"
.Ft "const void *"
.Fn nvlist_get_binary "const nvlist_t *nvl" "const char *name" "size_t *sizep"
+.Ft "const nvlist_t *"
+.Fn nvlist_get_parent "const nvlist_t *nvl"
.\"
.Ft bool
.Fn nvlist_take_bool "nvlist_t *nvl" "const char *name"
@@ -437,6 +439,10 @@ extension, which allows to provide default value for a missing element.
The nvlist must not be in error state.
.Pp
The
+.Fn nvlist_get_parent
+function allows to obtain the parent nvlist from the nested nvlist.
+.Pp
+The
.Fn nvlist_take_bool ,
.Fn nvlist_take_number ,
.Fn nvlist_take_string ,
diff --git a/lib/libproc/Makefile b/lib/libproc/Makefile
index dafe10d..d665dc4 100644
--- a/lib/libproc/Makefile
+++ b/lib/libproc/Makefile
@@ -29,4 +29,8 @@ SHLIB_MAJOR= 2
MAN=
+.if ${MK_TESTS} != "no"
+SUBDIR+= tests
+.endif
+
.include <bsd.lib.mk>
diff --git a/lib/libproc/proc_sym.c b/lib/libproc/proc_sym.c
index aa879ec..f5301e6 100644
--- a/lib/libproc/proc_sym.c
+++ b/lib/libproc/proc_sym.c
@@ -26,20 +26,20 @@
* 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$
*/
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#include <sys/types.h>
#include <sys/user.h>
#include <assert.h>
#include <err.h>
-#include <stdio.h>
+#include <fcntl.h>
#include <libgen.h>
-#include <string.h>
+#include <stdio.h>
#include <stdlib.h>
-#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <libutil.h>
@@ -228,22 +228,56 @@ proc_addr2map(struct proc_handle *p, uintptr_t addr)
return (NULL);
}
+/*
+ * Look up the symbol at addr, returning a copy of the symbol and its name.
+ */
+static int
+lookup_addr(Elf *e, Elf_Scn *scn, u_long stridx, uintptr_t off, uintptr_t addr,
+ const char **name, GElf_Sym *symcopy)
+{
+ GElf_Sym sym;
+ Elf_Data *data;
+ const char *s;
+ uint64_t rsym;
+ int i;
+
+ if ((data = elf_getdata(scn, NULL)) == NULL) {
+ DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
+ return (1);
+ }
+ for (i = 0; gelf_getsym(data, i, &sym) != NULL; i++) {
+ rsym = off + sym.st_value;
+ if (addr >= rsym && addr < rsym + sym.st_size) {
+ s = elf_strptr(e, stridx, sym.st_name);
+ if (s != NULL) {
+ *name = s;
+ memcpy(symcopy, &sym, sizeof(*symcopy));
+ /*
+ * DTrace expects the st_value to contain
+ * only the address relative to the start of
+ * the function.
+ */
+ symcopy->st_value = rsym;
+ return (0);
+ }
+ }
+ }
+ return (1);
+}
+
int
proc_addr2sym(struct proc_handle *p, uintptr_t addr, char *name,
size_t namesz, GElf_Sym *symcopy)
{
+ GElf_Ehdr ehdr;
+ GElf_Shdr shdr;
Elf *e;
Elf_Scn *scn, *dynsymscn = NULL, *symtabscn = NULL;
- Elf_Data *data;
- GElf_Shdr shdr;
- GElf_Sym sym;
- GElf_Ehdr ehdr;
- int fd, error = -1;
- size_t i;
- uint64_t rsym;
prmap_t *map;
- char *s;
- unsigned long symtabstridx = 0, dynsymstridx = 0;
+ const char *s;
+ uintptr_t off;
+ u_long symtabstridx = 0, dynsymstridx = 0;
+ int fd, error = -1;
if ((map = proc_addr2map(p, addr)) == NULL)
return (-1);
@@ -259,6 +293,7 @@ proc_addr2sym(struct proc_handle *p, uintptr_t addr, char *name,
DPRINTFX("ERROR: gelf_getehdr() failed: %s", elf_errmsg(-1));
goto err2;
}
+
/*
* Find the index of the STRTAB and SYMTAB sections to locate
* symbol names.
@@ -275,80 +310,25 @@ proc_addr2sym(struct proc_handle *p, uintptr_t addr, char *name,
dynsymscn = scn;
dynsymstridx = shdr.sh_link;
break;
- default:
- break;
}
}
+
+ off = ehdr.e_type == ET_EXEC ? 0 : map->pr_vaddr;
+
/*
- * Iterate over the Dynamic Symbols table to find the symbol.
- * Then look up the string name in STRTAB (.dynstr)
- */
- if ((data = elf_getdata(dynsymscn, NULL)) == NULL) {
- DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
- goto symtab;
- }
- i = 0;
- while (gelf_getsym(data, i++, &sym) != NULL) {
- /*
- * Calculate the address mapped to the virtual memory
- * by rtld.
- */
- if (ehdr.e_type != ET_EXEC)
- rsym = map->pr_vaddr + sym.st_value;
- else
- rsym = sym.st_value;
- if (addr >= rsym && addr < rsym + sym.st_size) {
- s = elf_strptr(e, dynsymstridx, sym.st_name);
- if (s) {
- demangle(s, name, namesz);
- memcpy(symcopy, &sym, sizeof(sym));
- /*
- * DTrace expects the st_value to contain
- * only the address relative to the start of
- * the function.
- */
- symcopy->st_value = rsym;
- error = 0;
- goto out;
- }
- }
- }
-symtab:
- /*
- * Iterate over the Symbols Table to find the symbol.
- * Then look up the string name in STRTAB (.dynstr)
+ * First look up the symbol in the dynsymtab, and fall back to the
+ * symtab if the lookup fails.
*/
- if ((data = elf_getdata(symtabscn, NULL)) == NULL) {
- DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
- goto err2;
- }
- i = 0;
- while (gelf_getsym(data, i++, &sym) != NULL) {
- /*
- * Calculate the address mapped to the virtual memory
- * by rtld.
- */
- if (ehdr.e_type != ET_EXEC)
- rsym = map->pr_vaddr + sym.st_value;
- else
- rsym = sym.st_value;
- if (addr >= rsym && addr < rsym + sym.st_size) {
- s = elf_strptr(e, symtabstridx, sym.st_name);
- if (s) {
- demangle(s, name, namesz);
- memcpy(symcopy, &sym, sizeof(sym));
- /*
- * DTrace expects the st_value to contain
- * only the address relative to the start of
- * the function.
- */
- symcopy->st_value = rsym;
- error = 0;
- goto out;
- }
- }
- }
+ error = lookup_addr(e, dynsymscn, dynsymstridx, off, addr, &s, symcopy);
+ if (error == 0)
+ goto out;
+
+ error = lookup_addr(e, symtabscn, symtabstridx, off, addr, &s, symcopy);
+ if (error == 0)
+ goto out;
+
out:
+ demangle(s, name, namesz);
err2:
elf_end(e);
err1:
@@ -363,7 +343,7 @@ proc_name2map(struct proc_handle *p, const char *name)
{
size_t i;
int cnt;
- prmap_t *map;
+ prmap_t *map = NULL;
char tmppath[MAXPATHLEN];
struct kinfo_vmentry *kves, *kve;
rd_loadobj_t *rdl;
@@ -382,30 +362,52 @@ proc_name2map(struct proc_handle *p, const char *name)
basename_r(kve->kve_path, tmppath);
if (strcmp(tmppath, name) == 0) {
map = proc_addr2map(p, kve->kve_start);
- free(kves);
- return (map);
+ break;
}
}
free(kves);
- return (NULL);
- }
- if ((name == NULL || strcmp(name, "a.out") == 0) &&
- p->rdexec != NULL) {
+ } else
+ for (i = 0; i < p->nobjs; i++) {
+ rdl = &p->rdobjs[i];
+ basename_r(rdl->rdl_path, tmppath);
+ if (strcmp(tmppath, name) == 0) {
+ if ((map = malloc(sizeof(*map))) == NULL)
+ return (NULL);
+ proc_rdl2prmap(rdl, map);
+ break;
+ }
+ }
+
+ if (map == NULL && strcmp(name, "a.out") == 0 && p->rdexec != NULL)
map = proc_addr2map(p, p->rdexec->rdl_saddr);
- return (map);
+
+ return (map);
+}
+
+/*
+ * Look up the symbol with the given name and return a copy of it.
+ */
+static int
+lookup_name(Elf *e, Elf_Scn *scn, u_long stridx, const char *symbol,
+ GElf_Sym *symcopy)
+{
+ GElf_Sym sym;
+ Elf_Data *data;
+ char *s;
+ int i;
+
+ if ((data = elf_getdata(scn, NULL)) == NULL) {
+ DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
+ return (1);
}
- for (i = 0; i < p->nobjs; i++) {
- rdl = &p->rdobjs[i];
- basename_r(rdl->rdl_path, tmppath);
- if (strcmp(tmppath, name) == 0) {
- if ((map = malloc(sizeof(*map))) == NULL)
- return (NULL);
- proc_rdl2prmap(rdl, map);
- return (map);
+ for (i = 0; gelf_getsym(data, i, &sym) != NULL; i++) {
+ s = elf_strptr(e, stridx, sym.st_name);
+ if (s != NULL && strcmp(s, symbol) == 0) {
+ memcpy(symcopy, &sym, sizeof(*symcopy));
+ return (0);
}
}
-
- return (NULL);
+ return (1);
}
int
@@ -414,15 +416,12 @@ proc_name2sym(struct proc_handle *p, const char *object, const char *symbol,
{
Elf *e;
Elf_Scn *scn, *dynsymscn = NULL, *symtabscn = NULL;
- Elf_Data *data;
GElf_Shdr shdr;
- GElf_Sym sym;
GElf_Ehdr ehdr;
- int fd, error = -1;
- size_t i;
prmap_t *map;
- char *s;
- unsigned long symtabstridx = 0, dynsymstridx = 0;
+ uintptr_t off;
+ u_long symtabstridx = 0, dynsymstridx = 0;
+ int fd, error = -1;
if ((map = proc_name2map(p, object)) == NULL) {
DPRINTFX("ERROR: couldn't find object %s", object);
@@ -456,46 +455,25 @@ proc_name2sym(struct proc_handle *p, const char *object, const char *symbol,
dynsymscn = scn;
dynsymstridx = shdr.sh_link;
break;
- default:
- break;
- }
- }
- /*
- * Iterate over the Dynamic Symbols table to find the symbol.
- * Then look up the string name in STRTAB (.dynstr)
- */
- if ((data = elf_getdata(dynsymscn, NULL))) {
- i = 0;
- while (gelf_getsym(data, i++, &sym) != NULL) {
- s = elf_strptr(e, dynsymstridx, sym.st_name);
- if (s && strcmp(s, symbol) == 0) {
- memcpy(symcopy, &sym, sizeof(sym));
- if (ehdr.e_type != ET_EXEC)
- symcopy->st_value += map->pr_vaddr;
- error = 0;
- goto out;
- }
}
}
+
/*
- * Iterate over the Symbols Table to find the symbol.
- * Then look up the string name in STRTAB (.dynstr)
+ * First look up the symbol in the dynsymtab, and fall back to the
+ * symtab if the lookup fails.
*/
- if ((data = elf_getdata(symtabscn, NULL))) {
- i = 0;
- while (gelf_getsym(data, i++, &sym) != NULL) {
- s = elf_strptr(e, symtabstridx, sym.st_name);
- if (s && strcmp(s, symbol) == 0) {
- memcpy(symcopy, &sym, sizeof(sym));
- if (ehdr.e_type != ET_EXEC)
- symcopy->st_value += map->pr_vaddr;
- error = 0;
- goto out;
- }
- }
- }
+ error = lookup_name(e, dynsymscn, dynsymstridx, symbol, symcopy);
+ if (error == 0)
+ goto out;
+
+ error = lookup_name(e, symtabscn, symtabstridx, symbol, symcopy);
+ if (error == 0)
+ goto out;
+
out:
- DPRINTFX("found addr 0x%lx for %s", symcopy->st_value, symbol);
+ off = ehdr.e_type == ET_EXEC ? 0 : map->pr_vaddr;
+ symcopy->st_value += off;
+
err2:
elf_end(e);
err1:
@@ -506,7 +484,6 @@ err0:
return (error);
}
-
int
proc_iter_symbyaddr(struct proc_handle *p, const char *object, int which,
int mask, proc_sym_f *func, void *cd)
@@ -543,7 +520,7 @@ proc_iter_symbyaddr(struct proc_handle *p, const char *object, int which,
scn = NULL;
while ((scn = elf_nextscn(e, scn)) != NULL) {
gelf_getshdr(scn, &shdr);
- if (which == PR_SYMTAB &&
+ if (which == PR_SYMTAB &&
shdr.sh_type == SHT_SYMTAB) {
foundscn = scn;
break;
@@ -560,8 +537,7 @@ proc_iter_symbyaddr(struct proc_handle *p, const char *object, int which,
DPRINTFX("ERROR: elf_getdata() failed: %s", elf_errmsg(-1));
goto err2;
}
- i = 0;
- while (gelf_getsym(data, i++, &sym) != NULL) {
+ for (i = 0; gelf_getsym(data, i, &sym) != NULL; i++) {
if (GELF_ST_BIND(sym.st_info) == STB_LOCAL &&
(mask & BIND_LOCAL) == 0)
continue;
diff --git a/lib/libproc/test/Makefile b/lib/libproc/test/Makefile
deleted file mode 100644
index e4d33f8..0000000
--- a/lib/libproc/test/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-# $FreeBSD$
-
-SUBDIR= t1-bkpt t2-name2map t3-name2sym
-
-.include <bsd.subdir.mk>
diff --git a/lib/libproc/test/t1-bkpt/Makefile b/lib/libproc/test/t1-bkpt/Makefile
deleted file mode 100644
index eb5b37f..0000000
--- a/lib/libproc/test/t1-bkpt/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# $FreeBSD$
-
-PROG= t1-bkpt
-
-SRCS= t1-bkpt.c
-
-LDADD= -lproc -lelf -lrtld_db -lutil
-DPADD= ${LIBPROC} ${LIBELF}
-
-MAN=
-
-.include <bsd.prog.mk>
diff --git a/lib/libproc/test/t1-bkpt/t1-bkpt.c b/lib/libproc/test/t1-bkpt/t1-bkpt.c
deleted file mode 100644
index 1cd4d17..0000000
--- a/lib/libproc/test/t1-bkpt/t1-bkpt.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2010 The FreeBSD Foundation
- * All rights reserved.
- *
- * This software was developed by Rui Paulo under sponsorship from the
- * FreeBSD Foundation.
- *
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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$
- */
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include <assert.h>
-#include <stdio.h>
-#include <string.h>
-#include <libproc.h>
-
-int __noinline
-t1_bkpt_t()
-{
- printf("TEST OK\n");
-}
-
-int
-t1_bkpt_d()
-{
- struct proc_handle *phdl;
- char *targv[] = { "t1-bkpt-t", NULL};
- unsigned long saved;
-
- proc_create("./t1-bkpt", targv, NULL, NULL, &phdl);
- assert(proc_bkptset(phdl, (uintptr_t)t1_bkpt_t, &saved) == 0);
- proc_continue(phdl);
- assert(proc_wstatus(phdl) == PS_STOP);
- proc_bkptexec(phdl, saved);
- proc_continue(phdl);
- proc_wstatus(phdl);
- proc_free(phdl);
-}
-
-
-int
-main(int argc, char **argv)
-{
- if (!strcmp(argv[0], "t1-bkpt-t"))
- t1_bkpt_t();
- else
- t1_bkpt_d();
-}
-
diff --git a/lib/libproc/test/t2-name2map/Makefile b/lib/libproc/test/t2-name2map/Makefile
deleted file mode 100644
index 9002acc..0000000
--- a/lib/libproc/test/t2-name2map/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# $FreeBSD$
-
-PROG= t2-name2map
-
-SRCS= t2-name2map.c
-
-LDADD= -lproc -lelf -lrtld_db -lutil
-DPADD= ${LIBPROC} ${LIBELF}
-
-MAN=
-
-.include <bsd.prog.mk>
diff --git a/lib/libproc/test/t3-name2sym/Makefile b/lib/libproc/test/t3-name2sym/Makefile
deleted file mode 100644
index 68e23c6..0000000
--- a/lib/libproc/test/t3-name2sym/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# $FreeBSD$
-
-PROG= t3-name2sym
-
-SRCS= t3-name2sym.c
-
-LDADD= -lproc -lelf -lrtld_db -lutil
-DPADD= ${LIBPROC} ${LIBELF}
-
-MAN=
-
-.include <bsd.prog.mk>
diff --git a/lib/libproc/test/t3-name2sym/t3-name2sym.c b/lib/libproc/test/t3-name2sym/t3-name2sym.c
deleted file mode 100644
index 0be8653..0000000
--- a/lib/libproc/test/t3-name2sym/t3-name2sym.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2010 The FreeBSD Foundation
- * All rights reserved.
- *
- * This software was developed by Rui Paulo under sponsorship from the
- * FreeBSD Foundation.
- *
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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$
- */
-#include <sys/types.h>
-#include <assert.h>
-#include <stdio.h>
-#include <libproc.h>
-#include <gelf.h>
-#include <string.h>
-
-int
-main(int argc, char *argv[])
-{
- prmap_t *map = NULL;
- struct proc_handle *phdl;
- GElf_Sym sym;
-
- proc_create("./t3-name2sym", argv, NULL, NULL, &phdl);
- memset(&sym, 0, sizeof(sym));
- assert(proc_name2sym(phdl, "ld-elf.so.1", "r_debug_state", &sym) == 0);
- printf("0x%lx\n", sym.st_value);
- assert(proc_name2sym(phdl, "t3-name2sym", "main", &sym) == 0);
- printf("0x%lx\n", sym.st_value);
-}
diff --git a/lib/libproc/tests/Makefile b/lib/libproc/tests/Makefile
new file mode 100644
index 0000000..1f98467
--- /dev/null
+++ b/lib/libproc/tests/Makefile
@@ -0,0 +1,21 @@
+# $FreeBSD$
+
+TESTSDIR= ${TESTSBASE}/lib/libproc
+
+ATF_TESTS_C+= proc_test
+
+PROGS= target_prog
+SRCS_target_prog= target_prog.c
+BINDIR_target_prog= ${TESTSDIR}
+
+LDADD+= -lelf -lproc -lrtld_db -lutil
+DPADD+= ${LIBELF} ${LIBPROC} ${LIBRTLD_DB} ${LIBUTIL}
+
+# Ensure that symbols aren't stripped from the test program, as they're needed
+# for testing symbol lookup.
+STRIP=
+
+MAN=
+WARNS?= 6
+
+.include <bsd.test.mk>
diff --git a/lib/libproc/tests/proc_test.c b/lib/libproc/tests/proc_test.c
new file mode 100644
index 0000000..60f1f04
--- /dev/null
+++ b/lib/libproc/tests/proc_test.c
@@ -0,0 +1,347 @@
+/*-
+ * Copyright (c) 2014 Mark Johnston <markj@FreeBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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$");
+
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <libgen.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <atf-c.h>
+#include <libelf.h>
+#include <libproc.h>
+
+static const char *aout_object = "a.out";
+static const char *ldelf_object = "ld-elf.so.1";
+static const char *target_prog_file = "target_prog";
+
+/*
+ * Run the test program. If the sig parameter is set to true, the test program
+ * will deliver SIGUSR1 to itself during execution.
+ */
+static struct proc_handle *
+start_prog(const struct atf_tc *tc, bool sig)
+{
+ char *argv[3];
+ struct proc_handle *phdl;
+ int error;
+
+ asprintf(&argv[0], "%s/%s", atf_tc_get_config_var(tc, "srcdir"),
+ target_prog_file);
+ ATF_REQUIRE(argv[0] != NULL);
+
+ if (sig) {
+ argv[1] = strdup("-s");
+ argv[2] = NULL;
+ } else {
+ argv[1] = NULL;
+ }
+
+ error = proc_create(argv[0], argv, NULL, NULL, &phdl);
+ ATF_REQUIRE_EQ_MSG(error, 0, "failed to run '%s'", target_prog_file);
+ ATF_REQUIRE(phdl != NULL);
+
+ free(argv[0]);
+ free(argv[1]);
+
+ return (phdl);
+}
+
+static void
+set_bkpt(struct proc_handle *phdl, uintptr_t addr, u_long *saved)
+{
+ int error;
+
+ error = proc_bkptset(phdl, addr, saved);
+ ATF_REQUIRE_EQ_MSG(error, 0, "failed to set breakpoint at 0x%jx",
+ (uintmax_t)addr);
+}
+
+static void
+remove_bkpt(struct proc_handle *phdl, uintptr_t addr, u_long val)
+{
+ int error;
+
+ error = proc_bkptdel(phdl, addr, val);
+ ATF_REQUIRE_EQ_MSG(error, 0,
+ "failed to delete breakpoint at 0x%jx", (uintmax_t)addr);
+
+ error = proc_regset(phdl, REG_PC, addr);
+ ATF_REQUIRE_EQ_MSG(error, 0, "failed to reset program counter");
+}
+
+/*
+ * Wait for the specified process to hit a breakpoint at the specified symbol.
+ */
+static void
+verify_bkpt(struct proc_handle *phdl, GElf_Sym *sym, const char *symname,
+ const char *mapname)
+{
+ char mapbname[MAXPATHLEN], *name;
+ GElf_Sym tsym;
+ prmap_t *map;
+ size_t namesz;
+ u_long addr;
+ int error, state;
+
+ state = proc_wstatus(phdl);
+ ATF_REQUIRE_EQ_MSG(state, PS_STOP, "process has state %d", state);
+
+ /* Get the program counter and decrement it. */
+ error = proc_regget(phdl, REG_PC, &addr);
+ ATF_REQUIRE_EQ_MSG(error, 0, "failed to obtain PC for '%s'",
+ target_prog_file);
+ proc_bkptregadj(&addr);
+
+ /*
+ * Make sure the PC matches the expected value obtained from the symbol
+ * definition we looked up earlier.
+ */
+ ATF_CHECK_EQ_MSG(addr, sym->st_value,
+ "program counter 0x%lx doesn't match expected value 0x%jx",
+ addr, (uintmax_t)sym->st_value);
+
+ /*
+ * Ensure we can look up the r_debug_state symbol using its starting
+ * address and that the resulting symbol matches the one we found using
+ * a name lookup.
+ */
+ namesz = strlen(symname) + 1;
+ name = malloc(namesz);
+ ATF_REQUIRE(name != NULL);
+
+ error = proc_addr2sym(phdl, addr, name, namesz, &tsym);
+ ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up symbol at 0x%lx", addr);
+ ATF_REQUIRE_EQ(memcmp(sym, &tsym, sizeof(*sym)), 0);
+ ATF_REQUIRE_EQ(strcmp(symname, name), 0);
+ free(name);
+
+ map = proc_addr2map(phdl, addr);
+ ATF_REQUIRE_MSG(map != NULL, "failed to look up map for address 0x%lx",
+ addr);
+ basename_r(map->pr_mapname, mapbname);
+ ATF_REQUIRE_EQ_MSG(strcmp(mapname, mapbname), 0,
+ "expected map name '%s' doesn't match '%s'", mapname, mapbname);
+}
+
+ATF_TC(map_alias_obj2map);
+ATF_TC_HEAD(map_alias_obj2map, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Callers are supposed to be able to use \"a.out\" as an alias for "
+ "the program executable. Make sure that proc_obj2map() handles "
+ "this properly.");
+}
+ATF_TC_BODY(map_alias_obj2map, tc)
+{
+ struct proc_handle *phdl;
+ prmap_t *map1, *map2;
+
+ phdl = start_prog(tc, false);
+
+ /* Initialize the rtld_db handle. */
+ (void)proc_rdagent(phdl);
+
+ /* Ensure that "target_prog" and "a.out" return the same map. */
+ map1 = proc_obj2map(phdl, target_prog_file);
+ ATF_REQUIRE_MSG(map1 != NULL, "failed to look up map for '%s'",
+ target_prog_file);
+ map2 = proc_obj2map(phdl, aout_object);
+ ATF_REQUIRE_MSG(map2 != NULL, "failed to look up map for '%s'",
+ aout_object);
+ ATF_CHECK_EQ(strcmp(map1->pr_mapname, map2->pr_mapname), 0);
+
+ ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");
+
+ proc_free(phdl);
+}
+
+ATF_TC(map_alias_name2map);
+ATF_TC_HEAD(map_alias_name2map, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Callers are supposed to be able to use \"a.out\" as an alias for "
+ "the program executable. Make sure that proc_name2map() handles "
+ "this properly.");
+}
+ATF_TC_BODY(map_alias_name2map, tc)
+{
+ struct proc_handle *phdl;
+ prmap_t *map1, *map2;
+
+ phdl = start_prog(tc, false);
+
+ /* Initialize the rtld_db handle. */
+ (void)proc_rdagent(phdl);
+
+ /* Ensure that "target_prog" and "a.out" return the same map. */
+ map1 = proc_name2map(phdl, target_prog_file);
+ ATF_REQUIRE_MSG(map1 != NULL, "failed to look up map for '%s'",
+ target_prog_file);
+ map2 = proc_name2map(phdl, aout_object);
+ ATF_REQUIRE_MSG(map2 != NULL, "failed to look up map for '%s'",
+ aout_object);
+ ATF_CHECK_EQ(strcmp(map1->pr_mapname, map2->pr_mapname), 0);
+
+ ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");
+
+ proc_free(phdl);
+}
+
+ATF_TC(map_alias_name2sym);
+ATF_TC_HEAD(map_alias_name2sym, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Callers are supposed to be able to use \"a.out\" as an alias for "
+ "the program executable. Make sure that proc_name2sym() handles "
+ "this properly.");
+}
+ATF_TC_BODY(map_alias_name2sym, tc)
+{
+ GElf_Sym sym1, sym2;
+ struct proc_handle *phdl;
+ int error;
+
+ phdl = start_prog(tc, false);
+
+ /* Initialize the rtld_db handle. */
+ (void)proc_rdagent(phdl);
+
+ /*
+ * Make sure that "target_prog:main" and "a.out:main" return the same
+ * symbol.
+ */
+ error = proc_name2sym(phdl, target_prog_file, "main", &sym1);
+ ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'main' via %s",
+ target_prog_file);
+ error = proc_name2sym(phdl, aout_object, "main", &sym2);
+ ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'main' via %s",
+ aout_object);
+
+ ATF_CHECK_EQ(memcmp(&sym1, &sym2, sizeof(sym1)), 0);
+
+ ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");
+
+ proc_free(phdl);
+}
+
+ATF_TC(symbol_lookup);
+ATF_TC_HEAD(symbol_lookup, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Look up a couple of well-known symbols in the test program, place "
+ "breakpoints on them, and verify that we hit the breakpoints. Also "
+ "make sure that we can use the breakpoint address to look up the "
+ "corresponding symbol.");
+}
+ATF_TC_BODY(symbol_lookup, tc)
+{
+ GElf_Sym main_sym, r_debug_state_sym;
+ struct proc_handle *phdl;
+ u_long saved;
+ int error;
+
+ phdl = start_prog(tc, false);
+
+ error = proc_name2sym(phdl, target_prog_file, "main", &main_sym);
+ ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'main'");
+
+ error = proc_name2sym(phdl, ldelf_object, "r_debug_state",
+ &r_debug_state_sym);
+ ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'r_debug_state'");
+
+ set_bkpt(phdl, r_debug_state_sym.st_value, &saved);
+ ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");
+ verify_bkpt(phdl, &r_debug_state_sym, "r_debug_state", ldelf_object);
+ remove_bkpt(phdl, r_debug_state_sym.st_value, saved);
+
+ set_bkpt(phdl, main_sym.st_value, &saved);
+ ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");
+ verify_bkpt(phdl, &main_sym, "main", target_prog_file);
+ remove_bkpt(phdl, main_sym.st_value, saved);
+
+ ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");
+
+ proc_free(phdl);
+}
+
+ATF_TC(signal_forward);
+ATF_TC_HEAD(signal_forward, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Run the test program in a mode which causes it to send a signal "
+ "to itself. Make sure that we intercept the signal and that "
+ "proc_continue() forwards it to the process.");
+}
+ATF_TC_BODY(signal_forward, tc)
+{
+ struct proc_handle *phdl;
+ int state, status;
+
+ phdl = start_prog(tc, true);
+ ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");
+
+ /* The process should have been interrupted by a signal. */
+ state = proc_wstatus(phdl);
+ ATF_REQUIRE_EQ_MSG(state, PS_STOP, "process has unexpected state %d",
+ state);
+
+ /* Continue execution and allow the signal to be delivered. */
+ ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution");
+
+ /*
+ * Make sure the process exited with status 0. If it didn't receive the
+ * SIGUSR1 that it sent to itself, it'll exit with a non-zero exit
+ * status, causing the test to fail.
+ */
+ state = proc_wstatus(phdl);
+ ATF_REQUIRE_EQ_MSG(state, PS_UNDEAD, "process has unexpected state %d",
+ state);
+
+ status = proc_getwstat(phdl);
+ ATF_REQUIRE(status >= 0);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE_EQ(WEXITSTATUS(status), 0);
+
+ proc_free(phdl);
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, map_alias_obj2map);
+ ATF_TP_ADD_TC(tp, map_alias_name2map);
+ ATF_TP_ADD_TC(tp, map_alias_name2sym);
+ ATF_TP_ADD_TC(tp, symbol_lookup);
+ ATF_TP_ADD_TC(tp, signal_forward);
+
+ return (atf_no_error());
+}
diff --git a/lib/libproc/test/t2-name2map/t2-name2map.c b/lib/libproc/tests/target_prog.c
index 825963d..1edf0de 100644
--- a/lib/libproc/test/t2-name2map/t2-name2map.c
+++ b/lib/libproc/tests/target_prog.c
@@ -1,46 +1,59 @@
-/*
- * Copyright (c) 2010 The FreeBSD Foundation
- * All rights reserved.
- *
- * This software was developed by Rui Paulo under sponsorship from the
- * FreeBSD Foundation.
- *
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+/*-
+ * Copyright (c) 2014 Mark Johnston <markj@FreeBSD.org>
+ * All rights reserved.
*
- * $FreeBSD$
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/types.h>
-#include <assert.h>
-#include <stdio.h>
-#include <libproc.h>
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <err.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static volatile sig_atomic_t saw;
+
+static void
+usr1(int sig __unused)
+{
+
+ saw = 1;
+}
int
-main(int argc, char *argv[])
+main(int argc, char **argv)
{
- prmap_t *map = NULL;
- struct proc_handle *phdl;
- proc_create("./t2-name2map", argv, NULL, NULL, &phdl);
- map = proc_name2map(phdl, "ld-elf.so.1");
- assert(map);
+ if (argc == 1)
+ return (EXIT_SUCCESS);
+ if (argc == 2 && strcmp(argv[1], "-s") == 0) {
+ if (signal(SIGUSR1, usr1) == SIG_ERR)
+ err(1, "signal");
+ if (kill(getpid(), SIGUSR1) != 0)
+ err(1, "kill");
+ return (saw == 1 ? EXIT_SUCCESS : EXIT_FAILURE);
+ }
+ return (EXIT_FAILURE);
}
diff --git a/lib/libthr/libthr.3 b/lib/libthr/libthr.3
index bfbebec..4b636ce 100644
--- a/lib/libthr/libthr.3
+++ b/lib/libthr/libthr.3
@@ -1,6 +1,11 @@
.\" Copyright (c) 2005 Robert N. M. Watson
+.\" Copyright (c) 2014 The FreeBSD Foundation, Inc.
.\" All rights reserved.
.\"
+.\" Part of this documentation was written by
+.\" Konstantin Belousov <kib@FreeBSD.org> under sponsorship
+.\" from the FreeBSD Foundation.
+.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
@@ -24,7 +29,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd October 19, 2007
+.Dd September 26, 2014
.Dt LIBTHR 3
.Os
.Sh NAME
@@ -45,8 +50,222 @@ has been optimized for use by applications expecting system scope thread
semantics, and can provide significant performance improvements
compared to
.Lb libkse .
+.Pp
+The library is tightly integrated with the run-time link editor
+.Xr ld-elf.so.1 1
+and
+.Lb libc ;
+all three components must be built from the same source tree.
+Mixing
+.Li libc
+and
+.Nm
+libraries from different versions of
+.Fx
+is not supported.
+The run-time linker
+.Xr ld-elf.so.1 1
+has some code to ensure backward-compatibility with older versions of
+.Nm .
+.Pp
+The man page documents the quirks and tunables of the
+.Nm .
+When linking with
+.Li -lpthread ,
+the run-time dependency
+.Li libthr.so.3
+is recorded in the produced object.
+.Sh MUTEX ACQUISITION
+A locked mutex (see
+.Xr pthread_mutex_lock 3 )
+is represented by a volatile variable of type
+.Dv lwpid_t ,
+which records the global system identifier of the thread
+owning the lock.
+.Nm
+performs a contested mutex acquisition in three stages, each of which
+is more resource-consuming than the previous.
+The first two stages are only applied for a mutex of
+.Dv PTHREAD_MUTEX_ADAPTIVE_NP
+type and
+.Dv PTHREAD_PRIO_NONE
+protocol (see
+.Xr pthread_mutexattr 3 ) .
+.Pp
+First, on SMP systems, a spin loop
+is performed, where the library attempts to acquire the lock by
+.Xr atomic 9
+operations.
+The loop count is controlled by the
+.Ev LIBPTHREAD_SPINLOOPS
+environment variable, with a default value of 2000.
+.Pp
+If the spin loop
+was unable to acquire the mutex, a yield loop
+is executed, performing the same
+.Xr atomic 9
+acquisition attempts as the spin loop,
+but each attempt is followed by a yield of the CPU time
+of the thread using the
+.Xr sched_yield 2
+syscall.
+By default, the yield loop
+is not executed.
+This is controlled by the
+.Ev LIBPTHREAD_YIELDLOOPS
+environment variable.
+.Pp
+If both the spin and yield loops
+failed to acquire the lock, the thread is taken off the CPU and
+put to sleep in the kernel with the
+.Xr umtx 2
+syscall.
+The kernel wakes up a thread and hands the ownership of the lock to
+the woken thread when the lock becomes available.
+.Sh THREAD STACKS
+Each thread is provided with a private user-mode stack area
+used by the C runtime.
+The size of the main (initial) thread stack is set by the kernel, and is
+controlled by the
+.Dv RLIMIT_STACK
+process resource limit (see
+.Xr getrlimit 2 ) .
+.Pp
+By default, the main thread's stack size is equal to the value of
+.Dv RLIMIT_STACK
+for the process.
+If the
+.Ev LIBPTHREAD_SPLITSTACK_MAIN
+environment variable is present in the process environment
+(its value does not matter),
+the main thread's stack is reduced to 4MB on 64bit architectures, and to
+2MB on 32bit architectures, when the threading library is initialized.
+The rest of the address space area which has been reserved by the
+kernel for the initial process stack is used for non-initial thread stacks
+in this case.
+The presence of the
+.Ev LIBPTHREAD_BIGSTACK_MAIN
+environment variable overrides
+.Ev LIBPTHREAD_SPLITSTACK_MAIN ;
+it is kept for backward-compatibility.
+.Pp
+The size of stacks for threads created by the process at run-time
+with the
+.Xr pthread_create 3
+call is controlled by thread attributes: see
+.Xr pthread_attr 3 ,
+in particular, the
+.Xr pthread_attr_setstacksize 3 ,
+.Xr pthread_attr_setguardsize 3
+and
+.Xr pthread_attr_setstackaddr 3
+functions.
+If no attributes for the thread stack size are specified, the default
+non-initial thread stack size is 2MB for 64bit architectures, and 1MB
+for 32bit architectures.
+.Sh RUN-TIME SETTINGS
+The following environment variables are recognized by
+.Nm
+and adjust the operation of the library at run-time:
+.Bl -tag -width LIBPTHREAD_SPLITSTACK_MAIN
+.It Ev LIBPTHREAD_BIGSTACK_MAIN
+Disables the reduction of the initial thread stack enabled by
+.Ev LIBPTHREAD_SPLITSTACK_MAIN .
+.It Ev LIBPTHREAD_SPLITSTACK_MAIN
+Causes a reduction of the initial thread stack, as described in the
+section
+.Sx THREAD STACKS .
+This was the default behaviour of
+.Nm
+before
+.Fx 11.0 .
+.It Ev LIBPTHREAD_SPINLOOPS
+The integer value of the variable overrides the default count of
+iterations in the
+.Li spin loop
+of the mutex acquisition.
+The default count is 2000, set by the
+.Dv MUTEX_ADAPTIVE_SPINS
+constant in the
+.Nm
+sources.
+.It Ev LIBPTHREAD_YIELDLOOPS
+A non-zero integer value enables the yield loop
+in the process of the mutex acquisition.
+The value is the count of loop operations.
+.It Ev LIBPTHREAD_QUEUE_FIFO
+The integer value of the variable specifies how often blocked
+threads are inserted at the head of the sleep queue, instead of its tail.
+Bigger values reduce the frequency of the FIFO discipline.
+The value must be between 0 and 255.
+.El
+.Sh INTERACTION WITH RUN-TIME LINKER
+The
+.Nm
+library must appear before
+.Li libc
+in the global order of depended objects.
+.Pp
+Loading
+.Nm
+with the
+.Xr dlopen 3
+call in the process after the program binary is activated
+is not supported, and causes miscellaneous and hard-to-diagnose misbehaviour.
+This is due to
+.Nm
+interposing several important
+.Li libc
+symbols to provide thread-safe services.
+In particular,
+.Dv errno
+and the locking stubs from
+.Li libc
+are affected.
+This requirement is currently not enforced.
+.Pp
+If the program loads any modules at run-time, and those modules may require
+threading services, the main program binary must be linked with
+.Li libpthread ,
+even if it does not require any services from the library.
+.Pp
+.Nm
+cannot be unloaded; the
+.Xr dlclose 3
+function does not perform any action when called with a handle for
+.Nm .
+One of the reasons is that the interposing of
+.Li libc
+functions cannot be undone.
+.Sh SIGNALS
+The implementation also interposes the user-installed
+.Xr signal 3
+handlers.
+This interposing is done to postpone signal delivery to threads which
+entered (libthr-internal) critical sections, where the calling
+of the user-provided signal handler is unsafe.
+An example of such a situation is owning the internal library lock.
+When a signal is delivered while the signal handler cannot be safely
+called, the call is postponed and performed until after the exit from
+the critical section.
+This should be taken into account when interpreting
+.Xr ktrace 1
+logs.
.Sh SEE ALSO
-.Xr pthread 3
+.Xr ktrace 1 ,
+.Xr ld-elf.so.1 1 ,
+.Xr getrlimit 2 ,
+.Xr umtx 2 ,
+.Xr dlclose 3 ,
+.Xr dlopen 3 ,
+.Xr errno 3 ,
+.Xr getenv 3 ,
+.Xr libc 3 ,
+.Xr pthread_attr 3 ,
+.Xr pthread_attr_setstacksize 3 ,
+.Xr pthread_create 3 ,
+.Xr signal 3 ,
+.Xr atomic 9
.Sh AUTHORS
.An -nosplit
The
diff --git a/lib/libthr/thread/thr_init.c b/lib/libthr/thread/thr_init.c
index 9bf0e29..6d6a532 100644
--- a/lib/libthr/thread/thr_init.c
+++ b/lib/libthr/thread/thr_init.c
@@ -445,7 +445,7 @@ init_private(void)
struct rlimit rlim;
size_t len;
int mib[2];
- char *env;
+ char *env, *env_bigstack, *env_splitstack;
_thr_umutex_init(&_mutex_static_lock);
_thr_umutex_init(&_cond_static_lock);
@@ -473,8 +473,9 @@ init_private(void)
len = sizeof (_usrstack);
if (sysctl(mib, 2, &_usrstack, &len, NULL, 0) == -1)
PANIC("Cannot get kern.usrstack from sysctl");
- env = getenv("LIBPTHREAD_BIGSTACK_MAIN");
- if (env != NULL) {
+ env_bigstack = getenv("LIBPTHREAD_BIGSTACK_MAIN");
+ env_splitstack = getenv("LIBPTHREAD_SPLITSTACK_MAIN");
+ if (env_bigstack != NULL || env_splitstack == NULL) {
if (getrlimit(RLIMIT_STACK, &rlim) == -1)
PANIC("Cannot get stack rlimit");
_thr_stack_initial = rlim.rlim_cur;
diff --git a/lib/msun/src/e_lgamma_r.c b/lib/msun/src/e_lgamma_r.c
index a6fd691..58940b3 100644
--- a/lib/msun/src/e_lgamma_r.c
+++ b/lib/msun/src/e_lgamma_r.c
@@ -1,4 +1,3 @@
-
/* @(#)e_lgamma_r.c 1.3 95/01/18 */
/*
* ====================================================
@@ -6,10 +5,9 @@
*
* Developed at SunSoft, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
+ * software is freely granted, provided that this notice
* is preserved.
* ====================================================
- *
*/
#include <sys/cdefs.h>
diff --git a/release/doc/en_US.ISO8859-1/hardware/article.xml b/release/doc/en_US.ISO8859-1/hardware/article.xml
index 8919eef..444e3ca 100644
--- a/release/doc/en_US.ISO8859-1/hardware/article.xml
+++ b/release/doc/en_US.ISO8859-1/hardware/article.xml
@@ -837,6 +837,8 @@
&hwlist.igb;
+ &hwlist.ipheth;
+
&hwlist.ixgb;
&hwlist.ixgbe;
@@ -885,6 +887,8 @@
&hwlist.sk;
+ &hwlist.smsc;
+
&hwlist.sn;
&hwlist.snc;
diff --git a/sbin/ping6/Makefile b/sbin/ping6/Makefile
index 89e7fbe..7f3a008 100644
--- a/sbin/ping6/Makefile
+++ b/sbin/ping6/Makefile
@@ -4,7 +4,7 @@ PROG= ping6
MAN= ping6.8
CFLAGS+=-DIPSEC -DKAME_SCOPEID -DUSE_RFC2292BIS \
- -DHAVE_POLL_H -DHAVE_ARC4RANDOM
+ -DHAVE_ARC4RANDOM
WARNS?= 2
BINOWN= root
diff --git a/sbin/ping6/ping6.c b/sbin/ping6/ping6.c
index b963de1..14f689d 100644
--- a/sbin/ping6/ping6.c
+++ b/sbin/ping6/ping6.c
@@ -125,10 +125,8 @@ __FBSDID("$FreeBSD$");
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sysexits.h>
#include <unistd.h>
-#ifdef HAVE_POLL_H
-#include <poll.h>
-#endif
#ifdef IPSEC
#include <netipsec/ah.h>
@@ -207,7 +205,6 @@ u_int options;
int mx_dup_ck = MAX_DUP_CHK;
char rcvd_tbl[MAX_DUP_CHK / 8];
-struct addrinfo *res = NULL;
struct sockaddr_in6 dst; /* who to ping6 */
struct sockaddr_in6 src; /* src addr of this packet */
socklen_t srclen;
@@ -223,12 +220,6 @@ u_int8_t nonce[8]; /* nonce field for node information */
int hoplimit = -1; /* hoplimit */
int pathmtu = 0; /* path MTU for the destination. 0 = unspec. */
u_char *packet = NULL;
-#ifdef HAVE_POLL_H
-struct pollfd fdmaskp[1];
-#else
-fd_set *fdmaskp = NULL;
-int fdmasks;
-#endif
/* counters */
long nmissedmax; /* max value of ntransmitted - nreceived - 1 */
@@ -236,7 +227,7 @@ long npackets; /* max packets to transmit */
long nreceived; /* # of packets we got back */
long nrepeats; /* number of duplicates */
long ntransmitted; /* sequence # for outbound packets = #sent */
-struct timeval interval = {1, 0}; /* interval between packets */
+int interval = 1000; /* interval between packets in ms */
/* timing */
int timing; /* flag to do timing */
@@ -253,7 +244,6 @@ struct msghdr smsghdr;
struct iovec smsgiov;
char *scmsg = 0;
-volatile sig_atomic_t seenalrm;
volatile sig_atomic_t seenint;
#ifdef SIGINFO
volatile sig_atomic_t seeninfo;
@@ -265,7 +255,6 @@ int get_hoplim(struct msghdr *);
int get_pathmtu(struct msghdr *);
struct in6_pktinfo *get_rcvpktinfo(struct msghdr *);
void onsignal(int);
-void retransmit(void);
void onint(int);
size_t pingerlen(void);
int pinger(void);
@@ -293,19 +282,15 @@ void usage(void);
int
main(int argc, char *argv[])
{
- struct itimerval itimer;
- struct sockaddr_in6 from;
+ struct timeval last, intvl;
+ struct sockaddr_in6 from, *sin6;
#ifndef HAVE_ARC4RANDOM
struct timeval seed;
#endif
-#ifdef HAVE_POLL_H
- int timeout;
-#else
- struct timeval timeout, *tv;
-#endif
- struct addrinfo hints;
+ struct addrinfo hints, *res;
+ struct sigaction si_sa;
int cc, i;
- int ch, hold, packlen, preload, optval, ret_ga;
+ int almost_done, ch, hold, packlen, preload, optval, error;
int nig_oldmcprefix = -1;
u_char *datap;
char *e, *target, *ifname = NULL, *gateway = NULL;
@@ -326,7 +311,7 @@ main(int argc, char *argv[])
char *policy_in = NULL;
char *policy_out = NULL;
#endif
- double intval;
+ double t;
size_t rthlen;
#ifdef IPV6_USE_MIN_MTU
int mflag = 0;
@@ -450,22 +435,22 @@ main(int argc, char *argv[])
#endif
break;
case 'i': /* wait between sending packets */
- intval = strtod(optarg, &e);
+ t = strtod(optarg, &e);
if (*optarg == '\0' || *e != '\0')
errx(1, "illegal timing interval %s", optarg);
- if (intval < 1 && getuid()) {
+ if (t < 1 && getuid()) {
errx(1, "%s: only root may use interval < 1s",
strerror(EPERM));
}
- interval.tv_sec = (long)intval;
- interval.tv_usec =
- (long)((intval - interval.tv_sec) * 1000000);
- if (interval.tv_sec < 0)
+ intvl.tv_sec = (long)t;
+ intvl.tv_usec =
+ (long)((t - intvl.tv_sec) * 1000000);
+ if (intvl.tv_sec < 0)
errx(1, "illegal timing interval %s", optarg);
/* less than 1/hz does not make sense */
- if (interval.tv_sec == 0 && interval.tv_usec < 1) {
+ if (intvl.tv_sec == 0 && intvl.tv_usec < 1) {
warnx("too small interval, raised to .000001");
- interval.tv_usec = 1;
+ intvl.tv_usec = 1;
}
options |= F_INTERVAL;
break;
@@ -516,10 +501,10 @@ main(int argc, char *argv[])
hints.ai_socktype = SOCK_RAW;
hints.ai_protocol = IPPROTO_ICMPV6;
- ret_ga = getaddrinfo(optarg, NULL, &hints, &res);
- if (ret_ga) {
+ error = getaddrinfo(optarg, NULL, &hints, &res);
+ if (error) {
errx(1, "invalid source address: %s",
- gai_strerror(ret_ga));
+ gai_strerror(error));
}
/*
* res->ai_family must be AF_INET6 and res->ai_addrlen
@@ -622,9 +607,9 @@ main(int argc, char *argv[])
hints.ai_socktype = SOCK_RAW;
hints.ai_protocol = IPPROTO_ICMPV6;
- ret_ga = getaddrinfo(target, NULL, &hints, &res);
- if (ret_ga)
- errx(1, "%s", gai_strerror(ret_ga));
+ error = getaddrinfo(target, NULL, &hints, &res);
+ if (error)
+ errx(1, "%s", gai_strerror(error));
if (res->ai_canonname)
hostname = res->ai_canonname;
else
@@ -647,28 +632,25 @@ main(int argc, char *argv[])
/* set the gateway (next hop) if specified */
if (gateway) {
- struct addrinfo ghints, *gres;
- int error;
-
- memset(&ghints, 0, sizeof(ghints));
- ghints.ai_family = AF_INET6;
- ghints.ai_socktype = SOCK_RAW;
- ghints.ai_protocol = IPPROTO_ICMPV6;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = SOCK_RAW;
+ hints.ai_protocol = IPPROTO_ICMPV6;
- error = getaddrinfo(gateway, NULL, &hints, &gres);
+ error = getaddrinfo(gateway, NULL, &hints, &res);
if (error) {
errx(1, "getaddrinfo for the gateway %s: %s",
gateway, gai_strerror(error));
}
- if (gres->ai_next && (options & F_VERBOSE))
+ if (res->ai_next && (options & F_VERBOSE))
warnx("gateway resolves to multiple addresses");
if (setsockopt(s, IPPROTO_IPV6, IPV6_NEXTHOP,
- gres->ai_addr, gres->ai_addrlen)) {
+ res->ai_addr, res->ai_addrlen)) {
err(1, "setsockopt(IPV6_NEXTHOP)");
}
- freeaddrinfo(gres);
+ freeaddrinfo(res);
}
/*
@@ -898,7 +880,7 @@ main(int argc, char *argv[])
}
if (argc > 1) { /* some intermediate addrs are specified */
- int hops, error;
+ int hops;
#ifdef USE_RFC2292BIS
int rthdrlen;
#endif
@@ -920,26 +902,25 @@ main(int argc, char *argv[])
#endif /* USE_RFC2292BIS */
for (hops = 0; hops < argc - 1; hops++) {
- struct addrinfo *iaip;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET6;
if ((error = getaddrinfo(argv[hops], NULL, &hints,
- &iaip)))
+ &res)))
errx(1, "%s", gai_strerror(error));
- if (SIN6(iaip->ai_addr)->sin6_family != AF_INET6)
+ if (res->ai_addr->sa_family != AF_INET6)
errx(1,
"bad addr family of an intermediate addr");
-
+ sin6 = (struct sockaddr_in6 *)(void *)res->ai_addr;
#ifdef USE_RFC2292BIS
- if (inet6_rth_add(rthdr,
- &(SIN6(iaip->ai_addr))->sin6_addr))
+ if (inet6_rth_add(rthdr, &sin6->sin6_addr))
errx(1, "can't add an intermediate node");
#else /* old advanced API */
- if (inet6_rthdr_add(scmsgp,
- &(SIN6(iaip->ai_addr))->sin6_addr,
+ if (inet6_rthdr_add(scmsg, &sin6->sin6_addr,
IPV6_RTHDR_LOOSE))
errx(1, "can't add an intermediate node");
#endif /* USE_RFC2292BIS */
- freeaddrinfo(iaip);
+ freeaddrinfo(res);
}
#ifndef USE_RFC2292BIS
@@ -1055,58 +1036,46 @@ main(int argc, char *argv[])
printf("%s --> ", pr_addr((struct sockaddr *)&src, sizeof(src)));
printf("%s\n", pr_addr((struct sockaddr *)&dst, sizeof(dst)));
- while (preload--) /* Fire off them quickies. */
- (void)pinger();
-
- (void)signal(SIGINT, onsignal);
-#ifdef SIGINFO
- (void)signal(SIGINFO, onsignal);
-#endif
-
- if ((options & F_FLOOD) == 0) {
- (void)signal(SIGALRM, onsignal);
- itimer.it_interval = interval;
- itimer.it_value = interval;
- (void)setitimer(ITIMER_REAL, &itimer, NULL);
- if (ntransmitted == 0)
- retransmit();
+ if (preload == 0)
+ pinger();
+ else {
+ if (npackets != 0 && preload > npackets)
+ preload = npackets;
+ while (preload--)
+ pinger();
}
-
-#ifndef HAVE_POLL_H
- fdmasks = howmany(s + 1, NFDBITS) * sizeof(fd_mask);
- if ((fdmaskp = malloc(fdmasks)) == NULL)
- err(1, "malloc");
-#endif
-
- seenalrm = seenint = 0;
+ gettimeofday(&last, NULL);
+
+ sigemptyset(&si_sa.sa_mask);
+ si_sa.sa_flags = 0;
+ si_sa.sa_handler = onsignal;
+ if (sigaction(SIGINT, &si_sa, 0) == -1)
+ err(EX_OSERR, "sigaction SIGINT");
+ seenint = 0;
#ifdef SIGINFO
+ if (sigaction(SIGINFO, &si_sa, 0) == -1)
+ err(EX_OSERR, "sigaction SIGINFO");
seeninfo = 0;
#endif
+ if (options & F_FLOOD) {
+ intvl.tv_sec = 0;
+ intvl.tv_usec = 10000;
+ } else if ((options & F_INTERVAL) == 0) {
+ intvl.tv_sec = interval / 1000;
+ intvl.tv_usec = interval % 1000 * 1000;
+ }
- for (;;) {
+ almost_done = 0;
+ while (seenint == 0) {
+ struct timeval now, timeout;
struct msghdr m;
struct iovec iov[2];
+ fd_set rfds;
+ int n;
/* signal handling */
- if (seenalrm) {
- /* last packet sent, timeout reached? */
- if (npackets && ntransmitted >= npackets) {
- struct timeval zerotime = {0, 0};
- itimer.it_value = zerotime;
- itimer.it_interval = zerotime;
- (void)setitimer(ITIMER_REAL, &itimer, NULL);
- seenalrm = 0; /* clear flag */
- continue;
- }
- retransmit();
- seenalrm = 0;
- continue;
- }
- if (seenint) {
+ if (seenint)
onint(SIGINT);
- seenint = 0;
- continue;
- }
#ifdef SIGINFO
if (seeninfo) {
summary();
@@ -1114,93 +1083,104 @@ main(int argc, char *argv[])
continue;
}
#endif
-
- if (options & F_FLOOD) {
- (void)pinger();
-#ifdef HAVE_POLL_H
- timeout = 10;
-#else
- timeout.tv_sec = 0;
- timeout.tv_usec = 10000;
- tv = &timeout;
-#endif
- } else {
-#ifdef HAVE_POLL_H
- timeout = INFTIM;
-#else
- tv = NULL;
-#endif
+ FD_ZERO(&rfds);
+ FD_SET(s, &rfds);
+ gettimeofday(&now, NULL);
+ timeout.tv_sec = last.tv_sec + intvl.tv_sec - now.tv_sec;
+ timeout.tv_usec = last.tv_usec + intvl.tv_usec - now.tv_usec;
+ while (timeout.tv_usec < 0) {
+ timeout.tv_usec += 1000000;
+ timeout.tv_sec--;
}
-#ifdef HAVE_POLL_H
- fdmaskp[0].fd = s;
- fdmaskp[0].events = POLLIN;
- cc = poll(fdmaskp, 1, timeout);
-#else
- memset(fdmaskp, 0, fdmasks);
- FD_SET(s, fdmaskp);
- cc = select(s + 1, fdmaskp, NULL, NULL, tv);
-#endif
- if (cc < 0) {
- if (errno != EINTR) {
-#ifdef HAVE_POLL_H
- warn("poll");
-#else
- warn("select");
-#endif
- sleep(1);
- }
- continue;
- } else if (cc == 0)
- continue;
-
- m.msg_name = (caddr_t)&from;
- m.msg_namelen = sizeof(from);
- memset(&iov, 0, sizeof(iov));
- iov[0].iov_base = (caddr_t)packet;
- iov[0].iov_len = packlen;
- m.msg_iov = iov;
- m.msg_iovlen = 1;
- memset(cm, 0, CONTROLLEN);
- m.msg_control = (void *)cm;
- m.msg_controllen = CONTROLLEN;
-
- cc = recvmsg(s, &m, 0);
- if (cc < 0) {
- if (errno != EINTR) {
- warn("recvmsg");
- sleep(1);
- }
- continue;
- } else if (cc == 0) {
- int mtu;
+ while (timeout.tv_usec > 1000000) {
+ timeout.tv_usec -= 1000000;
+ timeout.tv_sec++;
+ }
+ if (timeout.tv_sec < 0)
+ timeout.tv_sec = timeout.tv_usec = 0;
+
+ n = select(s + 1, &rfds, NULL, NULL, &timeout);
+ if (n < 0)
+ continue; /* EINTR */
+ if (n == 1) {
+ m.msg_name = (caddr_t)&from;
+ m.msg_namelen = sizeof(from);
+ memset(&iov, 0, sizeof(iov));
+ iov[0].iov_base = (caddr_t)packet;
+ iov[0].iov_len = packlen;
+ m.msg_iov = iov;
+ m.msg_iovlen = 1;
+ memset(cm, 0, CONTROLLEN);
+ m.msg_control = (void *)cm;
+ m.msg_controllen = CONTROLLEN;
+
+ cc = recvmsg(s, &m, 0);
+ if (cc < 0) {
+ if (errno != EINTR) {
+ warn("recvmsg");
+ sleep(1);
+ }
+ continue;
+ } else if (cc == 0) {
+ int mtu;
- /*
- * receive control messages only. Process the
- * exceptions (currently the only possibility is
- * a path MTU notification.)
- */
- if ((mtu = get_pathmtu(&m)) > 0) {
- if ((options & F_VERBOSE) != 0) {
- printf("new path MTU (%d) is "
- "notified\n", mtu);
+ /*
+ * receive control messages only. Process the
+ * exceptions (currently the only possibility is
+ * a path MTU notification.)
+ */
+ if ((mtu = get_pathmtu(&m)) > 0) {
+ if ((options & F_VERBOSE) != 0) {
+ printf("new path MTU (%d) is "
+ "notified\n", mtu);
+ }
}
+ continue;
+ } else {
+ /*
+ * an ICMPv6 message (probably an echoreply)
+ * arrived.
+ */
+ pr_pack(packet, cc, &m);
}
- continue;
- } else {
+ if (((options & F_ONCE) != 0 && nreceived > 0) ||
+ (npackets > 0 && nreceived >= npackets))
+ break;
+ }
+ if (n == 0 || (options & F_FLOOD)) {
+ if (npackets == 0 || ntransmitted < npackets)
+ pinger();
+ else {
+ if (almost_done)
+ break;
+ almost_done = 1;
/*
- * an ICMPv6 message (probably an echoreply) arrived.
+ * If we're not transmitting any more packets,
+ * change the timer to wait two round-trip times
+ * if we've received any packets or ten seconds
+ * if we haven't.
*/
- pr_pack(packet, cc, &m);
- }
- if (((options & F_ONCE) != 0 && nreceived > 0) ||
- (npackets > 0 && nreceived >= npackets))
- break;
- if (ntransmitted - nreceived - 1 > nmissedmax) {
- nmissedmax = ntransmitted - nreceived - 1;
- if (options & F_MISSED)
- (void)write(STDOUT_FILENO, &BBELL, 1);
+#define MAXWAIT 10
+ intvl.tv_usec = 0;
+ if (nreceived) {
+ intvl.tv_sec = 2 * tmax / 1000;
+ if (intvl.tv_sec == 0)
+ intvl.tv_sec = 1;
+ } else
+ intvl.tv_sec = MAXWAIT;
+ }
+ gettimeofday(&last, NULL);
+ if (ntransmitted - nreceived - 1 > nmissedmax) {
+ nmissedmax = ntransmitted - nreceived - 1;
+ if (options & F_MISSED)
+ (void)write(STDOUT_FILENO, &BBELL, 1);
+ }
}
}
+ sigemptyset(&si_sa.sa_mask);
+ si_sa.sa_flags = 0;
+ si_sa.sa_handler = SIG_IGN;
+ sigaction(SIGINT, &si_sa, 0);
summary();
if (res != NULL)
@@ -1209,11 +1189,6 @@ main(int argc, char *argv[])
if(packet != NULL)
free(packet);
-#ifndef HAVE_POLL_H
- if(fdmaskp != NULL)
- free(fdmaskp);
-#endif
-
exit(nreceived == 0 ? 2 : 0);
}
@@ -1222,9 +1197,6 @@ onsignal(int sig)
{
switch (sig) {
- case SIGALRM:
- seenalrm++;
- break;
case SIGINT:
seenint++;
break;
@@ -1237,38 +1209,6 @@ onsignal(int sig)
}
/*
- * retransmit --
- * This routine transmits another ping6.
- */
-void
-retransmit(void)
-{
- struct itimerval itimer;
-
- if (pinger() == 0)
- return;
-
- /*
- * If we're not transmitting any more packets, change the timer
- * to wait two round-trip times if we've received any packets or
- * ten seconds if we haven't.
- */
-#define MAXWAIT 10
- if (nreceived) {
- itimer.it_value.tv_sec = 2 * tmax / 1000;
- if (itimer.it_value.tv_sec == 0)
- itimer.it_value.tv_sec = 1;
- } else
- itimer.it_value.tv_sec = MAXWAIT;
- itimer.it_interval.tv_sec = 0;
- itimer.it_interval.tv_usec = 0;
- itimer.it_value.tv_usec = 0;
-
- (void)signal(SIGALRM, onsignal);
- (void)setitimer(ITIMER_REAL, &itimer, NULL);
-}
-
-/*
* pinger --
* Compose and transmit an ICMP ECHO REQUEST packet. The IP packet
* will be added on by the kernel. The ID field is our UNIX process ID,
@@ -2247,24 +2187,12 @@ tvsub(struct timeval *out, struct timeval *in)
void
onint(int notused __unused)
{
- summary();
-
- if (res != NULL)
- freeaddrinfo(res);
-
- if(packet != NULL)
- free(packet);
-
-#ifndef HAVE_POLL_H
- if(fdmaskp != NULL)
- free(fdmaskp);
-#endif
-
- (void)signal(SIGINT, SIG_DFL);
- (void)kill(getpid(), SIGINT);
-
- /* NOTREACHED */
- exit(1);
+ /*
+ * When doing reverse DNS lookups, the seenint flag might not
+ * be noticed for a while. Just exit if we get a second SIGINT.
+ */
+ if ((options & F_HOSTNAME) && seenint != 0)
+ _exit(nreceived ? 0 : 2);
}
/*
diff --git a/sbin/routed/defs.h b/sbin/routed/defs.h
index c42cd80..a31d6f5 100644
--- a/sbin/routed/defs.h
+++ b/sbin/routed/defs.h
@@ -462,6 +462,7 @@ extern int ridhosts; /* 1=reduce host routes */
extern int mhome; /* 1=want multi-homed host route */
extern int advertise_mhome; /* 1=must continue advertising it */
extern int auth_ok; /* 1=ignore auth if we do not care */
+extern int insecure; /* Reply to special queries or not */
extern struct timeval clk; /* system clock's idea of time */
extern struct timeval epoch; /* system clock when started */
diff --git a/sbin/routed/input.c b/sbin/routed/input.c
index 8f8eefc..901c4f3 100644
--- a/sbin/routed/input.c
+++ b/sbin/routed/input.c
@@ -289,8 +289,19 @@ input(struct sockaddr_in *from, /* received from this IP address */
* with all we know.
*/
if (from->sin_port != htons(RIP_PORT)) {
- supply(from, aifp, OUT_QUERY, 0,
- rip->rip_vers, ap != 0);
+ /*
+ * insecure: query from non-router node
+ * > 1: allow from distant node
+ * > 0: allow from neighbor node
+ * == 0: deny
+ */
+ if ((aifp != NULL && insecure > 0) ||
+ (aifp == NULL && insecure > 1))
+ supply(from, aifp, OUT_QUERY, 0,
+ rip->rip_vers, ap != 0);
+ else
+ trace_pkt("Warning: "
+ "possible attack detected");
return;
}
diff --git a/sbin/routed/main.c b/sbin/routed/main.c
index 1658d2e..5ebd7ec 100644
--- a/sbin/routed/main.c
+++ b/sbin/routed/main.c
@@ -68,6 +68,7 @@ int ridhosts; /* 1=reduce host routes */
int mhome; /* 1=want multi-homed host route */
int advertise_mhome; /* 1=must continue advertising it */
int auth_ok = 1; /* 1=ignore auth if we do not care */
+int insecure; /* Reply to special queries or not */
struct timeval epoch; /* when started */
struct timeval clk;
@@ -136,8 +137,11 @@ main(int argc,
(void)gethostname(myname, sizeof(myname)-1);
(void)gethost(myname, &myaddr);
- while ((n = getopt(argc, argv, "sqdghmAtvT:F:P:")) != -1) {
+ while ((n = getopt(argc, argv, "isqdghmAtvT:F:P:")) != -1) {
switch (n) {
+ case 'i':
+ insecure++;
+ break;
case 's':
supplier = 1;
supplier_set = 1;
diff --git a/sbin/routed/output.c b/sbin/routed/output.c
index 53eb4a5..c2ed468 100644
--- a/sbin/routed/output.c
+++ b/sbin/routed/output.c
@@ -673,8 +673,6 @@ supply(struct sockaddr_in *dst,
struct rt_entry *rt;
int def_metric;
- assert(ifp != NULL);
-
ws.state = 0;
ws.gen_limit = 1024;
diff --git a/sbin/routed/routed.8 b/sbin/routed/routed.8
index 2f8a021..ca5250b 100644
--- a/sbin/routed/routed.8
+++ b/sbin/routed/routed.8
@@ -30,7 +30,7 @@
.\" @(#)routed.8 8.2 (Berkeley) 12/11/93
.\" $FreeBSD$
.\"
-.Dd June 1, 1996
+.Dd August 26, 2014
.Dt ROUTED 8
.Os
.Sh NAME
@@ -39,7 +39,7 @@
.Nd network RIP and router discovery routing daemon
.Sh SYNOPSIS
.Nm
-.Op Fl sqdghmpAtv
+.Op Fl isqdghmpAtv
.Op Fl T Ar tracefile
.Oo
.Fl F
@@ -250,6 +250,20 @@ to infer the netmask used by the remote system when RIPv1 is used.
.Pp
The following options are available:
.Bl -tag -width indent
+.It Fl i
+allow
+.Nm
+to accept a RIP request from non-router node.
+When specified once,
+.Nm
+replies to a route information query from neighbor nodes.
+When specified twice,
+it replies to a query from remote nodes in addition.
+.Xr rtquery 8
+utility can be used to send a request.
+.Pp
+This feature is disabled by default because of a risk of reflection attack
+though it is useful for debugging purpose.
.It Fl s
force
.Nm
diff --git a/sbin/sysctl/sysctl.c b/sbin/sysctl/sysctl.c
index 20d5952..a6ea9f9 100644
--- a/sbin/sysctl/sysctl.c
+++ b/sbin/sysctl/sysctl.c
@@ -57,6 +57,7 @@ static const char rcsid[] =
#include <machine/pc/bios.h>
#endif
+#include <assert.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
@@ -78,9 +79,33 @@ static int parsefile(const char *);
static int parse(const char *, int);
static int show_var(int *, int);
static int sysctl_all(int *oid, int len);
-static int name2oid(char *, int *);
+static int name2oid(const char *, int *);
-static int set_IK(const char *, int *);
+static int strIKtoi(const char *, char **);
+
+static int ctl_sign[CTLTYPE+1] = {
+ [CTLTYPE_INT] = 1,
+ [CTLTYPE_LONG] = 1,
+ [CTLTYPE_S64] = 1,
+};
+
+static int ctl_size[CTLTYPE+1] = {
+ [CTLTYPE_INT] = sizeof(int),
+ [CTLTYPE_UINT] = sizeof(u_int),
+ [CTLTYPE_LONG] = sizeof(long),
+ [CTLTYPE_ULONG] = sizeof(u_long),
+ [CTLTYPE_S64] = sizeof(int64_t),
+ [CTLTYPE_U64] = sizeof(uint64_t),
+};
+
+static const char *ctl_typename[CTLTYPE+1] = {
+ [CTLTYPE_INT] = "integer",
+ [CTLTYPE_UINT] = "unsigned integer",
+ [CTLTYPE_LONG] = "long integer",
+ [CTLTYPE_ULONG] = "unsigned long",
+ [CTLTYPE_S64] = "int64_t",
+ [CTLTYPE_U64] = "uint64_t",
+};
static void
usage(void)
@@ -191,7 +216,8 @@ static int
parse(const char *string, int lineno)
{
int len, i, j;
- void *newval = 0;
+ const void *newval;
+ const char *newvalstr = NULL;
int intval;
unsigned int uintval;
long longval;
@@ -200,7 +226,7 @@ parse(const char *string, int lineno)
int64_t i64val;
uint64_t u64val;
int mib[CTL_MAXNAME];
- char *cp, *bufp, buf[BUFSIZ], *endptr, fmt[BUFSIZ], line[BUFSIZ];
+ char *cp, *bufp, buf[BUFSIZ], *endptr = NULL, fmt[BUFSIZ], line[BUFSIZ];
u_int kind;
if (lineno)
@@ -230,7 +256,7 @@ parse(const char *string, int lineno)
cp[strlen(cp) - 1] = '\0';
cp++;
}
- newval = cp;
+ newvalstr = cp;
newsize = strlen(cp);
}
len = name2oid(bufp, mib);
@@ -254,7 +280,7 @@ parse(const char *string, int lineno)
exit(1);
}
- if (newval == NULL || dflag) {
+ if (newvalstr == NULL || dflag) {
if ((kind & CTLTYPE) == CTLTYPE_NODE) {
if (dflag) {
i = show_var(mib, len);
@@ -282,97 +308,77 @@ parse(const char *string, int lineno)
return (1);
}
- if ((kind & CTLTYPE) == CTLTYPE_INT ||
- (kind & CTLTYPE) == CTLTYPE_UINT ||
- (kind & CTLTYPE) == CTLTYPE_LONG ||
- (kind & CTLTYPE) == CTLTYPE_ULONG ||
- (kind & CTLTYPE) == CTLTYPE_S64 ||
- (kind & CTLTYPE) == CTLTYPE_U64) {
- if (strlen(newval) == 0) {
+ switch (kind & CTLTYPE) {
+ case CTLTYPE_INT:
+ case CTLTYPE_UINT:
+ case CTLTYPE_LONG:
+ case CTLTYPE_ULONG:
+ case CTLTYPE_S64:
+ case CTLTYPE_U64:
+ if (strlen(newvalstr) == 0) {
warnx("empty numeric value");
return (1);
}
+ /* FALLTHROUGH */
+ case CTLTYPE_STRING:
+ break;
+ default:
+ warnx("oid '%s' is type %d,"
+ " cannot set that%s", bufp,
+ kind & CTLTYPE, line);
+ return (1);
}
+ errno = 0;
+
switch (kind & CTLTYPE) {
case CTLTYPE_INT:
- if (strcmp(fmt, "IK") == 0) {
- if (!set_IK(newval, &intval)) {
- warnx("invalid value '%s'%s",
- (char *)newval, line);
- return (1);
- }
- } else {
- intval = (int)strtol(newval, &endptr,
+ if (strcmp(fmt, "IK") == 0)
+ intval = strIKtoi(newvalstr, &endptr);
+ else
+ intval = (int)strtol(newvalstr, &endptr,
0);
- if (endptr == newval || *endptr != '\0') {
- warnx("invalid integer '%s'%s",
- (char *)newval, line);
- return (1);
- }
- }
newval = &intval;
newsize = sizeof(intval);
break;
case CTLTYPE_UINT:
- uintval = (int) strtoul(newval, &endptr, 0);
- if (endptr == newval || *endptr != '\0') {
- warnx("invalid unsigned integer '%s'%s",
- (char *)newval, line);
- return (1);
- }
+ uintval = (int) strtoul(newvalstr, &endptr, 0);
newval = &uintval;
newsize = sizeof(uintval);
break;
case CTLTYPE_LONG:
- longval = strtol(newval, &endptr, 0);
- if (endptr == newval || *endptr != '\0') {
- warnx("invalid long integer '%s'%s",
- (char *)newval, line);
- return (1);
- }
+ longval = strtol(newvalstr, &endptr, 0);
newval = &longval;
newsize = sizeof(longval);
break;
case CTLTYPE_ULONG:
- ulongval = strtoul(newval, &endptr, 0);
- if (endptr == newval || *endptr != '\0') {
- warnx("invalid unsigned long integer"
- " '%s'%s", (char *)newval, line);
- return (1);
- }
+ ulongval = strtoul(newvalstr, &endptr, 0);
newval = &ulongval;
newsize = sizeof(ulongval);
break;
case CTLTYPE_STRING:
+ newval = newvalstr;
break;
case CTLTYPE_S64:
- i64val = strtoimax(newval, &endptr, 0);
- if (endptr == newval || *endptr != '\0') {
- warnx("invalid int64_t '%s'%s",
- (char *)newval, line);
- return (1);
- }
+ i64val = strtoimax(newvalstr, &endptr, 0);
newval = &i64val;
newsize = sizeof(i64val);
break;
case CTLTYPE_U64:
- u64val = strtoumax(newval, &endptr, 0);
- if (endptr == newval || *endptr != '\0') {
- warnx("invalid uint64_t '%s'%s",
- (char *)newval, line);
- return (1);
- }
+ u64val = strtoumax(newvalstr, &endptr, 0);
newval = &u64val;
newsize = sizeof(u64val);
break;
- case CTLTYPE_OPAQUE:
- /* FALLTHROUGH */
default:
- warnx("oid '%s' is type %d,"
- " cannot set that%s", bufp,
- kind & CTLTYPE, line);
- return (1);
+ /* NOTREACHED */
+ abort();
+ }
+
+ if (errno != 0 || endptr == newvalstr ||
+ (endptr != NULL && *endptr != '\0')) {
+ warnx("invalid %s '%s'%s", ctl_typename[kind & CTLTYPE],
+ newvalstr, line);
+ return (1);
}
i = show_var(mib, len);
@@ -657,30 +663,35 @@ S_bios_smap_xattr(size_t l2, void *p)
#endif
static int
-set_IK(const char *str, int *val)
+strIKtoi(const char *str, char **endptrp)
{
+ int kelv;
float temp;
- int len, kelv;
+ size_t len;
const char *p;
- char *endptr;
- if ((len = strlen(str)) == 0)
- return (0);
+ assert(errno == 0);
+
+ len = strlen(str);
+ /* caller already checked this */
+ assert(len > 0);
+
p = &str[len - 1];
if (*p == 'C' || *p == 'F') {
- temp = strtof(str, &endptr);
- if (endptr == str || endptr != p)
- return (0);
- if (*p == 'F')
- temp = (temp - 32) * 5 / 9;
- kelv = temp * 10 + 2732;
+ temp = strtof(str, endptrp);
+ if (*endptrp != str && *endptrp == p && errno != 0) {
+ if (*p == 'F')
+ temp = (temp - 32) * 5 / 9;
+ return (temp * 10 + 2732);
+ }
} else {
- kelv = (int)strtol(str, &endptr, 10);
- if (endptr == str || *endptr != '\0')
- return (0);
+ kelv = (int)strtol(str, endptrp, 10);
+ if (*endptrp != str && *endptrp == p && errno != 0)
+ return (kelv);
}
- *val = kelv;
- return (1);
+
+ errno = ERANGE;
+ return (0);
}
/*
@@ -693,7 +704,7 @@ set_IK(const char *str, int *val)
*/
static int
-name2oid(char *name, int *oidp)
+name2oid(const char *name, int *oidp)
{
int oid[2];
int i;
@@ -735,21 +746,6 @@ oidfmt(int *oid, int len, char *fmt, u_int *kind)
return (0);
}
-static int ctl_sign[CTLTYPE+1] = {
- [CTLTYPE_INT] = 1,
- [CTLTYPE_LONG] = 1,
- [CTLTYPE_S64] = 1,
-};
-
-static int ctl_size[CTLTYPE+1] = {
- [CTLTYPE_INT] = sizeof(int),
- [CTLTYPE_UINT] = sizeof(u_int),
- [CTLTYPE_LONG] = sizeof(long),
- [CTLTYPE_ULONG] = sizeof(u_long),
- [CTLTYPE_S64] = sizeof(int64_t),
- [CTLTYPE_U64] = sizeof(int64_t),
-};
-
/*
* This formats and outputs the value of one variable
*
diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile
index 0a6621a..8200441 100644
--- a/share/man/man4/Makefile
+++ b/share/man/man4/Makefile
@@ -200,6 +200,7 @@ MAN= aac.4 \
ip.4 \
ip6.4 \
ipfirewall.4 \
+ ipheth.4 \
${_ipmi.4} \
ips.4 \
ipsec.4 \
@@ -438,6 +439,7 @@ MAN= aac.4 \
smb.4 \
smbus.4 \
smp.4 \
+ smsc.4 \
sn.4 \
snd_ad1816.4 \
snd_als4000.4 \
@@ -658,6 +660,7 @@ MLINKS+=ip.4 rawip.4
MLINKS+=ipfirewall.4 ipaccounting.4 \
ipfirewall.4 ipacct.4 \
ipfirewall.4 ipfw.4
+MLINKS+=ipheth.4 if_ipheth.4
MLINKS+=ipw.4 if_ipw.4
MLINKS+=iwi.4 if_iwi.4
MLINKS+=iwn.4 if_iwn.4
@@ -712,6 +715,7 @@ MLINKS+=sge.4 if_sge.4
MLINKS+=sis.4 if_sis.4
MLINKS+=sk.4 if_sk.4
MLINKS+=smp.4 SMP.4
+MLINKS+=smsc.4 if_smsc.4
MLINKS+=sn.4 if_sn.4
MLINKS+=snd_envy24.4 snd_ak452x.4
MLINKS+=snd_sbc.4 snd_sb16.4 \
diff --git a/share/man/man4/ada.4 b/share/man/man4/ada.4
index 433a547..10897cf 100644
--- a/share/man/man4/ada.4
+++ b/share/man/man4/ada.4
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 21, 2014
+.Dd September 21, 2014
.Dt ADA 4
.Os
.Sh NAME
@@ -123,11 +123,13 @@ seconds.
This variable determines whether to spin-down disks when shutting down.
Set to 1 to enable spin-down, 0 to disable.
The default is currently enabled.
+.It Va kern.cam.ada.read_ahead
+.It Va kern.cam.ada. Ns Ar X Ns Va .read_ahead
.It Va kern.cam.ada.write_cache
.It Va kern.cam.ada. Ns Ar X Ns Va .write_cache
.Pp
-These variables determine whether device write cache should be enabled
-globally or per-device or disabled.
+These variables determine whether device read-ahead and write caches
+should be enabled globally or per-device or disabled.
Set to 1 to enable write cache, 0 to disable, -1 to leave it as-is.
Values modified at runtime take effect only after device reset
.Pq using the reset subcommand of Xr camcontrol 8 .
diff --git a/share/man/man4/cdce.4 b/share/man/man4/cdce.4
index d38a969..fa921b6 100644
--- a/share/man/man4/cdce.4
+++ b/share/man/man4/cdce.4
@@ -28,7 +28,7 @@
.\" $NetBSD: cdce.4,v 1.4 2004/12/08 18:35:56 peter Exp $
.\" $FreeBSD$
.\"
-.Dd September 17, 2005
+.Dd September 25, 2014
.Dt CDCE 4
.Os
.Sh NAME
@@ -114,9 +114,10 @@ is running low on mbufs.
.Sh SEE ALSO
.Xr arp 4 ,
.Xr intro 4 ,
+.Xr ipheth 4 ,
.Xr netintro 4 ,
+.Xr urndis 4 ,
.Xr usb 4 ,
-.\" .Xr hostname.if 5 ,
.Xr ifconfig 8
.Rs
.%T "Universal Serial Bus Class Definitions for Communication Devices"
diff --git a/share/man/man4/ipheth.4 b/share/man/man4/ipheth.4
new file mode 100644
index 0000000..4c21976
--- /dev/null
+++ b/share/man/man4/ipheth.4
@@ -0,0 +1,93 @@
+.\" Copyright (c) 2014 Gavin Atkinson
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\"
+.\" - Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" - 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.
+.\"
+.\" 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 HOLDERS 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 September 25, 2014
+.Dt IPHETH 4
+.Os
+.Sh NAME
+.Nm ipheth
+.Nd "USB Apple iPhone/iPad Ethernet driver"
+.Sh SYNOPSIS
+To load the driver as a module at boot time, place the
+following line in
+.Xr loader.conf 5 :
+.Bd -literal -offset indent
+if_ipheth_load="YES"
+.Ed
+.Pp
+Alternatively, to compile this driver into the kernel, place the
+following lines in your kernel configuration file:
+.Bd -ragged -offset indent
+.Cd "device uhci"
+.Cd "device ohci"
+.Cd "device usb"
+.Cd "device ipheth"
+.Ed
+.Sh DESCRIPTION
+The
+.Nm
+driver provides support for network access through Apple
+iPhone and iPad devices, often referred to as USB tethering.
+.Pp
+.Nm
+should work with any Apple iPhone or iPad device.
+In most cases this must be explicitly enabled on the device first.
+.Pp
+For more information on configuring this device, see
+.Xr ifconfig 8 .
+.Sh HARDWARE
+The following devices are supported by the
+.Nm
+driver:
+.Pp
+.Bl -bullet -compact
+.It
+Apple iPhone (all models)
+.It
+Apple iPad (all models)
+.El
+.Sh SEE ALSO
+.Xr arp 4 ,
+.Xr cdce 4 ,
+.Xr intro 4 ,
+.Xr netintro 4 ,
+.Xr urndis 4 ,
+.Xr usb 4 ,
+.Xr ifconfig 8
+.Sh HISTORY
+The
+.Nm
+device driver first appeared in
+.Fx 8.2 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+driver was written by
+.An Hans Petter Selasky Aq Mt hselasky@FreeBSD.org .
diff --git a/share/man/man4/man4.arm/Makefile b/share/man/man4/man4.arm/Makefile
index 73e7bf7..0e5b576 100644
--- a/share/man/man4/man4.arm/Makefile
+++ b/share/man/man4/man4.arm/Makefile
@@ -1,11 +1,13 @@
# $FreeBSD$
-MAN= devcfg.4 \
+MAN= cgem.4 \
+ devcfg.4 \
mge.4 \
npe.4 \
ti_adc.4
-MLINKS= mge.4 if_mge.4
+MLINKS= cgem.4 if_cgem.4
+MLINKS+= mge.4 if_mge.4
MLINKS+=npe.4 if_npe.4
MANSUBDIR=/arm
diff --git a/share/man/man4/man4.arm/cgem.4 b/share/man/man4/man4.arm/cgem.4
new file mode 100644
index 0000000..8af1b2a
--- /dev/null
+++ b/share/man/man4/man4.arm/cgem.4
@@ -0,0 +1,297 @@
+.\"
+.\" Copyright (c) 2014 Thomas Skibo <thomasskibo@yahoo.com>
+.\" 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. The name of the author may not be used to endorse or promote products
+.\" derived from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 August 26, 2014
+.Dt CGEM 4
+.Os
+.Sh NAME
+.Nm cgem
+.Nd "Cadence GEM Gigabit Ethernet driver"
+.Sh SYNOPSIS
+To compile this driver into the kernel,
+place the following lines in your
+kernel configuration file:
+.Bd -ragged -offset indent
+.Cd "device ether"
+.Cd "device miibus"
+.Cd "device cgem"
+.Ed
+.Sh DESCRIPTION
+The
+.Nm
+driver provides support for the Cadence GEM (Gigabit Ethernet MAC).
+The Cadence GEM is used in some SoC (System on a Chip) devices such as
+the Xilinx Zynq-7000 and the Atmel SAMA5D3.
+.Pp
+The
+.Nm
+driver supports the following media types:
+.Bl -tag -width ".Cm 10baseT/UTP"
+.It Cm autoselect
+Enable autoselection of the media type and options.
+The user can manually override
+the autoselected mode using
+.Xr ifconfig 8
+or by adding media options to
+.Xr rc.conf 5 .
+.It Cm 10baseT/UTP
+Set 10Mbps operation.
+The
+.Xr ifconfig 8
+.Cm mediaopt
+option can also be used to select either
+.Cm full-duplex
+or
+.Cm half-duplex
+modes.
+.It Cm 100baseTX
+Set 100Mbps (Fast Ethernet) operation.
+The
+.Xr ifconfig 8
+.Cm mediaopt
+option can also be used to select either
+.Cm full-duplex
+or
+.Cm half-duplex
+modes.
+.It Cm 1000baseT
+Set 1000Mbps (Gigabit Ethernet) operation over twisted pair.
+The GEM supports 1000Mbps in
+.Cm full-duplex
+mode only.
+.El
+.Pp
+The
+.Nm
+driver supports the following media options:
+.Bl -tag -width ".Cm full-duplex"
+.It Cm full-duplex
+Force full-duplex operation.
+.It Cm half-duplex
+Force half-duplex operation.
+.El
+.Pp
+The driver provides support for TCP/UDP/IP checksum offloading (although
+disabled by default).
+The device and driver also support 1536-byte frames for VLANs (vlanmtu).
+.Sh SYSCTL VARIABLES
+The following variables are available as both
+.Xr sysctl 8
+variables and
+.Xr loader 8
+tunables:
+.Bl -tag -width "xxxxxxxx"
+.It Va dev.cgem.%d.rxbufs
+The number of receive buffers allocated to the hardware.
+The default value is 256.
+The maximum value is 511.
+If this number is increased while the interface is UP, it will not
+take effect until the next packet is received.
+If this number is decreased while the interface is UP, buffers will
+not be immediately removed from the receive buffer ring but the
+number of buffers will decrease as packets are received until it
+reaches the new value.
+.It Va dev.cgem.%d.rxhangwar
+This tunable enables a work-around to recover from receive hangs.
+The default value is 1.
+Set to 0 to disable the work-around.
+.El
+.Pp
+The following read-only variables are available as
+.Xr sysctl 8
+variables:
+.Bl -tag -width "xxxxxxxx"
+.It Va dev.cgem.%d._rxoverruns
+This variable counts the number of receive packet buffer overrun interrupts.
+.It Va dev.cgem.%d._rxnobufs
+This variable counts the number of interrupts due to the GEM buffer ring
+going empty.
+.It Va dev.cgem.%d._rxdmamapfails
+This variable is the number of times bus_dmamap_load_mbuf_sg(9) failed in
+the receive path.
+.It Va dev.cgem.%d._txfull
+The number of times the GEM's transmit ring was full.
+.It Va dev.cgem.%d._txdmamapfails
+This variable is the number of times bus_dmamap_load_mbuf_sg(9) failed in
+the transmit path.
+.It Va dev.cgem.%d._txdefrags
+This variable is the number of times the driver needed to call m_defrag(9)
+because a packet queued for transmit had too many DMA segments.
+.It Va dev.cgem.%d._txdefragfails
+This variable is the number of times
+.Xr m_defrag 9
+failed.
+.It Va dev.cgem.%d.stats.*
+The following variables are useful MAC counters supplied by the hardware:
+.It Va dev.cgem.%d.stats.tx_bytes
+A 64-bit counter of the number of bytes transmitted in frames without error.
+.It Va dev.cgem.%d.stats.tx_frames
+Counter of frames transmitted without error excluding pause frames.
+.It Va dev.cgem.%d.stats.tx_frames_bcast
+Counter of broadcast frames transmitted without error excluding
+pause frames.
+.It Va dev.cgem.%d.stats.tx_frames_multi
+Counter of multicast frames transmitted without error excluding
+pause frames.
+.It Va dev.cgem.%d.stats.tx_frames_pause
+Counter of pause frames transmitted without error.
+.It Va dev.cgem.%d.stats.tx_frames_64b
+Counter of 64 byte frames transmitted without error.
+.It Va dev.cgem.%d.stats.tx_frames_65to127b
+Counter of 65 to 127 byte frames transmitted without error.
+.It Va dev.cgem.%d.stats.tx_frames_128to255b
+Counter of 128 to 255 byte frames transmitted without error.
+.It Va dev.cgem.%d.stats.tx_frames_256to511b
+Counter of 256 to 511 byte frames transmitted without error.
+.It Va dev.cgem.%d.stats.tx_frames_512to1023b
+Counter of 512 to 1023 byte frames transmitted without error.
+.It Va dev.cgem.%d.stats.tx_frames_1024to1536b
+Counter of 1024 to 1536 byte frames transmitted without error.
+.It Va dev.cgem.%d.stats.tx_under_runs
+Counter of frames not transmitted due to a transmit underrun.
+.It Va dev.cgem.%d.stats.tx_single_collisn
+Counter of frames experiencing a single collision before being successfully
+transmitted.
+.It Va dev.cgem.%d.stats.tx_multi_collisn
+Counter of frames experiencing between 2 and 15 collisions before
+being successfully transmitted.
+.It Va dev.cgem.%d.stats.tx_excsv_collisn
+Counter of frames that failed to transmit because they experienced 16
+collisions.
+.It Va dev.cgem.%d.stats.tx_late_collisn
+Counter of frames that experienced a late collision.
+.It Va dev.cgem.%d.stats.tx_deferred_frames
+Counter of frames experiencing deferral due to carrier sense being
+active on their first attempt at transmission.
+.It Va dev.cgem.%d.stats.tx_carrier_sense_errs
+Counter of frames transmitted where carrier sense was not seen during
+transmission or where carrier sense was deasserted after being asserted
+in a transmit frame without collision.
+.It Va dev.cgem.%d.stats.rx_bytes
+A 64-bit counter of bytes received without error excluding pause
+frames.
+.It Va dev.cgem.%d.stats.rx_frames
+Counter of frames received without error excluding pause frames.
+.It Va dev.cgem.%d.stats.rx_frames_bcast
+Counter of broadcast frames receive without error excluding pause frames.
+.It Va dev.cgem.%d.stats.rx_frames_multi
+Counter of multicast frames receive without error excluding pause frames.
+.It Va dev.cgem.%d.stats.rx_frames_pause
+Counter of pause frames recevied without error.
+.It Va dev.cgem.%d.stats.rx_frames_64b
+Counter of 64-byte frames received without error.
+.It Va dev.cgem.%d.stats.rx_frames_65to127b
+Counter of 65 to 127 byte frames received without error.
+.It Va dev.cgem.%d.stats.rx_frames_128to255b
+Counter of 128 to 255 byte frames received without error.
+.It Va dev.cgem.%d.stats.rx_frames_256to511b
+Counter of 256 to 511 byte frames received without error.
+.It Va dev.cgem.%d.stats.rx_frames_512to1023b
+Counter of 512 to 1023 byte frames received without error.
+.It Va dev.cgem.%d.stats.rx_frames_1024to1536b
+Counter of 1024 to 1536 byte frames received without error.
+.It Va dev.cgem.%d.stats.rx_frames_undersize
+Counter of frames received less than 64 bytes in length that
+do not also have either a CRC error or an alignment error.
+.It Va dev.cgem.%d.stats.rx_frames_oversize
+Counter of frames received exceeding 1536 bytes and do not also have either
+a CRC error or an alignment error.
+.It Va dev.cgem.%d.stats.rx_frames_jabber
+Counter of frames received exceeding 1536 bytes and also have either a CRC
+error, an alignment error, or a receive symbol error.
+.It Va dev.cgem.%d.stats.rx_frames_fcs_errs
+Counter of frames received with a bad CRC and are between 64
+and 1536 bytes.
+.It Va dev.cgem.%d.stats.rx_frames_length_errs
+Counter of frames received that are shorter than that extracted
+from the length field.
+.It Va dev.cgem.%d.stats.rx_symbol_errs
+Counter of receive symbol errors.
+.It Va dev.cgem.%d.stats.rx_align_errs
+Counter of received frames that are not an integral number of bytes.
+.It Va dev.cgem.%d.stats.rx_resource_errs
+Counter of frames successfully receive by the MAC but could not be
+copied to memory because no receive buffer was available.
+.It Va dev.cgem.%d.stats.rx_overrun_errs
+Counter of frames that are address recognized but were not copied
+to memory due to a receive overrun.
+.It Va dev.cgem.%d.stats.rx_frames_ip_hdr_csum_errs
+Counter of frames discarded due to an incorrect IP header checksum when
+checksum offloading is enabled.
+.It Va dev.cgem.%d.stats.rx_frames_tcp_csum_errs
+Counter of frames discarded due to an incorrect TCP checksum when
+checksum offloading is enabled.
+.It Va dev.cgem.%d.stats.rx_frames_udp_csum_errs
+Counter of frames discarded due to an incorrect UDP checksum when
+checksum offloading is enabled.
+.El
+.Sh BUGS
+The GEM can perform TCP/UDP/IP checksum offloading.
+However, when transmit checksum offloading is enabled, the GEM generates and
+replaces checksums for all packets it transmits.
+In a system that is forwarding packets, the device could potentially correct
+the checksum of packet that was corrupted in transit.
+For this reason, checksum offloading is disabled by default but can be
+enabled using ifconfig(8).
+.Pp
+When receive checksum offloading is enabled, the device will discard packets
+with bad TCP/UDP/IP checksums.
+The bad packets will not be counted in any
+.Xr netstat 1
+statistics. There are
+.Xr sysctl 8
+variables that count
+packets discarded by the hardware (see below).
+.Pp
+The GEM used in the Zynq-7000 has a bug such that the receiver can
+potentially freeze up under a high load. The issue is described in sec. 16.7
+"Known Issues" of the Zynq-7000 SoC Technical Reference Manual (Xilinx
+UG585 v1.7).
+The
+.Nm
+driver implements the work-around suggested in the manual.
+If the bug does not exist in other versions of this device, the
+work-around can be disabled by setting the dev.cgem.%d.rxhangwar
+.Xr sysctl 8
+variable to 0.
+.Pp
+.Sh SEE ALSO
+.Xr miibus 4 ,
+.Xr ifconfig 8
+.Rs
+.%T "Zynq-7000 SoC Technical Reference Manual (Xilinx doc UG585)"
+.%U http://www.xilinx.com/support/documentation/user_guides/\:ug585-Zynq-7000-TRM.pdf
+.Re
+.Sh HISTORY
+The
+.Nm
+device driver first appeared in
+.Fx 10.0 .
+.Sh AUTHORS
+The
+.Nm
+driver and this manual page was written by
+.An Thomas Skibo Aq Mt thomasskibo@yahoo.com .
diff --git a/share/man/man4/miibus.4 b/share/man/man4/miibus.4
index 6152095..a04e7a8 100644
--- a/share/man/man4/miibus.4
+++ b/share/man/man4/miibus.4
@@ -8,7 +8,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd January 15, 2011
+.Dd September 26, 2014
.Dt MIIBUS 4
.Os
.Sh NAME
@@ -103,6 +103,8 @@ Silicon Integrated Systems SiS190/191 Ethernet
Silicon Integrated Systems SiS 900/SiS 7016
.It Xr sk 4
SysKonnect SK-984x and SK-982x Gigabit Ethernet
+.It Xr smsc 4
+SMSC LAN9xxx USB Fast Ethernet
.It Xr ste 4
Sundance ST201 (D-Link DFE-550TX)
.It Xr stge 4
@@ -166,6 +168,7 @@ but as a result are not well behaved newbus device drivers.
.Xr sge 4 ,
.Xr sis 4 ,
.Xr sk 4 ,
+.Xr smsc 4 ,
.Xr ste 4 ,
.Xr stge 4 ,
.Xr tl 4 ,
diff --git a/share/man/man4/smsc.4 b/share/man/man4/smsc.4
new file mode 100644
index 0000000..fb37539
--- /dev/null
+++ b/share/man/man4/smsc.4
@@ -0,0 +1,91 @@
+.\" Copyright (c) 2014 Gavin Atkinson
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\"
+.\" - Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" - 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.
+.\"
+.\" 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 HOLDERS 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 September 26, 2014
+.Dt SMSC 4
+.Os
+.Sh NAME
+.Nm smsc
+.Nd "USB SMSC LAN9xxx Fast Ethernet driver"
+.Sh SYNOPSIS
+To load the driver as a module at boot time, place the
+following line in
+.Xr loader.conf 5 :
+.Bd -literal -offset indent
+if_smsc_load="YES"
+.Ed
+.Pp
+Alternatively, to compile this driver into the kernel, place the
+following lines in your kernel configuration file:
+.Bd -ragged -offset indent
+.Cd "device uhci"
+.Cd "device ohci"
+.Cd "device usb"
+.Cd "device miibus"
+.Cd "device smsc"
+.Ed
+.Sh DESCRIPTION
+The
+.Nm
+device driver provides support for USB Fast Ethernet adapters based
+on the SMSC LAN9xxx chipsets.
+.Pp
+For more information on configuring this device, see
+.Xr ifconfig 8 .
+.Sh HARDWARE
+The following devices are supported by the
+.Nm
+driver:
+.Pp
+.Bl -bullet -compact
+.It
+SMSC LAN9500, LAN9500A, LAN9505 and LAN9505A based Ethernet adapters
+.It
+SMSC LAN89530, LAN9530 and LAN9730 based Ethernet adapters
+.It
+SMSC LAN951x Ethernet adapters with integrated USB hub
+.El
+.Sh SEE ALSO
+.Xr arp 4 ,
+.Xr intro 4 ,
+.Xr miibus 4 ,
+.Xr netintro 4 ,
+.Xr usb 4 ,
+.Xr ifconfig 8
+.Sh HISTORY
+The
+.Nm
+device driver first appeared in
+.Fx 10.0 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+driver was written by
+.An Ben Gray Aq Mt bgray@FreeBSD.org .
diff --git a/share/man/man4/urndis.4 b/share/man/man4/urndis.4
index 9d126bd..33acec5 100644
--- a/share/man/man4/urndis.4
+++ b/share/man/man4/urndis.4
@@ -29,7 +29,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd April 21, 2014
+.Dd September 25, 2014
.Dt URNDIS 4
.Os
.Sh NAME
@@ -70,6 +70,8 @@ For more information on configuring this device, see
.Xr ifconfig 8 .
.Sh SEE ALSO
.Xr arp 4 ,
+.Xr cdce 4 ,
+.Xr ipheth 4 ,
.Xr netintro 4 ,
.Xr usb 4 ,
.Xr ifconfig 8
diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile
index 0c25e6a..9e8297aa 100644
--- a/share/man/man9/Makefile
+++ b/share/man/man9/Makefile
@@ -391,13 +391,21 @@ MLINKS= unr.9 alloc_unr.9 \
unr.9 delete_unrhdr.9 \
unr.9 free_unr.9 \
unr.9 new_unrhdr.9
+MLINKS+=accept_filter.9 accept_filt_add.9 \
+ accept_filter.9 accept_filt_del.9 \
+ accept_filter.9 accept_filt_generic_mod_event.9 \
+ accept_filter.9 accept_filt_get.9
MLINKS+=alq.9 ALQ.9 \
alq.9 alq_close.9 \
alq.9 alq_flush.9 \
alq.9 alq_get.9 \
+ alq.9 alq_getn.9 \
alq.9 alq_open.9 \
+ alq.9 alq_open_flags.9 \
alq.9 alq_post.9 \
- alq.9 alq_write.9
+ alq.9 alq_post_flags.9 \
+ alq.9 alq_write.9 \
+ alq.9 alq_writen.9
MLINKS+=altq.9 ALTQ.9
MLINKS+=atomic.9 atomic_add.9 \
atomic.9 atomic_clear.9 \
@@ -407,7 +415,9 @@ MLINKS+=atomic.9 atomic_add.9 \
atomic.9 atomic_readandclear.9 \
atomic.9 atomic_set.9 \
atomic.9 atomic_store.9 \
- atomic.9 atomic_subtract.9
+ atomic.9 atomic_subtract.9 \
+ atomic.9 atomic_swap.9 \
+ atomic.9 atomic_testandset.9
MLINKS+=bpf.9 bpfattach.9 \
bpf.9 bpfattach2.9 \
bpf.9 bpfdetach.9 \
@@ -435,6 +445,8 @@ MLINKS+=bus_dma.9 busdma.9 \
bus_dma.9 bus_dmamap_create.9 \
bus_dma.9 bus_dmamap_destroy.9 \
bus_dma.9 bus_dmamap_load.9 \
+ bus_dma.9 bus_dmamap_load_bio.9 \
+ bus_dma.9 bus_dmamap_load_ccb.9 \
bus_dma.9 bus_dmamap_load_mbuf.9 \
bus_dma.9 bus_dmamap_load_mbuf_sg.9 \
bus_dma.9 bus_dmamap_load_uio.9 \
@@ -449,7 +461,8 @@ MLINKS+=BUS_READ_IVAR.9 BUS_WRITE_IVAR.9
MLINKS+=BUS_SETUP_INTR.9 bus_setup_intr.9 \
BUS_SETUP_INTR.9 BUS_TEARDOWN_INTR.9 \
BUS_SETUP_INTR.9 bus_teardown_intr.9
-MLINKS+=bus_space.9 bus_space_barrier.9 \
+MLINKS+=bus_space.9 bus_space_alloc.9 \
+ bus_space.9 bus_space_barrier.9 \
bus_space.9 bus_space_copy_region_1.9 \
bus_space.9 bus_space_copy_region_2.9 \
bus_space.9 bus_space_copy_region_4.9 \
@@ -560,6 +573,7 @@ MLINKS+=condvar.9 cv_broadcast.9 \
condvar.9 cv_signal.9 \
condvar.9 cv_timedwait.9 \
condvar.9 cv_timedwait_sig.9 \
+ condvar.9 cv_timedwait_sig_sbt.9 \
condvar.9 cv_wait.9 \
condvar.9 cv_wait_sig.9 \
condvar.9 cv_wait_unlock.9 \
@@ -664,12 +678,21 @@ MLINKS+=eventtimers.9 et_register.9 \
eventtimers.9 ET_UNLOCK.9 \
eventtimers.9 et_start.9 \
eventtimers.9 et_stop.9
+MLINKS+=fail.9 KFAIL_POINT_CODE.9 \
+ fail.9 KFAIL_POINT_ERROR.9 \
+ fail.9 KFAIL_POINT_GOTO.9 \
+ fail.9 KFAIL_POINT_RETURN.9 \
+ fail.9 KFAIL_POINT_RETURN_VOID.9
MLINKS+=fetch.9 fubyte.9 \
fetch.9 fuswintr.9 \
fetch.9 fuword.9 \
fetch.9 fuword16.9 \
fetch.9 fuword32.9 \
fetch.9 fuword64.9
+MLINKS+=firmware.9 firmware_get.9 \
+ firmware.9 firmware_put.9 \
+ firmware.9 firmware_register.9 \
+ firmware.9 firmware_unregister.9
MLINKS+=fpu_kern.9 fpu_kern_alloc_ctx.9 \
fpu_kern.9 fpu_kern_free_ctx.9 \
fpu_kern.9 fpu_kern_enter.9 \
@@ -677,8 +700,10 @@ MLINKS+=fpu_kern.9 fpu_kern_alloc_ctx.9 \
fpu_kern.9 fpu_kern_thread.9 \
fpu_kern.9 is_fpu_kern_thread.9
MLINKS+=g_attach.9 g_detach.9
-MLINKS+=g_bio.9 g_clone_bio.9 \
+MLINKS+=g_bio.9 g_alloc_bio.9 \
+ g_bio.9 g_clone_bio.9 \
g_bio.9 g_destroy_bio.9 \
+ g_bio.9 g_duplicate_bio.9 \
g_bio.9 g_new_bio.9 \
g_bio.9 g_print_bio.9
MLINKS+=g_consumer.9 g_destroy_consumer.9 \
@@ -692,7 +717,9 @@ MLINKS+=getenv.9 freeenv.9 \
getenv.9 getenv_quad.9 \
getenv.9 getenv_uint.9 \
getenv.9 getenv_ulong.9 \
- getenv.9 testenv.9
+ getenv.9 setenv.9 \
+ getenv.9 testenv.9 \
+ getenv.9 unsetenv.9
MLINKS+=g_event.9 g_cancel_event.9 \
g_event.9 g_post_event.9 \
g_event.9 g_waitfor_event.9
@@ -706,13 +733,22 @@ MLINKS+=hash.9 hash32.9 \
hash.9 hash32_str.9 \
hash.9 hash32_stre.9 \
hash.9 hash32_strn.9 \
- hash.9 hash32_strne.9
+ hash.9 hash32_strne.9 \
+ hash.9 jenkins_hash.9 \
+ hash.9 jenkins_hash32.9
MLINKS+=hashinit.9 hashdestroy.9 \
hashinit.9 hashinit_flags.9 \
hashinit.9 phashinit.9
+MLINKS+=hhook.9 hhook_head_register.9 \
+ hhook.9 hhook_head_deregister.9 \
+ hhook.9 hhook_head_deregister_lookup.9 \
+ hhook.9 hhook_run_hooks.9 \
+ hhook.9 HHOOKS_RUN_IF.9 \
+ hhook.9 HHOOKS_RUN_LOOKUP_IF.9
MLINKS+=ieee80211.9 ieee80211_ifattach.9 \
ieee80211.9 ieee80211_ifdetach.9
-MLINKS+=ieee80211_amrr.9 ieee80211_amrr_cleanup.9 \
+MLINKS+=ieee80211_amrr.9 ieee80211_amrr_choose.9 \
+ ieee80211_amrr.9 ieee80211_amrr_cleanup.9 \
ieee80211_amrr.9 ieee80211_amrr_init.9 \
ieee80211_amrr.9 ieee80211_amrr_node_init.9 \
ieee80211_amrr.9 ieee80211_amrr_setinterval.9 \
@@ -725,6 +761,7 @@ MLINKS+=ieee80211_bmiss.9 ieee80211_beacon_miss.9
MLINKS+=ieee80211_crypto.9 ieee80211_crypto_available.9 \
ieee80211_crypto.9 ieee80211_crypto_decap.9 \
ieee80211_crypto.9 ieee80211_crypto_delglobalkeys.9 \
+ ieee80211_crypto.9 ieee80211_crypto_delkey.9 \
ieee80211_crypto.9 ieee80211_crypto_demic.9 \
ieee80211_crypto.9 ieee80211_crypto_encap.9 \
ieee80211_crypto.9 ieee80211_crypto_enmic.9 \
@@ -763,12 +800,55 @@ MLINKS+=ieee80211_radiotap.9 ieee80211_radiotap_active.9 \
MLINKS+=ieee80211_regdomain.9 ieee80211_alloc_countryie.9 \
ieee80211_regdomain.9 ieee80211_init_channels.9 \
ieee80211_regdomain.9 ieee80211_sort_channels.9
+MLINKS+=ieee80211_scan.9 ieee80211_add_scan.9 \
+ ieee80211_scan.9 ieee80211_bg_scan.9 \
+ ieee80211_scan.9 ieee80211_cancel_scan.9 \
+ ieee80211_scan.9 ieee80211_cancel_scan_any.9 \
+ ieee80211_scan.9 ieee80211_check_scan.9 \
+ ieee80211_scan.9 ieee80211_check_scan_current.9 \
+ ieee80211_scan.9 ieee80211_flush.9 \
+ ieee80211_scan.9 ieee80211_probe_curchan.9 \
+ ieee80211_scan.9 ieee80211_scan_assoc_fail.9 \
+ ieee80211_scan.9 ieee80211_scan_done.9 \
+ ieee80211_scan.9 ieee80211_scan_dump_channels.9 \
+ ieee80211_scan.9 ieee80211_scan_flush.9 \
+ ieee80211_scan.9 ieee80211_scan_iterate.9 \
+ ieee80211_scan.9 ieee80211_scan_next.9 \
+ ieee80211_scan.9 ieee80211_scan_timeout.9 \
+ ieee80211_scan.9 ieee80211_scanner_get.9 \
+ ieee80211_scan.9 ieee80211_scanner_register.9 \
+ ieee80211_scan.9 ieee80211_scanner_unregister.9 \
+ ieee80211_scan.9 ieee80211_scanner_unregister_all.9 \
+ ieee80211_scan.9 ieee80211_start_scan.9
MLINKS+=ieee80211_vap.9 ieee80211_vap_attach.9 \
ieee80211_vap.9 ieee80211_vap_detach.9 \
ieee80211_vap.9 ieee80211_vap_setup.9
-MLINKS+=ifnet.9 ifaddr.9 \
+MLINKS+=ifnet.9 if_addmulti.9 \
+ ifnet.9 if_alloc.9 \
+ ifnet.9 if_allmulti.9 \
+ ifnet.9 if_attach.9 \
ifnet.9 if_data.9 \
- ifnet.9 ifqueue.9
+ ifnet.9 IF_DEQUEUE.9 \
+ ifnet.9 if_delmulti.9 \
+ ifnet.9 if_detach.9 \
+ ifnet.9 if_down.9 \
+ ifnet.9 if_findmulti.9 \
+ ifnet.9 if_free.9 \
+ ifnet.9 if_free_type.9 \
+ ifnet.9 if_up.9 \
+ ifnet.9 ifa_free.9 \
+ ifnet.9 ifa_ifwithaddr.9 \
+ ifnet.9 ifa_ifwithdstaddr.9 \
+ ifnet.9 ifa_ifwithnet.9 \
+ ifnet.9 ifa_ref.9 \
+ ifnet.9 ifaddr.9 \
+ ifnet.9 ifaddr_byindex.9 \
+ ifnet.9 ifaof_ifpforaddr.9 \
+ ifnet.9 ifioctl.9 \
+ ifnet.9 ifpromisc.9 \
+ ifnet.9 ifqueue.9 \
+ ifnet.9 ifunit.9 \
+ ifnet.9 ifunit_ref.9
MLINKS+=insmntque.9 insmntque1.9
MLINKS+=ithread.9 ithread_add_handler.9 \
ithread.9 ithread_create.9 \
@@ -783,6 +863,14 @@ MLINKS+=kernel_mount.9 free_mntarg.9 \
kernel_mount.9 mount_argb.9 \
kernel_mount.9 mount_argf.9 \
kernel_mount.9 mount_argsu.9
+MLINKS+=khelp.9 khelp_add_hhook.9 \
+ khelp.9 KHELP_DECLARE_MOD.9 \
+ khelp.9 KHELP_DECLARE_MOD_UMA.9 \
+ khelp.9 khelp_destroy_osd.9 \
+ khelp.9 khelp_get_id.9 \
+ khelp.9 khelp_get_osd.9 \
+ khelp.9 khelp_init_osd.9 \
+ khelp.9 khelp_remove_hhook.9
MLINKS+=kobj.9 DEFINE_CLASS.9 \
kobj.9 kobj_class_compile.9 \
kobj.9 kobj_class_compile_static.9 \
@@ -793,6 +881,7 @@ MLINKS+=kobj.9 DEFINE_CLASS.9 \
kobj.9 kobj_init_static.9
MLINKS+=kproc.9 kproc_create.9 \
kproc.9 kproc_exit.9 \
+ kproc.9 kproc_kthread_add.9 \
kproc.9 kproc_resume.9 \
kproc.9 kproc_shutdown.9 \
kproc.9 kproc_start.9 \
@@ -827,7 +916,8 @@ MLINKS+=ktr.9 CTR0.9 \
ktr.9 CTR2.9 \
ktr.9 CTR3.9 \
ktr.9 CTR4.9 \
- ktr.9 CTR5.9
+ ktr.9 CTR5.9 \
+ ktr.9 CTR6.9
MLINKS+=lock.9 lockdestroy.9 \
lock.9 lockinit.9 \
lock.9 lockmgr.9 \
@@ -884,6 +974,7 @@ MLINKS+=mbpool.9 mbp_alloc.9 \
mbpool.9 mbp_sync.9
MLINKS+=\
mbuf.9 m_adj.9 \
+ mbuf.9 m_align.9 \
mbuf.9 M_ALIGN.9 \
mbuf.9 m_append.9 \
mbuf.9 m_apply.9 \
@@ -894,6 +985,7 @@ MLINKS+=\
mbuf.9 m_copydata.9 \
mbuf.9 m_copym.9 \
mbuf.9 m_copypacket.9 \
+ mbuf.9 m_copyup.9 \
mbuf.9 m_defrag.9 \
mbuf.9 m_devget.9 \
mbuf.9 m_dup.9 \
@@ -1009,9 +1101,38 @@ MLINKS+=mutex.9 mtx_assert.9 \
MLINKS+=namei.9 NDFREE.9 \
namei.9 NDHASGIANT.9 \
namei.9 NDINIT.9
+MLINKS+=netisr.9 netisr_clearqdrops.9 \
+ netisr.9 netisr_default_flow2cpu.9 \
+ netisr.9 netisr_dispatch.9 \
+ netisr.9 netisr_dispatch_src.9 \
+ netisr.9 netisr_get_cpucount.9 \
+ netisr.9 netisr_get_cpuid.9 \
+ netisr.9 netisr_getqdrops.9 \
+ netisr.9 netisr_getqlimit.9 \
+ netisr.9 netisr_queue.9 \
+ netisr.9 netisr_queue_src.9 \
+ netisr.9 netisr_register.9 \
+ netisr.9 netisr_setqlimit.9 \
+ netisr.9 netisr_unregister.9
+MLINKS+=osd.9 osd_call.9 \
+ osd.9 osd_del.9 \
+ osd.9 osd_deregister.9 \
+ osd.9 osd_exit.9 \
+ osd.9 osd_get.9 \
+ osd.9 osd_register.9 \
+ osd.9 osd_set.9
MLINKS+=pbuf.9 getpbuf.9 \
pbuf.9 relpbuf.9 \
pbuf.9 trypbuf.9
+MLINKS+=PCBGROUP.9 in_pcbgroup_byhash.9 \
+ PCBGROUP.9 in_pcbgroup_byinpcb.9 \
+ PCBGROUP.9 in_pcbgroup_destroy.9 \
+ PCBGROUP.9 in_pcbgroup_enabled.9 \
+ PCBGROUP.9 in_pcbgroup_init.9 \
+ PCBGROUP.9 in_pcbgroup_remove.9 \
+ PCBGROUP.9 in_pcbgroup_update.9 \
+ PCBGROUP.9 in_pcbgroup_update_mbuf.9 \
+ PCBGROUP.9 in6_pcbgroup_byhash.9
MLINKS+=pci.9 pci_alloc_msi.9 \
pci.9 pci_alloc_msix.9 \
pci.9 pci_disable_busmaster.9 \
@@ -1040,8 +1161,15 @@ MLINKS+=pci.9 pci_alloc_msi.9 \
pci.9 pci_set_max_read_req.9 \
pci.9 pci_write_config.9
MLINKS+=pfil.9 pfil_add_hook.9 \
+ pfil.9 pfil_head_register.9 \
+ pfil.9 pfil_head_unregister.9 \
pfil.9 pfil_hook_get.9 \
- pfil.9 pfil_remove_hook.9
+ pfil.9 pfil_remove_hook.9 \
+ pfil.9 pfil_rlock.9 \
+ pfil.9 pfil_run_hooks.9 \
+ pfil.9 pfil_runlock.9 \
+ pfil.9 pfil_wlock.9 \
+ pfil.9 pfil_wunlock.9
MLINKS+=pfind.9 zpfind.9
MLINKS+=pmap_copy.9 pmap_copy_page.9
MLINKS+=pmap_extract.9 pmap_extract_and_hold.9
@@ -1114,6 +1242,11 @@ MLINKS+=rmlock.9 rm_assert.9 \
rmlock.9 rm_wunlock.9
MLINKS+=rtalloc.9 rtalloc1.9 \
rtalloc.9 rtalloc_ign.9 \
+ rtalloc.9 RT_ADDREF.9 \
+ rtalloc.9 RT_LOCK.9 \
+ rtalloc.9 RT_REMREF.9 \
+ rtalloc.9 RT_RTFREE.9 \
+ rtalloc.9 RT_UNLOCK.9 \
rtalloc.9 RTFREE_LOCKED.9 \
rtalloc.9 RTFREE.9 \
rtalloc.9 rtfree.9 \
@@ -1128,6 +1261,7 @@ MLINKS+=rwlock.9 rw_assert.9 \
rwlock.9 rw_destroy.9 \
rwlock.9 rw_downgrade.9 \
rwlock.9 rw_init.9 \
+ rwlock.9 rw_init_flags.9 \
rwlock.9 rw_initialized.9 \
rwlock.9 rw_rlock.9 \
rwlock.9 rw_runlock.9 \
@@ -1165,6 +1299,7 @@ MLINKS+=sbuf.9 sbuf_bcat.9 \
sbuf.9 sbuf_vprintf.9
MLINKS+=scheduler.9 curpriority_cmp.9 \
scheduler.9 maybe_resched.9 \
+ scheduler.9 propagate_priority.9 \
scheduler.9 resetpriority.9 \
scheduler.9 roundrobin.9 \
scheduler.9 roundrobin_interval.9 \
@@ -1253,17 +1388,18 @@ MLINKS+=sleepqueue.9 init_sleepqueues.9 \
sleepqueue.9 sleepq_add.9 \
sleepqueue.9 sleepq_alloc.9 \
sleepqueue.9 sleepq_broadcast.9 \
- sleepqueue.9 sleepq_calc_signal_retval.9 \
- sleepqueue.9 sleepq_catch_signals.9 \
sleepqueue.9 sleepq_free.9 \
sleepqueue.9 sleepq_lookup.9 \
+ sleepqueue.9 sleepq_lock.9 \
sleepqueue.9 sleepq_release.9 \
sleepqueue.9 sleepq_remove.9 \
sleepqueue.9 sleepq_set_timeout.9 \
sleepqueue.9 sleepq_set_timeout_sbt.9 \
sleepqueue.9 sleepq_signal.9 \
+ sleepqueue.9 sleepq_sleepcnt.9 \
sleepqueue.9 sleepq_timedwait.9 \
sleepqueue.9 sleepq_timedwait_sig.9 \
+ sleepqueue.9 sleepq_type.9 \
sleepqueue.9 sleepq_wait.9 \
sleepqueue.9 sleepq_wait_sig.9
MLINKS+=socket.9 soabort.9 \
@@ -1318,6 +1454,8 @@ MLINKS+=stack.9 stack_copy.9 \
stack.9 stack_destroy.9 \
stack.9 stack_print.9 \
stack.9 stack_print_ddb.9 \
+ stack.9 stack_print_short.9 \
+ stack.9 stack_print_short_ddb.9 \
stack.9 stack_put.9 \
stack.9 stack_save.9 \
stack.9 stack_sbuf_print.9 \
@@ -1339,6 +1477,7 @@ MLINKS+=sx.9 sx_assert.9 \
sx.9 sx_init_flags.9 \
sx.9 sx_sleep.9 \
sx.9 sx_slock.9 \
+ sx.9 sx_slock_sig.9 \
sx.9 sx_sunlock.9 \
sx.9 SX_SYSINIT.9 \
sx.9 sx_try_slock.9 \
@@ -1347,6 +1486,7 @@ MLINKS+=sx.9 sx_assert.9 \
sx.9 sx_unlock.9 \
sx.9 sx_xholder.9 \
sx.9 sx_xlock.9 \
+ sx.9 sx_xlock_sig.9 \
sx.9 sx_xlocked.9 \
sx.9 sx_xunlock.9
MLINKS+=sysctl.9 SYSCTL_DECL.9 \
@@ -1422,20 +1562,27 @@ MLINKS+=timeout.9 callout.9 \
timeout.9 callout_handle_init.9 \
timeout.9 callout_init.9 \
timeout.9 callout_init_mtx.9 \
+ timeout.9 callout_init_rm.9 \
timeout.9 callout_init_rw.9 \
timeout.9 callout_pending.9 \
timeout.9 callout_reset.9 \
+ timeout.9 callout_reset_curcpu.9 \
timeout.9 callout_reset_sbt.9 \
timeout.9 callout_reset_on.9 \
timeout.9 callout_reset_sbt_on.9 \
timeout.9 callout_schedule.9 \
+ timeout.9 callout_schedule_curcpu.9 \
+ timeout.9 callout_schedule_on.9 \
timeout.9 callout_stop.9 \
timeout.9 untimeout.9
-MLINKS+=ucred.9 crcopy.9 \
+MLINKS+=ucred.9 cred_update_thread.9 \
+ ucred.9 crcopy.9 \
+ ucred.9 crcopysafe.9 \
ucred.9 crdup.9 \
ucred.9 crfree.9 \
ucred.9 crget.9 \
ucred.9 crhold.9 \
+ ucred.9 crsetgroups.9 \
ucred.9 crshared.9 \
ucred.9 cru2x.9
MLINKS+=uidinfo.9 uifind.9 \
@@ -1582,6 +1729,7 @@ MLINKS+=vrele.9 vput.9 \
vrele.9 vunref.9
MLINKS+=vslock.9 vsunlock.9
MLINKS+=zone.9 uma.9 \
+ zone.9 uma_find_refcnt.9 \
zone.9 uma_zalloc.9 \
zone.9 uma_zalloc_arg.9 \
zone.9 uma_zcreate.9 \
@@ -1590,6 +1738,7 @@ MLINKS+=zone.9 uma.9 \
zone.9 uma_zfree_arg.9 \
zone.9 uma_zone_get_cur.9 \
zone.9 uma_zone_get_max.9 \
- zone.9 uma_zone_set_max.9
+ zone.9 uma_zone_set_max.9 \
+ zone.9 uma_zone_set_warning.9
.include <bsd.prog.mk>
diff --git a/share/man/man9/sleepqueue.9 b/share/man/man9/sleepqueue.9
index 8557b9f..f09f209 100644
--- a/share/man/man9/sleepqueue.9
+++ b/share/man/man9/sleepqueue.9
@@ -32,8 +32,6 @@
.Nm sleepq_add ,
.Nm sleepq_alloc ,
.Nm sleepq_broadcast ,
-.Nm sleepq_calc_signal_retval ,
-.Nm sleepq_catch_signals ,
.Nm sleepq_free ,
.Nm sleepq_lock ,
.Nm sleepq_lookup ,
@@ -62,10 +60,6 @@
.Fn sleepq_alloc "void"
.Ft int
.Fn sleepq_broadcast "void *wchan" "int flags" "int pri" "int queue"
-.Ft int
-.Fn sleepq_calc_signal_retval "int sig"
-.Ft int
-.Fn sleepq_catch_signals "void *wchan"
.Ft void
.Fn sleepq_free "struct sleepqueue *sq"
.Ft struct sleepqueue *
@@ -86,15 +80,15 @@
.Ft u_int
.Fn sleepq_sleepcnt "void *wchan" "int queue"
.Ft int
-.Fn sleepq_timedwait "void *wchan"
+.Fn sleepq_timedwait "void *wchan" "int pri"
.Ft int
-.Fn sleepq_timedwait_sig "void *wchan" "int signal_caught"
+.Fn sleepq_timedwait_sig "void *wchan" "int pri"
.Ft int
.Fn sleepq_type "void *wchan"
.Ft void
-.Fn sleepq_wait "void *wchan"
+.Fn sleepq_wait "void *wchan" "int pri"
.Ft int
-.Fn sleepq_wait_sig "void *wchan"
+.Fn sleepq_wait_sig "void *wchan" "int pri"
.Sh DESCRIPTION
Sleep queues provide a mechanism for suspending execution of a thread until
some condition is met.
@@ -252,17 +246,6 @@ allows to pass additional
.Fn callout_reset_sbt
flags.
.Pp
-The current thread may be marked interruptible by calling
-.Fn sleepq_catch_signals
-with
-.Fa wchan
-set to the wait channel.
-This function returns a signal number if there are any pending signals for
-the current thread and 0 if there is not a pending signal.
-The sleep queue chain associated with argument
-.Fa wchan
-should have been locked by a prior call to
-.Fn sleepq_lock .
.Pp
Once the thread is ready to suspend,
one of the wait functions is called to put the current thread to sleep
@@ -289,12 +272,9 @@ The sleep queue chain associated with argument
needs to have been locked with a prior call to
.Fn sleepq_lock .
The
-.Fa signal_caught
-parameter to
-.Fn sleepq_timedwait_sig
-specifies if a previous call to
-.Fn sleepq_catch_signals
-found a pending signal.
+.Fa pri
+argument is used to set the priority of the thread when it is awakened.
+If it is set to zero, the thread's priority is left alone.
.Pp
When the thread is resumed,
the wait functions return a non-zero value if the thread was awakened due to
@@ -304,20 +284,6 @@ If the sleep timed out, then
is returned.
If the sleep was interrupted by something other than a signal,
then some other return value will be returned.
-If zero is returned after resuming from an interruptible sleep,
-then
-.Fn sleepq_calc_signal_retval
-should be called to determine if the sleep was interrupted by a signal.
-If so,
-.Fn sleepq_calc_signal_retval
-returns
-.Er ERESTART
-if the interrupting signal is restartable and
-.Er EINTR
-otherwise.
-If the sleep was not interrupted by a signal,
-.Fn sleepq_calc_signal_retval
-will return 0.
.Pp
A sleeping thread is normally resumed by the
.Fn sleepq_broadcast
diff --git a/share/misc/committers-src.dot b/share/misc/committers-src.dot
index 100a0ce..07d6aa7 100644
--- a/share/misc/committers-src.dot
+++ b/share/misc/committers-src.dot
@@ -179,6 +179,7 @@ ivoras [label="Ivan Voras\nivoras@FreeBSD.org\n2008/06/10"]
jamie [label="Jamie Gritton\njamie@FreeBSD.org\n2009/01/28"]
jasone [label="Jason Evans\njasone@FreeBSD.org\n1999/03/03"]
jceel [label="Jakub Klama\njceel@FreeBSD.org\n2011/09/25"]
+jch [label="Julien Charbon\njch@FreeBSD.org\n2014/09/24"]
jchandra [label="Jayachandran C.\njchandra@FreeBSD.org\n2010/05/19"]
jeff [label="Jeff Roberson\njeff@FreeBSD.org\n2002/02/21"]
jh [label="Jaakko Heinonen\njh@FreeBSD.org\n2009/10/02"]
@@ -484,6 +485,7 @@ jdp -> fjoe
jhb -> arr
jhb -> avg
+jhb -> jch
jhb -> jeff
jhb -> kbyanc
jhb -> peterj
diff --git a/share/mk/bsd.progs.mk b/share/mk/bsd.progs.mk
index c5e8c3d..5ca1e45 100644
--- a/share/mk/bsd.progs.mk
+++ b/share/mk/bsd.progs.mk
@@ -42,10 +42,15 @@ PROG ?= $t
.if defined(PROG)
# just one of many
-PROG_VARS += BINDIR CFLAGS CPPFLAGS CXXFLAGS DPADD DPLIBS LDADD MAN SRCS
+PROG_OVERRIDE_VARS += BINDIR MAN SRCS
+PROG_VARS += CFLAGS CPPFLAGS CXXFLAGS DPADD DPLIBS LDADD ${PROG_OVERRIDE_VARS}
.for v in ${PROG_VARS:O:u}
-.if defined(${v}.${PROG}) || defined(${v}_${PROG})
-$v += ${${v}_${PROG}:U${${v}.${PROG}}}
+.if empty(${PROG_OVERRIDE_VARS:M$v})
+.if defined(${v}.${PROG})
+$v += ${${v}.${PROG}}
+.elif defined(${v}_${PROG})
+$v += ${${v}_${PROG}}
+.endif
.else
$v ?=
.endif
@@ -61,7 +66,7 @@ UPDATE_DEPENDFILE ?= NO
DEPENDFILE?= .depend.${PROG}
# prog.mk will do the rest
.else
-all: ${PROGS}
+all: ${FILES} ${PROGS} ${SCRIPTS}
# We cannot capture dependencies for meta mode here
UPDATE_DEPENDFILE = NO
@@ -75,7 +80,7 @@ UPDATE_DEPENDFILE = NO
.ifndef _RECURSING_PROGS
# tell progs.mk we might want to install things
-PROGS_TARGETS+= cleandepend cleandir cleanobj depend install
+PROGS_TARGETS+= checkdpadd clean cleandepend cleandir cleanobj depend install
.for p in ${PROGS}
.if defined(PROGS_CXX) && !empty(PROGS_CXX:M$p)
@@ -98,18 +103,15 @@ $p.$t: .PHONY .MAKE
$t: ${PROGS:%=%.$t}
.endfor
-SCRIPTS_TARGETS+= cleandepend cleandir cleanobj depend install
+.if empty(PROGS) && !empty(SCRIPTS)
-.for p in ${SCRIPTS}
-.for t in ${SCRIPTS_TARGETS:O:u}
-$p.$t: .PHONY .MAKE
- (cd ${.CURDIR} && ${MAKE} -f ${MAKEFILE} _RECURSING_PROGS= \
- SUBDIR= SCRIPT=$p ${x.$p} ${@:E})
-.endfor
+.for t in ${PROGS_TARGETS:O:u}
+scripts.$t: .PHONY .MAKE
+ (cd ${.CURDIR} && ${MAKE} -f ${MAKEFILE} SUBDIR= _RECURSING_PROGS= \
+ $t)
+$t: scripts.$t
.endfor
-.for t in ${SCRIPTS_TARGETS:O:u}
-$t: ${SCRIPTS:%=%.$t}
-.endfor
+.endif
.endif
diff --git a/sys/Makefile b/sys/Makefile
index dc1d5e9..46d883e 100644
--- a/sys/Makefile
+++ b/sys/Makefile
@@ -5,7 +5,7 @@ CSCOPEDIRS= boot bsm cam cddl compat conf contrib crypto ddb dev fs gdb \
geom gnu isa kern libkern modules net net80211 \
netgraph netinet netinet6 netipsec netnatm netpfil \
netsmb nfs nfsclient nfsserver nlm ofed opencrypto \
- pci rpc security sys ufs vm xdr xen ${CSCOPE_ARCHDIR}
+ rpc security sys ufs vm xdr xen ${CSCOPE_ARCHDIR}
.if !defined(CSCOPE_ARCHDIR)
.if defined(ALL_ARCH)
CSCOPE_ARCHDIR = amd64 arm i386 mips pc98 powerpc sparc64 x86
diff --git a/sys/amd64/amd64/fpu.c b/sys/amd64/amd64/fpu.c
index 0d59df4..5c61859 100644
--- a/sys/amd64/amd64/fpu.c
+++ b/sys/amd64/amd64/fpu.c
@@ -602,29 +602,30 @@ fputrap_sse(void)
return (fpetable[(mxcsr & (~mxcsr >> 7)) & 0x3f]);
}
-static int err_count = 0;
-
/*
* Device Not Available (DNA, #NM) exception handler.
*
* It would be better to switch FP context here (if curthread !=
* fpcurthread) and not necessarily for every context switch, but it
* is too hard to access foreign pcb's.
- *
- * The handler is entered with interrupts enabled, which allows the
- * context switch to happen before critical enter() is executed, and
- * causes restoration of FPU context on CPU other than that caused
- * DNA. It is fine, since context switch started emulation on the
- * current CPU as well.
*/
void
fpudna(void)
{
+ /*
+ * This handler is entered with interrupts enabled, so context
+ * switches may occur before critical_enter() is executed. If
+ * a context switch occurs, then when we regain control, our
+ * state will have been completely restored. The CPU may
+ * change underneath us, but the only part of our context that
+ * lives in the CPU is CR0.TS and that will be "restored" by
+ * setting it on the new CPU.
+ */
critical_enter();
+
if (PCPU_GET(fpcurthread) == curthread) {
- printf("fpudna: fpcurthread == curthread %d times\n",
- ++err_count);
+ printf("fpudna: fpcurthread == curthread\n");
stop_emulating();
critical_exit();
return;
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index c54b3b1..278409d 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -184,9 +184,6 @@ struct init_ops init_ops = {
* the physical address at which the kernel is loaded.
*/
extern char kernphys[];
-#ifdef DDB
-extern vm_offset_t ksym_start, ksym_end;
-#endif
struct msgbuf *msgbufp;
@@ -1823,6 +1820,10 @@ static caddr_t
native_parse_preload_data(u_int64_t modulep)
{
caddr_t kmdp;
+#ifdef DDB
+ vm_offset_t ksym_start;
+ vm_offset_t ksym_end;
+#endif
preload_metadata = (caddr_t)(uintptr_t)(modulep + KERNBASE);
preload_bootstrap_relocate(KERNBASE);
@@ -1834,6 +1835,7 @@ native_parse_preload_data(u_int64_t modulep)
#ifdef DDB
ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t);
ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t);
+ db_fetch_ksymtab(ksym_start, ksym_end);
#endif
return (kmdp);
diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
index f6459f4..4880c91 100644
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -436,8 +436,8 @@ trap(struct trapframe *frame)
case T_XMMFLT: /* SIMD floating-point exception */
case T_FPOPFLT: /* FPU operand fetch fault */
/*
- * XXXKIB for now disable any FPU traps in kernel
- * handler registration seems to be overkill
+ * For now, supporting kernel handler
+ * registration for FPU traps is overkill.
*/
trap_fatal(frame, 0);
goto out;
diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC
index 698f510..cf4fb46 100644
--- a/sys/amd64/conf/GENERIC
+++ b/sys/amd64/conf/GENERIC
@@ -216,6 +216,8 @@ device de # DEC/Intel DC21x4x (``Tulip'')
device em # Intel PRO/1000 Gigabit Ethernet Family
device igb # Intel PRO/1000 PCIE Server Gigabit Family
device ixgbe # Intel PRO/10GbE PCIE Ethernet Family
+device ixl # Intel XL710 40Gbe PCIE Ethernet
+device ixlv # Intel XL710 40Gbe VF PCIE Ethernet
device le # AMD Am7900 LANCE and Am79C9xx PCnet
device ti # Alteon Networks Tigon I/II gigabit Ethernet
device txp # 3Com 3cR990 (``Typhoon'')
diff --git a/sys/amd64/conf/NOTES b/sys/amd64/conf/NOTES
index 1262af3..a946c05 100644
--- a/sys/amd64/conf/NOTES
+++ b/sys/amd64/conf/NOTES
@@ -310,6 +310,8 @@ options DRM_DEBUG # Include debug printfs (slow)
# iwn: Intel Wireless WiFi Link 1000/105/135/2000/4965/5000/6000/6050 abgn
# 802.11 network adapters
# Requires the iwn firmware module
+# ixl: Intel XL710 40Gbe PCIE Ethernet
+# ixlv: Intel XL710 40Gbe VF PCIE Ethernet
# mlx4ib: Mellanox ConnectX HCA InfiniBand
# mlxen: Mellanox ConnectX HCA Ethernet
# mthca: Mellanox HCA InfiniBand
@@ -327,6 +329,8 @@ options ED_SIC
device ipw # Intel 2100 wireless NICs.
device iwi # Intel 2200BG/2225BG/2915ABG wireless NICs.
device iwn # Intel 4965/1000/5000/6000 wireless NICs.
+device ixl # Intel XL710 40Gbe PCIE Ethernet
+device ixlv # Intel XL710 40Gbe VF PCIE Ethernet
device mlx4ib # Mellanox ConnectX HCA InfiniBand
device mlxen # Mellanox ConnectX HCA Ethernet
device mthca # Mellanox HCA InfiniBand
diff --git a/sys/amd64/vmm/intel/vmx.c b/sys/amd64/vmm/intel/vmx.c
index 64d9fff..95adf12 100644
--- a/sys/amd64/vmm/intel/vmx.c
+++ b/sys/amd64/vmm/intel/vmx.c
@@ -885,12 +885,6 @@ vmx_vminit(struct vm *vm, pmap_t pmap)
* how they are saved/restored so can be directly accessed by the
* guest.
*
- * Guest KGSBASE is saved and restored in the guest MSR save area.
- * Host KGSBASE is restored before returning to userland from the pcb.
- * There will be a window of time when we are executing in the host
- * kernel context with a value of KGSBASE from the guest. This is ok
- * because the value of KGSBASE is inconsequential in kernel context.
- *
* MSR_EFER is saved and restored in the guest VMCS area on a
* VM exit and entry respectively. It is also restored from the
* host VMCS area on a VM exit.
@@ -905,7 +899,6 @@ vmx_vminit(struct vm *vm, pmap_t pmap)
guest_msr_rw(vmx, MSR_SYSENTER_CS_MSR) ||
guest_msr_rw(vmx, MSR_SYSENTER_ESP_MSR) ||
guest_msr_rw(vmx, MSR_SYSENTER_EIP_MSR) ||
- guest_msr_rw(vmx, MSR_KGSBASE) ||
guest_msr_rw(vmx, MSR_EFER) ||
guest_msr_ro(vmx, MSR_TSC))
panic("vmx_vminit: error setting guest msr access");
diff --git a/sys/amd64/vmm/io/vlapic.c b/sys/amd64/vmm/io/vlapic.c
index c6336bc..b192735 100644
--- a/sys/amd64/vmm/io/vlapic.c
+++ b/sys/amd64/vmm/io/vlapic.c
@@ -633,6 +633,7 @@ vlapic_fire_timer(struct vlapic *vlapic)
// The timer LVT always uses the fixed delivery mode.
lvt = vlapic_get_lvt(vlapic, APIC_OFFSET_TIMER_LVT);
if (vlapic_fire_lvt(vlapic, lvt | APIC_LVT_DM_FIXED)) {
+ VLAPIC_CTR0(vlapic, "vlapic timer fired");
vmm_stat_incr(vlapic->vm, vlapic->vcpuid, VLAPIC_INTR_TIMER, 1);
}
}
diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c
index 26f7c59..d73c7b3 100644
--- a/sys/amd64/vmm/vmm.c
+++ b/sys/amd64/vmm/vmm.c
@@ -1197,8 +1197,12 @@ vm_handle_paging(struct vm *vm, int vcpuid, bool *retu)
if (ftype == VM_PROT_READ || ftype == VM_PROT_WRITE) {
rv = pmap_emulate_accessed_dirty(vmspace_pmap(vm->vmspace),
vme->u.paging.gpa, ftype);
- if (rv == 0)
+ if (rv == 0) {
+ VCPU_CTR2(vm, vcpuid, "%s bit emulation for gpa %#lx",
+ ftype == VM_PROT_READ ? "accessed" : "dirty",
+ vme->u.paging.gpa);
goto done;
+ }
}
map = &vm->vmspace->vm_map;
@@ -1239,6 +1243,8 @@ vm_handle_inst_emul(struct vm *vm, int vcpuid, bool *retu)
paging = &vme->u.inst_emul.paging;
cpu_mode = paging->cpu_mode;
+ VCPU_CTR1(vm, vcpuid, "inst_emul fault accessing gpa %#lx", gpa);
+
/* Fetch, decode and emulate the faulting instruction */
if (vie->num_valid == 0) {
/*
diff --git a/sys/arm/allwinner/a10_clk.c b/sys/arm/allwinner/a10_clk.c
index 2bb683e0..af7e875 100644
--- a/sys/arm/allwinner/a10_clk.c
+++ b/sys/arm/allwinner/a10_clk.c
@@ -132,7 +132,7 @@ a10_clk_usb_activate(void)
/* Gating AHB clock for USB */
reg_value = ccm_read_4(sc, CCM_AHB_GATING0);
reg_value |= CCM_AHB_GATING_USB0; /* AHB clock gate usb0 */
- reg_value |= CCM_AHB_GATING_EHCI0; /* AHB clock gate ehci1 */
+ reg_value |= CCM_AHB_GATING_EHCI0; /* AHB clock gate ehci0 */
reg_value |= CCM_AHB_GATING_EHCI1; /* AHB clock gate ehci1 */
ccm_write_4(sc, CCM_AHB_GATING0, reg_value);
@@ -167,6 +167,7 @@ a10_clk_usb_deactivate(void)
/* Disable gating AHB clock for USB */
reg_value = ccm_read_4(sc, CCM_AHB_GATING0);
reg_value &= ~CCM_AHB_GATING_USB0; /* disable AHB clock gate usb0 */
+ reg_value &= ~CCM_AHB_GATING_EHCI0; /* disable AHB clock gate ehci0 */
reg_value &= ~CCM_AHB_GATING_EHCI1; /* disable AHB clock gate ehci1 */
ccm_write_4(sc, CCM_AHB_GATING0, reg_value);
diff --git a/sys/arm/altera/socfpga/files.socfpga b/sys/arm/altera/socfpga/files.socfpga
index 441e388..c420617 100644
--- a/sys/arm/altera/socfpga/files.socfpga
+++ b/sys/arm/altera/socfpga/files.socfpga
@@ -17,3 +17,5 @@ arm/altera/socfpga/socfpga_common.c standard
arm/altera/socfpga/socfpga_machdep.c standard
arm/altera/socfpga/socfpga_manager.c standard
arm/altera/socfpga/socfpga_rstmgr.c standard
+
+dev/dwc/if_dwc.c optional dwc
diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c
index 8a78232..98c424e 100644
--- a/sys/arm/arm/machdep.c
+++ b/sys/arm/arm/machdep.c
@@ -111,6 +111,10 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/openfirm.h>
#endif
+#ifdef DDB
+#include <ddb/ddb.h>
+#endif
+
#ifdef DEBUG
#define debugf(fmt, args...) printf(fmt, ##args)
#else
@@ -131,9 +135,6 @@ int _min_memcpy_size = 0;
int _min_bzero_size = 0;
extern int *end;
-#ifdef DDB
-extern vm_offset_t ksym_start, ksym_end;
-#endif
#ifdef FDT
/*
@@ -817,8 +818,7 @@ fake_preload_metadata(struct arm_boot_params *abp __unused)
lastaddr = *(uint32_t *)(KERNVIRTADDR + 8);
zend = lastaddr;
zstart = *(uint32_t *)(KERNVIRTADDR + 4);
- ksym_start = zstart;
- ksym_end = zend;
+ db_fetch_ksymtab(zstart, zend);
} else
#endif
lastaddr = (vm_offset_t)&end;
@@ -912,6 +912,10 @@ freebsd_parse_boot_param(struct arm_boot_params *abp)
vm_offset_t lastaddr = 0;
void *mdp;
void *kmdp;
+#ifdef DDB
+ vm_offset_t ksym_start;
+ vm_offset_t ksym_end;
+#endif
/*
* Mask metadata pointer: it is supposed to be on page boundary. If
@@ -934,6 +938,7 @@ freebsd_parse_boot_param(struct arm_boot_params *abp)
#ifdef DDB
ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t);
ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t);
+ db_fetch_ksymtab(ksym_start, ksym_end);
#endif
preload_addr_relocate = KERNVIRTADDR - abp->abp_physaddr;
return lastaddr;
diff --git a/sys/arm/arm/mpcore_timer.c b/sys/arm/arm/mpcore_timer.c
index 3f87a2a..62c5344 100644
--- a/sys/arm/arm/mpcore_timer.c
+++ b/sys/arm/arm/mpcore_timer.c
@@ -97,36 +97,25 @@ __FBSDID("$FreeBSD$");
#define GBL_TIMER_INTR_EVENT (1UL << 0)
struct arm_tmr_softc {
- struct resource * tmr_res[4];
- bus_space_tag_t prv_bst;
- bus_space_tag_t gbl_bst;
- bus_space_handle_t prv_bsh;
- bus_space_handle_t gbl_bsh;
+ device_t dev;
+ int irqrid;
+ int memrid;
+ struct resource * gbl_mem;
+ struct resource * prv_mem;
+ struct resource * prv_irq;
uint64_t clkfreq;
struct eventtimer et;
};
-static struct resource_spec arm_tmr_spec[] = {
- { SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Global registers */
- { SYS_RES_IRQ, 0, RF_ACTIVE }, /* Global timer interrupt (unused) */
- { SYS_RES_MEMORY, 1, RF_ACTIVE }, /* Private (per-CPU) registers */
- { SYS_RES_IRQ, 1, RF_ACTIVE }, /* Private timer interrupt */
- { -1, 0 }
-};
-
-static struct arm_tmr_softc *arm_tmr_sc = NULL;
-
-static uint64_t platform_arm_tmr_freq = 0;
-
-#define tmr_prv_read_4(reg) \
- bus_space_read_4(arm_tmr_sc->prv_bst, arm_tmr_sc->prv_bsh, reg)
-#define tmr_prv_write_4(reg, val) \
- bus_space_write_4(arm_tmr_sc->prv_bst, arm_tmr_sc->prv_bsh, reg, val)
-#define tmr_gbl_read_4(reg) \
- bus_space_read_4(arm_tmr_sc->gbl_bst, arm_tmr_sc->gbl_bsh, reg)
-#define tmr_gbl_write_4(reg, val) \
- bus_space_write_4(arm_tmr_sc->gbl_bst, arm_tmr_sc->gbl_bsh, reg, val)
+static struct eventtimer *arm_tmr_et;
+static struct timecounter *arm_tmr_tc;
+static uint64_t arm_tmr_freq;
+static boolean_t arm_tmr_freq_varies;
+#define tmr_prv_read_4(sc, reg) bus_read_4((sc)->prv_mem, reg)
+#define tmr_prv_write_4(sc, reg, val) bus_write_4((sc)->prv_mem, reg, val)
+#define tmr_gbl_read_4(sc, reg) bus_read_4((sc)->gbl_mem, reg)
+#define tmr_gbl_write_4(sc, reg, val) bus_write_4((sc)->gbl_mem, reg, val)
static timecounter_get_t arm_tmr_get_timecount;
@@ -139,6 +128,21 @@ static struct timecounter arm_tmr_timecount = {
.tc_quality = 800,
};
+#define TMR_GBL 0x01
+#define TMR_PRV 0x02
+#define TMR_BOTH (TMR_GBL | TMR_PRV)
+#define TMR_NONE 0
+
+static struct ofw_compat_data compat_data[] = {
+ {"arm,mpcore-timers", TMR_BOTH}, /* Non-standard, FreeBSD. */
+ {"arm,cortex-a9-global-timer", TMR_GBL},
+ {"arm,cortex-a5-global-timer", TMR_GBL},
+ {"arm,cortex-a9-twd-timer", TMR_PRV},
+ {"arm,cortex-a5-twd-timer", TMR_PRV},
+ {"arm,arm11mp-twd-timer", TMR_PRV},
+ {NULL, TMR_NONE}
+};
+
/**
* arm_tmr_get_timecount - reads the timecount (global) timer
* @tc: pointer to arm_tmr_timecount struct
@@ -152,7 +156,10 @@ static struct timecounter arm_tmr_timecount = {
static unsigned
arm_tmr_get_timecount(struct timecounter *tc)
{
- return (tmr_gbl_read_4(GBL_TIMER_COUNT_LOW));
+ struct arm_tmr_softc *sc;
+
+ sc = tc->tc_priv;
+ return (tmr_gbl_read_4(sc, GBL_TIMER_COUNT_LOW));
}
/**
@@ -172,11 +179,13 @@ arm_tmr_get_timecount(struct timecounter *tc)
static int
arm_tmr_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
{
+ struct arm_tmr_softc *sc;
uint32_t load, count;
uint32_t ctrl;
- tmr_prv_write_4(PRV_TIMER_CTRL, 0);
- tmr_prv_write_4(PRV_TIMER_INTR, PRV_TIMER_INTR_EVENT);
+ sc = et->et_priv;
+ tmr_prv_write_4(sc, PRV_TIMER_CTRL, 0);
+ tmr_prv_write_4(sc, PRV_TIMER_INTR, PRV_TIMER_INTR_EVENT);
ctrl = PRV_TIMER_CTRL_IRQ_ENABLE | PRV_TIMER_CTRL_TIMER_ENABLE;
@@ -191,9 +200,9 @@ arm_tmr_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
else
count = load;
- tmr_prv_write_4(PRV_TIMER_LOAD, load);
- tmr_prv_write_4(PRV_TIMER_COUNT, count);
- tmr_prv_write_4(PRV_TIMER_CTRL, ctrl);
+ tmr_prv_write_4(sc, PRV_TIMER_LOAD, load);
+ tmr_prv_write_4(sc, PRV_TIMER_COUNT, count);
+ tmr_prv_write_4(sc, PRV_TIMER_CTRL, ctrl);
return (0);
}
@@ -210,8 +219,11 @@ arm_tmr_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
static int
arm_tmr_stop(struct eventtimer *et)
{
- tmr_prv_write_4(PRV_TIMER_CTRL, 0);
- tmr_prv_write_4(PRV_TIMER_INTR, PRV_TIMER_INTR_EVENT);
+ struct arm_tmr_softc *sc;
+
+ sc = et->et_priv;
+ tmr_prv_write_4(sc, PRV_TIMER_CTRL, 0);
+ tmr_prv_write_4(sc, PRV_TIMER_INTR, PRV_TIMER_INTR_EVENT);
return (0);
}
@@ -227,13 +239,12 @@ arm_tmr_stop(struct eventtimer *et)
static int
arm_tmr_intr(void *arg)
{
- struct arm_tmr_softc *sc = (struct arm_tmr_softc *)arg;
-
- tmr_prv_write_4(PRV_TIMER_INTR, PRV_TIMER_INTR_EVENT);
+ struct arm_tmr_softc *sc;
+ sc = arg;
+ tmr_prv_write_4(sc, PRV_TIMER_INTR, PRV_TIMER_INTR_EVENT);
if (sc->et.et_active)
sc->et.et_event_cb(&sc->et, sc->et.et_arg);
-
return (FILTER_HANDLED);
}
@@ -257,13 +268,98 @@ arm_tmr_probe(device_t dev)
if (!ofw_bus_status_okay(dev))
return (ENXIO);
- if (!ofw_bus_is_compatible(dev, "arm,mpcore-timers"))
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == TMR_NONE)
return (ENXIO);
device_set_desc(dev, "ARM MPCore Timers");
return (BUS_PROBE_DEFAULT);
}
+static int
+attach_tc(struct arm_tmr_softc *sc)
+{
+ int rid;
+
+ if (arm_tmr_tc != NULL)
+ return (EBUSY);
+
+ rid = sc->memrid;
+ sc->gbl_mem = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->gbl_mem == NULL) {
+ device_printf(sc->dev, "could not allocate gbl mem resources\n");
+ return (ENXIO);
+ }
+ tmr_gbl_write_4(sc, GBL_TIMER_CTRL, 0x00000000);
+
+ arm_tmr_timecount.tc_frequency = sc->clkfreq;
+ arm_tmr_timecount.tc_priv = sc;
+ tc_init(&arm_tmr_timecount);
+ arm_tmr_tc = &arm_tmr_timecount;
+
+ tmr_gbl_write_4(sc, GBL_TIMER_CTRL, GBL_TIMER_CTRL_TIMER_ENABLE);
+
+ return (0);
+}
+
+static int
+attach_et(struct arm_tmr_softc *sc)
+{
+ void *ihl;
+ int irid, mrid;
+
+ if (arm_tmr_et != NULL)
+ return (EBUSY);
+
+ mrid = sc->memrid;
+ sc->prv_mem = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, &mrid,
+ RF_ACTIVE);
+ if (sc->prv_mem == NULL) {
+ device_printf(sc->dev, "could not allocate prv mem resources\n");
+ return (ENXIO);
+ }
+ tmr_prv_write_4(sc, PRV_TIMER_CTRL, 0x00000000);
+
+ irid = sc->irqrid;
+ sc->prv_irq = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, &irid, RF_ACTIVE);
+ if (sc->prv_irq == NULL) {
+ bus_release_resource(sc->dev, SYS_RES_MEMORY, mrid, sc->prv_mem);
+ device_printf(sc->dev, "could not allocate prv irq resources\n");
+ return (ENXIO);
+ }
+
+ if (bus_setup_intr(sc->dev, sc->prv_irq, INTR_TYPE_CLK, arm_tmr_intr,
+ NULL, sc, &ihl) != 0) {
+ bus_release_resource(sc->dev, SYS_RES_MEMORY, mrid, sc->prv_mem);
+ bus_release_resource(sc->dev, SYS_RES_IRQ, irid, sc->prv_irq);
+ device_printf(sc->dev, "unable to setup the et irq handler.\n");
+ return (ENXIO);
+ }
+
+ /*
+ * Setup and register the eventtimer. Most event timers set their min
+ * and max period values to some value calculated from the clock
+ * frequency. We might not know yet what our runtime clock frequency
+ * will be, so we just use some safe values. A max of 2 seconds ensures
+ * that even if our base clock frequency is 2GHz (meaning a 4GHz CPU),
+ * we won't overflow our 32-bit timer count register. A min of 20
+ * nanoseconds is pretty much completely arbitrary.
+ */
+ sc->et.et_name = "MPCore";
+ sc->et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT | ET_FLAGS_PERCPU;
+ sc->et.et_quality = 1000;
+ sc->et.et_frequency = sc->clkfreq;
+ sc->et.et_min_period = 20 * SBT_1NS;
+ sc->et.et_max_period = 2 * SBT_1S;
+ sc->et.et_start = arm_tmr_start;
+ sc->et.et_stop = arm_tmr_stop;
+ sc->et.et_priv = sc;
+ et_register(&sc->et);
+ arm_tmr_et = &sc->et;
+
+ return (0);
+}
+
/**
* arm_tmr_attach - attaches the timer to the simplebus
* @dev: new device
@@ -277,21 +373,19 @@ arm_tmr_probe(device_t dev)
static int
arm_tmr_attach(device_t dev)
{
- struct arm_tmr_softc *sc = device_get_softc(dev);
+ struct arm_tmr_softc *sc;
phandle_t node;
pcell_t clock;
- void *ihl;
- boolean_t fixed_freq;
+ int et_err, tc_err, tmrtype;
- if (arm_tmr_sc)
- return (ENXIO);
+ sc = device_get_softc(dev);
+ sc->dev = dev;
- if (platform_arm_tmr_freq == ARM_TMR_FREQUENCY_VARIES) {
- fixed_freq = false;
+ if (arm_tmr_freq_varies) {
+ sc->clkfreq = arm_tmr_freq;
} else {
- fixed_freq = true;
- if (platform_arm_tmr_freq != 0) {
- sc->clkfreq = platform_arm_tmr_freq;
+ if (arm_tmr_freq != 0) {
+ sc->clkfreq = arm_tmr_freq;
} else {
/* Get the base clock frequency */
node = ofw_bus_get_node(dev);
@@ -305,66 +399,40 @@ arm_tmr_attach(device_t dev)
}
}
- if (bus_alloc_resources(dev, arm_tmr_spec, sc->tmr_res)) {
- device_printf(dev, "could not allocate resources\n");
- return (ENXIO);
- }
-
- /* Global timer interface */
- sc->gbl_bst = rman_get_bustag(sc->tmr_res[0]);
- sc->gbl_bsh = rman_get_bushandle(sc->tmr_res[0]);
-
- /* Private per-CPU timer interface */
- sc->prv_bst = rman_get_bustag(sc->tmr_res[2]);
- sc->prv_bsh = rman_get_bushandle(sc->tmr_res[2]);
-
- arm_tmr_sc = sc;
-
- /* Disable both timers to start off */
- tmr_prv_write_4(PRV_TIMER_CTRL, 0x00000000);
- tmr_gbl_write_4(GBL_TIMER_CTRL, 0x00000000);
-
- if (bus_setup_intr(dev, sc->tmr_res[3], INTR_TYPE_CLK, arm_tmr_intr,
- NULL, sc, &ihl) != 0) {
- bus_release_resources(dev, arm_tmr_spec, sc->tmr_res);
- device_printf(dev, "Unable to setup the clock irq handler.\n");
- return (ENXIO);
- }
+ tmrtype = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
+ tc_err = ENXIO;
+ et_err = ENXIO;
/*
- * If the clock is fixed-frequency, setup and enable the global timer to
- * use as the timecounter. If it's variable frequency it won't work as
- * a timecounter. We also can't use it for DELAY(), so hopefully the
- * platform provides its own implementation. If it doesn't, ours will
+ * If we're handling the global timer and it is fixed-frequency, set it
+ * up to use as a timecounter. If it's variable frequency it won't work
+ * as a timecounter. We also can't use it for DELAY(), so hopefully the
+ * platform provides its own implementation. If it doesn't, ours will
* get used, but since the frequency isn't set, it will only use the
* bogus loop counter.
*/
- if (fixed_freq) {
- tmr_gbl_write_4(GBL_TIMER_CTRL, GBL_TIMER_CTRL_TIMER_ENABLE);
- arm_tmr_timecount.tc_frequency = sc->clkfreq;
- tc_init(&arm_tmr_timecount);
+ if (tmrtype & TMR_GBL) {
+ if (!arm_tmr_freq_varies)
+ tc_err = attach_tc(sc);
+ else if (bootverbose)
+ device_printf(sc->dev,
+ "not using variable-frequency device as timecounter");
+ sc->memrid++;
+ sc->irqrid++;
+ }
+
+ /* If we are handling the private timer, set it up as an eventtimer. */
+ if (tmrtype & TMR_PRV) {
+ et_err = attach_et(sc);
}
/*
- * Setup and register the eventtimer. Most event timers set their min
- * and max period values to some value calculated from the clock
- * frequency. We might not know yet what our runtime clock frequency
- * will be, so we just use some safe values. A max of 2 seconds ensures
- * that even if our base clock frequency is 2GHz (meaning a 4GHz CPU),
- * we won't overflow our 32-bit timer count register. A min of 20
- * nanoseconds is pretty much completely arbitrary.
+ * If we didn't successfully set up a timecounter or eventtimer then we
+ * didn't actually attach at all, return error.
*/
- sc->et.et_name = "MPCore";
- sc->et.et_flags = ET_FLAGS_PERIODIC | ET_FLAGS_ONESHOT | ET_FLAGS_PERCPU;
- sc->et.et_quality = 1000;
- sc->et.et_frequency = sc->clkfreq;
- sc->et.et_min_period = 20 * SBT_1NS;
- sc->et.et_max_period = 2 * SBT_1S;
- sc->et.et_start = arm_tmr_start;
- sc->et.et_stop = arm_tmr_stop;
- sc->et.et_priv = sc;
- et_register(&sc->et);
-
+ if (tc_err != 0 && et_err != 0) {
+ return (ENXIO);
+ }
return (0);
}
@@ -384,6 +452,8 @@ static devclass_t arm_tmr_devclass;
EARLY_DRIVER_MODULE(mp_tmr, simplebus, arm_tmr_driver, arm_tmr_devclass, 0, 0,
BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE);
+EARLY_DRIVER_MODULE(mp_tmr, ofwbus, arm_tmr_driver, arm_tmr_devclass, 0, 0,
+ BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE);
/*
* Handle a change in clock frequency. The mpcore timer runs at half the CPU
@@ -404,10 +474,14 @@ void
arm_tmr_change_frequency(uint64_t newfreq)
{
- if (arm_tmr_sc == NULL)
- platform_arm_tmr_freq = newfreq;
- else
- et_change_frequency(&arm_tmr_sc->et, newfreq);
+ if (newfreq == ARM_TMR_FREQUENCY_VARIES) {
+ arm_tmr_freq_varies = true;
+ return;
+ }
+
+ arm_tmr_freq = newfreq;
+ if (arm_tmr_et != NULL)
+ et_change_frequency(arm_tmr_et, newfreq);
}
/**
@@ -424,12 +498,13 @@ arm_tmr_change_frequency(uint64_t newfreq)
static void __used /* Must emit function code for the weak ref below. */
arm_tmr_DELAY(int usec)
{
+ struct arm_tmr_softc *sc;
int32_t counts_per_usec;
int32_t counts;
uint32_t first, last;
/* Check the timers are setup, if not just use a for loop for the meantime */
- if (arm_tmr_sc == NULL || arm_tmr_timecount.tc_frequency == 0) {
+ if (arm_tmr_tc == NULL || arm_tmr_timecount.tc_frequency == 0) {
for (; usec > 0; usec--)
for (counts = 200; counts > 0; counts--)
cpufunc_nullop(); /* Prevent gcc from optimizing
@@ -438,6 +513,8 @@ arm_tmr_DELAY(int usec)
return;
}
+ sc = arm_tmr_tc->tc_priv;
+
/* Get the number of times to count */
counts_per_usec = ((arm_tmr_timecount.tc_frequency / 1000000) + 1);
@@ -452,10 +529,10 @@ arm_tmr_DELAY(int usec)
else
counts = usec * counts_per_usec;
- first = tmr_gbl_read_4(GBL_TIMER_COUNT_LOW);
+ first = tmr_gbl_read_4(sc, GBL_TIMER_COUNT_LOW);
while (counts > 0) {
- last = tmr_gbl_read_4(GBL_TIMER_COUNT_LOW);
+ last = tmr_gbl_read_4(sc, GBL_TIMER_COUNT_LOW);
counts -= (int32_t)(last - first);
first = last;
}
diff --git a/sys/arm/at91/at91rm92reg.h b/sys/arm/at91/at91rm92reg.h
index 5db3d7e..16fc82c 100644
--- a/sys/arm/at91/at91rm92reg.h
+++ b/sys/arm/at91/at91rm92reg.h
@@ -124,7 +124,7 @@
* 9: USART 3
* 10: MMC Interface
* 11: USB device port
- * 12: Two-wirte interface
+ * 12: Two-wire interface
* 13: SPI
* 14: SSC
* 15: SSC
@@ -134,7 +134,7 @@
* 19: Timer Counter 2
* 20: Timer Counter 3
* 21: Timer Counter 4
- * 22: Timer Counter 6
+ * 22: Timer Counter 5
* 23: USB Host port
* 24: Ethernet
* 25: AIC
diff --git a/sys/arm/at91/at91sam9260reg.h b/sys/arm/at91/at91sam9260reg.h
index 839b714..1609ed1 100644
--- a/sys/arm/at91/at91sam9260reg.h
+++ b/sys/arm/at91/at91sam9260reg.h
@@ -164,7 +164,7 @@
* 8: USART 2
* 9: MMC Interface
* 10: USB device port
- * 11: Two-wirte interface
+ * 11: Two-wire interface
* 12: SPI 0
* 13: SPI 1
* 14: SSC
@@ -231,7 +231,7 @@
#define AT91SAM9260_WDT_SIZE 0x10
#define AT91SAM9260_PIT_BASE 0xffffd30
-#define AT91SAM9260_PIT_SIZE 10
+#define AT91SAM9260_PIT_SIZE 0x10
#define AT91SAM9260_SMC_BASE 0xfffec00
#define AT91SAM9260_SMC_SIZE 0x200
diff --git a/sys/arm/at91/at91sam9g20reg.h b/sys/arm/at91/at91sam9g20reg.h
index 59f6099..d29dfa5 100644
--- a/sys/arm/at91/at91sam9g20reg.h
+++ b/sys/arm/at91/at91sam9g20reg.h
@@ -165,7 +165,7 @@
* 8: USART 2
* 9: MMC Interface
* 10: USB device port
- * 11: Two-wirte interface
+ * 11: Two-wire interface
* 12: SPI 0
* 13: SPI 1
* 14: SSC
diff --git a/sys/arm/at91/at91sam9g45reg.h b/sys/arm/at91/at91sam9g45reg.h
index a92e3b9..c063748 100644
--- a/sys/arm/at91/at91sam9g45reg.h
+++ b/sys/arm/at91/at91sam9g45reg.h
@@ -142,13 +142,13 @@
* 9: USART 2
* 10: USART 3
* 11: Multimedia Card interface 0
- * 12: Two-wirte interface 0
- * 13: Two-wirte interface 1
+ * 12: Two-wire interface 0
+ * 13: Two-wire interface 1
* 14: SPI 0
* 15: SPI 1
* 16: SSC 0
- * 17: SSC 0
- * 18: Timer Counter 0, 2, 3, 4, 5
+ * 17: SSC 1
+ * 18: Timer Counter 0, 1, 2, 3, 4, 5
* 19: PWM
* 20: Touch Screen ADC
* 21: DMA
diff --git a/sys/arm/at91/at91sam9x5reg.h b/sys/arm/at91/at91sam9x5reg.h
index 17c43ff..dd777f9 100644
--- a/sys/arm/at91/at91sam9x5reg.h
+++ b/sys/arm/at91/at91sam9x5reg.h
@@ -151,9 +151,9 @@
* 6: USART 1
* 7: USART 2
* 8: USART 3
- * 9: Two-wirte interface
- * 10: Two-wirte interface
- * 11: Two-wirte interface
+ * 9: Two-wire interface
+ * 10: Two-wire interface
+ * 11: Two-wire interface
* 12: HSMCI Interface
* 13: SPI 0
* 14: SPI 1
diff --git a/sys/arm/conf/LN2410SBC b/sys/arm/conf/LN2410SBC
index 4c7480c..d4407eb 100644
--- a/sys/arm/conf/LN2410SBC
+++ b/sys/arm/conf/LN2410SBC
@@ -19,7 +19,7 @@
ident LN2410SBC
-include "../s3c2xx0/std.ln2410sbc"
+include "../samsung/s3c2xx0/std.ln2410sbc"
#To statically compile in device wiring instead of /boot/device.hints
#hints "GENERIC.hints" # Default places to look for devices.
makeoptions MODULES_OVERRIDE=""
diff --git a/sys/arm/conf/NOTES b/sys/arm/conf/NOTES
index 6a0218d..fa413bf 100644
--- a/sys/arm/conf/NOTES
+++ b/sys/arm/conf/NOTES
@@ -19,7 +19,7 @@ files "../mv/discovery/files.db78xxx"
files "../mv/kirkwood/files.kirkwood"
files "../mv/orion/files.db88f5xxx"
files "../mv/orion/files.ts7800"
-files "../s3c2xx0/files.s3c2xx0"
+files "../samsung/s3c2xx0/files.s3c2xx0"
files "../xscale/i80321/files.ep80219"
files "../xscale/i80321/files.i80219"
files "../xscale/i80321/files.i80321"
diff --git a/sys/arm/conf/SOCKIT b/sys/arm/conf/SOCKIT
index e524f30..d56a7f2 100644
--- a/sys/arm/conf/SOCKIT
+++ b/sys/arm/conf/SOCKIT
@@ -124,6 +124,7 @@ device ether
device mii
device smsc
device smscphy
+device dwc
# USB ethernet support, requires miibus
device miibus
diff --git a/sys/arm/s3c2xx0/files.s3c2xx0 b/sys/arm/s3c2xx0/files.s3c2xx0
deleted file mode 100644
index 5ad2890..0000000
--- a/sys/arm/s3c2xx0/files.s3c2xx0
+++ /dev/null
@@ -1,15 +0,0 @@
-# $FreeBSD$
-arm/arm/bus_space_asm_generic.S standard
-arm/arm/bus_space_generic.c standard
-arm/arm/cpufunc_asm_arm9.S standard
-arm/s3c2xx0/board_ln2410sbc.c optional board_ln2410sbc
-arm/s3c2xx0/s3c24x0_rtc.c standard
-arm/s3c2xx0/s3c24x0_machdep.c standard
-arm/s3c2xx0/s3c24x0.c standard
-arm/s3c2xx0/s3c2xx0_space.c standard
-arm/s3c2xx0/s3c24x0_clk.c standard
-arm/s3c2xx0/uart_bus_s3c2410.c optional uart
-arm/s3c2xx0/uart_cpu_s3c2410.c optional uart
-arm/s3c2xx0/uart_dev_s3c2410.c optional uart
-
-dev/usb/controller/ohci_s3c24x0.c optional ohci
diff --git a/sys/arm/s3c2xx0/board_ln2410sbc.c b/sys/arm/samsung/s3c2xx0/board_ln2410sbc.c
index 5f5ac90..d0f474e 100644
--- a/sys/arm/s3c2xx0/board_ln2410sbc.c
+++ b/sys/arm/samsung/s3c2xx0/board_ln2410sbc.c
@@ -30,8 +30,8 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
-#include <arm/s3c2xx0/s3c2410reg.h>
-#include <arm/s3c2xx0/s3c2xx0board.h>
+#include <arm/samsung/s3c2xx0/s3c2410reg.h>
+#include <arm/samsung/s3c2xx0/s3c2xx0board.h>
extern vm_offset_t s3c2410_uart_vaddr;
diff --git a/sys/arm/samsung/s3c2xx0/files.s3c2xx0 b/sys/arm/samsung/s3c2xx0/files.s3c2xx0
new file mode 100644
index 0000000..eb02fc5
--- /dev/null
+++ b/sys/arm/samsung/s3c2xx0/files.s3c2xx0
@@ -0,0 +1,15 @@
+# $FreeBSD$
+arm/arm/bus_space_asm_generic.S standard
+arm/arm/bus_space_generic.c standard
+arm/arm/cpufunc_asm_arm9.S standard
+arm/samsung/s3c2xx0/board_ln2410sbc.c optional board_ln2410sbc
+arm/samsung/s3c2xx0/s3c24x0_rtc.c standard
+arm/samsung/s3c2xx0/s3c24x0_machdep.c standard
+arm/samsung/s3c2xx0/s3c24x0.c standard
+arm/samsung/s3c2xx0/s3c2xx0_space.c standard
+arm/samsung/s3c2xx0/s3c24x0_clk.c standard
+arm/samsung/s3c2xx0/uart_bus_s3c2410.c optional uart
+arm/samsung/s3c2xx0/uart_cpu_s3c2410.c optional uart
+arm/samsung/s3c2xx0/uart_dev_s3c2410.c optional uart
+
+dev/usb/controller/ohci_s3c24x0.c optional ohci
diff --git a/sys/arm/s3c2xx0/s3c2410reg.h b/sys/arm/samsung/s3c2xx0/s3c2410reg.h
index 89298ea..e13ee3c 100644
--- a/sys/arm/s3c2xx0/s3c2410reg.h
+++ b/sys/arm/samsung/s3c2xx0/s3c2410reg.h
@@ -42,7 +42,7 @@
#define _ARM_S3C2XX0_S3C2410REG_H_
/* common definitions for S3C2410 and S3C2440 */
-#include <arm/s3c2xx0/s3c24x0reg.h>
+#include <arm/samsung/s3c2xx0/s3c24x0reg.h>
/*
* Memory Map
diff --git a/sys/arm/s3c2xx0/s3c2410var.h b/sys/arm/samsung/s3c2xx0/s3c2410var.h
index b17784d..1ce9b99 100644
--- a/sys/arm/s3c2xx0/s3c2410var.h
+++ b/sys/arm/samsung/s3c2xx0/s3c2410var.h
@@ -34,7 +34,7 @@
#ifndef _ARM_S3C2410VAR_H_
#define _ARM_S3C2410VAR_H_
-#include <arm/s3c2xx0/s3c24x0var.h>
+#include <arm/samsung/s3c2xx0/s3c24x0var.h>
int s3c2410_sscom_cnattach(bus_space_tag_t, int, int, int, tcflag_t);
int s3c2410_sscom_kgdb_attach(bus_space_tag_t, int, int, int, tcflag_t);
diff --git a/sys/arm/s3c2xx0/s3c2440reg.h b/sys/arm/samsung/s3c2xx0/s3c2440reg.h
index f3cda60..2304b69 100644
--- a/sys/arm/s3c2xx0/s3c2440reg.h
+++ b/sys/arm/samsung/s3c2xx0/s3c2440reg.h
@@ -36,7 +36,7 @@
#define _ARM_S3C2XX0_S3C2440REG_H_
/* common definitions for S3C2410 and S3C2440 */
-#include <arm/s3c2xx0/s3c24x0reg.h>
+#include <arm/samsung/s3c2xx0/s3c24x0reg.h>
/*
* Memory Map
diff --git a/sys/arm/s3c2xx0/s3c24x0.c b/sys/arm/samsung/s3c2xx0/s3c24x0.c
index 01e1135..49acdc6 100644
--- a/sys/arm/s3c2xx0/s3c24x0.c
+++ b/sys/arm/samsung/s3c2xx0/s3c24x0.c
@@ -49,9 +49,9 @@ __FBSDID("$FreeBSD$");
#include <machine/cpufunc.h>
#include <machine/intr.h>
-#include <arm/s3c2xx0/s3c2410reg.h>
-#include <arm/s3c2xx0/s3c2440reg.h>
-#include <arm/s3c2xx0/s3c24x0var.h>
+#include <arm/samsung/s3c2xx0/s3c2410reg.h>
+#include <arm/samsung/s3c2xx0/s3c2440reg.h>
+#include <arm/samsung/s3c2xx0/s3c24x0var.h>
#include <sys/rman.h>
#define S3C2XX0_XTAL_CLK 12000000
diff --git a/sys/arm/s3c2xx0/s3c24x0_clk.c b/sys/arm/samsung/s3c2xx0/s3c24x0_clk.c
index 35ce349..d4c4e98 100644
--- a/sys/arm/s3c2xx0/s3c24x0_clk.c
+++ b/sys/arm/samsung/s3c2xx0/s3c24x0_clk.c
@@ -48,8 +48,8 @@ __FBSDID("$FreeBSD$");
#include <machine/frame.h>
#include <machine/resource.h>
#include <machine/intr.h>
-#include <arm/s3c2xx0/s3c24x0reg.h>
-#include <arm/s3c2xx0/s3c24x0var.h>
+#include <arm/samsung/s3c2xx0/s3c24x0reg.h>
+#include <arm/samsung/s3c2xx0/s3c24x0var.h>
struct s3c24x0_timer_softc {
device_t dev;
diff --git a/sys/arm/s3c2xx0/s3c24x0_machdep.c b/sys/arm/samsung/s3c2xx0/s3c24x0_machdep.c
index 5264e7a..411447b 100644
--- a/sys/arm/s3c2xx0/s3c24x0_machdep.c
+++ b/sys/arm/samsung/s3c2xx0/s3c24x0_machdep.c
@@ -89,9 +89,9 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <sys/reboot.h>
-#include <arm/s3c2xx0/s3c24x0var.h>
-#include <arm/s3c2xx0/s3c2410reg.h>
-#include <arm/s3c2xx0/s3c2xx0board.h>
+#include <arm/samsung/s3c2xx0/s3c24x0var.h>
+#include <arm/samsung/s3c2xx0/s3c2410reg.h>
+#include <arm/samsung/s3c2xx0/s3c2xx0board.h>
/* Page table for mapping proc0 zero page */
#define KERNEL_PT_SYS 0
diff --git a/sys/arm/s3c2xx0/s3c24x0_rtc.c b/sys/arm/samsung/s3c2xx0/s3c24x0_rtc.c
index 8845c44..f0d35c9 100644
--- a/sys/arm/s3c2xx0/s3c24x0_rtc.c
+++ b/sys/arm/samsung/s3c2xx0/s3c24x0_rtc.c
@@ -39,7 +39,7 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
-#include <arm/s3c2xx0/s3c24x0reg.h>
+#include <arm/samsung/s3c2xx0/s3c24x0reg.h>
#include "clock_if.h"
diff --git a/sys/arm/s3c2xx0/s3c24x0reg.h b/sys/arm/samsung/s3c2xx0/s3c24x0reg.h
index e60ce88..2004e11 100644
--- a/sys/arm/s3c2xx0/s3c24x0reg.h
+++ b/sys/arm/samsung/s3c2xx0/s3c24x0reg.h
@@ -43,7 +43,7 @@
#define _ARM_S3C2XX0_S3C24X0REG_H_
/* common definitions for S3C2800, S3C2410 and S3C2440 */
-#include <arm/s3c2xx0/s3c2xx0reg.h>
+#include <arm/samsung/s3c2xx0/s3c2xx0reg.h>
/*
* Map the device registers into kernel space.
diff --git a/sys/arm/s3c2xx0/s3c24x0var.h b/sys/arm/samsung/s3c2xx0/s3c24x0var.h
index 5209da8..2ee042e 100644
--- a/sys/arm/s3c2xx0/s3c24x0var.h
+++ b/sys/arm/samsung/s3c2xx0/s3c24x0var.h
@@ -34,7 +34,7 @@
#ifndef _ARM_S3C24X0VAR_H_
#define _ARM_S3C24X0VAR_H_
-#include <arm/s3c2xx0/s3c2xx0var.h>
+#include <arm/samsung/s3c2xx0/s3c2xx0var.h>
struct s3c24x0_softc {
struct s3c2xx0_softc sc_sx;
diff --git a/sys/arm/s3c2xx0/s3c2xx0_space.c b/sys/arm/samsung/s3c2xx0/s3c2xx0_space.c
index fe01d2b..fe01d2b 100644
--- a/sys/arm/s3c2xx0/s3c2xx0_space.c
+++ b/sys/arm/samsung/s3c2xx0/s3c2xx0_space.c
diff --git a/sys/arm/s3c2xx0/s3c2xx0board.h b/sys/arm/samsung/s3c2xx0/s3c2xx0board.h
index 8a2c631..8a2c631 100644
--- a/sys/arm/s3c2xx0/s3c2xx0board.h
+++ b/sys/arm/samsung/s3c2xx0/s3c2xx0board.h
diff --git a/sys/arm/s3c2xx0/s3c2xx0reg.h b/sys/arm/samsung/s3c2xx0/s3c2xx0reg.h
index 627c3ca..627c3ca 100644
--- a/sys/arm/s3c2xx0/s3c2xx0reg.h
+++ b/sys/arm/samsung/s3c2xx0/s3c2xx0reg.h
diff --git a/sys/arm/s3c2xx0/s3c2xx0var.h b/sys/arm/samsung/s3c2xx0/s3c2xx0var.h
index fea0982..fea0982 100644
--- a/sys/arm/s3c2xx0/s3c2xx0var.h
+++ b/sys/arm/samsung/s3c2xx0/s3c2xx0var.h
diff --git a/sys/arm/s3c2xx0/std.ln2410sbc b/sys/arm/samsung/s3c2xx0/std.ln2410sbc
index a76a849..1f1143e 100644
--- a/sys/arm/s3c2xx0/std.ln2410sbc
+++ b/sys/arm/samsung/s3c2xx0/std.ln2410sbc
@@ -1,5 +1,5 @@
#$FreeBSD$
-include "../s3c2xx0/std.s3c2410"
+include "../samsung/s3c2xx0/std.s3c2410"
makeoptions KERNPHYSADDR=0x30000000
makeoptions KERNVIRTADDR=0xc0000000
diff --git a/sys/arm/s3c2xx0/std.s3c2410 b/sys/arm/samsung/s3c2xx0/std.s3c2410
index 266d9e7..4f55b93 100644
--- a/sys/arm/s3c2xx0/std.s3c2410
+++ b/sys/arm/samsung/s3c2xx0/std.s3c2410
@@ -1,6 +1,6 @@
# $FreeBSD$
-files "../s3c2xx0/files.s3c2xx0"
+files "../samsung/s3c2xx0/files.s3c2xx0"
cpu CPU_ARM9
machine arm
diff --git a/sys/arm/s3c2xx0/uart_bus_s3c2410.c b/sys/arm/samsung/s3c2xx0/uart_bus_s3c2410.c
index 41c750a..2102d8b 100644
--- a/sys/arm/s3c2xx0/uart_bus_s3c2410.c
+++ b/sys/arm/samsung/s3c2xx0/uart_bus_s3c2410.c
@@ -15,7 +15,7 @@ __FBSDID("$FreeBSD$");
#include <dev/uart/uart_bus.h>
#include <dev/uart/uart_cpu.h>
-#include <arm/s3c2xx0/s3c24x0reg.h>
+#include <arm/samsung/s3c2xx0/s3c24x0reg.h>
#include "uart_if.h"
diff --git a/sys/arm/s3c2xx0/uart_cpu_s3c2410.c b/sys/arm/samsung/s3c2xx0/uart_cpu_s3c2410.c
index 2ed036b..37b668e 100644
--- a/sys/arm/s3c2xx0/uart_cpu_s3c2410.c
+++ b/sys/arm/samsung/s3c2xx0/uart_cpu_s3c2410.c
@@ -37,7 +37,7 @@ __FBSDID("$FreeBSD$");
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
-#include <arm/s3c2xx0/s3c2xx0var.h>
+#include <arm/samsung/s3c2xx0/s3c2xx0var.h>
bus_space_tag_t uart_bus_space_io;
bus_space_tag_t uart_bus_space_mem;
diff --git a/sys/arm/s3c2xx0/uart_dev_s3c2410.c b/sys/arm/samsung/s3c2xx0/uart_dev_s3c2410.c
index aadd835..2ee1217 100644
--- a/sys/arm/s3c2xx0/uart_dev_s3c2410.c
+++ b/sys/arm/samsung/s3c2xx0/uart_dev_s3c2410.c
@@ -41,10 +41,10 @@ __FBSDID("$FreeBSD$");
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
#include <dev/uart/uart_bus.h>
-#include <arm/s3c2xx0/s3c2440reg.h>
-#include <arm/s3c2xx0/uart_dev_s3c2410.h>
-#include <arm/s3c2xx0/s3c2xx0reg.h>
-#include <arm/s3c2xx0/s3c2xx0var.h>
+#include <arm/samsung/s3c2xx0/s3c2440reg.h>
+#include <arm/samsung/s3c2xx0/uart_dev_s3c2410.h>
+#include <arm/samsung/s3c2xx0/s3c2xx0reg.h>
+#include <arm/samsung/s3c2xx0/s3c2xx0var.h>
#include "uart_if.h"
/* Finds the subirq from the parent */
diff --git a/sys/arm/s3c2xx0/uart_dev_s3c2410.h b/sys/arm/samsung/s3c2xx0/uart_dev_s3c2410.h
index 5479796..5479796 100644
--- a/sys/arm/s3c2xx0/uart_dev_s3c2410.h
+++ b/sys/arm/samsung/s3c2xx0/uart_dev_s3c2410.h
diff --git a/sys/boot/efi/include/eficonsctl.h b/sys/boot/efi/include/eficonsctl.h
index 2acf116..36dd2c1 100644
--- a/sys/boot/efi/include/eficonsctl.h
+++ b/sys/boot/efi/include/eficonsctl.h
@@ -132,122 +132,3 @@ struct _EFI_CONSOLE_CONTROL_PROTOCOL {
extern EFI_GUID gEfiConsoleControlProtocolGuid;
#endif
-/*-
- * Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.
- *
- * This program and the accompanying materials are licensed and made available
- * under the terms and conditions of the BSD License which accompanies this
- * distribution. The full text of the license may be found at
- * http://opensource.org/licenses/bsd-license.php
- *
- * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR
- * IMPLIED.
- *
- * Original Module Name: ConsoleControl.h
- * Abstract: Abstraction of a Text mode or GOP/UGA screen
- */
-
-/* $FreeBSD */
-
-#ifndef _EFI_CONS_CTL_H
-#define _EFI_CONS_CTL_H
-
-#define EFI_CONSOLE_CONTROL_PROTOCOL_GUID \
- { 0xf42f7782, 0x12e, 0x4c12, {0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21} }
-
-typedef struct _EFI_CONSOLE_CONTROL_PROTOCOL EFI_CONSOLE_CONTROL_PROTOCOL;
-
-
-typedef enum {
- EfiConsoleControlScreenText,
- EfiConsoleControlScreenGraphics,
- EfiConsoleControlScreenMaxValue
-} EFI_CONSOLE_CONTROL_SCREEN_MODE;
-
-
-typedef
-EFI_STATUS
-(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE) (
- IN EFI_CONSOLE_CONTROL_PROTOCOL *This,
- OUT EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode,
- OUT BOOLEAN *GopUgaExists, OPTIONAL
- OUT BOOLEAN *StdInLocked OPTIONAL
- )
-/*++
-
- Routine Description:
- Return the current video mode information. Also returns info about existence
- of Graphics Output devices or UGA Draw devices in system, and if the Std In
- device is locked. All the arguments are optional and only returned if a non
- NULL pointer is passed in.
-
- Arguments:
- This - Protocol instance pointer.
- Mode - Are we in text of grahics mode.
- GopUgaExists - TRUE if Console Spliter has found a GOP or UGA device
- StdInLocked - TRUE if StdIn device is keyboard locked
-
- Returns:
- EFI_SUCCESS - Mode information returned.
-
---*/
-;
-
-
-typedef
-EFI_STATUS
-(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE) (
- IN EFI_CONSOLE_CONTROL_PROTOCOL *This,
- IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode
- )
-/*++
-
- Routine Description:
- Set the current mode to either text or graphics. Graphics is
- for Quiet Boot.
-
- Arguments:
- This - Protocol instance pointer.
- Mode - Mode to set the
-
- Returns:
- EFI_SUCCESS - Mode information returned.
-
---*/
-;
-
-
-typedef
-EFI_STATUS
-(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN) (
- IN EFI_CONSOLE_CONTROL_PROTOCOL *This,
- IN CHAR16 *Password
- )
-/*++
-
- Routine Description:
- Lock Std In devices until Password is typed.
-
- Arguments:
- This - Protocol instance pointer.
- Password - Password needed to unlock screen. NULL means unlock keyboard
-
- Returns:
- EFI_SUCCESS - Mode information returned.
- EFI_DEVICE_ERROR - Std In not locked
-
---*/
-;
-
-
-
-struct _EFI_CONSOLE_CONTROL_PROTOCOL {
- EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE GetMode;
- EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE SetMode;
- EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN LockStdIn;
-};
-
-extern EFI_GUID gEfiConsoleControlProtocolGuid;
-
-#endif
diff --git a/sys/boot/fdt/dts/arm/socfpga-sockit.dts b/sys/boot/fdt/dts/arm/socfpga-sockit.dts
index 1cd90ea..d76b6cf 100644
--- a/sys/boot/fdt/dts/arm/socfpga-sockit.dts
+++ b/sys/boot/fdt/dts/arm/socfpga-sockit.dts
@@ -51,6 +51,10 @@
usb1: usb@ffb40000 {
status = "okay";
};
+
+ gmac1: ethernet@ff702000 {
+ status = "okay";
+ };
};
chosen {
diff --git a/sys/boot/fdt/dts/arm/socfpga.dtsi b/sys/boot/fdt/dts/arm/socfpga.dtsi
index e1b56cc..2480484 100644
--- a/sys/boot/fdt/dts/arm/socfpga.dtsi
+++ b/sys/boot/fdt/dts/arm/socfpga.dtsi
@@ -71,6 +71,11 @@
interrupt-parent = < &GIC >;
};
+ sysmgr: sysmgr@ffd08000 {
+ compatible = "altr,sys-mgr";
+ reg = <0xffd08000 0x1000>;
+ };
+
rstmgr: rstmgr@ffd05000 {
compatible = "altr,rst-mgr";
reg = <0xffd05000 0x1000>;
@@ -127,5 +132,25 @@
dr_mode = "host";
status = "disabled";
};
+
+ gmac0: ethernet@ff700000 {
+ compatible = "altr,socfpga-stmmac",
+ "snps,dwmac-3.70a", "snps,dwmac";
+ reg = <0xff700000 0x2000>;
+ interrupts = <147>;
+ interrupt-parent = <&GIC>;
+ phy-mode = "rgmii";
+ status = "disabled";
+ };
+
+ gmac1: ethernet@ff702000 {
+ compatible = "altr,socfpga-stmmac",
+ "snps,dwmac-3.70a", "snps,dwmac";
+ reg = <0xff702000 0x2000>;
+ interrupts = <152>;
+ interrupt-parent = <&GIC>;
+ phy-mode = "rgmii";
+ status = "disabled";
+ };
};
};
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index 9a19374..098c317 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -440,7 +440,7 @@ static void ctl_enqueue_rtr(union ctl_io *io);
static void ctl_enqueue_done(union ctl_io *io);
static void ctl_enqueue_isc(union ctl_io *io);
static const struct ctl_cmd_entry *
- ctl_get_cmd_entry(struct ctl_scsiio *ctsio);
+ ctl_get_cmd_entry(struct ctl_scsiio *ctsio, int *sa);
static const struct ctl_cmd_entry *
ctl_validate_command(struct ctl_scsiio *ctsio);
static int ctl_cmd_applicable(uint8_t lun_type,
@@ -644,7 +644,7 @@ ctl_isc_event_handler(ctl_ha_channel channel, ctl_ha_event event, int param)
if (ctl_softc->ha_mode == CTL_HA_MODE_XFER) {
const struct ctl_cmd_entry *entry;
- entry = ctl_get_cmd_entry(&io->scsiio);
+ entry = ctl_get_cmd_entry(&io->scsiio, NULL);
io->io_hdr.flags &= ~CTL_FLAG_DATA_MASK;
io->io_hdr.flags |=
entry->flags & CTL_FLAG_DATA_MASK;
@@ -5279,9 +5279,10 @@ ctl_config_write_done(union ctl_io *io)
* If there is an error, though, we don't want to keep processing.
* Instead, just send status back to the initiator.
*/
- if ((io->io_hdr.flags & CTL_FLAG_IO_CONT)
- && (((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE)
- || ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS))) {
+ if ((io->io_hdr.flags & CTL_FLAG_IO_CONT) &&
+ (io->io_hdr.flags & CTL_FLAG_ABORT) == 0 &&
+ ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE ||
+ (io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS)) {
io->scsiio.io_cont(io);
return;
}
@@ -5308,12 +5309,14 @@ ctl_scsi_release(struct ctl_scsiio *ctsio)
int length, longid, thirdparty_id, resv_id;
struct ctl_softc *ctl_softc;
struct ctl_lun *lun;
+ uint32_t residx;
length = 0;
resv_id = 0;
CTL_DEBUG_PRINT(("ctl_scsi_release\n"));
+ residx = ctl_get_resindex(&ctsio->io_hdr.nexus);
lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
ctl_softc = control_softc;
@@ -5371,14 +5374,8 @@ ctl_scsi_release(struct ctl_scsiio *ctsio)
* released, though, by the initiator who made it or by one of
* several reset type events.
*/
- if (lun->flags & CTL_LUN_RESERVED) {
- if ((ctsio->io_hdr.nexus.initid.id == lun->rsv_nexus.initid.id)
- && (ctsio->io_hdr.nexus.targ_port == lun->rsv_nexus.targ_port)
- && (ctsio->io_hdr.nexus.targ_target.id ==
- lun->rsv_nexus.targ_target.id)) {
+ if ((lun->flags & CTL_LUN_RESERVED) && (lun->res_idx == residx))
lun->flags &= ~CTL_LUN_RESERVED;
- }
- }
mtx_unlock(&lun->lun_lock);
@@ -5402,6 +5399,7 @@ ctl_scsi_reserve(struct ctl_scsiio *ctsio)
uint64_t thirdparty_id;
struct ctl_softc *ctl_softc;
struct ctl_lun *lun;
+ uint32_t residx;
extent = 0;
thirdparty = 0;
@@ -5412,6 +5410,7 @@ ctl_scsi_reserve(struct ctl_scsiio *ctsio)
CTL_DEBUG_PRINT(("ctl_reserve\n"));
+ residx = ctl_get_resindex(&ctsio->io_hdr.nexus);
lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
ctl_softc = control_softc;
@@ -5460,19 +5459,14 @@ ctl_scsi_reserve(struct ctl_scsiio *ctsio)
thirdparty_id = scsi_8btou64(ctsio->kern_data_ptr);
mtx_lock(&lun->lun_lock);
- if (lun->flags & CTL_LUN_RESERVED) {
- if ((ctsio->io_hdr.nexus.initid.id != lun->rsv_nexus.initid.id)
- || (ctsio->io_hdr.nexus.targ_port != lun->rsv_nexus.targ_port)
- || (ctsio->io_hdr.nexus.targ_target.id !=
- lun->rsv_nexus.targ_target.id)) {
- ctsio->scsi_status = SCSI_STATUS_RESERV_CONFLICT;
- ctsio->io_hdr.status = CTL_SCSI_ERROR;
- goto bailout;
- }
+ if ((lun->flags & CTL_LUN_RESERVED) && (lun->res_idx != residx)) {
+ ctsio->scsi_status = SCSI_STATUS_RESERV_CONFLICT;
+ ctsio->io_hdr.status = CTL_SCSI_ERROR;
+ goto bailout;
}
lun->flags |= CTL_LUN_RESERVED;
- lun->rsv_nexus = ctsio->io_hdr.nexus;
+ lun->res_idx = residx;
ctsio->scsi_status = SCSI_STATUS_OK;
ctsio->io_hdr.status = CTL_SUCCESS;
@@ -5993,8 +5987,9 @@ ctl_write_same(struct ctl_scsiio *ctsio)
break; /* NOTREACHED */
}
- /* NDOB flag can be used only together with UNMAP */
- if ((byte2 & (SWS_NDOB | SWS_UNMAP)) == SWS_NDOB) {
+ /* NDOB and ANCHOR flags can be used only together with UNMAP */
+ if ((byte2 & SWS_UNMAP) == 0 &&
+ (byte2 & (SWS_NDOB | SWS_ANCHOR)) != 0) {
ctl_set_invalid_field(ctsio, /*sks_valid*/ 1,
/*command*/ 1, /*field*/ 1, /*bit_valid*/ 1, /*bit*/ 0);
ctl_done((union ctl_io *)ctsio);
@@ -6066,7 +6061,7 @@ ctl_unmap(struct ctl_scsiio *ctsio)
struct scsi_unmap *cdb;
struct ctl_ptr_len_flags *ptrlen;
struct scsi_unmap_header *hdr;
- struct scsi_unmap_desc *buf, *end, *range;
+ struct scsi_unmap_desc *buf, *end, *endnz, *range;
uint64_t lba;
uint32_t num_blocks;
int len, retval;
@@ -6119,6 +6114,7 @@ ctl_unmap(struct ctl_scsiio *ctsio)
buf = (struct scsi_unmap_desc *)(hdr + 1);
end = buf + len / sizeof(*buf);
+ endnz = buf;
for (range = buf; range < end; range++) {
lba = scsi_8btou64(range->lba);
num_blocks = scsi_4btoul(range->length);
@@ -6128,6 +6124,19 @@ ctl_unmap(struct ctl_scsiio *ctsio)
ctl_done((union ctl_io *)ctsio);
return (CTL_RETVAL_COMPLETE);
}
+ if (num_blocks != 0)
+ endnz = range + 1;
+ }
+
+ /*
+ * Block backend can not handle zero last range.
+ * Filter it out and return if there is nothing left.
+ */
+ len = (uint8_t *)endnz - (uint8_t *)buf;
+ if (len == 0) {
+ ctl_set_success(ctsio);
+ ctl_done((union ctl_io *)ctsio);
+ return (CTL_RETVAL_COMPLETE);
}
mtx_lock(&lun->lun_lock);
@@ -9680,13 +9689,10 @@ ctl_request_sense(struct ctl_scsiio *ctsio)
if (lun->pending_ua[initidx] != CTL_UA_NONE) {
ctl_ua_type ua_type;
- ua_type = ctl_build_ua(lun->pending_ua[initidx],
+ ua_type = ctl_build_ua(&lun->pending_ua[initidx],
sense_ptr, sense_format);
- if (ua_type != CTL_UA_NONE) {
+ if (ua_type != CTL_UA_NONE)
have_error = 1;
- /* We're reporting this UA, so clear it */
- lun->pending_ua[initidx] &= ~ua_type;
- }
}
mtx_unlock(&lun->lun_lock);
@@ -10723,45 +10729,23 @@ ctl_inquiry(struct ctl_scsiio *ctsio)
struct scsi_inquiry *cdb;
int retval;
- cdb = (struct scsi_inquiry *)ctsio->cdb;
-
- retval = 0;
-
CTL_DEBUG_PRINT(("ctl_inquiry\n"));
- /*
- * Right now, we don't support the CmdDt inquiry information.
- * This would be nice to support in the future. When we do
- * support it, we should change this test so that it checks to make
- * sure SI_EVPD and SI_CMDDT aren't both set at the same time.
- */
-#ifdef notyet
- if (((cdb->byte2 & SI_EVPD)
- && (cdb->byte2 & SI_CMDDT)))
-#endif
- if (cdb->byte2 & SI_CMDDT) {
- /*
- * Point to the SI_CMDDT bit. We might change this
- * when we support SI_CMDDT, but since both bits would be
- * "wrong", this should probably just stay as-is then.
- */
+ cdb = (struct scsi_inquiry *)ctsio->cdb;
+ if (cdb->byte2 & SI_EVPD)
+ retval = ctl_inquiry_evpd(ctsio);
+ else if (cdb->page_code == 0)
+ retval = ctl_inquiry_std(ctsio);
+ else {
ctl_set_invalid_field(ctsio,
/*sks_valid*/ 1,
/*command*/ 1,
- /*field*/ 1,
- /*bit_valid*/ 1,
- /*bit*/ 1);
+ /*field*/ 2,
+ /*bit_valid*/ 0,
+ /*bit*/ 0);
ctl_done((union ctl_io *)ctsio);
return (CTL_RETVAL_COMPLETE);
}
- if (cdb->byte2 & SI_EVPD)
- retval = ctl_inquiry_evpd(ctsio);
-#ifdef notyet
- else if (cdb->byte2 & SI_CMDDT)
- retval = ctl_inquiry_cmddt(ctsio);
-#endif
- else
- retval = ctl_inquiry_std(ctsio);
return (retval);
}
@@ -11057,8 +11041,8 @@ ctl_check_for_blockage(struct ctl_lun *lun, union ctl_io *pending_io,
|| (ooa_io->scsiio.tag_type == CTL_TAG_ORDERED)))
return (CTL_ACTION_BLOCK);
- pending_entry = ctl_get_cmd_entry(&pending_io->scsiio);
- ooa_entry = ctl_get_cmd_entry(&ooa_io->scsiio);
+ pending_entry = ctl_get_cmd_entry(&pending_io->scsiio, NULL);
+ ooa_entry = ctl_get_cmd_entry(&ooa_io->scsiio, NULL);
serialize_row = ctl_serialize_table[ooa_entry->seridx];
@@ -11231,7 +11215,7 @@ ctl_check_blocked(struct ctl_lun *lun)
}
break;
}
- entry = ctl_get_cmd_entry(&cur_blocked->scsiio);
+ entry = ctl_get_cmd_entry(&cur_blocked->scsiio, NULL);
softc = control_softc;
initidx = ctl_get_initindex(&cur_blocked->io_hdr.nexus);
@@ -11282,6 +11266,7 @@ ctl_scsiio_lun_check(struct ctl_softc *ctl_softc, struct ctl_lun *lun,
const struct ctl_cmd_entry *entry, struct ctl_scsiio *ctsio)
{
int retval;
+ uint32_t residx;
retval = 0;
@@ -11306,12 +11291,10 @@ ctl_scsiio_lun_check(struct ctl_softc *ctl_softc, struct ctl_lun *lun,
* even on reserved LUNs, and if this initiator isn't the one who
* reserved us, reject the command with a reservation conflict.
*/
+ residx = ctl_get_resindex(&ctsio->io_hdr.nexus);
if ((lun->flags & CTL_LUN_RESERVED)
&& ((entry->flags & CTL_CMD_FLAG_ALLOW_ON_RESV) == 0)) {
- if ((ctsio->io_hdr.nexus.initid.id != lun->rsv_nexus.initid.id)
- || (ctsio->io_hdr.nexus.targ_port != lun->rsv_nexus.targ_port)
- || (ctsio->io_hdr.nexus.targ_target.id !=
- lun->rsv_nexus.targ_target.id)) {
+ if (lun->res_idx != residx) {
ctsio->scsi_status = SCSI_STATUS_RESERV_CONFLICT;
ctsio->io_hdr.status = CTL_SCSI_ERROR;
retval = 1;
@@ -11319,11 +11302,8 @@ ctl_scsiio_lun_check(struct ctl_softc *ctl_softc, struct ctl_lun *lun,
}
}
- if ( (lun->flags & CTL_LUN_PR_RESERVED)
+ if ((lun->flags & CTL_LUN_PR_RESERVED)
&& ((entry->flags & CTL_CMD_FLAG_ALLOW_ON_PR_RESV) == 0)) {
- uint32_t residx;
-
- residx = ctl_get_resindex(&ctsio->io_hdr.nexus);
/*
* if we aren't registered or it's a res holder type
* reservation and this isn't the res holder then set a
@@ -11760,8 +11740,7 @@ ctl_scsiio_precheck(struct ctl_softc *ctl_softc, struct ctl_scsiio *ctsio)
if ((entry->flags & CTL_CMD_FLAG_NO_SENSE) == 0) {
ctl_ua_type ua_type;
- ua_type = lun->pending_ua[initidx];
- if (ua_type != CTL_UA_NONE) {
+ if (lun->pending_ua[initidx] != CTL_UA_NONE) {
scsi_sense_data_type sense_format;
if (lun != NULL)
@@ -11771,14 +11750,13 @@ ctl_scsiio_precheck(struct ctl_softc *ctl_softc, struct ctl_scsiio *ctsio)
else
sense_format = SSD_TYPE_FIXED;
- ua_type = ctl_build_ua(ua_type, &ctsio->sense_data,
- sense_format);
+ ua_type = ctl_build_ua(&lun->pending_ua[initidx],
+ &ctsio->sense_data, sense_format);
if (ua_type != CTL_UA_NONE) {
ctsio->scsi_status = SCSI_STATUS_CHECK_COND;
ctsio->io_hdr.status = CTL_SCSI_ERROR |
CTL_AUTOSENSE;
ctsio->sense_len = SSD_FULL_SIZE;
- lun->pending_ua[initidx] &= ~ua_type;
mtx_unlock(&lun->lun_lock);
ctl_done((union ctl_io *)ctsio);
return (retval);
@@ -11882,12 +11860,14 @@ ctl_scsiio_precheck(struct ctl_softc *ctl_softc, struct ctl_scsiio *ctsio)
}
const struct ctl_cmd_entry *
-ctl_get_cmd_entry(struct ctl_scsiio *ctsio)
+ctl_get_cmd_entry(struct ctl_scsiio *ctsio, int *sa)
{
const struct ctl_cmd_entry *entry;
int service_action;
entry = &ctl_cmd_table[ctsio->cdb[0]];
+ if (sa)
+ *sa = ((entry->flags & CTL_CMD_FLAG_SA5) != 0);
if (entry->flags & CTL_CMD_FLAG_SA5) {
service_action = ctsio->cdb[1] & SERVICE_ACTION_MASK;
entry = &((const struct ctl_cmd_entry *)
@@ -11900,12 +11880,20 @@ const struct ctl_cmd_entry *
ctl_validate_command(struct ctl_scsiio *ctsio)
{
const struct ctl_cmd_entry *entry;
- int i;
+ int i, sa;
uint8_t diff;
- entry = ctl_get_cmd_entry(ctsio);
+ entry = ctl_get_cmd_entry(ctsio, &sa);
if (entry->execute == NULL) {
- ctl_set_invalid_opcode(ctsio);
+ if (sa)
+ ctl_set_invalid_field(ctsio,
+ /*sks_valid*/ 1,
+ /*command*/ 1,
+ /*field*/ 1,
+ /*bit_valid*/ 1,
+ /*bit*/ 4);
+ else
+ ctl_set_invalid_opcode(ctsio);
ctl_done((union ctl_io *)ctsio);
return (NULL);
}
@@ -11959,7 +11947,7 @@ ctl_scsiio(struct ctl_scsiio *ctsio)
CTL_DEBUG_PRINT(("ctl_scsiio cdb[0]=%02X\n", ctsio->cdb[0]));
- entry = ctl_get_cmd_entry(ctsio);
+ entry = ctl_get_cmd_entry(ctsio, NULL);
/*
* If this I/O has been aborted, just send it straight to
@@ -12179,9 +12167,10 @@ ctl_i_t_nexus_reset(union ctl_io *io)
{
struct ctl_softc *softc = control_softc;
struct ctl_lun *lun;
- uint32_t initindex;
+ uint32_t initindex, residx;
initindex = ctl_get_initindex(&io->io_hdr.nexus);
+ residx = ctl_get_resindex(&io->io_hdr.nexus);
mtx_lock(&softc->ctl_lock);
STAILQ_FOREACH(lun, &softc->lun_list, links) {
mtx_lock(&lun->lun_lock);
@@ -12191,6 +12180,8 @@ ctl_i_t_nexus_reset(union ctl_io *io)
#ifdef CTL_WITH_CA
ctl_clear_mask(lun->have_ca, initindex);
#endif
+ if ((lun->flags & CTL_LUN_RESERVED) && (lun->res_idx == residx))
+ lun->flags &= ~CTL_LUN_RESERVED;
lun->pending_ua[initindex] |= CTL_UA_I_T_NEXUS_LOSS;
mtx_unlock(&lun->lun_lock);
}
@@ -12489,7 +12480,7 @@ ctl_handle_isc(union ctl_io *io)
* This is only used in SER_ONLY mode.
*/
free_io = 0;
- entry = ctl_get_cmd_entry(&io->scsiio);
+ entry = ctl_get_cmd_entry(&io->scsiio, NULL);
mtx_lock(&lun->lun_lock);
if (ctl_scsiio_lun_check(ctl_softc, lun,
entry, (struct ctl_scsiio *)io) != 0) {
@@ -12569,7 +12560,7 @@ ctl_cmd_pattern_match(struct ctl_scsiio *ctsio, struct ctl_error_desc *desc)
if ((pattern & CTL_LUN_PAT_MASK) == CTL_LUN_PAT_ANY)
return (CTL_LUN_PAT_ANY);
- entry = ctl_get_cmd_entry(ctsio);
+ entry = ctl_get_cmd_entry(ctsio, NULL);
filtered_pattern = entry->pattern & pattern;
diff --git a/sys/cam/ctl/ctl.h b/sys/cam/ctl/ctl.h
index 2f1f24d..fa09c0e 100644
--- a/sys/cam/ctl/ctl.h
+++ b/sys/cam/ctl/ctl.h
@@ -119,7 +119,7 @@ typedef enum {
CTL_UA_I_T_NEXUS_LOSS = 0x0008,
CTL_UA_LUN_RESET = 0x0010,
CTL_UA_LUN_CHANGE = 0x0020,
- CTL_UA_MODE_CHANGE = 0x0030,
+ CTL_UA_MODE_CHANGE = 0x0040,
CTL_UA_LOG_CHANGE = 0x0080,
CTL_UA_LVD = 0x0100,
CTL_UA_SE = 0x0200,
diff --git a/sys/cam/ctl/ctl_cmd_table.c b/sys/cam/ctl/ctl_cmd_table.c
index 0f9e9d1..eb1b0ee 100644
--- a/sys/cam/ctl/ctl_cmd_table.c
+++ b/sys/cam/ctl/ctl_cmd_table.c
@@ -636,7 +636,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] =
CTL_CMD_FLAG_OK_ON_SECONDARY |
CTL_FLAG_DATA_IN |
CTL_CMD_FLAG_ALLOW_ON_PR_RESV,
- CTL_LUN_PAT_NONE, 6, {0x08, 0xff, 0, 0xff, 0x07}},
+ CTL_LUN_PAT_NONE, 6, {0x08, 0xff, 0xff, 0xff, 0x07}},
/* 1B START STOP UNIT */
{ctl_start_stop, CTL_SERIDX_START, CTL_CMD_FLAG_OK_ON_SLUN |
@@ -694,7 +694,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] =
CTL_FLAG_DATA_IN |
CTL_CMD_FLAG_ALLOW_ON_PR_RESV,
CTL_LUN_PAT_READ | CTL_LUN_PAT_RANGE,
- 10, {0x18, 0xff, 0xff, 0xff, 0xff, 0, 0xff, 0xff, 0x07}},
+ 10, {0x1a, 0xff, 0xff, 0xff, 0xff, 0, 0xff, 0xff, 0x07}},
/* 29 READ GENERATION */
{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
@@ -702,7 +702,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] =
/* 2A WRITE(10) */
{ctl_read_write, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_SLUN| CTL_FLAG_DATA_OUT,
CTL_LUN_PAT_WRITE | CTL_LUN_PAT_RANGE,
- 10, {0x18, 0xff, 0xff, 0xff, 0xff, 0, 0xff, 0xff, 0x07}},
+ 10, {0x1a, 0xff, 0xff, 0xff, 0xff, 0, 0xff, 0xff, 0x07}},
/* 2B SEEK(10) */
{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
@@ -716,7 +716,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] =
/* 2E WRITE AND VERIFY(10) */
{ctl_read_write, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_SLUN| CTL_FLAG_DATA_OUT,
CTL_LUN_PAT_WRITE | CTL_LUN_PAT_RANGE,
- 10, {0x10, 0xff, 0xff, 0xff, 0xff, 0, 0xff, 0xff, 0x07}},
+ 10, {0x12, 0xff, 0xff, 0xff, 0xff, 0, 0xff, 0xff, 0x07}},
/* 2F VERIFY(10) */
{ctl_verify, CTL_SERIDX_READ, CTL_CMD_FLAG_OK_ON_SLUN |
@@ -890,7 +890,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] =
CTL_CMD_FLAG_OK_ON_SECONDARY |
CTL_FLAG_DATA_IN |
CTL_CMD_FLAG_ALLOW_ON_PR_RESV,
- CTL_LUN_PAT_NONE, 10, {0x18, 0xff, 0, 0, 0, 0, 0xff, 0xff, 0x07} },
+ CTL_LUN_PAT_NONE, 10, {0x18, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0x07} },
/* 5B CLOSE TRACK/SESSION */
{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
@@ -1035,7 +1035,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] =
{ctl_read_write, CTL_SERIDX_READ, CTL_CMD_FLAG_OK_ON_SLUN | CTL_FLAG_DATA_IN |
CTL_CMD_FLAG_ALLOW_ON_PR_RESV,
CTL_LUN_PAT_READ | CTL_LUN_PAT_RANGE,
- 16, {0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 16, {0x1a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0x07}},
/* 89 COMPARE AND WRITE */
@@ -1047,7 +1047,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] =
/* 8A WRITE(16) */
{ctl_read_write, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_SLUN| CTL_FLAG_DATA_OUT,
CTL_LUN_PAT_WRITE | CTL_LUN_PAT_RANGE,
- 16, {0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 16, {0x1a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0x07}},
/* 8B */
@@ -1062,7 +1062,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] =
/* 8E WRITE AND VERIFY(16) */
{ctl_read_write, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_SLUN| CTL_FLAG_DATA_OUT,
CTL_LUN_PAT_WRITE | CTL_LUN_PAT_RANGE,
- 16, {0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 16, {0x12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0x07}},
/* 8F VERIFY(16) */
@@ -1169,7 +1169,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] =
{ctl_read_write, CTL_SERIDX_READ, CTL_CMD_FLAG_OK_ON_SLUN | CTL_FLAG_DATA_IN |
CTL_CMD_FLAG_ALLOW_ON_PR_RESV,
CTL_LUN_PAT_READ | CTL_LUN_PAT_RANGE,
- 12, {0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0x07}},
+ 12, {0x1a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0x07}},
/* A9 PLAY TRACK RELATIVE(12) */
{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
@@ -1177,7 +1177,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] =
/* AA WRITE(12) */
{ctl_read_write, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_SLUN| CTL_FLAG_DATA_OUT,
CTL_LUN_PAT_WRITE | CTL_LUN_PAT_RANGE,
- 12, {0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0x07}},
+ 12, {0x1a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0x07}},
/* AB SERVICE ACTION IN(12) */
{NULL, CTL_SERIDX_INVLD, CTL_CMD_FLAG_NONE, CTL_LUN_PAT_NONE},
@@ -1191,7 +1191,7 @@ const struct ctl_cmd_entry ctl_cmd_table[256] =
/* AE WRITE AND VERIFY(12) */
{ctl_read_write, CTL_SERIDX_WRITE, CTL_CMD_FLAG_OK_ON_SLUN| CTL_FLAG_DATA_OUT,
CTL_LUN_PAT_WRITE | CTL_LUN_PAT_RANGE,
- 12, {0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0x07}},
+ 12, {0x12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0x07}},
/* AF VERIFY(12) */
{ctl_verify, CTL_SERIDX_READ, CTL_CMD_FLAG_OK_ON_SLUN |
diff --git a/sys/cam/ctl/ctl_error.c b/sys/cam/ctl/ctl_error.c
index 6ecb54b..d2edb2a 100644
--- a/sys/cam/ctl/ctl_error.c
+++ b/sys/cam/ctl/ctl_error.c
@@ -367,44 +367,42 @@ ctl_set_ua(struct ctl_scsiio *ctsio, int asc, int ascq)
}
ctl_ua_type
-ctl_build_ua(ctl_ua_type ua_type, struct scsi_sense_data *sense,
+ctl_build_ua(ctl_ua_type *ua_type, struct scsi_sense_data *sense,
scsi_sense_data_type sense_format)
{
- ctl_ua_type ua_to_build;
- int i, asc, ascq;
+ ctl_ua_type ua_to_build, ua_to_clear;
+ int asc, ascq;
- if (ua_type == CTL_UA_NONE)
- return (ua_type);
+ if (*ua_type == CTL_UA_NONE)
+ return (CTL_UA_NONE);
- ua_to_build = CTL_UA_NONE;
-
- for (i = 0; i < (sizeof(ua_type) * 8); i++) {
- if (ua_type & (1 << i)) {
- ua_to_build = 1 << i;
- break;
- }
- }
+ ua_to_build = (1 << (ffs(*ua_type) - 1));
+ ua_to_clear = ua_to_build;
switch (ua_to_build) {
case CTL_UA_POWERON:
/* 29h/01h POWER ON OCCURRED */
asc = 0x29;
ascq = 0x01;
+ ua_to_clear = ~0;
break;
case CTL_UA_BUS_RESET:
/* 29h/02h SCSI BUS RESET OCCURRED */
asc = 0x29;
ascq = 0x02;
+ ua_to_clear = ~0;
break;
case CTL_UA_TARG_RESET:
/* 29h/03h BUS DEVICE RESET FUNCTION OCCURRED*/
asc = 0x29;
ascq = 0x03;
+ ua_to_clear = ~0;
break;
case CTL_UA_I_T_NEXUS_LOSS:
/* 29h/07h I_T NEXUS LOSS OCCURRED */
asc = 0x29;
ascq = 0x07;
+ ua_to_clear = ~0;
break;
case CTL_UA_LUN_RESET:
/* 29h/00h POWER ON, RESET, OR BUS DEVICE RESET OCCURRED */
@@ -466,9 +464,7 @@ ctl_build_ua(ctl_ua_type ua_type, struct scsi_sense_data *sense,
ascq = 0x09;
break;
default:
- ua_to_build = CTL_UA_NONE;
- return (ua_to_build);
- break; /* NOTREACHED */
+ panic("ctl_build_ua: Unknown UA %x", ua_to_build);
}
ctl_set_sense_data(sense,
@@ -480,6 +476,9 @@ ctl_build_ua(ctl_ua_type ua_type, struct scsi_sense_data *sense,
ascq,
SSD_ELEM_NONE);
+ /* We're reporting this UA, so clear it */
+ *ua_type &= ~ua_to_clear;
+
return (ua_to_build);
}
@@ -694,7 +693,7 @@ ctl_set_lun_not_ready(struct ctl_scsiio *ctsio)
/*current_error*/ 1,
/*sense_key*/ SSD_KEY_NOT_READY,
/*asc*/ 0x04,
- /*ascq*/ 0x05,
+ /*ascq*/ 0x03,
SSD_ELEM_NONE);
}
diff --git a/sys/cam/ctl/ctl_error.h b/sys/cam/ctl/ctl_error.h
index 62596d0..034d14b 100644
--- a/sys/cam/ctl/ctl_error.h
+++ b/sys/cam/ctl/ctl_error.h
@@ -55,7 +55,7 @@ void ctl_sense_to_desc(struct scsi_sense_data_fixed *sense_src,
void ctl_sense_to_fixed(struct scsi_sense_data_desc *sense_src,
struct scsi_sense_data_fixed *sense_dest);
void ctl_set_ua(struct ctl_scsiio *ctsio, int asc, int ascq);
-ctl_ua_type ctl_build_ua(ctl_ua_type ua_type, struct scsi_sense_data *sense,
+ctl_ua_type ctl_build_ua(ctl_ua_type *ua_type, struct scsi_sense_data *sense,
scsi_sense_data_type sense_format);
void ctl_set_overlapped_cmd(struct ctl_scsiio *ctsio);
void ctl_set_overlapped_tag(struct ctl_scsiio *ctsio, uint8_t tag);
diff --git a/sys/cam/ctl/ctl_frontend_iscsi.c b/sys/cam/ctl/ctl_frontend_iscsi.c
index 2dbc8d1..85a0667 100644
--- a/sys/cam/ctl/ctl_frontend_iscsi.c
+++ b/sys/cam/ctl/ctl_frontend_iscsi.c
@@ -2505,10 +2505,10 @@ cfiscsi_datamove_in(union ctl_io *io)
sg_addr += len;
sg_len -= len;
- KASSERT(buffer_offset + request->ip_data_len <= expected_len,
+ KASSERT(buffer_offset + response->ip_data_len <= expected_len,
("buffer_offset %zd + ip_data_len %zd > expected_len %zd",
- buffer_offset, request->ip_data_len, expected_len));
- if (buffer_offset + request->ip_data_len == expected_len) {
+ buffer_offset, response->ip_data_len, expected_len));
+ if (buffer_offset + response->ip_data_len == expected_len) {
/*
* Already have the amount of data the initiator wanted.
*/
diff --git a/sys/cam/ctl/ctl_private.h b/sys/cam/ctl/ctl_private.h
index 39861d3..43ee394 100644
--- a/sys/cam/ctl/ctl_private.h
+++ b/sys/cam/ctl/ctl_private.h
@@ -389,7 +389,6 @@ struct ctl_lun {
TAILQ_HEAD(ctl_blockq,ctl_io_hdr) blocked_queue;
STAILQ_ENTRY(ctl_lun) links;
STAILQ_ENTRY(ctl_lun) run_links;
- struct ctl_nexus rsv_nexus;
#ifdef CTL_WITH_CA
uint32_t have_ca[CTL_MAX_INITIATORS >> 5];
struct scsi_sense_data pending_sense[CTL_MAX_INITIATORS];
@@ -397,6 +396,7 @@ struct ctl_lun {
ctl_ua_type pending_ua[CTL_MAX_INITIATORS];
struct ctl_mode_pages mode_pages;
struct ctl_lun_io_stats stats;
+ uint32_t res_idx;
struct ctl_per_res_info per_res[2*CTL_MAX_INITIATORS];
unsigned int PRGeneration;
int pr_key_count;
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
index fb8736c..d909a71 100644
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -2984,7 +2984,7 @@ freebsd32_procctl(struct thread *td, struct freebsd32_procctl_args *uap)
int
freebsd32_fcntl(struct thread *td, struct freebsd32_fcntl_args *uap)
{
- intptr_t tmp;
+ long tmp;
switch (uap->cmd) {
/*
@@ -3003,5 +3003,5 @@ freebsd32_fcntl(struct thread *td, struct freebsd32_fcntl_args *uap)
tmp = uap->arg;
break;
}
- return (kern_fcntl(td, uap->fd, uap->cmd, tmp));
+ return (kern_fcntl_freebsd(td, uap->fd, uap->cmd, tmp));
}
diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c
index 77feed0..0148fec 100644
--- a/sys/compat/linux/linux_ioctl.c
+++ b/sys/compat/linux/linux_ioctl.c
@@ -1699,13 +1699,6 @@ linux_ioctl_vfat(struct thread *td, struct linux_ioctl_args *args)
* Sound related ioctls
*/
-struct linux_mixer_info {
- char id[16];
- char name[32];
- int modify_counter;
- int fillers[10];
-};
-
struct linux_old_mixer_info {
char id[16];
char name[32];
@@ -1793,12 +1786,8 @@ linux_ioctl_sound(struct thread *td, struct linux_ioctl_args *args)
/* Key on encoded length */
switch ((args->cmd >> 16) & 0x1fff) {
case 0x005c: { /* SOUND_MIXER_INFO */
- struct linux_mixer_info info;
- bzero(&info, sizeof(info));
- strncpy(info.id, "OSS", sizeof(info.id) - 1);
- strncpy(info.name, "FreeBSD OSS Mixer", sizeof(info.name) - 1);
- copyout(&info, (void *)args->arg, sizeof(info));
- return (0);
+ args->cmd = SOUND_MIXER_INFO;
+ return (sys_ioctl(td, (struct ioctl_args *)args));
}
case 0x0030: { /* SOUND_OLD_MIXER_INFO */
struct linux_old_mixer_info info;
diff --git a/sys/compat/linux/linux_mib.c b/sys/compat/linux/linux_mib.c
index 3b75307..8f8cb81 100644
--- a/sys/compat/linux/linux_mib.c
+++ b/sys/compat/linux/linux_mib.c
@@ -129,9 +129,9 @@ struct linux_prison {
static struct linux_prison lprison0 = {
.pr_osname = "Linux",
- .pr_osrelease = "2.6.16",
+ .pr_osrelease = "2.6.18",
.pr_oss_version = 0x030600,
- .pr_osrel = 2006016
+ .pr_osrel = 2006018
};
static unsigned linux_osd_jail_slot;
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index 62bca57..5baa306 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -2095,8 +2095,6 @@ device em # Intel Pro/1000 Gigabit Ethernet
device igb # Intel Pro/1000 PCIE Gigabit Ethernet
device ixgb # Intel Pro/10Gbe PCI-X Ethernet
device ixgbe # Intel Pro/10Gbe PCIE Ethernet
-device ixl # Intel XL710 40Gbe PCIE Ethernet
-device ixlv # Intel XL710 40Gbe VF PCIE Ethernet
device le # AMD Am7900 LANCE and Am79C9xx PCnet
device mxge # Myricom Myri-10G 10GbE NIC
device nxge # Neterion Xframe 10GbE Server/Storage Adapter
@@ -2627,9 +2625,8 @@ options NSFBUFS=1024
# Enable extra debugging code for locks. This stores the filename and
# line of whatever acquired the lock in the lock itself, and changes a
# number of function calls to pass around the relevant data. This is
-# not at all useful unless you are debugging lock code. Also note
-# that it is likely to break e.g. fstat(1) unless you recompile your
-# userland with -DDEBUG_LOCKS as well.
+# not at all useful unless you are debugging lock code. Note that
+# modules should be recompiled as this option modifies KBI.
#
options DEBUG_LOCKS
diff --git a/sys/conf/files b/sys/conf/files
index 634aa23..70d4d5a6 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -646,6 +646,7 @@ dev/aic7xxx/aic7xxx_pci.c optional ahc pci
dev/aic7xxx/aic7xxx_reg_print.c optional ahc ahc_reg_pretty_print
dev/alc/if_alc.c optional alc pci
dev/ale/if_ale.c optional ale pci
+dev/alpm/alpm.c optional alpm pci
dev/altera/avgen/altera_avgen.c optional altera_avgen
dev/altera/avgen/altera_avgen_fdt.c optional altera_avgen fdt
dev/altera/avgen/altera_avgen_nexus.c optional altera_avgen
@@ -654,6 +655,8 @@ dev/altera/sdcard/altera_sdcard_disk.c optional altera_sdcard
dev/altera/sdcard/altera_sdcard_io.c optional altera_sdcard
dev/altera/sdcard/altera_sdcard_fdt.c optional altera_sdcard fdt
dev/altera/sdcard/altera_sdcard_nexus.c optional altera_sdcard
+dev/amdpm/amdpm.c optional amdpm pci | nfpm pci
+dev/amdsmb/amdsmb.c optional amdsmb pci
dev/amr/amr.c optional amr
dev/amr/amr_cam.c optional amrp amr
dev/amr/amr_disk.c optional amr
@@ -1430,26 +1433,6 @@ dev/hptiop/hptiop.c optional hptiop scbus
dev/hwpmc/hwpmc_logging.c optional hwpmc
dev/hwpmc/hwpmc_mod.c optional hwpmc
dev/hwpmc/hwpmc_soft.c optional hwpmc
-dev/ixl/if_ixl.c optional ixl inet \
- compile-with "${NORMAL_C} -I$S/dev/ixl"
-dev/ixl/if_ixlv.c optional ixlv inet \
- compile-with "${NORMAL_C} -I$S/dev/ixl"
-dev/ixl/ixlvc.c optional ixlv inet \
- compile-with "${NORMAL_C} -I$S/dev/ixl"
-dev/ixl/ixl_txrx.c optional ixl ixlv inet \
- compile-with "${NORMAL_C} -I$S/dev/ixl"
-dev/ixl/i40e_osdep.c optional ixl ixlv inet \
- compile-with "${NORMAL_C} -I$S/dev/ixl"
-dev/ixl/i40e_lan_hmc.c optional ixl ixlv inet \
- compile-with "${NORMAL_C} -I$S/dev/ixl"
-dev/ixl/i40e_hmc.c optional ixl ixlv inet \
- compile-with "${NORMAL_C} -I$S/dev/ixl"
-dev/ixl/i40e_common.c optional ixl ixlv inet \
- compile-with "${NORMAL_C} -I$S/dev/ixl"
-dev/ixl/i40e_nvm.c optional ixl ixlv inet \
- compile-with "${NORMAL_C} -I$S/dev/ixl"
-dev/ixl/i40e_adminq.c optional ixl ixlv inet \
- compile-with "${NORMAL_C} -I$S/dev/ixl"
dev/ichsmb/ichsmb.c optional ichsmb
dev/ichsmb/ichsmb_pci.c optional ichsmb pci
dev/ida/ida.c optional ida
@@ -1483,6 +1466,7 @@ dev/iicbus/s35390a.c optional s35390a
dev/iir/iir.c optional iir
dev/iir/iir_ctrl.c optional iir
dev/iir/iir_pci.c optional iir pci
+dev/intpm/intpm.c optional intpm pci
# XXX Work around clang warning, until maintainer approves fix.
dev/ips/ips.c optional ips \
compile-with "${NORMAL_C} ${NO_WSOMETIMES_UNINITIALIZED}"
@@ -1965,6 +1949,7 @@ dev/nand/nandsim_ctrl.c optional nandsim nand
dev/nand/nandsim_log.c optional nandsim nand
dev/nand/nandsim_swap.c optional nandsim nand
dev/nand/nfc_if.m optional nand
+dev/ncr/ncr.c optional ncr pci
dev/ncv/ncr53c500.c optional ncv
dev/ncv/ncr53c500_pccard.c optional ncv pccard
dev/netmap/netmap.c optional netmap
@@ -1977,6 +1962,7 @@ dev/netmap/netmap_offloadings.c optional netmap
dev/netmap/netmap_pipe.c optional netmap
dev/netmap/netmap_vale.c optional netmap
# compile-with "${NORMAL_C} -Wconversion -Wextra"
+dev/nfsmb/nfsmb.c optional nfsmb pci
dev/nge/if_nge.c optional nge
dev/nxge/if_nxge.c optional nxge \
compile-with "${NORMAL_C} ${NO_WSELF_ASSIGN}"
@@ -2580,7 +2566,7 @@ dev/utopia/idtphy.c optional utopia
dev/utopia/suni.c optional utopia
dev/utopia/utopia.c optional utopia
dev/vge/if_vge.c optional vge
-
+dev/viapm/viapm.c optional viapm pci
dev/vkbd/vkbd.c optional vkbd
dev/vr/if_vr.c optional vr pci
dev/vt/colors/vt_termcolors.c optional vt
@@ -3794,7 +3780,7 @@ ofed/drivers/net/mlx4/sys_tune.c optional mlx4ib | mlxen \
ofed/drivers/net/mlx4/en_cq.c optional mlxen \
no-depend obj-prefix "mlx4_" \
compile-with "${OFED_C_NOIMP} -I$S/ofed/drivers/net/mlx4/"
-ofed/drivers/net/mlx4/en_frag.c optional mlxen \
+ofed/drivers/net/mlx4/utils.c optional mlxen \
no-depend obj-prefix "mlx4_" \
compile-with "${OFED_C_NOIMP} -I$S/ofed/drivers/net/mlx4/"
ofed/drivers/net/mlx4/en_main.c optional mlxen \
@@ -3864,14 +3850,6 @@ opencrypto/cryptodeflate.c optional crypto
opencrypto/rmd160.c optional crypto | ipsec
opencrypto/skipjack.c optional crypto
opencrypto/xform.c optional crypto
-pci/alpm.c optional alpm pci
-pci/amdpm.c optional amdpm pci | nfpm pci
-pci/amdsmb.c optional amdsmb pci
-pci/intpm.c optional intpm pci
-pci/ncr.c optional ncr pci \
- compile-with "${NORMAL_C} -Wno-unused"
-pci/nfsmb.c optional nfsmb pci
-pci/viapm.c optional viapm pci
rpc/auth_none.c optional krpc | nfslockd | nfsclient | nfsserver | nfscl | nfsd
rpc/auth_unix.c optional krpc | nfslockd | nfsclient | nfscl | nfsd
rpc/authunix_prot.c optional krpc | nfslockd | nfsclient | nfsserver | nfscl | nfsd
diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64
index 0f6d188..b75732f 100644
--- a/sys/conf/files.amd64
+++ b/sys/conf/files.amd64
@@ -192,6 +192,26 @@ dev/ipmi/ipmi_smbios.c optional ipmi
dev/ipmi/ipmi_ssif.c optional ipmi smbus
dev/ipmi/ipmi_pci.c optional ipmi pci
dev/ipmi/ipmi_linux.c optional ipmi compat_linux32
+dev/ixl/if_ixl.c optional ixl pci \
+ compile-with "${NORMAL_C} -I$S/dev/ixl"
+dev/ixl/if_ixlv.c optional ixlv pci \
+ compile-with "${NORMAL_C} -I$S/dev/ixl"
+dev/ixl/ixlvc.c optional ixlv pci \
+ compile-with "${NORMAL_C} -I$S/dev/ixl"
+dev/ixl/ixl_txrx.c optional ixl pci | ixlv pci \
+ compile-with "${NORMAL_C} -I$S/dev/ixl"
+dev/ixl/i40e_osdep.c optional ixl pci | ixlv pci \
+ compile-with "${NORMAL_C} -I$S/dev/ixl"
+dev/ixl/i40e_lan_hmc.c optional ixl pci | ixlv pci \
+ compile-with "${NORMAL_C} -I$S/dev/ixl"
+dev/ixl/i40e_hmc.c optional ixl pci | ixlv pci \
+ compile-with "${NORMAL_C} -I$S/dev/ixl"
+dev/ixl/i40e_common.c optional ixl pci | ixlv pci \
+ compile-with "${NORMAL_C} -I$S/dev/ixl"
+dev/ixl/i40e_nvm.c optional ixl pci | ixlv pci \
+ compile-with "${NORMAL_C} -I$S/dev/ixl"
+dev/ixl/i40e_adminq.c optional ixl pci | ixlv pci \
+ compile-with "${NORMAL_C} -I$S/dev/ixl"
dev/fdc/fdc.c optional fdc
dev/fdc/fdc_acpi.c optional fdc
dev/fdc/fdc_isa.c optional fdc isa
diff --git a/sys/conf/files.pc98 b/sys/conf/files.pc98
index 6d8666a..555b443 100644
--- a/sys/conf/files.pc98
+++ b/sys/conf/files.pc98
@@ -98,6 +98,8 @@ dev/ct/ct_isa.c optional ct isa
dev/ed/if_ed_cbus.c optional ed isa
dev/ed/if_ed_wd80x3.c optional ed isa
dev/fb/fb.c optional fb | gdc
+dev/fdc/fdc.c optional fdc
+dev/fdc/fdc_cbus.c optional fdc isa
dev/fe/if_fe_cbus.c optional fe isa
dev/hwpmc/hwpmc_amd.c optional hwpmc
dev/hwpmc/hwpmc_intel.c optional hwpmc
@@ -217,8 +219,6 @@ libkern/udivdi3.c standard
libkern/umoddi3.c standard
pc98/apm/apm_bioscall.S optional apm
pc98/cbus/cbus_dma.c optional isa
-pc98/cbus/fdc.c optional fdc
-pc98/cbus/fdc_cbus.c optional fdc isa
pc98/cbus/gdc.c optional gdc
pc98/cbus/nmi.c standard
pc98/cbus/olpt.c optional olpt
diff --git a/sys/conf/options b/sys/conf/options
index eff8a12..42113c3 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -363,7 +363,7 @@ SYM_SETUP_PCI_PARITY opt_sym.h #-PCI parity checking
SYM_SETUP_MAX_LUN opt_sym.h #-Number of LUNs supported
# default:8, range:[1..64]
-# Options used only in pci/ncr.c
+# Options used only in dev/ncr/*
SCSI_NCR_DEBUG opt_ncr.h
SCSI_NCR_MAX_SYNC opt_ncr.h
SCSI_NCR_MAX_WIDE opt_ncr.h
diff --git a/sys/contrib/ipfilter/netinet/ip_dstlist.c b/sys/contrib/ipfilter/netinet/ip_dstlist.c
index ce2e72e..d516556 100644
--- a/sys/contrib/ipfilter/netinet/ip_dstlist.c
+++ b/sys/contrib/ipfilter/netinet/ip_dstlist.c
@@ -1134,7 +1134,7 @@ ipf_dstlist_select(fin, d)
int family;
int x;
- if (d->ipld_dests == NULL || *d->ipld_dests == NULL)
+ if (d == NULL || d->ipld_dests == NULL || *d->ipld_dests == NULL)
return NULL;
family = fin->fin_family;
@@ -1222,7 +1222,7 @@ ipf_dstlist_select(fin, d)
break;
}
- if (sel->ipfd_dest.fd_addr.adf_family != family)
+ if (sel && sel->ipfd_dest.fd_addr.adf_family != family)
sel = NULL;
d->ipld_selected = sel;
diff --git a/sys/contrib/ipfilter/netinet/ip_frag.c b/sys/contrib/ipfilter/netinet/ip_frag.c
index fd4ff24..831326c 100644
--- a/sys/contrib/ipfilter/netinet/ip_frag.c
+++ b/sys/contrib/ipfilter/netinet/ip_frag.c
@@ -930,7 +930,8 @@ ipf_frag_known(fin, passp)
/* ------------------------------------------------------------------------ */
/* Function: ipf_frag_natforget */
/* Returns: Nil */
-/* Parameters: ptr(I) - pointer to data structure */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* ptr(I) - pointer to data structure */
/* */
/* Search through all of the fragment cache entries for NAT and wherever a */
/* pointer is found to match ptr, reset it to NULL. */
@@ -954,7 +955,8 @@ ipf_frag_natforget(softc, ptr)
/* ------------------------------------------------------------------------ */
/* Function: ipf_frag_delete */
/* Returns: Nil */
-/* Parameters: fra(I) - pointer to fragment structure to delete */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* fra(I) - pointer to fragment structure to delete */
/* tail(IO) - pointer to the pointer to the tail of the frag */
/* list */
/* */
@@ -991,7 +993,10 @@ ipf_frag_delete(softc, fra, tail)
/* ------------------------------------------------------------------------ */
/* Function: ipf_frag_free */
/* Returns: Nil */
+/* Parameters: softf(I) - pointer to fragment context information */
+/* fra(I) - pointer to fragment structure to free */
/* */
+/* Free up a fragment cache entry and bump relevent statistics. */
/* ------------------------------------------------------------------------ */
static void
ipf_frag_free(softf, fra)
@@ -1007,7 +1012,7 @@ ipf_frag_free(softf, fra)
/* ------------------------------------------------------------------------ */
/* Function: ipf_frag_clear */
/* Returns: Nil */
-/* Parameters: Nil */
+/* Parameters: softc(I) - pointer to soft context main structure */
/* */
/* Free memory in use by fragment state information kept. Do the normal */
/* fragment state stuff first and then the NAT-fragment table. */
@@ -1048,7 +1053,7 @@ ipf_frag_clear(softc)
/* ------------------------------------------------------------------------ */
/* Function: ipf_frag_expire */
/* Returns: Nil */
-/* Parameters: Nil */
+/* Parameters: softc(I) - pointer to soft context main structure */
/* */
/* Expire entries in the fragment cache table that have been there too long */
/* ------------------------------------------------------------------------ */
@@ -1120,6 +1125,13 @@ ipf_frag_expire(softc)
/* ------------------------------------------------------------------------ */
/* Function: ipf_frag_pkt_next */
+/* Returns: int - 0 == success, else error */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* token(I) - pointer to token information for this caller */
+/* itp(I) - pointer to generic iterator from caller */
+/* */
+/* This function is used to step through the fragment cache list used for */
+/* filter rules. The hard work is done by the more generic ipf_frag_next. */
/* ------------------------------------------------------------------------ */
int
ipf_frag_pkt_next(softc, token, itp)
@@ -1140,6 +1152,13 @@ ipf_frag_pkt_next(softc, token, itp)
/* ------------------------------------------------------------------------ */
/* Function: ipf_frag_nat_next */
+/* Returns: int - 0 == success, else error */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* token(I) - pointer to token information for this caller */
+/* itp(I) - pointer to generic iterator from caller */
+/* */
+/* This function is used to step through the fragment cache list used for */
+/* NAT. The hard work is done by the more generic ipf_frag_next. */
/* ------------------------------------------------------------------------ */
int
ipf_frag_nat_next(softc, token, itp)
@@ -1160,7 +1179,8 @@ ipf_frag_nat_next(softc, token, itp)
/* ------------------------------------------------------------------------ */
/* Function: ipf_frag_next */
/* Returns: int - 0 == success, else error */
-/* Parameters: token(I) - pointer to token information for this caller */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* token(I) - pointer to token information for this caller */
/* itp(I) - pointer to generic iterator from caller */
/* top(I) - top of the fragment list */
/* lock(I) - fragment cache lock */
@@ -1239,7 +1259,11 @@ ipf_frag_next(softc, token, itp, top
/* ------------------------------------------------------------------------ */
/* Function: ipf_frag_pkt_deref */
/* Returns: Nil */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* data(I) - pointer to frag cache pointer */
/* */
+/* This function is the external interface for dropping a reference to a */
+/* fragment cache entry used by filter rules. */
/* ------------------------------------------------------------------------ */
void
ipf_frag_pkt_deref(softc, data)
@@ -1261,7 +1285,11 @@ ipf_frag_pkt_deref(softc, data)
/* ------------------------------------------------------------------------ */
/* Function: ipf_frag_nat_deref */
/* Returns: Nil */
+/* Parameters: softc(I) - pointer to soft context main structure */
+/* data(I) - pointer to frag cache pointer */
/* */
+/* This function is the external interface for dropping a reference to a */
+/* fragment cache entry used by NAT table entries. */
/* ------------------------------------------------------------------------ */
void
ipf_frag_nat_deref(softc, data)
diff --git a/sys/ddb/db_main.c b/sys/ddb/db_main.c
index 6e9286c..bee321c 100644
--- a/sys/ddb/db_main.c
+++ b/sys/ddb/db_main.c
@@ -56,7 +56,12 @@ static dbbe_trace_thread_f db_trace_thread_wrapper;
KDB_BACKEND(ddb, db_init, db_trace_self_wrapper, db_trace_thread_wrapper,
db_trap);
-vm_offset_t ksym_start, ksym_end;
+/*
+ * Symbols can be loaded by specifying the exact addresses of
+ * the symtab and strtab in memory. This is used when loaded from
+ * boot loaders different than the native one (like Xen).
+ */
+vm_offset_t ksymtab, kstrtab, ksymtab_size;
boolean_t
X_db_line_at_pc(db_symtab_t *symtab, c_db_sym_t sym, char **file, int *line,
@@ -168,24 +173,39 @@ X_db_symbol_values(db_symtab_t *symtab, c_db_sym_t sym, const char **namep,
}
}
+int
+db_fetch_ksymtab(vm_offset_t ksym_start, vm_offset_t ksym_end)
+{
+ Elf_Size strsz;
+
+ if (ksym_end > ksym_start && ksym_start != 0) {
+ ksymtab = ksym_start;
+ ksymtab_size = *(Elf_Size*)ksymtab;
+ ksymtab += sizeof(Elf_Size);
+ kstrtab = ksymtab + ksymtab_size;
+ strsz = *(Elf_Size*)kstrtab;
+ kstrtab += sizeof(Elf_Size);
+ if (kstrtab + strsz > ksym_end) {
+ /* Sizes doesn't match, unset everything. */
+ ksymtab = ksymtab_size = kstrtab = 0;
+ }
+ }
+
+ if (ksymtab == 0 || ksymtab_size == 0 || kstrtab == 0)
+ return (-1);
+
+ return (0);
+}
+
static int
db_init(void)
{
- uintptr_t symtab, strtab;
- Elf_Size tabsz, strsz;
db_command_init();
- if (ksym_end > ksym_start && ksym_start != 0) {
- symtab = ksym_start;
- tabsz = *((Elf_Size*)symtab);
- symtab += sizeof(Elf_Size);
- strtab = symtab + tabsz;
- strsz = *((Elf_Size*)strtab);
- strtab += sizeof(Elf_Size);
- if (strtab + strsz <= ksym_end) {
- db_add_symbol_table((char *)symtab,
- (char *)(symtab + tabsz), "elf", (char *)strtab);
- }
+
+ if (ksymtab != 0 && kstrtab != 0 && ksymtab_size != 0) {
+ db_add_symbol_table((char *)ksymtab,
+ (char *)(ksymtab + ksymtab_size), "elf", (char *)kstrtab);
}
db_add_symbol_table(NULL, NULL, "kld", NULL);
return (1); /* We're the default debugger. */
diff --git a/sys/ddb/ddb.h b/sys/ddb/ddb.h
index 42fc902..5aa646b 100644
--- a/sys/ddb/ddb.h
+++ b/sys/ddb/ddb.h
@@ -77,6 +77,13 @@ int DB_CALL(db_expr_t, db_expr_t *, int, db_expr_t[]);
#endif
/*
+ * Extern variables to set the address and size of the symtab and strtab.
+ * Most users should use db_fetch_symtab in order to set them from the
+ * boot loader provided values.
+ */
+extern vm_offset_t ksymtab, kstrtab, ksymtab_size;
+
+/*
* There are three "command tables":
* - One for simple commands; a list of these is displayed
* by typing 'help' at the debugger prompt.
@@ -218,6 +225,7 @@ int db_value_of_name_vnet(const char *name, db_expr_t *valuep);
int db_write_bytes(vm_offset_t addr, size_t size, char *data);
void db_command_register(struct command_table *, struct command *);
void db_command_unregister(struct command_table *, struct command *);
+int db_fetch_ksymtab(vm_offset_t ksym_start, vm_offset_t ksym_end);
db_cmdfcn_t db_breakpoint_cmd;
db_cmdfcn_t db_capture_cmd;
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index b37e252..1913912 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -93,6 +93,7 @@ struct acpi_interface {
/* Global mutex for locking access to the ACPI subsystem. */
struct mtx acpi_mutex;
+struct callout acpi_sleep_timer;
/* Bitmap of device quirks. */
int acpi_quirks;
@@ -683,7 +684,9 @@ acpi_attach(device_t dev)
AcpiFormatException(status));
/* Allow sleep request after a while. */
- timeout(acpi_sleep_enable, sc, hz * ACPI_MINIMUM_AWAKETIME);
+ callout_init_mtx(&acpi_sleep_timer, &acpi_mutex, 0);
+ callout_reset(&acpi_sleep_timer, hz * ACPI_MINIMUM_AWAKETIME,
+ acpi_sleep_enable, sc);
error = 0;
@@ -851,11 +854,18 @@ acpi_child_location_str_method(device_t cbdev, device_t child, char *buf,
size_t buflen)
{
struct acpi_device *dinfo = device_get_ivars(child);
-
- if (dinfo->ad_handle)
- snprintf(buf, buflen, "handle=%s", acpi_name(dinfo->ad_handle));
- else
- snprintf(buf, buflen, "unknown");
+ char buf2[32];
+ int pxm;
+
+ if (dinfo->ad_handle) {
+ snprintf(buf, buflen, "handle=%s", acpi_name(dinfo->ad_handle));
+ if (ACPI_SUCCESS(acpi_GetInteger(dinfo->ad_handle, "_PXM", &pxm))) {
+ snprintf(buf2, 32, " _PXM=%d", pxm);
+ strlcat(buf, buf2, buflen);
+ }
+ } else {
+ snprintf(buf, buflen, "unknown");
+ }
return (0);
}
@@ -2483,8 +2493,8 @@ acpi_sleep_force(void *arg)
device_printf(sc->acpi_dev,
"suspend request timed out, forcing sleep now\n");
/*
- * XXX Suspending from callout cause the freeze in DEVICE_SUSPEND().
- * Suspend from acpi_task thread in stead.
+ * XXX Suspending from callout causes freezes in DEVICE_SUSPEND().
+ * Suspend from acpi_task thread instead.
*/
if (ACPI_FAILURE(AcpiOsExecute(OSL_NOTIFY_HANDLER,
acpi_sleep_force_task, sc)))
@@ -2636,15 +2646,15 @@ acpi_sleep_enable(void *arg)
{
struct acpi_softc *sc = (struct acpi_softc *)arg;
+ ACPI_LOCK_ASSERT(acpi);
+
/* Reschedule if the system is not fully up and running. */
if (!AcpiGbl_SystemAwakeAndRunning) {
- timeout(acpi_sleep_enable, sc, hz * ACPI_MINIMUM_AWAKETIME);
+ callout_schedule(&acpi_sleep_timer, hz * ACPI_MINIMUM_AWAKETIME);
return;
}
- ACPI_LOCK(acpi);
sc->acpi_sleep_disabled = FALSE;
- ACPI_UNLOCK(acpi);
}
static ACPI_STATUS
@@ -2859,7 +2869,7 @@ backout:
EVENTHANDLER_INVOKE(power_resume);
/* Allow another sleep request after a while. */
- timeout(acpi_sleep_enable, sc, hz * ACPI_MINIMUM_AWAKETIME);
+ callout_schedule(&acpi_sleep_timer, hz * ACPI_MINIMUM_AWAKETIME);
/* Run /etc/rc.resume after we are back. */
if (devctl_process_running())
diff --git a/sys/dev/acpica/acpi_pci.c b/sys/dev/acpica/acpi_pci.c
index 78d8639..f4e794a 100644
--- a/sys/dev/acpica/acpi_pci.c
+++ b/sys/dev/acpica/acpi_pci.c
@@ -149,12 +149,19 @@ acpi_pci_child_location_str_method(device_t cbdev, device_t child, char *buf,
size_t buflen)
{
struct acpi_pci_devinfo *dinfo = device_get_ivars(child);
+ int pxm;
+ char buf2[32];
pci_child_location_str_method(cbdev, child, buf, buflen);
-
+
if (dinfo->ap_handle) {
- strlcat(buf, " handle=", buflen);
- strlcat(buf, acpi_name(dinfo->ap_handle), buflen);
+ strlcat(buf, " handle=", buflen);
+ strlcat(buf, acpi_name(dinfo->ap_handle), buflen);
+
+ if (ACPI_SUCCESS(acpi_GetInteger(dinfo->ap_handle, "_PXM", &pxm))) {
+ snprintf(buf2, 32, " _PXM=%d", pxm);
+ strlcat(buf, buf2, buflen);
+ }
}
return (0);
}
diff --git a/sys/pci/alpm.c b/sys/dev/alpm/alpm.c
index 53b2f9d..53b2f9d 100644
--- a/sys/pci/alpm.c
+++ b/sys/dev/alpm/alpm.c
diff --git a/sys/pci/amdpm.c b/sys/dev/amdpm/amdpm.c
index 63b8fe1..63b8fe1 100644
--- a/sys/pci/amdpm.c
+++ b/sys/dev/amdpm/amdpm.c
diff --git a/sys/pci/amdsmb.c b/sys/dev/amdsmb/amdsmb.c
index 264b11a..264b11a 100644
--- a/sys/pci/amdsmb.c
+++ b/sys/dev/amdsmb/amdsmb.c
diff --git a/sys/dev/asmc/asmc.c b/sys/dev/asmc/asmc.c
index 099e7f1..5933307 100644
--- a/sys/dev/asmc/asmc.c
+++ b/sys/dev/asmc/asmc.c
@@ -77,6 +77,7 @@ static int asmc_key_read(device_t dev, const char *key, uint8_t *buf,
uint8_t);
static int asmc_fan_count(device_t dev);
static int asmc_fan_getvalue(device_t dev, const char *key, int fan);
+static int asmc_fan_setvalue(device_t dev, const char *key, int fan, int speed);
static int asmc_temp_getvalue(device_t dev, const char *key);
static int asmc_sms_read(device_t, const char *key, int16_t *val);
static void asmc_sms_calibrate(device_t dev);
@@ -94,6 +95,7 @@ static int asmc_key_dump(device_t, int);
/*
* Model functions.
*/
+static int asmc_mb_sysctl_fanid(SYSCTL_HANDLER_ARGS);
static int asmc_mb_sysctl_fanspeed(SYSCTL_HANDLER_ARGS);
static int asmc_mb_sysctl_fansafespeed(SYSCTL_HANDLER_ARGS);
static int asmc_mb_sysctl_fanminspeed(SYSCTL_HANDLER_ARGS);
@@ -115,6 +117,7 @@ struct asmc_model {
int (*smc_sms_x)(SYSCTL_HANDLER_ARGS);
int (*smc_sms_y)(SYSCTL_HANDLER_ARGS);
int (*smc_sms_z)(SYSCTL_HANDLER_ARGS);
+ int (*smc_fan_id)(SYSCTL_HANDLER_ARGS);
int (*smc_fan_speed)(SYSCTL_HANDLER_ARGS);
int (*smc_fan_safespeed)(SYSCTL_HANDLER_ARGS);
int (*smc_fan_minspeed)(SYSCTL_HANDLER_ARGS);
@@ -134,7 +137,7 @@ static struct asmc_model *asmc_match(device_t dev);
#define ASMC_SMS_FUNCS asmc_mb_sysctl_sms_x, asmc_mb_sysctl_sms_y, \
asmc_mb_sysctl_sms_z
-#define ASMC_FAN_FUNCS asmc_mb_sysctl_fanspeed, asmc_mb_sysctl_fansafespeed, \
+#define ASMC_FAN_FUNCS asmc_mb_sysctl_fanid, asmc_mb_sysctl_fanspeed, asmc_mb_sysctl_fansafespeed, \
asmc_mb_sysctl_fanminspeed, \
asmc_mb_sysctl_fanmaxspeed, \
asmc_mb_sysctl_fantargetspeed
@@ -196,6 +199,18 @@ struct asmc_model asmc_models[] = {
ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
ASMC_MBP4_TEMPS, ASMC_MBP4_TEMPNAMES, ASMC_MBP4_TEMPDESCS
},
+
+ {
+ "MacBookPro8,2", "Apple SMC MacBook Pro (early 2011)",
+ ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
+ ASMC_MBP8_TEMPS, ASMC_MBP8_TEMPNAMES, ASMC_MBP8_TEMPDESCS
+ },
+
+ {
+ "MacBookPro11,3", "Apple SMC MacBook Pro Retina Core i7 (2013/2014)",
+ ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS,
+ ASMC_MBP11_TEMPS, ASMC_MBP11_TEMPNAMES, ASMC_MBP11_TEMPDESCS
+ },
/* The Mac Mini has no SMS */
{
@@ -224,12 +239,27 @@ struct asmc_model asmc_models[] = {
ASMC_MP_TEMPS, ASMC_MP_TEMPNAMES, ASMC_MP_TEMPDESCS
},
+ /* Idem for the MacPro 2010*/
+ {
+ "MacPro5,1", "Apple SMC MacPro (2010)",
+ NULL, NULL, NULL,
+ ASMC_FAN_FUNCS,
+ NULL, NULL, NULL,
+ ASMC_MP5_TEMPS, ASMC_MP5_TEMPNAMES, ASMC_MP5_TEMPDESCS
+ },
+
{
"MacBookAir1,1", "Apple SMC MacBook Air",
ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, NULL, NULL, NULL,
ASMC_MBA_TEMPS, ASMC_MBA_TEMPNAMES, ASMC_MBA_TEMPDESCS
},
+ {
+ "MacBookAir3,1", "Apple SMC MacBook Air Core 2 Duo (Late 2010)",
+ ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, NULL, NULL, NULL,
+ ASMC_MBA3_TEMPS, ASMC_MBA3_TEMPNAMES, ASMC_MBA3_TEMPDESCS
+ },
+
{ NULL, NULL }
};
@@ -361,6 +391,12 @@ asmc_attach(device_t dev)
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sc->sc_fan_tree[i]),
+ OID_AUTO, "id", CTLTYPE_STRING | CTLFLAG_RD,
+ dev, j, model->smc_fan_id, "I",
+ "Fan ID");
+
+ SYSCTL_ADD_PROC(sysctlctx,
+ SYSCTL_CHILDREN(sc->sc_fan_tree[i]),
OID_AUTO, "speed", CTLTYPE_INT | CTLFLAG_RD,
dev, j, model->smc_fan_speed, "I",
"Fan speed in RPM");
@@ -375,21 +411,21 @@ asmc_attach(device_t dev)
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sc->sc_fan_tree[i]),
OID_AUTO, "minspeed",
- CTLTYPE_INT | CTLFLAG_RD,
+ CTLTYPE_INT | CTLFLAG_RW,
dev, j, model->smc_fan_minspeed, "I",
"Fan minimum speed in RPM");
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sc->sc_fan_tree[i]),
OID_AUTO, "maxspeed",
- CTLTYPE_INT | CTLFLAG_RD,
+ CTLTYPE_INT | CTLFLAG_RW,
dev, j, model->smc_fan_maxspeed, "I",
"Fan maximum speed in RPM");
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sc->sc_fan_tree[i]),
OID_AUTO, "targetspeed",
- CTLTYPE_INT | CTLFLAG_RD,
+ CTLTYPE_INT | CTLFLAG_RW,
dev, j, model->smc_fan_targetspeed, "I",
"Fan target speed in RPM");
}
@@ -641,11 +677,10 @@ nosms:
if (bootverbose) {
/*
- * XXX: The number of keys is a 32 bit buffer, but
- * right now Apple only uses the last 8 bit.
+ * The number of keys is a 32 bit buffer
*/
asmc_key_read(dev, ASMC_NKEYS, buf, 4);
- device_printf(dev, "number of keys: %d\n", buf[3]);
+ device_printf(dev, "number of keys: %d\n", ntohl(*(uint32_t*)buf));
}
#ifdef DEBUG
@@ -906,7 +941,7 @@ asmc_fan_count(device_t dev)
{
uint8_t buf[1];
- if (asmc_key_read(dev, ASMC_KEY_FANCOUNT, buf, 1) < 0)
+ if (asmc_key_read(dev, ASMC_KEY_FANCOUNT, buf, sizeof buf) < 0)
return (-1);
return (buf[0]);
@@ -920,13 +955,46 @@ asmc_fan_getvalue(device_t dev, const char *key, int fan)
char fankey[5];
snprintf(fankey, sizeof(fankey), key, fan);
- if (asmc_key_read(dev, fankey, buf, 2) < 0)
+ if (asmc_key_read(dev, fankey, buf, sizeof buf) < 0)
return (-1);
speed = (buf[0] << 6) | (buf[1] >> 2);
return (speed);
}
+static char*
+asmc_fan_getstring(device_t dev, const char *key, int fan)
+{
+ uint8_t buf[16];
+ char fankey[5];
+ char* desc;
+
+ snprintf(fankey, sizeof(fankey), key, fan);
+ if (asmc_key_read(dev, fankey, buf, sizeof buf) < 0)
+ return (NULL);
+ desc = buf+4;
+
+ return (desc);
+}
+
+static int
+asmc_fan_setvalue(device_t dev, const char *key, int fan, int speed)
+{
+ uint8_t buf[2];
+ char fankey[5];
+
+ speed *= 4;
+
+ buf[0] = speed>>8;
+ buf[1] = speed;
+
+ snprintf(fankey, sizeof(fankey), key, fan);
+ if (asmc_key_write(dev, fankey, buf, sizeof buf) < 0)
+ return (-1);
+
+ return (0);
+}
+
static int
asmc_mb_sysctl_fanspeed(SYSCTL_HANDLER_ARGS)
{
@@ -942,6 +1010,22 @@ asmc_mb_sysctl_fanspeed(SYSCTL_HANDLER_ARGS)
}
static int
+asmc_mb_sysctl_fanid(SYSCTL_HANDLER_ARGS)
+{
+ device_t dev = (device_t) arg1;
+ int fan = arg2;
+ int error = true;
+ char* desc;
+
+ desc = asmc_fan_getstring(dev, ASMC_KEY_FANID, fan);
+
+ if (desc != NULL)
+ error = sysctl_handle_string(oidp, desc, 0, req);
+
+ return (error);
+}
+
+static int
asmc_mb_sysctl_fansafespeed(SYSCTL_HANDLER_ARGS)
{
device_t dev = (device_t) arg1;
@@ -967,6 +1051,11 @@ asmc_mb_sysctl_fanminspeed(SYSCTL_HANDLER_ARGS)
v = asmc_fan_getvalue(dev, ASMC_KEY_FANMINSPEED, fan);
error = sysctl_handle_int(oidp, &v, 0, req);
+ if (error == 0 && req->newptr != NULL) {
+ unsigned int newspeed = *(unsigned int *)req->newptr;
+ asmc_fan_setvalue(dev, ASMC_KEY_FANMINSPEED, fan, newspeed);
+ }
+
return (error);
}
@@ -981,6 +1070,11 @@ asmc_mb_sysctl_fanmaxspeed(SYSCTL_HANDLER_ARGS)
v = asmc_fan_getvalue(dev, ASMC_KEY_FANMAXSPEED, fan);
error = sysctl_handle_int(oidp, &v, 0, req);
+ if (error == 0 && req->newptr != NULL) {
+ unsigned int newspeed = *(unsigned int *)req->newptr;
+ asmc_fan_setvalue(dev, ASMC_KEY_FANMAXSPEED, fan, newspeed);
+ }
+
return (error);
}
@@ -995,6 +1089,11 @@ asmc_mb_sysctl_fantargetspeed(SYSCTL_HANDLER_ARGS)
v = asmc_fan_getvalue(dev, ASMC_KEY_FANTARGETSPEED, fan);
error = sysctl_handle_int(oidp, &v, 0, req);
+ if (error == 0 && req->newptr != NULL) {
+ unsigned int newspeed = *(unsigned int *)req->newptr;
+ asmc_fan_setvalue(dev, ASMC_KEY_FANTARGETSPEED, fan, newspeed);
+ }
+
return (error);
}
@@ -1009,7 +1108,7 @@ asmc_temp_getvalue(device_t dev, const char *key)
/*
* Check for invalid temperatures.
*/
- if (asmc_key_read(dev, key, buf, 2) < 0)
+ if (asmc_key_read(dev, key, buf, sizeof buf) < 0)
return (-1);
return (buf[0]);
@@ -1042,7 +1141,7 @@ asmc_sms_read(device_t dev, const char *key, int16_t *val)
case 'X':
case 'Y':
case 'Z':
- error = asmc_key_read(dev, key, buf, 2);
+ error = asmc_key_read(dev, key, buf, sizeof buf);
break;
default:
device_printf(dev, "%s called with invalid argument %s\n",
@@ -1197,7 +1296,7 @@ asmc_mbp_sysctl_light_left(SYSCTL_HANDLER_ARGS)
int error;
int32_t v;
- asmc_key_read(dev, ASMC_KEY_LIGHTLEFT, buf, 6);
+ asmc_key_read(dev, ASMC_KEY_LIGHTLEFT, buf, sizeof buf);
v = buf[2];
error = sysctl_handle_int(oidp, &v, sizeof(v), req);
@@ -1212,7 +1311,7 @@ asmc_mbp_sysctl_light_right(SYSCTL_HANDLER_ARGS)
int error;
int32_t v;
- asmc_key_read(dev, ASMC_KEY_LIGHTRIGHT, buf, 6);
+ asmc_key_read(dev, ASMC_KEY_LIGHTRIGHT, buf, sizeof buf);
v = buf[2];
error = sysctl_handle_int(oidp, &v, sizeof(v), req);
@@ -1236,7 +1335,7 @@ asmc_mbp_sysctl_light_control(SYSCTL_HANDLER_ARGS)
v = level;
buf[0] = level;
buf[1] = 0x00;
- asmc_key_write(dev, ASMC_KEY_LIGHTVALUE, buf, 2);
+ asmc_key_write(dev, ASMC_KEY_LIGHTVALUE, buf, sizeof buf);
}
return (error);
diff --git a/sys/dev/asmc/asmcvar.h b/sys/dev/asmc/asmcvar.h
index 67e7f3b..368575b 100644
--- a/sys/dev/asmc/asmcvar.h
+++ b/sys/dev/asmc/asmcvar.h
@@ -27,7 +27,7 @@
*
*/
-#define ASMC_MAXFANS 2
+#define ASMC_MAXFANS 6
struct asmc_softc {
device_t sc_dev;
@@ -83,6 +83,7 @@ struct asmc_softc {
*/
#define ASMC_KEY_FANCOUNT "FNum" /* RO; 1 byte */
#define ASMC_KEY_FANMANUAL "FS! " /* RW; 2 bytes */
+#define ASMC_KEY_FANID "F%dID" /* RO; 16 bytes */
#define ASMC_KEY_FANSPEED "F%dAc" /* RO; 2 bytes */
#define ASMC_KEY_FANMINSPEED "F%dMn" /* RO; 2 bytes */
#define ASMC_KEY_FANMAXSPEED "F%dMx" /* RO; 2 bytes */
@@ -132,7 +133,7 @@ struct asmc_softc {
*
*/
/* maximum array size for temperatures including the last NULL */
-#define ASMC_TEMP_MAX 36
+#define ASMC_TEMP_MAX 80
#define ASMC_MB_TEMPS { "TB0T", "TN0P", "TN1P", "Th0H", "Th1H", \
"TM0P", NULL }
#define ASMC_MB_TEMPNAMES { "enclosure", "northbridge1", \
@@ -175,6 +176,57 @@ struct asmc_softc {
"Unknown", "Unknown", \
"Wireless Module", }
+#define ASMC_MBP8_TEMPS { "TB0T", "TB1T", "TB2T", "TC0C", "TC0D", \
+ "TC0E", "TC0F", "TC0P", "TC1C", "TC2C", \
+ "TC3C", "TC4C", "TCFC", "TCGC", "TCSA", \
+ "TCTD", "TG0D", "TG0P", "THSP", "TM0S", \
+ "TMBS", "TP0P", "TPCD", "TW0P", "Th1H", \
+ "Th2H", "Tm0P", "Ts0P", "Ts0S", NULL }
+
+#define ASMC_MBP8_TEMPNAMES { "enclosure", "TB1T", "TB2T", "TC0C", "TC0D", \
+ "TC0E", "TC0F", "TC0P", "TC1C", "TC2C", \
+ "TC3C", "TC4C", "TCFC", "TCGC", "TCSA", \
+ "TCTD", "graphics", "TG0P", "THSP", "TM0S", \
+ "TMBS", "TP0P", "TPCD", "wireless", "Th1H", \
+ "Th2H", "memory", "Ts0P", "Ts0S" }
+
+#define ASMC_MBP8_TEMPDESCS { "Enclosure Bottomside", "TB1T", "TB2T", "TC0C", "TC0D", \
+ "TC0E", "TC0F", "TC0P", "TC1C", "TC2C", \
+ "TC3C", "TC4C", "TCFC", "TCGC", "TCSA", \
+ "TCTD", "TG0D", "TG0P", "THSP", "TM0S", \
+ "TMBS", "TP0P", "TPCD", "TW0P", "Th1H", \
+ "Th2H", "Tm0P", "Ts0P", "Ts0S" }
+
+#define ASMC_MBP11_TEMPS { "TB0T", "TB1T", "TB2T", "TBXT", "TC0E", \
+ "TC0F", "TC0P", "TC1C", "TC2C", "TC3C", \
+ "TC4C", "TCFC", "TCGC", "TCSA", "TCTD", \
+ "TCXC", "TG0D", "TG0P", "TG1D", "TG1F", \
+ "TG1d", "TH0A", "TH0B", "TH0F", "TH0R", \
+ "TH0V", "TH0a", "TH0b", "TH0c", "TM0P", \
+ "TM0S", "TP0P", "TPCD", "TW0P", "Ta0P", \
+ "TaSP", "Th1H", "Th2H", "Ts0P", "Ts0S", \
+ "Ts1S", NULL }
+
+#define ASMC_MBP11_TEMPNAMES { "TB0T", "TB1T", "TB2T", "TBXT", "TC0E", \
+ "TC0F", "TC0P", "TC1C", "TC2C", "TC3C", \
+ "TC4C", "TCFC", "TCGC", "TCSA", "TCTD", \
+ "TCXC", "TG0D", "TG0P", "TG1D", "TG1F", \
+ "TG1d", "TH0A", "TH0B", "TH0F", "TH0R", \
+ "TH0V", "TH0a", "TH0b", "TH0c", "TM0P", \
+ "TM0S", "TP0P", "TPCD", "TW0P", "Ta0P", \
+ "TaSP", "Th1H", "Th2H", "Ts0P", "Ts0S", \
+ "Ts1S" }
+
+#define ASMC_MBP11_TEMPDESCS { "TB0T", "TB1T", "TB2T", "TBXT", "TC0E", \
+ "TC0F", "TC0P", "TC1C", "TC2C", "TC3C", \
+ "TC4C", "TCFC", "TCGC", "TCSA", "TCTD", \
+ "TCXC", "TG0D", "TG0P", "TG1D", "TG1F", \
+ "TG1d", "TH0A", "TH0B", "TH0F", "TH0R", \
+ "TH0V", "TH0a", "TH0b", "TH0c", "TM0P", \
+ "TM0S", "TP0P", "TPCD", "TW0P", "Ta0P", \
+ "TaSP", "Th1H", "Th2H", "Ts0P", "Ts0S", \
+ "Ts1S" }
+
#define ASMC_MM_TEMPS { "TN0P", "TN1P", NULL }
#define ASMC_MM_TEMPNAMES { "northbridge1", "northbridge2" }
#define ASMC_MM_TEMPDESCS { "Northbridge Point 1", \
@@ -214,8 +266,7 @@ struct asmc_softc {
"TH0P", "TH1P", "TH2P", "TH3P", "TMAP", \
"TMAS", "TMBS", "TM0P", "TM0S", "TM1P", \
"TM1S", "TM2P", "TM2S", "TM3S", "TM8P", \
- "TM8S", "TM9P", "TM9S", "TN0H", "TS0C", \
- NULL }
+ "TM8S", "TM9P", "TM9S", "TN0H", "TS0C", }
#define ASMC_MP_TEMPDESCS { "TA0P", "TCAG", "TCAH", "TCBG", "TCBH", \
"TC0C", "TC0D", "TC0P", "TC1C", "TC1D", \
@@ -223,9 +274,66 @@ struct asmc_softc {
"TH0P", "TH1P", "TH2P", "TH3P", "TMAP", \
"TMAS", "TMBS", "TM0P", "TM0S", "TM1P", \
"TM1S", "TM2P", "TM2S", "TM3S", "TM8P", \
- "TM8S", "TM9P", "TM9S", "TN0H", "TS0C", \
+ "TM8S", "TM9P", "TM9S", "TN0H", "TS0C", }
+
+#define ASMC_MP5_TEMPS { "TA0P", "TCAC", "TCAD", "TCAG", "TCAH", \
+ "TCAS", "TCBC", "TCBD", "TCBG", "TCBH", \
+ "TCBS", "TH1F", "TH1P", "TH1V", "TH2F", \
+ "TH2P", "TH2V", "TH3F", "TH3P", "TH3V", \
+ "TH4F", "TH4P", "TH4V", "THPS", "THTG", \
+ "TM1P", "TM2P", "TM2V", "TM3P", "TM3V", \
+ "TM4P", "TM5P", "TM6P", "TM6V", "TM7P", \
+ "TM7V", "TM8P", "TM8V", "TM9V", "TMA1", \
+ "TMA2", "TMA3", "TMA4", "TMB1", "TMB2", \
+ "TMB3", "TMB4", "TMHS", "TMLS", "TMPS", \
+ "TMPV", "TMTG", "TN0D", "TN0H", "TNTG", \
+ "Te1F", "Te1P", "Te1S", "Te2F", "Te2S", \
+ "Te3F", "Te3S", "Te4F", "Te4S", "Te5F", \
+ "Te5S", "TeGG", "TeGP", "TeRG", "TeRP", \
+ "TeRV", "Tp0C", "Tp1C", "TpPS", "TpTG", \
NULL }
+#define ASMC_MP5_TEMPNAMES { "ambient", "TCAC", "TCAD", "TCAG", "TCAH", \
+ "TCAS", "TCBC", "TCBD", "TCBG", "TCBH", \
+ "TCBS", "TH1F", "TH1P", "TH1V", "TH2F", \
+ "TH2P", "TH2V", "TH3F", "TH3P", "TH3V", \
+ "TH4F", "TH4P", "TH4V", "THPS", "THTG", \
+ "TM1P", "TM2P", "TM2V", "TM3P", "TM3V", \
+ "TM4P", "TM5P", "TM6P", "TM6V", "TM7P", \
+ "TM7V", "TM8P", "TM8V", "TM9V", "ram_a1", \
+ "ram_a2", "ram_a3", "ram_a4", "ram_b1", "ram_b2", \
+ "ram_b3", "ram_b4", "TMHS", "TMLS", "TMPS", \
+ "TMPV", "TMTG", "TN0D", "TN0H", "TNTG", \
+ "Te1F", "Te1P", "Te1S", "Te2F", "Te2S", \
+ "Te3F", "Te3S", "Te4F", "Te4S", "Te5F", \
+ "Te5S", "TeGG", "TeGP", "TeRG", "TeRP", \
+ "TeRV", "Tp0C", "Tp1C", "TpPS", "TpTG", }
+
+#define ASMC_MP5_TEMPDESCS { "TA0P", "TCAC", "TCAD", "TCAG", "TCAH", \
+ "TCAS", "TCBC", "TCBD", "TCBG", "TCBH", \
+ "TCBS", "TH1F", "TH1P", "TH1V", "TH2F", \
+ "TH2P", "TH2V", "TH3F", "TH3P", "TH3V", \
+ "TH4F", "TH4P", "TH4V", "THPS", "THTG", \
+ "TM1P", "TM2P", "TM2V", "TM3P", "TM3V", \
+ "TM4P", "TM5P", "TM6P", "TM6V", "TM7P", \
+ "TM7V", "TM8P", "TM8V", "TM9V", "TMA1", \
+ "TMA2", "TMA3", "TMA4", "TMB1", "TMB2", \
+ "TMB3", "TMB4", "TMHS", "TMLS", "TMPS", \
+ "TMPV", "TMTG", "TN0D", "TN0H", "TNTG", \
+ "Te1F", "Te1P", "Te1S", "Te2F", "Te2S", \
+ "Te3F", "Te3S", "Te4F", "Te4S", "Te5F", \
+ "Te5S", "TeGG", "TeGP", "TeRG", "TeRP", \
+ "TeRV", "Tp0C", "Tp1C", "TpPS", "TpTG", }
+
#define ASMC_MBA_TEMPS { "TB0T", NULL }
#define ASMC_MBA_TEMPNAMES { "enclosure" }
#define ASMC_MBA_TEMPDESCS { "Enclosure Bottom" }
+
+#define ASMC_MBA3_TEMPS { "TB0T", "TB1T", "TB2T", \
+ "TC0D", "TC0E", "TC0P", NULL }
+
+#define ASMC_MBA3_TEMPNAMES { "enclosure", "TB1T", "TB2T", \
+ "TC0D", "TC0E", "TC0P" }
+
+#define ASMC_MBA3_TEMPDESCS { "Enclosure Bottom", "TB1T", "TB2T", \
+ "TC0D", "TC0E", "TC0P" }
diff --git a/sys/dev/atkbdc/atkbd.c b/sys/dev/atkbdc/atkbd.c
index 199fcb1..0d2b44b 100644
--- a/sys/dev/atkbdc/atkbd.c
+++ b/sys/dev/atkbdc/atkbd.c
@@ -62,7 +62,20 @@ __FBSDID("$FreeBSD$");
#include <dev/atkbdc/atkbdreg.h>
#include <dev/atkbdc/atkbdcreg.h>
-static timeout_t atkbd_timeout;
+typedef struct atkbd_state {
+ KBDC kbdc; /* keyboard controller */
+ int ks_mode; /* input mode (K_XLATE,K_RAW,K_CODE) */
+ int ks_flags; /* flags */
+#define COMPOSE (1 << 0)
+ int ks_polling;
+ int ks_state; /* shift/lock key state */
+ int ks_accents; /* accent key index (> 0) */
+ u_int ks_composed_char; /* composed char code (> 0) */
+ u_char ks_prefix; /* AT scan code prefix */
+ struct callout ks_timer;
+} atkbd_state_t;
+
+static void atkbd_timeout(void *arg);
static void atkbd_shutdown_final(void *v);
int
@@ -88,6 +101,7 @@ int
atkbd_attach_unit(device_t dev, keyboard_t **kbd, int irq, int flags)
{
keyboard_switch_t *sw;
+ atkbd_state_t *state;
int args[2];
int error;
int unit;
@@ -120,6 +134,8 @@ atkbd_attach_unit(device_t dev, keyboard_t **kbd, int irq, int flags)
* This is a kludge to compensate for lost keyboard interrupts.
* A similar code used to be in syscons. See below. XXX
*/
+ state = (atkbd_state_t *)(*kbd)->kb_data;
+ callout_init(&state->ks_timer, 0);
atkbd_timeout(*kbd);
if (bootverbose)
@@ -134,6 +150,7 @@ atkbd_attach_unit(device_t dev, keyboard_t **kbd, int irq, int flags)
static void
atkbd_timeout(void *arg)
{
+ atkbd_state_t *state;
keyboard_t *kbd;
int s;
@@ -175,25 +192,14 @@ atkbd_timeout(void *arg)
kbdd_intr(kbd, NULL);
}
splx(s);
- timeout(atkbd_timeout, arg, hz/10);
+ state = (atkbd_state_t *)kbd->kb_data;
+ callout_reset(&state->ks_timer, hz / 10, atkbd_timeout, arg);
}
/* LOW-LEVEL */
#define ATKBD_DEFAULT 0
-typedef struct atkbd_state {
- KBDC kbdc; /* keyboard controller */
- int ks_mode; /* input mode (K_XLATE,K_RAW,K_CODE) */
- int ks_flags; /* flags */
-#define COMPOSE (1 << 0)
- int ks_polling;
- int ks_state; /* shift/lock key state */
- int ks_accents; /* accent key index (> 0) */
- u_int ks_composed_char; /* composed char code (> 0) */
- u_char ks_prefix; /* AT scan code prefix */
-} atkbd_state_t;
-
/* keyboard driver declaration */
static int atkbd_configure(int flags);
static kbd_probe_t atkbd_probe;
@@ -470,7 +476,10 @@ bad:
static int
atkbd_term(keyboard_t *kbd)
{
+ atkbd_state_t *state = (atkbd_state_t *)kbd->kb_data;
+
kbd_unregister(kbd);
+ callout_drain(&state->ks_timer);
return 0;
}
diff --git a/sys/dev/bce/if_bce.c b/sys/dev/bce/if_bce.c
index 0f6d68b..2f9f459 100644
--- a/sys/dev/bce/if_bce.c
+++ b/sys/dev/bce/if_bce.c
@@ -457,9 +457,10 @@ static struct mbuf *bce_tso_setup (struct bce_softc *,
struct mbuf **, u16 *);
static int bce_tx_encap (struct bce_softc *, struct mbuf **);
static void bce_start_locked (struct ifnet *);
-static void bce_start (struct ifnet *);
-static int bce_ioctl (struct ifnet *, u_long, caddr_t);
-static void bce_watchdog (struct bce_softc *);
+static void bce_start (struct ifnet *);
+static int bce_ioctl (struct ifnet *, u_long, caddr_t);
+static uint64_t bce_get_counter (struct ifnet *, ift_counter);
+static void bce_watchdog (struct bce_softc *);
static int bce_ifmedia_upd (struct ifnet *);
static int bce_ifmedia_upd_locked (struct ifnet *);
static void bce_ifmedia_sts (struct ifnet *, struct ifmediareq *);
@@ -1389,6 +1390,7 @@ bce_attach(device_t dev)
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_ioctl = bce_ioctl;
ifp->if_start = bce_start;
+ ifp->if_get_counter = bce_get_counter;
ifp->if_init = bce_init;
ifp->if_mtu = ETHERMTU;
@@ -6747,9 +6749,7 @@ bce_rx_intr(struct bce_softc *sc)
L2_FHDR_ERRORS_TOO_SHORT | L2_FHDR_ERRORS_GIANT_FRAME)) {
/* Log the error and release the mbuf. */
- ifp->if_ierrors++;
sc->l2fhdr_error_count++;
-
m_freem(m0);
m0 = NULL;
goto bce_rx_intr_next_rx;
@@ -6830,7 +6830,7 @@ bce_rx_intr(struct bce_softc *sc)
}
/* Increment received packet statistics. */
- ifp->if_ipackets++;
+ if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
bce_rx_intr_next_rx:
sw_rx_cons = NEXT_RX_BD(sw_rx_cons);
@@ -6988,7 +6988,7 @@ bce_tx_intr(struct bce_softc *sc)
sc->tx_mbuf_ptr[sw_tx_chain_cons] = NULL;
DBRUN(sc->debug_tx_mbuf_alloc--);
- ifp->if_opackets++;
+ if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
}
sc->used_tx_bd--;
@@ -7901,7 +7901,7 @@ bce_watchdog(struct bce_softc *sc)
sc->bce_ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
bce_init_locked(sc);
- sc->bce_ifp->if_oerrors++;
+ sc->watchdog_timeouts++;
bce_watchdog_exit:
REG_WR(sc, BCE_EMAC_RX_STATUS, status);
@@ -8157,28 +8157,15 @@ bce_set_rx_mode(struct bce_softc *sc)
static void
bce_stats_update(struct bce_softc *sc)
{
- struct ifnet *ifp;
struct statistics_block *stats;
DBENTER(BCE_EXTREME_MISC);
- ifp = sc->bce_ifp;
-
bus_dmamap_sync(sc->stats_tag, sc->stats_map, BUS_DMASYNC_POSTREAD);
stats = (struct statistics_block *) sc->stats_block;
/*
- * Certain controllers don't report
- * carrier sense errors correctly.
- * See errata E11_5708CA0_1165.
- */
- if (!(BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5706) &&
- !(BCE_CHIP_ID(sc) == BCE_CHIP_ID_5708_A0))
- ifp->if_oerrors +=
- (u_long) stats->stat_Dot3StatsCarrierSenseErrors;
-
- /*
* Update the sysctl statistics from the
* hardware statistics.
*/
@@ -8359,35 +8346,51 @@ bce_stats_update(struct bce_softc *sc)
sc->com_no_buffers = REG_RD_IND(sc, 0x120084);
- /*
- * Update the interface statistics from the
- * hardware statistics.
- */
- ifp->if_collisions =
- (u_long) sc->stat_EtherStatsCollisions;
-
- /* ToDo: This method loses soft errors. */
- ifp->if_ierrors =
- (u_long) sc->stat_EtherStatsUndersizePkts +
- (u_long) sc->stat_EtherStatsOversizePkts +
- (u_long) sc->stat_IfInMBUFDiscards +
- (u_long) sc->stat_Dot3StatsAlignmentErrors +
- (u_long) sc->stat_Dot3StatsFCSErrors +
- (u_long) sc->stat_IfInRuleCheckerDiscards +
- (u_long) sc->stat_IfInFTQDiscards +
- (u_long) sc->com_no_buffers;
-
- /* ToDo: This method loses soft errors. */
- ifp->if_oerrors =
- (u_long) sc->stat_emac_tx_stat_dot3statsinternalmactransmiterrors +
- (u_long) sc->stat_Dot3StatsExcessiveCollisions +
- (u_long) sc->stat_Dot3StatsLateCollisions;
-
/* ToDo: Add additional statistics? */
DBEXIT(BCE_EXTREME_MISC);
}
+static uint64_t
+bce_get_counter(struct ifnet *ifp, ift_counter cnt)
+{
+ struct bce_softc *sc;
+ uint64_t rv;
+
+ sc = if_getsoftc(ifp);
+
+ switch (cnt) {
+ case IFCOUNTER_COLLISIONS:
+ return (sc->stat_EtherStatsCollisions);
+ case IFCOUNTER_IERRORS:
+ return (sc->stat_EtherStatsUndersizePkts +
+ sc->stat_EtherStatsOversizePkts +
+ sc->stat_IfInMBUFDiscards +
+ sc->stat_Dot3StatsAlignmentErrors +
+ sc->stat_Dot3StatsFCSErrors +
+ sc->stat_IfInRuleCheckerDiscards +
+ sc->stat_IfInFTQDiscards +
+ sc->l2fhdr_error_count +
+ sc->com_no_buffers);
+ case IFCOUNTER_OERRORS:
+ rv = sc->stat_Dot3StatsExcessiveCollisions +
+ sc->stat_emac_tx_stat_dot3statsinternalmactransmiterrors +
+ sc->stat_Dot3StatsLateCollisions +
+ sc->watchdog_timeouts;
+ /*
+ * Certain controllers don't report
+ * carrier sense errors correctly.
+ * See errata E11_5708CA0_1165.
+ */
+ if (!(BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5706) &&
+ !(BCE_CHIP_ID(sc) == BCE_CHIP_ID_5708_A0))
+ rv += sc->stat_Dot3StatsCarrierSenseErrors;
+ return (rv);
+ default:
+ return (if_get_counter_default(ifp, cnt));
+ }
+}
+
/****************************************************************************/
/* Periodic function to notify the bootcode that the driver is still */
diff --git a/sys/dev/bce/if_bcereg.h b/sys/dev/bce/if_bcereg.h
index 16f99cc..d9df1fa 100644
--- a/sys/dev/bce/if_bcereg.h
+++ b/sys/dev/bce/if_bcereg.h
@@ -6692,6 +6692,7 @@ struct bce_softc
u32 l2fhdr_error_count;
u32 dma_map_addr_tx_failed_count;
u32 dma_map_addr_rx_failed_count;
+ u32 watchdog_timeouts;
/* Host coalescing block command register */
u32 hc_command;
diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c
index 3e87eaf..99bc344 100644
--- a/sys/dev/cxgbe/t4_main.c
+++ b/sys/dev/cxgbe/t4_main.c
@@ -3031,8 +3031,10 @@ update_mac_settings(struct ifnet *ifp, int flags)
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK)
continue;
- mcaddr[i++] =
+ mcaddr[i] =
LLADDR((struct sockaddr_dl *)ifma->ifma_addr);
+ MPASS(ETHER_IS_MULTICAST(mcaddr[i]));
+ i++;
if (i == FW_MAC_EXACT_CHUNK) {
rc = t4_alloc_mac_filt(sc, sc->mbox, viid, del,
@@ -8281,6 +8283,12 @@ t4_activate_uld(struct adapter *sc, int id)
SLIST_FOREACH(ui, &t4_uld_list, link) {
if (ui->uld_id == id) {
+ if (!(sc->flags & FULL_INIT_DONE)) {
+ rc = adapter_full_init(sc);
+ if (rc != 0)
+ goto done;
+ }
+
rc = ui->activate(sc);
if (rc == 0)
ui->refcount++;
diff --git a/sys/dev/cxgbe/tom/t4_listen.c b/sys/dev/cxgbe/tom/t4_listen.c
index 1c25baf..4380c9e 100644
--- a/sys/dev/cxgbe/tom/t4_listen.c
+++ b/sys/dev/cxgbe/tom/t4_listen.c
@@ -1311,7 +1311,7 @@ do_pass_accept_req(struct sge_iq *iq, const struct rss_header *rss,
REJECT_PASS_ACCEPT();
rpl = wrtod(wr);
- INP_INFO_WLOCK(&V_tcbinfo); /* for 4-tuple check, syncache_add */
+ INP_INFO_WLOCK(&V_tcbinfo); /* for 4-tuple check */
/* Don't offload if the 4-tuple is already in use */
if (toe_4tuple_check(&inc, &th, ifp) != 0) {
@@ -1319,6 +1319,7 @@ do_pass_accept_req(struct sge_iq *iq, const struct rss_header *rss,
free(wr, M_CXGBE);
REJECT_PASS_ACCEPT();
}
+ INP_INFO_WUNLOCK(&V_tcbinfo);
inp = lctx->inp; /* listening socket, not owned by TOE */
INP_WLOCK(inp);
@@ -1331,7 +1332,6 @@ do_pass_accept_req(struct sge_iq *iq, const struct rss_header *rss,
* resources tied to this listen context.
*/
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
free(wr, M_CXGBE);
REJECT_PASS_ACCEPT();
}
@@ -1378,12 +1378,10 @@ do_pass_accept_req(struct sge_iq *iq, const struct rss_header *rss,
/*
* If all goes well t4_syncache_respond will get called during
- * syncache_add. Also note that syncache_add releases both pcbinfo and
- * pcb locks.
+ * syncache_add. Note that syncache_add releases the pcb lock.
*/
toe_syncache_add(&inc, &to, &th, inp, tod, synqe);
INP_UNLOCK_ASSERT(inp); /* ok to assert, we have a ref on the inp */
- INP_INFO_UNLOCK_ASSERT(&V_tcbinfo);
/*
* If we replied during syncache_add (synqe->wr has been consumed),
diff --git a/sys/dev/dwc/if_dwc.c b/sys/dev/dwc/if_dwc.c
new file mode 100644
index 0000000..f07832c
--- /dev/null
+++ b/sys/dev/dwc/if_dwc.c
@@ -0,0 +1,1324 @@
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+/*
+ * Ethernet media access controller (EMAC)
+ * Chapter 17, Altera Cyclone V Device Handbook (CV-5V2 2014.07.22)
+ *
+ * EMAC is an instance of the Synopsys DesignWare 3504-0
+ * Universal 10/100/1000 Ethernet MAC (DWC_gmac).
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/timeet.h>
+#include <sys/timetc.h>
+#include <sys/endian.h>
+#include <sys/lock.h>
+#include <sys/mbuf.h>
+#include <sys/mutex.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <net/bpf.h>
+#include <net/if.h>
+#include <net/ethernet.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <net/if_var.h>
+#include <net/if_vlan_var.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/cpu.h>
+#include <machine/intr.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+#include "miibus_if.h"
+
+#define READ4(_sc, _reg) \
+ bus_read_4((_sc)->res[0], _reg)
+#define WRITE4(_sc, _reg, _val) \
+ bus_write_4((_sc)->res[0], _reg, _val)
+
+#define WATCHDOG_TIMEOUT_SECS 5
+#define STATS_HARVEST_INTERVAL 2
+#define MII_CLK_VAL 2
+
+#include <dev/dwc/if_dwc.h>
+
+#define DWC_LOCK(sc) mtx_lock(&(sc)->mtx)
+#define DWC_UNLOCK(sc) mtx_unlock(&(sc)->mtx)
+#define DWC_ASSERT_LOCKED(sc) mtx_assert(&(sc)->mtx, MA_OWNED);
+#define DWC_ASSERT_UNLOCKED(sc) mtx_assert(&(sc)->mtx, MA_NOTOWNED);
+
+#define DDESC_TDES0_OWN (1 << 31)
+#define DDESC_TDES0_TXINT (1 << 30)
+#define DDESC_TDES0_TXLAST (1 << 29)
+#define DDESC_TDES0_TXFIRST (1 << 28)
+#define DDESC_TDES0_TXCRCDIS (1 << 27)
+#define DDESC_TDES0_TXRINGEND (1 << 21)
+#define DDESC_TDES0_TXCHAIN (1 << 20)
+
+#define DDESC_RDES0_OWN (1 << 31)
+#define DDESC_RDES0_FL_MASK 0x3fff
+#define DDESC_RDES0_FL_SHIFT 16 /* Frame Length */
+#define DDESC_RDES1_CHAINED (1 << 14)
+
+struct dwc_bufmap {
+ bus_dmamap_t map;
+ struct mbuf *mbuf;
+};
+
+/*
+ * A hardware buffer descriptor. Rx and Tx buffers have the same descriptor
+ * layout, but the bits in the flags field have different meanings.
+ */
+struct dwc_hwdesc
+{
+ uint32_t tdes0;
+ uint32_t tdes1;
+ uint32_t addr; /* pointer to buffer data */
+ uint32_t addr_next; /* link to next descriptor */
+};
+
+/*
+ * Driver data and defines.
+ */
+#define RX_DESC_COUNT 1024
+#define RX_DESC_SIZE (sizeof(struct dwc_hwdesc) * RX_DESC_COUNT)
+#define TX_DESC_COUNT 1024
+#define TX_DESC_SIZE (sizeof(struct dwc_hwdesc) * TX_DESC_COUNT)
+
+/*
+ * The hardware imposes alignment restrictions on various objects involved in
+ * DMA transfers. These values are expressed in bytes (not bits).
+ */
+#define DWC_DESC_RING_ALIGN 2048
+
+struct dwc_softc {
+ struct resource *res[2];
+ bus_space_tag_t bst;
+ bus_space_handle_t bsh;
+ device_t dev;
+ int mii_clk;
+ device_t miibus;
+ struct mii_data * mii_softc;
+ struct ifnet *ifp;
+ int if_flags;
+ struct mtx mtx;
+ void * intr_cookie;
+ struct callout dwc_callout;
+ uint8_t phy_conn_type;
+ uint8_t mactype;
+ boolean_t link_is_up;
+ boolean_t is_attached;
+ boolean_t is_detaching;
+ int tx_watchdog_count;
+ int stats_harvest_count;
+
+ /* RX */
+ bus_dma_tag_t rxdesc_tag;
+ bus_dmamap_t rxdesc_map;
+ struct dwc_hwdesc *rxdesc_ring;
+ bus_addr_t rxdesc_ring_paddr;
+ bus_dma_tag_t rxbuf_tag;
+ struct dwc_bufmap rxbuf_map[RX_DESC_COUNT];
+ uint32_t rx_idx;
+
+ /* TX */
+ bus_dma_tag_t txdesc_tag;
+ bus_dmamap_t txdesc_map;
+ struct dwc_hwdesc *txdesc_ring;
+ bus_addr_t txdesc_ring_paddr;
+ bus_dma_tag_t txbuf_tag;
+ struct dwc_bufmap txbuf_map[RX_DESC_COUNT];
+ uint32_t tx_idx_head;
+ uint32_t tx_idx_tail;
+ int txcount;
+};
+
+static struct resource_spec dwc_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_IRQ, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static void dwc_txfinish_locked(struct dwc_softc *sc);
+static void dwc_rxfinish_locked(struct dwc_softc *sc);
+static void dwc_stop_locked(struct dwc_softc *sc);
+static void dwc_setup_rxfilter(struct dwc_softc *sc);
+
+static inline uint32_t
+next_rxidx(struct dwc_softc *sc, uint32_t curidx)
+{
+
+ return ((curidx + 1) % RX_DESC_COUNT);
+}
+
+static inline uint32_t
+next_txidx(struct dwc_softc *sc, uint32_t curidx)
+{
+
+ return ((curidx + 1) % TX_DESC_COUNT);
+}
+
+static void
+dwc_get1paddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+
+ if (error != 0)
+ return;
+ *(bus_addr_t *)arg = segs[0].ds_addr;
+}
+
+inline static uint32_t
+dwc_setup_txdesc(struct dwc_softc *sc, int idx, bus_addr_t paddr,
+ uint32_t len)
+{
+ uint32_t flags;
+ uint32_t nidx;
+
+ nidx = next_txidx(sc, idx);
+
+ /* Addr/len 0 means we're clearing the descriptor after xmit done. */
+ if (paddr == 0 || len == 0) {
+ flags = 0;
+ --sc->txcount;
+ } else {
+ flags = DDESC_TDES0_TXCHAIN | DDESC_TDES0_TXFIRST
+ | DDESC_TDES0_TXLAST | DDESC_TDES0_TXINT;
+ ++sc->txcount;
+ }
+
+ sc->txdesc_ring[idx].addr = (uint32_t)(paddr);
+ sc->txdesc_ring[idx].tdes0 = flags;
+ sc->txdesc_ring[idx].tdes1 = len;
+
+ if (paddr && len) {
+ wmb();
+ sc->txdesc_ring[idx].tdes0 |= DDESC_TDES0_OWN;
+ wmb();
+ }
+
+ return (nidx);
+}
+
+static int
+dwc_setup_txbuf(struct dwc_softc *sc, int idx, struct mbuf **mp)
+{
+ struct bus_dma_segment seg;
+ int error, nsegs;
+ struct mbuf * m;
+
+ if ((m = m_defrag(*mp, M_NOWAIT)) == NULL)
+ return (ENOMEM);
+ *mp = m;
+
+ error = bus_dmamap_load_mbuf_sg(sc->txbuf_tag, sc->txbuf_map[idx].map,
+ m, &seg, &nsegs, 0);
+ if (error != 0) {
+ return (ENOMEM);
+ }
+
+ KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs));
+
+ bus_dmamap_sync(sc->txbuf_tag, sc->txbuf_map[idx].map,
+ BUS_DMASYNC_PREWRITE);
+
+ sc->txbuf_map[idx].mbuf = m;
+
+ dwc_setup_txdesc(sc, idx, seg.ds_addr, seg.ds_len);
+
+ return (0);
+}
+
+static void
+dwc_txstart_locked(struct dwc_softc *sc)
+{
+ struct ifnet *ifp;
+ struct mbuf *m;
+ int enqueued;
+
+ DWC_ASSERT_LOCKED(sc);
+
+ if (!sc->link_is_up)
+ return;
+
+ ifp = sc->ifp;
+
+ if (ifp->if_drv_flags & IFF_DRV_OACTIVE) {
+ return;
+ }
+
+ enqueued = 0;
+
+ for (;;) {
+ if (sc->txcount == (TX_DESC_COUNT-1)) {
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ break;
+ }
+
+ IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
+ if (m == NULL)
+ break;
+ if (dwc_setup_txbuf(sc, sc->tx_idx_head, &m) != 0) {
+ IFQ_DRV_PREPEND(&ifp->if_snd, m);
+ break;
+ }
+ BPF_MTAP(ifp, m);
+ sc->tx_idx_head = next_txidx(sc, sc->tx_idx_head);
+ ++enqueued;
+ }
+
+ if (enqueued != 0) {
+ WRITE4(sc, TRANSMIT_POLL_DEMAND, 0x1);
+ sc->tx_watchdog_count = WATCHDOG_TIMEOUT_SECS;
+ }
+}
+
+static void
+dwc_txstart(struct ifnet *ifp)
+{
+ struct dwc_softc *sc = ifp->if_softc;
+
+ DWC_LOCK(sc);
+ dwc_txstart_locked(sc);
+ DWC_UNLOCK(sc);
+}
+
+static void
+dwc_stop_locked(struct dwc_softc *sc)
+{
+ struct ifnet *ifp;
+ int reg;
+
+ DWC_ASSERT_LOCKED(sc);
+
+ ifp = sc->ifp;
+ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ sc->tx_watchdog_count = 0;
+ sc->stats_harvest_count = 0;
+
+ callout_stop(&sc->dwc_callout);
+
+ /* Stop DMA TX */
+ reg = READ4(sc, OPERATION_MODE);
+ reg &= ~(MODE_ST);
+ WRITE4(sc, OPERATION_MODE, reg);
+
+ /* Flush TX */
+ reg = READ4(sc, OPERATION_MODE);
+ reg |= (MODE_FTF);
+ WRITE4(sc, OPERATION_MODE, reg);
+
+ /* Stop transmitters */
+ reg = READ4(sc, MAC_CONFIGURATION);
+ reg &= ~(CONF_TE | CONF_RE);
+ WRITE4(sc, MAC_CONFIGURATION, reg);
+
+ /* Stop DMA RX */
+ reg = READ4(sc, OPERATION_MODE);
+ reg &= ~(MODE_SR);
+ WRITE4(sc, OPERATION_MODE, reg);
+}
+
+static void dwc_clear_stats(struct dwc_softc *sc)
+{
+ int reg;
+
+ reg = READ4(sc, MMC_CONTROL);
+ reg |= (MMC_CONTROL_CNTRST);
+ WRITE4(sc, MMC_CONTROL, reg);
+}
+
+static void
+dwc_harvest_stats(struct dwc_softc *sc)
+{
+ struct ifnet *ifp;
+
+ /* We don't need to harvest too often. */
+ if (++sc->stats_harvest_count < STATS_HARVEST_INTERVAL)
+ return;
+
+ sc->stats_harvest_count = 0;
+ ifp = sc->ifp;
+
+ if_inc_counter(ifp, IFCOUNTER_IPACKETS, READ4(sc, RXFRAMECOUNT_GB));
+ if_inc_counter(ifp, IFCOUNTER_IMCASTS, READ4(sc, RXMULTICASTFRAMES_G));
+ if_inc_counter(ifp, IFCOUNTER_IERRORS,
+ READ4(sc, RXOVERSIZE_G) + READ4(sc, RXUNDERSIZE_G) +
+ READ4(sc, RXCRCERROR) + READ4(sc, RXALIGNMENTERROR) +
+ READ4(sc, RXRUNTERROR) + READ4(sc, RXJABBERERROR) +
+ READ4(sc, RXLENGTHERROR));
+
+ if_inc_counter(ifp, IFCOUNTER_OPACKETS, READ4(sc, TXFRAMECOUNT_G));
+ if_inc_counter(ifp, IFCOUNTER_OMCASTS, READ4(sc, TXMULTICASTFRAMES_G));
+ if_inc_counter(ifp, IFCOUNTER_OERRORS,
+ READ4(sc, TXOVERSIZE_G) + READ4(sc, TXEXCESSDEF) +
+ READ4(sc, TXCARRIERERR) + READ4(sc, TXUNDERFLOWERROR));
+
+ if_inc_counter(ifp, IFCOUNTER_COLLISIONS,
+ READ4(sc, TXEXESSCOL) + READ4(sc, TXLATECOL));
+
+ dwc_clear_stats(sc);
+}
+
+static void
+dwc_tick(void *arg)
+{
+ struct dwc_softc *sc;
+ struct ifnet *ifp;
+ int link_was_up;
+
+ sc = arg;
+
+ DWC_ASSERT_LOCKED(sc);
+
+ ifp = sc->ifp;
+
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
+ return;
+
+ /*
+ * Typical tx watchdog. If this fires it indicates that we enqueued
+ * packets for output and never got a txdone interrupt for them. Maybe
+ * it's a missed interrupt somehow, just pretend we got one.
+ */
+ if (sc->tx_watchdog_count > 0) {
+ if (--sc->tx_watchdog_count == 0) {
+ dwc_txfinish_locked(sc);
+ }
+ }
+
+ /* Gather stats from hardware counters. */
+ dwc_harvest_stats(sc);
+
+ /* Check the media status. */
+ link_was_up = sc->link_is_up;
+ mii_tick(sc->mii_softc);
+ if (sc->link_is_up && !link_was_up)
+ dwc_txstart_locked(sc);
+
+ /* Schedule another check one second from now. */
+ callout_reset(&sc->dwc_callout, hz, dwc_tick, sc);
+}
+
+static void
+dwc_init_locked(struct dwc_softc *sc)
+{
+ struct ifnet *ifp = sc->ifp;
+ int reg;
+
+ DWC_ASSERT_LOCKED(sc);
+
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ return;
+
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+
+ dwc_setup_rxfilter(sc);
+
+ /* Initializa DMA and enable transmitters */
+ reg = READ4(sc, OPERATION_MODE);
+ reg |= (MODE_TSF | MODE_OSF | MODE_FUF);
+ reg &= ~(MODE_RSF);
+ reg |= (MODE_RTC_LEV32 << MODE_RTC_SHIFT);
+ WRITE4(sc, OPERATION_MODE, reg);
+
+ WRITE4(sc, INTERRUPT_ENABLE, INT_EN_DEFAULT);
+
+ /* Start DMA */
+ reg = READ4(sc, OPERATION_MODE);
+ reg |= (MODE_ST | MODE_SR);
+ WRITE4(sc, OPERATION_MODE, reg);
+
+ /* Enable transmitters */
+ reg = READ4(sc, MAC_CONFIGURATION);
+ reg |= (CONF_JD | CONF_ACS | CONF_BE);
+ reg |= (CONF_TE | CONF_RE);
+ WRITE4(sc, MAC_CONFIGURATION, reg);
+
+ /*
+ * Call mii_mediachg() which will call back into dwc_miibus_statchg()
+ * to set up the remaining config registers based on current media.
+ */
+ mii_mediachg(sc->mii_softc);
+ callout_reset(&sc->dwc_callout, hz, dwc_tick, sc);
+}
+
+static void
+dwc_init(void *if_softc)
+{
+ struct dwc_softc *sc = if_softc;
+
+ DWC_LOCK(sc);
+ dwc_init_locked(sc);
+ DWC_UNLOCK(sc);
+}
+
+inline static uint32_t
+dwc_setup_rxdesc(struct dwc_softc *sc, int idx, bus_addr_t paddr)
+{
+ uint32_t nidx;
+
+ sc->rxdesc_ring[idx].addr = (uint32_t)paddr;
+ nidx = next_rxidx(sc, idx);
+ sc->rxdesc_ring[idx].addr_next = sc->rxdesc_ring_paddr + \
+ (nidx * sizeof(struct dwc_hwdesc));
+ sc->rxdesc_ring[idx].tdes1 = DDESC_RDES1_CHAINED | MCLBYTES;
+
+ wmb();
+ sc->rxdesc_ring[idx].tdes0 = DDESC_RDES0_OWN;
+ wmb();
+
+ return (nidx);
+}
+
+static int
+dwc_setup_rxbuf(struct dwc_softc *sc, int idx, struct mbuf *m)
+{
+ struct bus_dma_segment seg;
+ int error, nsegs;
+
+ m_adj(m, ETHER_ALIGN);
+
+ error = bus_dmamap_load_mbuf_sg(sc->rxbuf_tag, sc->rxbuf_map[idx].map,
+ m, &seg, &nsegs, 0);
+ if (error != 0) {
+ return (error);
+ }
+
+ KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs));
+
+ bus_dmamap_sync(sc->rxbuf_tag, sc->rxbuf_map[idx].map,
+ BUS_DMASYNC_PREREAD);
+
+ sc->rxbuf_map[idx].mbuf = m;
+ dwc_setup_rxdesc(sc, idx, seg.ds_addr);
+
+ return (0);
+}
+
+static struct mbuf *
+dwc_alloc_mbufcl(struct dwc_softc *sc)
+{
+ struct mbuf *m;
+
+ m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
+ m->m_pkthdr.len = m->m_len = m->m_ext.ext_size;
+
+ return (m);
+}
+
+static void
+dwc_media_status(struct ifnet * ifp, struct ifmediareq *ifmr)
+{
+ struct dwc_softc *sc;
+ struct mii_data *mii;
+
+ sc = ifp->if_softc;
+ mii = sc->mii_softc;
+ DWC_LOCK(sc);
+ mii_pollstat(mii);
+ ifmr->ifm_active = mii->mii_media_active;
+ ifmr->ifm_status = mii->mii_media_status;
+ DWC_UNLOCK(sc);
+}
+
+static int
+dwc_media_change_locked(struct dwc_softc *sc)
+{
+
+ return (mii_mediachg(sc->mii_softc));
+}
+
+static int
+dwc_media_change(struct ifnet * ifp)
+{
+ struct dwc_softc *sc;
+ int error;
+
+ sc = ifp->if_softc;
+
+ DWC_LOCK(sc);
+ error = dwc_media_change_locked(sc);
+ DWC_UNLOCK(sc);
+ return (error);
+}
+
+static const uint8_t nibbletab[] = {
+ /* 0x0 0000 -> 0000 */ 0x0,
+ /* 0x1 0001 -> 1000 */ 0x8,
+ /* 0x2 0010 -> 0100 */ 0x4,
+ /* 0x3 0011 -> 1100 */ 0xc,
+ /* 0x4 0100 -> 0010 */ 0x2,
+ /* 0x5 0101 -> 1010 */ 0xa,
+ /* 0x6 0110 -> 0110 */ 0x6,
+ /* 0x7 0111 -> 1110 */ 0xe,
+ /* 0x8 1000 -> 0001 */ 0x1,
+ /* 0x9 1001 -> 1001 */ 0x9,
+ /* 0xa 1010 -> 0101 */ 0x5,
+ /* 0xb 1011 -> 1101 */ 0xd,
+ /* 0xc 1100 -> 0011 */ 0x3,
+ /* 0xd 1101 -> 1011 */ 0xb,
+ /* 0xe 1110 -> 0111 */ 0x7,
+ /* 0xf 1111 -> 1111 */ 0xf, };
+
+static uint8_t
+bitreverse(uint8_t x)
+{
+
+ return (nibbletab[x & 0xf] << 4) | nibbletab[x >> 4];
+}
+
+static void
+dwc_setup_rxfilter(struct dwc_softc *sc)
+{
+ struct ifmultiaddr *ifma;
+ struct ifnet *ifp;
+ uint8_t *eaddr;
+ uint32_t crc;
+ uint8_t val;
+ int hashbit;
+ int hashreg;
+ int ffval;
+ int reg;
+ int lo;
+ int hi;
+
+ DWC_ASSERT_LOCKED(sc);
+
+ ifp = sc->ifp;
+
+ /*
+ * Set the multicast (group) filter hash.
+ */
+ if ((ifp->if_flags & IFF_ALLMULTI))
+ ffval = (FRAME_FILTER_PM);
+ else {
+ ffval = (FRAME_FILTER_HMC);
+ if_maddr_rlock(ifp);
+ TAILQ_FOREACH(ifma, &sc->ifp->if_multiaddrs, ifma_link) {
+ if (ifma->ifma_addr->sa_family != AF_LINK)
+ continue;
+ crc = ether_crc32_le(LLADDR((struct sockaddr_dl *)
+ ifma->ifma_addr), ETHER_ADDR_LEN);
+
+ /* Take lower 8 bits and reverse it */
+ val = bitreverse(~crc & 0xff);
+ hashreg = (val >> 5);
+ hashbit = (val & 31);
+
+ reg = READ4(sc, HASH_TABLE_REG(hashreg));
+ reg |= (1 << hashbit);
+ WRITE4(sc, HASH_TABLE_REG(hashreg), reg);
+ }
+ if_maddr_runlock(ifp);
+ }
+
+ /*
+ * Set the individual address filter hash.
+ */
+ if (ifp->if_flags & IFF_PROMISC)
+ ffval |= (FRAME_FILTER_PR);
+
+ /*
+ * Set the primary address.
+ */
+ eaddr = IF_LLADDR(ifp);
+ lo = eaddr[0] | (eaddr[1] << 8) | (eaddr[2] << 16) |
+ (eaddr[3] << 24);
+ hi = eaddr[4] | (eaddr[5] << 8);
+ WRITE4(sc, MAC_ADDRESS_LOW(0), lo);
+ WRITE4(sc, MAC_ADDRESS_HIGH(0), hi);
+ WRITE4(sc, MAC_FRAME_FILTER, ffval);
+}
+
+static int
+dwc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+{
+ struct dwc_softc *sc;
+ struct mii_data *mii;
+ struct ifreq *ifr;
+ int mask, error;
+
+ sc = ifp->if_softc;
+ ifr = (struct ifreq *)data;
+
+ error = 0;
+ switch (cmd) {
+ case SIOCSIFFLAGS:
+ DWC_LOCK(sc);
+ if (ifp->if_flags & IFF_UP) {
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ if ((ifp->if_flags ^ sc->if_flags) &
+ (IFF_PROMISC | IFF_ALLMULTI))
+ dwc_setup_rxfilter(sc);
+ } else {
+ if (!sc->is_detaching)
+ dwc_init_locked(sc);
+ }
+ } else {
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ dwc_stop_locked(sc);
+ }
+ sc->if_flags = ifp->if_flags;
+ DWC_UNLOCK(sc);
+ break;
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ DWC_LOCK(sc);
+ dwc_setup_rxfilter(sc);
+ DWC_UNLOCK(sc);
+ }
+ break;
+ case SIOCSIFMEDIA:
+ case SIOCGIFMEDIA:
+ mii = sc->mii_softc;
+ error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
+ break;
+ case SIOCSIFCAP:
+ mask = ifp->if_capenable ^ ifr->ifr_reqcap;
+ if (mask & IFCAP_VLAN_MTU) {
+ /* No work to do except acknowledge the change took */
+ ifp->if_capenable ^= IFCAP_VLAN_MTU;
+ }
+ break;
+
+ default:
+ error = ether_ioctl(ifp, cmd, data);
+ break;
+ }
+
+ return (error);
+}
+
+static void
+dwc_txfinish_locked(struct dwc_softc *sc)
+{
+ struct dwc_bufmap *bmap;
+ struct dwc_hwdesc *desc;
+ struct ifnet *ifp;
+
+ DWC_ASSERT_LOCKED(sc);
+
+ ifp = sc->ifp;
+
+ while (sc->tx_idx_tail != sc->tx_idx_head) {
+ desc = &sc->txdesc_ring[sc->tx_idx_tail];
+ if ((desc->tdes0 & DDESC_TDES0_OWN) != 0)
+ break;
+ bmap = &sc->txbuf_map[sc->tx_idx_tail];
+ bus_dmamap_sync(sc->txbuf_tag, bmap->map,
+ BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->txbuf_tag, bmap->map);
+ m_freem(bmap->mbuf);
+ bmap->mbuf = NULL;
+ dwc_setup_txdesc(sc, sc->tx_idx_tail, 0, 0);
+ sc->tx_idx_tail = next_txidx(sc, sc->tx_idx_tail);
+ }
+
+ /* If there are no buffers outstanding, muzzle the watchdog. */
+ if (sc->tx_idx_tail == sc->tx_idx_head) {
+ sc->tx_watchdog_count = 0;
+ }
+}
+
+static void
+dwc_rxfinish_locked(struct dwc_softc *sc)
+{
+ struct ifnet *ifp;
+ struct mbuf *m0;
+ struct mbuf *m;
+ int error;
+ int rdes0;
+ int idx;
+ int len;
+
+ ifp = sc->ifp;
+
+ for (;;) {
+ idx = sc->rx_idx;
+
+ rdes0 = sc->rxdesc_ring[idx].tdes0;
+ if ((rdes0 & DDESC_RDES0_OWN) != 0)
+ break;
+
+ bus_dmamap_sync(sc->rxbuf_tag, sc->rxbuf_map[idx].map,
+ BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->rxbuf_tag, sc->rxbuf_map[idx].map);
+
+ len = (rdes0 >> DDESC_RDES0_FL_SHIFT) & DDESC_RDES0_FL_MASK;
+ if (len != 0) {
+ m = sc->rxbuf_map[idx].mbuf;
+ m->m_pkthdr.rcvif = ifp;
+ m->m_pkthdr.len = len;
+ m->m_len = len;
+ ifp->if_ipackets++;
+
+ DWC_UNLOCK(sc);
+ (*ifp->if_input)(ifp, m);
+ DWC_LOCK(sc);
+ } else {
+ /* XXX Zero-length packet ? */
+ }
+
+ if ((m0 = dwc_alloc_mbufcl(sc)) != NULL) {
+ if ((error = dwc_setup_rxbuf(sc, idx, m0)) != 0) {
+ /*
+ * XXX Now what?
+ * We've got a hole in the rx ring.
+ */
+ }
+ } else
+ if_inc_counter(sc->ifp, IFCOUNTER_IQDROPS, 1);
+
+ sc->rx_idx = next_rxidx(sc, sc->rx_idx);
+ }
+}
+
+static void
+dwc_intr(void *arg)
+{
+ struct dwc_softc *sc;
+ uint32_t reg;
+
+ sc = arg;
+
+ DWC_LOCK(sc);
+
+ reg = READ4(sc, INTERRUPT_STATUS);
+ if (reg) {
+ mii_mediachg(sc->mii_softc);
+ READ4(sc, SGMII_RGMII_SMII_CTRL_STATUS);
+ }
+
+ reg = READ4(sc, DMA_STATUS);
+ if (reg & DMA_STATUS_NIS) {
+ if (reg & DMA_STATUS_RI)
+ dwc_rxfinish_locked(sc);
+
+ if (reg & DMA_STATUS_TI)
+ dwc_txfinish_locked(sc);
+ }
+
+ if (reg & DMA_STATUS_AIS) {
+ if (reg & DMA_STATUS_FBI) {
+ /* Fatal bus error */
+ device_printf(sc->dev,
+ "Ethernet DMA error, restarting controller.\n");
+ dwc_stop_locked(sc);
+ dwc_init_locked(sc);
+ }
+ }
+
+ WRITE4(sc, DMA_STATUS, reg & DMA_STATUS_INTR_MASK);
+ DWC_UNLOCK(sc);
+}
+
+static int
+setup_dma(struct dwc_softc *sc)
+{
+ struct mbuf *m;
+ int error;
+ int nidx;
+ int idx;
+
+ /*
+ * Set up TX descriptor ring, descriptors, and dma maps.
+ */
+ error = bus_dma_tag_create(
+ bus_get_dma_tag(sc->dev), /* Parent tag. */
+ DWC_DESC_RING_ALIGN, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ TX_DESC_SIZE, 1, /* maxsize, nsegments */
+ TX_DESC_SIZE, /* maxsegsize */
+ 0, /* flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->txdesc_tag);
+ if (error != 0) {
+ device_printf(sc->dev,
+ "could not create TX ring DMA tag.\n");
+ goto out;
+ }
+
+ error = bus_dmamem_alloc(sc->txdesc_tag, (void**)&sc->txdesc_ring,
+ BUS_DMA_COHERENT | BUS_DMA_WAITOK | BUS_DMA_ZERO,
+ &sc->txdesc_map);
+ if (error != 0) {
+ device_printf(sc->dev,
+ "could not allocate TX descriptor ring.\n");
+ goto out;
+ }
+
+ error = bus_dmamap_load(sc->txdesc_tag, sc->txdesc_map,
+ sc->txdesc_ring, TX_DESC_SIZE, dwc_get1paddr,
+ &sc->txdesc_ring_paddr, 0);
+ if (error != 0) {
+ device_printf(sc->dev,
+ "could not load TX descriptor ring map.\n");
+ goto out;
+ }
+
+ for (idx = 0; idx < TX_DESC_COUNT; idx++) {
+ sc->txdesc_ring[idx].tdes0 = DDESC_TDES0_TXCHAIN;
+ sc->txdesc_ring[idx].tdes1 = 0;
+ nidx = next_txidx(sc, idx);
+ sc->txdesc_ring[idx].addr_next = sc->txdesc_ring_paddr + \
+ (nidx * sizeof(struct dwc_hwdesc));
+ }
+
+ error = bus_dma_tag_create(
+ bus_get_dma_tag(sc->dev), /* Parent tag. */
+ 1, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ MCLBYTES, 1, /* maxsize, nsegments */
+ MCLBYTES, /* maxsegsize */
+ 0, /* flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->txbuf_tag);
+ if (error != 0) {
+ device_printf(sc->dev,
+ "could not create TX ring DMA tag.\n");
+ goto out;
+ }
+
+ for (idx = 0; idx < TX_DESC_COUNT; idx++) {
+ error = bus_dmamap_create(sc->txbuf_tag, BUS_DMA_COHERENT,
+ &sc->txbuf_map[idx].map);
+ if (error != 0) {
+ device_printf(sc->dev,
+ "could not create TX buffer DMA map.\n");
+ goto out;
+ }
+ dwc_setup_txdesc(sc, idx, 0, 0);
+ }
+
+ /*
+ * Set up RX descriptor ring, descriptors, dma maps, and mbufs.
+ */
+ error = bus_dma_tag_create(
+ bus_get_dma_tag(sc->dev), /* Parent tag. */
+ DWC_DESC_RING_ALIGN, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ RX_DESC_SIZE, 1, /* maxsize, nsegments */
+ RX_DESC_SIZE, /* maxsegsize */
+ 0, /* flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->rxdesc_tag);
+ if (error != 0) {
+ device_printf(sc->dev,
+ "could not create RX ring DMA tag.\n");
+ goto out;
+ }
+
+ error = bus_dmamem_alloc(sc->rxdesc_tag, (void **)&sc->rxdesc_ring,
+ BUS_DMA_COHERENT | BUS_DMA_WAITOK | BUS_DMA_ZERO,
+ &sc->rxdesc_map);
+ if (error != 0) {
+ device_printf(sc->dev,
+ "could not allocate RX descriptor ring.\n");
+ goto out;
+ }
+
+ error = bus_dmamap_load(sc->rxdesc_tag, sc->rxdesc_map,
+ sc->rxdesc_ring, RX_DESC_SIZE, dwc_get1paddr,
+ &sc->rxdesc_ring_paddr, 0);
+ if (error != 0) {
+ device_printf(sc->dev,
+ "could not load RX descriptor ring map.\n");
+ goto out;
+ }
+
+ error = bus_dma_tag_create(
+ bus_get_dma_tag(sc->dev), /* Parent tag. */
+ 1, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ MCLBYTES, 1, /* maxsize, nsegments */
+ MCLBYTES, /* maxsegsize */
+ 0, /* flags */
+ NULL, NULL, /* lockfunc, lockarg */
+ &sc->rxbuf_tag);
+ if (error != 0) {
+ device_printf(sc->dev,
+ "could not create RX buf DMA tag.\n");
+ goto out;
+ }
+
+ for (idx = 0; idx < RX_DESC_COUNT; idx++) {
+ error = bus_dmamap_create(sc->rxbuf_tag, BUS_DMA_COHERENT,
+ &sc->rxbuf_map[idx].map);
+ if (error != 0) {
+ device_printf(sc->dev,
+ "could not create RX buffer DMA map.\n");
+ goto out;
+ }
+ if ((m = dwc_alloc_mbufcl(sc)) == NULL) {
+ device_printf(sc->dev, "Could not alloc mbuf\n");
+ error = ENOMEM;
+ goto out;
+ }
+ if ((error = dwc_setup_rxbuf(sc, idx, m)) != 0) {
+ device_printf(sc->dev,
+ "could not create new RX buffer.\n");
+ goto out;
+ }
+ }
+
+out:
+ if (error != 0)
+ return (ENXIO);
+
+ return (0);
+}
+
+static int
+dwc_get_hwaddr(struct dwc_softc *sc, uint8_t *hwaddr)
+{
+ int rnd;
+ int lo;
+ int hi;
+
+ /*
+ * Try to recover a MAC address from the running hardware. If there's
+ * something non-zero there, assume the bootloader did the right thing
+ * and just use it.
+ *
+ * Otherwise, set the address to a convenient locally assigned address,
+ * 'bsd' + random 24 low-order bits. 'b' is 0x62, which has the locally
+ * assigned bit set, and the broadcast/multicast bit clear.
+ */
+ lo = READ4(sc, MAC_ADDRESS_LOW(0));
+ hi = READ4(sc, MAC_ADDRESS_HIGH(0)) & 0xffff;
+ if ((lo != 0xffffffff) || (hi != 0xffff)) {
+ hwaddr[0] = (lo >> 0) & 0xff;
+ hwaddr[1] = (lo >> 8) & 0xff;
+ hwaddr[2] = (lo >> 16) & 0xff;
+ hwaddr[3] = (lo >> 24) & 0xff;
+ hwaddr[4] = (hi >> 0) & 0xff;
+ hwaddr[5] = (hi >> 8) & 0xff;
+ } else {
+ rnd = arc4random() & 0x00ffffff;
+ hwaddr[0] = 'b';
+ hwaddr[1] = 's';
+ hwaddr[2] = 'd';
+ hwaddr[3] = rnd >> 16;
+ hwaddr[4] = rnd >> 8;
+ hwaddr[5] = rnd >> 0;
+ }
+
+ return (0);
+}
+
+static int
+dwc_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "snps,dwmac"))
+ return (ENXIO);
+
+ device_set_desc(dev, "Gigabit Ethernet Controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+dwc_attach(device_t dev)
+{
+ uint8_t macaddr[ETHER_ADDR_LEN];
+ struct dwc_softc *sc;
+ struct ifnet *ifp;
+ int error;
+ int reg;
+ int i;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ sc->mii_clk = MII_CLK_VAL;
+ sc->rx_idx = 0;
+
+ sc->txcount = TX_DESC_COUNT;
+
+ if (bus_alloc_resources(dev, dwc_spec, sc->res)) {
+ device_printf(dev, "could not allocate resources\n");
+ return (ENXIO);
+ }
+
+ /* Memory interface */
+ sc->bst = rman_get_bustag(sc->res[0]);
+ sc->bsh = rman_get_bushandle(sc->res[0]);
+
+ mtx_init(&sc->mtx, device_get_nameunit(sc->dev),
+ MTX_NETWORK_LOCK, MTX_DEF);
+
+ callout_init_mtx(&sc->dwc_callout, &sc->mtx, 0);
+
+ /* Setup interrupt handler. */
+ error = bus_setup_intr(dev, sc->res[1], INTR_TYPE_NET | INTR_MPSAFE,
+ NULL, dwc_intr, sc, &sc->intr_cookie);
+ if (error != 0) {
+ device_printf(dev, "could not setup interrupt handler.\n");
+ return (ENXIO);
+ }
+
+ /* Read MAC before reset */
+ if (dwc_get_hwaddr(sc, macaddr)) {
+ device_printf(sc->dev, "can't get mac\n");
+ return (ENXIO);
+ }
+
+ /* Reset */
+ reg = READ4(sc, BUS_MODE);
+ reg |= (BUS_MODE_SWR);
+ WRITE4(sc, BUS_MODE, reg);
+
+ for (i = 0; i < 100; i++) {
+ if ((READ4(sc, BUS_MODE) & BUS_MODE_SWR) == 0)
+ break;
+ DELAY(10);
+ }
+ if (i == 0) {
+ device_printf(sc->dev, "Can't reset DWC.\n");
+ return (ENXIO);
+ }
+
+ reg = READ4(sc, BUS_MODE);
+ reg |= (BUS_MODE_EIGHTXPBL);
+ reg |= (BUS_MODE_PBL_BEATS_8 << BUS_MODE_PBL_SHIFT);
+ WRITE4(sc, BUS_MODE, reg);
+
+ /*
+ * DMA must be stop while changing descriptor list addresses.
+ */
+ reg = READ4(sc, OPERATION_MODE);
+ reg &= ~(MODE_ST | MODE_SR);
+ WRITE4(sc, OPERATION_MODE, reg);
+
+ if (setup_dma(sc))
+ return (ENXIO);
+
+ /* Setup addresses */
+ WRITE4(sc, RX_DESCR_LIST_ADDR, sc->rxdesc_ring_paddr);
+ WRITE4(sc, TX_DESCR_LIST_ADDR, sc->txdesc_ring_paddr);
+
+ /* Set up the ethernet interface. */
+ sc->ifp = ifp = if_alloc(IFT_ETHER);
+
+ ifp->if_softc = sc;
+ if_initname(ifp, device_get_name(dev), device_get_unit(dev));
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_capabilities = IFCAP_VLAN_MTU;
+ ifp->if_capenable = ifp->if_capabilities;
+ ifp->if_start = dwc_txstart;
+ ifp->if_ioctl = dwc_ioctl;
+ ifp->if_init = dwc_init;
+ IFQ_SET_MAXLEN(&ifp->if_snd, TX_DESC_COUNT - 1);
+ ifp->if_snd.ifq_drv_maxlen = TX_DESC_COUNT - 1;
+ IFQ_SET_READY(&ifp->if_snd);
+ ifp->if_hdrlen = sizeof(struct ether_vlan_header);
+
+ /* Attach the mii driver. */
+ error = mii_attach(dev, &sc->miibus, ifp, dwc_media_change,
+ dwc_media_status, BMSR_DEFCAPMASK, MII_PHY_ANY,
+ MII_OFFSET_ANY, 0);
+
+ if (error != 0) {
+ device_printf(dev, "PHY attach failed\n");
+ return (ENXIO);
+ }
+ sc->mii_softc = device_get_softc(sc->miibus);
+
+ /* All ready to run, attach the ethernet interface. */
+ ether_ifattach(ifp, macaddr);
+ sc->is_attached = true;
+
+ return (0);
+}
+
+static int
+dwc_miibus_read_reg(device_t dev, int phy, int reg)
+{
+ struct dwc_softc *sc;
+ uint16_t mii;
+ size_t cnt;
+ int rv = 0;
+
+ sc = device_get_softc(dev);
+
+ mii = ((phy & GMII_ADDRESS_PA_MASK) << GMII_ADDRESS_PA_SHIFT)
+ | ((reg & GMII_ADDRESS_GR_MASK) << GMII_ADDRESS_GR_SHIFT)
+ | (sc->mii_clk << GMII_ADDRESS_CR_SHIFT)
+ | GMII_ADDRESS_GB; /* Busy flag */
+
+ WRITE4(sc, GMII_ADDRESS, mii);
+
+ for (cnt = 0; cnt < 1000; cnt++) {
+ if (!(READ4(sc, GMII_ADDRESS) & GMII_ADDRESS_GB)) {
+ rv = READ4(sc, GMII_DATA);
+ break;
+ }
+ DELAY(10);
+ }
+
+ return rv;
+}
+
+static int
+dwc_miibus_write_reg(device_t dev, int phy, int reg, int val)
+{
+ struct dwc_softc *sc;
+ uint16_t mii;
+ size_t cnt;
+
+ sc = device_get_softc(dev);
+
+ mii = ((phy & GMII_ADDRESS_PA_MASK) << GMII_ADDRESS_PA_SHIFT)
+ | ((reg & GMII_ADDRESS_GR_MASK) << GMII_ADDRESS_GR_SHIFT)
+ | (sc->mii_clk << GMII_ADDRESS_CR_SHIFT)
+ | GMII_ADDRESS_GB | GMII_ADDRESS_GW;
+
+ WRITE4(sc, GMII_DATA, val);
+ WRITE4(sc, GMII_ADDRESS, mii);
+
+ for (cnt = 0; cnt < 1000; cnt++) {
+ if (!(READ4(sc, GMII_ADDRESS) & GMII_ADDRESS_GB)) {
+ break;
+ }
+ DELAY(10);
+ }
+
+ return (0);
+}
+
+static void
+dwc_miibus_statchg(device_t dev)
+{
+ struct dwc_softc *sc;
+ struct mii_data *mii;
+ int reg;
+
+ /*
+ * Called by the MII bus driver when the PHY establishes
+ * link to set the MAC interface registers.
+ */
+
+ sc = device_get_softc(dev);
+
+ DWC_ASSERT_LOCKED(sc);
+
+ mii = sc->mii_softc;
+
+ if (mii->mii_media_status & IFM_ACTIVE)
+ sc->link_is_up = true;
+ else
+ sc->link_is_up = false;
+
+ reg = READ4(sc, MAC_CONFIGURATION);
+ switch (IFM_SUBTYPE(mii->mii_media_active)) {
+ case IFM_1000_T:
+ case IFM_1000_SX:
+ reg &= ~(CONF_FES | CONF_PS);
+ break;
+ case IFM_100_TX:
+ reg |= (CONF_FES | CONF_PS);
+ break;
+ case IFM_10_T:
+ reg &= ~(CONF_FES);
+ reg |= (CONF_PS);
+ break;
+ case IFM_NONE:
+ sc->link_is_up = false;
+ return;
+ default:
+ sc->link_is_up = false;
+ device_printf(dev, "Unsupported media %u\n",
+ IFM_SUBTYPE(mii->mii_media_active));
+ return;
+ }
+ if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0)
+ reg |= (CONF_DM);
+ else
+ reg &= ~(CONF_DM);
+ WRITE4(sc, MAC_CONFIGURATION, reg);
+}
+
+static device_method_t dwc_methods[] = {
+ DEVMETHOD(device_probe, dwc_probe),
+ DEVMETHOD(device_attach, dwc_attach),
+
+ /* MII Interface */
+ DEVMETHOD(miibus_readreg, dwc_miibus_read_reg),
+ DEVMETHOD(miibus_writereg, dwc_miibus_write_reg),
+ DEVMETHOD(miibus_statchg, dwc_miibus_statchg),
+
+ { 0, 0 }
+};
+
+static driver_t dwc_driver = {
+ "dwc",
+ dwc_methods,
+ sizeof(struct dwc_softc),
+};
+
+static devclass_t dwc_devclass;
+
+DRIVER_MODULE(dwc, simplebus, dwc_driver, dwc_devclass, 0, 0);
+DRIVER_MODULE(miibus, dwc, miibus_driver, miibus_devclass, 0, 0);
+
+MODULE_DEPEND(dwc, ether, 1, 1, 1);
+MODULE_DEPEND(dwc, miibus, 1, 1, 1);
diff --git a/sys/dev/dwc/if_dwc.h b/sys/dev/dwc/if_dwc.h
new file mode 100644
index 0000000..918ef00
--- /dev/null
+++ b/sys/dev/dwc/if_dwc.h
@@ -0,0 +1,262 @@
+/*-
+ * Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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$
+ */
+
+/*
+ * Register names were taken almost as is from the documentation.
+ */
+
+#define MAC_CONFIGURATION 0x0
+#define CONF_JD (1 << 22) /* jabber timer disable */
+#define CONF_BE (1 << 21) /* Frame Burst Enable */
+#define CONF_PS (1 << 15) /* GMII/MII */
+#define CONF_FES (1 << 14) /* MII speed select */
+#define CONF_DM (1 << 11) /* Full Duplex Enable */
+#define CONF_ACS (1 << 7)
+#define CONF_TE (1 << 3)
+#define CONF_RE (1 << 2)
+#define MAC_FRAME_FILTER 0x4
+#define FRAME_FILTER_RA (1 << 31) /* Receive All */
+#define FRAME_FILTER_HPF (1 << 10) /* Hash or Perfect Filter */
+#define FRAME_FILTER_PM (1 << 4) /* Pass multicast */
+#define FRAME_FILTER_HMC (1 << 2)
+#define FRAME_FILTER_HUC (1 << 1)
+#define FRAME_FILTER_PR (1 << 0) /* All Incoming Frames */
+#define GMII_ADDRESS 0x10
+#define GMII_ADDRESS_PA_MASK 0x1f /* Phy device */
+#define GMII_ADDRESS_PA_SHIFT 11
+#define GMII_ADDRESS_GR_MASK 0x1f /* Phy register */
+#define GMII_ADDRESS_GR_SHIFT 6
+#define GMII_ADDRESS_CR_MASK 0xf
+#define GMII_ADDRESS_CR_SHIFT 2 /* Clock */
+#define GMII_ADDRESS_GW (1 << 1) /* Write operation */
+#define GMII_ADDRESS_GB (1 << 0) /* Busy */
+#define GMII_DATA 0x14
+#define FLOW_CONTROL 0x18
+#define GMAC_VLAN_TAG 0x1C
+#define VERSION 0x20
+#define DEBUG 0x24
+#define LPI_CONTROL_STATUS 0x30
+#define LPI_TIMERS_CONTROL 0x34
+#define INTERRUPT_STATUS 0x38
+#define INTERRUPT_MASK 0x3C
+#define MAC_ADDRESS_HIGH(n) ((n > 15 ? 0x800 : 0x40) + 0x8 * n)
+#define MAC_ADDRESS_LOW(n) ((n > 15 ? 0x804 : 0x44) + 0x8 * n)
+
+#define SGMII_RGMII_SMII_CTRL_STATUS 0xD8
+#define MMC_CONTROL 0x100
+#define MMC_CONTROL_CNTRST (1 << 0)
+#define MMC_RECEIVE_INTERRUPT 0x104
+#define MMC_TRANSMIT_INTERRUPT 0x108
+#define MMC_RECEIVE_INTERRUPT_MASK 0x10C
+#define MMC_TRANSMIT_INTERRUPT_MASK 0x110
+#define TXOCTETCOUNT_GB 0x114
+#define TXFRAMECOUNT_GB 0x118
+#define TXBROADCASTFRAMES_G 0x11C
+#define TXMULTICASTFRAMES_G 0x120
+#define TX64OCTETS_GB 0x124
+#define TX65TO127OCTETS_GB 0x128
+#define TX128TO255OCTETS_GB 0x12C
+#define TX256TO511OCTETS_GB 0x130
+#define TX512TO1023OCTETS_GB 0x134
+#define TX1024TOMAXOCTETS_GB 0x138
+#define TXUNICASTFRAMES_GB 0x13C
+#define TXMULTICASTFRAMES_GB 0x140
+#define TXBROADCASTFRAMES_GB 0x144
+#define TXUNDERFLOWERROR 0x148
+#define TXSINGLECOL_G 0x14C
+#define TXMULTICOL_G 0x150
+#define TXDEFERRED 0x154
+#define TXLATECOL 0x158
+#define TXEXESSCOL 0x15C
+#define TXCARRIERERR 0x160
+#define TXOCTETCNT 0x164
+#define TXFRAMECOUNT_G 0x168
+#define TXEXCESSDEF 0x16C
+#define TXPAUSEFRAMES 0x170
+#define TXVLANFRAMES_G 0x174
+#define TXOVERSIZE_G 0x178
+#define RXFRAMECOUNT_GB 0x180
+#define RXOCTETCOUNT_GB 0x184
+#define RXOCTETCOUNT_G 0x188
+#define RXBROADCASTFRAMES_G 0x18C
+#define RXMULTICASTFRAMES_G 0x190
+#define RXCRCERROR 0x194
+#define RXALIGNMENTERROR 0x198
+#define RXRUNTERROR 0x19C
+#define RXJABBERERROR 0x1A0
+#define RXUNDERSIZE_G 0x1A4
+#define RXOVERSIZE_G 0x1A8
+#define RX64OCTETS_GB 0x1AC
+#define RX65TO127OCTETS_GB 0x1B0
+#define RX128TO255OCTETS_GB 0x1B4
+#define RX256TO511OCTETS_GB 0x1B8
+#define RX512TO1023OCTETS_GB 0x1BC
+#define RX1024TOMAXOCTETS_GB 0x1C0
+#define RXUNICASTFRAMES_G 0x1C4
+#define RXLENGTHERROR 0x1C8
+#define RXOUTOFRANGETYPE 0x1CC
+#define RXPAUSEFRAMES 0x1D0
+#define RXFIFOOVERFLOW 0x1D4
+#define RXVLANFRAMES_GB 0x1D8
+#define RXWATCHDOGERROR 0x1DC
+#define RXRCVERROR 0x1E0
+#define RXCTRLFRAMES_G 0x1E4
+#define MMC_IPC_RECEIVE_INT_MASK 0x200
+#define MMC_IPC_RECEIVE_INT 0x208
+#define RXIPV4_GD_FRMS 0x210
+#define RXIPV4_HDRERR_FRMS 0x214
+#define RXIPV4_NOPAY_FRMS 0x218
+#define RXIPV4_FRAG_FRMS 0x21C
+#define RXIPV4_UDSBL_FRMS 0x220
+#define RXIPV6_GD_FRMS 0x224
+#define RXIPV6_HDRERR_FRMS 0x228
+#define RXIPV6_NOPAY_FRMS 0x22C
+#define RXUDP_GD_FRMS 0x230
+#define RXUDP_ERR_FRMS 0x234
+#define RXTCP_GD_FRMS 0x238
+#define RXTCP_ERR_FRMS 0x23C
+#define RXICMP_GD_FRMS 0x240
+#define RXICMP_ERR_FRMS 0x244
+#define RXIPV4_GD_OCTETS 0x250
+#define RXIPV4_HDRERR_OCTETS 0x254
+#define RXIPV4_NOPAY_OCTETS 0x258
+#define RXIPV4_FRAG_OCTETS 0x25C
+#define RXIPV4_UDSBL_OCTETS 0x260
+#define RXIPV6_GD_OCTETS 0x264
+#define RXIPV6_HDRERR_OCTETS 0x268
+#define RXIPV6_NOPAY_OCTETS 0x26C
+#define RXUDP_GD_OCTETS 0x270
+#define RXUDP_ERR_OCTETS 0x274
+#define RXTCP_GD_OCTETS 0x278
+#define RXTCPERROCTETS 0x27C
+#define RXICMP_GD_OCTETS 0x280
+#define RXICMP_ERR_OCTETS 0x284
+#define L3_L4_CONTROL0 0x400
+#define LAYER4_ADDRESS0 0x404
+#define LAYER3_ADDR0_REG0 0x410
+#define LAYER3_ADDR1_REG0 0x414
+#define LAYER3_ADDR2_REG0 0x418
+#define LAYER3_ADDR3_REG0 0x41C
+#define L3_L4_CONTROL1 0x430
+#define LAYER4_ADDRESS1 0x434
+#define LAYER3_ADDR0_REG1 0x440
+#define LAYER3_ADDR1_REG1 0x444
+#define LAYER3_ADDR2_REG1 0x448
+#define LAYER3_ADDR3_REG1 0x44C
+#define L3_L4_CONTROL2 0x460
+#define LAYER4_ADDRESS2 0x464
+#define LAYER3_ADDR0_REG2 0x470
+#define LAYER3_ADDR1_REG2 0x474
+#define LAYER3_ADDR2_REG2 0x478
+#define LAYER3_ADDR3_REG2 0x47C
+#define L3_L4_CONTROL3 0x490
+#define LAYER4_ADDRESS3 0x494
+#define LAYER3_ADDR0_REG3 0x4A0
+#define LAYER3_ADDR1_REG3 0x4A4
+#define LAYER3_ADDR2_REG3 0x4A8
+#define LAYER3_ADDR3_REG3 0x4AC
+#define HASH_TABLE_REG(n) 0x500 + (0x4 * n)
+#define VLAN_INCL_REG 0x584
+#define VLAN_HASH_TABLE_REG 0x588
+#define TIMESTAMP_CONTROL 0x700
+#define SUB_SECOND_INCREMENT 0x704
+#define SYSTEM_TIME_SECONDS 0x708
+#define SYSTEM_TIME_NANOSECONDS 0x70C
+#define SYSTEM_TIME_SECONDS_UPDATE 0x710
+#define SYSTEM_TIME_NANOSECONDS_UPDATE 0x714
+#define TIMESTAMP_ADDEND 0x718
+#define TARGET_TIME_SECONDS 0x71C
+#define TARGET_TIME_NANOSECONDS 0x720
+#define SYSTEM_TIME_HIGHER_WORD_SECONDS 0x724
+#define TIMESTAMP_STATUS 0x728
+#define PPS_CONTROL 0x72C
+#define AUXILIARY_TIMESTAMP_NANOSECONDS 0x730
+#define AUXILIARY_TIMESTAMP_SECONDS 0x734
+#define PPS0_INTERVAL 0x760
+#define PPS0_WIDTH 0x764
+
+/* DMA */
+#define BUS_MODE 0x1000
+#define BUS_MODE_EIGHTXPBL (1 << 24) /* Multiplies PBL by 8 */
+#define BUS_MODE_PBL_SHIFT 8 /* Single block transfer size */
+#define BUS_MODE_PBL_BEATS_8 8
+#define BUS_MODE_SWR (1 << 0) /* Reset */
+#define TRANSMIT_POLL_DEMAND 0x1004
+#define RECEIVE_POLL_DEMAND 0x1008
+#define RX_DESCR_LIST_ADDR 0x100C
+#define TX_DESCR_LIST_ADDR 0x1010
+#define DMA_STATUS 0x1014
+#define DMA_STATUS_NIS (1 << 16)
+#define DMA_STATUS_AIS (1 << 15)
+#define DMA_STATUS_FBI (1 << 13)
+#define DMA_STATUS_RI (1 << 6)
+#define DMA_STATUS_TI (1 << 0)
+#define DMA_STATUS_INTR_MASK 0x1ffff
+#define OPERATION_MODE 0x1018
+#define MODE_RSF (1 << 25) /* RX Full Frame */
+#define MODE_TSF (1 << 21) /* TX Full Frame */
+#define MODE_FTF (1 << 20) /* Flush TX FIFO */
+#define MODE_ST (1 << 13) /* Start DMA TX */
+#define MODE_FUF (1 << 6) /* TX frames < 64bytes */
+#define MODE_RTC_LEV32 0x1
+#define MODE_RTC_SHIFT 3
+#define MODE_OSF (1 << 2) /* Process Second frame */
+#define MODE_SR (1 << 1) /* Start DMA RX */
+#define INTERRUPT_ENABLE 0x101C
+#define INT_EN_NIE (1 << 16) /* Normal/Summary */
+#define INT_EN_AIE (1 << 15) /* Abnormal/Summary */
+#define INT_EN_ERE (1 << 14) /* Early receive */
+#define INT_EN_FBE (1 << 13) /* Fatal bus error */
+#define INT_EN_ETE (1 << 10) /* Early transmit */
+#define INT_EN_RWE (1 << 9) /* Receive watchdog */
+#define INT_EN_RSE (1 << 8) /* Receive stopped */
+#define INT_EN_RUE (1 << 7) /* Recv buf unavailable */
+#define INT_EN_RIE (1 << 6) /* Receive interrupt */
+#define INT_EN_UNE (1 << 5) /* Tx underflow */
+#define INT_EN_OVE (1 << 4) /* Receive overflow */
+#define INT_EN_TJE (1 << 3) /* Transmit jabber */
+#define INT_EN_TUE (1 << 2) /* Tx. buf unavailable */
+#define INT_EN_TSE (1 << 1) /* Transmit stopped */
+#define INT_EN_TIE (1 << 0) /* Transmit interrupt */
+#define INT_EN_DEFAULT (INT_EN_TIE|INT_EN_RIE| \
+ INT_EN_NIE|INT_EN_AIE| \
+ INT_EN_FBE|INT_EN_UNE)
+
+#define MISSED_FRAMEBUF_OVERFLOW_CNTR 0x1020
+#define RECEIVE_INT_WATCHDOG_TMR 0x1024
+#define AXI_BUS_MODE 0x1028
+#define AHB_OR_AXI_STATUS 0x102C
+#define CURRENT_HOST_TRANSMIT_DESCR 0x1048
+#define CURRENT_HOST_RECEIVE_DESCR 0x104C
+#define CURRENT_HOST_TRANSMIT_BUF_ADDR 0x1050
+#define CURRENT_HOST_RECEIVE_BUF_ADDR 0x1054
+#define HW_FEATURE 0x1058
diff --git a/sys/dev/et/if_et.c b/sys/dev/et/if_et.c
index cd714b0..97fbdcf 100644
--- a/sys/dev/et/if_et.c
+++ b/sys/dev/et/if_et.c
@@ -104,6 +104,7 @@ static int et_watchdog(struct et_softc *);
static int et_ifmedia_upd_locked(struct ifnet *);
static int et_ifmedia_upd(struct ifnet *);
static void et_ifmedia_sts(struct ifnet *, struct ifmediareq *);
+static uint64_t et_get_counter(struct ifnet *, ift_counter);
static void et_add_sysctls(struct et_softc *);
static int et_sysctl_rx_intr_npkts(SYSCTL_HANDLER_ARGS);
@@ -324,6 +325,7 @@ et_attach(device_t dev)
ifp->if_init = et_init;
ifp->if_ioctl = et_ioctl;
ifp->if_start = et_start;
+ ifp->if_get_counter = et_get_counter;
ifp->if_capabilities = IFCAP_TXCSUM | IFCAP_VLAN_MTU;
ifp->if_capenable = ifp->if_capabilities;
ifp->if_snd.ifq_drv_maxlen = ET_TX_NDESC - 1;
@@ -1413,7 +1415,7 @@ et_start_locked(struct ifnet *ifp)
if (et_encap(sc, &m_head)) {
if (m_head == NULL) {
- ifp->if_oerrors++;
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
break;
}
IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
@@ -1465,7 +1467,7 @@ et_watchdog(struct et_softc *sc)
if_printf(sc->ifp, "watchdog timed out (0x%08x) -- resetting\n",
status);
- sc->ifp->if_oerrors++;
+ if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1);
sc->ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
et_init_locked(sc);
return (EJUSTRETURN);
@@ -2093,12 +2095,12 @@ et_rxeof(struct et_softc *sc)
CSR_WRITE_4(sc, ET_RXSTAT_POS, rxstat_pos);
if (ring_idx >= ET_RX_NRING) {
- ifp->if_ierrors++;
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
if_printf(ifp, "invalid ring index %d\n", ring_idx);
continue;
}
if (buf_idx >= ET_RX_NDESC) {
- ifp->if_ierrors++;
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
if_printf(ifp, "invalid buf index %d\n", buf_idx);
continue;
}
@@ -2110,13 +2112,13 @@ et_rxeof(struct et_softc *sc)
rbd->rbd_discard(rbd, buf_idx);
} else if (rbd->rbd_newbuf(rbd, buf_idx) != 0) {
/* No available mbufs, discard it. */
- ifp->if_iqdrops++;
+ if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
rbd->rbd_discard(rbd, buf_idx);
} else {
buflen -= ETHER_CRC_LEN;
if (buflen < ETHER_HDR_LEN) {
m_freem(m);
- ifp->if_ierrors++;
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
} else {
m->m_pkthdr.len = m->m_len = buflen;
m->m_pkthdr.rcvif = ifp;
@@ -2625,7 +2627,6 @@ back:
static void
et_stats_update(struct et_softc *sc)
{
- struct ifnet *ifp;
struct et_hw_stats *stats;
stats = &sc->sc_stats;
@@ -2675,18 +2676,35 @@ et_stats_update(struct et_softc *sc)
stats->tx_oversize += CSR_READ_4(sc, ET_STAT_TX_OVERSIZE);
stats->tx_undersize += CSR_READ_4(sc, ET_STAT_TX_UNDERSIZE);
stats->tx_fragments += CSR_READ_4(sc, ET_STAT_TX_FRAG);
+}
- /* Update ifnet counters. */
- ifp = sc->ifp;
- ifp->if_opackets = (u_long)stats->tx_frames;
- ifp->if_collisions = stats->tx_total_colls;
- ifp->if_oerrors = stats->tx_drop + stats->tx_jabbers +
- stats->tx_crcerrs + stats->tx_excess_deferred +
- stats->tx_late_colls;
- ifp->if_ipackets = (u_long)stats->rx_frames;
- ifp->if_ierrors = stats->rx_crcerrs + stats->rx_alignerrs +
- stats->rx_lenerrs + stats->rx_codeerrs + stats->rx_cserrs +
- stats->rx_runts + stats->rx_jabbers + stats->rx_drop;
+static uint64_t
+et_get_counter(struct ifnet *ifp, ift_counter cnt)
+{
+ struct et_softc *sc;
+ struct et_hw_stats *stats;
+
+ sc = if_getsoftc(ifp);
+ stats = &sc->sc_stats;
+
+ switch (cnt) {
+ case IFCOUNTER_OPACKETS:
+ return (stats->tx_frames);
+ case IFCOUNTER_COLLISIONS:
+ return (stats->tx_total_colls);
+ case IFCOUNTER_OERRORS:
+ return (stats->tx_drop + stats->tx_jabbers +
+ stats->tx_crcerrs + stats->tx_excess_deferred +
+ stats->tx_late_colls);
+ case IFCOUNTER_IPACKETS:
+ return (stats->rx_frames);
+ case IFCOUNTER_IERRORS:
+ return (stats->rx_crcerrs + stats->rx_alignerrs +
+ stats->rx_lenerrs + stats->rx_codeerrs + stats->rx_cserrs +
+ stats->rx_runts + stats->rx_jabbers + stats->rx_drop);
+ default:
+ return (if_get_counter_default(ifp, cnt));
+ }
}
static int
diff --git a/sys/dev/fdc/fdc.c b/sys/dev/fdc/fdc.c
index 9fe1e7e..5c5ffbe 100644
--- a/sys/dev/fdc/fdc.c
+++ b/sys/dev/fdc/fdc.c
@@ -82,9 +82,13 @@ __FBSDID("$FreeBSD$");
#include <machine/stdarg.h>
#include <isa/isavar.h>
+#ifdef PC98
+#include <pc98/pc98/pc98_machdep.h>
+#else
#include <isa/isareg.h>
-#include <dev/fdc/fdcvar.h>
#include <isa/rtc.h>
+#endif
+#include <dev/fdc/fdcvar.h>
#include <dev/ic/nec765.h>
@@ -136,33 +140,56 @@ __FBSDID("$FreeBSD$");
*/
static struct fd_type fd_searchlist_360k[] = {
+#ifndef PC98
{ FDF_5_360 },
+#endif
{ 0 }
};
static struct fd_type fd_searchlist_12m[] = {
+#ifdef PC98
+ { FDF_5_1200 | FL_AUTO },
+ { FDF_5_720 | FL_AUTO },
+ { FDF_5_360 | FL_AUTO },
+ { FDF_5_640 | FL_AUTO },
+ { FDF_5_1230 | FL_AUTO },
+#else
{ FDF_5_1200 | FL_AUTO },
{ FDF_5_360 | FL_2STEP | FL_AUTO},
+#endif
{ 0 }
};
static struct fd_type fd_searchlist_720k[] = {
+#ifndef PC98
{ FDF_3_720 },
+#endif
{ 0 }
};
static struct fd_type fd_searchlist_144m[] = {
+#ifdef PC98
{ FDF_3_1440 | FL_AUTO},
+ { FDF_3_1200 | FL_AUTO},
{ FDF_3_720 | FL_AUTO},
+ { FDF_3_360 | FL_AUTO},
+ { FDF_3_640 | FL_AUTO},
+ { FDF_3_1230 | FL_AUTO},
+#else
+ { FDF_3_1440 | FL_AUTO},
+ { FDF_3_720 | FL_AUTO},
+#endif
{ 0 }
};
static struct fd_type fd_searchlist_288m[] = {
+#ifndef PC98
{ FDF_3_1440 | FL_AUTO },
#if 0
{ FDF_3_2880 | FL_AUTO }, /* XXX: probably doesn't work */
#endif
{ FDF_3_720 | FL_AUTO},
+#endif
{ 0 }
};
@@ -183,6 +210,26 @@ static struct fd_type *fd_native_types[] = {
* Internals start here
*/
+#ifdef PC98
+/* registers */
+#define FDSTS 0 /* NEC 765 Main Status Register (R) */
+#define FDDATA 1 /* NEC 765 Data Register (R/W) */
+#define FDCTL 2 /* FD Control Register */
+#define FDC_RST 0x80 /* FDC RESET */
+#define FDC_RDY 0x40 /* force READY */
+#define FDC_DD 0x20 /* FDD Mode Exchange 0:1M 1:640K */
+#define FDC_DMAE 0x10 /* enable floppy DMA */
+#define FDC_MTON 0x08 /* MOTOR ON (when EMTON=1)*/
+#define FDC_TMSK 0x04 /* TIMER MASK */
+#define FDC_TTRG 0x01 /* TIMER TRIGER */
+
+#define FDP 3
+#define FDP_EMTON 0x04 /* enable MTON */
+#define FDP_FDDEXC 0x02 /* FDD Mode Exchange 1:1M 0:640K */
+#define FDP_PORTEXC 0x01 /* PORT Exchane 1:1M 0:640K */
+
+#define FDEM 4
+#else
/* registers */
#define FDOUT 2 /* Digital Output Register (W) */
#define FDO_FDSEL 0x03 /* floppy device select */
@@ -197,6 +244,7 @@ static struct fd_type *fd_native_types[] = {
#define FDDSR 4 /* Data Rate Select Register (W) */
#define FDDATA 5 /* NEC 765 Data Register (R/W) */
#define FDCTL 7 /* Control Register (W) */
+#endif /* PC98 */
/*
* The YE-DATA PC Card floppies use PIO to read in the data rather
@@ -219,9 +267,11 @@ static struct fd_type *fd_native_types[] = {
#define FDBCDR 0 /* And 1 */
#define FD_YE_DATAPORT 6 /* Drive Data port */
+#ifndef PC98
#define FDI_DCHG 0x80 /* diskette has been changed */
/* requires drive and motor being selected */
/* is cleared by any step pulse to drive */
+#endif
/*
* We have three private BIO commands.
@@ -258,6 +308,9 @@ struct fd_data {
struct g_provider *fd_provider;
device_t dev;
struct bio_queue_head fd_bq;
+#ifdef PC98
+ int pc98_trans;
+#endif
};
#define FD_NOT_VALID -2
@@ -281,11 +334,19 @@ static int retries = 10;
SYSCTL_INT(_debug_fdc, OID_AUTO, retries, CTLFLAG_RW, &retries, 0,
"Number of retries to attempt");
-static int spec1 = 0xaf;
+#ifdef PC98
+static int spec1 = NE7_SPEC_1(4, 240);
+#else
+static int spec1 = NE7_SPEC_1(6, 240);
+#endif
SYSCTL_INT(_debug_fdc, OID_AUTO, spec1, CTLFLAG_RW, &spec1, 0,
"Specification byte one (step-rate + head unload)");
-static int spec2 = 0x10;
+#ifdef PC98
+static int spec2 = NE7_SPEC_2(2, 0);
+#else
+static int spec2 = NE7_SPEC_2(16, 0);
+#endif
SYSCTL_INT(_debug_fdc, OID_AUTO, spec2, CTLFLAG_RW, &spec2, 0,
"Specification byte two (head load time + no-dma)");
@@ -335,12 +396,14 @@ fdctl_wr(struct fdc_data *fdc, u_int8_t v)
fdregwr(fdc, FDCTL, v);
}
+#ifndef PC98
static void
fdout_wr(struct fdc_data *fdc, u_int8_t v)
{
fdregwr(fdc, FDOUT, v);
}
+#endif
static u_int8_t
fdsts_rd(struct fdc_data *fdc)
@@ -349,12 +412,14 @@ fdsts_rd(struct fdc_data *fdc)
return fdregrd(fdc, FDSTS);
}
+#ifndef PC98
static void
fddsr_wr(struct fdc_data *fdc, u_int8_t v)
{
fdregwr(fdc, FDDSR, v);
}
+#endif
static void
fddata_wr(struct fdc_data *fdc, u_int8_t v)
@@ -370,12 +435,14 @@ fddata_rd(struct fdc_data *fdc)
return fdregrd(fdc, FDDATA);
}
+#ifndef PC98
static u_int8_t
fdin_rd(struct fdc_data *fdc)
{
return fdregrd(fdc, FDCTL);
}
+#endif
/*
* Magic pseudo-DMA initialization for YE FDC. Sets count and
@@ -502,11 +569,90 @@ fdc_cmd(struct fdc_data *fdc, int n_out, ...)
return (0);
}
+#ifdef PC98
+static void fd_motor(struct fd_data *fd, int turnon);
+
+static int pc98_trans = 0; /* 0 : HD , 1 : DD , 2 : 1.44 */
+static int pc98_trans_prev = -1;
+
+static void
+set_density(struct fdc_data *fdc)
+{
+ /* always motor on */
+ fdregwr(fdc, FDP, (pc98_trans != 1 ? FDP_FDDEXC : 0) | FDP_PORTEXC);
+ DELAY(100);
+ fdctl_wr(fdc, FDC_RST | FDC_DMAE);
+ /* in the case of note W, always inhibit 100ms timer */
+}
+
+static int
+pc98_fd_check_ready(struct fd_data *fd)
+{
+ struct fdc_data *fdc = fd->fdc;
+ int retry = 0, status;
+ int fdu = device_get_unit(fd->dev);
+
+ while (retry++ < 30000) {
+ fd_motor(fd, 1);
+ fdc_out(fdc, NE7CMD_SENSED); /* Sense Drive Status */
+ DELAY(100);
+ fdc_out(fdc, fdu); /* Drive number */
+ DELAY(100);
+ if ((fdc_in(fdc, &status) == 0) && (status & NE7_ST3_RD)) {
+ fdctl_wr(fdc, FDC_DMAE | FDC_MTON);
+ DELAY(10);
+ return (0);
+ }
+ }
+ return (-1);
+}
+
+static void
+pc98_fd_check_type(struct fd_data *fd, int unit)
+{
+ struct fdc_data *fdc;
+
+ if (fd->type != FDT_NONE || unit < 0 || unit > 3)
+ return;
+
+ fdc = fd->fdc;
+
+ /* Look up what the BIOS thinks we have. */
+ if (!((PC98_SYSTEM_PARAMETER(0x55c) >> unit) & 0x01)) {
+ fd->type = FDT_NONE;
+ return;
+ }
+ if ((PC98_SYSTEM_PARAMETER(0x5ae) >> unit) & 0x01) {
+ /* Check 3mode I/F */
+ fd->pc98_trans = 0;
+ fdregwr(fdc, FDEM, (unit << 5) | 0x10);
+ if (!(fdregrd(fdc, FDEM) & 0x01)) {
+ fd->type = FDT_144M;
+ return;
+ }
+ device_printf(fd->dev,
+ "Warning: can't control 3mode I/F, fallback to 2mode.\n");
+ }
+
+ fd->type = FDT_12M;
+}
+#endif /* PC98 */
+
static void
fdc_reset(struct fdc_data *fdc)
{
int i, r[10];
+#ifdef PC98
+ set_density(fdc);
+ if (pc98_machine_type & M_EPSON_PC98)
+ fdctl_wr(fdc, FDC_RST | FDC_RDY | FDC_DD | FDC_MTON);
+ else
+ fdctl_wr(fdc, FDC_RST | FDC_RDY | FDC_DMAE | FDC_MTON);
+ DELAY(200);
+ fdctl_wr(fdc, FDC_DMAE | FDC_MTON);
+ DELAY(10);
+#else
if (fdc->fdct == FDC_ENHANCED) {
/* Try a software reset, default precomp, and 500 kb/s */
fddsr_wr(fdc, I8207X_DSR_SR);
@@ -519,6 +665,7 @@ fdc_reset(struct fdc_data *fdc)
}
DELAY(100);
fdout_wr(fdc, fdc->fdout);
+#endif
/* XXX after a reset, silently believe the FDC will accept commands */
if (fdc_cmd(fdc, 3, NE7CMD_SPECIFY, spec1, spec2, 0))
@@ -612,6 +759,7 @@ fdc_read_status(struct fdc_data *fdc)
return ret;
}
+#ifndef PC98
/*
* Select this drive
*/
@@ -649,6 +797,7 @@ fd_turnon(void *arg)
if (once)
wakeup(&fd->fdc->head);
}
+#endif
static void
fd_motor(struct fd_data *fd, int turnon)
@@ -659,6 +808,11 @@ fd_motor(struct fd_data *fd, int turnon)
/*
mtx_assert(&fdc->fdc_mtx, MA_OWNED);
*/
+#ifdef PC98
+ fdregwr(fdc, FDP, (pc98_trans != 1 ? FDP_FDDEXC : 0) | FDP_PORTEXC);
+ DELAY(10);
+ fdctl_wr(fdc, FDC_DMAE | FDC_MTON);
+#else
if (turnon) {
fd->flags |= FD_MOTORWAIT;
fdc->fdout |= (FDO_MOEN0 << fd->fdsu);
@@ -669,6 +823,7 @@ fd_motor(struct fd_data *fd, int turnon)
fdc->fdout &= ~(FDO_MOEN0 << fd->fdsu);
}
fdout_wr(fdc, fdc->fdout);
+#endif
}
static void
@@ -836,15 +991,41 @@ fdc_worker(struct fdc_data *fdc)
}
/* Select drive, setup params */
+#ifdef PC98
+ pc98_trans = fd->ft->trans;
+ if (pc98_trans_prev != pc98_trans) {
+ int i;
+
+ set_density(fdc);
+ for (i = 0; i < 10; i++) {
+ outb(0x5f, 0);
+ outb(0x5f, 0);
+ }
+ pc98_trans_prev = pc98_trans;
+ }
+ if (pc98_trans != fd->pc98_trans) {
+ if (fd->type == FDT_144M) {
+ fdregwr(fdc, FDEM,
+ (device_get_unit(fd->dev) << 5) | 0x10 |
+ (pc98_trans >> 1));
+ outb(0x5f, 0);
+ outb(0x5f, 0);
+ }
+ fd->pc98_trans = pc98_trans;
+ }
+#else
fd_select(fd);
if (fdc->fdct == FDC_ENHANCED)
fddsr_wr(fdc, fd->ft->trans);
else
fdctl_wr(fdc, fd->ft->trans);
+#endif
if (bp->bio_cmd & BIO_PROBE) {
if ((!(device_get_flags(fd->dev) & FD_NO_CHLINE) &&
+#ifndef PC98
!(fdin_rd(fdc) & FDI_DCHG) &&
+#endif
!(fd->flags & FD_EMPTY)) ||
fd_probe_disk(fd, &need_recal) == 0)
return (fdc_biodone(fdc, 0));
@@ -857,6 +1038,7 @@ fdc_worker(struct fdc_data *fdc)
if (fd->flags & FD_EMPTY)
return (fdc_biodone(fdc, ENXIO));
+#ifndef PC98
/* Check if we lost our media */
if (fdin_rd(fdc) & FDI_DCHG) {
if (debugflags & 0x40)
@@ -874,9 +1056,10 @@ fdc_worker(struct fdc_data *fdc)
g_topology_unlock();
return (fdc_biodone(fdc, ENXIO));
}
+#endif
/* Check if the floppy is write-protected */
- if(bp->bio_cmd & (BIO_FMT | BIO_WRITE)) {
+ if (bp->bio_cmd & (BIO_FMT | BIO_WRITE)) {
retry_line = __LINE__;
if(fdc_sense_drive(fdc, &st3) != 0)
return (1);
@@ -907,6 +1090,9 @@ fdc_worker(struct fdc_data *fdc)
if ((need_recal & (1 << fd->fdsu)) ||
(cylinder == 0 && fd->track != 0) ||
fdc->retry > 2) {
+#ifdef PC98
+ pc98_fd_check_ready(fd);
+#endif
retry_line = __LINE__;
if (fdc_cmd(fdc, 2, NE7CMD_RECAL, fd->fdsu, 0))
return (1);
@@ -928,6 +1114,9 @@ fdc_worker(struct fdc_data *fdc)
* SEEK to where we want to be
*/
if (cylinder != fd->track) {
+#ifdef PC98
+ pc98_fd_check_ready(fd);
+#endif
retry_line = __LINE__;
if (fdc_cmd(fdc, 3, NE7CMD_SEEK, fd->fdsu, descyl, 0))
return (1);
@@ -1230,6 +1419,7 @@ fd_probe_disk(struct fd_data *fd, int *recal)
if (fdc_sense_int(fdc, &st0, &cyl) == FD_NOT_VALID)
goto done; /* XXX */
*recal |= (1 << fd->fdsu);
+#ifndef PC98
if (fdin_rd(fdc) & FDI_DCHG) {
if (debugflags & 0x40)
printf("Empty in probe\n");
@@ -1237,6 +1427,9 @@ fd_probe_disk(struct fd_data *fd, int *recal)
fd->flags |= FD_EMPTY;
mtx_unlock(&fdc->fdc_mtx);
} else {
+#else
+ {
+#endif
if (fdc_sense_drive(fdc, &st3) != 0)
goto done;
if (debugflags & 0x40)
@@ -1372,7 +1565,12 @@ fdautoselect(struct fd_data *fd)
} else {
if (debugflags & 0x40) {
device_printf(fd->dev,
- "autoselected %d KB medium\n", fd->ft->size / 2);
+ "autoselected %d KB medium\n",
+#ifdef PC98
+ (128 << (fd->ft->secsize)) * fd->ft->size / 1024);
+#else
+ fd->ft->size / 2);
+#endif
fdprinttype(fd->ft);
}
return (0);
@@ -1425,6 +1623,10 @@ fd_access(struct g_provider *pp, int r, int w, int e)
busy = 0;
if (pp->acr == 0 && pp->acw == 0 && pp->ace == 0) {
+#ifdef PC98
+ if (pc98_fd_check_ready(fd) == -1)
+ return (ENXIO);
+#endif
if (fdmisccmd(fd, BIO_PROBE, NULL))
return (ENXIO);
if (fd->flags & FD_EMPTY)
@@ -1494,6 +1696,10 @@ fd_ioctl(struct g_provider *pp, u_long cmd, void *data, int fflag, struct thread
fd = pp->geom->softc;
+#ifdef PC98
+ pc98_fd_check_ready(fd);
+#endif
+
switch (cmd) {
case FD_GTYPE: /* get drive type */
*(struct fd_type *)data = *fd->ft;
@@ -1661,6 +1867,12 @@ fdc_initial_reset(device_t dev, struct fdc_data *fdc)
{
int ic_type, part_id;
+#ifdef PC98
+ /* See if it can handle a command. */
+ if (fdc_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(4, 240),
+ NE7_SPEC_2(2, 0), 0))
+ return (ENXIO);
+#else
/*
* A status value of 0xff is very unlikely, but not theoretically
* impossible, but it is far more likely to indicate an empty bus.
@@ -1686,8 +1898,10 @@ fdc_initial_reset(device_t dev, struct fdc_data *fdc)
return (ENXIO);
/* Then, see if it can handle a command. */
- if (fdc_cmd(fdc, 3, NE7CMD_SPECIFY, 0xaf, 0x1e, 0))
+ if (fdc_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(6, 240),
+ NE7_SPEC_2(31, 0), 0))
return (ENXIO);
+#endif
/*
* Try to identify the chip.
@@ -1749,7 +1963,11 @@ fdc_detach(device_t dev)
mtx_unlock(&fdc->fdc_mtx);
/* reset controller, turn motor off */
+#ifdef PC98
+ fdc_reset(fdc);
+#else
fdout_wr(fdc, 0);
+#endif
if (!(fdc->flags & FDC_NODMA))
isa_dma_release(fdc->dmachan);
@@ -1823,7 +2041,11 @@ fdc_attach(device_t dev)
mtx_init(&fdc->fdc_mtx, "fdc lock", NULL, MTX_DEF);
/* reset controller, turn motor off, clear fdout mirror reg */
+#ifdef PC98
+ fdc_reset(fdc);
+#else
fdout_wr(fdc, fdc->fdout = 0);
+#endif
bioq_init(&fdc->head);
kproc_create(fdc_thread, fdc, &fdc->fdc_thread, 0, 0,
@@ -1877,8 +2099,11 @@ fdc_print_child(device_t me, device_t child)
static int
fd_probe(device_t dev)
{
- int i, unit;
+ int unit;
+#ifndef PC98
+ int i;
u_int st0, st3;
+#endif
struct fd_data *fd;
struct fdc_data *fdc;
int fdsu;
@@ -1905,7 +2130,9 @@ fd_probe(device_t dev)
fd->type = type;
}
-#if (defined(__i386__) && !defined(PC98)) || defined(__amd64__)
+#ifdef PC98
+ pc98_fd_check_type(fd, unit);
+#elif defined(__i386__) || defined(__amd64__)
if (fd->type == FDT_NONE && (unit == 0 || unit == 1)) {
/* Look up what the BIOS thinks we have. */
if (unit == 0)
@@ -1920,6 +2147,7 @@ fd_probe(device_t dev)
if (fd->type == FDT_NONE)
return (ENXIO);
+#ifndef PC98
/*
mtx_lock(&fdc->fdc_mtx);
*/
@@ -1972,10 +2200,19 @@ fd_probe(device_t dev)
if ((flags & FD_NO_PROBE) == 0 &&
(st0 & NE7_ST0_EC) != 0) /* no track 0 -> no drive present */
return (ENXIO);
+#endif /* PC98 */
done:
switch (fd->type) {
+#ifdef PC98
+ case FDT_144M:
+ device_set_desc(dev, "1.44M FDD");
+ break;
+ case FDT_12M:
+ device_set_desc(dev, "1M/640K FDD");
+ break;
+#else
case FDT_12M:
device_set_desc(dev, "1200-KB 5.25\" drive");
break;
@@ -1991,6 +2228,7 @@ done:
case FDT_720K:
device_set_desc(dev, "720-KB 3.5\" drive");
break;
+#endif
default:
return (ENXIO);
}
@@ -1998,6 +2236,9 @@ done:
fd->fdc = fdc;
fd->fdsu = fdsu;
fd->options = 0;
+#ifdef PC98
+ fd->pc98_trans = 0;
+#endif
callout_init_mtx(&fd->toffhandle, &fd->fdc->fdc_mtx, 0);
/* initialize densities for subdevices */
diff --git a/sys/pc98/cbus/fdc_cbus.c b/sys/dev/fdc/fdc_cbus.c
index 098ee5d..ee1598d 100644
--- a/sys/pc98/cbus/fdc_cbus.c
+++ b/sys/dev/fdc/fdc_cbus.c
@@ -33,15 +33,16 @@ __FBSDID("$FreeBSD$");
#include <sys/bio.h>
#include <sys/bus.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
#include <sys/module.h>
+#include <sys/mutex.h>
#include <sys/rman.h>
#include <sys/systm.h>
#include <machine/bus.h>
#include <pc98/cbus/cbus.h>
-#include <pc98/cbus/fdcreg.h>
-#include <pc98/cbus/fdcvar.h>
+#include <dev/fdc/fdcvar.h>
#include <isa/isavar.h>
@@ -50,62 +51,70 @@ static bus_addr_t fdc_iat[] = {0, 2, 4};
static int
fdc_cbus_alloc_resources(device_t dev, struct fdc_data *fdc)
{
- int rid;
+ struct resource *res;
+ int i, rid;
fdc->fdc_dev = dev;
- fdc->rid_ioport = 0;
- fdc->rid_irq = 0;
- fdc->rid_drq = 0;
- fdc->res_irq = 0;
- fdc->res_drq = 0;
-
- fdc->res_ioport = isa_alloc_resourcev(dev, SYS_RES_IOPORT,
- &fdc->rid_ioport, fdc_iat,
- 3, RF_ACTIVE);
- if (fdc->res_ioport == 0) {
+ rid = 0;
+ res = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, fdc_iat, 3,
+ RF_ACTIVE);
+ if (res == NULL) {
device_printf(dev, "cannot reserve I/O port range\n");
- return ENXIO;
+ return (ENXIO);
}
- isa_load_resourcev(fdc->res_ioport, fdc_iat, 3);
- fdc->portt = rman_get_bustag(fdc->res_ioport);
- fdc->porth = rman_get_bushandle(fdc->res_ioport);
-
+ isa_load_resourcev(res, fdc_iat, 3);
+ for (i = 0; i < 3; i++) {
+ fdc->resio[i] = res;
+ fdc->ridio[i] = rid;
+ fdc->ioff[i] = i;
+ fdc->ioh[i] = rman_get_bushandle(res);
+ }
+ fdc->iot = rman_get_bustag(res);
+
rid = 3;
bus_set_resource(dev, SYS_RES_IOPORT, rid, IO_FDPORT, 1);
- fdc->res_fdsio = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
- RF_ACTIVE);
- if (fdc->res_fdsio == 0)
- return ENXIO;
- fdc->sc_fdsiot = rman_get_bustag(fdc->res_fdsio);
- fdc->sc_fdsioh = rman_get_bushandle(fdc->res_fdsio);
+ res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
+ if (res == NULL) {
+ device_printf(dev, "cannot reserve I/O port range\n");
+ return (ENXIO);
+ }
+ fdc->resio[3] = res;
+ fdc->ridio[3] = rid;
+ fdc->ioff[3] = 0;
+ fdc->ioh[3] = rman_get_bushandle(res);
+ /* XXX: Reuses fdc->iot */
rid = 4;
bus_set_resource(dev, SYS_RES_IOPORT, rid, 0x4be, 1);
- fdc->res_fdemsio = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
- RF_ACTIVE);
- if (fdc->res_fdemsio == 0)
- return ENXIO;
- fdc->sc_fdemsiot = rman_get_bustag(fdc->res_fdemsio);
- fdc->sc_fdemsioh = rman_get_bushandle(fdc->res_fdemsio);
+ res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
+ if (res == NULL) {
+ device_printf(dev, "cannot reserve I/O port range\n");
+ return (ENXIO);
+ }
+ fdc->resio[4] = res;
+ fdc->ridio[4] = rid;
+ fdc->ioff[4] = 0;
+ fdc->ioh[4] = rman_get_bushandle(res);
+ /* XXX: Reuses fdc->iot */
fdc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &fdc->rid_irq,
- RF_ACTIVE);
- if (fdc->res_irq == 0) {
+ RF_ACTIVE);
+ if (fdc->res_irq == NULL) {
device_printf(dev, "cannot reserve interrupt line\n");
- return ENXIO;
+ return (ENXIO);
}
if ((fdc->flags & FDC_NODMA) == 0) {
fdc->res_drq = bus_alloc_resource_any(dev, SYS_RES_DRQ,
- &fdc->rid_drq, RF_ACTIVE);
- if (fdc->res_drq == 0) {
+ &fdc->rid_drq, RF_ACTIVE);
+ if (fdc->res_drq == NULL) {
device_printf(dev, "cannot reserve DMA request line\n");
- return ENXIO;
+ return (ENXIO);
}
fdc->dmachan = rman_get_start(fdc->res_drq);
}
- return 0;
+ return (0);
}
static int
@@ -122,8 +131,8 @@ fdc_cbus_probe(device_t dev)
/* Attempt to allocate our resources for the duration of the probe */
error = fdc_cbus_alloc_resources(dev, fdc);
- if (!error)
- error = fdc_initial_reset(fdc);
+ if (error == 0)
+ error = fdc_initial_reset(dev, fdc);
fdc_release_resources(fdc);
return (error);
@@ -136,15 +145,14 @@ fdc_cbus_attach(device_t dev)
int error;
fdc = device_get_softc(dev);
-
- if ((error = fdc_cbus_alloc_resources(dev, fdc)) != 0 ||
- (error = fdc_attach(dev)) != 0 ||
- (error = fdc_hints_probe(dev)) != 0) {
+ error = fdc_cbus_alloc_resources(dev, fdc);
+ if (error == 0)
+ error = fdc_attach(dev);
+ if (error == 0)
+ error = fdc_hints_probe(dev);
+ if (error)
fdc_release_resources(fdc);
- return (error);
- }
-
- return (0);
+ return (error);
}
static device_method_t fdc_methods[] = {
diff --git a/sys/dev/fdc/fdcvar.h b/sys/dev/fdc/fdcvar.h
index 5ab60a6..b09bfa1 100644
--- a/sys/dev/fdc/fdcvar.h
+++ b/sys/dev/fdc/fdcvar.h
@@ -49,7 +49,9 @@ struct fdc_data {
#define FDC_KTHREAD_ALIVE 0x2000 /* worker thread is alive */
struct fd_data *fd; /* The active drive */
int retry;
+#ifndef PC98
int fdout; /* mirror of the w/o digital output reg */
+#endif
u_int status[7]; /* copy of the registers */
enum fdc_type fdct; /* chip version of FDC */
int fdc_errs; /* number of logged errors */
diff --git a/sys/dev/fdt/fdt_common.c b/sys/dev/fdt/fdt_common.c
index 77cf8ba..9d0c0f0 100644
--- a/sys/dev/fdt/fdt_common.c
+++ b/sys/dev/fdt/fdt_common.c
@@ -494,46 +494,6 @@ out:
}
int
-fdt_intr_to_rl(device_t dev, phandle_t node, struct resource_list *rl,
- struct fdt_sense_level *intr_sl)
-{
- phandle_t iparent;
- uint32_t *intr, icells;
- int nintr, i, k;
-
- nintr = OF_getencprop_alloc(node, "interrupts", sizeof(*intr),
- (void **)&intr);
- if (nintr > 0) {
- if (OF_searchencprop(node, "interrupt-parent", &iparent,
- sizeof(iparent)) == -1) {
- device_printf(dev, "No interrupt-parent found, "
- "assuming direct parent\n");
- iparent = OF_parent(node);
- }
- if (OF_searchencprop(OF_node_from_xref(iparent),
- "#interrupt-cells", &icells, sizeof(icells)) == -1) {
- device_printf(dev, "Missing #interrupt-cells property, "
- "assuming <1>\n");
- icells = 1;
- }
- if (icells < 1 || icells > nintr) {
- device_printf(dev, "Invalid #interrupt-cells property "
- "value <%d>, assuming <1>\n", icells);
- icells = 1;
- }
- for (i = 0, k = 0; i < nintr; i += icells, k++) {
- intr[i] = ofw_bus_map_intr(dev, iparent, icells,
- &intr[i]);
- resource_list_add(rl, SYS_RES_IRQ, k, intr[i], intr[i],
- 1);
- }
- free(intr, M_OFWPROP);
- }
-
- return (0);
-}
-
-int
fdt_get_phyaddr(phandle_t node, device_t dev, int *phy_addr, void **phy_sc)
{
phandle_t phy_node;
diff --git a/sys/dev/fdt/fdt_common.h b/sys/dev/fdt/fdt_common.h
index d306f65..0a79ce0 100644
--- a/sys/dev/fdt/fdt_common.h
+++ b/sys/dev/fdt/fdt_common.h
@@ -88,7 +88,6 @@ int fdt_get_phyaddr(phandle_t, device_t, int *, void **);
int fdt_get_range(phandle_t, int, u_long *, u_long *);
int fdt_immr_addr(vm_offset_t);
int fdt_regsize(phandle_t, u_long *, u_long *);
-int fdt_intr_to_rl(device_t, phandle_t, struct resource_list *, struct fdt_sense_level *);
int fdt_is_compatible(phandle_t, const char *);
int fdt_is_compatible_strict(phandle_t, const char *);
int fdt_is_enabled(phandle_t);
diff --git a/sys/dev/fdt/simplebus.c b/sys/dev/fdt/simplebus.c
index e21b913..4159783 100644
--- a/sys/dev/fdt/simplebus.c
+++ b/sys/dev/fdt/simplebus.c
@@ -247,11 +247,9 @@ simplebus_setup_dinfo(device_t dev, phandle_t node)
{
struct simplebus_softc *sc;
struct simplebus_devinfo *ndi;
- uint32_t *reg, *intr, icells;
+ uint32_t *reg;
uint64_t phys, size;
- phandle_t iparent;
int i, j, k;
- int nintr;
int nreg;
sc = device_get_softc(dev);
@@ -289,34 +287,7 @@ simplebus_setup_dinfo(device_t dev, phandle_t node)
}
free(reg, M_OFWPROP);
- nintr = OF_getencprop_alloc(node, "interrupts", sizeof(*intr),
- (void **)&intr);
- if (nintr > 0) {
- if (OF_searchencprop(node, "interrupt-parent", &iparent,
- sizeof(iparent)) == -1) {
- device_printf(dev, "No interrupt-parent found, "
- "assuming direct parent\n");
- iparent = OF_parent(node);
- }
- if (OF_searchencprop(OF_node_from_xref(iparent),
- "#interrupt-cells", &icells, sizeof(icells)) == -1) {
- device_printf(dev, "Missing #interrupt-cells property, "
- "assuming <1>\n");
- icells = 1;
- }
- if (icells < 1 || icells > nintr) {
- device_printf(dev, "Invalid #interrupt-cells property "
- "value <%d>, assuming <1>\n", icells);
- icells = 1;
- }
- for (i = 0, k = 0; i < nintr; i += icells, k++) {
- intr[i] = ofw_bus_map_intr(dev, iparent, icells,
- &intr[i]);
- resource_list_add(&ndi->rl, SYS_RES_IRQ, k, intr[i],
- intr[i], 1);
- }
- free(intr, M_OFWPROP);
- }
+ ofw_bus_intr_to_rl(dev, node, &ndi->rl);
return (ndi);
}
diff --git a/sys/pci/intpm.c b/sys/dev/intpm/intpm.c
index 48ff26e..60ad17f 100644
--- a/sys/pci/intpm.c
+++ b/sys/dev/intpm/intpm.c
@@ -42,7 +42,7 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
-#include <pci/intpmreg.h>
+#include <dev/intpm/intpmreg.h>
#include "opt_intpm.h"
diff --git a/sys/pci/intpmreg.h b/sys/dev/intpm/intpmreg.h
index eaebcdd..eaebcdd 100644
--- a/sys/pci/intpmreg.h
+++ b/sys/dev/intpm/intpmreg.h
diff --git a/sys/dev/ixl/i40e_common.c b/sys/dev/ixl/i40e_common.c
index 143eeb7..ad1f945 100755
--- a/sys/dev/ixl/i40e_common.c
+++ b/sys/dev/ixl/i40e_common.c
@@ -4375,8 +4375,8 @@ enum i40e_status_code i40e_aq_alternate_write_indirect(struct i40e_hw *hw,
cmd_resp->address = CPU_TO_LE32(addr);
cmd_resp->length = CPU_TO_LE32(dw_count);
- cmd_resp->addr_high = CPU_TO_LE32(I40E_HI_WORD((u64)(uintptr_t)buffer));
- cmd_resp->addr_low = CPU_TO_LE32(I40E_LO_DWORD((u64)(uintptr_t)buffer));
+ cmd_resp->addr_high = CPU_TO_LE32(I40E_HI_WORD((u64)buffer));
+ cmd_resp->addr_low = CPU_TO_LE32(I40E_LO_DWORD((u64)buffer));
status = i40e_asq_send_command(hw, &desc, buffer,
I40E_LO_DWORD(4*dw_count), NULL);
@@ -4458,8 +4458,8 @@ enum i40e_status_code i40e_aq_alternate_read_indirect(struct i40e_hw *hw,
cmd_resp->address = CPU_TO_LE32(addr);
cmd_resp->length = CPU_TO_LE32(dw_count);
- cmd_resp->addr_high = CPU_TO_LE32(I40E_HI_DWORD((u64)(uintptr_t)buffer));
- cmd_resp->addr_low = CPU_TO_LE32(I40E_LO_DWORD((u64)(uintptr_t)buffer));
+ cmd_resp->addr_high = CPU_TO_LE32(I40E_HI_DWORD((u64)buffer));
+ cmd_resp->addr_low = CPU_TO_LE32(I40E_LO_DWORD((u64)buffer));
status = i40e_asq_send_command(hw, &desc, buffer,
I40E_LO_DWORD(4*dw_count), NULL);
diff --git a/sys/dev/ixl/if_ixl.c b/sys/dev/ixl/if_ixl.c
index d0b01c2..abae7a5 100755
--- a/sys/dev/ixl/if_ixl.c
+++ b/sys/dev/ixl/if_ixl.c
@@ -921,8 +921,10 @@ ixl_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
ifp->if_flags |= IFF_UP;
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
ixl_init(pf);
+#ifdef INET
if (!(ifp->if_flags & IFF_NOARP))
arp_ifinit(ifp, ifa);
+#endif
} else
error = ether_ioctl(ifp, command, data);
break;
diff --git a/sys/dev/ixl/if_ixlv.c b/sys/dev/ixl/if_ixlv.c
index 97dfadb..a29d669 100644
--- a/sys/dev/ixl/if_ixlv.c
+++ b/sys/dev/ixl/if_ixlv.c
@@ -755,8 +755,10 @@ ixlv_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
ifp->if_flags |= IFF_UP;
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
ixlv_init(sc);
+#ifdef INET
if (!(ifp->if_flags & IFF_NOARP))
arp_ifinit(ifp, ifa);
+#endif
} else
error = ether_ioctl(ifp, command, data);
break;
diff --git a/sys/dev/ixl/ixl_txrx.c b/sys/dev/ixl/ixl_txrx.c
index 12e09f7..306d4ec 100755
--- a/sys/dev/ixl/ixl_txrx.c
+++ b/sys/dev/ixl/ixl_txrx.c
@@ -1085,10 +1085,12 @@ ixl_allocate_rx_data(struct ixl_queue *que)
int
ixl_init_rx_ring(struct ixl_queue *que)
{
+ struct rx_ring *rxr = &que->rxr;
+#if defined(INET6) || defined(INET)
struct ixl_vsi *vsi = que->vsi;
struct ifnet *ifp = vsi->ifp;
- struct rx_ring *rxr = &que->rxr;
struct lro_ctrl *lro = &rxr->lro;
+#endif
struct ixl_rx_buf *buf;
bus_dma_segment_t pseg[1], hseg[1];
int rsize, nsegs, error = 0;
@@ -1187,6 +1189,7 @@ skip_head:
rxr->bytes = 0;
rxr->discard = FALSE;
+#if defined(INET6) || defined(INET)
/*
** Now set up the LRO interface:
*/
@@ -1200,6 +1203,7 @@ skip_head:
rxr->lro_enabled = TRUE;
lro->ifp = vsi->ifp;
}
+#endif
bus_dmamap_sync(rxr->dma.tag, rxr->dma.map,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
@@ -1274,6 +1278,8 @@ ixl_free_que_rx(struct ixl_queue *que)
static __inline void
ixl_rx_input(struct rx_ring *rxr, struct ifnet *ifp, struct mbuf *m, u8 ptype)
{
+
+#if defined(INET6) || defined(INET)
/*
* ATM LRO is only for IPv4/TCP packets and TCP checksum of the packet
* should be computed by hardware. Also it should not have VLAN tag in
@@ -1293,6 +1299,7 @@ ixl_rx_input(struct rx_ring *rxr, struct ifnet *ifp, struct mbuf *m, u8 ptype)
if (tcp_lro_rx(&rxr->lro, m, 0) == 0)
return;
}
+#endif
IXL_RX_UNLOCK(rxr);
(*ifp->if_input)(ifp, m);
IXL_RX_LOCK(rxr);
@@ -1350,8 +1357,10 @@ ixl_rxeof(struct ixl_queue *que, int count)
struct ixl_vsi *vsi = que->vsi;
struct rx_ring *rxr = &que->rxr;
struct ifnet *ifp = vsi->ifp;
+#if defined(INET6) || defined(INET)
struct lro_ctrl *lro = &rxr->lro;
struct lro_entry *queued;
+#endif
int i, nextp, processed = 0;
union i40e_rx_desc *cur;
struct ixl_rx_buf *rbuf, *nbuf;
@@ -1559,6 +1568,7 @@ next_desc:
rxr->next_check = i;
+#if defined(INET6) || defined(INET)
/*
* Flush any outstanding LRO work
*/
@@ -1566,6 +1576,7 @@ next_desc:
SLIST_REMOVE_HEAD(&lro->lro_active, next);
tcp_lro_flush(lro, queued);
}
+#endif
IXL_RX_UNLOCK(rxr);
return (FALSE);
diff --git a/sys/dev/jme/if_jme.c b/sys/dev/jme/if_jme.c
index 6300df6..35b2526 100644
--- a/sys/dev/jme/if_jme.c
+++ b/sys/dev/jme/if_jme.c
@@ -1947,7 +1947,7 @@ jme_watchdog(struct jme_softc *sc)
ifp = sc->jme_ifp;
if ((sc->jme_flags & JME_FLAG_LINK) == 0) {
if_printf(sc->jme_ifp, "watchdog timeout (missed link)\n");
- ifp->if_oerrors++;
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
jme_init_locked(sc);
return;
@@ -1962,7 +1962,7 @@ jme_watchdog(struct jme_softc *sc)
}
if_printf(sc->jme_ifp, "watchdog timeout\n");
- ifp->if_oerrors++;
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
jme_init_locked(sc);
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
@@ -2281,7 +2281,7 @@ jme_link_task(void *arg, int pending)
m_freem(txd->tx_m);
txd->tx_m = NULL;
txd->tx_ndesc = 0;
- ifp->if_oerrors++;
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
}
}
}
@@ -2449,13 +2449,13 @@ jme_txeof(struct jme_softc *sc)
break;
if ((status & (JME_TD_TMOUT | JME_TD_RETRY_EXP)) != 0)
- ifp->if_oerrors++;
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
else {
- ifp->if_opackets++;
+ if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
if ((status & JME_TD_COLLISION) != 0)
- ifp->if_collisions +=
+ if_inc_counter(ifp, IFCOUNTER_COLLISIONS,
le32toh(txd->tx_desc->buflen) &
- JME_TD_BUF_LEN_MASK;
+ JME_TD_BUF_LEN_MASK);
}
/*
* Only the first descriptor of multi-descriptor
@@ -2526,7 +2526,7 @@ jme_rxeof(struct jme_softc *sc)
nsegs = JME_RX_NSEGS(status);
sc->jme_cdata.jme_rxlen = JME_RX_BYTES(status) - JME_RX_PAD_BYTES;
if ((status & JME_RX_ERR_STAT) != 0) {
- ifp->if_ierrors++;
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
jme_discard_rxbuf(sc, sc->jme_cdata.jme_rx_cons);
#ifdef JME_SHOW_ERRORS
device_printf(sc->jme_dev, "%s : receive error = 0x%b\n",
@@ -2543,7 +2543,7 @@ jme_rxeof(struct jme_softc *sc)
mp = rxd->rx_m;
/* Add a new receive buffer to the ring. */
if (jme_newbuf(sc, rxd) != 0) {
- ifp->if_iqdrops++;
+ if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
/* Reuse buffer. */
for (; count < nsegs; count++) {
jme_discard_rxbuf(sc, cons);
@@ -2626,7 +2626,7 @@ jme_rxeof(struct jme_softc *sc)
m->m_flags |= M_VLANTAG;
}
- ifp->if_ipackets++;
+ if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
/* Pass it on. */
JME_UNLOCK(sc);
(*ifp->if_input)(ifp, m);
diff --git a/sys/dev/lmc/if_lmc.c b/sys/dev/lmc/if_lmc.c
index f7cdac5..9e1463b 100644
--- a/sys/dev/lmc/if_lmc.c
+++ b/sys/dev/lmc/if_lmc.c
@@ -71,7 +71,6 @@
*
* Send bug reports and improvements to <boggs@boggs.palo-alto.ca.us>.
*/
-#ifdef __FreeBSD__
# include <sys/param.h> /* OS version */
# define IFNET 1
# include "opt_inet.h" /* INET */
@@ -90,15 +89,9 @@
# define NETGRAPH 0
# endif
# define P2P 0 /* not in FreeBSD */
-# if (__FreeBSD_version >= 500000)
-# define NSPPP 1 /* No count devices in FreeBSD 5 */
-# include "opt_bpf.h" /* DEV_BPF */
-# define NBPFILTER DEV_BPF
-# else /* FreeBSD-4 */
-# include "sppp.h" /* NSPPP */
-# include "bpf.h" /* NBPF */
-# define NBPFILTER NBPF
-# endif
+# define NSPPP 1 /* No count devices in FreeBSD 5 */
+# include "opt_bpf.h" /* DEV_BPF */
+# define NBPFILTER DEV_BPF
# define GEN_HDLC 0 /* not in FreeBSD */
#
# include <sys/systm.h>
@@ -121,16 +114,9 @@
# include <sys/rman.h>
# include <vm/vm.h>
# include <vm/pmap.h>
-# if (__FreeBSD_version >= 700000)
-# include <sys/priv.h>
-# endif
-# if (__FreeBSD_version >= 500000)
+# include <sys/priv.h>
# include <sys/mutex.h>
# include <dev/pci/pcivar.h>
-# else /* FreeBSD-4 */
-# include <sys/proc.h>
-# include <pci/pcivar.h>
-# endif
# if NETGRAPH
# include <netgraph/ng_message.h>
# include <netgraph/netgraph.h>
@@ -147,180 +133,10 @@
# endif
/* and finally... */
# include <dev/lmc/if_lmc.h>
-#endif /*__FreeBSD__*/
-#ifdef __NetBSD__
-# include <sys/param.h> /* OS version */
-# define IFNET 1
-# include "opt_inet.h" /* INET6, INET */
-# define NETGRAPH 0 /* not in NetBSD */
-# include "sppp.h" /* NSPPP */
-# define P2P 0 /* not in NetBSD */
-# include "opt_altq_enabled.h" /* ALTQ */
-# include "bpfilter.h" /* NBPFILTER */
-# define GEN_HDLC 0 /* not in NetBSD */
-#
-# include <sys/systm.h>
-# include <sys/kernel.h>
-# include <sys/lkm.h>
-# include <sys/mbuf.h>
-# include <sys/socket.h>
-# include <sys/sockio.h>
-# include <sys/device.h>
-# include <sys/lock.h>
-# include <net/if.h>
-# include <net/if_var.h>
-# include <net/if_types.h>
-# include <net/if_media.h>
-# include <net/netisr.h>
-# include <machine/bus.h>
-# include <machine/intr.h>
-# include <dev/pci/pcivar.h>
-# if (__NetBSD_Version__ >= 106000000)
-# include <uvm/uvm_extern.h>
-# else
-# include <vm/vm.h>
-# endif
-# if (INET || INET6)
-# include <netinet/in.h>
-# include <netinet/in_var.h>
-# endif
-# if NSPPP
-# if (__NetBSD_Version__ >= 106000000)
-# include <net/if_spppvar.h>
-# else
-# include <net/if_sppp.h>
-# endif
-# endif
-# if NBPFILTER
-# include <net/bpf.h>
-# endif
-/* and finally... */
-# include "if_lmc.h"
-#endif /*__NetBSD__*/
-#ifdef __OpenBSD__
-# include <sys/param.h> /* OS version */
-# define IFNET 1
-/* -DINET is passed on the compiler command line */
-/* -DINET6 is passed on the compiler command line */
-# define NETGRAPH 0 /* not in OpenBSD */
-# include "sppp.h" /* NSPPP */
-# define P2P 0 /* not in OpenBSD */
-/* -DALTQ is passed on the compiler command line */
-# include "bpfilter.h" /* NBPFILTER */
-# define GEN_HDLC 0 /* not in OpenBSD */
-#
-# include <sys/systm.h>
-# include <sys/kernel.h>
-# include <sys/conf.h>
-# include <sys/exec.h>
-# include <sys/lkm.h>
-# include <sys/mbuf.h>
-# include <sys/socket.h>
-# include <sys/sockio.h>
-# include <sys/device.h>
-# include <sys/lock.h>
-# include <net/if.h>
-# include <net/if_types.h>
-# include <net/if_media.h>
-# include <net/netisr.h>
-# include <machine/bus.h>
-# include <machine/intr.h>
-# include <dev/pci/pcivar.h>
-# if (OpenBSD >= 200206)
-# include <uvm/uvm_extern.h>
-# else
-# include <vm/vm.h>
-# endif
-# if (INET || INET6)
-# include <netinet/in.h>
-# include <netinet/in_var.h>
-# endif
-# if NSPPP
-# include <net/if_sppp.h>
-# endif
-# if NBPFILTER
-# include <net/bpf.h>
-# endif
-/* and finally... */
-# include "if_lmc.h"
-#endif /*__OpenBSD__*/
-#ifdef __bsdi__
-# include <sys/param.h> /* OS version */
-# define IFNET 1
-/* -DINET is passed on the compiler command line */
-/* -DINET6 is passed on the compiler command line */
-# define NETGRAPH 0 /* not in BSD/OS */
-# define NSPPP 0 /* not in BSD/OS */
-/* -DPPP is passed on the compiler command line */
-/* -DCISCO_HDLC is passed on the compiler command line */
-/* -DFR is passed on the compiler command line */
-# if (PPP || CISCO_HDLC || FR)
-# define P2P 1
-# else
-# define P2P 0
-# endif
-# define ALTQ 0 /* not in BSD/OS */
-# include "bpfilter.h" /* NBPFILTER */
-# define GEN_HDLC 0 /* not in BSD/OS */
-#
-# include <sys/kernel.h>
-# include <sys/malloc.h>
-# include <sys/mbuf.h>
-# include <sys/socket.h>
-# include <sys/sockio.h>
-# include <sys/device.h>
-# include <sys/lock.h>
-# include <net/if.h>
-# include <net/if_types.h>
-# include <net/if_media.h>
-# include <net/netisr.h>
-# include <vm/vm.h>
-# include <i386/isa/dma.h>
-# include <i386/isa/isavar.h>
-# include <i386/include/cpu.h>
-# include <i386/pci/pci.h>
-# if (INET || INET6)
-# include <netinet/in.h>
-# include <netinet/in_var.h>
-# endif
-# if P2P
-# include <net/if_p2p.h>
-# include <sys/ttycom.h>
-# endif
-# if NBPFILTER
-# include <net/bpf.h>
-# endif
-/* and finally... */
-# include "if_lmc.h"
-#endif /*__bsdi__*/
-#ifdef __linux__
-# include <linux/config.h>
-# if (CONFIG_HDLC || CONFIG_HDLC_MODULE)
-# define GEN_HDLC 1
-# else
-# define GEN_HDLC 0
-# endif
-# define IFNET 0 /* different in Linux */
-# define NETGRAPH 0 /* not in Linux */
-# define NSPPP 0 /* different in Linux */
-# define P2P 0 /* not in Linux */
-# define ALTQ 0 /* different in Linux */
-# define NBPFILTER 0 /* different in Linux */
-#
-# include <linux/pci.h>
-# include <linux/delay.h>
-# include <linux/netdevice.h>
-# include <linux/if_arp.h>
-# if GEN_HDLC
-# include <linux/hdlc.h>
-# endif
-/* and finally... */
-# include "if_lmc.h"
-#endif /* __linux__ */
/* The SROM is a generic 93C46 serial EEPROM (64 words by 16 bits). */
/* Data is set up before the RISING edge of CLK; CLK is parked low. */
@@ -2484,44 +2300,6 @@ struct card t1_card =
/* RAWIP is raw IP packets (v4 or v6) in HDLC frames with NO HEADERS. */
/* No HDLC Address/Control fields! No line control protocol at all! */
-/* This code is BSD/ifnet-specific; Linux and Netgraph also do RAWIP. */
-
-#if IFNET
-
-# if ((defined(__FreeBSD__) && (__FreeBSD_version < 500000)) ||\
- defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__))
-static void
-netisr_dispatch(int isr, struct mbuf *mbuf)
- {
- struct ifqueue *intrq = NULL;
- int qfull = 0;
-
-#if INET
- if (isr == NETISR_IP) intrq = &ipintrq;
-#endif
-#if INET6
- if (isr == NETISR_IPV6) intrq = &ip6intrq;
-#endif
-
- if ((intrq != NULL) && ((qfull = IF_QFULL(intrq)) == 0))
- {
- /* rxintr_cleanup() ENQUEUES in a hard interrupt. */
- /* networking code DEQUEUES in a soft interrupt. */
- /* Some BSD QUEUE routines are not interrupt-safe. */
- DISABLE_INTR; /* noop in FreeBSD */
- IF_ENQUEUE(intrq, mbuf);
- ENABLE_INTR;
- schednetisr(isr); /* schedule a soft interrupt */
- }
- else
- {
- m_freem(mbuf);
- if ((intrq != NULL) && (qfull != 0))
- IF_DROP(intrq);
- }
- }
-# endif /* ((__FreeBSD__ && (__FreeBSD_version < 500000)) || */
- /* __NetBSD__ || __OpenBSD__ || __bsdi__) */
/* rxintr_cleanup calls this to give a newly arrived pkt to higher levels. */
static void
@@ -2549,20 +2327,12 @@ lmc_raw_input(struct ifnet *ifp, struct mbuf *mbuf)
}
}
-#endif /* IFNET */
-
-/* There are TWO VERSIONS of interrupt/DMA code: Linux & BSD.
- * Handling Linux and the BSDs with CPP directives would
- * make the code unreadable, so there are two versions.
- * Conceptually, the two versions do the same thing and
- * core_interrupt() doesn't know they are different.
- *
+/*
* We are "standing on the head of a pin" in these routines.
* Tulip CSRs can be accessed, but nothing else is interrupt-safe!
* Do NOT access: MII, GPIO, SROM, BIOSROM, XILINX, SYNTH, or DAC.
*/
-#if BSD /* BSD version of interrupt/DMA code */
/* Singly-linked tail-queues hold mbufs with active DMA.
* For RX, single mbuf clusters; for TX, mbuf chains are queued.
@@ -2593,7 +2363,6 @@ mbuf_dequeue(struct desc_ring *ring)
return m;
}
-# ifdef __FreeBSD__
static void /* *** FreeBSD ONLY *** Callout from bus_dmamap_load() */
fbsd_dmamap_load(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
{
@@ -2602,7 +2371,6 @@ fbsd_dmamap_load(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
ring->segs[0] = segs[0];
ring->segs[1] = segs[1];
}
-# endif
/* Initialize a DMA descriptor ring. */
static int /* BSD version */
@@ -2620,15 +2388,12 @@ create_ring(softc_t *sc, struct desc_ring *ring, int num_descs)
return EINVAL;
}
-#ifdef __FreeBSD__
/* Create a DMA tag for descriptors and buffers. */
if ((error = bus_dma_tag_create(bus_get_dma_tag(sc->dev),
4, 0, BUS_SPACE_MAXADDR_32BIT,
BUS_SPACE_MAXADDR, NULL, NULL, PAGE_SIZE, 2, PAGE_SIZE, BUS_DMA_ALLOCNOW,
-# if (__FreeBSD_version >= 502000)
NULL, NULL,
-# endif
&ring->tag)))
{
printf("%s: bus_dma_tag_create() failed: error %d\n", NAME_UNIT, error);
@@ -2662,70 +2427,6 @@ create_ring(softc_t *sc, struct desc_ring *ring, int num_descs)
return error;
}
-#elif (defined(__NetBSD__) || defined(__OpenBSD__))
-
- /* Use the DMA tag passed to attach() for descriptors and buffers. */
- ring->tag = sc->pa_dmat;
-
- /* Allocate wired physical memory for DMA descriptor array. */
- if ((error = bus_dmamem_alloc(ring->tag, size_descs, PAGE_SIZE, 0,
- ring->segs, 1, &ring->nsegs, BUS_DMA_NOWAIT)))
- {
- printf("%s: bus_dmamem_alloc() failed; error %d\n", NAME_UNIT, error);
- return error;
- }
-
- /* Map physical address to kernel virtual address. */
- if ((error = bus_dmamem_map(ring->tag, ring->segs, ring->nsegs,
- size_descs, (caddr_t *)&ring->first, BUS_DMA_NOWAIT | BUS_DMA_COHERENT)))
- {
- printf("%s: bus_dmamem_map() failed; error %d\n", NAME_UNIT, error);
- return error;
- }
- descs = ring->first; /* suppress compiler warning about aliasing */
- memset(descs, 0, size_descs);
-
- /* Allocate dmamap for PCI access to DMA descriptor array. */
- if ((error = bus_dmamap_create(ring->tag, size_descs, 1,
- size_descs, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ring->map)))
- {
- printf("%s: bus_dmamap_create() failed; error %d\n", NAME_UNIT, error);
- return error;
- }
-
- /* Map kernel virtual address to PCI address for DMA descriptor array. */
- if ((error = bus_dmamap_load(ring->tag, ring->map, descs, size_descs,
- 0, BUS_DMA_NOWAIT)))
- {
- printf("%s: bus_dmamap_load() failed; error %d\n", NAME_UNIT, error);
- return error;
- }
- ring->dma_addr = ring->map->dm_segs[0].ds_addr;
-
- /* Allocate dmamaps for each DMA descriptor. */
- for (i=0; i<num_descs; i++)
- if ((error = bus_dmamap_create(ring->tag, MAX_DESC_LEN, 2,
- MAX_CHUNK_LEN, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &descs[i].map)))
- {
- printf("%s: bus_dmamap_create() failed; error %d\n", NAME_UNIT, error);
- return error;
- }
-
-#elif defined(__bsdi__)
-
- /* Allocate wired physical memory for DMA descriptor array. */
- if ((ring->first = malloc(size_descs, M_DEVBUF, M_NOWAIT)) == NULL)
- {
- printf("%s: malloc() failed for DMA descriptor array\n", NAME_UNIT);
- return ENOMEM;
- }
- descs = ring->first;
- memset(descs, 0, size_descs);
-
- /* Map kernel virtual address to PCI address for DMA descriptor array. */
- ring->dma_addr = vtophys(descs); /* Relax! BSD/OS only. */
-
-#endif
ring->read = descs;
ring->write = descs;
@@ -2765,7 +2466,6 @@ destroy_ring(softc_t *sc, struct desc_ring *ring)
if (ring->read++ == ring->last) ring->read = ring->first;
}
-#ifdef __FreeBSD__
/* Free the dmamaps of all DMA descriptors. */
for (desc=ring->first; desc!=ring->last+1; desc++)
@@ -2782,33 +2482,6 @@ destroy_ring(softc_t *sc, struct desc_ring *ring)
if (ring->tag != NULL)
bus_dma_tag_destroy(ring->tag);
-#elif (defined(__NetBSD__) || defined(__OpenBSD__))
-
- /* Free the dmamaps of all DMA descriptors. */
- for (desc=ring->first; desc!=ring->last+1; desc++)
- if (desc->map != NULL)
- bus_dmamap_destroy(ring->tag, desc->map);
-
- /* Unmap PCI address for DMA descriptor array. */
- if (ring->dma_addr != 0)
- bus_dmamap_unload(ring->tag, ring->map);
- /* Free dmamap for DMA descriptor array. */
- if (ring->map != NULL)
- bus_dmamap_destroy(ring->tag, ring->map);
- /* Unmap kernel address for DMA descriptor array. */
- if (ring->first != NULL)
- bus_dmamem_unmap(ring->tag, (caddr_t)ring->first, ring->size_descs);
- /* Free kernel memory for DMA descriptor array. */
- if (ring->segs[0].ds_addr != 0)
- bus_dmamem_free(ring->tag, ring->segs, ring->nsegs);
-
-#elif defined(__bsdi__)
-
- /* Free kernel memory for DMA descriptor array. */
- if (ring->first != NULL)
- free(ring->first, M_DEVBUF);
-
-#endif
}
/* Clean up after a packet has been received. */
@@ -2821,7 +2494,7 @@ rxintr_cleanup(softc_t *sc)
struct mbuf *new_mbuf;
int pkt_len, desc_len;
-#if (defined(__FreeBSD__) && defined(DEVICE_POLLING))
+#if defined(DEVICE_POLLING)
/* Input packet flow control (livelock prevention): */
/* Give pkts to higher levels only if quota is > 0. */
if (sc->quota <= 0) return 0;
@@ -2890,11 +2563,7 @@ rxintr_cleanup(softc_t *sc)
{
first_mbuf = new_mbuf;
first_mbuf->m_pkthdr.len = pkt_len; /* total pkt length */
-#if IFNET
first_mbuf->m_pkthdr.rcvif = sc->ifp; /* how it got here */
-#else
- first_mbuf->m_pkthdr.rcvif = NULL;
-#endif
}
else /* 2) link mbufs. */
{
@@ -2933,11 +2602,9 @@ rxintr_cleanup(softc_t *sc)
/* Include CRC and one flag byte in input byte count. */
sc->status.cntrs.ibytes += first_mbuf->m_pkthdr.len + sc->config.crc_len +1;
sc->status.cntrs.ipackets++;
-#if IFNET
- sc->ifp->if_ipackets++;
+ if_inc_counter(sc->ifp, IFCOUNTER_IPACKETS, 1);
LMC_BPF_MTAP(first_mbuf);
-#endif
-#if (defined(__FreeBSD__) && defined(DEVICE_POLLING))
+#if defined(DEVICE_POLLING)
sc->quota--;
#endif
@@ -2945,12 +2612,8 @@ rxintr_cleanup(softc_t *sc)
#if NETGRAPH
if (sc->ng_hook != NULL) /* is hook connected? */
{
-# if (__FreeBSD_version >= 500000)
int error; /* ignore error */
NG_SEND_DATA_ONLY(error, sc->ng_hook, first_mbuf);
-# else /* FreeBSD-4 */
- ng_queue_data(sc->ng_hook, first_mbuf, NULL);
-# endif
return 1; /* did something */
}
#endif /* NETGRAPH */
@@ -3053,13 +2716,7 @@ rxintr_setup(softc_t *sc)
DMA_SYNC(desc->map, desc_len, BUS_DMASYNC_PREREAD);
/* Set up the DMA descriptor. */
-#ifdef __FreeBSD__
desc->address1 = ring->segs[0].ds_addr;
-#elif (defined(__NetBSD__) || defined(__OpenBSD__))
- desc->address1 = desc->map->dm_segs[0].ds_addr;
-#elif defined(__bsdi__)
- desc->address1 = vtophys(m->m_data); /* Relax! BSD/OS only. */
-#endif
desc->length1 = desc_len>>1;
desc->address2 = desc->address1 + desc->length1;
desc->length2 = desc_len>>1;
@@ -3108,10 +2765,8 @@ txintr_cleanup(softc_t *sc)
/* Include CRC and one flag byte in output byte count. */
sc->status.cntrs.obytes += m->m_pkthdr.len + sc->config.crc_len +1;
sc->status.cntrs.opackets++;
-#if IFNET
- sc->ifp->if_opackets++;
+ if_inc_counter(sc->ifp, IFCOUNTER_OPACKETS, 1);
LMC_BPF_MTAP(m);
-#endif
/* The only bad TX status is fifo underrun. */
if ((desc->status & TLP_DSTS_TX_UNDERRUN) != 0)
sc->status.cntrs.fifo_under++;
@@ -3181,15 +2836,9 @@ txintr_setup_mbuf(softc_t *sc, struct mbuf *m)
/* Prevent wild fetches if mapping fails (nsegs==0). */
desc->length1 = desc->length2 = 0;
desc->address1 = desc->address2 = 0;
-#if (defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__))
{
-# ifdef __FreeBSD__
bus_dma_segment_t *segs = ring->segs;
int nsegs = ring->nsegs;
-# elif (defined(__NetBSD__) || defined(__OpenBSD__))
- bus_dma_segment_t *segs = desc->map->dm_segs;
- int nsegs = desc->map->dm_nsegs;
-# endif
if (nsegs >= 1)
{
desc->address1 = segs[0].ds_addr;
@@ -3201,10 +2850,6 @@ txintr_setup_mbuf(softc_t *sc, struct mbuf *m)
desc->length2 = segs[1].ds_len;
}
}
-#elif defined(__bsdi__)
- desc->address1 = vtophys(data); /* Relax! BSD/OS only. */
- desc->length1 = desc_len;
-#endif
data += desc_len;
length -= desc_len;
@@ -3296,523 +2941,7 @@ txintr_setup(softc_t *sc)
return 1; /* did something */
}
-#endif /* BSD */
-
-#ifdef __linux__
-/* NOTE: this is the LINUX version of the interrupt/DMA code, */
-
-/* Singly-linked tail-queues hold sk_buffs with active DMA.
- * skbuffs are linked through their sk_buff.next field.
- * Callers must hold sc->bottom_lock; not otherwise locked.
- */
-
-/* Put an skbuff on the tail of the descriptor ring queue. */
-static void /* Linux version */
-skbuff_enqueue(struct desc_ring *ring, struct sk_buff *skb)
- {
- skb->next = NULL;
- if (ring->tail == NULL)
- ring->head = skb;
- else
- ring->tail->next = skb;
- ring->tail = skb;
- }
-
-/* Get an skbuff from the head of the descriptor ring queue. */
-static struct sk_buff* /* Linux version */
-skbuff_dequeue(struct desc_ring *ring)
- {
- struct sk_buff *skb = ring->head;
- if (skb != NULL)
- if ((ring->head = skb->next) == NULL)
- ring->tail = NULL;
- return skb;
- }
-
-/* Initialize a DMA descriptor ring. */
-static int /* Linux version */
-create_ring(softc_t *sc, struct desc_ring *ring, int num_descs)
- {
- struct dma_desc *descs;
- int size_descs = sizeof(struct dma_desc)*num_descs;
-
- /* Allocate and map memory for DMA descriptor array. */
- if ((descs = pci_alloc_consistent(sc->pci_dev, size_descs,
- &ring->dma_addr)) == NULL)
- {
- printk("%s: pci_alloc_consistent() failed\n", NAME_UNIT);
- return ENOMEM;
- }
- memset(descs, 0, size_descs);
-
- ring->read = descs;
- ring->write = descs;
- ring->first = descs;
- ring->last = descs + num_descs -1;
- ring->last->control = TLP_DCTL_END_RING;
- ring->num_descs = num_descs;
- ring->size_descs = size_descs;
- ring->head = NULL;
- ring->tail = NULL;
-
- return 0;
- }
-
-/* Destroy a DMA descriptor ring */
-static void /* Linux version */
-destroy_ring(softc_t *sc, struct desc_ring *ring)
- {
- struct sk_buff *skb;
-
- /* Free queued skbuffs. */
- while ((skb = skbuff_dequeue(ring)) != NULL)
- dev_kfree_skb(skb);
-
- /* TX may have one pkt that is not on any queue. */
- if (sc->tx_skb != NULL)
- {
- dev_kfree_skb(sc->tx_skb);
- sc->tx_skb = NULL;
- }
-
- if (ring->first != NULL)
- {
- /* Unmap active DMA descriptors. */
- while (ring->read != ring->write)
- {
- pci_unmap_single(sc->pci_dev, ring->read->address1,
- ring->read->length1 + ring->read->length2, PCI_DMA_BIDIRECTIONAL);
- if (ring->read++ == ring->last) ring->read = ring->first;
- }
-
- /* Unmap and free memory for DMA descriptor array. */
- pci_free_consistent(sc->pci_dev, ring->size_descs, ring->first,
- ring->dma_addr);
- }
- }
-
-static int /* Linux version */
-rxintr_cleanup(softc_t *sc)
- {
- struct desc_ring *ring = &sc->rxring;
- struct dma_desc *first_desc, *last_desc;
- struct sk_buff *first_skb=NULL, *last_skb=NULL;
- struct sk_buff *new_skb;
- int pkt_len, desc_len;
-
- /* Input packet flow control (livelock prevention): */
- /* Give pkts to higher levels only if quota is > 0. */
- if (sc->quota <= 0) return 0;
-
- /* This looks complicated, but remember: packets up to 4032 */
- /* bytes long fit in one skbuff and use one DMA descriptor. */
-
- first_desc = last_desc = ring->read;
-
- /* ASSERTION: If there is a descriptor in the ring and the hardware has */
- /* finished with it, then that descriptor will have RX_FIRST_DESC set. */
- if ((ring->read != ring->write) && /* descriptor ring not empty */
- ((ring->read->status & TLP_DSTS_OWNER) == 0) && /* hardware done */
- ((ring->read->status & TLP_DSTS_RX_FIRST_DESC) == 0)) /* should be set */
- panic("%s: rxintr_cleanup: rx-first-descriptor not set.\n", NAME_UNIT);
-
- /* First decide if a complete packet has arrived. */
- /* Run down DMA descriptors looking for one marked "last". */
- /* Bail out if an active descriptor is encountered. */
- /* Accumulate most significant bits of packet length. */
- pkt_len = 0;
- for (;;)
- {
- if (last_desc == ring->write) return 0; /* no more descs */
- if (last_desc->status & TLP_DSTS_OWNER) return 0; /* still active */
- if (last_desc->status & TLP_DSTS_RX_LAST_DESC) break; /* end of packet */
- pkt_len += last_desc->length1 + last_desc->length2; /* entire desc filled */
- if (last_desc++->control & TLP_DCTL_END_RING) last_desc = ring->first; /* ring wrap */
- }
-
- /* A complete packet has arrived; how long is it? */
- /* H/w ref man shows RX pkt length as a 14-bit field. */
- /* An experiment found that only the 12 LSBs work. */
- if (((last_desc->status>>16)&0xFFF) == 0) pkt_len += 4096; /* carry-bit */
- pkt_len = (pkt_len & 0xF000) + ((last_desc->status>>16) & 0x0FFF);
- /* Subtract the CRC length unless doing so would underflow. */
- if (pkt_len >= sc->config.crc_len) pkt_len -= sc->config.crc_len;
-
- /* Run down DMA descriptors again doing the following:
- * 1) put pkt info in hdr of first skbuff.
- * 2) put additional skbuffs on frag_list.
- * 3) set skbuff lengths.
- */
- first_desc = ring->read;
- do
- {
- /* Read a DMA descriptor from the ring. */
- last_desc = ring->read;
- /* Advance the ring read pointer. */
- if (ring->read++ == ring->last) ring->read = ring->first;
- /* Dequeue the corresponding skbuff. */
- new_skb = skbuff_dequeue(ring);
- if (new_skb == NULL)
- panic("%s: rxintr_cleanup: expected an skbuff\n", NAME_UNIT);
-
- desc_len = last_desc->length1 + last_desc->length2;
- /* Unmap kernel virtual addresss to PCI address. */
- pci_unmap_single(sc->pci_dev, last_desc->address1,
- desc_len, PCI_DMA_FROMDEVICE);
-
- /* Set skbuff length. */
- skb_put(new_skb, (pkt_len >= desc_len) ? desc_len : pkt_len);
- pkt_len -= new_skb->len;
-
- /* 1) Put pkt info in hdr of first skbuff. */
- if (last_desc == first_desc)
- {
- first_skb = new_skb;
- if (sc->config.line_pkg == PKG_RAWIP)
- {
- if (first_skb->data[0]>>4 == 4)
- first_skb->protocol = htons(ETH_P_IP);
- else if (first_skb->data[0]>>4 == 6)
- first_skb->protocol = htons(ETH_P_IPV6);
- }
- else
-#if GEN_HDLC
- first_skb->protocol = hdlc_type_trans(first_skb, sc->net_dev);
-#else
- first_skb->protocol = htons(ETH_P_HDLC);
-#endif
- first_skb->mac.raw = first_skb->data;
- first_skb->dev = sc->net_dev;
- do_gettimeofday(&first_skb->stamp);
- sc->net_dev->last_rx = jiffies;
- }
- else /* 2) link skbuffs. */
- {
- /* Put this skbuff on the frag_list of the first skbuff. */
- new_skb->next = NULL;
- if (skb_shinfo(first_skb)->frag_list == NULL)
- skb_shinfo(first_skb)->frag_list = new_skb;
- else
- last_skb->next = new_skb;
- /* 3) set skbuff lengths. */
- first_skb->len += new_skb->len;
- first_skb->data_len += new_skb->len;
- }
- last_skb = new_skb;
- } while ((last_desc->status & TLP_DSTS_RX_LAST_DESC) == 0);
-
- /* Decide whether to accept or to discard this packet. */
- /* RxHDLC sets MIIERR for bad CRC, abort and partial byte at pkt end. */
- if (((last_desc->status & TLP_DSTS_RX_BAD) == 0) &&
- (sc->status.oper_status == STATUS_UP) &&
- (first_skb->len > 0))
- {
- /* Optimization: copy a small pkt into a small skbuff. */
- if (first_skb->len <= COPY_BREAK)
- if ((new_skb = skb_copy(first_skb, GFP_ATOMIC)) != NULL)
- {
- dev_kfree_skb_any(first_skb);
- first_skb = new_skb;
- }
-
- /* Include CRC and one flag byte in input byte count. */
- sc->status.cntrs.ibytes += first_skb->len + sc->config.crc_len +1;
- sc->status.cntrs.ipackets++;
-
- /* Give this good packet to the network stacks. */
- netif_receive_skb(first_skb); /* NAPI */
- sc->quota--;
- }
- else if (sc->status.oper_status != STATUS_UP)
- {
- /* If the link is down, this packet is probably noise. */
- sc->status.cntrs.idiscards++;
- dev_kfree_skb_any(first_skb);
- if (DRIVER_DEBUG)
- printk("%s: rxintr_cleanup: rx pkt discarded: link down\n", NAME_UNIT);
- }
- else /* Log and discard this bad packet. */
- {
- if (DRIVER_DEBUG)
- printk("%s: RX bad pkt; len=%d %s%s%s%s\n",
- NAME_UNIT, first_skb->len,
- (last_desc->status & TLP_DSTS_RX_MII_ERR) ? " miierr" : "",
- (last_desc->status & TLP_DSTS_RX_DRIBBLE) ? " dribble" : "",
- (last_desc->status & TLP_DSTS_RX_DESC_ERR) ? " descerr" : "",
- (last_desc->status & TLP_DSTS_RX_OVERRUN) ? " overrun" : "");
- if (last_desc->status & TLP_DSTS_RX_OVERRUN)
- sc->status.cntrs.fifo_over++;
- else
- sc->status.cntrs.ierrors++;
- dev_kfree_skb_any(first_skb);
- }
-
- return 1; /* did something */
- }
-
-/* Setup (prepare) to receive a packet. */
-/* Try to keep the RX descriptor ring full of empty buffers. */
-static int /* Linux version */
-rxintr_setup(softc_t *sc)
- {
- struct desc_ring *ring = &sc->rxring;
- struct dma_desc *desc;
- struct sk_buff *skb;
- u_int32_t dma_addr;
-
- /* Ring is full if (wrap(write+1)==read) */
- if (((ring->write == ring->last) ? ring->first : ring->write+1) == ring->read)
- return 0; /* ring is full; nothing to do */
-
- /* Allocate an skbuff. */
- if ((skb = dev_alloc_skb(MAX_DESC_LEN)) == NULL)
- {
- sc->status.cntrs.rxdma++;
- if (DRIVER_DEBUG)
- printk("%s: rxintr_setup: dev_alloc_skb() failed\n", NAME_UNIT);
- return 0;
- }
- skb->dev = sc->net_dev;
-
- /* Queue the skbuff for later processing by rxintr_cleanup. */
- skbuff_enqueue(ring, skb);
-
- /* Write a DMA descriptor into the ring. */
- /* Hardware won't see it until the OWNER bit is set. */
- desc = ring->write;
- /* Advance the ring write pointer. */
- if (ring->write++ == ring->last) ring->write = ring->first;
-
- /* Map kernel virtual addresses to PCI addresses. */
- dma_addr = pci_map_single(sc->pci_dev, skb->data,
- MAX_DESC_LEN, PCI_DMA_FROMDEVICE);
- /* Set up the DMA descriptor. */
- desc->address1 = dma_addr;
- desc->length1 = MAX_CHUNK_LEN;
- desc->address2 = desc->address1 + desc->length1;
- desc->length2 = MAX_CHUNK_LEN;
-
- /* Before setting the OWNER bit, flush the cache (memory barrier). */
- wmb(); /* write memory barrier */
-
- /* Commit the DMA descriptor to the hardware. */
- desc->status = TLP_DSTS_OWNER;
-
- /* Notify the receiver that there is another buffer available. */
- WRITE_CSR(TLP_RX_POLL, 1);
-
- return 1; /* did something */
- }
-
-/* Clean up after a packet has been transmitted. */
-/* Free the sk_buff and update the DMA descriptor ring. */
-static int /* Linux version */
-txintr_cleanup(softc_t *sc)
- {
- struct desc_ring *ring = &sc->txring;
- struct dma_desc *desc;
-
- while ((ring->read != ring->write) && /* ring is not empty */
- ((ring->read->status & TLP_DSTS_OWNER) == 0))
- {
- /* Read a DMA descriptor from the ring. */
- desc = ring->read;
- /* Advance the ring read pointer. */
- if (ring->read++ == ring->last) ring->read = ring->first;
- /* Unmap kernel virtual address to PCI address. */
- pci_unmap_single(sc->pci_dev, desc->address1,
- desc->length1 + desc->length2, PCI_DMA_TODEVICE);
-
- /* If this descriptor is the last segment of a packet, */
- /* then dequeue and free the corresponding skbuff. */
- if ((desc->control & TLP_DCTL_TX_LAST_SEG) != 0)
- {
- struct sk_buff *skb;
- if ((skb = skbuff_dequeue(ring)) == NULL)
- panic("%s: txintr_cleanup: expected an sk_buff\n", NAME_UNIT);
-
- /* Include CRC and one flag byte in output byte count. */
- sc->status.cntrs.obytes += skb->len + sc->config.crc_len +1;
- sc->status.cntrs.opackets++;
-
- /* The only bad TX status is fifo underrun. */
- if ((desc->status & TLP_DSTS_TX_UNDERRUN) != 0)
- {
- sc->status.cntrs.fifo_under++; /* also increment oerrors? */
- if (DRIVER_DEBUG)
- printk("%s: txintr_cleanup: tx fifo underrun\n", NAME_UNIT);
- }
-
- dev_kfree_skb_any(skb);
- return 1; /* did something */
- }
- }
-
- return 0;
- }
-
-/* Build DMA descriptors for a tranmit packet fragment, */
-/* Assertion: fragment is contiguous in physical memory. */
-static int /* 0=success; 1=error */ /* linux version */
-txintr_setup_frag(softc_t *sc, char *data, int length)
- {
- struct desc_ring *ring = &sc->txring;
- struct dma_desc *desc;
- unsigned int desc_len;
- u_int32_t dma_addr;
-
- while (length > 0)
- {
- /* Ring is full if (wrap(write+1)==read) */
- if (((ring->temp==ring->last) ? ring->first : ring->temp+1) == ring->read)
- { /* Not enough DMA descriptors; try later. */
- for (; ring->temp!=ring->write;
- ring->temp = (ring->temp==ring->first)? ring->last : ring->temp-1)
- pci_unmap_single(sc->pci_dev, ring->temp->address1,
- ring->temp->length1 + ring->temp->length2, PCI_DMA_FROMDEVICE);
- sc->status.cntrs.txdma++;
- return 1;
- }
-
- /* Provisionally, write a DMA descriptor into the ring. */
- /* But don't change the REAL ring write pointer. */
- /* Hardware won't see it until the OWNER bit is set. */
- desc = ring->temp;
- /* Advance the temporary ring write pointer. */
- if (ring->temp++ == ring->last) ring->temp = ring->first;
-
- /* Clear all control bits except the END_RING bit. */
- desc->control &= TLP_DCTL_END_RING;
- /* Don't pad short packets up to 64 bytes */
- desc->control |= TLP_DCTL_TX_NO_PAD;
- /* Use Tulip's CRC-32 generator, if appropriate. */
- if (sc->config.crc_len != CFG_CRC_32)
- desc->control |= TLP_DCTL_TX_NO_CRC;
- /* Set the OWNER bit, except in the first descriptor. */
- if (desc != ring->write)
- desc->status = TLP_DSTS_OWNER;
-
- desc_len = (length >= MAX_DESC_LEN) ? MAX_DESC_LEN : length;
- /* Map kernel virtual address to PCI address. */
- dma_addr = pci_map_single(sc->pci_dev, data, desc_len, PCI_DMA_TODEVICE);
- /* If it will fit in one chunk, do so, otherwise split it. */
- if (desc_len <= MAX_CHUNK_LEN)
- {
- desc->address1 = dma_addr;
- desc->length1 = desc_len;
- desc->address2 = 0;
- desc->length2 = 0;
- }
- else
- {
- desc->address1 = dma_addr;
- desc->length1 = desc_len>>1;
- desc->address2 = desc->address1 + desc->length1;
- desc->length2 = desc_len>>1;
- if (desc_len & 1) desc->length2++;
- }
-
- data += desc_len;
- length -= desc_len;
- } /* while (length > 0) */
-
- return 0; /* success */
- }
-
-/* NB: this procedure is recursive! */
-static int /* 0=success; 1=error */
-txintr_setup_skb(softc_t *sc, struct sk_buff *skb)
- {
- struct sk_buff *list;
- int i;
-
- /* First, handle the data in the skbuff itself. */
- if (txintr_setup_frag(sc, skb->data, skb_headlen(skb)))
- return 1;
-
- /* Next, handle the VM pages in the Scatter/Gather list. */
- if (skb_shinfo(skb)->nr_frags != 0)
- for (i=0; i<skb_shinfo(skb)->nr_frags; i++)
- {
- skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
- if (txintr_setup_frag(sc, page_address(frag->page) +
- frag->page_offset, frag->size))
- return 1;
- }
-
- /* Finally, handle the skbuffs in the frag_list. */
- if ((list = skb_shinfo(skb)->frag_list) != NULL)
- for (; list; list=list->next)
- if (txintr_setup_skb(sc, list)) /* recursive! */
- return 1;
-
- return 0;
- }
-
-/* Setup (prepare) to transmit a packet. */
-/* Select a packet, build DMA descriptors and give packet to hardware. */
-/* If DMA descriptors run out, abandon the attempt and return 0. */
-static int /* Linux version */
-txintr_setup(softc_t *sc)
- {
- struct desc_ring *ring = &sc->txring;
- struct dma_desc *first_desc, *last_desc;
-
- /* Protect against half-up links: Don't transmit */
- /* if the receiver can't hear the far end. */
- if (sc->status.oper_status != STATUS_UP) return 0;
-
- /* Pick a packet to transmit. */
- /* linux_start() puts packets in sc->tx_skb. */
- if (sc->tx_skb == NULL)
- {
- if (netif_queue_stopped(sc->net_dev) != 0)
- netif_wake_queue(sc->net_dev);
- return 0; /* no pkt to transmit */
- }
-
- /* Build DMA descriptors for an outgoing skbuff. */
- ring->temp = ring->write; /* temporary ring write pointer */
- if (txintr_setup_skb(sc, sc->tx_skb) != 0) return 0;
-
- /* Enqueue the skbuff; txintr_cleanup will free it. */
- skbuff_enqueue(ring, sc->tx_skb);
-
- /* The transmitter has room for another packet. */
- sc->tx_skb = NULL;
-
- /* Set first & last segment bits. */
- /* last_desc is the desc BEFORE the one pointed to by ring->temp. */
- first_desc = ring->write;
- first_desc->control |= TLP_DCTL_TX_FIRST_SEG;
- last_desc = (ring->temp==ring->first)? ring->last : ring->temp-1;
- last_desc->control |= TLP_DCTL_TX_LAST_SEG;
- /* Interrupt at end-of-transmission? Why bother the poor computer! */
-/* last_desc->control |= TLP_DCTL_TX_INTERRUPT; */
-
- /* Make sure the OWNER bit is not set in the next descriptor. */
- /* The OWNER bit may have been set if a previous call aborted. */
- ring->temp->status = 0;
-
- /* Commit the DMA descriptors to the software. */
- ring->write = ring->temp;
-
- /* Before setting the OWNER bit, flush the cache (memory barrier). */
- wmb(); /* write memory barrier */
-
- /* Commit the DMA descriptors to the hardware. */
- first_desc->status = TLP_DSTS_OWNER;
-
- /* Notify the transmitter that there is another packet to send. */
- WRITE_CSR(TLP_TX_POLL, 1);
-
- sc->net_dev->trans_start = jiffies;
-
- return 1; /* did something */
- }
-
-#endif /* __linux__ */
static void
check_intr_status(softc_t *sc)
@@ -3914,7 +3043,6 @@ core_interrupt(void *arg, int check_status)
/* In Linux, pci_alloc_consistent() means DMA descriptors */
/* don't need explicit syncing. */
-#if BSD
{
struct desc_ring *ring = &sc->txring;
DMA_SYNC(sc->txring.map, sc->txring.size_descs,
@@ -3923,7 +3051,6 @@ core_interrupt(void *arg, int check_status)
DMA_SYNC(sc->rxring.map, sc->rxring.size_descs,
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
}
-#endif
do /* This is the main loop for interrupt processing. */
{
@@ -3933,7 +3060,6 @@ core_interrupt(void *arg, int check_status)
activity += rxintr_setup(sc);
} while (activity);
-#if BSD
{
struct desc_ring *ring = &sc->txring;
DMA_SYNC(sc->txring.map, sc->txring.size_descs,
@@ -3942,7 +3068,6 @@ core_interrupt(void *arg, int check_status)
DMA_SYNC(sc->rxring.map, sc->rxring.size_descs,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
}
-#endif
/* As the interrupt is dismissed, check for four unusual events. */
if (check_status) check_intr_status(sc);
@@ -3959,9 +3084,8 @@ user_interrupt(softc_t *sc, int check_status)
ENABLE_INTR; /* noop on FreeBSD-5 and Linux */
}
-#if BSD
-# if (defined(__FreeBSD__) && defined(DEVICE_POLLING))
+# if defined(DEVICE_POLLING)
/* Service the card from the kernel idle loop without interrupts. */
static int
@@ -3969,27 +3093,13 @@ fbsd_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
{
softc_t *sc = IFP2SC(ifp);
-#if (__FreeBSD_version < 700000)
- if ((ifp->if_capenable & IFCAP_POLLING) == 0)
- {
- ether_poll_deregister(ifp);
- cmd = POLL_DEREGISTER;
- }
-
- if (cmd == POLL_DEREGISTER)
- {
- /* Last call -- reenable card interrupts. */
- WRITE_CSR(TLP_INT_ENBL, TLP_INT_TXRX);
- return 0;
- }
-#endif
sc->quota = count;
core_interrupt(sc, (cmd==POLL_AND_CHECK_STATUS));
return 0;
}
-# endif /* (__FreeBSD__ && DEVICE_POLLING) */
+# endif /* DEVICE_POLLING */
/* BSD kernels call this procedure when an interrupt happens. */
static intr_return_t
@@ -4001,7 +3111,7 @@ bsd_interrupt(void *arg)
if ((READ_CSR(TLP_STATUS) & TLP_INT_TXRX) == 0)
return IRQ_NONE;
-# if (defined(__FreeBSD__) && defined(DEVICE_POLLING))
+# if defined(DEVICE_POLLING)
if (sc->ifp->if_capenable & IFCAP_POLLING)
return IRQ_NONE;
@@ -4013,7 +3123,7 @@ bsd_interrupt(void *arg)
}
else
sc->quota = sc->rxring.num_descs; /* input flow control */
-# endif /* (__FreeBSD__ && DEVICE_POLLING) */
+# endif /* DEVICE_POLLING */
/* Disable card interrupts. */
WRITE_CSR(TLP_INT_ENBL, TLP_INT_DISABLE);
@@ -4026,7 +3136,6 @@ bsd_interrupt(void *arg)
return IRQ_HANDLED;
}
-#endif /* BSD */
/* Administrative status of the driver (UP or DOWN) has changed. */
/* A card-specific action may be required: T1 and T3 cards: no-op. */
@@ -4081,12 +3190,8 @@ p2p_mdmctl(struct p2pcom *p2p, int flag)
static void
sppp_tls(struct sppp *sppp)
{
-# ifdef __FreeBSD__
if (!(sppp->pp_mode & IFF_LINK2) &&
!(sppp->pp_flags & PP_FR))
-# elif defined(__NetBSD__) || defined(__OpenBSD__)
- if (!(sppp->pp_flags & PP_CISCO))
-# endif
sppp->pp_up(sppp);
}
@@ -4094,12 +3199,8 @@ sppp_tls(struct sppp *sppp)
static void
sppp_tlf(struct sppp *sppp)
{
-# ifdef __FreeBSD__
if (!(sppp->pp_mode & IFF_LINK2) &&
!(sppp->pp_flags & PP_FR))
-# elif defined(__NetBSD__) || defined(__OpenBSD__)
- if (!(sppp->pp_flags & PP_CISCO))
-# endif
sppp->pp_down(sppp);
}
@@ -4193,12 +3294,8 @@ config_proto(softc_t *sc, struct config *config)
(config->line_prot == PROT_PPP))
{
LMC_BPF_DETACH;
-# if (defined(__NetBSD__) || defined(__OpenBSD__))
- sc->sppp->pp_flags &= ~PP_CISCO;
-# elif defined(__FreeBSD__)
sc->ifp->if_flags &= ~IFF_LINK2;
sc->sppp->pp_flags &= ~PP_FR;
-# endif
LMC_BPF_ATTACH(DLT_PPP, 4);
sppp_ioctl(sc->ifp, SIOCSIFFLAGS, NULL);
}
@@ -4212,12 +3309,8 @@ config_proto(softc_t *sc, struct config *config)
(config->line_prot == PROT_C_HDLC))
{
LMC_BPF_DETACH;
-# if (defined(__NetBSD__) || defined(__OpenBSD__))
- sc->sppp->pp_flags |= PP_CISCO;
-# elif defined(__FreeBSD__)
sc->ifp->if_flags |= IFF_LINK2;
sc->sppp->pp_flags &= ~PP_FR;
-# endif
LMC_BPF_ATTACH(DLT_C_HDLC, 4);
sppp_ioctl(sc->ifp, SIOCSIFFLAGS, NULL);
}
@@ -4227,12 +3320,8 @@ config_proto(softc_t *sc, struct config *config)
(config->line_prot == PROT_FRM_RLY))
{
LMC_BPF_DETACH;
-# if (defined(__NetBSD__) || defined(__OpenBSD__))
- sc->sppp->pp_flags &= ~PP_CISCO;
-# elif defined(__FreeBSD__)
sc->ifp->if_flags &= ~IFF_LINK2;
sc->sppp->pp_flags |= PP_FR;
-# endif
LMC_BPF_ATTACH(DLT_FRELAY, 4);
sppp_ioctl(sc->ifp, SIOCSIFFLAGS, NULL);
}
@@ -4468,7 +3557,6 @@ core_watchdog(softc_t *sc)
user_interrupt(sc, 1);
}
-#if IFNET
/* Called from a syscall (user context; no spinlocks). */
static int
@@ -4479,16 +3567,8 @@ lmc_raw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
switch (cmd)
{
-# if (defined(__FreeBSD__) && defined(DEVICE_POLLING)) /* XXX necessary? */
- case SIOCSIFCAP:
-# endif
case SIOCAIFADDR:
case SIOCSIFFLAGS:
-#if 0
- case SIOCADDMULTI:
- case SIOCDELMULTI:
- break;
-#endif
case SIOCSIFADDR:
ifp->if_flags |= IFF_UP; /* a Unix tradition */
break;
@@ -4507,9 +3587,6 @@ static int
lmc_ifnet_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
softc_t *sc = IFP2SC(ifp);
-# ifdef __OpenBSD__
- struct ifreq *ifr = (struct ifreq *) data;
-# endif
int error = 0;
switch (cmd)
@@ -4523,34 +3600,6 @@ lmc_ifnet_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
case LMCIOCTL:
error = core_ioctl(sc, cmd, data);
break;
-# ifdef __OpenBSD__
- /* Catch the IOCTLs used by ifconfig. */
- case SIOCSIFMEDIA:
- if ((error = CHECK_CAP)) break;
- case SIOCGIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &sc->ifm, cmd);
- break;
- case SIOCSIFTIMESLOT:
- if ((error = CHECK_CAP)) break;
- if (sc->status.card_type == TLP_CSID_T1E1)
- {
- struct config config = sc->config;
- if ((error = copyin(ifr->ifr_data, &config.time_slots,
- sizeof config.time_slots))) break;
- config.iohdr.cookie = NGM_LMC_COOKIE;
- error = core_ioctl(sc, LMCIOCSCFG, (caddr_t)&config);
- }
- else
- error = EINVAL;
- break;
- case SIOCGIFTIMESLOT:
- if (sc->status.card_type == TLP_CSID_T1E1)
- error = copyout(&sc->config.time_slots, ifr->ifr_data,
- sizeof sc->config.time_slots);
- else
- error = EINVAL;
- break;
-# endif
/* Pass the rest to the line protocol. */
default:
if (sc->config.line_pkg == PKG_RAWIP)
@@ -4621,11 +3670,7 @@ lmc_raw_output(struct ifnet *ifp, struct mbuf *m,
/* Some BSD QUEUE routines are not interrupt-safe. */
{
DISABLE_INTR;
-# if (__FreeBSD_version >= 503000)
IFQ_ENQUEUE(&ifp->if_snd, m, error);
-# else
- IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
-# endif
ENABLE_INTR;
}
@@ -4635,7 +3680,7 @@ lmc_raw_output(struct ifnet *ifp, struct mbuf *m,
{
m_freem(m);
sc->status.cntrs.odiscards++;
- ifp->if_oqdrops++;
+ if_inc_counter(ifp, IFCOUNTER_OQDROPS, 1);
if (DRIVER_DEBUG)
printf("%s: lmc_raw_output: IFQ_ENQUEUE() failed; error %d\n",
NAME_UNIT, error);
@@ -4647,11 +3692,10 @@ lmc_raw_output(struct ifnet *ifp, struct mbuf *m,
/* Called from a softirq once a second. */
static void
lmc_watchdog(void *arg)
- {
+{
struct ifnet *ifp = arg;
softc_t *sc = IFP2SC(ifp);
u_int8_t old_oper_status = sc->status.oper_status;
- struct event_cntrs *cntrs = &sc->status.cntrs;
core_watchdog(sc); /* updates oper_status */
@@ -4704,13 +3748,9 @@ lmc_watchdog(void *arg)
/* Notice change in line protocol. */
sc->status.line_pkg = PKG_SPPP;
-# ifdef __FreeBSD__
if (sc->sppp->pp_flags & PP_FR)
sc->status.line_prot = PROT_FRM_RLY;
else if (sc->ifp->if_flags & IFF_LINK2)
-# elif (defined(__NetBSD__) || defined(__OpenBSD__))
- if (sc->sppp->pp_flags & PP_CISCO)
-# endif
sc->status.line_prot = PROT_C_HDLC;
else
sc->status.line_prot = PROT_PPP;
@@ -4721,98 +3761,44 @@ lmc_watchdog(void *arg)
# endif
}
- /* Copy statistics from sc to ifp. */
ifp->if_baudrate = sc->status.tx_speed;
- ifp->if_ipackets = cntrs->ipackets;
- ifp->if_opackets = cntrs->opackets;
- ifp->if_ibytes = cntrs->ibytes;
- ifp->if_obytes = cntrs->obytes;
- ifp->if_ierrors = cntrs->ierrors;
- ifp->if_oerrors = cntrs->oerrors;
- ifp->if_iqdrops = cntrs->idiscards;
-
-# if ((__FreeBSD_version >= 500000) || defined(__OpenBSD__) || defined(__NetBSD__))
if (sc->status.oper_status == STATUS_UP)
ifp->if_link_state = LINK_STATE_UP;
else
ifp->if_link_state = LINK_STATE_DOWN;
-# endif
/* Call this procedure again after one second. */
callout_reset(&sc->callout, hz, lmc_watchdog, ifp);
- }
-
-# ifdef __OpenBSD__
-
-/* Callback from ifmedia. */
-static int
-ifmedia_change(struct ifnet *ifp)
- {
- softc_t *sc = IFP2SC(ifp);
- struct config config = sc->config;
- int media = sc->ifm.ifm_media;
- int error;
-
- /* ifconfig lmc0 media t1 */
- if (sc->status.card_type == TLP_CSID_T3)
- {
- if ((media & IFM_TMASK) == IFM_TDM_T3)
- config.format = CFG_FORMAT_T3CPAR;
- else if ((media & IFM_TMASK) == IFM_TDM_T3_M13)
- config.format = CFG_FORMAT_T3M13;
- }
- else if (sc->status.card_type == TLP_CSID_T1E1)
- {
- if ((media & IFM_TMASK) == IFM_TDM_T1)
- config.format = CFG_FORMAT_T1ESF;
- else if ((media & IFM_TMASK) == IFM_TDM_T1_AMI)
- config.format = CFG_FORMAT_T1SF;
- else if ((media & IFM_TMASK) == IFM_TDM_E1)
- config.format = CFG_FORMAT_E1NONE;
- else if ((media & IFM_TMASK) == IFM_TDM_E1_G704)
- config.format = CFG_FORMAT_E1FASCRC;
- }
-
- /* ifconfig lmc0 mediaopt loopback */
- if (media & IFM_LOOP)
- config.loop_back = CFG_LOOP_TULIP;
- else
- config.loop_back = CFG_LOOP_NONE;
-
- /* ifconfig lmc0 mediaopt crc16 */
- if (media & IFM_TDM_HDLC_CRC16)
- config.crc_len = CFG_CRC_16;
- else
- config.crc_len = CFG_CRC_32;
-
- /* Set ConFiGuration. */
- config.iohdr.cookie = NGM_LMC_COOKIE;
- error = core_ioctl(sc, LMCIOCSCFG, (caddr_t)&config);
-
- return error;
- }
-
-/* Callback from ifmedia. */
-static void
-ifmedia_status(struct ifnet *ifp, struct ifmediareq *ifmr)
- {
- softc_t *sc = IFP2SC(ifp);
-
- /* ifconfig wants to know if the hardware link is up. */
- ifmr->ifm_status = IFM_AVALID;
- if (sc->status.oper_status == STATUS_UP)
- ifmr->ifm_status |= IFM_ACTIVE;
-
- ifmr->ifm_active = sc->ifm.ifm_cur->ifm_media;
-
- if (sc->config.loop_back != CFG_LOOP_NONE)
- ifmr->ifm_active |= IFM_LOOP;
-
- if (sc->config.crc_len == CFG_CRC_16)
- ifmr->ifm_active |= IFM_TDM_HDLC_CRC16;
- }
-
-# endif /* __OpenBSD__ */
+}
+
+static uint64_t
+lmc_get_counter(struct ifnet *ifp, ift_counter cnt)
+{
+ softc_t *sc;
+ struct event_cntrs *cntrs;
+
+ sc = if_getsoftc(ifp);
+ cntrs = &sc->status.cntrs;
+
+ switch (cnt) {
+ case IFCOUNTER_IPACKETS:
+ return (cntrs->ipackets);
+ case IFCOUNTER_OPACKETS:
+ return (cntrs->opackets);
+ case IFCOUNTER_IBYTES:
+ return (cntrs->ibytes);
+ case IFCOUNTER_OBYTES:
+ return (cntrs->obytes);
+ case IFCOUNTER_IERRORS:
+ return (cntrs->ierrors);
+ case IFCOUNTER_OERRORS:
+ return (cntrs->oerrors);
+ case IFCOUNTER_IQDROPS:
+ return (cntrs->idiscards);
+ default:
+ return (if_get_counter_default(ifp, cnt));
+ }
+}
static void
setup_ifnet(struct ifnet *ifp)
@@ -4820,59 +3806,34 @@ setup_ifnet(struct ifnet *ifp)
softc_t *sc = ifp->if_softc;
/* Initialize the generic network interface. */
- /* Note similarity to linux's setup_netdev(). */
ifp->if_flags = IFF_POINTOPOINT;
ifp->if_flags |= IFF_RUNNING;
ifp->if_ioctl = lmc_ifnet_ioctl;
ifp->if_start = lmc_ifnet_start; /* sppp changes this */
ifp->if_output = lmc_raw_output; /* sppp & p2p change this */
ifp->if_input = lmc_raw_input;
+ ifp->if_get_counter = lmc_get_counter;
ifp->if_mtu = MAX_DESC_LEN; /* sppp & p2p change this */
ifp->if_type = IFT_PTPSERIAL; /* p2p changes this */
-# if (defined(__FreeBSD__) && defined(DEVICE_POLLING))
+# if defined(DEVICE_POLLING)
ifp->if_capabilities |= IFCAP_POLLING;
ifp->if_capenable |= IFCAP_POLLING_NOCOUNT;
-# if (__FreeBSD_version < 500000)
- ifp->if_capenable |= IFCAP_POLLING;
-# endif
# endif
- /* Every OS does it differently! */
-# if (defined(__FreeBSD__) && (__FreeBSD_version < 502000))
- (const char *)ifp->if_name = device_get_name(sc->dev);
- ifp->if_unit = device_get_unit(sc->dev);
-# elif (__FreeBSD_version >= 502000)
if_initname(ifp, device_get_name(sc->dev), device_get_unit(sc->dev));
-# elif defined(__NetBSD__)
- strcpy(ifp->if_xname, sc->dev.dv_xname);
-# elif defined(__OpenBSD__)
- bcopy(sc->dev.dv_xname, ifp->if_xname, IFNAMSIZ);
-# elif defined(__bsdi__)
- ifp->if_name = sc->dev.dv_cfdata->cf_driver->cd_name;
- ifp->if_unit = sc->dev.dv_unit;
-# endif
}
static int
lmc_ifnet_attach(softc_t *sc)
{
-# if (__FreeBSD_version >= 600000)
sc->ifp = if_alloc(NSPPP ? IFT_PPP : IFT_OTHER);
if (sc->ifp == NULL) return ENOMEM;
-# endif
# if NSPPP
-# if (__FreeBSD_version >= 600000)
sc->sppp = sc->ifp->if_l2com;
-# else
- sc->ifp = &sc->spppcom.pp_if;
- sc->sppp = &sc->spppcom;
-# endif
# elif P2P
sc->ifp = &sc->p2pcom.p2p_if;
sc->p2p = &sc->p2pcom;
-# elif (__FreeBSD_version < 600000)
- sc->ifp = &sc->ifnet;
# endif
/* Initialize the network interface struct. */
@@ -4886,40 +3847,9 @@ lmc_ifnet_attach(softc_t *sc)
/* Attach to the ifnet kernel interface. */
if_attach(sc->ifp);
-# if ((defined(__NetBSD__) && __NetBSD_Version__ >= 106000000) || \
- (defined(__OpenBSD__) && OpenBSD >= 200211))
- if_alloc_sadl(sc->ifp);
-# endif
-
/* Attach Berkeley Packet Filter. */
LMC_BPF_ATTACH(DLT_RAW, 0);
-# ifdef __OpenBSD__
- /* Initialize ifmedia mechanism. */
- ifmedia_init(&sc->ifm, IFM_OMASK | IFM_GMASK | IFM_IMASK,
- ifmedia_change, ifmedia_status);
- if (sc->status.card_type == TLP_CSID_T3)
- {
- ifmedia_add(&sc->ifm, IFM_TDM | IFM_TDM_T3, 0, NULL);
- ifmedia_add(&sc->ifm, IFM_TDM | IFM_TDM_T3_M13, 0, NULL);
- ifmedia_set(&sc->ifm, IFM_TDM | IFM_TDM_T3);
- }
- else if (sc->status.card_type == TLP_CSID_T1E1)
- {
- ifmedia_add(&sc->ifm, IFM_TDM | IFM_TDM_T1, 0, NULL);
- ifmedia_add(&sc->ifm, IFM_TDM | IFM_TDM_T1_AMI, 0, NULL);
- ifmedia_add(&sc->ifm, IFM_TDM | IFM_TDM_E1, 0, NULL);
- ifmedia_add(&sc->ifm, IFM_TDM | IFM_TDM_E1_G704, 0, NULL);
- ifmedia_set(&sc->ifm, IFM_TDM | IFM_TDM_T1);
- }
- else if ((sc->status.card_type == TLP_CSID_HSSI) ||
- (sc->status.card_type == TLP_CSID_SSI))
- {
- ifmedia_add(&sc->ifm, IFM_TDM | IFM_NONE, 0, NULL);
- ifmedia_set(&sc->ifm, IFM_TDM | IFM_NONE);
- }
-# endif /* __OpenBSD__ */
-
callout_reset(&sc->callout, hz, lmc_watchdog, sc);
return 0;
@@ -4928,11 +3858,8 @@ lmc_ifnet_attach(softc_t *sc)
static void
lmc_ifnet_detach(softc_t *sc)
{
-# ifdef __OpenBSD__
- ifmedia_delete_instance(&sc->ifm, IFM_INST_ANY);
-# endif
-# if (defined(__FreeBSD__) && defined(DEVICE_POLLING))
+# if defined(DEVICE_POLLING)
if (sc->ifp->if_capenable & IFCAP_POLLING)
ether_poll_deregister(sc->ifp);
# endif
@@ -4940,28 +3867,15 @@ lmc_ifnet_detach(softc_t *sc)
/* Detach Berkeley Packet Filter. */
LMC_BPF_DETACH;
-# if ((defined(__NetBSD__) && __NetBSD_Version__ >= 106000000) || \
- (defined(__OpenBSD__) && OpenBSD >= 200211))
- if_free_sadl(sc->ifp);
-# endif
-
/* Detach from the ifnet kernel interface. */
if_detach(sc->ifp);
-# if (defined(__FreeBSD__) && __FreeBSD_version >= 800082)
if_free(sc->ifp);
-# elif (defined(__FreeBSD__) && __FreeBSD_version >= 600000)
- if_free_type(sc->ifp, NSPPP ? IFT_PPP : IFT_OTHER);
-# endif
}
-#endif /* IFNET */
#if NETGRAPH
-/* Netgraph changed significantly between FreeBSD-4 and -5. */
-/* These are backward compatibility hacks for FreeBSD-4. */
-# if (__FreeBSD_version >= 500000)
/* These next two macros should be added to netgraph */
# define NG_TYPE_REF(type) atomic_add_int(&(type)->refs, 1)
# define NG_TYPE_UNREF(type) \
@@ -4971,39 +3885,16 @@ do { \
else \
atomic_subtract_int(&(type)->refs, 1); \
} while (0)
-# else /* FreeBSD-4 */
-# define NGI_GET_MSG(item, msg) /* nothing */
-# define NG_HOOK_FORCE_QUEUE(hook) /* nothing */
-# define NG_TYPE_REF(type) atomic_add_int(&(type)->refs, 1)
-# define NG_TYPE_UNREF(type) \
-do { \
- if ((type)->refs == 1) \
- LIST_REMOVE(type, types); \
- else \
- atomic_subtract_int(&(type)->refs, 1); \
- } while (0)
-# endif
/* It is an error to construct new copies of this Netgraph node. */
/* All instances are constructed by ng_attach and are persistent. */
-# if (__FreeBSD_version >= 500000)
static int ng_constructor(node_p node) { return EINVAL; }
-# else /* FreeBSD-4 */
-static int ng_constructor(node_p *node) { return EINVAL; }
-# endif
/* Incoming Netgraph control message. */
-# if (__FreeBSD_version >= 500000)
static int
ng_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
struct ng_mesg *msg;
-# else /* FreeBSD-4 */
-static int
-ng_rcvmsg(node_p node, struct ng_mesg *msg,
- const char *retaddr, struct ng_mesg **rptr)
- {
-# endif
struct ng_mesg *resp = NULL;
softc_t *sc = NG_NODE_PRIVATE(node);
int error = 0;
@@ -5073,16 +3964,8 @@ ng_rcvmsg(node_p node, struct ng_mesg *msg,
error = EINVAL;
/* Handle synchronous response. */
-# if (__FreeBSD_version >= 500000)
NG_RESPOND_MSG(error, node, item, resp);
NG_FREE_MSG(msg);
-# else /* FreeBSD-4 */
- if (rptr != NULL)
- *rptr = resp;
- else if (resp != NULL)
- free(resp, M_NETGRAPH);
- free(msg, M_NETGRAPH);
-# endif
return error;
}
@@ -5091,14 +3974,9 @@ ng_rcvmsg(node_p node, struct ng_mesg *msg,
static int
ng_shutdown(node_p node)
{
-# if (__FreeBSD_version >= 500000)
/* unless told to really die, bounce back to life */
if ((node->nd_flags & NG_REALLY_DIE)==0)
node->nd_flags &= ~NG_INVALID; /* bounce back to life */
-# else /* FreeBSD-4 */
- ng_cutlinks(node);
- node->flags &= ~NG_INVALID; /* bounce back to life */
-# endif
return 0;
}
@@ -5135,7 +4013,6 @@ ng_connect(hook_p hook)
/* Transmit an mbuf-chain on the communication link. */
/* This procedure is very similar to lmc_raw_output(). */
/* Called from a syscall (user context; no spinlocks). */
-# if (__FreeBSD_version >= 500000)
static int
ng_rcvdata(hook_p hook, item_p item)
{
@@ -5147,13 +4024,6 @@ ng_rcvdata(hook_p hook, item_p item)
NGI_GET_M(item, m);
NGI_GET_META(item, meta);
NG_FREE_ITEM(item);
-# else /* FreeBSD-4 */
-static int
-ng_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
- {
- softc_t *sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
- int error = 0;
-# endif
/* This macro must not store into meta! */
NG_FREE_META(meta);
@@ -5173,17 +4043,10 @@ ng_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
/* Some BSD QUEUE routines are not interrupt-safe. */
{
DISABLE_INTR;
-# if (__FreeBSD_version >= 503000)
if (meta==NULL)
IFQ_ENQUEUE(&sc->ng_sndq, m, error);
else
IFQ_ENQUEUE(&sc->ng_fastq, m, error);
-# else
- if (meta==NULL)
- IFQ_ENQUEUE(&sc->ng_sndq, m, NULL, error);
- else
- IFQ_ENQUEUE(&sc->ng_fastq, m, NULL, error);
-# endif
ENABLE_INTR;
}
@@ -5222,38 +4085,15 @@ struct ng_type ng_type =
.mod_event = NULL,
.constructor = ng_constructor,
.rcvmsg = ng_rcvmsg,
-# if (__FreeBSD_version >=503000)
.close = NULL,
-# endif
.shutdown = ng_shutdown,
.newhook = ng_newhook,
.findhook = NULL,
.connect = ng_connect,
.rcvdata = ng_rcvdata,
-# if (defined(__FreeBSD__) && (__FreeBSD_version < 500000))
- .rcvdataq = ng_rcvdata,
-# endif
.disconnect = ng_disconnect,
};
-# if (IFNET == 0)
-/* Called from a softirq once a second. */
-static void
-ng_watchdog(void *arg)
- {
- softc_t *sc = arg;
-
- /* Call the core watchdog procedure. */
- core_watchdog(sc);
-
- /* Set line protocol and package status. */
- sc->status.line_pkg = PKG_NG;
- sc->status.line_prot = 0;
-
- /* Call this procedure again after one second. */
- callout_reset(&sc->callout, hz, ng_watchdog, sc);
- }
-# endif
/* Attach to the Netgraph kernel interface (/sys/netgraph).
* It is called once for each physical card during device attach.
@@ -5293,11 +4133,9 @@ ng_attach(softc_t *sc)
return error;
}
-# if (__FreeBSD_version >= 500000)
/* Initialize the send queue mutexes. */
mtx_init(&sc->ng_sndq.ifq_mtx, NAME_UNIT, "sndq", MTX_DEF);
mtx_init(&sc->ng_fastq.ifq_mtx, NAME_UNIT, "fastq", MTX_DEF);
-# endif
/* Put a backpointer to the softc in the netgraph node. */
NG_NODE_SET_PRIVATE(sc->ng_node, sc);
@@ -5308,10 +4146,6 @@ ng_attach(softc_t *sc)
IFQ_SET_MAXLEN(&sc->ng_sndq, SNDQ_MAXLEN);
IFQ_SET_READY(&sc->ng_sndq);
-# if (IFNET == 0)
- /* Arrange to call ng_watchdog() once a second. */
- callout_reset(&sc->callout, hz, ng_watchdog, sc);
-# endif
return 0;
}
@@ -5320,18 +4154,11 @@ static void
ng_detach(softc_t *sc)
{
callout_drain(&sc->callout);
-# if (__FreeBSD_version >= 500000)
mtx_destroy(&sc->ng_sndq.ifq_mtx);
mtx_destroy(&sc->ng_fastq.ifq_mtx);
ng_rmnode_self(sc->ng_node); /* free hook */
NG_NODE_UNREF(sc->ng_node); /* free node */
NG_TYPE_UNREF(&ng_type);
-# else /* FreeBSD-4 */
- ng_unname(sc->ng_node); /* free name */
- ng_cutlinks(sc->ng_node); /* free hook */
- NG_NODE_UNREF(sc->ng_node); /* free node */
- NG_TYPE_UNREF(&ng_type);
-# endif
}
#endif /* NETGRAPH */
@@ -5491,21 +4318,15 @@ attach_card(softc_t *sc, const char *intrstr)
/* Start the card. */
if ((error = startup_card(sc))) return error;
-# if (__FreeBSD_version >= 500000)
callout_init(&sc->callout, 0);
-# else /* FreeBSD-4 */
- callout_init(&sc->callout);
-# endif
/* Attach a kernel interface. */
#if NETGRAPH
if ((error = ng_attach(sc))) return error;
sc->flags |= FLAG_NETGRAPH;
#endif
-#if IFNET
if ((error = lmc_ifnet_attach(sc))) return error;
sc->flags |= FLAG_IFNET;
-#endif
/* Attach a line protocol stack. */
sc->config.line_pkg = PKG_RAWIP;
@@ -5572,14 +4393,12 @@ detach_card(softc_t *sc)
sc->flags &= ~FLAG_NETGRAPH;
}
#endif
-#if IFNET
if (sc->flags & FLAG_IFNET)
{
IFQ_PURGE(&sc->ifp->if_snd);
lmc_ifnet_detach(sc);
sc->flags &= ~FLAG_IFNET;
}
-#endif
/* Reset the Tulip chip; stops DMA and Interrupts. */
shutdown_card(sc);
@@ -5587,7 +4406,6 @@ detach_card(softc_t *sc)
/* This is the I/O configuration interface for FreeBSD */
-#ifdef __FreeBSD__
static int
fbsd_probe(device_t dev)
@@ -5643,10 +4461,8 @@ fbsd_detach(device_t dev)
sc->csr_res = NULL;
}
-# if (__FreeBSD_version >= 500000)
mtx_destroy(&sc->top_mtx);
mtx_destroy(&sc->bottom_mtx);
-# endif
return 0; /* no error */
}
@@ -5723,11 +4539,9 @@ fbsd_attach(device_t dev)
return error;
}
-# if (__FreeBSD_version >= 500000)
/* Initialize the top-half and bottom-half locks. */
mtx_init(&sc->top_mtx, NAME_UNIT, "top half lock", MTX_DEF);
mtx_init(&sc->bottom_mtx, NAME_UNIT, "bottom half lock", MTX_DEF);
-# endif
/* Start the card and attach a kernel interface and line protocol. */
if ((error = attach_card(sc, ""))) detach_card(sc);
@@ -5748,11 +4562,7 @@ static driver_t driver =
{
.name = DEVICE_NAME,
.methods = methods,
-# if (__FreeBSD_version >= 500000)
.size = sizeof(softc_t),
-# else /* FreeBSD-4 */
- .softc = sizeof(softc_t),
-# endif
};
static devclass_t devclass;
@@ -5767,1281 +4577,13 @@ MODULE_DEPEND(lmc, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION);
MODULE_DEPEND(lmc, sppp, 1, 1, 1);
# endif
-#endif /* __FreeBSD__ */
/* This is the I/O configuration interface for NetBSD. */
-#ifdef __NetBSD__
-
-static int
-nbsd_match(struct device *parent, struct cfdata *match, void *aux)
- {
- struct pci_attach_args *pa = aux;
- u_int32_t cfid = pci_conf_read(pa->pa_pc, pa->pa_tag, TLP_CFID);
- u_int32_t csid = pci_conf_read(pa->pa_pc, pa->pa_tag, TLP_CSID);
-
- /* Looking for a DEC 21140A chip on any Lan Media Corp card. */
- if (cfid != TLP_CFID_TULIP) return 0;
- switch (csid)
- {
- case TLP_CSID_HSSI:
- case TLP_CSID_HSSIc:
- case TLP_CSID_T3:
- case TLP_CSID_SSI:
- case TLP_CSID_T1E1:
- return 100;
- default:
- return 0;
- }
- }
-
-static int
-nbsd_detach(struct device *self, int flags)
- {
- softc_t *sc = (softc_t *)self; /* device is first in softc */
-
- /* Stop the card and detach from the kernel. */
- detach_card(sc);
-
- /* Release resources. */
- if (sc->sdh_cookie != NULL)
- {
- shutdownhook_disestablish(sc->sdh_cookie);
- sc->sdh_cookie = NULL;
- }
- if (sc->irq_cookie != NULL)
- {
- pci_intr_disestablish(sc->pa_pc, sc->irq_cookie);
- sc->irq_cookie = NULL;
- }
- if (sc->csr_handle)
- {
- bus_space_unmap(sc->csr_tag, sc->csr_handle, TLP_CSR_SIZE);
- sc->csr_handle = 0;
- }
-
- return 0; /* no error */
- }
-
-static void
-nbsd_attach(struct device *parent, struct device *self, void *aux)
- {
- softc_t *sc = (softc_t *)self; /* device is first in softc */
- struct pci_attach_args *pa = aux;
- const char *intrstr;
- bus_addr_t csr_addr;
- int error;
-
- /* READ/WRITE_PCI_CFG need these. */
- sc->pa_pc = pa->pa_pc;
- sc->pa_tag = pa->pa_tag;
- /* bus_dma needs this. */
- sc->pa_dmat = pa->pa_dmat;
-
- /* What kind of card are we driving? */
- switch (READ_PCI_CFG(sc, TLP_CSID))
- {
- case TLP_CSID_HSSI:
- case TLP_CSID_HSSIc:
- sc->dev_desc = HSSI_DESC;
- sc->card = &hssi_card;
- break;
- case TLP_CSID_T3:
- sc->dev_desc = T3_DESC;
- sc->card = &t3_card;
- break;
- case TLP_CSID_SSI:
- sc->dev_desc = SSI_DESC;
- sc->card = &ssi_card;
- break;
- case TLP_CSID_T1E1:
- sc->dev_desc = T1E1_DESC;
- sc->card = &t1_card;
- break;
- default:
- return;
- }
- printf(": %s\n", sc->dev_desc);
-
- /* Allocate PCI resources to access the Tulip chip CSRs. */
-# if IOREF_CSR
- csr_addr = (bus_addr_t)READ_PCI_CFG(sc, TLP_CBIO) & -2;
- sc->csr_tag = pa->pa_iot; /* bus_space tag for IO refs */
-# else
- csr_addr = (bus_addr_t)READ_PCI_CFG(sc, TLP_CBMA);
- sc->csr_tag = pa->pa_memt; /* bus_space tag for MEM refs */
-# endif
- if ((error = bus_space_map(sc->csr_tag, csr_addr,
- TLP_CSR_SIZE, 0, &sc->csr_handle)))
- {
- printf("%s: bus_space_map() failed; error %d\n", NAME_UNIT, error);
- return;
- }
-
- /* Allocate PCI interrupt resources. */
- if ((error = pci_intr_map(pa, &sc->intr_handle)))
- {
- printf("%s: pci_intr_map() failed; error %d\n", NAME_UNIT, error);
- nbsd_detach(self, 0);
- return;
- }
- sc->irq_cookie = pci_intr_establish(pa->pa_pc, sc->intr_handle,
- IPL_NET, bsd_interrupt, sc);
- if (sc->irq_cookie == NULL)
- {
- printf("%s: pci_intr_establish() failed\n", NAME_UNIT);
- nbsd_detach(self, 0);
- return;
- }
- intrstr = pci_intr_string(pa->pa_pc, sc->intr_handle);
-
- /* Install a shutdown hook. */
- sc->sdh_cookie = shutdownhook_establish(shutdown_card, sc);
- if (sc->sdh_cookie == NULL)
- {
- printf("%s: shutdown_hook_establish() failed\n", NAME_UNIT);
- nbsd_detach(self, 0);
- return;
- }
-
- /* Initialize the top-half and bottom-half locks. */
- simple_lock_init(&sc->top_lock);
- simple_lock_init(&sc->bottom_lock);
-
- /* Start the card and attach a kernel interface and line protocol. */
- if ((error = attach_card(sc, intrstr))) detach_card(sc);
- }
-
-# if (__NetBSD_Version__ >= 106080000) /* 1.6H */
-CFATTACH_DECL(lmc, sizeof(softc_t),
- nbsd_match, nbsd_attach, nbsd_detach, NULL);
-# else
-struct cfattach lmc_ca =
- {
-/*.ca_name = DEVICE_NAME, */
- .ca_devsize = sizeof(softc_t),
- .ca_match = nbsd_match,
- .ca_attach = nbsd_attach,
- .ca_detach = nbsd_detach,
- .ca_activate = NULL,
- };
-# endif
-
-# if (__NetBSD_Version__ >= 106080000)
-CFDRIVER_DECL(lmc, DV_IFNET, NULL);
-# else
-static struct cfdriver lmc_cd =
- {
- .cd_name = DEVICE_NAME,
- .cd_class = DV_IFNET,
- .cd_ndevs = 0,
- .cd_devs = NULL,
- };
-# endif
-
-/* cfdata is declared static, unseen outside this module. */
-/* It is used for LKM; config builds its own in ioconf.c. */
-static struct cfdata lmc_cf =
- {
-# if (__NetBSD_Version__ >= 106080000)
- .cf_name = DEVICE_NAME,
- .cf_atname = DEVICE_NAME,
-# else
- .cf_driver = &lmc_cd,
- .cf_attach = &lmc_ca,
-# endif
- .cf_unit = 0,
- .cf_fstate = FSTATE_STAR,
- };
-
-# if (__NetBSD_Version__ >= 106080000)
-MOD_MISC(DEVICE_NAME)
-# else
-static struct lkm_misc _module =
- {
- .lkm_name = DEVICE_NAME,
- .lkm_type = LM_MISC,
- .lkm_offset = 0,
- .lkm_ver = LKM_VERSION,
- };
-# endif
-
-/* From /sys/dev/pci/pci.c (no public prototype). */
-int pciprint(void *, const char *);
-
-static int lkm_nbsd_match(struct pci_attach_args *pa)
- { return nbsd_match(0, 0, pa); }
-
-/* LKM loader finds this by appending "_lkmentry" to filename "if_lmc". */
-int if_lmc_lkmentry(struct lkm_table *lkmtp, int cmd, int ver)
- {
- int i, error = 0;
-
- if (ver != LKM_VERSION) return EINVAL;
- switch (cmd)
- {
- case LKM_E_LOAD:
- {
- struct cfdriver* pcicd;
-
- lkmtp->private.lkm_misc = &_module;
- if ((pcicd = config_cfdriver_lookup("pci")) == NULL)
- {
- printf("%s: config_cfdriver_lookup(pci) failed; error %d\n",
- lmc_cd.cd_name, error);
- return error;
- }
-# if (__NetBSD_Version__ >= 106080000)
- if ((error = config_cfdriver_attach(&lmc_cd)))
- {
- printf("%s: config_cfdriver_attach() failed; error %d\n",
- lmc_cd.cd_name, error);
- return error;
- }
- if ((error = config_cfattach_attach(lmc_cd.cd_name, &lmc_ca)))
- {
- printf("%s: config_cfattach_attach() failed; error %d\n",
- lmc_cd.cd_name, error);
- config_cfdriver_detach(&lmc_cd);
- return error;
- }
-# endif
- for (i=0; i<pcicd->cd_ndevs; i++)
- {
- int dev;
- /* A pointer to a device is a pointer to its softc. */
- struct pci_softc *sc = pcicd->cd_devs[i];
- if (sc == NULL) continue;
- for (dev=0; dev<sc->sc_maxndevs; dev++)
- {
- struct pci_attach_args pa;
- pcitag_t tag = pci_make_tag(sc->sc_pc, sc->sc_bus, dev, 0);
- if (pci_probe_device(sc, tag, lkm_nbsd_match, &pa) != 0)
- config_attach(pcicd->cd_devs[i], &lmc_cf, &pa, pciprint);
- /* config_attach doesn't return on failure; it calls panic. */
- }
- }
- break;
- }
- case LKM_E_UNLOAD:
- {
- for (i=lmc_cd.cd_ndevs-1; i>=0; i--)
- {
- struct device *dev = lmc_cd.cd_devs[i];
- if (dev == NULL) continue;
- if ((error = config_detach(dev, 0)))
- {
- printf("%s: config_detach() failed; error %d\n",
- dev->dv_xname, error);
- return error;
- }
- }
-# if (__NetBSD_Version__ >= 106080000)
- if ((error = config_cfattach_detach(lmc_cd.cd_name, &lmc_ca)))
- {
- printf("%s: config_cfattach_detach() failed; error %d\n",
- lmc_cd.cd_name, error);
- return error;
- }
- if ((error = config_cfdriver_detach(&lmc_cd)))
- {
- printf("%s: config_cfdriver_detach() failed; error %d\n",
- lmc_cd.cd_name, error);
- return error;
- }
-# endif
- break;
- }
- case LKM_E_STAT:
- break;
- }
-
- return error;
- }
-
-#endif /* __NetBSD__ */
/* This is the I/O configuration interface for OpenBSD. */
-#ifdef __OpenBSD__
-
-static int
-obsd_match(struct device *parent, void *match, void *aux)
- {
- struct pci_attach_args *pa = aux;
- u_int32_t cfid = pci_conf_read(pa->pa_pc, pa->pa_tag, TLP_CFID);
- u_int32_t csid = pci_conf_read(pa->pa_pc, pa->pa_tag, TLP_CSID);
-
- /* Looking for a DEC 21140A chip on any Lan Media Corp card. */
- if (cfid != TLP_CFID_TULIP) return 0;
- switch (csid)
- {
- case TLP_CSID_HSSI:
- case TLP_CSID_HSSIc:
- case TLP_CSID_T3:
- case TLP_CSID_SSI:
- case TLP_CSID_T1E1:
- return 100; /* match better than other 21140 drivers */
- default:
- return 0;
- }
- }
-
-static int
-obsd_detach(struct device *self, int flags)
- {
- softc_t *sc = (softc_t *)self; /* device is first in softc */
-
- /* Stop the card and detach from the kernel. */
- detach_card(sc);
-
- /* Release resources. */
- if (sc->sdh_cookie != NULL)
- {
- shutdownhook_disestablish(sc->sdh_cookie);
- sc->sdh_cookie = NULL;
- }
- if (sc->irq_cookie != NULL)
- {
- pci_intr_disestablish(sc->pa_pc, sc->irq_cookie);
- sc->irq_cookie = NULL;
- }
- if (sc->csr_handle)
- {
- bus_space_unmap(sc->csr_tag, sc->csr_handle, TLP_CSR_SIZE);
- sc->csr_handle = 0;
- }
-
- return 0; /* no error */
- }
-
-static void
-obsd_attach(struct device *parent, struct device *self, void *aux)
- {
- softc_t *sc = (softc_t *)self; /* device is first in softc */
- struct pci_attach_args *pa = aux;
- const char *intrstr;
- bus_addr_t csr_addr;
- int error;
-
- /* READ/WRITE_PCI_CFG need these. */
- sc->pa_pc = pa->pa_pc;
- sc->pa_tag = pa->pa_tag;
- /* bus_dma needs this. */
- sc->pa_dmat = pa->pa_dmat;
-
- /* What kind of card are we driving? */
- switch (READ_PCI_CFG(sc, TLP_CSID))
- {
- case TLP_CSID_HSSI:
- case TLP_CSID_HSSIc:
- sc->dev_desc = HSSI_DESC;
- sc->card = &hssi_card;
- break;
- case TLP_CSID_T3:
- sc->dev_desc = T3_DESC;
- sc->card = &t3_card;
- break;
- case TLP_CSID_SSI:
- sc->dev_desc = SSI_DESC;
- sc->card = &ssi_card;
- break;
- case TLP_CSID_T1E1:
- sc->dev_desc = T1E1_DESC;
- sc->card = &t1_card;
- break;
- default:
- return;
- }
- printf(": %s\n", sc->dev_desc);
-
- /* Allocate PCI resources to access the Tulip chip CSRs. */
-# if IOREF_CSR
- csr_addr = (bus_addr_t)READ_PCI_CFG(sc, TLP_CBIO) & -2;
- sc->csr_tag = pa->pa_iot; /* bus_space tag for IO refs */
-# else
- csr_addr = (bus_addr_t)READ_PCI_CFG(sc, TLP_CBMA);
- sc->csr_tag = pa->pa_memt; /* bus_space tag for MEM refs */
-# endif
- if ((error = bus_space_map(sc->csr_tag, csr_addr,
- TLP_CSR_SIZE, 0, &sc->csr_handle)))
- {
- printf("%s: bus_space_map() failed; error %d\n", NAME_UNIT, error);
- return;
- }
-
- /* Allocate PCI interrupt resources. */
- if ((error = pci_intr_map(pa, &sc->intr_handle)))
- {
- printf("%s: pci_intr_map() failed; error %d\n", NAME_UNIT, error);
- obsd_detach(self, 0);
- return;
- }
- sc->irq_cookie = pci_intr_establish(pa->pa_pc, sc->intr_handle,
- IPL_NET, bsd_interrupt, sc, self->dv_xname);
- if (sc->irq_cookie == NULL)
- {
- printf("%s: pci_intr_establish() failed\n", NAME_UNIT);
- obsd_detach(self, 0);
- return;
- }
- intrstr = pci_intr_string(pa->pa_pc, sc->intr_handle);
-
- /* Install a shutdown hook. */
- sc->sdh_cookie = shutdownhook_establish(shutdown_card, sc);
- if (sc->sdh_cookie == NULL)
- {
- printf("%s: shutdown_hook_establish() failed\n", NAME_UNIT);
- obsd_detach(self, 0);
- return;
- }
-
- /* Initialize the top-half and bottom-half locks. */
- simple_lock_init(&sc->top_lock);
- simple_lock_init(&sc->bottom_lock);
-
- /* Start the card and attach a kernel interface and line protocol. */
- if ((error = attach_card(sc, intrstr))) detach_card(sc);
- }
-
-struct cfattach lmc_ca =
- {
- .ca_devsize = sizeof(softc_t),
- .ca_match = obsd_match,
- .ca_attach = obsd_attach,
- .ca_detach = obsd_detach,
- .ca_activate = NULL,
- };
-
-struct cfdriver lmc_cd =
- {
- .cd_name = DEVICE_NAME,
- .cd_devs = NULL,
- .cd_class = DV_IFNET,
- .cd_indirect = 0,
- .cd_ndevs = 0,
- };
-
-/* cfdata is declared static, unseen outside this module. */
-/* It is used for LKM; config builds its own in ioconf.c. */
-static struct cfdata lmc_cfdata =
- {
- .cf_attach = &lmc_ca,
- .cf_driver = &lmc_cd,
- .cf_unit = 0,
- .cf_fstate = FSTATE_STAR,
- };
-
-static struct lkm_any _module =
- {
- .lkm_name = DEVICE_NAME,
- .lkm_type = LM_MISC,
- .lkm_offset = 0,
- .lkm_ver = LKM_VERSION,
- };
-
-/* From /sys/dev/pci/pci.c (no public prototype). */
-int pciprint(void *, const char *);
-
-extern struct cfdriver pci_cd;
-
-/* LKM loader finds this by appending "_lkmentry" to filename "if_lmc". */
-int if_lmc_lkmentry(struct lkm_table *lkmtp, int cmd, int ver)
- {
- int i, error = 0;
-
- if (ver != LKM_VERSION) return EINVAL;
- switch (cmd)
- {
- case LKM_E_LOAD:
- { /* XXX This works for ONE card on pci0 of a i386 machine! XXX */
- lkmtp->private.lkm_any = &_module;
- for (i=0; i<pci_cd.cd_ndevs; i++)
- {
- struct pci_attach_args pa;
- struct device *parent = pci_cd.cd_devs[i];
- if (parent == NULL) continue; /* dead clone? */
- if ((parent->dv_unit)!=0) continue; /* only bus zero */
- /* XXX For machine independence, need: pcibus_attach_args. XXX */
- /* XXX See NetBSD's sys/dev/pci/pci.c/pci_probe_device. XXX */
- /* XXX Why isn't there an LKM network interface module? XXX */
- pa.pa_pc = NULL; /* XXX */
- pa.pa_bus = 0; /* XXX */
- pa.pa_iot = X86_BUS_SPACE_IO; /* XXX */
- pa.pa_memt = X86_BUS_SPACE_MEM; /* XXX */
- pa.pa_dmat = &pci_bus_dma_tag; /* XXX */
- for (pa.pa_device=0; pa.pa_device<32; pa.pa_device++) /* XXX */
- {
- int intr;
- pa.pa_function = 0; /* DEC-21140A has function 0 only XXX */
- pa.pa_tag = pci_make_tag(pa.pa_pc, pa.pa_bus, pa.pa_device, 0);
- pa.pa_id = pci_conf_read(pa.pa_pc, pa.pa_tag, PCI_ID_REG);
- if ((pa.pa_id & 0xFFFF) == 0xFFFF) continue;
- if ((pa.pa_id & 0xFFFF) == 0) continue;
- /* XXX this only works for pci0 -- no swizzelling XXX */
- pa.pa_intrswiz = 0;
- pa.pa_intrtag = pa.pa_tag;
- intr = pci_conf_read(pa.pa_pc, pa.pa_tag, PCI_INTERRUPT_REG);
- pa.pa_intrline = PCI_INTERRUPT_LINE(intr);
- pa.pa_intrpin = ((PCI_INTERRUPT_PIN(intr) -1) % 4) +1;
- if (obsd_match(parent, &lmc_cfdata, &pa))
- config_attach(parent, &lmc_cfdata, &pa, pciprint);
- /* config_attach doesn't return on failure; it calls panic. */
- }
- }
- break;
- }
- case LKM_E_UNLOAD:
- {
- for (i=lmc_cd.cd_ndevs-1; i>=0; i--)
- {
- struct device *dev = lmc_cd.cd_devs[i];
- if (dev == NULL) continue;
- if ((error = config_detach(dev, 0)))
- printf("%s: config_detach() failed; error %d\n", dev->dv_xname, error);
- }
- break;
- }
- case LKM_E_STAT:
- break;
- }
-
- return error;
- }
-
-#endif /* __OpenBSD__ */
/* This is the I/O configuration interface for BSD/OS. */
-#ifdef __bsdi__
-
-static int
-bsdi_match(pci_devaddr_t *pa)
- {
- u_int32_t cfid = pci_inl(pa, TLP_CFID);
- u_int32_t csid = pci_inl(pa, TLP_CSID);
-
- /* Looking for a DEC 21140A chip on any Lan Media Corp card. */
- if (cfid != TLP_CFID_TULIP) return 0;
- switch (csid)
- {
- case TLP_CSID_HSSI:
- case TLP_CSID_HSSIc:
- case TLP_CSID_T3:
- case TLP_CSID_SSI:
- case TLP_CSID_T1E1:
- return 1;
- default:
- return 0;
- }
- }
-
-static int
-bsdi_probe(struct device *parent, struct cfdata *cf, void *aux)
- {
- struct isa_attach_args *ia = aux;
- pci_devaddr_t *pa = NULL;
- pci_devres_t res;
-
- /* This must be a PCI bus. */
- if (ia->ia_bustype != BUS_PCI) return 0;
-
- /* Scan PCI bus for our boards. */
- if ((pa = pci_scan(bsdi_match)) == 0) return 0;
-
- /* Scan config space for IO and MEM base registers and IRQ info. */
- pci_getres(pa, &res, 1, ia);
-
- /* Crucial: pass pci_devaddr to bsdi_attach in ia_aux. */
- ia->ia_aux = (void *)pa;
-
- return 1;
- }
-
-static void
-bsdi_attach(struct device *parent, struct device *self, void *aux)
- {
- softc_t *sc = (softc_t *)self; /* device is first in softc */
- struct isa_attach_args *ia = aux;
- pci_devaddr_t *pa = ia->ia_aux; /* this is crucial! */
- int error;
-
- /* READ/WRITE_PCI_CFG need this. */
- sc->cfgbase = *pa;
-
- /* What kind of card are we driving? */
- switch (READ_PCI_CFG(sc, TLP_CSID))
- {
- case TLP_CSID_HSSI:
- case TLP_CSID_HSSIc:
- sc->dev_desc = HSSI_DESC;
- sc->card = &hssi_card;
- break;
- case TLP_CSID_T3:
- sc->dev_desc = T3_DESC;
- sc->card = &t3_card;
- break;
- case TLP_CSID_SSI:
- sc->dev_desc = SSI_DESC;
- sc->card = &ssi_card;
- break;
- case TLP_CSID_T1E1:
- sc->dev_desc = T1E1_DESC;
- sc->card = &t1_card;
- break;
- default:
- return;
- }
- printf(": %s\n", sc->dev_desc);
-
- /* Allocate PCI memory or IO resources to access the Tulip chip CSRs. */
- sc->csr_iobase = ia->ia_iobase;
- sc->csr_membase = (u_int32_t *)mapphys((vm_offset_t)ia->ia_maddr, TLP_CSR_SIZE);
-
- /* Attach to the PCI bus. */
- isa_establish(&sc->id, &sc->dev);
-
- /* Allocate PCI interrupt resources for the card. */
- sc->ih.ih_fun = bsd_interrupt;
- sc->ih.ih_arg = sc;
- intr_establish(ia->ia_irq, &sc->ih, DV_NET);
-
- /* Install a shutdown hook. */
- sc->ats.func = shutdown_card;
- sc->ats.arg = sc;
- atshutdown(&sc->ats, ATSH_ADD);
-
- /* Initialize the top-half and bottom-half locks. */
- simple_lock_init(&sc->top_lock);
- simple_lock_init(&sc->bottom_lock);
-
- /* Start the card and attach a kernel interface and line protocol. */
- if ((error = attach_card(sc, ""))) detach_card(sc);
- }
-
-struct cfdriver lmccd =
- {
- .cd_devs = NULL,
- .cd_name = DEVICE_NAME,
- .cd_match = bsdi_probe,
- .cd_attach = bsdi_attach,
- .cd_class = DV_IFNET,
- .cd_devsize = sizeof(softc_t),
- };
-#endif /* __bsdi__ */
-
-#ifdef __linux__
-
-/* The kernel calls this procedure when an interrupt happens. */
-static irqreturn_t
-linux_interrupt(int irq, void *dev, struct pt_regs *regs)
- {
- struct net_device *net_dev = dev;
- softc_t *sc = dev_to_hdlc(net_dev)->priv;
-
- /* Cut losses early if this is not our interrupt. */
- if ((READ_CSR(TLP_STATUS) & TLP_INT_TXRX) == 0)
- return IRQ_NONE;
-
- /* Disable card interrupts. */
- WRITE_CSR(TLP_INT_ENBL, TLP_INT_DISABLE);
-
- /* Handle the card interrupt with the dev->poll method. */
- if (netif_rx_schedule_prep(net_dev))
- __netif_rx_schedule(net_dev); /* NAPI - add to poll list */
- else
- printk("%s: interrupt while on poll list\n", NAME_UNIT);
-
- return IRQ_HANDLED;
- }
-
-/* This net_device method services interrupts in a softirq. */
-/* With rxintr_cleanup(), it implements input flow control. */
-static int
-linux_poll(struct net_device *net_dev, int *budget)
- {
- softc_t *sc = dev_to_hdlc(net_dev)->priv;
- int received;
-
- /* Yes, we do NAPI. */
- /* Allow processing up to net_dev->quota incoming packets. */
- /* This is the ONLY time core_interrupt() may process rx pkts. */
- /* Otherwise (sc->quota == 0) and rxintr_cleanup() is a NOOP. */
- sc->quota = net_dev->quota;
-
- /* Handle the card interrupt with kernel ints enabled. */
- /* Process rx pkts (and tx pkts, too). */
- /* Card interrupts are disabled. */
- core_interrupt(sc, 0);
-
- /* Report number of rx packets processed. */
- received = net_dev->quota - sc->quota;
- net_dev->quota -= received;
- *budget -= received;
-
- /* if quota prevented processing all rx pkts, leave rx ints disabled */
- if (sc->quota == 0) /* this is off by one...but harmless */
- {
- WRITE_CSR(TLP_INT_ENBL, TLP_INT_TX);
- return 1; /* more pkts to handle -- reschedule */
- }
-
- sc->quota = 0; /* disable rx pkt processing by rxintr_cleanup() */
- netif_rx_complete(net_dev); /* NAPI - remove from poll list */
-
- /* Enable card interrupts. */
- WRITE_CSR(TLP_INT_ENBL, TLP_INT_TXRX);
- return 0;
- }
-
-/* These next routines are similar to BSD's ifnet kernel/driver interface. */
-
-/* This net_device method hands outgoing packets to the transmitter. */
-/* With txintr_setup(), it implements output flow control. */
-/* Called from a syscall (user context; no spinlocks). */
-static int
-linux_start(struct sk_buff *skb, struct net_device *net_dev)
- {
- softc_t *sc = dev_to_hdlc(net_dev)->priv;
-
- if (sc->tx_skb == NULL)
- {
- /* Put this skb where the transmitter will see it. */
- sc->tx_skb = skb;
-
- /* Start the transmitter; incoming pkts are NOT processed. */
- user_interrupt(sc, 0);
-
- /* If the tx didn't take the skb then stop the queue. */
- /* This can happen if another CPU is in core_interrupt(). */
- if (sc->tx_skb != NULL) netif_stop_queue(net_dev);
-
- return 0;
- }
-
- /* This shouldn't happen; skb is NOT consumed. */
- if (netif_queue_stopped(net_dev))
- printk("%s: dev->start() called with queue stopped\n", NAME_UNIT);
- else
- netif_stop_queue(net_dev);
-
- return 1;
- }
-
-/* This net_device method restarts the transmitter if it hangs. */
-/* Called from a softirq. */
-static void
-linux_timeout(struct net_device *net_dev)
- {
- softc_t *sc = dev_to_hdlc(net_dev)->priv;
-
- /* Start the transmitter; incoming packets are NOT processed. */
- user_interrupt(sc, 1);
- }
-
-/* This net_device method handles IOCTL syscalls. */
-/* Called from a syscall (user context; no spinlocks; can sleep). */
-static int
-linux_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
- {
- softc_t *sc = dev_to_hdlc(net_dev)->priv;
- int error = 0;
-
- if ((cmd >= SIOCDEVPRIVATE) && (cmd <= SIOCDEVPRIVATE+15))
- {
- struct iohdr *iohdr = (struct iohdr *)ifr;
- u_int16_t direction = iohdr->direction;
- u_int16_t length = iohdr->length;
- char *user_addr = (char *)iohdr->iohdr;
- char *kern_addr;
-
- if (iohdr->cookie != NGM_LMC_COOKIE) return -EINVAL;
-
- /* Emulate a BSD-style IOCTL syscall. */
- kern_addr = kmalloc(length, GFP_KERNEL);
- if (kern_addr == NULL)
- error = -ENOMEM;
- if ((error == 0) && ((direction & DIR_IOW) != 0))
- error = copy_from_user(kern_addr, user_addr, length);
- if (error == 0)
- error = -core_ioctl(sc, (unsigned long)cmd, kern_addr);
- if ((error == 0) && ((direction & DIR_IOR) != 0))
- error = copy_to_user(user_addr, kern_addr, length);
- kfree(kern_addr);
- }
-# if GEN_HDLC
- else if (cmd == SIOCWANDEV)
- {
- const size_t size = sizeof(sync_serial_settings);
-
- switch (ifr->ifr_settings.type)
- {
- case IF_GET_IFACE: /* get interface config */
- {
- ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL;
- if (ifr->ifr_settings.size < size)
- {
- ifr->ifr_settings.size = size;
- error = -ENOBUFS;
- }
- else
- {
- if (sc->config.tx_clk_src == CFG_CLKMUX_ST)
- sc->hdlc_settings.clock_type = CLOCK_EXT;
- if (sc->config.tx_clk_src == CFG_CLKMUX_INT)
- sc->hdlc_settings.clock_type = CLOCK_TXINT;
- if (sc->config.tx_clk_src == CFG_CLKMUX_RT)
- sc->hdlc_settings.clock_type = CLOCK_TXFROMRX;
- sc->hdlc_settings.loopback = (sc->config.loop_back != CFG_LOOP_NONE) ? 1:0;
- sc->hdlc_settings.clock_rate = sc->status.tx_speed;
- error = copy_to_user(ifr->ifr_settings.ifs_ifsu.sync,
- &sc->hdlc_settings, size);
- }
- break;
- }
- case IF_IFACE_SYNC_SERIAL: /* set interface config */
- {
- if (!capable(CAP_NET_ADMIN))
- error = -EPERM;
- if (error == 0)
- error = copy_from_user(&sc->hdlc_settings,
- ifr->ifr_settings.ifs_ifsu.sync, size);
- /* hdlc_settings are currently ignored. */
- break;
- }
- default: /* Pass the rest to the line protocol code. */
- {
- error = hdlc_ioctl(net_dev, ifr, cmd);
- break;
- }
- }
- }
-# endif /* GEN_HDLC */
- else /* unknown IOCTL command */
- error = -EINVAL;
-
- if (DRIVER_DEBUG)
- printk("%s: linux_ioctl; cmd=0x%08x error=%d\n",
- NAME_UNIT, cmd, error);
-
- return error;
- }
-
-/* This net_device method returns a pointer to device statistics. */
-static struct net_device_stats *
-linux_stats(struct net_device *net_dev)
- {
-# if GEN_HDLC
- return &dev_to_hdlc(net_dev)->stats;
-# else
- softc_t *sc = net_dev->priv;
- return &sc->net_stats;
-# endif
- }
-
-/* Called from a softirq once a second. */
-static void
-linux_watchdog(unsigned long softc)
- {
- softc_t *sc = (softc_t *)softc;
- u_int8_t old_oper_status = sc->status.oper_status;
- struct event_cntrs *cntrs = &sc->status.cntrs;
- struct net_device_stats *stats = linux_stats(sc->net_dev);
-
- core_watchdog(sc); /* updates oper_status */
-
- /* Notice change in link status. */
- if ((old_oper_status != STATUS_UP) &&
- (sc->status.oper_status == STATUS_UP)) /* link came up */
- {
- hdlc_set_carrier(1, sc->net_dev);
- netif_wake_queue(sc->net_dev);
- }
- if ((old_oper_status == STATUS_UP) &&
- (sc->status.oper_status != STATUS_UP)) /* link went down */
- {
- hdlc_set_carrier(0, sc->net_dev);
- netif_stop_queue(sc->net_dev);
- }
-
- /* Notice change in line protocol. */
- if (sc->config.line_pkg == PKG_RAWIP)
- {
- sc->status.line_pkg = PKG_RAWIP;
- sc->status.line_prot = PROT_IP_HDLC;
- }
-# if GEN_HDLC
- else
- {
- sc->status.line_pkg = PKG_GEN_HDLC;
- switch (sc->hdlc_dev->proto.id)
- {
- case IF_PROTO_PPP:
- sc->status.line_prot = PROT_PPP;
- break;
- case IF_PROTO_CISCO:
- sc->status.line_prot = PROT_C_HDLC;
- break;
- case IF_PROTO_FR:
- sc->status.line_prot = PROT_FRM_RLY;
- break;
- case IF_PROTO_HDLC:
- sc->status.line_prot = PROT_IP_HDLC;
- break;
- case IF_PROTO_X25:
- sc->status.line_prot = PROT_X25;
- break;
- case IF_PROTO_HDLC_ETH:
- sc->status.line_prot = PROT_ETH_HDLC;
- break;
- default:
- sc->status.line_prot = 0;
- break;
- }
- }
-# endif /* GEN_HDLC */
-
- /* Copy statistics from sc to net_dev for get_stats(). */
- stats->rx_packets = cntrs->ipackets;
- stats->tx_packets = cntrs->opackets;
- stats->rx_bytes = cntrs->ibytes;
- stats->tx_bytes = cntrs->obytes;
- stats->rx_errors = cntrs->ierrors;
- stats->tx_errors = cntrs->oerrors;
- stats->rx_dropped = cntrs->idiscards;
- stats->tx_dropped = cntrs->odiscards;
- stats->rx_fifo_errors = cntrs->fifo_over;
- stats->tx_fifo_errors = cntrs->fifo_under;
- stats->rx_missed_errors = cntrs->missed;
- stats->rx_over_errors = cntrs->overruns;
-
- /* Call this procedure again after one second. */
- sc->wd_timer.expires = jiffies + HZ; /* now plus one second */
- add_timer(&sc->wd_timer);
- }
-
-/* This is the I/O configuration interface for Linux. */
-
-/* This net_device method is called when IFF_UP goes false. */
-static int
-linux_stop(struct net_device *net_dev)
- {
- softc_t *sc = dev_to_hdlc(net_dev)->priv;
-
- /* Stop the card and detach from the kernel. */
- detach_card(sc); /* doesn't fail */
-
- free_irq(net_dev->irq, net_dev); /* doesn't fail */
-
- del_timer(&sc->wd_timer); /* return value ignored */
-
- return 0;
- }
-
-/* This net_device method is called when IFF_UP goes true. */
-static int
-linux_open(struct net_device *net_dev)
- {
- softc_t *sc = dev_to_hdlc(net_dev)->priv;
- int error;
-
- /* Allocate PCI interrupt resources for the card. */
- if ((error = request_irq(net_dev->irq, &linux_interrupt, SA_SHIRQ,
- NAME_UNIT, net_dev)))
- {
- printk("%s: request_irq() failed; error %d\n", NAME_UNIT, error);
- return error;
- }
-
- /* Arrange to call linux_watchdog() once a second. */
- init_timer(&sc->wd_timer);
- sc->wd_timer.expires = jiffies + HZ; /* now plus one second */
- sc->wd_timer.function = &linux_watchdog;
- sc->wd_timer.data = (unsigned long) sc;
- add_timer(&sc->wd_timer);
-
- /* Start the card and attach a kernel interface and line protocol. */
- if ((error = -attach_card(sc, "")))
- linux_stop(net_dev);
- else
- {
- net_dev->weight = sc->rxring.num_descs; /* input flow control */
- netif_start_queue(net_dev); /* output flow control */
- }
-
- return error;
- }
-
-# if GEN_HDLC
-static int
-hdlc_attach(struct net_device *net_dev,
- unsigned short encoding, unsigned short parity)
- { return 0; }
-# endif
-
-/* This pci_driver method is called during shutdown or module-unload. */
-/* This is called from user context; can sleep; no spinlocks! */
-static void __exit
-linux_remove(struct pci_dev *pci_dev)
- {
- struct net_device *net_dev = (struct net_device *)pci_get_drvdata(pci_dev);
- softc_t *sc = dev_to_hdlc(net_dev)->priv;
-
- if (net_dev == NULL) return;
-
- /* Assume that linux_stop() has already been called. */
- if (sc->flags & FLAG_NETDEV)
-# if GEN_HDLC
- unregister_hdlc_device(net_dev);
-# else
- unregister_netdev(net_dev);
-# endif
-
-# if (IOREF_CSR == 0)
- if (sc->csr_membase != NULL)
- iounmap(sc->csr_membase);
-# endif
-
- pci_disable_device(pci_dev);
-
- if (sc->csr_iobase != 0)
- pci_release_regions(pci_dev);
-
- pci_set_drvdata(pci_dev, NULL);
-
- kfree(sc);
- free_netdev(net_dev);
- }
-
-static void
-setup_netdev(struct net_device *net_dev)
- {
- /* Initialize the generic network device. */
- /* Note similarity to BSD's lmc_ifnet_attach(). */
- net_dev->flags = IFF_POINTOPOINT;
- net_dev->flags |= IFF_RUNNING;
- net_dev->open = linux_open;
- net_dev->stop = linux_stop;
- net_dev->hard_start_xmit = linux_start;
- net_dev->do_ioctl = linux_ioctl;
- net_dev->get_stats = linux_stats;
- net_dev->tx_timeout = linux_timeout;
- net_dev->poll = linux_poll;
- net_dev->watchdog_timeo = 1 * HZ;
- net_dev->tx_queue_len = SNDQ_MAXLEN;
- net_dev->mtu = MAX_DESC_LEN;
- net_dev->type = ARPHRD_RAWHDLC;
-/* The receiver generates frag-lists for packets >4032 bytes. */
-/* The transmitter accepts scatter/gather lists and frag-lists. */
-/* However Linux linearizes outgoing packets since our hardware */
-/* doesn't compute soft checksums. All that work for nothing! */
-/*net_dev->features |= NETIF_F_SG; */
-/*net_dev->features |= NETIF_F_FRAGLIST; */
- }
-
-/* This pci_driver method is called during boot or module-load. */
-/* This is called from user context; can sleep; no spinlocks! */
-static int __init
-linux_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
- {
- u_int32_t cfid, csid;
- struct net_device *net_dev;
- softc_t *sc;
- int error;
-
- /* Looking for a DEC 21140A chip on any Lan Media Corp card. */
- pci_read_config_dword(pci_dev, TLP_CFID, &cfid);
- if (cfid != TLP_CFID_TULIP) return -ENXIO;
- pci_read_config_dword(pci_dev, TLP_CSID, &csid);
- switch (csid)
- {
- case TLP_CSID_HSSI:
- case TLP_CSID_HSSIc:
- case TLP_CSID_T3:
- case TLP_CSID_SSI:
- case TLP_CSID_T1E1:
- break;
- default:
- return -ENXIO;
- }
-
- /* Declare that these cards use 32-bit single-address PCI cycles. */
- if ((error = pci_set_dma_mask(pci_dev, DMA_32BIT_MASK)))
- {
- printk("%s: pci_set_dma_mask() failed; error %d\n", DEVICE_NAME, error);
- return error;
- }
- pci_set_consistent_dma_mask(pci_dev, DMA_32BIT_MASK); /* can't fail */
-
-# if GEN_HDLC /* generic-hdlc line protocols */
-
- /* device driver instance data, aka Soft Context or sc */
- if ((sc = kmalloc(sizeof(softc_t), GFP_KERNEL)) == NULL)
- {
- printk("%s: kmalloc() failed\n", DEVICE_NAME);
- return -ENOMEM;
- }
- memset(sc, 0, sizeof(softc_t));
-
- /* Allocate space for the HDLC network device struct. */
- if ((net_dev = alloc_hdlcdev(sc)) == NULL)
- {
- printk("%s: alloc_hdlcdev() failed\n", DEVICE_NAME);
- kfree(sc);
- return -ENOMEM;
- }
-
- /* Initialize the network device struct. */
- setup_netdev(net_dev);
-
- /* Initialize the HDLC extension to the network device. */
- sc->hdlc_dev = dev_to_hdlc(net_dev);
- sc->hdlc_dev->attach = hdlc_attach; /* noop for this driver */
- sc->hdlc_dev->xmit = linux_start; /* the REAL hard_start_xmit() */
-
-# else /* GEN_HDLC */ /* no line protocol. */
-
- /* Allocate space for the bare network device struct. */
- net_dev = alloc_netdev(sizeof(softc_t), DEVICE_NAME"%d", setup_netdev);
- if (net_dev == NULL)
- {
- printk("%s: alloc_netdev() failed\n", DEVICE_NAME);
- return -ENOMEM;
- }
- /* device driver instance data, aka Soft Context or sc */
- sc = net_dev->priv;
-
-# endif /* GEN_HDLC */
-
- sc->net_dev = net_dev; /* NAME_UNIT macro needs this */
- sc->pci_dev = pci_dev; /* READ/WRITE_PCI_CFG macros need this */
-
- /* Cross-link pci_dev and net_dev. */
- pci_set_drvdata(pci_dev, net_dev); /* pci_dev->driver_data = net_dev */
- SET_NETDEV_DEV(net_dev, &pci_dev->dev); /* net_dev->class_dev.dev = &pci_dev->dev */
- SET_MODULE_OWNER(net_dev); /* ??? NOOP in linux-2.6.3. ??? */
-
- /* Sets cfcs.io and cfcs.mem; sets pci_dev->irq based on cfit.int */
- if ((error = pci_enable_device(pci_dev)))
- {
- printk("%s: pci_enable_device() failed; error %d\n", DEVICE_NAME, error);
- linux_remove(pci_dev);
- return error;
- }
- net_dev->irq = pci_dev->irq; /* linux_open/stop need this */
-
- /* Allocate PCI memory and IO resources to access the Tulip chip CSRs. */
- if ((error = pci_request_regions(pci_dev, DEVICE_NAME)))
- {
- printk("%s: pci_request_regions() failed; error %d\n", DEVICE_NAME, error);
- linux_remove(pci_dev);
- return error;
- }
- net_dev->base_addr = pci_resource_start(pci_dev, 0);
- net_dev->mem_start = pci_resource_start(pci_dev, 1);
- net_dev->mem_end = pci_resource_end(pci_dev, 1);
- sc->csr_iobase = net_dev->base_addr;
-
-# if (IOREF_CSR == 0)
- sc->csr_membase = ioremap_nocache(net_dev->mem_start, TLP_CSR_SIZE);
- if (sc->csr_membase == NULL)
- {
- printk("%s: ioremap_nocache() failed\n", DEVICE_NAME);
- linux_remove(pci_dev);
- return -EFAULT;
- }
-# endif
-
- /* Sets cfcs.master, enabling PCI DMA; checks latency timer value. */
- pci_set_master(pci_dev); /* Later, attach_card() does this too. */
-
- /* Initialize the top-half and bottom-half locks. */
- /* Top_lock must be initialized before net_dev is registered. */
- init_MUTEX(&sc->top_lock);
- spin_lock_init(&sc->bottom_lock);
-
-# if GEN_HDLC
- if ((error = register_hdlc_device(net_dev)))
- {
- printk("%s: register_hdlc_device() failed; error %d\n", DEVICE_NAME, error);
- linux_remove(pci_dev);
- return error;
- }
-# else
- if ((error = register_netdev(net_dev)))
- {
- printk("%s: register_netdev() failed; error %d\n", DEVICE_NAME, error);
- linux_remove(pci_dev);
- return error;
- }
-# endif
- /* The NAME_UNIT macro now works. Use DEVICE_NAME before this. */
- sc->flags |= FLAG_NETDEV;
-
- /* What kind of card are we driving? */
- switch (READ_PCI_CFG(sc, TLP_CSID))
- {
- case TLP_CSID_HSSI:
- case TLP_CSID_HSSIc:
- sc->dev_desc = HSSI_DESC;
- sc->card = &hssi_card;
- break;
- case TLP_CSID_T3:
- sc->dev_desc = T3_DESC;
- sc->card = &t3_card;
- break;
- case TLP_CSID_SSI:
- sc->dev_desc = SSI_DESC;
- sc->card = &ssi_card;
- break;
- case TLP_CSID_T1E1:
- sc->dev_desc = T1E1_DESC;
- sc->card = &t1_card;
- break;
- default: /* shouldn't happen! */
- linux_remove(pci_dev);
- return -ENXIO;
- }
-
- /* Announce the hardware on the console. */
- printk("%s: <%s> io 0x%04lx/9 mem 0x%08lx/25 rom 0x%08lx/14 irq %d pci %s\n",
- NAME_UNIT, sc->dev_desc, pci_resource_start(pci_dev, 0),
- pci_resource_start(pci_dev, 1), pci_resource_start(pci_dev, 6),
- pci_dev->irq, pci_name(pci_dev));
-
- return 0;
- }
-
-/* This pci driver knows how to drive these devices: */
-static __initdata struct pci_device_id pci_device_id_tbl[] =
- {
- /* Looking for a DEC 21140A chip on any Lan Media Corp card. */
- { 0x1011, 0x0009, 0x1376, PCI_ANY_ID, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0 }
- };
-MODULE_DEVICE_TABLE(pci, pci_device_id_tbl);
-
-static struct pci_driver pci_driver =
- {
- .name = DEVICE_NAME,
- .id_table = pci_device_id_tbl,
- .probe = linux_probe,
- .remove = __devexit_p(linux_remove),
- /* This driver does not suspend and resume. */
- };
-
-/* This ultimately calls our pci_driver.probe() method. */
-static int __init linux_modload(void)
- { return pci_module_init(&pci_driver); }
-module_init(linux_modload);
-
-/* This ultimately calls our pci_driver.remove() method. */
-static void __exit linux_modunload(void)
- { pci_unregister_driver(&pci_driver); }
-module_exit(linux_modunload);
-
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_DESCRIPTION("Device driver for SBE/LMC Wide-Area Network cards");
-MODULE_AUTHOR("David Boggs <boggs@boggs.palo-alto.ca.us>");
-#endif /* __linux__ */
diff --git a/sys/dev/lmc/if_lmc.h b/sys/dev/lmc/if_lmc.h
index e89c739..fe4e7d0 100644
--- a/sys/dev/lmc/if_lmc.h
+++ b/sys/dev/lmc/if_lmc.h
@@ -620,13 +620,6 @@
# define LMCIOCREAD _IOWR('i', 243, struct ioctl)
# define LMCIOCWRITE _IOW('i', 244, struct ioctl)
# define LMCIOCTL _IOWR('i', 245, struct ioctl)
-#elif defined(__linux__) /* sigh */
-# define LMCIOCGSTAT SIOCDEVPRIVATE+0
-# define LMCIOCGCFG SIOCDEVPRIVATE+1
-# define LMCIOCSCFG SIOCDEVPRIVATE+2
-# define LMCIOCREAD SIOCDEVPRIVATE+3
-# define LMCIOCWRITE SIOCDEVPRIVATE+4
-# define LMCIOCTL SIOCDEVPRIVATE+5
#endif
struct iohdr /* all LMCIOCs begin with this */
@@ -984,12 +977,8 @@ struct dma_desc
#endif
u_int32_t address1; /* buffer1 bus address */
u_int32_t address2; /* buffer2 bus address */
-#if (defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__))
bus_dmamap_t map; /* bus dmamap for this descriptor */
# define TLP_BUS_DSL_VAL (sizeof(bus_dmamap_t) & TLP_BUS_DSL)
-#else
-# define TLP_BUS_DSL_VAL 0
-#endif
} __attribute__ ((packed));
/* Tulip DMA descriptor status bits */
@@ -1029,18 +1018,13 @@ struct desc_ring
u_int32_t dma_addr; /* bus address for desc array */
int size_descs; /* bus_dmamap_sync needs this */
int num_descs; /* used to set rx quota */
-#ifdef __linux__
- struct sk_buff *head; /* tail-queue of skbuffs */
- struct sk_buff *tail;
-#elif BSD
+#if BSD
struct mbuf *head; /* tail-queue of mbufs */
struct mbuf *tail;
-# if (defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__))
bus_dma_tag_t tag; /* bus_dma tag for desc array */
bus_dmamap_t map; /* bus_dma map for desc array */
bus_dma_segment_t segs[2]; /* bus_dmamap_load() or bus_dmamem_alloc() */
int nsegs; /* bus_dmamap_load() or bus_dmamem_alloc() */
-# endif
#endif
};
@@ -1085,33 +1069,7 @@ struct card
/* FreeBSD wants struct ifnet first in the softc. */
struct softc
{
-#if (defined(__NetBSD__) || defined(__OpenBSD__))
- struct device dev; /* base device -- must be first in softc */
- pcitag_t pa_tag; /* pci_conf_read/write need this */
- pci_chipset_tag_t pa_pc; /* pci_conf_read/write need this */
- bus_dma_tag_t pa_dmat; /* bus_dma needs this */
- bus_space_tag_t csr_tag; /* bus_space needs this */
- bus_space_handle_t csr_handle;/* bus_space needs this */
- pci_intr_handle_t intr_handle;/* interrupt handle */
- void *irq_cookie; /* pci_intr_disestablish needs this */
- void *sdh_cookie; /* shutdownhook_disestablish needs this */
- struct simplelock top_lock; /* lock card->watchdog vs core_ioctl */
- struct simplelock bottom_lock;/* lock for buf queues & descriptor rings */
- struct mbuf *tx_mbuf; /* hang mbuf here while building dma descs */
-#endif /* __NetBSD__ || __OpenBSD__ */
-
-#ifdef __bsdi__
- struct device dev; /* base device -- must be first in softc */
- struct isadev id; /* bus resource */
- struct intrhand ih; /* interrupt vectoring */
- struct atshutdown ats; /* shutdown hook */
- pci_devaddr_t cfgbase; /* base address of PCI config regs */
- u_int16_t csr_iobase; /* io base address of Tulip CSRs */
- u_int32_t *csr_membase; /* kv mem base address of Tulip CSRs */
- struct simplelock top_lock; /* lock card->watchdog vs core_ioctl */
- struct simplelock bottom_lock;/* lock for buf queues & descriptor rings */
- struct mbuf *tx_mbuf; /* hang mbuf here while building dma descs */
-#endif /* __bsdi__ */
+
/* State for kernel-resident Line Protocols */
#if IFNET
@@ -1130,14 +1088,6 @@ struct softc
# endif
#endif
-#ifdef __linux__
-# if GEN_HDLC
- hdlc_device *hdlc_dev; /* state for HDLC code */
- sync_serial_settings hdlc_settings; /* state set by sethdlc program */
-# else
- struct net_device_stats net_stats; /* linux_stats storage */
-# endif
-#endif
#if NETGRAPH
node_p ng_node; /* pointer to our node struct */
@@ -1151,7 +1101,6 @@ struct softc
# endif
#endif
-#ifdef __FreeBSD__
struct callout callout; /* watchdog needs this */
struct device *dev; /* base device pointer */
bus_space_tag_t csr_tag; /* bus_space needs this */
@@ -1173,19 +1122,7 @@ struct softc
int top_spl; /* lock card->watchdog vs core_ioctl */
int bottom_spl; /* lock for buf queues & descriptor rings */
# endif
-#endif /* __FreeBSD__ */
-
-#ifdef __linux__
- struct pci_dev *pci_dev; /* READ/WRITE_PCI_CFG macros need this */
- struct net_device *net_dev; /* NAME_UNIT macro needs this */
- struct timer_list wd_timer; /* timer calls watchdog() once a second */
- u_int32_t csr_iobase; /* io base address of Tulip CSRs */
- void *csr_membase; /* kv mem base address of Tulip CSRs */
- struct sk_buff *tx_skb; /* hang skb here while building dma descs */
- int quota; /* used for incoming packet flow control */
- struct semaphore top_lock; /* lock card->watchdog vs core_ioctl */
- spinlock_t bottom_lock; /* lock for buf queues & descriptor rings */
-#endif /* __linux__ */
+
/* Top-half state used by all card types; lock with top_lock, */
const char *dev_desc; /* string describing type of board */
@@ -1210,7 +1147,6 @@ struct softc
/* Hide the minor differences between OS versions */
-#ifdef __FreeBSD__
typedef void intr_return_t;
# define READ_PCI_CFG(sc, addr) pci_read_config ((sc)->dev, addr, 4)
# define WRITE_PCI_CFG(sc, addr, data) pci_write_config((sc)->dev, addr, data, 4)
@@ -1264,162 +1200,10 @@ struct softc
# if (__FreeBSD_version >= 600000)
# define IFF_RUNNING IFF_DRV_RUNNING
# endif
-#endif /* __FreeBSD__ */
-#ifdef __NetBSD__
- typedef int intr_return_t;
-# define READ_PCI_CFG(sc, addr) pci_conf_read ((sc)->pa_pc, (sc)->pa_tag, addr)
-# define WRITE_PCI_CFG(sc, addr, data) pci_conf_write((sc)->pa_pc, (sc)->pa_tag, addr, data)
-# define READ_CSR(csr) bus_space_read_4 (sc->csr_tag, sc->csr_handle, csr)
-# define WRITE_CSR(csr, val) bus_space_write_4(sc->csr_tag, sc->csr_handle, csr, val)
-# define NAME_UNIT sc->dev.dv_xname
-# define DRIVER_DEBUG ((sc->config.debug) || (sc->ifp->if_flags & IFF_DEBUG))
-# define TOP_TRYLOCK simple_lock_try(&sc->top_lock)
-# define TOP_UNLOCK simple_unlock (&sc->top_lock)
-# define BOTTOM_TRYLOCK simple_lock_try(&sc->bottom_lock)
-# define BOTTOM_UNLOCK simple_unlock (&sc->bottom_lock)
-# define CHECK_CAP suser(curproc->p_ucred, &curproc->p_acflag)
-# define DISABLE_INTR int spl = splnet()
-# define ENABLE_INTR splx(spl)
-# define IRQ_NONE 0
-# define IRQ_HANDLED 1
-# define IFP2SC(ifp) (ifp)->if_softc
-# define COPY_BREAK MHLEN
-# define SLEEP(usecs) tsleep(sc, PCATCH | PZERO, DEVICE_NAME, 1+(usecs/tick))
-# define DMA_SYNC(map, size, flags) bus_dmamap_sync(ring->tag, map, 0, size, flags)
-# define DMA_LOAD(map, addr, size) bus_dmamap_load(ring->tag, map, addr, size, 0, BUS_DMA_NOWAIT)
-# if (NBPFILTER != 0)
-# define LMC_BPF_MTAP(mbuf) if (sc->ifp->if_bpf) bpf_mtap(sc->ifp->if_bpf, mbuf)
-# define LMC_BPF_ATTACH(dlt, len) bpfattach(sc->ifp, dlt, len)
-# define LMC_BPF_DETACH bpfdetach(sc->ifp)
-# endif
-#endif /* __NetBSD__ */
-#ifdef __OpenBSD__
- typedef int intr_return_t;
-# define READ_PCI_CFG(sc, addr) pci_conf_read ((sc)->pa_pc, (sc)->pa_tag, addr)
-# define WRITE_PCI_CFG(sc, addr, data) pci_conf_write((sc)->pa_pc, (sc)->pa_tag, addr, data)
-# define READ_CSR(csr) bus_space_read_4 (sc->csr_tag, sc->csr_handle, csr)
-# define WRITE_CSR(csr, val) bus_space_write_4(sc->csr_tag, sc->csr_handle, csr, val)
-# define NAME_UNIT sc->dev.dv_xname
-# define DRIVER_DEBUG ((sc->config.debug) || (sc->ifp->if_flags & IFF_DEBUG))
-# define TOP_TRYLOCK simple_lock_try(&sc->top_lock)
-# define TOP_UNLOCK simple_unlock (&sc->top_lock)
-# define BOTTOM_TRYLOCK simple_lock_try(&sc->bottom_lock)
-# define BOTTOM_UNLOCK simple_unlock (&sc->bottom_lock)
-# define CHECK_CAP suser(curproc, 0)
-# define DISABLE_INTR int spl = splnet()
-# define ENABLE_INTR splx(spl)
-# define IRQ_NONE 0
-# define IRQ_HANDLED 1
-# define IFP2SC(ifp) (ifp)->if_softc
-# define COPY_BREAK MHLEN
-# define SLEEP(usecs) tsleep(sc, PCATCH | PZERO, DEVICE_NAME, 1+(usecs/tick))
-# define DMA_SYNC(map, size, flags) bus_dmamap_sync(ring->tag, map, 0, size, flags)
-# define DMA_LOAD(map, addr, size) bus_dmamap_load(ring->tag, map, addr, size, 0, BUS_DMA_NOWAIT)
-# if (NBPFILTER != 0)
-# define LMC_BPF_MTAP(mbuf) if (sc->ifp->if_bpf) bpf_mtap(sc->ifp->if_bpf, mbuf)
-# define LMC_BPF_ATTACH(dlt, len) bpfattach(&sc->ifp->if_bpf, sc->ifp, dlt, len)
-# define LMC_BPF_DETACH bpfdetach(sc->ifp)
-# endif
-#endif /* __OpenBSD__ */
-
-#ifdef __bsdi__
- typedef int intr_return_t;
-# define READ_PCI_CFG(sc, addr) pci_inl(&(sc)->cfgbase, addr)
-# define WRITE_PCI_CFG(sc, addr, data) pci_outl(&(sc)->cfgbase, addr, data)
-# if IOREF_CSR
-# define READ_CSR(csr) inl(sc->csr_iobase+(csr))
-# define WRITE_CSR(csr, val) outl(sc->csr_iobase+(csr), (val))
-# else
-# error Memory refs to Tulip CSRs cause page faults in BSD/OS
-# define READ_CSR(csr) (0 + *(sc->csr_membase+(csr)))
-# define WRITE_CSR(csr, val) ((void)(*(sc->csr_membase+(csr)) = (val)))
-# endif
-# define NAME_UNIT sc->dev.dv_xname
-# define DRIVER_DEBUG ((sc->config.debug) || (sc->ifp->if_flags & IFF_DEBUG))
-# define TOP_TRYLOCK simple_lock_try(&sc->top_lock)
-# define TOP_UNLOCK simple_unlock (&sc->top_lock)
-# define BOTTOM_TRYLOCK simple_lock_try(&sc->bottom_lock)
-# define BOTTOM_UNLOCK simple_unlock (&sc->bottom_lock)
-# define CHECK_CAP suser(PCPU(curproc)->p_ucred, &PCPU(curproc)->p_acflag)
-# define DISABLE_INTR int spl = splimp()
-# define ENABLE_INTR splx(spl)
-# define IRQ_NONE 1 /* XXX 0 */
-# define IRQ_HANDLED 1
-# define IFP2SC(ifp) (ifp)->if_softc
-# define COPY_BREAK MHLEN
-# define SLEEP(usecs) tsleep(sc, PCATCH | PZERO, DEVICE_NAME, 1+(usecs/tick))
-# define DMA_SYNC(map, size, flags) /* nothing */
-# define DMA_LOAD(map, addr, size) 0
-# define bus_dmamap_unload(tag, map) /* nothing */
-# define bus_dmamap_destroy(tag, map) /* nothing */
-# if (NBPFILTER != 0)
-# define LMC_BPF_MTAP(mbuf) if (sc->ifp->if_bpf) bpf_mtap(sc->ifp->if_bpf, mbuf)
-# define LMC_BPF_ATTACH(dlt, len) bpfattach(&sc->ifp->if_bpf, sc->ifp, dlt, len)
-# define LMC_BPF_DETACH /* bpfdetach(sc->ifp) */
-# endif
-# define memcpy(dst, src, len) bcopy(src, dst, len)
-# define if_detach(ifp) /* nothing */
-
-/* BSD/OS-4.1 doesn't have a back pointer to softc in struct ifnet, */
-/* and it passes a unit number not a struct ifnet* to watchdog. */
-# if (_BSDI_VERSION <= 199910)
- extern struct cfdriver lmccd;
-# undef IFP2SC
-# define UNIT2SC(unit) ((softc_t *)lmccd.cd_devs[unit])
-# define IFP2SC(ifp) (UNIT2SC((ifp)->if_unit))
-# endif
-#endif /* __bsdi__ */
-#ifdef __linux__
-static u_int32_t /* inline? so rare it doesn't matter */
-READ_PCI_CFG(softc_t *sc, u_int32_t addr)
- {
- u_int32_t data;
- pci_read_config_dword(sc->pci_dev, addr, &data);
- return data;
- }
-# define WRITE_PCI_CFG(sc, addr, data) pci_write_config_dword(sc->pci_dev, addr, data)
-# if IOREF_CSR
-# define READ_CSR(csr) inl((sc->csr_iobase+(csr)))
-# define WRITE_CSR(csr, val) outl((val),(sc->csr_iobase+(csr)))
-# else
-# define READ_CSR(csr) readl((sc->csr_membase+(csr)))
-# define WRITE_CSR(csr, val) writel((val),(sc->csr_membase+(csr)))
-# endif
-# define NAME_UNIT sc->net_dev->name
-# define DRIVER_DEBUG ((sc->config.debug) || (sc->net_dev->flags & IFF_DEBUG))
-# define TOP_TRYLOCK ((down_trylock(&sc->top_lock)==0) ? 1:0)
-# define TOP_UNLOCK up(&sc->top_lock)
-# define BOTTOM_TRYLOCK spin_trylock_bh(&sc->bottom_lock)
-# define BOTTOM_UNLOCK spin_unlock_bh(&sc->bottom_lock)
-# define CHECK_CAP capable(CAP_NET_ADMIN)? 0 : -EPERM
-# define DISABLE_INTR /* nothing */
-# define ENABLE_INTR /* nothing */
-# define COPY_BREAK 200
-# define DELAY(usecs) udelay(usecs)
-# define SLEEP(usecs) do { set_current_state(TASK_INTERRUPTIBLE);\
- schedule_timeout(1+(usecs*HZ)/1000000UL); } while (0)
-# define printf printk
-# define copyin(u, k, len) copy_from_user(k, u, len)
-# define microtime(time) do_gettimeofday(time)
-# define malloc(len, t, f) kmalloc(len, GFP_KERNEL)
-# define free(addr, t) kfree(addr)
-# define LITTLE_ENDIAN 4321
-# define BIG_ENDIAN 1234
-# if defined(__LITTLE_ENDIAN)
-# define BYTE_ORDER LITTLE_ENDIAN
-# elif defined(__BIG_ENDIAN)
-# define BYTE_ORDER BIG_ENDIAN
-# else
-# error "asm/byteorder.h is wrong"
-# endif
-# if (GEN_HDLC == 0)
-# define dev_to_hdlc(net_dev) net_dev
-# define hdlc_set_carrier(val, net_dev) /* nothing */
-# endif
-#endif /* __linux__ */
+
#if (NBPFILTER == 0)
# define LMC_BPF_MTAP(mbuf) /* nothing */
@@ -1541,9 +1325,7 @@ static void lmc_raw_input(struct ifnet *, struct mbuf *);
#if BSD
static void mbuf_enqueue(struct desc_ring *, struct mbuf *);
static struct mbuf* mbuf_dequeue(struct desc_ring *);
-# ifdef __FreeBSD__
static void fbsd_dmamap_load(void *, bus_dma_segment_t *, int, int);
-# endif
static int create_ring(softc_t *, struct desc_ring *, int);
static void destroy_ring(softc_t *, struct desc_ring *);
static int rxintr_cleanup(softc_t *);
@@ -1553,18 +1335,6 @@ static int txintr_setup_mbuf(softc_t *, struct mbuf *);
static int txintr_setup(softc_t *);
#endif /* BSD */
-#ifdef __linux__
-static void skbuff_enqueue(struct desc_ring *, struct sk_buff *);
-static struct sk_buff* skbuff_dequeue(struct desc_ring *);
-static int create_ring(softc_t *, struct desc_ring *, int);
-static void destroy_ring(softc_t *, struct desc_ring *);
-static int rxintr_cleanup(softc_t *);
-static int rxintr_setup(softc_t *);
-static int txintr_cleanup(softc_t *sc);
-static int txintr_setup_frag(softc_t *, char *, int);
-static int txintr_setup_skb(softc_t *, struct sk_buff *);
-static int txintr_setup(softc_t *);
-#endif /* __linux__ */
static void check_intr_status(softc_t *);
static void core_interrupt(void *, int);
@@ -1596,10 +1366,6 @@ static int lmc_ifnet_ioctl(struct ifnet *, u_long, caddr_t);
static void lmc_ifnet_start(struct ifnet *);
static int lmc_raw_output(struct ifnet *, struct mbuf *,
const struct sockaddr *, struct route *);
-# ifdef __OpenBSD__
-static int ifmedia_change(struct ifnet *);
-static void ifmedia_status(struct ifnet *, struct ifmediareq *);
-# endif /* __OpenBSD__ */
static void setup_ifnet(struct ifnet *);
static int lmc_ifnet_attach(softc_t *);
static void lmc_ifnet_detach(softc_t *);
@@ -1638,52 +1404,14 @@ static void shutdown_card(void *);
static int attach_card(softc_t *, const char *);
static void detach_card(softc_t *);
-#ifdef __FreeBSD__
static int fbsd_probe(device_t);
static int fbsd_detach(device_t);
static int fbsd_shutdown(device_t);
static int fbsd_attach(device_t);
-#endif /* __FreeBSD__ */
-
-#ifdef __NetBSD__
-static int nbsd_match(struct device *t, struct cfdata *, void *);
-static int nbsd_detach(struct device *, int);
-static void nbsd_attach(struct device *, struct device *, void *);
-static int lkm_nbsd_match(struct pci_attach_args *);
-int if_lmc_lkmentry(struct lkm_table *, int, int);
-#endif /* __NetBSD__ */
-
-#ifdef __OpenBSD__
-static int obsd_match(struct device *, void *, void *);
-static int obsd_detach(struct device *, int);
-static void obsd_attach(struct device *, struct device *, void *);
-int if_lmc_lkmentry(struct lkm_table *, int, int);
-#endif /* __OpenBSD__ */
-
-#ifdef __bsdi__
-static int bsdi_match(pci_devaddr_t *);
-static int bsdi_probe(struct device *, struct cfdata *, void *);
-static void bsdi_attach(struct device *, struct device *, void *);
-#endif /* __bsdi__ */
-
-#ifdef __linux__
-static irqreturn_t linux_interrupt(int, void *, struct pt_regs *);
-static int linux_poll(struct net_device *, int *);
-static int linux_start(struct sk_buff *, struct net_device *);
-static void linux_timeout(struct net_device *);
-static int linux_ioctl(struct net_device *, struct ifreq *, int);
-static struct net_device_stats * linux_stats(struct net_device *);
-static void linux_watchdog(unsigned long);
-static int linux_stop(struct net_device *);
-static int linux_open(struct net_device *);
-# if GEN_HDLC
-static int hdlc_attach(struct net_device *,
- unsigned short, unsigned short);
-# endif
-static void __exit linux_remove(struct pci_dev *);
-static void setup_netdev(struct net_device *);
-static int __init linux_probe(struct pci_dev *, const struct pci_device_id *);
-#endif /* __linux__ */
+
+
+
+
#endif /* KERNEL */
diff --git a/sys/dev/mxge/if_mxge.c b/sys/dev/mxge/if_mxge.c
index 0dec649..8de1485 100644
--- a/sys/dev/mxge/if_mxge.c
+++ b/sys/dev/mxge/if_mxge.c
@@ -211,7 +211,7 @@ mxge_dmamap_callback(void *arg, bus_dma_segment_t *segs, int nsegs,
}
static int
-mxge_dma_alloc(mxge_softc_t *sc, mxge_dma_t *dma, size_t bytes,
+mxge_dma_alloc(mxge_softc_t *sc, mxge_dma_t *dma, size_t bytes,
bus_size_t alignment)
{
int err;
@@ -245,8 +245,8 @@ mxge_dma_alloc(mxge_softc_t *sc, mxge_dma_t *dma, size_t bytes,
}
/* allocate DMAable memory & map */
- err = bus_dmamem_alloc(dma->dmat, &dma->addr,
- (BUS_DMA_WAITOK | BUS_DMA_COHERENT
+ err = bus_dmamem_alloc(dma->dmat, &dma->addr,
+ (BUS_DMA_WAITOK | BUS_DMA_COHERENT
| BUS_DMA_ZERO), &dma->map);
if (err != 0) {
device_printf(dev, "couldn't alloc mem (err = %d)\n", err);
@@ -385,7 +385,7 @@ mxge_enable_nvidia_ecrc(mxge_softc_t *sc)
/* XXXX
Test below is commented because it is believed that doing
config read/write beyond 0xff will access the config space
- for the next larger function. Uncomment this and remove
+ for the next larger function. Uncomment this and remove
the hacky pmap_mapdev() way of accessing config space when
FreeBSD grows support for extended pcie config space access
*/
@@ -454,7 +454,7 @@ mxge_enable_nvidia_ecrc(mxge_softc_t *sc)
}
*ptr32 = val | 0x40;
pmap_unmapdev((vm_offset_t)va, PAGE_SIZE);
- if (mxge_verbose)
+ if (mxge_verbose)
device_printf(sc->dev,
"Enabled ECRC on upstream Nvidia bridge "
"at %d:%d:%d\n",
@@ -573,7 +573,7 @@ mxge_firmware_probe(mxge_softc_t *sc)
}
}
- /*
+ /*
* load the optimized firmware (which assumes aligned PCIe
* completions) in order to see if it works on this host.
*/
@@ -583,12 +583,12 @@ mxge_firmware_probe(mxge_softc_t *sc)
return status;
}
- /*
+ /*
* Enable ECRC if possible
*/
mxge_enable_nvidia_ecrc(sc);
- /*
+ /*
* Run a DMA test which watches for unaligned completions and
* aborts on the first one seen. Not required on Z8ES or newer.
*/
@@ -657,7 +657,7 @@ mxge_validate_firmware(mxge_softc_t *sc, const mcp_gen_header_t *hdr)
if (be32toh(hdr->mcp_type) != MCP_TYPE_ETH) {
- device_printf(sc->dev, "Bad firmware type: 0x%x\n",
+ device_printf(sc->dev, "Bad firmware type: 0x%x\n",
be32toh(hdr->mcp_type));
return EIO;
}
@@ -685,16 +685,16 @@ mxge_validate_firmware(mxge_softc_t *sc, const mcp_gen_header_t *hdr)
static void *
z_alloc(void *nil, u_int items, u_int size)
{
- void *ptr;
+ void *ptr;
- ptr = malloc(items * size, M_TEMP, M_NOWAIT);
- return ptr;
+ ptr = malloc(items * size, M_TEMP, M_NOWAIT);
+ return ptr;
}
static void
z_free(void *nil, void *ptr)
{
- free(ptr, M_TEMP);
+ free(ptr, M_TEMP);
}
@@ -732,7 +732,7 @@ mxge_load_firmware_helper(mxge_softc_t *sc, uint32_t *limit)
/* the uncompressed size is stored as the firmware version,
which would otherwise go unused */
- fw_len = (size_t) fw->version;
+ fw_len = (size_t) fw->version;
inflate_buffer = malloc(fw_len, M_TEMP, M_NOWAIT);
if (inflate_buffer == NULL)
goto abort_with_zs;
@@ -755,7 +755,7 @@ mxge_load_firmware_helper(mxge_softc_t *sc, uint32_t *limit)
status = EIO;
goto abort_with_buffer;
}
- hdr = (const void*)(inflate_buffer + hdr_offset);
+ hdr = (const void*)(inflate_buffer + hdr_offset);
status = mxge_validate_firmware(sc, hdr);
if (status != 0)
@@ -832,14 +832,14 @@ mxge_dummy_rdma(mxge_softc_t *sc, int enable)
i++;
}
if (*confirm != 0xffffffff) {
- device_printf(sc->dev, "dummy rdma %s failed (%p = 0x%x)",
- (enable ? "enable" : "disable"), confirm,
+ device_printf(sc->dev, "dummy rdma %s failed (%p = 0x%x)",
+ (enable ? "enable" : "disable"), confirm,
*confirm);
}
return;
}
-static int
+static int
mxge_send_cmd(mxge_softc_t *sc, uint32_t cmd, mxge_cmd_t *data)
{
mcp_cmd_t *buf;
@@ -869,7 +869,7 @@ mxge_send_cmd(mxge_softc_t *sc, uint32_t cmd, mxge_cmd_t *data)
/* wait up to 20ms */
err = EAGAIN;
for (sleep_total = 0; sleep_total < 20; sleep_total++) {
- bus_dmamap_sync(sc->cmd_dma.dmat,
+ bus_dmamap_sync(sc->cmd_dma.dmat,
sc->cmd_dma.map, BUS_DMASYNC_POSTREAD);
wmb();
switch (be32toh(response->result)) {
@@ -893,7 +893,7 @@ mxge_send_cmd(mxge_softc_t *sc, uint32_t cmd, mxge_cmd_t *data)
err = ENXIO;
break;
default:
- device_printf(sc->dev,
+ device_printf(sc->dev,
"mxge: command %d "
"failed, result = %d\n",
cmd, be32toh(response->result));
@@ -924,7 +924,7 @@ mxge_adopt_running_firmware(mxge_softc_t *sc)
(sc->sram + MCP_HEADER_PTR_OFFSET));
if ((hdr_offset & 3) || hdr_offset + sizeof(*hdr) > sc->sram_size) {
- device_printf(sc->dev,
+ device_printf(sc->dev,
"Running firmware has bad header offset (%d)\n",
(int)hdr_offset);
return EIO;
@@ -943,7 +943,7 @@ mxge_adopt_running_firmware(mxge_softc_t *sc)
status = mxge_validate_firmware(sc, hdr);
free(hdr, M_DEVBUF);
- /*
+ /*
* check to see if adopted firmware has bug where adopting
* it will cause broadcasts to be filtered unless the NIC
* is kept in ALLMULTI mode
@@ -1034,11 +1034,11 @@ mxge_load_firmware(mxge_softc_t *sc, int adopt)
while (*confirm != 0xffffffff && i < 20) {
DELAY(1000*10);
i++;
- bus_dmamap_sync(sc->cmd_dma.dmat,
+ bus_dmamap_sync(sc->cmd_dma.dmat,
sc->cmd_dma.map, BUS_DMASYNC_POSTREAD);
}
if (*confirm != 0xffffffff) {
- device_printf(sc->dev,"handoff failed (%p = 0x%x)",
+ device_printf(sc->dev,"handoff failed (%p = 0x%x)",
confirm, *confirm);
return ENXIO;
@@ -1054,7 +1054,7 @@ mxge_update_mac_address(mxge_softc_t *sc)
int status;
- cmd.data0 = ((addr[0] << 24) | (addr[1] << 16)
+ cmd.data0 = ((addr[0] << 24) | (addr[1] << 16)
| (addr[2] << 8) | addr[3]);
cmd.data1 = ((addr[4] << 8) | (addr[5]));
@@ -1136,7 +1136,7 @@ mxge_set_multicast_list(mxge_softc_t *sc)
err = mxge_send_cmd(sc, MXGEFW_LEAVE_ALL_MULTICAST_GROUPS, &cmd);
if (err != 0) {
- device_printf(sc->dev,
+ device_printf(sc->dev,
"Failed MXGEFW_LEAVE_ALL_MULTICAST_GROUPS"
", error status: %d\n", err);
return;
@@ -1219,7 +1219,7 @@ mxge_reset(mxge_softc_t *sc, int interrupts_setup)
cmd.data0 = sc->rx_ring_size;
status = mxge_send_cmd(sc, MXGEFW_CMD_SET_INTRQ_SIZE, &cmd);
- /*
+ /*
* Even though we already know how many slices are supported
* via mxge_slice_probe(), MXGEFW_CMD_GET_MAX_RSS_QUEUES
* has magic side effects, and must be called after a reset.
@@ -1229,17 +1229,17 @@ mxge_reset(mxge_softc_t *sc, int interrupts_setup)
* MXGEFW_CMD_SET_INTRQ_SIZE, since the intrq size is used by
* the firmware to compute offsets.
*/
-
+
if (sc->num_slices > 1) {
/* ask the maximum number of slices it supports */
status = mxge_send_cmd(sc, MXGEFW_CMD_GET_MAX_RSS_QUEUES,
&cmd);
if (status != 0) {
- device_printf(sc->dev,
+ device_printf(sc->dev,
"failed to get number of slices\n");
return status;
}
- /*
+ /*
* MXGEFW_CMD_ENABLE_RSS_QUEUES must be called prior
* to setting up the interrupt queue DMA
*/
@@ -1272,7 +1272,7 @@ mxge_reset(mxge_softc_t *sc, int interrupts_setup)
}
}
- status |= mxge_send_cmd(sc,
+ status |= mxge_send_cmd(sc,
MXGEFW_CMD_GET_INTR_COAL_DELAY_OFFSET, &cmd);
@@ -1282,7 +1282,7 @@ mxge_reset(mxge_softc_t *sc, int interrupts_setup)
irq_claim = (volatile uint32_t *)(sc->sram + cmd.data0);
- status |= mxge_send_cmd(sc, MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET,
+ status |= mxge_send_cmd(sc, MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET,
&cmd);
sc->irq_deassert = (volatile uint32_t *)(sc->sram + cmd.data0);
if (status != 0) {
@@ -1349,15 +1349,15 @@ mxge_change_throttle(SYSCTL_HANDLER_ARGS)
sc = arg1;
throttle = sc->throttle;
err = sysctl_handle_int(oidp, &throttle, arg2, req);
- if (err != 0) {
- return err;
- }
+ if (err != 0) {
+ return err;
+ }
if (throttle == sc->throttle)
return 0;
- if (throttle < MXGE_MIN_THROTTLE || throttle > MXGE_MAX_THROTTLE)
- return EINVAL;
+ if (throttle < MXGE_MIN_THROTTLE || throttle > MXGE_MAX_THROTTLE)
+ return EINVAL;
mtx_lock(&sc->driver_mtx);
cmd.data0 = throttle;
@@ -1371,64 +1371,64 @@ mxge_change_throttle(SYSCTL_HANDLER_ARGS)
static int
mxge_change_intr_coal(SYSCTL_HANDLER_ARGS)
{
- mxge_softc_t *sc;
- unsigned int intr_coal_delay;
- int err;
-
- sc = arg1;
- intr_coal_delay = sc->intr_coal_delay;
- err = sysctl_handle_int(oidp, &intr_coal_delay, arg2, req);
- if (err != 0) {
- return err;
- }
- if (intr_coal_delay == sc->intr_coal_delay)
- return 0;
-
- if (intr_coal_delay == 0 || intr_coal_delay > 1000*1000)
- return EINVAL;
+ mxge_softc_t *sc;
+ unsigned int intr_coal_delay;
+ int err;
+
+ sc = arg1;
+ intr_coal_delay = sc->intr_coal_delay;
+ err = sysctl_handle_int(oidp, &intr_coal_delay, arg2, req);
+ if (err != 0) {
+ return err;
+ }
+ if (intr_coal_delay == sc->intr_coal_delay)
+ return 0;
+
+ if (intr_coal_delay == 0 || intr_coal_delay > 1000*1000)
+ return EINVAL;
mtx_lock(&sc->driver_mtx);
*sc->intr_coal_delay_ptr = htobe32(intr_coal_delay);
sc->intr_coal_delay = intr_coal_delay;
mtx_unlock(&sc->driver_mtx);
- return err;
+ return err;
}
static int
mxge_change_flow_control(SYSCTL_HANDLER_ARGS)
{
- mxge_softc_t *sc;
- unsigned int enabled;
- int err;
-
- sc = arg1;
- enabled = sc->pause;
- err = sysctl_handle_int(oidp, &enabled, arg2, req);
- if (err != 0) {
- return err;
- }
- if (enabled == sc->pause)
- return 0;
+ mxge_softc_t *sc;
+ unsigned int enabled;
+ int err;
+
+ sc = arg1;
+ enabled = sc->pause;
+ err = sysctl_handle_int(oidp, &enabled, arg2, req);
+ if (err != 0) {
+ return err;
+ }
+ if (enabled == sc->pause)
+ return 0;
mtx_lock(&sc->driver_mtx);
err = mxge_change_pause(sc, enabled);
mtx_unlock(&sc->driver_mtx);
- return err;
+ return err;
}
static int
mxge_handle_be32(SYSCTL_HANDLER_ARGS)
{
- int err;
+ int err;
- if (arg1 == NULL)
- return EFAULT;
- arg2 = be32toh(*(int *)arg1);
- arg1 = NULL;
- err = sysctl_handle_int(oidp, arg1, arg2, req);
+ if (arg1 == NULL)
+ return EFAULT;
+ arg2 = be32toh(*(int *)arg1);
+ arg1 = NULL;
+ err = sysctl_handle_int(oidp, arg1, arg2, req);
- return err;
+ return err;
}
static void
@@ -1466,156 +1466,156 @@ mxge_add_sysctls(mxge_softc_t *sc)
fw = sc->ss[0].fw_stats;
/* random information */
- SYSCTL_ADD_STRING(ctx, children, OID_AUTO,
+ SYSCTL_ADD_STRING(ctx, children, OID_AUTO,
"firmware_version",
CTLFLAG_RD, &sc->fw_version,
0, "firmware version");
- SYSCTL_ADD_STRING(ctx, children, OID_AUTO,
+ SYSCTL_ADD_STRING(ctx, children, OID_AUTO,
"serial_number",
CTLFLAG_RD, &sc->serial_number_string,
0, "serial number");
- SYSCTL_ADD_STRING(ctx, children, OID_AUTO,
+ SYSCTL_ADD_STRING(ctx, children, OID_AUTO,
"product_code",
CTLFLAG_RD, &sc->product_code_string,
0, "product_code");
- SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"pcie_link_width",
CTLFLAG_RD, &sc->link_width,
0, "tx_boundary");
- SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"tx_boundary",
CTLFLAG_RD, &sc->tx_boundary,
0, "tx_boundary");
- SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"write_combine",
CTLFLAG_RD, &sc->wc,
0, "write combining PIO?");
- SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"read_dma_MBs",
CTLFLAG_RD, &sc->read_dma,
0, "DMA Read speed in MB/s");
- SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"write_dma_MBs",
CTLFLAG_RD, &sc->write_dma,
0, "DMA Write speed in MB/s");
- SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"read_write_dma_MBs",
CTLFLAG_RD, &sc->read_write_dma,
0, "DMA concurrent Read/Write speed in MB/s");
- SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"watchdog_resets",
CTLFLAG_RD, &sc->watchdog_resets,
0, "Number of times NIC was reset");
/* performance related tunables */
- SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
"intr_coal_delay",
CTLTYPE_INT|CTLFLAG_RW, sc,
- 0, mxge_change_intr_coal,
+ 0, mxge_change_intr_coal,
"I", "interrupt coalescing delay in usecs");
- SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
"throttle",
CTLTYPE_INT|CTLFLAG_RW, sc,
- 0, mxge_change_throttle,
+ 0, mxge_change_throttle,
"I", "transmit throttling");
- SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
"flow_control_enabled",
CTLTYPE_INT|CTLFLAG_RW, sc,
0, mxge_change_flow_control,
"I", "interrupt coalescing delay in usecs");
- SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"deassert_wait",
CTLFLAG_RW, &mxge_deassert_wait,
0, "Wait for IRQ line to go low in ihandler");
- /* stats block from firmware is in network byte order.
+ /* stats block from firmware is in network byte order.
Need to swap it */
- SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
"link_up",
CTLTYPE_INT|CTLFLAG_RD, &fw->link_up,
0, mxge_handle_be32,
"I", "link up");
- SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
"rdma_tags_available",
CTLTYPE_INT|CTLFLAG_RD, &fw->rdma_tags_available,
0, mxge_handle_be32,
"I", "rdma_tags_available");
- SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
"dropped_bad_crc32",
- CTLTYPE_INT|CTLFLAG_RD,
+ CTLTYPE_INT|CTLFLAG_RD,
&fw->dropped_bad_crc32,
0, mxge_handle_be32,
"I", "dropped_bad_crc32");
- SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
"dropped_bad_phy",
- CTLTYPE_INT|CTLFLAG_RD,
+ CTLTYPE_INT|CTLFLAG_RD,
&fw->dropped_bad_phy,
0, mxge_handle_be32,
"I", "dropped_bad_phy");
- SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
"dropped_link_error_or_filtered",
- CTLTYPE_INT|CTLFLAG_RD,
+ CTLTYPE_INT|CTLFLAG_RD,
&fw->dropped_link_error_or_filtered,
0, mxge_handle_be32,
"I", "dropped_link_error_or_filtered");
- SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
"dropped_link_overflow",
CTLTYPE_INT|CTLFLAG_RD, &fw->dropped_link_overflow,
0, mxge_handle_be32,
"I", "dropped_link_overflow");
- SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
"dropped_multicast_filtered",
- CTLTYPE_INT|CTLFLAG_RD,
+ CTLTYPE_INT|CTLFLAG_RD,
&fw->dropped_multicast_filtered,
0, mxge_handle_be32,
"I", "dropped_multicast_filtered");
- SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
"dropped_no_big_buffer",
CTLTYPE_INT|CTLFLAG_RD, &fw->dropped_no_big_buffer,
0, mxge_handle_be32,
"I", "dropped_no_big_buffer");
- SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
"dropped_no_small_buffer",
- CTLTYPE_INT|CTLFLAG_RD,
+ CTLTYPE_INT|CTLFLAG_RD,
&fw->dropped_no_small_buffer,
0, mxge_handle_be32,
"I", "dropped_no_small_buffer");
- SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
"dropped_overrun",
CTLTYPE_INT|CTLFLAG_RD, &fw->dropped_overrun,
0, mxge_handle_be32,
"I", "dropped_overrun");
- SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
"dropped_pause",
- CTLTYPE_INT|CTLFLAG_RD,
+ CTLTYPE_INT|CTLFLAG_RD,
&fw->dropped_pause,
0, mxge_handle_be32,
"I", "dropped_pause");
- SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
"dropped_runt",
CTLTYPE_INT|CTLFLAG_RD, &fw->dropped_runt,
0, mxge_handle_be32,
"I", "dropped_runt");
- SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
"dropped_unicast_filtered",
CTLTYPE_INT|CTLFLAG_RD, &fw->dropped_unicast_filtered,
0, mxge_handle_be32,
"I", "dropped_unicast_filtered");
/* verbose printing? */
- SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"verbose",
CTLFLAG_RW, &mxge_verbose,
0, "verbose printing");
/* add counters exported for debugging from all slices */
sysctl_ctx_init(&sc->slice_sysctl_ctx);
- sc->slice_sysctl_tree =
+ sc->slice_sysctl_tree =
SYSCTL_ADD_NODE(&sc->slice_sysctl_ctx, children, OID_AUTO,
"slice", CTLFLAG_RD, 0, "");
@@ -1625,15 +1625,15 @@ mxge_add_sysctls(mxge_softc_t *sc)
ctx = &ss->sysctl_ctx;
children = SYSCTL_CHILDREN(sc->slice_sysctl_tree);
sprintf(slice_num, "%d", slice);
- ss->sysctl_tree =
+ ss->sysctl_tree =
SYSCTL_ADD_NODE(ctx, children, OID_AUTO, slice_num,
CTLFLAG_RD, 0, "");
children = SYSCTL_CHILDREN(ss->sysctl_tree);
- SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"rx_small_cnt",
CTLFLAG_RD, &ss->rx_small.cnt,
0, "rx_small_cnt");
- SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"rx_big_cnt",
CTLFLAG_RD, &ss->rx_big.cnt,
0, "rx_small_cnt");
@@ -1655,118 +1655,118 @@ mxge_add_sysctls(mxge_softc_t *sc)
if (slice > 0)
continue;
#endif
- SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"tx_req",
CTLFLAG_RD, &ss->tx.req,
0, "tx_req");
- SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"tx_done",
CTLFLAG_RD, &ss->tx.done,
0, "tx_done");
- SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"tx_pkt_done",
CTLFLAG_RD, &ss->tx.pkt_done,
0, "tx_done");
- SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"tx_stall",
CTLFLAG_RD, &ss->tx.stall,
0, "tx_stall");
- SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"tx_wake",
CTLFLAG_RD, &ss->tx.wake,
0, "tx_wake");
- SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"tx_defrag",
CTLFLAG_RD, &ss->tx.defrag,
0, "tx_defrag");
- SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"tx_queue_active",
CTLFLAG_RD, &ss->tx.queue_active,
0, "tx_queue_active");
- SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"tx_activate",
CTLFLAG_RD, &ss->tx.activate,
0, "tx_activate");
- SYSCTL_ADD_INT(ctx, children, OID_AUTO,
+ SYSCTL_ADD_INT(ctx, children, OID_AUTO,
"tx_deactivate",
CTLFLAG_RD, &ss->tx.deactivate,
0, "tx_deactivate");
}
}
-/* copy an array of mcp_kreq_ether_send_t's to the mcp. Copy
+/* copy an array of mcp_kreq_ether_send_t's to the mcp. Copy
backwards one at a time and handle ring wraps */
-static inline void
-mxge_submit_req_backwards(mxge_tx_ring_t *tx,
+static inline void
+mxge_submit_req_backwards(mxge_tx_ring_t *tx,
mcp_kreq_ether_send_t *src, int cnt)
{
- int idx, starting_slot;
- starting_slot = tx->req;
- while (cnt > 1) {
- cnt--;
- idx = (starting_slot + cnt) & tx->mask;
- mxge_pio_copy(&tx->lanai[idx],
+ int idx, starting_slot;
+ starting_slot = tx->req;
+ while (cnt > 1) {
+ cnt--;
+ idx = (starting_slot + cnt) & tx->mask;
+ mxge_pio_copy(&tx->lanai[idx],
&src[cnt], sizeof(*src));
- wmb();
- }
+ wmb();
+ }
}
/*
* copy an array of mcp_kreq_ether_send_t's to the mcp. Copy
* at most 32 bytes at a time, so as to avoid involving the software
* pio handler in the nic. We re-write the first segment's flags
- * to mark them valid only after writing the entire chain
+ * to mark them valid only after writing the entire chain
*/
-static inline void
-mxge_submit_req(mxge_tx_ring_t *tx, mcp_kreq_ether_send_t *src,
- int cnt)
+static inline void
+mxge_submit_req(mxge_tx_ring_t *tx, mcp_kreq_ether_send_t *src,
+ int cnt)
{
- int idx, i;
- uint32_t *src_ints;
+ int idx, i;
+ uint32_t *src_ints;
volatile uint32_t *dst_ints;
- mcp_kreq_ether_send_t *srcp;
+ mcp_kreq_ether_send_t *srcp;
volatile mcp_kreq_ether_send_t *dstp, *dst;
uint8_t last_flags;
-
- idx = tx->req & tx->mask;
+
+ idx = tx->req & tx->mask;
last_flags = src->flags;
src->flags = 0;
- wmb();
- dst = dstp = &tx->lanai[idx];
- srcp = src;
-
- if ((idx + cnt) < tx->mask) {
- for (i = 0; i < (cnt - 1); i += 2) {
- mxge_pio_copy(dstp, srcp, 2 * sizeof(*src));
- wmb(); /* force write every 32 bytes */
- srcp += 2;
- dstp += 2;
- }
- } else {
- /* submit all but the first request, and ensure
- that it is submitted below */
- mxge_submit_req_backwards(tx, src, cnt);
- i = 0;
- }
- if (i < cnt) {
- /* submit the first request */
- mxge_pio_copy(dstp, srcp, sizeof(*src));
- wmb(); /* barrier before setting valid flag */
- }
-
- /* re-write the last 32-bits with the valid flags */
- src->flags = last_flags;
- src_ints = (uint32_t *)src;
- src_ints+=3;
- dst_ints = (volatile uint32_t *)dst;
- dst_ints+=3;
- *dst_ints = *src_ints;
- tx->req += cnt;
- wmb();
+ wmb();
+ dst = dstp = &tx->lanai[idx];
+ srcp = src;
+
+ if ((idx + cnt) < tx->mask) {
+ for (i = 0; i < (cnt - 1); i += 2) {
+ mxge_pio_copy(dstp, srcp, 2 * sizeof(*src));
+ wmb(); /* force write every 32 bytes */
+ srcp += 2;
+ dstp += 2;
+ }
+ } else {
+ /* submit all but the first request, and ensure
+ that it is submitted below */
+ mxge_submit_req_backwards(tx, src, cnt);
+ i = 0;
+ }
+ if (i < cnt) {
+ /* submit the first request */
+ mxge_pio_copy(dstp, srcp, sizeof(*src));
+ wmb(); /* barrier before setting valid flag */
+ }
+
+ /* re-write the last 32-bits with the valid flags */
+ src->flags = last_flags;
+ src_ints = (uint32_t *)src;
+ src_ints+=3;
+ dst_ints = (volatile uint32_t *)dst;
+ dst_ints+=3;
+ *dst_ints = *src_ints;
+ tx->req += cnt;
+ wmb();
}
static int
@@ -1969,7 +1969,7 @@ mxge_encap_tso(struct mxge_slice_state *ss, struct mbuf *m,
seglen = -cum_len;
small = (mss <= MXGEFW_SEND_SMALL_SIZE);
flags_next = MXGEFW_FLAGS_TSO_PLD |
- MXGEFW_FLAGS_FIRST |
+ MXGEFW_FLAGS_FIRST |
(small * MXGEFW_FLAGS_SMALL);
}
@@ -2038,7 +2038,7 @@ drop:
#endif /* IFCAP_TSO4 */
#ifdef MXGE_NEW_VLAN_API
-/*
+/*
* We reproduce the software vlan tag insertion from
* net/if_vlan.c:vlan_start() here so that we can advertise "hardware"
* vlan tag insertion. We need to advertise this in order to have the
@@ -2083,7 +2083,7 @@ mxge_encap(struct mxge_slice_state *ss, struct mbuf *m)
mxge_tx_ring_t *tx;
int cnt, cum_len, err, i, idx, odd_flag;
uint16_t pseudo_hdr_offset;
- uint8_t flags, cksum_offset;
+ uint8_t flags, cksum_offset;
sc = ss->sc;
@@ -2106,7 +2106,7 @@ mxge_encap(struct mxge_slice_state *ss, struct mbuf *m)
/* (try to) map the frame for DMA */
idx = tx->req & tx->mask;
err = bus_dmamap_load_mbuf_sg(tx->dmat, tx->info[idx].map,
- m, tx->seg_list, &cnt,
+ m, tx->seg_list, &cnt,
BUS_DMA_NOWAIT);
if (__predict_false(err == EFBIG)) {
/* Too many segments in the chain. Try
@@ -2117,9 +2117,9 @@ mxge_encap(struct mxge_slice_state *ss, struct mbuf *m)
}
ss->tx.defrag++;
m = m_tmp;
- err = bus_dmamap_load_mbuf_sg(tx->dmat,
+ err = bus_dmamap_load_mbuf_sg(tx->dmat,
tx->info[idx].map,
- m, tx->seg_list, &cnt,
+ m, tx->seg_list, &cnt,
BUS_DMA_NOWAIT);
}
if (__predict_false(err != 0)) {
@@ -2166,9 +2166,9 @@ mxge_encap(struct mxge_slice_state *ss, struct mbuf *m)
seg = tx->seg_list;
req->flags = MXGEFW_FLAGS_FIRST;
for (i = 0; i < cnt; i++) {
- req->addr_low =
+ req->addr_low =
htobe32(MXGE_LOWPART_TO_U32(seg->ds_addr));
- req->addr_high =
+ req->addr_high =
htobe32(MXGE_HIGHPART_TO_U32(seg->ds_addr));
req->length = htobe16(seg->ds_len);
req->cksum_offset = cksum_offset;
@@ -2189,9 +2189,9 @@ mxge_encap(struct mxge_slice_state *ss, struct mbuf *m)
/* pad runts to 60 bytes */
if (cum_len < 60) {
req++;
- req->addr_low =
+ req->addr_low =
htobe32(MXGE_LOWPART_TO_U32(sc->zeropad_dma.bus_addr));
- req->addr_high =
+ req->addr_high =
htobe32(MXGE_HIGHPART_TO_U32(sc->zeropad_dma.bus_addr));
req->length = htobe16(60 - cum_len);
req->cksum_offset = 0;
@@ -2427,16 +2427,16 @@ mxge_get_buf_small(struct mxge_slice_state *ss, bus_dmamap_t map, int idx)
goto done;
}
m->m_len = MHLEN;
- err = bus_dmamap_load_mbuf_sg(rx->dmat, map, m,
+ err = bus_dmamap_load_mbuf_sg(rx->dmat, map, m,
&seg, &cnt, BUS_DMA_NOWAIT);
if (err != 0) {
m_free(m);
goto done;
}
rx->info[idx].m = m;
- rx->shadow[idx].addr_low =
+ rx->shadow[idx].addr_low =
htobe32(MXGE_LOWPART_TO_U32(seg.ds_addr));
- rx->shadow[idx].addr_high =
+ rx->shadow[idx].addr_high =
htobe32(MXGE_HIGHPART_TO_U32(seg.ds_addr));
done:
@@ -2460,23 +2460,23 @@ mxge_get_buf_big(struct mxge_slice_state *ss, bus_dmamap_t map, int idx)
goto done;
}
m->m_len = rx->mlen;
- err = bus_dmamap_load_mbuf_sg(rx->dmat, map, m,
+ err = bus_dmamap_load_mbuf_sg(rx->dmat, map, m,
seg, &cnt, BUS_DMA_NOWAIT);
if (err != 0) {
m_free(m);
goto done;
}
rx->info[idx].m = m;
- rx->shadow[idx].addr_low =
+ rx->shadow[idx].addr_low =
htobe32(MXGE_LOWPART_TO_U32(seg->ds_addr));
- rx->shadow[idx].addr_high =
+ rx->shadow[idx].addr_high =
htobe32(MXGE_HIGHPART_TO_U32(seg->ds_addr));
#if MXGE_VIRT_JUMBOS
for (i = 1; i < cnt; i++) {
- rx->shadow[idx + i].addr_low =
+ rx->shadow[idx + i].addr_low =
htobe32(MXGE_LOWPART_TO_U32(seg[i].ds_addr));
- rx->shadow[idx + i].addr_high =
+ rx->shadow[idx + i].addr_high =
htobe32(MXGE_HIGHPART_TO_U32(seg[i].ds_addr));
}
#endif
@@ -2548,7 +2548,7 @@ mxge_rx_csum6(void *p, struct mbuf *m, uint32_t csum)
return (c);
}
#endif /* INET6 */
-/*
+/*
* Myri10GE hardware checksums are not valid if the sender
* padded the frame with non-zero padding. This is because
* the firmware just does a simple 16-bit 1s complement
@@ -2616,14 +2616,14 @@ mxge_vlan_tag_remove(struct mbuf *m, uint32_t *csum)
*/
/* put checksum into host byte order */
- *csum = ntohs(*csum);
+ *csum = ntohs(*csum);
partial = ntohl(*(uint32_t *)(mtod(m, char *) + ETHER_HDR_LEN));
(*csum) += ~partial;
(*csum) += ((*csum) < ~partial);
(*csum) = ((*csum) >> 16) + ((*csum) & 0xFFFF);
(*csum) = ((*csum) >> 16) + ((*csum) & 0xFFFF);
- /* restore checksum to network byte order;
+ /* restore checksum to network byte order;
later consumers expect this */
*csum = htons(*csum);
@@ -2678,7 +2678,7 @@ mxge_rx_done_big(struct mxge_slice_state *ss, uint32_t len,
/* try to replace the received mbuf */
if (mxge_get_buf_big(ss, rx->extra_map, idx)) {
/* drop the frame -- the old mbuf is re-cycled */
- ifp->if_ierrors++;
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
return;
}
@@ -2747,7 +2747,7 @@ mxge_rx_done_small(struct mxge_slice_state *ss, uint32_t len,
/* try to replace the received mbuf */
if (mxge_get_buf_small(ss, rx->extra_map, idx)) {
/* drop the frame -- the old mbuf is re-cycled */
- ifp->if_ierrors++;
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
return;
}
@@ -2863,7 +2863,7 @@ mxge_tx_done(struct mxge_slice_state *ss, uint32_t mcp_idx)
}
/* If we have space, clear IFF_OACTIVE to tell the stack that
- its OK to send packets */
+ its OK to send packets */
#ifdef IFNET_BUF_RING
flags = &ss->if_drv_flags;
#else
@@ -2919,7 +2919,7 @@ mxge_media_set(mxge_softc_t *sc, int media_type)
{
- ifmedia_add(&sc->media, IFM_ETHER | IFM_FDX | media_type,
+ ifmedia_add(&sc->media, IFM_ETHER | IFM_FDX | media_type,
0, NULL);
ifmedia_set(&sc->media, IFM_ETHER | IFM_FDX | media_type);
sc->current_media = media_type;
@@ -2935,7 +2935,7 @@ mxge_media_init(mxge_softc_t *sc)
ifmedia_removeall(&sc->media);
mxge_media_set(sc, IFM_AUTO);
- /*
+ /*
* parse the product code to deterimine the interface type
* (CX4, XFP, Quad Ribbon Fiber) by looking at the character
* after the 3rd dash in the driver's cached copy of the
@@ -2980,7 +2980,7 @@ mxge_media_init(mxge_softc_t *sc)
* themselves only when their link is up, so this is initiated via a
* link up interrupt. However, this can potentially take up to
* several milliseconds, so it is run via the watchdog routine, rather
- * than in the interrupt handler itself.
+ * than in the interrupt handler itself.
*/
static void
mxge_media_probe(mxge_softc_t *sc)
@@ -2997,7 +2997,7 @@ mxge_media_probe(mxge_softc_t *sc)
if (sc->connector == MXGE_XFP) {
/* -R is XFP */
mxge_media_types = mxge_xfp_media_types;
- mxge_media_type_entries =
+ mxge_media_type_entries =
sizeof (mxge_xfp_media_types) /
sizeof (mxge_xfp_media_types[0]);
byte = MXGE_XFP_COMPLIANCE_BYTE;
@@ -3005,7 +3005,7 @@ mxge_media_probe(mxge_softc_t *sc)
} else if (sc->connector == MXGE_SFP) {
/* -S or -2S is SFP+ */
mxge_media_types = mxge_sfp_media_types;
- mxge_media_type_entries =
+ mxge_media_type_entries =
sizeof (mxge_sfp_media_types) /
sizeof (mxge_sfp_media_types[0]);
cage_type = "SFP+";
@@ -3151,7 +3151,7 @@ mxge_intr(void *arg)
}
if (sc->rdma_tags_available !=
be32toh(stats->rdma_tags_available)) {
- sc->rdma_tags_available =
+ sc->rdma_tags_available =
be32toh(stats->rdma_tags_available);
device_printf(sc->dev, "RDMA timed out! %d tags "
"left\n", sc->rdma_tags_available);
@@ -3384,7 +3384,7 @@ mxge_alloc_slice_rings(struct mxge_slice_state *ss, int rx_ring_entries,
return err;
}
for (i = 0; i <= ss->rx_small.mask; i++) {
- err = bus_dmamap_create(ss->rx_small.dmat, 0,
+ err = bus_dmamap_create(ss->rx_small.dmat, 0,
&ss->rx_small.info[i].map);
if (err != 0) {
device_printf(sc->dev, "Err %d rx_small dmamap\n",
@@ -3392,7 +3392,7 @@ mxge_alloc_slice_rings(struct mxge_slice_state *ss, int rx_ring_entries,
return err;
}
}
- err = bus_dmamap_create(ss->rx_small.dmat, 0,
+ err = bus_dmamap_create(ss->rx_small.dmat, 0,
&ss->rx_small.extra_map);
if (err != 0) {
device_printf(sc->dev, "Err %d extra rx_small dmamap\n",
@@ -3401,7 +3401,7 @@ mxge_alloc_slice_rings(struct mxge_slice_state *ss, int rx_ring_entries,
}
for (i = 0; i <= ss->rx_big.mask; i++) {
- err = bus_dmamap_create(ss->rx_big.dmat, 0,
+ err = bus_dmamap_create(ss->rx_big.dmat, 0,
&ss->rx_big.info[i].map);
if (err != 0) {
device_printf(sc->dev, "Err %d rx_big dmamap\n",
@@ -3409,7 +3409,7 @@ mxge_alloc_slice_rings(struct mxge_slice_state *ss, int rx_ring_entries,
return err;
}
}
- err = bus_dmamap_create(ss->rx_big.dmat, 0,
+ err = bus_dmamap_create(ss->rx_big.dmat, 0,
&ss->rx_big.extra_map);
if (err != 0) {
device_printf(sc->dev, "Err %d extra rx_big dmamap\n",
@@ -3430,7 +3430,7 @@ mxge_alloc_slice_rings(struct mxge_slice_state *ss, int rx_ring_entries,
/* allocate the tx request copy block */
- bytes = 8 +
+ bytes = 8 +
sizeof (*ss->tx.req_list) * (ss->tx.max_desc + 4);
ss->tx.req_bytes = malloc(bytes, M_DEVBUF, M_WAITOK);
/* ensure req_list entries are aligned to 8 bytes */
@@ -3439,7 +3439,7 @@ mxge_alloc_slice_rings(struct mxge_slice_state *ss, int rx_ring_entries,
/* allocate the tx busdma segment list */
bytes = sizeof (*ss->tx.seg_list) * ss->tx.max_desc;
- ss->tx.seg_list = (bus_dma_segment_t *)
+ ss->tx.seg_list = (bus_dma_segment_t *)
malloc(bytes, M_DEVBUF, M_WAITOK);
/* allocate the tx host info ring */
@@ -3469,7 +3469,7 @@ mxge_alloc_slice_rings(struct mxge_slice_state *ss, int rx_ring_entries,
/* now use these tags to setup dmamaps for each slot
in the ring */
for (i = 0; i <= ss->tx.mask; i++) {
- err = bus_dmamap_create(ss->tx.dmat, 0,
+ err = bus_dmamap_create(ss->tx.dmat, 0,
&ss->tx.info[i].map);
if (err != 0) {
device_printf(sc->dev, "Err %d tx dmamap\n",
@@ -3580,7 +3580,7 @@ mxge_slice_open(struct mxge_slice_state *ss, int nbufs, int cl_size)
#endif
cmd.data0 = slice;
err = mxge_send_cmd(sc, MXGEFW_CMD_GET_SEND_OFFSET, &cmd);
- ss->tx.lanai =
+ ss->tx.lanai =
(volatile mcp_kreq_ether_send_t *)(sc->sram + cmd.data0);
ss->tx.send_go = (volatile uint32_t *)
(sc->sram + MXGEFW_ETH_SEND_GO + 64 * slice);
@@ -3590,17 +3590,17 @@ mxge_slice_open(struct mxge_slice_state *ss, int nbufs, int cl_size)
}
#endif
cmd.data0 = slice;
- err |= mxge_send_cmd(sc,
+ err |= mxge_send_cmd(sc,
MXGEFW_CMD_GET_SMALL_RX_OFFSET, &cmd);
- ss->rx_small.lanai =
+ ss->rx_small.lanai =
(volatile mcp_kreq_ether_recv_t *)(sc->sram + cmd.data0);
cmd.data0 = slice;
err |= mxge_send_cmd(sc, MXGEFW_CMD_GET_BIG_RX_OFFSET, &cmd);
- ss->rx_big.lanai =
+ ss->rx_big.lanai =
(volatile mcp_kreq_ether_recv_t *)(sc->sram + cmd.data0);
if (err != 0) {
- device_printf(sc->dev,
+ device_printf(sc->dev,
"failed to get ring sizes or locations\n");
return EIO;
}
@@ -3635,7 +3635,7 @@ mxge_slice_open(struct mxge_slice_state *ss, int nbufs, int cl_size)
return 0;
}
-static int
+static int
mxge_open(mxge_softc_t *sc)
{
mxge_cmd_t cmd;
@@ -3687,7 +3687,7 @@ mxge_open(mxge_softc_t *sc)
cmd.data0 = nbufs;
err = mxge_send_cmd(sc, MXGEFW_CMD_ALWAYS_USE_N_BIG_BUFFERS,
&cmd);
- /* error is only meaningful if we're trying to set
+ /* error is only meaningful if we're trying to set
MXGEFW_CMD_ALWAYS_USE_N_BIG_BUFFERS > 1 */
if (err && nbufs > 1) {
device_printf(sc->dev,
@@ -3712,7 +3712,7 @@ mxge_open(mxge_softc_t *sc)
}
/* Now give him the pointer to the stats block */
- for (slice = 0;
+ for (slice = 0;
#ifdef IFNET_BUF_RING
slice < sc->num_slices;
#else
@@ -3880,7 +3880,7 @@ mxge_watchdog_reset(mxge_softc_t *sc)
device_printf(sc->dev, "Watchdog reset!\n");
- /*
+ /*
* check to see if the NIC rebooted. If it did, then all of
* PCI config space has been reset, and things like the
* busmaster bit will be zero. If this is the case, then we
@@ -3889,10 +3889,10 @@ mxge_watchdog_reset(mxge_softc_t *sc)
*/
cmd = pci_read_config(sc->dev, PCIR_COMMAND, 2);
if (cmd == 0xffff) {
- /*
+ /*
* maybe the watchdog caught the NIC rebooting; wait
* up to 100ms for it to finish. If it does not come
- * back, then give up
+ * back, then give up
*/
DELAY(1000*100);
cmd = pci_read_config(sc->dev, PCIR_COMMAND, 2);
@@ -3908,7 +3908,7 @@ mxge_watchdog_reset(mxge_softc_t *sc)
running = sc->ifp->if_drv_flags & IFF_DRV_RUNNING;
if (running) {
- /*
+ /*
* quiesce NIC so that TX routines will not try to
* xmit after restoration of BAR
*/
@@ -4004,7 +4004,7 @@ mxge_watchdog(mxge_softc_t *sc)
/* see if we have outstanding transmits, which
have been pending for more than mxge_ticks */
- for (i = 0;
+ for (i = 0;
#ifdef IFNET_BUF_RING
(i < sc->num_slices) && (err == 0);
#else
@@ -4036,43 +4036,45 @@ mxge_watchdog(mxge_softc_t *sc)
return (err);
}
-static u_long
-mxge_update_stats(mxge_softc_t *sc)
+static uint64_t
+mxge_get_counter(struct ifnet *ifp, ift_counter cnt)
{
- struct mxge_slice_state *ss;
- u_long pkts = 0;
- u_long ipackets = 0;
- u_long opackets = 0;
-#ifdef IFNET_BUF_RING
- u_long obytes = 0;
- u_long omcasts = 0;
- u_long odrops = 0;
-#endif
- u_long oerrors = 0;
- int slice;
-
- for (slice = 0; slice < sc->num_slices; slice++) {
- ss = &sc->ss[slice];
- ipackets += ss->ipackets;
- opackets += ss->opackets;
+ struct mxge_softc *sc;
+ uint64_t rv;
+
+ sc = if_getsoftc(ifp);
+ rv = 0;
+
+ switch (cnt) {
+ case IFCOUNTER_IPACKETS:
+ for (int s = 0; s < sc->num_slices; s++)
+ rv += sc->ss[s].ipackets;
+ return (rv);
+ case IFCOUNTER_OPACKETS:
+ for (int s = 0; s < sc->num_slices; s++)
+ rv += sc->ss[s].opackets;
+ return (rv);
+ case IFCOUNTER_OERRORS:
+ for (int s = 0; s < sc->num_slices; s++)
+ rv += sc->ss[s].oerrors;
+ return (rv);
#ifdef IFNET_BUF_RING
- obytes += ss->obytes;
- omcasts += ss->omcasts;
- odrops += ss->tx.br->br_drops;
+ case IFCOUNTER_OBYTES:
+ for (int s = 0; s < sc->num_slices; s++)
+ rv += sc->ss[s].obytes;
+ return (rv);
+ case IFCOUNTER_OMCASTS:
+ for (int s = 0; s < sc->num_slices; s++)
+ rv += sc->ss[s].omcasts;
+ return (rv);
+ case IFCOUNTER_OQDROPS:
+ for (int s = 0; s < sc->num_slices; s++)
+ rv += sc->ss[s].tx.br->br_drops;
+ return (rv);
#endif
- oerrors += ss->oerrors;
+ default:
+ return (if_get_counter_default(ifp, cnt));
}
- pkts = (ipackets - sc->ifp->if_ipackets);
- pkts += (opackets - sc->ifp->if_opackets);
- sc->ifp->if_ipackets = ipackets;
- sc->ifp->if_opackets = opackets;
-#ifdef IFNET_BUF_RING
- sc->ifp->if_obytes = obytes;
- sc->ifp->if_omcasts = omcasts;
- sc->ifp->if_oqdrops = odrops;
-#endif
- sc->ifp->if_oerrors = oerrors;
- return pkts;
}
static void
@@ -4087,8 +4089,6 @@ mxge_tick(void *arg)
ticks = mxge_ticks;
running = sc->ifp->if_drv_flags & IFF_DRV_RUNNING;
if (running) {
- /* aggregate stats from different slices */
- pkts = mxge_update_stats(sc);
if (!sc->watchdog_countdown) {
err = mxge_watchdog(sc);
sc->watchdog_countdown = 4;
@@ -4189,7 +4189,7 @@ mxge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
} else {
/* take care of promis can allmulti
flag chages */
- mxge_change_promisc(sc,
+ mxge_change_promisc(sc,
ifp->if_flags & IFF_PROMISC);
mxge_set_multicast_list(sc);
}
@@ -4291,13 +4291,13 @@ mxge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
mtx_lock(&sc->driver_mtx);
mxge_media_probe(sc);
mtx_unlock(&sc->driver_mtx);
- err = ifmedia_ioctl(ifp, (struct ifreq *)data,
+ err = ifmedia_ioctl(ifp, (struct ifreq *)data,
&sc->media, command);
- break;
+ break;
default:
err = ENOTTY;
- }
+ }
return err;
}
@@ -4306,17 +4306,17 @@ mxge_fetch_tunables(mxge_softc_t *sc)
{
TUNABLE_INT_FETCH("hw.mxge.max_slices", &mxge_max_slices);
- TUNABLE_INT_FETCH("hw.mxge.flow_control_enabled",
+ TUNABLE_INT_FETCH("hw.mxge.flow_control_enabled",
&mxge_flow_control);
- TUNABLE_INT_FETCH("hw.mxge.intr_coal_delay",
+ TUNABLE_INT_FETCH("hw.mxge.intr_coal_delay",
&mxge_intr_coal_delay);
- TUNABLE_INT_FETCH("hw.mxge.nvidia_ecrc_enable",
+ TUNABLE_INT_FETCH("hw.mxge.nvidia_ecrc_enable",
&mxge_nvidia_ecrc_enable);
- TUNABLE_INT_FETCH("hw.mxge.force_firmware",
+ TUNABLE_INT_FETCH("hw.mxge.force_firmware",
&mxge_force_firmware);
- TUNABLE_INT_FETCH("hw.mxge.deassert_wait",
+ TUNABLE_INT_FETCH("hw.mxge.deassert_wait",
&mxge_deassert_wait);
- TUNABLE_INT_FETCH("hw.mxge.verbose",
+ TUNABLE_INT_FETCH("hw.mxge.verbose",
&mxge_verbose);
TUNABLE_INT_FETCH("hw.mxge.ticks", &mxge_ticks);
TUNABLE_INT_FETCH("hw.mxge.always_promisc", &mxge_always_promisc);
@@ -4332,7 +4332,7 @@ mxge_fetch_tunables(mxge_softc_t *sc)
if (mxge_ticks == 0)
mxge_ticks = hz / 2;
sc->pause = mxge_flow_control;
- if (mxge_rss_hash_type < MXGEFW_RSS_HASH_TYPE_IPV4
+ if (mxge_rss_hash_type < MXGEFW_RSS_HASH_TYPE_IPV4
|| mxge_rss_hash_type > MXGEFW_RSS_HASH_TYPE_MAX) {
mxge_rss_hash_type = MXGEFW_RSS_HASH_TYPE_SRC_DST_PORT;
}
@@ -4414,7 +4414,7 @@ mxge_alloc_slices(mxge_softc_t *sc)
ss->rx_done.entry = ss->rx_done.dma.addr;
bzero(ss->rx_done.entry, bytes);
- /*
+ /*
* allocate the per-slice firmware stats; stats
* (including tx) are used used only on the first
* slice for now
@@ -4425,7 +4425,7 @@ mxge_alloc_slices(mxge_softc_t *sc)
#endif
bytes = sizeof (*ss->fw_stats);
- err = mxge_dma_alloc(sc, &ss->fw_stats_dma,
+ err = mxge_dma_alloc(sc, &ss->fw_stats_dma,
sizeof (*ss->fw_stats), 64);
if (err != 0)
goto abort;
@@ -4454,9 +4454,9 @@ mxge_slice_probe(mxge_softc_t *sc)
int msix_cnt, status, max_intr_slots;
sc->num_slices = 1;
- /*
+ /*
* don't enable multiple slices if they are not enabled,
- * or if this is not an SMP system
+ * or if this is not an SMP system
*/
if (mxge_max_slices == 0 || mxge_max_slices == 1 || mp_ncpus < 2)
@@ -4593,7 +4593,7 @@ mxge_add_msix_irqs(mxge_softc_t *sc)
sc->msix_ih = malloc(bytes, M_DEVBUF, M_NOWAIT|M_ZERO);
for (i = 0; i < sc->num_slices; i++) {
- err = bus_setup_intr(sc->dev, sc->msix_irq_res[i],
+ err = bus_setup_intr(sc->dev, sc->msix_irq_res[i],
INTR_TYPE_NET | INTR_MPSAFE,
#if __FreeBSD_version > 700030
NULL,
@@ -4671,7 +4671,7 @@ mxge_add_single_irq(mxge_softc_t *sc)
device_printf(sc->dev, "using %s irq %ld\n",
sc->legacy_irq ? "INTx" : "MSI",
rman_get_start(sc->irq_res));
- err = bus_setup_intr(sc->dev, sc->irq_res,
+ err = bus_setup_intr(sc->dev, sc->irq_res,
INTR_TYPE_NET | INTR_MPSAFE,
#if __FreeBSD_version > 700030
NULL,
@@ -4753,7 +4753,7 @@ mxge_add_irq(mxge_softc_t *sc)
}
-static int
+static int
mxge_attach(device_t dev)
{
mxge_cmd_t cmd;
@@ -4835,7 +4835,7 @@ mxge_attach(device_t dev)
bus_space_read_region_1(rman_get_bustag(sc->mem_res),
rman_get_bushandle(sc->mem_res),
sc->sram_size - MXGE_EEPROM_STRINGS_SIZE,
- sc->eeprom_strings,
+ sc->eeprom_strings,
MXGE_EEPROM_STRINGS_SIZE - 2);
err = mxge_parse_strings(sc);
if (err != 0)
@@ -4845,13 +4845,13 @@ mxge_attach(device_t dev)
mxge_enable_wc(sc);
/* Allocate the out of band dma memory */
- err = mxge_dma_alloc(sc, &sc->cmd_dma,
+ err = mxge_dma_alloc(sc, &sc->cmd_dma,
sizeof (mxge_cmd_t), 64);
- if (err != 0)
+ if (err != 0)
goto abort_with_mem_res;
sc->cmd = (mcp_cmd_response_t *) sc->cmd_dma.addr;
err = mxge_dma_alloc(sc, &sc->zeropad_dma, 64, 64);
- if (err != 0)
+ if (err != 0)
goto abort_with_cmd_dma;
err = mxge_dma_alloc(sc, &sc->dmabench_dma, 4096, 4096);
@@ -4920,13 +4920,14 @@ mxge_attach(device_t dev)
ifp->if_capenable = ifp->if_capabilities;
if (sc->lro_cnt == 0)
ifp->if_capenable &= ~IFCAP_LRO;
- ifp->if_init = mxge_init;
- ifp->if_softc = sc;
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_ioctl = mxge_ioctl;
- ifp->if_start = mxge_start;
+ ifp->if_init = mxge_init;
+ ifp->if_softc = sc;
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_ioctl = mxge_ioctl;
+ ifp->if_start = mxge_start;
+ ifp->if_get_counter = mxge_get_counter;
/* Initialise the ifmedia structure */
- ifmedia_init(&sc->media, 0, mxge_media_change,
+ ifmedia_init(&sc->media, 0, mxge_media_change,
mxge_media_status);
mxge_media_init(sc);
mxge_media_probe(sc);
diff --git a/sys/pci/locate.pl b/sys/dev/ncr/locate.pl
index 89688e1..89688e1 100755
--- a/sys/pci/locate.pl
+++ b/sys/dev/ncr/locate.pl
diff --git a/sys/pci/ncr.c b/sys/dev/ncr/ncr.c
index d13769c..6c941e1 100644
--- a/sys/pci/ncr.c
+++ b/sys/dev/ncr/ncr.c
@@ -43,11 +43,6 @@
__FBSDID("$FreeBSD$");
-#define NCR_DATE "pl30 98/1/1"
-
-#define NCR_VERSION (2)
-#define MAX_UNITS (16)
-
#define NCR_GETCC_WITHMSG
#if defined (__FreeBSD__) && defined(_KERNEL)
@@ -197,7 +192,7 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
-#include <pci/ncrreg.h>
+#include <dev/ncr/ncrreg.h>
#include <cam/cam.h>
#include <cam/cam_ccb.h>
@@ -274,25 +269,22 @@ __FBSDID("$FreeBSD$");
**==========================================================
*/
-#define INB(r) bus_space_read_1(np->bst, np->bsh, offsetof(struct ncr_reg, r))
-#define INW(r) bus_space_read_2(np->bst, np->bsh, offsetof(struct ncr_reg, r))
-#define INL(r) bus_space_read_4(np->bst, np->bsh, offsetof(struct ncr_reg, r))
+#define INB(r) bus_read_1(np->reg_res, offsetof(struct ncr_reg, r))
+#define INW(r) bus_read_2(np->reg_res, offsetof(struct ncr_reg, r))
+#define INL(r) bus_read_4(np->reg_res, offsetof(struct ncr_reg, r))
-#define OUTB(r, val) bus_space_write_1(np->bst, np->bsh, \
- offsetof(struct ncr_reg, r), val)
-#define OUTW(r, val) bus_space_write_2(np->bst, np->bsh, \
- offsetof(struct ncr_reg, r), val)
-#define OUTL(r, val) bus_space_write_4(np->bst, np->bsh, \
- offsetof(struct ncr_reg, r), val)
-#define OUTL_OFF(o, val) bus_space_write_4(np->bst, np->bsh, o, val)
+#define OUTB(r, val) bus_write_1(np->reg_res, offsetof(struct ncr_reg, r), val)
+#define OUTW(r, val) bus_write_2(np->reg_res, offsetof(struct ncr_reg, r), val)
+#define OUTL(r, val) bus_write_4(np->reg_res, offsetof(struct ncr_reg, r), val)
+#define OUTL_OFF(o, val) bus_write_4(np->reg_res, o, val)
-#define INB_OFF(o) bus_space_read_1(np->bst, np->bsh, o)
-#define INW_OFF(o) bus_space_read_2(np->bst, np->bsh, o)
-#define INL_OFF(o) bus_space_read_4(np->bst, np->bsh, o)
+#define INB_OFF(o) bus_read_1(np->reg_res, o)
+#define INW_OFF(o) bus_read_2(np->reg_res, o)
+#define INL_OFF(o) bus_read_4(np->reg_res, o)
#define READSCRIPT_OFF(base, off) \
(base ? *((volatile u_int32_t *)((volatile char *)base + (off))) : \
- bus_space_read_4(np->bst2, np->bsh2, off))
+ bus_read_4(np->sram_res, off))
#define WRITESCRIPT_OFF(base, off, val) \
do { \
@@ -300,7 +292,7 @@ __FBSDID("$FreeBSD$");
*((volatile u_int32_t *) \
((volatile char *)base + (off))) = (val); \
else \
- bus_space_write_4(np->bst2, np->bsh2, off, val); \
+ bus_write_4(np->sram_res, off, val); \
} while (0)
#define READSCRIPT(r) \
@@ -974,7 +966,7 @@ struct ncb {
*/
struct head header;
- int unit;
+ device_t dev;
/*-----------------------------------------------
** Scripts ..
@@ -999,13 +991,9 @@ struct ncb {
*/
int reg_rid;
struct resource *reg_res;
- bus_space_tag_t bst;
- bus_space_handle_t bsh;
int sram_rid;
struct resource *sram_res;
- bus_space_tag_t bst2;
- bus_space_handle_t bsh2;
struct resource *irq_res;
void *irq_handle;
@@ -1086,7 +1074,7 @@ struct ncb {
u_short ticks;
u_short latetime;
time_t lasttime;
- struct callout_handle timeout_ch;
+ struct callout timer;
/*-----------------------------------------------
** Debug and profiling
@@ -1129,6 +1117,7 @@ struct ncb {
*/
u_char maxwide;
+ struct mtx lock;
#ifdef NCR_IOMAPPED
/*
** address of the ncr control registers in io space
@@ -1261,6 +1250,7 @@ static u_int32_t ncr_info(int unit);
#endif
static void ncr_init(ncb_p np, char * msg, u_long code);
static void ncr_intr(void *vnp);
+static void ncr_intr_locked(ncb_p np);
static void ncr_int_ma(ncb_p np, u_char dstat);
static void ncr_int_sir(ncb_p np);
static void ncr_int_sto(ncb_p np);
@@ -1299,12 +1289,6 @@ static int ncr_attach(device_t dev);
**==========================================================
*/
-static const u_long ncr_version = NCR_VERSION * 11
- + (u_long) sizeof (struct ncb) * 7
- + (u_long) sizeof (struct nccb) * 5
- + (u_long) sizeof (struct lcb) * 3
- + (u_long) sizeof (struct tcb) * 2;
-
#ifdef _KERNEL
static int ncr_debug = SCSI_NCR_DEBUG;
@@ -1335,13 +1319,6 @@ static int ncr_cache; /* to be aligned _NOT_ static */
#define NCR_1510D_ID (0x000a1000ul)
-static char *ncr_name (ncb_p np)
-{
- static char name[10];
- snprintf(name, sizeof(name), "ncr%d", np->unit);
- return (name);
-}
-
/*==========================================================
**
**
@@ -3017,8 +2994,8 @@ static void ncr_script_copy_and_bind (ncb_p np, ncrcmd *src, ncrcmd *dst, int le
*/
if (opcode == 0) {
- printf ("%s: ERROR0 IN SCRIPT at %d.\n",
- ncr_name(np), (int) (src-start-1));
+ device_printf(np->dev, "ERROR0 IN SCRIPT at %d.\n",
+ (int)(src - start - 1));
DELAY (1000000);
};
@@ -3043,8 +3020,9 @@ static void ncr_script_copy_and_bind (ncb_p np, ncrcmd *src, ncrcmd *dst, int le
if ((tmp2 & RELOC_MASK) == RELOC_KVAR)
tmp2 = 0;
if ((tmp1 ^ tmp2) & 3) {
- printf ("%s: ERROR1 IN SCRIPT at %d.\n",
- ncr_name(np), (int) (src-start-1));
+ device_printf(np->dev,
+ "ERROR1 IN SCRIPT at %d.\n",
+ (int)(src - start - 1));
DELAY (1000000);
}
/*
@@ -3368,14 +3346,16 @@ ncr_attach (device_t dev)
** allocate and initialize structures.
*/
- np->unit = device_get_unit(dev);
+ np->dev = dev;
+ mtx_init(&np->lock, "ncr", NULL, MTX_DEF);
+ callout_init_mtx(&np->timer, &np->lock, 0);
/*
** Try to map the controller chip to
** virtual and physical memory.
*/
- np->reg_rid = 0x14;
+ np->reg_rid = PCIR_BAR(1);
np->reg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
&np->reg_rid, RF_ACTIVE);
if (!np->reg_res) {
@@ -3384,15 +3364,10 @@ ncr_attach (device_t dev)
}
/*
- ** Make the controller's registers available.
** Now the INB INW INL OUTB OUTW OUTL macros
** can be used safely.
*/
- np->bst = rman_get_bustag(np->reg_res);
- np->bsh = rman_get_bushandle(np->reg_res);
-
-
#ifdef NCR_IOMAPPED
/*
** Try to map the controller chip into iospace.
@@ -3463,8 +3438,7 @@ ncr_attach (device_t dev)
#ifdef NCR_TEKRAM_EEPROM
if (bootverbose) {
- printf ("%s: Tekram EEPROM read %s\n",
- ncr_name(np),
+ device_printf(dev, "Tekram EEPROM read %s\n",
read_tekram_eeprom (np, NULL) ?
"succeeded" : "failed");
}
@@ -3572,7 +3546,7 @@ ncr_attach (device_t dev)
** Get on-chip SRAM address, if supported
*/
if ((np->features & FE_RAM) && sizeof(struct script) <= 4096) {
- np->sram_rid = 0x18;
+ np->sram_rid = PCIR_BAR(2);
np->sram_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
&np->sram_rid,
RF_ACTIVE);
@@ -3584,8 +3558,6 @@ ncr_attach (device_t dev)
if (np->sram_res != NULL) {
np->script = NULL;
np->p_script = rman_get_start(np->sram_res);
- np->bst2 = rman_get_bustag(np->sram_res);
- np->bsh2 = rman_get_bushandle(np->sram_res);
} else if (sizeof (struct script) > PAGE_SIZE) {
np->script = (struct script*) contigmalloc
(round_page(sizeof (struct script)), M_DEVBUF, M_WAITOK,
@@ -3617,15 +3589,16 @@ ncr_attach (device_t dev)
if (!cachelnsz) {
cachelnsz = 8;
- printf("%s: setting PCI cache line size register to %d.\n",
- ncr_name(np), (int)cachelnsz);
+ device_printf(dev,
+ "setting PCI cache line size register to %d.\n",
+ (int)cachelnsz);
pci_write_config(dev, PCIR_CACHELNSZ, cachelnsz, 1);
}
if (!(command & PCIM_CMD_MWRICEN)) {
command |= PCIM_CMD_MWRICEN;
- printf("%s: setting PCI command write and invalidate.\n",
- ncr_name(np));
+ device_printf(dev,
+ "setting PCI command write and invalidate.\n");
pci_write_config(dev, PCIR_COMMAND, command, 2);
}
}
@@ -3662,8 +3635,9 @@ ncr_attach (device_t dev)
** Bells and whistles ;-)
*/
if (bootverbose)
- printf("%s: minsync=%d, maxsync=%d, maxoffs=%d, %d dwords burst, %s dma fifo\n",
- ncr_name(np), np->minsync, np->maxsync, np->maxoffs,
+ device_printf(dev,
+ "minsync=%d, maxsync=%d, maxoffs=%d, %d dwords burst, %s dma fifo\n",
+ np->minsync, np->maxsync, np->maxoffs,
burst_length(np->maxburst),
(np->rv_ctest5 & DFS) ? "large" : "normal");
@@ -3671,8 +3645,7 @@ ncr_attach (device_t dev)
** Print some complementary information that can be helpfull.
*/
if (bootverbose)
- printf("%s: %s, %s IRQ driver%s\n",
- ncr_name(np),
+ device_printf(dev, "%s, %s IRQ driver%s\n",
np->rv_stest2 & 0x20 ? "differential" : "single-ended",
np->rv_dcntl & IRQM ? "totem pole" : "open drain",
np->sram_res ? ", using on-chip SRAM" : "");
@@ -3759,8 +3732,8 @@ ncr_attach (device_t dev)
device_printf(dev,
"interruptless mode: reduced performance.\n");
} else {
- bus_setup_intr(dev, np->irq_res, INTR_TYPE_CAM | INTR_ENTROPY,
- NULL, ncr_intr, np, &np->irq_handle);
+ bus_setup_intr(dev, np->irq_res, INTR_TYPE_CAM | INTR_ENTROPY |
+ INTR_MPSAFE, NULL, ncr_intr, np, &np->irq_handle);
}
/*
@@ -3776,16 +3749,17 @@ ncr_attach (device_t dev)
** Now tell the generic SCSI layer
** about our bus.
*/
- np->sim = cam_sim_alloc(ncr_action, ncr_poll, "ncr", np, np->unit,
- &Giant, 1, MAX_TAGS, devq);
+ np->sim = cam_sim_alloc(ncr_action, ncr_poll, "ncr", np,
+ device_get_unit(dev), &np->lock, 1, MAX_TAGS, devq);
if (np->sim == NULL) {
cam_simq_free(devq);
return ENOMEM;
}
-
+ mtx_lock(&np->lock);
if (xpt_bus_register(np->sim, dev, 0) != CAM_SUCCESS) {
cam_sim_free(np->sim, /*free_devq*/ TRUE);
+ mtx_unlock(&np->lock);
return ENOMEM;
}
@@ -3794,6 +3768,7 @@ ncr_attach (device_t dev)
CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
xpt_bus_deregister(cam_sim_path(np->sim));
cam_sim_free(np->sim, /*free_devq*/TRUE);
+ mtx_unlock(&np->lock);
return ENOMEM;
}
@@ -3802,6 +3777,7 @@ ncr_attach (device_t dev)
*/
ncr_timeout (np);
np->lasttime=0;
+ mtx_unlock(&np->lock);
return 0;
}
@@ -3820,7 +3796,15 @@ ncr_intr(vnp)
void *vnp;
{
ncb_p np = vnp;
- int oldspl = splcam();
+
+ mtx_lock(&np->lock);
+ ncr_intr_locked(np);
+ mtx_unlock(&np->lock);
+}
+
+static void
+ncr_intr_locked(ncb_p np)
+{
if (DEBUG_FLAGS & DEBUG_TINY) printf ("[");
@@ -3836,8 +3820,6 @@ ncr_intr(vnp)
};
if (DEBUG_FLAGS & DEBUG_TINY) printf ("]\n");
-
- splx (oldspl);
}
/*==========================================================
@@ -3856,6 +3838,7 @@ ncr_action (struct cam_sim *sim, union ccb *ccb)
ncb_p np;
np = (ncb_p) cam_sim_softc(sim);
+ mtx_assert(&np->lock, MA_OWNED);
switch (ccb->ccb_h.func_code) {
/* Common cases first */
@@ -3864,7 +3847,6 @@ ncr_action (struct cam_sim *sim, union ccb *ccb)
nccb_p cp;
lcb_p lp;
tcb_p tp;
- int oldspl;
struct ccb_scsiio *csio;
u_int8_t *msgptr;
u_int msglen;
@@ -3877,15 +3859,12 @@ ncr_action (struct cam_sim *sim, union ccb *ccb)
tp = &np->target[ccb->ccb_h.target_id];
csio = &ccb->csio;
- oldspl = splcam();
-
/*
* Last time we need to check if this CCB needs to
* be aborted.
*/
if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
xpt_done(ccb);
- splx(oldspl);
return;
}
ccb->ccb_h.status |= CAM_SIM_QUEUED;
@@ -4040,7 +4019,6 @@ ncr_action (struct cam_sim *sim, union ccb *ccb)
if (segments < 0) {
ccb->ccb_h.status = CAM_REQ_TOO_BIG;
ncr_free_nccb(np, cp);
- splx(oldspl);
xpt_done(ccb);
return;
}
@@ -4153,8 +4131,8 @@ ncr_action (struct cam_sim *sim, union ccb *ccb)
np->squeueput = qidx;
if(DEBUG_FLAGS & DEBUG_QUEUE)
- printf("%s: queuepos=%d tryoffset=%d.\n",
- ncr_name (np), np->squeueput,
+ device_printf(np->dev, "queuepos=%d tryoffset=%d.\n",
+ np->squeueput,
(unsigned)(READSCRIPT(startpos[0]) -
(NCB_SCRIPTH_PHYS (np, tryloop))));
@@ -4163,11 +4141,6 @@ ncr_action (struct cam_sim *sim, union ccb *ccb)
** Wake it up.
*/
OUTB (nc_istat, SIGP);
-
- /*
- ** and reenable interrupts
- */
- splx (oldspl);
break;
}
case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */
@@ -4185,7 +4158,6 @@ ncr_action (struct cam_sim *sim, union ccb *ccb)
struct ccb_trans_settings *cts = &ccb->cts;
tcb_p tp;
u_int update_type;
- int s;
struct ccb_trans_settings_scsi *scsi =
&cts->proto_specific.scsi;
struct ccb_trans_settings_spi *spi =
@@ -4197,7 +4169,6 @@ ncr_action (struct cam_sim *sim, union ccb *ccb)
if (cts->type == CTS_TYPE_USER_SETTINGS)
update_type |= NCR_TRANS_USER;
- s = splcam();
tp = &np->target[ccb->ccb_h.target_id];
/* Tag and disc enables */
if ((spi->valid & CTS_SPI_VALID_DISC) != 0) {
@@ -4271,7 +4242,6 @@ ncr_action (struct cam_sim *sim, union ccb *ccb)
if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0)
tp->tinfo.goal.width = spi->bus_width;
}
- splx(s);
ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
break;
@@ -4282,7 +4252,6 @@ ncr_action (struct cam_sim *sim, union ccb *ccb)
struct ccb_trans_settings *cts = &ccb->cts;
struct ncr_transinfo *tinfo;
tcb_p tp = &np->target[ccb->ccb_h.target_id];
- int s;
struct ccb_trans_settings_scsi *scsi =
&cts->proto_specific.scsi;
struct ccb_trans_settings_spi *spi =
@@ -4293,7 +4262,6 @@ ncr_action (struct cam_sim *sim, union ccb *ccb)
cts->transport = XPORT_SPI;
cts->transport_version = 2;
- s = splcam();
if (cts->type == CTS_TYPE_CURRENT_SETTINGS) {
tinfo = &tp->tinfo.current;
if (tp->tinfo.disc_tag & NCR_CUR_DISCENB)
@@ -4322,7 +4290,6 @@ ncr_action (struct cam_sim *sim, union ccb *ccb)
spi->sync_offset = tinfo->offset;
spi->bus_width = tinfo->width;
- splx(s);
spi->valid = CTS_SPI_VALID_SYNC_RATE
| CTS_SPI_VALID_SYNC_OFFSET
| CTS_SPI_VALID_BUS_WIDTH
@@ -4718,7 +4685,8 @@ ncr_init(ncb_p np, char * msg, u_long code)
** Message.
*/
- if (msg) printf ("%s: restart (%s).\n", ncr_name (np), msg);
+ if (msg)
+ device_printf(np->dev, "restart (%s).\n", msg);
/*
** Clear Start Queue
@@ -4813,7 +4781,7 @@ ncr_init(ncb_p np, char * msg, u_long code)
static void
ncr_poll(struct cam_sim *sim)
{
- ncr_intr(cam_sim_softc(sim));
+ ncr_intr_locked(cam_sim_softc(sim));
}
@@ -5089,11 +5057,8 @@ ncr_timeout (void *arg)
long signed t;
nccb_p cp;
+ mtx_assert(&np->lock, MA_OWNED);
if (np->lasttime != thistime) {
- /*
- ** block ncr interrupts
- */
- int oldspl = splcam();
np->lasttime = thistime;
/*----------------------------------------------------
@@ -5143,8 +5108,8 @@ ncr_timeout (void *arg)
cp->jump_nccb.l_cmd = (SCR_JUMP);
if (cp->phys.header.launch.l_paddr ==
NCB_SCRIPT_PHYS (np, select)) {
- printf ("%s: timeout nccb=%p (skip)\n",
- ncr_name (np), cp);
+ device_printf(np->dev,
+ "timeout nccb=%p (skip)\n", cp);
cp->phys.header.launch.l_paddr
= NCB_SCRIPT_PHYS (np, skip);
};
@@ -5164,11 +5129,9 @@ ncr_timeout (void *arg)
*/
ncr_complete (np, cp);
};
- splx (oldspl);
}
- np->timeout_ch =
- timeout (ncr_timeout, (caddr_t) np, step ? step : 1);
+ callout_reset(&np->timer, step ? step : 1, ncr_timeout, np);
if (INB(nc_istat) & (INTF|SIP|DIP)) {
@@ -5176,11 +5139,9 @@ ncr_timeout (void *arg)
** Process pending interrupts.
*/
- int oldspl = splcam();
if (DEBUG_FLAGS & DEBUG_TINY) printf ("{");
ncr_exception (np);
if (DEBUG_FLAGS & DEBUG_TINY) printf ("}");
- splx (oldspl);
};
}
@@ -5245,19 +5206,20 @@ static void ncr_log_hard_error(ncb_p np, u_short sist, u_char dstat)
script_name = "mem";
}
- printf ("%s:%d: ERROR (%x:%x) (%x-%x-%x) (%x/%x) @ (%s %x:%08x).\n",
- ncr_name (np), (unsigned)INB (nc_sdid)&0x0f, dstat, sist,
+ device_printf(np->dev,
+ "%d: ERROR (%x:%x) (%x-%x-%x) (%x/%x) @ (%s %x:%08x).\n",
+ (unsigned)INB (nc_sdid)&0x0f, dstat, sist,
(unsigned)INB (nc_socl), (unsigned)INB (nc_sbcl), (unsigned)INB (nc_sbdl),
(unsigned)INB (nc_sxfer),(unsigned)INB (nc_scntl3), script_name, script_ofs,
(unsigned)INL (nc_dbc));
if (((script_ofs & 3) == 0) &&
(unsigned)script_ofs < script_size) {
- printf ("%s: script cmd = %08x\n", ncr_name(np),
+ device_printf(np->dev, "script cmd = %08x\n",
(int)READSCRIPT_OFF(script_base, script_ofs));
}
- printf ("%s: regdump:", ncr_name(np));
+ device_printf(np->dev, "regdump:");
for (i=0; i<16;i++)
printf (" %02x", (unsigned)INB_OFF(i));
printf (".\n");
@@ -5411,7 +5373,7 @@ static void ncr_exception (ncb_p np)
(INB(nc_sstat1) & (FF3210) ) ||
(INB(nc_sstat2) & (ILF1|ORF1|OLF1)) || /* wide .. */
!(dstat & DFE)) {
- printf ("%s: have to clear fifos.\n", ncr_name (np));
+ device_printf(np->dev, "have to clear fifos.\n");
OUTB (nc_stest3, TE|CSF); /* clear scsi fifo */
OUTB (nc_ctest3, np->rv_ctest3 | CLF);
/* clear dma fifo */
@@ -5423,7 +5385,7 @@ static void ncr_exception (ncb_p np)
*/
if (sist & HTH) {
- printf ("%s: handshake timeout\n", ncr_name(np));
+ device_printf(np->dev, "handshake timeout\n");
OUTB (nc_scntl1, CRST);
DELAY (1000);
OUTB (nc_scntl1, 0x00);
@@ -5466,12 +5428,11 @@ static void ncr_exception (ncb_p np)
/*
** info message
*/
- printf ("%s: INFO: LDSC while IID.\n",
- ncr_name (np));
+ device_printf(np->dev, "INFO: LDSC while IID.\n");
return;
};
- printf ("%s: target %d doesn't release the bus.\n",
- ncr_name (np), INB (nc_sdid)&0x0f);
+ device_printf(np->dev, "target %d doesn't release the bus.\n",
+ INB (nc_sdid)&0x0f);
/*
** return without restarting the NCR.
** timeout will do the real work.
@@ -5515,8 +5476,7 @@ static void ncr_exception (ncb_p np)
switch (i%16) {
case 0:
- printf ("%s: reg[%d0]: ",
- ncr_name(np),i/16);
+ device_printf(np->dev, "reg[%d0]: ", i / 16);
break;
case 4:
case 8:
@@ -5524,14 +5484,14 @@ static void ncr_exception (ncb_p np)
printf (" ");
break;
};
- val = bus_space_read_1(np->bst, np->bsh, i);
+ val = bus_read_1(np->reg_res, i);
printf (" %x%x", val/16, val%16);
if (i%16==15) printf (".\n");
};
- untimeout (ncr_timeout, (caddr_t) np, np->timeout_ch);
+ callout_stop(&np->timer);
- printf ("%s: halted!\n", ncr_name(np));
+ device_printf(np->dev, "halted!\n");
/*
** don't restart controller ...
*/
@@ -5678,14 +5638,16 @@ static void ncr_int_ma (ncb_p np, u_char dstat)
cp = cp->link_nccb;
if (!cp) {
- printf ("%s: SCSI phase error fixup: CCB already dequeued (%p)\n",
- ncr_name (np), (void *) np->header.cp);
- return;
+ device_printf(np->dev,
+ "SCSI phase error fixup: CCB already dequeued (%p)\n",
+ (void *)np->header.cp);
+ return;
}
if (cp != np->header.cp) {
- printf ("%s: SCSI phase error fixup: CCB address mismatch "
+ device_printf(np->dev,
+ "SCSI phase error fixup: CCB address mismatch "
"(%p != %p) np->nccb = %p\n",
- ncr_name (np), (void *)cp, (void *)np->header.cp,
+ (void *)cp, (void *)np->header.cp,
(void *)np->link_nccb);
/* return;*/
}
@@ -5889,7 +5851,7 @@ static void ncr_int_sir (ncb_p np)
*/
if (DEBUG_FLAGS & DEBUG_RESTART)
- printf ("%s: int#%d",ncr_name (np),num);
+ device_printf(np->dev, "int#%d", num);
cp = (nccb_p) 0;
for (i=0; i<MAX_TARGET; i++) {
if (DEBUG_FLAGS & DEBUG_RESTART) printf (" t%d", i);
@@ -6374,7 +6336,7 @@ static void ncr_int_sir (ncb_p np)
** else remove the interrupt.
*/
- printf ("%s: queue empty.\n", ncr_name (np));
+ device_printf(np->dev, "queue empty.\n");
WRITESCRIPT(start1[0], SCR_INT ^ IFFALSE (0));
break;
};
@@ -6424,7 +6386,7 @@ static nccb_p ncr_get_nccb
if (cp != NULL) {
if (cp->magic) {
- printf("%s: Bogus free cp found\n", ncr_name(np));
+ device_printf(np->dev, "Bogus free cp found\n");
return (NULL);
}
cp->magic = 1;
@@ -6913,7 +6875,7 @@ static void ncr_selectclock(ncb_p np, u_char scntl3)
}
if (bootverbose >= 2)
- printf ("%s: enabling clock multiplier\n", ncr_name(np));
+ device_printf(np->dev, "enabling clock multiplier\n");
OUTB(nc_stest1, DBLEN); /* Enable clock multiplier */
if (np->multiplier > 2) { /* Poll bit 5 of stest4 for quadrupler */
@@ -6921,7 +6883,8 @@ static void ncr_selectclock(ncb_p np, u_char scntl3)
while (!(INB(nc_stest4) & LCKFRQ) && --i > 0)
DELAY(20);
if (!i)
- printf("%s: the chip cannot lock the frequency\n", ncr_name(np));
+ device_printf(np->dev,
+ "the chip cannot lock the frequency\n");
} else /* Wait 20 micro-seconds for doubler */
DELAY(20);
OUTB(nc_stest3, HSC); /* Halt the scsi clock */
diff --git a/sys/pci/ncrreg.h b/sys/dev/ncr/ncrreg.h
index 34f1618..34f1618 100644
--- a/sys/pci/ncrreg.h
+++ b/sys/dev/ncr/ncrreg.h
diff --git a/sys/dev/netmap/netmap.c b/sys/dev/netmap/netmap.c
index 0fd362f..f37bf9e 100644
--- a/sys/dev/netmap/netmap.c
+++ b/sys/dev/netmap/netmap.c
@@ -2222,23 +2222,18 @@ netmap_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
default: /* allow device-specific ioctls */
{
- struct socket so;
- struct ifnet *ifp;
+ struct ifnet *ifp = ifunit_ref(nmr->nr_name);
+ if (ifp == NULL) {
+ error = ENXIO;
+ } else {
+ struct socket so;
- bzero(&so, sizeof(so));
- NMG_LOCK();
- error = netmap_get_na(nmr, &na, 0 /* don't create */); /* keep reference */
- if (error) {
- netmap_adapter_put(na);
- NMG_UNLOCK();
- break;
+ bzero(&so, sizeof(so));
+ so.so_vnet = ifp->if_vnet;
+ // so->so_proto not null.
+ error = ifioctl(&so, cmd, data, td);
+ if_rele(ifp);
}
- ifp = na->ifp;
- so.so_vnet = ifp->if_vnet;
- // so->so_proto not null.
- error = ifioctl(&so, cmd, data, td);
- netmap_adapter_put(na);
- NMG_UNLOCK();
break;
}
diff --git a/sys/dev/netmap/netmap_kern.h b/sys/dev/netmap/netmap_kern.h
index e97d5b5..76d8935 100644
--- a/sys/dev/netmap/netmap_kern.h
+++ b/sys/dev/netmap/netmap_kern.h
@@ -63,6 +63,12 @@
#define NM_ATOMIC_TEST_AND_SET(p) (!atomic_cmpset_acq_int((p), 0, 1))
#define NM_ATOMIC_CLEAR(p) atomic_store_rel_int((p), 0)
+#if __FreeBSD_version >= 1100030
+#define WNA(_ifp) (_ifp)->if_netmap
+#else /* older FreeBSD */
+#define WNA(_ifp) (_ifp)->if_pspare[0]
+#endif /* older FreeBSD */
+
#if __FreeBSD_version >= 1100005
struct netmap_adapter *netmap_getna(if_t ifp);
#endif
@@ -1186,9 +1192,6 @@ extern int netmap_generic_rings;
* NA returns a pointer to the struct netmap adapter from the ifp,
* WNA is used to write it.
*/
-#ifndef WNA
-#define WNA(_ifp) (_ifp)->if_netmap
-#endif
#define NA(_ifp) ((struct netmap_adapter *)WNA(_ifp))
/*
diff --git a/sys/pci/nfsmb.c b/sys/dev/nfsmb/nfsmb.c
index a178ae3..a178ae3 100644
--- a/sys/pci/nfsmb.c
+++ b/sys/dev/nfsmb/nfsmb.c
diff --git a/sys/dev/oce/oce_if.c b/sys/dev/oce/oce_if.c
index 3348efc..fe48007 100644
--- a/sys/dev/oce/oce_if.c
+++ b/sys/dev/oce/oce_if.c
@@ -1731,7 +1731,9 @@ oce_attach_ifp(POCE_SOFTC sc)
sc->ifp->if_baudrate = IF_Gbps(10);
#if __FreeBSD_version >= 1000000
- sc->ifp->if_hw_tsomax = OCE_MAX_TSO_SIZE;
+ sc->ifp->if_hw_tsomax = 65536 - (ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN);
+ sc->ifp->if_hw_tsomaxsegcount = OCE_MAX_TX_ELEMENTS;
+ sc->ifp->if_hw_tsomaxsegsize = 4096;
#endif
ether_ifattach(sc->ifp, sc->macaddr.mac_addr);
diff --git a/sys/dev/oce/oce_if.h b/sys/dev/oce/oce_if.h
index b6db402..bb78841 100644
--- a/sys/dev/oce/oce_if.h
+++ b/sys/dev/oce/oce_if.h
@@ -152,7 +152,6 @@ extern int mp_ncpus; /* system's total active cpu cores */
#define OCE_MAX_TX_ELEMENTS 29
#define OCE_MAX_TX_DESC 1024
#define OCE_MAX_TX_SIZE 65535
-#define OCE_MAX_TSO_SIZE (65535 - ETHER_HDR_LEN)
#define OCE_MAX_RX_SIZE 4096
#define OCE_MAX_RQ_POSTS 255
#define OCE_DEFAULT_PROMISCUOUS 0
diff --git a/sys/dev/ofw/ofw_bus_subr.c b/sys/dev/ofw/ofw_bus_subr.c
index 7ddb5e6..cd11693 100644
--- a/sys/dev/ofw/ofw_bus_subr.c
+++ b/sys/dev/ofw/ofw_bus_subr.c
@@ -37,6 +37,8 @@ __FBSDID("$FreeBSD$");
#include <sys/errno.h>
#include <sys/libkern.h>
+#include <machine/resource.h>
+
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <dev/ofw/openfirm.h>
@@ -367,3 +369,64 @@ ofw_bus_search_intrmap(void *intr, int intrsz, void *regs, int physsz,
return (0);
}
+int
+ofw_bus_intr_to_rl(device_t dev, phandle_t node, struct resource_list *rl)
+{
+ phandle_t iparent;
+ uint32_t icells, *intr;
+ int err, i, irqnum, nintr, rid;
+ boolean_t extended;
+
+ nintr = OF_getencprop_alloc(node, "interrupts", sizeof(*intr),
+ (void **)&intr);
+ if (nintr > 0) {
+ if (OF_searchencprop(node, "interrupt-parent", &iparent,
+ sizeof(iparent)) == -1) {
+ device_printf(dev, "No interrupt-parent found, "
+ "assuming direct parent\n");
+ iparent = OF_parent(node);
+ }
+ if (OF_searchencprop(OF_node_from_xref(iparent),
+ "#interrupt-cells", &icells, sizeof(icells)) == -1) {
+ device_printf(dev, "Missing #interrupt-cells "
+ "property, assuming <1>\n");
+ icells = 1;
+ }
+ if (icells < 1 || icells > nintr) {
+ device_printf(dev, "Invalid #interrupt-cells property "
+ "value <%d>, assuming <1>\n", icells);
+ icells = 1;
+ }
+ extended = false;
+ } else {
+ nintr = OF_getencprop_alloc(node, "interrupts-extended",
+ sizeof(*intr), (void **)&intr);
+ if (nintr <= 0)
+ return (0);
+ extended = true;
+ }
+ err = 0;
+ rid = 0;
+ for (i = 0; i < nintr; i += icells) {
+ if (extended) {
+ iparent = intr[i++];
+ if (OF_searchencprop(OF_node_from_xref(iparent),
+ "#interrupt-cells", &icells, sizeof(icells)) == -1) {
+ device_printf(dev, "Missing #interrupt-cells "
+ "property\n");
+ err = ENOENT;
+ break;
+ }
+ if (icells < 1 || (i + icells) > nintr) {
+ device_printf(dev, "Invalid #interrupt-cells "
+ "property value <%d>\n", icells);
+ err = ERANGE;
+ break;
+ }
+ }
+ irqnum = ofw_bus_map_intr(dev, iparent, icells, &intr[i]);
+ resource_list_add(rl, SYS_RES_IRQ, rid++, irqnum, irqnum, 1);
+ }
+ free(intr, M_OFWPROP);
+ return (err);
+}
diff --git a/sys/dev/ofw/ofw_bus_subr.h b/sys/dev/ofw/ofw_bus_subr.h
index a4d8b92..59f83fc 100644
--- a/sys/dev/ofw/ofw_bus_subr.h
+++ b/sys/dev/ofw/ofw_bus_subr.h
@@ -72,6 +72,9 @@ int ofw_bus_lookup_imap(phandle_t, struct ofw_bus_iinfo *, void *, int,
int ofw_bus_search_intrmap(void *, int, void *, int, void *, int, void *,
void *, void *, int, phandle_t *);
+/* Routines for parsing device-tree data into resource lists. */
+int ofw_bus_intr_to_rl(device_t, phandle_t, struct resource_list *);
+
/* Helper to get device status property */
const char *ofw_bus_get_status(device_t dev);
int ofw_bus_status_okay(device_t dev);
diff --git a/sys/dev/ofw/ofwbus.c b/sys/dev/ofw/ofwbus.c
index 11a6a64..2b975ac 100644
--- a/sys/dev/ofw/ofwbus.c
+++ b/sys/dev/ofw/ofwbus.c
@@ -436,11 +436,9 @@ ofwbus_setup_dinfo(device_t dev, phandle_t node)
struct ofwbus_softc *sc;
struct ofwbus_devinfo *ndi;
const char *nodename;
- uint32_t *reg, *intr, icells;
+ uint32_t *reg;
uint64_t phys, size;
- phandle_t iparent;
int i, j, rid;
- int nintr;
int nreg;
sc = device_get_softc(dev);
@@ -485,35 +483,7 @@ ofwbus_setup_dinfo(device_t dev, phandle_t node)
}
free(reg, M_OFWPROP);
- nintr = OF_getencprop_alloc(node, "interrupts", sizeof(*intr),
- (void **)&intr);
- if (nintr > 0) {
- if (OF_searchencprop(node, "interrupt-parent", &iparent,
- sizeof(iparent)) == -1) {
- device_printf(dev, "No interrupt-parent found, "
- "assuming nexus on <%s>\n", nodename);
- iparent = 0xffffffff;
- }
- if (OF_searchencprop(OF_node_from_xref(iparent),
- "#interrupt-cells", &icells, sizeof(icells)) == -1) {
- device_printf(dev, "Missing #interrupt-cells property, "
- "assuming <1> on <%s>\n", nodename);
- icells = 1;
- }
- if (icells < 1 || icells > nintr) {
- device_printf(dev, "Invalid #interrupt-cells property "
- "value <%d>, assuming <1> on <%s>\n", icells,
- nodename);
- icells = 1;
- }
- for (i = 0, rid = 0; i < nintr; i += icells, rid++) {
- intr[i] = ofw_bus_map_intr(dev, iparent, icells,
- &intr[i]);
- resource_list_add(&ndi->ndi_rl, SYS_RES_IRQ, rid, intr[i],
- intr[i], 1);
- }
- free(intr, M_OFWPROP);
- }
+ ofw_bus_intr_to_rl(dev, node, &ndi->ndi_rl);
return (ndi);
}
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index 0526e8d..1bb3172 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -131,7 +131,7 @@ static device_method_t pci_methods[] = {
DEVMETHOD(device_detach, bus_generic_detach),
#endif
DEVMETHOD(device_shutdown, bus_generic_shutdown),
- DEVMETHOD(device_suspend, pci_suspend),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
DEVMETHOD(device_resume, pci_resume),
/* Bus interface */
@@ -157,6 +157,8 @@ static device_method_t pci_methods[] = {
DEVMETHOD(bus_child_pnpinfo_str, pci_child_pnpinfo_str_method),
DEVMETHOD(bus_child_location_str, pci_child_location_str_method),
DEVMETHOD(bus_remap_intr, pci_remap_intr_method),
+ DEVMETHOD(bus_suspend_child, pci_suspend_child),
+ DEVMETHOD(bus_resume_child, pci_resume_child),
/* PCI interface */
DEVMETHOD(pci_read_config, pci_read_config_method),
@@ -3622,12 +3624,11 @@ pci_detach(device_t dev)
#endif
static void
-pci_set_power_children(device_t dev, device_t *devlist, int numdevs,
- int state)
+pci_set_power_child(device_t dev, device_t child, int state)
{
- device_t child, pcib;
struct pci_devinfo *dinfo;
- int dstate, i;
+ device_t pcib;
+ int dstate;
/*
* Set the device to the given state. If the firmware suggests
@@ -3637,45 +3638,54 @@ pci_set_power_children(device_t dev, device_t *devlist, int numdevs,
* are handled separately.
*/
pcib = device_get_parent(dev);
- for (i = 0; i < numdevs; i++) {
- child = devlist[i];
- dinfo = device_get_ivars(child);
- dstate = state;
- if (device_is_attached(child) &&
- PCIB_POWER_FOR_SLEEP(pcib, dev, &dstate) == 0)
- pci_set_powerstate(child, dstate);
- }
+ dinfo = device_get_ivars(child);
+ dstate = state;
+ if (device_is_attached(child) &&
+ PCIB_POWER_FOR_SLEEP(pcib, dev, &dstate) == 0)
+ pci_set_powerstate(child, dstate);
}
int
-pci_suspend(device_t dev)
+pci_suspend_child(device_t dev, device_t child)
{
- device_t child, *devlist;
struct pci_devinfo *dinfo;
- int error, i, numdevs;
+ int error;
+
+ dinfo = device_get_ivars(child);
/*
- * Save the PCI configuration space for each child and set the
+ * Save the PCI configuration space for the child and set the
* device in the appropriate power state for this sleep state.
*/
- if ((error = device_get_children(dev, &devlist, &numdevs)) != 0)
- return (error);
- for (i = 0; i < numdevs; i++) {
- child = devlist[i];
- dinfo = device_get_ivars(child);
- pci_cfg_save(child, dinfo, 0);
- }
+ pci_cfg_save(child, dinfo, 0);
/* Suspend devices before potentially powering them down. */
- error = bus_generic_suspend(dev);
- if (error) {
- free(devlist, M_TEMP);
+ error = bus_generic_suspend_child(dev, child);
+
+ if (error)
return (error);
- }
+
if (pci_do_power_suspend)
- pci_set_power_children(dev, devlist, numdevs,
- PCI_POWERSTATE_D3);
- free(devlist, M_TEMP);
+ pci_set_power_child(dev, child, PCI_POWERSTATE_D3);
+
+ return (0);
+}
+
+int
+pci_resume_child(device_t dev, device_t child)
+{
+ struct pci_devinfo *dinfo;
+
+ if (pci_do_power_resume)
+ pci_set_power_child(dev, child, PCI_POWERSTATE_D0);
+
+ dinfo = device_get_ivars(child);
+ pci_cfg_restore(child, dinfo);
+ if (!device_is_attached(child))
+ pci_cfg_save(child, dinfo, 1);
+
+ bus_generic_resume_child(dev, child);
+
return (0);
}
@@ -3683,27 +3693,10 @@ int
pci_resume(device_t dev)
{
device_t child, *devlist;
- struct pci_devinfo *dinfo;
int error, i, numdevs;
- /*
- * Set each child to D0 and restore its PCI configuration space.
- */
if ((error = device_get_children(dev, &devlist, &numdevs)) != 0)
return (error);
- if (pci_do_power_resume)
- pci_set_power_children(dev, devlist, numdevs,
- PCI_POWERSTATE_D0);
-
- /* Now the device is powered up, restore its config space. */
- for (i = 0; i < numdevs; i++) {
- child = devlist[i];
- dinfo = device_get_ivars(child);
-
- pci_cfg_restore(child, dinfo);
- if (!device_is_attached(child))
- pci_cfg_save(child, dinfo, 1);
- }
/*
* Resume critical devices first, then everything else later.
@@ -3715,7 +3708,7 @@ pci_resume(device_t dev)
case PCIC_MEMORY:
case PCIC_BRIDGE:
case PCIC_BASEPERIPH:
- DEVICE_RESUME(child);
+ BUS_RESUME_CHILD(dev, child);
break;
}
}
@@ -3728,7 +3721,7 @@ pci_resume(device_t dev)
case PCIC_BASEPERIPH:
break;
default:
- DEVICE_RESUME(child);
+ BUS_RESUME_CHILD(dev, child);
}
}
free(devlist, M_TEMP);
diff --git a/sys/dev/pci/pci_private.h b/sys/dev/pci/pci_private.h
index 5a90ce9..c10701d 100644
--- a/sys/dev/pci/pci_private.h
+++ b/sys/dev/pci/pci_private.h
@@ -123,7 +123,8 @@ int pci_child_pnpinfo_str_method(device_t cbdev, device_t child,
char *buf, size_t buflen);
int pci_assign_interrupt_method(device_t dev, device_t child);
int pci_resume(device_t dev);
-int pci_suspend(device_t dev);
+int pci_resume_child(device_t dev, device_t child);
+int pci_suspend_child(device_t dev, device_t child);
bus_dma_tag_t pci_get_dma_tag(device_t bus, device_t dev);
void pci_child_added_method(device_t dev, device_t child);
diff --git a/sys/dev/ti/if_ti.c b/sys/dev/ti/if_ti.c
index fa63aa9..7d0fc9d 100644
--- a/sys/dev/ti/if_ti.c
+++ b/sys/dev/ti/if_ti.c
@@ -184,13 +184,13 @@ static int ti_detach(device_t);
static void ti_txeof(struct ti_softc *);
static void ti_rxeof(struct ti_softc *);
-static void ti_stats_update(struct ti_softc *);
static int ti_encap(struct ti_softc *, struct mbuf **);
static void ti_intr(void *);
static void ti_start(struct ifnet *);
static void ti_start_locked(struct ifnet *);
static int ti_ioctl(struct ifnet *, u_long, caddr_t);
+static uint64_t ti_get_counter(struct ifnet *, ift_counter);
static void ti_init(void *);
static void ti_init_locked(void *);
static void ti_init2(struct ti_softc *);
@@ -959,8 +959,6 @@ ti_handle_events(struct ti_softc *sc)
ti_init2(sc);
break;
case TI_EV_STATS_UPDATED:
- ti_stats_update(sc);
- break;
case TI_EV_RESET_JUMBO_RING:
case TI_EV_MCAST_UPDATED:
/* Who cares. */
@@ -2505,6 +2503,7 @@ ti_attach(device_t dev)
ifp->if_ioctl = ti_ioctl;
ifp->if_start = ti_start;
ifp->if_init = ti_init;
+ ifp->if_get_counter = ti_get_counter;
ifp->if_baudrate = IF_Gbps(1UL);
ifp->if_snd.ifq_drv_maxlen = TI_TX_RING_CNT - 1;
IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen);
@@ -2803,12 +2802,12 @@ ti_rxeof(struct ti_softc *sc)
m = sc->ti_cdata.ti_rx_jumbo_chain[rxidx];
#ifndef TI_SF_BUF_JUMBO
if (cur_rx->ti_flags & TI_BDFLAG_ERROR) {
- ifp->if_ierrors++;
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
ti_discard_jumbo(sc, rxidx);
continue;
}
if (ti_newbuf_jumbo(sc, rxidx, NULL) != 0) {
- ifp->if_iqdrops++;
+ if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
ti_discard_jumbo(sc, rxidx);
continue;
}
@@ -2820,12 +2819,12 @@ ti_rxeof(struct ti_softc *sc)
BUS_DMASYNC_POSTREAD);
bus_dmamap_unload(sc->ti_cdata.ti_rx_jumbo_tag, map);
if (cur_rx->ti_flags & TI_BDFLAG_ERROR) {
- ifp->if_ierrors++;
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
ti_newbuf_jumbo(sc, sc->ti_jumbo, m);
continue;
}
if (ti_newbuf_jumbo(sc, sc->ti_jumbo, NULL) == ENOBUFS) {
- ifp->if_iqdrops++;
+ if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
ti_newbuf_jumbo(sc, sc->ti_jumbo, m);
continue;
}
@@ -2842,12 +2841,12 @@ ti_rxeof(struct ti_softc *sc)
TI_INC(sc->ti_mini, TI_MINI_RX_RING_CNT);
m = sc->ti_cdata.ti_rx_mini_chain[rxidx];
if (cur_rx->ti_flags & TI_BDFLAG_ERROR) {
- ifp->if_ierrors++;
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
ti_discard_mini(sc, rxidx);
continue;
}
if (ti_newbuf_mini(sc, rxidx) != 0) {
- ifp->if_iqdrops++;
+ if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
ti_discard_mini(sc, rxidx);
continue;
}
@@ -2857,12 +2856,12 @@ ti_rxeof(struct ti_softc *sc)
TI_INC(sc->ti_std, TI_STD_RX_RING_CNT);
m = sc->ti_cdata.ti_rx_std_chain[rxidx];
if (cur_rx->ti_flags & TI_BDFLAG_ERROR) {
- ifp->if_ierrors++;
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
ti_discard_std(sc, rxidx);
continue;
}
if (ti_newbuf_std(sc, rxidx) != 0) {
- ifp->if_iqdrops++;
+ if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
ti_discard_std(sc, rxidx);
continue;
}
@@ -2870,7 +2869,7 @@ ti_rxeof(struct ti_softc *sc)
}
m->m_pkthdr.len = ti_len;
- ifp->if_ipackets++;
+ if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
m->m_pkthdr.rcvif = ifp;
if (ifp->if_capenable & IFCAP_RXCSUM) {
@@ -2961,7 +2960,7 @@ ti_txeof(struct ti_softc *sc)
BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->ti_cdata.ti_tx_tag, txd->tx_dmamap);
- ifp->if_opackets++;
+ if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
m_freem(txd->tx_m);
txd->tx_m = NULL;
STAILQ_REMOVE_HEAD(&sc->ti_cdata.ti_txbusyq, tx_q);
@@ -3016,27 +3015,35 @@ ti_intr(void *xsc)
TI_UNLOCK(sc);
}
-static void
-ti_stats_update(struct ti_softc *sc)
+static uint64_t
+ti_get_counter(struct ifnet *ifp, ift_counter cnt)
{
- struct ifnet *ifp;
- struct ti_stats *s;
-
- ifp = sc->ti_ifp;
- if (sc->ti_stat_ticks == 0)
- return;
- bus_dmamap_sync(sc->ti_cdata.ti_gib_tag, sc->ti_cdata.ti_gib_map,
- BUS_DMASYNC_POSTREAD);
+ switch (cnt) {
+ case IFCOUNTER_COLLISIONS:
+ {
+ struct ti_softc *sc;
+ struct ti_stats *s;
+ uint64_t rv;
- s = &sc->ti_rdata.ti_info->ti_stats;
- ifp->if_collisions += (s->dot3StatsSingleCollisionFrames +
- s->dot3StatsMultipleCollisionFrames +
- s->dot3StatsExcessiveCollisions + s->dot3StatsLateCollisions) -
- ifp->if_collisions;
+ sc = if_getsoftc(ifp);
+ s = &sc->ti_rdata.ti_info->ti_stats;
- bus_dmamap_sync(sc->ti_cdata.ti_gib_tag, sc->ti_cdata.ti_gib_map,
- BUS_DMASYNC_PREREAD);
+ TI_LOCK(sc);
+ bus_dmamap_sync(sc->ti_cdata.ti_gib_tag,
+ sc->ti_cdata.ti_gib_map, BUS_DMASYNC_POSTREAD);
+ rv = s->dot3StatsSingleCollisionFrames +
+ s->dot3StatsMultipleCollisionFrames +
+ s->dot3StatsExcessiveCollisions +
+ s->dot3StatsLateCollisions;
+ bus_dmamap_sync(sc->ti_cdata.ti_gib_tag,
+ sc->ti_cdata.ti_gib_map, BUS_DMASYNC_PREREAD);
+ TI_UNLOCK(sc);
+ return (rv);
+ }
+ default:
+ return (if_get_counter_default(ifp, cnt));
+ }
}
/*
@@ -3662,6 +3669,8 @@ ti_ioctl2(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
sc->ti_cdata.ti_gib_map, BUS_DMASYNC_POSTREAD);
bcopy(&sc->ti_rdata.ti_info->ti_stats, outstats,
sizeof(struct ti_stats));
+ bus_dmamap_sync(sc->ti_cdata.ti_gib_tag,
+ sc->ti_cdata.ti_gib_map, BUS_DMASYNC_PREREAD);
TI_UNLOCK(sc);
break;
}
@@ -3917,7 +3926,7 @@ ti_watchdog(void *arg)
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
ti_init_locked(sc);
- ifp->if_oerrors++;
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
}
/*
diff --git a/sys/dev/tws/tws.c b/sys/dev/tws/tws.c
index 11013cb..a94ac25 100644
--- a/sys/dev/tws/tws.c
+++ b/sys/dev/tws/tws.c
@@ -198,6 +198,7 @@ tws_attach(device_t dev)
mtx_init( &sc->sim_lock, "tws_sim_lock", NULL, MTX_DEF);
mtx_init( &sc->gen_lock, "tws_gen_lock", NULL, MTX_DEF);
mtx_init( &sc->io_lock, "tws_io_lock", NULL, MTX_DEF | MTX_RECURSE);
+ callout_init(&sc->stats_timer, CALLOUT_MPSAFE);
if ( tws_init_trace_q(sc) == FAILURE )
printf("trace init failure\n");
@@ -408,11 +409,20 @@ tws_detach(device_t dev)
TWS_TRACE(sc, "bus release mem resource", 0, sc->reg_res_id);
}
+ for ( i=0; i< tws_queue_depth; i++) {
+ if (sc->reqs[i].dma_map)
+ bus_dmamap_destroy(sc->data_tag, sc->reqs[i].dma_map);
+ callout_drain(&sc->reqs[i].timeout);
+ }
+
+ callout_drain(&sc->stats_timer);
free(sc->reqs, M_TWS);
free(sc->sense_bufs, M_TWS);
free(sc->scan_ccb, M_TWS);
if (sc->ioctl_data_mem)
bus_dmamem_free(sc->data_tag, sc->ioctl_data_mem, sc->ioctl_data_map);
+ if (sc->data_tag)
+ bus_dma_tag_destroy(sc->data_tag);
free(sc->aen_q.q, M_TWS);
free(sc->trace_q.q, M_TWS);
mtx_destroy(&sc->q_lock);
@@ -709,7 +719,7 @@ tws_init_reqs(struct tws_softc *sc, u_int32_t dma_mem_size)
sc->reqs[i].cmd_pkt->hdr.header_desc.size_header = 128;
- callout_handle_init(&sc->reqs[i].thandle);
+ callout_init(&sc->reqs[i].timeout, CALLOUT_MPSAFE);
sc->reqs[i].state = TWS_REQ_STATE_FREE;
if ( i >= TWS_RESERVED_REQS )
tws_q_insert_tail(sc, &sc->reqs[i], TWS_FREE_Q);
@@ -859,7 +869,7 @@ tws_get_request(struct tws_softc *sc, u_int16_t type)
r->error_code = TWS_REQ_RET_INVALID;
r->cb = NULL;
r->ccb_ptr = NULL;
- r->thandle.callout = NULL;
+ callout_stop(&r->timeout);
r->next = r->prev = NULL;
r->state = ((type == TWS_REQ_TYPE_SCSI_IO) ? TWS_REQ_STATE_TRAN : TWS_REQ_STATE_BUSY);
diff --git a/sys/dev/tws/tws.h b/sys/dev/tws/tws.h
index 1101730..8cb9791 100644
--- a/sys/dev/tws/tws.h
+++ b/sys/dev/tws/tws.h
@@ -268,4 +268,5 @@ struct tws_softc {
union ccb *scan_ccb; /* pointer to a ccb */
struct tws_request *q_head[TWS_MAX_QS]; /* head pointers to q's */
struct tws_request *q_tail[TWS_MAX_QS]; /* tail pointers to q's */
+ struct callout stats_timer;
};
diff --git a/sys/dev/tws/tws_cam.c b/sys/dev/tws/tws_cam.c
index cb94fee..9b429d2 100644
--- a/sys/dev/tws/tws_cam.c
+++ b/sys/dev/tws/tws_cam.c
@@ -341,7 +341,7 @@ tws_scsi_complete(struct tws_request *req)
tws_q_remove_request(sc, req, TWS_BUSY_Q);
mtx_unlock(&sc->q_lock);
- untimeout(tws_timeout, req, req->thandle);
+ callout_stop(&req->timeout);
tws_unmap_request(req->sc, req);
@@ -362,7 +362,7 @@ tws_getset_param_complete(struct tws_request *req)
TWS_TRACE_DEBUG(sc, "getset complete", req, req->request_id);
- untimeout(tws_timeout, req, req->thandle);
+ callout_stop(&req->timeout);
tws_unmap_request(sc, req);
free(req->data, M_TWS);
@@ -380,7 +380,7 @@ tws_aen_complete(struct tws_request *req)
TWS_TRACE_DEBUG(sc, "aen complete", 0, req->request_id);
- untimeout(tws_timeout, req, req->thandle);
+ callout_stop(&req->timeout);
tws_unmap_request(sc, req);
sense = (struct tws_command_header *)req->data;
@@ -454,7 +454,7 @@ tws_cmd_complete(struct tws_request *req)
{
struct tws_softc *sc = req->sc;
- untimeout(tws_timeout, req, req->thandle);
+ callout_stop(&req->timeout);
tws_unmap_request(sc, req);
}
@@ -561,7 +561,7 @@ tws_scsi_err_complete(struct tws_request *req, struct tws_command_header *hdr)
xpt_done(ccb);
mtx_unlock(&sc->sim_lock);
- untimeout(tws_timeout, req, req->thandle);
+ callout_stop(&req->timeout);
tws_unmap_request(req->sc, req);
mtx_lock(&sc->q_lock);
tws_q_remove_request(sc, req, TWS_BUSY_Q);
@@ -591,7 +591,7 @@ tws_drain_busy_queue(struct tws_softc *sc)
mtx_unlock(&sc->q_lock);
while ( req ) {
TWS_TRACE_DEBUG(sc, "moved to TWS_COMPLETE_Q", 0, req->request_id);
- untimeout(tws_timeout, req, req->thandle);
+ callout_stop(&req->timeout);
req->error_code = TWS_REQ_RET_RESET;
ccb = (union ccb *)(req->ccb_ptr);
@@ -622,7 +622,7 @@ tws_drain_reserved_reqs(struct tws_softc *sc)
r = &sc->reqs[TWS_REQ_TYPE_AEN_FETCH];
if ( r->state != TWS_REQ_STATE_FREE ) {
TWS_TRACE_DEBUG(sc, "reset aen req", 0, 0);
- untimeout(tws_timeout, r, r->thandle);
+ callout_stop(&r->timeout);
tws_unmap_request(sc, r);
free(r->data, M_TWS);
r->state = TWS_REQ_STATE_FREE;
@@ -638,7 +638,7 @@ tws_drain_reserved_reqs(struct tws_softc *sc)
r = &sc->reqs[TWS_REQ_TYPE_GETSET_PARAM];
if ( r->state != TWS_REQ_STATE_FREE ) {
TWS_TRACE_DEBUG(sc, "reset setparam req", 0, 0);
- untimeout(tws_timeout, r, r->thandle);
+ callout_stop(&r->timeout);
tws_unmap_request(sc, r);
free(r->data, M_TWS);
r->state = TWS_REQ_STATE_FREE;
@@ -747,7 +747,7 @@ tws_execute_scsi(struct tws_softc *sc, union ccb *ccb)
* and submit the I/O.
*/
sc->stats.scsi_ios++;
- req->thandle = timeout(tws_timeout, req, (ccb_h->timeout * hz)/1000);
+ callout_reset(&req->timeout, (ccb_h->timeout * hz) / 1000, tws_timeout, req);
error = tws_map_request(sc, req);
return(error);
}
@@ -785,7 +785,7 @@ tws_send_scsi_cmd(struct tws_softc *sc, int cmd)
bzero(req->data, TWS_SECTOR_SIZE);
req->flags = TWS_DIR_IN;
- req->thandle = timeout(tws_timeout, req, (TWS_IO_TIMEOUT * hz));
+ callout_reset(&req->timeout, (TWS_IO_TIMEOUT * hz), tws_timeout, req);
error = tws_map_request(sc, req);
return(error);
@@ -832,7 +832,7 @@ tws_set_param(struct tws_softc *sc, u_int32_t table_id, u_int32_t param_id,
param->parameter_size_bytes = (u_int16_t)param_size;
memcpy(param->data, data, param_size);
- req->thandle = timeout(tws_timeout, req, (TWS_IOCTL_TIMEOUT * hz));
+ callout_reset(&req->timeout, (TWS_IOCTL_TIMEOUT * hz), tws_timeout, req);
error = tws_map_request(sc, req);
return(error);
@@ -1168,7 +1168,6 @@ tws_timeout(void *arg)
return;
}
- tws_teardown_intr(sc);
xpt_freeze_simq(sc->sim, 1);
tws_send_event(sc, TWS_RESET_START);
@@ -1191,7 +1190,6 @@ tws_timeout(void *arg)
mtx_unlock(&sc->gen_lock);
xpt_release_simq(sc->sim, 1);
- tws_setup_intr(sc, sc->irqs);
}
void
@@ -1205,7 +1203,6 @@ tws_reset(void *arg)
return;
}
- tws_teardown_intr(sc);
xpt_freeze_simq(sc->sim, 1);
tws_send_event(sc, TWS_RESET_START);
@@ -1222,7 +1219,6 @@ tws_reset(void *arg)
mtx_unlock(&sc->gen_lock);
xpt_release_simq(sc->sim, 1);
- tws_setup_intr(sc, sc->irqs);
}
static void
diff --git a/sys/dev/tws/tws_hdm.c b/sys/dev/tws/tws_hdm.c
index f5bb3f1..2e568c8 100644
--- a/sys/dev/tws/tws_hdm.c
+++ b/sys/dev/tws/tws_hdm.c
@@ -161,7 +161,7 @@ tws_init_connect(struct tws_softc *sc, u_int16_t mcreadits )
req->error_code = TWS_REQ_RET_INVALID;
req->cb = NULL;
req->ccb_ptr = NULL;
- req->thandle.callout = NULL;
+ callout_stop(&req->timeout);
req->next = req->prev = NULL;
req->state = TWS_REQ_STATE_BUSY;
#endif // 0
diff --git a/sys/dev/tws/tws_hdm.h b/sys/dev/tws/tws_hdm.h
index 58feeee..5cacf19 100644
--- a/sys/dev/tws/tws_hdm.h
+++ b/sys/dev/tws/tws_hdm.h
@@ -410,7 +410,7 @@ struct tws_request {
void (*cb)(struct tws_request *); /* callback func */
bus_dmamap_t dma_map; /* dma map */
union ccb *ccb_ptr; /* pointer to ccb */
- struct callout_handle thandle; /* handle to req timeout */
+ struct callout timeout; /* request timeout timer */
struct tws_softc *sc; /* pointer back to ctlr softc */
struct tws_request *next; /* pointer to next request */
diff --git a/sys/dev/tws/tws_services.c b/sys/dev/tws/tws_services.c
index d2a52cd..243585b 100644
--- a/sys/dev/tws/tws_services.c
+++ b/sys/dev/tws/tws_services.c
@@ -395,7 +395,6 @@ tws_print_stats(void *arg)
, sc->stats.num_intrs);
TWS_TRACE(sc, "reqs(ioctls, scsi)", sc->stats.ioctls
, sc->stats.scsi_ios);
- timeout(tws_print_stats, sc, 300*hz);
-
+ callout_reset(&sc->stats_timer, 300 * hz, tws_print_stats, sc);
}
/* --------------------- misc service end --------------------- */
diff --git a/sys/dev/txp/if_txp.c b/sys/dev/txp/if_txp.c
index d000db4..8e0b91c 100644
--- a/sys/dev/txp/if_txp.c
+++ b/sys/dev/txp/if_txp.c
@@ -149,6 +149,7 @@ static int txp_intr(void *);
static void txp_int_task(void *, int);
static void txp_tick(void *);
static int txp_ioctl(struct ifnet *, u_long, caddr_t);
+static uint64_t txp_get_counter(struct ifnet *, ift_counter);
static void txp_start(struct ifnet *);
static void txp_start_locked(struct ifnet *);
static int txp_encap(struct txp_softc *, struct txp_tx_ring *, struct mbuf **);
@@ -413,6 +414,7 @@ txp_attach(device_t dev)
ifp->if_ioctl = txp_ioctl;
ifp->if_start = txp_start;
ifp->if_init = txp_init;
+ ifp->if_get_counter = txp_get_counter;
ifp->if_snd.ifq_drv_maxlen = TX_ENTRIES - 1;
IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen);
IFQ_SET_READY(&ifp->if_snd);
@@ -2540,7 +2542,7 @@ txp_watchdog(struct txp_softc *sc)
ifp = sc->sc_ifp;
if_printf(ifp, "watchdog timeout -- resetting\n");
- ifp->if_oerrors++;
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
txp_stop(sc);
txp_init_locked(sc);
}
@@ -2816,13 +2818,11 @@ out:
static void
txp_stats_update(struct txp_softc *sc, struct txp_rsp_desc *rsp)
{
- struct ifnet *ifp;
struct txp_hw_stats *ostats, *stats;
struct txp_ext_desc *ext;
TXP_LOCK_ASSERT(sc);
- ifp = sc->sc_ifp;
ext = (struct txp_ext_desc *)(rsp + 1);
ostats = &sc->sc_ostats;
stats = &sc->sc_stats;
@@ -2856,15 +2856,34 @@ txp_stats_update(struct txp_softc *sc, struct txp_rsp_desc *rsp)
le32toh(ext[4].ext_3);
stats->rx_oflows = ostats->rx_oflows + le32toh(ext[4].ext_4);
stats->rx_filtered = ostats->rx_filtered + le32toh(ext[5].ext_1);
+}
- ifp->if_ierrors = stats->rx_fifo_oflows + stats->rx_badssd +
- stats->rx_crcerrs + stats->rx_lenerrs + stats->rx_oflows;
- ifp->if_oerrors = stats->tx_deferred + stats->tx_carrier_lost +
- stats->tx_fifo_underruns + stats->tx_mcast_oflows;
- ifp->if_collisions = stats->tx_late_colls + stats->tx_multi_colls +
- stats->tx_excess_colls;
- ifp->if_opackets = stats->tx_frames;
- ifp->if_ipackets = stats->rx_frames;
+static uint64_t
+txp_get_counter(struct ifnet *ifp, ift_counter cnt)
+{
+ struct txp_softc *sc;
+ struct txp_hw_stats *stats;
+
+ sc = if_getsoftc(ifp);
+ stats = &sc->sc_stats;
+
+ switch (cnt) {
+ case IFCOUNTER_IERRORS:
+ return (stats->rx_fifo_oflows + stats->rx_badssd +
+ stats->rx_crcerrs + stats->rx_lenerrs + stats->rx_oflows);
+ case IFCOUNTER_OERRORS:
+ return (stats->tx_deferred + stats->tx_carrier_lost +
+ stats->tx_fifo_underruns + stats->tx_mcast_oflows);
+ case IFCOUNTER_COLLISIONS:
+ return (stats->tx_late_colls + stats->tx_multi_colls +
+ stats->tx_excess_colls);
+ case IFCOUNTER_OPACKETS:
+ return (stats->tx_frames);
+ case IFCOUNTER_IPACKETS:
+ return (stats->rx_frames);
+ default:
+ return (if_get_counter_default(ifp, cnt));
+ }
}
#define TXP_SYSCTL_STAT_ADD32(c, h, n, p, d) \
diff --git a/sys/dev/usb/controller/ohci_s3c24x0.c b/sys/dev/usb/controller/ohci_s3c24x0.c
index 225a2d2..08624d2 100644
--- a/sys/dev/usb/controller/ohci_s3c24x0.c
+++ b/sys/dev/usb/controller/ohci_s3c24x0.c
@@ -60,7 +60,7 @@ __FBSDID("$FreeBSD$");
#include <sys/rman.h>
-#include <arm/s3c2xx0/s3c24x0reg.h>
+#include <arm/samsung/s3c2xx0/s3c24x0reg.h>
static device_probe_t ohci_s3c24x0_probe;
static device_attach_t ohci_s3c24x0_attach;
diff --git a/sys/dev/usb/controller/xhci.c b/sys/dev/usb/controller/xhci.c
index 5e9029c..f06964e 100644
--- a/sys/dev/usb/controller/xhci.c
+++ b/sys/dev/usb/controller/xhci.c
@@ -2248,7 +2248,14 @@ xhci_configure_mask(struct usb_device *udev, uint32_t mask, uint8_t drop)
xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx0, mask);
xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx1, 0);
} else {
- xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx0, 0);
+ /*
+ * Some hardware requires that we drop the endpoint
+ * context before adding it again:
+ */
+ xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx0,
+ mask & XHCI_INCTX_NON_CTRL_MASK);
+
+ /* Add new endpoint context */
xhci_ctx_set_le32(sc, &pinp->ctx_input.dwInCtx1, mask);
/* find most significant set bit */
diff --git a/sys/dev/usb/net/if_smsc.c b/sys/dev/usb/net/if_smsc.c
index 515c9d5..bd2e751 100644
--- a/sys/dev/usb/net/if_smsc.c
+++ b/sys/dev/usb/net/if_smsc.c
@@ -123,7 +123,24 @@ SYSCTL_INT(_hw_usb_smsc, OID_AUTO, debug, CTLFLAG_RW, &smsc_debug, 0,
*/
static const struct usb_device_id smsc_devs[] = {
#define SMSC_DEV(p,i) { USB_VPI(USB_VENDOR_SMC2, USB_PRODUCT_SMC2_##p, i) }
+ SMSC_DEV(LAN89530_ETH, 0),
+ SMSC_DEV(LAN9500_ETH, 0),
+ SMSC_DEV(LAN9500_ETH_2, 0),
+ SMSC_DEV(LAN9500A_ETH, 0),
+ SMSC_DEV(LAN9500A_ETH_2, 0),
+ SMSC_DEV(LAN9505_ETH, 0),
+ SMSC_DEV(LAN9505A_ETH, 0),
SMSC_DEV(LAN9514_ETH, 0),
+ SMSC_DEV(LAN9514_ETH_2, 0),
+ SMSC_DEV(LAN9530_ETH, 0),
+ SMSC_DEV(LAN9730_ETH, 0),
+ SMSC_DEV(LAN9500_SAL10, 0),
+ SMSC_DEV(LAN9505_SAL10, 0),
+ SMSC_DEV(LAN9500A_SAL10, 0),
+ SMSC_DEV(LAN9505A_SAL10, 0),
+ SMSC_DEV(LAN9514_SAL10, 0),
+ SMSC_DEV(LAN9500A_HAL, 0),
+ SMSC_DEV(LAN9505A_HAL, 0),
#undef SMSC_DEV
};
diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs
index cf50960..330abbb 100644
--- a/sys/dev/usb/usbdevs
+++ b/sys/dev/usb/usbdevs
@@ -4135,6 +4135,23 @@ product SMC 2862WG 0xee13 EZ Connect Wireless Adapter
product SMC2 2020HUB 0x2020 USB Hub
product SMC2 2514HUB 0x2514 USB Hub
product SMC3 2662WUSB 0xa002 2662W-AR Wireless
+product SMC2 LAN9500_ETH 0x9500 USB/Ethernet
+product SMC2 LAN9505_ETH 0x9505 USB/Ethernet
+product SMC2 LAN9530_ETH 0x9530 USB/Ethernet
+product SMC2 LAN9730_ETH 0x9730 USB/Ethernet
+product SMC2 LAN9500_SAL10 0x9900 USB/Ethernet
+product SMC2 LAN9505_SAL10 0x9901 USB/Ethernet
+product SMC2 LAN9500A_SAL10 0x9902 USB/Ethernet
+product SMC2 LAN9505A_SAL10 0x9903 USB/Ethernet
+product SMC2 LAN9514_SAL10 0x9904 USB/Ethernet
+product SMC2 LAN9500A_HAL 0x9905 USB/Ethernet
+product SMC2 LAN9505A_HAL 0x9906 USB/Ethernet
+product SMC2 LAN9500_ETH_2 0x9907 USB/Ethernet
+product SMC2 LAN9500A_ETH_2 0x9908 USB/Ethernet
+product SMC2 LAN9514_ETH_2 0x9909 USB/Ethernet
+product SMC2 LAN9500A_ETH 0x9e00 USB/Ethernet
+product SMC2 LAN9505A_ETH 0x9e01 USB/Ethernet
+product SMC2 LAN89530_ETH 0x9e08 USB/Ethernet
product SMC2 LAN9514_ETH 0xec00 USB/Ethernet
/* SOHOware products */
diff --git a/sys/pci/viapm.c b/sys/dev/viapm/viapm.c
index 0cddd07..0cddd07 100644
--- a/sys/pci/viapm.c
+++ b/sys/dev/viapm/viapm.c
diff --git a/sys/dev/vmware/vmxnet3/if_vmx.c b/sys/dev/vmware/vmxnet3/if_vmx.c
index f3fde92..1d8c12e 100644
--- a/sys/dev/vmware/vmxnet3/if_vmx.c
+++ b/sys/dev/vmware/vmxnet3/if_vmx.c
@@ -187,6 +187,7 @@ static void vmxnet3_unregister_vlan(void *, struct ifnet *, uint16_t);
static void vmxnet3_set_rxfilter(struct vmxnet3_softc *);
static int vmxnet3_change_mtu(struct vmxnet3_softc *, int);
static int vmxnet3_ioctl(struct ifnet *, u_long, caddr_t);
+static uint64_t vmxnet3_get_counter(struct ifnet *, ift_counter);
#ifndef VMXNET3_LEGACY_TX
static void vmxnet3_qflush(struct ifnet *);
@@ -194,10 +195,6 @@ static void vmxnet3_qflush(struct ifnet *);
static int vmxnet3_watchdog(struct vmxnet3_txqueue *);
static void vmxnet3_refresh_host_stats(struct vmxnet3_softc *);
-static void vmxnet3_txq_accum_stats(struct vmxnet3_txqueue *,
- struct vmxnet3_txq_stats *);
-static void vmxnet3_rxq_accum_stats(struct vmxnet3_rxqueue *,
- struct vmxnet3_rxq_stats *);
static void vmxnet3_tick(void *);
static void vmxnet3_link_status(struct vmxnet3_softc *);
static void vmxnet3_media_status(struct ifnet *, struct ifmediareq *);
@@ -1722,7 +1719,10 @@ vmxnet3_setup_interface(struct vmxnet3_softc *sc)
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_init = vmxnet3_init;
ifp->if_ioctl = vmxnet3_ioctl;
- ifp->if_hw_tsomax = VMXNET3_TSO_MAXSIZE;
+ ifp->if_get_counter = vmxnet3_get_counter;
+ ifp->if_hw_tsomax = 65536 - (ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN);
+ ifp->if_hw_tsomaxsegcount = VMXNET3_TX_MAXSEGS;
+ ifp->if_hw_tsomaxsegsize = VMXNET3_TX_MAXSEGSIZE;
#ifdef VMXNET3_LEGACY_TX
ifp->if_start = vmxnet3_start;
@@ -3342,56 +3342,14 @@ vmxnet3_refresh_host_stats(struct vmxnet3_softc *sc)
vmxnet3_write_cmd(sc, VMXNET3_CMD_GET_STATS);
}
-static void
-vmxnet3_txq_accum_stats(struct vmxnet3_txqueue *txq,
- struct vmxnet3_txq_stats *accum)
-{
- struct vmxnet3_txq_stats *st;
-
- st = &txq->vxtxq_stats;
-
- accum->vmtxs_opackets += st->vmtxs_opackets;
- accum->vmtxs_obytes += st->vmtxs_obytes;
- accum->vmtxs_omcasts += st->vmtxs_omcasts;
- accum->vmtxs_csum += st->vmtxs_csum;
- accum->vmtxs_tso += st->vmtxs_tso;
- accum->vmtxs_full += st->vmtxs_full;
- accum->vmtxs_offload_failed += st->vmtxs_offload_failed;
-}
-
-static void
-vmxnet3_rxq_accum_stats(struct vmxnet3_rxqueue *rxq,
- struct vmxnet3_rxq_stats *accum)
+static uint64_t
+vmxnet3_get_counter(struct ifnet *ifp, ift_counter cnt)
{
- struct vmxnet3_rxq_stats *st;
-
- st = &rxq->vxrxq_stats;
-
- accum->vmrxs_ipackets += st->vmrxs_ipackets;
- accum->vmrxs_ibytes += st->vmrxs_ibytes;
- accum->vmrxs_iqdrops += st->vmrxs_iqdrops;
- accum->vmrxs_ierrors += st->vmrxs_ierrors;
-}
-
-static void
-vmxnet3_accumulate_stats(struct vmxnet3_softc *sc)
-{
- struct ifnet *ifp;
- struct vmxnet3_statistics *st;
- struct vmxnet3_txq_stats txaccum;
- struct vmxnet3_rxq_stats rxaccum;
- int i;
-
- ifp = sc->vmx_ifp;
- st = &sc->vmx_stats;
-
- bzero(&txaccum, sizeof(struct vmxnet3_txq_stats));
- bzero(&rxaccum, sizeof(struct vmxnet3_rxq_stats));
+ struct vmxnet3_softc *sc;
+ uint64_t rv;
- for (i = 0; i < sc->vmx_ntxqueues; i++)
- vmxnet3_txq_accum_stats(&sc->vmx_txq[i], &txaccum);
- for (i = 0; i < sc->vmx_nrxqueues; i++)
- vmxnet3_rxq_accum_stats(&sc->vmx_rxq[i], &rxaccum);
+ sc = if_getsoftc(ifp);
+ rv = 0;
/*
* With the exception of if_ierrors, these ifnet statistics are
@@ -3399,14 +3357,36 @@ vmxnet3_accumulate_stats(struct vmxnet3_softc *sc)
* values. if_ierrors is updated in ether_input() for malformed
* frames that we should have already discarded.
*/
- ifp->if_ipackets = rxaccum.vmrxs_ipackets;
- ifp->if_iqdrops = rxaccum.vmrxs_iqdrops;
- ifp->if_ierrors = rxaccum.vmrxs_ierrors;
- ifp->if_opackets = txaccum.vmtxs_opackets;
+ switch (cnt) {
+ case IFCOUNTER_IPACKETS:
+ for (int i = 0; i < sc->vmx_nrxqueues; i++)
+ rv += sc->vmx_rxq[i].vxrxq_stats.vmrxs_ipackets;
+ return (rv);
+ case IFCOUNTER_IQDROPS:
+ for (int i = 0; i < sc->vmx_nrxqueues; i++)
+ rv += sc->vmx_rxq[i].vxrxq_stats.vmrxs_iqdrops;
+ return (rv);
+ case IFCOUNTER_IERRORS:
+ for (int i = 0; i < sc->vmx_nrxqueues; i++)
+ rv += sc->vmx_rxq[i].vxrxq_stats.vmrxs_ierrors;
+ return (rv);
+ case IFCOUNTER_OPACKETS:
+ for (int i = 0; i < sc->vmx_ntxqueues; i++)
+ rv += sc->vmx_txq[i].vxtxq_stats.vmtxs_opackets;
+ return (rv);
#ifndef VMXNET3_LEGACY_TX
- ifp->if_obytes = txaccum.vmtxs_obytes;
- ifp->if_omcasts = txaccum.vmtxs_omcasts;
+ case IFCOUNTER_OBYTES:
+ for (int i = 0; i < sc->vmx_ntxqueues; i++)
+ rv += sc->vmx_txq[i].vxtxq_stats.vmtxs_obytes;
+ return (rv);
+ case IFCOUNTER_OMCASTS:
+ for (int i = 0; i < sc->vmx_ntxqueues; i++)
+ rv += sc->vmx_txq[i].vxtxq_stats.vmtxs_omcasts;
+ return (rv);
#endif
+ default:
+ return (if_get_counter_default(ifp, cnt));
+ }
}
static void
@@ -3422,7 +3402,6 @@ vmxnet3_tick(void *xsc)
VMXNET3_CORE_LOCK_ASSERT(sc);
- vmxnet3_accumulate_stats(sc);
vmxnet3_refresh_host_stats(sc);
for (i = 0; i < sc->vmx_ntxqueues; i++)
diff --git a/sys/dev/vmware/vmxnet3/if_vmxvar.h b/sys/dev/vmware/vmxnet3/if_vmxvar.h
index 6c79721..8613516 100644
--- a/sys/dev/vmware/vmxnet3/if_vmxvar.h
+++ b/sys/dev/vmware/vmxnet3/if_vmxvar.h
@@ -277,8 +277,6 @@ struct vmxnet3_softc {
*/
#define VMXNET3_TX_MAXSEGS 32
#define VMXNET3_TX_MAXSIZE (VMXNET3_TX_MAXSEGS * MCLBYTES)
-#define VMXNET3_TSO_MAXSIZE \
- (VMXNET3_TX_MAXSIZE - sizeof(struct ether_vlan_header))
/*
* Maximum support Tx segments size. The length field in the
diff --git a/sys/dev/vt/vt_buf.c b/sys/dev/vt/vt_buf.c
index 91ebba3..cc23b3b 100644
--- a/sys/dev/vt/vt_buf.c
+++ b/sys/dev/vt/vt_buf.c
@@ -83,6 +83,7 @@ vthistory_seek(struct vt_buf *vb, int offset, int whence)
bottom + vb->vb_scr_size.tp_row - vb->vb_history_size :
0;
+ roffset = 0; /* Make gcc happy. */
switch (whence) {
case VHS_SET:
if (offset < 0)
diff --git a/sys/dev/vte/if_vte.c b/sys/dev/vte/if_vte.c
index 79dd1fb..e10b988 100644
--- a/sys/dev/vte/if_vte.c
+++ b/sys/dev/vte/if_vte.c
@@ -109,6 +109,7 @@ static int vte_init_rx_ring(struct vte_softc *);
static int vte_init_tx_ring(struct vte_softc *);
static void vte_intr(void *);
static int vte_ioctl(struct ifnet *, u_long, caddr_t);
+static uint64_t vte_get_counter(struct ifnet *, ift_counter);
static void vte_mac_config(struct vte_softc *);
static int vte_miibus_readreg(device_t, int, int);
static void vte_miibus_statchg(device_t);
@@ -449,6 +450,7 @@ vte_attach(device_t dev)
ifp->if_ioctl = vte_ioctl;
ifp->if_start = vte_start;
ifp->if_init = vte_init;
+ ifp->if_get_counter = vte_get_counter;
ifp->if_snd.ifq_drv_maxlen = VTE_TX_RING_CNT - 1;
IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen);
IFQ_SET_READY(&ifp->if_snd);
@@ -1171,7 +1173,7 @@ vte_watchdog(struct vte_softc *sc)
ifp = sc->vte_ifp;
if_printf(sc->vte_ifp, "watchdog timeout -- resetting\n");
- ifp->if_oerrors++;
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
vte_init_locked(sc);
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
@@ -1272,12 +1274,10 @@ static void
vte_stats_update(struct vte_softc *sc)
{
struct vte_hw_stats *stat;
- struct ifnet *ifp;
uint16_t value;
VTE_LOCK_ASSERT(sc);
- ifp = sc->vte_ifp;
stat = &sc->vte_stats;
CSR_READ_2(sc, VTE_MECISR);
@@ -1304,14 +1304,32 @@ vte_stats_update(struct vte_softc *sc)
value = CSR_READ_2(sc, VTE_CNT_PAUSE);
stat->tx_pause_frames += (value >> 8);
stat->rx_pause_frames += (value & 0xFF);
+}
- /* Update ifp counters. */
- ifp->if_opackets = stat->tx_frames;
- ifp->if_collisions = stat->tx_late_colls;
- ifp->if_oerrors = stat->tx_late_colls + stat->tx_underruns;
- ifp->if_ipackets = stat->rx_frames;
- ifp->if_ierrors = stat->rx_crcerrs + stat->rx_runts +
- stat->rx_long_frames + stat->rx_fifo_full;
+static uint64_t
+vte_get_counter(struct ifnet *ifp, ift_counter cnt)
+{
+ struct vte_softc *sc;
+ struct vte_hw_stats *stat;
+
+ sc = if_getsoftc(ifp);
+ stat = &sc->vte_stats;
+
+ switch (cnt) {
+ case IFCOUNTER_OPACKETS:
+ return (stat->tx_frames);
+ case IFCOUNTER_COLLISIONS:
+ return (stat->tx_late_colls);
+ case IFCOUNTER_OERRORS:
+ return (stat->tx_late_colls + stat->tx_underruns);
+ case IFCOUNTER_IPACKETS:
+ return (stat->rx_frames);
+ case IFCOUNTER_IERRORS:
+ return (stat->rx_crcerrs + stat->rx_runts +
+ stat->rx_long_frames + stat->rx_fifo_full);
+ default:
+ return (if_get_counter_default(ifp, cnt));
+ }
}
static void
@@ -1503,7 +1521,7 @@ vte_rxeof(struct vte_softc *sc)
continue;
}
if (vte_newbuf(sc, rxd) != 0) {
- ifp->if_iqdrops++;
+ if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
rxd->rx_desc->drlen =
htole16(MCLBYTES - sizeof(uint32_t));
rxd->rx_desc->drst = htole16(VTE_DRST_RX_OWN);
diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c
index d713c97..6801823 100644
--- a/sys/dev/wi/if_wi.c
+++ b/sys/dev/wi/if_wi.c
@@ -132,6 +132,7 @@ static int wi_reset(struct wi_softc *);
static void wi_watchdog(void *);
static int wi_ioctl(struct ifnet *, u_long, caddr_t);
static void wi_media_status(struct ifnet *, struct ifmediareq *);
+static uint64_t wi_get_counter(struct ifnet *, ift_counter);
static void wi_rx_intr(struct wi_softc *);
static void wi_tx_intr(struct wi_softc *);
@@ -337,6 +338,7 @@ wi_attach(device_t dev)
ifp->if_ioctl = wi_ioctl;
ifp->if_start = wi_start;
ifp->if_init = wi_init;
+ ifp->if_get_counter = wi_get_counter;
IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
IFQ_SET_READY(&ifp->if_snd);
@@ -1028,7 +1030,7 @@ wi_start_locked(struct ifnet *ifp)
continue;
sc->sc_txnext = cur = (cur + 1) % sc->sc_ntxbuf;
- ifp->if_opackets++;
+ if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
}
}
@@ -1055,7 +1057,7 @@ wi_start_tx(struct ifnet *ifp, struct wi_frame *frmhdr, struct mbuf *m0)
|| wi_mwrite_bap(sc, fid, off, m0, m0->m_pkthdr.len) != 0;
m_freem(m0);
if (error) {
- ifp->if_oerrors++;
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
return -1;
}
sc->sc_txd[cur].d_len = off;
@@ -1182,7 +1184,7 @@ wi_watchdog(void *arg)
if (sc->sc_tx_timer && --sc->sc_tx_timer == 0) {
if_printf(ifp, "device timeout\n");
- ifp->if_oerrors++;
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
wi_init_locked(ifp->if_softc);
return;
}
@@ -1327,7 +1329,7 @@ wi_rx_intr(struct wi_softc *sc)
/* First read in the frame header */
if (wi_read_bap(sc, fid, 0, &frmhdr, sizeof(frmhdr))) {
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
- ifp->if_ierrors++;
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
DPRINTF(("wi_rx_intr: read fid %x failed\n", fid));
return;
}
@@ -1338,7 +1340,7 @@ wi_rx_intr(struct wi_softc *sc)
status = le16toh(frmhdr.wi_status);
if (status & WI_STAT_ERRSTAT) {
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
- ifp->if_ierrors++;
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
DPRINTF(("wi_rx_intr: fid %x error status %x\n", fid, status));
return;
}
@@ -1353,7 +1355,7 @@ wi_rx_intr(struct wi_softc *sc)
if (off + len > MCLBYTES) {
if (ic->ic_opmode != IEEE80211_M_MONITOR) {
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
- ifp->if_ierrors++;
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
DPRINTF(("wi_rx_intr: oversized packet\n"));
return;
} else
@@ -1366,7 +1368,7 @@ wi_rx_intr(struct wi_softc *sc)
m = m_gethdr(M_NOWAIT, MT_DATA);
if (m == NULL) {
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_RX);
- ifp->if_ierrors++;
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
DPRINTF(("wi_rx_intr: MGET failed\n"));
return;
}
@@ -1450,11 +1452,9 @@ wi_tx_ex_intr(struct wi_softc *sc)
printf(", status=0x%x", status);
printf("\n");
}
- ifp->if_oerrors++;
- } else {
+ if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+ } else
DPRINTF(("port disconnected\n"));
- ifp->if_collisions++; /* XXX */
- }
} else
DPRINTF(("wi_tx_ex_intr: read fid %x failed\n", fid));
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_TX_EXC);
@@ -1497,8 +1497,7 @@ wi_tx_intr(struct wi_softc *sc)
static __noinline void
wi_info_intr(struct wi_softc *sc)
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211com *ic = sc->sc_ifp->if_l2com;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
int i, fid, len, off;
u_int16_t ltbuf[2];
@@ -1562,9 +1561,6 @@ wi_info_intr(struct wi_softc *sc)
#endif
*ptr += stat;
}
- ifp->if_collisions = sc->sc_stats.wi_tx_single_retries +
- sc->sc_stats.wi_tx_multi_retries +
- sc->sc_stats.wi_tx_retry_limit;
break;
default:
DPRINTF(("wi_info_intr: got fid %x type %x len %d\n", fid,
@@ -1575,6 +1571,23 @@ finish:
CSR_WRITE_2(sc, WI_EVENT_ACK, WI_EV_INFO);
}
+static uint64_t
+wi_get_counter(struct ifnet *ifp, ift_counter cnt)
+{
+ struct wi_softc *sc;
+
+ sc = if_getsoftc(ifp);
+
+ switch (cnt) {
+ case IFCOUNTER_COLLISIONS:
+ return (sc->sc_stats.wi_tx_single_retries +
+ sc->sc_stats.wi_tx_multi_retries +
+ sc->sc_stats.wi_tx_retry_limit);
+ default:
+ return (if_get_counter_default(ifp, cnt));
+ }
+}
+
static int
wi_write_multi(struct wi_softc *sc)
{
diff --git a/sys/dev/xen/netfront/netfront.c b/sys/dev/xen/netfront/netfront.c
index 568511b..a652c75 100644
--- a/sys/dev/xen/netfront/netfront.c
+++ b/sys/dev/xen/netfront/netfront.c
@@ -134,7 +134,6 @@ static const int MODPARM_rx_flip = 0;
* to mirror the Linux MAX_SKB_FRAGS constant.
*/
#define MAX_TX_REQ_FRAGS (65536 / PAGE_SIZE + 2)
-#define NF_TSO_MAXBURST ((IP_MAXPACKET / PAGE_SIZE) * MCLBYTES)
#define RX_COPY_THRESHOLD 256
@@ -2102,7 +2101,9 @@ create_netdev(device_t dev)
ifp->if_hwassist = XN_CSUM_FEATURES;
ifp->if_capabilities = IFCAP_HWCSUM;
- ifp->if_hw_tsomax = NF_TSO_MAXBURST;
+ ifp->if_hw_tsomax = 65536 - (ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN);
+ ifp->if_hw_tsomaxsegcount = MAX_TX_REQ_FRAGS;
+ ifp->if_hw_tsomaxsegsize = PAGE_SIZE;
ether_ifattach(ifp, np->mac);
callout_init(&np->xn_stat_ch, CALLOUT_MPSAFE);
diff --git a/sys/fs/autofs/autofs.c b/sys/fs/autofs/autofs.c
index 988a1ab..5a247b4 100644
--- a/sys/fs/autofs/autofs.c
+++ b/sys/fs/autofs/autofs.c
@@ -429,11 +429,6 @@ autofs_trigger_one(struct autofs_node *anp,
&autofs_softc->sc_lock);
autofs_restore_sigmask(&oldset);
if (error != 0) {
- /*
- * XXX: For some reason this returns -1
- * instead of EINTR, wtf?!
- */
- error = EINTR;
AUTOFS_WARN("cv_wait_sig for %s failed "
"with error %d", ar->ar_path, error);
break;
@@ -495,7 +490,7 @@ autofs_trigger(struct autofs_node *anp,
anp->an_retries = 0;
return (0);
}
- if (error == EINTR) {
+ if (error == EINTR || error == ERESTART) {
AUTOFS_DEBUG("trigger interrupted by signal, "
"not retrying");
anp->an_retries = 0;
@@ -541,11 +536,6 @@ autofs_ioctl_request(struct autofs_daemon_request *adr)
error = cv_wait_sig(&autofs_softc->sc_cv,
&autofs_softc->sc_lock);
if (error != 0) {
- /*
- * XXX: For some reason this returns -1 instead
- * of EINTR, wtf?!
- */
- error = EINTR;
sx_xunlock(&autofs_softc->sc_lock);
AUTOFS_DEBUG("failed with error %d", error);
return (error);
diff --git a/sys/fs/autofs/autofs_vnops.c b/sys/fs/autofs/autofs_vnops.c
index e0a75fa..392c253 100644
--- a/sys/fs/autofs/autofs_vnops.c
+++ b/sys/fs/autofs/autofs_vnops.c
@@ -544,6 +544,8 @@ autofs_node_find(struct autofs_node *parent, const char *name,
TAILQ_FOREACH(anp, &parent->an_children, an_next) {
if (namelen >= 0) {
+ if (strlen(anp->an_name) != namelen)
+ continue;
if (strncmp(anp->an_name, name, namelen) != 0)
continue;
} else {
diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c
index 1e3f5e8..d0aabef 100644
--- a/sys/fs/devfs/devfs_vnops.c
+++ b/sys/fs/devfs/devfs_vnops.c
@@ -1700,6 +1700,7 @@ static struct fileops devfs_ops_f = {
.fo_chown = vn_chown,
.fo_sendfile = vn_sendfile,
.fo_seek = vn_seek,
+ .fo_fill_kinfo = vn_fill_kinfo,
.fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE
};
diff --git a/sys/gnu/fs/reiserfs/reiserfs_fs_i.h b/sys/gnu/fs/reiserfs/reiserfs_fs_i.h
index d9e358e..e269d92 100644
--- a/sys/gnu/fs/reiserfs/reiserfs_fs_i.h
+++ b/sys/gnu/fs/reiserfs/reiserfs_fs_i.h
@@ -59,7 +59,7 @@ struct reiserfs_node {
flags read from sd_attrs. */
uint16_t i_mode; /* IFMT, permissions. */
- uint16_t i_nlink; /* File link count. */
+ int16_t i_nlink; /* File link count. */
uint64_t i_size; /* File byte count. */
uint32_t i_bytes;
uid_t i_uid; /* File owner. */
diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
index 94e9db4..a3990ed 100644
--- a/sys/i386/i386/machdep.c
+++ b/sys/i386/i386/machdep.c
@@ -197,10 +197,6 @@ static void fill_fpregs_xmm(struct savexmm *, struct save87 *);
#endif /* CPU_ENABLE_SSE */
SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL);
-#ifdef DDB
-extern vm_offset_t ksym_start, ksym_end;
-#endif
-
/* Intel ICH registers */
#define ICH_PMBASE 0x400
#define ICH_SMI_EN ICH_PMBASE + 0x30
@@ -2736,8 +2732,7 @@ init386(first)
#endif
#ifdef DDB
- ksym_start = bootinfo.bi_symtab;
- ksym_end = bootinfo.bi_esymtab;
+ db_fetch_ksymtab(bootinfo.bi_symtab, bootinfo.bi_esymtab);
#endif
kdb_init();
@@ -3013,8 +3008,7 @@ init386(first)
#endif
#ifdef DDB
- ksym_start = bootinfo.bi_symtab;
- ksym_end = bootinfo.bi_esymtab;
+ db_fetch_ksymtab(bootinfo.bi_symtab, bootinfo.bi_esymtab);
#endif
kdb_init();
diff --git a/sys/kern/bus_if.m b/sys/kern/bus_if.m
index b0ad611..ccc854c 100644
--- a/sys/kern/bus_if.m
+++ b/sys/kern/bus_if.m
@@ -670,3 +670,25 @@ METHOD int remap_intr {
device_t _child;
u_int _irq;
} DEFAULT null_remap_intr;
+
+/**
+ * @brief Suspend a given child
+ *
+ * @param _dev the parent device of @p _child
+ * @param _child the device to suspend
+ */
+METHOD int suspend_child {
+ device_t _dev;
+ device_t _child;
+} DEFAULT bus_generic_suspend_child;
+
+/**
+ * @brief Resume a given child
+ *
+ * @param _dev the parent device of @p _child
+ * @param _child the device to resume
+ */
+METHOD int resume_child {
+ device_t _dev;
+ device_t _child;
+} DEFAULT bus_generic_resume_child;
diff --git a/sys/kern/kern_cons.c b/sys/kern/kern_cons.c
index da157ec..a6ccf62 100644
--- a/sys/kern/kern_cons.c
+++ b/sys/kern/kern_cons.c
@@ -607,6 +607,7 @@ SYSINIT(cndev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, cn_drvinit, NULL);
#ifdef HAS_TIMER_SPKR
static int beeping;
+static struct callout beeping_timer;
static void
sysbeepstop(void *chan)
@@ -629,11 +630,18 @@ sysbeep(int pitch, int period)
timer_spkr_setfreq(pitch);
if (!beeping) {
beeping = period;
- timeout(sysbeepstop, (void *)NULL, period);
+ callout_reset(&beeping_timer, period, sysbeepstop, NULL);
}
return (0);
}
+static void
+sysbeep_init(void *unused)
+{
+
+ callout_init(&beeping_timer, CALLOUT_MPSAFE);
+}
+SYSINIT(sysbeep, SI_SUB_SOFTINTR, SI_ORDER_ANY, sysbeep_init, NULL);
#else
/*
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index b6fcc76..c48378c 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -47,27 +47,21 @@ __FBSDID("$FreeBSD$");
#include <sys/capsicum.h>
#include <sys/conf.h>
-#include <sys/domain.h>
#include <sys/fcntl.h>
#include <sys/file.h>
#include <sys/filedesc.h>
#include <sys/filio.h>
#include <sys/jail.h>
#include <sys/kernel.h>
-#include <sys/ksem.h>
#include <sys/limits.h>
#include <sys/lock.h>
#include <sys/malloc.h>
-#include <sys/mman.h>
#include <sys/mount.h>
-#include <sys/mqueue.h>
#include <sys/mutex.h>
#include <sys/namei.h>
#include <sys/selinfo.h>
-#include <sys/pipe.h>
#include <sys/priv.h>
#include <sys/proc.h>
-#include <sys/procdesc.h>
#include <sys/protosw.h>
#include <sys/racct.h>
#include <sys/resourcevar.h>
@@ -79,10 +73,7 @@ __FBSDID("$FreeBSD$");
#include <sys/syscallsubr.h>
#include <sys/sysctl.h>
#include <sys/sysproto.h>
-#include <sys/tty.h>
#include <sys/unistd.h>
-#include <sys/un.h>
-#include <sys/unpcb.h>
#include <sys/user.h>
#include <sys/vnode.h>
#ifdef KTRACE
@@ -91,9 +82,6 @@ __FBSDID("$FreeBSD$");
#include <net/vnet.h>
-#include <netinet/in.h>
-#include <netinet/in_pcb.h>
-
#include <security/audit/audit.h>
#include <vm/uma.h>
@@ -111,26 +99,23 @@ MALLOC_DECLARE(M_FADVISE);
static uma_zone_t file_zone;
-void (*ksem_info)(struct ksem *ks, char *path, size_t size, uint32_t *value);
-
static int closefp(struct filedesc *fdp, int fd, struct file *fp,
struct thread *td, int holdleaders);
+static int do_dup(struct thread *td, int flags, int old, int new,
+ register_t *retval);
static int fd_first_free(struct filedesc *fdp, int low, int size);
static int fd_last_used(struct filedesc *fdp, int size);
static void fdgrowtable(struct filedesc *fdp, int nfd);
static void fdgrowtable_exp(struct filedesc *fdp, int nfd);
static void fdunused(struct filedesc *fdp, int fd);
static void fdused(struct filedesc *fdp, int fd);
-static int fill_pipe_info(struct pipe *pi, struct kinfo_file *kif);
-static int fill_procdesc_info(struct procdesc *pdp,
- struct kinfo_file *kif);
-static int fill_pts_info(struct tty *tp, struct kinfo_file *kif);
-static int fill_sem_info(struct file *fp, struct kinfo_file *kif);
-static int fill_shm_info(struct file *fp, struct kinfo_file *kif);
-static int fill_socket_info(struct socket *so, struct kinfo_file *kif);
-static int fill_vnode_info(struct vnode *vp, struct kinfo_file *kif);
static int getmaxfd(struct proc *p);
+/* Flags for do_dup() */
+#define DUP_FIXED 0x1 /* Force fixed allocation. */
+#define DUP_FCNTL 0x2 /* fcntl()-style errors. */
+#define DUP_CLOEXEC 0x4 /* Atomically set FD_CLOEXEC. */
+
/*
* Each process has:
*
@@ -400,22 +385,27 @@ struct fcntl_args {
int
sys_fcntl(struct thread *td, struct fcntl_args *uap)
{
+
+ return (kern_fcntl_freebsd(td, uap->fd, uap->cmd, uap->arg));
+}
+
+int
+kern_fcntl_freebsd(struct thread *td, int fd, int cmd, long arg)
+{
struct flock fl;
struct __oflock ofl;
- intptr_t arg;
+ intptr_t arg1;
int error;
- int cmd;
error = 0;
- cmd = uap->cmd;
- switch (uap->cmd) {
+ switch (cmd) {
case F_OGETLK:
case F_OSETLK:
case F_OSETLKW:
/*
* Convert old flock structure to new.
*/
- error = copyin((void *)(intptr_t)uap->arg, &ofl, sizeof(ofl));
+ error = copyin((void *)(intptr_t)arg, &ofl, sizeof(ofl));
fl.l_start = ofl.l_start;
fl.l_len = ofl.l_len;
fl.l_pid = ofl.l_pid;
@@ -423,7 +413,7 @@ sys_fcntl(struct thread *td, struct fcntl_args *uap)
fl.l_whence = ofl.l_whence;
fl.l_sysid = 0;
- switch (uap->cmd) {
+ switch (cmd) {
case F_OGETLK:
cmd = F_GETLK;
break;
@@ -434,33 +424,33 @@ sys_fcntl(struct thread *td, struct fcntl_args *uap)
cmd = F_SETLKW;
break;
}
- arg = (intptr_t)&fl;
+ arg1 = (intptr_t)&fl;
break;
case F_GETLK:
case F_SETLK:
case F_SETLKW:
case F_SETLK_REMOTE:
- error = copyin((void *)(intptr_t)uap->arg, &fl, sizeof(fl));
- arg = (intptr_t)&fl;
+ error = copyin((void *)(intptr_t)arg, &fl, sizeof(fl));
+ arg1 = (intptr_t)&fl;
break;
default:
- arg = uap->arg;
+ arg1 = arg;
break;
}
if (error)
return (error);
- error = kern_fcntl(td, uap->fd, cmd, arg);
+ error = kern_fcntl(td, fd, cmd, arg1);
if (error)
return (error);
- if (uap->cmd == F_OGETLK) {
+ if (cmd == F_OGETLK) {
ofl.l_start = fl.l_start;
ofl.l_len = fl.l_len;
ofl.l_pid = fl.l_pid;
ofl.l_type = fl.l_type;
ofl.l_whence = fl.l_whence;
- error = copyout(&ofl, (void *)(intptr_t)uap->arg, sizeof(ofl));
- } else if (uap->cmd == F_GETLK) {
- error = copyout(&fl, (void *)(intptr_t)uap->arg, sizeof(fl));
+ error = copyout(&ofl, (void *)(intptr_t)arg, sizeof(ofl));
+ } else if (cmd == F_GETLK) {
+ error = copyout(&fl, (void *)(intptr_t)arg, sizeof(fl));
}
return (error);
}
@@ -802,7 +792,7 @@ getmaxfd(struct proc *p)
/*
* Common code for dup, dup2, fcntl(F_DUPFD) and fcntl(F_DUP2FD).
*/
-int
+static int
do_dup(struct thread *td, int flags, int old, int new,
register_t *retval)
{
@@ -2945,280 +2935,14 @@ sysctl_kern_file(SYSCTL_HANDLER_ARGS)
SYSCTL_PROC(_kern, KERN_FILE, file, CTLTYPE_OPAQUE|CTLFLAG_RD|CTLFLAG_MPSAFE,
0, 0, sysctl_kern_file, "S,xfile", "Entire file table");
-#ifdef KINFO_OFILE_SIZE
-CTASSERT(sizeof(struct kinfo_ofile) == KINFO_OFILE_SIZE);
-#endif
-
-#ifdef COMPAT_FREEBSD7
-static int
-export_vnode_for_osysctl(struct vnode *vp, int type,
- struct kinfo_ofile *kif, struct filedesc *fdp, struct sysctl_req *req)
-{
- int error;
- char *fullpath, *freepath;
-
- bzero(kif, sizeof(*kif));
- kif->kf_structsize = sizeof(*kif);
-
- vref(vp);
- kif->kf_fd = type;
- kif->kf_type = KF_TYPE_VNODE;
- /* This function only handles directories. */
- if (vp->v_type != VDIR) {
- vrele(vp);
- return (ENOTDIR);
- }
- kif->kf_vnode_type = KF_VTYPE_VDIR;
-
- /*
- * This is not a true file descriptor, so we set a bogus refcount
- * and offset to indicate these fields should be ignored.
- */
- kif->kf_ref_count = -1;
- kif->kf_offset = -1;
-
- freepath = NULL;
- fullpath = "-";
- FILEDESC_SUNLOCK(fdp);
- vn_fullpath(curthread, vp, &fullpath, &freepath);
- vrele(vp);
- strlcpy(kif->kf_path, fullpath, sizeof(kif->kf_path));
- if (freepath != NULL)
- free(freepath, M_TEMP);
- error = SYSCTL_OUT(req, kif, sizeof(*kif));
- FILEDESC_SLOCK(fdp);
- return (error);
-}
-
-/*
- * Get per-process file descriptors for use by procstat(1), et al.
- */
-static int
-sysctl_kern_proc_ofiledesc(SYSCTL_HANDLER_ARGS)
-{
- char *fullpath, *freepath;
- struct kinfo_ofile *kif;
- struct filedesc *fdp;
- int error, i, *name;
- struct shmfd *shmfd;
- struct socket *so;
- struct vnode *vp;
- struct ksem *ks;
- struct file *fp;
- struct proc *p;
- struct tty *tp;
-
- name = (int *)arg1;
- error = pget((pid_t)name[0], PGET_CANDEBUG | PGET_NOTWEXIT, &p);
- if (error != 0)
- return (error);
- fdp = fdhold(p);
- PROC_UNLOCK(p);
- if (fdp == NULL)
- return (ENOENT);
- kif = malloc(sizeof(*kif), M_TEMP, M_WAITOK);
- FILEDESC_SLOCK(fdp);
- if (fdp->fd_cdir != NULL)
- export_vnode_for_osysctl(fdp->fd_cdir, KF_FD_TYPE_CWD, kif,
- fdp, req);
- if (fdp->fd_rdir != NULL)
- export_vnode_for_osysctl(fdp->fd_rdir, KF_FD_TYPE_ROOT, kif,
- fdp, req);
- if (fdp->fd_jdir != NULL)
- export_vnode_for_osysctl(fdp->fd_jdir, KF_FD_TYPE_JAIL, kif,
- fdp, req);
- for (i = 0; fdp->fd_refcnt > 0 && i <= fdp->fd_lastfile; i++) {
- if ((fp = fdp->fd_ofiles[i].fde_file) == NULL)
- continue;
- bzero(kif, sizeof(*kif));
- kif->kf_structsize = sizeof(*kif);
- ks = NULL;
- vp = NULL;
- so = NULL;
- tp = NULL;
- shmfd = NULL;
- kif->kf_fd = i;
-
- switch (fp->f_type) {
- case DTYPE_VNODE:
- kif->kf_type = KF_TYPE_VNODE;
- vp = fp->f_vnode;
- break;
-
- case DTYPE_SOCKET:
- kif->kf_type = KF_TYPE_SOCKET;
- so = fp->f_data;
- break;
-
- case DTYPE_PIPE:
- kif->kf_type = KF_TYPE_PIPE;
- break;
-
- case DTYPE_FIFO:
- kif->kf_type = KF_TYPE_FIFO;
- vp = fp->f_vnode;
- break;
-
- case DTYPE_KQUEUE:
- kif->kf_type = KF_TYPE_KQUEUE;
- break;
-
- case DTYPE_CRYPTO:
- kif->kf_type = KF_TYPE_CRYPTO;
- break;
-
- case DTYPE_MQUEUE:
- kif->kf_type = KF_TYPE_MQUEUE;
- break;
-
- case DTYPE_SHM:
- kif->kf_type = KF_TYPE_SHM;
- shmfd = fp->f_data;
- break;
-
- case DTYPE_SEM:
- kif->kf_type = KF_TYPE_SEM;
- ks = fp->f_data;
- break;
-
- case DTYPE_PTS:
- kif->kf_type = KF_TYPE_PTS;
- tp = fp->f_data;
- break;
-
- case DTYPE_PROCDESC:
- kif->kf_type = KF_TYPE_PROCDESC;
- break;
-
- default:
- kif->kf_type = KF_TYPE_UNKNOWN;
- break;
- }
- kif->kf_ref_count = fp->f_count;
- if (fp->f_flag & FREAD)
- kif->kf_flags |= KF_FLAG_READ;
- if (fp->f_flag & FWRITE)
- kif->kf_flags |= KF_FLAG_WRITE;
- if (fp->f_flag & FAPPEND)
- kif->kf_flags |= KF_FLAG_APPEND;
- if (fp->f_flag & FASYNC)
- kif->kf_flags |= KF_FLAG_ASYNC;
- if (fp->f_flag & FFSYNC)
- kif->kf_flags |= KF_FLAG_FSYNC;
- if (fp->f_flag & FNONBLOCK)
- kif->kf_flags |= KF_FLAG_NONBLOCK;
- if (fp->f_flag & O_DIRECT)
- kif->kf_flags |= KF_FLAG_DIRECT;
- if (fp->f_flag & FHASLOCK)
- kif->kf_flags |= KF_FLAG_HASLOCK;
- kif->kf_offset = foffset_get(fp);
- if (vp != NULL) {
- vref(vp);
- switch (vp->v_type) {
- case VNON:
- kif->kf_vnode_type = KF_VTYPE_VNON;
- break;
- case VREG:
- kif->kf_vnode_type = KF_VTYPE_VREG;
- break;
- case VDIR:
- kif->kf_vnode_type = KF_VTYPE_VDIR;
- break;
- case VBLK:
- kif->kf_vnode_type = KF_VTYPE_VBLK;
- break;
- case VCHR:
- kif->kf_vnode_type = KF_VTYPE_VCHR;
- break;
- case VLNK:
- kif->kf_vnode_type = KF_VTYPE_VLNK;
- break;
- case VSOCK:
- kif->kf_vnode_type = KF_VTYPE_VSOCK;
- break;
- case VFIFO:
- kif->kf_vnode_type = KF_VTYPE_VFIFO;
- break;
- case VBAD:
- kif->kf_vnode_type = KF_VTYPE_VBAD;
- break;
- default:
- kif->kf_vnode_type = KF_VTYPE_UNKNOWN;
- break;
- }
- /*
- * It is OK to drop the filedesc lock here as we will
- * re-validate and re-evaluate its properties when
- * the loop continues.
- */
- freepath = NULL;
- fullpath = "-";
- FILEDESC_SUNLOCK(fdp);
- vn_fullpath(curthread, vp, &fullpath, &freepath);
- vrele(vp);
- strlcpy(kif->kf_path, fullpath,
- sizeof(kif->kf_path));
- if (freepath != NULL)
- free(freepath, M_TEMP);
- FILEDESC_SLOCK(fdp);
- }
- if (so != NULL) {
- struct sockaddr *sa;
-
- if (so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa)
- == 0 && sa->sa_len <= sizeof(kif->kf_sa_local)) {
- bcopy(sa, &kif->kf_sa_local, sa->sa_len);
- free(sa, M_SONAME);
- }
- if (so->so_proto->pr_usrreqs->pru_peeraddr(so, &sa)
- == 0 && sa->sa_len <= sizeof(kif->kf_sa_peer)) {
- bcopy(sa, &kif->kf_sa_peer, sa->sa_len);
- free(sa, M_SONAME);
- }
- kif->kf_sock_domain =
- so->so_proto->pr_domain->dom_family;
- kif->kf_sock_type = so->so_type;
- kif->kf_sock_protocol = so->so_proto->pr_protocol;
- }
- if (tp != NULL) {
- strlcpy(kif->kf_path, tty_devname(tp),
- sizeof(kif->kf_path));
- }
- if (shmfd != NULL)
- shm_path(shmfd, kif->kf_path, sizeof(kif->kf_path));
- if (ks != NULL && ksem_info != NULL)
- ksem_info(ks, kif->kf_path, sizeof(kif->kf_path), NULL);
- error = SYSCTL_OUT(req, kif, sizeof(*kif));
- if (error)
- break;
- }
- FILEDESC_SUNLOCK(fdp);
- fddrop(fdp);
- free(kif, M_TEMP);
- return (0);
-}
-
-static SYSCTL_NODE(_kern_proc, KERN_PROC_OFILEDESC, ofiledesc,
- CTLFLAG_RD||CTLFLAG_MPSAFE, sysctl_kern_proc_ofiledesc,
- "Process ofiledesc entries");
-#endif /* COMPAT_FREEBSD7 */
-
#ifdef KINFO_FILE_SIZE
CTASSERT(sizeof(struct kinfo_file) == KINFO_FILE_SIZE);
#endif
-struct export_fd_buf {
- struct filedesc *fdp;
- struct sbuf *sb;
- ssize_t remainder;
- struct kinfo_file kif;
-};
-
static int
-export_fd_to_sb(void *data, int type, int fd, int fflags, int refcnt,
- int64_t offset, cap_rights_t *rightsp, struct export_fd_buf *efbuf)
+xlate_fflags(int fflags)
{
- struct {
+ static const struct {
int fflag;
int kf_fflag;
} fflags_table[] = {
@@ -3238,83 +2962,126 @@ export_fd_to_sb(void *data, int type, int fd, int fflags, int refcnt,
{ O_SHLOCK, KF_FLAG_SHLOCK },
{ O_TRUNC, KF_FLAG_TRUNC }
};
-#define NFFLAGS (sizeof(fflags_table) / sizeof(*fflags_table))
- struct kinfo_file *kif;
- struct vnode *vp;
- int error, locked;
unsigned int i;
+ int kflags;
+
+ kflags = 0;
+ for (i = 0; i < nitems(fflags_table); i++)
+ if (fflags & fflags_table[i].fflag)
+ kflags |= fflags_table[i].kf_fflag;
+ return (kflags);
+}
+
+/* Trim unused data from kf_path by truncating the structure size. */
+static void
+pack_kinfo(struct kinfo_file *kif)
+{
+
+ kif->kf_structsize = offsetof(struct kinfo_file, kf_path) +
+ strlen(kif->kf_path) + 1;
+ kif->kf_structsize = roundup(kif->kf_structsize, sizeof(uint64_t));
+}
+
+static void
+export_file_to_kinfo(struct file *fp, int fd, cap_rights_t *rightsp,
+ struct kinfo_file *kif, struct filedesc *fdp)
+{
+ int error;
- if (efbuf->remainder == 0)
- return (0);
- kif = &efbuf->kif;
bzero(kif, sizeof(*kif));
- locked = efbuf->fdp != NULL;
- switch (type) {
- case KF_TYPE_FIFO:
- case KF_TYPE_VNODE:
- if (locked) {
- FILEDESC_SUNLOCK(efbuf->fdp);
- locked = 0;
- }
- vp = (struct vnode *)data;
- error = fill_vnode_info(vp, kif);
- vrele(vp);
- break;
- case KF_TYPE_SOCKET:
- error = fill_socket_info((struct socket *)data, kif);
- break;
- case KF_TYPE_PIPE:
- error = fill_pipe_info((struct pipe *)data, kif);
- break;
- case KF_TYPE_PTS:
- error = fill_pts_info((struct tty *)data, kif);
- break;
- case KF_TYPE_PROCDESC:
- error = fill_procdesc_info((struct procdesc *)data, kif);
- break;
- case KF_TYPE_SEM:
- error = fill_sem_info((struct file *)data, kif);
- break;
- case KF_TYPE_SHM:
- error = fill_shm_info((struct file *)data, kif);
- break;
- default:
- error = 0;
- }
- if (error == 0)
- kif->kf_status |= KF_ATTR_VALID;
- /*
- * Translate file access flags.
- */
- for (i = 0; i < NFFLAGS; i++)
- if (fflags & fflags_table[i].fflag)
- kif->kf_flags |= fflags_table[i].kf_fflag;
+ /* Set a default type to allow for empty fill_kinfo() methods. */
+ kif->kf_type = KF_TYPE_UNKNOWN;
+ kif->kf_flags = xlate_fflags(fp->f_flag);
if (rightsp != NULL)
kif->kf_cap_rights = *rightsp;
else
cap_rights_init(&kif->kf_cap_rights);
kif->kf_fd = fd;
- kif->kf_type = type;
- kif->kf_ref_count = refcnt;
- kif->kf_offset = offset;
- /* Pack record size down */
- kif->kf_structsize = offsetof(struct kinfo_file, kf_path) +
- strlen(kif->kf_path) + 1;
- kif->kf_structsize = roundup(kif->kf_structsize, sizeof(uint64_t));
+ kif->kf_ref_count = fp->f_count;
+ kif->kf_offset = foffset_get(fp);
+
+ /*
+ * This may drop the filedesc lock, so the 'fp' cannot be
+ * accessed after this call.
+ */
+ error = fo_fill_kinfo(fp, kif, fdp);
+ if (error == 0)
+ kif->kf_status |= KF_ATTR_VALID;
+ pack_kinfo(kif);
+}
+
+static void
+export_vnode_to_kinfo(struct vnode *vp, int fd, int fflags,
+ struct kinfo_file *kif)
+{
+ int error;
+
+ bzero(kif, sizeof(*kif));
+
+ kif->kf_type = KF_TYPE_VNODE;
+ error = vn_fill_kinfo_vnode(vp, kif);
+ if (error == 0)
+ kif->kf_status |= KF_ATTR_VALID;
+ kif->kf_flags = xlate_fflags(fflags);
+ kif->kf_fd = fd;
+ kif->kf_ref_count = -1;
+ kif->kf_offset = -1;
+ pack_kinfo(kif);
+ vrele(vp);
+}
+
+struct export_fd_buf {
+ struct filedesc *fdp;
+ struct sbuf *sb;
+ ssize_t remainder;
+ struct kinfo_file kif;
+};
+
+static int
+export_kinfo_to_sb(struct export_fd_buf *efbuf)
+{
+ struct kinfo_file *kif;
+
+ kif = &efbuf->kif;
if (efbuf->remainder != -1) {
if (efbuf->remainder < kif->kf_structsize) {
/* Terminate export. */
efbuf->remainder = 0;
- if (efbuf->fdp != NULL && !locked)
- FILEDESC_SLOCK(efbuf->fdp);
return (0);
}
efbuf->remainder -= kif->kf_structsize;
}
- if (locked)
+ return (sbuf_bcat(efbuf->sb, kif, kif->kf_structsize));
+}
+
+static int
+export_file_to_sb(struct file *fp, int fd, cap_rights_t *rightsp,
+ struct export_fd_buf *efbuf)
+{
+ int error;
+
+ if (efbuf->remainder == 0)
+ return (0);
+ export_file_to_kinfo(fp, fd, rightsp, &efbuf->kif, efbuf->fdp);
+ FILEDESC_SUNLOCK(efbuf->fdp);
+ error = export_kinfo_to_sb(efbuf);
+ FILEDESC_SLOCK(efbuf->fdp);
+ return (error);
+}
+
+static int
+export_vnode_to_sb(struct vnode *vp, int fd, int fflags,
+ struct export_fd_buf *efbuf)
+{
+ int error;
+
+ if (efbuf->remainder == 0)
+ return (0);
+ if (efbuf->fdp != NULL)
FILEDESC_SUNLOCK(efbuf->fdp);
- error = sbuf_bcat(efbuf->sb, kif, kif->kf_structsize);
+ export_vnode_to_kinfo(vp, fd, fflags, &efbuf->kif);
+ error = export_kinfo_to_sb(efbuf);
if (efbuf->fdp != NULL)
FILEDESC_SLOCK(efbuf->fdp);
return (error);
@@ -3328,16 +3095,15 @@ export_fd_to_sb(void *data, int type, int fd, int fflags, int refcnt,
int
kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen)
{
+ struct thread *td;
struct file *fp;
struct filedesc *fdp;
struct export_fd_buf *efbuf;
struct vnode *cttyvp, *textvp, *tracevp;
- int64_t offset;
- void *data;
int error, i;
- int type, refcnt, fflags;
cap_rights_t rights;
+ td = curthread;
PROC_LOCK_ASSERT(p, MA_OWNED);
/* ktrace vnode */
@@ -3362,14 +3128,13 @@ kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen)
efbuf->sb = sb;
efbuf->remainder = maxlen;
if (tracevp != NULL)
- export_fd_to_sb(tracevp, KF_TYPE_VNODE, KF_FD_TYPE_TRACE,
- FREAD | FWRITE, -1, -1, NULL, efbuf);
+ export_vnode_to_sb(tracevp, KF_FD_TYPE_TRACE, FREAD | FWRITE,
+ efbuf);
if (textvp != NULL)
- export_fd_to_sb(textvp, KF_TYPE_VNODE, KF_FD_TYPE_TEXT,
- FREAD, -1, -1, NULL, efbuf);
+ export_vnode_to_sb(textvp, KF_FD_TYPE_TEXT, FREAD, efbuf);
if (cttyvp != NULL)
- export_fd_to_sb(cttyvp, KF_TYPE_VNODE, KF_FD_TYPE_CTTY,
- FREAD | FWRITE, -1, -1, NULL, efbuf);
+ export_vnode_to_sb(cttyvp, KF_FD_TYPE_CTTY, FREAD | FWRITE,
+ efbuf);
error = 0;
if (fdp == NULL)
goto fail;
@@ -3378,105 +3143,34 @@ kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen)
/* working directory */
if (fdp->fd_cdir != NULL) {
vref(fdp->fd_cdir);
- data = fdp->fd_cdir;
- export_fd_to_sb(data, KF_TYPE_VNODE, KF_FD_TYPE_CWD,
- FREAD, -1, -1, NULL, efbuf);
+ export_vnode_to_sb(fdp->fd_cdir, KF_FD_TYPE_CWD, FREAD, efbuf);
}
/* root directory */
if (fdp->fd_rdir != NULL) {
vref(fdp->fd_rdir);
- data = fdp->fd_rdir;
- export_fd_to_sb(data, KF_TYPE_VNODE, KF_FD_TYPE_ROOT,
- FREAD, -1, -1, NULL, efbuf);
+ export_vnode_to_sb(fdp->fd_rdir, KF_FD_TYPE_ROOT, FREAD, efbuf);
}
/* jail directory */
if (fdp->fd_jdir != NULL) {
vref(fdp->fd_jdir);
- data = fdp->fd_jdir;
- export_fd_to_sb(data, KF_TYPE_VNODE, KF_FD_TYPE_JAIL,
- FREAD, -1, -1, NULL, efbuf);
+ export_vnode_to_sb(fdp->fd_jdir, KF_FD_TYPE_JAIL, FREAD, efbuf);
}
for (i = 0; fdp->fd_refcnt > 0 && i <= fdp->fd_lastfile; i++) {
if ((fp = fdp->fd_ofiles[i].fde_file) == NULL)
continue;
- data = NULL;
#ifdef CAPABILITIES
rights = *cap_rights(fdp, i);
#else /* !CAPABILITIES */
cap_rights_init(&rights);
#endif
- switch (fp->f_type) {
- case DTYPE_VNODE:
- type = KF_TYPE_VNODE;
- vref(fp->f_vnode);
- data = fp->f_vnode;
- break;
-
- case DTYPE_SOCKET:
- type = KF_TYPE_SOCKET;
- data = fp->f_data;
- break;
-
- case DTYPE_PIPE:
- type = KF_TYPE_PIPE;
- data = fp->f_data;
- break;
-
- case DTYPE_FIFO:
- type = KF_TYPE_FIFO;
- vref(fp->f_vnode);
- data = fp->f_vnode;
- break;
-
- case DTYPE_KQUEUE:
- type = KF_TYPE_KQUEUE;
- break;
-
- case DTYPE_CRYPTO:
- type = KF_TYPE_CRYPTO;
- break;
-
- case DTYPE_MQUEUE:
- type = KF_TYPE_MQUEUE;
- break;
-
- case DTYPE_SHM:
- type = KF_TYPE_SHM;
- data = fp;
- break;
-
- case DTYPE_SEM:
- type = KF_TYPE_SEM;
- data = fp;
- break;
-
- case DTYPE_PTS:
- type = KF_TYPE_PTS;
- data = fp->f_data;
- break;
-
- case DTYPE_PROCDESC:
- type = KF_TYPE_PROCDESC;
- data = fp->f_data;
- break;
-
- default:
- type = KF_TYPE_UNKNOWN;
- break;
- }
- refcnt = fp->f_count;
- fflags = fp->f_flag;
- offset = foffset_get(fp);
-
/*
- * Create sysctl entry.
- * It is OK to drop the filedesc lock here as we will
- * re-validate and re-evaluate its properties when
- * the loop continues.
+ * Create sysctl entry. It is OK to drop the filedesc
+ * lock inside of export_file_to_sb() as we will
+ * re-validate and re-evaluate its properties when the
+ * loop continues.
*/
- error = export_fd_to_sb(data, type, i, fflags, refcnt,
- offset, &rights, efbuf);
- if (error != 0)
+ error = export_file_to_sb(fp, i, &rights, efbuf);
+ if (error != 0 || efbuf->remainder == 0)
break;
}
FILEDESC_SUNLOCK(fdp);
@@ -3514,6 +3208,105 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS)
return (error != 0 ? error : error2);
}
+#ifdef KINFO_OFILE_SIZE
+CTASSERT(sizeof(struct kinfo_ofile) == KINFO_OFILE_SIZE);
+#endif
+
+#ifdef COMPAT_FREEBSD7
+static void
+kinfo_to_okinfo(struct kinfo_file *kif, struct kinfo_ofile *okif)
+{
+
+ okif->kf_structsize = sizeof(*okif);
+ okif->kf_type = kif->kf_type;
+ okif->kf_fd = kif->kf_fd;
+ okif->kf_ref_count = kif->kf_ref_count;
+ okif->kf_flags = kif->kf_flags & (KF_FLAG_READ | KF_FLAG_WRITE |
+ KF_FLAG_APPEND | KF_FLAG_ASYNC | KF_FLAG_FSYNC | KF_FLAG_NONBLOCK |
+ KF_FLAG_DIRECT | KF_FLAG_HASLOCK);
+ okif->kf_offset = kif->kf_offset;
+ okif->kf_vnode_type = kif->kf_vnode_type;
+ okif->kf_sock_domain = kif->kf_sock_domain;
+ okif->kf_sock_type = kif->kf_sock_type;
+ okif->kf_sock_protocol = kif->kf_sock_protocol;
+ strlcpy(okif->kf_path, kif->kf_path, sizeof(okif->kf_path));
+ okif->kf_sa_local = kif->kf_sa_local;
+ okif->kf_sa_peer = kif->kf_sa_peer;
+}
+
+static int
+export_vnode_for_osysctl(struct vnode *vp, int type, struct kinfo_file *kif,
+ struct kinfo_ofile *okif, struct filedesc *fdp, struct sysctl_req *req)
+{
+ int error;
+
+ vref(vp);
+ FILEDESC_SUNLOCK(fdp);
+ export_vnode_to_kinfo(vp, type, 0, kif);
+ kinfo_to_okinfo(kif, okif);
+ error = SYSCTL_OUT(req, okif, sizeof(*okif));
+ FILEDESC_SLOCK(fdp);
+ return (error);
+}
+
+/*
+ * Get per-process file descriptors for use by procstat(1), et al.
+ */
+static int
+sysctl_kern_proc_ofiledesc(SYSCTL_HANDLER_ARGS)
+{
+ struct kinfo_ofile *okif;
+ struct kinfo_file *kif;
+ struct filedesc *fdp;
+ struct thread *td;
+ int error, i, *name;
+ struct file *fp;
+ struct proc *p;
+
+ td = curthread;
+ name = (int *)arg1;
+ error = pget((pid_t)name[0], PGET_CANDEBUG | PGET_NOTWEXIT, &p);
+ if (error != 0)
+ return (error);
+ fdp = fdhold(p);
+ PROC_UNLOCK(p);
+ if (fdp == NULL)
+ return (ENOENT);
+ kif = malloc(sizeof(*kif), M_TEMP, M_WAITOK);
+ okif = malloc(sizeof(*okif), M_TEMP, M_WAITOK);
+ FILEDESC_SLOCK(fdp);
+ if (fdp->fd_cdir != NULL)
+ export_vnode_for_osysctl(fdp->fd_cdir, KF_FD_TYPE_CWD, kif,
+ okif, fdp, req);
+ if (fdp->fd_rdir != NULL)
+ export_vnode_for_osysctl(fdp->fd_rdir, KF_FD_TYPE_ROOT, kif,
+ okif, fdp, req);
+ if (fdp->fd_jdir != NULL)
+ export_vnode_for_osysctl(fdp->fd_jdir, KF_FD_TYPE_JAIL, kif,
+ okif, fdp, req);
+ for (i = 0; fdp->fd_refcnt > 0 && i <= fdp->fd_lastfile; i++) {
+ if ((fp = fdp->fd_ofiles[i].fde_file) == NULL)
+ continue;
+ export_file_to_kinfo(fp, i, NULL, kif, fdp);
+ FILEDESC_SUNLOCK(fdp);
+ kinfo_to_okinfo(kif, okif);
+ error = SYSCTL_OUT(req, okif, sizeof(*okif));
+ FILEDESC_SLOCK(fdp);
+ if (error)
+ break;
+ }
+ FILEDESC_SUNLOCK(fdp);
+ fddrop(fdp);
+ free(kif, M_TEMP);
+ free(okif, M_TEMP);
+ return (0);
+}
+
+static SYSCTL_NODE(_kern_proc, KERN_PROC_OFILEDESC, ofiledesc,
+ CTLFLAG_RD||CTLFLAG_MPSAFE, sysctl_kern_proc_ofiledesc,
+ "Process ofiledesc entries");
+#endif /* COMPAT_FREEBSD7 */
+
int
vntype_to_kinfo(int vtype)
{
@@ -3543,170 +3336,6 @@ vntype_to_kinfo(int vtype)
return (KF_VTYPE_UNKNOWN);
}
-static int
-fill_vnode_info(struct vnode *vp, struct kinfo_file *kif)
-{
- struct vattr va;
- char *fullpath, *freepath;
- int error;
-
- if (vp == NULL)
- return (1);
- kif->kf_vnode_type = vntype_to_kinfo(vp->v_type);
- freepath = NULL;
- fullpath = "-";
- error = vn_fullpath(curthread, vp, &fullpath, &freepath);
- if (error == 0) {
- strlcpy(kif->kf_path, fullpath, sizeof(kif->kf_path));
- }
- if (freepath != NULL)
- free(freepath, M_TEMP);
-
- /*
- * Retrieve vnode attributes.
- */
- va.va_fsid = VNOVAL;
- va.va_rdev = NODEV;
- vn_lock(vp, LK_SHARED | LK_RETRY);
- error = VOP_GETATTR(vp, &va, curthread->td_ucred);
- VOP_UNLOCK(vp, 0);
- if (error != 0)
- return (error);
- if (va.va_fsid != VNOVAL)
- kif->kf_un.kf_file.kf_file_fsid = va.va_fsid;
- else
- kif->kf_un.kf_file.kf_file_fsid =
- vp->v_mount->mnt_stat.f_fsid.val[0];
- kif->kf_un.kf_file.kf_file_fileid = va.va_fileid;
- kif->kf_un.kf_file.kf_file_mode = MAKEIMODE(va.va_type, va.va_mode);
- kif->kf_un.kf_file.kf_file_size = va.va_size;
- kif->kf_un.kf_file.kf_file_rdev = va.va_rdev;
- return (0);
-}
-
-static int
-fill_socket_info(struct socket *so, struct kinfo_file *kif)
-{
- struct sockaddr *sa;
- struct inpcb *inpcb;
- struct unpcb *unpcb;
- int error;
-
- if (so == NULL)
- return (1);
- kif->kf_sock_domain = so->so_proto->pr_domain->dom_family;
- kif->kf_sock_type = so->so_type;
- kif->kf_sock_protocol = so->so_proto->pr_protocol;
- kif->kf_un.kf_sock.kf_sock_pcb = (uintptr_t)so->so_pcb;
- switch(kif->kf_sock_domain) {
- case AF_INET:
- case AF_INET6:
- if (kif->kf_sock_protocol == IPPROTO_TCP) {
- if (so->so_pcb != NULL) {
- inpcb = (struct inpcb *)(so->so_pcb);
- kif->kf_un.kf_sock.kf_sock_inpcb =
- (uintptr_t)inpcb->inp_ppcb;
- }
- }
- break;
- case AF_UNIX:
- if (so->so_pcb != NULL) {
- unpcb = (struct unpcb *)(so->so_pcb);
- if (unpcb->unp_conn) {
- kif->kf_un.kf_sock.kf_sock_unpconn =
- (uintptr_t)unpcb->unp_conn;
- kif->kf_un.kf_sock.kf_sock_rcv_sb_state =
- so->so_rcv.sb_state;
- kif->kf_un.kf_sock.kf_sock_snd_sb_state =
- so->so_snd.sb_state;
- }
- }
- break;
- }
- error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
- if (error == 0 && sa->sa_len <= sizeof(kif->kf_sa_local)) {
- bcopy(sa, &kif->kf_sa_local, sa->sa_len);
- free(sa, M_SONAME);
- }
- error = so->so_proto->pr_usrreqs->pru_peeraddr(so, &sa);
- if (error == 0 && sa->sa_len <= sizeof(kif->kf_sa_peer)) {
- bcopy(sa, &kif->kf_sa_peer, sa->sa_len);
- free(sa, M_SONAME);
- }
- strncpy(kif->kf_path, so->so_proto->pr_domain->dom_name,
- sizeof(kif->kf_path));
- return (0);
-}
-
-static int
-fill_pts_info(struct tty *tp, struct kinfo_file *kif)
-{
-
- if (tp == NULL)
- return (1);
- kif->kf_un.kf_pts.kf_pts_dev = tty_udev(tp);
- strlcpy(kif->kf_path, tty_devname(tp), sizeof(kif->kf_path));
- return (0);
-}
-
-static int
-fill_pipe_info(struct pipe *pi, struct kinfo_file *kif)
-{
-
- if (pi == NULL)
- return (1);
- kif->kf_un.kf_pipe.kf_pipe_addr = (uintptr_t)pi;
- kif->kf_un.kf_pipe.kf_pipe_peer = (uintptr_t)pi->pipe_peer;
- kif->kf_un.kf_pipe.kf_pipe_buffer_cnt = pi->pipe_buffer.cnt;
- return (0);
-}
-
-static int
-fill_procdesc_info(struct procdesc *pdp, struct kinfo_file *kif)
-{
-
- if (pdp == NULL)
- return (1);
- kif->kf_un.kf_proc.kf_pid = pdp->pd_pid;
- return (0);
-}
-
-static int
-fill_sem_info(struct file *fp, struct kinfo_file *kif)
-{
- struct thread *td;
- struct stat sb;
-
- td = curthread;
- if (fp->f_data == NULL)
- return (1);
- if (fo_stat(fp, &sb, td->td_ucred, td) != 0)
- return (1);
- if (ksem_info == NULL)
- return (1);
- ksem_info(fp->f_data, kif->kf_path, sizeof(kif->kf_path),
- &kif->kf_un.kf_sem.kf_sem_value);
- kif->kf_un.kf_sem.kf_sem_mode = sb.st_mode;
- return (0);
-}
-
-static int
-fill_shm_info(struct file *fp, struct kinfo_file *kif)
-{
- struct thread *td;
- struct stat sb;
-
- td = curthread;
- if (fp->f_data == NULL)
- return (1);
- if (fo_stat(fp, &sb, td->td_ucred, td) != 0)
- return (1);
- shm_path(fp->f_data, kif->kf_path, sizeof(kif->kf_path));
- kif->kf_un.kf_file.kf_file_mode = sb.st_mode;
- kif->kf_un.kf_file.kf_file_size = sb.st_size;
- return (0);
-}
-
static SYSCTL_NODE(_kern_proc, KERN_PROC_FILEDESC, filedesc,
CTLFLAG_RD|CTLFLAG_MPSAFE, sysctl_kern_proc_filedesc,
"Process filedesc entries");
@@ -3926,6 +3555,13 @@ badfo_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio,
return (EBADF);
}
+static int
+badfo_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
+{
+
+ return (0);
+}
+
struct fileops badfileops = {
.fo_read = badfo_readwrite,
.fo_write = badfo_readwrite,
@@ -3938,6 +3574,7 @@ struct fileops badfileops = {
.fo_chmod = badfo_chmod,
.fo_chown = badfo_chown,
.fo_sendfile = badfo_sendfile,
+ .fo_fill_kinfo = badfo_fill_kinfo,
};
int
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index 36ec19e..7488652 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$");
#include <sys/syscallsubr.h>
#include <sys/taskqueue.h>
#include <sys/uio.h>
+#include <sys/user.h>
#ifdef KTRACE
#include <sys/ktrace.h>
#endif
@@ -114,6 +115,7 @@ static fo_poll_t kqueue_poll;
static fo_kqfilter_t kqueue_kqfilter;
static fo_stat_t kqueue_stat;
static fo_close_t kqueue_close;
+static fo_fill_kinfo_t kqueue_fill_kinfo;
static struct fileops kqueueops = {
.fo_read = invfo_rdwr,
@@ -127,6 +129,7 @@ static struct fileops kqueueops = {
.fo_chmod = invfo_chmod,
.fo_chown = invfo_chown,
.fo_sendfile = invfo_sendfile,
+ .fo_fill_kinfo = kqueue_fill_kinfo,
};
static int knote_attach(struct knote *kn, struct kqueue *kq);
@@ -1802,6 +1805,14 @@ kqueue_close(struct file *fp, struct thread *td)
return (0);
}
+static int
+kqueue_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
+{
+
+ kif->kf_type = KF_TYPE_KQUEUE;
+ return (0);
+}
+
static void
kqueue_wakeup(struct kqueue *kq)
{
diff --git a/sys/kern/kern_malloc.c b/sys/kern/kern_malloc.c
index c39f143..9e29030f 100644
--- a/sys/kern/kern_malloc.c
+++ b/sys/kern/kern_malloc.c
@@ -717,6 +717,8 @@ kmeminit(void)
* a given architecture.
*/
mem_size = vm_cnt.v_page_count;
+ if (mem_size <= 32768) /* delphij XXX 128MB */
+ kmem_zmax = PAGE_SIZE;
if (vm_kmem_size_scale < 1)
vm_kmem_size_scale = VM_KMEM_SIZE_SCALE;
diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c
index 7e2e5fb..974c540 100644
--- a/sys/kern/subr_bus.c
+++ b/sys/kern/subr_bus.c
@@ -135,6 +135,7 @@ struct device {
#define DF_DONENOMATCH 0x20 /* don't execute DEVICE_NOMATCH again */
#define DF_EXTERNALSOFTC 0x40 /* softc not allocated by us */
#define DF_REBID 0x80 /* Can rebid after attach */
+#define DF_SUSPENDED 0x100 /* Device is suspended. */
u_int order; /**< order from device_add_child_ordered() */
void *ivars; /**< instance variables */
void *softc; /**< current driver's variables */
@@ -3301,7 +3302,10 @@ resource_list_alloc(struct resource_list *rl, device_t bus, device_t child,
rle->flags |= RLE_ALLOCATED;
return (rle->res);
}
- panic("resource_list_alloc: resource entry is busy");
+ device_printf(bus,
+ "resource entry %#x type %d for child %s is busy\n", *rid,
+ type, device_get_nameunit(child));
+ return (NULL);
}
if (isdefault) {
@@ -3631,6 +3635,39 @@ bus_generic_shutdown(device_t dev)
}
/**
+ * @brief Default function for suspending a child device.
+ *
+ * This function is to be used by a bus's DEVICE_SUSPEND_CHILD().
+ */
+int
+bus_generic_suspend_child(device_t dev, device_t child)
+{
+ int error;
+
+ error = DEVICE_SUSPEND(child);
+
+ if (error == 0)
+ dev->flags |= DF_SUSPENDED;
+
+ return (error);
+}
+
+/**
+ * @brief Default function for resuming a child device.
+ *
+ * This function is to be used by a bus's DEVICE_RESUME_CHILD().
+ */
+int
+bus_generic_resume_child(device_t dev, device_t child)
+{
+
+ DEVICE_RESUME(child);
+ dev->flags &= ~DF_SUSPENDED;
+
+ return (0);
+}
+
+/**
* @brief Helper function for implementing DEVICE_SUSPEND()
*
* This function can be used to help implement the DEVICE_SUSPEND()
@@ -3646,12 +3683,12 @@ bus_generic_suspend(device_t dev)
device_t child, child2;
TAILQ_FOREACH(child, &dev->children, link) {
- error = DEVICE_SUSPEND(child);
+ error = BUS_SUSPEND_CHILD(dev, child);
if (error) {
for (child2 = TAILQ_FIRST(&dev->children);
child2 && child2 != child;
child2 = TAILQ_NEXT(child2, link))
- DEVICE_RESUME(child2);
+ BUS_RESUME_CHILD(dev, child2);
return (error);
}
}
@@ -3670,7 +3707,7 @@ bus_generic_resume(device_t dev)
device_t child;
TAILQ_FOREACH(child, &dev->children, link) {
- DEVICE_RESUME(child);
+ BUS_RESUME_CHILD(dev, child);
/* if resume fails, there's nothing we can usefully do... */
}
return (0);
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
index 1d12c8f..b39c4fe 100644
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -115,6 +115,7 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/vnode.h>
#include <sys/uio.h>
+#include <sys/user.h>
#include <sys/event.h>
#include <security/mac/mac_framework.h>
@@ -152,6 +153,7 @@ static fo_stat_t pipe_stat;
static fo_close_t pipe_close;
static fo_chmod_t pipe_chmod;
static fo_chown_t pipe_chown;
+static fo_fill_kinfo_t pipe_fill_kinfo;
struct fileops pipeops = {
.fo_read = pipe_read,
@@ -165,6 +167,7 @@ struct fileops pipeops = {
.fo_chmod = pipe_chmod,
.fo_chown = pipe_chown,
.fo_sendfile = invfo_sendfile,
+ .fo_fill_kinfo = pipe_fill_kinfo,
.fo_flags = DFLAG_PASSABLE
};
@@ -1607,6 +1610,21 @@ pipe_chown(fp, uid, gid, active_cred, td)
return (error);
}
+static int
+pipe_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
+{
+ struct pipe *pi;
+
+ if (fp->f_type == DTYPE_FIFO)
+ return (vn_fill_kinfo(fp, kif, fdp));
+ kif->kf_type = KF_TYPE_PIPE;
+ pi = fp->f_data;
+ kif->kf_un.kf_pipe.kf_pipe_addr = (uintptr_t)pi;
+ kif->kf_un.kf_pipe.kf_pipe_peer = (uintptr_t)pi->pipe_peer;
+ kif->kf_un.kf_pipe.kf_pipe_buffer_cnt = pi->pipe_buffer.cnt;
+ return (0);
+}
+
static void
pipe_free_kmem(cpipe)
struct pipe *cpipe;
diff --git a/sys/kern/sys_procdesc.c b/sys/kern/sys_procdesc.c
index 9bdca9a..948595f 100644
--- a/sys/kern/sys_procdesc.c
+++ b/sys/kern/sys_procdesc.c
@@ -78,6 +78,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/systm.h>
#include <sys/ucred.h>
+#include <sys/user.h>
#include <security/audit/audit.h>
@@ -91,6 +92,7 @@ static fo_poll_t procdesc_poll;
static fo_kqfilter_t procdesc_kqfilter;
static fo_stat_t procdesc_stat;
static fo_close_t procdesc_close;
+static fo_fill_kinfo_t procdesc_fill_kinfo;
static struct fileops procdesc_ops = {
.fo_read = invfo_rdwr,
@@ -104,6 +106,7 @@ static struct fileops procdesc_ops = {
.fo_chmod = invfo_chmod,
.fo_chown = invfo_chown,
.fo_sendfile = invfo_sendfile,
+ .fo_fill_kinfo = procdesc_fill_kinfo,
.fo_flags = DFLAG_PASSABLE,
};
@@ -531,3 +534,14 @@ procdesc_stat(struct file *fp, struct stat *sb, struct ucred *active_cred,
return (0);
}
+static int
+procdesc_fill_kinfo(struct file *fp, struct kinfo_file *kif,
+ struct filedesc *fdp)
+{
+ struct procdesc *pdp;
+
+ kif->kf_type = KF_TYPE_PROCDESC;
+ pdp = fp->f_data;
+ kif->kf_un.kf_proc.kf_pid = pdp->pd_pid;
+ return (0);
+}
diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c
index 4af12e0..47cedfe 100644
--- a/sys/kern/sys_socket.c
+++ b/sys/kern/sys_socket.c
@@ -34,8 +34,10 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/domain.h>
#include <sys/file.h>
#include <sys/filedesc.h>
+#include <sys/malloc.h>
#include <sys/proc.h>
#include <sys/protosw.h>
#include <sys/sigio.h>
@@ -48,12 +50,18 @@ __FBSDID("$FreeBSD$");
#include <sys/stat.h>
#include <sys/uio.h>
#include <sys/ucred.h>
+#include <sys/un.h>
+#include <sys/unpcb.h>
+#include <sys/user.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/route.h>
#include <net/vnet.h>
+#include <netinet/in.h>
+#include <netinet/in_pcb.h>
+
#include <security/mac/mac_framework.h>
static fo_rdwr_t soo_read;
@@ -63,6 +71,7 @@ static fo_poll_t soo_poll;
extern fo_kqfilter_t soo_kqfilter;
static fo_stat_t soo_stat;
static fo_close_t soo_close;
+static fo_fill_kinfo_t soo_fill_kinfo;
struct fileops socketops = {
.fo_read = soo_read,
@@ -76,6 +85,7 @@ struct fileops socketops = {
.fo_chmod = invfo_chmod,
.fo_chown = invfo_chown,
.fo_sendfile = invfo_sendfile,
+ .fo_fill_kinfo = soo_fill_kinfo,
.fo_flags = DFLAG_PASSABLE
};
@@ -293,3 +303,58 @@ soo_close(struct file *fp, struct thread *td)
error = soclose(so);
return (error);
}
+
+static int
+soo_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
+{
+ struct sockaddr *sa;
+ struct inpcb *inpcb;
+ struct unpcb *unpcb;
+ struct socket *so;
+ int error;
+
+ kif->kf_type = KF_TYPE_SOCKET;
+ so = fp->f_data;
+ kif->kf_sock_domain = so->so_proto->pr_domain->dom_family;
+ kif->kf_sock_type = so->so_type;
+ kif->kf_sock_protocol = so->so_proto->pr_protocol;
+ kif->kf_un.kf_sock.kf_sock_pcb = (uintptr_t)so->so_pcb;
+ switch (kif->kf_sock_domain) {
+ case AF_INET:
+ case AF_INET6:
+ if (kif->kf_sock_protocol == IPPROTO_TCP) {
+ if (so->so_pcb != NULL) {
+ inpcb = (struct inpcb *)(so->so_pcb);
+ kif->kf_un.kf_sock.kf_sock_inpcb =
+ (uintptr_t)inpcb->inp_ppcb;
+ }
+ }
+ break;
+ case AF_UNIX:
+ if (so->so_pcb != NULL) {
+ unpcb = (struct unpcb *)(so->so_pcb);
+ if (unpcb->unp_conn) {
+ kif->kf_un.kf_sock.kf_sock_unpconn =
+ (uintptr_t)unpcb->unp_conn;
+ kif->kf_un.kf_sock.kf_sock_rcv_sb_state =
+ so->so_rcv.sb_state;
+ kif->kf_un.kf_sock.kf_sock_snd_sb_state =
+ so->so_snd.sb_state;
+ }
+ }
+ break;
+ }
+ error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
+ if (error == 0 && sa->sa_len <= sizeof(kif->kf_sa_local)) {
+ bcopy(sa, &kif->kf_sa_local, sa->sa_len);
+ free(sa, M_SONAME);
+ }
+ error = so->so_proto->pr_usrreqs->pru_peeraddr(so, &sa);
+ if (error == 0 && sa->sa_len <= sizeof(kif->kf_sa_peer)) {
+ bcopy(sa, &kif->kf_sa_peer, sa->sa_len);
+ free(sa, M_SONAME);
+ }
+ strncpy(kif->kf_path, so->so_proto->pr_domain->dom_name,
+ sizeof(kif->kf_path));
+ return (0);
+}
diff --git a/sys/kern/tty_pts.c b/sys/kern/tty_pts.c
index 16cbb3c..58cbc52 100644
--- a/sys/kern/tty_pts.c
+++ b/sys/kern/tty_pts.c
@@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/tty.h>
#include <sys/ttycom.h>
+#include <sys/user.h>
#include <machine/stdarg.h>
@@ -580,6 +581,18 @@ ptsdev_close(struct file *fp, struct thread *td)
return (0);
}
+static int
+ptsdev_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
+{
+ struct tty *tp;
+
+ kif->kf_type = KF_TYPE_PTS;
+ tp = fp->f_data;
+ kif->kf_un.kf_pts.kf_pts_dev = tty_udev(tp);
+ strlcpy(kif->kf_path, tty_devname(tp), sizeof(kif->kf_path));
+ return (0);
+}
+
static struct fileops ptsdev_ops = {
.fo_read = ptsdev_read,
.fo_write = ptsdev_write,
@@ -592,6 +605,7 @@ static struct fileops ptsdev_ops = {
.fo_chmod = invfo_chmod,
.fo_chown = invfo_chown,
.fo_sendfile = invfo_sendfile,
+ .fo_fill_kinfo = ptsdev_fill_kinfo,
.fo_flags = DFLAG_PASSABLE,
};
diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c
index 24d5ada..154c1e7 100644
--- a/sys/kern/uipc_mqueue.c
+++ b/sys/kern/uipc_mqueue.c
@@ -81,6 +81,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <sys/taskqueue.h>
#include <sys/unistd.h>
+#include <sys/user.h>
#include <sys/vnode.h>
#include <machine/atomic.h>
@@ -2571,6 +2572,14 @@ filt_mqwrite(struct knote *kn, long hint)
return (mq->mq_curmsgs < mq->mq_maxmsg);
}
+static int
+mqf_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
+{
+
+ kif->kf_type = KF_TYPE_MQUEUE;
+ return (0);
+}
+
static struct fileops mqueueops = {
.fo_read = invfo_rdwr,
.fo_write = invfo_rdwr,
@@ -2583,6 +2592,7 @@ static struct fileops mqueueops = {
.fo_chmod = mqf_chmod,
.fo_chown = mqf_chown,
.fo_sendfile = invfo_sendfile,
+ .fo_fill_kinfo = mqf_fill_kinfo,
};
static struct vop_vector mqfs_vnodeops = {
diff --git a/sys/kern/uipc_sem.c b/sys/kern/uipc_sem.c
index 593c2a3..63b1cec 100644
--- a/sys/kern/uipc_sem.c
+++ b/sys/kern/uipc_sem.c
@@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysproto.h>
#include <sys/systm.h>
#include <sys/sx.h>
+#include <sys/user.h>
#include <sys/vnode.h>
#include <security/mac/mac_framework.h>
@@ -130,6 +131,7 @@ static fo_stat_t ksem_stat;
static fo_close_t ksem_closef;
static fo_chmod_t ksem_chmod;
static fo_chown_t ksem_chown;
+static fo_fill_kinfo_t ksem_fill_kinfo;
/* File descriptor operations. */
static struct fileops ksem_ops = {
@@ -144,6 +146,7 @@ static struct fileops ksem_ops = {
.fo_chmod = ksem_chmod,
.fo_chown = ksem_chown,
.fo_sendfile = invfo_sendfile,
+ .fo_fill_kinfo = ksem_fill_kinfo,
.fo_flags = DFLAG_PASSABLE
};
@@ -252,6 +255,26 @@ ksem_closef(struct file *fp, struct thread *td)
return (0);
}
+static int
+ksem_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
+{
+ struct ksem *ks;
+
+ kif->kf_type = KF_TYPE_SEM;
+ ks = fp->f_data;
+ mtx_lock(&sem_lock);
+ kif->kf_un.kf_sem.kf_sem_value = ks->ks_value;
+ kif->kf_un.kf_sem.kf_sem_mode = S_IFREG | ks->ks_mode; /* XXX */
+ mtx_unlock(&sem_lock);
+ if (ks->ks_path != NULL) {
+ sx_slock(&ksem_dict_lock);
+ if (ks->ks_path != NULL)
+ strlcpy(kif->kf_path, ks->ks_path, sizeof(kif->kf_path));
+ sx_sunlock(&ksem_dict_lock);
+ }
+ return (0);
+}
+
/*
* ksem object management including creation and reference counting
* routines.
@@ -388,20 +411,6 @@ ksem_remove(char *path, Fnv32_t fnv, struct ucred *ucred)
return (ENOENT);
}
-static void
-ksem_info_impl(struct ksem *ks, char *path, size_t size, uint32_t *value)
-{
-
- if (ks->ks_path == NULL)
- return;
- sx_slock(&ksem_dict_lock);
- if (ks->ks_path != NULL)
- strlcpy(path, ks->ks_path, size);
- if (value != NULL)
- *value = ks->ks_value;
- sx_sunlock(&ksem_dict_lock);
-}
-
static int
ksem_create_copyout_semid(struct thread *td, semid_t *semidp, int fd,
int compat32)
@@ -983,7 +992,6 @@ ksem_module_init(void)
p31b_setcfg(CTL_P1003_1B_SEMAPHORES, 200112L);
p31b_setcfg(CTL_P1003_1B_SEM_NSEMS_MAX, SEM_MAX);
p31b_setcfg(CTL_P1003_1B_SEM_VALUE_MAX, SEM_VALUE_MAX);
- ksem_info = ksem_info_impl;
error = syscall_helper_register(ksem_syscalls);
if (error)
@@ -1005,7 +1013,6 @@ ksem_module_destroy(void)
#endif
syscall_helper_unregister(ksem_syscalls);
- ksem_info = NULL;
p31b_setcfg(CTL_P1003_1B_SEMAPHORES, 0);
hashdestroy(ksem_dictionary, M_KSEM, ksem_hash);
sx_destroy(&ksem_dict_lock);
diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c
index 9a558be..7829620 100644
--- a/sys/kern/uipc_shm.c
+++ b/sys/kern/uipc_shm.c
@@ -75,6 +75,7 @@ __FBSDID("$FreeBSD$");
#include <sys/time.h>
#include <sys/vnode.h>
#include <sys/unistd.h>
+#include <sys/user.h>
#include <security/mac/mac_framework.h>
@@ -125,6 +126,7 @@ static fo_close_t shm_close;
static fo_chmod_t shm_chmod;
static fo_chown_t shm_chown;
static fo_seek_t shm_seek;
+static fo_fill_kinfo_t shm_fill_kinfo;
/* File descriptor operations. */
static struct fileops shm_ops = {
@@ -140,6 +142,7 @@ static struct fileops shm_ops = {
.fo_chown = shm_chown,
.fo_sendfile = vn_sendfile,
.fo_seek = shm_seek,
+ .fo_fill_kinfo = shm_fill_kinfo,
.fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE
};
@@ -1022,14 +1025,24 @@ shm_unmap(struct file *fp, void *mem, size_t size)
return (0);
}
-void
-shm_path(struct shmfd *shmfd, char *path, size_t size)
+static int
+shm_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
{
+ struct shmfd *shmfd;
+
+ kif->kf_type = KF_TYPE_SHM;
+ shmfd = fp->f_data;
- if (shmfd->shm_path == NULL)
- return;
- sx_slock(&shm_dict_lock);
- if (shmfd->shm_path != NULL)
- strlcpy(path, shmfd->shm_path, size);
- sx_sunlock(&shm_dict_lock);
+ mtx_lock(&shm_timestamp_lock);
+ kif->kf_un.kf_file.kf_file_mode = S_IFREG | shmfd->shm_mode; /* XXX */
+ mtx_unlock(&shm_timestamp_lock);
+ kif->kf_un.kf_file.kf_file_size = shmfd->shm_size;
+ if (shmfd->shm_path != NULL) {
+ sx_slock(&shm_dict_lock);
+ if (shmfd->shm_path != NULL)
+ strlcpy(kif->kf_path, shmfd->shm_path,
+ sizeof(kif->kf_path));
+ sx_sunlock(&shm_dict_lock);
+ }
+ return (0);
}
diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c
index 2582089..c74343b 100644
--- a/sys/kern/uipc_sockbuf.c
+++ b/sys/kern/uipc_sockbuf.c
@@ -1015,6 +1015,37 @@ sbsndptr(struct sockbuf *sb, u_int off, u_int len, u_int *moff)
}
/*
+ * Return the first mbuf and the mbuf data offset for the provided
+ * send offset without changing the "sb_sndptroff" field.
+ */
+struct mbuf *
+sbsndmbuf(struct sockbuf *sb, u_int off, u_int *moff)
+{
+ struct mbuf *m;
+
+ KASSERT(sb->sb_mb != NULL, ("%s: sb_mb is NULL", __func__));
+
+ /*
+ * If the "off" is below the stored offset, which happens on
+ * retransmits, just use "sb_mb":
+ */
+ if (sb->sb_sndptr == NULL || sb->sb_sndptroff > off) {
+ m = sb->sb_mb;
+ } else {
+ m = sb->sb_sndptr;
+ off -= sb->sb_sndptroff;
+ }
+ while (off > 0 && m != NULL) {
+ if (off < m->m_len)
+ break;
+ off -= m->m_len;
+ m = m->m_next;
+ }
+ *moff = off;
+ return (m);
+}
+
+/*
* Drop a record off the front of a sockbuf and move the next record to the
* front.
*/
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index b3b7ed5..976da4e 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -1551,10 +1551,10 @@ kern_linkat(struct thread *td, int fd1, int fd2, char *path1, char *path2,
cap_rights_t rights;
int error;
+again:
bwillwrite();
NDINIT_AT(&nd, LOOKUP, follow | AUDITVNODE1, segflg, path1, fd1, td);
-again:
if ((error = namei(&nd)) != 0)
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
@@ -1563,50 +1563,65 @@ again:
vrele(vp);
return (EPERM); /* POSIX */
}
- if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) {
- vrele(vp);
- return (error);
- }
NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE2,
segflg, path2, fd2, cap_rights_init(&rights, CAP_LINKAT), td);
if ((error = namei(&nd)) == 0) {
if (nd.ni_vp != NULL) {
+ NDFREE(&nd, NDF_ONLY_PNBUF);
if (nd.ni_dvp == nd.ni_vp)
vrele(nd.ni_dvp);
else
vput(nd.ni_dvp);
vrele(nd.ni_vp);
- error = EEXIST;
- } else if ((error = vn_lock(vp, LK_EXCLUSIVE)) == 0) {
+ vrele(vp);
+ return (EEXIST);
+ } else if (nd.ni_dvp->v_mount != vp->v_mount) {
/*
- * Check for cross-device links. No need to
- * recheck vp->v_type, since it cannot change
- * for non-doomed vnode.
+ * Cross-device link. No need to recheck
+ * vp->v_type, since it cannot change, except
+ * to VBAD.
*/
- if (nd.ni_dvp->v_mount != vp->v_mount)
- error = EXDEV;
- else
- error = can_hardlink(vp, td->td_ucred);
- if (error == 0)
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ vput(nd.ni_dvp);
+ vrele(vp);
+ return (EXDEV);
+ } else if ((error = vn_lock(vp, LK_EXCLUSIVE)) == 0) {
+ error = can_hardlink(vp, td->td_ucred);
#ifdef MAC
+ if (error == 0)
error = mac_vnode_check_link(td->td_ucred,
nd.ni_dvp, vp, &nd.ni_cnd);
- if (error == 0)
#endif
- error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
+ if (error != 0) {
+ vput(vp);
+ vput(nd.ni_dvp);
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ return (error);
+ }
+ error = vn_start_write(vp, &mp, V_NOWAIT);
+ if (error != 0) {
+ vput(vp);
+ vput(nd.ni_dvp);
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ error = vn_start_write(NULL, &mp,
+ V_XSLEEP | PCATCH);
+ if (error != 0)
+ return (error);
+ goto again;
+ }
+ error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
VOP_UNLOCK(vp, 0);
vput(nd.ni_dvp);
+ vn_finished_write(mp);
+ NDFREE(&nd, NDF_ONLY_PNBUF);
} else {
vput(nd.ni_dvp);
NDFREE(&nd, NDF_ONLY_PNBUF);
vrele(vp);
- vn_finished_write(mp);
goto again;
}
- NDFREE(&nd, NDF_ONLY_PNBUF);
}
vrele(vp);
- vn_finished_write(mp);
return (error);
}
@@ -3519,6 +3534,7 @@ kern_renameat(struct thread *td, int oldfd, char *old, int newfd, char *new,
cap_rights_t rights;
int error;
+again:
bwillwrite();
#ifdef MAC
NDINIT_ATRIGHTS(&fromnd, DELETE, LOCKPARENT | LOCKLEAF | SAVESTART |
@@ -3539,14 +3555,6 @@ kern_renameat(struct thread *td, int oldfd, char *old, int newfd, char *new,
VOP_UNLOCK(fromnd.ni_vp, 0);
#endif
fvp = fromnd.ni_vp;
- if (error == 0)
- error = vn_start_write(fvp, &mp, V_WAIT | PCATCH);
- if (error != 0) {
- NDFREE(&fromnd, NDF_ONLY_PNBUF);
- vrele(fromnd.ni_dvp);
- vrele(fvp);
- goto out1;
- }
NDINIT_ATRIGHTS(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE |
SAVESTART | AUDITVNODE2, pathseg, new, newfd,
cap_rights_init(&rights, CAP_LINKAT), td);
@@ -3559,11 +3567,30 @@ kern_renameat(struct thread *td, int oldfd, char *old, int newfd, char *new,
NDFREE(&fromnd, NDF_ONLY_PNBUF);
vrele(fromnd.ni_dvp);
vrele(fvp);
- vn_finished_write(mp);
goto out1;
}
tdvp = tond.ni_dvp;
tvp = tond.ni_vp;
+ error = vn_start_write(fvp, &mp, V_NOWAIT);
+ if (error != 0) {
+ NDFREE(&fromnd, NDF_ONLY_PNBUF);
+ NDFREE(&tond, NDF_ONLY_PNBUF);
+ if (tvp != NULL)
+ vput(tvp);
+ if (tdvp == tvp)
+ vrele(tdvp);
+ else
+ vput(tdvp);
+ vrele(fromnd.ni_dvp);
+ vrele(fvp);
+ vrele(tond.ni_startdir);
+ if (fromnd.ni_startdir != NULL)
+ vrele(fromnd.ni_startdir);
+ error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH);
+ if (error != 0)
+ return (error);
+ goto again;
+ }
if (tvp != NULL) {
if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
error = ENOTDIR;
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index 98823f3..617bda0 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -69,6 +69,7 @@ __FBSDID("$FreeBSD$");
#include <sys/conf.h>
#include <sys/syslog.h>
#include <sys/unistd.h>
+#include <sys/user.h>
#include <security/audit/audit.h>
#include <security/mac/mac_framework.h>
@@ -103,6 +104,7 @@ struct fileops vnops = {
.fo_chown = vn_chown,
.fo_sendfile = vn_sendfile,
.fo_seek = vn_seek,
+ .fo_fill_kinfo = vn_fill_kinfo,
.fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE
};
@@ -2249,3 +2251,61 @@ vn_utimes_perm(struct vnode *vp, struct vattr *vap, struct ucred *cred,
error = VOP_ACCESS(vp, VWRITE, cred, td);
return (error);
}
+
+int
+vn_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
+{
+ struct vnode *vp;
+ int error;
+
+ if (fp->f_type == DTYPE_FIFO)
+ kif->kf_type = KF_TYPE_FIFO;
+ else
+ kif->kf_type = KF_TYPE_VNODE;
+ vp = fp->f_vnode;
+ vref(vp);
+ FILEDESC_SUNLOCK(fdp);
+ error = vn_fill_kinfo_vnode(vp, kif);
+ vrele(vp);
+ FILEDESC_SLOCK(fdp);
+ return (error);
+}
+
+int
+vn_fill_kinfo_vnode(struct vnode *vp, struct kinfo_file *kif)
+{
+ struct vattr va;
+ char *fullpath, *freepath;
+ int error;
+
+ kif->kf_vnode_type = vntype_to_kinfo(vp->v_type);
+ freepath = NULL;
+ fullpath = "-";
+ error = vn_fullpath(curthread, vp, &fullpath, &freepath);
+ if (error == 0) {
+ strlcpy(kif->kf_path, fullpath, sizeof(kif->kf_path));
+ }
+ if (freepath != NULL)
+ free(freepath, M_TEMP);
+
+ /*
+ * Retrieve vnode attributes.
+ */
+ va.va_fsid = VNOVAL;
+ va.va_rdev = NODEV;
+ vn_lock(vp, LK_SHARED | LK_RETRY);
+ error = VOP_GETATTR(vp, &va, curthread->td_ucred);
+ VOP_UNLOCK(vp, 0);
+ if (error != 0)
+ return (error);
+ if (va.va_fsid != VNOVAL)
+ kif->kf_un.kf_file.kf_file_fsid = va.va_fsid;
+ else
+ kif->kf_un.kf_file.kf_file_fsid =
+ vp->v_mount->mnt_stat.f_fsid.val[0];
+ kif->kf_un.kf_file.kf_file_fileid = va.va_fileid;
+ kif->kf_un.kf_file.kf_file_mode = MAKEIMODE(va.va_type, va.va_mode);
+ kif->kf_un.kf_file.kf_file_size = va.va_size;
+ kif->kf_un.kf_file.kf_file_rdev = va.va_rdev;
+ return (0);
+}
diff --git a/sys/mips/beri/beri_simplebus.c b/sys/mips/beri/beri_simplebus.c
index 3862a04..87ad3be 100644
--- a/sys/mips/beri/beri_simplebus.c
+++ b/sys/mips/beri/beri_simplebus.c
@@ -198,7 +198,7 @@ simplebus_attach(device_t dev)
continue;
}
- if (fdt_intr_to_rl(dev, dt_child, &di->di_res, di->di_intr_sl)) {
+ if (ofw_bus_intr_to_rl(dev, dt_child, &di->di_res)) {
device_printf(dev, "%s: could not process "
"'interrupts' property\n", di->di_ofw.obd_name);
resource_list_free(&di->di_res);
diff --git a/sys/mips/mips/machdep.c b/sys/mips/mips/machdep.c
index 6e9a4bd..5d25d88 100644
--- a/sys/mips/mips/machdep.c
+++ b/sys/mips/mips/machdep.c
@@ -167,9 +167,6 @@ extern char MipsCache[], MipsCacheEnd[];
extern char MipsWaitStart[], MipsWaitEnd[];
extern char edata[], end[];
-#ifdef DDB
-extern vm_offset_t ksym_start, ksym_end;
-#endif
u_int32_t bootdev;
struct bootinfo bootinfo;
@@ -434,6 +431,8 @@ mips_postboot_fixup(void)
#ifdef DDB
Elf_Size *trampoline_data = (Elf_Size*)kernel_kseg0_end;
Elf_Size symtabsize = 0;
+ vm_offset_t ksym_start;
+ vm_offset_t ksym_end;
if (trampoline_data[0] == SYMTAB_MAGIC) {
symtabsize = trampoline_data[1];
@@ -443,6 +442,7 @@ mips_postboot_fixup(void)
kernel_kseg0_end += symtabsize;
/* end of .strtab */
ksym_end = kernel_kseg0_end;
+ db_fetch_ksymtab(ksym_start, ksym_end);
}
#endif
}
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index 50e4371..58ddecc 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -242,7 +242,7 @@ SUBDIR= \
my \
${_nandfs} \
${_nandsim} \
- ${_ncp} \
+ ${_ncr} \
${_ncv} \
${_ndis} \
netfpga10g \
@@ -537,6 +537,7 @@ _mlx4ib= mlx4ib
_mlxen= mlxen
_mthca= mthca
.endif
+_ncr= ncr
_ncv= ncv
_ndis= ndis
_nsp= nsp
@@ -624,8 +625,6 @@ _iwnfw= iwnfw
.endif
_ixgb= ixgb
_ixgbe= ixgbe
-_ixl= ixl
-_ixlv= ixlv
_mly= mly
_nfe= nfe
_nvd= nvd
diff --git a/sys/modules/fdc/Makefile b/sys/modules/fdc/Makefile
index 43b85f5..40eb427 100644
--- a/sys/modules/fdc/Makefile
+++ b/sys/modules/fdc/Makefile
@@ -2,11 +2,10 @@
KMOD= fdc
+.PATH: ${.CURDIR}/../../dev/fdc
.if ${MACHINE} == "pc98"
-.PATH: ${.CURDIR}/../../pc98/cbus
SRCS= fdc.c fdc_cbus.c
.else
-.PATH: ${.CURDIR}/../../dev/fdc
SRCS= fdc.c fdc_isa.c fdc_pccard.c
.if ${MACHINE} == "i386" || ${MACHINE} == "amd64"
SRCS+= opt_acpi.h acpi_if.h fdc_acpi.c
diff --git a/sys/modules/i2c/controllers/alpm/Makefile b/sys/modules/i2c/controllers/alpm/Makefile
index 885b983..adddfb7 100644
--- a/sys/modules/i2c/controllers/alpm/Makefile
+++ b/sys/modules/i2c/controllers/alpm/Makefile
@@ -1,6 +1,6 @@
# $FreeBSD$
-.PATH: ${.CURDIR}/../../../../pci
+.PATH: ${.CURDIR}/../../../../dev/alpm
KMOD = alpm
SRCS = device_if.h bus_if.h iicbus_if.h smbus_if.h pci_if.h \
alpm.c
diff --git a/sys/modules/i2c/controllers/amdpm/Makefile b/sys/modules/i2c/controllers/amdpm/Makefile
index 5f6d7ed..2f6fcec 100644
--- a/sys/modules/i2c/controllers/amdpm/Makefile
+++ b/sys/modules/i2c/controllers/amdpm/Makefile
@@ -1,6 +1,6 @@
# $FreeBSD$
-.PATH: ${.CURDIR}/../../../../pci
+.PATH: ${.CURDIR}/../../../../dev/amdpm
KMOD = amdpm
SRCS = device_if.h bus_if.h pci_if.h smbus_if.h \
amdpm.c
diff --git a/sys/modules/i2c/controllers/amdsmb/Makefile b/sys/modules/i2c/controllers/amdsmb/Makefile
index d7306ce..43d1122 100644
--- a/sys/modules/i2c/controllers/amdsmb/Makefile
+++ b/sys/modules/i2c/controllers/amdsmb/Makefile
@@ -1,6 +1,6 @@
# $FreeBSD$
-.PATH: ${.CURDIR}/../../../../pci
+.PATH: ${.CURDIR}/../../../../dev/amdsmb
KMOD= amdsmb
SRCS= amdsmb.c
diff --git a/sys/modules/i2c/controllers/intpm/Makefile b/sys/modules/i2c/controllers/intpm/Makefile
index 7cef578..73d5254 100644
--- a/sys/modules/i2c/controllers/intpm/Makefile
+++ b/sys/modules/i2c/controllers/intpm/Makefile
@@ -1,6 +1,6 @@
# $FreeBSD$
-.PATH: ${.CURDIR}/../../../../pci
+.PATH: ${.CURDIR}/../../../../dev/intpm
KMOD = intpm
SRCS = device_if.h bus_if.h iicbus_if.h smbus_if.h pci_if.h \
opt_intpm.h intpmreg.h intpm.c
diff --git a/sys/modules/i2c/controllers/nfsmb/Makefile b/sys/modules/i2c/controllers/nfsmb/Makefile
index 21b67f3..bb2a0f2 100644
--- a/sys/modules/i2c/controllers/nfsmb/Makefile
+++ b/sys/modules/i2c/controllers/nfsmb/Makefile
@@ -1,6 +1,6 @@
# $FreeBSD$
-.PATH: ${.CURDIR}/../../../../pci
+.PATH: ${.CURDIR}/../../../../dev/nfsmb
KMOD= nfsmb
SRCS= nfsmb.c
diff --git a/sys/modules/i2c/controllers/viapm/Makefile b/sys/modules/i2c/controllers/viapm/Makefile
index 3710030..f08b053 100644
--- a/sys/modules/i2c/controllers/viapm/Makefile
+++ b/sys/modules/i2c/controllers/viapm/Makefile
@@ -1,6 +1,6 @@
# $FreeBSD$
-.PATH: ${.CURDIR}/../../../../pci
+.PATH: ${.CURDIR}/../../../../dev/viapm
KMOD = viapm
SRCS = device_if.h bus_if.h iicbb_if.h isa_if.h pci_if.h smbus_if.h \
opt_isa.h viapm.c
diff --git a/sys/modules/mlx4/Makefile b/sys/modules/mlx4/Makefile
index dec1ba9..1087123 100644
--- a/sys/modules/mlx4/Makefile
+++ b/sys/modules/mlx4/Makefile
@@ -2,7 +2,7 @@
.PATH: ${.CURDIR}/../../ofed/drivers/net/mlx4
.PATH: ${.CURDIR}/../../ofed/include/linux
KMOD = mlx4
-SRCS = device_if.h bus_if.h pci_if.h vnode_if.h
+SRCS = device_if.h bus_if.h pci_if.h vnode_if.h opt_inet.h opt_inet6.h
SRCS+= alloc.c catas.c cmd.c cq.c eq.c fw.c icm.c intf.c main.c mcg.c mr.c linux_compat.c linux_radix.c linux_idr.c
SRCS+= pd.c port.c profile.c qp.c reset.c sense.c srq.c resource_tracker.c sys_tune.c
diff --git a/sys/modules/mlxen/Makefile b/sys/modules/mlxen/Makefile
index 4e1415d..258cf7e 100644
--- a/sys/modules/mlxen/Makefile
+++ b/sys/modules/mlxen/Makefile
@@ -3,8 +3,8 @@
KMOD = mlxen
SRCS = device_if.h bus_if.h pci_if.h vnode_if.h
-SRCS += en_cq.c en_frag.c en_main.c en_netdev.c en_port.c en_resources.c
-SRCS += en_rx.c en_tx.c
+SRCS += en_cq.c en_main.c en_netdev.c en_port.c en_resources.c
+SRCS += en_rx.c en_tx.c utils.c
SRCS += opt_inet.h opt_inet6.h
CFLAGS+= -I${.CURDIR}/../../ofed/drivers/net/mlx4
CFLAGS+= -I${.CURDIR}/../../ofed/include/
diff --git a/sys/modules/ncr/Makefile b/sys/modules/ncr/Makefile
new file mode 100644
index 0000000..52fd88e
--- /dev/null
+++ b/sys/modules/ncr/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../dev/ncr
+
+KMOD= ncr
+SRCS= ncr.c
+SRCS+= device_if.h bus_if.h pci_if.h opt_ncr.h opt_cam.h
+
+.include <bsd.kmod.mk>
+
+CFLAGS+=-Wno-error=unused-const-variable
diff --git a/sys/modules/netmap/Makefile b/sys/modules/netmap/Makefile
index 647cd10..8e5364b 100644
--- a/sys/modules/netmap/Makefile
+++ b/sys/modules/netmap/Makefile
@@ -16,5 +16,6 @@ SRCS += netmap_vale.c
SRCS += netmap_freebsd.c
SRCS += netmap_offloadings.c
SRCS += netmap_pipe.c
+SRCS += netmap_monitor.c
.include <bsd.kmod.mk>
diff --git a/sys/net/ieee8023ad_lacp.c b/sys/net/ieee8023ad_lacp.c
index 12cc721..90ed6e0 100644
--- a/sys/net/ieee8023ad_lacp.c
+++ b/sys/net/ieee8023ad_lacp.c
@@ -300,7 +300,7 @@ lacp_pdu_input(struct lacp_port *lp, struct mbuf *m)
goto bad;
}
- if (lacp_debug > 0) {
+ if (lacp_debug > 0) {
lacp_dprintf(lp, "lacpdu receive\n");
lacp_dump_lacpdu(du);
}
@@ -528,7 +528,8 @@ lacp_port_create(struct lagg_port *lgp)
LLADDR(&sdl), ETHER_ADDR_LEN);
error = if_addmulti(ifp, (struct sockaddr *)&sdl, &rifma);
if (error) {
- printf("%s: ADDMULTI failed on %s\n", __func__, lgp->lp_ifname);
+ printf("%s: ADDMULTI failed on %s\n", __func__,
+ lgp->lp_ifp->if_xname);
return (error);
}
@@ -538,7 +539,7 @@ lacp_port_create(struct lagg_port *lgp)
return (ENOMEM);
LACP_LOCK(lsc);
- lgp->lp_psc = (caddr_t)lp;
+ lgp->lp_psc = lp;
lp->lp_ifp = ifp;
lp->lp_lagg = lgp;
lp->lp_lsc = lsc;
@@ -585,7 +586,7 @@ lacp_port_destroy(struct lagg_port *lgp)
}
void
-lacp_req(struct lagg_softc *sc, caddr_t data)
+lacp_req(struct lagg_softc *sc, void *data)
{
struct lacp_opreq *req = (struct lacp_opreq *)data;
struct lacp_softc *lsc = LACP_SOFTC(sc);
@@ -593,7 +594,7 @@ lacp_req(struct lagg_softc *sc, caddr_t data)
bzero(req, sizeof(struct lacp_opreq));
- /*
+ /*
* If the LACP softc is NULL, return with the opreq structure full of
* zeros. It is normal for the softc to be NULL while the lagg is
* being destroyed.
@@ -624,7 +625,7 @@ lacp_req(struct lagg_softc *sc, caddr_t data)
}
void
-lacp_portreq(struct lagg_port *lgp, caddr_t data)
+lacp_portreq(struct lagg_port *lgp, void *data)
{
struct lacp_opreq *req = (struct lacp_opreq *)data;
struct lacp_port *lp = LACP_PORT(lgp);
@@ -783,18 +784,15 @@ lacp_attach_sysctl_debug(struct lacp_softc *lsc, struct sysctl_oid *p_oid)
"Bitmap of if_dunit entries to drop TX frames for");
}
-int
+void
lacp_attach(struct lagg_softc *sc)
{
struct lacp_softc *lsc;
struct sysctl_oid *oid;
- lsc = malloc(sizeof(struct lacp_softc),
- M_DEVBUF, M_NOWAIT|M_ZERO);
- if (lsc == NULL)
- return (ENOMEM);
+ lsc = malloc(sizeof(struct lacp_softc), M_DEVBUF, M_WAITOK | M_ZERO);
- sc->sc_psc = (caddr_t)lsc;
+ sc->sc_psc = lsc;
lsc->lsc_softc = sc;
lsc->lsc_hashkey = arc4random();
@@ -818,27 +816,23 @@ lacp_attach(struct lagg_softc *sc)
/* if the lagg is already up then do the same */
if (sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING)
lacp_init(sc);
-
- return (0);
}
-int
-lacp_detach(struct lagg_softc *sc)
+void
+lacp_detach(void *psc)
{
- struct lacp_softc *lsc = LACP_SOFTC(sc);
+ struct lacp_softc *lsc = (struct lacp_softc *)psc;
KASSERT(TAILQ_EMPTY(&lsc->lsc_aggregators),
("aggregators still active"));
KASSERT(lsc->lsc_active_aggregator == NULL,
("aggregator still attached"));
- sc->sc_psc = NULL;
callout_drain(&lsc->lsc_transit_callout);
callout_drain(&lsc->lsc_callout);
LACP_LOCK_DESTROY(lsc);
free(lsc, M_DEVBUF);
- return (0);
}
void
@@ -993,13 +987,13 @@ lacp_select_active_aggregator(struct lacp_softc *lsc)
lacp_format_lagid_aggregator(la, buf, sizeof(buf)),
speed, la->la_nports));
- /* This aggregator is chosen if
- * the partner has a better system priority
- * or, the total aggregated speed is higher
- * or, it is already the chosen aggregator
+ /*
+ * This aggregator is chosen if the partner has a better
+ * system priority or, the total aggregated speed is higher
+ * or, it is already the chosen aggregator
*/
if ((best_la != NULL && LACP_SYS_PRI(la->la_partner) <
- LACP_SYS_PRI(best_la->la_partner)) ||
+ LACP_SYS_PRI(best_la->la_partner)) ||
speed > best_speed ||
(speed == best_speed &&
la == lsc->lsc_active_aggregator)) {
diff --git a/sys/net/ieee8023ad_lacp.h b/sys/net/ieee8023ad_lacp.h
index ca5f76e..535cf1f 100644
--- a/sys/net/ieee8023ad_lacp.h
+++ b/sys/net/ieee8023ad_lacp.h
@@ -282,15 +282,15 @@ struct lacp_softc {
struct mbuf *lacp_input(struct lagg_port *, struct mbuf *);
struct lagg_port *lacp_select_tx_port(struct lagg_softc *, struct mbuf *);
-int lacp_attach(struct lagg_softc *);
-int lacp_detach(struct lagg_softc *);
+void lacp_attach(struct lagg_softc *);
+void lacp_detach(void *);
void lacp_init(struct lagg_softc *);
void lacp_stop(struct lagg_softc *);
int lacp_port_create(struct lagg_port *);
void lacp_port_destroy(struct lagg_port *);
void lacp_linkstate(struct lagg_port *);
-void lacp_req(struct lagg_softc *, caddr_t);
-void lacp_portreq(struct lagg_port *, caddr_t);
+void lacp_req(struct lagg_softc *, void *);
+void lacp_portreq(struct lagg_port *, void *);
static __inline int
lacp_isactive(struct lagg_port *lgp)
diff --git a/sys/net/if.c b/sys/net/if.c
index 1b41b7e..831dc3f 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -584,6 +584,57 @@ if_attach(struct ifnet *ifp)
if_attach_internal(ifp, 0);
}
+/*
+ * Compute the least common TSO limit.
+ */
+void
+if_hw_tsomax_common(if_t ifp, struct ifnet_hw_tsomax *pmax)
+{
+ /*
+ * 1) If there is no limit currently, take the limit from
+ * the network adapter.
+ *
+ * 2) If the network adapter has a limit below the current
+ * limit, apply it.
+ */
+ if (pmax->tsomaxbytes == 0 || (ifp->if_hw_tsomax != 0 &&
+ ifp->if_hw_tsomax < pmax->tsomaxbytes)) {
+ pmax->tsomaxbytes = ifp->if_hw_tsomax;
+ }
+ if (pmax->tsomaxsegcount == 0 || (ifp->if_hw_tsomaxsegcount != 0 &&
+ ifp->if_hw_tsomaxsegcount < pmax->tsomaxsegcount)) {
+ pmax->tsomaxsegcount = ifp->if_hw_tsomaxsegcount;
+ }
+ if (pmax->tsomaxsegsize == 0 || (ifp->if_hw_tsomaxsegsize != 0 &&
+ ifp->if_hw_tsomaxsegsize < pmax->tsomaxsegsize)) {
+ pmax->tsomaxsegsize = ifp->if_hw_tsomaxsegsize;
+ }
+}
+
+/*
+ * Update TSO limit of a network adapter.
+ *
+ * Returns zero if no change. Else non-zero.
+ */
+int
+if_hw_tsomax_update(if_t ifp, struct ifnet_hw_tsomax *pmax)
+{
+ int retval = 0;
+ if (ifp->if_hw_tsomax != pmax->tsomaxbytes) {
+ ifp->if_hw_tsomax = pmax->tsomaxbytes;
+ retval++;
+ }
+ if (ifp->if_hw_tsomaxsegsize != pmax->tsomaxsegsize) {
+ ifp->if_hw_tsomaxsegsize = pmax->tsomaxsegsize;
+ retval++;
+ }
+ if (ifp->if_hw_tsomaxsegcount != pmax->tsomaxsegcount) {
+ ifp->if_hw_tsomaxsegcount = pmax->tsomaxsegcount;
+ retval++;
+ }
+ return (retval);
+}
+
static void
if_attach_internal(struct ifnet *ifp, int vmove)
{
@@ -659,13 +710,36 @@ if_attach_internal(struct ifnet *ifp, int vmove)
ifp->if_broadcastaddr = NULL;
#if defined(INET) || defined(INET6)
- /* Initialize to max value. */
- if (ifp->if_hw_tsomax == 0)
- ifp->if_hw_tsomax = min(IP_MAXPACKET, 32 * MCLBYTES -
+ /* Use defaults for TSO, if nothing is set */
+ if (ifp->if_hw_tsomax == 0 &&
+ ifp->if_hw_tsomaxsegcount == 0 &&
+ ifp->if_hw_tsomaxsegsize == 0) {
+ /*
+ * The TSO defaults needs to be such that an
+ * NFS mbuf list of 35 mbufs totalling just
+ * below 64K works and that a chain of mbufs
+ * can be defragged into at most 32 segments:
+ */
+ ifp->if_hw_tsomax = min(IP_MAXPACKET, (32 * MCLBYTES) -
(ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN));
- KASSERT(ifp->if_hw_tsomax <= IP_MAXPACKET &&
- ifp->if_hw_tsomax >= IP_MAXPACKET / 8,
- ("%s: tsomax outside of range", __func__));
+ ifp->if_hw_tsomaxsegcount = 35;
+ ifp->if_hw_tsomaxsegsize = 2048; /* 2K */
+
+ /* XXX some drivers set IFCAP_TSO after ethernet attach */
+ if (ifp->if_capabilities & IFCAP_TSO) {
+ if_printf(ifp, "Using defaults for TSO: %u/%u/%u\n",
+ ifp->if_hw_tsomax,
+ ifp->if_hw_tsomaxsegcount,
+ ifp->if_hw_tsomaxsegsize);
+ }
+ }
+ /*
+ * If the "if_hw_tsomax" limit is set, check if it is
+ * too small:
+ */
+ KASSERT(ifp->if_hw_tsomax == 0 ||
+ ifp->if_hw_tsomax >= (IP_MAXPACKET / 8),
+ ("%s: if_hw_tsomax is outside of range", __func__));
#endif
}
#ifdef VIMAGE
diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c
index 7071fef..f4cc3d8 100644
--- a/sys/net/if_gif.c
+++ b/sys/net/if_gif.c
@@ -92,13 +92,20 @@
static const char gifname[] = "gif";
/*
- * gif_mtx protects the global gif_softc_list.
+ * gif_mtx protects a per-vnet gif_softc_list.
*/
-static struct mtx gif_mtx;
+static VNET_DEFINE(struct mtx, gif_mtx);
+#define V_gif_mtx VNET(gif_mtx)
static MALLOC_DEFINE(M_GIF, "gif", "Generic Tunnel Interface");
static VNET_DEFINE(LIST_HEAD(, gif_softc), gif_softc_list);
#define V_gif_softc_list VNET(gif_softc_list)
+#define GIF_LIST_LOCK_INIT(x) mtx_init(&V_gif_mtx, "gif_mtx", \
+ NULL, MTX_DEF)
+#define GIF_LIST_LOCK_DESTROY(x) mtx_destroy(&V_gif_mtx)
+#define GIF_LIST_LOCK(x) mtx_lock(&V_gif_mtx)
+#define GIF_LIST_UNLOCK(x) mtx_unlock(&V_gif_mtx)
+
void (*ng_gif_input_p)(struct ifnet *ifp, struct mbuf **mp, int af);
void (*ng_gif_input_orphan_p)(struct ifnet *ifp, struct mbuf *m, int af);
void (*ng_gif_attach_p)(struct ifnet *ifp);
@@ -107,7 +114,8 @@ void (*ng_gif_detach_p)(struct ifnet *ifp);
static void gif_start(struct ifnet *);
static int gif_clone_create(struct if_clone *, int, caddr_t);
static void gif_clone_destroy(struct ifnet *);
-static struct if_clone *gif_cloner;
+static VNET_DEFINE(struct if_clone *, gif_cloner);
+#define V_gif_cloner VNET(gif_cloner)
static int gifmodevent(module_t, int, void *);
@@ -189,9 +197,9 @@ gif_clone_create(struct if_clone *ifc, int unit, caddr_t params)
if (ng_gif_attach_p != NULL)
(*ng_gif_attach_p)(GIF2IFP(sc));
- mtx_lock(&gif_mtx);
+ GIF_LIST_LOCK();
LIST_INSERT_HEAD(&V_gif_softc_list, sc, gif_list);
- mtx_unlock(&gif_mtx);
+ GIF_LIST_UNLOCK();
return (0);
}
@@ -204,9 +212,9 @@ gif_clone_destroy(struct ifnet *ifp)
#endif
struct gif_softc *sc = ifp->if_softc;
- mtx_lock(&gif_mtx);
+ GIF_LIST_LOCK();
LIST_REMOVE(sc, gif_list);
- mtx_unlock(&gif_mtx);
+ GIF_LIST_UNLOCK();
gif_delete_tunnel(ifp);
#ifdef INET6
@@ -238,9 +246,22 @@ vnet_gif_init(const void *unused __unused)
{
LIST_INIT(&V_gif_softc_list);
+ GIF_LIST_LOCK_INIT();
+ V_gif_cloner = if_clone_simple(gifname, gif_clone_create,
+ gif_clone_destroy, 0);
+}
+VNET_SYSINIT(vnet_gif_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
+ vnet_gif_init, NULL);
+
+static void
+vnet_gif_uninit(const void *unused __unused)
+{
+
+ if_clone_detach(V_gif_cloner);
+ GIF_LIST_LOCK_DESTROY();
}
-VNET_SYSINIT(vnet_gif_init, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, vnet_gif_init,
- NULL);
+VNET_SYSUNINIT(vnet_gif_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
+ vnet_gif_uninit, NULL);
static int
gifmodevent(module_t mod, int type, void *data)
@@ -248,19 +269,12 @@ gifmodevent(module_t mod, int type, void *data)
switch (type) {
case MOD_LOAD:
- mtx_init(&gif_mtx, "gif_mtx", NULL, MTX_DEF);
- gif_cloner = if_clone_simple(gifname, gif_clone_create,
- gif_clone_destroy, 0);
- break;
-
case MOD_UNLOAD:
- if_clone_detach(gif_cloner);
- mtx_destroy(&gif_mtx);
break;
default:
- return EOPNOTSUPP;
+ return (EOPNOTSUPP);
}
- return 0;
+ return (0);
}
static moduledata_t gif_mod = {
@@ -364,7 +378,7 @@ gif_start(struct ifnet *ifp)
#endif
#ifdef INET6
if (sc->gif_psrc->sa_family == AF_INET6)
- m->m_pkthdr.len -= GIF_HDR_LEN6;
+ m->m_pkthdr.len -= GIF_HDR_LEN6;
#endif
#endif
/*
@@ -373,6 +387,7 @@ gif_start(struct ifnet *ifp)
*/
af = m->m_pkthdr.csum_data;
+ /* override to IPPROTO_ETHERIP for bridged traffic */
if (ifp->if_bridge)
af = AF_LINK;
@@ -381,7 +396,6 @@ gif_start(struct ifnet *ifp)
/* Done by IFQ_HANDOFF */
/* if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len);*/
- /* override to IPPROTO_ETHERIP for bridged traffic */
M_SETFIB(m, sc->gif_fibnum);
/* inner AF-specific encapsulation */
@@ -904,7 +918,7 @@ gif_set_tunnel(struct ifnet *ifp, struct sockaddr *src, struct sockaddr *dst)
struct sockaddr *osrc, *odst, *sa;
int error = 0;
- mtx_lock(&gif_mtx);
+ GIF_LIST_LOCK();
LIST_FOREACH(sc2, &V_gif_softc_list, gif_list) {
if (sc2 == sc)
continue;
@@ -924,13 +938,13 @@ gif_set_tunnel(struct ifnet *ifp, struct sockaddr *src, struct sockaddr *dst)
bcmp(sc2->gif_pdst, dst, dst->sa_len) == 0 &&
bcmp(sc2->gif_psrc, src, src->sa_len) == 0) {
error = EADDRNOTAVAIL;
- mtx_unlock(&gif_mtx);
+ GIF_LIST_UNLOCK();
goto bad;
}
/* XXX both end must be valid? (I mean, not 0.0.0.0) */
}
- mtx_unlock(&gif_mtx);
+ GIF_LIST_UNLOCK();
/* XXX we can detach from both, but be polite just in case */
if (sc->gif_psrc)
diff --git a/sys/net/if_gre.c b/sys/net/if_gre.c
index 65b3029..8954f5c 100644
--- a/sys/net/if_gre.c
+++ b/sys/net/if_gre.c
@@ -102,15 +102,16 @@ struct mtag_gre_nesting {
* gre_mtx protects all global variables in if_gre.c.
* XXX: gre_softc data not protected yet.
*/
-struct mtx gre_mtx;
+VNET_DEFINE(struct mtx, gre_mtx);
+VNET_DEFINE(struct gre_softc_head, gre_softc_list);
+
static const char grename[] = "gre";
static MALLOC_DEFINE(M_GRE, grename, "Generic Routing Encapsulation");
-struct gre_softc_head gre_softc_list;
-
static int gre_clone_create(struct if_clone *, int, caddr_t);
static void gre_clone_destroy(struct ifnet *);
-static struct if_clone *gre_cloner;
+static VNET_DEFINE(struct if_clone *, gre_cloner);
+#define V_gre_cloner VNET(gre_cloner)
static int gre_ioctl(struct ifnet *, u_long, caddr_t);
static int gre_output(struct ifnet *, struct mbuf *,
@@ -118,8 +119,6 @@ static int gre_output(struct ifnet *, struct mbuf *,
static int gre_compute_route(struct gre_softc *sc);
-static void greattach(void);
-
#ifdef INET
extern struct domain inetdomain;
static const struct protosw in_gre_protosw = {
@@ -160,26 +159,34 @@ static SYSCTL_NODE(_net_link, IFT_TUNNEL, gre, CTLFLAG_RW, 0,
*/
#define MAX_GRE_NEST 1
#endif
-static int max_gre_nesting = MAX_GRE_NEST;
-SYSCTL_INT(_net_link_gre, OID_AUTO, max_nesting, CTLFLAG_RW,
- &max_gre_nesting, 0, "Max nested tunnels");
+static VNET_DEFINE(int, max_gre_nesting) = MAX_GRE_NEST;
+#define V_max_gre_nesting VNET(max_gre_nesting)
+SYSCTL_INT(_net_link_gre, OID_AUTO, max_nesting, CTLFLAG_RW | CTLFLAG_VNET,
+ &VNET_NAME(max_gre_nesting), 0, "Max nested tunnels");
-/* ARGSUSED */
static void
-greattach(void)
+vnet_gre_init(const void *unused __unused)
{
-
- mtx_init(&gre_mtx, "gre_mtx", NULL, MTX_DEF);
- LIST_INIT(&gre_softc_list);
- gre_cloner = if_clone_simple(grename, gre_clone_create,
+ LIST_INIT(&V_gre_softc_list);
+ GRE_LIST_LOCK_INIT();
+ V_gre_cloner = if_clone_simple(grename, gre_clone_create,
gre_clone_destroy, 0);
}
+VNET_SYSINIT(vnet_gre_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
+ vnet_gre_init, NULL);
+
+static void
+vnet_gre_uninit(const void *unused __unused)
+{
+
+ if_clone_detach(V_gre_cloner);
+ GRE_LIST_LOCK_DESTROY();
+}
+VNET_SYSUNINIT(vnet_gre_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
+ vnet_gre_uninit, NULL);
static int
-gre_clone_create(ifc, unit, params)
- struct if_clone *ifc;
- int unit;
- caddr_t params;
+gre_clone_create(struct if_clone *ifc, int unit, caddr_t params)
{
struct gre_softc *sc;
@@ -210,21 +217,20 @@ gre_clone_create(ifc, unit, params)
sc->key = 0;
if_attach(GRE2IFP(sc));
bpfattach(GRE2IFP(sc), DLT_NULL, sizeof(u_int32_t));
- mtx_lock(&gre_mtx);
- LIST_INSERT_HEAD(&gre_softc_list, sc, sc_list);
- mtx_unlock(&gre_mtx);
+ GRE_LIST_LOCK();
+ LIST_INSERT_HEAD(&V_gre_softc_list, sc, sc_list);
+ GRE_LIST_UNLOCK();
return (0);
}
static void
-gre_clone_destroy(ifp)
- struct ifnet *ifp;
+gre_clone_destroy(struct ifnet *ifp)
{
struct gre_softc *sc = ifp->if_softc;
- mtx_lock(&gre_mtx);
+ GRE_LIST_LOCK();
LIST_REMOVE(sc, sc_list);
- mtx_unlock(&gre_mtx);
+ GRE_LIST_UNLOCK();
#ifdef INET
if (sc->encap != NULL)
@@ -269,7 +275,7 @@ gre_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
gt = (struct mtag_gre_nesting *)(mtag + 1);
gt->count++;
- if (gt->count > min(gt->max,max_gre_nesting)) {
+ if (gt->count > min(gt->max, V_max_gre_nesting)) {
printf("%s: hit maximum recursion limit %u on %s\n",
__func__, gt->count - 1, ifp->if_xname);
m_freem(m);
@@ -301,7 +307,7 @@ gre_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
* Note: the sysctl does not actually check for saneness, so we
* limit the maximum numbers of possible recursions here.
*/
- max = imin(max_gre_nesting, 256);
+ max = imin(V_max_gre_nesting, 256);
/* If someone sets the sysctl <= 0, we want at least 1. */
max = imax(max, 1);
len = sizeof(struct mtag_gre_nesting) +
@@ -909,16 +915,12 @@ gremodevent(module_t mod, int type, void *data)
switch (type) {
case MOD_LOAD:
- greattach();
- break;
case MOD_UNLOAD:
- if_clone_detach(gre_cloner);
- mtx_destroy(&gre_mtx);
break;
default:
- return EOPNOTSUPP;
+ return (EOPNOTSUPP);
}
- return 0;
+ return (0);
}
static moduledata_t gre_mod = {
diff --git a/sys/net/if_gre.h b/sys/net/if_gre.h
index 74d16b1..cb2a44b 100644
--- a/sys/net/if_gre.h
+++ b/sys/net/if_gre.h
@@ -176,8 +176,16 @@ struct mobip_h {
#ifdef _KERNEL
LIST_HEAD(gre_softc_head, gre_softc);
-extern struct mtx gre_mtx;
-extern struct gre_softc_head gre_softc_list;
+VNET_DECLARE(struct gre_softc_head, gre_softc_list);
+#define V_gre_softc_list VNET(gre_softc_list)
+
+VNET_DECLARE(struct mtx, gre_mtx);
+#define V_gre_mtx VNET(gre_mtx)
+#define GRE_LIST_LOCK_INIT(x) mtx_init(&V_gre_mtx, "gre_mtx", NULL, \
+ MTX_DEF)
+#define GRE_LIST_LOCK_DESTROY(x) mtx_destroy(&V_gre_mtx)
+#define GRE_LIST_LOCK(x) mtx_lock(&V_gre_mtx)
+#define GRE_LIST_UNLOCK(x) mtx_unlock(&V_gre_mtx)
u_int16_t gre_in_cksum(u_int16_t *, u_int);
#endif /* _KERNEL */
diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c
index 418ccd5..a6e27ae 100644
--- a/sys/net/if_lagg.c
+++ b/sys/net/if_lagg.c
@@ -125,22 +125,19 @@ static const void *lagg_gethdr(struct mbuf *, u_int, u_int, void *);
static int lagg_sysctl_active(SYSCTL_HANDLER_ARGS);
/* Simple round robin */
-static int lagg_rr_attach(struct lagg_softc *);
-static int lagg_rr_detach(struct lagg_softc *);
+static void lagg_rr_attach(struct lagg_softc *);
static int lagg_rr_start(struct lagg_softc *, struct mbuf *);
static struct mbuf *lagg_rr_input(struct lagg_softc *, struct lagg_port *,
struct mbuf *);
/* Active failover */
-static int lagg_fail_attach(struct lagg_softc *);
-static int lagg_fail_detach(struct lagg_softc *);
static int lagg_fail_start(struct lagg_softc *, struct mbuf *);
static struct mbuf *lagg_fail_input(struct lagg_softc *, struct lagg_port *,
struct mbuf *);
/* Loadbalancing */
-static int lagg_lb_attach(struct lagg_softc *);
-static int lagg_lb_detach(struct lagg_softc *);
+static void lagg_lb_attach(struct lagg_softc *);
+static void lagg_lb_detach(struct lagg_softc *);
static int lagg_lb_port_create(struct lagg_port *);
static void lagg_lb_port_destroy(struct lagg_port *);
static int lagg_lb_start(struct lagg_softc *, struct mbuf *);
@@ -149,15 +146,13 @@ static struct mbuf *lagg_lb_input(struct lagg_softc *, struct lagg_port *,
static int lagg_lb_porttable(struct lagg_softc *, struct lagg_port *);
/* Broadcast */
-static int lagg_bcast_attach(struct lagg_softc *);
-static int lagg_bcast_detach(struct lagg_softc *);
static int lagg_bcast_start(struct lagg_softc *, struct mbuf *);
static struct mbuf *lagg_bcast_input(struct lagg_softc *, struct lagg_port *,
- struct mbuf *);
+ struct mbuf *);
/* 802.3ad LACP */
-static int lagg_lacp_attach(struct lagg_softc *);
-static int lagg_lacp_detach(struct lagg_softc *);
+static void lagg_lacp_attach(struct lagg_softc *);
+static void lagg_lacp_detach(struct lagg_softc *);
static int lagg_lacp_start(struct lagg_softc *, struct mbuf *);
static struct mbuf *lagg_lacp_input(struct lagg_softc *, struct lagg_port *,
struct mbuf *);
@@ -166,17 +161,72 @@ static void lagg_lacp_lladdr(struct lagg_softc *);
static void lagg_callout(void *);
/* lagg protocol table */
-static const struct {
- int ti_proto;
- int (*ti_attach)(struct lagg_softc *);
+static const struct lagg_proto {
+ lagg_proto pr_num;
+ void (*pr_attach)(struct lagg_softc *);
+ void (*pr_detach)(struct lagg_softc *);
+ int (*pr_start)(struct lagg_softc *, struct mbuf *);
+ struct mbuf * (*pr_input)(struct lagg_softc *, struct lagg_port *,
+ struct mbuf *);
+ int (*pr_addport)(struct lagg_port *);
+ void (*pr_delport)(struct lagg_port *);
+ void (*pr_linkstate)(struct lagg_port *);
+ void (*pr_init)(struct lagg_softc *);
+ void (*pr_stop)(struct lagg_softc *);
+ void (*pr_lladdr)(struct lagg_softc *);
+ void (*pr_request)(struct lagg_softc *, void *);
+ void (*pr_portreq)(struct lagg_port *, void *);
} lagg_protos[] = {
- { LAGG_PROTO_ROUNDROBIN, lagg_rr_attach },
- { LAGG_PROTO_FAILOVER, lagg_fail_attach },
- { LAGG_PROTO_LOADBALANCE, lagg_lb_attach },
- { LAGG_PROTO_ETHERCHANNEL, lagg_lb_attach },
- { LAGG_PROTO_LACP, lagg_lacp_attach },
- { LAGG_PROTO_BROADCAST, lagg_bcast_attach },
- { LAGG_PROTO_NONE, NULL }
+ {
+ .pr_num = LAGG_PROTO_NONE
+ },
+ {
+ .pr_num = LAGG_PROTO_ROUNDROBIN,
+ .pr_attach = lagg_rr_attach,
+ .pr_start = lagg_rr_start,
+ .pr_input = lagg_rr_input,
+ },
+ {
+ .pr_num = LAGG_PROTO_FAILOVER,
+ .pr_start = lagg_fail_start,
+ .pr_input = lagg_fail_input,
+ },
+ {
+ .pr_num = LAGG_PROTO_LOADBALANCE,
+ .pr_attach = lagg_lb_attach,
+ .pr_detach = lagg_lb_detach,
+ .pr_start = lagg_lb_start,
+ .pr_input = lagg_lb_input,
+ .pr_addport = lagg_lb_port_create,
+ .pr_delport = lagg_lb_port_destroy,
+ },
+ {
+ .pr_num = LAGG_PROTO_LACP,
+ .pr_attach = lagg_lacp_attach,
+ .pr_detach = lagg_lacp_detach,
+ .pr_start = lagg_lacp_start,
+ .pr_input = lagg_lacp_input,
+ .pr_addport = lacp_port_create,
+ .pr_delport = lacp_port_destroy,
+ .pr_linkstate = lacp_linkstate,
+ .pr_init = lacp_init,
+ .pr_stop = lacp_stop,
+ .pr_lladdr = lagg_lacp_lladdr,
+ .pr_request = lacp_req,
+ .pr_portreq = lacp_portreq,
+ },
+ {
+ .pr_num = LAGG_PROTO_ETHERCHANNEL,
+ .pr_attach = lagg_lb_attach,
+ .pr_detach = lagg_lb_detach,
+ .pr_start = lagg_lb_start,
+ .pr_input = lagg_lb_input,
+ },
+ {
+ .pr_num = LAGG_PROTO_BROADCAST,
+ .pr_start = lagg_bcast_start,
+ .pr_input = lagg_bcast_input,
+ },
};
SYSCTL_DECL(_net_link);
@@ -235,6 +285,117 @@ static moduledata_t lagg_mod = {
DECLARE_MODULE(if_lagg, lagg_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
MODULE_VERSION(if_lagg, 1);
+static void
+lagg_proto_attach(struct lagg_softc *sc, lagg_proto pr)
+{
+
+ KASSERT(sc->sc_proto == LAGG_PROTO_NONE, ("%s: sc %p has proto",
+ __func__, sc));
+
+ if (sc->sc_ifflags & IFF_DEBUG)
+ if_printf(sc->sc_ifp, "using proto %u\n", pr);
+
+ if (lagg_protos[pr].pr_attach != NULL)
+ lagg_protos[pr].pr_attach(sc);
+ sc->sc_proto = pr;
+}
+
+static void
+lagg_proto_detach(struct lagg_softc *sc)
+{
+ lagg_proto pr;
+
+ LAGG_WLOCK_ASSERT(sc);
+
+ pr = sc->sc_proto;
+ sc->sc_proto = LAGG_PROTO_NONE;
+
+ if (lagg_protos[pr].pr_detach != NULL)
+ lagg_protos[pr].pr_detach(sc);
+ else
+ LAGG_WUNLOCK(sc);
+}
+
+static int
+lagg_proto_start(struct lagg_softc *sc, struct mbuf *m)
+{
+
+ return (lagg_protos[sc->sc_proto].pr_start(sc, m));
+}
+
+static struct mbuf *
+lagg_proto_input(struct lagg_softc *sc, struct lagg_port *lp, struct mbuf *m)
+{
+
+ return (lagg_protos[sc->sc_proto].pr_input(sc, lp, m));
+}
+
+static int
+lagg_proto_addport(struct lagg_softc *sc, struct lagg_port *lp)
+{
+
+ if (lagg_protos[sc->sc_proto].pr_addport == NULL)
+ return (0);
+ else
+ return (lagg_protos[sc->sc_proto].pr_addport(lp));
+}
+
+static void
+lagg_proto_delport(struct lagg_softc *sc, struct lagg_port *lp)
+{
+
+ if (lagg_protos[sc->sc_proto].pr_delport != NULL)
+ lagg_protos[sc->sc_proto].pr_delport(lp);
+}
+
+static void
+lagg_proto_linkstate(struct lagg_softc *sc, struct lagg_port *lp)
+{
+
+ if (lagg_protos[sc->sc_proto].pr_linkstate != NULL)
+ lagg_protos[sc->sc_proto].pr_linkstate(lp);
+}
+
+static void
+lagg_proto_init(struct lagg_softc *sc)
+{
+
+ if (lagg_protos[sc->sc_proto].pr_init != NULL)
+ lagg_protos[sc->sc_proto].pr_init(sc);
+}
+
+static void
+lagg_proto_stop(struct lagg_softc *sc)
+{
+
+ if (lagg_protos[sc->sc_proto].pr_stop != NULL)
+ lagg_protos[sc->sc_proto].pr_stop(sc);
+}
+
+static void
+lagg_proto_lladdr(struct lagg_softc *sc)
+{
+
+ if (lagg_protos[sc->sc_proto].pr_lladdr != NULL)
+ lagg_protos[sc->sc_proto].pr_lladdr(sc);
+}
+
+static void
+lagg_proto_request(struct lagg_softc *sc, void *v)
+{
+
+ if (lagg_protos[sc->sc_proto].pr_request != NULL)
+ lagg_protos[sc->sc_proto].pr_request(sc, v);
+}
+
+static void
+lagg_proto_portreq(struct lagg_softc *sc, struct lagg_port *lp, void *v)
+{
+
+ if (lagg_protos[sc->sc_proto].pr_portreq != NULL)
+ lagg_protos[sc->sc_proto].pr_portreq(lp, v);
+}
+
/*
* This routine is run via an vlan
* config EVENT
@@ -242,19 +403,19 @@ MODULE_VERSION(if_lagg, 1);
static void
lagg_register_vlan(void *arg, struct ifnet *ifp, u_int16_t vtag)
{
- struct lagg_softc *sc = ifp->if_softc;
- struct lagg_port *lp;
- struct rm_priotracker tracker;
+ struct lagg_softc *sc = ifp->if_softc;
+ struct lagg_port *lp;
+ struct rm_priotracker tracker;
- if (ifp->if_softc != arg) /* Not our event */
- return;
+ if (ifp->if_softc != arg) /* Not our event */
+ return;
- LAGG_RLOCK(sc, &tracker);
- if (!SLIST_EMPTY(&sc->sc_ports)) {
- SLIST_FOREACH(lp, &sc->sc_ports, lp_entries)
- EVENTHANDLER_INVOKE(vlan_config, lp->lp_ifp, vtag);
- }
- LAGG_RUNLOCK(sc, &tracker);
+ LAGG_RLOCK(sc, &tracker);
+ if (!SLIST_EMPTY(&sc->sc_ports)) {
+ SLIST_FOREACH(lp, &sc->sc_ports, lp_entries)
+ EVENTHANDLER_INVOKE(vlan_config, lp->lp_ifp, vtag);
+ }
+ LAGG_RUNLOCK(sc, &tracker);
}
/*
@@ -264,19 +425,19 @@ lagg_register_vlan(void *arg, struct ifnet *ifp, u_int16_t vtag)
static void
lagg_unregister_vlan(void *arg, struct ifnet *ifp, u_int16_t vtag)
{
- struct lagg_softc *sc = ifp->if_softc;
- struct lagg_port *lp;
- struct rm_priotracker tracker;
+ struct lagg_softc *sc = ifp->if_softc;
+ struct lagg_port *lp;
+ struct rm_priotracker tracker;
- if (ifp->if_softc != arg) /* Not our event */
- return;
+ if (ifp->if_softc != arg) /* Not our event */
+ return;
- LAGG_RLOCK(sc, &tracker);
- if (!SLIST_EMPTY(&sc->sc_ports)) {
- SLIST_FOREACH(lp, &sc->sc_ports, lp_entries)
- EVENTHANDLER_INVOKE(vlan_unconfig, lp->lp_ifp, vtag);
- }
- LAGG_RUNLOCK(sc, &tracker);
+ LAGG_RLOCK(sc, &tracker);
+ if (!SLIST_EMPTY(&sc->sc_ports)) {
+ SLIST_FOREACH(lp, &sc->sc_ports, lp_entries)
+ EVENTHANDLER_INVOKE(vlan_unconfig, lp->lp_ifp, vtag);
+ }
+ LAGG_RUNLOCK(sc, &tracker);
}
static int
@@ -284,7 +445,6 @@ lagg_clone_create(struct if_clone *ifc, int unit, caddr_t params)
{
struct lagg_softc *sc;
struct ifnet *ifp;
- int i, error = 0;
static const u_char eaddr[6]; /* 00:00:00:00:00:00 */
struct sysctl_oid *oid;
char num[14]; /* sufficient for 32 bits */
@@ -327,18 +487,8 @@ lagg_clone_create(struct if_clone *ifc, int unit, caddr_t params)
/* Hash all layers by default */
sc->sc_flags = LAGG_F_HASHL2|LAGG_F_HASHL3|LAGG_F_HASHL4;
- sc->sc_proto = LAGG_PROTO_NONE;
- for (i = 0; lagg_protos[i].ti_proto != LAGG_PROTO_NONE; i++) {
- if (lagg_protos[i].ti_proto == LAGG_PROTO_DEFAULT) {
- sc->sc_proto = lagg_protos[i].ti_proto;
- if ((error = lagg_protos[i].ti_attach(sc)) != 0) {
- if_free(ifp);
- free(sc, M_DEVBUF);
- return (error);
- }
- break;
- }
- }
+ lagg_proto_attach(sc, LAGG_PROTO_DEFAULT);
+
LAGG_LOCK_INIT(sc);
LAGG_CALLOUT_LOCK_INIT(sc);
SLIST_INIT(&sc->sc_ports);
@@ -404,10 +554,7 @@ lagg_clone_destroy(struct ifnet *ifp)
while ((lp = SLIST_FIRST(&sc->sc_ports)) != NULL)
lagg_port_destroy(lp, 1);
/* Unhook the aggregation protocol */
- if (sc->sc_detach != NULL)
- (*sc->sc_detach)(sc);
-
- LAGG_WUNLOCK(sc);
+ lagg_proto_detach(sc);
sysctl_ctx_free(&sc->ctx);
ifmedia_removeall(&sc->sc_media);
@@ -443,8 +590,7 @@ lagg_lladdr(struct lagg_softc *sc, uint8_t *lladdr)
bcopy(lladdr, IF_LLADDR(ifp), ETHER_ADDR_LEN);
/* Let the protocol know the MAC has changed */
- if (sc->sc_lladdr != NULL)
- (*sc->sc_lladdr)(sc);
+ lagg_proto_lladdr(sc);
EVENTHANDLER_INVOKE(iflladdr_event, ifp);
}
@@ -454,23 +600,18 @@ lagg_capabilities(struct lagg_softc *sc)
struct lagg_port *lp;
int cap = ~0, ena = ~0;
u_long hwa = ~0UL;
-#if defined(INET) || defined(INET6)
- u_int hw_tsomax = IP_MAXPACKET; /* Initialize to the maximum value. */
-#else
- u_int hw_tsomax = ~0; /* if_hw_tsomax is only for INET/INET6, but.. */
-#endif
+ struct ifnet_hw_tsomax hw_tsomax;
LAGG_WLOCK_ASSERT(sc);
+ memset(&hw_tsomax, 0, sizeof(hw_tsomax));
+
/* Get capabilities from the lagg ports */
SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) {
cap &= lp->lp_ifp->if_capabilities;
ena &= lp->lp_ifp->if_capenable;
hwa &= lp->lp_ifp->if_hwassist;
- /* Set to the minimum value of the lagg ports. */
- if (lp->lp_ifp->if_hw_tsomax < hw_tsomax &&
- lp->lp_ifp->if_hw_tsomax > 0)
- hw_tsomax = lp->lp_ifp->if_hw_tsomax;
+ if_hw_tsomax_common(lp->lp_ifp, &hw_tsomax);
}
cap = (cap == ~0 ? 0 : cap);
ena = (ena == ~0 ? 0 : ena);
@@ -479,11 +620,10 @@ lagg_capabilities(struct lagg_softc *sc)
if (sc->sc_ifp->if_capabilities != cap ||
sc->sc_ifp->if_capenable != ena ||
sc->sc_ifp->if_hwassist != hwa ||
- sc->sc_ifp->if_hw_tsomax != hw_tsomax) {
+ if_hw_tsomax_update(sc->sc_ifp, &hw_tsomax) != 0) {
sc->sc_ifp->if_capabilities = cap;
sc->sc_ifp->if_capenable = ena;
sc->sc_ifp->if_hwassist = hwa;
- sc->sc_ifp->if_hw_tsomax = hw_tsomax;
getmicrotime(&sc->sc_ifp->if_lastchange);
if (sc->sc_ifflags & IFF_DEBUG)
@@ -571,8 +711,8 @@ static int
lagg_port_create(struct lagg_softc *sc, struct ifnet *ifp)
{
struct lagg_softc *sc_ptr;
- struct lagg_port *lp;
- int error = 0;
+ struct lagg_port *lp, *tlp;
+ int error;
LAGG_WLOCK_ASSERT(sc);
@@ -678,8 +818,18 @@ lagg_port_create(struct lagg_softc *sc, struct ifnet *ifp)
lagg_port_lladdr(lp, IF_LLADDR(sc->sc_ifp));
}
- /* Insert into the list of ports */
- SLIST_INSERT_HEAD(&sc->sc_ports, lp, lp_entries);
+ /* Insert into the list of ports. Keep ports sorted by if_index. */
+ SLIST_FOREACH(tlp, &sc->sc_ports, lp_entries) {
+ if (tlp->lp_ifp->if_index < ifp->if_index && (
+ SLIST_NEXT(tlp, lp_entries) == NULL ||
+ SLIST_NEXT(tlp, lp_entries)->lp_ifp->if_index <
+ ifp->if_index))
+ break;
+ }
+ if (tlp != NULL)
+ SLIST_INSERT_AFTER(tlp, lp, lp_entries);
+ else
+ SLIST_INSERT_HEAD(&sc->sc_ports, lp, lp_entries);
sc->sc_count++;
/* Update lagg capabilities */
@@ -690,15 +840,13 @@ lagg_port_create(struct lagg_softc *sc, struct ifnet *ifp)
lagg_ether_cmdmulti(lp, 1);
lagg_setflags(lp, 1);
- if (sc->sc_port_create != NULL)
- error = (*sc->sc_port_create)(lp);
- if (error) {
- /* remove the port again, without calling sc_port_destroy */
+ if ((error = lagg_proto_addport(sc, lp)) != 0) {
+ /* Remove the port, without calling pr_delport. */
lagg_port_destroy(lp, 0);
return (error);
}
- return (error);
+ return (0);
}
#ifdef LAGG_PORT_STACKING
@@ -723,7 +871,7 @@ lagg_port_checkstacking(struct lagg_softc *sc)
#endif
static int
-lagg_port_destroy(struct lagg_port *lp, int runpd)
+lagg_port_destroy(struct lagg_port *lp, int rundelport)
{
struct lagg_softc *sc = lp->lp_softc;
struct lagg_port *lp_ptr;
@@ -732,8 +880,8 @@ lagg_port_destroy(struct lagg_port *lp, int runpd)
LAGG_WLOCK_ASSERT(sc);
- if (runpd && sc->sc_port_destroy != NULL)
- (*sc->sc_port_destroy)(lp);
+ if (rundelport)
+ lagg_proto_delport(sc, lp);
/*
* Remove multicast addresses and interface flags from this port and
@@ -912,8 +1060,7 @@ lagg_port2req(struct lagg_port *lp, struct lagg_reqport *rp)
strlcpy(rp->rp_portname, lp->lp_ifp->if_xname, sizeof(rp->rp_portname));
rp->rp_prio = lp->lp_prio;
rp->rp_flags = lp->lp_flags;
- if (sc->sc_portreq != NULL)
- (*sc->sc_portreq)(lp, (caddr_t)&rp->rp_psc);
+ lagg_proto_portreq(sc, lp, &rp->rp_psc);
/* Add protocol specific flags */
switch (sc->sc_proto) {
@@ -927,7 +1074,7 @@ lagg_port2req(struct lagg_port *lp, struct lagg_reqport *rp)
case LAGG_PROTO_ROUNDROBIN:
case LAGG_PROTO_LOADBALANCE:
case LAGG_PROTO_ETHERCHANNEL:
- case LAGG_PROTO_BROADCAST:
+ case LAGG_PROTO_BROADCAST:
if (LAGG_PORTACTIVE(lp))
rp->rp_flags |= LAGG_PORT_ACTIVE;
break;
@@ -962,8 +1109,7 @@ lagg_init(void *xsc)
SLIST_FOREACH(lp, &sc->sc_ports, lp_entries)
lagg_port_lladdr(lp, IF_LLADDR(ifp));
- if (sc->sc_init != NULL)
- (*sc->sc_init)(sc);
+ lagg_proto_init(sc);
LAGG_WUNLOCK(sc);
}
@@ -980,8 +1126,7 @@ lagg_stop(struct lagg_softc *sc)
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
- if (sc->sc_stop != NULL)
- (*sc->sc_stop)(sc);
+ lagg_proto_stop(sc);
}
static int
@@ -1014,9 +1159,7 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
LAGG_RLOCK(sc, &tracker);
ra->ra_proto = sc->sc_proto;
- if (sc->sc_req != NULL)
- (*sc->sc_req)(sc, (caddr_t)&ra->ra_psc);
-
+ lagg_proto_request(sc, &ra->ra_psc);
count = 0;
buf = outbuf;
len = min(ra->ra_size, buflen);
@@ -1040,50 +1183,14 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
error = priv_check(td, PRIV_NET_LAGG);
if (error)
break;
- if (ra->ra_proto >= LAGG_PROTO_MAX) {
+ if (ra->ra_proto < 1 || ra->ra_proto >= LAGG_PROTO_MAX) {
error = EPROTONOSUPPORT;
break;
}
+
LAGG_WLOCK(sc);
- if (sc->sc_proto != LAGG_PROTO_NONE) {
- /* Reset protocol first in case detach unlocks */
- sc->sc_proto = LAGG_PROTO_NONE;
- error = sc->sc_detach(sc);
- sc->sc_detach = NULL;
- sc->sc_start = NULL;
- sc->sc_input = NULL;
- sc->sc_port_create = NULL;
- sc->sc_port_destroy = NULL;
- sc->sc_linkstate = NULL;
- sc->sc_init = NULL;
- sc->sc_stop = NULL;
- sc->sc_lladdr = NULL;
- sc->sc_req = NULL;
- sc->sc_portreq = NULL;
- } else if (sc->sc_input != NULL) {
- /* Still detaching */
- error = EBUSY;
- }
- if (error != 0) {
- LAGG_WUNLOCK(sc);
- break;
- }
- for (int i = 0; i < (sizeof(lagg_protos) /
- sizeof(lagg_protos[0])); i++) {
- if (lagg_protos[i].ti_proto == ra->ra_proto) {
- if (sc->sc_ifflags & IFF_DEBUG)
- printf("%s: using proto %u\n",
- sc->sc_ifname,
- lagg_protos[i].ti_proto);
- sc->sc_proto = lagg_protos[i].ti_proto;
- if (sc->sc_proto != LAGG_PROTO_NONE)
- error = lagg_protos[i].ti_attach(sc);
- LAGG_WUNLOCK(sc);
- return (error);
- }
- }
- LAGG_WUNLOCK(sc);
- error = EPROTONOSUPPORT;
+ lagg_proto_detach(sc);
+ lagg_proto_attach(sc, ra->ra_proto);
break;
case SIOCGLAGGFLAGS:
rf->rf_flags = sc->sc_flags;
@@ -1268,7 +1375,7 @@ lagg_ether_cmdmulti(struct lagg_port *lp, int set)
/* Handle a ref counted flag that should be set on the lagg port as well */
static int
lagg_setflag(struct lagg_port *lp, int flag, int status,
- int (*func)(struct ifnet *, int))
+ int (*func)(struct ifnet *, int))
{
struct lagg_softc *sc = lp->lp_softc;
struct ifnet *scifp = sc->sc_ifp;
@@ -1339,7 +1446,7 @@ lagg_transmit(struct ifnet *ifp, struct mbuf *m)
ETHER_BPF_MTAP(ifp, m);
- error = (*sc->sc_start)(sc, m);
+ error = lagg_proto_start(sc, m);
LAGG_RUNLOCK(sc, &tracker);
if (error == 0) {
@@ -1379,7 +1486,7 @@ lagg_input(struct ifnet *ifp, struct mbuf *m)
ETHER_BPF_MTAP(scifp, m);
- m = (*sc->sc_input)(sc, lp, m);
+ m = lagg_proto_input(sc, lp, m);
if (m != NULL) {
counter_u64_add(sc->sc_ipackets, 1);
@@ -1434,7 +1541,7 @@ lagg_linkstate(struct lagg_softc *sc)
/* Our link is considered up if at least one of our ports is active */
SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) {
- if (lp->lp_link_state == LINK_STATE_UP) {
+ if (lp->lp_ifp->if_link_state == LINK_STATE_UP) {
new_link = LINK_STATE_UP;
break;
}
@@ -1450,7 +1557,7 @@ lagg_linkstate(struct lagg_softc *sc)
case LAGG_PROTO_ROUNDROBIN:
case LAGG_PROTO_LOADBALANCE:
case LAGG_PROTO_ETHERCHANNEL:
- case LAGG_PROTO_BROADCAST:
+ case LAGG_PROTO_BROADCAST:
speed = 0;
SLIST_FOREACH(lp, &sc->sc_ports, lp_entries)
speed += lp->lp_ifp->if_baudrate;
@@ -1475,8 +1582,7 @@ lagg_port_state(struct ifnet *ifp, int state)
LAGG_WLOCK(sc);
lagg_linkstate(sc);
- if (sc->sc_linkstate != NULL)
- (*sc->sc_linkstate)(lp);
+ lagg_proto_linkstate(sc, lp);
LAGG_WUNLOCK(sc);
}
@@ -1676,24 +1782,11 @@ lagg_enqueue(struct ifnet *ifp, struct mbuf *m)
/*
* Simple round robin aggregation
*/
-
-static int
+static void
lagg_rr_attach(struct lagg_softc *sc)
{
- sc->sc_detach = lagg_rr_detach;
- sc->sc_start = lagg_rr_start;
- sc->sc_input = lagg_rr_input;
- sc->sc_port_create = NULL;
sc->sc_capabilities = IFCAP_LAGG_FULLDUPLEX;
sc->sc_seq = 0;
-
- return (0);
-}
-
-static int
-lagg_rr_detach(struct lagg_softc *sc)
-{
- return (0);
}
static int
@@ -1735,110 +1828,67 @@ lagg_rr_input(struct lagg_softc *sc, struct lagg_port *lp, struct mbuf *m)
/*
* Broadcast mode
*/
-
static int
-lagg_bcast_attach(struct lagg_softc *sc)
+lagg_bcast_start(struct lagg_softc *sc, struct mbuf *m)
{
- sc->sc_detach = lagg_bcast_detach;
- sc->sc_start = lagg_bcast_start;
- sc->sc_input = lagg_bcast_input;
- sc->sc_port_create = NULL;
- sc->sc_port_destroy = NULL;
- sc->sc_linkstate = NULL;
- sc->sc_req = NULL;
- sc->sc_portreq = NULL;
+ int active_ports = 0;
+ int errors = 0;
+ int ret;
+ struct lagg_port *lp, *last = NULL;
+ struct mbuf *m0;
- return (0);
-}
-
-static int
-lagg_bcast_detach(struct lagg_softc *sc)
-{
- return (0);
-}
+ SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) {
+ if (!LAGG_PORTACTIVE(lp))
+ continue;
-static int
-lagg_bcast_start(struct lagg_softc *sc, struct mbuf *m)
-{
- int active_ports = 0;
- int errors = 0;
- int ret;
- struct lagg_port *lp, *last = NULL;
- struct mbuf *m0;
-
- SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) {
- if (!LAGG_PORTACTIVE(lp))
- continue;
-
- active_ports++;
-
- if (last != NULL) {
- m0 = m_copym(m, 0, M_COPYALL,
- M_NOWAIT);
- if (m0 == NULL) {
- ret = ENOBUFS;
- errors++;
- break;
- }
-
- ret = lagg_enqueue(last->lp_ifp, m0);
- if (ret != 0)
- errors++;
- }
- last = lp;
- }
- if (last == NULL) {
- m_freem(m);
- return (ENOENT);
- }
- if ((last = lagg_link_active(sc, last)) == NULL) {
- m_freem(m);
- return (ENETDOWN);
- }
-
- ret = lagg_enqueue(last->lp_ifp, m);
- if (ret != 0)
- errors++;
-
- if (errors == 0)
- return (ret);
-
- return (0);
-}
+ active_ports++;
-static struct mbuf*
-lagg_bcast_input(struct lagg_softc *sc, struct lagg_port *lp,
- struct mbuf *m)
-{
- struct ifnet *ifp = sc->sc_ifp;
+ if (last != NULL) {
+ m0 = m_copym(m, 0, M_COPYALL, M_NOWAIT);
+ if (m0 == NULL) {
+ ret = ENOBUFS;
+ errors++;
+ break;
+ }
- /* Just pass in the packet to our lagg device */
- m->m_pkthdr.rcvif = ifp;
- return (m);
-}
+ ret = lagg_enqueue(last->lp_ifp, m0);
+ if (ret != 0)
+ errors++;
+ }
+ last = lp;
+ }
+ if (last == NULL) {
+ m_freem(m);
+ return (ENOENT);
+ }
+ if ((last = lagg_link_active(sc, last)) == NULL) {
+ m_freem(m);
+ return (ENETDOWN);
+ }
-/*
- * Active failover
- */
+ ret = lagg_enqueue(last->lp_ifp, m);
+ if (ret != 0)
+ errors++;
-static int
-lagg_fail_attach(struct lagg_softc *sc)
-{
- sc->sc_detach = lagg_fail_detach;
- sc->sc_start = lagg_fail_start;
- sc->sc_input = lagg_fail_input;
- sc->sc_port_create = NULL;
- sc->sc_port_destroy = NULL;
+ if (errors == 0)
+ return (ret);
return (0);
}
-static int
-lagg_fail_detach(struct lagg_softc *sc)
+static struct mbuf*
+lagg_bcast_input(struct lagg_softc *sc, struct lagg_port *lp, struct mbuf *m)
{
- return (0);
+ struct ifnet *ifp = sc->sc_ifp;
+
+ /* Just pass in the packet to our lagg device */
+ m->m_pkthdr.rcvif = ifp;
+ return (m);
}
+/*
+ * Active failover
+ */
static int
lagg_fail_start(struct lagg_softc *sc, struct mbuf *m)
{
@@ -1884,40 +1934,32 @@ lagg_fail_input(struct lagg_softc *sc, struct lagg_port *lp, struct mbuf *m)
/*
* Loadbalancing
*/
-
-static int
+static void
lagg_lb_attach(struct lagg_softc *sc)
{
struct lagg_port *lp;
struct lagg_lb *lb;
- if ((lb = (struct lagg_lb *)malloc(sizeof(struct lagg_lb),
- M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL)
- return (ENOMEM);
+ lb = malloc(sizeof(struct lagg_lb), M_DEVBUF, M_WAITOK | M_ZERO);
- sc->sc_detach = lagg_lb_detach;
- sc->sc_start = lagg_lb_start;
- sc->sc_input = lagg_lb_input;
- sc->sc_port_create = lagg_lb_port_create;
- sc->sc_port_destroy = lagg_lb_port_destroy;
sc->sc_capabilities = IFCAP_LAGG_FULLDUPLEX;
lb->lb_key = arc4random();
- sc->sc_psc = (caddr_t)lb;
+ sc->sc_psc = lb;
SLIST_FOREACH(lp, &sc->sc_ports, lp_entries)
lagg_lb_port_create(lp);
-
- return (0);
}
-static int
+static void
lagg_lb_detach(struct lagg_softc *sc)
{
- struct lagg_lb *lb = (struct lagg_lb *)sc->sc_psc;
+ struct lagg_lb *lb;
+
+ lb = (struct lagg_lb *)sc->sc_psc;
+ LAGG_WUNLOCK(sc);
if (lb != NULL)
free(lb, M_DEVBUF);
- return (0);
}
static int
@@ -1935,7 +1977,7 @@ lagg_lb_porttable(struct lagg_softc *sc, struct lagg_port *lp)
return (EINVAL);
if (sc->sc_ifflags & IFF_DEBUG)
printf("%s: port %s at index %d\n",
- sc->sc_ifname, lp_next->lp_ifname, i);
+ sc->sc_ifname, lp_next->lp_ifp->if_xname, i);
lb->lb_ports[i++] = lp_next;
}
@@ -1997,50 +2039,30 @@ lagg_lb_input(struct lagg_softc *sc, struct lagg_port *lp, struct mbuf *m)
/*
* 802.3ad LACP
*/
-
-static int
+static void
lagg_lacp_attach(struct lagg_softc *sc)
{
struct lagg_port *lp;
- int error;
-
- sc->sc_detach = lagg_lacp_detach;
- sc->sc_port_create = lacp_port_create;
- sc->sc_port_destroy = lacp_port_destroy;
- sc->sc_linkstate = lacp_linkstate;
- sc->sc_start = lagg_lacp_start;
- sc->sc_input = lagg_lacp_input;
- sc->sc_init = lacp_init;
- sc->sc_stop = lacp_stop;
- sc->sc_lladdr = lagg_lacp_lladdr;
- sc->sc_req = lacp_req;
- sc->sc_portreq = lacp_portreq;
-
- error = lacp_attach(sc);
- if (error)
- return (error);
+ lacp_attach(sc);
SLIST_FOREACH(lp, &sc->sc_ports, lp_entries)
lacp_port_create(lp);
-
- return (error);
}
-static int
+static void
lagg_lacp_detach(struct lagg_softc *sc)
{
struct lagg_port *lp;
- int error;
+ void *psc;
SLIST_FOREACH(lp, &sc->sc_ports, lp_entries)
lacp_port_destroy(lp);
- /* unlocking is safe here */
+ psc = sc->sc_psc;
+ sc->sc_psc = NULL;
LAGG_WUNLOCK(sc);
- error = lacp_detach(sc);
- LAGG_WLOCK(sc);
- return (error);
+ lacp_detach(psc);
}
static void
diff --git a/sys/net/if_lagg.h b/sys/net/if_lagg.h
index fe62920..1b07f7b 100644
--- a/sys/net/if_lagg.h
+++ b/sys/net/if_lagg.h
@@ -47,18 +47,20 @@
"\05DISTRIBUTING\06DISABLED"
/* Supported lagg PROTOs */
-#define LAGG_PROTO_NONE 0 /* no lagg protocol defined */
-#define LAGG_PROTO_ROUNDROBIN 1 /* simple round robin */
-#define LAGG_PROTO_FAILOVER 2 /* active failover */
-#define LAGG_PROTO_LOADBALANCE 3 /* loadbalance */
-#define LAGG_PROTO_LACP 4 /* 802.3ad lacp */
-#define LAGG_PROTO_ETHERCHANNEL 5 /* Cisco FEC */
-#define LAGG_PROTO_BROADCAST 6 /* broadcast */
-#define LAGG_PROTO_MAX 7
+typedef enum {
+ LAGG_PROTO_NONE = 0, /* no lagg protocol defined */
+ LAGG_PROTO_ROUNDROBIN, /* simple round robin */
+ LAGG_PROTO_FAILOVER, /* active failover */
+ LAGG_PROTO_LOADBALANCE, /* loadbalance */
+ LAGG_PROTO_LACP, /* 802.3ad lacp */
+ LAGG_PROTO_ETHERCHANNEL,/* Cisco FEC */
+ LAGG_PROTO_BROADCAST, /* broadcast */
+ LAGG_PROTO_MAX,
+} lagg_proto;
struct lagg_protos {
const char *lpr_name;
- int lpr_proto;
+ lagg_proto lpr_proto;
};
#define LAGG_PROTO_DEFAULT LAGG_PROTO_FAILOVER
@@ -144,11 +146,8 @@ struct lagg_reqflags {
* Internal kernel part
*/
-#define lp_ifname lp_ifp->if_xname /* interface name */
-#define lp_link_state lp_ifp->if_link_state /* link state */
-
#define LAGG_PORTACTIVE(_tp) ( \
- ((_tp)->lp_link_state == LINK_STATE_UP) && \
+ ((_tp)->lp_ifp->if_link_state == LINK_STATE_UP) && \
((_tp)->lp_ifp->if_flags & IFF_UP) \
)
@@ -199,7 +198,7 @@ struct lagg_softc {
* events */
struct lagg_port *sc_primary; /* primary port */
struct ifmedia sc_media; /* media config */
- caddr_t sc_psc; /* protocol data */
+ void *sc_psc; /* protocol data */
uint32_t sc_seq; /* sequence counter */
uint32_t sc_flags;
@@ -214,20 +213,6 @@ struct lagg_softc {
struct task sc_lladdr_task;
SLIST_HEAD(__llqhd, lagg_llq) sc_llq_head; /* interfaces to program
the lladdr on */
-
- /* lagg protocol callbacks */
- int (*sc_detach)(struct lagg_softc *);
- int (*sc_start)(struct lagg_softc *, struct mbuf *);
- struct mbuf *(*sc_input)(struct lagg_softc *, struct lagg_port *,
- struct mbuf *);
- int (*sc_port_create)(struct lagg_port *);
- void (*sc_port_destroy)(struct lagg_port *);
- void (*sc_linkstate)(struct lagg_port *);
- void (*sc_init)(struct lagg_softc *);
- void (*sc_stop)(struct lagg_softc *);
- void (*sc_lladdr)(struct lagg_softc *);
- void (*sc_req)(struct lagg_softc *, caddr_t);
- void (*sc_portreq)(struct lagg_port *, caddr_t);
eventhandler_tag vlan_attach;
eventhandler_tag vlan_detach;
struct callout sc_callout;
@@ -247,7 +232,7 @@ struct lagg_port {
uint32_t lp_flags; /* port flags */
int lp_ifflags; /* saved ifp flags */
void *lh_cookie; /* if state hook */
- caddr_t lp_psc; /* protocol data */
+ void *lp_psc; /* protocol data */
int lp_detaching; /* ifnet is detaching */
SLIST_HEAD(__mclhd, lagg_mc) lp_mc_head; /* multicast addresses */
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index 9daafdf..53bac32 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -119,6 +119,12 @@ typedef void (*if_qflush_fn_t)(if_t);
typedef int (*if_transmit_fn_t)(if_t, struct mbuf *);
typedef uint64_t (*if_get_counter_t)(if_t, ift_counter);
+struct ifnet_hw_tsomax {
+ u_int tsomaxbytes; /* TSO total burst length limit in bytes */
+ u_int tsomaxsegcount; /* TSO maximum segment count */
+ u_int tsomaxsegsize; /* TSO maximum segment size in bytes */
+};
+
/*
* Structure defining a network interface.
*
@@ -222,10 +228,11 @@ struct ifnet {
if_get_counter_t if_get_counter; /* get counter values */
/* Stuff that's only temporary and doesn't belong here. */
- u_int if_hw_tsomax; /* tso burst length limit, the minimum
- * is (IP_MAXPACKET / 8).
- * XXXAO: Have to find a better place
- * for it eventually. */
+ u_int if_hw_tsomax; /* TSO total burst length
+ * limit in bytes. A value of
+ * zero means no limit. Have
+ * to find a better place for
+ * it eventually. */
/*
* Old, racy and expensive statistics, should not be used in
* new drivers.
@@ -243,6 +250,10 @@ struct ifnet {
uint64_t if_oqdrops; /* dropped on output */
uint64_t if_noproto; /* destined for unsupported protocol */
+ /* TSO fields for segment limits. If a field is zero below, there is no limit. */
+ u_int if_hw_tsomaxsegcount; /* TSO maximum segment count */
+ u_int if_hw_tsomaxsegsize; /* TSO maximum segment size in bytes */
+
/*
* Spare fields to be added before branching a stable branch, so
* that structure can be enhanced without changing the kernel
@@ -596,5 +607,9 @@ struct mbuf* drbr_dequeue_drv(if_t ifp, struct buf_ring *br);
int drbr_needs_enqueue_drv(if_t ifp, struct buf_ring *br);
int drbr_enqueue_drv(if_t ifp, struct buf_ring *br, struct mbuf *m);
+/* TSO */
+void if_hw_tsomax_common(if_t ifp, struct ifnet_hw_tsomax *);
+int if_hw_tsomax_update(if_t ifp, struct ifnet_hw_tsomax *);
+
#endif /* _KERNEL */
#endif /* !_NET_IF_VAR_H_ */
diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c
index c7a2d01..926afa0 100644
--- a/sys/net/if_vlan.c
+++ b/sys/net/if_vlan.c
@@ -1536,6 +1536,7 @@ vlan_capabilities(struct ifvlan *ifv)
{
struct ifnet *p = PARENT(ifv);
struct ifnet *ifp = ifv->ifv_ifp;
+ struct ifnet_hw_tsomax hw_tsomax;
TRUNK_LOCK_ASSERT(TRUNK(ifv));
@@ -1562,8 +1563,9 @@ vlan_capabilities(struct ifvlan *ifv)
* propagate the hardware-assisted flag. TSO on VLANs
* does not necessarily require hardware VLAN tagging.
*/
- if (p->if_hw_tsomax > 0)
- ifp->if_hw_tsomax = p->if_hw_tsomax;
+ memset(&hw_tsomax, 0, sizeof(hw_tsomax));
+ if_hw_tsomax_common(p, &hw_tsomax);
+ if_hw_tsomax_update(ifp, &hw_tsomax);
if (p->if_capabilities & IFCAP_VLAN_HWTSO)
ifp->if_capabilities |= p->if_capabilities & IFCAP_TSO;
if (p->if_capenable & IFCAP_VLAN_HWTSO) {
diff --git a/sys/net/route.c b/sys/net/route.c
index 2e0bb99..38e610a 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -108,9 +108,9 @@ SYSCTL_UINT(_net, OID_AUTO, fibs, CTLFLAG_RDTUN, &rt_numfibs, 0, "");
* always work given the fib can be overridden and prefixes can be added
* from the network stack context.
*/
-u_int rt_add_addr_allfibs = 1;
-SYSCTL_UINT(_net, OID_AUTO, add_addr_allfibs, CTLFLAG_RWTUN,
- &rt_add_addr_allfibs, 0, "");
+VNET_DEFINE(u_int, rt_add_addr_allfibs) = 1;
+SYSCTL_UINT(_net, OID_AUTO, add_addr_allfibs, CTLFLAG_RWTUN | CTLFLAG_VNET,
+ &VNET_NAME(rt_add_addr_allfibs), 0, "");
VNET_DEFINE(struct rtstat, rtstat);
#define V_rtstat VNET(rtstat)
@@ -1613,9 +1613,9 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
break;
}
if (fibnum == RT_ALL_FIBS) {
- if (rt_add_addr_allfibs == 0 && cmd == (int)RTM_ADD) {
+ if (V_rt_add_addr_allfibs == 0 && cmd == (int)RTM_ADD)
startfib = endfib = ifa->ifa_ifp->if_fib;
- } else {
+ else {
startfib = 0;
endfib = rt_numfibs - 1;
}
diff --git a/sys/net/route.h b/sys/net/route.h
index df2fc58..bbdf98d 100644
--- a/sys/net/route.h
+++ b/sys/net/route.h
@@ -34,6 +34,7 @@
#define _NET_ROUTE_H_
#include <sys/counter.h>
+#include <net/vnet.h>
/*
* Kernel resident routing tables.
@@ -84,8 +85,11 @@ struct rt_metrics {
#define RT_DEFAULT_FIB 0 /* Explicitly mark fib=0 restricted cases */
#define RT_ALL_FIBS -1 /* Announce event for every fib */
+#ifdef _KERNEL
extern u_int rt_numfibs; /* number of usable routing tables */
-extern u_int rt_add_addr_allfibs; /* Announce interfaces to all fibs */
+VNET_DECLARE(u_int, rt_add_addr_allfibs); /* Announce interfaces to all fibs */
+#define V_rt_add_addr_allfibs VNET(rt_add_addr_allfibs)
+#endif
/*
* We distinguish between routes to hosts and routes to networks,
diff --git a/sys/netgraph/bluetooth/include/ng_btsocket_l2cap.h b/sys/netgraph/bluetooth/include/ng_btsocket_l2cap.h
index deea5b3..493ea42 100644
--- a/sys/netgraph/bluetooth/include/ng_btsocket_l2cap.h
+++ b/sys/netgraph/bluetooth/include/ng_btsocket_l2cap.h
@@ -162,7 +162,7 @@ struct ng_btsocket_l2cap_pcb {
u_int16_t flush_timo; /* flush timeout */
u_int16_t link_timo; /* link timeout */
- struct callout_handle timo; /* timeout */
+ struct callout timo; /* timeout */
u_int32_t token; /* message token */
ng_btsocket_l2cap_rtentry_p rt; /* routing info */
diff --git a/sys/netgraph/bluetooth/include/ng_btsocket_rfcomm.h b/sys/netgraph/bluetooth/include/ng_btsocket_rfcomm.h
index 4aaa658..fdc1d00 100644
--- a/sys/netgraph/bluetooth/include/ng_btsocket_rfcomm.h
+++ b/sys/netgraph/bluetooth/include/ng_btsocket_rfcomm.h
@@ -296,7 +296,7 @@ struct ng_btsocket_rfcomm_pcb {
int16_t tx_cred; /* TX credits */
struct mtx pcb_mtx; /* PCB lock */
- struct callout_handle timo; /* timeout */
+ struct callout timo; /* timeout */
LIST_ENTRY(ng_btsocket_rfcomm_pcb) session_next;/* link to next */
LIST_ENTRY(ng_btsocket_rfcomm_pcb) next; /* link to next */
diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c b/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c
index af2ce1a..bab8bbb 100644
--- a/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c
+++ b/sys/netgraph/bluetooth/socket/ng_btsocket_l2cap.c
@@ -1967,8 +1967,6 @@ ng_btsocket_l2cap_attach(struct socket *so, int proto, struct thread *td)
pcb->flush_timo = NG_L2CAP_FLUSH_TIMO_DEFAULT;
pcb->link_timo = NG_L2CAP_LINK_TIMO_DEFAULT;
- callout_handle_init(&pcb->timo);
-
/*
* XXX Mark PCB mutex as DUPOK to prevent "duplicated lock of
* the same type" message. When accepting new L2CAP connection
@@ -1978,6 +1976,7 @@ ng_btsocket_l2cap_attach(struct socket *so, int proto, struct thread *td)
mtx_init(&pcb->pcb_mtx, "btsocks_l2cap_pcb_mtx", NULL,
MTX_DEF|MTX_DUPOK);
+ callout_init_mtx(&pcb->timo, &pcb->pcb_mtx, 0);
/*
* Add the PCB to the list
@@ -2664,8 +2663,8 @@ ng_btsocket_l2cap_timeout(ng_btsocket_l2cap_pcb_p pcb)
if (!(pcb->flags & NG_BTSOCKET_L2CAP_TIMO)) {
pcb->flags |= NG_BTSOCKET_L2CAP_TIMO;
- pcb->timo = timeout(ng_btsocket_l2cap_process_timeout, pcb,
- bluetooth_l2cap_ertx_timeout());
+ callout_reset(&pcb->timo, bluetooth_l2cap_ertx_timeout(),
+ ng_btsocket_l2cap_process_timeout, pcb);
} else
KASSERT(0,
("%s: Duplicated socket timeout?!\n", __func__));
@@ -2681,7 +2680,7 @@ ng_btsocket_l2cap_untimeout(ng_btsocket_l2cap_pcb_p pcb)
mtx_assert(&pcb->pcb_mtx, MA_OWNED);
if (pcb->flags & NG_BTSOCKET_L2CAP_TIMO) {
- untimeout(ng_btsocket_l2cap_process_timeout, pcb, pcb->timo);
+ callout_stop(&pcb->timo);
pcb->flags &= ~NG_BTSOCKET_L2CAP_TIMO;
} else
KASSERT(0,
@@ -2697,7 +2696,7 @@ ng_btsocket_l2cap_process_timeout(void *xpcb)
{
ng_btsocket_l2cap_pcb_p pcb = (ng_btsocket_l2cap_pcb_p) xpcb;
- mtx_lock(&pcb->pcb_mtx);
+ mtx_assert(&pcb->pcb_mtx, MA_OWNED);
pcb->flags &= ~NG_BTSOCKET_L2CAP_TIMO;
pcb->so->so_error = ETIMEDOUT;
@@ -2731,8 +2730,6 @@ ng_btsocket_l2cap_process_timeout(void *xpcb)
"%s: Invalid socket state=%d\n", __func__, pcb->state);
break;
}
-
- mtx_unlock(&pcb->pcb_mtx);
} /* ng_btsocket_l2cap_process_timeout */
/*
diff --git a/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c b/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c
index 215843c..cb3753d 100644
--- a/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c
+++ b/sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c
@@ -434,7 +434,7 @@ ng_btsocket_rfcomm_attach(struct socket *so, int proto, struct thread *td)
pcb->rx_cred = RFCOMM_DEFAULT_CREDITS;
mtx_init(&pcb->pcb_mtx, "btsocks_rfcomm_pcb_mtx", NULL, MTX_DEF);
- callout_handle_init(&pcb->timo);
+ callout_init_mtx(&pcb->timo, &pcb->pcb_mtx, 0);
/* Add the PCB to the list */
mtx_lock(&ng_btsocket_rfcomm_sockets_mtx);
@@ -3451,8 +3451,8 @@ ng_btsocket_rfcomm_timeout(ng_btsocket_rfcomm_pcb_p pcb)
if (!(pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO)) {
pcb->flags |= NG_BTSOCKET_RFCOMM_DLC_TIMO;
pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
- pcb->timo = timeout(ng_btsocket_rfcomm_process_timeout, pcb,
- ng_btsocket_rfcomm_timo * hz);
+ callout_reset(&pcb->timo, ng_btsocket_rfcomm_timo * hz,
+ ng_btsocket_rfcomm_process_timeout, pcb);
} else
panic("%s: Duplicated socket timeout?!\n", __func__);
} /* ng_btsocket_rfcomm_timeout */
@@ -3467,7 +3467,7 @@ ng_btsocket_rfcomm_untimeout(ng_btsocket_rfcomm_pcb_p pcb)
mtx_assert(&pcb->pcb_mtx, MA_OWNED);
if (pcb->flags & NG_BTSOCKET_RFCOMM_DLC_TIMO) {
- untimeout(ng_btsocket_rfcomm_process_timeout, pcb, pcb->timo);
+ callout_stop(&pcb->timo);
pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMO;
pcb->flags &= ~NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT;
} else
@@ -3483,7 +3483,7 @@ ng_btsocket_rfcomm_process_timeout(void *xpcb)
{
ng_btsocket_rfcomm_pcb_p pcb = (ng_btsocket_rfcomm_pcb_p) xpcb;
- mtx_lock(&pcb->pcb_mtx);
+ mtx_assert(&pcb->pcb_mtx, MA_OWNED);
NG_BTSOCKET_RFCOMM_INFO(
"%s: Timeout, so=%p, dlci=%d, state=%d, flags=%#x\n",
@@ -3510,8 +3510,6 @@ ng_btsocket_rfcomm_process_timeout(void *xpcb)
}
ng_btsocket_rfcomm_task_wakeup();
-
- mtx_unlock(&pcb->pcb_mtx);
} /* ng_btsocket_rfcomm_process_timeout */
/*
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index 52fc446..0a2b130 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -674,7 +674,7 @@ in_addprefix(struct in_ifaddr *target, int flags)
} else {
int fibnum;
- fibnum = rt_add_addr_allfibs ? RT_ALL_FIBS :
+ fibnum = V_rt_add_addr_allfibs ? RT_ALL_FIBS :
target->ia_ifp->if_fib;
rt_addrmsg(RTM_ADD, &target->ia_ifa, fibnum);
IN_IFADDR_RUNLOCK();
@@ -745,7 +745,7 @@ in_scrubprefix(struct in_ifaddr *target, u_int flags)
if ((target->ia_flags & IFA_ROUTE) == 0) {
int fibnum;
- fibnum = rt_add_addr_allfibs ? RT_ALL_FIBS :
+ fibnum = V_rt_add_addr_allfibs ? RT_ALL_FIBS :
target->ia_ifp->if_fib;
rt_addrmsg(RTM_DELETE, &target->ia_ifa, fibnum);
return (0);
diff --git a/sys/netinet/ip_gre.c b/sys/netinet/ip_gre.c
index 53fecab..897adac 100644
--- a/sys/netinet/ip_gre.c
+++ b/sys/netinet/ip_gre.c
@@ -315,18 +315,18 @@ gre_lookup(struct mbuf *m, u_int8_t proto)
struct ip *ip = mtod(m, struct ip *);
struct gre_softc *sc;
- mtx_lock(&gre_mtx);
- for (sc = LIST_FIRST(&gre_softc_list); sc != NULL;
+ GRE_LIST_LOCK();
+ for (sc = LIST_FIRST(&V_gre_softc_list); sc != NULL;
sc = LIST_NEXT(sc, sc_list)) {
if ((sc->g_dst.s_addr == ip->ip_src.s_addr) &&
(sc->g_src.s_addr == ip->ip_dst.s_addr) &&
(sc->g_proto == proto) &&
((GRE2IFP(sc)->if_flags & IFF_UP) != 0)) {
- mtx_unlock(&gre_mtx);
+ GRE_LIST_UNLOCK();
return (sc);
}
}
- mtx_unlock(&gre_mtx);
+ GRE_LIST_UNLOCK();
return (NULL);
}
diff --git a/sys/netinet/ip_ipsec.c b/sys/netinet/ip_ipsec.c
index 6bd42c0..bf9f81f 100644
--- a/sys/netinet/ip_ipsec.c
+++ b/sys/netinet/ip_ipsec.c
@@ -63,15 +63,12 @@ __FBSDID("$FreeBSD$");
#include <machine/in_cksum.h>
-#ifdef IPSEC
#include <netipsec/ipsec.h>
#include <netipsec/xform.h>
#include <netipsec/key.h>
-#endif /*IPSEC*/
extern struct protosw inetsw[];
-#ifdef IPSEC
#ifdef IPSEC_FILTERTUNNEL
static VNET_DEFINE(int, ip4_ipsec_filtertunnel) = 1;
#else
@@ -83,7 +80,6 @@ SYSCTL_DECL(_net_inet_ipsec);
SYSCTL_VNET_INT(_net_inet_ipsec, OID_AUTO, filtertunnel,
CTLFLAG_RW, &VNET_NAME(ip4_ipsec_filtertunnel), 0,
"If set filter packets from an IPsec tunnel.");
-#endif /* IPSEC */
/*
* Check if we have to jump over firewall processing for this packet.
@@ -93,7 +89,6 @@ SYSCTL_VNET_INT(_net_inet_ipsec, OID_AUTO, filtertunnel,
int
ip_ipsec_filtertunnel(struct mbuf *m)
{
-#ifdef IPSEC
/*
* Bypass packet filtering for packets previously handled by IPsec.
@@ -101,7 +96,6 @@ ip_ipsec_filtertunnel(struct mbuf *m)
if (!V_ip4_ipsec_filtertunnel &&
m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL) != NULL)
return 1;
-#endif
return 0;
}
@@ -114,7 +108,6 @@ ip_ipsec_filtertunnel(struct mbuf *m)
int
ip_ipsec_fwd(struct mbuf *m)
{
-#ifdef IPSEC
struct m_tag *mtag;
struct tdb_ident *tdbi;
struct secpolicy *sp;
@@ -143,7 +136,6 @@ ip_ipsec_fwd(struct mbuf *m)
IPSTAT_INC(ips_cantforward);
return 1;
}
-#endif /* IPSEC */
return 0;
}
@@ -157,7 +149,6 @@ ip_ipsec_fwd(struct mbuf *m)
int
ip_ipsec_input(struct mbuf *m)
{
-#ifdef IPSEC
struct ip *ip = mtod(m, struct ip *);
struct m_tag *mtag;
struct tdb_ident *tdbi;
@@ -198,7 +189,6 @@ ip_ipsec_input(struct mbuf *m)
if (error)
return 1;
}
-#endif /* IPSEC */
return 0;
}
@@ -256,7 +246,6 @@ ip_ipsec_mtu(struct mbuf *m, int mtu)
int
ip_ipsec_output(struct mbuf **m, struct inpcb *inp, int *flags, int *error)
{
-#ifdef IPSEC
struct secpolicy *sp = NULL;
struct tdb_ident *tdbi;
struct m_tag *mtag;
@@ -388,6 +377,4 @@ bad:
if (sp != NULL)
KEY_FREESP(&sp);
return 1;
-#endif /* IPSEC */
- return 0;
}
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index ea0f1b8..e338b1e 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -3591,6 +3591,8 @@ tcp_mss(struct tcpcb *tp, int offer)
if (cap.ifcap & CSUM_TSO) {
tp->t_flags |= TF_TSO;
tp->t_tsomax = cap.tsomax;
+ tp->t_tsomaxsegcount = cap.tsomaxsegcount;
+ tp->t_tsomaxsegsize = cap.tsomaxsegsize;
}
}
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index 12d8e75..0697767 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -767,28 +767,113 @@ send:
flags &= ~TH_FIN;
if (tso) {
+ u_int if_hw_tsomax;
+ u_int if_hw_tsomaxsegcount;
+ u_int if_hw_tsomaxsegsize;
+ struct mbuf *mb;
+ u_int moff;
+ int max_len;
+
+ /* extract TSO information */
+ if_hw_tsomax = tp->t_tsomax;
+ if_hw_tsomaxsegcount = tp->t_tsomaxsegcount;
+ if_hw_tsomaxsegsize = tp->t_tsomaxsegsize;
+
+ /*
+ * Limit a TSO burst to prevent it from
+ * overflowing or exceeding the maximum length
+ * allowed by the network interface:
+ */
KASSERT(ipoptlen == 0,
("%s: TSO can't do IP options", __func__));
/*
- * Limit a burst to t_tsomax minus IP,
- * TCP and options length to keep ip->ip_len
- * from overflowing or exceeding the maximum
- * length allowed by the network interface.
+ * Check if we should limit by maximum payload
+ * length:
*/
- if (len > tp->t_tsomax - hdrlen) {
- len = tp->t_tsomax - hdrlen;
- sendalot = 1;
+ if (if_hw_tsomax != 0) {
+ /* compute maximum TSO length */
+ max_len = (if_hw_tsomax - hdrlen);
+ if (max_len <= 0) {
+ len = 0;
+ } else if (len > (u_int)max_len) {
+ sendalot = 1;
+ len = (u_int)max_len;
+ }
+ }
+
+ /*
+ * Check if we should limit by maximum segment
+ * size and count:
+ */
+ if (if_hw_tsomaxsegcount != 0 && if_hw_tsomaxsegsize != 0) {
+ max_len = 0;
+ mb = sbsndmbuf(&so->so_snd, off, &moff);
+
+ while (mb != NULL && (u_int)max_len < len) {
+ u_int cur_length;
+ u_int cur_frags;
+
+ /*
+ * Get length of mbuf fragment
+ * and how many hardware
+ * frags, rounded up, it would
+ * use:
+ */
+ cur_length = (mb->m_len - moff);
+ cur_frags = (cur_length + if_hw_tsomaxsegsize -
+ 1) / if_hw_tsomaxsegsize;
+
+ /* Handle special case: Zero Length Mbuf */
+ if (cur_frags == 0)
+ cur_frags = 1;
+
+ /*
+ * Check if the fragment limit
+ * will be reached or
+ * exceeded:
+ */
+ if (cur_frags >= if_hw_tsomaxsegcount) {
+ max_len += min(cur_length,
+ if_hw_tsomaxsegcount *
+ if_hw_tsomaxsegsize);
+ break;
+ }
+ max_len += cur_length;
+ if_hw_tsomaxsegcount -= cur_frags;
+ moff = 0;
+ mb = mb->m_next;
+ }
+ if (max_len <= 0) {
+ len = 0;
+ } else if (len > (u_int)max_len) {
+ sendalot = 1;
+ len = (u_int)max_len;
+ }
}
/*
* Prevent the last segment from being
- * fractional unless the send sockbuf can
- * be emptied.
+ * fractional unless the send sockbuf can be
+ * emptied:
+ */
+ max_len = (tp->t_maxopd - optlen);
+ if ((off + len) < so->so_snd.sb_cc) {
+ moff = len % (u_int)max_len;
+ if (moff != 0) {
+ len -= moff;
+ sendalot = 1;
+ }
+ }
+
+ /*
+ * In case there are too many small fragments
+ * don't use TSO:
*/
- if (sendalot && off + len < so->so_snd.sb_cc) {
- len -= len % (tp->t_maxopd - optlen);
+ if (len <= (u_int)max_len) {
+ len = (u_int)max_len;
sendalot = 1;
+ tso = 0;
}
/*
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index b8b08cf..7adda33 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -1819,6 +1819,8 @@ tcp_maxmtu(struct in_conninfo *inc, struct tcp_ifcap *cap)
ifp->if_hwassist & CSUM_TSO) {
cap->ifcap |= CSUM_TSO;
cap->tsomax = ifp->if_hw_tsomax;
+ cap->tsomaxsegcount = ifp->if_hw_tsomaxsegcount;
+ cap->tsomaxsegsize = ifp->if_hw_tsomaxsegsize;
}
}
RTFREE(sro.ro_rt);
@@ -1858,6 +1860,8 @@ tcp_maxmtu6(struct in_conninfo *inc, struct tcp_ifcap *cap)
ifp->if_hwassist & CSUM_TSO) {
cap->ifcap |= CSUM_TSO;
cap->tsomax = ifp->if_hw_tsomax;
+ cap->tsomaxsegcount = ifp->if_hw_tsomaxsegcount;
+ cap->tsomaxsegsize = ifp->if_hw_tsomaxsegsize;
}
}
RTFREE(sro6.ro_rt);
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index 5163f6e..c2298fc 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -199,9 +199,12 @@ struct tcpcb {
u_int t_keepintvl; /* interval between keepalives */
u_int t_keepcnt; /* number of keepalives before close */
- u_int t_tsomax; /* tso burst length limit */
+ u_int t_tsomax; /* TSO total burst length limit in bytes */
+
+ uint32_t t_ispare[6]; /* 5 UTO, 1 TBD */
+ uint32_t t_tsomaxsegcount; /* TSO maximum segment count */
+ uint32_t t_tsomaxsegsize; /* TSO maximum segment size in bytes */
- uint32_t t_ispare[8]; /* 5 UTO, 3 TBD */
void *t_pspare2[4]; /* 1 TCP_SIGNATURE, 3 TBD */
uint64_t _pad[6]; /* 6 TBD (1-2 CC/RTT?) */
};
@@ -324,6 +327,8 @@ struct hc_metrics_lite { /* must stay in sync with hc_metrics */
struct tcp_ifcap {
int ifcap;
u_int tsomax;
+ u_int tsomaxsegcount;
+ u_int tsomaxsegsize;
};
#ifndef _NETINET_IN_PCB_H_
diff --git a/sys/netinet/toecore.c b/sys/netinet/toecore.c
index 12f2c38..1ab6c73 100644
--- a/sys/netinet/toecore.c
+++ b/sys/netinet/toecore.c
@@ -329,7 +329,6 @@ toe_syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
{
struct socket *lso = inp->inp_socket;
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
INP_WLOCK_ASSERT(inp);
syncache_add(inc, to, th, inp, &lso, NULL, tod, todctx);
diff --git a/sys/netpfil/ipfw/ip_dn_io.c b/sys/netpfil/ipfw/ip_dn_io.c
index df298ae..b4cb690 100644
--- a/sys/netpfil/ipfw/ip_dn_io.c
+++ b/sys/netpfil/ipfw/ip_dn_io.c
@@ -751,10 +751,15 @@ dummynet_send(struct mbuf *m)
/* extract the dummynet info, rename the tag
* to carry reinject info.
*/
- dst = pkt->dn_dir;
- ifp = pkt->ifp;
- tag->m_tag_cookie = MTAG_IPFW_RULE;
- tag->m_tag_id = 0;
+ if (pkt->dn_dir == (DIR_OUT | PROTO_LAYER2) &&
+ pkt->ifp == NULL) {
+ dst = DIR_DROP;
+ } else {
+ dst = pkt->dn_dir;
+ ifp = pkt->ifp;
+ tag->m_tag_cookie = MTAG_IPFW_RULE;
+ tag->m_tag_id = 0;
+ }
}
switch (dst) {
diff --git a/sys/ofed/drivers/infiniband/hw/mlx4/mad.c b/sys/ofed/drivers/infiniband/hw/mlx4/mad.c
index b35cf1c..74bbf5c 100644
--- a/sys/ofed/drivers/infiniband/hw/mlx4/mad.c
+++ b/sys/ofed/drivers/infiniband/hw/mlx4/mad.c
@@ -1081,7 +1081,7 @@ static void handle_lid_change_event(struct mlx4_ib_dev *dev, u8 port_num)
if (mlx4_is_master(dev->dev) && !dev->sriov.is_going_down)
mlx4_gen_slaves_port_mgt_ev(dev->dev, port_num,
- MLX4_EQ_PORT_INFO_LID_CHANGE_MASK);
+ MLX4_EQ_PORT_INFO_LID_CHANGE_MASK, 0, 0);
}
static void handle_client_rereg_event(struct mlx4_ib_dev *dev, u8 port_num)
@@ -1093,7 +1093,7 @@ static void handle_client_rereg_event(struct mlx4_ib_dev *dev, u8 port_num)
if (!dev->sriov.is_going_down) {
mlx4_ib_mcg_port_cleanup(&dev->sriov.demux[port_num - 1], 0);
mlx4_gen_slaves_port_mgt_ev(dev->dev, port_num,
- MLX4_EQ_PORT_INFO_CLIENT_REREG_MASK);
+ MLX4_EQ_PORT_INFO_CLIENT_REREG_MASK, 0, 0);
}
}
mlx4_ib_dispatch_event(dev, port_num, IB_EVENT_CLIENT_REREGISTER);
@@ -1191,7 +1191,7 @@ void handle_port_mgmt_change_event(struct work_struct *work)
/*if master, notify all slaves*/
if (mlx4_is_master(dev->dev))
mlx4_gen_slaves_port_mgt_ev(dev->dev, port,
- MLX4_EQ_PORT_INFO_GID_PFX_CHANGE_MASK);
+ MLX4_EQ_PORT_INFO_GID_PFX_CHANGE_MASK, 0, 0);
}
if (changed_attr & MLX4_EQ_PORT_INFO_CLIENT_REREG_MASK)
diff --git a/sys/ofed/drivers/infiniband/hw/mlx4/main.c b/sys/ofed/drivers/infiniband/hw/mlx4/main.c
index 1e72826..343b193 100644
--- a/sys/ofed/drivers/infiniband/hw/mlx4/main.c
+++ b/sys/ofed/drivers/infiniband/hw/mlx4/main.c
@@ -1005,7 +1005,7 @@ static int flow_spec_to_net_rule(struct ib_device *dev, struct ib_flow_spec *flo
case IB_FLOW_IB_UC:
spec_l2->id = MLX4_NET_TRANS_RULE_ID_IB;
if(flow_spec->l2_id.ib_uc.qpn) {
- spec_l2->ib.r_u_qpn = cpu_to_be32(flow_spec->l2_id.ib_uc.qpn);
+ spec_l2->ib.l3_qpn = cpu_to_be32(flow_spec->l2_id.ib_uc.qpn);
spec_l2->ib.qpn_msk = cpu_to_be32(0xffffff);
}
break;
@@ -2013,7 +2013,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
for (i = 0; i < ibdev->num_ports; ++i) {
if (mlx4_ib_port_link_layer(&ibdev->ib_dev, i + 1) ==
IB_LINK_LAYER_ETHERNET) {
- err = mlx4_counter_alloc(ibdev->dev, &ibdev->counters[i]);
+ err = mlx4_counter_alloc(ibdev->dev, i + 1, &ibdev->counters[i]);
if (err)
ibdev->counters[i] = -1;
} else
@@ -2112,7 +2112,7 @@ err_steer_qp_release:
err_counter:
for (; i; --i)
if (ibdev->counters[i - 1] != -1)
- mlx4_counter_free(ibdev->dev, ibdev->counters[i - 1]);
+ mlx4_counter_free(ibdev->dev, i, ibdev->counters[i - 1]);
err_map:
iounmap(ibdev->priv_uar.map);
@@ -2200,7 +2200,7 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr)
iounmap(ibdev->priv_uar.map);
for (p = 0; p < ibdev->num_ports; ++p)
if (ibdev->counters[p] != -1)
- mlx4_counter_free(ibdev->dev, ibdev->counters[p]);
+ mlx4_counter_free(ibdev->dev, p + 1, ibdev->counters[p]);
mlx4_foreach_port(p, dev, MLX4_PORT_TYPE_IB)
mlx4_CLOSE_PORT(dev, p);
diff --git a/sys/ofed/drivers/infiniband/hw/mlx4/qp.c b/sys/ofed/drivers/infiniband/hw/mlx4/qp.c
index 4c7d819..c5ebe6b 100644
--- a/sys/ofed/drivers/infiniband/hw/mlx4/qp.c
+++ b/sys/ofed/drivers/infiniband/hw/mlx4/qp.c
@@ -2679,10 +2679,10 @@ static int mlx4_wq_overflow(struct mlx4_ib_wq *wq, int nreq, struct ib_cq *ib_cq
static __be32 convert_access(int acc)
{
- return (acc & IB_ACCESS_REMOTE_ATOMIC ? cpu_to_be32(MLX4_WQE_FMR_PERM_ATOMIC) : 0) |
- (acc & IB_ACCESS_REMOTE_WRITE ? cpu_to_be32(MLX4_WQE_FMR_PERM_REMOTE_WRITE) : 0) |
- (acc & IB_ACCESS_REMOTE_READ ? cpu_to_be32(MLX4_WQE_FMR_PERM_REMOTE_READ) : 0) |
- (acc & IB_ACCESS_LOCAL_WRITE ? cpu_to_be32(MLX4_WQE_FMR_PERM_LOCAL_WRITE) : 0) |
+ return (acc & IB_ACCESS_REMOTE_ATOMIC ? cpu_to_be32(MLX4_WQE_FMR_AND_BIND_PERM_ATOMIC) : 0) |
+ (acc & IB_ACCESS_REMOTE_WRITE ? cpu_to_be32(MLX4_WQE_FMR_AND_BIND_PERM_REMOTE_WRITE) : 0) |
+ (acc & IB_ACCESS_REMOTE_READ ? cpu_to_be32(MLX4_WQE_FMR_AND_BIND_PERM_REMOTE_READ) : 0) |
+ (acc & IB_ACCESS_LOCAL_WRITE ? cpu_to_be32(MLX4_WQE_FMR_PERM_LOCAL_WRITE) : 0) |
cpu_to_be32(MLX4_WQE_FMR_PERM_LOCAL_READ);
}
@@ -2709,10 +2709,12 @@ static void set_fmr_seg(struct mlx4_wqe_fmr_seg *fseg, struct ib_send_wr *wr)
static void set_local_inv_seg(struct mlx4_wqe_local_inval_seg *iseg, u32 rkey)
{
- iseg->flags = 0;
- iseg->mem_key = cpu_to_be32(rkey);
- iseg->guest_id = 0;
- iseg->pa = 0;
+ iseg->mem_key = cpu_to_be32(rkey);
+
+ iseg->reserved1 = 0;
+ iseg->reserved2 = 0;
+ iseg->reserved3[0] = 0;
+ iseg->reserved3[1] = 0;
}
static __always_inline void set_raddr_seg(struct mlx4_wqe_raddr_seg *rseg,
diff --git a/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 339e305..10ac933 100644
--- a/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -240,7 +240,7 @@ ipoib_ib_handle_rx_wc(struct ipoib_dev_priv *priv, struct ib_wc *wc)
*/
if (unlikely(!ipoib_alloc_rx_mb(priv, wr_id))) {
memcpy(&priv->rx_ring[wr_id], &saverx, sizeof(saverx));
- dev->if_iqdrops++;
+ if_inc_counter(dev, IFCOUNTER_IQDROPS, 1);
goto repost;
}
diff --git a/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c b/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 46cd5d1..9f33797 100644
--- a/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -745,7 +745,7 @@ ipoib_vlan_start(struct ifnet *dev)
if (mb == NULL)
break;
m_freem(mb);
- dev->if_oerrors++;
+ if_inc_counter(dev, IFCOUNTER_OERRORS, 1);
}
}
@@ -1452,7 +1452,7 @@ ipoib_input(struct ifnet *ifp, struct mbuf *m)
m->m_flags |= M_BCAST;
else
m->m_flags |= M_MCAST;
- ifp->if_imcasts++;
+ if_inc_counter(ifp, IFCOUNTER_IMCASTS, 1);
}
ipoib_demux(ifp, m, ntohs(eh->proto));
diff --git a/sys/ofed/drivers/net/mlx4/alloc.c b/sys/ofed/drivers/net/mlx4/alloc.c
index b444bbd..da36b34 100644
--- a/sys/ofed/drivers/net/mlx4/alloc.c
+++ b/sys/ofed/drivers/net/mlx4/alloc.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved.
- * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -34,7 +34,7 @@
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/mm.h>
-#include <linux/bitops.h>
+#include <linux/module.h>
#include <linux/dma-mapping.h>
#include <linux/vmalloc.h>
@@ -70,9 +70,9 @@ u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap)
return obj;
}
-void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj)
+void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj, int use_rr)
{
- mlx4_bitmap_free_range(bitmap, obj, 1);
+ mlx4_bitmap_free_range(bitmap, obj, 1, use_rr);
}
static unsigned long find_aligned_range(unsigned long *bitmap,
@@ -148,11 +148,17 @@ u32 mlx4_bitmap_avail(struct mlx4_bitmap *bitmap)
return bitmap->avail;
}
-void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt)
+void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt,
+ int use_rr)
{
obj &= bitmap->max + bitmap->reserved_top - 1;
spin_lock(&bitmap->lock);
+ if (!use_rr) {
+ bitmap->last = min(bitmap->last, obj);
+ bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top)
+ & bitmap->mask;
+ }
bitmap_clear(bitmap->table, obj, cnt);
bitmap->avail += cnt;
spin_unlock(&bitmap->lock);
diff --git a/sys/ofed/drivers/net/mlx4/catas.c b/sys/ofed/drivers/net/mlx4/catas.c
index 185129a..f62c16c 100644
--- a/sys/ofed/drivers/net/mlx4/catas.c
+++ b/sys/ofed/drivers/net/mlx4/catas.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
- * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -34,10 +34,11 @@
#include <linux/workqueue.h>
#include <linux/module.h>
-#include "mlx4.h"
+#include <asm/byteorder.h>
-#define MLX4_CATAS_POLL_INTERVAL (5 * HZ)
+#include "mlx4.h"
+#define MLX4_CATAS_POLL_INTERVAL (5 * HZ)
static DEFINE_SPINLOCK(catas_lock);
@@ -156,11 +157,13 @@ void mlx4_stop_catas_poll(struct mlx4_dev *dev)
del_timer_sync(&priv->catas_err.timer);
- if (priv->catas_err.map)
+ if (priv->catas_err.map) {
iounmap(priv->catas_err.map);
+ priv->catas_err.map = NULL;
+ }
spin_lock_irq(&catas_lock);
- list_del(&priv->catas_err.list);
+ list_del_init(&priv->catas_err.list);
spin_unlock_irq(&catas_lock);
}
diff --git a/sys/ofed/drivers/net/mlx4/cmd.c b/sys/ofed/drivers/net/mlx4/cmd.c
index edbde9c..828009d 100644
--- a/sys/ofed/drivers/net/mlx4/cmd.c
+++ b/sys/ofed/drivers/net/mlx4/cmd.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
- * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005, 2006, 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
* Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -34,14 +34,17 @@
#include <linux/sched.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <linux/pci.h>
#include <linux/errno.h>
#include <linux/mlx4/cmd.h>
+#include <linux/mlx4/device.h>
#include <linux/semaphore.h>
#include <rdma/ib_smi.h>
#include <asm/io.h>
+#include <linux/ktime.h>
#include "mlx4.h"
#include "fw.h"
@@ -110,6 +113,14 @@ enum {
GO_BIT_TIMEOUT_MSECS = 10000
};
+enum mlx4_vlan_transition {
+ MLX4_VLAN_TRANSITION_VST_VST = 0,
+ MLX4_VLAN_TRANSITION_VST_VGT = 1,
+ MLX4_VLAN_TRANSITION_VGT_VST = 2,
+ MLX4_VLAN_TRANSITION_VGT_VGT = 3,
+};
+
+
struct mlx4_cmd_context {
struct completion done;
int result;
@@ -152,6 +163,131 @@ static int mlx4_status_to_errno(u8 status)
return trans_table[status];
}
+static const char *cmd_to_str(u16 cmd)
+{
+ switch (cmd) {
+ case MLX4_CMD_SYS_EN: return "SYS_EN";
+ case MLX4_CMD_SYS_DIS: return "SYS_DIS";
+ case MLX4_CMD_MAP_FA: return "MAP_FA";
+ case MLX4_CMD_UNMAP_FA: return "UNMAP_FA";
+ case MLX4_CMD_RUN_FW: return "RUN_FW";
+ case MLX4_CMD_MOD_STAT_CFG: return "MOD_STAT_CFG";
+ case MLX4_CMD_QUERY_DEV_CAP: return "QUERY_DEV_CAP";
+ case MLX4_CMD_QUERY_FW: return "QUERY_FW";
+ case MLX4_CMD_ENABLE_LAM: return "ENABLE_LAM";
+ case MLX4_CMD_DISABLE_LAM: return "DISABLE_LAM";
+ case MLX4_CMD_QUERY_DDR: return "QUERY_DDR";
+ case MLX4_CMD_QUERY_ADAPTER: return "QUERY_ADAPTER";
+ case MLX4_CMD_INIT_HCA: return "INIT_HCA";
+ case MLX4_CMD_CLOSE_HCA: return "CLOSE_HCA";
+ case MLX4_CMD_INIT_PORT: return "INIT_PORT";
+ case MLX4_CMD_CLOSE_PORT: return "CLOSE_PORT";
+ case MLX4_CMD_QUERY_HCA: return "QUERY_HCA";
+ case MLX4_CMD_QUERY_PORT: return "QUERY_PORT";
+ case MLX4_CMD_SENSE_PORT: return "SENSE_PORT";
+ case MLX4_CMD_HW_HEALTH_CHECK: return "HW_HEALTH_CHECK";
+ case MLX4_CMD_SET_PORT: return "SET_PORT";
+ case MLX4_CMD_SET_NODE: return "SET_NODE";
+ case MLX4_CMD_QUERY_FUNC: return "QUERY_FUNC";
+ case MLX4_CMD_MAP_ICM: return "MAP_ICM";
+ case MLX4_CMD_UNMAP_ICM: return "UNMAP_ICM";
+ case MLX4_CMD_MAP_ICM_AUX: return "MAP_ICM_AUX";
+ case MLX4_CMD_UNMAP_ICM_AUX: return "UNMAP_ICM_AUX";
+ case MLX4_CMD_SET_ICM_SIZE: return "SET_ICM_SIZE";
+ /*master notify fw on finish for slave's flr*/
+ case MLX4_CMD_INFORM_FLR_DONE: return "INFORM_FLR_DONE";
+ case MLX4_CMD_GET_OP_REQ: return "GET_OP_REQ";
+
+ /* TPT commands */
+ case MLX4_CMD_SW2HW_MPT: return "SW2HW_MPT";
+ case MLX4_CMD_QUERY_MPT: return "QUERY_MPT";
+ case MLX4_CMD_HW2SW_MPT: return "HW2SW_MPT";
+ case MLX4_CMD_READ_MTT: return "READ_MTT";
+ case MLX4_CMD_WRITE_MTT: return "WRITE_MTT";
+ case MLX4_CMD_SYNC_TPT: return "SYNC_TPT";
+
+ /* EQ commands */
+ case MLX4_CMD_MAP_EQ: return "MAP_EQ";
+ case MLX4_CMD_SW2HW_EQ: return "SW2HW_EQ";
+ case MLX4_CMD_HW2SW_EQ: return "HW2SW_EQ";
+ case MLX4_CMD_QUERY_EQ: return "QUERY_EQ";
+
+ /* CQ commands */
+ case MLX4_CMD_SW2HW_CQ: return "SW2HW_CQ";
+ case MLX4_CMD_HW2SW_CQ: return "HW2SW_CQ";
+ case MLX4_CMD_QUERY_CQ: return "QUERY_CQ:";
+ case MLX4_CMD_MODIFY_CQ: return "MODIFY_CQ:";
+
+ /* SRQ commands */
+ case MLX4_CMD_SW2HW_SRQ: return "SW2HW_SRQ";
+ case MLX4_CMD_HW2SW_SRQ: return "HW2SW_SRQ";
+ case MLX4_CMD_QUERY_SRQ: return "QUERY_SRQ";
+ case MLX4_CMD_ARM_SRQ: return "ARM_SRQ";
+
+ /* QP/EE commands */
+ case MLX4_CMD_RST2INIT_QP: return "RST2INIT_QP";
+ case MLX4_CMD_INIT2RTR_QP: return "INIT2RTR_QP";
+ case MLX4_CMD_RTR2RTS_QP: return "RTR2RTS_QP";
+ case MLX4_CMD_RTS2RTS_QP: return "RTS2RTS_QP";
+ case MLX4_CMD_SQERR2RTS_QP: return "SQERR2RTS_QP";
+ case MLX4_CMD_2ERR_QP: return "2ERR_QP";
+ case MLX4_CMD_RTS2SQD_QP: return "RTS2SQD_QP";
+ case MLX4_CMD_SQD2SQD_QP: return "SQD2SQD_QP";
+ case MLX4_CMD_SQD2RTS_QP: return "SQD2RTS_QP";
+ case MLX4_CMD_2RST_QP: return "2RST_QP";
+ case MLX4_CMD_QUERY_QP: return "QUERY_QP";
+ case MLX4_CMD_INIT2INIT_QP: return "INIT2INIT_QP";
+ case MLX4_CMD_SUSPEND_QP: return "SUSPEND_QP";
+ case MLX4_CMD_UNSUSPEND_QP: return "UNSUSPEND_QP";
+ /* special QP and management commands */
+ case MLX4_CMD_CONF_SPECIAL_QP: return "CONF_SPECIAL_QP";
+ case MLX4_CMD_MAD_IFC: return "MAD_IFC";
+
+ /* multicast commands */
+ case MLX4_CMD_READ_MCG: return "READ_MCG";
+ case MLX4_CMD_WRITE_MCG: return "WRITE_MCG";
+ case MLX4_CMD_MGID_HASH: return "MGID_HASH";
+
+ /* miscellaneous commands */
+ case MLX4_CMD_DIAG_RPRT: return "DIAG_RPRT";
+ case MLX4_CMD_NOP: return "NOP";
+ case MLX4_CMD_ACCESS_MEM: return "ACCESS_MEM";
+ case MLX4_CMD_SET_VEP: return "SET_VEP";
+
+ /* Ethernet specific commands */
+ case MLX4_CMD_SET_VLAN_FLTR: return "SET_VLAN_FLTR";
+ case MLX4_CMD_SET_MCAST_FLTR: return "SET_MCAST_FLTR";
+ case MLX4_CMD_DUMP_ETH_STATS: return "DUMP_ETH_STATS";
+
+ /* Communication channel commands */
+ case MLX4_CMD_ARM_COMM_CHANNEL: return "ARM_COMM_CHANNEL";
+ case MLX4_CMD_GEN_EQE: return "GEN_EQE";
+
+ /* virtual commands */
+ case MLX4_CMD_ALLOC_RES: return "ALLOC_RES";
+ case MLX4_CMD_FREE_RES: return "FREE_RES";
+ case MLX4_CMD_MCAST_ATTACH: return "MCAST_ATTACH";
+ case MLX4_CMD_UCAST_ATTACH: return "UCAST_ATTACH";
+ case MLX4_CMD_PROMISC: return "PROMISC";
+ case MLX4_CMD_QUERY_FUNC_CAP: return "QUERY_FUNC_CAP";
+ case MLX4_CMD_QP_ATTACH: return "QP_ATTACH";
+
+ /* debug commands */
+ case MLX4_CMD_QUERY_DEBUG_MSG: return "QUERY_DEBUG_MSG";
+ case MLX4_CMD_SET_DEBUG_MSG: return "SET_DEBUG_MSG";
+
+ /* statistics commands */
+ case MLX4_CMD_QUERY_IF_STAT: return "QUERY_IF_STAT";
+ case MLX4_CMD_SET_IF_STAT: return "SET_IF_STAT";
+
+ /* register/delete flow steering network rules */
+ case MLX4_QP_FLOW_STEERING_ATTACH: return "QP_FLOW_STEERING_ATTACH";
+ case MLX4_QP_FLOW_STEERING_DETACH: return "QP_FLOW_STEERING_DETACH";
+ case MLX4_FLOW_STEERING_IB_UC_QP_RANGE: return "FLOW_STEERING_IB_UC_QP_RANGE";
+ default: return "OTHER";
+ }
+}
+
static u8 mlx4_errno_to_status(int errno)
{
switch (errno) {
@@ -244,6 +380,17 @@ static int mlx4_comm_cmd_wait(struct mlx4_dev *dev, u8 op,
down(&cmd->event_sem);
+ end = msecs_to_jiffies(timeout) + jiffies;
+ while (comm_pending(dev) && time_before(jiffies, end))
+ cond_resched();
+ if (comm_pending(dev)) {
+ mlx4_warn(dev, "mlx4_comm_cmd_wait: Comm channel "
+ "is not idle. My toggle is %d (op: 0x%x)\n",
+ mlx4_priv(dev)->cmd.comm_toggle, op);
+ up(&cmd->event_sem);
+ return -EAGAIN;
+ }
+
spin_lock(&cmd->context_lock);
BUG_ON(cmd->free_head < 0);
context = &cmd->context[cmd->free_head];
@@ -255,12 +402,8 @@ static int mlx4_comm_cmd_wait(struct mlx4_dev *dev, u8 op,
mlx4_comm_cmd_post(dev, op, param);
- if (!wait_for_completion_timeout(&context->done,
- msecs_to_jiffies(timeout))) {
- mlx4_warn(dev, "communication channel command 0x%x timed out\n", op);
- err = -EBUSY;
- goto out;
- }
+ /* In slave, wait unconditionally for completion */
+ wait_for_completion(&context->done);
err = context->result;
if (err && context->fw_status != CMD_STAT_MULTI_FUNC_REQ) {
@@ -309,14 +452,29 @@ static int cmd_pending(struct mlx4_dev *dev)
!!(status & swab32(1 << HCR_T_BIT)));
}
-static int mlx4_cmd_post(struct mlx4_dev *dev, u64 in_param, u64 out_param,
- u32 in_modifier, u8 op_modifier, u16 op, u16 token,
- int event)
+static int get_status(struct mlx4_dev *dev, u32 *status, int *go_bit,
+ int *t_bit)
+{
+ if (pci_channel_offline(dev->pdev))
+ return -EIO;
+
+ *status = readl(mlx4_priv(dev)->cmd.hcr + HCR_STATUS_OFFSET);
+ *t_bit = !!(*status & swab32(1 << HCR_T_BIT));
+ *go_bit = !!(*status & swab32(1 << HCR_GO_BIT));
+
+ return 0;
+}
+
+static int mlx4_cmd_post(struct mlx4_dev *dev, struct timespec *ts1,
+ u64 in_param, u64 out_param, u32 in_modifier,
+ u8 op_modifier, u16 op, u16 token, int event)
{
struct mlx4_cmd *cmd = &mlx4_priv(dev)->cmd;
u32 __iomem *hcr = cmd->hcr;
int ret = -EAGAIN;
unsigned long end;
+ int err, go_bit = 0, t_bit = 0;
+ u32 status = 0;
mutex_lock(&cmd->hcr_mutex);
@@ -363,6 +521,9 @@ static int mlx4_cmd_post(struct mlx4_dev *dev, u64 in_param, u64 out_param,
__raw_writel((__force u32) cpu_to_be32(out_param & 0xfffffffful), hcr + 4);
__raw_writel((__force u32) cpu_to_be32(token << 16), hcr + 5);
+ if (ts1)
+ ktime_get_ts(ts1);
+
/* __raw_writel may not order writes. */
wmb();
@@ -383,6 +544,15 @@ static int mlx4_cmd_post(struct mlx4_dev *dev, u64 in_param, u64 out_param,
ret = 0;
out:
+ if (ret) {
+ err = get_status(dev, &status, &go_bit, &t_bit);
+ mlx4_warn(dev, "Could not post command %s (0x%x): ret=%d, "
+ "in_param=0x%llx, in_mod=0x%x, op_mod=0x%x, "
+ "get_status err=%d, status_reg=0x%x, go_bit=%d, "
+ "t_bit=%d, toggle=0x%x\n", cmd_to_str(op), op, ret,
+ (unsigned long long) in_param, in_modifier, op_modifier, err, status,
+ go_bit, t_bit, cmd->toggle);
+ }
mutex_unlock(&cmd->hcr_mutex);
return ret;
}
@@ -439,7 +609,7 @@ static int mlx4_slave_cmd(struct mlx4_dev *dev, u64 in_param, u64 *out_param,
ret = mlx4_status_to_errno(vhcr->status);
} else
mlx4_err(dev, "failed execution of VHCR_POST command"
- "opcode 0x%x\n", op);
+ "opcode %s (0x%x)\n", cmd_to_str(op), op);
}
mutex_unlock(&priv->cmd.slave_cmd_mutex);
@@ -467,7 +637,7 @@ static int mlx4_cmd_poll(struct mlx4_dev *dev, u64 in_param, u64 *out_param,
goto out;
}
- err = mlx4_cmd_post(dev, in_param, out_param ? *out_param : 0,
+ err = mlx4_cmd_post(dev, NULL, in_param, out_param ? *out_param : 0,
in_modifier, op_modifier, op, CMD_POLL_TOKEN, 0);
if (err)
goto out;
@@ -487,7 +657,8 @@ static int mlx4_cmd_poll(struct mlx4_dev *dev, u64 in_param, u64 *out_param,
}
if (cmd_pending(dev)) {
- mlx4_warn(dev, "command 0x%x timed out (go bit not cleared)\n", op);
+ mlx4_warn(dev, "command %s (0x%x) timed out (go bit not cleared)\n",
+ cmd_to_str(op), op);
err = -ETIMEDOUT;
goto out;
}
@@ -502,8 +673,8 @@ static int mlx4_cmd_poll(struct mlx4_dev *dev, u64 in_param, u64 *out_param,
__raw_readl(hcr + HCR_STATUS_OFFSET)) >> 24;
err = mlx4_status_to_errno(stat);
if (err)
- mlx4_err(dev, "command 0x%x failed: fw status = 0x%x\n",
- op, stat);
+ mlx4_err(dev, "command %s (0x%x) failed: fw status = 0x%x\n",
+ cmd_to_str(op), op, stat);
out:
up(&priv->cmd.poll_sem);
@@ -527,19 +698,6 @@ void mlx4_cmd_event(struct mlx4_dev *dev, u16 token, u8 status, u64 out_param)
complete(&context->done);
}
-static int get_status(struct mlx4_dev *dev, u32 *status, int *go_bit,
- int *t_bit)
-{
- if (pci_channel_offline(dev->pdev))
- return -EIO;
-
- *status = readl(mlx4_priv(dev)->cmd.hcr + HCR_STATUS_OFFSET);
- *t_bit = !!(*status & swab32(1 << HCR_T_BIT));
- *go_bit = !!(*status & swab32(1 << HCR_GO_BIT));
-
- return 0;
-}
-
static int mlx4_cmd_wait(struct mlx4_dev *dev, u64 in_param, u64 *out_param,
int out_is_imm, u32 in_modifier, u8 op_modifier,
u16 op, unsigned long timeout)
@@ -549,6 +707,12 @@ static int mlx4_cmd_wait(struct mlx4_dev *dev, u64 in_param, u64 *out_param,
int err = 0;
int go_bit = 0, t_bit = 0, stat_err;
u32 status = 0;
+ struct timespec ts1, ts2;
+ ktime_t t1, t2, delta;
+ s64 ds;
+
+ if (out_is_imm && !out_param)
+ return -EINVAL;
down(&cmd->event_sem);
@@ -561,29 +725,38 @@ static int mlx4_cmd_wait(struct mlx4_dev *dev, u64 in_param, u64 *out_param,
init_completion(&context->done);
- err = mlx4_cmd_post(dev, in_param, out_param ? *out_param : 0,
+ err = mlx4_cmd_post(dev, &ts1, in_param, out_param ? *out_param : 0,
in_modifier, op_modifier, op, context->token, 1);
- if (err) {
- mlx4_warn(dev, "command 0x%x could not be posted (%d)\n",
- op, err);
+ if (err)
goto out;
- }
if (!wait_for_completion_timeout(&context->done,
msecs_to_jiffies(timeout))) {
stat_err = get_status(dev, &status, &go_bit, &t_bit);
- mlx4_warn(dev, "command 0x%x timed out: "
- "get_status err=%d, status=0x%x, go_bit=%d, "
- "t_bit=%d, toggle=0x%x\n", op, stat_err, status,
- go_bit, t_bit, mlx4_priv(dev)->cmd.toggle);
+ mlx4_warn(dev, "command %s (0x%x) timed out: in_param=0x%llx, "
+ "in_mod=0x%x, op_mod=0x%x, get_status err=%d, "
+ "status_reg=0x%x, go_bit=%d, t_bit=%d, toggle=0x%x\n"
+ , cmd_to_str(op), op, (unsigned long long) in_param, in_modifier,
+ op_modifier, stat_err, status, go_bit, t_bit,
+ mlx4_priv(dev)->cmd.toggle);
err = -EBUSY;
goto out;
}
+ if (mlx4_debug_level & MLX4_DEBUG_MASK_CMD_TIME) {
+ ktime_get_ts(&ts2);
+ t1 = timespec_to_ktime(ts1);
+ t2 = timespec_to_ktime(ts2);
+ delta = ktime_sub(t2, t1);
+ ds = ktime_to_ns(delta);
+ pr_info("mlx4: fw exec time for %s is %lld nsec\n", cmd_to_str(op), (long long) ds);
+ }
err = context->result;
if (err) {
- mlx4_err(dev, "command 0x%x failed: fw status = 0x%x\n",
- op, context->fw_status);
+ mlx4_err(dev, "command %s (0x%x) failed: in_param=0x%llx, "
+ "in_mod=0x%x, op_mod=0x%x, fw status = 0x%x\n",
+ cmd_to_str(op), op, (unsigned long long) in_param, in_modifier,
+ op_modifier, context->fw_status);
goto out;
}
@@ -640,7 +813,7 @@ static int mlx4_ACCESS_MEM(struct mlx4_dev *dev, u64 master_addr,
(slave & ~0x7f) | (size & 0xff)) {
mlx4_err(dev, "Bad access mem params - slave_addr:0x%llx "
"master_addr:0x%llx slave_id:%d size:%d\n",
- (long long)slave_addr, (long long)master_addr, slave, size);
+ (unsigned long long) slave_addr, (unsigned long long) master_addr, slave, size);
return -EINVAL;
}
@@ -813,6 +986,24 @@ static int mlx4_MAD_IFC_wrapper(struct mlx4_dev *dev, int slave,
vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE);
}
+static int MLX4_CMD_DIAG_RPRT_wrapper(struct mlx4_dev *dev, int slave,
+ struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox,
+ struct mlx4_cmd_info *cmd)
+{
+ return -EPERM;
+}
+
+static int MLX4_CMD_UPDATE_QP_wrapper(struct mlx4_dev *dev, int slave,
+ struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox,
+ struct mlx4_cmd_info *cmd)
+{
+ return -EPERM;
+}
+
int mlx4_DMA_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_vhcr *vhcr,
struct mlx4_cmd_mailbox *inbox,
@@ -950,6 +1141,16 @@ static struct mlx4_cmd_info cmd_info[] = {
.wrapper = NULL
},
{
+ .opcode = MLX4_CMD_DIAG_RPRT,
+ .has_inbox = false,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .encode_slave_id = false,
+ .skip_err_print = true,
+ .verify = NULL,
+ .wrapper = MLX4_CMD_DIAG_RPRT_wrapper
+ },
+ {
.opcode = MLX4_CMD_NOP,
.has_inbox = false,
.has_outbox = false,
@@ -1247,6 +1448,16 @@ static struct mlx4_cmd_info cmd_info[] = {
.wrapper = mlx4_GEN_QP_wrapper
},
{
+ .opcode = MLX4_CMD_UPDATE_QP,
+ .has_inbox = false,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .encode_slave_id = false,
+ .skip_err_print = true,
+ .verify = NULL,
+ .wrapper = MLX4_CMD_UPDATE_QP_wrapper
+ },
+ {
.opcode = MLX4_CMD_CONF_SPECIAL_QP,
.has_inbox = false,
.has_outbox = false,
@@ -1348,6 +1559,17 @@ static struct mlx4_cmd_info cmd_info[] = {
.verify = NULL,
.wrapper = mlx4_QP_FLOW_STEERING_DETACH_wrapper
},
+ /* wol commands */
+ {
+ .opcode = MLX4_CMD_MOD_STAT_CFG,
+ .has_inbox = false,
+ .has_outbox = false,
+ .out_is_imm = false,
+ .encode_slave_id = false,
+ .skip_err_print = true,
+ .verify = NULL,
+ .wrapper = mlx4_MOD_STAT_CFG_wrapper
+ },
};
static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave,
@@ -1401,8 +1623,8 @@ static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave,
}
}
if (!cmd) {
- mlx4_err(dev, "Unknown command:0x%x accepted from slave:%d\n",
- vhcr->op, slave);
+ mlx4_err(dev, "unparavirt command: %s (0x%x) accepted from slave:%d\n",
+ cmd_to_str(vhcr->op), vhcr->op, slave);
vhcr_cmd->status = CMD_STAT_BAD_PARAM;
goto out_status;
}
@@ -1420,8 +1642,8 @@ static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave,
if (mlx4_ACCESS_MEM(dev, inbox->dma, slave,
vhcr->in_param,
MLX4_MAILBOX_SIZE, 1)) {
- mlx4_err(dev, "%s: Failed reading inbox (cmd:0x%x)\n",
- __func__, cmd->opcode);
+ mlx4_err(dev, "%s: Failed reading inbox for cmd %s (0x%x)\n",
+ __func__, cmd_to_str(cmd->opcode), cmd->opcode);
vhcr_cmd->status = CMD_STAT_INTERNAL_ERR;
goto out_status;
}
@@ -1429,9 +1651,9 @@ static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave,
/* Apply permission and bound checks if applicable */
if (cmd->verify && cmd->verify(dev, slave, vhcr, inbox)) {
- mlx4_warn(dev, "Command:0x%x from slave: %d failed protection "
- "checks for resource_id:%d\n", vhcr->op, slave,
- vhcr->in_modifier);
+ mlx4_warn(dev, "Command %s (0x%x) from slave: %d failed protection "
+ "checks for resource_id: %d\n", cmd_to_str(vhcr->op),
+ vhcr->op, slave, vhcr->in_modifier);
vhcr_cmd->status = CMD_STAT_BAD_OP;
goto out_status;
}
@@ -1470,9 +1692,13 @@ static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave,
}
if (err) {
- mlx4_warn(dev, "vhcr command:0x%x slave:%d failed with"
- " error:%d, status %d\n",
- vhcr->op, slave, vhcr->errno, err);
+ if (!cmd->skip_err_print)
+ mlx4_warn(dev, "vhcr command %s (0x%x) slave:%d "
+ "in_param 0x%llx in_mod=0x%x, op_mod=0x%x "
+ "failed with error:%d, status %d\n",
+ cmd_to_str(vhcr->op), vhcr->op, slave,
+ (unsigned long long) vhcr->in_param, vhcr->in_modifier,
+ vhcr->op_modifier, vhcr->errno, err);
vhcr_cmd->status = mlx4_errno_to_status(err);
goto out_status;
}
@@ -1487,7 +1713,7 @@ static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave,
/* If we failed to write back the outbox after the
*command was successfully executed, we must fail this
* slave, as it is now in undefined state */
- mlx4_err(dev, "%s:Failed writing outbox\n", __func__);
+ mlx4_err(dev, "%s: Failed writing outbox\n", __func__);
goto out;
}
}
@@ -1516,6 +1742,75 @@ out:
return ret;
}
+static int mlx4_master_immediate_activate_vlan_qos(struct mlx4_priv *priv,
+ int slave, int port)
+{
+ struct mlx4_vport_oper_state *vp_oper;
+ struct mlx4_vport_state *vp_admin;
+ struct mlx4_vf_immed_vlan_work *work;
+ int err;
+ int admin_vlan_ix = NO_INDX;
+
+ vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
+ vp_admin = &priv->mfunc.master.vf_admin[slave].vport[port];
+
+ if (vp_oper->state.default_vlan == vp_admin->default_vlan &&
+ vp_oper->state.default_qos == vp_admin->default_qos)
+ return 0;
+
+ work = kzalloc(sizeof(*work), GFP_KERNEL);
+ if (!work)
+ return -ENOMEM;
+
+ if (vp_oper->state.default_vlan != vp_admin->default_vlan) {
+ if (MLX4_VGT != vp_admin->default_vlan) {
+ err = __mlx4_register_vlan(&priv->dev, port,
+ vp_admin->default_vlan,
+ &admin_vlan_ix);
+ if (err) {
+ mlx4_warn((&priv->dev),
+ "No vlan resources slave %d, port %d\n",
+ slave, port);
+ return err;
+ }
+ } else {
+ admin_vlan_ix = NO_INDX;
+ }
+ work->flags |= MLX4_VF_IMMED_VLAN_FLAG_VLAN;
+ mlx4_dbg((&(priv->dev)),
+ "alloc vlan %d idx %d slave %d port %d\n",
+ (int)(vp_admin->default_vlan),
+ admin_vlan_ix, slave, port);
+ }
+
+ /* save original vlan ix and vlan id */
+ work->orig_vlan_id = vp_oper->state.default_vlan;
+ work->orig_vlan_ix = vp_oper->vlan_idx;
+
+ /* handle new qos */
+ if (vp_oper->state.default_qos != vp_admin->default_qos)
+ work->flags |= MLX4_VF_IMMED_VLAN_FLAG_QOS;
+
+ if (work->flags & MLX4_VF_IMMED_VLAN_FLAG_VLAN)
+ vp_oper->vlan_idx = admin_vlan_ix;
+
+ vp_oper->state.default_vlan = vp_admin->default_vlan;
+ vp_oper->state.default_qos = vp_admin->default_qos;
+
+ /* iterate over QPs owned by this slave, using UPDATE_QP */
+ work->port = port;
+ work->slave = slave;
+ work->qos = vp_oper->state.default_qos;
+ work->vlan_id = vp_oper->state.default_vlan;
+ work->vlan_ix = vp_oper->vlan_idx;
+ work->priv = priv;
+ INIT_WORK(&work->work, mlx4_vf_immed_vlan_work_handler);
+ queue_work(priv->mfunc.master.comm_wq, &work->work);
+
+ return 0;
+}
+
+
static int mlx4_master_activate_admin_state(struct mlx4_priv *priv, int slave)
{
int port, err;
@@ -1527,7 +1822,7 @@ static int mlx4_master_activate_admin_state(struct mlx4_priv *priv, int slave)
vp_admin = &priv->mfunc.master.vf_admin[slave].vport[port];
vp_oper->state = *vp_admin;
if (MLX4_VGT != vp_admin->default_vlan) {
- err = mlx4_register_vlan(&priv->dev, port,
+ err = __mlx4_register_vlan(&priv->dev, port,
vp_admin->default_vlan, &(vp_oper->vlan_idx));
if (err) {
vp_oper->vlan_idx = NO_INDX;
@@ -1548,12 +1843,12 @@ static int mlx4_master_activate_admin_state(struct mlx4_priv *priv, int slave)
err = vp_oper->mac_idx;
vp_oper->mac_idx = NO_INDX;
mlx4_warn((&priv->dev),
- "No mac resorces slave %d, port %d\n",
+ "No mac resources slave %d, port %d\n",
slave, port);
return err;
}
mlx4_dbg((&(priv->dev)), "alloc mac %llx idx %d slave %d port %d\n",
- (long long)vp_oper->state.mac, vp_oper->mac_idx, slave, port);
+ (unsigned long long) vp_oper->state.mac, vp_oper->mac_idx, slave, port);
}
}
return 0;
@@ -1599,6 +1894,7 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd,
if (cmd == MLX4_COMM_CMD_RESET) {
mlx4_warn(dev, "Received reset from slave:%d\n", slave);
slave_state[slave].active = false;
+ slave_state[slave].old_vlan_api = false;
mlx4_master_deactivate_admin_state(priv, slave);
for (i = 0; i < MLX4_EVENT_TYPES_NUM; ++i) {
slave_state[slave].event_eq[i].eqn = -1;
@@ -1619,7 +1915,7 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd,
/*command from slave in the middle of FLR*/
if (cmd != MLX4_COMM_CMD_RESET &&
MLX4_COMM_CMD_FLR == slave_state[slave].last_cmd) {
- mlx4_warn(dev, "slave:%d is Trying to run cmd(0x%x) "
+ mlx4_warn(dev, "slave:%d is Trying to run cmd (0x%x) "
"in the middle of FLR\n", slave, cmd);
return;
}
@@ -1630,7 +1926,6 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd,
goto reset_slave;
slave_state[slave].vhcr_dma = ((u64) param) << 48;
priv->mfunc.master.slave_state[slave].cookie = 0;
- mutex_init(&priv->mfunc.master.gen_eqe_mutex[slave]);
break;
case MLX4_COMM_CMD_VHCR1:
if (slave_state[slave].last_cmd != MLX4_COMM_CMD_VHCR0)
@@ -1658,7 +1953,7 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd,
mutex_lock(&priv->cmd.slave_cmd_mutex);
if (mlx4_master_process_vhcr(dev, slave, NULL)) {
- mlx4_err(dev, "Failed processing vhcr for slave:%d,"
+ mlx4_err(dev, "Failed processing vhcr for slave: %d,"
" resetting slave.\n", slave);
mutex_unlock(&priv->cmd.slave_cmd_mutex);
goto reset_slave;
@@ -1666,7 +1961,7 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd,
mutex_unlock(&priv->cmd.slave_cmd_mutex);
break;
default:
- mlx4_warn(dev, "Bad comm cmd:%d from slave:%d\n", cmd, slave);
+ mlx4_warn(dev, "Bad comm cmd: %d from slave: %d\n", cmd, slave);
goto reset_slave;
}
spin_lock_irqsave(&priv->mfunc.master.slave_state_lock, flags);
@@ -1676,8 +1971,8 @@ static void mlx4_master_do_cmd(struct mlx4_dev *dev, int slave, u8 cmd,
is_going_down = 1;
spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags);
if (is_going_down) {
- mlx4_warn(dev, "Slave is going down aborting command(%d)"
- " executing from slave:%d\n",
+ mlx4_warn(dev, "Slave is going down aborting command (%d)"
+ " executing from slave: %d\n",
cmd, slave);
return;
}
@@ -1696,8 +1991,6 @@ reset_slave:
spin_unlock_irqrestore(&priv->mfunc.master.slave_state_lock, flags);
/*with slave in the middle of flr, no need to clean resources again.*/
inform_slave_state:
- memset(&slave_state[slave].event_eq, 0,
- sizeof(struct mlx4_slave_event_eq_info));
__raw_writel((__force u32) cpu_to_be32(reply),
&priv->mfunc.comm[slave].slave_read);
wmb();
@@ -1751,7 +2044,10 @@ void mlx4_master_comm_channel(struct work_struct *work)
comm_cmd >> 16 & 0xff,
comm_cmd & 0xffff, toggle);
++served;
- }
+ } else
+ mlx4_err(dev, "slave %d out of sync."
+ " read toggle %d, write toggle %d.\n", slave, slt,
+ toggle);
}
}
@@ -1759,6 +2055,19 @@ void mlx4_master_comm_channel(struct work_struct *work)
mlx4_warn(dev, "Got command event with bitmask from %d slaves"
" but %d were served\n",
reported, served);
+}
+/* master command processing */
+void mlx4_master_arm_comm_channel(struct work_struct *work)
+{
+ struct mlx4_mfunc_master_ctx *master =
+ container_of(work,
+ struct mlx4_mfunc_master_ctx,
+ arm_comm_work);
+ struct mlx4_mfunc *mfunc =
+ container_of(master, struct mlx4_mfunc, master);
+ struct mlx4_priv *priv =
+ container_of(mfunc, struct mlx4_priv, mfunc);
+ struct mlx4_dev *dev = &priv->dev;
if (mlx4_ARM_COMM_CHANNEL(dev))
mlx4_warn(dev, "Failed to arm comm channel events\n");
@@ -1839,6 +2148,7 @@ int mlx4_multi_func_init(struct mlx4_dev *dev)
for (i = 0; i < dev->num_slaves; ++i) {
s_state = &priv->mfunc.master.slave_state[i];
s_state->last_cmd = MLX4_COMM_CMD_RESET;
+ mutex_init(&priv->mfunc.master.gen_eqe_mutex[i]);
for (j = 0; j < MLX4_EVENT_TYPES_NUM; ++j)
s_state->event_eq[j].eqn = -1;
__raw_writel((__force u32) 0,
@@ -1868,6 +2178,8 @@ int mlx4_multi_func_init(struct mlx4_dev *dev)
priv->mfunc.master.cmd_eqe.type = MLX4_EVENT_TYPE_CMD;
INIT_WORK(&priv->mfunc.master.comm_work,
mlx4_master_comm_channel);
+ INIT_WORK(&priv->mfunc.master.arm_comm_work,
+ mlx4_master_arm_comm_channel);
INIT_WORK(&priv->mfunc.master.slave_event_work,
mlx4_gen_slave_eqe);
INIT_WORK(&priv->mfunc.master.slave_flr_event_work,
@@ -2081,6 +2393,8 @@ struct mlx4_cmd_mailbox *mlx4_alloc_cmd_mailbox(struct mlx4_dev *dev)
return ERR_PTR(-ENOMEM);
}
+ memset(mailbox->buf, 0, MLX4_MAILBOX_SIZE);
+
return mailbox;
}
EXPORT_SYMBOL_GPL(mlx4_alloc_cmd_mailbox);
@@ -2101,23 +2415,32 @@ u32 mlx4_comm_get_version(void)
return ((u32) CMD_CHAN_IF_REV << 8) | (u32) CMD_CHAN_VER;
}
+static int mlx4_get_slave_indx(struct mlx4_dev *dev, int vf)
+{
+ if ((vf < 0) || (vf >= dev->num_vfs)) {
+ mlx4_err(dev, "Bad vf number:%d (number of activated vf: %d)\n", vf, dev->num_vfs);
+ return -EINVAL;
+ }
+ return (vf+1);
+}
+
int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u8 *mac)
{
struct mlx4_priv *priv = mlx4_priv(dev);
struct mlx4_vport_state *s_info;
+ int slave;
if (!mlx4_is_master(dev))
return -EPROTONOSUPPORT;
- if ((vf <= 0) || (vf > dev->num_vfs)) {
- mlx4_err(dev, "Bad vf number:%d (max vf activated: %d)\n", vf, dev->num_vfs);
+ slave = mlx4_get_slave_indx(dev, vf);
+ if (slave < 0)
return -EINVAL;
- }
- s_info = &priv->mfunc.master.vf_admin[vf].vport[port];
+ s_info = &priv->mfunc.master.vf_admin[slave].vport[port];
s_info->mac = mlx4_mac_to_u64(mac);
mlx4_info(dev, "default mac on vf %d port %d to %llX will take afect only after vf restart\n",
- vf, port, (long long)s_info->mac);
+ vf, port, (unsigned long long) s_info->mac);
return 0;
}
EXPORT_SYMBOL_GPL(mlx4_set_vf_mac);
@@ -2125,40 +2448,145 @@ EXPORT_SYMBOL_GPL(mlx4_set_vf_mac);
int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos)
{
struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_vport_state *s_info;
+ struct mlx4_vport_oper_state *vf_oper;
+ struct mlx4_vport_state *vf_admin;
+ int slave;
if ((!mlx4_is_master(dev)) ||
- !(dev->caps.flags & MLX4_DEV_CAP_FLAG_ESWITCH_SUPPORT))
+ !(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_VLAN_CONTROL))
return -EPROTONOSUPPORT;
- if ((vf <= 0) || (vf > dev->num_vfs) || (vlan > 4095) || (qos > 7))
+ if ((vlan > 4095) || (qos > 7))
+ return -EINVAL;
+
+ slave = mlx4_get_slave_indx(dev, vf);
+ if (slave < 0)
return -EINVAL;
- s_info = &priv->mfunc.master.vf_admin[vf].vport[port];
+ vf_admin = &priv->mfunc.master.vf_admin[slave].vport[port];
+ vf_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
+
if ((0 == vlan) && (0 == qos))
- s_info->default_vlan = MLX4_VGT;
+ vf_admin->default_vlan = MLX4_VGT;
else
- s_info->default_vlan = vlan;
- s_info->default_qos = qos;
+ vf_admin->default_vlan = vlan;
+ vf_admin->default_qos = qos;
+
+ if (priv->mfunc.master.slave_state[slave].active &&
+ dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_UPDATE_QP) {
+ mlx4_info(dev, "updating vf %d port %d config params immediately\n",
+ vf, port);
+ mlx4_master_immediate_activate_vlan_qos(priv, slave, port);
+ }
return 0;
}
EXPORT_SYMBOL_GPL(mlx4_set_vf_vlan);
+ /* mlx4_get_slave_default_vlan -
+ * retrun true if VST ( default vlan)
+ * if VST will fill vlan & qos (if not NULL) */
+bool mlx4_get_slave_default_vlan(struct mlx4_dev *dev, int port, int slave, u16 *vlan, u8 *qos)
+{
+ struct mlx4_vport_oper_state *vp_oper;
+ struct mlx4_priv *priv;
+
+ priv = mlx4_priv(dev);
+ vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
+
+ if (MLX4_VGT != vp_oper->state.default_vlan) {
+ if (vlan)
+ *vlan = vp_oper->state.default_vlan;
+ if (qos)
+ *qos = vp_oper->state.default_qos;
+ return true;
+ }
+ return false;
+}
+EXPORT_SYMBOL_GPL(mlx4_get_slave_default_vlan);
+
int mlx4_set_vf_spoofchk(struct mlx4_dev *dev, int port, int vf, bool setting)
{
struct mlx4_priv *priv = mlx4_priv(dev);
struct mlx4_vport_state *s_info;
+ int slave;
if ((!mlx4_is_master(dev)) ||
- !(dev->caps.flags & MLX4_DEV_CAP_FLAG_ESWITCH_SUPPORT))
+ !(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_FSM))
return -EPROTONOSUPPORT;
- if ((vf <= 0) || (vf > dev->num_vfs))
+ slave = mlx4_get_slave_indx(dev, vf);
+ if (slave < 0)
return -EINVAL;
- s_info = &priv->mfunc.master.vf_admin[vf].vport[port];
+ s_info = &priv->mfunc.master.vf_admin[slave].vport[port];
s_info->spoofchk = setting;
return 0;
}
EXPORT_SYMBOL_GPL(mlx4_set_vf_spoofchk);
+
+int mlx4_set_vf_link_state(struct mlx4_dev *dev, int port, int vf, int link_state)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ struct mlx4_vport_state *s_info;
+ struct mlx4_vport_oper_state *vp_oper;
+ int slave;
+ u8 link_stat_event;
+
+ slave = mlx4_get_slave_indx(dev, vf);
+ if (slave < 0)
+ return -EINVAL;
+
+ switch (link_state) {
+ case IFLA_VF_LINK_STATE_AUTO:
+ /* get link curent state */
+ if (!priv->sense.do_sense_port[port])
+ link_stat_event = MLX4_PORT_CHANGE_SUBTYPE_ACTIVE;
+ else
+ link_stat_event = MLX4_PORT_CHANGE_SUBTYPE_DOWN;
+ break;
+
+ case IFLA_VF_LINK_STATE_ENABLE:
+ link_stat_event = MLX4_PORT_CHANGE_SUBTYPE_ACTIVE;
+ break;
+
+ case IFLA_VF_LINK_STATE_DISABLE:
+ link_stat_event = MLX4_PORT_CHANGE_SUBTYPE_DOWN;
+ break;
+
+ default:
+ mlx4_warn(dev, "unknown value for link_state %02x on slave %d port %d\n",
+ link_state, slave, port);
+ return -EINVAL;
+ };
+ /* update the admin & oper state on the link state */
+ s_info = &priv->mfunc.master.vf_admin[slave].vport[port];
+ vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
+ s_info->link_state = link_state;
+ vp_oper->state.link_state = link_state;
+
+ /* send event */
+ mlx4_gen_port_state_change_eqe(dev, slave, port, link_stat_event);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mlx4_set_vf_link_state);
+
+int mlx4_get_vf_link_state(struct mlx4_dev *dev, int port, int vf)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ struct mlx4_vport_state *s_info;
+ int slave;
+
+ if (!mlx4_is_master(dev))
+ return -EPROTONOSUPPORT;
+
+ slave = mlx4_get_slave_indx(dev, vf);
+ if (slave < 0)
+ return -EINVAL;
+
+ s_info = &priv->mfunc.master.vf_admin[slave].vport[port];
+
+ return s_info->link_state;
+}
+EXPORT_SYMBOL_GPL(mlx4_get_vf_link_state);
+
diff --git a/sys/ofed/drivers/net/mlx4/cq.c b/sys/ofed/drivers/net/mlx4/cq.c
index f87025a..b133ae6 100644
--- a/sys/ofed/drivers/net/mlx4/cq.c
+++ b/sys/ofed/drivers/net/mlx4/cq.c
@@ -2,7 +2,7 @@
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. All rights reserved.
- * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005, 2006, 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
* Copyright (c) 2004 Voltaire, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -35,7 +35,7 @@
*/
#include <linux/hardirq.h>
-
+#include <linux/module.h>
#include <linux/mlx4/cmd.h>
#include <linux/mlx4/cq.h>
@@ -56,12 +56,14 @@ void mlx4_cq_completion(struct mlx4_dev *dev, u32 cqn)
struct mlx4_cq_table *cq_table = &mlx4_priv(dev)->cq_table;
struct mlx4_cq *cq;
- spin_lock(&cq_table->lock);
+ read_lock(&cq_table->cq_table_lock);
+
cq = radix_tree_lookup(&mlx4_priv(dev)->cq_table.tree,
cqn & (dev->caps.num_cqs - 1));
if (cq)
atomic_inc(&cq->refcount);
- spin_unlock(&cq_table->lock);
+
+ read_unlock(&cq_table->cq_table_lock);
if (!cq) {
mlx4_dbg(dev, "Completion event for bogus CQ %08x\n", cqn);
@@ -81,13 +83,13 @@ void mlx4_cq_event(struct mlx4_dev *dev, u32 cqn, int event_type)
struct mlx4_cq_table *cq_table = &mlx4_priv(dev)->cq_table;
struct mlx4_cq *cq;
- spin_lock(&cq_table->lock);
+ read_lock(&cq_table->cq_table_lock);
cq = radix_tree_lookup(&cq_table->tree, cqn & (dev->caps.num_cqs - 1));
if (cq)
atomic_inc(&cq->refcount);
- spin_unlock(&cq_table->lock);
+ read_unlock(&cq_table->cq_table_lock);
if (!cq) {
mlx4_warn(dev, "Async event for bogus CQ %08x\n", cqn);
@@ -220,7 +222,7 @@ err_put:
mlx4_table_put(dev, &cq_table->table, *cqn);
err_out:
- mlx4_bitmap_free(&cq_table->bitmap, *cqn);
+ mlx4_bitmap_free(&cq_table->bitmap, *cqn, MLX4_NO_RR);
return err;
}
@@ -250,7 +252,7 @@ void __mlx4_cq_free_icm(struct mlx4_dev *dev, int cqn)
mlx4_table_put(dev, &cq_table->cmpt_table, cqn);
mlx4_table_put(dev, &cq_table->table, cqn);
- mlx4_bitmap_free(&cq_table->bitmap, cqn);
+ mlx4_bitmap_free(&cq_table->bitmap, cqn, MLX4_NO_RR);
}
static void mlx4_cq_free_icm(struct mlx4_dev *dev, int cqn)
@@ -269,23 +271,6 @@ static void mlx4_cq_free_icm(struct mlx4_dev *dev, int cqn)
__mlx4_cq_free_icm(dev, cqn);
}
-static int mlx4_find_least_loaded_vector(struct mlx4_priv *priv)
-{
- int i;
- int index = 0;
- int min = priv->eq_table.eq[0].load;
-
- for (i = 1; i < priv->dev.caps.num_comp_vectors; i++) {
- if (priv->eq_table.eq[i].load < min) {
- index = i;
- min = priv->eq_table.eq[i].load;
- }
- }
-
- return index;
-}
-
-
int mlx4_cq_alloc(struct mlx4_dev *dev, int nent,
struct mlx4_mtt *mtt, struct mlx4_uar *uar, u64 db_rec,
struct mlx4_cq *cq, unsigned vector, int collapsed,
@@ -298,24 +283,20 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent,
u64 mtt_addr;
int err;
- cq->vector = (vector == MLX4_LEAST_ATTACHED_VECTOR) ?
- mlx4_find_least_loaded_vector(priv) : vector;
-
- if (cq->vector > dev->caps.num_comp_vectors + dev->caps.comp_pool) {
+ if (vector > dev->caps.num_comp_vectors + dev->caps.comp_pool)
return -EINVAL;
- }
+
+ cq->vector = vector;
err = mlx4_cq_alloc_icm(dev, &cq->cqn);
- if (err) {
+ if (err)
return err;
- }
spin_lock_irq(&cq_table->lock);
err = radix_tree_insert(&cq_table->tree, cq->cqn, cq);
spin_unlock_irq(&cq_table->lock);
- if (err){
+ if (err)
goto err_icm;
- }
mailbox = mlx4_alloc_cmd_mailbox(dev);
if (IS_ERR(mailbox)) {
@@ -331,7 +312,7 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent,
cq_context->flags |= cpu_to_be32(1 << 19);
cq_context->logsize_usrpage = cpu_to_be32((ilog2(nent) << 24) | uar->index);
- cq_context->comp_eqn = priv->eq_table.eq[cq->vector].eqn;
+ cq_context->comp_eqn = priv->eq_table.eq[vector].eqn;
cq_context->log_page_size = mtt->page_shift - MLX4_ICM_PAGE_SHIFT;
mtt_addr = mlx4_mtt_addr(dev, mtt);
@@ -344,7 +325,6 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent,
if (err)
goto err_radix;
- priv->eq_table.eq[cq->vector].load++;
cq->cons_index = 0;
cq->arm_sn = 1;
cq->uar = uar;
@@ -378,8 +358,6 @@ void mlx4_cq_free(struct mlx4_dev *dev, struct mlx4_cq *cq)
if (err)
mlx4_warn(dev, "HW2SW_CQ failed (%d) for CQN %06x\n", err, cq->cqn);
-
- priv->eq_table.eq[cq->vector].load--;
synchronize_irq(priv->eq_table.eq[cq->vector].irq);
spin_lock_irq(&cq_table->lock);
@@ -400,6 +378,7 @@ int mlx4_init_cq_table(struct mlx4_dev *dev)
int err;
spin_lock_init(&cq_table->lock);
+ rwlock_init(&cq_table->cq_table_lock);
INIT_RADIX_TREE(&cq_table->tree, GFP_ATOMIC);
if (mlx4_is_slave(dev))
return 0;
diff --git a/sys/ofed/drivers/net/mlx4/en_cq.c b/sys/ofed/drivers/net/mlx4/en_cq.c
index 9783e23..be043ce 100644
--- a/sys/ofed/drivers/net/mlx4/en_cq.c
+++ b/sys/ofed/drivers/net/mlx4/en_cq.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2007, 2014 Mellanox Technologies. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -31,12 +31,13 @@
*
*/
-#include "mlx4_en.h"
-
#include <linux/mlx4/cq.h>
#include <linux/mlx4/qp.h>
#include <linux/mlx4/cmd.h>
+#include "mlx4_en.h"
+
+
static void mlx4_en_cq_event(struct mlx4_cq *cq, enum mlx4_event event)
{
return;
@@ -44,52 +45,72 @@ static void mlx4_en_cq_event(struct mlx4_cq *cq, enum mlx4_event event)
int mlx4_en_create_cq(struct mlx4_en_priv *priv,
- struct mlx4_en_cq *cq,
- int entries, int ring, enum cq_type mode)
+ struct mlx4_en_cq **pcq,
+ int entries, int ring, enum cq_type mode,
+ int node)
{
struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_en_cq *cq;
int err;
+ cq = kzalloc_node(sizeof(struct mlx4_en_cq), GFP_KERNEL, node);
+ if (!cq) {
+ cq = kzalloc(sizeof(struct mlx4_en_cq), GFP_KERNEL);
+ if (!cq) {
+ en_err(priv, "Failed to allocate CW struture\n");
+ return -ENOMEM;
+ }
+ }
+
cq->size = entries;
+ cq->buf_size = cq->size * mdev->dev->caps.cqe_size;
+
cq->tq = taskqueue_create_fast("mlx4_en_que", M_NOWAIT,
- taskqueue_thread_enqueue, &cq->tq);
- if (mode == RX) {
- cq->buf_size = cq->size * sizeof(struct mlx4_cqe);
- cq->vector = (ring + priv->port) %
- mdev->dev->caps.num_comp_vectors;
+ taskqueue_thread_enqueue, &cq->tq);
+ if (mode == RX) {
TASK_INIT(&cq->cq_task, 0, mlx4_en_rx_que, cq);
taskqueue_start_threads(&cq->tq, 1, PI_NET, "%s rx cq",
- if_name(priv->dev));
+ if_name(priv->dev));
+
} else {
- cq->buf_size = sizeof(struct mlx4_cqe);
- cq->vector = MLX4_LEAST_ATTACHED_VECTOR;
TASK_INIT(&cq->cq_task, 0, mlx4_en_tx_que, cq);
taskqueue_start_threads(&cq->tq, 1, PI_NET, "%s tx cq",
- if_name(priv->dev));
+ if_name(priv->dev));
}
cq->ring = ring;
cq->is_tx = mode;
- mtx_init(&cq->lock.m, "mlx4 cq", NULL, MTX_DEF);
+ spin_lock_init(&cq->lock);
err = mlx4_alloc_hwq_res(mdev->dev, &cq->wqres,
cq->buf_size, 2 * PAGE_SIZE);
if (err)
- return err;
+ goto err_cq;
err = mlx4_en_map_buffer(&cq->wqres.buf);
if (err)
- mlx4_free_hwq_res(mdev->dev, &cq->wqres, cq->buf_size);
- else
- cq->buf = (struct mlx4_cqe *) cq->wqres.buf.direct.buf;
+ goto err_res;
+
+ cq->buf = (struct mlx4_cqe *) cq->wqres.buf.direct.buf;
+ *pcq = cq;
+ return 0;
+
+err_res:
+ mlx4_free_hwq_res(mdev->dev, &cq->wqres, cq->buf_size);
+err_cq:
+ kfree(cq);
return err;
}
-int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
+
+int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
+ int cq_idx)
{
struct mlx4_en_dev *mdev = priv->mdev;
- int err;
+ int err = 0;
+ char name[25];
+ int timestamp_en = 0;
cq->dev = mdev->pndev[priv->port];
cq->mcq.set_ci_db = cq->wqres.db.db;
@@ -98,52 +119,83 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
*cq->mcq.arm_db = 0;
memset(cq->buf, 0, cq->buf_size);
- if (!cq->is_tx)
- cq->size = priv->rx_ring[cq->ring].actual_size;
-
+ if (cq->is_tx == RX) {
+ if (mdev->dev->caps.comp_pool) {
+ if (!cq->vector) {
+ sprintf(name, "%s-%d", if_name(priv->dev),
+ cq->ring);
+ /* Set IRQ for specific name (per ring) */
+ if (mlx4_assign_eq(mdev->dev, name, &cq->vector)) {
+ cq->vector = (cq->ring + 1 + priv->port)
+ % mdev->dev->caps.num_comp_vectors;
+ mlx4_warn(mdev, "Failed Assigning an EQ to "
+ "%s ,Falling back to legacy EQ's\n",
+ name);
+ }
+ }
+ } else {
+ cq->vector = (cq->ring + 1 + priv->port) %
+ mdev->dev->caps.num_comp_vectors;
+ }
+ } else {
+ struct mlx4_en_cq *rx_cq;
+ /*
+ * For TX we use the same irq per
+ * ring we assigned for the RX
+ */
+ cq_idx = cq_idx % priv->rx_ring_num;
+ rx_cq = priv->rx_cq[cq_idx];
+ cq->vector = rx_cq->vector;
+ }
- err = mlx4_cq_alloc(mdev->dev, cq->size, &cq->wqres.mtt, &mdev->priv_uar,
- cq->wqres.db.dma, &cq->mcq, cq->vector, cq->is_tx, 0);
- if (err) {
+ if (!cq->is_tx)
+ cq->size = priv->rx_ring[cq->ring]->actual_size;
+ err = mlx4_cq_alloc(mdev->dev, cq->size, &cq->wqres.mtt,
+ &mdev->priv_uar, cq->wqres.db.dma, &cq->mcq,
+ cq->vector, 0, timestamp_en);
+ if (err)
return err;
- }
cq->mcq.comp = cq->is_tx ? mlx4_en_tx_irq : mlx4_en_rx_irq;
cq->mcq.event = mlx4_en_cq_event;
- if (cq->is_tx) {
- init_timer(&cq->timer);
- cq->timer.function = mlx4_en_poll_tx_cq;
- cq->timer.data = (unsigned long) cq;
- }
+ if (cq->is_tx) {
+ init_timer(&cq->timer);
+ cq->timer.function = mlx4_en_poll_tx_cq;
+ cq->timer.data = (unsigned long) cq;
+ }
+
return 0;
}
-void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
+void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq **pcq)
{
struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_en_cq *cq = *pcq;
taskqueue_drain(cq->tq, &cq->cq_task);
taskqueue_free(cq->tq);
mlx4_en_unmap_buffer(&cq->wqres.buf);
mlx4_free_hwq_res(mdev->dev, &cq->wqres, cq->buf_size);
- cq->buf_size = 0;
- cq->buf = NULL;
- mtx_destroy(&cq->lock.m);
+ if (priv->mdev->dev->caps.comp_pool && cq->vector)
+ mlx4_release_eq(priv->mdev->dev, cq->vector);
+ kfree(cq);
+ *pcq = NULL;
}
void mlx4_en_deactivate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
{
- struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_en_dev *mdev = priv->mdev;
- taskqueue_drain(cq->tq, &cq->cq_task);
- if (cq->is_tx)
- del_timer(&cq->timer);
+ taskqueue_drain(cq->tq, &cq->cq_task);
+ if (cq->is_tx)
+ del_timer(&cq->timer);
- mlx4_cq_free(mdev->dev, &cq->mcq);
+ mlx4_cq_free(mdev->dev, &cq->mcq);
}
+
/* Set rx cq moderation parameters */
int mlx4_en_set_cq_moder(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
{
diff --git a/sys/ofed/drivers/net/mlx4/en_ethtool.c b/sys/ofed/drivers/net/mlx4/en_ethtool.c
index 9279944..6569a53 100644
--- a/sys/ofed/drivers/net/mlx4/en_ethtool.c
+++ b/sys/ofed/drivers/net/mlx4/en_ethtool.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2007, 2014 Mellanox Technologies. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -34,26 +34,57 @@
#include <linux/kernel.h>
#include <linux/ethtool.h>
#include <linux/netdevice.h>
-#include <linux/if_vlan.h>
+#include <linux/mlx4/driver.h>
+#include <linux/in.h>
+#include <net/ip.h>
+#include <linux/bitmap.h>
#include "mlx4_en.h"
#include "en_port.h"
+#define EN_ETHTOOL_QP_ATTACH (1ull << 63)
+
+union mlx4_ethtool_flow_union {
+ struct ethtool_tcpip4_spec tcp_ip4_spec;
+ struct ethtool_tcpip4_spec udp_ip4_spec;
+ struct ethtool_tcpip4_spec sctp_ip4_spec;
+ struct ethtool_ah_espip4_spec ah_ip4_spec;
+ struct ethtool_ah_espip4_spec esp_ip4_spec;
+ struct ethtool_usrip4_spec usr_ip4_spec;
+ struct ethhdr ether_spec;
+ __u8 hdata[52];
+};
-static void mlx4_en_update_lro_stats(struct mlx4_en_priv *priv)
-{
- int i;
+struct mlx4_ethtool_flow_ext {
+ __u8 padding[2];
+ unsigned char h_dest[ETH_ALEN];
+ __be16 vlan_etype;
+ __be16 vlan_tci;
+ __be32 data[2];
+};
- priv->port_stats.lro_aggregated = 0;
- priv->port_stats.lro_flushed = 0;
- priv->port_stats.lro_no_desc = 0;
+struct mlx4_ethtool_rx_flow_spec {
+ __u32 flow_type;
+ union mlx4_ethtool_flow_union h_u;
+ struct mlx4_ethtool_flow_ext h_ext;
+ union mlx4_ethtool_flow_union m_u;
+ struct mlx4_ethtool_flow_ext m_ext;
+ __u64 ring_cookie;
+ __u32 location;
+};
- for (i = 0; i < priv->rx_ring_num; i++) {
- priv->port_stats.lro_aggregated += priv->rx_ring[i].lro.stats.aggregated;
- priv->port_stats.lro_flushed += priv->rx_ring[i].lro.stats.flushed;
- priv->port_stats.lro_no_desc += priv->rx_ring[i].lro.stats.no_desc;
- }
-}
+struct mlx4_ethtool_rxnfc {
+ __u32 cmd;
+ __u32 flow_type;
+ __u64 data;
+ struct mlx4_ethtool_rx_flow_spec fs;
+ __u32 rule_cnt;
+ __u32 rule_locs[0];
+};
+
+#ifndef FLOW_MAC_EXT
+#define FLOW_MAC_EXT 0x40000000
+#endif
static void
mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
@@ -61,104 +92,142 @@ mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
struct mlx4_en_priv *priv = netdev_priv(dev);
struct mlx4_en_dev *mdev = priv->mdev;
- sprintf(drvinfo->driver, DRV_NAME " (%s)", mdev->dev->board_id);
- strncpy(drvinfo->version, DRV_VERSION " (" DRV_RELDATE ")", 32);
- sprintf(drvinfo->fw_version, "%d.%d.%d",
+ strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
+ strlcpy(drvinfo->version, DRV_VERSION " (" DRV_RELDATE ")",
+ sizeof(drvinfo->version));
+ snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
+ "%d.%d.%d",
(u16) (mdev->dev->caps.fw_ver >> 32),
(u16) ((mdev->dev->caps.fw_ver >> 16) & 0xffff),
(u16) (mdev->dev->caps.fw_ver & 0xffff));
- strncpy(drvinfo->bus_info, pci_name(mdev->dev->pdev), 32);
+ strlcpy(drvinfo->bus_info, pci_name(mdev->dev->pdev),
+ sizeof(drvinfo->bus_info));
drvinfo->n_stats = 0;
drvinfo->regdump_len = 0;
drvinfo->eedump_len = 0;
}
-static u32 mlx4_en_get_tso(struct net_device *dev)
-{
- return (dev->features & NETIF_F_TSO) != 0;
-}
-
-static int mlx4_en_set_tso(struct net_device *dev, u32 data)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
-
- if (data) {
- if (!priv->mdev->LSO_support)
- return -EPERM;
- dev->features |= (NETIF_F_TSO | NETIF_F_TSO6);
-#ifdef HAVE_NETDEV_VLAN_FEATURES
- dev->vlan_features |= (NETIF_F_TSO | NETIF_F_TSO6);
-#else
- if (priv->vlgrp) {
- int i;
- struct net_device *vdev;
- for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
- vdev = vlan_group_get_device(priv->vlgrp, i);
- if (vdev) {
- vdev->features |= (NETIF_F_TSO | NETIF_F_TSO6);
- vlan_group_set_device(priv->vlgrp, i, vdev);
- }
- }
- }
-#endif
- } else {
- dev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
-#ifdef HAVE_NETDEV_VLAN_FEATURES
- dev->vlan_features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
-#else
- if (priv->vlgrp) {
- int i;
- struct net_device *vdev;
- for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
- vdev = vlan_group_get_device(priv->vlgrp, i);
- if (vdev) {
- vdev->features &= ~(NETIF_F_TSO | NETIF_F_TSO6);
- vlan_group_set_device(priv->vlgrp, i, vdev);
- }
- }
- }
-#endif
- }
- return 0;
-}
-
-static u32 mlx4_en_get_rx_csum(struct net_device *dev)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- return priv->rx_csum;
-}
-
-static int mlx4_en_set_rx_csum(struct net_device *dev, u32 data)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- priv->rx_csum = (data != 0);
- return 0;
-}
-
static const char main_strings[][ETH_GSTRING_LEN] = {
- "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors",
- "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions",
- "rx_length_errors", "rx_over_errors", "rx_crc_errors",
- "rx_frame_errors", "rx_fifo_errors", "rx_missed_errors",
- "tx_aborted_errors", "tx_carrier_errors", "tx_fifo_errors",
- "tx_heartbeat_errors", "tx_window_errors",
+ /* packet statistics */
+ "rx_packets",
+ "rx_bytes",
+ "rx_multicast_packets",
+ "rx_broadcast_packets",
+ "rx_errors",
+ "rx_dropped",
+ "rx_length_errors",
+ "rx_over_errors",
+ "rx_crc_errors",
+ "rx_jabbers",
+ "rx_in_range_length_error",
+ "rx_out_range_length_error",
+ "rx_lt_64_bytes_packets",
+ "rx_127_bytes_packets",
+ "rx_255_bytes_packets",
+ "rx_511_bytes_packets",
+ "rx_1023_bytes_packets",
+ "rx_1518_bytes_packets",
+ "rx_1522_bytes_packets",
+ "rx_1548_bytes_packets",
+ "rx_gt_1548_bytes_packets",
+ "tx_packets",
+ "tx_bytes",
+ "tx_multicast_packets",
+ "tx_broadcast_packets",
+ "tx_errors",
+ "tx_dropped",
+ "tx_lt_64_bytes_packets",
+ "tx_127_bytes_packets",
+ "tx_255_bytes_packets",
+ "tx_511_bytes_packets",
+ "tx_1023_bytes_packets",
+ "tx_1518_bytes_packets",
+ "tx_1522_bytes_packets",
+ "tx_1548_bytes_packets",
+ "tx_gt_1548_bytes_packets",
+ "rx_prio_0_packets", "rx_prio_0_bytes",
+ "rx_prio_1_packets", "rx_prio_1_bytes",
+ "rx_prio_2_packets", "rx_prio_2_bytes",
+ "rx_prio_3_packets", "rx_prio_3_bytes",
+ "rx_prio_4_packets", "rx_prio_4_bytes",
+ "rx_prio_5_packets", "rx_prio_5_bytes",
+ "rx_prio_6_packets", "rx_prio_6_bytes",
+ "rx_prio_7_packets", "rx_prio_7_bytes",
+ "rx_novlan_packets", "rx_novlan_bytes",
+ "tx_prio_0_packets", "tx_prio_0_bytes",
+ "tx_prio_1_packets", "tx_prio_1_bytes",
+ "tx_prio_2_packets", "tx_prio_2_bytes",
+ "tx_prio_3_packets", "tx_prio_3_bytes",
+ "tx_prio_4_packets", "tx_prio_4_bytes",
+ "tx_prio_5_packets", "tx_prio_5_bytes",
+ "tx_prio_6_packets", "tx_prio_6_bytes",
+ "tx_prio_7_packets", "tx_prio_7_bytes",
+ "tx_novlan_packets", "tx_novlan_bytes",
+
+ /* flow control statistics */
+ "rx_pause_prio_0", "rx_pause_duration_prio_0",
+ "rx_pause_transition_prio_0", "tx_pause_prio_0",
+ "tx_pause_duration_prio_0", "tx_pause_transition_prio_0",
+ "rx_pause_prio_1", "rx_pause_duration_prio_1",
+ "rx_pause_transition_prio_1", "tx_pause_prio_1",
+ "tx_pause_duration_prio_1", "tx_pause_transition_prio_1",
+ "rx_pause_prio_2", "rx_pause_duration_prio_2",
+ "rx_pause_transition_prio_2", "tx_pause_prio_2",
+ "tx_pause_duration_prio_2", "tx_pause_transition_prio_2",
+ "rx_pause_prio_3", "rx_pause_duration_prio_3",
+ "rx_pause_transition_prio_3", "tx_pause_prio_3",
+ "tx_pause_duration_prio_3", "tx_pause_transition_prio_3",
+ "rx_pause_prio_4", "rx_pause_duration_prio_4",
+ "rx_pause_transition_prio_4", "tx_pause_prio_4",
+ "tx_pause_duration_prio_4", "tx_pause_transition_prio_4",
+ "rx_pause_prio_5", "rx_pause_duration_prio_5",
+ "rx_pause_transition_prio_5", "tx_pause_prio_5",
+ "tx_pause_duration_prio_5", "tx_pause_transition_prio_5",
+ "rx_pause_prio_6", "rx_pause_duration_prio_6",
+ "rx_pause_transition_prio_6", "tx_pause_prio_6",
+ "tx_pause_duration_prio_6", "tx_pause_transition_prio_6",
+ "rx_pause_prio_7", "rx_pause_duration_prio_7",
+ "rx_pause_transition_prio_7", "tx_pause_prio_7",
+ "tx_pause_duration_prio_7", "tx_pause_transition_prio_7",
+
+ /* VF statistics */
+ "rx_packets",
+ "rx_bytes",
+ "rx_multicast_packets",
+ "rx_broadcast_packets",
+ "rx_errors",
+ "rx_dropped",
+ "tx_packets",
+ "tx_bytes",
+ "tx_multicast_packets",
+ "tx_broadcast_packets",
+ "tx_errors",
+
+ /* VPort statistics */
+ "vport_rx_unicast_packets",
+ "vport_rx_unicast_bytes",
+ "vport_rx_multicast_packets",
+ "vport_rx_multicast_bytes",
+ "vport_rx_broadcast_packets",
+ "vport_rx_broadcast_bytes",
+ "vport_rx_dropped",
+ "vport_rx_errors",
+ "vport_tx_unicast_packets",
+ "vport_tx_unicast_bytes",
+ "vport_tx_multicast_packets",
+ "vport_tx_multicast_bytes",
+ "vport_tx_broadcast_packets",
+ "vport_tx_broadcast_bytes",
+ "vport_tx_errors",
/* port statistics */
- "lro_aggregated", "lro_flushed", "lro_no_desc", "tso_packets",
- "queue_stopped", "wake_queue", "tx_timeout", "rx_alloc_failed",
+ "tx_tso_packets",
+ "tx_queue_stopped", "tx_wake_queue", "tx_timeout", "rx_alloc_failed",
"rx_csum_good", "rx_csum_none", "tx_chksum_offload",
-
- /* packet statistics */
- "broadcast", "rx_prio_0", "rx_prio_1", "rx_prio_2", "rx_prio_3",
- "rx_prio_4", "rx_prio_5", "rx_prio_6", "rx_prio_7", "tx_prio_0",
- "tx_prio_1", "tx_prio_2", "tx_prio_3", "tx_prio_4", "tx_prio_5",
- "tx_prio_6", "tx_prio_7",
};
-#define NUM_MAIN_STATS 21
-#define NUM_ALL_STATS (NUM_MAIN_STATS + NUM_PORT_STATS + NUM_PKT_STATS + NUM_PERF_STATS)
static const char mlx4_en_test_names[][ETH_GSTRING_LEN]= {
- "Interupt Test",
+ "Interrupt Test",
"Link Test",
"Speed Test",
"Register Test",
@@ -178,56 +247,265 @@ static void mlx4_en_set_msglevel(struct net_device *dev, u32 val)
static void mlx4_en_get_wol(struct net_device *netdev,
struct ethtool_wolinfo *wol)
{
- wol->supported = 0;
- wol->wolopts = 0;
+ struct mlx4_en_priv *priv = netdev_priv(netdev);
+ int err = 0;
+ u64 config = 0;
+ u64 mask;
+
+ if ((priv->port < 1) || (priv->port > 2)) {
+ en_err(priv, "Failed to get WoL information\n");
+ return;
+ }
+
+ mask = (priv->port == 1) ? MLX4_DEV_CAP_FLAG_WOL_PORT1 :
+ MLX4_DEV_CAP_FLAG_WOL_PORT2;
+
+ if (!(priv->mdev->dev->caps.flags & mask)) {
+ wol->supported = 0;
+ wol->wolopts = 0;
+ return;
+ }
+
+ err = mlx4_wol_read(priv->mdev->dev, &config, priv->port);
+ if (err) {
+ en_err(priv, "Failed to get WoL information\n");
+ return;
+ }
+
+ if (config & MLX4_EN_WOL_MAGIC)
+ wol->supported = WAKE_MAGIC;
+ else
+ wol->supported = 0;
+
+ if (config & MLX4_EN_WOL_ENABLED)
+ wol->wolopts = WAKE_MAGIC;
+ else
+ wol->wolopts = 0;
+}
+
+static int mlx4_en_set_wol(struct net_device *netdev,
+ struct ethtool_wolinfo *wol)
+{
+ struct mlx4_en_priv *priv = netdev_priv(netdev);
+ u64 config = 0;
+ int err = 0;
+ u64 mask;
+
+ if ((priv->port < 1) || (priv->port > 2))
+ return -EOPNOTSUPP;
+
+ mask = (priv->port == 1) ? MLX4_DEV_CAP_FLAG_WOL_PORT1 :
+ MLX4_DEV_CAP_FLAG_WOL_PORT2;
+
+ if (!(priv->mdev->dev->caps.flags & mask))
+ return -EOPNOTSUPP;
+
+ if (wol->supported & ~WAKE_MAGIC)
+ return -EINVAL;
- return;
+ err = mlx4_wol_read(priv->mdev->dev, &config, priv->port);
+ if (err) {
+ en_err(priv, "Failed to get WoL info, unable to modify\n");
+ return err;
+ }
+
+ if (wol->wolopts & WAKE_MAGIC) {
+ config |= MLX4_EN_WOL_DO_MODIFY | MLX4_EN_WOL_ENABLED |
+ MLX4_EN_WOL_MAGIC;
+ } else {
+ config &= ~(MLX4_EN_WOL_ENABLED | MLX4_EN_WOL_MAGIC);
+ config |= MLX4_EN_WOL_DO_MODIFY;
+ }
+
+ err = mlx4_wol_write(priv->mdev->dev, config, priv->port);
+ if (err)
+ en_err(priv, "Failed to set WoL information\n");
+
+ return err;
+}
+
+struct bitmap_sim_iterator {
+ bool advance_array;
+ unsigned long *stats_bitmap;
+ unsigned int count;
+ unsigned int j;
+};
+
+static inline void bitmap_sim_iterator_init(struct bitmap_sim_iterator *h,
+ unsigned long *stats_bitmap,
+ int count)
+{
+ h->j = 0;
+ h->advance_array = !bitmap_empty(stats_bitmap, count);
+ h->count = h->advance_array ? bitmap_weight(stats_bitmap, count)
+ : count;
+ h->stats_bitmap = stats_bitmap;
}
-static int mlx4_en_get_sset_count(struct net_device *dev, int sset)
+static inline int bitmap_sim_iterator_test(struct bitmap_sim_iterator *h)
+{
+ return !h->advance_array ? 1 : test_bit(h->j, h->stats_bitmap);
+}
+
+static inline int bitmap_sim_iterator_inc(struct bitmap_sim_iterator *h)
+{
+ return h->j++;
+}
+
+static inline unsigned int bitmap_sim_iterator_count(
+ struct bitmap_sim_iterator *h)
+{
+ return h->count;
+}
+
+int mlx4_en_get_sset_count(struct net_device *dev, int sset)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct bitmap_sim_iterator it;
+
+ int num_of_stats = NUM_ALL_STATS -
+ ((priv->mdev->dev->caps.flags2 &
+ MLX4_DEV_CAP_FLAG2_FLOWSTATS_EN) ? 0 : NUM_FLOW_STATS);
+
+ bitmap_sim_iterator_init(&it, priv->stats_bitmap, num_of_stats);
switch (sset) {
case ETH_SS_STATS:
- return NUM_ALL_STATS +
- (priv->tx_ring_num + priv->rx_ring_num) * 2;
+ return bitmap_sim_iterator_count(&it) +
+ (priv->tx_ring_num * 2) +
+#ifdef LL_EXTENDED_STATS
+ (priv->rx_ring_num * 5);
+#else
+ (priv->rx_ring_num * 2);
+#endif
case ETH_SS_TEST:
- return MLX4_EN_NUM_SELF_TEST - !(priv->mdev->dev->caps.loopback_support) * 2;
+ return MLX4_EN_NUM_SELF_TEST - !(priv->mdev->dev->caps.flags
+ & MLX4_DEV_CAP_FLAG_UC_LOOPBACK) * 2;
default:
return -EOPNOTSUPP;
}
}
-static void mlx4_en_get_ethtool_stats(struct net_device *dev,
- struct ethtool_stats *stats, uint64_t *data)
+void mlx4_en_get_ethtool_stats(struct net_device *dev,
+ struct ethtool_stats *stats, u64 *data)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
int index = 0;
int i;
+ struct bitmap_sim_iterator it;
+
+ int num_of_stats = NUM_ALL_STATS -
+ ((priv->mdev->dev->caps.flags2 &
+ MLX4_DEV_CAP_FLAG2_FLOWSTATS_EN) ? 0 : NUM_FLOW_STATS);
+
+ bitmap_sim_iterator_init(&it, priv->stats_bitmap, num_of_stats);
+
+ if (!data || !priv->port_up)
+ return;
spin_lock_bh(&priv->stats_lock);
- mlx4_en_update_lro_stats(priv);
+ for (i = 0; i < NUM_PKT_STATS; i++,
+ bitmap_sim_iterator_inc(&it))
+ if (bitmap_sim_iterator_test(&it))
+ data[index++] =
+ ((unsigned long *)&priv->pkstats)[i];
+ for (i = 0; i < NUM_FLOW_STATS; i++,
+ bitmap_sim_iterator_inc(&it))
+ if (priv->mdev->dev->caps.flags2 &
+ MLX4_DEV_CAP_FLAG2_FLOWSTATS_EN)
+ if (bitmap_sim_iterator_test(&it))
+ data[index++] =
+ ((u64 *)&priv->flowstats)[i];
+ for (i = 0; i < NUM_VF_STATS; i++,
+ bitmap_sim_iterator_inc(&it))
+ if (bitmap_sim_iterator_test(&it))
+ data[index++] =
+ ((unsigned long *)&priv->vf_stats)[i];
+ for (i = 0; i < NUM_VPORT_STATS; i++,
+ bitmap_sim_iterator_inc(&it))
+ if (bitmap_sim_iterator_test(&it))
+ data[index++] =
+ ((unsigned long *)&priv->vport_stats)[i];
+ for (i = 0; i < NUM_PORT_STATS; i++,
+ bitmap_sim_iterator_inc(&it))
+ if (bitmap_sim_iterator_test(&it))
+ data[index++] =
+ ((unsigned long *)&priv->port_stats)[i];
- for (i = 0; i < NUM_MAIN_STATS; i++)
- data[index++] = ((unsigned long *) &priv->stats)[i];
- for (i = 0; i < NUM_PORT_STATS; i++)
- data[index++] = ((unsigned long *) &priv->port_stats)[i];
for (i = 0; i < priv->tx_ring_num; i++) {
- data[index++] = priv->tx_ring[i].packets;
- data[index++] = priv->tx_ring[i].bytes;
+ data[index++] = priv->tx_ring[i]->packets;
+ data[index++] = priv->tx_ring[i]->bytes;
}
for (i = 0; i < priv->rx_ring_num; i++) {
- data[index++] = priv->rx_ring[i].packets;
- data[index++] = priv->rx_ring[i].bytes;
+ data[index++] = priv->rx_ring[i]->packets;
+ data[index++] = priv->rx_ring[i]->bytes;
+#ifdef LL_EXTENDED_STATS
+ data[index++] = priv->rx_ring[i]->yields;
+ data[index++] = priv->rx_ring[i]->misses;
+ data[index++] = priv->rx_ring[i]->cleaned;
+#endif
}
- for (i = 0; i < NUM_PKT_STATS; i++)
- data[index++] = ((unsigned long *) &priv->pkstats)[i];
spin_unlock_bh(&priv->stats_lock);
}
+void mlx4_en_restore_ethtool_stats(struct mlx4_en_priv *priv, u64 *data)
+{
+ int index = 0;
+ int i;
+ struct bitmap_sim_iterator it;
+
+ int num_of_stats = NUM_ALL_STATS -
+ ((priv->mdev->dev->caps.flags2 &
+ MLX4_DEV_CAP_FLAG2_FLOWSTATS_EN) ? 0 : NUM_FLOW_STATS);
+
+ bitmap_sim_iterator_init(&it, priv->stats_bitmap, num_of_stats);
+
+ if (!data || !priv->port_up)
+ return;
+
+ spin_lock_bh(&priv->stats_lock);
+
+ for (i = 0; i < NUM_PKT_STATS; i++,
+ bitmap_sim_iterator_inc(&it))
+ if (bitmap_sim_iterator_test(&it))
+ ((unsigned long *)&priv->pkstats)[i] =
+ data[index++];
+ for (i = 0; i < NUM_FLOW_STATS; i++,
+ bitmap_sim_iterator_inc(&it))
+ if (priv->mdev->dev->caps.flags2 &
+ MLX4_DEV_CAP_FLAG2_FLOWSTATS_EN)
+ if (bitmap_sim_iterator_test(&it))
+ ((u64 *)&priv->flowstats)[i] =
+ data[index++];
+ for (i = 0; i < NUM_VF_STATS; i++,
+ bitmap_sim_iterator_inc(&it))
+ if (bitmap_sim_iterator_test(&it))
+ ((unsigned long *)&priv->vf_stats)[i] =
+ data[index++];
+ for (i = 0; i < NUM_VPORT_STATS; i++,
+ bitmap_sim_iterator_inc(&it))
+ if (bitmap_sim_iterator_test(&it))
+ ((unsigned long *)&priv->vport_stats)[i] =
+ data[index++];
+ for (i = 0; i < NUM_PORT_STATS; i++,
+ bitmap_sim_iterator_inc(&it))
+ if (bitmap_sim_iterator_test(&it))
+ ((unsigned long *)&priv->port_stats)[i] =
+ data[index++];
+
+ for (i = 0; i < priv->tx_ring_num; i++) {
+ priv->tx_ring[i]->packets = data[index++];
+ priv->tx_ring[i]->bytes = data[index++];
+ }
+ for (i = 0; i < priv->rx_ring_num; i++) {
+ priv->rx_ring[i]->packets = data[index++];
+ priv->rx_ring[i]->bytes = data[index++];
+ }
+ spin_unlock_bh(&priv->stats_lock);
+}
+
static void mlx4_en_self_test(struct net_device *dev,
struct ethtool_test *etest, u64 *buf)
{
@@ -239,24 +517,47 @@ static void mlx4_en_get_strings(struct net_device *dev,
{
struct mlx4_en_priv *priv = netdev_priv(dev);
int index = 0;
- int i;
+ int i, k;
+ struct bitmap_sim_iterator it;
+
+ int num_of_stats = NUM_ALL_STATS -
+ ((priv->mdev->dev->caps.flags2 &
+ MLX4_DEV_CAP_FLAG2_FLOWSTATS_EN) ? 0 : NUM_FLOW_STATS);
+
+ bitmap_sim_iterator_init(&it, priv->stats_bitmap, num_of_stats);
switch (stringset) {
case ETH_SS_TEST:
for (i = 0; i < MLX4_EN_NUM_SELF_TEST - 2; i++)
strcpy(data + i * ETH_GSTRING_LEN, mlx4_en_test_names[i]);
- if (priv->mdev->dev->caps.loopback_support)
+ if (priv->mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_UC_LOOPBACK)
for (; i < MLX4_EN_NUM_SELF_TEST; i++)
strcpy(data + i * ETH_GSTRING_LEN, mlx4_en_test_names[i]);
break;
case ETH_SS_STATS:
/* Add main counters */
- for (i = 0; i < NUM_MAIN_STATS; i++)
- strcpy(data + (index++) * ETH_GSTRING_LEN, main_strings[i]);
- for (i = 0; i< NUM_PORT_STATS; i++)
- strcpy(data + (index++) * ETH_GSTRING_LEN,
- main_strings[i + NUM_MAIN_STATS]);
+ for (i = 0; i < NUM_PKT_STATS; i++,
+ bitmap_sim_iterator_inc(&it))
+ if (bitmap_sim_iterator_test(&it))
+ strcpy(data + (index++) * ETH_GSTRING_LEN,
+ main_strings[i]);
+
+ for (k = 0; k < NUM_FLOW_STATS; k++,
+ bitmap_sim_iterator_inc(&it))
+ if (priv->mdev->dev->caps.flags2 &
+ MLX4_DEV_CAP_FLAG2_FLOWSTATS_EN)
+ if (bitmap_sim_iterator_test(&it))
+ strcpy(data + (index++) *
+ ETH_GSTRING_LEN,
+ main_strings[i + k]);
+
+ for (; (i + k) < num_of_stats; i++,
+ bitmap_sim_iterator_inc(&it))
+ if (bitmap_sim_iterator_test(&it))
+ strcpy(data + (index++) * ETH_GSTRING_LEN,
+ main_strings[i + k]);
+
for (i = 0; i < priv->tx_ring_num; i++) {
sprintf(data + (index++) * ETH_GSTRING_LEN,
"tx%d_packets", i);
@@ -268,32 +569,79 @@ static void mlx4_en_get_strings(struct net_device *dev,
"rx%d_packets", i);
sprintf(data + (index++) * ETH_GSTRING_LEN,
"rx%d_bytes", i);
+#ifdef LL_EXTENDED_STATS
+ sprintf(data + (index++) * ETH_GSTRING_LEN,
+ "rx%d_napi_yield", i);
+ sprintf(data + (index++) * ETH_GSTRING_LEN,
+ "rx%d_misses", i);
+ sprintf(data + (index++) * ETH_GSTRING_LEN,
+ "rx%d_cleaned", i);
+#endif
}
- for (i = 0; i< NUM_PKT_STATS; i++)
- strcpy(data + (index++) * ETH_GSTRING_LEN,
- main_strings[i + NUM_MAIN_STATS + NUM_PORT_STATS]);
break;
}
}
+static u32 mlx4_en_autoneg_get(struct net_device *dev)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ u32 autoneg = AUTONEG_DISABLE;
+
+ if ((mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_ETH_BACKPL_AN_REP) &&
+ priv->port_state.autoneg) {
+ autoneg = AUTONEG_ENABLE;
+ }
+
+ return autoneg;
+}
+
static int mlx4_en_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
int trans_type;
- cmd->autoneg = AUTONEG_DISABLE;
- cmd->supported = SUPPORTED_10000baseT_Full;
- cmd->advertising = ADVERTISED_10000baseT_Full;
+ /* SUPPORTED_1000baseT_Half isn't supported */
+ cmd->supported = SUPPORTED_1000baseT_Full
+ |SUPPORTED_10000baseT_Full;
+
+ cmd->advertising = ADVERTISED_1000baseT_Full
+ |ADVERTISED_10000baseT_Full;
+
+ cmd->supported |= SUPPORTED_1000baseKX_Full
+ |SUPPORTED_10000baseKX4_Full
+ |SUPPORTED_10000baseKR_Full
+ |SUPPORTED_10000baseR_FEC
+ |SUPPORTED_40000baseKR4_Full
+ |SUPPORTED_40000baseCR4_Full
+ |SUPPORTED_40000baseSR4_Full
+ |SUPPORTED_40000baseLR4_Full;
+
+ /* ADVERTISED_1000baseT_Half isn't advertised */
+ cmd->advertising |= ADVERTISED_1000baseKX_Full
+ |ADVERTISED_10000baseKX4_Full
+ |ADVERTISED_10000baseKR_Full
+ |ADVERTISED_10000baseR_FEC
+ |ADVERTISED_40000baseKR4_Full
+ |ADVERTISED_40000baseCR4_Full
+ |ADVERTISED_40000baseSR4_Full
+ |ADVERTISED_40000baseLR4_Full;
if (mlx4_en_QUERY_PORT(priv->mdev, priv->port))
return -ENOMEM;
+ cmd->autoneg = mlx4_en_autoneg_get(dev);
+ if (cmd->autoneg == AUTONEG_ENABLE) {
+ cmd->supported |= SUPPORTED_Autoneg;
+ cmd->advertising |= ADVERTISED_Autoneg;
+ }
+
trans_type = priv->port_state.transciver;
if (netif_carrier_ok(dev)) {
- cmd->speed = priv->port_state.link_speed;
+ ethtool_cmd_speed_set(cmd, priv->port_state.link_speed);
cmd->duplex = DUPLEX_FULL;
} else {
- cmd->speed = -1;
+ ethtool_cmd_speed_set(cmd, -1);
cmd->duplex = -1;
}
@@ -314,13 +662,38 @@ static int mlx4_en_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
return 0;
}
+static const char *mlx4_en_duplex_to_string(int duplex)
+{
+ switch (duplex) {
+ case DUPLEX_FULL:
+ return "FULL";
+ case DUPLEX_HALF:
+ return "HALF";
+ default:
+ break;
+ }
+ return "UNKNOWN";
+}
+
static int mlx4_en_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
- if ((cmd->autoneg == AUTONEG_ENABLE) ||
- (cmd->speed != SPEED_10000) || (cmd->duplex != DUPLEX_FULL))
- return -EINVAL;
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_port_state *port_state = &priv->port_state;
+
+ if ((cmd->autoneg != port_state->autoneg) ||
+ (ethtool_cmd_speed(cmd) != port_state->link_speed) ||
+ (cmd->duplex != DUPLEX_FULL)) {
+ en_info(priv, "Changing port state properties (auto-negotiation"
+ " , speed/duplex) is not supported. Current:"
+ " auto-negotiation=%d speed/duplex=%d/%s\n",
+ port_state->autoneg, port_state->link_speed,
+ mlx4_en_duplex_to_string(DUPLEX_FULL));
+ return -EOPNOTSUPP;
+ }
- /* Nothing to change */
+ /* User provided same port state properties that are currently set.
+ * Nothing to change
+ */
return 0;
}
@@ -329,8 +702,8 @@ static int mlx4_en_get_coalesce(struct net_device *dev,
{
struct mlx4_en_priv *priv = netdev_priv(dev);
- coal->tx_coalesce_usecs = 0;
- coal->tx_max_coalesced_frames = 0;
+ coal->tx_coalesce_usecs = priv->tx_usecs;
+ coal->tx_max_coalesced_frames = priv->tx_frames;
coal->rx_coalesce_usecs = priv->rx_usecs;
coal->rx_max_coalesced_frames = priv->rx_frames;
@@ -359,6 +732,21 @@ static int mlx4_en_set_coalesce(struct net_device *dev,
MLX4_EN_RX_COAL_TIME :
coal->rx_coalesce_usecs;
+ /* Setting TX coalescing parameters */
+ if (coal->tx_coalesce_usecs != priv->tx_usecs ||
+ coal->tx_max_coalesced_frames != priv->tx_frames) {
+ priv->tx_usecs = coal->tx_coalesce_usecs;
+ priv->tx_frames = coal->tx_max_coalesced_frames;
+ if (priv->port_up) {
+ for (i = 0; i < priv->tx_ring_num; i++) {
+ priv->tx_cq[i]->moder_cnt = priv->tx_frames;
+ priv->tx_cq[i]->moder_time = priv->tx_usecs;
+ if (mlx4_en_set_cq_moder(priv, priv->tx_cq[i]))
+ en_warn(priv, "Failed changing moderation for TX cq %d\n", i);
+ }
+ }
+ }
+
/* Set adaptive coalescing params */
priv->pkt_rate_low = coal->pkt_rate_low;
priv->rx_usecs_low = coal->rx_coalesce_usecs_low;
@@ -369,14 +757,17 @@ static int mlx4_en_set_coalesce(struct net_device *dev,
if (priv->adaptive_rx_coal)
return 0;
- for (i = 0; i < priv->rx_ring_num; i++) {
- priv->rx_cq[i].moder_cnt = priv->rx_frames;
- priv->rx_cq[i].moder_time = priv->rx_usecs;
- priv->last_moder_time[i] = MLX4_EN_AUTO_CONF;
- err = mlx4_en_set_cq_moder(priv, &priv->rx_cq[i]);
- if (err)
- return err;
+ if (priv->port_up) {
+ for (i = 0; i < priv->rx_ring_num; i++) {
+ priv->rx_cq[i]->moder_cnt = priv->rx_frames;
+ priv->rx_cq[i]->moder_time = priv->rx_usecs;
+ priv->last_moder_time[i] = MLX4_EN_AUTO_CONF;
+ err = mlx4_en_set_cq_moder(priv, priv->rx_cq[i]);
+ if (err)
+ return err;
+ }
}
+
return 0;
}
@@ -387,10 +778,13 @@ static int mlx4_en_set_pauseparam(struct net_device *dev,
struct mlx4_en_dev *mdev = priv->mdev;
int err;
+ if (pause->autoneg)
+ return -EOPNOTSUPP;
+
priv->prof->tx_pause = pause->tx_pause != 0;
priv->prof->rx_pause = pause->rx_pause != 0;
err = mlx4_SET_PORT_general(mdev->dev, priv->port,
- priv->rx_mb_size + ETH_FCS_LEN,
+ priv->rx_skb_size + ETH_FCS_LEN,
priv->prof->tx_pause,
priv->prof->tx_ppp,
priv->prof->rx_pause,
@@ -408,6 +802,41 @@ static void mlx4_en_get_pauseparam(struct net_device *dev,
pause->tx_pause = priv->prof->tx_pause;
pause->rx_pause = priv->prof->rx_pause;
+ pause->autoneg = mlx4_en_autoneg_get(dev);
+}
+
+/* rtnl lock must be taken before calling */
+int mlx4_en_pre_config(struct mlx4_en_priv *priv)
+{
+#ifdef CONFIG_RFS_ACCEL
+ struct cpu_rmap *rmap;
+
+ if (!priv->dev->rx_cpu_rmap)
+ return 0;
+
+ /* Disable RFS events
+ * Must have all RFS jobs flushed before freeing resources
+ */
+ rmap = priv->dev->rx_cpu_rmap;
+ priv->dev->rx_cpu_rmap = NULL;
+
+ rtnl_unlock();
+ free_irq_cpu_rmap(rmap);
+ rtnl_lock();
+
+ if (priv->dev->rx_cpu_rmap)
+ return -EBUSY; /* another configuration completed while lock
+ * was free
+ */
+
+ /* Make sure all currently running filter_work are being processed
+ * Other work will return immediatly because of disable_rfs
+ */
+ flush_workqueue(priv->mdev->workqueue);
+
+#endif
+
+ return 0;
}
static int mlx4_en_set_ringparam(struct net_device *dev,
@@ -418,7 +847,11 @@ static int mlx4_en_set_ringparam(struct net_device *dev,
u32 rx_size, tx_size;
int port_up = 0;
int err = 0;
- int i;
+ int i, n_stats;
+ u64 *data = NULL;
+
+ if (!priv->port_up)
+ return -ENOMEM;
if (param->rx_jumbo_pending || param->rx_mini_pending)
return -EINVAL;
@@ -430,10 +863,13 @@ static int mlx4_en_set_ringparam(struct net_device *dev,
tx_size = max_t(u32, tx_size, MLX4_EN_MIN_TX_SIZE);
tx_size = min_t(u32, tx_size, MLX4_EN_MAX_TX_SIZE);
- if (rx_size == (priv->port_up ? priv->rx_ring[0].actual_size :
- priv->rx_ring[0].size) &&
- tx_size == priv->tx_ring[0].size)
+ if (rx_size == (priv->port_up ? priv->rx_ring[0]->actual_size :
+ priv->rx_ring[0]->size) &&
+ tx_size == priv->tx_ring[0]->size)
return 0;
+ err = mlx4_en_pre_config(priv);
+ if (err)
+ return err;
mutex_lock(&mdev->state_lock);
if (priv->port_up) {
@@ -441,6 +877,14 @@ static int mlx4_en_set_ringparam(struct net_device *dev,
mlx4_en_stop_port(dev);
}
+ /* Cache port statistics */
+ n_stats = mlx4_en_get_sset_count(dev, ETH_SS_STATS);
+ if (n_stats > 0) {
+ data = kmalloc(n_stats * sizeof(u64), GFP_KERNEL);
+ if (data)
+ mlx4_en_get_ethtool_stats(dev, NULL, data);
+ }
+
mlx4_en_free_resources(priv);
priv->prof->tx_ring_size = tx_size;
@@ -451,22 +895,30 @@ static int mlx4_en_set_ringparam(struct net_device *dev,
en_err(priv, "Failed reallocating port resources\n");
goto out;
}
+
+ /* Restore port statistics */
+ if (n_stats > 0 && data)
+ mlx4_en_restore_ethtool_stats(priv, data);
+
if (port_up) {
err = mlx4_en_start_port(dev);
- if (err)
+ if (err) {
en_err(priv, "Failed starting port\n");
- }
-
- for (i = 0; i < priv->rx_ring_num; i++) {
- priv->rx_cq[i].moder_cnt = priv->rx_frames;
- priv->rx_cq[i].moder_time = priv->rx_usecs;
- priv->last_moder_time[i] = MLX4_EN_AUTO_CONF;
- err = mlx4_en_set_cq_moder(priv, &priv->rx_cq[i]);
- if (err)
goto out;
+ }
+
+ for (i = 0; i < priv->rx_ring_num; i++) {
+ priv->rx_cq[i]->moder_cnt = priv->rx_frames;
+ priv->rx_cq[i]->moder_time = priv->rx_usecs;
+ priv->last_moder_time[i] = MLX4_EN_AUTO_CONF;
+ err = mlx4_en_set_cq_moder(priv, priv->rx_cq[i]);
+ if (err)
+ goto out;
+ }
}
out:
+ kfree(data);
mutex_unlock(&mdev->state_lock);
return err;
}
@@ -476,29 +928,665 @@ static void mlx4_en_get_ringparam(struct net_device *dev,
{
struct mlx4_en_priv *priv = netdev_priv(dev);
+ if (!priv->port_up)
+ return;
+
memset(param, 0, sizeof(*param));
param->rx_max_pending = MLX4_EN_MAX_RX_SIZE;
param->tx_max_pending = MLX4_EN_MAX_TX_SIZE;
param->rx_pending = priv->port_up ?
- priv->rx_ring[0].actual_size : priv->rx_ring[0].size;
- param->tx_pending = priv->tx_ring[0].size;
+ priv->rx_ring[0]->actual_size : priv->rx_ring[0]->size;
+ param->tx_pending = priv->tx_ring[0]->size;
+}
+
+static u32 mlx4_en_get_rxfh_indir_size(struct net_device *dev)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+
+ return priv->rx_ring_num;
+}
+
+static int mlx4_en_get_rxfh_indir(struct net_device *dev, u32 *ring_index)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_rss_map *rss_map = &priv->rss_map;
+ int rss_rings;
+ size_t n = priv->rx_ring_num;
+ int err = 0;
+
+ rss_rings = priv->prof->rss_rings ?: priv->rx_ring_num;
+ rss_rings = 1 << ilog2(rss_rings);
+
+ while (n--) {
+ ring_index[n] = rss_map->qps[n % rss_rings].qpn -
+ rss_map->base_qpn;
+ }
+
+ return err;
+}
+
+static int mlx4_en_set_rxfh_indir(struct net_device *dev,
+ const u32 *ring_index)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int port_up = 0;
+ int err = 0;
+ int i;
+ int rss_rings = 0;
+
+ /* Calculate RSS table size and make sure flows are spread evenly
+ * between rings
+ */
+ for (i = 0; i < priv->rx_ring_num; i++) {
+ if (i > 0 && !ring_index[i] && !rss_rings)
+ rss_rings = i;
+
+ if (ring_index[i] != (i % (rss_rings ?: priv->rx_ring_num)))
+ return -EINVAL;
+ }
+
+ if (!rss_rings)
+ rss_rings = priv->rx_ring_num;
+
+ /* RSS table size must be an order of 2 */
+ if (!is_power_of_2(rss_rings))
+ return -EINVAL;
+
+ mutex_lock(&mdev->state_lock);
+ if (priv->port_up) {
+ port_up = 1;
+ mlx4_en_stop_port(dev);
+ }
+
+ priv->prof->rss_rings = rss_rings;
+
+ if (port_up) {
+ err = mlx4_en_start_port(dev);
+ if (err)
+ en_err(priv, "Failed starting port\n");
+ }
+
+ mutex_unlock(&mdev->state_lock);
+ return err;
+}
+
+#define all_zeros_or_all_ones(field) \
+ ((field) == 0 || (field) == (__force typeof(field))-1)
+
+static int mlx4_en_validate_flow(struct net_device *dev,
+ struct mlx4_ethtool_rxnfc *cmd)
+{
+ struct ethtool_usrip4_spec *l3_mask;
+ struct ethtool_tcpip4_spec *l4_mask;
+ struct ethhdr *eth_mask;
+
+ if (cmd->fs.location >= MAX_NUM_OF_FS_RULES)
+ return -EINVAL;
+
+ if (cmd->fs.flow_type & FLOW_MAC_EXT) {
+ /* dest mac mask must be ff:ff:ff:ff:ff:ff */
+ if (!is_broadcast_ether_addr(cmd->fs.m_ext.h_dest))
+ return -EINVAL;
+ }
+
+ switch (cmd->fs.flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) {
+ case TCP_V4_FLOW:
+ case UDP_V4_FLOW:
+ if (cmd->fs.m_u.tcp_ip4_spec.tos)
+ return -EINVAL;
+ l4_mask = &cmd->fs.m_u.tcp_ip4_spec;
+ /* don't allow mask which isn't all 0 or 1 */
+ if (!all_zeros_or_all_ones(l4_mask->ip4src) ||
+ !all_zeros_or_all_ones(l4_mask->ip4dst) ||
+ !all_zeros_or_all_ones(l4_mask->psrc) ||
+ !all_zeros_or_all_ones(l4_mask->pdst))
+ return -EINVAL;
+ break;
+ case IP_USER_FLOW:
+ l3_mask = &cmd->fs.m_u.usr_ip4_spec;
+ if (l3_mask->l4_4_bytes || l3_mask->tos || l3_mask->proto ||
+ cmd->fs.h_u.usr_ip4_spec.ip_ver != ETH_RX_NFC_IP4 ||
+ (!l3_mask->ip4src && !l3_mask->ip4dst) ||
+ !all_zeros_or_all_ones(l3_mask->ip4src) ||
+ !all_zeros_or_all_ones(l3_mask->ip4dst))
+ return -EINVAL;
+ break;
+ case ETHER_FLOW:
+ eth_mask = &cmd->fs.m_u.ether_spec;
+ /* source mac mask must not be set */
+ if (!is_zero_ether_addr(eth_mask->h_source))
+ return -EINVAL;
+
+ /* dest mac mask must be ff:ff:ff:ff:ff:ff */
+ if (!is_broadcast_ether_addr(eth_mask->h_dest))
+ return -EINVAL;
+
+ if (!all_zeros_or_all_ones(eth_mask->h_proto))
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if ((cmd->fs.flow_type & FLOW_EXT)) {
+ if (cmd->fs.m_ext.vlan_etype ||
+ !(cmd->fs.m_ext.vlan_tci == 0 ||
+ cmd->fs.m_ext.vlan_tci == cpu_to_be16(0xfff)))
+ return -EINVAL;
+ if (cmd->fs.m_ext.vlan_tci) {
+ if (be16_to_cpu(cmd->fs.h_ext.vlan_tci) <
+ VLAN_MIN_VALUE ||
+ be16_to_cpu(cmd->fs.h_ext.vlan_tci) >
+ VLAN_MAX_VALUE)
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static int mlx4_en_ethtool_add_mac_rule(struct mlx4_ethtool_rxnfc *cmd,
+ struct list_head *rule_list_h,
+ struct mlx4_spec_list *spec_l2,
+ unsigned char *mac)
+{
+ int err = 0;
+ __be64 mac_msk = cpu_to_be64(MLX4_MAC_MASK << 16);
+
+ spec_l2->id = MLX4_NET_TRANS_RULE_ID_ETH;
+ memcpy(spec_l2->eth.dst_mac_msk, &mac_msk, ETH_ALEN);
+ memcpy(spec_l2->eth.dst_mac, mac, ETH_ALEN);
+
+ if ((cmd->fs.flow_type & FLOW_EXT) && cmd->fs.m_ext.vlan_tci) {
+ spec_l2->eth.vlan_id = cmd->fs.h_ext.vlan_tci;
+ spec_l2->eth.vlan_id_msk = cpu_to_be16(0xfff);
+ }
+
+ list_add_tail(&spec_l2->list, rule_list_h);
+
+ return err;
+}
+
+static int mlx4_en_ethtool_add_mac_rule_by_ipv4(struct mlx4_en_priv *priv,
+ struct mlx4_ethtool_rxnfc *cmd,
+ struct list_head *rule_list_h,
+ struct mlx4_spec_list *spec_l2,
+ __be32 ipv4_dst)
+{
+ unsigned char mac[ETH_ALEN];
+
+ if (!ipv4_is_multicast(ipv4_dst)) {
+ if (cmd->fs.flow_type & FLOW_MAC_EXT)
+ memcpy(&mac, cmd->fs.h_ext.h_dest, ETH_ALEN);
+ else
+ memcpy(&mac, priv->dev->dev_addr, ETH_ALEN);
+ } else {
+ ip_eth_mc_map(ipv4_dst, mac);
+ }
+
+ return mlx4_en_ethtool_add_mac_rule(cmd, rule_list_h, spec_l2, &mac[0]);
+}
+
+static int add_ip_rule(struct mlx4_en_priv *priv,
+ struct mlx4_ethtool_rxnfc *cmd,
+ struct list_head *list_h)
+{
+ struct mlx4_spec_list *spec_l2 = NULL;
+ struct mlx4_spec_list *spec_l3 = NULL;
+ struct ethtool_usrip4_spec *l3_mask = &cmd->fs.m_u.usr_ip4_spec;
+
+ spec_l3 = kzalloc(sizeof(*spec_l3), GFP_KERNEL);
+ spec_l2 = kzalloc(sizeof(*spec_l2), GFP_KERNEL);
+ if (!spec_l2 || !spec_l3) {
+ en_err(priv, "Fail to alloc ethtool rule.\n");
+ kfree(spec_l2);
+ kfree(spec_l3);
+ return -ENOMEM;
+ }
+
+ mlx4_en_ethtool_add_mac_rule_by_ipv4(priv, cmd, list_h, spec_l2,
+ cmd->fs.h_u.
+ usr_ip4_spec.ip4dst);
+ spec_l3->id = MLX4_NET_TRANS_RULE_ID_IPV4;
+ spec_l3->ipv4.src_ip = cmd->fs.h_u.usr_ip4_spec.ip4src;
+ if (l3_mask->ip4src)
+ spec_l3->ipv4.src_ip_msk = MLX4_BE_WORD_MASK;
+ spec_l3->ipv4.dst_ip = cmd->fs.h_u.usr_ip4_spec.ip4dst;
+ if (l3_mask->ip4dst)
+ spec_l3->ipv4.dst_ip_msk = MLX4_BE_WORD_MASK;
+ list_add_tail(&spec_l3->list, list_h);
+
+ return 0;
+}
+
+static int add_tcp_udp_rule(struct mlx4_en_priv *priv,
+ struct mlx4_ethtool_rxnfc *cmd,
+ struct list_head *list_h, int proto)
+{
+ struct mlx4_spec_list *spec_l2 = NULL;
+ struct mlx4_spec_list *spec_l3 = NULL;
+ struct mlx4_spec_list *spec_l4 = NULL;
+ struct ethtool_tcpip4_spec *l4_mask = &cmd->fs.m_u.tcp_ip4_spec;
+
+ spec_l2 = kzalloc(sizeof(*spec_l2), GFP_KERNEL);
+ spec_l3 = kzalloc(sizeof(*spec_l3), GFP_KERNEL);
+ spec_l4 = kzalloc(sizeof(*spec_l4), GFP_KERNEL);
+ if (!spec_l2 || !spec_l3 || !spec_l4) {
+ en_err(priv, "Fail to alloc ethtool rule.\n");
+ kfree(spec_l2);
+ kfree(spec_l3);
+ kfree(spec_l4);
+ return -ENOMEM;
+ }
+
+ spec_l3->id = MLX4_NET_TRANS_RULE_ID_IPV4;
+
+ if (proto == TCP_V4_FLOW) {
+ mlx4_en_ethtool_add_mac_rule_by_ipv4(priv, cmd, list_h,
+ spec_l2,
+ cmd->fs.h_u.
+ tcp_ip4_spec.ip4dst);
+ spec_l4->id = MLX4_NET_TRANS_RULE_ID_TCP;
+ spec_l3->ipv4.src_ip = cmd->fs.h_u.tcp_ip4_spec.ip4src;
+ spec_l3->ipv4.dst_ip = cmd->fs.h_u.tcp_ip4_spec.ip4dst;
+ spec_l4->tcp_udp.src_port = cmd->fs.h_u.tcp_ip4_spec.psrc;
+ spec_l4->tcp_udp.dst_port = cmd->fs.h_u.tcp_ip4_spec.pdst;
+ } else {
+ mlx4_en_ethtool_add_mac_rule_by_ipv4(priv, cmd, list_h,
+ spec_l2,
+ cmd->fs.h_u.
+ udp_ip4_spec.ip4dst);
+ spec_l4->id = MLX4_NET_TRANS_RULE_ID_UDP;
+ spec_l3->ipv4.src_ip = cmd->fs.h_u.udp_ip4_spec.ip4src;
+ spec_l3->ipv4.dst_ip = cmd->fs.h_u.udp_ip4_spec.ip4dst;
+ spec_l4->tcp_udp.src_port = cmd->fs.h_u.udp_ip4_spec.psrc;
+ spec_l4->tcp_udp.dst_port = cmd->fs.h_u.udp_ip4_spec.pdst;
+ }
+
+ if (l4_mask->ip4src)
+ spec_l3->ipv4.src_ip_msk = MLX4_BE_WORD_MASK;
+ if (l4_mask->ip4dst)
+ spec_l3->ipv4.dst_ip_msk = MLX4_BE_WORD_MASK;
+
+ if (l4_mask->psrc)
+ spec_l4->tcp_udp.src_port_msk = MLX4_BE_SHORT_MASK;
+ if (l4_mask->pdst)
+ spec_l4->tcp_udp.dst_port_msk = MLX4_BE_SHORT_MASK;
+
+ list_add_tail(&spec_l3->list, list_h);
+ list_add_tail(&spec_l4->list, list_h);
+
+ return 0;
+}
+
+static int mlx4_en_ethtool_to_net_trans_rule(struct net_device *dev,
+ struct mlx4_ethtool_rxnfc *cmd,
+ struct list_head *rule_list_h)
+{
+ int err;
+ struct ethhdr *eth_spec;
+ struct mlx4_spec_list *spec_l2;
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+
+ err = mlx4_en_validate_flow(dev, cmd);
+ if (err)
+ return err;
+
+ switch (cmd->fs.flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) {
+ case ETHER_FLOW:
+ spec_l2 = kzalloc(sizeof(*spec_l2), GFP_KERNEL);
+ if (!spec_l2)
+ return -ENOMEM;
+
+ eth_spec = &cmd->fs.h_u.ether_spec;
+ mlx4_en_ethtool_add_mac_rule(cmd, rule_list_h, spec_l2, &eth_spec->h_dest[0]);
+ spec_l2->eth.ether_type = eth_spec->h_proto;
+ if (eth_spec->h_proto)
+ spec_l2->eth.ether_type_enable = 1;
+ break;
+ case IP_USER_FLOW:
+ err = add_ip_rule(priv, cmd, rule_list_h);
+ break;
+ case TCP_V4_FLOW:
+ err = add_tcp_udp_rule(priv, cmd, rule_list_h, TCP_V4_FLOW);
+ break;
+ case UDP_V4_FLOW:
+ err = add_tcp_udp_rule(priv, cmd, rule_list_h, UDP_V4_FLOW);
+ break;
+ }
+
+ return err;
+}
+
+static int mlx4_en_flow_replace(struct net_device *dev,
+ struct mlx4_ethtool_rxnfc *cmd)
+{
+ int err;
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct ethtool_flow_id *loc_rule;
+ struct mlx4_spec_list *spec, *tmp_spec;
+ u32 qpn;
+ u64 reg_id;
+
+ struct mlx4_net_trans_rule rule = {
+ .queue_mode = MLX4_NET_TRANS_Q_FIFO,
+ .exclusive = 0,
+ .allow_loopback = 1,
+ .promisc_mode = MLX4_FS_REGULAR,
+ };
+
+ rule.port = priv->port;
+ rule.priority = MLX4_DOMAIN_ETHTOOL | cmd->fs.location;
+ INIT_LIST_HEAD(&rule.list);
+
+ /* Allow direct QP attaches if the EN_ETHTOOL_QP_ATTACH flag is set */
+ if (cmd->fs.ring_cookie == RX_CLS_FLOW_DISC)
+ qpn = priv->drop_qp.qpn;
+ else if (cmd->fs.ring_cookie & EN_ETHTOOL_QP_ATTACH) {
+ qpn = cmd->fs.ring_cookie & (EN_ETHTOOL_QP_ATTACH - 1);
+ } else {
+ if (cmd->fs.ring_cookie >= priv->rx_ring_num) {
+ en_warn(priv, "rxnfc: RX ring (%llu) doesn't exist.\n",
+ cmd->fs.ring_cookie);
+ return -EINVAL;
+ }
+ qpn = priv->rss_map.qps[cmd->fs.ring_cookie].qpn;
+ if (!qpn) {
+ en_warn(priv, "rxnfc: RX ring (%llu) is inactive.\n",
+ cmd->fs.ring_cookie);
+ return -EINVAL;
+ }
+ }
+ rule.qpn = qpn;
+ err = mlx4_en_ethtool_to_net_trans_rule(dev, cmd, &rule.list);
+ if (err)
+ goto out_free_list;
+
+ mutex_lock(&mdev->state_lock);
+ loc_rule = &priv->ethtool_rules[cmd->fs.location];
+ if (loc_rule->id) {
+ err = mlx4_flow_detach(priv->mdev->dev, loc_rule->id);
+ if (err) {
+ en_err(priv, "Fail to detach network rule at location %d. registration id = %llx\n",
+ cmd->fs.location, loc_rule->id);
+ goto unlock;
+ }
+ loc_rule->id = 0;
+ memset(&loc_rule->flow_spec, 0,
+ sizeof(struct ethtool_rx_flow_spec));
+ list_del(&loc_rule->list);
+ }
+ err = mlx4_flow_attach(priv->mdev->dev, &rule, &reg_id);
+ if (err) {
+ en_err(priv, "Fail to attach network rule at location %d.\n",
+ cmd->fs.location);
+ goto unlock;
+ }
+ loc_rule->id = reg_id;
+ memcpy(&loc_rule->flow_spec, &cmd->fs,
+ sizeof(struct ethtool_rx_flow_spec));
+ list_add_tail(&loc_rule->list, &priv->ethtool_list);
+
+unlock:
+ mutex_unlock(&mdev->state_lock);
+out_free_list:
+ list_for_each_entry_safe(spec, tmp_spec, &rule.list, list) {
+ list_del(&spec->list);
+ kfree(spec);
+ }
+ return err;
+}
+
+static int mlx4_en_flow_detach(struct net_device *dev,
+ struct mlx4_ethtool_rxnfc *cmd)
+{
+ int err = 0;
+ struct ethtool_flow_id *rule;
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+
+ if (cmd->fs.location >= MAX_NUM_OF_FS_RULES)
+ return -EINVAL;
+
+ mutex_lock(&mdev->state_lock);
+ rule = &priv->ethtool_rules[cmd->fs.location];
+ if (!rule->id) {
+ err = -ENOENT;
+ goto out;
+ }
+
+ err = mlx4_flow_detach(priv->mdev->dev, rule->id);
+ if (err) {
+ en_err(priv, "Fail to detach network rule at location %d. registration id = 0x%llx\n",
+ cmd->fs.location, rule->id);
+ goto out;
+ }
+ rule->id = 0;
+ memset(&rule->flow_spec, 0, sizeof(struct ethtool_rx_flow_spec));
+
+ list_del(&rule->list);
+out:
+ mutex_unlock(&mdev->state_lock);
+ return err;
+
+}
+
+static int mlx4_en_get_flow(struct net_device *dev, struct mlx4_ethtool_rxnfc *cmd,
+ int loc)
+{
+ int err = 0;
+ struct ethtool_flow_id *rule;
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+
+ if (loc < 0 || loc >= MAX_NUM_OF_FS_RULES)
+ return -EINVAL;
+
+ rule = &priv->ethtool_rules[loc];
+ if (rule->id)
+ memcpy(&cmd->fs, &rule->flow_spec,
+ sizeof(struct ethtool_rx_flow_spec));
+ else
+ err = -ENOENT;
+
+ return err;
+}
+
+static int mlx4_en_get_num_flows(struct mlx4_en_priv *priv)
+{
+
+ int i, res = 0;
+ for (i = 0; i < MAX_NUM_OF_FS_RULES; i++) {
+ if (priv->ethtool_rules[i].id)
+ res++;
+ }
+ return res;
+
+}
+
+static int mlx4_en_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *c,
+ u32 *rule_locs)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int err = 0;
+ int i = 0, priority = 0;
+ struct mlx4_ethtool_rxnfc *cmd = (struct mlx4_ethtool_rxnfc *)c;
+
+ if ((cmd->cmd == ETHTOOL_GRXCLSRLCNT ||
+ cmd->cmd == ETHTOOL_GRXCLSRULE ||
+ cmd->cmd == ETHTOOL_GRXCLSRLALL) &&
+ (mdev->dev->caps.steering_mode !=
+ MLX4_STEERING_MODE_DEVICE_MANAGED || !priv->port_up))
+ return -EINVAL;
+
+ switch (cmd->cmd) {
+ case ETHTOOL_GRXRINGS:
+ cmd->data = priv->rx_ring_num;
+ break;
+ case ETHTOOL_GRXCLSRLCNT:
+ cmd->rule_cnt = mlx4_en_get_num_flows(priv);
+ break;
+ case ETHTOOL_GRXCLSRULE:
+ err = mlx4_en_get_flow(dev, cmd, cmd->fs.location);
+ break;
+ case ETHTOOL_GRXCLSRLALL:
+ while ((!err || err == -ENOENT) && priority < cmd->rule_cnt) {
+ err = mlx4_en_get_flow(dev, cmd, i);
+ if (!err)
+ rule_locs[priority++] = i;
+ i++;
+ }
+ err = 0;
+ break;
+ default:
+ err = -EOPNOTSUPP;
+ break;
+ }
+
+ return err;
+}
+
+static int mlx4_en_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *c)
+{
+ int err = 0;
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_ethtool_rxnfc *cmd = (struct mlx4_ethtool_rxnfc *)c;
+
+ if (mdev->dev->caps.steering_mode !=
+ MLX4_STEERING_MODE_DEVICE_MANAGED || !priv->port_up)
+ return -EINVAL;
+
+ switch (cmd->cmd) {
+ case ETHTOOL_SRXCLSRLINS:
+ err = mlx4_en_flow_replace(dev, cmd);
+ break;
+ case ETHTOOL_SRXCLSRLDEL:
+ err = mlx4_en_flow_detach(dev, cmd);
+ break;
+ default:
+ en_warn(priv, "Unsupported ethtool command. (%d)\n", cmd->cmd);
+ return -EINVAL;
+ }
+
+ return err;
+}
+
+static void mlx4_en_get_channels(struct net_device *dev,
+ struct ethtool_channels *channel)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+
+ memset(channel, 0, sizeof(*channel));
+
+ channel->max_rx = MAX_RX_RINGS;
+ channel->max_tx = MLX4_EN_MAX_TX_RING_P_UP;
+
+ channel->rx_count = priv->rx_ring_num;
+ channel->tx_count = priv->tx_ring_num / MLX4_EN_NUM_UP;
+}
+
+static int mlx4_en_set_channels(struct net_device *dev,
+ struct ethtool_channels *channel)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int port_up = 0;
+ int i;
+ int err = 0;
+
+ if (channel->other_count || channel->combined_count ||
+ channel->tx_count > MLX4_EN_MAX_TX_RING_P_UP ||
+ channel->rx_count > MAX_RX_RINGS ||
+ !channel->tx_count || !channel->rx_count)
+ return -EINVAL;
+
+ err = mlx4_en_pre_config(priv);
+ if (err)
+ return err;
+
+ mutex_lock(&mdev->state_lock);
+ if (priv->port_up) {
+ port_up = 1;
+ mlx4_en_stop_port(dev);
+ }
+
+ mlx4_en_free_resources(priv);
+
+ priv->num_tx_rings_p_up = channel->tx_count;
+ priv->tx_ring_num = channel->tx_count * MLX4_EN_NUM_UP;
+ priv->rx_ring_num = channel->rx_count;
+
+ err = mlx4_en_alloc_resources(priv);
+ if (err) {
+ en_err(priv, "Failed reallocating port resources\n");
+ goto out;
+ }
+
+ netif_set_real_num_tx_queues(dev, priv->tx_ring_num);
+ netif_set_real_num_rx_queues(dev, priv->rx_ring_num);
+
+ mlx4_en_setup_tc(dev, MLX4_EN_NUM_UP);
+
+ en_warn(priv, "Using %d TX rings\n", priv->tx_ring_num);
+ en_warn(priv, "Using %d RX rings\n", priv->rx_ring_num);
+
+ if (port_up) {
+ err = mlx4_en_start_port(dev);
+ if (err)
+ en_err(priv, "Failed starting port\n");
+
+ for (i = 0; i < priv->rx_ring_num; i++) {
+ priv->rx_cq[i]->moder_cnt = priv->rx_frames;
+ priv->rx_cq[i]->moder_time = priv->rx_usecs;
+ priv->last_moder_time[i] = MLX4_EN_AUTO_CONF;
+ err = mlx4_en_set_cq_moder(priv, priv->rx_cq[i]);
+ if (err)
+ goto out;
+ }
+ }
+
+out:
+ mutex_unlock(&mdev->state_lock);
+ return err;
+}
+
+static int mlx4_en_get_ts_info(struct net_device *dev,
+ struct ethtool_ts_info *info)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int ret;
+
+ ret = ethtool_op_get_ts_info(dev, info);
+ if (ret)
+ return ret;
+
+ if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS) {
+ info->so_timestamping |=
+ SOF_TIMESTAMPING_TX_HARDWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE |
+ SOF_TIMESTAMPING_RAW_HARDWARE;
+
+ info->tx_types =
+ (1 << HWTSTAMP_TX_OFF) |
+ (1 << HWTSTAMP_TX_ON);
+
+ info->rx_filters =
+ (1 << HWTSTAMP_FILTER_NONE) |
+ (1 << HWTSTAMP_FILTER_ALL);
+ }
+
+ return ret;
}
const struct ethtool_ops mlx4_en_ethtool_ops = {
.get_drvinfo = mlx4_en_get_drvinfo,
.get_settings = mlx4_en_get_settings,
.set_settings = mlx4_en_set_settings,
-#ifdef NETIF_F_TSO
- .get_tso = mlx4_en_get_tso,
- .set_tso = mlx4_en_set_tso,
-#endif
- .get_sg = ethtool_op_get_sg,
- .set_sg = ethtool_op_set_sg,
.get_link = ethtool_op_get_link,
- .get_rx_csum = mlx4_en_get_rx_csum,
- .set_rx_csum = mlx4_en_set_rx_csum,
- .get_tx_csum = ethtool_op_get_tx_csum,
- .set_tx_csum = ethtool_op_set_tx_ipv6_csum,
.get_strings = mlx4_en_get_strings,
.get_sset_count = mlx4_en_get_sset_count,
.get_ethtool_stats = mlx4_en_get_ethtool_stats,
@@ -513,8 +1601,14 @@ const struct ethtool_ops mlx4_en_ethtool_ops = {
.set_pauseparam = mlx4_en_set_pauseparam,
.get_ringparam = mlx4_en_get_ringparam,
.set_ringparam = mlx4_en_set_ringparam,
- .get_flags = ethtool_op_get_flags,
- .set_flags = ethtool_op_set_flags,
+ .get_rxnfc = mlx4_en_get_rxnfc,
+ .set_rxnfc = mlx4_en_set_rxnfc,
+ .get_rxfh_indir_size = mlx4_en_get_rxfh_indir_size,
+ .get_rxfh_indir = mlx4_en_get_rxfh_indir,
+ .set_rxfh_indir = mlx4_en_set_rxfh_indir,
+ .get_channels = mlx4_en_get_channels,
+ .set_channels = mlx4_en_set_channels,
+ .get_ts_info = mlx4_en_get_ts_info,
};
diff --git a/sys/ofed/drivers/net/mlx4/en_main.c b/sys/ofed/drivers/net/mlx4/en_main.c
index 302be52..cbbf37d 100644
--- a/sys/ofed/drivers/net/mlx4/en_main.c
+++ b/sys/ofed/drivers/net/mlx4/en_main.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2007, 2014 Mellanox Technologies. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -34,6 +34,7 @@
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
+#include <linux/slab.h>
#include <linux/mlx4/driver.h>
#include <linux/mlx4/device.h>
@@ -60,20 +61,9 @@ static const char mlx4_en_version[] =
* Device scope module parameters
*/
-
-/* Enable RSS TCP traffic */
-MLX4_EN_PARM_INT(tcp_rss, 1,
- "Enable RSS for incomming TCP traffic or disabled (0)");
/* Enable RSS UDP traffic */
MLX4_EN_PARM_INT(udp_rss, 1,
- "Enable RSS for incomming UDP traffic or disabled (0)");
-
-/* Number of LRO sessions per Rx ring (rounded up to a power of two) */
-MLX4_EN_PARM_INT(num_lro, MLX4_EN_MAX_LRO_DESCRIPTORS,
- "Number of LRO sessions per ring or disabled (0)");
-
-/* Allow reassembly of fragmented IP packets */
-MLX4_EN_PARM_INT(ip_reasm, 1, "Allow reassembly of fragmented IP packets (!0)");
+ "Enable RSS for incoming UDP traffic");
/* Priority pausing */
MLX4_EN_PARM_INT(pfctx, 0, "Priority based Flow Control policy on TX[7:0]."
@@ -81,20 +71,23 @@ MLX4_EN_PARM_INT(pfctx, 0, "Priority based Flow Control policy on TX[7:0]."
MLX4_EN_PARM_INT(pfcrx, 0, "Priority based Flow Control policy on RX[7:0]."
" Per priority bit mask");
+#define MAX_PFC_TX 0xff
+#define MAX_PFC_RX 0xff
+
+
static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
{
struct mlx4_en_profile *params = &mdev->profile;
int i;
- params->tcp_rss = tcp_rss;
params->udp_rss = udp_rss;
- if (params->udp_rss && !(mdev->dev->caps.flags
- & MLX4_DEV_CAP_FLAG_UDP_RSS)) {
+ params->num_tx_rings_p_up = min_t(int, mp_ncpus,
+ MLX4_EN_MAX_TX_RING_P_UP);
+ if (params->udp_rss && !(mdev->dev->caps.flags
+ & MLX4_DEV_CAP_FLAG_UDP_RSS)) {
mlx4_warn(mdev, "UDP RSS is not supported on this device.\n");
params->udp_rss = 0;
}
- params->num_lro = min_t(int, num_lro , MLX4_EN_MAX_LRO_DESCRIPTORS);
- params->ip_reasm = ip_reasm;
for (i = 1; i <= MLX4_MAX_PORTS; i++) {
params->prof[i].rx_pause = 1;
params->prof[i].rx_ppp = pfcrx;
@@ -102,14 +95,15 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
params->prof[i].tx_ppp = pfctx;
params->prof[i].tx_ring_size = MLX4_EN_DEF_TX_RING_SIZE;
params->prof[i].rx_ring_size = MLX4_EN_DEF_RX_RING_SIZE;
- params->prof[i].tx_ring_num = MLX4_EN_NUM_HASH_RINGS + 1 +
- (!!pfcrx) * MLX4_EN_NUM_PPP_RINGS;
+ params->prof[i].tx_ring_num = params->num_tx_rings_p_up *
+ MLX4_EN_NUM_UP;
+ params->prof[i].rss_rings = 0;
}
return 0;
}
-static void *get_netdev(struct mlx4_dev *dev, void *ctx, u8 port)
+static void *mlx4_en_get_netdev(struct mlx4_dev *dev, void *ctx, u8 port)
{
struct mlx4_en_dev *endev = ctx;
@@ -138,6 +132,9 @@ static void mlx4_en_event(struct mlx4_dev *dev, void *endev_ptr,
mlx4_err(mdev, "Internal error detected, restarting device\n");
break;
+ case MLX4_DEV_EVENT_SLAVE_INIT:
+ case MLX4_DEV_EVENT_SLAVE_SHUTDOWN:
+ break;
default:
if (port < 1 || port > dev->caps.num_ports ||
!mdev->pndev[port])
@@ -150,7 +147,7 @@ static void mlx4_en_event(struct mlx4_dev *dev, void *endev_ptr,
static void mlx4_en_remove(struct mlx4_dev *dev, void *endev_ptr)
{
struct mlx4_en_dev *mdev = endev_ptr;
- int i;
+ int i, ret;
mutex_lock(&mdev->state_lock);
mdev->device_up = false;
@@ -162,25 +159,22 @@ static void mlx4_en_remove(struct mlx4_dev *dev, void *endev_ptr)
flush_workqueue(mdev->workqueue);
destroy_workqueue(mdev->workqueue);
- mlx4_mr_free(dev, &mdev->mr);
+ ret = mlx4_mr_free(dev, &mdev->mr);
+ if (ret)
+ mlx4_err(mdev, "Error deregistering MR. The system may have become unstable.");
+ iounmap(mdev->uar_map);
mlx4_uar_free(dev, &mdev->priv_uar);
mlx4_pd_free(dev, mdev->priv_pdn);
- sx_destroy(&mdev->state_lock.sx);
- mtx_destroy(&mdev->uar_lock.m);
kfree(mdev);
}
static void *mlx4_en_add(struct mlx4_dev *dev)
{
- static int mlx4_en_version_printed;
struct mlx4_en_dev *mdev;
int i;
int err;
- if (!mlx4_en_version_printed) {
- printk(KERN_INFO "%s", mlx4_en_version);
- mlx4_en_version_printed++;
- }
+ printk_once(KERN_INFO "%s", mlx4_en_version);
mdev = kzalloc(sizeof *mdev, GFP_KERNEL);
if (!mdev) {
@@ -196,10 +190,11 @@ static void *mlx4_en_add(struct mlx4_dev *dev)
if (mlx4_uar_alloc(dev, &mdev->priv_uar))
goto err_pd;
- mtx_init(&mdev->uar_lock.m, "mlx4 uar", NULL, MTX_DEF);
- mdev->uar_map = ioremap(mdev->priv_uar.pfn << PAGE_SHIFT, PAGE_SIZE);
+ mdev->uar_map = ioremap((phys_addr_t) mdev->priv_uar.pfn << PAGE_SHIFT,
+ PAGE_SIZE);
if (!mdev->uar_map)
goto err_uar;
+ spin_lock_init(&mdev->uar_lock);
mdev->dev = dev;
mdev->dma_device = &(dev->pdev->dev);
@@ -215,7 +210,7 @@ static void *mlx4_en_add(struct mlx4_dev *dev)
MLX4_PERM_LOCAL_WRITE | MLX4_PERM_LOCAL_READ,
0, 0, &mdev->mr)) {
mlx4_err(mdev, "Failed allocating memory region\n");
- goto err_uar;
+ goto err_map;
}
if (mlx4_mr_enable(mdev->dev, &mdev->mr)) {
mlx4_err(mdev, "Failed enabling memory region\n");
@@ -229,21 +224,24 @@ static void *mlx4_en_add(struct mlx4_dev *dev)
goto err_mr;
}
- /* Configure wich ports to start according to module parameters */
+ /* Configure which ports to start according to module parameters */
mdev->port_cnt = 0;
mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH)
mdev->port_cnt++;
- /* If we did not receive an explicit number of Rx rings, default to
- * the number of completion vectors populated by the mlx4_core */
- mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) {
- mlx4_info(mdev, "Using %d tx rings for port:%d\n",
- mdev->profile.prof[i].tx_ring_num, i);
- mdev->profile.prof[i].rx_ring_num = rounddown_pow_of_two(
- min_t(int, dev->caps.num_comp_vectors, MAX_RX_RINGS));
- mlx4_info(mdev, "Defaulting to %d rx rings for port:%d\n",
- mdev->profile.prof[i].rx_ring_num, i);
+ mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) {
+ if (!dev->caps.comp_pool) {
+ mdev->profile.prof[i].rx_ring_num =
+ rounddown_pow_of_two(max_t(int, MIN_RX_RINGS,
+ min_t(int,
+ dev->caps.num_comp_vectors,
+ DEF_RX_RINGS)));
+ } else {
+ mdev->profile.prof[i].rx_ring_num = rounddown_pow_of_two(
+ min_t(int, dev->caps.comp_pool/
+ dev->caps.num_ports - 1 , MAX_MSIX_P_PORT - 1));
+ }
}
/* Create our own workqueue for reset/multicast tasks
@@ -257,7 +255,7 @@ static void *mlx4_en_add(struct mlx4_dev *dev)
/* At this stage all non-port specific tasks are complete:
* mark the card state as up */
- sx_init(&mdev->state_lock.sx, "mlxen state");
+ mutex_init(&mdev->state_lock);
mdev->device_up = true;
/* Setup ports */
@@ -265,32 +263,20 @@ static void *mlx4_en_add(struct mlx4_dev *dev)
/* Create a netdev for each port */
mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) {
mlx4_info(mdev, "Activating port:%d\n", i);
- if (mlx4_en_init_netdev(mdev, i, &mdev->profile.prof[i])) {
+ if (mlx4_en_init_netdev(mdev, i, &mdev->profile.prof[i]))
mdev->pndev[i] = NULL;
- goto err_free_netdev;
- }
- }
- return mdev;
-
-
-err_free_netdev:
- mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) {
- if (mdev->pndev[i])
- mlx4_en_destroy_netdev(mdev->pndev[i]);
}
- mutex_lock(&mdev->state_lock);
- mdev->device_up = false;
- mutex_unlock(&mdev->state_lock);
- flush_workqueue(mdev->workqueue);
-
- /* Stop event queue before we drop down to release shared SW state */
- destroy_workqueue(mdev->workqueue);
+ return mdev;
err_mr:
- mlx4_mr_free(dev, &mdev->mr);
+ err = mlx4_mr_free(dev, &mdev->mr);
+ if (err)
+ mlx4_err(mdev, "Error deregistering MR. The system may have become unstable.");
+err_map:
+ if (mdev->uar_map)
+ iounmap(mdev->uar_map);
err_uar:
- mtx_destroy(&mdev->uar_lock.m);
mlx4_uar_free(dev, &mdev->priv_uar);
err_pd:
mlx4_pd_free(dev, mdev->priv_pdn);
@@ -300,73 +286,51 @@ err_free_res:
return NULL;
}
-enum mlx4_query_reply mlx4_en_query(void *endev_ptr, void *int_dev)
-{
- struct mlx4_en_dev *mdev = endev_ptr;
- struct net_device *netdev = int_dev;
- int p;
-
- for (p = 1; p <= MLX4_MAX_PORTS; ++p)
- if (mdev->pndev[p] == netdev)
- return p;
-
- return MLX4_QUERY_NOT_MINE;
-}
-
-#if 0
-static struct pci_device_id mlx4_en_pci_table[] = {
- { PCI_VDEVICE(MELLANOX, 0x6340) }, /* MT25408 "Hermon" SDR */
- { PCI_VDEVICE(MELLANOX, 0x634a) }, /* MT25408 "Hermon" DDR */
- { PCI_VDEVICE(MELLANOX, 0x6354) }, /* MT25408 "Hermon" QDR */
- { PCI_VDEVICE(MELLANOX, 0x6732) }, /* MT25408 "Hermon" DDR PCIe gen2 */
- { PCI_VDEVICE(MELLANOX, 0x673c) }, /* MT25408 "Hermon" QDR PCIe gen2 */
- { PCI_VDEVICE(MELLANOX, 0x6368) }, /* MT25408 "Hermon" EN 10GigE */
- { PCI_VDEVICE(MELLANOX, 0x6750) }, /* MT25408 "Hermon" EN 10GigE PCIe gen2 */
- { PCI_VDEVICE(MELLANOX, 0x6372) }, /* MT25458 ConnectX EN 10GBASE-T 10GigE */
- { PCI_VDEVICE(MELLANOX, 0x675a) }, /* MT25458 ConnectX EN 10GBASE-T+Gen2 10GigE */
- { PCI_VDEVICE(MELLANOX, 0x6764) }, /* MT26468 ConnectX EN 10GigE PCIe gen2 */
- { PCI_VDEVICE(MELLANOX, 0x6746) }, /* MT26438 ConnectX VPI PCIe 2.0 5GT/s - IB QDR / 10GigE Virt+ */
- { PCI_VDEVICE(MELLANOX, 0x676e) }, /* MT26478 ConnectX EN 40GigE PCIe 2.0 5GT/s */
- { PCI_VDEVICE(MELLANOX, 0x6778) }, /* MT26488 ConnectX VPI PCIe 2.0 5GT/s - IB DDR / 10GigE Virt+ */
- { PCI_VDEVICE(MELLANOX, 0x1000) },
- { PCI_VDEVICE(MELLANOX, 0x1001) },
- { PCI_VDEVICE(MELLANOX, 0x1002) },
- { PCI_VDEVICE(MELLANOX, 0x1003) },
- { PCI_VDEVICE(MELLANOX, 0x1004) },
- { PCI_VDEVICE(MELLANOX, 0x1005) },
- { PCI_VDEVICE(MELLANOX, 0x1006) },
- { PCI_VDEVICE(MELLANOX, 0x1007) },
- { PCI_VDEVICE(MELLANOX, 0x1008) },
- { PCI_VDEVICE(MELLANOX, 0x1009) },
- { PCI_VDEVICE(MELLANOX, 0x100a) },
- { PCI_VDEVICE(MELLANOX, 0x100b) },
- { PCI_VDEVICE(MELLANOX, 0x100c) },
- { PCI_VDEVICE(MELLANOX, 0x100d) },
- { PCI_VDEVICE(MELLANOX, 0x100e) },
- { PCI_VDEVICE(MELLANOX, 0x100f) },
- { 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, mlx4_en_pci_table);
-#endif
-
static struct mlx4_interface mlx4_en_interface = {
- .add = mlx4_en_add,
- .remove = mlx4_en_remove,
- .event = mlx4_en_event,
- .query = mlx4_en_query,
- .get_dev = get_netdev,
+ .add = mlx4_en_add,
+ .remove = mlx4_en_remove,
+ .event = mlx4_en_event,
+ .get_dev = mlx4_en_get_netdev,
.protocol = MLX4_PROT_ETH,
};
+static void mlx4_en_verify_params(void)
+{
+ if (pfctx > MAX_PFC_TX) {
+ pr_warn("mlx4_en: WARNING: illegal module parameter pfctx 0x%x - "
+ "should be in range 0-0x%x, will be changed to default (0)\n",
+ pfctx, MAX_PFC_TX);
+ pfctx = 0;
+ }
+
+ if (pfcrx > MAX_PFC_RX) {
+ pr_warn("mlx4_en: WARNING: illegal module parameter pfcrx 0x%x - "
+ "should be in range 0-0x%x, will be changed to default (0)\n",
+ pfcrx, MAX_PFC_RX);
+ pfcrx = 0;
+ }
+}
+
+
static int __init mlx4_en_init(void)
{
+ mlx4_en_verify_params();
+
+#ifdef CONFIG_DEBUG_FS
+ int err = 0;
+ err = mlx4_en_register_debugfs();
+ if (err)
+ pr_err(KERN_ERR "Failed to register debugfs\n");
+#endif
return mlx4_register_interface(&mlx4_en_interface);
}
static void __exit mlx4_en_cleanup(void)
{
mlx4_unregister_interface(&mlx4_en_interface);
+#ifdef CONFIG_DEBUG_FS
+ mlx4_en_unregister_debugfs();
+#endif
}
module_init(mlx4_en_init);
diff --git a/sys/ofed/drivers/net/mlx4/en_netdev.c b/sys/ofed/drivers/net/mlx4/en_netdev.c
index d8b015b..e76da65 100644
--- a/sys/ofed/drivers/net/mlx4/en_netdev.c
+++ b/sys/ofed/drivers/net/mlx4/en_netdev.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2007, 2014 Mellanox Technologies. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -31,221 +31,809 @@
*
*/
-#include "mlx4_en.h"
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#ifdef CONFIG_NET_RX_BUSY_POLL
+#include <net/busy_poll.h>
+#endif
+
+#include <linux/list.h>
+#include <linux/if_ether.h>
#include <linux/mlx4/driver.h>
#include <linux/mlx4/device.h>
#include <linux/mlx4/cmd.h>
#include <linux/mlx4/cq.h>
-#include <linux/delay.h>
-#include <net/ethernet.h>
-#include <net/if_vlan_var.h>
#include <sys/sockio.h>
#include <sys/sysctl.h>
-static void mlx4_en_init_locked(struct mlx4_en_priv *priv);
+#include "mlx4_en.h"
+#include "en_port.h"
+
static void mlx4_en_sysctl_stat(struct mlx4_en_priv *priv);
+static void mlx4_en_sysctl_conf(struct mlx4_en_priv *priv);
+static int mlx4_en_unit;
+
+#ifdef CONFIG_NET_RX_BUSY_POLL
+/* must be called with local_bh_disable()d */
+static int mlx4_en_low_latency_recv(struct napi_struct *napi)
+{
+ struct mlx4_en_cq *cq = container_of(napi, struct mlx4_en_cq, napi);
+ struct net_device *dev = cq->dev;
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_rx_ring *rx_ring = priv->rx_ring[cq->ring];
+ int done;
+
+ if (!priv->port_up)
+ return LL_FLUSH_FAILED;
+
+ if (!mlx4_en_cq_lock_poll(cq))
+ return LL_FLUSH_BUSY;
+
+ done = mlx4_en_process_rx_cq(dev, cq, 4);
+#ifdef LL_EXTENDED_STATS
+ if (done)
+ rx_ring->cleaned += done;
+ else
+ rx_ring->misses++;
+#endif
+
+ mlx4_en_cq_unlock_poll(cq);
+
+ return done;
+}
+#endif /* CONFIG_NET_RX_BUSY_POLL */
+
+#ifdef CONFIG_RFS_ACCEL
+
+struct mlx4_en_filter {
+ struct list_head next;
+ struct work_struct work;
+
+ u8 ip_proto;
+ __be32 src_ip;
+ __be32 dst_ip;
+ __be16 src_port;
+ __be16 dst_port;
+
+ int rxq_index;
+ struct mlx4_en_priv *priv;
+ u32 flow_id; /* RFS infrastructure id */
+ int id; /* mlx4_en driver id */
+ u64 reg_id; /* Flow steering API id */
+ u8 activated; /* Used to prevent expiry before filter
+ * is attached
+ */
+ struct hlist_node filter_chain;
+};
+
+static void mlx4_en_filter_rfs_expire(struct mlx4_en_priv *priv);
+
+static enum mlx4_net_trans_rule_id mlx4_ip_proto_to_trans_rule_id(u8 ip_proto)
+{
+ switch (ip_proto) {
+ case IPPROTO_UDP:
+ return MLX4_NET_TRANS_RULE_ID_UDP;
+ case IPPROTO_TCP:
+ return MLX4_NET_TRANS_RULE_ID_TCP;
+ default:
+ return -EPROTONOSUPPORT;
+ }
+};
+
+static void mlx4_en_filter_work(struct work_struct *work)
+{
+ struct mlx4_en_filter *filter = container_of(work,
+ struct mlx4_en_filter,
+ work);
+ struct mlx4_en_priv *priv = filter->priv;
+ struct mlx4_spec_list spec_tcp_udp = {
+ .id = mlx4_ip_proto_to_trans_rule_id(filter->ip_proto),
+ {
+ .tcp_udp = {
+ .dst_port = filter->dst_port,
+ .dst_port_msk = (__force __be16)-1,
+ .src_port = filter->src_port,
+ .src_port_msk = (__force __be16)-1,
+ },
+ },
+ };
+ struct mlx4_spec_list spec_ip = {
+ .id = MLX4_NET_TRANS_RULE_ID_IPV4,
+ {
+ .ipv4 = {
+ .dst_ip = filter->dst_ip,
+ .dst_ip_msk = (__force __be32)-1,
+ .src_ip = filter->src_ip,
+ .src_ip_msk = (__force __be32)-1,
+ },
+ },
+ };
+ struct mlx4_spec_list spec_eth = {
+ .id = MLX4_NET_TRANS_RULE_ID_ETH,
+ };
+ struct mlx4_net_trans_rule rule = {
+ .list = LIST_HEAD_INIT(rule.list),
+ .queue_mode = MLX4_NET_TRANS_Q_LIFO,
+ .exclusive = 1,
+ .allow_loopback = 1,
+ .promisc_mode = MLX4_FS_REGULAR,
+ .port = priv->port,
+ .priority = MLX4_DOMAIN_RFS,
+ };
+ int rc;
+ __be64 mac_mask = cpu_to_be64(MLX4_MAC_MASK << 16);
+
+ if (spec_tcp_udp.id < 0) {
+ en_warn(priv, "RFS: ignoring unsupported ip protocol (%d)\n",
+ filter->ip_proto);
+ goto ignore;
+ }
+ list_add_tail(&spec_eth.list, &rule.list);
+ list_add_tail(&spec_ip.list, &rule.list);
+ list_add_tail(&spec_tcp_udp.list, &rule.list);
+
+ rule.qpn = priv->rss_map.qps[filter->rxq_index].qpn;
+ memcpy(spec_eth.eth.dst_mac, priv->dev->dev_addr, ETH_ALEN);
+ memcpy(spec_eth.eth.dst_mac_msk, &mac_mask, ETH_ALEN);
+
+ filter->activated = 0;
+
+ if (filter->reg_id) {
+ rc = mlx4_flow_detach(priv->mdev->dev, filter->reg_id);
+ if (rc && rc != -ENOENT)
+ en_err(priv, "Error detaching flow. rc = %d\n", rc);
+ }
+
+ rc = mlx4_flow_attach(priv->mdev->dev, &rule, &filter->reg_id);
+ if (rc)
+ en_err(priv, "Error attaching flow. err = %d\n", rc);
+
+ignore:
+ mlx4_en_filter_rfs_expire(priv);
+
+ filter->activated = 1;
+}
+
+static inline struct hlist_head *
+filter_hash_bucket(struct mlx4_en_priv *priv, __be32 src_ip, __be32 dst_ip,
+ __be16 src_port, __be16 dst_port)
+{
+ unsigned long l;
+ int bucket_idx;
+
+ l = (__force unsigned long)src_port |
+ ((__force unsigned long)dst_port << 2);
+ l ^= (__force unsigned long)(src_ip ^ dst_ip);
+
+ bucket_idx = hash_long(l, MLX4_EN_FILTER_HASH_SHIFT);
+
+ return &priv->filter_hash[bucket_idx];
+}
+
+static struct mlx4_en_filter *
+mlx4_en_filter_alloc(struct mlx4_en_priv *priv, int rxq_index, __be32 src_ip,
+ __be32 dst_ip, u8 ip_proto, __be16 src_port,
+ __be16 dst_port, u32 flow_id)
+{
+ struct mlx4_en_filter *filter = NULL;
+
+ filter = kzalloc(sizeof(struct mlx4_en_filter), GFP_ATOMIC);
+ if (!filter)
+ return NULL;
+
+ filter->priv = priv;
+ filter->rxq_index = rxq_index;
+ INIT_WORK(&filter->work, mlx4_en_filter_work);
+
+ filter->src_ip = src_ip;
+ filter->dst_ip = dst_ip;
+ filter->ip_proto = ip_proto;
+ filter->src_port = src_port;
+ filter->dst_port = dst_port;
+
+ filter->flow_id = flow_id;
+
+ filter->id = priv->last_filter_id++ % RPS_NO_FILTER;
+
+ list_add_tail(&filter->next, &priv->filters);
+ hlist_add_head(&filter->filter_chain,
+ filter_hash_bucket(priv, src_ip, dst_ip, src_port,
+ dst_port));
+
+ return filter;
+}
+
+static void mlx4_en_filter_free(struct mlx4_en_filter *filter)
+{
+ struct mlx4_en_priv *priv = filter->priv;
+ int rc;
+
+ list_del(&filter->next);
+
+ rc = mlx4_flow_detach(priv->mdev->dev, filter->reg_id);
+ if (rc && rc != -ENOENT)
+ en_err(priv, "Error detaching flow. rc = %d\n", rc);
+
+ kfree(filter);
+}
+
+static inline struct mlx4_en_filter *
+mlx4_en_filter_find(struct mlx4_en_priv *priv, __be32 src_ip, __be32 dst_ip,
+ u8 ip_proto, __be16 src_port, __be16 dst_port)
+{
+ struct hlist_node *elem;
+ struct mlx4_en_filter *filter;
+ struct mlx4_en_filter *ret = NULL;
+
+ hlist_for_each_entry(filter, elem,
+ filter_hash_bucket(priv, src_ip, dst_ip,
+ src_port, dst_port),
+ filter_chain) {
+ if (filter->src_ip == src_ip &&
+ filter->dst_ip == dst_ip &&
+ filter->ip_proto == ip_proto &&
+ filter->src_port == src_port &&
+ filter->dst_port == dst_port) {
+ ret = filter;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int
+mlx4_en_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
+ u16 rxq_index, u32 flow_id)
+{
+ struct mlx4_en_priv *priv = netdev_priv(net_dev);
+ struct mlx4_en_filter *filter;
+ const struct iphdr *ip;
+ const __be16 *ports;
+ u8 ip_proto;
+ __be32 src_ip;
+ __be32 dst_ip;
+ __be16 src_port;
+ __be16 dst_port;
+ int nhoff = skb_network_offset(skb);
+ int ret = 0;
+
+ if (skb->protocol != htons(ETH_P_IP))
+ return -EPROTONOSUPPORT;
+
+ ip = (const struct iphdr *)(skb->data + nhoff);
+ if (ip_is_fragment(ip))
+ return -EPROTONOSUPPORT;
+
+ if ((ip->protocol != IPPROTO_TCP) && (ip->protocol != IPPROTO_UDP))
+ return -EPROTONOSUPPORT;
+ ports = (const __be16 *)(skb->data + nhoff + 4 * ip->ihl);
+
+ ip_proto = ip->protocol;
+ src_ip = ip->saddr;
+ dst_ip = ip->daddr;
+ src_port = ports[0];
+ dst_port = ports[1];
+
+ spin_lock_bh(&priv->filters_lock);
+ filter = mlx4_en_filter_find(priv, src_ip, dst_ip, ip_proto,
+ src_port, dst_port);
+ if (filter) {
+ if (filter->rxq_index == rxq_index)
+ goto out;
+
+ filter->rxq_index = rxq_index;
+ } else {
+ filter = mlx4_en_filter_alloc(priv, rxq_index,
+ src_ip, dst_ip, ip_proto,
+ src_port, dst_port, flow_id);
+ if (!filter) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ }
+
+ queue_work(priv->mdev->workqueue, &filter->work);
+
+out:
+ ret = filter->id;
+err:
+ spin_unlock_bh(&priv->filters_lock);
+
+ return ret;
+}
+
+void mlx4_en_cleanup_filters(struct mlx4_en_priv *priv,
+ struct mlx4_en_rx_ring *rx_ring)
+{
+ struct mlx4_en_filter *filter, *tmp;
+ LIST_HEAD(del_list);
+
+ spin_lock_bh(&priv->filters_lock);
+ list_for_each_entry_safe(filter, tmp, &priv->filters, next) {
+ list_move(&filter->next, &del_list);
+ hlist_del(&filter->filter_chain);
+ }
+ spin_unlock_bh(&priv->filters_lock);
+
+ list_for_each_entry_safe(filter, tmp, &del_list, next) {
+ cancel_work_sync(&filter->work);
+ mlx4_en_filter_free(filter);
+ }
+}
+
+static void mlx4_en_filter_rfs_expire(struct mlx4_en_priv *priv)
+{
+ struct mlx4_en_filter *filter = NULL, *tmp, *last_filter = NULL;
+ LIST_HEAD(del_list);
+ int i = 0;
+
+ spin_lock_bh(&priv->filters_lock);
+ list_for_each_entry_safe(filter, tmp, &priv->filters, next) {
+ if (i > MLX4_EN_FILTER_EXPIRY_QUOTA)
+ break;
+
+ if (filter->activated &&
+ !work_pending(&filter->work) &&
+ rps_may_expire_flow(priv->dev,
+ filter->rxq_index, filter->flow_id,
+ filter->id)) {
+ list_move(&filter->next, &del_list);
+ hlist_del(&filter->filter_chain);
+ } else
+ last_filter = filter;
+
+ i++;
+ }
+
+ if (last_filter && (&last_filter->next != priv->filters.next))
+ list_move(&priv->filters, &last_filter->next);
+
+ spin_unlock_bh(&priv->filters_lock);
+
+ list_for_each_entry_safe(filter, tmp, &del_list, next)
+ mlx4_en_filter_free(filter);
+}
+#endif
static void mlx4_en_vlan_rx_add_vid(void *arg, struct net_device *dev, u16 vid)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int err;
int idx;
- u8 field;
if (arg != priv)
return;
- if ((vid == 0) || (vid > 4095)) /* Invalid */
- return;
en_dbg(HW, priv, "adding VLAN:%d\n", vid);
- idx = vid >> 5;
- field = 1 << (vid & 0x1f);
- spin_lock(&priv->vlan_lock);
- priv->vlgrp_modified = true;
- if (priv->vlan_unregister[idx] & field)
- priv->vlan_unregister[idx] &= ~field;
- else
- priv->vlan_register[idx] |= field;
- priv->vlans[idx] |= field;
- spin_unlock(&priv->vlan_lock);
+
+ set_bit(vid, priv->active_vlans);
+
+ /* Add VID to port VLAN filter */
+ mutex_lock(&mdev->state_lock);
+ if (mdev->device_up && priv->port_up) {
+ err = mlx4_SET_VLAN_FLTR(mdev->dev, priv);
+ if (err)
+ en_err(priv, "Failed configuring VLAN filter\n");
+ }
+ if (mlx4_register_vlan(mdev->dev, priv->port, vid, &idx))
+ en_dbg(HW, priv, "failed adding vlan %d\n", vid);
+ mutex_unlock(&mdev->state_lock);
+
}
static void mlx4_en_vlan_rx_kill_vid(void *arg, struct net_device *dev, u16 vid)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
- int idx;
- u8 field;
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int err;
if (arg != priv)
return;
- if ((vid == 0) || (vid > 4095)) /* Invalid */
- return;
en_dbg(HW, priv, "Killing VID:%d\n", vid);
- idx = vid >> 5;
- field = 1 << (vid & 0x1f);
- spin_lock(&priv->vlan_lock);
- priv->vlgrp_modified = true;
- if (priv->vlan_register[idx] & field)
- priv->vlan_register[idx] &= ~field;
- else
- priv->vlan_unregister[idx] |= field;
- priv->vlans[idx] &= ~field;
- spin_unlock(&priv->vlan_lock);
+
+ clear_bit(vid, priv->active_vlans);
+
+ /* Remove VID from port VLAN filter */
+ mutex_lock(&mdev->state_lock);
+ mlx4_unregister_vlan(mdev->dev, priv->port, vid);
+
+ if (mdev->device_up && priv->port_up) {
+ err = mlx4_SET_VLAN_FLTR(mdev->dev, priv);
+ if (err)
+ en_err(priv, "Failed configuring VLAN filter\n");
+ }
+ mutex_unlock(&mdev->state_lock);
+
}
-u64 mlx4_en_mac_to_u64(u8 *addr)
+static int mlx4_en_uc_steer_add(struct mlx4_en_priv *priv,
+ unsigned char *mac, int *qpn, u64 *reg_id)
{
- u64 mac = 0;
- int i;
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_dev *dev = mdev->dev;
+ int err;
+
+ switch (dev->caps.steering_mode) {
+ case MLX4_STEERING_MODE_B0: {
+ struct mlx4_qp qp;
+ u8 gid[16] = {0};
+
+ qp.qpn = *qpn;
+ memcpy(&gid[10], mac, ETH_ALEN);
+ gid[5] = priv->port;
- for (i = 0; i < ETHER_ADDR_LEN; i++) {
- mac <<= 8;
- mac |= addr[i];
+ err = mlx4_unicast_attach(dev, &qp, gid, 0, MLX4_PROT_ETH);
+ break;
+ }
+ case MLX4_STEERING_MODE_DEVICE_MANAGED: {
+ struct mlx4_spec_list spec_eth = { {NULL} };
+ __be64 mac_mask = cpu_to_be64(MLX4_MAC_MASK << 16);
+
+ struct mlx4_net_trans_rule rule = {
+ .queue_mode = MLX4_NET_TRANS_Q_FIFO,
+ .exclusive = 0,
+ .allow_loopback = 1,
+ .promisc_mode = MLX4_FS_REGULAR,
+ .priority = MLX4_DOMAIN_NIC,
+ };
+
+ rule.port = priv->port;
+ rule.qpn = *qpn;
+ INIT_LIST_HEAD(&rule.list);
+
+ spec_eth.id = MLX4_NET_TRANS_RULE_ID_ETH;
+ memcpy(spec_eth.eth.dst_mac, mac, ETH_ALEN);
+ memcpy(spec_eth.eth.dst_mac_msk, &mac_mask, ETH_ALEN);
+ list_add_tail(&spec_eth.list, &rule.list);
+
+ err = mlx4_flow_attach(dev, &rule, reg_id);
+ break;
}
- return mac;
+ default:
+ return -EINVAL;
+ }
+ if (err)
+ en_warn(priv, "Failed Attaching Unicast\n");
+
+ return err;
}
-static int mlx4_en_cache_mclist(struct net_device *dev, u64 **mcaddrp)
+static void mlx4_en_uc_steer_release(struct mlx4_en_priv *priv,
+ unsigned char *mac, int qpn, u64 reg_id)
{
- struct ifmultiaddr *ifma;
- u64 *mcaddr;
- int cnt;
- int i;
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_dev *dev = mdev->dev;
- *mcaddrp = NULL;
-restart:
- cnt = 0;
- if_maddr_rlock(dev);
- TAILQ_FOREACH(ifma, &dev->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- if (((struct sockaddr_dl *)ifma->ifma_addr)->sdl_alen !=
- ETHER_ADDR_LEN)
- continue;
- cnt++;
- }
- if_maddr_runlock(dev);
- if (cnt == 0)
- return (0);
- mcaddr = kmalloc(sizeof(u64) * cnt, GFP_KERNEL);
- if (mcaddr == NULL)
- return (0);
- i = 0;
- if_maddr_rlock(dev);
- TAILQ_FOREACH(ifma, &dev->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_LINK)
- continue;
- if (((struct sockaddr_dl *)ifma->ifma_addr)->sdl_alen !=
- ETHER_ADDR_LEN)
- continue;
- /* Make sure the list didn't grow. */
- if (i == cnt) {
- if_maddr_runlock(dev);
- kfree(mcaddr);
- goto restart;
- }
- mcaddr[i++] = mlx4_en_mac_to_u64(
- LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
+ switch (dev->caps.steering_mode) {
+ case MLX4_STEERING_MODE_B0: {
+ struct mlx4_qp qp;
+ u8 gid[16] = {0};
+
+ qp.qpn = qpn;
+ memcpy(&gid[10], mac, ETH_ALEN);
+ gid[5] = priv->port;
+
+ mlx4_unicast_detach(dev, &qp, gid, MLX4_PROT_ETH);
+ break;
+ }
+ case MLX4_STEERING_MODE_DEVICE_MANAGED: {
+ mlx4_flow_detach(dev, reg_id);
+ break;
+ }
+ default:
+ en_err(priv, "Invalid steering mode.\n");
}
- if_maddr_runlock(dev);
- *mcaddrp = mcaddr;
- return (i);
}
-static void mlx4_en_stop_port(struct net_device *dev)
+static int mlx4_en_get_qp(struct mlx4_en_priv *priv)
{
- struct mlx4_en_priv *priv = netdev_priv(dev);
-
- queue_work(priv->mdev->workqueue, &priv->stop_port_task);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_dev *dev = mdev->dev;
+ struct mlx4_mac_entry *entry;
+ int index = 0;
+ int err = 0;
+ u64 reg_id;
+ int *qpn = &priv->base_qpn;
+ u64 mac = mlx4_mac_to_u64(IF_LLADDR(priv->dev));
+
+ en_dbg(DRV, priv, "Registering MAC: %pM for adding\n",
+ IF_LLADDR(priv->dev));
+ index = mlx4_register_mac(dev, priv->port, mac);
+ if (index < 0) {
+ err = index;
+ en_err(priv, "Failed adding MAC: %pM\n",
+ IF_LLADDR(priv->dev));
+ return err;
+ }
+
+ if (dev->caps.steering_mode == MLX4_STEERING_MODE_A0) {
+ int base_qpn = mlx4_get_base_qpn(dev, priv->port);
+ *qpn = base_qpn + index;
+ return 0;
+ }
+
+ err = mlx4_qp_reserve_range(dev, 1, 1, qpn, 0);
+ en_dbg(DRV, priv, "Reserved qp %d\n", *qpn);
+ if (err) {
+ en_err(priv, "Failed to reserve qp for mac registration\n");
+ goto qp_err;
+ }
+
+ err = mlx4_en_uc_steer_add(priv, IF_LLADDR(priv->dev), qpn, &reg_id);
+ if (err)
+ goto steer_err;
+
+ entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry) {
+ err = -ENOMEM;
+ goto alloc_err;
+ }
+ memcpy(entry->mac, IF_LLADDR(priv->dev), sizeof(entry->mac));
+ entry->reg_id = reg_id;
+
+ hlist_add_head(&entry->hlist,
+ &priv->mac_hash[entry->mac[MLX4_EN_MAC_HASH_IDX]]);
+
+ return 0;
+
+alloc_err:
+ mlx4_en_uc_steer_release(priv, IF_LLADDR(priv->dev), *qpn, reg_id);
+
+steer_err:
+ mlx4_qp_release_range(dev, *qpn, 1);
+
+qp_err:
+ mlx4_unregister_mac(dev, priv->port, mac);
+ return err;
}
-static void mlx4_en_start_port(struct net_device *dev)
+static void mlx4_en_put_qp(struct mlx4_en_priv *priv)
{
- struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_dev *dev = mdev->dev;
+ int qpn = priv->base_qpn;
+ u64 mac;
+
+ if (dev->caps.steering_mode == MLX4_STEERING_MODE_A0) {
+ mac = mlx4_mac_to_u64(IF_LLADDR(priv->dev));
+ en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n",
+ IF_LLADDR(priv->dev));
+ mlx4_unregister_mac(dev, priv->port, mac);
+ } else {
+ struct mlx4_mac_entry *entry;
+ struct hlist_node *n, *tmp;
+ struct hlist_head *bucket;
+ unsigned int i;
+
+ for (i = 0; i < MLX4_EN_MAC_HASH_SIZE; ++i) {
+ bucket = &priv->mac_hash[i];
+ hlist_for_each_entry_safe(entry, n, tmp, bucket, hlist) {
+ mac = mlx4_mac_to_u64(entry->mac);
+ en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n",
+ entry->mac);
+ mlx4_en_uc_steer_release(priv, entry->mac,
+ qpn, entry->reg_id);
+
+ mlx4_unregister_mac(dev, priv->port, mac);
+ hlist_del(&entry->hlist);
+ kfree(entry);
+ }
+ }
- queue_work(priv->mdev->workqueue, &priv->start_port_task);
+ en_dbg(DRV, priv, "Releasing qp: port %d, qpn %d\n",
+ priv->port, qpn);
+ mlx4_qp_release_range(dev, qpn, 1);
+ priv->flags &= ~MLX4_EN_FLAG_FORCE_PROMISC;
+ }
}
-static void mlx4_en_set_multicast(struct net_device *dev)
+static void mlx4_en_clear_list(struct net_device *dev)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_mc_list *tmp, *mc_to_del;
- if (!priv->port_up)
- return;
+ list_for_each_entry_safe(mc_to_del, tmp, &priv->mc_list, list) {
+ list_del(&mc_to_del->list);
+ kfree(mc_to_del);
+ }
+}
+
+static void mlx4_en_cache_mclist(struct net_device *dev)
+{
+ struct ifmultiaddr *ifma;
+ struct mlx4_en_mc_list *tmp;
+ struct mlx4_en_priv *priv = netdev_priv(dev);
- queue_work(priv->mdev->workqueue, &priv->mcast_task);
+ TAILQ_FOREACH(ifma, &dev->if_multiaddrs, ifma_link) {
+ if (ifma->ifma_addr->sa_family != AF_LINK)
+ continue;
+ if (((struct sockaddr_dl *)ifma->ifma_addr)->sdl_alen !=
+ ETHER_ADDR_LEN)
+ continue;
+ /* Make sure the list didn't grow. */
+ tmp = kzalloc(sizeof(struct mlx4_en_mc_list), GFP_ATOMIC);
+ memcpy(tmp->addr,
+ LLADDR((struct sockaddr_dl *)ifma->ifma_addr), ETH_ALEN);
+ list_add_tail(&tmp->list, &priv->mc_list);
+ }
}
-static void mlx4_en_do_set_multicast(struct work_struct *work)
+static void update_mclist_flags(struct mlx4_en_priv *priv,
+ struct list_head *dst,
+ struct list_head *src)
{
- struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv,
- mcast_task);
- struct net_device *dev = priv->dev;
- struct mlx4_en_dev *mdev = priv->mdev;
- int err;
+ struct mlx4_en_mc_list *dst_tmp, *src_tmp, *new_mc;
+ bool found;
- mutex_lock(&mdev->state_lock);
- if (!mdev->device_up) {
- en_dbg(HW, priv, "Card is not up, "
- "ignoring multicast change.\n");
- goto out;
- }
- if (!priv->port_up) {
- en_dbg(HW, priv, "Port is down, "
- "ignoring multicast change.\n");
- goto out;
+ /* Find all the entries that should be removed from dst,
+ * These are the entries that are not found in src
+ */
+ list_for_each_entry(dst_tmp, dst, list) {
+ found = false;
+ list_for_each_entry(src_tmp, src, list) {
+ if (!memcmp(dst_tmp->addr, src_tmp->addr, ETH_ALEN)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ dst_tmp->action = MCLIST_REM;
}
- /*
- * Promsicuous mode: disable all filters
+ /* Add entries that exist in src but not in dst
+ * mark them as need to add
*/
+ list_for_each_entry(src_tmp, src, list) {
+ found = false;
+ list_for_each_entry(dst_tmp, dst, list) {
+ if (!memcmp(dst_tmp->addr, src_tmp->addr, ETH_ALEN)) {
+ dst_tmp->action = MCLIST_NONE;
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ new_mc = kmalloc(sizeof(struct mlx4_en_mc_list),
+ GFP_KERNEL);
+ if (!new_mc) {
+ en_err(priv, "Failed to allocate current multicast list\n");
+ return;
+ }
+ memcpy(new_mc, src_tmp,
+ sizeof(struct mlx4_en_mc_list));
+ new_mc->action = MCLIST_ADD;
+ list_add_tail(&new_mc->list, dst);
+ }
+ }
+}
- if (dev->if_flags & IFF_PROMISC) {
- if (!(priv->flags & MLX4_EN_FLAG_PROMISC)) {
- priv->flags |= MLX4_EN_FLAG_PROMISC;
+static void mlx4_en_set_rx_mode(struct net_device *dev)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
- /* Enable promiscouos mode */
- err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port,
- priv->base_qpn, 1);
+ if (!priv->port_up)
+ return;
+
+ queue_work(priv->mdev->workqueue, &priv->rx_mode_task);
+}
+
+static void mlx4_en_set_promisc_mode(struct mlx4_en_priv *priv,
+ struct mlx4_en_dev *mdev)
+{
+ int err = 0;
+ if (!(priv->flags & MLX4_EN_FLAG_PROMISC)) {
+ priv->flags |= MLX4_EN_FLAG_PROMISC;
+
+ /* Enable promiscouos mode */
+ switch (mdev->dev->caps.steering_mode) {
+ case MLX4_STEERING_MODE_DEVICE_MANAGED:
+ err = mlx4_flow_steer_promisc_add(mdev->dev,
+ priv->port,
+ priv->base_qpn,
+ MLX4_FS_ALL_DEFAULT);
if (err)
- en_err(priv, "Failed enabling "
- "promiscous mode\n");
+ en_err(priv, "Failed enabling promiscuous mode\n");
+ priv->flags |= MLX4_EN_FLAG_MC_PROMISC;
+ break;
- /* Disable port multicast filter (unconditionally) */
- err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
- 0, MLX4_MCAST_DISABLE);
+ case MLX4_STEERING_MODE_B0:
+ err = mlx4_unicast_promisc_add(mdev->dev,
+ priv->base_qpn,
+ priv->port);
if (err)
- en_err(priv, "Failed disabling "
- "multicast filter\n");
+ en_err(priv, "Failed enabling unicast promiscuous mode\n");
+
+ /* Add the default qp number as multicast
+ * promisc
+ */
+ if (!(priv->flags & MLX4_EN_FLAG_MC_PROMISC)) {
+ err = mlx4_multicast_promisc_add(mdev->dev,
+ priv->base_qpn,
+ priv->port);
+ if (err)
+ en_err(priv, "Failed enabling multicast promiscuous mode\n");
+ priv->flags |= MLX4_EN_FLAG_MC_PROMISC;
+ }
+ break;
- /* Disable port VLAN filter */
- err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, NULL);
+ case MLX4_STEERING_MODE_A0:
+ err = mlx4_SET_PORT_qpn_calc(mdev->dev,
+ priv->port,
+ priv->base_qpn,
+ 1);
if (err)
- en_err(priv, "Failed disabling VLAN filter\n");
+ en_err(priv, "Failed enabling promiscuous mode\n");
+ break;
}
- goto out;
+
+ /* Disable port multicast filter (unconditionally) */
+ err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
+ 0, MLX4_MCAST_DISABLE);
+ if (err)
+ en_err(priv, "Failed disabling multicast filter\n");
}
+}
- /*
- * Not in promiscous mode
- */
+static void mlx4_en_clear_promisc_mode(struct mlx4_en_priv *priv,
+ struct mlx4_en_dev *mdev)
+{
+ int err = 0;
- if (priv->flags & MLX4_EN_FLAG_PROMISC) {
- priv->flags &= ~MLX4_EN_FLAG_PROMISC;
+ priv->flags &= ~MLX4_EN_FLAG_PROMISC;
- /* Disable promiscouos mode */
- err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port,
- priv->base_qpn, 0);
+ /* Disable promiscouos mode */
+ switch (mdev->dev->caps.steering_mode) {
+ case MLX4_STEERING_MODE_DEVICE_MANAGED:
+ err = mlx4_flow_steer_promisc_remove(mdev->dev,
+ priv->port,
+ MLX4_FS_ALL_DEFAULT);
+ if (err)
+ en_err(priv, "Failed disabling promiscuous mode\n");
+ priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;
+ break;
+
+ case MLX4_STEERING_MODE_B0:
+ err = mlx4_unicast_promisc_remove(mdev->dev,
+ priv->base_qpn,
+ priv->port);
if (err)
- en_err(priv, "Failed disabling promiscous mode\n");
+ en_err(priv, "Failed disabling unicast promiscuous mode\n");
+ /* Disable Multicast promisc */
+ if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) {
+ err = mlx4_multicast_promisc_remove(mdev->dev,
+ priv->base_qpn,
+ priv->port);
+ if (err)
+ en_err(priv, "Failed disabling multicast promiscuous mode\n");
+ priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;
+ }
+ break;
- /* Enable port VLAN filter */
- err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlans);
+ case MLX4_STEERING_MODE_A0:
+ err = mlx4_SET_PORT_qpn_calc(mdev->dev,
+ priv->port,
+ priv->base_qpn, 0);
if (err)
- en_err(priv, "Failed enabling VLAN filter\n");
+ en_err(priv, "Failed disabling promiscuous mode\n");
+ break;
}
+}
+
+static void mlx4_en_do_multicast(struct mlx4_en_priv *priv,
+ struct net_device *dev,
+ struct mlx4_en_dev *mdev)
+{
+ struct mlx4_en_mc_list *mclist, *tmp;
+ u8 mc_list[16] = {0};
+ int err = 0;
+ u64 mcast_addr = 0;
+
/* Enable/disable the multicast filter according to IFF_ALLMULTI */
if (dev->if_flags & IFF_ALLMULTI) {
@@ -253,10 +841,53 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
0, MLX4_MCAST_DISABLE);
if (err)
en_err(priv, "Failed disabling multicast filter\n");
+
+ /* Add the default qp number as multicast promisc */
+ if (!(priv->flags & MLX4_EN_FLAG_MC_PROMISC)) {
+ switch (mdev->dev->caps.steering_mode) {
+ case MLX4_STEERING_MODE_DEVICE_MANAGED:
+ err = mlx4_flow_steer_promisc_add(mdev->dev,
+ priv->port,
+ priv->base_qpn,
+ MLX4_FS_MC_DEFAULT);
+ break;
+
+ case MLX4_STEERING_MODE_B0:
+ err = mlx4_multicast_promisc_add(mdev->dev,
+ priv->base_qpn,
+ priv->port);
+ break;
+
+ case MLX4_STEERING_MODE_A0:
+ break;
+ }
+ if (err)
+ en_err(priv, "Failed entering multicast promisc mode\n");
+ priv->flags |= MLX4_EN_FLAG_MC_PROMISC;
+ }
} else {
- u64 *mcaddr;
- int mccount;
- int i;
+ /* Disable Multicast promisc */
+ if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) {
+ switch (mdev->dev->caps.steering_mode) {
+ case MLX4_STEERING_MODE_DEVICE_MANAGED:
+ err = mlx4_flow_steer_promisc_remove(mdev->dev,
+ priv->port,
+ MLX4_FS_MC_DEFAULT);
+ break;
+
+ case MLX4_STEERING_MODE_B0:
+ err = mlx4_multicast_promisc_remove(mdev->dev,
+ priv->base_qpn,
+ priv->port);
+ break;
+
+ case MLX4_STEERING_MODE_A0:
+ break;
+ }
+ if (err)
+ en_err(priv, "Failed disabling multicast promiscuous mode\n");
+ priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;
+ }
err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
0, MLX4_MCAST_DISABLE);
@@ -269,17 +900,93 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
/* Update multicast list - we cache all addresses so they won't
* change while HW is updated holding the command semaphor */
- mccount = mlx4_en_cache_mclist(dev, &mcaddr);
- for (i = 0; i < mccount; i++)
+ mlx4_en_cache_mclist(dev);
+ list_for_each_entry(mclist, &priv->mc_list, list) {
+ mcast_addr = mlx4_mac_to_u64(mclist->addr);
mlx4_SET_MCAST_FLTR(mdev->dev, priv->port,
- mcaddr[i], 0, MLX4_MCAST_CONFIG);
+ mcast_addr, 0, MLX4_MCAST_CONFIG);
+ }
err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
0, MLX4_MCAST_ENABLE);
if (err)
en_err(priv, "Failed enabling multicast filter\n");
- kfree(mcaddr);
+ update_mclist_flags(priv, &priv->curr_list, &priv->mc_list);
+ list_for_each_entry_safe(mclist, tmp, &priv->curr_list, list) {
+ if (mclist->action == MCLIST_REM) {
+ /* detach this address and delete from list */
+ memcpy(&mc_list[10], mclist->addr, ETH_ALEN);
+ mc_list[5] = priv->port;
+ err = mlx4_multicast_detach(mdev->dev,
+ &priv->rss_map.indir_qp,
+ mc_list,
+ MLX4_PROT_ETH,
+ mclist->reg_id);
+ if (err)
+ en_err(priv, "Fail to detach multicast address\n");
+
+ /* remove from list */
+ list_del(&mclist->list);
+ kfree(mclist);
+ } else if (mclist->action == MCLIST_ADD) {
+ /* attach the address */
+ memcpy(&mc_list[10], mclist->addr, ETH_ALEN);
+ /* needed for B0 steering support */
+ mc_list[5] = priv->port;
+ err = mlx4_multicast_attach(mdev->dev,
+ &priv->rss_map.indir_qp,
+ mc_list,
+ priv->port, 0,
+ MLX4_PROT_ETH,
+ &mclist->reg_id);
+ if (err)
+ en_err(priv, "Fail to attach multicast address\n");
+
+ }
+ }
}
+}
+
+static void mlx4_en_do_set_rx_mode(struct work_struct *work)
+{
+ struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv,
+ rx_mode_task);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ struct net_device *dev = priv->dev;
+
+
+ mutex_lock(&mdev->state_lock);
+ if (!mdev->device_up) {
+ en_dbg(HW, priv, "Card is not up, ignoring rx mode change.\n");
+ goto out;
+ }
+ if (!priv->port_up) {
+ en_dbg(HW, priv, "Port is down, ignoring rx mode change.\n");
+ goto out;
+ }
+ if (!mlx4_en_QUERY_PORT(mdev, priv->port)) {
+ if (priv->port_state.link_state) {
+ priv->last_link_state = MLX4_DEV_EVENT_PORT_UP;
+ /* Important note: the following call for if_link_state_change
+ * is needed for interface up scenario (start port, link state
+ * change) */
+ if_link_state_change(priv->dev, LINK_STATE_UP);
+ en_dbg(HW, priv, "Link Up\n");
+ }
+ }
+
+ /* Promsicuous mode: disable all filters */
+ if ((dev->if_flags & IFF_PROMISC) ||
+ (priv->flags & MLX4_EN_FLAG_FORCE_PROMISC)) {
+ mlx4_en_set_promisc_mode(priv, mdev);
+ goto out;
+ }
+
+ /* Not in promiscuous mode */
+ if (priv->flags & MLX4_EN_FLAG_PROMISC)
+ mlx4_en_clear_promisc_mode(priv, mdev);
+
+ mlx4_en_do_multicast(priv, dev, mdev);
out:
mutex_unlock(&mdev->state_lock);
}
@@ -293,7 +1000,7 @@ static void mlx4_en_netpoll(struct net_device *dev)
int i;
for (i = 0; i < priv->rx_ring_num; i++) {
- cq = &priv->rx_cq[i];
+ cq = priv->rx_cq[i];
spin_lock_irqsave(&cq->lock, flags);
napi_synchronize(&cq->napi);
mlx4_en_process_rx_cq(dev, cq, 0);
@@ -304,38 +1011,40 @@ static void mlx4_en_netpoll(struct net_device *dev)
static void mlx4_en_watchdog_timeout(void *arg)
{
- struct mlx4_en_priv *priv = arg;
- struct mlx4_en_dev *mdev = priv->mdev;
-
- en_dbg(DRV, priv, "Scheduling watchdog\n");
- queue_work(mdev->workqueue, &priv->watchdog_task);
- if (priv->port_up)
- callout_reset(&priv->watchdog_timer, MLX4_EN_WATCHDOG_TIMEOUT,
- mlx4_en_watchdog_timeout, priv);
+ struct mlx4_en_priv *priv = arg;
+ struct mlx4_en_dev *mdev = priv->mdev;
+
+ en_dbg(DRV, priv, "Scheduling watchdog\n");
+ queue_work(mdev->workqueue, &priv->watchdog_task);
+ if (priv->port_up)
+ callout_reset(&priv->watchdog_timer, MLX4_EN_WATCHDOG_TIMEOUT,
+ mlx4_en_watchdog_timeout, priv);
}
-/* XXX This clears user settings in too many cases. */
+
static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv)
{
struct mlx4_en_cq *cq;
int i;
/* If we haven't received a specific coalescing setting
- * (module param), we set the moderation paramters as follows:
+ * (module param), we set the moderation parameters as follows:
* - moder_cnt is set to the number of mtu sized packets to
* satisfy our coelsing target.
* - moder_time is set to a fixed value.
*/
priv->rx_frames = MLX4_EN_RX_COAL_TARGET / priv->dev->if_mtu + 1;
priv->rx_usecs = MLX4_EN_RX_COAL_TIME;
- en_dbg(INTR, priv, "Default coalesing params for mtu:%u - "
- "rx_frames:%d rx_usecs:%d\n",
- priv->dev->if_mtu, priv->rx_frames, priv->rx_usecs);
+ priv->tx_frames = MLX4_EN_TX_COAL_PKTS;
+ priv->tx_usecs = MLX4_EN_TX_COAL_TIME;
+ en_dbg(INTR, priv, "Default coalesing params for mtu: %u - "
+ "rx_frames:%d rx_usecs:%d\n",
+ (unsigned)priv->dev->if_mtu, priv->rx_frames, priv->rx_usecs);
/* Setup cq moderation params */
for (i = 0; i < priv->rx_ring_num; i++) {
- cq = &priv->rx_cq[i];
+ cq = priv->rx_cq[i];
cq->moder_cnt = priv->rx_frames;
cq->moder_time = priv->rx_usecs;
priv->last_moder_time[i] = MLX4_EN_AUTO_CONF;
@@ -344,9 +1053,9 @@ static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv)
}
for (i = 0; i < priv->tx_ring_num; i++) {
- cq = &priv->tx_cq[i];
- cq->moder_cnt = MLX4_EN_TX_COAL_PKTS;
- cq->moder_time = MLX4_EN_TX_COAL_TIME;
+ cq = priv->tx_cq[i];
+ cq->moder_cnt = priv->tx_frames;
+ cq->moder_time = priv->tx_usecs;
}
/* Reset auto-moderation params */
@@ -375,10 +1084,11 @@ static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
if (!priv->adaptive_rx_coal || period < priv->sample_interval * HZ)
return;
+
for (ring = 0; ring < priv->rx_ring_num; ring++) {
- spin_lock(&priv->stats_lock);
- rx_packets = priv->rx_ring[ring].packets;
- rx_bytes = priv->rx_ring[ring].bytes;
+ spin_lock(&priv->stats_lock);
+ rx_packets = priv->rx_ring[ring]->packets;
+ rx_bytes = priv->rx_ring[ring]->bytes;
spin_unlock(&priv->stats_lock);
rx_pkt_diff = ((unsigned long) (rx_packets -
@@ -389,11 +1099,10 @@ static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
priv->last_moder_bytes[ring])) / packets : 0;
/* Apply auto-moderation only when packet rate
- * exceeds a rate that it matters */
+ * exceeds a rate that it matters */
if (rate > (MLX4_EN_RX_RATE_THRESH / priv->rx_ring_num) &&
- avg_pkt_size > MLX4_EN_AVG_PKT_SMALL) {
- if (rate < priv->pkt_rate_low ||
- avg_pkt_size < MLX4_EN_AVG_PKT_SMALL)
+ avg_pkt_size > MLX4_EN_AVG_PKT_SMALL) {
+ if (rate < priv->pkt_rate_low)
moder_time = priv->rx_usecs_low;
else if (rate > priv->pkt_rate_high)
moder_time = priv->rx_usecs_high;
@@ -408,12 +1117,12 @@ static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
if (moder_time != priv->last_moder_time[ring]) {
priv->last_moder_time[ring] = moder_time;
- cq = &priv->rx_cq[ring];
+ cq = priv->rx_cq[ring];
cq->moder_time = moder_time;
err = mlx4_en_set_cq_moder(priv, cq);
if (err)
- en_err(priv, "Failed modifying moderation "
- "for cq:%d\n", ring);
+ en_err(priv, "Failed modifying moderation for cq:%d\n",
+ ring);
}
priv->last_moder_packets[ring] = rx_packets;
priv->last_moder_bytes[ring] = rx_bytes;
@@ -422,47 +1131,6 @@ static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
priv->last_moder_jiffies = jiffies;
}
-static void mlx4_en_handle_vlans(struct mlx4_en_priv *priv)
-{
- u8 vlan_register[VLAN_FLTR_SIZE];
- u8 vlan_unregister[VLAN_FLTR_SIZE];
- int i, j, idx;
- u16 vid;
-
- /* cache the vlan data for processing
- * done under lock to avoid changes during work */
- spin_lock(&priv->vlan_lock);
- for (i = 0; i < VLAN_FLTR_SIZE; i++) {
- vlan_register[i] = priv->vlan_register[i];
- priv->vlan_register[i] = 0;
- vlan_unregister[i] = priv->vlan_unregister[i];
- priv->vlan_unregister[i] = 0;
- }
- priv->vlgrp_modified = false;
- spin_unlock(&priv->vlan_lock);
-
- /* Configure the vlan filter
- * The vlgrp is updated with all the vids that need to be allowed */
- if (mlx4_SET_VLAN_FLTR(priv->mdev->dev, priv->port, priv->vlans))
- en_err(priv, "Failed configuring VLAN filter\n");
-
- /* Configure the VLAN table */
- for (i = 0; i < VLAN_FLTR_SIZE; i++) {
- for (j = 0; j < 32; j++) {
- vid = (i << 5) + j;
- if (vlan_register[i] & (1 << j))
- if (mlx4_register_vlan(priv->mdev->dev, priv->port, vid, &idx))
- en_dbg(HW, priv, "failed registering vlan %d\n", vid);
- if (vlan_unregister[i] & (1 << j)) {
- if (!mlx4_find_cached_vlan(priv->mdev->dev, priv->port, vid, &idx))
- mlx4_unregister_vlan(priv->mdev->dev, priv->port, idx);
- else
- en_dbg(HW, priv, "could not find vid %d in cache\n", vid);
- }
- }
- }
-}
-
static void mlx4_en_do_get_stats(struct work_struct *work)
{
struct delayed_work *delay = to_delayed_work(work);
@@ -471,23 +1139,36 @@ static void mlx4_en_do_get_stats(struct work_struct *work)
struct mlx4_en_dev *mdev = priv->mdev;
int err;
- err = mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 0);
- if (err)
- en_dbg(HW, priv, "Could not update stats \n");
-
-
mutex_lock(&mdev->state_lock);
if (mdev->device_up) {
if (priv->port_up) {
- if (priv->vlgrp_modified)
- mlx4_en_handle_vlans(priv);
+ err = mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 0);
+ if (err)
+ en_dbg(HW, priv, "Could not update stats\n");
mlx4_en_auto_moderation(priv);
}
queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
}
- mlx4_en_QUERY_PORT(priv->mdev, priv->port);
+ mutex_unlock(&mdev->state_lock);
+}
+
+/* mlx4_en_service_task - Run service task for tasks that needed to be done
+ * periodically
+ */
+static void mlx4_en_service_task(struct work_struct *work)
+{
+ struct delayed_work *delay = to_delayed_work(work);
+ struct mlx4_en_priv *priv = container_of(delay, struct mlx4_en_priv,
+ service_task);
+ struct mlx4_en_dev *mdev = priv->mdev;
+
+ mutex_lock(&mdev->state_lock);
+ if (mdev->device_up) {
+ queue_delayed_work(mdev->workqueue, &priv->service_task,
+ SERVICE_TASK_DELAY);
+ }
mutex_unlock(&mdev->state_lock);
}
@@ -503,8 +1184,15 @@ static void mlx4_en_linkstate(struct work_struct *work)
* report to system log */
if (priv->last_link_state != linkstate) {
if (linkstate == MLX4_DEV_EVENT_PORT_DOWN) {
+ en_info(priv, "Link Down\n");
if_link_state_change(priv->dev, LINK_STATE_DOWN);
- } else {
+ /* make sure the port is up before notifying the OS.
+ * This is tricky since we get here on INIT_PORT and
+ * in such case we can't tell the OS the port is up.
+ * To solve this there is a call to if_link_state_change
+ * in set_rx_mode.
+ * */
+ } else if (priv->port_up && (linkstate == MLX4_DEV_EVENT_PORT_UP)){
en_info(priv, "Link Up\n");
if_link_state_change(priv->dev, LINK_STATE_UP);
}
@@ -513,51 +1201,38 @@ static void mlx4_en_linkstate(struct work_struct *work)
mutex_unlock(&mdev->state_lock);
}
-static void mlx4_en_lock_and_stop_port(struct work_struct *work)
-{
- struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv,
- stop_port_task);
- struct net_device *dev = priv->dev;
- struct mlx4_en_dev *mdev = priv->mdev;
-
- mutex_lock(&mdev->state_lock);
- mlx4_en_do_stop_port(dev);
- mutex_unlock(&mdev->state_lock);
-}
-static void mlx4_en_lock_and_start_port(struct work_struct *work)
-{
- struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv,
- start_port_task);
- struct net_device *dev = priv->dev;
- struct mlx4_en_dev *mdev = priv->mdev;
-
- mutex_lock(&mdev->state_lock);
- mlx4_en_do_start_port(dev);
- mutex_unlock(&mdev->state_lock);
-}
-
-int mlx4_en_do_start_port(struct net_device *dev)
+int mlx4_en_start_port(struct net_device *dev)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
struct mlx4_en_dev *mdev = priv->mdev;
struct mlx4_en_cq *cq;
struct mlx4_en_tx_ring *tx_ring;
- u64 config;
int rx_index = 0;
int tx_index = 0;
int err = 0;
int i;
int j;
+ u8 mc_list[16] = {0};
+
if (priv->port_up) {
en_dbg(DRV, priv, "start port called while port already up\n");
return 0;
}
+ INIT_LIST_HEAD(&priv->mc_list);
+ INIT_LIST_HEAD(&priv->curr_list);
+ INIT_LIST_HEAD(&priv->ethtool_list);
+
/* Calculate Rx buf size */
dev->if_mtu = min(dev->if_mtu, priv->max_mtu);
- mlx4_en_calc_rx_buf(dev);
+ mlx4_en_calc_rx_buf(dev);
+ priv->rx_alloc_size = max_t(int, 2 * roundup_pow_of_two(priv->rx_mb_size),
+ PAGE_SIZE);
+ priv->rx_alloc_order = get_order(priv->rx_alloc_size);
+ priv->rx_buf_size = roundup_pow_of_two(priv->rx_mb_size);
+ priv->log_rx_info = ROUNDUP_LOG2(sizeof(struct mlx4_en_rx_buf));
en_dbg(DRV, priv, "Rx buf size:%d\n", priv->rx_mb_size);
/* Configure rx cq's and rings */
@@ -566,11 +1241,11 @@ int mlx4_en_do_start_port(struct net_device *dev)
en_err(priv, "Failed to activate RX rings\n");
return err;
}
-
for (i = 0; i < priv->rx_ring_num; i++) {
- cq = &priv->rx_cq[i];
+ cq = priv->rx_cq[i];
- err = mlx4_en_activate_cq(priv, cq);
+ mlx4_en_cq_init_lock(cq);
+ err = mlx4_en_activate_cq(priv, cq, i);
if (err) {
en_err(priv, "Failed activating Rx CQ\n");
goto cq_err;
@@ -584,21 +1259,41 @@ int mlx4_en_do_start_port(struct net_device *dev)
goto cq_err;
}
mlx4_en_arm_cq(priv, cq);
- priv->rx_ring[i].cqn = cq->mcq.cqn;
+ priv->rx_ring[i]->cqn = cq->mcq.cqn;
++rx_index;
}
+ /* Set qp number */
+ en_dbg(DRV, priv, "Getting qp number for port %d\n", priv->port);
+ err = mlx4_en_get_qp(priv);
+ if (err) {
+ en_err(priv, "Failed getting eth qp\n");
+ goto cq_err;
+ }
+ mdev->mac_removed[priv->port] = 0;
+
+ /* gets default allocated counter index from func cap */
+ /* or sink counter index if no resources */
+ priv->counter_index = mdev->dev->caps.def_counter_index[priv->port - 1];
+
+ en_dbg(DRV, priv, "%s: default counter index %d for port %d\n",
+ __func__, priv->counter_index, priv->port);
+
err = mlx4_en_config_rss_steer(priv);
if (err) {
en_err(priv, "Failed configuring rss steering\n");
- goto cq_err;
+ goto mac_err;
}
+ err = mlx4_en_create_drop_qp(priv);
+ if (err)
+ goto rss_err;
+
/* Configure tx cq's and rings */
for (i = 0; i < priv->tx_ring_num; i++) {
/* Configure cq */
- cq = &priv->tx_cq[i];
- err = mlx4_en_activate_cq(priv, cq);
+ cq = priv->tx_cq[i];
+ err = mlx4_en_activate_cq(priv, cq, i);
if (err) {
en_err(priv, "Failed allocating Tx CQ\n");
goto tx_err;
@@ -613,13 +1308,19 @@ int mlx4_en_do_start_port(struct net_device *dev)
cq->buf->wqe_index = cpu_to_be16(0xffff);
/* Configure ring */
- tx_ring = &priv->tx_ring[i];
- err = mlx4_en_activate_tx_ring(priv, tx_ring, cq->mcq.cqn);
+ tx_ring = priv->tx_ring[i];
+
+ err = mlx4_en_activate_tx_ring(priv, tx_ring, cq->mcq.cqn,
+ i / priv->num_tx_rings_p_up);
if (err) {
en_err(priv, "Failed allocating Tx ring\n");
mlx4_en_deactivate_cq(priv, cq);
goto tx_err;
}
+
+ /* Arm CQ for TX completions */
+ mlx4_en_arm_cq(priv, cq);
+
/* Set initial ownership of all Tx TXBBs to SW (1) */
for (j = 0; j < tx_ring->buf_size; j += STAMP_STRIDE)
*((u32 *) (tx_ring->buf + j)) = 0xffffffff;
@@ -628,14 +1329,14 @@ int mlx4_en_do_start_port(struct net_device *dev)
/* Configure port */
err = mlx4_SET_PORT_general(mdev->dev, priv->port,
- priv->rx_mb_size + ETHER_CRC_LEN,
+ priv->rx_mb_size,
priv->prof->tx_pause,
priv->prof->tx_ppp,
priv->prof->rx_pause,
priv->prof->rx_ppp);
if (err) {
- en_err(priv, "Failed setting port general configurations "
- "for port %d, with error %d\n", priv->port, err);
+ en_err(priv, "Failed setting port general configurations for port %d, with error %d\n",
+ priv->port, err);
goto tx_err;
}
/* Set default qp number */
@@ -644,134 +1345,166 @@ int mlx4_en_do_start_port(struct net_device *dev)
en_err(priv, "Failed setting default qp numbers\n");
goto tx_err;
}
- /* Set port mac number */
- en_dbg(DRV, priv, "Setting mac for port %d\n", priv->port);
- err = mlx4_register_mac(mdev->dev, priv->port,
- mlx4_en_mac_to_u64(IF_LLADDR(dev)));
- if (err < 0) {
- en_err(priv, "Failed setting port mac err=%d\n", err);
- goto tx_err;
- }
- mdev->mac_removed[priv->port] = 0;
/* Init port */
en_dbg(HW, priv, "Initializing port\n");
err = mlx4_INIT_PORT(mdev->dev, priv->port);
if (err) {
en_err(priv, "Failed Initializing port\n");
- goto mac_err;
+ goto tx_err;
}
- /* Set the various hardware offload abilities */
- dev->if_hwassist = 0;
- if (dev->if_capenable & IFCAP_TSO4)
- dev->if_hwassist |= CSUM_TSO;
- if (dev->if_capenable & IFCAP_TXCSUM)
- dev->if_hwassist |= (CSUM_TCP | CSUM_UDP | CSUM_IP);
- if (dev->if_capenable & IFCAP_RXCSUM)
- priv->rx_csum = 1;
- else
- priv->rx_csum = 0;
+ /* Attach rx QP to bradcast address */
+ memset(&mc_list[10], 0xff, ETH_ALEN);
+ mc_list[5] = priv->port; /* needed for B0 steering support */
+ if (mlx4_multicast_attach(mdev->dev, &priv->rss_map.indir_qp, mc_list,
+ priv->port, 0, MLX4_PROT_ETH,
+ &priv->broadcast_id))
+ mlx4_warn(mdev, "Failed Attaching Broadcast\n");
- err = mlx4_wol_read(priv->mdev->dev, &config, priv->port);
- if (err) {
- en_err(priv, "Failed to get WoL info, unable to modify\n");
- goto wol_err;
- }
- if (dev->if_capenable & IFCAP_WOL_MAGIC) {
- config |= MLX4_EN_WOL_DO_MODIFY | MLX4_EN_WOL_ENABLED |
- MLX4_EN_WOL_MAGIC;
- } else {
- config &= ~(MLX4_EN_WOL_ENABLED | MLX4_EN_WOL_MAGIC);
- config |= MLX4_EN_WOL_DO_MODIFY;
- }
+ /* Must redo promiscuous mode setup. */
+ priv->flags &= ~(MLX4_EN_FLAG_PROMISC | MLX4_EN_FLAG_MC_PROMISC);
- err = mlx4_wol_write(priv->mdev->dev, config, priv->port);
- if (err) {
- en_err(priv, "Failed to set WoL information\n");
- goto wol_err;
- }
+ /* Schedule multicast task to populate multicast list */
+ queue_work(mdev->workqueue, &priv->rx_mode_task);
- priv->port_up = true;
+ mlx4_set_stats_bitmap(mdev->dev, priv->stats_bitmap);
- /* Populate multicast list */
- mlx4_en_set_multicast(dev);
+ priv->port_up = true;
- /* Enable the queues. */
- dev->if_drv_flags &= ~IFF_DRV_OACTIVE;
- dev->if_drv_flags |= IFF_DRV_RUNNING;
+ /* Enable the queues. */
+ dev->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ dev->if_drv_flags |= IFF_DRV_RUNNING;
+#ifdef CONFIG_DEBUG_FS
+ mlx4_en_create_debug_files(priv);
+#endif
+ callout_reset(&priv->watchdog_timer, MLX4_EN_WATCHDOG_TIMEOUT,
+ mlx4_en_watchdog_timeout, priv);
- callout_reset(&priv->watchdog_timer, MLX4_EN_WATCHDOG_TIMEOUT,
- mlx4_en_watchdog_timeout, priv);
return 0;
-wol_err:
- /* close port*/
- mlx4_CLOSE_PORT(mdev->dev, priv->port);
-
-mac_err:
- mlx4_unregister_mac(mdev->dev, priv->port, priv->mac);
tx_err:
while (tx_index--) {
- mlx4_en_deactivate_tx_ring(priv, &priv->tx_ring[tx_index]);
- mlx4_en_deactivate_cq(priv, &priv->tx_cq[tx_index]);
+ mlx4_en_deactivate_tx_ring(priv, priv->tx_ring[tx_index]);
+ mlx4_en_deactivate_cq(priv, priv->tx_cq[tx_index]);
}
-
+ mlx4_en_destroy_drop_qp(priv);
+rss_err:
mlx4_en_release_rss_steer(priv);
+mac_err:
+ mlx4_en_put_qp(priv);
cq_err:
while (rx_index--)
- mlx4_en_deactivate_cq(priv, &priv->rx_cq[rx_index]);
+ mlx4_en_deactivate_cq(priv, priv->rx_cq[rx_index]);
for (i = 0; i < priv->rx_ring_num; i++)
- mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[i]);
+ mlx4_en_deactivate_rx_ring(priv, priv->rx_ring[i]);
return err; /* need to close devices */
}
-void mlx4_en_do_stop_port(struct net_device *dev)
+void mlx4_en_stop_port(struct net_device *dev)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_en_mc_list *mclist, *tmp;
int i;
+ u8 mc_list[16] = {0};
if (!priv->port_up) {
en_dbg(DRV, priv, "stop port called while port already down\n");
return;
}
+#ifdef CONFIG_DEBUG_FS
+ mlx4_en_delete_debug_files(priv);
+#endif
+
+ /* close port*/
+ mlx4_CLOSE_PORT(mdev->dev, priv->port);
+
/* Set port as not active */
priv->port_up = false;
+ if (priv->counter_index != 0xff) {
+ mlx4_counter_free(mdev->dev, priv->port, priv->counter_index);
+ priv->counter_index = 0xff;
+ }
- /* Unregister Mac address for the port */
- mlx4_unregister_mac(mdev->dev, priv->port, priv->mac);
- mdev->mac_removed[priv->port] = 1;
+ /* Promsicuous mode */
+ if (mdev->dev->caps.steering_mode ==
+ MLX4_STEERING_MODE_DEVICE_MANAGED) {
+ priv->flags &= ~(MLX4_EN_FLAG_PROMISC |
+ MLX4_EN_FLAG_MC_PROMISC);
+ mlx4_flow_steer_promisc_remove(mdev->dev,
+ priv->port,
+ MLX4_FS_ALL_DEFAULT);
+ mlx4_flow_steer_promisc_remove(mdev->dev,
+ priv->port,
+ MLX4_FS_MC_DEFAULT);
+ } else if (priv->flags & MLX4_EN_FLAG_PROMISC) {
+ priv->flags &= ~MLX4_EN_FLAG_PROMISC;
+
+ /* Disable promiscouos mode */
+ mlx4_unicast_promisc_remove(mdev->dev, priv->base_qpn,
+ priv->port);
+
+ /* Disable Multicast promisc */
+ if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) {
+ mlx4_multicast_promisc_remove(mdev->dev, priv->base_qpn,
+ priv->port);
+ priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;
+ }
+ }
+
+ /* Detach All multicasts */
+ memset(&mc_list[10], 0xff, ETH_ALEN);
+ mc_list[5] = priv->port; /* needed for B0 steering support */
+ mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp, mc_list,
+ MLX4_PROT_ETH, priv->broadcast_id);
+ list_for_each_entry(mclist, &priv->curr_list, list) {
+ memcpy(&mc_list[10], mclist->addr, ETH_ALEN);
+ mc_list[5] = priv->port;
+ mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp,
+ mc_list, MLX4_PROT_ETH, mclist->reg_id);
+ }
+ mlx4_en_clear_list(dev);
+ list_for_each_entry_safe(mclist, tmp, &priv->curr_list, list) {
+ list_del(&mclist->list);
+ kfree(mclist);
+ }
+
+ /* Flush multicast filter */
+ mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, 1, MLX4_MCAST_CONFIG);
+ mlx4_en_destroy_drop_qp(priv);
/* Free TX Rings */
for (i = 0; i < priv->tx_ring_num; i++) {
- mlx4_en_deactivate_tx_ring(priv, &priv->tx_ring[i]);
- mlx4_en_deactivate_cq(priv, &priv->tx_cq[i]);
+ mlx4_en_deactivate_tx_ring(priv, priv->tx_ring[i]);
+ mlx4_en_deactivate_cq(priv, priv->tx_cq[i]);
}
msleep(10);
for (i = 0; i < priv->tx_ring_num; i++)
- mlx4_en_free_tx_buf(dev, &priv->tx_ring[i]);
+ mlx4_en_free_tx_buf(dev, priv->tx_ring[i]);
/* Free RSS qps */
mlx4_en_release_rss_steer(priv);
+ /* Unregister Mac address for the port */
+ mlx4_en_put_qp(priv);
+ mdev->mac_removed[priv->port] = 1;
+
/* Free RX Rings */
for (i = 0; i < priv->rx_ring_num; i++) {
- mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[i]);
- mlx4_en_deactivate_cq(priv, &priv->rx_cq[i]);
+ struct mlx4_en_cq *cq = priv->rx_cq[i];
+ mlx4_en_deactivate_rx_ring(priv, priv->rx_ring[i]);
+ mlx4_en_deactivate_cq(priv, cq);
}
- /* close port*/
- mlx4_CLOSE_PORT(mdev->dev, priv->port);
-
- callout_stop(&priv->watchdog_timer);
+ callout_stop(&priv->watchdog_timer);
- dev->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ dev->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
}
static void mlx4_en_restart(struct work_struct *work)
@@ -783,12 +1516,13 @@ static void mlx4_en_restart(struct work_struct *work)
struct mlx4_en_tx_ring *ring;
int i;
+
if (priv->blocked == 0 || priv->port_up == 0)
return;
for (i = 0; i < priv->tx_ring_num; i++) {
- ring = &priv->tx_ring[i];
+ ring = priv->tx_ring[i];
if (ring->blocked &&
- ring->watchdog_time + MLX4_EN_WATCHDOG_TIMEOUT < ticks)
+ ring->watchdog_time + MLX4_EN_WATCHDOG_TIMEOUT < ticks)
goto reset;
}
return;
@@ -799,129 +1533,175 @@ reset:
mutex_lock(&mdev->state_lock);
if (priv->port_up) {
- mlx4_en_do_stop_port(dev);
- if (mlx4_en_do_start_port(dev))
+ mlx4_en_stop_port(dev);
+ //for (i = 0; i < priv->tx_ring_num; i++)
+ // netdev_tx_reset_queue(priv->tx_ring[i]->tx_queue);
+ if (mlx4_en_start_port(dev))
en_err(priv, "Failed restarting port %d\n", priv->port);
}
mutex_unlock(&mdev->state_lock);
}
-
-static void
-mlx4_en_init(void *arg)
+static void mlx4_en_clear_stats(struct net_device *dev)
{
- struct mlx4_en_priv *priv;
- struct mlx4_en_dev *mdev;
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int i;
- priv = arg;
- mdev = priv->mdev;
- mutex_lock(&mdev->state_lock);
- mlx4_en_init_locked(priv);
- mutex_unlock(&mdev->state_lock);
+ if (!mlx4_is_slave(mdev->dev))
+ if (mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 1))
+ en_dbg(HW, priv, "Failed dumping statistics\n");
+
+ memset(&priv->pstats, 0, sizeof(priv->pstats));
+ memset(&priv->pkstats, 0, sizeof(priv->pkstats));
+ memset(&priv->port_stats, 0, sizeof(priv->port_stats));
+ memset(&priv->vport_stats, 0, sizeof(priv->vport_stats));
+
+ for (i = 0; i < priv->tx_ring_num; i++) {
+ priv->tx_ring[i]->bytes = 0;
+ priv->tx_ring[i]->packets = 0;
+ priv->tx_ring[i]->tx_csum = 0;
+ }
+ for (i = 0; i < priv->rx_ring_num; i++) {
+ priv->rx_ring[i]->bytes = 0;
+ priv->rx_ring[i]->packets = 0;
+ priv->rx_ring[i]->csum_ok = 0;
+ priv->rx_ring[i]->csum_none = 0;
+ }
}
-static void
-mlx4_en_init_locked(struct mlx4_en_priv *priv)
+static void mlx4_en_open(void* arg)
{
- struct mlx4_en_dev *mdev;
- struct ifnet *dev;
- int i;
+ struct mlx4_en_priv *priv;
+ struct mlx4_en_dev *mdev;
+ struct net_device *dev;
+ int err = 0;
- dev = priv->dev;
- mdev = priv->mdev;
- if (dev->if_drv_flags & IFF_DRV_RUNNING)
- mlx4_en_do_stop_port(dev);
+ priv = arg;
+ mdev = priv->mdev;
+ dev = priv->dev;
+
+
+ mutex_lock(&mdev->state_lock);
if (!mdev->device_up) {
en_err(priv, "Cannot open - device down/disabled\n");
- return;
+ goto out;
}
- /* Reset HW statistics and performance counters */
- if (mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 1))
- en_dbg(HW, priv, "Failed dumping statistics\n");
-
- memset(&priv->pstats, 0, sizeof(priv->pstats));
-
- for (i = 0; i < priv->tx_ring_num; i++) {
- priv->tx_ring[i].bytes = 0;
- priv->tx_ring[i].packets = 0;
- }
- for (i = 0; i < priv->rx_ring_num; i++) {
- priv->rx_ring[i].bytes = 0;
- priv->rx_ring[i].packets = 0;
- }
+ /* Reset HW statistics and SW counters */
+ mlx4_en_clear_stats(dev);
- mlx4_en_set_default_moderation(priv);
- if (mlx4_en_do_start_port(dev))
+ err = mlx4_en_start_port(dev);
+ if (err)
en_err(priv, "Failed starting port:%d\n", priv->port);
+
+out:
+ mutex_unlock(&mdev->state_lock);
+ return;
}
void mlx4_en_free_resources(struct mlx4_en_priv *priv)
{
int i;
+#ifdef CONFIG_RFS_ACCEL
+ if (priv->dev->rx_cpu_rmap) {
+ free_irq_cpu_rmap(priv->dev->rx_cpu_rmap);
+ priv->dev->rx_cpu_rmap = NULL;
+ }
+#endif
+
for (i = 0; i < priv->tx_ring_num; i++) {
- if (priv->tx_ring[i].tx_info)
+ if (priv->tx_ring && priv->tx_ring[i])
mlx4_en_destroy_tx_ring(priv, &priv->tx_ring[i]);
- if (priv->tx_cq[i].buf)
+ if (priv->tx_cq && priv->tx_cq[i])
mlx4_en_destroy_cq(priv, &priv->tx_cq[i]);
}
for (i = 0; i < priv->rx_ring_num; i++) {
- if (priv->rx_ring[i].rx_info)
- mlx4_en_destroy_rx_ring(priv, &priv->rx_ring[i]);
- if (priv->rx_cq[i].buf)
+ if (priv->rx_ring[i])
+ mlx4_en_destroy_rx_ring(priv, &priv->rx_ring[i],
+ priv->prof->rx_ring_size, priv->stride);
+ if (priv->rx_cq[i])
mlx4_en_destroy_cq(priv, &priv->rx_cq[i]);
}
- /* Free the stats tree when we resize the rings. */
+
if (priv->sysctl)
sysctl_ctx_free(&priv->stat_ctx);
+
}
int mlx4_en_alloc_resources(struct mlx4_en_priv *priv)
{
struct mlx4_en_port_profile *prof = priv->prof;
int i;
-
- /* Create tx Rings */
- for (i = 0; i < priv->tx_ring_num; i++) {
- if (mlx4_en_create_cq(priv, &priv->tx_cq[i],
- prof->tx_ring_size, i, TX))
- goto err;
-
- if (mlx4_en_create_tx_ring(priv, &priv->tx_ring[i],
- prof->tx_ring_size, TXBB_SIZE))
- goto err;
- }
+ int node = 0;
/* Create rx Rings */
for (i = 0; i < priv->rx_ring_num; i++) {
if (mlx4_en_create_cq(priv, &priv->rx_cq[i],
- prof->rx_ring_size, i, RX))
+ prof->rx_ring_size, i, RX, node))
goto err;
if (mlx4_en_create_rx_ring(priv, &priv->rx_ring[i],
- prof->rx_ring_size))
+ prof->rx_ring_size, node))
goto err;
}
- /* Re-create stat sysctls in case the number of rings changed. */
- mlx4_en_sysctl_stat(priv);
+ /* Create tx Rings */
+ for (i = 0; i < priv->tx_ring_num; i++) {
+ if (mlx4_en_create_cq(priv, &priv->tx_cq[i],
+ prof->tx_ring_size, i, TX, node))
+ goto err;
- /* Populate Tx priority mappings */
- mlx4_en_set_prio_map(priv, priv->tx_prio_map,
- priv->tx_ring_num - MLX4_EN_NUM_HASH_RINGS);
+ if (mlx4_en_create_tx_ring(priv, &priv->tx_ring[i],
+ prof->tx_ring_size, TXBB_SIZE, node, i))
+ goto err;
+ }
+#ifdef CONFIG_RFS_ACCEL
+ priv->dev->rx_cpu_rmap = alloc_irq_cpu_rmap(priv->rx_ring_num);
+ if (!priv->dev->rx_cpu_rmap)
+ goto err;
+#endif
+ /* Re-create stat sysctls in case the number of rings changed. */
+ mlx4_en_sysctl_stat(priv);
return 0;
err:
en_err(priv, "Failed to allocate NIC resources\n");
+ for (i = 0; i < priv->rx_ring_num; i++) {
+ if (priv->rx_ring[i])
+ mlx4_en_destroy_rx_ring(priv, &priv->rx_ring[i],
+ prof->rx_ring_size,
+ priv->stride);
+ if (priv->rx_cq[i])
+ mlx4_en_destroy_cq(priv, &priv->rx_cq[i]);
+ }
+ for (i = 0; i < priv->tx_ring_num; i++) {
+ if (priv->tx_ring[i])
+ mlx4_en_destroy_tx_ring(priv, &priv->tx_ring[i]);
+ if (priv->tx_cq[i])
+ mlx4_en_destroy_cq(priv, &priv->tx_cq[i]);
+ }
+ priv->port_up = false;
return -ENOMEM;
}
+struct en_port_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct en_port *, struct en_port_attribute *, char *buf);
+ ssize_t (*store)(struct en_port *, struct en_port_attribute *, char *buf, size_t count);
+};
+
+#define PORT_ATTR_RO(_name) \
+struct en_port_attribute en_port_attr_##_name = __ATTR_RO(_name)
+
+#define EN_PORT_ATTR(_name, _mode, _show, _store) \
+struct en_port_attribute en_port_attr_##_name = __ATTR(_name, _mode, _show, _store)
void mlx4_en_destroy_netdev(struct net_device *dev)
{
@@ -930,10 +1710,10 @@ void mlx4_en_destroy_netdev(struct net_device *dev)
en_dbg(DRV, priv, "Destroying netdev on port:%d\n", priv->port);
- if (priv->vlan_attach != NULL)
- EVENTHANDLER_DEREGISTER(vlan_config, priv->vlan_attach);
- if (priv->vlan_detach != NULL)
- EVENTHANDLER_DEREGISTER(vlan_unconfig, priv->vlan_detach);
+ if (priv->vlan_attach != NULL)
+ EVENTHANDLER_DEREGISTER(vlan_config, priv->vlan_attach);
+ if (priv->vlan_detach != NULL)
+ EVENTHANDLER_DEREGISTER(vlan_unconfig, priv->vlan_detach);
/* Unregister device - this will close the port if it was up */
if (priv->registered)
@@ -943,28 +1723,34 @@ void mlx4_en_destroy_netdev(struct net_device *dev)
mlx4_free_hwq_res(mdev->dev, &priv->res, MLX4_EN_PAGE_SIZE);
mutex_lock(&mdev->state_lock);
- mlx4_en_do_stop_port(dev);
+ mlx4_en_stop_port(dev);
mutex_unlock(&mdev->state_lock);
+
cancel_delayed_work(&priv->stats_task);
+ cancel_delayed_work(&priv->service_task);
/* flush any pending task for this netdev */
flush_workqueue(mdev->workqueue);
- callout_drain(&priv->watchdog_timer);
+ callout_drain(&priv->watchdog_timer);
/* Detach the netdev so tasks would not attempt to access it */
mutex_lock(&mdev->state_lock);
mdev->pndev[priv->port] = NULL;
mutex_unlock(&mdev->state_lock);
+
mlx4_en_free_resources(priv);
+ /* freeing the sysctl conf cannot be called from within mlx4_en_free_resources */
if (priv->sysctl)
sysctl_ctx_free(&priv->conf_ctx);
- mtx_destroy(&priv->stats_lock.m);
- mtx_destroy(&priv->vlan_lock.m);
- kfree(priv);
- if_free(dev);
+ kfree(priv->tx_ring);
+ kfree(priv->tx_cq);
+
+ kfree(priv);
+ if_free(dev);
+
}
static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu)
@@ -973,8 +1759,8 @@ static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu)
struct mlx4_en_dev *mdev = priv->mdev;
int err = 0;
- en_dbg(DRV, priv, "Change MTU called - current:%u new:%d\n",
- dev->if_mtu, new_mtu);
+ en_dbg(DRV, priv, "Change MTU called - current:%u new:%u\n",
+ (unsigned)dev->if_mtu, (unsigned)new_mtu);
if ((new_mtu < MLX4_EN_MIN_MTU) || (new_mtu > priv->max_mtu)) {
en_err(priv, "Bad MTU size:%d.\n", new_mtu);
@@ -985,15 +1771,14 @@ static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu)
if (dev->if_drv_flags & IFF_DRV_RUNNING) {
if (!mdev->device_up) {
/* NIC is probably restarting - let watchdog task reset
- * the port */
+ * * the port */
en_dbg(DRV, priv, "Change MTU called with card down!?\n");
} else {
- mlx4_en_do_stop_port(dev);
- mlx4_en_set_default_moderation(priv);
- err = mlx4_en_do_start_port(dev);
+ mlx4_en_stop_port(dev);
+ err = mlx4_en_start_port(dev);
if (err) {
en_err(priv, "Failed restarting port:%d\n",
- priv->port);
+ priv->port);
queue_work(mdev->workqueue, &priv->watchdog_task);
}
}
@@ -1042,7 +1827,6 @@ static int mlx4_en_calc_media(struct mlx4_en_priv *priv)
return (active);
}
-
static void mlx4_en_media_status(struct ifnet *dev, struct ifmediareq *ifmr)
{
struct mlx4_en_priv *priv;
@@ -1077,9 +1861,10 @@ static int mlx4_en_media_change(struct ifnet *dev)
case IFM_10G_SR:
case IFM_10G_CX4:
case IFM_1000_T:
- if (IFM_SUBTYPE(ifm->ifm_media) ==
- IFM_SUBTYPE(mlx4_en_calc_media(priv)) &&
- (ifm->ifm_media & IFM_FDX))
+ case IFM_40G_CR4:
+ if ((IFM_SUBTYPE(ifm->ifm_media)
+ == IFM_SUBTYPE(mlx4_en_calc_media(priv)))
+ && (ifm->ifm_media & IFM_FDX))
break;
/* Fallthrough */
default:
@@ -1116,36 +1901,28 @@ static int mlx4_en_ioctl(struct ifnet *dev, u_long command, caddr_t data)
mdev = priv->mdev;
ifr = (struct ifreq *) data;
switch (command) {
+
case SIOCSIFMTU:
error = -mlx4_en_change_mtu(dev, ifr->ifr_mtu);
break;
case SIOCSIFFLAGS:
+ mutex_lock(&mdev->state_lock);
if (dev->if_flags & IFF_UP) {
if ((dev->if_drv_flags & IFF_DRV_RUNNING) == 0)
mlx4_en_start_port(dev);
else
- mlx4_en_set_multicast(dev);
+ mlx4_en_set_rx_mode(dev);
} else {
if (dev->if_drv_flags & IFF_DRV_RUNNING) {
mlx4_en_stop_port(dev);
if_link_state_change(dev, LINK_STATE_DOWN);
- /*
- * Since mlx4_en_stop_port is defered we
- * have to wait till it's finished.
- */
- for (int count=0; count<10; count++) {
- if (dev->if_drv_flags & IFF_DRV_RUNNING) {
- DELAY(20000);
- } else {
- break;
- }
- }
}
}
+ mutex_unlock(&mdev->state_lock);
break;
case SIOCADDMULTI:
case SIOCDELMULTI:
- mlx4_en_set_multicast(dev);
+ mlx4_en_set_rx_mode(dev);
break;
case SIOCSIFMEDIA:
case SIOCGIFMEDIA:
@@ -1158,6 +1935,8 @@ static int mlx4_en_ioctl(struct ifnet *dev, u_long command, caddr_t data)
dev->if_capenable ^= IFCAP_HWCSUM;
if (mask & IFCAP_TSO4)
dev->if_capenable ^= IFCAP_TSO4;
+ if (mask & IFCAP_TSO6)
+ dev->if_capenable ^= IFCAP_TSO6;
if (mask & IFCAP_LRO)
dev->if_capenable ^= IFCAP_LRO;
if (mask & IFCAP_VLAN_HWTAGGING)
@@ -1167,7 +1946,7 @@ static int mlx4_en_ioctl(struct ifnet *dev, u_long command, caddr_t data)
if (mask & IFCAP_WOL_MAGIC)
dev->if_capenable ^= IFCAP_WOL_MAGIC;
if (dev->if_drv_flags & IFF_DRV_RUNNING)
- mlx4_en_init_locked(priv);
+ mlx4_en_start_port(dev);
mutex_unlock(&mdev->state_lock);
VLAN_CAPABILITIES(dev);
break;
@@ -1179,228 +1958,441 @@ static int mlx4_en_ioctl(struct ifnet *dev, u_long command, caddr_t data)
return (error);
}
-static int mlx4_en_set_ring_size(struct net_device *dev,
- int rx_size, int tx_size)
+
+int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
+ struct mlx4_en_port_profile *prof)
{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_dev *mdev = priv->mdev;
- int port_up = 0;
- int err = 0;
+ struct net_device *dev;
+ struct mlx4_en_priv *priv;
+ uint8_t dev_addr[ETHER_ADDR_LEN];
+ int err;
+ int i;
- rx_size = roundup_pow_of_two(rx_size);
- rx_size = max_t(u32, rx_size, MLX4_EN_MIN_RX_SIZE);
- rx_size = min_t(u32, rx_size, MLX4_EN_MAX_RX_SIZE);
- tx_size = roundup_pow_of_two(tx_size);
- tx_size = max_t(u32, tx_size, MLX4_EN_MIN_TX_SIZE);
- tx_size = min_t(u32, tx_size, MLX4_EN_MAX_TX_SIZE);
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ dev = priv->dev = if_alloc(IFT_ETHER);
+ if (dev == NULL) {
+ en_err(priv, "Net device allocation failed\n");
+ kfree(priv);
+ return -ENOMEM;
+ }
+ dev->if_softc = priv;
+ if_initname(dev, "mlxen", atomic_fetchadd_int(&mlx4_en_unit, 1));
+ dev->if_mtu = ETHERMTU;
+ dev->if_baudrate = 1000000000;
+ dev->if_init = mlx4_en_open;
+ dev->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ dev->if_ioctl = mlx4_en_ioctl;
+ dev->if_transmit = mlx4_en_transmit;
+ dev->if_qflush = mlx4_en_qflush;
+ dev->if_snd.ifq_maxlen = prof->tx_ring_size;
- if (rx_size == (priv->port_up ?
- priv->rx_ring[0].actual_size : priv->rx_ring[0].size) &&
- tx_size == priv->tx_ring[0].size)
- return 0;
+ /*
+ * Initialize driver private data
+ */
+ priv->counter_index = 0xff;
+ spin_lock_init(&priv->stats_lock);
+ INIT_WORK(&priv->rx_mode_task, mlx4_en_do_set_rx_mode);
+ INIT_WORK(&priv->watchdog_task, mlx4_en_restart);
+ INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate);
+ INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats);
+ INIT_DELAYED_WORK(&priv->service_task, mlx4_en_service_task);
+ callout_init(&priv->watchdog_timer, 1);
+#ifdef CONFIG_RFS_ACCEL
+ INIT_LIST_HEAD(&priv->filters);
+ spin_lock_init(&priv->filters_lock);
+#endif
- mutex_lock(&mdev->state_lock);
- if (priv->port_up) {
- port_up = 1;
- mlx4_en_do_stop_port(dev);
+ priv->msg_enable = MLX4_EN_MSG_LEVEL;
+ priv->dev = dev;
+ priv->mdev = mdev;
+ priv->ddev = &mdev->pdev->dev;
+ priv->prof = prof;
+ priv->port = port;
+ priv->port_up = false;
+ priv->flags = prof->flags;
+ priv->ctrl_flags = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE |
+ MLX4_WQE_CTRL_SOLICITED);
+
+ priv->num_tx_rings_p_up = mdev->profile.num_tx_rings_p_up;
+ priv->tx_ring_num = prof->tx_ring_num;
+ priv->tx_ring = kcalloc(MAX_TX_RINGS,
+ sizeof(struct mlx4_en_tx_ring *), GFP_KERNEL);
+ if (!priv->tx_ring) {
+ err = -ENOMEM;
+ goto out;
}
- mlx4_en_free_resources(priv);
- priv->prof->tx_ring_size = tx_size;
- priv->prof->rx_ring_size = rx_size;
+ priv->tx_cq = kcalloc(sizeof(struct mlx4_en_cq *), MAX_TX_RINGS,
+ GFP_KERNEL);
+ if (!priv->tx_cq) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ priv->rx_ring_num = prof->rx_ring_num;
+ priv->cqe_factor = (mdev->dev->caps.cqe_size == 64) ? 1 : 0;
+ priv->mac_index = -1;
+ priv->last_ifq_jiffies = 0;
+ priv->if_counters_rx_errors = 0;
+ priv->if_counters_rx_no_buffer = 0;
+#ifdef CONFIG_MLX4_EN_DCB
+ if (!mlx4_is_slave(priv->mdev->dev)) {
+ priv->dcbx_cap = DCB_CAP_DCBX_HOST;
+ priv->flags |= MLX4_EN_FLAG_DCB_ENABLED;
+ if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_ETS_CFG) {
+ dev->dcbnl_ops = &mlx4_en_dcbnl_ops;
+ } else {
+ en_info(priv, "QoS disabled - no HW support\n");
+ dev->dcbnl_ops = &mlx4_en_dcbnl_pfc_ops;
+ }
+ }
+#endif
+
+ for (i = 0; i < MLX4_EN_MAC_HASH_SIZE; ++i)
+ INIT_HLIST_HEAD(&priv->mac_hash[i]);
+
+
+ /* Query for default mac and max mtu */
+ priv->max_mtu = mdev->dev->caps.eth_mtu_cap[priv->port];
+ priv->mac = mdev->dev->caps.def_mac[priv->port];
+ if (ILLEGAL_MAC(priv->mac)) {
+#if BITS_PER_LONG == 64
+ en_err(priv, "Port: %d, invalid mac burned: 0x%lx, quiting\n",
+ priv->port, priv->mac);
+#elif BITS_PER_LONG == 32
+ en_err(priv, "Port: %d, invalid mac burned: 0x%llx, quiting\n",
+ priv->port, priv->mac);
+#endif
+ err = -EINVAL;
+ goto out;
+ }
+
+
+
+ priv->stride = roundup_pow_of_two(sizeof(struct mlx4_en_rx_desc) +
+ DS_SIZE);
+
+ mlx4_en_sysctl_conf(priv);
+
err = mlx4_en_alloc_resources(priv);
+ if (err)
+ goto out;
+
+ /* Allocate page for receive rings */
+ err = mlx4_alloc_hwq_res(mdev->dev, &priv->res,
+ MLX4_EN_PAGE_SIZE, MLX4_EN_PAGE_SIZE);
if (err) {
- en_err(priv, "Failed reallocating port resources\n");
+ en_err(priv, "Failed to allocate page for rx qps\n");
goto out;
}
- if (port_up) {
- err = mlx4_en_do_start_port(dev);
- if (err)
- en_err(priv, "Failed starting port\n");
+ priv->allocated = 1;
+
+ /*
+ * Set driver features
+ */
+ dev->if_capabilities |= IFCAP_RXCSUM | IFCAP_TXCSUM;
+ dev->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING;
+ dev->if_capabilities |= IFCAP_VLAN_HWCSUM | IFCAP_VLAN_HWFILTER;
+ dev->if_capabilities |= IFCAP_LINKSTATE | IFCAP_JUMBO_MTU;
+ dev->if_capabilities |= IFCAP_LRO;
+
+ if (mdev->LSO_support)
+ dev->if_capabilities |= IFCAP_TSO4 | IFCAP_TSO6 | IFCAP_VLAN_HWTSO;
+
+ /* set TSO limits so that we don't have to drop TX packets */
+ dev->if_hw_tsomax = 65536 - (ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN);
+ dev->if_hw_tsomaxsegcount = 16;
+ dev->if_hw_tsomaxsegsize = 65536; /* XXX can do up to 4GByte */
+
+ dev->if_capenable = dev->if_capabilities;
+
+ dev->if_hwassist = 0;
+ if (dev->if_capenable & (IFCAP_TSO4 | IFCAP_TSO6))
+ dev->if_hwassist |= CSUM_TSO;
+ if (dev->if_capenable & IFCAP_TXCSUM)
+ dev->if_hwassist |= (CSUM_TCP | CSUM_UDP | CSUM_IP);
+
+
+ /* Register for VLAN events */
+ priv->vlan_attach = EVENTHANDLER_REGISTER(vlan_config,
+ mlx4_en_vlan_rx_add_vid, priv, EVENTHANDLER_PRI_FIRST);
+ priv->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
+ mlx4_en_vlan_rx_kill_vid, priv, EVENTHANDLER_PRI_FIRST);
+
+ mdev->pndev[priv->port] = dev;
+
+ priv->last_link_state = MLX4_DEV_EVENT_PORT_DOWN;
+ mlx4_en_set_default_moderation(priv);
+
+ /* Set default MAC */
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ dev_addr[ETHER_ADDR_LEN - 1 - i] = (u8) (priv->mac >> (8 * i));
+
+
+ ether_ifattach(dev, dev_addr);
+ if_link_state_change(dev, LINK_STATE_DOWN);
+ ifmedia_init(&priv->media, IFM_IMASK | IFM_ETH_FMASK,
+ mlx4_en_media_change, mlx4_en_media_status);
+ ifmedia_add(&priv->media, IFM_ETHER | IFM_FDX | IFM_1000_T, 0, NULL);
+ ifmedia_add(&priv->media, IFM_ETHER | IFM_FDX | IFM_10G_SR, 0, NULL);
+ ifmedia_add(&priv->media, IFM_ETHER | IFM_FDX | IFM_10G_CX4, 0, NULL);
+ ifmedia_add(&priv->media, IFM_ETHER | IFM_FDX | IFM_40G_CR4, 0, NULL);
+ ifmedia_add(&priv->media, IFM_ETHER | IFM_AUTO, 0, NULL);
+ ifmedia_set(&priv->media, IFM_ETHER | IFM_AUTO);
+
+ en_warn(priv, "Using %d TX rings\n", prof->tx_ring_num);
+ en_warn(priv, "Using %d RX rings\n", prof->rx_ring_num);
+
+ priv->registered = 1;
+
+ en_warn(priv, "Using %d TX rings\n", prof->tx_ring_num);
+ en_warn(priv, "Using %d RX rings\n", prof->rx_ring_num);
+
+
+ priv->rx_mb_size = dev->if_mtu + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN;
+ err = mlx4_SET_PORT_general(mdev->dev, priv->port,
+ priv->rx_mb_size,
+ prof->tx_pause, prof->tx_ppp,
+ prof->rx_pause, prof->rx_ppp);
+ if (err) {
+ en_err(priv, "Failed setting port general configurations "
+ "for port %d, with error %d\n", priv->port, err);
+ goto out;
}
+
+ /* Init port */
+ en_warn(priv, "Initializing port\n");
+ err = mlx4_INIT_PORT(mdev->dev, priv->port);
+ if (err) {
+ en_err(priv, "Failed Initializing port\n");
+ goto out;
+ }
+
+ queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
+
+ if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS)
+ queue_delayed_work(mdev->workqueue, &priv->service_task, SERVICE_TASK_DELAY);
+
+
+
+ return 0;
+
out:
- mutex_unlock(&mdev->state_lock);
+ mlx4_en_destroy_netdev(dev);
return err;
}
-
+static int mlx4_en_set_ring_size(struct net_device *dev,
+ int rx_size, int tx_size)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_dev *mdev = priv->mdev;
+ int port_up = 0;
+ int err = 0;
+
+ rx_size = roundup_pow_of_two(rx_size);
+ rx_size = max_t(u32, rx_size, MLX4_EN_MIN_RX_SIZE);
+ rx_size = min_t(u32, rx_size, MLX4_EN_MAX_RX_SIZE);
+ tx_size = roundup_pow_of_two(tx_size);
+ tx_size = max_t(u32, tx_size, MLX4_EN_MIN_TX_SIZE);
+ tx_size = min_t(u32, tx_size, MLX4_EN_MAX_TX_SIZE);
+
+ if (rx_size == (priv->port_up ?
+ priv->rx_ring[0]->actual_size : priv->rx_ring[0]->size) &&
+ tx_size == priv->tx_ring[0]->size)
+ return 0;
+ mutex_lock(&mdev->state_lock);
+ if (priv->port_up) {
+ port_up = 1;
+ mlx4_en_stop_port(dev);
+ }
+ mlx4_en_free_resources(priv);
+ priv->prof->tx_ring_size = tx_size;
+ priv->prof->rx_ring_size = rx_size;
+ err = mlx4_en_alloc_resources(priv);
+ if (err) {
+ en_err(priv, "Failed reallocating port resources\n");
+ goto out;
+ }
+ if (port_up) {
+ err = mlx4_en_start_port(dev);
+ if (err)
+ en_err(priv, "Failed starting port\n");
+ }
+out:
+ mutex_unlock(&mdev->state_lock);
+ return err;
+}
static int mlx4_en_set_rx_ring_size(SYSCTL_HANDLER_ARGS)
{
- struct mlx4_en_priv *priv;
- int size;
- int error;
-
- priv = arg1;
- size = priv->prof->rx_ring_size;
- error = sysctl_handle_int(oidp, &size, 0, req);
- if (error || !req->newptr)
- return (error);
- error = -mlx4_en_set_ring_size(priv->dev, size,
- priv->prof->tx_ring_size);
-
- return (error);
+ struct mlx4_en_priv *priv;
+ int size;
+ int error;
+
+ priv = arg1;
+ size = priv->prof->rx_ring_size;
+ error = sysctl_handle_int(oidp, &size, 0, req);
+ if (error || !req->newptr)
+ return (error);
+ error = -mlx4_en_set_ring_size(priv->dev, size,
+ priv->prof->tx_ring_size);
+ return (error);
}
static int mlx4_en_set_tx_ring_size(SYSCTL_HANDLER_ARGS)
{
- struct mlx4_en_priv *priv;
- int size;
- int error;
-
- priv = arg1;
- size = priv->prof->tx_ring_size;
- error = sysctl_handle_int(oidp, &size, 0, req);
- if (error || !req->newptr)
- return (error);
- error = -mlx4_en_set_ring_size(priv->dev, priv->prof->rx_ring_size,
- size);
-
- return (error);
+ struct mlx4_en_priv *priv;
+ int size;
+ int error;
+
+ priv = arg1;
+ size = priv->prof->tx_ring_size;
+ error = sysctl_handle_int(oidp, &size, 0, req);
+ if (error || !req->newptr)
+ return (error);
+ error = -mlx4_en_set_ring_size(priv->dev, priv->prof->rx_ring_size,
+ size);
+
+ return (error);
}
static int mlx4_en_set_tx_ppp(SYSCTL_HANDLER_ARGS)
{
- struct mlx4_en_priv *priv;
- int ppp;
- int error;
-
- priv = arg1;
- ppp = priv->prof->tx_ppp;
- error = sysctl_handle_int(oidp, &ppp, 0, req);
- if (error || !req->newptr)
- return (error);
- if (ppp > 0xff || ppp < 0)
- return (-EINVAL);
- priv->prof->tx_ppp = ppp;
- error = -mlx4_SET_PORT_general(priv->mdev->dev, priv->port,
- priv->rx_mb_size + ETHER_CRC_LEN,
- priv->prof->tx_pause,
- priv->prof->tx_ppp,
- priv->prof->rx_pause,
- priv->prof->rx_ppp);
-
- return (error);
+ struct mlx4_en_priv *priv;
+ int ppp;
+ int error;
+
+ priv = arg1;
+ ppp = priv->prof->tx_ppp;
+ error = sysctl_handle_int(oidp, &ppp, 0, req);
+ if (error || !req->newptr)
+ return (error);
+ if (ppp > 0xff || ppp < 0)
+ return (-EINVAL);
+ priv->prof->tx_ppp = ppp;
+ error = -mlx4_SET_PORT_general(priv->mdev->dev, priv->port,
+ priv->rx_mb_size + ETHER_CRC_LEN,
+ priv->prof->tx_pause,
+ priv->prof->tx_ppp,
+ priv->prof->rx_pause,
+ priv->prof->rx_ppp);
+
+ return (error);
}
static int mlx4_en_set_rx_ppp(SYSCTL_HANDLER_ARGS)
{
- struct mlx4_en_priv *priv;
- struct mlx4_en_dev *mdev;
- int tx_ring_num;
- int ppp;
- int error;
- int port_up;
-
- port_up = 0;
- priv = arg1;
- mdev = priv->mdev;
- ppp = priv->prof->rx_ppp;
- error = sysctl_handle_int(oidp, &ppp, 0, req);
- if (error || !req->newptr)
- return (error);
- if (ppp > 0xff || ppp < 0)
- return (-EINVAL);
- /* See if we have to change the number of tx queues. */
- if (!ppp != !priv->prof->rx_ppp) {
- tx_ring_num = MLX4_EN_NUM_HASH_RINGS + 1 +
- (!!ppp) * MLX4_EN_NUM_PPP_RINGS;
- mutex_lock(&mdev->state_lock);
- if (priv->port_up) {
- port_up = 1;
- mlx4_en_do_stop_port(priv->dev);
- }
- mlx4_en_free_resources(priv);
- priv->tx_ring_num = tx_ring_num;
- priv->prof->rx_ppp = ppp;
- error = -mlx4_en_alloc_resources(priv);
- if (error)
- en_err(priv, "Failed reallocating port resources\n");
- if (error == 0 && port_up) {
- error = -mlx4_en_do_start_port(priv->dev);
- if (error)
- en_err(priv, "Failed starting port\n");
- }
- mutex_unlock(&mdev->state_lock);
- return (error);
-
- }
- priv->prof->rx_ppp = ppp;
- error = -mlx4_SET_PORT_general(priv->mdev->dev, priv->port,
- priv->rx_mb_size + ETHER_CRC_LEN,
- priv->prof->tx_pause,
- priv->prof->tx_ppp,
- priv->prof->rx_pause,
- priv->prof->rx_ppp);
-
- return (error);
+ struct mlx4_en_priv *priv;
+ struct mlx4_en_dev *mdev;
+ int ppp;
+ int error;
+ int port_up;
+
+ port_up = 0;
+ priv = arg1;
+ mdev = priv->mdev;
+ ppp = priv->prof->rx_ppp;
+ error = sysctl_handle_int(oidp, &ppp, 0, req);
+ if (error || !req->newptr)
+ return (error);
+ if (ppp > 0xff || ppp < 0)
+ return (-EINVAL);
+ /* See if we have to change the number of tx queues. */
+ if (!ppp != !priv->prof->rx_ppp) {
+ mutex_lock(&mdev->state_lock);
+ if (priv->port_up) {
+ port_up = 1;
+ mlx4_en_stop_port(priv->dev);
+ }
+ mlx4_en_free_resources(priv);
+ priv->prof->rx_ppp = ppp;
+ error = -mlx4_en_alloc_resources(priv);
+ if (error)
+ en_err(priv, "Failed reallocating port resources\n");
+ if (error == 0 && port_up) {
+ error = -mlx4_en_start_port(priv->dev);
+ if (error)
+ en_err(priv, "Failed starting port\n");
+ }
+ mutex_unlock(&mdev->state_lock);
+ return (error);
+
+ }
+ priv->prof->rx_ppp = ppp;
+ error = -mlx4_SET_PORT_general(priv->mdev->dev, priv->port,
+ priv->rx_mb_size + ETHER_CRC_LEN,
+ priv->prof->tx_pause,
+ priv->prof->tx_ppp,
+ priv->prof->rx_pause,
+ priv->prof->rx_ppp);
+
+ return (error);
}
static void mlx4_en_sysctl_conf(struct mlx4_en_priv *priv)
{
- struct net_device *dev;
- struct sysctl_ctx_list *ctx;
- struct sysctl_oid *node;
- struct sysctl_oid_list *node_list;
- struct sysctl_oid *coal;
- struct sysctl_oid_list *coal_list;
-
- dev = priv->dev;
- ctx = &priv->conf_ctx;
-
- sysctl_ctx_init(ctx);
- priv->sysctl = SYSCTL_ADD_NODE(ctx, SYSCTL_STATIC_CHILDREN(_hw),
- OID_AUTO, dev->if_xname, CTLFLAG_RD, 0, "mlx4 10gig ethernet");
- node = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(priv->sysctl), OID_AUTO,
- "conf", CTLFLAG_RD, NULL, "Configuration");
- node_list = SYSCTL_CHILDREN(node);
-
- SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "msg_enable",
- CTLFLAG_RW, &priv->msg_enable, 0,
- "Driver message enable bitfield");
- SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "rx_rings",
- CTLTYPE_INT | CTLFLAG_RD, &priv->rx_ring_num, 0,
- "Number of receive rings");
- SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "tx_rings",
- CTLTYPE_INT | CTLFLAG_RD, &priv->tx_ring_num, 0,
- "Number of transmit rings");
- SYSCTL_ADD_PROC(ctx, node_list, OID_AUTO, "rx_size",
- CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0,
- mlx4_en_set_rx_ring_size, "I", "Receive ring size");
- SYSCTL_ADD_PROC(ctx, node_list, OID_AUTO, "tx_size",
- CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0,
- mlx4_en_set_tx_ring_size, "I", "Transmit ring size");
- SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "ip_reasm",
- CTLFLAG_RW, &priv->ip_reasm, 0,
- "Allow reassembly of IP fragments.");
- SYSCTL_ADD_PROC(ctx, node_list, OID_AUTO, "tx_ppp",
- CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0,
- mlx4_en_set_tx_ppp, "I", "TX Per-priority pause");
- SYSCTL_ADD_PROC(ctx, node_list, OID_AUTO, "rx_ppp",
- CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0,
- mlx4_en_set_rx_ppp, "I", "RX Per-priority pause");
-
- /* Add coalescer configuration. */
- coal = SYSCTL_ADD_NODE(ctx, node_list, OID_AUTO,
- "coalesce", CTLFLAG_RD, NULL, "Interrupt coalesce configuration");
- coal_list = SYSCTL_CHILDREN(node);
- SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "pkt_rate_low",
- CTLFLAG_RW, &priv->pkt_rate_low, 0,
- "Packets per-second for minimum delay");
- SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "rx_usecs_low",
- CTLFLAG_RW, &priv->rx_usecs_low, 0,
- "Minimum RX delay in micro-seconds");
- SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "pkt_rate_high",
- CTLFLAG_RW, &priv->pkt_rate_high, 0,
- "Packets per-second for maximum delay");
- SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "rx_usecs_high",
- CTLFLAG_RW, &priv->rx_usecs_high, 0,
- "Maximum RX delay in micro-seconds");
- SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "sample_interval",
- CTLFLAG_RW, &priv->sample_interval, 0,
- "adaptive frequency in units of HZ ticks");
- SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "adaptive_rx_coal",
- CTLFLAG_RW, &priv->adaptive_rx_coal, 0,
- "Enable adaptive rx coalescing");
+ struct net_device *dev;
+ struct sysctl_ctx_list *ctx;
+ struct sysctl_oid *node;
+ struct sysctl_oid_list *node_list;
+ struct sysctl_oid *coal;
+ struct sysctl_oid_list *coal_list;
+
+ dev = priv->dev;
+ ctx = &priv->conf_ctx;
+
+ sysctl_ctx_init(ctx);
+ priv->sysctl = SYSCTL_ADD_NODE(ctx, SYSCTL_STATIC_CHILDREN(_hw),
+ OID_AUTO, dev->if_xname, CTLFLAG_RD, 0, "mlx4 10gig ethernet");
+ node = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(priv->sysctl), OID_AUTO,
+ "conf", CTLFLAG_RD, NULL, "Configuration");
+ node_list = SYSCTL_CHILDREN(node);
+
+ SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "msg_enable",
+ CTLFLAG_RW, &priv->msg_enable, 0,
+ "Driver message enable bitfield");
+ SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "rx_rings",
+ CTLTYPE_INT | CTLFLAG_RD, &priv->rx_ring_num, 0,
+ "Number of receive rings");
+ SYSCTL_ADD_UINT(ctx, node_list, OID_AUTO, "tx_rings",
+ CTLTYPE_INT | CTLFLAG_RD, &priv->tx_ring_num, 0,
+ "Number of transmit rings");
+ SYSCTL_ADD_PROC(ctx, node_list, OID_AUTO, "rx_size",
+ CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0,
+ mlx4_en_set_rx_ring_size, "I", "Receive ring size");
+ SYSCTL_ADD_PROC(ctx, node_list, OID_AUTO, "tx_size",
+ CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0,
+ mlx4_en_set_tx_ring_size, "I", "Transmit ring size");
+ SYSCTL_ADD_PROC(ctx, node_list, OID_AUTO, "tx_ppp",
+ CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0,
+ mlx4_en_set_tx_ppp, "I", "TX Per-priority pause");
+ SYSCTL_ADD_PROC(ctx, node_list, OID_AUTO, "rx_ppp",
+ CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, priv, 0,
+ mlx4_en_set_rx_ppp, "I", "RX Per-priority pause");
+
+ /* Add coalescer configuration. */
+ coal = SYSCTL_ADD_NODE(ctx, node_list, OID_AUTO,
+ "coalesce", CTLFLAG_RD, NULL, "Interrupt coalesce configuration");
+ coal_list = SYSCTL_CHILDREN(node);
+ SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "pkt_rate_low",
+ CTLFLAG_RW, &priv->pkt_rate_low, 0,
+ "Packets per-second for minimum delay");
+ SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "rx_usecs_low",
+ CTLFLAG_RW, &priv->rx_usecs_low, 0,
+ "Minimum RX delay in micro-seconds");
+ SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "pkt_rate_high",
+ CTLFLAG_RW, &priv->pkt_rate_high, 0,
+ "Packets per-second for maximum delay");
+ SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "rx_usecs_high",
+ CTLFLAG_RW, &priv->rx_usecs_high, 0,
+ "Maximum RX delay in micro-seconds");
+ SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "sample_interval",
+ CTLFLAG_RW, &priv->sample_interval, 0,
+ "adaptive frequency in units of HZ ticks");
+ SYSCTL_ADD_UINT(ctx, coal_list, OID_AUTO, "adaptive_rx_coal",
+ CTLFLAG_RW, &priv->adaptive_rx_coal, 0,
+ "Enable adaptive rx coalescing");
}
+
static void mlx4_en_sysctl_stat(struct mlx4_en_priv *priv)
{
struct net_device *dev;
@@ -1454,43 +2446,111 @@ static void mlx4_en_sysctl_stat(struct mlx4_en_priv *priv)
"TX checksum offloads");
/* Could strdup the names and add in a loop. This is simpler. */
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "broadcast", CTLFLAG_RD,
- &priv->pkstats.broadcast, "Broadcast packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_prio0", CTLFLAG_RD,
- &priv->pkstats.tx_prio[0], "TX Priority 0 packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_prio1", CTLFLAG_RD,
- &priv->pkstats.tx_prio[1], "TX Priority 1 packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_prio2", CTLFLAG_RD,
- &priv->pkstats.tx_prio[2], "TX Priority 2 packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_prio3", CTLFLAG_RD,
- &priv->pkstats.tx_prio[3], "TX Priority 3 packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_prio4", CTLFLAG_RD,
- &priv->pkstats.tx_prio[4], "TX Priority 4 packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_prio5", CTLFLAG_RD,
- &priv->pkstats.tx_prio[5], "TX Priority 5 packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_prio6", CTLFLAG_RD,
- &priv->pkstats.tx_prio[6], "TX Priority 6 packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_prio7", CTLFLAG_RD,
- &priv->pkstats.tx_prio[7], "TX Priority 7 packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_prio0", CTLFLAG_RD,
- &priv->pkstats.rx_prio[0], "RX Priority 0 packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_prio1", CTLFLAG_RD,
- &priv->pkstats.rx_prio[1], "RX Priority 1 packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_prio2", CTLFLAG_RD,
- &priv->pkstats.rx_prio[2], "RX Priority 2 packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_prio3", CTLFLAG_RD,
- &priv->pkstats.rx_prio[3], "RX Priority 3 packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_prio4", CTLFLAG_RD,
- &priv->pkstats.rx_prio[4], "RX Priority 4 packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_prio5", CTLFLAG_RD,
- &priv->pkstats.rx_prio[5], "RX Priority 5 packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_prio6", CTLFLAG_RD,
- &priv->pkstats.rx_prio[6], "RX Priority 6 packets");
- SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_prio7", CTLFLAG_RD,
- &priv->pkstats.rx_prio[7], "RX Priority 7 packets");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_bytes", CTLFLAG_RD,
+ &priv->pkstats.rx_bytes, "RX Bytes");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_packets", CTLFLAG_RD,
+ &priv->pkstats.rx_packets, "RX packets");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_multicast_packets", CTLFLAG_RD,
+ &priv->pkstats.rx_multicast_packets, "RX Multicast Packets");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_broadcast_packets", CTLFLAG_RD,
+ &priv->pkstats.rx_broadcast_packets, "RX Broadcast Packets");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_errors", CTLFLAG_RD,
+ &priv->pkstats.rx_errors, "RX Errors");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_dropped", CTLFLAG_RD,
+ &priv->pkstats.rx_dropped, "RX Dropped");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_length_errors", CTLFLAG_RD,
+ &priv->pkstats.rx_length_errors, "RX Length Errors");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_over_errors", CTLFLAG_RD,
+ &priv->pkstats.rx_over_errors, "RX Over Errors");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_crc_errors", CTLFLAG_RD,
+ &priv->pkstats.rx_crc_errors, "RX CRC Errors");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_jabbers", CTLFLAG_RD,
+ &priv->pkstats.rx_jabbers, "RX Jabbers");
+
+
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_in_range_length_error", CTLFLAG_RD,
+ &priv->pkstats.rx_in_range_length_error, "RX IN_Range Length Error");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_out_range_length_error",
+ CTLFLAG_RD, &priv->pkstats.rx_out_range_length_error,
+ "RX Out Range Length Error");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_lt_64_bytes_packets", CTLFLAG_RD,
+ &priv->pkstats.rx_lt_64_bytes_packets, "RX Lt 64 Bytes Packets");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_127_bytes_packets", CTLFLAG_RD,
+ &priv->pkstats.rx_127_bytes_packets, "RX 127 bytes Packets");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_255_bytes_packets", CTLFLAG_RD,
+ &priv->pkstats.rx_255_bytes_packets, "RX 255 bytes Packets");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_511_bytes_packets", CTLFLAG_RD,
+ &priv->pkstats.rx_511_bytes_packets, "RX 511 bytes Packets");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_1023_bytes_packets", CTLFLAG_RD,
+ &priv->pkstats.rx_1023_bytes_packets, "RX 1023 bytes Packets");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_1518_bytes_packets", CTLFLAG_RD,
+ &priv->pkstats.rx_1518_bytes_packets, "RX 1518 bytes Packets");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_1522_bytes_packets", CTLFLAG_RD,
+ &priv->pkstats.rx_1522_bytes_packets, "RX 1522 bytes Packets");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_1548_bytes_packets", CTLFLAG_RD,
+ &priv->pkstats.rx_1548_bytes_packets, "RX 1548 bytes Packets");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "rx_gt_1548_bytes_packets", CTLFLAG_RD,
+ &priv->pkstats.rx_gt_1548_bytes_packets,
+ "RX Greater Then 1548 bytes Packets");
+
+struct mlx4_en_pkt_stats {
+ unsigned long tx_packets;
+ unsigned long tx_bytes;
+ unsigned long tx_multicast_packets;
+ unsigned long tx_broadcast_packets;
+ unsigned long tx_errors;
+ unsigned long tx_dropped;
+ unsigned long tx_lt_64_bytes_packets;
+ unsigned long tx_127_bytes_packets;
+ unsigned long tx_255_bytes_packets;
+ unsigned long tx_511_bytes_packets;
+ unsigned long tx_1023_bytes_packets;
+ unsigned long tx_1518_bytes_packets;
+ unsigned long tx_1522_bytes_packets;
+ unsigned long tx_1548_bytes_packets;
+ unsigned long tx_gt_1548_bytes_packets;
+ unsigned long rx_prio[NUM_PRIORITIES][NUM_PRIORITY_STATS];
+ unsigned long tx_prio[NUM_PRIORITIES][NUM_PRIORITY_STATS];
+#define NUM_PKT_STATS 72
+};
+
+
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_packets", CTLFLAG_RD,
+ &priv->pkstats.tx_packets, "TX packets");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_bytes", CTLFLAG_RD,
+ &priv->pkstats.tx_packets, "TX Bytes");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_multicast_packets", CTLFLAG_RD,
+ &priv->pkstats.tx_multicast_packets, "TX Multicast Packets");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_broadcast_packets", CTLFLAG_RD,
+ &priv->pkstats.tx_broadcast_packets, "TX Broadcast Packets");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_errors", CTLFLAG_RD,
+ &priv->pkstats.tx_errors, "TX Errors");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_dropped", CTLFLAG_RD,
+ &priv->pkstats.tx_dropped, "TX Dropped");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_lt_64_bytes_packets", CTLFLAG_RD,
+ &priv->pkstats.tx_lt_64_bytes_packets, "TX Less Then 64 Bytes Packets");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_127_bytes_packets", CTLFLAG_RD,
+ &priv->pkstats.tx_127_bytes_packets, "TX 127 Bytes Packets");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_255_bytes_packets", CTLFLAG_RD,
+ &priv->pkstats.tx_255_bytes_packets, "TX 255 Bytes Packets");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_511_bytes_packets", CTLFLAG_RD,
+ &priv->pkstats.tx_511_bytes_packets, "TX 511 Bytes Packets");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_1023_bytes_packets", CTLFLAG_RD,
+ &priv->pkstats.tx_1023_bytes_packets, "TX 1023 Bytes Packets");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_1518_bytes_packets", CTLFLAG_RD,
+ &priv->pkstats.tx_1518_bytes_packets, "TX 1518 Bytes Packets");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_1522_bytes_packets", CTLFLAG_RD,
+ &priv->pkstats.tx_1522_bytes_packets, "TX 1522 Bytes Packets");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_1548_bytes_packets", CTLFLAG_RD,
+ &priv->pkstats.tx_1548_bytes_packets, "TX 1548 Bytes Packets");
+ SYSCTL_ADD_ULONG(ctx, node_list, OID_AUTO, "tx_gt_1548_bytes_packets", CTLFLAG_RD,
+ &priv->pkstats.tx_gt_1548_bytes_packets,
+ "TX Greater Then 1548 Bytes Packets");
+
+
for (i = 0; i < priv->tx_ring_num; i++) {
- tx_ring = &priv->tx_ring[i];
+ tx_ring = priv->tx_ring[i];
snprintf(namebuf, sizeof(namebuf), "tx_ring%d", i);
ring_node = SYSCTL_ADD_NODE(ctx, node_list, OID_AUTO, namebuf,
CTLFLAG_RD, NULL, "TX Ring");
@@ -1499,12 +2559,10 @@ static void mlx4_en_sysctl_stat(struct mlx4_en_priv *priv)
CTLFLAG_RD, &tx_ring->packets, "TX packets");
SYSCTL_ADD_ULONG(ctx, ring_list, OID_AUTO, "bytes",
CTLFLAG_RD, &tx_ring->bytes, "TX bytes");
- SYSCTL_ADD_ULONG(ctx, ring_list, OID_AUTO, "error",
- CTLFLAG_RD, &tx_ring->errors, "TX soft errors");
}
for (i = 0; i < priv->rx_ring_num; i++) {
- rx_ring = &priv->rx_ring[i];
+ rx_ring = priv->rx_ring[i];
snprintf(namebuf, sizeof(namebuf), "rx_ring%d", i);
ring_node = SYSCTL_ADD_NODE(ctx, node_list, OID_AUTO, namebuf,
CTLFLAG_RD, NULL, "RX Ring");
@@ -1515,153 +2573,5 @@ static void mlx4_en_sysctl_stat(struct mlx4_en_priv *priv)
CTLFLAG_RD, &rx_ring->bytes, "RX bytes");
SYSCTL_ADD_ULONG(ctx, ring_list, OID_AUTO, "error",
CTLFLAG_RD, &rx_ring->errors, "RX soft errors");
- SYSCTL_ADD_UINT(ctx, ring_list, OID_AUTO, "lro_queued",
- CTLFLAG_RD, &rx_ring->lro.lro_queued, 0, "LRO Queued");
- SYSCTL_ADD_UINT(ctx, ring_list, OID_AUTO, "lro_flushed",
- CTLFLAG_RD, &rx_ring->lro.lro_flushed, 0, "LRO Flushed");
}
}
-
-int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
- struct mlx4_en_port_profile *prof)
-{
- static volatile int mlx4_en_unit;
- struct net_device *dev;
- struct mlx4_en_priv *priv;
- uint8_t dev_addr[ETHER_ADDR_LEN];
- int err;
- int i;
-
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- dev = priv->dev = if_alloc(IFT_ETHER);
- if (dev == NULL) {
- mlx4_err(mdev, "Net device allocation failed\n");
- kfree(priv);
- return -ENOMEM;
- }
- dev->if_softc = priv;
- if_initname(dev, "mlxen", atomic_fetchadd_int(&mlx4_en_unit, 1));
- dev->if_mtu = ETHERMTU;
- dev->if_baudrate = 1000000000;
- dev->if_init = mlx4_en_init;
- dev->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- dev->if_ioctl = mlx4_en_ioctl;
- dev->if_transmit = mlx4_en_transmit;
- dev->if_qflush = mlx4_en_qflush;
- dev->if_snd.ifq_maxlen = prof->tx_ring_size;
-
- /*
- * Initialize driver private data
- */
- priv->dev = dev;
- priv->mdev = mdev;
- priv->prof = prof;
- priv->port = port;
- priv->port_up = false;
- priv->rx_csum = 1;
- priv->flags = prof->flags;
- priv->tx_ring_num = prof->tx_ring_num;
- priv->rx_ring_num = prof->rx_ring_num;
- priv->mac_index = -1;
- priv->msg_enable = MLX4_EN_MSG_LEVEL;
- priv->ip_reasm = priv->mdev->profile.ip_reasm;
- mtx_init(&priv->stats_lock.m, "mlx4 stats", NULL, MTX_DEF);
- mtx_init(&priv->vlan_lock.m, "mlx4 vlan", NULL, MTX_DEF);
- INIT_WORK(&priv->start_port_task, mlx4_en_lock_and_start_port);
- INIT_WORK(&priv->stop_port_task, mlx4_en_lock_and_stop_port);
- INIT_WORK(&priv->mcast_task, mlx4_en_do_set_multicast);
- INIT_WORK(&priv->watchdog_task, mlx4_en_restart);
- INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate);
- INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats);
- callout_init(&priv->watchdog_timer, 1);
-
- /* Query for default mac and max mtu */
- priv->max_mtu = mdev->dev->caps.eth_mtu_cap[priv->port];
- priv->mac = mdev->dev->caps.def_mac[priv->port];
-
- if (ILLEGAL_MAC(priv->mac)) {
- en_err(priv, "Port: %d, invalid mac burned: 0x%llx, quiting\n",
- priv->port, (long long)priv->mac);
- err = -EINVAL;
- goto out;
- }
-
- mlx4_en_sysctl_conf(priv);
-
- err = mlx4_en_alloc_resources(priv);
- if (err)
- goto out;
-
- /* Allocate page for receive rings */
- err = mlx4_alloc_hwq_res(mdev->dev, &priv->res,
- MLX4_EN_PAGE_SIZE, MLX4_EN_PAGE_SIZE);
- if (err) {
- en_err(priv, "Failed to allocate page for rx qps\n");
- goto out;
- }
- priv->allocated = 1;
-
- /*
- * Set driver features
- */
- dev->if_capabilities |= IFCAP_RXCSUM | IFCAP_TXCSUM;
- dev->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING;
- dev->if_capabilities |= IFCAP_VLAN_HWCSUM | IFCAP_VLAN_HWFILTER;
- dev->if_capabilities |= IFCAP_LINKSTATE | IFCAP_JUMBO_MTU;
- if (mdev->LSO_support)
- dev->if_capabilities |= IFCAP_TSO4 | IFCAP_VLAN_HWTSO;
- if (mdev->profile.num_lro)
- dev->if_capabilities |= IFCAP_LRO;
- dev->if_capenable = dev->if_capabilities;
- /*
- * Setup wake-on-lan.
- */
-#if 0
- if (priv->mdev->dev->caps.wol) {
- u64 config;
- if (mlx4_wol_read(priv->mdev->dev, &config, priv->port) == 0) {
- if (config & MLX4_EN_WOL_MAGIC)
- dev->if_capabilities |= IFCAP_WOL_MAGIC;
- if (config & MLX4_EN_WOL_ENABLED)
- dev->if_capenable |= IFCAP_WOL_MAGIC;
- }
- }
-#endif
-
- /* Register for VLAN events */
- priv->vlan_attach = EVENTHANDLER_REGISTER(vlan_config,
- mlx4_en_vlan_rx_add_vid, priv, EVENTHANDLER_PRI_FIRST);
- priv->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
- mlx4_en_vlan_rx_kill_vid, priv, EVENTHANDLER_PRI_FIRST);
-
- mdev->pndev[priv->port] = dev;
-
- priv->last_link_state = MLX4_DEV_EVENT_PORT_DOWN;
- if_link_state_change(dev, LINK_STATE_DOWN);
-
- /* Set default MAC */
- for (i = 0; i < ETHER_ADDR_LEN; i++)
- dev_addr[ETHER_ADDR_LEN - 1 - i] = (u8) (priv->mac >> (8 * i));
-
- ether_ifattach(dev, dev_addr);
- ifmedia_init(&priv->media, IFM_IMASK | IFM_ETH_FMASK,
- mlx4_en_media_change, mlx4_en_media_status);
- ifmedia_add(&priv->media, IFM_ETHER | IFM_FDX | IFM_1000_T, 0, NULL);
- ifmedia_add(&priv->media, IFM_ETHER | IFM_FDX | IFM_10G_SR, 0, NULL);
- ifmedia_add(&priv->media, IFM_ETHER | IFM_FDX | IFM_10G_CX4, 0, NULL);
- ifmedia_add(&priv->media, IFM_ETHER | IFM_AUTO, 0, NULL);
- ifmedia_set(&priv->media, IFM_ETHER | IFM_AUTO);
-
- en_warn(priv, "Using %d TX rings\n", prof->tx_ring_num);
- en_warn(priv, "Using %d RX rings\n", prof->rx_ring_num);
-
- priv->registered = 1;
- queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
-
- return 0;
-
-out:
- mlx4_en_destroy_netdev(dev);
- return err;
-}
-
diff --git a/sys/ofed/drivers/net/mlx4/en_port.c b/sys/ofed/drivers/net/mlx4/en_port.c
index 303bb2b..33eb0b9 100644
--- a/sys/ofed/drivers/net/mlx4/en_port.c
+++ b/sys/ofed/drivers/net/mlx4/en_port.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2007, 2014 Mellanox Technologies. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -31,28 +31,25 @@
*
*/
-
-#include "mlx4_en.h"
-
+#include <sys/types.h>
#include <linux/if_vlan.h>
#include <linux/mlx4/device.h>
#include <linux/mlx4/cmd.h>
-#if 0 // moved to port.c
-int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port,
- u64 mac, u64 clear, u8 mode)
-{
- return mlx4_cmd(dev, (mac | (clear << 63)), port, mode,
- MLX4_CMD_SET_MCAST_FLTR, MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
-}
-#endif
+#include "en_port.h"
+#include "mlx4_en.h"
+#define EN_IFQ_MIN_INTERVAL 3000
-int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, u8 port, u32 *vlans)
+
+int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, struct mlx4_en_priv *priv)
{
struct mlx4_cmd_mailbox *mailbox;
struct mlx4_set_vlan_fltr_mbox *filter;
- int i, j;
+ int i;
+ int j;
+ int index = 0;
+ u32 entry;
int err = 0;
mailbox = mlx4_alloc_cmd_mailbox(dev);
@@ -60,85 +57,20 @@ int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, u8 port, u32 *vlans)
return PTR_ERR(mailbox);
filter = mailbox->buf;
- memset(filter, 0, sizeof *filter);
- if (vlans)
- for (i = 0, j = VLAN_FLTR_SIZE - 1; i < VLAN_FLTR_SIZE;
- i++, j--)
- filter->entry[j] = cpu_to_be32(vlans[i]);
- err = mlx4_cmd(dev, mailbox->dma, port, 0, MLX4_CMD_SET_VLAN_FLTR,
- MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
-}
-
-
-#if 0 //moved to port.c - shahark
-int mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu,
- u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx)
-{
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_set_port_general_context *context;
- int err;
- u32 in_mod;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- context = mailbox->buf;
- memset(context, 0, sizeof *context);
-
- context->flags = SET_PORT_GEN_ALL_VALID;
- context->mtu = cpu_to_be16(mtu);
- context->pptx = (pptx * (!pfctx)) << 7;
- context->pfctx = pfctx;
- context->pprx = (pprx * (!pfcrx)) << 7;
- context->pfcrx = pfcrx;
-
- in_mod = MLX4_SET_PORT_GENERAL << 8 | port;
- err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
- MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
-
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
-}
-int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
- u8 promisc)
-{
-
- printf("%s %s:%d\n", __func__, __FILE__, __LINE__);
-
-
-
- struct mlx4_cmd_mailbox *mailbox;
- struct mlx4_set_port_rqp_calc_context *context;
- int err;
- u32 in_mod;
-
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- context = mailbox->buf;
- memset(context, 0, sizeof *context);
-
- context->base_qpn = cpu_to_be32(base_qpn);
- context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_EN_SHIFT | base_qpn);
-/*
- context->mcast = cpu_to_be32((dev->caps.mc_promisc_mode <<
- SET_PORT_PROMISC_MODE_SHIFT) | base_qpn);
-*/
- context->intra_no_vlan = 0;
- context->no_vlan = MLX4_NO_VLAN_IDX;
- context->intra_vlan_miss = 0;
- context->vlan_miss = MLX4_VLAN_MISS_IDX;
-
- in_mod = MLX4_SET_PORT_RQP_CALC << 8 | port;
- err = mlx4_cmd(dev, mailbox->dma, in_mod, 1, MLX4_CMD_SET_PORT,
- MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
-
+ memset(filter, 0, sizeof(*filter));
+ for (i = VLAN_FLTR_SIZE - 1; i >= 0; i--) {
+ entry = 0;
+ for (j = 0; j < 32; j++)
+ if (test_bit(index, priv->active_vlans))
+ entry |= 1 << j;
+ index++;
+ filter->entry[i] = cpu_to_be32(entry);
+ }
+ err = mlx4_cmd(dev, mailbox->dma, priv->port, 0, MLX4_CMD_SET_VLAN_FLTR,
+ MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED);
mlx4_free_cmd_mailbox(dev, mailbox);
return err;
}
-#endif
int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port)
{
@@ -153,7 +85,8 @@ int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port)
return PTR_ERR(mailbox);
memset(mailbox->buf, 0, sizeof(*qport_context));
err = mlx4_cmd_box(mdev->dev, 0, mailbox->dma, port, 0,
- MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED);
+ MLX4_CMD_QUERY_PORT, MLX4_CMD_TIME_CLASS_B,
+ MLX4_CMD_WRAPPED);
if (err)
goto out;
qport_context = mailbox->buf;
@@ -169,95 +102,77 @@ int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port)
case MLX4_EN_10G_SPEED_XFI:
state->link_speed = 10000;
break;
+ case MLX4_EN_20G_SPEED:
+ state->link_speed = 20000;
+ break;
case MLX4_EN_40G_SPEED:
state->link_speed = 40000;
break;
+ case MLX4_EN_56G_SPEED:
+ state->link_speed = 56000;
+ break;
default:
state->link_speed = -1;
break;
}
state->transciver = qport_context->transceiver;
- if (be32_to_cpu(qport_context->transceiver_code_hi) & 0x400)
- state->transciver = 0x80;
+ state->autoneg = !!(qport_context->autoneg & MLX4_EN_AUTONEG_MASK);
out:
mlx4_free_cmd_mailbox(mdev->dev, mailbox);
return err;
}
-#if 0
-static int read_iboe_counters(struct mlx4_dev *dev, int index, u64 counters[])
+int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
{
- struct mlx4_cmd_mailbox *mailbox;
+ struct mlx4_en_stat_out_mbox *mlx4_en_stats;
+ struct mlx4_en_stat_out_flow_control_mbox *flowstats;
+ struct mlx4_en_priv *priv = netdev_priv(mdev->pndev[port]);
+ struct mlx4_en_vport_stats *vport_stats = &priv->vport_stats;
+ struct mlx4_cmd_mailbox *mailbox = NULL;
+ struct mlx4_cmd_mailbox *mailbox_flow = NULL;
+ u64 in_mod = reset << 8 | port;
int err;
- int mode;
- struct mlx4_counters_ext *ext;
- struct mlx4_counters *reg;
+ int i;
+ int do_if_stat = 1;
+ unsigned long period = (unsigned long) (jiffies - priv->last_ifq_jiffies);
+ struct mlx4_en_vport_stats tmp_vport_stats;
+ struct net_device *dev;
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox))
- return -ENOMEM;
+ if (jiffies_to_msecs(period) < EN_IFQ_MIN_INTERVAL ||
+ priv->counter_index == 0xff)
+ do_if_stat = 0;
- err = mlx4_cmd_box(dev, 0, mailbox->dma, index, 0,
- MLX4_CMD_QUERY_IF_STAT, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_WRAPPED);
- if (err)
- goto out;
+ mailbox = mlx4_alloc_cmd_mailbox(mdev->dev);
+ if (IS_ERR(mailbox)) {
+ err = PTR_ERR(mailbox);
+ goto mailbox_out;
+ }
- mode = be32_to_cpu(((struct mlx4_counters *)mailbox->buf)->counter_mode) & 0xf;
- switch (mode) {
- case 0:
- reg = mailbox->buf;
- counters[0] = be64_to_cpu(reg->rx_frames);
- counters[1] = be64_to_cpu(reg->tx_frames);
- counters[2] = be64_to_cpu(reg->rx_bytes);
- counters[3] = be64_to_cpu(reg->tx_bytes);
- break;
- case 1:
- ext = mailbox->buf;
- counters[0] = be64_to_cpu(ext->rx_uni_frames);
- counters[1] = be64_to_cpu(ext->tx_uni_frames);
- counters[2] = be64_to_cpu(ext->rx_uni_bytes);
- counters[3] = be64_to_cpu(ext->tx_uni_bytes);
- break;
- default:
- err = -EINVAL;
+ mailbox_flow = mlx4_alloc_cmd_mailbox(mdev->dev);
+ if (IS_ERR(mailbox_flow)) {
+ mlx4_free_cmd_mailbox(mdev->dev, mailbox);
+ err = PTR_ERR(mailbox_flow);
+ goto mailbox_out;
}
-out:
- mlx4_free_cmd_mailbox(dev, mailbox);
- return err;
-}
-#endif
+ /* 0xffs indicates invalid value */
+ memset(mailbox_flow->buf, 0xff, sizeof(*flowstats) *
+ MLX4_NUM_PRIORITIES);
-int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
-{
- struct mlx4_en_stat_out_mbox *mlx4_en_stats;
- struct net_device *dev;
- struct mlx4_en_priv *priv;
- struct mlx4_cmd_mailbox *mailbox;
- u64 in_mod = reset << 8 | port;
- unsigned long oerror;
- unsigned long ierror;
- int err;
- int i;
- //int counter;
- u64 counters[4];
-
- dev = mdev->pndev[port];
- priv = netdev_priv(dev);
- memset(counters, 0, sizeof counters);
- /*
- counter = mlx4_get_iboe_counter(priv->mdev->dev, port);
- if (counter >= 0)
- err = read_iboe_counters(priv->mdev->dev, counter, counters);
- */
+ if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_FLOWSTATS_EN) {
+ memset(mailbox_flow->buf, 0, sizeof(*flowstats));
+ err = mlx4_cmd_box(mdev->dev, 0, mailbox_flow->dma,
+ in_mod | 1<<12, 0, MLX4_CMD_DUMP_ETH_STATS,
+ MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
+
+ if (err)
+ goto out;
+ }
- mailbox = mlx4_alloc_cmd_mailbox(mdev->dev);
- if (IS_ERR(mailbox))
- return PTR_ERR(mailbox);
- memset(mailbox->buf, 0, sizeof(*mlx4_en_stats));
err = mlx4_cmd_box(mdev->dev, 0, mailbox->dma, in_mod, 0,
- MLX4_CMD_DUMP_ETH_STATS, MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED);
+ MLX4_CMD_DUMP_ETH_STATS, MLX4_CMD_TIME_CLASS_B,
+ MLX4_CMD_NATIVE);
if (err)
goto out;
@@ -265,74 +180,404 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
spin_lock(&priv->stats_lock);
- oerror = ierror = 0;
- dev->if_ipackets = counters[0];
- dev->if_ibytes = counters[2];
+ priv->port_stats.rx_chksum_good = 0;
+ priv->port_stats.rx_chksum_none = 0;
for (i = 0; i < priv->rx_ring_num; i++) {
- dev->if_ipackets += priv->rx_ring[i].packets;
- dev->if_ibytes += priv->rx_ring[i].bytes;
- ierror += priv->rx_ring[i].errors;
+ priv->port_stats.rx_chksum_good += priv->rx_ring[i]->csum_ok;
+ priv->port_stats.rx_chksum_none += priv->rx_ring[i]->csum_none;
}
- dev->if_opackets = counters[1];
- dev->if_obytes = counters[3];
- for (i = 0; i <= priv->tx_ring_num; i++) {
- dev->if_opackets += priv->tx_ring[i].packets;
- dev->if_obytes += priv->tx_ring[i].bytes;
- oerror += priv->tx_ring[i].errors;
+
+ priv->port_stats.tx_chksum_offload = 0;
+ priv->port_stats.queue_stopped = 0;
+ priv->port_stats.wake_queue = 0;
+ for (i = 0; i < priv->tx_ring_num; i++) {
+ priv->port_stats.tx_chksum_offload += priv->tx_ring[i]->tx_csum;
+ priv->port_stats.queue_stopped += priv->tx_ring[i]->queue_stopped;
+ priv->port_stats.wake_queue += priv->tx_ring[i]->wake_queue;
+ }
+ /* RX Statistics */
+ priv->pkstats.rx_packets = be64_to_cpu(mlx4_en_stats->RTOT_prio_0) +
+ be64_to_cpu(mlx4_en_stats->RTOT_prio_1) +
+ be64_to_cpu(mlx4_en_stats->RTOT_prio_2) +
+ be64_to_cpu(mlx4_en_stats->RTOT_prio_3) +
+ be64_to_cpu(mlx4_en_stats->RTOT_prio_4) +
+ be64_to_cpu(mlx4_en_stats->RTOT_prio_5) +
+ be64_to_cpu(mlx4_en_stats->RTOT_prio_6) +
+ be64_to_cpu(mlx4_en_stats->RTOT_prio_7) +
+ be64_to_cpu(mlx4_en_stats->RTOT_novlan);
+ priv->pkstats.rx_bytes = be64_to_cpu(mlx4_en_stats->ROCT_prio_0) +
+ be64_to_cpu(mlx4_en_stats->ROCT_prio_1) +
+ be64_to_cpu(mlx4_en_stats->ROCT_prio_2) +
+ be64_to_cpu(mlx4_en_stats->ROCT_prio_3) +
+ be64_to_cpu(mlx4_en_stats->ROCT_prio_4) +
+ be64_to_cpu(mlx4_en_stats->ROCT_prio_5) +
+ be64_to_cpu(mlx4_en_stats->ROCT_prio_6) +
+ be64_to_cpu(mlx4_en_stats->ROCT_prio_7) +
+ be64_to_cpu(mlx4_en_stats->ROCT_novlan);
+ priv->pkstats.rx_multicast_packets = be64_to_cpu(mlx4_en_stats->MCAST_prio_0) +
+ be64_to_cpu(mlx4_en_stats->MCAST_prio_1) +
+ be64_to_cpu(mlx4_en_stats->MCAST_prio_2) +
+ be64_to_cpu(mlx4_en_stats->MCAST_prio_3) +
+ be64_to_cpu(mlx4_en_stats->MCAST_prio_4) +
+ be64_to_cpu(mlx4_en_stats->MCAST_prio_5) +
+ be64_to_cpu(mlx4_en_stats->MCAST_prio_6) +
+ be64_to_cpu(mlx4_en_stats->MCAST_prio_7) +
+ be64_to_cpu(mlx4_en_stats->MCAST_novlan);
+ priv->pkstats.rx_broadcast_packets = be64_to_cpu(mlx4_en_stats->RBCAST_prio_0) +
+ be64_to_cpu(mlx4_en_stats->RBCAST_prio_1) +
+ be64_to_cpu(mlx4_en_stats->RBCAST_prio_2) +
+ be64_to_cpu(mlx4_en_stats->RBCAST_prio_3) +
+ be64_to_cpu(mlx4_en_stats->RBCAST_prio_4) +
+ be64_to_cpu(mlx4_en_stats->RBCAST_prio_5) +
+ be64_to_cpu(mlx4_en_stats->RBCAST_prio_6) +
+ be64_to_cpu(mlx4_en_stats->RBCAST_prio_7) +
+ be64_to_cpu(mlx4_en_stats->RBCAST_novlan);
+ priv->pkstats.rx_errors = be64_to_cpu(mlx4_en_stats->PCS) +
+ be32_to_cpu(mlx4_en_stats->RJBBR) +
+ be32_to_cpu(mlx4_en_stats->RCRC) +
+ be32_to_cpu(mlx4_en_stats->RRUNT) +
+ be64_to_cpu(mlx4_en_stats->RInRangeLengthErr) +
+ be64_to_cpu(mlx4_en_stats->ROutRangeLengthErr) +
+ be32_to_cpu(mlx4_en_stats->RSHORT) +
+ be64_to_cpu(mlx4_en_stats->RGIANT_prio_0) +
+ be64_to_cpu(mlx4_en_stats->RGIANT_prio_1) +
+ be64_to_cpu(mlx4_en_stats->RGIANT_prio_2) +
+ be64_to_cpu(mlx4_en_stats->RGIANT_prio_3) +
+ be64_to_cpu(mlx4_en_stats->RGIANT_prio_4) +
+ be64_to_cpu(mlx4_en_stats->RGIANT_prio_5) +
+ be64_to_cpu(mlx4_en_stats->RGIANT_prio_6) +
+ be64_to_cpu(mlx4_en_stats->RGIANT_prio_7) +
+ be64_to_cpu(mlx4_en_stats->RGIANT_novlan);
+ priv->pkstats.rx_dropped = be32_to_cpu(mlx4_en_stats->RdropOvflw);
+ priv->pkstats.rx_length_errors = be32_to_cpu(mlx4_en_stats->RdropLength);
+ priv->pkstats.rx_over_errors = be32_to_cpu(mlx4_en_stats->RdropOvflw);
+ priv->pkstats.rx_crc_errors = be32_to_cpu(mlx4_en_stats->RCRC);
+ priv->pkstats.rx_jabbers = be32_to_cpu(mlx4_en_stats->RJBBR);
+ priv->pkstats.rx_in_range_length_error = be64_to_cpu(mlx4_en_stats->RInRangeLengthErr);
+ priv->pkstats.rx_out_range_length_error = be64_to_cpu(mlx4_en_stats->ROutRangeLengthErr);
+ priv->pkstats.rx_lt_64_bytes_packets = be64_to_cpu(mlx4_en_stats->R64_prio_0) +
+ be64_to_cpu(mlx4_en_stats->R64_prio_1) +
+ be64_to_cpu(mlx4_en_stats->R64_prio_2) +
+ be64_to_cpu(mlx4_en_stats->R64_prio_3) +
+ be64_to_cpu(mlx4_en_stats->R64_prio_4) +
+ be64_to_cpu(mlx4_en_stats->R64_prio_5) +
+ be64_to_cpu(mlx4_en_stats->R64_prio_6) +
+ be64_to_cpu(mlx4_en_stats->R64_prio_7) +
+ be64_to_cpu(mlx4_en_stats->R64_novlan);
+ priv->pkstats.rx_127_bytes_packets = be64_to_cpu(mlx4_en_stats->R127_prio_0) +
+ be64_to_cpu(mlx4_en_stats->R127_prio_1) +
+ be64_to_cpu(mlx4_en_stats->R127_prio_2) +
+ be64_to_cpu(mlx4_en_stats->R127_prio_3) +
+ be64_to_cpu(mlx4_en_stats->R127_prio_4) +
+ be64_to_cpu(mlx4_en_stats->R127_prio_5) +
+ be64_to_cpu(mlx4_en_stats->R127_prio_6) +
+ be64_to_cpu(mlx4_en_stats->R127_prio_7) +
+ be64_to_cpu(mlx4_en_stats->R127_novlan);
+ priv->pkstats.rx_255_bytes_packets = be64_to_cpu(mlx4_en_stats->R255_prio_0) +
+ be64_to_cpu(mlx4_en_stats->R255_prio_1) +
+ be64_to_cpu(mlx4_en_stats->R255_prio_2) +
+ be64_to_cpu(mlx4_en_stats->R255_prio_3) +
+ be64_to_cpu(mlx4_en_stats->R255_prio_4) +
+ be64_to_cpu(mlx4_en_stats->R255_prio_5) +
+ be64_to_cpu(mlx4_en_stats->R255_prio_6) +
+ be64_to_cpu(mlx4_en_stats->R255_prio_7) +
+ be64_to_cpu(mlx4_en_stats->R255_novlan);
+ priv->pkstats.rx_511_bytes_packets = be64_to_cpu(mlx4_en_stats->R511_prio_0) +
+ be64_to_cpu(mlx4_en_stats->R511_prio_1) +
+ be64_to_cpu(mlx4_en_stats->R511_prio_2) +
+ be64_to_cpu(mlx4_en_stats->R511_prio_3) +
+ be64_to_cpu(mlx4_en_stats->R511_prio_4) +
+ be64_to_cpu(mlx4_en_stats->R511_prio_5) +
+ be64_to_cpu(mlx4_en_stats->R511_prio_6) +
+ be64_to_cpu(mlx4_en_stats->R511_prio_7) +
+ be64_to_cpu(mlx4_en_stats->R511_novlan);
+ priv->pkstats.rx_1023_bytes_packets = be64_to_cpu(mlx4_en_stats->R1023_prio_0) +
+ be64_to_cpu(mlx4_en_stats->R1023_prio_1) +
+ be64_to_cpu(mlx4_en_stats->R1023_prio_2) +
+ be64_to_cpu(mlx4_en_stats->R1023_prio_3) +
+ be64_to_cpu(mlx4_en_stats->R1023_prio_4) +
+ be64_to_cpu(mlx4_en_stats->R1023_prio_5) +
+ be64_to_cpu(mlx4_en_stats->R1023_prio_6) +
+ be64_to_cpu(mlx4_en_stats->R1023_prio_7) +
+ be64_to_cpu(mlx4_en_stats->R1023_novlan);
+ priv->pkstats.rx_1518_bytes_packets = be64_to_cpu(mlx4_en_stats->R1518_prio_0) +
+ be64_to_cpu(mlx4_en_stats->R1518_prio_1) +
+ be64_to_cpu(mlx4_en_stats->R1518_prio_2) +
+ be64_to_cpu(mlx4_en_stats->R1518_prio_3) +
+ be64_to_cpu(mlx4_en_stats->R1518_prio_4) +
+ be64_to_cpu(mlx4_en_stats->R1518_prio_5) +
+ be64_to_cpu(mlx4_en_stats->R1518_prio_6) +
+ be64_to_cpu(mlx4_en_stats->R1518_prio_7) +
+ be64_to_cpu(mlx4_en_stats->R1518_novlan);
+ priv->pkstats.rx_1522_bytes_packets = be64_to_cpu(mlx4_en_stats->R1522_prio_0) +
+ be64_to_cpu(mlx4_en_stats->R1522_prio_1) +
+ be64_to_cpu(mlx4_en_stats->R1522_prio_2) +
+ be64_to_cpu(mlx4_en_stats->R1522_prio_3) +
+ be64_to_cpu(mlx4_en_stats->R1522_prio_4) +
+ be64_to_cpu(mlx4_en_stats->R1522_prio_5) +
+ be64_to_cpu(mlx4_en_stats->R1522_prio_6) +
+ be64_to_cpu(mlx4_en_stats->R1522_prio_7) +
+ be64_to_cpu(mlx4_en_stats->R1522_novlan);
+ priv->pkstats.rx_1548_bytes_packets = be64_to_cpu(mlx4_en_stats->R1548_prio_0) +
+ be64_to_cpu(mlx4_en_stats->R1548_prio_1) +
+ be64_to_cpu(mlx4_en_stats->R1548_prio_2) +
+ be64_to_cpu(mlx4_en_stats->R1548_prio_3) +
+ be64_to_cpu(mlx4_en_stats->R1548_prio_4) +
+ be64_to_cpu(mlx4_en_stats->R1548_prio_5) +
+ be64_to_cpu(mlx4_en_stats->R1548_prio_6) +
+ be64_to_cpu(mlx4_en_stats->R1548_prio_7) +
+ be64_to_cpu(mlx4_en_stats->R1548_novlan);
+ priv->pkstats.rx_gt_1548_bytes_packets = be64_to_cpu(mlx4_en_stats->R2MTU_prio_0) +
+ be64_to_cpu(mlx4_en_stats->R2MTU_prio_1) +
+ be64_to_cpu(mlx4_en_stats->R2MTU_prio_2) +
+ be64_to_cpu(mlx4_en_stats->R2MTU_prio_3) +
+ be64_to_cpu(mlx4_en_stats->R2MTU_prio_4) +
+ be64_to_cpu(mlx4_en_stats->R2MTU_prio_5) +
+ be64_to_cpu(mlx4_en_stats->R2MTU_prio_6) +
+ be64_to_cpu(mlx4_en_stats->R2MTU_prio_7) +
+ be64_to_cpu(mlx4_en_stats->R2MTU_novlan);
+
+ /* Tx Stats */
+ priv->pkstats.tx_packets = be64_to_cpu(mlx4_en_stats->TTOT_prio_0) +
+ be64_to_cpu(mlx4_en_stats->TTOT_prio_1) +
+ be64_to_cpu(mlx4_en_stats->TTOT_prio_2) +
+ be64_to_cpu(mlx4_en_stats->TTOT_prio_3) +
+ be64_to_cpu(mlx4_en_stats->TTOT_prio_4) +
+ be64_to_cpu(mlx4_en_stats->TTOT_prio_5) +
+ be64_to_cpu(mlx4_en_stats->TTOT_prio_6) +
+ be64_to_cpu(mlx4_en_stats->TTOT_prio_7) +
+ be64_to_cpu(mlx4_en_stats->TTOT_novlan);
+ priv->pkstats.tx_bytes = be64_to_cpu(mlx4_en_stats->TOCT_prio_0) +
+ be64_to_cpu(mlx4_en_stats->TOCT_prio_1) +
+ be64_to_cpu(mlx4_en_stats->TOCT_prio_2) +
+ be64_to_cpu(mlx4_en_stats->TOCT_prio_3) +
+ be64_to_cpu(mlx4_en_stats->TOCT_prio_4) +
+ be64_to_cpu(mlx4_en_stats->TOCT_prio_5) +
+ be64_to_cpu(mlx4_en_stats->TOCT_prio_6) +
+ be64_to_cpu(mlx4_en_stats->TOCT_prio_7) +
+ be64_to_cpu(mlx4_en_stats->TOCT_novlan);
+ priv->pkstats.tx_multicast_packets = be64_to_cpu(mlx4_en_stats->TMCAST_prio_0) +
+ be64_to_cpu(mlx4_en_stats->TMCAST_prio_1) +
+ be64_to_cpu(mlx4_en_stats->TMCAST_prio_2) +
+ be64_to_cpu(mlx4_en_stats->TMCAST_prio_3) +
+ be64_to_cpu(mlx4_en_stats->TMCAST_prio_4) +
+ be64_to_cpu(mlx4_en_stats->TMCAST_prio_5) +
+ be64_to_cpu(mlx4_en_stats->TMCAST_prio_6) +
+ be64_to_cpu(mlx4_en_stats->TMCAST_prio_7) +
+ be64_to_cpu(mlx4_en_stats->TMCAST_novlan);
+ priv->pkstats.tx_broadcast_packets = be64_to_cpu(mlx4_en_stats->TBCAST_prio_0) +
+ be64_to_cpu(mlx4_en_stats->TBCAST_prio_1) +
+ be64_to_cpu(mlx4_en_stats->TBCAST_prio_2) +
+ be64_to_cpu(mlx4_en_stats->TBCAST_prio_3) +
+ be64_to_cpu(mlx4_en_stats->TBCAST_prio_4) +
+ be64_to_cpu(mlx4_en_stats->TBCAST_prio_5) +
+ be64_to_cpu(mlx4_en_stats->TBCAST_prio_6) +
+ be64_to_cpu(mlx4_en_stats->TBCAST_prio_7) +
+ be64_to_cpu(mlx4_en_stats->TBCAST_novlan);
+ priv->pkstats.tx_errors = be64_to_cpu(mlx4_en_stats->TGIANT_prio_0) +
+ be64_to_cpu(mlx4_en_stats->TGIANT_prio_1) +
+ be64_to_cpu(mlx4_en_stats->TGIANT_prio_2) +
+ be64_to_cpu(mlx4_en_stats->TGIANT_prio_3) +
+ be64_to_cpu(mlx4_en_stats->TGIANT_prio_4) +
+ be64_to_cpu(mlx4_en_stats->TGIANT_prio_5) +
+ be64_to_cpu(mlx4_en_stats->TGIANT_prio_6) +
+ be64_to_cpu(mlx4_en_stats->TGIANT_prio_7) +
+ be64_to_cpu(mlx4_en_stats->TGIANT_novlan);
+ priv->pkstats.tx_dropped = be32_to_cpu(mlx4_en_stats->TDROP) -
+ priv->pkstats.tx_errors;
+ priv->pkstats.tx_lt_64_bytes_packets = be64_to_cpu(mlx4_en_stats->T64_prio_0) +
+ be64_to_cpu(mlx4_en_stats->T64_prio_1) +
+ be64_to_cpu(mlx4_en_stats->T64_prio_2) +
+ be64_to_cpu(mlx4_en_stats->T64_prio_3) +
+ be64_to_cpu(mlx4_en_stats->T64_prio_4) +
+ be64_to_cpu(mlx4_en_stats->T64_prio_5) +
+ be64_to_cpu(mlx4_en_stats->T64_prio_6) +
+ be64_to_cpu(mlx4_en_stats->T64_prio_7) +
+ be64_to_cpu(mlx4_en_stats->T64_novlan);
+ priv->pkstats.tx_127_bytes_packets = be64_to_cpu(mlx4_en_stats->T127_prio_0) +
+ be64_to_cpu(mlx4_en_stats->T127_prio_1) +
+ be64_to_cpu(mlx4_en_stats->T127_prio_2) +
+ be64_to_cpu(mlx4_en_stats->T127_prio_3) +
+ be64_to_cpu(mlx4_en_stats->T127_prio_4) +
+ be64_to_cpu(mlx4_en_stats->T127_prio_5) +
+ be64_to_cpu(mlx4_en_stats->T127_prio_6) +
+ be64_to_cpu(mlx4_en_stats->T127_prio_7) +
+ be64_to_cpu(mlx4_en_stats->T127_novlan);
+ priv->pkstats.tx_255_bytes_packets = be64_to_cpu(mlx4_en_stats->T255_prio_0) +
+ be64_to_cpu(mlx4_en_stats->T255_prio_1) +
+ be64_to_cpu(mlx4_en_stats->T255_prio_2) +
+ be64_to_cpu(mlx4_en_stats->T255_prio_3) +
+ be64_to_cpu(mlx4_en_stats->T255_prio_4) +
+ be64_to_cpu(mlx4_en_stats->T255_prio_5) +
+ be64_to_cpu(mlx4_en_stats->T255_prio_6) +
+ be64_to_cpu(mlx4_en_stats->T255_prio_7) +
+ be64_to_cpu(mlx4_en_stats->T255_novlan);
+ priv->pkstats.tx_511_bytes_packets = be64_to_cpu(mlx4_en_stats->T511_prio_0) +
+ be64_to_cpu(mlx4_en_stats->T511_prio_1) +
+ be64_to_cpu(mlx4_en_stats->T511_prio_2) +
+ be64_to_cpu(mlx4_en_stats->T511_prio_3) +
+ be64_to_cpu(mlx4_en_stats->T511_prio_4) +
+ be64_to_cpu(mlx4_en_stats->T511_prio_5) +
+ be64_to_cpu(mlx4_en_stats->T511_prio_6) +
+ be64_to_cpu(mlx4_en_stats->T511_prio_7) +
+ be64_to_cpu(mlx4_en_stats->T511_novlan);
+ priv->pkstats.tx_1023_bytes_packets = be64_to_cpu(mlx4_en_stats->T1023_prio_0) +
+ be64_to_cpu(mlx4_en_stats->T1023_prio_1) +
+ be64_to_cpu(mlx4_en_stats->T1023_prio_2) +
+ be64_to_cpu(mlx4_en_stats->T1023_prio_3) +
+ be64_to_cpu(mlx4_en_stats->T1023_prio_4) +
+ be64_to_cpu(mlx4_en_stats->T1023_prio_5) +
+ be64_to_cpu(mlx4_en_stats->T1023_prio_6) +
+ be64_to_cpu(mlx4_en_stats->T1023_prio_7) +
+ be64_to_cpu(mlx4_en_stats->T1023_novlan);
+ priv->pkstats.tx_1518_bytes_packets = be64_to_cpu(mlx4_en_stats->T1518_prio_0) +
+ be64_to_cpu(mlx4_en_stats->T1518_prio_1) +
+ be64_to_cpu(mlx4_en_stats->T1518_prio_2) +
+ be64_to_cpu(mlx4_en_stats->T1518_prio_3) +
+ be64_to_cpu(mlx4_en_stats->T1518_prio_4) +
+ be64_to_cpu(mlx4_en_stats->T1518_prio_5) +
+ be64_to_cpu(mlx4_en_stats->T1518_prio_6) +
+ be64_to_cpu(mlx4_en_stats->T1518_prio_7) +
+ be64_to_cpu(mlx4_en_stats->T1518_novlan);
+ priv->pkstats.tx_1522_bytes_packets = be64_to_cpu(mlx4_en_stats->T1522_prio_0) +
+ be64_to_cpu(mlx4_en_stats->T1522_prio_1) +
+ be64_to_cpu(mlx4_en_stats->T1522_prio_2) +
+ be64_to_cpu(mlx4_en_stats->T1522_prio_3) +
+ be64_to_cpu(mlx4_en_stats->T1522_prio_4) +
+ be64_to_cpu(mlx4_en_stats->T1522_prio_5) +
+ be64_to_cpu(mlx4_en_stats->T1522_prio_6) +
+ be64_to_cpu(mlx4_en_stats->T1522_prio_7) +
+ be64_to_cpu(mlx4_en_stats->T1522_novlan);
+ priv->pkstats.tx_1548_bytes_packets = be64_to_cpu(mlx4_en_stats->T1548_prio_0) +
+ be64_to_cpu(mlx4_en_stats->T1548_prio_1) +
+ be64_to_cpu(mlx4_en_stats->T1548_prio_2) +
+ be64_to_cpu(mlx4_en_stats->T1548_prio_3) +
+ be64_to_cpu(mlx4_en_stats->T1548_prio_4) +
+ be64_to_cpu(mlx4_en_stats->T1548_prio_5) +
+ be64_to_cpu(mlx4_en_stats->T1548_prio_6) +
+ be64_to_cpu(mlx4_en_stats->T1548_prio_7) +
+ be64_to_cpu(mlx4_en_stats->T1548_novlan);
+ priv->pkstats.tx_gt_1548_bytes_packets = be64_to_cpu(mlx4_en_stats->T2MTU_prio_0) +
+ be64_to_cpu(mlx4_en_stats->T2MTU_prio_1) +
+ be64_to_cpu(mlx4_en_stats->T2MTU_prio_2) +
+ be64_to_cpu(mlx4_en_stats->T2MTU_prio_3) +
+ be64_to_cpu(mlx4_en_stats->T2MTU_prio_4) +
+ be64_to_cpu(mlx4_en_stats->T2MTU_prio_5) +
+ be64_to_cpu(mlx4_en_stats->T2MTU_prio_6) +
+ be64_to_cpu(mlx4_en_stats->T2MTU_prio_7) +
+ be64_to_cpu(mlx4_en_stats->T2MTU_novlan);
+
+ priv->pkstats.rx_prio[0][0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_0);
+ priv->pkstats.rx_prio[0][1] = be64_to_cpu(mlx4_en_stats->ROCT_prio_0);
+ priv->pkstats.rx_prio[1][0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_1);
+ priv->pkstats.rx_prio[1][1] = be64_to_cpu(mlx4_en_stats->ROCT_prio_1);
+ priv->pkstats.rx_prio[2][0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_2);
+ priv->pkstats.rx_prio[2][1] = be64_to_cpu(mlx4_en_stats->ROCT_prio_2);
+ priv->pkstats.rx_prio[3][0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_3);
+ priv->pkstats.rx_prio[3][1] = be64_to_cpu(mlx4_en_stats->ROCT_prio_3);
+ priv->pkstats.rx_prio[4][0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_4);
+ priv->pkstats.rx_prio[4][1] = be64_to_cpu(mlx4_en_stats->ROCT_prio_4);
+ priv->pkstats.rx_prio[5][0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_5);
+ priv->pkstats.rx_prio[5][1] = be64_to_cpu(mlx4_en_stats->ROCT_prio_5);
+ priv->pkstats.rx_prio[6][0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_6);
+ priv->pkstats.rx_prio[6][1] = be64_to_cpu(mlx4_en_stats->ROCT_prio_6);
+ priv->pkstats.rx_prio[7][0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_7);
+ priv->pkstats.rx_prio[7][1] = be64_to_cpu(mlx4_en_stats->ROCT_prio_7);
+ priv->pkstats.rx_prio[8][0] = be64_to_cpu(mlx4_en_stats->RTOT_novlan);
+ priv->pkstats.rx_prio[8][1] = be64_to_cpu(mlx4_en_stats->ROCT_novlan);
+ priv->pkstats.tx_prio[0][0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_0);
+ priv->pkstats.tx_prio[0][1] = be64_to_cpu(mlx4_en_stats->TOCT_prio_0);
+ priv->pkstats.tx_prio[1][0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_1);
+ priv->pkstats.tx_prio[1][1] = be64_to_cpu(mlx4_en_stats->TOCT_prio_1);
+ priv->pkstats.tx_prio[2][0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_2);
+ priv->pkstats.tx_prio[2][1] = be64_to_cpu(mlx4_en_stats->TOCT_prio_2);
+ priv->pkstats.tx_prio[3][0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_3);
+ priv->pkstats.tx_prio[3][1] = be64_to_cpu(mlx4_en_stats->TOCT_prio_3);
+ priv->pkstats.tx_prio[4][0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_4);
+ priv->pkstats.tx_prio[4][1] = be64_to_cpu(mlx4_en_stats->TOCT_prio_4);
+ priv->pkstats.tx_prio[5][0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_5);
+ priv->pkstats.tx_prio[5][1] = be64_to_cpu(mlx4_en_stats->TOCT_prio_5);
+ priv->pkstats.tx_prio[6][0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_6);
+ priv->pkstats.tx_prio[6][1] = be64_to_cpu(mlx4_en_stats->TOCT_prio_6);
+ priv->pkstats.tx_prio[7][0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_7);
+ priv->pkstats.tx_prio[7][1] = be64_to_cpu(mlx4_en_stats->TOCT_prio_7);
+ priv->pkstats.tx_prio[8][0] = be64_to_cpu(mlx4_en_stats->TTOT_novlan);
+ priv->pkstats.tx_prio[8][1] = be64_to_cpu(mlx4_en_stats->TOCT_novlan);
+
+ flowstats = mailbox_flow->buf;
+
+ for (i = 0; i < MLX4_NUM_PRIORITIES; i++) {
+ priv->flowstats[i].rx_pause =
+ be64_to_cpu(flowstats[i].rx_pause);
+ priv->flowstats[i].rx_pause_duration =
+ be64_to_cpu(flowstats[i].rx_pause_duration);
+ priv->flowstats[i].rx_pause_transition =
+ be64_to_cpu(flowstats[i].rx_pause_transition);
+ priv->flowstats[i].tx_pause =
+ be64_to_cpu(flowstats[i].tx_pause);
+ priv->flowstats[i].tx_pause_duration =
+ be64_to_cpu(flowstats[i].tx_pause_duration);
+ priv->flowstats[i].tx_pause_transition =
+ be64_to_cpu(flowstats[i].tx_pause_transition);
+ }
+
+ memset(&tmp_vport_stats, 0, sizeof(tmp_vport_stats));
+ spin_unlock(&priv->stats_lock);
+ err = mlx4_get_vport_ethtool_stats(mdev->dev, port,
+ &tmp_vport_stats, reset);
+ spin_lock(&priv->stats_lock);
+ if (!err) {
+ /* ethtool stats format */
+ vport_stats->rx_unicast_packets = tmp_vport_stats.rx_unicast_packets;
+ vport_stats->rx_unicast_bytes = tmp_vport_stats.rx_unicast_bytes;
+ vport_stats->rx_multicast_packets = tmp_vport_stats.rx_multicast_packets;
+ vport_stats->rx_multicast_bytes = tmp_vport_stats.rx_multicast_bytes;
+ vport_stats->rx_broadcast_packets = tmp_vport_stats.rx_broadcast_packets;
+ vport_stats->rx_broadcast_bytes = tmp_vport_stats.rx_broadcast_bytes;
+ vport_stats->rx_dropped = tmp_vport_stats.rx_dropped;
+ vport_stats->rx_errors = tmp_vport_stats.rx_errors;
+ vport_stats->tx_unicast_packets = tmp_vport_stats.tx_unicast_packets;
+ vport_stats->tx_unicast_bytes = tmp_vport_stats.tx_unicast_bytes;
+ vport_stats->tx_multicast_packets = tmp_vport_stats.tx_multicast_packets;
+ vport_stats->tx_multicast_bytes = tmp_vport_stats.tx_multicast_bytes;
+ vport_stats->tx_broadcast_packets = tmp_vport_stats.tx_broadcast_packets;
+ vport_stats->tx_broadcast_bytes = tmp_vport_stats.tx_broadcast_bytes;
+ vport_stats->tx_errors = tmp_vport_stats.tx_errors;
+ }
+
+ if (!mlx4_is_mfunc(mdev->dev)) {
+ if (reset == 0) {
+ /* netdevice stats format */
+ dev = mdev->pndev[port];
+ if_inc_counter(dev, IFCOUNTER_IPACKETS,
+ priv->pkstats.rx_packets - priv->pkstats_last.rx_packets);
+ if_inc_counter(dev, IFCOUNTER_OPACKETS,
+ priv->pkstats.tx_packets - priv->pkstats_last.tx_packets);
+ if_inc_counter(dev, IFCOUNTER_IBYTES,
+ priv->pkstats.rx_bytes - priv->pkstats_last.rx_bytes);
+ if_inc_counter(dev, IFCOUNTER_OBYTES,
+ priv->pkstats.tx_bytes - priv->pkstats_last.tx_bytes);
+ if_inc_counter(dev, IFCOUNTER_IERRORS,
+ priv->pkstats.rx_errors - priv->pkstats_last.rx_errors);
+ if_inc_counter(dev, IFCOUNTER_IQDROPS,
+ priv->pkstats.rx_dropped - priv->pkstats_last.rx_dropped);
+ if_inc_counter(dev, IFCOUNTER_IMCASTS,
+ priv->pkstats.rx_multicast_packets - priv->pkstats_last.rx_multicast_packets);
+ if_inc_counter(dev, IFCOUNTER_OMCASTS,
+ priv->pkstats.tx_multicast_packets - priv->pkstats_last.tx_multicast_packets);
+ }
+ priv->pkstats_last = priv->pkstats;
}
- dev->if_ierrors = be32_to_cpu(mlx4_en_stats->RDROP) + ierror;
- dev->if_oerrors = be32_to_cpu(mlx4_en_stats->TDROP) + oerror;
- dev->if_imcasts = be64_to_cpu(mlx4_en_stats->MCAST_prio_0) +
- be64_to_cpu(mlx4_en_stats->MCAST_prio_1) +
- be64_to_cpu(mlx4_en_stats->MCAST_prio_2) +
- be64_to_cpu(mlx4_en_stats->MCAST_prio_3) +
- be64_to_cpu(mlx4_en_stats->MCAST_prio_4) +
- be64_to_cpu(mlx4_en_stats->MCAST_prio_5) +
- be64_to_cpu(mlx4_en_stats->MCAST_prio_6) +
- be64_to_cpu(mlx4_en_stats->MCAST_prio_7) +
- be64_to_cpu(mlx4_en_stats->MCAST_novlan);
- dev->if_omcasts = be64_to_cpu(mlx4_en_stats->TMCAST_prio_0) +
- be64_to_cpu(mlx4_en_stats->TMCAST_prio_1) +
- be64_to_cpu(mlx4_en_stats->TMCAST_prio_2) +
- be64_to_cpu(mlx4_en_stats->TMCAST_prio_3) +
- be64_to_cpu(mlx4_en_stats->TMCAST_prio_4) +
- be64_to_cpu(mlx4_en_stats->TMCAST_prio_5) +
- be64_to_cpu(mlx4_en_stats->TMCAST_prio_6) +
- be64_to_cpu(mlx4_en_stats->TMCAST_prio_7) +
- be64_to_cpu(mlx4_en_stats->TMCAST_novlan);
- dev->if_collisions = 0;
-
- priv->pkstats.broadcast =
- be64_to_cpu(mlx4_en_stats->RBCAST_prio_0) +
- be64_to_cpu(mlx4_en_stats->RBCAST_prio_1) +
- be64_to_cpu(mlx4_en_stats->RBCAST_prio_2) +
- be64_to_cpu(mlx4_en_stats->RBCAST_prio_3) +
- be64_to_cpu(mlx4_en_stats->RBCAST_prio_4) +
- be64_to_cpu(mlx4_en_stats->RBCAST_prio_5) +
- be64_to_cpu(mlx4_en_stats->RBCAST_prio_6) +
- be64_to_cpu(mlx4_en_stats->RBCAST_prio_7) +
- be64_to_cpu(mlx4_en_stats->RBCAST_novlan);
- priv->pkstats.rx_prio[0] = be64_to_cpu(mlx4_en_stats->RTOT_prio_0);
- priv->pkstats.rx_prio[1] = be64_to_cpu(mlx4_en_stats->RTOT_prio_1);
- priv->pkstats.rx_prio[2] = be64_to_cpu(mlx4_en_stats->RTOT_prio_2);
- priv->pkstats.rx_prio[3] = be64_to_cpu(mlx4_en_stats->RTOT_prio_3);
- priv->pkstats.rx_prio[4] = be64_to_cpu(mlx4_en_stats->RTOT_prio_4);
- priv->pkstats.rx_prio[5] = be64_to_cpu(mlx4_en_stats->RTOT_prio_5);
- priv->pkstats.rx_prio[6] = be64_to_cpu(mlx4_en_stats->RTOT_prio_6);
- priv->pkstats.rx_prio[7] = be64_to_cpu(mlx4_en_stats->RTOT_prio_7);
- priv->pkstats.tx_prio[0] = be64_to_cpu(mlx4_en_stats->TTOT_prio_0);
- priv->pkstats.tx_prio[1] = be64_to_cpu(mlx4_en_stats->TTOT_prio_1);
- priv->pkstats.tx_prio[2] = be64_to_cpu(mlx4_en_stats->TTOT_prio_2);
- priv->pkstats.tx_prio[3] = be64_to_cpu(mlx4_en_stats->TTOT_prio_3);
- priv->pkstats.tx_prio[4] = be64_to_cpu(mlx4_en_stats->TTOT_prio_4);
- priv->pkstats.tx_prio[5] = be64_to_cpu(mlx4_en_stats->TTOT_prio_5);
- priv->pkstats.tx_prio[6] = be64_to_cpu(mlx4_en_stats->TTOT_prio_6);
- priv->pkstats.tx_prio[7] = be64_to_cpu(mlx4_en_stats->TTOT_prio_7);
spin_unlock(&priv->stats_lock);
out:
+ mlx4_free_cmd_mailbox(mdev->dev, mailbox_flow);
mlx4_free_cmd_mailbox(mdev->dev, mailbox);
+
+mailbox_out:
+ if (do_if_stat)
+ priv->last_ifq_jiffies = jiffies;
+
return err;
}
-
diff --git a/sys/ofed/drivers/net/mlx4/en_port.h b/sys/ofed/drivers/net/mlx4/en_port.h
index 5319814..6301717 100644
--- a/sys/ofed/drivers/net/mlx4/en_port.h
+++ b/sys/ofed/drivers/net/mlx4/en_port.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2007, 2014 Mellanox Technologies. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -36,39 +36,10 @@
#define SET_PORT_GEN_ALL_VALID 0x7
-#define SET_PORT_PROMISC_EN_SHIFT 31
-#define SET_PORT_PROMISC_MODE_SHIFT 30
+#define SET_PORT_PROMISC_SHIFT 31
+#define SET_PORT_MC_PROMISC_SHIFT 30
-#if 0 //moved to port.c - shahark
-
-struct mlx4_set_port_general_context {
- u8 reserved[3];
- u8 flags;
- u16 reserved2;
- __be16 mtu;
- u8 pptx;
- u8 pfctx;
- u16 reserved3;
- u8 pprx;
- u8 pfcrx;
- u16 reserved4;
-};
-
-struct mlx4_set_port_rqp_calc_context {
- __be32 base_qpn;
- __be32 flags;
- u8 reserved[3];
- u8 mac_miss;
- u8 intra_no_vlan;
- u8 no_vlan;
- u8 intra_vlan_miss;
- u8 vlan_miss;
- u8 reserved2[3];
- u8 no_vlan_prio;
- __be32 promisc;
- __be32 mcast;
-};
-#endif
+#define MLX4_EN_NUM_TC 8
#define VLAN_FLTR_SIZE 128
struct mlx4_set_vlan_fltr_mbox {
@@ -83,29 +54,27 @@ enum {
};
enum {
- MLX4_EN_1G_SPEED = 0x02,
- MLX4_EN_10G_SPEED_XFI = 0x01,
MLX4_EN_10G_SPEED_XAUI = 0x00,
+ MLX4_EN_10G_SPEED_XFI = 0x01,
+ MLX4_EN_1G_SPEED = 0x02,
+ MLX4_EN_20G_SPEED = 0x08,
MLX4_EN_40G_SPEED = 0x40,
+ MLX4_EN_56G_SPEED = 0x20,
MLX4_EN_OTHER_SPEED = 0x0f,
};
struct mlx4_en_query_port_context {
u8 link_up;
#define MLX4_EN_LINK_UP_MASK 0x80
- u8 reserved;
+ u8 autoneg;
+#define MLX4_EN_AUTONEG_MASK 0x80
__be16 mtu;
u8 reserved2;
u8 link_speed;
-#define MLX4_EN_SPEED_MASK 0x43
+#define MLX4_EN_SPEED_MASK 0x6b
u16 reserved3[5];
__be64 mac;
u8 transceiver;
- u8 reserved4[3];
- __be32 wavelenth;
- u32 reserved5;
- __be32 transceiver_code_hi;
- __be32 transceiver_code_low;
};
@@ -590,6 +559,5 @@ struct mlx4_en_stat_out_mbox {
__be32 TDROP;
};
-enum mlx4_query_reply mlx4_en_query(void *endev_ptr, void *int_dev);
#endif
diff --git a/sys/ofed/drivers/net/mlx4/en_resources.c b/sys/ofed/drivers/net/mlx4/en_resources.c
index a147153..669ecbd 100644
--- a/sys/ofed/drivers/net/mlx4/en_resources.c
+++ b/sys/ofed/drivers/net/mlx4/en_resources.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2007, 2014 Mellanox Technologies. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -31,24 +31,26 @@
*
*/
+#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/mlx4/qp.h>
#include "mlx4_en.h"
+
void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
int is_tx, int rss, int qpn, int cqn,
- struct mlx4_qp_context *context)
+ int user_prio, struct mlx4_qp_context *context)
{
struct mlx4_en_dev *mdev = priv->mdev;
+ struct net_device *dev = priv->dev;
memset(context, 0, sizeof *context);
- context->flags = cpu_to_be32(7 << 16 | rss << 13);
+ context->flags = cpu_to_be32(7 << 16 | rss << MLX4_RSS_QPC_FLAG_OFFSET);
context->pd = cpu_to_be32(mdev->priv_pdn);
context->mtu_msgmax = 0xff;
- if (!is_tx && !rss) {
+ if (!is_tx && !rss)
context->rq_size_stride = ilog2(size) << 3 | (ilog2(stride) - 4);
- }
if (is_tx)
context->sq_size_stride = ilog2(size) << 3 | (ilog2(stride) - 4);
else
@@ -57,10 +59,25 @@ void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
context->local_qpn = cpu_to_be32(qpn);
context->pri_path.ackto = 1 & 0x07;
context->pri_path.sched_queue = 0x83 | (priv->port - 1) << 6;
- context->pri_path.counter_index = 0xff;
+ if (user_prio >= 0) {
+ context->pri_path.sched_queue |= user_prio << 3;
+ context->pri_path.feup = 1 << 6;
+ }
+ context->pri_path.counter_index = (u8)(priv->counter_index);
+ if (!rss &&
+ (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_LB_SRC_CHK) &&
+ context->pri_path.counter_index != 0xFF) {
+ /* disable multicast loopback to qp with same counter */
+ context->pri_path.fl |= MLX4_FL_ETH_SRC_CHECK_MC_LB;
+ context->pri_path.vlan_control |=
+ MLX4_VLAN_CTRL_ETH_SRC_CHECK_IF_COUNTER;
+ }
+
context->cqn_send = cpu_to_be32(cqn);
context->cqn_recv = cpu_to_be32(cqn);
context->db_rec_addr = cpu_to_be64(priv->res.db.dma << 2);
+ if (!(dev->if_capabilities & IFCAP_VLAN_HWCSUM))
+ context->param3 |= cpu_to_be32(1 << 30);
}
@@ -69,6 +86,8 @@ int mlx4_en_map_buffer(struct mlx4_buf *buf)
struct page **pages;
int i;
+ // if nbufs == 1 - there is no need to vmap
+ // if buf->direct.buf is not NULL it means that vmap was already done by mlx4_alloc_buff
if (buf->direct.buf != NULL || buf->nbufs == 1)
return 0;
@@ -89,11 +108,10 @@ int mlx4_en_map_buffer(struct mlx4_buf *buf)
void mlx4_en_unmap_buffer(struct mlx4_buf *buf)
{
- if (buf->direct.buf != NULL || buf->nbufs == 1)
+ if (BITS_PER_LONG == 64 || buf->nbufs == 1)
return;
vunmap(buf->direct.buf);
- buf->direct.buf = NULL;
}
void mlx4_en_sqp_event(struct mlx4_qp *qp, enum mlx4_event event)
diff --git a/sys/ofed/drivers/net/mlx4/en_rx.c b/sys/ofed/drivers/net/mlx4/en_rx.c
index ca46721..320462e 100644
--- a/sys/ofed/drivers/net/mlx4/en_rx.c
+++ b/sys/ofed/drivers/net/mlx4/en_rx.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2007, 2014 Mellanox Technologies. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -30,20 +30,48 @@
* SOFTWARE.
*
*/
-
#include "opt_inet.h"
-#include "mlx4_en.h"
-
#include <linux/mlx4/cq.h>
+#include <linux/slab.h>
#include <linux/mlx4/qp.h>
+#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
+#include <linux/vmalloc.h>
+#include <linux/mlx4/driver.h>
+#ifdef CONFIG_NET_RX_BUSY_POLL
+#include <net/busy_poll.h>
+#endif
-#include <net/ethernet.h>
-#include <net/if_vlan_var.h>
-#include <sys/mbuf.h>
+#include "mlx4_en.h"
-enum {
- MIN_RX_ARM = 1024,
-};
+
+static void mlx4_en_init_rx_desc(struct mlx4_en_priv *priv,
+ struct mlx4_en_rx_ring *ring,
+ int index)
+{
+ struct mlx4_en_rx_desc *rx_desc = ring->buf + ring->stride * index;
+ int possible_frags;
+ int i;
+
+
+ /* Set size and memtype fields */
+ for (i = 0; i < priv->num_frags; i++) {
+ rx_desc->data[i].byte_count =
+ cpu_to_be32(priv->frag_info[i].frag_size);
+ rx_desc->data[i].lkey = cpu_to_be32(priv->mdev->mr.key);
+ }
+
+ /* If the number of used fragments does not fill up the ring stride,
+ * * remaining (unused) fragments must be padded with null address/size
+ * * and a special memory key */
+ possible_frags = (ring->stride - sizeof(struct mlx4_en_rx_desc)) / DS_SIZE;
+ for (i = priv->num_frags; i < possible_frags; i++) {
+ rx_desc->data[i].byte_count = 0;
+ rx_desc->data[i].lkey = cpu_to_be32(MLX4_EN_MEMTYPE_PAD);
+ rx_desc->data[i].addr = 0;
+ }
+
+}
static int mlx4_en_alloc_buf(struct mlx4_en_priv *priv,
struct mlx4_en_rx_desc *rx_desc,
@@ -70,48 +98,24 @@ static int mlx4_en_alloc_buf(struct mlx4_en_priv *priv,
return 0;
}
-static void mlx4_en_init_rx_desc(struct mlx4_en_priv *priv,
- struct mlx4_en_rx_ring *ring, int index)
-{
- struct mlx4_en_rx_desc *rx_desc = ring->buf + ring->stride * index;
- int possible_frags;
- int i;
-
- /* Set size and memtype fields */
- for (i = 0; i < priv->num_frags; i++) {
- rx_desc->data[i].byte_count =
- cpu_to_be32(priv->frag_info[i].frag_size);
- rx_desc->data[i].lkey = cpu_to_be32(priv->mdev->mr.key);
- }
-
- /* If the number of used fragments does not fill up the ring stride,
- * remaining (unused) fragments must be padded with null address/size
- * and a special memory key */
- possible_frags = (ring->stride - sizeof(struct mlx4_en_rx_desc)) / DS_SIZE;
- for (i = priv->num_frags; i < possible_frags; i++) {
- rx_desc->data[i].byte_count = 0;
- rx_desc->data[i].lkey = cpu_to_be32(MLX4_EN_MEMTYPE_PAD);
- rx_desc->data[i].addr = 0;
- }
-}
static int mlx4_en_prepare_rx_desc(struct mlx4_en_priv *priv,
- struct mlx4_en_rx_ring *ring, int index)
+ struct mlx4_en_rx_ring *ring, int index)
{
- struct mlx4_en_rx_desc *rx_desc = ring->buf + (index * ring->stride);
- struct mbuf **mb_list = ring->rx_info + (index << priv->log_rx_info);
- int i;
+ struct mlx4_en_rx_desc *rx_desc = ring->buf + (index * ring->stride);
+ struct mbuf **mb_list = ring->rx_info + (index << priv->log_rx_info);
+ int i;
- for (i = 0; i < priv->num_frags; i++)
- if (mlx4_en_alloc_buf(priv, rx_desc, mb_list, i))
- goto err;
+ for (i = 0; i < priv->num_frags; i++)
+ if (mlx4_en_alloc_buf(priv, rx_desc, mb_list, i))
+ goto err;
- return 0;
+ return 0;
err:
- while (i--)
- m_free(mb_list[i]);
- return -ENOMEM;
+ while (i--)
+ m_free(mb_list[i]);
+ return -ENOMEM;
}
static inline void mlx4_en_update_rx_prod_db(struct mlx4_en_rx_ring *ring)
@@ -136,7 +140,11 @@ static void mlx4_en_free_rx_desc(struct mlx4_en_priv *priv,
frag_info = &priv->frag_info[nr];
dma = be64_to_cpu(rx_desc->data[nr].addr);
- en_dbg(DRV, priv, "Unmaping buffer at dma:0x%llx\n", (long long) dma);
+#if BITS_PER_LONG == 64
+ en_dbg(DRV, priv, "Unmaping buffer at dma:0x%lx\n", (u64) dma);
+#elif BITS_PER_LONG == 32
+ en_dbg(DRV, priv, "Unmaping buffer at dma:0x%llx\n", (u64) dma);
+#endif
pci_unmap_single(mdev->pdev, dma, frag_info->frag_size,
PCI_DMA_FROMDEVICE);
m_free(mb_list[nr]);
@@ -153,7 +161,7 @@ static int mlx4_en_fill_rx_buffers(struct mlx4_en_priv *priv)
for (buf_ind = 0; buf_ind < priv->prof->rx_ring_size; buf_ind++) {
for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) {
- ring = &priv->rx_ring[ring_ind];
+ ring = priv->rx_ring[ring_ind];
err = mlx4_en_prepare_rx_desc(priv, ring,
ring->actual_size);
@@ -163,7 +171,8 @@ static int mlx4_en_fill_rx_buffers(struct mlx4_en_priv *priv)
"enough rx buffers\n");
return -ENOMEM;
} else {
- new_size = rounddown_pow_of_two(ring->actual_size);
+ new_size =
+ rounddown_pow_of_two(ring->actual_size);
en_warn(priv, "Only %d buffers allocated "
"reducing ring size to %d\n",
ring->actual_size, new_size);
@@ -178,7 +187,7 @@ static int mlx4_en_fill_rx_buffers(struct mlx4_en_priv *priv)
reduce_rings:
for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) {
- ring = &priv->rx_ring[ring_ind];
+ ring = priv->rx_ring[ring_ind];
while (ring->actual_size > new_size) {
ring->actual_size--;
ring->prod--;
@@ -207,39 +216,95 @@ static void mlx4_en_free_rx_buf(struct mlx4_en_priv *priv,
}
}
+#if MLX4_EN_MAX_RX_FRAGS == 3
+static int frag_sizes[] = {
+ FRAG_SZ0,
+ FRAG_SZ1,
+ FRAG_SZ2,
+};
+#elif MLX4_EN_MAX_RX_FRAGS == 2
+static int frag_sizes[] = {
+ FRAG_SZ0,
+ FRAG_SZ1,
+};
+#else
+#error "Unknown MAX_RX_FRAGS"
+#endif
+
+void mlx4_en_calc_rx_buf(struct net_device *dev)
+{
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ int eff_mtu = dev->if_mtu + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN;
+ int buf_size = 0;
+ int i, frag;
+
+ for (i = 0, frag = 0; buf_size < eff_mtu; frag++, i++) {
+ /*
+ * Allocate small to large but only as much as is needed for
+ * the tail.
+ */
+ while (i > 0 && eff_mtu - buf_size <= frag_sizes[i - 1])
+ i--;
+ priv->frag_info[frag].frag_size = frag_sizes[i];
+ priv->frag_info[frag].frag_prefix_size = buf_size;
+ buf_size += priv->frag_info[frag].frag_size;
+ }
+
+ priv->num_frags = frag;
+ priv->rx_mb_size = eff_mtu;
+ priv->log_rx_info =
+ ROUNDUP_LOG2(priv->num_frags * sizeof(struct mbuf *));
+
+ en_dbg(DRV, priv, "Rx buffer scatter-list (effective-mtu:%d "
+ "num_frags:%d):\n", eff_mtu, priv->num_frags);
+ for (i = 0; i < priv->num_frags; i++) {
+ en_dbg(DRV, priv, " frag:%d - size:%d prefix:%d\n", i,
+ priv->frag_info[i].frag_size,
+ priv->frag_info[i].frag_prefix_size);
+ }
+}
+
int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
- struct mlx4_en_rx_ring *ring, u32 size)
+ struct mlx4_en_rx_ring **pring,
+ u32 size, int node)
{
struct mlx4_en_dev *mdev = priv->mdev;
- int err;
+ struct mlx4_en_rx_ring *ring;
+ int err = -ENOMEM;
int tmp;
-
+ ring = kzalloc(sizeof(struct mlx4_en_rx_ring), GFP_KERNEL);
+ if (!ring) {
+ en_err(priv, "Failed to allocate RX ring structure\n");
+ return -ENOMEM;
+ }
+
ring->prod = 0;
ring->cons = 0;
ring->size = size;
ring->size_mask = size - 1;
ring->stride = roundup_pow_of_two(sizeof(struct mlx4_en_rx_desc) +
- DS_SIZE * MLX4_EN_MAX_RX_FRAGS);
+ DS_SIZE * MLX4_EN_MAX_RX_FRAGS);
ring->log_stride = ffs(ring->stride) - 1;
ring->buf_size = ring->size * ring->stride + TXBB_SIZE;
tmp = size * roundup_pow_of_two(MLX4_EN_MAX_RX_FRAGS *
- sizeof(struct mbuf *));
+ sizeof(struct mbuf *));
- ring->rx_info = kmalloc(tmp, GFP_KERNEL);
- if (!ring->rx_info) {
- en_err(priv, "Failed allocating rx_info ring\n");
- return -ENOMEM;
- }
- en_dbg(DRV, priv, "Allocated rx_info ring at addr:%p size:%d stride:%d (%d)\n",
- ring->rx_info, tmp, ring->stride, ring->log_stride);
+ ring->rx_info = kmalloc(tmp, GFP_KERNEL);
+ if (!ring->rx_info) {
+ err = -ENOMEM;
+ goto err_ring;
+ }
+
+ en_dbg(DRV, priv, "Allocated rx_info ring at addr:%p size:%d\n",
+ ring->rx_info, tmp);
err = mlx4_alloc_hwq_res(mdev->dev, &ring->wqres,
ring->buf_size, 2 * PAGE_SIZE);
if (err)
- goto err_ring;
+ goto err_info;
err = mlx4_en_map_buffer(&ring->wqres.buf);
if (err) {
@@ -247,18 +312,20 @@ int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
goto err_hwq;
}
ring->buf = ring->wqres.buf.direct.buf;
-
+ *pring = ring;
return 0;
- mlx4_en_unmap_buffer(&ring->wqres.buf);
err_hwq:
mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size);
+err_info:
+ vfree(ring->rx_info);
err_ring:
- kfree(ring->rx_info);
- ring->rx_info = NULL;
+ kfree(ring);
+
return err;
}
+
int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv)
{
struct mlx4_en_rx_ring *ring;
@@ -266,14 +333,20 @@ int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv)
int ring_ind;
int err;
int stride = roundup_pow_of_two(sizeof(struct mlx4_en_rx_desc) +
- DS_SIZE * priv->num_frags);
+ DS_SIZE * priv->num_frags);
+
for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) {
- ring = &priv->rx_ring[ring_ind];
+ ring = priv->rx_ring[ring_ind];
ring->prod = 0;
ring->cons = 0;
ring->actual_size = 0;
- ring->cqn = priv->rx_cq[ring_ind].mcq.cqn;
+ ring->cqn = priv->rx_cq[ring_ind]->mcq.cqn;
+ ring->rx_alloc_order = priv->rx_alloc_order;
+ ring->rx_alloc_size = priv->rx_alloc_size;
+ ring->rx_buf_size = priv->rx_buf_size;
+ ring->rx_mb_size = priv->rx_mb_size;
+
ring->stride = stride;
if (ring->stride <= TXBB_SIZE)
ring->buf += TXBB_SIZE;
@@ -284,9 +357,10 @@ int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv)
memset(ring->buf, 0, ring->buf_size);
mlx4_en_update_rx_prod_db(ring);
- /* Initailize all descriptors */
+ /* Initialize all descriptors */
for (i = 0; i < ring->size; i++)
mlx4_en_init_rx_desc(priv, ring, i);
+
#ifdef INET
/* Configure lro mngr */
if (priv->dev->if_capenable & IFCAP_LRO) {
@@ -297,38 +371,56 @@ int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv)
}
#endif
}
+
+
err = mlx4_en_fill_rx_buffers(priv);
if (err)
goto err_buffers;
for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) {
- ring = &priv->rx_ring[ring_ind];
+ ring = priv->rx_ring[ring_ind];
ring->size_mask = ring->actual_size - 1;
mlx4_en_update_rx_prod_db(ring);
}
-
return 0;
err_buffers:
for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++)
- mlx4_en_free_rx_buf(priv, &priv->rx_ring[ring_ind]);
+ mlx4_en_free_rx_buf(priv, priv->rx_ring[ring_ind]);
+
+ ring_ind = priv->rx_ring_num - 1;
+
+ while (ring_ind >= 0) {
+ ring = priv->rx_ring[ring_ind];
+ if (ring->stride <= TXBB_SIZE)
+ ring->buf -= TXBB_SIZE;
+ ring_ind--;
+ }
return err;
}
+
void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv,
- struct mlx4_en_rx_ring *ring)
+ struct mlx4_en_rx_ring **pring,
+ u32 size, u16 stride)
{
struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_en_rx_ring *ring = *pring;
mlx4_en_unmap_buffer(&ring->wqres.buf);
- mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size + TXBB_SIZE);
- kfree(ring->rx_info);
- ring->rx_info = NULL;
+ mlx4_free_hwq_res(mdev->dev, &ring->wqres, size * stride + TXBB_SIZE);
+ vfree(ring->rx_info);
+ kfree(ring);
+ *pring = NULL;
+#ifdef CONFIG_RFS_ACCEL
+ mlx4_en_cleanup_filters(priv, ring);
+#endif
}
+
void mlx4_en_deactivate_rx_ring(struct mlx4_en_priv *priv,
struct mlx4_en_rx_ring *ring)
{
@@ -341,6 +433,43 @@ void mlx4_en_deactivate_rx_ring(struct mlx4_en_priv *priv,
}
+static void validate_loopback(struct mlx4_en_priv *priv, struct mbuf *mb)
+{
+ int i;
+ int offset = ETHER_HDR_LEN;
+
+ for (i = 0; i < MLX4_LOOPBACK_TEST_PAYLOAD; i++, offset++) {
+ if (*(mb->m_data + offset) != (unsigned char) (i & 0xff))
+ goto out_loopback;
+ }
+ /* Loopback found */
+ priv->loopback_ok = 1;
+
+out_loopback:
+ m_freem(mb);
+}
+
+
+static inline int invalid_cqe(struct mlx4_en_priv *priv,
+ struct mlx4_cqe *cqe)
+{
+ /* Drop packet on bad receive or bad checksum */
+ if (unlikely((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) ==
+ MLX4_CQE_OPCODE_ERROR)) {
+ en_err(priv, "CQE completed in error - vendor syndrom:%d syndrom:%d\n",
+ ((struct mlx4_err_cqe *)cqe)->vendor_err_syndrome,
+ ((struct mlx4_err_cqe *)cqe)->syndrome);
+ return 1;
+ }
+ if (unlikely(cqe->badfcs_enc & MLX4_CQE_BAD_FCS)) {
+ en_dbg(RX_ERR, priv, "Accepted frame with bad FCS\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+
/* Unmap a completed descriptor and free unused pages */
static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv,
struct mlx4_en_rx_desc *rx_desc,
@@ -360,15 +489,15 @@ static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv,
frag_info = &priv->frag_info[nr];
if (length <= frag_info->frag_prefix_size)
break;
- if (nr)
+ if (nr)
mb->m_next = mb_list[nr];
mb = mb_list[nr];
mb->m_len = frag_info[nr].frag_size;
dma = be64_to_cpu(rx_desc->data[nr].addr);
- /* Allocate a replacement page */
- if (mlx4_en_alloc_buf(priv, rx_desc, mb_list, nr))
- goto fail;
+ /* Allocate a replacement page */
+ if (mlx4_en_alloc_buf(priv, rx_desc, mb_list, nr))
+ goto fail;
/* Unmap buffer */
pci_unmap_single(mdev->pdev, dma, frag_info[nr].frag_size,
@@ -380,50 +509,14 @@ static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv,
return 0;
fail:
- /* Drop all accumulated fragments (which have already been replaced in
- * the descriptor) of this packet; remaining fragments are reused... */
- while (nr > 0) {
- nr--;
- m_free(mb_list[nr]);
- }
- return -ENOMEM;
-}
-
-
-static inline int invalid_cqe(struct mlx4_en_priv *priv,
- struct mlx4_cqe *cqe)
-{
- /* Drop packet on bad receive or bad checksum */
- if (unlikely((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) ==
- MLX4_CQE_OPCODE_ERROR)) {
- en_err(priv, "CQE completed in error - vendor "
- "syndrom:%d syndrom:%d\n",
- ((struct mlx4_err_cqe *) cqe)->vendor_err_syndrome,
- ((struct mlx4_err_cqe *) cqe)->syndrome);
- return 1;
- }
- if (unlikely(cqe->badfcs_enc & MLX4_CQE_BAD_FCS)) {
- en_dbg(RX_ERR, priv, "Accepted frame with bad FCS\n");
- return 1;
- }
-
- return 0;
-}
+ /* Drop all accumulated fragments (which have already been replaced in
+ * the descriptor) of this packet; remaining fragments are reused... */
+ while (nr > 0) {
+ nr--;
+ m_free(mb_list[nr]);
+ }
+ return -ENOMEM;
-static void validate_loopback(struct mlx4_en_priv *priv, struct mbuf *mb)
-{
- int i;
- int offset = ETHER_HDR_LEN;
-
- for (i = 0; i < MLX4_LOOPBACK_TEST_PAYLOAD; i++, offset++) {
- if (*(mb->m_data + offset) != (unsigned char) (i & 0xff))
- goto out_loopback;
- }
- /* Loopback found */
- priv->loopback_ok = 1;
-
-out_loopback:
- m_freem(mb);
}
static struct mbuf *mlx4_en_rx_mb(struct mlx4_en_priv *priv,
@@ -441,35 +534,45 @@ static struct mbuf *mlx4_en_rx_mb(struct mlx4_en_priv *priv,
return mb;
}
-
+/* For cpu arch with cache line of 64B the performance is better when cqe size==64B
+ * To enlarge cqe size from 32B to 64B --> 32B of garbage (i.e. 0xccccccc)
+ * was added in the beginning of each cqe (the real data is in the corresponding 32B).
+ * The following calc ensures that when factor==1, it means we are alligned to 64B
+ * and we get the real cqe data*/
+#define CQE_FACTOR_INDEX(index, factor) ((index << factor) + factor)
int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int budget)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
struct mlx4_cqe *cqe;
- struct mlx4_en_rx_ring *ring = &priv->rx_ring[cq->ring];
+ struct mlx4_en_rx_ring *ring = priv->rx_ring[cq->ring];
struct mbuf **mb_list;
struct mlx4_en_rx_desc *rx_desc;
struct mbuf *mb;
+ struct mlx4_cq *mcq = &cq->mcq;
+ struct mlx4_cqe *buf = cq->buf;
#ifdef INET
struct lro_entry *queued;
#endif
int index;
unsigned int length;
int polled = 0;
+ u32 cons_index = mcq->cons_index;
+ u32 size_mask = ring->size_mask;
+ int size = cq->size;
+ int factor = priv->cqe_factor;
if (!priv->port_up)
return 0;
/* We assume a 1:1 mapping between CQEs and Rx descriptors, so Rx
- * descriptor offset can be deduced from the CQE index instead of
+ * descriptor offset can be deducted from the CQE index instead of
* reading 'cqe->index' */
- index = cq->mcq.cons_index & ring->size_mask;
- cqe = &cq->buf[index];
+ index = cons_index & size_mask;
+ cqe = &buf[CQE_FACTOR_INDEX(index, factor)];
/* Process all completed CQEs */
while (XNOR(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK,
- cq->mcq.cons_index & cq->size)) {
-
+ cons_index & size)) {
mb_list = ring->rx_info + (index << priv->log_rx_info);
rx_desc = ring->buf + (index << ring->log_stride);
@@ -478,13 +581,14 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
*/
rmb();
- if (invalid_cqe(priv, cqe))
+ if (invalid_cqe(priv, cqe)) {
goto next;
-
+ }
/*
* Packet is OK - process it.
*/
length = be32_to_cpu(cqe->byte_cnt);
+ length -= ring->fcs_del;
mb = mlx4_en_rx_mb(priv, rx_desc, mb_list, length);
if (!mb) {
ring->errors++;
@@ -494,7 +598,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
ring->bytes += length;
ring->packets++;
- if (unlikely(priv->validate_loopback)) {
+ if (unlikely(priv->validate_loopback)) {
validate_loopback(priv, mb);
goto next;
}
@@ -507,11 +611,11 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
mb->m_pkthdr.ether_vtag = be16_to_cpu(cqe->sl_vid);
mb->m_flags |= M_VLANTAG;
}
- if (likely(priv->rx_csum) &&
+ if (likely(dev->if_capabilities & IFCAP_RXCSUM) &&
(cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) &&
(cqe->checksum == cpu_to_be16(0xffff))) {
priv->port_stats.rx_chksum_good++;
- mb->m_pkthdr.csum_flags =
+ mb->m_pkthdr.csum_flags =
CSUM_IP_CHECKED | CSUM_IP_VALID |
CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
mb->m_pkthdr.csum_data = htons(0xffff);
@@ -523,139 +627,89 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
*/
#ifdef INET
if (mlx4_en_can_lro(cqe->status) &&
- (dev->if_capenable & IFCAP_LRO)) {
+ (dev->if_capenable & IFCAP_LRO)) {
if (ring->lro.lro_cnt != 0 &&
- tcp_lro_rx(&ring->lro, mb, 0) == 0)
+ tcp_lro_rx(&ring->lro, mb, 0) == 0)
goto next;
}
-#endif
+#endif
/* LRO not possible, complete processing here */
INC_PERF_COUNTER(priv->pstats.lro_misses);
} else {
mb->m_pkthdr.csum_flags = 0;
priv->port_stats.rx_chksum_none++;
-#ifdef INET
- if (priv->ip_reasm &&
- cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPV4) &&
- !mlx4_en_rx_frags(priv, ring, mb, cqe))
- goto next;
-#endif
}
/* Push it up the stack */
dev->if_input(dev, mb);
next:
- ++cq->mcq.cons_index;
- index = (cq->mcq.cons_index) & ring->size_mask;
- cqe = &cq->buf[index];
+ ++cons_index;
+ index = cons_index & size_mask;
+ cqe = &buf[CQE_FACTOR_INDEX(index, factor)];
if (++polled == budget)
goto out;
}
/* Flush all pending IP reassembly sessions */
out:
#ifdef INET
- mlx4_en_flush_frags(priv, ring);
while ((queued = SLIST_FIRST(&ring->lro.lro_active)) != NULL) {
SLIST_REMOVE_HEAD(&ring->lro.lro_active, next);
tcp_lro_flush(&ring->lro, queued);
}
#endif
AVG_PERF_COUNTER(priv->pstats.rx_coal_avg, polled);
- mlx4_cq_set_ci(&cq->mcq);
+ mcq->cons_index = cons_index;
+ mlx4_cq_set_ci(mcq);
wmb(); /* ensure HW sees CQ consumer before we post new buffers */
- ring->cons = cq->mcq.cons_index;
+ ring->cons = mcq->cons_index;
ring->prod += polled; /* Polled descriptors were realocated in place */
mlx4_en_update_rx_prod_db(ring);
return polled;
-}
+}
/* Rx CQ polling - called by NAPI */
static int mlx4_en_poll_rx_cq(struct mlx4_en_cq *cq, int budget)
{
- struct net_device *dev = cq->dev;
- int done;
-
- done = mlx4_en_process_rx_cq(dev, cq, budget);
- cq->tot_rx += done;
+ struct net_device *dev = cq->dev;
+ int done;
- return done;
-}
+ done = mlx4_en_process_rx_cq(dev, cq, budget);
+ cq->tot_rx += done;
-void mlx4_en_rx_que(void *context, int pending)
-{
- struct mlx4_en_cq *cq;
+ return done;
- cq = context;
- while (mlx4_en_poll_rx_cq(cq, MLX4_EN_MAX_RX_POLL)
- == MLX4_EN_MAX_RX_POLL);
- mlx4_en_arm_cq(cq->dev->if_softc, cq);
}
-
void mlx4_en_rx_irq(struct mlx4_cq *mcq)
{
struct mlx4_en_cq *cq = container_of(mcq, struct mlx4_en_cq, mcq);
struct mlx4_en_priv *priv = netdev_priv(cq->dev);
- int done;
+ int done;
- done = mlx4_en_poll_rx_cq(cq, MLX4_EN_MAX_RX_POLL);
- if (done == MLX4_EN_MAX_RX_POLL)
+ // Shoot one within the irq context
+ // Because there is no NAPI in freeBSD
+ done = mlx4_en_poll_rx_cq(cq, MLX4_EN_RX_BUDGET);
+ if (priv->port_up && (done == MLX4_EN_RX_BUDGET) ) {
taskqueue_enqueue(cq->tq, &cq->cq_task);
- else
+ }
+ else {
mlx4_en_arm_cq(priv, cq);
+ }
}
-
-#if MLX4_EN_MAX_RX_FRAGS == 3
-static int frag_sizes[] = {
- FRAG_SZ0,
- FRAG_SZ1,
- FRAG_SZ2,
-};
-#elif MLX4_EN_MAX_RX_FRAGS == 2
-static int frag_sizes[] = {
- FRAG_SZ0,
- FRAG_SZ1,
-};
-#else
-#error "Unknown MAX_RX_FRAGS"
-#endif
-
-void mlx4_en_calc_rx_buf(struct net_device *dev)
+void mlx4_en_rx_que(void *context, int pending)
{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- int eff_mtu = dev->if_mtu + ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN + ETH_LLC_SNAP_SIZE;
- int buf_size = 0;
- int i, frag;
-
- for (i = 0, frag = 0; buf_size < eff_mtu; frag++, i++) {
- /*
- * Allocate small to large but only as much as is needed for
- * the tail.
- */
- while (i > 0 && eff_mtu - buf_size <= frag_sizes[i - 1])
- i--;
- priv->frag_info[frag].frag_size = frag_sizes[i];
- priv->frag_info[frag].frag_prefix_size = buf_size;
- buf_size += priv->frag_info[frag].frag_size;
- }
+ struct mlx4_en_cq *cq;
- priv->num_frags = frag;
- priv->rx_mb_size = eff_mtu;
- priv->log_rx_info =
- ROUNDUP_LOG2(priv->num_frags * sizeof(struct mbuf *));
-
- en_dbg(DRV, priv, "Rx buffer scatter-list (effective-mtu:%d "
- "num_frags:%d):\n", eff_mtu, priv->num_frags);
- for (i = 0; i < priv->num_frags; i++) {
- en_dbg(DRV, priv, " frag:%d - size:%d prefix:%d\n", i,
- priv->frag_info[i].frag_size,
- priv->frag_info[i].frag_prefix_size)
- }
+ cq = context;
+ while (mlx4_en_poll_rx_cq(cq, MLX4_EN_RX_BUDGET)
+ == MLX4_EN_RX_BUDGET);
+ mlx4_en_arm_cq(cq->dev->if_softc, cq);
}
+
/* RSS related functions */
static int mlx4_en_config_rss_qp(struct mlx4_en_priv *priv, int qpn,
@@ -672,6 +726,7 @@ static int mlx4_en_config_rss_qp(struct mlx4_en_priv *priv, int qpn,
en_err(priv, "Failed to allocate qp context\n");
return -ENOMEM;
}
+
err = mlx4_qp_alloc(mdev->dev, qpn, qp);
if (err) {
en_err(priv, "Failed to allocate qp #%x\n", qpn);
@@ -681,9 +736,16 @@ static int mlx4_en_config_rss_qp(struct mlx4_en_priv *priv, int qpn,
memset(context, 0, sizeof *context);
mlx4_en_fill_qp_context(priv, ring->actual_size, ring->stride, 0, 0,
- qpn, ring->cqn, context);
+ qpn, ring->cqn, -1, context);
context->db_rec_addr = cpu_to_be64(ring->wqres.db.dma);
+ /* Cancel FCS removal if FW allows */
+ if (mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_FCS_KEEP) {
+ context->param3 |= cpu_to_be32(1 << 29);
+ ring->fcs_del = ETH_FCS_LEN;
+ } else
+ ring->fcs_del = 0;
+
err = mlx4_qp_to_ready(mdev->dev, &ring->wqres.mtt, context, qp, state);
if (err) {
mlx4_qp_remove(mdev->dev, qp);
@@ -695,26 +757,57 @@ out:
return err;
}
+int mlx4_en_create_drop_qp(struct mlx4_en_priv *priv)
+{
+ int err;
+ u32 qpn;
+
+ err = mlx4_qp_reserve_range(priv->mdev->dev, 1, 1, &qpn, 0);
+ if (err) {
+ en_err(priv, "Failed reserving drop qpn\n");
+ return err;
+ }
+ err = mlx4_qp_alloc(priv->mdev->dev, qpn, &priv->drop_qp);
+ if (err) {
+ en_err(priv, "Failed allocating drop qp\n");
+ mlx4_qp_release_range(priv->mdev->dev, qpn, 1);
+ return err;
+ }
+
+ return 0;
+}
+
+void mlx4_en_destroy_drop_qp(struct mlx4_en_priv *priv)
+{
+ u32 qpn;
+
+ qpn = priv->drop_qp.qpn;
+ mlx4_qp_remove(priv->mdev->dev, &priv->drop_qp);
+ mlx4_qp_free(priv->mdev->dev, &priv->drop_qp);
+ mlx4_qp_release_range(priv->mdev->dev, qpn, 1);
+}
+
/* Allocate rx qp's and configure them according to rss map */
int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
{
struct mlx4_en_dev *mdev = priv->mdev;
struct mlx4_en_rss_map *rss_map = &priv->rss_map;
struct mlx4_qp_context context;
- struct mlx4_en_rss_context *rss_context;
+ struct mlx4_rss_context *rss_context;
+ int rss_rings;
void *ptr;
- u8 rss_mask;
- int i, qpn;
+ u8 rss_mask = (MLX4_RSS_IPV4 | MLX4_RSS_TCP_IPV4 | MLX4_RSS_IPV6 |
+ MLX4_RSS_TCP_IPV6);
+ int i;
int err = 0;
int good_qps = 0;
+ static const u32 rsskey[10] = { 0xD181C62C, 0xF7F4DB5B, 0x1983A2FC,
+ 0x943E1ADB, 0xD9389E6B, 0xD1039C2C, 0xA74499AD,
+ 0x593D56D9, 0xF3253C06, 0x2ADC1FFC};
- if (mdev->profile.udp_rss)
- rss_mask = 0x3f;
- else
- rss_mask = 0x14;
en_dbg(DRV, priv, "Configuring rss steering\n");
err = mlx4_qp_reserve_range(mdev->dev, priv->rx_ring_num,
- roundup_pow_of_two(priv->rx_ring_num),
+ priv->rx_ring_num,
&rss_map->base_qpn, 0);
if (err) {
en_err(priv, "Failed reserving %d qps\n", priv->rx_ring_num);
@@ -722,9 +815,9 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
}
for (i = 0; i < priv->rx_ring_num; i++) {
- qpn = rss_map->base_qpn + i;
- err = mlx4_en_config_rss_qp(priv, qpn,
- &priv->rx_ring[i],
+ priv->rx_ring[i]->qpn = rss_map->base_qpn + i;
+ err = mlx4_en_config_rss_qp(priv, priv->rx_ring[i]->qpn,
+ priv->rx_ring[i],
&rss_map->state[i],
&rss_map->qps[i]);
if (err)
@@ -734,28 +827,34 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
}
/* Configure RSS indirection qp */
- err = mlx4_qp_reserve_range(mdev->dev, 1, 1, &priv->base_qpn, 0);
- if (err) {
- en_err(priv, "Failed to reserve range for RSS "
- "indirection qp\n");
- goto rss_err;
- }
err = mlx4_qp_alloc(mdev->dev, priv->base_qpn, &rss_map->indir_qp);
if (err) {
en_err(priv, "Failed to allocate RSS indirection QP\n");
- goto reserve_err;
+ goto rss_err;
}
rss_map->indir_qp.event = mlx4_en_sqp_event;
mlx4_en_fill_qp_context(priv, 0, 0, 0, 1, priv->base_qpn,
- priv->rx_ring[0].cqn, &context);
+ priv->rx_ring[0]->cqn, -1, &context);
- ptr = ((void *) &context) + 0x3c;
- rss_context = (struct mlx4_en_rss_context *) ptr;
- rss_context->base_qpn = cpu_to_be32(ilog2(priv->rx_ring_num) << 24 |
+ if (!priv->prof->rss_rings || priv->prof->rss_rings > priv->rx_ring_num)
+ rss_rings = priv->rx_ring_num;
+ else
+ rss_rings = priv->prof->rss_rings;
+
+ ptr = ((void *) &context) + offsetof(struct mlx4_qp_context, pri_path)
+ + MLX4_RSS_OFFSET_IN_QPC_PRI_PATH;
+ rss_context = ptr;
+ rss_context->base_qpn = cpu_to_be32(ilog2(rss_rings) << 24 |
(rss_map->base_qpn));
rss_context->default_qpn = cpu_to_be32(rss_map->base_qpn);
+ if (priv->mdev->profile.udp_rss) {
+ rss_mask |= MLX4_RSS_UDP_IPV4 | MLX4_RSS_UDP_IPV6;
+ rss_context->base_qpn_udp = rss_context->default_qpn;
+ }
rss_context->flags = rss_mask;
- rss_context->base_qpn_udp = rss_context->default_qpn;
+ rss_context->hash_fn = MLX4_RSS_HASH_TOP;
+ for (i = 0; i < 10; i++)
+ rss_context->rss_key[i] = cpu_to_be32(rsskey[i]);
err = mlx4_qp_to_ready(mdev->dev, &priv->res.mtt, &context,
&rss_map->indir_qp, &rss_map->indir_state);
@@ -769,8 +868,6 @@ indir_err:
MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->indir_qp);
mlx4_qp_remove(mdev->dev, &rss_map->indir_qp);
mlx4_qp_free(mdev->dev, &rss_map->indir_qp);
-reserve_err:
- mlx4_qp_release_range(mdev->dev, priv->base_qpn, 1);
rss_err:
for (i = 0; i < good_qps; i++) {
mlx4_qp_modify(mdev->dev, NULL, rss_map->state[i],
@@ -792,7 +889,6 @@ void mlx4_en_release_rss_steer(struct mlx4_en_priv *priv)
MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->indir_qp);
mlx4_qp_remove(mdev->dev, &rss_map->indir_qp);
mlx4_qp_free(mdev->dev, &rss_map->indir_qp);
- mlx4_qp_release_range(mdev->dev, priv->base_qpn, 1);
for (i = 0; i < priv->rx_ring_num; i++) {
mlx4_qp_modify(mdev->dev, NULL, rss_map->state[i],
@@ -802,3 +898,4 @@ void mlx4_en_release_rss_steer(struct mlx4_en_priv *priv)
}
mlx4_qp_release_range(mdev->dev, rss_map->base_qpn, priv->rx_ring_num);
}
+
diff --git a/sys/ofed/drivers/net/mlx4/en_selftest.c b/sys/ofed/drivers/net/mlx4/en_selftest.c
index 0e62027..2a28315 100644
--- a/sys/ofed/drivers/net/mlx4/en_selftest.c
+++ b/sys/ofed/drivers/net/mlx4/en_selftest.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2007, 2014 Mellanox Technologies. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -31,24 +31,24 @@
*
*/
-#include "mlx4_en.h"
-
#include <linux/kernel.h>
#include <linux/ethtool.h>
#include <linux/netdevice.h>
#include <linux/delay.h>
#include <linux/mlx4/driver.h>
+#include "mlx4_en.h"
+
static int mlx4_en_test_registers(struct mlx4_en_priv *priv)
{
return mlx4_cmd(priv->mdev->dev, 0, 0, 0, MLX4_CMD_HW_HEALTH_CHECK,
- MLX4_CMD_TIME_CLASS_A);
+ MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
}
static int mlx4_en_test_loopback_xmit(struct mlx4_en_priv *priv)
{
- struct mbuf *mb;
+ struct sk_buff *skb;
struct ethhdr *ethh;
unsigned char *packet;
unsigned int packet_size = MLX4_LOOPBACK_TEST_PAYLOAD;
@@ -57,24 +57,24 @@ static int mlx4_en_test_loopback_xmit(struct mlx4_en_priv *priv)
/* build the pkt before xmit */
- mb = netdev_alloc_mb(priv->dev, MLX4_LOOPBACK_TEST_PAYLOAD + ETH_HLEN + NET_IP_ALIGN);
- if (!mb) {
- en_err(priv, "-LOOPBACK_TEST_XMIT- failed to create mb for xmit\n");
+ skb = netdev_alloc_skb(priv->dev, MLX4_LOOPBACK_TEST_PAYLOAD + ETH_HLEN + NET_IP_ALIGN);
+ if (!skb) {
+ en_err(priv, "-LOOPBACK_TEST_XMIT- failed to create skb for xmit\n");
return -ENOMEM;
}
- mb_reserve(mb, NET_IP_ALIGN);
+ skb_reserve(skb, NET_IP_ALIGN);
- ethh = (struct ethhdr *)mb_put(mb, sizeof(struct ethhdr));
- packet = (unsigned char *)mb_put(mb, packet_size);
+ ethh = (struct ethhdr *)skb_put(skb, sizeof(struct ethhdr));
+ packet = (unsigned char *)skb_put(skb, packet_size);
memcpy(ethh->h_dest, priv->dev->dev_addr, ETH_ALEN);
memset(ethh->h_source, 0, ETH_ALEN);
ethh->h_proto = htons(ETH_P_ARP);
- mb_set_mac_header(mb, 0);
+ skb_set_mac_header(skb, 0);
for (i = 0; i < packet_size; ++i) /* fill our packet */
packet[i] = (unsigned char)(i & 0xff);
/* xmit the pkt */
- err = mlx4_en_xmit(mb, priv->dev);
+ err = mlx4_en_xmit(skb, priv->dev);
return err;
}
@@ -87,6 +87,8 @@ static int mlx4_en_test_loopback(struct mlx4_en_priv *priv)
priv->loopback_ok = 0;
priv->validate_loopback = 1;
+ mlx4_en_update_loopback_state(priv->dev, priv->dev->features);
+
/* xmit */
if (mlx4_en_test_loopback_xmit(priv)) {
en_err(priv, "Transmitting loopback packet failed\n");
@@ -107,7 +109,8 @@ static int mlx4_en_test_loopback(struct mlx4_en_priv *priv)
mlx4_en_test_loopback_exit:
priv->validate_loopback = 0;
- return (!loopback_ok);
+ mlx4_en_update_loopback_state(priv->dev, priv->dev->features);
+ return !loopback_ok;
}
@@ -127,8 +130,10 @@ static int mlx4_en_test_speed(struct mlx4_en_priv *priv)
if (mlx4_en_QUERY_PORT(priv->mdev, priv->port))
return -ENOMEM;
- /* The device currently only supports 10G speed */
- if (priv->port_state.link_speed != SPEED_10000)
+ /* The device supports 1G, 10G and 40G speed */
+ if (priv->port_state.link_speed != MLX4_EN_LINK_SPEED_1G &&
+ priv->port_state.link_speed != MLX4_EN_LINK_SPEED_10G &&
+ priv->port_state.link_speed != MLX4_EN_LINK_SPEED_40G)
return priv->port_state.link_speed;
return 0;
}
@@ -138,7 +143,6 @@ void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
struct mlx4_en_dev *mdev = priv->mdev;
- struct mlx4_en_tx_ring *tx_ring;
int i, carrier_ok;
memset(buf, 0, sizeof(u64) * MLX4_EN_NUM_SELF_TEST);
@@ -148,20 +152,16 @@ void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf)
carrier_ok = netif_carrier_ok(dev);
netif_carrier_off(dev);
-retry_tx:
- /* Wait untill all tx queues are empty.
+ /* Wait until all tx queues are empty.
* there should not be any additional incoming traffic
* since we turned the carrier off */
msleep(200);
- for (i = 0; i < priv->tx_ring_num && carrier_ok; i++) {
- tx_ring = &priv->tx_ring[i];
- if (tx_ring->prod != (tx_ring->cons + tx_ring->last_nr_txbb))
- goto retry_tx;
- }
- if (priv->mdev->dev->caps.loopback_support){
+ if (priv->mdev->dev->caps.flags &
+ MLX4_DEV_CAP_FLAG_UC_LOOPBACK) {
buf[3] = mlx4_en_test_registers(priv);
- buf[4] = mlx4_en_test_loopback(priv);
+ if (priv->port_up)
+ buf[4] = mlx4_en_test_loopback(priv);
}
if (carrier_ok)
diff --git a/sys/ofed/drivers/net/mlx4/en_tx.c b/sys/ofed/drivers/net/mlx4/en_tx.c
index 4661024..94ac8c5 100644
--- a/sys/ofed/drivers/net/mlx4/en_tx.c
+++ b/sys/ofed/drivers/net/mlx4/en_tx.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2007, 2014 Mellanox Technologies. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -31,15 +31,13 @@
*
*/
-#include "mlx4_en.h"
-
+#include <asm/page.h>
#include <linux/mlx4/cq.h>
+#include <linux/slab.h>
#include <linux/mlx4/qp.h>
+#include <linux/if_vlan.h>
#include <linux/vmalloc.h>
-
-#include <net/ethernet.h>
-#include <net/if_vlan_var.h>
-#include <sys/mbuf.h>
+#include <linux/moduleparam.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
@@ -50,59 +48,78 @@
#include <netinet/tcp_lro.h>
#include <netinet/udp.h>
+#include "mlx4_en.h"
+#include "utils.h"
+
enum {
MAX_INLINE = 104, /* 128 - 16 - 4 - 4 */
MAX_BF = 256,
+ MIN_PKT_LEN = 17,
};
-static int inline_thold = MAX_INLINE;
+static int inline_thold __read_mostly = MAX_INLINE;
-module_param_named(inline_thold, inline_thold, int, 0444);
-MODULE_PARM_DESC(inline_thold, "treshold for using inline data");
+module_param_named(inline_thold, inline_thold, uint, 0444);
+MODULE_PARM_DESC(inline_thold, "threshold for using inline data");
int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
- struct mlx4_en_tx_ring *ring, u32 size,
- u16 stride)
+ struct mlx4_en_tx_ring **pring, u32 size,
+ u16 stride, int node, int queue_idx)
{
struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_en_tx_ring *ring;
int tmp;
int err;
+ ring = kzalloc_node(sizeof(struct mlx4_en_tx_ring), GFP_KERNEL, node);
+ if (!ring) {
+ ring = kzalloc(sizeof(struct mlx4_en_tx_ring), GFP_KERNEL);
+ if (!ring) {
+ en_err(priv, "Failed allocating TX ring\n");
+ return -ENOMEM;
+ }
+ }
+
ring->size = size;
ring->size_mask = size - 1;
ring->stride = stride;
-
- inline_thold = min(inline_thold, MAX_INLINE);
-
+ ring->full_size = ring->size - HEADROOM - MAX_DESC_TXBBS;
+ ring->inline_thold = min(inline_thold, MAX_INLINE);
mtx_init(&ring->tx_lock.m, "mlx4 tx", NULL, MTX_DEF);
mtx_init(&ring->comp_lock.m, "mlx4 comp", NULL, MTX_DEF);
/* Allocate the buf ring */
ring->br = buf_ring_alloc(MLX4_EN_DEF_TX_QUEUE_SIZE, M_DEVBUF,
- M_WAITOK, &ring->tx_lock.m);
+ M_WAITOK, &ring->tx_lock.m);
if (ring->br == NULL) {
en_err(priv, "Failed allocating tx_info ring\n");
return -ENOMEM;
}
tmp = size * sizeof(struct mlx4_en_tx_info);
- ring->tx_info = kmalloc(tmp, GFP_KERNEL);
+ ring->tx_info = vmalloc_node(tmp, node);
if (!ring->tx_info) {
- en_err(priv, "Failed allocating tx_info ring\n");
- err = -ENOMEM;
- goto err_tx;
+ ring->tx_info = vmalloc(tmp);
+ if (!ring->tx_info) {
+ err = -ENOMEM;
+ goto err_ring;
+ }
}
+
en_dbg(DRV, priv, "Allocated tx_info ring at addr:%p size:%d\n",
ring->tx_info, tmp);
- ring->bounce_buf = kmalloc(MAX_DESC_SIZE, GFP_KERNEL);
+ ring->bounce_buf = kmalloc_node(MAX_DESC_SIZE, GFP_KERNEL, node);
if (!ring->bounce_buf) {
- en_err(priv, "Failed allocating bounce buffer\n");
- err = -ENOMEM;
- goto err_tx;
+ ring->bounce_buf = kmalloc(MAX_DESC_SIZE, GFP_KERNEL);
+ if (!ring->bounce_buf) {
+ err = -ENOMEM;
+ goto err_info;
+ }
}
ring->buf_size = ALIGN(size * ring->stride, MLX4_EN_PAGE_SIZE);
+ /* Allocate HW buffers on provided NUMA node */
err = mlx4_alloc_hwq_res(mdev->dev, &ring->wqres, ring->buf_size,
2 * PAGE_SIZE);
if (err) {
@@ -122,9 +139,10 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
"buf_size:%d dma:%llx\n", ring, ring->buf, ring->size,
ring->buf_size, (unsigned long long) ring->wqres.buf.direct.map);
- err = mlx4_qp_reserve_range(mdev->dev, 1, 256, &ring->qpn, MLX4_RESERVE_BF_QP);
+ err = mlx4_qp_reserve_range(mdev->dev, 1, 1, &ring->qpn,
+ MLX4_RESERVE_BF_QP);
if (err) {
- en_err(priv, "Failed reserving qp for tx ring.\n");
+ en_err(priv, "failed reserving qp for TX ring\n");
goto err_map;
}
@@ -135,14 +153,19 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
}
ring->qp.event = mlx4_en_sqp_event;
- err = mlx4_bf_alloc(mdev->dev, &ring->bf, 0);
+ err = mlx4_bf_alloc(mdev->dev, &ring->bf, node);
if (err) {
+ en_dbg(DRV, priv, "working without blueflame (%d)", err);
ring->bf.uar = &mdev->priv_uar;
ring->bf.uar->map = mdev->uar_map;
ring->bf_enabled = false;
} else
ring->bf_enabled = true;
+ ring->queue_index = queue_idx;
+ if (queue_idx < priv->num_tx_rings_p_up )
+ CPU_SET(queue_idx, &ring->affinity_mask);
+ *pring = ring;
return 0;
err_reserve:
@@ -153,18 +176,19 @@ err_hwq_res:
mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size);
err_bounce:
kfree(ring->bounce_buf);
- ring->bounce_buf = NULL;
-err_tx:
+err_info:
+ vfree(ring->tx_info);
+err_ring:
buf_ring_free(ring->br, M_DEVBUF);
- kfree(ring->tx_info);
- ring->tx_info = NULL;
+ kfree(ring);
return err;
}
void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv,
- struct mlx4_en_tx_ring *ring)
+ struct mlx4_en_tx_ring **pring)
{
struct mlx4_en_dev *mdev = priv->mdev;
+ struct mlx4_en_tx_ring *ring = *pring;
en_dbg(DRV, priv, "Destroying tx ring, qpn: %d\n", ring->qpn);
buf_ring_free(ring->br, M_DEVBUF);
@@ -172,20 +196,20 @@ void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv,
mlx4_bf_free(mdev->dev, &ring->bf);
mlx4_qp_remove(mdev->dev, &ring->qp);
mlx4_qp_free(mdev->dev, &ring->qp);
- mlx4_qp_release_range(mdev->dev, ring->qpn, 1);
+ mlx4_qp_release_range(priv->mdev->dev, ring->qpn, 1);
mlx4_en_unmap_buffer(&ring->wqres.buf);
mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size);
kfree(ring->bounce_buf);
- ring->bounce_buf = NULL;
- kfree(ring->tx_info);
- ring->tx_info = NULL;
+ vfree(ring->tx_info);
mtx_destroy(&ring->tx_lock.m);
mtx_destroy(&ring->comp_lock.m);
+ kfree(ring);
+ *pring = NULL;
}
int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
struct mlx4_en_tx_ring *ring,
- int cq)
+ int cq, int user_prio)
{
struct mlx4_en_dev *mdev = priv->mdev;
int err;
@@ -200,16 +224,15 @@ int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
memset(ring->buf, 0, ring->buf_size);
ring->qp_state = MLX4_QP_STATE_RST;
- ring->doorbell_qpn = swab32(ring->qp.qpn << 8);
+ ring->doorbell_qpn = ring->qp.qpn << 8;
mlx4_en_fill_qp_context(priv, ring->size, ring->stride, 1, 0, ring->qpn,
- ring->cqn, &ring->context);
+ ring->cqn, user_prio, &ring->context);
if (ring->bf_enabled)
ring->context.usr_page = cpu_to_be32(ring->bf.uar->index);
err = mlx4_qp_to_ready(mdev->dev, &ring->wqres.mtt, &ring->context,
&ring->qp, &ring->qp_state);
-
return err;
}
@@ -222,65 +245,98 @@ void mlx4_en_deactivate_tx_ring(struct mlx4_en_priv *priv,
MLX4_QP_STATE_RST, NULL, 0, 0, &ring->qp);
}
+static void mlx4_en_stamp_wqe(struct mlx4_en_priv *priv,
+ struct mlx4_en_tx_ring *ring,
+ int index, u8 owner)
+{
+ struct mlx4_en_tx_info *tx_info = &ring->tx_info[index];
+ struct mlx4_en_tx_desc *tx_desc = ring->buf + index * TXBB_SIZE;
+ void *end = ring->buf + ring->buf_size;
+ __be32 *ptr = (__be32 *)tx_desc;
+ __be32 stamp = cpu_to_be32(STAMP_VAL | (!!owner << STAMP_SHIFT));
+ int i;
+
+ /* Optimize the common case when there are no wraparounds */
+ if (likely((void *)tx_desc + tx_info->nr_txbb * TXBB_SIZE <= end))
+ /* Stamp the freed descriptor */
+ for (i = 0; i < tx_info->nr_txbb * TXBB_SIZE; i += STAMP_STRIDE) {
+ *ptr = stamp;
+ ptr += STAMP_DWORDS;
+ }
+ else
+ /* Stamp the freed descriptor */
+ for (i = 0; i < tx_info->nr_txbb * TXBB_SIZE; i += STAMP_STRIDE) {
+ *ptr = stamp;
+ ptr += STAMP_DWORDS;
+ if ((void *)ptr >= end) {
+ ptr = ring->buf;
+ stamp ^= cpu_to_be32(0x80000000);
+ }
+ }
+}
static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
struct mlx4_en_tx_ring *ring,
- int index, u8 owner)
+ int index, u8 owner, u64 timestamp)
{
struct mlx4_en_dev *mdev = priv->mdev;
struct mlx4_en_tx_info *tx_info = &ring->tx_info[index];
struct mlx4_en_tx_desc *tx_desc = ring->buf + index * TXBB_SIZE;
struct mlx4_wqe_data_seg *data = (void *) tx_desc + tx_info->data_offset;
- struct mbuf *mb = tx_info->mb;
+ struct mbuf *mb = tx_info->mb;
void *end = ring->buf + ring->buf_size;
- int frags = tx_info->nr_segs;
+ int frags = tx_info->nr_segs;;
int i;
- __be32 *ptr = (__be32 *)tx_desc;
- __be32 stamp = cpu_to_be32(STAMP_VAL | (!!owner << STAMP_SHIFT));
/* Optimize the common case when there are no wraparounds */
if (likely((void *) tx_desc + tx_info->nr_txbb * TXBB_SIZE <= end)) {
if (!tx_info->inl) {
+ if (tx_info->linear) {
+ dma_unmap_single(priv->ddev,
+ (dma_addr_t) be64_to_cpu(data->addr),
+ be32_to_cpu(data->byte_count),
+ PCI_DMA_TODEVICE);
+ ++data;
+ }
+
for (i = 0; i < frags; i++) {
- pci_unmap_single(mdev->pdev,
- (dma_addr_t) be64_to_cpu(data[i].addr),
- data[i].byte_count, PCI_DMA_TODEVICE);
+ pci_unmap_single(mdev->pdev,
+ (dma_addr_t) be64_to_cpu(data[i].addr),
+ data[i].byte_count, PCI_DMA_TODEVICE);
}
}
- /* Stamp the freed descriptor */
- for (i = 0; i < tx_info->nr_txbb * TXBB_SIZE; i += STAMP_STRIDE) {
- *ptr = stamp;
- ptr += STAMP_DWORDS;
- }
-
} else {
if (!tx_info->inl) {
+ if ((void *) data >= end) {
+ data = ring->buf + ((void *)data - end);
+ }
+
+ if (tx_info->linear) {
+ dma_unmap_single(priv->ddev,
+ (dma_addr_t) be64_to_cpu(data->addr),
+ be32_to_cpu(data->byte_count),
+ PCI_DMA_TODEVICE);
+ ++data;
+ }
+
for (i = 0; i < frags; i++) {
/* Check for wraparound before unmapping */
if ((void *) data >= end)
- data = (struct mlx4_wqe_data_seg *) ring->buf;
- pci_unmap_single(mdev->pdev,
- (dma_addr_t) be64_to_cpu(data->addr),
- data->byte_count, PCI_DMA_TODEVICE);
+ data = ring->buf;
+ pci_unmap_single(mdev->pdev,
+ (dma_addr_t) be64_to_cpu(data->addr),
+ data->byte_count, PCI_DMA_TODEVICE);
++data;
}
}
- /* Stamp the freed descriptor */
- for (i = 0; i < tx_info->nr_txbb * TXBB_SIZE; i += STAMP_STRIDE) {
- *ptr = stamp;
- ptr += STAMP_DWORDS;
- if ((void *) ptr >= end) {
- ptr = ring->buf;
- stamp ^= cpu_to_be32(0x80000000);
- }
- }
-
}
- m_freem(mb);
+ /* Send a copy of the frame to the BPF listener */
+ if (priv->dev && priv->dev->if_bpf)
+ ETHER_BPF_MTAP(priv->dev, mb);
+ m_freem(mb);
return tx_info->nr_txbb;
}
-
int mlx4_en_free_tx_buf(struct net_device *dev, struct mlx4_en_tx_ring *ring)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
@@ -292,14 +348,14 @@ int mlx4_en_free_tx_buf(struct net_device *dev, struct mlx4_en_tx_ring *ring)
ring->cons, ring->prod);
if ((u32) (ring->prod - ring->cons) > ring->size) {
- en_warn(priv, "Tx consumer passed producer!\n");
+ en_warn(priv, "Tx consumer passed producer!\n");
return 0;
}
while (ring->cons != ring->prod) {
ring->last_nr_txbb = mlx4_en_free_tx_desc(priv, ring,
ring->cons & ring->size_mask,
- !!(ring->cons & ring->size));
+ !!(ring->cons & ring->size), 0);
ring->cons += ring->last_nr_txbb;
cnt++;
}
@@ -310,109 +366,105 @@ int mlx4_en_free_tx_buf(struct net_device *dev, struct mlx4_en_tx_ring *ring)
return cnt;
}
-void mlx4_en_set_prio_map(struct mlx4_en_priv *priv, u16 *prio_map, u32 ring_num)
-{
- int block = 8 / ring_num;
- int extra = 8 - (block * ring_num);
- int num = 0;
- u16 ring = 1;
- int prio;
-
- if (ring_num == 1) {
- for (prio = 0; prio < 8; prio++)
- prio_map[prio] = 0;
- return;
- }
-
- for (prio = 0; prio < 8; prio++) {
- if (extra && (num == block + 1)) {
- ring++;
- num = 0;
- extra--;
- } else if (!extra && (num == block)) {
- ring++;
- num = 0;
- }
- prio_map[prio] = ring;
- en_dbg(DRV, priv, " prio:%d --> ring:%d\n", prio, ring);
- num++;
- }
-}
-
-static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq)
+static int mlx4_en_process_tx_cq(struct net_device *dev,
+ struct mlx4_en_cq *cq)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
struct mlx4_cq *mcq = &cq->mcq;
- struct mlx4_en_tx_ring *ring = &priv->tx_ring[cq->ring];
- struct mlx4_cqe *cqe = cq->buf;
+ struct mlx4_en_tx_ring *ring = priv->tx_ring[cq->ring];
+ struct mlx4_cqe *cqe;
u16 index;
- u16 new_index;
+ u16 new_index, ring_index, stamp_index;
u32 txbbs_skipped = 0;
- u32 cq_last_sav;
+ u32 txbbs_stamp = 0;
+ u32 cons_index = mcq->cons_index;
+ int size = cq->size;
+ u32 size_mask = ring->size_mask;
+ struct mlx4_cqe *buf = cq->buf;
+ u32 packets = 0;
+ u32 bytes = 0;
+ int factor = priv->cqe_factor;
+ u64 timestamp = 0;
+ int done = 0;
- /* index always points to the first TXBB of the last polled descriptor */
- index = ring->cons & ring->size_mask;
- new_index = be16_to_cpu(cqe->wqe_index) & ring->size_mask;
- if (index == new_index)
- return;
if (!priv->port_up)
- return;
+ return 0;
+
+ index = cons_index & size_mask;
+ cqe = &buf[(index << factor) + factor];
+ ring_index = ring->cons & size_mask;
+ stamp_index = ring_index;
+
+ /* Process all completed CQEs */
+ while (XNOR(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK,
+ cons_index & size)) {
+ /*
+ * make sure we read the CQE after we read the
+ * ownership bit
+ */
+ rmb();
+
+ if (unlikely((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) ==
+ MLX4_CQE_OPCODE_ERROR)) {
+ en_err(priv, "CQE completed in error - vendor syndrom: 0x%x syndrom: 0x%x\n",
+ ((struct mlx4_err_cqe *)cqe)->
+ vendor_err_syndrome,
+ ((struct mlx4_err_cqe *)cqe)->syndrome);
+ }
+
+ /* Skip over last polled CQE */
+ new_index = be16_to_cpu(cqe->wqe_index) & size_mask;
- /*
- * We use a two-stage loop:
- * - the first samples the HW-updated CQE
- * - the second frees TXBBs until the last sample
- * This lets us amortize CQE cache misses, while still polling the CQ
- * until is quiescent.
- */
- cq_last_sav = mcq->cons_index;
- do {
do {
- /* Skip over last polled CQE */
- index = (index + ring->last_nr_txbb) & ring->size_mask;
txbbs_skipped += ring->last_nr_txbb;
-
- /* Poll next CQE */
+ ring_index = (ring_index + ring->last_nr_txbb) & size_mask;
+ /* free next descriptor */
ring->last_nr_txbb = mlx4_en_free_tx_desc(
- priv, ring, index,
- !!((ring->cons + txbbs_skipped) &
- ring->size));
- ++mcq->cons_index;
-
- } while (index != new_index);
+ priv, ring, ring_index,
+ !!((ring->cons + txbbs_skipped) &
+ ring->size), timestamp);
+ mlx4_en_stamp_wqe(priv, ring, stamp_index,
+ !!((ring->cons + txbbs_stamp) &
+ ring->size));
+ stamp_index = ring_index;
+ txbbs_stamp = txbbs_skipped;
+ packets++;
+ bytes += ring->tx_info[ring_index].nr_bytes;
+ } while (ring_index != new_index);
+
+ ++cons_index;
+ index = cons_index & size_mask;
+ cqe = &buf[(index << factor) + factor];
+ }
- new_index = be16_to_cpu(cqe->wqe_index) & ring->size_mask;
- } while (index != new_index);
- AVG_PERF_COUNTER(priv->pstats.tx_coal_avg,
- (u32) (mcq->cons_index - cq_last_sav));
/*
* To prevent CQ overflow we first update CQ consumer and only then
* the ring consumer.
*/
+ mcq->cons_index = cons_index;
mlx4_cq_set_ci(mcq);
wmb();
ring->cons += txbbs_skipped;
- /* Wakeup Tx queue if this ring stopped it */
- if (unlikely(ring->blocked)) {
- if ((u32) (ring->prod - ring->cons) <=
- ring->size - HEADROOM - MAX_DESC_TXBBS) {
- ring->blocked = 0;
- if (atomic_fetchadd_int(&priv->blocked, -1) == 1)
- atomic_clear_int(&dev->if_drv_flags,
- IFF_DRV_OACTIVE);
- priv->port_stats.wake_queue++;
- }
+ /* Wakeup Tx queue if it was stopped and ring is not full */
+ if (unlikely(ring->blocked) &&
+ (ring->prod - ring->cons) <= ring->full_size) {
+ ring->blocked = 0;
+ if (atomic_fetchadd_int(&priv->blocked, -1) == 1)
+ atomic_clear_int(&dev->if_drv_flags ,IFF_DRV_OACTIVE);
+ ring->wake_queue++;
+ priv->port_stats.wake_queue++;
}
+ return done;
}
void mlx4_en_tx_irq(struct mlx4_cq *mcq)
{
struct mlx4_en_cq *cq = container_of(mcq, struct mlx4_en_cq, mcq);
struct mlx4_en_priv *priv = netdev_priv(cq->dev);
- struct mlx4_en_tx_ring *ring = &priv->tx_ring[cq->ring];
+ struct mlx4_en_tx_ring *ring = priv->tx_ring[cq->ring];
if (!spin_trylock(&ring->comp_lock))
return;
@@ -421,12 +473,11 @@ void mlx4_en_tx_irq(struct mlx4_cq *mcq)
spin_unlock(&ring->comp_lock);
}
-
void mlx4_en_poll_tx_cq(unsigned long data)
{
struct mlx4_en_cq *cq = (struct mlx4_en_cq *) data;
struct mlx4_en_priv *priv = netdev_priv(cq->dev);
- struct mlx4_en_tx_ring *ring = &priv->tx_ring[cq->ring];
+ struct mlx4_en_tx_ring *ring = priv->tx_ring[cq->ring];
u32 inflight;
INC_PERF_COUNTER(priv->pstats.tx_poll);
@@ -477,8 +528,8 @@ static struct mlx4_en_tx_desc *mlx4_en_bounce_to_desc(struct mlx4_en_priv *priv,
static inline void mlx4_en_xmit_poll(struct mlx4_en_priv *priv, int tx_ind)
{
- struct mlx4_en_cq *cq = &priv->tx_cq[tx_ind];
- struct mlx4_en_tx_ring *ring = &priv->tx_ring[tx_ind];
+ struct mlx4_en_cq *cq = priv->tx_cq[tx_ind];
+ struct mlx4_en_tx_ring *ring = priv->tx_ring[tx_ind];
/* If we don't have a pending timer, set one up to catch our recent
post in case the interface becomes idle */
@@ -493,14 +544,13 @@ static inline void mlx4_en_xmit_poll(struct mlx4_en_priv *priv, int tx_ind)
}
}
-static int is_inline(struct mbuf *mb)
+static int is_inline(struct mbuf *mb, int thold)
{
-
- if (inline_thold && mb->m_pkthdr.len <= inline_thold &&
- (mb->m_pkthdr.csum_flags & CSUM_TSO) == 0)
+ if (thold && mb->m_pkthdr.len <= thold &&
+ (mb->m_pkthdr.csum_flags & CSUM_TSO) == 0)
return 1;
- return 0;
+ return 0;
}
static int inline_size(struct mbuf *mb)
@@ -519,81 +569,108 @@ static int inline_size(struct mbuf *mb)
static int get_head_size(struct mbuf *mb)
{
- struct tcphdr *th;
- struct ip *ip;
- int ip_hlen, tcp_hlen;
- int len;
-
- len = ETHER_HDR_LEN;
- if (mb->m_len < len + sizeof(struct ip))
+ struct ether_vlan_header *eh;
+ struct tcphdr *th;
+ struct ip *ip;
+ int ip_hlen, tcp_hlen;
+ struct ip6_hdr *ip6;
+ uint16_t eth_type;
+ int eth_hdr_len;
+
+ eh = mtod(mb, struct ether_vlan_header *);
+ if (mb->m_len < ETHER_HDR_LEN)
+ return (0);
+ if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
+ eth_type = ntohs(eh->evl_proto);
+ eth_hdr_len = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
+ } else {
+ eth_type = ntohs(eh->evl_encap_proto);
+ eth_hdr_len = ETHER_HDR_LEN;
+ }
+ if (mb->m_len < eth_hdr_len)
return (0);
- ip = (struct ip *)(mtod(mb, char *) + len);
- if (ip->ip_p != IPPROTO_TCP)
+ switch (eth_type) {
+ case ETHERTYPE_IP:
+ ip = (struct ip *)(mb->m_data + eth_hdr_len);
+ if (mb->m_len < eth_hdr_len + sizeof(*ip))
+ return (0);
+ if (ip->ip_p != IPPROTO_TCP)
+ return (0);
+ ip_hlen = ip->ip_hl << 2;
+ eth_hdr_len += ip_hlen;
+ break;
+ case ETHERTYPE_IPV6:
+ ip6 = (struct ip6_hdr *)(mb->m_data + eth_hdr_len);
+ if (mb->m_len < eth_hdr_len + sizeof(*ip6))
+ return (0);
+ if (ip6->ip6_nxt != IPPROTO_TCP)
+ return (0);
+ eth_hdr_len += sizeof(*ip6);
+ break;
+ default:
return (0);
- ip_hlen = ip->ip_hl << 2;
- len += ip_hlen;
- if (mb->m_len < len + sizeof(struct tcphdr))
+ }
+ if (mb->m_len < eth_hdr_len + sizeof(*th))
return (0);
- th = (struct tcphdr *)(mtod(mb, char *) + len);
+ th = (struct tcphdr *)(mb->m_data + eth_hdr_len);
tcp_hlen = th->th_off << 2;
- len += tcp_hlen;
- if (mb->m_len < len)
+ eth_hdr_len += tcp_hlen;
+ if (mb->m_len < eth_hdr_len)
return (0);
- return (len);
+ return (eth_hdr_len);
}
-static int get_real_size(struct mbuf *mb, struct net_device *dev, int *segsp,
- int *lso_header_size)
+static int get_real_size(struct mbuf *mb, struct net_device *dev, int *p_n_segs,
+ int *lso_header_size, int inl)
{
- struct mbuf *m;
- int nr_segs;
-
- nr_segs = 0;
- for (m = mb; m != NULL; m = m->m_next)
- if (m->m_len)
- nr_segs++;
-
- if (mb->m_pkthdr.csum_flags & CSUM_TSO) {
- *lso_header_size = get_head_size(mb);
- if (*lso_header_size) {
- if (mb->m_len == *lso_header_size)
- nr_segs--;
- *segsp = nr_segs;
- return CTRL_SIZE + nr_segs * DS_SIZE +
- ALIGN(*lso_header_size + 4, DS_SIZE);
- }
- } else
- *lso_header_size = 0;
- *segsp = nr_segs;
- if (is_inline(mb))
- return inline_size(mb);
- return (CTRL_SIZE + nr_segs * DS_SIZE);
+ struct mbuf *m;
+ int nr_segs = 0;
+
+ for (m = mb; m != NULL; m = m->m_next)
+ if (m->m_len)
+ nr_segs++;
+
+ if (mb->m_pkthdr.csum_flags & CSUM_TSO) {
+ *lso_header_size = get_head_size(mb);
+ if (*lso_header_size) {
+ if (mb->m_len == *lso_header_size)
+ nr_segs--;
+ *p_n_segs = nr_segs;
+ return CTRL_SIZE + nr_segs * DS_SIZE +
+ ALIGN(*lso_header_size + 4, DS_SIZE);
+ }
+ } else
+ *lso_header_size = 0;
+ *p_n_segs = nr_segs;
+ if (inl)
+ return inline_size(mb);
+ return (CTRL_SIZE + nr_segs * DS_SIZE);
}
static struct mbuf *mb_copy(struct mbuf *mb, int *offp, char *data, int len)
{
- int bytes;
- int off;
-
- off = *offp;
- while (len) {
- bytes = min(mb->m_len - off, len);
- if (bytes)
- memcpy(data, mb->m_data + off, bytes);
- len -= bytes;
- data += bytes;
- off += bytes;
- if (off == mb->m_len) {
- off = 0;
- mb = mb->m_next;
- }
- }
- *offp = off;
- return (mb);
+ int bytes;
+ int off;
+
+ off = *offp;
+ while (len) {
+ bytes = min(mb->m_len - off, len);
+ if (bytes)
+ memcpy(data, mb->m_data + off, bytes);
+ len -= bytes;
+ data += bytes;
+ off += bytes;
+ if (off == mb->m_len) {
+ off = 0;
+ mb = mb->m_next;
+ }
+ }
+ *offp = off;
+ return (mb);
}
static void build_inline_wqe(struct mlx4_en_tx_desc *tx_desc, struct mbuf *mb,
- int real_size, u16 *vlan_tag, int tx_ind)
+ int real_size, u16 *vlan_tag, int tx_ind)
{
struct mlx4_wqe_inline_seg *inl = &tx_desc->inl;
int spc = MLX4_INLINE_ALIGN - CTRL_SIZE - sizeof *inl;
@@ -603,8 +680,12 @@ static void build_inline_wqe(struct mlx4_en_tx_desc *tx_desc, struct mbuf *mb,
off = 0;
len = mb->m_pkthdr.len;
if (len <= spc) {
- inl->byte_count = cpu_to_be32(1 << 31 | len);
+ inl->byte_count = cpu_to_be32(1 << 31 |
+ (max_t(typeof(len), len, MIN_PKT_LEN)));
mb_copy(mb, &off, (void *)(inl + 1), len);
+ if (len < MIN_PKT_LEN)
+ memset(((void *)(inl + 1)) + len, 0,
+ MIN_PKT_LEN - len);
} else {
inl->byte_count = cpu_to_be32(1 << 31 | spc);
mb = mb_copy(mb, &off, (void *)(inl + 1), spc);
@@ -618,74 +699,50 @@ static void build_inline_wqe(struct mlx4_en_tx_desc *tx_desc, struct mbuf *mb,
tx_desc->ctrl.fence_size = (real_size / 16) & 0x3f;
}
+static unsigned long hashrandom;
+static void hashrandom_init(void *arg)
+{
+ hashrandom = random();
+}
+SYSINIT(hashrandom_init, SI_SUB_KLD, SI_ORDER_SECOND, &hashrandom_init, NULL);
+
u16 mlx4_en_select_queue(struct net_device *dev, struct mbuf *mb)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_tx_hash_entry *entry;
- struct ether_header *eth;
- struct tcphdr *th;
- struct ip *iph;
- u32 hash_index;
- int tx_ind = 0;
- u16 vlan_tag = 0;
- int len;
+ u32 rings_p_up = priv->num_tx_rings_p_up;
+ u32 vlan_tag = 0;
+ u32 up = 0;
+ u32 queue_index;
/* Obtain VLAN information if present */
if (mb->m_flags & M_VLANTAG) {
vlan_tag = mb->m_pkthdr.ether_vtag;
- /* Set the Tx ring to use according to vlan priority */
- tx_ind = priv->tx_prio_map[vlan_tag >> 13];
- if (tx_ind)
- return tx_ind;
- }
- if (mb->m_len <
- ETHER_HDR_LEN + sizeof(struct ip) + sizeof(struct tcphdr))
- return MLX4_EN_NUM_HASH_RINGS;
- eth = mtod(mb, struct ether_header *);
- /* Hashing is only done for TCP/IP or UDP/IP packets */
- if (be16_to_cpu(eth->ether_type) != ETHERTYPE_IP)
- return MLX4_EN_NUM_HASH_RINGS;
- len = ETHER_HDR_LEN;
- iph = (struct ip *)(mtod(mb, char *) + len);
- len += iph->ip_hl << 2;
- th = (struct tcphdr *)(mtod(mb, char *) + len);
- hash_index = be32_to_cpu(iph->ip_dst.s_addr) & MLX4_EN_TX_HASH_MASK;
- switch(iph->ip_p) {
- case IPPROTO_UDP:
- break;
- case IPPROTO_TCP:
- if (mb->m_len < len + sizeof(struct tcphdr))
- return MLX4_EN_NUM_HASH_RINGS;
- hash_index =
- (hash_index ^ be16_to_cpu(th->th_dport ^ th->th_sport)) &
- MLX4_EN_TX_HASH_MASK;
- break;
- default:
- return MLX4_EN_NUM_HASH_RINGS;
+ up = (vlan_tag >> 13);
}
- entry = &priv->tx_hash[hash_index];
- if(unlikely(!entry->cnt)) {
- tx_ind = hash_index & (MLX4_EN_NUM_HASH_RINGS / 2 - 1);
- if (2 * entry->small_pkts > entry->big_pkts)
- tx_ind += MLX4_EN_NUM_HASH_RINGS / 2;
- entry->small_pkts = entry->big_pkts = 0;
- entry->ring = tx_ind;
- }
+ /* hash mbuf */
+ queue_index = mlx4_en_hashmbuf(MLX4_F_HASHL3 | MLX4_F_HASHL4, mb, hashrandom);
- entry->cnt++;
- if (mb->m_pkthdr.len > MLX4_EN_SMALL_PKT_SIZE)
- entry->big_pkts++;
- else
- entry->small_pkts++;
- return entry->ring;
+ return ((queue_index % rings_p_up) + (up * rings_p_up));
}
-static void mlx4_bf_copy(unsigned long *dst, unsigned long *src, unsigned bytecnt)
+static void mlx4_bf_copy(void __iomem *dst, unsigned long *src, unsigned bytecnt)
{
__iowrite64_copy(dst, src, bytecnt / 8);
}
+static u64 mlx4_en_mac_to_u64(u8 *addr)
+{
+ u64 mac = 0;
+ int i;
+
+ for (i = 0; i < ETHER_ADDR_LEN; i++) {
+ mac <<= 8;
+ mac |= addr[i];
+ }
+ return mac;
+}
+
static int mlx4_en_xmit(struct net_device *dev, int tx_ind, struct mbuf **mbp)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
@@ -701,57 +758,73 @@ static int mlx4_en_xmit(struct net_device *dev, int tx_ind, struct mbuf **mbp)
int desc_size;
int real_size;
dma_addr_t dma;
- u32 index, bf_index;
+ u32 index, bf_index, ring_size;
__be32 op_own;
u16 vlan_tag = 0;
int i;
int lso_header_size;
bool bounce = false;
+ bool inl = false;
struct mbuf *mb;
+ mb = *mbp;
int defrag = 1;
- ring = &priv->tx_ring[tx_ind];
- mb = *mbp;
if (!priv->port_up)
goto tx_drop;
+ ring = priv->tx_ring[tx_ind];
+ ring_size = ring->size;
+ inl = is_inline(mb, ring->inline_thold);
+
retry:
- real_size = get_real_size(mb, dev, &nr_segs, &lso_header_size);
+ real_size = get_real_size(mb, dev, &nr_segs, &lso_header_size, inl);
if (unlikely(!real_size))
goto tx_drop;
- /* Allign descriptor to TXBB size */
+ /* Align descriptor to TXBB size */
desc_size = ALIGN(real_size, TXBB_SIZE);
nr_txbb = desc_size / TXBB_SIZE;
if (unlikely(nr_txbb > MAX_DESC_TXBBS)) {
if (defrag) {
- mb = m_defrag(*mbp, M_NOWAIT);
- if (mb == NULL) {
- mb = *mbp;
- goto tx_drop;
- }
- *mbp = mb;
- defrag = 0;
- goto retry;
- }
+ mb = m_defrag(*mbp, M_NOWAIT);
+ if (mb == NULL) {
+ mb = *mbp;
+ goto tx_drop;
+ }
+ *mbp = mb;
+ defrag = 0;
+ goto retry;
+ }
+ en_warn(priv, "Oversized header or SG list\n");
goto tx_drop;
}
- /* Check available TXBBs And 2K spare for prefetch */
- if (unlikely(((int)(ring->prod - ring->cons)) >
- ring->size - HEADROOM - MAX_DESC_TXBBS)) {
+ /* Obtain VLAN information if present */
+ if (mb->m_flags & M_VLANTAG) {
+ vlan_tag = mb->m_pkthdr.ether_vtag;
+ }
+
+ /* Check available TXBBs and 2K spare for prefetch
+ * Even if netif_tx_stop_queue() will be called
+ * driver will send current packet to ensure
+ * that at least one completion will be issued after
+ * stopping the queue
+ */
+ if (unlikely((int)(ring->prod - ring->cons) > ring->full_size)) {
/* every full Tx ring stops queue */
if (ring->blocked == 0)
- atomic_add_int(&priv->blocked, 1);
+ atomic_add_int(&priv->blocked, 1);
+ /* Set HW-queue-is-full flag */
atomic_set_int(&dev->if_drv_flags, IFF_DRV_OACTIVE);
ring->blocked = 1;
priv->port_stats.queue_stopped++;
+ ring->queue_stopped++;
/* Use interrupts to find out when queue opened */
- cq = &priv->tx_cq[tx_ind];
+ cq = priv->tx_cq[tx_ind];
mlx4_en_arm_cq(priv, cq);
return EBUSY;
- }
+ }
/* Track current inflight packets for performance analysis */
AVG_PERF_COUNTER(priv->pstats.inflight_avg,
@@ -763,128 +836,135 @@ retry:
/* See if we have enough space for whole descriptor TXBB for setting
* SW ownership on next descriptor; if not, use a bounce buffer. */
- if (likely(index + nr_txbb <= ring->size))
+ if (likely(index + nr_txbb <= ring_size))
tx_desc = ring->buf + index * TXBB_SIZE;
else {
tx_desc = (struct mlx4_en_tx_desc *) ring->bounce_buf;
bounce = true;
}
+ /* Save mb in tx_info ring */
+ tx_info = &ring->tx_info[index];
+ tx_info->mb = mb;
+ tx_info->nr_txbb = nr_txbb;
+ tx_info->nr_segs = nr_segs;
+
+ if (lso_header_size) {
+ memcpy(tx_desc->lso.header, mb->m_data, lso_header_size);
+ data = ((void *)&tx_desc->lso + ALIGN(lso_header_size + 4,
+ DS_SIZE));
+ /* lso header is part of m_data.
+ * need to omit when mapping DMA */
+ mb->m_data += lso_header_size;
+ mb->m_len -= lso_header_size;
+ }
+ else
+ data = &tx_desc->data;
+
+ /* valid only for none inline segments */
+ tx_info->data_offset = (void *)data - (void *)tx_desc;
+
+ if (inl) {
+ tx_info->inl = 1;
+ } else {
+ for (i = 0, m = mb; i < nr_segs; i++, m = m->m_next) {
+ if (m->m_len == 0) {
+ i--;
+ continue;
+ }
+ dma = pci_map_single(mdev->dev->pdev, m->m_data,
+ m->m_len, PCI_DMA_TODEVICE);
+ data->addr = cpu_to_be64(dma);
+ data->lkey = cpu_to_be32(mdev->mr.key);
+ wmb();
+ data->byte_count = cpu_to_be32(m->m_len);
+ data++;
+ }
+ if (lso_header_size) {
+ mb->m_data -= lso_header_size;
+ mb->m_len += lso_header_size;
+ }
+ tx_info->inl = 0;
+ }
+
+
/* Prepare ctrl segement apart opcode+ownership, which depends on
* whether LSO is used */
- if (mb->m_flags & M_VLANTAG)
- vlan_tag = mb->m_pkthdr.ether_vtag;
tx_desc->ctrl.vlan_tag = cpu_to_be16(vlan_tag);
- tx_desc->ctrl.ins_vlan = MLX4_WQE_CTRL_INS_VLAN * !!vlan_tag;
+ tx_desc->ctrl.ins_vlan = MLX4_WQE_CTRL_INS_VLAN *
+ !!vlan_tag;
tx_desc->ctrl.fence_size = (real_size / 16) & 0x3f;
- tx_desc->ctrl.srcrb_flags = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE |
- MLX4_WQE_CTRL_SOLICITED);
- if (mb->m_pkthdr.csum_flags & (CSUM_IP|CSUM_TCP|CSUM_UDP)) {
- if (mb->m_pkthdr.csum_flags & CSUM_IP)
- tx_desc->ctrl.srcrb_flags |=
- cpu_to_be32(MLX4_WQE_CTRL_IP_CSUM);
- if (mb->m_pkthdr.csum_flags & (CSUM_TCP|CSUM_UDP))
- tx_desc->ctrl.srcrb_flags |=
- cpu_to_be32(MLX4_WQE_CTRL_TCP_UDP_CSUM);
+ tx_desc->ctrl.srcrb_flags = priv->ctrl_flags;
+ if (mb->m_pkthdr.csum_flags & (CSUM_IP | CSUM_TSO |
+ CSUM_TCP | CSUM_UDP | CSUM_TCP_IPV6 | CSUM_UDP_IPV6)) {
+ if (mb->m_pkthdr.csum_flags & (CSUM_IP | CSUM_TSO))
+ tx_desc->ctrl.srcrb_flags |= cpu_to_be32(MLX4_WQE_CTRL_IP_CSUM);
+ if (mb->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP |
+ CSUM_UDP_IPV6 | CSUM_TCP_IPV6 | CSUM_TSO))
+ tx_desc->ctrl.srcrb_flags |= cpu_to_be32(MLX4_WQE_CTRL_TCP_UDP_CSUM);
priv->port_stats.tx_chksum_offload++;
- }
+ ring->tx_csum++;
+ }
if (unlikely(priv->validate_loopback)) {
/* Copy dst mac address to wqe */
- struct ether_header *ethh;
- u64 mac;
- u32 mac_l, mac_h;
-
- ethh = mtod(mb, struct ether_header *);
- mac = mlx4_en_mac_to_u64(ethh->ether_dhost);
- if (mac) {
- mac_h = (u32) ((mac & 0xffff00000000ULL) >> 16);
- mac_l = (u32) (mac & 0xffffffff);
- tx_desc->ctrl.srcrb_flags |= cpu_to_be32(mac_h);
- tx_desc->ctrl.imm = cpu_to_be32(mac_l);
- }
+ struct ether_header *ethh;
+ u64 mac;
+ u32 mac_l, mac_h;
+
+ ethh = mtod(mb, struct ether_header *);
+ mac = mlx4_en_mac_to_u64(ethh->ether_dhost);
+ if (mac) {
+ mac_h = (u32) ((mac & 0xffff00000000ULL) >> 16);
+ mac_l = (u32) (mac & 0xffffffff);
+ tx_desc->ctrl.srcrb_flags |= cpu_to_be32(mac_h);
+ tx_desc->ctrl.imm = cpu_to_be32(mac_l);
+ }
}
/* Handle LSO (TSO) packets */
if (lso_header_size) {
int segsz;
-
/* Mark opcode as LSO */
op_own = cpu_to_be32(MLX4_OPCODE_LSO | (1 << 6)) |
- ((ring->prod & ring->size) ?
+ ((ring->prod & ring_size) ?
cpu_to_be32(MLX4_EN_BIT_DESC_OWN) : 0);
/* Fill in the LSO prefix */
tx_desc->lso.mss_hdr_size = cpu_to_be32(
mb->m_pkthdr.tso_segsz << 16 | lso_header_size);
- /* Copy headers;
- * note that we already verified that it is linear */
- memcpy(tx_desc->lso.header, mb->m_data, lso_header_size);
- data = ((void *) &tx_desc->lso +
- ALIGN(lso_header_size + 4, DS_SIZE));
-
- priv->port_stats.tso_packets++;
- segsz = mb->m_pkthdr.tso_segsz;
- i = ((mb->m_pkthdr.len - lso_header_size) / segsz) +
- !!((mb->m_pkthdr.len - lso_header_size) % segsz);
- ring->bytes += mb->m_pkthdr.len + (i - 1) * lso_header_size;
- ring->packets += i;
- mb->m_data += lso_header_size;
- mb->m_len -= lso_header_size;
+ priv->port_stats.tso_packets++;
+ segsz = mb->m_pkthdr.tso_segsz;
+ i = ((mb->m_pkthdr.len - lso_header_size + segsz - 1) / segsz);
+ tx_info->nr_bytes= mb->m_pkthdr.len + (i - 1) * lso_header_size;
+ ring->packets += i;
} else {
/* Normal (Non LSO) packet */
op_own = cpu_to_be32(MLX4_OPCODE_SEND) |
- ((ring->prod & ring->size) ?
+ ((ring->prod & ring_size) ?
cpu_to_be32(MLX4_EN_BIT_DESC_OWN) : 0);
- data = &tx_desc->data;
- ring->bytes += max(mb->m_pkthdr.len,
- (unsigned int)ETHER_MIN_LEN - ETHER_CRC_LEN);
+ tx_info->nr_bytes = max(mb->m_pkthdr.len,
+ (unsigned int)ETHER_MIN_LEN - ETHER_CRC_LEN);
ring->packets++;
}
+ ring->bytes += tx_info->nr_bytes;
AVG_PERF_COUNTER(priv->pstats.tx_pktsz_avg, mb->m_pkthdr.len);
- /* Save mb in tx_info ring */
- tx_info = &ring->tx_info[index];
- tx_info->mb = mb;
- tx_info->nr_txbb = nr_txbb;
- tx_info->nr_segs = nr_segs;
- /* valid only for non inline segments */
- tx_info->data_offset = (void *) data - (void *) tx_desc;
-
- if (!is_inline(mb)) {
- for (i = 0, m = mb; i < nr_segs; i++, m = m->m_next) {
- if (m->m_len == 0) {
- i--;
- continue;
- }
- dma = pci_map_single(mdev->dev->pdev, m->m_data,
- m->m_len, PCI_DMA_TODEVICE);
- data->addr = cpu_to_be64(dma);
- data->lkey = cpu_to_be32(mdev->mr.key);
- wmb();
- data->byte_count = cpu_to_be32(m->m_len);
- data++;
- }
- if (lso_header_size) {
- mb->m_data -= lso_header_size;
- mb->m_len += lso_header_size;
- }
- tx_info->inl = 0;
- } else {
+ if (tx_info->inl) {
build_inline_wqe(tx_desc, mb, real_size, &vlan_tag, tx_ind);
tx_info->inl = 1;
}
ring->prod += nr_txbb;
+
/* If we used a bounce buffer then copy descriptor back into place */
- if (bounce)
+ if (unlikely(bounce))
tx_desc = mlx4_en_bounce_to_desc(priv, ring, index, desc_size);
-
if (ring->bf_enabled && desc_size <= MAX_BF && !bounce && !vlan_tag) {
- *(u32 *) (&tx_desc->ctrl.vlan_tag) |= ring->doorbell_qpn;
+ *(__be32 *) (&tx_desc->ctrl.vlan_tag) |= cpu_to_be32(ring->doorbell_qpn);
op_own |= htonl((bf_index & 0xffff) << 8);
/* Ensure new descirptor hits memory
* before setting ownership of this descriptor to HW */
@@ -905,19 +985,16 @@ retry:
wmb();
tx_desc->ctrl.owner_opcode = op_own;
wmb();
- writel(ring->doorbell_qpn, ring->bf.uar->map + MLX4_SEND_DOORBELL);
+ writel(cpu_to_be32(ring->doorbell_qpn), ring->bf.uar->map + MLX4_SEND_DOORBELL);
}
return 0;
-
tx_drop:
*mbp = NULL;
m_freem(mb);
- ring->errors++;
return EINVAL;
}
-
static int
mlx4_en_transmit_locked(struct ifnet *dev, int tx_ind, struct mbuf *m)
{
@@ -926,12 +1003,12 @@ mlx4_en_transmit_locked(struct ifnet *dev, int tx_ind, struct mbuf *m)
struct mbuf *next;
int enqueued, err = 0;
- ring = &priv->tx_ring[tx_ind];
+ ring = priv->tx_ring[tx_ind];
if ((dev->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
IFF_DRV_RUNNING || priv->port_up == 0) {
if (m != NULL)
err = drbr_enqueue(dev, ring->br, m);
- return (err);
+ return (err);
}
enqueued = 0;
@@ -951,11 +1028,6 @@ mlx4_en_transmit_locked(struct ifnet *dev, int tx_ind, struct mbuf *m)
}
drbr_advance(dev, ring->br);
enqueued++;
- dev->if_obytes += next->m_pkthdr.len;
- if (next->m_flags & M_MCAST)
- dev->if_omcasts++;
- /* Send a copy of the frame to the BPF listener */
- ETHER_BPF_MTAP(dev, next);
if ((dev->if_drv_flags & IFF_DRV_RUNNING) == 0)
break;
}
@@ -974,12 +1046,11 @@ mlx4_en_tx_que(void *context, int pending)
struct net_device *dev;
struct mlx4_en_cq *cq;
int tx_ind;
-
cq = context;
dev = cq->dev;
priv = dev->if_softc;
tx_ind = cq->ring;
- ring = &priv->tx_ring[tx_ind];
+ ring = priv->tx_ring[tx_ind];
if (dev->if_drv_flags & IFF_DRV_RUNNING) {
mlx4_en_xmit_poll(priv, tx_ind);
spin_lock(&ring->tx_lock);
@@ -998,12 +1069,13 @@ mlx4_en_transmit(struct ifnet *dev, struct mbuf *m)
int i = 0, err = 0;
/* Which queue to use */
- if ((m->m_flags & (M_FLOWID | M_VLANTAG)) == M_FLOWID)
- i = m->m_pkthdr.flowid % (MLX4_EN_NUM_HASH_RINGS - 1);
- else
+ if ((m->m_flags & (M_FLOWID | M_VLANTAG)) == M_FLOWID) {
+ i = m->m_pkthdr.flowid % (priv->tx_ring_num - 1);
+ }
+ else {
i = mlx4_en_select_queue(dev, m);
-
- ring = &priv->tx_ring[i];
+ }
+ ring = priv->tx_ring[i];
if (spin_trylock(&ring->tx_lock)) {
err = mlx4_en_transmit_locked(dev, i, m);
@@ -1012,7 +1084,7 @@ mlx4_en_transmit(struct ifnet *dev, struct mbuf *m)
mlx4_en_xmit_poll(priv, i);
} else {
err = drbr_enqueue(dev, ring->br, m);
- cq = &priv->tx_cq[i];
+ cq = priv->tx_cq[i];
taskqueue_enqueue(cq->tq, &cq->cq_task);
}
@@ -1026,10 +1098,11 @@ void
mlx4_en_qflush(struct ifnet *dev)
{
struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_tx_ring *ring = priv->tx_ring;
+ struct mlx4_en_tx_ring *ring;
struct mbuf *m;
- for (int i = 0; i < priv->tx_ring_num; i++, ring++) {
+ for (int i = 0; i < priv->tx_ring_num; i++) {
+ ring = priv->tx_ring[i];
spin_lock(&ring->tx_lock);
while ((m = buf_ring_dequeue_sc(ring->br)) != NULL)
m_freem(m);
diff --git a/sys/ofed/drivers/net/mlx4/eq.c b/sys/ofed/drivers/net/mlx4/eq.c
index b585e8c..31fafbe 100644
--- a/sys/ofed/drivers/net/mlx4/eq.c
+++ b/sys/ofed/drivers/net/mlx4/eq.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005, 2006, 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
* Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -33,6 +33,7 @@
#include <linux/interrupt.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <linux/mm.h>
#include <linux/dma-mapping.h>
@@ -86,6 +87,8 @@ static u64 get_async_ev_mask(struct mlx4_dev *dev)
u64 async_ev_mask = MLX4_ASYNC_EVENT_MASK;
if (dev->caps.flags & MLX4_DEV_CAP_FLAG_PORT_MNG_CHG_EV)
async_ev_mask |= (1ull << MLX4_EVENT_TYPE_PORT_MNG_CHG_EVENT);
+ if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RECOVERABLE_ERROR_EVENT)
+ async_ev_mask |= (1ull << MLX4_EVENT_TYPE_RECOVERABLE_ERROR_EVENT);
return async_ev_mask;
}
@@ -147,12 +150,9 @@ void mlx4_gen_slave_eqe(struct work_struct *work)
/* All active slaves need to receive the event */
if (slave == ALL_SLAVES) {
for (i = 0; i < dev->num_slaves; i++) {
- if (i != dev->caps.function &&
- master->slave_state[i].active)
- if (mlx4_GEN_EQE(dev, i, eqe))
- mlx4_warn(dev, "Failed to "
- " generate event "
- "for slave %d\n", i);
+ if (mlx4_GEN_EQE(dev, i, eqe))
+ mlx4_warn(dev, "Failed to generate "
+ "event for slave %d\n", i);
}
} else {
if (mlx4_GEN_EQE(dev, slave, eqe))
@@ -197,13 +197,13 @@ static void mlx4_slave_event(struct mlx4_dev *dev, int slave,
struct mlx4_eqe *eqe)
{
struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_slave_state *s_slave =
- &priv->mfunc.master.slave_state[slave];
- if (!s_slave->active) {
- /*mlx4_warn(dev, "Trying to pass event to inactive slave\n");*/
+ if (slave < 0 || slave >= dev->num_slaves ||
+ slave == dev->caps.function)
+ return;
+
+ if (!priv->mfunc.master.slave_state[slave].active)
return;
- }
slave_event(dev, slave, eqe);
}
@@ -375,7 +375,7 @@ out:
EXPORT_SYMBOL(set_and_calc_slave_port_state);
-int mlx4_gen_slaves_port_mgt_ev(struct mlx4_dev *dev, u8 port, int attr)
+int mlx4_gen_slaves_port_mgt_ev(struct mlx4_dev *dev, u8 port, int attr, u16 sm_lid, u8 sm_sl)
{
struct mlx4_eqe eqe;
@@ -386,6 +386,12 @@ int mlx4_gen_slaves_port_mgt_ev(struct mlx4_dev *dev, u8 port, int attr)
eqe.event.port_mgmt_change.port = port;
eqe.event.port_mgmt_change.params.port_info.changed_attr =
cpu_to_be32((u32) attr);
+ if (attr & MSTR_SM_CHANGE_MASK) {
+ eqe.event.port_mgmt_change.params.port_info.mstr_sm_lid =
+ cpu_to_be16(sm_lid);
+ eqe.event.port_mgmt_change.params.port_info.mstr_sm_sl =
+ sm_sl;
+ }
slave_event(dev, ALL_SLAVES, &eqe);
return 0;
@@ -446,6 +452,7 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
int i;
enum slave_port_gen_event gen_event;
unsigned long flags;
+ struct mlx4_vport_state *s_info;
while ((eqe = next_eqe_sw(eq, dev->caps.eqe_factor))) {
/*
@@ -495,8 +502,9 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
break;
case MLX4_EVENT_TYPE_SRQ_LIMIT:
- mlx4_warn(dev, "%s: MLX4_EVENT_TYPE_SRQ_LIMIT\n",
- __func__);
+ mlx4_dbg(dev, "%s: MLX4_EVENT_TYPE_SRQ_LIMIT\n",
+ __func__);
+ /* fall through */
case MLX4_EVENT_TYPE_SRQ_CATAS_ERROR:
if (mlx4_is_master(dev)) {
/* forward only to slave owning the SRQ */
@@ -513,17 +521,15 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
eq->eqn, eq->cons_index, ret);
break;
}
- mlx4_warn(dev, "%s: slave:%d, srq_no:0x%x,"
- " event: %02x(%02x)\n", __func__,
- slave,
- be32_to_cpu(eqe->event.srq.srqn),
- eqe->type, eqe->subtype);
+ mlx4_dbg(dev, "%s: slave:%d, srq_no:0x%x, event: %02x(%02x)\n",
+ __func__, slave,
+ be32_to_cpu(eqe->event.srq.srqn),
+ eqe->type, eqe->subtype);
if (!ret && slave != dev->caps.function) {
- mlx4_warn(dev, "%s: sending event "
- "%02x(%02x) to slave:%d\n",
- __func__, eqe->type,
- eqe->subtype, slave);
+ mlx4_dbg(dev, "%s: sending event %02x(%02x) to slave:%d\n",
+ __func__, eqe->type,
+ eqe->subtype, slave);
mlx4_slave_event(dev, slave, eqe);
break;
}
@@ -554,7 +560,9 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
mlx4_dbg(dev, "%s: Sending MLX4_PORT_CHANGE_SUBTYPE_DOWN"
" to slave: %d, port:%d\n",
__func__, i, port);
- mlx4_slave_event(dev, i, eqe);
+ s_info = &priv->mfunc.master.vf_oper[slave].vport[port].state;
+ if (IFLA_VF_LINK_STATE_AUTO == s_info->link_state)
+ mlx4_slave_event(dev, i, eqe);
} else { /* IB port */
set_and_calc_slave_port_state(dev, i, port,
MLX4_PORT_STATE_DEV_EVENT_PORT_DOWN,
@@ -578,7 +586,9 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
for (i = 0; i < dev->num_slaves; i++) {
if (i == mlx4_master_func_num(dev))
continue;
- mlx4_slave_event(dev, i, eqe);
+ s_info = &priv->mfunc.master.vf_oper[slave].vport[port].state;
+ if (IFLA_VF_LINK_STATE_AUTO == s_info->link_state)
+ mlx4_slave_event(dev, i, eqe);
}
else /* IB port */
/* port-up event will be sent to a slave when the
@@ -635,11 +645,18 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
"for non master device\n");
break;
}
+
memcpy(&priv->mfunc.master.comm_arm_bit_vector,
eqe->event.comm_channel_arm.bit_vec,
sizeof eqe->event.comm_channel_arm.bit_vec);
- queue_work(priv->mfunc.master.comm_wq,
- &priv->mfunc.master.comm_work);
+
+ if (!queue_work(priv->mfunc.master.comm_wq,
+ &priv->mfunc.master.comm_work))
+ mlx4_warn(dev, "Failed to queue comm channel work\n");
+
+ if (!queue_work(priv->mfunc.master.comm_wq,
+ &priv->mfunc.master.arm_comm_work))
+ mlx4_warn(dev, "Failed to queue arm comm channel work\n");
break;
case MLX4_EVENT_TYPE_FLR_EVENT:
@@ -704,6 +721,27 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
(unsigned long) eqe);
break;
+ case MLX4_EVENT_TYPE_RECOVERABLE_ERROR_EVENT:
+ switch (eqe->subtype) {
+ case MLX4_RECOVERABLE_ERROR_EVENT_SUBTYPE_BAD_CABLE:
+ mlx4_warn(dev, "Bad cable detected on port %u\n",
+ eqe->event.bad_cable.port);
+ break;
+ case MLX4_RECOVERABLE_ERROR_EVENT_SUBTYPE_UNSUPPORTED_CABLE:
+ mlx4_warn(dev, "Unsupported cable detected\n");
+ break;
+ default:
+ mlx4_dbg(dev, "Unhandled recoverable error event "
+ "detected: %02x(%02x) on EQ %d at index %u. "
+ "owner=%x, nent=0x%x, ownership=%s\n",
+ eqe->type, eqe->subtype, eq->eqn,
+ eq->cons_index, eqe->owner, eq->nent,
+ !!(eqe->owner & 0x80) ^
+ !!(eq->cons_index & eq->nent) ? "HW" : "SW");
+ break;
+ }
+ break;
+
case MLX4_EVENT_TYPE_EEC_CATAS_ERROR:
case MLX4_EVENT_TYPE_ECC_DETECT:
default:
@@ -747,7 +785,6 @@ static irqreturn_t mlx4_interrupt(int irq, void *dev_ptr)
int work = 0;
int i;
-
writel(priv->eq_table.clr_mask, priv->eq_table.clr_int);
for (i = 0; i < dev->caps.num_comp_vectors + 1; ++i)
@@ -777,7 +814,7 @@ int mlx4_MAP_EQ_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_slave_event_eq_info *event_eq =
priv->mfunc.master.slave_state[slave].event_eq;
u32 in_modifier = vhcr->in_modifier;
- u32 eqn = in_modifier & 0x1FF;
+ u32 eqn = in_modifier & 0x3FF;
u64 in_param = vhcr->in_param;
int err = 0;
int i;
@@ -956,7 +993,7 @@ err_out_free_mtt:
mlx4_mtt_cleanup(dev, &eq->mtt);
err_out_free_eq:
- mlx4_bitmap_free(&priv->eq_table.bitmap, eq->eqn);
+ mlx4_bitmap_free(&priv->eq_table.bitmap, eq->eqn, MLX4_USE_RR);
err_out_free_pages:
for (i = 0; i < npages; ++i)
@@ -1011,7 +1048,7 @@ static void mlx4_free_eq(struct mlx4_dev *dev,
eq->page_list[i].map);
kfree(eq->page_list);
- mlx4_bitmap_free(&priv->eq_table.bitmap, eq->eqn);
+ mlx4_bitmap_free(&priv->eq_table.bitmap, eq->eqn, MLX4_USE_RR);
mlx4_free_cmd_mailbox(dev, mailbox);
}
@@ -1306,7 +1343,7 @@ int mlx4_test_interrupts(struct mlx4_dev *dev)
}
EXPORT_SYMBOL(mlx4_test_interrupts);
-int mlx4_assign_eq(struct mlx4_dev *dev, char *name, int *vector)
+int mlx4_assign_eq(struct mlx4_dev *dev, char* name, int * vector)
{
struct mlx4_priv *priv = mlx4_priv(dev);
diff --git a/sys/ofed/drivers/net/mlx4/fw.c b/sys/ofed/drivers/net/mlx4/fw.c
index cf079ea..93f7f71 100644
--- a/sys/ofed/drivers/net/mlx4/fw.c
+++ b/sys/ofed/drivers/net/mlx4/fw.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
- * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005, 2006, 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
* Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -32,8 +32,10 @@
* SOFTWARE.
*/
+#include <linux/etherdevice.h>
#include <linux/mlx4/cmd.h>
#include <linux/module.h>
+#include <linux/cache.h>
#include "fw.h"
#include "icm.h"
@@ -106,6 +108,7 @@ static void dump_dev_cap_flags(struct mlx4_dev *dev, u64 flags)
[40] = "UDP RSS support",
[41] = "Unicast VEP steering support",
[42] = "Multicast VEP steering support",
+ [44] = "Cross-channel (sync_qp) operations support",
[48] = "Counters support",
[59] = "Port management change event support",
[60] = "eSwitch support",
@@ -126,7 +129,18 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags)
[0] = "RSS support",
[1] = "RSS Toeplitz Hash Function support",
[2] = "RSS XOR Hash Function support",
- [3] = "Device manage flow steering support"
+ [3] = "Device manage flow steering support",
+ [4] = "FSM (MAC unti-spoofing) support",
+ [5] = "VST (control vlan insertion/stripping) support",
+ [6] = "Dynamic QP updates support",
+ [7] = "Loopback source checks support",
+ [8] = "Device managed flow steering IPoIB support",
+ [9] = "ETS configuration support",
+ [10] = "ETH backplane autoneg report",
+ [11] = "Ethernet Flow control statistics support",
+ [12] = "Recoverable error events support",
+ [13] = "Time stamping support",
+ [14] = "Report driver version to FW support"
};
int i;
@@ -170,7 +184,7 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_cmd_info *cmd)
{
struct mlx4_priv *priv = mlx4_priv(dev);
- u8 field;
+ u8 field, port;
u32 size;
int err = 0;
@@ -178,23 +192,32 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
#define QUERY_FUNC_CAP_NUM_PORTS_OFFSET 0x1
#define QUERY_FUNC_CAP_PF_BHVR_OFFSET 0x4
#define QUERY_FUNC_CAP_FMR_OFFSET 0x8
-#define QUERY_FUNC_CAP_QP_QUOTA_OFFSET 0x10
-#define QUERY_FUNC_CAP_CQ_QUOTA_OFFSET 0x14
-#define QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET 0x18
-#define QUERY_FUNC_CAP_MPT_QUOTA_OFFSET 0x20
-#define QUERY_FUNC_CAP_MTT_QUOTA_OFFSET 0x24
-#define QUERY_FUNC_CAP_MCG_QUOTA_OFFSET 0x28
+#define QUERY_FUNC_CAP_QP_QUOTA_OFFSET_DEP 0x10
+#define QUERY_FUNC_CAP_CQ_QUOTA_OFFSET_DEP 0x14
+#define QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET_DEP 0x18
+#define QUERY_FUNC_CAP_MPT_QUOTA_OFFSET_DEP 0x20
+#define QUERY_FUNC_CAP_MTT_QUOTA_OFFSET_DEP 0x24
+#define QUERY_FUNC_CAP_MCG_QUOTA_OFFSET_DEP 0x28
#define QUERY_FUNC_CAP_MAX_EQ_OFFSET 0x2c
#define QUERY_FUNC_CAP_RESERVED_EQ_OFFSET 0x30
+#define QUERY_FUNC_CAP_QP_QUOTA_OFFSET 0x50
+#define QUERY_FUNC_CAP_CQ_QUOTA_OFFSET 0x54
+#define QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET 0x58
+#define QUERY_FUNC_CAP_MPT_QUOTA_OFFSET 0x60
+#define QUERY_FUNC_CAP_MTT_QUOTA_OFFSET 0x64
+#define QUERY_FUNC_CAP_MCG_QUOTA_OFFSET 0x68
+
#define QUERY_FUNC_CAP_FMR_FLAG 0x80
#define QUERY_FUNC_CAP_FLAG_RDMA 0x40
#define QUERY_FUNC_CAP_FLAG_ETH 0x80
+#define QUERY_FUNC_CAP_FLAG_QUOTAS 0x10
/* when opcode modifier = 1 */
#define QUERY_FUNC_CAP_PHYS_PORT_OFFSET 0x3
-#define QUERY_FUNC_CAP_RDMA_PROPS_OFFSET 0x8
-#define QUERY_FUNC_CAP_ETH_PROPS_OFFSET 0xc
+#define QUERY_FUNC_CAP_FLAGS0_OFFSET 0x8
+#define QUERY_FUNC_CAP_FLAGS1_OFFSET 0xc
+#define QUERY_FUNC_CAP_COUNTER_INDEX_OFFSET 0xd
#define QUERY_FUNC_CAP_QP0_TUNNEL 0x10
#define QUERY_FUNC_CAP_QP0_PROXY 0x14
@@ -203,35 +226,45 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
#define QUERY_FUNC_CAP_ETH_PROPS_FORCE_MAC 0x40
#define QUERY_FUNC_CAP_ETH_PROPS_FORCE_VLAN 0x80
+#define QUERY_FUNC_CAP_PROPS_DEF_COUNTER 0x20
#define QUERY_FUNC_CAP_RDMA_PROPS_FORCE_PHY_WQE_GID 0x80
if (vhcr->op_modifier == 1) {
+ port = vhcr->in_modifier; /* phys-port = logical-port */
+ MLX4_PUT(outbox->buf, port, QUERY_FUNC_CAP_PHYS_PORT_OFFSET);
+
field = 0;
- /* ensure force vlan and force mac bits are not set */
- MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_ETH_PROPS_OFFSET);
/* ensure that phy_wqe_gid bit is not set */
- MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_RDMA_PROPS_OFFSET);
+ MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS0_OFFSET);
- field = vhcr->in_modifier; /* phys-port = logical-port */
- MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_PHYS_PORT_OFFSET);
+ /* ensure force vlan and force mac bits are not set
+ * and that default counter bit is set
+ */
+ field = QUERY_FUNC_CAP_PROPS_DEF_COUNTER; /* def counter */
+ MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS1_OFFSET);
+
+ /* There is always default counter legal or sink counter */
+ field = mlx4_get_default_counter_index(dev, slave, vhcr->in_modifier);
+ MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_COUNTER_INDEX_OFFSET);
/* size is now the QP number */
- size = dev->phys_caps.base_tunnel_sqpn + 8 * slave + field - 1;
+ size = dev->phys_caps.base_tunnel_sqpn + 8 * slave + port - 1;
MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP0_TUNNEL);
size += 2;
MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP1_TUNNEL);
- size = dev->phys_caps.base_proxy_sqpn + 8 * slave + field - 1;
+ size = dev->phys_caps.base_proxy_sqpn + 8 * slave + port - 1;
MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP0_PROXY);
size += 2;
MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP1_PROXY);
} else if (vhcr->op_modifier == 0) {
- /* enable rdma and ethernet interfaces */
- field = (QUERY_FUNC_CAP_FLAG_ETH | QUERY_FUNC_CAP_FLAG_RDMA);
+ /* enable rdma and ethernet interfaces, and new quota locations */
+ field = (QUERY_FUNC_CAP_FLAG_ETH | QUERY_FUNC_CAP_FLAG_RDMA |
+ QUERY_FUNC_CAP_FLAG_QUOTAS);
MLX4_PUT(outbox->buf, field, QUERY_FUNC_CAP_FLAGS_OFFSET);
field = dev->caps.num_ports;
@@ -245,12 +278,18 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
size = priv->mfunc.master.res_tracker.res_alloc[RES_QP].quota[slave];
MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP_QUOTA_OFFSET);
+ size = dev->caps.num_qps;
+ MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_QP_QUOTA_OFFSET_DEP);
size = priv->mfunc.master.res_tracker.res_alloc[RES_SRQ].quota[slave];
MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET);
+ size = dev->caps.num_srqs;
+ MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET_DEP);
size = priv->mfunc.master.res_tracker.res_alloc[RES_CQ].quota[slave];
MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET);
+ size = dev->caps.num_cqs;
+ MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET_DEP);
size = dev->caps.num_eqs;
MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MAX_EQ_OFFSET);
@@ -260,12 +299,17 @@ int mlx4_QUERY_FUNC_CAP_wrapper(struct mlx4_dev *dev, int slave,
size = priv->mfunc.master.res_tracker.res_alloc[RES_MPT].quota[slave];
MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET);
+ size = dev->caps.num_mpts;
+ MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET_DEP);
size = priv->mfunc.master.res_tracker.res_alloc[RES_MTT].quota[slave];
MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET);
+ size = dev->caps.num_mtts;
+ MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET_DEP);
size = dev->caps.num_mgms + dev->caps.num_amgms;
MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET);
+ MLX4_PUT(outbox->buf, size, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET_DEP);
} else
err = -EINVAL;
@@ -280,7 +324,7 @@ int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u32 gen_or_port,
u32 *outbox;
u8 field, op_modifier;
u32 size;
- int err = 0;
+ int err = 0, quotas = 0;
op_modifier = !!gen_or_port; /* 0 = general, 1 = logical port */
@@ -304,6 +348,7 @@ int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u32 gen_or_port,
goto out;
}
func_cap->flags = field;
+ quotas = !!(func_cap->flags & QUERY_FUNC_CAP_FLAG_QUOTAS);
MLX4_GET(field, outbox, QUERY_FUNC_CAP_NUM_PORTS_OFFSET);
func_cap->num_ports = field;
@@ -311,29 +356,50 @@ int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u32 gen_or_port,
MLX4_GET(size, outbox, QUERY_FUNC_CAP_PF_BHVR_OFFSET);
func_cap->pf_context_behaviour = size;
- MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP_QUOTA_OFFSET);
- func_cap->qp_quota = size & 0xFFFFFF;
+ if (quotas) {
+ MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP_QUOTA_OFFSET);
+ func_cap->qp_quota = size & 0xFFFFFF;
+
+ MLX4_GET(size, outbox, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET);
+ func_cap->srq_quota = size & 0xFFFFFF;
+
+ MLX4_GET(size, outbox, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET);
+ func_cap->cq_quota = size & 0xFFFFFF;
+
+ MLX4_GET(size, outbox, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET);
+ func_cap->mpt_quota = size & 0xFFFFFF;
+
+ MLX4_GET(size, outbox, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET);
+ func_cap->mtt_quota = size & 0xFFFFFF;
+
+ MLX4_GET(size, outbox, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET);
+ func_cap->mcg_quota = size & 0xFFFFFF;
+
+ } else {
+ MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP_QUOTA_OFFSET_DEP);
+ func_cap->qp_quota = size & 0xFFFFFF;
- MLX4_GET(size, outbox, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET);
- func_cap->srq_quota = size & 0xFFFFFF;
+ MLX4_GET(size, outbox, QUERY_FUNC_CAP_SRQ_QUOTA_OFFSET_DEP);
+ func_cap->srq_quota = size & 0xFFFFFF;
- MLX4_GET(size, outbox, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET);
- func_cap->cq_quota = size & 0xFFFFFF;
+ MLX4_GET(size, outbox, QUERY_FUNC_CAP_CQ_QUOTA_OFFSET_DEP);
+ func_cap->cq_quota = size & 0xFFFFFF;
+ MLX4_GET(size, outbox, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET_DEP);
+ func_cap->mpt_quota = size & 0xFFFFFF;
+
+ MLX4_GET(size, outbox, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET_DEP);
+ func_cap->mtt_quota = size & 0xFFFFFF;
+
+ MLX4_GET(size, outbox, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET_DEP);
+ func_cap->mcg_quota = size & 0xFFFFFF;
+ }
MLX4_GET(size, outbox, QUERY_FUNC_CAP_MAX_EQ_OFFSET);
func_cap->max_eq = size & 0xFFFFFF;
MLX4_GET(size, outbox, QUERY_FUNC_CAP_RESERVED_EQ_OFFSET);
func_cap->reserved_eq = size & 0xFFFFFF;
- MLX4_GET(size, outbox, QUERY_FUNC_CAP_MPT_QUOTA_OFFSET);
- func_cap->mpt_quota = size & 0xFFFFFF;
-
- MLX4_GET(size, outbox, QUERY_FUNC_CAP_MTT_QUOTA_OFFSET);
- func_cap->mtt_quota = size & 0xFFFFFF;
-
- MLX4_GET(size, outbox, QUERY_FUNC_CAP_MCG_QUOTA_OFFSET);
- func_cap->mcg_quota = size & 0xFFFFFF;
goto out;
}
@@ -344,7 +410,7 @@ int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u32 gen_or_port,
}
if (dev->caps.port_type[gen_or_port] == MLX4_PORT_TYPE_ETH) {
- MLX4_GET(field, outbox, QUERY_FUNC_CAP_ETH_PROPS_OFFSET);
+ MLX4_GET(field, outbox, QUERY_FUNC_CAP_FLAGS1_OFFSET);
if (field & QUERY_FUNC_CAP_ETH_PROPS_FORCE_VLAN) {
mlx4_err(dev, "VLAN is enforced on this port\n");
err = -EPROTONOSUPPORT;
@@ -357,7 +423,7 @@ int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u32 gen_or_port,
goto out;
}
} else if (dev->caps.port_type[gen_or_port] == MLX4_PORT_TYPE_IB) {
- MLX4_GET(field, outbox, QUERY_FUNC_CAP_RDMA_PROPS_OFFSET);
+ MLX4_GET(field, outbox, QUERY_FUNC_CAP_FLAGS0_OFFSET);
if (field & QUERY_FUNC_CAP_RDMA_PROPS_FORCE_PHY_WQE_GID) {
mlx4_err(dev, "phy_wqe_gid is "
"enforced on this ib port\n");
@@ -373,6 +439,14 @@ int mlx4_QUERY_FUNC_CAP(struct mlx4_dev *dev, u32 gen_or_port,
goto out;
}
+ MLX4_GET(field, outbox, QUERY_FUNC_CAP_FLAGS1_OFFSET);
+ if (field & QUERY_FUNC_CAP_PROPS_DEF_COUNTER) {
+ MLX4_GET(field, outbox, QUERY_FUNC_CAP_COUNTER_INDEX_OFFSET);
+ func_cap->def_counter_index = field;
+ } else {
+ func_cap->def_counter_index = MLX4_SINK_COUNTER_INDEX;
+ }
+
MLX4_GET(size, outbox, QUERY_FUNC_CAP_QP0_TUNNEL);
func_cap->qp0_tunnel_qpn = size & 0xFFFFFF;
@@ -466,7 +540,10 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
#define QUERY_DEV_CAP_MAX_XRC_OFFSET 0x67
#define QUERY_DEV_CAP_MAX_BASIC_COUNTERS_OFFSET 0x68
#define QUERY_DEV_CAP_MAX_EXTENDED_COUNTERS_OFFSET 0x6c
+#define QUERY_DEV_CAP_PORT_FLOWSTATS_COUNTERS_OFFSET 0x70
#define QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET 0x76
+#define QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET 0x70
+#define QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET 0x74
#define QUERY_DEV_CAP_FLOW_STEERING_MAX_QP_OFFSET 0x77
#define QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET 0x80
#define QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET 0x82
@@ -480,6 +557,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
#define QUERY_DEV_CAP_D_MPT_ENTRY_SZ_OFFSET 0x92
#define QUERY_DEV_CAP_BMME_FLAGS_OFFSET 0x94
#define QUERY_DEV_CAP_RSVD_LKEY_OFFSET 0x98
+#define QUERY_DEV_CAP_ETS_CFG_OFFSET 0x9c
#define QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET 0xa0
dev_cap->flags2 = 0;
@@ -551,16 +629,23 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev_cap->num_ports = field & 0xf;
MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MSG_SZ_OFFSET);
dev_cap->max_msg_sz = 1 << (field & 0x1f);
+ MLX4_GET(field, outbox, QUERY_DEV_CAP_PORT_FLOWSTATS_COUNTERS_OFFSET);
+ if (field & 0x10)
+ dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_FLOWSTATS_EN;
MLX4_GET(field, outbox, QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET);
if (field & 0x80)
dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_FS_EN;
+ MLX4_GET(field, outbox, QUERY_DEV_CAP_FLOW_STEERING_IPOIB_OFFSET);
+ if (field & 0x80)
+ dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_DMFS_IPOIB;
dev_cap->fs_log_max_ucast_qp_range_size = field & 0x1f;
MLX4_GET(field, outbox, QUERY_DEV_CAP_FLOW_STEERING_MAX_QP_OFFSET);
dev_cap->fs_max_num_qp_per_entry = field;
MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET);
dev_cap->stat_rate_support = stat_rate;
MLX4_GET(field, outbox, QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET);
- dev_cap->timestamp_support = field & 0x80;
+ if (field & 0x80)
+ dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_TS;
MLX4_GET(ext_flags, outbox, QUERY_DEV_CAP_EXT_FLAGS_OFFSET);
MLX4_GET(flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET);
dev_cap->flags = flags | (u64)ext_flags << 32;
@@ -644,6 +729,16 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
QUERY_DEV_CAP_BMME_FLAGS_OFFSET);
MLX4_GET(dev_cap->reserved_lkey, outbox,
QUERY_DEV_CAP_RSVD_LKEY_OFFSET);
+ MLX4_GET(field32, outbox, QUERY_DEV_CAP_ETS_CFG_OFFSET);
+ if (field32 & (1 << 0))
+ dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_ETH_BACKPL_AN_REP;
+ if (field32 & (1 << 7))
+ dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_RECOVERABLE_ERROR_EVENT;
+ if (field32 & (1 << 8))
+ dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_DRIVER_VERSION_TO_FW;
+ if (field32 & (1 << 13))
+ dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_ETS_CFG;
+
MLX4_GET(dev_cap->max_icm_sz, outbox,
QUERY_DEV_CAP_MAX_ICM_SZ_OFFSET);
if (dev_cap->flags & MLX4_DEV_CAP_FLAG_COUNTERS)
@@ -655,6 +750,16 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
MLX4_GET(dev_cap->max_extended_counters, outbox,
QUERY_DEV_CAP_MAX_EXTENDED_COUNTERS_OFFSET);
+ MLX4_GET(field32, outbox, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET);
+ if (field32 & (1 << 16))
+ dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_UPDATE_QP;
+ if (field32 & (1 << 19))
+ dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_LB_SRC_CHK;
+ if (field32 & (1 << 20))
+ dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_FSM;
+ if (field32 & (1 << 26))
+ dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_VLAN_CONTROL;
+
if (dev->flags & MLX4_FLAG_OLD_PORT_CMDS) {
for (i = 1; i <= dev_cap->num_ports; ++i) {
MLX4_GET(field, outbox, QUERY_DEV_CAP_VL_PORT_OFFSET);
@@ -786,6 +891,14 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave,
field &= 0x7f;
MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_BF_OFFSET);
+ /* turn off device-managed steering capability if not enabled */
+ if (dev->caps.steering_mode != MLX4_STEERING_MODE_DEVICE_MANAGED) {
+ MLX4_GET(field, outbox->buf,
+ QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET);
+ field &= 0x7f;
+ MLX4_PUT(outbox->buf, field,
+ QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET);
+ }
return 0;
}
@@ -800,8 +913,10 @@ int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave,
u8 port_type;
u16 short_field;
int err;
+ int admin_link_state;
#define MLX4_VF_PORT_NO_LINK_SENSE_MASK 0xE0
+#define MLX4_PORT_LINK_UP_MASK 0x80
#define QUERY_PORT_CUR_MAX_PKEY_OFFSET 0x0c
#define QUERY_PORT_CUR_MAX_GID_OFFSET 0x0e
@@ -810,12 +925,8 @@ int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave,
MLX4_CMD_NATIVE);
if (!err && dev->caps.function != slave) {
- /* set slave default_mac address */
- MLX4_GET(def_mac, outbox->buf, QUERY_PORT_MAC_OFFSET);
- def_mac += slave << 8;
- /* if config MAC in DB use it */
- if (priv->mfunc.master.vf_oper[slave].vport[vhcr->in_modifier].state.mac)
- def_mac = priv->mfunc.master.vf_oper[slave].vport[vhcr->in_modifier].state.mac;
+ /* set slave default_mac address to be zero MAC */
+ def_mac = priv->mfunc.master.vf_oper[slave].vport[vhcr->in_modifier].state.mac;
MLX4_PUT(outbox->buf, def_mac, QUERY_PORT_MAC_OFFSET);
/* get port type - currently only eth is enabled */
@@ -827,6 +938,12 @@ int mlx4_QUERY_PORT_wrapper(struct mlx4_dev *dev, int slave,
/* set port type to currently operating port type */
port_type |= (dev->caps.port_type[vhcr->in_modifier] & 0x3);
+ admin_link_state = priv->mfunc.master.vf_oper[slave].vport[vhcr->in_modifier].state.link_state;
+ if (IFLA_VF_LINK_STATE_ENABLE == admin_link_state)
+ port_type |= MLX4_PORT_LINK_UP_MASK;
+ else if (IFLA_VF_LINK_STATE_DISABLE == admin_link_state)
+ port_type &= ~MLX4_PORT_LINK_UP_MASK;
+
MLX4_PUT(outbox->buf, port_type,
QUERY_PORT_SUPPORTED_TYPE_OFFSET);
@@ -1078,14 +1195,14 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev)
MLX4_GET(fw->comm_bar, outbox, QUERY_FW_COMM_BAR_OFFSET);
fw->comm_bar = (fw->comm_bar >> 6) * 2;
mlx4_dbg(dev, "Communication vector bar:%d offset:0x%llx\n",
- fw->comm_bar, (long long)fw->comm_base);
+ fw->comm_bar, (unsigned long long)fw->comm_base);
mlx4_dbg(dev, "FW size %d KB\n", fw->fw_pages >> 2);
MLX4_GET(fw->clock_offset, outbox, QUERY_FW_CLOCK_OFFSET);
MLX4_GET(fw->clock_bar, outbox, QUERY_FW_CLOCK_BAR);
fw->clock_bar = (fw->clock_bar >> 6) * 2;
mlx4_dbg(dev, "Internal clock bar:%d offset:0x%llx\n",
- fw->comm_bar, (long long)fw->comm_base);
+ fw->comm_bar, (unsigned long long)fw->comm_base);
/*
* Round up number of system pages needed in case
@@ -1127,7 +1244,7 @@ int mlx4_QUERY_FW_wrapper(struct mlx4_dev *dev, int slave,
return 0;
}
-static void get_board_id(void *vsd, char *board_id)
+static void get_board_id(void *vsd, char *board_id, char *vsdstr)
{
int i;
@@ -1135,9 +1252,16 @@ static void get_board_id(void *vsd, char *board_id)
#define VSD_OFFSET_SIG2 0xde
#define VSD_OFFSET_MLX_BOARD_ID 0xd0
#define VSD_OFFSET_TS_BOARD_ID 0x20
+#define VSD_LEN 0xd0
#define VSD_SIGNATURE_TOPSPIN 0x5ad
+ memset(vsdstr, 0, MLX4_VSD_LEN);
+
+ for (i = 0; i < VSD_LEN / 4; i++)
+ ((u32 *)vsdstr)[i] =
+ swab32(*(u32 *)(vsd + i * 4));
+
memset(board_id, 0, MLX4_BOARD_ID_LEN);
if (be16_to_cpup(vsd + VSD_OFFSET_SIG1) == VSD_SIGNATURE_TOPSPIN &&
@@ -1164,6 +1288,7 @@ int mlx4_QUERY_ADAPTER(struct mlx4_dev *dev, struct mlx4_adapter *adapter)
#define QUERY_ADAPTER_OUT_SIZE 0x100
#define QUERY_ADAPTER_INTA_PIN_OFFSET 0x10
#define QUERY_ADAPTER_VSD_OFFSET 0x20
+#define QUERY_ADAPTER_VSD_VENDOR_ID_OFFSET 0x1e
mailbox = mlx4_alloc_cmd_mailbox(dev);
if (IS_ERR(mailbox))
@@ -1177,8 +1302,11 @@ int mlx4_QUERY_ADAPTER(struct mlx4_dev *dev, struct mlx4_adapter *adapter)
MLX4_GET(adapter->inta_pin, outbox, QUERY_ADAPTER_INTA_PIN_OFFSET);
+ adapter->vsd_vendor_id = be16_to_cpup((u16 *)outbox +
+ QUERY_ADAPTER_VSD_VENDOR_ID_OFFSET / 2);
+
get_board_id(outbox + QUERY_ADAPTER_VSD_OFFSET / 4,
- adapter->board_id);
+ adapter->board_id, adapter->vsd);
out:
mlx4_free_cmd_mailbox(dev, mailbox);
@@ -1189,13 +1317,16 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
{
struct mlx4_cmd_mailbox *mailbox;
__be32 *inbox;
+ u32 mw_enable;
int err;
#define INIT_HCA_IN_SIZE 0x200
+#define INIT_HCA_DRV_NAME_FOR_FW_MAX_SIZE 64
#define INIT_HCA_VERSION_OFFSET 0x000
#define INIT_HCA_VERSION 2
#define INIT_HCA_CACHELINE_SZ_OFFSET 0x0e
#define INIT_HCA_FLAGS_OFFSET 0x014
+#define INIT_HCA_RECOVERABLE_ERROR_EVENT_OFFSET 0x018
#define INIT_HCA_QPC_OFFSET 0x020
#define INIT_HCA_QPC_BASE_OFFSET (INIT_HCA_QPC_OFFSET + 0x10)
#define INIT_HCA_LOG_QP_OFFSET (INIT_HCA_QPC_OFFSET + 0x17)
@@ -1217,6 +1348,7 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
#define INIT_HCA_UC_STEERING_OFFSET (INIT_HCA_MCAST_OFFSET + 0x18)
#define INIT_HCA_LOG_MC_TABLE_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x1b)
#define INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN 0x6
+#define INIT_HCA_DRIVER_VERSION_OFFSET 0x140
#define INIT_HCA_FS_PARAM_OFFSET 0x1d0
#define INIT_HCA_FS_BASE_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x00)
#define INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x12)
@@ -1227,6 +1359,8 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
#define INIT_HCA_FS_IB_NUM_ADDRS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x26)
#define INIT_HCA_TPT_OFFSET 0x0f0
#define INIT_HCA_DMPT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x00)
+#define INIT_HCA_TPT_MW_OFFSET (INIT_HCA_TPT_OFFSET + 0x08)
+#define INIT_HCA_TPT_MW_ENABLE (1 << 31)
#define INIT_HCA_LOG_MPT_SZ_OFFSET (INIT_HCA_TPT_OFFSET + 0x0b)
#define INIT_HCA_MTT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x10)
#define INIT_HCA_CMPT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x18)
@@ -1244,7 +1378,7 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
*((u8 *) mailbox->buf + INIT_HCA_VERSION_OFFSET) = INIT_HCA_VERSION;
*((u8 *) mailbox->buf + INIT_HCA_CACHELINE_SZ_OFFSET) =
- ((ilog2(CACHE_LINE_SIZE) - 4) << 5) | (1 << 4);
+ ((ilog2(cache_line_size()) - 4) << 5) | (1 << 4);
#if defined(__LITTLE_ENDIAN)
*(inbox + INIT_HCA_FLAGS_OFFSET / 4) &= ~cpu_to_be32(1 << 1);
@@ -1290,6 +1424,17 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
dev->caps.cqe_size = 32;
}
+ if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_RECOVERABLE_ERROR_EVENT)
+ *(inbox + INIT_HCA_RECOVERABLE_ERROR_EVENT_OFFSET / 4) |= cpu_to_be32(1 << 31);
+
+ if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_DRIVER_VERSION_TO_FW) {
+ strncpy((u8 *)mailbox->buf + INIT_HCA_DRIVER_VERSION_OFFSET,
+ DRV_NAME_FOR_FW,
+ INIT_HCA_DRV_NAME_FOR_FW_MAX_SIZE - 1);
+ mlx4_dbg(dev, "Reporting Driver Version to FW: %s\n",
+ (u8 *)mailbox->buf + INIT_HCA_DRIVER_VERSION_OFFSET);
+ }
+
/* QPC/EEC/CQC/EQC/RDMARC attributes */
MLX4_PUT(inbox, param->qpc_base, INIT_HCA_QPC_BASE_OFFSET);
@@ -1339,15 +1484,16 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
MLX4_PUT(inbox, param->log_mc_table_sz,
INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
- if (dev->caps.steering_mode == MLX4_STEERING_MODE_B0) {
+ if (dev->caps.steering_mode == MLX4_STEERING_MODE_B0)
MLX4_PUT(inbox, (u8) (1 << 3),
INIT_HCA_UC_STEERING_OFFSET);
- }
}
/* TPT attributes */
MLX4_PUT(inbox, param->dmpt_base, INIT_HCA_DMPT_BASE_OFFSET);
+ mw_enable = param->mw_enable ? INIT_HCA_TPT_MW_ENABLE : 0;
+ MLX4_PUT(inbox, mw_enable, INIT_HCA_TPT_MW_OFFSET);
MLX4_PUT(inbox, param->log_mpt_sz, INIT_HCA_LOG_MPT_SZ_OFFSET);
MLX4_PUT(inbox, param->mtt_base, INIT_HCA_MTT_BASE_OFFSET);
MLX4_PUT(inbox, param->cmpt_base, INIT_HCA_CMPT_BASE_OFFSET);
@@ -1373,6 +1519,7 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
struct mlx4_cmd_mailbox *mailbox;
__be32 *outbox;
u32 dword_field;
+ u32 mw_enable;
int err;
u8 byte_field;
@@ -1414,13 +1561,12 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
param->steering_mode = MLX4_STEERING_MODE_DEVICE_MANAGED;
} else {
MLX4_GET(byte_field, outbox, INIT_HCA_UC_STEERING_OFFSET);
- if (byte_field & 0x8) {
+ if (byte_field & 0x8)
param->steering_mode = MLX4_STEERING_MODE_B0;
- }
- else {
+ else
param->steering_mode = MLX4_STEERING_MODE_A0;
- }
}
+ /* steering attributes */
if (param->steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) {
MLX4_GET(param->mc_base, outbox, INIT_HCA_FS_BASE_OFFSET);
MLX4_GET(param->log_mc_entry_sz, outbox,
@@ -1447,6 +1593,9 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
/* TPT attributes */
MLX4_GET(param->dmpt_base, outbox, INIT_HCA_DMPT_BASE_OFFSET);
+ MLX4_GET(mw_enable, outbox, INIT_HCA_TPT_MW_OFFSET);
+ param->mw_enable = (mw_enable & INIT_HCA_TPT_MW_ENABLE) ==
+ INIT_HCA_TPT_MW_ENABLE;
MLX4_GET(param->log_mpt_sz, outbox, INIT_HCA_LOG_MPT_SZ_OFFSET);
MLX4_GET(param->mtt_base, outbox, INIT_HCA_MTT_BASE_OFFSET);
MLX4_GET(param->cmpt_base, outbox, INIT_HCA_CMPT_BASE_OFFSET);
@@ -1682,6 +1831,15 @@ out:
}
EXPORT_SYMBOL_GPL(mlx4_query_diag_counters);
+int mlx4_MOD_STAT_CFG_wrapper(struct mlx4_dev *dev, int slave,
+ struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox,
+ struct mlx4_cmd_info *cmd)
+{
+ return -EPERM;
+}
+
#define MLX4_WOL_SETUP_MODE (5 << 28)
int mlx4_wol_read(struct mlx4_dev *dev, u64 *config, int port)
{
diff --git a/sys/ofed/drivers/net/mlx4/fw.h b/sys/ofed/drivers/net/mlx4/fw.h
index 5fe7782..0efd047 100644
--- a/sys/ofed/drivers/net/mlx4/fw.h
+++ b/sys/ofed/drivers/net/mlx4/fw.h
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
- * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005, 2006, 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
* Copyright (c) 2006, 2007 Cisco Systems. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -143,10 +143,13 @@ struct mlx4_func_cap {
u32 qp1_proxy_qpn;
u8 physical_port;
u8 port_flags;
+ u8 def_counter_index;
};
struct mlx4_adapter {
+ u16 vsd_vendor_id;
char board_id[MLX4_BOARD_ID_LEN];
+ char vsd[MLX4_VSD_LEN];
u8 inta_pin;
};
@@ -175,6 +178,8 @@ struct mlx4_init_hca_param {
u8 log_mpt_sz;
u8 log_uar_sz;
u8 uar_page_sz; /* log pg sz in 4k chunks */
+ u8 mw_enable; /* Enable memory windows */
+ u8 fs_hash_enable_bits;
u8 steering_mode; /* for QUERY_HCA */
u64 dev_cap_enabled;
};
@@ -218,8 +223,6 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param);
int mlx4_CLOSE_HCA(struct mlx4_dev *dev, int panic);
int mlx4_map_cmd(struct mlx4_dev *dev, u16 op, struct mlx4_icm *icm, u64 virt);
int mlx4_SET_ICM_SIZE(struct mlx4_dev *dev, u64 icm_size, u64 *aux_pages);
-int mlx4_MAP_ICM_AUX(struct mlx4_dev *dev, struct mlx4_icm *icm);
-int mlx4_UNMAP_ICM_AUX(struct mlx4_dev *dev);
int mlx4_NOP(struct mlx4_dev *dev);
int mlx4_MOD_STAT_CFG(struct mlx4_dev *dev, struct mlx4_mod_stat_cfg *cfg);
void mlx4_opreq_action(struct work_struct *work);
diff --git a/sys/ofed/drivers/net/mlx4/icm.c b/sys/ofed/drivers/net/mlx4/icm.c
index d18fde1..25ae7b7 100644
--- a/sys/ofed/drivers/net/mlx4/icm.c
+++ b/sys/ofed/drivers/net/mlx4/icm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005, 2006, 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
* Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -35,6 +35,7 @@
#include <linux/mm.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>
+#include <linux/math64.h>
#include <linux/mlx4/cmd.h>
@@ -288,10 +289,14 @@ void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj)
if (--table->icm[i]->refcount == 0) {
offset = (u64) i * MLX4_TABLE_CHUNK_SIZE;
- mlx4_UNMAP_ICM(dev, table->virt + offset,
- MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE);
- mlx4_free_icm(dev, table->icm[i], table->coherent);
- table->icm[i] = NULL;
+
+ if (!mlx4_UNMAP_ICM(dev, table->virt + offset,
+ MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE)) {
+ mlx4_free_icm(dev, table->icm[i], table->coherent);
+ table->icm[i] = NULL;
+ } else {
+ pr_warn("mlx4_core: mlx4_UNMAP_ICM failed.\n");
+ }
}
mutex_unlock(&table->mutex);
@@ -378,7 +383,7 @@ void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,
}
int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table,
- u64 virt, int obj_size, u32 nobj, int reserved,
+ u64 virt, int obj_size, u64 nobj, int reserved,
int use_lowmem, int use_coherent)
{
int obj_per_chunk;
@@ -388,7 +393,7 @@ int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table,
u64 size;
obj_per_chunk = MLX4_TABLE_CHUNK_SIZE / obj_size;
- num_icm = (nobj + obj_per_chunk - 1) / obj_per_chunk;
+ num_icm = div_u64((nobj + obj_per_chunk - 1), obj_per_chunk);
table->icm = kcalloc(num_icm, sizeof *table->icm, GFP_KERNEL);
if (!table->icm)
@@ -431,11 +436,15 @@ int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table,
err:
for (i = 0; i < num_icm; ++i)
if (table->icm[i]) {
- mlx4_UNMAP_ICM(dev, virt + i * MLX4_TABLE_CHUNK_SIZE,
- MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE);
- mlx4_free_icm(dev, table->icm[i], use_coherent);
+ if (!mlx4_UNMAP_ICM(dev,
+ virt + i * MLX4_TABLE_CHUNK_SIZE,
+ MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE)) {
+ mlx4_free_icm(dev, table->icm[i], use_coherent);
+ } else {
+ pr_warn("mlx4_core: mlx4_UNMAP_ICM failed.\n");
+ return -ENOMEM;
+ }
}
-
kfree(table->icm);
return -ENOMEM;
@@ -443,14 +452,22 @@ err:
void mlx4_cleanup_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table)
{
- int i;
+ int i, err = 0;
for (i = 0; i < table->num_icm; ++i)
if (table->icm[i]) {
- mlx4_UNMAP_ICM(dev, table->virt + i * MLX4_TABLE_CHUNK_SIZE,
- MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE);
- mlx4_free_icm(dev, table->icm[i], table->coherent);
+ err = mlx4_UNMAP_ICM(dev,
+ table->virt + i * MLX4_TABLE_CHUNK_SIZE,
+ MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE);
+ if (!err) {
+ mlx4_free_icm(dev, table->icm[i],
+ table->coherent);
+ } else {
+ pr_warn("mlx4_core: mlx4_UNMAP_ICM failed.\n");
+ break;
+ }
}
- kfree(table->icm);
+ if (!err)
+ kfree(table->icm);
}
diff --git a/sys/ofed/drivers/net/mlx4/icm.h b/sys/ofed/drivers/net/mlx4/icm.h
index f83ad81..f7a2537 100644
--- a/sys/ofed/drivers/net/mlx4/icm.h
+++ b/sys/ofed/drivers/net/mlx4/icm.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005, 2006, 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
* Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -37,6 +37,7 @@
#include <linux/list.h>
#include <linux/pci.h>
#include <linux/mutex.h>
+#include <linux/scatterlist.h>
#define MLX4_ICM_CHUNK_LEN \
((256 - sizeof (struct list_head) - 2 * sizeof (int)) / \
@@ -78,7 +79,7 @@ int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,
void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,
u32 start, u32 end);
int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table,
- u64 virt, int obj_size, u32 nobj, int reserved,
+ u64 virt, int obj_size, u64 nobj, int reserved,
int use_lowmem, int use_coherent);
void mlx4_cleanup_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table);
void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj, dma_addr_t *dma_handle);
@@ -122,5 +123,7 @@ static inline unsigned long mlx4_icm_size(struct mlx4_icm_iter *iter)
return sg_dma_len(&iter->chunk->mem[iter->page_idx]);
}
+int mlx4_MAP_ICM_AUX(struct mlx4_dev *dev, struct mlx4_icm *icm);
+int mlx4_UNMAP_ICM_AUX(struct mlx4_dev *dev);
#endif /* MLX4_ICM_H */
diff --git a/sys/ofed/drivers/net/mlx4/intf.c b/sys/ofed/drivers/net/mlx4/intf.c
index 0f6754b..1416298 100644
--- a/sys/ofed/drivers/net/mlx4/intf.c
+++ b/sys/ofed/drivers/net/mlx4/intf.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved.
- * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -32,6 +32,7 @@
*/
#include <linux/slab.h>
+#include <linux/module.h>
#include "mlx4.h"
@@ -160,7 +161,7 @@ void mlx4_unregister_device(struct mlx4_dev *dev)
list_for_each_entry(intf, &intf_list, list)
mlx4_remove_device(intf, priv);
- list_del(&priv->dev_list);
+ list_del_init(&priv->dev_list);
mutex_unlock(&intf_mutex);
}
diff --git a/sys/ofed/drivers/net/mlx4/main.c b/sys/ofed/drivers/net/mlx4/main.c
index 5fe77d6..12c5836 100644
--- a/sys/ofed/drivers/net/mlx4/main.c
+++ b/sys/ofed/drivers/net/mlx4/main.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
- * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005, 2006, 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
* Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -33,6 +33,11 @@
* SOFTWARE.
*/
+#include <linux/kmod.h>
+/*
+ * kmod.h must be included before module.h since it includes (indirectly) sys/module.h
+ * To use the FBSD macro sys/module.h should define MODULE_VERSION before linux/module does.
+*/
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/pci.h>
@@ -41,6 +46,7 @@
#include <linux/io-mapping.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
+#include <linux/string.h>
#include <linux/fs.h>
#include <linux/mlx4/device.h>
@@ -49,11 +55,11 @@
#include "mlx4.h"
#include "fw.h"
#include "icm.h"
+#include "mlx4_stats.h"
MODULE_AUTHOR("Roland Dreier");
MODULE_DESCRIPTION("Mellanox ConnectX HCA low-level driver");
MODULE_LICENSE("Dual BSD/GPL");
-MODULE_VERSION(DRV_VERSION);
struct workqueue_struct *mlx4_wq;
@@ -69,7 +75,7 @@ MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0");
static int msi_x = 1;
module_param(msi_x, int, 0444);
-MODULE_PARM_DESC(msi_x, "attempt to use MSI-X if nonzero");
+MODULE_PARM_DESC(msi_x, "0 - don't use MSI-X, 1 - use MSI-X, >1 - limit number of MSI-X irqs to msi_x (non-SRIOV only)");
#else /* CONFIG_PCI_MSI */
@@ -85,14 +91,60 @@ int mlx4_blck_lb = 1;
module_param_named(block_loopback, mlx4_blck_lb, int, 0644);
MODULE_PARM_DESC(block_loopback, "Block multicast loopback packets if > 0 "
"(default: 1)");
+enum {
+ DEFAULT_DOMAIN = 0,
+ BDF_STR_SIZE = 8, /* bb:dd.f- */
+ DBDF_STR_SIZE = 13 /* mmmm:bb:dd.f- */
+};
-static int num_vfs;
-module_param(num_vfs, int, 0444);
-MODULE_PARM_DESC(num_vfs, "enable #num_vfs functions if num_vfs > 0");
+enum {
+ NUM_VFS,
+ PROBE_VF,
+ PORT_TYPE_ARRAY
+};
-static int probe_vf;
-module_param(probe_vf, int, 0644);
-MODULE_PARM_DESC(probe_vf, "number of vfs to probe by pf driver (num_vfs > 0)");
+enum {
+ VALID_DATA,
+ INVALID_DATA,
+ INVALID_STR
+};
+
+struct param_data {
+ int id;
+ struct mlx4_dbdf2val_lst dbdf2val;
+};
+
+static struct param_data num_vfs = {
+ .id = NUM_VFS,
+ .dbdf2val = {
+ .name = "num_vfs param",
+ .num_vals = 1,
+ .def_val = {0},
+ .range = {0, MLX4_MAX_NUM_VF}
+ }
+};
+module_param_string(num_vfs, num_vfs.dbdf2val.str,
+ sizeof(num_vfs.dbdf2val.str), 0444);
+MODULE_PARM_DESC(num_vfs,
+ "Either single value (e.g. '5') to define uniform num_vfs value for all devices functions\n"
+ "\t\tor a string to map device function numbers to their num_vfs values (e.g. '0000:04:00.0-5,002b:1c:0b.a-15').\n"
+ "\t\tHexadecimal digits for the device function (e.g. 002b:1c:0b.a) and decimal for num_vfs value (e.g. 15).");
+
+static struct param_data probe_vf = {
+ .id = PROBE_VF,
+ .dbdf2val = {
+ .name = "probe_vf param",
+ .num_vals = 1,
+ .def_val = {0},
+ .range = {0, MLX4_MAX_NUM_VF}
+ }
+};
+module_param_string(probe_vf, probe_vf.dbdf2val.str,
+ sizeof(probe_vf.dbdf2val.str), 0444);
+MODULE_PARM_DESC(probe_vf,
+ "Either single value (e.g. '3') to define uniform number of VFs to probe by the pf driver for all devices functions\n"
+ "\t\tor a string to map device function numbers to their probe_vf values (e.g. '0000:04:00.0-3,002b:1c:0b.a-13').\n"
+ "\t\tHexadecimal digits for the device function (e.g. 002b:1c:0b.a) and decimal for probe_vf value (e.g. 13).");
int mlx4_log_num_mgm_entry_size = MLX4_DEFAULT_MGM_LOG_ENTRY_SIZE;
@@ -115,10 +167,10 @@ module_param_named(fast_drop, fast_drop, int, 0444);
MODULE_PARM_DESC(fast_drop,
"Enable fast packet drop when no recieve WQEs are posted");
-int mlx4_enable_64b_cqe_eqe;
+int mlx4_enable_64b_cqe_eqe = 1;
module_param_named(enable_64b_cqe_eqe, mlx4_enable_64b_cqe_eqe, int, 0644);
MODULE_PARM_DESC(enable_64b_cqe_eqe,
- "Enable 64 byte CQEs/EQEs when the the FW supports this, if nonzero");
+ "Enable 64 byte CQEs/EQEs when the the FW supports this if non-zero (default: 1)");
#define HCA_GLOBAL_CAP_MASK 0
@@ -144,13 +196,23 @@ module_param_named(log_mtts_per_seg, log_mtts_per_seg, int, 0444);
MODULE_PARM_DESC(log_mtts_per_seg, "Log2 number of MTT entries per segment "
"(0-7) (default: 0)");
-static int port_type_array[2] = {MLX4_PORT_TYPE_NONE, MLX4_PORT_TYPE_NONE};
-#if 0
-static int arr_argc = 2;
-module_param_array(port_type_array, int, &arr_argc, 0444);
-MODULE_PARM_DESC(port_type_array, "Array of port types: HW_DEFAULT (0) is default "
- "1 for IB, 2 for Ethernet");
-#endif
+static struct param_data port_type_array = {
+ .id = PORT_TYPE_ARRAY,
+ .dbdf2val = {
+ .name = "port_type_array param",
+ .num_vals = 2,
+ .def_val = {MLX4_PORT_TYPE_ETH, MLX4_PORT_TYPE_ETH},
+ .range = {MLX4_PORT_TYPE_IB, MLX4_PORT_TYPE_NA}
+ }
+};
+module_param_string(port_type_array, port_type_array.dbdf2val.str,
+ sizeof(port_type_array.dbdf2val.str), 0444);
+MODULE_PARM_DESC(port_type_array,
+ "Either pair of values (e.g. '1,2') to define uniform port1/port2 types configuration for all devices functions\n"
+ "\t\tor a string to map device function numbers to their pair of port types values (e.g. '0000:04:00.0-1;2,002b:1c:0b.a-1;1').\n"
+ "\t\tValid port types: 1-ib, 2-eth, 3-auto, 4-N/A\n"
+ "\t\tIn case that only one port is available use the N/A port type for port2 (e.g '1,4').");
+
struct mlx4_port_config {
struct list_head list;
@@ -170,7 +232,7 @@ static struct mlx4_profile mod_param_profile = {
.num_cq = 16,
.num_mcg = 13,
.num_mpt = 19,
- .num_mtt = 0, /* max(20, 2*MTTs for host memory)) */
+ .num_mtt_segs = 0, /* max(20, 2*MTTs for host memory)) */
};
module_param_named(log_num_qp, mod_param_profile.num_qp, int, 0444);
@@ -197,7 +259,7 @@ MODULE_PARM_DESC(log_num_mpt,
"log maximum number of memory protection table entries per "
"HCA (default: 19)");
-module_param_named(log_num_mtt, mod_param_profile.num_mtt, int, 0444);
+module_param_named(log_num_mtt, mod_param_profile.num_mtt_segs, int, 0444);
MODULE_PARM_DESC(log_num_mtt,
"log maximum number of memory translation table segments per "
"HCA (default: max(20, 2*MTTs for register all of the host memory limited to 30))");
@@ -206,9 +268,263 @@ enum {
MLX4_IF_STATE_BASIC,
MLX4_IF_STATE_EXTENDED
};
-static void process_mod_param_profile(struct mlx4_profile *profile)
+
+static inline u64 dbdf_to_u64(int domain, int bus, int dev, int fn)
{
+ return (domain << 20) | (bus << 12) | (dev << 4) | fn;
+}
+
+static inline void pr_bdf_err(const char *dbdf, const char *pname)
+{
+ pr_warn("mlx4_core: '%s' is not valid bdf in '%s'\n", dbdf, pname);
+}
+
+static inline void pr_val_err(const char *dbdf, const char *pname,
+ const char *val)
+{
+ pr_warn("mlx4_core: value '%s' of bdf '%s' in '%s' is not valid\n"
+ , val, dbdf, pname);
+}
+
+static inline void pr_out_of_range_bdf(const char *dbdf, int val,
+ struct mlx4_dbdf2val_lst *dbdf2val)
+{
+ pr_warn("mlx4_core: value %d in bdf '%s' of '%s' is out of its valid range (%d,%d)\n"
+ , val, dbdf, dbdf2val->name , dbdf2val->range.min,
+ dbdf2val->range.max);
+}
+
+static inline void pr_out_of_range(struct mlx4_dbdf2val_lst *dbdf2val)
+{
+ pr_warn("mlx4_core: value of '%s' is out of its valid range (%d,%d)\n"
+ , dbdf2val->name , dbdf2val->range.min, dbdf2val->range.max);
+}
+
+static inline int is_in_range(int val, struct mlx4_range *r)
+{
+ return (val >= r->min && val <= r->max);
+}
+
+static int update_defaults(struct param_data *pdata)
+{
+ long int val[MLX4_MAX_BDF_VALS];
+ int ret;
+ char *t, *p = pdata->dbdf2val.str;
+ char sval[32];
+ int val_len;
+
+ if (!strlen(p) || strchr(p, ':') || strchr(p, '.') || strchr(p, ';'))
+ return INVALID_STR;
+
+ switch (pdata->id) {
+ case PORT_TYPE_ARRAY:
+ t = strchr(p, ',');
+ if (!t || t == p || (t - p) > sizeof(sval))
+ return INVALID_STR;
+
+ val_len = t - p;
+ strncpy(sval, p, val_len);
+ sval[val_len] = 0;
+
+ ret = kstrtol(sval, 0, &val[0]);
+ if (ret == -EINVAL)
+ return INVALID_STR;
+ if (ret || !is_in_range(val[0], &pdata->dbdf2val.range)) {
+ pr_out_of_range(&pdata->dbdf2val);
+ return INVALID_DATA;
+ }
+
+ ret = kstrtol(t + 1, 0, &val[1]);
+ if (ret == -EINVAL)
+ return INVALID_STR;
+ if (ret || !is_in_range(val[1], &pdata->dbdf2val.range)) {
+ pr_out_of_range(&pdata->dbdf2val);
+ return INVALID_DATA;
+ }
+
+ pdata->dbdf2val.tbl[0].val[0] = val[0];
+ pdata->dbdf2val.tbl[0].val[1] = val[1];
+ break;
+
+ case NUM_VFS:
+ case PROBE_VF:
+ ret = kstrtol(p, 0, &val[0]);
+ if (ret == -EINVAL)
+ return INVALID_STR;
+ if (ret || !is_in_range(val[0], &pdata->dbdf2val.range)) {
+ pr_out_of_range(&pdata->dbdf2val);
+ return INVALID_DATA;
+ }
+ pdata->dbdf2val.tbl[0].val[0] = val[0];
+ break;
+ }
+ pdata->dbdf2val.tbl[1].dbdf = MLX4_ENDOF_TBL;
+
+ return VALID_DATA;
+}
+
+int mlx4_fill_dbdf2val_tbl(struct mlx4_dbdf2val_lst *dbdf2val_lst)
+{
+ int domain, bus, dev, fn;
+ u64 dbdf;
+ char *p, *t, *v;
+ char tmp[32];
+ char sbdf[32];
+ char sep = ',';
+ int j, k, str_size, i = 1;
+ int prfx_size;
+
+ p = dbdf2val_lst->str;
+
+ for (j = 0; j < dbdf2val_lst->num_vals; j++)
+ dbdf2val_lst->tbl[0].val[j] = dbdf2val_lst->def_val[j];
+ dbdf2val_lst->tbl[1].dbdf = MLX4_ENDOF_TBL;
+
+ str_size = strlen(dbdf2val_lst->str);
+
+ if (str_size == 0)
+ return 0;
+
+ while (strlen(p)) {
+ prfx_size = BDF_STR_SIZE;
+ sbdf[prfx_size] = 0;
+ strncpy(sbdf, p, prfx_size);
+ domain = DEFAULT_DOMAIN;
+ if (sscanf(sbdf, "%02x:%02x.%x-", &bus, &dev, &fn) != 3) {
+ prfx_size = DBDF_STR_SIZE;
+ sbdf[prfx_size] = 0;
+ strncpy(sbdf, p, prfx_size);
+ if (sscanf(sbdf, "%04x:%02x:%02x.%x-", &domain, &bus,
+ &dev, &fn) != 4) {
+ pr_bdf_err(sbdf, dbdf2val_lst->name);
+ goto err;
+ }
+ sprintf(tmp, "%04x:%02x:%02x.%x-", domain, bus, dev,
+ fn);
+ } else {
+ sprintf(tmp, "%02x:%02x.%x-", bus, dev, fn);
+ }
+
+ if (strnicmp(sbdf, tmp, sizeof(tmp))) {
+ pr_bdf_err(sbdf, dbdf2val_lst->name);
+ goto err;
+ }
+
+ dbdf = dbdf_to_u64(domain, bus, dev, fn);
+
+ for (j = 1; j < i; j++)
+ if (dbdf2val_lst->tbl[j].dbdf == dbdf) {
+ pr_warn("mlx4_core: in '%s', %s appears multiple times\n"
+ , dbdf2val_lst->name, sbdf);
+ goto err;
+ }
+
+ if (i >= MLX4_DEVS_TBL_SIZE) {
+ pr_warn("mlx4_core: Too many devices in '%s'\n"
+ , dbdf2val_lst->name);
+ goto err;
+ }
+
+ p += prfx_size;
+ t = strchr(p, sep);
+ t = t ? t : p + strlen(p);
+ if (p >= t) {
+ pr_val_err(sbdf, dbdf2val_lst->name, "");
+ goto err;
+ }
+
+ for (k = 0; k < dbdf2val_lst->num_vals; k++) {
+ char sval[32];
+ long int val;
+ int ret, val_len;
+ char vsep = ';';
+
+ v = (k == dbdf2val_lst->num_vals - 1) ? t : strchr(p, vsep);
+ if (!v || v > t || v == p || (v - p) > sizeof(sval)) {
+ pr_val_err(sbdf, dbdf2val_lst->name, p);
+ goto err;
+ }
+ val_len = v - p;
+ strncpy(sval, p, val_len);
+ sval[val_len] = 0;
+
+ ret = kstrtol(sval, 0, &val);
+ if (ret) {
+ if (strchr(p, vsep))
+ pr_warn("mlx4_core: too many vals in bdf '%s' of '%s'\n"
+ , sbdf, dbdf2val_lst->name);
+ else
+ pr_val_err(sbdf, dbdf2val_lst->name,
+ sval);
+ goto err;
+ }
+ if (!is_in_range(val, &dbdf2val_lst->range)) {
+ pr_out_of_range_bdf(sbdf, val, dbdf2val_lst);
+ goto err;
+ }
+
+ dbdf2val_lst->tbl[i].val[k] = val;
+ p = v;
+ if (p[0] == vsep)
+ p++;
+ }
+
+ dbdf2val_lst->tbl[i].dbdf = dbdf;
+ if (strlen(p)) {
+ if (p[0] != sep) {
+ pr_warn("mlx4_core: expect separator '%c' before '%s' in '%s'\n"
+ , sep, p, dbdf2val_lst->name);
+ goto err;
+ }
+ p++;
+ }
+ i++;
+ if (i < MLX4_DEVS_TBL_SIZE)
+ dbdf2val_lst->tbl[i].dbdf = MLX4_ENDOF_TBL;
+ }
+
+ return 0;
+
+err:
+ dbdf2val_lst->tbl[1].dbdf = MLX4_ENDOF_TBL;
+ pr_warn("mlx4_core: The value of '%s' is incorrect. The value is discarded!\n"
+ , dbdf2val_lst->name);
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL(mlx4_fill_dbdf2val_tbl);
+
+int mlx4_get_val(struct mlx4_dbdf2val *tbl, struct pci_dev *pdev, int idx,
+ int *val)
+{
+ u64 dbdf;
+ int i = 1;
+
+ *val = tbl[0].val[idx];
+ if (!pdev)
+ return -EINVAL;
+
+ if (!pdev->bus) {
+ return -EINVAL;
+ }
+
+ dbdf = dbdf_to_u64(pci_get_domain(pdev->dev.bsddev), pci_get_bus(pdev->dev.bsddev),
+ PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+
+ while ((i < MLX4_DEVS_TBL_SIZE) && (tbl[i].dbdf != MLX4_ENDOF_TBL)) {
+ if (tbl[i].dbdf == dbdf) {
+ *val = tbl[i].val[idx];
+ return 0;
+ }
+ i++;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(mlx4_get_val);
+static void process_mod_param_profile(struct mlx4_profile *profile)
+{
vm_size_t hwphyssz;
hwphyssz = 0;
TUNABLE_ULONG_FETCH("hw.realmem", (u_long *) &hwphyssz);
@@ -232,10 +548,10 @@ static void process_mod_param_profile(struct mlx4_profile *profile)
* That limits us to 4TB of memory registration per HCA with
* 4KB pages, which is probably OK for the next few months.
*/
- if (mod_param_profile.num_mtt)
- profile->num_mtt = 1 << mod_param_profile.num_mtt;
+ if (mod_param_profile.num_mtt_segs)
+ profile->num_mtt_segs = 1 << mod_param_profile.num_mtt_segs;
else {
- profile->num_mtt =
+ profile->num_mtt_segs =
roundup_pow_of_two(max_t(unsigned,
1 << (MLX4_LOG_NUM_MTT - log_mtts_per_seg),
min(1UL <<
@@ -245,7 +561,7 @@ static void process_mod_param_profile(struct mlx4_profile *profile)
>> log_mtts_per_seg)));
/* set the actual value, so it will be reflected to the user
using the sysfs */
- mod_param_profile.num_mtt = ilog2(profile->num_mtt * (1 << log_mtts_per_seg));
+ mod_param_profile.num_mtt_segs = ilog2(profile->num_mtt_segs);
}
}
@@ -406,14 +722,26 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
MLX4_PORT_TYPE_IB)
dev->caps.port_type[i] = MLX4_PORT_TYPE_IB;
else {
- /* if IB and ETH are supported, we set the port
+ /*
+ * if IB and ETH are supported, we set the port
* type according to user selection of port type;
- * if user selected none, take the FW hint */
- if (port_type_array[i - 1] == MLX4_PORT_TYPE_NONE)
+ * if there is no user selection, take the FW hint
+ */
+ int pta;
+ mlx4_get_val(port_type_array.dbdf2val.tbl,
+ pci_physfn(dev->pdev), i - 1,
+ &pta);
+ if (pta == MLX4_PORT_TYPE_NONE) {
dev->caps.port_type[i] = dev->caps.suggested_type[i] ?
MLX4_PORT_TYPE_ETH : MLX4_PORT_TYPE_IB;
- else
- dev->caps.port_type[i] = port_type_array[i - 1];
+ } else if (pta == MLX4_PORT_TYPE_NA) {
+ mlx4_err(dev, "Port %d is valid port. "
+ "It is not allowed to configure its type to N/A(%d)\n",
+ i, MLX4_PORT_TYPE_NA);
+ return -EINVAL;
+ } else {
+ dev->caps.port_type[i] = pta;
+ }
}
}
/*
@@ -427,6 +755,9 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
(dev->caps.flags & MLX4_DEV_CAP_FLAG_DPDP) &&
(dev->caps.flags & MLX4_DEV_CAP_FLAG_SENSE_SUPPORT));
+ /* Disablling auto sense for default Eth ports support */
+ mlx4_priv(dev)->sense.sense_allowed[i] = 0;
+
/*
* If "default_sense" bit is set, we move the port to "AUTO" mode
* and perform sense_port FW command to try and set the correct
@@ -478,9 +809,12 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
dev->caps.reserved_qps_cnt[MLX4_QP_REGION_FC_EXCH];
dev->caps.sync_qp = dev_cap->sync_qp;
+ if (dev->pdev->device == 0x1003)
+ dev->caps.cq_flags |= MLX4_DEV_CAP_CQ_FLAG_IO;
+
dev->caps.sqp_demux = (mlx4_is_master(dev)) ? MLX4_MAX_NUM_SLAVES : 0;
- if (!mlx4_enable_64b_cqe_eqe) {
+ if (!mlx4_enable_64b_cqe_eqe && !mlx4_is_slave(dev)) {
if (dev_cap->flags &
(MLX4_DEV_CAP_FLAG_64B_CQE | MLX4_DEV_CAP_FLAG_64B_EQE)) {
mlx4_warn(dev, "64B EQEs/CQEs supported by the device but not enabled\n");
@@ -494,6 +828,11 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
mlx4_is_master(dev))
dev->caps.function_caps |= MLX4_FUNC_CAP_64B_EQE_CQE;
+ if (!mlx4_is_slave(dev)) {
+ for (i = 0; i < dev->caps.num_ports; ++i)
+ dev->caps.def_counter_index[i] = i << 1;
+ }
+
return 0;
}
/*The function checks if there are live vf, return the num of them*/
@@ -634,6 +973,11 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)
if (err)
mlx4_err(dev, "QUERY_FW command failed: could not get FW version.\n");
+ if (!hca_param.mw_enable) {
+ dev->caps.flags &= ~MLX4_DEV_CAP_FLAG_MEM_WINDOW;
+ dev->caps.bmme_flags &= ~MLX4_BMME_FLAG_TYPE_2_WIN;
+ }
+
page_size = ~dev->caps.page_size_cap + 1;
mlx4_warn(dev, "HCA minimum page size:%d\n", page_size);
if (page_size > PAGE_SIZE) {
@@ -711,6 +1055,8 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)
dev->caps.qp0_proxy[i - 1] = func_cap.qp0_proxy_qpn;
dev->caps.qp1_tunnel[i - 1] = func_cap.qp1_tunnel_qpn;
dev->caps.qp1_proxy[i - 1] = func_cap.qp1_proxy_qpn;
+ dev->caps.def_counter_index[i - 1] = func_cap.def_counter_index;
+
dev->caps.port_mask[i] = dev->caps.port_type[i];
err = mlx4_get_slave_pkey_gid_tbl_len(dev, i,
&dev->caps.gid_table_len[i],
@@ -745,6 +1091,9 @@ static int mlx4_slave_cap(struct mlx4_dev *dev)
dev->caps.cqe_size = 32;
}
+ dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_TS;
+ mlx4_warn(dev, "Timestamping is not supported in slave mode.\n");
+
slave_adjust_steering_mode(dev, &dev_cap, &hca_param);
return 0;
@@ -760,6 +1109,27 @@ err_mem:
return err;
}
+static void mlx4_request_modules(struct mlx4_dev *dev)
+{
+ int port;
+ int has_ib_port = false;
+ int has_eth_port = false;
+#define EN_DRV_NAME "mlx4_en"
+#define IB_DRV_NAME "mlx4_ib"
+
+ for (port = 1; port <= dev->caps.num_ports; port++) {
+ if (dev->caps.port_type[port] == MLX4_PORT_TYPE_IB)
+ has_ib_port = true;
+ else if (dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH)
+ has_eth_port = true;
+ }
+
+ if (has_ib_port)
+ request_module_nowait(IB_DRV_NAME);
+ if (has_eth_port)
+ request_module_nowait(EN_DRV_NAME);
+}
+
/*
* Change the port configuration of the device.
* Every user of this function must hold the port mutex.
@@ -791,6 +1161,11 @@ int mlx4_change_port_types(struct mlx4_dev *dev,
}
mlx4_set_port_mask(dev);
err = mlx4_register_device(dev);
+ if (err) {
+ mlx4_err(dev, "Failed to register device\n");
+ goto out;
+ }
+ mlx4_request_modules(dev);
}
out:
@@ -841,7 +1216,14 @@ static ssize_t set_port_type(struct device *dev,
return -EINVAL;
}
- mlx4_stop_sense(mdev);
+ if ((info->tmp_type & mdev->caps.supported_type[info->port]) !=
+ info->tmp_type) {
+ mlx4_err(mdev, "Requested port type for port %d is not supported on this HCA\n",
+ info->port);
+ return -EINVAL;
+ }
+
+ mlx4_stop_sense(mdev);
mutex_lock(&priv->port_mutex);
/* Possible type is always the one that was delivered */
mdev->caps.possible_type[info->port] = info->tmp_type;
@@ -984,7 +1366,7 @@ err_set_port:
static int mlx4_load_fw(struct mlx4_dev *dev)
{
struct mlx4_priv *priv = mlx4_priv(dev);
- int err;
+ int err, unmap_flag = 0;
priv->fw.fw_icm = mlx4_alloc_icm(dev, priv->fw.fw_pages,
GFP_HIGHUSER | __GFP_NOWARN, 0);
@@ -1008,10 +1390,13 @@ static int mlx4_load_fw(struct mlx4_dev *dev)
return 0;
err_unmap_fa:
- mlx4_UNMAP_FA(dev);
+ unmap_flag = mlx4_UNMAP_FA(dev);
+ if (unmap_flag)
+ pr_warn("mlx4_core: mlx4_UNMAP_FA failed.\n");
err_free:
- mlx4_free_icm(dev, priv->fw.fw_icm, 0);
+ if (!unmap_flag)
+ mlx4_free_icm(dev, priv->fw.fw_icm, 0);
return err;
}
@@ -1081,7 +1466,7 @@ static int mlx4_init_icm(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap,
struct mlx4_priv *priv = mlx4_priv(dev);
u64 aux_pages;
int num_eqs;
- int err;
+ int err, unmap_flag = 0;
err = mlx4_SET_ICM_SIZE(dev, icm_size, &aux_pages);
if (err) {
@@ -1272,10 +1657,13 @@ err_unmap_cmpt:
mlx4_cleanup_icm_table(dev, &priv->qp_table.cmpt_table);
err_unmap_aux:
- mlx4_UNMAP_ICM_AUX(dev);
+ unmap_flag = mlx4_UNMAP_ICM_AUX(dev);
+ if (unmap_flag)
+ pr_warn("mlx4_core: mlx4_UNMAP_ICM_AUX failed.\n");
err_free_aux:
- mlx4_free_icm(dev, priv->fw.aux_icm, 0);
+ if (!unmap_flag)
+ mlx4_free_icm(dev, priv->fw.aux_icm, 0);
return err;
}
@@ -1299,8 +1687,10 @@ static void mlx4_free_icms(struct mlx4_dev *dev)
mlx4_cleanup_icm_table(dev, &priv->srq_table.cmpt_table);
mlx4_cleanup_icm_table(dev, &priv->qp_table.cmpt_table);
- mlx4_UNMAP_ICM_AUX(dev);
- mlx4_free_icm(dev, priv->fw.aux_icm, 0);
+ if (!mlx4_UNMAP_ICM_AUX(dev))
+ mlx4_free_icm(dev, priv->fw.aux_icm, 0);
+ else
+ pr_warn("mlx4_core: mlx4_UNMAP_ICM_AUX failed.\n");
}
static void mlx4_slave_exit(struct mlx4_dev *dev)
@@ -1340,13 +1730,16 @@ static void unmap_bf_area(struct mlx4_dev *dev)
io_mapping_free(mlx4_priv(dev)->bf_mapping);
}
-cycle_t mlx4_read_clock(struct mlx4_dev *dev)
+int mlx4_read_clock(struct mlx4_dev *dev)
{
u32 clockhi, clocklo, clockhi1;
cycle_t cycles;
int i;
struct mlx4_priv *priv = mlx4_priv(dev);
+ if (!priv->clock_mapping)
+ return -ENOTSUPP;
+
for (i = 0; i < 10; i++) {
clockhi = swab32(readl(priv->clock_mapping));
clocklo = swab32(readl(priv->clock_mapping + 4));
@@ -1376,6 +1769,25 @@ static int map_internal_clock(struct mlx4_dev *dev)
return 0;
}
+
+int mlx4_get_internal_clock_params(struct mlx4_dev *dev,
+ struct mlx4_clock_params *params)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+
+ if (mlx4_is_slave(dev))
+ return -ENOTSUPP;
+ if (!params)
+ return -EINVAL;
+
+ params->bar = priv->fw.clock_bar;
+ params->offset = priv->fw.clock_offset;
+ params->size = MLX4_CLOCK_SIZE;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mlx4_get_internal_clock_params);
+
static void unmap_internal_clock(struct mlx4_dev *dev)
{
struct mlx4_priv *priv = mlx4_priv(dev);
@@ -1388,13 +1800,16 @@ static void mlx4_close_hca(struct mlx4_dev *dev)
{
unmap_internal_clock(dev);
unmap_bf_area(dev);
- if (mlx4_is_slave(dev))
+ if (mlx4_is_slave(dev)) {
mlx4_slave_exit(dev);
- else {
+ } else {
mlx4_CLOSE_HCA(dev, 0);
mlx4_free_icms(dev);
- mlx4_UNMAP_FA(dev);
- mlx4_free_icm(dev, mlx4_priv(dev)->fw.fw_icm, 0);
+
+ if (!mlx4_UNMAP_FA(dev))
+ mlx4_free_icm(dev, mlx4_priv(dev)->fw.fw_icm, 0);
+ else
+ pr_warn("mlx4_core: mlx4_UNMAP_FA failed.\n");
}
}
@@ -1497,13 +1912,9 @@ static int choose_log_fs_mgm_entry_size(int qp_per_entry)
static void choose_steering_mode(struct mlx4_dev *dev,
struct mlx4_dev_cap *dev_cap)
{
- // This is only valid to the integrated driver.
- // The new ported mlx4_core driver is in B0 steering mode by default
- // and the old mlx4_en driver is in A0 steering mode by default.
- // If high_rate_steer == TRUE it means that A0 steering mode is on.
- // The integration fix is to hard code high_rate_steer to TRUE.
- high_rate_steer = 1;
+ int nvfs;
+ mlx4_get_val(num_vfs.dbdf2val.tbl, pci_physfn(dev->pdev), 0, &nvfs);
if (high_rate_steer && !mlx4_is_mfunc(dev)) {
dev->caps.flags &= ~(MLX4_DEV_CAP_FLAG_VEP_MC_STEER |
MLX4_DEV_CAP_FLAG_VEP_UC_STEER);
@@ -1512,9 +1923,8 @@ static void choose_steering_mode(struct mlx4_dev *dev,
if (mlx4_log_num_mgm_entry_size == -1 &&
dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_FS_EN &&
- dev_cap->fs_log_max_ucast_qp_range_size == 0 &&
(!mlx4_is_mfunc(dev) ||
- (dev_cap->fs_max_num_qp_per_entry >= (num_vfs + 1))) &&
+ (dev_cap->fs_max_num_qp_per_entry >= (nvfs + 1))) &&
choose_log_fs_mgm_entry_size(dev_cap->fs_max_num_qp_per_entry) >=
MLX4_MIN_MGM_LOG_ENTRY_SIZE) {
dev->oper_log_mgm_entry_size =
@@ -1523,9 +1933,8 @@ static void choose_steering_mode(struct mlx4_dev *dev,
dev->caps.num_qp_per_mgm = dev_cap->fs_max_num_qp_per_entry;
} else {
if (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_UC_STEER &&
- dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) {
+ dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER)
dev->caps.steering_mode = MLX4_STEERING_MODE_B0;
- }
else {
dev->caps.steering_mode = MLX4_STEERING_MODE_A0;
@@ -1618,11 +2027,42 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
if (err)
goto err_stop_fw;
+ init_hca.mw_enable = 1;
+
err = mlx4_INIT_HCA(dev, &init_hca);
if (err) {
mlx4_err(dev, "INIT_HCA command failed, aborting.\n");
goto err_free_icm;
}
+
+ /*
+ * Read HCA frequency by QUERY_HCA command
+ */
+ if (dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS) {
+ memset(&init_hca, 0, sizeof(init_hca));
+ err = mlx4_QUERY_HCA(dev, &init_hca);
+ if (err) {
+ mlx4_err(dev, "QUERY_HCA command failed, disable timestamp.\n");
+ dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_TS;
+ } else {
+ dev->caps.hca_core_clock =
+ init_hca.hca_core_clock;
+ }
+
+ /* In case we got HCA frequency 0 - disable timestamping
+ * to avoid dividing by zero
+ */
+ if (!dev->caps.hca_core_clock) {
+ dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_TS;
+ mlx4_err(dev, "HCA frequency is 0. Timestamping is not supported.");
+ } else if (map_internal_clock(dev)) {
+ /* Map internal clock,
+ * in case of failure disable timestamping
+ */
+ dev->caps.flags2 &= ~MLX4_DEV_CAP_FLAG2_TS;
+ mlx4_err(dev, "Failed to map internal clock. Timestamping is not supported.\n");
+ }
+ }
} else {
err = mlx4_init_slave(dev);
if (err) {
@@ -1640,39 +2080,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
if (map_bf_area(dev))
mlx4_dbg(dev, "Failed to map blue flame area\n");
- /*
- * Read HCA frequency by QUERY_HCA command
- */
- if (dev->caps.cq_timestamp) {
- memset(&init_hca, 0, sizeof(init_hca));
- err = mlx4_QUERY_HCA(dev, &init_hca);
- if (err) {
- mlx4_err(dev, "QUERY_HCA command failed, disable timestamp.\n");
- dev->caps.cq_timestamp = 0;
- } else
- dev->caps.hca_core_clock = init_hca.hca_core_clock;
-
- /*
- * In case we got HCA frequency 0 - disable timestamping
- * to avoid dividing by zero
- */
- if (!dev->caps.hca_core_clock) {
- dev->caps.cq_timestamp = 0;
- mlx4_err(dev, "HCA frequency is 0. "
- "Timestamping is not supported.");
- }
-
- /*
- * Map internal clock, in case of failure disable timestamping
- */
- if (map_internal_clock(dev)) {
- dev->caps.cq_timestamp = 0;
- mlx4_err(dev, "Failed to map internal clock. "
- "Timestamping is not supported.\n");
- }
- }
-
- /*Only the master set the ports, all the rest got it from it.*/
+ /* Only the master set the ports, all the rest got it from it.*/
if (!mlx4_is_slave(dev))
mlx4_set_port_mask(dev);
@@ -1684,6 +2092,8 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
priv->eq_table.inta_pin = adapter.inta_pin;
memcpy(dev->board_id, adapter.board_id, sizeof dev->board_id);
+ memcpy(dev->vsd, adapter.vsd, sizeof(dev->vsd));
+ dev->vsd_vendor_id = adapter.vsd_vendor_id;
if (!mlx4_is_slave(dev))
kfree(dev_cap);
@@ -1691,7 +2101,8 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
return 0;
unmap_bf:
- unmap_internal_clock(dev);
+ if (!mlx4_is_slave(dev))
+ unmap_internal_clock(dev);
unmap_bf_area(dev);
if (mlx4_is_slave(dev)) {
@@ -1713,10 +2124,11 @@ err_free_icm:
err_stop_fw:
if (!mlx4_is_slave(dev)) {
- mlx4_UNMAP_FA(dev);
- mlx4_free_icm(dev, priv->fw.fw_icm, 0);
- if (dev_cap)
- kfree(dev_cap);
+ if (!mlx4_UNMAP_FA(dev))
+ mlx4_free_icm(dev, priv->fw.fw_icm, 0);
+ else
+ pr_warn("mlx4_core: mlx4_UNMAP_FA failed.\n");
+ kfree(dev_cap);
}
return err;
}
@@ -1724,92 +2136,539 @@ err_stop_fw:
static int mlx4_init_counters_table(struct mlx4_dev *dev)
{
struct mlx4_priv *priv = mlx4_priv(dev);
- int res;
- int nent_pow2;
+ int nent_pow2, port_indx, vf_index, num_counters;
+ int res, index = 0;
+ struct counter_index *new_counter_index;
+
if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_COUNTERS))
return -ENOENT;
- nent_pow2 = roundup_pow_of_two(dev->caps.max_counters);
- res = mlx4_bitmap_init(&priv->counters_bitmap, nent_pow2,
- nent_pow2 - 1, 0,
- nent_pow2 - dev->caps.max_counters);
- if (res)
- return res;
+ if (!mlx4_is_slave(dev) &&
+ dev->caps.max_counters == dev->caps.max_extended_counters) {
+ res = mlx4_cmd(dev, MLX4_IF_STATE_EXTENDED, 0, 0,
+ MLX4_CMD_SET_IF_STAT,
+ MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
+ if (res) {
+ mlx4_err(dev, "Failed to set extended counters (err=%d)\n", res);
+ return res;
+ }
+ }
+
+ mutex_init(&priv->counters_table.mutex);
- if (dev->caps.max_counters == dev->caps.max_basic_counters)
+ if (mlx4_is_slave(dev)) {
+ for (port_indx = 0; port_indx < dev->caps.num_ports; port_indx++) {
+ INIT_LIST_HEAD(&priv->counters_table.global_port_list[port_indx]);
+ if (dev->caps.def_counter_index[port_indx] != 0xFF) {
+ new_counter_index = kmalloc(sizeof(struct counter_index), GFP_KERNEL);
+ if (!new_counter_index)
+ return -ENOMEM;
+ new_counter_index->index = dev->caps.def_counter_index[port_indx];
+ list_add_tail(&new_counter_index->list, &priv->counters_table.global_port_list[port_indx]);
+ }
+ }
+ mlx4_dbg(dev, "%s: slave allocated %d counters for %d ports\n",
+ __func__, dev->caps.num_ports, dev->caps.num_ports);
return 0;
+ }
- res = mlx4_cmd(dev, MLX4_IF_STATE_EXTENDED, 0, 0,
- MLX4_CMD_SET_IF_STAT, MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
+ nent_pow2 = roundup_pow_of_two(dev->caps.max_counters);
+
+ for (port_indx = 0; port_indx < dev->caps.num_ports; port_indx++) {
+ INIT_LIST_HEAD(&priv->counters_table.global_port_list[port_indx]);
+ /* allocating 2 counters per port for PFs */
+ /* For the PF, the ETH default counters are 0,2; */
+ /* and the RoCE default counters are 1,3 */
+ for (num_counters = 0; num_counters < 2; num_counters++, index++) {
+ new_counter_index = kmalloc(sizeof(struct counter_index), GFP_KERNEL);
+ if (!new_counter_index)
+ return -ENOMEM;
+ new_counter_index->index = index;
+ list_add_tail(&new_counter_index->list,
+ &priv->counters_table.global_port_list[port_indx]);
+ }
+ }
+
+ if (mlx4_is_master(dev)) {
+ for (vf_index = 0; vf_index < dev->num_vfs; vf_index++) {
+ for (port_indx = 0; port_indx < dev->caps.num_ports; port_indx++) {
+ INIT_LIST_HEAD(&priv->counters_table.vf_list[vf_index][port_indx]);
+ new_counter_index = kmalloc(sizeof(struct counter_index), GFP_KERNEL);
+ if (!new_counter_index)
+ return -ENOMEM;
+ if (index < nent_pow2 - 2) {
+ new_counter_index->index = index;
+ index++;
+ } else {
+ new_counter_index->index = MLX4_SINK_COUNTER_INDEX;
+ }
+
+ list_add_tail(&new_counter_index->list,
+ &priv->counters_table.vf_list[vf_index][port_indx]);
+ }
+ }
+
+ res = mlx4_bitmap_init(&priv->counters_table.bitmap,
+ nent_pow2, nent_pow2 - 1,
+ index, 1);
+ mlx4_dbg(dev, "%s: master allocated %d counters for %d VFs\n",
+ __func__, index, dev->num_vfs);
+ } else {
+ res = mlx4_bitmap_init(&priv->counters_table.bitmap,
+ nent_pow2, nent_pow2 - 1,
+ index, 1);
+ mlx4_dbg(dev, "%s: native allocated %d counters for %d ports\n",
+ __func__, index, dev->caps.num_ports);
+ }
- if (res)
- mlx4_err(dev, "Failed to set extended counters (err=%d)\n",
- res);
- return res;
+ return 0;
}
static void mlx4_cleanup_counters_table(struct mlx4_dev *dev)
{
- if (!mlx4_is_slave(dev) &&
- (dev->caps.flags & MLX4_DEV_CAP_FLAG_COUNTERS))
- mlx4_bitmap_cleanup(&mlx4_priv(dev)->counters_bitmap);
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ int i, j;
+ struct counter_index *port, *tmp_port;
+ struct counter_index *vf, *tmp_vf;
+
+ mutex_lock(&priv->counters_table.mutex);
+
+ if (dev->caps.flags & MLX4_DEV_CAP_FLAG_COUNTERS) {
+ for (i = 0; i < dev->caps.num_ports; i++) {
+ list_for_each_entry_safe(port, tmp_port,
+ &priv->counters_table.global_port_list[i],
+ list) {
+ list_del(&port->list);
+ kfree(port);
+ }
+ }
+ if (!mlx4_is_slave(dev)) {
+ for (i = 0; i < dev->num_vfs; i++) {
+ for (j = 0; j < dev->caps.num_ports; j++) {
+ list_for_each_entry_safe(vf, tmp_vf,
+ &priv->counters_table.vf_list[i][j],
+ list) {
+ /* clear the counter statistic */
+ if (__mlx4_clear_if_stat(dev, vf->index))
+ mlx4_dbg(dev, "%s: reset counter %d failed\n",
+ __func__, vf->index);
+ list_del(&vf->list);
+ kfree(vf);
+ }
+ }
+ }
+ mlx4_bitmap_cleanup(&priv->counters_table.bitmap);
+ }
+ }
+ mutex_unlock(&priv->counters_table.mutex);
}
-int __mlx4_counter_alloc(struct mlx4_dev *dev, u32 *idx)
+int __mlx4_slave_counters_free(struct mlx4_dev *dev, int slave)
{
struct mlx4_priv *priv = mlx4_priv(dev);
+ int i, first;
+ struct counter_index *vf, *tmp_vf;
+
+ /* clean VF's counters for the next useg */
+ if (slave > 0 && slave <= dev->num_vfs) {
+ mlx4_dbg(dev, "%s: free counters of slave(%d)\n"
+ , __func__, slave);
+
+ mutex_lock(&priv->counters_table.mutex);
+ for (i = 0; i < dev->caps.num_ports; i++) {
+ first = 0;
+ list_for_each_entry_safe(vf, tmp_vf,
+ &priv->counters_table.vf_list[slave - 1][i],
+ list) {
+ /* clear the counter statistic */
+ if (__mlx4_clear_if_stat(dev, vf->index))
+ mlx4_dbg(dev, "%s: reset counter %d failed\n",
+ __func__, vf->index);
+ if (first++ && vf->index != MLX4_SINK_COUNTER_INDEX) {
+ mlx4_dbg(dev, "%s: delete counter index %d for slave %d and port %d\n"
+ , __func__, vf->index, slave, i + 1);
+ mlx4_bitmap_free(&priv->counters_table.bitmap, vf->index, MLX4_USE_RR);
+ list_del(&vf->list);
+ kfree(vf);
+ } else {
+ mlx4_dbg(dev, "%s: can't delete default counter index %d for slave %d and port %d\n"
+ , __func__, vf->index, slave, i + 1);
+ }
+ }
+ }
+ mutex_unlock(&priv->counters_table.mutex);
+ }
+
+ return 0;
+}
+
+int __mlx4_counter_alloc(struct mlx4_dev *dev, int slave, int port, u32 *idx)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ struct counter_index *new_counter_index;
if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_COUNTERS))
return -ENOENT;
- *idx = mlx4_bitmap_alloc(&priv->counters_bitmap);
- if (*idx == -1)
- return -ENOMEM;
+ if ((slave > MLX4_MAX_NUM_VF) || (slave < 0) ||
+ (port < 0) || (port > MLX4_MAX_PORTS)) {
+ mlx4_dbg(dev, "%s: invalid slave(%d) or port(%d) index\n",
+ __func__, slave, port);
+ return -EINVAL;
+ }
+ /* handle old guest request does not support request by port index */
+ if (port == 0) {
+ *idx = MLX4_SINK_COUNTER_INDEX;
+ mlx4_dbg(dev, "%s: allocated default counter index %d for slave %d port %d\n"
+ , __func__, *idx, slave, port);
+ return 0;
+ }
+
+ mutex_lock(&priv->counters_table.mutex);
+
+ *idx = mlx4_bitmap_alloc(&priv->counters_table.bitmap);
+ /* if no resources return the default counter of the slave and port */
+ if (*idx == -1) {
+ if (slave == 0) { /* its the ethernet counter ?????? */
+ new_counter_index = list_entry(priv->counters_table.global_port_list[port - 1].next,
+ struct counter_index,
+ list);
+ } else {
+ new_counter_index = list_entry(priv->counters_table.vf_list[slave - 1][port - 1].next,
+ struct counter_index,
+ list);
+ }
+
+ *idx = new_counter_index->index;
+ mlx4_dbg(dev, "%s: allocated defualt counter index %d for slave %d port %d\n"
+ , __func__, *idx, slave, port);
+ goto out;
+ }
+
+ if (slave == 0) { /* native or master */
+ new_counter_index = kmalloc(sizeof(struct counter_index), GFP_KERNEL);
+ if (!new_counter_index)
+ goto no_mem;
+ new_counter_index->index = *idx;
+ list_add_tail(&new_counter_index->list, &priv->counters_table.global_port_list[port - 1]);
+ } else {
+ new_counter_index = kmalloc(sizeof(struct counter_index), GFP_KERNEL);
+ if (!new_counter_index)
+ goto no_mem;
+ new_counter_index->index = *idx;
+ list_add_tail(&new_counter_index->list, &priv->counters_table.vf_list[slave - 1][port - 1]);
+ }
+
+ mlx4_dbg(dev, "%s: allocated counter index %d for slave %d port %d\n"
+ , __func__, *idx, slave, port);
+out:
+ mutex_unlock(&priv->counters_table.mutex);
return 0;
+
+no_mem:
+ mlx4_bitmap_free(&priv->counters_table.bitmap, *idx, MLX4_USE_RR);
+ mutex_unlock(&priv->counters_table.mutex);
+ *idx = MLX4_SINK_COUNTER_INDEX;
+ mlx4_dbg(dev, "%s: failed err (%d)\n"
+ , __func__, -ENOMEM);
+ return -ENOMEM;
}
-int mlx4_counter_alloc(struct mlx4_dev *dev, u32 *idx)
+int mlx4_counter_alloc(struct mlx4_dev *dev, u8 port, u32 *idx)
{
u64 out_param;
int err;
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ struct counter_index *new_counter_index, *c_index;
if (mlx4_is_mfunc(dev)) {
- err = mlx4_cmd_imm(dev, 0, &out_param, RES_COUNTER,
+ err = mlx4_cmd_imm(dev, 0, &out_param,
+ ((u32) port) << 8 | (u32) RES_COUNTER,
RES_OP_RESERVE, MLX4_CMD_ALLOC_RES,
MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
- if (!err)
+ if (!err) {
*idx = get_param_l(&out_param);
-
+ if (*idx == MLX4_SINK_COUNTER_INDEX)
+ return -ENOSPC;
+
+ mutex_lock(&priv->counters_table.mutex);
+ c_index = list_entry(priv->counters_table.global_port_list[port - 1].next,
+ struct counter_index,
+ list);
+ mutex_unlock(&priv->counters_table.mutex);
+ if (c_index->index == *idx)
+ return -EEXIST;
+
+ if (mlx4_is_slave(dev)) {
+ new_counter_index = kmalloc(sizeof(struct counter_index), GFP_KERNEL);
+ if (!new_counter_index) {
+ mlx4_counter_free(dev, port, *idx);
+ return -ENOMEM;
+ }
+ new_counter_index->index = *idx;
+ mutex_lock(&priv->counters_table.mutex);
+ list_add_tail(&new_counter_index->list, &priv->counters_table.global_port_list[port - 1]);
+ mutex_unlock(&priv->counters_table.mutex);
+ mlx4_dbg(dev, "%s: allocated counter index %d for port %d\n"
+ , __func__, *idx, port);
+ }
+ }
return err;
}
- return __mlx4_counter_alloc(dev, idx);
+ return __mlx4_counter_alloc(dev, 0, port, idx);
}
EXPORT_SYMBOL_GPL(mlx4_counter_alloc);
-void __mlx4_counter_free(struct mlx4_dev *dev, u32 idx)
+void __mlx4_counter_free(struct mlx4_dev *dev, int slave, int port, u32 idx)
{
- mlx4_bitmap_free(&mlx4_priv(dev)->counters_bitmap, idx);
- return;
+ /* check if native or slave and deletes acordingly */
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ struct counter_index *pf, *tmp_pf;
+ struct counter_index *vf, *tmp_vf;
+ int first;
+
+
+ if (idx == MLX4_SINK_COUNTER_INDEX) {
+ mlx4_dbg(dev, "%s: try to delete default counter index %d for port %d\n"
+ , __func__, idx, port);
+ return;
+ }
+
+ if ((slave > MLX4_MAX_NUM_VF) || (slave < 0) ||
+ (port < 0) || (port > MLX4_MAX_PORTS)) {
+ mlx4_warn(dev, "%s: deletion failed due to invalid slave(%d) or port(%d) index\n"
+ , __func__, slave, idx);
+ return;
+ }
+
+ mutex_lock(&priv->counters_table.mutex);
+ if (slave == 0) {
+ first = 0;
+ list_for_each_entry_safe(pf, tmp_pf,
+ &priv->counters_table.global_port_list[port - 1],
+ list) {
+ /* the first 2 counters are reserved */
+ if (pf->index == idx) {
+ /* clear the counter statistic */
+ if (__mlx4_clear_if_stat(dev, pf->index))
+ mlx4_dbg(dev, "%s: reset counter %d failed\n",
+ __func__, pf->index);
+ if (1 < first && idx != MLX4_SINK_COUNTER_INDEX) {
+ list_del(&pf->list);
+ kfree(pf);
+ mlx4_dbg(dev, "%s: delete counter index %d for native device (%d) port %d\n"
+ , __func__, idx, slave, port);
+ mlx4_bitmap_free(&priv->counters_table.bitmap, idx, MLX4_USE_RR);
+ goto out;
+ } else {
+ mlx4_dbg(dev, "%s: can't delete default counter index %d for native device (%d) port %d\n"
+ , __func__, idx, slave, port);
+ goto out;
+ }
+ }
+ first++;
+ }
+ mlx4_dbg(dev, "%s: can't delete counter index %d for native device (%d) port %d\n"
+ , __func__, idx, slave, port);
+ } else {
+ first = 0;
+ list_for_each_entry_safe(vf, tmp_vf,
+ &priv->counters_table.vf_list[slave - 1][port - 1],
+ list) {
+ /* the first element is reserved */
+ if (vf->index == idx) {
+ /* clear the counter statistic */
+ if (__mlx4_clear_if_stat(dev, vf->index))
+ mlx4_dbg(dev, "%s: reset counter %d failed\n",
+ __func__, vf->index);
+ if (first) {
+ list_del(&vf->list);
+ kfree(vf);
+ mlx4_dbg(dev, "%s: delete counter index %d for slave %d port %d\n",
+ __func__, idx, slave, port);
+ mlx4_bitmap_free(&priv->counters_table.bitmap, idx, MLX4_USE_RR);
+ goto out;
+ } else {
+ mlx4_dbg(dev, "%s: can't delete default slave (%d) counter index %d for port %d\n"
+ , __func__, slave, idx, port);
+ goto out;
+ }
+ }
+ first++;
+ }
+ mlx4_dbg(dev, "%s: can't delete slave (%d) counter index %d for port %d\n"
+ , __func__, slave, idx, port);
+ }
+
+out:
+ mutex_unlock(&priv->counters_table.mutex);
}
-void mlx4_counter_free(struct mlx4_dev *dev, u32 idx)
+void mlx4_counter_free(struct mlx4_dev *dev, u8 port, u32 idx)
{
u64 in_param = 0;
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ struct counter_index *counter, *tmp_counter;
+ int first = 0;
if (mlx4_is_mfunc(dev)) {
set_param_l(&in_param, idx);
- mlx4_cmd(dev, in_param, RES_COUNTER, RES_OP_RESERVE,
+ mlx4_cmd(dev, in_param,
+ ((u32) port) << 8 | (u32) RES_COUNTER,
+ RES_OP_RESERVE,
MLX4_CMD_FREE_RES, MLX4_CMD_TIME_CLASS_A,
MLX4_CMD_WRAPPED);
+
+ if (mlx4_is_slave(dev) && idx != MLX4_SINK_COUNTER_INDEX) {
+ mutex_lock(&priv->counters_table.mutex);
+ list_for_each_entry_safe(counter, tmp_counter,
+ &priv->counters_table.global_port_list[port - 1],
+ list) {
+ if (counter->index == idx && first++) {
+ list_del(&counter->list);
+ kfree(counter);
+ mlx4_dbg(dev, "%s: delete counter index %d for port %d\n"
+ , __func__, idx, port);
+ mutex_unlock(&priv->counters_table.mutex);
+ return;
+ }
+ }
+ mutex_unlock(&priv->counters_table.mutex);
+ }
+
return;
}
- __mlx4_counter_free(dev, idx);
+ __mlx4_counter_free(dev, 0, port, idx);
}
EXPORT_SYMBOL_GPL(mlx4_counter_free);
+int __mlx4_clear_if_stat(struct mlx4_dev *dev,
+ u8 counter_index)
+{
+ struct mlx4_cmd_mailbox *if_stat_mailbox = NULL;
+ int err = 0;
+ u32 if_stat_in_mod = (counter_index & 0xff) | (1 << 31);
+
+ if (counter_index == MLX4_SINK_COUNTER_INDEX)
+ return -EINVAL;
+
+ if (mlx4_is_slave(dev))
+ return 0;
+
+ if_stat_mailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(if_stat_mailbox)) {
+ err = PTR_ERR(if_stat_mailbox);
+ return err;
+ }
+
+ err = mlx4_cmd_box(dev, 0, if_stat_mailbox->dma, if_stat_in_mod, 0,
+ MLX4_CMD_QUERY_IF_STAT, MLX4_CMD_TIME_CLASS_C,
+ MLX4_CMD_NATIVE);
+
+ mlx4_free_cmd_mailbox(dev, if_stat_mailbox);
+ return err;
+}
+
+u8 mlx4_get_default_counter_index(struct mlx4_dev *dev, int slave, int port)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ struct counter_index *new_counter_index;
+
+ if (dev->caps.port_type[port] == MLX4_PORT_TYPE_IB) {
+ mlx4_dbg(dev, "%s: return counter index %d for slave %d port (MLX4_PORT_TYPE_IB) %d\n",
+ __func__, MLX4_SINK_COUNTER_INDEX, slave, port);
+ return (u8)MLX4_SINK_COUNTER_INDEX;
+ }
+
+ mutex_lock(&priv->counters_table.mutex);
+ if (slave == 0) {
+ new_counter_index = list_entry(priv->counters_table.global_port_list[port - 1].next,
+ struct counter_index,
+ list);
+ } else {
+ new_counter_index = list_entry(priv->counters_table.vf_list[slave - 1][port - 1].next,
+ struct counter_index,
+ list);
+ }
+ mutex_unlock(&priv->counters_table.mutex);
+
+ mlx4_dbg(dev, "%s: return counter index %d for slave %d port %d\n",
+ __func__, new_counter_index->index, slave, port);
+
+
+ return (u8)new_counter_index->index;
+}
+
+int mlx4_get_vport_ethtool_stats(struct mlx4_dev *dev, int port,
+ struct mlx4_en_vport_stats *vport_stats,
+ int reset)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ struct mlx4_cmd_mailbox *if_stat_mailbox = NULL;
+ union mlx4_counter *counter;
+ int err = 0;
+ u32 if_stat_in_mod;
+ struct counter_index *vport, *tmp_vport;
+
+ if (!vport_stats)
+ return -EINVAL;
+
+ if_stat_mailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(if_stat_mailbox)) {
+ err = PTR_ERR(if_stat_mailbox);
+ return err;
+ }
+
+ mutex_lock(&priv->counters_table.mutex);
+ list_for_each_entry_safe(vport, tmp_vport,
+ &priv->counters_table.global_port_list[port - 1],
+ list) {
+ if (vport->index == MLX4_SINK_COUNTER_INDEX)
+ continue;
+
+ memset(if_stat_mailbox->buf, 0, sizeof(union mlx4_counter));
+ if_stat_in_mod = (vport->index & 0xff) | ((reset & 1) << 31);
+ err = mlx4_cmd_box(dev, 0, if_stat_mailbox->dma,
+ if_stat_in_mod, 0,
+ MLX4_CMD_QUERY_IF_STAT,
+ MLX4_CMD_TIME_CLASS_C,
+ MLX4_CMD_NATIVE);
+ if (err) {
+ mlx4_dbg(dev, "%s: failed to read statistics for counter index %d\n",
+ __func__, vport->index);
+ goto if_stat_out;
+ }
+ counter = (union mlx4_counter *)if_stat_mailbox->buf;
+ if ((counter->control.cnt_mode & 0xf) == 1) {
+ vport_stats->rx_broadcast_packets += be64_to_cpu(counter->ext.counters[0].IfRxBroadcastFrames);
+ vport_stats->rx_unicast_packets += be64_to_cpu(counter->ext.counters[0].IfRxUnicastFrames);
+ vport_stats->rx_multicast_packets += be64_to_cpu(counter->ext.counters[0].IfRxMulticastFrames);
+ vport_stats->tx_broadcast_packets += be64_to_cpu(counter->ext.counters[0].IfTxBroadcastFrames);
+ vport_stats->tx_unicast_packets += be64_to_cpu(counter->ext.counters[0].IfTxUnicastFrames);
+ vport_stats->tx_multicast_packets += be64_to_cpu(counter->ext.counters[0].IfTxMulticastFrames);
+ vport_stats->rx_broadcast_bytes += be64_to_cpu(counter->ext.counters[0].IfRxBroadcastOctets);
+ vport_stats->rx_unicast_bytes += be64_to_cpu(counter->ext.counters[0].IfRxUnicastOctets);
+ vport_stats->rx_multicast_bytes += be64_to_cpu(counter->ext.counters[0].IfRxMulticastOctets);
+ vport_stats->tx_broadcast_bytes += be64_to_cpu(counter->ext.counters[0].IfTxBroadcastOctets);
+ vport_stats->tx_unicast_bytes += be64_to_cpu(counter->ext.counters[0].IfTxUnicastOctets);
+ vport_stats->tx_multicast_bytes += be64_to_cpu(counter->ext.counters[0].IfTxMulticastOctets);
+ vport_stats->rx_errors += be64_to_cpu(counter->ext.counters[0].IfRxErrorFrames);
+ vport_stats->rx_dropped += be64_to_cpu(counter->ext.counters[0].IfRxNoBufferFrames);
+ vport_stats->tx_errors += be64_to_cpu(counter->ext.counters[0].IfTxDroppedFrames);
+ }
+ }
+
+if_stat_out:
+ mutex_unlock(&priv->counters_table.mutex);
+ mlx4_free_cmd_mailbox(dev, if_stat_mailbox);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(mlx4_get_vport_ethtool_stats);
+
static int mlx4_setup_hca(struct mlx4_dev *dev)
{
struct mlx4_priv *priv = mlx4_priv(dev);
@@ -1862,11 +2721,21 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
goto err_xrcd_table_free;
}
+ if (!mlx4_is_slave(dev)) {
+ err = mlx4_init_mcg_table(dev);
+ if (err) {
+ mlx4_err(dev, "Failed to initialize "
+ "multicast group table (err=%d), aborting.\n",
+ err);
+ goto err_mr_table_free;
+ }
+ }
+
err = mlx4_init_eq_table(dev);
if (err) {
mlx4_err(dev, "Failed to initialize "
"event queue table (err=%d), aborting.\n", err);
- goto err_mr_table_free;
+ goto err_mcg_table_free;
}
err = mlx4_cmd_use_events(dev);
@@ -1917,22 +2786,14 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
goto err_srq_table_free;
}
- if (!mlx4_is_slave(dev)) {
- err = mlx4_init_mcg_table(dev);
- if (err) {
- mlx4_err(dev, "Failed to initialize "
- "multicast group table (err=%d), aborting.\n",
- err);
- goto err_qp_table_free;
- }
-
- err = mlx4_init_counters_table(dev);
- if (err && err != -ENOENT) {
- mlx4_err(dev, "Failed to initialize counters table (err=%d), "
- "aborting.\n", err);
- goto err_mcg_table_free;
- }
+ err = mlx4_init_counters_table(dev);
+ if (err && err != -ENOENT) {
+ mlx4_err(dev, "Failed to initialize counters table (err=%d), "
+ "aborting.\n", err);
+ goto err_qp_table_free;
+ }
+ if (!mlx4_is_slave(dev)) {
for (port = 1; port <= dev->caps.num_ports; port++) {
ib_port_default_caps = 0;
err = mlx4_get_port_ib_caps(dev, port,
@@ -1954,10 +2815,7 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
}
}
- if (mlx4_is_mfunc(dev))
- dev->caps.port_ib_mtu[port] = IB_MTU_2048;
- else
- dev->caps.port_ib_mtu[port] = IB_MTU_4096;
+ dev->caps.port_ib_mtu[port] = IB_MTU_4096;
err = mlx4_SET_PORT(dev, port, mlx4_is_master(dev) ?
dev->caps.pkey_table_len[port] : -1);
@@ -1974,9 +2832,6 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
err_counters_table_free:
mlx4_cleanup_counters_table(dev);
-err_mcg_table_free:
- mlx4_cleanup_mcg_table(dev);
-
err_qp_table_free:
mlx4_cleanup_qp_table(dev);
@@ -1992,6 +2847,10 @@ err_cmd_poll:
err_eq_table_free:
mlx4_cleanup_eq_table(dev);
+err_mcg_table_free:
+ if (!mlx4_is_slave(dev))
+ mlx4_cleanup_mcg_table(dev);
+
err_mr_table_free:
mlx4_cleanup_mr_table(dev);
@@ -2026,6 +2885,9 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)
nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs,
nreq);
+ if (msi_x > 1 && !mlx4_is_mfunc(dev))
+ nreq = min_t(int, nreq, msi_x);
+
entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL);
if (!entries)
goto no_msi;
@@ -2237,6 +3099,7 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data)
struct mlx4_dev *dev;
int err;
int port;
+ int nvfs, prb_vf;
pr_info(DRV_NAME ": Initializing %s\n", pci_name(pdev));
@@ -2246,13 +3109,16 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data)
"aborting.\n");
return err;
}
- if (num_vfs > MLX4_MAX_NUM_VF) {
+
+ mlx4_get_val(num_vfs.dbdf2val.tbl, pci_physfn(pdev), 0, &nvfs);
+ mlx4_get_val(probe_vf.dbdf2val.tbl, pci_physfn(pdev), 0, &prb_vf);
+ if (nvfs > MLX4_MAX_NUM_VF) {
dev_err(&pdev->dev, "There are more VF's (%d) than allowed(%d)\n",
- num_vfs, MLX4_MAX_NUM_VF);
+ nvfs, MLX4_MAX_NUM_VF);
return -EINVAL;
}
- if (num_vfs < 0) {
+ if (nvfs < 0) {
dev_err(&pdev->dev, "num_vfs module parameter cannot be negative\n");
return -EINVAL;
}
@@ -2315,6 +3181,7 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data)
dev = &priv->dev;
dev->pdev = pdev;
+ INIT_LIST_HEAD(&priv->dev_list);
INIT_LIST_HEAD(&priv->ctx_list);
spin_lock_init(&priv->ctx_lock);
@@ -2332,7 +3199,7 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data)
if (pci_dev_data & MLX4_PCI_DEV_IS_VF) {
/* When acting as pf, we normally skip vfs unless explicitly
* requested to probe them. */
- if (num_vfs && extended_func_num(pdev) > probe_vf) {
+ if (nvfs && extended_func_num(pdev) > prb_vf) {
mlx4_warn(dev, "Skipping virtual function:%d\n",
extended_func_num(pdev));
err = -ENODEV;
@@ -2356,9 +3223,9 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data)
}
}
- if (num_vfs) {
- mlx4_warn(dev, "Enabling SR-IOV with %d VFs\n", num_vfs);
- err = pci_enable_sriov(pdev, num_vfs);
+ if (nvfs) {
+ mlx4_warn(dev, "Enabling SR-IOV with %d VFs\n", nvfs);
+ err = pci_enable_sriov(pdev, nvfs);
if (err) {
mlx4_err(dev, "Failed to enable SR-IOV, continuing without SR-IOV (err = %d).\n",
err);
@@ -2367,7 +3234,7 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data)
mlx4_warn(dev, "Running in master mode\n");
dev->flags |= MLX4_FLAG_SRIOV |
MLX4_FLAG_MASTER;
- dev->num_vfs = num_vfs;
+ dev->num_vfs = nvfs;
}
}
@@ -2481,10 +3348,9 @@ slave_start:
if (err)
goto err_port;
- err = mlx4_sense_init(dev);
- if (err)
- goto err_port;
+ mlx4_request_modules(dev);
+ mlx4_sense_init(dev);
mlx4_start_sense(dev);
priv->pci_dev_data = pci_dev_data;
@@ -2497,12 +3363,12 @@ err_port:
mlx4_cleanup_port_info(&priv->port[port]);
mlx4_cleanup_counters_table(dev);
- mlx4_cleanup_mcg_table(dev);
mlx4_cleanup_qp_table(dev);
mlx4_cleanup_srq_table(dev);
mlx4_cleanup_cq_table(dev);
mlx4_cmd_use_polling(dev);
mlx4_cleanup_eq_table(dev);
+ mlx4_cleanup_mcg_table(dev);
mlx4_cleanup_mr_table(dev);
mlx4_cleanup_xrcd_table(dev);
mlx4_cleanup_pd_table(dev);
@@ -2516,8 +3382,10 @@ err_free_eq:
mlx4_free_eq_table(dev);
err_master_mfunc:
- if (mlx4_is_master(dev))
+ if (mlx4_is_master(dev)) {
+ mlx4_free_resource_tracker(dev, RES_TR_FREE_STRUCTS_ONLY);
mlx4_multi_func_cleanup(dev);
+ }
if (mlx4_is_slave(dev)) {
kfree(dev->caps.qp0_tunnel);
@@ -2579,7 +3447,7 @@ static void mlx4_remove_one(struct pci_dev *pdev)
if (mlx4_how_many_lives_vf(dev))
mlx4_err(dev, "Removing PF when there are assigned VF's !!!\n");
}
- mlx4_sense_cleanup(dev);
+ mlx4_stop_sense(dev);
mlx4_unregister_device(dev);
for (p = 1; p <= dev->caps.num_ports; p++) {
@@ -2592,12 +3460,12 @@ static void mlx4_remove_one(struct pci_dev *pdev)
RES_TR_FREE_SLAVES_ONLY);
mlx4_cleanup_counters_table(dev);
- mlx4_cleanup_mcg_table(dev);
mlx4_cleanup_qp_table(dev);
mlx4_cleanup_srq_table(dev);
mlx4_cleanup_cq_table(dev);
mlx4_cmd_use_polling(dev);
mlx4_cleanup_eq_table(dev);
+ mlx4_cleanup_mcg_table(dev);
mlx4_cleanup_mr_table(dev);
mlx4_cleanup_xrcd_table(dev);
mlx4_cleanup_pd_table(dev);
@@ -2641,15 +3509,48 @@ static void mlx4_remove_one(struct pci_dev *pdev)
}
}
+static int restore_current_port_types(struct mlx4_dev *dev,
+ enum mlx4_port_type *types,
+ enum mlx4_port_type *poss_types)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ int err, i;
+
+ mlx4_stop_sense(dev);
+ mutex_lock(&priv->port_mutex);
+ for (i = 0; i < dev->caps.num_ports; i++)
+ dev->caps.possible_type[i + 1] = poss_types[i];
+ err = mlx4_change_port_types(dev, types);
+ mlx4_start_sense(dev);
+ mutex_unlock(&priv->port_mutex);
+ return err;
+}
+
int mlx4_restart_one(struct pci_dev *pdev)
{
struct mlx4_dev *dev = pci_get_drvdata(pdev);
struct mlx4_priv *priv = mlx4_priv(dev);
- int pci_dev_data;
+ enum mlx4_port_type curr_type[MLX4_MAX_PORTS];
+ enum mlx4_port_type poss_type[MLX4_MAX_PORTS];
+ int pci_dev_data, err, i;
pci_dev_data = priv->pci_dev_data;
+ for (i = 0; i < dev->caps.num_ports; i++) {
+ curr_type[i] = dev->caps.port_type[i + 1];
+ poss_type[i] = dev->caps.possible_type[i + 1];
+ }
+
mlx4_remove_one(pdev);
- return __mlx4_init_one(pdev, pci_dev_data);
+ err = __mlx4_init_one(pdev, pci_dev_data);
+ if (err)
+ return err;
+
+ dev = pci_get_drvdata(pdev);
+ err = restore_current_port_types(dev, curr_type, poss_type);
+ if (err)
+ mlx4_err(dev, "mlx4_restart_one: could not restore original port types (%d)\n",
+ err);
+ return 0;
}
static DEFINE_PCI_DEVICE_TABLE(mlx4_pci_table) = {
@@ -2725,16 +3626,6 @@ static int suspend(struct pci_dev *pdev, pm_message_t state)
{
mlx4_remove_one(pdev);
- if (mlx4_log_num_mgm_entry_size != -1 &&
- (mlx4_log_num_mgm_entry_size < MLX4_MIN_MGM_LOG_ENTRY_SIZE ||
- mlx4_log_num_mgm_entry_size > MLX4_MAX_MGM_LOG_ENTRY_SIZE)) {
- pr_warning("mlx4_core: mlx4_log_num_mgm_entry_size (%d) not "
- "in legal range (-1 or %d..%d)\n",
- mlx4_log_num_mgm_entry_size,
- MLX4_MIN_MGM_LOG_ENTRY_SIZE,
- MLX4_MAX_MGM_LOG_ENTRY_SIZE);
- return -1;
- }
return 0;
}
@@ -2745,16 +3636,47 @@ static int resume(struct pci_dev *pdev)
static struct pci_driver mlx4_driver = {
.name = DRV_NAME,
- .id_table = (struct pci_device_id*)mlx4_pci_table,
+ .id_table = mlx4_pci_table,
.probe = mlx4_init_one,
.remove = __devexit_p(mlx4_remove_one),
.suspend = suspend,
.resume = resume,
- .err_handler = (struct pci_error_handlers*)&mlx4_err_handler,
+ .err_handler = &mlx4_err_handler,
};
static int __init mlx4_verify_params(void)
{
+ int status;
+
+ status = update_defaults(&port_type_array);
+ if (status == INVALID_STR) {
+ if (mlx4_fill_dbdf2val_tbl(&port_type_array.dbdf2val))
+ return -1;
+ } else if (status == INVALID_DATA) {
+ return -1;
+ }
+
+ status = update_defaults(&num_vfs);
+ if (status == INVALID_STR) {
+ if (mlx4_fill_dbdf2val_tbl(&num_vfs.dbdf2val))
+ return -1;
+ } else if (status == INVALID_DATA) {
+ return -1;
+ }
+
+ status = update_defaults(&probe_vf);
+ if (status == INVALID_STR) {
+ if (mlx4_fill_dbdf2val_tbl(&probe_vf.dbdf2val))
+ return -1;
+ } else if (status == INVALID_DATA) {
+ return -1;
+ }
+
+ if (msi_x < 0) {
+ pr_warn("mlx4_core: bad msi_x: %d\n", msi_x);
+ return -1;
+ }
+
if ((log_num_mac < 0) || (log_num_mac > 7)) {
pr_warning("mlx4_core: bad num_mac: %d\n", log_num_mac);
return -1;
@@ -2772,12 +3694,6 @@ static int __init mlx4_verify_params(void)
return -1;
}
- /* Check if module param for ports type has legal combination */
- if (port_type_array[0] == false && port_type_array[1] == true) {
- pr_warning("mlx4_core: module parameter configuration ETH/IB is not supported. Switching to default configuration IB/IB\n");
- port_type_array[0] = true;
- }
-
if (mlx4_log_num_mgm_entry_size != -1 &&
(mlx4_log_num_mgm_entry_size < MLX4_MIN_MGM_LOG_ENTRY_SIZE ||
mlx4_log_num_mgm_entry_size > MLX4_MAX_MGM_LOG_ENTRY_SIZE)) {
@@ -2813,15 +3729,16 @@ static int __init mlx4_verify_params(void)
return -1;
}
- if (mod_param_profile.num_mtt && mod_param_profile.num_mtt < 15) {
+ if (mod_param_profile.num_mtt_segs &&
+ mod_param_profile.num_mtt_segs < 15) {
pr_warning("mlx4_core: too low log_num_mtt: %d\n",
- mod_param_profile.num_mtt);
+ mod_param_profile.num_mtt_segs);
return -1;
}
- if (mod_param_profile.num_mtt > MLX4_MAX_LOG_NUM_MTT) {
+ if (mod_param_profile.num_mtt_segs > MLX4_MAX_LOG_NUM_MTT) {
pr_warning("mlx4_core: too high log_num_mtt: %d\n",
- mod_param_profile.num_mtt);
+ mod_param_profile.num_mtt_segs);
return -1;
}
return 0;
@@ -2844,10 +3761,18 @@ static int __init mlx4_init(void)
sys_tune_init();
ret = pci_register_driver(&mlx4_driver);
- if (ret < 0 && enable_sys_tune)
+ if (ret < 0)
+ goto err;
+
+ return 0;
+
+err:
+ if (enable_sys_tune)
sys_tune_fini();
- return ret < 0 ? ret : 0;
+ destroy_workqueue(mlx4_wq);
+
+ return ret;
}
static void __exit mlx4_cleanup(void)
@@ -2862,17 +3787,16 @@ static void __exit mlx4_cleanup(void)
module_init_order(mlx4_init, SI_ORDER_MIDDLE);
module_exit(mlx4_cleanup);
-#undef MODULE_VERSION
#include <sys/module.h>
static int
mlx4_evhand(module_t mod, int event, void *arg)
{
- return (0);
+ return (0);
}
static moduledata_t mlx4_mod = {
- .name = "mlx4",
- .evhand = mlx4_evhand,
+ .name = "mlx4",
+ .evhand = mlx4_evhand,
};
MODULE_VERSION(mlx4, 1);
DECLARE_MODULE(mlx4, mlx4_mod, SI_SUB_OFED_PREINIT, SI_ORDER_ANY);
diff --git a/sys/ofed/drivers/net/mlx4/mcg.c b/sys/ofed/drivers/net/mlx4/mcg.c
index 60ac951..52c52f8 100644
--- a/sys/ofed/drivers/net/mlx4/mcg.c
+++ b/sys/ofed/drivers/net/mlx4/mcg.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved.
- * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -32,8 +32,10 @@
*/
#include <linux/string.h>
+#include <linux/etherdevice.h>
#include <linux/mlx4/cmd.h>
+#include <linux/module.h>
#include "mlx4.h"
@@ -124,9 +126,14 @@ static struct mlx4_promisc_qp *get_promisc_qp(struct mlx4_dev *dev, u8 port,
enum mlx4_steer_type steer,
u32 qpn)
{
- struct mlx4_steer *s_steer = &mlx4_priv(dev)->steer[port - 1];
+ struct mlx4_steer *s_steer;
struct mlx4_promisc_qp *pqp;
+ if (port < 1 || port > dev->caps.num_ports)
+ return NULL;
+
+ s_steer = &mlx4_priv(dev)->steer[port - 1];
+
list_for_each_entry(pqp, &s_steer->promisc_qps[steer], list) {
if (pqp->qpn == qpn)
return pqp;
@@ -153,6 +160,9 @@ static int new_steering_entry(struct mlx4_dev *dev, u8 port,
u32 prot;
int err;
+ if (port < 1 || port > dev->caps.num_ports)
+ return -EINVAL;
+
s_steer = &mlx4_priv(dev)->steer[port - 1];
new_entry = kzalloc(sizeof *new_entry, GFP_KERNEL);
if (!new_entry)
@@ -237,6 +247,9 @@ static int existing_steering_entry(struct mlx4_dev *dev, u8 port,
struct mlx4_promisc_qp *pqp;
struct mlx4_promisc_qp *dqp;
+ if (port < 1 || port > dev->caps.num_ports)
+ return -EINVAL;
+
s_steer = &mlx4_priv(dev)->steer[port - 1];
pqp = get_promisc_qp(dev, port, steer, qpn);
@@ -258,7 +271,7 @@ static int existing_steering_entry(struct mlx4_dev *dev, u8 port,
* we need to add it as a duplicate to this entry
* for future references */
list_for_each_entry(dqp, &entry->duplicates, list) {
- if (qpn == pqp->qpn)
+ if (qpn == dqp->qpn)
return 0; /* qp is already duplicated */
}
@@ -282,6 +295,9 @@ static bool check_duplicate_entry(struct mlx4_dev *dev, u8 port,
struct mlx4_steer_index *tmp_entry, *entry = NULL;
struct mlx4_promisc_qp *dqp, *tmp_dqp;
+ if (port < 1 || port > dev->caps.num_ports)
+ return NULL;
+
s_steer = &mlx4_priv(dev)->steer[port - 1];
/* if qp is not promisc, it cannot be duplicated */
@@ -309,20 +325,24 @@ static bool check_duplicate_entry(struct mlx4_dev *dev, u8 port,
return true;
}
-/* I a steering entry contains only promisc QPs, it can be removed. */
-static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port,
+/*
+ * returns true if all the QPs != tqpn contained in this entry
+ * are Promisc QPs. return false otherwise.
+ */
+static bool promisc_steering_entry(struct mlx4_dev *dev, u8 port,
enum mlx4_steer_type steer,
- unsigned int index, u32 tqpn)
+ unsigned int index, u32 tqpn, u32 *members_count)
{
struct mlx4_steer *s_steer;
struct mlx4_cmd_mailbox *mailbox;
struct mlx4_mgm *mgm;
- struct mlx4_steer_index *entry = NULL, *tmp_entry;
- u32 qpn;
- u32 members_count;
+ u32 m_count;
bool ret = false;
int i;
+ if (port < 1 || port > dev->caps.num_ports)
+ return false;
+
s_steer = &mlx4_priv(dev)->steer[port - 1];
mailbox = mlx4_alloc_cmd_mailbox(dev);
@@ -332,15 +352,42 @@ static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port,
if (mlx4_READ_ENTRY(dev, index, mailbox))
goto out;
- members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
- for (i = 0; i < members_count; i++) {
- qpn = be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK;
+ m_count = be32_to_cpu(mgm->members_count) & 0xffffff;
+ if (members_count)
+ *members_count = m_count;
+
+ for (i = 0; i < m_count; i++) {
+ u32 qpn = be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK;
if (!get_promisc_qp(dev, port, steer, qpn) && qpn != tqpn) {
/* the qp is not promisc, the entry can't be removed */
goto out;
}
}
- /* All the qps currently registered for this entry are promiscuous,
+ ret = true;
+out:
+ mlx4_free_cmd_mailbox(dev, mailbox);
+ return ret;
+}
+
+/* IF a steering entry contains only promisc QPs, it can be removed. */
+static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port,
+ enum mlx4_steer_type steer,
+ unsigned int index, u32 tqpn)
+{
+ struct mlx4_steer *s_steer;
+ struct mlx4_steer_index *entry = NULL, *tmp_entry;
+ u32 members_count;
+ bool ret = false;
+
+ if (port < 1 || port > dev->caps.num_ports)
+ return NULL;
+
+ s_steer = &mlx4_priv(dev)->steer[port - 1];
+
+ if (!promisc_steering_entry(dev, port, steer, index, tqpn, &members_count))
+ goto out;
+
+ /* All the qps currently registered for this entry are promiscuous,
* Checking for duplicates */
ret = true;
list_for_each_entry_safe(entry, tmp_entry, &s_steer->steer_entries[steer], list) {
@@ -369,7 +416,6 @@ static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port,
}
out:
- mlx4_free_cmd_mailbox(dev, mailbox);
return ret;
}
@@ -389,6 +435,9 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 port,
int err;
struct mlx4_priv *priv = mlx4_priv(dev);
+ if (port < 1 || port > dev->caps.num_ports)
+ return -EINVAL;
+
s_steer = &mlx4_priv(dev)->steer[port - 1];
mutex_lock(&priv->mcg_table.mutex);
@@ -412,43 +461,45 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 port,
}
mgm = mailbox->buf;
- /* the promisc qp needs to be added for each one of the steering
- * entries, if it already exists, needs to be added as a duplicate
- * for this entry */
- list_for_each_entry(entry, &s_steer->steer_entries[steer], list) {
- err = mlx4_READ_ENTRY(dev, entry->index, mailbox);
- if (err)
- goto out_mailbox;
+ if (!(mlx4_is_mfunc(dev) && steer == MLX4_UC_STEER)) {
+ /* the promisc qp needs to be added for each one of the steering
+ * entries, if it already exists, needs to be added as a duplicate
+ * for this entry */
+ list_for_each_entry(entry, &s_steer->steer_entries[steer], list) {
+ err = mlx4_READ_ENTRY(dev, entry->index, mailbox);
+ if (err)
+ goto out_mailbox;
- members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
- prot = be32_to_cpu(mgm->members_count) >> 30;
- found = false;
- for (i = 0; i < members_count; i++) {
- if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qpn) {
- /* Entry already exists, add to duplicates */
- dqp = kmalloc(sizeof *dqp, GFP_KERNEL);
- if (!dqp) {
+ members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
+ prot = be32_to_cpu(mgm->members_count) >> 30;
+ found = false;
+ for (i = 0; i < members_count; i++) {
+ if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qpn) {
+ /* Entry already exists, add to duplicates */
+ dqp = kmalloc(sizeof *dqp, GFP_KERNEL);
+ if (!dqp) {
+ err = -ENOMEM;
+ goto out_mailbox;
+ }
+ dqp->qpn = qpn;
+ list_add_tail(&dqp->list, &entry->duplicates);
+ found = true;
+ }
+ }
+ if (!found) {
+ /* Need to add the qpn to mgm */
+ if (members_count == dev->caps.num_qp_per_mgm) {
+ /* entry is full */
err = -ENOMEM;
goto out_mailbox;
}
- dqp->qpn = qpn;
- list_add_tail(&dqp->list, &entry->duplicates);
- found = true;
+ mgm->qp[members_count++] = cpu_to_be32(qpn & MGM_QPN_MASK);
+ mgm->members_count = cpu_to_be32(members_count | (prot << 30));
+ err = mlx4_WRITE_ENTRY(dev, entry->index, mailbox);
+ if (err)
+ goto out_mailbox;
}
}
- if (!found) {
- /* Need to add the qpn to mgm */
- if (members_count == dev->caps.num_qp_per_mgm) {
- /* entry is full */
- err = -ENOMEM;
- goto out_mailbox;
- }
- mgm->qp[members_count++] = cpu_to_be32(qpn & MGM_QPN_MASK);
- mgm->members_count = cpu_to_be32(members_count | (prot << 30));
- err = mlx4_WRITE_ENTRY(dev, entry->index, mailbox);
- if (err)
- goto out_mailbox;
- }
}
/* add the new qpn to list of promisc qps */
@@ -492,7 +543,7 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 port,
struct mlx4_steer *s_steer;
struct mlx4_cmd_mailbox *mailbox;
struct mlx4_mgm *mgm;
- struct mlx4_steer_index *entry;
+ struct mlx4_steer_index *entry, *tmp_entry;
struct mlx4_promisc_qp *pqp;
struct mlx4_promisc_qp *dqp;
u32 members_count;
@@ -501,6 +552,9 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 port,
int i, loc = -1;
int err;
+ if (port < 1 || port > dev->caps.num_ports)
+ return -EINVAL;
+
s_steer = &mlx4_priv(dev)->steer[port - 1];
mutex_lock(&priv->mcg_table.mutex);
@@ -533,49 +587,58 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 port,
if (err)
goto out_mailbox;
- /* remove the qp from all the steering entries*/
- list_for_each_entry(entry, &s_steer->steer_entries[steer], list) {
- found = false;
- list_for_each_entry(dqp, &entry->duplicates, list) {
- if (dqp->qpn == qpn) {
- found = true;
- break;
- }
- }
- if (found) {
- /* a duplicate, no need to change the mgm,
- * only update the duplicates list */
- list_del(&dqp->list);
- kfree(dqp);
- } else {
- err = mlx4_READ_ENTRY(dev, entry->index, mailbox);
- if (err)
- goto out_mailbox;
- members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
- for (i = 0; i < members_count; ++i)
- if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qpn) {
- loc = i;
+ if (!(mlx4_is_mfunc(dev) && steer == MLX4_UC_STEER)) {
+ /* remove the qp from all the steering entries*/
+ list_for_each_entry_safe(entry, tmp_entry, &s_steer->steer_entries[steer], list) {
+ found = false;
+ list_for_each_entry(dqp, &entry->duplicates, list) {
+ if (dqp->qpn == qpn) {
+ found = true;
break;
}
-
- if (loc < 0) {
- mlx4_err(dev, "QP %06x wasn't found in entry %d\n",
- qpn, entry->index);
- err = -EINVAL;
- goto out_mailbox;
}
+ if (found) {
+ /* a duplicate, no need to change the mgm,
+ * only update the duplicates list */
+ list_del(&dqp->list);
+ kfree(dqp);
+ } else {
+ err = mlx4_READ_ENTRY(dev, entry->index, mailbox);
+ if (err)
+ goto out_mailbox;
+ members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
+ if (!members_count) {
+ mlx4_warn(dev, "QP %06x wasn't found in entry %x mcount=0."
+ " deleting entry...\n", qpn, entry->index);
+ list_del(&entry->list);
+ kfree(entry);
+ continue;
+ }
- /* copy the last QP in this MGM over removed QP */
- mgm->qp[loc] = mgm->qp[members_count - 1];
- mgm->qp[members_count - 1] = 0;
- mgm->members_count = cpu_to_be32(--members_count |
- (MLX4_PROT_ETH << 30));
+ for (i = 0; i < members_count; ++i)
+ if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qpn) {
+ loc = i;
+ break;
+ }
- err = mlx4_WRITE_ENTRY(dev, entry->index, mailbox);
- if (err)
+ if (loc < 0) {
+ mlx4_err(dev, "QP %06x wasn't found in entry %d\n",
+ qpn, entry->index);
+ err = -EINVAL;
goto out_mailbox;
- }
+ }
+ /* copy the last QP in this MGM over removed QP */
+ mgm->qp[loc] = mgm->qp[members_count - 1];
+ mgm->qp[members_count - 1] = 0;
+ mgm->members_count = cpu_to_be32(--members_count |
+ (MLX4_PROT_ETH << 30));
+
+ err = mlx4_WRITE_ENTRY(dev, entry->index, mailbox);
+ if (err)
+ goto out_mailbox;
+ }
+ }
}
out_mailbox:
@@ -661,26 +724,37 @@ static int find_entry(struct mlx4_dev *dev, u8 port,
return err;
}
+static const u8 __promisc_mode[] = {
+ [MLX4_FS_REGULAR] = 0x0,
+ [MLX4_FS_ALL_DEFAULT] = 0x1,
+ [MLX4_FS_MC_DEFAULT] = 0x3,
+ [MLX4_FS_UC_SNIFFER] = 0x4,
+ [MLX4_FS_MC_SNIFFER] = 0x5,
+};
+
+int map_sw_to_hw_steering_mode(struct mlx4_dev *dev,
+ enum mlx4_net_trans_promisc_mode flow_type)
+{
+ if (flow_type >= MLX4_FS_MODE_NUM || flow_type < 0) {
+ mlx4_err(dev, "Invalid flow type. type = %d\n", flow_type);
+ return -EINVAL;
+ }
+ return __promisc_mode[flow_type];
+}
+EXPORT_SYMBOL_GPL(map_sw_to_hw_steering_mode);
+
static void trans_rule_ctrl_to_hw(struct mlx4_net_trans_rule *ctrl,
struct mlx4_net_trans_rule_hw_ctrl *hw)
{
- static const u8 __promisc_mode[] = {
- [MLX4_FS_REGULAR] = 0x0,
- [MLX4_FS_ALL_DEFAULT] = 0x1,
- [MLX4_FS_MC_DEFAULT] = 0x3,
- [MLX4_FS_UC_SNIFFER] = 0x4,
- [MLX4_FS_MC_SNIFFER] = 0x5,
- };
-
- u32 dw = 0;
-
- dw = ctrl->queue_mode == MLX4_NET_TRANS_Q_LIFO ? 1 : 0;
- dw |= ctrl->exclusive ? (1 << 2) : 0;
- dw |= ctrl->allow_loopback ? (1 << 3) : 0;
- dw |= __promisc_mode[ctrl->promisc_mode] << 8;
- dw |= ctrl->priority << 16;
-
- hw->ctrl = cpu_to_be32(dw);
+ u8 flags = 0;
+
+ flags = ctrl->queue_mode == MLX4_NET_TRANS_Q_LIFO ? 1 : 0;
+ flags |= ctrl->exclusive ? (1 << 2) : 0;
+ flags |= ctrl->allow_loopback ? (1 << 3) : 0;
+
+ hw->flags = flags;
+ hw->type = __promisc_mode[ctrl->promisc_mode];
+ hw->prio = cpu_to_be16(ctrl->priority);
hw->port = ctrl->port;
hw->qpn = cpu_to_be32(ctrl->qpn);
}
@@ -694,29 +768,51 @@ const u16 __sw_id_hw[] = {
[MLX4_NET_TRANS_RULE_ID_UDP] = 0xE006
};
+int map_sw_to_hw_steering_id(struct mlx4_dev *dev,
+ enum mlx4_net_trans_rule_id id)
+{
+ if (id >= MLX4_NET_TRANS_RULE_NUM || id < 0) {
+ mlx4_err(dev, "Invalid network rule id. id = %d\n", id);
+ return -EINVAL;
+ }
+ return __sw_id_hw[id];
+}
+EXPORT_SYMBOL_GPL(map_sw_to_hw_steering_id);
+
+static const int __rule_hw_sz[] = {
+ [MLX4_NET_TRANS_RULE_ID_ETH] =
+ sizeof(struct mlx4_net_trans_rule_hw_eth),
+ [MLX4_NET_TRANS_RULE_ID_IB] =
+ sizeof(struct mlx4_net_trans_rule_hw_ib),
+ [MLX4_NET_TRANS_RULE_ID_IPV6] = 0,
+ [MLX4_NET_TRANS_RULE_ID_IPV4] =
+ sizeof(struct mlx4_net_trans_rule_hw_ipv4),
+ [MLX4_NET_TRANS_RULE_ID_TCP] =
+ sizeof(struct mlx4_net_trans_rule_hw_tcp_udp),
+ [MLX4_NET_TRANS_RULE_ID_UDP] =
+ sizeof(struct mlx4_net_trans_rule_hw_tcp_udp)
+};
+
+int hw_rule_sz(struct mlx4_dev *dev,
+ enum mlx4_net_trans_rule_id id)
+{
+ if (id >= MLX4_NET_TRANS_RULE_NUM || id < 0) {
+ mlx4_err(dev, "Invalid network rule id. id = %d\n", id);
+ return -EINVAL;
+ }
+
+ return __rule_hw_sz[id];
+}
+EXPORT_SYMBOL_GPL(hw_rule_sz);
+
static int parse_trans_rule(struct mlx4_dev *dev, struct mlx4_spec_list *spec,
struct _rule_hw *rule_hw)
{
- static const size_t __rule_hw_sz[] = {
- [MLX4_NET_TRANS_RULE_ID_ETH] =
- sizeof(struct mlx4_net_trans_rule_hw_eth),
- [MLX4_NET_TRANS_RULE_ID_IB] =
- sizeof(struct mlx4_net_trans_rule_hw_ib),
- [MLX4_NET_TRANS_RULE_ID_IPV6] = 0,
- [MLX4_NET_TRANS_RULE_ID_IPV4] =
- sizeof(struct mlx4_net_trans_rule_hw_ipv4),
- [MLX4_NET_TRANS_RULE_ID_TCP] =
- sizeof(struct mlx4_net_trans_rule_hw_tcp_udp),
- [MLX4_NET_TRANS_RULE_ID_UDP] =
- sizeof(struct mlx4_net_trans_rule_hw_tcp_udp)
- };
- if (spec->id >= MLX4_NET_TRANS_RULE_NUM) {
- mlx4_err(dev, "Invalid network rule id. id = %d\n", spec->id);
+ if (hw_rule_sz(dev, spec->id) < 0)
return -EINVAL;
- }
- memset(rule_hw, 0, __rule_hw_sz[spec->id]);
+ memset(rule_hw, 0, hw_rule_sz(dev, spec->id));
rule_hw->id = cpu_to_be16(__sw_id_hw[spec->id]);
- rule_hw->size = __rule_hw_sz[spec->id] >> 2;
+ rule_hw->size = hw_rule_sz(dev, spec->id) >> 2;
switch (spec->id) {
case MLX4_NET_TRANS_RULE_ID_ETH:
@@ -730,12 +826,12 @@ static int parse_trans_rule(struct mlx4_dev *dev, struct mlx4_spec_list *spec,
rule_hw->eth.ether_type_enable = 1;
rule_hw->eth.ether_type = spec->eth.ether_type;
}
- rule_hw->eth.vlan_id = spec->eth.vlan_id;
- rule_hw->eth.vlan_id_msk = spec->eth.vlan_id_msk;
+ rule_hw->eth.vlan_tag = spec->eth.vlan_id;
+ rule_hw->eth.vlan_tag_msk = spec->eth.vlan_id_msk;
break;
case MLX4_NET_TRANS_RULE_ID_IB:
- rule_hw->ib.r_u_qpn = spec->ib.r_u_qpn;
+ rule_hw->ib.l3_qpn = spec->ib.l3_qpn;
rule_hw->ib.qpn_mask = spec->ib.qpn_msk;
memcpy(&rule_hw->ib.dst_gid, &spec->ib.dst_gid, 16);
memcpy(&rule_hw->ib.dst_gid_msk, &spec->ib.dst_gid_msk, 16);
@@ -886,7 +982,7 @@ int mlx4_flow_detach(struct mlx4_dev *dev, u64 reg_id)
err = mlx4_QP_FLOW_STEERING_DETACH(dev, reg_id);
if (err)
mlx4_err(dev, "Fail to detach network rule. registration id = 0x%llx\n",
- (long long)reg_id);
+ (unsigned long long)reg_id);
return err;
}
EXPORT_SYMBOL_GPL(mlx4_flow_detach);
@@ -977,8 +1073,9 @@ int mlx4_qp_attach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
if (err)
goto out;
+ /* if !link, still add the new entry. */
if (!link)
- goto out;
+ goto skip_link;
err = mlx4_READ_ENTRY(dev, prev, mailbox);
if (err)
@@ -990,6 +1087,7 @@ int mlx4_qp_attach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
if (err)
goto out;
+skip_link:
if (prot == MLX4_PROT_ETH) {
/* manage the steering entry for promisc mode */
if (new_entry)
@@ -1006,7 +1104,7 @@ out:
index, dev->caps.num_mgms);
else
mlx4_bitmap_free(&priv->mcg_table.bitmap,
- index - dev->caps.num_mgms);
+ index - dev->caps.num_mgms, MLX4_USE_RR);
}
mutex_unlock(&priv->mcg_table.mutex);
@@ -1045,10 +1143,14 @@ int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
goto out;
}
- /* if this pq is also a promisc qp, it shouldn't be removed */
+ /*
+ if this QP is also a promisc QP, it shouldn't be removed only if
+ at least one none promisc QP is also attached to this MCG
+ */
if (prot == MLX4_PROT_ETH &&
- check_duplicate_entry(dev, port, steer, index, qp->qpn))
- goto out;
+ check_duplicate_entry(dev, port, steer, index, qp->qpn) &&
+ !promisc_steering_entry(dev, port, steer, index, qp->qpn, NULL))
+ goto out;
members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
for (i = 0; i < members_count; ++i)
@@ -1099,7 +1201,7 @@ int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
index, amgm_index, dev->caps.num_mgms);
else
mlx4_bitmap_free(&priv->mcg_table.bitmap,
- amgm_index - dev->caps.num_mgms);
+ amgm_index - dev->caps.num_mgms, MLX4_USE_RR);
}
} else {
/* Remove entry from AMGM */
@@ -1119,7 +1221,7 @@ int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
prev, index, dev->caps.num_mgms);
else
mlx4_bitmap_free(&priv->mcg_table.bitmap,
- index - dev->caps.num_mgms);
+ index - dev->caps.num_mgms, MLX4_USE_RR);
}
out:
@@ -1148,7 +1250,7 @@ static int mlx4_QP_ATTACH(struct mlx4_dev *dev, struct mlx4_qp *qp,
qpn = qp->qpn;
qpn |= (prot << 28);
if (attach && block_loopback)
- qpn |= (1U << 31);
+ qpn |= (1 << 31);
err = mlx4_cmd(dev, mailbox->dma, qpn, attach,
MLX4_CMD_QP_ATTACH, MLX4_CMD_TIME_CLASS_A,
@@ -1158,28 +1260,11 @@ static int mlx4_QP_ATTACH(struct mlx4_dev *dev, struct mlx4_qp *qp,
return err;
}
-int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
- u8 port, int block_mcast_loopback,
- enum mlx4_protocol prot, u64 *reg_id)
+int mlx4_trans_to_dmfs_attach(struct mlx4_dev *dev, struct mlx4_qp *qp,
+ u8 gid[16], u8 port,
+ int block_mcast_loopback,
+ enum mlx4_protocol prot, u64 *reg_id)
{
-
- switch (dev->caps.steering_mode) {
- case MLX4_STEERING_MODE_A0:
- if (prot == MLX4_PROT_ETH)
- return 0;
-
- case MLX4_STEERING_MODE_B0:
- if (prot == MLX4_PROT_ETH)
- gid[7] |= (MLX4_MC_STEER << 1);
-
- if (mlx4_is_mfunc(dev))
- return mlx4_QP_ATTACH(dev, qp, gid, 1,
- block_mcast_loopback, prot);
- return mlx4_qp_attach_common(dev, qp, gid,
- block_mcast_loopback, prot,
- MLX4_MC_STEER);
-
- case MLX4_STEERING_MODE_DEVICE_MANAGED: {
struct mlx4_spec_list spec = { {NULL} };
__be64 mac_mask = cpu_to_be64(MLX4_MAC_MASK << 16);
@@ -1213,8 +1298,35 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
list_add_tail(&spec.list, &rule.list);
return mlx4_flow_attach(dev, &rule, reg_id);
- }
+}
+int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
+ u8 port, int block_mcast_loopback,
+ enum mlx4_protocol prot, u64 *reg_id)
+{
+ enum mlx4_steer_type steer;
+ steer = (is_valid_ether_addr(&gid[10])) ? MLX4_UC_STEER : MLX4_MC_STEER;
+
+ switch (dev->caps.steering_mode) {
+ case MLX4_STEERING_MODE_A0:
+ if (prot == MLX4_PROT_ETH)
+ return 0;
+
+ case MLX4_STEERING_MODE_B0:
+ if (prot == MLX4_PROT_ETH)
+ gid[7] |= (steer << 1);
+
+ if (mlx4_is_mfunc(dev))
+ return mlx4_QP_ATTACH(dev, qp, gid, 1,
+ block_mcast_loopback, prot);
+ return mlx4_qp_attach_common(dev, qp, gid,
+ block_mcast_loopback, prot,
+ MLX4_MC_STEER);
+
+ case MLX4_STEERING_MODE_DEVICE_MANAGED:
+ return mlx4_trans_to_dmfs_attach(dev, qp, gid, port,
+ block_mcast_loopback,
+ prot, reg_id);
default:
return -EINVAL;
}
@@ -1224,6 +1336,9 @@ EXPORT_SYMBOL_GPL(mlx4_multicast_attach);
int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
enum mlx4_protocol prot, u64 reg_id)
{
+ enum mlx4_steer_type steer;
+ steer = (is_valid_ether_addr(&gid[10])) ? MLX4_UC_STEER : MLX4_MC_STEER;
+
switch (dev->caps.steering_mode) {
case MLX4_STEERING_MODE_A0:
if (prot == MLX4_PROT_ETH)
@@ -1231,7 +1346,7 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
case MLX4_STEERING_MODE_B0:
if (prot == MLX4_PROT_ETH)
- gid[7] |= (MLX4_MC_STEER << 1);
+ gid[7] |= (steer << 1);
if (mlx4_is_mfunc(dev))
return mlx4_QP_ATTACH(dev, qp, gid, 0, 0, prot);
@@ -1345,8 +1460,8 @@ int mlx4_PROMISC_wrapper(struct mlx4_dev *dev, int slave,
u8 port = vhcr->in_param >> 62;
enum mlx4_steer_type steer = vhcr->in_modifier;
- /* Promiscuous unicast is not allowed in mfunc */
- if (mlx4_is_mfunc(dev) && steer == MLX4_UC_STEER)
+ /* Promiscuous unicast is not allowed in mfunc for VFs */
+ if ((slave != dev->caps.function) && (steer == MLX4_UC_STEER))
return 0;
if (vhcr->op_modifier)
diff --git a/sys/ofed/drivers/net/mlx4/mlx4.h b/sys/ofed/drivers/net/mlx4/mlx4.h
index b342d9a..624a61c 100644
--- a/sys/ofed/drivers/net/mlx4/mlx4.h
+++ b/sys/ofed/drivers/net/mlx4/mlx4.h
@@ -2,7 +2,7 @@
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) 2005, 2006, 2007 Cisco Systems. All rights reserved.
- * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005, 2006, 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
* Copyright (c) 2004 Voltaire, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -43,7 +43,7 @@
#include <linux/timer.h>
#include <linux/semaphore.h>
#include <linux/workqueue.h>
-
+#include <linux/device.h>
#include <linux/mlx4/device.h>
#include <linux/mlx4/driver.h>
#include <linux/mlx4/doorbell.h>
@@ -51,8 +51,12 @@
#define DRV_NAME "mlx4_core"
#define PFX DRV_NAME ": "
-#define DRV_VERSION "1.1"
-#define DRV_RELDATE "Dec, 2011"
+#define DRV_VERSION "2.1"
+#define DRV_RELDATE __DATE__
+
+#define DRV_STACK_NAME "Linux-MLNX_OFED"
+#define DRV_STACK_VERSION "2.1"
+#define DRV_NAME_FOR_FW DRV_STACK_NAME","DRV_STACK_VERSION
#define MLX4_FS_UDP_UC_EN (1 << 1)
#define MLX4_FS_TCP_UC_EN (1 << 2)
@@ -108,10 +112,10 @@ enum {
MLX4_NUM_CMPTS = MLX4_CMPT_NUM_TYPE << MLX4_CMPT_SHIFT
};
-enum mlx4_mr_state {
- MLX4_MR_DISABLED = 0,
- MLX4_MR_EN_HW,
- MLX4_MR_EN_SW
+enum mlx4_mpt_state {
+ MLX4_MPT_DISABLED = 0,
+ MLX4_MPT_EN_HW,
+ MLX4_MPT_EN_SW
};
#define MLX4_COMM_TIME 10000
@@ -139,9 +143,10 @@ enum mlx4_resource {
RES_MTT,
RES_MAC,
RES_VLAN,
- RES_EQ,
+ RES_NPORT_ID,
RES_COUNTER,
RES_FS_RULE,
+ RES_EQ,
MLX4_NUM_OF_RESOURCE_TYPE
};
@@ -180,13 +185,14 @@ struct mlx4_vhcr {
struct mlx4_vhcr_cmd {
__be64 in_param;
__be32 in_modifier;
+ u32 reserved1;
__be64 out_param;
__be16 token;
u16 reserved;
u8 status;
u8 flags;
__be16 opcode;
-};
+} __packed;
struct mlx4_cmd_info {
u16 opcode;
@@ -194,6 +200,7 @@ struct mlx4_cmd_info {
bool has_outbox;
bool out_is_imm;
bool encode_slave_id;
+ bool skip_err_print;
int (*verify)(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
struct mlx4_cmd_mailbox *inbox);
int (*wrapper)(struct mlx4_dev *dev, int slave, struct mlx4_vhcr *vhcr,
@@ -202,6 +209,10 @@ struct mlx4_cmd_info {
struct mlx4_cmd_info *cmd);
};
+enum {
+ MLX4_DEBUG_MASK_CMD_TIME = 0x100,
+};
+
#ifdef CONFIG_MLX4_DEBUG
extern int mlx4_debug_level;
#else /* CONFIG_MLX4_DEBUG */
@@ -260,6 +271,22 @@ struct mlx4_icm_table {
struct mlx4_icm **icm;
};
+#define MLX4_MPT_FLAG_SW_OWNS (0xfUL << 28)
+#define MLX4_MPT_FLAG_FREE (0x3UL << 28)
+#define MLX4_MPT_FLAG_MIO (1 << 17)
+#define MLX4_MPT_FLAG_BIND_ENABLE (1 << 15)
+#define MLX4_MPT_FLAG_PHYSICAL (1 << 9)
+#define MLX4_MPT_FLAG_REGION (1 << 8)
+
+#define MLX4_MPT_PD_FLAG_FAST_REG (1 << 27)
+#define MLX4_MPT_PD_FLAG_RAE (1 << 28)
+#define MLX4_MPT_PD_FLAG_EN_INV (3 << 24)
+
+#define MLX4_MPT_QP_FLAG_BOUND_QP (1 << 7)
+
+#define MLX4_MPT_STATUS_SW 0xF0
+#define MLX4_MPT_STATUS_HW 0x00
+
/*
* Must be packed because mtt_seg is 64 bits but only aligned to 32 bits.
*/
@@ -353,7 +380,6 @@ struct mlx4_eq {
u16 irq;
u16 have_irq;
int nent;
- int load;
struct mlx4_buf_list *page_list;
struct mlx4_mtt mtt;
};
@@ -376,7 +402,7 @@ struct mlx4_profile {
int num_cq;
int num_mcg;
int num_mpt;
- unsigned num_mtt;
+ unsigned num_mtt_segs;
};
struct mlx4_fw {
@@ -434,6 +460,7 @@ struct mlx4_slave_state {
u8 last_cmd;
u8 init_port_mask;
bool active;
+ bool old_vlan_api;
u8 function;
dma_addr_t vhcr_dma;
u16 mtu[MLX4_MAX_PORTS + 1];
@@ -455,12 +482,14 @@ struct mlx4_slave_state {
#define MLX4_VGT 4095
#define NO_INDX (-1)
+
struct mlx4_vport_state {
u64 mac;
u16 default_vlan;
u8 default_qos;
u32 tx_rate;
bool spoofchk;
+ u32 link_state;
};
struct mlx4_vf_admin_state {
@@ -531,6 +560,7 @@ struct mlx4_mfunc_master_ctx {
struct mlx4_resource_tracker res_tracker;
struct workqueue_struct *comm_wq;
struct work_struct comm_work;
+ struct work_struct arm_comm_work;
struct work_struct slave_event_work;
struct work_struct slave_flr_event_work;
spinlock_t slave_state_lock;
@@ -576,6 +606,24 @@ struct mlx4_cmd {
u8 comm_toggle;
};
+enum {
+ MLX4_VF_IMMED_VLAN_FLAG_VLAN = 1 << 0,
+ MLX4_VF_IMMED_VLAN_FLAG_QOS = 1 << 1,
+};
+struct mlx4_vf_immed_vlan_work {
+ struct work_struct work;
+ struct mlx4_priv *priv;
+ int flags;
+ int slave;
+ int vlan_ix;
+ int orig_vlan_ix;
+ u8 port;
+ u8 qos;
+ u16 vlan_id;
+ u16 orig_vlan_id;
+};
+
+
struct mlx4_uar_table {
struct mlx4_bitmap bitmap;
};
@@ -592,6 +640,7 @@ struct mlx4_mr_table {
struct mlx4_cq_table {
struct mlx4_bitmap bitmap;
spinlock_t lock;
+ rwlock_t cq_table_lock;
struct radix_tree_root tree;
struct mlx4_icm_table table;
struct mlx4_icm_table cmpt_table;
@@ -724,8 +773,6 @@ struct mlx4_sense {
u8 do_sense_port[MLX4_MAX_PORTS + 1];
u8 sense_allowed[MLX4_MAX_PORTS + 1];
struct delayed_work sense_poll;
- struct workqueue_struct *sense_wq;
- u32 resched;
};
struct mlx4_msix_ctl {
@@ -738,85 +785,6 @@ struct mlx4_steer {
struct list_head steer_entries[MLX4_NUM_STEERS];
};
-struct mlx4_net_trans_rule_hw_ctrl {
- __be32 ctrl;
- u8 rsvd1;
- u8 funcid;
- u8 vep;
- u8 port;
- __be32 qpn;
- __be32 rsvd2;
-};
-
-struct mlx4_net_trans_rule_hw_ib {
- u8 size;
- u8 rsvd1;
- __be16 id;
- u32 rsvd2;
- __be32 r_u_qpn;
- __be32 qpn_mask;
- u8 dst_gid[16];
- u8 dst_gid_msk[16];
-} __packed;
-
-struct mlx4_net_trans_rule_hw_eth {
- u8 size;
- u8 rsvd;
- __be16 id;
- u8 rsvd1[6];
- u8 dst_mac[6];
- u16 rsvd2;
- u8 dst_mac_msk[6];
- u16 rsvd3;
- u8 src_mac[6];
- u16 rsvd4;
- u8 src_mac_msk[6];
- u8 rsvd5;
- u8 ether_type_enable;
- __be16 ether_type;
- __be16 vlan_id_msk;
- __be16 vlan_id;
-} __packed;
-
-struct mlx4_net_trans_rule_hw_tcp_udp {
- u8 size;
- u8 rsvd;
- __be16 id;
- __be16 rsvd1[3];
- __be16 dst_port;
- __be16 rsvd2;
- __be16 dst_port_msk;
- __be16 rsvd3;
- __be16 src_port;
- __be16 rsvd4;
- __be16 src_port_msk;
-} __packed;
-
-struct mlx4_net_trans_rule_hw_ipv4 {
- u8 size;
- u8 rsvd;
- __be16 id;
- __be32 rsvd1;
- __be32 dst_ip;
- __be32 dst_ip_msk;
- __be32 src_ip;
- __be32 src_ip_msk;
-} __packed;
-
-struct _rule_hw {
- union {
- struct {
- u8 size;
- u8 rsvd;
- __be16 id;
- };
- struct mlx4_net_trans_rule_hw_eth eth;
- struct mlx4_net_trans_rule_hw_ib ib;
- struct mlx4_net_trans_rule_hw_ipv4 ipv4;
- struct mlx4_net_trans_rule_hw_tcp_udp tcp_udp;
- };
-};
-
enum {
MLX4_PCI_DEV_IS_VF = 1 << 0,
MLX4_PCI_DEV_FORCE_SENSE_PORT = 1 << 1,
@@ -826,6 +794,23 @@ struct mlx4_roce_gid_entry {
u8 raw[16];
};
+struct counter_index {
+ struct list_head list;
+ u32 index;
+};
+
+struct mlx4_counters {
+ struct mlx4_bitmap bitmap;
+ struct list_head global_port_list[MLX4_MAX_PORTS];
+ struct list_head vf_list[MLX4_MAX_NUM_VF][MLX4_MAX_PORTS];
+ struct mutex mutex;
+};
+
+enum {
+ MLX4_NO_RR = 0,
+ MLX4_USE_RR = 1,
+};
+
struct mlx4_priv {
struct mlx4_dev dev;
@@ -851,7 +836,7 @@ struct mlx4_priv {
struct mlx4_srq_table srq_table;
struct mlx4_qp_table qp_table;
struct mlx4_mcg_table mcg_table;
- struct mlx4_bitmap counters_bitmap;
+ struct mlx4_counters counters_table;
struct mlx4_catas_err catas_err;
@@ -887,10 +872,11 @@ static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev)
extern struct workqueue_struct *mlx4_wq;
u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap);
-void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj);
+void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj, int use_rr);
u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt,
int align, u32 skip_mask);
-void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt);
+void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt,
+ int use_rr);
u32 mlx4_bitmap_avail(struct mlx4_bitmap *bitmap);
int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask,
u32 reserved_bot, u32 resetrved_top);
@@ -926,10 +912,10 @@ int __mlx4_cq_alloc_icm(struct mlx4_dev *dev, int *cqn);
void __mlx4_cq_free_icm(struct mlx4_dev *dev, int cqn);
int __mlx4_srq_alloc_icm(struct mlx4_dev *dev, int *srqn);
void __mlx4_srq_free_icm(struct mlx4_dev *dev, int srqn);
-int __mlx4_mr_reserve(struct mlx4_dev *dev);
-void __mlx4_mr_release(struct mlx4_dev *dev, u32 index);
-int __mlx4_mr_alloc_icm(struct mlx4_dev *dev, u32 index);
-void __mlx4_mr_free_icm(struct mlx4_dev *dev, u32 index);
+int __mlx4_mpt_reserve(struct mlx4_dev *dev);
+void __mlx4_mpt_release(struct mlx4_dev *dev, u32 index);
+int __mlx4_mpt_alloc_icm(struct mlx4_dev *dev, u32 index);
+void __mlx4_mpt_free_icm(struct mlx4_dev *dev, u32 index);
u32 __mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order);
void __mlx4_free_mtt_range(struct mlx4_dev *dev, u32 first_seg, int order);
@@ -969,14 +955,20 @@ int mlx4_DMA_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_cmd_mailbox *outbox,
struct mlx4_cmd_info *cmd);
int __mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align,
- int *base, u8 bf_qp);
+ int *base, u8 flags);
void __mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt);
int __mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac);
void __mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac);
int __mlx4_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
int start_index, int npages, u64 *page_list);
-int __mlx4_counter_alloc(struct mlx4_dev *dev, u32 *idx);
-void __mlx4_counter_free(struct mlx4_dev *dev, u32 idx);
+int __mlx4_counter_alloc(struct mlx4_dev *dev, int slave, int port, u32 *idx);
+void __mlx4_counter_free(struct mlx4_dev *dev, int slave, int port, u32 idx);
+
+int __mlx4_slave_counters_free(struct mlx4_dev *dev, int slave);
+int __mlx4_clear_if_stat(struct mlx4_dev *dev,
+ u8 counter_index);
+u8 mlx4_get_default_counter_index(struct mlx4_dev *dev, int slave, int port);
+
int __mlx4_xrcd_alloc(struct mlx4_dev *dev, u32 *xrcdn);
void __mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn);
@@ -997,6 +989,7 @@ u64 mlx4_make_profile(struct mlx4_dev *dev,
struct mlx4_dev_cap *dev_cap,
struct mlx4_init_hca_param *init_hca);
void mlx4_master_comm_channel(struct work_struct *work);
+void mlx4_master_arm_comm_channel(struct work_struct *work);
void mlx4_gen_slave_eqe(struct work_struct *work);
void mlx4_master_handle_slave_flr(struct work_struct *work);
@@ -1164,8 +1157,7 @@ void mlx4_do_sense_ports(struct mlx4_dev *dev,
enum mlx4_port_type *defaults);
void mlx4_start_sense(struct mlx4_dev *dev);
void mlx4_stop_sense(struct mlx4_dev *dev);
-void mlx4_sense_cleanup(struct mlx4_dev *dev);
-int mlx4_sense_init(struct mlx4_dev *dev);
+void mlx4_sense_init(struct mlx4_dev *dev);
int mlx4_check_port_params(struct mlx4_dev *dev,
enum mlx4_port_type *port_type);
int mlx4_change_port_types(struct mlx4_dev *dev,
@@ -1238,6 +1230,10 @@ int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
int mlx4_qp_attach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
int block_mcast_loopback, enum mlx4_protocol prot,
enum mlx4_steer_type steer);
+int mlx4_trans_to_dmfs_attach(struct mlx4_dev *dev, struct mlx4_qp *qp,
+ u8 gid[16], u8 port,
+ int block_mcast_loopback,
+ enum mlx4_protocol prot, u64 *reg_id);
int mlx4_SET_MCAST_FLTR_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_vhcr *vhcr,
struct mlx4_cmd_mailbox *inbox,
@@ -1250,8 +1246,6 @@ int mlx4_SET_VLAN_FLTR_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_cmd_info *cmd);
int mlx4_common_set_vlan_fltr(struct mlx4_dev *dev, int function,
int port, void *buf);
-int mlx4_common_dump_eth_stats(struct mlx4_dev *dev, int slave, u32 in_mod,
- struct mlx4_cmd_mailbox *outbox);
int mlx4_DUMP_ETH_STATS_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_vhcr *vhcr,
struct mlx4_cmd_mailbox *inbox,
@@ -1277,6 +1271,11 @@ int mlx4_QP_FLOW_STEERING_DETACH_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_cmd_mailbox *inbox,
struct mlx4_cmd_mailbox *outbox,
struct mlx4_cmd_info *cmd);
+int mlx4_MOD_STAT_CFG_wrapper(struct mlx4_dev *dev, int slave,
+ struct mlx4_vhcr *vhcr,
+ struct mlx4_cmd_mailbox *inbox,
+ struct mlx4_cmd_mailbox *outbox,
+ struct mlx4_cmd_info *cmd);
int mlx4_get_mgm_entry_size(struct mlx4_dev *dev);
int mlx4_get_qp_per_mgm(struct mlx4_dev *dev);
@@ -1315,5 +1314,6 @@ void mlx4_init_quotas(struct mlx4_dev *dev);
int mlx4_get_slave_num_gids(struct mlx4_dev *dev, int slave);
int mlx4_get_base_gid_ix(struct mlx4_dev *dev, int slave);
+void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work);
#endif /* MLX4_H */
diff --git a/sys/ofed/drivers/net/mlx4/mlx4_en.h b/sys/ofed/drivers/net/mlx4/mlx4_en.h
index 0dc5fe6..1cb19e3 100644
--- a/sys/ofed/drivers/net/mlx4/mlx4_en.h
+++ b/sys/ofed/drivers/net/mlx4/mlx4_en.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2007, 2014 Mellanox Technologies. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -34,13 +34,17 @@
#ifndef _MLX4_EN_H_
#define _MLX4_EN_H_
-#include <sys/cdefs.h>
-
-#include <linux/types.h>
+#include <linux/bitops.h>
#include <linux/compiler.h>
#include <linux/list.h>
#include <linux/mutex.h>
+#include <linux/kobject.h>
#include <linux/netdevice.h>
+#include <linux/if_vlan.h>
+#include <linux/if_ether.h>
+#ifdef CONFIG_MLX4_EN_DCB
+#include <linux/dcbnl.h>
+#endif
#include <linux/mlx4/device.h>
#include <linux/mlx4/qp.h>
@@ -49,56 +53,17 @@
#include <linux/mlx4/doorbell.h>
#include <linux/mlx4/cmd.h>
-#include <net/if_media.h>
#include <netinet/tcp_lro.h>
#include "en_port.h"
+#include "mlx4_stats.h"
#define DRV_NAME "mlx4_en"
-#define DRV_VERSION "1.5.2"
-#define DRV_RELDATE "July 2010"
-
-/* XXX */
-#define NETIF_MSG_LINK 0x1
-#define NETIF_MSG_IFDOWN 0x2
-#define NETIF_MSG_HW 0x4
-#define NETIF_MSG_DRV 0x8
-#define NETIF_MSG_INTR 0x10
-#define NETIF_MSG_RX_ERR 0x20
+#define DRV_VERSION "2.1"
+#define DRV_RELDATE __DATE__
#define MLX4_EN_MSG_LEVEL (NETIF_MSG_LINK | NETIF_MSG_IFDOWN)
-#define en_print(level, priv, format, arg...) \
- { \
- if ((priv)->registered) \
- printk(level "%s: %s: " format, DRV_NAME, \
- (priv->dev)->if_xname, ## arg); \
- else \
- printk(level "%s: %s: Port %d: " format, \
- DRV_NAME, dev_name(&priv->mdev->pdev->dev), \
- (priv)->port, ## arg); \
- }
-
-#define en_dbg(mlevel, priv, format, arg...) \
- if (NETIF_MSG_##mlevel & priv->msg_enable) \
- en_print(KERN_DEBUG, priv, format, ## arg)
-#define en_warn(priv, format, arg...) \
- en_print(KERN_WARNING, priv, format, ## arg)
-#define en_err(priv, format, arg...) \
- en_print(KERN_ERR, priv, format, ## arg)
-#define en_info(priv, format, arg...) \
- en_print(KERN_INFO, priv, format, ## arg)
-
-#define mlx4_err(mdev, format, arg...) \
- printk(KERN_ERR "%s %s: " format , DRV_NAME ,\
- dev_name(&mdev->pdev->dev) , ## arg)
-#define mlx4_info(mdev, format, arg...) \
- printk(KERN_INFO "%s %s: " format , DRV_NAME ,\
- dev_name(&mdev->pdev->dev) , ## arg)
-#define mlx4_warn(mdev, format, arg...) \
- printk(KERN_WARNING "%s %s: " format , DRV_NAME ,\
- dev_name(&mdev->pdev->dev) , ## arg)
-
/*
* Device constants
*/
@@ -106,8 +71,9 @@
#define MLX4_EN_PAGE_SHIFT 12
#define MLX4_EN_PAGE_SIZE (1 << MLX4_EN_PAGE_SHIFT)
-#define MAX_TX_RINGS (MLX4_EN_NUM_HASH_RINGS + 1 + MLX4_EN_NUM_PPP_RINGS)
-#define MAX_RX_RINGS 16
+#define DEF_RX_RINGS 16
+#define MAX_RX_RINGS 128
+#define MIN_RX_RINGS 4
#define TXBB_SIZE 64
#define HEADROOM (2048 / TXBB_SIZE + 1)
#define STAMP_STRIDE 64
@@ -115,6 +81,19 @@
#define STAMP_SHIFT 31
#define STAMP_VAL 0x7fffffff
#define STATS_DELAY (HZ / 4)
+#define SERVICE_TASK_DELAY (HZ / 4)
+#define MAX_NUM_OF_FS_RULES 256
+
+#define MLX4_EN_FILTER_HASH_SHIFT 4
+#define MLX4_EN_FILTER_EXPIRY_QUOTA 60
+
+#ifdef CONFIG_NET_RX_BUSY_POLL
+#define LL_EXTENDED_STATS
+#endif
+
+/* vlan valid range */
+#define VLAN_MIN_VALUE 1
+#define VLAN_MAX_VALUE 4094
/* Typical TSO descriptor with 16 gather entries is 352 bytes... */
#define MAX_DESC_SIZE 512
@@ -126,8 +105,13 @@
#define MLX4_EN_WATCHDOG_TIMEOUT (15 * HZ)
-#define MLX4_EN_MAX_LRO_DESCRIPTORS 32
-#define MLX4_EN_NUM_IPFRAG_SESSIONS 16
+#define MLX4_EN_ALLOC_SIZE PAGE_ALIGN(PAGE_SIZE)
+#define MLX4_EN_ALLOC_ORDER get_order(MLX4_EN_ALLOC_SIZE)
+
+enum mlx4_en_alloc_type {
+ MLX4_EN_ALLOC_NEW = 0,
+ MLX4_EN_ALLOC_REPLACEMENT = 1,
+};
/* Receive fragment sizes; we use at most 3 fragments (for 9600 byte MTU
* and 4K allocations) */
@@ -150,28 +134,37 @@ enum {
#endif
/* Maximum ring sizes */
+#define MLX4_EN_DEF_TX_QUEUE_SIZE 4096
+
+/* Minimum packet number till arming the CQ */
+#define MLX4_EN_MIN_RX_ARM 2048
+#define MLX4_EN_MIN_TX_ARM 2048
+
+/* Maximum ring sizes */
#define MLX4_EN_MAX_TX_SIZE 8192
#define MLX4_EN_MAX_RX_SIZE 8192
-#define MLX4_EN_MIN_RX_SIZE (128)
+/* Minimum ring sizes */
+#define MLX4_EN_MIN_RX_SIZE (4096 / TXBB_SIZE)
#define MLX4_EN_MIN_TX_SIZE (4096 / TXBB_SIZE)
#define MLX4_EN_SMALL_PKT_SIZE 64
-#define MLX4_EN_TX_HASH_SIZE 256
-#define MLX4_EN_TX_HASH_MASK (MLX4_EN_TX_HASH_SIZE - 1)
-#define MLX4_EN_NUM_HASH_RINGS 4
-#define MLX4_EN_NUM_PPP_RINGS 8
-#define MLX4_EN_DEF_TX_RING_SIZE 512
-#define MLX4_EN_DEF_TX_QUEUE_SIZE 4096
+
+#define MLX4_EN_MAX_TX_RING_P_UP 32
+#define MLX4_EN_NUM_UP 1
+
+#define MAX_TX_RINGS (MLX4_EN_MAX_TX_RING_P_UP * \
+ (MLX4_EN_NUM_UP + 1))
+
+#define MLX4_EN_DEF_TX_RING_SIZE 1024
#define MLX4_EN_DEF_RX_RING_SIZE 1024
-#define MLX4_EN_MAX_RX_POLL 1024
/* Target number of bytes to coalesce with interrupt moderation */
#define MLX4_EN_RX_COAL_TARGET 0x20000
#define MLX4_EN_RX_COAL_TIME 0x10
-#define MLX4_EN_TX_COAL_PKTS 5
-#define MLX4_EN_TX_COAL_TIME 0x80
+#define MLX4_EN_TX_COAL_PKTS 64
+#define MLX4_EN_TX_COAL_TIME 64
#define MLX4_EN_RX_RATE_LOW 400000
#define MLX4_EN_RX_COAL_TIME_LOW 0
@@ -187,14 +180,13 @@ enum {
#define MLX4_EN_DEF_RX_PAUSE 1
#define MLX4_EN_DEF_TX_PAUSE 1
-/* Interval between sucessive polls in the Tx routine when polling is used
+/* Interval between successive polls in the Tx routine when polling is used
instead of interrupts (in per-core Tx rings) - should be power of 2 */
#define MLX4_EN_TX_POLL_MODER 16
#define MLX4_EN_TX_POLL_TIMEOUT (HZ / 4)
-#define ETH_LLC_SNAP_SIZE 8
-
-#define SMALL_PACKET_SIZE (MHLEN)
+#define MLX4_EN_64_ALIGN (64 - NET_SKB_PAD)
+#define SMALL_PACKET_SIZE (256 - NET_IP_ALIGN)
#define HEADER_COPY_SIZE (128)
#define MLX4_LOOPBACK_TEST_PAYLOAD (HEADER_COPY_SIZE - ETHER_HDR_LEN)
@@ -208,7 +200,6 @@ enum {
/* Number of samples to 'average' */
#define AVG_SIZE 128
#define AVG_FACTOR 1024
-#define NUM_PERF_STATS NUM_PERF_COUNTERS
#define INC_PERF_COUNTER(cnt) (++(cnt))
#define ADD_PERF_COUNTER(cnt, add) ((cnt) += (add))
@@ -219,7 +210,6 @@ enum {
#else
-#define NUM_PERF_STATS 0
#define INC_PERF_COUNTER(cnt) do {} while (0)
#define ADD_PERF_COUNTER(cnt, add) do {} while (0)
#define AVG_PERF_COUNTER(cnt, sample) do {} while (0)
@@ -244,13 +234,17 @@ enum cq_type {
#define XNOR(x, y) (!(x) == !(y))
#define ILLEGAL_MAC(addr) (addr == 0xffffffffffffULL || addr == 0x0)
-
struct mlx4_en_tx_info {
- struct mbuf *mb;
- u32 nr_txbb;
- u8 nr_segs;
- u8 data_offset;
- u8 inl;
+ struct mbuf *mb;
+ u32 nr_txbb;
+ u32 nr_bytes;
+ u8 linear;
+ u8 nr_segs;
+ u8 data_offset;
+ u8 inl;
+#if 0
+ u8 ts_requested;
+#endif
};
@@ -271,8 +265,14 @@ struct mlx4_en_tx_desc {
#define MLX4_EN_USE_SRQ 0x01000000
+#define MLX4_EN_TX_BUDGET 64*4 //Compensate for no NAPI in freeBSD - might need some fine tunning in the future.
+#define MLX4_EN_RX_BUDGET 64
+
+#define MLX4_EN_CX3_LOW_ID 0x1000
+#define MLX4_EN_CX3_HIGH_ID 0x1005
+
struct mlx4_en_tx_ring {
- spinlock_t tx_lock;
+ spinlock_t tx_lock;
struct mlx4_hwq_resources wqres;
u32 size ; /* number of TXBBs */
u32 size_mask;
@@ -285,9 +285,11 @@ struct mlx4_en_tx_ring {
void *buf;
u16 poll_cnt;
int blocked;
- struct buf_ring *br;
struct mlx4_en_tx_info *tx_info;
u8 *bounce_buf;
+ u8 queue_index;
+ cpuset_t affinity_mask;
+ struct buf_ring *br;
u32 last_nr_txbb;
struct mlx4_qp qp;
struct mlx4_qp_context context;
@@ -296,29 +298,30 @@ struct mlx4_en_tx_ring {
struct mlx4_srq dummy;
unsigned long bytes;
unsigned long packets;
- unsigned long errors;
- spinlock_t comp_lock;
+ unsigned long tx_csum;
+ unsigned long queue_stopped;
+ unsigned long wake_queue;
struct mlx4_bf bf;
bool bf_enabled;
+ struct netdev_queue *tx_queue;
+ int hwtstamp_tx_type;
+ spinlock_t comp_lock;
+ int full_size;
+ int inline_thold;
u64 watchdog_time;
};
-struct mlx4_en_ipfrag {
- struct mbuf *fragments;
- struct mbuf *last;
- __be32 saddr;
- __be32 daddr;
- __be16 id;
- u8 protocol;
- int total_len;
- u16 offset;
-};
-
struct mlx4_en_rx_desc {
/* actual number of entries depends on rx ring stride */
struct mlx4_wqe_data_seg data[0];
};
+struct mlx4_en_rx_buf {
+ dma_addr_t dma;
+ struct page *page;
+ unsigned int page_offset;
+};
+
struct mlx4_en_rx_ring {
struct mlx4_hwq_resources wqres;
u32 size ; /* number of Rx descs*/
@@ -330,38 +333,66 @@ struct mlx4_en_rx_ring {
u32 prod;
u32 cons;
u32 buf_size;
+ u8 fcs_del;
+ u16 rx_alloc_order;
+ u32 rx_alloc_size;
+ u32 rx_buf_size;
+ u32 rx_mb_size;
+ int qpn;
void *buf;
void *rx_info;
+ unsigned long errors;
unsigned long bytes;
unsigned long packets;
- unsigned long errors;
+#ifdef LL_EXTENDED_STATS
+ unsigned long yields;
+ unsigned long misses;
+ unsigned long cleaned;
+#endif
+ unsigned long csum_ok;
+ unsigned long csum_none;
+ int hwtstamp_rx_filter;
+ int numa_node;
struct lro_ctrl lro;
- struct mlx4_en_ipfrag ipfrag[MLX4_EN_NUM_IPFRAG_SESSIONS];
};
-
static inline int mlx4_en_can_lro(__be16 status)
{
- return (status & cpu_to_be16(MLX4_CQE_STATUS_IPV4 |
- MLX4_CQE_STATUS_IPV4F |
- MLX4_CQE_STATUS_IPV6 |
- MLX4_CQE_STATUS_IPV4OPT |
- MLX4_CQE_STATUS_TCP |
- MLX4_CQE_STATUS_UDP |
- MLX4_CQE_STATUS_IPOK)) ==
- cpu_to_be16(MLX4_CQE_STATUS_IPV4 |
- MLX4_CQE_STATUS_IPOK |
- MLX4_CQE_STATUS_TCP);
+ static __be16 status_all;
+ static __be16 status_ipv4_ipok_tcp;
+ static __be16 status_ipv6_ipok_tcp;
+
+ status_all = cpu_to_be16(
+ MLX4_CQE_STATUS_IPV4 |
+ MLX4_CQE_STATUS_IPV4F |
+ MLX4_CQE_STATUS_IPV6 |
+ MLX4_CQE_STATUS_IPV4OPT |
+ MLX4_CQE_STATUS_TCP |
+ MLX4_CQE_STATUS_UDP |
+ MLX4_CQE_STATUS_IPOK);
+ status_ipv4_ipok_tcp = cpu_to_be16(
+ MLX4_CQE_STATUS_IPV4 |
+ MLX4_CQE_STATUS_IPOK |
+ MLX4_CQE_STATUS_TCP);
+ status_ipv6_ipok_tcp = cpu_to_be16(
+ MLX4_CQE_STATUS_IPV6 |
+ MLX4_CQE_STATUS_IPOK |
+ MLX4_CQE_STATUS_TCP);
+
+ status &= status_all;
+ return (status == status_ipv4_ipok_tcp ||
+ status == status_ipv6_ipok_tcp);
}
+
struct mlx4_en_cq {
struct mlx4_cq mcq;
struct mlx4_hwq_resources wqres;
int ring;
spinlock_t lock;
struct net_device *dev;
- /* Per-core Tx cq processing support */
- struct timer_list timer;
+ /* Per-core Tx cq processing support */
+ struct timer_list timer;
int size;
int buf_size;
unsigned vector;
@@ -373,6 +404,20 @@ struct mlx4_en_cq {
struct taskqueue *tq;
#define MLX4_EN_OPCODE_ERROR 0x1e
u32 tot_rx;
+ u32 tot_tx;
+
+#ifdef CONFIG_NET_RX_BUSY_POLL
+ unsigned int state;
+#define MLX4_EN_CQ_STATEIDLE 0
+#define MLX4_EN_CQ_STATENAPI 1 /* NAPI owns this CQ */
+#define MLX4_EN_CQ_STATEPOLL 2 /* poll owns this CQ */
+#define MLX4_CQ_LOCKED (MLX4_EN_CQ_STATENAPI | MLX4_EN_CQ_STATEPOLL)
+#define MLX4_EN_CQ_STATENAPI_YIELD 4 /* NAPI yielded this CQ */
+#define MLX4_EN_CQ_STATEPOLL_YIELD 8 /* poll yielded this CQ */
+#define CQ_YIELD (MLX4_EN_CQ_STATENAPI_YIELD | MLX4_EN_CQ_STATEPOLL_YIELD)
+#define CQ_USER_PEND (MLX4_EN_CQ_STATEPOLL | MLX4_EN_CQ_STATEPOLL_YIELD)
+ spinlock_t poll_lock; /* protects from LLS/napi conflicts */
+#endif /* CONFIG_NET_RX_BUSY_POLL */
};
struct mlx4_en_port_profile {
@@ -382,41 +427,42 @@ struct mlx4_en_port_profile {
u32 tx_ring_size;
u32 rx_ring_size;
u8 rx_pause;
+ u8 rx_ppp;
u8 tx_pause;
- u32 rx_ppp;
- u32 tx_ppp;
+ u8 tx_ppp;
+ int rss_rings;
};
struct mlx4_en_profile {
int rss_xor;
- int num_lro;
- int ip_reasm;
- int tcp_rss;
int udp_rss;
u8 rss_mask;
u32 active_ports;
u32 small_pkt_int;
u8 no_reset;
+ u8 num_tx_rings_p_up;
struct mlx4_en_port_profile prof[MLX4_MAX_PORTS + 1];
};
struct mlx4_en_dev {
- struct mlx4_dev *dev;
+ struct mlx4_dev *dev;
struct pci_dev *pdev;
struct mutex state_lock;
- struct net_device *pndev[MLX4_MAX_PORTS + 1];
- u32 port_cnt;
+ struct net_device *pndev[MLX4_MAX_PORTS + 1];
+ u32 port_cnt;
bool device_up;
- struct mlx4_en_profile profile;
+ struct mlx4_en_profile profile;
u32 LSO_support;
struct workqueue_struct *workqueue;
- struct device *dma_device;
- void __iomem *uar_map;
- struct mlx4_uar priv_uar;
+ struct device *dma_device;
+ void __iomem *uar_map;
+ struct mlx4_uar priv_uar;
struct mlx4_mr mr;
- u32 priv_pdn;
- spinlock_t uar_lock;
+ u32 priv_pdn;
+ spinlock_t uar_lock;
u8 mac_removed[MLX4_MAX_PORTS + 1];
+ unsigned long last_overflow_check;
+ unsigned long overflow_period;
};
@@ -428,71 +474,76 @@ struct mlx4_en_rss_map {
enum mlx4_qp_state indir_state;
};
-struct mlx4_en_rss_context {
- __be32 base_qpn;
- __be32 default_qpn;
- u16 reserved;
- u8 hash_fn;
- u8 flags;
- __be32 rss_key[10];
- __be32 base_qpn_udp;
-};
-
struct mlx4_en_port_state {
int link_state;
int link_speed;
int transciver;
+ int autoneg;
};
-struct mlx4_en_pkt_stats {
- unsigned long broadcast;
- unsigned long rx_prio[8];
- unsigned long tx_prio[8];
-#define NUM_PKT_STATS 17
+enum mlx4_en_mclist_act {
+ MCLIST_NONE,
+ MCLIST_REM,
+ MCLIST_ADD,
};
-struct mlx4_en_port_stats {
- unsigned long tso_packets;
- unsigned long queue_stopped;
- unsigned long wake_queue;
- unsigned long tx_timeout;
- unsigned long rx_alloc_failed;
- unsigned long rx_chksum_good;
- unsigned long rx_chksum_none;
- unsigned long tx_chksum_offload;
+struct mlx4_en_mc_list {
+ struct list_head list;
+ enum mlx4_en_mclist_act action;
+ u8 addr[ETH_ALEN];
+ u64 reg_id;
};
-struct mlx4_en_perf_stats {
- u32 tx_poll;
- u64 tx_pktsz_avg;
- u32 inflight_avg;
- u32 tx_coal_avg;
- u32 rx_coal_avg;
+#ifdef CONFIG_MLX4_EN_DCB
+/* Minimal TC BW - setting to 0 will block traffic */
+#define MLX4_EN_BW_MIN 1
+#define MLX4_EN_BW_MAX 100 /* Utilize 100% of the line */
+
+#define MLX4_EN_TC_ETS 7
+
+#endif
+
+
+enum {
+ MLX4_EN_FLAG_PROMISC = (1 << 0),
+ MLX4_EN_FLAG_MC_PROMISC = (1 << 1),
+ /* whether we need to enable hardware loopback by putting dmac
+ * in Tx WQE
+ */
+ MLX4_EN_FLAG_ENABLE_HW_LOOPBACK = (1 << 2),
+ /* whether we need to drop packets that hardware loopback-ed */
+ MLX4_EN_FLAG_RX_FILTER_NEEDED = (1 << 3),
+ MLX4_EN_FLAG_FORCE_PROMISC = (1 << 4),
+#ifdef CONFIG_MLX4_EN_DCB
+ MLX4_EN_FLAG_DCB_ENABLED = (1 << 5)
+#endif
};
-struct mlx4_en_frag_info {
- u16 frag_size;
- u16 frag_prefix_size;
+#define MLX4_EN_MAC_HASH_SIZE (1 << BITS_PER_BYTE)
+#define MLX4_EN_MAC_HASH_IDX 5
+
+struct en_port {
+ struct kobject kobj;
+ struct mlx4_dev *dev;
+ u8 port_num;
+ u8 vport_num;
};
-struct mlx4_en_tx_hash_entry {
- u8 cnt;
- unsigned int small_pkts;
- unsigned int big_pkts;
- unsigned int ring;
+struct mlx4_en_frag_info {
+ u16 frag_size;
+ u16 frag_prefix_size;
};
+
struct mlx4_en_priv {
struct mlx4_en_dev *mdev;
struct mlx4_en_port_profile *prof;
struct net_device *dev;
- bool vlgrp_modified;
- u32 vlan_register[VLAN_FLTR_SIZE];
- u32 vlan_unregister[VLAN_FLTR_SIZE];
- u32 vlans[VLAN_FLTR_SIZE];
- spinlock_t vlan_lock;
+ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
struct mlx4_en_port_state port_state;
spinlock_t stats_lock;
+ /* To allow rules removal while port is going down */
+ struct list_head ethtool_list;
unsigned long last_moder_packets[MAX_RX_RINGS];
unsigned long last_moder_tx_packets;
@@ -520,139 +571,381 @@ struct mlx4_en_priv {
int port;
int registered;
int allocated;
- int rx_csum;
- u64 mac;
+ int stride;
+ unsigned char current_mac[ETH_ALEN + 2];
+ u64 mac;
int mac_index;
unsigned max_mtu;
int base_qpn;
+ int cqe_factor;
struct mlx4_en_rss_map rss_map;
- u16 tx_prio_map[8];
+ __be32 ctrl_flags;
u32 flags;
-#define MLX4_EN_FLAG_PROMISC 0x1
+ u8 num_tx_rings_p_up;
u32 tx_ring_num;
u32 rx_ring_num;
u32 rx_mb_size;
- struct mlx4_en_frag_info frag_info[MLX4_EN_MAX_RX_FRAGS];
- u16 num_frags;
+ struct mlx4_en_frag_info frag_info[MLX4_EN_MAX_RX_FRAGS];
+ u16 rx_alloc_order;
+ u32 rx_alloc_size;
+ u32 rx_buf_size;
+ u16 num_frags;
u16 log_rx_info;
- int ip_reasm;
- bool wol;
- struct mlx4_en_tx_ring tx_ring[MAX_TX_RINGS];
- struct mlx4_en_rx_ring rx_ring[MAX_RX_RINGS];
- struct mlx4_en_cq tx_cq[MAX_TX_RINGS];
- struct mlx4_en_cq rx_cq[MAX_RX_RINGS];
- struct mlx4_en_tx_hash_entry tx_hash[MLX4_EN_TX_HASH_SIZE];
- struct work_struct mcast_task;
- struct work_struct start_port_task;
- struct work_struct stop_port_task;
+ struct mlx4_en_tx_ring **tx_ring;
+ struct mlx4_en_rx_ring *rx_ring[MAX_RX_RINGS];
+ struct mlx4_en_cq **tx_cq;
+ struct mlx4_en_cq *rx_cq[MAX_RX_RINGS];
+ struct mlx4_qp drop_qp;
+ struct work_struct rx_mode_task;
struct work_struct watchdog_task;
struct work_struct linkstate_task;
struct delayed_work stats_task;
+ struct delayed_work service_task;
struct mlx4_en_perf_stats pstats;
struct mlx4_en_pkt_stats pkstats;
+ struct mlx4_en_pkt_stats pkstats_last;
+ struct mlx4_en_flow_stats flowstats[MLX4_NUM_PRIORITIES];
struct mlx4_en_port_stats port_stats;
+ struct mlx4_en_vport_stats vport_stats;
+ struct mlx4_en_vf_stats vf_stats;
+ DECLARE_BITMAP(stats_bitmap, NUM_ALL_STATS);
+ struct list_head mc_list;
+ struct list_head curr_list;
+ u64 broadcast_id;
struct mlx4_en_stat_out_mbox hw_stats;
- struct ifmedia media;
+ int vids[128];
+ bool wol;
+ struct device *ddev;
+ struct dentry *dev_root;
+ u32 counter_index;
eventhandler_tag vlan_attach;
eventhandler_tag vlan_detach;
struct callout watchdog_timer;
+ struct ifmedia media;
volatile int blocked;
struct sysctl_oid *sysctl;
struct sysctl_ctx_list conf_ctx;
struct sysctl_ctx_list stat_ctx;
+#define MLX4_EN_MAC_HASH_IDX 5
+ struct hlist_head mac_hash[MLX4_EN_MAC_HASH_SIZE];
+
+#ifdef CONFIG_MLX4_EN_DCB
+ struct ieee_ets ets;
+ u16 maxrate[IEEE_8021QAZ_MAX_TCS];
+ u8 dcbx_cap;
+#endif
+#ifdef CONFIG_RFS_ACCEL
+ spinlock_t filters_lock;
+ int last_filter_id;
+ struct list_head filters;
+ struct hlist_head filter_hash[1 << MLX4_EN_FILTER_HASH_SHIFT];
+#endif
+ struct en_port *vf_ports[MLX4_MAX_NUM_VF];
+ unsigned long last_ifq_jiffies;
+ u64 if_counters_rx_errors;
+ u64 if_counters_rx_no_buffer;
+
};
enum mlx4_en_wol {
MLX4_EN_WOL_MAGIC = (1ULL << 61),
MLX4_EN_WOL_ENABLED = (1ULL << 62),
- MLX4_EN_WOL_DO_MODIFY = (1ULL << 63),
};
-int mlx4_en_transmit(struct net_device *dev, struct mbuf *mb);
-void mlx4_en_qflush(struct net_device *dev);
+struct mlx4_mac_entry {
+ struct hlist_node hlist;
+ unsigned char mac[ETH_ALEN + 2];
+ u64 reg_id;
+};
+
+#ifdef CONFIG_NET_RX_BUSY_POLL
+static inline void mlx4_en_cq_init_lock(struct mlx4_en_cq *cq)
+{
+ spin_lock_init(&cq->poll_lock);
+ cq->state = MLX4_EN_CQ_STATEIDLE;
+}
+
+/* called from the device poll rutine to get ownership of a cq */
+static inline bool mlx4_en_cq_lock_napi(struct mlx4_en_cq *cq)
+{
+ int rc = true;
+ spin_lock(&cq->poll_lock);
+ if (cq->state & MLX4_CQ_LOCKED) {
+ WARN_ON(cq->state & MLX4_EN_CQ_STATENAPI);
+ cq->state |= MLX4_EN_CQ_STATENAPI_YIELD;
+ rc = false;
+ } else
+ /* we don't care if someone yielded */
+ cq->state = MLX4_EN_CQ_STATENAPI;
+ spin_unlock(&cq->poll_lock);
+ return rc;
+}
+
+/* returns true is someone tried to get the cq while napi had it */
+static inline bool mlx4_en_cq_unlock_napi(struct mlx4_en_cq *cq)
+{
+ int rc = false;
+ spin_lock(&cq->poll_lock);
+ WARN_ON(cq->state & (MLX4_EN_CQ_STATEPOLL |
+ MLX4_EN_CQ_STATENAPI_YIELD));
+
+ if (cq->state & MLX4_EN_CQ_STATEPOLL_YIELD)
+ rc = true;
+ cq->state = MLX4_EN_CQ_STATEIDLE;
+ spin_unlock(&cq->poll_lock);
+ return rc;
+}
+
+/* called from mlx4_en_low_latency_poll() */
+static inline bool mlx4_en_cq_lock_poll(struct mlx4_en_cq *cq)
+{
+ int rc = true;
+ spin_lock_bh(&cq->poll_lock);
+ if ((cq->state & MLX4_CQ_LOCKED)) {
+ struct net_device *dev = cq->dev;
+ struct mlx4_en_priv *priv = netdev_priv(dev);
+ struct mlx4_en_rx_ring *rx_ring = priv->rx_ring[cq->ring];
+
+ cq->state |= MLX4_EN_CQ_STATEPOLL_YIELD;
+ rc = false;
+#ifdef LL_EXTENDED_STATS
+ rx_ring->yields++;
+#endif
+ } else
+ /* preserve yield marks */
+ cq->state |= MLX4_EN_CQ_STATEPOLL;
+ spin_unlock_bh(&cq->poll_lock);
+ return rc;
+}
+
+/* returns true if someone tried to get the cq while it was locked */
+static inline bool mlx4_en_cq_unlock_poll(struct mlx4_en_cq *cq)
+{
+ int rc = false;
+ spin_lock_bh(&cq->poll_lock);
+ WARN_ON(cq->state & (MLX4_EN_CQ_STATENAPI));
+
+ if (cq->state & MLX4_EN_CQ_STATEPOLL_YIELD)
+ rc = true;
+ cq->state = MLX4_EN_CQ_STATEIDLE;
+ spin_unlock_bh(&cq->poll_lock);
+ return rc;
+}
+
+/* true if a socket is polling, even if it did not get the lock */
+static inline bool mlx4_en_cq_ll_polling(struct mlx4_en_cq *cq)
+{
+ WARN_ON(!(cq->state & MLX4_CQ_LOCKED));
+ return cq->state & CQ_USER_PEND;
+}
+#else
+static inline void mlx4_en_cq_init_lock(struct mlx4_en_cq *cq)
+{
+}
+
+static inline bool mlx4_en_cq_lock_napi(struct mlx4_en_cq *cq)
+{
+ return true;
+}
+
+static inline bool mlx4_en_cq_unlock_napi(struct mlx4_en_cq *cq)
+{
+ return false;
+}
+
+static inline bool mlx4_en_cq_lock_poll(struct mlx4_en_cq *cq)
+{
+ return false;
+}
+
+static inline bool mlx4_en_cq_unlock_poll(struct mlx4_en_cq *cq)
+{
+ return false;
+}
+
+static inline bool mlx4_en_cq_ll_polling(struct mlx4_en_cq *cq)
+{
+ return false;
+}
+#endif /* CONFIG_NET_RX_BUSY_POLL */
+
+#define MLX4_EN_WOL_DO_MODIFY (1ULL << 63)
-int mlx4_en_rx_frags(struct mlx4_en_priv *priv, struct mlx4_en_rx_ring *ring,
- struct mbuf *mb, struct mlx4_cqe *cqe);
-void mlx4_en_flush_frags(struct mlx4_en_priv *priv,
- struct mlx4_en_rx_ring *ring);
void mlx4_en_destroy_netdev(struct net_device *dev);
int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
struct mlx4_en_port_profile *prof);
-int mlx4_en_do_start_port(struct net_device *dev);
-void mlx4_en_do_stop_port(struct net_device *dev);
+int mlx4_en_start_port(struct net_device *dev);
+void mlx4_en_stop_port(struct net_device *dev);
void mlx4_en_free_resources(struct mlx4_en_priv *priv);
int mlx4_en_alloc_resources(struct mlx4_en_priv *priv);
-int mlx4_en_create_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
- int entries, int ring, enum cq_type mode);
-void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
-int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
+int mlx4_en_pre_config(struct mlx4_en_priv *priv);
+int mlx4_en_create_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq **pcq,
+ int entries, int ring, enum cq_type mode, int node);
+void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq **pcq);
+int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
+ int cq_idx);
void mlx4_en_deactivate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
int mlx4_en_set_cq_moder(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
int mlx4_en_arm_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
-void mlx4_en_poll_tx_cq(unsigned long data);
void mlx4_en_tx_irq(struct mlx4_cq *mcq);
u16 mlx4_en_select_queue(struct net_device *dev, struct mbuf *mb);
-int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv, struct mlx4_en_tx_ring *ring,
- u32 size, u16 stride);
-void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv, struct mlx4_en_tx_ring *ring);
+int mlx4_en_transmit(struct ifnet *dev, struct mbuf *m);
+int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
+ struct mlx4_en_tx_ring **pring,
+ u32 size, u16 stride, int node, int queue_idx);
+void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv,
+ struct mlx4_en_tx_ring **pring);
int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
struct mlx4_en_tx_ring *ring,
- int cq);
+ int cq, int user_prio);
void mlx4_en_deactivate_tx_ring(struct mlx4_en_priv *priv,
struct mlx4_en_tx_ring *ring);
+void mlx4_en_qflush(struct ifnet *dev);
int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
- struct mlx4_en_rx_ring *ring, u32 size);
+ struct mlx4_en_rx_ring **pring,
+ u32 size, int node);
void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv,
- struct mlx4_en_rx_ring *ring);
+ struct mlx4_en_rx_ring **pring,
+ u32 size, u16 stride);
+void mlx4_en_tx_que(void *context, int pending);
+void mlx4_en_rx_que(void *context, int pending);
int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv);
void mlx4_en_deactivate_rx_ring(struct mlx4_en_priv *priv,
struct mlx4_en_rx_ring *ring);
int mlx4_en_process_rx_cq(struct net_device *dev,
struct mlx4_en_cq *cq,
int budget);
-int mlx4_en_process_rx_cq_mb(struct net_device *dev,
- struct mlx4_en_cq *cq,
- int budget);
-void mlx4_en_tx_que(void *context, int pending);
-void mlx4_en_rx_que(void *context, int pending);
+void mlx4_en_poll_tx_cq(unsigned long data);
void mlx4_en_fill_qp_context(struct mlx4_en_priv *priv, int size, int stride,
- int is_tx, int rss, int qpn, int cqn,
- struct mlx4_qp_context *context);
+ int is_tx, int rss, int qpn, int cqn, int user_prio,
+ struct mlx4_qp_context *context);
void mlx4_en_sqp_event(struct mlx4_qp *qp, enum mlx4_event event);
int mlx4_en_map_buffer(struct mlx4_buf *buf);
void mlx4_en_unmap_buffer(struct mlx4_buf *buf);
-
void mlx4_en_calc_rx_buf(struct net_device *dev);
-void mlx4_en_set_prio_map(struct mlx4_en_priv *priv, u16 *prio_map, u32 ring_num);
+
int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv);
void mlx4_en_release_rss_steer(struct mlx4_en_priv *priv);
+int mlx4_en_create_drop_qp(struct mlx4_en_priv *priv);
+void mlx4_en_destroy_drop_qp(struct mlx4_en_priv *priv);
int mlx4_en_free_tx_buf(struct net_device *dev, struct mlx4_en_tx_ring *ring);
void mlx4_en_rx_irq(struct mlx4_cq *mcq);
-//int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, u64 mac, u64 clear, u8 mode);
-int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, u8 port, u32 *vlans);
-//int mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu,
-// u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx);
-//int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
-// u8 promisc);
+int mlx4_SET_MCAST_FLTR(struct mlx4_dev *dev, u8 port, u64 mac, u64 clear, u8 mode);
+int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, struct mlx4_en_priv *priv);
int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset);
int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port);
+int mlx4_en_get_vport_stats(struct mlx4_en_dev *mdev, u8 port);
+void mlx4_en_create_debug_files(struct mlx4_en_priv *priv);
+void mlx4_en_delete_debug_files(struct mlx4_en_priv *priv);
+int mlx4_en_register_debugfs(void);
+void mlx4_en_unregister_debugfs(void);
+
+#ifdef CONFIG_MLX4_EN_DCB
+extern const struct dcbnl_rtnl_ops mlx4_en_dcbnl_ops;
+extern const struct dcbnl_rtnl_ops mlx4_en_dcbnl_pfc_ops;
+#endif
+
+int mlx4_en_setup_tc(struct net_device *dev, u8 up);
+
+#ifdef CONFIG_RFS_ACCEL
+void mlx4_en_cleanup_filters(struct mlx4_en_priv *priv,
+ struct mlx4_en_rx_ring *rx_ring);
+#endif
#define MLX4_EN_NUM_SELF_TEST 5
void mlx4_en_ex_selftest(struct net_device *dev, u32 *flags, u64 *buf);
-u64 mlx4_en_mac_to_u64(u8 *addr);
+void mlx4_en_ptp_overflow_check(struct mlx4_en_dev *mdev);
+
+/*
+ * Functions for time stamping
+ */
+#define SKBTX_HW_TSTAMP (1 << 0)
+#define SKBTX_IN_PROGRESS (1 << 2)
+
+u64 mlx4_en_get_cqe_ts(struct mlx4_cqe *cqe);
+
+/* Functions for caching and restoring statistics */
+int mlx4_en_get_sset_count(struct net_device *dev, int sset);
+void mlx4_en_restore_ethtool_stats(struct mlx4_en_priv *priv,
+ u64 *data);
/*
* Globals
*/
extern const struct ethtool_ops mlx4_en_ethtool_ops;
+
+/*
+ * Defines for link speed - needed by selftest
+ */
+#define MLX4_EN_LINK_SPEED_1G 1000
+#define MLX4_EN_LINK_SPEED_10G 10000
+#define MLX4_EN_LINK_SPEED_40G 40000
+
+enum {
+ NETIF_MSG_DRV = 0x0001,
+ NETIF_MSG_PROBE = 0x0002,
+ NETIF_MSG_LINK = 0x0004,
+ NETIF_MSG_TIMER = 0x0008,
+ NETIF_MSG_IFDOWN = 0x0010,
+ NETIF_MSG_IFUP = 0x0020,
+ NETIF_MSG_RX_ERR = 0x0040,
+ NETIF_MSG_TX_ERR = 0x0080,
+ NETIF_MSG_TX_QUEUED = 0x0100,
+ NETIF_MSG_INTR = 0x0200,
+ NETIF_MSG_TX_DONE = 0x0400,
+ NETIF_MSG_RX_STATUS = 0x0800,
+ NETIF_MSG_PKTDATA = 0x1000,
+ NETIF_MSG_HW = 0x2000,
+ NETIF_MSG_WOL = 0x4000,
+};
+
+
+/*
+ * printk / logging functions
+ */
+
+#define en_print(level, priv, format, arg...) \
+ { \
+ if ((priv)->registered) \
+ printk(level "%s: %s: " format, DRV_NAME, \
+ (priv->dev)->if_xname, ## arg); \
+ else \
+ printk(level "%s: %s: Port %d: " format, \
+ DRV_NAME, dev_name(&priv->mdev->pdev->dev), \
+ (priv)->port, ## arg); \
+ }
+
+
+#define en_dbg(mlevel, priv, format, arg...) \
+do { \
+ if (NETIF_MSG_##mlevel & priv->msg_enable) \
+ en_print(KERN_DEBUG, priv, format, ##arg); \
+} while (0)
+#define en_warn(priv, format, arg...) \
+ en_print(KERN_WARNING, priv, format, ##arg)
+#define en_err(priv, format, arg...) \
+ en_print(KERN_ERR, priv, format, ##arg)
+#define en_info(priv, format, arg...) \
+ en_print(KERN_INFO, priv, format, ## arg)
+
+#define mlx4_err(mdev, format, arg...) \
+ pr_err("%s %s: " format, DRV_NAME, \
+ dev_name(&mdev->pdev->dev), ##arg)
+#define mlx4_info(mdev, format, arg...) \
+ pr_info("%s %s: " format, DRV_NAME, \
+ dev_name(&mdev->pdev->dev), ##arg)
+#define mlx4_warn(mdev, format, arg...) \
+ pr_warning("%s %s: " format, DRV_NAME, \
+ dev_name(&mdev->pdev->dev), ##arg)
+
#endif
diff --git a/sys/ofed/drivers/net/mlx4/mlx4_stats.h b/sys/ofed/drivers/net/mlx4/mlx4_stats.h
new file mode 100644
index 0000000..0270cef
--- /dev/null
+++ b/sys/ofed/drivers/net/mlx4/mlx4_stats.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2014 Mellanox Technologies Ltd. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _MLX4_STATS_
+#define _MLX4_STATS_
+
+
+#ifdef MLX4_EN_PERF_STAT
+#define NUM_PERF_STATS NUM_PERF_COUNTERS
+#else
+#define NUM_PERF_STATS 0
+#endif
+
+#define NUM_PRIORITIES 9
+#define NUM_PRIORITY_STATS 2
+
+struct mlx4_en_pkt_stats {
+ unsigned long rx_packets;
+ unsigned long rx_bytes;
+ unsigned long rx_multicast_packets;
+ unsigned long rx_broadcast_packets;
+ unsigned long rx_errors;
+ unsigned long rx_dropped;
+ unsigned long rx_length_errors;
+ unsigned long rx_over_errors;
+ unsigned long rx_crc_errors;
+ unsigned long rx_jabbers;
+ unsigned long rx_in_range_length_error;
+ unsigned long rx_out_range_length_error;
+ unsigned long rx_lt_64_bytes_packets;
+ unsigned long rx_127_bytes_packets;
+ unsigned long rx_255_bytes_packets;
+ unsigned long rx_511_bytes_packets;
+ unsigned long rx_1023_bytes_packets;
+ unsigned long rx_1518_bytes_packets;
+ unsigned long rx_1522_bytes_packets;
+ unsigned long rx_1548_bytes_packets;
+ unsigned long rx_gt_1548_bytes_packets;
+ unsigned long tx_packets;
+ unsigned long tx_bytes;
+ unsigned long tx_multicast_packets;
+ unsigned long tx_broadcast_packets;
+ unsigned long tx_errors;
+ unsigned long tx_dropped;
+ unsigned long tx_lt_64_bytes_packets;
+ unsigned long tx_127_bytes_packets;
+ unsigned long tx_255_bytes_packets;
+ unsigned long tx_511_bytes_packets;
+ unsigned long tx_1023_bytes_packets;
+ unsigned long tx_1518_bytes_packets;
+ unsigned long tx_1522_bytes_packets;
+ unsigned long tx_1548_bytes_packets;
+ unsigned long tx_gt_1548_bytes_packets;
+ unsigned long rx_prio[NUM_PRIORITIES][NUM_PRIORITY_STATS];
+ unsigned long tx_prio[NUM_PRIORITIES][NUM_PRIORITY_STATS];
+#define NUM_PKT_STATS 72
+};
+
+struct mlx4_en_vf_stats {
+ unsigned long rx_packets;
+ unsigned long rx_bytes;
+ unsigned long rx_multicast_packets;
+ unsigned long rx_broadcast_packets;
+ unsigned long rx_errors;
+ unsigned long rx_dropped;
+ unsigned long tx_packets;
+ unsigned long tx_bytes;
+ unsigned long tx_multicast_packets;
+ unsigned long tx_broadcast_packets;
+ unsigned long tx_errors;
+#define NUM_VF_STATS 11
+};
+
+struct mlx4_en_vport_stats {
+ unsigned long rx_unicast_packets;
+ unsigned long rx_unicast_bytes;
+ unsigned long rx_multicast_packets;
+ unsigned long rx_multicast_bytes;
+ unsigned long rx_broadcast_packets;
+ unsigned long rx_broadcast_bytes;
+ unsigned long rx_dropped;
+ unsigned long rx_errors;
+ unsigned long tx_unicast_packets;
+ unsigned long tx_unicast_bytes;
+ unsigned long tx_multicast_packets;
+ unsigned long tx_multicast_bytes;
+ unsigned long tx_broadcast_packets;
+ unsigned long tx_broadcast_bytes;
+ unsigned long tx_errors;
+#define NUM_VPORT_STATS 15
+};
+
+struct mlx4_en_port_stats {
+ unsigned long tso_packets;
+ unsigned long queue_stopped;
+ unsigned long wake_queue;
+ unsigned long tx_timeout;
+ unsigned long rx_alloc_failed;
+ unsigned long rx_chksum_good;
+ unsigned long rx_chksum_none;
+ unsigned long tx_chksum_offload;
+#define NUM_PORT_STATS 8
+};
+
+struct mlx4_en_perf_stats {
+ u32 tx_poll;
+ u64 tx_pktsz_avg;
+ u32 inflight_avg;
+ u16 tx_coal_avg;
+ u16 rx_coal_avg;
+ u32 napi_quota;
+#define NUM_PERF_COUNTERS 6
+};
+
+struct mlx4_en_flow_stats {
+ u64 rx_pause;
+ u64 rx_pause_duration;
+ u64 rx_pause_transition;
+ u64 tx_pause;
+ u64 tx_pause_duration;
+ u64 tx_pause_transition;
+};
+#define MLX4_NUM_PRIORITIES 8
+#define NUM_FLOW_PRIORITY_STATS 6
+#define NUM_FLOW_STATS (NUM_FLOW_PRIORITY_STATS*MLX4_NUM_PRIORITIES)
+
+
+struct mlx4_en_stat_out_flow_control_mbox {
+ /* Total number of PAUSE frames received from the far-end port */
+ __be64 rx_pause;
+ /* Total number of microseconds that far-end port requested to pause
+ * transmission of packets
+ */
+ __be64 rx_pause_duration;
+ /* Number of received transmission from XOFF state to XON state */
+ __be64 rx_pause_transition;
+ /* Total number of PAUSE frames sent from the far-end port */
+ __be64 tx_pause;
+ /* Total time in microseconds that transmission of packets has been
+ * paused
+ */
+ __be64 tx_pause_duration;
+ /* Number of transmitter transitions from XOFF state to XON state */
+ __be64 tx_pause_transition;
+ /* Reserverd */
+ __be64 reserved[2];
+};
+
+int mlx4_get_vport_ethtool_stats(struct mlx4_dev *dev, int port,
+ struct mlx4_en_vport_stats *vport_stats,
+ int reset);
+
+#define NUM_ALL_STATS (NUM_PKT_STATS + NUM_FLOW_STATS + NUM_VPORT_STATS + \
+ NUM_VF_STATS + NUM_PORT_STATS + NUM_PERF_STATS)
+#endif
diff --git a/sys/ofed/drivers/net/mlx4/mr.c b/sys/ofed/drivers/net/mlx4/mr.c
index 69a0abd..876d16d 100644
--- a/sys/ofed/drivers/net/mlx4/mr.c
+++ b/sys/ofed/drivers/net/mlx4/mr.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
- * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005, 2006, 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
* Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -32,30 +32,20 @@
* SOFTWARE.
*/
+#include <linux/err.h>
#include <linux/errno.h>
+#include <linux/module.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/vmalloc.h>
#include <linux/mlx4/cmd.h>
+#include <linux/math64.h>
+
#include "mlx4.h"
#include "icm.h"
-#define MLX4_MPT_FLAG_SW_OWNS (0xfUL << 28)
-#define MLX4_MPT_FLAG_FREE (0x3UL << 28)
-#define MLX4_MPT_FLAG_MIO (1 << 17)
-#define MLX4_MPT_FLAG_BIND_ENABLE (1 << 15)
-#define MLX4_MPT_FLAG_PHYSICAL (1 << 9)
-#define MLX4_MPT_FLAG_REGION (1 << 8)
-
-#define MLX4_MPT_PD_FLAG_FAST_REG (1 << 27)
-#define MLX4_MPT_PD_FLAG_RAE (1 << 28)
-#define MLX4_MPT_PD_FLAG_EN_INV (3 << 24)
-
-#define MLX4_MPT_STATUS_SW 0xF0
-#define MLX4_MPT_STATUS_HW 0x00
-
static u32 mlx4_buddy_alloc(struct mlx4_buddy *buddy, int order)
{
int o;
@@ -129,9 +119,8 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order)
for (i = 0; i <= buddy->max_order; ++i) {
s = BITS_TO_LONGS(1 << (buddy->max_order - i));
buddy->bits[i] = kcalloc(s, sizeof (long), GFP_KERNEL | __GFP_NOWARN);
- if (!buddy->bits[i]) {
- goto err_out_free;
- }
+ if (!buddy->bits[i])
+ goto err_out_free;
}
set_bit(0, buddy->bits[buddy->max_order]);
@@ -141,8 +130,7 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order)
err_out_free:
for (i = 0; i <= buddy->max_order; ++i)
- if ( buddy->bits[i] )
- kfree(buddy->bits[i]);
+ kfree(buddy->bits[i]);
err_out:
kfree(buddy->bits);
@@ -156,7 +144,7 @@ static void mlx4_buddy_cleanup(struct mlx4_buddy *buddy)
int i;
for (i = 0; i <= buddy->max_order; ++i)
- kfree(buddy->bits[i]);
+ kfree(buddy->bits[i]);
kfree(buddy->bits);
kfree(buddy->num_free);
@@ -315,7 +303,7 @@ static int mlx4_mr_alloc_reserved(struct mlx4_dev *dev, u32 mridx, u32 pd,
mr->size = size;
mr->pd = pd;
mr->access = access;
- mr->enabled = MLX4_MR_DISABLED;
+ mr->enabled = MLX4_MPT_DISABLED;
mr->key = hw_index_to_key(mridx);
return mlx4_mtt_init(dev, npages, page_shift, &mr->mtt);
@@ -329,14 +317,14 @@ static int mlx4_WRITE_MTT(struct mlx4_dev *dev,
MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
}
-int __mlx4_mr_reserve(struct mlx4_dev *dev)
+int __mlx4_mpt_reserve(struct mlx4_dev *dev)
{
struct mlx4_priv *priv = mlx4_priv(dev);
return mlx4_bitmap_alloc(&priv->mr_table.mpt_bitmap);
}
-static int mlx4_mr_reserve(struct mlx4_dev *dev)
+static int mlx4_mpt_reserve(struct mlx4_dev *dev)
{
u64 out_param;
@@ -347,17 +335,17 @@ static int mlx4_mr_reserve(struct mlx4_dev *dev)
return -1;
return get_param_l(&out_param);
}
- return __mlx4_mr_reserve(dev);
+ return __mlx4_mpt_reserve(dev);
}
-void __mlx4_mr_release(struct mlx4_dev *dev, u32 index)
+void __mlx4_mpt_release(struct mlx4_dev *dev, u32 index)
{
struct mlx4_priv *priv = mlx4_priv(dev);
- mlx4_bitmap_free(&priv->mr_table.mpt_bitmap, index);
+ mlx4_bitmap_free(&priv->mr_table.mpt_bitmap, index, MLX4_NO_RR);
}
-static void mlx4_mr_release(struct mlx4_dev *dev, u32 index)
+static void mlx4_mpt_release(struct mlx4_dev *dev, u32 index)
{
u64 in_param = 0;
@@ -370,17 +358,17 @@ static void mlx4_mr_release(struct mlx4_dev *dev, u32 index)
index);
return;
}
- __mlx4_mr_release(dev, index);
+ __mlx4_mpt_release(dev, index);
}
-int __mlx4_mr_alloc_icm(struct mlx4_dev *dev, u32 index)
+int __mlx4_mpt_alloc_icm(struct mlx4_dev *dev, u32 index)
{
struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table;
return mlx4_table_get(dev, &mr_table->dmpt_table, index);
}
-static int mlx4_mr_alloc_icm(struct mlx4_dev *dev, u32 index)
+static int mlx4_mpt_alloc_icm(struct mlx4_dev *dev, u32 index)
{
u64 param = 0;
@@ -391,17 +379,17 @@ static int mlx4_mr_alloc_icm(struct mlx4_dev *dev, u32 index)
MLX4_CMD_TIME_CLASS_A,
MLX4_CMD_WRAPPED);
}
- return __mlx4_mr_alloc_icm(dev, index);
+ return __mlx4_mpt_alloc_icm(dev, index);
}
-void __mlx4_mr_free_icm(struct mlx4_dev *dev, u32 index)
+void __mlx4_mpt_free_icm(struct mlx4_dev *dev, u32 index)
{
struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table;
mlx4_table_put(dev, &mr_table->dmpt_table, index);
}
-static void mlx4_mr_free_icm(struct mlx4_dev *dev, u32 index)
+static void mlx4_mpt_free_icm(struct mlx4_dev *dev, u32 index)
{
u64 in_param = 0;
@@ -414,7 +402,7 @@ static void mlx4_mr_free_icm(struct mlx4_dev *dev, u32 index)
index);
return;
}
- return __mlx4_mr_free_icm(dev, index);
+ return __mlx4_mpt_free_icm(dev, index);
}
int mlx4_mr_alloc(struct mlx4_dev *dev, u32 pd, u64 iova, u64 size, u32 access,
@@ -423,41 +411,52 @@ int mlx4_mr_alloc(struct mlx4_dev *dev, u32 pd, u64 iova, u64 size, u32 access,
u32 index;
int err;
- index = mlx4_mr_reserve(dev);
+ index = mlx4_mpt_reserve(dev);
if (index == -1)
return -ENOMEM;
err = mlx4_mr_alloc_reserved(dev, index, pd, iova, size,
access, npages, page_shift, mr);
if (err)
- mlx4_mr_release(dev, index);
+ mlx4_mpt_release(dev, index);
return err;
}
EXPORT_SYMBOL_GPL(mlx4_mr_alloc);
-static void mlx4_mr_free_reserved(struct mlx4_dev *dev, struct mlx4_mr *mr)
+static int mlx4_mr_free_reserved(struct mlx4_dev *dev, struct mlx4_mr *mr)
{
int err;
- if (mr->enabled == MLX4_MR_EN_HW) {
+ if (mr->enabled == MLX4_MPT_EN_HW) {
err = mlx4_HW2SW_MPT(dev, NULL,
key_to_hw_index(mr->key) &
(dev->caps.num_mpts - 1));
- if (err)
- mlx4_warn(dev, "xxx HW2SW_MPT failed (%d)\n", err);
+ if (err) {
+ mlx4_warn(dev, "HW2SW_MPT failed (%d).", err);
+ mlx4_warn(dev, "Most likely the MR has MWs bound to it.\n");
+ return err;
+ }
- mr->enabled = MLX4_MR_EN_SW;
+ mr->enabled = MLX4_MPT_EN_SW;
}
mlx4_mtt_cleanup(dev, &mr->mtt);
+
+ return 0;
}
-void mlx4_mr_free(struct mlx4_dev *dev, struct mlx4_mr *mr)
+int mlx4_mr_free(struct mlx4_dev *dev, struct mlx4_mr *mr)
{
- mlx4_mr_free_reserved(dev, mr);
+ int ret;
+
+ ret = mlx4_mr_free_reserved(dev, mr);
+ if (ret)
+ return ret;
if (mr->enabled)
- mlx4_mr_free_icm(dev, key_to_hw_index(mr->key));
- mlx4_mr_release(dev, key_to_hw_index(mr->key));
+ mlx4_mpt_free_icm(dev, key_to_hw_index(mr->key));
+ mlx4_mpt_release(dev, key_to_hw_index(mr->key));
+
+ return 0;
}
EXPORT_SYMBOL_GPL(mlx4_mr_free);
@@ -467,7 +466,7 @@ int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr)
struct mlx4_mpt_entry *mpt_entry;
int err;
- err = mlx4_mr_alloc_icm(dev, key_to_hw_index(mr->key));
+ err = mlx4_mpt_alloc_icm(dev, key_to_hw_index(mr->key));
if (err)
return err;
@@ -514,7 +513,7 @@ int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr)
mlx4_warn(dev, "SW2HW_MPT failed (%d)\n", err);
goto err_cmd;
}
- mr->enabled = MLX4_MR_EN_HW;
+ mr->enabled = MLX4_MPT_EN_HW;
mlx4_free_cmd_mailbox(dev, mailbox);
@@ -524,7 +523,7 @@ err_cmd:
mlx4_free_cmd_mailbox(dev, mailbox);
err_table:
- mlx4_mr_free_icm(dev, key_to_hw_index(mr->key));
+ mlx4_mpt_free_icm(dev, key_to_hw_index(mr->key));
return err;
}
EXPORT_SYMBOL_GPL(mlx4_mr_enable);
@@ -651,6 +650,95 @@ int mlx4_buf_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
}
EXPORT_SYMBOL_GPL(mlx4_buf_write_mtt);
+int mlx4_mw_alloc(struct mlx4_dev *dev, u32 pd, enum mlx4_mw_type type,
+ struct mlx4_mw *mw)
+{
+ u32 index;
+
+ index = mlx4_mpt_reserve(dev);
+ if (index == -1)
+ return -ENOMEM;
+
+ mw->key = hw_index_to_key(index);
+ mw->pd = pd;
+ mw->type = type;
+ mw->enabled = MLX4_MPT_DISABLED;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mlx4_mw_alloc);
+
+int mlx4_mw_enable(struct mlx4_dev *dev, struct mlx4_mw *mw)
+{
+ struct mlx4_cmd_mailbox *mailbox;
+ struct mlx4_mpt_entry *mpt_entry;
+ int err;
+
+ err = mlx4_mpt_alloc_icm(dev, key_to_hw_index(mw->key));
+ if (err)
+ return err;
+
+ mailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(mailbox)) {
+ err = PTR_ERR(mailbox);
+ goto err_table;
+ }
+ mpt_entry = mailbox->buf;
+
+ memset(mpt_entry, 0, sizeof(*mpt_entry));
+
+ /* Note that the MLX4_MPT_FLAG_REGION bit in mpt_entry->flags is turned
+ * off, thus creating a memory window and not a memory region.
+ */
+ mpt_entry->key = cpu_to_be32(key_to_hw_index(mw->key));
+ mpt_entry->pd_flags = cpu_to_be32(mw->pd);
+ if (mw->type == MLX4_MW_TYPE_2) {
+ mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_FREE);
+ mpt_entry->qpn = cpu_to_be32(MLX4_MPT_QP_FLAG_BOUND_QP);
+ mpt_entry->pd_flags |= cpu_to_be32(MLX4_MPT_PD_FLAG_EN_INV);
+ }
+
+ err = mlx4_SW2HW_MPT(dev, mailbox,
+ key_to_hw_index(mw->key) &
+ (dev->caps.num_mpts - 1));
+ if (err) {
+ mlx4_warn(dev, "SW2HW_MPT failed (%d)\n", err);
+ goto err_cmd;
+ }
+ mw->enabled = MLX4_MPT_EN_HW;
+
+ mlx4_free_cmd_mailbox(dev, mailbox);
+
+ return 0;
+
+err_cmd:
+ mlx4_free_cmd_mailbox(dev, mailbox);
+
+err_table:
+ mlx4_mpt_free_icm(dev, key_to_hw_index(mw->key));
+ return err;
+}
+EXPORT_SYMBOL_GPL(mlx4_mw_enable);
+
+void mlx4_mw_free(struct mlx4_dev *dev, struct mlx4_mw *mw)
+{
+ int err;
+
+ if (mw->enabled == MLX4_MPT_EN_HW) {
+ err = mlx4_HW2SW_MPT(dev, NULL,
+ key_to_hw_index(mw->key) &
+ (dev->caps.num_mpts - 1));
+ if (err)
+ mlx4_warn(dev, "xxx HW2SW_MPT failed (%d)\n", err);
+
+ mw->enabled = MLX4_MPT_EN_SW;
+ }
+ if (mw->enabled)
+ mlx4_mpt_free_icm(dev, key_to_hw_index(mw->key));
+ mlx4_mpt_release(dev, key_to_hw_index(mw->key));
+}
+EXPORT_SYMBOL_GPL(mlx4_mw_free);
+
int mlx4_init_mr_table(struct mlx4_dev *dev)
{
struct mlx4_priv *priv = mlx4_priv(dev);
@@ -671,8 +759,8 @@ int mlx4_init_mr_table(struct mlx4_dev *dev)
return err;
err = mlx4_buddy_init(&mr_table->mtt_buddy,
- ilog2((u32)dev->caps.num_mtts /
- (1 << log_mtts_per_seg)));
+ ilog2(div_u64(dev->caps.num_mtts,
+ (1 << log_mtts_per_seg))));
if (err)
goto err_buddy;
@@ -791,7 +879,7 @@ int mlx4_fmr_alloc(struct mlx4_dev *dev, u32 pd, u32 access, int max_pages,
int max_maps, u8 page_shift, struct mlx4_fmr *fmr)
{
struct mlx4_priv *priv = mlx4_priv(dev);
- int err = -ENOMEM;
+ int err = -ENOMEM, ret;
if (max_maps > dev->caps.max_fmr_maps)
return -EINVAL;
@@ -825,7 +913,9 @@ int mlx4_fmr_alloc(struct mlx4_dev *dev, u32 pd, u32 access, int max_pages,
return 0;
err_free:
- mlx4_mr_free(dev, &fmr->mr);
+ ret = mlx4_mr_free(dev, &fmr->mr);
+ if (ret)
+ mlx4_err(dev, "Error deregistering MR. The system may have become unstable.");
return err;
}
EXPORT_SYMBOL_GPL(mlx4_fmr_alloc);
@@ -851,40 +941,48 @@ EXPORT_SYMBOL_GPL(mlx4_fmr_enable);
void mlx4_fmr_unmap(struct mlx4_dev *dev, struct mlx4_fmr *fmr,
u32 *lkey, u32 *rkey)
{
- struct mlx4_cmd_mailbox *mailbox;
- int err;
+ u32 key;
if (!fmr->maps)
return;
- fmr->maps = 0;
+ key = key_to_hw_index(fmr->mr.key) & (dev->caps.num_mpts - 1);
- mailbox = mlx4_alloc_cmd_mailbox(dev);
- if (IS_ERR(mailbox)) {
- err = PTR_ERR(mailbox);
- mlx4_warn(dev, "mlx4_alloc_cmd_mailbox failed (%d)\n", err);
- return;
- }
+ *(u8 *)fmr->mpt = MLX4_MPT_STATUS_SW;
- err = mlx4_HW2SW_MPT(dev, NULL,
- key_to_hw_index(fmr->mr.key) &
- (dev->caps.num_mpts - 1));
- mlx4_free_cmd_mailbox(dev, mailbox);
- if (err) {
- mlx4_warn(dev, "mlx4_HW2SW_MPT failed (%d)\n", err);
- return;
- }
- fmr->mr.enabled = MLX4_MR_EN_SW;
+ /* Make sure MPT status is visible before changing MPT fields */
+ wmb();
+
+ fmr->mr.key = hw_index_to_key(key);
+
+ fmr->mpt->key = cpu_to_be32(key);
+ fmr->mpt->lkey = cpu_to_be32(key);
+ fmr->mpt->length = 0;
+ fmr->mpt->start = 0;
+
+ /* Make sure MPT data is visible before changing MPT status */
+ wmb();
+
+ *(u8 *)fmr->mpt = MLX4_MPT_STATUS_HW;
+
+ /* Make sure MPT satus is visible */
+ wmb();
+
+ fmr->maps = 0;
}
EXPORT_SYMBOL_GPL(mlx4_fmr_unmap);
int mlx4_fmr_free(struct mlx4_dev *dev, struct mlx4_fmr *fmr)
{
+ int ret;
+
if (fmr->maps)
return -EBUSY;
- mlx4_mr_free(dev, &fmr->mr);
- fmr->mr.enabled = MLX4_MR_DISABLED;
+ ret = mlx4_mr_free(dev, &fmr->mr);
+ if (ret)
+ return ret;
+ fmr->mr.enabled = MLX4_MPT_DISABLED;
return 0;
}
diff --git a/sys/ofed/drivers/net/mlx4/pd.c b/sys/ofed/drivers/net/mlx4/pd.c
index 2c525aa..5162a47 100644
--- a/sys/ofed/drivers/net/mlx4/pd.c
+++ b/sys/ofed/drivers/net/mlx4/pd.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved.
- * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005, 2014 Mellanox Technologies. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -32,6 +32,7 @@
*/
#include <linux/errno.h>
+#include <linux/module.h>
#include <linux/io-mapping.h>
#include <asm/page.h>
@@ -57,7 +58,7 @@ EXPORT_SYMBOL_GPL(mlx4_pd_alloc);
void mlx4_pd_free(struct mlx4_dev *dev, u32 pdn)
{
- mlx4_bitmap_free(&mlx4_priv(dev)->pd_bitmap, pdn);
+ mlx4_bitmap_free(&mlx4_priv(dev)->pd_bitmap, pdn, MLX4_USE_RR);
}
EXPORT_SYMBOL_GPL(mlx4_pd_free);
@@ -94,7 +95,7 @@ EXPORT_SYMBOL_GPL(mlx4_xrcd_alloc);
void __mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn)
{
- mlx4_bitmap_free(&mlx4_priv(dev)->xrcd_bitmap, xrcdn);
+ mlx4_bitmap_free(&mlx4_priv(dev)->xrcd_bitmap, xrcdn, MLX4_USE_RR);
}
void mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn)
@@ -162,7 +163,7 @@ EXPORT_SYMBOL_GPL(mlx4_uar_alloc);
void mlx4_uar_free(struct mlx4_dev *dev, struct mlx4_uar *uar)
{
- mlx4_bitmap_free(&mlx4_priv(dev)->uar_table.bitmap, uar->index);
+ mlx4_bitmap_free(&mlx4_priv(dev)->uar_table.bitmap, uar->index, MLX4_USE_RR);
}
EXPORT_SYMBOL_GPL(mlx4_uar_free);
diff --git a/sys/ofed/drivers/net/mlx4/port.c b/sys/ofed/drivers/net/mlx4/port.c
index 2a009ea..c653d4b 100644
--- a/sys/ofed/drivers/net/mlx4/port.c
+++ b/sys/ofed/drivers/net/mlx4/port.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2007, 2014 Mellanox Technologies. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -32,10 +32,14 @@
#include <linux/errno.h>
#include <linux/if_ether.h>
+#include <linux/module.h>
+#include <linux/err.h>
#include <linux/mlx4/cmd.h>
#include <linux/moduleparam.h>
#include "mlx4.h"
+#include "mlx4_stats.h"
+
int mlx4_set_4k_mtu = -1;
module_param_named(set_4k_mtu, mlx4_set_4k_mtu, int, 0444);
@@ -48,12 +52,6 @@ MODULE_PARM_DESC(set_4k_mtu,
#define MLX4_VLAN_VALID (1u << 31)
#define MLX4_VLAN_MASK 0xfff
-#define MLX4_STATS_TRAFFIC_COUNTERS_MASK 0xfULL
-#define MLX4_STATS_TRAFFIC_DROPS_MASK 0xc0ULL
-#define MLX4_STATS_ERROR_COUNTERS_MASK 0x1ffc30ULL
-#define MLX4_STATS_PORT_COUNTERS_MASK 0x1fe00000ULL
-#define MLX4_STATS_IF_RX_ERRORS_COUNTERS_MASK 0x8010ULL
-
void mlx4_init_mac_table(struct mlx4_dev *dev, struct mlx4_mac_table *table)
{
int i;
@@ -85,7 +83,7 @@ static int validate_index(struct mlx4_dev *dev,
{
int err = 0;
- if (index < 0 || index >= table->max || !table->entries[index]) {
+ if (index < 0 || index >= table->max || !table->refs[index]) {
mlx4_warn(dev, "No valid Mac entry for the given index\n");
err = -EINVAL;
}
@@ -140,14 +138,15 @@ int __mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac)
mutex_lock(&table->mutex);
for (i = 0; i < MLX4_MAX_MAC_NUM; i++) {
- if (free < 0 && !table->entries[i]) {
+ if (free < 0 && !table->refs[i]) {
free = i;
continue;
}
- if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) {
+ if ((mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) &&
+ table->refs[i]) {
/* MAC already registered, Must not have duplicates */
- err = i;
+ err = i;
++table->refs[i];
goto out;
}
@@ -184,13 +183,24 @@ EXPORT_SYMBOL_GPL(__mlx4_register_mac);
int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac)
{
u64 out_param = 0;
- int err;
+ int err = -EINVAL;
if (mlx4_is_mfunc(dev)) {
- err = mlx4_cmd_imm(dev, mac, &out_param,
- ((u32) port) << 8 | (u32) RES_MAC,
- RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
+ if (!(dev->flags & MLX4_FLAG_OLD_REG_MAC)) {
+ err = mlx4_cmd_imm(dev, mac, &out_param,
+ ((u32) port) << 8 | (u32) RES_MAC,
+ RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES,
+ MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
+ }
+ if (err && err == -EINVAL && mlx4_is_slave(dev)) {
+ /* retry using old REG_MAC format */
+ set_param_l(&out_param, port);
+ err = mlx4_cmd_imm(dev, mac, &out_param, RES_MAC,
+ RES_OP_RESERVE_AND_MAP, MLX4_CMD_ALLOC_RES,
+ MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
+ if (!err)
+ dev->flags |= MLX4_FLAG_OLD_REG_MAC;
+ }
if (err)
return err;
@@ -245,10 +255,18 @@ void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac)
u64 out_param = 0;
if (mlx4_is_mfunc(dev)) {
- (void) mlx4_cmd_imm(dev, mac, &out_param,
- ((u32) port) << 8 | (u32) RES_MAC,
- RES_OP_RESERVE_AND_MAP, MLX4_CMD_FREE_RES,
- MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
+ if (!(dev->flags & MLX4_FLAG_OLD_REG_MAC)) {
+ (void) mlx4_cmd_imm(dev, mac, &out_param,
+ ((u32) port) << 8 | (u32) RES_MAC,
+ RES_OP_RESERVE_AND_MAP, MLX4_CMD_FREE_RES,
+ MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
+ } else {
+ /* use old unregister mac format */
+ set_param_l(&out_param, port);
+ (void) mlx4_cmd_imm(dev, mac, &out_param, RES_MAC,
+ RES_OP_RESERVE_AND_MAP, MLX4_CMD_FREE_RES,
+ MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
+ }
return;
}
__mlx4_unregister_mac(dev, port, mac);
@@ -535,17 +553,21 @@ static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod,
__be32 new_cap_mask;
port = in_mod & 0xff;
- in_modifier = in_mod >> 8;
+ in_modifier = (in_mod >> 8) & 0xff;
is_eth = op_mod;
port_info = &priv->port[port];
+ if (op_mod > 1)
+ return -EINVAL;
+
/* Slaves cannot perform SET_PORT operations except changing MTU */
if (is_eth) {
if (slave != dev->caps.function &&
in_modifier != MLX4_SET_PORT_GENERAL &&
in_modifier != MLX4_SET_PORT_GID_TABLE) {
- mlx4_warn(dev, "denying SET_PORT for slave:%d\n",
- slave);
+ mlx4_warn(dev, "denying SET_PORT for slave:%d,"
+ "port %d, config_select 0x%x\n",
+ slave, port, in_modifier);
return -EINVAL;
}
switch (in_modifier) {
@@ -570,7 +592,8 @@ static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod,
/* Mtu is configured as the max MTU among all the
* the functions on the port. */
mtu = be16_to_cpu(gen_context->mtu);
- mtu = min_t(int, mtu, dev->caps.eth_mtu_cap[port]);
+ mtu = min_t(int, mtu, dev->caps.eth_mtu_cap[port] +
+ ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN);
prev_mtu = slave_st->mtu[port];
slave_st->mtu[port] = mtu;
if (mtu > master->max_mtu[port])
@@ -650,7 +673,7 @@ static int mlx4_common_set_port(struct mlx4_dev *dev, int slave, u32 in_mod,
break;
}
- return mlx4_cmd(dev, inbox->dma, in_mod, op_mod,
+ return mlx4_cmd(dev, inbox->dma, in_mod & 0xffff, op_mod,
MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B,
MLX4_CMD_NATIVE);
}
@@ -727,19 +750,10 @@ enum {
MLX4_CHANGE_PORT_MTU_CAP = 22,
};
-#define CX3_PPF_DEV_ID 0x1003
-static int vl_cap_start(struct mlx4_dev *dev)
-{
- /* for non CX3 devices, start with 4 VLs to avoid errors in syslog */
- if (dev->pdev->device != CX3_PPF_DEV_ID)
- return 4;
- return 8;
-}
-
int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port, int pkey_tbl_sz)
{
struct mlx4_cmd_mailbox *mailbox;
- int err, vl_cap, pkey_tbl_flag = 0;
+ int err = -EINVAL, vl_cap, pkey_tbl_flag = 0;
u32 in_mod;
if (dev->caps.port_type[port] == MLX4_PORT_TYPE_NONE)
@@ -765,7 +779,8 @@ int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port, int pkey_tbl_sz)
}
/* IB VL CAP enum isn't used by the firmware, just numerical values */
- for (vl_cap = vl_cap_start(dev); vl_cap >= 1; vl_cap >>= 1) {
+ for (vl_cap = dev->caps.vl_cap[port];
+ vl_cap >= 1; vl_cap >>= 1) {
((__be32 *) mailbox->buf)[0] = cpu_to_be32(
(1 << MLX4_CHANGE_PORT_MTU_CAP) |
(1 << MLX4_CHANGE_PORT_VL_CAP) |
@@ -822,10 +837,9 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
u32 in_mod;
u32 m_promisc = (dev->caps.flags & MLX4_DEV_CAP_FLAG_VEP_MC_STEER) ?
MCAST_DIRECT : MCAST_DEFAULT;
-/*
+
if (dev->caps.steering_mode != MLX4_STEERING_MODE_A0)
return 0;
-*/
mailbox = mlx4_alloc_cmd_mailbox(dev);
if (IS_ERR(mailbox))
@@ -834,10 +848,7 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
memset(context, 0, sizeof *context);
context->base_qpn = cpu_to_be32(base_qpn);
- /*
- * This assignment breaks vlan support - I don't know why. Probablya an A0 issue - shahar Klein
- * context->n_mac = dev->caps.log_num_macs;
- */
+ context->n_mac = dev->caps.log_num_macs;
context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_SHIFT |
base_qpn);
context->mcast = cpu_to_be32(m_promisc << SET_PORT_MC_PROMISC_SHIFT |
@@ -960,40 +971,44 @@ int mlx4_SET_VLAN_FLTR_wrapper(struct mlx4_dev *dev, int slave,
return err;
}
-int mlx4_common_dump_eth_stats(struct mlx4_dev *dev, int slave,
- u32 in_mod, struct mlx4_cmd_mailbox *outbox)
-{
- return mlx4_cmd_box(dev, 0, outbox->dma, in_mod, 0,
- MLX4_CMD_DUMP_ETH_STATS, MLX4_CMD_TIME_CLASS_B,
- MLX4_CMD_NATIVE);
-}
-
int mlx4_DUMP_ETH_STATS_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_vhcr *vhcr,
struct mlx4_cmd_mailbox *inbox,
struct mlx4_cmd_mailbox *outbox,
struct mlx4_cmd_info *cmd)
{
- if (slave != dev->caps.function)
- return 0;
- return mlx4_common_dump_eth_stats(dev, slave,
- vhcr->in_modifier, outbox);
+ return 0;
}
-void mlx4_set_stats_bitmap(struct mlx4_dev *dev, u64 *stats_bitmap)
+void mlx4_set_stats_bitmap(struct mlx4_dev *dev, unsigned long *stats_bitmap)
{
- if (!mlx4_is_mfunc(dev)) {
- *stats_bitmap = 0;
- return;
+ int last_i = 0;
+
+ bitmap_zero(stats_bitmap, NUM_ALL_STATS);
+
+ if (mlx4_is_slave(dev)) {
+ last_i = dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_FLOWSTATS_EN ?
+ NUM_PKT_STATS + NUM_FLOW_STATS : NUM_PKT_STATS;
+ } else {
+ bitmap_set(stats_bitmap, last_i, NUM_PKT_STATS);
+ last_i = NUM_PKT_STATS;
+
+ if (dev->caps.flags2 &
+ MLX4_DEV_CAP_FLAG2_FLOWSTATS_EN) {
+ bitmap_set(stats_bitmap, last_i, NUM_FLOW_STATS);
+ last_i += NUM_FLOW_STATS;
+ }
}
- *stats_bitmap = (MLX4_STATS_TRAFFIC_COUNTERS_MASK |
- MLX4_STATS_TRAFFIC_DROPS_MASK |
- MLX4_STATS_PORT_COUNTERS_MASK |
- MLX4_STATS_IF_RX_ERRORS_COUNTERS_MASK);
+ if (mlx4_is_slave(dev))
+ bitmap_set(stats_bitmap, last_i, NUM_VF_STATS);
+ last_i += NUM_VF_STATS;
if (mlx4_is_master(dev))
- *stats_bitmap |= MLX4_STATS_ERROR_COUNTERS_MASK;
+ bitmap_set(stats_bitmap, last_i, NUM_VPORT_STATS);
+ last_i += NUM_VPORT_STATS;
+
+ bitmap_set(stats_bitmap, last_i, NUM_PORT_STATS);
}
EXPORT_SYMBOL(mlx4_set_stats_bitmap);
diff --git a/sys/ofed/drivers/net/mlx4/profile.c b/sys/ofed/drivers/net/mlx4/profile.c
index d3042f0..aa5f957 100644
--- a/sys/ofed/drivers/net/mlx4/profile.c
+++ b/sys/ofed/drivers/net/mlx4/profile.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
- * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005, 2014 Mellanox Technologies. All rights reserved.
* Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -76,7 +76,7 @@ u64 mlx4_make_profile(struct mlx4_dev *dev,
u64 size;
u64 start;
int type;
- u32 num;
+ u64 num;
int log_num;
};
@@ -112,7 +112,8 @@ u64 mlx4_make_profile(struct mlx4_dev *dev,
min_t(unsigned, dev_cap->max_eqs, MAX_MSIX);
profile[MLX4_RES_DMPT].num = request->num_mpt;
profile[MLX4_RES_CMPT].num = MLX4_NUM_CMPTS;
- profile[MLX4_RES_MTT].num = request->num_mtt * (1 << log_mtts_per_seg);
+ profile[MLX4_RES_MTT].num = ((u64)request->num_mtt_segs) *
+ (1 << log_mtts_per_seg);
profile[MLX4_RES_MCG].num = request->num_mcg;
for (i = 0; i < MLX4_RES_NUM; ++i) {
diff --git a/sys/ofed/drivers/net/mlx4/qp.c b/sys/ofed/drivers/net/mlx4/qp.c
index 2e2033d..fe8d3c2 100644
--- a/sys/ofed/drivers/net/mlx4/qp.c
+++ b/sys/ofed/drivers/net/mlx4/qp.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2004 Topspin Communications. All rights reserved.
* Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. All rights reserved.
- * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2005, 2006, 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
* Copyright (c) 2004 Voltaire, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -33,6 +33,10 @@
* SOFTWARE.
*/
+#include <linux/types.h>
+#include <linux/gfp.h>
+#include <linux/module.h>
+
#include <linux/mlx4/cmd.h>
#include <linux/mlx4/qp.h>
@@ -210,13 +214,18 @@ int mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
EXPORT_SYMBOL_GPL(mlx4_qp_modify);
int __mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align,
- int *base, u8 bf_qp)
+ int *base, u8 flags)
{
+ int bf_qp = !!(flags & (u8) MLX4_RESERVE_BF_QP);
+
struct mlx4_priv *priv = mlx4_priv(dev);
struct mlx4_qp_table *qp_table = &priv->qp_table;
+ /* Only IPoIB uses a large cnt. In this case, just allocate
+ * as usual, ignoring bf skipping, since IPoIB does not run over RoCE
+ */
if (cnt > MLX4_MAX_BF_QP_RANGE && bf_qp)
- return -ENOMEM;
+ bf_qp = 0;
*base = mlx4_bitmap_alloc_range(&qp_table->bitmap, cnt, align,
bf_qp ? MLX4_BF_QP_SKIP_MASK : 0);
@@ -227,14 +236,14 @@ int __mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align,
}
int mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align,
- int *base, u8 bf_qp)
+ int *base, u8 flags)
{
u64 in_param = 0;
u64 out_param;
int err;
if (mlx4_is_mfunc(dev)) {
- set_param_l(&in_param, (((!!bf_qp) << 31) | (u32)cnt));
+ set_param_l(&in_param, (((u32) flags) << 24) | (u32) cnt);
set_param_h(&in_param, align);
err = mlx4_cmd_imm(dev, in_param, &out_param,
RES_QP, RES_OP_RESERVE,
@@ -246,7 +255,7 @@ int mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align,
*base = get_param_l(&out_param);
return 0;
}
- return __mlx4_qp_reserve_range(dev, cnt, align, base, bf_qp);
+ return __mlx4_qp_reserve_range(dev, cnt, align, base, flags);
}
EXPORT_SYMBOL_GPL(mlx4_qp_reserve_range);
@@ -257,7 +266,7 @@ void __mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt)
if (mlx4_is_qp_reserved(dev, (u32) base_qpn))
return;
- mlx4_bitmap_free_range(&qp_table->bitmap, base_qpn, cnt);
+ mlx4_bitmap_free_range(&qp_table->bitmap, base_qpn, cnt, MLX4_USE_RR);
}
void mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt)
diff --git a/sys/ofed/drivers/net/mlx4/reset.c b/sys/ofed/drivers/net/mlx4/reset.c
index 43b1541..44ec1e1 100644
--- a/sys/ofed/drivers/net/mlx4/reset.c
+++ b/sys/ofed/drivers/net/mlx4/reset.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved.
- * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -77,7 +77,7 @@ int mlx4_reset(struct mlx4_dev *dev)
goto out;
}
- pcie_cap = pci_find_capability(dev->pdev, PCI_CAP_ID_EXP);
+ pcie_cap = pci_pcie_cap(dev->pdev);
for (i = 0; i < 64; ++i) {
if (i == 22 || i == 23)
@@ -119,8 +119,8 @@ int mlx4_reset(struct mlx4_dev *dev)
writel(MLX4_RESET_VALUE, reset + MLX4_RESET_OFFSET);
iounmap(reset);
- /* Docs say to wait one second before accessing device */
- msleep(2000);
+ /* wait half a second before accessing device */
+ msleep(500);
end = jiffies + MLX4_RESET_TIMEOUT_JIFFIES;
do {
@@ -138,11 +138,10 @@ int mlx4_reset(struct mlx4_dev *dev)
goto out;
}
-
/* Now restore the PCI headers */
if (pcie_cap) {
devctl = hca_header[(pcie_cap + PCI_EXP_DEVCTL) / 4];
- if (pci_write_config_word(dev->pdev, pcie_cap + PCI_EXP_DEVCTL,
+ if (pcie_capability_write_word(dev->pdev, PCI_EXP_DEVCTL,
devctl)) {
err = -ENODEV;
mlx4_err(dev, "Couldn't restore HCA PCI Express "
@@ -150,7 +149,7 @@ int mlx4_reset(struct mlx4_dev *dev)
goto out;
}
linkctl = hca_header[(pcie_cap + PCI_EXP_LNKCTL) / 4];
- if (pci_write_config_word(dev->pdev, pcie_cap + PCI_EXP_LNKCTL,
+ if (pcie_capability_write_word(dev->pdev, PCI_EXP_LNKCTL,
linkctl)) {
err = -ENODEV;
mlx4_err(dev, "Couldn't restore HCA PCI Express "
diff --git a/sys/ofed/drivers/net/mlx4/resource_tracker.c b/sys/ofed/drivers/net/mlx4/resource_tracker.c
index 65fc1dd..743c887 100644
--- a/sys/ofed/drivers/net/mlx4/resource_tracker.c
+++ b/sys/ofed/drivers/net/mlx4/resource_tracker.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
- * Copyright (c) 2005, 2006, 2007, 2008 Mellanox Technologies.
+ * Copyright (c) 2005, 2006, 2007, 2008, 2014 Mellanox Technologies.
* All rights reserved.
* Copyright (c) 2005, 2006, 2007 Cisco Systems, Inc. All rights reserved.
*
@@ -42,7 +42,7 @@
#include <linux/mlx4/cmd.h>
#include <linux/mlx4/qp.h>
#include <linux/if_ether.h>
-#include <linux/compat.h>
+#include <linux/etherdevice.h>
#include "mlx4.h"
#include "fw.h"
@@ -85,6 +85,7 @@ struct res_gid {
u8 gid[16];
enum mlx4_protocol prot;
enum mlx4_steer_type steer;
+ u64 reg_id;
};
enum res_qp_states {
@@ -109,6 +110,16 @@ struct res_qp {
struct list_head mcg_list;
spinlock_t mcg_spl;
int local_qpn;
+ atomic_t ref_count;
+ u32 qpc_flags;
+ /* saved qp params before VST enforcement in order to restore on VGT */
+ u8 sched_queue;
+ __be32 param3;
+ u8 vlan_control;
+ u8 fvl_rx;
+ u8 pri_path_fl;
+ u8 vlan_index;
+ u8 feup;
};
enum res_mtt_states {
@@ -207,6 +218,7 @@ enum res_fs_rule_states {
struct res_fs_rule {
struct res_common com;
+ int qpn;
};
static int mlx4_is_eth(struct mlx4_dev *dev, int port)
@@ -622,9 +634,33 @@ static void update_gid(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *inbox,
}
}
+static int check_counter_index_validity(struct mlx4_dev *dev, int slave, int port, int idx)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ struct counter_index *counter, *tmp_counter;
+
+ if (slave == 0) {
+ list_for_each_entry_safe(counter, tmp_counter,
+ &priv->counters_table.global_port_list[port - 1],
+ list) {
+ if (counter->index == idx)
+ return 0;
+ }
+ return -EINVAL;
+ } else {
+ list_for_each_entry_safe(counter, tmp_counter,
+ &priv->counters_table.vf_list[slave - 1][port - 1],
+ list) {
+ if (counter->index == idx)
+ return 0;
+ }
+ return -EINVAL;
+ }
+}
+
static int update_vport_qp_param(struct mlx4_dev *dev,
struct mlx4_cmd_mailbox *inbox,
- u8 slave)
+ u8 slave, u32 qpn)
{
struct mlx4_qp_context *qpc = inbox->buf + 8;
struct mlx4_vport_oper_state *vp_oper;
@@ -635,31 +671,63 @@ static int update_vport_qp_param(struct mlx4_dev *dev,
port = (qpc->pri_path.sched_queue & 0x40) ? 2 : 1;
priv = mlx4_priv(dev);
vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port];
+ qp_type = (be32_to_cpu(qpc->flags) >> 16) & 0xff;
- if (MLX4_VGT != vp_oper->state.default_vlan) {
- qp_type = (be32_to_cpu(qpc->flags) >> 16) & 0xff;
- if (MLX4_QP_ST_RC == qp_type)
+ if (dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH &&
+ qpc->pri_path.counter_index != MLX4_SINK_COUNTER_INDEX) {
+ if (check_counter_index_validity(dev, slave, port,
+ qpc->pri_path.counter_index))
return -EINVAL;
+ }
+
+ mlx4_dbg(dev, "%s: QP counter_index %d for slave %d port %d\n",
+ __func__, qpc->pri_path.counter_index, slave, port);
+
+ if ((dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_LB_SRC_CHK) &&
+ dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH &&
+ !mlx4_is_qp_reserved(dev, qpn) &&
+ qp_type == MLX4_QP_ST_MLX &&
+ qpc->pri_path.counter_index != 0xFF) {
+ /* disable multicast loopback to qp with same counter */
+ qpc->pri_path.fl |= MLX4_FL_ETH_SRC_CHECK_MC_LB;
+ qpc->pri_path.vlan_control |=
+ MLX4_VLAN_CTRL_ETH_SRC_CHECK_IF_COUNTER;
+ }
+
+ if (MLX4_VGT != vp_oper->state.default_vlan) {
+ /* the reserved QPs (special, proxy, tunnel)
+ * do not operate over vlans
+ */
+ if (mlx4_is_qp_reserved(dev, qpn))
+ return 0;
- qpc->srqn |= cpu_to_be32(1 << 25); /*set cqe vlan mask */
+ /* force strip vlan by clear vsd */
+ qpc->param3 &= ~cpu_to_be32(MLX4_STRIP_VLAN);
+ /* preserve IF_COUNTER flag */
+ qpc->pri_path.vlan_control &=
+ MLX4_VLAN_CTRL_ETH_SRC_CHECK_IF_COUNTER;
+ if (MLX4_QP_ST_RC != qp_type) {
+ if (0 != vp_oper->state.default_vlan) {
+ qpc->pri_path.vlan_control |=
+ MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED |
+ MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED |
+ MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED;
+ } else { /* priority tagged */
+ qpc->pri_path.vlan_control |=
+ MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED |
+ MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED;
+ }
+ }
+ qpc->pri_path.fvl_rx |= MLX4_FVL_RX_FORCE_ETH_VLAN;
qpc->pri_path.vlan_index = vp_oper->vlan_idx;
- qpc->pri_path.fl = 1 << 6; /* set cv bit*/
- qpc->pri_path.feup |= 1 << 3; /* set fvl bit */
+ qpc->pri_path.fl |= MLX4_FL_CV | MLX4_FL_ETH_HIDE_CQE_VLAN;
+ qpc->pri_path.feup |= MLX4_FEUP_FORCE_ETH_UP | MLX4_FVL_FORCE_ETH_VLAN;
qpc->pri_path.sched_queue &= 0xC7;
qpc->pri_path.sched_queue |= (vp_oper->state.default_qos) << 3;
- mlx4_dbg(dev, "qp %d port %d Q 0x%x set vlan to %d vidx %d feup %x fl %x\n",
- be32_to_cpu(qpc->local_qpn) & 0xffffff, port,
- (int)(qpc->pri_path.sched_queue), vp_oper->state.default_vlan,
- vp_oper->vlan_idx, (int)(qpc->pri_path.feup),
- (int)(qpc->pri_path.fl));
}
if (vp_oper->state.spoofchk) {
- qpc->pri_path.feup |= 1 << 5; /* set fsm bit */;
+ qpc->pri_path.feup |= MLX4_FSM_FORCE_ETH_SRC_MAC;
qpc->pri_path.grh_mylmc = (0x80 & qpc->pri_path.grh_mylmc) + vp_oper->mac_idx;
- mlx4_dbg(dev, "spoof qp %d port %d feup 0x%x, myLmc 0x%x mindx %d\n",
- be32_to_cpu(qpc->local_qpn) & 0xffffff, port,
- (int)qpc->pri_path.feup, (int)qpc->pri_path.grh_mylmc,
- vp_oper->mac_idx);
}
return 0;
}
@@ -669,7 +737,7 @@ static int mpt_mask(struct mlx4_dev *dev)
return dev->caps.num_mpts - 1;
}
-static void *find_res(struct mlx4_dev *dev, int res_id,
+static void *find_res(struct mlx4_dev *dev, u64 res_id,
enum mlx4_resource type)
{
struct mlx4_priv *priv = mlx4_priv(dev);
@@ -688,7 +756,7 @@ static int get_res(struct mlx4_dev *dev, int slave, u64 res_id,
spin_lock_irq(mlx4_tlock(dev));
r = find_res(dev, res_id, type);
if (!r) {
- err = -ENOENT;
+ err = -ENONET;
goto exit;
}
@@ -761,6 +829,7 @@ static struct res_common *alloc_qp_tr(int id)
ret->local_qpn = id;
INIT_LIST_HEAD(&ret->mcg_list);
spin_lock_init(&ret->mcg_spl);
+ atomic_set(&ret->ref_count, 0);
return &ret->com;
}
@@ -868,7 +937,7 @@ static struct res_common *alloc_xrcdn_tr(int id)
return &ret->com;
}
-static struct res_common *alloc_fs_rule_tr(u64 id)
+static struct res_common *alloc_fs_rule_tr(u64 id, int qpn)
{
struct res_fs_rule *ret;
@@ -878,7 +947,7 @@ static struct res_common *alloc_fs_rule_tr(u64 id)
ret->com.res_id = id;
ret->com.state = RES_FS_RULE_ALLOCATED;
-
+ ret->qpn = qpn;
return &ret->com;
}
@@ -916,7 +985,7 @@ static struct res_common *alloc_tr(u64 id, enum mlx4_resource type, int slave,
ret = alloc_xrcdn_tr(id);
break;
case RES_FS_RULE:
- ret = alloc_fs_rule_tr(id);
+ ret = alloc_fs_rule_tr(id, extra);
break;
default:
return NULL;
@@ -970,8 +1039,10 @@ static int add_res_range(struct mlx4_dev *dev, int slave, u64 base, int count,
return 0;
undo:
- for (--i; i >= base; --i)
+ for (--i; i >= 0; --i) {
rb_erase(&res_arr[i]->node, root);
+ list_del_init(&res_arr[i]->list);
+ }
spin_unlock_irq(mlx4_tlock(dev));
@@ -985,10 +1056,14 @@ undo:
static int remove_qp_ok(struct res_qp *res)
{
- if (res->com.state == RES_QP_BUSY)
+ if (res->com.state == RES_QP_BUSY || atomic_read(&res->ref_count) ||
+ !list_empty(&res->mcg_list)) {
+ pr_err("resource tracker: fail to remove qp, state %d, ref_count %d\n",
+ res->com.state, atomic_read(&res->ref_count));
return -EBUSY;
- else if (res->com.state != RES_QP_RESERVED)
+ } else if (res->com.state != RES_QP_RESERVED) {
return -EPERM;
+ }
return 0;
}
@@ -1166,7 +1241,7 @@ static int qp_res_start_move_to(struct mlx4_dev *dev, int slave, int qpn,
switch (state) {
case RES_QP_BUSY:
mlx4_dbg(dev, "%s: failed RES_QP, 0x%llx\n",
- __func__, (long long)r->com.res_id);
+ __func__, (unsigned long long)r->com.res_id);
err = -EBUSY;
break;
@@ -1174,7 +1249,7 @@ static int qp_res_start_move_to(struct mlx4_dev *dev, int slave, int qpn,
if (r->com.state == RES_QP_MAPPED && !alloc)
break;
- mlx4_dbg(dev, "failed RES_QP, 0x%llx\n", (long long)r->com.res_id);
+ mlx4_dbg(dev, "failed RES_QP, 0x%llx\n", (unsigned long long)r->com.res_id);
err = -EINVAL;
break;
@@ -1184,7 +1259,7 @@ static int qp_res_start_move_to(struct mlx4_dev *dev, int slave, int qpn,
break;
else {
mlx4_dbg(dev, "failed RES_QP, 0x%llx\n",
- (long long)r->com.res_id);
+ (unsigned long long)r->com.res_id);
err = -EINVAL;
}
@@ -1464,18 +1539,18 @@ static int qp_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
int align;
int base;
int qpn;
- u8 bf_qp;
+ u8 flags;
switch (op) {
case RES_OP_RESERVE:
count = get_param_l(&in_param) & 0xffffff;
- bf_qp = get_param_l(&in_param) >> 31;
+ flags = get_param_l(&in_param) >> 24;
align = get_param_h(&in_param);
err = mlx4_grant_resource(dev, slave, RES_QP, count, 0);
if (err)
return err;
- err = __mlx4_qp_reserve_range(dev, count, align, &base, bf_qp);
+ err = __mlx4_qp_reserve_range(dev, count, align, &base, flags);
if (err) {
mlx4_release_resource(dev, slave, RES_QP, count, 0);
return err;
@@ -1566,7 +1641,7 @@ static int mpt_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
if (err)
break;
- index = __mlx4_mr_reserve(dev);
+ index = __mlx4_mpt_reserve(dev);
if (index == -1) {
mlx4_release_resource(dev, slave, RES_MPT, 1, 0);
break;
@@ -1576,7 +1651,7 @@ static int mpt_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
err = add_res_range(dev, slave, id, 1, RES_MPT, index);
if (err) {
mlx4_release_resource(dev, slave, RES_MPT, 1, 0);
- __mlx4_mr_release(dev, index);
+ __mlx4_mpt_release(dev, index);
break;
}
set_param_l(out_param, index);
@@ -1589,7 +1664,7 @@ static int mpt_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
if (err)
return err;
- err = __mlx4_mr_alloc_icm(dev, mpt->key);
+ err = __mlx4_mpt_alloc_icm(dev, mpt->key);
if (err) {
res_abort_move(dev, slave, RES_MPT, id);
return err;
@@ -1867,11 +1942,16 @@ static void rem_slave_vlans(struct mlx4_dev *dev, int slave)
}
static int vlan_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
- u64 in_param, u64 *out_param, int port)
+ u64 in_param, u64 *out_param, int in_port)
{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ struct mlx4_slave_state *slave_state = priv->mfunc.master.slave_state;
int err = -EINVAL;
u16 vlan;
int vlan_index;
+ int port;
+
+ port = !in_port ? get_param_l(out_param) : in_port;
if (!port)
return err;
@@ -1879,6 +1959,12 @@ static int vlan_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
if (op != RES_OP_RESERVE_AND_MAP)
return err;
+ /* upstream kernels had NOP for reg/unreg vlan. Continue this. */
+ if (!in_port && port > 0 && port <= dev->caps.num_ports) {
+ slave_state[slave].old_vlan_api = true;
+ return 0;
+ }
+
vlan = (u16) in_param;
err = __mlx4_register_vlan(dev, port, vlan, &vlan_index);
@@ -1892,7 +1978,7 @@ static int vlan_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
}
static int counter_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
- u64 in_param, u64 *out_param)
+ u64 in_param, u64 *out_param, int port)
{
u32 index;
int err;
@@ -1900,23 +1986,9 @@ static int counter_alloc_res(struct mlx4_dev *dev, int slave, int op, int cmd,
if (op != RES_OP_RESERVE)
return -EINVAL;
- err = mlx4_grant_resource(dev, slave, RES_COUNTER, 1, 0);
- if (err)
- return err;
-
- err = __mlx4_counter_alloc(dev, &index);
- if (err) {
- mlx4_release_resource(dev, slave, RES_COUNTER, 1, 0);
- return err;
- }
-
- err = add_res_range(dev, slave, index, 1, RES_COUNTER, 0);
- if (err) {
- __mlx4_counter_free(dev, index);
- mlx4_release_resource(dev, slave, RES_COUNTER, 1, 0);
- } else {
+ err = __mlx4_counter_alloc(dev, slave, port, &index);
+ if (!err)
set_param_l(out_param, index);
- }
return err;
}
@@ -1992,7 +2064,8 @@ int mlx4_ALLOC_RES_wrapper(struct mlx4_dev *dev, int slave,
case RES_COUNTER:
err = counter_alloc_res(dev, slave, vhcr->op_modifier, alop,
- vhcr->in_param, &vhcr->out_param);
+ vhcr->in_param, &vhcr->out_param,
+ (vhcr->in_modifier >> 8) & 0xFF);
break;
case RES_XRCD:
@@ -2090,7 +2163,7 @@ static int mpt_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
if (err)
break;
mlx4_release_resource(dev, slave, RES_MPT, 1, 0);
- __mlx4_mr_release(dev, index);
+ __mlx4_mpt_release(dev, index);
break;
case RES_OP_MAP_ICM:
index = get_param_l(&in_param);
@@ -2100,7 +2173,7 @@ static int mpt_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
if (err)
return err;
- __mlx4_mr_free_icm(dev, mpt->key);
+ __mlx4_mpt_free_icm(dev, mpt->key);
res_end_move(dev, slave, RES_MPT, id);
return err;
break;
@@ -2185,10 +2258,14 @@ static int mac_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
static int vlan_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
u64 in_param, u64 *out_param, int port)
{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+ struct mlx4_slave_state *slave_state = priv->mfunc.master.slave_state;
int err = 0;
switch (op) {
case RES_OP_RESERVE_AND_MAP:
+ if (slave_state[slave].old_vlan_api == true)
+ return 0;
if (!port)
return -EINVAL;
vlan_del_from_slave(dev, slave, in_param, port);
@@ -2203,23 +2280,18 @@ static int vlan_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
}
static int counter_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
- u64 in_param, u64 *out_param)
+ u64 in_param, u64 *out_param, int port)
{
int index;
- int err;
if (op != RES_OP_RESERVE)
return -EINVAL;
index = get_param_l(&in_param);
- err = rem_res_range(dev, slave, index, 1, RES_COUNTER, 0);
- if (err)
- return err;
- __mlx4_counter_free(dev, index);
- mlx4_release_resource(dev, slave, RES_COUNTER, 1, 0);
+ __mlx4_counter_free(dev, slave, port, index);
- return err;
+ return 0;
}
static int xrcdn_free_res(struct mlx4_dev *dev, int slave, int op, int cmd,
@@ -2290,7 +2362,8 @@ int mlx4_FREE_RES_wrapper(struct mlx4_dev *dev, int slave,
case RES_COUNTER:
err = counter_free_res(dev, slave, vhcr->op_modifier, alop,
- vhcr->in_param, &vhcr->out_param);
+ vhcr->in_param, &vhcr->out_param,
+ (vhcr->in_modifier >> 8) & 0xFF);
break;
case RES_XRCD:
@@ -2319,6 +2392,26 @@ static int mr_get_mtt_size(struct mlx4_mpt_entry *mpt)
return be32_to_cpu(mpt->mtt_sz);
}
+static u32 mr_get_pd(struct mlx4_mpt_entry *mpt)
+{
+ return be32_to_cpu(mpt->pd_flags) & 0x00ffffff;
+}
+
+static int mr_is_fmr(struct mlx4_mpt_entry *mpt)
+{
+ return be32_to_cpu(mpt->pd_flags) & MLX4_MPT_PD_FLAG_FAST_REG;
+}
+
+static int mr_is_bind_enabled(struct mlx4_mpt_entry *mpt)
+{
+ return be32_to_cpu(mpt->flags) & MLX4_MPT_FLAG_BIND_ENABLE;
+}
+
+static int mr_is_region(struct mlx4_mpt_entry *mpt)
+{
+ return be32_to_cpu(mpt->flags) & MLX4_MPT_FLAG_REGION;
+}
+
static int qp_get_mtt_addr(struct mlx4_qp_context *qpc)
{
return be32_to_cpu(qpc->mtt_base_addr_l) & 0xfffffff8;
@@ -2338,7 +2431,8 @@ static int qp_get_mtt_size(struct mlx4_qp_context *qpc)
int log_rq_stride = qpc->rq_size_stride & 7;
int srq = (be32_to_cpu(qpc->srqn) >> 24) & 1;
int rss = (be32_to_cpu(qpc->flags) >> 13) & 1;
- int xrc = (be32_to_cpu(qpc->local_qpn) >> 23) & 1;
+ u32 ts = (be32_to_cpu(qpc->flags) >> 16) & 0xff;
+ int xrc = (ts == MLX4_QP_ST_XRC) ? 1 : 0;
int sq_size;
int rq_size;
int total_pages;
@@ -2379,12 +2473,43 @@ int mlx4_SW2HW_MPT_wrapper(struct mlx4_dev *dev, int slave,
int mtt_base = mr_get_mtt_addr(inbox->buf) / dev->caps.mtt_entry_sz;
int phys;
int id;
+ u32 pd;
+ int pd_slave;
id = index & mpt_mask(dev);
err = mr_res_start_move_to(dev, slave, id, RES_MPT_HW, &mpt);
if (err)
return err;
+ /* Currently disable memory windows since this feature isn't tested yet
+ * under virtualization.
+ */
+ if (!mr_is_region(inbox->buf)) {
+ err = -ENOSYS;
+ goto ex_abort;
+ }
+
+ /* Make sure that the PD bits related to the slave id are zeros. */
+ pd = mr_get_pd(inbox->buf);
+ pd_slave = (pd >> 17) & 0x7f;
+ if (pd_slave != 0 && pd_slave != slave) {
+ err = -EPERM;
+ goto ex_abort;
+ }
+
+ if (mr_is_fmr(inbox->buf)) {
+ /* FMR and Bind Enable are forbidden in slave devices. */
+ if (mr_is_bind_enabled(inbox->buf)) {
+ err = -EPERM;
+ goto ex_abort;
+ }
+ /* FMR and Memory Windows are also forbidden. */
+ if (!mr_is_region(inbox->buf)) {
+ err = -EPERM;
+ goto ex_abort;
+ }
+ }
+
phys = mr_phys_mpt(inbox->buf);
if (!phys) {
err = get_res(dev, slave, mtt_base, RES_MTT, &mtt);
@@ -2534,6 +2659,14 @@ int mlx4_RST2INIT_QP_wrapper(struct mlx4_dev *dev, int slave,
if (err)
return err;
qp->local_qpn = local_qpn;
+ qp->sched_queue = 0;
+ qp->param3 = 0;
+ qp->vlan_control = 0;
+ qp->fvl_rx = 0;
+ qp->pri_path_fl = 0;
+ qp->vlan_index = 0;
+ qp->feup = 0;
+ qp->qpc_flags = be32_to_cpu(qpc->flags);
err = get_res(dev, slave, mtt_base, RES_MTT, &mtt);
if (err)
@@ -2851,6 +2984,12 @@ int mlx4_GEN_EQE(struct mlx4_dev *dev, int slave, struct mlx4_eqe *eqe)
if (!priv->mfunc.master.slave_state)
return -EINVAL;
+ /* check for slave valid, slave not PF, and slave active */
+ if (slave < 0 || slave >= dev->num_slaves ||
+ slave == dev->caps.function ||
+ !priv->mfunc.master.slave_state[slave].active)
+ return 0;
+
event_eq = &priv->mfunc.master.slave_state[slave].event_eq[eqe->type];
/* Create the event only if the slave is registered */
@@ -3288,6 +3427,15 @@ int mlx4_INIT2RTR_QP_wrapper(struct mlx4_dev *dev, int slave,
{
int err;
struct mlx4_qp_context *qpc = inbox->buf + 8;
+ int qpn = vhcr->in_modifier & 0x7fffff;
+ struct res_qp *qp;
+ u8 orig_sched_queue;
+ __be32 orig_param3 = qpc->param3;
+ u8 orig_vlan_control = qpc->pri_path.vlan_control;
+ u8 orig_fvl_rx = qpc->pri_path.fvl_rx;
+ u8 orig_pri_path_fl = qpc->pri_path.fl;
+ u8 orig_vlan_index = qpc->pri_path.vlan_index;
+ u8 orig_feup = qpc->pri_path.feup;
err = verify_qp_parameters(dev, inbox, QP_TRANS_INIT2RTR, slave);
if (err)
@@ -3299,11 +3447,40 @@ int mlx4_INIT2RTR_QP_wrapper(struct mlx4_dev *dev, int slave,
update_pkey_index(dev, slave, inbox);
update_gid(dev, inbox, (u8)slave);
adjust_proxy_tun_qkey(dev, vhcr, qpc);
- err = update_vport_qp_param(dev, inbox, slave);
+ orig_sched_queue = qpc->pri_path.sched_queue;
+
+ err = get_res(dev, slave, qpn, RES_QP, &qp);
if (err)
return err;
+ if (qp->com.from_state != RES_QP_HW) {
+ err = -EBUSY;
+ goto out;
+ }
- return mlx4_GEN_QP_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
+ /* do not modify vport QP params for RSS QPs */
+ if (!(qp->qpc_flags & (1 << MLX4_RSS_QPC_FLAG_OFFSET))) {
+ err = update_vport_qp_param(dev, inbox, slave, qpn);
+ if (err)
+ goto out;
+ }
+
+ err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
+out:
+ /* if no error, save sched queue value passed in by VF. This is
+ * essentially the QOS value provided by the VF. This will be useful
+ * if we allow dynamic changes from VST back to VGT
+ */
+ if (!err) {
+ qp->sched_queue = orig_sched_queue;
+ qp->param3 = orig_param3;
+ qp->vlan_control = orig_vlan_control;
+ qp->fvl_rx = orig_fvl_rx;
+ qp->pri_path_fl = orig_pri_path_fl;
+ qp->vlan_index = orig_vlan_index;
+ qp->feup = orig_feup;
+ }
+ put_res(dev, slave, qpn, RES_QP);
+ return err;
}
int mlx4_RTR2RTS_QP_wrapper(struct mlx4_dev *dev, int slave,
@@ -3439,7 +3616,7 @@ static struct res_gid *find_gid(struct mlx4_dev *dev, int slave,
static int add_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp,
u8 *gid, enum mlx4_protocol prot,
- enum mlx4_steer_type steer)
+ enum mlx4_steer_type steer, u64 reg_id)
{
struct res_gid *res;
int err;
@@ -3456,6 +3633,7 @@ static int add_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp,
memcpy(res->gid, gid, 16);
res->prot = prot;
res->steer = steer;
+ res->reg_id = reg_id;
list_add_tail(&res->list, &rqp->mcg_list);
err = 0;
}
@@ -3466,7 +3644,7 @@ static int add_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp,
static int rem_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp,
u8 *gid, enum mlx4_protocol prot,
- enum mlx4_steer_type steer)
+ enum mlx4_steer_type steer, u64 *reg_id)
{
struct res_gid *res;
int err;
@@ -3476,6 +3654,7 @@ static int rem_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp,
if (!res || res->prot != prot || res->steer != steer)
err = -EINVAL;
else {
+ *reg_id = res->reg_id;
list_del(&res->list);
kfree(res);
err = 0;
@@ -3485,6 +3664,37 @@ static int rem_mcg_res(struct mlx4_dev *dev, int slave, struct res_qp *rqp,
return err;
}
+static int qp_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
+ int block_loopback, enum mlx4_protocol prot,
+ enum mlx4_steer_type type, u64 *reg_id)
+{
+ switch (dev->caps.steering_mode) {
+ case MLX4_STEERING_MODE_DEVICE_MANAGED:
+ return mlx4_trans_to_dmfs_attach(dev, qp, gid, gid[5],
+ block_loopback, prot,
+ reg_id);
+ case MLX4_STEERING_MODE_B0:
+ return mlx4_qp_attach_common(dev, qp, gid,
+ block_loopback, prot, type);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int qp_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
+ enum mlx4_protocol prot, enum mlx4_steer_type type,
+ u64 reg_id)
+{
+ switch (dev->caps.steering_mode) {
+ case MLX4_STEERING_MODE_DEVICE_MANAGED:
+ return mlx4_flow_detach(dev, reg_id);
+ case MLX4_STEERING_MODE_B0:
+ return mlx4_qp_detach_common(dev, qp, gid, prot, type);
+ default:
+ return -EINVAL;
+ }
+}
+
int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_vhcr *vhcr,
struct mlx4_cmd_mailbox *inbox,
@@ -3497,6 +3707,7 @@ int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
int err;
int qpn;
struct res_qp *rqp;
+ u64 reg_id = 0;
int attach = vhcr->op_modifier;
int block_loopback = vhcr->in_modifier >> 31;
u8 steer_type_mask = 2;
@@ -3509,30 +3720,32 @@ int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
qp.qpn = qpn;
if (attach) {
- err = add_mcg_res(dev, slave, rqp, gid, prot, type);
- if (err)
+ err = qp_attach(dev, &qp, gid, block_loopback, prot,
+ type, &reg_id);
+ if (err) {
+ pr_err("Fail to attach rule to qp 0x%x\n", qpn);
goto ex_put;
-
- err = mlx4_qp_attach_common(dev, &qp, gid,
- block_loopback, prot, type);
+ }
+ err = add_mcg_res(dev, slave, rqp, gid, prot, type, reg_id);
if (err)
- goto ex_rem;
+ goto ex_detach;
} else {
- err = rem_mcg_res(dev, slave, rqp, gid, prot, type);
+ err = rem_mcg_res(dev, slave, rqp, gid, prot, type, &reg_id);
if (err)
goto ex_put;
- err = mlx4_qp_detach_common(dev, &qp, gid, prot, type);
- }
+ err = qp_detach(dev, &qp, gid, prot, type, reg_id);
+ if (err)
+ pr_err("Fail to detach rule from qp 0x%x reg_id = 0x%llx\n",
+ qpn, (unsigned long long)reg_id);
+ }
put_res(dev, slave, qpn, RES_QP);
- return 0;
+ return err;
-ex_rem:
- /* ignore error return below, already in error */
- (void) rem_mcg_res(dev, slave, rqp, gid, prot, type);
+ex_detach:
+ qp_detach(dev, &qp, gid, prot, type, reg_id);
ex_put:
put_res(dev, slave, qpn, RES_QP);
-
return err;
}
@@ -3540,7 +3753,6 @@ ex_put:
* MAC validation for Flow Steering rules.
* VF can attach rules only with a mac address which is assigned to it.
*/
-
static int validate_eth_header_mac(int slave, struct _rule_hw *eth_header,
struct list_head *rlist)
{
@@ -3633,6 +3845,8 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
struct list_head *rlist = &tracker->slave_list[slave].res_list[RES_MAC];
int err;
+ int qpn;
+ struct res_qp *rqp;
struct mlx4_net_trans_rule_hw_ctrl *ctrl;
struct _rule_hw *rule_header;
int header_id;
@@ -3642,13 +3856,21 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
return -EOPNOTSUPP;
ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf;
+ qpn = be32_to_cpu(ctrl->qpn) & 0xffffff;
+ err = get_res(dev, slave, qpn, RES_QP, &rqp);
+ if (err) {
+ pr_err("Steering rule with qpn 0x%x rejected.\n", qpn);
+ return err;
+ }
rule_header = (struct _rule_hw *)(ctrl + 1);
header_id = map_hw_to_sw_id(be16_to_cpu(rule_header->id));
switch (header_id) {
case MLX4_NET_TRANS_RULE_ID_ETH:
- if (validate_eth_header_mac(slave, rule_header, rlist))
- return -EINVAL;
+ if (validate_eth_header_mac(slave, rule_header, rlist)) {
+ err = -EINVAL;
+ goto err_put;
+ }
break;
case MLX4_NET_TRANS_RULE_ID_IB:
break;
@@ -3656,14 +3878,17 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
case MLX4_NET_TRANS_RULE_ID_TCP:
case MLX4_NET_TRANS_RULE_ID_UDP:
pr_warn("Can't attach FS rule without L2 headers, adding L2 header.\n");
- if (add_eth_header(dev, slave, inbox, rlist, header_id))
- return -EINVAL;
+ if (add_eth_header(dev, slave, inbox, rlist, header_id)) {
+ err = -EINVAL;
+ goto err_put;
+ }
vhcr->in_modifier +=
sizeof(struct mlx4_net_trans_rule_hw_eth) >> 2;
break;
default:
pr_err("Corrupted mailbox.\n");
- return -EINVAL;
+ err = -EINVAL;
+ goto err_put;
}
err = mlx4_cmd_imm(dev, inbox->dma, &vhcr->out_param,
@@ -3671,16 +3896,20 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A,
MLX4_CMD_NATIVE);
if (err)
- return err;
+ goto err_put;
- err = add_res_range(dev, slave, vhcr->out_param, 1, RES_FS_RULE, 0);
+ err = add_res_range(dev, slave, vhcr->out_param, 1, RES_FS_RULE, qpn);
if (err) {
mlx4_err(dev, "Fail to add flow steering resources.\n ");
/* detach rule*/
mlx4_cmd(dev, vhcr->out_param, 0, 0,
- MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A,
+ MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A,
MLX4_CMD_NATIVE);
+ goto err_put;
}
+ atomic_inc(&rqp->ref_count);
+err_put:
+ put_res(dev, slave, qpn, RES_QP);
return err;
}
@@ -3691,20 +3920,38 @@ int mlx4_QP_FLOW_STEERING_DETACH_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_cmd_info *cmd)
{
int err;
+ struct res_qp *rqp;
+ struct res_fs_rule *rrule;
if (dev->caps.steering_mode !=
MLX4_STEERING_MODE_DEVICE_MANAGED)
return -EOPNOTSUPP;
- err = rem_res_range(dev, slave, vhcr->in_param, 1, RES_FS_RULE, 0);
- if (err) {
- mlx4_err(dev, "Fail to remove flow steering resources.\n ");
+ err = get_res(dev, slave, vhcr->in_param, RES_FS_RULE, &rrule);
+ if (err)
+ return err;
+ /* Release the rule form busy state before removal */
+ put_res(dev, slave, vhcr->in_param, RES_FS_RULE);
+ err = get_res(dev, slave, rrule->qpn, RES_QP, &rqp);
+ if (err)
return err;
- }
err = mlx4_cmd(dev, vhcr->in_param, 0, 0,
MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A,
MLX4_CMD_NATIVE);
+ if (!err) {
+ err = rem_res_range(dev, slave, vhcr->in_param, 1, RES_FS_RULE,
+ 0);
+ atomic_dec(&rqp->ref_count);
+
+ if (err) {
+ mlx4_err(dev, "Fail to remove flow steering resources.\n ");
+ goto out;
+ }
+ }
+
+out:
+ put_res(dev, slave, rrule->qpn, RES_QP);
return err;
}
@@ -3719,14 +3966,9 @@ int mlx4_QUERY_IF_STAT_wrapper(struct mlx4_dev *dev, int slave,
struct mlx4_cmd_info *cmd)
{
int err;
- int index = vhcr->in_modifier & 0xffff;
-
- err = get_res(dev, slave, index, RES_COUNTER, NULL);
- if (err)
- return err;
err = mlx4_DMA_wrapper(dev, slave, vhcr, inbox, outbox, cmd);
- put_res(dev, slave, index, RES_COUNTER);
+
return err;
}
@@ -3737,9 +3979,16 @@ static void detach_qp(struct mlx4_dev *dev, int slave, struct res_qp *rqp)
struct mlx4_qp qp; /* dummy for calling attach/detach */
list_for_each_entry_safe(rgid, tmp, &rqp->mcg_list, list) {
- qp.qpn = rqp->local_qpn;
- (void) mlx4_qp_detach_common(dev, &qp, rgid->gid, rgid->prot,
- rgid->steer);
+ switch (dev->caps.steering_mode) {
+ case MLX4_STEERING_MODE_DEVICE_MANAGED:
+ mlx4_flow_detach(dev, rgid->reg_id);
+ break;
+ case MLX4_STEERING_MODE_B0:
+ qp.qpn = rqp->local_qpn;
+ (void) mlx4_qp_detach_common(dev, &qp, rgid->gid,
+ rgid->prot, rgid->steer);
+ break;
+ }
list_del(&rgid->list);
kfree(rgid);
}
@@ -3766,7 +4015,7 @@ static int _move_all_busy(struct mlx4_dev *dev, int slave,
mlx4_dbg(dev,
"%s id 0x%llx is busy\n",
ResourceType(type),
- (long long)r->res_id);
+ (unsigned long long)r->res_id);
++busy;
} else {
r->from_state = r->state;
@@ -3834,6 +4083,11 @@ static void rem_slave_qps(struct mlx4_dev *dev, int slave)
&tracker->res_tree[RES_QP]);
list_del(&qp->com.list);
spin_unlock_irq(mlx4_tlock(dev));
+ if (!valid_reserved(dev, slave, qpn)) {
+ __mlx4_qp_release_range(dev, qpn, 1);
+ mlx4_release_resource(dev, slave,
+ RES_QP, 1, 0);
+ }
kfree(qp);
state = 0;
break;
@@ -3905,6 +4159,8 @@ static void rem_slave_srqs(struct mlx4_dev *dev, int slave)
&tracker->res_tree[RES_SRQ]);
list_del(&srq->com.list);
spin_unlock_irq(mlx4_tlock(dev));
+ mlx4_release_resource(dev, slave,
+ RES_SRQ, 1, 0);
kfree(srq);
state = 0;
break;
@@ -3971,6 +4227,8 @@ static void rem_slave_cqs(struct mlx4_dev *dev, int slave)
&tracker->res_tree[RES_CQ]);
list_del(&cq->com.list);
spin_unlock_irq(mlx4_tlock(dev));
+ mlx4_release_resource(dev, slave,
+ RES_CQ, 1, 0);
kfree(cq);
state = 0;
break;
@@ -4028,18 +4286,20 @@ static void rem_slave_mrs(struct mlx4_dev *dev, int slave)
while (state != 0) {
switch (state) {
case RES_MPT_RESERVED:
- __mlx4_mr_release(dev, mpt->key);
+ __mlx4_mpt_release(dev, mpt->key);
spin_lock_irq(mlx4_tlock(dev));
rb_erase(&mpt->com.node,
&tracker->res_tree[RES_MPT]);
list_del(&mpt->com.list);
spin_unlock_irq(mlx4_tlock(dev));
+ mlx4_release_resource(dev, slave,
+ RES_MPT, 1, 0);
kfree(mpt);
state = 0;
break;
case RES_MPT_MAPPED:
- __mlx4_mr_free_icm(dev, mpt->key);
+ __mlx4_mpt_free_icm(dev, mpt->key);
state = RES_MPT_RESERVED;
break;
@@ -4103,6 +4363,8 @@ static void rem_slave_mtts(struct mlx4_dev *dev, int slave)
&tracker->res_tree[RES_MTT]);
list_del(&mtt->com.list);
spin_unlock_irq(mlx4_tlock(dev));
+ mlx4_release_resource(dev, slave, RES_MTT,
+ 1 << mtt->order, 0);
kfree(mtt);
state = 0;
break;
@@ -4238,32 +4500,7 @@ static void rem_slave_eqs(struct mlx4_dev *dev, int slave)
static void rem_slave_counters(struct mlx4_dev *dev, int slave)
{
- struct mlx4_priv *priv = mlx4_priv(dev);
- struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
- struct list_head *counter_list =
- &tracker->slave_list[slave].res_list[RES_COUNTER];
- struct res_counter *counter;
- struct res_counter *tmp;
- int err;
- int index;
-
- err = move_all_busy(dev, slave, RES_COUNTER);
- if (err)
- mlx4_warn(dev, "rem_slave_counters: Could not move all counters to "
- "busy for slave %d\n", slave);
-
- spin_lock_irq(mlx4_tlock(dev));
- list_for_each_entry_safe(counter, tmp, counter_list, com.list) {
- if (counter->com.owner == slave) {
- index = counter->com.res_id;
- rb_erase(&counter->com.node,
- &tracker->res_tree[RES_COUNTER]);
- list_del(&counter->com.list);
- kfree(counter);
- __mlx4_counter_free(dev, index);
- }
- }
- spin_unlock_irq(mlx4_tlock(dev));
+ __mlx4_slave_counters_free(dev, slave);
}
static void rem_slave_xrcdns(struct mlx4_dev *dev, int slave)
@@ -4302,6 +4539,7 @@ void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave)
mutex_lock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex);
rem_slave_macs(dev, slave);
rem_slave_vlans(dev, slave);
+ rem_slave_fs_rule(dev, slave);
rem_slave_qps(dev, slave);
rem_slave_srqs(dev, slave);
rem_slave_cqs(dev, slave);
@@ -4310,6 +4548,139 @@ void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave)
rem_slave_mtts(dev, slave);
rem_slave_counters(dev, slave);
rem_slave_xrcdns(dev, slave);
- rem_slave_fs_rule(dev, slave);
mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex);
}
+
+void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work)
+{
+ struct mlx4_vf_immed_vlan_work *work =
+ container_of(_work, struct mlx4_vf_immed_vlan_work, work);
+ struct mlx4_cmd_mailbox *mailbox;
+ struct mlx4_update_qp_context *upd_context;
+ struct mlx4_dev *dev = &work->priv->dev;
+ struct mlx4_resource_tracker *tracker =
+ &work->priv->mfunc.master.res_tracker;
+ struct list_head *qp_list =
+ &tracker->slave_list[work->slave].res_list[RES_QP];
+ struct res_qp *qp;
+ struct res_qp *tmp;
+ u64 qp_path_mask_vlan_ctrl =
+ ((1ULL << MLX4_UPD_QP_PATH_MASK_ETH_TX_BLOCK_UNTAGGED) |
+ (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_TX_BLOCK_1P) |
+ (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_TX_BLOCK_TAGGED) |
+ (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_RX_BLOCK_UNTAGGED) |
+ (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_RX_BLOCK_1P) |
+ (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_RX_BLOCK_TAGGED));
+
+ u64 qp_path_mask = ((1ULL << MLX4_UPD_QP_PATH_MASK_VLAN_INDEX) |
+ (1ULL << MLX4_UPD_QP_PATH_MASK_FVL) |
+ (1ULL << MLX4_UPD_QP_PATH_MASK_CV) |
+ (1ULL << MLX4_UPD_QP_PATH_MASK_ETH_HIDE_CQE_VLAN) |
+ (1ULL << MLX4_UPD_QP_PATH_MASK_FEUP) |
+ (1ULL << MLX4_UPD_QP_PATH_MASK_FVL_RX) |
+ (1ULL << MLX4_UPD_QP_PATH_MASK_SCHED_QUEUE));
+
+ int err;
+ int port, errors = 0;
+ u8 vlan_control;
+
+ if (mlx4_is_slave(dev)) {
+ mlx4_warn(dev, "Trying to update-qp in slave %d\n",
+ work->slave);
+ goto out;
+ }
+
+ mailbox = mlx4_alloc_cmd_mailbox(dev);
+ if (IS_ERR(mailbox))
+ goto out;
+
+ if (!work->vlan_id)
+ vlan_control = MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED |
+ MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED;
+ else
+ vlan_control = MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED |
+ MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED |
+ MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED;
+
+ upd_context = mailbox->buf;
+ upd_context->qp_mask = cpu_to_be64(MLX4_UPD_QP_MASK_VSD);
+
+ spin_lock_irq(mlx4_tlock(dev));
+ list_for_each_entry_safe(qp, tmp, qp_list, com.list) {
+ spin_unlock_irq(mlx4_tlock(dev));
+ if (qp->com.owner == work->slave) {
+ if (qp->com.from_state != RES_QP_HW ||
+ !qp->sched_queue || /* no INIT2RTR trans yet */
+ mlx4_is_qp_reserved(dev, qp->local_qpn) ||
+ qp->qpc_flags & (1 << MLX4_RSS_QPC_FLAG_OFFSET)) {
+ spin_lock_irq(mlx4_tlock(dev));
+ continue;
+ }
+ port = (qp->sched_queue >> 6 & 1) + 1;
+ if (port != work->port) {
+ spin_lock_irq(mlx4_tlock(dev));
+ continue;
+ }
+ if (MLX4_QP_ST_RC == ((qp->qpc_flags >> 16) & 0xff))
+ upd_context->primary_addr_path_mask = cpu_to_be64(qp_path_mask);
+ else
+ upd_context->primary_addr_path_mask =
+ cpu_to_be64(qp_path_mask | qp_path_mask_vlan_ctrl);
+ if (work->vlan_id == MLX4_VGT) {
+ upd_context->qp_context.param3 = qp->param3;
+ upd_context->qp_context.pri_path.vlan_control = qp->vlan_control;
+ upd_context->qp_context.pri_path.fvl_rx = qp->fvl_rx;
+ upd_context->qp_context.pri_path.vlan_index = qp->vlan_index;
+ upd_context->qp_context.pri_path.fl = qp->pri_path_fl;
+ upd_context->qp_context.pri_path.feup = qp->feup;
+ upd_context->qp_context.pri_path.sched_queue =
+ qp->sched_queue;
+ } else {
+ upd_context->qp_context.param3 = qp->param3 & ~cpu_to_be32(MLX4_STRIP_VLAN);
+ upd_context->qp_context.pri_path.vlan_control = vlan_control;
+ upd_context->qp_context.pri_path.vlan_index = work->vlan_ix;
+ upd_context->qp_context.pri_path.fvl_rx =
+ qp->fvl_rx | MLX4_FVL_RX_FORCE_ETH_VLAN;
+ upd_context->qp_context.pri_path.fl =
+ qp->pri_path_fl | MLX4_FL_CV | MLX4_FL_ETH_HIDE_CQE_VLAN;
+ upd_context->qp_context.pri_path.feup =
+ qp->feup | MLX4_FEUP_FORCE_ETH_UP | MLX4_FVL_FORCE_ETH_VLAN;
+ upd_context->qp_context.pri_path.sched_queue =
+ qp->sched_queue & 0xC7;
+ upd_context->qp_context.pri_path.sched_queue |=
+ ((work->qos & 0x7) << 3);
+ }
+
+ err = mlx4_cmd(dev, mailbox->dma,
+ qp->local_qpn & 0xffffff,
+ 0, MLX4_CMD_UPDATE_QP,
+ MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE);
+ if (err) {
+ mlx4_info(dev, "UPDATE_QP failed for slave %d, "
+ "port %d, qpn %d (%d)\n",
+ work->slave, port, qp->local_qpn,
+ err);
+ errors++;
+ }
+ }
+ spin_lock_irq(mlx4_tlock(dev));
+ }
+ spin_unlock_irq(mlx4_tlock(dev));
+ mlx4_free_cmd_mailbox(dev, mailbox);
+
+ if (errors)
+ mlx4_err(dev, "%d UPDATE_QP failures for slave %d, port %d\n",
+ errors, work->slave, work->port);
+
+ /* unregister previous vlan_id if needed and we had no errors
+ * while updating the QPs
+ */
+ if (work->flags & MLX4_VF_IMMED_VLAN_FLAG_VLAN && !errors &&
+ NO_INDX != work->orig_vlan_ix)
+ __mlx4_unregister_vlan(&work->priv->dev, work->port,
+ work->orig_vlan_id);
+out:
+ kfree(work);
+ return;
+}
+
diff --git a/sys/ofed/drivers/net/mlx4/sense.c b/sys/ofed/drivers/net/mlx4/sense.c
index 5e1665e..3615e65 100644
--- a/sys/ofed/drivers/net/mlx4/sense.c
+++ b/sys/ofed/drivers/net/mlx4/sense.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2007, 2014 Mellanox Technologies. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -53,7 +53,7 @@ int mlx4_SENSE_PORT(struct mlx4_dev *dev, int port,
}
if (out_param > 2) {
- mlx4_err(dev, "Sense returned illegal value: 0x%llx\n", (long long)out_param);
+ mlx4_err(dev, "Sense returned illegal value: 0x%llx\n", (unsigned long long)out_param);
return -EINVAL;
}
@@ -108,9 +108,8 @@ static void mlx4_sense_port(struct work_struct *work)
sense_again:
mutex_unlock(&priv->port_mutex);
- if (sense->resched)
- queue_delayed_work(sense->sense_wq , &sense->sense_poll,
- round_jiffies(MLX4_SENSE_RANGE));
+ queue_delayed_work(mlx4_wq , &sense->sense_poll,
+ round_jiffies_relative(MLX4_SENSE_RANGE));
}
void mlx4_start_sense(struct mlx4_dev *dev)
@@ -121,40 +120,24 @@ void mlx4_start_sense(struct mlx4_dev *dev)
if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_DPDP))
return;
- sense->resched = 1;
- queue_delayed_work(sense->sense_wq , &sense->sense_poll,
- round_jiffies(MLX4_SENSE_RANGE));
+ queue_delayed_work(mlx4_wq , &sense->sense_poll,
+ round_jiffies_relative(MLX4_SENSE_RANGE));
}
void mlx4_stop_sense(struct mlx4_dev *dev)
{
- mlx4_priv(dev)->sense.resched = 0;
+ cancel_delayed_work_sync(&mlx4_priv(dev)->sense.sense_poll);
}
-void mlx4_sense_cleanup(struct mlx4_dev *dev)
-{
- mlx4_stop_sense(dev);
- cancel_delayed_work(&mlx4_priv(dev)->sense.sense_poll);
- destroy_workqueue(mlx4_priv(dev)->sense.sense_wq);
-}
-
-
-int mlx4_sense_init(struct mlx4_dev *dev)
+void mlx4_sense_init(struct mlx4_dev *dev)
{
struct mlx4_priv *priv = mlx4_priv(dev);
struct mlx4_sense *sense = &priv->sense;
int port;
-
sense->dev = dev;
- sense->sense_wq = create_singlethread_workqueue("mlx4_sense");
- if (!sense->sense_wq)
- return -ENOMEM;
-
for (port = 1; port <= dev->caps.num_ports; port++)
sense->do_sense_port[port] = 1;
INIT_DEFERRABLE_WORK(&sense->sense_poll, mlx4_sense_port);
-
- return 0;
}
diff --git a/sys/ofed/drivers/net/mlx4/srq.c b/sys/ofed/drivers/net/mlx4/srq.c
index c37f682..fcb6255 100644
--- a/sys/ofed/drivers/net/mlx4/srq.c
+++ b/sys/ofed/drivers/net/mlx4/srq.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved.
- * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2007, 2008, 2014 Mellanox Technologies. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -32,6 +32,8 @@
*/
#include <linux/mlx4/cmd.h>
+#include <linux/mlx4/srq.h>
+#include <linux/module.h>
#include <linux/gfp.h>
#include "mlx4.h"
@@ -113,7 +115,7 @@ err_put:
mlx4_table_put(dev, &srq_table->table, *srqn);
err_out:
- mlx4_bitmap_free(&srq_table->bitmap, *srqn);
+ mlx4_bitmap_free(&srq_table->bitmap, *srqn, MLX4_NO_RR);
return err;
}
@@ -141,7 +143,7 @@ void __mlx4_srq_free_icm(struct mlx4_dev *dev, int srqn)
mlx4_table_put(dev, &srq_table->cmpt_table, srqn);
mlx4_table_put(dev, &srq_table->table, srqn);
- mlx4_bitmap_free(&srq_table->bitmap, srqn);
+ mlx4_bitmap_free(&srq_table->bitmap, srqn, MLX4_NO_RR);
}
static void mlx4_srq_free_icm(struct mlx4_dev *dev, int srqn)
@@ -295,3 +297,18 @@ void mlx4_cleanup_srq_table(struct mlx4_dev *dev)
return;
mlx4_bitmap_cleanup(&mlx4_priv(dev)->srq_table.bitmap);
}
+
+struct mlx4_srq *mlx4_srq_lookup(struct mlx4_dev *dev, u32 srqn)
+{
+ struct mlx4_srq_table *srq_table = &mlx4_priv(dev)->srq_table;
+ struct mlx4_srq *srq;
+ unsigned long flags;
+
+ spin_lock_irqsave(&srq_table->lock, flags);
+ srq = radix_tree_lookup(&srq_table->tree,
+ srqn & (dev->caps.num_srqs - 1));
+ spin_unlock_irqrestore(&srq_table->lock, flags);
+
+ return srq;
+}
+EXPORT_SYMBOL_GPL(mlx4_srq_lookup);
diff --git a/sys/ofed/drivers/net/mlx4/sys_tune.c b/sys/ofed/drivers/net/mlx4/sys_tune.c
index 0675e90..87eb30e 100644
--- a/sys/ofed/drivers/net/mlx4/sys_tune.c
+++ b/sys/ofed/drivers/net/mlx4/sys_tune.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2010, 2014 Mellanox Technologies. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
@@ -39,8 +39,6 @@
#if defined(CONFIG_X86) && defined(CONFIG_APM_MODULE)
-
-
/* Each CPU is put into a group. In most cases, the group number is
* equal to the CPU number of one of the CPUs in the group. The
* exception is group NR_CPUS which is the default group. This is
diff --git a/sys/ofed/drivers/net/mlx4/utils.c b/sys/ofed/drivers/net/mlx4/utils.c
new file mode 100644
index 0000000..2444ec5
--- /dev/null
+++ b/sys/ofed/drivers/net/mlx4/utils.c
@@ -0,0 +1,189 @@
+/* $OpenBSD: if_trunk.c,v 1.30 2007/01/31 06:20:19 reyk Exp $ */
+
+/*
+ * Copyright (c) 2005, 2006 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2007 Andrew Thompson <thompsa@FreeBSD.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_inet.h"
+#include "opt_inet6.h"
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+#include <sys/module.h>
+#include <sys/priv.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/hash.h>
+#include <sys/lock.h>
+#include <sys/rmlock.h>
+#include <sys/taskqueue.h>
+#include <sys/eventhandler.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_clone.h>
+#include <net/if_arp.h>
+#include <net/if_dl.h>
+#include <net/if_llc.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <net/if_var.h>
+#include <net/bpf.h>
+
+#if defined(INET) || defined(INET6)
+#include <netinet/in.h>
+#endif
+#ifdef INET
+#include <netinet/in_systm.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip.h>
+#endif
+
+#ifdef INET6
+#include <netinet/ip6.h>
+#include <netinet6/in6_var.h>
+#include <netinet6/in6_ifattach.h>
+#endif
+
+#include <net/if_vlan_var.h>
+
+#include "utils.h"
+
+/* XXX this code should be factored out */
+/* XXX copied from if_lagg.c */
+
+static const void *
+mlx4_en_gethdr(struct mbuf *m, u_int off, u_int len, void *buf)
+{
+ if (m->m_pkthdr.len < (off + len)) {
+ return (NULL);
+ } else if (m->m_len < (off + len)) {
+ m_copydata(m, off, len, buf);
+ return (buf);
+ }
+ return (mtod(m, char *) + off);
+}
+
+uint32_t
+mlx4_en_hashmbuf(uint32_t flags, struct mbuf *m, uint32_t key)
+{
+ uint16_t etype;
+ uint32_t p = key;
+ int off;
+ struct ether_header *eh;
+ const struct ether_vlan_header *vlan;
+#ifdef INET
+ const struct ip *ip;
+ const uint32_t *ports;
+ int iphlen;
+#endif
+#ifdef INET6
+ const struct ip6_hdr *ip6;
+ uint32_t flow;
+#endif
+ union {
+#ifdef INET
+ struct ip ip;
+#endif
+#ifdef INET6
+ struct ip6_hdr ip6;
+#endif
+ struct ether_vlan_header vlan;
+ uint32_t port;
+ } buf;
+
+
+ off = sizeof(*eh);
+ if (m->m_len < off)
+ goto out;
+ eh = mtod(m, struct ether_header *);
+ etype = ntohs(eh->ether_type);
+ if (flags & MLX4_F_HASHL2) {
+ p = hash32_buf(&eh->ether_shost, ETHER_ADDR_LEN, p);
+ p = hash32_buf(&eh->ether_dhost, ETHER_ADDR_LEN, p);
+ }
+
+ /* Special handling for encapsulating VLAN frames */
+ if ((m->m_flags & M_VLANTAG) && (flags & MLX4_F_HASHL2)) {
+ p = hash32_buf(&m->m_pkthdr.ether_vtag,
+ sizeof(m->m_pkthdr.ether_vtag), p);
+ } else if (etype == ETHERTYPE_VLAN) {
+ vlan = mlx4_en_gethdr(m, off, sizeof(*vlan), &buf);
+ if (vlan == NULL)
+ goto out;
+
+ if (flags & MLX4_F_HASHL2)
+ p = hash32_buf(&vlan->evl_tag, sizeof(vlan->evl_tag), p);
+ etype = ntohs(vlan->evl_proto);
+ off += sizeof(*vlan) - sizeof(*eh);
+ }
+
+ switch (etype) {
+#ifdef INET
+ case ETHERTYPE_IP:
+ ip = mlx4_en_gethdr(m, off, sizeof(*ip), &buf);
+ if (ip == NULL)
+ goto out;
+
+ if (flags & MLX4_F_HASHL3) {
+ p = hash32_buf(&ip->ip_src, sizeof(struct in_addr), p);
+ p = hash32_buf(&ip->ip_dst, sizeof(struct in_addr), p);
+ }
+ if (!(flags & MLX4_F_HASHL4))
+ break;
+ switch (ip->ip_p) {
+ case IPPROTO_TCP:
+ case IPPROTO_UDP:
+ case IPPROTO_SCTP:
+ iphlen = ip->ip_hl << 2;
+ if (iphlen < sizeof(*ip))
+ break;
+ off += iphlen;
+ ports = mlx4_en_gethdr(m, off, sizeof(*ports), &buf);
+ if (ports == NULL)
+ break;
+ p = hash32_buf(ports, sizeof(*ports), p);
+ break;
+ }
+ break;
+#endif
+#ifdef INET6
+ case ETHERTYPE_IPV6:
+ if (!(flags & MLX4_F_HASHL3))
+ break;
+ ip6 = mlx4_en_gethdr(m, off, sizeof(*ip6), &buf);
+ if (ip6 == NULL)
+ goto out;
+
+ p = hash32_buf(&ip6->ip6_src, sizeof(struct in6_addr), p);
+ p = hash32_buf(&ip6->ip6_dst, sizeof(struct in6_addr), p);
+ flow = ip6->ip6_flow & IPV6_FLOWLABEL_MASK;
+ p = hash32_buf(&flow, sizeof(flow), p); /* IPv6 flow label */
+ break;
+#endif
+ }
+out:
+ return (p);
+}
diff --git a/sys/ofed/drivers/net/mlx4/utils.h b/sys/ofed/drivers/net/mlx4/utils.h
new file mode 100644
index 0000000..51a654c
--- /dev/null
+++ b/sys/ofed/drivers/net/mlx4/utils.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014 Mellanox Technologies Ltd. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _MLX4_UTILS_H_
+#define _MLX4_UTILS_H_
+
+/* Lagg flags */
+#define MLX4_F_HASHL2 0x00000001 /* hash layer 2 */
+#define MLX4_F_HASHL3 0x00000002 /* hash layer 3 */
+#define MLX4_F_HASHL4 0x00000004 /* hash layer 4 */
+#define MLX4_F_HASHMASK 0x00000007
+
+uint32_t mlx4_en_hashmbuf(uint32_t flags, struct mbuf *m, uint32_t key);
+
+#endif /* _MLX4_UTILS_H_ */
diff --git a/sys/ofed/include/linux/linux_compat.c b/sys/ofed/include/linux/linux_compat.c
index f670391..c2fb4d7 100644
--- a/sys/ofed/include/linux/linux_compat.c
+++ b/sys/ofed/include/linux/linux_compat.c
@@ -576,6 +576,14 @@ linux_file_stat(struct file *fp, struct stat *sb, struct ucred *active_cred,
return (EOPNOTSUPP);
}
+static int
+linux_file_fill_kinfo(struct file *fp, struct kinfo_file *kif,
+ struct filedesc *fdp)
+{
+
+ return (0);
+}
+
struct fileops linuxfileops = {
.fo_read = linux_file_read,
.fo_write = invfo_rdwr,
@@ -588,6 +596,7 @@ struct fileops linuxfileops = {
.fo_chmod = invfo_chmod,
.fo_chown = invfo_chown,
.fo_sendfile = invfo_sendfile,
+ .fo_fill_kinfo = linux_file_fill_kinfo,
};
/*
diff --git a/sys/ofed/include/linux/mlx4/cmd.h b/sys/ofed/include/linux/mlx4/cmd.h
index d83ee3a..e2d41bc 100644
--- a/sys/ofed/include/linux/mlx4/cmd.h
+++ b/sys/ofed/include/linux/mlx4/cmd.h
@@ -34,6 +34,7 @@
#define MLX4_CMD_H
#include <linux/dma-mapping.h>
+#include <linux/types.h>
enum {
/* initialization and general commands */
@@ -111,6 +112,7 @@ enum {
MLX4_CMD_INIT2INIT_QP = 0x2d,
MLX4_CMD_SUSPEND_QP = 0x32,
MLX4_CMD_UNSUSPEND_QP = 0x33,
+ MLX4_CMD_UPDATE_QP = 0x61,
/* special QP and management commands */
MLX4_CMD_CONF_SPECIAL_QP = 0x23,
MLX4_CMD_MAD_IFC = 0x24,
@@ -152,10 +154,6 @@ enum {
MLX4_CMD_QUERY_IF_STAT = 0X54,
MLX4_CMD_SET_IF_STAT = 0X55,
- /* set port opcode modifiers */
- MLX4_SET_PORT_PRIO2TC = 0x8,
- MLX4_SET_PORT_SCHEDULER = 0x9,
-
/* register/delete flow steering network rules */
MLX4_QP_FLOW_STEERING_ATTACH = 0x65,
MLX4_QP_FLOW_STEERING_DETACH = 0x66,
@@ -175,12 +173,14 @@ enum {
enum {
/* set port opcode modifiers */
- MLX4_SET_PORT_GENERAL = 0x0,
- MLX4_SET_PORT_RQP_CALC = 0x1,
- MLX4_SET_PORT_MAC_TABLE = 0x2,
- MLX4_SET_PORT_VLAN_TABLE = 0x3,
- MLX4_SET_PORT_PRIO_MAP = 0x4,
- MLX4_SET_PORT_GID_TABLE = 0x5,
+ MLX4_SET_PORT_GENERAL = 0x0,
+ MLX4_SET_PORT_RQP_CALC = 0x1,
+ MLX4_SET_PORT_MAC_TABLE = 0x2,
+ MLX4_SET_PORT_VLAN_TABLE = 0x3,
+ MLX4_SET_PORT_PRIO_MAP = 0x4,
+ MLX4_SET_PORT_GID_TABLE = 0x5,
+ MLX4_SET_PORT_PRIO2TC = 0x8,
+ MLX4_SET_PORT_SCHEDULER = 0x9
};
enum {
@@ -237,7 +237,21 @@ u32 mlx4_comm_get_version(void);
int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u8 *mac);
int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos);
int mlx4_set_vf_spoofchk(struct mlx4_dev *dev, int port, int vf, bool setting);
+int mlx4_set_vf_link_state(struct mlx4_dev *dev, int port, int vf, int link_state);
+int mlx4_get_vf_link_state(struct mlx4_dev *dev, int port, int vf);
+/*
+ * mlx4_get_slave_default_vlan -
+ * retrun true if VST ( default vlan)
+ * if VST will fill vlan & qos (if not NULL)
+ */
+bool mlx4_get_slave_default_vlan(struct mlx4_dev *dev, int port, int slave, u16 *vlan, u8 *qos);
+enum {
+ IFLA_VF_LINK_STATE_AUTO, /* link state of the uplink */
+ IFLA_VF_LINK_STATE_ENABLE, /* link always up */
+ IFLA_VF_LINK_STATE_DISABLE, /* link always down */
+ __IFLA_VF_LINK_STATE_MAX,
+};
#define MLX4_COMM_GET_IF_REV(cmd_chan_ver) (u8)((cmd_chan_ver) >> 8)
diff --git a/sys/ofed/include/linux/mlx4/cq.h b/sys/ofed/include/linux/mlx4/cq.h
index 0821669..ed6bec1 100644
--- a/sys/ofed/include/linux/mlx4/cq.h
+++ b/sys/ofed/include/linux/mlx4/cq.h
@@ -42,17 +42,31 @@ struct mlx4_cqe {
__be32 vlan_my_qpn;
__be32 immed_rss_invalid;
__be32 g_mlpath_rqpn;
- __be16 sl_vid;
- __be16 rlid;
- __be16 status;
- u8 ipv6_ext_mask;
- u8 badfcs_enc;
+ union {
+ struct {
+ union {
+ struct {
+ __be16 sl_vid;
+ __be16 rlid;
+ };
+ __be32 timestamp_16_47;
+ };
+ __be16 status;
+ u8 ipv6_ext_mask;
+ u8 badfcs_enc;
+ };
+ struct {
+ __be16 reserved1;
+ u8 smac[6];
+ };
+ };
__be32 byte_cnt;
__be16 wqe_index;
__be16 checksum;
- u8 reserved[3];
+ u8 reserved2[1];
+ __be16 timestamp_0_15;
u8 owner_sr_opcode;
-};
+} __packed;
struct mlx4_err_cqe {
__be32 my_qpn;
@@ -83,6 +97,7 @@ struct mlx4_ts_cqe {
enum {
MLX4_CQE_VLAN_PRESENT_MASK = 1 << 29,
MLX4_CQE_QPN_MASK = 0xffffff,
+ MLX4_CQE_VID_MASK = 0xfff,
};
enum {
diff --git a/sys/ofed/include/linux/mlx4/device.h b/sys/ofed/include/linux/mlx4/device.h
index 2828ef0..a1beedb 100644
--- a/sys/ofed/include/linux/mlx4/device.h
+++ b/sys/ofed/include/linux/mlx4/device.h
@@ -36,11 +36,12 @@
#include <linux/pci.h>
#include <linux/completion.h>
#include <linux/radix-tree.h>
-//#include <linux/cpu_rmap.h> /* XXX SK Probably not needed in freeBSD XXX */
-
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <linux/workqueue.h>
#include <asm/atomic.h>
-#include <linux/clocksource.h> /* XXX SK ported to freeBSD */
+#include <linux/clocksource.h>
#define MAX_MSIX_P_PORT 17
#define MAX_MSIX 64
@@ -61,9 +62,7 @@
#define MLX4_RATELIMIT_1G_UNITS 4 /* 1 Gbps */
#define MLX4_RATELIMIT_DEFAULT 0x00ff
-
-
-#define MLX4_LEAST_ATTACHED_VECTOR 0xffffffff
+#define CORE_CLOCK_MASK 0xffffffffffffULL
enum {
MLX4_FLAG_MSI_X = 1 << 0,
@@ -71,6 +70,8 @@ enum {
MLX4_FLAG_MASTER = 1 << 2,
MLX4_FLAG_SLAVE = 1 << 3,
MLX4_FLAG_SRIOV = 1 << 4,
+ MLX4_FLAG_DEV_NUM_STR = 1 << 5,
+ MLX4_FLAG_OLD_REG_MAC = 1 << 6,
};
enum {
@@ -91,7 +92,8 @@ enum {
#define MLX4_RESERVED_QKEY_MASK (0xFFFF0000)
enum {
- MLX4_BOARD_ID_LEN = 64
+ MLX4_BOARD_ID_LEN = 64,
+ MLX4_VSD_LEN = 208
};
enum {
@@ -159,13 +161,13 @@ enum {
MLX4_DEV_CAP_FLAG_UDP_RSS = 1LL << 40,
MLX4_DEV_CAP_FLAG_VEP_UC_STEER = 1LL << 41,
MLX4_DEV_CAP_FLAG_VEP_MC_STEER = 1LL << 42,
+ MLX4_DEV_CAP_FLAG_CROSS_CHANNEL = 1LL << 44,
MLX4_DEV_CAP_FLAG_COUNTERS = 1LL << 48,
MLX4_DEV_CAP_FLAG_COUNTERS_EXT = 1LL << 49,
MLX4_DEV_CAP_FLAG_SET_PORT_ETH_SCHED = 1LL << 53,
MLX4_DEV_CAP_FLAG_SENSE_SUPPORT = 1LL << 55,
MLX4_DEV_CAP_FLAG_FAST_DROP = 1LL << 57,
MLX4_DEV_CAP_FLAG_PORT_MNG_CHG_EV = 1LL << 59,
- MLX4_DEV_CAP_FLAG_ESWITCH_SUPPORT = 1LL << 60,
MLX4_DEV_CAP_FLAG_64B_EQE = 1LL << 61,
MLX4_DEV_CAP_FLAG_64B_CQE = 1LL << 62
};
@@ -174,7 +176,34 @@ enum {
MLX4_DEV_CAP_FLAG2_RSS = 1LL << 0,
MLX4_DEV_CAP_FLAG2_RSS_TOP = 1LL << 1,
MLX4_DEV_CAP_FLAG2_RSS_XOR = 1LL << 2,
- MLX4_DEV_CAP_FLAG2_FS_EN = 1LL << 3
+ MLX4_DEV_CAP_FLAG2_FS_EN = 1LL << 3,
+ MLX4_DEV_CAP_FLAG2_FSM = 1LL << 4,
+ MLX4_DEV_CAP_FLAG2_VLAN_CONTROL = 1LL << 5,
+ MLX4_DEV_CAP_FLAG2_UPDATE_QP = 1LL << 6,
+ MLX4_DEV_CAP_FLAG2_LB_SRC_CHK = 1LL << 7,
+ MLX4_DEV_CAP_FLAG2_DMFS_IPOIB = 1LL << 8,
+ MLX4_DEV_CAP_FLAG2_ETS_CFG = 1LL << 9,
+ MLX4_DEV_CAP_FLAG2_ETH_BACKPL_AN_REP = 1LL << 10,
+ MLX4_DEV_CAP_FLAG2_FLOWSTATS_EN = 1LL << 11,
+ MLX4_DEV_CAP_FLAG2_RECOVERABLE_ERROR_EVENT = 1LL << 12,
+ MLX4_DEV_CAP_FLAG2_TS = 1LL << 13,
+ MLX4_DEV_CAP_FLAG2_DRIVER_VERSION_TO_FW = 1LL << 14
+};
+
+/* bit enums for an 8-bit flags field indicating special use
+ * QPs which require special handling in qp_reserve_range.
+ * Currently, this only includes QPs used by the ETH interface,
+ * where we expect to use blueflame. These QPs must not have
+ * bits 6 and 7 set in their qp number.
+ *
+ * This enum may use only bits 0..7.
+ */
+enum {
+ MLX4_RESERVE_BF_QP = 1 << 7,
+};
+
+enum {
+ MLX4_DEV_CAP_CQ_FLAG_IO = 1 << 0
};
enum {
@@ -190,22 +219,11 @@ enum {
MLX4_FUNC_CAP_64B_EQE_CQE = 1L << 0
};
-/* bit enums for an 8-bit flags field indicating special use
- * QPs which require special handling in qp_reserve_range.
- * Currently, this only includes QPs used by the ETH interface,
- * where we expect to use blueflame. These QPs must not have
- * bits 6 and 7 set in their qp number.
- *
- * This enum may use only bits 0..7.
- */
-enum {
- MLX4_RESERVE_BF_QP = 1 << 7,
-};
-
#define MLX4_ATTR_EXTENDED_PORT_INFO cpu_to_be16(0xff90)
enum {
+ MLX4_BMME_FLAG_WIN_TYPE_2B = 1 << 1,
MLX4_BMME_FLAG_LOCAL_INV = 1 << 6,
MLX4_BMME_FLAG_REMOTE_INV = 1 << 7,
MLX4_BMME_FLAG_TYPE_2_WIN = 1 << 9,
@@ -238,6 +256,7 @@ enum mlx4_event {
MLX4_EVENT_TYPE_FATAL_WARNING = 0x1b,
MLX4_EVENT_TYPE_FLR_EVENT = 0x1c,
MLX4_EVENT_TYPE_PORT_MNG_CHG_EVENT = 0x1d,
+ MLX4_EVENT_TYPE_RECOVERABLE_ERROR_EVENT = 0x3e,
MLX4_EVENT_TYPE_NONE = 0xff,
};
@@ -247,6 +266,11 @@ enum {
};
enum {
+ MLX4_RECOVERABLE_ERROR_EVENT_SUBTYPE_BAD_CABLE = 1,
+ MLX4_RECOVERABLE_ERROR_EVENT_SUBTYPE_UNSUPPORTED_CABLE = 2,
+};
+
+enum {
MLX4_FATAL_WARNING_SUBTYPE_WARMING = 0,
};
@@ -274,7 +298,8 @@ enum {
MLX4_PERM_LOCAL_WRITE = 1 << 11,
MLX4_PERM_REMOTE_READ = 1 << 12,
MLX4_PERM_REMOTE_WRITE = 1 << 13,
- MLX4_PERM_ATOMIC = 1 << 14
+ MLX4_PERM_ATOMIC = 1 << 14,
+ MLX4_PERM_BIND_MW = 1 << 15,
};
enum {
@@ -335,7 +360,8 @@ enum mlx4_port_type {
MLX4_PORT_TYPE_NONE = 0,
MLX4_PORT_TYPE_IB = 1,
MLX4_PORT_TYPE_ETH = 2,
- MLX4_PORT_TYPE_AUTO = 3
+ MLX4_PORT_TYPE_AUTO = 3,
+ MLX4_PORT_TYPE_NA = 4
};
enum mlx4_special_vlan_idx {
@@ -435,7 +461,7 @@ struct mlx4_caps {
int comp_pool;
int num_mpts;
int max_fmr_maps;
- int num_mtts;
+ u64 num_mtts;
int fmr_reserved_mtts;
int reserved_mtts;
int reserved_mrws;
@@ -476,6 +502,7 @@ struct mlx4_caps {
u8 port_ib_mtu[MLX4_MAX_PORTS + 1];
u16 sqp_demux;
u32 sync_qp;
+ u32 cq_flags;
u32 eqe_size;
u32 cqe_size;
u8 eqe_factor;
@@ -485,6 +512,7 @@ struct mlx4_caps {
u16 hca_core_clock;
u32 max_basic_counters;
u32 max_extended_counters;
+ u8 def_counter_index[MLX4_MAX_PORTS + 1];
};
struct mlx4_buf_list {
@@ -548,6 +576,18 @@ struct mlx4_mr {
int enabled;
};
+enum mlx4_mw_type {
+ MLX4_MW_TYPE_1 = 1,
+ MLX4_MW_TYPE_2 = 2,
+};
+
+struct mlx4_mw {
+ u32 key;
+ u32 pd;
+ enum mlx4_mw_type type;
+ int enabled;
+};
+
struct mlx4_fmr {
struct mlx4_mr mr;
struct mlx4_mpt_entry *mpt;
@@ -641,7 +681,8 @@ struct mlx4_eth_av {
u8 hop_limit;
__be32 sl_tclass_flowlabel;
u8 dgid[16];
- u32 reserved4[2];
+ u8 s_mac[6];
+ u8 reserved4[2];
__be16 vlan;
u8 mac[6];
};
@@ -731,6 +772,8 @@ struct mlx4_dev {
struct radix_tree_root qp_table_tree;
u8 rev_id;
char board_id[MLX4_BOARD_ID_LEN];
+ u16 vsd_vendor_id;
+ char vsd[MLX4_VSD_LEN];
int num_vfs;
int numa_node;
int oper_log_mgm_entry_size;
@@ -738,6 +781,12 @@ struct mlx4_dev {
u64 regid_allmulti_array[MLX4_MAX_PORTS + 1];
};
+struct mlx4_clock_params {
+ u64 offset;
+ u8 bar;
+ u8 size;
+};
+
struct mlx4_eqe {
u8 reserved1;
u8 type;
@@ -807,6 +856,11 @@ struct mlx4_eqe {
} __packed tbl_change_info;
} params;
} __packed port_mgmt_change;
+ struct {
+ u8 reserved[3];
+ u8 port;
+ u32 reserved1[5];
+ } __packed bad_cable;
} event;
u8 slave_id;
u8 reserved3[2];
@@ -842,6 +896,8 @@ struct mlx4_init_port_param {
#define MLX4_INVALID_SLAVE_ID 0xFF
+#define MLX4_SINK_COUNTER_INDEX 0xff
+
void handle_port_mgmt_change_event(struct work_struct *work);
static inline int mlx4_master_func_num(struct mlx4_dev *dev)
@@ -915,8 +971,12 @@ u64 mlx4_mtt_addr(struct mlx4_dev *dev, struct mlx4_mtt *mtt);
int mlx4_mr_alloc(struct mlx4_dev *dev, u32 pd, u64 iova, u64 size, u32 access,
int npages, int page_shift, struct mlx4_mr *mr);
-void mlx4_mr_free(struct mlx4_dev *dev, struct mlx4_mr *mr);
+int mlx4_mr_free(struct mlx4_dev *dev, struct mlx4_mr *mr);
int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr);
+int mlx4_mw_alloc(struct mlx4_dev *dev, u32 pd, enum mlx4_mw_type type,
+ struct mlx4_mw *mw);
+void mlx4_mw_free(struct mlx4_dev *dev, struct mlx4_mw *mw);
+int mlx4_mw_enable(struct mlx4_dev *dev, struct mlx4_mw *mw);
int mlx4_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
int start_index, int npages, u64 *page_list);
int mlx4_buf_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
@@ -936,7 +996,7 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt,
void mlx4_cq_free(struct mlx4_dev *dev, struct mlx4_cq *cq);
int mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align,
- int *base, u8 bf_qp);
+ int *base, u8 flags);
void mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt);
int mlx4_qp_alloc(struct mlx4_dev *dev, int qpn, struct mlx4_qp *qp);
@@ -990,12 +1050,14 @@ static inline int map_hw_to_sw_id(u16 header_id)
}
return -EINVAL;
}
+
enum mlx4_net_trans_promisc_mode {
- MLX4_FS_REGULAR = 0,
- MLX4_FS_ALL_DEFAULT = 1,
- MLX4_FS_MC_DEFAULT = 3,
- MLX4_FS_UC_SNIFFER = 4,
- MLX4_FS_MC_SNIFFER = 5,
+ MLX4_FS_REGULAR = 1,
+ MLX4_FS_ALL_DEFAULT,
+ MLX4_FS_MC_DEFAULT,
+ MLX4_FS_UC_SNIFFER,
+ MLX4_FS_MC_SNIFFER,
+ MLX4_FS_MODE_NUM, /* should be last */
};
struct mlx4_spec_eth {
@@ -1024,7 +1086,7 @@ struct mlx4_spec_ipv4 {
};
struct mlx4_spec_ib {
- __be32 r_u_qpn;
+ __be32 l3_qpn;
__be32 qpn_msk;
u8 dst_gid[16];
u8 dst_gid_msk[16];
@@ -1057,6 +1119,87 @@ struct mlx4_net_trans_rule {
u32 qpn;
};
+struct mlx4_net_trans_rule_hw_ctrl {
+ __be16 prio;
+ u8 type;
+ u8 flags;
+ u8 rsvd1;
+ u8 funcid;
+ u8 vep;
+ u8 port;
+ __be32 qpn;
+ __be32 rsvd2;
+};
+
+struct mlx4_net_trans_rule_hw_ib {
+ u8 size;
+ u8 rsvd1;
+ __be16 id;
+ u32 rsvd2;
+ __be32 l3_qpn;
+ __be32 qpn_mask;
+ u8 dst_gid[16];
+ u8 dst_gid_msk[16];
+} __packed;
+
+struct mlx4_net_trans_rule_hw_eth {
+ u8 size;
+ u8 rsvd;
+ __be16 id;
+ u8 rsvd1[6];
+ u8 dst_mac[6];
+ u16 rsvd2;
+ u8 dst_mac_msk[6];
+ u16 rsvd3;
+ u8 src_mac[6];
+ u16 rsvd4;
+ u8 src_mac_msk[6];
+ u8 rsvd5;
+ u8 ether_type_enable;
+ __be16 ether_type;
+ __be16 vlan_tag_msk;
+ __be16 vlan_tag;
+} __packed;
+
+struct mlx4_net_trans_rule_hw_tcp_udp {
+ u8 size;
+ u8 rsvd;
+ __be16 id;
+ __be16 rsvd1[3];
+ __be16 dst_port;
+ __be16 rsvd2;
+ __be16 dst_port_msk;
+ __be16 rsvd3;
+ __be16 src_port;
+ __be16 rsvd4;
+ __be16 src_port_msk;
+} __packed;
+
+struct mlx4_net_trans_rule_hw_ipv4 {
+ u8 size;
+ u8 rsvd;
+ __be16 id;
+ __be32 rsvd1;
+ __be32 dst_ip;
+ __be32 dst_ip_msk;
+ __be32 src_ip;
+ __be32 src_ip_msk;
+} __packed;
+
+struct _rule_hw {
+ union {
+ struct {
+ u8 size;
+ u8 rsvd;
+ __be16 id;
+ };
+ struct mlx4_net_trans_rule_hw_eth eth;
+ struct mlx4_net_trans_rule_hw_ib ib;
+ struct mlx4_net_trans_rule_hw_ipv4 ipv4;
+ struct mlx4_net_trans_rule_hw_tcp_udp tcp_udp;
+ };
+};
+
int mlx4_flow_steer_promisc_add(struct mlx4_dev *dev, u8 port, u32 qpn,
enum mlx4_net_trans_promisc_mode mode);
int mlx4_flow_steer_promisc_remove(struct mlx4_dev *dev, u8 port,
@@ -1071,7 +1214,7 @@ int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac);
void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac);
int mlx4_get_base_qpn(struct mlx4_dev *dev, u8 port);
int __mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac);
-void mlx4_set_stats_bitmap(struct mlx4_dev *dev, u64 *stats_bitmap);
+void mlx4_set_stats_bitmap(struct mlx4_dev *dev, unsigned long *stats_bitmap);
int mlx4_SET_PORT_general(struct mlx4_dev *dev, u8 port, int mtu,
u8 pptx, u8 pfctx, u8 pprx, u8 pfcrx);
int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
@@ -1097,18 +1240,23 @@ int mlx4_query_diag_counters(struct mlx4_dev *mlx4_dev, int array_length,
u32 counter_out[]);
int mlx4_test_interrupts(struct mlx4_dev *dev);
-int mlx4_assign_eq(struct mlx4_dev *dev, char *name, int *vector);
+int mlx4_assign_eq(struct mlx4_dev *dev, char* name, int * vector);
void mlx4_release_eq(struct mlx4_dev *dev, int vec);
int mlx4_wol_read(struct mlx4_dev *dev, u64 *config, int port);
int mlx4_wol_write(struct mlx4_dev *dev, u64 config, int port);
-int mlx4_counter_alloc(struct mlx4_dev *dev, u32 *idx);
-void mlx4_counter_free(struct mlx4_dev *dev, u32 idx);
+int mlx4_counter_alloc(struct mlx4_dev *dev, u8 port, u32 *idx);
+void mlx4_counter_free(struct mlx4_dev *dev, u8 port, u32 idx);
int mlx4_flow_attach(struct mlx4_dev *dev,
struct mlx4_net_trans_rule *rule, u64 *reg_id);
int mlx4_flow_detach(struct mlx4_dev *dev, u64 reg_id);
+int map_sw_to_hw_steering_mode(struct mlx4_dev *dev,
+ enum mlx4_net_trans_promisc_mode flow_type);
+int map_sw_to_hw_steering_id(struct mlx4_dev *dev,
+ enum mlx4_net_trans_rule_id id);
+int hw_rule_sz(struct mlx4_dev *dev, enum mlx4_net_trans_rule_id id);
void mlx4_sync_pkey_table(struct mlx4_dev *dev, int slave, int port,
int i, int val);
@@ -1118,7 +1266,7 @@ int mlx4_get_parav_qkey(struct mlx4_dev *dev, u32 qpn, u32 *qkey);
int mlx4_is_slave_active(struct mlx4_dev *dev, int slave);
int mlx4_gen_pkey_eqe(struct mlx4_dev *dev, int slave, u8 port);
int mlx4_gen_guid_change_eqe(struct mlx4_dev *dev, int slave, u8 port);
-int mlx4_gen_slaves_port_mgt_ev(struct mlx4_dev *dev, u8 port, int attr);
+int mlx4_gen_slaves_port_mgt_ev(struct mlx4_dev *dev, u8 port, int attr, u16 lid, u8 sl);
int mlx4_gen_port_state_change_eqe(struct mlx4_dev *dev, int slave, u8 port, u8 port_subtype_change);
enum slave_port_state mlx4_get_slave_port_state(struct mlx4_dev *dev, int slave, u8 port);
int set_and_calc_slave_port_state(struct mlx4_dev *dev, int slave, u8 port, int event, enum slave_port_gen_event *gen_event);
@@ -1130,6 +1278,8 @@ int mlx4_get_roce_gid_from_slave(struct mlx4_dev *dev, int port, int slave_id, u
int mlx4_FLOW_STEERING_IB_UC_QP_RANGE(struct mlx4_dev *dev, u32 min_range_qpn, u32 max_range_qpn);
-cycle_t mlx4_read_clock(struct mlx4_dev *dev);
+int mlx4_read_clock(struct mlx4_dev *dev);
+int mlx4_get_internal_clock_params(struct mlx4_dev *dev,
+ struct mlx4_clock_params *params);
#endif /* MLX4_DEVICE_H */
diff --git a/sys/ofed/include/linux/mlx4/driver.h b/sys/ofed/include/linux/mlx4/driver.h
index 8235a97..2a7fd21 100644
--- a/sys/ofed/include/linux/mlx4/driver.h
+++ b/sys/ofed/include/linux/mlx4/driver.h
@@ -51,32 +51,72 @@ enum mlx4_dev_event {
MLX4_DEV_EVENT_SLAVE_SHUTDOWN,
};
-enum mlx4_query_reply {
- MLX4_QUERY_NOT_MINE = -1,
- MLX4_QUERY_MINE_NOPORT = 0
-};
-
-enum mlx4_mcast_prot {
- MLX4_MCAST_PROT_IB = 0,
- MLX4_MCAST_PROT_EN = 1,
-};
-
struct mlx4_interface {
void * (*add) (struct mlx4_dev *dev);
void (*remove)(struct mlx4_dev *dev, void *context);
void (*event) (struct mlx4_dev *dev, void *context,
enum mlx4_dev_event event, unsigned long param);
void * (*get_dev)(struct mlx4_dev *dev, void *context, u8 port);
-
- enum mlx4_query_reply (*query) (void *context, void *);
struct list_head list;
enum mlx4_protocol protocol;
};
+enum {
+ MLX4_MAX_DEVICES = 32,
+ MLX4_DEVS_TBL_SIZE = MLX4_MAX_DEVICES + 1,
+ MLX4_DBDF2VAL_STR_SIZE = 512,
+ MLX4_STR_NAME_SIZE = 64,
+ MLX4_MAX_BDF_VALS = 2,
+ MLX4_ENDOF_TBL = -1LL
+};
+
+struct mlx4_dbdf2val {
+ u64 dbdf;
+ int val[MLX4_MAX_BDF_VALS];
+};
+
+struct mlx4_range {
+ int min;
+ int max;
+};
+
+/*
+ * mlx4_dbdf2val_lst struct holds all the data needed to convert
+ * dbdf-to-value-list string into dbdf-to-value table.
+ * dbdf-to-value-list string is a comma separated list of dbdf-to-value strings.
+ * the format of dbdf-to-value string is: "[mmmm:]bb:dd.f-v1[;v2]"
+ * mmmm - Domain number (optional)
+ * bb - Bus number
+ * dd - device number
+ * f - Function number
+ * v1 - First value related to the domain-bus-device-function.
+ * v2 - Second value related to the domain-bus-device-function (optional).
+ * bb, dd - Two hexadecimal digits without preceding 0x.
+ * mmmm - Four hexadecimal digits without preceding 0x.
+ * f - One hexadecimal without preceding 0x.
+ * v1,v2 - Number with normal convention (e.g 100, 0xd3).
+ * dbdf-to-value-list string format:
+ * "[mmmm:]bb:dd.f-v1[;v2],[mmmm:]bb:dd.f-v1[;v2],..."
+ *
+ */
+struct mlx4_dbdf2val_lst {
+ char name[MLX4_STR_NAME_SIZE]; /* String name */
+ char str[MLX4_DBDF2VAL_STR_SIZE]; /* dbdf2val list str */
+ struct mlx4_dbdf2val tbl[MLX4_DEVS_TBL_SIZE];/* dbdf to value table */
+ int num_vals; /* # of vals per dbdf */
+ int def_val[MLX4_MAX_BDF_VALS]; /* Default values */
+ struct mlx4_range range; /* Valid values range */
+};
+
+int mlx4_fill_dbdf2val_tbl(struct mlx4_dbdf2val_lst *dbdf2val_lst);
+int mlx4_get_val(struct mlx4_dbdf2val *tbl, struct pci_dev *pdev, int idx,
+ int *val);
+
int mlx4_register_interface(struct mlx4_interface *intf);
void mlx4_unregister_interface(struct mlx4_interface *intf);
-void *mlx4_get_protocol_dev(struct mlx4_dev *dev, enum mlx4_protocol proto, int port);
+void *mlx4_get_protocol_dev(struct mlx4_dev *dev, enum mlx4_protocol proto,
+ int port);
#ifndef ETH_ALEN
#define ETH_ALEN 6
diff --git a/sys/ofed/include/linux/mlx4/qp.h b/sys/ofed/include/linux/mlx4/qp.h
index 2d45a9d..8ab9bb4 100644
--- a/sys/ofed/include/linux/mlx4/qp.h
+++ b/sys/ofed/include/linux/mlx4/qp.h
@@ -104,9 +104,9 @@ enum {
MLX4_QP_BIT_RWE = 1 << 14,
MLX4_QP_BIT_RAE = 1 << 13,
MLX4_QP_BIT_RIC = 1 << 4,
- MLX4_QP_BIT_COLL_SYNC_RQ = 1 << 2,
- MLX4_QP_BIT_COLL_SYNC_SQ = 1 << 1,
- MLX4_QP_BIT_COLL_MASTER = 1 << 0
+ MLX4_QP_BIT_COLL_SYNC_RQ = 1 << 2,
+ MLX4_QP_BIT_COLL_SYNC_SQ = 1 << 1,
+ MLX4_QP_BIT_COLL_MASTER = 1 << 0
};
enum {
@@ -138,7 +138,7 @@ struct mlx4_rss_context {
struct mlx4_qp_path {
u8 fl;
- u8 reserved1[1];
+ u8 vlan_control;
u8 disable_pkey_check;
u8 pkey_index;
u8 counter_index;
@@ -153,11 +153,35 @@ struct mlx4_qp_path {
u8 sched_queue;
u8 vlan_index;
u8 feup;
- u8 reserved3;
+ u8 fvl_rx;
u8 reserved4[2];
u8 dmac[6];
};
+enum { /* fl */
+ MLX4_FL_CV = 1 << 6,
+ MLX4_FL_ETH_HIDE_CQE_VLAN = 1 << 2,
+ MLX4_FL_ETH_SRC_CHECK_MC_LB = 1 << 1,
+ MLX4_FL_ETH_SRC_CHECK_UC_LB = 1 << 0,
+};
+enum { /* vlan_control */
+ MLX4_VLAN_CTRL_ETH_SRC_CHECK_IF_COUNTER = 1 << 7,
+ MLX4_VLAN_CTRL_ETH_TX_BLOCK_TAGGED = 1 << 6,
+ MLX4_VLAN_CTRL_ETH_RX_BLOCK_TAGGED = 1 << 2,
+ MLX4_VLAN_CTRL_ETH_RX_BLOCK_PRIO_TAGGED = 1 << 1,/* 802.1p priorty tag*/
+ MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED = 1 << 0
+};
+
+enum { /* feup */
+ MLX4_FEUP_FORCE_ETH_UP = 1 << 6, /* force Eth UP */
+ MLX4_FSM_FORCE_ETH_SRC_MAC = 1 << 5, /* force Source MAC */
+ MLX4_FVL_FORCE_ETH_VLAN = 1 << 3 /* force Eth vlan */
+};
+
+enum { /* fvl_rx */
+ MLX4_FVL_RX_FORCE_ETH_VLAN = 1 << 0 /* enforce Eth rx vlan */
+};
+
struct mlx4_qp_context {
__be32 flags;
__be32 pd;
@@ -197,6 +221,45 @@ struct mlx4_qp_context {
u32 reserved5[10];
};
+struct mlx4_update_qp_context {
+ __be64 qp_mask;
+ __be64 primary_addr_path_mask;
+ __be64 secondary_addr_path_mask;
+ u64 reserved1;
+ struct mlx4_qp_context qp_context;
+ u64 reserved2[58];
+};
+
+enum {
+ MLX4_UPD_QP_MASK_PM_STATE = 32,
+ MLX4_UPD_QP_MASK_VSD = 33,
+};
+
+enum {
+ MLX4_UPD_QP_PATH_MASK_PKEY_INDEX = 0 + 32,
+ MLX4_UPD_QP_PATH_MASK_FSM = 1 + 32,
+ MLX4_UPD_QP_PATH_MASK_MAC_INDEX = 2 + 32,
+ MLX4_UPD_QP_PATH_MASK_FVL = 3 + 32,
+ MLX4_UPD_QP_PATH_MASK_CV = 4 + 32,
+ MLX4_UPD_QP_PATH_MASK_VLAN_INDEX = 5 + 32,
+ MLX4_UPD_QP_PATH_MASK_ETH_HIDE_CQE_VLAN = 6 + 32,
+ MLX4_UPD_QP_PATH_MASK_ETH_TX_BLOCK_UNTAGGED = 7 + 32,
+ MLX4_UPD_QP_PATH_MASK_ETH_TX_BLOCK_1P = 8 + 32,
+ MLX4_UPD_QP_PATH_MASK_ETH_TX_BLOCK_TAGGED = 9 + 32,
+ MLX4_UPD_QP_PATH_MASK_ETH_RX_BLOCK_UNTAGGED = 10 + 32,
+ MLX4_UPD_QP_PATH_MASK_ETH_RX_BLOCK_1P = 11 + 32,
+ MLX4_UPD_QP_PATH_MASK_ETH_RX_BLOCK_TAGGED = 12 + 32,
+ MLX4_UPD_QP_PATH_MASK_FEUP = 13 + 32,
+ MLX4_UPD_QP_PATH_MASK_SCHED_QUEUE = 14 + 32,
+ MLX4_UPD_QP_PATH_MASK_IF_COUNTER_INDEX = 15 + 32,
+ MLX4_UPD_QP_PATH_MASK_FVL_RX = 16 + 32,
+};
+
+enum { /* param3 */
+ MLX4_STRIP_VLAN = 1 << 30
+};
+
+
/* Which firmware version adds support for NEC (NoErrorCompletion) bit */
#define MLX4_FW_VER_WQE_CTRL_NEC mlx4_fw_ver(2, 2, 232)
@@ -277,6 +340,11 @@ struct mlx4_wqe_lso_seg {
__be32 header[0];
};
+enum mlx4_wqe_bind_seg_flags2 {
+ MLX4_WQE_BIND_TYPE_2 = (1<<31),
+ MLX4_WQE_BIND_ZERO_BASED = (1<<30),
+};
+
struct mlx4_wqe_bind_seg {
__be32 flags1;
__be32 flags2;
@@ -289,9 +357,9 @@ struct mlx4_wqe_bind_seg {
enum {
MLX4_WQE_FMR_PERM_LOCAL_READ = 1 << 27,
MLX4_WQE_FMR_PERM_LOCAL_WRITE = 1 << 28,
- MLX4_WQE_FMR_PERM_REMOTE_READ = 1 << 29,
- MLX4_WQE_FMR_PERM_REMOTE_WRITE = 1 << 30,
- MLX4_WQE_FMR_PERM_ATOMIC = 1 << 31
+ MLX4_WQE_FMR_AND_BIND_PERM_REMOTE_READ = 1 << 29,
+ MLX4_WQE_FMR_AND_BIND_PERM_REMOTE_WRITE = 1 << 30,
+ MLX4_WQE_FMR_AND_BIND_PERM_ATOMIC = 1 << 31
};
struct mlx4_wqe_fmr_seg {
@@ -316,12 +384,10 @@ struct mlx4_wqe_fmr_ext_seg {
};
struct mlx4_wqe_local_inval_seg {
- __be32 flags;
- u32 reserved1;
+ u64 reserved1;
__be32 mem_key;
- u32 reserved2[2];
- __be32 guest_id;
- __be64 pa;
+ u32 reserved2;
+ u64 reserved3[2];
};
struct mlx4_wqe_raddr_seg {
diff --git a/sys/ofed/include/linux/mlx4/srq.h b/sys/ofed/include/linux/mlx4/srq.h
index 799a069..192e0f7 100644
--- a/sys/ofed/include/linux/mlx4/srq.h
+++ b/sys/ofed/include/linux/mlx4/srq.h
@@ -39,4 +39,6 @@ struct mlx4_wqe_srq_next_seg {
u32 reserved2[3];
};
+struct mlx4_srq *mlx4_srq_lookup(struct mlx4_dev *dev, u32 srqn);
+
#endif /* MLX4_SRQ_H */
diff --git a/sys/opencrypto/cryptodev.c b/sys/opencrypto/cryptodev.c
index 778a670..bf46138 100644
--- a/sys/opencrypto/cryptodev.c
+++ b/sys/opencrypto/cryptodev.c
@@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
#include <sys/module.h>
#include <sys/fcntl.h>
#include <sys/bus.h>
+#include <sys/user.h>
#include <opencrypto/cryptodev.h>
#include <opencrypto/xform.h>
@@ -286,6 +287,8 @@ static int cryptof_ioctl(struct file *, u_long, void *,
static int cryptof_stat(struct file *, struct stat *,
struct ucred *, struct thread *);
static int cryptof_close(struct file *, struct thread *);
+static int cryptof_fill_kinfo(struct file *, struct kinfo_file *,
+ struct filedesc *);
static struct fileops cryptofops = {
.fo_read = invfo_rdwr,
@@ -299,6 +302,7 @@ static struct fileops cryptofops = {
.fo_chmod = invfo_chmod,
.fo_chown = invfo_chown,
.fo_sendfile = invfo_sendfile,
+ .fo_fill_kinfo = cryptof_fill_kinfo,
};
static struct csession *csefind(struct fcrypt *, u_int);
@@ -958,6 +962,14 @@ cryptof_close(struct file *fp, struct thread *td)
return 0;
}
+static int
+cryptof_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
+{
+
+ kif->kf_type = KF_TYPE_CRYPTO;
+ return (0);
+}
+
static struct csession *
csefind(struct fcrypt *fcr, u_int ses)
{
diff --git a/sys/pc98/cbus/fdc.c b/sys/pc98/cbus/fdc.c
deleted file mode 100644
index fd65d72..0000000
--- a/sys/pc98/cbus/fdc.c
+++ /dev/null
@@ -1,2596 +0,0 @@
-/*-
- * Copyright (c) 1990 The Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Don Ahn.
- *
- * Libretto PCMCIA floppy support by David Horwitt (dhorwitt@ucsd.edu)
- * aided by the Linux floppy driver modifications from David Bateman
- * (dbateman@eng.uts.edu.au).
- *
- * Copyright (c) 1993, 1994 by
- * jc@irbs.UUCP (John Capo)
- * vak@zebub.msk.su (Serge Vakulenko)
- * ache@astral.msk.su (Andrew A. Chernov)
- *
- * Copyright (c) 1993, 1994, 1995 by
- * joerg_wunsch@uriah.sax.de (Joerg Wunsch)
- * dufault@hda.com (Peter Dufault)
- *
- * Copyright (c) 2001 Joerg Wunsch,
- * joerg_wunsch@uriah.heep.sax.de (Joerg Wunsch)
- *
- * 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 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.
- *
- * from: @(#)fd.c 7.4 (Berkeley) 5/25/91
- * $FreeBSD$
- */
-
-#include "opt_fdc.h"
-
-#include <sys/param.h>
-#include <sys/bio.h>
-#include <sys/bus.h>
-#include <sys/devicestat.h>
-#include <sys/disk.h>
-#include <sys/fcntl.h>
-#include <sys/fdcio.h>
-#include <sys/filio.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/module.h>
-#include <sys/mutex.h>
-#include <sys/priv.h>
-#include <sys/proc.h>
-#include <sys/rman.h>
-#include <sys/systm.h>
-
-#include <machine/bus.h>
-#include <machine/stdarg.h>
-
-#ifdef PC98
-#include <isa/isavar.h>
-#include <pc98/cbus/fdcreg.h>
-#include <pc98/cbus/fdcvar.h>
-#include <pc98/pc98/pc98_machdep.h>
-#else
-#include <isa/isavar.h>
-#include <isa/isareg.h>
-#include <dev/fdc/fdcreg.h>
-#include <dev/fdc/fdcvar.h>
-#include <isa/rtc.h>
-#endif
-
-#define FDBIO_FORMAT BIO_CMD2
-
-/* configuration flags for fdc */
-#define FDC_NO_FIFO (1 << 2) /* do not enable FIFO */
-
-/*
- * Stop retrying after this many DMA overruns. Since each retry takes
- * one revolution, with 300 rpm., 25 retries take approximately 5
- * seconds which the read attempt will block in case the DMA overrun
- * is persistent.
- */
-#define FDC_DMAOV_MAX 25
-
-/*
- * Timeout value for the PIO loops to wait until the FDC main status
- * register matches our expectations (request for master, direction
- * bit). This is supposed to be a number of microseconds, although
- * timing might actually not be very accurate.
- *
- * Timeouts of 100 msec are believed to be required for some broken
- * (old) hardware.
- */
-#define FDSTS_TIMEOUT 100000
-
-/*
- * Number of subdevices that can be used for different density types.
- */
-#ifdef PC98
-#define NUMDENS 12
-#else
-#define NUMDENS 16
-#endif
-
-#define FDBIO_RDSECTID BIO_CMD1
-
-/*
- * List of native drive densities. Order must match enum fd_drivetype
- * in <sys/fdcio.h>. Upon attaching the drive, each of the
- * programmable subdevices is initialized with the native density
- * definition.
- */
-#ifdef PC98
-static struct fd_type fd_native_types[] =
-{
-{ 0 }, /* FDT_NONE */
-{ 0 }, /* FDT_360K */
-{ 15,2,0xFF,0x1B,80,2400,0,2,0x54,1,0,FL_MFM }, /* FDT_12M */
-{ 0 }, /* FDT_720K */
-{ 18,2,0xFF,0x1B,80,2880,2,2,0x54,1,0,FL_MFM }, /* FDT_144M */
-{ 0 }, /* FDT_288M */
-};
-
-static struct fd_type fd_searchlist_12m[] = {
-{ 15,2,0xFF,0x1B,80,2400,0,2,0x54,1,0,FL_MFM }, /* 1.2M */
-#if 0
-{ 10,2,0xFF,0x10,82,1640,1,2,0x30,1,0,FL_MFM }, /* 820K */
-{ 10,2,0xFF,0x10,80,1600,1,2,0x30,1,0,FL_MFM }, /* 800K */
-#endif
-{ 9,2,0xFF,0x20,80,1440,1,2,0x50,1,0,FL_MFM }, /* 720K */
-{ 9,2,0xFF,0x20,40, 720,1,2,0x50,1,0,FL_MFM|FL_2STEP },/* 360K */
-{ 8,2,0xFF,0x2A,80,1280,1,2,0x50,1,0,FL_MFM }, /* 640K */
-{ 8,3,0xFF,0x35,77,1232,0,2,0x74,1,0,FL_MFM }, /* 1.23M 1024/sec */
-#if 0
-{ 8,3,0xFF,0x35,80,1280,0,2,0x74,1,0,FL_MFM }, /* 1.28M 1024/sec */
-#endif
-};
-static struct fd_type fd_searchlist_144m[] = {
-#if 0
-{ 21,2,0xFF,0x04,82,3444,2,2,0x0C,2,0,FL_MFM }, /* 1.72M in 3mode */
-{ 18,2,0xFF,0x1B,82,2952,2,2,0x54,1,0,FL_MFM }, /* 1.48M in 3mode */
-#endif
-{ 18,2,0xFF,0x1B,80,2880,2,2,0x54,1,0,FL_MFM }, /* 1.44M in 3mode */
-{ 15,2,0xFF,0x1B,80,2400,0,2,0x54,1,0,FL_MFM }, /* 1.2M */
-#if 0
-{ 10,2,0xFF,0x10,82,1640,1,2,0x30,1,0,FL_MFM }, /* 820K */
-{ 10,2,0xFF,0x10,80,1600,1,2,0x30,1,0,FL_MFM }, /* 800K */
-#endif
-{ 9,2,0xFF,0x20,80,1440,1,2,0x50,1,0,FL_MFM }, /* 720K */
-{ 9,2,0xFF,0x20,40, 720,1,2,0x50,1,0,FL_MFM|FL_2STEP },/* 360K */
-{ 8,2,0xFF,0x2A,80,1280,1,2,0x50,1,0,FL_MFM }, /* 640K */
-{ 8,3,0xFF,0x35,77,1232,0,2,0x74,1,0,FL_MFM }, /* 1.23M 1024/sec */
-#if 0
-{ 8,3,0xFF,0x35,80,1280,0,2,0x74,1,0,FL_MFM }, /* 1.28M 1024/sec */
-{ 9,3,0xFF,0x35,82,1476,0,2,0x47,1,0,FL_MFM }, /* 1.48M 1024/sec 9sec */
-{ 10,3,0xFF,0x1B,82,1640,2,2,0x54,1,0,FL_MFM }, /* 1.64M in 3mode - Reserve */
-#endif
-};
-#else /* PC98 */
-static struct fd_type fd_native_types[] =
-{
-{ 0 }, /* FDT_NONE */
-{ 9,2,0xFF,0x2A,40, 720,FDC_250KBPS,2,0x50,1,0,FL_MFM }, /* FDT_360K */
-{ 15,2,0xFF,0x1B,80,2400,FDC_500KBPS,2,0x54,1,0,FL_MFM }, /* FDT_12M */
-{ 9,2,0xFF,0x20,80,1440,FDC_250KBPS,2,0x50,1,0,FL_MFM }, /* FDT_720K */
-{ 18,2,0xFF,0x1B,80,2880,FDC_500KBPS,2,0x6C,1,0,FL_MFM }, /* FDT_144M */
-#if 0 /* we currently don't handle 2.88 MB */
-{ 36,2,0xFF,0x1B,80,5760,FDC_1MBPS, 2,0x4C,1,1,FL_MFM|FL_PERPND } /*FDT_288M*/
-#else
-{ 18,2,0xFF,0x1B,80,2880,FDC_500KBPS,2,0x6C,1,0,FL_MFM }, /* FDT_144M */
-#endif
-};
-
-/*
- * 360 KB 5.25" and 720 KB 3.5" drives don't have automatic density
- * selection, they just start out with their native density (or lose).
- * So 1.2 MB 5.25", 1.44 MB 3.5", and 2.88 MB 3.5" drives have their
- * respective lists of densities to search for.
- */
-static struct fd_type fd_searchlist_12m[] = {
-{ 15,2,0xFF,0x1B,80,2400,FDC_500KBPS,2,0x54,1,0,FL_MFM }, /* 1.2M */
-{ 9,2,0xFF,0x23,40, 720,FDC_300KBPS,2,0x50,1,0,FL_MFM|FL_2STEP }, /* 360K */
-{ 9,2,0xFF,0x20,80,1440,FDC_300KBPS,2,0x50,1,0,FL_MFM }, /* 720K */
-};
-
-static struct fd_type fd_searchlist_144m[] = {
-{ 18,2,0xFF,0x1B,80,2880,FDC_500KBPS,2,0x6C,1,0,FL_MFM }, /* 1.44M */
-{ 9,2,0xFF,0x20,80,1440,FDC_250KBPS,2,0x50,1,0,FL_MFM }, /* 720K */
-};
-
-/* We search for 1.44M first since this is the most common case. */
-static struct fd_type fd_searchlist_288m[] = {
-{ 18,2,0xFF,0x1B,80,2880,FDC_500KBPS,2,0x6C,1,0,FL_MFM }, /* 1.44M */
-#if 0
-{ 36,2,0xFF,0x1B,80,5760,FDC_1MBPS, 2,0x4C,1,1,FL_MFM|FL_PERPND } /* 2.88M */
-#endif
-{ 9,2,0xFF,0x20,80,1440,FDC_250KBPS,2,0x50,1,0,FL_MFM }, /* 720K */
-};
-#endif /* PC98 */
-
-#define MAX_SEC_SIZE (128 << 3)
-#define MAX_CYLINDER 85 /* some people really stress their drives
- * up to cyl 82 */
-#define MAX_HEAD 1
-
-devclass_t fdc_devclass;
-
-/*
- * Per drive structure (softc).
- */
-struct fd_data {
- struct fdc_data *fdc; /* pointer to controller structure */
- int fdsu; /* this units number on this controller */
- enum fd_drivetype type; /* drive type */
- struct fd_type *ft; /* pointer to current type descriptor */
- struct fd_type fts[NUMDENS]; /* type descriptors */
- int flags;
-#define FD_OPEN 0x01 /* it's open */
-#define FD_NONBLOCK 0x02 /* O_NONBLOCK set */
-#define FD_ACTIVE 0x04 /* it's active */
-#define FD_MOTOR 0x08 /* motor should be on */
-#define FD_MOTOR_WAIT 0x10 /* motor coming up */
-#define FD_UA 0x20 /* force unit attention */
- int skip;
- int hddrv;
-#define FD_NO_TRACK -2
- int track; /* where we think the head is */
- int options; /* user configurable options, see fdcio.h */
- struct callout_handle toffhandle;
- struct callout_handle tohandle;
- struct devstat *device_stats;
- struct cdev *masterdev;
- device_t dev;
- fdu_t fdu;
-#ifdef PC98
- int pc98_trans;
-#endif
-};
-
-struct fdc_ivars {
- int fdunit;
- int fdtype;
-};
-
-static devclass_t fd_devclass;
-
-/* configuration flags for fd */
-#define FD_TYPEMASK 0x0f /* drive type, matches enum
- * fd_drivetype; on i386 machines, if
- * given as 0, use RTC type for fd0
- * and fd1 */
-#define FD_DTYPE(flags) ((flags) & FD_TYPEMASK)
-#define FD_NO_CHLINE 0x10 /* drive does not support changeline
- * aka. unit attention */
-#define FD_NO_PROBE 0x20 /* don't probe drive (seek test), just
- * assume it is there */
-
-/*
- * Throughout this file the following conventions will be used:
- *
- * fd is a pointer to the fd_data struct for the drive in question
- * fdc is a pointer to the fdc_data struct for the controller
- * fdu is the floppy drive unit number
- * fdcu is the floppy controller unit number
- * fdsu is the floppy drive unit number on that controller. (sub-unit)
- */
-
-/*
- * Function declarations, same (chaotic) order as they appear in the
- * file. Re-ordering is too late now, it would only obfuscate the
- * diffs against old and offspring versions (like the PC98 one).
- *
- * Anyone adding functions here, please keep this sequence the same
- * as below -- makes locating a particular function in the body much
- * easier.
- */
-static u_int8_t fdsts_rd(fdc_p);
-static void fddata_wr(fdc_p, u_int8_t);
-static u_int8_t fddata_rd(fdc_p);
-static int fdc_err(struct fdc_data *, const char *);
-static int enable_fifo(fdc_p fdc);
-static int fd_sense_drive_status(fdc_p, int *);
-static int fd_sense_int(fdc_p, int *, int *);
-static int fd_read_status(fdc_p);
-static int fd_probe(device_t);
-static int fd_attach(device_t);
-static int fd_detach(device_t);
-static void set_motor(struct fdc_data *, int, int);
-# define TURNON 1
-# define TURNOFF 0
-static timeout_t fd_turnoff;
-static timeout_t fd_motor_on;
-static void fd_turnon(struct fd_data *);
-static void fdc_reset(fdc_p);
-static int fd_in(struct fdc_data *, int *);
-static int out_fdc(struct fdc_data *, int);
-static d_open_t fdopen;
-static d_close_t fdclose;
-static d_strategy_t fdstrategy;
-static void fdstart(struct fdc_data *);
-static timeout_t fd_iotimeout;
-static timeout_t fd_pseudointr;
-static driver_intr_t fdc_intr;
-static int fdcpio(fdc_p, long, caddr_t, u_int);
-static int fdautoselect(struct cdev *);
-static int fdstate(struct fdc_data *);
-static int retrier(struct fdc_data *);
-static void fdbiodone(struct bio *);
-static int fdmisccmd(struct cdev *, u_int, void *);
-static d_ioctl_t fdioctl;
-
-static int fifo_threshold = 8; /* XXX: should be accessible via sysctl */
-
-#ifdef FDC_DEBUG
-/* CAUTION: fd_debug causes huge amounts of logging output */
-static int volatile fd_debug = 0;
-#define TRACE0(arg) do { if (fd_debug) printf(arg); } while (0)
-#define TRACE1(arg1, arg2) do { if (fd_debug) printf(arg1, arg2); } while (0)
-#else /* FDC_DEBUG */
-#define TRACE0(arg) do { } while (0)
-#define TRACE1(arg1, arg2) do { } while (0)
-#endif /* FDC_DEBUG */
-
-/*
- * Bus space handling (access to low-level IO).
- */
-#ifndef PC98
-void
-fdout_wr(fdc_p fdc, u_int8_t v)
-{
- bus_space_write_1(fdc->portt, fdc->porth, FDOUT+fdc->port_off, v);
-}
-#endif
-
-static u_int8_t
-fdsts_rd(fdc_p fdc)
-{
- return bus_space_read_1(fdc->portt, fdc->porth, FDSTS+fdc->port_off);
-}
-
-static void
-fddata_wr(fdc_p fdc, u_int8_t v)
-{
- bus_space_write_1(fdc->portt, fdc->porth, FDDATA+fdc->port_off, v);
-}
-
-static u_int8_t
-fddata_rd(fdc_p fdc)
-{
- return bus_space_read_1(fdc->portt, fdc->porth, FDDATA+fdc->port_off);
-}
-
-#ifdef PC98
-static void
-fdctl_wr(fdc_p fdc, u_int8_t v)
-{
- bus_space_write_1(fdc->portt, fdc->porth, FDCTL, v);
-}
-#endif
-
-#ifndef PC98
-static u_int8_t
-fdin_rd(fdc_p fdc)
-{
- return bus_space_read_1(fdc->portt, fdc->porth, FDIN);
-}
-#endif /* PC98 */
-
-static struct cdevsw fd_cdevsw = {
- .d_version = D_VERSION,
- .d_open = fdopen,
- .d_close = fdclose,
- .d_read = physread,
- .d_write = physwrite,
- .d_ioctl = fdioctl,
- .d_strategy = fdstrategy,
- .d_name = "fd",
- .d_flags = D_DISK | D_NEEDGIANT,
-};
-
-/*
- * Auxiliary functions. Well, some only. Others are scattered
- * throughout the entire file.
- */
-static int
-fdc_err(struct fdc_data *fdc, const char *s)
-{
- fdc->fdc_errs++;
- if (s) {
- if (fdc->fdc_errs < FDC_ERRMAX)
- device_printf(fdc->fdc_dev, "%s", s);
- else if (fdc->fdc_errs == FDC_ERRMAX)
- device_printf(fdc->fdc_dev, "too many errors, not "
- "logging any more\n");
- }
-
- return FD_FAILED;
-}
-
-/*
- * fd_cmd: Send a command to the chip. Takes a varargs with this structure:
- * Unit number,
- * # of output bytes, output bytes as ints ...,
- * # of input bytes, input bytes as ints ...
- */
-int
-fd_cmd(struct fdc_data *fdc, int n_out, ...)
-{
- u_char cmd;
- int n_in;
- int n;
- va_list ap;
-
- va_start(ap, n_out);
- cmd = (u_char)(va_arg(ap, int));
- va_end(ap);
- va_start(ap, n_out);
- for (n = 0; n < n_out; n++)
- {
- if (out_fdc(fdc, va_arg(ap, int)) < 0)
- {
- char msg[50];
- snprintf(msg, sizeof(msg),
- "cmd %x failed at out byte %d of %d\n",
- cmd, n + 1, n_out);
- return fdc_err(fdc, msg);
- }
- }
- n_in = va_arg(ap, int);
- for (n = 0; n < n_in; n++)
- {
- int *ptr = va_arg(ap, int *);
- if (fd_in(fdc, ptr) < 0)
- {
- char msg[50];
- snprintf(msg, sizeof(msg),
- "cmd %02x failed at in byte %d of %d\n",
- cmd, n + 1, n_in);
- return fdc_err(fdc, msg);
- }
- }
-
- return 0;
-}
-
-static int
-enable_fifo(fdc_p fdc)
-{
- int i, j;
-
- if ((fdc->flags & FDC_HAS_FIFO) == 0) {
-
- /*
- * Cannot use fd_cmd the normal way here, since
- * this might be an invalid command. Thus we send the
- * first byte, and check for an early turn of data directon.
- */
-
- if (out_fdc(fdc, I8207X_CONFIG) < 0)
- return fdc_err(fdc, "Enable FIFO failed\n");
-
- /* If command is invalid, return */
- j = FDSTS_TIMEOUT;
- while ((i = fdsts_rd(fdc) & (NE7_DIO | NE7_RQM))
- != NE7_RQM && j-- > 0) {
- if (i == (NE7_DIO | NE7_RQM)) {
- fdc_reset(fdc);
- return FD_FAILED;
- }
- DELAY(1);
- }
- if (j<0 ||
- fd_cmd(fdc, 3,
- 0, (fifo_threshold - 1) & 0xf, 0, 0) < 0) {
- fdc_reset(fdc);
- return fdc_err(fdc, "Enable FIFO failed\n");
- }
- fdc->flags |= FDC_HAS_FIFO;
- return 0;
- }
- if (fd_cmd(fdc, 4,
- I8207X_CONFIG, 0, (fifo_threshold - 1) & 0xf, 0, 0) < 0)
- return fdc_err(fdc, "Re-enable FIFO failed\n");
- return 0;
-}
-
-static int
-fd_sense_drive_status(fdc_p fdc, int *st3p)
-{
- int st3;
-
- if (fd_cmd(fdc, 2, NE7CMD_SENSED, fdc->fdu, 1, &st3))
- {
- return fdc_err(fdc, "Sense Drive Status failed\n");
- }
- if (st3p)
- *st3p = st3;
-
- return 0;
-}
-
-static int
-fd_sense_int(fdc_p fdc, int *st0p, int *cylp)
-{
- int cyl, st0, ret;
-
- ret = fd_cmd(fdc, 1, NE7CMD_SENSEI, 1, &st0);
- if (ret) {
- (void)fdc_err(fdc,
- "sense intr err reading stat reg 0\n");
- return ret;
- }
-
- if (st0p)
- *st0p = st0;
-
- if ((st0 & NE7_ST0_IC) == NE7_ST0_IC_IV) {
- /*
- * There doesn't seem to have been an interrupt.
- */
- return FD_NOT_VALID;
- }
-
- if (fd_in(fdc, &cyl) < 0) {
- return fdc_err(fdc, "can't get cyl num\n");
- }
-
- if (cylp)
- *cylp = cyl;
-
- return 0;
-}
-
-
-static int
-fd_read_status(fdc_p fdc)
-{
- int i, ret;
-
- for (i = ret = 0; i < 7; i++) {
- /*
- * XXX types are poorly chosen. Only bytes can be read
- * from the hardware, but fdc->status[] wants u_ints and
- * fd_in() gives ints.
- */
- int status;
-
- ret = fd_in(fdc, &status);
- fdc->status[i] = status;
- if (ret != 0)
- break;
- }
-
- if (ret == 0)
- fdc->flags |= FDC_STAT_VALID;
- else
- fdc->flags &= ~FDC_STAT_VALID;
-
- return ret;
-}
-
-#ifdef PC98
-static int pc98_trans = 0; /* 0 : HD , 1 : DD , 2 : 1.44 */
-static int pc98_trans_prev = -1;
-
-static void set_density(fdc_p fdc)
-{
- /* always motor on */
- bus_space_write_1(fdc->sc_fdsiot, fdc->sc_fdsioh, 0,
- (pc98_trans != 1 ? FDP_FDDEXC : 0) | FDP_PORTEXC);
- DELAY(100);
- fdctl_wr(fdc, FDC_RST | FDC_DMAE);
- /* in the case of note W, always inhibit 100ms timer */
-}
-
-static int pc98_fd_check_ready(fdu_t fdu)
-{
- fd_p fd = devclass_get_softc(fd_devclass, fdu);
- struct fdc_data *fdc = fd->fdc;
- int retry = 0, status;
-
- while (retry++ < 30000) {
- set_motor(fdc, fd->fdsu, TURNON);
- out_fdc(fdc, NE7CMD_SENSED); /* Sense Drive Status */
- DELAY(100);
- out_fdc(fdc, fdu); /* Drive number */
- DELAY(100);
- if ((fd_in(fdc, &status) == 0) && (status & NE7_ST3_RD)) {
- fdctl_wr(fdc, FDC_DMAE | FDC_MTON);
- DELAY(10);
- return 0;
- }
- }
- return -1;
-}
-
-static void pc98_fd_check_type(struct fd_data *fd)
-{
- struct fdc_data *fdc;
-
- if (fd->type != FDT_NONE || fd->fdu < 0 || fd->fdu > 3)
- return;
-
- fdc = fd->fdc;
-
- /* Look up what the BIOS thinks we have. */
- if (!((PC98_SYSTEM_PARAMETER(0x55c) >> fd->fdu) & 0x01)) {
- fd->type = FDT_NONE;
- return;
- }
- if ((PC98_SYSTEM_PARAMETER(0x5ae) >> fd->fdu) & 0x01) {
- /* Check 3mode I/F */
- fd->pc98_trans = 0;
- bus_space_write_1(fdc->sc_fdemsiot, fdc->sc_fdemsioh, 0,
- (fd->fdu << 5) | 0x10);
- if (!(bus_space_read_1(fdc->sc_fdemsiot, fdc->sc_fdemsioh, 0) &
- 0x01)) {
- fd->type = FDT_144M;
- return;
- }
- device_printf(fd->dev,
- "Warning: can't control 3mode I/F, fallback to 2mode.\n");
- }
-
- fd->type = FDT_12M;
-}
-#endif /* PC98 */
-
-void
-fdc_release_resources(struct fdc_data *fdc)
-{
- device_t dev;
-
- dev = fdc->fdc_dev;
- if (fdc->fdc_intr) {
- bus_teardown_intr(dev, fdc->res_irq, fdc->fdc_intr);
- fdc->fdc_intr = NULL;
- }
- if (fdc->res_irq != 0) {
- bus_release_resource(dev, SYS_RES_IRQ, fdc->rid_irq,
- fdc->res_irq);
- fdc->res_irq = NULL;
- }
-#ifndef PC98
- if (fdc->res_ctl != 0) {
- bus_release_resource(dev, SYS_RES_IOPORT, fdc->rid_ctl,
- fdc->res_ctl);
- fdc->res_ctl = NULL;
- }
-#endif
-#ifdef PC98
- if (fdc->res_fdsio != 0) {
- bus_release_resource(dev, SYS_RES_IOPORT, 3, fdc->res_fdsio);
- fdc->res_fdsio = NULL;
- }
- if (fdc->res_fdemsio != 0) {
- bus_release_resource(dev, SYS_RES_IOPORT, 4, fdc->res_fdemsio);
- fdc->res_fdemsio = NULL;
- }
-#endif
- if (fdc->res_ioport != 0) {
- bus_release_resource(dev, SYS_RES_IOPORT, fdc->rid_ioport,
- fdc->res_ioport);
- fdc->res_ioport = NULL;
- }
- if (fdc->res_drq != 0) {
- bus_release_resource(dev, SYS_RES_DRQ, fdc->rid_drq,
- fdc->res_drq);
- fdc->res_drq = NULL;
- }
-}
-
-/*
- * Configuration/initialization stuff, per controller.
- */
-
-int
-fdc_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
-{
- struct fdc_ivars *ivars = device_get_ivars(child);
-
- switch (which) {
- case FDC_IVAR_FDUNIT:
- *result = ivars->fdunit;
- break;
- case FDC_IVAR_FDTYPE:
- *result = ivars->fdtype;
- break;
- default:
- return (ENOENT);
- }
- return (0);
-}
-
-int
-fdc_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
-{
- struct fdc_ivars *ivars = device_get_ivars(child);
-
- switch (which) {
- case FDC_IVAR_FDUNIT:
- ivars->fdunit = value;
- break;
- case FDC_IVAR_FDTYPE:
- ivars->fdtype = value;
- break;
- default:
- return (ENOENT);
- }
- return (0);
-}
-
-int
-fdc_initial_reset(struct fdc_data *fdc)
-{
-#ifdef PC98
- /* see if it can handle a command */
- if (fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(4, 240),
- NE7_SPEC_2(2, 0), 0))
- return (ENXIO);
-#else
- /* First, reset the floppy controller. */
- fdout_wr(fdc, 0);
- DELAY(100);
- fdout_wr(fdc, FDO_FRST);
-
- /* Then, see if it can handle a command. */
- if (fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(3, 240),
- NE7_SPEC_2(2, 0), 0))
- return (ENXIO);
-#endif
- return (0);
-}
-
-int
-fdc_detach(device_t dev)
-{
- struct fdc_data *fdc;
- int error;
-
- fdc = device_get_softc(dev);
-
- /* have our children detached first */
- if ((error = bus_generic_detach(dev)))
- return (error);
-
-#ifdef PC98
- /* reset controller, turn motor off */
- fdc_reset(fdc);
-#else
- /* reset controller, turn motor off */
- fdout_wr(fdc, 0);
-#endif
-
- fdc_release_resources(fdc);
- return (0);
-}
-
-/*
- * Add a child device to the fdc controller. It will then be probed etc.
- */
-device_t
-fdc_add_child(device_t dev, const char *name, int unit)
-{
- struct fdc_ivars *ivar;
- device_t child;
-
- ivar = malloc(sizeof *ivar, M_DEVBUF /* XXX */, M_NOWAIT | M_ZERO);
- if (ivar == NULL)
- return (NULL);
- child = device_add_child(dev, name, unit);
- if (child == NULL) {
- free(ivar, M_DEVBUF);
- return (NULL);
- }
- device_set_ivars(child, ivar);
- ivar->fdunit = unit;
- ivar->fdtype = FDT_NONE;
- if (resource_disabled(name, unit))
- device_disable(child);
- return (child);
-}
-
-int
-fdc_attach(device_t dev)
-{
- struct fdc_data *fdc;
- int error;
-
- fdc = device_get_softc(dev);
- fdc->fdc_dev = dev;
- error = bus_setup_intr(dev, fdc->res_irq,
- INTR_TYPE_BIO | INTR_ENTROPY, NULL, fdc_intr, fdc,
- &fdc->fdc_intr);
- if (error) {
- device_printf(dev, "cannot setup interrupt\n");
- return error;
- }
- fdc->fdcu = device_get_unit(dev);
- fdc->flags |= FDC_NEEDS_RESET;
-
- fdc->state = DEVIDLE;
-
-#ifdef PC98
- /* reset controller, turn motor off, clear fdout mirror reg */
- fdc_reset(fdc);
-#else
- /* reset controller, turn motor off, clear fdout mirror reg */
- fdout_wr(fdc, fdc->fdout = 0);
-#endif
- bioq_init(&fdc->head);
-
- return (0);
-}
-
-int
-fdc_hints_probe(device_t dev)
-{
- const char *name, *dname;
- int i, error, dunit;
-
- /*
- * Probe and attach any children. We should probably detect
- * devices from the BIOS unless overridden.
- */
- name = device_get_nameunit(dev);
- i = 0;
- while ((resource_find_match(&i, &dname, &dunit, "at", name)) == 0) {
- resource_int_value(dname, dunit, "drive", &dunit);
- fdc_add_child(dev, dname, dunit);
- }
-
- if ((error = bus_generic_attach(dev)) != 0)
- return (error);
- return (0);
-}
-
-int
-fdc_print_child(device_t me, device_t child)
-{
- int retval = 0, flags;
-
- retval += bus_print_child_header(me, child);
- retval += printf(" on %s drive %d", device_get_nameunit(me),
- fdc_get_fdunit(child));
- if ((flags = device_get_flags(me)) != 0)
- retval += printf(" flags %#x", flags);
- retval += printf("\n");
-
- return (retval);
-}
-
-/*
- * Configuration/initialization, per drive.
- */
-static int
-fd_probe(device_t dev)
-{
- int i;
-#ifndef PC98
- u_int st0, st3;
-#endif
- struct fd_data *fd;
- struct fdc_data *fdc;
- fdsu_t fdsu;
- int flags, type;
-
- fdsu = fdc_get_fdunit(dev);
- fd = device_get_softc(dev);
- fdc = device_get_softc(device_get_parent(dev));
- flags = device_get_flags(dev);
-
- fd->dev = dev;
- fd->fdc = fdc;
- fd->fdsu = fdsu;
- fd->fdu = device_get_unit(dev);
-
- /* Auto-probe if fdinfo is present, but always allow override. */
- type = FD_DTYPE(flags);
- if (type == FDT_NONE && (type = fdc_get_fdtype(dev)) != FDT_NONE) {
- fd->type = type;
- goto done;
- } else {
- /* make sure fdautoselect() will be called */
- fd->flags = FD_UA;
- fd->type = type;
- }
-
-#ifdef PC98
- pc98_fd_check_type(fd);
-#else
-/*
- * XXX I think using __i386__ is wrong here since we actually want to probe
- * for the machine type, not the CPU type (so non-PC arch's like the PC98 will
- * fail the probe).
- */
-#ifdef __i386__
- if (fd->type == FDT_NONE && (fd->fdu == 0 || fd->fdu == 1)) {
- /* Look up what the BIOS thinks we have. */
- if (fd->fdu == 0) {
- if ((fdc->flags & FDC_ISPCMCIA))
- /*
- * Somewhat special. No need to force the
- * user to set device flags, since the Y-E
- * Data PCMCIA floppy is always a 1.44 MB
- * device.
- */
- fd->type = FDT_144M;
- else
- fd->type = (rtcin(RTC_FDISKETTE) & 0xf0) >> 4;
- } else {
- fd->type = rtcin(RTC_FDISKETTE) & 0x0f;
- }
- if (fd->type == FDT_288M_1)
- fd->type = FDT_288M;
- }
-#endif /* __i386__ */
-#endif /* PC98 */
-
- /* is there a unit? */
- if (fd->type == FDT_NONE)
- return (ENXIO);
-
-#ifndef PC98
- /* select it */
- set_motor(fdc, fdsu, TURNON);
- fdc_reset(fdc); /* XXX reset, then unreset, etc. */
- DELAY(1000000); /* 1 sec */
-
- if ((flags & FD_NO_PROBE) == 0) {
- /* If we're at track 0 first seek inwards. */
- if ((fd_sense_drive_status(fdc, &st3) == 0) &&
- (st3 & NE7_ST3_T0)) {
- /* Seek some steps... */
- if (fd_cmd(fdc, 3, NE7CMD_SEEK, fdsu, 10, 0) == 0) {
- /* ...wait a moment... */
- DELAY(300000);
- /* make ctrlr happy: */
- fd_sense_int(fdc, 0, 0);
- }
- }
-
- for (i = 0; i < 2; i++) {
- /*
- * we must recalibrate twice, just in case the
- * heads have been beyond cylinder 76, since
- * most FDCs still barf when attempting to
- * recalibrate more than 77 steps
- */
- /* go back to 0: */
- if (fd_cmd(fdc, 2, NE7CMD_RECAL, fdsu, 0) == 0) {
- /* a second being enough for full stroke seek*/
- DELAY(i == 0 ? 1000000 : 300000);
-
- /* anything responding? */
- if (fd_sense_int(fdc, &st0, 0) == 0 &&
- (st0 & NE7_ST0_EC) == 0)
- break; /* already probed succesfully */
- }
- }
- }
-
- set_motor(fdc, fdsu, TURNOFF);
-
- if ((flags & FD_NO_PROBE) == 0 &&
- (st0 & NE7_ST0_EC) != 0) /* no track 0 -> no drive present */
- return (ENXIO);
-#endif /* PC98 */
-
-done:
-#ifndef PC98
- /* This doesn't work before the first reset. */
- if ((fdc->flags & FDC_HAS_FIFO) == 0 &&
- fdc->fdct == FDC_ENHANCED &&
- (device_get_flags(fdc->fdc_dev) & FDC_NO_FIFO) == 0 &&
- enable_fifo(fdc) == 0) {
- device_printf(device_get_parent(dev),
- "FIFO enabled, %d bytes threshold\n", fifo_threshold);
- }
-#endif /* PC98 */
-
-#ifdef PC98
- switch (fd->type) {
- case FDT_144M:
- device_set_desc(dev, "1.44M FDD");
- break;
- case FDT_12M:
- device_set_desc(dev, "1M/640K FDD");
- break;
- default:
- return (ENXIO);
- }
-#else
- switch (fd->type) {
- case FDT_12M:
- device_set_desc(dev, "1200-KB 5.25\" drive");
- break;
- case FDT_144M:
- device_set_desc(dev, "1440-KB 3.5\" drive");
- break;
- case FDT_288M:
- device_set_desc(dev, "2880-KB 3.5\" drive (in 1440-KB mode)");
- break;
- case FDT_360K:
- device_set_desc(dev, "360-KB 5.25\" drive");
- break;
- case FDT_720K:
- device_set_desc(dev, "720-KB 3.5\" drive");
- break;
- default:
- return (ENXIO);
- }
-#endif
- fd->track = FD_NO_TRACK;
- fd->fdc = fdc;
- fd->fdsu = fdsu;
- fd->options = 0;
-#ifdef PC98
- fd->pc98_trans = 0;
-#endif
- callout_handle_init(&fd->toffhandle);
- callout_handle_init(&fd->tohandle);
-
- /* initialize densities for subdevices */
-#ifdef PC98
- for (i = 0; i < NUMDENS; i++)
- memcpy(fd->fts + i, fd_searchlist_144m + i,
- sizeof(struct fd_type));
-#else
- for (i = 0; i < NUMDENS; i++)
- memcpy(fd->fts + i, fd_native_types + fd->type,
- sizeof(struct fd_type));
-#endif
- return (0);
-}
-
-static int
-fd_attach(device_t dev)
-{
- struct fd_data *fd;
-
- fd = device_get_softc(dev);
- fd->masterdev = make_dev(&fd_cdevsw, fd->fdu,
- UID_ROOT, GID_OPERATOR, 0640, "fd%d", fd->fdu);
- fd->masterdev->si_drv1 = fd;
- fd->device_stats = devstat_new_entry(device_get_name(dev),
- device_get_unit(dev), 0, DEVSTAT_NO_ORDERED_TAGS,
- DEVSTAT_TYPE_FLOPPY | DEVSTAT_TYPE_IF_OTHER,
- DEVSTAT_PRIORITY_FD);
- return (0);
-}
-
-static int
-fd_detach(device_t dev)
-{
- struct fd_data *fd;
-
- fd = device_get_softc(dev);
- untimeout(fd_turnoff, fd, fd->toffhandle);
- devstat_remove_entry(fd->device_stats);
- destroy_dev(fd->masterdev);
-
- return (0);
-}
-
-static device_method_t fd_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, fd_probe),
- DEVMETHOD(device_attach, fd_attach),
- DEVMETHOD(device_detach, fd_detach),
- DEVMETHOD(device_shutdown, bus_generic_shutdown),
- DEVMETHOD(device_suspend, bus_generic_suspend), /* XXX */
- DEVMETHOD(device_resume, bus_generic_resume), /* XXX */
-
- { 0, 0 }
-};
-
-static driver_t fd_driver = {
- "fd",
- fd_methods,
- sizeof(struct fd_data)
-};
-
-DRIVER_MODULE(fd, fdc, fd_driver, fd_devclass, 0, 0);
-
-/*
- * More auxiliary functions.
- */
-/*
- * Motor control stuff.
- * Remember to not deselect the drive we're working on.
- */
-static void
-set_motor(struct fdc_data *fdc, int fdsu, int turnon)
-{
-#ifdef PC98
- bus_space_write_1(fdc->sc_fdsiot, fdc->sc_fdsioh, 0,
- (pc98_trans != 1 ? FDP_FDDEXC : 0) | FDP_PORTEXC);
- DELAY(10);
- fdctl_wr(fdc, FDC_DMAE | FDC_MTON);
-#else
- int fdout;
-
- fdout = fdc->fdout;
- if (turnon) {
- fdout &= ~FDO_FDSEL;
- fdout |= (FDO_MOEN0 << fdsu) | FDO_FDMAEN | FDO_FRST | fdsu;
- } else
- fdout &= ~(FDO_MOEN0 << fdsu);
- fdc->fdout = fdout;
- fdout_wr(fdc, fdout);
- TRACE1("[0x%x->FDOUT]", fdout);
-#endif
-}
-
-static void
-fd_turnoff(void *xfd)
-{
- int s;
- fd_p fd = xfd;
-
- TRACE1("[fd%d: turnoff]", fd->fdu);
-
- s = splbio();
- /*
- * Don't turn off the motor yet if the drive is active.
- *
- * If we got here, this could only mean we missed an interrupt.
- * This can e. g. happen on the Y-E Date PCMCIA floppy controller
- * after a controller reset. Just schedule a pseudo-interrupt
- * so the state machine gets re-entered.
- */
- if (fd->fdc->state != DEVIDLE && fd->fdc->fdu == fd->fdu) {
- fdc_intr(fd->fdc);
- splx(s);
- return;
- }
-
- fd->flags &= ~FD_MOTOR;
- set_motor(fd->fdc, fd->fdsu, TURNOFF);
- splx(s);
-}
-
-static void
-fd_motor_on(void *xfd)
-{
- int s;
- fd_p fd = xfd;
-
- s = splbio();
- fd->flags &= ~FD_MOTOR_WAIT;
- if((fd->fdc->fd == fd) && (fd->fdc->state == MOTORWAIT))
- {
- fdc_intr(fd->fdc);
- }
- splx(s);
-}
-
-static void
-fd_turnon(fd_p fd)
-{
- if(!(fd->flags & FD_MOTOR))
- {
- fd->flags |= (FD_MOTOR + FD_MOTOR_WAIT);
- set_motor(fd->fdc, fd->fdsu, TURNON);
- timeout(fd_motor_on, fd, hz); /* in 1 sec its ok */
- }
-}
-
-static void
-fdc_reset(fdc_p fdc)
-{
- /* Try a reset, keep motor on */
-#ifdef PC98
- set_density(fdc);
- if (pc98_machine_type & M_EPSON_PC98)
- fdctl_wr(fdc, FDC_RST | FDC_RDY | FDC_DD | FDC_MTON);
- else
- fdctl_wr(fdc, FDC_RST | FDC_RDY | FDC_DMAE | FDC_MTON);
- DELAY(200);
- fdctl_wr(fdc, FDC_DMAE | FDC_MTON);
- DELAY(10);
-#else
- fdout_wr(fdc, fdc->fdout & ~(FDO_FRST|FDO_FDMAEN));
- TRACE1("[0x%x->FDOUT]", fdc->fdout & ~(FDO_FRST|FDO_FDMAEN));
- DELAY(100);
- /* enable FDC, but defer interrupts a moment */
- fdout_wr(fdc, fdc->fdout & ~FDO_FDMAEN);
- TRACE1("[0x%x->FDOUT]", fdc->fdout & ~FDO_FDMAEN);
- DELAY(100);
- fdout_wr(fdc, fdc->fdout);
- TRACE1("[0x%x->FDOUT]", fdc->fdout);
-#endif
-
- /* XXX after a reset, silently believe the FDC will accept commands */
-#ifdef PC98
- (void)fd_cmd(fdc, 3, NE7CMD_SPECIFY,
- NE7_SPEC_1(4, 240), NE7_SPEC_2(2, 0),
- 0);
-#else
- (void)fd_cmd(fdc, 3, NE7CMD_SPECIFY,
- NE7_SPEC_1(3, 240), NE7_SPEC_2(2, 0),
- 0);
-#endif
- if (fdc->flags & FDC_HAS_FIFO)
- (void) enable_fifo(fdc);
-}
-
-/*
- * FDC IO functions, take care of the main status register, timeout
- * in case the desired status bits are never set.
- *
- * These PIO loops initially start out with short delays between
- * each iteration in the expectation that the required condition
- * is usually met quickly, so it can be handled immediately. After
- * about 1 ms, stepping is increased to achieve a better timing
- * accuracy in the calls to DELAY().
- */
-static int
-fd_in(struct fdc_data *fdc, int *ptr)
-{
- int i, j, step;
-
- for (j = 0, step = 1;
- (i = fdsts_rd(fdc) & (NE7_DIO|NE7_RQM)) != (NE7_DIO|NE7_RQM) &&
- j < FDSTS_TIMEOUT;
- j += step) {
- if (i == NE7_RQM)
- return (fdc_err(fdc, "ready for output in input\n"));
- if (j == 1000)
- step = 1000;
- DELAY(step);
- }
- if (j >= FDSTS_TIMEOUT)
- return (fdc_err(fdc, bootverbose? "input ready timeout\n": 0));
-#ifdef FDC_DEBUG
- i = fddata_rd(fdc);
- TRACE1("[FDDATA->0x%x]", (unsigned char)i);
- *ptr = i;
- return (0);
-#else /* !FDC_DEBUG */
- i = fddata_rd(fdc);
- if (ptr)
- *ptr = i;
- return (0);
-#endif /* FDC_DEBUG */
-}
-
-static int
-out_fdc(struct fdc_data *fdc, int x)
-{
- int i, j, step;
-
- for (j = 0, step = 1;
- (i = fdsts_rd(fdc) & (NE7_DIO|NE7_RQM)) != NE7_RQM &&
- j < FDSTS_TIMEOUT;
- j += step) {
- if (i == (NE7_DIO|NE7_RQM))
- return (fdc_err(fdc, "ready for input in output\n"));
- if (j == 1000)
- step = 1000;
- DELAY(step);
- }
- if (j >= FDSTS_TIMEOUT)
- return (fdc_err(fdc, bootverbose? "output ready timeout\n": 0));
-
- /* Send the command and return */
- fddata_wr(fdc, x);
- TRACE1("[0x%x->FDDATA]", x);
- return (0);
-}
-
-/*
- * Block device driver interface functions (interspersed with even more
- * auxiliary functions).
- */
-static int
-fdopen(struct cdev *dev, int flags, int mode, struct thread *td)
-{
- fd_p fd;
- fdc_p fdc;
-#ifdef PC98
- fdu_t fdu;
-#endif
- int rv, unitattn, dflags;
-
- fd = dev->si_drv1;
- if (fd == NULL)
- return (ENXIO);
- fdc = fd->fdc;
- if ((fdc == NULL) || (fd->type == FDT_NONE))
- return (ENXIO);
-#ifdef PC98
- fdu = fd->fdu;
-#endif
- dflags = device_get_flags(fd->dev);
- /*
- * This is a bit bogus. It's still possible that e. g. a
- * descriptor gets inherited to a child, but then it's at
- * least for the same subdevice. By checking FD_OPEN here, we
- * can ensure that a device isn't attempted to be opened with
- * different densities at the same time where the second open
- * could clobber the settings from the first one.
- */
- if (fd->flags & FD_OPEN)
- return (EBUSY);
-
-#ifdef PC98
- if (pc98_fd_check_ready(fdu) == -1)
- return(EIO);
-#endif
-
- if (flags & FNONBLOCK) {
- /*
- * Unfortunately, physio(9) discards its ioflag
- * argument, thus preventing us from seeing the
- * O_NONBLOCK bit. So we need to keep track
- * ourselves.
- */
- fd->flags |= FD_NONBLOCK;
- fd->ft = 0;
- } else {
- /*
- * Figure out a unit attention condition.
- *
- * If UA has been forced, proceed.
- *
- * If the drive has no changeline support,
- * or if the drive parameters have been lost
- * due to previous non-blocking access,
- * assume a forced UA condition.
- *
- * If motor is off, turn it on for a moment
- * and select our drive, in order to read the
- * UA hardware signal.
- *
- * If motor is on, and our drive is currently
- * selected, just read the hardware bit.
- *
- * If motor is on, but active for another
- * drive on that controller, we are lost. We
- * cannot risk to deselect the other drive, so
- * we just assume a forced UA condition to be
- * on the safe side.
- */
- unitattn = 0;
- if ((dflags & FD_NO_CHLINE) != 0 ||
- (fd->flags & FD_UA) != 0 ||
- fd->ft == 0) {
- unitattn = 1;
- fd->flags &= ~FD_UA;
-#ifndef PC98
- } else if (fdc->fdout & (FDO_MOEN0 | FDO_MOEN1 |
- FDO_MOEN2 | FDO_MOEN3)) {
- if ((fdc->fdout & FDO_FDSEL) == fd->fdsu)
- unitattn = fdin_rd(fdc) & FDI_DCHG;
- else
- unitattn = 1;
- } else {
- set_motor(fdc, fd->fdsu, TURNON);
- unitattn = fdin_rd(fdc) & FDI_DCHG;
- set_motor(fdc, fd->fdsu, TURNOFF);
-#endif /* PC98 */
- }
- if (unitattn && (rv = fdautoselect(dev)) != 0)
- return (rv);
- }
- fd->flags |= FD_OPEN;
-
- if ((fdc->flags & FDC_NODMA) == 0) {
- if (fdc->dmacnt++ == 0) {
- isa_dma_acquire(fdc->dmachan);
- isa_dmainit(fdc->dmachan, MAX_SEC_SIZE);
- }
- }
-
- /*
- * Clearing the DMA overrun counter at open time is a bit messy.
- * Since we're only managing one counter per controller, opening
- * the second drive could mess it up. Anyway, if the DMA overrun
- * condition is really persistent, it will eventually time out
- * still. OTOH, clearing it here will ensure we'll at least start
- * trying again after a previous (maybe even long ago) failure.
- * Also, this is merely a stop-gap measure only that should not
- * happen during normal operation, so we can tolerate it to be a
- * bit sloppy about this.
- */
- fdc->dma_overruns = 0;
-
- return 0;
-}
-
-static int
-fdclose(struct cdev *dev, int flags, int mode, struct thread *td)
-{
- struct fd_data *fd;
- fdc_p fdc;
-
- fd = dev->si_drv1;
- fdc = fd->fdc;
- fd->flags &= ~(FD_OPEN | FD_NONBLOCK);
- fd->options &= ~(FDOPT_NORETRY | FDOPT_NOERRLOG | FDOPT_NOERROR);
-
- if ((fdc->flags & FDC_NODMA) == 0)
- if (--fdc->dmacnt == 0)
- isa_dma_release(fdc->dmachan);
-
- return (0);
-}
-
-static void
-fdstrategy(struct bio *bp)
-{
- long blknum, nblocks;
- int s;
- fdu_t fdu;
- fdc_p fdc;
- fd_p fd;
- size_t fdblk;
-
- fd = bp->bio_dev->si_drv1;
- fdu = fd->fdu;
- fdc = fd->fdc;
- bp->bio_resid = bp->bio_bcount;
- if (fd->type == FDT_NONE || fd->ft == 0) {
- if (fd->type != FDT_NONE && (fd->flags & FD_NONBLOCK))
- bp->bio_error = EAGAIN;
- else
- bp->bio_error = ENXIO;
- bp->bio_flags |= BIO_ERROR;
- goto bad;
- }
- fdblk = 128 << (fd->ft->secsize);
- if (bp->bio_cmd != FDBIO_FORMAT && bp->bio_cmd != FDBIO_RDSECTID) {
- if (fd->flags & FD_NONBLOCK) {
- bp->bio_error = EAGAIN;
- bp->bio_flags |= BIO_ERROR;
- goto bad;
- }
- if (bp->bio_offset < 0) {
- printf(
- "fd%d: fdstrat: bad request offset = %ju, bcount = %ld\n",
- fdu, (intmax_t)bp->bio_offset, bp->bio_bcount);
- bp->bio_error = EINVAL;
- bp->bio_flags |= BIO_ERROR;
- goto bad;
- }
- if ((bp->bio_bcount % fdblk) != 0) {
- bp->bio_error = EINVAL;
- bp->bio_flags |= BIO_ERROR;
- goto bad;
- }
- }
-
- /*
- * Set up block calculations.
- */
-#ifndef PC98
- if (bp->bio_offset >= ((off_t)128 << fd->ft->secsize) * fd->ft->size) {
- bp->bio_error = EINVAL;
- bp->bio_flags |= BIO_ERROR;
- goto bad;
- }
-#endif
- blknum = bp->bio_offset / fdblk;
- nblocks = fd->ft->size;
- if (blknum + bp->bio_bcount / fdblk > nblocks) {
- if (blknum >= nblocks) {
- if (bp->bio_cmd != BIO_READ) {
- bp->bio_error = ENOSPC;
- bp->bio_flags |= BIO_ERROR;
- }
- goto bad; /* not always bad, but EOF */
- }
- bp->bio_bcount = (nblocks - blknum) * fdblk;
- }
- bp->bio_pblkno = blknum;
- s = splbio();
- bioq_disksort(&fdc->head, bp);
- untimeout(fd_turnoff, fd, fd->toffhandle); /* a good idea */
- devstat_start_transaction_bio(fd->device_stats, bp);
- device_busy(fd->dev);
- fdstart(fdc);
- splx(s);
- return;
-
-bad:
- biodone(bp);
-}
-
-/*
- * fdstart
- *
- * We have just queued something. If the controller is not busy
- * then simulate the case where it has just finished a command
- * So that it (the interrupt routine) looks on the queue for more
- * work to do and picks up what we just added.
- *
- * If the controller is already busy, we need do nothing, as it
- * will pick up our work when the present work completes.
- */
-static void
-fdstart(struct fdc_data *fdc)
-{
- int s;
-
- s = splbio();
- if(fdc->state == DEVIDLE)
- {
- fdc_intr(fdc);
- }
- splx(s);
-}
-
-static void
-fd_iotimeout(void *xfdc)
-{
- fdc_p fdc;
- int s;
-
- fdc = xfdc;
- TRACE1("fd%d[fd_iotimeout()]", fdc->fdu);
-
- /*
- * Due to IBM's brain-dead design, the FDC has a faked ready
- * signal, hardwired to ready == true. Thus, any command
- * issued if there's no diskette in the drive will _never_
- * complete, and must be aborted by resetting the FDC.
- * Many thanks, Big Blue!
- * The FDC must not be reset directly, since that would
- * interfere with the state machine. Instead, pretend that
- * the command completed but was invalid. The state machine
- * will reset the FDC and retry once.
- */
- s = splbio();
- fdc->status[0] = NE7_ST0_IC_IV;
- fdc->flags &= ~FDC_STAT_VALID;
- fdc->state = IOTIMEDOUT;
- fdc_intr(fdc);
- splx(s);
-}
-
-/* Just ensure it has the right spl. */
-static void
-fd_pseudointr(void *xfdc)
-{
- int s;
-
- s = splbio();
- fdc_intr(xfdc);
- splx(s);
-}
-
-/*
- * fdc_intr
- *
- * Keep calling the state machine until it returns a 0.
- * Always called at splbio.
- */
-static void
-fdc_intr(void *xfdc)
-{
- fdc_p fdc = xfdc;
- while(fdstate(fdc))
- ;
-}
-
-/*
- * Magic pseudo-DMA initialization for YE FDC. Sets count and
- * direction.
- */
-#define SET_BCDR(fdc,wr,cnt,port) \
- bus_space_write_1(fdc->portt, fdc->porth, fdc->port_off + port, \
- ((cnt)-1) & 0xff); \
- bus_space_write_1(fdc->portt, fdc->porth, fdc->port_off + port + 1, \
- ((wr ? 0x80 : 0) | ((((cnt)-1) >> 8) & 0x7f)));
-
-/*
- * fdcpio(): perform programmed IO read/write for YE PCMCIA floppy.
- */
-static int
-fdcpio(fdc_p fdc, long flags, caddr_t addr, u_int count)
-{
- u_char *cptr = (u_char *)addr;
-
- if (flags == BIO_READ) {
- if (fdc->state != PIOREAD) {
- fdc->state = PIOREAD;
- return(0);
- }
- SET_BCDR(fdc, 0, count, 0);
- bus_space_read_multi_1(fdc->portt, fdc->porth, fdc->port_off +
- FDC_YE_DATAPORT, cptr, count);
- } else {
- bus_space_write_multi_1(fdc->portt, fdc->porth, fdc->port_off +
- FDC_YE_DATAPORT, cptr, count);
- SET_BCDR(fdc, 0, count, 0);
- }
- return(1);
-}
-
-/*
- * Try figuring out the density of the media present in our device.
- */
-static int
-fdautoselect(struct cdev *dev)
-{
- fd_p fd;
- struct fd_type *fdtp;
- struct fdc_readid id;
- int i, n, oopts, rv;
-
- fd = dev->si_drv1;
-
- switch (fd->type) {
- default:
- return (ENXIO);
-
-#ifndef PC98
- case FDT_360K:
- case FDT_720K:
- /* no autoselection on those drives */
- fd->ft = fd_native_types + fd->type;
- return (0);
-#endif
-
- case FDT_12M:
- fdtp = fd_searchlist_12m;
- n = sizeof fd_searchlist_12m / sizeof(struct fd_type);
- break;
-
- case FDT_144M:
- fdtp = fd_searchlist_144m;
- n = sizeof fd_searchlist_144m / sizeof(struct fd_type);
- break;
-
-#ifndef PC98
- case FDT_288M:
- fdtp = fd_searchlist_288m;
- n = sizeof fd_searchlist_288m / sizeof(struct fd_type);
- break;
-#endif
- }
-
- /*
- * Try reading sector ID fields, first at cylinder 0, head 0,
- * then at cylinder 2, head N. We don't probe cylinder 1,
- * since for 5.25in DD media in a HD drive, there are no data
- * to read (2 step pulses per media cylinder required). For
- * two-sided media, the second probe always goes to head 1, so
- * we can tell them apart from single-sided media. As a
- * side-effect this means that single-sided media should be
- * mentioned in the search list after two-sided media of an
- * otherwise identical density. Media with a different number
- * of sectors per track but otherwise identical parameters
- * cannot be distinguished at all.
- *
- * If we successfully read an ID field on both cylinders where
- * the recorded values match our expectation, we are done.
- * Otherwise, we try the next density entry from the table.
- *
- * Stepping to cylinder 2 has the side-effect of clearing the
- * unit attention bit.
- */
- oopts = fd->options;
- fd->options |= FDOPT_NOERRLOG | FDOPT_NORETRY;
- for (i = 0; i < n; i++, fdtp++) {
- fd->ft = fdtp;
-
- id.cyl = id.head = 0;
- rv = fdmisccmd(dev, FDBIO_RDSECTID, &id);
- if (rv != 0)
- continue;
- if (id.cyl != 0 || id.head != 0 ||
- id.secshift != fdtp->secsize)
- continue;
- id.cyl = 2;
- id.head = fd->ft->heads - 1;
- rv = fdmisccmd(dev, FDBIO_RDSECTID, &id);
- if (id.cyl != 2 || id.head != fdtp->heads - 1 ||
- id.secshift != fdtp->secsize)
- continue;
- if (rv == 0)
- break;
- }
-
- fd->options = oopts;
- if (i == n) {
- if (bootverbose)
- device_printf(fd->dev, "autoselection failed\n");
- fd->ft = 0;
- return (EIO);
- } else {
- if (bootverbose)
- device_printf(fd->dev, "autoselected %d KB medium\n",
-#ifdef PC98
- (128 << (fd->ft->secsize)) *
- fd->ft->size / 1024);
-#else
- fd->ft->size / 2);
-#endif
- return (0);
- }
-}
-
-
-/*
- * The controller state machine.
- *
- * If it returns a non zero value, it should be called again immediately.
- */
-static int
-fdstate(fdc_p fdc)
-{
- struct fdc_readid *idp;
- int read, format, rdsectid, cylinder, head, i, sec = 0, sectrac;
- int st0, cyl, st3, idf, ne7cmd, mfm, steptrac;
- unsigned long blknum;
- fdu_t fdu = fdc->fdu;
- fd_p fd;
- register struct bio *bp;
- struct fd_formb *finfo = NULL;
- size_t fdblk;
-
- bp = fdc->bp;
- if (bp == NULL) {
- bp = bioq_takefirst(&fdc->head);
- if (bp != NULL)
- fdc->bp = bp;
- }
- if (bp == NULL) {
- /*
- * Nothing left for this controller to do,
- * force into the IDLE state.
- */
- fdc->state = DEVIDLE;
- if (fdc->fd) {
- device_printf(fdc->fdc_dev,
- "unexpected valid fd pointer\n");
- fdc->fd = (fd_p) 0;
- fdc->fdu = -1;
- }
- TRACE1("[fdc%d IDLE]", fdc->fdcu);
- return (0);
- }
- fd = bp->bio_dev->si_drv1;
- fdu = fd->fdu;
- fdblk = 128 << fd->ft->secsize;
- if (fdc->fd && (fd != fdc->fd))
- device_printf(fd->dev, "confused fd pointers\n");
- read = bp->bio_cmd == BIO_READ;
- mfm = (fd->ft->flags & FL_MFM)? NE7CMD_MFM: 0;
- steptrac = (fd->ft->flags & FL_2STEP)? 2: 1;
- if (read)
- idf = ISADMA_READ;
- else
- idf = ISADMA_WRITE;
- format = bp->bio_cmd == FDBIO_FORMAT;
- rdsectid = bp->bio_cmd == FDBIO_RDSECTID;
- if (format)
- finfo = (struct fd_formb *)bp->bio_data;
- TRACE1("fd%d", fdu);
- TRACE1("[%s]", fdstates[fdc->state]);
- TRACE1("(0x%x)", fd->flags);
- untimeout(fd_turnoff, fd, fd->toffhandle);
- fd->toffhandle = timeout(fd_turnoff, fd, 4 * hz);
- switch (fdc->state)
- {
- case DEVIDLE:
- case FINDWORK: /* we have found new work */
- fdc->retry = 0;
- fd->skip = 0;
- fdc->fd = fd;
- fdc->fdu = fdu;
-#ifdef PC98
- pc98_trans = fd->ft->trans;
- if (pc98_trans_prev != pc98_trans) {
- int i;
- set_density(fdc);
- for (i = 0; i < 10; i++) {
- outb(0x5f, 0);
- outb(0x5f, 0);
- }
- pc98_trans_prev = pc98_trans;
- }
- if (pc98_trans != fd->pc98_trans) {
- if (fd->type == FDT_144M) {
- bus_space_write_1(fdc->sc_fdemsiot,
- fdc->sc_fdemsioh,
- 0,
- (fdu << 5) | 0x10 |
- (pc98_trans >> 1));
- outb(0x5f, 0);
- outb(0x5f, 0);
- }
- fd->pc98_trans = pc98_trans;
- }
-#else
- fdc->fdctl_wr(fdc, fd->ft->trans);
-#endif
- TRACE1("[0x%x->FDCTL]", fd->ft->trans);
- /*
- * If the next drive has a motor startup pending, then
- * it will start up in its own good time.
- */
- if(fd->flags & FD_MOTOR_WAIT) {
- fdc->state = MOTORWAIT;
- return (0); /* will return later */
- }
- /*
- * Maybe if it's not starting, it SHOULD be starting.
- */
- if (!(fd->flags & FD_MOTOR))
- {
- fdc->state = MOTORWAIT;
- fd_turnon(fd);
- return (0); /* will return later */
- }
- else /* at least make sure we are selected */
- {
- set_motor(fdc, fd->fdsu, TURNON);
- }
- if (fdc->flags & FDC_NEEDS_RESET) {
- fdc->state = RESETCTLR;
- fdc->flags &= ~FDC_NEEDS_RESET;
- } else
- fdc->state = DOSEEK;
- return (1); /* will return immediately */
-
- case DOSEEK:
- blknum = bp->bio_pblkno + fd->skip / fdblk;
- cylinder = blknum / (fd->ft->sectrac * fd->ft->heads);
- if (cylinder == fd->track)
- {
- fdc->state = SEEKCOMPLETE;
- return (1); /* will return immediately */
- }
-#ifdef PC98
- pc98_fd_check_ready(fdu);
-#endif
- if (fd_cmd(fdc, 3, NE7CMD_SEEK,
- fd->fdsu, cylinder * steptrac, 0))
- {
- /*
- * Seek command not accepted, looks like
- * the FDC went off to the Saints...
- */
- fdc->retry = 6; /* try a reset */
- return(retrier(fdc));
- }
- fd->track = FD_NO_TRACK;
- fdc->state = SEEKWAIT;
- return(0); /* will return later */
-
- case SEEKWAIT:
- /* allow heads to settle */
- timeout(fd_pseudointr, fdc, hz / 16);
- fdc->state = SEEKCOMPLETE;
- return(0); /* will return later */
-
- case SEEKCOMPLETE : /* seek done, start DMA */
- blknum = bp->bio_pblkno + fd->skip / fdblk;
- cylinder = blknum / (fd->ft->sectrac * fd->ft->heads);
-
- /* Make sure seek really happened. */
- if(fd->track == FD_NO_TRACK) {
- int descyl = cylinder * steptrac;
- do {
- /*
- * This might be a "ready changed" interrupt,
- * which cannot really happen since the
- * RDY pin is hardwired to + 5 volts. This
- * generally indicates a "bouncing" intr
- * line, so do one of the following:
- *
- * When running on an enhanced FDC that is
- * known to not go stuck after responding
- * with INVALID, fetch all interrupt states
- * until seeing either an INVALID or a
- * real interrupt condition.
- *
- * When running on a dumb old NE765, give
- * up immediately. The controller will
- * provide up to four dummy RC interrupt
- * conditions right after reset (for the
- * corresponding four drives), so this is
- * our only chance to get notice that it
- * was not the FDC that caused the interrupt.
- */
- if (fd_sense_int(fdc, &st0, &cyl)
- == FD_NOT_VALID)
- return (0); /* will return later */
- if(fdc->fdct == FDC_NE765
- && (st0 & NE7_ST0_IC) == NE7_ST0_IC_RC)
- return (0); /* hope for a real intr */
- } while ((st0 & NE7_ST0_IC) == NE7_ST0_IC_RC);
-
- if (0 == descyl) {
- int failed = 0;
- /*
- * seek to cyl 0 requested; make sure we are
- * really there
- */
- if (fd_sense_drive_status(fdc, &st3))
- failed = 1;
- if ((st3 & NE7_ST3_T0) == 0) {
- printf(
- "fd%d: Seek to cyl 0, but not really there (ST3 = %b)\n",
- fdu, st3, NE7_ST3BITS);
- failed = 1;
- }
-
- if (failed) {
- if(fdc->retry < 3)
- fdc->retry = 3;
- return (retrier(fdc));
- }
- }
-
- if (cyl != descyl) {
- printf(
- "fd%d: Seek to cyl %d failed; am at cyl %d (ST0 = 0x%x)\n",
- fdu, descyl, cyl, st0);
- if (fdc->retry < 3)
- fdc->retry = 3;
- return (retrier(fdc));
- }
- }
-
- fd->track = cylinder;
- if (format)
- fd->skip = (char *)&(finfo->fd_formb_cylno(0))
- - (char *)finfo;
- if (!rdsectid && !(fdc->flags & FDC_NODMA))
- isa_dmastart(idf, bp->bio_data+fd->skip,
- format ? bp->bio_bcount : fdblk, fdc->dmachan);
- blknum = bp->bio_pblkno + fd->skip / fdblk;
- sectrac = fd->ft->sectrac;
- sec = blknum % (sectrac * fd->ft->heads);
- head = sec / sectrac;
- sec = sec % sectrac + 1;
- if (head != 0 && fd->ft->offset_side2 != 0)
- sec += fd->ft->offset_side2;
- fd->hddrv = ((head&1)<<2)+fdu;
-
- if(format || !(read || rdsectid))
- {
- /* make sure the drive is writable */
- if(fd_sense_drive_status(fdc, &st3) != 0)
- {
- /* stuck controller? */
- if (!(fdc->flags & FDC_NODMA))
- isa_dmadone(idf,
- bp->bio_data + fd->skip,
- format ? bp->bio_bcount : fdblk,
- fdc->dmachan);
- fdc->retry = 6; /* reset the beast */
- return (retrier(fdc));
- }
- if(st3 & NE7_ST3_WP)
- {
- /*
- * XXX YES! this is ugly.
- * in order to force the current operation
- * to fail, we will have to fake an FDC
- * error - all error handling is done
- * by the retrier()
- */
- fdc->status[0] = NE7_ST0_IC_AT;
- fdc->status[1] = NE7_ST1_NW;
- fdc->status[2] = 0;
- fdc->status[3] = fd->track;
- fdc->status[4] = head;
- fdc->status[5] = sec;
- fdc->retry = 8; /* break out immediately */
- fdc->state = IOTIMEDOUT; /* not really... */
- return (1); /* will return immediately */
- }
- }
-
- if (format) {
- ne7cmd = NE7CMD_FORMAT | mfm;
- if (fdc->flags & FDC_NODMA) {
- /*
- * This seems to be necessary for
- * whatever obscure reason; if we omit
- * it, we end up filling the sector ID
- * fields of the newly formatted track
- * entirely with garbage, causing
- * `wrong cylinder' errors all over
- * the place when trying to read them
- * back.
- *
- * Umpf.
- */
- SET_BCDR(fdc, 1, bp->bio_bcount, 0);
-
- (void)fdcpio(fdc,bp->bio_cmd,
- bp->bio_data+fd->skip,
- bp->bio_bcount);
-
- }
- /* formatting */
- if(fd_cmd(fdc, 6, ne7cmd, head << 2 | fdu,
- finfo->fd_formb_secshift,
- finfo->fd_formb_nsecs,
- finfo->fd_formb_gaplen,
- finfo->fd_formb_fillbyte, 0)) {
- /* controller fell over */
- if (!(fdc->flags & FDC_NODMA))
- isa_dmadone(idf,
- bp->bio_data + fd->skip,
- format ? bp->bio_bcount : fdblk,
- fdc->dmachan);
- fdc->retry = 6;
- return (retrier(fdc));
- }
- } else if (rdsectid) {
- ne7cmd = NE7CMD_READID | mfm;
- if (fd_cmd(fdc, 2, ne7cmd, head << 2 | fdu, 0)) {
- /* controller jamming */
- fdc->retry = 6;
- return (retrier(fdc));
- }
- } else {
- /* read or write operation */
- ne7cmd = (read ? NE7CMD_READ | NE7CMD_SK : NE7CMD_WRITE) | mfm;
- if (fdc->flags & FDC_NODMA) {
- /*
- * This seems to be necessary even when
- * reading data.
- */
- SET_BCDR(fdc, 1, fdblk, 0);
-
- /*
- * Perform the write pseudo-DMA before
- * the WRITE command is sent.
- */
- if (!read)
- (void)fdcpio(fdc,bp->bio_cmd,
- bp->bio_data+fd->skip,
- fdblk);
- }
- if (fd_cmd(fdc, 9,
- ne7cmd,
- head << 2 | fdu, /* head & unit */
- fd->track, /* track */
- head,
- sec, /* sector + 1 */
- fd->ft->secsize, /* sector size */
- sectrac, /* sectors/track */
- fd->ft->gap, /* gap size */
- fd->ft->datalen, /* data length */
- 0)) {
- /* the beast is sleeping again */
- if (!(fdc->flags & FDC_NODMA))
- isa_dmadone(idf,
- bp->bio_data + fd->skip,
- format ? bp->bio_bcount : fdblk,
- fdc->dmachan);
- fdc->retry = 6;
- return (retrier(fdc));
- }
- }
- if (!rdsectid && (fdc->flags & FDC_NODMA))
- /*
- * If this is a read, then simply await interrupt
- * before performing PIO.
- */
- if (read && !fdcpio(fdc,bp->bio_cmd,
- bp->bio_data+fd->skip,fdblk)) {
- fd->tohandle = timeout(fd_iotimeout, fdc, hz);
- return(0); /* will return later */
- }
-
- /*
- * Write (or format) operation will fall through and
- * await completion interrupt.
- */
- fdc->state = IOCOMPLETE;
- fd->tohandle = timeout(fd_iotimeout, fdc, hz);
- return (0); /* will return later */
-
- case PIOREAD:
- /*
- * Actually perform the PIO read. The IOCOMPLETE case
- * removes the timeout for us.
- */
- (void)fdcpio(fdc,bp->bio_cmd,bp->bio_data+fd->skip,fdblk);
- fdc->state = IOCOMPLETE;
- /* FALLTHROUGH */
- case IOCOMPLETE: /* IO done, post-analyze */
- untimeout(fd_iotimeout, fdc, fd->tohandle);
-
- if (fd_read_status(fdc)) {
- if (!rdsectid && !(fdc->flags & FDC_NODMA))
- isa_dmadone(idf, bp->bio_data + fd->skip,
- format ? bp->bio_bcount : fdblk,
- fdc->dmachan);
- if (fdc->retry < 6)
- fdc->retry = 6; /* force a reset */
- return (retrier(fdc));
- }
-
- fdc->state = IOTIMEDOUT;
-
- /* FALLTHROUGH */
- case IOTIMEDOUT:
- if (!rdsectid && !(fdc->flags & FDC_NODMA))
- isa_dmadone(idf, bp->bio_data + fd->skip,
- format ? bp->bio_bcount : fdblk, fdc->dmachan);
- if (fdc->status[0] & NE7_ST0_IC) {
- if ((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_AT
- && fdc->status[1] & NE7_ST1_OR) {
- /*
- * DMA overrun. Someone hogged the bus and
- * didn't release it in time for the next
- * FDC transfer.
- *
- * We normally restart this without bumping
- * the retry counter. However, in case
- * something is seriously messed up (like
- * broken hardware), we rather limit the
- * number of retries so the IO operation
- * doesn't block indefinately.
- */
- if (fdc->dma_overruns++ < FDC_DMAOV_MAX) {
- fdc->state = SEEKCOMPLETE;
- return (1);/* will return immediately */
- } /* else fall through */
- }
- if((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_IV
- && fdc->retry < 6)
- fdc->retry = 6; /* force a reset */
- else if((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_AT
- && fdc->status[2] & NE7_ST2_WC
- && fdc->retry < 3)
- fdc->retry = 3; /* force recalibrate */
- return (retrier(fdc));
- }
- /* All OK */
- if (rdsectid) {
- /* copy out ID field contents */
- idp = (struct fdc_readid *)bp->bio_data;
- idp->cyl = fdc->status[3];
- idp->head = fdc->status[4];
- idp->sec = fdc->status[5];
- idp->secshift = fdc->status[6];
- }
- /* Operation successful, retry DMA overruns again next time. */
- fdc->dma_overruns = 0;
- fd->skip += fdblk;
- if (!rdsectid && !format && fd->skip < bp->bio_bcount) {
- /* set up next transfer */
- fdc->state = DOSEEK;
- } else {
- /* ALL DONE */
- fd->skip = 0;
- bp->bio_resid = 0;
- fdc->bp = NULL;
- device_unbusy(fd->dev);
- biofinish(bp, fd->device_stats, 0);
- fdc->fd = (fd_p) 0;
- fdc->fdu = -1;
- fdc->state = FINDWORK;
- }
- return (1); /* will return immediately */
-
- case RESETCTLR:
- fdc_reset(fdc);
- fdc->retry++;
- fdc->state = RESETCOMPLETE;
- return (0); /* will return later */
-
- case RESETCOMPLETE:
- /*
- * Discard all the results from the reset so that they
- * can't cause an unexpected interrupt later.
- */
- for (i = 0; i < 4; i++)
- (void)fd_sense_int(fdc, &st0, &cyl);
- fdc->state = STARTRECAL;
- /* FALLTHROUGH */
- case STARTRECAL:
-#ifdef PC98
- pc98_fd_check_ready(fdu);
-#endif
- if(fd_cmd(fdc, 2, NE7CMD_RECAL, fdu, 0)) {
- /* arrgl */
- fdc->retry = 6;
- return (retrier(fdc));
- }
- fdc->state = RECALWAIT;
- return (0); /* will return later */
-
- case RECALWAIT:
- /* allow heads to settle */
- timeout(fd_pseudointr, fdc, hz / 8);
- fdc->state = RECALCOMPLETE;
- return (0); /* will return later */
-
- case RECALCOMPLETE:
- do {
- /*
- * See SEEKCOMPLETE for a comment on this:
- */
- if (fd_sense_int(fdc, &st0, &cyl) == FD_NOT_VALID)
- return (0); /* will return later */
- if(fdc->fdct == FDC_NE765
- && (st0 & NE7_ST0_IC) == NE7_ST0_IC_RC)
- return (0); /* hope for a real intr */
- } while ((st0 & NE7_ST0_IC) == NE7_ST0_IC_RC);
- if ((st0 & NE7_ST0_IC) != NE7_ST0_IC_NT || cyl != 0)
- {
- if(fdc->retry > 3)
- /*
- * A recalibrate from beyond cylinder 77
- * will "fail" due to the FDC limitations;
- * since people used to complain much about
- * the failure message, try not logging
- * this one if it seems to be the first
- * time in a line.
- */
- printf("fd%d: recal failed ST0 %b cyl %d\n",
- fdu, st0, NE7_ST0BITS, cyl);
- if(fdc->retry < 3) fdc->retry = 3;
- return (retrier(fdc));
- }
- fd->track = 0;
- /* Seek (probably) necessary */
- fdc->state = DOSEEK;
- return (1); /* will return immediately */
-
- case MOTORWAIT:
- if(fd->flags & FD_MOTOR_WAIT)
- {
- return (0); /* time's not up yet */
- }
- if (fdc->flags & FDC_NEEDS_RESET) {
- fdc->state = RESETCTLR;
- fdc->flags &= ~FDC_NEEDS_RESET;
- } else
- fdc->state = DOSEEK;
- return (1); /* will return immediately */
-
- default:
- device_printf(fdc->fdc_dev, "unexpected FD int->");
- if (fd_read_status(fdc) == 0)
- printf("FDC status :%x %x %x %x %x %x %x ",
- fdc->status[0],
- fdc->status[1],
- fdc->status[2],
- fdc->status[3],
- fdc->status[4],
- fdc->status[5],
- fdc->status[6] );
- else
- printf("No status available ");
- if (fd_sense_int(fdc, &st0, &cyl) != 0)
- {
- printf("[controller is dead now]\n");
- return (0); /* will return later */
- }
- printf("ST0 = %x, PCN = %x\n", st0, cyl);
- return (0); /* will return later */
- }
- /* noone should ever get here */
-}
-
-static int
-retrier(struct fdc_data *fdc)
-{
- struct bio *bp;
- struct fd_data *fd;
- int fdu;
-
- bp = fdc->bp;
-
- /* XXX shouldn't this be cached somewhere? */
- fd = bp->bio_dev->si_drv1;
- fdu = fd->fdu;
- if (fd->options & FDOPT_NORETRY)
- goto fail;
-
- switch (fdc->retry) {
- case 0: case 1: case 2:
- fdc->state = SEEKCOMPLETE;
- break;
- case 3: case 4: case 5:
- fdc->state = STARTRECAL;
- break;
- case 6:
- fdc->state = RESETCTLR;
- break;
- case 7:
- break;
- default:
- fail:
- if ((fd->options & FDOPT_NOERRLOG) == 0) {
- disk_err(bp, "hard error",
- fdc->fd->skip / DEV_BSIZE, 0);
- if (fdc->flags & FDC_STAT_VALID) {
- printf(
- " (ST0 %b ST1 %b ST2 %b cyl %u hd %u sec %u)\n",
- fdc->status[0], NE7_ST0BITS,
- fdc->status[1], NE7_ST1BITS,
- fdc->status[2], NE7_ST2BITS,
- fdc->status[3], fdc->status[4],
- fdc->status[5]);
- }
- else
- printf(" (No status)\n");
- }
- if ((fd->options & FDOPT_NOERROR) == 0) {
- bp->bio_flags |= BIO_ERROR;
- bp->bio_error = EIO;
- bp->bio_resid = bp->bio_bcount - fdc->fd->skip;
- } else
- bp->bio_resid = 0;
- fdc->bp = NULL;
- fdc->fd->skip = 0;
- device_unbusy(fd->dev);
- biofinish(bp, fdc->fd->device_stats, 0);
- fdc->state = FINDWORK;
- fdc->flags |= FDC_NEEDS_RESET;
- fdc->fd = (fd_p) 0;
- fdc->fdu = -1;
- return (1);
- }
- fdc->retry++;
- return (1);
-}
-
-static void
-fdbiodone(struct bio *bp)
-{
- wakeup(bp);
-}
-
-static int
-fdmisccmd(struct cdev *dev, u_int cmd, void *data)
-{
- fdu_t fdu;
- fd_p fd;
- struct bio *bp;
- struct fd_formb *finfo;
- struct fdc_readid *idfield;
- size_t fdblk;
- int error;
-
- fd = dev->si_drv1;
- fdu = fd->fdu;
- fdblk = 128 << fd->ft->secsize;
- finfo = (struct fd_formb *)data;
- idfield = (struct fdc_readid *)data;
-
- bp = malloc(sizeof(struct bio), M_TEMP, M_WAITOK | M_ZERO);
-
- /*
- * Set up a bio request for fdstrategy(). bio_offset is faked
- * so that fdstrategy() will seek to the requested
- * cylinder, and use the desired head.
- */
- bp->bio_cmd = cmd;
- if (cmd == FDBIO_FORMAT) {
- bp->bio_offset =
- (finfo->cyl * (fd->ft->sectrac * fd->ft->heads) +
- finfo->head * fd->ft->sectrac) * fdblk;
- bp->bio_bcount = sizeof(struct fd_idfield_data) *
- finfo->fd_formb_nsecs;
- } else if (cmd == FDBIO_RDSECTID) {
- bp->bio_offset =
- (idfield->cyl * (fd->ft->sectrac * fd->ft->heads) +
- idfield->head * fd->ft->sectrac) * fdblk;
- bp->bio_bcount = sizeof(struct fdc_readid);
- } else
- panic("wrong cmd in fdmisccmd()");
- bp->bio_data = data;
- bp->bio_dev = dev;
- bp->bio_done = fdbiodone;
- bp->bio_flags = 0;
-
- /* Now run the command. */
- fdstrategy(bp);
- error = biowait(bp, "fdcmd");
-
- free(bp, M_TEMP);
- return (error);
-}
-
-static int
-fdioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
-{
- fdu_t fdu;
- fd_p fd;
- struct fdc_status *fsp;
- struct fdc_readid *rid;
- int error;
-
- fd = dev->si_drv1;
- fdu = fd->fdu;
-
-#ifdef PC98
- pc98_fd_check_ready(fdu);
-#endif
-
- /*
- * First, handle everything that could be done with
- * FD_NONBLOCK still being set.
- */
- switch (cmd) {
-
- case DIOCGMEDIASIZE:
- if (fd->ft == 0)
- return ((fd->flags & FD_NONBLOCK) ? EAGAIN : ENXIO);
- *(off_t *)addr = (128 << (fd->ft->secsize)) * fd->ft->size;
- return (0);
-
- case DIOCGSECTORSIZE:
- if (fd->ft == 0)
- return ((fd->flags & FD_NONBLOCK) ? EAGAIN : ENXIO);
- *(u_int *)addr = 128 << (fd->ft->secsize);
- return (0);
-
- case FIONBIO:
- if (*(int *)addr != 0)
- fd->flags |= FD_NONBLOCK;
- else {
- if (fd->ft == 0) {
- /*
- * No drive type has been selected yet,
- * cannot turn FNONBLOCK off.
- */
- return (EINVAL);
- }
- fd->flags &= ~FD_NONBLOCK;
- }
- return (0);
-
- case FIOASYNC:
- /* keep the generic fcntl() code happy */
- return (0);
-
- case FD_GTYPE: /* get drive type */
- if (fd->ft == 0)
- /* no type known yet, return the native type */
- *(struct fd_type *)addr = fd_native_types[fd->type];
- else
- *(struct fd_type *)addr = *fd->ft;
- return (0);
-
- case FD_STYPE: /* set drive type */
- /*
- * Allow setting drive type temporarily iff
- * currently unset. Used for fdformat so any
- * user can set it, and then start formatting.
- */
- if (fd->ft)
- return (EINVAL); /* already set */
- fd->fts[0] = *(struct fd_type *)addr;
- fd->ft = &fd->fts[0];
- fd->flags |= FD_UA;
- return (0);
-
- case FD_GOPTS: /* get drive options */
- *(int *)addr = fd->options + FDOPT_AUTOSEL;
- return (0);
-
- case FD_SOPTS: /* set drive options */
- fd->options = *(int *)addr & ~FDOPT_AUTOSEL;
- return (0);
-
-#ifdef FDC_DEBUG
- case FD_DEBUG:
- if ((fd_debug != 0) != (*(int *)addr != 0)) {
- fd_debug = (*(int *)addr != 0);
- printf("fd%d: debugging turned %s\n",
- fd->fdu, fd_debug ? "on" : "off");
- }
- return (0);
-#endif
-
- case FD_CLRERR:
- if (priv_check(td, PRIV_DRIVER) != 0)
- return (EPERM);
- fd->fdc->fdc_errs = 0;
- return (0);
-
- case FD_GSTAT:
- fsp = (struct fdc_status *)addr;
- if ((fd->fdc->flags & FDC_STAT_VALID) == 0)
- return (EINVAL);
- memcpy(fsp->status, fd->fdc->status, 7 * sizeof(u_int));
- return (0);
-
- case FD_GDTYPE:
- *(enum fd_drivetype *)addr = fd->type;
- return (0);
- }
-
- /*
- * Now handle everything else. Make sure we have a valid
- * drive type.
- */
- if (fd->flags & FD_NONBLOCK)
- return (EAGAIN);
- if (fd->ft == 0)
- return (ENXIO);
- error = 0;
-
- switch (cmd) {
-
- case FD_FORM:
- if ((flag & FWRITE) == 0)
- return (EBADF); /* must be opened for writing */
- if (((struct fd_formb *)addr)->format_version !=
- FD_FORMAT_VERSION)
- return (EINVAL); /* wrong version of formatting prog */
- error = fdmisccmd(dev, FDBIO_FORMAT, addr);
- break;
-
- case FD_GTYPE: /* get drive type */
- *(struct fd_type *)addr = *fd->ft;
- break;
-
- case FD_STYPE: /* set drive type */
- /* this is considered harmful; only allow for superuser */
- if (priv_check(td, PRIV_DRIVER) != 0)
- return (EPERM);
- *fd->ft = *(struct fd_type *)addr;
- break;
-
- case FD_GOPTS: /* get drive options */
- *(int *)addr = fd->options;
- break;
-
- case FD_SOPTS: /* set drive options */
- fd->options = *(int *)addr;
- break;
-
-#ifdef FDC_DEBUG
- case FD_DEBUG:
- if ((fd_debug != 0) != (*(int *)addr != 0)) {
- fd_debug = (*(int *)addr != 0);
- printf("fd%d: debugging turned %s\n",
- fd->fdu, fd_debug ? "on" : "off");
- }
- break;
-#endif
-
- case FD_CLRERR:
- if (priv_check(td, PRIV_DRIVER) != 0)
- return (EPERM);
- fd->fdc->fdc_errs = 0;
- break;
-
- case FD_GSTAT:
- fsp = (struct fdc_status *)addr;
- if ((fd->fdc->flags & FDC_STAT_VALID) == 0)
- return (EINVAL);
- memcpy(fsp->status, fd->fdc->status, 7 * sizeof(u_int));
- break;
-
- case FD_READID:
- rid = (struct fdc_readid *)addr;
- if (rid->cyl > MAX_CYLINDER || rid->head > MAX_HEAD)
- return (EINVAL);
- error = fdmisccmd(dev, FDBIO_RDSECTID, addr);
- break;
-
- default:
- error = ENOTTY;
- break;
- }
- return (error);
-}
diff --git a/sys/pc98/cbus/fdcreg.h b/sys/pc98/cbus/fdcreg.h
deleted file mode 100644
index 6d8e7e1..0000000
--- a/sys/pc98/cbus/fdcreg.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*-
- * Copyright (c) 1991 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.
- *
- * from: @(#)fdreg.h 7.1 (Berkeley) 5/9/91
- * $FreeBSD$
- */
-
-/*
- * AT floppy controller registers and bitfields
- */
-
-/* uses NEC765 controller */
-#include <dev/ic/nec765.h>
-
-#ifdef PC98
-/* registers */
-#define FDSTS 0 /* NEC 765 Main Status Register (R) */
-#define FDDATA 1 /* NEC 765 Data Register (R/W) */
-#define FDCTL 2 /* FD Control Register */
-#define FDC_RST 0x80 /* FDC RESET */
-#define FDC_RDY 0x40 /* force READY */
-#define FDC_DD 0x20 /* FDD Mode Exchange 0:1M 1:640K */
-#define FDC_DMAE 0x10 /* enable floppy DMA */
-#define FDC_MTON 0x08 /* MOTOR ON (when EMTON=1)*/
-#define FDC_TMSK 0x04 /* TIMER MASK */
-#define FDC_TTRG 0x01 /* TIMER TRIGER */
-
-#define FDP_EMTON 0x04 /* enable MTON */
-#define FDP_FDDEXC 0x02 /* FDD Mode Exchange 1:1M 0:640K */
-#define FDP_PORTEXC 0x01 /* PORT Exchane 1:1M 0:640K */
-
-#else
-/* registers */
-#define FDOUT 2 /* Digital Output Register (W) */
-#define FDO_FDSEL 0x03 /* floppy device select */
-#define FDO_FRST 0x04 /* floppy controller reset */
-#define FDO_FDMAEN 0x08 /* enable floppy DMA and Interrupt */
-#define FDO_MOEN0 0x10 /* motor enable drive 0 */
-#define FDO_MOEN1 0x20 /* motor enable drive 1 */
-#define FDO_MOEN2 0x40 /* motor enable drive 2 */
-#define FDO_MOEN3 0x80 /* motor enable drive 3 */
-
-#define FDSTS 4 /* NEC 765 Main Status Register (R) */
-#define FDDATA 5 /* NEC 765 Data Register (R/W) */
-#define FDCTL 7 /* Control Register (W) */
-#endif /* PC98 */
-
-/*
- * The definitions for FDC_500KBPS etc. have been moved out to <sys/fdcio.h>
- * since they need to be visible in userland. They cover the lower two bits
- * of FDCTL when used for output.
- */
-/*
- * this is the secret PIO data port (offset from base)
- */
-#define FDC_YE_DATAPORT 6
-
-#ifndef PC98
-#define FDIN 7 /* Digital Input Register (R) */
-#define FDI_DCHG 0x80 /* diskette has been changed */
- /* requires drive and motor being selected */
- /* is cleared by any step pulse to drive */
-#endif
diff --git a/sys/pc98/cbus/fdcvar.h b/sys/pc98/cbus/fdcvar.h
deleted file mode 100644
index 4ae53d9..0000000
--- a/sys/pc98/cbus/fdcvar.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/*-
- * Copyright (c) 2004 M. Warner Losh.
- * 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,
- * without modification, immediately at the beginning of the file.
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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$
- */
-
-/* XXX should audit this file to see if additional copyrights needed */
-
-enum fdc_type
-{
- FDC_NE765, FDC_ENHANCED, FDC_UNKNOWN = -1
-};
-
-enum fdc_states {
- DEVIDLE,
- FINDWORK,
- DOSEEK,
- SEEKCOMPLETE ,
- IOCOMPLETE,
- RECALCOMPLETE,
- STARTRECAL,
- RESETCTLR,
- SEEKWAIT,
- RECALWAIT,
- MOTORWAIT,
- IOTIMEDOUT,
- RESETCOMPLETE,
- PIOREAD
-};
-
-#ifdef FDC_DEBUG
-static char const * const fdstates[] = {
- "DEVIDLE",
- "FINDWORK",
- "DOSEEK",
- "SEEKCOMPLETE",
- "IOCOMPLETE",
- "RECALCOMPLETE",
- "STARTRECAL",
- "RESETCTLR",
- "SEEKWAIT",
- "RECALWAIT",
- "MOTORWAIT",
- "IOTIMEDOUT",
- "RESETCOMPLETE",
- "PIOREAD"
-};
-#endif
-
-/*
- * Per controller structure (softc).
- */
-struct fdc_data
-{
- int fdcu; /* our unit number */
- int dmacnt;
- int dmachan;
- int flags;
-#define FDC_STAT_VALID 0x08
-#define FDC_HAS_FIFO 0x10
-#define FDC_NEEDS_RESET 0x20
-#define FDC_NODMA 0x40
-#define FDC_ISPNP 0x80
-#define FDC_ISPCMCIA 0x100
- struct fd_data *fd;
- int fdu; /* the active drive */
- enum fdc_states state;
- int retry;
-#ifndef PC98
- int fdout; /* mirror of the w/o digital output reg */
-#endif
- u_int status[7]; /* copy of the registers */
- enum fdc_type fdct; /* chip version of FDC */
- int fdc_errs; /* number of logged errors */
- int dma_overruns; /* number of DMA overruns */
- struct bio_queue_head head;
- struct bio *bp; /* active buffer */
-#ifdef PC98
- struct resource *res_ioport, *res_fdsio, *res_fdemsio;
- struct resource *res_irq, *res_drq;
- int rid_ioport, rid_irq, rid_drq;
-#else
- struct resource *res_ioport, *res_ctl, *res_irq, *res_drq;
- int rid_ioport, rid_ctl, rid_irq, rid_drq;
-#endif
- int port_off;
- bus_space_tag_t portt;
- bus_space_handle_t porth;
-#ifdef PC98
- bus_space_tag_t sc_fdsiot;
- bus_space_handle_t sc_fdsioh;
- bus_space_tag_t sc_fdemsiot;
- bus_space_handle_t sc_fdemsioh;
-#else
- bus_space_tag_t ctlt;
- bus_space_handle_t ctlh;
-#endif
- void *fdc_intr;
- struct device *fdc_dev;
-#ifndef PC98
- void (*fdctl_wr)(struct fdc_data *fdc, u_int8_t v);
-#endif
-};
-
-typedef int fdu_t;
-typedef int fdcu_t;
-typedef int fdsu_t;
-typedef struct fd_data *fd_p;
-typedef struct fdc_data *fdc_p;
-typedef enum fdc_type fdc_t;
-
-/* error returns for fd_cmd() */
-#define FD_FAILED -1
-#define FD_NOT_VALID -2
-#define FDC_ERRMAX 100 /* do not log more */
-
-extern devclass_t fdc_devclass;
-
-enum fdc_device_ivars {
- FDC_IVAR_FDUNIT,
- FDC_IVAR_FDTYPE,
-};
-
-__BUS_ACCESSOR(fdc, fdunit, FDC, FDUNIT, int);
-__BUS_ACCESSOR(fdc, fdtype, FDC, FDTYPE, int);
-
-int fdc_alloc_resources(struct fdc_data *);
-#ifndef PC98
-void fdout_wr(fdc_p, u_int8_t);
-#endif
-int fd_cmd(struct fdc_data *, int, ...);
-void fdc_release_resources(struct fdc_data *);
-int fdc_attach(device_t);
-int fdc_hints_probe(device_t);
-int fdc_detach(device_t dev);
-device_t fdc_add_child(device_t, const char *, int);
-int fdc_initial_reset(struct fdc_data *);
-int fdc_print_child(device_t, device_t);
-int fdc_read_ivar(device_t, device_t, int, uintptr_t *);
-int fdc_write_ivar(device_t, device_t, int, uintptr_t);
-#ifndef PC98
-int fdc_isa_alloc_resources(device_t, struct fdc_data *);
-#endif
diff --git a/sys/pc98/cbus/olpt.c b/sys/pc98/cbus/olpt.c
index 2423d6e..9aa8212 100644
--- a/sys/pc98/cbus/olpt.c
+++ b/sys/pc98/cbus/olpt.c
@@ -140,6 +140,7 @@ struct lpt_softc {
struct resource *res_port;
struct resource *res_irq;
void *sc_ih;
+ struct callout timer;
int sc_port;
short sc_state;
@@ -319,6 +320,7 @@ lpt_attach(device_t dev)
unit = device_get_unit(dev);
sc = device_get_softc(dev);
+ callout_init(&sc->timer, 0);
rid = 0;
sc->res_port = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid,
@@ -418,8 +420,8 @@ lptopen (struct cdev *dev, int flags, int fmt, struct thread *td)
lprintf(("irq %x\n", sc->sc_irq));
if (sc->sc_irq & LP_USE_IRQ) {
sc->sc_state |= TOUT;
- timeout (lptout, (caddr_t)sc,
- (sc->sc_backoff = hz/LPTOUTINITIAL));
+ sc->sc_backoff = hz / LPTOUTINITIAL;;
+ callout_reset(&sc->timer, sc->sc_backoff, lptout, sc);
}
lprintf(("opened.\n"));
@@ -437,7 +439,7 @@ lptout (void *arg)
sc->sc_backoff++;
if (sc->sc_backoff > hz/LPTOUTMAX)
sc->sc_backoff = sc->sc_backoff > hz/LPTOUTMAX;
- timeout (lptout, (caddr_t)sc, sc->sc_backoff);
+ callout_reset(&sc->timer, sc->sc_backoff, lptout, sc);
} else
sc->sc_state &= ~TOUT;
diff --git a/sys/pc98/cbus/pckbd.c b/sys/pc98/cbus/pckbd.c
index e424294..92331b6 100644
--- a/sys/pc98/cbus/pckbd.c
+++ b/sys/pc98/cbus/pckbd.c
@@ -52,6 +52,19 @@
/* device configuration flags */
#define KB_CONF_FAIL_IF_NO_KBD (1 << 0) /* don't install if no kbd is found */
+typedef caddr_t KBDC;
+
+typedef struct pckbd_state {
+ KBDC kbdc; /* keyboard controller */
+ int ks_mode; /* input mode (K_XLATE,K_RAW,K_CODE) */
+ int ks_flags; /* flags */
+#define COMPOSE (1 << 0)
+ int ks_state; /* shift/lock key state */
+ int ks_accents; /* accent key index (> 0) */
+ u_int ks_composed_char; /* composed char code (> 0) */
+ struct callout ks_timer;
+} pckbd_state_t;
+
static devclass_t pckbd_devclass;
static int pckbdprobe(device_t dev);
@@ -186,6 +199,7 @@ static int
pckbd_attach_unit(device_t dev, keyboard_t **kbd, int port, int irq, int flags)
{
keyboard_switch_t *sw;
+ pckbd_state_t *state;
int args[2];
int error;
int unit;
@@ -218,6 +232,8 @@ pckbd_attach_unit(device_t dev, keyboard_t **kbd, int port, int irq, int flags)
* This is a kludge to compensate for lost keyboard interrupts.
* A similar code used to be in syscons. See below. XXX
*/
+ state = (pckbd_state_t *)(*kbd)->kb_data;
+ callout_init(&state->ks_timer, 0);
pckbd_timeout(*kbd);
if (bootverbose)
@@ -229,6 +245,7 @@ pckbd_attach_unit(device_t dev, keyboard_t **kbd, int port, int irq, int flags)
static void
pckbd_timeout(void *arg)
{
+ pckbd_state_t *state;
keyboard_t *kbd;
int s;
@@ -259,7 +276,8 @@ pckbd_timeout(void *arg)
kbdd_intr(kbd, NULL);
}
splx(s);
- timeout(pckbd_timeout, arg, hz/10);
+ state = (pckbd_state_t *)kbd->kb_data;
+ callout_reset(&state->ks_timer, hz / 10, pckbd_timeout, arg);
}
/* LOW-LEVEL */
@@ -268,18 +286,6 @@ pckbd_timeout(void *arg)
#define PC98KBD_DEFAULT 0
-typedef caddr_t KBDC;
-
-typedef struct pckbd_state {
- KBDC kbdc; /* keyboard controller */
- int ks_mode; /* input mode (K_XLATE,K_RAW,K_CODE) */
- int ks_flags; /* flags */
-#define COMPOSE (1 << 0)
- int ks_state; /* shift/lock key state */
- int ks_accents; /* accent key index (> 0) */
- u_int ks_composed_char; /* composed char code (> 0) */
-} pckbd_state_t;
-
/* keyboard driver declaration */
static int pckbd_configure(int flags);
static kbd_probe_t pckbd_probe;
@@ -486,7 +492,10 @@ pckbd_init(int unit, keyboard_t **kbdp, void *arg, int flags)
static int
pckbd_term(keyboard_t *kbd)
{
+ pckbd_state_t *state = (pckbd_state_t *)kbd->kb_data;
+
kbd_unregister(kbd);
+ callout_drain(&state->ks_timer);
return 0;
}
diff --git a/sys/pc98/pc98/machdep.c b/sys/pc98/pc98/machdep.c
index c42b4ce..848af79 100644
--- a/sys/pc98/pc98/machdep.c
+++ b/sys/pc98/pc98/machdep.c
@@ -169,10 +169,6 @@ SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL);
int need_pre_dma_flush; /* If 1, use wbinvd befor DMA transfer. */
int need_post_dma_flush; /* If 1, use invd after DMA transfer. */
-#ifdef DDB
-extern vm_offset_t ksym_start, ksym_end;
-#endif
-
int _udatasel, _ucodesel;
u_int basemem;
@@ -2298,8 +2294,7 @@ init386(first)
#endif
#ifdef DDB
- ksym_start = bootinfo.bi_symtab;
- ksym_end = bootinfo.bi_esymtab;
+ db_fetch_ksymtab(bootinfo.bi_symtab,bootinfo.bi_esymtab);
#endif
kdb_init();
diff --git a/sys/powerpc/aim/locore64.S b/sys/powerpc/aim/locore64.S
index 65c4999..0c26e01 100644
--- a/sys/powerpc/aim/locore64.S
+++ b/sys/powerpc/aim/locore64.S
@@ -160,6 +160,7 @@ ASENTRY_NOPROF(__start)
li 8,1
insrdi 9,8,1,0
mtmsrd 9
+ isync
bl OF_initial_setup
nop
diff --git a/sys/powerpc/aim/machdep.c b/sys/powerpc/aim/machdep.c
index 16b2290..17fc452 100644
--- a/sys/powerpc/aim/machdep.c
+++ b/sys/powerpc/aim/machdep.c
@@ -129,10 +129,6 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/openfirm.h>
-#ifdef DDB
-extern vm_offset_t ksym_start, ksym_end;
-#endif
-
int cold = 1;
#ifdef __powerpc64__
extern int n_slbs;
@@ -268,6 +264,10 @@ powerpc_init(vm_offset_t startkernel, vm_offset_t endkernel,
#ifndef __powerpc64__
int ppc64;
#endif
+#ifdef DDB
+ vm_offset_t ksym_start;
+ vm_offset_t ksym_end;
+#endif
kmdp = NULL;
trap_offset = 0;
@@ -302,6 +302,7 @@ powerpc_init(vm_offset_t startkernel, vm_offset_t endkernel,
#ifdef DDB
ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t);
ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t);
+ db_fetch_ksymtab(ksym_start, ksym_end);
#endif
}
}
diff --git a/sys/powerpc/booke/machdep.c b/sys/powerpc/booke/machdep.c
index fc98ed6..d3de34c 100644
--- a/sys/powerpc/booke/machdep.c
+++ b/sys/powerpc/booke/machdep.c
@@ -142,7 +142,7 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/openfirm.h>
#ifdef DDB
-extern vm_offset_t ksym_start, ksym_end;
+#include <ddb/ddb.h>
#endif
#ifdef DEBUG
@@ -300,6 +300,10 @@ booke_init(uint32_t arg1, uint32_t arg2)
struct pcpu *pc;
void *kmdp, *mdp;
vm_offset_t dtbp, end;
+#ifdef DDB
+ vm_offset_t ksym_start;
+ vm_offset_t ksym_end;
+#endif
kmdp = NULL;
@@ -360,6 +364,7 @@ booke_init(uint32_t arg1, uint32_t arg2)
#ifdef DDB
ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t);
ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t);
+ db_fetch_ksymtab(ksym_start, ksym_end);
#endif
}
} else {
diff --git a/sys/powerpc/ofw/ofw_pcibus.c b/sys/powerpc/ofw/ofw_pcibus.c
index aa943ac..66fa341 100644
--- a/sys/powerpc/ofw/ofw_pcibus.c
+++ b/sys/powerpc/ofw/ofw_pcibus.c
@@ -200,29 +200,8 @@ ofw_pcibus_enum_devtree(device_t dev, u_int domain, u_int busno)
* interrupts property, so add that value to the device's
* resource list.
*/
- if (dinfo->opd_dinfo.cfg.intpin == 0) {
- ofw_pci_intr_t intr[2];
- phandle_t iparent;
- int icells;
-
- if (OF_getprop(child, "interrupts", &intr,
- sizeof(intr)) > 0) {
- iparent = 0;
- icells = 1;
- OF_getprop(child, "interrupt-parent", &iparent,
- sizeof(iparent));
- if (iparent != 0) {
- OF_getprop(OF_node_from_xref(iparent),
- "#interrupt-cells", &icells,
- sizeof(icells));
- intr[0] = ofw_bus_map_intr(dev, iparent,
- icells, intr);
- }
-
- resource_list_add(&dinfo->opd_dinfo.resources,
- SYS_RES_IRQ, 0, intr[0], intr[0], 1);
- }
- }
+ if (dinfo->opd_dinfo.cfg.intpin == 0)
+ ofw_bus_intr_to_rl(dev, child, &dinfo->opd_dinfo.resources);
}
}
diff --git a/sys/powerpc/pseries/vdevice.c b/sys/powerpc/pseries/vdevice.c
index d2c399b..8dadd63 100644
--- a/sys/powerpc/pseries/vdevice.c
+++ b/sys/powerpc/pseries/vdevice.c
@@ -128,8 +128,6 @@ vdevice_attach(device_t dev)
{
phandle_t root, child;
device_t cdev;
- int icells, i, nintr, *intr;
- phandle_t iparent;
struct vdevice_devinfo *dinfo;
root = ofw_bus_get_node(dev);
@@ -144,25 +142,7 @@ vdevice_attach(device_t dev)
}
resource_list_init(&dinfo->mdi_resources);
- if (OF_searchprop(child, "#interrupt-cells", &icells,
- sizeof(icells)) <= 0)
- icells = 2;
- if (OF_getprop(child, "interrupt-parent", &iparent,
- sizeof(iparent)) <= 0)
- iparent = -1;
- nintr = OF_getprop_alloc(child, "interrupts", sizeof(*intr),
- (void **)&intr);
- if (nintr > 0) {
- for (i = 0; i < nintr; i += icells) {
- u_int irq = intr[i];
- if (iparent != -1)
- irq = ofw_bus_map_intr(dev, iparent,
- icells, &intr[i]);
-
- resource_list_add(&dinfo->mdi_resources,
- SYS_RES_IRQ, i, irq, irq, i);
- }
- }
+ ofw_bus_intr_to_rl(dev, child, &dinfo->mdi_resources);
cdev = device_add_child(dev, NULL, -1);
if (cdev == NULL) {
diff --git a/sys/sparc64/sparc64/machdep.c b/sys/sparc64/sparc64/machdep.c
index 587c908..0ee6de3 100644
--- a/sys/sparc64/sparc64/machdep.c
+++ b/sys/sparc64/sparc64/machdep.c
@@ -114,10 +114,6 @@ __FBSDID("$FreeBSD$");
typedef int ofw_vec_t(void *);
-#ifdef DDB
-extern vm_offset_t ksym_start, ksym_end;
-#endif
-
int dtlb_slots;
int itlb_slots;
struct tlb_entry *kernel_tlbs;
diff --git a/sys/sys/bus.h b/sys/sys/bus.h
index 86bd40a..f457905 100644
--- a/sys/sys/bus.h
+++ b/sys/sys/bus.h
@@ -339,6 +339,7 @@ int bus_generic_read_ivar(device_t dev, device_t child, int which,
int bus_generic_release_resource(device_t bus, device_t child,
int type, int rid, struct resource *r);
int bus_generic_resume(device_t dev);
+int bus_generic_resume_child(device_t dev, device_t child);
int bus_generic_setup_intr(device_t dev, device_t child,
struct resource *irq, int flags,
driver_filter_t *filter, driver_intr_t *intr,
@@ -357,6 +358,7 @@ int bus_generic_rl_release_resource (device_t, device_t, int, int,
int bus_generic_shutdown(device_t dev);
int bus_generic_suspend(device_t dev);
+int bus_generic_suspend_child(device_t dev, device_t child);
int bus_generic_teardown_intr(device_t dev, device_t child,
struct resource *irq, void *cookie);
int bus_generic_write_ivar(device_t dev, device_t child, int which,
diff --git a/sys/sys/file.h b/sys/sys/file.h
index 92f125f..e593d43 100644
--- a/sys/sys/file.h
+++ b/sys/sys/file.h
@@ -43,6 +43,7 @@
#include <sys/_lock.h>
#include <sys/_mutex.h>
+struct filedesc;
struct stat;
struct thread;
struct uio;
@@ -70,6 +71,7 @@ struct socket;
struct file;
struct filecaps;
+struct kinfo_file;
struct ucred;
#define FOF_OFFSET 0x01 /* Use the offset in uio argument */
@@ -114,6 +116,8 @@ typedef int fo_sendfile_t(struct file *fp, int sockfd, struct uio *hdr_uio,
struct sendfile_sync *sfs, struct thread *td);
typedef int fo_seek_t(struct file *fp, off_t offset, int whence,
struct thread *td);
+typedef int fo_fill_kinfo_t(struct file *fp, struct kinfo_file *kif,
+ struct filedesc *fdp);
typedef int fo_flags_t;
struct fileops {
@@ -129,6 +133,7 @@ struct fileops {
fo_chown_t *fo_chown;
fo_sendfile_t *fo_sendfile;
fo_seek_t *fo_seek;
+ fo_fill_kinfo_t *fo_fill_kinfo;
fo_flags_t fo_flags; /* DFLAG_* below */
};
@@ -242,6 +247,8 @@ fo_sendfile_t invfo_sendfile;
fo_sendfile_t vn_sendfile;
fo_seek_t vn_seek;
+fo_fill_kinfo_t vn_fill_kinfo;
+int vn_fill_kinfo_vnode(struct vnode *vp, struct kinfo_file *kif);
void finit(struct file *, u_int, short, void *, struct fileops *);
int fgetvp(struct thread *td, int fd, cap_rights_t *rightsp,
@@ -378,6 +385,13 @@ fo_seek(struct file *fp, off_t offset, int whence, struct thread *td)
return ((*fp->f_ops->fo_seek)(fp, offset, whence, td));
}
+static __inline int
+fo_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
+{
+
+ return ((*fp->f_ops->fo_fill_kinfo)(fp, kif, fdp));
+}
+
#endif /* _KERNEL */
#endif /* !SYS_FILE_H */
diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h
index d407cd2..9d23662 100644
--- a/sys/sys/filedesc.h
+++ b/sys/sys/filedesc.h
@@ -109,11 +109,6 @@ struct filedesc_to_leader {
#ifdef _KERNEL
-/* Flags for do_dup() */
-#define DUP_FIXED 0x1 /* Force fixed allocation. */
-#define DUP_FCNTL 0x2 /* fcntl()-style errors. */
-#define DUP_CLOEXEC 0x4 /* Atomically set FD_CLOEXEC. */
-
/* Lock a file descriptor table. */
#define FILEDESC_LOCK_INIT(fdp) sx_init(&(fdp)->fd_sx, "filedesc structure")
#define FILEDESC_LOCK_DESTROY(fdp) sx_destroy(&(fdp)->fd_sx)
@@ -137,8 +132,6 @@ void filecaps_move(struct filecaps *src, struct filecaps *dst);
void filecaps_free(struct filecaps *fcaps);
int closef(struct file *fp, struct thread *td);
-int do_dup(struct thread *td, int flags, int old, int new,
- register_t *retval);
int dupfdopen(struct thread *td, struct filedesc *fdp, int dfd, int mode,
int openerror, int *indxp);
int falloc(struct thread *td, struct file **resultfp, int *resultfd,
diff --git a/sys/sys/ksem.h b/sys/sys/ksem.h
index c11c865..b337a2b 100644
--- a/sys/sys/ksem.h
+++ b/sys/sys/ksem.h
@@ -63,9 +63,4 @@ struct ksem {
#define KS_ANONYMOUS 0x0001 /* Anonymous (unnamed) semaphore. */
#define KS_DEAD 0x0002 /* No new waiters allowed. */
-#ifdef _KERNEL
-extern void (*ksem_info)(struct ksem *ks, char *path, size_t size,
- uint32_t *value);
-#endif
-
#endif /* !_POSIX4_KSEM_H_ */
diff --git a/sys/sys/mman.h b/sys/sys/mman.h
index a13e3d1..f0e01b6 100644
--- a/sys/sys/mman.h
+++ b/sys/sys/mman.h
@@ -234,7 +234,6 @@ int shm_mmap(struct shmfd *shmfd, vm_size_t objsize, vm_ooffset_t foff,
vm_object_t *obj);
int shm_map(struct file *fp, size_t size, off_t offset, void **memp);
int shm_unmap(struct file *fp, void *mem, size_t size);
-void shm_path(struct shmfd *shmfd, char *path, size_t size);
#else /* !_KERNEL */
diff --git a/sys/sys/sleepqueue.h b/sys/sys/sleepqueue.h
index dcb1b48..cdb7a39 100644
--- a/sys/sys/sleepqueue.h
+++ b/sys/sys/sleepqueue.h
@@ -46,13 +46,6 @@
* call sleepq_set_timeout() after sleepq_add() to setup a timeout. It
* should then use one of the sleepq_timedwait() functions to block.
*
- * If the thread wants the sleep to be interruptible by signals, it can
- * call sleepq_catch_signals() after sleepq_add(). It should then use
- * one of the sleepq_wait_sig() functions to block. After the thread has
- * been resumed, it should call sleepq_calc_signal_retval() to determine
- * if it should return EINTR or ERESTART passing in the value returned from
- * the earlier call to sleepq_catch_signals().
- *
* A thread is normally resumed from a sleep queue by either the
* sleepq_signal() or sleepq_broadcast() functions. Sleepq_signal() wakes
* the thread with the highest priority that is sleeping on the specified
diff --git a/sys/sys/sockbuf.h b/sys/sys/sockbuf.h
index 877b530..ef80e9c 100644
--- a/sys/sys/sockbuf.h
+++ b/sys/sys/sockbuf.h
@@ -158,6 +158,8 @@ int sbreserve_locked(struct sockbuf *sb, u_long cc, struct socket *so,
struct thread *td);
struct mbuf *
sbsndptr(struct sockbuf *sb, u_int off, u_int len, u_int *moff);
+struct mbuf *
+ sbsndmbuf(struct sockbuf *sb, u_int off, u_int *moff);
void sbtoxsockbuf(struct sockbuf *sb, struct xsockbuf *xsb);
int sbwait(struct sockbuf *sb);
int sblock(struct sockbuf *sb, int flags);
diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h
index bc447ab..05e9be8 100644
--- a/sys/sys/syscallsubr.h
+++ b/sys/sys/syscallsubr.h
@@ -97,6 +97,7 @@ int kern_fchmodat(struct thread *td, int fd, char *path,
int kern_fchownat(struct thread *td, int fd, char *path,
enum uio_seg pathseg, int uid, int gid, int flag);
int kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg);
+int kern_fcntl_freebsd(struct thread *td, int fd, int cmd, long arg);
int kern_fhstat(struct thread *td, fhandle_t fh, struct stat *buf);
int kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf);
int kern_fstat(struct thread *td, int fd, struct stat *sbp);
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index 50929f6..b8d67bd 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -2197,7 +2197,14 @@ vm_map_madvise(
vm_object_madvise(current->object.vm_object, pstart,
pend, behav);
- if (behav == MADV_WILLNEED) {
+
+ /*
+ * Pre-populate paging structures in the
+ * WILLNEED case. For wired entries, the
+ * paging structures are already populated.
+ */
+ if (behav == MADV_WILLNEED &&
+ current->wired_count == 0) {
vm_map_pmap_enter(map,
useStart,
current->protection,
diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c
index 9835d8d..24b9f6d 100644
--- a/sys/vm/vm_pageout.c
+++ b/sys/vm/vm_pageout.c
@@ -916,7 +916,7 @@ vm_pageout_scan(struct vm_domain *vmd, int pass)
* some. We rate limit to avoid thrashing.
*/
if (vmd == &vm_dom[0] && pass > 0 &&
- lowmem_ticks + (lowmem_period * hz) < ticks) {
+ (ticks - lowmem_ticks) / hz >= lowmem_period) {
/*
* Decrease registered cache sizes.
*/
diff --git a/sys/x86/xen/pv.c b/sys/x86/xen/pv.c
index c98c8bc..ee2cd6b 100644
--- a/sys/x86/xen/pv.c
+++ b/sys/x86/xen/pv.c
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2004 Christian Limpach.
* Copyright (c) 2004-2006,2008 Kip Macy
+ * Copyright (c) 2008 The NetBSD Foundation, Inc.
* Copyright (c) 2013 Roger Pau Monné <roger.pau@citrix.com>
* All rights reserved.
*
@@ -29,12 +30,15 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_ddb.h"
+
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/reboot.h>
#include <sys/systm.h>
#include <sys/malloc.h>
+#include <sys/linker.h>
#include <sys/lock.h>
#include <sys/rwlock.h>
#include <sys/boot.h>
@@ -66,6 +70,10 @@ __FBSDID("$FreeBSD$");
#include <dev/xen/timer/timer.h>
+#ifdef DDB
+#include <ddb/ddb.h>
+#endif
+
/* Native initial function */
extern u_int64_t hammer_time(u_int64_t, u_int64_t);
/* Xen initial function */
@@ -93,6 +101,12 @@ extern int bootAP;
extern char *bootSTK;
#endif
+/*
+ * Placed by the linker at the end of the bss section, which is the last
+ * section loaded by Xen before loading the symtab and strtab.
+ */
+extern uint32_t end;
+
/*-------------------------------- Global Data -------------------------------*/
/* Xen init_ops implementation. */
struct init_ops xen_init_ops = {
@@ -297,6 +311,68 @@ xen_pv_set_boothowto(void)
}
}
+#ifdef DDB
+/*
+ * The way Xen loads the symtab is different from the native boot loader,
+ * because it's tailored for NetBSD. So we have to adapt and use the same
+ * method as NetBSD. Portions of the code below have been picked from NetBSD:
+ * sys/kern/kern_ksyms.c CVS Revision 1.71.
+ */
+static void
+xen_pv_parse_symtab(void)
+{
+ Elf_Ehdr *ehdr;
+ Elf_Shdr *shdr;
+ vm_offset_t sym_end;
+ uint32_t size;
+ int i, j;
+
+ size = end;
+ sym_end = HYPERVISOR_start_info->mod_start != 0 ?
+ HYPERVISOR_start_info->mod_start :
+ HYPERVISOR_start_info->mfn_list;
+
+ /*
+ * Make sure the size is right headed, sym_end is just a
+ * high boundary, but at least allows us to fail earlier.
+ */
+ if ((vm_offset_t)&end + size > sym_end) {
+ xc_printf("Unable to load ELF symtab: size mismatch\n");
+ return;
+ }
+
+ ehdr = (Elf_Ehdr *)(&end + 1);
+ if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) ||
+ ehdr->e_ident[EI_CLASS] != ELF_TARG_CLASS ||
+ ehdr->e_version > 1) {
+ xc_printf("Unable to load ELF symtab: invalid symbol table\n");
+ return;
+ }
+
+ shdr = (Elf_Shdr *)((uint8_t *)ehdr + ehdr->e_shoff);
+ /* Find the symbol table and the corresponding string table. */
+ for (i = 1; i < ehdr->e_shnum; i++) {
+ if (shdr[i].sh_type != SHT_SYMTAB)
+ continue;
+ if (shdr[i].sh_offset == 0)
+ continue;
+ ksymtab = (uintptr_t)((uint8_t *)ehdr + shdr[i].sh_offset);
+ ksymtab_size = shdr[i].sh_size;
+ j = shdr[i].sh_link;
+ if (shdr[j].sh_offset == 0)
+ continue; /* Can this happen? */
+ kstrtab = (uintptr_t)((uint8_t *)ehdr + shdr[j].sh_offset);
+ break;
+ }
+
+ if (ksymtab == 0 || kstrtab == 0) {
+ xc_printf(
+ "Unable to load ELF symtab: could not find symtab or strtab\n");
+ return;
+ }
+}
+#endif
+
static caddr_t
xen_pv_parse_preload_data(u_int64_t modulep)
{
@@ -304,6 +380,10 @@ xen_pv_parse_preload_data(u_int64_t modulep)
xen_pv_set_env();
xen_pv_set_boothowto();
+#ifdef DDB
+ xen_pv_parse_symtab();
+#endif
+
return (NULL);
}
diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc
index faa59cb..a12775b8b 100644
--- a/tools/build/mk/OptionalObsoleteFiles.inc
+++ b/tools/build/mk/OptionalObsoleteFiles.inc
@@ -3510,9 +3510,9 @@ OLD_FILES+=usr/libexec/ssh-pkcs11-helper
OLD_FILES+=usr/sbin/sshd
.endif
-#.if ${MK_OPENSSL} == no
-# to be filled in
-#.endif
+.if ${MK_OPENSSL} == no
+OLD_FILES+=etc/rc.d/keyserv
+.endif
.if ${MK_PC_SYSINSTALL} == no
# backend-partmanager
@@ -3606,6 +3606,7 @@ OLD_DIRS+=usr/share/examples/pc-sysinstall
.if ${MK_PF} == no
OLD_FILES+=etc/periodic/security/520.pfdenied
OLD_FILES+=etc/pf.os
+OLD_FILES+=etc/rc.d/ftp-proxy
OLD_FILES+=sbin/pfctl
OLD_FILES+=sbin/pflogd
OLD_FILES+=usr/libexec/tftp-proxy
@@ -3766,6 +3767,7 @@ OLD_FILES+=usr/lib/private/libssh_p.a
.if ${MK_RCMDS} == no
OLD_FILES+=bin/rcp
+OLD_FILES+=etc/rc.d/rwho
OLD_FILES+=etc/periodic/daily/140.clean-rwho
OLD_FILES+=etc/periodic/daily/430.status-rwho
OLD_FILES+=rescue/rcp
diff --git a/tools/regression/pjdfstest/tests/open/16.t b/tools/regression/pjdfstest/tests/open/16.t
deleted file mode 100644
index a15cd9b..0000000
--- a/tools/regression/pjdfstest/tests/open/16.t
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/sh
-# $FreeBSD$
-
-desc="open returns ELOOP when O_NOFOLLOW was specified and the target is a symbolic link"
-
-dir=`dirname $0`
-. ${dir}/../misc.sh
-
-echo "1..6"
-
-n0=`namegen`
-n1=`namegen`
-
-expect 0 symlink ${n0} ${n1}
-expect ELOOP open ${n1} O_RDONLY,O_CREAT,O_NOFOLLOW 0644
-expect ELOOP open ${n1} O_RDONLY,O_NOFOLLOW
-expect ELOOP open ${n1} O_WRONLY,O_NOFOLLOW
-expect ELOOP open ${n1} O_RDWR,O_NOFOLLOW
-expect 0 unlink ${n1}
diff --git a/tools/test/dtrace/Makefile b/tools/test/dtrace/Makefile
index 012a116..405d536 100644
--- a/tools/test/dtrace/Makefile
+++ b/tools/test/dtrace/Makefile
@@ -85,7 +85,8 @@ IGNORE= \
${TESTSRCDIR}/tst/common/ip/tst.localtcpstate.ksh \
${TESTSRCDIR}/tst/common/ip/tst.remotetcpstate.ksh \
${TESTSRCDIR}/tst/common/scripting/tst.projid.ksh \
- ${TESTSRCDIR}/tst/common/scripting/tst.taskid.ksh
+ ${TESTSRCDIR}/tst/common/scripting/tst.taskid.ksh \
+ ${TESTSRCDIR}/tst/common/json/tst.usdt.c
diff --git a/usr.bin/calendar/calendars/calendar.freebsd b/usr.bin/calendar/calendars/calendar.freebsd
index 9205bd9..fc6df82 100644
--- a/usr.bin/calendar/calendars/calendar.freebsd
+++ b/usr.bin/calendar/calendars/calendar.freebsd
@@ -52,6 +52,7 @@
02/03 Jason Helfman <jgh@FreeBSD.org> born in Royal Oak, Michigan, United States, 1972
02/04 Eitan Adler <eadler@FreeBSD.org> born in West Hempstead, New York, United States, 1991
02/05 Frank Laszlo <laszlof@FreeBSD.org> born in Howell, Michigan, United States, 1983
+02/06 Julien Charbon <jch@FreeBSD.org> born in Saint Etienne, Loire, France, 1978
02/10 David Greenman <dg@FreeBSD.org> born in Portland, Oregon, United States, 1968
02/10 Paul Richards <paul@FreeBSD.org> born in Ammanford, Carmarthenshire, United Kingdom, 1968
02/10 Simon Barner <barner@FreeBSD.org> born in Rosenheim, Bayern, Germany, 1980
diff --git a/usr.bin/grep/regex/tre-fastmatch.c b/usr.bin/grep/regex/tre-fastmatch.c
index eddab26..0881c55 100644
--- a/usr.bin/grep/regex/tre-fastmatch.c
+++ b/usr.bin/grep/regex/tre-fastmatch.c
@@ -727,7 +727,7 @@ badpat:
for (unsigned int i = 0; i < fg->len; i++)
if (fg->pattern[i] == '\\')
escaped = !escaped;
- else if (fg->pattern[i] == '.' && escaped)
+ else if (fg->pattern[i] == '.' && fg->escmap && escaped)
{
fg->escmap[i] = true;
escaped = false;
diff --git a/usr.bin/man/man.1 b/usr.bin/man/man.1
index 4763cc6..7517a64 100644
--- a/usr.bin/man/man.1
+++ b/usr.bin/man/man.1
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd June 3, 2011
+.Dd September 26, 2014
.Dt MAN 1
.Os
.Sh NAME
@@ -58,6 +58,28 @@ is provided,
.Nm
restricts the search to the specific section of the manual.
.Pp
+The sections of the manual are:
+.Bl -enum -offset indent -compact
+.It
+.Fx General Commands Manual
+.It
+.Fx System Calls Manual
+.It
+.Fx Library Functions Manual
+.It
+.Fx Kernel Interfaces Manual
+.It
+.Fx File Formats Manual
+.It
+.Fx Games Manual
+.It
+.Fx Miscellaneous Information Manual
+.It
+.Fx System Manager's Manual
+.It
+.Fx Kernel Developer's Manual
+.El
+.Pp
Options that
.Nm
understands:
@@ -318,6 +340,14 @@ Local configuration files.
.Sh SEE ALSO
.Xr apropos 1 ,
.Xr intro 1 ,
+.Xr intro 2 ,
+.Xr intro 3 ,
+.Xr intro 4 ,
+.Xr intro 5 ,
+.Xr intro 6 ,
+.Xr intro 7 ,
+.Xr intro 8 ,
+.Xr intro 9 ,
.Xr locale 1 ,
.Xr manpath 1 ,
.Xr nroff 1 ,
diff --git a/usr.bin/mkimg/Makefile b/usr.bin/mkimg/Makefile
index b802799..1152ce3 100644
--- a/usr.bin/mkimg/Makefile
+++ b/usr.bin/mkimg/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <src.opts.mk>
+
PROG= mkimg
SRCS= format.c image.c mkimg.c scheme.c
MAN= mkimg.1
@@ -8,6 +10,7 @@ CFLAGS+=-DSPARSE_WRITE
# List of formats to support
SRCS+= \
+ qcow.c \
raw.c \
vhd.c \
vmdk.c
@@ -29,4 +32,8 @@ LDADD= -lutil
WARNS?= 6
+.if ${MK_TESTS} != "no"
+SUBDIR+= tests
+.endif
+
.include <bsd.prog.mk>
diff --git a/usr.bin/mkimg/qcow.c b/usr.bin/mkimg/qcow.c
new file mode 100644
index 0000000..5033286
--- /dev/null
+++ b/usr.bin/mkimg/qcow.c
@@ -0,0 +1,369 @@
+/*-
+ * Copyright (c) 2014 Marcel Moolenaar
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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$");
+
+#include <sys/types.h>
+#include <sys/endian.h>
+#include <sys/errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "image.h"
+#include "format.h"
+#include "mkimg.h"
+
+/* Default cluster sizes. */
+#define QCOW1_CLSTR_LOG2SZ 12 /* 4KB */
+#define QCOW2_CLSTR_LOG2SZ 16 /* 64KB */
+
+/* Flag bits in cluster offsets */
+#define QCOW_CLSTR_COMPRESSED (1ULL << 62)
+#define QCOW_CLSTR_COPIED (1ULL << 63)
+
+struct qcow_header {
+ uint32_t magic;
+#define QCOW_MAGIC 0x514649fb
+ uint32_t version;
+#define QCOW_VERSION_1 1
+#define QCOW_VERSION_2 2
+ uint64_t path_offset;
+ uint32_t path_length;
+ uint32_t clstr_log2sz; /* v2 only */
+ uint64_t disk_size;
+ union {
+ struct {
+ uint8_t clstr_log2sz;
+ uint8_t l2_log2sz;
+ uint16_t _pad;
+ uint32_t encryption;
+ uint64_t l1_offset;
+ } v1;
+ struct {
+ uint32_t encryption;
+ uint32_t l1_entries;
+ uint64_t l1_offset;
+ uint64_t refcnt_offset;
+ uint32_t refcnt_entries;
+ uint32_t snapshot_count;
+ uint64_t snapshot_offset;
+ } v2;
+ } u;
+};
+
+static u_int clstr_log2sz;
+
+static uint64_t
+round_clstr(uint64_t ofs)
+{
+ uint64_t clstrsz;
+
+ clstrsz = 1UL << clstr_log2sz;
+ return ((ofs + clstrsz - 1) & ~(clstrsz - 1));
+}
+
+static int
+qcow_resize(lba_t imgsz, u_int version)
+{
+ uint64_t imagesz;
+
+ switch (version) {
+ case QCOW_VERSION_1:
+ clstr_log2sz = QCOW1_CLSTR_LOG2SZ;
+ break;
+ case QCOW_VERSION_2:
+ clstr_log2sz = QCOW2_CLSTR_LOG2SZ;
+ break;
+ default:
+ return (EDOOFUS);
+ }
+
+ imagesz = round_clstr(imgsz * secsz);
+
+ if (verbose)
+ fprintf(stderr, "QCOW: image size = %ju, cluster size = %u\n",
+ (uintmax_t)imagesz, (u_int)(1U << clstr_log2sz));
+
+ return (image_set_size(imagesz / secsz));
+}
+
+static int
+qcow1_resize(lba_t imgsz)
+{
+
+ return (qcow_resize(imgsz, QCOW_VERSION_1));
+}
+
+static int
+qcow2_resize(lba_t imgsz)
+{
+
+ return (qcow_resize(imgsz, QCOW_VERSION_2));
+}
+
+static int
+qcow_write(int fd, u_int version)
+{
+ struct qcow_header *hdr;
+ uint64_t *l1tbl, *l2tbl, *rctbl;
+ uint16_t *rcblk;
+ uint64_t clstr_imgsz, clstr_l2tbls, clstr_l1tblsz;
+ uint64_t clstr_rcblks, clstr_rctblsz;
+ uint64_t n, imagesz, nclstrs, ofs, ofsflags;
+ lba_t blk, blkofs, blk_imgsz;
+ u_int l1clno, l2clno, rcclno;
+ u_int blk_clstrsz;
+ u_int clstrsz, l1idx, l2idx;
+ int error;
+
+ if (clstr_log2sz == 0)
+ return (EDOOFUS);
+
+ clstrsz = 1U << clstr_log2sz;
+ blk_clstrsz = clstrsz / secsz;
+ blk_imgsz = image_get_size();
+ imagesz = blk_imgsz * secsz;
+ clstr_imgsz = imagesz >> clstr_log2sz;
+ clstr_l2tbls = round_clstr(clstr_imgsz * 8) >> clstr_log2sz;
+ clstr_l1tblsz = round_clstr(clstr_l2tbls * 8) >> clstr_log2sz;
+ nclstrs = clstr_imgsz + clstr_l2tbls + clstr_l1tblsz + 1;
+ clstr_rcblks = clstr_rctblsz = 0;
+ do {
+ n = clstr_rcblks + clstr_rctblsz;
+ clstr_rcblks = round_clstr((nclstrs + n) * 2) >> clstr_log2sz;
+ clstr_rctblsz = round_clstr(clstr_rcblks * 8) >> clstr_log2sz;
+ } while (n < (clstr_rcblks + clstr_rctblsz));
+
+ /*
+ * We got all the sizes in clusters. Start the layout.
+ * 0 - header
+ * 1 - L1 table
+ * 2 - RC table (v2 only)
+ * 3 - L2 tables
+ * 4 - RC block (v2 only)
+ * 5 - data
+ */
+
+ l1clno = 1;
+ rcclno = 0;
+ rctbl = l2tbl = l1tbl = NULL;
+ rcblk = NULL;
+
+ hdr = calloc(1, clstrsz);
+ if (hdr == NULL)
+ return (errno);
+
+ be32enc(&hdr->magic, QCOW_MAGIC);
+ be32enc(&hdr->version, version);
+ be64enc(&hdr->disk_size, imagesz);
+ switch (version) {
+ case QCOW_VERSION_1:
+ ofsflags = 0;
+ l2clno = l1clno + clstr_l1tblsz;
+ hdr->u.v1.clstr_log2sz = clstr_log2sz;
+ hdr->u.v1.l2_log2sz = clstr_log2sz - 3;
+ be64enc(&hdr->u.v1.l1_offset, clstrsz * l1clno);
+ break;
+ case QCOW_VERSION_2:
+ ofsflags = QCOW_CLSTR_COPIED;
+ rcclno = l1clno + clstr_l1tblsz;
+ l2clno = rcclno + clstr_rctblsz;
+ be32enc(&hdr->clstr_log2sz, clstr_log2sz);
+ be32enc(&hdr->u.v2.l1_entries, clstr_l2tbls);
+ be64enc(&hdr->u.v2.l1_offset, clstrsz * l1clno);
+ be64enc(&hdr->u.v2.refcnt_offset, clstrsz * rcclno);
+ be32enc(&hdr->u.v2.refcnt_entries, clstr_rcblks);
+ break;
+ default:
+ return (EDOOFUS);
+ }
+
+ if (sparse_write(fd, hdr, clstrsz) < 0) {
+ error = errno;
+ goto out;
+ }
+
+ free(hdr);
+ hdr = NULL;
+
+ ofs = clstrsz * l2clno;
+ nclstrs = 1 + clstr_l1tblsz + clstr_rctblsz;
+
+ l1tbl = calloc(1, clstrsz * clstr_l1tblsz);
+ if (l1tbl == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+
+ for (n = 0; n < clstr_imgsz; n++) {
+ blk = n * blk_clstrsz;
+ if (image_data(blk, blk_clstrsz)) {
+ nclstrs++;
+ l1idx = n >> (clstr_log2sz - 3);
+ if (l1tbl[l1idx] == 0) {
+ be64enc(l1tbl + l1idx, ofs + ofsflags);
+ ofs += clstrsz;
+ nclstrs++;
+ }
+ }
+ }
+
+ if (sparse_write(fd, l1tbl, clstrsz * clstr_l1tblsz) < 0) {
+ error = errno;
+ goto out;
+ }
+
+ clstr_rcblks = 0;
+ do {
+ n = clstr_rcblks;
+ clstr_rcblks = round_clstr((nclstrs + n) * 2) >> clstr_log2sz;
+ } while (n < clstr_rcblks);
+
+ if (rcclno > 0) {
+ rctbl = calloc(1, clstrsz * clstr_rctblsz);
+ if (rctbl == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+ for (n = 0; n < clstr_rcblks; n++) {
+ be64enc(rctbl + n, ofs);
+ ofs += clstrsz;
+ nclstrs++;
+ }
+ if (sparse_write(fd, rctbl, clstrsz * clstr_rctblsz) < 0) {
+ error = errno;
+ goto out;
+ }
+ free(rctbl);
+ rctbl = NULL;
+ }
+
+ l2tbl = malloc(clstrsz);
+ if (l2tbl == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+
+ for (l1idx = 0; l1idx < clstr_l2tbls; l1idx++) {
+ if (l1tbl[l1idx] == 0)
+ continue;
+ memset(l2tbl, 0, clstrsz);
+ blkofs = (lba_t)l1idx * blk_clstrsz * (clstrsz >> 3);
+ for (l2idx = 0; l2idx < (clstrsz >> 3); l2idx++) {
+ blk = blkofs + (lba_t)l2idx * blk_clstrsz;
+ if (blk >= blk_imgsz)
+ break;
+ if (image_data(blk, blk_clstrsz)) {
+ be64enc(l2tbl + l2idx, ofs + ofsflags);
+ ofs += clstrsz;
+ }
+ }
+ if (sparse_write(fd, l2tbl, clstrsz) < 0) {
+ error = errno;
+ goto out;
+ }
+ }
+
+ free(l2tbl);
+ l2tbl = NULL;
+ free(l1tbl);
+ l1tbl = NULL;
+
+ if (rcclno > 0) {
+ rcblk = calloc(1, clstrsz * clstr_rcblks);
+ if (rcblk == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+ for (n = 0; n < nclstrs; n++)
+ be16enc(rcblk + n, 1);
+ if (sparse_write(fd, rcblk, clstrsz * clstr_rcblks) < 0) {
+ error = errno;
+ goto out;
+ }
+ free(rcblk);
+ rcblk = NULL;
+ }
+
+ error = 0;
+ for (n = 0; n < clstr_imgsz; n++) {
+ blk = n * blk_clstrsz;
+ if (image_data(blk, blk_clstrsz)) {
+ error = image_copyout_region(fd, blk, blk_clstrsz);
+ if (error)
+ break;
+ }
+ }
+ if (!error)
+ error = image_copyout_done(fd);
+
+ out:
+ if (rcblk != NULL)
+ free(rcblk);
+ if (l2tbl != NULL)
+ free(l2tbl);
+ if (rctbl != NULL)
+ free(rctbl);
+ if (l1tbl != NULL)
+ free(l1tbl);
+ if (hdr != NULL)
+ free(hdr);
+ return (error);
+}
+
+static int
+qcow1_write(int fd)
+{
+
+ return (qcow_write(fd, QCOW_VERSION_1));
+}
+
+static int
+qcow2_write(int fd)
+{
+
+ return (qcow_write(fd, QCOW_VERSION_2));
+}
+
+static struct mkimg_format qcow1_format = {
+ .name = "qcow",
+ .description = "QEMU Copy-On-Write, version 1",
+ .resize = qcow1_resize,
+ .write = qcow1_write,
+};
+FORMAT_DEFINE(qcow1_format);
+
+static struct mkimg_format qcow2_format = {
+ .name = "qcow2",
+ .description = "QEMU Copy-On-Write, version 2",
+ .resize = qcow2_resize,
+ .write = qcow2_write,
+};
+FORMAT_DEFINE(qcow2_format);
diff --git a/usr.bin/mkimg/tests/Makefile b/usr.bin/mkimg/tests/Makefile
new file mode 100644
index 0000000..144b4fc
--- /dev/null
+++ b/usr.bin/mkimg/tests/Makefile
@@ -0,0 +1,19 @@
+# $FreeBSD$
+
+TESTSDIR= ${TESTSBASE}/usr.bin/mkimg
+
+ATF_TESTS_SH= mkimg
+
+SOURCES!= cd ${.CURDIR}; echo *.uu
+FILES= ${SOURCES:S,.gz.uu,,g}
+FILESDIR= ${TESTSDIR}
+
+${FILES}:
+ uudecode -p ${.CURDIR}/${.TARGET}.gz.uu | gunzip -c > ${.TARGET}
+
+CLEANFILES+= ${FILES}
+
+rebase:
+ (cd ${.CURDIR}; atf-sh mkimg.sh rebase)
+
+.include <bsd.test.mk>
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-apm.qcow.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-apm.qcow.gz.uu
new file mode 100644
index 0000000..0f8ec4e
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-apm.qcow.gz.uu
@@ -0,0 +1,127 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-apm.qcow.gz
+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
+C_<;GUYW3^9TG\$_^B:^_O+G_G]O!YMO@3_\'*;=.DB.F````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-apm.qcow2.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-apm.qcow2.gz.uu
new file mode 100644
index 0000000..0caab8b
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-apm.qcow2.gz.uu
@@ -0,0 +1,22 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-apm.qcow2.gz
+M'XL(")T[(U0``VEM9RTQ>#$M-#`Y-BUA<&TN<6-O=S(N;W5T`*V826_;,!!&
+M[_D53/>F32K.D)35/9N!'@JD#7H.O,A`@"Y&&J`7__A2ULB4J1DQ-N0(1@SB
+M>Q@/GT>FLZQ^*&6U,DZ90BVFRK^F"U3KQ?:E5M_&7T[:C]5!#=.9D&(6#&YP
+M6ZSS@`,)E^GN@N9QK>J0P4&3ZH)2."-6U[?`X(X.UJU;;\8H2N`^P!HG;L9>
+M]4%=7YPP>]8'0]>'?/]LDXL77']]6-<7IW()-TKB@$D5$FZ2Q"&3FDJX61)G
+MF-1<PI5)G&52"P&G$ZIXG&-26L)!$I<S*91P)HD;,2G).YWVKF!2DG<Z[=V$
+M24G>Z;1W4R8E>:?3WLV8E.2=3GLW9U*2=R!XIP*N9%*2=Q!Y=TBX1P&W8%*2
+M=Q!Y]YAP3S8XS:4D[R#R[BGAG@4<,^]`\@XB[YX3[D7`,?,.).\@\NXEX8X"
+MCIEW('D'D7>O"/<ZX)AY!Y)W$'EWW/%.,_,.).\P\NX-L;*`8^8=2MYAY)TF
+M'`0<,^]0\@XC[Y!P)N"8>8>2=QAY9PGG`HZ9=RAYAY%W.>%&`<?,.Y2\P\B[
+M@G!O`XZ9=RAYAY%W[PCW/N"8>8>2=QAY]X%P'P..F7<H>6<B[SX1[G/`,?/.
+M2-Z9R+M3PIT%'#/OC.2=B;P[)]S%!@=<:N-=EO$7X2X[GUD8]ONG"=^/-?,L
+M+_0`1[L`^RJL<<6@;]C6;]CO@(5PCLK6=\A1+_#R>X4YW*[/#GT@L+4P?C*;
+M>2>'TH'/+ZRNOC+]L[4P_N/@IZF_W$PY^Z#Z3I?+GR6#DT^WNQ^G/`Z[U=G%
+M^G\O2PXJ-\H5].P6RI75,E5WLYS<W=_>W_[Y?=/@JANDFU?A?)?J?DV6;'5V
+MX+TU#]S;YGX!!-S>6]749X9VSZRWPU6-]QOA+S\N+593SG_-4-96:Q:[P/%=
+M69Y=7QS_&%^W^V>&_;'!^A-5NG_0ZE_](6GW3[7K<T/WS_7V+T>5YXR;H7]_
+J_]4B-O4-W#^=4?_\2;W[+"^LKDZV_VJ@(>!@%1I73>>#_Z4*H1'E$P``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-apm.raw.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-apm.raw.gz.uu
new file mode 100644
index 0000000..3f148c0
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-apm.raw.gz.uu
@@ -0,0 +1,12 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-apm.raw.gz
+M'XL(".W%'50``VEM9RTQ>#$M-#`Y-BUA<&TN<F%W+F]U=`"MD\UJPS`0A.]^
+MBNFU4"/)*RD]MK2Y%4)#S\'4#@3:Q*2!7O3PE2*)R#\)+FB]"(ME/\:S:\9\
+M`"0A!9A-%E)PL`4N]T'"O+Z7-N[*&*;P,,YN=%W'E8,PQ;T'"E>6#-2,^JH4
+MR/L%LWH;`CW.Z2,.S5RJ3R@Y2]]3UWVU$SB1ZW,]KAJKD]OS.P>T@":HQW"J
+M+53KRD'=IJN/I]UI=]AO(HXL3C6N6?]'W7?=3:J3F6=+,V>[B$L9@/W9(NJC
+MW+M'YW$H9[P=A$T2D!6((!HK7+J:O8^`RV/;/J]?'CZ6Z]0_HLSZU`S_1.*?
+M_TE2_Y#J4[G]4S?]TQ6TGMC-BW\_OWX1H[[,_G$6_&/UQ'F]8%9E__%`"L!L
+."DDX8/$'F8$ZXZ<%````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-apm.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-apm.vhd.gz.uu
new file mode 100644
index 0000000..3245790
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-apm.vhd.gz.uu
@@ -0,0 +1,18 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-apm.vhd.gz
+M'XL(".W%'50``VEM9RTQ>#$M-#`Y-BUA<&TN=FAD+F]U=`"M5EUOVR`4?<^O
+MN-+>*BT"#+A[7-7F;5*U:L\M<W`5:6VC)M+ZD!\_+A\!V^`F&0Y!6/@>#N=^
+M`"'N`9`-R!ZD!BEPW'*0WZ"]!C"3OC';4_\*A^[M57?[S<?2/X>%`Z,DM1J:
+MHSUK@)M%6F`*%Y%K',,AP"R_W#U?;5Z>`QSS<&%A+H$S$`:$3]:1Y,@.D58W
+M#[<6\BFR:Z;LHI7Y_^9`.%":?-$$=D]'CD<X;JSZWK86E+(T0QN\#";B9D=P
+M@HRL$IHY49/-YN#DG-4Y<%<+[PL7*B8P6M,;Z2BT#,<F;((.DV9"Y6.W5>\[
+M/>+'"J$BC_SH9*XI;Y?Y4&'A8\^`8SC/;1<LRGX,EPF5_U)/#NVX'Q@1B`@3
+MS&Y_J%Z$@I2?I&1&\[(SBOP4\C.I*5A(=MN:SS9\]Q-AR-@=JN#=B_7K<-ID
+M"%_GHB*^C'/W_D<V7#KDQRF&,49RAS%\"K_OV^T?G8%CM;;KX)HI.]'[G+-)
+MYTJT[5WI%GU@]VBR;;_9;]Y>'P,<%BHLM1;Q='8O:IME)RK[5I_HV^LD3\C$
+MMQ#XZ=JQIZT[)`J/)Z2(9Q!;&^("Y\S[!'#UKK4YA;[^6CVD^FE>EQ\E)^C'
+M$OU<DJ3ZI;6%E@[QR_G-ZH>'29N)S:C?[J\+Q,"OMG[*ZT=4IB]/'.Z7PY\#
+M9+Z85JO.+%:_.@RY!ZS&D,<<KL60ZEEGGNMEZ1E6NNK*<I6YY*J+<!6ONM*7
+CK*(5.>NJ*WW)JG351;B*5UV$JWK5E;:@+OX!7ZN]MA\-````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-apm.vhdf.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-apm.vhdf.gz.uu
new file mode 100644
index 0000000..3e83de7
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-apm.vhdf.gz.uu
@@ -0,0 +1,15 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-apm.vhdf.gz
+M'XL(".W%'50``VEM9RTQ>#$M-#`Y-BUA<&TN=FAD9BYO=70`K571:L(P%'WW
+M*R[L35A)DYM;][@Q?1O(9,]:;2N%J<4)VT,_?DF3V-16<2/I)23<YO3DG.26
+M,=,`4(+DP%0P&Z+IV_E%0#U]CU1CD6OUR(#%MU9=AXLN6CT:&T"NTY(!9KUU
+MP@>,NXEZ_G8):.`T/XPA83IH`R3OXO=<59_Y`!P/M5T#)_KL9-&,8X"$0X)`
+M3[:G`BC7:<MN6:7'4WDJ#_NE@T,%1YE>G/R%W2ZM!MG)P-[BG=Y.[(!;P*ZW
+MX/AAZ+.'C1VDA5=&J$`.4@`B\$P1ESJGYCW`V3'/7Q:OCQ^SA:\?8F!^=(=^
+MW-//7!)?/_#Y46C]Z*9^B8`D&3B;K7Y?W^8@.GZ!]8N9U8^E`_WU1#V/NH\!
+M1`L8C"'9ZDS"WG4MHG`U8.(#\M;>!G!SV.>;4_GCWV"RU;DHAD.OYT+_"R@!
+MGC8E)M-CC]_#=#LN=UL'YZJ?^[#R^FSQY2ZIN]V9,KB!7+7L1%\D\M5;(S"$
+M..YLW+);^>H9.#QO-B]@+1N:+CJ33F*P-FNXIOKY+__76P-'@8^*^E&.?@&@
+'6R\`T@<`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-apm.vmdk.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-apm.vmdk.gz.uu
new file mode 100644
index 0000000..4b6923a
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-apm.vmdk.gz.uu
@@ -0,0 +1,82 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-apm.vmdk.gz
+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
+J^HSK5Z2^?N[^SD_^O__"^</%]K\U8>X3FJTP=S>?35_]'S/@3HZ37@``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-bsd.qcow.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-bsd.qcow.gz.uu
new file mode 100644
index 0000000..e9033f4
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-bsd.qcow.gz.uu
@@ -0,0 +1,125 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-bsd.qcow.gz
+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
+D_.\5P>Z'6?[RW!Y^U!_X]J^W]_^Y&QQ^#/[Q_[+N5S>!I0``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-bsd.qcow2.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-bsd.qcow2.gz.uu
new file mode 100644
index 0000000..34b715e6
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-bsd.qcow2.gz.uu
@@ -0,0 +1,21 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-bsd.qcow2.gz
+M'XL(")X[(U0``VEM9RTQ>#$M-#`Y-BUB<V0N<6-O=S(N;W5T`*V8VY+20!"&
+M[WF*6<^NBIGN24@\K+KK6N6=WN@UL/`4/+P;ILDDG?XS2`52J:*&_ZN>S)=F
+M0E'$EW.E=Z%RH7'[C7O\+`>YWH?AX0Z_?_Q<]E^'183Y`J2,@<`=;L"Z2SA"
+MN,*/![R-ZU7'!HY.J3$HAPNPNJD!`W>].%ZZXV+4*L&7`",.+L9%]5&L3R?"
+MA?71W/6Q??W*4TX/5-/U<:Q/IU8(5V=Q9*0:A%MG<6RD-@BWS>*"D7I`N%T6
+M5QJI/<#YC"J/N,I(>82C+&YEI!CA0A97&RGDG<][UQ@IY)W/>[<V4L@[G_=N
+M8Z20=S[OW=9((>]\WKL'(X6\(^"=2[B=D4+>D?+N2G!/$FYOI)!WI+Q[*KAG
+M'<Y;*>0=*>^>"^Y%PAG]CI!WI+Q[*;A7"6?T.T+>D?+NM>"N$\[H=X2\(^7=
+M&\&]33BCWQ'RCI1W[T;>>:/?$?*.E7?OA54DG-'O&'G'RCLO.$HXH]\Q\HZ5
+M=RRXD'!&OV/D'2OO2L%5"6?T.T;>L?)N);@ZX8Q^Q\@[5MXU@ON0<$:_8^0=
+M*^\^"NY3PAG]CI%WK+S[++B;A#/Z'2/O@O+NB^"^)IS1[P+R+BCOO@GN-N&,
+M?A>0=T%Y=R>X[QV.K%3G75'8A^#N1_<LS;O_#&E_[(TS'I@`UO\#G*HPXII9
+M)US&";<:K(TS'CC<+H?O#GA<X7+5KFI9N9K.K?#O_9_QA,L95SCB\..H#'0%
+M^W-PQ\?1WC?K_N8"#@PW%U<)-_DXVNZQ=]8`K*Z<61:J5:Z_SJ[9'Q]23MU=
+M;<VZ]76I/D-F&DQWHCXWGF[[J]$]W:E5;'&4F:X;XC:3:SM=W=6XNNW,B\'Z
+MSCCSSFTAPSLWXFC>1D#Q?ZFB_=;XC`<.OY;#=P0&`<YV!4/5]K[%/SE0:JE#
+#$P``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-bsd.raw.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-bsd.raw.gz.uu
new file mode 100644
index 0000000..d48f343
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-bsd.raw.gz.uu
@@ -0,0 +1,10 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-bsd.raw.gz
+M'XL(".[%'50``VEM9RTQ>#$M-#`Y-BUB<V0N<F%W+F]U=`"ME,$.@R`,AN\^
+M1;WN0$J%Z:Y+=M]I.SNS/04//U!4*@-=0C$DI.V7O]2".!F`(L#^QYYVF*O@
+MRU2G:J21`^H6E`9]ALZ&X_JQ`W.8Y^TA0C,>)W-9:9S8V(RC/=PB6![!-2XK
+MB+1J22ZXE&/"U9Y5KSB54V<1^/ZK6%WJ[N;>=IN\L,^`'\`!L/,^XL"EO[#J
+MN\0RB)6;T0=QN;W#M3Q>!CC:*1<X[I7M;5Y=':L;"C>CV4[&P<EU$#ZY$X[*
+C/@0TOBSV#[11\9YVF+O@:P(J#RQV@XH<L/H"TT^@ZP4%````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-bsd.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-bsd.vhd.gz.uu
new file mode 100644
index 0000000..1c0e8d7
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-bsd.vhd.gz.uu
@@ -0,0 +1,17 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-bsd.vhd.gz
+M'XL(".[%'50``VEM9RTQ>#$M-#`Y-BUB<V0N=FAD+F]U=`"MESUOPR`0AO?\
+MBI.Z98C@C+&[1DWG2I7:-8YC1QGZH29#!O_X<C;88(R3M-@$8<$]O'<<B##6
+M/0`R`5F#K$"FU,X$R$?(<@#5J0NV-=>?T)1?GU5Y/EY6^FD6'8PSV\HU)WM,
+M0*A),L"")I%[:D-C,*N'S6%Y_#@8'&J<F5A($`BI@@AO'LEZ=41Z7K\^M<CM
+MH"[QU0U6ZK<3P`1P;HU(C+IMK[''"655UVW)H"A:F:8X'T['X.P(E[*1E25S
+M*JB6LU,X.6=U#VZYT&O1I8I*C$S5*G0<,J2V2AL3!Z^H5+F<OHN?4S72AX%4
+MD;T^[O4E87=1IPJ:P5J!H'2><Q=:RGF,FTB5?T5/NG9"-U006&HZL'7?C=Z`
+M`EN?Y&PFYN'%".HK2)_:6ZR8J,,=S7KEOCVP)&":T79/)>1X:P3?-V]3ZUL&
+MTN6/NZ/$:[A>,+\%E^B]:U&2`1?JZ'!,L]B`$W/J*&>JNYQ-(R=SF8_L['4&
+M7@/?`\NMK+:`_?K"H._1EX&.NS/ZP'>W(%SFCN<6#J^X"RYN-[NV\^J8KZZ,
+MO!C[\<ZX<><2Q-VY'0[C'@38GBPJ`]4HOPYW-"\K]^V`J(^J:&<?FJ,JED*A
+M@=$4*F`562%6L\EV;Q9*K3#219)P$2^2A(MXD21<Q(LDX2)>)`D7\2))N*@7
+02:G^(C"V^`74/'YQ?0P`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-bsd.vhdf.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-bsd.vhdf.gz.uu
new file mode 100644
index 0000000..6660765
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-bsd.vhdf.gz.uu
@@ -0,0 +1,13 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-bsd.vhdf.gz
+M'XL("._%'50``VEM9RTQ>#$M-#`Y-BUB<V0N=FAD9BYO=70`K91-;X,P#(;O
+M_`I+N_6`DI`8>JW6G2=-VJX%"E4/W2X[[)`?OQ@"Q'RUFPA1!'+\\-I.+$0[
+M`+0"D<^LRP9[B/ECHUW4T!0!30K:@$'(W'8Q3/;!#/;C^!Z'PWJ<7/-:QL6C
+MT>'4/5PO6#Z"2\A+,DHRX)8,+4YXEAAP>DV=RX2H_A2LV2IW76VSD5]89Y`U
+MR#.(S-L4!_;UA4'??BI#L7!7],$TW)QP*=\O`YRZ$RYP7+%:VW5U8JJNW+@8
+MR?AF/'AS"<)O;HM3VS8"U706=P+=KNFZ;+"O,7]:H/;`S3*(OO=A`E@#5H"&
+MWE,-N(<T"X&*GR1;?GU6Y??U)ZPPX:@@=3T_R5\E=%LP!9733_!,[X&^I^-E
+M=[U=.ES7JKH?:Z2D&P?1DW"1A_MR>'MND*=!73)-$H;9*S0(#5*RP+VZ$S_.
+IA--]L%4-A6ED=I-],,-LJR*<$2.O_]:VQ>'&1\4=ON@7D=A:0S`'````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-bsd.vmdk.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-bsd.vmdk.gz.uu
new file mode 100644
index 0000000..ac4864b
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-bsd.vmdk.gz.uu
@@ -0,0 +1,81 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-bsd.vmdk.gz
+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
+-/@=\\W^I>^KAH%T`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-ebr.qcow.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-ebr.qcow.gz.uu
new file mode 100644
index 0000000..0dfdc6c
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-ebr.qcow.gz.uu
@@ -0,0 +1,127 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-ebr.qcow.gz
+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
+4^+>=X+`>O[_*/_X7*6^YQ%^G````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-ebr.qcow2.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-ebr.qcow2.gz.uu
new file mode 100644
index 0000000..426de83
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-ebr.qcow2.gz.uu
@@ -0,0 +1,22 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-ebr.qcow2.gz
+M'XL("*`[(U0``VEM9RTQ>#$M-#`Y-BUE8G(N<6-O=S(N;W5T`*V76[/2,!#'
+MW_D4P<M1CXK-;E**EZ.>BS.^Z8/Z7"[]%'QXVV9IVNUN`TRAP\"$_V\VY)>E
+MR;+P,,9;XW+C-J;:FOHS76!Z'X:7.?[^\7/5?QP7`68S)24,..QP`]9#Q(&&
+MR^QXP,JX7G4HX."4&H-2.*=6-S4@X&X7[4_7+D;!$G@-,.#4Q;BJ/@CU\82[
+MLCZ8NSZ4?S]_RO&!?+H^#/7QU%K#%4D<"*F-ABN3.!126PVW2^*<D-IKN$,2
+MYX54I>!L0I4:EPLIJ^$@B5L+*=1P+HDKA)3FG4U[MQ%2FG<V[5TII#3O;-J[
+MK9#2O+-I[W9"2O/.IKW;"RG-.U"\,Q%W$%*:=\"\6Q+N6<150DKS#IAWSPGW
+MHL-9*:5Y!\R[EX2[B3BAWX'F'3#O7A'N=<0)_0XT[X!Y]X9PMQ$G]#O0O`/F
+MW5O"O8LXH=^!YATP[]Z/O+-"OP/-.V3>?2!6%G%"OT/-.V3>6<)!Q`G]#C7O
+MD'F'A',1)_0[U+Q#YITG7!YQ0K]#S3MDWJT)5T2<T.]0\PZ9=QO"?8PXH=^A
+MYATR[SX1[G/$"?T.->^0>?>%<'<1)_0[U+QSS+NOA/L6<4*_<YIWCGGWG7#W
+M$2?T.Z=YYYAW#X1[['`@I3KOLDR^"/<TVK,P[_VGB_?'5GC5!R:`Q27`J0H#
+M;C/KA'W8&Y<!JTJKSX>]47^AODI/;^HK3(_RMO<'+-2W[./V<T^WN@SHO2G+
+M$?#/J;Y6YV83E<*K/G"\7PV?77VN`?IULR=\;@HX=\+_GOY*R^%FVQ\!IQ_F
+M::`KV)Z#:P_SO6_VS=`'AK=FRXB;/,PW)Y2#-*!6YV=VSQ4LUU_G]FBUBV=0
+M=F/;K:^)]0FM``;3G:C/C*?;_.=V9V.VBNT")*9KAKCMY-I.5[<<5[>;>3$\
+MWQEG[MP&,MRY`0?S-@)H.TMM8/VM\:L^</RU&CX#T!%PME_0Y<U?Y>(_(V[D
+%[($4````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-ebr.raw.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-ebr.raw.gz.uu
new file mode 100644
index 0000000..bbf6836
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-ebr.raw.gz.uu
@@ -0,0 +1,11 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-ebr.raw.gz
+M'XL("._%'50``VEM9RTQ>#$M-#`Y-BUE8G(N<F%W+F]U=`"ME,T.@R`,Q^\^
+M17?=P4`'TUV7[+[+MC.Z^10\_(KX`2*H"8!H4OK+O[:%,3L`Z%E=<8,N%T,7
+MYZ*G\>8PL.M6@1;7DA<=H*7D\$&+<0?'&2"/ZSNYN&_N<+MC0"E!J0#X&O6A
+M\1((3*WL<8.^E_Z<]`D#E!4("?(*->X-^/-XKZ5#\%S_S^)P"S<)YGMP%^/E
+MG'0K(V[0<YG8]X@3*76$8+]#P<K,M2?JA9^;9V#4)2VP>K"A#YSR"[.^6R@#
+MO7`3^B`,5QE<Y9_G#@XWP@4?UR1SFU9W"M6UF9,AEYVQLW,-Q.]<B\.\%P'V
+?-PM5()T*][A!/TM_6J`8@-G^H$`#+/YC5JB9E`8`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-ebr.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-ebr.vhd.gz.uu
new file mode 100644
index 0000000..6eb54df
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-ebr.vhd.gz.uu
@@ -0,0 +1,18 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-ebr.vhd.gz
+M'XL("._%'50``VEM9RTQ>#$M-#`Y-BUE8G(N=FAD+F]U=`"METU3PR`0AN_]
+M%>MX\]"!#6S:JZ.>G7'4JVE,'`]^C'KPD!\O!$@@"=@H34J3@7WR[K)L*&/F
+M`T`%4`O4`$E]70J@/90[`-5I3^Q;;F^AJ]]>F_KK^7MK/]W&P#CSK4)S;8\%
+M"/60$K#2#Z%'?0V=PVQ/+Y_.GE^>'`XMSCU8$`@$J2!B]AQB@SI-NCJ_N>B1
+M#Z.Z8JYNM%+?@P`F@'-O1.'4/0P:!YQ05FW;GR5452_3G<%-T#$Z.\%)-K'R
+M9"X%U7-V"4<IJS6XLXV="Y,J*C%*U:K0<2A17ZNT<7&8G2I5OC_?JX_/9J(/
+M(ZE"@SX^ZROB[J)-%72#K0*ATSGE+O24KREN(57^%3T*[82]4$%@TG5@[WX8
+MO1$%OC[B+!'S^&1$]55)O_[@\.&P&AA1:'#UX'`E1X],DHS!1![7=^+C'G.[
+MVZX#2JDKQA1XZ_35VDJ5.E8MM/&.[GP;'H.^1@-EJ:NO)-CAL0[?7]XM34<3
+M6;WKXV=P^!MN$,R/P16VE+J1?F;$.[HQ3<ROPXF4.KV$FU7.RLRYU^PF=OX\
+M`U.KI`:VLWT8`H?YA5'??BX#`W<3^F#N;J5Q93B>>SC\Q5T(<8?DW*;5G<S5
+MU9DGHYVNC"-7KH:$*]?@,&\AP+ZRJ`Q4H^9MO*.[WH:'`:)]<V1[%:&M?=D4
+M"@O,IE"X8II/8<&2R;8V"\DJS+2OIWBY_\N^GKQRGV%?3Z[<QZS8JGT]V7*?
+<:5]/KMSGV==K7-9]/:E_;(QM?@!J8S.+#`X`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-ebr.vhdf.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-ebr.vhdf.gz.uu
new file mode 100644
index 0000000..f298a70
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-ebr.vhdf.gz.uu
@@ -0,0 +1,14 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-ebr.vhdf.gz
+M'XL("/#%'50``VEM9RTQ>#$M-#`Y-BUE8G(N=FAD9BYO=70`K96Q;H,P$(;W
+M/,5%W3)$MK$/LD9-YTI5VS5`(,J0=NG0@8>OC3'Q82"D,A@P.M_'?[ZS8<P>
+M`/H:;=.&9CLXFM5FU=)X\3"PKD>!%E=J+SU`MUQU'=T8]W"<@>#3^M8^[A0[
+MW/HQH%*0YP'PW>D3QDL*8/G(?=K0[+?T[/5)`U0I2`4*(1-+`_X\?(RE0_)8
+M\V=QXAZN%\R7X!+CY8WT*V/:T-S*Q#X=3LZITPA6/12LBEQ[,AOX^7D&IE=)
+M"2SK;(("^_S"3=\NE"%(N#/Z(`PW-[B4CN<>3MP)%RBNF,WMO+IUJ*Z,G`PU
+M7!D+5ZZ!T)5K<2+N1B#:G457H!X5WJ<-S>N6GA8H.V"T&<3N5X0)8`U8`2K3
+M3R7@#M+,!PI:24WY_565/Y=?/\,&Q_L_1]B,OTC,:L$41&X^@B?3]_0]'<Z;
+MR_7L<&ZK<A^6:"9=:8@,PD4:[LO^[;E%'F_JDG"2T)^]0@*3P#D)O%-WI.6,
+I[3[O@JUJ*%0KTS7R0@RC6Y7!*3;P^F]N+0XCEXJNO=4?V8%!.+\(````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-ebr.vmdk.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-ebr.vmdk.gz.uu
new file mode 100644
index 0000000..4db541f
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-ebr.vmdk.gz.uu
@@ -0,0 +1,82 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-ebr.vmdk.gz
+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
+>=_S&];O3_L^6L/0)S3I8N@].R[_Z/_V4$^TO7P``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-gpt.qcow.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-gpt.qcow.gz.uu
new file mode 100644
index 0000000..a67e3eb
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-gpt.qcow.gz.uu
@@ -0,0 +1,132 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-gpt.qcow.gz
+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
+8Q"_BY[E'_2+>'HXWWOOM/_VP*B?UK```
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-gpt.qcow2.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-gpt.qcow2.gz.uu
new file mode 100644
index 0000000..c9d99d1
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-gpt.qcow2.gz.uu
@@ -0,0 +1,26 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-gpt.qcow2.gz
+M'XL("*([(U0``VEM9RTQ>#$M-#`Y-BUG<'0N<6-O=S(N;W5T`*V92V_4,!"`
+M[_T5+F]:6.)7DN51:$LK]=8BN'')\UB)*PK\=N+8B9/)3-PNWK6BKJSY9#O?
+MC)TT2>R',<V92IG:L[9D_6_7!)O]6#;6W5W?[.:?[LC">$)$(1U*3K@%Z]+C
+M!(5+^+J#X[C9Z"2"$V/4&A3"*7)T6QT([N1H6+KA9N0@0AX"M#CR9APT/F''
+M!R/4@>,3L<<G\?738QSL2+?')^WX8%1&X?(@3B!1>PI7!'$2B2HI7!7$*22J
+MIG!-$*>1J);`\8`J/2Y%HCB%$T%<AD1)"J>"N!R)HKSC8>_V2!3E'0][5R!1
+ME'<\[%V)1%'>\;!W%1)%><?#WM5(%.6=(+QC'M<@491W`GAW['!//*Y%HBCO
+M!/#NJ<,]FW`<BZ*\$\"[YP[WPN.0>B<H[P3P[J7#O?(XI-X)RCL!O'OM<"<>
+MA]0[07DG@'>G#O?&XY!Z)RCO!/#N[<H[CM0[07DG@7?O'"OQ.*3>2<H[";SC
+M#B<\#JEWDO).`N^DPRF/0^J=I+R3P#OM<*G'(?5.4MY)X%WF<+G'(?5.4MY)
+MX-W>X=Y['%+O).6=!-Y]<+B/'H?4.TEY)X%WGQSNS..0>B<I[Q3P[K/#??$X
+MI-XIRCL%O#MWN`N/0^J=HKQ3P+M+A_LZX006-7F7)'ASN*M5S@JDWJGT@;CK
+M-8Y^6#GD.*O\<9LC5[IC`Y@_'DCNM<J>4^)-6-L)&ZL*Y$IW=!>[Y7<"#KG[
+M".`XPB7.35C;W+4/C$W#VM8UNU(N.)\=$)`)'^]FN#KR^@WI]@B@UJPH5L`?
+MX_B&=.OSR[X;Z.W60S'0@FDUX8:YZFH^OJOK&W9[_NV[@?WTTQW2+2M8Q5F1
+MLP*.CE/3_8W9IVVZ92U<[1$G*=QT+`,X<[S(Z@T<UECWA\"IK:CII<,#[JW%
+MZ609-2];9ILH)6L+5M0$[@S@TLCF*=-=IBRK6-J8]TE5:_ZH4_.4QO(^3>RV
+M+88SUIYEW)S=>F!W?[>[M["WNU^G;GR*.R.P1G=0JZ>&RIQ3T\W\@P`Q7;;$
+M8:^1_FOU3%TN=;35VSM9L$9WD*M7V-7#%\FL'IHRW;AJ8\*-N#+NZG'["C,Q
+M]7M]I3NZV]WR:X'*`:.-4*5M%3$[#"YB=AA<Q.PPN*C988`1L\/@(F:'P47,
+M#H.+FAT]L$GB;>(&9]PK,E8+\YRX^'_!UG;<#8^/Z^DV8FOKW]C$\9O11-S$
+B#6YS$\\:>K+V\Q=,-N(F;G!1-W&5F>/WT3\!FKQU%1H`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-gpt.raw.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-gpt.raw.gz.uu
new file mode 100644
index 0000000..c8adeb3
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-gpt.raw.gz.uu
@@ -0,0 +1,15 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-gpt.raw.gz
+M'XL("/#%'50``VEM9RTQ>#$M-#`Y-BUG<'0N<F%W+F]U=`"MEC]O@S`0Q?=\
+MBI>U52W;V`262JW42MW2JMW:@3]FC-2=#U\?A@2(C1KIP$)(Q_UR]_#C(F4X
+M`*,AJ\@U'>B?Q?+L=W>[@:;JVX#^]ZF$%5!X8,`U/B@U/>,<NFY<4@U9(5E)
+M:#7>3SAQ.?9BAFO/6=<K'9CC1,!-[7:W`:U%55T!OZ;Z]/`Z+$P.4T+[YR6,
+M@M6PYHP;>K7-O+Z7US<<GSX^"?9]:5=[:5#[_!95!K<22:IDNS_K=@-.4U:W
+M5GO"94G</H[+**O=P,56&F>VLL(>^M^[#3@KEUG%/"MSJ#-T%:HV@7M<X7+F
+MG6<H7.<X-,@=K$+3T4V;0RF@\#8I!HB&]B66."CHFH#]Z5V<`NQ!_-Z/]1DU
+M[HC82@=2ZIEAJQ2I=@^TMS?;Q1*7<:M7D'J63;URW"RQE0XDU:N">G&12+VH
+M9?I)M<DA$Z[F54\-4\/[PW^_KZ_I0'\4RS,`S0ADJ]!H/S;XW$$X1G<0CM$=
+MA&-U!P$9W4$X1G<0CM$=A&-UAP<ZR3?$":?"F.Q:%!HN6]67&L>7^I;M.KTU
+F^C>&>/QE.,8A3KCM(>YN;99QB!..=8@;_W]*RMT?5F[7A(@+````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-gpt.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-gpt.vhd.gz.uu
new file mode 100644
index 0000000..6936b13
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-gpt.vhd.gz.uu
@@ -0,0 +1,22 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-gpt.vhd.gz
+M'XL("/'%'50``VEM9RTQ>#$M-#`Y-BUG<'0N=FAD+F]U=`"MF$MOVS`,Q^_Y
+M%!QVZS#7DB79N0Q8L1;8K7O==JCER$4/RQ[IH1C\X2?*\D.VY"$M$]5(H/#G
+M/RF*8IWG_0M`%:!:4`:4Q,^E`+6'L@*PDWYP=V7^*W3-SZ-I'A^>,O_J=CV,
+MY7.KT!SM>0'"WJ0$7N--U`$_0S=@LM?7]Q<//^X''/>XX<9"@>`@+42L[J/R
+M41V2;JZ^?'#(NTE=L58W6=D_+2`7P-CL%\6@[F[4..*$M6I;-THH:[0=1_`E
+MF$#<WRQ;XV2^L)K)C`5UYFP,I[:LSL%=[/Q:]*EB$Z.T5QLZ!B7'SS9MACBL
+MADV5I].O^L_)+/3Q1*JH41];S15I=[E/%3[\V"L0F,Y;[H*C/"YQD51Y4?14
+M:#>LK@U"+H<)[MP/HS>A8*Y/L7PCYNG%2.JK49_=6WD=N:8GNJLL?(]`K<\#
+M#A$,<:/#NL'XN3IBS.11GR138(N-!<EG\=,'XO75[7E`*:&N5\!O@[[&+8=T
+M!6^/B6&+@V`@;?&;TMGY+INYONN;CW#[_O-7A'V?W&TP70X<J@::/;1ZH6Z]
+MT[9K2\/[[.-MU-DBB;N,XW"SM8<-7&RD<6++RA]E9S@K\]"JFEL5!G0!;0WU
+M(8%[M\!1UV6#TUI!V>`1+ADT[BP_*#S(H++;I'(0#MQ*M`>[/84U`KOCI^S8
+MP]YFO]]X?8;YC(B-]$0J>L;5Y2KE;CD5[(2[$.*HZ[*I,'J2+'I[GRRQD9Y(
+M1J_NHQ</$D8OMG7'4RW+7H4X31L]YDX-NS]L_5Y?TQ/=;1:^>R#WQQ#9N<9]
+M(253*#R03*'P^Y=0(3.;BWGN*BN_*$05!G&$%09QA!4&<:05!H&$%09QA!4&
+M<805!G&D%4;1-D+*-T)%!8;A/RXZS)IT2]-5V:D7=AFXZQJA9/NTT0C%%X.R
+M$5+_:X1:DW)VY"R<)6R$%'4CI'PA)7J6H89&:*WA.<\RU-`(S6[\@F<9*MX(
+>/?=9!N((GV4@CO!9!N*(4X79WF7W#]HOQ!D`$P``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-gpt.vhdf.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-gpt.vhdf.gz.uu
new file mode 100644
index 0000000..0c18ed8
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-gpt.vhdf.gz.uu
@@ -0,0 +1,19 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-gpt.vhdf.gz
+M'XL("/'%'50``VEM9RTQ>#$M-#`Y-BUG<'0N=FAD9BYO=70`K9<[;]PP#(#W
+M^Q4LNJ6HH_?IE@`-F@#=TD>V#O%#"C+DBJ(=.OC'5Y3LL^23C%XAFS!TH/F9
+MI$G11T@X``0#TF:N9<5XVZ3GN+O:>1KM+@.ZYZ,+*V#C@`'7.R5A>(\Q8.TD
+MA'JK8.R$DV7M<<URD";"#;'52LJ*&-<$W!RNO0PH);3M&?!Q]H_YUR%!*!`'
+M8.Y^`H*"9"#%">=CEWWLW]W])WCX\.4;PKXOX3+JE`,#W4-_`-NMO*/_'F[`
+M.8<P^\QF@^5%W'4>QQ$W;.!R4L:)+:M00Y<$*TEJI6,K;J#C8%MHAP+N9H53
+ME2M/H+I3L.]!&9`4>HN+00&E`-JUB?80!LRY>(`]!=8A<#Q^;HX!]K[Y^6[R
+M3]"I(G)25I2R)[!4B"Z%N\?:W@P74AROG3V-V9/5LG>8BB4G944Q>VW(7CY)
+MF+U<ZSK<E+7F38KKZF:/^JGA^L/MW^?7LF)\:-(S`,4$K.:AM+:OV!V(J]@=
+MB*O8'8BKVAT(K-@=B*O8'8BKV!V(J]H=#FA(O2&..*P]KL%0V'/HTJHIC^-1
+M-[^"8]=)N(9MC?Z-(9Y_&:;B$$?<YA"WIA3LB;,*MN(01US5(:ZFSV_%0?G^
+M4A+7>P'*M92.@6RI&0_L?QQ-__OE3YP]Y7=F6#Z25X+VC&-A*M<B+3Y$#;B.
+M_'M[]WSU\OH\X]@4U?Q@K&A7Q0XBSL)5:;CWMU\_>N33XEUFFU)Q]CH!1.`6
+M$P<^>?>4EHKR7T!SL,:"EFA[DN1'HL@6,N)\J<0W_^^[#;C:I>+^&NS^`N3M
+&#A:S#0``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-gpt.vmdk.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-gpt.vmdk.gz.uu
new file mode 100644
index 0000000..782cb6c
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-gpt.vmdk.gz.uu
@@ -0,0 +1,87 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-gpt.vmdk.gz
+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
+G,1A>Q#W<DQ?Q<4@FRY\'R1I>Q#V<Z46\\'?OS#[Y/TT579ZT90``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-mbr.qcow.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-mbr.qcow.gz.uu
new file mode 100644
index 0000000..40c4fb3
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-mbr.qcow.gz.uu
@@ -0,0 +1,127 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-mbr.qcow.gz
+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
+BX=_Z)[[]\^W]?WX.#O/@WW:"PWK\_BI_^W]F=\)"L*<`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-mbr.qcow2.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-mbr.qcow2.gz.uu
new file mode 100644
index 0000000..09fa383
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-mbr.qcow2.gz.uu
@@ -0,0 +1,22 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-mbr.qcow2.gz
+M'XL("*0[(U0``VEM9RTQ>#$M-#`Y-BUM8G(N<6-O=S(N;W5T`*V8V;+3,`Q`
+MW_L5+LL%+E!BR4Y3E@O<A1G>X`%X3I=\13^>)%;C1)'BMI/6DVG'T1G9/E:6
+M+`L?8[PU+C=N8ZJMJ?]3`]/[,VSF^/O'SU7_<UP$F,V4**'#88<;L!XB#C1<
+M9L<=5L;ULD,!!Z>H,2B%<VIV4QT"[G;13EV[&`6+P&N``:<NQE7Y0<B/1[@K
+M\X.Y\T-Y_OPICG?DT_EAR(]'K35<D<2!$+71<&42AT+45L/MDC@G1.TUW"&)
+M\T)4I>!L0I4:EPM15L-!$K<6HE##N22N$*(T[VS:NXT0I7EGT]Z50I3FG4U[
+MMQ6B-.]LVKN=$*5Y9]/>[84HS3M0O#,1=Q"B-.^`>;<DW+.(JX0HS3M@WCTG
+MW(L.9Z4HS3M@WKTDW$W$"?4.-.^`>?>*<*\C3JAWH'D'S+LWA+N-.*'>@>8=
+M,._>$NY=Q`GU#C3O@'GW?N2=%>H=:-XA\^X#L;*($^H=:MXA\\X2#B).J'>H
+M>8?,.R2<BSBAWJ'F'3+O/.'RB!/J'6K>(?-N3;@BXH1ZAYIWR+S;$.YCQ`GU
+M#C7OD'GWB7"?(TZH=ZAYA\R[+X2[BSBAWJ'FG6/>?27<MX@3ZIW3O'/,N^^$
+MNX\XH=XYS3O'O'L@W&.'`RFJ\R[+Y$:XI]&>A7GO/UV\/[;"4>^8`!:7`*<R
+M#+C-K`/V8<"-!J5PU#N.]ZOAMP.VF^T"8#T_534"TH!]V&SU"74K/?VH6Y@O
+M&I[M7=&%`2]7/=Q^YOEK]\<%0.]-68Z`?T[YP=S+X1J@7S>;S.>F@','_._I
+M[]B_&C?;A@LX_>T`=70)VW-P[=N!WIE],_2.X;W>,N(FWPXTCSP'J4/-SL_L
+MGBM87'^=VV>U77RH97?*W?J:F)]06V`PW(G\S'BXS46\>]AFJ]@N0&*X9HC;
+M3J[M=';+<7:[F1?#\YUQYLYM(,.=&W`P;R&`MK+4!M9GC8]ZQ_'7:O@-0$?`
+1V6;0Y<VE:/$?-R^$K](4````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-mbr.raw.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-mbr.raw.gz.uu
new file mode 100644
index 0000000..f256873
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-mbr.raw.gz.uu
@@ -0,0 +1,11 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-mbr.raw.gz
+M'XL("/+%'50``VEM9RTQ>#$M-#`Y-BUM8G(N<F%W+F]U=`"ME,NRPB`,AO=]
+MBKAUP80(Q[IUQKT;=8WU]"EX>(/I!8JM[0R04F8"W_PA!$1I`(8`W9=QWN'/
+M*NV^VE<?FGYN`]8(;9L!%0,%US".%[`YVTW84$,0SA^;1B#=S<7`J['M5(1[
+M#;MRFW?$."6X/MQV&]!:<"X#WGI]5#H=)@#M$8P%^P<UK0WX<;E/`A:<+G5^
+M@J-?N$&P7H,[A%W1ROAFS#O\>$WDW^/,DCI&X/^F8&WANV?JR;XXSX!<)0U@
+MW?DH!0[YA5'?*9=!2;@+^B`/UP7<,5VO(QS]"!=2W',QM\OJ=KFZIG`R[+0R
+L5E9N@*25*S@J^Q#0YV7A&\BK\G'>X:\J[0(T';#8"1H*P.H-:WH%_)0&````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-mbr.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-mbr.vhd.gz.uu
new file mode 100644
index 0000000..92039f8
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-mbr.vhd.gz.uu
@@ -0,0 +1,18 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-mbr.vhd.gz
+M'XL("/+%'50``VEM9RTQ>#$M-#`Y-BUM8G(N=FAD+F]U=`"METU3@S`0AN_]
+M%>MX\]!)EF2A5T<].^.H5P'!\>#'J`</_'@32$("!(NFI10FV8=W/[)-&1M>
+M`)0!M4`-D-37N0`Z0%X`J$%S8'_FYA:Z^NVUJ;^>O_?FU>T&&&>^56BN[3$#
+MH1Z2`Y;Z(?2HKZ&SF/WIY=/9\\N3Q:'!V0<+`H$@%43,GD/,J=.DJ_.;BQ[Y
+M,*K+YNI&*_6I!#`!G'LS,JONP6ET.*&LVK8_<BC+7J8]@IM@8'1V@I-L8N7)
+M7`JJY^P2CM:LMN#.=B870ZFHPLC5686.0X[Z6I6-C</L4*7R_?E>?GPV$WT8
+M*15R^OAL+(N[BZ94T$XV"H0NYS5WH:=\37$+I?*OZ%%H)\R%"@*3=@![]\/H
+MC2CP]1%G*S&/)R.JK]3ZU-IBY<(Y/M"=[\.W`U;5-F#!!H4ASCE<U<[A4HX>
+M#44R!A-Y/"$G7ORJQ\3YK=IM0"EUQY@";ZV^.G4Z&@V4N>Z^DJ#`8QV^O[Q;
+M6FY-9/7^L5DU^!O.">;'X#+32NU,OS+B`]U8)L.WQ8DU=7H)-YN<E8EKKRDF
+M=GZ>@:E54@,KO";C`5U^8=1WF,O`P-T5?3!WM]2X/)S//1S^XBZ$N&HUM^OJ
+M3N;JZL3):*<KX\B5JR'ARAUPF+818-]95`6J6?-S?*"[WH?O`8CFER/93Q&:
+MWI=,H3#`9`J%;:;I%&9LM=BV5B$9A8GV]11O]W_9UY/7[A/LZ\FV^Y@5V[2O
+?)]/N$^WKR;;[-/MZC4NZKR?UCXVQW0]_N`=E#`X`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-mbr.vhdf.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-mbr.vhdf.gz.uu
new file mode 100644
index 0000000..171e991
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-mbr.vhdf.gz.uu
@@ -0,0 +1,15 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-mbr.vhdf.gz
+M'XL("/+%'50``VEM9RTQ>#$M-#`Y-BUM8G(N=FAD9BYO=70`K96Q;H,P$(;W
+M/,5%W3(@^[`/LD9-YTI5VS5`(,J0=NG0@8>OC3'8.)"D,AQ@=/;'?[ZS8<P<
+M``*!%5?N\XYVE_AGN]JL.AHO'P/F#)HF`"8*:'"5PJD.R@K9-Y0Q#EJXNI1Q
+M!LC[MC%HD_%8)P[N.(P*;=[AXA*#L^$VCP&EA*((@.]6'\9.A]!`F8&0(`ER
+MO#?@S_W')&"#X['FS^#P%FX0S._!I7J4T].MC'E'.Y:)>5J<6%*G$*Q^*%@9
+MN?9$/AGGYAF86B45L+SWH0\<\@NCOFTH`[UP%_1!&&ZA<9G?GSLXO!$N^+AR
+M,;?+ZM:ANBIR,N1T9=RY<C7$7[D&AW$W`NQV%E6!JE=XGW>TKXE_&J#H@=%F
+MD/I?$:5`#5`-)'4[$T!;R'(7B'XEM=7W5UW]G'_=#&L<'_X<H>GQF.K50AE@
+MH3]"1]UV]#WM3YOSY61Q=JNR'Q:D)UTJB`C")3_<E]W;<X<\C.K2<)+(G;U2
+M`!/`N1=XK^[@ES-U^[P-MFZ@E)U,:]Z+Y[BZ56F<9)-1_\VMP5'D4E&UM_H#
+(GF2M3+\(````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-mbr.vmdk.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-mbr.vmdk.gz.uu
new file mode 100644
index 0000000..bcbad1e
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-mbr.vmdk.gz.uu
@@ -0,0 +1,82 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-mbr.vmdk.gz
+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
+E69AE]6+<_KW_Q/6[T_:_%;`,@&8=+/TGL>5?_1_0^/1A@%\`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-pc98.qcow.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-pc98.qcow.gz.uu
new file mode 100644
index 0000000..efca490
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-pc98.qcow.gz.uu
@@ -0,0 +1,127 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-pc98.qcow.gz
+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
+"````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-pc98.qcow2.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-pc98.qcow2.gz.uu
new file mode 100644
index 0000000..afb67c9
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-pc98.qcow2.gz.uu
@@ -0,0 +1,21 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-pc98.qcow2.gz
+M'XL("*8[(U0``VEM9RTQ>#$M-#`Y-BUP8SDX+G%C;W<R+F]U=`"MF-N2TS`,
+MAN_[%"Z'!18HL62G"8<%]L`,=W`!7+?=]BGZ\&QB;90H4MSMI,UDIN/^W\CQ
+M%S5N4:27<]&[4+I0N\/6/7RF`USOP_!PQ]\_?J[ZK^,BP7QAI)2!@!UNP+IA
+M'%BXPH\'O([K58<*#AY38U`.%\SJI@84W.6BO73M8E0B@><`$\Y<C+/J@U2?
+M3(0SZX.YZT/]^L7'G!PHI^O#5)],K2U<E<6!DJHMW":+0R6UM7"[+"XHJ7L+
+MM\_BHI(Z&#B?4>4!5RHI;^$@BULK*;1P(8NKE)3EG<][5RLIRSN?]VZCI"SO
+M?-Z[K9*RO/-Y[W9*RO+.Y[V[5U*6=V!XYQBW5U*6=R"\6Q+N&>,.2LKR#H1W
+MSPGWHL-Y+65Y!\*[EX2[8)S2[\#R#H1WKPCWFG%*OP/+.Q#>O2'<)>.4?@>6
+M=R"\>TNX=XQ3^AU8WH'P[OW(.Z_T.["\0^'=!V(5C%/Z'5K>H?#.$PX8I_0[
+MM+Q#X1T2+C!.Z7=H>8?"NTBXDG%*OT/+.Q3>K0E7,4[I=VAYA\*[FG`?&:?T
+M.[2\0^'=)\)]9IS2[]#R#H5W7PAWQ3BEWZ'E71#>?27<-\8I_2Y8W@7AW7?"
+M73-.Z7?!\BX([VX(=]OA0$MUWA6%?A#N;G3/PKS/GX&?C[URM@<F@-53@%,5
+M)EP]ZX1CFG"CP48YVP/'Z]7PW0%;89X`C-%MQL`_:<(Q"5,'MPO:O`X'/DZX
+M?G%N86*S)+->/V@G'-?-71%+5\&I%?Z[^ZM,&.:;<,+9VWD:Z`KVI^#:[7SO
+MF[[_<&8.#!_.EHR;W,XW>Y2]-F!6%^>5!:`2N?XZMYNK'>]"Q:-MM[Z.ZU.:
+M`0RF.U&?&T^W^=7M=L=B%=L%R$S7#7';R;6=KFXYKFXW\V*@O#-.O',;R/#.
+I33B8MQ&$]+]>T?;(T=D>./Y:#=\)&`@XVQ4,9?/;L?@/'U:4T(,4````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-pc98.raw.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-pc98.raw.gz.uu
new file mode 100644
index 0000000..5398eae
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-pc98.raw.gz.uu
@@ -0,0 +1,11 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-pc98.raw.gz
+M'XL("//%'50``VEM9RTQ>#$M-#`Y-BUP8SDX+G)A=RYO=70`K91!#H,@$$7W
+MGF+<=F%@'*INFW3?3=NU-?44'+X@5`4$-0$,,?GP\C\#,&8:`"&P?F.,"_)6
+MN5T6EV*B\?$<4`CH0^!3`2<<:G\=P4"@_KP/QG'Y'$%67OOCN!)#D%T5%39P
+M-BYEWC^<`HL&2("X0HM'';[OKXW`F"^PP>$>;C;,C^!JO6HU4[E%/N-B@L&5
+MEE4N.$JY4PCV/156Y#TLB*VW;EUG8.H,#\!:JZ$+G.L+B[\NM(%.W(0_"./V
+M&M>X\_D*ASMQP<5]DK5-NRM#=T/F8M3^S3AX<S7$O;D&AWD?`II>9G4"]1L9
+9C'%!/BJW&R!98+8=)-3`X@?$\J!S108`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-pc98.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-pc98.vhd.gz.uu
new file mode 100644
index 0000000..8df641e
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-pc98.vhd.gz.uu
@@ -0,0 +1,18 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-pc98.vhd.gz
+M'XL("//%'50``VEM9RTQ>#$M-#`Y-BUP8SDX+G9H9"YO=70`K9=-;X,P#(;O
+M_16N=NNA2HP3VNNT[CQIVG8M9;3:81]:>^B!'[\8$DCX6KL%*`H*?O+:<4PJ
+M1'T`Z`3T'G0!6G$[)=!K2%<`IM->6-VE?80R__PH\M/;>6F/<E;#I/"M0G.V
+MQP3(#)("9CR(?N4VE`ZSO-D<%F_O!X=#BW,#DP9"4`9"O7&T:-0QZ?[V\:Y"
+M;EMU25]=:V5^.P)!(*7W1N+4;1N-#8Z,U7Y?72ED62737<%#T-$ZV\$IT;'R
+M9`X%U7-V"*>GK*[!+69V+NI4,8F1FKL)G804N6W2QL6A=YE4.1^_LN]CT=&'
+M(ZFB&WVRUY>,NXLV5="];!40I_.4NU!13EW<0*K\*WHZM"/;,$$0RG5@Y7X8
+MO18%OCXMQ43,QR=C5%_&^LS:$MG`?;RCO%V&9P/<[:\#*L5+J`M\<@[GK&]-
+MD--0W'TG+UH=^4CV_7E^B\CQP\IAE7*Y5!I6>*G"E\WS@,,8S^$:A[_A&L'R
+M$EQB:Y][TZC%YFLSVE'CYI8U;W$TI8[77'&5LRINLF"^ZMCY\PS"Y'`.8N55
+M!0_8S"^T^M9]&1BX.Z$/^NYFC$O#]Z6'PU_<A1"WFYS;:77SOKH\\F2\=E?&
+MA2N7(>'*K7$8MQ!059E-!G*-[-W'.\J'97C60+2E/MJW`VUMCJ:0+#":0K+5
+M.:)"*B:3[=HLU%9AI(TXXR)NQ!D7<2/.N(@;<<9%W(@S+N)&G'%1-^+:_,42
++8O8#/[LV_KT-````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-pc98.vhdf.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-pc98.vhdf.gz.uu
new file mode 100644
index 0000000..49a64aa
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-pc98.vhdf.gz.uu
@@ -0,0 +1,14 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-pc98.vhdf.gz
+M'XL("//%'50``VEM9RTQ>#$M-#`Y-BUP8SDX+G9H9&8N;W5T`*V5L6Z#,!"&
+M]SS%1=TR1/BP#UBCIG.EJNT:0B'*T';IT(&'KVU,\&$@266PD-'AC__WV><D
+MZ2X`B9"4$\_Y0+O;\KM=;5:6)IK[@$I!&0)?-=#BT.@K)%02=&_4H&F&Q@+M
+M=G3U.*&#(<B-F@U,X)Q=&7G^T!I6&4@%BB#'6Q6^[]\F#&,\PQT.K^$N@L4M
+MN-2,\K[4:E%<<'.!#K=VK/6`DTOJ-"*I[S*KXBX6Q'PTSL\S)'H-5Y#D+H8<
+M>,DO#/J*4`8RNPOZ(+1;&ES&OQ<>#J_8!8X[+N9V6=TZ5%=%3D8ZWADW[EP#
+MX3NWPV'<0B!M9=8KT-3(X#D?:)^W_.Z`T@&CS2"YLX-2H`:H!E*FGTF@`K+<
+M!R)?26WU_557/^=?/\,&)T85W6]F/*9FMU`&6)J?T(?I>_H>]J?-^?/4X_I2
+MU?]8DIETI2$RL$O<[M/NY=$B#X.Z-)PD\F?OJ$\H"4(PXT[=@2]GLOGMS=8-
+D')65V3?VP@*3I<K@5#(:]=_<=CB*O%3TJ;;Z`TU!^3)P"```
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-pc98.vmdk.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-pc98.vmdk.gz.uu
new file mode 100644
index 0000000..f76b425
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-pc98.vmdk.gz.uu
@@ -0,0 +1,82 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-pc98.vmdk.gz
+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
+.8+X`OOH_SBV/UN!>````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.qcow.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.qcow.gz.uu
new file mode 100644
index 0000000..ddcfe73
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.qcow.gz.uu
@@ -0,0 +1,125 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-vtoc8.qcow.gz
+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
+J//?S&:<?4MK#W_4O?/O7V_M_W:$RS(-_&WO#>OO]4_[Q?X8;4W9_I0``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.qcow2.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.qcow2.gz.uu
new file mode 100644
index 0000000..426bfa7
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.qcow2.gz.uu
@@ -0,0 +1,21 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-vtoc8.qcow2.gz
+M'XL("*@[(U0``VEM9RTQ>#$M-#`Y-BUV=&]C."YQ8V]W,BYO=70`K9C;CM,P
+M$(;O^Q3N<EY@B6?L-.&PP.ZR$A=((%Z`IG$?@.L^/$[LULED)BY5VK129?V?
+MQO;7J=.B"`^EK%:F5*96^T;YS_$"-?@POM3AU^/WF^'CL`HP70@I9L#@"3=B
+MW2<<2+A"3P<TCQM4APP.CJDI*(<S8G5S`PSN>M4O7;\9%4G@)<"`$S?CHOH@
+MU$<3YL+Z8.GZD%\_>\S1@7*^/@SUT=1&PE59'#"I6L)MLSAD4HV$VV5QADFU
+M$LYE<99)[06<SJCB<263TA(.LK@-DT()9[*XBDE)WNF\=S63DKS3>>^V3$KR
+M3N>]:YB4Y)W.>[=C4I)W.N]=RZ0D[T#P3B6<8U*2=T"\6T?<5<+MF93D'1#O
+MGD3<TQ-.<RG).R#>/8NXYPG']#N0O`/BW8N(>YEP3+\#R3L@WKV*N.N$8_H=
+M2-X!\>YUQ+U).*;?@>0=$._>3KS33+\#R3LDWKV+K"+AF'Z'DG=(O-,1!PG'
+M]#N4O$/B'4:<23BFWZ'D'1+O;,25"<?T.Y2\0^+=)N*JA&/Z'4K>(?&NCKCW
+M"<?T.Y2\0^+=AXC[F'!,OT/).R3>?8JXVX1C^AU*WAGBW>>(^Y)P3+\SDG>&
+M>/<UXNX2CNEW1O+.$._N(^[AA`,N=?*N*/@KXKY-OK.P[/G3I/.Q9M[E@1E@
+M]3_`N0H#KEYTPC9,V-\Z;D"5MKN\$A:[G?1-1)E6`C[^=>[N]X/Y,:S/+GU#
+M8-/Z%=PR4535'\=!6C\[6K\ZB\MLAPT'LT6F&W#-N3C_X^*/]JU3SA'<GP%N
+MM_!FZ,ET77?R]\>IZ@S@>@`,N&ZZ(4QWF/EOX#BL#NM)?0&7I@N#"(QPFJO.
+MGQ;[UQC7)IRF/6MVLFNV.K>H*GU?/@O7;E7CNI-MLYG@KHZXOB_[`Y"_:9V^
+;RP.'GS?C9U#%1.!B[IFR:U2K?VQQ7;KP$@``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.raw.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.raw.gz.uu
new file mode 100644
index 0000000..f5ae94e
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.raw.gz.uu
@@ -0,0 +1,10 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-vtoc8.raw.gz
+M'XL("/3%'50``VEM9RTQ>#$M-#`Y-BUV=&]C."YR87<N;W5T`*V230Z",!"%
+M]YSBX=(%:8=296N,.Q,3+R#8>@#7/;QMA@0*Y<>$H73S>%_F,2,$%Z`T3@1=
+MA:,(50FE4"HO&'A]>N!N7VLOSZNZ%UPN8YCT8M(BE@17C,IEQPYXCGQR&7B&
+MJ"$H"61<W;OJ5=Q2?XQK]HK+N'8K3OO;P%A8.\*]!KCWSL.0D[@6?N`DPY]<
+M!>;CN#+$9?-XPK,X+[A\TA_C^K@TL%"$DZGN4/`;XTR/DW^M2I[LSNZZ*O*S
+M%6<:M!9$*/4$=]`=CH*K\M\WB7M><(\B?GA55`?<;?<4!6#V`]&)2;VR!```
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vhd.gz.uu
new file mode 100644
index 0000000..aadaa42
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vhd.gz.uu
@@ -0,0 +1,17 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-vtoc8.vhd.gz
+M'XL("/3%'50``VEM9RTQ>#$M-#`Y-BUV=&]C."YV:&0N;W5T`*V6R6[",!"&
+M[SS%2+UQ0-[BP+5JN56JU!?`21S40Q<!!PX\?&<29W$2!R@.QC)RYO,_X[$9
+MQNH'0$O0)6@+.J%QJD!O(%T#X*1KHNJY^PF7_.?;YJ?/\\H]ET4-XZQOY9N3
+MO9"@<)$4A*%%=$%CN#28U=/K?OGYM6]PPN&:A94&)2!!B!JMHUFKCDC;YX^7
+M"KGKU,FQNLX*OYD"IH#SWANR4;=K-;8XA59E6;44C*ED-LW[X4UTS@YP"1M8
+M]61.!;7G[!1.SUG=@ULNW%[4J8*)D6*/H>.0"AICVC1Q&#5,E?/QUQR.=J!/
+M!%)%M_KX:$Z&W14N543SLE.@*)WGW(6*<AKB)E+EH>AIWTZY`0:!)<V$J-SW
+MH]>AH*]/<S83\_!F!/49TH?'"W>4;H&D.V=2XT01<GA[L!9/FG[SXV<"N_OO
+M^)FU9W?E=*R!;>C6"::+V716F\</FS&QW*UQV:TXNKX**"Q8.\#M>K@\\F9D
+M(W<M9;*\#<B&[F;DKAR\SUT?P-%%RD;Z:ESGKNB9"`\WNEQ(';3'K(\K6MQ0
+MXQ5GV:0Z&S55LO)67&$@LR`ER&2$DXG#Y62%?T3,3/3AB<O[RO_4J2+<O1+M
+MHA*Q%2H'C*80@3:R0LYF,^/>\ZN=PDA5'^$B5GV$BUCU$2YBU4>XB%4?X2)6
+2?82+6O7I*O<6?^^O%OLJ#```
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vhdf.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vhdf.gz.uu
new file mode 100644
index 0000000..bcf2071
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vhdf.gz.uu
@@ -0,0 +1,14 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-vtoc8.vhdf.gz
+M'XL("/7%'50``VEM9RTQ>#$M-#`Y-BUV=&]C."YV:&1F+F]U=`"ME,MN@S`0
+M1??YBBMUEP7R<PC;JLVN4J7^0""8J(NV4M5%%_[XVK%)L'$>JC"#!1KF>*X]
+M#&-A`(I0"Y#VI@2TA%*0Y!P]G']NL-MO8Q[?GNBE"L.N`HP[9S&$77/8*AMV
+MM8[`31+'KP,W8`V8*`(#KCE'-3=QU_(+N'8IN0'7W8LC-_?H#8S)<+L);K_P
+M8?"97`-WX/(^(,OE<B]79M_S.%_`.8=EL_P"[BQ73$)$@N.E[%"%.\7U)UR>
+MXPVQK)B=6;14^'`OKF_1&4@)J6<XJ2-.^"CMOF\+\V6'?:W2*Y2*BL#%:H]B
+MHR()&D#FV*LD:@5J4&^F0)$<,^S^Z]/L?]Y_I_M'L5$-0]E\O'!-T"U20[1^
+M$>K]\R2_A^?#^OWC,.)$5#4N[%KJJ9/F*BF5NW5]=/QU1YR<;Q)-=Z]38`J<
+M)\)C=KNT6#Q.G<2:`9T^ICE:\I(XBK7G<9IE4?\O98^CA4O%U=[J#P!,R,C=
+#!@``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vmdk.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vmdk.gz.uu
new file mode 100644
index 0000000..238837c
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vmdk.gz.uu
@@ -0,0 +1,81 @@
+# $FreeBSD$
+begin 644 img-1x1-4096-vtoc8.vmdk.gz
+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
+5%`'0[+U7^,]AS;[Z/YH4:2:>70``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-apm.qcow.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-apm.qcow.gz.uu
new file mode 100644
index 0000000..99f2a7b
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-apm.qcow.gz.uu
@@ -0,0 +1,127 @@
+# $FreeBSD$
+begin 644 img-1x1-512-apm.qcow.gz
+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
+HSV](YW>>P#_Y)[[^\N;^?VX'FS3XF[UA<[[^!I]_^C_<Q@LX=*8`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-apm.qcow2.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-apm.qcow2.gz.uu
new file mode 100644
index 0000000..88ef9cd
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-apm.qcow2.gz.uu
@@ -0,0 +1,22 @@
+# $FreeBSD$
+begin 644 img-1x1-512-apm.qcow2.gz
+M'XL("(\[(U0``VEM9RTQ>#$M-3$R+6%P;2YQ8V]W,BYO=70`K9A);]LP$$;O
+M^15,]Z9-*LZ0E-P]FX$>"J0->@Z\R$"`+D8:H!?_^%+6R)2I&3$VY`A"#.)[
+M&`^?QZ:SK'XH9;4R3IF16DR5?TX7J-:3[4NMOHV_G+0?JX,:IC,AQ2P8W."V
+M6.<!!Q(NT]T%S>-:U2&#@R;5!:5P1JRN;X'!'1VL6[?>C")*X#[`&B=NQE[U
+M05U?G#![U@=#UX=\_VR3BQ=<?WU8UQ>G<@E7)''`I$82;I+$(9.:2KA9$F>8
+MU%S"E4F<95(+`:<3JGB<8U):PD$2ES,IE'`FB2N8E.2=3GLW8E*2=SKMW81)
+M2=[IM'=3)B5YI]/>S9B4Y)U.>S=G4I)W('BG`JYD4I)W$'EW2+A'`;=@4I)W
+M$'GWF'!/-CC-I23O(/+N*>&>!1PS[T#R#B+OGA/N1<`Q\PXD[R#R[B7AC@*.
+MF7<@>0>1=Z\(]SK@F'D'DG<0>7?<\4XS\PXD[S#R[@VQLH!CYAU*WF'DG28<
+M!!PS[U#R#B/OD'`FX)AYAY)W&'EG"><"CIEW*'F'D7<YX8J`8^8=2MYAY-V(
+M<&\#CIEW*'F'D7?O"/<^X)AYAY)W&'GW@7`?`XZ9=RAY9R+O/A'N<\`Q\\Y(
+MWIG(NU/"G04<,^^,Y)V)O#LGW,4&!UQJXUV6\1?A+COO61CV^Z<)WX\U<Y<7
+M>H#%+L"^"FO<:-`7;.L7['?`0CA'9>M/R*(7>/F]PAQNUV>'/A#86A@_F<V\
+MDT/IP.<75E=?F?[96AC_=O#3U%]NIIQ]4'VGR^7/DL')I]O=CU,>A]WJ[&+]
+MOY<E!Y4;Y49T=POERFJ9JKM93N[N;^]O__R^:7#5!Z2;5^%\E^I^399L=7;@
+MO34/W-MFJ@`!M_=6-?69H=TSZ^UP5>/]1OC+CTN+U93S7S.4M=6:Q2YP?%>6
+M9]<7QS_&U^W^F6%_;+#^1)7N'[3Z5[])VOU3[?K<T/USO?W+4>4YXV;HW]]_
+HM8A-?4/WKZ#^^9-Z]RXOK*Y.MO]JH"'@8!4:5TWG@_\+*`W"Y1,`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-apm.raw.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-apm.raw.gz.uu
new file mode 100644
index 0000000..025d7ad
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-apm.raw.gz.uu
@@ -0,0 +1,12 @@
+# $FreeBSD$
+begin 644 img-1x1-512-apm.raw.gz
+M'XL(".3%'50``VEM9RTQ>#$M-3$R+6%P;2YR87<N;W5T`*V3S6K#,!"$[WZ*
+MZ;50(\DKJ3FFM+D50D//P=0.!-K4I(%>]/"5(HG(/PDN:+T(BV4_QK-KQGP`
+M)"$%F$T64G`PPN4^2)B7M]+&71G#%![&V8VNZ[AR$*:X]T#ARI*!FE%?E0)Y
+MOV#6KT.@QSE]Q*&92_4!)6?I6W;=9SN!$[D^U^.JL3JY.[]S0`MH@EJ$4^V@
+M6E<.ZK9=?3SM3_OOPS;BR.)4XYKU?]1]U=VD.IEYMC1SMA27,@#[LT741[EW
+MC\[C4,YX.PB;)"`K$$$T5KAT-7L?`5?'MGW:/#^\KS:I?T29]:D9_HG$/_^3
+MI/XAU:=R^Z=N^J<K:#VQFQ?_?G[](D9]N?U[#/ZQ>N*\7C#KLO]X(`5@-H4D
+,'+#X`^%)]I"G!0``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-apm.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-apm.vhd.gz.uu
new file mode 100644
index 0000000..ad1859a
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-apm.vhd.gz.uu
@@ -0,0 +1,18 @@
+# $FreeBSD$
+begin 644 img-1x1-512-apm.vhd.gz
+M'XL(".7%'50``VEM9RTQ>#$M-3$R+6%P;2YV:&0N;W5T`*U6RVX;(13=^RNN
+ME%VD6L#`G739JO&N4I2HZV0Z9B)+36+%EIJ%/SY<'H9Y,+5=QA@Q8N[A<.X#
+M&',/`%:`':`&5#2N)>!7J&\`S*1OPO;<O\*A?7O5[7[SL?3/8>'`.$NM^N9D
+M+RJ09I$:1$.+X)K&<`@PRZO;Y^O-RW.`$QXN+"P1I`!E0.1H'61'=H2T^O[P
+MPT(^17;5F%VT,O_?$I@$SI,OJL#NZ<CQ"">-5=?95D/36)JA]5YZ$W&S`SC%
+M!E8)S2E1D\U.P>&<U3EPUPOO"Q<J)C!JTQOI.-2"QB9L@@ZC9D+E8[=MWG=Z
+MP$]D0@6/_/AHKLIO5_A0$>%CST!2.,]M%RS*?@@W$2K_I1[V[:0?&!&8"A/"
+M;K^O7H2"E!]R-J-YWAE9?@WQ,ZFI1$AVVZI_;?CVGF#8T!U-QKL7Z]?2M,D0
+MN9Z*BO@RS-V[GY/ATA(_R2F,*9);BN%3^'W;;O_H"3A1:KL.KAJS4YW/.9MT
+MKD3;WI5NU05VCR;;]IO]YNWU,<!1H:)2:Q%/9_?2;"?9J<*^U2?Z-B2-\(!]
+MWT+@ITO'GK;N0!*>3D@5SR"Q-L05S9GW$>#J76MS"GWYM7I(]=.R+#_.3M!/
+M)/JY)$GU2VL+SQWBE_.;U8\.DWHB-J-^N[\N$`._TOH)KQ]K)OK\Q.%NV?\Y
+M0.&+:;'J+&+U*\-0>L!B#&7,X5(,.<XZ\UPOHV=8Z*J+^2ISR567X`I>==&7
+BK*P5.^NJB[YD%;KJ$ES!JR[!%;WJHBVHBT^(Z?)+'PT`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-apm.vhdf.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-apm.vhdf.gz.uu
new file mode 100644
index 0000000..189b488
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-apm.vhdf.gz.uu
@@ -0,0 +1,15 @@
+# $FreeBSD$
+begin 644 img-1x1-512-apm.vhdf.gz
+M'XL(".7%'50``VEM9RTQ>#$M-3$R+6%P;2YV:&1F+F]U=`"M54UOPC`,O?,K
+M+.V&M*I-'(<=-PUND]#0SE!HBRH-J!C2=NB/7SYI2@MB4U,K2N3F]?G9<>/8
+M#@`4(!C$RF)GW,S-_L*@GKY':L21'_7(@B6W3EV'BRY&/1I;0*;=(@;,.N=X
+M")BT'?7\[1+0PFE^F(",M=$&2-S%[[FJ/O,>.#94N!:.=]F)PJP3`,E`(M"3
+MFZD`RK7;L5M6Z?%4GLK#?NGA4,%1I@_+O[#;I54O.S%P;O'.W*);,`?8SBUX
+M?CAT[:%)!VGA52*4(0/!`1%8IH@+[5/[#N#LF.<OB]?'C]DBU`]Q8'YTAWXL
+MT,]>DE`_"/G1T/K13?TD!RE[:K/1[^O;%J+G-[1^$Z=?G/;,UQWU/&H_%A`=
+MX&`,R75GXNZN:Q&Y[P&3$)`UZ36`F\,^WYS*G_`&D^O.1=%O^CSC^E]`$EAJ
+M6DRFUP&_A^EV7.ZV'LYW/_]AE>MSBB^CI':X,Y5@`[EJV/&N2!2JMT9=RTG2
+M"MRQ6X7J63@\!YL7L!:&IK?6IN7H[<T:SG2_\.7_YM;"T<"EHGZ4HU\LKXQY
+$T@<`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-apm.vmdk.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-apm.vmdk.gz.uu
new file mode 100644
index 0000000..d704c00
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-apm.vmdk.gz.uu
@@ -0,0 +1,82 @@
+# $FreeBSD$
+begin 644 img-1x1-512-apm.vmdk.gz
+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
+G]:M]_=S]G9_\=_^%\X>+[?_6A+E/:+;"W-U\-GWU?YW"XEV37@``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-bsd.qcow.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-bsd.qcow.gz.uu
new file mode 100644
index 0000000..1aab948
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-bsd.qcow.gz.uu
@@ -0,0 +1,125 @@
+# $FreeBSD$
+begin 644 img-1x1-512-bsd.qcow.gz
+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
+C[Q7![H=9_O+<'G[4'_CVK[?W_[D;''X,_O'_LNY7-X&E````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-bsd.qcow2.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-bsd.qcow2.gz.uu
new file mode 100644
index 0000000..0fb9958
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-bsd.qcow2.gz.uu
@@ -0,0 +1,21 @@
+# $FreeBSD$
+begin 644 img-1x1-512-bsd.qcow2.gz
+M'XL(")$[(U0``VEM9RTQ>#$M-3$R+6)S9"YQ8V]W,BYO=70`K9C;DM)`$(;O
+M>8I9SZZ*F>Y)2#RLNNM:Y9W>Z#6P\!0\O!NFR22=_C-(!5*IHH;_JY[,EV9"
+M4<27<Z5WH7*A<?N->_PL![G>A^'A#K]__%SV7X=%A/D"I(R!P!UNP+I+.$*X
+MPH\'O(WK5<<&CDZI,2B'"["ZJ0$#=[TX7KKC8M0JP9<`(PXNQD7U4:Q/)\*%
+M]='<];%]_<I33@]4T_5QK$^G5@A79W%DI!J$6V=Q;*0V"+?-XH*1>D"X7197
+M&JD]P/F,*H^XRDAYA*,L;F6D&.%"%E<;*>2=SWO7&"GDG<][MS92R#N?]VYC
+MI)!W/N_=UD@A[WS>NP<CA;PCX)U+N)V10MZ1\NY*<$\2;F^DD'>DO'LJN&<=
+MSELIY!TI[YX+[D7"&?V.D'>DO'LIN%<)9_0[0MZ1\NZUX*X3SNAWA+PCY=T;
+MP;U-.*/?$?*.E'?O1MYYH]\1\HZ5=^^%522<T>\8><?*.R\X2CBCWS'RCI5W
+M++B0<$:_8^0=*^]*P54)9_0[1MZQ\FXEN#KAC'['R#M6WC6"^Y!P1K]CY!TK
+M[SX*[E/"&?V.D7>LO/LLN)N$,_H=(^^"\NZ+X+XFG-'O`O(N*.^^">XVX8Q^
+M%Y!W07EW)[CO'8ZL5.==4=B'X.Y']RS-N_\,:7_LC3,>F`#6_P.<JC#BFEDG
+M7,8)MQJLC3,>.-PNA^\.>%SA<M6N:EFYFLZM\._]G_&$RQE7..+PXZ@,=`7[
+M<W#'Q]'>-^O^Y@(.##<75PDW^3C:[K%WU@"LKIQ9%JI5KK_.KMD?'U).W5UM
+MS;KU=:D^0V8:3'>B/C>>;ONKT3W=J55L<929KAOB-I-K.UW=U;BZ[<R+P?K.
+M.//.;2'#.S?B:-Y&0/%_J:+]UOB,!PZ_EL-W!`8!SG8%0]7VOL4_.5!JJ4,3
+"````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-bsd.raw.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-bsd.raw.gz.uu
new file mode 100644
index 0000000..874e570
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-bsd.raw.gz.uu
@@ -0,0 +1,10 @@
+# $FreeBSD$
+begin 644 img-1x1-512-bsd.raw.gz
+M'XL(".;%'50``VEM9RTQ>#$M-3$R+6)S9"YR87<N;W5T`*V4P0Z#(`R&[SY%
+MO>Y`2H7IKDMVWVD[.[,]!0\_4%0J`UU",22D[9>_U((X&8`BP/['GG:8J^#+
+M5*=JI)$#ZA:4!GV&SH;C^K$#<YCG[2%",QXG<UEIG-C8C*,]W")8'L$U+BN(
+MM&I)+KB48\+5GE6O.)539Q'X_JM87>KNYMYVF[RPSX`?P`&P\S[BP*6_L.J[
+MQ#*(E9O1!W&YO<.U/%X&.-HI%SCNE>UM7ET=JQL*-Z/93L;!R740/KD3CLH^
+B!#2^+/8/M%'QGG:8N^!K`BH/+':#BARP^@+33Z#K!04`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-bsd.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-bsd.vhd.gz.uu
new file mode 100644
index 0000000..ef644e4
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-bsd.vhd.gz.uu
@@ -0,0 +1,17 @@
+# $FreeBSD$
+begin 644 img-1x1-512-bsd.vhd.gz
+M'XL(".;%'50``VEM9RTQ>#$M-3$R+6)S9"YV:&0N;W5T`*V7/6_#(!"&]_R*
+MD[IEB.",L;M&3>=*E=HUCF-'&?JA)D,&__AR-MA@C).TV`1AP3V\=QR(,-8]
+M`#(!68.L0*;4S@3(1\AR`-6I"[8UUY_0E%^?57D^7E;Z:18=C#/;RC4G>TQ`
+MJ$DRP((FD7MJ0V,PJX?-87G\.!@<:IR96$@0"*F""&\>R7IU1'I>OSZUR.V@
+M+O'5#5;JMQ/`!'!NC4B,NFVOL<<)9577;<F@*%J9IC@?3L?@[`B7LI&5)7,J
+MJ):S4S@Y9W4/;KG0:]&EBDJ,3-4J=!PRI+9*&Q,'KZA4N9R^BY]3-=*'@521
+MO3[N]25A=U&G"IK!6H&@=)YS%UK*>8R;2)5_14^Z=D(W5!!8:CJP==^-WH`"
+M6Y_D;";FX<4(ZBM(G]I;K)BHPQW->N6^/;`D8)K1=D\EY'AK!-\W;U/K6P;2
+MY8^[H\1KN%XPOP67Z+UK49(!%^KH<$RSV(`3<^HH9ZJ[G$TC)W.9C^SL=09>
+M`]\#RZVLMH#]^L*@[]&7@8Z[,_K`=[<@7.:.YQ8.K[@++FXWN[;SZIBOKHR\
+M&/OQSKAQYQ+$W;D=#N,>!-B>+"H#U2B_#G<T+ROW[8"HCZIH9Q^:HRJ60J&!
+MT10J8!59(5:SR79O%DJM,-)%DG`1+Y*$BWB1)%S$BR3A(EXD"1?Q(DFXJ!=)
+/J?XB,+;X!=0\?G%]#```
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-bsd.vhdf.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-bsd.vhdf.gz.uu
new file mode 100644
index 0000000..7edc3a0
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-bsd.vhdf.gz.uu
@@ -0,0 +1,13 @@
+# $FreeBSD$
+begin 644 img-1x1-512-bsd.vhdf.gz
+M'XL(".;%'50``VEM9RTQ>#$M-3$R+6)S9"YV:&1F+F]U=`"ME$UO@S`,AN_\
+M"DN[]8"2D!AZK=:=)TW:K@4*50_=+COLD!^_&`+$?+6;"%$$<OSPVDXL1#L`
+MM`*1SZS+!GN(^6.C7=30%`%-"MJ`0<C<=C%,]L$,]N/X'H?#>IQ<\UK&Q:/1
+MX=0]7"]8/H)+R$LR2C+@E@PM3GB6&'!Z39W+A*C^%*S9*G==;;.17UAGD#7(
+M,XC,VQ0']O6%0=]^*D.Q<%?TP33<G'`IWR\#G+H3+G!<L5K;=75BJJ[<N!C)
+M^&8\>',)PF]NBU/;-@+5=!9W`MVNZ;ILL*\Q?UJ@]L#-,HB^]V$"6`-6@(;>
+M4PVXAS0+@8J?)%M^?5;E]_4GK##AJ"!U/3_)7R5T6S`%E=-/\$SO@;ZGXV5W
+MO5TZ7->JNA]KI*0;!]&3<)&'^W)X>VZ0IT%=,DT2AMDK-`@-4K+`O;H3/\Z$
+HTWVP50V%:61VDWTPPVRK(IP1(Z__UK;%X<9'Q1V^Z!>1V%I#,`<`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-bsd.vmdk.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-bsd.vmdk.gz.uu
new file mode 100644
index 0000000..84e2c3e
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-bsd.vmdk.gz.uu
@@ -0,0 +1,81 @@
+# $FreeBSD$
+begin 644 img-1x1-512-bsd.vmdk.gz
+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
+,!WSS?ZE[ZN&@70``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-ebr.qcow.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-ebr.qcow.gz.uu
new file mode 100644
index 0000000..8e8e277
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-ebr.qcow.gz.uu
@@ -0,0 +1,127 @@
+# $FreeBSD$
+begin 644 img-1x1-512-ebr.qcow.gz
+M'XL("*$S(E0``VEM9RTQ>#$M-3$R+65B<BYQ8V]W+F]U=`"MG=F.'-=R1=_U
+M%<5Y)BLBLJHR.>,"-N"WZP?;K[?&Y_H`?KPY9)[3';4V0[9$-0029&Y4G5Y:
+MA*3%T^OUKV^KU<96PW8U3*O+8?7]Q_.'K>[\X/['ZMM__OM_O+W[[=L?O\9L
+M_9NGTH\'7\4\=V_K'^LVYS^>.J[6TY^8^_YA-'?GU<7_X=7=>;.W<R__^/5F
+M^3E7@_??[FJ>6]ZNB=,;_MSK^YK>KOTZO;_O[;IXNQLUN+TW^,]Y[E_SZW/Q
+M=G=J;KPW=TUOU\7;G=3<_K>PN(#EH.:.Q=R`3YW4W+F8V^!3%YZSWWQN?\UM
+M\2E3<XYSJS:WPZ="S0WWYM9O%Z"7N1&?$MQ9R=V$3PGNK.1NCT\)[JSD[H!/
+M">ZLY.Z(3PGNK.3NA$\)[KSD[HQ/">Z\Y.Z"3PGNO.+.^"G!G5?<&?G.%7=>
+M<6?D.U?<><6=D>]<<><5=T:^<\6=5]P9^<X5=U%Q9^2[4-Q%Q9V1[T)Q%R5W
+MY+M0W$7)'?DN%'=1<D>^"\5=E-R1[T)Q%R5WY+M0W$7)'?DN%'=#R1WY;E#<
+M#25WY+M!<3=4W#D_);@;*NZ<?#<H[H:*.R??#8J[H>+.R7>#XFZHN'/RW:"X
+M&RKNG'PW*.XV%7=.OMLH[C85=TZ^VRCN-B5WY+N-XFY3<D>^VRCN-B5WY+N-
+MXFY3<D>^VRCN-B5WY+N-XFY3<D>^VRCNMB5WY+NMXFY;<D>^VRKNMA5WP4\)
+M[K85=T&^VRKNMA5W0;[;*NZV%7=!OMLJ[K85=T&^VRKNMA5W0;[;*NYV%7=!
+MOMLI[G85=T&^VRGN=B5WY+N=XFY7<D>^VRGN=B5WY+N=XFY7<D>^VRGN=B5W
+MY+N=XFY7<D>^VRGNQI([\MVHN!M+[LAWH^)NK+@;^"G!W5AQ-Y#O1L7=6'$W
+MD.]&Q=U8<3>0[T;%W5AQ-Y#O1L7=6'$WD.]&Q=WRG[_U'/EN4MQ-%7<#^6Y2
+MW$TE=^2[27$WE=R1[R;%W51R1[Z;%'=3R1WY;E+<325WY+M)<3>5W)'O)L7=
+MON2.?+=7W.U+[LAW>\7=ON)NPT\)[O85=QORW5YQMZ^XVY#O]HJ[?<7=AGRW
+M5]SM*^XVY+N]XFY?<;<AW^T5=\O_AM1SY+N#XNY0<;<AWQT4=X>2._+=07%W
+M*+DCWQT4=X>2._+=07%W*+DCWQT4=X>2._+=07%W*+DCWQT4=\>2._+=47%W
+M++DCWQT5=\>*NRT_);@[5MQMR7='Q=VQXFY+OCLJ[HX5=UORW5%Q=ZRXVY+O
+MCHJ[8\7=EGQW5-R=*NZVY+N3XNY4<;<EWYT4=Z>2._+=27%W*KDCWYT4=Z>2
+M._+=27%W*KDCWYT4=Z>2._+=27%W*KDCWYT4=^>2._+=67%W+KDCWYT5=^>*
+MNQT_);@[5]SMR'=GQ=VYXFY'OCLK[LX5=SORW5EQ=ZZXVY'OSHJ[<\7=CGQW
+M5MQ=*NYVY+N+XNY2<;<CWUT4=Y>2._+=17%W*;DCWUT4=Y>2._+=17%W*;DC
+MWUT4=Y>2._+=17%W*;DCWUT$=[9\1\^![VPMN+-UR1WXSM:".UM7W(W\%'-G
+M97\W@N],]7=6]G<C^,Y4?V=E?S>"[TSU=U;V=R/XSE1_9V5_-X+O3/5W5O9W
+M(_C.5']G97\W@N],]7=6]G<C^,Y4?V=E?S>"[TSU=U;V=R/XSE1_9V5_-X+O
+M3/5W5O9W(_C.5']G97\W@N],]7=6]G<C^4[U=U;V=R/Y3O5W5O9W$S\EN"O[
+MNXE\I_H[*_N[B7RG^CLK^[N)?*?Z.RO[NXE\I_H[*_N[B7RG^CLK^[N)?*?Z
+M.RO[NXE\I_H[*_N[B7RG^CLK^[N)?*?Z.RO[NXE\I_H[*_N[B7RG^CLK^[N)
+M?*?Z.RO[NXE\I_H[*_N[B7RG^CLK^[N)?*?Z.RO[NST_);@K^[L]^4[U=U;V
+M=WORG>KOK.SO]N0[U=]9V=_MR7>JO[.RO]N3[U1_9V5_MR??J?[.ROYN3[Y3
+M_9V5_=V>?*?Z.RO[NSWY3O5W5O9W>_*=ZN^L[._VY#O5WUG9W^W)=ZJ_L[*_
+MVY/O5']G97^W)]^I_L[*_FY/OE/]G97]W8&?$MR5_=V!?*?Z.RO[NP/Y3O5W
+M5O9W!_*=ZN^L[.\.Y#O5WUG9WQW(=ZJ_L[*_.Y#O5']G97]W(-^I_L[*_NY`
+MOE/]G97]W8%\I_H[*_N[`_E.]7=6]G<'\IWJ[ZSL[P[D.]7?6=G?'<AWJK^S
+MLK\[D.]4?V=E?W<@WZG^SLK^[LA/">[*_NY(OE/]G97]W9%\I_H[*_N[(_E.
+M]7=6]G='\IWJ[ZSL[X[D.]7?6=G?'<EWJK^SLK\[DN]4?V=E?W<DWZG^SLK^
+M[DB^4_V=E?W=D7RG^CLK^[LC^4[U=U;V=T?RG>KOK.SOCN0[U=]9V=\=R7>J
+MO[.ROSN2[U1_9V5_=^*G!'=E?W<BWZG^SLK^[D2^4_V=E?W=B7RG^CLK^[L3
+M^4[U=U;V=R?RG>KOK.SO3N0[U=]9V=^=R'>JO[.ROSN1[U1_9V5_=R+?J?[.
+MRO[N1+Y3_9V5_=V)?*?Z.RO[NQ/Y3O5W5O9W)_*=ZN^L[.].Y#O5WUG9WYW(
+M=ZJ_L[*_._-3@KNROSN3[U1_9V5_=R;?J?[.RO[N3+Y3_9V5_=V9?*?Z.RO[
+MNS/Y3O5W5O9W9_*=ZN^L[._.Y#O5WUG9WYW)=ZJ_L[*_.Y/O5']G97]W)M^I
+M_L[*_NY,OE/]G97]W9E\I_H[*_N[,_E.]7=6]G=G\IWJ[ZSL[\[D.]7?6=G?
+M7?@IP5W9WUW(=ZJ_L[*_NY#O5']G97]W(=^I_L[*_NY"OE/]G97]W85\I_H[
+M*_N["_E.]7=6]G<7\IWJ[ZSL[R[D.]7?6=G?7<AWJK^SLK^[D.]4?V=E?W<A
+MWZG^SLK^[D*^4_V=E?W=A7RG^CM?OI/F5GT.?/?]*>;.4W^WW*>WZMR![USU
+M=Y[ZN]7,W6KA+M;\%'/GJ;];S=RM_M7FP'>N^CM/_=WJFLXNZ/X[5_V=I_ZN
+MG5V?`]^YZN\\]7<P![YSU=]YZN]@#GSGJK_SU-\M<P_Z'/C.57_GJ;][L,RM
+MVASXSE5_YZF_>S!S]Z!S![YSU=]YZN\>S-P]Z-R![USU=Y[ZNP?7F[,#W[GJ
+M[SSU=^WL^ASXSE5_YZF_@SGPG:O^SE-_!W/@.U?]G:?^;IE[V.?(=ZJ_\]3?
+M/5SF.G?D.]7?>>KO'L[</6S<T?UWKOH[3_W=PYF[AXT[NO_.57_GJ;][>,UG
+M1_??N>KO//5W[>SZ'/E.]7>>^CN8(]^I_LY3?P=SY#O5WWGJ[Y:Y1WV.?*?Z
+M.T_]W:-EKG%']]^YZN\\]7>/9NX>=>[(=ZJ_\]3?/9JY>]2Y(]^I_LY3?_?H
+M>G-VY#O5WWGJ[]K9]3GRG>KO//5W,$>^4_V=I_X.YLAWJK_SU-\M<X_['/E.
+M]7>>^KO'RUSGCGRG^CM/_=WCF;O'C3NZ_\Y5?^>IOWL\<_>X<4?WW[GJ[SSU
+M=X^O^>SH_CM7_9VG_JZ=79\CWZG^SE-_!W/D.]7?>>KO8(Y\I_H[3_W=,O>D
+MSY'O5'_GJ;][LLPU[NC^.U?]G:?^[LG,W9/.'?E.]7>>^KLG,W=/.G?D.]7?
+M>>KOGEQOSHY\I_H[3_U=.[L^1[Y3_9VG_@[FR'>JO_/4W\$<^4[U=Y[ZNV7N
+M:9\CWZG^SE-_]W29Z]R1[U1_YZF_>SIS][1Q1_??N>KO//5W3V?NGC;NZ/X[
+M5_V=I_[NZ36?'=U_YZJ_\]3?M;/K<^0[U=]YZN]@CGRG^CM/_1W,D>]4?^>I
+MOUOFGO4Y\IWJ[SSU=\^6N<8=W7_GJK_SU-\]F[E[UKDCWZG^SE-_]VSF[EGG
+MCGRG^CM/_=VSZ\W9D>]4?^>IOVMGU^?(=ZJ_\]3?P1SY3O5WGOH[F"/?J?[.
+M4W^WS#WO<^0[U=]YZN^>+W.=._*=ZN\\]7?/9^Z>-^[H_CM7_9VG_N[YS-WS
+MQAW=?^>JO_/4WSV_YK.C^^]<]7>>^KMV=GV.?*?Z.T_]'<R1[U1_YZF_@SGR
+MG>KO//5WR]R+/D>^4_V=I_[NQ3+7N*/[[USU=Y[ZNQ<S=R\Z=^0[U=]YZN]>
+MS-R]Z-R1[U1_YZF_>W&].3ORG>KO//5W[>SZ'/E.]7>>^CN8(]^I_LY3?P=S
+MY#O5WWGJ[Y:YEWV.?*?Z.T_]W<MEKG-'OE/]G:?^[N7,W<O&'=U_YZJ_\]3?
+MO9RY>]FXH_OO7/5WGOJ[E]=\=G3_G:O^SE-_U\ZNSY'O5'_GJ;^#.?*=ZN\\
+M]7<P1[Y3_9VG_FZ9>]7GR'>JO_/4W[U:YAIW=/^=J_[.4W_W:N;N5>>.?*?Z
+M.T_]W:N9NU>=._*=ZN\\]7>OKC=G1[Y3_9VG_JZ=79\CWZG^SE-_!W/D.]7?
+M>>KO8(Y\I_H[3_W=,O>ZSY'O5'_GJ;][O<QU[LAWJK_SU-^]GKE[W;BC^^]<
+M]7>>^KO7,W>O&W=T_YVK_LY3?_?ZFL^.[K]SU=]YZN_:V?4Y\IWJ[SSU=S!'
+MOE/]G:?^#N;(=ZJ_\]3?+7-O^ASY3O5WGOJ[-\M<XX[NOW/5WWGJ[][,W+WI
+MW)'O5'_GJ;][,W/WIG-'OE/]G:?^[LWUYNS(=ZJ_\]3?M;/K<^0[U=]YZN]@
+MCGRG^CM/_1W,D>]4?^>IOUOFWO8Y\IWJ[[SJ[X+NOW/5WWG5WP7=?^>JO_.J
+MOPNZ_\Y5?^=5?Q=T_YVK_LZK_B[H_CM7_9U7_5W0_7>N^CNO^KN@^^]<]7<N
+M^KMW?8Y\I_H[3_W=NV6N<4?WW[GJ[SSU=^]F[MYU[LAWJK_SU-^]F[E[U[DC
+MWZG^SE-_]^YZ<W;D.]7?>>KOVMGU.?*=ZN\\]7<P1[Y3_9VG_@[FR'>JOXOE
+M.VENW>?`=Z'ZN^\_<8^[Q4_KSAWX+E1_%ZF_6\][Z\8=W7\7JK^+U-^M9^[6
+MC3NZ_RY4?Q>IOUM?\]G1_7>A^KM(_5T[NSX'O@O5WT7J[V`.?!>JOXO4W\$<
+M^"Y4?Q>IOUOFK,^![T+U=Y'Z.UOF&G=T_UVH_BY2?V?SR[/.'?@N5'\7J;^S
+MF3OKW('O0O5WD?H[N]Z<'?@N5'\7J;]K9]?GP'>A^KM(_1W,@>]"]7>1^CN8
+M`]^%ZN\B]7?+G/<Y\IWJ[R+U=[[,=>[(=ZJ_B]3?^<R=-^[H_KM0_5VD_LYG
+M[KQQ1_??A>KO(O5W?LUG1_??A>KO(O5W[>SZ'/E.]7>1^CN8(]^I_BY2?P=S
+MY#O5WT7J[Y:YZ'/D.]7?1>KO8IEKW-']=Z'ZNTC]7<S<1>>.?*?ZNTC]7<S<
+M1>>.?*?ZNTC]75QOSHY\I_J[2/U=.[L^1[Y3_5VD_@[FR'>JOXO4W\$<^4[U
+M=Y'ZNV5NZ'/D.]7?1>KOAF6N<T>^4_U=I/YNF+D;&G=T_UVH_BY2?S?,W`V-
+M.[K_+E1_%ZF_&Z[Y[.C^NU#]7:3^KIU=GR/?J?XN4G\'<^0[U=]%ZN]@CGRG
+M^KM(_=TRM^ESY#O5WT7J[S;+7...[K\+U=]%ZN\V,W>;SAWY3O5WD?J[S<S=
+MIG-'OE/]7:3^;G.].3ORG>KO(O5W[>SZ'/E.]7>1^CN8(]^I_BY2?P=SY#O5
+MWT7J[Y:Y;9\CWZG^+E)_MUWF.G?D.]7?1>KOMC-WV\8=W7\7JK^+U-]M9^ZV
+MC3NZ_RY4?Q>IO]M>\]G1_7>A^KM(_5T[NSY'OE/]7:3^#N;(=ZJ_B]3?P1SY
+M3O5WD?J[96[7Y\AWJK^+U-_MEKG&'=U_%ZJ_B]3?[6;N=IT[\IWJ[R+U=[N9
+MNUWGCGRG^KM(_=WN>G-VY#O5WT7J[]K9]3GRG>KO(O5W,$>^4_U=I/X.YLAW
+MJK^+U-\M<V.?(]^I_BY2?S<N<YT[\IWJ[R+U=^/,W=BXH_OO0O5WD?J[<>9N
+M;-S1_7>A^KM(_=UXS6=']]^%ZN\B]7?M[/H<^4[U=Y'Z.Y@CWZG^+E)_!W/D
+M.]7?1>KOEKFISY'O5'\7J;^;EKG&'=U_%ZJ_B]3?33-W4^>.?*?ZNTC]W31S
+M-W7NR'>JOXO4WTW7F[,CWZG^+E)_U\ZNSY'O5'\7J;^#.?*=ZN\B]7<P1[Y3
+M_5VD_FZ9>]_GR'>JOXO4W[U?YCIWY#O5WT7J[][/W+UOW-']=Z'ZNTC]W?N9
+MN_>-.[K_+E1_%ZF_>W_-9T?WWX7J[R+U=^WL^ASY3O5WD?H[F"/?J?XN4G\'
+M<^0[U=]%ZN^6N0]]CGRG^KM(_=V'9:YQ1_??A>KO(O5W'V;N/G3NR'>JOXO4
+MWWV8N?O0N2/?J?XN4G_WX7IS=N0[U=]%ZN_:V?4Y\IWJ[R+U=S!'OE/]7:3^
+M#N;(=ZJ_B]3?+7,?^QSY3O5WD?J[C\M<YXY\I_J[2/W=QYF[CXT[NO\N5'\7
+MJ;_[.'/WL7%']]^%ZN\B]7<?K_GLZ/Z[4/U=I/ZNG5V?(]^I_BY2?P=SY#O5
+MWT7J[V".?*?ZNTC]W3+WJ<^1[U1_%ZF_^[3,->[H_KM0_5VD_N[3S-VGSAWY
+M3O5WD?J[3S-WGSIWY#O5WT7J[SY=;\Z.?*?ZNTC]73N[/D>^4_U=I/X.YLAW
+MJK^+U-_!'/E.]7>1^KME[G.?(]^I_BY2?_=YF>O<D>]4?Q>IO_L\<_>Y<4?W
+MWX7J[R+U=Y]G[CXW[NC^NU#]7:3^[O,UGQW=?Q>JOXO4W[6SZW/D.]7?1>KO
+M8(Y\I_J[2/T=S)'O5'\7J;];YK[T.?*=ZN\B]7=?EKG&'=U_%ZJ_B]3??9FY
+M^]*Y(]^I_BY2?_=EYNY+YXY\I_J[2/W=E^O-V9'O5'\7J;]K9]?GR'>JOXO4
+MW\$<^4[U=Y'Z.Y@CWZG^;EB^D^:^]CGPW:#ZNR'U=U^7N<X=^.[[4\S=D/J[
+MKS-W7Q?NAC4_Q=P-J;_[.G/W]5]M#GPWJ/ZN?2QSN3<>Z/Z[_E0Q=^?;MS]>
+M_AS<T,T\Q>#E@H._YGZ0]_T7?/_8;^;O?/]8VYVY'U]2V/3K>W!WCK[R\5]Z
+MN_3%V7\SN-FL]ON;P?]:7M_/RW0&7ZWW\'?]$]_^\?;^7^WU_?S3VYO=:MBL
+M-MO5Z'_V#?_/O_TW?3KH3V___\[OUUQ)7WO!]F?F?OYN>^=7WB5#_\2WCLG;
+M.]?6;>A/;_<7\4,O9_H)^>KHJ[W_%?9N_H3TW<_SSZ\7__U?C9?_^Y&N$6V?
+MWU5_?524WWN[OWE]J]NW^_-WM-W]7V]WYKQXNZO[<X???FY__^H>W+XZ^HKJ
+M?^63<?/G?/_D/[D_1N[_D_MKSO]>$>Q^FN7';SI[^+O^B6__?'O_KU^#PSSX
+3MYW@L!Z_O\H__A<I;[G$7Z<`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-ebr.qcow2.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-ebr.qcow2.gz.uu
new file mode 100644
index 0000000..07c721f
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-ebr.qcow2.gz.uu
@@ -0,0 +1,22 @@
+# $FreeBSD$
+begin 644 img-1x1-512-ebr.qcow2.gz
+M'XL("),[(U0``VEM9RTQ>#$M-3$R+65B<BYQ8V]W,BYO=70`K9=;L](P$,??
+M^13!RU&/BLUN4HJ7HYZ+,[[I@_I<+OT4?'C;9FG:[6X#3*'#P(3_;S;DEZ7)
+MLO`PQEOC<N,VIMJ:^C-=8'H?AI<Y_O[Q<]5_'!<!9C,E)0PX['`#UD/$@8;+
+M['C`RKA>=2C@X)0:@U(XIU8W-2#@;A?M3]<N1L$2>`TPX-3%N*H^"/7QA+NR
+M/IB[/I1_/W_*\8%\NCX,]?'46L,521P(J8V&*Y,X%%);#;=+XIR0VFNX0Q+G
+MA52EX&Q"E1J7"RFKX2")6PLIU'`NB2N$E.:=37NW$5*:=S;M72FD-.]LVKNM
+MD-*\LVGO=D)*\\ZFO=L+*<T[4+PS$7<04IIWP+Q;$NY9Q%5"2O,.F'?/"?>B
+MPUDII7D'S+N7A+N).*'?@>8=,.]>$>YUQ`G]#C3O@'GWAG"W$2?T.]"\`^;=
+M6\*]BSBAWX'F'3#OWH^\LT*_`\T[9-Y](%86<4*_0\T[9-Y9PD'$"?T.->^0
+M>8>$<Q$G]#O4O$/FG2=<'G%"OT/-.V3>K0E71)S0[U#S#IEW&\)]C#BAWZ'F
+M'3+O/A'N<\0)_0XU[Y!Y]X5P=Q$G]#O4O'/,NZ^$^Q9Q0K]SFG>.>?>=</<1
+M)_0[IWGGF'</A'OL<""E.N^R3+X(]S3:LS#O_:>+]\=6>-4')H#%)<"I"@-N
+M,^N$?=@;EP&K2JO/A[U1?Z&^2D]OZBM,C_*V]P<LU+?LX_9S3[>Z#.B]*<L1
+M\,^IOE;G9A.5PJL^<+Q?#9]=?:X!^G6S)WQN"CAWPO^>_DK+X6;;'P&G'^9I
+MH"O8GH-K#_.];_;-T`>&MV;+B)L\S#<GE(,TH%;G9W;/%2S77^?V:+6+9U!V
+M8]NMKXGU":T`!M.=J,^,I]O\YW9G8[:*[0(DIFN&N.WDVDY7MQQ7MYMY,3S?
+M&6?NW`8RW+D!!_,V`F@[2VU@_:WQJSYP_+4:/@/0$7"V7]#ES5_EXC\C;N3L
+$@10`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-ebr.raw.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-ebr.raw.gz.uu
new file mode 100644
index 0000000..70326d3
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-ebr.raw.gz.uu
@@ -0,0 +1,11 @@
+# $FreeBSD$
+begin 644 img-1x1-512-ebr.raw.gz
+M'XL(".?%'50``VEM9RTQ>#$M-3$R+65B<BYR87<N;W5T`*V4S0Z#(`S'[SY%
+M=]W!0`?379?LOLNV,[KY%#S\BO@!(J@)@&A2^LN_MH4Q.P#H65UQ@RX70Q?G
+MHJ?QYC"PZU:!%M>2%QV@I>3P08MQ!\<9((_K.[FX;^YPNV-`*4&I`/@:]:'Q
+M$@A,K>QQ@[Z7_IST"0.4%0@)\@HU[@WX\WBOI4/P7/_/XG`+-PGF>W`7X^6<
+M="LC;M!SF=CWB!,I=81@OT/!RLRU)^J%GYMG8-0E+;!ZL*$/G/(+L[Y;*`.]
+M<!/Z(`Q7&5SEG^<.#C?"!1_7)'.;5G<*U;69DR&7G;&S<PW$[UR+P[P7`?8W
+>"U4@G0KWN$$_2W]:H!B`V?Z@0`,L_F-6J)F4!@``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-ebr.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-ebr.vhd.gz.uu
new file mode 100644
index 0000000..c1f997c
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-ebr.vhd.gz.uu
@@ -0,0 +1,18 @@
+# $FreeBSD$
+begin 644 img-1x1-512-ebr.vhd.gz
+M'XL(".?%'50``VEM9RTQ>#$M-3$R+65B<BYV:&0N;W5T`*V735/#(!"&[_T5
+MZWCST($-;-JKHYZ=<=2K:4P<#WZ,>O"0'R\$2"`)V"A-2I.!??+NLFPH8^8#
+M0`50"]0`27U="J`]E#L`U6E/[%MN;Z&KWUZ;^NOY>VL_W<;`./.M0G-MCP4(
+M]9`2L-(/H4=]#9W#;$\OG\Z>7YX<#BW./5@0"`2I(&+V'&*#.DVZ.K^YZ)$/
+MH[IBKFZT4M^#`":`<V]$X=0]#!H'G%!6;=N?)515+].=P4W0,3H[P4DVL?)D
+M+@75<W8)1RFK-;BSC9T+DRHJ,4K5JM!Q*%%?J[1Q<9B=*E6^/]^KC\]FH@\C
+MJ4*#/C[K*^+NHDT5=(.M`J'3.>4N])2O*6XA5?X5/0KMA+U006#2=6#O?AB]
+M$06^/N(L$?/X9$3U54F__N#PX;`:&%%H</7@<"5'CTR2C,%$'M=WXN,><[O;
+MK@-*J2O&%'CK]-7:2I4Z5BVT\8[N?!L>@[Y&`V6IJZ\DV.&Q#M]?WBU-1Q-9
+MO>OC9W#X&VX0S(_!%;:4NI%^9L0[NC%-S*_#B90ZO82;5<[*S+G7["9V_CP#
+M4ZND!K:S?1@"A_F%4=]^+@,#=Q/Z8.YNI7%E.)Y[./S%70AQA^3<IM6=S-75
+MF2>CG:Z,(U>NAH0KU^`P;R'`OK*H#%2CYFV\H[O>AH<!HGUS9'L5H:U]V10*
+M"\RF4+ABFD]AP9+)MC8+R2K,M*^G>+G_R[Z>O'*?85]/KMS'K-BJ?3W9<I]I
+;7T^NW.?9UVM<UGT]J7]LC&U^`&IC,XL,#@``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-ebr.vhdf.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-ebr.vhdf.gz.uu
new file mode 100644
index 0000000..c7d0a81
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-ebr.vhdf.gz.uu
@@ -0,0 +1,14 @@
+# $FreeBSD$
+begin 644 img-1x1-512-ebr.vhdf.gz
+M'XL(".?%'50``VEM9RTQ>#$M-3$R+65B<BYV:&1F+F]U=`"ME;%N@S`0AO<\
+MQ47=,D2VL0^R1DWG2E7;-4`@RI!VZ="!AZ^-,?%A(*0R&#`ZW\=_OK-AS!X`
+M^AIMTX9F.SB:U6;5TGCQ,+"N1X$65VHO/4"W7'4=W1CW<)R!X-/ZUC[N%#O<
+M^C&@4I#G`?#=Z1/&2PI@^<A]VM#LM_3L]4D#5"E(!0HA$TL#_CQ\C*5#\ECS
+M9W'B'JX7S)?@$N/EC?0K8]K0W,K$/AU.SJG3"%8]%*R*7'LR&_CY>0:F5TD)
+M+.ML@@+[_,)-WRZ4(4BX,_H@##<WN)2.YQY.W`D7**Z8S>V\NG6HKHR<##5<
+M&0M7KH'0E6MQ(NY&(-J=15>@'A7>IPW-ZY:>%B@[8+09Q.Y7A`E@#5@!*M-/
+M)>`.TLP'"EI)3?G]594_EU\_PP;'^S]'V(R_2,QJP11$;CZ")]/W]#T=SIO+
+M]>QP;JMR'Y9H)EUIB`S"11KNR_[MN44>;^J2<)+0G[U"`I/`.0F\4W>DY8SM
+H/N^"K6HH5"O3-?)"#*-;E<$I-O#Z;VXM#B.7BJZ]U1_9@4$XOP@`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-ebr.vmdk.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-ebr.vmdk.gz.uu
new file mode 100644
index 0000000..9ad3787
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-ebr.vmdk.gz.uu
@@ -0,0 +1,82 @@
+# $FreeBSD$
+begin 644 img-1x1-512-ebr.vmdk.gz
+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
+=_,;UN]/^SY:P]`G-.EBZ#T[+O_H__903[2]?````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-gpt.qcow.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-gpt.qcow.gz.uu
new file mode 100644
index 0000000..93e4a77
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-gpt.qcow.gz.uu
@@ -0,0 +1,132 @@
+# $FreeBSD$
+begin 644 img-1x1-512-gpt.qcow.gz
+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
+4N4?](MX>AAN9_O;_@'C+'O6L````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-gpt.qcow2.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-gpt.qcow2.gz.uu
new file mode 100644
index 0000000..7528fc4
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-gpt.qcow2.gz.uu
@@ -0,0 +1,26 @@
+# $FreeBSD$
+begin 644 img-1x1-512-gpt.qcow2.gz
+M'XL(")4[(U0``VEM9RTQ>#$M-3$R+6=P="YQ8V]W,BYO=70`K9A+;YPP$(#O
+M^15.WTT:BL<VC[Z3-"OE4B55>VL/+(]3%:EWVM]>C`T&,P/)UKMHE<B:3V/S
+MS=@0Q^;#F.),)DSFK-FS[G][`9O\,[]8>[N[CJ:?]LC`>$Q$(0-2C+@9Z]+A
+M@,+%?#G`<=PD.X'@8(A:@K9PDLQN;0#!G1SU2]??C,R+$(<`#8Z\&0?E!R8_
+M/T(>F!^$SD_@ZZ>&.'\@6<]/F/S\J)3"99LX0*)R"E=LX@02M:=PY29.(E$5
+MA:LW<0J):@@<WU"EPR5(%*=PL(E+D2A!X>0F+D.B*._XMG<Y$D5YQ[>]*Y`H
+MRCN^[=T>B:*\X]O>E4@4Y1W?]JY"HBCO@/"..5R-1%'>@>?=L<4]<K@&B:*\
+M`\^[QQ;W9,1Q+(KR#CSOGEK<,X=#^AU0WH'GW7.+>^%P2+\#RCOPO'MI<2<.
+MA_0[H+P#S[M3BWOE<$B_`\H[\+P[6WC'D7X'E'?"\^ZU9<4.A_0[07DG/.^X
+MQ8'#(?U.4-X)SSMA<=+AD'XG*.^$YYVRN,3AD'XG*.^$YUUJ<9G#(?U.4-X)
+MS[O<XMXX'-+O!.6=\+Q[:W'O'`[I=X+R3GC>O;>X#PZ']#M!>2<][SY:W">'
+M0_J=I+R3GG?G%G?A<$B_DY1WTO/NTN(^CSC`HD;OXAB_+.YJ4;.`]#N9W!.W
+M6^+HAY5#CK/2';<Y\DL/K`"SAP/)O5::<TJX"2LS86U5@?S2`^U%-/^.P+YV
+M'P`<,ISC[(25J5WSP%C7K&GL95;*!F>3`P(RX>-H@JL"KU]?;@\`*L6*8@'\
+M/N37EUM77^;=0&>WZIN!`J;DB.OGJLII?E>[:W9S_O6;AOUPT^W+3>-J_;!4
+M)%YVG)KNU1?$/F7*+6W\U1YP@L*-QS(/IX\7:;6"PR[6_B%P<BUJ?.EPCWMK
+M<"J>1TW;%LL4RX`E):L*$O=KADL"FR?U\#YA:<F26K]/*AO]1Y7HIS26=65B
+MMFWHSU@Y2[D^NW7`]NXVNC.PL^CWJ<U/<FL$=M$#U.I)6#-")[4Q73;'8:^1
+M_FOU=%_>JV"KEUM9L(L>(%>O,*N'+Y)."BV9=EBUH>`&W#[PZB5ZN*N/KG\O
+M?^F!]B::?PU06F"P#&72E`&K0^,"5H?&!:P.C0M:'1H8L#HT+F!U:%S`ZM"X
+MH-71`>LXW":N<=J]/&.J8KED335/@]R.V^@G.MT:UK;^E4T<OQEUP$U<XU8W
+?\;0F)VL_?[W)!MS$-2[H)BY3??P^^@=.=Z`2%1H`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-gpt.raw.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-gpt.raw.gz.uu
new file mode 100644
index 0000000..98d9945
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-gpt.raw.gz.uu
@@ -0,0 +1,15 @@
+# $FreeBSD$
+begin 644 img-1x1-512-gpt.raw.gz
+M'XL(".C%'50``VEM9RTQ>#$M-3$R+6=P="YR87<N;W5T`*V534_#,`R&[_L5
+MWA5$E*1)FIWXD$#B-A#<N/1C/:%)W,M_)VX:UG9Q89+3J*KD^JGM^*VEC`O`
+M:)!5YDX;^@<QO_K-U6:@J?HR8/@^AK``B@",N"88I<9W#@?HNG%+-7A%9VE!
+MJ_0\XL1I;<4$UYZ\SC9MF.)$Q*5TN\N`UD)5G0'?4WQZ.`X+QH'9@0[O2S`*
+MK`9K?G%#KK:9QO?X]`S[^]<WA'V<TM4J&%4#1D)30MLMHE-DNG?+="-.HY=9
+M5COA"A*WS>.*>+8T+K=IG%GSBCWTO[.-."OG7G[JY2UX#:Z!MB)QGS.<8^X\
+M@^;:0=F`.X!5T'3XT#I0*L079.('2*AO"W('I0)=([`_OHACA-V(K^LQ/J/&
+MCLAMVD!5S^BUCL"@_D@7YKB"NWH>JV?9JK<;FR6W:0-9O2I6+U\D4C)]JEI2
+M2,+5S-5S:`[Z"/_O\SMMZ/=B?D6@&8%L$8;F<XSJ0!RC.A#'J`[$L:H#@8SJ
+M0!RC.A#'J`[$L:HC`+WD&^*(&X:X@;*%MH!B.<2I<=R+;W&;2=?KM=&_,L3S
+CA^$9ASCBUH=X02:;UB)9QB&..-8A'H"5E)L?B^NWCH@+````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-gpt.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-gpt.vhd.gz.uu
new file mode 100644
index 0000000..61a70ff
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-gpt.vhd.gz.uu
@@ -0,0 +1,22 @@
+# $FreeBSD$
+begin 644 img-1x1-512-gpt.vhd.gz
+M'XL(".C%'50``VEM9RTQ>#$M-3$R+6=P="YV:&0N;W5T`*V82V^<,!"`[_D5
+M4_66JA0;V[#'1DVDWM+7+8>`@6BE=OM(#E'%CZ_'V(`7FW238;V(E7<^YN7Q
+MR'D^7@"J`-6#ZD!)?"X%J!V4%8"9=(/;.W,_8=`_#YU^V#]F[AK.1AC+EU*A
+M.,KS`H1Y20F\QI>H%I]A\)CL]>7=^?['G<=QA_,O%@H$!VD@8O4>E4_:(>GJ
+MXLL'B[R=M2O6VLU2YML(R`4PMOA'X;6[G72<<,)(];T=)90URDXC^!%,(.YO
+MEJUQ,C^26J@9<^K"V!A.;4F=@CL_<[$84\4D1FGNQG4,2H[/)FV\'U;#I,KC
+M_:_ZSWUWI!]/I(J:]&.KN2)M+G>IPOV?G08"TWG+7+"4AV-<)%5>Y#T5ROGH
+M&B?DTD]P:W[HO1D%2_T4RS=\G@Y&4K\:]3-K*Z\C]_3$<)&%GPG8-*<!O0=#
+MW&1PH]%_MHYTW6S1F"2S8XN-@.0+_S4M<7R;_C2@E%#7*^`WKY^VX9"VX.TP
+M,4QQ$`RD*7YS.EO;I5[J=WGU$:[??_Z*L)O97(WITK6X@DS5[=LC[=8K;3)W
+M'UMLFH_9Q_NHL442]RZZ=C4N-J-4&A<;:9S8DG);V?\74BWS4*I:2E42*@Y*
+M0ULG<=\#''5=[G"Z45!JW,(E`VWW\E;A1@:562:5A7#@)NYF8S>[<(/`X?`I
+M.XRPM]GO-TZ_CKF,B(WT1,I['=_*"%3J"7,AQ%'7Y:Y"[TDR[^U<LL1&>B+I
+MO7KT7MQ)J%1LZ4Z[6I:]"G$-K?>8;1_-^C#U>WU/3PS76?@9@=QM0V3[&G>%
+ME$Q#X8!D&@JW?@DU9&(SF*=&6;F@$%48Q!%6&,015AC$D588!!)6&,015AC$
+M$588Q)%6&$7;""G7".6E#4`!31>JD6QI!A\(WW)X'-]JGS8:H7@P*!LA]50C
+MU'=)8_UU9"QA(Z2H&R'E"BG168;RC=!:A^><92C?""U>_(*S#!5OA)Y[EH$X
+8PK,,Q!&>92"..%6P;SG[!W<O66(`$P``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-gpt.vhdf.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-gpt.vhdf.gz.uu
new file mode 100644
index 0000000..7e6c736
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-gpt.vhdf.gz.uu
@@ -0,0 +1,18 @@
+# $FreeBSD$
+begin 644 img-1x1-512-gpt.vhdf.gz
+M'XL(".G%'50``VEM9RTQ>#$M-3$R+6=P="YV:&1F+F]U=`"METMOU#`0@._[
+M*P;U5D2P'=O)'EO12MS*Z]9#\["KE6`1$@<.^?%X_"!VU@X4.1E%64W\99X9
+M+R'N`.`,R)"YEA7+;9.>R^'Z8&ET?!G0O!]-V``;`W2XR2@)PV>4`JV]$&I7
+MN<5&6K+>6URS'J2)<'.\:B-E18QK'"ZXJU\&%`*&X0+X)=C';#H$<`G\",P\
+M3X!3$`P$_X.SOHLIMN_N_CT\W'S\C+#'U5U&C5+-0%J01]#SQCI:=O>T<=?A
+MC$$8?::SSK9%W-MM]!RN1=R\@\M)&<?W5KD:^K?<.IP@Z:H^7M4+Z!G(">:A
+MB/N:X&3ERN.H'B5T$T@%@L*D\6:60*FQS[1);R$,F,G[$3H*;$3@<O[0G!WL
+M3?/CM;>/4U\1.2DK2M'C;*\BT*B_N`LIKJT=O1ZC)ZI%[^B+)2=E13%Z@XM>
+M/DAH5*YU#<Y'K7F5XL;*T9.H-OUAOM^7U[)B>6C2TP&Y!U:S4&@]5>P.Q%7L
+M#L15[`[$5>T.!%;L#L15[`[$5>P.Q%7M#@-4I-X01YRMO<XFH(51I684Q_$2
+M$A'&9<"QO=&_,\3SR5`5ASCB=H>X5D5GP[%QMN(01US5(2[]]EN:W9GM+RGP
+MON.X6>OZ&,C6FK'`Z?M933]/O^+H(8ZZBL@*KF<M%J;L@`WX$CGC?63?U=WS
+M]>G;<\`Q[U5X,5:TJ6(#X1?NRM3=^]M/[RSR:;4N\YF2<?1&#H3C)R9VW%OW
+ME):*M#N@X*S2F$O"5TE^)(IL(2/.EDK\\/_FUN%JEXKY:W#X#1@%S56S#0``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-gpt.vmdk.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-gpt.vmdk.gz.uu
new file mode 100644
index 0000000..cec7ced
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-gpt.vmdk.gz.uu
@@ -0,0 +1,87 @@
+# $FreeBSD$
+begin 644 img-1x1-512-gpt.vmdk.gz
+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
+BDU_BXY!.-OP\2-;P2]S#F7Z)%_[IG=D7_P=,%9H/M&4`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-mbr.qcow.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-mbr.qcow.gz.uu
new file mode 100644
index 0000000..903950a4
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-mbr.qcow.gz.uu
@@ -0,0 +1,127 @@
+# $FreeBSD$
+begin 644 img-1x1-512-mbr.qcow.gz
+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
+AW_HGOOWS[?U_?@X.\^#?=H+#>OS^*G_[?V9WPD*PIP``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-mbr.qcow2.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-mbr.qcow2.gz.uu
new file mode 100644
index 0000000..0b7d7db
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-mbr.qcow2.gz.uu
@@ -0,0 +1,22 @@
+# $FreeBSD$
+begin 644 img-1x1-512-mbr.qcow2.gz
+M'XL(")<[(U0``VEM9RTQ>#$M-3$R+6UB<BYQ8V]W,BYO=70`K9C9LM,P#$#?
+M^Q4NRP4N4&+)3E.6"]R%&=[@`7A.EWQ%/YXD5N-$D>*VD]:3:<?1&=D^5I8L
+M"Q]CO#4N-VYCJJVI_U,#T_LS;.;X^\?/5?]S7`28S90HH<-AAQNP'B(.-%QF
+MQQU6QO6R0P$'IZ@Q*(5S:G93'0+N=M%.7;L8!8O`:X`!IR[&5?E!R(]'N"OS
+M@[GS0WG^_"F.=^33^6'(CT>M-5R1Q($0M=%P91*'0M16P^V2."=$[37<(8GS
+M0E2EX&Q"E1J7"U%6PT$2MQ:B4,.Y)*X0HC3O;-J[C1"E>6?3WI5"E.:=37NW
+M%:(T[VS:NYT0I7EGT][MA2C-.U"\,Q%W$*(T[X!YMR3<LXBKA"C-.V#>/2?<
+MBPYGI2C-.V#>O23<3<0)]0XT[X!Y]XIPKR-.J'>@>0?,NS>$NXTXH=Z!YATP
+M[]X2[EW$"?4.-.^`>?=^Y)T5ZAUHWB'S[@.QLH@3ZAUJWB'SSA(.(DZH=ZAY
+MA\P[))R+.*'>H>8=,N\\X?*($^H=:MXA\VY-N"+BA'J'FG?(O-L0[F/$"?4.
+M->^0>?>)<)\C3JAWJ'F'S+LOA+N+.*'>H>:=8]Y])=RWB!/JG=.\<\R[[X2[
+MCSBAWCG-.\>\>R#<8X<#*:KS+LOD1KBGT9Z%>>\_7;P_ML)1[Y@`%I<`IS(,
+MN,VL`_9AP(T&I7#4.X[WJ^&W`[:;[0)@/3]5-0+2@'W8;/4)=2L]_:A;F"\:
+MGNU=T84!+U<]W'[F^6OWQP5`[TU9CH!_3OG!W,OA&J!?-YO,YZ:`<P?\[^GO
+MV+\:-]N&"SC][0!U=`G;<W#MVX'>F7TS]([AO=XRXB;?#C2//`>I0\W.S^R>
+M*UA<?YW;9[5=?*AE=\K=^IJ8GU!;8##<B?S,>+C-1;Q[V&:KV"Y`8KAFB-M.
+MKNUT=LMQ=KN9%\/SG7'FSFT@PYT;<#!O(8"VLM0&UF>-CWK'\==J^`U`1\#9
+09M#ES:5H\1\W+X2OTA0`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-mbr.raw.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-mbr.raw.gz.uu
new file mode 100644
index 0000000..494fe71
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-mbr.raw.gz.uu
@@ -0,0 +1,11 @@
+# $FreeBSD$
+begin 644 img-1x1-512-mbr.raw.gz
+M'XL(".G%'50``VEM9RTQ>#$M-3$R+6UB<BYR87<N;W5T`*V4R[+"(`R&]WV*
+MN'7!A`C'NG7&O1MUC?7T*7AX@^D%BJWM#)!29@+?_"$$1&D`A@#=EW'>X<\J
+M[;[:5Q^:?FX#U@AMFP$5`P77,(X7L#G;3=A00Q#.'YM&(-W-Q<"KL>U4A'L-
+MNW*;=\0X);@^W'8;T%IP+@/>>GU4.ATF`.T1C`7[!S6M#?AQN4\"%IPN=7Z"
+MHU^X0;!>@SN$7='*^&;,._QX3>3?X\R2.D;@_Z9@;>&[9^K)OCC/@%PE#6#=
+M^2@%#OF%4=\IET%)N`OZ(`_7!=PQ7:\C'/T(%U+<<S&WR^IVN;JF<#+LM#)6
+K5FZ`I)4K."K[$-#G9>$;R*OR<=[AKRKM`C0=L-@)&@K`Z@UK>@7\E`8`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-mbr.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-mbr.vhd.gz.uu
new file mode 100644
index 0000000..69446fd
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-mbr.vhd.gz.uu
@@ -0,0 +1,18 @@
+# $FreeBSD$
+begin 644 img-1x1-512-mbr.vhd.gz
+M'XL(".K%'50``VEM9RTQ>#$M-3$R+6UB<BYV:&0N;W5T`*V735.#,!"&[_T5
+MZWCST$F69*%71ST[XZA7`<'QX,>H!P_\>!-(0@($BZ:E%";9AW<_LDT9&UX`
+ME`&U0`V0U->Y`#I`7@"H07-@?^;F%KKZ[;6IOYZ_]^;5[0889[Y5:*[M,0.A
+M'I(#EOHA]*BOH;.8_>GET]GSRY/%H<'9!PL"@2`51,R>0\RITZ2K\YN+'ODP
+MJLOFZD8K]:D$,`&<>S,RJ^[!:70XH:S:MC]R*,M>ICV"FV!@=':"DVQBY<E<
+M"JKG[!*.UJRVX,YV)A=#J:C"R-59A8Y#COI:E8V-P^Q0I?+]^5Y^?#83?1@I
+M%7+Z^&PLB[N+IE303C8*A"[G-7>AIWQ-<0NE\J_H46@GS(4*`I-V`'OWP^B-
+M*/#U$6<K,8\G(ZJOU/K4VF+EPCD^T)WOP[<#5M4V8,$&A2'..5S5SN%2CAX-
+M13(&$WD\(2=>_*K'Q/FMVFU`*77'F`)OK;XZ=3H:#92Y[KZ2H,!C';Z_O%M:
+M;DUD]?ZQ637X&\X)YL?@,M-*[4R_,N(#W5@FP[?%B35U>@DWFYR5B6NO*29V
+M?IZ!J552`RN\)N,!77YAU'>8R\#`W15],'>WU+@\G,\]'/[B+H2X:C6WZ^I.
+MYNKJQ,EHIROCR)6K(>'*'7"8MA%@WUE4!:I9\W-\H+O>A^\!B.:7(]E/$9K>
+METRA,,!D"H5MIND49FRUV+96(1F%B?;U%&_W?]G7D]?N$^SKR;;[F!7;M*\G
+>T^X3[>O)MOLT^WJ-2[JO)_6/C;'=#W^X!V4,#@``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-mbr.vhdf.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-mbr.vhdf.gz.uu
new file mode 100644
index 0000000..b9c8a97
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-mbr.vhdf.gz.uu
@@ -0,0 +1,15 @@
+# $FreeBSD$
+begin 644 img-1x1-512-mbr.vhdf.gz
+M'XL(".K%'50``VEM9RTQ>#$M-3$R+6UB<BYV:&1F+F]U=`"ME;%N@S`0AO<\
+MQ47=,B#[L`^R1DWG2E7;-4`@RI!VZ="!AZ^-,=@XD*0R'&!T]L=_OK-AS!P`
+M`H$55^[SCG:7^&>[VJPZ&B\?`^8,FB8`)@IH<)7"J0[*"MDWE#$.6KBZE'$&
+MR/NV,6B3\5@G#NXXC`IMWN'B$H.SX3:/`:6$H@B`[U8?QDZ'T$"9@9`@"7*\
+M-^#/_<<D8(/CL>;/X/`6;A#,[\&E>I33TZV,>4<[EHEY6IQ84J<0K'XH6!FY
+M]D0^&>?F&9A:)16PO/>A#QSR"Z.^;2@#O7`7]$$8;J%QF=^?.SB\$2[XN'(Q
+MM\OJUJ&Z*G(RY'1EW+ER-<1?N0:'<3<"['8658&J5WB?=[2OB7\:H.B!T6:0
+M^E\1I4`-4`TD=3L30%O(<A>(?B6UU?=77?V<?]T,:QP?_ARAZ?&8ZM5"&6"A
+M/T)'W7;T/>U/F_/E9'%VJ[(?%J0G72J(",(E/]R7W=MSASR,ZM)PDLB=O5(`
+M$\"Y%WBO[N"7,W7[O`VV;J"4G4QKWHOGN+I5:9QDDU'_S:W!4>124;6W^@.>
+'9*U,OP@`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-mbr.vmdk.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-mbr.vmdk.gz.uu
new file mode 100644
index 0000000..2464362
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-mbr.vmdk.gz.uu
@@ -0,0 +1,82 @@
+# $FreeBSD$
+begin 644 img-1x1-512-mbr.vmdk.gz
+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
+DF&7U8MS^O?_$];O3]K\5L`R`9ATL_2>QY5_]']#X]&&`7P``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-pc98.qcow.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-pc98.qcow.gz.uu
new file mode 100644
index 0000000..5a36a47
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-pc98.qcow.gz.uu
@@ -0,0 +1,127 @@
+# $FreeBSD$
+begin 644 img-1x1-512-pc98.qcow.gz
+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
+!````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-pc98.qcow2.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-pc98.qcow2.gz.uu
new file mode 100644
index 0000000..632e42a
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-pc98.qcow2.gz.uu
@@ -0,0 +1,21 @@
+# $FreeBSD$
+begin 644 img-1x1-512-pc98.qcow2.gz
+M'XL(")D[(U0``VEM9RTQ>#$M-3$R+7!C.3@N<6-O=S(N;W5T`*V8VY+3,`R&
+M[_L4+H<%%BBQ9*<)AP7VP`QW<`%<M]WV*?KP;&)ME"A2W.VDS62FX_[?R/$7
+M-6Y1I)=ST;M0NE"[P]8]?*8#7._#\'#'WS]^KOJOXR+!?&&DE(&`'6[`NF$<
+M6+C"CP>\CNM5APH.'E-C4`X7S.JF!A3<Y:*]=.UB5"*!YP`3SER,L^J#5)],
+MA#/K@[GK0_WZQ<><'"BGZ\-4GTRM+5R5Q8&2JBW<)HM#);6U<+LL+BBI>PNW
+MS^*BDCH8.)]1Y0%7*BEOX2"+6RLIM'`ABZN4E.6=SWM7*RG+.Y_W;J.D+.]\
+MWKNMDK*\\WGO=DK*\L[GO;M74I9W8'CG&+=74I9W(+Q;$NX9XPY*RO(.A'?/
+M"?>BPWDM97D'PKN7A+M@G-+OP/(.A'>O"/>:<4J_`\L[$-Z](=PEXY1^!Y9W
+M(+Q[2[AWC%/Z'5C>@?#N_<@[K_0[L+Q#X=T'8A6,4_H=6MZA\,X3#ABG]#NT
+MO$/A'1(N,$[I=VAYA\*[2+B2<4J_0\L[%-ZM"5<Q3NEW:'F'PKN:<!\9I_0[
+MM+Q#X=TGPGUFG-+OT/(.A7=?"'?%.*7?H>5=$-Y])=PWQBG]+EC>!>'==\)=
+M,T[I=\'R+@CO;@AWV^%`2W7>%85^$.YN=,_"O,^?@9^/O7*V!R:`U5.`4Q4F
+M7#WKA&.:<*/!1CG;`\?KU?#=`5MAG@",T6W&P#]IPC$)4P>W"]J\#@<^3KA^
+M<6YA8K,DLUX_:"<<U\U=$4M7P:D5_KO[JTP8YIMPPMG;>1KH"O:GX-KM?.^;
+MOO]P9@X,'\Z6C)O<SC=[E+TV8%87YY4%H!*Y_CJWFZL=[T+%HVVWOH[K4YH!
+M#*8[49\;3[?YU>UVQV(5VP7(3-<-<=O)M9VN;CFN;C?S8J"\,TZ\<QO(\,Y-
+H.)BW$83TOU[1]LC1V1XX_EH-WPD8"#C;%0QE\]NQ^`\?5I30@Q0`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-pc98.raw.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-pc98.raw.gz.uu
new file mode 100644
index 0000000..4145c82
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-pc98.raw.gz.uu
@@ -0,0 +1,11 @@
+# $FreeBSD$
+begin 644 img-1x1-512-pc98.raw.gz
+M'XL(".K%'50``VEM9RTQ>#$M-3$R+7!C.3@N<F%W+F]U=`"ME$$.@R`01?>>
+M8MQV86`<JFZ;=-]-V[4U]10<OB!4!00U`0PQ^?#R/P,P9AH`(;!^8XP+\E:Y
+M71:78J+Q\1Q0".A#X%,!)QQJ?QW!0*#^O`_&<?D<059>^^.X$D.07145-G`V
+M+F7>/YP"BP9(@+A"BT<=ON^OC<"8+[#!X1YN-LR/X&J]:C53N44^XV*"P966
+M52XX2KE3"/8]%5;D/2R(K;=N76=@Z@P/P%JKH0N<ZPN+ORZT@4[<A#\(X_8:
+MU[CS^0J'.W'!Q7V2M4V[*T-W0^9BU/[-.'AS-<2]N0:'>1\"FEYF=0+U&QF,
+8<4$^*K<;(%E@MATDU,#B!\3RH'-%!@``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-pc98.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-pc98.vhd.gz.uu
new file mode 100644
index 0000000..01016a5
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-pc98.vhd.gz.uu
@@ -0,0 +1,18 @@
+# $FreeBSD$
+begin 644 img-1x1-512-pc98.vhd.gz
+M'XL(".O%'50``VEM9RTQ>#$M-3$R+7!C.3@N=FAD+F]U=`"METUO@S`,AN_]
+M%:YVZZ%*C!/:Z[3N/&G:=BUEM-IA'UI[Z($?OQ@22/A:NP4H"@I^\MIQ3"I$
+M?0#H!/0>=`%:<3LET&M(5P"FTUY8W:5]A#+__"CRT]MY:8]R5L.D\*U"<[;'
+M!,@,D@)F/(A^Y3:4#K.\V1P6;^\'AT.+<P.3!D)0!D*]<;1HU#'I_O;QKD)N
+M6W5)7UUK97X[`D$@I?=&XM1M&XT-CHS5?E]=*619)=-=P4/0T3K;P2G1L?)D
+M#@75<W8(IZ>LKL$M9G8NZE0QB9&:NPF=A!2Y;=+&Q:%WF50Y'[^R[V/1T8<C
+MJ:(;?;+7EXR[BS95T+UL%1"G\Y2[4%%.7=Q`JOPK>CJT(]LP01#*=6#E?AB]
+M%@6^/BW%1,S')V-47\;ZS-H2V<!]O*.\789G`]SMKP,JQ4NH"WQR#N>L;TV0
+MTU#<?2<O6AWY2/;]>7Z+R/'#RF&5<KE4&E9XJ<*7S?.`PQC/X1J'O^$:P?(2
+M7&)KGWO3J,7F:S/:4>/FEC5O<32ECM=<<96S*FZR8+[JV/GS#,+D<`YBY54%
+M#]C,+[3ZUGT9&+@[H0_Z[F:,2\/WI8?#7]R%$+>;G-MI=?.^NCSR9+QV5\:%
+M*Y<AX<JM<1BW$%!5F4T&<HWLW<<[RH=E>-9`M*4^VK<#;6V.II`L,)I"LM4Y
+MHD(J)I/MVBS45F&DC3CC(F[$&1=Q(\ZXB!MQQD7<B#,NXD:<<5$WXMK\Q1)B
+*]@,_NS;^O0T`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-pc98.vhdf.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-pc98.vhdf.gz.uu
new file mode 100644
index 0000000..94e27d6
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-pc98.vhdf.gz.uu
@@ -0,0 +1,14 @@
+# $FreeBSD$
+begin 644 img-1x1-512-pc98.vhdf.gz
+M'XL(".O%'50``VEM9RTQ>#$M-3$R+7!C.3@N=FAD9BYO=70`K96Q;H,P$(;W
+M/,5%W3)$^+`/6*.F<Z6J[1I"(<K0=NG0@8>O;4SP82!)9;"0T>&/__?9YR3I
+M+@")D)03S_E`N]ORNUUM5I8FFON`2D$9`E\UT.+0Z"LD5!)T;]2@:8;&`NUV
+M=/4XH8,AR(V:#4S@G%T9>?[0&E892`6*(,=;%;[OWR8,8SS#'0ZOX2Z"Q2VX
+MU(SROM1J45QP<X$.MW:L]8"32^HT(JGO,JOB+A;$?#3.SS,D>@U7D.0NAAQX
+MR2\,^HI0!C*["_H@M%L:7,:_%QX.K]@%CCLNYG99W3I45T5.1CK>&3?N7`/A
+M.[?#8=Q"(&UEUBO0U,C@.1]HG[?\[H#2`:/-(+FS@U*@!J@&4J:?2:`"LMP'
+M(E]);?7]55<_YU\_PP8G1A7=;V8\IF:W4`98FI_0A^E[^A[VI\WY\]3C^E+5
+M_UB2F72E(3*P2]SNT^[ET2(/@[HTG"3R9^^H3R@)0C#C3MV!+V>R^>W-U@T<
+CE979-_;"`I.ERN!4,AKUW]QV.(J\5/2IMOH#34'Y,G`(````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-pc98.vmdk.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-pc98.vmdk.gz.uu
new file mode 100644
index 0000000..7f13ae4
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-pc98.vmdk.gz.uu
@@ -0,0 +1,82 @@
+# $FreeBSD$
+begin 644 img-1x1-512-pc98.vmdk.gz
+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
+-O@"^^C_.+8_6X%X`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-vtoc8.qcow.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-vtoc8.qcow.gz.uu
new file mode 100644
index 0000000..e8eb9e2
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-vtoc8.qcow.gz.uu
@@ -0,0 +1,125 @@
+# $FreeBSD$
+begin 644 img-1x1-512-vtoc8.qcow.gz
+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
+I]_,9IQ]2VL/?]2]\^]?;^W_=H3+,@W\;>\-Z^_U3_O%_AAM3=G^E````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-vtoc8.qcow2.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-vtoc8.qcow2.gz.uu
new file mode 100644
index 0000000..c389b8f
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-vtoc8.qcow2.gz.uu
@@ -0,0 +1,21 @@
+# $FreeBSD$
+begin 644 img-1x1-512-vtoc8.qcow2.gz
+M'XL(")L[(U0``VEM9RTQ>#$M-3$R+79T;V,X+G%C;W<R+F]U=`"MF-N.TS`0
+MAN_[%.YR7F")9^PTX;#`[K(2%T@@7H"F<1^`ZSX\3NS6R60F+E7:M%)E_9_&
+M]M>ITZ((#Z6L5J94IE;[1OG/\0(U^#"^U.'7X_>;X>.P"C!=""EFP.`)-V+=
+M)QQ(N$)/!S2/&U2'#`Z.J2DHAS-B=7,##.YZU2]=OQD52>`EP(`3-^.B^B#4
+M1Q/FPOI@Z?J07S][S-&!<KX^#/71U$;"55D<,*E:PFVS.&12C83;97&&2;42
+MSF5QEDGM!9S.J.)Q)9/2$@ZRN`V30@EGLKB*24G>Z;QW-9.2O--Y[[9,2O).
+MY[UKF)3DG<Y[MV-2DG<Z[UW+I"3O0/!.)9QC4I)W0+Q;1]Q5PNV9E.0=$.^>
+M1-S3$TYS*<D[(-X]B[CG"<?T.Y"\`^+=BXA[F7!,OP/).R#>O8JXZX1C^AU(
+MW@'Q[G7$O4DXIM^!Y!T0[]Y.O--,OP/).R3>O8NL(N&8?H>2=TB\TQ$'"<?T
+M.Y2\0^(=1IQ).*;?H>0=$N]LQ)4)Q_0[E+Q#XMTFXJJ$8_H=2MXA\:Z.N/<)
+MQ_0[E+Q#XMV'B/N8<$R_0\D[)-Y]BKC;A&/Z'4K>&>+=YXC[DG!,OS.2=X9X
+M]S7B[A*.Z7=&\LX0[^XC[N&$`RYU\JXH^"OBODV^L[#L^=.D\[%FWN6!&6#U
+M/\"Y"@.N7G3"-DS8WSIN0)6VN[P2%KN=]$U$F58"/OYU[N[W@_DQK,\N?4-@
+MT_H5W#)15-4?QT%:/SM:OSJ+RVR'#0>S1:8;<,VY./_CXH_VK5/.$=R?`6ZW
+M\&;HR71==_+WQZGJ#.!Z``RX;KHA3'>8^6_@.*P.ZTE]`9>F"X,(C'":J\Z?
+M%OO7&-<FG*8]:W:R:[8ZMZ@J?5\^"]=N5>.ZDVVSF>"NCKB^+_L#D+]IG;[+
+:`X>?-^-G4,5$X&+NF;)K5*M_;'%=NO`2````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-vtoc8.raw.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-vtoc8.raw.gz.uu
new file mode 100644
index 0000000..c35f98d
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-vtoc8.raw.gz.uu
@@ -0,0 +1,10 @@
+# $FreeBSD$
+begin 644 img-1x1-512-vtoc8.raw.gz
+M'XL(".S%'50``VEM9RTQ>#$M-3$R+79T;V,X+G)A=RYO=70`K9)-#H(P$(7W
+MG.+AT@5IAU)E:XP[$Q,O(-AZ`-<]O&V&!`KEQX2A=/-X7^8Q(P07H#1.!%V%
+MHPA5":50*B\8>'UZX&Y?:R_/J[H77"YCF/1BTB*6!%>,RF7'#GB.?'(9>(:H
+M(2@)9%S=N^I5W%)_C&OVBLNX=BM.^]O`6%@[PKT&N/?.PY"3N!9^X"3#GUP%
+MYN.X,L1E\WC"LS@ON'S2'^/ZN#2P4(23J>Y0\!OC3(^3?ZU*GNS.[KHJ\K,5
+L9QJT%D0H]01WT!V.@JORWS>)>UYPCR)^>%54!]QM]Q0%8/8#T8E)O;($````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-vtoc8.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-vtoc8.vhd.gz.uu
new file mode 100644
index 0000000..e3f9594
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-vtoc8.vhd.gz.uu
@@ -0,0 +1,17 @@
+# $FreeBSD$
+begin 644 img-1x1-512-vtoc8.vhd.gz
+M'XL(".S%'50``VEM9RTQ>#$M-3$R+79T;V,X+G9H9"YO=70`K9;);L(P$(;O
+M/,5(O7%`WN+`M6JY5:K4%\!)'-1#%P$'#CQ\9Q)G<1('*`[&,G+F\S_CL1G&
+MZ@=`2]`E:`LZH7&J0&\@70/@I&NBZKG["9?\Y]OFI\_SRCV710WCK&_EFY.]
+MD*!PD12$H45T06.X-)C5T^M^^?FU;W#"X9J%E08E($&(&JVC6:N.2-OGCY<*
+MN>O4R;&ZS@J_F0*F@//>&[)1MVLUMCB%5F59M12,J60VS?OA373.#G`)&UCU
+M9$X%M>?L%$[/6=V#6R[<7M2I@HF18H^AXY`*&F/:-'$8-4R5\_'7'(YVH$\$
+M4D6W^OAH3H;=%2Y51/.R4Z`HG>?<A8IR&N(F4N6AZ&G?3KD!!H$ES82HW/>C
+MUZ&@KT]S-A/S\&8$]1G2A\<+=Y1N@:0[9U+C1!%R>'NP%D^:?O/C9P*[^^_X
+MF;5G=^5TK(%MZ-8)IHO9=%:;QP^;,;'<K7'9K3BZO@HH+%@[P.UZN#SR9F0C
+M=RUELKP-R(;N9N2N'+S/71_`T47*1OIJ7.>NZ)D(#S>Z7$@=M,>LCRM:W%#C
+M%6?9I#H;-56R\E9<82"S("7(9(23B</E9(5_1,Q,].&)R_O*_]2I(MR]$NVB
+M$K$5*@>,IA"!-K)"SF8SX][SJYW"2%4?X2)6?82+6/41+F+51[B(51_A(E9]
+1A(M:]>DJ]Q9_[Z\6^RH,````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-vtoc8.vhdf.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-vtoc8.vhdf.gz.uu
new file mode 100644
index 0000000..bb8e698
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-vtoc8.vhdf.gz.uu
@@ -0,0 +1,14 @@
+# $FreeBSD$
+begin 644 img-1x1-512-vtoc8.vhdf.gz
+M'XL(".S%'50``VEM9RTQ>#$M-3$R+79T;V,X+G9H9&8N;W5T`*V4RVZ#,!!%
+M]_F**W67!?)S"-NJS:Y2I?Y`()BHB[92U447_OC:L4FP<1ZJ,(,%&N9XKCT,
+M8V$`BE`+D/:F!+2$4I#D'#V<?VZPVV]C'M^>Z*4*PZX"C#MG,81=<]@J&W:U
+MCL!-$L>O`S=@#9@H`@.N.4<U-W'7\@NX=BFY`=?=BR,W]^@-C,EPNPENO_!A
+M\)E<`W?@\CX@R^5R+U=FW_,X7\`YAV6S_`+N+%=,0D2"XZ7L4(4[Q?4G7)[C
+M#;&LF)U9M%3X<"^N;]$92`FI9SBI(T[X*.V^;POS98=]K=(KE(J*P,5JCV*C
+M(@D:0.;8JR1J!6I0;Z9`D1PS[/[KT^Q_WG^G^T>Q40U#V7R\<$W0+5)#M'X1
+MZOWS)+^'Y\/Z_>,PXD14-2[L6NJID^8J*96[=7UT_'5'G)QO$DUWKU-@"IPG
+MPF-VN[18/$Z=Q)H!G3ZF.5KRDCB*M>=QFF51_R]ECZ.%2\75WNH/`$S(R-T&
+"````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-1x1-512-vtoc8.vmdk.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-vtoc8.vmdk.gz.uu
new file mode 100644
index 0000000..2cc570c
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-1x1-512-vtoc8.vmdk.gz.uu
@@ -0,0 +1,81 @@
+# $FreeBSD$
+begin 644 img-1x1-512-vtoc8.vmdk.gz
+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
+4`=#LO5?XSV'-OOH_FA1I)IY=````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-apm.qcow.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-apm.qcow.gz.uu
new file mode 100644
index 0000000..491ab80
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-apm.qcow.gz.uu
@@ -0,0 +1,127 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-apm.qcow.gz
+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
+F$//[_<;GUYW3^9TG\$_^B:^_O+G_G]O!YMO@3_\'*;=.DB.F````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-apm.qcow2.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-apm.qcow2.gz.uu
new file mode 100644
index 0000000..aa257d4
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-apm.qcow2.gz.uu
@@ -0,0 +1,22 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-apm.qcow2.gz
+M'XL("+@[(U0``VEM9RTV,W@R-34M-#`Y-BUA<&TN<6-O=S(N;W5T`*V826_;
+M,!!&[_D53/>F32K.D)35/9N!'@JD#7H.O,A`@"Y&&J`7__A2ULB4J1DQ-N0(
+M1@SB>Q@/GT>FLZQ^*&6U,DZ90BVFRK^F"U3KQ?:E5M_&7T[:C]5!#=.9D&(6
+M#&YP6ZSS@`,)E^GN@N9QK>J0P4&3ZH)2."-6U[?`X(X.UJU;;\8H2N`^P!HG
+M;L9>]4%=7YPP>]8'0]>'?/]LDXL77']]6-<7IW()-TKB@$D5$FZ2Q"&3FDJX
+M61)GF-1<PI5)G&52"P&G$ZIXG&-26L)!$I<S*91P)HD;,2G).YWVKF!2DG<Z
+M[=V$24G>Z;1W4R8E>:?3WLV8E.2=3GLW9U*2=R!XIP*N9%*2=Q!Y=TBX1P&W
+M8%*2=Q!Y]YAP3S8XS:4D[R#R[BGAG@4<,^]`\@XB[YX3[D7`,?,.).\@\NXE
+MX8X"CIEW('D'D7>O"/<ZX)AY!Y)W$'EWW/%.,_,.).\P\NX-L;*`8^8=2MYA
+MY)TF'`0<,^]0\@XC[Y!P)N"8>8>2=QAY9PGG`HZ9=RAYAY%W.>%&`<?,.Y2\
+MP\B[@G!O`XZ9=RAYAY%W[PCW/N"8>8>2=QAY]X%P'P..F7<H>6<B[SX1[G/`
+M,?/.2-Z9R+M3PIT%'#/OC.2=B;P[)]S%!@=<:N-=EO$7X2X[GUD8]ONG"=^/
+M-?,L+_0`1[L`^RJL<<6@;]C6;]CO@(5PCLK6=\A1+_#R>X4YW*[/#GT@L+4P
+M?C*;>2>'TH'/+ZRNOC+]L[4P_N/@IZF_W$PY^Z#Z3I?+GR6#DT^WNQ^G/`Z[
+MU=G%^G\O2PXJ-\H5].P6RI75,E5WLYS<W=_>W_[Y?=/@JANDFU?A?)?J?DV6
+M;'5VX+TU#]S;YGX!!-S>6]749X9VSZRWPU6-]QOA+S\N+593SG_-4-96:Q:[
+MP/%=69Y=7QS_&%^W^V>&_;'!^A-5NG_0ZE_](6GW3[7K<T/WS_7V+T>5YXR;
+MH7]__]4B-O4-W#^=4?_\2;W[+"^LKDZV_VJ@(>!@%1I73>>#_Z4*H1'E$P``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-apm.raw.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-apm.raw.gz.uu
new file mode 100644
index 0000000..13210f0
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-apm.raw.gz.uu
@@ -0,0 +1,12 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-apm.raw.gz
+M'XL("/[%'50``VEM9RTV,W@R-34M-#`Y-BUA<&TN<F%W+F]U=`"MD\UJPS`0
+MA.]^BNFU4"/)*RD]MK2Y%4)#S\'4#@3:Q*2!7O3PE2*)R#\)+FB]"(ME/\:S
+M:\9\`"0A!9A-%E)PL`4N]T'"O+Z7-N[*&*;P,,YN=%W'E8,PQ;T'"E>6#-2,
+M^JH4R/L%LWH;`CW.Z2,.S5RJ3R@Y2]]3UWVU$SB1ZW,]KAJKD]OS.P>T@":H
+MQW"J+53KRD'=IJN/I]UI=]AO(HXL3C6N6?]'W7?=3:J3F6=+,V>[B$L9@/W9
+M(NJCW+M'YW$H9[P=A$T2D!6((!HK7+J:O8^`RV/;/J]?'CZ6Z]0_HLSZU`S_
+M1.*?_TE2_Y#J4[G]4S?]TQ6TGMC-BW\_OWX1H[[,_G$6_&/UQ'F]8%9E__%`
+1"L!L"DDX8/$'F8$ZXZ<%````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-apm.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-apm.vhd.gz.uu
new file mode 100644
index 0000000..0349231
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-apm.vhd.gz.uu
@@ -0,0 +1,18 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-apm.vhd.gz
+M'XL("/_%'50``VEM9RTV,W@R-34M-#`Y-BUA<&TN=FAD+F]U=`"M5EUOVR`4
+M?<^ON-+>*BT"#-?=T]1JS=ND:M6>6\O!5:2UC9I(ZX-__+A\U#@&U\UP$,'"
+M]W`X]P,8<P\`5H`=H`94-*XEX#>H+P',I&_"]MR_0M^^/.OVN'M;^Z=?.3#.
+M8JNQ.=F+"J19I`;1T"*XI3'T`6;]Y>;Q8O?T&."$APL+2P0I0!D0.5D'V3L[
+M0MI<W_VPD`\#NVK*;K!R?UT'51=]405V#[;_'F]6&BOS/;4:*F5IAC9Z&4T0
+MG%I'3X!3[,0JHID2-=IL"@[GK#X#=['ROG"A8@*C-KV1CD,M:&S")N@P:294
+MW@[[YO6@3_B)3*C@.S\^F:ORVQ4^5$3XV#.0%,YSVP6+<CR%2X3*?ZF'8SOI
+M!T8$IL*$L-L?JS=`0<P/.9O1/.^,++^&^)G45"(DNVW51QN^^44P[-0=3<:[
+M9^O7TK3)$+E-1<7PPL<3_>W/9+BTQ$]R"F.*Y)9B>`F_J_W^CT[`B5+;=7#5
+ME)WJ?,[9I',EVO:N=*LNL+LWV7;<'7<OS_<!C@H5E5J+N)S=4[-/LE.%?:L7
+M^O8RRA,V\2T$?KIT[&GK#B3AZ814PQDDMH:XHCGS/@'<O&IM3J&OOS=WL7Y:
+MEN7'V0+]1*2?2Y)8O[BV\-PA?CZ_6?WH,*D3L3GH=_CK`C'P*ZU?X_5C3:+/
+M3_2WZ_'/`0I?3(M59S%4OS(,I0<LQE`..5R*(=>SSORLE]$S+'35Q7R5.>>J
+J2W`%K[KH2U;6ROTMO>JB+UF%KKH$5_"J2W!%K[IH"^KJ'[J1;&,?#0``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-apm.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-apm.vhdf.gz.uu
new file mode 100644
index 0000000..e1b6626
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-apm.vhdf.gz.uu
@@ -0,0 +1,15 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-apm.vhdf.gz
+M'XL("/_%'50``VEM9RTV,W@R-34M-#`Y-BUA<&TN=FAD9BYO=70`K57);L(P
+M$+WS%2/UAM3(\3*FIRXJW"JAHIXA(@F*5""B2.TA'U^OX"P@6MF,+$<3/]Z\
+M9T\(L0.`"Q`4B`KB@IGY_-P):*;OB1HD\:,96;#TVJ[+<$EG-*.Q!:0Z+0CP
+MO+>/A8!I.]',W[J`%D[SXRE(H@/7@.(F?L]U_5D,P-%8Y5HXUF<G2K-.`20%
+MR0$?W(PE8*'3CMVRS@['ZECM=TL/QQ4<YGJS_`N[;58/LA.1O>4W>CMQ"^H`
+MV]Z"Y\=CGSUN[$`MO#)"!:<@&'`.-%?$A<ZIYQ[@[%`4+XO7^X_9(M2/\\C\
+M\`;]:*"?O22A?A#RP]CZX57])`,I!\[F6;^O;WL0/;_(^J7$Z4>R@?ERHIDG
+M[9\%Y`XP&D-TW1F9N^M:1.9[P"0$I&=[#>!ZORO6Q^HGO,'HNG-9#H?>3YG^
+M%J`$FID6D^MUP.]NNAE7VXV'\]W/_['R^F1QMTILESM3!AO(U9D=ZXN$'?44
+M3U:V"G?L5F9^#(OEIV*+$KBEZ:/UT$IHN*>V&1;.=+_PY?]Z:^$P\E%1'\K1
+)+TV"K"_2!P``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-apm.vmdk.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-apm.vmdk.gz.uu
new file mode 100644
index 0000000..860e005
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-apm.vmdk.gz.uu
@@ -0,0 +1,83 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-apm.vmdk.gz
+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
+,]*O_`W*E&0&37@``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-bsd.qcow.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-bsd.qcow.gz.uu
new file mode 100644
index 0000000..c016f6e
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-bsd.qcow.gz.uu
@@ -0,0 +1,126 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-bsd.qcow.gz
+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
+#I0``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-bsd.qcow2.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-bsd.qcow2.gz.uu
new file mode 100644
index 0000000..b27f56c
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-bsd.qcow2.gz.uu
@@ -0,0 +1,21 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-bsd.qcow2.gz
+M'XL("+H[(U0``VEM9RTV,W@R-34M-#`Y-BUB<V0N<6-O=S(N;W5T`*V8VY+3
+M,`R&[_L4Y@P+E%AR3ARVL+#,<`<W<-UVVZ?H\.RL:R5*%"E>.FD[F>FX_S=R
+M_%E)6A3IY5SI7:A<:-UQY^Z_TP?<X,OXXTZ_OO]8#U^G58+YPD@I`_6AQXU8
+M?QD'%J[PTP&OXP;5H8*#+C4%Y7#!K&YN0,%=K<ZG[KP8C4C@)<"$,Q?CHOH@
+MU2<3X<+Z8.GZ4#]_99>3`]5\?9CJDZG:PC59'"BIUL)MLSA44CL+M\_B@I*Z
+MLW#&SAW@2B5U-'`^H\H]KE)2WL)!%E<K*;1P(8MKE)3EG<][URHIRSN?]VZK
+MI"SO?-Z[G9*RO/-Y[_9*RO+.Y[V[4U*6=V!XYQAW4%*6=R"\>T2XQXP[*BG+
+M.Q#>/2'<TQ[GM93E'0COGA'N.>.4?@>6=R"\>T&XEXQ3^AU8WH'P[A7AKABG
+M]#NPO`/AW6O"O6&<TN_`\@Z$=V\GWGFEWX'E'0KOWA&K8)S2[]#R#H5WGG#`
+M.*7?H>4="N^0<(%Q2K]#RSL4WI6$JQBG]#NTO$/A74VXAG%*OT/+.Q3>M81[
+MSSBEWZ'E'0KO/A#N(^.4?H>6=RB\^T2X:\8I_0XM[X+P;D.XSXQ3^EVPO`O"
+MNR^$NV&<TN^"Y5T0WGTEW+<>!UJJ]ZXH]`_A;B=[%I:]_PQ\?^R5HSTP`VS^
+M!SA78<*UBTZX3!..&FR5HSUPNEF/WSWPO,)E'5>UK%P##ZWPS^WOZ83+!5<X
+MX>S'41KH"NZWX`2W&>#B%>TX^.5P'=W>\_8?$@>XZ\3K<+./H_$>^Z`-F),M
+M%Y8%&I$;KG.\M8MWX%UW%[=F_?HZKD^1&4;3G:G/3:<;KQK]TYU8CXB#S'3=
+M&!>O&F)?\A)FSMYF6MU^X<5`N3,>N',C9+QS$PZ6;020_I<JXJ^F1WO@]',]
+6?B=@(.!B9S!4L?>M_@&MW,<Y0Q,`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-bsd.raw.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-bsd.raw.gz.uu
new file mode 100644
index 0000000..b44538e
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-bsd.raw.gz.uu
@@ -0,0 +1,11 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-bsd.raw.gz
+M'XL("`#&'50``VEM9RTV,W@R-34M-#`Y-BUB<V0N<F%W+F]U=`"ME#L.@S`,
+M0'=.X;E#E&])%RI5ZMZIG2F%4^3P38`4FQ#H$`<B(MM/_N!P/@F`EL#;C3VO
+M<#=&EZM.U4B3`6AJT`;,&:PWY\M##D3A7O<GP^)FG-CSRN/82B).'N%BP&K(
+MX:X(I[QR0)9<(*].@.KG`_Y&N&9Z(T[O1><KP?LM13994ZIVL;=VY8?[#*('
+MH8#;62<I\-=?6.*[I&%(DNY.?)"FVP9<3>T%PLF#=('BW@&'^DE:>%"])HVN
+M*]P,M9Z,/R<W0.CD3CA9]B*0X\WB_T!OE>YYA7LPNB:@GH'%*EA_K"=67[CE
+&;;$%!0``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-bsd.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-bsd.vhd.gz.uu
new file mode 100644
index 0000000..9e10396
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-bsd.vhd.gz.uu
@@ -0,0 +1,17 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-bsd.vhd.gz
+M'XL("`#&'50``VEM9RTV,W@R-34M-#`Y-BUB<V0N=FAD+F]U=`"MESUOPR`0
+MAO?\BI.Z9;#P&6-W::*HZ5RI4CN[Q(XR]$--APS^\>5LB`]_)6VQ"<*">WB/
+M.Q`1HGT`5`*J`E6"2JF=25"WD.4`IM,6;.K8?D*M/]Y+_7TX1?:I%RTL%MS*
+M-R=[3$":23+`@B91.VI#[3#1S7:_/+SM'0XMSDTL%4B$U$#D8)Y<G-41Z6'S
+M=-]7EPS5=5;M/%4%2<5&)%Q=%*TX3AHK,YZ*@DHV,EWQ/KP.CO/4I:)GQ62.
+M+2IS=@RGYJQ^@ULN;"S:5#&)D9E:@(HA0VJ;M''K,"@F54['S^+K6/;TX42J
+M*!:,?I^<=A=MJJ`;;!5($CCG+C248Q\WDBK_6CWEVTG;,(L@4M>!C?O^ZG4H
+MX/I4+&;6?#H8D_H*TF?VEBA&ZNF.>A/Y[QFH"9AFM-U3!3E>NX(OV^>Q^.J)
+M=/GC[M!X"><$\]/`QZT8+FG#T5%8\H*.(2F[;SF"NS._=8>3<^HH9\JQCDEG
+MT\#)K/.>'8\SQ"7$"8B<934#GN,+G;[;H0STW)W1!T-W"\)E_OB8X?""N^#C
+M7NVYS`9W(;RP>NNA.ATX&+O^SKARYQ+$W[DM#L,>!-B<+"8#S:AA/=U1/T;^
+MVP+1'E7!SCYT1U4HA=("@RDTP#*P0BQGD^VW6:BLPD`72<(%O$@2+N!%DG`!
+>+Y*$"WB1)%S`BR3A@EXDE?F+(,3B!S97<<M]#```
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-bsd.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-bsd.vhdf.gz.uu
new file mode 100644
index 0000000..1605f5a
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-bsd.vhdf.gz.uu
@@ -0,0 +1,14 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-bsd.vhdf.gz
+M'XL("`#&'50``VEM9RTV,W@R-34M-#`Y-BUB<V0N=FAD9BYO=70`K90[3\,P
+M$(#W_(J3V#I$?L==:%519B0DF$-PJ@[`PL#@'X\OB1M?G@C%=J)8=_?E'O8Q
+MU@X`)8"5$^]Y@3_E=/ILES4T@4!=@-*@#=B@SOI%-D3@7\\O>3I\A^-+5O.X
+M?#`B3JSAHL.RGL,=$IP,PCK19#RQJCA(U^_5!.X^/,<>IY:\"YE@;DHP&ZS>
+M*G>QMG9@E]89N`,N@=E.)BCP5E_H_=N/W1`DW`7_8!QNB;B"ZO,$)U;"!8I[
+M0QPGRGT)5[)W''M7;5P,.;P9?[RY"*$WM\6);1N!:#I+.(%!:_R>%_BGG,X6
+MJ#K@9AFT7>\S$DP-QH'1^%TH,'LH;`H4]"3YZNO35=_7G[3"B.-M,YA<:"\D
+MWA93@"CQ)^8=OQ/_[LZ7W?7C$G&Q5<4?*X-)UP&B1N%:&N[CZ?EAZ)T<)\F2
+M[''T,VU[(7"2O4.*4[=@G6M:(.\7V1#!9*M"G&8#J__6ML69C8]*.'S9+_P)
+&SWLP!P``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-bsd.vmdk.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-bsd.vmdk.gz.uu
new file mode 100644
index 0000000..3df9b01
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-bsd.vmdk.gz.uu
@@ -0,0 +1,81 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-bsd.vmdk.gz
+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
+G^\Y=TYUM&T&U=)9U^'_[]_X3UV]/V__6A,62\(O_`X=39<Z@70``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-ebr.qcow.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-ebr.qcow.gz.uu
new file mode 100644
index 0000000..ce9a989
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-ebr.qcow.gz.uu
@@ -0,0 +1,128 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-ebr.qcow.gz
+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
+C8A/X._^%;_]X__"ON\$F#?YI)]C<TG<^/_H?-'D14%"H````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-ebr.qcow2.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-ebr.qcow2.gz.uu
new file mode 100644
index 0000000..5e5f371
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-ebr.qcow2.gz.uu
@@ -0,0 +1,22 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-ebr.qcow2.gz
+M'XL("+P[(U0``VEM9RTV,W@R-34M-#`Y-BUE8G(N<6-O=S(N;W5T`*V8R9+3
+M0`Q`[_F*9E@&!@ANJ;VQ)#`P5'&#`W!V%G]%BF_'3LMN6Y;<DY03ERNIMEZI
+MW4_RDB3^8TQJC<N,*TV],\U_VL`,_HPW<_KU_<=Z^#FM/,PF2I0PD!][W(CU
+M+^!`PR5V.F!EW"`[%'#014U!,9Q3LYL;$'!WJ_.I.R]&P2+P&J#'J8MQ57[@
+M\^,1[LK\8.G\4#Y_:1?'![+Y_-#GQZ-R#5=$<2!$E1JNBN)0B-IIN'T4YX2H
+M@X93*G>`2X6H6L'9B"H-+A.BK(:#*"X7HE##N2BN$*(T[VS<NU*(TKRS<>\J
+M(4KSSL:]VPE1FG<V[MU>B-*\LW'O#D*4YATHWIF`.PI1FG?`O'M"N)N`JX4H
+MS3M@WCTEW+,>9Z4HS3M@WCTGW(N`$_H=:-X!\^Z6<"\#3NAWH'D'S+M7A+L+
+M.*'?@>8=,.]>$^Y-P`G]#C3O@'GW=N*=%?H=:-XA\^X=L9*`$_H=:MXA\\X2
+M#@).Z'>H>8?,.R2<"SBAWZ'F'3+O4L)E`2?T.]2\0^9=3K@BX(1^AYIWR+PK
+M"?<^X(1^AYIWR+S[0+B/`2?T.]2\0^;=)\)M`D[H=ZAYYYAW6\)]#CBAWSG-
+M.\>\^T*X^X`3^IW3O'/,NZ^$^];C0(KJO4L2>2/<PZ1F8=G[3Q?NCZVPUP=F
+M@,4EP+D,/:Y<=,*IKXW+@'6MY9?ZVF@.:+8JI1_-YGVF^+T-53'.;TN5$7"'
+MI:=;7P9,4U-5$^#O+C^83>/R_/)C.]Q6927L]8'3_7K\[8"%?SN0MT669J:`
+MQV;X]^&/L+[%<@]\'J>_':"!+N&^(TYPVP$.O7V!,BBKD7?#WP/<9ATZ<X.;
+M?3O0/O(<I0%ULNFRLA1];^EM':QS>Z?=/A!U%UMVI]ROKPGY";T%1M.=R<],
+MI]M>Q/N';;8>+0XBTS5CW+E1#=9SM(21L[>99K=?>#$LKXQ'5FX+&5>NQ\&R
+FC:`\=Y;&P.:HZ5X?./U<C[\>Z`BXV!ET67OM7?T'9%>AF-(4````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-ebr.raw.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-ebr.raw.gz.uu
new file mode 100644
index 0000000..a874b5b
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-ebr.raw.gz.uu
@@ -0,0 +1,12 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-ebr.raw.gz
+M'XL("`'&'50``VEM9RTV,W@R-34M-#`Y-BUE8G(N<F%W+F]U=`"ME,T.PB`,
+MQ^][BIX]+,"&P\N6F'CWHIYQ;D^QA[>,35MA'R;P%9+"+__24B%\`\`9'<N&
+M(?]I0W;(1II\_@WL^RC0XUJ\A0=P6#UM<!0]P;42BBZJKW%+37&OU.[V_P&U
+M!FL#X&W6IQ*'H^J<N50@;&1=-@SGG/<9:,:$T164&O01C-JK\'&Y1^)KA$SE
+ML,>I+=PLV&=0#-<07.&S[TN1Y!;-.[HGN-K/&5>NJ<.7$%W,L.BL3ILL!CN_
+M1^,,L@-9@#"337'@)[[PU7<*92CF[HH^"-VU#E?Q\Y+@U(:[P'%CH2+Q9"'<
+M>+TZ5-<F#H;\_1D[?ZZ#\)_K<2IM(3B-E04S$$^%Z[)AN.:\>V`Y`9.]H*M\
++0F1O]"SVO.4&````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhd.gz.uu
new file mode 100644
index 0000000..c00d389
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhd.gz.uu
@@ -0,0 +1,18 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-ebr.vhd.gz
+M'XL("`'&'50``VEM9RTV,W@R-34M-#`Y-BUE8G(N=FAD+F]U=`"ME\%NG#`0
+MAN_[%"/UE@,R@VW(92-%3<^1HK1G+X$HAS91MX<<>/AXL+W8@-EL,\`BK\;S
+M^1_/V,A"N`M`5Z![T!UH1>U:@KZ&N@&P1O_@^"[]7QC:US]=^^_EO?#7L'.P
+M4L1>J3OY8P72#E(#&AI$/U$;AH`IOMT]7[W\?@XX]+@PL-0@$92%R,4XC3BI
+M(]*/VX?O<W754MWDY<;I>ZCZJ$<5JRN*FQ@GK9?M3X^&7HXRPY/\20PQ+E&G
+MQ,PKDKDVJ5&P:SB]Y74)[FKG<^%*Q19&;=\"=`DU4MN639B'Q6-+Y?WX9OX>
+MNYD^S)2*CI(QM\E\N.A+!4-GKT"2P*UP8:0<Y[B54OG2[.G43_J&G02A@@''
+M\-/9FU`0Z].EV)CS?#*R^LQF7/\1\.%P,3"CT.':4\!&31&YM>K]VQ*J;E7?
+MN&SW,>Z).]S^,J!28,P"^!CTM<SI:!HRV[U3F)5WWC#<%NE]`HX%HVK:SI6&
+M!C^K\-?=SY7\-B:S'5P>L,/A.5P0'._V*>XFPE6N^B9*M#DE=1>W(]S>_0).
+M;JFC/:%;,V2#5<S%8IJ97YQG*#LH*Q"-MV$*/.47)GW72QF8A+NA#Y;A&L+5
+M:?\RPN&9<"'%'?QW-_1,4GAF]O9+=2US,@[SE?')E4N0=.4Z'/)N!&;<66P%
+MVE[+=]XPW!?I[8#H/T5LWS;TFRF;0NF!;`HML&-6:'B_']HK9#HH$([QH$`X
+BQH,"X1@/"H1C/"@0CO&@0#C6@X*V1T`A=A\#O(;Y70X`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhdf.gz.uu
new file mode 100644
index 0000000..b2dd812
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhdf.gz.uu
@@ -0,0 +1,15 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-ebr.vhdf.gz
+M'XL("`'&'50``VEM9RTV,W@R-34M-#`Y-BUE8G(N=FAD9BYO=70`K94[;\,@
+M$(#W_(J3NF6(``,FBR-%3>=*5=O9=7"4H>W2H8-_?,$8FS,XCPJ#$=;!YWMQ
+M$.(>`/,F^[*@V\R>;K5>]33Z<3>P;9-`AVO,+K/`]%H,$].+-L`U%`J=U&]G
+MARK$'7.;V]X'%`+J.@*^>OU8YG"4VHHY`U(GQF5!M]_@YH&J3QA1`A<@)"AV
+MJX;OA[=$?!6AN0QV.'8-YQ5V&93"[0)<X;)OHM!@5YAWX3S`5>[U.'Y).^,)
+MHE."16-%WF11IN%]89R!:J`%$#7(&`:.\85)OVVL!D/F7M`/8G-KBROQ>AK@
+MV!5S`>/Z0A7$$X7PBO>J6+LF<S#H_&3<>'(M!)]<AV-Y"\&VKRPF`\VJ>%P6
+M=,\;W!R0#\!L'E3#W28+D"U(#5+8><E!;J%4(9#A3.J:[R_=_)Q_PPA;'!VO
+MHKC;_:RPIT66P&K[$WFT\T"_A\-I??X\>9PO5?['7%JG"P/AD;D*F_NT?WF<
+M:U?$3E+(>W2Z.$?#D?=V(8Z/QFK=ET`Z=?2!!,E297&"S';]-[8.)S.GBKEW
+*5W]/U6F<$`D`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-ebr.vmdk.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-ebr.vmdk.gz.uu
new file mode 100644
index 0000000..92bef31
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-ebr.vmdk.gz.uu
@@ -0,0 +1,84 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-ebr.vmdk.gz
+M'XL("`+&'50``VEM9RTV,W@R-34M-#`Y-BUE8G(N=FUD:RYO=70`K5S1;N3&
+M$7SW5PSDMSPL6,LEN7PX.W'.`8(@@!$[]FO(Y3`68M\==$*0`_3QX9!3HR)%
+M'FFK=:L#^]A=V]U#M735!679].'<I767B[MTKBA=!C?\T_1R6?YL#*]+NO'T
+MM[=___'$CS^>3D]?3&`(41*"3.'$F+W/TVGQ0;CSYZ)F-X;7>1<N#U'MB\`(
+M=]ZXL0DW],.=UT*873/>[L*%P+D$Y&9PQ4I-F\5^+KL_?!&;%_++0P[#\9:U
+MJW)7MM%T93':N:O.X[W,58-3/P!^Z=[>?_R/>^L_WA[N/SR^C_F=P]D.SI<R
+M^)>W@#`45I7A(MP(<'6`*+W+.Y<CW'9/#W^Y_\6?_NL?/MZ_?_<&+/<<SO:2
+MNTL=T@G^V?-K9H0WR5R)\![NZ<]_??LF/KG9Z4/S0+@0-20RO/=0A^*6I0N?
+M+U]C=O[=8T#LXT?*+IQM;$XQOO<E7!075]5N3*<(V.?A=A=+'GMW>_#-H__A
+MTP?_YN[7]^]2[\+9AI;5(]!U;%3NBCQ`Q=)"^XJ`&!Z;\=3<TR_WCS_?W[X?
+MROSH[TY?.L*5H7?#`5YC7E/50TBY>;)#VD_?_N]QJ-=U\63O"3<F,18QO'=Q
+M=D45L(8#S(?>Y;G+KRX?X8>$ATHN"$[NZ?V[TS]^<BCSZ\5]_]V?_D&XZP`W
+M>`X)#B%#0;.:BJG^8OE8NJ?OOW5WH<@??O;C$TBX>OHR"\[3.6`TS^$B=FV"
+M#T/L$FZ,)^O>-H^-^Z;YZ$]?OGW[33K9)A1[&5]#:CZ@E!-T>+['=@Z-FTYZ
+M.NCQ*+JN/35=\^'1/X3C34?1AJ>UBY6&8[T\'^/\?:KQI/KPQ+BG-^[NOAO.
+M-,#^V[__E7"WZ3$>\@B/1#T&YN%B>'I&>!_?87IBPC$%./_X\.ET^_3+_;MN
+M^$)S;PC73;T;TAE.<THJY;1,*KWMT+L[/*<V8!/.AQ9-25WC%\:`->7QW(5\
+M>!7A%;OP].GTLV^Z(2UW=RZ*NW04_?(HM$6++DP'/?1B.HJ8V*?31W^+<'D6
+M#["?-6?**3S*PY,\930?H(_O'\;4ROQ.YW&^_%[VVGE\>?$MM?J=@!.<=7YE
+MMO?]C*]\!N@$+'O.KPSY7<2ST*A2C&H&-_PT<?IN^/S7\/E!X,(C=A7/6J,:
+M,=HCW2O#]XN;>'8:Y<7H#\%=8HOX`PKD>FPJC5QO)#BWZ%T1>T?/0J-*,:H9
+MW%;ORM@[>M8:U8C1KF:W++:*O:-GIU%>C/X0W#7VCC^`0:['WM'(L[6?\I:]
+MJV/OZ%EH5"E&-8/;ZET3>T?/6J,:,=K5[);%MK%W].PTRHO1'X*[Q=YQK$"N
+MQ][1R/7&9N^ZV#MZ%AI5BE'-X+9ZYV/OZ%EK5"-&NYK=LM@^]HZ>G49Y,?HC
+M<%46>W>1WO%Z[!V-7&]L]:[BO*-GH5&E&-4,;J-W%><=/6N-:L1H5[-;%LMY
+M1\].H[P8_2$XSKM">L?KL7<T<KVQV3O..WH6&E6*4<W@MGK'>4?/6J,:,=K5
+M[);%<M[1L],H+T9_"([SKI3>\7KL'8U<;VSVCO..GH5&E6)4,[BMWG'>T;/6
+MJ$:,=C6[9;&<=_3L-,J+T1^"X[SCCTZ0Z[%W-'*]L=D[SCMZ%AI5BE'-X+9Z
+MQWE'SUJC&C':U>R6Q7+>T;/3*"]&?P3NFL7>7:5WO!Y[1R/7&UN]NW+>T;/0
+MJ%*,:@:WT;LKYQT]:XUJQ&A7LUL6RWE'STZCO!C](3C.NUIZQ^NQ=S1RO;'9
+M.\X[>A8:58I1S>"V>L=Y1\]:HQHQVM7LEL5RWM&STR@O1G\(CO..__&"7(^]
+MHY'KC<W><=[1L]"H4HQJ!K?5.\X[>M8:U8C1KF:W+);SCIZ=1GDQ^D-PG'=D
+M+2'78^]HY'ICLW><=_0L-*H4HYK!;?6.\XZ>M48U8K2KV2V+Y;RC9Z=17HS^
+M"%R=Q=[=I'>\'GM'(]<;6[VK.>_H66A4*48U@]OH7<UY1\]:HQHQVM7LEL5R
+MWM&STR@O1G\(CO.ND][QFJQVZEWW`F[9.\X[>A8:58I1S>"V>L=Y1\]:HQHQ
+MVM7LEL5RWM&STR@O1G\(CO/.2^]X/?:.1JXW-GO'>4?/0J-*,:H9W%;O.._H
+M66M4(T:[FMVR6,X[>G8:Y<7H#\%QWO72.UZ/O:.1ZXW-WG'>T;/0J%*,:@:W
+MU3O..WK6&M6(T:YFMRR6\XZ>G49Y,?HC<$TV]2[MW"#7H7?)R/7&5N^:..^2
+M9Z%1I1C5#&ZC=TV<=\FSUJA&C'8UNV6Q<=XESTZCO!C](;@X[R#\'92_@_!W
+MV.7OFCCO(/P=E+^#\'?8Y>^:..\@_!V4OX/P=RO9+8N-\P["WT'Y.PA_=P`N
+MSCL(?P?E[R#\'7;YNR;..PA_!^7O(/P==OF[)LX["'\'Y>\@_-U*=LMBX[R#
+M\'=0_@["WQV`B_,.PM]!^3L(?X==_JZ)\P["WT'Y.PA_AUW^KHGS#L+?0?D[
+M"'^WDMVRV#CO(/P=E+^#\'?[<&T6>R?\'92_@_!WV.7O6LX[X>^@_!V$O\,N
+M?]=RW@E_!^7O(/S=2G;+8CGOA+^#\G<0_NX`'.>=\'=0_@["WV&7OVLY[X2_
+M@_)W$/X.N_Q=RWDG_!V4OX/P=RO9+8OEO!/^#LK?0?B[`W"<=\+?0?D["'^'
+M7?ZNY;P3_@[*WT'X.^SR=RWGG?!W4/X.PM^M9+<LEO-.^#LH?P?A[P[`<=X)
+M?P?E[R#\'7;YNY;S3O@[*'\'X>^PR]^UG'?"WT'Y.PA_MY+=LEC..^'OH/P=
+MA+_;A[MEL7?"WT'Y.PA_AUW^[L9Y)_P=E+^#\'?8Y>]NG'?"WT'Y.PA_MY+=
+MLEC..^'OH/P=A+\[`,=Y)_P=E+^#\'?8Y>]NG'?"WT'Y.PA_AUW^[L9Y)_P=
+ME+^#\'<KV2V+Y;P3_@[*WT'XNP-PG'?"WT'Y.PA_AUW^[L9Y)_P=E+^#\'?8
+MY>]NG'?"WT'Y.PA_MY+=LEC..^'OH/P=A+\[`,=Y)_P=E+^#\'?8Y>]NG'?"
+MWT'Y.PA_AUW^[L9Y)_P=E+^#\'<KV2V+Y;P3_@[*WT'XNWVX+HN]$_X.RM]!
+M^#OL\G<=YYWP=U#^#L+?89>_ZSCOA+^#\G<0_FXENV6QG'?"WT'Y.PA_=P".
+M\T[X.RA_!^'OL,O?=9QWPM]!^3L(?X==_J[CO!/^#LK?0?B[E>R6Q7+>"7\'
+MY>\@_-T!.,X[X>^@_!V$O\,N?]=QW@E_!^7O(/P==OF[CO-.^#LH?P?A[U:R
+M6Q;+>2?\'92_@_!W!^`X[X2_@_)W$/X.N_Q=QWDG_!V4OX/P=]CE[SK..^'O
+MH/P=A+];R6Y9+.>=\'=0_@["W^W#^6SJ79+@0:Y'&2.-7&\\C4T;/MWPF;EG
+MN#CO5A5]*_^4>N?6LWNAQ3\&][+826Z(46Z8-A%3N;\/<((SED/B&KN^#WA$
+M#HFT+N?K57)(I'4Y7Z^20R*MR_EZE1P2:5UN(H=$6I>;R"&1UN4F<DBD=;F)
+M'!)I76XBAT1:EYO((9'6Y29R2*1UN8D<$FE=;B*'1%J7F\@AD=;E)G)(I'6Y
+MB1P2:5UN(H=$6I>;R"&1UN4F<DBD=;F)'!)I76XBAT1:EYO((9'6Y29R2*1U
+MN8D<$FE=;B*'1%J7F\@AD=;E)G)(I'6YB1P2:5UN(H=$6I>;R"&1UN4F<DBD
+M=;F)'!)<E]O((<%UN8T<$ER7V\@AP76YC1P27)?;R"'!=;F-'!)<E]O((<%U
+MN8T<$ER7V\@AP76YC1P27)?;R"'!=;F-'!)<E]O((<%UN8T<$ER7V\@AP76Y
+MC1P27)?;R"'!=;F-'!)<E]O((<%UN8T<$ER7V\@AP76YC1P27)?;R"'!=;F-
+M'!)<E]O((<%UN8T<$ER7V\@AP76YC1P27)?;R"'!=;F-'!)<E]O((<%UN8T<
+M$FE=GCWW[O?+(9'6Y?1\E1P2:5U.SU?)(9'6Y?1\E1P2:5UN(H=$6I>;R"&1
+MUN4F<DBD=;F)'!)I76XBAT1:EYO((9'6Y29R2*1UN8D<$FE=;B*'1%J7F\@A
+MD=;E)G)(I'6YB1P2:5UN(H=$6I>;R"&1UN4F<DBD=;F)'!)I76XBAT1:EYO(
+M(9'6Y29R2*1UN8D<$FE=;B*'1%J7F\@AD=;E)G)(I'6YB1P2:5UN(H=$6I>;
+MR"&1UN4F<DBD=;F)'!)<E]O((<%UN8T<$MY4#@EO*H>$-Y5#PIO*(>%-Y9#P
+MIG)(>%,Y)+RI'!+>5`X);RJ'A#>50\*;RB'A3>60\*9R2/199BB'1&\JAT1O
+M*H=$;RJ'1&\JAT1O*H=$;RJ'1&\JAT1O*H=$;RJ'1&\JAT1O*H=$;RJ'1&\J
+MAT1O*H=$;RJ'/&=99BB'/&>F<LCSRU]-?`SN9;&3W/""]C<#]OUF]RX(3][@
+M,+R:(EX,K[P7N!M<[E?S^SK\]97"==;E]K\-L"A<T[P`_"?S.W\VC=^>7S7^
+M[V+Z5;(O_]Z^\?3-:?Z'@-?Q<2ZJ\%MQB])=ST<S_.G;'Q<93G!F<M<);O=Q
+M3J1EOP7WM<#ET]/WC**_N%N?.[T6N*^F3\)=/I>=[I..%6O\F[:OV741I^<<
+MODT$]H[_*3O/`=/YNN?\ZI=IG&?E?B8_][+<\"U2?]>LGL=LJFZ4Z^9PXZ"2
+M\YP=X4[WOGJ9W<WX,+#\RCCXE1M`YE^Y$]S9=A#4XV291!HO_]Z^\?3=:?YG
+6`KQ$0+,.7L+O$<F^^#]5"_Y['F``````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-gpt.qcow.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-gpt.qcow.gz.uu
new file mode 100644
index 0000000..624c326
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-gpt.qcow.gz.uu
@@ -0,0 +1,132 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-gpt.qcow.gz
+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
+;Z)M]Q"_BY[E'_2+>'HXWWOOM/_VP*B?UK```
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-gpt.qcow2.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-gpt.qcow2.gz.uu
new file mode 100644
index 0000000..b082a2d
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-gpt.qcow2.gz.uu
@@ -0,0 +1,26 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-gpt.qcow2.gz
+M'XL("+X[(U0``VEM9RTV,W@R-34M-#`Y-BUG<'0N<6-O=S(N;W5T`*V92V_4
+M,!"`[_T5+F]:6.)7DN51:$LK]=8BN'')\UB)*PK\=N+8B9/)3-PNWK6BKJSY
+M9#O?C)TT2>R',<V92IG:L[9D_6_7!)O]6#;6W5W?[.:?[LC">$)$(1U*3K@%
+MZ]+C!(5+^+J#X[C9Z"2"$V/4&A3"*7)T6QT([N1H6+KA9N0@0AX"M#CR9APT
+M/F''!R/4@>,3L<<G\?738QSL2+?')^WX8%1&X?(@3B!1>PI7!'$2B2HI7!7$
+M*22JIG!-$*>1J);`\8`J/2Y%HCB%$T%<AD1)"J>"N!R)HKSC8>_V2!3E'0][
+M5R!1E'<\[%V)1%'>\;!W%1)%><?#WM5(%.6=(+QC'M<@491W`GAW['!//*Y%
+MHBCO!/#NJ<,]FW`<BZ*\$\"[YP[WPN.0>B<H[P3P[J7#O?(XI-X)RCL!O'OM
+M<"<>A]0[07DG@'>G#O?&XY!Z)RCO!/#N[<H[CM0[07DG@7?O'"OQ.*3>2<H[
+M";SC#B<\#JEWDO).`N^DPRF/0^J=I+R3P#OM<*G'(?5.4MY)X%WF<+G'(?5.
+M4MY)X-W>X=Y['%+O).6=!-Y]<+B/'H?4.TEY)X%WGQSNS..0>B<I[Q3P[K/#
+M??$XI-XIRCL%O#MWN`N/0^J=HKQ3P+M+A_LZX006-7F7)'ASN*M5S@JDWJGT
+M@;CK-8Y^6#GD.*O\<9LC5[IC`Y@_'DCNM<J>4^)-6-L)&ZL*Y$IW=!>[Y7<"
+M#KG[".`XPB7.35C;W+4/C$W#VM8UNU(N.)\=$)`)'^]FN#KR^@WI]@B@UJPH
+M5L`?X_B&=.OSR[X;Z.W60S'0@FDUX8:YZFH^OJOK&W9[_NV[@?WTTQW2+2M8
+MQ5F1LP*.CE/3_8W9IVVZ92U<[1$G*=QT+`,X<[S(Z@T<UECWA\"IK:CII<,#
+M[JW%Z609-2];9ILH)6L+5M0$[@S@TLCF*=-=IBRK6-J8]TE5:_ZH4_.4QO(^
+M3>RV+88SUIYEW)S=>F!W?[>[M["WNU^G;GR*.R.P1G=0JZ>&RIQ3T\W\@P`Q
+M7;;$8:^1_FOU3%TN=;35VSM9L$9WD*M7V-7#%\FL'IHRW;AJ8\*-N#+NZG'[
+M"C,Q]7M]I3NZV]WR:X'*`:.-4*5M%3$[#"YB=AA<Q.PPN*C988`1L\/@(F:'
+MP47,#H.+FAT]L$GB;>(&9]PK,E8+\YRX^'_!UG;<#8^/Z^DV8FOKW]C$\9O1
+E1-S$#6YS$\\:>K+V\Q=,-N(F;G!1-W&5F>/WT3\!FKQU%1H`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-gpt.raw.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-gpt.raw.gz.uu
new file mode 100644
index 0000000..d413df2
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-gpt.raw.gz.uu
@@ -0,0 +1,15 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-gpt.raw.gz
+M'XL("`+&'50``VEM9RTV,W@R-34M-#`Y-BUG<'0N<F%W+F]U=`"MEC]O@S`0
+MQ?=\BI>U52W;V`262JW42MW2JMW:@3]FC-2=#U\?A@2(C1KIP$)(Q_UR]_#C
+M(F4X`*,AJ\@U'>B?Q?+L=W>[@:;JVX#^]ZF$%5!X8,`U/B@U/>,<NFY<4@U9
+M(5E):#7>3SAQ.?9BAFO/6=<K'9CC1,!-[7:W`:U%55T!OZ;Z]/`Z+$P.4T+[
+MYR6,@M6PYHP;>K7-O+Z7US<<GSX^"?9]:5=[:5#[_!95!K<22:IDNS_K=@-.
+M4U:W5GO"94G</H[+**O=P,56&F>VLL(>^M^[#3@KEUG%/"MSJ#-T%:HV@7M<
+MX7+FG6<H7.<X-,@=K$+3T4V;0RF@\#8I!HB&]B66."CHFH#]Z5V<`NQ!_-Z/
+M]1DU[HC82@=2ZIEAJQ2I=@^TMS?;Q1*7<:M7D'J63;URW"RQE0XDU:N">G&1
+M2+VH9?I)M<DA$Z[F54\-4\/[PW^_KZ_I0'\4RS,`S0ADJ]!H/S;XW$$X1G<0
+MCM$=A&-U!P$9W4$X1G<0CM$=A&-UAP<ZR3?$":?"F.Q:%!HN6]67&L>7^I;M
+I.KTU^C>&>/QE.,8A3KCM(>YN;99QB!..=8@;_W]*RMT?5F[7A(@+````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-gpt.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-gpt.vhd.gz.uu
new file mode 100644
index 0000000..0dfa2d8
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-gpt.vhd.gz.uu
@@ -0,0 +1,22 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-gpt.vhd.gz
+M'XL("`+&'50``VEM9RTV,W@R-34M-#`Y-BUG<'0N=FAD+F]U=`"MF#MOW#`,
+M@/?[%2RZI:ACR9+L6UHT:`)T2U];A_@A!QEZ?5R&#/[Q%67Y(5MRX81W@LZ&
+MS,\D15$\I6G_`5`9J!:4!B7Q.A>@CI`7`&;0-6Y[YFZAJW^==/WX\)2X3W?H
+M82R=2_GB*,\S$.8E.?`27Z(:O(9NP"2OK^\O'G[>#SCN<,.+A0+!01J(6+U'
+MI:-V2+JY^OK1(N\F[;*U=I-4_].VD+6S)[)!NSO;OY\;*XR4>1Y;#JF$5$S-
+MN_$&)F,7OI/I0FJF9LBI,V-#.+4EM0=W<7!ST8>*"8S<],9U#'*.UR9L!C^L
+MF@F5I_/O\N]9+_3CD5!1HWYL-9;%S>4N5/CPL--`8#AOF0N6\KC$!4+E1=Y3
+MOMPPN\8))G#<#;?F^]Z;4##73[%TP^?QR8CJ5Z)^9FVE9:"/#W17B?\=@56U
+M#SAXT,>-!E<U^L_F$:TGB_H@F1R;;4Q(.O-?U1#/;]7N`TH)9;D"?A_TJ^UT
+M2)OPCA@8)CD(!M(DORF<K>VRGNMW??,);C]\^8:P'Y.Y-89+PZ&HH3Y"6RVT
+M6Z^T[=Q2\S[Z>!LT-HOB+L,X7&QMLX$+M3A.;$FYK6R'L3+UI8JY5*:ARJ`M
+MH6PBN'<+''5>UCA<*<AKW,(E@]KNY8T"Q@`*LTP*"^'`C8IF8S>[<(7`[O0Y
+M.?6PM\F?-TX_S5Q$A%I\(.8];?-R$3,WGQ)VQ%SP<=1Y61?H/4GFO:,+EE"+
+M#T2]5_;>"SL)O1=:NN.NEB2O?%Q%ZSUF=PVS/DS^7O?Q@>XV\;\]D+MMB&Q?
+MXRZ1DFDH')!,0^'6+Z&&3&].YMY95FY2B#(,X@@S#.((,PSB2#,,`@DS#.((
+M,PSB"#,,XD@SC*(MA)0KA+("-,,_+I4?-?&2IBN2<Z_8I6>N+82BY=-&(12>
+M#,I"2/VO$&IUS-B1LS"6L!!2U(60<HF4Z"Q##8706H?GG&6HH1":O?@%9QDJ
+@7`@]]RP#<81G&8@C/,M`''&H,%.['/X!4B?R+P`3````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-gpt.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-gpt.vhdf.gz.uu
new file mode 100644
index 0000000..820c91d
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-gpt.vhdf.gz.uu
@@ -0,0 +1,19 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-gpt.vhdf.gz
+M'XL("`/&'50``VEM9RTV,W@R-34M-#`Y-BUG<'0N=FAD9BYO=70`K9<[;]PP
+M#,?W^Q0LLJ6HHK=]2XL&38!NZ6OK$#^D($.O*-JA@S]\1<EWEGR2T0MD$X8/
+MM'[FGR9-'Z5A`Y`<:)<YEAW3+4GW:7>]\S367P9T]\<05D#B@`$W."?E>(TQ
+M8.ULE/E58;$S09=SCR/+1DF$&^-5*RL[8AP)N*-<>QE0*>BZ,^"W8WS</PX%
+M4H/<`W?74Y`,%`<E3SBO70UQ?'?W'^'A_>>O"/N^R.7,.4<.[0##'FR_BH[]
+MO]R`<P%A]KG-BA5%W$T>)Q`W;N!R5L;)K56AABX1JVBZJHU7"0.]`-M!-Q9P
+M;U<X7;GR)+I[#<T`VH!B,%@\&34P!M"Z-FD]A`-W(>ZA8<![!$Z'3^008&_(
+MK]=S?)+-%9&SLJ.4/8FE0MN2W`9K>U,NI#A1.WLM9D]5R]Y^+I:<E1W%['4A
+M>_DD8?9RK>MP<];(JQ37U\T>\U/#]8=[?Y\?RX[I@:1[`,H96"U"9>U0L3L0
+M5[$[$%>Q.Q!7M3L06+$[$%>Q.Q!7L3L05[4['-#0>D,<<5A[H@7#H!'0IU53
+M'L=32WZ'P&X2N89OC?Z-(9Y_&*;B$$?<YA"WIB3VQ%F)K3C$$5=UB.OY\UL+
+MT+Z_M,+S1H)V+=7&0+[4C`<./P]F^//\-\Z>]F]F6#Z25X;KN<#"U*Y%.KR)
+M'O$\BN_J[NGZ^<?3$<=G5<<;8T6[*G80>297IW+O;[]\\,C');K,:TJOLN?B
+M%#81/D?WZ(_O8K'R)-98<,JI7"SYD3BRA8PX7RKQQ2]]M@%7NU3<7X/=/VC0
+&,#.S#0``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-gpt.vmdk.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-gpt.vmdk.gz.uu
new file mode 100644
index 0000000..8292403
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-gpt.vmdk.gz.uu
@@ -0,0 +1,88 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-gpt.vmdk.gz
+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
+)_ZT-&`6T90``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-mbr.qcow.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-mbr.qcow.gz.uu
new file mode 100644
index 0000000..003299f
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-mbr.qcow.gz.uu
@@ -0,0 +1,128 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-mbr.qcow.gz
+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
+K6A$,W\WRQV^+$_@[_\*W?WYX_-?]8),&?]D)-G?TG<^__1>$>8]XH:@`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-mbr.qcow2.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-mbr.qcow2.gz.uu
new file mode 100644
index 0000000..8d3e191
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-mbr.qcow2.gz.uu
@@ -0,0 +1,23 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-mbr.qcow2.gz
+M'XL(",`[(U0``VEM9RTV,W@R-34M-#`Y-BUM8G(N<6-O=S(N;W5T`*V8VY+3
+M,`Q`W_<KS!T6*+'DI`F7%A:6&=[@`7A.;U_1X=M):C5*%"G>=M)F,NVX.B/;
+M1VJ2+(LOYW+O0N%"Y0X;UWRG`USOR_!PQU_??RSZK^--A/G,B%(&EOL.-V#]
+M8QQ8N,R/![R.ZV6'"@[.46-0"A?,[*8&%-SMS6GI3IM1B@B\!AAQYF9<E1_$
+M_&1$N#(_F#L_U-<O/\?)@6(Z/XSYR:BEA2N3.%"B*@M7)W&H1&TLW#:)"TK4
+MSL(9E=O#Y4K4P<#YA"H-KE"BO(6#)&ZI1*&%"TE<J419WOFT=Y4297GGT][5
+M2I3EG4][MU&B+.]\VKNM$F5YY]/>[90HRSLPO'.,VRM1EG<@O'M$N,>,.RA1
+MEG<@O'M"N*<=SFM1EG<@O'M&N.>,4_H=6-Z!\.X%X5XR3NEW8'D'PKM7A+ME
+MG-+OP/(.A'>O"?>&<4J_`\L[$-Z]'7GGE7X'EG<HO'M'K(QQ2K]#RSL4WGG"
+M`>.4?H>6=RB\0\(%QBG]#BWO4'B7$ZY@G-+OT/(.A7=+PI6,4_H=6MZA\*XB
+MW'O&*?T.+>]0>/>!<!\9I_0[M+Q#X=TGPJT8I_0[M+P+PKLUX3XS3NEWP?(N
+M".^^$.Z.<4J_"Y9W07CWE7#?.AQH49UW6:8?A+L?U2S,>_T9^/K8*V=[8`)8
+M7@*<RC#BJEDGG,<)MQK4RMD>.-XMAN\.>"JV"X#-^AP.(R!-.(_%UOR@.>J<
+M/C1'+!":WM9SF0TGO*928]QNYO4[U<<%P#QW=3T"_C[G!Y-I7)[?<C_S_I;Q
+M<<.RK=J\<"4\-,._]W_&0C>XV2HXXNS'#31P3KAKL2/<NH?#:!]3>G4Z\*[_
+MN8=;+;C5-[C)QPWM/=1>&S`GF\\K2]DUJ\[6WCZWE^[M'=;YWUM<>G?[ZS@_
+MI5G!8+H3^;GQ=-NK@N[N7>Q'BX/$=-T0US:J_GX.MC"Q>JMQ=MN9-\/+RGA@
+MY;:08>5&',S;"*I39VD,;'XU/ML#QY^+X3L"`P%G6\%0M/]M-_\!8,LR/2,5
+"````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-mbr.raw.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-mbr.raw.gz.uu
new file mode 100644
index 0000000..7daee29
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-mbr.raw.gz.uu
@@ -0,0 +1,12 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-mbr.raw.gz
+M'XL("`/&'50``VEM9RTV,W@R-34M-#`Y-BUM8G(N<F%W+F]U=`"ME+V.PR`,
+MQ_<\A><."$AHZ))*E6Z_I>W,Y9*GR,/7Q*0Q)1^-!!B$9/CI;VR0DAI`I4&Z
+MA7G=,=Q$W(?B5(PT]7<,:"7T?0(4""1<BSC<@.9,6*"5/7CA.-!:!647UF0P
+MB+%=_=0(AOM_GTIMW1%P<YO#[8\!C0'G$N!]TJ<W91S75W>9\VO'@C$U5`;,
+M&:S^5N'SY_&AD'`J5\"$TWNX23!5T!+NRG`E5=],4>P4KSN^9KB&QH2KMM3A
+M3<ANR;$:K,E;+!9[?([G&50'J@1I@T_'P'=^8=9W267H*-P-?9"&ZSRNCO<K
+MAM,[X4*,\Q\5SV>4PIW;:U)U;>9DJ,^7\>7+]9#XY1).Y_T(+N//@A6(N])Y
+9W3'\BK@3L`K`;#?H?SXIBQ>7_'@>Y08`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhd.gz.uu
new file mode 100644
index 0000000..7b3c619
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhd.gz.uu
@@ -0,0 +1,18 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-mbr.vhd.gz
+M'XL("`3&'50``VEM9RTV,W@R-34M-#`Y-BUM8G(N=FAD+F]U=`"METUOXR`0
+MAN_Y%2/MK0<+CP'32RI5FSU7JMJ>L6M'/>RVVNPA!__X,@9L\%>:+;9C$<$\
+MO,,,8\&8O0!D`;(%V8`4U"XYR%LH%8#I=`_V[]S]A:Y^_]/4_][.F;NZG87E
+M++2*S<D>"^!FDA)0TR3RE=K0>4SVXW"\>?M]]#AT.#\QE\`1A('PV3R*#>J(
+M].O^\>=473%7-UK9>=H6BC88483JLNPNQ'%C9<;3(Z'EO4S_1'^BCA`7J1-L
+M8A7(7%K4P-DEG-RRN@9WLW.QL*EB$J,T;P8RAQ*I;=+&K\/L,:ER/GWHOZ=F
+MH@]74D4&P9CV\75WT:4*^L%.`2>!6^Y"3SE-<0NI\JW5D[$==PVS"$SX#NS=
+MCU=O1$&H3^9L8\W7@[&J3Y,^L[>87GBO=W3W67P/P*JZ#JB851CC!H>K>G!8
+MB]$CNU?=^M4Y%,UB0/IMNP_6KWI-'-^JO0XH!&@]`SYY??6FC.OU*94XOJI/
+M&%%2.1<2%'Y5X<OA>6'_*KU2#OZO^BF-EW!><%CM8]Q=@"ML]HV4H#A%>1>V
+M`]S>_CR.;ZFCFM`L=:PZ*Q(GBU83NS#.D#>0%\"4Z\,8.,071GVW<QD8N;NA
+M#^;N:L*5\?@\P.$%=R'&5>Z[ZT=&(;RP>ONYNCIQ,*KISOCBSB5(O',M#M,6
+M`MU7%I.!9M3\O=[1/63Q;8'H/D7)OFWHBFDRA=P!DRDTP":Q0IWV^R&=PD0'
+J!<(E/"@0+N%!@7`)#PJ$2WA0(%S"@P+ADAX4I#D",K;[!%1JM8A=#@``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhdf.gz.uu
new file mode 100644
index 0000000..8cbe404
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhdf.gz.uu
@@ -0,0 +1,15 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-mbr.vhdf.gz
+M'XL("`3&'50``VEM9RTV,W@R-34M-#`Y-BUM8G(N=FAD9BYO=70`K96[;L,@
+M%(;W/,61NF6PN)LLB10UG2M5;6?7P5&&MDN'#G[X@O&%8WQ)*NQC"POX_)\+
+M0(B_``0#4DR\YSOJ8X;O>K/=-#3Z<1]0$ZBJ")A9H,>5%F<'6"MDV[#&*W#"
+M[6.MI,!-V_8&==9<!_?:9P'NW,^*;;ZCQ0W7X&YU'U!**(H(^-KI8XLR[M>7
+MF\3YU4W!R!R$!*E`LUL5OI_>1@H]CJ9RV./8&JX3["MH"G<(<-Q7WT"AP:RP
+M[L)V@-O[I\.))74V$L1,=<PZ*],6B[8WGA?F&:@!RH'HMH]A8)]?&/3M8AD,
+MN;N@#V)W"X?+\7@:X-B*NX!Q;J,*\XE2N!*]?:RN3)P,.EX9-ZY<!\$KU^-8
+MVHU@U^PLM@+MJ/@]WU$_9_CV0-$"DT50MV>;XJ`J4`:4=.U<@-I!KD,@PY54
+ME]]?IORY_H89=CC:'T6QN?F,N]6B<F"%^XDZNW:@[^%TV5X_+QVNVZJZ'POE
+M@BXM1$3N:NSNT_'E<:R.QT'2*'IT.#A[QU'T#B%.],X:TVR!=##T@3HFMRJ'
+8DV0TZ[^Y]3B5N%3LN;OY`[XTL3D0"0``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-mbr.vmdk.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-mbr.vmdk.gz.uu
new file mode 100644
index 0000000..c26e913
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-mbr.vmdk.gz.uu
@@ -0,0 +1,84 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-mbr.vmdk.gz
+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
+>;]]X^NXT_S,!7B*@60<OX1>39%_\'RJ'TQAO8```
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-pc98.qcow.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-pc98.qcow.gz.uu
new file mode 100644
index 0000000..0eada21
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-pc98.qcow.gz.uu
@@ -0,0 +1,126 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-pc98.qcow.gz
+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
+C3O?P=_W"UR^O[_[U8W!H@[_L!(=ON&RWO_T?@O'+%J.H````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-pc98.qcow2.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-pc98.qcow2.gz.uu
new file mode 100644
index 0000000..4d325d8
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-pc98.qcow2.gz.uu
@@ -0,0 +1,22 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-pc98.qcow2.gz
+M'XL(",([(U0``VEM9RTV,W@R-34M-#`Y-BUP8SDX+G%C;W<R+F]U=`"MF-N2
+MTS`,0-_[%>8."Y18LG/ATET6EAG>X`%X;KO-5W3X=NK:C1)%BKLE;2;3CD=G
+M9/M8L5,4\6.,M\:5QC6FW9C#_W2!Z?T97F;_\]OW9?^S7T28+90HH:':=;@!
+MZR_A0,,5=MQ@95PO.Q1P<(H:@W(XIV8WU2#@KA;'H3M.1LTB\!)@Q*F3<5%^
+M$//C$>["_&#N_%`>/W^*XPWE='X8\^-1E8:KLS@0HAH-M\[B4(C::+AM%N>$
+MJ'L-IZS<'LX+4:V"LQE5#KA2B+(:#K*X2HA"#>>RN%J(TKRS>>\:(4KSSN:]
+M6PM1FG<V[]U&B-*\LWGOMD*4YIW->W<O1&G>@>*=(=Q.B-*\`^;=HX1[3+A6
+MB-*\`^;=DX1[VN&L%*5Y!\R[9PGWG'!"O0/-.V#>O4BXEX03ZAUHW@'S[E7"
+M71%.J'>@>0?,N]<)]X9P0KT#S3M@WKT=>6>%>@>:=\B\>Y=8!>&$>H>:=\B\
+MLPD'A!/J'6K>(?,.$\X13JAWJ'F'S#N?<"7AA'J'FG?(O*L2KB:<4.]0\PZ9
+M=TW"O2><4.]0\PZ9=Q\2[B/AA'J'FG?(O/N4<"O""?4.->\<\^XZX6X()]0[
+MIWGGF'>?$^Z6<$*]<YIWCGGW)>&^=CB0HCKOBD*^$NYNM&9AWOVGH_VQ%>YZ
+MPP2P?@AP*L.(:V;ML(\=#AJLA;O>L+]=#K\=\"C,`X#>F_48^"MVV$=A&F>V
+M3NI7V])UQOCYN87Q84IF'3\03VC_D6&UFSG#.KYPJ,*Z]:6IX=P,_]S]%J:D
+MGN\,&7'Z"X?4<$H86PUWW<-AU(PHO95JMI8*?/]W#[=:4K$_X"9?.(13U$YJ
+M4#OKYY6E[LK5Z>K/<]B\AS/6Z?G--M_=_!K*3RA7,.CN1'YFW-VP+^C.[VP^
+M`@XRW35#7-@7].=S,(69T5N-L]O./!F6KXPS5VZ`#%=NQ,&\A:`Y5I:#@:&*
+=C^YZP_['<OB-0)>`LXV@*\/3;?$/F4FZ`B45````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-pc98.raw.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-pc98.raw.gz.uu
new file mode 100644
index 0000000..7869940
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-pc98.raw.gz.uu
@@ -0,0 +1,12 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-pc98.raw.gz
+M'XL("`7&'50``VEM9RTV,W@R-34M-#`Y-BUP8SDX+G)A=RYO=70`K93-CH0@
+M#,?O/D7/>S"EPHH7)YED[W.9W;-K]"E\^`7!E8KXD0!(,(5?_FVAB*X!2`+L
+M=N:T87J6O$_%1S'3Q'@/J!1T,?!M@#..K+Y&0B_!K#8#QG$=S#"5F[;@A#'&
+M('\J:=C!>7=EYO@1'@JYK[`>,BO4LT)5@U2@/D'3584_7]\[*=&8+24.1V>X
+M17`UIG"/`%>Y:[921'"J%U`-_B=<![C6?0M.'JDSD<!ASY!T5N6]+-IT?B[,
+M,X@!1`6HO8TX\#^_L.IK8AG$W#W0![&[G<75?+\(<'3B+G#<K\4%^60I/(E>
+M&ZOK,R=#;%_&Q9=K(?SE.ASE+03-7%G,#;15/)K3ANE5\NZ`T@.S1=!6/L3B
+)#]P1(I+G!@``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-pc98.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-pc98.vhd.gz.uu
new file mode 100644
index 0000000..8582877
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-pc98.vhd.gz.uu
@@ -0,0 +1,18 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-pc98.vhd.gz
+M'XL("`7&'50``VEM9RTV,W@R-34M-#`Y-BUP8SDX+G9H9"YO=70`K9=-;^,@
+M$(;O^14C[:T'"X\!DTLK5=N>*U7MGHG7KGKH;M7LH0?_^#(&DL%?2;;$#L("
+M'M[Y`(00_@>@*]`=Z!:THGHM06^A-@"N,;PXE&7XA+[Y^Z=M_KU^%N'7;SRL
+M%'Q4.IS&8P7235(#6II$_Z8Z]!%3_+A[N7I]>XDX#+@XL=0@$92#R,D\1AS4
+M$>G^]O'G6%TU57<<Y>?I.J@ZUJ/BZHKBAN.D&^7ZTZNADX/,^"8?20/')>J4
+M&(UB,N><RHR=P^FU49?@KC8A%CY57&+4KA2@2ZB1ZBYMHA\FKTN5S_V[_=BW
+M(WVXD"J:!6/<)I?-Q9`J&#L'!9($KID+`V4_QLVDRK>\I]-Q,E2<$X2*#3B8
+MGWKOB`*N3Y=BQ>?+P5C49TF?6UO"SI3+#?UMD3X'X*Z[#*@4V"GP*1K<D+ZM
+MA$;.^9T;>=;J:!:R[[_CVV;V']I5(9<K-":S0C,H5#5MZ$J#P7,5_KI[G@F)
+ML=E"XG%X"A<%\_T^Q=TP7.73[$AAVQ,T)51M^.!UAKOV_XB3:^IH5VCG&A:-
+M59F3Q9K1.!YG*%LH*Q`FM&$*/,07COJV4QF8F+NB#Z;F6L+5:?^2X?"$N9#B
+M=N'DC3V3$)[PWO5479,Y&+OQRCASY1(D7;D>AWDW`COL+"X#:1>?E,L-_4.1
+M/AZ(X3#*=KIA.#VR*90!F$VA#.='1H6V64VV2[-0!X69K@J$RWA5(%S&JP+A
+?,EX5")?QJD"XC%<%PF6]*FAW"11B\P51KS:'7PX`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-pc98.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-pc98.vhdf.gz.uu
new file mode 100644
index 0000000..bfbd1f1
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-pc98.vhdf.gz.uu
@@ -0,0 +1,15 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-pc98.vhdf.gz
+M'XL("`7&'50``VEM9RTV,W@R-34M-#`Y-BUP8SDX+G9H9&8N;W5T`*V5/6^#
+M,!"&]_R*D[IEB/R-61(I:CI7JMK.E)HH0]NE0P=^?'T8@@]#DE;&!AD=?GCO
+MSCXS%BX`)8!5,\]E0[O?T-:NUJN.QIN_`;6&*@4^>V"'$ZBO5%`K\*-)AZ89
+M.S&TF\DUX+@WIJ!^UJ)A!M>[JS+'3["+0OZNL'"9%=I.H2Y`:=`&K+A5X>OA
+M928EEF5+2<"):[A!L&R6<+L()\,R&RD\FE5SD*Y_B<<1;AON`:<NJ?.18&[.
+ML.BLSKM8K&]T7IQGX`ZX!&9[FZ#`<WYAU%>F,@1Q]X(^2-VM$%?0[WF$$U?<
+M!8I[0UR43Y+"*]';INKJS,G@TYUQX\Y%"-VY`2?R%H*RJRQ^!6(53Y[+AO9Q
+M0UL`JAZ8+8*V/]V,!-.`<6`TC@L%IH3"QD!!5U);?WVZ^OOT$V<8<7QRYL0=
+MYPN)N\44("K\B7G'<:3O[G!<GSZ.`VXH5<./E<&@:P]1B;N6NONP?[J?JI-I
+MD"R)'D>=<=GSCI/H[6*<.COK7%<"^=C)"S',EBK$:3:9]=_<!IS)O%3\P;OZ
+)!3S1^)L2"0``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-pc98.vmdk.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-pc98.vmdk.gz.uu
new file mode 100644
index 0000000..9036f37
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-pc98.vmdk.gz.uu
@@ -0,0 +1,84 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-pc98.vmdk.gz
+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
+/YC^:)/GB_P?]NZ=Q8```
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.qcow.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.qcow.gz.uu
new file mode 100644
index 0000000..50e4d02
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.qcow.gz.uu
@@ -0,0 +1,127 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-vtoc8.qcow.gz
+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
+F#'Z6Y@S^SC_PZ\\_WO_KZV#*@W_9*TQW7CF??_@_"8E_G;^F````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.qcow2.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.qcow2.gz.uu
new file mode 100644
index 0000000..32a7f31
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.qcow2.gz.uu
@@ -0,0 +1,21 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-vtoc8.qcow2.gz
+M'XL(",0[(U0``VEM9RTV,W@R-34M-#`Y-BUV=&]C."YQ8V]W,BYO=70`K9C;
+M;M-`$(;O\Q3+J4"!DIW9=6Q.A1XB<8$$X@6(8_L!N$/*P[.Q-QE[/.--(J=6
+MI-3]/\VNO_ZUNUQV+V.\-2XSKC!-:<+G>(#I?1@>9O=K_?VF_]HM.IA=*JG1
+M"6M6Q1$W8/TC'&BX$!>^)>)ZTZ&`@T-J#$KAG#K=U`D!=[UHMZZ]&#E+X"7`
+M#J=>C(OF@VX^GG`7S@=SSX?R_OD+Y\/YY\-Z*L<'SU+S82.D5AHN3^&<E"HT
+MW":)LT*JU'#;)`Z$5*7AZB0.A52CX&Q2%>>$E-5PD,1Y(84:SB5QF9#R&B[I
+MG5L)*<T[F_8N%U*:=S;M72&D-.]LVKN-D-*\LVGO2B&E>0>*=X9P6R&E>0?,
+MNR<1]Y1PE9#2O`/FW;.(>TZX6DAIW@'S[D7$71%.Z#O0O`/FW<N(>W7$>2FE
+M>0?,N]<1=TTXH>]`\PZ8=V\B[BWAA+X#S3M@WKT;>>>%O@/-.V3>O8^L)>&$
+MOD/-.V3>V8@#P@E]AYIWR+S#B'.$$_H.->^0>><C+B.<T'>H>8?,NU7$Y803
+M^@XU[Y!Y5T3<!\()?8>:=\B\^QAQGP@G]!UJWB'S[G/$?2&<T'>H>>>8=[<1
+M]Y5P0M\YS3O'O/L6<7>$$_K.:=XYYMU]Q#T03N@[IWGGF'>/$;<F7#/K_:>C
+M^W<KO.LG)H#Y^4#UCV/`%;,NV'<+#AN]`I/Y_1&4\+B_DJ&3]@WC*A&X_EO7
+M=[\?`'_TYO-S/Q!XVK_E8(,48-[>CH.V?WZP?T42-S5?A]O,M=P.5YZ*"_4=
+M;NVKVM0UP_WIX;8S7PP[6FY]N//'"Y9K#\M%^N&F;;[0?PJN]\MVRW&T7&`I
+M^D>-E:8SXG35$5=NJ?-.V;U["3?Y9'O^WIW<?-7&E,$3:YJMCH/)(<Y6)<M;
+C8+AG"4_!XW?]Q.[GS?"K`[H(G&W"\(`67HO_;MD=L>$3````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.raw.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.raw.gz.uu
new file mode 100644
index 0000000..941ae5b
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.raw.gz.uu
@@ -0,0 +1,11 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-vtoc8.raw.gz
+M'XL("`;&'50``VEM9RTV,W@R-34M-#`Y-BUV=&]C."YR87<N;W5T`*V206[#
+M(!!%]S[%7W=A,8!MO*J45ME5JM0+U#9P@*PY?$AP0HRQXT0>T`AIYC_-%\-8
+M"$#6:#CJZG(E1R4@)00'A']I^);DPAU/QAS^OKGX*:_AB@`C7YSWCZK%@BN3
+M<,7'"%03':T#%5@+QK/`@&NCJGV*6YLOX+J][`9<OQ57^ZRA#8Q)</\/N&'G
+MSZ"970,*#_&&7;K9%;'9VDL6=@E'$?>9XJ)=GJ@XHCXS';+3Z3NN'R#%5+5J
+M]BN',[NN"MFM.-VA]WM"L,,RCJ\.\>JJ-%I=@97OZC)YN>!^R^D)P'X$[C4A
+.-4K5C!5GC7NA2P,%````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.vhd.gz.uu
new file mode 100644
index 0000000..7c4a413
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.vhd.gz.uu
@@ -0,0 +1,18 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-vtoc8.vhd.gz
+M'XL("`;&'50``VEM9RTV,W@R-34M-#`Y-BUV=&]C."YV:&0N;W5T`*V6S6[;
+M,`S'[WD*`KOU8,B4+-NG`NO6VX`!>X')MEP4P]:AW:&'//Q(6XXE?ZU9F0B.
+M#(D__2E1#)4:/P!6@^W!>K`%]TL#MH:R`J#!T'!XYN$5SNW3+]_^>7S-PN=\
+M&F&YBJU2<[9'#886*0$=+V([[L-YPF0?/C_<//Y\F'`8<-/"QH)!*`AB%NOD
+M4*F+.B;=?_SV::E.+]7%5ORCH>]!]]$,':O+LML89\B*YG.ST(\RIY:\)`,Q
+M+E%7J(55I'1K4R-GMW#VR.H:W,TIG,48*A08)3T5V!Q*Y#Z%S;0/JT:A\OKR
+MVSV_^(4^W`D5>]&7K\;:?7<QA`I.DX,"BN7FT%T8*#^6N%6HO'/W;&IGTDV*
+M7\89M#NJV'?7SKN'TZ91(]6J/#J,;/!7K7"H#JR.<#ON.G:7;BL%"">58KZV
+M&@$T];K-_;M_]IXN+NHOB3ZW$RS_?1RN2NS^<=DJ4#4GL=WC</5L5;__[CHG
+MY>Z(:]Z*HYRA.N@\>+_`?8]PK?!A-"MW_1#_:DB_5[O;3.[J>?)XKRBS[^"B
+MO'R[Q+7)58L;PFR_H0XVU7477-."T:G5H;-W6S@O&BI-_U9<YZ"A.,FA/\C*
+M[:&(:T,%0UX12U0HK5!WE>=A^BM7;N.Y/W#^FJ7?$6B"0C&7"2BKT`:@F$)+
+M1:2HPK*K4?24JZ!0J&YFG&#=S#C!NIEQ@G4SXP3K9L8)ULV,$ZV;"4BQ=_H+
+(%O'FLVP-````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.vhdf.gz.uu
new file mode 100644
index 0000000..d5ecd33
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.vhdf.gz.uu
@@ -0,0 +1,14 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-vtoc8.vhdf.gz
+M'XL("`?&'50``VEM9RTV,W@R-34M-#`Y-BUV=&]C."YV:&1F+F]U=`"ME+UN
+MPR`4A?<\Q9&Z98C,C[$]1>I/MDJ5^@*U#409VDI5APY^^&*P8R#832-CA(C@
+M?)Q++C?+7`.X0$$A\KYSBIR!<S`*,#.3,%NBCN[PI=3]ZR-ESSO;NHV#$;-X
+MN7]0S2YTNZAUF^T`+`,=60:6R"ID-`ETN&I257_BEOPY7+U6N`[77(L39I20
+M"DI%N#</UZ[\9Y"+<!6(F[`;PB5CN&S:K'4_,CV'(Q-N'^.F<&FDHICT"7=(
+MNI-G7-."LU"U&.Q#"J=6316BK\7)&HW)$P+=SN/HHHG_IDHA2PO,S:XZ,<XO
+M="^[\'/`9@"NY9"40^43#$)#*%O\&`H.4:$H?2`-\@9=^_FAVN_3CW>#%M=7
+M/I.]R=[KJ:FEYI`"M.X/$;*?>_[NGH[;T_MQQ-$AJO%@4Z//I3E^$F48[L$4
+MYM@=BR_)5[DW:'PR'3X:__;V/HZ?@S4%2#?6YMB#'\%"*OLL+L\BU<UOP^+$
+/RJEB<F_S"YNC6FHN!P``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.vmdk.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.vmdk.gz.uu
new file mode 100644
index 0000000..06f3b92
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.vmdk.gz.uu
@@ -0,0 +1,83 @@
+# $FreeBSD$
+begin 644 img-63x255-4096-vtoc8.vmdk.gz
+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
+H_/^/2K\`KOZ`R__OO^"_9VS_6P$U`IJ=4/U[HRR_^A][EZ;PS5\`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-apm.qcow.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-apm.qcow.gz.uu
new file mode 100644
index 0000000..d037063
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-apm.qcow.gz.uu
@@ -0,0 +1,127 @@
+# $FreeBSD$
+begin 644 img-63x255-512-apm.qcow.gz
+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
+K]_NMSV](YW>>P#_Y)[[^\N;^?VX'FS3XF[UA<[[^!I]_^C_<Q@LX=*8`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-apm.qcow2.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-apm.qcow2.gz.uu
new file mode 100644
index 0000000..290ead4
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-apm.qcow2.gz.uu
@@ -0,0 +1,22 @@
+# $FreeBSD$
+begin 644 img-63x255-512-apm.qcow2.gz
+M'XL("*H[(U0``VEM9RTV,W@R-34M-3$R+6%P;2YQ8V]W,BYO=70`K9A);]LP
+M$$;O^15,]Z9-*LZ0E-P]FX$>"J0->@Z\R$"`+D8:H!?_^%+6R)2I&3$VY`A"
+M#.)[&`^?QZ:SK'XH9;4R3IF16DR5?TX7J-:3[4NMOHV_G+0?JX,:IC,AQ2P8
+MW."V6.<!!Q(NT]T%S>-:U2&#@R;5!:5P1JRN;X'!'1VL6[?>C")*X#[`&B=N
+MQE[U05U?G#![U@=#UX=\_VR3BQ=<?WU8UQ>G<@E7)''`I$82;I+$(9.:2KA9
+M$F>8U%S"E4F<95(+`:<3JGB<8U):PD$2ES,IE'`FB2N8E.2=3GLW8E*2=SKM
+MW81)2=[IM'=3)B5YI]/>S9B4Y)U.>S=G4I)W('BG`JYD4I)W$'EW2+A'`;=@
+M4I)W$'GWF'!/-CC-I23O(/+N*>&>!1PS[T#R#B+OGA/N1<`Q\PXD[R#R[B7A
+MC@*.F7<@>0>1=Z\(]SK@F'D'DG<0>7?<\4XS\PXD[S#R[@VQLH!CYAU*WF'D
+MG28<!!PS[U#R#B/OD'`FX)AYAY)W&'EG"><"CIEW*'F'D7<YX8J`8^8=2MYA
+MY-V(<&\#CIEW*'F'D7?O"/<^X)AYAY)W&'GW@7`?`XZ9=RAY9R+O/A'N<\`Q
+M\\Y(WIG(NU/"G04<,^^,Y)V)O#LGW,4&!UQJXUV6\1?A+COO61CV^Z<)WX\U
+M<Y<7>H#%+L"^"FO<:-`7;.L7['?`0CA'9>M/R*(7>/F]PAQNUV>'/A#86A@_
+MF<V\DT/IP.<75E=?F?[96AC_=O#3U%]NIIQ]4'VGR^7/DL')I]O=CU,>A]WJ
+M[&+]OY<E!Y4;Y49T=POERFJ9JKM93N[N;^]O__R^:7#5!Z2;5^%\E^I^399L
+M=7;@O34/W-MFJ@`!M_=6-?69H=TSZ^UP5>/]1OC+CTN+U93S7S.4M=6:Q2YP
+M?%>69]<7QS_&U^W^F6%_;+#^1)7N'[3Z5[])VOU3[?K<T/USO?W+4>4YXV;H
+KW]]_M8A-?4/WKZ#^^9-Z]RXOK*Y.MO]JH"'@8!4:5TWG@_\+*`W"Y1,`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-apm.raw.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-apm.raw.gz.uu
new file mode 100644
index 0000000..b47d4c6
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-apm.raw.gz.uu
@@ -0,0 +1,12 @@
+# $FreeBSD$
+begin 644 img-63x255-512-apm.raw.gz
+M'XL("/7%'50``VEM9RTV,W@R-34M-3$R+6%P;2YR87<N;W5T`*V3S6K#,!"$
+M[WZ*Z;50(\DKJ3FFM+D50D//P=0.!-K4I(%>]/"5(HG(/PDN:+T(BV4_QK-K
+MQGP`)"$%F$T64G`PPN4^2)B7M]+&71G#%![&V8VNZ[AR$*:X]T#ARI*!FE%?
+ME0)YOV#6KT.@QSE]Q*&92_4!)6?I6W;=9SN!$[D^U^.JL3JY.[]S0`MH@EJ$
+M4^V@6E<.ZK9=?3SM3_OOPS;BR.)4XYKU?]1]U=VD.IEYMC1SMA27,@#[LT74
+M1[EWC\[C4,YX.PB;)"`K$$$T5KAT-7L?`5?'MGW:/#^\KS:I?T29]:D9_HG$
+M/_^3I/XAU:=R^Z=N^J<K:#VQFQ?_?G[](D9]N?U[#/ZQ>N*\7C#KLO]X(`5@
+/-H4D'+#X`^%)]I"G!0``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-apm.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-apm.vhd.gz.uu
new file mode 100644
index 0000000..68c3838
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-apm.vhd.gz.uu
@@ -0,0 +1,18 @@
+# $FreeBSD$
+begin 644 img-63x255-512-apm.vhd.gz
+M'XL("/;%'50``VEM9RTV,W@R-34M-3$R+6%P;2YV:&0N;W5T`*U66VO;,!1^
+MSZ\XT+="@Z['W=/86/,V*"M[;HTCE\#:AB:P/OC'5T>76HYES\WD"$5&/I\^
+M?><B,>8?`)2`+:`!U#2N%.`7J*X![&1HPO4\O$+7O#R;YKA[6X>G6WDPSE*K
+MH3G9"PG*+E*!J&D1W-(8N@BSOKAYO-P]/48X$>#BP@I!"=`61(W60?;!CI`V
+MW^]^.,B'GIT<L^NM_%_;@FR3+V1D]^#ZK^EFE;6RWU.K0&I',[;!RV""X/0Z
+M>2*<9B=6"<V<J,EF<W`X9_49N,M5\(4/%1L8E>VM=!PJ06,;-E&'4;.A\G;8
+MUZ\'<\)/3(0*?O#CHSDYO5T10D7$CP,#1>$\MUUP*,=3N$RH_)=Z.+1386!%
+M8#I."+?]H7H]%*3\D+,9S:>=,<FO)GXV-;6(R>Z:_->&;WX1##MU1SWAW;/U
+M:VC:9HC:YJ*B?^'#B>[V9S9<&N*G.(4Q17)#,;R$W[?]_H_)P(E2V_5P<LQ.
+MMR'G7-+Y$NUZ7[IU&]G=VVP[[HZ[E^?["$>%BDJM0US.[JG>9]GIPKXU"WT;
+MDT8$P*%O(?(SI6//.'<@"4\GI.[/(+&UQ#7-V?<1X.;5&'L*7?W>W*7Z&566
+M'V<+]!.)?CY)4OW2VL*G#O'S^<WJ1X=)E8G-7K_#7Q^(D5]I_430C]69?GJB
+MNUT/?QY0A&):K#J+OOJ58:@"8#&&JL_A4@PYSCKSLU[&P+#051>GJ\PY5UV"
+I*WC5Q5"R)JW\W]*K+H:25>BJ2W`%K[H$5_2JBZZ@KMX!;=,CGA\-````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-apm.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-apm.vhdf.gz.uu
new file mode 100644
index 0000000..6096dac
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-apm.vhdf.gz.uu
@@ -0,0 +1,15 @@
+# $FreeBSD$
+begin 644 img-63x255-512-apm.vhdf.gz
+M'XL("/;%'50``VEM9RTV,W@R-34M-3$R+6%P;2YV:&1F+F]U=`"M54UKPD`0
+MO?LK!GH3&I+=R<2>^D'U5I!*SQI,(H&JP0KM(3^^^ZF[211;=AV6#9-]OGEO
+M=Q+'>@!@"BF#6$1L@JOY_-P):*?OD1AQ9$<[TF#)M5V7X:+.:$=C#<AD.HT!
+MB]X^[@(F?J*=OW4!-9SDAPEDL0Q:`Z4W\7MNFL]R`(Z%*E?#\3Z[M%+K!"!C
+MD"'0@YFI`BIEVK!;-OGA6!_K_6YIX5#`42$W9W]AM\V;079I8&_Q1F_1+)@!
+M]+T%RP]#GSU4=I`47A@A`AFD'!"!%8)X*G/BN0<X.Y3ER^+U_F.V</5##,R/
+M;M"/.?KI2^+J!RX_"JT?7=4OXY!E`V?SK-_7MSZ(EE]H_29&OS@?F"\GVGGD
+M_S0@&L!@#,ET9^+FKDL1N>T!$Q>0G>U5@.O]KEP?ZQ_W!I/ISE4U''(_X_);
+M0!FP7+680JX=?G?3S;C>;BR<[7[VCX77)XN[59)?[DP8K"!79W:\+Q)UU!,\
+M>>45;MBMU/SH%HNG8LL*4-.TX3UX"0GWY)NAX53W<U_^K[<:C@(?%?&A'/T"
+(P78/5M('````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-apm.vmdk.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-apm.vmdk.gz.uu
new file mode 100644
index 0000000..89cfd3e
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-apm.vmdk.gz.uu
@@ -0,0 +1,83 @@
+# $FreeBSD$
+begin 644 img-63x255-512-apm.vmdk.gz
+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
+)!]R'M=*37@``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-bsd.qcow.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-bsd.qcow.gz.uu
new file mode 100644
index 0000000..97e3920
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-bsd.qcow.gz.uu
@@ -0,0 +1,126 @@
+# $FreeBSD$
+begin 644 img-63x255-512-bsd.qcow.gz
+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
+"````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-bsd.qcow2.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-bsd.qcow2.gz.uu
new file mode 100644
index 0000000..3663da0
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-bsd.qcow2.gz.uu
@@ -0,0 +1,21 @@
+# $FreeBSD$
+begin 644 img-63x255-512-bsd.qcow2.gz
+M'XL("*P[(U0``VEM9RTV,W@R-34M-3$R+6)S9"YQ8V]W,BYO=70`K9C;DM,P
+M#(;O^Q3F#`N46').'+:PL,QP!S=PW7;;I^CP[*QK)4H4*5XZ:3N9Z;C_-W+\
+M64E:%.GE7.E=J%QHW7'G[K_3!]S@R_CC3K^^_U@/7Z=5@OG"2"D#]:''C5A_
+M&0<6KO#3`:_C!M6A@H,N-07E<,&L;FY`P5VMSJ?NO!B-2.`EP(0S%^.B^B#5
+M)Q/APOI@Z?I0/W]EEY,#U7Q]F.J3J=K"-5D<**G6PFVS.%12.PNWS^*"DKJS
+M<,;.'>!*)74T<#ZCRCVN4E+>PD$65RLIM'`ABVN4E.6=SWO7*BG+.Y_W;JND
+M+.]\WKN=DK*\\WGO]DK*\L[GO;M34I9W8'CG&'=04I9W(+Q[1+C'C#LJ*<L[
+M$-X](=S3'N>UE.4=".^>$>XYXY1^!Y9W(+Q[0;B7C%/Z'5C>@?#N%>&N&*?T
+M.["\`^'=:\*]89S2[\#R#H1W;R?>>:7?@>4="N_>$:M@G-+OT/(.A7>><,`X
+MI=^AY1T*[Y!P@7%*OT/+.Q3>E82K&*?T.[2\0^%=3;B&<4J_0\L[%-ZUA'O/
+M.*7?H>4="N\^$.XCXY1^AY9W*+S[1+AKQBG]#BWO@O!N0[C/C%/Z7;"\"\*[
+M+X2[89S2[X+E71#>?27<MQX'6JKWKBCT#^%N)WL6EKW_#'Q_[)6C/3`#;/X'
+M.%=APK6+3KA,$XX:;)6C/7"Z68_?/?"\PF4=5[6L7`,/K?#/[>_IA,L%5SCA
+M[,=1&N@*[K?@!+<9X.(5[3CXY7`=W=[S]A\2![CKQ.MPLX^C\1[[H`V8DRT7
+ME@4:D1NN<[RUBW?@77<7MV;]^CJN3Y$91M.=J<]-IQNO&OW3G5B/B(/,=-T8
+M%Z\:8E_R$F;.WF9:W7[AQ4"Y,QZX<R-DO',3#I9M!)#^ERKBKZ9'>^#T<SU^
+5)V`@X&)G,%2Q]ZW^`:W<QSE#$P``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-bsd.raw.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-bsd.raw.gz.uu
new file mode 100644
index 0000000..31141a5
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-bsd.raw.gz.uu
@@ -0,0 +1,11 @@
+# $FreeBSD$
+begin 644 img-63x255-512-bsd.raw.gz
+M'XL("/;%'50``VEM9RTV,W@R-34M-3$R+6)S9"YR87<N;W5T`*V4.PZ#,`Q`
+M=T[AN4.4;TD7*E7JWJF=*853Y/!-@!2;$.@0!R(BVT_^X'`^"8"6P-N-/:]P
+M-T:7JT[52),!:&K0!LP9K#?GRT,.1.%>]R?#XF:<V//*X]A*(DX>X6+`:LCA
+MK@BGO')`EEP@KTZ`ZN<#_D:X9GHC3N]%YRO!^RU%-EE3JG:QMW;EA_L,H@>A
+M@-M9)RGPUU]8XKND84B2[DY\D*;;!EQ-[07"R8-T@>+>`8?Z25IX4+TFC:XK
+MW`RUGHP_)S=`Z.1..%GV(I#CS>+_0&^5[GF%>S"Z)J">@<4J6'^L)U9?N.5M
+%L04%````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-bsd.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-bsd.vhd.gz.uu
new file mode 100644
index 0000000..2e7c657
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-bsd.vhd.gz.uu
@@ -0,0 +1,17 @@
+# $FreeBSD$
+begin 644 img-63x255-512-bsd.vhd.gz
+M'XL("/?%'50``VEM9RTV,W@R-34M-3$R+6)S9"YV:&0N;W5T`*V7/6_#(!"&
+M]_R*D[IEL/`98W=IHJCI7*E2.[O$CC+T0TV'#/[QY6R(#W\E;;$)PH)[>(\[
+M$!&B?0!4`JH"58)*J9U)4+>0Y0"FTQ9LZMA^0JT_WDO]?3A%]JD7+2P6W,HW
+M)WM,0)I),L"")E$[:D/M,-'-=K\\O.T=#BW.32P52(340.1@GER<U1'I8?-T
+MWU>7#-5U5NT\505)Q48D7%T4K3A.&BLSGHJ"2C8R7?$^O`Z.\]2EHF?%9(XM
+M*G-V#*?FK'Z#6RYL+-I4,8F1F5J`BB%#:INT<>LP*"953L?/XNM8]O3A1*HH
+M%HQ^GYQV%VVJH!ML%4@2..<N-)1C'S>2*O]:/>7;2=LPBR!2UX&-^_[J=2C@
+M^E0L9M9\.AB3^@K29_:6*$;JZ8YZ$_GO&:@)F&:TW5,%.5Z[@B_;Y['XZHET
+M^>/NT'@)YP3ST\#'K1@N:</145CR@HXA*;MO.8*[,[]UAY-SZBAGRK&.26?3
+MP,FL\YX=CS/$)<0)B)QE-0.>XPN=OMNA#/3<G=$'0W<+PF7^^)CA\(*[X.->
+M[;G,!G<AO+!ZZZ$Z'3@8N_[.N'+G$L3?N2T.PQX$V)PL)@/-J&$]W5$_1O[;
+M`M$>5<'./G1'52B%T@*#*33`,K!"+&>3[;=9J*S"0!=)P@6\2!(NX$62<`$O
+=DH0+>)$D7,"+).&"7B25^8L@Q.('-E=QRWT,````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-bsd.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-bsd.vhdf.gz.uu
new file mode 100644
index 0000000..c102a9f
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-bsd.vhdf.gz.uu
@@ -0,0 +1,14 @@
+# $FreeBSD$
+begin 644 img-63x255-512-bsd.vhdf.gz
+M'XL("/?%'50``VEM9RTV,W@R-34M-3$R+6)S9"YV:&1F+F]U=`"ME#M/PS`0
+M@/?\BI/8.D1^QUUH55%F)"280W"J#L#"P.`?CR^)&U^>",5VHEAW]^4>]C'6
+M#@`E@)43[WF!/^5T^FR7-32!0%V`TJ`-V*#.^D4V1.!?SR]Y.GR'XTM6\[A\
+M,").K.&BP[*>PQT2G`S".M%D/+&J.$C7[]4$[CX\QQZGEKP+F6!N2C`;K-XJ
+M=[&V=F"7UAFX`RZ!V4XF*/!67^C]VX_=$"3<!?]@'&Z)N(+J\P0G5L(%BGM#
+M'"?*?0E7LG<<>U=M7`PYO!E_O+D(H3>WQ8EM&X%H.DLX@4%K_)X7^*><SA:H
+M.N!F&;1=[S,23`W&@='X72@P>RAL"A3T)/GJZ]-5W]>?M,*(XVTSF%QH+R3>
+M%E.`*/$GYAV_$__NSI?=]>,2<;%5Q1\K@TG7`:)&X5H:[N/I^6'HG1PGR9+L
+M<?0S;7LA<)*]0XI3MV"=:UH@[Q?9$,%DJT*<9@.K_]:VQ9F-CTHX?-DO_`G/
+%>S`'````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-bsd.vmdk.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-bsd.vmdk.gz.uu
new file mode 100644
index 0000000..79b142e
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-bsd.vmdk.gz.uu
@@ -0,0 +1,81 @@
+# $FreeBSD$
+begin 644 img-63x255-512-bsd.vmdk.gz
+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
+FSEW3G6T;0;5TEG7X?_OW_A/7;T_;_]:$Q9+PB_\#AU-ESJ!=````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-ebr.qcow.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-ebr.qcow.gz.uu
new file mode 100644
index 0000000..490438a
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-ebr.qcow.gz.uu
@@ -0,0 +1,128 @@
+# $FreeBSD$
+begin 644 img-63x255-512-ebr.qcow.gz
+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
+B$_@[_X5O_WC_\*^[P28-_FDGV-S2=SX_^A\T>1%04*@`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-ebr.qcow2.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-ebr.qcow2.gz.uu
new file mode 100644
index 0000000..dfe95ff
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-ebr.qcow2.gz.uu
@@ -0,0 +1,22 @@
+# $FreeBSD$
+begin 644 img-63x255-512-ebr.qcow2.gz
+M'XL("*X[(U0``VEM9RTV,W@R-34M-3$R+65B<BYQ8V]W,BYO=70`K9C)DM-`
+M#$#O^8IF6`8&"&ZIO;$D,#!4<8,#<'86?T6*;\=.RVY;EMR3E!.7*ZFV7JG=
+M3_*2)/YC3&J-RXPK3;TSS7_:P`S^C#=S^O7]QWKX.:T\S"9*E#"0'WO<B/4O
+MX$##)78Z8&7<(#L4<-!%34$QG%.SFQL0<'>K\ZD[+T;!(O`:H,>IBW%5?N#S
+MXQ'NROQ@Z?Q0/G]I%\<'LOG\T.?'HW(-5T1Q($25&JZ*XE"(VFFX?13GA*B#
+MAE,J=X!+A:A:P=F(*@TN$Z*LAH,H+A>B4,.Y**X0HC3O;-R[4HC2O+-Q[RHA
+M2O/.QKW;"5&:=S;NW5Z(TKRS<>\.0I3F'2C>F8`["E&:=\"\>T*XFX"KA2C-
+M.V#>/27<LQYGI2C-.V#>/2?<BX`3^AUHW@'S[I9P+P-.Z'>@>0?,NU>$NPLX
+MH=^!YATP[UX3[DW`"?T.-.^`>?=VXIT5^AUHWB'S[AVQDH`3^AUJWB'SSA(.
+M`D[H=ZAYA\P[))P+.*'?H>8=,N]2PF4!)_0[U+Q#YEU.N"+@A'Z'FG?(O"L)
+M]S[@A'Z'FG?(O/M`N(\!)_0[U+Q#YMTGPFT"3NAWJ'GGF'=;PGT..*'?.<T[
+MQ[S[0KC[@!/ZG=.\<\R[KX3[UN-`BNJ]2Q)Y(]S#I&9AV?M/%^Z/K;#7!V:`
+MQ27`N0P]KEQTPJFOC<N`=:WEE_K::`YHMBJE'\WF?:;XO0U5,<YO2Y41<(>E
+MIUM?!DQ34U43X.\N/YA-X_+\\F,[W%9E)>SU@=/]>OSM@(5_.Y"W199FIH#'
+M9OCWX8^POL5R#WP>I[\=H($NX;XC3G#;`0Z]?8$R**N1=\/?`]QF'3IS@YM]
+M.]`^\ARE`76RZ;*R%'UOZ6T=K'-[I]T^$'476W:GW*^O"?D)O05&TYW)STRG
+MVU[$^X=MMAXM#B+3-6/<N5$-UG.TA)&SMYEFMU]X,2ROC$=6;@L95Z['P;*-
+EH#QWEL;`YJCI7A\X_5R/OQ[H"+C8&719>^U=_0=D5Z&8TA0`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-ebr.raw.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-ebr.raw.gz.uu
new file mode 100644
index 0000000..ba30800
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-ebr.raw.gz.uu
@@ -0,0 +1,12 @@
+# $FreeBSD$
+begin 644 img-63x255-512-ebr.raw.gz
+M'XL("/C%'50``VEM9RTV,W@R-34M-3$R+65B<BYR87<N;W5T`*V4S0["(`S'
+M[WN*GCTLP(;#RY:8>/>BGG%N3[&'MXQ-6V$?)O`5DL(O_])2(7P#P!D=RX8A
+M_VE#=LA&FGS^#>S[*-#C6KR%!W!8/6UP%#W!M1**+JJO<4M-<:_4[O;_`;4&
+M:P/@;=:G$H>CZIRY5"!L9%TV#.><]QEHQH31%90:]!&,VJOP<;E'XFN$3.6P
+MQZDMW"S89U`,UQ!<X;/O2Y'D%LT[NB>XVL\95ZZIPY<07<RPZ*Q.FRP&.[]'
+MXPRR`UF`,)--<>`GOO#5=PIE*.;NBCX(W;4.5_'SDN#4AKO`<6.A(O%D(=QX
+MO3I4UR8.AOS]&3M_KH/PG^MQ*FTA.(V5!3,03X7KLF&XYKQ[8#D!D[V@JWQ"
+*9&_T+/:\Y08`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-ebr.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-ebr.vhd.gz.uu
new file mode 100644
index 0000000..b0e08ed
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-ebr.vhd.gz.uu
@@ -0,0 +1,18 @@
+# $FreeBSD$
+begin 644 img-63x255-512-ebr.vhd.gz
+M'XL("/C%'50``VEM9RTV,W@R-34M-3$R+65B<BYV:&0N;W5T`*V7P6Z<,!"&
+M[_L4(_66`S*#;<AE(T5-SY&BM&<O@2B'-E&WAQQX^'BPO=B`V6PSP"*OQO/Y
+M'\_8R$*X"T!7H'O0'6A%[5J"OH:Z`;!&_^#X+OU?&-K7/UW[[^6]\->P<[!2
+MQ%ZI._EC!=(.4@,:&D0_41N&@"F^W3U?O?Q^#CCTN#"PU"`1E(7(Q3B-.*DC
+MTH_;A^]S==52W>3EQNE[J/JH1Q6K*XJ;&">ME^U/CX9>CC+#D_Q)##$N4:?$
+MS"N2N3:I4;!K.+WE=0GN:N=SX4K%%D9MWP)T"352VY9-F(?%8TOE_?AF_AZ[
+MF3[,E(J.DC&WR7RXZ$L%0V>O0)+`K7!AI!SGN)52^=+LZ=1/^H:=!*&"`<?P
+MT]F;4!#KTZ78F/-\,K+ZS&9<_Q'PX7`Q,*/0X=I3P$9-$;FUZOW;$JIN5=^X
+M;/<Q[HD[W/XRH%)@S`+X&/2US.EH&C+;O5.8E7?>,-P6Z7T"C@6C:MK.E88&
+M/ZOPU]W/E?PV)K,=7!ZPP^$Y7!`<[_8I[B;"5:[Z)DJT.25U%[<CW-[]`DYN
+MJ:,]H5LS9(-5S,5BFIE?G&<H.R@K$(VW80H\Y1<F?==+&9B$NZ$/EN$:PM5I
+M_S+"X9EP(<4=_'<W]$Q2>&;V]DMU+7,R#O.5\<F52Y!TY3H<\FX$9MQ9;`7:
+M7LMWWC#<%^GM@.@_16S?-O2;*9M"Z8%L"BVP8U9H>+\?VBMD.B@0CO&@0#C&
+A@P+A&`\*A&,\*!".\:!`.-:#@K9'0"%V'P.\AOE=#@``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-ebr.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-ebr.vhdf.gz.uu
new file mode 100644
index 0000000..b865e86
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-ebr.vhdf.gz.uu
@@ -0,0 +1,15 @@
+# $FreeBSD$
+begin 644 img-63x255-512-ebr.vhdf.gz
+M'XL("/C%'50``VEM9RTV,W@R-34M-3$R+65B<BYV:&1F+F]U=`"ME3MOPR`0
+M@/?\BI.Z98@``R:+(T5-YTI5V]EU<)2A[=*A@W]\P1B;,SB/"H,1UL'G>W$0
+MXAX`\R;[LJ#;S)YNM5[U-/IQ-[!MDT"':\PNL\#T6@P3TXLVP#44"IW4;V>'
+M*L0=<YO;W@<4`NHZ`KYZ_5CF<)3:BCD#4B?&94&WW^#F@:I/&%$"%R`D*':K
+MAN^'MT1\%:&Y#'8X=@WG%789E,+M`ESALF^BT&!7F'?A/,!5[O4X?DD[XPFB
+M4X)%8T7>9%&FX7UAG(%JH`40-<@8!H[QA4F_;:P&0^9>T`]B<VN+*_%Z&N#8
+M%7,!X_I"%<03A?"*]ZI8NR9S,.C\9-QX<BT$GUR'8WD+P;:O+"8#S:IX7!9T
+MSQO<')`/P&P>5,/=)@N0+4@-4MAYR4%NH50AD.%,ZIKO+]W\G'_#"%L<':^B
+MN-O]K+"G19;`:OL3>;3S0+^'PVE]_CQYG"]5_L=<6J<+`^&1N0J;^[1_>9QK
+M5\1.4LA[=+HX1\.1]W8ACH_&:MV70#IU]($$R5)E<8+,=OTWM@XG,Z>*N7=7
+)?T_5:9P0"0``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-ebr.vmdk.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-ebr.vmdk.gz.uu
new file mode 100644
index 0000000..869f19c
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-ebr.vmdk.gz.uu
@@ -0,0 +1,84 @@
+# $FreeBSD$
+begin 644 img-63x255-512-ebr.vmdk.gz
+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
+5O$1`LPY>PN\1R;[X/U4+_GL>8```
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-gpt.qcow.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-gpt.qcow.gz.uu
new file mode 100644
index 0000000..4753ee6
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-gpt.qcow.gz.uu
@@ -0,0 +1,132 @@
+# $FreeBSD$
+begin 644 img-63x255-512-gpt.qcow.gz
+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
+7+^+GN4?](MX>AAN9_O;_@'C+'O6L````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-gpt.qcow2.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-gpt.qcow2.gz.uu
new file mode 100644
index 0000000..26ffd0b
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-gpt.qcow2.gz.uu
@@ -0,0 +1,26 @@
+# $FreeBSD$
+begin 644 img-63x255-512-gpt.qcow2.gz
+M'XL("+`[(U0``VEM9RTV,W@R-34M-3$R+6=P="YQ8V]W,BYO=70`K9A+;YPP
+M$(#O^15.WTT:BL<VC[Z3-"OE4B55>VL/+(]3%:EWVM]>C`T&,P/)UKMHE<B:
+M3V/SS=@0Q^;#F.),)DSFK-FS[G][`9O\,[]8>[N[CJ:?]LC`>$Q$(0-2C+@9
+MZ]+A@,+%?#G`<=PD.X'@8(A:@K9PDLQN;0#!G1SU2]??C,R+$(<`#8Z\&0?E
+M!R8_/T(>F!^$SD_@ZZ>&.'\@6<]/F/S\J)3"99LX0*)R"E=LX@02M:=PY29.
+M(E$5A:LW<0J):@@<WU"EPR5(%*=PL(E+D2A!X>0F+D.B*._XMG<Y$D5YQ[>]
+M*Y`HRCN^[=T>B:*\X]O>E4@4Y1W?]JY"HBCO@/"..5R-1%'>@>?=L<4]<K@&
+MB:*\`\^[QQ;W9,1Q+(KR#CSOGEK<,X=#^AU0WH'GW7.+>^%P2+\#RCOPO'MI
+M<2<.A_0[H+P#S[M3BWOE<$B_`\H[\+P[6WC'D7X'E'?"\^ZU9<4.A_0[07DG
+M/.^XQ8'#(?U.4-X)SSMA<=+AD'XG*.^$YYVRN,3AD'XG*.^$YUUJ<9G#(?U.
+M4-X)S[O<XMXX'-+O!.6=\+Q[:W'O'`[I=X+R3GC>O;>X#PZ']#M!>2<][SY:
+MW">'0_J=I+R3GG?G%G?A<$B_DY1WTO/NTN(^CSC`HD;OXAB_+.YJ4;.`]#N9
+MW!.W6^+HAY5#CK/2';<Y\DL/K`"SAP/)O5::<TJX"2LS86U5@?S2`^U%-/^.
+MP+YV'P`<,ISC[(25J5WSP%C7K&GL95;*!F>3`P(RX>-H@JL"KU]?;@\`*L6*
+M8@'\/N37EUM77^;=0&>WZIN!`J;DB.OGJLII?E>[:W9S_O6;AOUPT^W+3>-J
+M_;!4)%YVG)KNU1?$/F7*+6W\U1YP@L*-QS(/IX\7:;6"PR[6_B%P<BUJ?.EP
+MCWMK<"J>1TW;%LL4RX`E):L*$O=KADL"FR?U\#YA:<F26K]/*AO]1Y7HIS26
+M=65BMFWHSU@Y2[D^NW7`]NXVNC.PL^CWJ<U/<FL$=M$#U.I)6#-")[4Q73;'
+M8:^1_FOU=%_>JV"KEUM9L(L>(%>O,*N'+Y)."BV9=EBUH>`&W#[PZB5ZN*N/
+MKG\O?^F!]B::?PU06F"P#&72E`&K0^,"5H?&!:P.C0M:'1H8L#HT+F!U:%S`
+MZM"XH-71`>LXW":N<=J]/&.J8KED335/@]R.V^@G.MT:UK;^E4T<OQEUP$U<
+BXU8W\;0F)VL_?[W)!MS$-2[H)BY3??P^^@=.=Z`2%1H`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-gpt.raw.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-gpt.raw.gz.uu
new file mode 100644
index 0000000..2a259cb
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-gpt.raw.gz.uu
@@ -0,0 +1,15 @@
+# $FreeBSD$
+begin 644 img-63x255-512-gpt.raw.gz
+M'XL("/G%'50``VEM9RTV,W@R-34M-3$R+6=P="YR87<N;W5T`*V534_#,`R&
+M[_L5WA5$E*1)FIWXD$#B-A#<N/1C/:%)W,M_)VX:UG9Q89+3J*KD^JGM^*VE
+MC`O`:)!5YDX;^@<QO_K-U6:@J?HR8/@^AK``B@",N"88I<9W#@?HNG%+-7A%
+M9VE!J_0\XL1I;<4$UYZ\SC9MF.)$Q*5TN\N`UD)5G0'?4WQZ.`X+QH'9@0[O
+M2S`*K`9K?G%#KK:9QO?X]`S[^]<WA'V<TM4J&%4#1D)30MLMHE-DNG?+="-.
+MHY=95COA"A*WS>.*>+8T+K=IG%GSBCWTO[.-."OG7G[JY2UX#:Z!MB)QGS.<
+M8^X\@^;:0=F`.X!5T'3XT#I0*L079.('2*AO"W('I0)=([`_OHACA-V(K^LQ
+M/J/&CLAMVD!5S^BUCL"@_D@7YKB"NWH>JV?9JK<;FR6W:0-9O2I6+U\D4C)]
+MJEI22,+5S-5S:`[Z"/_O\SMMZ/=B?D6@&8%L$8;F<XSJ0!RC.A#'J`[$L:H#
+M@8SJ0!RC.A#'J`[$L:HC`+WD&^*(&X:X@;*%MH!B.<2I<=R+;W&;2=?KM=&_
+F,L3SA^$9ASCBUH=X02:;UB)9QB&..-8A'H"5E)L?B^NWCH@+````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-gpt.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-gpt.vhd.gz.uu
new file mode 100644
index 0000000..0473ed9
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-gpt.vhd.gz.uu
@@ -0,0 +1,22 @@
+# $FreeBSD$
+begin 644 img-63x255-512-gpt.vhd.gz
+M'XL("/G%'50``VEM9RTV,W@R-34M-3$R+6=P="YV:&0N;W5T`*U82V^<,!"^
+MYU=,U5NJ4F-LPYZJ1DVDWM)';CT$#$0KM=M'<LB!'U^/L1<,-NDFPUI>D)F/
+M;YX>F;'Q`E`%J!Y4!TKB?2E`[:"L`,RB&]S.N7N$0?\Z=/IA_YBY:S@;P7(V
+MEPK%49X7(,Q'2N`U?D2U>`^#A\E>7]Z=[W_>>3CNX/R'A0+!01H0L?J.8D=V
+MB'1U\?6CA;R=V!5K=I/4^-?W4/2S-PK/[M;.[^?*"B-EWL=1`I/`Q#2"AV!A
+M4G9A.\D64C.:,:/.E(W!J2VI4^#.SYPOQE`Q@5&:V9@NAY+CO0D;;X?5,*'R
+M>/^[_GO?+?CQ1*BH([]\M5:DU>4N5+A_V3$0&,Y;ZH)%>5C"14+E1=93H9SW
+MKC&""1SWP*WZH?4F*)CS4SG;L'G:&4E^-?(SN<7JR)Q>&"ZR\'<$;)K3`+T%
+M0[BCPHU&^]DZTG631F.03(8M-AS"9O9K6F+_-OUI@%)"7:\`;SP_;=TA;<';
+M86"8XB!RD*;X3>%L=9=ZSN_RZA-<?_CR#<&^3^IJ#)>NQ0PR5;=O%^S6F794
+M=Q]+-LW'Z.-]5-DB"?<NFKL:D\V02L/%1AI.;$FYK>S_"ZF6+)2JYE*5A(J#
+MTM#62;@?`1QU7>YPN5%0:MS"90[:[N6M@CPW_$R:5!:$`S=^-QN[V84;!!P.
+MG[/#"/8V^_/&\>MR%Q&QD5Y(6:_C6Q&!I)Y0%T(XZKK<56@]26:]G0N6V$@O
+M)*U7C]:+&PE)Q5+WN*MEV:L0KJ&U7F[;1Y,?IGZOY_3"<)V%OQ&0NVV(;%_C
+MKI"2,10.D(RA</E+R#`7F\X\U<O*.86HPB`<885!.,(*@W"D%08!"2L,PA%6
+M&(0CK#`(1UIA%&TCI%PCQ$KK@`*:+J21;&D&[PC?<G@XOM4^;31"<6=0-D+J
+MJ4:H[Y+*^FNA+&$CI*@;(>4**=%9AO*-T)K#<\XRE&^$9A]^P5F&BC="SSW+
+:0#C"LPR$(SS+0#CB4,&^Y>P?_R=O5``3````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-gpt.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-gpt.vhdf.gz.uu
new file mode 100644
index 0000000..b9a9b8a
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-gpt.vhdf.gz.uu
@@ -0,0 +1,19 @@
+# $FreeBSD$
+begin 644 img-63x255-512-gpt.vhdf.gz
+M'XL("/G%'50``VEM9RTV,W@R-34M-3$R+6=P="YV:&1F+F]U=`"METUOU#`0
+MAN_[*P9Q*R+8CNUD3XB*5N)6/GKCT'S8U4JP"(D#A_QX9NRDL;-VH,B)%7DU
+M\9-YQS.9+&/^`)`"6)>XY@W3=16?T^'JX&B\?QX0GT\N;(`5`CUN0",3=(\Q
+M8.T\&'>K_&(<-5OG#E>M!ZL"W!BNVHR\(<15'K?(M<\#*@5==P&\7_P3;CL4
+M2`WR"`+O9R`Y*`%*/N&<=C6$_MW<?H"[=Y^^$.SK*E=P-)H16`WZ"';<>,?S
+M<D\;N1Z'#E'TA4V*K;.X-]OH>5Q-N'$'EQIYG-Q;Y7/HW_;6XQ2+5[7AJE9!
+M*T`/,'99W+<(IPMGGB1SKZ$90!M0'`9+DU$#Y^@?EDGK(`($[OL1&@ZB)^!T
+M_EB=/>QU]?/5[)_D<T:D1MZ0BYX4>QE!3OU%+L2XNG3T6HJ>*A:]XYPLJ9$W
+M9*/7^>BE@T1.I4H7<7/4JA<QKB\</4UFK`]\?U]>\X;IKHI/#Y0SL)B'RMJA
+M8'40KF!U$*Y@=1"N:'40L&!U$*Y@=1"N8'40KFAU(-"P<DV<<"[W&K<!-?0F
+M=B/;CJ=E(Y9VN>#$7NO?:>+IS3`%FSCA=INX-5FQR[$16[")$ZYH$]?SY[?&
+MKS-77UK1O)'TL=:T(5"L.>.`PX^S&7Z=?H?1(QSW&9$<M%[4E)BZ`='10_1(
+M\\"_ES>/5Z?OCPM.S*J6!U-&8Q8C1%[(U;'<V^O/[QWR8?4N\9K2F^BAG[6-
+MA,_>/;CKVU"L?!)K+*!R)M<1_8@,R40FG$N5\.;_W5N/*YTJ^-?@\`>4./-P
+$LPT`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-gpt.vmdk.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-gpt.vmdk.gz.uu
new file mode 100644
index 0000000..ea3a546
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-gpt.vmdk.gz.uu
@@ -0,0 +1,88 @@
+# $FreeBSD$
+begin 644 img-63x255-512-gpt.vmdk.gz
+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
+%E+1E````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-mbr.qcow.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-mbr.qcow.gz.uu
new file mode 100644
index 0000000..2abc3ee
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-mbr.qcow.gz.uu
@@ -0,0 +1,128 @@
+# $FreeBSD$
+begin 644 img-63x255-512-mbr.qcow.gz
+M'XL("+PS(E0``VEM9RTV,W@R-34M-3$R+6UB<BYQ8V]W+F]U=`"MG<EN7%>R
+M1>?^BE0O45U&Q&W5D$0!KX":U1N\JJEO.\X/$.K;BQ9/0\;=6R$_2R8,"O3=
+MR#Q<6C+LA:/S^?['Z=3*J>E.S7C:Y]/=S].'G![\Y/''Z=O__OT?'Q[^^/;;
+M_9B<?_"4^WF_E;E'6_^I<_K'4\OI//[$W-V'H+D'K\[^Q*M[\&:/<U>_W;]9
+M_)RR07LT>$ISY_3ZA)Q>\W.O[]:]7;D_O5_W=I6\W?;G!O_I7I_^*5A^ZO7]
+MR>]O!P=_+Z^O@4_U;&YX-'<YO-T6/C6RN>F',.NY@T_-;&X)YGKXU,KFMF!N
+M@$_M>$Y^\+V]GQOA4\+F%,Z=RMP$GS(VUSR:.Z>YVS(WPZ?(KPMQW.5?%Y6[
+M!3Y%N).0NQ4^1;B3D+L-/D6XDY"['3Y%N).(.\%/$>XTXDZ0HI1QIQ%W@HRL
+MC#N-N!/D.V7<:<2=(-\IXTXC[@3Y3AEW&G$GR'?*N-.(.T&^4\:=AMPAWRGC
+MSD+ND.^,<6<A=\AWQKBSD#OD.V/<6<@=\ITQ[BSD#OG.&'<6<H=\9XP["[E#
+MOC/&G47<*7Z*<-=$W"GR7<.X:R+N%/FN8=PU$7>*?-<P[IJ(.T6^:QAW3<2=
+M(M\UC+LFXDZ1[QK&71-QI\AW#>.N";E#OFL8=VW('?)=R[AK0^Z0[UK&71MR
+MAWS7,N[:D#ODNY9QUX;<(=^UC+LVY`[YKF7<M2%WR'<MXZZ-N#/\%.&NB[@S
+MY+N.<==%W!GR7<>XZR+N#/FN8]QU$7>&?-<Q[KJ(.T.^ZQAW7<2=(=]UC+LN
+MXLZ0[SK&71=RAWS7,>[ZD#ODNYYQUX?<(=_UC+L^Y`[YKF?<]2%WR'<]XZX/
+MN4.^ZQEW?<@=\EW/N.M#[I#O>L9='W'7X*<(=T/$78-\-S#NAHB[!OEN8-P-
+M$7<-\MW`N!LB[AKDNX%Q-T3<-<AW`^-NB+AKD.\&QMT0<=<@WPV,NR'D#OEN
+M8-SE_SS/YY#O1L;=&'*'?#<R[L:0.^2[D7$WAMPAWXV,NS'D#OEN9-R-(7?(
+M=R/C;@RY0[X;&7=CQ%V+GR+<31%W+?+=Q+B;(NY:Y+N)<3=%W+7(=Q/C;HJX
+M:Y'O)L;=%''7(M]-C+LIXJY%OIL8=U/$78M\-S'NII`[Y+N)<9?_-RF?0[Z;
+M&7=SR!WRW<RXFT/ND.]FQMT<<H=\-S/NYI`[Y+N9<3>'W"'?S8R[.>0.^6YF
+MW,T1=QU^BG"W1-QUR'<+XVZ)N.N0[Q;&W1)QUR'?+8R[)>*N0[Y;&'=+Q%V'
+M?+<P[I:(NP[Y;F'<+1%W'?+=PKA;0NZ0[Q;&W1IRAWRW,N[6D#ODNY5QMX;<
+M(=^MC+LUY`[Y;F7<K2%WR'<KXVX-N4.^6QEW:\@=\MW*N%LC[GK\%.&.!$(/
+MYI#O-L;=%G'7(]]MC+LMXJY'OML8=UO$78]\MS'NMHB['OEN8]QM$7<]\MW&
+MN-LB[GKDNXUQMX7<(=]MC+L]Y`[Y;F?<[2%WR'<[XVX/N4.^VQEW>\@=\MW.
+MN-M#[I#O=L;='G*'?+<S[O:0.^2[G7&W1]P-^"G,G>1/^!SPG9P)=W*.N!N`
+M[^1,N)-SQ-T`?">L#Q3?WQVX&X#OA/5W$O9W`_"=L/Y.POYN`+X3UM])V-\-
+MP'?"^CL)^[L!^$Y8?R=A?S<`WPGK[R3L[P;@.V']G83]W0!\)ZR_D["_&X#O
+MA/5W$O9W`_"=L/Y.POYN`+X3UM])V-\-P'?"^CL)^[L1/T6X"_N[$?F.]7<2
+M]G<C\AWK[R3L[T;D.];?2=C?C<AWK+^3L+\;D>]8?R=A?S<BW['^3L+^;D2^
+M8_V=A/W=B'S'^CL)^[L1^8[U=Q+V=R/R'>OO).SO1N0[UM])V-^-R'>LOY.P
+MOQN1[UA_)V%_-R+?L?Y.POYN1+YC_9V$_=V$GR+<A?W=A'S'^CL)^[L)^8[U
+M=Q+V=Q/R'>OO).SO)N0[UM])V-]-R'>LOY.POYN0[UA_)V%_-R'?L?Y.POYN
+M0KYC_9V$_=V$?,?Z.PG[NPGYCO5W$O9W$_(=Z^\D[.\FY#O6WTG8WTW(=ZR_
+MD["_FY#O6'\G87\W(=^Q_D["_F[&3Q'NPOYN1KYC_9V$_=V,?,?Z.PG[NQGY
+MCO5W$O9W,_(=Z^\D[.]FY#O6WTG8W\W(=ZR_D["_FY'O6'\G87\W(]^Q_D["
+M_FY&OF/]G83]W8Q\Q_H["?N[&?F.]7<2]G<S\AWK[R3L[V;D.];?2=C?S<AW
+MK+^3L+^;D>]8?R=A?[?@IPAW87^W(-^Q_D["_FY!OF/]G83]W8)\Q_H["?N[
+M!?F.]7<2]G<+\AWK[R3L[Q;D.];?2=C?+<AWK+^3L+];D.]8?R=A?[<@W['^
+M3L+^;D&^8_V=A/W=@GS'^CL)^[L%^8[U=Q+V=POR'>OO).SO%N0[UM])V-\M
+MR'>LOY.POUOQ4X2[L+];D>]8?R=A?[<BW['^3L+^;D6^8_V=A/W=BGS'^CL)
+M^[L5^8[U=Q+V=ROR'>OO).SO5N0[UM])V-^MR'>LOY.POUN1[UA_)V%_MR+?
+ML?Y.POYN1;YC_9V$_=V*?,?Z.PG[NQ7YCO5W$O9W*_(=Z^\D[.]6Y#O6WTG8
+MWVWX*<)=V-]MR'>LOY.PO]N0[UA_)V%_MR'?L?Y.POYN0[YC_9V$_=V&?,?Z
+M.PG[NPWYCO5W$O9W&_(=Z^\D[.\VY#O6WTG8WVW(=ZR_D["_VY#O6'\G87^W
+M(=^Q_D["_FY#OF/]G83]W89\Q_H["?N[#?F.]7<2]G<;\AWK[R3L[W;\%.$N
+M[.]VY#O6WTG8W^W(=ZR_D["_VY'O6'\G87^W(]^Q_D["_FY'OF/]G83]W8Y\
+MQ_H["?N['?F.]7<2]G<[\AWK[R3L[W;D.];?2=C?[<AWK+^3L+_;D>]8?R=A
+M?[<CW['^3L+^;D>^8_V=A/W=CGS'^CL)^[L=^8[U=Q+U=W;&3V'N-'_BYDYU
+M#OCN[BG,G;K^+M_W=SJ5.>`[9?V=NO[NE+@[W98YX#ME_9VZ_NZ4N#O]7N:`
+M[Y3U=^KZN]/E<';`=\KZ.W7]73F[.@=\IZR_4]??@3G@.V7]G;K^#LP!WRGK
+M[]3U=WGN29T#OE/6WZGK[Y[DN<H=\)VR_DY=?_<D<?>D<@=\IZR_4]??/4G<
+M/:G<`=\IZ^_4]7=/+H>S`[Y3UM^IZ^_*V=4YX#ME_9VZ_@[,`=\IZ^_4]7?'
+M.73_G;+^3EU_E^>>UCGD.];?J>OOGN:YPAVZ_TY9?Z>NOWN:N'M:N$/WWRGK
+M[]3U=T\3=T\+=^C^.V7]G;K^[NGE<';(=ZR_4]??E;.K<\AWK+]3U]^!.>0[
+MUM^IZ^_`'/(=Z^_4]7=Y[EF=0[YC_9VZ_NY9GJO<(=^Q_DY=?_<L<?>L<H=\
+MQ_H[=?W=L\3=L\H=\AWK[]3U=\\NA[-#OF/]G;K^KIQ=G4.^8_V=NOX.S"'?
+ML?Y.77]WG$/WWRGK[]3U=WGN>9U#OF/]G;K^[GF>*]RA^^^4]7?J^KOGB;OG
+MA3MT_YVR_DY=?_<\<?>\<(?NOU/6WZGK[YY?#F>'?,?Z.W7]73F[.H=\Q_H[
+M=?T=F$.^8_V=NOX.S"'?L?Y.77^7YU[4.>0[UM^IZ^]>Y+G*'?(=Z^_4]7<O
+M$G<O*G?(=ZR_4]??O4C<O:C<(=^Q_DY=?_?B<C@[Y#O6WZGK[\K9U3GD.];?
+MJ>OOP!SR'>OOU/5WQSET_YVR_DY=?Y?G7M8YY#O6WZGK[U[FN<(=NO].67^G
+MKK][F;A[6;A#]]\IZ^_4]7<O$W<O"W?H_CME_9VZ_N[EY7!VR'>LOU/7WY6S
+MJW/(=ZR_4]??@3GD.];?J>OOP!SR'>OOU/5W>>Y5G4.^8_V=NO[N59ZKW"'?
+ML?Y.77_W*G'WJG*'?,?Z.W7]W:O$W:O*'?(=Z^_4]7>O+H>S0[YC_9VZ_JZ<
+M79U#OF/]G;K^#LPAW['^3EU_=YQ#]]\IZ^_4]7=Y[G6=0[YC_9VZ_NYUGBO<
+MH?OOE/5WZOJ[UXF[UX4[=/^=LOY.77_W.G'WNG"'[K]3UM^IZ^]>7PYGAWS'
+M^CMU_5TYNSJ'?,?Z.W7]'9A#OF/]G;K^#LPAW['^3EU_E^?>U#GD.];?J>OO
+MWN2YRAWR'>OOU/5W;Q)W;RIWR'>LOU/7W[U)W+VIW"'?L?Y.77_WYG(X.^0[
+MUM^IZ^_*V=4YY#O6WZGK[\`<\AWK[]3U=\<Y=/^=LOY.77^7YZ[J'/(=Z^_4
+M]7=7>:YPA^Z_4];?J>OOKA)W5X4[=/^=LOY.77]WE;B[*MRA^^^4]7?J^KNK
+MR^'LD.]8?Z>NORMG5^>0[UA_IZZ_`W/(=ZR_4]??@3GD.];?J>OO\MS;.H=\
+MQ_H[=?W=VSQ7N4.^8_V=NO[N;>+N;>4.^8[U=^KZN[>)N[>5.^0[UM^IZ^_>
+M7@YGAWS'^CMU_5TYNSJ'?,?Z.W7]'9A#OF/]G;K^[CB'[K]3UM^IZ^_RW+LZ
+MAWS'^CMU_=V[/%>X0_??*>OOU/5W[Q)W[PIWZ/X[9?V=NO[N7>+N7>$.W7^G
+MK+]3U]^]NQS.#OF.]7?J^KMR=G4.^8[U=^KZ.S"'?,?Z.W7]'9A#OF/]G;K^
+M+L^]KW/(=ZR_4]??O<]SE3OD.];?J>OOWB?NWE?ND.]8?Z>NOWN?N'M?N4.^
+M8_V=NO[N_>5P=LAWK+]3U]^5LZMSR'>LOU/7WX$YY#O6WZGK[XYSZ/X[9?V=
+MNOXNSWVH<\AWK+_3J+\S=/^=LOY.H_[.T/UWROH[C?H[0_??*>OO-.KO#-U_
+MIZR_TZB_,W3_G;+^3J/^SM#]=\KZ.XWZ.T/WWRGK[Y3T=Q_K'/(=Z^_4]7<?
+M\USE#OF.]7?J^KN/B;N/E3OD.];?J>OO/B;N/E;ND.]8?Z>NO_MX.9P=\AWK
+M[]3U=^7LZASR'>OOU/5W8`[YCO5WZOJ[XQRZ_TY9?V?Y$S=WKG/`=\;ZN[LO
+M/.(N^^E<N$/WWQGK[\SU=^>T=R[<H?OOC/5WYOJ[<^+N7+A#]]\9Z^_,]7?G
+MR^'L@.^,]7?F^KMR=G4.^,Y8?V>NOP-SP'?&^CMS_1V8`[XSUM^9Z^_RG-0Y
+MX#MC_9VY_D[R7.4.^,Y8?V>NOY/T\J1R!WQGK+\SU]])XDXJ=\!WQOH[<_V=
+M7`YG!WQGK+\SU]^5LZMSP'?&^CMS_1V8`[XSUM^9Z^^.<^C^.V/]G;G^+L]I
+MG4.^8_V=N?Y.\USA#MU_9ZR_,]??:>)."W?H_CMC_9VY_DX3=UJX0_??&>OO
+MS/5W>CF<'?(=Z^_,]7?E[.H<\AWK[\SU=V`.^8[U=^;Z.S"'?,?Z.W/]79ZS
+M.H=\Q_H[<_V=Y;G*'?(=Z^_,]7>6N+/*'?(=Z^_,]7>6N+/*'?(=Z^_,]7=V
+M.9P=\AWK[\SU=^7LZASR'>OOS/5W8`[YCO5WYOJ[XQRZ_\Y8?V>NO\MS39U#
+MOF/]G;G^KLESA3MT_YVQ_LY<?]<D[IK"';K_SEA_9ZZ_:Q)W3>$.W7]GK+\S
+MU]\UE\/9(=^Q_LY<?U?.KLXAW['^SEQ_!^:0[UA_9ZZ_`W/(=ZR_,]??Y;FV
+MSB'?L?[.7'_7YKG*'?(=Z^_,]7=MXJZMW"'?L?[.7'_7)N[:RAWR'>OOS/5W
+M[>5P=LAWK+\SU]^5LZMSR'>LOS/7WX$YY#O6WYGK[XYSZ/X[8_V=N?XNSW5U
+M#OF.]7?F^KLNSQ7NT/UWQOH[<_U=E[CK"G?H_CMC_9VY_JY+W'6%.W3_G;'^
+MSEQ_UUT.9X=\Q_H[<_U=.;LZAWS'^CMS_1V80[YC_9VY_@[,(=^Q_LY<?Y?G
+M^CJ'?,?Z.W/]79_G*G?(=ZR_,]??]8F[OG*'?,?Z.W/]79^XZRMWR'>LOS/7
+MW_67P]DAW['^SEQ_5\ZNSB'?L?[.7'\'YI#O6']GKK\[SJ'[[XSU=^;ZNSPW
+MU#GD.];?F>OOACQ7N$/WWQGK[\SU=T/B;BC<H?OOC/5WYOJ[(7$W%.[0_7?&
+M^CMS_=UP.9P=\AWK[\SU=^7LZASR'>OOS/5W8`[YCO5WYOH[,(=\Q_H[<_U=
+MGAOK'/(=Z^_,]7=CGJO<(=^Q_LY<?S<F[L;*'?(=Z^_,]7=CXFZLW"'?L?[.
+M7'\W7@YGAWS'^CMS_5TYNSJ'?,?Z.W/]'9A#OF/]G;G^[CB'[K\SUM^9Z^_R
+MW*<ZAWS'^CMS_=VG/%>X0_??&>OOS/5WGQ)WGPIWZ/X[8_V=N?[N4^+N4^$.
+MW7]GK+\SU]]]NAS.#OF.]7?F^KMR=G4.^8[U=^;Z.S"'?,?Z.W/]'9A#OF/]
+MG;G^+L]]KG/(=ZR_,]???<YSE3OD.];?F>OO/B?N/E?ND.]8?V>NO_N<N/M<
+MN4.^8_V=N?[N\^5P=LAWK+\SU]^5LZMSR'>LOS/7WX$YY#O6WYGK[XYSZ/X[
+M8_V=N?XNSWVI<\AWK+\SU]]]R7.%.W3_G;'^SEQ_]R5Q]Z5PA^Z_,];?F>OO
+MOB3NOA3NT/UWQOH[<_W=E\OA[)#O6']GKK\K9U?GD.]8?V>NOP-SR'>LOS/7
+MWX$YY#O6WYGK[_+<USJ'?,?Z.W/]W=<\5[E#OF/]G;G^[FOB[FOE#OF.]7?F
+M^KNOB;NOE3OD.];?F>OOOEX.9X=\Q_H[<_U=.;LZAWS'^CMS_1V80[YC_9VY
+M_NXXA^Z_,];?F>OO\MQUG4.^8_V=N?[N.L\5[M#]=\;Z.W/]W77B[KIPA^Z_
+M,];?F>OOKA-WUX4[=/^=L?[.7']W?3F<'?(=Z^_,]7?E[.H<\AWK[\SU=V`.
+M^8[U=^;Z.S"'?,?Z.W/]79Z[J7/(=ZR_,]??W>2YRAWR'>OOS/5W-XF[F\H=
+M\AWK[\SU=S>)NYO*'?(=Z^_,]7<WE\/9(=^Q_LY<?U?.KLXAW['^SEQ_!^:0
+M[UA_9ZZ_.\PU9_P4YJ[)G[BYVSH'?->P_JYQ_=UMGCN5.>"[NZ<P=XWK[VX3
+M=[>W90[XKF']7>/ZN]O$W>WO90[XKF']7>/ZN]O+X>S0G[==3IQ^X=L']^/;
+M;U??!]OOW]M&3^<)_)U_X=O?/CS^JPQ^O]?H3PS>O>%]/PSF-]Q^O]?H[A^X
+M^YC:],G=Q[W=TMM;I/XN^_@-WQ3SY3GTYT;_E?-#5Q']:+!M3]-T&/R__/K0
+M541_Y?5UVR_^_O;?@6G[4].>VNXTZ,^^PG__S[_<*[R?`S+X_[WA^SD@@\=S
+M^067WQ\/<S</YNR>OKHB#YYZR-W#SQ_,77]X\!MXCV10Y_X0X(:^0-_L+Y9!
+M?[AP\N'W^?N=S'8ZY_\_XRXZ+=_?4WU]*/!_]'9_\/I.Q[?[_5\P^L?_O#R8
+MT^#MGA[/??\7C`??ST??PN#TKH^O#OT!]W_EFW&X-O$G?^7^,?+X5^[]G/Y:
+J$0S?S?+';XL3^#O_PK=_?GC\U_U@DP9_V0DV=_2=S[_]%X1YCWBAJ```
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-mbr.qcow2.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-mbr.qcow2.gz.uu
new file mode 100644
index 0000000..bb82f75
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-mbr.qcow2.gz.uu
@@ -0,0 +1,23 @@
+# $FreeBSD$
+begin 644 img-63x255-512-mbr.qcow2.gz
+M'XL("+([(U0``VEM9RTV,W@R-34M-3$R+6UB<BYQ8V]W,BYO=70`K9C;DM,P
+M#$#?]RO,'18HL>2D"9<6%I89WN`!>$YO7]'AVTEJ-4H4*=YVTF8R[;@Z(]M'
+M:I(LBR_G<N]"X4+E#AO7?*<#7._+\'#'7]]_+/JOXTV$^<R(4@:6^PXW8/UC
+M'%BXS(\'O([K98<*#LY18U`*%\SLI@84W.W-:>E.FU&*"+P&&''F9ER5'\3\
+M9$2X,C^8.S_4UR\_Q\F!8CH_C/G)J*6%*Y,X4*(J"U<G<:A$;2S<-HD+2M3.
+MPAF5V\/E2M3!P/F$*@VN4**\A8,D;JE$H84+25RI1%G>^;1WE1)E>>?3WM5*
+ME.6=3WNW4:(L[WS:NZT297GGT][ME"C+.S"\<XS;*U&6=R"\>T2XQXP[*%&6
+M=R"\>T*XIQW.:U&6=R"\>T:XYXQ3^AU8WH'P[@7A7C).Z7=@>0?"NU>$NV6<
+MTN_`\@Z$=Z\)]X9Q2K\#RSL0WKT=>>>5?@>6=RB\>T>LC'%*OT/+.Q3>><(!
+MXY1^AY9W*+Q#P@7&*?T.+>]0>)<3KF"<TN_0\@Z%=TO"E8Q3^AU:WJ'PKB+<
+M>\8I_0XM[U!X]X%P'QFG]#NTO$/AW2?"K1BG]#NTO`O"NS7A/C-.Z7?!\BX(
+M[[X0[HYQ2K\+EG=!>/>5<-\Z'&A1G7=9IA^$NQ_5+,Q[_1GX^M@K9WM@`EA>
+M`IS*,.*J62><QPFW&M3*V1XXWBV&[PYX*K8+@,WZ'`XC($TXC\76_*`YZIP^
+M-$<L$)K>UG.9#2>\IE)CW&[F]3O5QP7`/'=U/0+^/N<'DVE<GM]R/_/^EO%Q
+MP[*MVKQP)3PTP[_W?\9"-[C9*CCB[,<--'!.N&NQ(]RZA\-H'U-Z=3KPKO^Y
+MAULMN-4WN,G'#>T]U%X;,">;SRM+V36KSM;>/K>7[NT=UOG?6UQZ=_OK.#^E
+M6<%@NA/YN?%TVZN"[NY=[$>+@\1TW1#7-JK^?@ZV,+%ZJW%VVYDWP\O*>&#E
+MMI!AY48<S-L(JE-G:0QL?C4^VP/'GXOA.P(#`6=;P5"T_VTW_P%@RS(](Q4`
+!````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-mbr.raw.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-mbr.raw.gz.uu
new file mode 100644
index 0000000..894b95d
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-mbr.raw.gz.uu
@@ -0,0 +1,12 @@
+# $FreeBSD$
+begin 644 img-63x255-512-mbr.raw.gz
+M'XL("/K%'50``VEM9RTV,W@R-34M-3$R+6UB<BYR87<N;W5T`*V4O8[#(`S'
+M]SR%YPX(2&CHDDJ5;K^E[<SEDJ?(P]?$I#$E'XT$&(1D^.EO;)"2&D"E0;J%
+M>=TQW$3<A^)4C#3U=PQH)?1]`A0()%R+.-R`YDQ8H)4]>.$XT%H%91?69#"(
+ML5W]U`B&^W^?2FW=$7!SF\/MCP&-`><2X'W2IS=E'-=7=YGS:\>",354!LP9
+MK/Y6X?/G\:&0<"I7P(33>[A),%70$N[*<"55WTQ1[!2O.[YFN(;&A*NVU.%-
+MR&[)L1JLR5LL%GM\CN<95`>J!&F#3\?`=WYAUG=)9>@HW`U]D(;K/*Z.]RN&
+MTSOA0HSS'Q7/9Y3"G=MK4G5MYF2HSY?QY<OUD/CE$D[G_0@NX\^"%8B[TGG=
+8,?R*N!.P"L!L-^A_/BF+%Y?\>![E!@``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-mbr.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-mbr.vhd.gz.uu
new file mode 100644
index 0000000..53ce054
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-mbr.vhd.gz.uu
@@ -0,0 +1,18 @@
+# $FreeBSD$
+begin 644 img-63x255-512-mbr.vhd.gz
+M'XL("/K%'50``VEM9RTV,W@R-34M-3$R+6UB<BYV:&0N;W5T`*V736_C(!"&
+M[_D5(^VM!PN/`=-+*E6;/5>JVIZQ:T<][+;:["$'__@R!FSP5YHMMF,1P3R\
+MPPQCP9B]`&0!L@79@!34+CG(6R@5@.ET#_;OW/V%KG[_T]3_WLZ9N[J=A>4L
+MM(K-R1X+X&:2$E#3)/*5VM!Y3/;C<+QY^WWT.'0X/S&7P!&$@?#9/(H-ZHCT
+MZ_[QYU1=,5<W6MEYVA:*-AA1A.JR["[$<6-EQM,CH>6]3/]$?Z*.$!>I$VQB
+M%<A<6M3`V26<W+*Z!G>S<[&PJ6(2HS1O!C*'$JEMTL:OP^PQJ7(^?>B_IV:B
+M#U=210;!F/;Q=7?1I0KZP4X!)X%;[D)/.4UQ"ZGRK=63L1UW#;,(3/@.[-V/
+M5V]$0:A/YFQCS=>#L:I/DSZSMYA>>*]W=/=9?`_`JKH.J)A5&.,&AZMZ<%B+
+MT2.[5]WZU3D4S6)`^FV[#]:O>DT<WZJ]#B@$:#T#/GE]]::,Z_4IE3B^JD\8
+M45(Y%Q(4?E7AR^%Y8?\JO5(._J_Z*8V7<%YP6.UCW%V`*VSVC92@.$5Y%[8#
+MW-[^/(YOJ:.:T"QUK#HK$B>+5A.[,,Z0-Y`7P)3KPQ@XQ!=&?;=S&1BYNZ$/
+MYNYJPI7Q^#S`X05W(<95[KOK1T8AO+!Z^[FZ.G$PJNG.^.+.)4B\<RT.TQ8"
+MW5<6DX%FU/R]WM$]9/%M@>@^1<F^;>B*:3*%W`&3*33`)K%"G?;[(9W"1`<%
+IPB4\*!`NX4&!<`D/"H1+>%`@7,*#`N&2'A2D.0(RMOL$5&JUB%T.````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-mbr.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-mbr.vhdf.gz.uu
new file mode 100644
index 0000000..7191855
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-mbr.vhdf.gz.uu
@@ -0,0 +1,15 @@
+# $FreeBSD$
+begin 644 img-63x255-512-mbr.vhdf.gz
+M'XL("/O%'50``VEM9RTV,W@R-34M-3$R+6UB<BYV:&1F+F]U=`"ME;MNPR`4
+MAO<\Q9&Z9;"XFRR)%#6=*U5M9]?!48:V2X<.?OB"\85C?$DJ[&,+"_C\GPM`
+MB+\`!`-23+SG.^ICAN]ZL]TT-/IQ'U`3J*H(F%F@QY469P=8*V3;L,8K<,+M
+M8ZVDP$W;]@9UUEP']]IG`>[<SXIMOJ/%#=?@;G4?4$HHB@CXVNECBS+NUY>;
+MQ/G53<'('(0$J4"S6Q6^G]Y&"CV.IG+8X]@:KA/L*V@*=PAPW%??0*'!K+#N
+MPG:`V_NGPXDE=382Q$QUS#HKTQ:+MC>>%^89J`'*@>BVCV%@GU\8].UB&0RY
+MNZ`/8G<+A\OQ>!K@V(J[@'%NHPKSB5*X$KU]K*Y,G`PZ7ADWKEP'P2O7XUC:
+MC6#7["RV`NVH^#W?43]G^/9`T0*315"W9YOBH"I0!I1T[5R`VD&N0R##E527
+MWU^F_+G^AAEV.-H?1;&Y^8R[U:)R8(7[B3J[=J#OX7397C\O':[;JKH?"^6"
+M+BU$1.YJ[.[3\>5QK(['0=(H>G0X.'O'4?0.(4[TSAK3;(%T,/2!.B:W*H>3
+79#3KO[GU.)6X5.RYN_D#OC2Q.1`)````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-mbr.vmdk.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-mbr.vmdk.gz.uu
new file mode 100644
index 0000000..0c79f43
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-mbr.vmdk.gz.uu
@@ -0,0 +1,84 @@
+# $FreeBSD$
+begin 644 img-63x255-512-mbr.vmdk.gz
+M'XL("/O%'50``VEM9RTV,W@R-34M-3$R+6UB<BYV;61K+F]U=`"M7-%NY,81
+M?/=7#.2W/"Q8RR6Y?#@[<<X!@B"`$3OV:\CE,!9BWQUT0I`#]/'AD%.C(D4>
+M::MUJP/[V%W;W4.U=-4%9=GTX=RE=9>+NW2N*%T&-_S3]')9_FP,KTNZ\?2W
+MMW__\<2//YY.3U],8`A1$H),X<28O<_3:?%!N//GHF8WAM=Y%RX/4>V+P`AW
+MWKBQ"3?TPYW70IA=,][NPH7`N03D9G#%2DV;Q7XNNS]\$9L7\LM##L/QEK6K
+M<E>VT71E,=JYJ\[CO<Q5@U,_`'[IWMY__(][ZS_>'NX_/+Z/^9W#V0[.ES+X
+ME[>`,!16E>$BW`AP=8`HO<L[ER/<=D\/?[G_Q9_^ZQ\^WK]_]P8L]QS.]I*[
+M2QW2"?[9\VMFA#?)7(GP'N[ISW]]^R8^N=GI0_-`N!`U)#*\]U"'XI:E"Y\O
+M7V-V_MUC0.SC1\HNG&UL3C&^]R5<%!=7U6Y,IPC8Y^%V%TL>>W=[\,VC_^'3
+M!__F[M?W[U+OPMF&EM4CT'5L5.Z*/$#%TD+[BH`8'IOQU-S3+_>//]_?OA_*
+M_.CO3E\ZPI6A=\,!7F->4]5#2+EYLD/:3]_^[W&HUW7Q9.\)-R8Q%C&\=W%V
+M116PA@/,A][EN<NO+A_AAX2'2BX(3N[I_;O3/WYR*//KQ7W_W9_^0;CK`#=X
+M#@D.(4-!LYJ*J?YB^5BZI^^_=7>AR!]^]N,32+AZ^C(+SM,Y8#3/X2)V;8(/
+M0^P2;HPGZ]XVCXW[IOGH3U^^??M-.MDF%'L97T-J/J"4$W1XOL=V#HV;3GHZ
+MZ/$HNJX]-5WSX=$_A.--1]&&I[6+E89CO3P?X_Q]JO&D^O#$N*<W[NZ^&\XT
+MP/[;O_^5<+?I,1[R"(]$/0;FX6)X>D9X']]A>F+",04X__CPZ73[],O]NV[X
+M0G-O"-=-O1O2&4YS2BKEM$PJO>W0NSL\IS9@$\Z'%DU)7>,7QH`UY?'<A7QX
+M%>$5N_#TZ?2S;[HA+7=W+HJ[=!3]\BBT18LN3`<]]&(ZBIC8I]-'?XMP>18/
+ML)\U9\HI/,K#DSQE-!^@C^\?QM3*_$[G<;[\7O;:>7QY\2VU^IV`$YQU?F6V
+M]_V,KWP&Z`0L>\ZO#/E=Q+/0J%*,:@8W_#1Q^F[X_-?P^4'@PB-V%<]:HQHQ
+MVB/=*\/WBYMX=AKEQ>@/P5UBB_@#"N1Z;"J-7&\D.+?H71%[1\]"HTHQJAG<
+M5N_*V#MZUAK5B-&N9K<LMHJ]HV>G45Z,_A#<-?:./X!!KL?>T<BSM9_REKVK
+M8^_H66A4*48U@]OJ71-[1\]:HQHQVM7LEL6VL7?T[#3*B]$?@KO%WG&L0*['
+MWM'(]<9F[[K8.WH6&E6*4<W@MGKG8^_H66M4(T:[FMVRV#[VCIZ=1GDQ^B-P
+M519[=Y'>\7KL'8U<;VSUKN*\HV>A4:48U0QNHW<5YQT]:XUJQ&A7LUL6RWE'
+MSTZCO!C](3C.NT)ZQ^NQ=S1RO;'9.\X[>A8:58I1S>"V>L=Y1\]:HQHQVM7L
+MEL5RWM&STR@O1G\(CO.NE-[Q>NP=C5QO;/:.\XZ>A4:58E0SN*W><=[1L]:H
+M1HQV-;MEL9QW].PTRHO1'X+CO../3I#KL7<T<KVQV3O..WH6&E6*4<W@MGK'
+M>4?/6J,:,=K5[);%<M[1L],H+T9_!.Z:Q=Y=I7>\'GM'(]<;6[V[<M[1L]"H
+M4HQJ!K?1NROG'3UKC6K$:%>S6Q;+>4?/3J.\&/TA.,Z[6GK'Z[%W-'*]L=D[
+MSCMZ%AI5BE'-X+9ZQWE'SUJC&C':U>R6Q7+>T;/3*"]&?PB.\X[_\8)<C[VC
+MD>N-S=YQWM&ST*A2C&H&M]4[SCMZUAK5B-&N9K<LEO..GIU&>3'Z0W"<=V0M
+M(==C[VCD>F.S=YQW]"PTJA2CFL%M]8[SCIZU1C5BM*O9+8OEO*-GIU%>C/X(
+M7)W%WMVD=[P>>T<CUQM;O:LY[^A9:%0I1C6#V^A=S7E'SUJC&C':U>R6Q7+>
+MT;/3*"]&?PB.\ZZ3WO&:K';J7?<";MD[SCMZ%AI5BE'-X+9ZQWE'SUJC&C':
+MU>R6Q7+>T;/3*"]&?PB.\\Y+[W@]]HY&KC<V>\=Y1\]"HTHQJAG<5N\X[^A9
+M:U0C1KN:W;)8SCMZ=AKEQ>@/P7'>]=([7H^]HY'KC<W><=[1L]"H4HQJ!K?5
+M.\X[>M8:U8C1KF:W+);SCIZ=1GDQ^B-P33;U+NW<(->A=\G(]<96[YHX[Y)G
+MH5&E&-4,;J-W39QWR;/6J$:,=C6[9;%QWB7/3J.\&/TAN#CO(/P=E+^#\'?8
+MY>^:..\@_!V4OX/P=]CE[YHX[R#\'92_@_!W*]DMBXWS#L+?0?D["']W`"[.
+M.PA_!^7O(/P==OF[)LX["'\'Y>\@_!UV^;LFSCL(?P?E[R#\W4IVRV+CO(/P
+M=U#^#L+?'8"+\P["WT'Y.PA_AUW^KHGS#L+?0?D["'^'7?ZNB?,.PM]!^3L(
+M?[>2W;+8..\@_!V4OX/P=_MP;19[)_P=E+^#\'?8Y>]:SCOA[Z#\'82_PRY_
+MUW+>"7\'Y>\@_-U*=LMB.>^$OX/R=Q#^[@`<YYWP=U#^#L+?89>_:SGOA+^#
+M\G<0_@Z[_%W+>2?\'92_@_!W*]DMB^6\$_X.RM]!^+L#<)QWPM]!^3L(?X==
+M_J[EO!/^#LK?0?@[[/)W+>>=\'=0_@["WZUDMRR6\T[X.RA_!^'O#L!QW@E_
+M!^7O(/P==OF[EO-.^#LH?P?A[[#+W[6<=\+?0?D["'^WDMVR6,X[X>^@_!V$
+MO]N'NV6Q=\+?0?D["'^'7?[NQGDG_!V4OX/P=]CE[VZ<=\+?0?D["'^WDMVR
+M6,X[X>^@_!V$OSL`QWDG_!V4OX/P=]CE[VZ<=\+?0?D["'^'7?[NQGDG_!V4
+MOX/P=RO9+8OEO!/^#LK?0?B[`W"<=\+?0?D["'^'7?[NQGDG_!V4OX/P=]CE
+M[VZ<=\+?0?D["'^WDMVR6,X[X>^@_!V$OSL`QWDG_!V4OX/P=]CE[VZ<=\+?
+M0?D["'^'7?[NQGDG_!V4OX/P=RO9+8OEO!/^#LK?0?B[?;@NB[T3_@[*WT'X
+M.^SR=QWGG?!W4/X.PM]AE[_K..^$OX/R=Q#^;B6[9;&<=\+?0?D["']W`([S
+M3O@[*'\'X>^PR]]UG'?"WT'Y.PA_AUW^KN.\$_X.RM]!^+N5[);%<MX)?P?E
+M[R#\W0$XSCOA[Z#\'82_PRY_UW'>"7\'Y>\@_!UV^;N.\T[X.RA_!^'O5K);
+M%LMY)_P=E+^#\'<'X#COA+^#\G<0_@Z[_%W'>2?\'92_@_!WV.7O.LX[X>^@
+M_!V$OUO);EDLYYWP=U#^#L+?[</Y;.I=DN!!KD<9(XU<;SR-31L^W?"9N6>X
+M..]6%7TK_Y1ZY]:S>Z'%/P;WLMA);HA1;I@V$5.YOP]P@C.60^(:N[X/>$0.
+MB;0NY^M5<DBD=3E?KY)#(JW+^7J5'!)I76XBAT1:EYO((9'6Y29R2*1UN8D<
+M$FE=;B*'1%J7F\@AD=;E)G)(I'6YB1P2:5UN(H=$6I>;R"&1UN4F<DBD=;F)
+M'!)I76XBAT1:EYO((9'6Y29R2*1UN8D<$FE=;B*'1%J7F\@AD=;E)G)(I'6Y
+MB1P2:5UN(H=$6I>;R"&1UN4F<DBD=;F)'!)I76XBAT1:EYO((9'6Y29R2*1U
+MN8D<$ER7V\@AP76YC1P27)?;R"'!=;F-'!)<E]O((<%UN8T<$ER7V\@AP76Y
+MC1P27)?;R"'!=;F-'!)<E]O((<%UN8T<$ER7V\@AP76YC1P27)?;R"'!=;F-
+M'!)<E]O((<%UN8T<$ER7V\@AP76YC1P27)?;R"'!=;F-'!)<E]O((<%UN8T<
+M$ER7V\@AP76YC1P27)?;R"'!=;F-'!)<E]O((<%UN8T<$ER7V\@AP76YC1P2
+M:5V>/??N]\LAD=;E]'R5'!)I74[/5\DAD=;E]'R5'!)I76XBAT1:EYO((9'6
+MY29R2*1UN8D<$FE=;B*'1%J7F\@AD=;E)G)(I'6YB1P2:5UN(H=$6I>;R"&1
+MUN4F<DBD=;F)'!)I76XBAT1:EYO((9'6Y29R2*1UN8D<$FE=;B*'1%J7F\@A
+MD=;E)G)(I'6YB1P2:5UN(H=$6I>;R"&1UN4F<DBD=;F)'!)I76XBAT1:EYO(
+M(9'6Y29R2*1UN8D<$ER7V\@AP76YC1P2WE0."6\JAX0WE4/"F\HAX4WED/"F
+M<DAX4SDDO*D<$MY4#@EO*H>$-Y5#PIO*(>%-Y9#PIG)(]%EF*(=$;RJ'1&\J
+MAT1O*H=$;RJ'1&\JAT1O*H=$;RJ'1&\JAT1O*H=$;RJ'1&\JAT1O*H=$;RJ'
+M1&\JAT1O*H<\9UEF*(<\9Z9RR//+7TU\#.YEL9/<\#*6._WNTI=_;]]X^N8T
+M_Y,`T?XVP.%!Z/L7@"SX@O`H#P[#JRGBQ?#*>RGX!I?[U8*_#G]]=1*XSKA_
+MZ'\;8%&XIGD!^$_F=_YL&K\]O\H;G^]U?&"**OR:W:)TU_/1#'_Z]L=%AA.<
+MF7YV@MO]^D@L:+\%][7`Y=/3]XRBOPE<GSN]%KBOID_"73Z7G2ZHCA5K_*N[
+MK]EU$:?G'+[O!#J0_\L[SP'3^;KG_.J7:9QGY7XF/_>RW/`]5W]YK9[';$QO
+ME.OF<&%0Z7G.CG"G>U^]S.YF?!A8?F4<_,H-(/.OW`GN;#L(ZG&R3*J/EW]O
+=WWCZ[C3_,P%>(J!9!R_A%Y-D7_P?*H?3&&]@````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-pc98.qcow.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-pc98.qcow.gz.uu
new file mode 100644
index 0000000..8572850
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-pc98.qcow.gz.uu
@@ -0,0 +1,126 @@
+# $FreeBSD$
+begin 644 img-63x255-512-pc98.qcow.gz
+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
+B]_!W_<+7+Z_O_O5C<&B#O^P$AV^X;+>__1^"\<L6HZ@`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-pc98.qcow2.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-pc98.qcow2.gz.uu
new file mode 100644
index 0000000..85e22d7
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-pc98.qcow2.gz.uu
@@ -0,0 +1,22 @@
+# $FreeBSD$
+begin 644 img-63x255-512-pc98.qcow2.gz
+M'XL("+0[(U0``VEM9RTV,W@R-34M-3$R+7!C.3@N<6-O=S(N;W5T`*V8VY+3
+M,`Q`W_L5Y@X+E%BR<^'271:6&=[@`7ANN\U7=/AVZMJ-$D6*NR5M)M..1V=D
+M^UBQ4Q3Q8XRWQI7&-:;=F,/_=('I_1E>9O_SV_=E_[-?1)@ME"BAH=IUN`'K
+M+^%`PQ5VW&!E7"\[%'!PBAJ#<CBG9C?5(."N%L>A.TY&S2+P$F#$J9-Q47X0
+M\^,1[L+\8.[\4!X_?XKC#>5T?ACSXU&5AJNS.!"B&@VWSN)0B-IHN&T6YX2H
+M>PVGK-P>S@M1K8*S&54.N%*(LAH.LKA*B$(-Y[*X6HC2O+-Y[QHA2O/.YKU;
+M"U&:=S;OW4:(TKRS>>^V0I3FG<U[=R]$:=Z!XITAW$Z(TKP#YMVCA'M,N%:(
+MTKP#YMV3A'O:X:P4I7D'S+MG"?><<$*]`\T[8-Z]2+B7A!/J'6C>`?/N5<)=
+M$4ZH=Z!Y!\R[UPGWAG!"O0/-.V#>O1UY9X5Z!YIWR+Q[EU@%X81ZAYIWR+RS
+M"0>$$^H=:MXA\PX3SA%.J'>H>8?,.Y]P)>&$>H>:=\B\JQ*N)IQ0[U#S#IEW
+M3<*])YQ0[U#S#IEW'Q+N(^&$>H>:=\B\^Y1P*\()]0XU[QSS[CKA;@@GU#NG
+M>>>8=Y\3[I9P0KUSFG>.>?<EX;YV.)"B.N^*0KX2[FZT9F'>_:>C_;$5[GK#
+M!+!^"'`JPXAK9NVPCQT.&JR%N]ZPOUT.OQWP*,P#@-Z;]1CX*W;81V$:9[9.
+MZE?;TG7&^/FYA?%A2F8=/Q!/:/^18;6;.<,ZOG"HPKKUI:GAW`S_W/T6IJ2>
+M[PP9<?H+A]1P2AA;#7?=PV'4C"B]E6JVE@I\_W</MUI2L3_@)E\XA%/43FI0
+M.^OGE:7NRM7IZL]SV+R',];I^<TVW]W\&LI/*%<PZ.Y$?F;<W;`OZ,[O;#X"
+M#C+=-4-<V!?TYW,PA9G16XVSV\X\&9:OC#-7;H`,5V[$P;R%H#E6EH.!H8J/
+<[GK#_L=R^(U`EX"SC:`KP]-M\0^92;H")14`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-pc98.raw.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-pc98.raw.gz.uu
new file mode 100644
index 0000000..1a19b11
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-pc98.raw.gz.uu
@@ -0,0 +1,12 @@
+# $FreeBSD$
+begin 644 img-63x255-512-pc98.raw.gz
+M'XL("/O%'50``VEM9RTV,W@R-34M-3$R+7!C.3@N<F%W+F]U=`"ME,V.A"`,
+MQ^\^1<][,*7"BA<GF63O<YG=LVOT*7SX!<&5BOB1`$@PA5_^;:&(K@%(`NQV
+MYK1A>I:\3\5',=/$>`^H%'0Q\&V`,XZLOD9"+\&L-@/&<1W,,)6;MN"$,<8@
+M?RIIV,%Y=V7F^!$>"KFOL!XR*]2S0E6#5*`^0=-5A3]?WSLIT9@M)0Y'9[A%
+M<#6F<(\`5[EKME)$<*H74`W^)UP'N-9]"TX>J3.1P&'/D'16Y;TLVG1^+LPS
+MB`%$!:B]C3CP/[^PZFMB&<3</=`'L;N=Q=5\OPAP=.(N<-ROQ07Y9"D\B5X;
+MJ^LS)T-L7\;%EVLA_.4Z'.4M!,U<6<P-M%4\FM.&Z57R[H#2`[-%T%8^Q.(/
+(W!$BDN<&````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-pc98.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-pc98.vhd.gz.uu
new file mode 100644
index 0000000..f474436
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-pc98.vhd.gz.uu
@@ -0,0 +1,18 @@
+# $FreeBSD$
+begin 644 img-63x255-512-pc98.vhd.gz
+M'XL("/S%'50``VEM9RTV,W@R-34M-3$R+7!C.3@N=FAD+F]U=`"METUOXR`0
+MAN_Y%2/MK0<+CP&32RM5VYXK5>V>B=>N>NANU>RA!__X,@:2P5])ML0.P@(>
+MWOD`A!#^!Z`KT!WH%K2B>BU!;Z$V`*XQO#B49?B$OOG[IVW^O7X6X==O/*P4
+M?%0ZG,9C!=)-4@-:FD3_ICKT$5/\N'NY>GU[B3@,N#BQU"`1E(/(R3Q&'-01
+MZ?[V\>=87355=QSEY^DZJ#K6H^+JBN*&XZ0;Y?K3JZ&3@\SX)A])`\<EZI08
+MC6(RYYS*C)W#Z;51E^"N-B$6/E5<8M2N%*!+J)'J+FVB'R:O2Y7/_;O]V+<C
+M?;B0*IH%8]PFE\W%D"H8.P<%D@2NF0L#93_&S:3*M[RGTW$R5)P3A(H-.)B?
+M>N^(`JY/EV+%Y\O!6-1G29];6\+.E,L-_6V1/@?@KKL,J!38*?`I&MR0OJV$
+M1L[YG1MYUNIH%K+OO^/;9O8?VE4AERLT)K-",RA4-6WH2H/!<Q7^NGN>"8FQ
+MV4+B<7@*%P7S_3[%W3!<Y=/L2&';$S0E5&WXX'6&N_;_B)-KZFA7:.<:%HU5
+MF9/%FM$X'F<H6R@K$":T80H\Q!>.^K93&9B8NZ(/IN9:PM5I_Y+A\(2YD.)V
+MX>2-/9,0GO#>]51=DSD8N_'*.'/E$B1=N1Z'>3<".^PL+@-I%Y^4RPW]0Y$^
+M'HCA,,IVNF$X/;(IE`&83:$,YT=&A;993;9+LU`'A9FN"H3+>%4@7,:K`N$R
+>7A4(E_&J0+B,5P7"9;TJ:'<)%&+S!5&O-H=?#@``
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-pc98.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-pc98.vhdf.gz.uu
new file mode 100644
index 0000000..dce8fa3
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-pc98.vhdf.gz.uu
@@ -0,0 +1,15 @@
+# $FreeBSD$
+begin 644 img-63x255-512-pc98.vhdf.gz
+M'XL("/S%'50``VEM9RTV,W@R-34M-3$R+7!C.3@N=FAD9BYO=70`K94];X,P
+M$(;W_(J3NF6(_(U9$BEJ.E>JVLZ4FBA#VZ5#!WY\?1B"#T.25L8&&1U^>._.
+M/C,6+@`E@%4SSV5#N]_0UJ[6JX[&F[\!M88J!3Y[8(<3J*]44"OPHTF'IAD[
+M,;2;R37@N#>FH'[6HF$&U[NK,L=/L(M"_JZP<)D5VDZA+D!IT`:LN%7AZ^%E
+M)B6694M)P(EKN$&P;)9PNP@GPS(;*3R:57.0KG^)QQ%N&^X!IRZI\Y%@;LZP
+MZ*S.NUBL;W1>G&?@#K@$9GN;H,!S?F'45Z8R!''W@CY(W:T05]#O>8035]P%
+MBGM#7)1/DL(KT=NFZNK,R>#3G7'CSD4(W;D!)_(6@K*K+'X%8A5/GLN&]G%#
+M6P"J'I@M@K8_W8P$TX!Q8#2."P6FA,+&0$%74EM_?;KZ^_039QAQ?'+FQ!WG
+M"XF[Q10@*OR)><=QI._N<%R?/HX#;BA5PX^5P:!K#U&)NY:Z^[!_NI^JDVF0
+M+(D>1YUQV?..D^CM8IPZ.^M<5P+YV,D+,<R6*L1I-IGUW]P&G,F\5/S!N_H%
+(/-'XFQ()````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-pc98.vmdk.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-pc98.vmdk.gz.uu
new file mode 100644
index 0000000..7279c4b
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-pc98.vmdk.gz.uu
@@ -0,0 +1,84 @@
+# $FreeBSD$
+begin 644 img-63x255-512-pc98.vmdk.gz
+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
+./YHD^>+_!_V[IW%@````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-vtoc8.qcow.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-vtoc8.qcow.gz.uu
new file mode 100644
index 0000000..791a1e0
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-vtoc8.qcow.gz.uu
@@ -0,0 +1,127 @@
+# $FreeBSD$
+begin 644 img-63x255-512-vtoc8.qcow.gz
+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
+E?I;F#/[./_#KSS_>_^OK8,J#?]DK3'=>.9]_^#\)B7^=OZ8`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-vtoc8.qcow2.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-vtoc8.qcow2.gz.uu
new file mode 100644
index 0000000..0a79ac2
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-vtoc8.qcow2.gz.uu
@@ -0,0 +1,21 @@
+# $FreeBSD$
+begin 644 img-63x255-512-vtoc8.qcow2.gz
+M'XL("+8[(U0``VEM9RTV,W@R-34M-3$R+79T;V,X+G%C;W<R+F]U=`"MF-MN
+MTT`0AN_S%,NI0(&2G=EU;$Z%'B)Q@03B!8AC^P&X0\K#L[$W&7L\XTTBIU:D
+MU/T_S:Z__K6[7'8O8[PU+C.N,$UIPN=X@.E]&!YF]VO]_:;_VBTZF%TJJ=$)
+M:U;%$3=@_2,<:+@0%[XEXGK3H8"#0VH,2N&<.MW4"0%WO6BWKKT8.4O@)<`.
+MIUZ,B^:#;CZ><!?.!W//A_+^^0OGP_GGPWHJQP?/4O-A(Z16&BY/X9R4*C3<
+M)HFS0JK4<-LD#H14I>'J)`Z%5*/@;%(5YX24U7"0Q'DAA1K.)7&9D/(:+NF=
+M6PDIS3N;]BX74IIW-NU=(:0T[VS:NXV0TKRS:>]*(:5Y!XIWAG!;(:5Y!\R[
+M)Q'WE'"5D-*\`^;=LXA[3KA:2&G>`?/N1<1=$4[H.]"\`^;=RXA[=<1Y*:5Y
+M!\R[UQ%W33BA[T#S#IAW;R+N+>&$O@/-.V#>O1MYYX6^`\T[9-Z]CZPEX82^
+M0\T[9-[9B`/""7V'FG?(O,.(<X03^@XU[Y!YYR,N(YS0=ZAYA\R[5<3EA!/Z
+M#C7OD'E71-P'P@E]AYIWR+S[&'&?""?T'6K>(?/N<\1](9S0=ZAYYYAWMQ'W
+ME7!"WSG-.\>\^Q9Q=X03^LYIWCGFW7W$/1!.Z#NG>>>8=X\1MR9<,^O]IZ/[
+M=RN\ZR<F@/GY0/6/8\`5LR[8=PL.&[T"D_G]$93PN+^2H9/V#>,J$;C^6]=W
+MOQ\`?_3F\W,_$'C:O^5@@Q1@WMZ.@[9_?K!_11(W-5^'V\RUW`Y7GHH+]1UN
+M[:O:U#7#_>GAMC-?##M:;GVX\\<+EFL/RT7ZX:9MOM!_"J[WRW;+<;1<8"GZ
+M1XV5IC/B=-415VZI\T[9O7L)-_ED>_[>G=Q\U<:4P1-KFJV.@\DASE8ERUM@
+BN&<)3\'C=_W$[N?-\*L#N@B<;<+P@!9>B_]NV1VQX1,`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-vtoc8.raw.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-vtoc8.raw.gz.uu
new file mode 100644
index 0000000..c949873
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-vtoc8.raw.gz.uu
@@ -0,0 +1,11 @@
+# $FreeBSD$
+begin 644 img-63x255-512-vtoc8.raw.gz
+M'XL("/W%'50``VEM9RTV,W@R-34M-3$R+79T;V,X+G)A=RYO=70`K9)!;L,@
+M$$7W/L5?=V$Q@&V\JI16V56JU`O4-G"`K#E\2'!"C+'C1![0"&GF/\T7PU@(
+M0-9H..KJ<B5')2`E!`>$?VGXEN3"'4_&'/Z^N?@IK^&*`"-?G/>/JL6"*Y-P
+MQ<<(5!,=K0,56`O&L\"`:Z.J?8I;FR_@NKWL!ER_%5?[K*$-C$EP_P^X8>?/
+MH)E=`PH/\89=NMD5L=G:2Q9V"4<1]YGBHEV>J#BB/C,=LM/I.ZX?(,54M6KV
+M*X<SNZX*V:TXW:'W>T*PPS*.KP[QZJHT6EV!E>_J,GFYX'[+Z0G`?@3N-2$U
+-2M6,%6>->Z%+`P4`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-vtoc8.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-vtoc8.vhd.gz.uu
new file mode 100644
index 0000000..523a1ae
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-vtoc8.vhd.gz.uu
@@ -0,0 +1,18 @@
+# $FreeBSD$
+begin 644 img-63x255-512-vtoc8.vhd.gz
+M'XL("/W%'50``VEM9RTV,W@R-34M-3$R+79T;V,X+G9H9"YO=70`K9;-;MLP
+M#,?O>0H"N_5@R)0LVZ<"Z];;@`%[@<FV7!3#UJ'=H8<\_$A;CB5_K5F9"(X,
+MB3_]*5$,E1H_`%:#[<%ZL`7W2P.VAK("H,'0<'CFX17.[=,OW_YY?,W"YWP:
+M8;F*K5)SMD<-AA8I`1TO8CONPWG"9!\^/]P\_GR8<!APT\+&@D$H"&(6Z^10
+MJ8LZ)MU__/9IJ4XOU<56_*.A[T'WT0P=J\NRVQAGR(KF<[/0CS*GEKPD`S$N
+M45>HA56D=&M3(V>W</;(ZAK<S2F<Q1@J%!@E/178'$KD/H7-M`^K1J'R^O+;
+M/;_XA3[<"15[T9>OQMI]=S&$"DZ3@P**Y>;071@H/Y:X5:B\<_=L:F?238I?
+MQAFT.ZK8=]?.NX?3IE$CU:H\.HQL\%>M<*@.K(YP.^XZ=I=N*P4()Y5BOK8:
+M`33UNLW]NW_VGBXNZB^)/K<3+/]]'*Y*[/YQV2I0-2>QW>-P]6Q5O__N.B?E
+M[HAKWHJCG*$ZZ#QXO\!]CW"M\&$T*W?]$/]J2+]7N]M,[NIY\GBO*+/OX**\
+M?+O$M<E5BQO";+^A#C;5=1=<TX+1J=6ALW=;."\:*DW_5ESGH*$XR:$_R,KM
+MH8AK0P5#7A%+5"BM4'>5YV'Z*U=NX[D_</Z:I=\1:()",9<)**O0!J"80DM%
+MI*C"LJM1])2KH%"H;F:<8-W,.,&ZF7&"=3/C!.MFQ@G6S8P3K9L)2+%W^@L6
+'\>:S;`T`````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-vtoc8.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-vtoc8.vhdf.gz.uu
new file mode 100644
index 0000000..d8c4d3d
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-vtoc8.vhdf.gz.uu
@@ -0,0 +1,14 @@
+# $FreeBSD$
+begin 644 img-63x255-512-vtoc8.vhdf.gz
+M'XL("/[%'50``VEM9RTV,W@R-34M-3$R+79T;V,X+G9H9&8N;W5T`*V4O6[#
+M(!2%]SS%D;IEB,R/L3U%ZD^V2I7Z`K4-1!G:2E6'#G[X8K!C(-A-(V.$B.!\
+MG$LN-\M<`[A`02'ROG.*G(%S,`HP,Y,P6Z*.[O"EU/WK(V7/.]NZC8,1LWBY
+M?U#-+G2[J'6;[0`L`QU9!I;(*F0T"72X:E)5?^*6_#E<O5:X#M=<BQ-FE)`*
+M2D6X-P_7KOQGD(MP%8B;L!O")6.X;-JL=3\R/8<C$VX?XZ9P::2BF/0)=TBZ
+MDV=<TX*S4+48[$,*IU9-%:*OQ<D:C<D3`MW.X^BBB?^F2B%+"\S-KCHQSB]T
+M+[OP<\!F`*[ED)1#Y1,,0D,H6_P8"@Y1H2A](`WR!EW[^:':[]./=X,6UU<^
+MD[W)WNNIJ:7FD`*T[@\1LI][_NZ>CMO3^W'$T2&J\6!3H\^E.7X291CNP13F
+MV!V++\E7N3=H?#(=/AK_]O8^CI^#-05(-];FV(,?P4(J^RPNSR+5S6_#XL3*
+.J6)R;_,+FZ-::BX'````
+`
+end
diff --git a/usr.bin/mkimg/tests/img-63x255-512-vtoc8.vmdk.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-vtoc8.vmdk.gz.uu
new file mode 100644
index 0000000..d9340d1
--- /dev/null
+++ b/usr.bin/mkimg/tests/img-63x255-512-vtoc8.vmdk.gz.uu
@@ -0,0 +1,83 @@
+# $FreeBSD$
+begin 644 img-63x255-512-vtoc8.vmdk.gz
+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
+G_X]*OP"N_H#+_^^_X+]G;/];`34"FIU0_7NC++_Z'WN7IO#-7P``
+`
+end
diff --git a/usr.bin/mkimg/tests/mkimg.sh b/usr.bin/mkimg/tests/mkimg.sh
new file mode 100755
index 0000000..8dfb74c
--- /dev/null
+++ b/usr.bin/mkimg/tests/mkimg.sh
@@ -0,0 +1,164 @@
+# $FreeBSD$
+
+mkimg_blksz_list="512 4096"
+mkimg_format_list="qcow qcow2 raw vhd vhdf vmdk"
+mkimg_geom_list="1x1 63x255"
+mkimg_scheme_list="apm bsd ebr gpt mbr pc98 vtoc8"
+
+bootcode()
+{
+ case $1 in
+ bsd|pc98) echo 8192 ;;
+ gpt|mbr) echo 512 ;;
+ *) echo 0 ;;
+ esac
+ return 0
+}
+
+mkcontents()
+{
+ local byte count name
+
+ byte=$1
+ count=$2
+
+ name=_tmp-$byte-$count.bin
+ jot -b $byte $(($count/2)) > $name
+ echo $name
+ return 0
+}
+
+makeimage()
+{
+ local blksz bootarg bootsz format geom nhds nsecs partarg pfx scheme
+
+ format=$1
+ scheme=$2
+ blksz=$3
+ geom=$4
+ pfx=$5
+ shift 5
+
+ nsecs=${geom%x*}
+ nhds=${geom#*x}
+
+ bootsz=`bootcode $scheme`
+ if test $bootsz -gt 0; then
+ bootarg="-b `mkcontents B $bootsz`"
+ else
+ bootarg=""
+ fi
+
+ partarg=""
+ for P in $*; do
+ partarg="$partarg -p $P"
+ done
+ if test -z "$partarg"; then
+ local swap ufs
+ swap="-p freebsd-swap::128K"
+ ufs="-p freebsd-ufs:=`mkcontents P 4194304`"
+ partarg="$ufs $swap"
+ fi
+
+ imagename=$pfx-$geom-$blksz-$scheme.$format
+
+ mkimg -y -f $format -o $imagename -s $scheme -P $blksz -H $nhds -T $nsecs \
+ $bootarg $partarg
+ echo $imagename
+ return 0
+}
+
+mkimg_rebase()
+{
+ local baseline image result tmpfile update
+
+ image=$1
+ result=$2
+
+ baseline=$image.gz.uu
+ update=yes
+
+ if test -f $baseline; then
+ tmpfile=_tmp-baseline
+ uudecode -p $baseline | gunzip -c > $tmpfile
+ if cmp -s $tmpfile $result; then
+ update=no
+ fi
+ fi
+
+ if test $update = yes; then
+ # Prevent keyword expansion when writing the keyword.
+ (echo -n '# $'; echo -n FreeBSD; echo '$') > $baseline
+ gzip -c $result | uuencode $image.gz >> $baseline
+ fi
+
+ rm $image $result _tmp-*
+ return 0
+}
+
+mkimg_test()
+{
+ local blksz format geom scheme
+
+ geom=$1
+ blksz=$2
+ scheme=$3
+ format=$4
+
+ case $scheme in
+ ebr|mbr|pc98)
+ bsd=`makeimage raw bsd $blksz $geom _tmp`
+ partinfo="freebsd:=$bsd"
+ ;;
+ *)
+ partinfo=""
+ ;;
+ esac
+ image=`makeimage $format $scheme $blksz $geom img $partinfo`
+ result=$image.out
+ hexdump -C $image > $result
+ if test "x$mkimg_update_baseline" = "xyes"; then
+ mkimg_rebase $image $result
+ else
+ baseline=`atf_get_srcdir`/$image
+ atf_check -s exit:0 cmp -s $baseline $result
+ fi
+ return 0
+}
+
+atf_test_case rebase
+rebase_body()
+{
+ local nm
+
+ mkimg_update_baseline=yes
+ for nm in $mkimg_tests; do
+ ${nm}_body
+ done
+ return 0
+}
+
+atf_init_test_cases()
+{
+ local B F G S nm
+
+ for G in $mkimg_geom_list; do
+ for B in $mkimg_blksz_list; do
+ for S in $mkimg_scheme_list; do
+ for F in $mkimg_format_list; do
+ nm="${S}_${G}_${B}_${F}"
+ atf_test_case $nm
+ eval "${nm}_body() { mkimg_test $G $B $S $F; }"
+ mkimg_tests="${mkimg_tests} ${nm}"
+ atf_add_test_case $nm
+ done
+ done
+ done
+ done
+
+ # XXX hack to make updating the baseline easier
+ if test "${__RUNNING_INSIDE_ATF_RUN}" != "internal-yes-value"; then
+ atf_add_test_case rebase
+ fi
+}
+
diff --git a/usr.bin/xinstall/xinstall.c b/usr.bin/xinstall/xinstall.c
index f40cdc5..b59db70 100644
--- a/usr.bin/xinstall/xinstall.c
+++ b/usr.bin/xinstall/xinstall.c
@@ -1263,13 +1263,18 @@ install_dir(char *path)
if (!*p || (p != path && *p == '/')) {
ch = *p;
*p = '\0';
- if (stat(path, &sb)) {
- if (errno != ENOENT || mkdir(path, 0755) < 0) {
+again:
+ if (stat(path, &sb) < 0) {
+ if (errno != ENOENT)
+ err(EX_OSERR, "stat %s", path);
+ if (mkdir(path, 0755) < 0) {
+ if (errno == EEXIST)
+ goto again;
err(EX_OSERR, "mkdir %s", path);
- /* NOTREACHED */
- } else if (verbose)
+ }
+ if (verbose)
(void)printf("install: mkdir %s\n",
- path);
+ path);
} else if (!S_ISDIR(sb.st_mode))
errx(EX_OSERR, "%s exists but is not a directory", path);
if (!(*p = ch))
diff --git a/usr.sbin/autofs/common.c b/usr.sbin/autofs/common.c
index 1d1117c..cefbcc8 100644
--- a/usr.sbin/autofs/common.c
+++ b/usr.sbin/autofs/common.c
@@ -673,11 +673,21 @@ node_find(struct node *node, const char *path)
{
struct node *child, *found;
char *tmp;
+ size_t tmplen;
//log_debugx("looking up %s in %s", path, node->n_key);
tmp = node_path(node);
- if (strncmp(tmp, path, strlen(tmp)) != 0) {
+ tmplen = strlen(tmp);
+ if (strncmp(tmp, path, tmplen) != 0) {
+ free(tmp);
+ return (NULL);
+ }
+ if (path[tmplen] != '/' && path[tmplen] != '\0') {
+ /*
+ * If we have two map entries like 'foo' and 'foobar', make
+ * sure the search for 'foobar' won't match 'foo' instead.
+ */
free(tmp);
return (NULL);
}
diff --git a/usr.sbin/bhyve/smbiostbl.c b/usr.sbin/bhyve/smbiostbl.c
index 28c7eb2..59a1358 100644
--- a/usr.sbin/bhyve/smbiostbl.c
+++ b/usr.sbin/bhyve/smbiostbl.c
@@ -737,7 +737,7 @@ smbios_ep_initializer(struct smbios_entry_point *smbios_ep, uint32_t staddr)
smbios_ep->eplen = 0x1F;
assert(sizeof (struct smbios_entry_point) == smbios_ep->eplen);
smbios_ep->major = 2;
- smbios_ep->minor = 4;
+ smbios_ep->minor = 6;
smbios_ep->revision = 0;
memcpy(smbios_ep->ianchor, SMBIOS_ENTRY_IANCHOR,
SMBIOS_ENTRY_IANCHORLEN);
diff --git a/usr.sbin/bsdinstall/scripts/services b/usr.sbin/bsdinstall/scripts/services
index 54c5018..83786c2 100755
--- a/usr.sbin/bsdinstall/scripts/services
+++ b/usr.sbin/bsdinstall/scripts/services
@@ -43,6 +43,7 @@ DAEMONS=$( dialog --backtitle "FreeBSD Installer" \
--title "System Configuration" --nocancel --separate-output \
--checklist "Choose the services you would like to be started at boot:" \
0 0 0 \
+ local_unbound "Local caching validating resolver" ${local_unbound:-off} \
sshd "Secure shell daemon" ${sshd_enable:-off} \
moused "PS/2 mouse pointer on console" ${moused_enable:-off} \
ntpd "Synchronize system and network time" ${ntpd_enable:-off} \
diff --git a/usr.sbin/newsyslog/newsyslog.8 b/usr.sbin/newsyslog/newsyslog.8
index e6d79a4..ba3db8a 100644
--- a/usr.sbin/newsyslog/newsyslog.8
+++ b/usr.sbin/newsyslog/newsyslog.8
@@ -17,7 +17,7 @@
.\" the suitability of this software for any purpose. It is
.\" provided "as is" without express or implied warranty.
.\"
-.Dd May 19, 2014
+.Dd September 23, 2014
.Dt NEWSYSLOG 8
.Os
.Sh NAME
@@ -156,6 +156,7 @@ will create the
.Dq rotated
logfiles using the specified time format instead of the default
sequential filenames.
+The filename used will be kept until it is deleted.
The time format is described in the
.Xr strftime 3
manual page.
OpenPOWER on IntegriCloud