diff options
author | Jerry Jelinek <jerry.jelinek@joyent.com> | 2016-11-18 13:13:08 +0000 |
---|---|---|
committer | Jerry Jelinek <jerry.jelinek@joyent.com> | 2016-11-18 13:13:08 +0000 |
commit | acaf9b750d3116b5a05a4d23d4aa10c788ca318b (patch) | |
tree | 2a14052051229f9c233869862f4e58e76af7afea /usr/src | |
parent | 9035d37f2dc0a9fee9342a2b7cc8a86621788ae7 (diff) | |
parent | 6849994e8263545ed3c0f6f5676e47b38e14f63e (diff) | |
download | illumos-joyent-acaf9b750d3116b5a05a4d23d4aa10c788ca318b.tar.gz |
[illumos-gate merge]
commit 6849994e8263545ed3c0f6f5676e47b38e14f63e
7582 vmxnet3s MAC callbacks erroneously return DDI_ return values
7583 vmxnet3s rx buffer allocations can result in system unresponsiveness
commit ca5345b6a28e9e9bfd0c135121d62c6b35a5390d
7581 merge vmxnet3s changes from open-vm-tools stable-10.0.x
commit ac89d1e83d4735655102d06f099fb2d21bf120f6
7535 need test for resumed send of top most filesystem
commit 231d78912999b46bdfbedbcac4bd08f1fd0d2a7b
7564 boot/forth Create a hook 'post-initialize'.
commit a192d1c0eb1d05a03ead3c7f898e864e4bf0399c
7506 epoll_create1 should toss EINVAL for invalid flags
Conflicts:
usr/src/test/os-tests/tests/poll/Makefile
Diffstat (limited to 'usr/src')
25 files changed, 556 insertions, 686 deletions
diff --git a/usr/src/boot/sys/boot/forth/loader.4th b/usr/src/boot/sys/boot/forth/loader.4th index cd2f777d36..b6955f1b98 100644 --- a/usr/src/boot/sys/boot/forth/loader.4th +++ b/usr/src/boot/sys/boot/forth/loader.4th @@ -508,6 +508,8 @@ only forth definitions also support-functions include_bootenv include_conf_files include_transient + \ If the user defined a post-initialize hook, call it now + s" post-initialize" sfind if execute else drop then parse-boot-args \ Will *NOT* try to load kernel and modules if no configuration file \ was successfully loaded! @@ -531,13 +533,15 @@ only forth definitions also support-functions \ \ Overrides support.4th initialization word with one that does \ everything start one does, short of loading the kernel and -\ modules. Returns a flag +\ modules. Returns a flag. : initialize ( -- flag ) s" /boot/defaults/loader.conf" initialize include_bootenv include_conf_files include_transient + \ If the user defined a post-initialize hook, call it now + s" post-initialize" sfind if execute else drop then parse-boot-args any_conf_read? ; diff --git a/usr/src/lib/libc/port/llib-lc b/usr/src/lib/libc/port/llib-lc index d887a44f37..358e1fb71a 100644 --- a/usr/src/lib/libc/port/llib-lc +++ b/usr/src/lib/libc/port/llib-lc @@ -100,6 +100,7 @@ #include <sys/cladm.h> #include <sys/corectl.h> #include <sys/dl.h> +#include <sys/epoll.h> #include <sys/exacct.h> #include <sys/fcntl.h> #include <sys/file.h> diff --git a/usr/src/pkg/manifests/system-test-ostest.mf b/usr/src/pkg/manifests/system-test-ostest.mf index f3ab60203f..7a1a0624f4 100644 --- a/usr/src/pkg/manifests/system-test-ostest.mf +++ b/usr/src/pkg/manifests/system-test-ostest.mf @@ -31,6 +31,7 @@ dir path=opt/os-tests/tests/sigqueue file path=opt/os-tests/README mode=0444 file path=opt/os-tests/bin/ostest mode=0555 file path=opt/os-tests/runfiles/default.run mode=0444 +file path=opt/os-tests/tests/epoll_test mode=0555 file path=opt/os-tests/tests/file-locking/acquire-lock.32 mode=0555 file path=opt/os-tests/tests/file-locking/acquire-lock.64 mode=0555 file path=opt/os-tests/tests/file-locking/runtests.32 mode=0555 diff --git a/usr/src/test/os-tests/tests/poll/Makefile b/usr/src/test/os-tests/tests/poll/Makefile index 66ee75160e..14cc28b056 100644 --- a/usr/src/test/os-tests/tests/poll/Makefile +++ b/usr/src/test/os-tests/tests/poll/Makefile @@ -21,7 +21,8 @@ PROG = poll_test epoll_test OBJS = $(PROG:%=%.o) SRCS = $(OBJS:%.o=%.c) -LDLIBS += -lsocket +poll_test := LDLIBS += -lsocket +poll_test.ln := LDLIBS += -lsocket C99MODE = -xc99=%all ROOTOPTPKG = $(ROOT)/opt/os-tests @@ -30,11 +31,13 @@ TESTDIR = $(ROOTOPTPKG)/tests CMDS = $(PROG:%=$(TESTDIR)/%) $(CMDS) := FILEMODE = 0555 +LINTS = $(PROG:%=%.ln) + all: $(PROG) install: all $(CMDS) -lint: lint_SRCS +lint: $(LINTS) clobber: clean -$(RM) $(PROG) @@ -42,6 +45,9 @@ clobber: clean clean: -$(RM) $(OBJS) +%.ln: %.c + $(LINT.c) $< $(UTILS) $(LDLIBS) + $(CMDS): $(TESTDIR) $(PROG) $(TESTDIR): diff --git a/usr/src/test/zfs-tests/include/default.cfg b/usr/src/test/zfs-tests/include/default.cfg index 84ac02b524..8747963bfa 100644 --- a/usr/src/test/zfs-tests/include/default.cfg +++ b/usr/src/test/zfs-tests/include/default.cfg @@ -65,42 +65,47 @@ export FIO_SCRIPTS=$STF_SUITE/tests/perf/fio export PERF_SCRIPTS=$STF_SUITE/tests/perf/scripts # some test pool names -export TESTPOOL=testpool.$$ -export TESTPOOL1=testpool1.$$ -export TESTPOOL2=testpool2.$$ -export TESTPOOL3=testpool3.$$ +export TESTPOOL=testpool +export TESTPOOL1=testpool1 +export TESTPOOL2=testpool2 +export TESTPOOL3=testpool3 export PERFPOOL=perfpool # some test file system names -export TESTFS=testfs.$$ -export TESTFS1=testfs1.$$ -export TESTFS2=testfs2.$$ -export TESTFS3=testfs3.$$ +export TESTFS=testfs +export TESTFS1=testfs1 +export TESTFS2=testfs2 +export TESTFS3=testfs3 # some test directory names -export TESTDIR=${TEST_BASE_DIR%%/}/testdir$$ -export TESTDIR0=${TEST_BASE_DIR%%/}/testdir0$$ -export TESTDIR1=${TEST_BASE_DIR%%/}/testdir1$$ -export TESTDIR2=${TEST_BASE_DIR%%/}/testdir2$$ +export TESTDIR=${TEST_BASE_DIR%%/}/testdir +export TESTDIR0=${TEST_BASE_DIR%%/}/testdir0 +export TESTDIR1=${TEST_BASE_DIR%%/}/testdir1 +export TESTDIR2=${TEST_BASE_DIR%%/}/testdir2 + +# some test sub file system names +export TESTSUBFS=subfs +export TESTSUBFS1=subfs1 +export TESTSUBFS2=subfs2 export ZFSROOT= -export TESTSNAP=testsnap$$ -export TESTSNAP1=testsnap1$$ -export TESTSNAP2=testsnap2$$ -export TESTCLONE=testclone$$ -export TESTCLONE1=testclone1$$ -export TESTCLONE2=testclone2$$ -export TESTCLCT=testclct$$ -export TESTCTR=testctr$$ -export TESTCTR1=testctr1$$ -export TESTCTR2=testctr2$$ -export TESTVOL=testvol$$ -export TESTVOL1=testvol1$$ -export TESTVOL2=testvol2$$ -export TESTFILE0=testfile0.$$ -export TESTFILE1=testfile1.$$ -export TESTFILE2=testfile2.$$ +export TESTSNAP=testsnap +export TESTSNAP1=testsnap1 +export TESTSNAP2=testsnap2 +export TESTCLONE=testclone +export TESTCLONE1=testclone1 +export TESTCLONE2=testclone2 +export TESTCLCT=testclct +export TESTCTR=testctr +export TESTCTR1=testctr1 +export TESTCTR2=testctr2 +export TESTVOL=testvol +export TESTVOL1=testvol1 +export TESTVOL2=testvol2 +export TESTFILE0=testfile0 +export TESTFILE1=testfile1 +export TESTFILE2=testfile2 export LONGPNAME="poolname50charslong_012345678901234567890123456789" export LONGFSNAME="fsysname50charslong_012345678901234567890123456789" diff --git a/usr/src/test/zfs-tests/tests/functional/acl/nontrivial/zfs_acl_chmod_aclmode_001_pos.ksh b/usr/src/test/zfs-tests/tests/functional/acl/nontrivial/zfs_acl_chmod_aclmode_001_pos.ksh index 85d0412abf..764bc879fd 100644 --- a/usr/src/test/zfs-tests/tests/functional/acl/nontrivial/zfs_acl_chmod_aclmode_001_pos.ksh +++ b/usr/src/test/zfs-tests/tests/functional/acl/nontrivial/zfs_acl_chmod_aclmode_001_pos.ksh @@ -476,8 +476,6 @@ typeset acl typeset target typeset -i passthrough=0 typeset -i flag=0 -cwd=$PWD -cd $TESTDIR for mode in "${aclmode_flag[@]}"; do log_must zfs set aclmode=$mode $TESTPOOL/$TESTFS diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_007_pos.ksh b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_007_pos.ksh index 35644f4f55..2b99089e09 100644 --- a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_007_pos.ksh +++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_send/zfs_send_007_pos.ksh @@ -42,7 +42,7 @@ function cleanup zfs destroy -rf $TESTPOOL/recvfs rm $streamfile rm $vdev - zpool destroy testpool + zpool destroy tmp_pool } @@ -88,12 +88,11 @@ test_pool () test_pool $TESTPOOL log_must truncate --size=1G $vdev -log_must zpool create -o version=1 testpool $vdev -test_pool testpool -log_must zpool destroy testpool -log_must zpool create -d testpool $vdev -test_pool testpool -log_must zpool destroy testpool - +log_must zpool create -o version=1 tmp_pool $vdev +test_pool tmp_pool +log_must zpool destroy tmp_pool +log_must zpool create -d tmp_pool $vdev +test_pool tmp_pool +log_must zpool destroy tmp_pool log_pass "'zfs send' drills appropriate holes" diff --git a/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_rename_001_pos.ksh b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_rename_001_pos.ksh index ea4ea0caf8..6d8db3b674 100644 --- a/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_rename_001_pos.ksh +++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zpool_import/zpool_import_rename_001_pos.ksh @@ -164,10 +164,11 @@ done VDEV_FILE=$(mktemp /tmp/tmp.XXXXXX) log_must mkfile -n 128M $VDEV_FILE -log_must zpool create testpool $VDEV_FILE -log_must zfs create testpool/testfs -ID=$(zpool get -Ho value guid testpool) -log_must zpool export testpool -log_mustnot zpool import $(echo id) $(printf "%*s\n" 250 "" | tr ' ' 'c') +log_must zpool create overflow $VDEV_FILE +log_must zfs create overflow/testfs +ID=$(zpool get -Ho value guid overflow) +log_must zpool export overflow +log_mustnot zpool import -d /tmp $(echo id) \ + $(printf "%*s\n" 250 "" | tr ' ' 'c') log_pass "Successfully imported and renamed a ZPOOL" diff --git a/usr/src/test/zfs-tests/tests/functional/rsend/cleanup.ksh b/usr/src/test/zfs-tests/tests/functional/rsend/cleanup.ksh index 14e15fd963..a3141c74e4 100644 --- a/usr/src/test/zfs-tests/tests/functional/rsend/cleanup.ksh +++ b/usr/src/test/zfs-tests/tests/functional/rsend/cleanup.ksh @@ -36,9 +36,11 @@ verify_runnable "both" if is_global_zone ; then destroy_pool $POOL destroy_pool $POOL2 + poolexists $POOL3 && destroy_pool $POOL3 else cleanup_pool $POOL cleanup_pool $POOL2 + poolexists $POOL3 && cleanup_pool $POOL3 fi log_must rm -rf $BACKDIR $TESTDIR diff --git a/usr/src/test/zfs-tests/tests/functional/rsend/rsend.cfg b/usr/src/test/zfs-tests/tests/functional/rsend/rsend.cfg index 564b0a4b6b..2c1654e089 100644 --- a/usr/src/test/zfs-tests/tests/functional/rsend/rsend.cfg +++ b/usr/src/test/zfs-tests/tests/functional/rsend/rsend.cfg @@ -31,7 +31,9 @@ export BACKDIR=${TEST_BASE_DIR%%/}/backdir-rsend export DISK1=$(echo $DISKS | awk '{print $1}') export DISK2=$(echo $DISKS | awk '{print $2}') +export DISK3=$(echo $DISKS | awk '{print $3}') export POOL=$TESTPOOL export POOL2=$TESTPOOL1 +export POOL3=$TESTPOOL2 export FS=$TESTFS diff --git a/usr/src/test/zfs-tests/tests/functional/rsend/rsend.kshlib b/usr/src/test/zfs-tests/tests/functional/rsend/rsend.kshlib index 60e51dd19a..da5b7cb3a4 100644 --- a/usr/src/test/zfs-tests/tests/functional/rsend/rsend.kshlib +++ b/usr/src/test/zfs-tests/tests/functional/rsend/rsend.kshlib @@ -118,7 +118,7 @@ function cleanup_pool if is_global_zone ; then log_must zfs destroy -Rf $pool else - typeset list=$(zfs list -H -r -t filesystem,snapshot,volume -o name $pool) + typeset list=$(zfs list -H -r -t all -o name $pool) for ds in $list ; do if [[ $ds != $pool ]] ; then if datasetexists $ds ; then @@ -138,12 +138,18 @@ function cleanup_pool log_must zfs mount $pool fi if [[ -d $mntpnt ]]; then - log_must rm -rf $mntpnt/* + rm -rf $mntpnt/* fi return 0 } +function cleanup_pools +{ + cleanup_pool $POOL2 + destroy_pool $POOL3 +} + # # Detect if the given two filesystems have same sub-datasets # @@ -155,8 +161,8 @@ function cmp_ds_subs typeset src_fs=$1 typeset dst_fs=$2 - zfs list -r -H -t filesystem,snapshot,volume -o name $src_fs > $BACKDIR/src1 - zfs list -r -H -t filesystem,snapshot,volume -o name $dst_fs > $BACKDIR/dst1 + zfs list -r -H -t all -o name $src_fs > $BACKDIR/src1 + zfs list -r -H -t all -o name $dst_fs > $BACKDIR/dst1 eval sed -e 's:^$src_fs:PREFIX:g' < $BACKDIR/src1 > $BACKDIR/src eval sed -e 's:^$dst_fs:PREFIX:g' < $BACKDIR/dst1 > $BACKDIR/dst @@ -322,8 +328,7 @@ function getds_with_suffix typeset ds=$1 typeset suffix=$2 - typeset list=$(zfs list -r -H -t filesystem,snapshot,volume -o name $ds \ - | grep "$suffix$") + typeset list=$(zfs list -r -H -t all -o name $ds | grep "$suffix$") echo $list } @@ -485,7 +490,7 @@ function resume_test for ((i=0; i<2; i=i+1)); do mess_file /$streamfs/$stream_num - log_mustnot zfs recv -sv $recvfs </$streamfs/$stream_num + log_mustnot zfs recv -suv $recvfs </$streamfs/$stream_num stream_num=$((stream_num+1)) token=$(zfs get -Hp -o value receive_resume_token $recvfs) @@ -493,31 +498,26 @@ function resume_test [[ -f /$streamfs/$stream_num ]] || \ log_fail "NO FILE /$streamfs/$stream_num" done - log_must zfs recv -sv $recvfs </$streamfs/$stream_num + log_must zfs recv -suv $recvfs </$streamfs/$stream_num } # # Setup filesystems for the resumable send/receive tests # -# $1 The pool to set up with the "send" filesystems -# $2 The pool for receive +# $1 The "send" filesystem +# $2 The "recv" filesystem # function test_fs_setup { - sendpool=$1 - recvpool=$2 + typeset sendfs=$1 + typeset recvfs=$2 + typeset sendpool=${sendfs%%/*} + typeset recvpool=${recvfs%%/*} - sendfs=$sendpool/sendfs - recvfs=$recvpool/recvfs - streamfs=$sendpool/stream + datasetexists $sendfs && log_must $ZFS destroy -r $sendpool + datasetexists $recvfs && log_must $ZFS destroy -r $recvpool - if datasetexists $recvfs; then - log_must zfs destroy -r $recvfs - fi - if datasetexists $sendfs; then - log_must zfs destroy -r $sendfs - fi - if $(zfs create -o compress=lz4 $sendfs); then + if $(datasetexists $sendfs || zfs create -o compress=lz4 $sendfs); then mk_files 1000 256 0 $sendfs & mk_files 1000 131072 0 $sendfs & mk_files 100 1048576 0 $sendfs & diff --git a/usr/src/test/zfs-tests/tests/functional/rsend/rsend_019_pos.ksh b/usr/src/test/zfs-tests/tests/functional/rsend/rsend_019_pos.ksh index 45d3d6b9f6..d6a5fa2b75 100644 --- a/usr/src/test/zfs-tests/tests/functional/rsend/rsend_019_pos.ksh +++ b/usr/src/test/zfs-tests/tests/functional/rsend/rsend_019_pos.ksh @@ -30,22 +30,24 @@ # 4. ZFS send to the stream state file again using the receive_resume_token # 5. ZFS receieve and verify the receive completes successfully # 6. Repeat steps on an incremental ZFS send +# 7. Repeat the entire procedure for a dataset at the pool root # verify_runnable "both" log_assert "Verify resumability of a full and incremental ZFS send/receive " \ "in the presence of a corrupted stream" -log_onexit cleanup_pool $POOL2 +log_onexit cleanup_pools $POOL2 $POOL3 -sendfs=$POOL/sendfs -recvfs=$POOL2/recvfs -streamfs=$POOL/stream +recvfs=$POOL3/recvfs +streamfs=$POOL2/stream -test_fs_setup $POOL $POOL2 -resume_test "zfs send -v $sendfs@a" $streamfs $recvfs -resume_test "zfs send -v -i @a $sendfs@b" $streamfs $recvfs -file_check $sendfs $recvfs +for sendfs in $POOL2/sendfs $POOL2; do + test_fs_setup $sendfs $recvfs + resume_test "zfs send -v $sendfs@a" $streamfs $recvfs + resume_test "zfs send -v -i @a $sendfs@b" $streamfs $recvfs + file_check $sendfs $recvfs +done log_pass "Verify resumability of a full and incremental ZFS send/receive " \ "in the presence of a corrupted stream" diff --git a/usr/src/test/zfs-tests/tests/functional/rsend/rsend_020_pos.ksh b/usr/src/test/zfs-tests/tests/functional/rsend/rsend_020_pos.ksh index 0d1f8330a5..1dcbdace8e 100644 --- a/usr/src/test/zfs-tests/tests/functional/rsend/rsend_020_pos.ksh +++ b/usr/src/test/zfs-tests/tests/functional/rsend/rsend_020_pos.ksh @@ -41,7 +41,7 @@ sendfs=$POOL/sendfs recvfs=$POOL2/recvfs streamfs=$POOL/stream -test_fs_setup $POOL $POOL2 +test_fs_setup $sendfs $recvfs resume_test "zfs send -D -v $sendfs@a" $streamfs $recvfs file_check $sendfs $recvfs diff --git a/usr/src/test/zfs-tests/tests/functional/rsend/rsend_021_pos.ksh b/usr/src/test/zfs-tests/tests/functional/rsend/rsend_021_pos.ksh index f95f88439b..8fb0abb7a5 100644 --- a/usr/src/test/zfs-tests/tests/functional/rsend/rsend_021_pos.ksh +++ b/usr/src/test/zfs-tests/tests/functional/rsend/rsend_021_pos.ksh @@ -43,7 +43,7 @@ sendfs=$POOL/sendfs recvfs=$POOL2/recvfs streamfs=$POOL/stream -test_fs_setup $POOL $POOL2 +test_fs_setup $sendfs $recvfs resume_test "zfs send -v -e $sendfs@a" $streamfs $recvfs resume_test "zfs send -v -e -i @a $sendfs@b" $streamfs $recvfs file_check $sendfs $recvfs diff --git a/usr/src/test/zfs-tests/tests/functional/rsend/rsend_022_pos.ksh b/usr/src/test/zfs-tests/tests/functional/rsend/rsend_022_pos.ksh index cd042558c1..3fdb049422 100644 --- a/usr/src/test/zfs-tests/tests/functional/rsend/rsend_022_pos.ksh +++ b/usr/src/test/zfs-tests/tests/functional/rsend/rsend_022_pos.ksh @@ -46,7 +46,7 @@ sendfs=$POOL/sendfs recvfs=$POOL2/recvfs streamfs=$POOL/stream -test_fs_setup $POOL $POOL2 +test_fs_setup $sendfs $recvfs log_must zfs bookmark $sendfs@a $sendfs#bm_a log_must zfs destroy $sendfs@a log_must zfs receive -v $recvfs </$POOL/initial.zsend diff --git a/usr/src/test/zfs-tests/tests/functional/rsend/rsend_024_pos.ksh b/usr/src/test/zfs-tests/tests/functional/rsend/rsend_024_pos.ksh index e87a628d32..62fba64589 100644 --- a/usr/src/test/zfs-tests/tests/functional/rsend/rsend_024_pos.ksh +++ b/usr/src/test/zfs-tests/tests/functional/rsend/rsend_024_pos.ksh @@ -43,7 +43,7 @@ sendfs=$POOL/sendfs recvfs=$POOL2/recvfs streamfs=$POOL/stream -test_fs_setup $POOL $POOL2 +test_fs_setup $sendfs $recvfs log_must zfs unmount $sendfs resume_test "zfs send $sendfs" $streamfs $recvfs file_check $sendfs $recvfs diff --git a/usr/src/test/zfs-tests/tests/functional/rsend/setup.ksh b/usr/src/test/zfs-tests/tests/functional/rsend/setup.ksh index a4479b4265..7707b81604 100644 --- a/usr/src/test/zfs-tests/tests/functional/rsend/setup.ksh +++ b/usr/src/test/zfs-tests/tests/functional/rsend/setup.ksh @@ -37,6 +37,7 @@ verify_disk_count "$DISKS" 2 if is_global_zone ; then log_must zpool create $POOL $DISK1 log_must zpool create $POOL2 $DISK2 + log_must zpool create $POOL3 $DISK3 fi log_must mkdir $BACKDIR $TESTDIR diff --git a/usr/src/uts/intel/io/vmxnet3s/README.txt b/usr/src/uts/intel/io/vmxnet3s/README.txt index 7539907a63..79bf666a64 100644 --- a/usr/src/uts/intel/io/vmxnet3s/README.txt +++ b/usr/src/uts/intel/io/vmxnet3s/README.txt @@ -1,4 +1,6 @@ # +# CDDL HEADER START +# # This file and its contents are supplied under the terms of the # Common Development and Distribution License ("CDDL"), version 1.0. # You may only use this file in accordance with the terms of version @@ -8,24 +10,25 @@ # source. A copy of the CDDL is also available via the Internet at # http://www.illumos.org/license/CDDL. # - +# CDDL HEADER END # -# Copyright (c) 2012 by Delphix. All rights reserved. +# Copyright (c) 2012, 2016 by Delphix. All rights reserved. # The vmxnet3s driver is a paravirtualized GLDv3 NIC driver designed to -be used on VMware virtual machines version 7 and later. - -This version of the driver was initially based on the "stable-8.6.x" branch -of the VMware open-vm-tools which can be obtained from: +be used on VMware virtual machines version 7 and later. This version +of the driver is based on the "stable-10.0.x" branch of the VMware +open-vm-tools which can be obtained from: https://github.com/vmware/open-vm-tools -Current changes include: +Changes from stable-10.0.x include: -* cstyle and lint cleanup: the driver is lint clean with two categorical +* add support for VLANs +* enable building in the illumos gate +* enable building with the Sun Studio compiler +* lint cleanup: the driver is lint clean with two categorical exceptions for which warnings are disabled in the Makefile -* added support for dladm mtu property -* added support for VLANs -* LSO fix contributed by Michael Tsymbalyuk <mtzaurus@gmail.com> +The driver remains in the original C style to facilitate potential +future synchronization with upstream. diff --git a/usr/src/uts/intel/io/vmxnet3s/vmxnet3.h b/usr/src/uts/intel/io/vmxnet3s/vmxnet3.h index c6250cdf09..039c0f2e11 100644 --- a/usr/src/uts/intel/io/vmxnet3s/vmxnet3.h +++ b/usr/src/uts/intel/io/vmxnet3s/vmxnet3.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 VMware, Inc. All rights reserved. + * Copyright (C) 2007-2014 VMware, Inc. All rights reserved. * * The contents of this file are subject to the terms of the Common * Development and Distribution License (the "License") version 1.0 @@ -14,7 +14,7 @@ */ /* - * Copyright (c) 2012 by Delphix. All rights reserved. + * Copyright (c) 2012, 2016 by Delphix. All rights reserved. */ #ifndef _VMXNET3_H_ @@ -127,6 +127,7 @@ typedef struct vmxnet3_softc_t { boolean_t devEnabled; uint8_t macaddr[6]; uint32_t cur_mtu; + boolean_t allow_jumbo; link_state_t linkState; uint64_t linkSpeed; vmxnet3_dmabuf_t sharedData; @@ -147,8 +148,8 @@ typedef struct vmxnet3_softc_t { vmxnet3_rxqueue_t rxQueue; kmutex_t rxPoolLock; vmxnet3_rxpool_t rxPool; - volatile uint32_t rxNumBufs; uint32_t rxMode; + boolean_t alloc_ok; vmxnet3_dmabuf_t mfTable; kstat_t *devKstats; @@ -157,8 +158,10 @@ typedef struct vmxnet3_softc_t { uint32_t tx_pullup_failed; uint32_t tx_ring_full; uint32_t tx_error; + uint32_t rx_num_bufs; uint32_t rx_alloc_buf; uint32_t rx_alloc_failed; + uint32_t rx_pool_empty; } vmxnet3_softc_t; typedef struct vmxnet3_kstats_t { @@ -166,8 +169,11 @@ typedef struct vmxnet3_kstats_t { kstat_named_t tx_pullup_needed; kstat_named_t tx_ring_full; kstat_named_t rx_alloc_buf; + kstat_named_t rx_pool_empty; + kstat_named_t rx_num_bufs; } vmxnet3_kstats_t; +int vmxnet3_dmaerr2errno(int); int vmxnet3_alloc_dma_mem_1(vmxnet3_softc_t *dp, vmxnet3_dmabuf_t *dma, size_t size, boolean_t canSleep); int vmxnet3_alloc_dma_mem_128(vmxnet3_softc_t *dp, vmxnet3_dmabuf_t *dma, @@ -192,13 +198,14 @@ extern ddi_device_acc_attr_t vmxnet3_dev_attr; extern int vmxnet3s_debug; -#define VMXNET3_MODNAME "vmxnet3s" +#define VMXNET3_MODNAME "vmxnet3s" +#define VMXNET3_DRIVER_VERSION_STRING "1.1.0.0" /* Logging stuff */ #define VMXNET3_WARN(Device, ...) vmxnet3_log(CE_WARN, Device, __VA_ARGS__) #ifdef DEBUG -#define VMXNET3_DEBUG(Device, Level, ...) { \ +#define VMXNET3_DEBUG(Device, Level, ...) { \ if (Level <= vmxnet3s_debug) { \ vmxnet3_log(CE_CONT, Device, "?" __VA_ARGS__); \ } \ diff --git a/usr/src/uts/intel/io/vmxnet3s/vmxnet3_defs.h b/usr/src/uts/intel/io/vmxnet3s/vmxnet3_defs.h index 8ef59990cf..4dfac84e77 100644 --- a/usr/src/uts/intel/io/vmxnet3s/vmxnet3_defs.h +++ b/usr/src/uts/intel/io/vmxnet3s/vmxnet3_defs.h @@ -31,7 +31,7 @@ #define VMXNET3_REG_UVRS 0x8 /* UPT Version Report Selection */ #define VMXNET3_REG_DSAL 0x10 /* Driver Shared Address Low */ #define VMXNET3_REG_DSAH 0x18 /* Driver Shared Address High */ -#define VMXNET3_REG_CMD 0x20 /* Command */ +#define VMXNET3_REG_CMD 0x20 /* Command */ #define VMXNET3_REG_MACL 0x28 /* MAC Address Low */ #define VMXNET3_REG_MACH 0x30 /* MAC Address High */ #define VMXNET3_REG_ICR 0x38 /* Interrupt Cause Register */ diff --git a/usr/src/uts/intel/io/vmxnet3s/vmxnet3_main.c b/usr/src/uts/intel/io/vmxnet3s/vmxnet3_main.c index 2b54baf799..612dc052f1 100644 --- a/usr/src/uts/intel/io/vmxnet3s/vmxnet3_main.c +++ b/usr/src/uts/intel/io/vmxnet3s/vmxnet3_main.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 VMware, Inc. All rights reserved. + * Copyright (C) 2007-2014 VMware, Inc. All rights reserved. * * The contents of this file are subject to the terms of the Common * Development and Distribution License (the "License") version 1.0 @@ -14,25 +14,31 @@ */ /* - * Copyright (c) 2012, 2014 by Delphix. All rights reserved. + * Copyright (c) 2012, 2016 by Delphix. All rights reserved. */ #include <vmxnet3.h> -#define BUILD_NUMBER_NUMERIC 20160330 -#define BUILD_NUMBER_NUMERIC_STRING "20160330" +/* + * This driver is based on VMware's version 3227872, and contains additional + * enhancements (see README.txt). + */ +#define BUILD_NUMBER_NUMERIC 3227872 + +/* + * If we run out of rxPool buffers, only allocate if the MTU is <= PAGESIZE + * so that we don't have to incur the cost of allocating multiple contiguous + * pages (very slow) in interrupt context. + */ +#define VMXNET3_ALLOC_OK(dp) ((dp)->cur_mtu <= PAGESIZE) /* * TODO: * - Tx data ring * - MAC_CAPAB_POLL support - * - JF support * - Dynamic RX pool */ -/* - * Forward declarations - */ static int vmxnet3_getstat(void *, uint_t, uint64_t *); static int vmxnet3_start(void *); static void vmxnet3_stop(void *); @@ -41,9 +47,11 @@ static void vmxnet3_ioctl(void *arg, queue_t *wq, mblk_t *mp); static int vmxnet3_multicst(void *, boolean_t, const uint8_t *); static int vmxnet3_unicst(void *, const uint8_t *); static boolean_t vmxnet3_getcapab(void *, mac_capab_t, void *); -static int vmxnet3_setmacprop(void *, const char *, mac_prop_id_t, uint_t, +static int vmxnet3_get_prop(void *, const char *, mac_prop_id_t, uint_t, + void *); +static int vmxnet3_set_prop(void *, const char *, mac_prop_id_t, uint_t, const void *); -static void vmxnet3_macpropinfo(void *, const char *, mac_prop_id_t, +static void vmxnet3_prop_info(void *, const char *, mac_prop_id_t, mac_prop_info_handle_t); int vmxnet3s_debug = 0; @@ -60,8 +68,9 @@ static mac_callbacks_t vmxnet3_mac_callbacks = { .mc_tx = vmxnet3_tx, .mc_ioctl = vmxnet3_ioctl, .mc_getcapab = vmxnet3_getcapab, - .mc_setprop = vmxnet3_setmacprop, - .mc_propinfo = vmxnet3_macpropinfo + .mc_getprop = vmxnet3_get_prop, + .mc_setprop = vmxnet3_set_prop, + .mc_propinfo = vmxnet3_prop_info }; /* Tx DMA engine description */ @@ -83,15 +92,10 @@ static ddi_dma_attr_t vmxnet3_dma_attrs_tx = { /* --- */ /* - * vmxnet3_getstat -- + * Fetch the statistics of a vmxnet3 device. * - * Fetch the statistics of a vmxnet3 device. - * - * Results: - * DDI_FAILURE. - * - * Side effects: - * None. + * Returns: + * 0 on success, non-zero on failure. */ static int vmxnet3_getstat(void *data, uint_t stat, uint64_t *val) @@ -103,7 +107,7 @@ vmxnet3_getstat(void *data, uint_t stat, uint64_t *val) VMXNET3_DEBUG(dp, 3, "getstat(%u)\n", stat); if (!dp->devEnabled) { - return (DDI_FAILURE); + return (EBUSY); } txStats = &VMXNET3_TQDESC(dp)->stats; @@ -133,7 +137,7 @@ vmxnet3_getstat(void *data, uint_t stat, uint64_t *val) /* nothing */ break; default: - return (DDI_FAILURE); + return (ENOTSUP); } /* @@ -193,39 +197,34 @@ vmxnet3_getstat(void *data, uint_t stat, uint64_t *val) ASSERT(B_FALSE); } - return (DDI_SUCCESS); + return (0); } /* - * vmxnet3_prepare_drivershared -- - * - * Allocate and initialize the shared data structures - * of a vmxnet3 device. - * - * Results: - * DDI_SUCCESS or DDI_FAILURE. + * Allocate and initialize the shared data structures of a vmxnet3 device. * - * Side effects: - * None. + * Returns: + * 0 on sucess, non-zero on failure. */ static int vmxnet3_prepare_drivershared(vmxnet3_softc_t *dp) { Vmxnet3_DriverShared *ds; size_t allocSize = sizeof (Vmxnet3_DriverShared); + int err; - if (vmxnet3_alloc_dma_mem_1(dp, &dp->sharedData, allocSize, - B_TRUE) != DDI_SUCCESS) { - return (DDI_FAILURE); + if ((err = vmxnet3_alloc_dma_mem_1(dp, &dp->sharedData, allocSize, + B_TRUE)) != 0) { + return (err); } ds = VMXNET3_DS(dp); (void) memset(ds, 0, allocSize); allocSize = sizeof (Vmxnet3_TxQueueDesc) + sizeof (Vmxnet3_RxQueueDesc); - if (vmxnet3_alloc_dma_mem_128(dp, &dp->queueDescs, allocSize, - B_TRUE) != DDI_SUCCESS) { + if ((err = vmxnet3_alloc_dma_mem_128(dp, &dp->queueDescs, allocSize, + B_TRUE)) != 0) { vmxnet3_free_dma_mem(&dp->sharedData); - return (DDI_FAILURE); + return (err); } (void) memset(dp->queueDescs.buf, 0, allocSize); @@ -263,19 +262,11 @@ vmxnet3_prepare_drivershared(vmxnet3_softc_t *dp) VMXNET3_BAR1_PUT32(dp, VMXNET3_REG_DSAH, VMXNET3_ADDR_HI(dp->sharedData.bufPA)); - return (DDI_SUCCESS); + return (0); } /* - * vmxnet3_destroy_drivershared -- - * - * Destroy the shared data structures of a vmxnet3 device. - * - * Results: - * None. - * - * Side effects: - * None. + * Destroy the shared data structures of a vmxnet3 device. */ static void vmxnet3_destroy_drivershared(vmxnet3_softc_t *dp) @@ -288,43 +279,34 @@ vmxnet3_destroy_drivershared(vmxnet3_softc_t *dp) } /* - * vmxnet3_alloc_cmdring -- + * Allocate and initialize the command ring of a queue. * - * Allocate and initialize the command ring of a queue. - * - * Results: - * DDI_SUCCESS or DDI_FAILURE. - * - * Side effects: - * None. + * Returns: + * 0 on success, non-zero on error. */ static int vmxnet3_alloc_cmdring(vmxnet3_softc_t *dp, vmxnet3_cmdring_t *cmdRing) { size_t ringSize = cmdRing->size * sizeof (Vmxnet3_TxDesc); + int err; - if (vmxnet3_alloc_dma_mem_512(dp, &cmdRing->dma, ringSize, - B_TRUE) != DDI_SUCCESS) { - return (DDI_FAILURE); + if ((err = vmxnet3_alloc_dma_mem_512(dp, &cmdRing->dma, ringSize, + B_TRUE)) != 0) { + return (err); } (void) memset(cmdRing->dma.buf, 0, ringSize); cmdRing->avail = cmdRing->size; cmdRing->next2fill = 0; cmdRing->gen = VMXNET3_INIT_GEN; - return (DDI_SUCCESS); + return (0); } /* - * vmxnet3_alloc_compring -- + * Allocate and initialize the completion ring of a queue. * - * Allocate and initialize the completion ring of a queue. - * - * Results: + * Returns: * DDI_SUCCESS or DDI_FAILURE. - * - * Side effects: - * None. */ static int vmxnet3_alloc_compring(vmxnet3_softc_t *dp, vmxnet3_compring_t *compRing) @@ -343,27 +325,23 @@ vmxnet3_alloc_compring(vmxnet3_softc_t *dp, vmxnet3_compring_t *compRing) } /* - * vmxnet3_prepare_txqueue -- + * Initialize the tx queue of a vmxnet3 device. * - * Initialize the tx queue of a vmxnet3 device. - * - * Results: - * DDI_SUCCESS or DDI_FAILURE. - * - * Side effects: - * None. + * Returns: + * 0 on success, non-zero on failure. */ static int vmxnet3_prepare_txqueue(vmxnet3_softc_t *dp) { Vmxnet3_TxQueueDesc *tqdesc = VMXNET3_TQDESC(dp); vmxnet3_txqueue_t *txq = &dp->txQueue; + int err; ASSERT(!(txq->cmdRing.size & VMXNET3_RING_SIZE_MASK)); ASSERT(!(txq->compRing.size & VMXNET3_RING_SIZE_MASK)); ASSERT(!txq->cmdRing.dma.buf && !txq->compRing.dma.buf); - if (vmxnet3_alloc_cmdring(dp, &txq->cmdRing) != DDI_SUCCESS) { + if ((err = vmxnet3_alloc_cmdring(dp, &txq->cmdRing)) != 0) { goto error; } tqdesc->conf.txRingBasePA = txq->cmdRing.dma.bufPA; @@ -371,7 +349,7 @@ vmxnet3_prepare_txqueue(vmxnet3_softc_t *dp) tqdesc->conf.dataRingBasePA = 0; tqdesc->conf.dataRingSize = 0; - if (vmxnet3_alloc_compring(dp, &txq->compRing) != DDI_SUCCESS) { + if ((err = vmxnet3_alloc_compring(dp, &txq->compRing)) != 0) { goto error_cmdring; } tqdesc->conf.compRingBasePA = txq->compRing.dma.bufPA; @@ -381,11 +359,11 @@ vmxnet3_prepare_txqueue(vmxnet3_softc_t *dp) sizeof (vmxnet3_metatx_t), KM_SLEEP); ASSERT(txq->metaRing); - if (vmxnet3_txqueue_init(dp, txq) != DDI_SUCCESS) { + if ((err = vmxnet3_txqueue_init(dp, txq)) != 0) { goto error_mpring; } - return (DDI_SUCCESS); + return (0); error_mpring: kmem_free(txq->metaRing, txq->cmdRing.size * sizeof (vmxnet3_metatx_t)); @@ -393,31 +371,27 @@ error_mpring: error_cmdring: vmxnet3_free_dma_mem(&txq->cmdRing.dma); error: - return (DDI_FAILURE); + return (err); } /* - * vmxnet3_prepare_rxqueue -- + * Initialize the rx queue of a vmxnet3 device. * - * Initialize the rx queue of a vmxnet3 device. - * - * Results: - * DDI_SUCCESS or DDI_FAILURE. - * - * Side effects: - * None. + * Returns: + * 0 on success, non-zero on failure. */ static int vmxnet3_prepare_rxqueue(vmxnet3_softc_t *dp) { Vmxnet3_RxQueueDesc *rqdesc = VMXNET3_RQDESC(dp); vmxnet3_rxqueue_t *rxq = &dp->rxQueue; + int err = 0; ASSERT(!(rxq->cmdRing.size & VMXNET3_RING_SIZE_MASK)); ASSERT(!(rxq->compRing.size & VMXNET3_RING_SIZE_MASK)); ASSERT(!rxq->cmdRing.dma.buf && !rxq->compRing.dma.buf); - if (vmxnet3_alloc_cmdring(dp, &rxq->cmdRing) != DDI_SUCCESS) { + if ((err = vmxnet3_alloc_cmdring(dp, &rxq->cmdRing)) != 0) { goto error; } rqdesc->conf.rxRingBasePA[0] = rxq->cmdRing.dma.bufPA; @@ -425,7 +399,7 @@ vmxnet3_prepare_rxqueue(vmxnet3_softc_t *dp) rqdesc->conf.rxRingBasePA[1] = 0; rqdesc->conf.rxRingSize[1] = 0; - if (vmxnet3_alloc_compring(dp, &rxq->compRing) != DDI_SUCCESS) { + if ((err = vmxnet3_alloc_compring(dp, &rxq->compRing)) != 0) { goto error_cmdring; } rqdesc->conf.compRingBasePA = rxq->compRing.dma.bufPA; @@ -435,11 +409,11 @@ vmxnet3_prepare_rxqueue(vmxnet3_softc_t *dp) sizeof (vmxnet3_bufdesc_t), KM_SLEEP); ASSERT(rxq->bufRing); - if (vmxnet3_rxqueue_init(dp, rxq) != DDI_SUCCESS) { + if ((err = vmxnet3_rxqueue_init(dp, rxq)) != 0) { goto error_bufring; } - return (DDI_SUCCESS); + return (0); error_bufring: kmem_free(rxq->bufRing, rxq->cmdRing.size * sizeof (vmxnet3_bufdesc_t)); @@ -447,19 +421,11 @@ error_bufring: error_cmdring: vmxnet3_free_dma_mem(&rxq->cmdRing.dma); error: - return (DDI_FAILURE); + return (err); } /* - * vmxnet3_destroy_txqueue -- - * - * Destroy the tx queue of a vmxnet3 device. - * - * Results: - * None. - * - * Side effects: - * None. + * Destroy the tx queue of a vmxnet3 device. */ static void vmxnet3_destroy_txqueue(vmxnet3_softc_t *dp) @@ -478,15 +444,7 @@ vmxnet3_destroy_txqueue(vmxnet3_softc_t *dp) } /* - * vmxnet3_destroy_rxqueue -- - * - * Destroy the rx queue of a vmxnet3 device. - * - * Results: - * None. - * - * Side effects: - * None. + * Destroy the rx queue of a vmxnet3 device. */ static void vmxnet3_destroy_rxqueue(vmxnet3_softc_t *dp) @@ -505,15 +463,7 @@ vmxnet3_destroy_rxqueue(vmxnet3_softc_t *dp) } /* - * vmxnet3_refresh_rxfilter -- - * - * Apply new RX filters settings to a vmxnet3 device. - * - * Results: - * None. - * - * Side effects: - * None. + * Apply new RX filters settings to a vmxnet3 device. */ static void vmxnet3_refresh_rxfilter(vmxnet3_softc_t *dp) @@ -525,15 +475,7 @@ vmxnet3_refresh_rxfilter(vmxnet3_softc_t *dp) } /* - * vmxnet3_refresh_linkstate -- - * - * Fetch the link state of a vmxnet3 device. - * - * Results: - * None. - * - * Side effects: - * None. + * Fetch the link state of a vmxnet3 device. */ static void vmxnet3_refresh_linkstate(vmxnet3_softc_t *dp) @@ -552,16 +494,11 @@ vmxnet3_refresh_linkstate(vmxnet3_softc_t *dp) } /* - * vmxnet3_start -- - * - * Start a vmxnet3 device: allocate and initialize the shared data - * structures and send a start command to the device. + * Start a vmxnet3 device: allocate and initialize the shared data + * structures and send a start command to the device. * - * Results: - * DDI_SUCCESS or DDI_FAILURE. - * - * Side effects: - * None. + * Returns: + * 0 on success, non-zero error on failure. */ static int vmxnet3_start(void *data) @@ -571,14 +508,16 @@ vmxnet3_start(void *data) Vmxnet3_RxQueueDesc *rqdesc; int txQueueSize, rxQueueSize; uint32_t ret32; + int err, dmaerr; VMXNET3_DEBUG(dp, 1, "start()\n"); /* * Allocate vmxnet3's shared data and advertise its PA */ - if (vmxnet3_prepare_drivershared(dp) != DDI_SUCCESS) { - VMXNET3_WARN(dp, "vmxnet3_prepare_drivershared() failed\n"); + if ((err = vmxnet3_prepare_drivershared(dp)) != 0) { + VMXNET3_WARN(dp, "vmxnet3_prepare_drivershared() failed: %d", + err); goto error; } tqdesc = VMXNET3_TQDESC(dp); @@ -593,12 +532,14 @@ vmxnet3_start(void *data) dp->txQueue.cmdRing.size = txQueueSize; dp->txQueue.compRing.size = txQueueSize; dp->txQueue.sharedCtrl = &tqdesc->ctrl; - if (vmxnet3_prepare_txqueue(dp) != DDI_SUCCESS) { - VMXNET3_WARN(dp, "vmxnet3_prepare_txqueue() failed\n"); + if ((err = vmxnet3_prepare_txqueue(dp)) != 0) { + VMXNET3_WARN(dp, "vmxnet3_prepare_txqueue() failed: %d", + err); goto error_shared_data; } } else { VMXNET3_WARN(dp, "invalid tx ring size (%d)\n", txQueueSize); + err = EINVAL; goto error_shared_data; } @@ -611,21 +552,24 @@ vmxnet3_start(void *data) dp->rxQueue.cmdRing.size = rxQueueSize; dp->rxQueue.compRing.size = rxQueueSize; dp->rxQueue.sharedCtrl = &rqdesc->ctrl; - if (vmxnet3_prepare_rxqueue(dp) != DDI_SUCCESS) { - VMXNET3_WARN(dp, "vmxnet3_prepare_rxqueue() failed\n"); + if ((err = vmxnet3_prepare_rxqueue(dp)) != 0) { + VMXNET3_WARN(dp, "vmxnet3_prepare_rxqueue() failed: %d", + err); goto error_tx_queue; } } else { VMXNET3_WARN(dp, "invalid rx ring size (%d)\n", rxQueueSize); + err = EINVAL; goto error_tx_queue; } /* * Allocate the Tx DMA handle */ - if (ddi_dma_alloc_handle(dp->dip, &vmxnet3_dma_attrs_tx, DDI_DMA_SLEEP, - NULL, &dp->txDmaHandle) != DDI_SUCCESS) { - VMXNET3_WARN(dp, "ddi_dma_alloc_handle() failed\n"); + if ((dmaerr = ddi_dma_alloc_handle(dp->dip, &vmxnet3_dma_attrs_tx, + DDI_DMA_SLEEP, NULL, &dp->txDmaHandle)) != DDI_SUCCESS) { + VMXNET3_WARN(dp, "ddi_dma_alloc_handle() failed: %d", dmaerr); + err = vmxnet3_dmaerr2errno(dmaerr); goto error_rx_queue; } @@ -636,6 +580,7 @@ vmxnet3_start(void *data) ret32 = VMXNET3_BAR1_GET32(dp, VMXNET3_REG_CMD); if (ret32) { VMXNET3_WARN(dp, "ACTIVATE_DEV failed: 0x%x\n", ret32); + err = ENXIO; goto error_txhandle; } dp->devEnabled = B_TRUE; @@ -660,7 +605,7 @@ vmxnet3_start(void *data) */ VMXNET3_BAR0_PUT32(dp, VMXNET3_REG_IMR, 0); - return (DDI_SUCCESS); + return (0); error_txhandle: ddi_dma_free_handle(&dp->txDmaHandle); @@ -671,20 +616,12 @@ error_tx_queue: error_shared_data: vmxnet3_destroy_drivershared(dp); error: - return (DDI_FAILURE); + return (err); } /* - * vmxnet3_stop -- - * - * Stop a vmxnet3 device: send a stop command to the device and - * de-allocate the shared data structures. - * - * Results: - * None. - * - * Side effects: - * None. + * Stop a vmxnet3 device: send a stop command to the device and + * de-allocate the shared data structures. */ static void vmxnet3_stop(void *data) @@ -714,15 +651,7 @@ vmxnet3_stop(void *data) } /* - * vmxnet3_setpromisc -- - * - * Set or unset promiscuous mode on a vmxnet3 device. - * - * Results: - * DDI_SUCCESS. - * - * Side effects: - * None. + * Set or unset promiscuous mode on a vmxnet3 device. */ static int vmxnet3_setpromisc(void *data, boolean_t promisc) @@ -739,26 +668,21 @@ vmxnet3_setpromisc(void *data, boolean_t promisc) vmxnet3_refresh_rxfilter(dp); - return (DDI_SUCCESS); + return (0); } /* - * vmxnet3_multicst -- + * Add or remove a multicast address from/to a vmxnet3 device. * - * Add or remove a multicast address from/to a vmxnet3 device. - * - * Results: - * DDI_FAILURE. - * - * Side effects: - * None. + * Returns: + * 0 on success, non-zero on failure. */ static int vmxnet3_multicst(void *data, boolean_t add, const uint8_t *macaddr) { vmxnet3_softc_t *dp = data; vmxnet3_dmabuf_t newMfTable; - int ret = DDI_SUCCESS; + int ret = 0; uint16_t macIdx; size_t allocSize; @@ -799,7 +723,7 @@ vmxnet3_multicst(void *data, boolean_t add, const uint8_t *macaddr) if (allocSize) { ret = vmxnet3_alloc_dma_mem_1(dp, &newMfTable, allocSize, B_TRUE); - ASSERT(ret == DDI_SUCCESS); + ASSERT(ret == 0); if (add) { (void) memcpy(newMfTable.buf, dp->mfTable.buf, dp->mfTable.bufLen); @@ -852,15 +776,10 @@ done: } /* - * vmxnet3_unicst -- - * - * Set the mac address of a vmxnet3 device. + * Set the mac address of a vmxnet3 device. * - * Results: - * DDI_FAILURE. - * - * Side effects: - * None. + * Returns: + * 0 */ static int vmxnet3_unicst(void *data, const uint8_t *macaddr) @@ -878,25 +797,18 @@ vmxnet3_unicst(void *data, const uint8_t *macaddr) (void) memcpy(dp->macaddr, macaddr, 6); - return (DDI_SUCCESS); + return (0); } - /* - * vmxnet3_change_mtu -- + * Change the MTU as seen by the driver. This is only supported when + * the mac is stopped. * - * Change the MTU as seen by the driver. This is only supported when - * the mac is stopped. - * - * Results: - * EBUSY if the device is enabled. - * EINVAL for invalid MTU values. - * 0 on success. - * - * Side effects: - * None. + * Returns: + * EBUSY if the device is enabled. + * EINVAL for invalid MTU values. + * 0 on success. */ - static int vmxnet3_change_mtu(vmxnet3_softc_t *dp, uint32_t new_mtu) { @@ -914,9 +826,14 @@ vmxnet3_change_mtu(vmxnet3_softc_t *dp, uint32_t new_mtu) VMXNET3_WARN(dp, "New MTU not in valid range [%d, %d].\n", VMXNET3_MIN_MTU, VMXNET3_MAX_MTU); return (EINVAL); + } else if (new_mtu > ETHERMTU && !dp->allow_jumbo) { + VMXNET3_WARN(dp, "MTU cannot be greater than %d because " + "accept-jumbo is not enabled.\n", ETHERMTU); + return (EINVAL); } dp->cur_mtu = new_mtu; + dp->alloc_ok = VMXNET3_ALLOC_OK(dp); if ((ret = mac_maxsdu_update(dp->mac, new_mtu)) != 0) VMXNET3_WARN(dp, "Unable to update mac with %d mtu: %d", @@ -925,22 +842,80 @@ vmxnet3_change_mtu(vmxnet3_softc_t *dp, uint32_t new_mtu) return (ret); } +/* ARGSUSED */ +static int +vmxnet3_get_prop(void *data, const char *prop_name, mac_prop_id_t prop_id, + uint_t prop_val_size, void *prop_val) +{ + vmxnet3_softc_t *dp = data; + int ret = 0; + + switch (prop_id) { + case MAC_PROP_MTU: + ASSERT(prop_val_size >= sizeof (uint32_t)); + bcopy(&dp->cur_mtu, prop_val, sizeof (uint32_t)); + break; + default: + VMXNET3_WARN(dp, "vmxnet3_get_prop property %d not supported", + prop_id); + ret = ENOTSUP; + } + return (ret); +} + +/* ARGSUSED */ +static int +vmxnet3_set_prop(void *data, const char *prop_name, mac_prop_id_t prop_id, + uint_t prop_val_size, const void *prop_val) +{ + vmxnet3_softc_t *dp = data; + int ret; + + switch (prop_id) { + case MAC_PROP_MTU: { + uint32_t new_mtu; + ASSERT(prop_val_size >= sizeof (uint32_t)); + bcopy(prop_val, &new_mtu, sizeof (new_mtu)); + ret = vmxnet3_change_mtu(dp, new_mtu); + break; + } + default: + VMXNET3_WARN(dp, "vmxnet3_set_prop property %d not supported", + prop_id); + ret = ENOTSUP; + } + + return (ret); +} + +/* ARGSUSED */ +static void +vmxnet3_prop_info(void *data, const char *prop_name, mac_prop_id_t prop_id, + mac_prop_info_handle_t prop_handle) +{ + vmxnet3_softc_t *dp = data; + + switch (prop_id) { + case MAC_PROP_MTU: + mac_prop_info_set_range_uint32(prop_handle, VMXNET3_MIN_MTU, + VMXNET3_MAX_MTU); + break; + default: + VMXNET3_WARN(dp, "vmxnet3_prop_info: property %d not supported", + prop_id); + } +} /* - * vmxnet3_ioctl -- - * - * DDI/DDK callback to handle IOCTL in driver. Currently it only handles - * ND_SET ioctl. Rest all are ignored. The ND_SET is used to set/reset - * accept-jumbo ndd parameted for the interface. - * - * Results: - * Nothing is returned directly. An ACK or NACK is conveyed to the calling - * function from the mblk which was used to call this function. + * DDI/DDK callback to handle IOCTL in driver. Currently it only handles + * ND_SET ioctl. Rest all are ignored. The ND_SET is used to set/reset + * accept-jumbo ndd parameted for the interface. * * Side effects: - * MTU can be changed and device can be reset. + * MTU can be changed and device can be reset. An ACK or NACK is conveyed + * to the calling function from the mblk which was used to call this + * function. */ - static void vmxnet3_ioctl(void *arg, queue_t *wq, mblk_t *mp) { @@ -1011,10 +986,12 @@ vmxnet3_ioctl(void *arg, queue_t *wq, mblk_t *mp) if (data == 1) { VMXNET3_DEBUG(dp, 2, "Accepting jumbo frames\n"); + dp->allow_jumbo = B_TRUE; ret = vmxnet3_change_mtu(dp, VMXNET3_MAX_MTU); } else if (data == 0) { VMXNET3_DEBUG(dp, 2, "Rejecting jumbo frames\n"); + dp->allow_jumbo = B_FALSE; ret = vmxnet3_change_mtu(dp, ETHERMTU); } else { VMXNET3_WARN(dp, "Invalid data value to be set," @@ -1041,17 +1018,11 @@ vmxnet3_ioctl(void *arg, queue_t *wq, mblk_t *mp) miocnak(wq, mp, 0, EINVAL); } - /* - * vmxnet3_getcapab -- - * - * Get the capabilities of a vmxnet3 device. + * Get the capabilities of a vmxnet3 device. * - * Results: - * B_TRUE or B_FALSE. - * - * Side effects: - * None. + * Returns: + * B_TRUE if the capability is supported, B_FALSE otherwise. */ static boolean_t vmxnet3_getcapab(void *data, mac_capab_t capab, void *arg) @@ -1060,21 +1031,21 @@ vmxnet3_getcapab(void *data, mac_capab_t capab, void *arg) boolean_t ret; switch (capab) { - case MAC_CAPAB_HCKSUM: { - uint32_t *txflags = arg; - *txflags = HCKSUM_INET_PARTIAL; - ret = B_TRUE; - break; - } - case MAC_CAPAB_LSO: { - mac_capab_lso_t *lso = arg; - lso->lso_flags = LSO_TX_BASIC_TCP_IPV4; - lso->lso_basic_tcp_ipv4.lso_max = IP_MAXPACKET; - ret = vmxnet3_getprop(dp, "EnableLSO", 0, 1, 1); - break; - } - default: - ret = B_FALSE; + case MAC_CAPAB_HCKSUM: { + uint32_t *txflags = arg; + *txflags = HCKSUM_INET_PARTIAL; + ret = B_TRUE; + break; + } + case MAC_CAPAB_LSO: { + mac_capab_lso_t *lso = arg; + lso->lso_flags = LSO_TX_BASIC_TCP_IPV4; + lso->lso_basic_tcp_ipv4.lso_max = IP_MAXPACKET; + ret = vmxnet3_getprop(dp, "EnableLSO", 0, 1, 1); + break; + } + default: + ret = B_FALSE; } VMXNET3_DEBUG(dp, 2, "getcapab(0x%x) -> %s\n", capab, @@ -1084,73 +1055,10 @@ vmxnet3_getcapab(void *data, mac_capab_t capab, void *arg) } /* - * vmxnet3_setmacprop -- - * - * Set a MAC property. - * - * Results: - * 0 on success, errno otherwise. + * Reset a vmxnet3 device. Only to be used when the device is wedged. * * Side effects: - * None. - */ -/* ARGSUSED */ -static int -vmxnet3_setmacprop(void *data, const char *pr_name, mac_prop_id_t pr_num, - uint_t pr_valsize, const void *pr_val) -{ - vmxnet3_softc_t *dp = data; - int ret = 0; - uint32_t newmtu; - - switch (pr_num) { - case MAC_PROP_MTU: - (void) memcpy(&newmtu, pr_val, sizeof (newmtu)); - ret = vmxnet3_change_mtu(dp, newmtu); - break; - default: - ret = ENOTSUP; - } - - return (ret); -} - -/* - * vmxnet3_macpropinfo -- - * - * Get MAC property information. - * - * Results: - * None. - * - * Side effects: - * None. - */ -/* ARGSUSED */ -static void -vmxnet3_macpropinfo(void *data, const char *pr_name, mac_prop_id_t pr_num, - mac_prop_info_handle_t prh) -{ - switch (pr_num) { - case MAC_PROP_MTU: - mac_prop_info_set_range_uint32(prh, VMXNET3_MIN_MTU, - VMXNET3_MAX_MTU); - break; - default: - break; - } -} - -/* - * vmxnet3_reset -- - * - * Reset a vmxnet3 device. Only to be used when the device is wedged. - * - * Results: - * None. - * - * Side effects: - * The device is reset. + * The device is reset. */ static void vmxnet3_reset(void *data) @@ -1164,20 +1072,15 @@ vmxnet3_reset(void *data) atomic_inc_32(&dp->reset_count); vmxnet3_stop(dp); VMXNET3_BAR1_PUT32(dp, VMXNET3_REG_CMD, VMXNET3_CMD_RESET_DEV); - if ((ret = vmxnet3_start(dp)) != DDI_SUCCESS) + if ((ret = vmxnet3_start(dp)) != 0) VMXNET3_WARN(dp, "failed to reset the device: %d", ret); } /* - * vmxnet3_intr_events -- + * Process pending events on a vmxnet3 device. * - * Process pending events on a vmxnet3 device. - * - * Results: - * B_TRUE if the link state changed, B_FALSE otherwise. - * - * Side effects: - * None. + * Returns: + * B_TRUE if the link state changed, B_FALSE otherwise. */ static boolean_t vmxnet3_intr_events(vmxnet3_softc_t *dp) @@ -1225,15 +1128,10 @@ vmxnet3_intr_events(vmxnet3_softc_t *dp) } /* - * vmxnet3_intr -- + * Interrupt handler of a vmxnet3 device. * - * Interrupt handler of a vmxnet3 device. - * - * Results: - * DDI_INTR_CLAIMED or DDI_INTR_UNCLAIMED. - * - * Side effects: - * None. + * Returns: + * DDI_INTR_CLAIMED or DDI_INTR_UNCLAIMED. */ /* ARGSUSED1 */ static uint_t @@ -1297,6 +1195,8 @@ vmxnet3_kstat_update(kstat_t *ksp, int rw) statp->tx_pullup_needed.value.ul = dp->tx_pullup_needed; statp->tx_ring_full.value.ul = dp->tx_ring_full; statp->rx_alloc_buf.value.ul = dp->rx_alloc_buf; + statp->rx_pool_empty.value.ul = dp->rx_pool_empty; + statp->rx_num_bufs.value.ul = dp->rx_num_bufs; return (0); } @@ -1324,6 +1224,10 @@ vmxnet3_kstat_init(vmxnet3_softc_t *dp) KSTAT_DATA_ULONG); kstat_named_init(&statp->rx_alloc_buf, "rx_alloc_buf", KSTAT_DATA_ULONG); + kstat_named_init(&statp->rx_pool_empty, "rx_pool_empty", + KSTAT_DATA_ULONG); + kstat_named_init(&statp->rx_num_bufs, "rx_num_bufs", + KSTAT_DATA_ULONG); kstat_install(dp->devKstats); @@ -1331,15 +1235,10 @@ vmxnet3_kstat_init(vmxnet3_softc_t *dp) } /* - * vmxnet3_attach -- - * - * Probe and attach a vmxnet3 instance to the stack. + * Probe and attach a vmxnet3 instance to the stack. * - * Results: - * DDI_SUCCESS or DDI_FAILURE. - * - * Side effects: - * None. + * Returns: + * DDI_SUCCESS or DDI_FAILURE. */ static int vmxnet3_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) @@ -1364,6 +1263,8 @@ vmxnet3_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) dp->dip = dip; dp->instance = ddi_get_instance(dip); dp->cur_mtu = ETHERMTU; + dp->allow_jumbo = B_TRUE; + dp->alloc_ok = VMXNET3_ALLOC_OK(dp); VMXNET3_DEBUG(dp, 1, "attach()\n"); @@ -1593,15 +1494,10 @@ error: } /* - * vmxnet3_detach -- - * - * Detach a vmxnet3 instance from the stack. + * Detach a vmxnet3 instance from the stack. * - * Results: - * DDI_SUCCESS or DDI_FAILURE. - * - * Side effects: - * None. + * Returns: + * DDI_SUCCESS or DDI_FAILURE. */ static int vmxnet3_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) @@ -1616,10 +1512,10 @@ vmxnet3_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) return (DDI_FAILURE); } - while (dp->rxNumBufs) { + while (dp->rx_num_bufs > 0) { if (retries++ < 10) { VMXNET3_WARN(dp, "rx pending (%u), waiting 1 second\n", - dp->rxNumBufs); + dp->rx_num_bufs); delay(drv_usectohz(1000000)); } else { VMXNET3_WARN(dp, "giving up\n"); @@ -1668,7 +1564,7 @@ vmxnet3_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) * Structures used by the module loader */ -#define VMXNET3_IDENT "VMware Ethernet v3 (" BUILD_NUMBER_NUMERIC_STRING ")" +#define VMXNET3_IDENT "VMware Ethernet v3 " VMXNET3_DRIVER_VERSION_STRING DDI_DEFINE_STREAM_OPS( vmxnet3_dev_ops, diff --git a/usr/src/uts/intel/io/vmxnet3s/vmxnet3_rx.c b/usr/src/uts/intel/io/vmxnet3s/vmxnet3_rx.c index 1084be45df..0099464824 100644 --- a/usr/src/uts/intel/io/vmxnet3s/vmxnet3_rx.c +++ b/usr/src/uts/intel/io/vmxnet3s/vmxnet3_rx.c @@ -12,26 +12,20 @@ * See the License for the specific language governing permissions * and limitations under the License. */ - /* - * Copyright (c) 2013 by Delphix. All rights reserved. + * Copyright (c) 2013, 2016 by Delphix. All rights reserved. */ #include <vmxnet3.h> -static void vmxnet3_put_rxbuf(vmxnet3_rxbuf_t *rxBuf); +static void vmxnet3_put_rxbuf(vmxnet3_rxbuf_t *); /* - * vmxnet3_alloc_rxbuf -- - * - * Allocate a new rxBuf from memory. All its fields are set except - * for its associated mblk which has to be allocated later. + * Allocate a new rxBuf from memory. All its fields are set except + * for its associated mblk which has to be allocated later. * - * Results: - * A new rxBuf or NULL. - * - * Side effects: - * None. + * Returns: + * A new rxBuf or NULL. */ static vmxnet3_rxbuf_t * vmxnet3_alloc_rxbuf(vmxnet3_softc_t *dp, boolean_t canSleep) @@ -40,7 +34,6 @@ vmxnet3_alloc_rxbuf(vmxnet3_softc_t *dp, boolean_t canSleep) int flag = canSleep ? KM_SLEEP : KM_NOSLEEP; int err; - atomic_inc_32(&dp->rx_alloc_buf); rxBuf = kmem_zalloc(sizeof (vmxnet3_rxbuf_t), flag); if (!rxBuf) { atomic_inc_32(&dp->rx_alloc_failed); @@ -48,7 +41,7 @@ vmxnet3_alloc_rxbuf(vmxnet3_softc_t *dp, boolean_t canSleep) } if ((err = vmxnet3_alloc_dma_mem_1(dp, &rxBuf->dma, (dp->cur_mtu + 18), - canSleep)) != DDI_SUCCESS) { + canSleep)) != 0) { VMXNET3_DEBUG(dp, 0, "Failed to allocate %d bytes for rx buf, " "err:%d\n", (dp->cur_mtu + 18), err); kmem_free(rxBuf, sizeof (vmxnet3_rxbuf_t)); @@ -60,59 +53,47 @@ vmxnet3_alloc_rxbuf(vmxnet3_softc_t *dp, boolean_t canSleep) rxBuf->freeCB.free_arg = (caddr_t)rxBuf; rxBuf->dp = dp; - atomic_inc_32(&dp->rxNumBufs); - + atomic_inc_32(&dp->rx_num_bufs); + atomic_inc_32(&dp->rx_alloc_buf); return (rxBuf); } -/* - * vmxnet3_free_rxbuf -- - * - * Free a rxBuf. - * - * Results: - * None. - * - * Side effects: - * None. - */ static void vmxnet3_free_rxbuf(vmxnet3_softc_t *dp, vmxnet3_rxbuf_t *rxBuf) { vmxnet3_free_dma_mem(&rxBuf->dma); kmem_free(rxBuf, sizeof (vmxnet3_rxbuf_t)); -#ifndef DEBUG - atomic_dec_32(&dp->rxNumBufs); +#ifndef DEBUG + atomic_dec_32(&dp->rx_num_bufs); #else { - uint32_t nv = atomic_dec_32_nv(&dp->rxNumBufs); + uint32_t nv = atomic_dec_32_nv(&dp->rx_num_bufs); ASSERT(nv != (uint32_t)-1); } #endif } /* - * vmxnet3_put_rxpool_buf -- - * - * Return a rxBuf to the pool. - * - * Results: - * B_TRUE if there was room in the pool and the rxBuf was returned, - * B_FALSE otherwise. - * - * Side effects: - * None. + * Return a rxBuf to the pool. The init argument, when B_TRUE, indicates + * that we're being called for the purpose of pool initialization, and + * therefore, we should place the buffer in the pool even if the device + * isn't enabled. + * + * Returns: + * B_TRUE if the buffer was returned to the pool, or B_FALSE if it + * wasn't (e.g. if the device is stopped). */ static boolean_t -vmxnet3_put_rxpool_buf(vmxnet3_softc_t *dp, vmxnet3_rxbuf_t *rxBuf) +vmxnet3_put_rxpool_buf(vmxnet3_softc_t *dp, vmxnet3_rxbuf_t *rxBuf, + boolean_t init) { vmxnet3_rxpool_t *rxPool = &dp->rxPool; boolean_t returned = B_FALSE; mutex_enter(&dp->rxPoolLock); ASSERT(rxPool->nBufs <= rxPool->nBufsLimit); - if (dp->devEnabled && rxPool->nBufs < rxPool->nBufsLimit) { + if ((dp->devEnabled || init) && rxPool->nBufs < rxPool->nBufsLimit) { ASSERT((rxPool->listHead == NULL && rxPool->nBufs == 0) || (rxPool->listHead != NULL && rxPool->nBufs != 0)); rxBuf->next = rxPool->listHead; @@ -125,37 +106,22 @@ vmxnet3_put_rxpool_buf(vmxnet3_softc_t *dp, vmxnet3_rxbuf_t *rxBuf) } /* - * vmxnet3_put_rxbuf -- - * - * Return a rxBuf to the pool or free it. - * - * Results: - * None. - * - * Side effects: - * None. + * Return a rxBuf to the pool or free it. */ static void vmxnet3_put_rxbuf(vmxnet3_rxbuf_t *rxBuf) { vmxnet3_softc_t *dp = rxBuf->dp; - VMXNET3_DEBUG(dp, 5, "free 0x%p\n", rxBuf); - - if (!vmxnet3_put_rxpool_buf(dp, rxBuf)) + if (!vmxnet3_put_rxpool_buf(dp, rxBuf, B_FALSE)) vmxnet3_free_rxbuf(dp, rxBuf); } /* - * vmxnet3_get_rxpool_buf -- - * - * Get an unused rxBuf from the pool. - * - * Results: - * A rxBuf or NULL if there are no buffers in the pool. + * Get an unused rxBuf from the pool. * - * Side effects: - * None. + * Returns: + * A rxBuf or NULL if there are no buffers in the pool. */ static vmxnet3_rxbuf_t * vmxnet3_get_rxpool_buf(vmxnet3_softc_t *dp) @@ -164,7 +130,7 @@ vmxnet3_get_rxpool_buf(vmxnet3_softc_t *dp) vmxnet3_rxbuf_t *rxBuf = NULL; mutex_enter(&dp->rxPoolLock); - if (rxPool->listHead) { + if (rxPool->listHead != NULL) { rxBuf = rxPool->listHead; rxPool->listHead = rxBuf->next; rxPool->nBufs--; @@ -176,60 +142,77 @@ vmxnet3_get_rxpool_buf(vmxnet3_softc_t *dp) } /* - * vmxnet3_get_rxbuf -- + * Fill a rxPool by allocating the maximum number of buffers. * - * Get an unused rxBuf from either the pool or from memory. - * The returned rxBuf has a mblk associated with it. - * - * Results: - * A rxBuf or NULL. - * - * Side effects: - * None. + * Returns: + * 0 on success, non-zero on failure. */ -static vmxnet3_rxbuf_t * -vmxnet3_get_rxbuf(vmxnet3_softc_t *dp, boolean_t canSleep) +static int +vmxnet3_rxpool_init(vmxnet3_softc_t *dp) { + int err = 0; vmxnet3_rxbuf_t *rxBuf; - if ((rxBuf = vmxnet3_get_rxpool_buf(dp))) { - VMXNET3_DEBUG(dp, 5, "alloc 0x%p from pool\n", rxBuf); - } else if ((rxBuf = vmxnet3_alloc_rxbuf(dp, canSleep))) { - VMXNET3_DEBUG(dp, 5, "alloc 0x%p from mem\n", rxBuf); + ASSERT(dp->rxPool.nBufsLimit > 0); + while (dp->rxPool.nBufs < dp->rxPool.nBufsLimit) { + if ((rxBuf = vmxnet3_alloc_rxbuf(dp, B_FALSE)) == NULL) { + err = ENOMEM; + break; + } + VERIFY(vmxnet3_put_rxpool_buf(dp, rxBuf, B_TRUE)); } - if (rxBuf) { - rxBuf->mblk = desballoc((uchar_t *)rxBuf->dma.buf, - rxBuf->dma.bufLen, BPRI_MED, &rxBuf->freeCB); - if (!rxBuf->mblk) { - vmxnet3_put_rxbuf(rxBuf); - atomic_inc_32(&dp->rx_alloc_failed); - rxBuf = NULL; + if (err != 0) { + while ((rxBuf = vmxnet3_get_rxpool_buf(dp)) != NULL) { + vmxnet3_free_rxbuf(dp, rxBuf); } } - return (rxBuf); + return (err); } /* - * vmxnet3_rx_populate -- - * - * Populate a Rx descriptor with a new rxBuf. - * - * Results: - * DDI_SUCCESS or DDI_FAILURE. - * - * Side effects: - * None. + * Populate a Rx descriptor with a new rxBuf. If the pool argument is B_TRUE, + * then try to take a buffer from rxPool. If the pool is empty and the + * dp->alloc_ok is true, then fall back to dynamic allocation. If pool is + * B_FALSE, then always allocate a new buffer (this is only used when + * populating the initial set of buffers in the receive queue during start). + * + * Returns: + * 0 on success, non-zero on failure. */ static int vmxnet3_rx_populate(vmxnet3_softc_t *dp, vmxnet3_rxqueue_t *rxq, uint16_t idx, - boolean_t canSleep) + boolean_t canSleep, boolean_t pool) { - int ret = DDI_SUCCESS; - vmxnet3_rxbuf_t *rxBuf = vmxnet3_get_rxbuf(dp, canSleep); + vmxnet3_rxbuf_t *rxBuf = NULL; + + if (pool && (rxBuf = vmxnet3_get_rxpool_buf(dp)) == NULL) { + /* The maximum number of pool buffers have been allocated. */ + atomic_inc_32(&dp->rx_pool_empty); + if (!dp->alloc_ok) { + atomic_inc_32(&dp->rx_alloc_failed); + } + } + + if (rxBuf == NULL && (!pool || dp->alloc_ok)) { + rxBuf = vmxnet3_alloc_rxbuf(dp, canSleep); + } + + if (rxBuf != NULL) { + rxBuf->mblk = desballoc((uchar_t *)rxBuf->dma.buf, + rxBuf->dma.bufLen, BPRI_MED, &rxBuf->freeCB); + if (rxBuf->mblk == NULL) { + if (pool) { + VERIFY(vmxnet3_put_rxpool_buf(dp, rxBuf, + B_FALSE)); + } else { + vmxnet3_free_rxbuf(dp, rxBuf); + } + atomic_inc_32(&dp->rx_alloc_failed); + return (ENOMEM); + } - if (rxBuf) { vmxnet3_cmdring_t *cmdRing = &rxq->cmdRing; Vmxnet3_GenericDesc *rxDesc = VMXNET3_GET_DESC(cmdRing, idx); @@ -240,40 +223,45 @@ vmxnet3_rx_populate(vmxnet3_softc_t *dp, vmxnet3_rxqueue_t *rxq, uint16_t idx, membar_producer(); rxDesc->rxd.gen = cmdRing->gen; } else { - ret = DDI_FAILURE; + return (ENOMEM); } - return (ret); + return (0); } /* - * vmxnet3_rxqueue_init -- - * - * Initialize a RxQueue by populating the whole Rx ring with rxBufs. - * - * Results: - * DDI_SUCCESS or DDI_FAILURE. + * Initialize a RxQueue by populating the whole Rx ring with rxBufs. * - * Side effects: - * None. + * Returns: + * 0 on success, non-zero on failure. */ int vmxnet3_rxqueue_init(vmxnet3_softc_t *dp, vmxnet3_rxqueue_t *rxq) { vmxnet3_cmdring_t *cmdRing = &rxq->cmdRing; + int err; + + dp->rxPool.nBufsLimit = vmxnet3_getprop(dp, "RxBufPoolLimit", 0, + cmdRing->size * 10, cmdRing->size * 2); do { - if (vmxnet3_rx_populate(dp, rxq, cmdRing->next2fill, - B_TRUE) != DDI_SUCCESS) { + if ((err = vmxnet3_rx_populate(dp, rxq, cmdRing->next2fill, + B_TRUE, B_FALSE)) != 0) { goto error; } VMXNET3_INC_RING_IDX(cmdRing, cmdRing->next2fill); } while (cmdRing->next2fill); - dp->rxPool.nBufsLimit = vmxnet3_getprop(dp, "RxBufPoolLimit", 0, - cmdRing->size * 10, cmdRing->size * 2); + /* + * Pre-allocate rxPool buffers so that we never have to allocate + * new buffers from interrupt context when we need to replace a buffer + * in the rxqueue. + */ + if ((err = vmxnet3_rxpool_init(dp)) != 0) { + goto error; + } - return (DDI_SUCCESS); + return (0); error: while (cmdRing->next2fill) { @@ -281,19 +269,11 @@ error: vmxnet3_free_rxbuf(dp, rxq->bufRing[cmdRing->next2fill].rxBuf); } - return (DDI_FAILURE); + return (err); } /* - * vmxnet3_rxqueue_fini -- - * - * Finish a RxQueue by freeing all the related rxBufs. - * - * Results: - * DDI_SUCCESS. - * - * Side effects: - * None. + * Finish a RxQueue by freeing all the related rxBufs. */ void vmxnet3_rxqueue_fini(vmxnet3_softc_t *dp, vmxnet3_rxqueue_t *rxq) @@ -322,16 +302,8 @@ vmxnet3_rxqueue_fini(vmxnet3_softc_t *dp, vmxnet3_rxqueue_t *rxq) } /* - * vmxnet3_rx_hwcksum -- - * - * Determine if a received packet was checksummed by the Vmxnet3 - * device and tag the mp appropriately. - * - * Results: - * None. - * - * Side effects: - * The mp may get tagged. + * Determine if a received packet was checksummed by the Vmxnet3 + * device and tag the mp appropriately. */ static void vmxnet3_rx_hwcksum(vmxnet3_softc_t *dp, mblk_t *mp, @@ -355,16 +327,11 @@ vmxnet3_rx_hwcksum(vmxnet3_softc_t *dp, mblk_t *mp, } /* - * vmxnet3_rx_intr -- - * - * Interrupt handler for Rx. Look if there are any pending Rx and - * put them in mplist. - * - * Results: - * A list of messages to pass to the MAC subystem. + * Interrupt handler for Rx. Look if there are any pending Rx and + * put them in mplist. * - * Side effects: - * None. + * Returns: + * A list of messages to pass to the MAC subystem. */ mblk_t * vmxnet3_rx_intr(vmxnet3_softc_t *dp, vmxnet3_rxqueue_t *rxq) @@ -419,8 +386,8 @@ vmxnet3_rx_intr(vmxnet3_softc_t *dp, vmxnet3_rxqueue_t *rxq) * descriptor. Grab it only if we achieve to replace * it with a fresh buffer. */ - if (vmxnet3_rx_populate(dp, rxq, rxdIdx, - B_FALSE) == DDI_SUCCESS) { + if (vmxnet3_rx_populate(dp, rxq, rxdIdx, B_FALSE, + B_TRUE) == 0) { /* Success, we can chain the mblk with the mp */ mblk->b_wptr = mblk->b_rptr + compDesc->rcd.len; *mpTail = mblk; diff --git a/usr/src/uts/intel/io/vmxnet3s/vmxnet3_tx.c b/usr/src/uts/intel/io/vmxnet3s/vmxnet3_tx.c index b783f4c65f..4789bf55ef 100644 --- a/usr/src/uts/intel/io/vmxnet3s/vmxnet3_tx.c +++ b/usr/src/uts/intel/io/vmxnet3s/vmxnet3_tx.c @@ -14,7 +14,7 @@ */ /* - * Copyright (c) 2012 by Delphix. All rights reserved. + * Copyright (c) 2012, 2016 by Delphix. All rights reserved. */ #include <vmxnet3.h> @@ -33,33 +33,17 @@ typedef struct vmxnet3_offload_t { } vmxnet3_offload_t; /* - * vmxnet3_txqueue_init -- - * - * Initialize a TxQueue. Currently nothing needs to be done. - * - * Results: - * DDI_SUCCESS. - * - * Side effects: - * None. + * Initialize a TxQueue. Currently nothing needs to be done. */ /* ARGSUSED */ int vmxnet3_txqueue_init(vmxnet3_softc_t *dp, vmxnet3_txqueue_t *txq) { - return (DDI_SUCCESS); + return (0); } /* - * vmxnet3_txqueue_fini -- - * - * Finish a TxQueue by freeing all pending Tx. - * - * Results: - * DDI_SUCCESS. - * - * Side effects: - * None. + * Finish a TxQueue by freeing all pending Tx. */ void vmxnet3_txqueue_fini(vmxnet3_softc_t *dp, vmxnet3_txqueue_t *txq) @@ -77,24 +61,19 @@ vmxnet3_txqueue_fini(vmxnet3_softc_t *dp, vmxnet3_txqueue_t *txq) } /* - * vmxnet3_tx_prepare_offload -- - * - * Build the offload context of a msg. - * - * Results: - * 0 if everything went well. - * +n if n bytes need to be pulled up. - * -1 in case of error (not used). + * Build the offload context of a msg. * - * Side effects: - * None. + * Returns: + * 0 if everything went well. + * +n if n bytes need to be pulled up. + * -1 in case of error (not used). */ static int vmxnet3_tx_prepare_offload(vmxnet3_softc_t *dp, vmxnet3_offload_t *ol, mblk_t *mp) { int ret = 0; - uint32_t start, stuff, value, flags, lsoflags, mss; + uint32_t start, stuff, value, flags, lso_flag, mss; ol->om = VMXNET3_OM_NONE; ol->hlen = 0; @@ -102,12 +81,9 @@ vmxnet3_tx_prepare_offload(vmxnet3_softc_t *dp, vmxnet3_offload_t *ol, hcksum_retrieve(mp, NULL, NULL, &start, &stuff, NULL, &value, &flags); - mac_lso_get(mp, &mss, &lsoflags); - if (lsoflags & HW_LSO) { - flags |= HW_LSO; - } + mac_lso_get(mp, &mss, &lso_flag); - if (flags) { + if (flags || lso_flag) { struct ether_vlan_header *eth = (void *) mp->b_rptr; uint8_t ethLen; @@ -120,12 +96,7 @@ vmxnet3_tx_prepare_offload(vmxnet3_softc_t *dp, vmxnet3_offload_t *ol, VMXNET3_DEBUG(dp, 4, "flags=0x%x, ethLen=%u, start=%u, " "stuff=%u, value=%u\n", flags, ethLen, start, stuff, value); - if (flags & HCK_PARTIALCKSUM) { - ol->om = VMXNET3_OM_CSUM; - ol->hlen = start + ethLen; - ol->msscof = stuff + ethLen; - } - if (flags & HW_LSO) { + if (lso_flag & HW_LSO) { mblk_t *mblk = mp; uint8_t *ip, *tcp; uint8_t ipLen, tcpLen; @@ -155,11 +126,15 @@ vmxnet3_tx_prepare_offload(vmxnet3_softc_t *dp, vmxnet3_offload_t *ol, ol->om = VMXNET3_OM_TSO; ol->hlen = ethLen + ipLen + tcpLen; - ol->msscof = DB_LSOMSS(mp); + ol->msscof = mss; if (mblk != mp) { ret = ol->hlen; } + } else if (flags & HCK_PARTIALCKSUM) { + ol->om = VMXNET3_OM_CSUM; + ol->hlen = start + ethLen; + ol->msscof = stuff + ethLen; } } @@ -167,18 +142,16 @@ vmxnet3_tx_prepare_offload(vmxnet3_softc_t *dp, vmxnet3_offload_t *ol, } /* - * vmxnet3_tx_one -- - * - * Map a msg into the Tx command ring of a vmxnet3 device. + * Map a msg into the Tx command ring of a vmxnet3 device. * - * Results: - * VMXNET3_TX_OK if everything went well. - * VMXNET3_TX_RINGFULL if the ring is nearly full. - * VMXNET3_TX_PULLUP if the msg is overfragmented. - * VMXNET3_TX_FAILURE if there was a DMA or offload error. + * Returns: + * VMXNET3_TX_OK if everything went well. + * VMXNET3_TX_RINGFULL if the ring is nearly full. + * VMXNET3_TX_PULLUP if the msg is overfragmented. + * VMXNET3_TX_FAILURE if there was a DMA or offload error. * * Side effects: - * The ring is filled if VMXNET3_TX_OK is returned. + * The ring is filled if VMXNET3_TX_OK is returned. */ static vmxnet3_txstatus vmxnet3_tx_one(vmxnet3_softc_t *dp, vmxnet3_txqueue_t *txq, @@ -339,16 +312,11 @@ done: } /* - * vmxnet3_tx -- + * Send packets on a vmxnet3 device. * - * Send packets on a vmxnet3 device. - * - * Results: - * NULL in case of success or failure. - * The mps to be retransmitted later if the ring is full. - * - * Side effects: - * None. + * Returns: + * NULL in case of success or failure. + * The mps to be retransmitted later if the ring is full. */ mblk_t * vmxnet3_tx(void *data, mblk_t *mps) @@ -450,15 +418,10 @@ vmxnet3_tx(void *data, mblk_t *mps) } /* - * vmxnet3_tx_complete -- + * Parse a transmit queue and complete packets. * - * Parse a transmit queue and complete packets. - * - * Results: - * B_TRUE if Tx must be updated or B_FALSE if no action is required. - * - * Side effects: - * None. + * Returns: + * B_TRUE if Tx must be updated or B_FALSE if no action is required. */ boolean_t vmxnet3_tx_complete(vmxnet3_softc_t *dp, vmxnet3_txqueue_t *txq) diff --git a/usr/src/uts/intel/io/vmxnet3s/vmxnet3_utils.c b/usr/src/uts/intel/io/vmxnet3s/vmxnet3_utils.c index 26784c3d65..bec73524f7 100644 --- a/usr/src/uts/intel/io/vmxnet3s/vmxnet3_utils.c +++ b/usr/src/uts/intel/io/vmxnet3s/vmxnet3_utils.c @@ -12,6 +12,9 @@ * See the License for the specific language governing permissions * and limitations under the License. */ +/* + * Copyright (c) 2016 by Delphix. All rights reserved. + */ #include <vmxnet3.h> @@ -70,16 +73,33 @@ static ddi_dma_attr_t vmxnet3_dma_attrs_512 = { .dma_attr_flags = 0 }; +int +vmxnet3_dmaerr2errno(int dmaerr) +{ + int err; + + switch (dmaerr) { + case DDI_DMA_NORESOURCES: + case DDI_DMA_TOOBIG: + err = ENOMEM; + break; + case DDI_DMA_INUSE: + err = EBUSY; + break; + case DDI_DMA_BADATTR: + case DDI_DMA_NOMAPPING: + default: + err = EINVAL; + } + + return (err); +} + /* - * vmxnet3_alloc_dma_mem -- + * Allocate /size/ bytes of contiguous DMA-ble memory. * - * Allocate /size/ bytes of contiguous DMA-ble memory. - * - * Results: - * DDI_SUCCESS or DDI_FAILURE. - * - * Side effects: - * None. + * Returns: + * 0 on success, non-zero on failure. */ static int vmxnet3_alloc_dma_mem(vmxnet3_softc_t *dp, vmxnet3_dmabuf_t *dma, size_t size, @@ -87,6 +107,7 @@ vmxnet3_alloc_dma_mem(vmxnet3_softc_t *dp, vmxnet3_dmabuf_t *dma, size_t size, { ddi_dma_cookie_t cookie; uint_t cookieCount; + int dmaerr, err = 0; int (*cb) (caddr_t) = canSleep ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT; ASSERT(size != 0); @@ -94,9 +115,10 @@ vmxnet3_alloc_dma_mem(vmxnet3_softc_t *dp, vmxnet3_dmabuf_t *dma, size_t size, /* * Allocate a DMA handle */ - if (ddi_dma_alloc_handle(dp->dip, dma_attrs, cb, NULL, - &dma->dmaHandle) != DDI_SUCCESS) { - VMXNET3_WARN(dp, "ddi_dma_alloc_handle() failed\n"); + if ((dmaerr = ddi_dma_alloc_handle(dp->dip, dma_attrs, cb, NULL, + &dma->dmaHandle)) != DDI_SUCCESS) { + VMXNET3_WARN(dp, "ddi_dma_alloc_handle() failed: %d", dmaerr); + err = vmxnet3_dmaerr2errno(dmaerr); goto error; } @@ -106,24 +128,27 @@ vmxnet3_alloc_dma_mem(vmxnet3_softc_t *dp, vmxnet3_dmabuf_t *dma, size_t size, if (ddi_dma_mem_alloc(dma->dmaHandle, size, &vmxnet3_dev_attr, DDI_DMA_CONSISTENT, cb, NULL, &dma->buf, &dma->bufLen, &dma->dataHandle) != DDI_SUCCESS) { - VMXNET3_WARN(dp, "ddi_dma_mem_alloc() failed\n"); + VMXNET3_WARN(dp, "ddi_dma_mem_alloc() failed"); + err = ENOMEM; goto error_dma_handle; } /* * Map the memory */ - if (ddi_dma_addr_bind_handle(dma->dmaHandle, NULL, dma->buf, + if ((dmaerr = ddi_dma_addr_bind_handle(dma->dmaHandle, NULL, dma->buf, dma->bufLen, DDI_DMA_RDWR | DDI_DMA_STREAMING, cb, NULL, &cookie, - &cookieCount) != DDI_DMA_MAPPED) { - VMXNET3_WARN(dp, "ddi_dma_addr_bind_handle() failed\n"); + &cookieCount)) != DDI_DMA_MAPPED) { + VMXNET3_WARN(dp, "ddi_dma_addr_bind_handle() failed: %d", + dmaerr); + err = vmxnet3_dmaerr2errno(dmaerr); goto error_dma_mem; } ASSERT(cookieCount == 1); dma->bufPA = cookie.dmac_laddress; - return (DDI_SUCCESS); + return (0); error_dma_mem: ddi_dma_mem_free(&dma->dataHandle); @@ -133,7 +158,7 @@ error: dma->buf = NULL; dma->bufPA = NULL; dma->bufLen = 0; - return (DDI_FAILURE); + return (err); } int @@ -161,15 +186,7 @@ vmxnet3_alloc_dma_mem_128(vmxnet3_softc_t *dp, vmxnet3_dmabuf_t *dma, } /* - * vmxnet3_free_dma_mem -- - * - * Free DMA-ble memory. - * - * Results: - * None. - * - * Side effects: - * None. + * Free DMA-ble memory. */ void vmxnet3_free_dma_mem(vmxnet3_dmabuf_t *dma) @@ -184,18 +201,13 @@ vmxnet3_free_dma_mem(vmxnet3_dmabuf_t *dma) } /* - * vmxnet3_getprop -- - * - * Get the numeric value of the property "name" in vmxnet3s.conf for - * the corresponding device instance. - * If the property isn't found or if it doesn't satisfy the conditions, - * "def" is returned. - * - * Results: - * The value of the property or "def". + * Get the numeric value of the property "name" in vmxnet3s.conf for + * the corresponding device instance. + * If the property isn't found or if it doesn't satisfy the conditions, + * "def" is returned. * - * Side effects: - * None. + * Returns: + * The value of the property or "def". */ int vmxnet3_getprop(vmxnet3_softc_t *dp, char *name, int min, int max, int def) diff --git a/usr/src/uts/intel/io/vmxnet3s/vmxnet3s.conf b/usr/src/uts/intel/io/vmxnet3s/vmxnet3s.conf index 7f16946092..8345dc27f4 100644 --- a/usr/src/uts/intel/io/vmxnet3s/vmxnet3s.conf +++ b/usr/src/uts/intel/io/vmxnet3s/vmxnet3s.conf @@ -27,7 +27,7 @@ RxRingSize=4096,4096,4096,4096,4096,4096,4096,4096,4096,4096; # Minimum value: 0 # Maximum value: RxRingSize * 10 # -RxBufPoolLimit=4096,4096,4096,4096,4096,4096,4096,4096,4096,4096; +RxBufPoolLimit=16384,16384,16384,16384,16384,16384,16384,16384,16384,16384; # EnableLSO -- # |