summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cddl/contrib/opensolaris/tools/ctf/cvt/merge.c2
-rw-r--r--crypto/openssh/readconf.c5
-rw-r--r--etc/Makefile9
-rwxr-xr-xetc/rc.d/mountcritlocal14
-rw-r--r--lib/clang/clang.lib.mk4
-rw-r--r--lib/libc++/Makefile3
-rw-r--r--lib/libc/stdlib/tdelete.c1
-rw-r--r--lib/libc/string/wcslcat.c2
-rw-r--r--lib/libc/string/wcsncat.c2
-rw-r--r--lib/libc/sys/stat.27
-rw-r--r--lib/libdpv/dpv.c6
-rw-r--r--lib/libdpv/dpv.h3
-rw-r--r--lib/libkvm/kvm_i386.h2
-rw-r--r--lib/libmd/mdXhl.c60
-rw-r--r--lib/libthr/thread/thr_umtx.c5
-rw-r--r--share/examples/pf/pf.conf4
-rw-r--r--share/man/man4/ddb.443
-rw-r--r--share/man/man4/ioat.415
-rw-r--r--share/man/man4/sfxge.46
-rw-r--r--share/mk/bsd.sys.mk5
-rw-r--r--sys/amd64/linux/linux_proto.h4
-rw-r--r--sys/amd64/linux/linux_syscall.h2
-rw-r--r--sys/amd64/linux/linux_syscalls.c2
-rw-r--r--sys/amd64/linux/linux_sysent.c2
-rw-r--r--sys/amd64/linux/linux_systrace_args.c4
-rw-r--r--sys/amd64/linux/syscalls.master4
-rw-r--r--sys/amd64/linux32/linux32_proto.h4
-rw-r--r--sys/amd64/linux32/linux32_syscall.h2
-rw-r--r--sys/amd64/linux32/linux32_syscalls.c2
-rw-r--r--sys/amd64/linux32/linux32_sysent.c2
-rw-r--r--sys/amd64/linux32/linux32_systrace_args.c4
-rw-r--r--sys/amd64/linux32/syscalls.master4
-rw-r--r--sys/arm/at91/at91_mci.c21
-rw-r--r--sys/arm/conf/IMX538
-rw-r--r--sys/arm/conf/IMX68
-rw-r--r--sys/boot/common/bootstrap.h2
-rw-r--r--sys/boot/common/module.c13
-rw-r--r--sys/boot/common/ufsread.c9
-rw-r--r--sys/boot/efi/Makefile8
-rw-r--r--sys/boot/efi/boot1/Makefile30
-rw-r--r--sys/boot/efi/boot1/boot1.c403
-rw-r--r--sys/boot/efi/boot1/boot_module.h113
-rw-r--r--sys/boot/efi/boot1/ufs_module.c253
-rw-r--r--sys/boot/efi/boot1/zfs_module.c199
-rw-r--r--sys/boot/efi/include/efilib.h4
-rw-r--r--sys/boot/efi/libefi/handles.c24
-rw-r--r--sys/boot/efi/loader/Makefile20
-rw-r--r--sys/boot/efi/loader/conf.c9
-rw-r--r--sys/boot/efi/loader/devicename.c57
-rw-r--r--sys/boot/efi/loader/main.c169
-rw-r--r--sys/boot/fdt/fdt_loader_cmd.c2
-rw-r--r--sys/boot/i386/loader/main.c29
-rw-r--r--sys/boot/userboot/test/test.c12
-rw-r--r--sys/boot/userboot/userboot/main.c27
-rw-r--r--sys/boot/zfs/libzfs.h1
-rw-r--r--sys/boot/zfs/zfs.c33
-rw-r--r--sys/boot/zfs/zfsimpl.c8
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c3
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c1
-rw-r--r--sys/compat/linux/linux_futex.c2
-rw-r--r--sys/compat/linux/linux_misc.c4
-rw-r--r--sys/compat/linuxkpi/common/include/linux/pci.h5
-rw-r--r--sys/compat/linuxkpi/common/src/linux_pci.c46
-rw-r--r--sys/conf/files.amd642
-rw-r--r--sys/conf/files.i3861
-rw-r--r--sys/contrib/vchiq/interface/vchiq_arm/vchiq_kmod.c2
-rw-r--r--sys/dev/drm2/drm_crtc.c20
-rw-r--r--sys/dev/drm2/drm_pci.c2
-rw-r--r--sys/dev/e1000/if_em.c19
-rw-r--r--sys/dev/e1000/if_em.h7
-rw-r--r--sys/dev/e1000/if_igb.c12
-rw-r--r--sys/dev/e1000/if_igb.h17
-rw-r--r--sys/dev/e1000/if_lem.c10
-rw-r--r--sys/dev/e1000/if_lem.h8
-rw-r--r--sys/dev/gpio/gpiobus.c2
-rw-r--r--sys/dev/hyperv/include/hyperv.h5
-rw-r--r--sys/dev/hyperv/netvsc/hv_net_vsc.c9
-rw-r--r--sys/dev/hyperv/netvsc/hv_net_vsc.h2
-rw-r--r--sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c8
-rw-r--r--sys/dev/hyperv/vmbus/hv_connection.c19
-rw-r--r--sys/dev/hyperv/vmbus/hv_et.c131
-rw-r--r--sys/dev/hyperv/vmbus/hv_hv.c61
-rw-r--r--sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c78
-rw-r--r--sys/dev/hyperv/vmbus/hv_vmbus_priv.h57
-rw-r--r--sys/dev/ioat/ioat.c2
-rw-r--r--sys/dev/ioat/ioat.h8
-rw-r--r--sys/dev/sfxge/common/ef10_impl.h46
-rw-r--r--sys/dev/sfxge/common/efsys.h2
-rw-r--r--sys/dev/sfxge/common/efx.h72
-rw-r--r--sys/dev/sfxge/common/efx_check.h11
-rw-r--r--sys/dev/sfxge/common/efx_impl.h29
-rw-r--r--sys/dev/sfxge/common/efx_lic.c792
-rw-r--r--sys/dev/sfxge/common/efx_mcdi.c166
-rw-r--r--sys/dev/sfxge/common/efx_mcdi.h5
-rw-r--r--sys/dev/sfxge/common/efx_nic.c52
-rw-r--r--sys/dev/sfxge/common/efx_nvram.c29
-rw-r--r--sys/dev/sfxge/common/efx_rx.c4
-rw-r--r--sys/dev/sfxge/common/efx_tx.c22
-rw-r--r--sys/dev/sfxge/common/efx_vpd.c19
-rw-r--r--sys/dev/sfxge/common/hunt_ev.c6
-rw-r--r--sys/dev/sfxge/common/hunt_impl.h91
-rw-r--r--sys/dev/sfxge/common/hunt_mac.c16
-rw-r--r--sys/dev/sfxge/common/hunt_mcdi.c145
-rw-r--r--sys/dev/sfxge/common/hunt_nic.c203
-rw-r--r--sys/dev/sfxge/common/hunt_nvram.c51
-rw-r--r--sys/dev/sfxge/common/hunt_phy.c12
-rwxr-xr-xsys/dev/sfxge/common/hunt_tx.c35
-rw-r--r--sys/dev/sfxge/common/hunt_vpd.c41
-rw-r--r--sys/dev/sfxge/common/medford_impl.h22
-rw-r--r--sys/dev/sfxge/common/medford_nic.c203
-rw-r--r--sys/dev/sfxge/common/siena_impl.h45
-rw-r--r--sys/dev/sfxge/common/siena_mcdi.c75
-rw-r--r--sys/dev/sfxge/common/siena_nic.c1
-rw-r--r--sys/dev/sfxge/common/siena_nvram.c40
-rw-r--r--sys/dev/sfxge/common/siena_vpd.c7
-rw-r--r--sys/dev/sfxge/sfxge.h5
-rw-r--r--sys/dev/sfxge/sfxge_tx.c238
-rw-r--r--sys/dev/sfxge/sfxge_tx.h1
-rw-r--r--sys/dev/usb/usb_device.c15
-rw-r--r--sys/fs/nfs/nfs_var.h2
-rw-r--r--sys/fs/nfsclient/nfs_clport.c102
-rw-r--r--sys/fs/nfsclient/nfs_clrpcops.c3
-rw-r--r--sys/geom/geom_disk.c17
-rw-r--r--sys/i386/linux/linux_proto.h2
-rw-r--r--sys/i386/linux/linux_syscall.h2
-rw-r--r--sys/i386/linux/linux_syscalls.c2
-rw-r--r--sys/i386/linux/linux_sysent.c2
-rw-r--r--sys/i386/linux/syscalls.master4
-rw-r--r--sys/kern/kern_prot.c3
-rw-r--r--sys/kern/vfs_aio.c17
-rw-r--r--sys/modules/hyperv/vmbus/Makefile3
-rw-r--r--sys/modules/sfxge/Makefile2
-rw-r--r--sys/net/radix_mpath.c11
-rw-r--r--sys/net/route.c64
-rw-r--r--sys/net/route.h12
-rw-r--r--sys/netgraph/netflow/netflow.c100
-rw-r--r--sys/netinet/in_rmx.c12
-rw-r--r--sys/netinet/in_var.h2
-rw-r--r--sys/netinet/ip_mroute.c2
-rw-r--r--sys/netinet/sctp_pcb.c8
-rw-r--r--sys/netinet/sctp_usrreq.c18
-rw-r--r--sys/netinet/tcp_output.c6
-rw-r--r--sys/netinet6/sctp6_usrreq.c5
-rw-r--r--sys/powerpc/include/vmparam.h4
-rw-r--r--sys/sys/param.h2
-rw-r--r--sys/sys/ucred.h1
-rw-r--r--sys/x86/x86/identcpu.c2
-rw-r--r--tests/sys/geom/class/gate/1_test.sh3
-rwxr-xr-xtests/sys/geom/class/gate/conf.sh2
-rw-r--r--usr.bin/clang/clang/Makefile4
-rw-r--r--usr.bin/clang/lldb/Makefile3
-rw-r--r--usr.bin/numactl/numactl.c11
-rw-r--r--usr.sbin/boot0cfg/boot0cfg.c3
-rwxr-xr-xusr.sbin/bsdinstall/scripts/auto2
-rw-r--r--usr.sbin/kldxref/ef_aarch64.c77
155 files changed, 3819 insertions, 1436 deletions
diff --git a/cddl/contrib/opensolaris/tools/ctf/cvt/merge.c b/cddl/contrib/opensolaris/tools/ctf/cvt/merge.c
index d366f3182731..5b22a31140d7 100644
--- a/cddl/contrib/opensolaris/tools/ctf/cvt/merge.c
+++ b/cddl/contrib/opensolaris/tools/ctf/cvt/merge.c
@@ -283,7 +283,6 @@ static int
equiv_su(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed)
{
mlist_t *ml1 = stdp->t_members, *ml2 = ttdp->t_members;
- mlist_t *olm1 = NULL;
while (ml1 && ml2) {
if (ml1->ml_offset != ml2->ml_offset ||
@@ -292,7 +291,6 @@ equiv_su(tdesc_t *stdp, tdesc_t *ttdp, equiv_data_t *ed)
!equiv_node(ml1->ml_type, ml2->ml_type, ed))
return (0);
- olm1 = ml1;
ml1 = ml1->ml_next;
ml2 = ml2->ml_next;
}
diff --git a/crypto/openssh/readconf.c b/crypto/openssh/readconf.c
index 700a79b50ce9..9cf6ab9bae8e 100644
--- a/crypto/openssh/readconf.c
+++ b/crypto/openssh/readconf.c
@@ -1610,7 +1610,7 @@ initialize_options(Options * options)
options->tun_remote = -1;
options->local_command = NULL;
options->permit_local_command = -1;
- options->use_roaming = -1;
+ options->use_roaming = 0;
options->visual_host_key = -1;
options->ip_qos_interactive = -1;
options->ip_qos_bulk = -1;
@@ -1788,8 +1788,7 @@ fill_default_options(Options * options)
options->tun_remote = SSH_TUNID_ANY;
if (options->permit_local_command == -1)
options->permit_local_command = 0;
- if (options->use_roaming == -1)
- options->use_roaming = 1;
+ options->use_roaming = 0;
if (options->visual_host_key == -1)
options->visual_host_key = 0;
if (options->ip_qos_interactive == -1)
diff --git a/etc/Makefile b/etc/Makefile
index 5484c11e1424..27d1ba447b9e 100644
--- a/etc/Makefile
+++ b/etc/Makefile
@@ -82,10 +82,6 @@ BIN1+= apmd.conf
BIN1+= auto_master
.endif
-.if ${MK_BSNMP} != "no"
-BIN1+= snmpd.config
-.endif
-
.if ${MK_FREEBSD_UPDATE} != "no"
BIN1+= freebsd-update.conf
.endif
@@ -219,6 +215,11 @@ distribution:
${BIN2} ${DESTDIR}/etc; \
${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 600 \
master.passwd nsmb.conf opieaccess ${DESTDIR}/etc;
+.if ${MK_BSNMP} != "no"
+ cd ${.CURDIR}; \
+ ${INSTALL} -o ${BINOWN} -g ${BINGRP} -m 600 \
+ snmpd.config ${DESTDIR}/etc;
+.endif
.if ${MK_AT} == "no"
sed -i "" -e 's;.*/usr/libexec/atrun;#&;' ${DESTDIR}/etc/crontab
.endif
diff --git a/etc/rc.d/mountcritlocal b/etc/rc.d/mountcritlocal
index 1513ec7397ac..069e3fda48fd 100755
--- a/etc/rc.d/mountcritlocal
+++ b/etc/rc.d/mountcritlocal
@@ -36,15 +36,15 @@ mountcritlocal_start()
done
mount_excludes=${mount_excludes%,}
- # Originally, root mount hold had to be released before mounting the root
- # filesystem. This delayed the boot, so it was changed to only wait if
- # the root device isn't readily available. This can result in this script
- # executing before all the devices - such as graid(8) - are available.
- # Thus, should the mount fail, we will wait for the root mount hold release
- # and retry.
+ # Originally, root mount hold had to be released before mounting
+ # the root filesystem. This delayed the boot, so it was changed
+ # to only wait if the root device isn't readily available. This
+ # can result in this script executing before all the devices - such
+ # as graid(8) - are available. Thus, should the mount fail,
+ # we will wait for the root mount hold release and retry.
mount -a -t ${mount_excludes}
err=$?
- if [ $? -ne 0 ]; then
+ if [ ${err} -ne 0 ]; then
echo
echo 'Mounting /etc/fstab filesystems failed,' \
'will retry after root mount hold release'
diff --git a/lib/clang/clang.lib.mk b/lib/clang/clang.lib.mk
index 13afa85bf4cc..ab3551e2d4f7 100644
--- a/lib/clang/clang.lib.mk
+++ b/lib/clang/clang.lib.mk
@@ -6,4 +6,8 @@ LLVM_SRCS= ${.CURDIR}/../../../contrib/llvm
INTERNALLIB=
+.if ${MACHINE_CPUARCH} == "arm"
+STATIC_CXXFLAGS+= -mlong-calls
+.endif
+
.include <bsd.lib.mk>
diff --git a/lib/libc++/Makefile b/lib/libc++/Makefile
index d81710ef5364..94e91b94b003 100644
--- a/lib/libc++/Makefile
+++ b/lib/libc++/Makefile
@@ -6,6 +6,9 @@ _LIBCXXRTDIR= ${.CURDIR}/../../contrib/libcxxrt
HDRDIR= ${.CURDIR}/../../contrib/libc++/include
SRCDIR= ${.CURDIR}/../../contrib/libc++/src
CXXINCLUDEDIR= ${INCLUDEDIR}/c++/v${SHLIB_MAJOR}
+.if ${MACHINE_CPUARCH} == "arm"
+STATIC_CXXFLAGS+= -mlong-calls
+.endif
.PATH: ${SRCDIR}
diff --git a/lib/libc/stdlib/tdelete.c b/lib/libc/stdlib/tdelete.c
index 7799f35cc1e7..ff63576a1bf5 100644
--- a/lib/libc/stdlib/tdelete.c
+++ b/lib/libc/stdlib/tdelete.c
@@ -62,7 +62,6 @@ __FBSDID("$FreeBSD$");
base = leaf; \
path_init(&path); \
} \
- result = &(*leaf)->key; \
path_taking_right(&path); \
leaf = &(*leaf)->rlink; \
} while (0)
diff --git a/lib/libc/string/wcslcat.c b/lib/libc/string/wcslcat.c
index f5f1e1ee7559..2df94777d51f 100644
--- a/lib/libc/string/wcslcat.c
+++ b/lib/libc/string/wcslcat.c
@@ -54,7 +54,7 @@ wcslcat(wchar_t *dst, const wchar_t *src, size_t siz)
size_t dlen;
/* Find the end of dst and adjust bytes left but don't go past end */
- while (*d != '\0' && n-- != 0)
+ while (n-- != 0 && *d != '\0')
d++;
dlen = d - dst;
n = siz - dlen;
diff --git a/lib/libc/string/wcsncat.c b/lib/libc/string/wcsncat.c
index 44f1ff98980c..5a243477db5b 100644
--- a/lib/libc/string/wcsncat.c
+++ b/lib/libc/string/wcsncat.c
@@ -48,7 +48,7 @@ wcsncat(wchar_t * __restrict s1, const wchar_t * __restrict s2, size_t n)
p++;
q = p;
r = s2;
- while (*r && n) {
+ while (n && *r) {
*q++ = *r++;
n--;
}
diff --git a/lib/libc/sys/stat.2 b/lib/libc/sys/stat.2
index 5e49b3c0b992..3405d6e3511c 100644
--- a/lib/libc/sys/stat.2
+++ b/lib/libc/sys/stat.2
@@ -28,7 +28,7 @@
.\" @(#)stat.2 8.4 (Berkeley) 5/1/95
.\" $FreeBSD$
.\"
-.Dd June 2, 2012
+.Dd January 14, 2016
.Dt STAT 2
.Os
.Sh NAME
@@ -40,12 +40,11 @@
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
-.In sys/types.h
.In sys/stat.h
.Ft int
-.Fn stat "const char *path" "struct stat *sb"
+.Fn stat "const char * restrict path" "struct stat * restrict sb"
.Ft int
-.Fn lstat "const char *path" "struct stat *sb"
+.Fn lstat "const char * restrict path" "struct stat * restrict sb"
.Ft int
.Fn fstat "int fd" "struct stat *sb"
.Ft int
diff --git a/lib/libdpv/dpv.c b/lib/libdpv/dpv.c
index 6a03922ff9fd..d3506ca9d82d 100644
--- a/lib/libdpv/dpv.c
+++ b/lib/libdpv/dpv.c
@@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
#include <dialog.h>
#include <err.h>
#include <limits.h>
+#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -482,6 +483,11 @@ dpv(struct dpv_config *config, struct dpv_file_node *file_list)
/* Reads: label_size pbar_size pprompt aprompt dpv_nfiles */
/* Inits: dheight and dwidth */
+ /* Default localeconv(3) settings for dialog(3) status */
+ setlocale(LC_NUMERIC,
+ getenv("LC_ALL") == NULL && getenv("LC_NUMERIC") == NULL ?
+ LC_NUMERIC_DEFAULT : "");
+
if (!debug) {
/* Internally create the initial `--gauge' prompt text */
dprompt_recreate(file_list, (struct dpv_file_node *)NULL, 0);
diff --git a/lib/libdpv/dpv.h b/lib/libdpv/dpv.h
index dbcd59bd67c0..03768a7ced40 100644
--- a/lib/libdpv/dpv.h
+++ b/lib/libdpv/dpv.h
@@ -38,6 +38,9 @@
#define FALSE 0
#endif
+/* localeconv(3) */
+#define LC_NUMERIC_DEFAULT "en_US.ISO8859-1"
+
/* Data to process */
extern long long dpv_overall_read;
diff --git a/lib/libkvm/kvm_i386.h b/lib/libkvm/kvm_i386.h
index 2949e6893024..51eb6f8f7f70 100644
--- a/lib/libkvm/kvm_i386.h
+++ b/lib/libkvm/kvm_i386.h
@@ -70,7 +70,7 @@ _Static_assert(NBPDR == I386_NBPDR, "NBPDR mismatch");
_Static_assert(PG_V == I386_PG_V, "PG_V mismatch");
_Static_assert(PG_PS == I386_PG_PS, "PG_PS mismatch");
-_Static_assert(PG_FRAME == I386_PG_FRAME, "PG_FRAME mismatch");
+_Static_assert((u_int)PG_FRAME == I386_PG_FRAME, "PG_FRAME mismatch");
_Static_assert(PG_PS_FRAME == I386_PG_PS_FRAME, "PG_PS_FRAME mismatch");
#endif
diff --git a/lib/libmd/mdXhl.c b/lib/libmd/mdXhl.c
index 378d8adfafc0..6ed214bce844 100644
--- a/lib/libmd/mdXhl.c
+++ b/lib/libmd/mdXhl.c
@@ -1,4 +1,5 @@
-/* mdXhl.c * ----------------------------------------------------------------------------
+/* mdXhl.c
+ * ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <phk@FreeBSD.org> wrote this file. As long as you retain this notice you
* can do whatever you want with this stuff. If we meet some day, and you think
@@ -52,43 +53,44 @@ MDXFileChunk(const char *filename, char *buf, off_t ofs, off_t len)
unsigned char buffer[16*1024];
MDX_CTX ctx;
struct stat stbuf;
- int f, i, e;
- off_t n;
+ int fd, readrv, e;
+ off_t remain;
- MDXInit(&ctx);
- f = open(filename, O_RDONLY);
- if (f < 0)
- return 0;
- if (fstat(f, &stbuf) < 0) {
- i = -1;
- goto error;
+ if (len < 0) {
+ errno = EINVAL;
+ return NULL;
}
- if (ofs > stbuf.st_size)
- ofs = stbuf.st_size;
- if ((len == 0) || (len > stbuf.st_size - ofs))
- len = stbuf.st_size - ofs;
- if (lseek(f, ofs, SEEK_SET) < 0) {
- i = -1;
- goto error;
+
+ MDXInit(&ctx);
+ fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ return NULL;
+ if (ofs != 0) {
+ errno = 0;
+ if (lseek(fd, ofs, SEEK_SET) != ofs ||
+ (ofs == -1 && errno != 0)) {
+ readrv = -1;
+ goto error;
+ }
}
- n = len;
- i = 0;
- while (n > 0) {
- if (n > sizeof(buffer))
- i = read(f, buffer, sizeof(buffer));
+ remain = len;
+ readrv = 0;
+ while (len == 0 || remain > 0) {
+ if (len == 0 || remain > sizeof(buffer))
+ readrv = read(fd, buffer, sizeof(buffer));
else
- i = read(f, buffer, n);
- if (i <= 0)
+ readrv = read(fd, buffer, remain);
+ if (readrv <= 0)
break;
- MDXUpdate(&ctx, buffer, i);
- n -= i;
+ MDXUpdate(&ctx, buffer, readrv);
+ remain -= readrv;
}
error:
e = errno;
- close(f);
+ close(fd);
errno = e;
- if (i < 0)
- return 0;
+ if (readrv < 0)
+ return NULL;
return (MDXEnd(&ctx, buf));
}
diff --git a/lib/libthr/thread/thr_umtx.c b/lib/libthr/thread/thr_umtx.c
index a61dab023f52..37e5df183eb8 100644
--- a/lib/libthr/thread/thr_umtx.c
+++ b/lib/libthr/thread/thr_umtx.c
@@ -42,7 +42,7 @@ int _umtx_op_err(void *obj, int op, u_long val, void *uaddr, void *uaddr2)
void
_thr_umutex_init(struct umutex *mtx)
{
- static struct umutex default_mtx = DEFAULT_UMUTEX;
+ static const struct umutex default_mtx = DEFAULT_UMUTEX;
*mtx = default_mtx;
}
@@ -50,7 +50,8 @@ _thr_umutex_init(struct umutex *mtx)
void
_thr_urwlock_init(struct urwlock *rwl)
{
- static struct urwlock default_rwl = DEFAULT_URWLOCK;
+ static const struct urwlock default_rwl = DEFAULT_URWLOCK;
+
*rwl = default_rwl;
}
diff --git a/share/examples/pf/pf.conf b/share/examples/pf/pf.conf
index d97b4ede16e3..950b47c7ba44 100644
--- a/share/examples/pf/pf.conf
+++ b/share/examples/pf/pf.conf
@@ -2,8 +2,8 @@
# $OpenBSD: pf.conf,v 1.34 2007/02/24 19:30:59 millert Exp $
#
# See pf.conf(5) and /usr/share/examples/pf for syntax and examples.
-# Remember to set net.inet.ip.forwarding=1 and/or net.inet6.ip6.forwarding=1
-# in /etc/sysctl.conf if packets are to be forwarded between interfaces.
+# Remember to set gateway_enable="YES" and/or ipv6_gateway_enable="YES"
+# in /etc/rc.conf if packets are to be forwarded between interfaces.
#ext_if="ext0"
#int_if="int0"
diff --git a/share/man/man4/ddb.4 b/share/man/man4/ddb.4
index d29bcdda78a0..83bf001a8e1f 100644
--- a/share/man/man4/ddb.4
+++ b/share/man/man4/ddb.4
@@ -60,7 +60,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd November 5, 2015
+.Dd January 14, 2016
.Dt DDB 4
.Os
.Sh NAME
@@ -1435,6 +1435,47 @@ The NMI allows one to break into the debugger on a wedged machine to
diagnose problems.
Other bus' bridge chipsets may be able to generate NMI using bus specific
methods.
+There are many PCI and PCIe add-in cards which can generate NMI for
+debugging.
+Modern systems typically use IPMI to generate signals to enter the
+debugger.
+The
+.Dv devel/ipmitool
+port can be used to send the
+.Cd chassis power diag
+command which delivers an NMI to the processor.
+.Pp
+For serial consoles, you can break to the debugger by sending a BREAK
+condition on the serial line if
+.Cd options BREAK_TO_DEBUGGER
+is specified in the kernel.
+Most terminal emulation programs can send a break sequence with a
+special key sequence or via a menu item.
+However, in some setups, sending the break can be difficult to arrange
+or happens spuriously, so if the kernel contains
+.Cd options ALT_BREAK_TO_DEBUGGER
+then the sequence of CR TILDE CTRL-B enters the debugger;
+CR TILDE CTRL-P causes a panic instead of entering the
+debugger; and
+CR TILDE CTRL-R causes an immediate reboot.
+In all the above sequences, CR is a Carriage Return and is usually
+sent by hitting the Enter or Return key.
+TILDE is the ASCII tilde character (~).
+CTRL-x is Control x created by hitting the control key and then x
+and then releasing both.
+.Pp
+The break to debugger behavior may also be enabled by setting the
+.Xr sysctl 8
+.Dv debug.kdb.break_to_debugger
+to 1.
+The alt break to debugger behavior may also be enabled by setting the
+.Xr sysctl 8
+.Dv debug.kdb.alt_break_to_debugger
+to 1.
+The debugger may be entered by setting the
+.Xr sysctl 8
+.Dv debug.kdb.enter
+to 1.
.Sh FILES
Header files mentioned in this manual page can be found below
.Pa /usr/include
diff --git a/share/man/man4/ioat.4 b/share/man/man4/ioat.4
index 10f2663ed8f0..e71c2e12b745 100644
--- a/share/man/man4/ioat.4
+++ b/share/man/man4/ioat.4
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd January 7, 2016
+.Dd January 14, 2016
.Dt IOAT 4
.Os
.Sh NAME
@@ -134,7 +134,7 @@ Null operations do nothing, but may be used to test the interrupt and callback
mechanism.
.Pp
All operations can optionally trigger an interrupt at completion with the
-.Ar DMA_EN_INT
+.Ar DMA_INT_EN
flag.
For example, a user might submit multiple operations to the same channel and
only enable an interrupt and callback for the last operation.
@@ -160,6 +160,17 @@ flag.
.Ar DMA_NO_WAIT
may return NULL.)
.Pp
+Operations that depend on the result of prior operations should use
+.Ar DMA_FENCE .
+For example, such a scenario can happen when two related DMA operations are
+queued.
+First, a DMA copy to one location (A), followed directly by a DMA copy
+from A to B.
+In this scenario, some classes of I/OAT hardware may prefetch A for the second
+operation before it is written by the first operation.
+To avoid reading a stale value in sequences of dependent operations, use
+.Ar DMA_FENCE .
+.Pp
All operations, as well as
.Fn ioat_get_dmaengine ,
can return NULL in special circumstances.
diff --git a/share/man/man4/sfxge.4 b/share/man/man4/sfxge.4
index 81e2af4bf26f..7ddd684b6535 100644
--- a/share/man/man4/sfxge.4
+++ b/share/man/man4/sfxge.4
@@ -121,8 +121,10 @@ If a packet is dropped, the
counter is incremented and the local sender receives ENOBUFS.
The value must be greater than or equal to 0.
.It Va hw.sfxge.tso_fw_assisted
-Enable/disable usage of FW-assisted TSO if supported by NIC firmware.
-Enabled by default.
+Bitmask to enable/disable usage of FW-assisted TSO version if supported
+by NIC firmware.
+FATSOv1 (bit 0) and FATSOv2 (bit 1) are supported.
+All enabled by default.
.It Va hw.sfxge.N.max_rss_channels
The maximum number of allocated RSS channels for the Nth adapter.
If set to 0 or unset, the number of channels is determined by the number
diff --git a/share/mk/bsd.sys.mk b/share/mk/bsd.sys.mk
index de62195b84fd..7ac7917e9e89 100644
--- a/share/mk/bsd.sys.mk
+++ b/share/mk/bsd.sys.mk
@@ -164,10 +164,11 @@ SSP_CFLAGS?= -fstack-protector
CFLAGS+= ${SSP_CFLAGS}
.endif # SSP && !ARM && !MIPS
-# Allow user-specified additional warning flags, plus compiler specific flag overrides.
-# Unless we've overriden this...
+# Allow user-specified additional warning flags, plus compiler and file
+# specific flag overrides, unless we've overriden this...
.if ${MK_WARNS} != "no"
CFLAGS+= ${CWARNFLAGS} ${CWARNFLAGS.${COMPILER_TYPE}}
+CFLAGS+= ${CWARNFLAGS.${.IMPSRC:T}}
.endif
CFLAGS+= ${CFLAGS.${COMPILER_TYPE}}
diff --git a/sys/amd64/linux/linux_proto.h b/sys/amd64/linux/linux_proto.h
index 8aecd7c0f976..54e11fe8bdfc 100644
--- a/sys/amd64/linux/linux_proto.h
+++ b/sys/amd64/linux/linux_proto.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/amd64/linux/syscalls.master 289769 2015-10-22 21:28:20Z jhb
+ * created from FreeBSD: head/sys/amd64/linux/syscalls.master 293907 2016-01-14 10:13:58Z glebius
*/
#ifndef _LINUX_SYSPROTO_H_
@@ -966,7 +966,7 @@ struct linux_set_robust_list_args {
};
struct linux_get_robust_list_args {
char pid_l_[PADL_(l_int)]; l_int pid; char pid_r_[PADR_(l_int)];
- char head_l_[PADL_(struct linux_robust_list_head *)]; struct linux_robust_list_head * head; char head_r_[PADR_(struct linux_robust_list_head *)];
+ char head_l_[PADL_(struct linux_robust_list_head **)]; struct linux_robust_list_head ** head; char head_r_[PADR_(struct linux_robust_list_head **)];
char len_l_[PADL_(l_size_t *)]; l_size_t * len; char len_r_[PADR_(l_size_t *)];
};
struct linux_splice_args {
diff --git a/sys/amd64/linux/linux_syscall.h b/sys/amd64/linux/linux_syscall.h
index 671eb0b344d7..cee28556b237 100644
--- a/sys/amd64/linux/linux_syscall.h
+++ b/sys/amd64/linux/linux_syscall.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/amd64/linux/syscalls.master 289769 2015-10-22 21:28:20Z jhb
+ * created from FreeBSD: head/sys/amd64/linux/syscalls.master 293907 2016-01-14 10:13:58Z glebius
*/
#define LINUX_SYS_read 0
diff --git a/sys/amd64/linux/linux_syscalls.c b/sys/amd64/linux/linux_syscalls.c
index a414ea0cebaf..ea001ba68467 100644
--- a/sys/amd64/linux/linux_syscalls.c
+++ b/sys/amd64/linux/linux_syscalls.c
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/amd64/linux/syscalls.master 289769 2015-10-22 21:28:20Z jhb
+ * created from FreeBSD: head/sys/amd64/linux/syscalls.master 293907 2016-01-14 10:13:58Z glebius
*/
const char *linux_syscallnames[] = {
diff --git a/sys/amd64/linux/linux_sysent.c b/sys/amd64/linux/linux_sysent.c
index 31f2eeb02e4d..053f8d1e415d 100644
--- a/sys/amd64/linux/linux_sysent.c
+++ b/sys/amd64/linux/linux_sysent.c
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/amd64/linux/syscalls.master 289769 2015-10-22 21:28:20Z jhb
+ * created from FreeBSD: head/sys/amd64/linux/syscalls.master 293907 2016-01-14 10:13:58Z glebius
*/
#include <sys/param.h>
diff --git a/sys/amd64/linux/linux_systrace_args.c b/sys/amd64/linux/linux_systrace_args.c
index d649eed3d4de..bc279c947ec1 100644
--- a/sys/amd64/linux/linux_systrace_args.c
+++ b/sys/amd64/linux/linux_systrace_args.c
@@ -2020,7 +2020,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
case 274: {
struct linux_get_robust_list_args *p = params;
iarg[0] = p->pid; /* l_int */
- uarg[1] = (intptr_t) p->head; /* struct linux_robust_list_head * */
+ uarg[1] = (intptr_t) p->head; /* struct linux_robust_list_head ** */
uarg[2] = (intptr_t) p->len; /* l_size_t * */
*n_args = 3;
break;
@@ -5347,7 +5347,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "l_int";
break;
case 1:
- p = "struct linux_robust_list_head *";
+ p = "struct linux_robust_list_head **";
break;
case 2:
p = "l_size_t *";
diff --git a/sys/amd64/linux/syscalls.master b/sys/amd64/linux/syscalls.master
index 87c800079b14..eb36d5f2ec90 100644
--- a/sys/amd64/linux/syscalls.master
+++ b/sys/amd64/linux/syscalls.master
@@ -461,8 +461,8 @@
272 AUE_NULL STD { int linux_unshare(void); }
273 AUE_NULL STD { int linux_set_robust_list(struct linux_robust_list_head *head, \
l_size_t len); }
-274 AUE_NULL STD { int linux_get_robust_list(l_int pid, struct linux_robust_list_head *head, \
- l_size_t *len); }
+274 AUE_NULL STD { int linux_get_robust_list(l_int pid, \
+ struct linux_robust_list_head **head, l_size_t *len); }
275 AUE_NULL STD { int linux_splice(void); }
276 AUE_NULL STD { int linux_tee(void); }
277 AUE_NULL STD { int linux_sync_file_range(void); }
diff --git a/sys/amd64/linux32/linux32_proto.h b/sys/amd64/linux32/linux32_proto.h
index 84c78152a7ab..e76384fb445b 100644
--- a/sys/amd64/linux32/linux32_proto.h
+++ b/sys/amd64/linux32/linux32_proto.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/amd64/linux32/syscalls.master 289769 2015-10-22 21:28:20Z jhb
+ * created from FreeBSD: head/sys/amd64/linux32/syscalls.master 293907 2016-01-14 10:13:58Z glebius
*/
#ifndef _LINUX32_SYSPROTO_H_
@@ -1023,7 +1023,7 @@ struct linux_set_robust_list_args {
};
struct linux_get_robust_list_args {
char pid_l_[PADL_(l_int)]; l_int pid; char pid_r_[PADR_(l_int)];
- char head_l_[PADL_(struct linux_robust_list_head *)]; struct linux_robust_list_head * head; char head_r_[PADR_(struct linux_robust_list_head *)];
+ char head_l_[PADL_(struct linux_robust_list_head **)]; struct linux_robust_list_head ** head; char head_r_[PADR_(struct linux_robust_list_head **)];
char len_l_[PADL_(l_size_t *)]; l_size_t * len; char len_r_[PADR_(l_size_t *)];
};
struct linux_splice_args {
diff --git a/sys/amd64/linux32/linux32_syscall.h b/sys/amd64/linux32/linux32_syscall.h
index a3fbb26bb41c..990adf3642ed 100644
--- a/sys/amd64/linux32/linux32_syscall.h
+++ b/sys/amd64/linux32/linux32_syscall.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/amd64/linux32/syscalls.master 289769 2015-10-22 21:28:20Z jhb
+ * created from FreeBSD: head/sys/amd64/linux32/syscalls.master 293907 2016-01-14 10:13:58Z glebius
*/
#define LINUX32_SYS_linux_exit 1
diff --git a/sys/amd64/linux32/linux32_syscalls.c b/sys/amd64/linux32/linux32_syscalls.c
index f3b4510177a0..79b96a71bf2a 100644
--- a/sys/amd64/linux32/linux32_syscalls.c
+++ b/sys/amd64/linux32/linux32_syscalls.c
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/amd64/linux32/syscalls.master 289769 2015-10-22 21:28:20Z jhb
+ * created from FreeBSD: head/sys/amd64/linux32/syscalls.master 293907 2016-01-14 10:13:58Z glebius
*/
const char *linux32_syscallnames[] = {
diff --git a/sys/amd64/linux32/linux32_sysent.c b/sys/amd64/linux32/linux32_sysent.c
index 6f0420dec634..7d6d22078f83 100644
--- a/sys/amd64/linux32/linux32_sysent.c
+++ b/sys/amd64/linux32/linux32_sysent.c
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/amd64/linux32/syscalls.master 289769 2015-10-22 21:28:20Z jhb
+ * created from FreeBSD: head/sys/amd64/linux32/syscalls.master 293907 2016-01-14 10:13:58Z glebius
*/
#include "opt_compat.h"
diff --git a/sys/amd64/linux32/linux32_systrace_args.c b/sys/amd64/linux32/linux32_systrace_args.c
index b6ccd334178f..80889bf83b62 100644
--- a/sys/amd64/linux32/linux32_systrace_args.c
+++ b/sys/amd64/linux32/linux32_systrace_args.c
@@ -2122,7 +2122,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
case 312: {
struct linux_get_robust_list_args *p = params;
iarg[0] = p->pid; /* l_int */
- uarg[1] = (intptr_t) p->head; /* struct linux_robust_list_head * */
+ uarg[1] = (intptr_t) p->head; /* struct linux_robust_list_head ** */
uarg[2] = (intptr_t) p->len; /* l_size_t * */
*n_args = 3;
break;
@@ -5551,7 +5551,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "l_int";
break;
case 1:
- p = "struct linux_robust_list_head *";
+ p = "struct linux_robust_list_head **";
break;
case 2:
p = "l_size_t *";
diff --git a/sys/amd64/linux32/syscalls.master b/sys/amd64/linux32/syscalls.master
index 8d9f90c21043..0396b30db9c8 100644
--- a/sys/amd64/linux32/syscalls.master
+++ b/sys/amd64/linux32/syscalls.master
@@ -520,8 +520,8 @@
; linux 2.6.17:
311 AUE_NULL STD { int linux_set_robust_list(struct linux_robust_list_head *head, \
l_size_t len); }
-312 AUE_NULL STD { int linux_get_robust_list(l_int pid, struct linux_robust_list_head *head, \
- l_size_t *len); }
+312 AUE_NULL STD { int linux_get_robust_list(l_int pid, \
+ struct linux_robust_list_head **head, l_size_t *len); }
313 AUE_NULL STD { int linux_splice(void); }
314 AUE_NULL STD { int linux_sync_file_range(void); }
315 AUE_NULL STD { int linux_tee(void); }
diff --git a/sys/arm/at91/at91_mci.c b/sys/arm/at91/at91_mci.c
index 8e55e02f6f1e..5bab815202a3 100644
--- a/sys/arm/at91/at91_mci.c
+++ b/sys/arm/at91/at91_mci.c
@@ -446,6 +446,9 @@ at91_mci_attach(device_t dev)
CTLFLAG_RW, &sc->allow_overclock, 0,
"Allow up to 30MHz clock for 25MHz request when next highest speed 15MHz or less.");
+ SYSCTL_ADD_UINT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "debug",
+ CTLFLAG_RWTUN, &mci_debug, 0, "enable debug output");
+
/*
* Our real min freq is master_clock/512, but upper driver layers are
* going to set the min speed during card discovery, and the right speed
@@ -783,15 +786,6 @@ at91_mci_start_cmd(struct at91_mci_softc *sc, struct mmc_command *cmd)
WR4(sc, PDC_PTCR, PDC_PTCR_RXTEN);
} else {
len = min(BBSIZE, remaining);
- /*
- * If this is MCI1 revision 2xx controller, apply
- * a work-around for the "Data Write Operation and
- * number of bytes" erratum.
- */
- if ((sc->sc_cap & CAP_MCI1_REV2XX) && len < 12) {
- len = 12;
- memset(sc->bbuf_vaddr[0], 0, 12);
- }
at91_bswap_buf(sc, sc->bbuf_vaddr[0], data->data, len);
err = bus_dmamap_load(sc->dmatag, sc->bbuf_map[0],
sc->bbuf_vaddr[0], len, at91_mci_getaddr,
@@ -800,8 +794,13 @@ at91_mci_start_cmd(struct at91_mci_softc *sc, struct mmc_command *cmd)
panic("IO write dmamap_load failed\n");
bus_dmamap_sync(sc->dmatag, sc->bbuf_map[0],
BUS_DMASYNC_PREWRITE);
+ /*
+ * Erratum workaround: PDC transfer length on a write
+ * must not be smaller than 12 bytes (3 words); only
+ * blklen bytes (set above) are actually transferred.
+ */
WR4(sc, PDC_TPR,paddr);
- WR4(sc, PDC_TCR, len / 4);
+ WR4(sc, PDC_TCR, (len < 12) ? 3 : len / 4);
sc->bbuf_len[0] = len;
remaining -= len;
if (remaining == 0) {
@@ -818,7 +817,7 @@ at91_mci_start_cmd(struct at91_mci_softc *sc, struct mmc_command *cmd)
bus_dmamap_sync(sc->dmatag, sc->bbuf_map[1],
BUS_DMASYNC_PREWRITE);
WR4(sc, PDC_TNPR, paddr);
- WR4(sc, PDC_TNCR, len / 4);
+ WR4(sc, PDC_TNCR, (len < 12) ? 3 : len / 4);
sc->bbuf_len[1] = len;
remaining -= len;
}
diff --git a/sys/arm/conf/IMX53 b/sys/arm/conf/IMX53
index 7fe97a290a02..972437516e38 100644
--- a/sys/arm/conf/IMX53
+++ b/sys/arm/conf/IMX53
@@ -136,11 +136,3 @@ device wlan_amrr # AMRR transmit rate control algorithm
# Flattened Device Tree
options FDT # Configure using FDT/DTB data
-
-# NOTE: serial console will be disabled if syscons enabled
-# Uncomment following lines for framebuffer/syscons support
-#device sc
-#device vt
-#device kbdmux
-#options SC_DFLT_FONT # compile font in
-#makeoptions SC_DFLT_FONT=cp437
diff --git a/sys/arm/conf/IMX6 b/sys/arm/conf/IMX6
index 6de7c26e549c..6b383e28ccfd 100644
--- a/sys/arm/conf/IMX6
+++ b/sys/arm/conf/IMX6
@@ -125,14 +125,6 @@ device u3g # USB modems
#device wlan_tkip # 802.11 TKIP support
#device wlan_amrr # AMRR transmit rate control algorithm
-# NOTE: serial console will be disabled if syscons enabled
-# Uncomment following lines for framebuffer/syscons support
-# Wandboard has no video console support yet.
-#device sc
-#device kbdmux
-#options SC_DFLT_FONT # compile font in
-#makeoptions SC_DFLT_FONT=cp437
-
device vt
device kbdmux
device ukbd
diff --git a/sys/boot/common/bootstrap.h b/sys/boot/common/bootstrap.h
index 78d742d62718..7efc2c2ddc68 100644
--- a/sys/boot/common/bootstrap.h
+++ b/sys/boot/common/bootstrap.h
@@ -237,7 +237,7 @@ void unload(void);
struct preloaded_file *file_alloc(void);
struct preloaded_file *file_findfile(const char *name, const char *type);
struct file_metadata *file_findmetadata(struct preloaded_file *fp, int type);
-struct preloaded_file *file_loadraw(char *name, char *type, int insert);
+struct preloaded_file *file_loadraw(const char *name, char *type, int insert);
void file_discard(struct preloaded_file *fp);
void file_addmetadata(struct preloaded_file *fp, int type, size_t size, void *p);
int file_addmodule(struct preloaded_file *fp, char *modname, int version,
diff --git a/sys/boot/common/module.c b/sys/boot/common/module.c
index d73f1c8d0fb9..923da5b4a795 100644
--- a/sys/boot/common/module.c
+++ b/sys/boot/common/module.c
@@ -388,14 +388,14 @@ file_load_dependencies(struct preloaded_file *base_file)
}
/*
- * We've been asked to load (name) as (type), so just suck it in,
+ * We've been asked to load (fname) as (type), so just suck it in,
* no arguments or anything.
*/
struct preloaded_file *
-file_loadraw(char *name, char *type, int insert)
+file_loadraw(const char *fname, char *type, int insert)
{
struct preloaded_file *fp;
- char *cp;
+ char *name;
int fd, got;
vm_offset_t laddr;
@@ -406,12 +406,11 @@ file_loadraw(char *name, char *type, int insert)
}
/* locate the file on the load path */
- cp = file_search(name, NULL);
- if (cp == NULL) {
- sprintf(command_errbuf, "can't find '%s'", name);
+ name = file_search(fname, NULL);
+ if (name == NULL) {
+ sprintf(command_errbuf, "can't find '%s'", fname);
return(NULL);
}
- name = cp;
if ((fd = open(name, O_RDONLY)) < 0) {
sprintf(command_errbuf, "can't open '%s': %s", name, strerror(errno));
diff --git a/sys/boot/common/ufsread.c b/sys/boot/common/ufsread.c
index acff1e56b84e..08ab697d881b 100644
--- a/sys/boot/common/ufsread.c
+++ b/sys/boot/common/ufsread.c
@@ -187,8 +187,15 @@ fsread(ufs_ino_t inode, void *buf, size_t nbyte)
blkbuf = dmadat->blkbuf;
indbuf = dmadat->indbuf;
- if (!dsk_meta) {
+
+ /*
+ * Force probe if inode is zero to ensure we have a valid fs, otherwise
+ * when probing multiple paritions, reads from subsequent parititions
+ * will incorrectly succeed.
+ */
+ if (!dsk_meta || inode == 0) {
inomap = 0;
+ dsk_meta = 0;
for (n = 0; sblock_try[n] != -1; n++) {
if (dskread(dmadat->sbbuf, sblock_try[n] / DEV_BSIZE,
SBLOCKSIZE / DEV_BSIZE))
diff --git a/sys/boot/efi/Makefile b/sys/boot/efi/Makefile
index 57d4e81b4860..94a975a8ec0b 100644
--- a/sys/boot/efi/Makefile
+++ b/sys/boot/efi/Makefile
@@ -2,7 +2,8 @@
.include <src.opts.mk>
-SUBDIR= libefi
+# In-tree GCC does not support __attribute__((ms_abi)).
+.if ${COMPILER_TYPE} != "gcc"
.if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "arm"
.if ${MK_FDT} != "no"
@@ -13,7 +14,10 @@ SUBDIR+= fdt
.if ${MACHINE_CPUARCH} == "aarch64" || \
${MACHINE_CPUARCH} == "amd64" || \
${MACHINE_CPUARCH} == "arm"
-SUBDIR+= loader boot1
+SUBDIR+= libefi loader boot1
.endif
+.endif # ${COMPILER_TYPE} != "gcc"
+
.include <bsd.subdir.mk>
+
diff --git a/sys/boot/efi/boot1/Makefile b/sys/boot/efi/boot1/Makefile
index 9a003ce17e85..6b1ea8d7d583 100644
--- a/sys/boot/efi/boot1/Makefile
+++ b/sys/boot/efi/boot1/Makefile
@@ -2,10 +2,7 @@
MAN=
-.include <bsd.own.mk>
-
-# In-tree GCC does not support __attribute__((ms_abi)).
-.if ${COMPILER_TYPE} != "gcc"
+.include <src.opts.mk>
MK_SSP= no
@@ -13,14 +10,35 @@ PROG= boot1.sym
INTERNALPROG=
WARNS?= 6
+.if ${MK_ZFS} != "no"
+# Disable warnings that are currently incompatible with the zfs boot code
+CWARNFLAGS.zfs_module.c += -Wno-array-bounds
+CWARNFLAGS.zfs_module.c += -Wno-cast-align
+CWARNFLAGS.zfs_module.c += -Wno-cast-qual
+CWARNFLAGS.zfs_module.c += -Wno-missing-prototypes
+CWARNFLAGS.zfs_module.c += -Wno-sign-compare
+CWARNFLAGS.zfs_module.c += -Wno-unused-parameter
+CWARNFLAGS.zfs_module.c += -Wno-unused-function
+.endif
+
# architecture-specific loader code
-SRCS= boot1.c self_reloc.c start.S
+SRCS= boot1.c self_reloc.c start.S ufs_module.c
+.if ${MK_ZFS} != "no"
+SRCS+= zfs_module.c
+.endif
CFLAGS+= -I.
CFLAGS+= -I${.CURDIR}/../include
CFLAGS+= -I${.CURDIR}/../include/${MACHINE}
CFLAGS+= -I${.CURDIR}/../../../contrib/dev/acpica/include
CFLAGS+= -I${.CURDIR}/../../..
+CFLAGS+= -DEFI_UFS_BOOT
+
+.if ${MK_ZFS} != "no"
+CFLAGS+= -I${.CURDIR}/../../zfs/
+CFLAGS+= -I${.CURDIR}/../../../cddl/boot/zfs/
+CFLAGS+= -DEFI_ZFS_BOOT
+.endif
# Always add MI sources and REGULAR efi loader bits
.PATH: ${.CURDIR}/../loader/arch/${MACHINE}
@@ -96,8 +114,6 @@ boot1.efifat: boot1.efi
CLEANFILES= boot1.efi boot1.efifat
-.endif # ${COMPILER_TYPE} != "gcc"
-
.include <bsd.prog.mk>
beforedepend ${OBJS}: machine
diff --git a/sys/boot/efi/boot1/boot1.c b/sys/boot/efi/boot1/boot1.c
index 2b000e066d8e..e4d039d48ff0 100644
--- a/sys/boot/efi/boot1/boot1.c
+++ b/sys/boot/efi/boot1/boot1.c
@@ -5,6 +5,8 @@
* All rights reserved.
* Copyright (c) 2014 Nathan Whitehorn
* All rights reserved.
+ * Copyright (c) 2015 Eric McCorkle
+ * All rights reserved.
*
* Redistribution and use in source and binary forms are freely
* permitted provided that the above copyright notice and this
@@ -21,7 +23,6 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
-#include <sys/dirent.h>
#include <machine/elf.h>
#include <machine/stdarg.h>
#include <stand.h>
@@ -29,19 +30,32 @@ __FBSDID("$FreeBSD$");
#include <efi.h>
#include <eficonsctl.h>
+#include "boot_module.h"
+
#define _PATH_LOADER "/boot/loader.efi"
-#define _PATH_KERNEL "/boot/kernel/kernel"
-#define BSIZEMAX 16384
+static const boot_module_t *boot_modules[] =
+{
+#ifdef EFI_ZFS_BOOT
+ &zfs_module,
+#endif
+#ifdef EFI_UFS_BOOT
+ &ufs_module
+#endif
+};
+
+#define NUM_BOOT_MODULES (sizeof(boot_modules) / sizeof(boot_module_t*))
+/* The initial number of handles used to query EFI for partitions. */
+#define NUM_HANDLES_INIT 24
-void panic(const char *fmt, ...) __dead2;
void putchar(int c);
EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab);
-static int domount(EFI_DEVICE_PATH *device, EFI_BLOCK_IO *blkio, int quiet);
-static void load(const char *fname);
+static void try_load(const boot_module_t* mod);
+static EFI_STATUS probe_handle(EFI_HANDLE h);
-static EFI_SYSTEM_TABLE *systab;
+EFI_SYSTEM_TABLE *systab;
+EFI_BOOT_SERVICES *bs;
static EFI_HANDLE *image;
static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL;
@@ -49,27 +63,92 @@ static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL;
static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL;
static EFI_GUID ConsoleControlGUID = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
-static EFI_BLOCK_IO *bootdev;
-static EFI_DEVICE_PATH *bootdevpath;
-static EFI_HANDLE *bootdevhandle;
+/*
+ * Provide Malloc / Free backed by EFIs AllocatePool / FreePool which ensures
+ * memory is correctly aligned avoiding EFI_INVALID_PARAMETER returns from
+ * EFI methods.
+ */
+void *
+Malloc(size_t len, const char *file __unused, int line __unused)
+{
+ void *out;
+
+ if (bs->AllocatePool(EfiLoaderData, len, &out) == EFI_SUCCESS)
+ return (out);
-EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab)
+ return (NULL);
+}
+
+void
+Free(void *buf, const char *file __unused, int line __unused)
{
- EFI_HANDLE handles[128];
- EFI_BLOCK_IO *blkio;
- UINTN i, nparts = sizeof(handles), cols, rows, max_dim, best_mode;
+ (void)bs->FreePool(buf);
+}
+
+/*
+ * This function only returns if it fails to load the kernel. If it
+ * succeeds, it simply boots the kernel.
+ */
+void
+try_load(const boot_module_t *mod)
+{
+ size_t bufsize;
+ void *buf;
+ dev_info_t *dev;
+ EFI_HANDLE loaderhandle;
+ EFI_LOADED_IMAGE *loaded_image;
+ EFI_STATUS status;
+
+ status = mod->load(_PATH_LOADER, &dev, &buf, &bufsize);
+ if (status == EFI_NOT_FOUND)
+ return;
+
+ if (status != EFI_SUCCESS) {
+ printf("%s failed to load %s (%lu)\n", mod->name, _PATH_LOADER,
+ EFI_ERROR_CODE(status));
+ return;
+ }
+
+ if ((status = bs->LoadImage(TRUE, image, dev->devpath, buf, bufsize,
+ &loaderhandle)) != EFI_SUCCESS) {
+ printf("Failed to load image provided by %s, size: %zu, (%lu)\n",
+ mod->name, bufsize, EFI_ERROR_CODE(status));
+ return;
+ }
+
+ if ((status = bs->HandleProtocol(loaderhandle, &LoadedImageGUID,
+ (VOID**)&loaded_image)) != EFI_SUCCESS) {
+ printf("Failed to query LoadedImage provided by %s (%lu)\n",
+ mod->name, EFI_ERROR_CODE(status));
+ return;
+ }
+
+ loaded_image->DeviceHandle = dev->devhandle;
+
+ if ((status = bs->StartImage(loaderhandle, NULL, NULL)) !=
+ EFI_SUCCESS) {
+ printf("Failed start image provided by %s (%lu)\n", mod->name,
+ EFI_ERROR_CODE(status));
+ return;
+ }
+}
+
+EFI_STATUS
+efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE *Xsystab)
+{
+ EFI_HANDLE *handles;
EFI_STATUS status;
- EFI_DEVICE_PATH *devpath;
- EFI_BOOT_SERVICES *BS;
EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
SIMPLE_TEXT_OUTPUT_INTERFACE *conout = NULL;
- const char *path = _PATH_LOADER;
+ UINTN i, max_dim, best_mode, cols, rows, hsize, nhandles;
+ /* Basic initialization*/
systab = Xsystab;
image = Ximage;
+ bs = Xsystab->BootServices;
- BS = systab->BootServices;
- status = BS->LocateProtocol(&ConsoleControlGUID, NULL,
+ /* Set up the console, so printf works. */
+ status = bs->LocateProtocol(&ConsoleControlGUID, NULL,
(VOID **)&ConsoleControl);
if (status == EFI_SUCCESS)
(void)ConsoleControl->SetMode(ConsoleControl,
@@ -94,200 +173,162 @@ EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab)
conout->EnableCursor(conout, TRUE);
conout->ClearScreen(conout);
- printf("\n"
- ">> FreeBSD EFI boot block\n");
- printf(" Loader path: %s\n", path);
-
- status = systab->BootServices->LocateHandle(ByProtocol,
- &BlockIoProtocolGUID, NULL, &nparts, handles);
- nparts /= sizeof(handles[0]);
-
- for (i = 0; i < nparts; i++) {
- status = systab->BootServices->HandleProtocol(handles[i],
- &DevicePathGUID, (void **)&devpath);
- if (EFI_ERROR(status))
+ printf("\n>> FreeBSD EFI boot block\n");
+ printf(" Loader path: %s\n\n", _PATH_LOADER);
+ printf(" Initializing modules:");
+ for (i = 0; i < NUM_BOOT_MODULES; i++) {
+ if (boot_modules[i] == NULL)
continue;
- while (!IsDevicePathEnd(NextDevicePathNode(devpath)))
- devpath = NextDevicePathNode(devpath);
+ printf(" %s", boot_modules[i]->name);
+ if (boot_modules[i]->init != NULL)
+ boot_modules[i]->init();
+ }
+ putchar('\n');
- status = systab->BootServices->HandleProtocol(handles[i],
- &BlockIoProtocolGUID, (void **)&blkio);
- if (EFI_ERROR(status))
- continue;
+ /* Get all the device handles */
+ hsize = (UINTN)NUM_HANDLES_INIT * sizeof(EFI_HANDLE);
+ if ((status = bs->AllocatePool(EfiLoaderData, hsize, (void **)&handles))
+ != EFI_SUCCESS)
+ panic("Failed to allocate %d handles (%lu)", NUM_HANDLES_INIT,
+ EFI_ERROR_CODE(status));
- if (!blkio->Media->LogicalPartition)
- continue;
+ status = bs->LocateHandle(ByProtocol, &BlockIoProtocolGUID, NULL,
+ &hsize, handles);
+ switch (status) {
+ case EFI_SUCCESS:
+ break;
+ case EFI_BUFFER_TOO_SMALL:
+ (void)bs->FreePool(handles);
+ if ((status = bs->AllocatePool(EfiLoaderData, hsize,
+ (void **)&handles) != EFI_SUCCESS)) {
+ panic("Failed to allocate %zu handles (%lu)", hsize /
+ sizeof(*handles), EFI_ERROR_CODE(status));
+ }
+ status = bs->LocateHandle(ByProtocol, &BlockIoProtocolGUID,
+ NULL, &hsize, handles);
+ if (status != EFI_SUCCESS)
+ panic("Failed to get device handles (%lu)\n",
+ EFI_ERROR_CODE(status));
+ break;
+ default:
+ panic("Failed to get device handles (%lu)",
+ EFI_ERROR_CODE(status));
+ }
- if (domount(devpath, blkio, 1) >= 0)
+ /* Scan all partitions, probing with all modules. */
+ nhandles = hsize / sizeof(*handles);
+ printf(" Probing %zu block devices...", nhandles);
+ for (i = 0; i < nhandles; i++) {
+ status = probe_handle(handles[i]);
+ switch (status) {
+ case EFI_UNSUPPORTED:
+ printf(".");
break;
+ case EFI_SUCCESS:
+ printf("+");
+ break;
+ default:
+ printf("x");
+ break;
+ }
}
+ printf(" done\n");
- if (i == nparts)
- panic("No bootable partition found");
-
- bootdevhandle = handles[i];
- load(path);
+ /* Status summary. */
+ for (i = 0; i < NUM_BOOT_MODULES; i++) {
+ if (boot_modules[i] != NULL) {
+ printf(" ");
+ boot_modules[i]->status();
+ }
+ }
- panic("Load failed");
+ /* Select a partition to boot by trying each module in order. */
+ for (i = 0; i < NUM_BOOT_MODULES; i++)
+ if (boot_modules[i] != NULL)
+ try_load(boot_modules[i]);
- return EFI_SUCCESS;
+ /* If we get here, we're out of luck... */
+ panic("No bootable partitions found!");
}
-static int
-dskread(void *buf, u_int64_t lba, int nblk)
+static EFI_STATUS
+probe_handle(EFI_HANDLE h)
{
+ dev_info_t *devinfo;
+ EFI_BLOCK_IO *blkio;
+ EFI_DEVICE_PATH *devpath;
EFI_STATUS status;
- int size;
+ UINTN i;
- lba = lba / (bootdev->Media->BlockSize / DEV_BSIZE);
- size = nblk * DEV_BSIZE;
- status = bootdev->ReadBlocks(bootdev, bootdev->Media->MediaId, lba,
- size, buf);
+ /* Figure out if we're dealing with an actual partition. */
+ status = bs->HandleProtocol(h, &DevicePathGUID, (void **)&devpath);
+ if (status == EFI_UNSUPPORTED)
+ return (status);
- if (EFI_ERROR(status))
- return (-1);
+ if (status != EFI_SUCCESS) {
+ DPRINTF("\nFailed to query DevicePath (%lu)\n",
+ EFI_ERROR_CODE(status));
+ return (status);
+ }
- return (0);
-}
+ while (!IsDevicePathEnd(NextDevicePathNode(devpath)))
+ devpath = NextDevicePathNode(devpath);
-#include "ufsread.c"
+ status = bs->HandleProtocol(h, &BlockIoProtocolGUID, (void **)&blkio);
+ if (status == EFI_UNSUPPORTED)
+ return (status);
-static ssize_t
-fsstat(ufs_ino_t inode)
-{
-#ifndef UFS2_ONLY
- static struct ufs1_dinode dp1;
-#endif
-#ifndef UFS1_ONLY
- static struct ufs2_dinode dp2;
-#endif
- static struct fs fs;
- static ufs_ino_t inomap;
- char *blkbuf;
- void *indbuf;
- size_t n, size;
- static ufs2_daddr_t blkmap, indmap;
-
- blkbuf = dmadat->blkbuf;
- indbuf = dmadat->indbuf;
- if (!dsk_meta) {
- inomap = 0;
- for (n = 0; sblock_try[n] != -1; n++) {
- if (dskread(dmadat->sbbuf, sblock_try[n] / DEV_BSIZE,
- SBLOCKSIZE / DEV_BSIZE))
- return -1;
- memcpy(&fs, dmadat->sbbuf, sizeof(struct fs));
- if ((
-#if defined(UFS1_ONLY)
- fs.fs_magic == FS_UFS1_MAGIC
-#elif defined(UFS2_ONLY)
- (fs.fs_magic == FS_UFS2_MAGIC &&
- fs.fs_sblockloc == sblock_try[n])
-#else
- fs.fs_magic == FS_UFS1_MAGIC ||
- (fs.fs_magic == FS_UFS2_MAGIC &&
- fs.fs_sblockloc == sblock_try[n])
-#endif
- ) &&
- fs.fs_bsize <= MAXBSIZE &&
- fs.fs_bsize >= (int32_t)sizeof(struct fs))
- break;
- }
- if (sblock_try[n] == -1) {
- return -1;
- }
- dsk_meta++;
- } else
- memcpy(&fs, dmadat->sbbuf, sizeof(struct fs));
- if (!inode)
- return 0;
- if (inomap != inode) {
- n = IPERVBLK(&fs);
- if (dskread(blkbuf, INO_TO_VBA(&fs, n, inode), DBPERVBLK))
- return -1;
- n = INO_TO_VBO(n, inode);
-#if defined(UFS1_ONLY)
- memcpy(&dp1, (struct ufs1_dinode *)blkbuf + n,
- sizeof(struct ufs1_dinode));
-#elif defined(UFS2_ONLY)
- memcpy(&dp2, (struct ufs2_dinode *)blkbuf + n,
- sizeof(struct ufs2_dinode));
-#else
- if (fs.fs_magic == FS_UFS1_MAGIC)
- memcpy(&dp1, (struct ufs1_dinode *)(void *)blkbuf + n,
- sizeof(struct ufs1_dinode));
- else
- memcpy(&dp2, (struct ufs2_dinode *)(void *)blkbuf + n,
- sizeof(struct ufs2_dinode));
-#endif
- inomap = inode;
- fs_off = 0;
- blkmap = indmap = 0;
+ if (status != EFI_SUCCESS) {
+ DPRINTF("\nFailed to query BlockIoProtocol (%lu)\n",
+ EFI_ERROR_CODE(status));
+ return (status);
}
- size = DIP(di_size);
- n = size - fs_off;
- return (n);
-}
-static struct dmadat __dmadat;
+ if (!blkio->Media->LogicalPartition)
+ return (EFI_UNSUPPORTED);
-static int
-domount(EFI_DEVICE_PATH *device, EFI_BLOCK_IO *blkio, int quiet)
-{
+ /* Run through each module, see if it can load this partition */
+ for (i = 0; i < NUM_BOOT_MODULES; i++) {
+ if (boot_modules[i] == NULL)
+ continue;
- dmadat = &__dmadat;
- bootdev = blkio;
- bootdevpath = device;
- if (fsread(0, NULL, 0)) {
- if (!quiet)
- printf("domount: can't read superblock\n");
- return (-1);
+ if ((status = bs->AllocatePool(EfiLoaderData,
+ sizeof(*devinfo), (void **)&devinfo)) !=
+ EFI_SUCCESS) {
+ DPRINTF("\nFailed to allocate devinfo (%lu)\n",
+ EFI_ERROR_CODE(status));
+ continue;
+ }
+ devinfo->dev = blkio;
+ devinfo->devpath = devpath;
+ devinfo->devhandle = h;
+ devinfo->devdata = NULL;
+ devinfo->next = NULL;
+
+ status = boot_modules[i]->probe(devinfo);
+ if (status == EFI_SUCCESS)
+ return (EFI_SUCCESS);
+ (void)bs->FreePool(devinfo);
}
- if (!quiet)
- printf("Succesfully mounted UFS filesystem\n");
- return (0);
+
+ return (EFI_UNSUPPORTED);
}
-static void
-load(const char *fname)
+void
+add_device(dev_info_t **devinfop, dev_info_t *devinfo)
{
- ufs_ino_t ino;
- EFI_STATUS status;
- EFI_HANDLE loaderhandle;
- EFI_LOADED_IMAGE *loaded_image;
- void *buffer;
- size_t bufsize;
+ dev_info_t *dev;
- if ((ino = lookup(fname)) == 0) {
- printf("File %s not found\n", fname);
+ if (*devinfop == NULL) {
+ *devinfop = devinfo;
return;
}
- bufsize = fsstat(ino);
- status = systab->BootServices->AllocatePool(EfiLoaderData,
- bufsize, &buffer);
- fsread(ino, buffer, bufsize);
+ for (dev = *devinfop; dev->next != NULL; dev = dev->next)
+ ;
- /* XXX: For secure boot, we need our own loader here */
- status = systab->BootServices->LoadImage(TRUE, image, bootdevpath,
- buffer, bufsize, &loaderhandle);
- if (EFI_ERROR(status))
- printf("LoadImage failed with error %lu\n",
- EFI_ERROR_CODE(status));
-
- status = systab->BootServices->HandleProtocol(loaderhandle,
- &LoadedImageGUID, (VOID**)&loaded_image);
- if (EFI_ERROR(status))
- printf("HandleProtocol failed with error %lu\n",
- EFI_ERROR_CODE(status));
-
- loaded_image->DeviceHandle = bootdevhandle;
-
- status = systab->BootServices->StartImage(loaderhandle, NULL, NULL);
- if (EFI_ERROR(status))
- printf("StartImage failed with error %lu\n",
- EFI_ERROR_CODE(status));
+ dev->next = devinfo;
}
void
diff --git a/sys/boot/efi/boot1/boot_module.h b/sys/boot/efi/boot1/boot_module.h
new file mode 100644
index 000000000000..1d0729538f77
--- /dev/null
+++ b/sys/boot/efi/boot1/boot_module.h
@@ -0,0 +1,113 @@
+/*-
+ * Copyright (c) 2015 Eric McCorkle
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _BOOT_MODULE_H_
+#define _BOOT_MODULE_H_
+
+#include <stdbool.h>
+
+#include <efi.h>
+#include <efilib.h>
+#include <eficonsctl.h>
+
+#ifdef EFI_DEBUG
+#define DPRINTF(fmt, args...) \
+ do { \
+ printf(fmt, ##args) \
+ } while (0)
+#else
+#define DPRINTF(fmt, args...) {}
+#endif
+
+/* EFI device info */
+typedef struct dev_info
+{
+ EFI_BLOCK_IO *dev;
+ EFI_DEVICE_PATH *devpath;
+ EFI_HANDLE *devhandle;
+ void *devdata;
+ struct dev_info *next;
+} dev_info_t;
+
+/*
+ * A boot loader module.
+ *
+ * This is a standard interface for filesystem modules in the EFI system.
+ */
+typedef struct boot_module_t
+{
+ const char *name;
+
+ /* init is the optional initialiser for the module. */
+ void (*init)();
+
+ /*
+ * probe checks to see if the module can handle dev.
+ *
+ * Return codes:
+ * EFI_SUCCESS = The module can handle the device.
+ * EFI_NOT_FOUND = The module can not handle the device.
+ * Other = The module encountered an error.
+ */
+ EFI_STATUS (*probe)(dev_info_t* dev);
+
+ /*
+ * load should select the best out of a set of devices that probe
+ * indicated were loadable and load it.
+ *
+ * Return codes:
+ * EFI_SUCCESS = The module can handle the device.
+ * EFI_NOT_FOUND = The module can not handle the device.
+ * Other = The module encountered an error.
+ */
+ EFI_STATUS (*load)(const char *loader_path, dev_info_t **devinfo,
+ void **buf, size_t *bufsize);
+
+ /* status outputs information about the probed devices. */
+ void (*status)();
+
+} boot_module_t;
+
+/* Standard boot modules. */
+#ifdef EFI_UFS_BOOT
+extern const boot_module_t ufs_module;
+#endif
+#ifdef EFI_ZFS_BOOT
+extern const boot_module_t zfs_module;
+#endif
+
+/* Functions available to modules. */
+extern void add_device(dev_info_t **devinfop, dev_info_t *devinfo);
+extern void panic(const char *fmt, ...) __dead2;
+extern int printf(const char *fmt, ...);
+extern int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap);
+
+extern EFI_SYSTEM_TABLE *systab;
+extern EFI_BOOT_SERVICES *bs;
+
+#endif
diff --git a/sys/boot/efi/boot1/ufs_module.c b/sys/boot/efi/boot1/ufs_module.c
new file mode 100644
index 000000000000..7d36f84df216
--- /dev/null
+++ b/sys/boot/efi/boot1/ufs_module.c
@@ -0,0 +1,253 @@
+/*-
+ * Copyright (c) 1998 Robert Nordier
+ * All rights reserved.
+ * Copyright (c) 2001 Robert Drehmel
+ * All rights reserved.
+ * Copyright (c) 2014 Nathan Whitehorn
+ * All rights reserved.
+ * Copyright (c) 2015 Eric McCorkle
+ * All rights reverved.
+ *
+ * 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 <stdarg.h>
+#include <stdbool.h>
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <efi.h>
+
+#include "boot_module.h"
+
+static dev_info_t *devinfo;
+static dev_info_t *devices;
+
+static int
+dskread(void *buf, u_int64_t lba, int nblk)
+{
+ int size;
+ EFI_STATUS status;
+
+ lba = lba / (devinfo->dev->Media->BlockSize / DEV_BSIZE);
+ size = nblk * DEV_BSIZE;
+
+ status = devinfo->dev->ReadBlocks(devinfo->dev,
+ devinfo->dev->Media->MediaId, lba, size, buf);
+
+ if (status != EFI_SUCCESS) {
+ DPRINTF("dskread: failed dev: %p, id: %u, lba: %lu, size: %d, "
+ "status: %lu\n", devinfo->dev,
+ devinfo->dev->Media->MediaId, lba, size,
+ EFI_ERROR_CODE(status));
+ return (-1);
+ }
+
+ return (0);
+}
+
+#include "ufsread.c"
+
+static ssize_t
+fsstat(ufs_ino_t inode)
+{
+#ifndef UFS2_ONLY
+ static struct ufs1_dinode dp1;
+#endif
+#ifndef UFS1_ONLY
+ static struct ufs2_dinode dp2;
+#endif
+ static struct fs fs;
+ static ufs_ino_t inomap;
+ char *blkbuf;
+ void *indbuf;
+ size_t n, size;
+ static ufs2_daddr_t blkmap, indmap;
+
+ blkbuf = dmadat->blkbuf;
+ indbuf = dmadat->indbuf;
+ if (!dsk_meta) {
+ inomap = 0;
+ for (n = 0; sblock_try[n] != -1; n++) {
+ if (dskread(dmadat->sbbuf, sblock_try[n] / DEV_BSIZE,
+ SBLOCKSIZE / DEV_BSIZE))
+ return (-1);
+ memcpy(&fs, dmadat->sbbuf, sizeof(struct fs));
+ if ((
+#if defined(UFS1_ONLY)
+ fs.fs_magic == FS_UFS1_MAGIC
+#elif defined(UFS2_ONLY)
+ (fs.fs_magic == FS_UFS2_MAGIC &&
+ fs.fs_sblockloc == sblock_try[n])
+#else
+ fs.fs_magic == FS_UFS1_MAGIC ||
+ (fs.fs_magic == FS_UFS2_MAGIC &&
+ fs.fs_sblockloc == sblock_try[n])
+#endif
+ ) &&
+ fs.fs_bsize <= MAXBSIZE &&
+ fs.fs_bsize >= (int32_t)sizeof(struct fs))
+ break;
+ }
+ if (sblock_try[n] == -1) {
+ return (-1);
+ }
+ dsk_meta++;
+ } else
+ memcpy(&fs, dmadat->sbbuf, sizeof(struct fs));
+ if (!inode)
+ return (0);
+ if (inomap != inode) {
+ n = IPERVBLK(&fs);
+ if (dskread(blkbuf, INO_TO_VBA(&fs, n, inode), DBPERVBLK))
+ return (-1);
+ n = INO_TO_VBO(n, inode);
+#if defined(UFS1_ONLY)
+ memcpy(&dp1, (struct ufs1_dinode *)blkbuf + n,
+ sizeof(struct ufs1_dinode));
+#elif defined(UFS2_ONLY)
+ memcpy(&dp2, (struct ufs2_dinode *)blkbuf + n,
+ sizeof(struct ufs2_dinode));
+#else
+ if (fs.fs_magic == FS_UFS1_MAGIC)
+ memcpy(&dp1, (struct ufs1_dinode *)(void *)blkbuf + n,
+ sizeof(struct ufs1_dinode));
+ else
+ memcpy(&dp2, (struct ufs2_dinode *)(void *)blkbuf + n,
+ sizeof(struct ufs2_dinode));
+#endif
+ inomap = inode;
+ fs_off = 0;
+ blkmap = indmap = 0;
+ }
+ size = DIP(di_size);
+ n = size - fs_off;
+
+ return (n);
+}
+
+static struct dmadat __dmadat;
+
+static EFI_STATUS
+probe(dev_info_t* dev)
+{
+
+ devinfo = dev;
+ dmadat = &__dmadat;
+ if (fsread(0, NULL, 0) < 0)
+ return (EFI_UNSUPPORTED);
+
+ add_device(&devices, dev);
+
+ return (EFI_SUCCESS);
+}
+
+static EFI_STATUS
+try_load(dev_info_t *dev, const char *loader_path, void **bufp, size_t *bufsize)
+{
+ ufs_ino_t ino;
+ EFI_STATUS status;
+ size_t size;
+ ssize_t read;
+ void *buf;
+
+ devinfo = dev;
+ if ((ino = lookup(loader_path)) == 0)
+ return (EFI_NOT_FOUND);
+
+ size = fsstat(ino);
+ if (size <= 0) {
+ printf("Failed to fsstat %s ino: %d\n", loader_path, ino);
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ if ((status = bs->AllocatePool(EfiLoaderData, size, &buf)) !=
+ EFI_SUCCESS) {
+ printf("Failed to allocate read buffer (%lu)\n",
+ EFI_ERROR_CODE(status));
+ return (status);
+ }
+
+ read = fsread(ino, buf, size);
+ if ((size_t)read != size) {
+ printf("Failed to read %s (%zd != %zu)\n", loader_path, read,
+ size);
+ (void)bs->FreePool(buf);
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ *bufp = buf;
+ *bufsize = size;
+
+ return (EFI_SUCCESS);
+}
+
+static EFI_STATUS
+load(const char *loader_path, dev_info_t **devinfop, void **buf,
+ size_t *bufsize)
+{
+ dev_info_t *dev;
+ EFI_STATUS status;
+
+ for (dev = devices; dev != NULL; dev = dev->next) {
+ status = try_load(dev, loader_path, buf, bufsize);
+ if (status == EFI_SUCCESS) {
+ *devinfop = dev;
+ return (EFI_SUCCESS);
+ } else if (status != EFI_NOT_FOUND) {
+ return (status);
+ }
+ }
+
+ return (EFI_NOT_FOUND);
+}
+
+static void
+status()
+{
+ int i;
+ dev_info_t *dev;
+
+ for (dev = devices, i = 0; dev != NULL; dev = dev->next, i++)
+ ;
+
+ printf("%s found ", ufs_module.name);
+ switch (i) {
+ case 0:
+ printf("no partitions\n");
+ break;
+ case 1:
+ printf("%d partition\n", i);
+ break;
+ default:
+ printf("%d partitions\n", i);
+ }
+}
+
+const boot_module_t ufs_module =
+{
+ .name = "UFS",
+ .probe = probe,
+ .load = load,
+ .status = status
+};
diff --git a/sys/boot/efi/boot1/zfs_module.c b/sys/boot/efi/boot1/zfs_module.c
new file mode 100644
index 000000000000..345d0e114f59
--- /dev/null
+++ b/sys/boot/efi/boot1/zfs_module.c
@@ -0,0 +1,199 @@
+/*-
+ * Copyright (c) 2015 Eric McCorkle
+ * 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.
+ *
+ * $FreeBSD$
+ */
+#include <stddef.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <efi.h>
+
+#include "boot_module.h"
+
+#include "libzfs.h"
+#include "zfsimpl.c"
+
+static dev_info_t *devices;
+
+static int
+vdev_read(vdev_t *vdev, void *priv, off_t off, void *buf, size_t bytes)
+{
+ dev_info_t *devinfo;
+ off_t lba;
+ EFI_STATUS status;
+
+ devinfo = (dev_info_t *)priv;
+ lba = off / devinfo->dev->Media->BlockSize;
+
+ status = devinfo->dev->ReadBlocks(devinfo->dev,
+ devinfo->dev->Media->MediaId, lba, bytes, buf);
+ if (status != EFI_SUCCESS) {
+ DPRINTF("vdev_read: failed dev: %p, id: %u, lba: %lu, size: %d,"
+ " status: %lu\n", devinfo->dev,
+ devinfo->dev->Media->MediaId, lba, size,
+ EFI_ERROR_CODE(status));
+ return (-1);
+ }
+
+ return (0);
+}
+
+static EFI_STATUS
+probe(dev_info_t *dev)
+{
+ spa_t *spa;
+ dev_info_t *tdev;
+ EFI_STATUS status;
+
+ /* ZFS consumes the dev on success so we need a copy. */
+ if ((status = bs->AllocatePool(EfiLoaderData, sizeof(*dev),
+ (void**)&tdev)) != EFI_SUCCESS) {
+ DPRINTF("Failed to allocate tdev (%lu)\n",
+ EFI_ERROR_CODE(status));
+ return (status);
+ }
+ memcpy(tdev, dev, sizeof(*dev));
+
+ if (vdev_probe(vdev_read, tdev, &spa) != 0) {
+ (void)bs->FreePool(tdev);
+ return (EFI_UNSUPPORTED);
+ }
+
+ dev->devdata = spa;
+ add_device(&devices, dev);
+
+ return (EFI_SUCCESS);
+}
+
+static EFI_STATUS
+try_load(dev_info_t *devinfo, const char *loader_path, void **bufp, size_t *bufsize)
+{
+ spa_t *spa;
+ struct zfsmount zfsmount;
+ dnode_phys_t dn;
+ struct stat st;
+ int err;
+ void *buf;
+ EFI_STATUS status;
+
+ spa = devinfo->devdata;
+ if (zfs_spa_init(spa) != 0) {
+ /* Init failed, don't report this loudly. */
+ return (EFI_NOT_FOUND);
+ }
+
+ if (zfs_mount(spa, 0, &zfsmount) != 0) {
+ /* Mount failed, don't report this loudly. */
+ return (EFI_NOT_FOUND);
+ }
+
+ if ((err = zfs_lookup(&zfsmount, loader_path, &dn)) != 0) {
+ printf("Failed to lookup %s on pool %s (%d)\n", loader_path,
+ spa->spa_name, err);
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ if ((err = zfs_dnode_stat(spa, &dn, &st)) != 0) {
+ printf("Failed to lookup %s on pool %s (%d)\n", loader_path,
+ spa->spa_name, err);
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ if ((status = bs->AllocatePool(EfiLoaderData, (UINTN)st.st_size, &buf))
+ != EFI_SUCCESS) {
+ printf("Failed to allocate load buffer for pool %s (%lu)\n",
+ spa->spa_name, EFI_ERROR_CODE(status));
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ if ((err = dnode_read(spa, &dn, 0, buf, st.st_size)) != 0) {
+ printf("Failed to read node from %s (%d)\n", spa->spa_name,
+ err);
+ (void)bs->FreePool(buf);
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ *bufsize = st.st_size;
+ *bufp = buf;
+
+ return (EFI_SUCCESS);
+}
+
+static EFI_STATUS
+load(const char *loader_path, dev_info_t **devinfop, void **bufp,
+ size_t *bufsize)
+{
+ dev_info_t *devinfo;
+ EFI_STATUS status;
+
+ for (devinfo = devices; devinfo != NULL; devinfo = devinfo->next) {
+ status = try_load(devinfo, loader_path, bufp, bufsize);
+ if (status == EFI_SUCCESS) {
+ *devinfop = devinfo;
+ return (EFI_SUCCESS);
+ } else if (status != EFI_NOT_FOUND) {
+ return (status);
+ }
+ }
+
+ return (EFI_NOT_FOUND);
+}
+
+static void
+status()
+{
+ spa_t *spa;
+
+ spa = STAILQ_FIRST(&zfs_pools);
+ if (spa == NULL) {
+ printf("%s found no pools\n", zfs_module.name);
+ return;
+ }
+
+ printf("%s found the following pools:", zfs_module.name);
+ STAILQ_FOREACH(spa, &zfs_pools, spa_link)
+ printf(" %s", spa->spa_name);
+
+ printf("\n");
+}
+
+static void
+init()
+{
+
+ zfs_init();
+}
+
+const boot_module_t zfs_module =
+{
+ .name = "ZFS",
+ .init = init,
+ .probe = probe,
+ .load = load,
+ .status = status
+};
diff --git a/sys/boot/efi/include/efilib.h b/sys/boot/efi/include/efilib.h
index b67ffc5305ca..ba5b663da5f0 100644
--- a/sys/boot/efi/include/efilib.h
+++ b/sys/boot/efi/include/efilib.h
@@ -39,11 +39,11 @@ extern struct devsw efinet_dev;
extern struct netif_driver efinetif;
void *efi_get_table(EFI_GUID *tbl);
-void efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table);
int efi_register_handles(struct devsw *, EFI_HANDLE *, EFI_HANDLE *, int);
EFI_HANDLE efi_find_handle(struct devsw *, int);
-int efi_handle_lookup(EFI_HANDLE, struct devsw **, int *);
+int efi_handle_lookup(EFI_HANDLE, struct devsw **, int *, uint64_t *);
+int efi_handle_update_dev(EFI_HANDLE, struct devsw *, int, uint64_t);
int efi_status_to_errno(EFI_STATUS);
time_t efi_time(EFI_TIME *);
diff --git a/sys/boot/efi/libefi/handles.c b/sys/boot/efi/libefi/handles.c
index b15c0a5c1322..1e4ef6ffbd50 100644
--- a/sys/boot/efi/libefi/handles.c
+++ b/sys/boot/efi/libefi/handles.c
@@ -35,6 +35,7 @@ struct entry {
EFI_HANDLE alias;
struct devsw *dev;
int unit;
+ uint64_t extra;
};
struct entry *entry;
@@ -79,7 +80,7 @@ efi_find_handle(struct devsw *dev, int unit)
}
int
-efi_handle_lookup(EFI_HANDLE h, struct devsw **dev, int *unit)
+efi_handle_lookup(EFI_HANDLE h, struct devsw **dev, int *unit, uint64_t *extra)
{
int idx;
@@ -90,7 +91,28 @@ efi_handle_lookup(EFI_HANDLE h, struct devsw **dev, int *unit)
*dev = entry[idx].dev;
if (unit != NULL)
*unit = entry[idx].unit;
+ if (extra != NULL)
+ *extra = entry[idx].extra;
return (0);
}
return (ENOENT);
}
+
+int
+efi_handle_update_dev(EFI_HANDLE h, struct devsw *dev, int unit,
+ uint64_t guid)
+{
+ int idx;
+
+ for (idx = 0; idx < nentries; idx++) {
+ if (entry[idx].handle != h)
+ continue;
+ entry[idx].dev = dev;
+ entry[idx].unit = unit;
+ entry[idx].alias = NULL;
+ entry[idx].extra = guid;
+ return (0);
+ }
+
+ return (ENOENT);
+}
diff --git a/sys/boot/efi/loader/Makefile b/sys/boot/efi/loader/Makefile
index 56f3cabf8367..d36e54bc077d 100644
--- a/sys/boot/efi/loader/Makefile
+++ b/sys/boot/efi/loader/Makefile
@@ -4,9 +4,6 @@ MAN=
.include <src.opts.mk>
-# In-tree GCC does not support __attribute__((ms_abi)).
-.if ${COMPILER_TYPE} != "gcc"
-
MK_SSP= no
PROG= loader.sym
@@ -24,6 +21,16 @@ SRCS= autoload.c \
smbios.c \
vers.c
+.if ${MK_ZFS} != "no"
+SRCS+= zfs.c
+.PATH: ${.CURDIR}/../../zfs
+
+# Disable warnings that are currently incompatible with the zfs boot code
+CWARNFLAGS.zfs.c+= -Wno-sign-compare
+CWARNFLAGS.zfs.c+= -Wno-array-bounds
+CWARNFLAGS.zfs.c+= -Wno-missing-prototypes
+.endif
+
.PATH: ${.CURDIR}/arch/${MACHINE}
# For smbios.c
.PATH: ${.CURDIR}/../../i386/libi386
@@ -36,6 +43,11 @@ CFLAGS+= -I${.CURDIR}/../include/${MACHINE}
CFLAGS+= -I${.CURDIR}/../../../contrib/dev/acpica/include
CFLAGS+= -I${.CURDIR}/../../..
CFLAGS+= -I${.CURDIR}/../../i386/libi386
+.if ${MK_ZFS} != "no"
+CFLAGS+= -I${.CURDIR}/../../zfs
+CFLAGS+= -I${.CURDIR}/../../../cddl/boot/zfs
+CFLAGS+= -DEFI_ZFS_BOOT
+.endif
CFLAGS+= -DNO_PCI -DEFI
# make buildenv doesn't set DESTDIR, this means LIBSTAND
@@ -113,8 +125,6 @@ DPADD= ${LIBFICL} ${LIBEFI} ${LIBFDT} ${LIBEFI_FDT} ${LIBSTAND} \
${LDSCRIPT}
LDADD= ${LIBFICL} ${LIBEFI} ${LIBFDT} ${LIBEFI_FDT} ${LIBSTAND}
-.endif # ${COMPILER_TYPE} != "gcc"
-
.include <bsd.prog.mk>
beforedepend ${OBJS}: machine
diff --git a/sys/boot/efi/loader/conf.c b/sys/boot/efi/loader/conf.c
index 8bb9d5f0cda7..ecbf8b02c8e3 100644
--- a/sys/boot/efi/loader/conf.c
+++ b/sys/boot/efi/loader/conf.c
@@ -31,14 +31,23 @@ __FBSDID("$FreeBSD$");
#include <bootstrap.h>
#include <efi.h>
#include <efilib.h>
+#ifdef EFI_ZFS_BOOT
+#include <libzfs.h>
+#endif
struct devsw *devsw[] = {
&efipart_dev,
&efinet_dev,
+#ifdef EFI_ZFS_BOOT
+ &zfs_dev,
+#endif
NULL
};
struct fs_ops *file_system[] = {
+#ifdef EFI_ZFS_BOOT
+ &zfs_fsops,
+#endif
&dosfs_fsops,
&ufs_fsops,
&cd9660_fsops,
diff --git a/sys/boot/efi/loader/devicename.c b/sys/boot/efi/loader/devicename.c
index 45f9871bd45d..8fc80ebbc57e 100644
--- a/sys/boot/efi/loader/devicename.c
+++ b/sys/boot/efi/loader/devicename.c
@@ -31,7 +31,11 @@ __FBSDID("$FreeBSD$");
#include <stand.h>
#include <string.h>
#include <sys/disklabel.h>
+#include <sys/param.h>
#include <bootstrap.h>
+#ifdef EFI_ZFS_BOOT
+#include <libzfs.h>
+#endif
#include <efi.h>
#include <efilib.h>
@@ -86,7 +90,7 @@ efi_parsedev(struct devdesc **dev, const char *devspec, const char **path)
struct devsw *dv;
char *cp;
const char *np;
- int i, err;
+ int i;
/* minimum length check */
if (strlen(devspec) < 2)
@@ -101,24 +105,43 @@ efi_parsedev(struct devdesc **dev, const char *devspec, const char **path)
if (devsw[i] == NULL)
return (ENOENT);
- idev = malloc(sizeof(struct devdesc));
- if (idev == NULL)
- return (ENOMEM);
+ np = devspec + strlen(dv->dv_name);
- idev->d_dev = dv;
- idev->d_type = dv->dv_type;
- idev->d_unit = -1;
+#ifdef EFI_ZFS_BOOT
+ if (dv->dv_type == DEVT_ZFS) {
+ int err;
- err = 0;
- np = devspec + strlen(dv->dv_name);
- if (*np != '\0' && *np != ':') {
- idev->d_unit = strtol(np, &cp, 0);
- if (cp == np) {
- idev->d_unit = -1;
+ idev = malloc(sizeof(struct zfs_devdesc));
+ if (idev == NULL)
+ return (ENOMEM);
+
+ err = zfs_parsedev((struct zfs_devdesc*)idev, np, path);
+ if (err != 0) {
free(idev);
- return (EUNIT);
+ return (err);
+ }
+ *dev = idev;
+ cp = strchr(np + 1, ':');
+ } else
+#endif
+ {
+ idev = malloc(sizeof(struct devdesc));
+ if (idev == NULL)
+ return (ENOMEM);
+
+ idev->d_dev = dv;
+ idev->d_type = dv->dv_type;
+ idev->d_unit = -1;
+ if (*np != '\0' && *np != ':') {
+ idev->d_unit = strtol(np, &cp, 0);
+ if (cp == np) {
+ idev->d_unit = -1;
+ free(idev);
+ return (EUNIT);
+ }
}
}
+
if (*cp != '\0' && *cp != ':') {
free(idev);
return (EINVAL);
@@ -137,9 +160,13 @@ char *
efi_fmtdev(void *vdev)
{
struct devdesc *dev = (struct devdesc *)vdev;
- static char buf[32]; /* XXX device length constant? */
+ static char buf[SPECNAMELEN + 1];
switch(dev->d_type) {
+#ifdef EFI_ZFS_BOOT
+ case DEVT_ZFS:
+ return (zfs_fmtdev(dev));
+#endif
case DEVT_NONE:
strcpy(buf, "(no device)");
break;
diff --git a/sys/boot/efi/loader/main.c b/sys/boot/efi/loader/main.c
index ddd96b41e572..0b9dcf6da09c 100644
--- a/sys/boot/efi/loader/main.c
+++ b/sys/boot/efi/loader/main.c
@@ -28,6 +28,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <sys/param.h>
#include <stand.h>
#include <string.h>
#include <setjmp.h>
@@ -38,6 +39,10 @@ __FBSDID("$FreeBSD$");
#include <bootstrap.h>
#include <smbios.h>
+#ifdef EFI_ZFS_BOOT
+#include <libzfs.h>
+#endif
+
#include "loader_efi.h"
extern char bootprog_name[];
@@ -45,7 +50,6 @@ extern char bootprog_rev[];
extern char bootprog_date[];
extern char bootprog_maker[];
-struct devdesc currdev; /* our current device */
struct arch_switch archsw; /* MI/MD interface boundary */
EFI_GUID acpi = ACPI_TABLE_GUID;
@@ -61,15 +65,45 @@ EFI_GUID memtype = MEMORY_TYPE_INFORMATION_TABLE_GUID;
EFI_GUID debugimg = DEBUG_IMAGE_INFO_TABLE_GUID;
EFI_GUID fdtdtb = FDT_TABLE_GUID;
+#ifdef EFI_ZFS_BOOT
+static void efi_zfs_probe(void);
+#endif
+
+/*
+ * Need this because EFI uses UTF-16 unicode string constants, but we
+ * use UTF-8. We can't use printf due to the possiblity of \0 and we
+ * don't support support wide characters either.
+ */
+static void
+print_str16(const CHAR16 *str)
+{
+ int i;
+
+ for (i = 0; str[i]; i++)
+ printf("%c", (char)str[i]);
+}
+
EFI_STATUS
main(int argc, CHAR16 *argv[])
{
char var[128];
EFI_LOADED_IMAGE *img;
EFI_GUID *guid;
- int i, j, vargood;
+ int i, j, vargood, unit;
+ struct devsw *dev;
+ uint64_t pool_guid;
UINTN k;
+ archsw.arch_autoload = efi_autoload;
+ archsw.arch_getdev = efi_getdev;
+ archsw.arch_copyin = efi_copyin;
+ archsw.arch_copyout = efi_copyout;
+ archsw.arch_readin = efi_readin;
+#ifdef EFI_ZFS_BOOT
+ /* Note this needs to be set before ZFS init. */
+ archsw.arch_zfs_probe = efi_zfs_probe;
+#endif
+
/*
* XXX Chicken-and-egg problem; we want to have console output
* early, but some console attributes may depend on reading from
@@ -116,6 +150,13 @@ main(int argc, CHAR16 *argv[])
/* Get our loaded image protocol interface structure. */
BS->HandleProtocol(IH, &imgid, (VOID**)&img);
+ printf("Command line arguments:");
+ for (i = 0; i < argc; i++) {
+ printf(" ");
+ print_str16(argv[i]);
+ }
+ printf("\n");
+
printf("Image base: 0x%lx\n", (u_long)img->ImageBase);
printf("EFI version: %d.%02d\n", ST->Hdr.Revision >> 16,
ST->Hdr.Revision & 0xffff);
@@ -129,9 +170,6 @@ main(int argc, CHAR16 *argv[])
printf("%s, Revision %s\n", bootprog_name, bootprog_rev);
printf("(%s, %s)\n", bootprog_maker, bootprog_date);
- efi_handle_lookup(img->DeviceHandle, &currdev.d_dev, &currdev.d_unit);
- currdev.d_type = currdev.d_dev->dv_type;
-
/*
* Disable the watchdog timer. By default the boot manager sets
* the timer to 5 minutes before invoking a boot option. If we
@@ -143,19 +181,45 @@ main(int argc, CHAR16 *argv[])
*/
BS->SetWatchdogTimer(0, 0, 0, NULL);
- env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev),
- efi_setcurrdev, env_nounset);
- env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset,
- env_nounset);
+ if (efi_handle_lookup(img->DeviceHandle, &dev, &unit, &pool_guid) != 0)
+ return (EFI_NOT_FOUND);
+
+ switch (dev->dv_type) {
+#ifdef EFI_ZFS_BOOT
+ case DEVT_ZFS: {
+ struct zfs_devdesc currdev;
+
+ currdev.d_dev = dev;
+ currdev.d_unit = unit;
+ currdev.d_type = currdev.d_dev->dv_type;
+ currdev.d_opendata = NULL;
+ currdev.pool_guid = pool_guid;
+ currdev.root_guid = 0;
+ env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev),
+ efi_setcurrdev, env_nounset);
+ env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset,
+ env_nounset);
+ init_zfs_bootenv(zfs_fmtdev(&currdev));
+ break;
+ }
+#endif
+ default: {
+ struct devdesc currdev;
+
+ currdev.d_dev = dev;
+ currdev.d_unit = unit;
+ currdev.d_opendata = NULL;
+ currdev.d_type = currdev.d_dev->dv_type;
+ env_setenv("currdev", EV_VOLATILE, efi_fmtdev(&currdev),
+ efi_setcurrdev, env_nounset);
+ env_setenv("loaddev", EV_VOLATILE, efi_fmtdev(&currdev), env_noset,
+ env_nounset);
+ break;
+ }
+ }
setenv("LINES", "24", 1); /* optional */
- archsw.arch_autoload = efi_autoload;
- archsw.arch_getdev = efi_getdev;
- archsw.arch_copyin = efi_copyin;
- archsw.arch_copyout = efi_copyout;
- archsw.arch_readin = efi_readin;
-
for (k = 0; k < ST->NumberOfTableEntries; k++) {
guid = &ST->ConfigurationTable[k].VendorGuid;
if (!memcmp(guid, &smbios, sizeof(EFI_GUID))) {
@@ -423,6 +487,61 @@ command_nvram(int argc, char *argv[])
return (CMD_OK);
}
+#ifdef EFI_ZFS_BOOT
+COMMAND_SET(lszfs, "lszfs", "list child datasets of a zfs dataset",
+ command_lszfs);
+
+static int
+command_lszfs(int argc, char *argv[])
+{
+ int err;
+
+ if (argc != 2) {
+ command_errmsg = "wrong number of arguments";
+ return (CMD_ERROR);
+ }
+
+ err = zfs_list(argv[1]);
+ if (err != 0) {
+ command_errmsg = strerror(err);
+ return (CMD_ERROR);
+ }
+ return (CMD_OK);
+}
+
+COMMAND_SET(reloadbe, "reloadbe", "refresh the list of ZFS Boot Environments",
+ command_reloadbe);
+
+static int
+command_reloadbe(int argc, char *argv[])
+{
+ int err;
+ char *root;
+
+ if (argc > 2) {
+ command_errmsg = "wrong number of arguments";
+ return (CMD_ERROR);
+ }
+
+ if (argc == 2) {
+ err = zfs_bootenv(argv[1]);
+ } else {
+ root = getenv("zfs_be_root");
+ if (root == NULL) {
+ return (CMD_OK);
+ }
+ err = zfs_bootenv(root);
+ }
+
+ if (err != 0) {
+ command_errmsg = strerror(err);
+ return (CMD_ERROR);
+ }
+
+ return (CMD_OK);
+}
+#endif
+
#ifdef LOADER_FDT_SUPPORT
extern int command_fdt_internal(int argc, char *argv[]);
@@ -441,3 +560,23 @@ command_fdt(int argc, char *argv[])
COMMAND_SET(fdt, "fdt", "flattened device tree handling", command_fdt);
#endif
+
+#ifdef EFI_ZFS_BOOT
+static void
+efi_zfs_probe(void)
+{
+ EFI_HANDLE h;
+ u_int unit;
+ int i;
+ char dname[SPECNAMELEN + 1];
+ uint64_t guid;
+
+ unit = 0;
+ h = efi_find_handle(&efipart_dev, 0);
+ for (i = 0; h != NULL; h = efi_find_handle(&efipart_dev, ++i)) {
+ snprintf(dname, sizeof(dname), "%s%d:", efipart_dev.dv_name, i);
+ if (zfs_probe_dev(dname, &guid) == 0)
+ (void)efi_handle_update_dev(h, &zfs_dev, unit++, guid);
+ }
+}
+#endif
diff --git a/sys/boot/fdt/fdt_loader_cmd.c b/sys/boot/fdt/fdt_loader_cmd.c
index 0ce8f153a80a..a1eaf9d8bbeb 100644
--- a/sys/boot/fdt/fdt_loader_cmd.c
+++ b/sys/boot/fdt/fdt_loader_cmd.c
@@ -464,7 +464,7 @@ fdt_fixup_memory(struct fdt_mem_region *region, size_t num)
{
struct fdt_mem_region *curmr;
uint32_t addr_cells, size_cells;
- uint32_t *addr_cellsp, *reg, *size_cellsp;
+ uint32_t *addr_cellsp, *size_cellsp;
int err, i, len, memory, root;
size_t realmrno;
uint8_t *buf, *sb;
diff --git a/sys/boot/i386/loader/main.c b/sys/boot/i386/loader/main.c
index 644747e81510..c0782fc70e37 100644
--- a/sys/boot/i386/loader/main.c
+++ b/sys/boot/i386/loader/main.c
@@ -69,7 +69,6 @@ static int isa_inb(int port);
static void isa_outb(int port, int value);
void exit(int code);
#ifdef LOADER_ZFS_SUPPORT
-static void init_zfs_bootenv(char *currdev);
static void i386_zfs_probe(void);
#endif
@@ -306,34 +305,6 @@ extract_currdev(void)
env_nounset);
}
-#ifdef LOADER_ZFS_SUPPORT
-static void
-init_zfs_bootenv(char *currdev)
-{
- char *beroot;
-
- if (strlen(currdev) == 0)
- return;
- if(strncmp(currdev, "zfs:", 4) != 0)
- return;
- /* Remove the trailing : */
- currdev[strlen(currdev) - 1] = '\0';
- setenv("zfs_be_active", currdev, 1);
- setenv("zfs_be_currpage", "1", 1);
- /* Do not overwrite if already set */
- setenv("vfs.root.mountfrom", currdev, 0);
- /* Forward past zfs: */
- currdev = strchr(currdev, ':');
- currdev++;
- /* Remove the last element (current bootenv) */
- beroot = strrchr(currdev, '/');
- if (beroot != NULL)
- beroot[0] = '\0';
- beroot = currdev;
- setenv("zfs_be_root", beroot, 1);
-}
-#endif
-
COMMAND_SET(reboot, "reboot", "reboot the system", command_reboot);
static int
diff --git a/sys/boot/userboot/test/test.c b/sys/boot/userboot/test/test.c
index d7ec3e4b5e99..d5707de216a8 100644
--- a/sys/boot/userboot/test/test.c
+++ b/sys/boot/userboot/test/test.c
@@ -414,7 +414,7 @@ void
usage()
{
- printf("usage: [-d <disk image path>] [-h <host filesystem path>\n");
+ printf("usage: [-b <userboot shared object>] [-d <disk image path>] [-h <host filesystem path>\n");
exit(1);
}
@@ -425,9 +425,14 @@ main(int argc, char** argv)
void (*func)(struct loader_callbacks *, void *, int, int);
int opt;
char *disk_image = NULL;
+ const char *userboot_obj = "/boot/userboot.so";
- while ((opt = getopt(argc, argv, "d:h:")) != -1) {
+ while ((opt = getopt(argc, argv, "b:d:h:")) != -1) {
switch (opt) {
+ case 'b':
+ userboot_obj = optarg;
+ break;
+
case 'd':
disk_image = optarg;
break;
@@ -441,8 +446,7 @@ main(int argc, char** argv)
}
}
- h = dlopen("/boot/userboot.so",
- RTLD_LOCAL);
+ h = dlopen(userboot_obj, RTLD_LOCAL);
if (!h) {
printf("%s\n", dlerror());
return (1);
diff --git a/sys/boot/userboot/userboot/main.c b/sys/boot/userboot/userboot/main.c
index a52550cbaea8..e64bbc702419 100644
--- a/sys/boot/userboot/userboot/main.c
+++ b/sys/boot/userboot/userboot/main.c
@@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$");
static void userboot_zfs_probe(void);
static int userboot_zfs_found;
-static void init_zfs_bootenv(char *currdev);
#endif
#define USERBOOT_VERSION USERBOOT_VERSION_3
@@ -200,32 +199,6 @@ extract_currdev(void)
#if defined(USERBOOT_ZFS_SUPPORT)
static void
-init_zfs_bootenv(char *currdev)
-{
- char *beroot;
-
- if (strlen(currdev) == 0)
- return;
- if(strncmp(currdev, "zfs:", 4) != 0)
- return;
- /* Remove the trailing : */
- currdev[strlen(currdev) - 1] = '\0';
- setenv("zfs_be_active", currdev, 1);
- setenv("zfs_be_currpage", "1", 1);
- /* Do not overwrite if already set */
- setenv("vfs.root.mountfrom", currdev, 0);
- /* Forward past zfs: */
- currdev = strchr(currdev, ':');
- currdev++;
- /* Remove the last element (current bootenv) */
- beroot = strrchr(currdev, '/');
- if (beroot != NULL)
- beroot[0] = '\0';
- beroot = currdev;
- setenv("zfs_be_root", beroot, 1);
-}
-
-static void
userboot_zfs_probe(void)
{
char devname[32];
diff --git a/sys/boot/zfs/libzfs.h b/sys/boot/zfs/libzfs.h
index b28984958c9a..ee64d1cf32d3 100644
--- a/sys/boot/zfs/libzfs.h
+++ b/sys/boot/zfs/libzfs.h
@@ -62,6 +62,7 @@ int zfs_parsedev(struct zfs_devdesc *dev, const char *devspec,
char *zfs_fmtdev(void *vdev);
int zfs_probe_dev(const char *devname, uint64_t *pool_guid);
int zfs_list(const char *name);
+void init_zfs_bootenv(char *currdev);
int zfs_bootenv(const char *name);
int zfs_belist_add(const char *name);
int zfs_set_env(void);
diff --git a/sys/boot/zfs/zfs.c b/sys/boot/zfs/zfs.c
index c8b1284bc8c7..8e6d420b4e92 100644
--- a/sys/boot/zfs/zfs.c
+++ b/sys/boot/zfs/zfs.c
@@ -709,6 +709,32 @@ zfs_list(const char *name)
return (zfs_list_dataset(spa, objid));
}
+void
+init_zfs_bootenv(char *currdev)
+{
+ char *beroot;
+
+ if (strlen(currdev) == 0)
+ return;
+ if(strncmp(currdev, "zfs:", 4) != 0)
+ return;
+ /* Remove the trailing : */
+ currdev[strlen(currdev) - 1] = '\0';
+ setenv("zfs_be_active", currdev, 1);
+ setenv("zfs_be_currpage", "1", 1);
+ /* Do not overwrite if already set */
+ setenv("vfs.root.mountfrom", currdev, 0);
+ /* Forward past zfs: */
+ currdev = strchr(currdev, ':');
+ currdev++;
+ /* Remove the last element (current bootenv) */
+ beroot = strrchr(currdev, '/');
+ if (beroot != NULL)
+ beroot[0] = '\0';
+ beroot = currdev;
+ setenv("zfs_be_root", beroot, 1);
+}
+
int
zfs_bootenv(const char *name)
{
@@ -779,8 +805,15 @@ int
zfs_belist_add(const char *name)
{
+ /* Skip special datasets that start with a $ character */
+ if (strncmp(name, "$", 1) == 0) {
+ return (0);
+ }
/* Add the boot environment to the head of the SLIST */
zfs_be = malloc(sizeof(struct zfs_be_entry));
+ if (zfs_be == NULL) {
+ return (ENOMEM);
+ }
zfs_be->name = name;
SLIST_INSERT_HEAD(&zfs_be_head, zfs_be, entries);
zfs_env_count++;
diff --git a/sys/boot/zfs/zfsimpl.c b/sys/boot/zfs/zfsimpl.c
index 927fbadd8021..aa1a789b6c33 100644
--- a/sys/boot/zfs/zfsimpl.c
+++ b/sys/boot/zfs/zfsimpl.c
@@ -2165,7 +2165,13 @@ zfs_lookup(const struct zfsmount *mount, const char *upath, dnode_phys_t *dnode)
strcpy(&path[sb.st_size], p);
else
path[sb.st_size] = 0;
- if (sb.st_size + sizeof(znode_phys_t) <= dn.dn_bonuslen) {
+ /*
+ * Second test is purely to silence bogus compiler
+ * warning about accessing past the end of dn_bonus.
+ */
+ if (sb.st_size + sizeof(znode_phys_t) <=
+ dn.dn_bonuslen && sizeof(znode_phys_t) <=
+ sizeof(dn.dn_bonus)) {
memcpy(path, &dn.dn_bonus[sizeof(znode_phys_t)],
sb.st_size);
} else {
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
index cf9112b72aa2..b7801acaadc5 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
@@ -610,7 +610,6 @@ spa_prop_validate(spa_t *spa, nvlist_t *props)
error = SET_ERROR(EINVAL);
break;
}
- check++;
}
if (strlen(strval) > ZPROP_MAX_COMMENT)
error = E2BIG;
@@ -5952,6 +5951,8 @@ spa_async_remove(spa_t *spa, vdev_t *vd)
vd->vdev_stat.vs_checksum_errors = 0;
vdev_state_dirty(vd->vdev_top);
+ /* Tell userspace that the vdev is gone. */
+ zfs_post_remove(spa, vd);
}
for (int c = 0; c < vd->vdev_children; c++)
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
index 99496c06af8f..4c7c89df3b0f 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
@@ -160,7 +160,6 @@ vdev_geom_orphan(struct g_consumer *cp)
* async removal support to invoke a close on this
* vdev once it is safe to do so.
*/
- zfs_post_remove(vd->vdev_spa, vd);
vd->vdev_remove_wanted = B_TRUE;
spa_async_request(vd->vdev_spa, SPA_ASYNC_REMOVE);
}
diff --git a/sys/compat/linux/linux_futex.c b/sys/compat/linux/linux_futex.c
index db8ab2c71eb6..be7c8a0d5388 100644
--- a/sys/compat/linux/linux_futex.c
+++ b/sys/compat/linux/linux_futex.c
@@ -1131,7 +1131,7 @@ linux_get_robust_list(struct thread *td, struct linux_get_robust_list_args *args
return (EFAULT);
}
- error = copyout(head, args->head, sizeof(struct linux_robust_list_head));
+ error = copyout(&head, args->head, sizeof(head));
if (error) {
LIN_SDT_PROBE1(futex, linux_get_robust_list, copyout_error,
error);
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
index de918695c8e8..fe4dbf642427 100644
--- a/sys/compat/linux/linux_misc.c
+++ b/sys/compat/linux/linux_misc.c
@@ -1304,9 +1304,11 @@ linux_setgroups(struct thread *td, struct linux_setgroups_args *args)
if (error)
goto out;
newcred = crget();
+ crextend(newcred, ngrp + 1);
p = td->td_proc;
PROC_LOCK(p);
- oldcred = crcopysafe(p, newcred);
+ oldcred = p->p_ucred;
+ crcopy(newcred, oldcred);
/*
* cr_groups[0] holds egid. Setting the whole set from
diff --git a/sys/compat/linuxkpi/common/include/linux/pci.h b/sys/compat/linuxkpi/common/include/linux/pci.h
index 54ea99c5e8e4..0e6dbfd0bb4e 100644
--- a/sys/compat/linuxkpi/common/include/linux/pci.h
+++ b/sys/compat/linuxkpi/common/include/linux/pci.h
@@ -129,8 +129,9 @@ struct pci_driver {
const struct pci_device_id *id_table;
int (*probe)(struct pci_dev *dev, const struct pci_device_id *id);
void (*remove)(struct pci_dev *dev);
- int (*suspend) (struct pci_dev *dev, pm_message_t state); /* Device suspended */
- int (*resume) (struct pci_dev *dev); /* Device woken up */
+ int (*suspend) (struct pci_dev *dev, pm_message_t state); /* Device suspended */
+ int (*resume) (struct pci_dev *dev); /* Device woken up */
+ void (*shutdown) (struct pci_dev *dev); /* Device shutdown */
driver_t driver;
devclass_t bsdclass;
const struct pci_error_handlers *err_handler;
diff --git a/sys/compat/linuxkpi/common/src/linux_pci.c b/sys/compat/linuxkpi/common/src/linux_pci.c
index 7c49a54a6dc0..74d4f7711297 100644
--- a/sys/compat/linuxkpi/common/src/linux_pci.c
+++ b/sys/compat/linuxkpi/common/src/linux_pci.c
@@ -61,11 +61,17 @@ __FBSDID("$FreeBSD$");
static device_probe_t linux_pci_probe;
static device_attach_t linux_pci_attach;
static device_detach_t linux_pci_detach;
+static device_suspend_t linux_pci_suspend;
+static device_resume_t linux_pci_resume;
+static device_shutdown_t linux_pci_shutdown;
static device_method_t pci_methods[] = {
DEVMETHOD(device_probe, linux_pci_probe),
DEVMETHOD(device_attach, linux_pci_attach),
DEVMETHOD(device_detach, linux_pci_detach),
+ DEVMETHOD(device_suspend, linux_pci_suspend),
+ DEVMETHOD(device_resume, linux_pci_resume),
+ DEVMETHOD(device_shutdown, linux_pci_shutdown),
DEVMETHOD_END
};
@@ -169,6 +175,46 @@ linux_pci_detach(device_t dev)
return (0);
}
+static int
+linux_pci_suspend(device_t dev)
+{
+ struct pm_message pm = { };
+ struct pci_dev *pdev;
+ int err;
+
+ pdev = device_get_softc(dev);
+ if (pdev->pdrv->suspend != NULL)
+ err = -pdev->pdrv->suspend(pdev, pm);
+ else
+ err = 0;
+ return (err);
+}
+
+static int
+linux_pci_resume(device_t dev)
+{
+ struct pci_dev *pdev;
+ int err;
+
+ pdev = device_get_softc(dev);
+ if (pdev->pdrv->resume != NULL)
+ err = -pdev->pdrv->resume(pdev);
+ else
+ err = 0;
+ return (err);
+}
+
+static int
+linux_pci_shutdown(device_t dev)
+{
+ struct pci_dev *pdev;
+
+ pdev = device_get_softc(dev);
+ if (pdev->pdrv->shutdown != NULL)
+ pdev->pdrv->shutdown(pdev);
+ return (0);
+}
+
int
pci_register_driver(struct pci_driver *pdrv)
{
diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64
index 0788b4669efa..5944a383d692 100644
--- a/sys/conf/files.amd64
+++ b/sys/conf/files.amd64
@@ -273,6 +273,7 @@ dev/hyperv/vmbus/hv_channel.c optional hyperv
dev/hyperv/vmbus/hv_channel_mgmt.c optional hyperv
dev/hyperv/vmbus/hv_connection.c optional hyperv
dev/hyperv/vmbus/hv_hv.c optional hyperv
+dev/hyperv/vmbus/hv_et.c optional hyperv
dev/hyperv/vmbus/hv_ring_buffer.c optional hyperv
dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c optional hyperv
dev/nfe/if_nfe.c optional nfe pci
@@ -316,6 +317,7 @@ dev/sfxge/common/efx_ev.c optional sfxge pci
dev/sfxge/common/efx_filter.c optional sfxge pci
dev/sfxge/common/efx_hash.c optional sfxge pci
dev/sfxge/common/efx_intr.c optional sfxge pci
+dev/sfxge/common/efx_lic.c optional sfxge pci
dev/sfxge/common/efx_mac.c optional sfxge pci
dev/sfxge/common/efx_mcdi.c optional sfxge pci
dev/sfxge/common/efx_mon.c optional sfxge pci
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index ffe272e382d7..334e85784955 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -247,6 +247,7 @@ dev/hyperv/vmbus/hv_channel.c optional hyperv
dev/hyperv/vmbus/hv_channel_mgmt.c optional hyperv
dev/hyperv/vmbus/hv_connection.c optional hyperv
dev/hyperv/vmbus/hv_hv.c optional hyperv
+dev/hyperv/vmbus/hv_et.c optional hyperv
dev/hyperv/vmbus/hv_ring_buffer.c optional hyperv
dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c optional hyperv
dev/ichwd/ichwd.c optional ichwd
diff --git a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_kmod.c b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_kmod.c
index e0cbb6622d3d..93aa6f8ba27a 100644
--- a/sys/contrib/vchiq/interface/vchiq_arm/vchiq_kmod.c
+++ b/sys/contrib/vchiq/interface/vchiq_arm/vchiq_kmod.c
@@ -173,7 +173,7 @@ bcm_vchiq_attach(device_t dev)
return (ENXIO);
}
- mtx_init(&sc->lock, "vchiq", MTX_DEF, 0);
+ mtx_init(&sc->lock, "vchiq", 0, MTX_DEF);
bcm_vchiq_sc = sc;
vchiq_init();
diff --git a/sys/dev/drm2/drm_crtc.c b/sys/dev/drm2/drm_crtc.c
index 79f66aafc549..318a764805cb 100644
--- a/sys/dev/drm2/drm_crtc.c
+++ b/sys/dev/drm2/drm_crtc.c
@@ -663,7 +663,7 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
plane->dev = dev;
plane->funcs = funcs;
plane->format_types = malloc(sizeof(uint32_t) * format_count,
- DRM_MEM_KMS, M_NOWAIT);
+ DRM_MEM_KMS, M_WAITOK);
if (!plane->format_types) {
DRM_DEBUG_KMS("out of memory when allocating plane\n");
drm_mode_object_put(dev, &plane->base);
@@ -1010,7 +1010,7 @@ int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group)
total_objects += dev->mode_config.num_encoder;
group->id_list = malloc(total_objects * sizeof(uint32_t),
- DRM_MEM_KMS, M_NOWAIT | M_ZERO);
+ DRM_MEM_KMS, M_WAITOK | M_ZERO);
if (!group->id_list)
return -ENOMEM;
@@ -1998,7 +1998,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
connector_set = malloc(crtc_req->count_connectors *
sizeof(struct drm_connector *),
- DRM_MEM_KMS, M_NOWAIT);
+ DRM_MEM_KMS, M_WAITOK);
if (!connector_set) {
ret = -ENOMEM;
goto out;
@@ -2523,7 +2523,7 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
goto out_err1;
}
clips = malloc(num_clips * sizeof(*clips), DRM_MEM_KMS,
- M_NOWAIT | M_ZERO);
+ M_WAITOK | M_ZERO);
if (!clips) {
ret = -ENOMEM;
goto out_err1;
@@ -2774,13 +2774,13 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags,
int ret;
property = malloc(sizeof(struct drm_property), DRM_MEM_KMS,
- M_NOWAIT | M_ZERO);
+ M_WAITOK | M_ZERO);
if (!property)
return NULL;
if (num_values) {
property->values = malloc(sizeof(uint64_t)*num_values, DRM_MEM_KMS,
- M_NOWAIT | M_ZERO);
+ M_WAITOK | M_ZERO);
if (!property->values)
goto fail;
}
@@ -2908,7 +2908,7 @@ int drm_property_add_enum(struct drm_property *property, int index,
}
prop_enum = malloc(sizeof(struct drm_property_enum), DRM_MEM_KMS,
- M_NOWAIT | M_ZERO);
+ M_WAITOK | M_ZERO);
if (!prop_enum)
return -ENOMEM;
@@ -3104,7 +3104,7 @@ static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev
return NULL;
blob = malloc(sizeof(struct drm_property_blob)+length, DRM_MEM_KMS,
- M_NOWAIT | M_ZERO);
+ M_WAITOK | M_ZERO);
if (!blob)
return NULL;
@@ -3434,7 +3434,7 @@ int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
crtc->gamma_size = gamma_size;
crtc->gamma_store = malloc(gamma_size * sizeof(uint16_t) * 3,
- DRM_MEM_KMS, M_NOWAIT | M_ZERO);
+ DRM_MEM_KMS, M_WAITOK | M_ZERO);
if (!crtc->gamma_store) {
crtc->gamma_size = 0;
return -ENOMEM;
@@ -3632,7 +3632,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
file_priv->event_space -= sizeof e->event;
mtx_unlock(&dev->event_lock);
- e = malloc(sizeof *e, DRM_MEM_KMS, M_NOWAIT | M_ZERO);
+ e = malloc(sizeof *e, DRM_MEM_KMS, M_WAITOK | M_ZERO);
if (e == NULL) {
mtx_lock(&dev->event_lock);
file_priv->event_space += sizeof e->event;
diff --git a/sys/dev/drm2/drm_pci.c b/sys/dev/drm2/drm_pci.c
index ecbfcb7c7df3..f2c5bbd2dc5e 100644
--- a/sys/dev/drm2/drm_pci.c
+++ b/sys/dev/drm2/drm_pci.c
@@ -225,7 +225,7 @@ int drm_pci_set_unique(struct drm_device *dev,
master->unique_len = u->unique_len;
master->unique_size = u->unique_len + 1;
- master->unique = malloc(master->unique_size, DRM_MEM_DRIVER, M_NOWAIT);
+ master->unique = malloc(master->unique_size, DRM_MEM_DRIVER, M_WAITOK);
if (!master->unique) {
ret = -ENOMEM;
goto err;
diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index f586d399822f..c1a9ce8717df 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -2035,9 +2035,9 @@ retry:
if (error == EFBIG && remap) {
struct mbuf *m;
- m = m_defrag(*m_headp, M_NOWAIT);
+ m = m_collapse(*m_headp, M_NOWAIT, EM_MAX_SCATTER);
if (m == NULL) {
- adapter->mbuf_alloc_failed++;
+ adapter->mbuf_defrag_failed++;
m_freem(*m_headp);
*m_headp = NULL;
return (ENOBUFS);
@@ -5493,18 +5493,15 @@ em_add_hw_stats(struct adapter *adapter)
char namebuf[QUEUE_NAME_LEN];
/* Driver Statistics */
- SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "link_irq",
- CTLFLAG_RD, &adapter->link_irq,
- "Link MSIX IRQ Handled");
- SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "mbuf_alloc_fail",
- CTLFLAG_RD, &adapter->mbuf_alloc_failed,
- "Std mbuf failed");
- SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "cluster_alloc_fail",
- CTLFLAG_RD, &adapter->mbuf_cluster_failed,
- "Std mbuf cluster failed");
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped",
CTLFLAG_RD, &adapter->dropped_pkts,
"Driver dropped packets");
+ SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "link_irq",
+ CTLFLAG_RD, &adapter->link_irq,
+ "Link MSIX IRQ Handled");
+ SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "mbuf_defrag_fail",
+ CTLFLAG_RD, &adapter->mbuf_defrag_failed,
+ "Defragmenting mbuf chain failed");
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_dma_fail",
CTLFLAG_RD, &adapter->no_tx_dma_setup,
"Driver tx dma failure in xmit");
diff --git a/sys/dev/e1000/if_em.h b/sys/dev/e1000/if_em.h
index be9fdc96e6d3..362df49442a7 100644
--- a/sys/dev/e1000/if_em.h
+++ b/sys/dev/e1000/if_em.h
@@ -473,13 +473,12 @@ struct adapter {
/* Misc stats maintained by the driver */
unsigned long dropped_pkts;
- unsigned long mbuf_alloc_failed;
- unsigned long mbuf_cluster_failed;
+ unsigned long link_irq;
+ unsigned long mbuf_defrag_failed;
+ unsigned long no_tx_dma_setup;
unsigned long no_tx_map_avail;
- unsigned long no_tx_dma_setup;
unsigned long rx_overruns;
unsigned long watchdog_events;
- unsigned long link_irq;
struct e1000_hw_stats stats;
};
diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c
index 498817838f3a..5b172dfe017f 100644
--- a/sys/dev/e1000/if_igb.c
+++ b/sys/dev/e1000/if_igb.c
@@ -1835,7 +1835,8 @@ retry:
/* Try it again? - one try */
if (remap == TRUE) {
remap = FALSE;
- m = m_defrag(*m_headp, M_NOWAIT);
+ m = m_collapse(*m_headp, M_NOWAIT,
+ IGB_MAX_SCATTER);
if (m == NULL) {
adapter->mbuf_defrag_failed++;
m_freem(*m_headp);
@@ -5826,12 +5827,15 @@ igb_add_hw_stats(struct adapter *adapter)
char namebuf[QUEUE_NAME_LEN];
/* Driver Statistics */
- SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "link_irq",
- CTLFLAG_RD, &adapter->link_irq,
- "Link MSIX IRQ Handled");
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped",
CTLFLAG_RD, &adapter->dropped_pkts,
"Driver dropped packets");
+ SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "link_irq",
+ CTLFLAG_RD, &adapter->link_irq,
+ "Link MSIX IRQ Handled");
+ SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "mbuf_defrag_fail",
+ CTLFLAG_RD, &adapter->mbuf_defrag_failed,
+ "Defragmenting mbuf chain failed");
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "tx_dma_fail",
CTLFLAG_RD, &adapter->no_tx_dma_setup,
"Driver tx dma failure in xmit");
diff --git a/sys/dev/e1000/if_igb.h b/sys/dev/e1000/if_igb.h
index c14778891fe8..af42b56ec873 100644
--- a/sys/dev/e1000/if_igb.h
+++ b/sys/dev/e1000/if_igb.h
@@ -512,20 +512,19 @@ struct adapter {
u8 *mta;
/* Misc stats maintained by the driver */
+ unsigned long device_control;
unsigned long dropped_pkts;
+ unsigned long eint_mask;
+ unsigned long int_mask;
+ unsigned long link_irq;
unsigned long mbuf_defrag_failed;
- unsigned long mbuf_header_failed;
- unsigned long mbuf_packet_failed;
unsigned long no_tx_dma_setup;
- unsigned long watchdog_events;
- unsigned long link_irq;
- unsigned long rx_overruns;
- unsigned long device_control;
- unsigned long rx_control;
- unsigned long int_mask;
- unsigned long eint_mask;
unsigned long packet_buf_alloc_rx;
unsigned long packet_buf_alloc_tx;
+ unsigned long rx_control;
+ unsigned long rx_overruns;
+ unsigned long watchdog_events;
+
/* Used in pf and vf */
void *stats;
diff --git a/sys/dev/e1000/if_lem.c b/sys/dev/e1000/if_lem.c
index 7476be50be7d..674fe5be1984 100644
--- a/sys/dev/e1000/if_lem.c
+++ b/sys/dev/e1000/if_lem.c
@@ -1675,9 +1675,9 @@ lem_xmit(struct adapter *adapter, struct mbuf **m_headp)
if (error == EFBIG) {
struct mbuf *m;
- m = m_defrag(*m_headp, M_NOWAIT);
+ m = m_collapse(*m_headp, M_NOWAIT, EM_MAX_SCATTER);
if (m == NULL) {
- adapter->mbuf_alloc_failed++;
+ adapter->mbuf_defrag_failed++;
m_freem(*m_headp);
*m_headp = NULL;
return (ENOBUFS);
@@ -4526,12 +4526,12 @@ lem_add_hw_stats(struct adapter *adapter)
struct sysctl_oid_list *stat_list;
/* Driver Statistics */
- SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "mbuf_alloc_fail",
- CTLFLAG_RD, &adapter->mbuf_alloc_failed,
- "Std mbuf failed");
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "cluster_alloc_fail",
CTLFLAG_RD, &adapter->mbuf_cluster_failed,
"Std mbuf cluster failed");
+ SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "mbuf_defrag_fail",
+ CTLFLAG_RD, &adapter->mbuf_defrag_failed,
+ "Defragmenting mbuf chain failed");
SYSCTL_ADD_ULONG(ctx, child, OID_AUTO, "dropped",
CTLFLAG_RD, &adapter->dropped_pkts,
"Driver dropped packets");
diff --git a/sys/dev/e1000/if_lem.h b/sys/dev/e1000/if_lem.h
index 4c43bddb5636..0dde26ecb4ee 100644
--- a/sys/dev/e1000/if_lem.h
+++ b/sys/dev/e1000/if_lem.h
@@ -417,17 +417,17 @@ struct adapter {
/* Misc stats maintained by the driver */
unsigned long dropped_pkts;
- unsigned long mbuf_alloc_failed;
+ unsigned long link_irq;
unsigned long mbuf_cluster_failed;
+ unsigned long mbuf_defrag_failed;
unsigned long no_tx_desc_avail1;
unsigned long no_tx_desc_avail2;
+ unsigned long no_tx_dma_setup;
unsigned long no_tx_map_avail;
- unsigned long no_tx_dma_setup;
unsigned long watchdog_events;
- unsigned long rx_overruns;
unsigned long rx_irq;
+ unsigned long rx_overruns;
unsigned long tx_irq;
- unsigned long link_irq;
/* 82547 workaround */
uint32_t tx_fifo_size;
diff --git a/sys/dev/gpio/gpiobus.c b/sys/dev/gpio/gpiobus.c
index 67106eaaca82..4a7994ead3a1 100644
--- a/sys/dev/gpio/gpiobus.c
+++ b/sys/dev/gpio/gpiobus.c
@@ -184,7 +184,7 @@ gpiobus_init_softc(device_t dev)
if (GPIO_PIN_MAX(sc->sc_dev, &sc->sc_npins) != 0)
return (ENXIO);
- KASSERT(sc->sc_npins != 0, ("GPIO device with no pins"));
+ KASSERT(sc->sc_npins >= 0, ("GPIO device with no pins"));
/* Pins = GPIO_PIN_MAX() + 1 */
sc->sc_npins++;
diff --git a/sys/dev/hyperv/include/hyperv.h b/sys/dev/hyperv/include/hyperv.h
index b5600baf0149..1a45b7ba8b3b 100644
--- a/sys/dev/hyperv/include/hyperv.h
+++ b/sys/dev/hyperv/include/hyperv.h
@@ -335,11 +335,6 @@ typedef enum {
HV_CHANNEL_MESSAGE_INITIATED_CONTACT = 14,
HV_CHANNEL_MESSAGE_VERSION_RESPONSE = 15,
HV_CHANNEL_MESSAGE_UNLOAD = 16,
-
-#ifdef HV_VMBUS_FEATURE_PARENT_OR_PEER_MEMORY_MAPPED_INTO_A_CHILD
- HV_CHANNEL_MESSAGE_VIEW_RANGE_ADD = 17,
- HV_CHANNEL_MESSAGE_VIEW_RANGE_REMOVE = 18,
-#endif
HV_CHANNEL_MESSAGE_COUNT
} hv_vmbus_channel_msg_type;
diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.c b/sys/dev/hyperv/netvsc/hv_net_vsc.c
index 99e500c57479..65913b5a76f2 100644
--- a/sys/dev/hyperv/netvsc/hv_net_vsc.c
+++ b/sys/dev/hyperv/netvsc/hv_net_vsc.c
@@ -642,6 +642,12 @@ hv_nv_connect_to_vsp(struct hv_device *device)
/* sema_wait(&NetVscChannel->channel_init_sema); */
/* Post the big receive buffer to NetVSP */
+ if (net_dev->nvsp_version <= NVSP_PROTOCOL_VERSION_2)
+ net_dev->rx_buf_size = NETVSC_RECEIVE_BUFFER_SIZE_LEGACY;
+ else
+ net_dev->rx_buf_size = NETVSC_RECEIVE_BUFFER_SIZE;
+ net_dev->send_buf_size = NETVSC_SEND_BUFFER_SIZE;
+
ret = hv_nv_init_rx_buffer_with_net_vsp(device);
if (ret == 0)
ret = hv_nv_init_send_buffer_with_net_vsp(device);
@@ -676,9 +682,6 @@ hv_nv_on_device_add(struct hv_device *device, void *additional_info)
goto cleanup;
/* Initialize the NetVSC channel extension */
- net_dev->rx_buf_size = NETVSC_RECEIVE_BUFFER_SIZE;
-
- net_dev->send_buf_size = NETVSC_SEND_BUFFER_SIZE;
sema_init(&net_dev->channel_init_sema, 0, "netdev_sema");
diff --git a/sys/dev/hyperv/netvsc/hv_net_vsc.h b/sys/dev/hyperv/netvsc/hv_net_vsc.h
index b1d1e37cedca..9157f918dbb1 100644
--- a/sys/dev/hyperv/netvsc/hv_net_vsc.h
+++ b/sys/dev/hyperv/netvsc/hv_net_vsc.h
@@ -857,7 +857,7 @@ typedef struct nvsp_msg_ {
#define NETVSC_SEND_BUFFER_SIZE (1024*1024*15) /* 15M */
#define NETVSC_SEND_BUFFER_ID 0xface
-
+#define NETVSC_RECEIVE_BUFFER_SIZE_LEGACY (1024*1024*15) /* 15MB */
#define NETVSC_RECEIVE_BUFFER_SIZE (1024*1024*16) /* 16MB */
#define NETVSC_RECEIVE_BUFFER_ID 0xcafe
diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
index 68f822a004bd..fd23db90e9d7 100644
--- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
+++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
@@ -391,12 +391,14 @@ netvsc_attach(device_t dev)
sc->hn_carrier = 1;
}
+#if defined(INET) || defined(INET6)
tcp_lro_init(&sc->hn_lro);
/* Driver private LRO settings */
sc->hn_lro.ifp = ifp;
#ifdef HN_LRO_HIWAT
sc->hn_lro.lro_hiwat = sc->hn_lro_hiwat;
#endif
+#endif /* INET || INET6 */
ether_ifattach(ifp, device_info.mac_addr);
@@ -475,7 +477,9 @@ netvsc_detach(device_t dev)
hv_rf_on_device_remove(hv_device, HV_RF_NV_DESTROY_CHANNEL);
ifmedia_removeall(&sc->hn_media);
+#if defined(INET) || defined(INET6)
tcp_lro_free(&sc->hn_lro);
+#endif
return (0);
}
@@ -1083,6 +1087,7 @@ skip:
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
if ((ifp->if_capenable & IFCAP_LRO) && do_lro) {
+#if defined(INET) || defined(INET6)
struct lro_ctrl *lro = &sc->hn_lro;
if (lro->lro_cnt) {
@@ -1092,6 +1097,7 @@ skip:
return 0;
}
}
+#endif
}
/* We're not holding the lock here, so don't release it */
@@ -1103,6 +1109,7 @@ skip:
void
netvsc_recv_rollup(struct hv_device *device_ctx)
{
+#if defined(INET) || defined(INET6)
hn_softc_t *sc = device_get_softc(device_ctx->device);
struct lro_ctrl *lro = &sc->hn_lro;
struct lro_entry *queued;
@@ -1111,6 +1118,7 @@ netvsc_recv_rollup(struct hv_device *device_ctx)
SLIST_REMOVE_HEAD(&lro->lro_active, next);
tcp_lro_flush(lro, queued);
}
+#endif
}
/*
diff --git a/sys/dev/hyperv/vmbus/hv_connection.c b/sys/dev/hyperv/vmbus/hv_connection.c
index 0300828961ba..691d0694e1b6 100644
--- a/sys/dev/hyperv/vmbus/hv_connection.c
+++ b/sys/dev/hyperv/vmbus/hv_connection.c
@@ -251,7 +251,7 @@ hv_vmbus_connect(void) {
hv_vmbus_protocal_version = version;
if (bootverbose)
- printf("VMBUS: Portocal Version: %d.%d\n",
+ printf("VMBUS: Protocol Version: %d.%d\n",
version >> 16, version & 0xFFFF);
sema_destroy(&msg_info->wait_sema);
@@ -423,12 +423,6 @@ VmbusProcessChannelEvent(uint32_t relid)
// mtx_unlock(&channel->inbound_lock);
}
-#ifdef HV_DEBUG_INTR
-extern uint32_t hv_intr_count;
-extern uint32_t hv_vmbus_swintr_event_cpu[MAXCPU];
-extern uint32_t hv_vmbus_intr_cpu[MAXCPU];
-#endif
-
/**
* Handler for events
*/
@@ -449,17 +443,6 @@ hv_vmbus_on_events(void *arg)
KASSERT(cpu <= mp_maxid, ("VMBUS: hv_vmbus_on_events: "
"cpu out of range!"));
-#ifdef HV_DEBUG_INTR
- int i;
- hv_vmbus_swintr_event_cpu[cpu]++;
- if (hv_intr_count % 10000 == 0) {
- printf("VMBUS: Total interrupt %d\n", hv_intr_count);
- for (i = 0; i < mp_ncpus; i++)
- printf("VMBUS: hw cpu[%d]: %d, event sw intr cpu[%d]: %d\n",
- i, hv_vmbus_intr_cpu[i], i, hv_vmbus_swintr_event_cpu[i]);
- }
-#endif
-
if ((hv_vmbus_protocal_version == HV_VMBUS_VERSION_WS2008) ||
(hv_vmbus_protocal_version == HV_VMBUS_VERSION_WIN7)) {
maxdword = HV_MAX_NUM_CHANNELS_SUPPORTED >> 5;
diff --git a/sys/dev/hyperv/vmbus/hv_et.c b/sys/dev/hyperv/vmbus/hv_et.c
new file mode 100644
index 000000000000..d96148673b6f
--- /dev/null
+++ b/sys/dev/hyperv/vmbus/hv_et.c
@@ -0,0 +1,131 @@
+/*-
+ * Copyright (c) 2015 Microsoft Corp.
+ * 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/param.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/smp.h>
+#include <sys/time.h>
+#include <sys/timeet.h>
+
+#include "hv_vmbus_priv.h"
+
+#define HV_TIMER_FREQUENCY (10 * 1000 * 1000LL) /* 100ns period */
+#define HV_MAX_DELTA_TICKS 0xffffffffLL
+#define HV_MIN_DELTA_TICKS 1LL
+
+static struct eventtimer et;
+static uint64_t periodticks[MAXCPU];
+
+static inline uint64_t
+sbintime2tick(sbintime_t time)
+{
+ struct timespec val;
+
+ val = sbttots(time);
+ return val.tv_sec * HV_TIMER_FREQUENCY + val.tv_nsec / 100;
+}
+
+static int
+hv_et_start(struct eventtimer *et, sbintime_t firsttime, sbintime_t periodtime)
+{
+ union hv_timer_config timer_cfg;
+ uint64_t current;
+
+ timer_cfg.as_uint64 = 0;
+ timer_cfg.auto_enable = 1;
+ timer_cfg.sintx = HV_VMBUS_MESSAGE_SINT;
+
+ periodticks[curcpu] = sbintime2tick(periodtime);
+ if (firsttime == 0)
+ firsttime = periodtime;
+
+ current = rdmsr(HV_X64_MSR_TIME_REF_COUNT);
+ current += sbintime2tick(firsttime);
+
+ wrmsr(HV_X64_MSR_STIMER0_CONFIG, timer_cfg.as_uint64);
+ wrmsr(HV_X64_MSR_STIMER0_COUNT, current);
+
+ return (0);
+}
+
+static int
+hv_et_stop(struct eventtimer *et)
+{
+ wrmsr(HV_X64_MSR_STIMER0_CONFIG, 0);
+ wrmsr(HV_X64_MSR_STIMER0_COUNT, 0);
+
+ return (0);
+}
+
+void
+hv_et_intr(struct trapframe *frame)
+{
+ union hv_timer_config timer_cfg;
+ struct trapframe *oldframe;
+ struct thread *td;
+
+ if (periodticks[curcpu] != 0) {
+ uint64_t tick = sbintime2tick(periodticks[curcpu]);
+ timer_cfg.as_uint64 = rdmsr(HV_X64_MSR_STIMER0_CONFIG);
+ timer_cfg.enable = 0;
+ timer_cfg.auto_enable = 1;
+ timer_cfg.periodic = 1;
+ periodticks[curcpu] = 0;
+
+ wrmsr(HV_X64_MSR_STIMER0_CONFIG, timer_cfg.as_uint64);
+ wrmsr(HV_X64_MSR_STIMER0_COUNT, tick);
+ }
+
+ if (et.et_active) {
+ td = curthread;
+ td->td_intr_nesting_level++;
+ oldframe = td->td_intr_frame;
+ td->td_intr_frame = frame;
+ et.et_event_cb(&et, et.et_arg);
+ td->td_intr_frame = oldframe;
+ td->td_intr_nesting_level--;
+ }
+}
+
+void
+hv_et_init(void)
+{
+ et.et_name = "HyperV";
+ et.et_flags = ET_FLAGS_ONESHOT | ET_FLAGS_PERCPU | ET_FLAGS_PERIODIC;
+ et.et_quality = 1000;
+ et.et_frequency = HV_TIMER_FREQUENCY;
+ et.et_min_period = (1LL << 32) / HV_TIMER_FREQUENCY;
+ et.et_max_period = HV_MAX_DELTA_TICKS * ((1LL << 32) / HV_TIMER_FREQUENCY);
+ et.et_start = hv_et_start;
+ et.et_stop = hv_et_stop;
+ et.et_priv = &et;
+ et_register(&et);
+}
+
diff --git a/sys/dev/hyperv/vmbus/hv_hv.c b/sys/dev/hyperv/vmbus/hv_hv.c
index 84e2a5e46fcf..ca5641f620bf 100644
--- a/sys/dev/hyperv/vmbus/hv_hv.c
+++ b/sys/dev/hyperv/vmbus/hv_hv.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/pcpu.h>
#include <sys/timetc.h>
#include <machine/bus.h>
+#include <machine/md_var.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/pmap.h>
@@ -44,23 +45,11 @@ __FBSDID("$FreeBSD$");
#include "hv_vmbus_priv.h"
-#define HV_X64_MSR_GUEST_OS_ID 0x40000000
-
-#define HV_X64_CPUID_MIN 0x40000005
-#define HV_X64_CPUID_MAX 0x4000ffff
-#define HV_X64_MSR_TIME_REF_COUNT 0x40000020
-
#define HV_NANOSECONDS_PER_SEC 1000000000L
static u_int hv_get_timecount(struct timecounter *tc);
-static inline void do_cpuid_inline(unsigned int op, unsigned int *eax,
- unsigned int *ebx, unsigned int *ecx, unsigned int *edx) {
- __asm__ __volatile__("cpuid" : "=a" (*eax), "=b" (*ebx), "=c" (*ecx),
- "=d" (*edx) : "0" (op), "c" (ecx));
-}
-
/**
* Globals
*/
@@ -86,27 +75,10 @@ hv_get_timecount(struct timecounter *tc)
int
hv_vmbus_query_hypervisor_presence(void)
{
- u_int regs[4];
- int hyper_v_detected = 0;
-
- /*
- * When Xen is detected and native Xen PV support is enabled,
- * ignore Xen's HyperV emulation.
- */
- if (vm_guest == VM_GUEST_XEN)
+ if (vm_guest != VM_GUEST_HV)
return (0);
- do_cpuid(1, regs);
- if (regs[2] & 0x80000000) { /* if(a hypervisor is detected) */
- /* make sure this really is Hyper-V */
- /* we look at the CPUID info */
- do_cpuid(HV_X64_MSR_GUEST_OS_ID, regs);
- hyper_v_detected =
- regs[0] >= HV_X64_CPUID_MIN &&
- regs[0] <= HV_X64_CPUID_MAX &&
- !memcmp("Microsoft Hv", &regs[1], 12);
- }
- return (hyper_v_detected);
+ return (hv_high >= HV_X64_CPUID_MIN && hv_high <= HV_X64_CPUID_MAX);
}
/**
@@ -115,10 +87,7 @@ hv_vmbus_query_hypervisor_presence(void)
static int
hv_vmbus_get_hypervisor_version(void)
{
- unsigned int eax;
- unsigned int ebx;
- unsigned int ecx;
- unsigned int edx;
+ u_int regs[4];
unsigned int maxLeaf;
unsigned int op;
@@ -127,28 +96,16 @@ hv_vmbus_get_hypervisor_version(void)
* Viridian is present
* Query id and revision.
*/
- eax = 0;
- ebx = 0;
- ecx = 0;
- edx = 0;
op = HV_CPU_ID_FUNCTION_HV_VENDOR_AND_MAX_FUNCTION;
- do_cpuid_inline(op, &eax, &ebx, &ecx, &edx);
+ do_cpuid(op, regs);
- maxLeaf = eax;
- eax = 0;
- ebx = 0;
- ecx = 0;
- edx = 0;
+ maxLeaf = regs[0];
op = HV_CPU_ID_FUNCTION_HV_INTERFACE;
- do_cpuid_inline(op, &eax, &ebx, &ecx, &edx);
+ do_cpuid(op, regs);
if (maxLeaf >= HV_CPU_ID_FUNCTION_MS_HV_VERSION) {
- eax = 0;
- ebx = 0;
- ecx = 0;
- edx = 0;
op = HV_CPU_ID_FUNCTION_MS_HV_VERSION;
- do_cpuid_inline(op, &eax, &ebx, &ecx, &edx);
+ do_cpuid(op, regs);
}
return (maxLeaf);
}
@@ -255,6 +212,8 @@ hv_vmbus_init(void)
hv_vmbus_g_context.hypercall_page = virt_addr;
tc_init(&hv_timecounter); /* register virtual timecount */
+
+ hv_et_init();
return (0);
diff --git a/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c b/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
index 201f1c93e65b..6df466468170 100644
--- a/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
+++ b/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/module.h>
+#include <sys/proc.h>
#include <sys/sysctl.h>
#include <sys/syslog.h>
#include <sys/systm.h>
@@ -60,13 +61,15 @@ __FBSDID("$FreeBSD$");
#include "hv_vmbus_priv.h"
-
-#define VMBUS_IRQ 0x5
+#include <contrib/dev/acpica/include/acpi.h>
+#include "acpi_if.h"
static device_t vmbus_devp;
static int vmbus_inited;
static hv_setup_args setup_args; /* only CPU 0 supported at this time */
+static char *vmbus_ids[] = { "VMBUS", NULL };
+
/**
* @brief Software interrupt thread routine to handle channel messages from
* the hypervisor.
@@ -151,7 +154,7 @@ handled:
* message to process - an event or a channel message.
*/
static inline int
-hv_vmbus_isr(void *unused)
+hv_vmbus_isr(struct trapframe *frame)
{
int cpu;
hv_vmbus_message* msg;
@@ -191,41 +194,57 @@ hv_vmbus_isr(void *unused)
page_addr = hv_vmbus_g_context.syn_ic_msg_page[cpu];
msg = (hv_vmbus_message*) page_addr + HV_VMBUS_MESSAGE_SINT;
+ /* we call eventtimer process the message */
+ if (msg->header.message_type == HV_MESSAGE_TIMER_EXPIRED) {
+ msg->header.message_type = HV_MESSAGE_TYPE_NONE;
+
+ /*
+ * Make sure the write to message_type (ie set to
+ * HV_MESSAGE_TYPE_NONE) happens before we read the
+ * message_pending and EOMing. Otherwise, the EOMing will
+ * not deliver any more messages
+ * since there is no empty slot
+ */
+ wmb();
+
+ if (msg->header.message_flags.u.message_pending) {
+ /*
+ * This will cause message queue rescan to possibly
+ * deliver another msg from the hypervisor
+ */
+ wrmsr(HV_X64_MSR_EOM, 0);
+ }
+ hv_et_intr(frame);
+ return (FILTER_HANDLED);
+ }
+
if (msg->header.message_type != HV_MESSAGE_TYPE_NONE) {
swi_sched(hv_vmbus_g_context.msg_swintr[cpu], 0);
}
- return FILTER_HANDLED;
+ return (FILTER_HANDLED);
}
-#ifdef HV_DEBUG_INTR
-uint32_t hv_intr_count = 0;
-#endif
uint32_t hv_vmbus_swintr_event_cpu[MAXCPU];
-uint32_t hv_vmbus_intr_cpu[MAXCPU];
+u_long *hv_vmbus_intr_cpu[MAXCPU];
void
hv_vector_handler(struct trapframe *trap_frame)
{
-#ifdef HV_DEBUG_INTR
int cpu;
-#endif
/*
* Disable preemption.
*/
critical_enter();
-#ifdef HV_DEBUG_INTR
/*
* Do a little interrupt counting.
*/
cpu = PCPU_GET(cpuid);
- hv_vmbus_intr_cpu[cpu]++;
- hv_intr_count++;
-#endif
+ (*hv_vmbus_intr_cpu[cpu])++;
- hv_vmbus_isr(NULL);
+ hv_vmbus_isr(trap_frame);
/*
* Enable preemption.
@@ -350,25 +369,15 @@ hv_vmbus_child_device_unregister(struct hv_device *child_dev)
return(ret);
}
-static void
-vmbus_identify(driver_t *driver, device_t parent)
-{
- if (!hv_vmbus_query_hypervisor_presence())
- return;
-
- vm_guest = VM_GUEST_HV;
-
- BUS_ADD_CHILD(parent, 0, "vmbus", 0);
-}
-
static int
vmbus_probe(device_t dev) {
- if(bootverbose)
- device_printf(dev, "VMBUS: probe\n");
+ if (ACPI_ID_PROBE(device_get_parent(dev), dev, vmbus_ids) == NULL ||
+ device_get_unit(dev) != 0)
+ return (ENXIO);
device_set_desc(dev, "Vmbus Devices");
- return (BUS_PROBE_NOWILDCARD);
+ return (BUS_PROBE_DEFAULT);
}
#ifdef HYPERV
@@ -462,6 +471,7 @@ static int
vmbus_bus_init(void)
{
int i, j, n, ret;
+ char buf[MAXCOMLEN + 1];
if (vmbus_inited)
return (0);
@@ -498,13 +508,15 @@ vmbus_bus_init(void)
setup_args.vector = hv_vmbus_g_context.hv_cb_vector;
CPU_FOREACH(j) {
- hv_vmbus_intr_cpu[j] = 0;
hv_vmbus_swintr_event_cpu[j] = 0;
hv_vmbus_g_context.hv_event_intr_event[j] = NULL;
hv_vmbus_g_context.hv_msg_intr_event[j] = NULL;
hv_vmbus_g_context.event_swintr[j] = NULL;
hv_vmbus_g_context.msg_swintr[j] = NULL;
+ snprintf(buf, sizeof(buf), "cpu%d:hyperv", j);
+ intrcnt_add(buf, &hv_vmbus_intr_cpu[j]);
+
for (i = 0; i < 2; i++)
setup_args.page_buffers[2 * j + i] = NULL;
}
@@ -723,7 +735,6 @@ vmbus_modevent(module_t mod, int what, void *arg)
static device_method_t vmbus_methods[] = {
/** Device interface */
- DEVMETHOD(device_identify, vmbus_identify),
DEVMETHOD(device_probe, vmbus_probe),
DEVMETHOD(device_attach, vmbus_attach),
DEVMETHOD(device_detach, vmbus_detach),
@@ -745,8 +756,9 @@ static driver_t vmbus_driver = { driver_name, vmbus_methods,0, };
devclass_t vmbus_devclass;
-DRIVER_MODULE(vmbus, nexus, vmbus_driver, vmbus_devclass, vmbus_modevent, 0);
-MODULE_VERSION(vmbus,1);
+DRIVER_MODULE(vmbus, acpi, vmbus_driver, vmbus_devclass, vmbus_modevent, 0);
+MODULE_DEPEND(vmbus, acpi, 1, 1, 1);
+MODULE_VERSION(vmbus, 1);
/* We want to be started after SMP is initialized */
SYSINIT(vmb_init, SI_SUB_SMP + 1, SI_ORDER_FIRST, vmbus_init, NULL);
diff --git a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
index 0503d06aeb57..74fe8240bfd4 100644
--- a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
+++ b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
@@ -359,11 +359,6 @@ typedef struct {
struct sema control_sema;
} hv_vmbus_connection;
-/*
- * Declare the MSR used to identify the guest OS
- */
-#define HV_X64_MSR_GUEST_OS_ID 0x40000000
-
typedef union {
uint64_t as_uint64_t;
struct {
@@ -380,10 +375,6 @@ typedef union {
} u;
} hv_vmbus_x64_msr_guest_os_id_contents;
-/*
- * Declare the MSR used to setup pages used to communicate with the hypervisor
- */
-#define HV_X64_MSR_HYPERCALL 0x40000001
typedef union {
uint64_t as_uint64_t;
@@ -513,6 +504,22 @@ typedef union {
} hv_vmbus_synic_sint;
/*
+ * Timer configuration register.
+ */
+union hv_timer_config {
+ uint64_t as_uint64;
+ struct {
+ uint64_t enable:1;
+ uint64_t periodic:1;
+ uint64_t lazy:1;
+ uint64_t auto_enable:1;
+ uint64_t reserved_z0:12;
+ uint64_t sintx:4;
+ uint64_t reserved_z1:44;
+ };
+};
+
+/*
* Define syn_ic control register
*/
typedef union _hv_vmbus_synic_scontrol {
@@ -542,8 +549,21 @@ typedef union {
uint32_t flags32[HV_EVENT_FLAGS_DWORD_COUNT];
} hv_vmbus_synic_event_flags;
+#define HV_X64_CPUID_MIN (0x40000005)
+#define HV_X64_CPUID_MAX (0x4000ffff)
+
+/*
+ * Declare the MSR used to identify the guest OS
+ */
+#define HV_X64_MSR_GUEST_OS_ID (0x40000000)
+/*
+ * Declare the MSR used to setup pages used to communicate with the hypervisor
+ */
+#define HV_X64_MSR_HYPERCALL (0x40000001)
/* MSR used to provide vcpu index */
-#define HV_X64_MSR_VP_INDEX (0x40000002)
+#define HV_X64_MSR_VP_INDEX (0x40000002)
+
+#define HV_X64_MSR_TIME_REF_COUNT (0x40000020)
/*
* Define synthetic interrupt controller model specific registers
@@ -572,6 +592,18 @@ typedef union {
#define HV_X64_MSR_SINT15 (0x4000009F)
/*
+ * Synthetic Timer MSRs. Four timers per vcpu.
+ */
+#define HV_X64_MSR_STIMER0_CONFIG 0x400000B0
+#define HV_X64_MSR_STIMER0_COUNT 0x400000B1
+#define HV_X64_MSR_STIMER1_CONFIG 0x400000B2
+#define HV_X64_MSR_STIMER1_COUNT 0x400000B3
+#define HV_X64_MSR_STIMER2_CONFIG 0x400000B4
+#define HV_X64_MSR_STIMER2_COUNT 0x400000B5
+#define HV_X64_MSR_STIMER3_CONFIG 0x400000B6
+#define HV_X64_MSR_STIMER3_COUNT 0x400000B7
+
+/*
* Declare the various hypercall operations
*/
typedef enum {
@@ -678,6 +710,11 @@ int hv_vmbus_post_message(void *buffer, size_t buf_size);
int hv_vmbus_set_event(hv_vmbus_channel *channel);
void hv_vmbus_on_events(void *);
+/**
+ * Event Timer interfaces
+ */
+void hv_et_init(void);
+void hv_et_intr(struct trapframe*);
/*
* The guest OS needs to register the guest ID with the hypervisor.
diff --git a/sys/dev/ioat/ioat.c b/sys/dev/ioat/ioat.c
index 7f14c3ff40ec..956e8d1463f4 100644
--- a/sys/dev/ioat/ioat.c
+++ b/sys/dev/ioat/ioat.c
@@ -852,6 +852,8 @@ ioat_op_generic(struct ioat_softc *ioat, uint8_t op,
if ((flags & DMA_INT_EN) != 0)
hw_desc->u.control_generic.int_enable = 1;
+ if ((flags & DMA_FENCE) != 0)
+ hw_desc->u.control_generic.fence = 1;
hw_desc->size = size;
hw_desc->src_addr = src;
diff --git a/sys/dev/ioat/ioat.h b/sys/dev/ioat/ioat.h
index 64f97830a2d6..3b6e0946ac1e 100644
--- a/sys/dev/ioat/ioat.h
+++ b/sys/dev/ioat/ioat.h
@@ -46,7 +46,13 @@ __FBSDID("$FreeBSD$");
* descriptor without blocking.
*/
#define DMA_NO_WAIT 0x2
-#define DMA_ALL_FLAGS (DMA_INT_EN | DMA_NO_WAIT)
+/*
+ * Disallow prefetching the source of the following operation. Ordinarily, DMA
+ * operations can be pipelined on some hardware. E.g., operation 2's source
+ * may be prefetched before operation 1 completes.
+ */
+#define DMA_FENCE 0x4
+#define DMA_ALL_FLAGS (DMA_INT_EN | DMA_NO_WAIT | DMA_FENCE)
/*
* Hardware revision number. Different hardware revisions support different
diff --git a/sys/dev/sfxge/common/ef10_impl.h b/sys/dev/sfxge/common/ef10_impl.h
index 9b9f0aaf4b55..0c687ae1b452 100644
--- a/sys/dev/sfxge/common/ef10_impl.h
+++ b/sys/dev/sfxge/common/ef10_impl.h
@@ -45,6 +45,52 @@ extern "C" {
#define EF10_MAX_PIOBUF_NBUFS MEDFORD_PIOBUF_NBUFS
#endif
+extern __checkReturn efx_rc_t
+efx_mcdi_get_port_assignment(
+ __in efx_nic_t *enp,
+ __out uint32_t *portp);
+
+extern __checkReturn efx_rc_t
+efx_mcdi_get_port_modes(
+ __in efx_nic_t *enp,
+ __out uint32_t *modesp);
+
+extern __checkReturn efx_rc_t
+efx_mcdi_get_mac_address_pf(
+ __in efx_nic_t *enp,
+ __out_ecount_opt(6) uint8_t mac_addrp[6]);
+
+extern __checkReturn efx_rc_t
+efx_mcdi_get_mac_address_vf(
+ __in efx_nic_t *enp,
+ __out_ecount_opt(6) uint8_t mac_addrp[6]);
+
+extern __checkReturn efx_rc_t
+efx_mcdi_get_clock(
+ __in efx_nic_t *enp,
+ __out uint32_t *sys_freqp);
+
+extern __checkReturn efx_rc_t
+efx_mcdi_get_vector_cfg(
+ __in efx_nic_t *enp,
+ __out_opt uint32_t *vec_basep,
+ __out_opt uint32_t *pf_nvecp,
+ __out_opt uint32_t *vf_nvecp);
+
+extern __checkReturn efx_rc_t
+ef10_get_datapath_caps(
+ __in efx_nic_t *enp);
+
+extern __checkReturn efx_rc_t
+ef10_get_privilege_mask(
+ __in efx_nic_t *enp,
+ __out uint32_t *maskp);
+
+extern __checkReturn efx_rc_t
+ef10_external_port_mapping(
+ __in efx_nic_t *enp,
+ __in uint32_t port,
+ __out uint8_t *external_portp);
#ifdef __cplusplus
diff --git a/sys/dev/sfxge/common/efsys.h b/sys/dev/sfxge/common/efsys.h
index 4d72e28903e3..c6729cab875d 100644
--- a/sys/dev/sfxge/common/efsys.h
+++ b/sys/dev/sfxge/common/efsys.h
@@ -293,6 +293,8 @@ sfxge_map_mbuf_fast(bus_dma_tag_t tag, bus_dmamap_t map,
#define EFSYS_OPT_DECODE_INTR_FATAL 1
+#define EFSYS_OPT_LICENSING 0
+
/* ID */
typedef struct __efsys_identifier_s efsys_identifier_t;
diff --git a/sys/dev/sfxge/common/efx.h b/sys/dev/sfxge/common/efx.h
index 0483c9a7c4b4..fcf9fc522f01 100644
--- a/sys/dev/sfxge/common/efx.h
+++ b/sys/dev/sfxge/common/efx.h
@@ -1071,6 +1071,7 @@ efx_bist_stop(
#define EFX_FEATURE_TX_SRC_FILTERS 0x00000400
#define EFX_FEATURE_PIO_BUFFERS 0x00000800
#define EFX_FEATURE_FW_ASSISTED_TSO 0x00001000
+#define EFX_FEATURE_FW_ASSISTED_TSO_V2 0x00002000
typedef struct efx_nic_cfg_s {
uint32_t enc_board_type;
@@ -1152,6 +1153,7 @@ typedef struct efx_nic_cfg_s {
*/
uint32_t enc_tx_tso_tcp_header_offset_limit;
boolean_t enc_fw_assisted_tso_enabled;
+ boolean_t enc_fw_assisted_tso_v2_enabled;
boolean_t enc_hw_tx_insert_vlan_enabled;
/* Datapath firmware vadapter/vport/vswitch support */
boolean_t enc_datapath_cap_evb;
@@ -1160,6 +1162,8 @@ typedef struct efx_nic_cfg_s {
/* External port identifier */
uint8_t enc_external_port;
uint32_t enc_mcdi_max_payload_length;
+ /* VPD may be per-PF or global */
+ boolean_t enc_vpd_is_global;
} efx_nic_cfg_t;
#define EFX_PCI_FUNCTION_IS_PF(_encp) ((_encp)->enc_vf == 0xffff)
@@ -1315,6 +1319,7 @@ typedef enum efx_nvram_type_e {
EFX_NVRAM_CPLD,
EFX_NVRAM_FPGA_BACKUP,
EFX_NVRAM_DYNAMIC_CFG,
+ EFX_NVRAM_LICENSE,
EFX_NVRAM_NTYPES,
} efx_nvram_type_t;
@@ -2002,6 +2007,7 @@ efx_tx_fini(
#define EFX_TXQ_CKSUM_IPV4 0x0001
#define EFX_TXQ_CKSUM_TCPUDP 0x0002
+#define EFX_TXQ_FATSOV2 0x0004
extern __checkReturn efx_rc_t
efx_tx_qcreate(
@@ -2089,6 +2095,21 @@ efx_tx_qdesc_tso_create(
__in uint8_t tcp_flags,
__out efx_desc_t *edp);
+/* Number of FATSOv2 option descriptors */
+#define EFX_TX_FATSOV2_OPT_NDESCS 2
+
+/* Maximum number of DMA segments per TSO packet (not superframe) */
+#define EFX_TX_FATSOV2_DMA_SEGS_PER_PKT_MAX 24
+
+extern void
+efx_tx_qdesc_tso2_create(
+ __in efx_txq_t *etp,
+ __in uint16_t ipv4_id,
+ __in uint32_t tcp_seq,
+ __in uint16_t tcp_mss,
+ __out_ecount(count) efx_desc_t *edp,
+ __in int count);
+
extern void
efx_tx_qdesc_vlantci_create(
__in efx_txq_t *etp,
@@ -2291,6 +2312,57 @@ efx_hash_bytes(
__in size_t length,
__in uint32_t init);
+#if EFSYS_OPT_LICENSING
+
+/* LICENSING */
+
+typedef struct efx_key_stats_s {
+ uint32_t eks_valid;
+ uint32_t eks_invalid;
+ uint32_t eks_blacklisted;
+ uint32_t eks_unverifiable;
+ uint32_t eks_wrong_node;
+ uint32_t eks_licensed_apps_lo;
+ uint32_t eks_licensed_apps_hi;
+ uint32_t eks_licensed_features_lo;
+ uint32_t eks_licensed_features_hi;
+} efx_key_stats_t;
+
+extern __checkReturn efx_rc_t
+efx_lic_init(
+ __in efx_nic_t *enp);
+
+extern void
+efx_lic_fini(
+ __in efx_nic_t *enp);
+
+extern __checkReturn efx_rc_t
+efx_lic_update_licenses(
+ __in efx_nic_t *enp);
+
+extern __checkReturn efx_rc_t
+efx_lic_get_key_stats(
+ __in efx_nic_t *enp,
+ __out efx_key_stats_t *ksp);
+
+extern __checkReturn efx_rc_t
+efx_lic_app_state(
+ __in efx_nic_t *enp,
+ __in uint64_t app_id,
+ __out boolean_t *licensedp);
+
+extern __checkReturn efx_rc_t
+efx_lic_get_id(
+ __in efx_nic_t *enp,
+ __in size_t buffer_size,
+ __out uint32_t *typep,
+ __out size_t *lengthp,
+ __out_opt uint8_t *bufferp);
+
+
+#endif /* EFSYS_OPT_LICENSING */
+
+
#ifdef __cplusplus
}
diff --git a/sys/dev/sfxge/common/efx_check.h b/sys/dev/sfxge/common/efx_check.h
index 199fab013f38..d6b7cf42eef8 100644
--- a/sys/dev/sfxge/common/efx_check.h
+++ b/sys/dev/sfxge/common/efx_check.h
@@ -401,4 +401,15 @@
# endif
#endif /* EFSYS_OPT_BIST */
+/* Support MCDI licensing API */
+#if EFSYS_OPT_LICENSING
+# if !EFSYS_OPT_MCDI
+# error "LICENSING requires MCDI"
+# endif
+# if !EFSYS_HAS_UINT64
+# error "LICENSING requires UINT64"
+# endif
+#endif /* EFSYS_OPT_LICENSING */
+
+
#endif /* _SYS_EFX_CHECK_H */
diff --git a/sys/dev/sfxge/common/efx_impl.h b/sys/dev/sfxge/common/efx_impl.h
index 5397ffebbbb7..6f9df035aa3a 100644
--- a/sys/dev/sfxge/common/efx_impl.h
+++ b/sys/dev/sfxge/common/efx_impl.h
@@ -84,6 +84,7 @@ extern "C" {
#define EFX_MOD_WOL 0x00000800
#define EFX_MOD_FILTER 0x00001000
#define EFX_MOD_PKTFILTER 0x00002000
+#define EFX_MOD_LIC 0x00004000
#define EFX_RESET_MAC 0x00000001
#define EFX_RESET_PHY 0x00000002
@@ -146,6 +147,9 @@ typedef struct efx_tx_ops_s {
void (*etxo_qdesc_tso_create)(efx_txq_t *, uint16_t,
uint32_t, uint8_t,
efx_desc_t *);
+ void (*etxo_qdesc_tso2_create)(efx_txq_t *, uint16_t,
+ uint32_t, uint16_t,
+ efx_desc_t *, int);
void (*etxo_qdesc_vlantci_create)(efx_txq_t *, uint16_t,
efx_desc_t *);
#if EFSYS_OPT_QSTATS
@@ -358,6 +362,7 @@ typedef struct efx_intr_s {
typedef struct efx_nic_ops_s {
efx_rc_t (*eno_probe)(efx_nic_t *);
+ efx_rc_t (*eno_board_cfg)(efx_nic_t *);
efx_rc_t (*eno_set_drv_limits)(efx_nic_t *, efx_drv_limits_t*);
efx_rc_t (*eno_reset)(efx_nic_t *);
efx_rc_t (*eno_init)(efx_nic_t *);
@@ -456,9 +461,8 @@ falconsiena_filter_tbl_clear(
typedef struct efx_mcdi_ops_s {
efx_rc_t (*emco_init)(efx_nic_t *, const efx_mcdi_transport_t *);
- void (*emco_request_copyin)(efx_nic_t *, efx_mcdi_req_t *,
- unsigned int, boolean_t, boolean_t);
- void (*emco_request_copyout)(efx_nic_t *, efx_mcdi_req_t *);
+ void (*emco_send_request)(efx_nic_t *, void *, size_t,
+ void *, size_t);
efx_rc_t (*emco_poll_reboot)(efx_nic_t *);
boolean_t (*emco_poll_response)(efx_nic_t *);
void (*emco_read_response)(efx_nic_t *, void *, size_t, size_t);
@@ -479,10 +483,8 @@ typedef struct efx_nvram_ops_s {
#if EFSYS_OPT_DIAG
efx_rc_t (*envo_test)(efx_nic_t *);
#endif /* EFSYS_OPT_DIAG */
- efx_rc_t (*envo_size)(efx_nic_t *, efx_nvram_type_t, size_t *);
efx_rc_t (*envo_get_version)(efx_nic_t *, efx_nvram_type_t,
uint32_t *, uint16_t *);
- efx_rc_t (*envo_rw_start)(efx_nic_t *, efx_nvram_type_t, size_t *);
efx_rc_t (*envo_read_chunk)(efx_nic_t *, efx_nvram_type_t,
unsigned int, caddr_t, size_t);
efx_rc_t (*envo_erase)(efx_nic_t *, efx_nvram_type_t);
@@ -494,6 +496,8 @@ typedef struct efx_nvram_ops_s {
efx_rc_t (*envo_type_to_partn)(efx_nic_t *, efx_nvram_type_t,
uint32_t *);
+ efx_rc_t (*envo_partn_size)(efx_nic_t *, uint32_t, size_t *);
+ efx_rc_t (*envo_partn_rw_start)(efx_nic_t *, uint32_t, size_t *);
} efx_nvram_ops_t;
#endif /* EFSYS_OPT_NVRAM */
@@ -587,6 +591,18 @@ efx_mcdi_nvram_test(
#endif /* EFSYS_OPT_VPD || EFSYS_OPT_NVRAM */
+#if EFSYS_OPT_LICENSING
+
+typedef struct efx_lic_ops_s {
+ efx_rc_t (*elo_update_licenses)(efx_nic_t *);
+ efx_rc_t (*elo_get_key_stats)(efx_nic_t *, efx_key_stats_t *);
+ efx_rc_t (*elo_app_state)(efx_nic_t *, uint64_t, boolean_t *);
+ efx_rc_t (*elo_get_id)(efx_nic_t *, size_t, uint32_t *,
+ size_t *, uint8_t *);
+} efx_lic_ops_t;
+
+#endif
+
typedef struct efx_drv_cfg_s {
uint32_t edc_min_vi_count;
uint32_t edc_max_vi_count;
@@ -636,6 +652,9 @@ struct efx_nic_s {
uint32_t en_rss_context;
#endif /* EFSYS_OPT_RX_SCALE */
uint32_t en_vport_id;
+#if EFSYS_OPT_LICENSING
+ efx_lic_ops_t *en_elop;
+#endif
union {
#if EFSYS_OPT_FALCON
struct {
diff --git a/sys/dev/sfxge/common/efx_lic.c b/sys/dev/sfxge/common/efx_lic.c
new file mode 100644
index 000000000000..33c8aba6abfc
--- /dev/null
+++ b/sys/dev/sfxge/common/efx_lic.c
@@ -0,0 +1,792 @@
+/*-
+ * Copyright (c) 2009-2015 Solarflare Communications Inc.
+ * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are
+ * those of the authors and should not be interpreted as representing official
+ * policies, either expressed or implied, of the FreeBSD Project.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "efx.h"
+#include "efx_impl.h"
+
+#if EFSYS_OPT_LICENSING
+
+#if EFSYS_OPT_SIENA
+
+static __checkReturn efx_rc_t
+efx_mcdi_fc_license_update_license(
+ __in efx_nic_t *enp);
+
+static __checkReturn efx_rc_t
+efx_mcdi_fc_license_get_key_stats(
+ __in efx_nic_t *enp,
+ __out efx_key_stats_t *eksp);
+
+static efx_lic_ops_t __efx_lic_v1_ops = {
+ efx_mcdi_fc_license_update_license, /* elo_update_licenses */
+ efx_mcdi_fc_license_get_key_stats, /* elo_get_key_stats */
+ NULL, /* elo_app_state */
+ NULL, /* elo_get_id */
+};
+
+#endif /* EFSYS_OPT_SIENA */
+
+#if EFSYS_OPT_HUNTINGTON
+
+static __checkReturn efx_rc_t
+efx_mcdi_licensing_update_licenses(
+ __in efx_nic_t *enp);
+
+static __checkReturn efx_rc_t
+efx_mcdi_licensing_get_key_stats(
+ __in efx_nic_t *enp,
+ __out efx_key_stats_t *eksp);
+
+static __checkReturn efx_rc_t
+efx_mcdi_licensed_app_state(
+ __in efx_nic_t *enp,
+ __in uint64_t app_id,
+ __out boolean_t *licensedp);
+
+static efx_lic_ops_t __efx_lic_v2_ops = {
+ efx_mcdi_licensing_update_licenses, /* elo_update_licenses */
+ efx_mcdi_licensing_get_key_stats, /* elo_get_key_stats */
+ efx_mcdi_licensed_app_state, /* elo_app_state */
+ NULL, /* elo_get_id */
+};
+
+#endif /* EFSYS_OPT_HUNTINGTON */
+
+#if EFSYS_OPT_MEDFORD
+
+static __checkReturn efx_rc_t
+efx_mcdi_licensing_v3_update_licenses(
+ __in efx_nic_t *enp);
+
+static __checkReturn efx_rc_t
+efx_mcdi_licensing_v3_report_license(
+ __in efx_nic_t *enp,
+ __out efx_key_stats_t *eksp);
+
+static __checkReturn efx_rc_t
+efx_mcdi_licensing_v3_app_state(
+ __in efx_nic_t *enp,
+ __in uint64_t app_id,
+ __out boolean_t *licensedp);
+
+static __checkReturn efx_rc_t
+efx_mcdi_licensing_v3_get_id(
+ __in efx_nic_t *enp,
+ __in size_t buffer_size,
+ __out uint32_t *typep,
+ __out size_t *lengthp,
+ __out_bcount_part_opt(buffer_size, *lengthp)
+ uint8_t *bufferp);
+
+static efx_lic_ops_t __efx_lic_v3_ops = {
+ efx_mcdi_licensing_v3_update_licenses, /* elo_update_licenses */
+ efx_mcdi_licensing_v3_report_license, /* elo_get_key_stats */
+ efx_mcdi_licensing_v3_app_state, /* elo_app_state */
+ efx_mcdi_licensing_v3_get_id, /* elo_get_id */
+};
+
+#endif /* EFSYS_OPT_MEDFORD */
+
+
+/* V1 Licensing - used in Siena Modena only */
+
+#if EFSYS_OPT_SIENA
+
+static __checkReturn efx_rc_t
+efx_mcdi_fc_license_update_license(
+ __in efx_nic_t *enp)
+{
+ efx_mcdi_req_t req;
+ uint8_t payload[MC_CMD_FC_IN_LICENSE_LEN];
+ efx_rc_t rc;
+
+ EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
+
+ (void) memset(payload, 0, sizeof (payload));
+ req.emr_cmd = MC_CMD_FC_OP_LICENSE;
+ req.emr_in_buf = payload;
+ req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
+ req.emr_out_buf = payload;
+ req.emr_out_length = 0;
+
+ MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
+ MC_CMD_FC_IN_LICENSE_UPDATE_LICENSE);
+
+ efx_mcdi_execute(enp, &req);
+
+ if (req.emr_rc != 0) {
+ rc = req.emr_rc;
+ goto fail1;
+ }
+
+ if (req.emr_out_length_used != 0) {
+ rc = EIO;
+ goto fail2;
+ }
+
+ return (0);
+
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
+
+static __checkReturn efx_rc_t
+efx_mcdi_fc_license_get_key_stats(
+ __in efx_nic_t *enp,
+ __out efx_key_stats_t *eksp)
+{
+ efx_mcdi_req_t req;
+ uint8_t payload[MAX(MC_CMD_FC_IN_LICENSE_LEN,
+ MC_CMD_FC_OUT_LICENSE_LEN)];
+ efx_rc_t rc;
+
+ EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
+
+ (void) memset(payload, 0, sizeof (payload));
+ req.emr_cmd = MC_CMD_FC_OP_LICENSE;
+ req.emr_in_buf = payload;
+ req.emr_in_length = MC_CMD_FC_IN_LICENSE_LEN;
+ req.emr_out_buf = payload;
+ req.emr_out_length = MC_CMD_FC_OUT_LICENSE_LEN;
+
+ MCDI_IN_SET_DWORD(req, FC_IN_LICENSE_OP,
+ MC_CMD_FC_IN_LICENSE_GET_KEY_STATS);
+
+ efx_mcdi_execute(enp, &req);
+
+ if (req.emr_rc != 0) {
+ rc = req.emr_rc;
+ goto fail1;
+ }
+
+ if (req.emr_out_length_used < MC_CMD_FC_OUT_LICENSE_LEN) {
+ rc = EMSGSIZE;
+ goto fail2;
+ }
+
+ eksp->eks_valid =
+ MCDI_OUT_DWORD(req, FC_OUT_LICENSE_VALID_KEYS);
+ eksp->eks_invalid =
+ MCDI_OUT_DWORD(req, FC_OUT_LICENSE_INVALID_KEYS);
+ eksp->eks_blacklisted =
+ MCDI_OUT_DWORD(req, FC_OUT_LICENSE_BLACKLISTED_KEYS);
+ eksp->eks_unverifiable = 0;
+ eksp->eks_wrong_node = 0;
+ eksp->eks_licensed_apps_lo = 0;
+ eksp->eks_licensed_apps_hi = 0;
+ eksp->eks_licensed_features_lo = 0;
+ eksp->eks_licensed_features_hi = 0;
+
+ return (0);
+
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
+
+#endif /* EFSYS_OPT_SIENA */
+
+/* V2 Licensing - used by Huntington family only. See SF-113611-TC */
+
+#if EFSYS_OPT_HUNTINGTON
+
+static __checkReturn efx_rc_t
+efx_mcdi_licensed_app_state(
+ __in efx_nic_t *enp,
+ __in uint64_t app_id,
+ __out boolean_t *licensedp)
+{
+ efx_mcdi_req_t req;
+ uint8_t payload[MAX(MC_CMD_GET_LICENSED_APP_STATE_IN_LEN,
+ MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN)];
+ uint32_t app_state;
+ efx_rc_t rc;
+
+ EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
+
+ /* V2 licensing supports 32bit app id only */
+ if ((app_id >> 32) != 0) {
+ rc = EINVAL;
+ goto fail1;
+ }
+
+ (void) memset(payload, 0, sizeof (payload));
+ req.emr_cmd = MC_CMD_GET_LICENSED_APP_STATE;
+ req.emr_in_buf = payload;
+ req.emr_in_length = MC_CMD_GET_LICENSED_APP_STATE_IN_LEN;
+ req.emr_out_buf = payload;
+ req.emr_out_length = MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN;
+
+ MCDI_IN_SET_DWORD(req, GET_LICENSED_APP_STATE_IN_APP_ID,
+ app_id & 0xffffffff);
+
+ efx_mcdi_execute(enp, &req);
+
+ if (req.emr_rc != 0) {
+ rc = req.emr_rc;
+ goto fail2;
+ }
+
+ if (req.emr_out_length_used < MC_CMD_GET_LICENSED_APP_STATE_OUT_LEN) {
+ rc = EMSGSIZE;
+ goto fail3;
+ }
+
+ app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_APP_STATE_OUT_STATE));
+ if (app_state != MC_CMD_GET_LICENSED_APP_STATE_OUT_NOT_LICENSED) {
+ *licensedp = B_TRUE;
+ } else {
+ *licensedp = B_FALSE;
+ }
+
+ return (0);
+
+fail3:
+ EFSYS_PROBE(fail3);
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
+
+static __checkReturn efx_rc_t
+efx_mcdi_licensing_update_licenses(
+ __in efx_nic_t *enp)
+{
+ efx_mcdi_req_t req;
+ uint8_t payload[MC_CMD_LICENSING_IN_LEN];
+ efx_rc_t rc;
+
+ EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
+
+ (void) memset(payload, 0, sizeof (payload));
+ req.emr_cmd = MC_CMD_LICENSING;
+ req.emr_in_buf = payload;
+ req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
+ req.emr_out_buf = payload;
+ req.emr_out_length = 0;
+
+ MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
+ MC_CMD_LICENSING_IN_OP_UPDATE_LICENSE);
+
+ efx_mcdi_execute(enp, &req);
+
+ if (req.emr_rc != 0) {
+ rc = req.emr_rc;
+ goto fail1;
+ }
+
+ if (req.emr_out_length_used != 0) {
+ rc = EIO;
+ goto fail2;
+ }
+
+ return (0);
+
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
+
+static __checkReturn efx_rc_t
+efx_mcdi_licensing_get_key_stats(
+ __in efx_nic_t *enp,
+ __out efx_key_stats_t *eksp)
+{
+ efx_mcdi_req_t req;
+ uint8_t payload[MAX(MC_CMD_LICENSING_IN_LEN,
+ MC_CMD_LICENSING_OUT_LEN)];
+ efx_rc_t rc;
+
+ EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
+
+ (void) memset(payload, 0, sizeof (payload));
+ req.emr_cmd = MC_CMD_LICENSING;
+ req.emr_in_buf = payload;
+ req.emr_in_length = MC_CMD_LICENSING_IN_LEN;
+ req.emr_out_buf = payload;
+ req.emr_out_length = MC_CMD_LICENSING_OUT_LEN;
+
+ MCDI_IN_SET_DWORD(req, LICENSING_IN_OP,
+ MC_CMD_LICENSING_IN_OP_GET_KEY_STATS);
+
+ efx_mcdi_execute(enp, &req);
+
+ if (req.emr_rc != 0) {
+ rc = req.emr_rc;
+ goto fail1;
+ }
+
+ if (req.emr_out_length_used < MC_CMD_LICENSING_OUT_LEN) {
+ rc = EMSGSIZE;
+ goto fail2;
+ }
+
+ eksp->eks_valid =
+ MCDI_OUT_DWORD(req, LICENSING_OUT_VALID_APP_KEYS);
+ eksp->eks_invalid =
+ MCDI_OUT_DWORD(req, LICENSING_OUT_INVALID_APP_KEYS);
+ eksp->eks_blacklisted =
+ MCDI_OUT_DWORD(req, LICENSING_OUT_BLACKLISTED_APP_KEYS);
+ eksp->eks_unverifiable =
+ MCDI_OUT_DWORD(req, LICENSING_OUT_UNVERIFIABLE_APP_KEYS);
+ eksp->eks_wrong_node =
+ MCDI_OUT_DWORD(req, LICENSING_OUT_WRONG_NODE_APP_KEYS);
+ eksp->eks_licensed_apps_lo = 0;
+ eksp->eks_licensed_apps_hi = 0;
+ eksp->eks_licensed_features_lo = 0;
+ eksp->eks_licensed_features_hi = 0;
+
+ return (0);
+
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
+
+#endif /* EFSYS_OPT_HUNTINGTON */
+
+/* V3 Licensing - used starting from Medford family. See SF-114884-SW */
+
+#if EFSYS_OPT_MEDFORD
+
+static __checkReturn efx_rc_t
+efx_mcdi_licensing_v3_update_licenses(
+ __in efx_nic_t *enp)
+{
+ efx_mcdi_req_t req;
+ uint8_t payload[MC_CMD_LICENSING_V3_IN_LEN];
+ efx_rc_t rc;
+
+ EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
+
+ (void) memset(payload, 0, sizeof (payload));
+ req.emr_cmd = MC_CMD_LICENSING_V3;
+ req.emr_in_buf = payload;
+ req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
+ req.emr_out_buf = NULL;
+ req.emr_out_length = 0;
+
+ MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
+ MC_CMD_LICENSING_V3_IN_OP_UPDATE_LICENSE);
+
+ efx_mcdi_execute(enp, &req);
+
+ if (req.emr_rc != 0) {
+ rc = req.emr_rc;
+ goto fail1;
+ }
+
+ return (0);
+
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
+
+static __checkReturn efx_rc_t
+efx_mcdi_licensing_v3_report_license(
+ __in efx_nic_t *enp,
+ __out efx_key_stats_t *eksp)
+{
+ efx_mcdi_req_t req;
+ uint8_t payload[MAX(MC_CMD_LICENSING_V3_IN_LEN,
+ MC_CMD_LICENSING_V3_OUT_LEN)];
+ efx_rc_t rc;
+
+ EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
+
+ (void) memset(payload, 0, sizeof (payload));
+ req.emr_cmd = MC_CMD_LICENSING_V3;
+ req.emr_in_buf = payload;
+ req.emr_in_length = MC_CMD_LICENSING_V3_IN_LEN;
+ req.emr_out_buf = payload;
+ req.emr_out_length = MC_CMD_LICENSING_V3_OUT_LEN;
+
+ MCDI_IN_SET_DWORD(req, LICENSING_V3_IN_OP,
+ MC_CMD_LICENSING_V3_IN_OP_REPORT_LICENSE);
+
+ efx_mcdi_execute(enp, &req);
+
+ if (req.emr_rc != 0) {
+ rc = req.emr_rc;
+ goto fail1;
+ }
+
+ if (req.emr_out_length_used < MC_CMD_LICENSING_V3_OUT_LEN) {
+ rc = EMSGSIZE;
+ goto fail2;
+ }
+
+ eksp->eks_valid =
+ MCDI_OUT_DWORD(req, LICENSING_V3_OUT_VALID_KEYS);
+ eksp->eks_invalid =
+ MCDI_OUT_DWORD(req, LICENSING_V3_OUT_INVALID_KEYS);
+ eksp->eks_blacklisted = 0;
+ eksp->eks_unverifiable =
+ MCDI_OUT_DWORD(req, LICENSING_V3_OUT_UNVERIFIABLE_KEYS);
+ eksp->eks_wrong_node =
+ MCDI_OUT_DWORD(req, LICENSING_V3_OUT_WRONG_NODE_KEYS);
+ eksp->eks_licensed_apps_lo =
+ MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_LO);
+ eksp->eks_licensed_apps_hi =
+ MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_APPS_HI);
+ eksp->eks_licensed_features_lo =
+ MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_LO);
+ eksp->eks_licensed_features_hi =
+ MCDI_OUT_DWORD(req, LICENSING_V3_OUT_LICENSED_FEATURES_HI);
+
+ return (0);
+
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
+
+static __checkReturn efx_rc_t
+efx_mcdi_licensing_v3_app_state(
+ __in efx_nic_t *enp,
+ __in uint64_t app_id,
+ __out boolean_t *licensedp)
+{
+ efx_mcdi_req_t req;
+ uint8_t payload[MAX(MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN,
+ MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN)];
+ uint32_t app_state;
+ efx_rc_t rc;
+
+ EFSYS_ASSERT(enp->en_family == EFX_FAMILY_MEDFORD);
+
+ (void) memset(payload, 0, sizeof (payload));
+ req.emr_cmd = MC_CMD_GET_LICENSED_V3_APP_STATE;
+ req.emr_in_buf = payload;
+ req.emr_in_length = MC_CMD_GET_LICENSED_V3_APP_STATE_IN_LEN;
+ req.emr_out_buf = payload;
+ req.emr_out_length = MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN;
+
+ MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_LO,
+ app_id & 0xffffffff);
+ MCDI_IN_SET_DWORD(req, GET_LICENSED_V3_APP_STATE_IN_APP_ID_HI,
+ app_id >> 32);
+
+ efx_mcdi_execute(enp, &req);
+
+ if (req.emr_rc != 0) {
+ rc = req.emr_rc;
+ goto fail1;
+ }
+
+ if (req.emr_out_length_used < MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_LEN) {
+ rc = EMSGSIZE;
+ goto fail2;
+ }
+
+ app_state = (MCDI_OUT_DWORD(req, GET_LICENSED_V3_APP_STATE_OUT_STATE));
+ if (app_state != MC_CMD_GET_LICENSED_V3_APP_STATE_OUT_NOT_LICENSED) {
+ *licensedp = B_TRUE;
+ } else {
+ *licensedp = B_FALSE;
+ }
+
+ return (0);
+
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
+
+static __checkReturn efx_rc_t
+efx_mcdi_licensing_v3_get_id(
+ __in efx_nic_t *enp,
+ __in size_t buffer_size,
+ __out uint32_t *typep,
+ __out size_t *lengthp,
+ __out_bcount_part_opt(buffer_size, *lengthp)
+ uint8_t *bufferp)
+{
+ efx_mcdi_req_t req;
+ uint8_t payload[MAX(MC_CMD_LICENSING_GET_ID_V3_IN_LEN,
+ MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN)];
+ efx_rc_t rc;
+
+ req.emr_cmd = MC_CMD_LICENSING_GET_ID_V3;
+
+ if (bufferp == NULL) {
+ /* Request id type and length only */
+ req.emr_in_buf = bufferp;
+ req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
+ req.emr_out_buf = bufferp;
+ req.emr_out_length = MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
+ (void) memset(payload, 0, sizeof (payload));
+ } else {
+ /* Request full buffer */
+ req.emr_in_buf = bufferp;
+ req.emr_in_length = MC_CMD_LICENSING_GET_ID_V3_IN_LEN;
+ req.emr_out_buf = bufferp;
+ req.emr_out_length = MIN(buffer_size, MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN);
+ (void) memset(bufferp, 0, req.emr_out_length);
+ }
+
+ efx_mcdi_execute(enp, &req);
+
+ if (req.emr_rc != 0) {
+ rc = req.emr_rc;
+ goto fail1;
+ }
+
+ if (req.emr_out_length_used < MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN) {
+ rc = EMSGSIZE;
+ goto fail2;
+ }
+
+ *typep = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_TYPE);
+ *lengthp = MCDI_OUT_DWORD(req, LICENSING_GET_ID_V3_OUT_LICENSE_ID_LENGTH);
+
+ if (bufferp == NULL) {
+ /* modify length requirements to indicate to caller the extra buffering
+ ** needed to read the complete output.
+ */
+ *lengthp += MC_CMD_LICENSING_GET_ID_V3_OUT_LENMIN;
+ } else {
+ /* Shift ID down to start of buffer */
+ memmove(bufferp,
+ bufferp+MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST,
+ *lengthp);
+ memset(bufferp+(*lengthp), 0, MC_CMD_LICENSING_GET_ID_V3_OUT_LICENSE_ID_OFST);
+ }
+
+ return (0);
+
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
+
+
+#endif /* EFSYS_OPT_MEDFORD */
+
+ __checkReturn efx_rc_t
+efx_lic_init(
+ __in efx_nic_t *enp)
+{
+ efx_lic_ops_t *elop;
+ efx_rc_t rc;
+
+ EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+ EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+ EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_LIC));
+
+ switch (enp->en_family) {
+
+#if EFSYS_OPT_SIENA
+ case EFX_FAMILY_SIENA:
+ elop = (efx_lic_ops_t *)&__efx_lic_v1_ops;
+ break;
+#endif /* EFSYS_OPT_SIENA */
+
+#if EFSYS_OPT_HUNTINGTON
+ case EFX_FAMILY_HUNTINGTON:
+ elop = (efx_lic_ops_t *)&__efx_lic_v2_ops;
+ break;
+#endif /* EFSYS_OPT_HUNTINGTON */
+
+#if EFSYS_OPT_MEDFORD
+ case EFX_FAMILY_MEDFORD:
+ elop = (efx_lic_ops_t *)&__efx_lic_v3_ops;
+ break;
+#endif /* EFSYS_OPT_MEDFORD */
+
+ default:
+ EFSYS_ASSERT(0);
+ rc = ENOTSUP;
+ goto fail1;
+ }
+
+ enp->en_elop = elop;
+ enp->en_mod_flags |= EFX_MOD_LIC;
+
+ return (0);
+
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
+
+ void
+efx_lic_fini(
+ __in efx_nic_t *enp)
+{
+ efx_lic_ops_t *elop = enp->en_elop;
+
+ EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+ EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
+ EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
+
+ enp->en_elop = NULL;
+ enp->en_mod_flags &= ~EFX_MOD_LIC;
+}
+
+
+ __checkReturn efx_rc_t
+efx_lic_update_licenses(
+ __in efx_nic_t *enp)
+{
+ efx_lic_ops_t *elop = enp->en_elop;
+ efx_rc_t rc;
+
+ EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+ EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
+
+ if ((rc = elop->elo_update_licenses(enp)) != 0)
+ goto fail1;
+
+ return (0);
+
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
+
+ __checkReturn efx_rc_t
+efx_lic_get_key_stats(
+ __in efx_nic_t *enp,
+ __out efx_key_stats_t *eksp)
+{
+ efx_lic_ops_t *elop = enp->en_elop;
+ efx_rc_t rc;
+
+ EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+ EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
+
+ if ((rc = elop->elo_get_key_stats(enp, eksp)) != 0)
+ goto fail1;
+
+ return (0);
+
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
+
+ __checkReturn efx_rc_t
+efx_lic_app_state(
+ __in efx_nic_t *enp,
+ __in uint64_t app_id,
+ __out boolean_t *licensedp)
+{
+ efx_lic_ops_t *elop = enp->en_elop;
+ efx_rc_t rc;
+
+ EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+ EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
+
+ if (elop->elo_app_state == NULL) {
+ rc = ENOTSUP;
+ goto fail1;
+ }
+ if ((rc = elop->elo_app_state(enp, app_id, licensedp)) != 0)
+ goto fail2;
+
+ return (0);
+
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
+
+ __checkReturn efx_rc_t
+efx_lic_get_id(
+ __in efx_nic_t *enp,
+ __in size_t buffer_size,
+ __out uint32_t *typep,
+ __out size_t *lengthp,
+ __out_opt uint8_t *bufferp
+ )
+{
+ efx_lic_ops_t *elop = enp->en_elop;
+ efx_rc_t rc;
+
+ EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
+ EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_LIC);
+
+ if (elop->elo_get_id == NULL) {
+ rc = ENOTSUP;
+ goto fail1;
+ }
+
+ if ((rc = elop->elo_get_id(enp, buffer_size, typep,
+ lengthp, bufferp)) != 0)
+ goto fail2;
+
+ return (0);
+
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
+
+#endif /* EFSYS_OPT_LICENSING */
diff --git a/sys/dev/sfxge/common/efx_mcdi.c b/sys/dev/sfxge/common/efx_mcdi.c
index 07224c71d8b1..9f7a9ffedd8c 100644
--- a/sys/dev/sfxge/common/efx_mcdi.c
+++ b/sys/dev/sfxge/common/efx_mcdi.c
@@ -36,13 +36,32 @@ __FBSDID("$FreeBSD$");
#if EFSYS_OPT_MCDI
+/*
+ * There are three versions of the MCDI interface:
+ * - MCDIv0: Siena BootROM. Transport uses MCDIv1 headers.
+ * - MCDIv1: Siena firmware and Huntington BootROM.
+ * - MCDIv2: EF10 firmware (Huntington/Medford) and Medford BootROM.
+ * Transport uses MCDIv2 headers.
+ *
+ * MCDIv2 Header NOT_EPOCH flag
+ * ----------------------------
+ * A new epoch begins at initial startup or after an MC reboot, and defines when
+ * the MC should reject stale MCDI requests.
+ *
+ * The first MCDI request sent by the host should contain NOT_EPOCH=0, and all
+ * subsequent requests (until the next MC reboot) should contain NOT_EPOCH=1.
+ *
+ * After rebooting the MC will fail all requests with NOT_EPOCH=1 by writing a
+ * response with ERROR=1 and DATALEN=0 until a request is seen with NOT_EPOCH=0.
+ */
+
+
#if EFSYS_OPT_SIENA
static efx_mcdi_ops_t __efx_mcdi_siena_ops = {
siena_mcdi_init, /* emco_init */
- siena_mcdi_request_copyin, /* emco_request_copyin */
- siena_mcdi_request_copyout, /* emco_request_copyout */
+ siena_mcdi_send_request, /* emco_send_request */
siena_mcdi_poll_reboot, /* emco_poll_reboot */
siena_mcdi_poll_response, /* emco_poll_response */
siena_mcdi_read_response, /* emco_read_response */
@@ -56,8 +75,7 @@ static efx_mcdi_ops_t __efx_mcdi_siena_ops = {
static efx_mcdi_ops_t __efx_mcdi_ef10_ops = {
ef10_mcdi_init, /* emco_init */
- ef10_mcdi_request_copyin, /* emco_request_copyin */
- ef10_mcdi_request_copyout, /* emco_request_copyout */
+ ef10_mcdi_send_request, /* emco_send_request */
ef10_mcdi_poll_reboot, /* emco_poll_reboot */
ef10_mcdi_poll_response, /* emco_poll_response */
ef10_mcdi_read_response, /* emco_read_response */
@@ -179,26 +197,16 @@ efx_mcdi_new_epoch(
}
static void
-efx_mcdi_request_copyin(
+efx_mcdi_send_request(
__in efx_nic_t *enp,
- __in efx_mcdi_req_t *emrp,
- __in unsigned int seq,
- __in boolean_t ev_cpl,
- __in boolean_t new_epoch)
-{
- efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop;
-
- emcop->emco_request_copyin(enp, emrp, seq, ev_cpl, new_epoch);
-}
-
-static void
-efx_mcdi_request_copyout(
- __in efx_nic_t *enp,
- __in efx_mcdi_req_t *emrp)
+ __in void *hdrp,
+ __in size_t hdr_len,
+ __in void *sdup,
+ __in size_t sdu_len)
{
efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop;
- emcop->emco_request_copyout(enp, emrp);
+ emcop->emco_send_request(enp, hdrp, hdr_len, sdup, sdu_len);
}
static efx_rc_t
@@ -241,8 +249,15 @@ efx_mcdi_request_start(
__in efx_mcdi_req_t *emrp,
__in boolean_t ev_cpl)
{
+#if EFSYS_OPT_MCDI_LOGGING
+ const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp;
+#endif
efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
+ efx_dword_t hdr[2];
+ size_t hdr_len;
+ unsigned int max_version;
unsigned int seq;
+ unsigned int xflags;
boolean_t new_epoch;
int state;
@@ -269,13 +284,64 @@ efx_mcdi_request_start(
emip->emi_poll_cnt = 0;
seq = emip->emi_seq++ & EFX_MASK32(MCDI_HEADER_SEQ);
new_epoch = emip->emi_new_epoch;
+ max_version = emip->emi_max_version;
EFSYS_UNLOCK(enp->en_eslp, state);
- efx_mcdi_request_copyin(enp, emrp, seq, ev_cpl, new_epoch);
+ xflags = 0;
+ if (ev_cpl)
+ xflags |= MCDI_HEADER_XFLAGS_EVREQ;
+
+ /*
+ * Huntington firmware supports MCDIv2, but the Huntington BootROM only
+ * supports MCDIv1. Use MCDIv1 headers for MCDIv1 commands where
+ * possible to support this.
+ */
+ if ((max_version >= 2) &&
+ ((emrp->emr_cmd > MC_CMD_CMD_SPACE_ESCAPE_7) ||
+ (emrp->emr_in_length > MCDI_CTL_SDU_LEN_MAX_V1))) {
+ /* Construct MCDI v2 header */
+ hdr_len = sizeof (hdr);
+ EFX_POPULATE_DWORD_8(hdr[0],
+ MCDI_HEADER_CODE, MC_CMD_V2_EXTN,
+ MCDI_HEADER_RESYNC, 1,
+ MCDI_HEADER_DATALEN, 0,
+ MCDI_HEADER_SEQ, seq,
+ MCDI_HEADER_NOT_EPOCH, new_epoch ? 0 : 1,
+ MCDI_HEADER_ERROR, 0,
+ MCDI_HEADER_RESPONSE, 0,
+ MCDI_HEADER_XFLAGS, xflags);
+
+ EFX_POPULATE_DWORD_2(hdr[1],
+ MC_CMD_V2_EXTN_IN_EXTENDED_CMD, emrp->emr_cmd,
+ MC_CMD_V2_EXTN_IN_ACTUAL_LEN, emrp->emr_in_length);
+ } else {
+ /* Construct MCDI v1 header */
+ hdr_len = sizeof (hdr[0]);
+ EFX_POPULATE_DWORD_8(hdr[0],
+ MCDI_HEADER_CODE, emrp->emr_cmd,
+ MCDI_HEADER_RESYNC, 1,
+ MCDI_HEADER_DATALEN, emrp->emr_in_length,
+ MCDI_HEADER_SEQ, seq,
+ MCDI_HEADER_NOT_EPOCH, new_epoch ? 0 : 1,
+ MCDI_HEADER_ERROR, 0,
+ MCDI_HEADER_RESPONSE, 0,
+ MCDI_HEADER_XFLAGS, xflags);
+ }
+
+#if EFSYS_OPT_MCDI_LOGGING
+ if (emtp->emt_logger != NULL) {
+ emtp->emt_logger(emtp->emt_context, EFX_LOG_MCDI_REQUEST,
+ &hdr, hdr_len,
+ emrp->emr_in_buf, emrp->emr_in_length);
+ }
+#endif /* EFSYS_OPT_MCDI_LOGGING */
+
+ efx_mcdi_send_request(enp, &hdr[0], hdr_len,
+ emrp->emr_in_buf, emrp->emr_in_length);
}
- void
+static void
efx_mcdi_read_response_header(
__in efx_nic_t *enp,
__inout efx_mcdi_req_t *emrp)
@@ -384,19 +450,56 @@ efx_mcdi_read_response_header(
return;
fail3:
- if (!emrp->emr_quiet)
- EFSYS_PROBE(fail3);
fail2:
- if (!emrp->emr_quiet)
- EFSYS_PROBE(fail2);
fail1:
- if (!emrp->emr_quiet)
- EFSYS_PROBE1(fail1, efx_rc_t, rc);
-
emrp->emr_rc = rc;
emrp->emr_out_length_used = 0;
}
+static void
+efx_mcdi_finish_response(
+ __in efx_nic_t *enp,
+ __in efx_mcdi_req_t *emrp)
+{
+#if EFSYS_OPT_MCDI_LOGGING
+ const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp;
+#endif /* EFSYS_OPT_MCDI_LOGGING */
+ efx_dword_t hdr[2];
+ unsigned int hdr_len;
+ size_t bytes;
+
+ if (emrp->emr_out_buf == NULL)
+ return;
+
+ /* Read the command header to detect MCDI response format */
+ hdr_len = sizeof (hdr[0]);
+ efx_mcdi_read_response(enp, &hdr[0], 0, hdr_len);
+ if (EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_CODE) == MC_CMD_V2_EXTN) {
+ /*
+ * Read the actual payload length. The length given in the event
+ * is only correct for responses with the V1 format.
+ */
+ efx_mcdi_read_response(enp, &hdr[1], hdr_len, sizeof (hdr[1]));
+ hdr_len += sizeof (hdr[1]);
+
+ emrp->emr_out_length_used = EFX_DWORD_FIELD(hdr[1],
+ MC_CMD_V2_EXTN_IN_ACTUAL_LEN);
+ }
+
+ /* Copy payload out into caller supplied buffer */
+ bytes = MIN(emrp->emr_out_length_used, emrp->emr_out_length);
+ efx_mcdi_read_response(enp, emrp->emr_out_buf, hdr_len, bytes);
+
+#if EFSYS_OPT_MCDI_LOGGING
+ if (emtp->emt_logger != NULL) {
+ emtp->emt_logger(emtp->emt_context,
+ EFX_LOG_MCDI_RESPONSE,
+ &hdr, hdr_len,
+ emrp->emr_out_buf, bytes);
+ }
+#endif /* EFSYS_OPT_MCDI_LOGGING */
+}
+
__checkReturn boolean_t
efx_mcdi_request_poll(
@@ -444,7 +547,7 @@ efx_mcdi_request_poll(
if ((rc = emrp->emr_rc) != 0)
goto fail2;
- efx_mcdi_request_copyout(enp, emrp);
+ efx_mcdi_finish_response(enp, emrp);
return (B_TRUE);
fail2:
@@ -638,7 +741,6 @@ efx_mcdi_ev_cpl(
{
efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp;
- efx_mcdi_ops_t *emcop = enp->en_mcdi.em_emcop;
efx_mcdi_req_t *emrp;
int state;
@@ -680,7 +782,7 @@ efx_mcdi_ev_cpl(
}
}
if (errcode == 0) {
- emcop->emco_request_copyout(enp, emrp);
+ efx_mcdi_finish_response(enp, emrp);
}
emtp->emt_ev_cpl(emtp->emt_context);
diff --git a/sys/dev/sfxge/common/efx_mcdi.h b/sys/dev/sfxge/common/efx_mcdi.h
index 36b3d8d44aae..dd1d76e5fafa 100644
--- a/sys/dev/sfxge/common/efx_mcdi.h
+++ b/sys/dev/sfxge/common/efx_mcdi.h
@@ -88,11 +88,6 @@ efx_mcdi_execute_quiet(
__in efx_nic_t *enp,
__inout efx_mcdi_req_t *emrp);
- extern void
-efx_mcdi_read_response_header(
- __in efx_nic_t *enp,
- __inout efx_mcdi_req_t *emrp);
-
extern void
efx_mcdi_ev_cpl(
__in efx_nic_t *enp,
diff --git a/sys/dev/sfxge/common/efx_nic.c b/sys/dev/sfxge/common/efx_nic.c
index 07acc56d779c..dd28ecef029f 100644
--- a/sys/dev/sfxge/common/efx_nic.c
+++ b/sys/dev/sfxge/common/efx_nic.c
@@ -244,6 +244,7 @@ fail1:
static efx_nic_ops_t __efx_nic_falcon_ops = {
falcon_nic_probe, /* eno_probe */
+ NULL, /* eno_board_cfg */
NULL, /* eno_set_drv_limits */
falcon_nic_reset, /* eno_reset */
falcon_nic_init, /* eno_init */
@@ -263,6 +264,7 @@ static efx_nic_ops_t __efx_nic_falcon_ops = {
static efx_nic_ops_t __efx_nic_siena_ops = {
siena_nic_probe, /* eno_probe */
+ NULL, /* eno_board_cfg */
NULL, /* eno_set_drv_limits */
siena_nic_reset, /* eno_reset */
siena_nic_init, /* eno_init */
@@ -282,6 +284,7 @@ static efx_nic_ops_t __efx_nic_siena_ops = {
static efx_nic_ops_t __efx_nic_hunt_ops = {
ef10_nic_probe, /* eno_probe */
+ hunt_board_cfg, /* eno_board_cfg */
ef10_nic_set_drv_limits, /* eno_set_drv_limits */
ef10_nic_reset, /* eno_reset */
ef10_nic_init, /* eno_init */
@@ -297,6 +300,27 @@ static efx_nic_ops_t __efx_nic_hunt_ops = {
#endif /* EFSYS_OPT_HUNTINGTON */
+#if EFSYS_OPT_MEDFORD
+
+static efx_nic_ops_t __efx_nic_medford_ops = {
+ ef10_nic_probe, /* eno_probe */
+ medford_board_cfg, /* eno_board_cfg */
+ ef10_nic_set_drv_limits, /* eno_set_drv_limits */
+ ef10_nic_reset, /* eno_reset */
+ ef10_nic_init, /* eno_init */
+ ef10_nic_get_vi_pool, /* eno_get_vi_pool */
+ ef10_nic_get_bar_region, /* eno_get_bar_region */
+#if EFSYS_OPT_DIAG
+ ef10_sram_test, /* eno_sram_test */
+ ef10_nic_register_test, /* eno_register_test */
+#endif /* EFSYS_OPT_DIAG */
+ ef10_nic_fini, /* eno_fini */
+ ef10_nic_unprobe, /* eno_unprobe */
+};
+
+#endif /* EFSYS_OPT_MEDFORD */
+
+
__checkReturn efx_rc_t
efx_nic_create(
__in efx_family_t family,
@@ -357,10 +381,29 @@ efx_nic_create(
EFX_FEATURE_MAC_HEADER_FILTERS |
EFX_FEATURE_MCDI_DMA |
EFX_FEATURE_PIO_BUFFERS |
- EFX_FEATURE_FW_ASSISTED_TSO;
+ EFX_FEATURE_FW_ASSISTED_TSO |
+ EFX_FEATURE_FW_ASSISTED_TSO_V2;
break;
#endif /* EFSYS_OPT_HUNTINGTON */
+#if EFSYS_OPT_MEDFORD
+ case EFX_FAMILY_MEDFORD:
+ enp->en_enop = (efx_nic_ops_t *)&__efx_nic_medford_ops;
+ /*
+ * FW_ASSISTED_TSO ommitted as Medford only supports firmware
+ * assisted TSO version 2, not the v1 scheme used on Huntington.
+ */
+ enp->en_features =
+ EFX_FEATURE_IPV6 |
+ EFX_FEATURE_LINK_EVENTS |
+ EFX_FEATURE_PERIODIC_MAC_STATS |
+ EFX_FEATURE_MCDI |
+ EFX_FEATURE_MAC_HEADER_FILTERS |
+ EFX_FEATURE_MCDI_DMA |
+ EFX_FEATURE_PIO_BUFFERS;
+ break;
+#endif /* EFSYS_OPT_MEDFORD */
+
default:
rc = ENOTSUP;
goto fail2;
@@ -665,8 +708,9 @@ efx_nic_reset(
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
/*
- * All modules except the MCDI, PROBE, NVRAM, VPD, MON (which we
- * do not reset here) must have been shut down or never initialized.
+ * All modules except the MCDI, PROBE, NVRAM, VPD, MON, LIC
+ * (which we do not reset here) must have been shut down or never
+ * initialized.
*
* A rule of thumb here is: If the controller or MC reboots, is *any*
* state lost. If it's lost and needs reapplying, then the module
@@ -674,7 +718,7 @@ efx_nic_reset(
*/
mod_flags = enp->en_mod_flags;
mod_flags &= ~(EFX_MOD_MCDI | EFX_MOD_PROBE | EFX_MOD_NVRAM |
- EFX_MOD_VPD | EFX_MOD_MON);
+ EFX_MOD_VPD | EFX_MOD_MON | EFX_MOD_LIC);
EFSYS_ASSERT3U(mod_flags, ==, 0);
if (mod_flags != 0) {
rc = EINVAL;
diff --git a/sys/dev/sfxge/common/efx_nvram.c b/sys/dev/sfxge/common/efx_nvram.c
index 759763623db8..abb1dd7508b9 100644
--- a/sys/dev/sfxge/common/efx_nvram.c
+++ b/sys/dev/sfxge/common/efx_nvram.c
@@ -42,15 +42,15 @@ static efx_nvram_ops_t __efx_nvram_falcon_ops = {
#if EFSYS_OPT_DIAG
falcon_nvram_test, /* envo_test */
#endif /* EFSYS_OPT_DIAG */
- falcon_nvram_size, /* envo_size */
falcon_nvram_get_version, /* envo_get_version */
- falcon_nvram_rw_start, /* envo_rw_start */
falcon_nvram_read_chunk, /* envo_read_chunk */
falcon_nvram_erase, /* envo_erase */
falcon_nvram_write_chunk, /* envo_write_chunk */
falcon_nvram_rw_finish, /* envo_rw_finish */
falcon_nvram_set_version, /* envo_set_version */
falcon_nvram_type_to_partn, /* envo_type_to_partn */
+ falcon_nvram_partn_size, /* envo_partn_size */
+ falcon_nvram_partn_rw_start, /* envo_partn_rw_start */
};
#endif /* EFSYS_OPT_FALCON */
@@ -61,15 +61,15 @@ static efx_nvram_ops_t __efx_nvram_siena_ops = {
#if EFSYS_OPT_DIAG
siena_nvram_test, /* envo_test */
#endif /* EFSYS_OPT_DIAG */
- siena_nvram_size, /* envo_size */
siena_nvram_get_version, /* envo_get_version */
- siena_nvram_rw_start, /* envo_rw_start */
siena_nvram_read_chunk, /* envo_read_chunk */
siena_nvram_erase, /* envo_erase */
siena_nvram_write_chunk, /* envo_write_chunk */
siena_nvram_rw_finish, /* envo_rw_finish */
siena_nvram_set_version, /* envo_set_version */
siena_nvram_type_to_partn, /* envo_type_to_partn */
+ siena_nvram_partn_size, /* envo_partn_size */
+ siena_nvram_partn_rw_start, /* envo_partn_rw_start */
};
#endif /* EFSYS_OPT_SIENA */
@@ -80,15 +80,15 @@ static efx_nvram_ops_t __efx_nvram_ef10_ops = {
#if EFSYS_OPT_DIAG
ef10_nvram_test, /* envo_test */
#endif /* EFSYS_OPT_DIAG */
- ef10_nvram_size, /* envo_size */
ef10_nvram_get_version, /* envo_get_version */
- ef10_nvram_rw_start, /* envo_rw_start */
ef10_nvram_read_chunk, /* envo_read_chunk */
ef10_nvram_erase, /* envo_erase */
ef10_nvram_write_chunk, /* envo_write_chunk */
ef10_nvram_rw_finish, /* envo_rw_finish */
ef10_nvram_set_version, /* envo_set_version */
ef10_nvram_type_to_partn, /* envo_type_to_partn */
+ ef10_nvram_partn_size, /* envo_partn_size */
+ ef10_nvram_partn_rw_start, /* envo_partn_rw_start */
};
#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
@@ -178,6 +178,7 @@ efx_nvram_size(
__out size_t *sizep)
{
efx_nvram_ops_t *envop = enp->en_envop;
+ uint32_t partn;
efx_rc_t rc;
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
@@ -185,13 +186,19 @@ efx_nvram_size(
EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
- if ((rc = envop->envo_size(enp, type, sizep)) != 0)
+ if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
goto fail1;
+ if ((rc = envop->envo_partn_size(enp, partn, sizep)) != 0)
+ goto fail2;
+
return (0);
+fail2:
+ EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
+ *sizep = 0;
return (rc);
}
@@ -230,6 +237,7 @@ efx_nvram_rw_start(
__out_opt size_t *chunk_sizep)
{
efx_nvram_ops_t *envop = enp->en_envop;
+ uint32_t partn;
efx_rc_t rc;
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
@@ -240,13 +248,18 @@ efx_nvram_rw_start(
EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
- if ((rc = envop->envo_rw_start(enp, type, chunk_sizep)) != 0)
+ if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
goto fail1;
+ if ((rc = envop->envo_partn_rw_start(enp, partn, chunk_sizep)) != 0)
+ goto fail2;
+
enp->en_nvram_locked = type;
return (0);
+fail2:
+ EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
diff --git a/sys/dev/sfxge/common/efx_rx.c b/sys/dev/sfxge/common/efx_rx.c
index a0b143f2b764..8ebe205715bd 100644
--- a/sys/dev/sfxge/common/efx_rx.c
+++ b/sys/dev/sfxge/common/efx_rx.c
@@ -78,14 +78,14 @@ falconsiena_rx_prefix_hash(
__in efx_rx_hash_alg_t func,
__in uint8_t *buffer);
+#endif /* EFSYS_OPT_RX_SCALE */
+
static __checkReturn efx_rc_t
falconsiena_rx_prefix_pktlen(
__in efx_nic_t *enp,
__in uint8_t *buffer,
__out uint16_t *lengthp);
-#endif /* EFSYS_OPT_RX_SCALE */
-
static void
falconsiena_rx_qpost(
__in efx_rxq_t *erp,
diff --git a/sys/dev/sfxge/common/efx_tx.c b/sys/dev/sfxge/common/efx_tx.c
index cff77426fe06..168fde4cfbc0 100644
--- a/sys/dev/sfxge/common/efx_tx.c
+++ b/sys/dev/sfxge/common/efx_tx.c
@@ -142,6 +142,7 @@ static efx_tx_ops_t __efx_tx_falcon_ops = {
falconsiena_tx_qdesc_post, /* etxo_qdesc_post */
falconsiena_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */
NULL, /* etxo_qdesc_tso_create */
+ NULL, /* etxo_qdesc_tso2_create */
NULL, /* etxo_qdesc_vlantci_create */
#if EFSYS_OPT_QSTATS
falconsiena_tx_qstats_update, /* etxo_qstats_update */
@@ -167,6 +168,7 @@ static efx_tx_ops_t __efx_tx_siena_ops = {
falconsiena_tx_qdesc_post, /* etxo_qdesc_post */
falconsiena_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */
NULL, /* etxo_qdesc_tso_create */
+ NULL, /* etxo_qdesc_tso2_create */
NULL, /* etxo_qdesc_vlantci_create */
#if EFSYS_OPT_QSTATS
falconsiena_tx_qstats_update, /* etxo_qstats_update */
@@ -192,6 +194,7 @@ static efx_tx_ops_t __efx_tx_hunt_ops = {
ef10_tx_qdesc_post, /* etxo_qdesc_post */
ef10_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */
hunt_tx_qdesc_tso_create, /* etxo_qdesc_tso_create */
+ ef10_tx_qdesc_tso2_create, /* etxo_qdesc_tso2_create */
ef10_tx_qdesc_vlantci_create, /* etxo_qdesc_vlantci_create */
#if EFSYS_OPT_QSTATS
ef10_tx_qstats_update, /* etxo_qstats_update */
@@ -217,6 +220,7 @@ static efx_tx_ops_t __efx_tx_medford_ops = {
ef10_tx_qdesc_post, /* etxo_qdesc_post */
ef10_tx_qdesc_dma_create, /* etxo_qdesc_dma_create */
NULL, /* etxo_qdesc_tso_create */
+ ef10_tx_qdesc_tso2_create, /* etxo_qdesc_tso2_create */
ef10_tx_qdesc_vlantci_create, /* etxo_qdesc_vlantci_create */
#if EFSYS_OPT_QSTATS
ef10_tx_qstats_update, /* etxo_qstats_update */
@@ -641,6 +645,24 @@ efx_tx_qdesc_tso_create(
}
void
+efx_tx_qdesc_tso2_create(
+ __in efx_txq_t *etp,
+ __in uint16_t ipv4_id,
+ __in uint32_t tcp_seq,
+ __in uint16_t mss,
+ __out_ecount(count) efx_desc_t *edp,
+ __in int count)
+{
+ efx_nic_t *enp = etp->et_enp;
+ efx_tx_ops_t *etxop = enp->en_etxop;
+
+ EFSYS_ASSERT3U(etp->et_magic, ==, EFX_TXQ_MAGIC);
+ EFSYS_ASSERT(etxop->etxo_qdesc_tso2_create != NULL);
+
+ etxop->etxo_qdesc_tso2_create(etp, ipv4_id, tcp_seq, mss, edp, count);
+}
+
+ void
efx_tx_qdesc_vlantci_create(
__in efx_txq_t *etp,
__in uint16_t tci,
diff --git a/sys/dev/sfxge/common/efx_vpd.c b/sys/dev/sfxge/common/efx_vpd.c
index c1762e62193f..ebeddfea90f5 100644
--- a/sys/dev/sfxge/common/efx_vpd.c
+++ b/sys/dev/sfxge/common/efx_vpd.c
@@ -669,7 +669,7 @@ efx_vpd_hunk_next(
__in size_t size,
__out efx_vpd_tag_t *tagp,
__out efx_vpd_keyword_t *keywordp,
- __out_bcount_opt(*paylenp) unsigned int *payloadp,
+ __out_opt unsigned int *payloadp,
__out_opt uint8_t *paylenp,
__inout unsigned int *contp)
{
@@ -689,12 +689,18 @@ efx_vpd_hunk_next(
if ((rc = efx_vpd_next_tag(data, size, &offset,
&tag, &taglen)) != 0)
goto fail1;
- if (tag == EFX_VPD_END)
+
+ if (tag == EFX_VPD_END) {
+ keyword = 0;
+ paylen = 0;
+ index = 0;
break;
+ }
if (tag == EFX_VPD_ID) {
- if (index == *contp) {
+ if (index++ == *contp) {
EFSYS_ASSERT3U(taglen, <, 0x100);
+ keyword = 0;
paylen = (uint8_t)MIN(taglen, 0xff);
goto done;
@@ -705,7 +711,7 @@ efx_vpd_hunk_next(
taglen, pos, &keyword, &keylen)) != 0)
goto fail2;
- if (index == *contp) {
+ if (index++ == *contp) {
offset += pos + 3;
paylen = keylen;
@@ -717,9 +723,6 @@ efx_vpd_hunk_next(
offset += taglen;
}
- *contp = 0;
- return (0);
-
done:
*tagp = tag;
*keywordp = keyword;
@@ -728,7 +731,7 @@ done:
if (paylenp != NULL)
*paylenp = paylen;
- ++(*contp);
+ *contp = index;
return (0);
fail2:
diff --git a/sys/dev/sfxge/common/hunt_ev.c b/sys/dev/sfxge/common/hunt_ev.c
index 2cea2e05bfe0..6c607cc60b14 100644
--- a/sys/dev/sfxge/common/hunt_ev.c
+++ b/sys/dev/sfxge/common/hunt_ev.c
@@ -444,9 +444,9 @@ ef10_ev_qmoderate(
eep->ee_index, &dword, 0);
} else {
EFX_POPULATE_DWORD_2(dword,
- FRF_CZ_TC_TIMER_MODE, mode,
- FRF_CZ_TC_TIMER_VAL, timer_val);
- EFX_BAR_TBL_WRITED(enp, FR_BZ_TIMER_COMMAND_REGP0,
+ ERF_DZ_TC_TIMER_MODE, mode,
+ ERF_DZ_TC_TIMER_VAL, timer_val);
+ EFX_BAR_TBL_WRITED(enp, ER_DZ_EVQ_TMR_REG,
eep->ee_index, &dword, 0);
}
diff --git a/sys/dev/sfxge/common/hunt_impl.h b/sys/dev/sfxge/common/hunt_impl.h
index f8c3b5e67678..646817724b71 100644
--- a/sys/dev/sfxge/common/hunt_impl.h
+++ b/sys/dev/sfxge/common/hunt_impl.h
@@ -54,6 +54,13 @@ extern "C" {
*/
#define EF10_RX_WPTR_ALIGN 8
+/*
+ * Max byte offset into the packet the TCP header must start for the hardware
+ * to be able to parse the packet correctly.
+ * FIXME: Move to ef10_impl.h when it is included in all driver builds.
+ */
+#define EF10_TCP_HEADER_OFFSET_LIMIT 208
+
/* Invalid RSS context handle */
#define EF10_RSS_CONTEXT_INVALID (0xffffffff)
@@ -165,6 +172,10 @@ ef10_nic_probe(
__in efx_nic_t *enp);
extern __checkReturn efx_rc_t
+hunt_board_cfg(
+ __in efx_nic_t *enp);
+
+extern __checkReturn efx_rc_t
ef10_nic_set_drv_limits(
__inout efx_nic_t *enp,
__in efx_drv_limits_t *edlp);
@@ -276,12 +287,12 @@ ef10_mcdi_fini(
__in efx_nic_t *enp);
extern void
-ef10_mcdi_request_copyin(
+ef10_mcdi_send_request(
__in efx_nic_t *enp,
- __in efx_mcdi_req_t *emrp,
- __in unsigned int seq,
- __in boolean_t ev_cpl,
- __in boolean_t new_epoch);
+ __in void *hdrp,
+ __in size_t hdr_len,
+ __in void *sdup,
+ __in size_t sdu_len);
extern __checkReturn boolean_t
ef10_mcdi_poll_response(
@@ -294,11 +305,6 @@ ef10_mcdi_read_response(
__in size_t offset,
__in size_t length);
-extern void
-ef10_mcdi_request_copyout(
- __in efx_nic_t *enp,
- __in efx_mcdi_req_t *emrp);
-
extern efx_rc_t
ef10_mcdi_poll_reboot(
__in efx_nic_t *enp);
@@ -359,12 +365,6 @@ ef10_nvram_partn_write_segment_tlv(
__in boolean_t all_segments);
extern __checkReturn efx_rc_t
-ef10_nvram_partn_size(
- __in efx_nic_t *enp,
- __in uint32_t partn,
- __out size_t *sizep);
-
-extern __checkReturn efx_rc_t
ef10_nvram_partn_lock(
__in efx_nic_t *enp,
__in uint32_t partn);
@@ -410,12 +410,6 @@ ef10_nvram_test(
#endif /* EFSYS_OPT_DIAG */
extern __checkReturn efx_rc_t
-ef10_nvram_size(
- __in efx_nic_t *enp,
- __in efx_nvram_type_t type,
- __out size_t *sizep);
-
-extern __checkReturn efx_rc_t
ef10_nvram_get_version(
__in efx_nic_t *enp,
__in efx_nvram_type_t type,
@@ -423,12 +417,6 @@ ef10_nvram_get_version(
__out_ecount(4) uint16_t version[4]);
extern __checkReturn efx_rc_t
-ef10_nvram_rw_start(
- __in efx_nic_t *enp,
- __in efx_nvram_type_t type,
- __out size_t *pref_chunkp);
-
-extern __checkReturn efx_rc_t
ef10_nvram_read_chunk(
__in efx_nic_t *enp,
__in efx_nvram_type_t type,
@@ -472,21 +460,33 @@ ef10_nvram_type_to_partn(
__in efx_nvram_type_t type,
__out uint32_t *partnp);
+extern __checkReturn efx_rc_t
+ef10_nvram_partn_size(
+ __in efx_nic_t *enp,
+ __in uint32_t partn,
+ __out size_t *sizep);
+
+extern __checkReturn efx_rc_t
+ef10_nvram_partn_rw_start(
+ __in efx_nic_t *enp,
+ __in uint32_t partn,
+ __out size_t *chunk_sizep);
+
#endif /* EFSYS_OPT_NVRAM */
/* PHY */
-typedef struct hunt_link_state_s {
- uint32_t hls_adv_cap_mask;
- uint32_t hls_lp_cap_mask;
- unsigned int hls_fcntl;
- efx_link_mode_t hls_link_mode;
+typedef struct ef10_link_state_s {
+ uint32_t els_adv_cap_mask;
+ uint32_t els_lp_cap_mask;
+ unsigned int els_fcntl;
+ efx_link_mode_t els_link_mode;
#if EFSYS_OPT_LOOPBACK
- efx_loopback_type_t hls_loopback;
+ efx_loopback_type_t els_loopback;
#endif
- boolean_t hls_mac_up;
-} hunt_link_state_t;
+ boolean_t els_mac_up;
+} ef10_link_state_t;
extern void
hunt_phy_link_ev(
@@ -497,7 +497,7 @@ hunt_phy_link_ev(
extern __checkReturn efx_rc_t
hunt_phy_get_link(
__in efx_nic_t *enp,
- __out hunt_link_state_t *hlsp);
+ __out ef10_link_state_t *elsp);
extern __checkReturn efx_rc_t
hunt_phy_power(
@@ -696,6 +696,15 @@ hunt_tx_qdesc_tso_create(
__out efx_desc_t *edp);
extern void
+ef10_tx_qdesc_tso2_create(
+ __in efx_txq_t *etp,
+ __in uint16_t ipv4_id,
+ __in uint32_t tcp_seq,
+ __in uint16_t tcp_mss,
+ __out_ecount(count) efx_desc_t *edp,
+ __in int count);
+
+extern void
ef10_tx_qdesc_vlantci_create(
__in efx_txq_t *etp,
__in uint16_t vlan_tci,
@@ -733,7 +742,7 @@ ef10_tx_qstats_update(
#define HUNT_MIN_PIO_ALLOC_SIZE (HUNT_PIOBUF_SIZE / 32)
-#define HUNT_LEGACY_PF_PRIVILEGE_MASK \
+#define EF10_LEGACY_PF_PRIVILEGE_MASK \
(MC_CMD_PRIVILEGE_MASK_IN_GRP_ADMIN | \
MC_CMD_PRIVILEGE_MASK_IN_GRP_LINK | \
MC_CMD_PRIVILEGE_MASK_IN_GRP_ONLOAD | \
@@ -746,7 +755,7 @@ ef10_tx_qstats_update(
MC_CMD_PRIVILEGE_MASK_IN_GRP_ALL_MULTICAST | \
MC_CMD_PRIVILEGE_MASK_IN_GRP_PROMISCUOUS)
-#define HUNT_LEGACY_VF_PRIVILEGE_MASK 0
+#define EF10_LEGACY_VF_PRIVILEGE_MASK 0
typedef uint32_t efx_piobuf_handle_t;
@@ -886,14 +895,14 @@ ef10_rx_prefix_hash(
__in efx_rx_hash_alg_t func,
__in uint8_t *buffer);
+#endif /* EFSYS_OPT_RX_SCALE */
+
extern __checkReturn efx_rc_t
ef10_rx_prefix_pktlen(
__in efx_nic_t *enp,
__in uint8_t *buffer,
__out uint16_t *lengthp);
-#endif /* EFSYS_OPT_RX_SCALE */
-
extern void
ef10_rx_qpost(
__in efx_rxq_t *erp,
diff --git a/sys/dev/sfxge/common/hunt_mac.c b/sys/dev/sfxge/common/hunt_mac.c
index 358c4d91e920..dcc64c1ec53f 100644
--- a/sys/dev/sfxge/common/hunt_mac.c
+++ b/sys/dev/sfxge/common/hunt_mac.c
@@ -48,16 +48,16 @@ hunt_mac_poll(
*/
efx_port_t *epp = &(enp->en_port);
- hunt_link_state_t hls;
+ ef10_link_state_t els;
efx_rc_t rc;
- if ((rc = hunt_phy_get_link(enp, &hls)) != 0)
+ if ((rc = hunt_phy_get_link(enp, &els)) != 0)
goto fail1;
- epp->ep_adv_cap_mask = hls.hls_adv_cap_mask;
- epp->ep_fcntl = hls.hls_fcntl;
+ epp->ep_adv_cap_mask = els.els_adv_cap_mask;
+ epp->ep_fcntl = els.els_fcntl;
- *link_modep = hls.hls_link_mode;
+ *link_modep = els.els_link_mode;
return (0);
@@ -79,17 +79,17 @@ hunt_mac_up(
* essentially identical.
*/
- hunt_link_state_t hls;
+ ef10_link_state_t els;
efx_rc_t rc;
/*
* Because Huntington doesn't *require* polling, we can't rely on
* hunt_mac_poll() being executed to populate epp->ep_mac_up.
*/
- if ((rc = hunt_phy_get_link(enp, &hls)) != 0)
+ if ((rc = hunt_phy_get_link(enp, &els)) != 0)
goto fail1;
- *mac_upp = hls.hls_mac_up;
+ *mac_upp = els.els_mac_up;
return (0);
diff --git a/sys/dev/sfxge/common/hunt_mcdi.c b/sys/dev/sfxge/common/hunt_mcdi.c
index 1cccb23afce3..f39e977ef705 100644
--- a/sys/dev/sfxge/common/hunt_mcdi.c
+++ b/sys/dev/sfxge/common/hunt_mcdi.c
@@ -43,37 +43,6 @@ __FBSDID("$FreeBSD$");
#error "WITH_MCDI_V2 required for EF10 MCDIv2 commands."
#endif
-typedef enum efx_mcdi_header_type_e {
- EFX_MCDI_HEADER_TYPE_V1, /* MCDIv0 (BootROM), MCDIv1 commands */
- EFX_MCDI_HEADER_TYPE_V2, /* MCDIv2 commands */
-} efx_mcdi_header_type_t;
-
-/*
- * Return the header format to use for sending an MCDI request.
- *
- * An MCDIv1 (Siena compatible) command should use MCDIv2 encapsulation if the
- * request input buffer or response output buffer are too large for the MCDIv1
- * format. An MCDIv2 command must always be sent using MCDIv2 encapsulation.
- */
-#define EFX_MCDI_HEADER_TYPE(_cmd, _length) \
- ((((_cmd) & ~EFX_MASK32(MCDI_HEADER_CODE)) || \
- ((_length) & ~EFX_MASK32(MCDI_HEADER_DATALEN))) ? \
- EFX_MCDI_HEADER_TYPE_V2 : EFX_MCDI_HEADER_TYPE_V1)
-
-
-/*
- * MCDI Header NOT_EPOCH flag
- * ==========================
- * A new epoch begins at initial startup or after an MC reboot, and defines when
- * the MC should reject stale MCDI requests.
- *
- * The first MCDI request sent by the host should contain NOT_EPOCH=0, and all
- * subsequent requests (until the next MC reboot) should contain NOT_EPOCH=1.
- *
- * After rebooting the MC will fail all requests with NOT_EPOCH=1 by writing a
- * response with ERROR=1 and DATALEN=0 until a request is seen with NOT_EPOCH=0.
- */
-
__checkReturn efx_rc_t
ef10_mcdi_init(
@@ -139,7 +108,7 @@ ef10_mcdi_fini(
emip->emi_new_epoch = B_FALSE;
}
-static void
+ void
ef10_mcdi_send_request(
__in efx_nic_t *enp,
__in void *hdrp,
@@ -181,118 +150,6 @@ ef10_mcdi_send_request(
EFX_BAR_WRITED(enp, ER_DZ_MC_DB_HWRD_REG, &dword, B_FALSE);
}
- void
-ef10_mcdi_request_copyin(
- __in efx_nic_t *enp,
- __in efx_mcdi_req_t *emrp,
- __in unsigned int seq,
- __in boolean_t ev_cpl,
- __in boolean_t new_epoch)
-{
-#if EFSYS_OPT_MCDI_LOGGING
- const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp;
-#endif /* EFSYS_OPT_MCDI_LOGGING */
- efx_mcdi_header_type_t hdr_type;
- efx_dword_t hdr[2];
- size_t hdr_len;
- unsigned int xflags;
-
- EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
- enp->en_family == EFX_FAMILY_MEDFORD);
-
- xflags = 0;
- if (ev_cpl)
- xflags |= MCDI_HEADER_XFLAGS_EVREQ;
-
- hdr_type = EFX_MCDI_HEADER_TYPE(emrp->emr_cmd,
- MAX(emrp->emr_in_length, emrp->emr_out_length));
-
- if (hdr_type == EFX_MCDI_HEADER_TYPE_V2) {
- /* Construct MCDI v2 header */
- hdr_len = sizeof (hdr);
- EFX_POPULATE_DWORD_8(hdr[0],
- MCDI_HEADER_CODE, MC_CMD_V2_EXTN,
- MCDI_HEADER_RESYNC, 1,
- MCDI_HEADER_DATALEN, 0,
- MCDI_HEADER_SEQ, seq,
- MCDI_HEADER_NOT_EPOCH, new_epoch ? 0 : 1,
- MCDI_HEADER_ERROR, 0,
- MCDI_HEADER_RESPONSE, 0,
- MCDI_HEADER_XFLAGS, xflags);
-
- EFX_POPULATE_DWORD_2(hdr[1],
- MC_CMD_V2_EXTN_IN_EXTENDED_CMD, emrp->emr_cmd,
- MC_CMD_V2_EXTN_IN_ACTUAL_LEN, emrp->emr_in_length);
- } else {
- /* Construct MCDI v1 header */
- hdr_len = sizeof (hdr[0]);
- EFX_POPULATE_DWORD_8(hdr[0],
- MCDI_HEADER_CODE, emrp->emr_cmd,
- MCDI_HEADER_RESYNC, 1,
- MCDI_HEADER_DATALEN, emrp->emr_in_length,
- MCDI_HEADER_SEQ, seq,
- MCDI_HEADER_NOT_EPOCH, new_epoch ? 0 : 1,
- MCDI_HEADER_ERROR, 0,
- MCDI_HEADER_RESPONSE, 0,
- MCDI_HEADER_XFLAGS, xflags);
- }
-
-#if EFSYS_OPT_MCDI_LOGGING
- if (emtp->emt_logger != NULL) {
- emtp->emt_logger(emtp->emt_context, EFX_LOG_MCDI_REQUEST,
- &hdr, hdr_len,
- emrp->emr_in_buf, emrp->emr_in_length);
- }
-#endif /* EFSYS_OPT_MCDI_LOGGING */
-
- ef10_mcdi_send_request(enp, &hdr[0], hdr_len,
- emrp->emr_in_buf, emrp->emr_in_length);
-}
-
- void
-ef10_mcdi_request_copyout(
- __in efx_nic_t *enp,
- __in efx_mcdi_req_t *emrp)
-{
-#if EFSYS_OPT_MCDI_LOGGING
- const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp;
-#endif /* EFSYS_OPT_MCDI_LOGGING */
- efx_dword_t hdr[2];
- unsigned int hdr_len;
- size_t bytes;
-
- if (emrp->emr_out_buf == NULL)
- return;
-
- /* Read the command header to detect MCDI response format */
- hdr_len = sizeof (hdr[0]);
- ef10_mcdi_read_response(enp, &hdr[0], 0, hdr_len);
- if (EFX_DWORD_FIELD(hdr[0], MCDI_HEADER_CODE) == MC_CMD_V2_EXTN) {
- /*
- * Read the actual payload length. The length given in the event
- * is only correct for responses with the V1 format.
- */
- ef10_mcdi_read_response(enp, &hdr[1], hdr_len, sizeof (hdr[1]));
- hdr_len += sizeof (hdr[1]);
-
- emrp->emr_out_length_used = EFX_DWORD_FIELD(hdr[1],
- MC_CMD_V2_EXTN_IN_ACTUAL_LEN);
- }
-
- /* Copy payload out into caller supplied buffer */
- bytes = MIN(emrp->emr_out_length_used, emrp->emr_out_length);
- ef10_mcdi_read_response(enp, emrp->emr_out_buf, hdr_len, bytes);
-
-#if EFSYS_OPT_MCDI_LOGGING
- if (emtp->emt_logger != NULL) {
- emtp->emt_logger(emtp->emt_context,
- EFX_LOG_MCDI_RESPONSE,
- &hdr, hdr_len,
- emrp->emr_out_buf, bytes);
- }
-#endif /* EFSYS_OPT_MCDI_LOGGING */
-}
-
__checkReturn boolean_t
ef10_mcdi_poll_response(
__in efx_nic_t *enp)
diff --git a/sys/dev/sfxge/common/hunt_nic.c b/sys/dev/sfxge/common/hunt_nic.c
index d87f3cd0694f..08eaa9c3761e 100644
--- a/sys/dev/sfxge/common/hunt_nic.c
+++ b/sys/dev/sfxge/common/hunt_nic.c
@@ -41,7 +41,7 @@ __FBSDID("$FreeBSD$");
#include "ef10_tlv_layout.h"
-static __checkReturn efx_rc_t
+ __checkReturn efx_rc_t
efx_mcdi_get_port_assignment(
__in efx_nic_t *enp,
__out uint32_t *portp)
@@ -85,7 +85,7 @@ fail1:
return (rc);
}
-static __checkReturn efx_rc_t
+ __checkReturn efx_rc_t
efx_mcdi_get_port_modes(
__in efx_nic_t *enp,
__out uint32_t *modesp)
@@ -112,7 +112,10 @@ efx_mcdi_get_port_modes(
goto fail1;
}
- /* Accept pre-Medford size (8 bytes - no CurrentMode field) */
+ /*
+ * Require only Modes and DefaultMode fields.
+ * (CurrentMode field was added for Medford)
+ */
if (req.emr_out_length_used <
MC_CMD_GET_PORT_MODES_OUT_CURRENT_MODE_OFST) {
rc = EMSGSIZE;
@@ -205,7 +208,7 @@ fail1:
return (rc);
}
-static __checkReturn efx_rc_t
+ __checkReturn efx_rc_t
efx_mcdi_get_mac_address_pf(
__in efx_nic_t *enp,
__out_ecount_opt(6) uint8_t mac_addrp[6])
@@ -263,7 +266,7 @@ fail1:
return (rc);
}
-static __checkReturn efx_rc_t
+ __checkReturn efx_rc_t
efx_mcdi_get_mac_address_vf(
__in efx_nic_t *enp,
__out_ecount_opt(6) uint8_t mac_addrp[6])
@@ -326,7 +329,7 @@ fail1:
return (rc);
}
-static __checkReturn efx_rc_t
+ __checkReturn efx_rc_t
efx_mcdi_get_clock(
__in efx_nic_t *enp,
__out uint32_t *sys_freqp)
@@ -376,7 +379,7 @@ fail1:
return (rc);
}
-static __checkReturn efx_rc_t
+ __checkReturn efx_rc_t
efx_mcdi_get_vector_cfg(
__in efx_nic_t *enp,
__out_opt uint32_t *vec_basep,
@@ -427,8 +430,8 @@ fail1:
static __checkReturn efx_rc_t
efx_mcdi_get_capabilities(
__in efx_nic_t *enp,
- __out efx_dword_t *flagsp,
- __out efx_dword_t *flags2p)
+ __out uint32_t *flagsp,
+ __out uint32_t *flags2p)
{
efx_mcdi_req_t req;
uint8_t payload[MAX(MC_CMD_GET_CAPABILITIES_IN_LEN,
@@ -454,13 +457,12 @@ efx_mcdi_get_capabilities(
goto fail2;
}
- *flagsp = *MCDI_OUT2(req, efx_dword_t, GET_CAPABILITIES_OUT_FLAGS1);
+ *flagsp = MCDI_OUT_DWORD(req, GET_CAPABILITIES_OUT_FLAGS1);
if (req.emr_out_length_used < MC_CMD_GET_CAPABILITIES_V2_OUT_LEN)
- EFX_ZERO_DWORD(*flags2p);
+ *flags2p = 0;
else
- *flags2p = *MCDI_OUT2(req, efx_dword_t,
- GET_CAPABILITIES_V2_OUT_FLAGS2);
+ *flags2p = MCDI_OUT_DWORD(req, GET_CAPABILITIES_V2_OUT_FLAGS2);
return (0);
@@ -889,76 +891,68 @@ ef10_nic_pio_unlink(
return (efx_mcdi_unlink_piobuf(enp, vi_index));
}
-static __checkReturn efx_rc_t
+ __checkReturn efx_rc_t
ef10_get_datapath_caps(
__in efx_nic_t *enp)
{
efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
- efx_dword_t datapath_capabilities;
- efx_dword_t datapath_capabilities_v2;
+ uint32_t flags;
+ uint32_t flags2;
efx_rc_t rc;
- if ((rc = efx_mcdi_get_capabilities(enp, &datapath_capabilities,
- &datapath_capabilities_v2)) != 0)
+ if ((rc = efx_mcdi_get_capabilities(enp, &flags, &flags2)) != 0)
goto fail1;
+#define CAP_FLAG(flags1, field) \
+ ((flags1) & (1 << (MC_CMD_GET_CAPABILITIES_V2_OUT_ ## field ## _LBN)))
+
+#define CAP_FLAG2(flags2, field) \
+ ((flags2) & (1 << (MC_CMD_GET_CAPABILITIES_V2_OUT_ ## field ## _LBN)))
+
/*
* Huntington RXDP firmware inserts a 0 or 14 byte prefix.
* We only support the 14 byte prefix here.
*/
- if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities,
- GET_CAPABILITIES_OUT_RX_PREFIX_LEN_14) != 1) {
+ if (CAP_FLAG(flags, RX_PREFIX_LEN_14) == 0) {
rc = ENOTSUP;
goto fail2;
}
encp->enc_rx_prefix_size = 14;
/* Check if the firmware supports TSO */
- if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities,
- GET_CAPABILITIES_OUT_TX_TSO) == 1)
- encp->enc_fw_assisted_tso_enabled = B_TRUE;
- else
- encp->enc_fw_assisted_tso_enabled = B_FALSE;
+ encp->enc_fw_assisted_tso_enabled =
+ CAP_FLAG(flags, TX_TSO) ? B_TRUE : B_FALSE;
+
+ /* Check if the firmware supports FATSOv2 */
+ encp->enc_fw_assisted_tso_v2_enabled =
+ CAP_FLAG2(flags2, TX_TSO_V2) ? B_TRUE : B_FALSE;
/* Check if the firmware has vadapter/vport/vswitch support */
- if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities,
- GET_CAPABILITIES_OUT_EVB) == 1)
- encp->enc_datapath_cap_evb = B_TRUE;
- else
- encp->enc_datapath_cap_evb = B_FALSE;
+ encp->enc_datapath_cap_evb =
+ CAP_FLAG(flags, EVB) ? B_TRUE : B_FALSE;
/* Check if the firmware supports VLAN insertion */
- if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities,
- GET_CAPABILITIES_OUT_TX_VLAN_INSERTION) == 1)
- encp->enc_hw_tx_insert_vlan_enabled = B_TRUE;
- else
- encp->enc_hw_tx_insert_vlan_enabled = B_FALSE;
+ encp->enc_hw_tx_insert_vlan_enabled =
+ CAP_FLAG(flags, TX_VLAN_INSERTION) ? B_TRUE : B_FALSE;
/* Check if the firmware supports RX event batching */
- if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities,
- GET_CAPABILITIES_OUT_RX_BATCHING) == 1) {
- encp->enc_rx_batching_enabled = B_TRUE;
+ encp->enc_rx_batching_enabled =
+ CAP_FLAG(flags, RX_BATCHING) ? B_TRUE : B_FALSE;
+
+ if (encp->enc_rx_batching_enabled)
encp->enc_rx_batch_max = 16;
- } else {
- encp->enc_rx_batching_enabled = B_FALSE;
- }
/* Check if the firmware supports disabling scatter on RXQs */
- if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities,
- GET_CAPABILITIES_OUT_RX_DISABLE_SCATTER) == 1) {
- encp->enc_rx_disable_scatter_supported = B_TRUE;
- } else {
- encp->enc_rx_disable_scatter_supported = B_FALSE;
- }
+ encp->enc_rx_disable_scatter_supported =
+ CAP_FLAG(flags, RX_DISABLE_SCATTER) ? B_TRUE : B_FALSE;
/* Check if the firmware supports set mac with running filters */
- if (MCDI_CMD_DWORD_FIELD(&datapath_capabilities,
- GET_CAPABILITIES_OUT_VADAPTOR_PERMIT_SET_MAC_WHEN_FILTERS_INSTALLED)
- == 1) {
- encp->enc_allow_set_mac_with_installed_filters = B_TRUE;
- } else {
- encp->enc_allow_set_mac_with_installed_filters = B_FALSE;
- }
+ encp->enc_allow_set_mac_with_installed_filters =
+ CAP_FLAG(flags, VADAPTOR_PERMIT_SET_MAC_WHEN_FILTERS_INSTALLED) ?
+ B_TRUE : B_FALSE;
+
+#undef CAP_FLAG
+#undef CAP_FLAG2
return (0);
@@ -970,6 +964,42 @@ fail1:
return (rc);
}
+
+ __checkReturn efx_rc_t
+ef10_get_privilege_mask(
+ __in efx_nic_t *enp,
+ __out uint32_t *maskp)
+{
+ efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+ uint32_t mask;
+ efx_rc_t rc;
+
+ if ((rc = efx_mcdi_privilege_mask(enp, encp->enc_pf, encp->enc_vf,
+ &mask)) != 0) {
+ if (rc != ENOTSUP)
+ goto fail1;
+
+ /* Fallback for old firmware without privilege mask support */
+ if (EFX_PCI_FUNCTION_IS_PF(encp)) {
+ /* Assume PF has admin privilege */
+ mask = EF10_LEGACY_PF_PRIVILEGE_MASK;
+ } else {
+ /* VF is always unprivileged by default */
+ mask = EF10_LEGACY_VF_PRIVILEGE_MASK;
+ }
+ }
+
+ *maskp = mask;
+
+ return (0);
+
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
+
+
/*
* The external port mapping is a one-based numbering of the external
* connectors on the board. It does not distinguish off-board separated
@@ -992,6 +1022,13 @@ static struct {
(1 << TLV_PORT_MODE_10G_10G_10G_10G),
1
},
+ {
+ EFX_FAMILY_MEDFORD,
+ (1 << TLV_PORT_MODE_10G) |
+ (1 << TLV_PORT_MODE_10G_10G) |
+ (1 << TLV_PORT_MODE_10G_10G_10G_10G),
+ 1
+ },
/* Supported modes requiring 2 outputs per port */
{
EFX_FAMILY_HUNTINGTON,
@@ -1000,18 +1037,25 @@ static struct {
(1 << TLV_PORT_MODE_40G_10G_10G) |
(1 << TLV_PORT_MODE_10G_10G_40G),
2
- }
- /*
- * NOTE: Medford modes will require 4 outputs per port:
- * TLV_PORT_MODE_10G_10G_10G_10G_Q
- * TLV_PORT_MODE_10G_10G_10G_10G_Q2
- * The Q2 mode routes outputs to external port 2. Support for this
- * will require a new field specifying the number to add after
- * scaling by stride. This is fixed at 1 currently.
- */
+ },
+ {
+ EFX_FAMILY_MEDFORD,
+ (1 << TLV_PORT_MODE_40G) |
+ (1 << TLV_PORT_MODE_40G_40G) |
+ (1 << TLV_PORT_MODE_40G_10G_10G) |
+ (1 << TLV_PORT_MODE_10G_10G_40G),
+ 2
+ },
+ /* Supported modes requiring 4 outputs per port */
+ {
+ EFX_FAMILY_MEDFORD,
+ (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q) |
+ (1 << TLV_PORT_MODE_10G_10G_10G_10G_Q2),
+ 4
+ },
};
-static __checkReturn efx_rc_t
+ __checkReturn efx_rc_t
ef10_external_port_mapping(
__in efx_nic_t *enp,
__in uint32_t port,
@@ -1064,7 +1108,7 @@ fail1:
return (rc);
}
-static __checkReturn efx_rc_t
+ __checkReturn efx_rc_t
hunt_board_cfg(
__in efx_nic_t *enp)
{
@@ -1072,7 +1116,7 @@ hunt_board_cfg(
efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
uint8_t mac_addr[6];
uint32_t board_type = 0;
- hunt_link_state_t hls;
+ ef10_link_state_t els;
efx_port_t *epp = &(enp->en_port);
uint32_t port;
uint32_t pf;
@@ -1146,10 +1190,10 @@ hunt_board_cfg(
goto fail6;
/* Obtain the default PHY advertised capabilities */
- if ((rc = hunt_phy_get_link(enp, &hls)) != 0)
+ if ((rc = hunt_phy_get_link(enp, &els)) != 0)
goto fail7;
- epp->ep_default_adv_cap_mask = hls.hls_adv_cap_mask;
- epp->ep_adv_cap_mask = hls.hls_adv_cap_mask;
+ epp->ep_default_adv_cap_mask = els.els_adv_cap_mask;
+ epp->ep_adv_cap_mask = els.els_adv_cap_mask;
/*
* Enable firmware workarounds for hardware errata.
@@ -1288,20 +1332,8 @@ hunt_board_cfg(
* the privilege mask to check for sufficient privileges, as that
* can result in time-of-check/time-of-use bugs.
*/
- if ((rc = efx_mcdi_privilege_mask(enp, pf, vf, &mask)) != 0) {
- if (rc != ENOTSUP)
- goto fail13;
-
- /* Fallback for old firmware without privilege mask support */
- if (EFX_PCI_FUNCTION_IS_PF(encp)) {
- /* Assume PF has admin privilege */
- mask = HUNT_LEGACY_PF_PRIVILEGE_MASK;
- } else {
- /* VF is always unprivileged by default */
- mask = HUNT_LEGACY_VF_PRIVILEGE_MASK;
- }
- }
-
+ if ((rc = ef10_get_privilege_mask(enp, &mask)) != 0)
+ goto fail13;
encp->enc_privilege_mask = mask;
/* Get interrupt vector limits */
@@ -1320,7 +1352,7 @@ hunt_board_cfg(
* Maximum number of bytes into the frame the TCP header can start for
* firmware assisted TSO to work.
*/
- encp->enc_tx_tso_tcp_header_offset_limit = 208;
+ encp->enc_tx_tso_tcp_header_offset_limit = EF10_TCP_HEADER_OFFSET_LIMIT;
return (0);
@@ -1361,6 +1393,7 @@ fail1:
ef10_nic_probe(
__in efx_nic_t *enp)
{
+ efx_nic_ops_t *enop = enp->en_enop;
efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
efx_drv_cfg_t *edcp = &(enp->en_drv_cfg);
efx_rc_t rc;
@@ -1380,7 +1413,7 @@ ef10_nic_probe(
if ((rc = efx_mcdi_drv_attach(enp, B_TRUE)) != 0)
goto fail3;
- if ((rc = hunt_board_cfg(enp)) != 0)
+ if ((rc = enop->eno_board_cfg(enp)) != 0)
if (rc != EACCES)
goto fail4;
diff --git a/sys/dev/sfxge/common/hunt_nvram.c b/sys/dev/sfxge/common/hunt_nvram.c
index cbead9b66a9a..17dc4ef122d1 100644
--- a/sys/dev/sfxge/common/hunt_nvram.c
+++ b/sys/dev/sfxge/common/hunt_nvram.c
@@ -1541,7 +1541,11 @@ static ef10_parttbl_entry_t hunt_parttbl[] = {
{NVRAM_PARTITION_TYPE_FPGA_BACKUP, 1, EFX_NVRAM_FPGA_BACKUP},
{NVRAM_PARTITION_TYPE_FPGA_BACKUP, 2, EFX_NVRAM_FPGA_BACKUP},
{NVRAM_PARTITION_TYPE_FPGA_BACKUP, 3, EFX_NVRAM_FPGA_BACKUP},
- {NVRAM_PARTITION_TYPE_FPGA_BACKUP, 4, EFX_NVRAM_FPGA_BACKUP}
+ {NVRAM_PARTITION_TYPE_FPGA_BACKUP, 4, EFX_NVRAM_FPGA_BACKUP},
+ {NVRAM_PARTITION_TYPE_LICENSE, 1, EFX_NVRAM_LICENSE},
+ {NVRAM_PARTITION_TYPE_LICENSE, 2, EFX_NVRAM_LICENSE},
+ {NVRAM_PARTITION_TYPE_LICENSE, 3, EFX_NVRAM_LICENSE},
+ {NVRAM_PARTITION_TYPE_LICENSE, 4, EFX_NVRAM_LICENSE}
};
static ef10_parttbl_entry_t medford_parttbl[] = {
@@ -1572,7 +1576,11 @@ static ef10_parttbl_entry_t medford_parttbl[] = {
{NVRAM_PARTITION_TYPE_FPGA_BACKUP, 1, EFX_NVRAM_FPGA_BACKUP},
{NVRAM_PARTITION_TYPE_FPGA_BACKUP, 2, EFX_NVRAM_FPGA_BACKUP},
{NVRAM_PARTITION_TYPE_FPGA_BACKUP, 3, EFX_NVRAM_FPGA_BACKUP},
- {NVRAM_PARTITION_TYPE_FPGA_BACKUP, 4, EFX_NVRAM_FPGA_BACKUP}
+ {NVRAM_PARTITION_TYPE_FPGA_BACKUP, 4, EFX_NVRAM_FPGA_BACKUP},
+ {NVRAM_PARTITION_TYPE_LICENSE, 1, EFX_NVRAM_LICENSE},
+ {NVRAM_PARTITION_TYPE_LICENSE, 2, EFX_NVRAM_LICENSE},
+ {NVRAM_PARTITION_TYPE_LICENSE, 3, EFX_NVRAM_LICENSE},
+ {NVRAM_PARTITION_TYPE_LICENSE, 4, EFX_NVRAM_LICENSE}
};
static __checkReturn efx_rc_t
@@ -1709,33 +1717,6 @@ fail1:
#endif /* EFSYS_OPT_DIAG */
__checkReturn efx_rc_t
-ef10_nvram_size(
- __in efx_nic_t *enp,
- __in efx_nvram_type_t type,
- __out size_t *sizep)
-{
- uint32_t partn;
- efx_rc_t rc;
-
- if ((rc = ef10_nvram_type_to_partn(enp, type, &partn)) != 0)
- goto fail1;
-
- if ((rc = ef10_nvram_partn_size(enp, partn, sizep)) != 0)
- goto fail2;
-
- return (0);
-
-fail2:
- EFSYS_PROBE(fail2);
-fail1:
- EFSYS_PROBE1(fail1, efx_rc_t, rc);
-
- *sizep = 0;
-
- return (rc);
-}
-
- __checkReturn efx_rc_t
ef10_nvram_get_version(
__in efx_nic_t *enp,
__in efx_nvram_type_t type,
@@ -1766,27 +1747,21 @@ fail1:
}
__checkReturn efx_rc_t
-ef10_nvram_rw_start(
+ef10_nvram_partn_rw_start(
__in efx_nic_t *enp,
- __in efx_nvram_type_t type,
+ __in uint32_t partn,
__out size_t *chunk_sizep)
{
- uint32_t partn;
efx_rc_t rc;
- if ((rc = ef10_nvram_type_to_partn(enp, type, &partn)) != 0)
- goto fail1;
-
if ((rc = ef10_nvram_partn_lock(enp, partn)) != 0)
- goto fail2;
+ goto fail1;
if (chunk_sizep != NULL)
*chunk_sizep = EF10_NVRAM_CHUNK;
return (0);
-fail2:
- EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
diff --git a/sys/dev/sfxge/common/hunt_phy.c b/sys/dev/sfxge/common/hunt_phy.c
index c25e8200c510..d0d709b2e637 100644
--- a/sys/dev/sfxge/common/hunt_phy.c
+++ b/sys/dev/sfxge/common/hunt_phy.c
@@ -219,7 +219,7 @@ fail1:
__checkReturn efx_rc_t
hunt_phy_get_link(
__in efx_nic_t *enp,
- __out hunt_link_state_t *hlsp)
+ __out ef10_link_state_t *elsp)
{
/*
* TBD: consider common Siena/Hunt function: Hunt is very similar
@@ -252,14 +252,14 @@ hunt_phy_get_link(
}
hunt_phy_decode_cap(MCDI_OUT_DWORD(req, GET_LINK_OUT_CAP),
- &hlsp->hls_adv_cap_mask);
+ &elsp->els_adv_cap_mask);
hunt_phy_decode_cap(MCDI_OUT_DWORD(req, GET_LINK_OUT_LP_CAP),
- &hlsp->hls_lp_cap_mask);
+ &elsp->els_lp_cap_mask);
hunt_phy_decode_link_mode(enp, MCDI_OUT_DWORD(req, GET_LINK_OUT_FLAGS),
MCDI_OUT_DWORD(req, GET_LINK_OUT_LINK_SPEED),
MCDI_OUT_DWORD(req, GET_LINK_OUT_FCNTL),
- &hlsp->hls_link_mode, &hlsp->hls_fcntl);
+ &elsp->els_link_mode, &elsp->els_fcntl);
#if EFSYS_OPT_LOOPBACK
/* Assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespace agree */
@@ -282,10 +282,10 @@ hunt_phy_get_link(
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PCS == EFX_LOOPBACK_PCS);
EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PMAPMD == EFX_LOOPBACK_PMA_PMD);
- hlsp->hls_loopback = MCDI_OUT_DWORD(req, GET_LINK_OUT_LOOPBACK_MODE);
+ elsp->els_loopback = MCDI_OUT_DWORD(req, GET_LINK_OUT_LOOPBACK_MODE);
#endif /* EFSYS_OPT_LOOPBACK */
- hlsp->hls_mac_up = MCDI_OUT_DWORD(req, GET_LINK_OUT_MAC_FAULT) == 0;
+ elsp->els_mac_up = MCDI_OUT_DWORD(req, GET_LINK_OUT_MAC_FAULT) == 0;
return (0);
diff --git a/sys/dev/sfxge/common/hunt_tx.c b/sys/dev/sfxge/common/hunt_tx.c
index 593db8835058..baa74443544a 100755
--- a/sys/dev/sfxge/common/hunt_tx.c
+++ b/sys/dev/sfxge/common/hunt_tx.c
@@ -87,12 +87,13 @@ efx_mcdi_init_txq(
MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_LABEL, label);
MCDI_IN_SET_DWORD(req, INIT_TXQ_IN_INSTANCE, instance);
- MCDI_IN_POPULATE_DWORD_6(req, INIT_TXQ_IN_FLAGS,
+ MCDI_IN_POPULATE_DWORD_7(req, INIT_TXQ_IN_FLAGS,
INIT_TXQ_IN_FLAG_BUFF_MODE, 0,
INIT_TXQ_IN_FLAG_IP_CSUM_DIS,
(flags & EFX_TXQ_CKSUM_IPV4) ? 0 : 1,
INIT_TXQ_IN_FLAG_TCP_CSUM_DIS,
(flags & EFX_TXQ_CKSUM_TCPUDP) ? 0 : 1,
+ INIT_TXQ_EXT_IN_FLAG_TSOV2_EN, (flags & EFX_TXQ_FATSOV2) ? 1 : 0,
INIT_TXQ_IN_FLAG_TCP_UDP_ONLY, 0,
INIT_TXQ_IN_CRC_MODE, 0,
INIT_TXQ_IN_FLAG_TIMESTAMP, 0);
@@ -589,6 +590,38 @@ hunt_tx_qdesc_tso_create(
}
void
+ef10_tx_qdesc_tso2_create(
+ __in efx_txq_t *etp,
+ __in uint16_t ipv4_id,
+ __in uint32_t tcp_seq,
+ __in uint16_t tcp_mss,
+ __out_ecount(count) efx_desc_t *edp,
+ __in int count)
+{
+ EFSYS_PROBE4(tx_desc_tso2_create, unsigned int, etp->et_index,
+ uint16_t, ipv4_id, uint32_t, tcp_seq,
+ uint16_t, tcp_mss);
+
+ EFSYS_ASSERT(count >= EFX_TX_FATSOV2_OPT_NDESCS);
+
+ EFX_POPULATE_QWORD_5(edp[0].ed_eq,
+ ESF_DZ_TX_DESC_IS_OPT, 1,
+ ESF_DZ_TX_OPTION_TYPE,
+ ESE_DZ_TX_OPTION_DESC_TSO,
+ ESF_DZ_TX_TSO_OPTION_TYPE,
+ ESE_DZ_TX_TSO_OPTION_DESC_FATSO2A,
+ ESF_DZ_TX_TSO_IP_ID, ipv4_id,
+ ESF_DZ_TX_TSO_TCP_SEQNO, tcp_seq);
+ EFX_POPULATE_QWORD_4(edp[1].ed_eq,
+ ESF_DZ_TX_DESC_IS_OPT, 1,
+ ESF_DZ_TX_OPTION_TYPE,
+ ESE_DZ_TX_OPTION_DESC_TSO,
+ ESF_DZ_TX_TSO_OPTION_TYPE,
+ ESE_DZ_TX_TSO_OPTION_DESC_FATSO2B,
+ ESF_DZ_TX_TSO_TCP_MSS, tcp_mss);
+}
+
+ void
ef10_tx_qdesc_vlantci_create(
__in efx_txq_t *etp,
__in uint16_t tci,
diff --git a/sys/dev/sfxge/common/hunt_vpd.c b/sys/dev/sfxge/common/hunt_vpd.c
index 58e9a66ac712..41b4b83fa381 100644
--- a/sys/dev/sfxge/common/hunt_vpd.c
+++ b/sys/dev/sfxge/common/hunt_vpd.c
@@ -48,13 +48,20 @@ ef10_vpd_init(
caddr_t svpd;
size_t svpd_size;
uint32_t pci_pf;
+ uint32_t tag;
efx_rc_t rc;
EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
enp->en_family == EFX_FAMILY_MEDFORD);
- pci_pf = enp->en_nic_cfg.enc_pf;
+ if (enp->en_nic_cfg.enc_vpd_is_global) {
+ tag = TLV_TAG_GLOBAL_STATIC_VPD;
+ } else {
+ pci_pf = enp->en_nic_cfg.enc_pf;
+ tag = TLV_TAG_PF_STATIC_VPD(pci_pf);
+ }
+
/*
* The VPD interface exposes VPD resources from the combined static and
* dynamic VPD storage. As the static VPD configuration should *never*
@@ -64,8 +71,7 @@ ef10_vpd_init(
svpd_size = 0;
rc = ef10_nvram_partn_read_tlv(enp,
NVRAM_PARTITION_TYPE_STATIC_CONFIG,
- TLV_TAG_PF_STATIC_VPD(pci_pf),
- &svpd, &svpd_size);
+ tag, &svpd, &svpd_size);
if (rc != 0) {
if (rc == EACCES) {
/* Unpriviledged functions cannot access VPD */
@@ -132,17 +138,22 @@ ef10_vpd_read(
caddr_t dvpd;
size_t dvpd_size;
uint32_t pci_pf;
+ uint32_t tag;
efx_rc_t rc;
EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
enp->en_family == EFX_FAMILY_MEDFORD);
- pci_pf = enp->en_nic_cfg.enc_pf;
+ if (enp->en_nic_cfg.enc_vpd_is_global) {
+ tag = TLV_TAG_GLOBAL_DYNAMIC_VPD;
+ } else {
+ pci_pf = enp->en_nic_cfg.enc_pf;
+ tag = TLV_TAG_PF_DYNAMIC_VPD(pci_pf);
+ }
if ((rc = ef10_nvram_partn_read_tlv(enp,
NVRAM_PARTITION_TYPE_DYNAMIC_CONFIG,
- TLV_TAG_PF_DYNAMIC_VPD(pci_pf),
- &dvpd, &dvpd_size)) != 0)
+ tag, &dvpd, &dvpd_size)) != 0)
goto fail1;
if (dvpd_size > size) {
@@ -210,6 +221,13 @@ ef10_vpd_verify(
if (dcont == 0)
break;
+ /*
+ * Skip the RV keyword. It should be present in both the static
+ * and dynamic cfg sectors.
+ */
+ if (dtag == EFX_VPD_RO && dkey == EFX_VPD_KEYWORD('R', 'V'))
+ continue;
+
scont = 0;
_NOTE(CONSTANTCONDITION)
while (1) {
@@ -389,12 +407,18 @@ ef10_vpd_write(
{
size_t vpd_length;
uint32_t pci_pf;
+ uint32_t tag;
efx_rc_t rc;
EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
enp->en_family == EFX_FAMILY_MEDFORD);
- pci_pf = enp->en_nic_cfg.enc_pf;
+ if (enp->en_nic_cfg.enc_vpd_is_global) {
+ tag = TLV_TAG_GLOBAL_DYNAMIC_VPD;
+ } else {
+ pci_pf = enp->en_nic_cfg.enc_pf;
+ tag = TLV_TAG_PF_DYNAMIC_VPD(pci_pf);
+ }
/* Determine total length of new dynamic VPD */
if ((rc = efx_vpd_hunk_length(data, size, &vpd_length)) != 0)
@@ -403,8 +427,7 @@ ef10_vpd_write(
/* Store new dynamic VPD in all segments in DYNAMIC_CONFIG partition */
if ((rc = ef10_nvram_partn_write_segment_tlv(enp,
NVRAM_PARTITION_TYPE_DYNAMIC_CONFIG,
- TLV_TAG_PF_DYNAMIC_VPD(pci_pf),
- data, vpd_length, B_TRUE)) != 0) {
+ tag, data, vpd_length, B_TRUE)) != 0) {
goto fail2;
}
diff --git a/sys/dev/sfxge/common/medford_impl.h b/sys/dev/sfxge/common/medford_impl.h
index 11084dc00f68..59ea35fb613d 100644
--- a/sys/dev/sfxge/common/medford_impl.h
+++ b/sys/dev/sfxge/common/medford_impl.h
@@ -37,7 +37,29 @@
extern "C" {
#endif
+/* Alignment requirement for value written to RX WPTR:
+ * the WPTR must be aligned to an 8 descriptor boundary
+ *
+ * FIXME: Is this the same on Medford as Huntington?
+ */
+#define MEDFORD_RX_WPTR_ALIGN 8
+
+
+
+#ifndef ER_EZ_TX_PIOBUF_SIZE
+#define ER_EZ_TX_PIOBUF_SIZE 4096
+#endif
+
+
#define MEDFORD_PIOBUF_NBUFS (16)
+#define MEDFORD_PIOBUF_SIZE (ER_EZ_TX_PIOBUF_SIZE)
+
+#define MEDFORD_MIN_PIO_ALLOC_SIZE (MEDFORD_PIOBUF_SIZE / 32)
+
+
+extern __checkReturn efx_rc_t
+medford_board_cfg(
+ __in efx_nic_t *enp);
#ifdef __cplusplus
diff --git a/sys/dev/sfxge/common/medford_nic.c b/sys/dev/sfxge/common/medford_nic.c
index 68c8184f5b18..21ba8e0c5967 100644
--- a/sys/dev/sfxge/common/medford_nic.c
+++ b/sys/dev/sfxge/common/medford_nic.c
@@ -39,7 +39,210 @@ __FBSDID("$FreeBSD$");
#include "ef10_tlv_layout.h"
+ __checkReturn efx_rc_t
+medford_board_cfg(
+ __in efx_nic_t *enp)
+{
+ efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
+ efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+ uint8_t mac_addr[6] = { 0 };
+ uint32_t board_type = 0;
+ ef10_link_state_t els;
+ efx_port_t *epp = &(enp->en_port);
+ uint32_t port;
+ uint32_t pf;
+ uint32_t vf;
+ uint32_t mask;
+ uint32_t flags;
+ uint32_t sysclk;
+ uint32_t base, nvec;
+ efx_rc_t rc;
+ /*
+ * FIXME: Likely to be incomplete and incorrect.
+ * Parts of this should be shared with Huntington.
+ */
+ if ((rc = efx_mcdi_get_port_assignment(enp, &port)) != 0)
+ goto fail1;
+
+ /*
+ * NOTE: The MCDI protocol numbers ports from zero.
+ * The common code MCDI interface numbers ports from one.
+ */
+ emip->emi_port = port + 1;
+
+ if ((rc = ef10_external_port_mapping(enp, port,
+ &encp->enc_external_port)) != 0)
+ goto fail2;
+
+ /*
+ * Get PCIe function number from firmware (used for
+ * per-function privilege and dynamic config info).
+ * - PCIe PF: pf = PF number, vf = 0xffff.
+ * - PCIe VF: pf = parent PF, vf = VF number.
+ */
+ if ((rc = efx_mcdi_get_function_info(enp, &pf, &vf)) != 0)
+ goto fail3;
+
+ encp->enc_pf = pf;
+ encp->enc_vf = vf;
+
+ /* MAC address for this function */
+ if (EFX_PCI_FUNCTION_IS_PF(encp)) {
+ rc = efx_mcdi_get_mac_address_pf(enp, mac_addr);
+ if ((rc == 0) && (mac_addr[0] & 0x02)) {
+ /*
+ * If the static config does not include a global MAC
+ * address pool then the board may return a locally
+ * administered MAC address (this should only happen on
+ * incorrectly programmed boards).
+ */
+ rc = EINVAL;
+ }
+ } else {
+ rc = efx_mcdi_get_mac_address_vf(enp, mac_addr);
+ }
+ if (rc != 0)
+ goto fail4;
+
+ EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr);
+
+ /* Board configuration */
+ rc = efx_mcdi_get_board_cfg(enp, &board_type, NULL, NULL);
+ if (rc != 0) {
+ /* Unprivileged functions may not be able to read board cfg */
+ if (rc == EACCES)
+ board_type = 0;
+ else
+ goto fail5;
+ }
+
+ encp->enc_board_type = board_type;
+ encp->enc_clk_mult = 1; /* not used for Medford */
+
+ /* Fill out fields in enp->en_port and enp->en_nic_cfg from MCDI */
+ if ((rc = efx_mcdi_get_phy_cfg(enp)) != 0)
+ goto fail6;
+
+ /* Obtain the default PHY advertised capabilities */
+ if ((rc = hunt_phy_get_link(enp, &els)) != 0)
+ goto fail7;
+ epp->ep_default_adv_cap_mask = els.els_adv_cap_mask;
+ epp->ep_adv_cap_mask = els.els_adv_cap_mask;
+
+ if (EFX_PCI_FUNCTION_IS_VF(encp)) {
+ /*
+ * Interrupt testing does not work for VFs. See bug50084.
+ * FIXME: Does this still apply to Medford?
+ */
+ encp->enc_bug41750_workaround = B_TRUE;
+ }
+
+ /* Chained multicast is always enabled on Medford */
+ encp->enc_bug26807_workaround = B_TRUE;
+
+ /* Get sysclk frequency (in MHz). */
+ if ((rc = efx_mcdi_get_clock(enp, &sysclk)) != 0)
+ goto fail8;
+
+ /*
+ * The timer quantum is 1536 sysclk cycles, documented for the
+ * EV_TMR_VAL field of EV_TIMER_TBL. Scale for MHz and ns units.
+ */
+ encp->enc_evq_timer_quantum_ns = 1536000UL / sysclk; /* 1536 cycles */
+ encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
+ FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000;
+
+ /* Check capabilities of running datapath firmware */
+ if ((rc = ef10_get_datapath_caps(enp)) != 0)
+ goto fail9;
+
+ /* Alignment for receive packet DMA buffers */
+ encp->enc_rx_buf_align_start = 1;
+
+ /* FIXME: RX DMA end padding is configurable on Medford */
+ encp->enc_rx_buf_align_end = 64;
+
+ /* Alignment for WPTR updates */
+ encp->enc_rx_push_align = EF10_RX_WPTR_ALIGN;
+
+ /*
+ * Set resource limits for MC_CMD_ALLOC_VIS. Note that we cannot use
+ * MC_CMD_GET_RESOURCE_LIMITS here as that reports the available
+ * resources (allocated to this PCIe function), which is zero until
+ * after we have allocated VIs.
+ */
+ encp->enc_evq_limit = 1024;
+ encp->enc_rxq_limit = EFX_RXQ_LIMIT_TARGET;
+ encp->enc_txq_limit = EFX_TXQ_LIMIT_TARGET;
+
+ encp->enc_buftbl_limit = 0xFFFFFFFF;
+
+ encp->enc_piobuf_limit = MEDFORD_PIOBUF_NBUFS;
+ encp->enc_piobuf_size = MEDFORD_PIOBUF_SIZE;
+ encp->enc_piobuf_min_alloc_size = MEDFORD_MIN_PIO_ALLOC_SIZE;
+
+ /*
+ * Get the current privilege mask. Note that this may be modified
+ * dynamically, so this value is informational only. DO NOT use
+ * the privilege mask to check for sufficient privileges, as that
+ * can result in time-of-check/time-of-use bugs.
+ */
+ if ((rc = ef10_get_privilege_mask(enp, &mask)) != 0)
+ goto fail10;
+ encp->enc_privilege_mask = mask;
+
+ /* Get interrupt vector limits */
+ if ((rc = efx_mcdi_get_vector_cfg(enp, &base, &nvec, NULL)) != 0) {
+ if (EFX_PCI_FUNCTION_IS_PF(encp))
+ goto fail11;
+
+ /* Ignore error (cannot query vector limits from a VF). */
+ base = 0;
+ nvec = 1024;
+ }
+ encp->enc_intr_vec_base = base;
+ encp->enc_intr_limit = nvec;
+
+ /*
+ * Maximum number of bytes into the frame the TCP header can start for
+ * firmware assisted TSO to work.
+ */
+ encp->enc_tx_tso_tcp_header_offset_limit = EF10_TCP_HEADER_OFFSET_LIMIT;
+
+ /*
+ * Medford stores a single global copy of VPD, not per-PF as on
+ * Huntington.
+ */
+ encp->enc_vpd_is_global = B_TRUE;
+
+ return (0);
+
+fail11:
+ EFSYS_PROBE(fail11);
+fail10:
+ EFSYS_PROBE(fail10);
+fail9:
+ EFSYS_PROBE(fail9);
+fail8:
+ EFSYS_PROBE(fail8);
+fail7:
+ EFSYS_PROBE(fail7);
+fail6:
+ EFSYS_PROBE(fail6);
+fail5:
+ EFSYS_PROBE(fail5);
+fail4:
+ EFSYS_PROBE(fail4);
+fail3:
+ EFSYS_PROBE(fail3);
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
#endif /* EFSYS_OPT_MEDFORD */
diff --git a/sys/dev/sfxge/common/siena_impl.h b/sys/dev/sfxge/common/siena_impl.h
index 639ac6b43fb7..95c15ff2c9ac 100644
--- a/sys/dev/sfxge/common/siena_impl.h
+++ b/sys/dev/sfxge/common/siena_impl.h
@@ -114,12 +114,12 @@ siena_mcdi_init(
__in const efx_mcdi_transport_t *mtp);
extern void
-siena_mcdi_request_copyin(
+siena_mcdi_send_request(
__in efx_nic_t *enp,
- __in efx_mcdi_req_t *emrp,
- __in unsigned int seq,
- __in boolean_t ev_cpl,
- __in boolean_t new_epoch);
+ __in void *hdrp,
+ __in size_t hdr_len,
+ __in void *sdup,
+ __in size_t sdu_len);
extern __checkReturn boolean_t
siena_mcdi_poll_response(
@@ -132,11 +132,6 @@ siena_mcdi_read_response(
__in size_t offset,
__in size_t length);
-extern void
-siena_mcdi_request_copyout(
- __in efx_nic_t *enp,
- __in efx_mcdi_req_t *emrp);
-
extern efx_rc_t
siena_mcdi_poll_reboot(
__in efx_nic_t *enp);
@@ -156,12 +151,6 @@ siena_mcdi_feature_supported(
#if EFSYS_OPT_NVRAM || EFSYS_OPT_VPD
extern __checkReturn efx_rc_t
-siena_nvram_partn_size(
- __in efx_nic_t *enp,
- __in uint32_t partn,
- __out size_t *sizep);
-
-extern __checkReturn efx_rc_t
siena_nvram_partn_lock(
__in efx_nic_t *enp,
__in uint32_t partn);
@@ -215,12 +204,6 @@ siena_nvram_test(
#endif /* EFSYS_OPT_DIAG */
extern __checkReturn efx_rc_t
-siena_nvram_size(
- __in efx_nic_t *enp,
- __in efx_nvram_type_t type,
- __out size_t *sizep);
-
-extern __checkReturn efx_rc_t
siena_nvram_get_subtype(
__in efx_nic_t *enp,
__in uint32_t partn,
@@ -234,12 +217,6 @@ siena_nvram_get_version(
__out_ecount(4) uint16_t version[4]);
extern __checkReturn efx_rc_t
-siena_nvram_rw_start(
- __in efx_nic_t *enp,
- __in efx_nvram_type_t type,
- __out size_t *pref_chunkp);
-
-extern __checkReturn efx_rc_t
siena_nvram_read_chunk(
__in efx_nic_t *enp,
__in efx_nvram_type_t type,
@@ -277,6 +254,18 @@ siena_nvram_type_to_partn(
__in efx_nvram_type_t type,
__out uint32_t *partnp);
+extern __checkReturn efx_rc_t
+siena_nvram_partn_size(
+ __in efx_nic_t *enp,
+ __in uint32_t partn,
+ __out size_t *sizep);
+
+extern __checkReturn efx_rc_t
+siena_nvram_partn_rw_start(
+ __in efx_nic_t *enp,
+ __in uint32_t partn,
+ __out size_t *chunk_sizep);
+
#endif /* EFSYS_OPT_NVRAM */
#if EFSYS_OPT_VPD
diff --git a/sys/dev/sfxge/common/siena_mcdi.c b/sys/dev/sfxge/common/siena_mcdi.c
index f3af2bf6f479..4fb2b6c8c87f 100644
--- a/sys/dev/sfxge/common/siena_mcdi.c
+++ b/sys/dev/sfxge/common/siena_mcdi.c
@@ -52,7 +52,7 @@ __FBSDID("$FreeBSD$");
: MC_SMEM_P1_STATUS_OFST >> 2)
-static void
+ void
siena_mcdi_send_request(
__in efx_nic_t *enp,
__in void *hdrp,
@@ -89,79 +89,6 @@ siena_mcdi_send_request(
EFX_BAR_TBL_WRITED(enp, FR_CZ_MC_TREG_SMEM, dbr, &dword, B_FALSE);
}
- void
-siena_mcdi_request_copyin(
- __in efx_nic_t *enp,
- __in efx_mcdi_req_t *emrp,
- __in unsigned int seq,
- __in boolean_t ev_cpl,
- __in boolean_t new_epoch)
-{
-#if EFSYS_OPT_MCDI_LOGGING
- const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp;
-#endif
- efx_dword_t hdr;
- size_t hdr_len;
- unsigned int xflags;
-
- EFSYS_ASSERT(enp->en_family == EFX_FAMILY_SIENA);
- _NOTE(ARGUNUSED(new_epoch))
-
- xflags = 0;
- if (ev_cpl)
- xflags |= MCDI_HEADER_XFLAGS_EVREQ;
-
- /* Construct the header */
- hdr_len = sizeof (hdr);
- EFX_POPULATE_DWORD_6(hdr,
- MCDI_HEADER_CODE, emrp->emr_cmd,
- MCDI_HEADER_RESYNC, 1,
- MCDI_HEADER_DATALEN, emrp->emr_in_length,
- MCDI_HEADER_SEQ, seq,
- MCDI_HEADER_RESPONSE, 0,
- MCDI_HEADER_XFLAGS, xflags);
-
-#if EFSYS_OPT_MCDI_LOGGING
- if (emtp->emt_logger != NULL) {
- emtp->emt_logger(emtp->emt_context, EFX_LOG_MCDI_REQUEST,
- &hdr, sizeof (hdr),
- emrp->emr_in_buf, emrp->emr_in_length);
- }
-#endif /* EFSYS_OPT_MCDI_LOGGING */
-
- siena_mcdi_send_request(enp, &hdr, hdr_len,
- emrp->emr_in_buf, emrp->emr_in_length);
-}
-
- void
-siena_mcdi_request_copyout(
- __in efx_nic_t *enp,
- __in efx_mcdi_req_t *emrp)
-{
-#if EFSYS_OPT_MCDI_LOGGING
- const efx_mcdi_transport_t *emtp = enp->en_mcdi.em_emtp;
- efx_dword_t hdr;
-#endif
- size_t bytes = MIN(emrp->emr_out_length_used, emrp->emr_out_length);
-
- /* Copy payload out if caller supplied buffer */
- if (emrp->emr_out_buf != NULL) {
- siena_mcdi_read_response(enp, emrp->emr_out_buf,
- sizeof (efx_dword_t), bytes);
- }
-
-#if EFSYS_OPT_MCDI_LOGGING
- if (emtp->emt_logger != NULL) {
- siena_mcdi_read_response(enp, &hdr, 0, sizeof (hdr));
-
- emtp->emt_logger(emtp->emt_context,
- EFX_LOG_MCDI_RESPONSE,
- &hdr, sizeof (hdr),
- emrp->emr_out_buf, bytes);
- }
-#endif /* EFSYS_OPT_MCDI_LOGGING */
-}
-
efx_rc_t
siena_mcdi_poll_reboot(
__in efx_nic_t *enp)
diff --git a/sys/dev/sfxge/common/siena_nic.c b/sys/dev/sfxge/common/siena_nic.c
index 70e7b5d1ccad..59e12833160c 100644
--- a/sys/dev/sfxge/common/siena_nic.c
+++ b/sys/dev/sfxge/common/siena_nic.c
@@ -169,6 +169,7 @@ siena_board_cfg(
encp->enc_hw_tx_insert_vlan_enabled = B_FALSE;
encp->enc_fw_assisted_tso_enabled = B_FALSE;
+ encp->enc_fw_assisted_tso_v2_enabled = B_FALSE;
encp->enc_allow_set_mac_with_installed_filters = B_TRUE;
return (0);
diff --git a/sys/dev/sfxge/common/siena_nvram.c b/sys/dev/sfxge/common/siena_nvram.c
index 8f107b49f61b..67e689ab4436 100644
--- a/sys/dev/sfxge/common/siena_nvram.c
+++ b/sys/dev/sfxge/common/siena_nvram.c
@@ -227,6 +227,8 @@ static siena_parttbl_entry_t siena_parttbl[] = {
{MC_CMD_NVRAM_TYPE_FC_FW, 2, EFX_NVRAM_FCFW},
{MC_CMD_NVRAM_TYPE_CPLD, 1, EFX_NVRAM_CPLD},
{MC_CMD_NVRAM_TYPE_CPLD, 2, EFX_NVRAM_CPLD},
+ {MC_CMD_NVRAM_TYPE_LICENSE, 1, EFX_NVRAM_LICENSE},
+ {MC_CMD_NVRAM_TYPE_LICENSE, 2, EFX_NVRAM_LICENSE}
};
__checkReturn efx_rc_t
@@ -291,32 +293,6 @@ fail1:
#endif /* EFSYS_OPT_DIAG */
- __checkReturn efx_rc_t
-siena_nvram_size(
- __in efx_nic_t *enp,
- __in efx_nvram_type_t type,
- __out size_t *sizep)
-{
- uint32_t partn;
- efx_rc_t rc;
-
- if ((rc = siena_nvram_type_to_partn(enp, type, &partn)) != 0)
- goto fail1;
-
- if ((rc = siena_nvram_partn_size(enp, partn, sizep)) != 0)
- goto fail2;
-
- return (0);
-
-fail2:
- EFSYS_PROBE(fail2);
-fail1:
- EFSYS_PROBE1(fail1, efx_rc_t, rc);
-
- *sizep = 0;
-
- return (rc);
-}
#define SIENA_DYNAMIC_CFG_SIZE(_nitems) \
(sizeof (siena_mc_dynamic_config_hdr_t) + ((_nitems) * \
@@ -596,27 +572,21 @@ fail1:
}
__checkReturn efx_rc_t
-siena_nvram_rw_start(
+siena_nvram_partn_rw_start(
__in efx_nic_t *enp,
- __in efx_nvram_type_t type,
+ __in uint32_t partn,
__out size_t *chunk_sizep)
{
- uint32_t partn;
efx_rc_t rc;
- if ((rc = siena_nvram_type_to_partn(enp, type, &partn)) != 0)
- goto fail1;
-
if ((rc = siena_nvram_partn_lock(enp, partn)) != 0)
- goto fail2;
+ goto fail1;
if (chunk_sizep != NULL)
*chunk_sizep = SIENA_NVRAM_CHUNK;
return (0);
-fail2:
- EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
diff --git a/sys/dev/sfxge/common/siena_vpd.c b/sys/dev/sfxge/common/siena_vpd.c
index 9a07f9130e00..7a7ce675ef56 100644
--- a/sys/dev/sfxge/common/siena_vpd.c
+++ b/sys/dev/sfxge/common/siena_vpd.c
@@ -326,6 +326,13 @@ siena_vpd_verify(
if (dcont == 0)
break;
+ /*
+ * Skip the RV keyword. It should be present in both the static
+ * and dynamic cfg sectors.
+ */
+ if (dtag == EFX_VPD_RO && dkey == EFX_VPD_KEYWORD('R', 'V'))
+ continue;
+
scont = 0;
_NOTE(CONSTANTCONDITION)
while (1) {
diff --git a/sys/dev/sfxge/sfxge.h b/sys/dev/sfxge/sfxge.h
index fbe0bd4542dd..9ff84c03a0b7 100644
--- a/sys/dev/sfxge/sfxge.h
+++ b/sys/dev/sfxge/sfxge.h
@@ -280,7 +280,10 @@ struct sfxge_softc {
unsigned int rxq_count;
unsigned int txq_count;
- int tso_fw_assisted;
+ unsigned int tso_fw_assisted;
+#define SFXGE_FATSOV1 (1 << 0)
+#define SFXGE_FATSOV2 (1 << 1)
+
#if EFSYS_OPT_MCDI_LOGGING
int mcdi_logging;
#endif
diff --git a/sys/dev/sfxge/sfxge_tx.c b/sys/dev/sfxge/sfxge_tx.c
index 1ffb4bedd0cf..9cf5c79a8213 100644
--- a/sys/dev/sfxge/sfxge_tx.c
+++ b/sys/dev/sfxge/sfxge_tx.c
@@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <sys/syslog.h>
+#include <sys/limits.h>
#include <net/bpf.h>
#include <net/ethernet.h>
@@ -96,11 +97,11 @@ SYSCTL_INT(_hw_sfxge, OID_AUTO, tx_dpl_put_max, CTLFLAG_RDTUN,
"Maximum number of any packets in deferred packet put-list");
#define SFXGE_PARAM_TSO_FW_ASSISTED SFXGE_PARAM(tso_fw_assisted)
-static int sfxge_tso_fw_assisted = 1;
+static int sfxge_tso_fw_assisted = (SFXGE_FATSOV1 | SFXGE_FATSOV2);
TUNABLE_INT(SFXGE_PARAM_TSO_FW_ASSISTED, &sfxge_tso_fw_assisted);
SYSCTL_INT(_hw_sfxge, OID_AUTO, tso_fw_assisted, CTLFLAG_RDTUN,
&sfxge_tso_fw_assisted, 0,
- "Use FW-assisted TSO if supported by NIC firmware");
+ "Bitmask of FW-assisted TSO allowed to use if supported by NIC firmware");
static const struct {
@@ -850,6 +851,8 @@ struct sfxge_tso_state {
unsigned out_len; /* Remaining length in current segment */
unsigned seqnum; /* Current sequence number */
unsigned packet_space; /* Remaining space in current packet */
+ unsigned segs_space; /* Remaining number of DMA segments
+ for the packet (FATSOv2 only) */
/* Input position */
uint64_t dma_addr; /* DMA address of current position */
@@ -952,7 +955,7 @@ static void tso_start(struct sfxge_txq *txq, struct sfxge_tso_state *tso,
struct tcphdr th_copy;
#endif
- tso->fw_assisted = txq->sc->tso_fw_assisted;
+ tso->fw_assisted = txq->tso_fw_assisted;
tso->mbuf = mbuf;
/* Find network protocol and header */
@@ -1059,6 +1062,8 @@ static void tso_fill_packet_with_fragment(struct sfxge_txq *txq,
{
efx_desc_t *desc;
int n;
+ uint64_t dma_addr = tso->dma_addr;
+ boolean_t eop;
if (tso->in_len == 0 || tso->packet_space == 0)
return;
@@ -1066,20 +1071,38 @@ static void tso_fill_packet_with_fragment(struct sfxge_txq *txq,
KASSERT(tso->in_len > 0, ("TSO input length went negative"));
KASSERT(tso->packet_space > 0, ("TSO packet space went negative"));
- n = min(tso->in_len, tso->packet_space);
+ if (tso->fw_assisted & SFXGE_FATSOV2) {
+ n = tso->in_len;
+ tso->out_len -= n;
+ tso->seqnum += n;
+ tso->in_len = 0;
+ if (n < tso->packet_space) {
+ tso->packet_space -= n;
+ tso->segs_space--;
+ } else {
+ tso->packet_space = tso->seg_size -
+ (n - tso->packet_space) % tso->seg_size;
+ tso->segs_space =
+ EFX_TX_FATSOV2_DMA_SEGS_PER_PKT_MAX - 1 -
+ (tso->packet_space != tso->seg_size);
+ }
+ } else {
+ n = min(tso->in_len, tso->packet_space);
+ tso->packet_space -= n;
+ tso->out_len -= n;
+ tso->dma_addr += n;
+ tso->in_len -= n;
+ }
- tso->packet_space -= n;
- tso->out_len -= n;
- tso->in_len -= n;
+ /*
+ * It is OK to use binary OR below to avoid extra branching
+ * since all conditions may always be checked.
+ */
+ eop = (tso->out_len == 0) | (tso->packet_space == 0) |
+ (tso->segs_space == 0);
desc = &txq->pend_desc[txq->n_pend_desc++];
- efx_tx_qdesc_dma_create(txq->common,
- tso->dma_addr,
- n,
- tso->out_len == 0 || tso->packet_space == 0,
- desc);
-
- tso->dma_addr += n;
+ efx_tx_qdesc_dma_create(txq->common, dma_addr, n, eop, desc);
}
/* Callback from bus_dmamap_load() for long TSO headers. */
@@ -1112,28 +1135,47 @@ static int tso_start_new_packet(struct sfxge_txq *txq,
int rc;
if (tso->fw_assisted) {
- uint8_t tcp_flags = tso->tcp_flags;
-
- if (tso->out_len > tso->seg_size)
- tcp_flags &= ~(TH_FIN | TH_PUSH);
-
- /* TSO option descriptor */
- desc = &txq->pend_desc[txq->n_pend_desc++];
- efx_tx_qdesc_tso_create(txq->common,
- tso->packet_id,
- tso->seqnum,
- tcp_flags,
- desc++);
- KASSERT(txq->stmp[id].flags == 0, ("stmp flags are not 0"));
- id = (id + 1) & txq->ptr_mask;
+ if (tso->fw_assisted & SFXGE_FATSOV2) {
+ /* Add 2 FATSOv2 option descriptors */
+ desc = &txq->pend_desc[txq->n_pend_desc];
+ efx_tx_qdesc_tso2_create(txq->common,
+ tso->packet_id,
+ tso->seqnum,
+ tso->seg_size,
+ desc,
+ EFX_TX_FATSOV2_OPT_NDESCS);
+ desc += EFX_TX_FATSOV2_OPT_NDESCS;
+ txq->n_pend_desc += EFX_TX_FATSOV2_OPT_NDESCS;
+ KASSERT(txq->stmp[id].flags == 0, ("stmp flags are not 0"));
+ id = (id + EFX_TX_FATSOV2_OPT_NDESCS) & txq->ptr_mask;
+
+ tso->segs_space =
+ EFX_TX_FATSOV2_DMA_SEGS_PER_PKT_MAX - 1;
+ } else {
+ uint8_t tcp_flags = tso->tcp_flags;
+
+ if (tso->out_len > tso->seg_size)
+ tcp_flags &= ~(TH_FIN | TH_PUSH);
+
+ /* Add FATSOv1 option descriptor */
+ desc = &txq->pend_desc[txq->n_pend_desc++];
+ efx_tx_qdesc_tso_create(txq->common,
+ tso->packet_id,
+ tso->seqnum,
+ tcp_flags,
+ desc++);
+ KASSERT(txq->stmp[id].flags == 0, ("stmp flags are not 0"));
+ id = (id + 1) & txq->ptr_mask;
+
+ tso->seqnum += tso->seg_size;
+ tso->segs_space = UINT_MAX;
+ }
/* Header DMA descriptor */
*desc = tso->header_desc;
txq->n_pend_desc++;
KASSERT(txq->stmp[id].flags == 0, ("stmp flags are not 0"));
id = (id + 1) & txq->ptr_mask;
-
- tso->seqnum += tso->seg_size;
} else {
/* Allocate a DMA-mapped header buffer. */
if (__predict_true(tso->header_len <= TSOH_STD_SIZE)) {
@@ -1215,6 +1257,8 @@ static int tso_start_new_packet(struct sfxge_txq *txq,
0,
desc);
id = (id + 1) & txq->ptr_mask;
+
+ tso->segs_space = UINT_MAX;
}
tso->packet_space = tso->seg_size;
txq->tso_packets++;
@@ -1264,15 +1308,19 @@ sfxge_tx_queue_tso(struct sfxge_txq *txq, struct mbuf *mbuf,
}
/* End of packet? */
- if (tso.packet_space == 0) {
+ if ((tso.packet_space == 0) | (tso.segs_space == 0)) {
+ unsigned int n_fatso_opt_desc =
+ (tso.fw_assisted & SFXGE_FATSOV2) ?
+ EFX_TX_FATSOV2_OPT_NDESCS :
+ (tso.fw_assisted & SFXGE_FATSOV1) ? 1 : 0;
+
/* If the queue is now full due to tiny MSS,
* or we can't create another header, discard
* the remainder of the input mbuf but do not
* roll back the work we have done.
*/
- if (txq->n_pend_desc + tso.fw_assisted +
- 1 /* header */ + n_dma_seg >
- txq->max_pkt_desc) {
+ if (txq->n_pend_desc + n_fatso_opt_desc +
+ 1 /* header */ + n_dma_seg > txq->max_pkt_desc) {
txq->tso_pdrop_too_many++;
break;
}
@@ -1407,12 +1455,67 @@ sfxge_tx_qstop(struct sfxge_softc *sc, unsigned int index)
SFXGE_TXQ_UNLOCK(txq);
}
+/*
+ * Estimate maximum number of Tx descriptors required for TSO packet.
+ * With minimum MSS and maximum mbuf length we might need more (even
+ * than a ring-ful of descriptors), but this should not happen in
+ * practice except due to deliberate attack. In that case we will
+ * truncate the output at a packet boundary.
+ */
+static unsigned int
+sfxge_tx_max_pkt_desc(const struct sfxge_softc *sc, enum sfxge_txq_type type,
+ unsigned int tso_fw_assisted)
+{
+ /* One descriptor for every input fragment */
+ unsigned int max_descs = SFXGE_TX_MAPPING_MAX_SEG;
+ unsigned int sw_tso_max_descs;
+ unsigned int fa_tso_v1_max_descs = 0;
+ unsigned int fa_tso_v2_max_descs = 0;
+
+ /* VLAN tagging Tx option descriptor may be required */
+ if (efx_nic_cfg_get(sc->enp)->enc_hw_tx_insert_vlan_enabled)
+ max_descs++;
+
+ if (type == SFXGE_TXQ_IP_TCP_UDP_CKSUM) {
+ /*
+ * Plus header and payload descriptor for each output segment.
+ * Minus one since header fragment is already counted.
+ * Even if FATSO is used, we should be ready to fallback
+ * to do it in the driver.
+ */
+ sw_tso_max_descs = SFXGE_TSO_MAX_SEGS * 2 - 1;
+
+ /* FW assisted TSOv1 requires one more descriptor per segment
+ * in comparison to SW TSO */
+ if (tso_fw_assisted & SFXGE_FATSOV1)
+ fa_tso_v1_max_descs =
+ sw_tso_max_descs + SFXGE_TSO_MAX_SEGS;
+
+ /* FW assisted TSOv2 requires 3 (2 FATSO plus header) extra
+ * descriptors per superframe limited by number of DMA fetches
+ * per packet. The first packet header is already counted.
+ */
+ if (tso_fw_assisted & SFXGE_FATSOV2) {
+ fa_tso_v2_max_descs =
+ howmany(SFXGE_TX_MAPPING_MAX_SEG,
+ EFX_TX_FATSOV2_DMA_SEGS_PER_PKT_MAX - 1) *
+ (EFX_TX_FATSOV2_OPT_NDESCS + 1) - 1;
+ }
+
+ max_descs += MAX(sw_tso_max_descs,
+ MAX(fa_tso_v1_max_descs, fa_tso_v2_max_descs));
+ }
+
+ return (max_descs);
+}
+
static int
sfxge_tx_qstart(struct sfxge_softc *sc, unsigned int index)
{
struct sfxge_txq *txq;
efsys_mem_t *esmp;
uint16_t flags;
+ unsigned int tso_fw_assisted;
struct sfxge_evq *evq;
unsigned int desc_index;
int rc;
@@ -1434,6 +1537,7 @@ sfxge_tx_qstart(struct sfxge_softc *sc, unsigned int index)
return (rc);
/* Determine the kind of queue we are creating. */
+ tso_fw_assisted = 0;
switch (txq->type) {
case SFXGE_TXQ_NON_CKSUM:
flags = 0;
@@ -1443,6 +1547,9 @@ sfxge_tx_qstart(struct sfxge_softc *sc, unsigned int index)
break;
case SFXGE_TXQ_IP_TCP_UDP_CKSUM:
flags = EFX_TXQ_CKSUM_IPV4 | EFX_TXQ_CKSUM_TCPUDP;
+ tso_fw_assisted = sc->tso_fw_assisted;
+ if (tso_fw_assisted & SFXGE_FATSOV2)
+ flags |= EFX_TXQ_FATSOV2;
break;
default:
KASSERT(0, ("Impossible TX queue"));
@@ -1453,8 +1560,19 @@ sfxge_tx_qstart(struct sfxge_softc *sc, unsigned int index)
/* Create the common code transmit queue. */
if ((rc = efx_tx_qcreate(sc->enp, index, txq->type, esmp,
sc->txq_entries, txq->buf_base_id, flags, evq->common,
- &txq->common, &desc_index)) != 0)
- goto fail;
+ &txq->common, &desc_index)) != 0) {
+ /* Retry if no FATSOv2 resources, otherwise fail */
+ if ((rc != ENOSPC) || (~flags & EFX_TXQ_FATSOV2))
+ goto fail;
+
+ /* Looks like all FATSOv2 contexts are used */
+ flags &= ~EFX_TXQ_FATSOV2;
+ tso_fw_assisted &= ~SFXGE_FATSOV2;
+ if ((rc = efx_tx_qcreate(sc->enp, index, txq->type, esmp,
+ sc->txq_entries, txq->buf_base_id, flags, evq->common,
+ &txq->common, &desc_index)) != 0)
+ goto fail;
+ }
/* Initialise queue descriptor indexes */
txq->added = txq->pending = txq->completed = txq->reaped = desc_index;
@@ -1466,6 +1584,10 @@ sfxge_tx_qstart(struct sfxge_softc *sc, unsigned int index)
txq->init_state = SFXGE_TXQ_STARTED;
txq->flush_state = SFXGE_FLUSH_REQUIRED;
+ txq->tso_fw_assisted = tso_fw_assisted;
+
+ txq->max_pkt_desc = sfxge_tx_max_pkt_desc(sc, txq->type,
+ tso_fw_assisted);
SFXGE_TXQ_UNLOCK(txq);
@@ -1574,38 +1696,6 @@ sfxge_tx_qfini(struct sfxge_softc *sc, unsigned int index)
free(txq, M_SFXGE);
}
-/*
- * Estimate maximum number of Tx descriptors required for TSO packet.
- * With minimum MSS and maximum mbuf length we might need more (even
- * than a ring-ful of descriptors), but this should not happen in
- * practice except due to deliberate attack. In that case we will
- * truncate the output at a packet boundary.
- */
-static unsigned int
-sfxge_tx_max_pkt_desc(const struct sfxge_softc *sc, enum sfxge_txq_type type)
-{
- /* One descriptor for every input fragment */
- unsigned int max_descs = SFXGE_TX_MAPPING_MAX_SEG;
-
- /* VLAN tagging Tx option descriptor may be required */
- if (efx_nic_cfg_get(sc->enp)->enc_hw_tx_insert_vlan_enabled)
- max_descs++;
-
- if (type == SFXGE_TXQ_IP_TCP_UDP_CKSUM) {
- /*
- * Plus header and payload descriptor for each output segment.
- * Minus one since header fragment is already counted.
- */
- max_descs += SFXGE_TSO_MAX_SEGS * 2 - 1;
-
- /* FW assisted TSO requires one more descriptor per segment */
- if (sc->tso_fw_assisted)
- max_descs += SFXGE_TSO_MAX_SEGS;
- }
-
- return (max_descs);
-}
-
static int
sfxge_tx_qinit(struct sfxge_softc *sc, unsigned int txq_index,
enum sfxge_txq_type type, unsigned int evq_index)
@@ -1735,8 +1825,6 @@ sfxge_tx_qinit(struct sfxge_softc *sc, unsigned int txq_index,
txq->init_state = SFXGE_TXQ_INITIALIZED;
txq->hw_vlan_tci = 0;
- txq->max_pkt_desc = sfxge_tx_max_pkt_desc(sc, type);
-
return (0);
fail_txq_stat_init:
@@ -1846,10 +1934,12 @@ sfxge_tx_init(struct sfxge_softc *sc)
sc->txq_count = SFXGE_TXQ_NTYPES - 1 + sc->intr.n_alloc;
sc->tso_fw_assisted = sfxge_tso_fw_assisted;
- if (sc->tso_fw_assisted)
- sc->tso_fw_assisted =
- (encp->enc_features & EFX_FEATURE_FW_ASSISTED_TSO) &&
- (encp->enc_fw_assisted_tso_enabled);
+ if ((~encp->enc_features & EFX_FEATURE_FW_ASSISTED_TSO) ||
+ (!encp->enc_fw_assisted_tso_enabled))
+ sc->tso_fw_assisted &= ~SFXGE_FATSOV1;
+ if ((~encp->enc_features & EFX_FEATURE_FW_ASSISTED_TSO_V2) ||
+ (!encp->enc_fw_assisted_tso_v2_enabled))
+ sc->tso_fw_assisted &= ~SFXGE_FATSOV2;
sc->txqs_node = SYSCTL_ADD_NODE(
device_get_sysctl_ctx(sc->dev),
diff --git a/sys/dev/sfxge/sfxge_tx.h b/sys/dev/sfxge/sfxge_tx.h
index a18fdb7ce6a0..c24aee13ad50 100644
--- a/sys/dev/sfxge/sfxge_tx.h
+++ b/sys/dev/sfxge/sfxge_tx.h
@@ -170,6 +170,7 @@ struct sfxge_txq {
struct sfxge_softc *sc;
enum sfxge_txq_state init_state;
enum sfxge_flush_state flush_state;
+ unsigned int tso_fw_assisted;
enum sfxge_txq_type type;
unsigned int txq_index;
unsigned int evq_index;
diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c
index 8940171459a0..2976fec70be2 100644
--- a/sys/dev/usb/usb_device.c
+++ b/sys/dev/usb/usb_device.c
@@ -1962,6 +1962,7 @@ usb_make_dev(struct usb_device *udev, const char *devname, int ep,
int fi, int rwmode, uid_t uid, gid_t gid, int mode)
{
struct usb_fs_privdata* pd;
+ struct make_dev_args args;
char buffer[32];
/* Store information to locate ourselves again later */
@@ -1980,17 +1981,19 @@ usb_make_dev(struct usb_device *udev, const char *devname, int ep,
pd->bus_index, pd->dev_index, pd->ep_addr);
}
- pd->cdev = make_dev(&usb_devsw, 0, uid, gid, mode, "%s", devname);
+ /* Setup arguments for make_dev_s() */
+ make_dev_args_init(&args);
+ args.mda_devsw = &usb_devsw;
+ args.mda_uid = uid;
+ args.mda_gid = gid;
+ args.mda_mode = mode;
+ args.mda_si_drv1 = pd;
- if (pd->cdev == NULL) {
+ if (make_dev_s(&args, &pd->cdev, "%s", devname) != 0) {
DPRINTFN(0, "Failed to create device %s\n", devname);
free(pd, M_USBDEV);
return (NULL);
}
-
- /* XXX setting si_drv1 and creating the device is not atomic! */
- pd->cdev->si_drv1 = pd;
-
return (pd);
}
diff --git a/sys/fs/nfs/nfs_var.h b/sys/fs/nfs/nfs_var.h
index 23475b29e141..3b494a51fa88 100644
--- a/sys/fs/nfs/nfs_var.h
+++ b/sys/fs/nfs/nfs_var.h
@@ -306,7 +306,7 @@ void nfscl_reqstart(struct nfsrv_descript *, int, struct nfsmount *,
nfsuint64 *nfscl_getcookie(struct nfsnode *, off_t off, int);
void nfscl_fillsattr(struct nfsrv_descript *, struct vattr *,
vnode_t, int, u_int32_t);
-u_int8_t *nfscl_getmyip(struct nfsmount *, int *);
+u_int8_t *nfscl_getmyip(struct nfsmount *, struct in6_addr *, int *);
int nfsm_getfh(struct nfsrv_descript *, struct nfsfh **);
int nfscl_mtofh(struct nfsrv_descript *, struct nfsfh **,
struct nfsvattr *, int *);
diff --git a/sys/fs/nfsclient/nfs_clport.c b/sys/fs/nfsclient/nfs_clport.c
index cdccbc897c61..44085066216f 100644
--- a/sys/fs/nfsclient/nfs_clport.c
+++ b/sys/fs/nfsclient/nfs_clport.c
@@ -34,6 +34,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_inet.h"
#include "opt_inet6.h"
#include <sys/capsicum.h>
@@ -46,7 +47,9 @@ __FBSDID("$FreeBSD$");
#include <sys/hash.h>
#include <sys/sysctl.h>
#include <fs/nfs/nfsport.h>
+#include <netinet/in_fib.h>
#include <netinet/if_ether.h>
+#include <netinet6/ip6_var.h>
#include <net/if_types.h>
#include <fs/nfsclient/nfs_kdtrace.h>
@@ -1038,73 +1041,66 @@ nfscl_loadfsinfo(struct nfsmount *nmp, struct nfsfsinfo *fsp)
}
/*
- * Get a pointer to my IP addrress and return it.
- * Return NULL if you can't find one.
+ * Lookups source address which should be used to communicate with
+ * @nmp and stores it inside @pdst.
+ *
+ * Returns 0 on success.
*/
u_int8_t *
-nfscl_getmyip(struct nfsmount *nmp, int *isinet6p)
+nfscl_getmyip(struct nfsmount *nmp, struct in6_addr *paddr, int *isinet6p)
{
- struct sockaddr_in sad, *sin;
- struct rtentry *rt;
- u_int8_t *retp = NULL;
- static struct in_addr laddr;
+ int error, fibnum;
- *isinet6p = 0;
- /*
- * Loop up a route for the destination address.
- */
+ fibnum = curthread->td_proc->p_fibnum;
+
+#ifdef INET
if (nmp->nm_nam->sa_family == AF_INET) {
- bzero(&sad, sizeof (sad));
+ struct sockaddr_in *sin;
+ struct nhop4_extended nh_ext;
+
sin = (struct sockaddr_in *)nmp->nm_nam;
- sad.sin_family = AF_INET;
- sad.sin_len = sizeof (struct sockaddr_in);
- sad.sin_addr.s_addr = sin->sin_addr.s_addr;
CURVNET_SET(CRED_TO_VNET(nmp->nm_sockreq.nr_cred));
- rt = rtalloc1_fib((struct sockaddr *)&sad, 0, 0UL,
- curthread->td_proc->p_fibnum);
- if (rt != NULL) {
- if (rt->rt_ifp != NULL &&
- rt->rt_ifa != NULL &&
- ((rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0) &&
- rt->rt_ifa->ifa_addr->sa_family == AF_INET) {
- sin = (struct sockaddr_in *)
- rt->rt_ifa->ifa_addr;
- laddr.s_addr = sin->sin_addr.s_addr;
- retp = (u_int8_t *)&laddr;
- }
- RTFREE_LOCKED(rt);
- }
+ error = fib4_lookup_nh_ext(fibnum, sin->sin_addr, 0, 0,
+ &nh_ext);
CURVNET_RESTORE();
+ if (error != 0)
+ return (NULL);
+
+ if ((ntohl(nh_ext.nh_src.s_addr) >> IN_CLASSA_NSHIFT) ==
+ IN_LOOPBACKNET) {
+ /* Ignore loopback addresses */
+ return (NULL);
+ }
+
+ *isinet6p = 0;
+ *((struct in_addr *)paddr) = nh_ext.nh_src;
+
+ return (u_int8_t *)paddr;
+ }
+#endif
#ifdef INET6
- } else if (nmp->nm_nam->sa_family == AF_INET6) {
- struct sockaddr_in6 sad6, *sin6;
- static struct in6_addr laddr6;
+ if (nmp->nm_nam->sa_family == AF_INET6) {
+ struct sockaddr_in6 *sin6;
- bzero(&sad6, sizeof (sad6));
sin6 = (struct sockaddr_in6 *)nmp->nm_nam;
- sad6.sin6_family = AF_INET6;
- sad6.sin6_len = sizeof (struct sockaddr_in6);
- sad6.sin6_addr = sin6->sin6_addr;
+
CURVNET_SET(CRED_TO_VNET(nmp->nm_sockreq.nr_cred));
- rt = rtalloc1_fib((struct sockaddr *)&sad6, 0, 0UL,
- curthread->td_proc->p_fibnum);
- if (rt != NULL) {
- if (rt->rt_ifp != NULL &&
- rt->rt_ifa != NULL &&
- ((rt->rt_ifp->if_flags & IFF_LOOPBACK) == 0) &&
- rt->rt_ifa->ifa_addr->sa_family == AF_INET6) {
- sin6 = (struct sockaddr_in6 *)
- rt->rt_ifa->ifa_addr;
- laddr6 = sin6->sin6_addr;
- retp = (u_int8_t *)&laddr6;
- *isinet6p = 1;
- }
- RTFREE_LOCKED(rt);
- }
+ error = in6_selectsrc_addr(fibnum, &sin6->sin6_addr,
+ sin6->sin6_scope_id, NULL, paddr, NULL);
CURVNET_RESTORE();
-#endif
+ if (error != 0)
+ return (NULL);
+
+ if (IN6_IS_ADDR_LOOPBACK(paddr))
+ return (NULL);
+
+ /* Scope is embedded in */
+ *isinet6p = 1;
+
+ return (u_int8_t *)paddr;
}
- return (retp);
+#endif
+ return (NULL);
}
/*
diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c
index 710994442ff1..a7d47f0ab9e0 100644
--- a/sys/fs/nfsclient/nfs_clrpcops.c
+++ b/sys/fs/nfsclient/nfs_clrpcops.c
@@ -829,6 +829,7 @@ nfsrpc_setclient(struct nfsmount *nmp, struct nfsclclient *clp, int reclaim,
u_int32_t lease;
static u_int32_t rev = 0;
struct nfsclds *dsp, *ndsp, *tdsp;
+ struct in6_addr a6;
if (nfsboottime.tv_sec == 0)
NFSSETBOOTTIME(nfsboottime);
@@ -889,7 +890,7 @@ nfsrpc_setclient(struct nfsmount *nmp, struct nfsclclient *clp, int reclaim,
*tl = txdr_unsigned(NFS_CALLBCKPROG);
callblen = strlen(nfsv4_callbackaddr);
if (callblen == 0)
- cp = nfscl_getmyip(nmp, &isinet6);
+ cp = nfscl_getmyip(nmp, &a6, &isinet6);
if (nfscl_enablecallb && nfs_numnfscbd > 0 &&
(callblen > 0 || cp != NULL)) {
port = htons(nfsv4_cbport);
diff --git a/sys/geom/geom_disk.c b/sys/geom/geom_disk.c
index 1943430985ff..afd1fdef7a81 100644
--- a/sys/geom/geom_disk.c
+++ b/sys/geom/geom_disk.c
@@ -549,6 +549,23 @@ g_disk_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, struct g
indent, dp->d_fwheads);
sbuf_printf(sb, "%s<fwsectors>%u</fwsectors>\n",
indent, dp->d_fwsectors);
+
+ /*
+ * "rotationrate" is a little complicated, because the value
+ * returned by the drive might not be the RPM; 0 and 1 are
+ * special cases, and there's also a valid range.
+ */
+ sbuf_printf(sb, "%s<rotationrate>", indent);
+ if (dp->d_rotation_rate == 0) /* Old drives don't */
+ sbuf_printf(sb, "unknown"); /* report RPM. */
+ else if (dp->d_rotation_rate == 1) /* Since 0 is used */
+ sbuf_printf(sb, "0"); /* above, SSDs use 1. */
+ else if ((dp->d_rotation_rate >= 0x041) &&
+ (dp->d_rotation_rate <= 0xfffe))
+ sbuf_printf(sb, "%u", dp->d_rotation_rate);
+ else
+ sbuf_printf(sb, "invalid");
+ sbuf_printf(sb, "</rotationrate>\n");
if (dp->d_getattr != NULL) {
buf = g_malloc(DISK_IDENT_SIZE, M_WAITOK);
bp = g_alloc_bio();
diff --git a/sys/i386/linux/linux_proto.h b/sys/i386/linux/linux_proto.h
index a5d6ed2e158c..884292f106b3 100644
--- a/sys/i386/linux/linux_proto.h
+++ b/sys/i386/linux/linux_proto.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/i386/linux/syscalls.master 283492 2015-05-24 18:08:01Z dchagin
+ * created from FreeBSD: head/sys/i386/linux/syscalls.master 293907 2016-01-14 10:13:58Z glebius
*/
#ifndef _LINUX_SYSPROTO_H_
diff --git a/sys/i386/linux/linux_syscall.h b/sys/i386/linux/linux_syscall.h
index 60c284a656b8..1be670ae0f6b 100644
--- a/sys/i386/linux/linux_syscall.h
+++ b/sys/i386/linux/linux_syscall.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/i386/linux/syscalls.master 283492 2015-05-24 18:08:01Z dchagin
+ * created from FreeBSD: head/sys/i386/linux/syscalls.master 293907 2016-01-14 10:13:58Z glebius
*/
#define LINUX_SYS_linux_exit 1
diff --git a/sys/i386/linux/linux_syscalls.c b/sys/i386/linux/linux_syscalls.c
index 64556a9b6cd7..68a81ef5cc48 100644
--- a/sys/i386/linux/linux_syscalls.c
+++ b/sys/i386/linux/linux_syscalls.c
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/i386/linux/syscalls.master 283492 2015-05-24 18:08:01Z dchagin
+ * created from FreeBSD: head/sys/i386/linux/syscalls.master 293907 2016-01-14 10:13:58Z glebius
*/
const char *linux_syscallnames[] = {
diff --git a/sys/i386/linux/linux_sysent.c b/sys/i386/linux/linux_sysent.c
index 922ddbb19aed..d853d1d592d3 100644
--- a/sys/i386/linux/linux_sysent.c
+++ b/sys/i386/linux/linux_sysent.c
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/i386/linux/syscalls.master 283492 2015-05-24 18:08:01Z dchagin
+ * created from FreeBSD: head/sys/i386/linux/syscalls.master 293907 2016-01-14 10:13:58Z glebius
*/
#include <sys/param.h>
diff --git a/sys/i386/linux/syscalls.master b/sys/i386/linux/syscalls.master
index e6609a9c4b08..248770c9bd55 100644
--- a/sys/i386/linux/syscalls.master
+++ b/sys/i386/linux/syscalls.master
@@ -528,8 +528,8 @@
; linux 2.6.17:
311 AUE_NULL STD { int linux_set_robust_list(struct linux_robust_list_head *head, \
l_size_t len); }
-312 AUE_NULL STD { int linux_get_robust_list(l_int pid, struct linux_robust_list_head **head, \
- l_size_t *len); }
+312 AUE_NULL STD { int linux_get_robust_list(l_int pid, \
+ struct linux_robust_list_head **head, l_size_t *len); }
313 AUE_NULL STD { int linux_splice(void); }
314 AUE_NULL STD { int linux_sync_file_range(void); }
315 AUE_NULL STD { int linux_tee(void); }
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c
index d7ec70134ddf..6594e51e7d04 100644
--- a/sys/kern/kern_prot.c
+++ b/sys/kern/kern_prot.c
@@ -88,7 +88,6 @@ static MALLOC_DEFINE(M_CRED, "cred", "credentials");
SYSCTL_NODE(_security, OID_AUTO, bsd, CTLFLAG_RW, 0, "BSD security policy");
-static void crextend(struct ucred *cr, int n);
static void crsetgroups_locked(struct ucred *cr, int ngrp,
gid_t *groups);
@@ -1997,7 +1996,7 @@ crcopysafe(struct proc *p, struct ucred *cr)
/*
* Extend the passed in credential to hold n items.
*/
-static void
+void
crextend(struct ucred *cr, int n)
{
int cnt;
diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c
index 122dff702045..e5081056a40a 100644
--- a/sys/kern/vfs_aio.c
+++ b/sys/kern/vfs_aio.c
@@ -117,10 +117,6 @@ static uint64_t jobseqno;
#define MAX_BUF_AIO 16
#endif
-#ifndef AIOD_TIMEOUT_DEFAULT
-#define AIOD_TIMEOUT_DEFAULT (10 * hz)
-#endif
-
#ifndef AIOD_LIFETIME_DEFAULT
#define AIOD_LIFETIME_DEFAULT (30 * hz)
#endif
@@ -165,10 +161,6 @@ SYSCTL_INT(_vfs_aio, OID_AUTO, num_buf_aio, CTLFLAG_RD, &num_buf_aio, 0,
/* XXX This should be local to aio_aqueue() */
static int num_aio_resv_start = 0;
-static int aiod_timeout;
-SYSCTL_INT(_vfs_aio, OID_AUTO, aiod_timeout, CTLFLAG_RW, &aiod_timeout, 0,
- "Timeout value for synchronous aio operations");
-
static int aiod_lifetime;
SYSCTL_INT(_vfs_aio, OID_AUTO, aiod_lifetime, CTLFLAG_RW, &aiod_lifetime, 0,
"Maximum lifetime for idle aiod");
@@ -392,7 +384,7 @@ static struct filterops lio_filtops = {
static eventhandler_tag exit_tag, exec_tag;
-TASKQUEUE_DEFINE_THREAD(aiod_bio);
+TASKQUEUE_DEFINE_THREAD(aiod_kick);
/*
* Main operations function for use as a kernel module.
@@ -504,7 +496,6 @@ aio_onceonly(void)
NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
aiolio_zone = uma_zcreate("AIOLIO", sizeof(struct aioliojob), NULL,
NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
- aiod_timeout = AIOD_TIMEOUT_DEFAULT;
aiod_lifetime = AIOD_LIFETIME_DEFAULT;
jobrefid = 1;
async_io_version = _POSIX_VERSION;
@@ -555,7 +546,7 @@ aio_unload(void)
return error;
async_io_version = 0;
aio_swake = NULL;
- taskqueue_free(taskqueue_aiod_bio);
+ taskqueue_free(taskqueue_aiod_kick);
delete_unrhdr(aiod_unr);
uma_zdestroy(kaio_zone);
uma_zdestroy(aiop_zone);
@@ -802,7 +793,7 @@ restart:
}
}
AIO_UNLOCK(ki);
- taskqueue_drain(taskqueue_aiod_bio, &ki->kaio_task);
+ taskqueue_drain(taskqueue_aiod_kick, &ki->kaio_task);
mtx_destroy(&ki->kaio_mtx);
uma_zfree(kaio_zone, ki);
p->p_aioinfo = NULL;
@@ -1861,7 +1852,7 @@ aio_kick_nowait(struct proc *userp)
} else if (((num_aio_resv_start + num_aio_procs) < max_aio_procs) &&
((ki->kaio_active_count + num_aio_resv_start) <
ki->kaio_maxactive_count)) {
- taskqueue_enqueue(taskqueue_aiod_bio, &ki->kaio_task);
+ taskqueue_enqueue(taskqueue_aiod_kick, &ki->kaio_task);
}
}
diff --git a/sys/modules/hyperv/vmbus/Makefile b/sys/modules/hyperv/vmbus/Makefile
index 11228cd22c73..637157b3ec49 100644
--- a/sys/modules/hyperv/vmbus/Makefile
+++ b/sys/modules/hyperv/vmbus/Makefile
@@ -7,11 +7,12 @@ KMOD= hv_vmbus
SRCS= hv_channel.c \
hv_channel_mgmt.c \
hv_connection.c \
+ hv_et.c \
hv_hv.c \
hv_ring_buffer.c \
hv_vmbus_drv_freebsd.c \
hv_vmbus_priv.h
-SRCS+= bus_if.h device_if.h
+SRCS+= acpi_if.h bus_if.h device_if.h opt_acpi.h
CFLAGS+= -I${.CURDIR}/../../../dev/hyperv/include \
-I${.CURDIR}/../../../dev/hyperv/vmbus \
diff --git a/sys/modules/sfxge/Makefile b/sys/modules/sfxge/Makefile
index 54d0af13d730..ab9bb2139a76 100644
--- a/sys/modules/sfxge/Makefile
+++ b/sys/modules/sfxge/Makefile
@@ -14,7 +14,7 @@ SRCS+= sfxge_port.c sfxge_rx.c sfxge_tx.c
SRCS+= sfxge.h sfxge_rx.h sfxge_tx.h sfxge_version.h
.PATH: ${.CURDIR}/../../dev/sfxge/common
-SRCS+= efx_bootcfg.c efx_crc32.c efx_ev.c efx_intr.c efx_mac.c
+SRCS+= efx_bootcfg.c efx_crc32.c efx_ev.c efx_intr.c efx_lic.c efx_mac.c
SRCS+= efx_mcdi.c efx_mon.c efx_nic.c
SRCS+= efx_nvram.c efx_phy.c efx_port.c efx_rx.c efx_sram.c efx_tx.c
SRCS+= efx_vpd.c efx_wol.c efx_filter.c efx_hash.c
diff --git a/sys/net/radix_mpath.c b/sys/net/radix_mpath.c
index 56574002a972..5f40745f4904 100644
--- a/sys/net/radix_mpath.c
+++ b/sys/net/radix_mpath.c
@@ -201,19 +201,20 @@ static struct rtentry *
rt_mpath_selectrte(struct rtentry *rte, uint32_t hash)
{
struct radix_node *rn0, *rn;
- u_int32_t n;
+ uint32_t total_weight;
struct rtentry *rt;
int64_t weight;
/* beyond here, we use rn as the master copy */
rn0 = rn = (struct radix_node *)rte;
- n = rn_mpath_count(rn0);
+ rt = rte;
/* gw selection by Modulo-N Hash (RFC2991) XXX need improvement? */
+ total_weight = rn_mpath_count(rn0);
hash += hashjitter;
- hash %= n;
- for (weight = abs((int32_t)hash), rt = rte;
- weight >= rt->rt_weight && rn;
+ hash %= total_weight;
+ for (weight = abs((int32_t)hash);
+ rt != NULL && weight >= rt->rt_weight;
weight -= rt->rt_weight) {
/* stay within the multipath routes */
diff --git a/sys/net/route.c b/sys/net/route.c
index bcc56d9d6fb6..001a15f6c8e5 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -343,35 +343,6 @@ sys_setfib(struct thread *td, struct setfib_args *uap)
* Packet routing routines.
*/
void
-rtalloc(struct route *ro)
-{
-
- rtalloc_ign_fib(ro, 0UL, RT_DEFAULT_FIB);
-}
-
-void
-rtalloc_fib(struct route *ro, u_int fibnum)
-{
- rtalloc_ign_fib(ro, 0UL, fibnum);
-}
-
-void
-rtalloc_ign(struct route *ro, u_long ignore)
-{
- struct rtentry *rt;
-
- if ((rt = ro->ro_rt) != NULL) {
- if (rt->rt_ifp != NULL && rt->rt_flags & RTF_UP)
- return;
- RTFREE(rt);
- ro->ro_rt = NULL;
- }
- ro->ro_rt = rtalloc1_fib(&ro->ro_dst, 1, ignore, RT_DEFAULT_FIB);
- if (ro->ro_rt)
- RT_UNLOCK(ro->ro_rt);
-}
-
-void
rtalloc_ign_fib(struct route *ro, u_long ignore, u_int fibnum)
{
struct rtentry *rt;
@@ -539,17 +510,6 @@ done:
* message from the network layer.
*/
void
-rtredirect(struct sockaddr *dst,
- struct sockaddr *gateway,
- struct sockaddr *netmask,
- int flags,
- struct sockaddr *src)
-{
-
- rtredirect_fib(dst, gateway, netmask, flags, src, RT_DEFAULT_FIB);
-}
-
-void
rtredirect_fib(struct sockaddr *dst,
struct sockaddr *gateway,
struct sockaddr *netmask,
@@ -616,8 +576,8 @@ rtredirect_fib(struct sockaddr *dst,
* Create new route, rather than smashing route to net.
*/
create:
- RTFREE(rt);
- rt = NULL;
+ if (rt != NULL)
+ RTFREE_LOCKED(rt);
flags |= RTF_DYNAMIC;
bzero((caddr_t)&info, sizeof(info));
@@ -673,13 +633,6 @@ out:
ifa_free(ifa);
}
-int
-rtioctl(u_long req, caddr_t data)
-{
-
- return (rtioctl_fib(req, data, RT_DEFAULT_FIB));
-}
-
/*
* Routing table ioctl interface.
*/
@@ -776,19 +729,6 @@ ifa_ifwithroute(int flags, const struct sockaddr *dst, struct sockaddr *gateway,
* all the bits of info needed
*/
int
-rtrequest(int req,
- struct sockaddr *dst,
- struct sockaddr *gateway,
- struct sockaddr *netmask,
- int flags,
- struct rtentry **ret_nrt)
-{
-
- return (rtrequest_fib(req, dst, gateway, netmask, flags, ret_nrt,
- RT_DEFAULT_FIB));
-}
-
-int
rtrequest_fib(int req,
struct sockaddr *dst,
struct sockaddr *gateway,
diff --git a/sys/net/route.h b/sys/net/route.h
index 9ce286523db0..ed21a299b7e9 100644
--- a/sys/net/route.h
+++ b/sys/net/route.h
@@ -436,8 +436,6 @@ int rtsock_routemsg(int, struct ifnet *ifp, int, struct rtentry *, int);
/*
* Note the following locking behavior:
*
- * rtalloc_ign() and rtalloc() return ro->ro_rt unlocked
- *
* rtalloc1() returns a locked rtentry
*
* rtfree() and RTFREE_LOCKED() require a locked rtentry
@@ -445,9 +443,7 @@ int rtsock_routemsg(int, struct ifnet *ifp, int, struct rtentry *, int);
* RTFREE() uses an unlocked entry.
*/
-int rt_expunge(struct radix_node_head *, struct rtentry *);
void rtfree(struct rtentry *);
-int rt_check(struct rtentry **, struct rtentry **, struct sockaddr *);
void rt_updatemtu(struct ifnet *);
typedef int rt_walktree_f_t(struct rtentry *, void *);
@@ -458,15 +454,8 @@ void rt_flushifroutes(struct ifnet *ifp);
/* XXX MRT COMPAT VERSIONS THAT SET UNIVERSE to 0 */
/* Thes are used by old code not yet converted to use multiple FIBS */
-void rtalloc_ign(struct route *ro, u_long ignflags);
-void rtalloc(struct route *ro); /* XXX deprecated, use rtalloc_ign(ro, 0) */
struct rtentry *rtalloc1(struct sockaddr *, int, u_long);
int rtinit(struct ifaddr *, int, int);
-int rtioctl(u_long, caddr_t);
-void rtredirect(struct sockaddr *, struct sockaddr *,
- struct sockaddr *, int, struct sockaddr *);
-int rtrequest(int, struct sockaddr *,
- struct sockaddr *, struct sockaddr *, int, struct rtentry **);
/* XXX MRT NEW VERSIONS THAT USE FIBs
* For now the protocol indepedent versions are the same as the AF_INET ones
@@ -474,7 +463,6 @@ int rtrequest(int, struct sockaddr *,
*/
int rt_getifa_fib(struct rt_addrinfo *, u_int fibnum);
void rtalloc_ign_fib(struct route *ro, u_long ignflags, u_int fibnum);
-void rtalloc_fib(struct route *ro, u_int fibnum);
struct rtentry *rtalloc1_fib(struct sockaddr *, int, u_long, u_int);
int rtioctl_fib(u_long, caddr_t, u_int);
void rtredirect_fib(struct sockaddr *, struct sockaddr *,
diff --git a/sys/netgraph/netflow/netflow.c b/sys/netgraph/netflow/netflow.c
index 87ff18909025..6adffc9e6072 100644
--- a/sys/netgraph/netflow/netflow.c
+++ b/sys/netgraph/netflow/netflow.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <net/if.h>
+#include <net/if_dl.h>
#include <net/if_var.h>
#include <net/route.h>
#include <net/ethernet.h>
@@ -307,8 +308,9 @@ hash_insert(priv_p priv, struct flow_hash_entry *hsh, struct flow_rec *r,
int plen, uint8_t flags, uint8_t tcp_flags)
{
struct flow_entry *fle;
- struct sockaddr_in sin;
- struct rtentry *rt;
+ struct sockaddr_in sin, sin_mask;
+ struct sockaddr_dl rt_gateway;
+ struct rt_addrinfo info;
mtx_assert(&hsh->mtx, MA_OWNED);
@@ -339,23 +341,30 @@ hash_insert(priv_p priv, struct flow_hash_entry *hsh, struct flow_rec *r,
sin.sin_len = sizeof(struct sockaddr_in);
sin.sin_family = AF_INET;
sin.sin_addr = fle->f.r.r_dst;
- rt = rtalloc1_fib((struct sockaddr *)&sin, 0, 0, r->fib);
- if (rt != NULL) {
- fle->f.fle_o_ifx = rt->rt_ifp->if_index;
- if (rt->rt_flags & RTF_GATEWAY &&
- rt->rt_gateway->sa_family == AF_INET)
+ rt_gateway.sdl_len = sizeof(rt_gateway);
+ sin_mask.sin_len = sizeof(struct sockaddr_in);
+ bzero(&info, sizeof(info));
+
+ info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&rt_gateway;
+ info.rti_info[RTAX_NETMASK] = (struct sockaddr *)&sin_mask;
+
+ if (rib_lookup_info(r->fib, (struct sockaddr *)&sin, NHR_REF, 0,
+ &info) == 0) {
+ fle->f.fle_o_ifx = info.rti_ifp->if_index;
+
+ if (info.rti_flags & RTF_GATEWAY &&
+ rt_gateway.sdl_family == AF_INET)
fle->f.next_hop =
- ((struct sockaddr_in *)(rt->rt_gateway))->sin_addr;
+ ((struct sockaddr_in *)&rt_gateway)->sin_addr;
- if (rt_mask(rt))
- fle->f.dst_mask =
- bitcount32(((struct sockaddr_in *)rt_mask(rt))->sin_addr.s_addr);
- else if (rt->rt_flags & RTF_HOST)
+ if (info.rti_addrs & RTA_NETMASK)
+ fle->f.dst_mask = bitcount32(sin_mask.sin_addr.s_addr);
+ else if (info.rti_flags & RTF_HOST)
/* Give up. We can't determine mask :( */
fle->f.dst_mask = 32;
- RTFREE_LOCKED(rt);
+ rib_free_info(&info);
}
}
@@ -365,16 +374,20 @@ hash_insert(priv_p priv, struct flow_hash_entry *hsh, struct flow_rec *r,
sin.sin_len = sizeof(struct sockaddr_in);
sin.sin_family = AF_INET;
sin.sin_addr = fle->f.r.r_src;
- rt = rtalloc1_fib((struct sockaddr *)&sin, 0, 0, r->fib);
- if (rt != NULL) {
- if (rt_mask(rt))
+
+ sin_mask.sin_len = sizeof(struct sockaddr_in);
+ bzero(&info, sizeof(info));
+
+ info.rti_info[RTAX_NETMASK] = (struct sockaddr *)&sin_mask;
+
+ if (rib_lookup_info(r->fib, (struct sockaddr *)&sin, 0, 0,
+ &info) == 0) {
+ if (info.rti_addrs & RTA_NETMASK)
fle->f.src_mask =
- bitcount32(((struct sockaddr_in *)rt_mask(rt))->sin_addr.s_addr);
- else if (rt->rt_flags & RTF_HOST)
+ bitcount32(sin_mask.sin_addr.s_addr);
+ else if (info.rti_flags & RTF_HOST)
/* Give up. We can't determine mask :( */
fle->f.src_mask = 32;
-
- RTFREE_LOCKED(rt);
}
}
@@ -390,14 +403,14 @@ hash_insert(priv_p priv, struct flow_hash_entry *hsh, struct flow_rec *r,
bitcount32((x).__u6_addr.__u6_addr32[1]) + \
bitcount32((x).__u6_addr.__u6_addr32[2]) + \
bitcount32((x).__u6_addr.__u6_addr32[3])
-#define RT_MASK6(x) (ipv6_masklen(((struct sockaddr_in6 *)rt_mask(x))->sin6_addr))
static int
hash6_insert(priv_p priv, struct flow_hash_entry *hsh6, struct flow6_rec *r,
int plen, uint8_t flags, uint8_t tcp_flags)
{
struct flow6_entry *fle6;
- struct sockaddr_in6 sin6;
- struct rtentry *rt;
+ struct sockaddr_in6 sin6, sin6_mask;
+ struct sockaddr_dl rt_gateway;
+ struct rt_addrinfo info;
mtx_assert(&hsh6->mtx, MA_OWNED);
@@ -430,22 +443,29 @@ hash6_insert(priv_p priv, struct flow_hash_entry *hsh6, struct flow6_rec *r,
sin6.sin6_family = AF_INET6;
sin6.sin6_addr = r->dst.r_dst6;
- rt = rtalloc1_fib((struct sockaddr *)&sin6, 0, 0, r->fib);
+ rt_gateway.sdl_len = sizeof(rt_gateway);
+ sin6_mask.sin6_len = sizeof(struct sockaddr_in6);
+ bzero(&info, sizeof(info));
+
+ info.rti_info[RTAX_GATEWAY] = (struct sockaddr *)&rt_gateway;
+ info.rti_info[RTAX_NETMASK] = (struct sockaddr *)&sin6_mask;
- if (rt != NULL) {
- fle6->f.fle_o_ifx = rt->rt_ifp->if_index;
+ if (rib_lookup_info(r->fib, (struct sockaddr *)&sin6, NHR_REF,
+ 0, &info) == 0) {
+ fle6->f.fle_o_ifx = info.rti_ifp->if_index;
- if (rt->rt_flags & RTF_GATEWAY &&
- rt->rt_gateway->sa_family == AF_INET6)
+ if (info.rti_flags & RTF_GATEWAY &&
+ rt_gateway.sdl_family == AF_INET6)
fle6->f.n.next_hop6 =
- ((struct sockaddr_in6 *)(rt->rt_gateway))->sin6_addr;
+ ((struct sockaddr_in6 *)&rt_gateway)->sin6_addr;
- if (rt_mask(rt))
- fle6->f.dst_mask = RT_MASK6(rt);
+ if (info.rti_addrs & RTA_NETMASK)
+ fle6->f.dst_mask =
+ ipv6_masklen(sin6_mask.sin6_addr);
else
fle6->f.dst_mask = 128;
- RTFREE_LOCKED(rt);
+ rib_free_info(&info);
}
}
@@ -456,15 +476,18 @@ hash6_insert(priv_p priv, struct flow_hash_entry *hsh6, struct flow6_rec *r,
sin6.sin6_family = AF_INET6;
sin6.sin6_addr = r->src.r_src6;
- rt = rtalloc1_fib((struct sockaddr *)&sin6, 0, 0, r->fib);
+ sin6_mask.sin6_len = sizeof(struct sockaddr_in6);
+ bzero(&info, sizeof(info));
- if (rt != NULL) {
- if (rt_mask(rt))
- fle6->f.src_mask = RT_MASK6(rt);
+ info.rti_info[RTAX_NETMASK] = (struct sockaddr *)&sin6_mask;
+
+ if (rib_lookup_info(r->fib, (struct sockaddr *)&sin6, 0, 0,
+ &info) == 0) {
+ if (info.rti_addrs & RTA_NETMASK)
+ fle6->f.src_mask =
+ ipv6_masklen(sin6_mask.sin6_addr);
else
fle6->f.src_mask = 128;
-
- RTFREE_LOCKED(rt);
}
}
@@ -474,7 +497,6 @@ hash6_insert(priv_p priv, struct flow_hash_entry *hsh6, struct flow6_rec *r,
return (0);
}
#undef ipv6_masklen
-#undef RT_MASK6
#endif
diff --git a/sys/netinet/in_rmx.c b/sys/netinet/in_rmx.c
index 283c45087c15..ced53816ada6 100644
--- a/sys/netinet/in_rmx.c
+++ b/sys/netinet/in_rmx.c
@@ -191,12 +191,6 @@ in_rtalloc_ign(struct route *ro, u_long ignflags, u_int fibnum)
rtalloc_ign_fib(ro, ignflags, fibnum);
}
-struct rtentry *
-in_rtalloc1(struct sockaddr *dst, int report, u_long ignflags, u_int fibnum)
-{
- return (rtalloc1_fib(dst, report, ignflags, fibnum));
-}
-
void
in_rtredirect(struct sockaddr *dst,
struct sockaddr *gateway,
@@ -208,9 +202,3 @@ in_rtredirect(struct sockaddr *dst,
rtredirect_fib(dst, gateway, netmask, flags, src, fibnum);
}
-void
-in_rtalloc(struct route *ro, u_int fibnum)
-{
- rtalloc_ign_fib(ro, 0UL, fibnum);
-}
-
diff --git a/sys/netinet/in_var.h b/sys/netinet/in_var.h
index f21ddf43b4a6..121c6da19436 100644
--- a/sys/netinet/in_var.h
+++ b/sys/netinet/in_var.h
@@ -387,8 +387,6 @@ void in_domifdetach(struct ifnet *, void *);
/* XXX */
void in_rtalloc_ign(struct route *ro, u_long ignflags, u_int fibnum);
-void in_rtalloc(struct route *ro, u_int fibnum);
-struct rtentry *in_rtalloc1(struct sockaddr *, int, u_long, u_int);
void in_rtredirect(struct sockaddr *, struct sockaddr *,
struct sockaddr *, int, struct sockaddr *, u_int);
#endif /* _KERNEL */
diff --git a/sys/netinet/ip_mroute.c b/sys/netinet/ip_mroute.c
index 9b762d6a631f..69e12c3cd5b5 100644
--- a/sys/netinet/ip_mroute.c
+++ b/sys/netinet/ip_mroute.c
@@ -538,7 +538,7 @@ X_mrt_ioctl(u_long cmd, caddr_t data, int fibnum __unused)
int error = 0;
/*
- * Currently the only function calling this ioctl routine is rtioctl().
+ * Currently the only function calling this ioctl routine is rtioctl_fib().
* Typically, only root can create the raw socket in order to execute
* this ioctl method, however the request might be coming from a prison
*/
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index fc3be4c955dc..d4a9dff0bb22 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -2269,8 +2269,12 @@ sctp_findassociation_addr(struct mbuf *m, int offset,
}
}
find_tcp_pool = 0;
- if ((ch->chunk_type != SCTP_INITIATION) &&
- (ch->chunk_type != SCTP_INITIATION_ACK) &&
+ /*
+ * Don't consider INIT chunks since that breaks 1-to-1 sockets: When
+ * a server closes the listener, incoming INIT chunks are not
+ * responsed by an INIT-ACK chunk.
+ */
+ if ((ch->chunk_type != SCTP_INITIATION_ACK) &&
(ch->chunk_type != SCTP_COOKIE_ACK) &&
(ch->chunk_type != SCTP_COOKIE_ECHO)) {
/* Other chunk types go to the tcp pool. */
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
index 60deff0ff253..2ea4eed96cab 100644
--- a/sys/netinet/sctp_usrreq.c
+++ b/sys/netinet/sctp_usrreq.c
@@ -1883,8 +1883,15 @@ flags_out:
uint32_t *value, cnt;
SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
- cnt = 0;
SCTP_INP_RLOCK(inp);
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
+ /* Can't do this for a 1-1 socket */
+ error = EINVAL;
+ SCTP_INP_RUNLOCK(inp);
+ break;
+ }
+ cnt = 0;
LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
cnt++;
}
@@ -1899,9 +1906,16 @@ flags_out:
unsigned int at, limit;
SCTP_CHECK_AND_CAST(ids, optval, struct sctp_assoc_ids, *optsize);
+ SCTP_INP_RLOCK(inp);
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
+ /* Can't do this for a 1-1 socket */
+ error = EINVAL;
+ SCTP_INP_RUNLOCK(inp);
+ break;
+ }
at = 0;
limit = (*optsize - sizeof(uint32_t)) / sizeof(sctp_assoc_t);
- SCTP_INP_RLOCK(inp);
LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
if (at < limit) {
ids->gaids_assoc_id[at++] = sctp_get_associd(stcb);
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index 3c32d77c377e..4a4e7eb5061a 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -752,8 +752,8 @@ send:
* segments. Options for SYN-ACK segments are handled in TCP
* syncache.
*/
+ to.to_flags = 0;
if ((tp->t_flags & TF_NOOPT) == 0) {
- to.to_flags = 0;
/* Maximum segment size. */
if (flags & TH_SYN) {
tp->snd_nxt = tp->iss;
@@ -1233,7 +1233,7 @@ send:
tp->snd_up = tp->snd_una; /* drag it along */
#ifdef TCP_SIGNATURE
- if (tp->t_flags & TF_SIGNATURE) {
+ if (to.to_flags & TOF_SIGNATURE) {
int sigoff = to.to_signature - opt;
tcp_signature_compute(m, 0, len, optlen,
(u_char *)(th + 1) + sigoff, IPSEC_DIR_OUTBOUND);
@@ -1713,6 +1713,7 @@ tcp_addoptions(struct tcpopt *to, u_char *optp)
bcopy((u_char *)&to->to_tsecr, optp, sizeof(to->to_tsecr));
optp += sizeof(to->to_tsecr);
break;
+#ifdef TCP_SIGNATURE
case TOF_SIGNATURE:
{
int siglen = TCPOLEN_SIGNATURE - 2;
@@ -1731,6 +1732,7 @@ tcp_addoptions(struct tcpopt *to, u_char *optp)
*optp++ = 0;
break;
}
+#endif
case TOF_SACK:
{
int sackblks = 0;
diff --git a/sys/netinet6/sctp6_usrreq.c b/sys/netinet6/sctp6_usrreq.c
index 43df06edeb37..40c1b411697e 100644
--- a/sys/netinet6/sctp6_usrreq.c
+++ b/sys/netinet6/sctp6_usrreq.c
@@ -379,7 +379,6 @@ sctp6_ctlinput(int cmd, struct sockaddr *pktdst, void *d)
* XXX: We assume that when IPV6 is non NULL, M and OFF are
* valid.
*/
- /* check if we can safely examine src and dst ports */
struct sctp_inpcb *inp = NULL;
struct sctp_tcb *stcb = NULL;
struct sctp_nets *net = NULL;
@@ -388,6 +387,10 @@ sctp6_ctlinput(int cmd, struct sockaddr *pktdst, void *d)
if (ip6cp->ip6c_m == NULL)
return;
+ /* Check if we can safely examine the SCTP header. */
+ if (ip6cp->ip6c_m->m_pkthdr.len < ip6cp->ip6c_off + sizeof(sh))
+ return;
+
bzero(&sh, sizeof(sh));
bzero(&final, sizeof(final));
inp = NULL;
diff --git a/sys/powerpc/include/vmparam.h b/sys/powerpc/include/vmparam.h
index 5b808abc1fee..1d7a06e5e6f8 100644
--- a/sys/powerpc/include/vmparam.h
+++ b/sys/powerpc/include/vmparam.h
@@ -111,7 +111,7 @@
#define KERNBASE 0xc0000000 /* start of kernel virtual */
#define VM_MIN_KERNEL_ADDRESS KERNBASE
-#define VM_MAX_KERNEL_ADDRESS 0xf8000000
+#define VM_MAX_KERNEL_ADDRESS 0xf7ffffff
#define VM_MAX_SAFE_KERNEL_ADDRESS VM_MAX_KERNEL_ADDRESS
#endif /* AIM/E500 */
@@ -129,7 +129,7 @@ struct pmap_physseg {
* The physical address space is densely populated on 32-bit systems,
* but may not be on 64-bit ones.
*/
-#ifdef __powerpc64__
+#ifdef __powerpc__
#define VM_PHYSSEG_SPARSE
#else
#define VM_PHYSSEG_DENSE
diff --git a/sys/sys/param.h b/sys/sys/param.h
index 3c9747aa4045..6e25339e1f33 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -58,7 +58,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 1100093 /* Master, propagated to newvers */
+#define __FreeBSD_version 1100094 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
diff --git a/sys/sys/ucred.h b/sys/sys/ucred.h
index d7e7fa5a947c..8dbf2fef74fe 100644
--- a/sys/sys/ucred.h
+++ b/sys/sys/ucred.h
@@ -105,6 +105,7 @@ void change_svuid(struct ucred *newcred, uid_t svuid);
void crcopy(struct ucred *dest, struct ucred *src);
struct ucred *crcopysafe(struct proc *p, struct ucred *cr);
struct ucred *crdup(struct ucred *cr);
+void crextend(struct ucred *cr, int n);
void proc_set_cred_init(struct proc *p, struct ucred *cr);
struct ucred *proc_set_cred(struct proc *p, struct ucred *cr);
void crfree(struct ucred *cr);
diff --git a/sys/x86/x86/identcpu.c b/sys/x86/x86/identcpu.c
index 38c1c6617c12..bc232a261ce3 100644
--- a/sys/x86/x86/identcpu.c
+++ b/sys/x86/x86/identcpu.c
@@ -1294,6 +1294,8 @@ identify_hypervisor(void)
hv_vendor[12] = '\0';
if (strcmp(hv_vendor, "VMwareVMware") == 0)
vm_guest = VM_GUEST_VMWARE;
+ else if (strcmp(hv_vendor, "Microsoft Hv") == 0)
+ vm_guest = VM_GUEST_HV;
}
return;
}
diff --git a/tests/sys/geom/class/gate/1_test.sh b/tests/sys/geom/class/gate/1_test.sh
index 83f609602ed3..3e277349631f 100644
--- a/tests/sys/geom/class/gate/1_test.sh
+++ b/tests/sys/geom/class/gate/1_test.sh
@@ -11,7 +11,6 @@ while [ -c /dev/ggate${us} ]; do
: $(( us += 1 ))
done
conf=`mktemp $base.XXXXXX` || exit 1
-pidfile=/var/run/ggated.pid
port=33080
work=$(attach_md -t malloc -s 1M)
@@ -20,7 +19,7 @@ src=$(attach_md -t malloc -s 1M)
test_cleanup()
{
ggatec destroy -f -u $us
- pkill -F $pidfile
+ killall ggated
geom_test_cleanup
}
trap test_cleanup ABRT EXIT INT TERM
diff --git a/tests/sys/geom/class/gate/conf.sh b/tests/sys/geom/class/gate/conf.sh
index 4eede088ad29..7e22ce46af66 100755
--- a/tests/sys/geom/class/gate/conf.sh
+++ b/tests/sys/geom/class/gate/conf.sh
@@ -5,6 +5,4 @@ name="$(mktemp -u gate.XXXXXX)"
class="gate"
base=`basename $0`
-kldstat -q -m g_${class} || kldload geom_${class} || exit 1
-
. `dirname $0`/../geom_subr.sh
diff --git a/usr.bin/clang/clang/Makefile b/usr.bin/clang/clang/Makefile
index e28ba9de5f32..3665888fd46a 100644
--- a/usr.bin/clang/clang/Makefile
+++ b/usr.bin/clang/clang/Makefile
@@ -11,6 +11,10 @@ SRCS= cc1_main.cpp \
.if ${MK_SHARED_TOOLCHAIN} == "no"
NO_SHARED?= yes
+
+.if ${MACHINE_CPUARCH} == "arm"
+CFLAGS+= -mlong-calls
+.endif
.endif
LINKS= ${BINDIR}/clang ${BINDIR}/clang++ \
diff --git a/usr.bin/clang/lldb/Makefile b/usr.bin/clang/lldb/Makefile
index ff5e0501412f..b2c905045580 100644
--- a/usr.bin/clang/lldb/Makefile
+++ b/usr.bin/clang/lldb/Makefile
@@ -8,6 +8,9 @@ LLDB_SRCS=${.CURDIR}/../../../contrib/llvm/tools/lldb
CFLAGS+= -I${LLDB_SRCS}/include
CXXFLAGS+= -std=c++11
+.if ${MACHINE_CPUARCH} == "arm"
+CFLAGS+= -mlong-calls
+.endif
SRCDIR= tools/lldb/tools/driver
SRCS= Driver.cpp \
diff --git a/usr.bin/numactl/numactl.c b/usr.bin/numactl/numactl.c
index ce1dfaecabc7..8ad0d0076c72 100644
--- a/usr.bin/numactl/numactl.c
+++ b/usr.bin/numactl/numactl.c
@@ -133,7 +133,7 @@ usage(void)
}
static int
-set_numa_domain_cpuaffinity(int cpu_domain)
+set_numa_domain_cpuaffinity(int cpu_domain, cpuwhich_t which, id_t id)
{
cpuset_t set;
int error;
@@ -142,8 +142,8 @@ set_numa_domain_cpuaffinity(int cpu_domain)
cpu_domain, sizeof(set), &set);
if (error != 0)
err(1, "cpuset_getaffinity");
- error = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1,
- sizeof(set), &set);
+ error = cpuset_setaffinity(CPU_LEVEL_WHICH, which, id, sizeof(set),
+ &set);
if (error != 0)
err(1, "cpuset_setaffinity");
@@ -228,7 +228,8 @@ main(int argc, char *argv[])
/* If a CPU domain policy was given, include that too */
if (cpu_domain != -1)
- (void) set_numa_domain_cpuaffinity(cpu_domain);
+ (void) set_numa_domain_cpuaffinity(cpu_domain,
+ CPU_WHICH_PID, -1);
errno = 0;
execvp(*argv, argv);
@@ -278,7 +279,7 @@ main(int argc, char *argv[])
/* If a CPU domain policy was given, include that too */
if (cpu_domain != -1)
- (void) set_numa_domain_cpuaffinity(cpu_domain);
+ (void) set_numa_domain_cpuaffinity(cpu_domain, which, id);
exit(0);
}
diff --git a/usr.sbin/boot0cfg/boot0cfg.c b/usr.sbin/boot0cfg/boot0cfg.c
index f2cbf67a39d3..c2cb91de4166 100644
--- a/usr.sbin/boot0cfg/boot0cfg.c
+++ b/usr.sbin/boot0cfg/boot0cfg.c
@@ -336,8 +336,7 @@ read_mbr(const char *disk, u_int8_t **mbr, int check_version)
close(fd);
return (mbr_size);
}
- *mbr = malloc(sizeof(buf));
- if (*mbr == NULL)
+ if ((*mbr = malloc(sizeof(buf))) == NULL)
errx(1, "%s: unable to allocate MBR buffer", disk);
memcpy(*mbr, buf, sizeof(buf));
close(fd);
diff --git a/usr.sbin/bsdinstall/scripts/auto b/usr.sbin/bsdinstall/scripts/auto
index c681a12fd2a3..db0fea925221 100755
--- a/usr.sbin/bsdinstall/scripts/auto
+++ b/usr.sbin/bsdinstall/scripts/auto
@@ -195,7 +195,7 @@ if f_interactive; then
;;
"Dell Inc.")
case "$sys_model" in
- "Latitude E7440"|"Latitude E7240")
+ "Latitude E7440"|"Latitude E7240"|"Precision Tower 5810")
dialog_workaround "$msg_gpt_active_fix"
retval=$?
f_dprintf "gpt_active_fix_prompt=[%s]" "$retval"
diff --git a/usr.sbin/kldxref/ef_aarch64.c b/usr.sbin/kldxref/ef_aarch64.c
new file mode 100644
index 000000000000..cc55ed103be3
--- /dev/null
+++ b/usr.sbin/kldxref/ef_aarch64.c
@@ -0,0 +1,77 @@
+/*-
+ * Copyright (c) 2005 Peter Grehan.
+ * Copyright 1996-1998 John D. Polstra.
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <machine/elf.h>
+
+#include <err.h>
+#include <errno.h>
+#include <string.h>
+
+#include "ef.h"
+
+#include <stdio.h>
+
+/*
+ * Apply relocations to the values obtained from the file. `relbase' is the
+ * target relocation address of the section, and `dataoff/len' is the region
+ * that is to be relocated, and has been copied to *dest
+ */
+int
+ef_reloc(struct elf_file *ef, const void *reldata, int reltype, Elf_Off relbase,
+ Elf_Off dataoff, size_t len, void *dest)
+{
+ Elf_Addr *where, addend;
+ Elf_Size rtype, symidx;
+ const Elf_Rela *rela;
+
+ if (reltype != EF_RELOC_RELA)
+ return (EINVAL);
+
+ rela = (const Elf_Rela *)reldata;
+ where = (Elf_Addr *) ((Elf_Off)dest - dataoff + rela->r_offset);
+ addend = rela->r_addend;
+ rtype = ELF_R_TYPE(rela->r_info);
+ symidx = ELF_R_SYM(rela->r_info);
+
+ if ((char *)where < (char *)dest || (char *)where >= (char *)dest + len)
+ return (0);
+
+ switch(rtype) {
+ case R_AARCH64_RELATIVE:
+ *where = relbase + addend;
+ break;
+ case R_AARCH64_ABS64:
+ break;
+ default:
+ warnx("unhandled relocation type %lu", rtype);
+ break;
+ }
+ return (0);
+}