summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/amd64/elf_machdep.c1
-rw-r--r--sys/amd64/amd64/machdep.c2
-rw-r--r--sys/amd64/amd64/trap.c7
-rw-r--r--sys/amd64/include/metadata.h56
-rw-r--r--sys/amd64/include/pcb.h20
-rw-r--r--sys/amd64/linux/linux_proto.h2
-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.c12
-rw-r--r--sys/amd64/linux/linux_sysvec.c51
-rw-r--r--sys/amd64/linux/syscalls.master6
-rw-r--r--sys/amd64/linux32/linux.h2
-rw-r--r--sys/amd64/linux32/linux32_locore.s4
-rw-r--r--sys/amd64/linux32/linux32_proto.h562
-rw-r--r--sys/amd64/linux32/linux32_syscall.h634
-rw-r--r--sys/amd64/linux32/linux32_syscalls.c4
-rw-r--r--sys/amd64/linux32/linux32_sysent.c4
-rw-r--r--sys/amd64/linux32/linux32_sysvec.c11
-rw-r--r--sys/amd64/linux32/syscalls.conf8
-rw-r--r--sys/amd64/linux32/syscalls.master2
-rw-r--r--sys/arm/arm/bcopyinout.S3
-rw-r--r--sys/arm/arm/bcopyinout_xscale.S4
-rw-r--r--sys/arm/arm/busdma_machdep.c3
-rw-r--r--sys/arm/arm/copystr.S3
-rw-r--r--sys/arm/arm/elf_machdep.c1
-rw-r--r--sys/arm/arm/fusu.S4
-rw-r--r--sys/arm/arm/locore-v4.S239
-rw-r--r--sys/arm/arm/locore-v6.S188
-rw-r--r--sys/arm/arm/machdep.c8
-rw-r--r--sys/arm/arm/physmem.c29
-rw-r--r--sys/arm/arm/trap.c3
-rw-r--r--sys/arm/at91/at91_mci.c21
-rw-r--r--sys/arm/freescale/imx/imx6_anatop.c17
-rw-r--r--sys/arm/freescale/imx/imx6_machdep.c4
-rw-r--r--sys/arm/freescale/imx/imx_machdep.c36
-rw-r--r--sys/arm/freescale/imx/imx_machdep.h4
-rw-r--r--sys/arm/freescale/imx/imx_sdhci.c12
-rw-r--r--sys/arm/freescale/imx/imx_wdogreg.h1
-rw-r--r--sys/arm/mv/std-pj4b.mv6
-rw-r--r--sys/arm/xscale/ixp425/avila_machdep.c8
-rw-r--r--sys/boot/common/bootstrap.h7
-rw-r--r--sys/boot/common/load_elf.c265
-rw-r--r--sys/boot/common/load_elf_obj.c9
-rw-r--r--sys/boot/common/module.c11
-rw-r--r--sys/boot/efi/boot1/Makefile14
-rw-r--r--sys/boot/efi/boot1/boot1.c31
-rw-r--r--sys/boot/efi/include/efierr.h3
-rw-r--r--sys/boot/efi/libefi/Makefile1
-rw-r--r--sys/boot/efi/libefi/efi_console.c420
-rw-r--r--sys/boot/efi/loader/Makefile3
-rw-r--r--sys/boot/efi/loader/bootinfo.c7
-rw-r--r--sys/boot/efi/loader/copy.c2
-rw-r--r--sys/boot/efi/loader/main.c99
-rw-r--r--sys/boot/fdt/dts/arm/beaglebone-black.dts4
-rw-r--r--sys/boot/fdt/dts/arm/beaglebone.dts2
-rw-r--r--sys/boot/fdt/fdt_loader_cmd.c2
-rw-r--r--sys/boot/ficl/amd64/sysdep.c2
-rw-r--r--sys/boot/forth/beastie.4th6
-rw-r--r--sys/boot/forth/beastie.4th.85
-rw-r--r--sys/boot/forth/loader.4th3
-rw-r--r--sys/boot/forth/loader.conf.55
-rw-r--r--sys/boot/forth/support.4th27
-rw-r--r--sys/boot/i386/libi386/Makefile3
-rw-r--r--sys/boot/i386/libi386/bootinfo64.c45
-rw-r--r--sys/boot/i386/libi386/elf64_freebsd.c2
-rw-r--r--sys/boot/i386/libi386/libi386.h3
-rw-r--r--sys/boot/i386/libi386/multiboot.c425
-rw-r--r--sys/boot/i386/libi386/multiboot.h225
-rw-r--r--sys/boot/i386/libi386/multiboot_tramp.S51
-rw-r--r--sys/boot/i386/loader/conf.c4
-rw-r--r--sys/boot/i386/zfsboot/zfsboot.c6
-rw-r--r--sys/boot/ia64/efi/Makefile1
-rw-r--r--sys/boot/libstand32/Makefile4
-rw-r--r--sys/boot/pc98/boot2/boot2.c2
-rw-r--r--sys/boot/pc98/libpc98/biosdisk.c6
-rw-r--r--sys/boot/uboot/common/main.c55
-rw-r--r--sys/boot/uboot/lib/copy.c22
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c1
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_queue.c2
-rw-r--r--sys/cddl/dev/systrace/systrace.c44
-rw-r--r--sys/compat/ia32/ia32_sysvec.c1
-rw-r--r--sys/compat/linux/linux_misc.c11
-rw-r--r--sys/compat/linux/linux_socket.c1
-rw-r--r--sys/compat/svr4/svr4_sysvec.c1
-rw-r--r--sys/conf/files.amd641
-rw-r--r--sys/dev/drm2/i915/intel_iic.c3
-rw-r--r--sys/dev/e1000/if_igb.c11
-rw-r--r--sys/dev/iicbus/icee.c157
-rw-r--r--sys/dev/iicbus/iicbb.c17
-rw-r--r--sys/dev/iicbus/iicbus.c9
-rw-r--r--sys/dev/iicbus/iicoc.c1
-rw-r--r--sys/dev/iicbus/iiconf.c15
-rw-r--r--sys/dev/iicbus/iiconf.h2
-rw-r--r--sys/dev/iicbus/iicsmb.c6
-rw-r--r--sys/dev/iscsi/iscsi.c99
-rw-r--r--sys/dev/iscsi/iscsi.h3
-rw-r--r--sys/dev/nvd/nvd.c2
-rw-r--r--sys/dev/nvme/nvme.h1
-rw-r--r--sys/dev/nvme/nvme_ns.c18
-rw-r--r--sys/dev/nvme/nvme_sysctl.c16
-rw-r--r--sys/dev/ofw/ofw_iicbus.c6
-rw-r--r--sys/dev/pci/pci.c24
-rw-r--r--sys/dev/pci/pci_if.m16
-rw-r--r--sys/dev/pci/pci_private.h2
-rw-r--r--sys/dev/pci/pcireg.h24
-rw-r--r--sys/dev/pci/pcivar.h17
-rw-r--r--sys/dev/rt/if_rt.c24
-rw-r--r--sys/dev/sfxge/common/ef10_impl.h46
-rw-r--r--sys/dev/sfxge/common/ef10_tlv_layout.h10
-rw-r--r--sys/dev/sfxge/common/efsys.h4
-rw-r--r--sys/dev/sfxge/common/efx.h73
-rw-r--r--sys/dev/sfxge/common/efx_check.h11
-rw-r--r--sys/dev/sfxge/common/efx_impl.h54
-rw-r--r--sys/dev/sfxge/common/efx_lic.c792
-rw-r--r--sys/dev/sfxge/common/efx_mac.c51
-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.c131
-rw-r--r--sys/dev/sfxge/common/efx_phy.c30
-rw-r--r--sys/dev/sfxge/common/efx_regs_ef10.h65
-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.c184
-rw-r--r--sys/dev/sfxge/common/hunt_impl.h193
-rw-r--r--sys/dev/sfxge/common/hunt_mac.c307
-rw-r--r--sys/dev/sfxge/common/hunt_mcdi.c145
-rw-r--r--sys/dev/sfxge/common/hunt_nic.c210
-rw-r--r--sys/dev/sfxge/common/hunt_nvram.c215
-rw-r--r--sys/dev/sfxge/common/hunt_phy.c85
-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.c266
-rw-r--r--sys/dev/sfxge/common/siena_flash.h4
-rw-r--r--sys/dev/sfxge/common/siena_impl.h102
-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.c181
-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/sfxge/sfxge_version.h2
-rw-r--r--sys/dev/uart/uart_bus.h1
-rw-r--r--sys/dev/uart/uart_core.c145
-rw-r--r--sys/dev/uart/uart_dev_ns8250.c76
-rw-r--r--sys/dev/uart/uart_ppstypes.h46
-rw-r--r--sys/dev/usb/serial/usb_serial.c45
-rw-r--r--sys/fs/devfs/devfs_vnops.c8
-rw-r--r--sys/fs/smbfs/smbfs_smb.c8
-rw-r--r--sys/fs/smbfs/smbfs_subr.h3
-rw-r--r--sys/fs/smbfs/smbfs_vnops.c3
-rw-r--r--sys/geom/geom_disk.c17
-rw-r--r--sys/geom/multipath/g_multipath.c20
-rw-r--r--sys/i386/i386/elf_machdep.c1
-rw-r--r--sys/i386/i386/machdep.c9
-rw-r--r--sys/i386/ibcs2/ibcs2_sysvec.c1
-rw-r--r--sys/i386/include/metadata.h36
-rw-r--r--sys/i386/include/pcb.h16
-rw-r--r--sys/i386/linux/linux_sysvec.c2
-rw-r--r--sys/kern/imgact_aout.c1
-rw-r--r--sys/kern/init_main.c1
-rw-r--r--sys/kern/kern_environment.c38
-rw-r--r--sys/kern/kern_linker.c6
-rw-r--r--sys/kern/kern_mib.c5
-rw-r--r--sys/kern/kern_proc.c15
-rw-r--r--sys/kern/kern_thread.c11
-rw-r--r--sys/kern/makesyscalls.sh4
-rw-r--r--sys/kern/subr_busdma_bufalloc.c4
-rw-r--r--sys/mips/include/elf.h29
-rw-r--r--sys/mips/mips/elf_machdep.c2
-rw-r--r--sys/mips/mips/freebsd32_machdep.c1
-rw-r--r--sys/modules/dtrace/Makefile5
-rw-r--r--sys/modules/dtrace/systrace_linux/Makefile18
-rw-r--r--sys/modules/dtrace/systrace_linux32/Makefile6
-rw-r--r--sys/modules/sfxge/Makefile2
-rw-r--r--sys/net/bpf.c2
-rw-r--r--sys/net/if.c20
-rw-r--r--sys/net/if_llatbl.c14
-rw-r--r--sys/net/sff8436.h2
-rw-r--r--sys/netinet/sctp.h20
-rw-r--r--sys/netinet/sctp_asconf.c8
-rw-r--r--sys/netinet/sctp_auth.c31
-rw-r--r--sys/netinet/sctp_constants.h8
-rw-r--r--sys/netinet/sctp_header.h51
-rw-r--r--sys/netinet/sctp_indata.c167
-rw-r--r--sys/netinet/sctp_indata.h6
-rw-r--r--sys/netinet/sctp_input.c274
-rw-r--r--sys/netinet/sctp_os_bsd.h1
-rw-r--r--sys/netinet/sctp_output.c362
-rw-r--r--sys/netinet/sctp_output.h11
-rw-r--r--sys/netinet/sctp_pcb.c72
-rw-r--r--sys/netinet/sctp_pcb.h8
-rw-r--r--sys/netinet/sctp_structs.h15
-rw-r--r--sys/netinet/sctp_sysctl.c3
-rw-r--r--sys/netinet/sctp_sysctl.h4
-rw-r--r--sys/netinet/sctp_timer.c17
-rw-r--r--sys/netinet/sctp_uio.h22
-rw-r--r--sys/netinet/sctp_usrreq.c252
-rw-r--r--sys/netinet/sctputil.c129
-rw-r--r--sys/netinet/sctputil.h5
-rw-r--r--sys/netinet/tcp_subr.c2
-rw-r--r--sys/netinet6/in6.c4
-rw-r--r--sys/netinet6/sctp6_usrreq.c7
-rw-r--r--sys/ofed/include/linux/linux_compat.c2
-rw-r--r--sys/powerpc/powerpc/busdma_machdep.c4
-rw-r--r--sys/powerpc/powerpc/elf32_machdep.c1
-rw-r--r--sys/powerpc/powerpc/elf64_machdep.c1
-rw-r--r--sys/security/audit/audit_worker.c60
-rw-r--r--sys/sparc64/sparc64/bus_machdep.c4
-rw-r--r--sys/sparc64/sparc64/elf_machdep.c1
-rw-r--r--sys/sparc64/sparc64/machdep.c3
-rw-r--r--sys/sys/conf.h4
-rw-r--r--sys/sys/elf32.h12
-rw-r--r--sys/sys/elf64.h12
-rw-r--r--sys/sys/elf_common.h217
-rw-r--r--sys/sys/sysent.h1
-rw-r--r--sys/vm/vm_kern.c3
-rw-r--r--sys/x86/include/metadata.h57
-rw-r--r--sys/x86/x86/busdma_bounce.c4
223 files changed, 7152 insertions, 3495 deletions
diff --git a/sys/amd64/amd64/elf_machdep.c b/sys/amd64/amd64/elf_machdep.c
index d961f09..d7c9fef 100644
--- a/sys/amd64/amd64/elf_machdep.c
+++ b/sys/amd64/amd64/elf_machdep.c
@@ -83,6 +83,7 @@ struct sysentvec elf64_freebsd_sysvec = {
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
+ .sv_trap = NULL,
};
INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec);
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index 03334f1..15265aa 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -1847,7 +1847,7 @@ hammer_time(u_int64_t modulep, u_int64_t physfree)
if (kmdp == NULL)
kmdp = preload_search_by_type("elf64 kernel");
boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int);
- kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *) + KERNBASE;
+ init_static_kenv(MD_FETCH(kmdp, MODINFOMD_ENVP, char *) + KERNBASE, 0);
#ifdef DDB
ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t);
ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t);
diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
index 3ecfabe..218c8cf 100644
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -327,6 +327,13 @@ trap(struct trapframe *frame)
break;
case T_PAGEFLT: /* page fault */
+ /*
+ * Emulator can take care about this trap?
+ */
+ if (*p->p_sysent->sv_trap != NULL &&
+ (*p->p_sysent->sv_trap)(td) == 0)
+ goto userout;
+
addr = frame->tf_addr;
i = trap_pfault(frame, TRUE);
if (i == -1)
diff --git a/sys/amd64/include/metadata.h b/sys/amd64/include/metadata.h
index 7dc22bf..98d0272 100644
--- a/sys/amd64/include/metadata.h
+++ b/sys/amd64/include/metadata.h
@@ -1,56 +1,6 @@
/*-
- * Copyright (c) 2003 Peter Wemm <peter@FreeBSD.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
+ * This file is in the public domain.
*/
+/* $FreeBSD$ */
-#ifndef _MACHINE_METADATA_H_
-#define _MACHINE_METADATA_H_
-
-#define MODINFOMD_SMAP 0x1001
-#define MODINFOMD_SMAP_XATTR 0x1002
-#define MODINFOMD_DTBP 0x1003
-#define MODINFOMD_EFI_MAP 0x1004
-#define MODINFOMD_EFI_FB 0x1005
-
-struct efi_map_header {
- size_t memory_size;
- size_t descriptor_size;
- uint32_t descriptor_version;
-};
-
-struct efi_fb {
- uint64_t fb_addr;
- uint64_t fb_size;
- int fb_height;
- int fb_width;
- int fb_stride;
- uint32_t fb_mask_red;
- uint32_t fb_mask_green;
- uint32_t fb_mask_blue;
- uint32_t fb_mask_reserved;
-};
-
-#endif /* !_MACHINE_METADATA_H_ */
+#include <x86/metadata.h>
diff --git a/sys/amd64/include/pcb.h b/sys/amd64/include/pcb.h
index 4bf9a4f..3f8d4c7 100644
--- a/sys/amd64/include/pcb.h
+++ b/sys/amd64/include/pcb.h
@@ -44,15 +44,19 @@
#include <machine/segments.h>
#ifdef __amd64__
+/*
+ * NB: The fields marked with (*) are used by kernel debuggers. Their
+ * ABI should be preserved.
+ */
struct pcb {
- register_t pcb_r15;
- register_t pcb_r14;
- register_t pcb_r13;
- register_t pcb_r12;
- register_t pcb_rbp;
- register_t pcb_rsp;
- register_t pcb_rbx;
- register_t pcb_rip;
+ register_t pcb_r15; /* (*) */
+ register_t pcb_r14; /* (*) */
+ register_t pcb_r13; /* (*) */
+ register_t pcb_r12; /* (*) */
+ register_t pcb_rbp; /* (*) */
+ register_t pcb_rsp; /* (*) */
+ register_t pcb_rbx; /* (*) */
+ register_t pcb_rip; /* (*) */
register_t pcb_fsbase;
register_t pcb_gsbase;
register_t pcb_kgsbase;
diff --git a/sys/amd64/linux/linux_proto.h b/sys/amd64/linux/linux_proto.h
index eedd423..0a0cbe6 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: stable/10/sys/amd64/linux/syscalls.master 293592 2016-01-09 17:54:37Z dchagin
+ * created from FreeBSD: stable/10/sys/amd64/linux/syscalls.master 294368 2016-01-20 01:09:53Z jhb
*/
#ifndef _LINUX_SYSPROTO_H_
diff --git a/sys/amd64/linux/linux_syscall.h b/sys/amd64/linux/linux_syscall.h
index c8d811a..874651c 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: stable/10/sys/amd64/linux/syscalls.master 293592 2016-01-09 17:54:37Z dchagin
+ * created from FreeBSD: stable/10/sys/amd64/linux/syscalls.master 294368 2016-01-20 01:09:53Z jhb
*/
#define LINUX_SYS_read 0
diff --git a/sys/amd64/linux/linux_syscalls.c b/sys/amd64/linux/linux_syscalls.c
index 5c1e1a2..fcea91e 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: stable/10/sys/amd64/linux/syscalls.master 293592 2016-01-09 17:54:37Z dchagin
+ * created from FreeBSD: stable/10/sys/amd64/linux/syscalls.master 294368 2016-01-20 01:09:53Z jhb
*/
const char *linux_syscallnames[] = {
diff --git a/sys/amd64/linux/linux_sysent.c b/sys/amd64/linux/linux_sysent.c
index 97a15cc..14d5c87 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: stable/10/sys/amd64/linux/syscalls.master 293592 2016-01-09 17:54:37Z dchagin
+ * created from FreeBSD: stable/10/sys/amd64/linux/syscalls.master 294368 2016-01-20 01:09:53Z jhb
*/
#include <sys/param.h>
diff --git a/sys/amd64/linux/linux_systrace_args.c b/sys/amd64/linux/linux_systrace_args.c
index 529e768..d649eed 100644
--- a/sys/amd64/linux/linux_systrace_args.c
+++ b/sys/amd64/linux/linux_systrace_args.c
@@ -73,8 +73,8 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
/* poll */
case 7: {
struct poll_args *p = params;
- iarg[0] = p->*; /* struct pollfd */
- uarg[1] = p->nfds; /* unsigned int */
+ uarg[0] = (intptr_t) p->fds; /* struct pollfd * */
+ uarg[1] = p->nfds; /* u_int */
iarg[2] = p->timeout; /* int */
*n_args = 3;
break;
@@ -591,7 +591,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
iarg[0] = p->semid; /* l_int */
iarg[1] = p->semnum; /* l_int */
iarg[2] = p->cmd; /* l_int */
- uarg[3] = p->arg; /* union l_semun */
+ uarg[3] = p->arg.buf; /* union l_semun */
*n_args = 4;
break;
}
@@ -1327,7 +1327,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
/* settimeofday */
case 164: {
struct settimeofday_args *p = params;
- uarg[0] = (intptr_t) p->tp; /* struct l_timeval * */
+ uarg[0] = (intptr_t) p->tv; /* struct l_timeval * */
uarg[1] = (intptr_t) p->tzp; /* struct timezone * */
*n_args = 2;
break;
@@ -2380,10 +2380,10 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
case 7:
switch(ndx) {
case 0:
- p = "struct pollfd";
+ p = "struct pollfd *";
break;
case 1:
- p = "unsigned int";
+ p = "u_int";
break;
case 2:
p = "int";
diff --git a/sys/amd64/linux/linux_sysvec.c b/sys/amd64/linux/linux_sysvec.c
index 37c1b69..d53a266 100644
--- a/sys/amd64/linux/linux_sysvec.c
+++ b/sys/amd64/linux/linux_sysvec.c
@@ -129,6 +129,7 @@ static void linux_set_syscall_retval(struct thread *td, int error);
static int linux_fetch_syscall_args(struct thread *td, struct syscall_args *sa);
static void linux_exec_setregs(struct thread *td, struct image_params *imgp,
u_long stack);
+static int linux_vsyscall(struct thread *td);
/*
* Linux syscalls return negative errno's, we do positive and map them
@@ -746,6 +747,53 @@ exec_linux_imgact_try(struct image_params *imgp)
return(error);
}
+#define LINUX_VSYSCALL_START (-10UL << 20)
+#define LINUX_VSYSCALL_SZ 1024
+
+const unsigned long linux_vsyscall_vector[] = {
+ LINUX_SYS_gettimeofday,
+ LINUX_SYS_linux_time,
+ /* getcpu not implemented */
+};
+
+static int
+linux_vsyscall(struct thread *td)
+{
+ struct trapframe *frame;
+ uint64_t retqaddr;
+ int code, traced;
+ int error;
+
+ frame = td->td_frame;
+
+ /* Check %rip for vsyscall area */
+ if (__predict_true(frame->tf_rip < LINUX_VSYSCALL_START))
+ return (EINVAL);
+ if ((frame->tf_rip & (LINUX_VSYSCALL_SZ - 1)) != 0)
+ return (EINVAL);
+ code = (frame->tf_rip - LINUX_VSYSCALL_START) / LINUX_VSYSCALL_SZ;
+ if (code >= nitems(linux_vsyscall_vector))
+ return (EINVAL);
+
+ /*
+ * vsyscall called as callq *(%rax), so we must
+ * use return address from %rsp and also fixup %rsp
+ */
+ error = copyin((void *)frame->tf_rsp, &retqaddr, sizeof(retqaddr));
+ if (error)
+ return (error);
+
+ frame->tf_rip = retqaddr;
+ frame->tf_rax = linux_vsyscall_vector[code];
+ frame->tf_rsp += 8;
+
+ traced = (frame->tf_flags & PSL_T);
+
+ amd64_syscall(td, traced);
+
+ return (0);
+}
+
struct sysentvec elf_linux_sysvec = {
.sv_size = LINUX_SYS_MAXSYSCALL,
.sv_table = linux_sysent,
@@ -781,7 +829,8 @@ struct sysentvec elf_linux_sysvec = {
.sv_shared_page_base = SHAREDPAGE,
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = linux_schedtail,
- .sv_thread_detach = linux_thread_detach
+ .sv_thread_detach = linux_thread_detach,
+ .sv_trap = linux_vsyscall,
};
static void
diff --git a/sys/amd64/linux/syscalls.master b/sys/amd64/linux/syscalls.master
index d840f88..87c8000 100644
--- a/sys/amd64/linux/syscalls.master
+++ b/sys/amd64/linux/syscalls.master
@@ -49,8 +49,8 @@
struct l_newstat *buf); }
6 AUE_LSTAT STD { int linux_newlstat(char *path, \
struct l_newstat *buf); }
-7 AUE_POLL NOPROTO { int poll(struct pollfd*, \
- unsigned int nfds, int timeout); }
+7 AUE_POLL NOPROTO { int poll(struct pollfd *fds, u_int nfds, \
+ int timeout); }
8 AUE_LSEEK STD { int linux_lseek(l_uint fdes, l_off_t off, \
l_int whence); }
9 AUE_MMAP STD { int linux_mmap2(l_ulong addr, l_ulong len, \
@@ -316,7 +316,7 @@
161 AUE_CHROOT NOPROTO { int chroot(char *path); }
162 AUE_SYNC NOPROTO { int sync(void); }
163 AUE_ACCT NOPROTO { int acct(char *path); }
-164 AUE_SETTIMEOFDAY NOPROTO { int settimeofday(struct l_timeval *tp, struct timezone *tzp); }
+164 AUE_SETTIMEOFDAY NOPROTO { int settimeofday(struct l_timeval *tv, struct timezone *tzp); }
165 AUE_MOUNT STD { int linux_mount(char *specialfile, \
char *dir, char *filesystemtype, \
l_ulong rwflag, void *data); }
diff --git a/sys/amd64/linux32/linux.h b/sys/amd64/linux32/linux.h
index e3b9f11..02d12f5 100644
--- a/sys/amd64/linux32/linux.h
+++ b/sys/amd64/linux32/linux.h
@@ -40,7 +40,7 @@
* debugging support
*/
extern u_char linux_debug_map[];
-#define ldebug(name) isclr(linux_debug_map, LINUX_SYS_linux_ ## name)
+#define ldebug(name) isclr(linux_debug_map, LINUX32_SYS_linux_ ## name)
#define ARGS(nm, fmt) "linux(%ld/%ld): "#nm"("fmt")\n", \
(long)td->td_proc->p_pid, (long)td->td_tid
#define LMSG(fmt) "linux(%ld/%ld): "fmt"\n", \
diff --git a/sys/amd64/linux32/linux32_locore.s b/sys/amd64/linux32/linux32_locore.s
index 4edbdf3..7bbd69a 100644
--- a/sys/amd64/linux32/linux32_locore.s
+++ b/sys/amd64/linux32/linux32_locore.s
@@ -28,7 +28,7 @@ NON_GPROF_ENTRY(linux32_sigcode)
jmp *LINUX_SIGF_HANDLER(%ebx)
.startsigcode:
popl %eax
- movl $LINUX_SYS_linux_sigreturn,%eax /* linux_sigreturn() */
+ movl $LINUX32_SYS_linux_sigreturn,%eax /* linux_sigreturn() */
int $0x80 /* enter kernel with args */
.endsigcode:
0: jmp 0b
@@ -44,7 +44,7 @@ NON_GPROF_ENTRY(linux32_rt_sigcode)
push %eax
jmp *LINUX_RT_SIGF_HANDLER(%edi)
.startrtsigcode:
- movl $LINUX_SYS_linux_rt_sigreturn,%eax /* linux_rt_sigreturn() */
+ movl $LINUX32_SYS_linux_rt_sigreturn,%eax /* linux_rt_sigreturn() */
int $0x80 /* enter kernel with args */
.endrtsigcode:
0: jmp 0b
diff --git a/sys/amd64/linux32/linux32_proto.h b/sys/amd64/linux32/linux32_proto.h
index 56106d7..124abb1 100644
--- a/sys/amd64/linux32/linux32_proto.h
+++ b/sys/amd64/linux32/linux32_proto.h
@@ -3,11 +3,11 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: stable/10/sys/amd64/linux32/syscalls.master 293592 2016-01-09 17:54:37Z dchagin
+ * created from FreeBSD: stable/10/sys/amd64/linux32/syscalls.master 294368 2016-01-20 01:09:53Z jhb
*/
-#ifndef _LINUX_SYSPROTO_H_
-#define _LINUX_SYSPROTO_H_
+#ifndef _LINUX32_SYSPROTO_H_
+#define _LINUX32_SYSPROTO_H_
#include <sys/signal.h>
#include <sys/acl.h>
@@ -1464,286 +1464,286 @@ int linux_process_vm_writev(struct thread *, struct linux_process_vm_writev_args
#endif /* COMPAT_FREEBSD7 */
-#define LINUX_SYS_AUE_linux_exit AUE_EXIT
-#define LINUX_SYS_AUE_linux_fork AUE_FORK
-#define LINUX_SYS_AUE_linux_open AUE_OPEN_RWTC
-#define LINUX_SYS_AUE_linux_waitpid AUE_WAIT4
-#define LINUX_SYS_AUE_linux_creat AUE_CREAT
-#define LINUX_SYS_AUE_linux_link AUE_LINK
-#define LINUX_SYS_AUE_linux_unlink AUE_UNLINK
-#define LINUX_SYS_AUE_linux_execve AUE_EXECVE
-#define LINUX_SYS_AUE_linux_chdir AUE_CHDIR
-#define LINUX_SYS_AUE_linux_time AUE_NULL
-#define LINUX_SYS_AUE_linux_mknod AUE_MKNOD
-#define LINUX_SYS_AUE_linux_chmod AUE_CHMOD
-#define LINUX_SYS_AUE_linux_lchown16 AUE_LCHOWN
-#define LINUX_SYS_AUE_linux_stat AUE_STAT
-#define LINUX_SYS_AUE_linux_lseek AUE_LSEEK
-#define LINUX_SYS_AUE_linux_getpid AUE_GETPID
-#define LINUX_SYS_AUE_linux_mount AUE_MOUNT
-#define LINUX_SYS_AUE_linux_oldumount AUE_UMOUNT
-#define LINUX_SYS_AUE_linux_setuid16 AUE_SETUID
-#define LINUX_SYS_AUE_linux_getuid16 AUE_GETUID
-#define LINUX_SYS_AUE_linux_stime AUE_SETTIMEOFDAY
-#define LINUX_SYS_AUE_linux_ptrace AUE_PTRACE
-#define LINUX_SYS_AUE_linux_alarm AUE_NULL
-#define LINUX_SYS_AUE_linux_pause AUE_NULL
-#define LINUX_SYS_AUE_linux_utime AUE_UTIME
-#define LINUX_SYS_AUE_linux_access AUE_ACCESS
-#define LINUX_SYS_AUE_linux_nice AUE_NICE
-#define LINUX_SYS_AUE_linux_kill AUE_KILL
-#define LINUX_SYS_AUE_linux_rename AUE_RENAME
-#define LINUX_SYS_AUE_linux_mkdir AUE_MKDIR
-#define LINUX_SYS_AUE_linux_rmdir AUE_RMDIR
-#define LINUX_SYS_AUE_linux_pipe AUE_PIPE
-#define LINUX_SYS_AUE_linux_times AUE_NULL
-#define LINUX_SYS_AUE_linux_brk AUE_NULL
-#define LINUX_SYS_AUE_linux_setgid16 AUE_SETGID
-#define LINUX_SYS_AUE_linux_getgid16 AUE_GETGID
-#define LINUX_SYS_AUE_linux_signal AUE_NULL
-#define LINUX_SYS_AUE_linux_geteuid16 AUE_GETEUID
-#define LINUX_SYS_AUE_linux_getegid16 AUE_GETEGID
-#define LINUX_SYS_AUE_linux_umount AUE_UMOUNT
-#define LINUX_SYS_AUE_linux_ioctl AUE_IOCTL
-#define LINUX_SYS_AUE_linux_fcntl AUE_FCNTL
-#define LINUX_SYS_AUE_linux_olduname AUE_NULL
-#define LINUX_SYS_AUE_linux_ustat AUE_NULL
-#define LINUX_SYS_AUE_linux_getppid AUE_GETPPID
-#define LINUX_SYS_AUE_linux_sigaction AUE_NULL
-#define LINUX_SYS_AUE_linux_sgetmask AUE_NULL
-#define LINUX_SYS_AUE_linux_ssetmask AUE_NULL
-#define LINUX_SYS_AUE_linux_setreuid16 AUE_SETREUID
-#define LINUX_SYS_AUE_linux_setregid16 AUE_SETREGID
-#define LINUX_SYS_AUE_linux_sigsuspend AUE_NULL
-#define LINUX_SYS_AUE_linux_sigpending AUE_NULL
-#define LINUX_SYS_AUE_linux_sethostname AUE_SYSCTL
-#define LINUX_SYS_AUE_linux_setrlimit AUE_SETRLIMIT
-#define LINUX_SYS_AUE_linux_old_getrlimit AUE_GETRLIMIT
-#define LINUX_SYS_AUE_linux_getrusage AUE_GETRUSAGE
-#define LINUX_SYS_AUE_linux_gettimeofday AUE_NULL
-#define LINUX_SYS_AUE_linux_settimeofday AUE_SETTIMEOFDAY
-#define LINUX_SYS_AUE_linux_getgroups16 AUE_GETGROUPS
-#define LINUX_SYS_AUE_linux_setgroups16 AUE_SETGROUPS
-#define LINUX_SYS_AUE_linux_old_select AUE_SELECT
-#define LINUX_SYS_AUE_linux_symlink AUE_SYMLINK
-#define LINUX_SYS_AUE_linux_lstat AUE_LSTAT
-#define LINUX_SYS_AUE_linux_readlink AUE_READLINK
-#define LINUX_SYS_AUE_linux_reboot AUE_REBOOT
-#define LINUX_SYS_AUE_linux_readdir AUE_GETDIRENTRIES
-#define LINUX_SYS_AUE_linux_mmap AUE_MMAP
-#define LINUX_SYS_AUE_linux_truncate AUE_TRUNCATE
-#define LINUX_SYS_AUE_linux_ftruncate AUE_FTRUNCATE
-#define LINUX_SYS_AUE_linux_getpriority AUE_GETPRIORITY
-#define LINUX_SYS_AUE_linux_statfs AUE_STATFS
-#define LINUX_SYS_AUE_linux_fstatfs AUE_FSTATFS
-#define LINUX_SYS_AUE_linux_socketcall AUE_NULL
-#define LINUX_SYS_AUE_linux_syslog AUE_NULL
-#define LINUX_SYS_AUE_linux_setitimer AUE_SETITIMER
-#define LINUX_SYS_AUE_linux_getitimer AUE_GETITIMER
-#define LINUX_SYS_AUE_linux_newstat AUE_STAT
-#define LINUX_SYS_AUE_linux_newlstat AUE_LSTAT
-#define LINUX_SYS_AUE_linux_newfstat AUE_FSTAT
-#define LINUX_SYS_AUE_linux_uname AUE_NULL
-#define LINUX_SYS_AUE_linux_iopl AUE_NULL
-#define LINUX_SYS_AUE_linux_vhangup AUE_NULL
-#define LINUX_SYS_AUE_linux_wait4 AUE_WAIT4
-#define LINUX_SYS_AUE_linux_swapoff AUE_SWAPOFF
-#define LINUX_SYS_AUE_linux_sysinfo AUE_NULL
-#define LINUX_SYS_AUE_linux_ipc AUE_NULL
-#define LINUX_SYS_AUE_linux_sigreturn AUE_SIGRETURN
-#define LINUX_SYS_AUE_linux_clone AUE_RFORK
-#define LINUX_SYS_AUE_linux_setdomainname AUE_SYSCTL
-#define LINUX_SYS_AUE_linux_newuname AUE_NULL
-#define LINUX_SYS_AUE_linux_adjtimex AUE_ADJTIME
-#define LINUX_SYS_AUE_linux_mprotect AUE_MPROTECT
-#define LINUX_SYS_AUE_linux_sigprocmask AUE_SIGPROCMASK
-#define LINUX_SYS_AUE_linux_create_module AUE_NULL
-#define LINUX_SYS_AUE_linux_init_module AUE_NULL
-#define LINUX_SYS_AUE_linux_delete_module AUE_NULL
-#define LINUX_SYS_AUE_linux_get_kernel_syms AUE_NULL
-#define LINUX_SYS_AUE_linux_quotactl AUE_QUOTACTL
-#define LINUX_SYS_AUE_linux_bdflush AUE_BDFLUSH
-#define LINUX_SYS_AUE_linux_sysfs AUE_NULL
-#define LINUX_SYS_AUE_linux_personality AUE_PERSONALITY
-#define LINUX_SYS_AUE_linux_setfsuid16 AUE_SETFSUID
-#define LINUX_SYS_AUE_linux_setfsgid16 AUE_SETFSGID
-#define LINUX_SYS_AUE_linux_llseek AUE_LSEEK
-#define LINUX_SYS_AUE_linux_getdents AUE_GETDIRENTRIES
-#define LINUX_SYS_AUE_linux_select AUE_SELECT
-#define LINUX_SYS_AUE_linux_msync AUE_MSYNC
-#define LINUX_SYS_AUE_linux_readv AUE_READV
-#define LINUX_SYS_AUE_linux_writev AUE_WRITEV
-#define LINUX_SYS_AUE_linux_getsid AUE_GETSID
-#define LINUX_SYS_AUE_linux_fdatasync AUE_NULL
-#define LINUX_SYS_AUE_linux_sysctl AUE_SYSCTL
-#define LINUX_SYS_AUE_linux_sched_setparam AUE_SCHED_SETPARAM
-#define LINUX_SYS_AUE_linux_sched_getparam AUE_SCHED_GETPARAM
-#define LINUX_SYS_AUE_linux_sched_setscheduler AUE_SCHED_SETSCHEDULER
-#define LINUX_SYS_AUE_linux_sched_getscheduler AUE_SCHED_GETSCHEDULER
-#define LINUX_SYS_AUE_linux_sched_get_priority_max AUE_SCHED_GET_PRIORITY_MAX
-#define LINUX_SYS_AUE_linux_sched_get_priority_min AUE_SCHED_GET_PRIORITY_MIN
-#define LINUX_SYS_AUE_linux_sched_rr_get_interval AUE_SCHED_RR_GET_INTERVAL
-#define LINUX_SYS_AUE_linux_nanosleep AUE_NULL
-#define LINUX_SYS_AUE_linux_mremap AUE_NULL
-#define LINUX_SYS_AUE_linux_setresuid16 AUE_SETRESUID
-#define LINUX_SYS_AUE_linux_getresuid16 AUE_GETRESUID
-#define LINUX_SYS_AUE_linux_query_module AUE_NULL
-#define LINUX_SYS_AUE_linux_nfsservctl AUE_NULL
-#define LINUX_SYS_AUE_linux_setresgid16 AUE_SETRESGID
-#define LINUX_SYS_AUE_linux_getresgid16 AUE_GETRESGID
-#define LINUX_SYS_AUE_linux_prctl AUE_PRCTL
-#define LINUX_SYS_AUE_linux_rt_sigreturn AUE_NULL
-#define LINUX_SYS_AUE_linux_rt_sigaction AUE_NULL
-#define LINUX_SYS_AUE_linux_rt_sigprocmask AUE_NULL
-#define LINUX_SYS_AUE_linux_rt_sigpending AUE_NULL
-#define LINUX_SYS_AUE_linux_rt_sigtimedwait AUE_NULL
-#define LINUX_SYS_AUE_linux_rt_sigqueueinfo AUE_NULL
-#define LINUX_SYS_AUE_linux_rt_sigsuspend AUE_NULL
-#define LINUX_SYS_AUE_linux_pread AUE_PREAD
-#define LINUX_SYS_AUE_linux_pwrite AUE_PWRITE
-#define LINUX_SYS_AUE_linux_chown16 AUE_CHOWN
-#define LINUX_SYS_AUE_linux_getcwd AUE_GETCWD
-#define LINUX_SYS_AUE_linux_capget AUE_CAPGET
-#define LINUX_SYS_AUE_linux_capset AUE_CAPSET
-#define LINUX_SYS_AUE_linux_sigaltstack AUE_NULL
-#define LINUX_SYS_AUE_linux_sendfile AUE_SENDFILE
-#define LINUX_SYS_AUE_linux_vfork AUE_VFORK
-#define LINUX_SYS_AUE_linux_getrlimit AUE_GETRLIMIT
-#define LINUX_SYS_AUE_linux_mmap2 AUE_MMAP
-#define LINUX_SYS_AUE_linux_truncate64 AUE_TRUNCATE
-#define LINUX_SYS_AUE_linux_ftruncate64 AUE_FTRUNCATE
-#define LINUX_SYS_AUE_linux_stat64 AUE_STAT
-#define LINUX_SYS_AUE_linux_lstat64 AUE_LSTAT
-#define LINUX_SYS_AUE_linux_fstat64 AUE_FSTAT
-#define LINUX_SYS_AUE_linux_lchown AUE_LCHOWN
-#define LINUX_SYS_AUE_linux_getuid AUE_GETUID
-#define LINUX_SYS_AUE_linux_getgid AUE_GETGID
-#define LINUX_SYS_AUE_linux_getgroups AUE_GETGROUPS
-#define LINUX_SYS_AUE_linux_setgroups AUE_SETGROUPS
-#define LINUX_SYS_AUE_linux_chown AUE_CHOWN
-#define LINUX_SYS_AUE_linux_setfsuid AUE_SETFSUID
-#define LINUX_SYS_AUE_linux_setfsgid AUE_SETFSGID
-#define LINUX_SYS_AUE_linux_pivot_root AUE_PIVOT_ROOT
-#define LINUX_SYS_AUE_linux_mincore AUE_MINCORE
-#define LINUX_SYS_AUE_linux_getdents64 AUE_GETDIRENTRIES
-#define LINUX_SYS_AUE_linux_fcntl64 AUE_FCNTL
-#define LINUX_SYS_AUE_linux_gettid AUE_NULL
-#define LINUX_SYS_AUE_linux_setxattr AUE_NULL
-#define LINUX_SYS_AUE_linux_lsetxattr AUE_NULL
-#define LINUX_SYS_AUE_linux_fsetxattr AUE_NULL
-#define LINUX_SYS_AUE_linux_getxattr AUE_NULL
-#define LINUX_SYS_AUE_linux_lgetxattr AUE_NULL
-#define LINUX_SYS_AUE_linux_fgetxattr AUE_NULL
-#define LINUX_SYS_AUE_linux_listxattr AUE_NULL
-#define LINUX_SYS_AUE_linux_llistxattr AUE_NULL
-#define LINUX_SYS_AUE_linux_flistxattr AUE_NULL
-#define LINUX_SYS_AUE_linux_removexattr AUE_NULL
-#define LINUX_SYS_AUE_linux_lremovexattr AUE_NULL
-#define LINUX_SYS_AUE_linux_fremovexattr AUE_NULL
-#define LINUX_SYS_AUE_linux_tkill AUE_NULL
-#define LINUX_SYS_AUE_linux_sys_futex AUE_NULL
-#define LINUX_SYS_AUE_linux_sched_setaffinity AUE_NULL
-#define LINUX_SYS_AUE_linux_sched_getaffinity AUE_NULL
-#define LINUX_SYS_AUE_linux_set_thread_area AUE_NULL
-#define LINUX_SYS_AUE_linux_fadvise64 AUE_NULL
-#define LINUX_SYS_AUE_linux_exit_group AUE_EXIT
-#define LINUX_SYS_AUE_linux_lookup_dcookie AUE_NULL
-#define LINUX_SYS_AUE_linux_epoll_create AUE_NULL
-#define LINUX_SYS_AUE_linux_epoll_ctl AUE_NULL
-#define LINUX_SYS_AUE_linux_epoll_wait AUE_NULL
-#define LINUX_SYS_AUE_linux_remap_file_pages AUE_NULL
-#define LINUX_SYS_AUE_linux_set_tid_address AUE_NULL
-#define LINUX_SYS_AUE_linux_timer_create AUE_NULL
-#define LINUX_SYS_AUE_linux_timer_settime AUE_NULL
-#define LINUX_SYS_AUE_linux_timer_gettime AUE_NULL
-#define LINUX_SYS_AUE_linux_timer_getoverrun AUE_NULL
-#define LINUX_SYS_AUE_linux_timer_delete AUE_NULL
-#define LINUX_SYS_AUE_linux_clock_settime AUE_CLOCK_SETTIME
-#define LINUX_SYS_AUE_linux_clock_gettime AUE_NULL
-#define LINUX_SYS_AUE_linux_clock_getres AUE_NULL
-#define LINUX_SYS_AUE_linux_clock_nanosleep AUE_NULL
-#define LINUX_SYS_AUE_linux_statfs64 AUE_STATFS
-#define LINUX_SYS_AUE_linux_fstatfs64 AUE_FSTATFS
-#define LINUX_SYS_AUE_linux_tgkill AUE_NULL
-#define LINUX_SYS_AUE_linux_utimes AUE_UTIMES
-#define LINUX_SYS_AUE_linux_fadvise64_64 AUE_NULL
-#define LINUX_SYS_AUE_linux_mbind AUE_NULL
-#define LINUX_SYS_AUE_linux_get_mempolicy AUE_NULL
-#define LINUX_SYS_AUE_linux_set_mempolicy AUE_NULL
-#define LINUX_SYS_AUE_linux_mq_open AUE_NULL
-#define LINUX_SYS_AUE_linux_mq_unlink AUE_NULL
-#define LINUX_SYS_AUE_linux_mq_timedsend AUE_NULL
-#define LINUX_SYS_AUE_linux_mq_timedreceive AUE_NULL
-#define LINUX_SYS_AUE_linux_mq_notify AUE_NULL
-#define LINUX_SYS_AUE_linux_mq_getsetattr AUE_NULL
-#define LINUX_SYS_AUE_linux_kexec_load AUE_NULL
-#define LINUX_SYS_AUE_linux_waitid AUE_WAIT6
-#define LINUX_SYS_AUE_linux_add_key AUE_NULL
-#define LINUX_SYS_AUE_linux_request_key AUE_NULL
-#define LINUX_SYS_AUE_linux_keyctl AUE_NULL
-#define LINUX_SYS_AUE_linux_ioprio_set AUE_NULL
-#define LINUX_SYS_AUE_linux_ioprio_get AUE_NULL
-#define LINUX_SYS_AUE_linux_inotify_init AUE_NULL
-#define LINUX_SYS_AUE_linux_inotify_add_watch AUE_NULL
-#define LINUX_SYS_AUE_linux_inotify_rm_watch AUE_NULL
-#define LINUX_SYS_AUE_linux_migrate_pages AUE_NULL
-#define LINUX_SYS_AUE_linux_openat AUE_OPEN_RWTC
-#define LINUX_SYS_AUE_linux_mkdirat AUE_MKDIRAT
-#define LINUX_SYS_AUE_linux_mknodat AUE_MKNODAT
-#define LINUX_SYS_AUE_linux_fchownat AUE_FCHOWNAT
-#define LINUX_SYS_AUE_linux_futimesat AUE_FUTIMESAT
-#define LINUX_SYS_AUE_linux_fstatat64 AUE_FSTATAT
-#define LINUX_SYS_AUE_linux_unlinkat AUE_UNLINKAT
-#define LINUX_SYS_AUE_linux_renameat AUE_RENAMEAT
-#define LINUX_SYS_AUE_linux_linkat AUE_LINKAT
-#define LINUX_SYS_AUE_linux_symlinkat AUE_SYMLINKAT
-#define LINUX_SYS_AUE_linux_readlinkat AUE_READLINKAT
-#define LINUX_SYS_AUE_linux_fchmodat AUE_FCHMODAT
-#define LINUX_SYS_AUE_linux_faccessat AUE_FACCESSAT
-#define LINUX_SYS_AUE_linux_pselect6 AUE_SELECT
-#define LINUX_SYS_AUE_linux_ppoll AUE_POLL
-#define LINUX_SYS_AUE_linux_unshare AUE_NULL
-#define LINUX_SYS_AUE_linux_set_robust_list AUE_NULL
-#define LINUX_SYS_AUE_linux_get_robust_list AUE_NULL
-#define LINUX_SYS_AUE_linux_splice AUE_NULL
-#define LINUX_SYS_AUE_linux_sync_file_range AUE_NULL
-#define LINUX_SYS_AUE_linux_tee AUE_NULL
-#define LINUX_SYS_AUE_linux_vmsplice AUE_NULL
-#define LINUX_SYS_AUE_linux_move_pages AUE_NULL
-#define LINUX_SYS_AUE_linux_getcpu AUE_NULL
-#define LINUX_SYS_AUE_linux_epoll_pwait AUE_NULL
-#define LINUX_SYS_AUE_linux_utimensat AUE_FUTIMESAT
-#define LINUX_SYS_AUE_linux_signalfd AUE_NULL
-#define LINUX_SYS_AUE_linux_timerfd_create AUE_NULL
-#define LINUX_SYS_AUE_linux_eventfd AUE_NULL
-#define LINUX_SYS_AUE_linux_fallocate AUE_NULL
-#define LINUX_SYS_AUE_linux_timerfd_settime AUE_NULL
-#define LINUX_SYS_AUE_linux_timerfd_gettime AUE_NULL
-#define LINUX_SYS_AUE_linux_signalfd4 AUE_NULL
-#define LINUX_SYS_AUE_linux_eventfd2 AUE_NULL
-#define LINUX_SYS_AUE_linux_epoll_create1 AUE_NULL
-#define LINUX_SYS_AUE_linux_dup3 AUE_NULL
-#define LINUX_SYS_AUE_linux_pipe2 AUE_NULL
-#define LINUX_SYS_AUE_linux_inotify_init1 AUE_NULL
-#define LINUX_SYS_AUE_linux_preadv AUE_NULL
-#define LINUX_SYS_AUE_linux_pwritev AUE_NULL
-#define LINUX_SYS_AUE_linux_rt_tsigqueueinfo AUE_NULL
-#define LINUX_SYS_AUE_linux_perf_event_open AUE_NULL
-#define LINUX_SYS_AUE_linux_recvmmsg AUE_NULL
-#define LINUX_SYS_AUE_linux_fanotify_init AUE_NULL
-#define LINUX_SYS_AUE_linux_fanotify_mark AUE_NULL
-#define LINUX_SYS_AUE_linux_prlimit64 AUE_NULL
-#define LINUX_SYS_AUE_linux_name_to_handle_at AUE_NULL
-#define LINUX_SYS_AUE_linux_open_by_handle_at AUE_NULL
-#define LINUX_SYS_AUE_linux_clock_adjtime AUE_NULL
-#define LINUX_SYS_AUE_linux_syncfs AUE_SYNC
-#define LINUX_SYS_AUE_linux_sendmmsg AUE_NULL
-#define LINUX_SYS_AUE_linux_setns AUE_NULL
-#define LINUX_SYS_AUE_linux_process_vm_readv AUE_NULL
-#define LINUX_SYS_AUE_linux_process_vm_writev AUE_NULL
+#define LINUX32_SYS_AUE_linux_exit AUE_EXIT
+#define LINUX32_SYS_AUE_linux_fork AUE_FORK
+#define LINUX32_SYS_AUE_linux_open AUE_OPEN_RWTC
+#define LINUX32_SYS_AUE_linux_waitpid AUE_WAIT4
+#define LINUX32_SYS_AUE_linux_creat AUE_CREAT
+#define LINUX32_SYS_AUE_linux_link AUE_LINK
+#define LINUX32_SYS_AUE_linux_unlink AUE_UNLINK
+#define LINUX32_SYS_AUE_linux_execve AUE_EXECVE
+#define LINUX32_SYS_AUE_linux_chdir AUE_CHDIR
+#define LINUX32_SYS_AUE_linux_time AUE_NULL
+#define LINUX32_SYS_AUE_linux_mknod AUE_MKNOD
+#define LINUX32_SYS_AUE_linux_chmod AUE_CHMOD
+#define LINUX32_SYS_AUE_linux_lchown16 AUE_LCHOWN
+#define LINUX32_SYS_AUE_linux_stat AUE_STAT
+#define LINUX32_SYS_AUE_linux_lseek AUE_LSEEK
+#define LINUX32_SYS_AUE_linux_getpid AUE_GETPID
+#define LINUX32_SYS_AUE_linux_mount AUE_MOUNT
+#define LINUX32_SYS_AUE_linux_oldumount AUE_UMOUNT
+#define LINUX32_SYS_AUE_linux_setuid16 AUE_SETUID
+#define LINUX32_SYS_AUE_linux_getuid16 AUE_GETUID
+#define LINUX32_SYS_AUE_linux_stime AUE_SETTIMEOFDAY
+#define LINUX32_SYS_AUE_linux_ptrace AUE_PTRACE
+#define LINUX32_SYS_AUE_linux_alarm AUE_NULL
+#define LINUX32_SYS_AUE_linux_pause AUE_NULL
+#define LINUX32_SYS_AUE_linux_utime AUE_UTIME
+#define LINUX32_SYS_AUE_linux_access AUE_ACCESS
+#define LINUX32_SYS_AUE_linux_nice AUE_NICE
+#define LINUX32_SYS_AUE_linux_kill AUE_KILL
+#define LINUX32_SYS_AUE_linux_rename AUE_RENAME
+#define LINUX32_SYS_AUE_linux_mkdir AUE_MKDIR
+#define LINUX32_SYS_AUE_linux_rmdir AUE_RMDIR
+#define LINUX32_SYS_AUE_linux_pipe AUE_PIPE
+#define LINUX32_SYS_AUE_linux_times AUE_NULL
+#define LINUX32_SYS_AUE_linux_brk AUE_NULL
+#define LINUX32_SYS_AUE_linux_setgid16 AUE_SETGID
+#define LINUX32_SYS_AUE_linux_getgid16 AUE_GETGID
+#define LINUX32_SYS_AUE_linux_signal AUE_NULL
+#define LINUX32_SYS_AUE_linux_geteuid16 AUE_GETEUID
+#define LINUX32_SYS_AUE_linux_getegid16 AUE_GETEGID
+#define LINUX32_SYS_AUE_linux_umount AUE_UMOUNT
+#define LINUX32_SYS_AUE_linux_ioctl AUE_IOCTL
+#define LINUX32_SYS_AUE_linux_fcntl AUE_FCNTL
+#define LINUX32_SYS_AUE_linux_olduname AUE_NULL
+#define LINUX32_SYS_AUE_linux_ustat AUE_NULL
+#define LINUX32_SYS_AUE_linux_getppid AUE_GETPPID
+#define LINUX32_SYS_AUE_linux_sigaction AUE_NULL
+#define LINUX32_SYS_AUE_linux_sgetmask AUE_NULL
+#define LINUX32_SYS_AUE_linux_ssetmask AUE_NULL
+#define LINUX32_SYS_AUE_linux_setreuid16 AUE_SETREUID
+#define LINUX32_SYS_AUE_linux_setregid16 AUE_SETREGID
+#define LINUX32_SYS_AUE_linux_sigsuspend AUE_NULL
+#define LINUX32_SYS_AUE_linux_sigpending AUE_NULL
+#define LINUX32_SYS_AUE_linux_sethostname AUE_SYSCTL
+#define LINUX32_SYS_AUE_linux_setrlimit AUE_SETRLIMIT
+#define LINUX32_SYS_AUE_linux_old_getrlimit AUE_GETRLIMIT
+#define LINUX32_SYS_AUE_linux_getrusage AUE_GETRUSAGE
+#define LINUX32_SYS_AUE_linux_gettimeofday AUE_NULL
+#define LINUX32_SYS_AUE_linux_settimeofday AUE_SETTIMEOFDAY
+#define LINUX32_SYS_AUE_linux_getgroups16 AUE_GETGROUPS
+#define LINUX32_SYS_AUE_linux_setgroups16 AUE_SETGROUPS
+#define LINUX32_SYS_AUE_linux_old_select AUE_SELECT
+#define LINUX32_SYS_AUE_linux_symlink AUE_SYMLINK
+#define LINUX32_SYS_AUE_linux_lstat AUE_LSTAT
+#define LINUX32_SYS_AUE_linux_readlink AUE_READLINK
+#define LINUX32_SYS_AUE_linux_reboot AUE_REBOOT
+#define LINUX32_SYS_AUE_linux_readdir AUE_GETDIRENTRIES
+#define LINUX32_SYS_AUE_linux_mmap AUE_MMAP
+#define LINUX32_SYS_AUE_linux_truncate AUE_TRUNCATE
+#define LINUX32_SYS_AUE_linux_ftruncate AUE_FTRUNCATE
+#define LINUX32_SYS_AUE_linux_getpriority AUE_GETPRIORITY
+#define LINUX32_SYS_AUE_linux_statfs AUE_STATFS
+#define LINUX32_SYS_AUE_linux_fstatfs AUE_FSTATFS
+#define LINUX32_SYS_AUE_linux_socketcall AUE_NULL
+#define LINUX32_SYS_AUE_linux_syslog AUE_NULL
+#define LINUX32_SYS_AUE_linux_setitimer AUE_SETITIMER
+#define LINUX32_SYS_AUE_linux_getitimer AUE_GETITIMER
+#define LINUX32_SYS_AUE_linux_newstat AUE_STAT
+#define LINUX32_SYS_AUE_linux_newlstat AUE_LSTAT
+#define LINUX32_SYS_AUE_linux_newfstat AUE_FSTAT
+#define LINUX32_SYS_AUE_linux_uname AUE_NULL
+#define LINUX32_SYS_AUE_linux_iopl AUE_NULL
+#define LINUX32_SYS_AUE_linux_vhangup AUE_NULL
+#define LINUX32_SYS_AUE_linux_wait4 AUE_WAIT4
+#define LINUX32_SYS_AUE_linux_swapoff AUE_SWAPOFF
+#define LINUX32_SYS_AUE_linux_sysinfo AUE_NULL
+#define LINUX32_SYS_AUE_linux_ipc AUE_NULL
+#define LINUX32_SYS_AUE_linux_sigreturn AUE_SIGRETURN
+#define LINUX32_SYS_AUE_linux_clone AUE_RFORK
+#define LINUX32_SYS_AUE_linux_setdomainname AUE_SYSCTL
+#define LINUX32_SYS_AUE_linux_newuname AUE_NULL
+#define LINUX32_SYS_AUE_linux_adjtimex AUE_ADJTIME
+#define LINUX32_SYS_AUE_linux_mprotect AUE_MPROTECT
+#define LINUX32_SYS_AUE_linux_sigprocmask AUE_SIGPROCMASK
+#define LINUX32_SYS_AUE_linux_create_module AUE_NULL
+#define LINUX32_SYS_AUE_linux_init_module AUE_NULL
+#define LINUX32_SYS_AUE_linux_delete_module AUE_NULL
+#define LINUX32_SYS_AUE_linux_get_kernel_syms AUE_NULL
+#define LINUX32_SYS_AUE_linux_quotactl AUE_QUOTACTL
+#define LINUX32_SYS_AUE_linux_bdflush AUE_BDFLUSH
+#define LINUX32_SYS_AUE_linux_sysfs AUE_NULL
+#define LINUX32_SYS_AUE_linux_personality AUE_PERSONALITY
+#define LINUX32_SYS_AUE_linux_setfsuid16 AUE_SETFSUID
+#define LINUX32_SYS_AUE_linux_setfsgid16 AUE_SETFSGID
+#define LINUX32_SYS_AUE_linux_llseek AUE_LSEEK
+#define LINUX32_SYS_AUE_linux_getdents AUE_GETDIRENTRIES
+#define LINUX32_SYS_AUE_linux_select AUE_SELECT
+#define LINUX32_SYS_AUE_linux_msync AUE_MSYNC
+#define LINUX32_SYS_AUE_linux_readv AUE_READV
+#define LINUX32_SYS_AUE_linux_writev AUE_WRITEV
+#define LINUX32_SYS_AUE_linux_getsid AUE_GETSID
+#define LINUX32_SYS_AUE_linux_fdatasync AUE_NULL
+#define LINUX32_SYS_AUE_linux_sysctl AUE_SYSCTL
+#define LINUX32_SYS_AUE_linux_sched_setparam AUE_SCHED_SETPARAM
+#define LINUX32_SYS_AUE_linux_sched_getparam AUE_SCHED_GETPARAM
+#define LINUX32_SYS_AUE_linux_sched_setscheduler AUE_SCHED_SETSCHEDULER
+#define LINUX32_SYS_AUE_linux_sched_getscheduler AUE_SCHED_GETSCHEDULER
+#define LINUX32_SYS_AUE_linux_sched_get_priority_max AUE_SCHED_GET_PRIORITY_MAX
+#define LINUX32_SYS_AUE_linux_sched_get_priority_min AUE_SCHED_GET_PRIORITY_MIN
+#define LINUX32_SYS_AUE_linux_sched_rr_get_interval AUE_SCHED_RR_GET_INTERVAL
+#define LINUX32_SYS_AUE_linux_nanosleep AUE_NULL
+#define LINUX32_SYS_AUE_linux_mremap AUE_NULL
+#define LINUX32_SYS_AUE_linux_setresuid16 AUE_SETRESUID
+#define LINUX32_SYS_AUE_linux_getresuid16 AUE_GETRESUID
+#define LINUX32_SYS_AUE_linux_query_module AUE_NULL
+#define LINUX32_SYS_AUE_linux_nfsservctl AUE_NULL
+#define LINUX32_SYS_AUE_linux_setresgid16 AUE_SETRESGID
+#define LINUX32_SYS_AUE_linux_getresgid16 AUE_GETRESGID
+#define LINUX32_SYS_AUE_linux_prctl AUE_PRCTL
+#define LINUX32_SYS_AUE_linux_rt_sigreturn AUE_NULL
+#define LINUX32_SYS_AUE_linux_rt_sigaction AUE_NULL
+#define LINUX32_SYS_AUE_linux_rt_sigprocmask AUE_NULL
+#define LINUX32_SYS_AUE_linux_rt_sigpending AUE_NULL
+#define LINUX32_SYS_AUE_linux_rt_sigtimedwait AUE_NULL
+#define LINUX32_SYS_AUE_linux_rt_sigqueueinfo AUE_NULL
+#define LINUX32_SYS_AUE_linux_rt_sigsuspend AUE_NULL
+#define LINUX32_SYS_AUE_linux_pread AUE_PREAD
+#define LINUX32_SYS_AUE_linux_pwrite AUE_PWRITE
+#define LINUX32_SYS_AUE_linux_chown16 AUE_CHOWN
+#define LINUX32_SYS_AUE_linux_getcwd AUE_GETCWD
+#define LINUX32_SYS_AUE_linux_capget AUE_CAPGET
+#define LINUX32_SYS_AUE_linux_capset AUE_CAPSET
+#define LINUX32_SYS_AUE_linux_sigaltstack AUE_NULL
+#define LINUX32_SYS_AUE_linux_sendfile AUE_SENDFILE
+#define LINUX32_SYS_AUE_linux_vfork AUE_VFORK
+#define LINUX32_SYS_AUE_linux_getrlimit AUE_GETRLIMIT
+#define LINUX32_SYS_AUE_linux_mmap2 AUE_MMAP
+#define LINUX32_SYS_AUE_linux_truncate64 AUE_TRUNCATE
+#define LINUX32_SYS_AUE_linux_ftruncate64 AUE_FTRUNCATE
+#define LINUX32_SYS_AUE_linux_stat64 AUE_STAT
+#define LINUX32_SYS_AUE_linux_lstat64 AUE_LSTAT
+#define LINUX32_SYS_AUE_linux_fstat64 AUE_FSTAT
+#define LINUX32_SYS_AUE_linux_lchown AUE_LCHOWN
+#define LINUX32_SYS_AUE_linux_getuid AUE_GETUID
+#define LINUX32_SYS_AUE_linux_getgid AUE_GETGID
+#define LINUX32_SYS_AUE_linux_getgroups AUE_GETGROUPS
+#define LINUX32_SYS_AUE_linux_setgroups AUE_SETGROUPS
+#define LINUX32_SYS_AUE_linux_chown AUE_CHOWN
+#define LINUX32_SYS_AUE_linux_setfsuid AUE_SETFSUID
+#define LINUX32_SYS_AUE_linux_setfsgid AUE_SETFSGID
+#define LINUX32_SYS_AUE_linux_pivot_root AUE_PIVOT_ROOT
+#define LINUX32_SYS_AUE_linux_mincore AUE_MINCORE
+#define LINUX32_SYS_AUE_linux_getdents64 AUE_GETDIRENTRIES
+#define LINUX32_SYS_AUE_linux_fcntl64 AUE_FCNTL
+#define LINUX32_SYS_AUE_linux_gettid AUE_NULL
+#define LINUX32_SYS_AUE_linux_setxattr AUE_NULL
+#define LINUX32_SYS_AUE_linux_lsetxattr AUE_NULL
+#define LINUX32_SYS_AUE_linux_fsetxattr AUE_NULL
+#define LINUX32_SYS_AUE_linux_getxattr AUE_NULL
+#define LINUX32_SYS_AUE_linux_lgetxattr AUE_NULL
+#define LINUX32_SYS_AUE_linux_fgetxattr AUE_NULL
+#define LINUX32_SYS_AUE_linux_listxattr AUE_NULL
+#define LINUX32_SYS_AUE_linux_llistxattr AUE_NULL
+#define LINUX32_SYS_AUE_linux_flistxattr AUE_NULL
+#define LINUX32_SYS_AUE_linux_removexattr AUE_NULL
+#define LINUX32_SYS_AUE_linux_lremovexattr AUE_NULL
+#define LINUX32_SYS_AUE_linux_fremovexattr AUE_NULL
+#define LINUX32_SYS_AUE_linux_tkill AUE_NULL
+#define LINUX32_SYS_AUE_linux_sys_futex AUE_NULL
+#define LINUX32_SYS_AUE_linux_sched_setaffinity AUE_NULL
+#define LINUX32_SYS_AUE_linux_sched_getaffinity AUE_NULL
+#define LINUX32_SYS_AUE_linux_set_thread_area AUE_NULL
+#define LINUX32_SYS_AUE_linux_fadvise64 AUE_NULL
+#define LINUX32_SYS_AUE_linux_exit_group AUE_EXIT
+#define LINUX32_SYS_AUE_linux_lookup_dcookie AUE_NULL
+#define LINUX32_SYS_AUE_linux_epoll_create AUE_NULL
+#define LINUX32_SYS_AUE_linux_epoll_ctl AUE_NULL
+#define LINUX32_SYS_AUE_linux_epoll_wait AUE_NULL
+#define LINUX32_SYS_AUE_linux_remap_file_pages AUE_NULL
+#define LINUX32_SYS_AUE_linux_set_tid_address AUE_NULL
+#define LINUX32_SYS_AUE_linux_timer_create AUE_NULL
+#define LINUX32_SYS_AUE_linux_timer_settime AUE_NULL
+#define LINUX32_SYS_AUE_linux_timer_gettime AUE_NULL
+#define LINUX32_SYS_AUE_linux_timer_getoverrun AUE_NULL
+#define LINUX32_SYS_AUE_linux_timer_delete AUE_NULL
+#define LINUX32_SYS_AUE_linux_clock_settime AUE_CLOCK_SETTIME
+#define LINUX32_SYS_AUE_linux_clock_gettime AUE_NULL
+#define LINUX32_SYS_AUE_linux_clock_getres AUE_NULL
+#define LINUX32_SYS_AUE_linux_clock_nanosleep AUE_NULL
+#define LINUX32_SYS_AUE_linux_statfs64 AUE_STATFS
+#define LINUX32_SYS_AUE_linux_fstatfs64 AUE_FSTATFS
+#define LINUX32_SYS_AUE_linux_tgkill AUE_NULL
+#define LINUX32_SYS_AUE_linux_utimes AUE_UTIMES
+#define LINUX32_SYS_AUE_linux_fadvise64_64 AUE_NULL
+#define LINUX32_SYS_AUE_linux_mbind AUE_NULL
+#define LINUX32_SYS_AUE_linux_get_mempolicy AUE_NULL
+#define LINUX32_SYS_AUE_linux_set_mempolicy AUE_NULL
+#define LINUX32_SYS_AUE_linux_mq_open AUE_NULL
+#define LINUX32_SYS_AUE_linux_mq_unlink AUE_NULL
+#define LINUX32_SYS_AUE_linux_mq_timedsend AUE_NULL
+#define LINUX32_SYS_AUE_linux_mq_timedreceive AUE_NULL
+#define LINUX32_SYS_AUE_linux_mq_notify AUE_NULL
+#define LINUX32_SYS_AUE_linux_mq_getsetattr AUE_NULL
+#define LINUX32_SYS_AUE_linux_kexec_load AUE_NULL
+#define LINUX32_SYS_AUE_linux_waitid AUE_WAIT6
+#define LINUX32_SYS_AUE_linux_add_key AUE_NULL
+#define LINUX32_SYS_AUE_linux_request_key AUE_NULL
+#define LINUX32_SYS_AUE_linux_keyctl AUE_NULL
+#define LINUX32_SYS_AUE_linux_ioprio_set AUE_NULL
+#define LINUX32_SYS_AUE_linux_ioprio_get AUE_NULL
+#define LINUX32_SYS_AUE_linux_inotify_init AUE_NULL
+#define LINUX32_SYS_AUE_linux_inotify_add_watch AUE_NULL
+#define LINUX32_SYS_AUE_linux_inotify_rm_watch AUE_NULL
+#define LINUX32_SYS_AUE_linux_migrate_pages AUE_NULL
+#define LINUX32_SYS_AUE_linux_openat AUE_OPEN_RWTC
+#define LINUX32_SYS_AUE_linux_mkdirat AUE_MKDIRAT
+#define LINUX32_SYS_AUE_linux_mknodat AUE_MKNODAT
+#define LINUX32_SYS_AUE_linux_fchownat AUE_FCHOWNAT
+#define LINUX32_SYS_AUE_linux_futimesat AUE_FUTIMESAT
+#define LINUX32_SYS_AUE_linux_fstatat64 AUE_FSTATAT
+#define LINUX32_SYS_AUE_linux_unlinkat AUE_UNLINKAT
+#define LINUX32_SYS_AUE_linux_renameat AUE_RENAMEAT
+#define LINUX32_SYS_AUE_linux_linkat AUE_LINKAT
+#define LINUX32_SYS_AUE_linux_symlinkat AUE_SYMLINKAT
+#define LINUX32_SYS_AUE_linux_readlinkat AUE_READLINKAT
+#define LINUX32_SYS_AUE_linux_fchmodat AUE_FCHMODAT
+#define LINUX32_SYS_AUE_linux_faccessat AUE_FACCESSAT
+#define LINUX32_SYS_AUE_linux_pselect6 AUE_SELECT
+#define LINUX32_SYS_AUE_linux_ppoll AUE_POLL
+#define LINUX32_SYS_AUE_linux_unshare AUE_NULL
+#define LINUX32_SYS_AUE_linux_set_robust_list AUE_NULL
+#define LINUX32_SYS_AUE_linux_get_robust_list AUE_NULL
+#define LINUX32_SYS_AUE_linux_splice AUE_NULL
+#define LINUX32_SYS_AUE_linux_sync_file_range AUE_NULL
+#define LINUX32_SYS_AUE_linux_tee AUE_NULL
+#define LINUX32_SYS_AUE_linux_vmsplice AUE_NULL
+#define LINUX32_SYS_AUE_linux_move_pages AUE_NULL
+#define LINUX32_SYS_AUE_linux_getcpu AUE_NULL
+#define LINUX32_SYS_AUE_linux_epoll_pwait AUE_NULL
+#define LINUX32_SYS_AUE_linux_utimensat AUE_FUTIMESAT
+#define LINUX32_SYS_AUE_linux_signalfd AUE_NULL
+#define LINUX32_SYS_AUE_linux_timerfd_create AUE_NULL
+#define LINUX32_SYS_AUE_linux_eventfd AUE_NULL
+#define LINUX32_SYS_AUE_linux_fallocate AUE_NULL
+#define LINUX32_SYS_AUE_linux_timerfd_settime AUE_NULL
+#define LINUX32_SYS_AUE_linux_timerfd_gettime AUE_NULL
+#define LINUX32_SYS_AUE_linux_signalfd4 AUE_NULL
+#define LINUX32_SYS_AUE_linux_eventfd2 AUE_NULL
+#define LINUX32_SYS_AUE_linux_epoll_create1 AUE_NULL
+#define LINUX32_SYS_AUE_linux_dup3 AUE_NULL
+#define LINUX32_SYS_AUE_linux_pipe2 AUE_NULL
+#define LINUX32_SYS_AUE_linux_inotify_init1 AUE_NULL
+#define LINUX32_SYS_AUE_linux_preadv AUE_NULL
+#define LINUX32_SYS_AUE_linux_pwritev AUE_NULL
+#define LINUX32_SYS_AUE_linux_rt_tsigqueueinfo AUE_NULL
+#define LINUX32_SYS_AUE_linux_perf_event_open AUE_NULL
+#define LINUX32_SYS_AUE_linux_recvmmsg AUE_NULL
+#define LINUX32_SYS_AUE_linux_fanotify_init AUE_NULL
+#define LINUX32_SYS_AUE_linux_fanotify_mark AUE_NULL
+#define LINUX32_SYS_AUE_linux_prlimit64 AUE_NULL
+#define LINUX32_SYS_AUE_linux_name_to_handle_at AUE_NULL
+#define LINUX32_SYS_AUE_linux_open_by_handle_at AUE_NULL
+#define LINUX32_SYS_AUE_linux_clock_adjtime AUE_NULL
+#define LINUX32_SYS_AUE_linux_syncfs AUE_SYNC
+#define LINUX32_SYS_AUE_linux_sendmmsg AUE_NULL
+#define LINUX32_SYS_AUE_linux_setns AUE_NULL
+#define LINUX32_SYS_AUE_linux_process_vm_readv AUE_NULL
+#define LINUX32_SYS_AUE_linux_process_vm_writev AUE_NULL
#undef PAD_
#undef PADL_
#undef PADR_
-#endif /* !_LINUX_SYSPROTO_H_ */
+#endif /* !_LINUX32_SYSPROTO_H_ */
diff --git a/sys/amd64/linux32/linux32_syscall.h b/sys/amd64/linux32/linux32_syscall.h
index e3424b4..29c78a6 100644
--- a/sys/amd64/linux32/linux32_syscall.h
+++ b/sys/amd64/linux32/linux32_syscall.h
@@ -3,322 +3,322 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: stable/10/sys/amd64/linux32/syscalls.master 293592 2016-01-09 17:54:37Z dchagin
+ * created from FreeBSD: stable/10/sys/amd64/linux32/syscalls.master 294368 2016-01-20 01:09:53Z jhb
*/
-#define LINUX_SYS_linux_exit 1
-#define LINUX_SYS_linux_fork 2
-#define LINUX_SYS_read 3
-#define LINUX_SYS_write 4
-#define LINUX_SYS_linux_open 5
-#define LINUX_SYS_close 6
-#define LINUX_SYS_linux_waitpid 7
-#define LINUX_SYS_linux_creat 8
-#define LINUX_SYS_linux_link 9
-#define LINUX_SYS_linux_unlink 10
-#define LINUX_SYS_linux_execve 11
-#define LINUX_SYS_linux_chdir 12
-#define LINUX_SYS_linux_time 13
-#define LINUX_SYS_linux_mknod 14
-#define LINUX_SYS_linux_chmod 15
-#define LINUX_SYS_linux_lchown16 16
-#define LINUX_SYS_linux_stat 18
-#define LINUX_SYS_linux_lseek 19
-#define LINUX_SYS_linux_getpid 20
-#define LINUX_SYS_linux_mount 21
-#define LINUX_SYS_linux_oldumount 22
-#define LINUX_SYS_linux_setuid16 23
-#define LINUX_SYS_linux_getuid16 24
-#define LINUX_SYS_linux_stime 25
-#define LINUX_SYS_linux_ptrace 26
-#define LINUX_SYS_linux_alarm 27
-#define LINUX_SYS_linux_pause 29
-#define LINUX_SYS_linux_utime 30
-#define LINUX_SYS_linux_access 33
-#define LINUX_SYS_linux_nice 34
-#define LINUX_SYS_sync 36
-#define LINUX_SYS_linux_kill 37
-#define LINUX_SYS_linux_rename 38
-#define LINUX_SYS_linux_mkdir 39
-#define LINUX_SYS_linux_rmdir 40
-#define LINUX_SYS_dup 41
-#define LINUX_SYS_linux_pipe 42
-#define LINUX_SYS_linux_times 43
-#define LINUX_SYS_linux_brk 45
-#define LINUX_SYS_linux_setgid16 46
-#define LINUX_SYS_linux_getgid16 47
-#define LINUX_SYS_linux_signal 48
-#define LINUX_SYS_linux_geteuid16 49
-#define LINUX_SYS_linux_getegid16 50
-#define LINUX_SYS_acct 51
-#define LINUX_SYS_linux_umount 52
-#define LINUX_SYS_linux_ioctl 54
-#define LINUX_SYS_linux_fcntl 55
-#define LINUX_SYS_setpgid 57
-#define LINUX_SYS_linux_olduname 59
-#define LINUX_SYS_umask 60
-#define LINUX_SYS_chroot 61
-#define LINUX_SYS_linux_ustat 62
-#define LINUX_SYS_dup2 63
-#define LINUX_SYS_linux_getppid 64
-#define LINUX_SYS_getpgrp 65
-#define LINUX_SYS_setsid 66
-#define LINUX_SYS_linux_sigaction 67
-#define LINUX_SYS_linux_sgetmask 68
-#define LINUX_SYS_linux_ssetmask 69
-#define LINUX_SYS_linux_setreuid16 70
-#define LINUX_SYS_linux_setregid16 71
-#define LINUX_SYS_linux_sigsuspend 72
-#define LINUX_SYS_linux_sigpending 73
-#define LINUX_SYS_linux_sethostname 74
-#define LINUX_SYS_linux_setrlimit 75
-#define LINUX_SYS_linux_old_getrlimit 76
-#define LINUX_SYS_linux_getrusage 77
-#define LINUX_SYS_linux_gettimeofday 78
-#define LINUX_SYS_linux_settimeofday 79
-#define LINUX_SYS_linux_getgroups16 80
-#define LINUX_SYS_linux_setgroups16 81
-#define LINUX_SYS_linux_old_select 82
-#define LINUX_SYS_linux_symlink 83
-#define LINUX_SYS_linux_lstat 84
-#define LINUX_SYS_linux_readlink 85
-#define LINUX_SYS_swapon 87
-#define LINUX_SYS_linux_reboot 88
-#define LINUX_SYS_linux_readdir 89
-#define LINUX_SYS_linux_mmap 90
-#define LINUX_SYS_munmap 91
-#define LINUX_SYS_linux_truncate 92
-#define LINUX_SYS_linux_ftruncate 93
-#define LINUX_SYS_fchmod 94
-#define LINUX_SYS_fchown 95
-#define LINUX_SYS_linux_getpriority 96
-#define LINUX_SYS_setpriority 97
-#define LINUX_SYS_linux_statfs 99
-#define LINUX_SYS_linux_fstatfs 100
-#define LINUX_SYS_linux_socketcall 102
-#define LINUX_SYS_linux_syslog 103
-#define LINUX_SYS_linux_setitimer 104
-#define LINUX_SYS_linux_getitimer 105
-#define LINUX_SYS_linux_newstat 106
-#define LINUX_SYS_linux_newlstat 107
-#define LINUX_SYS_linux_newfstat 108
-#define LINUX_SYS_linux_uname 109
-#define LINUX_SYS_linux_iopl 110
-#define LINUX_SYS_linux_vhangup 111
-#define LINUX_SYS_linux_wait4 114
-#define LINUX_SYS_linux_swapoff 115
-#define LINUX_SYS_linux_sysinfo 116
-#define LINUX_SYS_linux_ipc 117
-#define LINUX_SYS_fsync 118
-#define LINUX_SYS_linux_sigreturn 119
-#define LINUX_SYS_linux_clone 120
-#define LINUX_SYS_linux_setdomainname 121
-#define LINUX_SYS_linux_newuname 122
-#define LINUX_SYS_linux_adjtimex 124
-#define LINUX_SYS_linux_mprotect 125
-#define LINUX_SYS_linux_sigprocmask 126
-#define LINUX_SYS_linux_create_module 127
-#define LINUX_SYS_linux_init_module 128
-#define LINUX_SYS_linux_delete_module 129
-#define LINUX_SYS_linux_get_kernel_syms 130
-#define LINUX_SYS_linux_quotactl 131
-#define LINUX_SYS_getpgid 132
-#define LINUX_SYS_fchdir 133
-#define LINUX_SYS_linux_bdflush 134
-#define LINUX_SYS_linux_sysfs 135
-#define LINUX_SYS_linux_personality 136
-#define LINUX_SYS_linux_setfsuid16 138
-#define LINUX_SYS_linux_setfsgid16 139
-#define LINUX_SYS_linux_llseek 140
-#define LINUX_SYS_linux_getdents 141
-#define LINUX_SYS_linux_select 142
-#define LINUX_SYS_flock 143
-#define LINUX_SYS_linux_msync 144
-#define LINUX_SYS_linux_readv 145
-#define LINUX_SYS_linux_writev 146
-#define LINUX_SYS_linux_getsid 147
-#define LINUX_SYS_linux_fdatasync 148
-#define LINUX_SYS_linux_sysctl 149
-#define LINUX_SYS_mlock 150
-#define LINUX_SYS_munlock 151
-#define LINUX_SYS_mlockall 152
-#define LINUX_SYS_munlockall 153
-#define LINUX_SYS_linux_sched_setparam 154
-#define LINUX_SYS_linux_sched_getparam 155
-#define LINUX_SYS_linux_sched_setscheduler 156
-#define LINUX_SYS_linux_sched_getscheduler 157
-#define LINUX_SYS_sched_yield 158
-#define LINUX_SYS_linux_sched_get_priority_max 159
-#define LINUX_SYS_linux_sched_get_priority_min 160
-#define LINUX_SYS_linux_sched_rr_get_interval 161
-#define LINUX_SYS_linux_nanosleep 162
-#define LINUX_SYS_linux_mremap 163
-#define LINUX_SYS_linux_setresuid16 164
-#define LINUX_SYS_linux_getresuid16 165
-#define LINUX_SYS_linux_query_module 167
-#define LINUX_SYS_poll 168
-#define LINUX_SYS_linux_nfsservctl 169
-#define LINUX_SYS_linux_setresgid16 170
-#define LINUX_SYS_linux_getresgid16 171
-#define LINUX_SYS_linux_prctl 172
-#define LINUX_SYS_linux_rt_sigreturn 173
-#define LINUX_SYS_linux_rt_sigaction 174
-#define LINUX_SYS_linux_rt_sigprocmask 175
-#define LINUX_SYS_linux_rt_sigpending 176
-#define LINUX_SYS_linux_rt_sigtimedwait 177
-#define LINUX_SYS_linux_rt_sigqueueinfo 178
-#define LINUX_SYS_linux_rt_sigsuspend 179
-#define LINUX_SYS_linux_pread 180
-#define LINUX_SYS_linux_pwrite 181
-#define LINUX_SYS_linux_chown16 182
-#define LINUX_SYS_linux_getcwd 183
-#define LINUX_SYS_linux_capget 184
-#define LINUX_SYS_linux_capset 185
-#define LINUX_SYS_linux_sigaltstack 186
-#define LINUX_SYS_linux_sendfile 187
-#define LINUX_SYS_linux_vfork 190
-#define LINUX_SYS_linux_getrlimit 191
-#define LINUX_SYS_linux_mmap2 192
-#define LINUX_SYS_linux_truncate64 193
-#define LINUX_SYS_linux_ftruncate64 194
-#define LINUX_SYS_linux_stat64 195
-#define LINUX_SYS_linux_lstat64 196
-#define LINUX_SYS_linux_fstat64 197
-#define LINUX_SYS_linux_lchown 198
-#define LINUX_SYS_linux_getuid 199
-#define LINUX_SYS_linux_getgid 200
-#define LINUX_SYS_geteuid 201
-#define LINUX_SYS_getegid 202
-#define LINUX_SYS_setreuid 203
-#define LINUX_SYS_setregid 204
-#define LINUX_SYS_linux_getgroups 205
-#define LINUX_SYS_linux_setgroups 206
-#define LINUX_SYS_setresuid 208
-#define LINUX_SYS_getresuid 209
-#define LINUX_SYS_setresgid 210
-#define LINUX_SYS_getresgid 211
-#define LINUX_SYS_linux_chown 212
-#define LINUX_SYS_setuid 213
-#define LINUX_SYS_setgid 214
-#define LINUX_SYS_linux_setfsuid 215
-#define LINUX_SYS_linux_setfsgid 216
-#define LINUX_SYS_linux_pivot_root 217
-#define LINUX_SYS_linux_mincore 218
-#define LINUX_SYS_madvise 219
-#define LINUX_SYS_linux_getdents64 220
-#define LINUX_SYS_linux_fcntl64 221
-#define LINUX_SYS_linux_gettid 224
-#define LINUX_SYS_linux_setxattr 226
-#define LINUX_SYS_linux_lsetxattr 227
-#define LINUX_SYS_linux_fsetxattr 228
-#define LINUX_SYS_linux_getxattr 229
-#define LINUX_SYS_linux_lgetxattr 230
-#define LINUX_SYS_linux_fgetxattr 231
-#define LINUX_SYS_linux_listxattr 232
-#define LINUX_SYS_linux_llistxattr 233
-#define LINUX_SYS_linux_flistxattr 234
-#define LINUX_SYS_linux_removexattr 235
-#define LINUX_SYS_linux_lremovexattr 236
-#define LINUX_SYS_linux_fremovexattr 237
-#define LINUX_SYS_linux_tkill 238
-#define LINUX_SYS_linux_sys_futex 240
-#define LINUX_SYS_linux_sched_setaffinity 241
-#define LINUX_SYS_linux_sched_getaffinity 242
-#define LINUX_SYS_linux_set_thread_area 243
-#define LINUX_SYS_linux_fadvise64 250
-#define LINUX_SYS_linux_exit_group 252
-#define LINUX_SYS_linux_lookup_dcookie 253
-#define LINUX_SYS_linux_epoll_create 254
-#define LINUX_SYS_linux_epoll_ctl 255
-#define LINUX_SYS_linux_epoll_wait 256
-#define LINUX_SYS_linux_remap_file_pages 257
-#define LINUX_SYS_linux_set_tid_address 258
-#define LINUX_SYS_linux_timer_create 259
-#define LINUX_SYS_linux_timer_settime 260
-#define LINUX_SYS_linux_timer_gettime 261
-#define LINUX_SYS_linux_timer_getoverrun 262
-#define LINUX_SYS_linux_timer_delete 263
-#define LINUX_SYS_linux_clock_settime 264
-#define LINUX_SYS_linux_clock_gettime 265
-#define LINUX_SYS_linux_clock_getres 266
-#define LINUX_SYS_linux_clock_nanosleep 267
-#define LINUX_SYS_linux_statfs64 268
-#define LINUX_SYS_linux_fstatfs64 269
-#define LINUX_SYS_linux_tgkill 270
-#define LINUX_SYS_linux_utimes 271
-#define LINUX_SYS_linux_fadvise64_64 272
-#define LINUX_SYS_linux_mbind 274
-#define LINUX_SYS_linux_get_mempolicy 275
-#define LINUX_SYS_linux_set_mempolicy 276
-#define LINUX_SYS_linux_mq_open 277
-#define LINUX_SYS_linux_mq_unlink 278
-#define LINUX_SYS_linux_mq_timedsend 279
-#define LINUX_SYS_linux_mq_timedreceive 280
-#define LINUX_SYS_linux_mq_notify 281
-#define LINUX_SYS_linux_mq_getsetattr 282
-#define LINUX_SYS_linux_kexec_load 283
-#define LINUX_SYS_linux_waitid 284
-#define LINUX_SYS_linux_add_key 286
-#define LINUX_SYS_linux_request_key 287
-#define LINUX_SYS_linux_keyctl 288
-#define LINUX_SYS_linux_ioprio_set 289
-#define LINUX_SYS_linux_ioprio_get 290
-#define LINUX_SYS_linux_inotify_init 291
-#define LINUX_SYS_linux_inotify_add_watch 292
-#define LINUX_SYS_linux_inotify_rm_watch 293
-#define LINUX_SYS_linux_migrate_pages 294
-#define LINUX_SYS_linux_openat 295
-#define LINUX_SYS_linux_mkdirat 296
-#define LINUX_SYS_linux_mknodat 297
-#define LINUX_SYS_linux_fchownat 298
-#define LINUX_SYS_linux_futimesat 299
-#define LINUX_SYS_linux_fstatat64 300
-#define LINUX_SYS_linux_unlinkat 301
-#define LINUX_SYS_linux_renameat 302
-#define LINUX_SYS_linux_linkat 303
-#define LINUX_SYS_linux_symlinkat 304
-#define LINUX_SYS_linux_readlinkat 305
-#define LINUX_SYS_linux_fchmodat 306
-#define LINUX_SYS_linux_faccessat 307
-#define LINUX_SYS_linux_pselect6 308
-#define LINUX_SYS_linux_ppoll 309
-#define LINUX_SYS_linux_unshare 310
-#define LINUX_SYS_linux_set_robust_list 311
-#define LINUX_SYS_linux_get_robust_list 312
-#define LINUX_SYS_linux_splice 313
-#define LINUX_SYS_linux_sync_file_range 314
-#define LINUX_SYS_linux_tee 315
-#define LINUX_SYS_linux_vmsplice 316
-#define LINUX_SYS_linux_move_pages 317
-#define LINUX_SYS_linux_getcpu 318
-#define LINUX_SYS_linux_epoll_pwait 319
-#define LINUX_SYS_linux_utimensat 320
-#define LINUX_SYS_linux_signalfd 321
-#define LINUX_SYS_linux_timerfd_create 322
-#define LINUX_SYS_linux_eventfd 323
-#define LINUX_SYS_linux_fallocate 324
-#define LINUX_SYS_linux_timerfd_settime 325
-#define LINUX_SYS_linux_timerfd_gettime 326
-#define LINUX_SYS_linux_signalfd4 327
-#define LINUX_SYS_linux_eventfd2 328
-#define LINUX_SYS_linux_epoll_create1 329
-#define LINUX_SYS_linux_dup3 330
-#define LINUX_SYS_linux_pipe2 331
-#define LINUX_SYS_linux_inotify_init1 332
-#define LINUX_SYS_linux_preadv 333
-#define LINUX_SYS_linux_pwritev 334
-#define LINUX_SYS_linux_rt_tsigqueueinfo 335
-#define LINUX_SYS_linux_perf_event_open 336
-#define LINUX_SYS_linux_recvmmsg 337
-#define LINUX_SYS_linux_fanotify_init 338
-#define LINUX_SYS_linux_fanotify_mark 339
-#define LINUX_SYS_linux_prlimit64 340
-#define LINUX_SYS_linux_name_to_handle_at 341
-#define LINUX_SYS_linux_open_by_handle_at 342
-#define LINUX_SYS_linux_clock_adjtime 343
-#define LINUX_SYS_linux_syncfs 344
-#define LINUX_SYS_linux_sendmmsg 345
-#define LINUX_SYS_linux_setns 346
-#define LINUX_SYS_linux_process_vm_readv 347
-#define LINUX_SYS_linux_process_vm_writev 348
-#define LINUX_SYS_MAXSYSCALL 350
+#define LINUX32_SYS_linux_exit 1
+#define LINUX32_SYS_linux_fork 2
+#define LINUX32_SYS_read 3
+#define LINUX32_SYS_write 4
+#define LINUX32_SYS_linux_open 5
+#define LINUX32_SYS_close 6
+#define LINUX32_SYS_linux_waitpid 7
+#define LINUX32_SYS_linux_creat 8
+#define LINUX32_SYS_linux_link 9
+#define LINUX32_SYS_linux_unlink 10
+#define LINUX32_SYS_linux_execve 11
+#define LINUX32_SYS_linux_chdir 12
+#define LINUX32_SYS_linux_time 13
+#define LINUX32_SYS_linux_mknod 14
+#define LINUX32_SYS_linux_chmod 15
+#define LINUX32_SYS_linux_lchown16 16
+#define LINUX32_SYS_linux_stat 18
+#define LINUX32_SYS_linux_lseek 19
+#define LINUX32_SYS_linux_getpid 20
+#define LINUX32_SYS_linux_mount 21
+#define LINUX32_SYS_linux_oldumount 22
+#define LINUX32_SYS_linux_setuid16 23
+#define LINUX32_SYS_linux_getuid16 24
+#define LINUX32_SYS_linux_stime 25
+#define LINUX32_SYS_linux_ptrace 26
+#define LINUX32_SYS_linux_alarm 27
+#define LINUX32_SYS_linux_pause 29
+#define LINUX32_SYS_linux_utime 30
+#define LINUX32_SYS_linux_access 33
+#define LINUX32_SYS_linux_nice 34
+#define LINUX32_SYS_sync 36
+#define LINUX32_SYS_linux_kill 37
+#define LINUX32_SYS_linux_rename 38
+#define LINUX32_SYS_linux_mkdir 39
+#define LINUX32_SYS_linux_rmdir 40
+#define LINUX32_SYS_dup 41
+#define LINUX32_SYS_linux_pipe 42
+#define LINUX32_SYS_linux_times 43
+#define LINUX32_SYS_linux_brk 45
+#define LINUX32_SYS_linux_setgid16 46
+#define LINUX32_SYS_linux_getgid16 47
+#define LINUX32_SYS_linux_signal 48
+#define LINUX32_SYS_linux_geteuid16 49
+#define LINUX32_SYS_linux_getegid16 50
+#define LINUX32_SYS_acct 51
+#define LINUX32_SYS_linux_umount 52
+#define LINUX32_SYS_linux_ioctl 54
+#define LINUX32_SYS_linux_fcntl 55
+#define LINUX32_SYS_setpgid 57
+#define LINUX32_SYS_linux_olduname 59
+#define LINUX32_SYS_umask 60
+#define LINUX32_SYS_chroot 61
+#define LINUX32_SYS_linux_ustat 62
+#define LINUX32_SYS_dup2 63
+#define LINUX32_SYS_linux_getppid 64
+#define LINUX32_SYS_getpgrp 65
+#define LINUX32_SYS_setsid 66
+#define LINUX32_SYS_linux_sigaction 67
+#define LINUX32_SYS_linux_sgetmask 68
+#define LINUX32_SYS_linux_ssetmask 69
+#define LINUX32_SYS_linux_setreuid16 70
+#define LINUX32_SYS_linux_setregid16 71
+#define LINUX32_SYS_linux_sigsuspend 72
+#define LINUX32_SYS_linux_sigpending 73
+#define LINUX32_SYS_linux_sethostname 74
+#define LINUX32_SYS_linux_setrlimit 75
+#define LINUX32_SYS_linux_old_getrlimit 76
+#define LINUX32_SYS_linux_getrusage 77
+#define LINUX32_SYS_linux_gettimeofday 78
+#define LINUX32_SYS_linux_settimeofday 79
+#define LINUX32_SYS_linux_getgroups16 80
+#define LINUX32_SYS_linux_setgroups16 81
+#define LINUX32_SYS_linux_old_select 82
+#define LINUX32_SYS_linux_symlink 83
+#define LINUX32_SYS_linux_lstat 84
+#define LINUX32_SYS_linux_readlink 85
+#define LINUX32_SYS_swapon 87
+#define LINUX32_SYS_linux_reboot 88
+#define LINUX32_SYS_linux_readdir 89
+#define LINUX32_SYS_linux_mmap 90
+#define LINUX32_SYS_munmap 91
+#define LINUX32_SYS_linux_truncate 92
+#define LINUX32_SYS_linux_ftruncate 93
+#define LINUX32_SYS_fchmod 94
+#define LINUX32_SYS_fchown 95
+#define LINUX32_SYS_linux_getpriority 96
+#define LINUX32_SYS_setpriority 97
+#define LINUX32_SYS_linux_statfs 99
+#define LINUX32_SYS_linux_fstatfs 100
+#define LINUX32_SYS_linux_socketcall 102
+#define LINUX32_SYS_linux_syslog 103
+#define LINUX32_SYS_linux_setitimer 104
+#define LINUX32_SYS_linux_getitimer 105
+#define LINUX32_SYS_linux_newstat 106
+#define LINUX32_SYS_linux_newlstat 107
+#define LINUX32_SYS_linux_newfstat 108
+#define LINUX32_SYS_linux_uname 109
+#define LINUX32_SYS_linux_iopl 110
+#define LINUX32_SYS_linux_vhangup 111
+#define LINUX32_SYS_linux_wait4 114
+#define LINUX32_SYS_linux_swapoff 115
+#define LINUX32_SYS_linux_sysinfo 116
+#define LINUX32_SYS_linux_ipc 117
+#define LINUX32_SYS_fsync 118
+#define LINUX32_SYS_linux_sigreturn 119
+#define LINUX32_SYS_linux_clone 120
+#define LINUX32_SYS_linux_setdomainname 121
+#define LINUX32_SYS_linux_newuname 122
+#define LINUX32_SYS_linux_adjtimex 124
+#define LINUX32_SYS_linux_mprotect 125
+#define LINUX32_SYS_linux_sigprocmask 126
+#define LINUX32_SYS_linux_create_module 127
+#define LINUX32_SYS_linux_init_module 128
+#define LINUX32_SYS_linux_delete_module 129
+#define LINUX32_SYS_linux_get_kernel_syms 130
+#define LINUX32_SYS_linux_quotactl 131
+#define LINUX32_SYS_getpgid 132
+#define LINUX32_SYS_fchdir 133
+#define LINUX32_SYS_linux_bdflush 134
+#define LINUX32_SYS_linux_sysfs 135
+#define LINUX32_SYS_linux_personality 136
+#define LINUX32_SYS_linux_setfsuid16 138
+#define LINUX32_SYS_linux_setfsgid16 139
+#define LINUX32_SYS_linux_llseek 140
+#define LINUX32_SYS_linux_getdents 141
+#define LINUX32_SYS_linux_select 142
+#define LINUX32_SYS_flock 143
+#define LINUX32_SYS_linux_msync 144
+#define LINUX32_SYS_linux_readv 145
+#define LINUX32_SYS_linux_writev 146
+#define LINUX32_SYS_linux_getsid 147
+#define LINUX32_SYS_linux_fdatasync 148
+#define LINUX32_SYS_linux_sysctl 149
+#define LINUX32_SYS_mlock 150
+#define LINUX32_SYS_munlock 151
+#define LINUX32_SYS_mlockall 152
+#define LINUX32_SYS_munlockall 153
+#define LINUX32_SYS_linux_sched_setparam 154
+#define LINUX32_SYS_linux_sched_getparam 155
+#define LINUX32_SYS_linux_sched_setscheduler 156
+#define LINUX32_SYS_linux_sched_getscheduler 157
+#define LINUX32_SYS_sched_yield 158
+#define LINUX32_SYS_linux_sched_get_priority_max 159
+#define LINUX32_SYS_linux_sched_get_priority_min 160
+#define LINUX32_SYS_linux_sched_rr_get_interval 161
+#define LINUX32_SYS_linux_nanosleep 162
+#define LINUX32_SYS_linux_mremap 163
+#define LINUX32_SYS_linux_setresuid16 164
+#define LINUX32_SYS_linux_getresuid16 165
+#define LINUX32_SYS_linux_query_module 167
+#define LINUX32_SYS_poll 168
+#define LINUX32_SYS_linux_nfsservctl 169
+#define LINUX32_SYS_linux_setresgid16 170
+#define LINUX32_SYS_linux_getresgid16 171
+#define LINUX32_SYS_linux_prctl 172
+#define LINUX32_SYS_linux_rt_sigreturn 173
+#define LINUX32_SYS_linux_rt_sigaction 174
+#define LINUX32_SYS_linux_rt_sigprocmask 175
+#define LINUX32_SYS_linux_rt_sigpending 176
+#define LINUX32_SYS_linux_rt_sigtimedwait 177
+#define LINUX32_SYS_linux_rt_sigqueueinfo 178
+#define LINUX32_SYS_linux_rt_sigsuspend 179
+#define LINUX32_SYS_linux_pread 180
+#define LINUX32_SYS_linux_pwrite 181
+#define LINUX32_SYS_linux_chown16 182
+#define LINUX32_SYS_linux_getcwd 183
+#define LINUX32_SYS_linux_capget 184
+#define LINUX32_SYS_linux_capset 185
+#define LINUX32_SYS_linux_sigaltstack 186
+#define LINUX32_SYS_linux_sendfile 187
+#define LINUX32_SYS_linux_vfork 190
+#define LINUX32_SYS_linux_getrlimit 191
+#define LINUX32_SYS_linux_mmap2 192
+#define LINUX32_SYS_linux_truncate64 193
+#define LINUX32_SYS_linux_ftruncate64 194
+#define LINUX32_SYS_linux_stat64 195
+#define LINUX32_SYS_linux_lstat64 196
+#define LINUX32_SYS_linux_fstat64 197
+#define LINUX32_SYS_linux_lchown 198
+#define LINUX32_SYS_linux_getuid 199
+#define LINUX32_SYS_linux_getgid 200
+#define LINUX32_SYS_geteuid 201
+#define LINUX32_SYS_getegid 202
+#define LINUX32_SYS_setreuid 203
+#define LINUX32_SYS_setregid 204
+#define LINUX32_SYS_linux_getgroups 205
+#define LINUX32_SYS_linux_setgroups 206
+#define LINUX32_SYS_setresuid 208
+#define LINUX32_SYS_getresuid 209
+#define LINUX32_SYS_setresgid 210
+#define LINUX32_SYS_getresgid 211
+#define LINUX32_SYS_linux_chown 212
+#define LINUX32_SYS_setuid 213
+#define LINUX32_SYS_setgid 214
+#define LINUX32_SYS_linux_setfsuid 215
+#define LINUX32_SYS_linux_setfsgid 216
+#define LINUX32_SYS_linux_pivot_root 217
+#define LINUX32_SYS_linux_mincore 218
+#define LINUX32_SYS_madvise 219
+#define LINUX32_SYS_linux_getdents64 220
+#define LINUX32_SYS_linux_fcntl64 221
+#define LINUX32_SYS_linux_gettid 224
+#define LINUX32_SYS_linux_setxattr 226
+#define LINUX32_SYS_linux_lsetxattr 227
+#define LINUX32_SYS_linux_fsetxattr 228
+#define LINUX32_SYS_linux_getxattr 229
+#define LINUX32_SYS_linux_lgetxattr 230
+#define LINUX32_SYS_linux_fgetxattr 231
+#define LINUX32_SYS_linux_listxattr 232
+#define LINUX32_SYS_linux_llistxattr 233
+#define LINUX32_SYS_linux_flistxattr 234
+#define LINUX32_SYS_linux_removexattr 235
+#define LINUX32_SYS_linux_lremovexattr 236
+#define LINUX32_SYS_linux_fremovexattr 237
+#define LINUX32_SYS_linux_tkill 238
+#define LINUX32_SYS_linux_sys_futex 240
+#define LINUX32_SYS_linux_sched_setaffinity 241
+#define LINUX32_SYS_linux_sched_getaffinity 242
+#define LINUX32_SYS_linux_set_thread_area 243
+#define LINUX32_SYS_linux_fadvise64 250
+#define LINUX32_SYS_linux_exit_group 252
+#define LINUX32_SYS_linux_lookup_dcookie 253
+#define LINUX32_SYS_linux_epoll_create 254
+#define LINUX32_SYS_linux_epoll_ctl 255
+#define LINUX32_SYS_linux_epoll_wait 256
+#define LINUX32_SYS_linux_remap_file_pages 257
+#define LINUX32_SYS_linux_set_tid_address 258
+#define LINUX32_SYS_linux_timer_create 259
+#define LINUX32_SYS_linux_timer_settime 260
+#define LINUX32_SYS_linux_timer_gettime 261
+#define LINUX32_SYS_linux_timer_getoverrun 262
+#define LINUX32_SYS_linux_timer_delete 263
+#define LINUX32_SYS_linux_clock_settime 264
+#define LINUX32_SYS_linux_clock_gettime 265
+#define LINUX32_SYS_linux_clock_getres 266
+#define LINUX32_SYS_linux_clock_nanosleep 267
+#define LINUX32_SYS_linux_statfs64 268
+#define LINUX32_SYS_linux_fstatfs64 269
+#define LINUX32_SYS_linux_tgkill 270
+#define LINUX32_SYS_linux_utimes 271
+#define LINUX32_SYS_linux_fadvise64_64 272
+#define LINUX32_SYS_linux_mbind 274
+#define LINUX32_SYS_linux_get_mempolicy 275
+#define LINUX32_SYS_linux_set_mempolicy 276
+#define LINUX32_SYS_linux_mq_open 277
+#define LINUX32_SYS_linux_mq_unlink 278
+#define LINUX32_SYS_linux_mq_timedsend 279
+#define LINUX32_SYS_linux_mq_timedreceive 280
+#define LINUX32_SYS_linux_mq_notify 281
+#define LINUX32_SYS_linux_mq_getsetattr 282
+#define LINUX32_SYS_linux_kexec_load 283
+#define LINUX32_SYS_linux_waitid 284
+#define LINUX32_SYS_linux_add_key 286
+#define LINUX32_SYS_linux_request_key 287
+#define LINUX32_SYS_linux_keyctl 288
+#define LINUX32_SYS_linux_ioprio_set 289
+#define LINUX32_SYS_linux_ioprio_get 290
+#define LINUX32_SYS_linux_inotify_init 291
+#define LINUX32_SYS_linux_inotify_add_watch 292
+#define LINUX32_SYS_linux_inotify_rm_watch 293
+#define LINUX32_SYS_linux_migrate_pages 294
+#define LINUX32_SYS_linux_openat 295
+#define LINUX32_SYS_linux_mkdirat 296
+#define LINUX32_SYS_linux_mknodat 297
+#define LINUX32_SYS_linux_fchownat 298
+#define LINUX32_SYS_linux_futimesat 299
+#define LINUX32_SYS_linux_fstatat64 300
+#define LINUX32_SYS_linux_unlinkat 301
+#define LINUX32_SYS_linux_renameat 302
+#define LINUX32_SYS_linux_linkat 303
+#define LINUX32_SYS_linux_symlinkat 304
+#define LINUX32_SYS_linux_readlinkat 305
+#define LINUX32_SYS_linux_fchmodat 306
+#define LINUX32_SYS_linux_faccessat 307
+#define LINUX32_SYS_linux_pselect6 308
+#define LINUX32_SYS_linux_ppoll 309
+#define LINUX32_SYS_linux_unshare 310
+#define LINUX32_SYS_linux_set_robust_list 311
+#define LINUX32_SYS_linux_get_robust_list 312
+#define LINUX32_SYS_linux_splice 313
+#define LINUX32_SYS_linux_sync_file_range 314
+#define LINUX32_SYS_linux_tee 315
+#define LINUX32_SYS_linux_vmsplice 316
+#define LINUX32_SYS_linux_move_pages 317
+#define LINUX32_SYS_linux_getcpu 318
+#define LINUX32_SYS_linux_epoll_pwait 319
+#define LINUX32_SYS_linux_utimensat 320
+#define LINUX32_SYS_linux_signalfd 321
+#define LINUX32_SYS_linux_timerfd_create 322
+#define LINUX32_SYS_linux_eventfd 323
+#define LINUX32_SYS_linux_fallocate 324
+#define LINUX32_SYS_linux_timerfd_settime 325
+#define LINUX32_SYS_linux_timerfd_gettime 326
+#define LINUX32_SYS_linux_signalfd4 327
+#define LINUX32_SYS_linux_eventfd2 328
+#define LINUX32_SYS_linux_epoll_create1 329
+#define LINUX32_SYS_linux_dup3 330
+#define LINUX32_SYS_linux_pipe2 331
+#define LINUX32_SYS_linux_inotify_init1 332
+#define LINUX32_SYS_linux_preadv 333
+#define LINUX32_SYS_linux_pwritev 334
+#define LINUX32_SYS_linux_rt_tsigqueueinfo 335
+#define LINUX32_SYS_linux_perf_event_open 336
+#define LINUX32_SYS_linux_recvmmsg 337
+#define LINUX32_SYS_linux_fanotify_init 338
+#define LINUX32_SYS_linux_fanotify_mark 339
+#define LINUX32_SYS_linux_prlimit64 340
+#define LINUX32_SYS_linux_name_to_handle_at 341
+#define LINUX32_SYS_linux_open_by_handle_at 342
+#define LINUX32_SYS_linux_clock_adjtime 343
+#define LINUX32_SYS_linux_syncfs 344
+#define LINUX32_SYS_linux_sendmmsg 345
+#define LINUX32_SYS_linux_setns 346
+#define LINUX32_SYS_linux_process_vm_readv 347
+#define LINUX32_SYS_linux_process_vm_writev 348
+#define LINUX32_SYS_MAXSYSCALL 350
diff --git a/sys/amd64/linux32/linux32_syscalls.c b/sys/amd64/linux32/linux32_syscalls.c
index 6d81d6b..8e7585a 100644
--- a/sys/amd64/linux32/linux32_syscalls.c
+++ b/sys/amd64/linux32/linux32_syscalls.c
@@ -3,10 +3,10 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: stable/10/sys/amd64/linux32/syscalls.master 293592 2016-01-09 17:54:37Z dchagin
+ * created from FreeBSD: stable/10/sys/amd64/linux32/syscalls.master 294368 2016-01-20 01:09:53Z jhb
*/
-const char *linux_syscallnames[] = {
+const char *linux32_syscallnames[] = {
#define nosys linux_nosys
"#0", /* 0 = setup */
"linux_exit", /* 1 = linux_exit */
diff --git a/sys/amd64/linux32/linux32_sysent.c b/sys/amd64/linux32/linux32_sysent.c
index a4d3075..f254a86 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: stable/10/sys/amd64/linux32/syscalls.master 293592 2016-01-09 17:54:37Z dchagin
+ * created from FreeBSD: stable/10/sys/amd64/linux32/syscalls.master 294368 2016-01-20 01:09:53Z jhb
*/
#include "opt_compat.h"
@@ -17,7 +17,7 @@
#define AS(name) (sizeof(struct name) / sizeof(register_t))
/* The casts are bogus but will do for now. */
-struct sysent linux_sysent[] = {
+struct sysent linux32_sysent[] = {
#define nosys linux_nosys
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 0 = setup */
{ AS(linux_exit_args), (sy_call_t *)linux_exit, AUE_EXIT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 1 = linux_exit */
diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c
index 250e16b..73949d9 100644
--- a/sys/amd64/linux32/linux32_sysvec.c
+++ b/sys/amd64/linux32/linux32_sysvec.c
@@ -105,8 +105,8 @@ MODULE_VERSION(linux, 1);
* to syscall 0. This is slightly less bogus than using
* ldebug(sigreturn).
*/
-#define LINUX_SYS_linux_rt_sendsig 0
-#define LINUX_SYS_linux_sendsig 0
+#define LINUX32_SYS_linux_rt_sendsig 0
+#define LINUX32_SYS_linux_sendsig 0
const char *linux_kplatform;
static int linux_szsigcode;
@@ -115,7 +115,7 @@ static char *linux_shared_page_mapping;
extern char _binary_linux32_locore_o_start;
extern char _binary_linux32_locore_o_end;
-extern struct sysent linux_sysent[LINUX_SYS_MAXSYSCALL];
+extern struct sysent linux32_sysent[LINUX32_SYS_MAXSYSCALL];
SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler);
@@ -1008,8 +1008,8 @@ linux32_fixlimit(struct rlimit *rl, int which)
}
struct sysentvec elf_linux_sysvec = {
- .sv_size = LINUX_SYS_MAXSYSCALL,
- .sv_table = linux_sysent,
+ .sv_size = LINUX32_SYS_MAXSYSCALL,
+ .sv_table = linux32_sysent,
.sv_mask = 0,
.sv_sigsize = 0,
.sv_sigtbl = NULL,
@@ -1043,6 +1043,7 @@ struct sysentvec elf_linux_sysvec = {
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = linux_schedtail,
.sv_thread_detach = linux_thread_detach,
+ .sv_trap = NULL,
};
static void
diff --git a/sys/amd64/linux32/syscalls.conf b/sys/amd64/linux32/syscalls.conf
index dc0ad82..7d096b5 100644
--- a/sys/amd64/linux32/syscalls.conf
+++ b/sys/amd64/linux32/syscalls.conf
@@ -1,11 +1,11 @@
# $FreeBSD$
sysnames="linux32_syscalls.c"
sysproto="linux32_proto.h"
-sysproto_h=_LINUX_SYSPROTO_H_
+sysproto_h=_LINUX32_SYSPROTO_H_
syshdr="linux32_syscall.h"
syssw="linux32_sysent.c"
sysmk="/dev/null"
-syscallprefix="LINUX_SYS_"
-switchname="linux_sysent"
-namesname="linux_syscallnames"
+syscallprefix="LINUX32_SYS_"
+switchname="linux32_sysent"
+namesname="linux32_syscallnames"
systrace="linux32_systrace_args.c"
diff --git a/sys/amd64/linux32/syscalls.master b/sys/amd64/linux32/syscalls.master
index 6e09c5a..0396b30 100644
--- a/sys/amd64/linux32/syscalls.master
+++ b/sys/amd64/linux32/syscalls.master
@@ -2,7 +2,7 @@
; @(#)syscalls.master 8.1 (Berkeley) 7/19/93
; System call name/number master file (or rather, slave, from LINUX).
-; Processed to create linux_sysent.c, linux_proto.h and linux_syscall.h.
+; Processed to create linux32_sysent.c, linux32_proto.h and linux32_syscall.h.
; Columns: number audit type nargs name alt{name,tag,rtyp}/comments
; number system call number, must be in order
diff --git a/sys/arm/arm/bcopyinout.S b/sys/arm/arm/bcopyinout.S
index 3624f92..0a12e45 100644
--- a/sys/arm/arm/bcopyinout.S
+++ b/sys/arm/arm/bcopyinout.S
@@ -38,6 +38,7 @@
#include "assym.s"
+#include <machine/acle-compat.h>
#include <machine/asm.h>
#include <sys/errno.h>
@@ -54,7 +55,7 @@ __FBSDID("$FreeBSD$");
.text
.align 2
-#ifdef _ARM_ARCH_6
+#if __ARM_ARCH >= 6
#define GET_PCB(tmp) \
mrc p15, 0, tmp, c13, c0, 4; \
add tmp, tmp, #(TD_PCB)
diff --git a/sys/arm/arm/bcopyinout_xscale.S b/sys/arm/arm/bcopyinout_xscale.S
index 487737e..b4204f6 100644
--- a/sys/arm/arm/bcopyinout_xscale.S
+++ b/sys/arm/arm/bcopyinout_xscale.S
@@ -38,11 +38,13 @@
#include <machine/asm.h>
__FBSDID("$FreeBSD$");
+#include <machine/acle-compat.h>
+
.syntax unified
.text
.align 2
-#ifdef _ARM_ARCH_6
+#if __ARM_ARCH >= 6
#define GET_PCB(tmp) \
mrc p15, 0, tmp, c13, c0, 4; \
add tmp, tmp, #(TD_PCB)
diff --git a/sys/arm/arm/busdma_machdep.c b/sys/arm/arm/busdma_machdep.c
index d24f2d2..c130731 100644
--- a/sys/arm/arm/busdma_machdep.c
+++ b/sys/arm/arm/busdma_machdep.c
@@ -786,10 +786,9 @@ bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map)
ba = coherent_allocator;
else
ba = standard_allocator;
- uma_zfree(dmamap_zone, map);
free(map->slist, M_DEVBUF);
- /* Be careful not to access map from here on. */
+ uma_zfree(dmamap_zone, map);
bufzone = busdma_bufalloc_findzone(ba, dmat->maxsize);
diff --git a/sys/arm/arm/copystr.S b/sys/arm/arm/copystr.S
index 57c9e70..89b1708 100644
--- a/sys/arm/arm/copystr.S
+++ b/sys/arm/arm/copystr.S
@@ -40,6 +40,7 @@
#include "assym.s"
+#include <machine/acle-compat.h>
#include <machine/asm.h>
#include <machine/armreg.h>
__FBSDID("$FreeBSD$");
@@ -49,7 +50,7 @@ __FBSDID("$FreeBSD$");
.text
.align 2
-#ifdef _ARM_ARCH_6
+#if __ARM_ARCH >= 6
#define GET_PCB(tmp) \
mrc p15, 0, tmp, c13, c0, 4; \
add tmp, tmp, #(TD_PCB)
diff --git a/sys/arm/arm/elf_machdep.c b/sys/arm/arm/elf_machdep.c
index 8472858..55d4a41 100644
--- a/sys/arm/arm/elf_machdep.c
+++ b/sys/arm/arm/elf_machdep.c
@@ -80,6 +80,7 @@ struct sysentvec elf32_freebsd_sysvec = {
.sv_syscallnames = syscallnames,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
+ .sv_trap = NULL,
};
static Elf32_Brandinfo freebsd_brand_info = {
diff --git a/sys/arm/arm/fusu.S b/sys/arm/arm/fusu.S
index dec49ed..7bc3a98 100644
--- a/sys/arm/arm/fusu.S
+++ b/sys/arm/arm/fusu.S
@@ -131,8 +131,8 @@ EENTRY_NP(fuword32)
str r1, [r2, #PCB_ONFAULT]
mov r0, r3
RET
-EEND(fuword32)
-END(fuword)
+EEND(fueword32)
+END(fueword)
/*
* fusword(caddr_t uaddr);
diff --git a/sys/arm/arm/locore-v4.S b/sys/arm/arm/locore-v4.S
index 6c20b68..c46c0bf 100644
--- a/sys/arm/arm/locore-v4.S
+++ b/sys/arm/arm/locore-v4.S
@@ -42,20 +42,8 @@
__FBSDID("$FreeBSD$");
-/*
- * Sanity check the configuration.
- * FLASHADDR and LOADERRAMADDR depend on PHYSADDR in some cases.
- * ARMv4 and ARMv5 make assumptions on where they are loaded.
- *
- * TODO: Fix the ARMv4/v5 case.
- */
-#if (defined(FLASHADDR) || defined(LOADERRAMADDR) || !defined(_ARM_ARCH_6)) && \
- !defined(PHYSADDR)
-#error PHYSADDR must be defined for this configuration
-#endif
-
-/* What size should this really be ? It is only used by initarm() */
-#define INIT_ARM_STACK_SIZE (2048 * 4)
+/* 2K initial stack is plenty, it is only used by initarm() */
+#define INIT_ARM_STACK_SIZE 2048
#define CPWAIT_BRANCH \
sub pc, pc, #4
@@ -110,13 +98,23 @@ ASENTRY_NP(_start)
msr cpsr_c, r7
#if defined (FLASHADDR) && defined(LOADERRAMADDR)
+/*
+ * Sanity check the configuration.
+ * FLASHADDR and LOADERRAMADDR depend on PHYSADDR in some cases.
+ * ARMv4 and ARMv5 make assumptions on where they are loaded.
+ * TODO: Fix the ARMv4/v5 case.
+ */
+#ifndef PHYSADDR
+#error PHYSADDR must be defined for this configuration
+#endif
+
/* Check if we're running from flash. */
ldr r7, =FLASHADDR
/*
* If we're running with MMU disabled, test against the
* physical address instead.
*/
- mrc p15, 0, r2, c1, c0, 0
+ mrc p15, 0, r2, c1, c0, 0
ands r2, r2, #CPU_CONTROL_MMU_ENABLE
ldreq r6, =PHYSADDR
ldrne r6, =LOADERRAMADDR
@@ -125,7 +123,7 @@ ASENTRY_NP(_start)
cmp r7, pc
bhi from_ram
b do_copy
-
+
flash_lower:
cmp r6, pc
bls from_ram
@@ -148,12 +146,12 @@ from_ram:
disable_mmu:
/* Disable MMU for a while */
- mrc p15, 0, r2, c1, c0, 0
+ mrc p15, 0, r2, c1, c0, 0
bic r2, r2, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\
CPU_CONTROL_WBUF_ENABLE)
bic r2, r2, #(CPU_CONTROL_IC_ENABLE)
bic r2, r2, #(CPU_CONTROL_BPRD_ENABLE)
- mcr p15, 0, r2, c1, c0, 0
+ mcr p15, 0, r2, c1, c0, 0
nop
nop
@@ -165,85 +163,57 @@ Lunmapped:
* Build page table from scratch.
*/
- /* Find the delta between VA and PA */
+ /*
+ * Figure out the physical address we're loaded at by assuming this
+ * entry point code is in the first L1 section and so if we clear the
+ * offset bits of the pc that will give us the section-aligned load
+ * address, which remains in r5 throughout all the following code.
+ */
+ ldr r2, =(L1_S_OFFSET)
+ bic r5, pc, r2
+
+ /* Find the delta between VA and PA, result stays in r0 throughout. */
adr r0, Lpagetable
bl translate_va_to_pa
-#ifndef _ARM_ARCH_6
- /*
- * Some of the older ports (the various XScale, mostly) assume
- * that the memory before the kernel is mapped, and use it for
- * the various stacks, page tables, etc. For those CPUs, map the
- * 64 first MB of RAM, as it used to be.
+ /*
+ * First map the entire 4GB address space as VA=PA. It's mapped as
+ * normal (cached) memory because it's for things like accessing the
+ * parameters passed in from the bootloader, which might be at any
+ * physical address, different for every platform.
*/
- /*
- * Map PA == VA
- */
- ldr r5, =PHYSADDR
- mov r1, r5
- mov r2, r5
- /* Map 64MiB, preserved over calls to build_pagetables */
- mov r3, #64
- bl build_pagetables
-
- /* Create the kernel map to jump to */
- mov r1, r5
- ldr r2, =(KERNBASE)
- bl build_pagetables
- ldr r5, =(KERNPHYSADDR)
-#else
- /*
- * Map PA == VA
- */
- /* Find the start kernels load address */
- adr r5, _start
- ldr r2, =(L1_S_OFFSET)
- bic r5, r2
- mov r1, r5
- mov r2, r5
- /* Map 64MiB, preserved over calls to build_pagetables */
- mov r3, #64
+ mov r1, #0
+ mov r2, #0
+ mov r3, #4096
bl build_pagetables
- /* Create the kernel map to jump to */
+ /*
+ * Next we do 64MiB starting at the physical load address, mapped to
+ * the VA the kernel is linked for.
+ */
mov r1, r5
ldr r2, =(KERNVIRTADDR)
+ mov r3, #64
bl build_pagetables
-#endif
-
+
+ /* Create a device mapping for early_printf if specified. */
#if defined(SOCDEV_PA) && defined(SOCDEV_VA)
- /* Create the custom map */
ldr r1, =SOCDEV_PA
ldr r2, =SOCDEV_VA
- bl build_pagetables
+ mov r3, #1
+ bl build_device_pagetables
#endif
-#if defined(SMP)
- orr r0, r0, #2 /* Set TTB shared memory flag */
-#endif
mcr p15, 0, r0, c2, c0, 0 /* Set TTB */
mcr p15, 0, r0, c8, c7, 0 /* Flush TLB */
-#if defined(CPU_ARM1136) || defined(CPU_ARM1176) || defined(CPU_CORTEXA) || defined(CPU_MV_PJ4B) || defined(CPU_KRAIT)
- mov r0, #0
- mcr p15, 0, r0, c13, c0, 1 /* Set ASID to 0 */
-#endif
-
/* Set the Domain Access register. Very important! */
- mov r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT)
+ mov r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT)
mcr p15, 0, r0, c3, c0, 0
- /*
+ /*
* Enable MMU.
- * On armv6 enable extended page tables, and set alignment checking
- * to modulo-4 (CPU_CONTROL_UNAL_ENABLE) for the ldrd/strd
- * instructions emitted by clang.
*/
mrc p15, 0, r0, c1, c0, 0
-#ifdef _ARM_ARCH_6
- orr r0, r0, #(CPU_CONTROL_V6_EXTPAGE | CPU_CONTROL_UNAL_ENABLE)
- orr r0, r0, #(CPU_CONTROL_AFLT_ENABLE)
- orr r0, r0, #(CPU_CONTROL_AF_ENABLE)
-#endif
orr r0, r0, #(CPU_CONTROL_MMU_ENABLE)
mcr p15, 0, r0, c1, c0, 0
nop
@@ -251,6 +221,9 @@ Lunmapped:
nop
CPWAIT(r0)
+ /* Transition the PC from physical to virtual addressing. */
+ ldr pc,=mmu_done
+
mmu_done:
nop
adr r1, .Lstart
@@ -261,7 +234,6 @@ mmu_done:
str r3, [r1], #0x0004 /* get zero init data */
subs r2, r2, #4
bgt .L1
- ldr pc, .Lvirt_done
virt_done:
mov r1, #28 /* loader info size is 28 bytes also second arg */
@@ -283,7 +255,7 @@ virt_done:
/* init arm will return the new stack pointer. */
mov sp, r0
- bl _C_LABEL(mi_startup) /* call mi_startup()! */
+ bl _C_LABEL(mi_startup) /* call mi_startup()! */
adr r0, .Lmainreturned
b _C_LABEL(panic)
@@ -335,24 +307,25 @@ translate_va_to_pa:
*
* Addresses must be 1MiB aligned
*/
+build_device_pagetables:
+ ldr r4, =(L1_TYPE_S|L1_S_AP(AP_KRW))
+ b 1f
build_pagetables:
/* Set the required page attributed */
ldr r4, =(L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW))
-#if defined(SMP)
- orr r4, #(L1_SHARED)
-#endif
+1:
orr r1, r4
/* Move the virtual address to the correct bit location */
lsr r2, #(L1_S_SHIFT - 2)
mov r4, r3
-1:
+2:
str r1, [r0, r2]
add r2, r2, #4
add r1, r1, #(L1_S_SIZE)
adds r4, r4, #-1
- bhi 1b
+ bhi 2b
RET
@@ -394,98 +367,12 @@ pagetable:
.Lcpufuncs:
.word _C_LABEL(cpufuncs)
-#if defined(SMP)
-
-.Lmpvirt_done:
- .word mpvirt_done
-VA_TO_PA_POINTER(Lstartup_pagetable_secondary, temp_pagetable)
-
-ASENTRY_NP(mpentry)
-
- /* Make sure interrupts are disabled. */
- mrs r7, cpsr
- orr r7, r7, #(PSR_I | PSR_F)
- msr cpsr_c, r7
-
- /* Disable MMU. It should be disabled already, but make sure. */
- mrc p15, 0, r2, c1, c0, 0
- bic r2, r2, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\
- CPU_CONTROL_WBUF_ENABLE)
- bic r2, r2, #(CPU_CONTROL_IC_ENABLE)
- bic r2, r2, #(CPU_CONTROL_BPRD_ENABLE)
- mcr p15, 0, r2, c1, c0, 0
- nop
- nop
- nop
- CPWAIT(r0)
-
-#if ARM_MMU_V6
- bl armv6_idcache_inv_all /* Modifies r0 only */
-#elif ARM_MMU_V7
- bl armv7_idcache_inv_all /* Modifies r0-r3, ip */
-#endif
-
- /* Load the page table physical address */
- adr r0, Lstartup_pagetable_secondary
- bl translate_va_to_pa
- /* Load the address the secondary page table */
- ldr r0, [r0]
-
- orr r0, r0, #2 /* Set TTB shared memory flag */
- mcr p15, 0, r0, c2, c0, 0 /* Set TTB */
- mcr p15, 0, r0, c8, c7, 0 /* Flush TLB */
-
- mov r0, #0
- mcr p15, 0, r0, c13, c0, 1 /* Set ASID to 0 */
-
- /* Set the Domain Access register. Very important! */
- mov r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT)
- mcr p15, 0, r0, c3, c0, 0
- /* Enable MMU */
- mrc p15, 0, r0, c1, c0, 0
- orr r0, r0, #CPU_CONTROL_V6_EXTPAGE
- orr r0, r0, #CPU_CONTROL_AF_ENABLE
- orr r0, r0, #(CPU_CONTROL_MMU_ENABLE | CPU_CONTROL_DC_ENABLE |\
- CPU_CONTROL_WBUF_ENABLE)
- orr r0, r0, #(CPU_CONTROL_IC_ENABLE)
- orr r0, r0, #(CPU_CONTROL_BPRD_ENABLE)
- mcr p15, 0, r0, c1, c0, 0
- nop
- nop
- nop
- CPWAIT(r0)
-
- adr r1, .Lstart
- ldmia r1, {r1, r2, sp} /* Set initial stack and */
- mrc p15, 0, r0, c0, c0, 5
- and r0, r0, #15
- mov r1, #2048
- mul r2, r1, r0
- sub sp, sp, r2
- str r1, [sp]
- ldr pc, .Lmpvirt_done
-
-mpvirt_done:
-
- mov fp, #0 /* trace back starts here */
- bl _C_LABEL(init_secondary) /* Off we go */
-
- adr r0, .Lmpreturned
- b _C_LABEL(panic)
- /* NOTREACHED */
-
-.Lmpreturned:
- .asciz "init_secondary() returned"
- .align 2
-END(mpentry)
-#endif
-
ENTRY_NP(cpu_halt)
- mrs r2, cpsr
+ mrs r2, cpsr
bic r2, r2, #(PSR_MODE)
- orr r2, r2, #(PSR_SVC32_MODE)
+ orr r2, r2, #(PSR_SVC32_MODE)
orr r2, r2, #(PSR_I | PSR_F)
- msr cpsr_fsxc, r2
+ msr cpsr_fsxc, r2
ldr r4, .Lcpu_reset_address
ldr r4, [r4]
@@ -511,9 +398,9 @@ ENTRY_NP(cpu_halt)
* Hurl ourselves into the ROM
*/
mov r0, #(CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE)
- mcr p15, 0, r0, c1, c0, 0
- mcrne p15, 0, r2, c8, c7, 0 /* nail I+D TLB on ARMv4 and greater */
- mov pc, r4
+ mcr p15, 0, r0, c1, c0, 0
+ mcrne p15, 0, r2, c8, c7, 0 /* nail I+D TLB on ARMv4 and greater */
+ mov pc, r4
/*
* _cpu_reset_address contains the address to branch to, to complete
@@ -550,7 +437,7 @@ ENTRY(longjmp)
END(longjmp)
.data
- .global _C_LABEL(esym)
+ .global _C_LABEL(esym)
_C_LABEL(esym): .word _C_LABEL(end)
ENTRY_NP(abort)
@@ -563,7 +450,7 @@ ENTRY_NP(sigcode)
/*
* Call the sigreturn system call.
- *
+ *
* We have to load r7 manually rather than using
* "ldr r7, =SYS_sigreturn" to ensure the value of szsigcode is
* correct. Using the alternative places esigcode at the address
diff --git a/sys/arm/arm/locore-v6.S b/sys/arm/arm/locore-v6.S
index 55b4311..510af6c 100644
--- a/sys/arm/arm/locore-v6.S
+++ b/sys/arm/arm/locore-v6.S
@@ -39,7 +39,7 @@
__FBSDID("$FreeBSD$");
-#ifndef ARM_NEW_PMAP
+#ifndef ARM_NEW_PMAP
#define PTE1_OFFSET L1_S_OFFSET
#define PTE1_SHIFT L1_S_SHIFT
#define PTE1_SIZE L1_S_SIZE
@@ -52,13 +52,13 @@ __FBSDID("$FreeBSD$");
.align 2
/*
- * On entry for FreeBSD boot ABI:
- * r0 - metadata pointer or 0 (boothowto on AT91's boot2)
- * r1 - if (r0 == 0) then metadata pointer
- * On entry for Linux boot ABI:
+ * On entry for FreeBSD boot ABI:
+ * r0 - metadata pointer or 0 (boothowto on AT91's boot2)
+ * r1 - if (r0 == 0) then metadata pointer
+ * On entry for Linux boot ABI:
* r0 - 0
* r1 - machine type (passed as arg2 to initarm)
- * r2 - Pointer to a tagged list or dtb image (phys addr) (passed as arg1 initarm)
+ * r2 - Pointer to a tagged list or dtb image (phys addr) (passed as arg1 initarm)
*
* For both types of boot we gather up the args, put them in a struct arm_boot_params
* structure and pass that to initarm.
@@ -66,17 +66,17 @@ __FBSDID("$FreeBSD$");
.globl btext
btext:
ASENTRY_NP(_start)
- STOP_UNWINDING /* Can't unwind into the bootloader! */
+ STOP_UNWINDING /* Can't unwind into the bootloader! */
- /* Make sure interrupts are disabled. */
+ /* Make sure interrupts are disabled. */
cpsid ifa
- mov r8, r0 /* 0 or boot mode from boot2 */
- mov r9, r1 /* Save Machine type */
- mov r10, r2 /* Save meta data */
+ mov r8, r0 /* 0 or boot mode from boot2 */
+ mov r9, r1 /* Save Machine type */
+ mov r10, r2 /* Save meta data */
mov r11, r3 /* Future expansion */
- /*
+ /*
* Check whether data cache is enabled. If it is, then we know
* current tags are valid (not power-on garbage values) and there
* might be dirty lines that need cleaning. Disable cache to prevent
@@ -93,7 +93,7 @@ ASENTRY_NP(_start)
* valid. Disable all caches and the MMU, and invalidate everything
* before setting up new page tables and re-enabling the mmu.
*/
-1:
+1:
bic r7, #CPU_CONTROL_DC_ENABLE
bic r7, #CPU_CONTROL_MMU_ENABLE
bic r7, #CPU_CONTROL_IC_ENABLE
@@ -103,80 +103,94 @@ ASENTRY_NP(_start)
orr r7, #CPU_CONTROL_AFLT_ENABLE
orr r7, #CPU_CONTROL_VECRELOC
mcr CP15_SCTLR(r7)
+ DSB
ISB
bl dcache_inv_poc_all
mcr CP15_ICIALLU
+ DSB
ISB
/*
* Build page table from scratch.
*/
- /* Calculate the physical address of the startup pagetable. */
+ /*
+ * Figure out the physical address we're loaded at by assuming this
+ * entry point code is in the first L1 section and so if we clear the
+ * offset bits of the pc that will give us the section-aligned load
+ * address, which remains in r5 throughout all the following code.
+ */
+ ldr r2, =(L1_S_OFFSET)
+ bic r5, pc, r2
+
+ /* Find the delta between VA and PA, result stays in r0 throughout. */
adr r0, Lpagetable
bl translate_va_to_pa
- /*
- * Map PA == VA
+ /*
+ * First map the entire 4GB address space as VA=PA. It's mapped as
+ * normal (cached) memory because it's for things like accessing the
+ * parameters passed in from the bootloader, which might be at any
+ * physical address, different for every platform.
*/
- /* Find the start kernels load address */
- adr r5, _start
- ldr r2, =(PTE1_OFFSET)
- bic r5, r2
- mov r1, r5
- mov r2, r5
- /* Map 64MiB, preserved over calls to build_pagetables */
- mov r3, #64
+ mov r1, #0
+ mov r2, #0
+ mov r3, #4096
bl build_pagetables
- /* Create the kernel map to jump to */
+ /*
+ * Next we do 64MiB starting at the physical load address, mapped to
+ * the VA the kernel is linked for.
+ */
mov r1, r5
ldr r2, =(KERNVIRTADDR)
+ mov r3, #64
bl build_pagetables
+ /* Create a device mapping for early_printf if specified. */
#if defined(SOCDEV_PA) && defined(SOCDEV_VA)
- /* Create the custom map used for early_printf(). */
ldr r1, =SOCDEV_PA
ldr r2, =SOCDEV_VA
- bl build_pagetables
+ mov r3, #1
+ bl build_device_pagetables
#endif
bl init_mmu
- /* Switch to virtual addresses. */
+ /* Transition the PC from physical to virtual addressing. */
ldr pc, =1f
1:
- /* Setup stack, clear BSS */
+ /* Setup stack, clear BSS */
ldr r1, =.Lstart
ldmia r1, {r1, r2, sp} /* Set initial stack and */
add sp, sp, #INIT_ARM_STACK_SIZE
- sub r2, r2, r1 /* get zero init data */
+ sub r2, r2, r1 /* get zero init data */
mov r3, #0
2:
str r3, [r1], #0x0004 /* get zero init data */
- subs r2, r2, #4
+ subs r2, r2, #4
bgt 2b
- mov r1, #28 /* loader info size is 28 bytes also second arg */
- subs sp, sp, r1 /* allocate arm_boot_params struct on stack */
- mov r0, sp /* loader info pointer is first arg */
- bic sp, sp, #7 /* align stack to 8 bytes */
- str r1, [r0] /* Store length of loader info */
+ mov r1, #28 /* loader info size is 28 bytes also second arg */
+ subs sp, sp, r1 /* allocate arm_boot_params struct on stack */
+ mov r0, sp /* loader info pointer is first arg */
+ bic sp, sp, #7 /* align stack to 8 bytes */
+ str r1, [r0] /* Store length of loader info */
str r8, [r0, #4] /* Store r0 from boot loader */
str r9, [r0, #8] /* Store r1 from boot loader */
str r10, [r0, #12] /* store r2 from boot loader */
str r11, [r0, #16] /* store r3 from boot loader */
str r5, [r0, #20] /* store the physical address */
- adr r4, Lpagetable /* load the pagetable address */
+ adr r4, Lpagetable /* load the pagetable address */
ldr r5, [r4, #4]
str r5, [r0, #24] /* store the pagetable address */
mov fp, #0 /* trace back starts here */
bl _C_LABEL(initarm) /* Off we go */
- /* init arm will return the new stack pointer. */
+ /* init arm will return the new stack pointer. */
mov sp, r0
- bl _C_LABEL(mi_startup) /* call mi_startup()! */
+ bl _C_LABEL(mi_startup) /* call mi_startup()! */
ldr r0, =.Lmainreturned
b _C_LABEL(panic)
@@ -219,8 +233,8 @@ translate_va_to_pa:
mov pc, lr
/*
- * Init MMU
- * r0 - The table base address
+ * Init MMU
+ * r0 - the table base address
*/
ASENTRY_NP(init_mmu)
@@ -261,17 +275,19 @@ ASENTRY_NP(init_mmu)
ISB
mcr CP15_TLBIALL /* Flush TLB */
mcr CP15_BPIALL /* Flush Branch predictor */
+ DSB
ISB
+
mov pc, lr
END(init_mmu)
/*
- * Init SMP coherent mode, enable caching and switch to final MMU table.
- * Called with disabled caches
- * r0 - The table base address
- * r1 - clear bits for aux register
- * r2 - set bits for aux register
+ * Init SMP coherent mode, enable caching and switch to final MMU table.
+ * Called with disabled caches
+ * r0 - The table base address
+ * r1 - clear bits for aux register
+ * r2 - set bits for aux register
*/
ASENTRY_NP(reinit_mmu)
push {r4-r11, lr}
@@ -289,6 +305,7 @@ ASENTRY_NP(reinit_mmu)
bl dcache_inv_pou_all
#endif
mcr CP15_ICIALLU
+ DSB
ISB
/* Set auxiliary register */
@@ -297,6 +314,7 @@ ASENTRY_NP(reinit_mmu)
eor r8, r8, r6 /* Set bits */
teq r7, r8
mcrne CP15_ACTLR(r8)
+ DSB
ISB
/* Enable caches. */
@@ -311,8 +329,8 @@ ASENTRY_NP(reinit_mmu)
DSB
ISB
- /* Flush all TLBs */
- mcr CP15_TLBIALL
+ mcr CP15_TLBIALL /* Flush TLB */
+ mcr CP15_BPIALL /* Flush Branch predictor */
DSB
ISB
@@ -323,6 +341,7 @@ ASENTRY_NP(reinit_mmu)
bl dcache_inv_pou_all
#endif
mcr CP15_ICIALLU
+ DSB
ISB
pop {r4-r11, pc}
@@ -331,14 +350,23 @@ END(reinit_mmu)
/*
* Builds the page table
- * r0 - The table base address
- * r1 - The physical address (trashed)
- * r2 - The virtual address (trashed)
- * r3 - The number of 1MiB sections
- * r4 - Trashed
+ * r0 - The table base address
+ * r1 - The physical address (trashed)
+ * r2 - The virtual address (trashed)
+ * r3 - The number of 1MiB sections
+ * r4 - Trashed
*
* Addresses must be 1MiB aligned
*/
+build_device_pagetables:
+#if defined(ARM_NEW_PMAP)
+ ldr r4, =PTE1_V|PTE1_A|PTE1_AP_KRW|TEX1_CLASS_0
+#elif defined(SMP)
+ ldr r4, =(L1_TYPE_S|L1_S_AP(AP_KRW)|L1_SHARED)
+#else
+ ldr r4, =(L1_TYPE_S|L1_S_AP(AP_KRW))
+#endif
+ b 1f
build_pagetables:
/* Set the required page attributed */
#if defined(ARM_NEW_PMAP)
@@ -348,18 +376,19 @@ build_pagetables:
#else
ldr r4, =(L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW))
#endif
+1:
orr r1, r4
- /* Move the virtual address to the correct bit location */
+ /* Move the virtual address to the correct bit location */
lsr r2, #(PTE1_SHIFT - 2)
mov r4, r3
-1:
+2:
str r1, [r0, r2]
- add r2, r2, #4
- add r1, r1, #(PTE1_SIZE)
- adds r4, r4, #-1
- bhi 1b
+ add r2, r2, #4
+ add r1, r1, #(PTE1_SIZE)
+ adds r4, r4, #-1
+ bhi 2b
mov pc, lr
@@ -372,7 +401,7 @@ VA_TO_PA_POINTER(Lpagetable, boot_pt1)
.word svcstk /* must remain in order together. */
.Lmainreturned:
- .asciz "main() returned"
+ .asciz "main() returned"
.align 2
.bss
@@ -380,8 +409,8 @@ svcstk:
.space INIT_ARM_STACK_SIZE * MAXCPU
/*
- * Memory for the initial pagetable. We are unable to place this in
- * the bss as this will be cleared after the table is loaded.
+ * Memory for the initial pagetable. We are unable to place this in
+ * the bss as this will be cleared after the table is loaded.
*/
.section ".init_pagetable"
.align 14 /* 16KiB aligned */
@@ -398,7 +427,7 @@ boot_pt1:
#if defined(SMP)
ASENTRY_NP(mpentry)
- /* Make sure interrupts are disabled. */
+ /* Make sure interrupts are disabled. */
cpsid ifa
/* Setup core, disable all caches. */
@@ -412,17 +441,19 @@ ASENTRY_NP(mpentry)
orr r0, #CPU_CONTROL_AFLT_ENABLE
orr r0, #CPU_CONTROL_VECRELOC
mcr CP15_SCTLR(r0)
+ DSB
ISB
/* Invalidate L1 cache I+D cache */
bl dcache_inv_pou_all
mcr CP15_ICIALLU
+ DSB
ISB
- /* Find the delta between VA and PA */
+ /* Find the delta between VA and PA */
adr r0, Lpagetable
bl translate_va_to_pa
-
+
bl init_mmu
adr r1, .Lstart+8 /* Get initstack pointer from */
@@ -433,7 +464,7 @@ ASENTRY_NP(mpentry)
mul r2, r1, r0 /* Point sp to initstack */
add sp, sp, r2 /* area for this processor. */
- /* Switch to virtual addresses. */
+ /* Switch to virtual addresses. */
ldr pc, =1f
1:
mov fp, #0 /* trace back starts here */
@@ -459,14 +490,14 @@ ENTRY_NP(cpu_halt)
ldr r4, [r4]
teq r4, #0
movne pc, r4
-1:
+1:
WFI
b 1b
/*
* _cpu_reset_address contains the address to branch to, to complete
* the cpu reset after turning the MMU off
- * This variable is provided by the hardware specific code
+ * This variable is provided by the hardware specific code
*/
.Lcpu_reset_address:
.word _C_LABEL(cpu_reset_address)
@@ -498,38 +529,37 @@ END(abort)
ENTRY_NP(sigcode)
mov r0, sp
- add r0, r0, #SIGF_UC
+ add r0, r0, #SIGF_UC
/*
- * Call the sigreturn system call.
+ * Call the sigreturn system call.
*
* We have to load r7 manually rather than using
- * "ldr r7, =SYS_sigreturn" to ensure the value of szsigcode is
+ * "ldr r7, =SYS_sigreturn" to ensure the value of szsigcode is
* correct. Using the alternative places esigcode at the address
- * of the data rather than the address one past the data.
+ * of the data rather than the address one past the data.
*/
- ldr r7, [pc, #12] /* Load SYS_sigreturn */
+ ldr r7, [pc, #12] /* Load SYS_sigreturn */
swi SYS_sigreturn
- /* Well if that failed we better exit quick ! */
+ /* Well if that failed we better exit quick ! */
- ldr r7, [pc, #8] /* Load SYS_exit */
+ ldr r7, [pc, #8] /* Load SYS_exit */
swi SYS_exit
- /* Branch back to retry SYS_sigreturn */
+ /* Branch back to retry SYS_sigreturn */
b . - 16
END(sigcode)
-
.word SYS_sigreturn
.word SYS_exit
.align 2
- .global _C_LABEL(esigcode)
+ .global _C_LABEL(esigcode)
_C_LABEL(esigcode):
.data
- .global szsigcode
+ .global szsigcode
szsigcode:
.long esigcode-sigcode
diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c
index 66dae32..443cc5b 100644
--- a/sys/arm/arm/machdep.c
+++ b/sys/arm/arm/machdep.c
@@ -826,13 +826,15 @@ fake_preload_metadata(struct arm_boot_params *abp __unused)
fake_preload[i] = 0;
preload_metadata = (void *)fake_preload;
+ init_static_kenv(NULL, 0);
+
return (lastaddr);
}
void
pcpu0_init(void)
{
-#if ARM_ARCH_6 || ARM_ARCH_7A || defined(CPU_MV_PJ4B)
+#if __ARM_ARCH >= 6
set_curthread(&thread0);
#endif
pcpu_init(pcpup, 0, sizeof(struct pcpu));
@@ -901,6 +903,8 @@ linux_parse_boot_param(struct arm_boot_params *abp)
bcopy(atag_list, atags,
(char *)walker - (char *)atag_list + ATAG_SIZE(walker));
+ init_static_kenv(NULL, 0);
+
return fake_preload_metadata(abp);
}
#endif
@@ -929,7 +933,7 @@ freebsd_parse_boot_param(struct arm_boot_params *abp)
return 0;
boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int);
- kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *);
+ init_static_kenv(MD_FETCH(kmdp, MODINFOMD_ENVP, char *), 0);
lastaddr = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t);
#ifdef DDB
ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t);
diff --git a/sys/arm/arm/physmem.c b/sys/arm/arm/physmem.c
index bc72ce2..8c41fbb 100644
--- a/sys/arm/arm/physmem.c
+++ b/sys/arm/arm/physmem.c
@@ -161,7 +161,7 @@ static size_t
regions_to_avail(vm_paddr_t *avail, uint32_t exflags, long *pavail)
{
size_t acnt, exi, hwi;
- vm_paddr_t end, start, xend, xstart;
+ uint64_t end, start, xend, xstart;
long availmem;
const struct region *exp, *hwp;
@@ -171,7 +171,7 @@ regions_to_avail(vm_paddr_t *avail, uint32_t exflags, long *pavail)
for (hwi = 0, hwp = hwregions; hwi < hwcnt; ++hwi, ++hwp) {
start = hwp->addr;
end = hwp->size + start;
- realmem += arm32_btop(end - start);
+ realmem += arm32_btop((vm_offset_t)(end - start));
for (exi = 0, exp = exregions; exi < excnt; ++exi, ++exp) {
/*
* If the excluded region does not match given flags,
@@ -212,9 +212,10 @@ regions_to_avail(vm_paddr_t *avail, uint32_t exflags, long *pavail)
* could affect the remainder of this hw region.
*/
if ((xstart > start) && (xend < end)) {
- avail[acnt++] = start;
- avail[acnt++] = xstart;
- availmem += arm32_btop(xstart - start);
+ avail[acnt++] = (vm_paddr_t)start;
+ avail[acnt++] = (vm_paddr_t)xstart;
+ availmem +=
+ arm32_btop((vm_offset_t)(xstart - start));
start = xend;
continue;
}
@@ -233,9 +234,9 @@ regions_to_avail(vm_paddr_t *avail, uint32_t exflags, long *pavail)
* available entry for it.
*/
if (end > start) {
- avail[acnt++] = start;
- avail[acnt++] = end;
- availmem += arm32_btop(end - start);
+ avail[acnt++] = (vm_paddr_t)start;
+ avail[acnt++] = (vm_paddr_t)end;
+ availmem += arm32_btop((vm_offset_t)(end - start));
}
if (acnt >= MAX_AVAIL_ENTRIES)
panic("Not enough space in the dump/phys_avail arrays");
@@ -279,10 +280,22 @@ arm_physmem_hardware_region(vm_paddr_t pa, vm_size_t sz)
/*
* Filter out the page at PA 0x00000000. The VM can't handle it, as
* pmap_extract() == 0 means failure.
+ *
+ * Also filter out the page at the end of the physical address space --
+ * if addr is non-zero and addr+size is zero we wrapped to the next byte
+ * beyond what vm_paddr_t can express. That leads to a NULL pointer
+ * deref early in startup; work around it by leaving the last page out.
+ *
+ * XXX This just in: subtract out a whole megabyte, not just 1 page.
+ * Reducing the size by anything less than 1MB results in the NULL
+ * pointer deref in _vm_map_lock_read(). Better to give up a megabyte
+ * than leave some folks with an unusable system while we investigate.
*/
if (pa == 0) {
pa = PAGE_SIZE;
sz -= PAGE_SIZE;
+ } else if (pa + sz == 0) {
+ sz -= 1024 * 1024;
}
/*
diff --git a/sys/arm/arm/trap.c b/sys/arm/arm/trap.c
index 82d2f0f..726b718 100644
--- a/sys/arm/arm/trap.c
+++ b/sys/arm/arm/trap.c
@@ -95,6 +95,7 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_map.h>
#include <vm/vm_extern.h>
+#include <machine/acle-compat.h>
#include <machine/cpu.h>
#include <machine/frame.h>
#include <machine/machdep.h>
@@ -322,7 +323,7 @@ abort_handler(struct trapframe *tf, int type)
* location, so we can deal with those quickly. Otherwise we need to
* disassemble the faulting instruction to determine if it was a write.
*/
-#if ARM_ARCH_6 || ARM_ARCH_7A
+#if __ARM_ARCH >= 6
ftype = (fsr & FAULT_WNR) ? VM_PROT_READ | VM_PROT_WRITE : VM_PROT_READ;
#else
if (IS_PERMISSION_FAULT(fsr))
diff --git a/sys/arm/at91/at91_mci.c b/sys/arm/at91/at91_mci.c
index 5d58228..a506715 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/freescale/imx/imx6_anatop.c b/sys/arm/freescale/imx/imx6_anatop.c
index e7abb9e..d38d432 100644
--- a/sys/arm/freescale/imx/imx6_anatop.c
+++ b/sys/arm/freescale/imx/imx6_anatop.c
@@ -73,11 +73,10 @@ __FBSDID("$FreeBSD$");
#include <arm/freescale/fsl_ocotpreg.h>
#include <arm/freescale/fsl_ocotpvar.h>
#include <arm/freescale/imx/imx_ccmvar.h>
+#include <arm/freescale/imx/imx_machdep.h>
#include <arm/freescale/imx/imx6_anatopreg.h>
#include <arm/freescale/imx/imx6_anatopvar.h>
-static SYSCTL_NODE(_hw, OID_AUTO, imx6, CTLFLAG_RW, NULL, "i.MX6 container");
-
static struct resource_spec imx6_anatop_spec[] = {
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
{ SYS_RES_IRQ, 0, RF_ACTIVE },
@@ -396,23 +395,23 @@ cpufreq_initialize(struct imx6_anatop_softc *sc)
uint32_t cfg3speed;
struct oppt * op;
- SYSCTL_ADD_INT(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx6),
+ SYSCTL_ADD_INT(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx),
OID_AUTO, "cpu_mhz", CTLFLAG_RD, &sc->cpu_curmhz, 0,
"CPU frequency");
- SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx6),
+ SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx),
OID_AUTO, "cpu_minmhz", CTLTYPE_INT | CTLFLAG_RWTUN, sc, 0,
cpufreq_sysctl_minmhz, "IU", "Minimum CPU frequency");
- SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx6),
+ SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx),
OID_AUTO, "cpu_maxmhz", CTLTYPE_INT | CTLFLAG_RWTUN, sc, 0,
cpufreq_sysctl_maxmhz, "IU", "Maximum CPU frequency");
- SYSCTL_ADD_INT(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx6),
+ SYSCTL_ADD_INT(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx),
OID_AUTO, "cpu_maxmhz_hw", CTLFLAG_RD, &sc->cpu_maxmhz_hw, 0,
"Maximum CPU frequency allowed by hardware");
- SYSCTL_ADD_INT(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx6),
+ SYSCTL_ADD_INT(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx),
OID_AUTO, "cpu_overclock_enable", CTLFLAG_RWTUN,
&sc->cpu_overclock_enable, 0,
"Allow setting CPU frequency higher than cpu_maxmhz_hw");
@@ -630,10 +629,10 @@ initialize_tempmon(struct imx6_anatop_softc *sc)
callout_reset_sbt(&sc->temp_throttle_callout, sc->temp_throttle_delay,
0, tempmon_throttle_check, sc, 0);
- SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx6),
+ SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx),
OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD, sc, 0,
temp_sysctl_handler, "IK", "Current die temperature");
- SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx6),
+ SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_imx),
OID_AUTO, "throttle_temperature", CTLTYPE_INT | CTLFLAG_RW, sc,
0, temp_throttle_sysctl_handler, "IK",
"Throttle CPU when exceeding this temperature");
diff --git a/sys/arm/freescale/imx/imx6_machdep.c b/sys/arm/freescale/imx/imx6_machdep.c
index 2335f7d..a5539ea 100644
--- a/sys/arm/freescale/imx/imx6_machdep.c
+++ b/sys/arm/freescale/imx/imx6_machdep.c
@@ -99,7 +99,6 @@ initarm_lastaddr(void)
void
initarm_early_init(void)
{
-
/* Inform the MPCore timer driver that its clock is variable. */
arm_tmr_change_frequency(ARM_TMR_FREQUENCY_VARIES);
}
@@ -113,6 +112,9 @@ initarm_gpio_init(void)
void
initarm_late_init(void)
{
+ const uint32_t IMX6_WDOG_SR_PHYS = 0x020bc004;
+
+ imx_wdog_init_last_reset(IMX6_WDOG_SR_PHYS);
/* Cache the gpio1 node handle for imx6_decode_fdt() workaround code. */
gpio1_node = OF_node_from_xref(
diff --git a/sys/arm/freescale/imx/imx_machdep.c b/sys/arm/freescale/imx/imx_machdep.c
index 3618637..002651a 100644
--- a/sys/arm/freescale/imx/imx_machdep.c
+++ b/sys/arm/freescale/imx/imx_machdep.c
@@ -45,6 +45,15 @@ __FBSDID("$FreeBSD$");
#include <arm/freescale/imx/imx_machdep.h>
#include <arm/freescale/imx/imx_wdogreg.h>
+SYSCTL_NODE(_hw, OID_AUTO, imx, CTLFLAG_RW, NULL, "i.MX container");
+
+static int last_reset_status;
+SYSCTL_UINT(_hw_imx, OID_AUTO, last_reset_status, CTLFLAG_RD,
+ &last_reset_status, 0, "Last reset status register");
+
+SYSCTL_STRING(_hw_imx, OID_AUTO, last_reset_reason, CTLFLAG_RD,
+ "unknown", 0, "Last reset reason");
+
struct arm32_dma_range *
bus_dma_get_range(void)
{
@@ -72,21 +81,36 @@ imx_wdog_cpu_reset(vm_offset_t wdcr_physaddr)
volatile uint16_t * pcr;
/*
- * The deceptively simple write of WDOG_CR_WDE enables the watchdog,
- * sets the timeout to its minimum value (half a second), and also
- * clears the SRS bit which results in the SFTW (software-requested
- * reset) bit being set in the watchdog status register after the reset.
- * This is how software can distinguish a reset from a wdog timeout.
+ * Trigger an immediate reset by clearing the SRS bit in the watchdog
+ * control register. The reset happens on the next cycle of the wdog
+ * 32KHz clock, so hang out in a spin loop until the reset takes effect.
*/
if ((pcr = arm_devmap_ptov(wdcr_physaddr, sizeof(*pcr))) == NULL) {
printf("cpu_reset() can't find its control register... locking up now.");
} else {
- *pcr = WDOG_CR_WDE;
+ *pcr &= ~WDOG_CR_SRS;
}
for (;;)
continue;
}
+void
+imx_wdog_init_last_reset(vm_offset_t wdsr_phys)
+{
+ volatile uint16_t * psr;
+
+ if ((psr = arm_devmap_ptov(wdsr_phys, sizeof(*psr))) == NULL)
+ return;
+ last_reset_status = *psr;
+ if (last_reset_status & WDOG_RSR_SFTW) {
+ sysctl___hw_imx_last_reset_reason.oid_arg1 = "SoftwareReset";
+ } else if (last_reset_status & WDOG_RSR_TOUT) {
+ sysctl___hw_imx_last_reset_reason.oid_arg1 = "WatchdogTimeout";
+ } else if (last_reset_status & WDOG_RSR_POR) {
+ sysctl___hw_imx_last_reset_reason.oid_arg1 = "PowerOnReset";
+ }
+}
+
u_int
imx_soc_family(void)
{
diff --git a/sys/arm/freescale/imx/imx_machdep.h b/sys/arm/freescale/imx/imx_machdep.h
index 6909e51..2bb8bb3 100644
--- a/sys/arm/freescale/imx/imx_machdep.h
+++ b/sys/arm/freescale/imx/imx_machdep.h
@@ -30,10 +30,14 @@
#define IMX_MACHDEP_H
#include <sys/types.h>
+#include <sys/sysctl.h>
+
+SYSCTL_DECL(_hw_imx);
/* Common functions, implemented in imx_machdep.c. */
void imx_wdog_cpu_reset(vm_offset_t _wdcr_phys) __attribute__((__noreturn__));
+void imx_wdog_init_last_reset(vm_offset_t _wdsr_phys);
/* From here down, routines are implemented in imxNN_machdep.c. */
diff --git a/sys/arm/freescale/imx/imx_sdhci.c b/sys/arm/freescale/imx/imx_sdhci.c
index 7d982c5..98d5e23 100644
--- a/sys/arm/freescale/imx/imx_sdhci.c
+++ b/sys/arm/freescale/imx/imx_sdhci.c
@@ -429,6 +429,7 @@ imx_sdhci_write_2(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint16_
} else {
imx_sdhc_set_clock(sc, false);
}
+ return;
}
/*
@@ -522,12 +523,19 @@ imx_sdhc_set_clock(struct imx_sdhci_softc *sc, int enable)
else
freq = sc->baseclk_hz / (2 * divisor);
- for (prescale = 2; prescale < freq / prescale / 16;)
+ for (prescale = 2; freq < sc->baseclk_hz / (prescale * 16);)
prescale <<= 1;
- for (divisor = 1; freq < freq / prescale / divisor;)
+ for (divisor = 1; freq < sc->baseclk_hz / (prescale * divisor);)
++divisor;
+#ifdef DEBUG
+ device_printf(sc->dev,
+ "desired SD freq: %d, actual: %d; base %d prescale %d divisor %d\n",
+ freq, sc->baseclk_hz / (prescale * divisor), sc->baseclk_hz,
+ prescale, divisor);
+#endif
+
prescale >>= 1;
divisor -= 1;
diff --git a/sys/arm/freescale/imx/imx_wdogreg.h b/sys/arm/freescale/imx/imx_wdogreg.h
index 1bff106..030cee8 100644
--- a/sys/arm/freescale/imx/imx_wdogreg.h
+++ b/sys/arm/freescale/imx/imx_wdogreg.h
@@ -47,6 +47,7 @@
#define WDOG_SR_STEP2 0xaaaa
#define WDOG_RSR_REG 0x04 /* Reset Status Register */
+#define WDOG_RSR_POR (1 << 4) /* Due to Power-On Reset */
#define WDOG_RSR_TOUT (1 << 1) /* Due WDog timeout reset */
#define WDOG_RSR_SFTW (1 << 0) /* Due Soft reset */
diff --git a/sys/arm/mv/std-pj4b.mv b/sys/arm/mv/std-pj4b.mv
index 1053ff0..cc14abc 100644
--- a/sys/arm/mv/std-pj4b.mv
+++ b/sys/arm/mv/std-pj4b.mv
@@ -5,4 +5,8 @@ cpu CPU_MV_PJ4B
machine arm armv6
makeoptions CONF_CFLAGS="-march=armv7a -Wa,-march=armv7a"
-options VM_MAXUSER_ADDRESS="(KERNBASE-(1024*1024*1024))"
+# This was originally defined as "(KERNBASE-(1024*1024*1024))" but that
+# (in opt_global.h) clashed with the value emitted by genassym which
+# reduces the original macro text to its numeric value. The only way
+# to avoid that is to define it here as the numeric value genassym emits.
+options VM_MAXUSER_ADDRESS="0x80000000"
diff --git a/sys/arm/xscale/ixp425/avila_machdep.c b/sys/arm/xscale/ixp425/avila_machdep.c
index b1d6734..e72798a 100644
--- a/sys/arm/xscale/ixp425/avila_machdep.c
+++ b/sys/arm/xscale/ixp425/avila_machdep.c
@@ -223,8 +223,8 @@ initarm(struct arm_boot_params *abp)
pcpu_init(pcpup, 0, sizeof(struct pcpu));
PCPU_SET(curthread, &thread0);
- if (envmode == 1)
- kern_envp = static_env;
+ init_static_kenv(NULL, 0);
+
/* Do basic tuning, hz etc */
init_param1();
@@ -420,10 +420,6 @@ initarm(struct arm_boot_params *abp)
init_param2(physmem);
kdb_init();
- /* use static kernel environment if so configured */
- if (envmode == 1)
- kern_envp = static_env;
-
return ((void *)(kernelstack.pv_va + USPACE_SVC_STACK_TOP -
sizeof(struct pcb)));
#undef next_page
diff --git a/sys/boot/common/bootstrap.h b/sys/boot/common/bootstrap.h
index c9bcc52..de77c7b 100644
--- a/sys/boot/common/bootstrap.h
+++ b/sys/boot/common/bootstrap.h
@@ -231,9 +231,9 @@ int mod_load(char *name, struct mod_depend *verinfo, int argc, char *argv[]);
int mod_loadkld(const char *name, int argc, char *argv[]);
struct preloaded_file *file_alloc(void);
-struct preloaded_file *file_findfile(char *name, char *type);
+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);
+struct preloaded_file *file_loadraw(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,
@@ -257,6 +257,9 @@ int __elfN(obj_loadfile)(char *filename, u_int64_t dest,
int __elfN(reloc)(struct elf_file *ef, symaddr_fn *symaddr,
const void *reldata, int reltype, Elf_Addr relbase,
Elf_Addr dataaddr, void *data, size_t len);
+int __elfN(loadfile_raw)(char *filename, u_int64_t dest,
+ struct preloaded_file **result, int multiboot);
+int __elfN(load_modmetadata)(struct preloaded_file *fp, u_int64_t dest);
#endif
/*
diff --git a/sys/boot/common/load_elf.c b/sys/boot/common/load_elf.c
index edbad05..200a29c 100644
--- a/sys/boot/common/load_elf.c
+++ b/sys/boot/common/load_elf.c
@@ -76,7 +76,8 @@ static int __elfN(loadimage)(struct preloaded_file *mp, elf_file_t ef, u_int64_t
static int __elfN(lookup_symbol)(struct preloaded_file *mp, elf_file_t ef, const char* name, Elf_Sym* sym);
static int __elfN(reloc_ptr)(struct preloaded_file *mp, elf_file_t ef,
Elf_Addr p, void *val, size_t len);
-static int __elfN(parse_modmetadata)(struct preloaded_file *mp, elf_file_t ef);
+static int __elfN(parse_modmetadata)(struct preloaded_file *mp, elf_file_t ef,
+ Elf_Addr p_start, Elf_Addr p_end);
static symaddr_fn __elfN(symaddr);
static char *fake_modname(const char *name);
@@ -85,6 +86,61 @@ const char *__elfN(moduletype) = "elf module";
u_int64_t __elfN(relocation_offset) = 0;
+static int
+__elfN(load_elf_header)(char *filename, elf_file_t ef)
+{
+ ssize_t bytes_read;
+ Elf_Ehdr *ehdr;
+ int err;
+
+ /*
+ * Open the image, read and validate the ELF header
+ */
+ if (filename == NULL) /* can't handle nameless */
+ return (EFTYPE);
+ if ((ef->fd = open(filename, O_RDONLY)) == -1)
+ return (errno);
+ ef->firstpage = malloc(PAGE_SIZE);
+ if (ef->firstpage == NULL) {
+ close(ef->fd);
+ return (ENOMEM);
+ }
+ bytes_read = read(ef->fd, ef->firstpage, PAGE_SIZE);
+ ef->firstlen = (size_t)bytes_read;
+ if (bytes_read < 0 || ef->firstlen <= sizeof(Elf_Ehdr)) {
+ err = EFTYPE; /* could be EIO, but may be small file */
+ goto error;
+ }
+ ehdr = ef->ehdr = (Elf_Ehdr *)ef->firstpage;
+
+ /* Is it ELF? */
+ if (!IS_ELF(*ehdr)) {
+ err = EFTYPE;
+ goto error;
+ }
+ if (ehdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || /* Layout ? */
+ ehdr->e_ident[EI_DATA] != ELF_TARG_DATA ||
+ ehdr->e_ident[EI_VERSION] != EV_CURRENT || /* Version ? */
+ ehdr->e_version != EV_CURRENT ||
+ ehdr->e_machine != ELF_TARG_MACH) { /* Machine ? */
+ err = EFTYPE;
+ goto error;
+ }
+
+ return (0);
+
+error:
+ if (ef->firstpage != NULL) {
+ free(ef->firstpage);
+ ef->firstpage = NULL;
+ }
+ if (ef->fd != -1) {
+ close(ef->fd);
+ ef->fd = -1;
+ }
+ return (err);
+}
+
/*
* Attempt to load the file (file) as an ELF module. It will be stored at
* (dest), and a pointer to a module structure describing the loaded object
@@ -93,54 +149,32 @@ u_int64_t __elfN(relocation_offset) = 0;
int
__elfN(loadfile)(char *filename, u_int64_t dest, struct preloaded_file **result)
{
+ return (__elfN(loadfile_raw)(filename, dest, result, 0));
+}
+
+int
+__elfN(loadfile_raw)(char *filename, u_int64_t dest,
+ struct preloaded_file **result, int multiboot)
+{
struct preloaded_file *fp, *kfp;
struct elf_file ef;
Elf_Ehdr *ehdr;
int err;
- ssize_t bytes_read;
fp = NULL;
bzero(&ef, sizeof(struct elf_file));
+ ef.fd = -1;
- /*
- * Open the image, read and validate the ELF header
- */
- if (filename == NULL) /* can't handle nameless */
- return(EFTYPE);
- if ((ef.fd = open(filename, O_RDONLY)) == -1)
- return(errno);
- ef.firstpage = malloc(PAGE_SIZE);
- if (ef.firstpage == NULL) {
- close(ef.fd);
- return(ENOMEM);
- }
- bytes_read = read(ef.fd, ef.firstpage, PAGE_SIZE);
- ef.firstlen = (size_t)bytes_read;
- if (bytes_read < 0 || ef.firstlen <= sizeof(Elf_Ehdr)) {
- err = EFTYPE; /* could be EIO, but may be small file */
- goto oerr;
- }
- ehdr = ef.ehdr = (Elf_Ehdr *)ef.firstpage;
-
- /* Is it ELF? */
- if (!IS_ELF(*ehdr)) {
- err = EFTYPE;
- goto oerr;
- }
- if (ehdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || /* Layout ? */
- ehdr->e_ident[EI_DATA] != ELF_TARG_DATA ||
- ehdr->e_ident[EI_VERSION] != EV_CURRENT || /* Version ? */
- ehdr->e_version != EV_CURRENT ||
- ehdr->e_machine != ELF_TARG_MACH) { /* Machine ? */
- err = EFTYPE;
- goto oerr;
- }
+ err = __elfN(load_elf_header)(filename, &ef);
+ if (err != 0)
+ return (err);
+ ehdr = ef.ehdr;
/*
* Check to see what sort of module we are.
*/
- kfp = file_findfile(NULL, NULL);
+ kfp = file_findfile(NULL, __elfN(kerneltype));
#ifdef __powerpc__
/*
* Kernels can be ET_DYN, so just assume the first loaded object is the
@@ -177,6 +211,11 @@ __elfN(loadfile)(char *filename, u_int64_t dest, struct preloaded_file **result)
} else if (ehdr->e_type == ET_DYN) {
/* Looks like a kld module */
+ if (multiboot != 0) {
+ printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module as multiboot\n");
+ err = EPERM;
+ goto oerr;
+ }
if (kfp == NULL) {
printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module before kernel\n");
err = EPERM;
@@ -209,10 +248,14 @@ __elfN(loadfile)(char *filename, u_int64_t dest, struct preloaded_file **result)
err = EPERM;
goto out;
}
- if (ef.kernel)
+ if (ef.kernel == 1 && multiboot == 0)
setenv("kernelname", filename, 1);
fp->f_name = strdup(filename);
- fp->f_type = strdup(ef.kernel ? __elfN(kerneltype) : __elfN(moduletype));
+ if (multiboot == 0)
+ fp->f_type = strdup(ef.kernel ?
+ __elfN(kerneltype) : __elfN(moduletype));
+ else
+ fp->f_type = strdup("elf multiboot kernel");
#ifdef ELF_VERBOSE
if (ef.kernel)
@@ -240,7 +283,8 @@ __elfN(loadfile)(char *filename, u_int64_t dest, struct preloaded_file **result)
out:
if (ef.firstpage)
free(ef.firstpage);
- close(ef.fd);
+ if (ef.fd != -1)
+ close(ef.fd);
return(err);
}
@@ -269,6 +313,8 @@ __elfN(loadimage)(struct preloaded_file *fp, elf_file_t ef, u_int64_t off)
int symtabindex;
Elf_Size size;
u_int fpcopy;
+ Elf_Sym sym;
+ Elf_Addr p_start, p_end;
dp = NULL;
shdr = NULL;
@@ -571,7 +617,15 @@ nosyms:
COPYOUT(ef->hashtab + 1, &ef->nchains, sizeof(ef->nchains));
ef->buckets = ef->hashtab + 2;
ef->chains = ef->buckets + ef->nbuckets;
- if (__elfN(parse_modmetadata)(fp, ef) == 0)
+
+ if (__elfN(lookup_symbol)(fp, ef, "__start_set_modmetadata_set", &sym) != 0)
+ return 0;
+ p_start = sym.st_value + ef->off;
+ if (__elfN(lookup_symbol)(fp, ef, "__stop_set_modmetadata_set", &sym) != 0)
+ return ENOENT;
+ p_end = sym.st_value + ef->off;
+
+ if (__elfN(parse_modmetadata)(fp, ef, p_start, p_end) == 0)
goto out;
if (ef->kernel) /* kernel must not depend on anything */
@@ -634,7 +688,123 @@ struct mod_metadata32 {
#endif
int
-__elfN(parse_modmetadata)(struct preloaded_file *fp, elf_file_t ef)
+__elfN(load_modmetadata)(struct preloaded_file *fp, u_int64_t dest)
+{
+ struct elf_file ef;
+ int err, i, j;
+ Elf_Shdr *sh_meta, *shdr = NULL;
+ Elf_Shdr *sh_data[2];
+ char *shstrtab = NULL;
+ size_t size;
+ Elf_Addr p_start, p_end;
+
+ bzero(&ef, sizeof(struct elf_file));
+ ef.fd = -1;
+
+ err = __elfN(load_elf_header)(fp->f_name, &ef);
+ if (err != 0)
+ goto out;
+
+ if (ef.ehdr->e_type == ET_EXEC) {
+ ef.kernel = 1;
+ } else if (ef.ehdr->e_type != ET_DYN) {
+ err = EFTYPE;
+ goto out;
+ }
+
+ size = ef.ehdr->e_shnum * ef.ehdr->e_shentsize;
+ shdr = alloc_pread(ef.fd, ef.ehdr->e_shoff, size);
+ if (shdr == NULL) {
+ err = ENOMEM;
+ goto out;
+ }
+
+ /* Load shstrtab. */
+ shstrtab = alloc_pread(ef.fd, shdr[ef.ehdr->e_shstrndx].sh_offset,
+ shdr[ef.ehdr->e_shstrndx].sh_size);
+ if (shstrtab == NULL) {
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
+ "load_modmetadata: unable to load shstrtab\n");
+ err = EFTYPE;
+ goto out;
+ }
+
+ /* Find set_modmetadata_set and data sections. */
+ sh_data[0] = sh_data[1] = sh_meta = NULL;
+ for (i = 0, j = 0; i < ef.ehdr->e_shnum; i++) {
+ if (strcmp(&shstrtab[shdr[i].sh_name],
+ "set_modmetadata_set") == 0) {
+ sh_meta = &shdr[i];
+ }
+ if ((strcmp(&shstrtab[shdr[i].sh_name], ".data") == 0) ||
+ (strcmp(&shstrtab[shdr[i].sh_name], ".rodata") == 0)) {
+ sh_data[j++] = &shdr[i];
+ }
+ }
+ if (sh_meta == NULL || sh_data[0] == NULL || sh_data[1] == NULL) {
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
+ "load_modmetadata: unable to find set_modmetadata_set or data sections\n");
+ err = EFTYPE;
+ goto out;
+ }
+
+ /* Load set_modmetadata_set into memory */
+ err = kern_pread(ef.fd, dest, sh_meta->sh_size, sh_meta->sh_offset);
+ if (err != 0) {
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
+ "load_modmetadata: unable to load set_modmetadata_set: %d\n", err);
+ goto out;
+ }
+ p_start = dest;
+ p_end = dest + sh_meta->sh_size;
+ dest += sh_meta->sh_size;
+
+ /* Load data sections into memory. */
+ err = kern_pread(ef.fd, dest, sh_data[0]->sh_size,
+ sh_data[0]->sh_offset);
+ if (err != 0) {
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
+ "load_modmetadata: unable to load data: %d\n", err);
+ goto out;
+ }
+
+ /*
+ * We have to increment the dest, so that the offset is the same into
+ * both the .rodata and .data sections.
+ */
+ ef.off = -(sh_data[0]->sh_addr - dest);
+ dest += (sh_data[1]->sh_addr - sh_data[0]->sh_addr);
+
+ err = kern_pread(ef.fd, dest, sh_data[1]->sh_size,
+ sh_data[1]->sh_offset);
+ if (err != 0) {
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
+ "load_modmetadata: unable to load data: %d\n", err);
+ goto out;
+ }
+
+ err = __elfN(parse_modmetadata)(fp, &ef, p_start, p_end);
+ if (err != 0) {
+ printf("\nelf" __XSTRING(__ELF_WORD_SIZE)
+ "load_modmetadata: unable to parse metadata: %d\n", err);
+ goto out;
+ }
+
+out:
+ if (shstrtab != NULL)
+ free(shstrtab);
+ if (shdr != NULL)
+ free(shdr);
+ if (ef.firstpage != NULL)
+ free(ef.firstpage);
+ if (ef.fd != -1)
+ close(ef.fd);
+ return (err);
+}
+
+int
+__elfN(parse_modmetadata)(struct preloaded_file *fp, elf_file_t ef,
+ Elf_Addr p_start, Elf_Addr p_end)
{
struct mod_metadata md;
#if (defined(__i386__) || defined(__powerpc__)) && __ELF_WORD_SIZE == 64
@@ -644,20 +814,13 @@ __elfN(parse_modmetadata)(struct preloaded_file *fp, elf_file_t ef)
#endif
struct mod_depend *mdepend;
struct mod_version mver;
- Elf_Sym sym;
char *s;
int error, modcnt, minfolen;
- Elf_Addr v, p, p_stop;
-
- if (__elfN(lookup_symbol)(fp, ef, "__start_set_modmetadata_set", &sym) != 0)
- return 0;
- p = sym.st_value + ef->off;
- if (__elfN(lookup_symbol)(fp, ef, "__stop_set_modmetadata_set", &sym) != 0)
- return ENOENT;
- p_stop = sym.st_value + ef->off;
+ Elf_Addr v, p;
modcnt = 0;
- while (p < p_stop) {
+ p = p_start;
+ while (p < p_end) {
COPYOUT(p, &v, sizeof(v));
error = __elfN(reloc_ptr)(fp, ef, p, &v, sizeof(v));
if (error == EOPNOTSUPP)
diff --git a/sys/boot/common/load_elf_obj.c b/sys/boot/common/load_elf_obj.c
index 2c8e184..3d8b02a 100644
--- a/sys/boot/common/load_elf_obj.c
+++ b/sys/boot/common/load_elf_obj.c
@@ -129,20 +129,13 @@ __elfN(obj_loadfile)(char *filename, u_int64_t dest,
goto oerr;
}
- kfp = file_findfile(NULL, NULL);
+ kfp = file_findfile(NULL, __elfN(obj_kerneltype));
if (kfp == NULL) {
printf("elf" __XSTRING(__ELF_WORD_SIZE)
"_obj_loadfile: can't load module before kernel\n");
err = EPERM;
goto oerr;
}
- if (strcmp(__elfN(obj_kerneltype), kfp->f_type)) {
- printf("elf" __XSTRING(__ELF_WORD_SIZE)
- "_obj_loadfile: can't load module with kernel type '%s'\n",
- kfp->f_type);
- err = EPERM;
- goto oerr;
- }
if (archsw.arch_loadaddr != NULL)
dest = archsw.arch_loadaddr(LOAD_ELF, hdr, dest);
diff --git a/sys/boot/common/module.c b/sys/boot/common/module.c
index c7d19d1..2af9c20 100644
--- a/sys/boot/common/module.c
+++ b/sys/boot/common/module.c
@@ -138,7 +138,7 @@ command_load(int argc, char *argv[])
command_errmsg = "invalid load type";
return(CMD_ERROR);
}
- return(file_loadraw(argv[1], typestr) ? CMD_OK : CMD_ERROR);
+ return (file_loadraw(argv[1], typestr, 1) ? CMD_OK : CMD_ERROR);
}
/*
* Do we have explicit KLD load ?
@@ -193,7 +193,7 @@ command_load_geli(int argc, char *argv[])
argv += (optind - 1);
argc -= (optind - 1);
sprintf(typestr, "%s:geli_keyfile%d", argv[1], num);
- return(file_loadraw(argv[2], typestr) ? CMD_OK : CMD_ERROR);
+ return (file_loadraw(argv[2], typestr, 1) ? CMD_OK : CMD_ERROR);
}
COMMAND_SET(unload, "unload", "unload all modules", command_unload);
@@ -362,7 +362,7 @@ file_load_dependencies(struct preloaded_file *base_file)
* no arguments or anything.
*/
struct preloaded_file *
-file_loadraw(char *name, char *type)
+file_loadraw(char *name, char *type, int insert)
{
struct preloaded_file *fp;
char *cp;
@@ -421,7 +421,8 @@ file_loadraw(char *name, char *type)
loadaddr = laddr;
/* Add to the list of loaded files */
- file_insert_tail(fp);
+ if (insert != 0)
+ file_insert_tail(fp);
close(fd);
return(fp);
}
@@ -524,7 +525,7 @@ mod_loadkld(const char *kldname, int argc, char *argv[])
* NULL may be passed as a wildcard to either.
*/
struct preloaded_file *
-file_findfile(char *name, char *type)
+file_findfile(const char *name, const char *type)
{
struct preloaded_file *fp;
diff --git a/sys/boot/efi/boot1/Makefile b/sys/boot/efi/boot1/Makefile
index ddf3147..8cb6c62 100644
--- a/sys/boot/efi/boot1/Makefile
+++ b/sys/boot/efi/boot1/Makefile
@@ -9,7 +9,7 @@ MAN=
MK_SSP= no
-PROG= loader.sym
+PROG= boot1.sym
INTERNALPROG=
# architecture-specific loader code
@@ -38,7 +38,7 @@ LDFLAGS= -Wl,-T${LDSCRIPT} -Wl,-Bsymbolic -shared
LDFLAGS+= -Wl,-znocombreloc
.endif
-${PROG}: ${LDSCRIPT}
+DPADD+= ${LDSCRIPT}
OBJCOPY?= objcopy
OBJDUMP?= objdump
@@ -49,19 +49,19 @@ EFI_TARGET= efi-app-x86_64
EFI_TARGET= efi-app-ia32
.endif
-boot1.efi: loader.sym
+boot1.efi: ${PROG}
if [ `${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*' | wc -l` != 0 ]; then \
${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*'; \
exit 1; \
fi
${OBJCOPY} -j .text -j .sdata -j .data \
-j .dynamic -j .dynsym -j .rel.dyn \
- -j .rela.dyn -j .reloc -j .eh_frame -j set_Xcommand_set \
+ -j .rela.dyn -j .reloc -j .eh_frame \
--output-target=${EFI_TARGET} ${.ALLSRC} ${.TARGET}
boot1.o: ${.CURDIR}/../../common/ufsread.c
-# The following inserts out objects into a template FAT file system
+# The following inserts our objects into a template FAT file system
# created by generate-fat.sh
.include "${.CURDIR}/Makefile.fat"
@@ -73,7 +73,7 @@ boot1.efifat: boot1.efi
bzip2 -f -d ${.TARGET}.bz2
dd if=boot1.efi of=${.TARGET} seek=${BOOT1_OFFSET} conv=notrunc
-CLEANFILES= boot1.efifat
+CLEANFILES= boot1.efi boot1.efifat
.endif # ${COMPILER_TYPE} != "gcc"
@@ -82,7 +82,7 @@ CLEANFILES= boot1.efifat
.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386"
beforedepend ${OBJS}: machine x86
-CLEANFILES+= machine x86 boot1.efi
+CLEANFILES+= machine x86
machine:
ln -sf ${.CURDIR}/../../../amd64/include machine
diff --git a/sys/boot/efi/boot1/boot1.c b/sys/boot/efi/boot1/boot1.c
index e0c26da..1e3821b 100644
--- a/sys/boot/efi/boot1/boot1.c
+++ b/sys/boot/efi/boot1/boot1.c
@@ -30,7 +30,7 @@ __FBSDID("$FreeBSD$");
#define _PATH_LOADER "/boot/loader.efi"
#define _PATH_KERNEL "/boot/kernel/kernel"
-
+
#define BSIZEMAX 16384
typedef int putc_func_t(char c, void *arg);
@@ -40,7 +40,7 @@ struct sp_data {
u_int sp_len;
u_int sp_size;
};
-
+
static const char digits[] = "0123456789abcdef";
static void panic(const char *fmt, ...) __dead2;
@@ -62,7 +62,7 @@ static void load(const char *fname);
EFI_SYSTEM_TABLE *systab;
EFI_HANDLE *image;
-static void
+static void
bcopy(const void *src, void *dst, size_t len)
{
const char *s = src;
@@ -71,12 +71,12 @@ bcopy(const void *src, void *dst, size_t len)
while (len-- != 0)
*d++ = *s++;
}
-
+
static void
memcpy(void *dst, const void *src, size_t len)
{
bcopy(src, dst, len);
-}
+}
static void
bzero(void *b, size_t len)
@@ -86,7 +86,7 @@ bzero(void *b, size_t len)
while (len-- != 0)
*p++ = 0;
}
-
+
static int
strcmp(const char *s1, const char *s2)
{
@@ -134,7 +134,7 @@ EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab)
for (i = 0; i < nparts; i++) {
status = systab->BootServices->HandleProtocol(handles[i],
- &DevicePathGUID, (void **)&devpath);
+ &DevicePathGUID, (void **)&devpath);
if (EFI_ERROR(status))
continue;
@@ -142,7 +142,7 @@ EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab)
devpath = NextDevicePathNode(devpath);
status = systab->BootServices->HandleProtocol(handles[i],
- &BlockIoProtocolGUID, (void **)&blkio);
+ &BlockIoProtocolGUID, (void **)&blkio);
if (EFI_ERROR(status))
continue;
@@ -158,7 +158,7 @@ EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab)
bootdevhandle = handles[i];
load(path);
-
+
panic("Load failed");
return EFI_SUCCESS;
@@ -266,7 +266,7 @@ fsstat(ufs_ino_t inode)
}
static struct dmadat __dmadat;
-
+
static int
domount(EFI_DEVICE_PATH *device, EFI_BLOCK_IO *blkio, int quiet)
{
@@ -278,7 +278,7 @@ domount(EFI_DEVICE_PATH *device, EFI_BLOCK_IO *blkio, int quiet)
if (!quiet)
printf("domount: can't read superblock\n");
return (-1);
- }
+ }
if (!quiet)
printf("Succesfully mounted UFS filesystem\n");
return (0);
@@ -303,26 +303,26 @@ load(const char *fname)
status = systab->BootServices->AllocatePool(EfiLoaderData,
bufsize, &buffer);
fsread(ino, buffer, bufsize);
-
+
/* 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",
- status & ~EFI_ERROR_MASK);
+ EFI_ERROR_CODE(status));
status = systab->BootServices->HandleProtocol(loaderhandle,
&LoadedImageGUID, (VOID**)&loaded_image);
if (EFI_ERROR(status))
printf("HandleProtocol failed with error %lu\n",
- status & ~EFI_ERROR_MASK);
+ 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",
- status & ~EFI_ERROR_MASK);
+ EFI_ERROR_CODE(status));
}
static void
@@ -552,4 +552,3 @@ __ultoa(char *buf, u_long ul, int base)
while ((ul /= base) != 0);
return (p);
}
-
diff --git a/sys/boot/efi/include/efierr.h b/sys/boot/efi/include/efierr.h
index dc57f0e..921b297 100644
--- a/sys/boot/efi/include/efierr.h
+++ b/sys/boot/efi/include/efierr.h
@@ -30,7 +30,8 @@ Revision History
#define EFIWARN(a) (a)
-#define EFI_ERROR(a) (((INTN) a) < 0)
+#define EFI_ERROR(a) (((INTN) a) < 0)
+#define EFI_ERROR_CODE(a) (a & ~EFI_ERROR_MASK)
#define EFI_SUCCESS 0
diff --git a/sys/boot/efi/libefi/Makefile b/sys/boot/efi/libefi/Makefile
index 8180d9e..900b230 100644
--- a/sys/boot/efi/libefi/Makefile
+++ b/sys/boot/efi/libefi/Makefile
@@ -19,5 +19,6 @@ CFLAGS+= -I${.CURDIR}/../../common
# Suppress warning from clang for FreeBSD %b and %D formats
CFLAGS+= -fformat-extensions
+CFLAGS+= -DTERM_EMU
.include <bsd.lib.mk>
diff --git a/sys/boot/efi/libefi/efi_console.c b/sys/boot/efi/libefi/efi_console.c
index 3538994..52a3725 100644
--- a/sys/boot/efi/libefi/efi_console.c
+++ b/sys/boot/efi/libefi/efi_console.c
@@ -35,6 +35,69 @@ __FBSDID("$FreeBSD$");
static SIMPLE_TEXT_OUTPUT_INTERFACE *conout;
static SIMPLE_INPUT_INTERFACE *conin;
+#ifdef TERM_EMU
+#define DEFAULT_FGCOLOR EFI_LIGHTGRAY
+#define DEFAULT_BGCOLOR EFI_BLACK
+
+#define MAXARGS 8
+static int args[MAXARGS], argc;
+static int fg_c, bg_c, curx, cury;
+static int esc;
+
+void get_pos(int *x, int *y);
+void curs_move(int *_x, int *_y, int x, int y);
+static void CL(int);
+#endif
+
+static void efi_cons_probe(struct console *);
+static int efi_cons_init(int);
+void efi_cons_putchar(int);
+int efi_cons_getchar(void);
+void efi_cons_efiputchar(int);
+int efi_cons_poll(void);
+
+struct console efi_console = {
+ "efi",
+ "EFI console",
+ 0,
+ efi_cons_probe,
+ efi_cons_init,
+ efi_cons_putchar,
+ efi_cons_getchar,
+ efi_cons_poll
+};
+
+#ifdef TERM_EMU
+
+/* Get cursor position. */
+void
+get_pos(int *x, int *y)
+{
+ *x = conout->Mode->CursorColumn;
+ *y = conout->Mode->CursorRow;
+}
+
+/* Move cursor to x rows and y cols (0-based). */
+void
+curs_move(int *_x, int *_y, int x, int y)
+{
+ conout->SetCursorPosition(conout, x, y);
+ if (_x != NULL)
+ *_x = conout->Mode->CursorColumn;
+ if (_y != NULL)
+ *_y = conout->Mode->CursorRow;
+}
+
+/* Clear internal state of the terminal emulation code. */
+void
+end_term(void)
+{
+ esc = 0;
+ argc = -1;
+}
+
+#endif
+
static void
efi_cons_probe(struct console *cp)
{
@@ -46,22 +109,314 @@ efi_cons_probe(struct console *cp)
static int
efi_cons_init(int arg)
{
- conout->SetAttribute(conout, EFI_TEXT_ATTR(EFI_LIGHTGRAY, EFI_BLACK));
+ conout->SetAttribute(conout, EFI_TEXT_ATTR(DEFAULT_FGCOLOR,
+ DEFAULT_BGCOLOR));
+#ifdef TERM_EMU
+ end_term();
+ get_pos(&curx, &cury);
+ curs_move(&curx, &cury, curx, cury);
+ fg_c = DEFAULT_FGCOLOR;
+ bg_c = DEFAULT_BGCOLOR;
+#endif
+ conout->EnableCursor(conout, TRUE);
return 0;
}
+static void
+efi_cons_rawputchar(int c)
+{
+ int i;
+ UINTN x, y;
+ conout->QueryMode(conout, conout->Mode->Mode, &x, &y);
+
+ if (c == '\t')
+ /* XXX lame tab expansion */
+ for (i = 0; i < 8; i++)
+ efi_cons_rawputchar(' ');
+ else {
+#ifndef TERM_EMU
+ if (c == '\n')
+ efi_cons_efiputchar('\r');
+ else
+ efi_cons_efiputchar(c);
+#else
+ switch (c) {
+ case '\r':
+ curx = 0;
+ curs_move(&curx, &cury, curx, cury);
+ return;
+ case '\n':
+ cury++;
+ if (cury >= y) {
+ efi_cons_efiputchar('\n');
+ cury--;
+ } else
+ curs_move(&curx, &cury, curx, cury);
+ return;
+ case '\b':
+ if (curx > 0) {
+ curx--;
+ curs_move(&curx, &cury, curx, cury);
+ }
+ return;
+ default:
+ efi_cons_efiputchar(c);
+ curx++;
+ if (curx > x-1) {
+ curx = 0;
+ cury++;
+ }
+ if (cury > y-1) {
+ curx = 0;
+ cury--;
+ }
+ }
+ curs_move(&curx, &cury, curx, cury);
+#endif
+ }
+}
+
+/* Gracefully exit ESC-sequence processing in case of misunderstanding. */
+static void
+bail_out(int c)
+{
+ char buf[16], *ch;
+ int i;
+
+ if (esc) {
+ efi_cons_rawputchar('\033');
+ if (esc != '\033')
+ efi_cons_rawputchar(esc);
+ for (i = 0; i <= argc; ++i) {
+ sprintf(buf, "%d", args[i]);
+ ch = buf;
+ while (*ch)
+ efi_cons_rawputchar(*ch++);
+ }
+ }
+ efi_cons_rawputchar(c);
+ end_term();
+}
+
+/* Clear display from current position to end of screen. */
+static void
+CD(void) {
+ int i;
+ UINTN x, y;
+
+ get_pos(&curx, &cury);
+ if (curx == 0 && cury == 0) {
+ conout->ClearScreen(conout);
+ end_term();
+ return;
+ }
+
+ conout->QueryMode(conout, conout->Mode->Mode, &x, &y);
+ CL(0); /* clear current line from cursor to end */
+ for (i = cury + 1; i < y-1; i++) {
+ curs_move(NULL, NULL, 0, i);
+ CL(0);
+ }
+ curs_move(NULL, NULL, curx, cury);
+ end_term();
+}
+
+/*
+ * Absolute cursor move to args[0] rows and args[1] columns
+ * (the coordinates are 1-based).
+ */
+static void
+CM(void)
+{
+ if (args[0] > 0)
+ args[0]--;
+ if (args[1] > 0)
+ args[1]--;
+ curs_move(&curx, &cury, args[1], args[0]);
+ end_term();
+}
+
+/* Home cursor (left top corner), also called from mode command. */
void
-efi_cons_putchar(int c)
+HO(void)
{
- CHAR16 buf[2];
+ argc = 1;
+ args[0] = args[1] = 1;
+ CM();
+}
- if (c == '\n')
- efi_cons_putchar('\r');
+/* Clear line from current position to end of line */
+static void
+CL(int direction)
+{
+ int i, len;
+ UINTN x, y;
+ CHAR16 *line;
- buf[0] = c;
- buf[1] = 0;
+ conout->QueryMode(conout, conout->Mode->Mode, &x, &y);
+ switch (direction) {
+ case 0: /* from cursor to end */
+ len = x - curx + 1;
+ break;
+ case 1: /* from beginning to cursor */
+ len = curx;
+ break;
+ case 2: /* entire line */
+ len = x;
+ break;
+ }
- conout->OutputString(conout, buf);
+ if (cury == y - 1)
+ len--;
+
+ line = malloc(len * sizeof (CHAR16));
+ if (line == NULL) {
+ printf("out of memory\n");
+ return;
+ }
+ for (i = 0; i < len; i++)
+ line[i] = ' ';
+ line[len-1] = 0;
+
+ if (direction != 0)
+ curs_move(NULL, NULL, 0, cury);
+
+ conout->OutputString(conout, line);
+ /* restore cursor position */
+ curs_move(NULL, NULL, curx, cury);
+ free(line);
+ end_term();
+}
+
+static void
+get_arg(int c)
+{
+ if (argc < 0)
+ argc = 0;
+ args[argc] *= 10;
+ args[argc] += c - '0';
+}
+
+/* Emulate basic capabilities of cons25 terminal */
+static void
+efi_term_emu(int c)
+{
+ static int ansi_col[] = {
+ 0, 4, 2, 6, 1, 5, 3, 7
+ };
+ int t, i;
+
+ switch (esc) {
+ case 0:
+ switch (c) {
+ case '\033':
+ esc = c;
+ break;
+ default:
+ efi_cons_rawputchar(c);
+ break;
+ }
+ break;
+ case '\033':
+ switch (c) {
+ case '[':
+ esc = c;
+ args[0] = 0;
+ argc = -1;
+ break;
+ default:
+ bail_out(c);
+ break;
+ }
+ break;
+ case '[':
+ switch (c) {
+ case ';':
+ if (argc < 0)
+ argc = 0;
+ else if (argc + 1 >= MAXARGS)
+ bail_out(c);
+ else
+ args[++argc] = 0;
+ break;
+ case 'H': /* ho = \E[H */
+ if (argc < 0)
+ HO();
+ else if (argc == 1)
+ CM();
+ else
+ bail_out(c);
+ break;
+ case 'J': /* cd = \E[J */
+ if (argc < 0)
+ CD();
+ else
+ bail_out(c);
+ break;
+ case 'm':
+ if (argc < 0) {
+ fg_c = DEFAULT_FGCOLOR;
+ bg_c = DEFAULT_BGCOLOR;
+ }
+ for (i = 0; i <= argc; ++i) {
+ switch (args[i]) {
+ case 0: /* back to normal */
+ fg_c = DEFAULT_FGCOLOR;
+ bg_c = DEFAULT_BGCOLOR;
+ break;
+ case 1: /* bold */
+ fg_c |= 0x8;
+ break;
+ case 4: /* underline */
+ case 5: /* blink */
+ bg_c |= 0x8;
+ break;
+ case 7: /* reverse */
+ t = fg_c;
+ fg_c = bg_c;
+ bg_c = t;
+ break;
+ case 30: case 31: case 32: case 33:
+ case 34: case 35: case 36: case 37:
+ fg_c = ansi_col[args[i] - 30];
+ break;
+ case 39: /* normal */
+ fg_c = DEFAULT_FGCOLOR;
+ break;
+ case 40: case 41: case 42: case 43:
+ case 44: case 45: case 46: case 47:
+ bg_c = ansi_col[args[i] - 40];
+ break;
+ case 49: /* normal */
+ bg_c = DEFAULT_BGCOLOR;
+ break;
+ }
+ }
+ conout->SetAttribute(conout, EFI_TEXT_ATTR(fg_c, bg_c));
+ end_term();
+ break;
+ default:
+ if (isdigit(c))
+ get_arg(c);
+ else
+ bail_out(c);
+ break;
+ }
+ break;
+ default:
+ bail_out(c);
+ break;
+ }
+}
+
+void
+efi_cons_putchar(int c)
+{
+#ifdef TERM_EMU
+ efi_term_emu(c);
+#else
+ efi_cons_rawputchar(c);
+#endif
}
int
@@ -77,6 +432,12 @@ efi_cons_getchar()
BS->WaitForEvent(1, &conin->WaitForKey, &junk);
status = conin->ReadKeyStroke(conin, &key);
}
+ switch (key.ScanCode) {
+ case 0x17: /* ESC */
+ return (0x1b); /* esc */
+ }
+
+ /* this can return */
return (key.UnicodeChar);
}
@@ -87,13 +448,36 @@ efi_cons_poll()
return (BS->CheckEvent(conin->WaitForKey) == EFI_SUCCESS);
}
-struct console efi_console = {
- "efi",
- "EFI console",
- 0,
- efi_cons_probe,
- efi_cons_init,
- efi_cons_putchar,
- efi_cons_getchar,
- efi_cons_poll
-};
+/* Plain direct access to EFI OutputString(). */
+void
+efi_cons_efiputchar(int c)
+{
+ CHAR16 buf[2];
+
+ /*
+ * translate box chars to unicode
+ */
+ switch (c) {
+ /* single frame */
+ case 0xb3: buf[0] = BOXDRAW_VERTICAL; break;
+ case 0xbf: buf[0] = BOXDRAW_DOWN_LEFT; break;
+ case 0xc0: buf[0] = BOXDRAW_UP_RIGHT; break;
+ case 0xc4: buf[0] = BOXDRAW_HORIZONTAL; break;
+ case 0xda: buf[0] = BOXDRAW_DOWN_RIGHT; break;
+ case 0xd9: buf[0] = BOXDRAW_UP_LEFT; break;
+
+ /* double frame */
+ case 0xba: buf[0] = BOXDRAW_DOUBLE_VERTICAL; break;
+ case 0xbb: buf[0] = BOXDRAW_DOUBLE_DOWN_LEFT; break;
+ case 0xbc: buf[0] = BOXDRAW_DOUBLE_UP_LEFT; break;
+ case 0xc8: buf[0] = BOXDRAW_DOUBLE_UP_RIGHT; break;
+ case 0xc9: buf[0] = BOXDRAW_DOUBLE_DOWN_RIGHT; break;
+ case 0xcd: buf[0] = BOXDRAW_DOUBLE_HORIZONTAL; break;
+
+ default:
+ buf[0] = c;
+ }
+ buf[1] = 0; /* terminate string */
+
+ conout->OutputString(conout, buf);
+}
diff --git a/sys/boot/efi/loader/Makefile b/sys/boot/efi/loader/Makefile
index 8d3fe87..268edce 100644
--- a/sys/boot/efi/loader/Makefile
+++ b/sys/boot/efi/loader/Makefile
@@ -12,7 +12,6 @@ MK_SSP= no
PROG= loader.sym
INTERNALPROG=
-.PATH: ${.CURDIR}/../../efi/loader
# architecture-specific loader code
SRCS= autoload.c \
bootinfo.c \
@@ -80,7 +79,7 @@ EFI_TARGET= efi-app-x86_64
EFI_TARGET= efi-app-ia32
.endif
-loader.efi: loader.sym
+loader.efi: ${PROG}
if [ `${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*' | wc -l` != 0 ]; then \
${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*'; \
exit 1; \
diff --git a/sys/boot/efi/loader/bootinfo.c b/sys/boot/efi/loader/bootinfo.c
index f3bb9cc..18837f8 100644
--- a/sys/boot/efi/loader/bootinfo.c
+++ b/sys/boot/efi/loader/bootinfo.c
@@ -275,7 +275,7 @@ bi_load_efi_data(struct preloaded_file *kfp)
pages, &addr);
if (EFI_ERROR(status)) {
printf("%s: AllocatePages error %lu\n", __func__,
- (unsigned long)(status & ~EFI_ERROR_MASK));
+ EFI_ERROR_CODE(status));
return (ENOMEM);
}
@@ -291,7 +291,7 @@ bi_load_efi_data(struct preloaded_file *kfp)
status = BS->GetMemoryMap(&sz, mm, &efi_mapkey, &mmsz, &mmver);
if (EFI_ERROR(status)) {
printf("%s: GetMemoryMap error %lu\n", __func__,
- (unsigned long)(status & ~EFI_ERROR_MASK));
+ EFI_ERROR_CODE(status));
return (EINVAL);
}
status = BS->ExitBootServices(IH, efi_mapkey);
@@ -305,8 +305,7 @@ bi_load_efi_data(struct preloaded_file *kfp)
}
BS->FreePages(addr, pages);
}
- printf("ExitBootServices error %lu\n",
- (unsigned long)(status & ~EFI_ERROR_MASK));
+ printf("ExitBootServices error %lu\n", EFI_ERROR_CODE(status));
return (EINVAL);
}
diff --git a/sys/boot/efi/loader/copy.c b/sys/boot/efi/loader/copy.c
index a7d6bf1..363d95d 100644
--- a/sys/boot/efi/loader/copy.c
+++ b/sys/boot/efi/loader/copy.c
@@ -56,7 +56,7 @@ efi_copy_init(void)
STAGE_PAGES, &staging);
if (EFI_ERROR(status)) {
printf("failed to allocate staging area: %lu\n",
- (unsigned long)(status & EFI_ERROR_MASK));
+ EFI_ERROR_CODE(status));
return (status);
}
staging_end = staging + STAGE_PAGES * EFI_PAGE_SIZE;
diff --git a/sys/boot/efi/loader/main.c b/sys/boot/efi/loader/main.c
index e6e13f1..ec9f9af 100644
--- a/sys/boot/efi/loader/main.c
+++ b/sys/boot/efi/loader/main.c
@@ -63,10 +63,10 @@ EFI_GUID debugimg = DEBUG_IMAGE_INFO_TABLE_GUID;
EFI_STATUS
main(int argc, CHAR16 *argv[])
{
- char vendor[128];
+ char var[128];
EFI_LOADED_IMAGE *img;
EFI_GUID *guid;
- int i;
+ int i, j, vargood;
/*
* XXX Chicken-and-egg problem; we want to have console output
@@ -76,6 +76,29 @@ main(int argc, CHAR16 *argv[])
*/
cons_probe();
+ /*
+ * Loop through the args, and for each one that contains an '=' that is
+ * not the first character, add it to the environment. This allows
+ * loader and kernel env vars to be passed on the command line. Convert
+ * args from UCS-2 to ASCII (16 to 8 bit) as they are copied.
+ */
+ for (i = 1; i < argc; i++) {
+ vargood = 0;
+ for (j = 0; argv[i][j] != 0; j++) {
+ if (j == sizeof(var)) {
+ vargood = 0;
+ break;
+ }
+ if (j > 0 && argv[i][j] == '=')
+ vargood = 1;
+ var[j] = (char)argv[i][j];
+ }
+ if (vargood) {
+ var[j] = 0;
+ putenv(var);
+ }
+ }
+
if (efi_copy_init()) {
printf("failed to allocate staging area\n");
return (EFI_BUFFER_TOO_SMALL);
@@ -203,50 +226,47 @@ command_memmap(int argc, char *argv[])
status = BS->GetMemoryMap(&sz, 0, &key, &dsz, &dver);
if (status != EFI_BUFFER_TOO_SMALL) {
printf("Can't determine memory map size\n");
- return CMD_ERROR;
+ return (CMD_ERROR);
}
map = malloc(sz);
status = BS->GetMemoryMap(&sz, map, &key, &dsz, &dver);
if (EFI_ERROR(status)) {
printf("Can't read memory map\n");
- return CMD_ERROR;
+ return (CMD_ERROR);
}
ndesc = sz / dsz;
printf("%23s %12s %12s %8s %4s\n",
- "Type", "Physical", "Virtual", "#Pages", "Attr");
+ "Type", "Physical", "Virtual", "#Pages", "Attr");
for (i = 0, p = map; i < ndesc;
i++, p = NextMemoryDescriptor(p, dsz)) {
- printf("%23s %012lx %012lx %08lx ",
- types[p->Type],
- p->PhysicalStart,
- p->VirtualStart,
- p->NumberOfPages);
- if (p->Attribute & EFI_MEMORY_UC)
- printf("UC ");
- if (p->Attribute & EFI_MEMORY_WC)
- printf("WC ");
- if (p->Attribute & EFI_MEMORY_WT)
- printf("WT ");
- if (p->Attribute & EFI_MEMORY_WB)
- printf("WB ");
- if (p->Attribute & EFI_MEMORY_UCE)
- printf("UCE ");
- if (p->Attribute & EFI_MEMORY_WP)
- printf("WP ");
- if (p->Attribute & EFI_MEMORY_RP)
- printf("RP ");
- if (p->Attribute & EFI_MEMORY_XP)
- printf("XP ");
- printf("\n");
+ printf("%23s %012lx %012lx %08lx ", types[p->Type],
+ p->PhysicalStart, p->VirtualStart, p->NumberOfPages);
+ if (p->Attribute & EFI_MEMORY_UC)
+ printf("UC ");
+ if (p->Attribute & EFI_MEMORY_WC)
+ printf("WC ");
+ if (p->Attribute & EFI_MEMORY_WT)
+ printf("WT ");
+ if (p->Attribute & EFI_MEMORY_WB)
+ printf("WB ");
+ if (p->Attribute & EFI_MEMORY_UCE)
+ printf("UCE ");
+ if (p->Attribute & EFI_MEMORY_WP)
+ printf("WP ");
+ if (p->Attribute & EFI_MEMORY_RP)
+ printf("RP ");
+ if (p->Attribute & EFI_MEMORY_XP)
+ printf("XP ");
+ printf("\n");
}
- return CMD_OK;
+ return (CMD_OK);
}
-COMMAND_SET(configuration, "configuration",
- "print configuration tables", command_configuration);
+COMMAND_SET(configuration, "configuration", "print configuration tables",
+ command_configuration);
static const char *
guid_to_string(EFI_GUID *guid)
@@ -292,7 +312,7 @@ command_configuration(int argc, char *argv[])
printf(" at %p\n", ST->ConfigurationTable[i].VendorTable);
}
- return CMD_OK;
+ return (CMD_OK);
}
@@ -308,6 +328,7 @@ command_mode(int argc, char *argv[])
char rowenv[8];
EFI_STATUS status;
SIMPLE_TEXT_OUTPUT_INTERFACE *conout;
+ extern void HO(void);
conout = ST->ConOut;
@@ -329,14 +350,15 @@ command_mode(int argc, char *argv[])
}
sprintf(rowenv, "%u", (unsigned)rows);
setenv("LINES", rowenv, 1);
-
+ HO(); /* set cursor */
return (CMD_OK);
}
- for (i = 0; ; i++) {
+ printf("Current mode: %d\n", conout->Mode->Mode);
+ for (i = 0; i <= conout->Mode->MaxMode; i++) {
status = conout->QueryMode(conout, i, &cols, &rows);
if (EFI_ERROR(status))
- break;
+ continue;
printf("Mode %d: %u columns, %u rows\n", i, (unsigned)cols,
(unsigned)rows);
}
@@ -367,20 +389,17 @@ command_nvram(int argc, char *argv[])
status = RS->GetNextVariableName(&varsz, NULL, NULL);
for (; status != EFI_NOT_FOUND; ) {
- status = RS->GetNextVariableName(&varsz, var,
- &varguid);
+ status = RS->GetNextVariableName(&varsz, var, &varguid);
//if (EFI_ERROR(status))
//break;
conout->OutputString(conout, var);
printf("=");
datasz = 0;
- status = RS->GetVariable(var, &varguid, NULL, &datasz,
- NULL);
+ status = RS->GetVariable(var, &varguid, NULL, &datasz, NULL);
/* XXX: check status */
data = malloc(datasz);
- status = RS->GetVariable(var, &varguid, NULL, &datasz,
- data);
+ status = RS->GetVariable(var, &varguid, NULL, &datasz, data);
if (EFI_ERROR(status))
printf("<error retrieving variable>");
else {
diff --git a/sys/boot/fdt/dts/arm/beaglebone-black.dts b/sys/boot/fdt/dts/arm/beaglebone-black.dts
index ff25f9d..0e35a7a 100644
--- a/sys/boot/fdt/dts/arm/beaglebone-black.dts
+++ b/sys/boot/fdt/dts/arm/beaglebone-black.dts
@@ -146,9 +146,9 @@
};
i2c@44e0b000 {
- pmic@48 {
+ pmic@24 {
compatible = "ti,am335x-pmic";
- reg = <0x48>;
+ reg = <0x24>;
};
};
};
diff --git a/sys/boot/fdt/dts/arm/beaglebone.dts b/sys/boot/fdt/dts/arm/beaglebone.dts
index 83b948f..3f8e022 100644
--- a/sys/boot/fdt/dts/arm/beaglebone.dts
+++ b/sys/boot/fdt/dts/arm/beaglebone.dts
@@ -133,7 +133,7 @@
i2c@44e0b000 {
pmic@24 {
compatible = "ti,am335x-pmic";
- reg = <0x48>;
+ reg = <0x24>;
};
};
};
diff --git a/sys/boot/fdt/fdt_loader_cmd.c b/sys/boot/fdt/fdt_loader_cmd.c
index 0f63776..98a0388 100644
--- a/sys/boot/fdt/fdt_loader_cmd.c
+++ b/sys/boot/fdt/fdt_loader_cmd.c
@@ -261,7 +261,7 @@ fdt_load_dtb_file(const char * filename)
oldbfp = file_findfile(NULL, "dtb");
/* Attempt to load and validate a new dtb from a file. */
- if ((bfp = file_loadraw(filename, "dtb")) == NULL) {
+ if ((bfp = file_loadraw(filename, "dtb", 1)) == NULL) {
sprintf(command_errbuf, "failed to load file '%s'", filename);
return (1);
}
diff --git a/sys/boot/ficl/amd64/sysdep.c b/sys/boot/ficl/amd64/sysdep.c
index 00b0d4a..6031094 100644
--- a/sys/boot/ficl/amd64/sysdep.c
+++ b/sys/boot/ficl/amd64/sysdep.c
@@ -55,7 +55,7 @@ void ficlTextOut(FICL_VM *pVM, char *msg, int fNewline)
IGNORE(pVM);
while(*msg != 0)
- putchar(*(msg++));
+ putchar((unsigned char)*(msg++));
if (fNewline)
putchar('\n');
diff --git a/sys/boot/forth/beastie.4th b/sys/boot/forth/beastie.4th
index 9ede592..752cce2 100644
--- a/sys/boot/forth/beastie.4th
+++ b/sys/boot/forth/beastie.4th
@@ -85,14 +85,10 @@ variable logoY
also support-functions
: beastie-start ( -- ) \ starts the menu
- s" console" getenv dup -1 <> if
- s" efi" 2swap contains? if
- s" set beastie_disable=YES" evaluate
- then
- else drop then
s" beastie_disable" getenv dup -1 <> if
s" YES" compare-insensitive 0= if
any_conf_read? if
+ load_xen_throw
load_kernel
load_modules
then
diff --git a/sys/boot/forth/beastie.4th.8 b/sys/boot/forth/beastie.4th.8
index 534a60c..70d8694 100644
--- a/sys/boot/forth/beastie.4th.8
+++ b/sys/boot/forth/beastie.4th.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd April 27, 2014
+.Dd January 20, 2016
.Dt BEASTIE.4TH 8
.Os
.Sh NAME
@@ -119,8 +119,7 @@ Sets the desired row position of the logo. Default is 4.
If set to
.Dq YES ,
the beastie boot menu will be skipped.
-The beastie boot menu is always skipped if booting UEFI or running non-x86
-hardware.
+The beastie boot menu is always skipped if running non-x86 hardware.
.It Va loader_delay
If set to a number higher than zero, introduces a delay before starting the
beastie boot menu. During the delay the user can press either Ctrl-C to skip
diff --git a/sys/boot/forth/loader.4th b/sys/boot/forth/loader.4th
index 43d2a8e..ad4042e 100644
--- a/sys/boot/forth/loader.4th
+++ b/sys/boot/forth/loader.4th
@@ -147,13 +147,14 @@ only forth definitions also support-functions
\ was succesfully loaded!
any_conf_read? if
s" loader_delay" getenv -1 = if
+ load_xen_throw
load_kernel
load_modules
else
drop
." Loading Kernel and Modules (Ctrl-C to Abort)" cr
s" also support-functions" evaluate
- s" set delay_command='load_kernel load_modules'" evaluate
+ s" set delay_command='load_xen_throw load_kernel load_modules'" evaluate
s" set delay_showdots" evaluate
delay_execute
then
diff --git a/sys/boot/forth/loader.conf.5 b/sys/boot/forth/loader.conf.5
index 3c1ce1d..c574a92 100644
--- a/sys/boot/forth/loader.conf.5
+++ b/sys/boot/forth/loader.conf.5
@@ -23,7 +23,7 @@
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
-.Dd April 27, 2014
+.Dd January 20, 2016
.Dt LOADER.CONF 5
.Os
.Sh NAME
@@ -236,8 +236,7 @@ be displayed.
If set to
.Dq YES ,
the beastie boot menu will be skipped.
-The beastie boot menu is always skipped if booting UEFI or running non-x86
-hardware.
+The beastie boot menu is always skipped if running non-x86 hardware.
.It Va loader_logo Pq Dq Li orbbw
Selects a desired logo in the beastie boot menu.
Possible values are:
diff --git a/sys/boot/forth/support.4th b/sys/boot/forth/support.4th
index 1acef70..3d9990d 100644
--- a/sys/boot/forth/support.4th
+++ b/sys/boot/forth/support.4th
@@ -1460,6 +1460,20 @@ also builtins
abort" Unable to load a kernel!"
;
+: load_xen ( -- )
+ s" xen_kernel" getenv dup -1 <> if
+ 1 1 load
+ else
+ drop
+ 0
+ then
+;
+
+: load_xen_throw ( -- ) ( throws: abort )
+ load_xen
+ abort" Unable to load Xen!"
+;
+
: set_defaultoptions ( -- )
s" kernel_options" getenv dup -1 = if
drop
@@ -1578,12 +1592,15 @@ also builtins
else
drop
then
- r> if ( a path was passed )
- load_directory_or_file
- else
- standard_kernel_search
+ load_xen
+ ?dup 0= if ( success )
+ r> if ( a path was passed )
+ load_directory_or_file
+ else
+ standard_kernel_search
+ then
+ ?dup 0= if ['] load_modules catch then
then
- ?dup 0= if ['] load_modules catch then
;
only forth definitions
diff --git a/sys/boot/i386/libi386/Makefile b/sys/boot/i386/libi386/Makefile
index 1c4f049..d4fea80 100644
--- a/sys/boot/i386/libi386/Makefile
+++ b/sys/boot/i386/libi386/Makefile
@@ -6,7 +6,7 @@ INTERNALLIB=
SRCS= biosacpi.c bioscd.c biosdisk.c biosmem.c biospnp.c \
biospci.c biossmap.c bootinfo.c bootinfo32.c bootinfo64.c \
comconsole.c devicename.c elf32_freebsd.c \
- elf64_freebsd.c \
+ elf64_freebsd.c multiboot.c multiboot_tramp.S \
i386_copy.c i386_module.c nullconsole.c pxe.c pxetramp.s \
smbios.c time.c vidconsole.c amd64_tramp.S spinconsole.c
.PATH: ${.CURDIR}/../../zfs
@@ -65,6 +65,7 @@ machine:
# XXX: clang integrated-as doesn't grok .codeNN directives yet
CFLAGS.amd64_tramp.S= ${CLANG_NO_IAS}
+CFLAGS.multiboot_tramp.S= ${CLANG_NO_IAS}
CFLAGS+= ${CFLAGS.${.IMPSRC:T}}
.if ${MACHINE_CPUARCH} == "amd64"
diff --git a/sys/boot/i386/libi386/bootinfo64.c b/sys/boot/i386/libi386/bootinfo64.c
index 617414e..751e806 100644
--- a/sys/boot/i386/libi386/bootinfo64.c
+++ b/sys/boot/i386/libi386/bootinfo64.c
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include <sys/linker.h>
#include <machine/bootinfo.h>
#include <machine/cpufunc.h>
+#include <machine/metadata.h>
#include <machine/psl.h>
#include <machine/specialreg.h>
#include "bootstrap.h"
@@ -176,14 +177,15 @@ bi_checkcpu(void)
* - Module metadata are formatted and placed in kernel space.
*/
int
-bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernendp)
+bi_load64(char *args, vm_offset_t addr, vm_offset_t *modulep,
+ vm_offset_t *kernendp, int add_smap)
{
struct preloaded_file *xp, *kfp;
struct i386_devdesc *rootdev;
struct file_metadata *md;
- vm_offset_t addr;
u_int64_t kernend;
u_int64_t envp;
+ u_int64_t module;
vm_offset_t size;
char *rootdevname;
int howto;
@@ -210,21 +212,18 @@ bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernendp)
/* Try reading the /etc/fstab file to select the root device */
getrootmount(i386_fmtdev((void *)rootdev));
- /* find the last module in the chain */
- addr = 0;
- for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) {
- if (addr < (xp->f_addr + xp->f_size))
- addr = xp->f_addr + xp->f_size;
+ if (addr == 0) {
+ /* find the last module in the chain */
+ for (xp = file_findfile(NULL, NULL); xp != NULL; xp = xp->f_next) {
+ if (addr < (xp->f_addr + xp->f_size))
+ addr = xp->f_addr + xp->f_size;
+ }
}
/* pad to a page boundary */
addr = roundup(addr, PAGE_SIZE);
- /* copy our environment */
- envp = addr;
- addr = bi_copyenv(addr);
-
- /* pad to a page boundary */
- addr = roundup(addr, PAGE_SIZE);
+ /* place the metadata before anything */
+ module = *modulep = addr;
kfp = file_findfile(NULL, "elf kernel");
if (kfp == NULL)
@@ -235,20 +234,30 @@ bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernendp)
file_addmetadata(kfp, MODINFOMD_HOWTO, sizeof howto, &howto);
file_addmetadata(kfp, MODINFOMD_ENVP, sizeof envp, &envp);
file_addmetadata(kfp, MODINFOMD_KERNEND, sizeof kernend, &kernend);
- bios_addsmapdata(kfp);
+ file_addmetadata(kfp, MODINFOMD_MODULEP, sizeof module, &module);
+ if (add_smap != 0)
+ bios_addsmapdata(kfp);
- /* Figure out the size and location of the metadata */
- *modulep = addr;
size = bi_copymodules64(0);
- kernend = roundup(addr + size, PAGE_SIZE);
+
+ /* copy our environment */
+ envp = roundup(addr + size, PAGE_SIZE);
+ addr = bi_copyenv(envp);
+
+ /* set kernend */
+ kernend = roundup(addr, PAGE_SIZE);
*kernendp = kernend;
/* patch MODINFOMD_KERNEND */
md = file_findmetadata(kfp, MODINFOMD_KERNEND);
bcopy(&kernend, md->md_data, sizeof kernend);
+ /* patch MODINFOMD_ENVP */
+ md = file_findmetadata(kfp, MODINFOMD_ENVP);
+ bcopy(&envp, md->md_data, sizeof envp);
+
/* copy module list and metadata */
- (void)bi_copymodules64(addr);
+ (void)bi_copymodules64(*modulep);
return(0);
}
diff --git a/sys/boot/i386/libi386/elf64_freebsd.c b/sys/boot/i386/libi386/elf64_freebsd.c
index 627d416..338a745 100644
--- a/sys/boot/i386/libi386/elf64_freebsd.c
+++ b/sys/boot/i386/libi386/elf64_freebsd.c
@@ -81,7 +81,7 @@ elf64_exec(struct preloaded_file *fp)
return(EFTYPE);
ehdr = (Elf_Ehdr *)&(md->md_data);
- err = bi_load64(fp->f_args, &modulep, &kernend);
+ err = bi_load64(fp->f_args, 0, &modulep, &kernend, 1);
if (err != 0)
return(err);
diff --git a/sys/boot/i386/libi386/libi386.h b/sys/boot/i386/libi386/libi386.h
index 357b8fd..e8bdf65 100644
--- a/sys/boot/i386/libi386/libi386.h
+++ b/sys/boot/i386/libi386/libi386.h
@@ -117,6 +117,7 @@ void bi_setboothowto(int howto);
vm_offset_t bi_copyenv(vm_offset_t addr);
int bi_load32(char *args, int *howtop, int *bootdevp, vm_offset_t *bip,
vm_offset_t *modulep, vm_offset_t *kernend);
-int bi_load64(char *args, vm_offset_t *modulep, vm_offset_t *kernend);
+int bi_load64(char *args, vm_offset_t addr, vm_offset_t *modulep,
+ vm_offset_t *kernend, int add_smap);
void pxe_enable(void *pxeinfo);
diff --git a/sys/boot/i386/libi386/multiboot.c b/sys/boot/i386/libi386/multiboot.c
new file mode 100644
index 0000000..00e36f2
--- /dev/null
+++ b/sys/boot/i386/libi386/multiboot.c
@@ -0,0 +1,425 @@
+/*-
+ * Copyright (c) 2014 Roger Pau Monné <royger@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * This multiboot implementation only implements a subset of the full
+ * multiboot specification in order to be able to boot Xen and a
+ * FreeBSD Dom0. Trying to use it to boot other multiboot compliant
+ * kernels will most surely fail.
+ *
+ * The full multiboot specification can be found here:
+ * http://www.gnu.org/software/grub/manual/multiboot/multiboot.html
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/exec.h>
+#include <sys/linker.h>
+#include <sys/module.h>
+#include <sys/stdint.h>
+#define _MACHINE_ELF_WANT_32BIT
+#include <machine/elf.h>
+#include <string.h>
+#include <stand.h>
+
+#include "bootstrap.h"
+#include "multiboot.h"
+#include "../i386/libi386/libi386.h"
+#include "../i386/btx/lib/btxv86.h"
+
+#define MULTIBOOT_SUPPORTED_FLAGS \
+ (MULTIBOOT_PAGE_ALIGN|MULTIBOOT_MEMORY_INFO)
+#define NUM_MODULES 2
+#define METADATA_FIXED_SIZE (PAGE_SIZE*4)
+#define METADATA_MODULE_SIZE PAGE_SIZE
+
+#define METADATA_RESV_SIZE(mod_num) \
+ roundup(METADATA_FIXED_SIZE + METADATA_MODULE_SIZE * mod_num, PAGE_SIZE)
+
+extern int elf32_loadfile_raw(char *filename, u_int64_t dest,
+ struct preloaded_file **result, int multiboot);
+extern int elf64_load_modmetadata(struct preloaded_file *fp, u_int64_t dest);
+extern int elf64_obj_loadfile(char *filename, u_int64_t dest,
+ struct preloaded_file **result);
+
+static int multiboot_loadfile(char *, u_int64_t, struct preloaded_file **);
+static int multiboot_exec(struct preloaded_file *);
+
+static int multiboot_obj_loadfile(char *, u_int64_t, struct preloaded_file **);
+static int multiboot_obj_exec(struct preloaded_file *fp);
+
+struct file_format multiboot = { multiboot_loadfile, multiboot_exec };
+struct file_format multiboot_obj =
+ { multiboot_obj_loadfile, multiboot_obj_exec };
+
+extern void multiboot_tramp();
+
+static const char mbl_name[] = "FreeBSD Loader";
+
+static int
+num_modules(struct preloaded_file *kfp)
+{
+ struct kernel_module *kmp;
+ int mod_num = 0;
+
+ for (kmp = kfp->f_modules; kmp != NULL; kmp = kmp->m_next)
+ mod_num++;
+
+ return (mod_num);
+}
+
+static vm_offset_t
+max_addr(void)
+{
+ struct preloaded_file *fp;
+ vm_offset_t addr = 0;
+
+ for (fp = file_findfile(NULL, NULL); fp != NULL; fp = fp->f_next) {
+ if (addr < (fp->f_addr + fp->f_size))
+ addr = fp->f_addr + fp->f_size;
+ }
+
+ return (addr);
+}
+
+static int
+multiboot_loadfile(char *filename, u_int64_t dest,
+ struct preloaded_file **result)
+{
+ uint32_t *magic;
+ int i, error;
+ caddr_t header_search;
+ ssize_t search_size;
+ int fd;
+ struct multiboot_header *header;
+ char *cmdline;
+
+ /*
+ * Read MULTIBOOT_SEARCH size in order to search for the
+ * multiboot magic header.
+ */
+ if (filename == NULL)
+ return (EFTYPE);
+ if ((fd = open(filename, O_RDONLY)) == -1)
+ return (errno);
+ header_search = malloc(MULTIBOOT_SEARCH);
+ if (header_search == NULL) {
+ close(fd);
+ return (ENOMEM);
+ }
+ search_size = read(fd, header_search, MULTIBOOT_SEARCH);
+ magic = (uint32_t *)header_search;
+
+ header = NULL;
+ for (i = 0; i < (search_size / sizeof(uint32_t)); i++) {
+ if (magic[i] == MULTIBOOT_HEADER_MAGIC) {
+ header = (struct multiboot_header *)&magic[i];
+ break;
+ }
+ }
+
+ if (header == NULL) {
+ error = EFTYPE;
+ goto out;
+ }
+
+ /* Valid multiboot header has been found, validate checksum */
+ if (header->magic + header->flags + header->checksum != 0) {
+ printf(
+ "Multiboot checksum failed, magic: 0x%x flags: 0x%x checksum: 0x%x\n",
+ header->magic, header->flags, header->checksum);
+ error = EFTYPE;
+ goto out;
+ }
+
+ if ((header->flags & ~MULTIBOOT_SUPPORTED_FLAGS) != 0) {
+ printf("Unsupported multiboot flags found: 0x%x\n",
+ header->flags);
+ error = EFTYPE;
+ goto out;
+ }
+
+ error = elf32_loadfile_raw(filename, dest, result, 1);
+ if (error != 0) {
+ printf(
+ "elf32_loadfile_raw failed: %d unable to load multiboot kernel\n",
+ error);
+ goto out;
+ }
+
+ /*
+ * f_addr is already aligned to PAGE_SIZE, make sure
+ * f_size it's also aligned so when the modules are loaded
+ * they are aligned to PAGE_SIZE.
+ */
+ (*result)->f_size = roundup((*result)->f_size, PAGE_SIZE);
+
+out:
+ free(header_search);
+ close(fd);
+ return (error);
+}
+
+static int
+multiboot_exec(struct preloaded_file *fp)
+{
+ vm_offset_t module_start, last_addr, metadata_size;
+ vm_offset_t modulep, kernend, entry;
+ struct file_metadata *md;
+ Elf_Ehdr *ehdr;
+ struct multiboot_info *mb_info = NULL;
+ struct multiboot_mod_list *mb_mod = NULL;
+ char *cmdline = NULL;
+ size_t len;
+ int error, mod_num;
+
+ /*
+ * Don't pass the memory size found by the bootloader, the memory
+ * available to Dom0 will be lower than that.
+ */
+ unsetenv("smbios.memory.enabled");
+
+ /* Allocate the multiboot struct and fill the basic details. */
+ mb_info = malloc(sizeof(struct multiboot_info));
+ if (mb_info == NULL) {
+ error = ENOMEM;
+ goto error;
+ }
+ bzero(mb_info, sizeof(struct multiboot_info));
+ mb_info->flags = MULTIBOOT_INFO_MEMORY|MULTIBOOT_INFO_BOOT_LOADER_NAME;
+ mb_info->mem_lower = bios_basemem / 1024;
+ mb_info->mem_upper = bios_extmem / 1024;
+ mb_info->boot_loader_name = VTOP(mbl_name);
+
+ /* Set the Xen command line. */
+ if (fp->f_args == NULL) {
+ /* Add the Xen command line if it is set. */
+ cmdline = getenv("xen_cmdline");
+ if (cmdline != NULL) {
+ fp->f_args = strdup(cmdline);
+ if (fp->f_args == NULL) {
+ error = ENOMEM;
+ goto error;
+ }
+ }
+ }
+ if (fp->f_args != NULL) {
+ len = strlen(fp->f_name) + 1 + strlen(fp->f_args) + 1;
+ cmdline = malloc(len);
+ if (cmdline == NULL) {
+ error = ENOMEM;
+ goto error;
+ }
+ snprintf(cmdline, len, "%s %s", fp->f_name, fp->f_args);
+ mb_info->cmdline = VTOP(cmdline);
+ mb_info->flags |= MULTIBOOT_INFO_CMDLINE;
+ }
+
+ /* Find the entry point of the Xen kernel and save it for later */
+ if ((md = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) {
+ printf("Unable to find %s entry point\n", fp->f_name);
+ error = EINVAL;
+ goto error;
+ }
+ ehdr = (Elf_Ehdr *)&(md->md_data);
+ entry = ehdr->e_entry & 0xffffff;
+
+ /*
+ * Prepare the multiboot module list, Xen assumes the first
+ * module is the Dom0 kernel, and the second one is the initramfs.
+ * This is not optimal for FreeBSD, that doesn't have a initramfs
+ * but instead loads modules dynamically and creates the metadata
+ * info on-the-fly.
+ *
+ * As expected, the first multiboot module is going to be the
+ * FreeBSD kernel loaded as a raw file. The second module is going
+ * to contain the metadata info and the loaded modules.
+ *
+ * On native FreeBSD loads all the modules and then places the
+ * metadata info at the end, but this is painful when running on Xen,
+ * because it relocates the second multiboot module wherever it
+ * likes. In order to workaround this limitation the metadata
+ * information is placed at the start of the second module and
+ * the original modulep value is saved together with the other
+ * metadata, so we can relocate everything.
+ */
+ fp = file_findfile(NULL, "elf kernel");
+ if (fp == NULL) {
+ printf("No FreeBSD kernel provided, aborting\n");
+ error = EINVAL;
+ goto error;
+ }
+
+ mb_mod = malloc(sizeof(struct multiboot_mod_list) * NUM_MODULES);
+ if (mb_mod == NULL) {
+ error = ENOMEM;
+ goto error;
+ }
+
+ bzero(mb_mod, sizeof(struct multiboot_mod_list) * NUM_MODULES);
+
+ /*
+ * Calculate how much memory is needed for the metatdata. We did
+ * an approximation of the maximum size when loading the kernel,
+ * but now we know the exact size, so we can release some of this
+ * preallocated memory if not needed.
+ */
+ last_addr = roundup(max_addr(), PAGE_SIZE);
+ mod_num = num_modules(fp);
+
+ /*
+ * Place the metadata after the last used address in order to
+ * calculate it's size, this will not be used.
+ */
+ error = bi_load64(fp->f_args, last_addr, &modulep, &kernend, 0);
+ if (error != 0) {
+ printf("bi_load64 failed: %d\n", error);
+ goto error;
+ }
+ metadata_size = roundup(kernend - last_addr, PAGE_SIZE);
+
+ /* Check that the size is not greater than what we have reserved */
+ if (metadata_size > METADATA_RESV_SIZE(mod_num)) {
+ printf("Required memory for metadata is greater than reserved "
+ "space, please increase METADATA_FIXED_SIZE and "
+ "METADATA_MODULE_SIZE and rebuild the loader\n");
+ error = ENOMEM;
+ goto error;
+ }
+
+ /*
+ * This is the position where the second multiboot module
+ * will be placed.
+ */
+ module_start = fp->f_addr + fp->f_size - metadata_size;
+
+ error = bi_load64(fp->f_args, module_start, &modulep, &kernend, 0);
+ if (error != 0) {
+ printf("bi_load64 failed: %d\n", error);
+ goto error;
+ }
+
+ mb_mod[0].mod_start = fp->f_addr;
+ mb_mod[0].mod_end = fp->f_addr + fp->f_size;
+ mb_mod[0].mod_end -= METADATA_RESV_SIZE(mod_num);
+
+ mb_mod[1].mod_start = module_start;
+ mb_mod[1].mod_end = last_addr;
+
+ mb_info->mods_count = NUM_MODULES;
+ mb_info->mods_addr = VTOP(mb_mod);
+ mb_info->flags |= MULTIBOOT_INFO_MODS;
+
+ dev_cleanup();
+ __exec((void *)VTOP(multiboot_tramp), (void *)entry,
+ (void *)VTOP(mb_info));
+
+ panic("exec returned");
+
+error:
+ if (mb_mod)
+ free(mb_mod);
+ if (mb_info)
+ free(mb_info);
+ if (cmdline)
+ free(cmdline);
+ return (error);
+}
+
+static int
+multiboot_obj_loadfile(char *filename, u_int64_t dest,
+ struct preloaded_file **result)
+{
+ struct preloaded_file *mfp, *kfp, *rfp;
+ struct kernel_module *kmp;
+ int error, mod_num;
+
+ /* See if there's a multiboot kernel loaded */
+ mfp = file_findfile(NULL, "elf multiboot kernel");
+ if (mfp == NULL)
+ return (EFTYPE);
+
+ /*
+ * We have a multiboot kernel loaded, see if there's a FreeBSD
+ * kernel loaded also.
+ */
+ kfp = file_findfile(NULL, "elf kernel");
+ if (kfp == NULL) {
+ /*
+ * No kernel loaded, this must be it. The kernel has to
+ * be loaded as a raw file, it will be processed by
+ * Xen and correctly loaded as an ELF file.
+ */
+ rfp = file_loadraw(filename, "elf kernel", 0);
+ if (rfp == NULL) {
+ printf(
+ "Unable to load %s as a multiboot payload kernel\n",
+ filename);
+ return (EINVAL);
+ }
+
+ /* Load kernel metadata... */
+ setenv("kernelname", filename, 1);
+ error = elf64_load_modmetadata(rfp, rfp->f_addr + rfp->f_size);
+ if (error) {
+ printf("Unable to load kernel %s metadata error: %d\n",
+ rfp->f_name, error);
+ return (EINVAL);
+ }
+
+ /*
+ * Save space at the end of the kernel in order to place
+ * the metadata information. We do an approximation of the
+ * max metadata size, this is not optimal but it's probably
+ * the best we can do at this point. Once all modules are
+ * loaded and the size of the metadata is known this
+ * space will be recovered if not used.
+ */
+ mod_num = num_modules(rfp);
+ rfp->f_size = roundup(rfp->f_size, PAGE_SIZE);
+ rfp->f_size += METADATA_RESV_SIZE(mod_num);
+ *result = rfp;
+ } else {
+ /* The rest should be loaded as regular modules */
+ error = elf64_obj_loadfile(filename, dest, result);
+ if (error != 0) {
+ printf("Unable to load %s as an object file, error: %d",
+ filename, error);
+ return (error);
+ }
+ }
+
+ return (0);
+}
+
+static int
+multiboot_obj_exec(struct preloaded_file *fp)
+{
+
+ return (EFTYPE);
+}
diff --git a/sys/boot/i386/libi386/multiboot.h b/sys/boot/i386/libi386/multiboot.h
new file mode 100644
index 0000000..819fa2e
--- /dev/null
+++ b/sys/boot/i386/libi386/multiboot.h
@@ -0,0 +1,225 @@
+/* multiboot.h - Multiboot header file. */
+/* Copyright (C) 1999,2003,2007,2008,2009 Free Software Foundation, Inc.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to
+* deal in the Software without restriction, including without limitation the
+* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+* sell copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY
+* DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*
+* $FreeBSD$
+*/
+
+#ifndef MULTIBOOT_HEADER
+#define MULTIBOOT_HEADER 1
+
+/* How many bytes from the start of the file we search for the header. */
+#define MULTIBOOT_SEARCH 8192
+
+/* The magic field should contain this. */
+#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
+
+/* This should be in %eax. */
+#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
+
+/* The bits in the required part of flags field we don't support. */
+#define MULTIBOOT_UNSUPPORTED 0x0000fffc
+
+/* Alignment of multiboot modules. */
+#define MULTIBOOT_MOD_ALIGN 0x00001000
+
+/* Alignment of the multiboot info structure. */
+#define MULTIBOOT_INFO_ALIGN 0x00000004
+
+/* Flags set in the 'flags' member of the multiboot header. */
+
+/* Align all boot modules on i386 page (4KB) boundaries. */
+#define MULTIBOOT_PAGE_ALIGN 0x00000001
+
+/* Must pass memory information to OS. */
+#define MULTIBOOT_MEMORY_INFO 0x00000002
+
+/* Must pass video information to OS. */
+#define MULTIBOOT_VIDEO_MODE 0x00000004
+
+/* This flag indicates the use of the address fields in the header. */
+#define MULTIBOOT_AOUT_KLUDGE 0x00010000
+
+/* Flags to be set in the 'flags' member of the multiboot info structure. */
+
+/* is there basic lower/upper memory information? */
+#define MULTIBOOT_INFO_MEMORY 0x00000001
+/* is there a boot device set? */
+#define MULTIBOOT_INFO_BOOTDEV 0x00000002
+/* is the command-line defined? */
+#define MULTIBOOT_INFO_CMDLINE 0x00000004
+/* are there modules to do something with? */
+#define MULTIBOOT_INFO_MODS 0x00000008
+
+/* These next two are mutually exclusive */
+
+/* is there a symbol table loaded? */
+#define MULTIBOOT_INFO_AOUT_SYMS 0x00000010
+/* is there an ELF section header table? */
+#define MULTIBOOT_INFO_ELF_SHDR 0X00000020
+
+/* is there a full memory map? */
+#define MULTIBOOT_INFO_MEM_MAP 0x00000040
+
+/* Is there drive info? */
+#define MULTIBOOT_INFO_DRIVE_INFO 0x00000080
+
+/* Is there a config table? */
+#define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100
+
+/* Is there a boot loader name? */
+#define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200
+
+/* Is there a APM table? */
+#define MULTIBOOT_INFO_APM_TABLE 0x00000400
+
+/* Is there video information? */
+#define MULTIBOOT_INFO_VIDEO_INFO 0x00000800
+
+#ifndef ASM_FILE
+
+typedef unsigned short multiboot_uint16_t;
+typedef unsigned int multiboot_uint32_t;
+typedef unsigned long long multiboot_uint64_t;
+
+struct multiboot_header
+{
+/* Must be MULTIBOOT_MAGIC - see above. */
+ multiboot_uint32_t magic;
+
+/* Feature flags. */
+ multiboot_uint32_t flags;
+
+/* The above fields plus this one must equal 0 mod 2^32. */
+ multiboot_uint32_t checksum;
+
+/* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */
+ multiboot_uint32_t header_addr;
+ multiboot_uint32_t load_addr;
+ multiboot_uint32_t load_end_addr;
+ multiboot_uint32_t bss_end_addr;
+ multiboot_uint32_t entry_addr;
+
+/* These are only valid if MULTIBOOT_VIDEO_MODE is set. */
+ multiboot_uint32_t mode_type;
+ multiboot_uint32_t width;
+ multiboot_uint32_t height;
+ multiboot_uint32_t depth;
+};
+
+/* The symbol table for a.out. */
+struct multiboot_aout_symbol_table
+{
+ multiboot_uint32_t tabsize;
+ multiboot_uint32_t strsize;
+ multiboot_uint32_t addr;
+ multiboot_uint32_t reserved;
+};
+typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t;
+
+/* The section header table for ELF. */
+struct multiboot_elf_section_header_table
+{
+ multiboot_uint32_t num;
+ multiboot_uint32_t size;
+ multiboot_uint32_t addr;
+ multiboot_uint32_t shndx;
+};
+typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t;
+
+struct multiboot_info
+{
+/* Multiboot info version number */
+ multiboot_uint32_t flags;
+
+/* Available memory from BIOS */
+ multiboot_uint32_t mem_lower;
+ multiboot_uint32_t mem_upper;
+
+/* "root" partition */
+ multiboot_uint32_t boot_device;
+
+/* Kernel command line */
+ multiboot_uint32_t cmdline;
+
+/* Boot-Module list */
+ multiboot_uint32_t mods_count;
+ multiboot_uint32_t mods_addr;
+
+ union
+ {
+ multiboot_aout_symbol_table_t aout_sym;
+ multiboot_elf_section_header_table_t elf_sec;
+ } u;
+
+/* Memory Mapping buffer */
+ multiboot_uint32_t mmap_length;
+ multiboot_uint32_t mmap_addr;
+
+/* Drive Info buffer */
+ multiboot_uint32_t drives_length;
+ multiboot_uint32_t drives_addr;
+
+/* ROM configuration table */
+ multiboot_uint32_t config_table;
+
+/* Boot Loader Name */
+ multiboot_uint32_t boot_loader_name;
+
+/* APM table */
+ multiboot_uint32_t apm_table;
+
+/* Video */
+ multiboot_uint32_t vbe_control_info;
+ multiboot_uint32_t vbe_mode_info;
+ multiboot_uint16_t vbe_mode;
+ multiboot_uint16_t vbe_interface_seg;
+ multiboot_uint16_t vbe_interface_off;
+ multiboot_uint16_t vbe_interface_len;
+};
+typedef struct multiboot_info multiboot_info_t;
+
+struct multiboot_mmap_entry
+{
+ multiboot_uint32_t size;
+ multiboot_uint64_t addr;
+ multiboot_uint64_t len;
+#define MULTIBOOT_MEMORY_AVAILABLE 1
+#define MULTIBOOT_MEMORY_RESERVED 2
+ multiboot_uint32_t type;
+} __attribute__((packed));
+typedef struct multiboot_mmap_entry multiboot_memory_map_t;
+
+struct multiboot_mod_list
+{
+/* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */
+ multiboot_uint32_t mod_start;
+ multiboot_uint32_t mod_end;
+
+/* Module command line */
+ multiboot_uint32_t cmdline;
+
+/* padding to take it to 16 bytes (must be zero) */
+ multiboot_uint32_t pad;
+};
+typedef struct multiboot_mod_list multiboot_module_t;
+
+#endif /* ! ASM_FILE */
+
+#endif /* ! MULTIBOOT_HEADER */
diff --git a/sys/boot/i386/libi386/multiboot_tramp.S b/sys/boot/i386/libi386/multiboot_tramp.S
new file mode 100644
index 0000000..0bd6043
--- /dev/null
+++ b/sys/boot/i386/libi386/multiboot_tramp.S
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 2014 Roger Pau Monné <royger@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#define ASM_FILE
+#include "multiboot.h"
+
+/*
+ * The multiboot specification requires the executable to be launched
+ * with %cs set to a flat read/execute segment with offset 0 and limit
+ * 0xFFFFFFFF, and the rest of the segment registers (%ds, %es, %fs,
+ * %gs, %ss) to flat read/write segments with the same offset and limit.
+ * This is already done by the BTX code before calling multiboot_tramp,
+ * so there is no need to do anything here.
+ */
+
+ .globl multiboot_tramp
+multiboot_tramp:
+ /* Be sure that interrupts are disabled. */
+ cli
+
+ movl $MULTIBOOT_BOOTLOADER_MAGIC, %eax
+ /* Get the entry point and address of the multiboot_info parameter. */
+ movl 8(%esp), %ebx
+ movl 4(%esp), %ecx
+
+ call *%ecx
diff --git a/sys/boot/i386/loader/conf.c b/sys/boot/i386/loader/conf.c
index fda6fd2..38df74d 100644
--- a/sys/boot/i386/loader/conf.c
+++ b/sys/boot/i386/loader/conf.c
@@ -107,8 +107,12 @@ extern struct file_format i386_elf;
extern struct file_format i386_elf_obj;
extern struct file_format amd64_elf;
extern struct file_format amd64_elf_obj;
+extern struct file_format multiboot;
+extern struct file_format multiboot_obj;
struct file_format *file_formats[] = {
+ &multiboot,
+ &multiboot_obj,
#ifdef LOADER_PREFER_AMD64
&amd64_elf,
&amd64_elf_obj,
diff --git a/sys/boot/i386/zfsboot/zfsboot.c b/sys/boot/i386/zfsboot/zfsboot.c
index afb77b2..ca82c63 100644
--- a/sys/boot/i386/zfsboot/zfsboot.c
+++ b/sys/boot/i386/zfsboot/zfsboot.c
@@ -238,7 +238,7 @@ bios_getmem(void)
v86.es = VTOPSEG(&smap);
v86.edi = VTOPOFF(&smap);
v86int();
- if ((v86.efl & 1) || (v86.eax != SMAP_SIG))
+ if (V86_CY(v86.efl) || (v86.eax != SMAP_SIG))
break;
/* look for a low-memory segment that's large enough */
if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base == 0) &&
@@ -285,7 +285,7 @@ bios_getmem(void)
v86.addr = 0x15; /* int 0x15 function 0xe801*/
v86.eax = 0xe801;
v86int();
- if (!(v86.efl & 1)) {
+ if (!V86_CY(v86.efl)) {
bios_extmem = ((v86.ecx & 0xffff) + ((v86.edx & 0xffff) * 64)) * 1024;
}
}
@@ -320,7 +320,7 @@ int13probe(int drive)
v86.edx = drive;
v86int();
- if (!(v86.efl & 0x1) && /* carry clear */
+ if (!V86_CY(v86.efl) && /* carry clear */
((v86.edx & 0xff) != (drive & DRV_MASK))) { /* unit # OK */
if ((v86.ecx & 0x3f) == 0) { /* absurd sector size */
return(0); /* skip device */
diff --git a/sys/boot/ia64/efi/Makefile b/sys/boot/ia64/efi/Makefile
index 6bb53b5..18b6d3a 100644
--- a/sys/boot/ia64/efi/Makefile
+++ b/sys/boot/ia64/efi/Makefile
@@ -37,7 +37,6 @@ FILESMODE_loader.efi= ${BINMODE}
loader.efi: loader.sym
if [ `${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*' | wc -l` != 0 ]; then \
${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*'; \
- rm ${.ALLSRC}; \
exit 1; \
fi
${OBJCOPY} -j .data -j .dynamic -j .dynstr -j .dynsym -j .hash \
diff --git a/sys/boot/libstand32/Makefile b/sys/boot/libstand32/Makefile
index 1fc04a2..4ee8690 100644
--- a/sys/boot/libstand32/Makefile
+++ b/sys/boot/libstand32/Makefile
@@ -63,8 +63,8 @@ SRCS+= ntoh.c
.if ${MACHINE_CPUARCH} != "ia64"
SRCS+= bcmp.c bcopy.c bzero.c ffs.c memccpy.c memchr.c memcmp.c memcpy.c \
memmove.c memset.c qdivrem.c strcat.c strchr.c strcmp.c strcpy.c \
- strcspn.c strlen.c strncat.c strncmp.c strncpy.c strpbrk.c \
- strrchr.c strsep.c strspn.c strstr.c strtok.c swab.c
+ strcspn.c strlcat.c strlcpy.c strlen.c strncat.c strncmp.c strncpy.c \
+ strpbrk.c strrchr.c strsep.c strspn.c strstr.c strtok.c swab.c
.endif
.if ${MACHINE_CPUARCH} == "arm"
.PATH: ${LIBC}/arm/gen
diff --git a/sys/boot/pc98/boot2/boot2.c b/sys/boot/pc98/boot2/boot2.c
index 69a422e..72aae7d 100644
--- a/sys/boot/pc98/boot2/boot2.c
+++ b/sys/boot/pc98/boot2/boot2.c
@@ -326,7 +326,7 @@ bd_getbigeom(int bunit)
v86.addr = 0x1b;
v86.eax = 0x8400 | unit;
v86int();
- if (v86.efl & 0x1)
+ if (V86_CY(v86.efl))
return 0x4F020F; /* 1200KB FD C:80 H:2 S:15 */
return ((v86.ecx & 0xffff) << 16) | (v86.edx & 0xffff);
}
diff --git a/sys/boot/pc98/libpc98/biosdisk.c b/sys/boot/pc98/libpc98/biosdisk.c
index 96dbd1f..b777d25 100644
--- a/sys/boot/pc98/libpc98/biosdisk.c
+++ b/sys/boot/pc98/libpc98/biosdisk.c
@@ -824,7 +824,7 @@ bd_chs_io(struct open_disk *od, daddr_t dblk, int blks, caddr_t dest, int write)
v86.es = VTOPSEG(dest);
v86.ebp = VTOPOFF(dest);
v86int();
- return (v86.efl & 0x1);
+ return (V86_CY(v86.efl));
}
static int
@@ -959,7 +959,7 @@ bd_getgeom(struct open_disk *od)
od->od_cyl = v86.ecx;
od->od_hds = (v86.edx >> 8) & 0xff;
od->od_sec = v86.edx & 0xff;
- if (v86.efl & 0x1)
+ if (V86_CY(v86.efl))
return(1);
}
@@ -1010,7 +1010,7 @@ bd_getbigeom(int bunit)
v86.addr = 0x1b;
v86.eax = 0x8400 | unit;
v86int();
- if (v86.efl & 0x1)
+ if (V86_CY(v86.efl))
return 0x4F020F; /* 1200KB FD C:80 H:2 S:15 */
return ((v86.ecx & 0xffff) << 16) | (v86.edx & 0xffff);
}
diff --git a/sys/boot/uboot/common/main.c b/sys/boot/uboot/common/main.c
index b830354..d860d97 100644
--- a/sys/boot/uboot/common/main.c
+++ b/sys/boot/uboot/common/main.c
@@ -315,7 +315,7 @@ print_disk_probe_info()
else
strcpy(slice, "<auto>");
- if (currdev.d_disk.partition > 0)
+ if (currdev.d_disk.partition >= 0)
sprintf(partition, "%d", currdev.d_disk.partition);
else
strcpy(partition, "<auto>");
@@ -382,7 +382,7 @@ probe_disks(int devidx, int load_type, int load_unit, int load_slice,
printf("\n");
}
- printf(" Requested disk type/unit not found\n");
+ printf(" Requested disk type/unit/slice/partition not found\n");
return (-1);
}
@@ -392,7 +392,7 @@ main(void)
struct api_signature *sig = NULL;
int load_type, load_unit, load_slice, load_partition;
int i;
- const char * loaderdev;
+ const char *ldev;
/*
* If we can't find the magic signature and related info, exit with a
@@ -485,10 +485,10 @@ main(void)
return (0xbadef1ce);
}
- env_setenv("currdev", EV_VOLATILE, uboot_fmtdev(&currdev),
- uboot_setcurrdev, env_nounset);
- env_setenv("loaddev", EV_VOLATILE, uboot_fmtdev(&currdev),
- env_noset, env_nounset);
+ ldev = uboot_fmtdev(&currdev);
+ env_setenv("currdev", EV_VOLATILE, ldev, uboot_setcurrdev, env_nounset);
+ env_setenv("loaddev", EV_VOLATILE, ldev, env_noset, env_nounset);
+ printf("Booting from %s\n", ldev);
setenv("LINES", "24", 1); /* optional */
setenv("prompt", "loader>", 1);
@@ -573,17 +573,47 @@ enum ubenv_action {
static void
handle_uboot_env_var(enum ubenv_action action, const char * var)
{
- const char * val;
- char ubv[128];
+ char ldvar[128];
+ const char *val;
+ char *wrk;
+ int len;
+
+ /*
+ * On an import with the variable name formatted as ldname=ubname,
+ * import the uboot variable ubname into the loader variable ldname,
+ * otherwise the historical behavior is to import to uboot.ubname.
+ */
+ if (action == UBENV_IMPORT) {
+ len = strcspn(var, "=");
+ if (len == 0) {
+ printf("name cannot start with '=': '%s'\n", var);
+ return;
+ }
+ if (var[len] == 0) {
+ strcpy(ldvar, "uboot.");
+ strncat(ldvar, var, sizeof(ldvar) - 7);
+ } else {
+ len = MIN(len, sizeof(ldvar) - 1);
+ strncpy(ldvar, var, len);
+ ldvar[len] = 0;
+ var = &var[len + 1];
+ }
+ }
/*
* If the user prepended "uboot." (which is how they usually see these
* names) strip it off as a convenience.
*/
if (strncmp(var, "uboot.", 6) == 0) {
- snprintf(ubv, sizeof(ubv), "%s", &var[6]);
- var = ubv;
+ var = &var[6];
}
+
+ /* If there is no variable name left, punt. */
+ if (var[0] == 0) {
+ printf("empty variable name\n");
+ return;
+ }
+
val = ub_env_get(var);
if (action == UBENV_SHOW) {
if (val == NULL)
@@ -592,8 +622,7 @@ handle_uboot_env_var(enum ubenv_action action, const char * var)
printf("uboot.%s=%s\n", var, val);
} else if (action == UBENV_IMPORT) {
if (val != NULL) {
- snprintf(ubv, sizeof(ubv), "uboot.%s", var);
- setenv(ubv, val, 1);
+ setenv(ldvar, val, 1);
}
}
}
diff --git a/sys/boot/uboot/lib/copy.c b/sys/boot/uboot/lib/copy.c
index bb658e3..76f2faf 100644
--- a/sys/boot/uboot/lib/copy.c
+++ b/sys/boot/uboot/lib/copy.c
@@ -69,11 +69,11 @@ uint64_t
uboot_loadaddr(u_int type, void *data, uint64_t addr)
{
struct sys_info *si;
- uintptr_t sblock, eblock, subldr, eubldr;
- uintptr_t biggest_block, this_block;
- size_t biggest_size, this_size;
+ uint64_t sblock, eblock, subldr, eubldr;
+ uint64_t biggest_block, this_block;
+ uint64_t biggest_size, this_size;
int i;
- char * envstr;
+ char *envstr;
if (addr == 0) {
/*
@@ -101,13 +101,14 @@ uboot_loadaddr(u_int type, void *data, uint64_t addr)
biggest_block = 0;
biggest_size = 0;
subldr = rounddown2((uintptr_t)_start, KERN_ALIGN);
- eubldr = roundup2(uboot_heap_end, KERN_ALIGN);
+ eubldr = roundup2((uint64_t)uboot_heap_end, KERN_ALIGN);
for (i = 0; i < si->mr_no; i++) {
if (si->mr[i].flags != MR_ATTR_DRAM)
continue;
- sblock = roundup2(si->mr[i].start, KERN_ALIGN);
- eblock = rounddown2(si->mr[i].start + si->mr[i].size,
+ sblock = roundup2((uint64_t)si->mr[i].start,
KERN_ALIGN);
+ eblock = rounddown2((uint64_t)si->mr[i].start +
+ si->mr[i].size, KERN_ALIGN);
if (biggest_size == 0)
sblock += KERN_MINADDR;
if (subldr >= sblock && subldr < eblock) {
@@ -127,9 +128,10 @@ uboot_loadaddr(u_int type, void *data, uint64_t addr)
if (biggest_size == 0)
panic("Not enough DRAM to load kernel\n");
#if 0
- printf("Loading kernel into region 0x%08x-0x%08x (%u MiB)\n",
- biggest_block, biggest_block + biggest_size - 1,
- biggest_size / 1024 / 1024);
+ printf("Loading kernel into region 0x%08jx-0x%08jx (%ju MiB)\n",
+ (uintmax_t)biggest_block,
+ (uintmax_t)biggest_block + biggest_size - 1,
+ (uintmax_t)biggest_size / 1024 / 1024);
#endif
return (biggest_block);
}
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 fd3e537..ee0b52f 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
@@ -607,7 +607,6 @@ spa_prop_validate(spa_t *spa, nvlist_t *props)
error = SET_ERROR(EINVAL);
break;
}
- check++;
}
if (strlen(strval) > ZPROP_MAX_COMMENT)
error = E2BIG;
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_queue.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_queue.c
index 49d87e6..9f83abb 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_queue.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_queue.c
@@ -520,7 +520,7 @@ vdev_queue_class_min_active(zio_priority_t p)
}
}
-static int
+static __noinline int
vdev_queue_max_async_writes(spa_t *spa)
{
int writes;
diff --git a/sys/cddl/dev/systrace/systrace.c b/sys/cddl/dev/systrace/systrace.c
index 921393c..1796091 100644
--- a/sys/cddl/dev/systrace/systrace.c
+++ b/sys/cddl/dev/systrace/systrace.c
@@ -60,24 +60,37 @@
#ifdef LINUX_SYSTRACE
#if defined(__amd64__)
-#include <amd64/linux32/linux.h>
-#include <amd64/linux32/linux32_proto.h>
-#include <amd64/linux32/linux32_syscalls.c>
-#include <amd64/linux32/linux32_systrace_args.c>
-#define MODNAME "linux32"
+#include <amd64/linux/linux.h>
+#include <amd64/linux/linux_proto.h>
+#include <amd64/linux/linux_syscalls.c>
+#include <amd64/linux/linux_systrace_args.c>
#elif defined(__i386__)
#include <i386/linux/linux.h>
#include <i386/linux/linux_proto.h>
#include <i386/linux/linux_syscalls.c>
#include <i386/linux/linux_systrace_args.c>
-#define MODNAME "linux"
#else
#error Only i386 and amd64 are supported.
#endif
+#define MODNAME "linux"
extern struct sysent linux_sysent[];
#define MAXSYSCALL LINUX_SYS_MAXSYSCALL
#define SYSCALLNAMES linux_syscallnames
#define SYSENT linux_sysent
+#elif defined(LINUX32_SYSTRACE)
+#if defined(__amd64__)
+#include <amd64/linux32/linux.h>
+#include <amd64/linux32/linux32_proto.h>
+#include <amd64/linux32/linux32_syscalls.c>
+#include <amd64/linux32/linux32_systrace_args.c>
+#else
+#error Only amd64 is supported.
+#endif
+#define MODNAME "linux32"
+extern struct sysent linux32_sysent[];
+#define MAXSYSCALL LINUX32_SYS_MAXSYSCALL
+#define SYSCALLNAMES linux32_syscallnames
+#define SYSENT linux32_sysent
#elif defined(FREEBSD32_SYSTRACE)
/*
* The syscall arguments are processed into a DTrace argument array
@@ -103,6 +116,7 @@ extern const char *freebsd32_syscallnames[];
#define MAXSYSCALL SYS_MAXSYSCALL
#define SYSCALLNAMES syscallnames
#define SYSENT sysent
+#define NATIVE_ABI
#endif
#define PROVNAME "syscall"
@@ -132,7 +146,7 @@ static void systrace_load(void *);
static struct cdevsw systrace_cdevsw = {
.d_version = D_VERSION,
.d_open = systrace_open,
-#ifdef LINUX_SYSTRACE
+#ifndef NATIVE_ABI
.d_name = "systrace_" MODNAME,
#else
.d_name = "systrace",
@@ -171,7 +185,7 @@ static dtrace_provider_id_t systrace_id;
typedef void (*systrace_dtrace_probe_t)(dtrace_id_t, uintptr_t, uintptr_t,
uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
-#if !defined(LINUX_SYSTRACE)
+#ifdef NATIVE_ABI
/*
* Probe callback function.
*
@@ -314,7 +328,7 @@ systrace_load(void *dummy)
NULL, &systrace_pops, NULL, &systrace_id) != 0)
return;
-#if !defined(LINUX_SYSTRACE)
+#ifdef NATIVE_ABI
systrace_probe_func = systrace_probe;
#endif
}
@@ -328,7 +342,7 @@ systrace_unload()
if ((error = dtrace_unregister(systrace_id)) != 0)
return (error);
-#if !defined(LINUX_SYSTRACE)
+#ifdef NATIVE_ABI
systrace_probe_func = NULL;
#endif
@@ -370,6 +384,16 @@ SYSINIT(systrace_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, systrace_load, NULL
SYSUNINIT(systrace_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, systrace_unload, NULL);
#ifdef LINUX_SYSTRACE
+DEV_MODULE(systrace_linux, systrace_modevent, NULL);
+MODULE_VERSION(systrace_linux, 1);
+#ifdef __amd64__
+MODULE_DEPEND(systrace_linux, linux64, 1, 1, 1);
+#else
+MODULE_DEPEND(systrace_linux, linux, 1, 1, 1);
+#endif
+MODULE_DEPEND(systrace_linux, dtrace, 1, 1, 1);
+MODULE_DEPEND(systrace_linux, opensolaris, 1, 1, 1);
+#elif defined(LINUX32_SYSTRACE)
DEV_MODULE(systrace_linux32, systrace_modevent, NULL);
MODULE_VERSION(systrace_linux32, 1);
MODULE_DEPEND(systrace_linux32, linux, 1, 1, 1);
diff --git a/sys/compat/ia32/ia32_sysvec.c b/sys/compat/ia32/ia32_sysvec.c
index 206935a..d2870ce 100644
--- a/sys/compat/ia32/ia32_sysvec.c
+++ b/sys/compat/ia32/ia32_sysvec.c
@@ -140,6 +140,7 @@ struct sysentvec ia32_freebsd_sysvec = {
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
+ .sv_trap = NULL,
};
INIT_SYSENTVEC(elf_ia32_sysvec, &ia32_freebsd_sysvec);
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
index 8f2a687..538b9dc 100644
--- a/sys/compat/linux/linux_misc.c
+++ b/sys/compat/linux/linux_misc.c
@@ -2362,7 +2362,13 @@ linux_ppoll(struct thread *td, struct linux_ppoll_args *args)
#if defined(DEBUG) || defined(KTR)
/* XXX: can be removed when every ldebug(...) and KTR stuff are removed. */
-u_char linux_debug_map[howmany(LINUX_SYS_MAXSYSCALL, sizeof(u_char))];
+#ifdef COMPAT_LINUX32
+#define L_MAXSYSCALL LINUX32_SYS_MAXSYSCALL
+#else
+#define L_MAXSYSCALL LINUX_SYS_MAXSYSCALL
+#endif
+
+u_char linux_debug_map[howmany(L_MAXSYSCALL, sizeof(u_char))];
static int
linux_debug(int syscall, int toggle, int global)
@@ -2374,7 +2380,7 @@ linux_debug(int syscall, int toggle, int global)
memset(linux_debug_map, c, sizeof(linux_debug_map));
return (0);
}
- if (syscall < 0 || syscall >= LINUX_SYS_MAXSYSCALL)
+ if (syscall < 0 || syscall >= L_MAXSYSCALL)
return (EINVAL);
if (toggle)
clrbit(linux_debug_map, syscall);
@@ -2382,6 +2388,7 @@ linux_debug(int syscall, int toggle, int global)
setbit(linux_debug_map, syscall);
return (0);
}
+#undef L_MAXSYSCALL
/*
* Usage: sysctl linux.debug=<syscall_nr>.<0/1>
diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c
index 34af9da..dee4093 100644
--- a/sys/compat/linux/linux_socket.c
+++ b/sys/compat/linux/linux_socket.c
@@ -1164,6 +1164,7 @@ linux_sendmsg_common(struct thread *td, l_int s, struct l_msghdr *msghdr,
msg.msg_iov = iov;
msg.msg_flags = 0;
error = linux_sendit(td, s, &msg, flags, control, UIO_USERSPACE);
+ control = NULL;
bad:
m_freem(control);
diff --git a/sys/compat/svr4/svr4_sysvec.c b/sys/compat/svr4/svr4_sysvec.c
index 125a7d8..8b339c8 100644
--- a/sys/compat/svr4/svr4_sysvec.c
+++ b/sys/compat/svr4/svr4_sysvec.c
@@ -197,6 +197,7 @@ struct sysentvec svr4_sysvec = {
.sv_syscallnames = NULL,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
+ .sv_trap = NULL,
};
const char svr4_emul_path[] = "/compat/svr4";
diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64
index 268892b..445912a 100644
--- a/sys/conf/files.amd64
+++ b/sys/conf/files.amd64
@@ -322,6 +322,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/dev/drm2/i915/intel_iic.c b/sys/dev/drm2/i915/intel_iic.c
index 36a5b9e..30be2efb 100644
--- a/sys/dev/drm2/i915/intel_iic.c
+++ b/sys/dev/drm2/i915/intel_iic.c
@@ -467,8 +467,7 @@ timeout:
* Try GPIO bitbanging instead.
*/
sc->force_bit_dev = true;
- error = -IICBUS_TRANSFER(idev, msgs, nmsgs);
- goto out;
+ error = -IICBUS_TRANSFER(dev_priv->bbbus[unit], msgs, nmsgs);
out:
sx_xunlock(&dev_priv->gmbus_sx);
diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c
index 088ba1e..c4dc51d 100644
--- a/sys/dev/e1000/if_igb.c
+++ b/sys/dev/e1000/if_igb.c
@@ -1313,7 +1313,8 @@ igb_init_locked(struct adapter *adapter)
if (ifp->if_capenable & IFCAP_TXCSUM) {
ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP);
#if __FreeBSD_version >= 800000
- if (adapter->hw.mac.type == e1000_82576)
+ if ((adapter->hw.mac.type == e1000_82576) ||
+ (adapter->hw.mac.type == e1000_82580))
ifp->if_hwassist |= CSUM_SCTP;
#endif
}
@@ -4587,8 +4588,9 @@ igb_initialize_receive_units(struct adapter *adapter)
rxcsum |= E1000_RXCSUM_PCSD;
#if __FreeBSD_version >= 800000
/* For SCTP Offload */
- if ((hw->mac.type == e1000_82576)
- && (ifp->if_capenable & IFCAP_RXCSUM))
+ if (((hw->mac.type == e1000_82576) ||
+ (hw->mac.type == e1000_82580)) &&
+ (ifp->if_capenable & IFCAP_RXCSUM))
rxcsum |= E1000_RXCSUM_CRCOFL;
#endif
} else {
@@ -4596,7 +4598,8 @@ igb_initialize_receive_units(struct adapter *adapter)
if (ifp->if_capenable & IFCAP_RXCSUM) {
rxcsum |= E1000_RXCSUM_IPPCSE;
#if __FreeBSD_version >= 800000
- if (adapter->hw.mac.type == e1000_82576)
+ if ((adapter->hw.mac.type == e1000_82576) ||
+ (adapter->hw.mac.type == e1000_82580))
rxcsum |= E1000_RXCSUM_CRCOFL;
#endif
} else
diff --git a/sys/dev/iicbus/icee.c b/sys/dev/iicbus/icee.c
index 800ec4c..fffb356 100644
--- a/sys/dev/iicbus/icee.c
+++ b/sys/dev/iicbus/icee.c
@@ -27,6 +27,9 @@ __FBSDID("$FreeBSD$");
/*
* Generic IIC eeprom support, modeled after the AT24C family of products.
*/
+
+#include "opt_platform.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
@@ -37,26 +40,73 @@ __FBSDID("$FreeBSD$");
#include <sys/sx.h>
#include <sys/uio.h>
#include <machine/bus.h>
+
+#ifdef FDT
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#endif
+
#include <dev/iicbus/iiconf.h>
#include <dev/iicbus/iicbus.h>
#include "iicbus_if.h"
-#define IIC_M_WR 0 /* write operation */
+/*
+ * AT24 parts have a "write page size" that differs per-device, and a "read page
+ * size" that is always equal to the full device size. We define maximum values
+ * here to limit how long we occupy the bus with a single transfer, and because
+ * there are temporary buffers of these sizes allocated on the stack.
+ */
#define MAX_RD_SZ 256 /* Largest read size we support */
-#define MAX_WR_SZ 256 /* Largest write size we support */
+#define MAX_WR_SZ 256 /* Largest write size we support */
struct icee_softc {
- device_t sc_dev; /* Myself */
- device_t sc_busdev; /* Parent bus */
+ device_t dev; /* Myself */
struct cdev *cdev; /* user interface */
- int addr;
+ int addr; /* Slave address on the bus */
int size; /* How big am I? */
- int type; /* What type 8 or 16 bit? */
- int rd_sz; /* What's the read page size */
+ int type; /* What address type 8 or 16 bit? */
int wr_sz; /* What's the write page size */
};
+#ifdef FDT
+struct eeprom_desc {
+ int type;
+ int size;
+ int wr_sz;
+ const char *name;
+};
+
+static struct eeprom_desc type_desc[] = {
+ { 8, 128, 8, "AT24C01"},
+ { 8, 256, 8, "AT24C02"},
+ { 8, 512, 16, "AT24C04"},
+ { 8, 1024, 16, "AT24C08"},
+ { 8, 2 * 1024, 16, "AT24C16"},
+ {16, 4 * 1024, 32, "AT24C32"},
+ {16, 8 * 1024, 32, "AT24C64"},
+ {16, 16 * 1024, 64, "AT24C128"},
+ {16, 32 * 1024, 64, "AT24C256"},
+ {16, 64 * 1024, 128, "AT24C512"},
+ {16, 128 * 1024, 256, "AT24CM01"},
+};
+
+static struct ofw_compat_data compat_data[] = {
+ {"atmel,24c01", (uintptr_t)(&type_desc[0])},
+ {"atmel,24c02", (uintptr_t)(&type_desc[1])},
+ {"atmel,24c04", (uintptr_t)(&type_desc[2])},
+ {"atmel,24c08", (uintptr_t)(&type_desc[3])},
+ {"atmel,24c16", (uintptr_t)(&type_desc[4])},
+ {"atmel,24c32", (uintptr_t)(&type_desc[5])},
+ {"atmel,24c64", (uintptr_t)(&type_desc[6])},
+ {"atmel,24c128", (uintptr_t)(&type_desc[7])},
+ {"atmel,24c256", (uintptr_t)(&type_desc[8])},
+ {"atmel,24c512", (uintptr_t)(&type_desc[9])},
+ {"atmel,24c1024", (uintptr_t)(&type_desc[10])},
+ {NULL, (uintptr_t)NULL},
+};
+#endif
+
#define CDEV2SOFTC(dev) ((dev)->si_drv1)
/* cdev routines */
@@ -75,6 +125,39 @@ static struct cdevsw icee_cdevsw =
.d_write = icee_write
};
+#ifdef FDT
+static int
+icee_probe(device_t dev)
+{
+ struct eeprom_desc *d;
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ d = (struct eeprom_desc *)
+ ofw_bus_search_compatible(dev, compat_data)->ocd_data;
+ if (d == NULL)
+ return (ENXIO);
+
+ device_set_desc(dev, d->name);
+ return (BUS_PROBE_DEFAULT);
+}
+
+static void
+icee_init(struct icee_softc *sc)
+{
+ struct eeprom_desc *d;
+
+ d = (struct eeprom_desc *)
+ ofw_bus_search_compatible(sc->dev, compat_data)->ocd_data;
+ if (d == NULL)
+ return; /* attach will see sc->size == 0 and return error */
+
+ sc->size = d->size;
+ sc->type = d->type;
+ sc->wr_sz = d->wr_sz;
+}
+#else /* !FDT */
static int
icee_probe(device_t dev)
{
@@ -83,37 +166,44 @@ icee_probe(device_t dev)
return (BUS_PROBE_NOWILDCARD);
}
-static int
-icee_attach(device_t dev)
+static void
+icee_init(struct icee_softc *sc)
{
- struct icee_softc *sc = device_get_softc(dev);
const char *dname;
- int dunit, err;
+ int dunit;
- sc->sc_dev = dev;
- sc->sc_busdev = device_get_parent(sc->sc_dev);
- sc->addr = iicbus_get_addr(dev);
- err = 0;
- dname = device_get_name(dev);
- dunit = device_get_unit(dev);
+ dname = device_get_name(sc->dev);
+ dunit = device_get_unit(sc->dev);
resource_int_value(dname, dunit, "size", &sc->size);
resource_int_value(dname, dunit, "type", &sc->type);
- resource_int_value(dname, dunit, "rd_sz", &sc->rd_sz);
- if (sc->rd_sz > MAX_RD_SZ)
- sc->rd_sz = MAX_RD_SZ;
resource_int_value(dname, dunit, "wr_sz", &sc->wr_sz);
+}
+#endif /* FDT */
+
+static int
+icee_attach(device_t dev)
+{
+ struct icee_softc *sc = device_get_softc(dev);
+
+ sc->dev = dev;
+ sc->addr = iicbus_get_addr(dev);
+ icee_init(sc);
+ if (sc->size == 0 || sc->type == 0 || sc->wr_sz == 0) {
+ device_printf(sc->dev, "Missing config data, "
+ "these cannot be zero: size %d type %d wr_sz %d\n",
+ sc->size, sc->type, sc->wr_sz);
+ return (EINVAL);
+ }
if (bootverbose)
- device_printf(dev, "size: %d bytes bus_width: %d-bits\n",
+ device_printf(dev, "size: %d bytes, addressing: %d-bits\n",
sc->size, sc->type);
sc->cdev = make_dev(&icee_cdevsw, device_get_unit(dev), UID_ROOT,
GID_WHEEL, 0600, "icee%d", device_get_unit(dev));
if (sc->cdev == NULL) {
- err = ENOMEM;
- goto out;
+ return (ENOMEM);
}
sc->cdev->si_drv1 = sc;
-out:
- return (err);
+ return (0);
}
static int
@@ -149,14 +239,11 @@ icee_read(struct cdev *dev, struct uio *uio, int ioflag)
return (EIO);
if (sc->type != 8 && sc->type != 16)
return (EINVAL);
- error = iicbus_request_bus(sc->sc_busdev, sc->sc_dev, IIC_INTRWAIT);
- if (error!= 0)
- return (iic2errno(error));
slave = error = 0;
while (uio->uio_resid > 0) {
if (uio->uio_offset >= sc->size)
break;
- len = MIN(sc->rd_sz - (uio->uio_offset & (sc->rd_sz - 1)),
+ len = MIN(MAX_RD_SZ - (uio->uio_offset & (MAX_RD_SZ - 1)),
uio->uio_resid);
switch (sc->type) {
case 8:
@@ -175,7 +262,7 @@ icee_read(struct cdev *dev, struct uio *uio, int ioflag)
}
for (i = 0; i < 2; i++)
msgs[i].slave = slave;
- error = iicbus_transfer(sc->sc_dev, msgs, 2);
+ error = iicbus_transfer_excl(sc->dev, msgs, 2, IIC_INTRWAIT);
if (error) {
error = iic2errno(error);
break;
@@ -184,7 +271,6 @@ icee_read(struct cdev *dev, struct uio *uio, int ioflag)
if (error)
break;
}
- iicbus_release_bus(sc->sc_busdev, sc->sc_dev);
return (error);
}
@@ -213,9 +299,6 @@ icee_write(struct cdev *dev, struct uio *uio, int ioflag)
if (sc->type != 8 && sc->type != 16)
return (EINVAL);
- error = iicbus_request_bus(sc->sc_busdev, sc->sc_dev, IIC_INTRWAIT);
- if (error!= 0)
- return (iic2errno(error));
slave = error = 0;
while (uio->uio_resid > 0) {
if (uio->uio_offset >= sc->size)
@@ -239,7 +322,7 @@ icee_write(struct cdev *dev, struct uio *uio, int ioflag)
error = uiomove(data + sc->type / 8, len, uio);
if (error)
break;
- error = iicbus_transfer(sc->sc_dev, wr, 1);
+ error = iicbus_transfer_excl(sc->dev, wr, 1, IIC_INTRWAIT);
if (error) {
error = iic2errno(error);
break;
@@ -248,14 +331,14 @@ icee_write(struct cdev *dev, struct uio *uio, int ioflag)
waitlimit = 10000;
rd[0].slave = slave;
do {
- error = iicbus_transfer(sc->sc_dev, rd, 1);
+ error = iicbus_transfer_excl(sc->dev, rd, 1,
+ IIC_INTRWAIT);
} while (waitlimit-- > 0 && error != 0);
if (error) {
error = iic2errno(error);
break;
}
}
- iicbus_release_bus(sc->sc_busdev, sc->sc_dev);
return error;
}
diff --git a/sys/dev/iicbus/iicbb.c b/sys/dev/iicbus/iicbb.c
index 977d52a..ed1d7b8 100644
--- a/sys/dev/iicbus/iicbb.c
+++ b/sys/dev/iicbus/iicbb.c
@@ -149,22 +149,9 @@ iicbb_attach(device_t dev)
static int
iicbb_detach(device_t dev)
{
- struct iicbb_softc *sc = (struct iicbb_softc *)device_get_softc(dev);
- device_t child;
-
- /*
- * We need to save child because the detach indirectly causes
- * sc->iicbus to be zeroed. Since we added the device
- * unconditionally in iicbb_attach, we need to make sure we
- * delete it here. See iicbb_child_detached. We need that
- * callback in case newbus detached our children w/o detaching
- * us (say iicbus is a module and unloaded w/o iicbb being
- * unloaded).
- */
- child = sc->iicbus;
+
bus_generic_detach(dev);
- if (child)
- device_delete_child(dev, child);
+ device_delete_children(dev);
return (0);
}
diff --git a/sys/dev/iicbus/iicbus.c b/sys/dev/iicbus/iicbus.c
index dc56760..e377383 100644
--- a/sys/dev/iicbus/iicbus.c
+++ b/sys/dev/iicbus/iicbus.c
@@ -39,7 +39,7 @@ __FBSDID("$FreeBSD$");
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/sysctl.h>
-#include <sys/bus.h>
+#include <sys/bus.h>
#include <dev/iicbus/iiconf.h>
#include <dev/iicbus/iicbus.h>
@@ -60,7 +60,7 @@ iicbus_probe(device_t dev)
}
#if SCAN_IICBUS
-static int
+static int
iic_probe_device(device_t dev, u_char addr)
{
int count;
@@ -126,7 +126,7 @@ iicbus_attach(device_t dev)
bus_generic_attach(dev);
return (0);
}
-
+
static int
iicbus_detach(device_t dev)
{
@@ -134,10 +134,11 @@ iicbus_detach(device_t dev)
iicbus_reset(dev, IIC_FASTEST, 0, NULL);
bus_generic_detach(dev);
+ device_delete_children(dev);
mtx_destroy(&sc->lock);
return (0);
}
-
+
static int
iicbus_print_child(device_t dev, device_t child)
{
diff --git a/sys/dev/iicbus/iicoc.c b/sys/dev/iicbus/iicoc.c
index 45f1692..c55d6fe 100644
--- a/sys/dev/iicbus/iicoc.c
+++ b/sys/dev/iicbus/iicoc.c
@@ -229,6 +229,7 @@ static int
iicoc_detach(device_t dev)
{
bus_generic_detach(dev);
+ device_delete_children(dev);
return (0);
}
diff --git a/sys/dev/iicbus/iiconf.c b/sys/dev/iicbus/iiconf.c
index e28d341..8ac8a47 100644
--- a/sys/dev/iicbus/iiconf.c
+++ b/sys/dev/iicbus/iiconf.c
@@ -395,6 +395,21 @@ iicbus_transfer(device_t bus, struct iic_msg *msgs, uint32_t nmsgs)
return (IICBUS_TRANSFER(device_get_parent(bus), msgs, nmsgs));
}
+int
+iicbus_transfer_excl(device_t dev, struct iic_msg *msgs, uint32_t nmsgs,
+ int how)
+{
+ device_t bus;
+ int error;
+
+ bus = device_get_parent(dev);
+ error = iicbus_request_bus(bus, dev, how);
+ if (error == 0)
+ error = IICBUS_TRANSFER(bus, msgs, nmsgs);
+ iicbus_release_bus(bus, dev);
+ return (error);
+}
+
/*
* Generic version of iicbus_transfer that calls the appropriate
* routines to accomplish this. See note above about acceptable
diff --git a/sys/dev/iicbus/iiconf.h b/sys/dev/iicbus/iiconf.h
index aca0137..12ac0d7 100644
--- a/sys/dev/iicbus/iiconf.h
+++ b/sys/dev/iicbus/iiconf.h
@@ -129,6 +129,8 @@ extern int iicbus_block_read(device_t, u_char, char *, int, int *);
/* vectors of iic operations to pass to bridge */
int iicbus_transfer(device_t bus, struct iic_msg *msgs, uint32_t nmsgs);
+int iicbus_transfer_excl(device_t bus, struct iic_msg *msgs, uint32_t nmsgs,
+ int how);
int iicbus_transfer_gen(device_t bus, struct iic_msg *msgs, uint32_t nmsgs);
#define IICBUS_MODVER 1
diff --git a/sys/dev/iicbus/iicsmb.c b/sys/dev/iicbus/iicsmb.c
index 27f1d2b..d8f35c6 100644
--- a/sys/dev/iicbus/iicsmb.c
+++ b/sys/dev/iicbus/iicsmb.c
@@ -167,11 +167,9 @@ static int
iicsmb_detach(device_t dev)
{
struct iicsmb_softc *sc = (struct iicsmb_softc *)device_get_softc(dev);
-
+
bus_generic_detach(dev);
- if (sc->smbus) {
- device_delete_child(dev, sc->smbus);
- }
+ device_delete_children(dev);
mtx_destroy(&sc->lock);
return (0);
diff --git a/sys/dev/iscsi/iscsi.c b/sys/dev/iscsi/iscsi.c
index 63abafc..b0c9448 100644
--- a/sys/dev/iscsi/iscsi.c
+++ b/sys/dev/iscsi/iscsi.c
@@ -102,6 +102,9 @@ static int fail_on_disconnection = 0;
TUNABLE_INT("kern.iscsi.fail_on_disconnection", &fail_on_disconnection);
SYSCTL_INT(_kern_iscsi, OID_AUTO, fail_on_disconnection, CTLFLAG_RWTUN,
&fail_on_disconnection, 0, "Destroy CAM SIM on connection failure");
+static int fail_on_shutdown = 1;
+SYSCTL_INT(_kern_iscsi, OID_AUTO, fail_on_shutdown, CTLFLAG_RWTUN,
+ &fail_on_shutdown, 0, "Fail disconnected sessions on shutdown");
static MALLOC_DEFINE(M_ISCSI, "iSCSI", "iSCSI initiator");
static uma_zone_t iscsi_outstanding_zone;
@@ -421,8 +424,6 @@ iscsi_maintenance_thread_terminate(struct iscsi_session *is)
sc = is->is_softc;
sx_xlock(&sc->sc_lock);
- TAILQ_REMOVE(&sc->sc_sessions, is, is_next);
- sx_xunlock(&sc->sc_lock);
icl_conn_close(is->is_conn);
callout_drain(&is->is_callout);
@@ -454,6 +455,9 @@ iscsi_maintenance_thread_terminate(struct iscsi_session *is)
#ifdef ICL_KERNEL_PROXY
cv_destroy(&is->is_login_cv);
#endif
+ TAILQ_REMOVE(&sc->sc_sessions, is, is_next);
+ sx_xunlock(&sc->sc_lock);
+
ISCSI_SESSION_DEBUG(is, "terminated");
free(is, M_ISCSI);
@@ -477,12 +481,7 @@ iscsi_maintenance_thread(void *arg)
STAILQ_EMPTY(&is->is_postponed))
cv_wait(&is->is_maintenance_cv, &is->is_lock);
- if (is->is_reconnecting) {
- ISCSI_SESSION_UNLOCK(is);
- iscsi_maintenance_thread_reconnect(is);
- continue;
- }
-
+ /* Terminate supersedes reconnect. */
if (is->is_terminating) {
ISCSI_SESSION_UNLOCK(is);
iscsi_maintenance_thread_terminate(is);
@@ -490,6 +489,12 @@ iscsi_maintenance_thread(void *arg)
return;
}
+ if (is->is_reconnecting) {
+ ISCSI_SESSION_UNLOCK(is);
+ iscsi_maintenance_thread_reconnect(is);
+ continue;
+ }
+
iscsi_session_send_postponed(is);
ISCSI_SESSION_UNLOCK(is);
}
@@ -609,6 +614,11 @@ iscsi_callout(void *context)
return;
out:
+ if (is->is_terminating) {
+ ISCSI_SESSION_UNLOCK(is);
+ return;
+ }
+
ISCSI_SESSION_UNLOCK(is);
if (reconnect_needed)
@@ -2320,30 +2330,62 @@ iscsi_poll(struct cam_sim *sim)
}
static void
-iscsi_shutdown(struct iscsi_softc *sc)
+iscsi_terminate_sessions(struct iscsi_softc *sc)
{
struct iscsi_session *is;
- /*
- * Trying to reconnect during system shutdown would lead to hang.
- */
- fail_on_disconnection = 1;
+ sx_slock(&sc->sc_lock);
+ TAILQ_FOREACH(is, &sc->sc_sessions, is_next)
+ iscsi_session_terminate(is);
+ while(!TAILQ_EMPTY(&sc->sc_sessions)) {
+ ISCSI_DEBUG("waiting for sessions to terminate");
+ cv_wait(&sc->sc_cv, &sc->sc_lock);
+ }
+ ISCSI_DEBUG("all sessions terminated");
+ sx_sunlock(&sc->sc_lock);
+}
+
+static void
+iscsi_shutdown_pre(struct iscsi_softc *sc)
+{
+ struct iscsi_session *is;
+
+ if (!fail_on_shutdown)
+ return;
/*
* If we have any sessions waiting for reconnection, request
* maintenance thread to fail them immediately instead of waiting
* for reconnect timeout.
+ *
+ * This prevents LUNs with mounted filesystems that are supported
+ * by disconnected iSCSI sessions from hanging, however it will
+ * fail all queued BIOs.
*/
+ ISCSI_DEBUG("forcing failing all disconnected sessions due to shutdown");
+
+ fail_on_disconnection = 1;
+
sx_slock(&sc->sc_lock);
TAILQ_FOREACH(is, &sc->sc_sessions, is_next) {
ISCSI_SESSION_LOCK(is);
- if (is->is_waiting_for_iscsid)
+ if (!is->is_connected) {
+ ISCSI_SESSION_DEBUG(is, "force failing disconnected session early");
iscsi_session_reconnect(is);
+ }
ISCSI_SESSION_UNLOCK(is);
}
sx_sunlock(&sc->sc_lock);
}
+static void
+iscsi_shutdown_post(struct iscsi_softc *sc)
+{
+
+ ISCSI_DEBUG("removing all sessions due to shutdown");
+ iscsi_terminate_sessions(sc);
+}
+
static int
iscsi_load(void)
{
@@ -2366,8 +2408,16 @@ iscsi_load(void)
}
sc->sc_cdev->si_drv1 = sc;
- sc->sc_shutdown_eh = EVENTHANDLER_REGISTER(shutdown_pre_sync,
- iscsi_shutdown, sc, SHUTDOWN_PRI_FIRST);
+ sc->sc_shutdown_pre_eh = EVENTHANDLER_REGISTER(shutdown_pre_sync,
+ iscsi_shutdown_pre, sc, SHUTDOWN_PRI_FIRST);
+ /*
+ * shutdown_post_sync needs to run after filesystem shutdown and before
+ * CAM shutdown - otherwise when rebooting with an iSCSI session that is
+ * disconnected but has outstanding requests, dashutdown() will hang on
+ * cam_periph_runccb().
+ */
+ sc->sc_shutdown_post_eh = EVENTHANDLER_REGISTER(shutdown_post_sync,
+ iscsi_shutdown_post, sc, SHUTDOWN_PRI_DEFAULT - 1);
return (0);
}
@@ -2375,7 +2425,6 @@ iscsi_load(void)
static int
iscsi_unload(void)
{
- struct iscsi_session *is, *tmp;
if (sc->sc_cdev != NULL) {
ISCSI_DEBUG("removing device node");
@@ -2383,18 +2432,12 @@ iscsi_unload(void)
ISCSI_DEBUG("device node removed");
}
- if (sc->sc_shutdown_eh != NULL)
- EVENTHANDLER_DEREGISTER(shutdown_pre_sync, sc->sc_shutdown_eh);
+ if (sc->sc_shutdown_pre_eh != NULL)
+ EVENTHANDLER_DEREGISTER(shutdown_pre_sync, sc->sc_shutdown_pre_eh);
+ if (sc->sc_shutdown_post_eh != NULL)
+ EVENTHANDLER_DEREGISTER(shutdown_post_sync, sc->sc_shutdown_post_eh);
- sx_slock(&sc->sc_lock);
- TAILQ_FOREACH_SAFE(is, &sc->sc_sessions, is_next, tmp)
- iscsi_session_terminate(is);
- while(!TAILQ_EMPTY(&sc->sc_sessions)) {
- ISCSI_DEBUG("waiting for sessions to terminate");
- cv_wait(&sc->sc_cv, &sc->sc_lock);
- }
- ISCSI_DEBUG("all sessions terminated");
- sx_sunlock(&sc->sc_lock);
+ iscsi_terminate_sessions(sc);
uma_zdestroy(iscsi_outstanding_zone);
sx_destroy(&sc->sc_lock);
diff --git a/sys/dev/iscsi/iscsi.h b/sys/dev/iscsi/iscsi.h
index 0fe1515..11ecc42 100644
--- a/sys/dev/iscsi/iscsi.h
+++ b/sys/dev/iscsi/iscsi.h
@@ -130,7 +130,8 @@ struct iscsi_softc {
TAILQ_HEAD(, iscsi_session) sc_sessions;
struct cv sc_cv;
unsigned int sc_last_session_id;
- eventhandler_tag sc_shutdown_eh;
+ eventhandler_tag sc_shutdown_pre_eh;
+ eventhandler_tag sc_shutdown_post_eh;
};
#endif /* !ISCSI_H */
diff --git a/sys/dev/nvd/nvd.c b/sys/dev/nvd/nvd.c
index 7be8a18..24ee075 100644
--- a/sys/dev/nvd/nvd.c
+++ b/sys/dev/nvd/nvd.c
@@ -295,7 +295,7 @@ nvd_new_disk(struct nvme_namespace *ns, void *ctrlr_arg)
disk->d_sectorsize = nvme_ns_get_sector_size(ns);
disk->d_mediasize = (off_t)nvme_ns_get_size(ns);
disk->d_delmaxsize = (off_t)nvme_ns_get_size(ns);
- disk->d_stripesize = nvme_ns_get_stripesize(ns);
+ disk->d_stripesize = nvme_ns_get_optimal_sector_size(ns);
if (TAILQ_EMPTY(&disk_head))
disk->d_unit = 0;
diff --git a/sys/dev/nvme/nvme.h b/sys/dev/nvme/nvme.h
index 7e41e77..227a89e 100644
--- a/sys/dev/nvme/nvme.h
+++ b/sys/dev/nvme/nvme.h
@@ -870,6 +870,7 @@ const char * nvme_ns_get_serial_number(struct nvme_namespace *ns);
const char * nvme_ns_get_model_number(struct nvme_namespace *ns);
const struct nvme_namespace_data *
nvme_ns_get_data(struct nvme_namespace *ns);
+uint32_t nvme_ns_get_optimal_sector_size(struct nvme_namespace *ns);
uint32_t nvme_ns_get_stripesize(struct nvme_namespace *ns);
int nvme_ns_bio_process(struct nvme_namespace *ns, struct bio *bp,
diff --git a/sys/dev/nvme/nvme_ns.c b/sys/dev/nvme/nvme_ns.c
index 754d074..4580e66 100644
--- a/sys/dev/nvme/nvme_ns.c
+++ b/sys/dev/nvme/nvme_ns.c
@@ -45,6 +45,8 @@ __FBSDID("$FreeBSD$");
#include "nvme_private.h"
+extern int nvme_max_optimal_sectorsize;
+
static void nvme_bio_child_inbed(struct bio *parent, int bio_error);
static void nvme_bio_child_done(void *arg,
const struct nvme_completion *cpl);
@@ -217,6 +219,22 @@ nvme_ns_get_stripesize(struct nvme_namespace *ns)
return (ns->stripesize);
}
+uint32_t
+nvme_ns_get_optimal_sector_size(struct nvme_namespace *ns)
+{
+ uint32_t stripesize;
+
+ stripesize = nvme_ns_get_stripesize(ns);
+
+ if (stripesize == 0)
+ return nvme_ns_get_sector_size(ns);
+
+ if (nvme_max_optimal_sectorsize == 0)
+ return (stripesize);
+
+ return (MIN(stripesize, nvme_max_optimal_sectorsize));
+}
+
static void
nvme_ns_bio_done(void *arg, const struct nvme_completion *status)
{
diff --git a/sys/dev/nvme/nvme_sysctl.c b/sys/dev/nvme/nvme_sysctl.c
index 44b0ab7..08cd15e 100644
--- a/sys/dev/nvme/nvme_sysctl.c
+++ b/sys/dev/nvme/nvme_sysctl.c
@@ -33,6 +33,22 @@ __FBSDID("$FreeBSD$");
#include "nvme_private.h"
+SYSCTL_NODE(_kern, OID_AUTO, nvme, CTLFLAG_RD, 0, "NVM Express");
+/*
+ * Intel NVMe controllers have a slow path for I/Os that span a 128KB
+ * stripe boundary but ZFS limits ashift, which is derived from
+ * d_stripesize, to 13 (8KB) so we limit the stripesize reported to
+ * geom(8) to 4KB by default.
+ *
+ * This may result in a small number of additional I/Os to require
+ * splitting in nvme(4), however the NVMe I/O path is very efficient
+ * so these additional I/Os will cause very minimal (if any) difference
+ * in performance or CPU utilisation.
+ */
+int nvme_max_optimal_sectorsize = 1<<12;
+SYSCTL_INT(_kern_nvme, OID_AUTO, max_optimal_sectorsize, CTLFLAG_RWTUN,
+ &nvme_max_optimal_sectorsize, 0, "The maximum optimal sectorsize reported");
+
/*
* CTLTYPE_S64 and sysctl_handle_64 were added in r217616. Define these
* explicitly here for older kernels that don't include the r217616
diff --git a/sys/dev/ofw/ofw_iicbus.c b/sys/dev/ofw/ofw_iicbus.c
index f6d1be5..98fc060 100644
--- a/sys/dev/ofw/ofw_iicbus.c
+++ b/sys/dev/ofw/ofw_iicbus.c
@@ -147,7 +147,11 @@ ofw_iicbus_attach(device_t dev)
M_NOWAIT | M_ZERO);
if (dinfo == NULL)
continue;
- dinfo->opd_dinfo.addr = paddr;
+ /*
+ * OFW uses 7-bit I2C address format (see ePAPR),
+ * but system expect 8-bit.
+ */
+ dinfo->opd_dinfo.addr = paddr << 1;
if (ofw_bus_gen_setup_devinfo(&dinfo->opd_obdinfo, child) !=
0) {
free(dinfo, M_DEVBUF);
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index e08237b..cef2db4 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -182,6 +182,8 @@ static device_method_t pci_methods[] = {
DEVMETHOD(pci_release_msi, pci_release_msi_method),
DEVMETHOD(pci_msi_count, pci_msi_count_method),
DEVMETHOD(pci_msix_count, pci_msix_count_method),
+ DEVMETHOD(pci_msix_pba_bar, pci_msix_pba_bar_method),
+ DEVMETHOD(pci_msix_table_bar, pci_msix_table_bar_method),
DEVMETHOD(pci_get_rid, pci_get_rid_method),
DEVMETHOD(pci_child_added, pci_child_added_method),
@@ -1827,6 +1829,28 @@ pci_msix_count_method(device_t dev, device_t child)
return (0);
}
+int
+pci_msix_pba_bar_method(device_t dev, device_t child)
+{
+ struct pci_devinfo *dinfo = device_get_ivars(child);
+ struct pcicfg_msix *msix = &dinfo->cfg.msix;
+
+ if (pci_do_msix && msix->msix_location != 0)
+ return (msix->msix_pba_bar);
+ return (-1);
+}
+
+int
+pci_msix_table_bar_method(device_t dev, device_t child)
+{
+ struct pci_devinfo *dinfo = device_get_ivars(child);
+ struct pcicfg_msix *msix = &dinfo->cfg.msix;
+
+ if (pci_do_msix && msix->msix_location != 0)
+ return (msix->msix_table_bar);
+ return (-1);
+}
+
/*
* HyperTransport MSI mapping control
*/
diff --git a/sys/dev/pci/pci_if.m b/sys/dev/pci/pci_if.m
index 227d362..a44a641 100644
--- a/sys/dev/pci/pci_if.m
+++ b/sys/dev/pci/pci_if.m
@@ -36,6 +36,12 @@ CODE {
{
return (0);
}
+
+ static int
+ null_msix_bar(device_t dev, device_t child)
+ {
+ return (-1);
+ }
};
@@ -180,6 +186,16 @@ METHOD int msix_count {
device_t child;
} DEFAULT null_msi_count;
+METHOD int msix_pba_bar {
+ device_t dev;
+ device_t child;
+} DEFAULT null_msix_bar;
+
+METHOD int msix_table_bar {
+ device_t dev;
+ device_t child;
+} DEFAULT null_msix_bar;
+
METHOD uint16_t get_rid {
device_t dev;
device_t child;
diff --git a/sys/dev/pci/pci_private.h b/sys/dev/pci/pci_private.h
index 5a90ce9..e446dc5 100644
--- a/sys/dev/pci/pci_private.h
+++ b/sys/dev/pci/pci_private.h
@@ -100,6 +100,8 @@ int pci_remap_msix_method(device_t dev, device_t child,
int pci_release_msi_method(device_t dev, device_t child);
int pci_msi_count_method(device_t dev, device_t child);
int pci_msix_count_method(device_t dev, device_t child);
+int pci_msix_pba_bar_method(device_t dev, device_t child);
+int pci_msix_table_bar_method(device_t dev, device_t child);
struct resource *pci_alloc_resource(device_t dev, device_t child,
int type, int *rid, u_long start, u_long end, u_long count,
u_int flags);
diff --git a/sys/dev/pci/pcireg.h b/sys/dev/pci/pcireg.h
index 73ce5e9..5453a53 100644
--- a/sys/dev/pci/pcireg.h
+++ b/sys/dev/pci/pcireg.h
@@ -260,6 +260,11 @@
#define PCIR_BIOS_1 0x38
#define PCIR_BRIDGECTL_1 0x3e
+#define PCI_PPBMEMBASE(h,l) ((((uint64_t)(h) << 32) + ((l)<<16)) & ~0xfffff)
+#define PCI_PPBMEMLIMIT(h,l) ((((uint64_t)(h) << 32) + ((l)<<16)) | 0xfffff)
+#define PCI_PPBIOBASE(h,l) ((((h)<<16) + ((l)<<8)) & ~0xfff)
+#define PCI_PPBIOLIMIT(h,l) ((((h)<<16) + ((l)<<8)) | 0xfff)
+
/* config registers for header type 2 (CardBus) devices */
#define PCIR_MAX_BAR_2 0
@@ -279,6 +284,9 @@
#define PCIR_IOLIMIT0_2 0x30
#define PCIR_IOBASE1_2 0x34
#define PCIR_IOLIMIT1_2 0x38
+#define PCIM_CBBIO_16 0x0
+#define PCIM_CBBIO_32 0x1
+#define PCIM_CBBIO_MASK 0x3
#define PCIR_BRIDGECTL_2 0x3e
@@ -287,6 +295,11 @@
#define PCIR_PCCARDIF_2 0x44
+#define PCI_CBBMEMBASE(l) ((l) & ~0xfffff)
+#define PCI_CBBMEMLIMIT(l) ((l) | 0xfffff)
+#define PCI_CBBIOBASE(l) ((l) & ~0x3)
+#define PCI_CBBIOLIMIT(l) ((l) | 0x3)
+
/* PCI device class, subclass and programming interface definitions */
#define PCIC_OLD 0x00
@@ -474,6 +487,17 @@
#define PCIB_BCR_DISCARD_TIMER_STATUS 0x0400
#define PCIB_BCR_DISCARD_TIMER_SERREN 0x0800
+#define CBB_BCR_PERR_ENABLE 0x0001
+#define CBB_BCR_SERR_ENABLE 0x0002
+#define CBB_BCR_ISA_ENABLE 0x0004
+#define CBB_BCR_VGA_ENABLE 0x0008
+#define CBB_BCR_MASTER_ABORT_MODE 0x0020
+#define CBB_BCR_CARDBUS_RESET 0x0040
+#define CBB_BCR_IREQ_INT_ENABLE 0x0080
+#define CBB_BCR_PREFETCH_0_ENABLE 0x0100
+#define CBB_BCR_PREFETCH_1_ENABLE 0x0200
+#define CBB_BCR_WRITE_POSTING_ENABLE 0x0400
+
/* PCI power manangement */
#define PCIR_POWER_CAP 0x2
#define PCIM_PCAP_SPEC 0x0007
diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h
index 2bb26bd..14132bf 100644
--- a/sys/dev/pci/pcivar.h
+++ b/sys/dev/pci/pcivar.h
@@ -190,11 +190,6 @@ typedef struct pcicfg {
/* additional type 1 device config header information (PCI to PCI bridge) */
-#define PCI_PPBMEMBASE(h,l) ((((pci_addr_t)(h) << 32) + ((l)<<16)) & ~0xfffff)
-#define PCI_PPBMEMLIMIT(h,l) ((((pci_addr_t)(h) << 32) + ((l)<<16)) | 0xfffff)
-#define PCI_PPBIOBASE(h,l) ((((h)<<16) + ((l)<<8)) & ~0xfff)
-#define PCI_PPBIOLIMIT(h,l) ((((h)<<16) + ((l)<<8)) | 0xfff)
-
typedef struct {
pci_addr_t pmembase; /* base address of prefetchable memory */
pci_addr_t pmemlimit; /* topmost address of prefetchable memory */
@@ -500,6 +495,18 @@ pci_msix_count(device_t dev)
return (PCI_MSIX_COUNT(device_get_parent(dev), dev));
}
+static __inline int
+pci_msix_pba_bar(device_t dev)
+{
+ return (PCI_MSIX_PBA_BAR(device_get_parent(dev), dev));
+}
+
+static __inline int
+pci_msix_table_bar(device_t dev)
+{
+ return (PCI_MSIX_TABLE_BAR(device_get_parent(dev), dev));
+}
+
static __inline uint16_t
pci_get_rid(device_t dev)
{
diff --git a/sys/dev/rt/if_rt.c b/sys/dev/rt/if_rt.c
index ea252d1..814698c 100644
--- a/sys/dev/rt/if_rt.c
+++ b/sys/dev/rt/if_rt.c
@@ -176,20 +176,6 @@ macaddr_atoi(const char *str, uint8_t *mac)
}
#ifdef USE_GENERATED_MAC_ADDRESS
-static char *
-kernenv_next(char *cp)
-{
-
- if (cp != NULL) {
- while (*cp != 0)
- cp++;
- cp++;
- if (*cp == 0)
- cp = NULL;
- }
- return (cp);
-}
-
/*
* generate_mac(uin8_t *mac)
* This is MAC address generator for cases when real device MAC address
@@ -208,14 +194,8 @@ generate_mac(uint8_t *mac)
uint32_t crc = 0xffffffff;
/* Generate CRC32 on kenv */
- if (dynamic_kenv) {
- for (cp = kenvp[0]; cp != NULL; cp = kenvp[++i]) {
- crc = calculate_crc32c(crc, cp, strlen(cp) + 1);
- }
- } else {
- for (cp = kern_envp; cp != NULL; cp = kernenv_next(cp)) {
- crc = calculate_crc32c(crc, cp, strlen(cp) + 1);
- }
+ for (cp = kenvp[0]; cp != NULL; cp = kenvp[++i]) {
+ crc = calculate_crc32c(crc, cp, strlen(cp) + 1);
}
crc = ~crc;
diff --git a/sys/dev/sfxge/common/ef10_impl.h b/sys/dev/sfxge/common/ef10_impl.h
index 9b9f0aa..0c687ae 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/ef10_tlv_layout.h b/sys/dev/sfxge/common/ef10_tlv_layout.h
index 4063165..80364ce 100644
--- a/sys/dev/sfxge/common/ef10_tlv_layout.h
+++ b/sys/dev/sfxge/common/ef10_tlv_layout.h
@@ -113,7 +113,11 @@ struct tlv_partition_header {
uint32_t tag;
uint32_t length;
uint16_t type_id;
- uint16_t reserved;
+/* 0 indicates the default segment (always located at offset 0), while other values
+ * are for RFID-selectable presets that should immediately follow the default segment.
+ * The default segment may also have preset > 0, which means that it is a preset
+ * selected through an RFID command and copied by FW to the location at offset 0. */
+ uint16_t preset;
uint32_t generation;
uint32_t total_length;
};
@@ -376,7 +380,7 @@ struct tlv_tmp_gubbins {
int8_t with_rmon; /* 0 -> off, 1 -> on, -1 -> leave alone */
/* Consumed by clocks_hunt.c */
int8_t clk_mode; /* 0 -> off, 1 -> on, -1 -> leave alone */
- /* Consumed by sram.c */
+ /* No longer used, superseded by TLV_TAG_DESCRIPTOR_CACHE_CONFIG. */
int8_t rx_dc_size; /* -1 -> leave alone */
int8_t tx_dc_size;
int16_t num_q_allocs;
@@ -690,7 +694,6 @@ struct tlv_mcast_filter_chaining {
#define TLV_MCAST_FILTER_CHAINING_ENABLED (1)
};
-
/* Pacer rate limit per PF */
#define TLV_TAG_RATE_LIMIT(pf) (0x101b0000 + (pf))
@@ -700,7 +703,6 @@ struct tlv_rate_limit {
uint32_t rate_mbps;
};
-
/* OCSD Enable/Disable
*
* This setting allows OCSD to be disabled. This is a requirement for HP
diff --git a/sys/dev/sfxge/common/efsys.h b/sys/dev/sfxge/common/efsys.h
index 7bc1fe0..14238ad 100644
--- a/sys/dev/sfxge/common/efsys.h
+++ b/sys/dev/sfxge/common/efsys.h
@@ -211,6 +211,8 @@ sfxge_map_mbuf_fast(bus_dma_tag_t tag, bus_dmamap_t map,
#define __out_ecount_opt(_n)
#define __out_bcount(_n)
#define __out_bcount_opt(_n)
+#define __out_bcount_part(_n, _l)
+#define __out_bcount_part_opt(_n, _l)
#define __deref_out
@@ -293,6 +295,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 0483c9a..ce70546 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,14 +1153,18 @@ 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;
boolean_t enc_rx_disable_scatter_supported;
boolean_t enc_allow_set_mac_with_installed_filters;
+ boolean_t enc_enhanced_set_mac_supported;
/* 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 +1320,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 +2008,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 +2096,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 +2313,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 199fab0..d6b7cf4 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 5397ffe..5495b15 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
@@ -96,6 +97,7 @@ typedef enum efx_mac_type_e {
EFX_MAC_FALCON_XMAC,
EFX_MAC_SIENA,
EFX_MAC_HUNTINGTON,
+ EFX_MAC_MEDFORD,
EFX_MAC_NTYPES
} efx_mac_type_t;
@@ -146,6 +148,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
@@ -189,6 +194,7 @@ typedef struct efx_mac_ops_s {
efx_rc_t (*emo_poll)(efx_nic_t *, efx_link_mode_t *);
efx_rc_t (*emo_up)(efx_nic_t *, boolean_t *);
efx_rc_t (*emo_addr_set)(efx_nic_t *);
+ efx_rc_t (*emo_pdu_set)(efx_nic_t *);
efx_rc_t (*emo_reconfigure)(efx_nic_t *);
efx_rc_t (*emo_multicast_list_set)(efx_nic_t *);
efx_rc_t (*emo_filter_default_rxq_set)(efx_nic_t *,
@@ -358,6 +364,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 +463,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,21 +485,21 @@ 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,
+ 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_rc_t (*envo_partn_read)(efx_nic_t *, uint32_t,
unsigned int, caddr_t, size_t);
- efx_rc_t (*envo_erase)(efx_nic_t *, efx_nvram_type_t);
- efx_rc_t (*envo_write_chunk)(efx_nic_t *, efx_nvram_type_t,
+ efx_rc_t (*envo_partn_erase)(efx_nic_t *, uint32_t,
+ unsigned int, size_t);
+ efx_rc_t (*envo_partn_write)(efx_nic_t *, uint32_t,
unsigned int, caddr_t, size_t);
- void (*envo_rw_finish)(efx_nic_t *, efx_nvram_type_t);
- efx_rc_t (*envo_set_version)(efx_nic_t *, efx_nvram_type_t,
+ void (*envo_partn_rw_finish)(efx_nic_t *, uint32_t);
+ efx_rc_t (*envo_partn_get_version)(efx_nic_t *, uint32_t,
+ uint32_t *, uint16_t *);
+ efx_rc_t (*envo_partn_set_version)(efx_nic_t *, uint32_t,
uint16_t *);
-
- efx_rc_t (*envo_type_to_partn)(efx_nic_t *, efx_nvram_type_t,
- uint32_t *);
} efx_nvram_ops_t;
#endif /* EFSYS_OPT_NVRAM */
@@ -553,7 +559,8 @@ efx_mcdi_nvram_read(
__in uint32_t partn,
__in uint32_t offset,
__out_bcount(size) caddr_t data,
- __in size_t size);
+ __in size_t size,
+ __in uint32_t mode);
__checkReturn efx_rc_t
efx_mcdi_nvram_erase(
@@ -587,6 +594,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 +655,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 0000000..33c8aba
--- /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_mac.c b/sys/dev/sfxge/common/efx_mac.c
index c8794a6..4868c4b 100644
--- a/sys/dev/sfxge/common/efx_mac.c
+++ b/sys/dev/sfxge/common/efx_mac.c
@@ -56,6 +56,7 @@ static efx_mac_ops_t __efx_falcon_gmac_ops = {
falcon_mac_poll, /* emo_poll */
falcon_mac_up, /* emo_up */
falcon_gmac_reconfigure, /* emo_addr_set */
+ falcon_gmac_reconfigure, /* emo_pdu_set */
falcon_gmac_reconfigure, /* emo_reconfigure */
falconsiena_mac_multicast_list_set, /* emo_multicast_list_set */
NULL, /* emo_filter_set_default_rxq */
@@ -77,6 +78,7 @@ static efx_mac_ops_t __efx_falcon_xmac_ops = {
falcon_mac_poll, /* emo_poll */
falcon_mac_up, /* emo_up */
falcon_xmac_reconfigure, /* emo_addr_set */
+ falcon_xmac_reconfigure, /* emo_pdu_set */
falcon_xmac_reconfigure, /* emo_reconfigure */
falconsiena_mac_multicast_list_set, /* emo_multicast_list_set */
NULL, /* emo_filter_set_default_rxq */
@@ -98,6 +100,7 @@ static efx_mac_ops_t __efx_siena_mac_ops = {
siena_mac_poll, /* emo_poll */
siena_mac_up, /* emo_up */
siena_mac_reconfigure, /* emo_addr_set */
+ siena_mac_reconfigure, /* emo_pdu_set */
siena_mac_reconfigure, /* emo_reconfigure */
falconsiena_mac_multicast_list_set, /* emo_multicast_list_set */
NULL, /* emo_filter_set_default_rxq */
@@ -113,27 +116,28 @@ static efx_mac_ops_t __efx_siena_mac_ops = {
};
#endif /* EFSYS_OPT_SIENA */
-#if EFSYS_OPT_HUNTINGTON
-static efx_mac_ops_t __efx_hunt_mac_ops = {
+#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
+static efx_mac_ops_t __efx_ef10_mac_ops = {
NULL, /* emo_reset */
- hunt_mac_poll, /* emo_poll */
- hunt_mac_up, /* emo_up */
- hunt_mac_addr_set, /* emo_addr_set */
- hunt_mac_reconfigure, /* emo_reconfigure */
- hunt_mac_multicast_list_set, /* emo_multicast_list_set */
- hunt_mac_filter_default_rxq_set, /* emo_filter_default_rxq_set */
- hunt_mac_filter_default_rxq_clear,
+ ef10_mac_poll, /* emo_poll */
+ ef10_mac_up, /* emo_up */
+ ef10_mac_addr_set, /* emo_addr_set */
+ ef10_mac_pdu_set, /* emo_pdu_set */
+ ef10_mac_reconfigure, /* emo_reconfigure */
+ ef10_mac_multicast_list_set, /* emo_multicast_list_set */
+ ef10_mac_filter_default_rxq_set, /* emo_filter_default_rxq_set */
+ ef10_mac_filter_default_rxq_clear,
/* emo_filter_default_rxq_clear */
#if EFSYS_OPT_LOOPBACK
- hunt_mac_loopback_set, /* emo_loopback_set */
+ ef10_mac_loopback_set, /* emo_loopback_set */
#endif /* EFSYS_OPT_LOOPBACK */
#if EFSYS_OPT_MAC_STATS
efx_mcdi_mac_stats_upload, /* emo_stats_upload */
efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */
- hunt_mac_stats_update /* emo_stats_update */
+ ef10_mac_stats_update /* emo_stats_update */
#endif /* EFSYS_OPT_MAC_STATS */
};
-#endif /* EFSYS_OPT_HUNTINGTON */
+#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
static efx_mac_ops_t *__efx_mac_ops[] = {
/* [EFX_MAC_INVALID] */
@@ -158,7 +162,13 @@ static efx_mac_ops_t *__efx_mac_ops[] = {
#endif
/* [EFX_MAC_HUNTINGTON] */
#if EFSYS_OPT_HUNTINGTON
- &__efx_hunt_mac_ops,
+ &__efx_ef10_mac_ops,
+#else
+ NULL,
+#endif
+ /* [EFX_MAC_MEDFORD] */
+#if EFSYS_OPT_MEDFORD
+ &__efx_ef10_mac_ops,
#else
NULL,
#endif
@@ -190,7 +200,7 @@ efx_mac_pdu_set(
old_pdu = epp->ep_mac_pdu;
epp->ep_mac_pdu = (uint32_t)pdu;
- if ((rc = emop->emo_reconfigure(enp)) != 0)
+ if ((rc = emop->emo_pdu_set(enp)) != 0)
goto fail3;
return (0);
@@ -781,6 +791,13 @@ efx_mac_select(
efx_mac_ops_t *emop;
int rc = EINVAL;
+#if EFSYS_OPT_SIENA
+ if (enp->en_family == EFX_FAMILY_SIENA) {
+ type = EFX_MAC_SIENA;
+ goto chosen;
+ }
+#endif
+
#if EFSYS_OPT_HUNTINGTON
if (enp->en_family == EFX_FAMILY_HUNTINGTON) {
type = EFX_MAC_HUNTINGTON;
@@ -788,9 +805,9 @@ efx_mac_select(
}
#endif
-#if EFSYS_OPT_SIENA
- if (enp->en_family == EFX_FAMILY_SIENA) {
- type = EFX_MAC_SIENA;
+#if EFSYS_OPT_MEDFORD
+ if (enp->en_family == EFX_FAMILY_MEDFORD) {
+ type = EFX_MAC_MEDFORD;
goto chosen;
}
#endif
diff --git a/sys/dev/sfxge/common/efx_mcdi.c b/sys/dev/sfxge/common/efx_mcdi.c
index 07224c7..9f7a9ff 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 36b3d8d..dd1d76e 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 07acc56..dd28ece 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 7597636..272e6c7 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 */
+ falcon_nvram_partn_read, /* envo_partn_read */
+ falcon_nvram_partn_erase, /* envo_partn_erase */
+ falcon_nvram_partn_write, /* envo_partn_write */
+ falcon_nvram_partn_rw_finish, /* envo_partn_rw_finish */
+ falcon_nvram_partn_get_version, /* envo_partn_get_version */
+ falcon_nvram_partn_set_version, /* envo_partn_set_version */
};
#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 */
+ siena_nvram_partn_read, /* envo_partn_read */
+ siena_nvram_partn_erase, /* envo_partn_erase */
+ siena_nvram_partn_write, /* envo_partn_write */
+ siena_nvram_partn_rw_finish, /* envo_partn_rw_finish */
+ siena_nvram_partn_get_version, /* envo_partn_get_version */
+ siena_nvram_partn_set_version, /* envo_partn_set_version */
};
#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 */
+ ef10_nvram_partn_read, /* envo_partn_read */
+ ef10_nvram_partn_erase, /* envo_partn_erase */
+ ef10_nvram_partn_write, /* envo_partn_write */
+ ef10_nvram_partn_rw_finish, /* envo_partn_rw_finish */
+ ef10_nvram_partn_get_version, /* envo_partn_get_version */
+ ef10_nvram_partn_set_version, /* envo_partn_set_version */
};
#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);
}
@@ -204,6 +211,7 @@ efx_nvram_get_version(
__out_ecount(4) uint16_t version[4])
{
efx_nvram_ops_t *envop = enp->en_envop;
+ uint32_t partn;
efx_rc_t rc;
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
@@ -212,11 +220,17 @@ efx_nvram_get_version(
EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
- if ((rc = envop->envo_get_version(enp, type, subtypep, version)) != 0)
+ if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
goto fail1;
+ if ((rc = envop->envo_partn_get_version(enp, partn,
+ subtypep, version)) != 0)
+ goto fail2;
+
return (0);
+fail2:
+ EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
@@ -230,6 +244,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 +255,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);
@@ -262,6 +282,7 @@ efx_nvram_read_chunk(
__in size_t size)
{
efx_nvram_ops_t *envop = enp->en_envop;
+ uint32_t partn;
efx_rc_t rc;
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
@@ -272,11 +293,16 @@ efx_nvram_read_chunk(
EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
- if ((rc = envop->envo_read_chunk(enp, type, offset, data, size)) != 0)
+ if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
goto fail1;
+ if ((rc = envop->envo_partn_read(enp, partn, offset, data, size)) != 0)
+ goto fail2;
+
return (0);
+fail2:
+ EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
@@ -289,6 +315,9 @@ efx_nvram_erase(
__in efx_nvram_type_t type)
{
efx_nvram_ops_t *envop = enp->en_envop;
+ unsigned int offset = 0;
+ size_t size = 0;
+ uint32_t partn;
efx_rc_t rc;
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
@@ -299,11 +328,21 @@ efx_nvram_erase(
EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
- if ((rc = envop->envo_erase(enp, type)) != 0)
+ if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
goto fail1;
+ if ((rc = envop->envo_partn_size(enp, partn, &size)) != 0)
+ goto fail2;
+
+ if ((rc = envop->envo_partn_erase(enp, partn, offset, size)) != 0)
+ goto fail3;
+
return (0);
+fail3:
+ EFSYS_PROBE(fail3);
+fail2:
+ EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
@@ -319,6 +358,7 @@ efx_nvram_write_chunk(
__in size_t size)
{
efx_nvram_ops_t *envop = enp->en_envop;
+ uint32_t partn;
efx_rc_t rc;
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
@@ -329,11 +369,16 @@ efx_nvram_write_chunk(
EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
- if ((rc = envop->envo_write_chunk(enp, type, offset, data, size)) != 0)
+ if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
goto fail1;
+ if ((rc = envop->envo_partn_write(enp, partn, offset, data, size)) != 0)
+ goto fail2;
+
return (0);
+fail2:
+ EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
@@ -346,6 +391,7 @@ efx_nvram_rw_finish(
__in efx_nvram_type_t type)
{
efx_nvram_ops_t *envop = enp->en_envop;
+ uint32_t partn;
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
@@ -355,7 +401,8 @@ efx_nvram_rw_finish(
EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
- envop->envo_rw_finish(enp, type);
+ if (envop->envo_type_to_partn(enp, type, &partn) == 0)
+ envop->envo_partn_rw_finish(enp, partn);
enp->en_nvram_locked = EFX_NVRAM_INVALID;
}
@@ -367,6 +414,7 @@ efx_nvram_set_version(
__in_ecount(4) uint16_t version[4])
{
efx_nvram_ops_t *envop = enp->en_envop;
+ uint32_t partn;
efx_rc_t rc;
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
@@ -382,11 +430,16 @@ efx_nvram_set_version(
*/
EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
- if ((rc = envop->envo_set_version(enp, type, version)) != 0)
+ if ((rc = envop->envo_type_to_partn(enp, type, &partn)) != 0)
goto fail1;
+ if ((rc = envop->envo_partn_set_version(enp, partn, version)) != 0)
+ goto fail2;
+
return (0);
+fail2:
+ EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
@@ -668,10 +721,11 @@ efx_mcdi_nvram_read(
__in uint32_t partn,
__in uint32_t offset,
__out_bcount(size) caddr_t data,
- __in size_t size)
+ __in size_t size,
+ __in uint32_t mode)
{
efx_mcdi_req_t req;
- uint8_t payload[MAX(MC_CMD_NVRAM_READ_IN_LEN,
+ uint8_t payload[MAX(MC_CMD_NVRAM_READ_IN_V2_LEN,
MC_CMD_NVRAM_READ_OUT_LENMAX)];
efx_rc_t rc;
@@ -683,13 +737,14 @@ efx_mcdi_nvram_read(
(void) memset(payload, 0, sizeof (payload));
req.emr_cmd = MC_CMD_NVRAM_READ;
req.emr_in_buf = payload;
- req.emr_in_length = MC_CMD_NVRAM_READ_IN_LEN;
+ req.emr_in_length = MC_CMD_NVRAM_READ_IN_V2_LEN;
req.emr_out_buf = payload;
req.emr_out_length = MC_CMD_NVRAM_READ_OUT_LENMAX;
- MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_TYPE, partn);
- MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_OFFSET, offset);
- MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_LENGTH, size);
+ MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_TYPE, partn);
+ MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_OFFSET, offset);
+ MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_LENGTH, size);
+ MCDI_IN_SET_DWORD(req, NVRAM_READ_IN_V2_MODE, mode);
efx_mcdi_execute(enp, &req);
diff --git a/sys/dev/sfxge/common/efx_phy.c b/sys/dev/sfxge/common/efx_phy.c
index dd966be..51e1ccb 100644
--- a/sys/dev/sfxge/common/efx_phy.c
+++ b/sys/dev/sfxge/common/efx_phy.c
@@ -265,33 +265,34 @@ static efx_phy_ops_t __efx_phy_siena_ops = {
};
#endif /* EFSYS_OPT_SIENA */
-#if EFSYS_OPT_HUNTINGTON
-static efx_phy_ops_t __efx_phy_hunt_ops = {
- hunt_phy_power, /* epo_power */
+#if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
+static efx_phy_ops_t __efx_phy_ef10_ops = {
+ ef10_phy_power, /* epo_power */
NULL, /* epo_reset */
- hunt_phy_reconfigure, /* epo_reconfigure */
- hunt_phy_verify, /* epo_verify */
+ ef10_phy_reconfigure, /* epo_reconfigure */
+ ef10_phy_verify, /* epo_verify */
NULL, /* epo_uplink_check */
NULL, /* epo_downlink_check */
- hunt_phy_oui_get, /* epo_oui_get */
+ ef10_phy_oui_get, /* epo_oui_get */
#if EFSYS_OPT_PHY_STATS
- hunt_phy_stats_update, /* epo_stats_update */
+ ef10_phy_stats_update, /* epo_stats_update */
#endif /* EFSYS_OPT_PHY_STATS */
#if EFSYS_OPT_PHY_PROPS
#if EFSYS_OPT_NAMES
- hunt_phy_prop_name, /* epo_prop_name */
+ ef10_phy_prop_name, /* epo_prop_name */
#endif
- hunt_phy_prop_get, /* epo_prop_get */
- hunt_phy_prop_set, /* epo_prop_set */
+ ef10_phy_prop_get, /* epo_prop_get */
+ ef10_phy_prop_set, /* epo_prop_set */
#endif /* EFSYS_OPT_PHY_PROPS */
#if EFSYS_OPT_BIST
+ /* FIXME: Are these BIST methods appropriate for Medford? */
hunt_bist_enable_offline, /* epo_bist_enable_offline */
hunt_bist_start, /* epo_bist_start */
hunt_bist_poll, /* epo_bist_poll */
hunt_bist_stop, /* epo_bist_stop */
#endif /* EFSYS_OPT_BIST */
};
-#endif /* EFSYS_OPT_HUNTINGTON */
+#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
__checkReturn efx_rc_t
efx_phy_probe(
@@ -356,9 +357,14 @@ efx_phy_probe(
#endif /* EFSYS_OPT_SIENA */
#if EFSYS_OPT_HUNTINGTON
case EFX_FAMILY_HUNTINGTON:
- epop = (efx_phy_ops_t *)&__efx_phy_hunt_ops;
+ epop = (efx_phy_ops_t *)&__efx_phy_ef10_ops;
break;
#endif /* EFSYS_OPT_HUNTINGTON */
+#if EFSYS_OPT_MEDFORD
+ case EFX_FAMILY_MEDFORD:
+ epop = (efx_phy_ops_t *)&__efx_phy_ef10_ops;
+ break;
+#endif /* EFSYS_OPT_MEDFORD */
default:
rc = ENOTSUP;
goto fail1;
diff --git a/sys/dev/sfxge/common/efx_regs_ef10.h b/sys/dev/sfxge/common/efx_regs_ef10.h
index bd7619a..43745e5 100644
--- a/sys/dev/sfxge/common/efx_regs_ef10.h
+++ b/sys/dev/sfxge/common/efx_regs_ef10.h
@@ -50,7 +50,7 @@ extern "C" {
*/
#define ER_DZ_BIU_HW_REV_ID_REG_OFST 0x00000000
-/* hunta0=pcie_pf_bar2 */
+/* hunta0,medforda0=pcie_pf_bar2 */
#define ER_DZ_BIU_HW_REV_ID_REG_RESET 0xeb14face
@@ -64,7 +64,7 @@ extern "C" {
*/
#define ER_DZ_BIU_MC_SFT_STATUS_REG_OFST 0x00000010
-/* hunta0=pcie_pf_bar2 */
+/* hunta0,medforda0=pcie_pf_bar2 */
#define ER_DZ_BIU_MC_SFT_STATUS_REG_STEP 4
#define ER_DZ_BIU_MC_SFT_STATUS_REG_ROWS 8
#define ER_DZ_BIU_MC_SFT_STATUS_REG_RESET 0x1111face
@@ -80,7 +80,7 @@ extern "C" {
*/
#define ER_DZ_BIU_INT_ISR_REG_OFST 0x00000090
-/* hunta0=pcie_pf_bar2 */
+/* hunta0,medforda0=pcie_pf_bar2 */
#define ER_DZ_BIU_INT_ISR_REG_RESET 0x0
@@ -94,7 +94,7 @@ extern "C" {
*/
#define ER_DZ_MC_DB_LWRD_REG_OFST 0x00000200
-/* hunta0=pcie_pf_bar2 */
+/* hunta0,medforda0=pcie_pf_bar2 */
#define ER_DZ_MC_DB_LWRD_REG_RESET 0x0
@@ -108,7 +108,7 @@ extern "C" {
*/
#define ER_DZ_MC_DB_HWRD_REG_OFST 0x00000204
-/* hunta0=pcie_pf_bar2 */
+/* hunta0,medforda0=pcie_pf_bar2 */
#define ER_DZ_MC_DB_HWRD_REG_RESET 0x0
@@ -122,7 +122,7 @@ extern "C" {
*/
#define ER_DZ_EVQ_RPTR_REG_OFST 0x00000400
-/* hunta0=pcie_pf_bar2 */
+/* hunta0,medforda0=pcie_pf_bar2 */
#define ER_DZ_EVQ_RPTR_REG_STEP 8192
#define ER_DZ_EVQ_RPTR_REG_ROWS 2048
#define ER_DZ_EVQ_RPTR_REG_RESET 0x0
@@ -140,7 +140,7 @@ extern "C" {
*/
#define ER_DZ_EVQ_TMR_REG_OFST 0x00000420
-/* hunta0=pcie_pf_bar2 */
+/* hunta0,medforda0=pcie_pf_bar2 */
#define ER_DZ_EVQ_TMR_REG_STEP 8192
#define ER_DZ_EVQ_TMR_REG_ROWS 2048
#define ER_DZ_EVQ_TMR_REG_RESET 0x0
@@ -158,7 +158,7 @@ extern "C" {
*/
#define ER_DZ_RX_DESC_UPD_REG_OFST 0x00000830
-/* hunta0=pcie_pf_bar2 */
+/* hunta0,medforda0=pcie_pf_bar2 */
#define ER_DZ_RX_DESC_UPD_REG_STEP 8192
#define ER_DZ_RX_DESC_UPD_REG_ROWS 2048
#define ER_DZ_RX_DESC_UPD_REG_RESET 0x0
@@ -174,7 +174,7 @@ extern "C" {
*/
#define ER_DZ_TX_DESC_UPD_REG_OFST 0x00000a10
-/* hunta0=pcie_pf_bar2 */
+/* hunta0,medforda0=pcie_pf_bar2 */
#define ER_DZ_TX_DESC_UPD_REG_STEP 8192
#define ER_DZ_TX_DESC_UPD_REG_ROWS 2048
#define ER_DZ_TX_DESC_UPD_REG_RESET 0x0
@@ -248,8 +248,14 @@ extern "C" {
#define ESF_DZ_RX_OVERRIDE_HOLDOFF_WIDTH 1
#define ESF_DZ_RX_DROP_EVENT_LBN 58
#define ESF_DZ_RX_DROP_EVENT_WIDTH 1
-#define ESF_DZ_RX_EV_RSVD2_LBN 54
-#define ESF_DZ_RX_EV_RSVD2_WIDTH 4
+#define ESF_DD_RX_EV_RSVD2_LBN 54
+#define ESF_DD_RX_EV_RSVD2_WIDTH 4
+#define ESF_EZ_RX_TCP_UDP_INNER_CHKSUM_ERR_LBN 57
+#define ESF_EZ_RX_TCP_UDP_INNER_CHKSUM_ERR_WIDTH 1
+#define ESF_EZ_RX_IP_INNER_CHKSUM_ERR_LBN 56
+#define ESF_EZ_RX_IP_INNER_CHKSUM_ERR_WIDTH 1
+#define ESF_EZ_RX_EV_RSVD2_LBN 54
+#define ESF_EZ_RX_EV_RSVD2_WIDTH 2
#define ESF_DZ_RX_EV_SOFT2_LBN 52
#define ESF_DZ_RX_EV_SOFT2_WIDTH 2
#define ESF_DZ_RX_DSC_PTR_LBITS_LBN 48
@@ -293,10 +299,21 @@ extern "C" {
#define ESF_DZ_RX_MAC_CLASS_WIDTH 1
#define ESE_DZ_MAC_CLASS_MCAST 1
#define ESE_DZ_MAC_CLASS_UCAST 0
-#define ESF_DZ_RX_EV_SOFT1_LBN 32
-#define ESF_DZ_RX_EV_SOFT1_WIDTH 3
-#define ESF_DZ_RX_EV_RSVD1_LBN 30
-#define ESF_DZ_RX_EV_RSVD1_WIDTH 2
+#define ESF_DD_RX_EV_SOFT1_LBN 32
+#define ESF_DD_RX_EV_SOFT1_WIDTH 3
+#define ESF_EZ_RX_EV_SOFT1_LBN 34
+#define ESF_EZ_RX_EV_SOFT1_WIDTH 1
+#define ESF_EZ_RX_ENCAP_HDR_LBN 32
+#define ESF_EZ_RX_ENCAP_HDR_WIDTH 2
+#define ESE_EZ_ENCAP_HDR_GRE 2
+#define ESE_EZ_ENCAP_HDR_VXLAN 1
+#define ESE_EZ_ENCAP_HDR_NONE 0
+#define ESF_DD_RX_EV_RSVD1_LBN 30
+#define ESF_DD_RX_EV_RSVD1_WIDTH 2
+#define ESF_EZ_RX_EV_RSVD1_LBN 31
+#define ESF_EZ_RX_EV_RSVD1_WIDTH 1
+#define ESF_EZ_RX_ABORT_LBN 30
+#define ESF_EZ_RX_ABORT_WIDTH 1
#define ESF_DZ_RX_ECC_ERR_LBN 29
#define ESF_DZ_RX_ECC_ERR_WIDTH 1
#define ESF_DZ_RX_CRC1_ERR_LBN 28
@@ -369,12 +386,22 @@ extern "C" {
#define ESF_DZ_TX_OVERRIDE_HOLDOFF_WIDTH 1
#define ESF_DZ_TX_DROP_EVENT_LBN 58
#define ESF_DZ_TX_DROP_EVENT_WIDTH 1
-#define ESF_DZ_TX_EV_RSVD_LBN 48
-#define ESF_DZ_TX_EV_RSVD_WIDTH 10
+#define ESF_DD_TX_EV_RSVD_LBN 48
+#define ESF_DD_TX_EV_RSVD_WIDTH 10
+#define ESF_EZ_TCP_UDP_INNER_CHKSUM_ERR_LBN 57
+#define ESF_EZ_TCP_UDP_INNER_CHKSUM_ERR_WIDTH 1
+#define ESF_EZ_IP_INNER_CHKSUM_ERR_LBN 56
+#define ESF_EZ_IP_INNER_CHKSUM_ERR_WIDTH 1
+#define ESF_EZ_TX_EV_RSVD_LBN 48
+#define ESF_EZ_TX_EV_RSVD_WIDTH 8
#define ESF_DZ_TX_SOFT2_LBN 32
#define ESF_DZ_TX_SOFT2_WIDTH 16
-#define ESF_DZ_TX_SOFT1_LBN 24
-#define ESF_DZ_TX_SOFT1_WIDTH 8
+#define ESF_DD_TX_SOFT1_LBN 24
+#define ESF_DD_TX_SOFT1_WIDTH 8
+#define ESF_EZ_TX_CAN_MERGE_LBN 31
+#define ESF_EZ_TX_CAN_MERGE_WIDTH 1
+#define ESF_EZ_TX_SOFT1_LBN 24
+#define ESF_EZ_TX_SOFT1_WIDTH 7
#define ESF_DZ_TX_QLABEL_LBN 16
#define ESF_DZ_TX_QLABEL_WIDTH 5
#define ESF_DZ_TX_DESCR_INDX_LBN 0
diff --git a/sys/dev/sfxge/common/efx_rx.c b/sys/dev/sfxge/common/efx_rx.c
index a0b143f..8ebe205 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 cff7742..168fde4 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 c1762e6..ebeddfe 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 2cea2e0..1a41b49 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);
}
@@ -486,17 +486,14 @@ ef10_ev_rx(
{
efx_nic_t *enp = eep->ee_enp;
uint32_t size;
-#if 0
- boolean_t parse_err;
-#endif
uint32_t label;
- uint32_t mcast;
- uint32_t eth_base_class;
+ uint32_t mac_class;
uint32_t eth_tag_class;
uint32_t l3_class;
uint32_t l4_class;
uint32_t next_read_lbits;
uint16_t flags;
+ boolean_t cont;
boolean_t should_abort;
efx_evq_rxq_state_t *eersp;
unsigned int desc_count;
@@ -508,10 +505,15 @@ ef10_ev_rx(
if (enp->en_reset_flags & (EFX_RESET_RXQ_ERR | EFX_RESET_TXQ_ERR))
return (B_FALSE);
- /*
- * FIXME: likely to be incomplete, incorrect and inefficient.
- * Improvements in all three areas are required.
- */
+ /* Basic packet information */
+ size = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_BYTES);
+ next_read_lbits = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_DSC_PTR_LBITS);
+ label = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_QLABEL);
+ eth_tag_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_ETH_TAG_CLASS);
+ mac_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_MAC_CLASS);
+ l3_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_L3_CLASS);
+ l4_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_L4_CLASS);
+ cont = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_CONT);
if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_DROP_EVENT) != 0) {
/* Drop this event */
@@ -519,9 +521,7 @@ ef10_ev_rx(
}
flags = 0;
- size = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_BYTES);
-
- if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_CONT) != 0) {
+ if (cont != 0) {
/*
* This may be part of a scattered frame, or it may be a
* truncated frame if scatter is disabled on this RXQ.
@@ -534,41 +534,9 @@ ef10_ev_rx(
flags |= EFX_PKT_CONT;
}
-#if 0
- /* TODO What to do if the packet is flagged with parsing error */
- parse_err = (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_PARSE_INCOMPLETE) != 0);
-#endif
- label = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_QLABEL);
-
- if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_ECRC_ERR) != 0) {
- /* Ethernet frame CRC bad */
- flags |= EFX_DISCARD;
- }
- if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_CRC0_ERR) != 0) {
- /* IP+TCP, bad CRC in iSCSI header */
- flags |= EFX_DISCARD;
- }
- if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_CRC1_ERR) != 0) {
- /* IP+TCP, bad CRC in iSCSI payload or FCoE or FCoIP */
- flags |= EFX_DISCARD;
- }
- if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_ECC_ERR) != 0) {
- /* ECC memory error */
- flags |= EFX_DISCARD;
- }
-
- mcast = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_MAC_CLASS);
- if (mcast == ESE_DZ_MAC_CLASS_UCAST)
+ if (mac_class == ESE_DZ_MAC_CLASS_UCAST)
flags |= EFX_PKT_UNICAST;
- eth_base_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_ETH_BASE_CLASS);
- eth_tag_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_ETH_TAG_CLASS);
- l3_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_L3_CLASS);
- l4_class = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_L4_CLASS);
-
- /* bottom 4 bits of incremented index (not last desc consumed) */
- next_read_lbits = EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_DSC_PTR_LBITS);
-
/* Increment the count of descriptors read */
eersp = &eep->ee_rxq_state[label];
desc_count = (next_read_lbits - eersp->eers_rx_read_ptr) &
@@ -587,88 +555,84 @@ ef10_ev_rx(
/* Calculate the index of the the last descriptor consumed */
last_used_id = (eersp->eers_rx_read_ptr - 1) & eersp->eers_rx_mask;
- /* EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_OVERRIDE_HOLDOFF); */
-
- switch (eth_base_class) {
- case ESE_DZ_ETH_BASE_CLASS_LLC_SNAP:
- case ESE_DZ_ETH_BASE_CLASS_LLC:
- case ESE_DZ_ETH_BASE_CLASS_ETH2:
- default:
- break;
+ /* Check for errors that invalidate checksum and L3/L4 fields */
+ if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_ECC_ERR) != 0) {
+ /* RX frame truncated (error flag is misnamed) */
+ EFX_EV_QSTAT_INCR(eep, EV_RX_FRM_TRUNC);
+ flags |= EFX_DISCARD;
+ goto deliver;
+ }
+ if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_ECRC_ERR) != 0) {
+ /* Bad Ethernet frame CRC */
+ EFX_EV_QSTAT_INCR(eep, EV_RX_ETH_CRC_ERR);
+ flags |= EFX_DISCARD;
+ goto deliver;
+ }
+ if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_PARSE_INCOMPLETE)) {
+ /*
+ * Hardware parse failed, due to malformed headers
+ * or headers that are too long for the parser.
+ * Headers and checksums must be validated by the host.
+ */
+ // TODO: EFX_EV_QSTAT_INCR(eep, EV_RX_PARSE_INCOMPLETE);
+ goto deliver;
}
- switch (eth_tag_class) {
- case ESE_DZ_ETH_TAG_CLASS_RSVD7:
- case ESE_DZ_ETH_TAG_CLASS_RSVD6:
- case ESE_DZ_ETH_TAG_CLASS_RSVD5:
- case ESE_DZ_ETH_TAG_CLASS_RSVD4:
- break;
-
- case ESE_DZ_ETH_TAG_CLASS_RSVD3: /* Triple tagged */
- case ESE_DZ_ETH_TAG_CLASS_VLAN2: /* Double tagged */
- case ESE_DZ_ETH_TAG_CLASS_VLAN1: /* VLAN tagged */
+ if ((eth_tag_class == ESE_DZ_ETH_TAG_CLASS_VLAN1) ||
+ (eth_tag_class == ESE_DZ_ETH_TAG_CLASS_VLAN2)) {
flags |= EFX_PKT_VLAN_TAGGED;
- break;
-
- case ESE_DZ_ETH_TAG_CLASS_NONE:
- default:
- break;
}
switch (l3_class) {
- case ESE_DZ_L3_CLASS_RSVD7: /* Used by firmware for packet overrun */
-#if 0
- parse_err = B_TRUE;
-#endif
- flags |= EFX_DISCARD;
- break;
+ case ESE_DZ_L3_CLASS_IP4:
+ case ESE_DZ_L3_CLASS_IP4_FRAG:
+ flags |= EFX_PKT_IPV4;
+ if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_IPCKSUM_ERR)) {
+ EFX_EV_QSTAT_INCR(eep, EV_RX_IPV4_HDR_CHKSUM_ERR);
+ } else {
+ flags |= EFX_CKSUM_IPV4;
+ }
- case ESE_DZ_L3_CLASS_ARP:
- case ESE_DZ_L3_CLASS_FCOE:
+ if (l4_class == ESE_DZ_L4_CLASS_TCP) {
+ EFX_EV_QSTAT_INCR(eep, EV_RX_TCP_IPV4);
+ flags |= EFX_PKT_TCP;
+ } else if (l4_class == ESE_DZ_L4_CLASS_UDP) {
+ EFX_EV_QSTAT_INCR(eep, EV_RX_UDP_IPV4);
+ flags |= EFX_PKT_UDP;
+ } else {
+ EFX_EV_QSTAT_INCR(eep, EV_RX_OTHER_IPV4);
+ }
break;
- case ESE_DZ_L3_CLASS_IP6_FRAG:
case ESE_DZ_L3_CLASS_IP6:
+ case ESE_DZ_L3_CLASS_IP6_FRAG:
flags |= EFX_PKT_IPV6;
- break;
- case ESE_DZ_L3_CLASS_IP4_FRAG:
- case ESE_DZ_L3_CLASS_IP4:
- flags |= EFX_PKT_IPV4;
- if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_IPCKSUM_ERR) == 0)
- flags |= EFX_CKSUM_IPV4;
+ if (l4_class == ESE_DZ_L4_CLASS_TCP) {
+ EFX_EV_QSTAT_INCR(eep, EV_RX_TCP_IPV6);
+ flags |= EFX_PKT_TCP;
+ } else if (l4_class == ESE_DZ_L4_CLASS_UDP) {
+ EFX_EV_QSTAT_INCR(eep, EV_RX_UDP_IPV6);
+ flags |= EFX_PKT_UDP;
+ } else {
+ EFX_EV_QSTAT_INCR(eep, EV_RX_OTHER_IPV6);
+ }
break;
- case ESE_DZ_L3_CLASS_UNKNOWN:
default:
+ EFX_EV_QSTAT_INCR(eep, EV_RX_NON_IP);
break;
}
- switch (l4_class) {
- case ESE_DZ_L4_CLASS_RSVD7:
- case ESE_DZ_L4_CLASS_RSVD6:
- case ESE_DZ_L4_CLASS_RSVD5:
- case ESE_DZ_L4_CLASS_RSVD4:
- case ESE_DZ_L4_CLASS_RSVD3:
- break;
-
- case ESE_DZ_L4_CLASS_UDP:
- flags |= EFX_PKT_UDP;
- if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_TCPUDP_CKSUM_ERR) == 0)
- flags |= EFX_CKSUM_TCPUDP;
- break;
-
- case ESE_DZ_L4_CLASS_TCP:
- flags |= EFX_PKT_TCP;
- if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_TCPUDP_CKSUM_ERR) == 0)
+ if (flags & (EFX_PKT_TCP | EFX_PKT_UDP)) {
+ if (EFX_QWORD_FIELD(*eqp, ESF_DZ_RX_TCPUDP_CKSUM_ERR)) {
+ EFX_EV_QSTAT_INCR(eep, EV_RX_TCP_UDP_CHKSUM_ERR);
+ } else {
flags |= EFX_CKSUM_TCPUDP;
- break;
-
- case ESE_DZ_L4_CLASS_UNKNOWN:
- default:
- break;
+ }
}
+deliver:
/* If we're not discarding the packet then it is ok */
if (~flags & EFX_DISCARD)
EFX_EV_QSTAT_INCR(eep, EV_RX_OK);
@@ -835,7 +799,7 @@ ef10_ev_mcdi(
case MCDI_EVENT_CODE_LINKCHANGE: {
efx_link_mode_t link_mode;
- hunt_phy_link_ev(enp, eqp, &link_mode);
+ ef10_phy_link_ev(enp, eqp, &link_mode);
should_abort = eecp->eec_link_change(arg, link_mode);
break;
}
diff --git a/sys/dev/sfxge/common/hunt_impl.h b/sys/dev/sfxge/common/hunt_impl.h
index f8c3b5e..49ecbea 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);
@@ -209,41 +220,45 @@ ef10_nic_unprobe(
/* MAC */
extern __checkReturn efx_rc_t
-hunt_mac_poll(
+ef10_mac_poll(
__in efx_nic_t *enp,
__out efx_link_mode_t *link_modep);
extern __checkReturn efx_rc_t
-hunt_mac_up(
+ef10_mac_up(
__in efx_nic_t *enp,
__out boolean_t *mac_upp);
extern __checkReturn efx_rc_t
-hunt_mac_addr_set(
+ef10_mac_addr_set(
__in efx_nic_t *enp);
extern __checkReturn efx_rc_t
-hunt_mac_reconfigure(
+ef10_mac_pdu_set(
__in efx_nic_t *enp);
extern __checkReturn efx_rc_t
-hunt_mac_multicast_list_set(
+ef10_mac_reconfigure(
+ __in efx_nic_t *enp);
+
+extern __checkReturn efx_rc_t
+ef10_mac_multicast_list_set(
__in efx_nic_t *enp);
extern __checkReturn efx_rc_t
-hunt_mac_filter_default_rxq_set(
+ef10_mac_filter_default_rxq_set(
__in efx_nic_t *enp,
__in efx_rxq_t *erp,
__in boolean_t using_rss);
extern void
-hunt_mac_filter_default_rxq_clear(
+ef10_mac_filter_default_rxq_clear(
__in efx_nic_t *enp);
#if EFSYS_OPT_LOOPBACK
extern __checkReturn efx_rc_t
-hunt_mac_loopback_set(
+ef10_mac_loopback_set(
__in efx_nic_t *enp,
__in efx_link_mode_t link_mode,
__in efx_loopback_type_t loopback_type);
@@ -253,7 +268,7 @@ hunt_mac_loopback_set(
#if EFSYS_OPT_MAC_STATS
extern __checkReturn efx_rc_t
-hunt_mac_stats_update(
+ef10_mac_stats_update(
__in efx_nic_t *enp,
__in efsys_mem_t *esmp,
__inout_ecount(EFX_MAC_NSTATS) efsys_stat_t *stat,
@@ -276,12 +291,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 +309,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,39 +369,10 @@ 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);
-extern __checkReturn efx_rc_t
-ef10_nvram_partn_read(
- __in efx_nic_t *enp,
- __in uint32_t partn,
- __in unsigned int offset,
- __out_bcount(size) caddr_t data,
- __in size_t size);
-
-extern __checkReturn efx_rc_t
-ef10_nvram_partn_erase(
- __in efx_nic_t *enp,
- __in uint32_t partn,
- __in unsigned int offset,
- __in size_t size);
-
-extern __checkReturn efx_rc_t
-ef10_nvram_partn_write(
- __in efx_nic_t *enp,
- __in uint32_t partn,
- __in unsigned int offset,
- __out_bcount(size) caddr_t data,
- __in size_t size);
-
extern void
ef10_nvram_partn_unlock(
__in efx_nic_t *enp,
@@ -410,117 +391,122 @@ ef10_nvram_test(
#endif /* EFSYS_OPT_DIAG */
extern __checkReturn efx_rc_t
-ef10_nvram_size(
+ef10_nvram_type_to_partn(
__in efx_nic_t *enp,
__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_get_version(
+ef10_nvram_partn_rw_start(
__in efx_nic_t *enp,
- __in efx_nvram_type_t type,
- __out uint32_t *subtypep,
- __out_ecount(4) uint16_t version[4]);
+ __in uint32_t partn,
+ __out size_t *chunk_sizep);
extern __checkReturn efx_rc_t
-ef10_nvram_rw_start(
+ef10_nvram_partn_read_mode(
__in efx_nic_t *enp,
- __in efx_nvram_type_t type,
- __out size_t *pref_chunkp);
+ __in uint32_t partn,
+ __in unsigned int offset,
+ __out_bcount(size) caddr_t data,
+ __in size_t size,
+ __in uint32_t mode);
extern __checkReturn efx_rc_t
-ef10_nvram_read_chunk(
+ef10_nvram_partn_read(
__in efx_nic_t *enp,
- __in efx_nvram_type_t type,
+ __in uint32_t partn,
__in unsigned int offset,
__out_bcount(size) caddr_t data,
__in size_t size);
-extern __checkReturn efx_rc_t
-ef10_nvram_erase(
+extern __checkReturn efx_rc_t
+ef10_nvram_partn_erase(
__in efx_nic_t *enp,
- __in efx_nvram_type_t type);
+ __in uint32_t partn,
+ __in unsigned int offset,
+ __in size_t size);
extern __checkReturn efx_rc_t
-ef10_nvram_write_chunk(
+ef10_nvram_partn_write(
__in efx_nic_t *enp,
- __in efx_nvram_type_t type,
+ __in uint32_t partn,
__in unsigned int offset,
- __in_bcount(size) caddr_t data,
+ __out_bcount(size) caddr_t data,
__in size_t size);
extern void
-ef10_nvram_rw_finish(
+ef10_nvram_partn_rw_finish(
__in efx_nic_t *enp,
- __in efx_nvram_type_t type);
+ __in uint32_t partn);
extern __checkReturn efx_rc_t
-ef10_nvram_partn_set_version(
+ef10_nvram_partn_get_version(
__in efx_nic_t *enp,
__in uint32_t partn,
- __in_ecount(4) uint16_t version[4]);
+ __out uint32_t *subtypep,
+ __out_ecount(4) uint16_t version[4]);
extern __checkReturn efx_rc_t
-ef10_nvram_set_version(
+ef10_nvram_partn_set_version(
__in efx_nic_t *enp,
- __in efx_nvram_type_t type,
+ __in uint32_t partn,
__in_ecount(4) uint16_t version[4]);
-extern __checkReturn efx_rc_t
-ef10_nvram_type_to_partn(
- __in efx_nic_t *enp,
- __in efx_nvram_type_t type,
- __out uint32_t *partnp);
-
#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(
+ef10_phy_link_ev(
__in efx_nic_t *enp,
__in efx_qword_t *eqp,
__out efx_link_mode_t *link_modep);
extern __checkReturn efx_rc_t
-hunt_phy_get_link(
+ef10_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(
+ef10_phy_power(
__in efx_nic_t *enp,
__in boolean_t on);
extern __checkReturn efx_rc_t
-hunt_phy_reconfigure(
+ef10_phy_reconfigure(
__in efx_nic_t *enp);
extern __checkReturn efx_rc_t
-hunt_phy_verify(
+ef10_phy_verify(
__in efx_nic_t *enp);
extern __checkReturn efx_rc_t
-hunt_phy_oui_get(
+ef10_phy_oui_get(
__in efx_nic_t *enp,
__out uint32_t *ouip);
#if EFSYS_OPT_PHY_STATS
extern __checkReturn efx_rc_t
-hunt_phy_stats_update(
+ef10_phy_stats_update(
__in efx_nic_t *enp,
__in efsys_mem_t *esmp,
__inout_ecount(EFX_PHY_NSTATS) uint32_t *stat);
@@ -532,21 +518,21 @@ hunt_phy_stats_update(
#if EFSYS_OPT_NAMES
extern const char *
-hunt_phy_prop_name(
+ef10_phy_prop_name(
__in efx_nic_t *enp,
__in unsigned int id);
#endif /* EFSYS_OPT_NAMES */
extern __checkReturn efx_rc_t
-hunt_phy_prop_get(
+ef10_phy_prop_get(
__in efx_nic_t *enp,
__in unsigned int id,
__in uint32_t flags,
__out uint32_t *valp);
extern __checkReturn efx_rc_t
-hunt_phy_prop_set(
+ef10_phy_prop_set(
__in efx_nic_t *enp,
__in unsigned int id,
__in uint32_t val);
@@ -696,6 +682,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 +728,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 +741,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 +881,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 358c4d9..a36a11a 100644
--- a/sys/dev/sfxge/common/hunt_mac.c
+++ b/sys/dev/sfxge/common/hunt_mac.c
@@ -38,26 +38,21 @@ __FBSDID("$FreeBSD$");
#if EFSYS_OPT_HUNTINGTON
__checkReturn efx_rc_t
-hunt_mac_poll(
+ef10_mac_poll(
__in efx_nic_t *enp,
__out efx_link_mode_t *link_modep)
{
- /*
- * TBD: Consider a common Siena/Huntington function. The code is
- * essentially identical.
- */
-
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 = ef10_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);
@@ -70,26 +65,21 @@ fail1:
}
__checkReturn efx_rc_t
-hunt_mac_up(
+ef10_mac_up(
__in efx_nic_t *enp,
__out boolean_t *mac_upp)
{
- /*
- * TBD: Consider a common Siena/Huntington function. The code is
- * 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.
+ * Because EF10 doesn't *require* polling, we can't rely on
+ * ef10_mac_poll() being executed to populate epp->ep_mac_up.
*/
- if ((rc = hunt_phy_get_link(enp, &hls)) != 0)
+ if ((rc = ef10_phy_get_link(enp, &els)) != 0)
goto fail1;
- *mac_upp = hls.hls_mac_up;
+ *mac_upp = els.els_mac_up;
return (0);
@@ -100,7 +90,7 @@ fail1:
}
/*
- * Huntington uses MC_CMD_VADAPTOR_SET_MAC to set the
+ * EF10 adapters use MC_CMD_VADAPTOR_SET_MAC to set the
* MAC address; the address field in MC_CMD_SET_MAC has no
* effect.
* MC_CMD_VADAPTOR_SET_MAC requires mac-spoofing privilege and
@@ -144,7 +134,7 @@ fail1:
}
__checkReturn efx_rc_t
-hunt_mac_addr_set(
+ef10_mac_addr_set(
__in efx_nic_t *enp)
{
efx_rc_t rc;
@@ -153,8 +143,11 @@ hunt_mac_addr_set(
if (rc != ENOTSUP)
goto fail1;
- /* Fallback for older firmware without Vadapter support */
- if ((rc = hunt_mac_reconfigure(enp)) != 0)
+ /*
+ * Fallback for older Huntington firmware without Vadapter
+ * support.
+ */
+ if ((rc = ef10_mac_reconfigure(enp)) != 0)
goto fail2;
}
@@ -169,8 +162,76 @@ fail1:
return (rc);
}
+static __checkReturn efx_rc_t
+efx_mcdi_mtu_set(
+ __in efx_nic_t *enp,
+ __in uint32_t mtu)
+{
+ efx_mcdi_req_t req;
+ uint8_t payload[MAX(MC_CMD_SET_MAC_EXT_IN_LEN,
+ MC_CMD_SET_MAC_OUT_LEN)];
+ efx_rc_t rc;
+
+ (void) memset(payload, 0, sizeof (payload));
+ req.emr_cmd = MC_CMD_SET_MAC;
+ req.emr_in_buf = payload;
+ req.emr_in_length = MC_CMD_SET_MAC_EXT_IN_LEN;
+ req.emr_out_buf = payload;
+ req.emr_out_length = MC_CMD_SET_MAC_OUT_LEN;
+
+ /* Only configure the MTU in this call to MC_CMD_SET_MAC */
+ MCDI_IN_SET_DWORD(req, SET_MAC_EXT_IN_MTU, mtu);
+ MCDI_IN_POPULATE_DWORD_1(req, SET_MAC_EXT_IN_CONTROL,
+ SET_MAC_EXT_IN_CFG_MTU, 1);
+
+ 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);
+}
+
+ __checkReturn efx_rc_t
+ef10_mac_pdu_set(
+ __in efx_nic_t *enp)
+{
+ efx_port_t *epp = &(enp->en_port);
+ efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
+ efx_rc_t rc;
+
+ if (encp->enc_enhanced_set_mac_supported) {
+ if ((rc = efx_mcdi_mtu_set(enp, epp->ep_mac_pdu)) != 0)
+ goto fail1;
+ } else {
+ /*
+ * Fallback for older Huntington firmware, which always
+ * configure all of the parameters to MC_CMD_SET_MAC. This isn't
+ * suitable for setting the MTU on unpriviliged functions.
+ */
+ if ((rc = ef10_mac_reconfigure(enp)) != 0)
+ goto fail2;
+ }
+
+ return (0);
+
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
+
__checkReturn efx_rc_t
-hunt_mac_reconfigure(
+ef10_mac_reconfigure(
__in efx_nic_t *enp)
{
efx_port_t *epp = &(enp->en_port);
@@ -197,6 +258,8 @@ hunt_mac_reconfigure(
* from reaching the filters. As Huntington filters drop any
* traffic that does not match a filter it is ok to leave the
* MAC running in promiscuous mode. See bug41141.
+ *
+ * FIXME: Does REJECT_UNCST behave the same way on Medford?
*/
MCDI_IN_POPULATE_DWORD_2(req, SET_MAC_IN_REJECT,
SET_MAC_IN_REJECT_UNCST, 0,
@@ -247,16 +310,15 @@ fail1:
}
__checkReturn efx_rc_t
-hunt_mac_multicast_list_set(
+ef10_mac_multicast_list_set(
__in efx_nic_t *enp)
{
efx_port_t *epp = &(enp->en_port);
efx_mac_ops_t *emop = epp->ep_emop;
efx_rc_t rc;
- EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON);
-
- /* FIXME: Insert filters for multicast list */
+ EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
+ enp->en_family == EFX_FAMILY_MEDFORD);
if ((rc = emop->emo_reconfigure(enp)) != 0)
goto fail1;
@@ -270,7 +332,7 @@ fail1:
}
__checkReturn efx_rc_t
-hunt_mac_filter_default_rxq_set(
+ef10_mac_filter_default_rxq_set(
__in efx_nic_t *enp,
__in efx_rxq_t *erp,
__in boolean_t using_rss)
@@ -304,7 +366,7 @@ fail1:
}
void
-hunt_mac_filter_default_rxq_clear(
+ef10_mac_filter_default_rxq_clear(
__in efx_nic_t *enp)
{
efx_port_t *epp = &(enp->en_port);
@@ -322,23 +384,18 @@ hunt_mac_filter_default_rxq_clear(
#if EFSYS_OPT_LOOPBACK
__checkReturn efx_rc_t
-hunt_mac_loopback_set(
+ef10_mac_loopback_set(
__in efx_nic_t *enp,
__in efx_link_mode_t link_mode,
__in efx_loopback_type_t loopback_type)
{
- /*
- * TBD: Consider a common Siena/Huntington function. The code is
- * essentially identical.
- */
-
efx_port_t *epp = &(enp->en_port);
efx_phy_ops_t *epop = epp->ep_epop;
efx_loopback_type_t old_loopback_type;
efx_link_mode_t old_loopback_link_mode;
efx_rc_t rc;
- /* The PHY object handles this on Huntington */
+ /* The PHY object handles this on EF10 */
old_loopback_type = epp->ep_loopback_type;
old_loopback_link_mode = epp->ep_loopback_link_mode;
epp->ep_loopback_type = loopback_type;
@@ -362,12 +419,12 @@ fail1:
#if EFSYS_OPT_MAC_STATS
-#define HUNT_MAC_STAT_READ(_esmp, _field, _eqp) \
+#define EF10_MAC_STAT_READ(_esmp, _field, _eqp) \
EFSYS_MEM_READQ((_esmp), (_field) * sizeof (efx_qword_t), _eqp)
__checkReturn efx_rc_t
-hunt_mac_stats_update(
+ef10_mac_stats_update(
__in efx_nic_t *enp,
__in efsys_mem_t *esmp,
__inout_ecount(EFX_MAC_NSTATS) efsys_stat_t *stat,
@@ -381,301 +438,301 @@ hunt_mac_stats_update(
/* Read END first so we don't race with the MC */
EFSYS_DMA_SYNC_FOR_KERNEL(esmp, 0, EFX_MAC_STATS_SIZE);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_GENERATION_END,
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_GENERATION_END,
&generation_end);
EFSYS_MEM_READ_BARRIER();
/* TX */
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_CONTROL_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_CONTROL_PKTS, &value);
EFSYS_STAT_SUBR_QWORD(&(stat[EFX_MAC_TX_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_PAUSE_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_PAUSE_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_PAUSE_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_UNICAST_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_UNICAST_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_UNICST_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_MULTICAST_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_MULTICAST_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_MULTICST_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_BROADCAST_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_BROADCAST_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_BRDCST_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_BYTES, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_BYTES, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_OCTETS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_LT64_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_LT64_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_LE_64_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_64_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_64_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_LE_64_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_65_TO_127_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_65_TO_127_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_65_TO_127_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_128_TO_255_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_128_TO_255_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_128_TO_255_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_256_TO_511_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_256_TO_511_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_256_TO_511_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_512_TO_1023_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_512_TO_1023_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_512_TO_1023_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_1024_TO_15XX_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_1024_TO_15XX_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_1024_TO_15XX_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_15XX_TO_JUMBO_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_15XX_TO_JUMBO_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_GE_15XX_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_GTJUMBO_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_GTJUMBO_PKTS, &value);
EFSYS_STAT_INCR_QWORD(&(stat[EFX_MAC_TX_GE_15XX_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_BAD_FCS_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_BAD_FCS_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_ERRORS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_SINGLE_COLLISION_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_SINGLE_COLLISION_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_SGL_COL_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_MULTIPLE_COLLISION_PKTS,
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_MULTIPLE_COLLISION_PKTS,
&value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_MULT_COL_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_EXCESSIVE_COLLISION_PKTS,
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_EXCESSIVE_COLLISION_PKTS,
&value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_EX_COL_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_LATE_COLLISION_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_LATE_COLLISION_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_LATE_COL_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_DEFERRED_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_DEFERRED_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_DEF_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_EXCESSIVE_DEFERRED_PKTS,
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_TX_EXCESSIVE_DEFERRED_PKTS,
&value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_TX_EX_DEF_PKTS]), &value);
/* RX */
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_BYTES, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_BYTES, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_OCTETS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_UNICAST_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_UNICAST_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_UNICST_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_MULTICAST_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_MULTICAST_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_MULTICST_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_BROADCAST_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_BROADCAST_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_BRDCST_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_PAUSE_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_PAUSE_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_PAUSE_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_UNDERSIZE_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_UNDERSIZE_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_LE_64_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_64_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_64_PKTS, &value);
EFSYS_STAT_INCR_QWORD(&(stat[EFX_MAC_RX_LE_64_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_65_TO_127_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_65_TO_127_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_65_TO_127_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_128_TO_255_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_128_TO_255_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_128_TO_255_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_256_TO_511_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_256_TO_511_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_256_TO_511_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_512_TO_1023_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_512_TO_1023_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_512_TO_1023_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_1024_TO_15XX_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_1024_TO_15XX_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_1024_TO_15XX_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_15XX_TO_JUMBO_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_15XX_TO_JUMBO_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_GE_15XX_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_GTJUMBO_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_GTJUMBO_PKTS, &value);
EFSYS_STAT_INCR_QWORD(&(stat[EFX_MAC_RX_GE_15XX_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_BAD_FCS_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_BAD_FCS_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_FCS_ERRORS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_OVERFLOW_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_OVERFLOW_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_DROP_EVENTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_FALSE_CARRIER_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_FALSE_CARRIER_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_FALSE_CARRIER_ERRORS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_SYMBOL_ERROR_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_SYMBOL_ERROR_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_SYMBOL_ERRORS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_ALIGN_ERROR_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_ALIGN_ERROR_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_ALIGN_ERRORS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_INTERNAL_ERROR_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_INTERNAL_ERROR_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_INTERNAL_ERRORS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_JABBER_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_JABBER_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_JABBER_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES01_CHAR_ERR, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES01_CHAR_ERR, &value);
EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE0_CHAR_ERR]),
&(value.eq_dword[0]));
EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE1_CHAR_ERR]),
&(value.eq_dword[1]));
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES23_CHAR_ERR, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES23_CHAR_ERR, &value);
EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE2_CHAR_ERR]),
&(value.eq_dword[0]));
EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE3_CHAR_ERR]),
&(value.eq_dword[1]));
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES01_DISP_ERR, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES01_DISP_ERR, &value);
EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE0_DISP_ERR]),
&(value.eq_dword[0]));
EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE1_DISP_ERR]),
&(value.eq_dword[1]));
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES23_DISP_ERR, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_LANES23_DISP_ERR, &value);
EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE2_DISP_ERR]),
&(value.eq_dword[0]));
EFSYS_STAT_SET_DWORD(&(stat[EFX_MAC_RX_LANE3_DISP_ERR]),
&(value.eq_dword[1]));
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_MATCH_FAULT, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_MATCH_FAULT, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_MATCH_FAULT]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_NODESC_DROPS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RX_NODESC_DROPS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RX_NODESC_DROP_CNT]), &value);
/* Packet memory (EF10 only) */
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_PM_TRUNC_BB_OVERFLOW, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_PM_TRUNC_BB_OVERFLOW, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_PM_TRUNC_BB_OVERFLOW]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_PM_DISCARD_BB_OVERFLOW, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_PM_DISCARD_BB_OVERFLOW, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_PM_DISCARD_BB_OVERFLOW]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_PM_TRUNC_VFIFO_FULL, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_PM_TRUNC_VFIFO_FULL, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_PM_TRUNC_VFIFO_FULL]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_PM_DISCARD_VFIFO_FULL, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_PM_DISCARD_VFIFO_FULL, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_PM_DISCARD_VFIFO_FULL]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_PM_TRUNC_QBB, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_PM_TRUNC_QBB, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_PM_TRUNC_QBB]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_PM_DISCARD_QBB, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_PM_DISCARD_QBB, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_PM_DISCARD_QBB]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_PM_DISCARD_MAPPING, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_PM_DISCARD_MAPPING, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_PM_DISCARD_MAPPING]), &value);
/* RX datapath */
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RXDP_Q_DISABLED_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RXDP_Q_DISABLED_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RXDP_Q_DISABLED_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RXDP_DI_DROPPED_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RXDP_DI_DROPPED_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RXDP_DI_DROPPED_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RXDP_STREAMING_PKTS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RXDP_STREAMING_PKTS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RXDP_STREAMING_PKTS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RXDP_HLB_FETCH_CONDITIONS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RXDP_HLB_FETCH_CONDITIONS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RXDP_HLB_FETCH]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_RXDP_HLB_WAIT_CONDITIONS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_RXDP_HLB_WAIT_CONDITIONS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_RXDP_HLB_WAIT]), &value);
/* VADAPTER RX */
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_UNICAST_PACKETS,
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_UNICAST_PACKETS,
&value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_RX_UNICAST_PACKETS]),
&value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_UNICAST_BYTES,
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_UNICAST_BYTES,
&value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_RX_UNICAST_BYTES]),
&value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_MULTICAST_PACKETS,
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_MULTICAST_PACKETS,
&value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_RX_MULTICAST_PACKETS]),
&value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_MULTICAST_BYTES,
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_MULTICAST_BYTES,
&value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_RX_MULTICAST_BYTES]),
&value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_BROADCAST_PACKETS,
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_BROADCAST_PACKETS,
&value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_RX_BROADCAST_PACKETS]),
&value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_BROADCAST_BYTES,
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_BROADCAST_BYTES,
&value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_RX_BROADCAST_BYTES]),
&value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_BAD_PACKETS,
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_BAD_PACKETS,
&value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_RX_BAD_PACKETS]),
&value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_BAD_BYTES, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_BAD_BYTES, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_RX_BAD_BYTES]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_OVERFLOW, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_RX_OVERFLOW, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_RX_OVERFLOW]), &value);
/* VADAPTER TX */
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_UNICAST_PACKETS,
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_UNICAST_PACKETS,
&value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_TX_UNICAST_PACKETS]),
&value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_UNICAST_BYTES,
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_UNICAST_BYTES,
&value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_TX_UNICAST_BYTES]),
&value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_MULTICAST_PACKETS,
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_MULTICAST_PACKETS,
&value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_TX_MULTICAST_PACKETS]),
&value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_MULTICAST_BYTES,
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_MULTICAST_BYTES,
&value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_TX_MULTICAST_BYTES]),
&value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_BROADCAST_PACKETS,
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_BROADCAST_PACKETS,
&value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_TX_BROADCAST_PACKETS]),
&value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_BROADCAST_BYTES,
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_BROADCAST_BYTES,
&value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_TX_BROADCAST_BYTES]),
&value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_BAD_PACKETS, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_BAD_PACKETS, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_TX_BAD_PACKETS]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_BAD_BYTES, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_BAD_BYTES, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_TX_BAD_BYTES]), &value);
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_OVERFLOW, &value);
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_VADAPTER_TX_OVERFLOW, &value);
EFSYS_STAT_SET_QWORD(&(stat[EFX_MAC_VADAPTER_TX_OVERFLOW]), &value);
EFSYS_DMA_SYNC_FOR_KERNEL(esmp, 0, EFX_MAC_STATS_SIZE);
EFSYS_MEM_READ_BARRIER();
- HUNT_MAC_STAT_READ(esmp, MC_CMD_MAC_GENERATION_START,
+ EF10_MAC_STAT_READ(esmp, MC_CMD_MAC_GENERATION_START,
&generation_start);
/* Check that we didn't read the stats in the middle of a DMA */
diff --git a/sys/dev/sfxge/common/hunt_mcdi.c b/sys/dev/sfxge/common/hunt_mcdi.c
index 1cccb23..f39e977 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 d87f3cd..7f0c068 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,75 @@ 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;
+
+ /*
+ * Check if firmware supports the extended MC_CMD_SET_MAC, which allows
+ * specifying which parameters to configure.
+ */
+ encp->enc_enhanced_set_mac_supported =
+ CAP_FLAG(flags, SET_MAC_ENHANCED) ? B_TRUE : B_FALSE;
+
+#undef CAP_FLAG
+#undef CAP_FLAG2
return (0);
@@ -970,6 +971,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 +1029,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 +1044,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 +1115,7 @@ fail1:
return (rc);
}
-static __checkReturn efx_rc_t
+ __checkReturn efx_rc_t
hunt_board_cfg(
__in efx_nic_t *enp)
{
@@ -1072,7 +1123,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 +1197,10 @@ hunt_board_cfg(
goto fail6;
/* Obtain the default PHY advertised capabilities */
- if ((rc = hunt_phy_get_link(enp, &hls)) != 0)
+ if ((rc = ef10_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 +1339,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 +1359,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 +1400,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 +1420,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 35c5ddd..dd471f4 100644
--- a/sys/dev/sfxge/common/hunt_nvram.c
+++ b/sys/dev/sfxge/common/hunt_nvram.c
@@ -598,8 +598,9 @@ ef10_nvram_read_tlv_segment(
}
/* Read initial chunk of the segment, starting at offset */
- if ((rc = ef10_nvram_partn_read(enp, partn, seg_offset, seg_data,
- EF10_NVRAM_CHUNK)) != 0) {
+ if ((rc = ef10_nvram_partn_read_mode(enp, partn, seg_offset, seg_data,
+ EF10_NVRAM_CHUNK,
+ MC_CMD_NVRAM_READ_IN_V2_TARGET_CURRENT)) != 0) {
goto fail2;
}
@@ -624,10 +625,11 @@ ef10_nvram_read_tlv_segment(
/* Read the remaining segment content */
if (total_length > EF10_NVRAM_CHUNK) {
- if ((rc = ef10_nvram_partn_read(enp, partn,
+ if ((rc = ef10_nvram_partn_read_mode(enp, partn,
seg_offset + EF10_NVRAM_CHUNK,
seg_data + EF10_NVRAM_CHUNK,
- total_length - EF10_NVRAM_CHUNK)) != 0)
+ total_length - EF10_NVRAM_CHUNK,
+ MC_CMD_NVRAM_READ_IN_V2_TARGET_CURRENT)) != 0)
goto fail6;
}
@@ -1321,12 +1323,13 @@ fail1:
}
__checkReturn efx_rc_t
-ef10_nvram_partn_read(
+ef10_nvram_partn_read_mode(
__in efx_nic_t *enp,
__in uint32_t partn,
__in unsigned int offset,
__out_bcount(size) caddr_t data,
- __in size_t size)
+ __in size_t size,
+ __in uint32_t mode)
{
size_t chunk;
efx_rc_t rc;
@@ -1335,7 +1338,7 @@ ef10_nvram_partn_read(
chunk = MIN(size, EF10_NVRAM_CHUNK);
if ((rc = efx_mcdi_nvram_read(enp, partn, offset,
- data, chunk)) != 0) {
+ data, chunk, mode)) != 0) {
goto fail1;
}
@@ -1353,6 +1356,22 @@ fail1:
}
__checkReturn efx_rc_t
+ef10_nvram_partn_read(
+ __in efx_nic_t *enp,
+ __in uint32_t partn,
+ __in unsigned int offset,
+ __out_bcount(size) caddr_t data,
+ __in size_t size)
+{
+ /*
+ * Read requests which come in through the EFX API expect to
+ * read the current, active partition.
+ */
+ return ef10_nvram_partn_read_mode(enp, partn, offset, data, size,
+ MC_CMD_NVRAM_READ_IN_V2_TARGET_CURRENT);
+}
+
+ __checkReturn efx_rc_t
ef10_nvram_partn_erase(
__in efx_nic_t *enp,
__in uint32_t partn,
@@ -1541,7 +1560,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 +1595,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
@@ -1707,56 +1734,23 @@ 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(
+ef10_nvram_partn_get_version(
__in efx_nic_t *enp,
- __in efx_nvram_type_t type,
+ __in uint32_t partn,
__out uint32_t *subtypep,
__out_ecount(4) uint16_t version[4])
{
- uint32_t partn;
efx_rc_t rc;
- if ((rc = ef10_nvram_type_to_partn(enp, type, &partn)) != 0)
- goto fail1;
-
/* FIXME: get highest partn version from all ports */
/* FIXME: return partn description if available */
if ((rc = efx_mcdi_nvram_metadata(enp, partn, subtypep,
version, NULL, 0)) != 0)
- goto fail2;
+ goto fail1;
return (0);
-fail2:
- EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
@@ -1764,111 +1758,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);
-
- return (rc);
-}
-
- __checkReturn efx_rc_t
-ef10_nvram_read_chunk(
- __in efx_nic_t *enp,
- __in efx_nvram_type_t type,
- __in unsigned int offset,
- __out_bcount(size) caddr_t data,
- __in size_t size)
-{
- 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_read(enp, partn, offset, data, size)) != 0)
- goto fail2;
-
- return (0);
-
-fail2:
- EFSYS_PROBE(fail2);
-fail1:
- EFSYS_PROBE1(fail1, efx_rc_t, rc);
-
- return (rc);
-}
-
- __checkReturn efx_rc_t
-ef10_nvram_erase(
- __in efx_nic_t *enp,
- __in efx_nvram_type_t type)
-{
- uint32_t partn;
- size_t size;
- 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, &size)) != 0)
- goto fail2;
-
- if ((rc = ef10_nvram_partn_erase(enp, partn, 0, size)) != 0)
- goto fail3;
-
- return (0);
-
-fail3:
- EFSYS_PROBE(fail3);
-fail2:
- EFSYS_PROBE(fail2);
-fail1:
- EFSYS_PROBE1(fail1, efx_rc_t, rc);
-
- return (rc);
-}
-
- __checkReturn efx_rc_t
-ef10_nvram_write_chunk(
- __in efx_nic_t *enp,
- __in efx_nvram_type_t type,
- __in unsigned int offset,
- __in_bcount(size) caddr_t data,
- __in size_t size)
-{
- 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_write(enp, partn, offset, data, size)) != 0)
- goto fail2;
-
- return (0);
-
-fail2:
- EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
@@ -1876,40 +1780,11 @@ fail1:
}
void
-ef10_nvram_rw_finish(
- __in efx_nic_t *enp,
- __in efx_nvram_type_t type)
-{
- uint32_t partn;
- efx_rc_t rc;
-
- if ((rc = ef10_nvram_type_to_partn(enp, type, &partn)) == 0)
- ef10_nvram_partn_unlock(enp, partn);
-}
-
- __checkReturn efx_rc_t
-ef10_nvram_set_version(
+ef10_nvram_partn_rw_finish(
__in efx_nic_t *enp,
- __in efx_nvram_type_t type,
- __in_ecount(4) uint16_t version[4])
+ __in uint32_t partn)
{
- 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_set_version(enp, partn, version)) != 0)
- goto fail2;
-
- return (0);
-
-fail2:
- EFSYS_PROBE(fail2);
-fail1:
- EFSYS_PROBE1(fail1, efx_rc_t, rc);
-
- return (rc);
+ ef10_nvram_partn_unlock(enp, partn);
}
#endif /* EFSYS_OPT_NVRAM */
diff --git a/sys/dev/sfxge/common/hunt_phy.c b/sys/dev/sfxge/common/hunt_phy.c
index c25e820..a6b7faa 100644
--- a/sys/dev/sfxge/common/hunt_phy.c
+++ b/sys/dev/sfxge/common/hunt_phy.c
@@ -37,15 +37,10 @@ __FBSDID("$FreeBSD$");
#if EFSYS_OPT_HUNTINGTON
static void
-hunt_phy_decode_cap(
+mcdi_phy_decode_cap(
__in uint32_t mcdi_cap,
__out uint32_t *maskp)
{
- /*
- * TBD: consider common Siena/Hunt function: Hunt is a superset of
- * Siena here (adds 40G)
- */
-
uint32_t mask;
mask = 0;
@@ -76,7 +71,7 @@ hunt_phy_decode_cap(
}
static void
-hunt_phy_decode_link_mode(
+mcdi_phy_decode_link_mode(
__in efx_nic_t *enp,
__in uint32_t link_flags,
__in unsigned int speed,
@@ -84,11 +79,6 @@ hunt_phy_decode_link_mode(
__out efx_link_mode_t *link_modep,
__out unsigned int *fcntlp)
{
- /*
- * TBD: consider common Siena/Hunt function: Hunt is a superset of
- * Siena here (adds 40G and generate-only flow control)
- */
-
boolean_t fd = !!(link_flags &
(1 << MC_CMD_GET_LINK_OUT_FULL_DUPLEX_LBN));
boolean_t up = !!(link_flags &
@@ -127,16 +117,11 @@ hunt_phy_decode_link_mode(
void
-hunt_phy_link_ev(
+ef10_phy_link_ev(
__in efx_nic_t *enp,
__in efx_qword_t *eqp,
__out efx_link_mode_t *link_modep)
{
- /*
- * TBD: consider common Siena/Hunt function: Hunt is a superset of
- * Siena here (adds 40G)
- */
-
efx_port_t *epp = &(enp->en_port);
unsigned int link_flags;
unsigned int speed;
@@ -167,10 +152,10 @@ hunt_phy_link_ev(
}
link_flags = MCDI_EV_FIELD(eqp, LINKCHANGE_LINK_FLAGS);
- hunt_phy_decode_link_mode(enp, link_flags, speed,
+ mcdi_phy_decode_link_mode(enp, link_flags, speed,
MCDI_EV_FIELD(eqp, LINKCHANGE_FCNTL),
&link_mode, &fcntl);
- hunt_phy_decode_cap(MCDI_EV_FIELD(eqp, LINKCHANGE_LP_CAP),
+ mcdi_phy_decode_cap(MCDI_EV_FIELD(eqp, LINKCHANGE_LP_CAP),
&lp_cap_mask);
/*
@@ -191,19 +176,17 @@ hunt_phy_link_ev(
}
__checkReturn efx_rc_t
-hunt_phy_power(
+ef10_phy_power(
__in efx_nic_t *enp,
__in boolean_t power)
{
- /* TBD: consider common Siena/Hunt function: essentially identical */
-
efx_rc_t rc;
if (!power)
return (0);
/* Check if the PHY is a zombie */
- if ((rc = hunt_phy_verify(enp)) != 0)
+ if ((rc = ef10_phy_verify(enp)) != 0)
goto fail1;
enp->en_reset_flags |= EFX_RESET_PHY;
@@ -217,16 +200,10 @@ fail1:
}
__checkReturn efx_rc_t
-hunt_phy_get_link(
+ef10_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
- * (at least for now; not clear that the loopbacks should necessarily
- * be quite the same...)
- */
-
efx_mcdi_req_t req;
uint8_t payload[MAX(MC_CMD_GET_LINK_IN_LEN,
MC_CMD_GET_LINK_OUT_LEN)];
@@ -251,15 +228,15 @@ hunt_phy_get_link(
goto fail2;
}
- hunt_phy_decode_cap(MCDI_OUT_DWORD(req, GET_LINK_OUT_CAP),
- &hlsp->hls_adv_cap_mask);
- hunt_phy_decode_cap(MCDI_OUT_DWORD(req, GET_LINK_OUT_LP_CAP),
- &hlsp->hls_lp_cap_mask);
+ mcdi_phy_decode_cap(MCDI_OUT_DWORD(req, GET_LINK_OUT_CAP),
+ &elsp->els_adv_cap_mask);
+ mcdi_phy_decode_cap(MCDI_OUT_DWORD(req, GET_LINK_OUT_LP_CAP),
+ &elsp->els_lp_cap_mask);
- hunt_phy_decode_link_mode(enp, MCDI_OUT_DWORD(req, GET_LINK_OUT_FLAGS),
+ mcdi_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 +259,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);
@@ -298,15 +275,9 @@ fail1:
}
__checkReturn efx_rc_t
-hunt_phy_reconfigure(
+ef10_phy_reconfigure(
__in efx_nic_t *enp)
{
- /*
- * TBD: this is a little different for now (no LED support for Hunt
- * yet), but ultimately should consider common Siena/Hunt function:
- * Hunt should be a superset of Siena here (adds 40G)
- */
-
efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
efx_port_t *epp = &(enp->en_port);
efx_mcdi_req_t req;
@@ -428,11 +399,9 @@ fail1:
}
__checkReturn efx_rc_t
-hunt_phy_verify(
+ef10_phy_verify(
__in efx_nic_t *enp)
{
- /* TBD: consider common Siena/Hunt function: essentially identical */
-
efx_mcdi_req_t req;
uint8_t payload[MAX(MC_CMD_GET_PHY_STATE_IN_LEN,
MC_CMD_GET_PHY_STATE_OUT_LEN)];
@@ -479,7 +448,7 @@ fail1:
}
__checkReturn efx_rc_t
-hunt_phy_oui_get(
+ef10_phy_oui_get(
__in efx_nic_t *enp,
__out uint32_t *ouip)
{
@@ -491,7 +460,7 @@ hunt_phy_oui_get(
#if EFSYS_OPT_PHY_STATS
__checkReturn efx_rc_t
-hunt_phy_stats_update(
+ef10_phy_stats_update(
__in efx_nic_t *enp,
__in efsys_mem_t *esmp,
__inout_ecount(EFX_PHY_NSTATS) uint32_t *stat)
@@ -509,8 +478,8 @@ hunt_phy_stats_update(
#if EFSYS_OPT_NAMES
-extern const char *
-hunt_phy_prop_name(
+ const char *
+ef10_phy_prop_name(
__in efx_nic_t *enp,
__in unsigned int id)
{
@@ -521,8 +490,8 @@ hunt_phy_prop_name(
#endif /* EFSYS_OPT_NAMES */
-extern __checkReturn efx_rc_t
-hunt_phy_prop_get(
+ __checkReturn efx_rc_t
+ef10_phy_prop_get(
__in efx_nic_t *enp,
__in unsigned int id,
__in uint32_t flags,
@@ -533,8 +502,8 @@ hunt_phy_prop_get(
return (ENOTSUP);
}
-extern __checkReturn efx_rc_t
-hunt_phy_prop_set(
+ __checkReturn efx_rc_t
+ef10_phy_prop_set(
__in efx_nic_t *enp,
__in unsigned int id,
__in uint32_t val)
diff --git a/sys/dev/sfxge/common/hunt_tx.c b/sys/dev/sfxge/common/hunt_tx.c
index 593db88..baa7444 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 58e9a66..41b4b83 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 11084dc..59ea35f 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 68c8184..7c176b5 100644
--- a/sys/dev/sfxge/common/medford_nic.c
+++ b/sys/dev/sfxge/common/medford_nic.c
@@ -39,7 +39,273 @@ __FBSDID("$FreeBSD$");
#include "ef10_tlv_layout.h"
+static __checkReturn efx_rc_t
+efx_mcdi_get_rxdp_config(
+ __in efx_nic_t *enp,
+ __out uint32_t *end_paddingp)
+{
+ efx_mcdi_req_t req;
+ uint8_t payload[MAX(MC_CMD_GET_RXDP_CONFIG_IN_LEN,
+ MC_CMD_GET_RXDP_CONFIG_OUT_LEN)];
+ uint32_t end_padding;
+ efx_rc_t rc;
+ memset(payload, 0, sizeof (payload));
+ req.emr_cmd = MC_CMD_GET_RXDP_CONFIG;
+ req.emr_in_buf = payload;
+ req.emr_in_length = MC_CMD_GET_RXDP_CONFIG_IN_LEN;
+ req.emr_out_buf = payload;
+ req.emr_out_length = MC_CMD_GET_RXDP_CONFIG_OUT_LEN;
+ efx_mcdi_execute(enp, &req);
+ if (req.emr_rc != 0) {
+ rc = req.emr_rc;
+ goto fail1;
+ }
+
+ if (MCDI_OUT_DWORD_FIELD(req, GET_RXDP_CONFIG_OUT_DATA,
+ GET_RXDP_CONFIG_OUT_PAD_HOST_DMA) == 0) {
+ /* RX DMA end padding is disabled */
+ end_padding = 0;
+ } else {
+ switch(MCDI_OUT_DWORD_FIELD(req, GET_RXDP_CONFIG_OUT_DATA,
+ GET_RXDP_CONFIG_OUT_PAD_HOST_LEN)) {
+ case MC_CMD_SET_RXDP_CONFIG_IN_PAD_HOST_64:
+ end_padding = 64;
+ break;
+ case MC_CMD_SET_RXDP_CONFIG_IN_PAD_HOST_128:
+ end_padding = 128;
+ break;
+ case MC_CMD_SET_RXDP_CONFIG_IN_PAD_HOST_256:
+ end_padding = 256;
+ break;
+ default:
+ rc = ENOTSUP;
+ goto fail2;
+ }
+ }
+
+ *end_paddingp = end_padding;
+
+ return (0);
+
+fail2:
+ EFSYS_PROBE(fail2);
+fail1:
+ EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+ return (rc);
+}
+
+ __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;
+ uint32_t end_padding;
+ 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 = ef10_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;
+
+ /* Get the RX DMA end padding alignment configuration */
+ if ((rc = efx_mcdi_get_rxdp_config(enp, &end_padding)) != 0)
+ goto fail10;
+ encp->enc_rx_buf_align_end = end_padding;
+
+ /* 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 fail11;
+ 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 fail12;
+
+ /* 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);
+
+fail12:
+ EFSYS_PROBE(fail12);
+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_flash.h b/sys/dev/sfxge/common/siena_flash.h
index 48ddfac..143a14e 100644
--- a/sys/dev/sfxge/common/siena_flash.h
+++ b/sys/dev/sfxge/common/siena_flash.h
@@ -115,14 +115,14 @@ typedef struct siena_mc_boot_hdr_s { /* GENERATED BY scripts/genfwdef */
efx_word_t checksum; /* of whole header area + firmware image */
efx_word_t firmware_version_d;
efx_byte_t mcfw_subtype;
- efx_byte_t reserved_a[1]; /* (set to 0) */
+ efx_byte_t generation; /* Valid for medford, SBZ for earlier chips */
efx_dword_t firmware_text_offset; /* offset to firmware .text */
efx_dword_t firmware_text_size; /* length of firmware .text, in bytes */
efx_dword_t firmware_data_offset; /* offset to firmware .data */
efx_dword_t firmware_data_size; /* length of firmware .data, in bytes */
efx_byte_t spi_rate; /* SPI rate for reading image, 0 is BootROM default */
efx_byte_t spi_phase_adj; /* SPI SDO/SCL phase adjustment, 0 is default (no adj) */
- efx_word_t reserved_b[1]; /* (set to 0) */
+ efx_word_t xpm_sector; /* The sector that contains the key, or 0xffff if unsigned (medford) SBZ (earlier) */
efx_dword_t reserved_c[7]; /* (set to 0) */
} siena_mc_boot_hdr_t;
diff --git a/sys/dev/sfxge/common/siena_impl.h b/sys/dev/sfxge/common/siena_impl.h
index 639ac6b..4c80cd6 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,39 +151,10 @@ 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);
-extern __checkReturn efx_rc_t
-siena_nvram_partn_read(
- __in efx_nic_t *enp,
- __in uint32_t partn,
- __in unsigned int offset,
- __out_bcount(size) caddr_t data,
- __in size_t size);
-
-extern __checkReturn efx_rc_t
-siena_nvram_partn_erase(
- __in efx_nic_t *enp,
- __in uint32_t partn,
- __in unsigned int offset,
- __in size_t size);
-
-extern __checkReturn efx_rc_t
-siena_nvram_partn_write(
- __in efx_nic_t *enp,
- __in uint32_t partn,
- __in unsigned int offset,
- __out_bcount(size) caddr_t data,
- __in size_t size);
-
extern void
siena_nvram_partn_unlock(
__in efx_nic_t *enp,
@@ -215,67 +181,69 @@ 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,
__out uint32_t *subtypep);
extern __checkReturn efx_rc_t
-siena_nvram_get_version(
+siena_nvram_type_to_partn(
__in efx_nic_t *enp,
__in efx_nvram_type_t type,
- __out uint32_t *subtypep,
- __out_ecount(4) uint16_t version[4]);
+ __out uint32_t *partnp);
extern __checkReturn efx_rc_t
-siena_nvram_rw_start(
+siena_nvram_partn_size(
__in efx_nic_t *enp,
- __in efx_nvram_type_t type,
- __out size_t *pref_chunkp);
+ __in uint32_t partn,
+ __out size_t *sizep);
extern __checkReturn efx_rc_t
-siena_nvram_read_chunk(
+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);
+
+extern __checkReturn efx_rc_t
+siena_nvram_partn_read(
+ __in efx_nic_t *enp,
+ __in uint32_t partn,
__in unsigned int offset,
__out_bcount(size) caddr_t data,
__in size_t size);
-extern __checkReturn efx_rc_t
-siena_nvram_erase(
+extern __checkReturn efx_rc_t
+siena_nvram_partn_erase(
__in efx_nic_t *enp,
- __in efx_nvram_type_t type);
+ __in uint32_t partn,
+ __in unsigned int offset,
+ __in size_t size);
extern __checkReturn efx_rc_t
-siena_nvram_write_chunk(
+siena_nvram_partn_write(
__in efx_nic_t *enp,
- __in efx_nvram_type_t type,
+ __in uint32_t partn,
__in unsigned int offset,
- __in_bcount(size) caddr_t data,
+ __out_bcount(size) caddr_t data,
__in size_t size);
extern void
-siena_nvram_rw_finish(
+siena_nvram_partn_rw_finish(
__in efx_nic_t *enp,
- __in efx_nvram_type_t type);
+ __in uint32_t partn);
extern __checkReturn efx_rc_t
-siena_nvram_set_version(
+siena_nvram_partn_get_version(
__in efx_nic_t *enp,
- __in efx_nvram_type_t type,
- __in_ecount(4) uint16_t version[4]);
+ __in uint32_t partn,
+ __out uint32_t *subtypep,
+ __out_ecount(4) uint16_t version[4]);
extern __checkReturn efx_rc_t
-siena_nvram_type_to_partn(
+siena_nvram_partn_set_version(
__in efx_nic_t *enp,
- __in efx_nvram_type_t type,
- __out uint32_t *partnp);
+ __in uint32_t partn,
+ __in_ecount(4) uint16_t version[4]);
#endif /* EFSYS_OPT_NVRAM */
diff --git a/sys/dev/sfxge/common/siena_mcdi.c b/sys/dev/sfxge/common/siena_mcdi.c
index f3af2bf6f..4fb2b6c 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 70e7b5d..59e1283 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 8f107b4..9708e0c 100644
--- a/sys/dev/sfxge/common/siena_nvram.c
+++ b/sys/dev/sfxge/common/siena_nvram.c
@@ -99,8 +99,8 @@ siena_nvram_partn_read(
while (size > 0) {
chunk = MIN(size, SIENA_NVRAM_CHUNK);
- if ((rc = efx_mcdi_nvram_read(enp, partn, offset,
- data, chunk)) != 0) {
+ if ((rc = efx_mcdi_nvram_read(enp, partn, offset, data, chunk,
+ MC_CMD_NVRAM_READ_IN_V2_DEFAULT)) != 0) {
goto fail1;
}
@@ -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) * \
@@ -506,29 +482,25 @@ fail1:
}
__checkReturn efx_rc_t
-siena_nvram_get_version(
+siena_nvram_partn_get_version(
__in efx_nic_t *enp,
- __in efx_nvram_type_t type,
+ __in uint32_t partn,
__out uint32_t *subtypep,
__out_ecount(4) uint16_t version[4])
{
siena_mc_dynamic_config_hdr_t *dcfg;
siena_parttbl_entry_t *entry;
uint32_t dcfg_partn;
- uint32_t partn;
unsigned int i;
efx_rc_t rc;
- if ((rc = siena_nvram_type_to_partn(enp, type, &partn)) != 0)
- goto fail1;
-
if ((1 << partn) & ~enp->en_u.siena.enu_partn_mask) {
rc = ENOTSUP;
- goto fail2;
+ goto fail1;
}
if ((rc = siena_nvram_get_subtype(enp, partn, subtypep)) != 0)
- goto fail3;
+ goto fail2;
/*
* Some partitions are accessible from both ports (for instance BOOTROM)
@@ -537,6 +509,7 @@ siena_nvram_get_version(
*/
version[0] = version[1] = version[2] = version[3] = 0;
for (i = 0; i < EFX_ARRAY_SIZE(siena_parttbl); i++) {
+ siena_mc_fw_version_t *verp;
unsigned int nitems;
uint16_t temp[4];
size_t length;
@@ -559,32 +532,27 @@ siena_nvram_get_version(
if ((rc = siena_nvram_get_dynamic_cfg(enp, dcfg_partn,
B_FALSE, &dcfg, &length)) != 0)
- goto fail4;
+ goto fail3;
nitems = EFX_DWORD_FIELD(dcfg->num_fw_version_items,
EFX_DWORD_0);
if (nitems < entry->partn)
goto done;
- temp[0] = EFX_WORD_FIELD(dcfg->fw_version[partn].version_w,
- EFX_WORD_0);
- temp[1] = EFX_WORD_FIELD(dcfg->fw_version[partn].version_x,
- EFX_WORD_0);
- temp[2] = EFX_WORD_FIELD(dcfg->fw_version[partn].version_y,
- EFX_WORD_0);
- temp[3] = EFX_WORD_FIELD(dcfg->fw_version[partn].version_z,
- EFX_WORD_0);
+ verp = &dcfg->fw_version[partn];
+ temp[0] = EFX_WORD_FIELD(verp->version_w, EFX_WORD_0);
+ temp[1] = EFX_WORD_FIELD(verp->version_x, EFX_WORD_0);
+ temp[2] = EFX_WORD_FIELD(verp->version_y, EFX_WORD_0);
+ temp[3] = EFX_WORD_FIELD(verp->version_z, EFX_WORD_0);
if (memcmp(version, temp, sizeof (temp)) < 0)
memcpy(version, temp, sizeof (temp));
- done:
+done:
EFSYS_KMEM_FREE(enp->en_esip, length, dcfg);
}
return (0);
-fail4:
- EFSYS_PROBE(fail4);
fail3:
EFSYS_PROBE(fail3);
fail2:
@@ -596,111 +564,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);
-
- return (rc);
-}
-
- __checkReturn efx_rc_t
-siena_nvram_read_chunk(
- __in efx_nic_t *enp,
- __in efx_nvram_type_t type,
- __in unsigned int offset,
- __out_bcount(size) caddr_t data,
- __in size_t size)
-{
- 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_read(enp, partn, offset, data, size)) != 0)
- goto fail2;
-
- return (0);
-
-fail2:
- EFSYS_PROBE(fail2);
-fail1:
- EFSYS_PROBE1(fail1, efx_rc_t, rc);
-
- return (rc);
-}
-
- __checkReturn efx_rc_t
-siena_nvram_erase(
- __in efx_nic_t *enp,
- __in efx_nvram_type_t type)
-{
- size_t size;
- 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, &size)) != 0)
- goto fail2;
-
- if ((rc = siena_nvram_partn_erase(enp, partn, 0, size)) != 0)
- goto fail3;
-
- return (0);
-
-fail3:
- EFSYS_PROBE(fail3);
-fail2:
- EFSYS_PROBE(fail2);
-fail1:
- EFSYS_PROBE1(fail1, efx_rc_t, rc);
-
- return (rc);
-}
-
- __checkReturn efx_rc_t
-siena_nvram_write_chunk(
- __in efx_nic_t *enp,
- __in efx_nvram_type_t type,
- __in unsigned int offset,
- __in_bcount(size) caddr_t data,
- __in size_t size)
-{
- 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_write(enp, partn, offset, data, size)) != 0)
- goto fail2;
-
- return (0);
-
-fail2:
- EFSYS_PROBE(fail2);
fail1:
EFSYS_PROBE1(fail1, efx_rc_t, rc);
@@ -708,27 +586,23 @@ fail1:
}
void
-siena_nvram_rw_finish(
+siena_nvram_partn_rw_finish(
__in efx_nic_t *enp,
- __in efx_nvram_type_t type)
+ __in uint32_t partn)
{
- uint32_t partn;
- efx_rc_t rc;
-
- if ((rc = siena_nvram_type_to_partn(enp, type, &partn)) == 0)
- siena_nvram_partn_unlock(enp, partn);
+ siena_nvram_partn_unlock(enp, partn);
}
__checkReturn efx_rc_t
-siena_nvram_set_version(
+siena_nvram_partn_set_version(
__in efx_nic_t *enp,
- __in efx_nvram_type_t type,
+ __in uint32_t partn,
__in_ecount(4) uint16_t version[4])
{
efx_mcdi_iface_t *emip = &(enp->en_mcdi.em_emip);
siena_mc_dynamic_config_hdr_t *dcfg = NULL;
siena_mc_fw_version_t *fwverp;
- uint32_t dcfg_partn, partn;
+ uint32_t dcfg_partn;
size_t dcfg_size;
unsigned int hdr_length;
unsigned int vpd_length;
@@ -741,15 +615,12 @@ siena_nvram_set_version(
size_t length;
efx_rc_t rc;
- if ((rc = siena_nvram_type_to_partn(enp, type, &partn)) != 0)
- goto fail1;
-
dcfg_partn = (emip->emi_port == 1)
? MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0
: MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1;
if ((rc = siena_nvram_partn_size(enp, dcfg_partn, &dcfg_size)) != 0)
- goto fail2;
+ goto fail1;
if ((rc = siena_nvram_partn_lock(enp, dcfg_partn)) != 0)
goto fail2;
diff --git a/sys/dev/sfxge/common/siena_vpd.c b/sys/dev/sfxge/common/siena_vpd.c
index 9a07f91..7a7ce67 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 bea1eba..9cf8f07 100644
--- a/sys/dev/sfxge/sfxge.h
+++ b/sys/dev/sfxge/sfxge.h
@@ -283,7 +283,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 780ed26..6ae5a07 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:
@@ -1852,10 +1940,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 816856a..ce5d3c4 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/sfxge/sfxge_version.h b/sys/dev/sfxge/sfxge_version.h
index 9d93e79..dbc23ba 100644
--- a/sys/dev/sfxge/sfxge_version.h
+++ b/sys/dev/sfxge/sfxge_version.h
@@ -36,6 +36,6 @@
#ifndef _SFXGE_VERSION_H
#define _SFXGE_VERSION_H
-#define SFXGE_VERSION_STRING "v4.5.3.1002"
+#define SFXGE_VERSION_STRING "v4.8.0.1019"
#endif /* _SFXGE_DRIVER_VERSION_H */
diff --git a/sys/dev/uart/uart_bus.h b/sys/dev/uart/uart_bus.h
index 4a2ab91..3422269 100644
--- a/sys/dev/uart/uart_bus.h
+++ b/sys/dev/uart/uart_bus.h
@@ -112,6 +112,7 @@ struct uart_softc {
/* Pulse capturing support (PPS). */
struct pps_state sc_pps;
int sc_pps_mode;
+ sbintime_t sc_pps_captime;
/* Upper layer data. */
void *sc_softih;
diff --git a/sys/dev/uart/uart_core.c b/sys/dev/uart/uart_core.c
index 3da37e0..b9cffe3 100644
--- a/sys/dev/uart/uart_core.c
+++ b/sys/dev/uart/uart_core.c
@@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
#include <dev/uart/uart.h>
#include <dev/uart/uart_bus.h>
#include <dev/uart/uart_cpu.h>
+#include <dev/uart/uart_ppstypes.h>
#include "uart_if.h"
@@ -65,47 +66,47 @@ static MALLOC_DEFINE(M_UART, "UART", "UART driver");
static int uart_poll_freq = UART_POLL_FREQ;
TUNABLE_INT("debug.uart_poll_freq", &uart_poll_freq);
-#define PPS_MODE_DISABLED 0
-#define PPS_MODE_CTS 1
-#define PPS_MODE_DCD 2
-
-static inline int
-uart_pps_signal(int pps_mode)
-{
-
- switch(pps_mode) {
- case PPS_MODE_CTS:
- return (SER_CTS);
- case PPS_MODE_DCD:
- return (SER_DCD);
- }
- return (0);
-}
static inline int
uart_pps_mode_valid(int pps_mode)
{
-
- switch(pps_mode) {
- case PPS_MODE_DISABLED:
- case PPS_MODE_CTS:
- case PPS_MODE_DCD:
- return (true);
+ int opt;
+
+ switch(pps_mode & UART_PPS_SIGNAL_MASK) {
+ case UART_PPS_DISABLED:
+ case UART_PPS_CTS:
+ case UART_PPS_DCD:
+ break;
+ default:
+ return (false);
}
- return (false);
+
+ opt = pps_mode & UART_PPS_OPTION_MASK;
+ if ((opt & ~(UART_PPS_INVERT_PULSE | UART_PPS_NARROW_PULSE)) != 0)
+ return (false);
+
+ return (true);
}
-static const char *
-uart_pps_mode_name(int pps_mode)
+static void
+uart_pps_print_mode(struct uart_softc *sc)
{
- switch(pps_mode) {
- case PPS_MODE_DISABLED:
- return ("disabled");
- case PPS_MODE_CTS:
- return ("CTS");
- case PPS_MODE_DCD:
- return ("DCD");
+
+ device_printf(sc->sc_dev, "PPS capture mode: ");
+ switch(sc->sc_pps_mode) {
+ case UART_PPS_DISABLED:
+ printf("disabled");
+ case UART_PPS_CTS:
+ printf("CTS");
+ case UART_PPS_DCD:
+ printf("DCD");
+ default:
+ printf("invalid");
}
- return ("invalid");
+ if (sc->sc_pps_mode & UART_PPS_INVERT_PULSE)
+ printf("-Inverted");
+ if (sc->sc_pps_mode & UART_PPS_NARROW_PULSE)
+ printf("-NarrowPulse");
+ printf("\n");
}
static int
@@ -126,6 +127,55 @@ uart_pps_mode_sysctl(SYSCTL_HANDLER_ARGS)
}
static void
+uart_pps_process(struct uart_softc *sc, int ser_sig)
+{
+ sbintime_t now;
+ int is_assert, pps_sig;
+
+ /* Which signal is configured as PPS? Early out if none. */
+ switch(sc->sc_pps_mode & UART_PPS_SIGNAL_MASK) {
+ case UART_PPS_CTS:
+ pps_sig = SER_CTS;
+ break;
+ case UART_PPS_DCD:
+ pps_sig = SER_DCD;
+ break;
+ default:
+ return;
+ }
+
+ /* Early out if there is no change in the signal configured as PPS. */
+ if ((ser_sig & SER_DELTA(pps_sig)) == 0)
+ return;
+
+ /*
+ * In narrow-pulse mode we need to synthesize both capture and clear
+ * events from a single "delta occurred" indication from the uart
+ * hardware because the pulse width is too narrow to reliably detect
+ * both edges. However, when the pulse width is close to our interrupt
+ * processing latency we might intermittantly catch both edges. To
+ * guard against generating spurious events when that happens, we use a
+ * separate timer to ensure at least half a second elapses before we
+ * generate another event.
+ */
+ pps_capture(&sc->sc_pps);
+ if (sc->sc_pps_mode & UART_PPS_NARROW_PULSE) {
+ now = getsbinuptime();
+ if (now > sc->sc_pps_captime + 500 * SBT_1MS) {
+ sc->sc_pps_captime = now;
+ pps_event(&sc->sc_pps, PPS_CAPTUREASSERT);
+ pps_event(&sc->sc_pps, PPS_CAPTURECLEAR);
+ }
+ } else {
+ is_assert = ser_sig & pps_sig;
+ if (sc->sc_pps_mode & UART_PPS_INVERT_PULSE)
+ is_assert = !is_assert;
+ pps_event(&sc->sc_pps, is_assert ? PPS_CAPTUREASSERT :
+ PPS_CAPTURECLEAR);
+ }
+}
+
+static void
uart_pps_init(struct uart_softc *sc)
{
struct sysctl_ctx_list *ctx;
@@ -142,23 +192,23 @@ uart_pps_init(struct uart_softc *sc)
* for one specific device.
*/
#ifdef UART_PPS_ON_CTS
- sc->sc_pps_mode = PPS_MODE_CTS;
+ sc->sc_pps_mode = UART_PPS_CTS;
#else
- sc->sc_pps_mode = PPS_MODE_DCD;
+ sc->sc_pps_mode = UART_PPS_DCD;
#endif
TUNABLE_INT_FETCH("hw.uart.pps_mode", &sc->sc_pps_mode);
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "pps_mode",
CTLTYPE_INT | CTLFLAG_RWTUN, sc, 0, uart_pps_mode_sysctl, "I",
- "pulse capturing mode - 0/1/2 - disabled/CTS/DCD");
+ "pulse mode: 0/1/2=disabled/CTS/DCD; "
+ "add 0x10 to invert, 0x20 for narrow pulse");
if (!uart_pps_mode_valid(sc->sc_pps_mode)) {
device_printf(sc->sc_dev,
- "Invalid pps_mode %d configured; disabling PPS capture\n",
+ "Invalid pps_mode 0x%02x configured; disabling PPS capture\n",
sc->sc_pps_mode);
- sc->sc_pps_mode = PPS_MODE_DISABLED;
+ sc->sc_pps_mode = UART_PPS_DISABLED;
} else if (bootverbose) {
- device_printf(sc->sc_dev, "PPS capture mode %d (%s)\n",
- sc->sc_pps_mode, uart_pps_mode_name(sc->sc_pps_mode));
+ uart_pps_print_mode(sc);
}
sc->sc_pps.ppscap = PPS_CAPTUREBOTH;
@@ -302,23 +352,16 @@ static __inline int
uart_intr_sigchg(void *arg)
{
struct uart_softc *sc = arg;
- int new, old, pps_sig, sig;
+ int new, old, sig;
sig = UART_GETSIG(sc);
/*
- * Time pulse counting support. Note that both CTS and DCD are
- * active-low signals. The status bit is high to indicate that
- * the signal on the line is low, which corresponds to a PPS
- * clear event.
+ * Time pulse counting support, invoked whenever the PPS parameters are
+ * currently set to capture either edge of the signal.
*/
if (sc->sc_pps.ppsparam.mode & PPS_CAPTUREBOTH) {
- pps_sig = uart_pps_signal(sc->sc_pps_mode);
- if (sig & SER_DELTA(pps_sig)) {
- pps_capture(&sc->sc_pps);
- pps_event(&sc->sc_pps, (sig & pps_sig) ?
- PPS_CAPTURECLEAR : PPS_CAPTUREASSERT);
- }
+ uart_pps_process(sc, sig);
}
/*
diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c
index 99692e6..67149d6 100644
--- a/sys/dev/uart/uart_dev_ns8250.c
+++ b/sys/dev/uart/uart_dev_ns8250.c
@@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$");
#endif
#include <dev/uart/uart_bus.h>
#include <dev/uart/uart_dev_ns8250.h>
+#include <dev/uart/uart_ppstypes.h>
#include <dev/ic/ns16550.h>
@@ -390,11 +391,40 @@ static struct ofw_compat_data compat_data[] = {
UART_FDT_CLASS_AND_DEVICE(compat_data);
#endif
-#define SIGCHG(c, i, s, d) \
- if (c) { \
- i |= (i & s) ? s : s | d; \
- } else { \
- i = (i & s) ? (i & ~s) | d : i; \
+/* Use token-pasting to form SER_ and MSR_ named constants. */
+#define SER(sig) SER_##sig
+#define SERD(sig) SER_D##sig
+#define MSR(sig) MSR_##sig
+#define MSRD(sig) MSR_D##sig
+
+/*
+ * Detect signal changes using software delta detection. The previous state of
+ * the signals is in 'var' the new hardware state is in 'msr', and 'sig' is the
+ * short name (DCD, CTS, etc) of the signal bit being processed; 'var' gets the
+ * new state of both the signal and the delta bits.
+ */
+#define SIGCHGSW(var, msr, sig) \
+ if ((msr) & MSR(sig)) { \
+ if ((var & SER(sig)) == 0) \
+ var |= SERD(sig) | SER(sig); \
+ } else { \
+ if ((var & SER(sig)) != 0) \
+ var = SERD(sig) | (var & ~SER(sig)); \
+ }
+
+/*
+ * Detect signal changes using the hardware msr delta bits. This is currently
+ * used only when PPS timing information is being captured using the "narrow
+ * pulse" option. With a narrow PPS pulse the signal may not still be asserted
+ * by time the interrupt handler is invoked. The hardware will latch the fact
+ * that it changed in the delta bits.
+ */
+#define SIGCHGHW(var, msr, sig) \
+ if ((msr) & MSRD(sig)) { \
+ if (((msr) & MSR(sig)) != 0) \
+ var |= SERD(sig) | SER(sig); \
+ else \
+ var = SERD(sig) | (var & ~SER(sig)); \
}
int
@@ -521,21 +551,37 @@ ns8250_bus_flush(struct uart_softc *sc, int what)
int
ns8250_bus_getsig(struct uart_softc *sc)
{
- uint32_t new, old, sig;
+ uint32_t old, sig;
uint8_t msr;
+ /*
+ * The delta bits are reputed to be broken on some hardware, so use
+ * software delta detection by default. Use the hardware delta bits
+ * when capturing PPS pulses which are too narrow for software detection
+ * to see the edges. Hardware delta for RI doesn't work like the
+ * others, so always use software for it. Other threads may be changing
+ * other (non-MSR) bits in sc_hwsig, so loop until it can succesfully
+ * update without other changes happening. Note that the SIGCHGxx()
+ * macros carefully preserve the delta bits when we have to loop several
+ * times and a signal transitions between iterations.
+ */
do {
old = sc->sc_hwsig;
sig = old;
uart_lock(sc->sc_hwmtx);
msr = uart_getreg(&sc->sc_bas, REG_MSR);
uart_unlock(sc->sc_hwmtx);
- SIGCHG(msr & MSR_DSR, sig, SER_DSR, SER_DDSR);
- SIGCHG(msr & MSR_CTS, sig, SER_CTS, SER_DCTS);
- SIGCHG(msr & MSR_DCD, sig, SER_DCD, SER_DDCD);
- SIGCHG(msr & MSR_RI, sig, SER_RI, SER_DRI);
- new = sig & ~SER_MASK_DELTA;
- } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
+ if (sc->sc_pps_mode & UART_PPS_NARROW_PULSE) {
+ SIGCHGHW(sig, msr, DSR);
+ SIGCHGHW(sig, msr, CTS);
+ SIGCHGHW(sig, msr, DCD);
+ } else {
+ SIGCHGSW(sig, msr, DSR);
+ SIGCHGSW(sig, msr, CTS);
+ SIGCHGSW(sig, msr, DCD);
+ }
+ SIGCHGSW(sig, msr, RI);
+ } while (!atomic_cmpset_32(&sc->sc_hwsig, old, sig & ~SER_MASK_DELTA));
return (sig);
}
@@ -889,12 +935,10 @@ ns8250_bus_setsig(struct uart_softc *sc, int sig)
old = sc->sc_hwsig;
new = old;
if (sig & SER_DDTR) {
- SIGCHG(sig & SER_DTR, new, SER_DTR,
- SER_DDTR);
+ new = (new & ~SER_DTR) | (sig & (SER_DTR | SER_DDTR));
}
if (sig & SER_DRTS) {
- SIGCHG(sig & SER_RTS, new, SER_RTS,
- SER_DRTS);
+ new = (new & ~SER_RTS) | (sig & (SER_RTS | SER_DRTS));
}
} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
uart_lock(sc->sc_hwmtx);
diff --git a/sys/dev/uart/uart_ppstypes.h b/sys/dev/uart/uart_ppstypes.h
new file mode 100644
index 0000000..142d0f1
--- /dev/null
+++ b/sys/dev/uart/uart_ppstypes.h
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2015 Ian Lepore
+ * 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 ``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 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 _DEV_UART_PPSTYPES_H_
+#define _DEV_UART_PPSTYPES_H_
+
+/*
+ * These constants are shared by several drivers including uart and usb_serial.
+ */
+
+#define UART_PPS_SIGNAL_MASK 0x0f
+#define UART_PPS_OPTION_MASK 0xf0
+
+#define UART_PPS_DISABLED 0x00
+#define UART_PPS_CTS 0x01
+#define UART_PPS_DCD 0x02
+
+#define UART_PPS_INVERT_PULSE 0x10
+#define UART_PPS_NARROW_PULSE 0x20
+
+#endif /* _DEV_UART_PPSTYPES_H_ */
diff --git a/sys/dev/usb/serial/usb_serial.c b/sys/dev/usb/serial/usb_serial.c
index 499d5c1..5bc23b8 100644
--- a/sys/dev/usb/serial/usb_serial.c
+++ b/sys/dev/usb/serial/usb_serial.c
@@ -81,6 +81,8 @@ __FBSDID("$FreeBSD$");
#include <sys/cons.h>
#include <sys/kdb.h>
+#include <dev/uart/uart_ppstypes.h>
+
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
@@ -99,7 +101,8 @@ static SYSCTL_NODE(_hw_usb, OID_AUTO, ucom, CTLFLAG_RW, 0, "USB ucom");
static int ucom_pps_mode;
SYSCTL_INT(_hw_usb_ucom, OID_AUTO, pps_mode, CTLFLAG_RWTUN,
- &ucom_pps_mode, 0, "pulse capturing mode - 0/1/2 - disabled/CTS/DCD");
+ &ucom_pps_mode, 0,
+ "pulse capture mode: 0/1/2=disabled/CTS/DCD; add 0x10 to invert");
#ifdef USB_DEBUG
static int ucom_debug = 0;
@@ -1074,10 +1077,12 @@ ucom_cfg_status_change(struct usb_proc_msg *_task)
(struct ucom_cfg_task *)_task;
struct ucom_softc *sc = task->sc;
struct tty *tp;
+ int onoff;
uint8_t new_msr;
uint8_t new_lsr;
uint8_t msr_delta;
uint8_t lsr_delta;
+ uint8_t pps_signal;
tp = sc->sc_tty;
@@ -1107,35 +1112,33 @@ ucom_cfg_status_change(struct usb_proc_msg *_task)
sc->sc_lsr = new_lsr;
/*
- * Time pulse counting support. Note that both CTS and DCD are
- * active-low signals. The status bit is high to indicate that
- * the signal on the line is low, which corresponds to a PPS
- * clear event.
+ * Time pulse counting support.
*/
- switch(ucom_pps_mode) {
- case 1:
- if ((sc->sc_pps.ppsparam.mode & PPS_CAPTUREBOTH) &&
- (msr_delta & SER_CTS)) {
- pps_capture(&sc->sc_pps);
- pps_event(&sc->sc_pps, (sc->sc_msr & SER_CTS) ?
- PPS_CAPTURECLEAR : PPS_CAPTUREASSERT);
- }
+ switch(ucom_pps_mode & UART_PPS_SIGNAL_MASK) {
+ case UART_PPS_CTS:
+ pps_signal = SER_CTS;
break;
- case 2:
- if ((sc->sc_pps.ppsparam.mode & PPS_CAPTUREBOTH) &&
- (msr_delta & SER_DCD)) {
- pps_capture(&sc->sc_pps);
- pps_event(&sc->sc_pps, (sc->sc_msr & SER_DCD) ?
- PPS_CAPTURECLEAR : PPS_CAPTUREASSERT);
- }
+ case UART_PPS_DCD:
+ pps_signal = SER_DCD;
break;
default:
+ pps_signal = 0;
break;
}
+ if ((sc->sc_pps.ppsparam.mode & PPS_CAPTUREBOTH) &&
+ (msr_delta & pps_signal)) {
+ pps_capture(&sc->sc_pps);
+ onoff = (sc->sc_msr & pps_signal) ? 1 : 0;
+ if (ucom_pps_mode & UART_PPS_INVERT_PULSE)
+ onoff = !onoff;
+ pps_event(&sc->sc_pps, onoff ? PPS_CAPTUREASSERT :
+ PPS_CAPTURECLEAR);
+ }
+
if (msr_delta & SER_DCD) {
- int onoff = (sc->sc_msr & SER_DCD) ? 1 : 0;
+ onoff = (sc->sc_msr & SER_DCD) ? 1 : 0;
DPRINTF("DCD changed to %d\n", onoff);
diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c
index ba56e56..a45e07d 100644
--- a/sys/fs/devfs/devfs_vnops.c
+++ b/sys/fs/devfs/devfs_vnops.c
@@ -146,7 +146,7 @@ devfs_get_cdevpriv(void **datap)
}
int
-devfs_set_cdevpriv(void *priv, cdevpriv_dtr_t priv_dtr)
+devfs_set_cdevpriv(void *priv, d_priv_dtor_t *priv_dtr)
{
struct file *fp;
struct cdev_priv *cdp;
@@ -239,18 +239,18 @@ devfs_populate_vp(struct vnode *vp)
if (DEVFS_DMP_DROP(dmp)) {
sx_xunlock(&dmp->dm_lock);
devfs_unmount_final(dmp);
- return (EBADF);
+ return (ERESTART);
}
if ((vp->v_iflag & VI_DOOMED) != 0) {
sx_xunlock(&dmp->dm_lock);
- return (EBADF);
+ return (ERESTART);
}
de = vp->v_data;
KASSERT(de != NULL,
("devfs_populate_vp: vp->v_data == NULL but vnode not doomed"));
if ((de->de_flags & DE_DOOMED) != 0) {
sx_xunlock(&dmp->dm_lock);
- return (EBADF);
+ return (ERESTART);
}
return (0);
diff --git a/sys/fs/smbfs/smbfs_smb.c b/sys/fs/smbfs/smbfs_smb.c
index ada84c2..c5b8a68 100644
--- a/sys/fs/smbfs/smbfs_smb.c
+++ b/sys/fs/smbfs/smbfs_smb.c
@@ -333,18 +333,18 @@ smbfs_smb_flush(struct smbnode *np, struct smb_cred *scred)
}
int
-smbfs_smb_setfsize(struct smbnode *np, int newsize, struct smb_cred *scred)
+smbfs_smb_setfsize(struct smbnode *np, int64_t newsize, struct smb_cred *scred)
{
struct smb_share *ssp = np->n_mount->sm_share;
struct smb_rq *rqp;
struct mbchain *mbp;
int error;
- if (!smbfs_smb_seteof(np, (int64_t) newsize, scred)) {
+ if (!smbfs_smb_seteof(np, newsize, scred)) {
np->n_flag |= NFLUSHWIRE;
return (0);
}
-
+ /* XXX: We should use SMB_COM_WRITE_ANDX to support large offsets */
error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE, scred, &rqp);
if (error)
return (error);
@@ -352,7 +352,7 @@ smbfs_smb_setfsize(struct smbnode *np, int newsize, struct smb_cred *scred)
smb_rq_wstart(rqp);
mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM);
mb_put_uint16le(mbp, 0);
- mb_put_uint32le(mbp, newsize);
+ mb_put_uint32le(mbp, (uint32_t)newsize);
mb_put_uint16le(mbp, 0);
smb_rq_wend(rqp);
smb_rq_bstart(rqp);
diff --git a/sys/fs/smbfs/smbfs_subr.h b/sys/fs/smbfs/smbfs_subr.h
index d22df08..4ee143c 100644
--- a/sys/fs/smbfs/smbfs_subr.h
+++ b/sys/fs/smbfs/smbfs_subr.h
@@ -128,7 +128,8 @@ int smbfs_smb_lock(struct smbnode *np, int op, caddr_t id,
off_t start, off_t end, struct smb_cred *scred);
int smbfs_smb_statfs(struct smb_share *ssp, struct statfs *sbp,
struct smb_cred *scred);
-int smbfs_smb_setfsize(struct smbnode *np, int newsize, struct smb_cred *scred);
+int smbfs_smb_setfsize(struct smbnode *np, int64_t newsize,
+ struct smb_cred *scred);
int smbfs_smb_query_info(struct smbnode *np, const char *name, int len,
struct smbfattr *fap, struct smb_cred *scred);
diff --git a/sys/fs/smbfs/smbfs_vnops.c b/sys/fs/smbfs/smbfs_vnops.c
index 8ea1198..c78ceb2 100644
--- a/sys/fs/smbfs/smbfs_vnops.c
+++ b/sys/fs/smbfs/smbfs_vnops.c
@@ -358,7 +358,8 @@ smbfs_setattr(ap)
doclose = 1;
}
if (error == 0)
- error = smbfs_smb_setfsize(np, vap->va_size, scred);
+ error = smbfs_smb_setfsize(np,
+ (int64_t)vap->va_size, scred);
if (doclose)
smbfs_smb_close(ssp, np->n_fid, NULL, scred);
if (error) {
diff --git a/sys/geom/geom_disk.c b/sys/geom/geom_disk.c
index 1a879f7..5d7965e 100644
--- a/sys/geom/geom_disk.c
+++ b/sys/geom/geom_disk.c
@@ -581,6 +581,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/geom/multipath/g_multipath.c b/sys/geom/multipath/g_multipath.c
index 0953d18..6644532 100644
--- a/sys/geom/multipath/g_multipath.c
+++ b/sys/geom/multipath/g_multipath.c
@@ -107,8 +107,9 @@ struct g_class g_multipath_class = {
#define MP_NEW 0x00000004
#define MP_POSTED 0x00000008
#define MP_BAD (MP_FAIL | MP_LOST | MP_NEW)
-#define MP_IDLE 0x00000010
-#define MP_IDLE_MASK 0xfffffff0
+#define MP_WITHER 0x00000010
+#define MP_IDLE 0x00000020
+#define MP_IDLE_MASK 0xffffffe0
static int
g_multipath_good(struct g_geom *gp)
@@ -204,6 +205,7 @@ g_mpd(void *arg, int flags __unused)
g_access(cp, -cp->acr, -cp->acw, -cp->ace);
if (w > 0 && cp->provider != NULL &&
(cp->provider->geom->flags & G_GEOM_WITHER) == 0) {
+ cp->index |= MP_WITHER;
g_post_event(g_mpd, cp, M_WAITOK, NULL);
return;
}
@@ -467,23 +469,37 @@ g_multipath_access(struct g_provider *pp, int dr, int dw, int de)
gp = pp->geom;
+ /* Error used if we have no valid consumers. */
+ error = ENXIO;
+
LIST_FOREACH(cp, &gp->consumer, consumer) {
+ if (cp->index & MP_WITHER)
+ continue;
+
error = g_access(cp, dr, dw, de);
if (error) {
badcp = cp;
goto fail;
}
}
+
+ if (error != 0)
+ return (error);
+
sc = gp->softc;
sc->sc_opened += dr + dw + de;
if (sc->sc_stopping && sc->sc_opened == 0)
g_multipath_destroy(gp);
+
return (0);
fail:
LIST_FOREACH(cp, &gp->consumer, consumer) {
if (cp == badcp)
break;
+ if (cp->index & MP_WITHER)
+ continue;
+
(void) g_access(cp, -dr, -dw, -de);
}
return (error);
diff --git a/sys/i386/i386/elf_machdep.c b/sys/i386/i386/elf_machdep.c
index 81d6e35..29a8885 100644
--- a/sys/i386/i386/elf_machdep.c
+++ b/sys/i386/i386/elf_machdep.c
@@ -89,6 +89,7 @@ struct sysentvec elf32_freebsd_sysvec = {
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
+ .sv_trap = NULL,
};
INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec);
diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
index 36aeca5..f55900c 100644
--- a/sys/i386/i386/machdep.c
+++ b/sys/i386/i386/machdep.c
@@ -3190,10 +3190,11 @@ init386(first)
} else {
metadata_missing = 1;
}
- if (envmode == 1)
- kern_envp = static_env;
- else if (bootinfo.bi_envp)
- kern_envp = (caddr_t)bootinfo.bi_envp + KERNBASE;
+
+ if (bootinfo.bi_envp)
+ init_static_kenv((caddr_t)bootinfo.bi_envp + KERNBASE, 0);
+ else
+ init_static_kenv(NULL, 0);
/* Init basic tunables, hz etc */
init_param1();
diff --git a/sys/i386/ibcs2/ibcs2_sysvec.c b/sys/i386/ibcs2/ibcs2_sysvec.c
index 16507ee..372e5ea 100644
--- a/sys/i386/ibcs2/ibcs2_sysvec.c
+++ b/sys/i386/ibcs2/ibcs2_sysvec.c
@@ -90,6 +90,7 @@ struct sysentvec ibcs2_svr3_sysvec = {
.sv_syscallnames = NULL,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
+ .sv_trap = NULL,
};
static int
diff --git a/sys/i386/include/metadata.h b/sys/i386/include/metadata.h
index 73c9207..98d0272 100644
--- a/sys/i386/include/metadata.h
+++ b/sys/i386/include/metadata.h
@@ -1,36 +1,6 @@
/*-
- * Copyright (c) 2003 Peter Wemm <peter@FreeBSD.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
+ * This file is in the public domain.
*/
+/* $FreeBSD$ */
-#ifndef _MACHINE_METADATA_H_
-#define _MACHINE_METADATA_H_
-
-#define MODINFOMD_SMAP 0x1001
-#define MODINFOMD_SMAP_XATTR 0x1002
-#define MODINFOMD_DTBP 0x1003
-
-#endif /* !_MACHINE_METADATA_H_ */
+#include <x86/metadata.h>
diff --git a/sys/i386/include/pcb.h b/sys/i386/include/pcb.h
index 4bfd603..558565b 100644
--- a/sys/i386/include/pcb.h
+++ b/sys/i386/include/pcb.h
@@ -44,13 +44,17 @@
#endif
#include <machine/npx.h>
+/*
+ * NB: The fields marked with (*) are used by kernel debuggers. Their
+ * ABI should be preserved.
+ */
struct pcb {
- int pcb_edi;
- int pcb_esi;
- int pcb_ebp;
- int pcb_esp;
- int pcb_ebx;
- int pcb_eip;
+ int pcb_edi; /* (*) */
+ int pcb_esi; /* (*) */
+ int pcb_ebp; /* (*) */
+ int pcb_esp; /* (*) */
+ int pcb_ebx; /* (*) */
+ int pcb_eip; /* (*) */
struct segment_descriptor pcb_fsd;
struct segment_descriptor pcb_gsd;
int pcb_ds;
diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c
index 7c980ce..df5441b 100644
--- a/sys/i386/linux/linux_sysvec.c
+++ b/sys/i386/linux/linux_sysvec.c
@@ -988,6 +988,7 @@ struct sysentvec linux_sysvec = {
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = linux_schedtail,
.sv_thread_detach = linux_thread_detach,
+ .sv_trap = NULL,
};
INIT_SYSENTVEC(aout_sysvec, &linux_sysvec);
@@ -1027,6 +1028,7 @@ struct sysentvec elf_linux_sysvec = {
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = linux_schedtail,
.sv_thread_detach = linux_thread_detach,
+ .sv_trap = NULL,
};
static void
diff --git a/sys/kern/imgact_aout.c b/sys/kern/imgact_aout.c
index edd5f5f..553dc04 100644
--- a/sys/kern/imgact_aout.c
+++ b/sys/kern/imgact_aout.c
@@ -100,6 +100,7 @@ struct sysentvec aout_sysvec = {
.sv_syscallnames = syscallnames,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
+ .sv_trap = NULL,
};
#elif defined(__amd64__)
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index 6cb5017..201680a 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -415,6 +415,7 @@ struct sysentvec null_sysvec = {
.sv_syscallnames = NULL,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
+ .sv_trap = NULL,
};
/*
diff --git a/sys/kern/kern_environment.c b/sys/kern/kern_environment.c
index ff453cb..05c4f62 100644
--- a/sys/kern/kern_environment.c
+++ b/sys/kern/kern_environment.c
@@ -210,12 +210,44 @@ done:
return (error);
}
+/*
+ * Populate the initial kernel environment.
+ *
+ * This is called very early in MD startup, either to provide a copy of the
+ * environment obtained from a boot loader, or to provide an empty buffer into
+ * which MD code can store an initial environment using kern_setenv() calls.
+ *
+ * If the global envmode is 1, the environment is initialized from the global
+ * static_env[], regardless of the arguments passed. This implements the env
+ * keyword described in config(5). In this case env_pos is set to env_len,
+ * causing kern_setenv() to return -1 (if len > 0) or panic (if len == 0) until
+ * the dynamic environment is available. The envmode and static_env variables
+ * are defined in env.c which is generated by config(8).
+ *
+ * If len is non-zero, the caller is providing an empty buffer. The caller will
+ * subsequently use kern_setenv() to add up to len bytes of initial environment
+ * before the dynamic environment is available.
+ *
+ * If len is zero, the caller is providing a pre-loaded buffer containing
+ * environment strings. Additional strings cannot be added until the dynamic
+ * environment is available. The memory pointed to must remain stable at least
+ * until sysinit runs init_dynamic_kenv(). If no initial environment is
+ * available from the boot loader, passing a NULL pointer allows the static_env
+ * to be installed if it is configured.
+ */
void
init_static_kenv(char *buf, size_t len)
{
- kern_envp = buf;
- env_len = len;
- env_pos = 0;
+
+ if (envmode == 1) {
+ kern_envp = static_env;
+ env_len = len;
+ env_pos = len;
+ } else {
+ kern_envp = buf;
+ env_len = len;
+ env_pos = 0;
+ }
}
/*
diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c
index e379f5f..78eab87 100644
--- a/sys/kern/kern_linker.c
+++ b/sys/kern/kern_linker.c
@@ -71,6 +71,12 @@ SYSCTL_INT(_debug, OID_AUTO, kld_debug, CTLFLAG_RW | CTLFLAG_TUN,
TUNABLE_INT("debug.kld_debug", &kld_debug);
#endif
+/* These variables are used by kernel debuggers to enumerate loaded files. */
+const int kld_off_address = offsetof(struct linker_file, address);
+const int kld_off_filename = offsetof(struct linker_file, filename);
+const int kld_off_pathname = offsetof(struct linker_file, pathname);
+const int kld_off_next = offsetof(struct linker_file, link.tqe_next);
+
/*
* static char *linker_search_path(const char *name, struct mod_depend
* *verinfo);
diff --git a/sys/kern/kern_mib.c b/sys/kern/kern_mib.c
index 0307791..ccecbc9 100644
--- a/sys/kern/kern_mib.c
+++ b/sys/kern/kern_mib.c
@@ -574,6 +574,11 @@ SYSCTL_INT(_debug_sizeof, OID_AUTO, buf, CTLFLAG_RD,
SYSCTL_INT(_debug_sizeof, OID_AUTO, kinfo_proc, CTLFLAG_RD,
SYSCTL_NULL_INT_PTR, sizeof(struct kinfo_proc), "sizeof(struct kinfo_proc)");
+/* Used by kernel debuggers. */
+const int pcb_size = sizeof(struct pcb);
+SYSCTL_INT(_debug_sizeof, OID_AUTO, pcb, CTLFLAG_RD,
+ SYSCTL_NULL_INT_PTR, sizeof(struct pcb), "sizeof(struct pcb)");
+
/* XXX compatibility, remove for 6.0 */
#include <sys/imgact.h>
#include <sys/imgact_elf.h>
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index c9b7ca3..6b60840 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -139,6 +139,21 @@ struct sx proctree_lock;
struct mtx ppeers_lock;
uma_zone_t proc_zone;
+/*
+ * The offset of various fields in struct proc and struct thread.
+ * These are used by kernel debuggers to enumerate kernel threads and
+ * processes.
+ */
+const int proc_off_p_pid = offsetof(struct proc, p_pid);
+const int proc_off_p_comm = offsetof(struct proc, p_comm);
+const int proc_off_p_list = offsetof(struct proc, p_list);
+const int proc_off_p_threads = offsetof(struct proc, p_threads);
+const int thread_off_td_tid = offsetof(struct thread, td_tid);
+const int thread_off_td_name = offsetof(struct thread, td_name);
+const int thread_off_td_oncpu = offsetof(struct thread, td_oncpu);
+const int thread_off_td_pcb = offsetof(struct thread, td_pcb);
+const int thread_off_td_plist = offsetof(struct thread, td_plist);
+
int kstack_pages = KSTACK_PAGES;
SYSCTL_INT(_kern, OID_AUTO, kstack_pages, CTLFLAG_RD, &kstack_pages, 0,
"Kernel stack size in pages");
diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c
index 96f68609ca..c85813b 100644
--- a/sys/kern/kern_thread.c
+++ b/sys/kern/kern_thread.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sched.h>
#include <sys/sleepqueue.h>
#include <sys/selinfo.h>
+#include <sys/syscallsubr.h>
#include <sys/sysent.h>
#include <sys/turnstile.h>
#include <sys/ktr.h>
@@ -885,7 +886,6 @@ thread_suspend_check(int return_instead)
*/
if ((p->p_flag & P_SINGLE_EXIT) && (p->p_singlethread != td)) {
PROC_UNLOCK(p);
- tidhash_remove(td);
/*
* Allow Linux emulation layer to do some work
@@ -893,13 +893,8 @@ thread_suspend_check(int return_instead)
*/
if (__predict_false(p->p_sysent->sv_thread_detach != NULL))
(p->p_sysent->sv_thread_detach)(td);
-
- PROC_LOCK(p);
- tdsigcleanup(td);
- umtx_thread_exit(td);
- PROC_SLOCK(p);
- thread_stopped(p);
- thread_exit();
+ kern_thr_exit(td);
+ panic("stopped thread did not exit");
}
PROC_SLOCK(p);
diff --git a/sys/kern/makesyscalls.sh b/sys/kern/makesyscalls.sh
index 8be4896..1d3af65 100644
--- a/sys/kern/makesyscalls.sh
+++ b/sys/kern/makesyscalls.sh
@@ -410,6 +410,10 @@ s/\$//g
printf("\t\tuarg[%d] = (intptr_t) p->%s; /* %s */\n", \
i - 1, \
argname[i], arg) > systrace
+ else if (arg == "union l_semun")
+ printf("\t\tuarg[%d] = p->%s.buf; /* %s */\n", \
+ i - 1, \
+ argname[i], arg) > systrace
else if (substr(arg, 1, 1) == "u" || arg == "size_t")
printf("\t\tuarg[%d] = p->%s; /* %s */\n", \
i - 1, \
diff --git a/sys/kern/subr_busdma_bufalloc.c b/sys/kern/subr_busdma_bufalloc.c
index b0b1ba8..c8980e1 100644
--- a/sys/kern/subr_busdma_bufalloc.c
+++ b/sys/kern/subr_busdma_bufalloc.c
@@ -94,8 +94,8 @@ busdma_bufalloc_create(const char *name, bus_size_t minimum_alignment,
for (i = 0, bz = ba->buf_zones, cursize = ba->min_size;
i < nitems(ba->buf_zones) && cursize <= MAX_ZONE_BUFSIZE;
++i, ++bz, cursize <<= 1) {
- snprintf(bz->name, sizeof(bz->name), "dma %.10s %lu",
- name, cursize);
+ snprintf(bz->name, sizeof(bz->name), "dma %.10s %ju",
+ name, (uintmax_t)cursize);
bz->size = cursize;
bz->umazone = uma_zcreate(bz->name, bz->size,
NULL, NULL, NULL, NULL, bz->size - 1, zcreate_flags);
diff --git a/sys/mips/include/elf.h b/sys/mips/include/elf.h
index c1e792b..a33c090 100644
--- a/sys/mips/include/elf.h
+++ b/sys/mips/include/elf.h
@@ -238,39 +238,10 @@ __ElfType(Auxinfo);
#define R_MIPS_COPY 126
#define R_MIPS_JUMP_SLOT 127
-/* mips dynamic tags */
-
-#define DT_MIPS_RLD_VERSION 0x70000001
-#define DT_MIPS_TIME_STAMP 0x70000002
-#define DT_MIPS_ICHECKSUM 0x70000003
-#define DT_MIPS_IVERSION 0x70000004
-#define DT_MIPS_FLAGS 0x70000005
-#define DT_MIPS_BASE_ADDRESS 0x70000006
-#define DT_MIPS_CONFLICT 0x70000008
-#define DT_MIPS_LIBLIST 0x70000009
-#define DT_MIPS_CONFLICTNO 0x7000000b
-#define DT_MIPS_LOCAL_GOTNO 0x7000000a /* number of local got ents */
-#define DT_MIPS_LIBLISTNO 0x70000010
-#define DT_MIPS_SYMTABNO 0x70000011 /* number of .dynsym entries */
-#define DT_MIPS_UNREFEXTNO 0x70000012
-#define DT_MIPS_GOTSYM 0x70000013 /* first dynamic sym in got */
-#define DT_MIPS_HIPAGENO 0x70000014
-#define DT_MIPS_RLD_MAP 0x70000016 /* address of loader map */
-#define DT_MIPS_PLTGOT 0x70000032
-#define DT_MIPS_RWPLT 0x70000034
-
/*
* ELF Flags
*/
-#define EF_MIPS_PIC 0x00000002 /* Contains PIC code */
-#define EF_MIPS_CPIC 0x00000004 /* STD PIC calling sequence */
-#define EF_MIPS_ABI2 0x00000020 /* N32 */
-
-#define EF_MIPS_ARCH_ASE 0x0f000000 /* Architectural extensions */
-#define EF_MIPS_ARCH_MDMX 0x08000000 /* MDMX multimedia extension */
-#define EF_MIPS_ARCH_M16 0x04000000 /* MIPS-16 ISA extensions */
-#define EF_MIPS_ARCH 0xf0000000 /* Architecture field */
#define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code */
#define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code */
#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code */
diff --git a/sys/mips/mips/elf_machdep.c b/sys/mips/mips/elf_machdep.c
index 626b5f8..db50a73 100644
--- a/sys/mips/mips/elf_machdep.c
+++ b/sys/mips/mips/elf_machdep.c
@@ -84,6 +84,7 @@ struct sysentvec elf64_freebsd_sysvec = {
.sv_syscallnames = syscallnames,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
+ .sv_trap = NULL,
};
static Elf64_Brandinfo freebsd_brand_info = {
@@ -141,6 +142,7 @@ struct sysentvec elf32_freebsd_sysvec = {
.sv_syscallnames = syscallnames,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
+ .sv_trap = NULL,
};
static Elf32_Brandinfo freebsd_brand_info = {
diff --git a/sys/mips/mips/freebsd32_machdep.c b/sys/mips/mips/freebsd32_machdep.c
index 5303420..87fda42 100644
--- a/sys/mips/mips/freebsd32_machdep.c
+++ b/sys/mips/mips/freebsd32_machdep.c
@@ -107,6 +107,7 @@ struct sysentvec elf32_freebsd_sysvec = {
.sv_syscallnames = freebsd32_syscallnames,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
+ .sv_trap = NULL,
};
INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec);
diff --git a/sys/modules/dtrace/Makefile b/sys/modules/dtrace/Makefile
index 1b12371..9f3c993 100644
--- a/sys/modules/dtrace/Makefile
+++ b/sys/modules/dtrace/Makefile
@@ -16,7 +16,10 @@ SUBDIR= dtmalloc \
systrace
.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386"
-SUBDIR+= fasttrap fbt systrace_linux32
+SUBDIR+= fasttrap fbt systrace_linux
+.endif
+.if ${MACHINE_CPUARCH} == "amd64"
+SUBDIR+= systrace_linux32
.endif
.if ${MACHINE_CPUARCH} == "powerpc"
SUBDIR+= fbt fasttrap
diff --git a/sys/modules/dtrace/systrace_linux/Makefile b/sys/modules/dtrace/systrace_linux/Makefile
new file mode 100644
index 0000000..1cf5e31
--- /dev/null
+++ b/sys/modules/dtrace/systrace_linux/Makefile
@@ -0,0 +1,18 @@
+# $FreeBSD$
+
+SYSDIR?= ${.CURDIR}/../../..
+
+.PATH: ${SYSDIR}/cddl/dev/systrace
+
+KMOD= systrace_linux
+
+SRCS= systrace.c
+SRCS+= vnode_if.h
+
+CFLAGS+= -I${SYSDIR}/cddl/compat/opensolaris \
+ -I${SYSDIR}/cddl/contrib/opensolaris/uts/common \
+ -I${SYSDIR} -DLINUX_SYSTRACE
+
+.include <bsd.kmod.mk>
+
+CFLAGS+= -include ${SYSDIR}/cddl/compat/opensolaris/sys/debug_compat.h
diff --git a/sys/modules/dtrace/systrace_linux32/Makefile b/sys/modules/dtrace/systrace_linux32/Makefile
index a2bfc81..3183482 100644
--- a/sys/modules/dtrace/systrace_linux32/Makefile
+++ b/sys/modules/dtrace/systrace_linux32/Makefile
@@ -2,18 +2,14 @@
.PATH: ${.CURDIR}/../../../cddl/dev/systrace
-.if ${MACHINE} == "amd64"
KMOD= systrace_linux32
-.else
-KMOD= systrace_linux
-.endif
SRCS= systrace.c
SRCS+= vnode_if.h
CFLAGS+= -I${.CURDIR}/../../../cddl/compat/opensolaris \
-I${.CURDIR}/../../../cddl/contrib/opensolaris/uts/common \
- -I${.CURDIR}/../../.. -DLINUX_SYSTRACE
+ -I${.CURDIR}/../../.. -DLINUX32_SYSTRACE
.include <bsd.kmod.mk>
diff --git a/sys/modules/sfxge/Makefile b/sys/modules/sfxge/Makefile
index c444152..ba4108b 100644
--- a/sys/modules/sfxge/Makefile
+++ b/sys/modules/sfxge/Makefile
@@ -16,7 +16,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/bpf.c b/sys/net/bpf.c
index 914dad6..15ab5aa 100644
--- a/sys/net/bpf.c
+++ b/sys/net/bpf.c
@@ -2500,7 +2500,7 @@ bpfattach2(struct ifnet *ifp, u_int dlt, u_int hdrlen, struct bpf_if **driverp)
bp->bif_hdrlen = hdrlen;
- if (bootverbose)
+ if (bootverbose && IS_DEFAULT_VNET(curvnet))
if_printf(ifp, "bpf attached\n");
}
diff --git a/sys/net/if.c b/sys/net/if.c
index efaece7..288d944 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -176,7 +176,7 @@ static int if_getgroup(struct ifgroupreq *, struct ifnet *);
static int if_getgroupmembers(struct ifgroupreq *);
static void if_delgroups(struct ifnet *);
static void if_attach_internal(struct ifnet *, int, struct if_clone *);
-static void if_detach_internal(struct ifnet *, int, struct if_clone **);
+static int if_detach_internal(struct ifnet *, int, struct if_clone **);
#ifdef INET6
/*
@@ -894,7 +894,7 @@ if_detach(struct ifnet *ifp)
CURVNET_RESTORE();
}
-static void
+static int
if_detach_internal(struct ifnet *ifp, int vmove, struct if_clone **ifcp)
{
struct ifaddr *ifa;
@@ -917,11 +917,19 @@ if_detach_internal(struct ifnet *ifp, int vmove, struct if_clone **ifcp)
#endif
IFNET_WUNLOCK();
if (!found) {
+ /*
+ * While we would want to panic here, we cannot
+ * guarantee that the interface is indeed still on
+ * the list given we don't hold locks all the way.
+ */
+ return (ENOENT);
+#if 0
if (vmove)
panic("%s: ifp=%p not on the ifnet tailq %p",
__func__, ifp, &V_ifnet);
else
return; /* XXX this should panic as well? */
+#endif
}
/* Check if this is a cloned interface or not. */
@@ -1019,6 +1027,8 @@ if_detach_internal(struct ifnet *ifp, int vmove, struct if_clone **ifcp)
(*dp->dom_ifdetach)(ifp,
ifp->if_afdata[dp->dom_family]);
}
+
+ return (0);
}
#ifdef VIMAGE
@@ -1034,12 +1044,16 @@ if_vmove(struct ifnet *ifp, struct vnet *new_vnet)
{
u_short idx;
struct if_clone *ifc;
+ int rc;
/*
* Detach from current vnet, but preserve LLADDR info, do not
* mark as dead etc. so that the ifnet can be reattached later.
+ * If we cannot find it, we lost the race to someone else.
*/
- if_detach_internal(ifp, 1, &ifc);
+ rc = if_detach_internal(ifp, 1, &ifc);
+ if (rc != 0)
+ return;
/*
* Unlink the ifnet from ifindex_table[] in current vnet, and shrink
diff --git a/sys/net/if_llatbl.c b/sys/net/if_llatbl.c
index 84ea6c6..11e415d 100644
--- a/sys/net/if_llatbl.c
+++ b/sys/net/if_llatbl.c
@@ -62,11 +62,10 @@ __FBSDID("$FreeBSD$");
MALLOC_DEFINE(M_LLTABLE, "lltable", "link level address tables");
-static VNET_DEFINE(SLIST_HEAD(, lltable), lltables);
+static VNET_DEFINE(SLIST_HEAD(, lltable), lltables) =
+ SLIST_HEAD_INITIALIZER(lltables);
#define V_lltables VNET(lltables)
-static void vnet_lltable_init(void);
-
struct rwlock lltable_rwlock;
RW_SYSINIT(lltable_rwlock, &lltable_rwlock, "lltable_rwlock");
@@ -367,15 +366,6 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
return (error);
}
-static void
-vnet_lltable_init()
-{
-
- SLIST_INIT(&V_lltables);
-}
-VNET_SYSINIT(vnet_lltable_init, SI_SUB_PSEUDO, SI_ORDER_FIRST,
- vnet_lltable_init, NULL);
-
#ifdef DDB
struct llentry_sa {
struct llentry base;
diff --git a/sys/net/sff8436.h b/sys/net/sff8436.h
index 97abe10..3399cce 100644
--- a/sys/net/sff8436.h
+++ b/sys/net/sff8436.h
@@ -131,7 +131,7 @@ enum {
SFF_8436_CONNECTOR = 130, /* Connector type (Table 32) */
SFF_8436_TRANS_START = 131, /* Electric or Optical Compatibility
* (Table 33) */
- SFF_8436_CODE_E1040G = 131, /* 10/40G Ethernet Compliance Code */
+ SFF_8436_CODE_E1040100G = 131, /* 10/40/100G Ethernet Compliance Code */
SFF_8436_CODE_SONET = 132, /* SONET Compliance codes */
SFF_8436_CODE_SATA = 133, /* SAS/SATA compliance codes */
SFF_8436_CODE_E1G = 134, /* Gigabit Ethernet Compliant codes */
diff --git a/sys/netinet/sctp.h b/sys/netinet/sctp.h
index 8a033d8..784c1d4 100644
--- a/sys/netinet/sctp.h
+++ b/sys/netinet/sctp.h
@@ -388,33 +388,32 @@ struct sctp_error_cause {
} SCTP_PACKED;
struct sctp_error_invalid_stream {
- struct sctp_error_cause cause; /* code=SCTP_ERROR_INVALID_STREAM */
+ struct sctp_error_cause cause; /* code=SCTP_CAUSE_INVALID_STREAM */
uint16_t stream_id; /* stream id of the DATA in error */
uint16_t reserved;
} SCTP_PACKED;
struct sctp_error_missing_param {
- struct sctp_error_cause cause; /* code=SCTP_ERROR_MISSING_PARAM */
+ struct sctp_error_cause cause; /* code=SCTP_CAUSE_MISSING_PARAM */
uint32_t num_missing_params; /* number of missing parameters */
- /* uint16_t param_type's follow */
+ uint16_t type[];
} SCTP_PACKED;
struct sctp_error_stale_cookie {
- struct sctp_error_cause cause; /* code=SCTP_ERROR_STALE_COOKIE */
+ struct sctp_error_cause cause; /* code=SCTP_CAUSE_STALE_COOKIE */
uint32_t stale_time; /* time in usec of staleness */
} SCTP_PACKED;
struct sctp_error_out_of_resource {
- struct sctp_error_cause cause; /* code=SCTP_ERROR_OUT_OF_RESOURCES */
+ struct sctp_error_cause cause; /* code=SCTP_CAUSE_OUT_OF_RESOURCES */
} SCTP_PACKED;
struct sctp_error_unresolv_addr {
- struct sctp_error_cause cause; /* code=SCTP_ERROR_UNRESOLVABLE_ADDR */
-
+ struct sctp_error_cause cause; /* code=SCTP_CAUSE_UNRESOLVABLE_ADDR */
} SCTP_PACKED;
struct sctp_error_unrecognized_chunk {
- struct sctp_error_cause cause; /* code=SCTP_ERROR_UNRECOG_CHUNK */
+ struct sctp_error_cause cause; /* code=SCTP_CAUSE_UNRECOG_CHUNK */
struct sctp_chunkhdr ch;/* header from chunk in error */
} SCTP_PACKED;
@@ -423,6 +422,11 @@ struct sctp_error_no_user_data {
uint32_t tsn; /* TSN of the empty data chunk */
} SCTP_PACKED;
+struct sctp_error_auth_invalid_hmac {
+ struct sctp_error_cause cause; /* code=SCTP_CAUSE_UNSUPPORTED_HMACID */
+ uint16_t hmac_id;
+} SCTP_PACKED;
+
/*
* Main SCTP chunk types we place these here so natd and f/w's in user land
* can find them.
diff --git a/sys/netinet/sctp_asconf.c b/sys/netinet/sctp_asconf.c
index a64e7f9..540cc65 100644
--- a/sys/netinet/sctp_asconf.c
+++ b/sys/netinet/sctp_asconf.c
@@ -1680,8 +1680,14 @@ sctp_handle_asconf_ack(struct mbuf *m, int offset,
* abort the asoc, since someone probably just hijacked us...
*/
if (serial_num == (asoc->asconf_seq_out + 1)) {
+ struct mbuf *op_err;
+ char msg[SCTP_DIAG_INFO_LEN];
+
SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf_ack: got unexpected next serial number! Aborting asoc!\n");
- sctp_abort_an_association(stcb->sctp_ep, stcb, NULL, SCTP_SO_NOT_LOCKED);
+ snprintf(msg, sizeof(msg), "Never sent serial number %8.8x",
+ serial_num);
+ op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
+ sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
*abort_no_unlock = 1;
return;
}
diff --git a/sys/netinet/sctp_auth.c b/sys/netinet/sctp_auth.c
index 7c2e194..07dbf8b 100644
--- a/sys/netinet/sctp_auth.c
+++ b/sys/netinet/sctp_auth.c
@@ -558,7 +558,7 @@ sctp_auth_key_acquire(struct sctp_tcb *stcb, uint16_t key_id)
atomic_add_int(&skey->refcount, 1);
SCTPDBG(SCTP_DEBUG_AUTH2,
"%s: stcb %p key %u refcount acquire to %d\n",
- __FUNCTION__, (void *)stcb, key_id, skey->refcount);
+ __func__, (void *)stcb, key_id, skey->refcount);
}
}
@@ -578,7 +578,7 @@ sctp_auth_key_release(struct sctp_tcb *stcb, uint16_t key_id, int so_locked
if (skey) {
SCTPDBG(SCTP_DEBUG_AUTH2,
"%s: stcb %p key %u refcount release to %d\n",
- __FUNCTION__, (void *)stcb, key_id, skey->refcount);
+ __func__, (void *)stcb, key_id, skey->refcount);
/* see if a notification should be generated */
if ((skey->refcount <= 2) && (skey->deactivated)) {
@@ -587,7 +587,7 @@ sctp_auth_key_release(struct sctp_tcb *stcb, uint16_t key_id, int so_locked
key_id, 0, so_locked);
SCTPDBG(SCTP_DEBUG_AUTH2,
"%s: stcb %p key %u no longer used, %d\n",
- __FUNCTION__, (void *)stcb, key_id, skey->refcount);
+ __func__, (void *)stcb, key_id, skey->refcount);
}
sctp_free_sharedkey(skey);
}
@@ -1651,8 +1651,8 @@ sctp_handle_auth(struct sctp_tcb *stcb, struct sctp_auth_chunk *auth,
/* is the indicated HMAC supported? */
if (!sctp_auth_is_supported_hmac(stcb->asoc.local_hmacs, hmac_id)) {
- struct mbuf *m_err;
- struct sctp_auth_invalid_hmac *err;
+ struct mbuf *op_err;
+ struct sctp_error_auth_invalid_hmac *cause;
SCTP_STAT_INCR(sctps_recvivalhmacid);
SCTPDBG(SCTP_DEBUG_AUTH1,
@@ -1662,20 +1662,19 @@ sctp_handle_auth(struct sctp_tcb *stcb, struct sctp_auth_chunk *auth,
* report this in an Error Chunk: Unsupported HMAC
* Identifier
*/
- m_err = sctp_get_mbuf_for_msg(sizeof(*err), 0, M_NOWAIT,
- 1, MT_HEADER);
- if (m_err != NULL) {
+ op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_error_auth_invalid_hmac),
+ 0, M_NOWAIT, 1, MT_HEADER);
+ if (op_err != NULL) {
/* pre-reserve some space */
- SCTP_BUF_RESV_UF(m_err, sizeof(struct sctp_chunkhdr));
+ SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr));
/* fill in the error */
- err = mtod(m_err, struct sctp_auth_invalid_hmac *);
- bzero(err, sizeof(*err));
- err->ph.param_type = htons(SCTP_CAUSE_UNSUPPORTED_HMACID);
- err->ph.param_length = htons(sizeof(*err));
- err->hmac_id = ntohs(hmac_id);
- SCTP_BUF_LEN(m_err) = sizeof(*err);
+ cause = mtod(op_err, struct sctp_error_auth_invalid_hmac *);
+ cause->cause.code = htons(SCTP_CAUSE_UNSUPPORTED_HMACID);
+ cause->cause.length = htons(sizeof(struct sctp_error_auth_invalid_hmac));
+ cause->hmac_id = ntohs(hmac_id);
+ SCTP_BUF_LEN(op_err) = sizeof(struct sctp_error_auth_invalid_hmac);
/* queue it */
- sctp_queue_op_err(stcb, m_err);
+ sctp_queue_op_err(stcb, op_err);
}
return (-1);
}
diff --git a/sys/netinet/sctp_constants.h b/sys/netinet/sctp_constants.h
index d90bd25..a26bc5b 100644
--- a/sys/netinet/sctp_constants.h
+++ b/sys/netinet/sctp_constants.h
@@ -66,6 +66,8 @@ __FBSDID("$FreeBSD$");
*/
#define SCTP_LARGEST_INIT_ACCEPTED (65535 - 2048)
+/* Largest length of a chunk */
+#define SCTP_MAX_CHUNK_LENGTH 0xffff
/* Number of addresses where we just skip the counting */
#define SCTP_COUNT_LIMIT 40
@@ -458,7 +460,7 @@ __FBSDID("$FreeBSD$");
/*
- * SCTP states for internal state machine XXX (should match "user" values)
+ * SCTP states for internal state machine
*/
#define SCTP_STATE_EMPTY 0x0000
#define SCTP_STATE_INUSE 0x0001
@@ -612,10 +614,6 @@ __FBSDID("$FreeBSD$");
/* 30 seconds + RTO (in ms) */
#define SCTP_HB_DEFAULT_MSEC 30000
-/* Max time I will wait for Shutdown to complete */
-#define SCTP_DEF_MAX_SHUTDOWN_SEC 180
-
-
/*
* This is how long a secret lives, NOT how long a cookie lives how many
* ticks the current secret will live.
diff --git a/sys/netinet/sctp_header.h b/sys/netinet/sctp_header.h
index f322e04..dc05b3d 100644
--- a/sys/netinet/sctp_header.h
+++ b/sys/netinet/sctp_header.h
@@ -202,34 +202,6 @@ struct sctp_state_cookie { /* this is our definition... */
*/
} SCTP_PACKED;
-
-/* Used for NAT state error cause */
-struct sctp_missing_nat_state {
- uint16_t cause;
- uint16_t length;
- uint8_t data[];
-} SCTP_PACKED;
-
-
-struct sctp_inv_mandatory_param {
- uint16_t cause;
- uint16_t length;
- uint32_t num_param;
- uint16_t param;
- /*
- * We include this to 0 it since only a missing cookie will cause
- * this error.
- */
- uint16_t resv;
-} SCTP_PACKED;
-
-struct sctp_unresolv_addr {
- uint16_t cause;
- uint16_t length;
- uint16_t addr_type;
- uint16_t reserved; /* Only one invalid addr type */
-} SCTP_PACKED;
-
/* state cookie parameter */
struct sctp_state_cookie_param {
struct sctp_paramhdr ph;
@@ -370,28 +342,11 @@ struct sctp_shutdown_complete_chunk {
struct sctp_chunkhdr ch;
} SCTP_PACKED;
-/* Oper error holding a stale cookie */
-struct sctp_stale_cookie_msg {
- struct sctp_paramhdr ph;/* really an error cause */
- uint32_t time_usec;
-} SCTP_PACKED;
-
struct sctp_adaptation_layer_indication {
struct sctp_paramhdr ph;
uint32_t indication;
} SCTP_PACKED;
-struct sctp_cookie_while_shutting_down {
- struct sctphdr sh;
- struct sctp_chunkhdr ch;
- struct sctp_paramhdr ph;/* really an error cause */
-} SCTP_PACKED;
-
-struct sctp_shutdown_complete_msg {
- struct sctphdr sh;
- struct sctp_shutdown_complete_chunk shut_cmp;
-} SCTP_PACKED;
-
/*
* draft-ietf-tsvwg-addip-sctp
*/
@@ -554,12 +509,6 @@ struct sctp_auth_chunk {
uint8_t hmac[];
} SCTP_PACKED;
-struct sctp_auth_invalid_hmac {
- struct sctp_paramhdr ph;
- uint16_t hmac_id;
- uint16_t padding;
-} SCTP_PACKED;
-
/*
* we pre-reserve enough room for a ECNE or CWR AND a SACK with no missing
* pieces. If ENCE is missing we could have a couple of blocks. This way we
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c
index 50a6628..75c1ac5 100644
--- a/sys/netinet/sctp_indata.c
+++ b/sys/netinet/sctp_indata.c
@@ -223,9 +223,9 @@ sctp_build_ctl_nchunk(struct sctp_inpcb *inp, struct sctp_sndrcvinfo *sinfo)
}
seinfo = (struct sctp_extrcvinfo *)sinfo;
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO) &&
- (seinfo->sreinfo_next_flags & SCTP_NEXT_MSG_AVAIL)) {
+ (seinfo->serinfo_next_flags & SCTP_NEXT_MSG_AVAIL)) {
provide_nxt = 1;
- len += CMSG_SPACE(sizeof(struct sctp_rcvinfo));
+ len += CMSG_SPACE(sizeof(struct sctp_nxtinfo));
} else {
provide_nxt = 0;
}
@@ -276,20 +276,20 @@ sctp_build_ctl_nchunk(struct sctp_inpcb *inp, struct sctp_sndrcvinfo *sinfo)
cmh->cmsg_len = CMSG_LEN(sizeof(struct sctp_nxtinfo));
cmh->cmsg_type = SCTP_NXTINFO;
nxtinfo = (struct sctp_nxtinfo *)CMSG_DATA(cmh);
- nxtinfo->nxt_sid = seinfo->sreinfo_next_stream;
+ nxtinfo->nxt_sid = seinfo->serinfo_next_stream;
nxtinfo->nxt_flags = 0;
- if (seinfo->sreinfo_next_flags & SCTP_NEXT_MSG_IS_UNORDERED) {
+ if (seinfo->serinfo_next_flags & SCTP_NEXT_MSG_IS_UNORDERED) {
nxtinfo->nxt_flags |= SCTP_UNORDERED;
}
- if (seinfo->sreinfo_next_flags & SCTP_NEXT_MSG_IS_NOTIFICATION) {
+ if (seinfo->serinfo_next_flags & SCTP_NEXT_MSG_IS_NOTIFICATION) {
nxtinfo->nxt_flags |= SCTP_NOTIFICATION;
}
- if (seinfo->sreinfo_next_flags & SCTP_NEXT_MSG_ISCOMPLETE) {
+ if (seinfo->serinfo_next_flags & SCTP_NEXT_MSG_ISCOMPLETE) {
nxtinfo->nxt_flags |= SCTP_COMPLETE;
}
- nxtinfo->nxt_ppid = seinfo->sreinfo_next_ppid;
- nxtinfo->nxt_length = seinfo->sreinfo_next_length;
- nxtinfo->nxt_assoc_id = seinfo->sreinfo_next_aid;
+ nxtinfo->nxt_ppid = seinfo->serinfo_next_ppid;
+ nxtinfo->nxt_length = seinfo->serinfo_next_length;
+ nxtinfo->nxt_assoc_id = seinfo->serinfo_next_aid;
cmh = (struct cmsghdr *)((caddr_t)cmh + CMSG_SPACE(sizeof(struct sctp_nxtinfo)));
SCTP_BUF_LEN(ret) += CMSG_SPACE(sizeof(struct sctp_nxtinfo));
}
@@ -578,10 +578,10 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb, struct sctp_association *asoc,
sctp_log_strm_del(control, NULL, SCTP_STR_LOG_FROM_INTO_STRD);
}
SCTPDBG(SCTP_DEBUG_INDATA1,
- "queue to stream called for ssn:%u lastdel:%u nxt:%u\n",
- (uint32_t) control->sinfo_stream,
- (uint32_t) strm->last_sequence_delivered,
- (uint32_t) nxt_todel);
+ "queue to stream called for sid:%u ssn:%u tsn:%u lastdel:%u nxt:%u\n",
+ (uint32_t) control->sinfo_stream, (uint32_t) control->sinfo_ssn,
+ (uint32_t) control->sinfo_tsn,
+ (uint32_t) strm->last_sequence_delivered, (uint32_t) nxt_todel);
if (SCTP_SSN_GE(strm->last_sequence_delivered, control->sinfo_ssn)) {
/* The incoming sseq is behind where we last delivered? */
SCTPDBG(SCTP_DEBUG_INDATA1, "Duplicate S-SEQ:%d delivered:%d from peer, Abort association\n",
@@ -602,6 +602,20 @@ protocol_error:
return;
}
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+ struct socket *so;
+
+ so = SCTP_INP_SO(stcb->sctp_ep);
+ atomic_add_int(&stcb->asoc.refcnt, 1);
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_SOCKET_LOCK(so, 1);
+ SCTP_TCB_LOCK(stcb);
+ atomic_subtract_int(&stcb->asoc.refcnt, 1);
+ if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
+ SCTP_SOCKET_UNLOCK(so, 1);
+ return;
+ }
+#endif
if (nxt_todel == control->sinfo_ssn) {
/* can be delivered right away? */
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_STR_LOGGING_ENABLE) {
@@ -617,7 +631,7 @@ protocol_error:
sctp_add_to_readq(stcb->sctp_ep, stcb,
control,
&stcb->sctp_socket->so_rcv, 1,
- SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
+ SCTP_READ_LOCK_NOT_HELD, SCTP_SO_LOCKED);
TAILQ_FOREACH_SAFE(control, &strm->inqueue, next, at) {
/* all delivered */
nxt_todel = strm->last_sequence_delivered + 1;
@@ -641,7 +655,7 @@ protocol_error:
control,
&stcb->sctp_socket->so_rcv, 1,
SCTP_READ_LOCK_NOT_HELD,
- SCTP_SO_NOT_LOCKED);
+ SCTP_SO_LOCKED);
continue;
}
break;
@@ -653,6 +667,9 @@ protocol_error:
* to put it on the queue.
*/
if (SCTP_TSN_GE(asoc->cumulative_tsn, control->sinfo_tsn)) {
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+ SCTP_SOCKET_UNLOCK(so, 1);
+#endif
goto protocol_error;
}
if (TAILQ_EMPTY(&strm->inqueue)) {
@@ -699,6 +716,9 @@ protocol_error:
control->whoFrom = NULL;
}
sctp_free_a_readq(stcb, control);
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+ SCTP_SOCKET_UNLOCK(so, 1);
+#endif
return;
} else {
if (TAILQ_NEXT(at, next) == NULL) {
@@ -718,6 +738,9 @@ protocol_error:
}
}
}
+#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+ SCTP_SOCKET_UNLOCK(so, 1);
+#endif
}
/*
@@ -1403,30 +1426,25 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
}
strmno = ntohs(ch->dp.stream_id);
if (strmno >= asoc->streamincnt) {
- struct sctp_paramhdr *phdr;
- struct mbuf *mb;
+ struct sctp_error_invalid_stream *cause;
- mb = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) * 2),
+ op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_error_invalid_stream),
0, M_NOWAIT, 1, MT_DATA);
- if (mb != NULL) {
+ if (op_err != NULL) {
/* add some space up front so prepend will work well */
- SCTP_BUF_RESV_UF(mb, sizeof(struct sctp_chunkhdr));
- phdr = mtod(mb, struct sctp_paramhdr *);
+ SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr));
+ cause = mtod(op_err, struct sctp_error_invalid_stream *);
/*
* Error causes are just param's and this one has
* two back to back phdr, one with the error type
* and size, the other with the streamid and a rsvd
*/
- SCTP_BUF_LEN(mb) = (sizeof(struct sctp_paramhdr) * 2);
- phdr->param_type = htons(SCTP_CAUSE_INVALID_STREAM);
- phdr->param_length =
- htons(sizeof(struct sctp_paramhdr) * 2);
- phdr++;
- /* We insert the stream in the type field */
- phdr->param_type = ch->dp.stream_id;
- /* And set the length to 0 for the rsvd field */
- phdr->param_length = 0;
- sctp_queue_op_err(stcb, mb);
+ SCTP_BUF_LEN(op_err) = sizeof(struct sctp_error_invalid_stream);
+ cause->cause.code = htons(SCTP_CAUSE_INVALID_STREAM);
+ cause->cause.length = htons(sizeof(struct sctp_error_invalid_stream));
+ cause->stream_id = ch->dp.stream_id;
+ cause->reserved = htons(0);
+ sctp_queue_op_err(stcb, op_err);
}
SCTP_STAT_INCR(sctps_badsid);
SCTP_TCB_LOCK_ASSERT(stcb);
@@ -1886,6 +1904,7 @@ finish_express_del:
sctp_reset_in_stream(stcb, liste->number_entries, liste->list_of_streams);
TAILQ_REMOVE(&asoc->resetHead, liste, next_resp);
+ sctp_send_deferred_reset_response(stcb, liste, SCTP_STREAM_RESET_RESULT_PERFORMED);
SCTP_FREE(liste, SCTP_M_STRESET);
/* sa_ignore FREED_MEMORY */
liste = TAILQ_FIRST(&asoc->resetHead);
@@ -2288,11 +2307,8 @@ doit_again:
int
sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
- struct sockaddr *src, struct sockaddr *dst,
- struct sctphdr *sh, struct sctp_inpcb *inp,
- struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t * high_tsn,
- uint8_t mflowtype, uint32_t mflowid,
- uint32_t vrf_id, uint16_t port)
+ struct sctp_inpcb *inp, struct sctp_tcb *stcb,
+ struct sctp_nets *net, uint32_t * high_tsn)
{
struct sctp_data_chunk *ch, chunk_buf;
struct sctp_association *asoc;
@@ -2384,10 +2400,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
chk_length);
op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_21;
- sctp_abort_association(inp, stcb, m, iphlen,
- src, dst, sh, op_err,
- mflowtype, mflowid,
- vrf_id, port);
+ sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED);
return (2);
}
if ((size_t)chk_length == sizeof(struct sctp_data_chunk)) {
@@ -2399,10 +2412,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
op_err = sctp_generate_no_user_data_cause(ch->dp.tsn);
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_22;
- sctp_abort_association(inp, stcb, m, iphlen,
- src, dst, sh, op_err,
- mflowtype, mflowid,
- vrf_id, port);
+ sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED);
return (2);
}
#ifdef SCTP_AUDITING_ENABLED
@@ -2464,14 +2474,12 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
*/
if (SCTP_BASE_SYSCTL(sctp_strict_data_order)) {
struct mbuf *op_err;
+ char msg[SCTP_DIAG_INFO_LEN];
- op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, "");
- sctp_abort_association(inp, stcb,
- m, iphlen,
- src, dst,
- sh, op_err,
- mflowtype, mflowid,
- vrf_id, port);
+ snprintf(msg, sizeof(msg), "DATA chunk followed by chunk of type %2.2x",
+ ch->ch.chunk_type);
+ op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
+ sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED);
return (2);
}
break;
@@ -2479,34 +2487,21 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
/* unknown chunk type, use bit rules */
if (ch->ch.chunk_type & 0x40) {
/* Add a error report to the queue */
- struct mbuf *merr;
- struct sctp_paramhdr *phd;
-
- merr = sctp_get_mbuf_for_msg(sizeof(*phd), 0, M_NOWAIT, 1, MT_DATA);
- if (merr) {
- phd = mtod(merr, struct sctp_paramhdr *);
- /*
- * We cheat and use param
- * type since we did not
- * bother to define a error
- * cause struct. They are
- * the same basic format
- * with different names.
- */
- phd->param_type =
- htons(SCTP_CAUSE_UNRECOG_CHUNK);
- phd->param_length =
- htons(chk_length + sizeof(*phd));
- SCTP_BUF_LEN(merr) = sizeof(*phd);
- SCTP_BUF_NEXT(merr) = SCTP_M_COPYM(m, *offset, chk_length, M_NOWAIT);
- if (SCTP_BUF_NEXT(merr)) {
- if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(merr), SCTP_SIZE32(chk_length) - chk_length, NULL) == NULL) {
- sctp_m_freem(merr);
- } else {
- sctp_queue_op_err(stcb, merr);
- }
+ struct mbuf *op_err;
+ struct sctp_gen_error_cause *cause;
+
+ op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_gen_error_cause),
+ 0, M_NOWAIT, 1, MT_DATA);
+ if (op_err != NULL) {
+ cause = mtod(op_err, struct sctp_gen_error_cause *);
+ cause->code = htons(SCTP_CAUSE_UNRECOG_CHUNK);
+ cause->length = htons(chk_length + sizeof(struct sctp_gen_error_cause));
+ SCTP_BUF_LEN(op_err) = sizeof(struct sctp_gen_error_cause);
+ SCTP_BUF_NEXT(op_err) = SCTP_M_COPYM(m, *offset, chk_length, M_NOWAIT);
+ if (SCTP_BUF_NEXT(op_err) != NULL) {
+ sctp_queue_op_err(stcb, op_err);
} else {
- sctp_m_freem(merr);
+ sctp_m_freem(op_err);
}
}
}
@@ -2768,6 +2763,11 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1
panic("No chunks on the queues for sid %u.", tp1->rec.data.stream_number);
#endif
}
+ if ((stcb->asoc.strmout[tp1->rec.data.stream_number].chunks_on_queues == 0) &&
+ (stcb->asoc.strmout[tp1->rec.data.stream_number].state == SCTP_STREAM_RESET_PENDING) &&
+ TAILQ_EMPTY(&stcb->asoc.strmout[tp1->rec.data.stream_number].outqueue)) {
+ stcb->asoc.trigger_reset = 1;
+ }
tp1->sent = SCTP_DATAGRAM_NR_ACKED;
if (tp1->data) {
/*
@@ -3741,6 +3741,11 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
#endif
}
}
+ if ((asoc->strmout[tp1->rec.data.stream_number].chunks_on_queues == 0) &&
+ (asoc->strmout[tp1->rec.data.stream_number].state == SCTP_STREAM_RESET_PENDING) &&
+ TAILQ_EMPTY(&asoc->strmout[tp1->rec.data.stream_number].outqueue)) {
+ asoc->trigger_reset = 1;
+ }
TAILQ_REMOVE(&asoc->sent_queue, tp1, sctp_next);
if (tp1->data) {
/* sa_ignore NO_NULL_CHK */
@@ -3989,6 +3994,7 @@ again:
op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_26;
sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
+ return;
} else {
struct sctp_nets *netp;
@@ -4466,6 +4472,11 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
#endif
}
}
+ if ((asoc->strmout[tp1->rec.data.stream_number].chunks_on_queues == 0) &&
+ (asoc->strmout[tp1->rec.data.stream_number].state == SCTP_STREAM_RESET_PENDING) &&
+ TAILQ_EMPTY(&asoc->strmout[tp1->rec.data.stream_number].outqueue)) {
+ asoc->trigger_reset = 1;
+ }
TAILQ_REMOVE(&asoc->sent_queue, tp1, sctp_next);
if (PR_SCTP_ENABLED(tp1->flags)) {
if (asoc->pr_sctp_cnt != 0)
diff --git a/sys/netinet/sctp_indata.h b/sys/netinet/sctp_indata.h
index 79a86e2..94cd49c 100644
--- a/sys/netinet/sctp_indata.h
+++ b/sys/netinet/sctp_indata.h
@@ -112,12 +112,8 @@ void
int
sctp_process_data(struct mbuf **, int, int *, int,
- struct sockaddr *src, struct sockaddr *dst,
- struct sctphdr *,
struct sctp_inpcb *, struct sctp_tcb *,
- struct sctp_nets *, uint32_t *,
- uint8_t, uint32_t,
- uint32_t, uint16_t);
+ struct sctp_nets *, uint32_t *);
void sctp_slide_mapping_arrays(struct sctp_tcb *stcb);
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index 0986293..3b50590 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -357,14 +357,17 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb)
sctp_free_a_strmoq(stcb, sp, SCTP_SO_NOT_LOCKED);
/* sa_ignore FREED_MEMORY */
}
+ outs->state = SCTP_STREAM_CLOSED;
}
}
/* cut back the count */
asoc->pre_open_streams = newcnt;
}
SCTP_TCB_SEND_UNLOCK(stcb);
- asoc->strm_realoutsize = asoc->streamoutcnt = asoc->pre_open_streams;
-
+ asoc->streamoutcnt = asoc->pre_open_streams;
+ for (i = 0; i < asoc->streamoutcnt; i++) {
+ asoc->strmout[i].state = SCTP_STREAM_OPEN;
+ }
/* EY - nr_sack: initialize highest tsn in nr_mapping_array */
asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map;
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) {
@@ -518,7 +521,6 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
/* calculate the RTO */
net->RTO = sctp_calculate_rto(stcb, asoc, net, &asoc->time_entered, sctp_align_safe_nocopy,
SCTP_RTT_FROM_NON_DATA);
-
retval = sctp_send_cookie_echo(m, offset, stcb, net);
if (retval < 0) {
/*
@@ -527,25 +529,21 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
* abandon the peer, its broke.
*/
if (retval == -3) {
+ uint16_t len;
+
+ len = (uint16_t) (sizeof(struct sctp_error_missing_param) + sizeof(uint16_t));
/* We abort with an error of missing mandatory param */
- op_err = sctp_generate_cause(SCTP_CAUSE_MISSING_PARAM, "");
- if (op_err) {
- /*
- * Expand beyond to include the mandatory
- * param cookie
- */
- struct sctp_inv_mandatory_param *mp;
+ op_err = sctp_get_mbuf_for_msg(len, 0, M_NOWAIT, 1, MT_DATA);
+ if (op_err != NULL) {
+ struct sctp_error_missing_param *cause;
- SCTP_BUF_LEN(op_err) =
- sizeof(struct sctp_inv_mandatory_param);
- mp = mtod(op_err,
- struct sctp_inv_mandatory_param *);
+ SCTP_BUF_LEN(op_err) = len;
+ cause = mtod(op_err, struct sctp_error_missing_param *);
/* Subtract the reserved param */
- mp->length =
- htons(sizeof(struct sctp_inv_mandatory_param) - 2);
- mp->num_param = htonl(1);
- mp->param = htons(SCTP_STATE_COOKIE);
- mp->resv = 0;
+ cause->cause.code = htons(SCTP_CAUSE_MISSING_PARAM);
+ cause->cause.length = htons(len);
+ cause->num_missing_params = htonl(1);
+ cause->type[0] = htons(SCTP_STATE_COOKIE);
}
sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen,
src, dst, sh, op_err,
@@ -778,10 +776,10 @@ sctp_handle_abort(struct sctp_abort_chunk *abort,
* Need to check the cause codes for our two magic nat
* aborts which don't kill the assoc necessarily.
*/
- struct sctp_missing_nat_state *natc;
+ struct sctp_gen_error_cause *cause;
- natc = (struct sctp_missing_nat_state *)(abort + 1);
- error = ntohs(natc->cause);
+ cause = (struct sctp_gen_error_cause *)(abort + 1);
+ error = ntohs(cause->code);
if (error == SCTP_CAUSE_NAT_COLLIDING_STATE) {
SCTPDBG(SCTP_DEBUG_INPUT2, "Received Colliding state abort flags:%x\n",
abort->ch.chunk_flags);
@@ -864,6 +862,7 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
{
struct sctp_association *asoc;
int some_on_streamwheel;
+ int old_state;
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
@@ -882,11 +881,11 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_shutdown_chunk)) {
/* Shutdown NOT the expected size */
return;
- } else {
- sctp_update_acked(stcb, cp, abort_flag);
- if (*abort_flag) {
- return;
- }
+ }
+ old_state = SCTP_GET_STATE(asoc);
+ sctp_update_acked(stcb, cp, abort_flag);
+ if (*abort_flag) {
+ return;
}
if (asoc->control_pdapi) {
/*
@@ -956,12 +955,16 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
(SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
- SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT);
SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
- sctp_stop_timers_for_shutdown(stcb);
- sctp_send_shutdown_ack(stcb, net);
- sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep,
- stcb, net);
+ if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT) {
+ SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT);
+ sctp_stop_timers_for_shutdown(stcb);
+ sctp_send_shutdown_ack(stcb, net);
+ sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK,
+ stcb->sctp_ep, stcb, net);
+ } else if (old_state == SCTP_STATE_SHUTDOWN_ACK_SENT) {
+ sctp_send_shutdown_ack(stcb, net);
+ }
}
}
@@ -2100,6 +2103,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
*/
stcb = sctp_aloc_assoc(inp, init_src, &error,
ntohl(initack_cp->init.initiate_tag), vrf_id,
+ ntohs(initack_cp->init.num_outbound_streams),
(struct thread *)NULL
);
if (stcb == NULL) {
@@ -2343,12 +2347,17 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb, NULL);
}
(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
- if ((netp) && (*netp)) {
+ if ((netp != NULL) && (*netp != NULL)) {
/* calculate the RTT and set the encaps port */
(*netp)->RTO = sctp_calculate_rto(stcb, asoc, *netp,
&cookie->time_entered, sctp_align_unsafe_makecopy,
SCTP_RTT_FROM_NON_DATA);
+#if defined(INET) || defined(INET6)
+ if (((*netp)->port == 0) && (port != 0)) {
+ sctp_pathmtu_adjustment(stcb, (*netp)->mtu - sizeof(struct udphdr));
+ }
(*netp)->port = port;
+#endif
}
/* respond with a COOKIE-ACK */
sctp_send_cookie_ack(stcb);
@@ -2431,8 +2440,8 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
cookie_offset = offset + sizeof(struct sctp_chunkhdr);
cookie_len = ntohs(cp->ch.chunk_length);
- if ((cookie->peerport != sh->src_port) &&
- (cookie->myport != sh->dest_port) &&
+ if ((cookie->peerport != sh->src_port) ||
+ (cookie->myport != sh->dest_port) ||
(cookie->my_vtag != sh->v_tag)) {
/*
* invalid ports or bad tag. Note that we always leave the
@@ -2550,27 +2559,27 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
if (timevalcmp(&now, &time_expires, >)) {
/* cookie is stale! */
struct mbuf *op_err;
- struct sctp_stale_cookie_msg *scm;
+ struct sctp_error_stale_cookie *cause;
uint32_t tim;
- op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_stale_cookie_msg),
+ op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_error_stale_cookie),
0, M_NOWAIT, 1, MT_DATA);
if (op_err == NULL) {
/* FOOBAR */
return (NULL);
}
/* Set the len */
- SCTP_BUF_LEN(op_err) = sizeof(struct sctp_stale_cookie_msg);
- scm = mtod(op_err, struct sctp_stale_cookie_msg *);
- scm->ph.param_type = htons(SCTP_CAUSE_STALE_COOKIE);
- scm->ph.param_length = htons((sizeof(struct sctp_paramhdr) +
+ SCTP_BUF_LEN(op_err) = sizeof(struct sctp_error_stale_cookie);
+ cause = mtod(op_err, struct sctp_error_stale_cookie *);
+ cause->cause.code = htons(SCTP_CAUSE_STALE_COOKIE);
+ cause->cause.length = htons((sizeof(struct sctp_paramhdr) +
(sizeof(uint32_t))));
/* seconds to usec */
tim = (now.tv_sec - time_expires.tv_sec) * 1000000;
/* add in usec */
if (tim == 0)
tim = now.tv_usec - cookie->time_entered.tv_usec;
- scm->time_usec = htonl(tim);
+ cause->stale_time = htonl(tim);
sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err,
mflowtype, mflowid, l_inp->fibnum,
vrf_id, port);
@@ -3506,6 +3515,28 @@ sctp_reset_out_streams(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t
sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_SEND, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED);
}
+static void
+sctp_reset_clear_pending(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t * list)
+{
+ uint32_t i;
+ uint16_t temp;
+
+ if (number_entries > 0) {
+ for (i = 0; i < number_entries; i++) {
+ temp = ntohs(list[i]);
+ if (temp >= stcb->asoc.streamoutcnt) {
+ /* no such stream */
+ continue;
+ }
+ stcb->asoc.strmout[temp].state = SCTP_STREAM_OPEN;
+ }
+ } else {
+ for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
+ stcb->asoc.strmout[i].state = SCTP_STREAM_OPEN;
+ }
+ }
+}
+
struct sctp_stream_reset_request *
sctp_find_stream_reset(struct sctp_tcb *stcb, uint32_t seq, struct sctp_tmit_chunk **bchk)
@@ -3604,6 +3635,8 @@ sctp_handle_stream_reset_response(struct sctp_tcb *stcb,
type = ntohs(req_param->ph.param_type);
lparm_len = ntohs(req_param->ph.param_length);
if (type == SCTP_STR_RESET_OUT_REQUEST) {
+ int no_clear = 0;
+
req_out_param = (struct sctp_stream_reset_out_request *)req_param;
number_entries = (lparm_len - sizeof(struct sctp_stream_reset_out_request)) / sizeof(uint16_t);
asoc->stream_reset_out_is_outstanding = 0;
@@ -3614,9 +3647,21 @@ sctp_handle_stream_reset_response(struct sctp_tcb *stcb,
sctp_reset_out_streams(stcb, number_entries, req_out_param->list_of_streams);
} else if (action == SCTP_STREAM_RESET_RESULT_DENIED) {
sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_DENIED_OUT, stcb, number_entries, req_out_param->list_of_streams, SCTP_SO_NOT_LOCKED);
+ } else if (action == SCTP_STREAM_RESET_RESULT_IN_PROGRESS) {
+ /*
+ * Set it up so we don't stop
+ * retransmitting
+ */
+ asoc->stream_reset_outstanding++;
+ stcb->asoc.str_reset_seq_out--;
+ asoc->stream_reset_out_is_outstanding = 1;
+ no_clear = 1;
} else {
sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_OUT, stcb, number_entries, req_out_param->list_of_streams, SCTP_SO_NOT_LOCKED);
}
+ if (no_clear == 0) {
+ sctp_reset_clear_pending(stcb, number_entries, req_out_param->list_of_streams);
+ }
} else if (type == SCTP_STR_RESET_IN_REQUEST) {
req_in_param = (struct sctp_stream_reset_in_request *)req_param;
number_entries = (lparm_len - sizeof(struct sctp_stream_reset_in_request)) / sizeof(uint16_t);
@@ -3643,7 +3688,12 @@ sctp_handle_stream_reset_response(struct sctp_tcb *stcb,
asoc->stream_reset_outstanding--;
if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) {
/* Put the new streams into effect */
- stcb->asoc.streamoutcnt += num_stream;
+ int i;
+
+ for (i = asoc->streamoutcnt; i < (asoc->streamoutcnt + num_stream); i++) {
+ asoc->strmout[i].state = SCTP_STREAM_OPEN;
+ }
+ asoc->streamoutcnt += num_stream;
sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 0);
} else if (action == SCTP_STREAM_RESET_RESULT_DENIED) {
sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt,
@@ -3720,6 +3770,9 @@ sctp_handle_stream_reset_response(struct sctp_tcb *stcb,
}
}
}
+ if (asoc->stream_reset_outstanding == 0) {
+ sctp_send_stream_reset_out_if_possible(stcb, SCTP_SO_NOT_LOCKED);
+ }
return (0);
}
@@ -3750,22 +3803,33 @@ sctp_handle_str_reset_request_in(struct sctp_tcb *stcb,
} else if (stcb->asoc.stream_reset_out_is_outstanding == 0) {
len = ntohs(req->ph.param_length);
number_entries = ((len - sizeof(struct sctp_stream_reset_in_request)) / sizeof(uint16_t));
- for (i = 0; i < number_entries; i++) {
- temp = ntohs(req->list_of_streams[i]);
- req->list_of_streams[i] = temp;
+ if (number_entries) {
+ for (i = 0; i < number_entries; i++) {
+ temp = ntohs(req->list_of_streams[i]);
+ if (temp >= stcb->asoc.streamoutcnt) {
+ asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
+ goto bad_boy;
+ }
+ req->list_of_streams[i] = temp;
+ }
+ for (i = 0; i < number_entries; i++) {
+ if (stcb->asoc.strmout[req->list_of_streams[i]].state == SCTP_STREAM_OPEN) {
+ stcb->asoc.strmout[req->list_of_streams[i]].state = SCTP_STREAM_RESET_PENDING;
+ }
+ }
+ } else {
+ /* Its all */
+ for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
+ if (stcb->asoc.strmout[i].state == SCTP_STREAM_OPEN)
+ stcb->asoc.strmout[i].state = SCTP_STREAM_RESET_PENDING;
+ }
}
asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED;
- sctp_add_stream_reset_out(chk, number_entries, req->list_of_streams,
- asoc->str_reset_seq_out,
- seq, (asoc->sending_seq - 1));
- asoc->stream_reset_out_is_outstanding = 1;
- asoc->str_reset = chk;
- sctp_timer_start(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo);
- stcb->asoc.stream_reset_outstanding++;
} else {
/* Can't do it, since we have sent one out */
asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_ERR_IN_PROGRESS;
}
+bad_boy:
sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]);
asoc->str_reset_seq_in++;
} else if (asoc->str_reset_seq_in - 1 == seq) {
@@ -3775,6 +3839,7 @@ sctp_handle_str_reset_request_in(struct sctp_tcb *stcb,
} else {
sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO);
}
+ sctp_send_stream_reset_out_if_possible(stcb, SCTP_SO_NOT_LOCKED);
}
static int
@@ -3893,11 +3958,12 @@ sctp_handle_str_reset_request_out(struct sctp_tcb *stcb,
sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]);
return;
}
+ liste->seq = seq;
liste->tsn = tsn;
liste->number_entries = number_entries;
memcpy(&liste->list_of_streams, req->list_of_streams, number_entries * sizeof(uint16_t));
TAILQ_INSERT_TAIL(&asoc->resetHead, liste, next_resp);
- asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED;
+ asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_IN_PROGRESS;
}
sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]);
asoc->str_reset_seq_in++;
@@ -4034,7 +4100,7 @@ sctp_handle_str_reset_add_out_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk
mychk += num_stream;
if (mychk < 0x10000) {
stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED;
- if (sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 0, 1, num_stream, 0, 1)) {
+ if (sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 1, num_stream, 0, 1)) {
stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
}
} else {
@@ -4565,7 +4631,7 @@ __attribute__((noinline))
}
}
if (stcb == NULL) {
- snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__);
+ snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__);
op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
msg);
/* no association, so it's out of the blue... */
@@ -4609,7 +4675,7 @@ __attribute__((noinline))
if (locked_tcb) {
SCTP_TCB_UNLOCK(locked_tcb);
}
- snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__);
+ snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__);
op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
msg);
sctp_handle_ootb(m, iphlen, *offset, src, dst,
@@ -4755,13 +4821,11 @@ process_control_chunks:
/* The INIT chunk must be the only chunk. */
if ((num_chunks > 1) ||
(length - *offset > (int)SCTP_SIZE32(chk_length))) {
- op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
- "INIT not the only chunk");
- sctp_abort_association(inp, stcb, m, iphlen,
- src, dst, sh, op_err,
- mflowtype, mflowid,
- vrf_id, port);
+ /* RFC 4960 requires that no ABORT is sent */
*offset = length;
+ if (locked_tcb) {
+ SCTP_TCB_UNLOCK(locked_tcb);
+ }
return (NULL);
}
/* Honor our resource limit. */
@@ -5519,39 +5583,27 @@ process_control_chunks:
unknown_chunk:
/* it's an unknown chunk! */
if ((ch->chunk_type & 0x40) && (stcb != NULL)) {
- struct mbuf *mm;
- struct sctp_paramhdr *phd;
+ struct sctp_gen_error_cause *cause;
int len;
- mm = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr),
+ op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_gen_error_cause),
0, M_NOWAIT, 1, MT_DATA);
- if (mm) {
+ if (op_err != NULL) {
len = min(SCTP_SIZE32(chk_length), (uint32_t) (length - *offset));
- phd = mtod(mm, struct sctp_paramhdr *);
- /*
- * We cheat and use param type since
- * we did not bother to define a
- * error cause struct. They are the
- * same basic format with different
- * names.
- */
- phd->param_type = htons(SCTP_CAUSE_UNRECOG_CHUNK);
- phd->param_length = htons(len + sizeof(*phd));
- SCTP_BUF_LEN(mm) = sizeof(*phd);
- SCTP_BUF_NEXT(mm) = SCTP_M_COPYM(m, *offset, len, M_NOWAIT);
- if (SCTP_BUF_NEXT(mm)) {
- if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(mm), SCTP_SIZE32(len) - len, NULL) == NULL) {
- sctp_m_freem(mm);
- } else {
+ cause = mtod(op_err, struct sctp_gen_error_cause *);
+ cause->code = htons(SCTP_CAUSE_UNRECOG_CHUNK);
+ cause->length = htons(len + sizeof(struct sctp_gen_error_cause));
+ SCTP_BUF_LEN(op_err) = sizeof(struct sctp_gen_error_cause);
+ SCTP_BUF_NEXT(op_err) = SCTP_M_COPYM(m, *offset, len, M_NOWAIT);
+ if (SCTP_BUF_NEXT(op_err) != NULL) {
#ifdef SCTP_MBUF_LOGGING
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
- sctp_log_mbc(SCTP_BUF_NEXT(mm), SCTP_MBUF_ICOPY);
- }
-#endif
- sctp_queue_op_err(stcb, mm);
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
+ sctp_log_mbc(SCTP_BUF_NEXT(op_err), SCTP_MBUF_ICOPY);
}
+#endif
+ sctp_queue_op_err(stcb, op_err);
} else {
- sctp_m_freem(mm);
+ sctp_m_freem(op_err);
}
}
}
@@ -5589,30 +5641,6 @@ next_chunk:
}
-#ifdef INVARIANTS
-#ifdef __GNUC__
-__attribute__((noinline))
-#endif
- void
- sctp_validate_no_locks(struct sctp_inpcb *inp)
-{
- struct sctp_tcb *lstcb;
-
- LIST_FOREACH(lstcb, &inp->sctp_asoc_list, sctp_tcblist) {
- if (mtx_owned(&lstcb->tcb_mtx)) {
- panic("Own lock on stcb at return from input");
- }
- }
- if (mtx_owned(&inp->inp_create_mtx)) {
- panic("Own create lock on inp");
- }
- if (mtx_owned(&inp->inp_mtx)) {
- panic("Own inp lock on inp");
- }
-}
-
-#endif
-
/*
* common input chunk processing (v4 and v6)
*/
@@ -5775,7 +5803,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
*/
SCTP_TCB_UNLOCK(stcb);
stcb = NULL;
- snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__);
+ snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__);
op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
msg);
sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err,
@@ -5799,7 +5827,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
*/
inp = stcb->sctp_ep;
#if defined(INET) || defined(INET6)
- if ((net) && (port)) {
+ if ((net != NULL) && (port != 0)) {
if (net->port == 0) {
sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr));
}
@@ -5827,7 +5855,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
}
if (stcb == NULL) {
/* out of the blue DATA chunk */
- snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__);
+ snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__);
op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
msg);
sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err,
@@ -5899,7 +5927,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
/*
* We consider OOTB any data sent during asoc setup.
*/
- snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__);
+ snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__);
op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
msg);
sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err,
@@ -5922,10 +5950,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
}
/* plow through the data chunks while length > offset */
retval = sctp_process_data(mm, iphlen, &offset, length,
- src, dst, sh,
- inp, stcb, net, &high_tsn,
- mflowtype, mflowid,
- vrf_id, port);
+ inp, stcb, net, &high_tsn);
if (retval == 2) {
/*
* The association aborted, NO UNLOCK needed since
@@ -5977,7 +6002,7 @@ trigger_send:
if (!TAILQ_EMPTY(&stcb->asoc.control_send_queue)) {
cnt_ctrl_ready = stcb->asoc.ctrl_queue_cnt - stcb->asoc.ecn_echo_cnt_onq;
}
- if (cnt_ctrl_ready ||
+ if (cnt_ctrl_ready || stcb->asoc.trigger_reset ||
((un_sent) &&
(stcb->asoc.peers_rwnd > 0 ||
(stcb->asoc.peers_rwnd <= 0 && stcb->asoc.total_flight == 0)))) {
@@ -5999,11 +6024,6 @@ out:
SCTP_INP_DECR_REF(inp_decr);
SCTP_INP_WUNLOCK(inp_decr);
}
-#ifdef INVARIANTS
- if (inp != NULL) {
- sctp_validate_no_locks(inp);
- }
-#endif
return;
}
diff --git a/sys/netinet/sctp_os_bsd.h b/sys/netinet/sctp_os_bsd.h
index 7ae332a..88ad978 100644
--- a/sys/netinet/sctp_os_bsd.h
+++ b/sys/netinet/sctp_os_bsd.h
@@ -95,7 +95,6 @@ __FBSDID("$FreeBSD$");
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
#include <netinet6/in6_pcb.h>
-#include <netinet/icmp6.h>
#include <netinet6/ip6protosw.h>
#include <netinet6/nd6.h>
#include <netinet6/scope6_var.h>
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index 0cdeb94..5328f49 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -2417,7 +2417,7 @@ sctp_is_addr_restricted(struct sctp_tcb *stcb, struct sctp_ifa *ifa)
LIST_FOREACH(laddr, &stcb->asoc.sctp_restricted_addrs, sctp_nxt_addr) {
if (laddr->ifa == NULL) {
SCTPDBG(SCTP_DEBUG_OUTPUT1, "%s: NULL ifa\n",
- __FUNCTION__);
+ __func__);
continue;
}
if (laddr->ifa == ifa) {
@@ -2439,7 +2439,7 @@ sctp_is_addr_in_ep(struct sctp_inpcb *inp, struct sctp_ifa *ifa)
LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
if (laddr->ifa == NULL) {
SCTPDBG(SCTP_DEBUG_OUTPUT1, "%s: NULL ifa\n",
- __FUNCTION__);
+ __func__);
continue;
}
if ((laddr->ifa == ifa) && laddr->action == 0)
@@ -3652,6 +3652,7 @@ sctp_process_cmsgs_for_init(struct sctp_tcb *stcb, struct mbuf *control, int *er
#endif
stcb->asoc.strmout[i].stream_no = i;
stcb->asoc.strmout[i].last_msg_incomplete = 0;
+ stcb->asoc.strmout[i].state = SCTP_STREAM_OPENING;
stcb->asoc.ss_functions.sctp_ss_init_stream(&stcb->asoc.strmout[i], NULL);
}
}
@@ -5524,7 +5525,7 @@ do_a_abort:
if (op_err == NULL) {
char msg[SCTP_DIAG_INFO_LEN];
- snprintf(msg, sizeof(msg), "%s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__);
+ snprintf(msg, sizeof(msg), "%s:%d at %s", __FILE__, __LINE__, __func__);
op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
msg);
}
@@ -5841,10 +5842,10 @@ do_a_abort:
his_limit = ntohs(init_chk->init.num_inbound_streams);
/* choose what I want */
if (asoc != NULL) {
- if (asoc->streamoutcnt > inp->sctp_ep.pre_open_stream_count) {
+ if (asoc->streamoutcnt > asoc->pre_open_streams) {
i_want = asoc->streamoutcnt;
} else {
- i_want = inp->sctp_ep.pre_open_stream_count;
+ i_want = asoc->pre_open_streams;
}
} else {
i_want = inp->sctp_ep.pre_open_stream_count;
@@ -6682,10 +6683,17 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
if (TAILQ_EMPTY(&asoc->send_queue) &&
TAILQ_EMPTY(&asoc->sent_queue) &&
(asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
+ struct mbuf *op_err;
+ char msg[SCTP_DIAG_INFO_LEN];
+
abort_anyway:
+ snprintf(msg, sizeof(msg),
+ "%s:%d at %s", __FILE__, __LINE__, __func__);
+ op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
+ msg);
atomic_add_int(&stcb->asoc.refcnt, 1);
sctp_abort_an_association(stcb->sctp_ep, stcb,
- NULL, SCTP_SO_NOT_LOCKED);
+ op_err, SCTP_SO_NOT_LOCKED);
atomic_add_int(&stcb->asoc.refcnt, -1);
goto no_chunk_output;
}
@@ -7162,6 +7170,11 @@ one_more_time:
}
atomic_subtract_int(&asoc->stream_queue_cnt, 1);
TAILQ_REMOVE(&strq->outqueue, sp, next);
+ if ((strq->state == SCTP_STREAM_RESET_PENDING) &&
+ (strq->chunks_on_queues == 0) &&
+ TAILQ_EMPTY(&strq->outqueue)) {
+ stcb->asoc.trigger_reset = 1;
+ }
stcb->asoc.ss_functions.sctp_ss_remove_from_stream(stcb, asoc, strq, sp, send_lock_up);
if (sp->net) {
sctp_free_remote_addr(sp->net);
@@ -7206,7 +7219,7 @@ one_more_time:
}
/* Whack down the size */
atomic_subtract_int(&stcb->asoc.total_output_queue_size, sp->length);
- if ((stcb->sctp_socket != NULL) && \
+ if ((stcb->sctp_socket != NULL) &&
((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) {
atomic_subtract_int(&stcb->sctp_socket->so_snd.sb_cc, sp->length);
@@ -7225,9 +7238,6 @@ one_more_time:
}
}
some_taken = sp->some_taken;
- if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
- sp->msg_is_complete = 1;
- }
re_look:
length = sp->length;
if (sp->msg_is_complete) {
@@ -7560,6 +7570,11 @@ dont_do_it:
send_lock_up = 1;
}
TAILQ_REMOVE(&strq->outqueue, sp, next);
+ if ((strq->state == SCTP_STREAM_RESET_PENDING) &&
+ (strq->chunks_on_queues == 0) &&
+ TAILQ_EMPTY(&strq->outqueue)) {
+ stcb->asoc.trigger_reset = 1;
+ }
stcb->asoc.ss_functions.sctp_ss_remove_from_stream(stcb, asoc, strq, sp, send_lock_up);
if (sp->net) {
sctp_free_remote_addr(sp->net);
@@ -7787,7 +7802,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
#endif
SCTP_TCB_LOCK_ASSERT(stcb);
hbflag = 0;
- if ((control_only) || (asoc->stream_reset_outstanding))
+ if (control_only)
no_data_chunks = 1;
else
no_data_chunks = 0;
@@ -8851,9 +8866,37 @@ sctp_queue_op_err(struct sctp_tcb *stcb, struct mbuf *op_err)
*/
struct sctp_chunkhdr *hdr;
struct sctp_tmit_chunk *chk;
- struct mbuf *mat;
+ struct mbuf *mat, *last_mbuf;
+ uint32_t chunk_length;
+ uint16_t padding_length;
SCTP_TCB_LOCK_ASSERT(stcb);
+ SCTP_BUF_PREPEND(op_err, sizeof(struct sctp_chunkhdr), M_NOWAIT);
+ if (op_err == NULL) {
+ return;
+ }
+ last_mbuf = NULL;
+ chunk_length = 0;
+ for (mat = op_err; mat != NULL; mat = SCTP_BUF_NEXT(mat)) {
+ chunk_length += SCTP_BUF_LEN(mat);
+ if (SCTP_BUF_NEXT(mat) == NULL) {
+ last_mbuf = mat;
+ }
+ }
+ if (chunk_length > SCTP_MAX_CHUNK_LENGTH) {
+ sctp_m_freem(op_err);
+ return;
+ }
+ padding_length = chunk_length % 4;
+ if (padding_length != 0) {
+ padding_length = 4 - padding_length;
+ }
+ if (padding_length != 0) {
+ if (sctp_add_pad_tombuf(last_mbuf, padding_length) == NULL) {
+ sctp_m_freem(op_err);
+ return;
+ }
+ }
sctp_alloc_a_chunk(stcb, chk);
if (chk == NULL) {
/* no memory */
@@ -8861,15 +8904,7 @@ sctp_queue_op_err(struct sctp_tcb *stcb, struct mbuf *op_err)
return;
}
chk->copy_by_ref = 0;
- SCTP_BUF_PREPEND(op_err, sizeof(struct sctp_chunkhdr), M_NOWAIT);
- if (op_err == NULL) {
- sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
- return;
- }
- chk->send_size = 0;
- for (mat = op_err; mat != NULL; mat = SCTP_BUF_NEXT(mat)) {
- chk->send_size += SCTP_BUF_LEN(mat);
- }
+ chk->send_size = (uint16_t) chunk_length;
chk->sent = SCTP_DATAGRAM_UNSENT;
chk->snd_count = 0;
chk->asoc = &stcb->asoc;
@@ -8879,9 +8914,7 @@ sctp_queue_op_err(struct sctp_tcb *stcb, struct mbuf *op_err)
hdr->chunk_type = SCTP_OPERATION_ERROR;
hdr->chunk_flags = 0;
hdr->chunk_length = htons(chk->send_size);
- TAILQ_INSERT_TAIL(&chk->asoc->control_send_queue,
- chk,
- sctp_next);
+ TAILQ_INSERT_TAIL(&chk->asoc->control_send_queue, chk, sctp_next);
chk->asoc->ctrl_queue_cnt++;
}
@@ -9462,12 +9495,16 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
}
if ((SCTP_BASE_SYSCTL(sctp_max_retran_chunk)) &&
(chk->snd_count >= SCTP_BASE_SYSCTL(sctp_max_retran_chunk))) {
- /* Gak, we have exceeded max unlucky retran, abort! */
- SCTP_PRINTF("Gak, chk->snd_count:%d >= max:%d - send abort\n",
- chk->snd_count,
- SCTP_BASE_SYSCTL(sctp_max_retran_chunk));
+ struct mbuf *op_err;
+ char msg[SCTP_DIAG_INFO_LEN];
+
+ snprintf(msg, sizeof(msg), "TSN %8.8x retransmitted %d times, giving up",
+ chk->rec.data.TSN_seq, chk->snd_count);
+ op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
+ msg);
atomic_add_int(&stcb->asoc.refcnt, 1);
- sctp_abort_an_association(stcb->sctp_ep, stcb, NULL, so_locked);
+ sctp_abort_an_association(stcb->sctp_ep, stcb, op_err,
+ so_locked);
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
return (SCTP_RETRAN_EXIT);
@@ -9872,6 +9909,7 @@ sctp_chunk_output(struct sctp_inpcb *inp,
unsigned int tot_frs = 0;
asoc = &stcb->asoc;
+do_it_again:
/* The Nagle algorithm is only applied when handling a send call. */
if (from_where == SCTP_OUTPUT_FROM_USR_SEND) {
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NODELAY)) {
@@ -9889,7 +9927,8 @@ sctp_chunk_output(struct sctp_inpcb *inp,
if ((un_sent <= 0) &&
(TAILQ_EMPTY(&asoc->control_send_queue)) &&
(TAILQ_EMPTY(&asoc->asconf_send_queue)) &&
- (asoc->sent_queue_retran_cnt == 0)) {
+ (asoc->sent_queue_retran_cnt == 0) &&
+ (asoc->trigger_reset == 0)) {
/* Nothing to do unless there is something to be sent left */
return;
}
@@ -10108,6 +10147,12 @@ sctp_chunk_output(struct sctp_inpcb *inp,
*/
if (stcb->asoc.ecn_echo_cnt_onq)
sctp_fix_ecn_echo(asoc);
+
+ if (stcb->asoc.trigger_reset) {
+ if (sctp_send_stream_reset_out_if_possible(stcb, so_locked) == 0) {
+ goto do_it_again;
+ }
+ }
return;
}
@@ -11224,6 +11269,11 @@ sctp_send_hb(struct sctp_tcb *stcb, struct sctp_nets *net, int so_locked
break;
#endif
default:
+ if (chk->data) {
+ sctp_m_freem(chk->data);
+ chk->data = NULL;
+ }
+ sctp_free_a_chunk(stcb, chk, so_locked);
return;
break;
}
@@ -11510,30 +11560,60 @@ sctp_send_cwr(struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t high_tsn, u
asoc->ctrl_queue_cnt++;
}
-void
-sctp_add_stream_reset_out(struct sctp_tmit_chunk *chk,
- int number_entries, uint16_t * list,
+static int
+sctp_add_stream_reset_out(struct sctp_tcb *stcb, struct sctp_tmit_chunk *chk,
uint32_t seq, uint32_t resp_seq, uint32_t last_sent)
{
uint16_t len, old_len, i;
struct sctp_stream_reset_out_request *req_out;
struct sctp_chunkhdr *ch;
+ int at;
+ int number_entries = 0;
ch = mtod(chk->data, struct sctp_chunkhdr *);
old_len = len = SCTP_SIZE32(ntohs(ch->chunk_length));
-
/* get to new offset for the param. */
req_out = (struct sctp_stream_reset_out_request *)((caddr_t)ch + len);
/* now how long will this param be? */
+ for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
+ if ((stcb->asoc.strmout[i].state == SCTP_STREAM_RESET_PENDING) &&
+ (stcb->asoc.strmout[i].chunks_on_queues == 0) &&
+ TAILQ_EMPTY(&stcb->asoc.strmout[i].outqueue)) {
+ number_entries++;
+ }
+ }
+ if (number_entries == 0) {
+ return (0);
+ }
+ if (number_entries == stcb->asoc.streamoutcnt) {
+ number_entries = 0;
+ }
+ if (number_entries > SCTP_MAX_STREAMS_AT_ONCE_RESET) {
+ number_entries = SCTP_MAX_STREAMS_AT_ONCE_RESET;
+ }
len = (sizeof(struct sctp_stream_reset_out_request) + (sizeof(uint16_t) * number_entries));
req_out->ph.param_type = htons(SCTP_STR_RESET_OUT_REQUEST);
req_out->ph.param_length = htons(len);
req_out->request_seq = htonl(seq);
req_out->response_seq = htonl(resp_seq);
req_out->send_reset_at_tsn = htonl(last_sent);
+ at = 0;
if (number_entries) {
- for (i = 0; i < number_entries; i++) {
- req_out->list_of_streams[i] = htons(list[i]);
+ for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
+ if ((stcb->asoc.strmout[i].state == SCTP_STREAM_RESET_PENDING) &&
+ (stcb->asoc.strmout[i].chunks_on_queues == 0) &&
+ TAILQ_EMPTY(&stcb->asoc.strmout[i].outqueue)) {
+ req_out->list_of_streams[at] = htons(i);
+ at++;
+ stcb->asoc.strmout[i].state = SCTP_STREAM_RESET_IN_FLIGHT;
+ if (at >= number_entries) {
+ break;
+ }
+ }
+ }
+ } else {
+ for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
+ stcb->asoc.strmout[i].state = SCTP_STREAM_RESET_IN_FLIGHT;
}
}
if (SCTP_SIZE32(len) > len) {
@@ -11550,7 +11630,7 @@ sctp_add_stream_reset_out(struct sctp_tmit_chunk *chk,
chk->book_size_scale = 0;
chk->send_size = SCTP_SIZE32(chk->book_size);
SCTP_BUF_LEN(chk->data) = chk->send_size;
- return;
+ return (1);
}
static void
@@ -11652,6 +11732,68 @@ sctp_add_stream_reset_result(struct sctp_tmit_chunk *chk,
}
void
+sctp_send_deferred_reset_response(struct sctp_tcb *stcb,
+ struct sctp_stream_reset_list *ent,
+ int response)
+{
+ struct sctp_association *asoc;
+ struct sctp_tmit_chunk *chk;
+ struct sctp_chunkhdr *ch;
+
+ asoc = &stcb->asoc;
+
+ /*
+ * Reset our last reset action to the new one IP -> response
+ * (PERFORMED probably). This assures that if we fail to send, a
+ * retran from the peer will get the new response.
+ */
+ asoc->last_reset_action[0] = response;
+ if (asoc->stream_reset_outstanding) {
+ return;
+ }
+ sctp_alloc_a_chunk(stcb, chk);
+ if (chk == NULL) {
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
+ return;
+ }
+ chk->copy_by_ref = 0;
+ chk->rec.chunk_id.id = SCTP_STREAM_RESET;
+ chk->rec.chunk_id.can_take_data = 0;
+ chk->flags = 0;
+ chk->asoc = &stcb->asoc;
+ chk->book_size = sizeof(struct sctp_chunkhdr);
+ chk->send_size = SCTP_SIZE32(chk->book_size);
+ chk->book_size_scale = 0;
+ chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA);
+ if (chk->data == NULL) {
+ sctp_free_a_chunk(stcb, chk, SCTP_SO_LOCKED);
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
+ return;
+ }
+ SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD);
+ sctp_add_stream_reset_result(chk, ent->seq, response);
+ /* setup chunk parameters */
+ chk->sent = SCTP_DATAGRAM_UNSENT;
+ chk->snd_count = 0;
+ if (stcb->asoc.alternate) {
+ chk->whoTo = stcb->asoc.alternate;
+ } else {
+ chk->whoTo = stcb->asoc.primary_destination;
+ }
+ ch = mtod(chk->data, struct sctp_chunkhdr *);
+ ch->chunk_type = SCTP_STREAM_RESET;
+ ch->chunk_flags = 0;
+ ch->chunk_length = htons(chk->book_size);
+ atomic_add_int(&chk->whoTo->ref_count, 1);
+ SCTP_BUF_LEN(chk->data) = chk->send_size;
+ /* insert the chunk for sending */
+ TAILQ_INSERT_TAIL(&asoc->control_send_queue,
+ chk,
+ sctp_next);
+ asoc->ctrl_queue_cnt++;
+}
+
+void
sctp_add_stream_reset_result_tsn(struct sctp_tmit_chunk *chk,
uint32_t resp_seq, uint32_t result,
uint32_t send_una, uint32_t recv_next)
@@ -11749,19 +11891,90 @@ sctp_add_an_in_stream(struct sctp_tmit_chunk *chk,
}
int
+sctp_send_stream_reset_out_if_possible(struct sctp_tcb *stcb, int so_locked)
+{
+ struct sctp_association *asoc;
+ struct sctp_tmit_chunk *chk;
+ struct sctp_chunkhdr *ch;
+ uint32_t seq;
+
+ asoc = &stcb->asoc;
+ asoc->trigger_reset = 0;
+ if (asoc->stream_reset_outstanding) {
+ return (EALREADY);
+ }
+ sctp_alloc_a_chunk(stcb, chk);
+ if (chk == NULL) {
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
+ return (ENOMEM);
+ }
+ chk->copy_by_ref = 0;
+ chk->rec.chunk_id.id = SCTP_STREAM_RESET;
+ chk->rec.chunk_id.can_take_data = 0;
+ chk->flags = 0;
+ chk->asoc = &stcb->asoc;
+ chk->book_size = sizeof(struct sctp_chunkhdr);
+ chk->send_size = SCTP_SIZE32(chk->book_size);
+ chk->book_size_scale = 0;
+ chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA);
+ if (chk->data == NULL) {
+ sctp_free_a_chunk(stcb, chk, so_locked);
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
+ return (ENOMEM);
+ }
+ SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD);
+
+ /* setup chunk parameters */
+ chk->sent = SCTP_DATAGRAM_UNSENT;
+ chk->snd_count = 0;
+ if (stcb->asoc.alternate) {
+ chk->whoTo = stcb->asoc.alternate;
+ } else {
+ chk->whoTo = stcb->asoc.primary_destination;
+ }
+ ch = mtod(chk->data, struct sctp_chunkhdr *);
+ ch->chunk_type = SCTP_STREAM_RESET;
+ ch->chunk_flags = 0;
+ ch->chunk_length = htons(chk->book_size);
+ atomic_add_int(&chk->whoTo->ref_count, 1);
+ SCTP_BUF_LEN(chk->data) = chk->send_size;
+ seq = stcb->asoc.str_reset_seq_out;
+ if (sctp_add_stream_reset_out(stcb, chk, seq, (stcb->asoc.str_reset_seq_in - 1), (stcb->asoc.sending_seq - 1))) {
+ seq++;
+ asoc->stream_reset_outstanding++;
+ } else {
+ m_freem(chk->data);
+ chk->data = NULL;
+ sctp_free_a_chunk(stcb, chk, so_locked);
+ return (ENOENT);
+ }
+ asoc->str_reset = chk;
+ /* insert the chunk for sending */
+ TAILQ_INSERT_TAIL(&asoc->control_send_queue,
+ chk,
+ sctp_next);
+ asoc->ctrl_queue_cnt++;
+
+ if (stcb->asoc.send_sack) {
+ sctp_send_sack(stcb, so_locked);
+ }
+ sctp_timer_start(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo);
+ return (0);
+}
+
+int
sctp_send_str_reset_req(struct sctp_tcb *stcb,
uint16_t number_entries, uint16_t * list,
- uint8_t send_out_req,
uint8_t send_in_req,
uint8_t send_tsn_req,
uint8_t add_stream,
uint16_t adding_o,
uint16_t adding_i, uint8_t peer_asked)
{
-
struct sctp_association *asoc;
struct sctp_tmit_chunk *chk;
struct sctp_chunkhdr *ch;
+ int can_send_out_req = 0;
uint32_t seq;
asoc = &stcb->asoc;
@@ -11772,16 +11985,18 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb,
SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EBUSY);
return (EBUSY);
}
- if ((send_out_req == 0) && (send_in_req == 0) && (send_tsn_req == 0) &&
+ if ((send_in_req == 0) && (send_tsn_req == 0) &&
(add_stream == 0)) {
/* nothing to do */
SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EINVAL);
return (EINVAL);
}
- if (send_tsn_req && (send_out_req || send_in_req)) {
+ if (send_tsn_req && send_in_req) {
/* error, can't do that */
SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, EINVAL);
return (EINVAL);
+ } else if (send_in_req) {
+ can_send_out_req = 1;
}
if (number_entries > (MCLBYTES -
SCTP_MIN_OVERHEAD -
@@ -11829,12 +12044,14 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb,
SCTP_BUF_LEN(chk->data) = chk->send_size;
seq = stcb->asoc.str_reset_seq_out;
- if (send_out_req) {
- sctp_add_stream_reset_out(chk, number_entries, list,
- seq, (stcb->asoc.str_reset_seq_in - 1), (stcb->asoc.sending_seq - 1));
- asoc->stream_reset_out_is_outstanding = 1;
- seq++;
- asoc->stream_reset_outstanding++;
+ if (can_send_out_req) {
+ int ret;
+
+ ret = sctp_add_stream_reset_out(stcb, chk, seq, (stcb->asoc.str_reset_seq_in - 1), (stcb->asoc.sending_seq - 1));
+ if (ret) {
+ seq++;
+ asoc->stream_reset_outstanding++;
+ }
}
if ((add_stream & 1) &&
((stcb->asoc.strm_realoutsize - stcb->asoc.streamoutcnt) < adding_o)) {
@@ -11851,7 +12068,7 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb,
oldstream = stcb->asoc.strmout;
/* get some more */
SCTP_MALLOC(stcb->asoc.strmout, struct sctp_stream_out *,
- ((stcb->asoc.streamoutcnt + adding_o) * sizeof(struct sctp_stream_out)),
+ (stcb->asoc.streamoutcnt + adding_o) * sizeof(struct sctp_stream_out),
SCTP_M_STRMO);
if (stcb->asoc.strmout == NULL) {
uint8_t x;
@@ -11874,6 +12091,7 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb,
stcb->asoc.strmout[i].next_sequence_send = oldstream[i].next_sequence_send;
stcb->asoc.strmout[i].last_msg_incomplete = oldstream[i].last_msg_incomplete;
stcb->asoc.strmout[i].stream_no = i;
+ stcb->asoc.strmout[i].state = oldstream[i].state;
stcb->asoc.ss_functions.sctp_ss_init_stream(&stcb->asoc.strmout[i], &oldstream[i]);
/* now anything on those queues? */
TAILQ_FOREACH_SAFE(sp, &oldstream[i].outqueue, next, nsp) {
@@ -11906,6 +12124,7 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb,
stcb->asoc.strmout[i].stream_no = i;
stcb->asoc.strmout[i].last_msg_incomplete = 0;
stcb->asoc.ss_functions.sctp_ss_init_stream(&stcb->asoc.strmout[i], NULL);
+ stcb->asoc.strmout[i].state = SCTP_STREAM_CLOSED;
}
stcb->asoc.strm_realoutsize = stcb->asoc.streamoutcnt + adding_o;
SCTP_FREE(oldstream, SCTP_M_STRMO);
@@ -11939,6 +12158,9 @@ skip_stuff:
chk,
sctp_next);
asoc->ctrl_queue_cnt++;
+ if (stcb->asoc.send_sack) {
+ sctp_send_sack(stcb, SCTP_SO_LOCKED);
+ }
sctp_timer_start(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo);
return (0);
}
@@ -12393,6 +12615,7 @@ sctp_lower_sosend(struct socket *so,
}
#endif
stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id,
+ inp->sctp_ep.pre_open_stream_count,
p
);
if (stcb == NULL) {
@@ -12515,12 +12738,24 @@ sctp_lower_sosend(struct socket *so,
SCTP_ASOC_CREATE_UNLOCK(inp);
create_lock_applied = 0;
}
- if (asoc->stream_reset_outstanding) {
+ /* Is the stream no. valid? */
+ if (srcv->sinfo_stream >= asoc->streamoutcnt) {
+ /* Invalid stream number */
+ SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
+ error = EINVAL;
+ goto out_unlocked;
+ }
+ if ((asoc->strmout[srcv->sinfo_stream].state != SCTP_STREAM_OPEN) &&
+ (asoc->strmout[srcv->sinfo_stream].state != SCTP_STREAM_OPENING)) {
/*
* Can't queue any data while stream reset is underway.
*/
- SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EAGAIN);
- error = EAGAIN;
+ if (asoc->strmout[srcv->sinfo_stream].state > SCTP_STREAM_OPEN) {
+ error = EAGAIN;
+ } else {
+ error = EINVAL;
+ }
+ SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, error);
goto out_unlocked;
}
if ((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) ||
@@ -12659,13 +12894,6 @@ sctp_lower_sosend(struct socket *so,
SCTP_TCB_UNLOCK(stcb);
hold_tcblock = 0;
}
- /* Is the stream no. valid? */
- if (srcv->sinfo_stream >= asoc->streamoutcnt) {
- /* Invalid stream number */
- SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
- error = EINVAL;
- goto out_unlocked;
- }
if (asoc->strmout == NULL) {
/* huh? software error */
SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EFAULT);
@@ -12961,7 +13189,7 @@ skip_preblock:
/*-
* Ok, Nagle is set on and we have data outstanding.
* Don't send anything and let SACKs drive out the
- * data unless wen have a "full" segment to send.
+ * data unless we have a "full" segment to send.
*/
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_NAGLE_LOGGING_ENABLE) {
sctp_log_nagle_event(stcb, SCTP_NAGLE_APPLIED);
@@ -13170,13 +13398,20 @@ dataless_eof:
if (TAILQ_EMPTY(&asoc->send_queue) &&
TAILQ_EMPTY(&asoc->sent_queue) &&
(asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
+ struct mbuf *op_err;
+ char msg[SCTP_DIAG_INFO_LEN];
+
abort_anyway:
if (free_cnt_applied) {
atomic_add_int(&stcb->asoc.refcnt, -1);
free_cnt_applied = 0;
}
+ snprintf(msg, sizeof(msg),
+ "%s:%d at %s", __FILE__, __LINE__, __func__);
+ op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
+ msg);
sctp_abort_an_association(stcb->sctp_ep, stcb,
- NULL, SCTP_SO_LOCKED);
+ op_err, SCTP_SO_LOCKED);
/*
* now relock the stcb so everything
* is sane
@@ -13316,13 +13551,6 @@ out_unlocked:
}
}
#endif
-#ifdef INVARIANTS
- if (inp) {
- sctp_validate_no_locks(inp);
- } else {
- SCTP_PRINTF("Warning - inp is NULL so cant validate locks\n");
- }
-#endif
if (top) {
sctp_m_freem(top);
}
diff --git a/sys/netinet/sctp_output.h b/sys/netinet/sctp_output.h
index 8e45e5c..d7222c4 100644
--- a/sys/netinet/sctp_output.h
+++ b/sys/netinet/sctp_output.h
@@ -170,18 +170,21 @@ void sctp_send_cwr(struct sctp_tcb *, struct sctp_nets *, uint32_t, uint8_t);
void
-sctp_add_stream_reset_out(struct sctp_tmit_chunk *,
- int, uint16_t *, uint32_t, uint32_t, uint32_t);
+ sctp_add_stream_reset_result(struct sctp_tmit_chunk *, uint32_t, uint32_t);
void
- sctp_add_stream_reset_result(struct sctp_tmit_chunk *, uint32_t, uint32_t);
+sctp_send_deferred_reset_response(struct sctp_tcb *,
+ struct sctp_stream_reset_list *,
+ int);
void
sctp_add_stream_reset_result_tsn(struct sctp_tmit_chunk *,
uint32_t, uint32_t, uint32_t, uint32_t);
+int
+ sctp_send_stream_reset_out_if_possible(struct sctp_tcb *, int);
int
-sctp_send_str_reset_req(struct sctp_tcb *, uint16_t, uint16_t *, uint8_t,
+sctp_send_str_reset_req(struct sctp_tcb *, uint16_t, uint16_t *,
uint8_t, uint8_t, uint8_t, uint16_t, uint16_t, uint8_t);
void
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index 344cdfc..39872e4 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -1115,7 +1115,7 @@ sctp_tcb_special_locate(struct sctp_inpcb **inp_p, struct sockaddr *from,
LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
if (laddr->ifa == NULL) {
- SCTPDBG(SCTP_DEBUG_PCB1, "%s: NULL ifa\n", __FUNCTION__);
+ SCTPDBG(SCTP_DEBUG_PCB1, "%s: NULL ifa\n", __func__);
continue;
}
if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) {
@@ -1773,7 +1773,7 @@ sctp_endpoint_probe(struct sockaddr *nam, struct sctppcbhead *head,
LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
if (laddr->ifa == NULL) {
SCTPDBG(SCTP_DEBUG_PCB1, "%s: NULL ifa\n",
- __FUNCTION__);
+ __func__);
continue;
}
SCTPDBG(SCTP_DEBUG_PCB1, "Ok laddr->ifa:%p is possible, ",
@@ -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. */
@@ -2343,7 +2347,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int offset,
&parm_buf, sizeof(struct sctp_paramhdr));
if (phdr == NULL) {
SCTPDBG(SCTP_DEBUG_INPUT3, "%s: failed to get asconf lookup addr\n",
- __FUNCTION__);
+ __func__);
return NULL;
}
ptype = (int)((uint32_t) ntohs(phdr->param_type));
@@ -2363,7 +2367,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int offset,
&p6_buf.ph, sizeof(*p6));
if (p6 == NULL) {
SCTPDBG(SCTP_DEBUG_INPUT3, "%s: failed to get asconf v6 lookup addr\n",
- __FUNCTION__);
+ __func__);
return (NULL);
}
sin6 = &remote_store.sin6;
@@ -2390,7 +2394,7 @@ sctp_findassociation_ep_asconf(struct mbuf *m, int offset,
&p4_buf.ph, sizeof(*p4));
if (p4 == NULL) {
SCTPDBG(SCTP_DEBUG_INPUT3, "%s: failed to get asconf v4 lookup addr\n",
- __FUNCTION__);
+ __func__);
return (NULL);
}
sin = &remote_store.sin;
@@ -2499,14 +2503,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
return (ENOBUFS);
}
#ifdef IPSEC
- {
- struct inpcbpolicy *pcb_sp = NULL;
-
- error = ipsec_init_policy(so, &pcb_sp);
- /* Arrange to share the policy */
- inp->ip_inp.inp.inp_sp = pcb_sp;
- ((struct in6pcb *)(&inp->ip_inp.inp))->in6p_sp = pcb_sp;
- }
+ error = ipsec_init_policy(so, &inp->ip_inp.inp.inp_sp);
if (error != 0) {
crfree(inp->ip_inp.inp.inp_cred);
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp);
@@ -2540,6 +2537,9 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EOPNOTSUPP);
so->so_pcb = NULL;
crfree(inp->ip_inp.inp.inp_cred);
+#ifdef IPSEC
+ ipsec_delete_pcbpolicy(&inp->ip_inp.inp);
+#endif
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp);
return (EOPNOTSUPP);
}
@@ -2560,6 +2560,9 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, ENOBUFS);
so->so_pcb = NULL;
crfree(inp->ip_inp.inp.inp_cred);
+#ifdef IPSEC
+ ipsec_delete_pcbpolicy(&inp->ip_inp.inp);
+#endif
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_ep), inp);
return (ENOBUFS);
}
@@ -3644,13 +3647,9 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
* macro here since le_next will get freed as part of the
* sctp_free_assoc() call.
*/
- if (so) {
#ifdef IPSEC
- ipsec_delete_pcbpolicy(ip_pcb);
-#endif /* IPSEC */
-
- /* Unlocks not needed since the socket is gone now */
- }
+ ipsec_delete_pcbpolicy(ip_pcb);
+#endif
if (ip_pcb->inp_options) {
(void)sctp_m_free(ip_pcb->inp_options);
ip_pcb->inp_options = 0;
@@ -4169,6 +4168,7 @@ try_again:
struct sctp_tcb *
sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
int *error, uint32_t override_tag, uint32_t vrf_id,
+ uint16_t o_streams,
struct thread *p
)
{
@@ -4327,7 +4327,7 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
/* setup back pointer's */
stcb->sctp_ep = inp;
stcb->sctp_socket = inp->sctp_socket;
- if ((err = sctp_init_asoc(inp, stcb, override_tag, vrf_id))) {
+ if ((err = sctp_init_asoc(inp, stcb, override_tag, vrf_id, o_streams))) {
/* failed */
SCTP_TCB_LOCK_DESTROY(stcb);
SCTP_TCB_SEND_LOCK_DESTROY(stcb);
@@ -5304,7 +5304,7 @@ sctp_update_ep_vflag(struct sctp_inpcb *inp)
LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
if (laddr->ifa == NULL) {
SCTPDBG(SCTP_DEBUG_PCB1, "%s: NULL ifa\n",
- __FUNCTION__);
+ __func__);
continue;
}
if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED) {
@@ -6254,12 +6254,20 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
*/
if (stcb_tmp) {
if (SCTP_GET_STATE(&stcb_tmp->asoc) & SCTP_STATE_COOKIE_WAIT) {
+ struct mbuf *op_err;
+ char msg[SCTP_DIAG_INFO_LEN];
+
/*
* in setup state we
* abort this guy
*/
+ snprintf(msg, sizeof(msg),
+ "%s:%d at %s", __FILE__, __LINE__, __func__);
+ op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
+ msg);
sctp_abort_an_association(stcb_tmp->sctp_ep,
- stcb_tmp, NULL, SCTP_SO_NOT_LOCKED);
+ stcb_tmp, op_err,
+ SCTP_SO_NOT_LOCKED);
goto add_it_now;
}
SCTP_TCB_UNLOCK(stcb_tmp);
@@ -6343,18 +6351,26 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
* strange, address is in another
* assoc? straighten out locks.
*/
- if (stcb_tmp)
+ if (stcb_tmp) {
if (SCTP_GET_STATE(&stcb_tmp->asoc) & SCTP_STATE_COOKIE_WAIT) {
+ struct mbuf *op_err;
+ char msg[SCTP_DIAG_INFO_LEN];
+
/*
* in setup state we
* abort this guy
*/
+ snprintf(msg, sizeof(msg),
+ "%s:%d at %s", __FILE__, __LINE__, __func__);
+ op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
+ msg);
sctp_abort_an_association(stcb_tmp->sctp_ep,
- stcb_tmp, NULL, SCTP_SO_NOT_LOCKED);
+ stcb_tmp, op_err,
+ SCTP_SO_NOT_LOCKED);
goto add_it_now6;
}
- SCTP_TCB_UNLOCK(stcb_tmp);
-
+ SCTP_TCB_UNLOCK(stcb_tmp);
+ }
if (stcb->asoc.state == 0) {
/* the assoc was freed? */
return (-21);
diff --git a/sys/netinet/sctp_pcb.h b/sys/netinet/sctp_pcb.h
index f5ede2a..165ef3b 100644
--- a/sys/netinet/sctp_pcb.h
+++ b/sys/netinet/sctp_pcb.h
@@ -584,7 +584,7 @@ void sctp_inpcb_free(struct sctp_inpcb *, int, int);
struct sctp_tcb *
sctp_aloc_assoc(struct sctp_inpcb *, struct sockaddr *,
- int *, uint32_t, uint32_t, struct thread *);
+ int *, uint32_t, uint32_t, uint16_t, struct thread *);
int sctp_free_assoc(struct sctp_inpcb *, struct sctp_tcb *, int, int);
@@ -654,11 +654,5 @@ void
#endif
-#ifdef INVARIANTS
-void
- sctp_validate_no_locks(struct sctp_inpcb *inp);
-
-#endif
-
#endif /* _KERNEL */
#endif /* !__sctp_pcb_h__ */
diff --git a/sys/netinet/sctp_structs.h b/sys/netinet/sctp_structs.h
index 8f61cd7..eda99fe 100644
--- a/sys/netinet/sctp_structs.h
+++ b/sys/netinet/sctp_structs.h
@@ -76,6 +76,7 @@ TAILQ_HEAD(sctpnetlisthead, sctp_nets);
struct sctp_stream_reset_list {
TAILQ_ENTRY(sctp_stream_reset_list) next_resp;
+ uint32_t seq;
uint32_t tsn;
uint32_t number_entries;
uint16_t list_of_streams[];
@@ -580,11 +581,20 @@ union scheduling_parameters {
struct ss_fb fb;
};
+/* States for outgoing streams */
+#define SCTP_STREAM_CLOSED 0x00
+#define SCTP_STREAM_OPENING 0x01
+#define SCTP_STREAM_OPEN 0x02
+#define SCTP_STREAM_RESET_PENDING 0x03
+#define SCTP_STREAM_RESET_IN_FLIGHT 0x04
+
+#define SCTP_MAX_STREAMS_AT_ONCE_RESET 200
+
/* This struct is used to track the traffic on outbound streams */
struct sctp_stream_out {
struct sctp_streamhead outqueue;
union scheduling_parameters ss_params;
- uint32_t chunks_on_queues;
+ uint32_t chunks_on_queues; /* send queue and sent queue */
#if defined(SCTP_DETAILED_STR_STATS)
uint32_t abandoned_unsent[SCTP_PR_SCTP_MAX + 1];
uint32_t abandoned_sent[SCTP_PR_SCTP_MAX + 1];
@@ -596,6 +606,7 @@ struct sctp_stream_out {
uint16_t stream_no;
uint16_t next_sequence_send; /* next one I expect to send out */
uint8_t last_msg_incomplete;
+ uint8_t state;
};
/* used to keep track of the addresses yet to try to add/delete */
@@ -1148,7 +1159,7 @@ struct sctp_association {
uint8_t hb_random_idx;
uint8_t default_dscp;
uint8_t asconf_del_pending; /* asconf delete last addr pending */
-
+ uint8_t trigger_reset;
/*
* This value, plus all other ack'd but above cum-ack is added
* together to cross check against the bit that we have yet to
diff --git a/sys/netinet/sctp_sysctl.c b/sys/netinet/sctp_sysctl.c
index 997ee53..1b35af7 100644
--- a/sys/netinet/sctp_sysctl.c
+++ b/sys/netinet/sctp_sysctl.c
@@ -453,7 +453,7 @@ sctp_sysctl_handle_assoclist(SYSCTL_HANDLER_ARGS)
if (stcb->asoc.primary_destination != NULL)
xstcb.primary_addr = stcb->asoc.primary_destination->ro._l_addr;
xstcb.heartbeat_interval = stcb->asoc.heart_beat_delay;
- xstcb.state = SCTP_GET_STATE(&stcb->asoc); /* FIXME */
+ xstcb.state = (uint32_t) sctp_map_assoc_state(stcb->asoc.state);
/* 7.0 does not support these */
xstcb.assoc_id = sctp_get_associd(stcb);
xstcb.peers_rwnd = stcb->asoc.peers_rwnd;
@@ -511,6 +511,7 @@ sctp_sysctl_handle_assoclist(SYSCTL_HANDLER_ARGS)
xraddr.mtu = net->mtu;
xraddr.rtt = net->rtt / 1000;
xraddr.heartbeat_interval = net->heart_beat_delay;
+ xraddr.ssthresh = net->ssthresh;
xraddr.start_time.tv_sec = (uint32_t) net->start_time.tv_sec;
xraddr.start_time.tv_usec = (uint32_t) net->start_time.tv_usec;
SCTP_INP_RUNLOCK(inp);
diff --git a/sys/netinet/sctp_sysctl.h b/sys/netinet/sctp_sysctl.h
index 857bda1..8233343 100644
--- a/sys/netinet/sctp_sysctl.h
+++ b/sys/netinet/sctp_sysctl.h
@@ -291,10 +291,10 @@ struct sctp_sysctl {
#define SCTPCTL_PMTU_RAISE_TIME_DEFAULT SCTP_DEF_PMTU_RAISE_SEC
/* shutdown_guard_time: Default shutdown guard timer in seconds */
-#define SCTPCTL_SHUTDOWN_GUARD_TIME_DESC "Default shutdown guard timer in seconds"
+#define SCTPCTL_SHUTDOWN_GUARD_TIME_DESC "Shutdown guard timer in seconds (0 means 5 times RTO.Max)"
#define SCTPCTL_SHUTDOWN_GUARD_TIME_MIN 0
#define SCTPCTL_SHUTDOWN_GUARD_TIME_MAX 0xFFFFFFFF
-#define SCTPCTL_SHUTDOWN_GUARD_TIME_DEFAULT SCTP_DEF_MAX_SHUTDOWN_SEC
+#define SCTPCTL_SHUTDOWN_GUARD_TIME_DEFAULT 0
/* secret_lifetime: Default secret lifetime in seconds */
#define SCTPCTL_SECRET_LIFETIME_DESC "Default secret lifetime in seconds"
diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c
index 257d188..0d684b3 100644
--- a/sys/netinet/sctp_timer.c
+++ b/sys/netinet/sctp_timer.c
@@ -153,7 +153,7 @@ sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
/* Abort notification sends a ULP notify */
struct mbuf *op_err;
- op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION,
+ op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
"Association error counter exceeded");
inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_2;
sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED);
@@ -408,7 +408,11 @@ sctp_backoff_on_timeout(struct sctp_tcb *stcb,
int num_marked, int num_abandoned)
{
if (net->RTO == 0) {
- net->RTO = stcb->asoc.minrto;
+ if (net->RTO_measured) {
+ net->RTO = stcb->asoc.minrto;
+ } else {
+ net->RTO = stcb->asoc.initial_rto;
+ }
}
net->RTO <<= 1;
if (net->RTO > stcb->asoc.maxrto) {
@@ -438,6 +442,11 @@ sctp_recover_sent_list(struct sctp_tcb *stcb)
asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--;
}
}
+ if ((asoc->strmout[chk->rec.data.stream_number].chunks_on_queues == 0) &&
+ (asoc->strmout[chk->rec.data.stream_number].state == SCTP_STREAM_RESET_PENDING) &&
+ TAILQ_EMPTY(&asoc->strmout[chk->rec.data.stream_number].outqueue)) {
+ asoc->trigger_reset = 1;
+ }
TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
if (PR_SCTP_ENABLED(chk->flags)) {
if (asoc->pr_sctp_cnt != 0)
@@ -1046,7 +1055,7 @@ sctp_cookie_timer(struct sctp_inpcb *inp,
/* FOOBAR! */
struct mbuf *op_err;
- op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION,
+ op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
"Cookie timer expired, but no cookie");
inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_3;
sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED);
@@ -1492,6 +1501,8 @@ sctp_pathmtu_timer(struct sctp_inpcb *inp,
#endif
if (mtu > next_mtu) {
net->mtu = next_mtu;
+ } else {
+ net->mtu = mtu;
}
}
}
diff --git a/sys/netinet/sctp_uio.h b/sys/netinet/sctp_uio.h
index 9305413..ee31543 100644
--- a/sys/netinet/sctp_uio.h
+++ b/sys/netinet/sctp_uio.h
@@ -134,20 +134,27 @@ struct sctp_extrcvinfo {
uint16_t sinfo_flags;
uint32_t sinfo_ppid;
uint32_t sinfo_context;
- uint32_t sinfo_timetolive;
+ uint32_t sinfo_timetolive; /* should have been sinfo_pr_value */
uint32_t sinfo_tsn;
uint32_t sinfo_cumtsn;
sctp_assoc_t sinfo_assoc_id;
- uint16_t sreinfo_next_flags;
- uint16_t sreinfo_next_stream;
- uint32_t sreinfo_next_aid;
- uint32_t sreinfo_next_length;
- uint32_t sreinfo_next_ppid;
+ uint16_t serinfo_next_flags;
+ uint16_t serinfo_next_stream;
+ uint32_t serinfo_next_aid;
+ uint32_t serinfo_next_length;
+ uint32_t serinfo_next_ppid;
uint16_t sinfo_keynumber;
uint16_t sinfo_keynumber_valid;
uint8_t __reserve_pad[SCTP_ALIGN_RESV_PAD_SHORT];
};
+#define sinfo_pr_value sinfo_timetolive
+#define sreinfo_next_flags serinfo_next_flags
+#define sreinfo_next_stream serinfo_next_stream
+#define sreinfo_next_aid serinfo_next_aid
+#define sreinfo_next_length serinfo_next_length
+#define sreinfo_next_ppid serinfo_next_ppid
+
struct sctp_sndinfo {
uint16_t snd_sid;
uint16_t snd_flags;
@@ -1229,7 +1236,8 @@ struct xsctp_raddr {
struct sctp_timeval start_time; /* sctpAssocLocalRemEntry 8 */
uint32_t rtt;
uint32_t heartbeat_interval;
- uint32_t extra_padding[31]; /* future */
+ uint32_t ssthresh;
+ uint32_t extra_padding[30]; /* future */
};
#define SCTP_MAX_LOGGING_SIZE 30000
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
index 907412c..2ea4eed 100644
--- a/sys/netinet/sctp_usrreq.c
+++ b/sys/netinet/sctp_usrreq.c
@@ -487,11 +487,6 @@ sctp_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNUS
int error;
uint32_t vrf_id = SCTP_DEFAULT_VRFID;
-#ifdef IPSEC
- uint32_t flags;
-
-#endif
-
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp != 0) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
@@ -513,33 +508,6 @@ sctp_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNUS
ip_inp = &inp->ip_inp.inp;
ip_inp->inp_vflag |= INP_IPV4;
ip_inp->inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
-#ifdef IPSEC
- error = ipsec_init_policy(so, &ip_inp->inp_sp);
-#ifdef SCTP_LOG_CLOSING
- sctp_log_closing(inp, NULL, 17);
-#endif
- if (error != 0) {
-try_again:
- flags = inp->sctp_flags;
- if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
- (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
-#ifdef SCTP_LOG_CLOSING
- sctp_log_closing(inp, NULL, 15);
-#endif
- SCTP_INP_WUNLOCK(inp);
- sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
- SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
- } else {
- flags = inp->sctp_flags;
- if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
- goto try_again;
- } else {
- SCTP_INP_WUNLOCK(inp);
- }
- }
- return (error);
- }
-#endif /* IPSEC */
SCTP_INP_WUNLOCK(inp);
return (0);
}
@@ -957,14 +925,15 @@ sctp_shutdown(struct socket *so)
SCTP_INP_RUNLOCK(inp);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
return (EOPNOTSUPP);
- }
- /*
- * Ok if we reach here its the TCP model and it is either a SHUT_WR
- * or SHUT_RDWR. This means we put the shutdown flag against it.
- */
- {
+ } else {
+ /*
+ * Ok, if we reach here its the TCP model and it is either a
+ * SHUT_WR or SHUT_RDWR. This means we put the shutdown flag
+ * against it.
+ */
struct sctp_tcb *stcb;
struct sctp_association *asoc;
+ struct sctp_nets *netp;
if ((so->so_state &
(SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING)) == 0) {
@@ -976,7 +945,7 @@ sctp_shutdown(struct socket *so)
stcb = LIST_FIRST(&inp->sctp_asoc_list);
if (stcb == NULL) {
/*
- * Ok we hit the case that the shutdown call was
+ * Ok, we hit the case that the shutdown call was
* made after an abort or something. Nothing to do
* now.
*/
@@ -985,53 +954,48 @@ sctp_shutdown(struct socket *so)
}
SCTP_TCB_LOCK(stcb);
asoc = &stcb->asoc;
- if (TAILQ_EMPTY(&asoc->send_queue) &&
+ if (asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) {
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_INP_RUNLOCK(inp);
+ return (0);
+ }
+ if ((SCTP_GET_STATE(asoc) != SCTP_STATE_COOKIE_WAIT) &&
+ (SCTP_GET_STATE(asoc) != SCTP_STATE_COOKIE_ECHOED) &&
+ (SCTP_GET_STATE(asoc) != SCTP_STATE_OPEN)) {
+ /*
+ * If we are not in or before ESTABLISHED, there is
+ * no protocol action required.
+ */
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_INP_RUNLOCK(inp);
+ return (0);
+ }
+ if (stcb->asoc.alternate) {
+ netp = stcb->asoc.alternate;
+ } else {
+ netp = stcb->asoc.primary_destination;
+ }
+ if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) &&
+ TAILQ_EMPTY(&asoc->send_queue) &&
TAILQ_EMPTY(&asoc->sent_queue) &&
(asoc->stream_queue_cnt == 0)) {
if (asoc->locked_on_sending) {
goto abort_anyway;
}
/* there is nothing queued to send, so I'm done... */
- if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) {
- /* only send SHUTDOWN the first time through */
- struct sctp_nets *netp;
-
- if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
- (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
- SCTP_STAT_DECR_GAUGE32(sctps_currestab);
- }
- SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
- SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
- sctp_stop_timers_for_shutdown(stcb);
- if (stcb->asoc.alternate) {
- netp = stcb->asoc.alternate;
- } else {
- netp = stcb->asoc.primary_destination;
- }
- sctp_send_shutdown(stcb, netp);
- sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
- stcb->sctp_ep, stcb, netp);
- sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
- stcb->sctp_ep, stcb, netp);
- sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED);
- }
+ SCTP_STAT_DECR_GAUGE32(sctps_currestab);
+ SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
+ SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
+ sctp_stop_timers_for_shutdown(stcb);
+ sctp_send_shutdown(stcb, netp);
+ sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
+ stcb->sctp_ep, stcb, netp);
} else {
/*
- * we still got (or just got) data to send, so set
- * SHUTDOWN_PENDING
+ * We still got (or just got) data to send, so set
+ * SHUTDOWN_PENDING.
*/
- struct sctp_nets *netp;
-
- if (stcb->asoc.alternate) {
- netp = stcb->asoc.alternate;
- } else {
- netp = stcb->asoc.primary_destination;
- }
-
- asoc->state |= SCTP_STATE_SHUTDOWN_PENDING;
- sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
- netp);
-
+ SCTP_ADD_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
if (asoc->locked_on_sending) {
/* Locked to send out the data */
struct sctp_stream_queue_pending *sp;
@@ -1042,7 +1006,7 @@ sctp_shutdown(struct socket *so)
asoc->locked_on_sending->stream_no);
} else {
if ((sp->length == 0) && (sp->msg_is_complete == 0)) {
- asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT;
+ SCTP_ADD_SUBSTATE(asoc, SCTP_STATE_PARTIAL_MSG_LEFT);
}
}
}
@@ -1056,16 +1020,20 @@ sctp_shutdown(struct socket *so)
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6;
sctp_abort_an_association(stcb->sctp_ep, stcb,
op_err, SCTP_SO_LOCKED);
- goto skip_unlock;
- } else {
- sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
+ SCTP_INP_RUNLOCK(inp);
+ return (0);
}
}
+ sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb, netp);
+ /*
+ * XXX: Why do this in the case where we have still data
+ * queued?
+ */
+ sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
SCTP_TCB_UNLOCK(stcb);
+ SCTP_INP_RUNLOCK(inp);
+ return (0);
}
-skip_unlock:
- SCTP_INP_RUNLOCK(inp);
- return (0);
}
/*
@@ -1533,6 +1501,7 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
/* We are GOOD to go */
stcb = sctp_aloc_assoc(inp, sa, &error, 0, vrf_id,
+ inp->sctp_ep.pre_open_stream_count,
(struct thread *)p
);
if (stcb == NULL) {
@@ -1914,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++;
}
@@ -1930,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);
@@ -2668,12 +2651,7 @@ flags_out:
error = EINVAL;
break;
}
- /*
- * I think passing the state is fine since
- * sctp_constants.h will be available to the user
- * land.
- */
- sstat->sstat_state = stcb->asoc.state;
+ sstat->sstat_state = sctp_map_assoc_state(stcb->asoc.state);
sstat->sstat_assoc_id = sctp_get_associd(stcb);
sstat->sstat_rwnd = stcb->asoc.peers_rwnd;
sstat->sstat_unackdata = stcb->asoc.sent_queue_cnt;
@@ -4620,18 +4598,24 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_TCB_UNLOCK(stcb);
break;
}
- if (stcb->asoc.stream_reset_outstanding) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
- error = EALREADY;
- SCTP_TCB_UNLOCK(stcb);
- break;
- }
if (strrst->srs_flags & SCTP_STREAM_RESET_INCOMING) {
send_in = 1;
+ if (stcb->asoc.stream_reset_outstanding) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
+ error = EALREADY;
+ SCTP_TCB_UNLOCK(stcb);
+ break;
+ }
}
if (strrst->srs_flags & SCTP_STREAM_RESET_OUTGOING) {
send_out = 1;
}
+ if ((strrst->srs_number_streams > SCTP_MAX_STREAMS_AT_ONCE_RESET) && send_in) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
+ error = ENOMEM;
+ SCTP_TCB_UNLOCK(stcb);
+ break;
+ }
if ((send_in == 0) && (send_out == 0)) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
@@ -4656,11 +4640,46 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_TCB_UNLOCK(stcb);
break;
}
- error = sctp_send_str_reset_req(stcb, strrst->srs_number_streams,
- strrst->srs_stream_list,
- send_out, send_in, 0, 0, 0, 0, 0);
-
- sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
+ if (send_out) {
+ int cnt;
+ uint16_t strm;
+
+ if (strrst->srs_number_streams) {
+ for (i = 0, cnt = 0; i < strrst->srs_number_streams; i++) {
+ strm = strrst->srs_stream_list[i];
+ if (stcb->asoc.strmout[strm].state == SCTP_STREAM_OPEN) {
+ stcb->asoc.strmout[strm].state = SCTP_STREAM_RESET_PENDING;
+ cnt++;
+ }
+ }
+ } else {
+ /* Its all */
+ for (i = 0, cnt = 0; i < stcb->asoc.streamoutcnt; i++) {
+ if (stcb->asoc.strmout[i].state == SCTP_STREAM_OPEN) {
+ stcb->asoc.strmout[i].state = SCTP_STREAM_RESET_PENDING;
+ cnt++;
+ }
+ }
+ }
+ }
+ if (send_in) {
+ error = sctp_send_str_reset_req(stcb, strrst->srs_number_streams,
+ strrst->srs_stream_list,
+ send_in, 0, 0, 0, 0, 0);
+ } else {
+ error = sctp_send_stream_reset_out_if_possible(stcb, SCTP_SO_LOCKED);
+ }
+ if (error == 0) {
+ sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
+ } else {
+ /*
+ * For outgoing streams don't report any
+ * problems in sending the request to the
+ * application. XXX: Double check resetting
+ * incoming streams.
+ */
+ error = 0;
+ }
SCTP_TCB_UNLOCK(stcb);
break;
}
@@ -4730,7 +4749,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
goto skip_stuff;
}
}
- error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 0, addstream, add_o_strmcnt, add_i_strmcnt, 0);
+ error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, addstream, add_o_strmcnt, add_i_strmcnt, 0);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
skip_stuff:
SCTP_TCB_UNLOCK(stcb);
@@ -4738,6 +4757,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
case SCTP_RESET_ASSOC:
{
+ int i;
uint32_t *value;
SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
@@ -4762,7 +4782,25 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_TCB_UNLOCK(stcb);
break;
}
- error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 1, 0, 0, 0, 0);
+ /*
+ * Is there any data pending in the send or sent
+ * queues?
+ */
+ if (!TAILQ_EMPTY(&stcb->asoc.send_queue) ||
+ !TAILQ_EMPTY(&stcb->asoc.sent_queue)) {
+ busy_out:
+ error = EBUSY;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
+ SCTP_TCB_UNLOCK(stcb);
+ break;
+ }
+ /* Do any streams have data queued? */
+ for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
+ if (!TAILQ_EMPTY(&stcb->asoc.strmout[i].outqueue)) {
+ goto busy_out;
+ }
+ }
+ error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 1, 0, 0, 0, 0);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
SCTP_TCB_UNLOCK(stcb);
break;
@@ -5769,7 +5807,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
if (laddr->ifa == NULL) {
SCTPDBG(SCTP_DEBUG_OUTPUT1, "%s: NULL ifa\n",
- __FUNCTION__);
+ __func__);
continue;
}
if (laddr->ifa == ifa) {
@@ -6906,7 +6944,7 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
}
vrf_id = inp->def_vrf_id;
/* We are GOOD to go */
- stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, p);
+ stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, inp->sctp_ep.pre_open_stream_count, p);
if (stcb == NULL) {
/* Gak! no memory */
goto out_now;
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index c25ec39..4cf134b 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -893,9 +893,52 @@ sctp_select_a_tag(struct sctp_inpcb *inp, uint16_t lport, uint16_t rport, int ch
return (x);
}
+int32_t
+sctp_map_assoc_state(int kernel_state)
+{
+ int32_t user_state;
+
+ if (kernel_state & SCTP_STATE_WAS_ABORTED) {
+ user_state = SCTP_CLOSED;
+ } else if (kernel_state & SCTP_STATE_SHUTDOWN_PENDING) {
+ user_state = SCTP_SHUTDOWN_PENDING;
+ } else {
+ switch (kernel_state & SCTP_STATE_MASK) {
+ case SCTP_STATE_EMPTY:
+ user_state = SCTP_CLOSED;
+ break;
+ case SCTP_STATE_INUSE:
+ user_state = SCTP_CLOSED;
+ break;
+ case SCTP_STATE_COOKIE_WAIT:
+ user_state = SCTP_COOKIE_WAIT;
+ break;
+ case SCTP_STATE_COOKIE_ECHOED:
+ user_state = SCTP_COOKIE_ECHOED;
+ break;
+ case SCTP_STATE_OPEN:
+ user_state = SCTP_ESTABLISHED;
+ break;
+ case SCTP_STATE_SHUTDOWN_SENT:
+ user_state = SCTP_SHUTDOWN_SENT;
+ break;
+ case SCTP_STATE_SHUTDOWN_RECEIVED:
+ user_state = SCTP_SHUTDOWN_RECEIVED;
+ break;
+ case SCTP_STATE_SHUTDOWN_ACK_SENT:
+ user_state = SCTP_SHUTDOWN_ACK_SENT;
+ break;
+ default:
+ user_state = SCTP_CLOSED;
+ break;
+ }
+ }
+ return (user_state);
+}
+
int
sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
- uint32_t override_tag, uint32_t vrf_id)
+ uint32_t override_tag, uint32_t vrf_id, uint16_t o_strms)
{
struct sctp_association *asoc;
@@ -1057,7 +1100,7 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
* that we request by default.
*/
asoc->strm_realoutsize = asoc->streamoutcnt = asoc->pre_open_streams =
- inp->sctp_ep.pre_open_stream_count;
+ o_strms;
SCTP_MALLOC(asoc->strmout, struct sctp_stream_out *,
asoc->streamoutcnt * sizeof(struct sctp_stream_out),
SCTP_M_STRMO);
@@ -1089,6 +1132,7 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
#endif
asoc->strmout[i].stream_no = i;
asoc->strmout[i].last_msg_incomplete = 0;
+ asoc->strmout[i].state = SCTP_STREAM_OPENING;
asoc->ss_functions.sctp_ss_init_stream(&asoc->strmout[i], NULL);
}
asoc->ss_functions.sctp_ss_init(stcb, asoc, 0);
@@ -1444,12 +1488,14 @@ sctp_timeout_handler(void *t)
struct sctp_tcb *stcb;
struct sctp_nets *net;
struct sctp_timer *tmr;
+ struct mbuf *op_err;
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so;
#endif
int did_output;
+ int type;
tmr = (struct sctp_timer *)t;
inp = (struct sctp_inpcb *)tmr->ep;
@@ -1518,8 +1564,9 @@ sctp_timeout_handler(void *t)
return;
}
}
+ type = tmr->type;
tmr->stopped_from = 0xa005;
- SCTPDBG(SCTP_DEBUG_TIMER1, "Timer type %d goes off\n", tmr->type);
+ SCTPDBG(SCTP_DEBUG_TIMER1, "Timer type %d goes off\n", type);
if (!SCTP_OS_TIMER_ACTIVE(&tmr->timer)) {
if (inp) {
SCTP_INP_DECR_REF(inp);
@@ -1535,7 +1582,7 @@ sctp_timeout_handler(void *t)
if (stcb) {
SCTP_TCB_LOCK(stcb);
atomic_add_int(&stcb->asoc.refcnt, -1);
- if ((tmr->type != SCTP_TIMER_TYPE_ASOCKILL) &&
+ if ((type != SCTP_TIMER_TYPE_ASOCKILL) &&
((stcb->asoc.state == 0) ||
(stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED))) {
SCTP_TCB_UNLOCK(stcb);
@@ -1547,7 +1594,7 @@ sctp_timeout_handler(void *t)
}
}
/* record in stopped what t-o occured */
- tmr->stopped_from = tmr->type;
+ tmr->stopped_from = type;
/* mark as being serviced now */
if (SCTP_OS_TIMER_PENDING(&tmr->timer)) {
@@ -1565,7 +1612,7 @@ sctp_timeout_handler(void *t)
SCTP_OS_TIMER_DEACTIVATE(&tmr->timer);
/* call the handler for the appropriate timer type */
- switch (tmr->type) {
+ switch (type) {
case SCTP_TIMER_TYPE_ZERO_COPY:
if (inp == NULL) {
break;
@@ -1755,7 +1802,9 @@ sctp_timeout_handler(void *t)
break;
}
SCTP_STAT_INCR(sctps_timoshutdownguard);
- sctp_abort_an_association(inp, stcb, NULL, SCTP_SO_NOT_LOCKED);
+ op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
+ "Shutdown guard timer expired");
+ sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED);
/* no need to unlock on tcb its gone */
goto out_decr;
@@ -1847,11 +1896,11 @@ sctp_timeout_handler(void *t)
goto out_no_decr;
default:
SCTPDBG(SCTP_DEBUG_TIMER1, "sctp_timeout_handler:unknown timer %d\n",
- tmr->type);
+ type);
break;
}
#ifdef SCTP_AUDITING_ENABLED
- sctp_audit_log(0xF1, (uint8_t) tmr->type);
+ sctp_audit_log(0xF1, (uint8_t) type);
if (inp)
sctp_auditing(5, inp, stcb, net);
#endif
@@ -1874,8 +1923,7 @@ out_decr:
SCTP_INP_DECR_REF(inp);
}
out_no_decr:
- SCTPDBG(SCTP_DEBUG_TIMER1, "Timer now complete (type %d)\n",
- tmr->type);
+ SCTPDBG(SCTP_DEBUG_TIMER1, "Timer now complete (type = %d)\n", type);
CURVNET_RESTORE();
}
@@ -2076,7 +2124,11 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
if (stcb == NULL) {
return;
}
- to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_MAXSHUTDOWN];
+ if (inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_MAXSHUTDOWN] == 0) {
+ to_ticks = 5 * MSEC_TO_TICKS(stcb->asoc.maxrto);
+ } else {
+ to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_MAXSHUTDOWN];
+ }
tmr = &stcb->asoc.shut_guard_timer;
break;
case SCTP_TIMER_TYPE_STRRESET:
@@ -2132,13 +2184,13 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
break;
default:
SCTPDBG(SCTP_DEBUG_TIMER1, "%s: Unknown timer type %d\n",
- __FUNCTION__, t_type);
+ __func__, t_type);
return;
break;
}
if ((to_ticks <= 0) || (tmr == NULL)) {
SCTPDBG(SCTP_DEBUG_TIMER1, "%s: %d:software error to_ticks:%d tmr:%p not set ??\n",
- __FUNCTION__, t_type, to_ticks, (void *)tmr);
+ __func__, t_type, to_ticks, (void *)tmr);
return;
}
if (SCTP_OS_TIMER_PENDING(&tmr->timer)) {
@@ -2294,7 +2346,7 @@ sctp_timer_stop(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
break;
default:
SCTPDBG(SCTP_DEBUG_TIMER1, "%s: Unknown timer type %d\n",
- __FUNCTION__, t_type);
+ __func__, t_type);
break;
}
if (tmr == NULL) {
@@ -2616,6 +2668,9 @@ sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb,
#endif
+ if (stcb == NULL) {
+ return;
+ }
if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT)) {
notif_len = sizeof(struct sctp_assoc_change);
if (abort != NULL) {
@@ -3723,7 +3778,7 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
break;
default:
SCTPDBG(SCTP_DEBUG_UTIL1, "%s: unknown notification %xh (%u)\n",
- __FUNCTION__, notification, notification);
+ __func__, notification, notification);
break;
} /* end switch */
}
@@ -5600,20 +5655,20 @@ found_one:
s_extra = (struct sctp_extrcvinfo *)sinfo;
if ((nxt) &&
(nxt->length)) {
- s_extra->sreinfo_next_flags = SCTP_NEXT_MSG_AVAIL;
+ s_extra->serinfo_next_flags = SCTP_NEXT_MSG_AVAIL;
if (nxt->sinfo_flags & SCTP_UNORDERED) {
- s_extra->sreinfo_next_flags |= SCTP_NEXT_MSG_IS_UNORDERED;
+ s_extra->serinfo_next_flags |= SCTP_NEXT_MSG_IS_UNORDERED;
}
if (nxt->spec_flags & M_NOTIFICATION) {
- s_extra->sreinfo_next_flags |= SCTP_NEXT_MSG_IS_NOTIFICATION;
+ s_extra->serinfo_next_flags |= SCTP_NEXT_MSG_IS_NOTIFICATION;
}
- s_extra->sreinfo_next_aid = nxt->sinfo_assoc_id;
- s_extra->sreinfo_next_length = nxt->length;
- s_extra->sreinfo_next_ppid = nxt->sinfo_ppid;
- s_extra->sreinfo_next_stream = nxt->sinfo_stream;
+ s_extra->serinfo_next_aid = nxt->sinfo_assoc_id;
+ s_extra->serinfo_next_length = nxt->length;
+ s_extra->serinfo_next_ppid = nxt->sinfo_ppid;
+ s_extra->serinfo_next_stream = nxt->sinfo_stream;
if (nxt->tail_mbuf != NULL) {
if (nxt->end_added) {
- s_extra->sreinfo_next_flags |= SCTP_NEXT_MSG_ISCOMPLETE;
+ s_extra->serinfo_next_flags |= SCTP_NEXT_MSG_ISCOMPLETE;
}
}
} else {
@@ -5624,11 +5679,11 @@ found_one:
* :-D
*/
nxt = NULL;
- s_extra->sreinfo_next_flags = SCTP_NO_NEXT_MSG;
- s_extra->sreinfo_next_aid = 0;
- s_extra->sreinfo_next_length = 0;
- s_extra->sreinfo_next_ppid = 0;
- s_extra->sreinfo_next_stream = 0;
+ s_extra->serinfo_next_flags = SCTP_NO_NEXT_MSG;
+ s_extra->serinfo_next_aid = 0;
+ s_extra->serinfo_next_length = 0;
+ s_extra->serinfo_next_ppid = 0;
+ s_extra->serinfo_next_stream = 0;
}
}
/*
@@ -6111,7 +6166,7 @@ out:
struct sctp_extrcvinfo *s_extra;
s_extra = (struct sctp_extrcvinfo *)sinfo;
- s_extra->sreinfo_next_flags = SCTP_NO_NEXT_MSG;
+ s_extra->serinfo_next_flags = SCTP_NO_NEXT_MSG;
}
if (hold_rlock == 1) {
SCTP_INP_READ_UNLOCK(inp);
@@ -6855,7 +6910,7 @@ sctp_log_trace(uint32_t subsys, const char *str SCTP_UNUSED, uint32_t a, uint32_
#endif
static void
-sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *ignored,
+sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *inp,
const struct sockaddr *sa SCTP_UNUSED, void *ctx SCTP_UNUSED)
{
struct ip *iph;
@@ -6903,6 +6958,18 @@ sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *ignored,
for (last = m; last->m_next; last = last->m_next);
last->m_next = sp;
m->m_pkthdr.len += sp->m_pkthdr.len;
+ /*
+ * The CSUM_DATA_VALID flags indicates that the HW checked the UDP
+ * checksum and it was valid. Since CSUM_DATA_VALID ==
+ * CSUM_SCTP_VALID this would imply that the HW also verified the
+ * SCTP checksum. Therefore, clear the bit.
+ */
+ SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
+ "sctp_recv_udp_tunneled_packet(): Packet of length %d received on %s with csum_flags 0x%b.\n",
+ m->m_pkthdr.len,
+ if_name(m->m_pkthdr.rcvif),
+ (int)m->m_pkthdr.csum_flags, CSUM_BITS);
+ m->m_pkthdr.csum_flags &= ~CSUM_DATA_VALID;
iph = mtod(m, struct ip *);
switch (iph->ip_v) {
#ifdef INET
diff --git a/sys/netinet/sctputil.h b/sys/netinet/sctputil.h
index 7df0a6c..354d40e 100644
--- a/sys/netinet/sctputil.h
+++ b/sys/netinet/sctputil.h
@@ -67,6 +67,9 @@ void
/*
* Function prototypes
*/
+int32_t
+sctp_map_assoc_state(int);
+
uint32_t
sctp_get_ifa_hash_val(struct sockaddr *addr);
@@ -80,7 +83,7 @@ uint32_t sctp_select_initial_TSN(struct sctp_pcb *);
uint32_t sctp_select_a_tag(struct sctp_inpcb *, uint16_t lport, uint16_t rport, int);
-int sctp_init_asoc(struct sctp_inpcb *, struct sctp_tcb *, uint32_t, uint32_t);
+int sctp_init_asoc(struct sctp_inpcb *, struct sctp_tcb *, uint32_t, uint32_t, uint16_t);
void sctp_fill_random_store(struct sctp_pcb *);
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 3ce21a9..c0add82 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -341,7 +341,7 @@ tcp_init(void)
*/
if (hashsize < 512)
hashsize = 512;
- if (bootverbose)
+ if (bootverbose && IS_DEFAULT_VNET(curvnet))
printf("%s: %s auto tuned to %d\n", __func__,
tcbhash_tuneable, hashsize);
}
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index 3baaa93..e3c3229 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -2003,7 +2003,7 @@ in6ifa_llaonifp(struct ifnet *ifp)
if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)
return (NULL);
- if_addr_rlock(ifp);
+ IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
@@ -2013,7 +2013,7 @@ in6ifa_llaonifp(struct ifnet *ifp)
IN6_IS_ADDR_MC_NODELOCAL(&sin6->sin6_addr))
break;
}
- if_addr_runlock(ifp);
+ IF_ADDR_RUNLOCK(ifp);
return ((struct in6_ifaddr *)ifa);
}
diff --git a/sys/netinet6/sctp6_usrreq.c b/sys/netinet6/sctp6_usrreq.c
index 7670289..6749875 100644
--- a/sys/netinet6/sctp6_usrreq.c
+++ b/sys/netinet6/sctp6_usrreq.c
@@ -39,9 +39,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/sctp_pcb.h>
#include <netinet/sctp_header.h>
#include <netinet/sctp_var.h>
-#ifdef INET6
#include <netinet6/sctp6_var.h>
-#endif
#include <netinet/sctp_sysctl.h>
#include <netinet/sctp_output.h>
#include <netinet/sctp_uio.h>
@@ -54,13 +52,12 @@ __FBSDID("$FreeBSD$");
#include <netinet/sctp_output.h>
#include <netinet/sctp_bsd_addr.h>
#include <netinet/sctp_crc32.h>
+#include <netinet/icmp6.h>
#include <netinet/udp.h>
#ifdef IPSEC
#include <netipsec/ipsec.h>
-#ifdef INET6
#include <netipsec/ipsec6.h>
-#endif /* INET6 */
#endif /* IPSEC */
extern struct protosw inetsw[];
@@ -956,7 +953,7 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
return (EALREADY);
}
/* We are GOOD to go */
- stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, p);
+ stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, inp->sctp_ep.pre_open_stream_count, p);
SCTP_ASOC_CREATE_UNLOCK(inp);
if (stcb == NULL) {
/* Gak! no memory */
diff --git a/sys/ofed/include/linux/linux_compat.c b/sys/ofed/include/linux/linux_compat.c
index ef44c6d..92b6ac7 100644
--- a/sys/ofed/include/linux/linux_compat.c
+++ b/sys/ofed/include/linux/linux_compat.c
@@ -480,7 +480,7 @@ linux_dev_mmap_single(struct cdev *dev, vm_ooffset_t *offset,
vma.vm_end = size;
vma.vm_pgoff = *offset / PAGE_SIZE;
vma.vm_pfn = 0;
- vma.vm_page_prot = 0;
+ vma.vm_page_prot = VM_MEMATTR_DEFAULT;
if (filp->f_op->mmap) {
error = -filp->f_op->mmap(filp, &vma);
if (error == 0) {
diff --git a/sys/powerpc/powerpc/busdma_machdep.c b/sys/powerpc/powerpc/busdma_machdep.c
index 9ea51ce..1e57d92 100644
--- a/sys/powerpc/powerpc/busdma_machdep.c
+++ b/sys/powerpc/powerpc/busdma_machdep.c
@@ -514,14 +514,14 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
/*
* XXX:
- * (dmat->alignment < dmat->maxsize) is just a quick hack; the exact
+ * (dmat->alignment <= dmat->maxsize) is just a quick hack; the exact
* alignment guarantees of malloc need to be nailed down, and the
* code below should be rewritten to take that into account.
*
* In the meantime, we'll warn the user if malloc gets it wrong.
*/
if ((dmat->maxsize <= PAGE_SIZE) &&
- (dmat->alignment < dmat->maxsize) &&
+ (dmat->alignment <= dmat->maxsize) &&
dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem) &&
attr == VM_MEMATTR_DEFAULT) {
*vaddr = malloc(dmat->maxsize, M_DEVBUF, mflags);
diff --git a/sys/powerpc/powerpc/elf32_machdep.c b/sys/powerpc/powerpc/elf32_machdep.c
index e8d563a..6b3a9af 100644
--- a/sys/powerpc/powerpc/elf32_machdep.c
+++ b/sys/powerpc/powerpc/elf32_machdep.c
@@ -108,6 +108,7 @@ struct sysentvec elf32_freebsd_sysvec = {
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
+ .sv_trap = NULL,
};
INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec);
diff --git a/sys/powerpc/powerpc/elf64_machdep.c b/sys/powerpc/powerpc/elf64_machdep.c
index 4324266..d871e54 100644
--- a/sys/powerpc/powerpc/elf64_machdep.c
+++ b/sys/powerpc/powerpc/elf64_machdep.c
@@ -84,6 +84,7 @@ struct sysentvec elf64_freebsd_sysvec = {
.sv_shared_page_len = PAGE_SIZE,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
+ .sv_trap = NULL,
};
INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec);
diff --git a/sys/security/audit/audit_worker.c b/sys/security/audit/audit_worker.c
index caad5ac..f526cd4 100644
--- a/sys/security/audit/audit_worker.c
+++ b/sys/security/audit/audit_worker.c
@@ -71,6 +71,8 @@ __FBSDID("$FreeBSD$");
#include <vm/uma.h>
+#include <machine/stdarg.h>
+
/*
* Worker thread that will schedule disk I/O, etc.
*/
@@ -98,6 +100,26 @@ static struct sx audit_worker_lock;
#define AUDIT_WORKER_LOCK() sx_xlock(&audit_worker_lock)
#define AUDIT_WORKER_UNLOCK() sx_xunlock(&audit_worker_lock)
+static void
+audit_worker_sync_vp(struct vnode *vp, struct mount *mp, const char *fmt, ...)
+{
+ struct mount *mp1;
+ int error;
+ va_list va;
+
+ va_start(va, fmt);
+ error = vn_start_write(vp, &mp1, 0);
+ if (error == 0) {
+ VOP_LOCK(vp, LK_EXCLUSIVE | LK_RETRY);
+ (void)VOP_FSYNC(vp, MNT_WAIT, curthread);
+ VOP_UNLOCK(vp, 0);
+ vn_finished_write(mp1);
+ }
+ vfs_unbusy(mp);
+ vpanic(fmt, va);
+ va_end(va);
+}
+
/*
* Write an audit record to a file, performed as the last stage after both
* preselection and BSM conversion. Both space management and write failures
@@ -114,6 +136,7 @@ audit_record_write(struct vnode *vp, struct ucred *cred, void *data,
static struct timeval last_fail;
static int cur_lowspace_trigger;
struct statfs *mnt_stat;
+ struct mount *mp;
int error;
static int cur_fail;
long temp;
@@ -123,15 +146,25 @@ audit_record_write(struct vnode *vp, struct ucred *cred, void *data,
if (vp == NULL)
return;
- mnt_stat = &vp->v_mount->mnt_stat;
+ mp = vp->v_mount;
+ if (mp == NULL) {
+ error = EINVAL;
+ goto fail;
+ }
+ error = vfs_busy(mp, 0);
+ if (error != 0) {
+ mp = NULL;
+ goto fail;
+ }
+ mnt_stat = &mp->mnt_stat;
/*
* First, gather statistics on the audit log file and file system so
* that we know how we're doing on space. Consider failure of these
* operations to indicate a future inability to write to the file.
*/
- error = VFS_STATFS(vp->v_mount, mnt_stat);
- if (error)
+ error = VFS_STATFS(mp, mnt_stat);
+ if (error != 0)
goto fail;
/*
@@ -246,13 +279,12 @@ audit_record_write(struct vnode *vp, struct ucred *cred, void *data,
*/
if (audit_in_failure) {
if (audit_q_len == 0 && audit_pre_q_len == 0) {
- VOP_LOCK(vp, LK_EXCLUSIVE | LK_RETRY);
- (void)VOP_FSYNC(vp, MNT_WAIT, curthread);
- VOP_UNLOCK(vp, 0);
- panic("Audit store overflow; record queue drained.");
+ audit_worker_sync_vp(vp, mp,
+ "Audit store overflow; record queue drained.");
}
}
+ vfs_unbusy(mp);
return;
fail_enospc:
@@ -262,10 +294,8 @@ fail_enospc:
* space, or ENOSPC returned by the vnode write call.
*/
if (audit_fail_stop) {
- VOP_LOCK(vp, LK_EXCLUSIVE | LK_RETRY);
- (void)VOP_FSYNC(vp, MNT_WAIT, curthread);
- VOP_UNLOCK(vp, 0);
- panic("Audit log space exhausted and fail-stop set.");
+ audit_worker_sync_vp(vp, mp,
+ "Audit log space exhausted and fail-stop set.");
}
(void)audit_send_trigger(AUDIT_TRIGGER_NO_SPACE);
audit_suspended = 1;
@@ -277,12 +307,12 @@ fail:
* lost, which may require an immediate system halt.
*/
if (audit_panic_on_write_fail) {
- VOP_LOCK(vp, LK_EXCLUSIVE | LK_RETRY);
- (void)VOP_FSYNC(vp, MNT_WAIT, curthread);
- VOP_UNLOCK(vp, 0);
- panic("audit_worker: write error %d\n", error);
+ audit_worker_sync_vp(vp, mp,
+ "audit_worker: write error %d\n", error);
} else if (ppsratecheck(&last_fail, &cur_fail, 1))
printf("audit_worker: write error %d\n", error);
+ if (mp != NULL)
+ vfs_unbusy(mp);
}
/*
diff --git a/sys/sparc64/sparc64/bus_machdep.c b/sys/sparc64/sparc64/bus_machdep.c
index 415f43d..fcac25a 100644
--- a/sys/sparc64/sparc64/bus_machdep.c
+++ b/sys/sparc64/sparc64/bus_machdep.c
@@ -521,14 +521,14 @@ nexus_dmamem_alloc(bus_dma_tag_t dmat, void **vaddr, int flags,
/*
* XXX:
- * (dmat->dt_alignment < dmat->dt_maxsize) is just a quick hack; the
+ * (dmat->dt_alignment <= dmat->dt_maxsize) is just a quick hack; the
* exact alignment guarantees of malloc need to be nailed down, and
* the code below should be rewritten to take that into account.
*
* In the meantime, we'll warn the user if malloc gets it wrong.
*/
if (dmat->dt_maxsize <= PAGE_SIZE &&
- dmat->dt_alignment < dmat->dt_maxsize)
+ dmat->dt_alignment <= dmat->dt_maxsize)
*vaddr = malloc(dmat->dt_maxsize, M_DEVBUF, mflags);
else {
/*
diff --git a/sys/sparc64/sparc64/elf_machdep.c b/sys/sparc64/sparc64/elf_machdep.c
index 0dab76d..6ddbd98 100644
--- a/sys/sparc64/sparc64/elf_machdep.c
+++ b/sys/sparc64/sparc64/elf_machdep.c
@@ -88,6 +88,7 @@ static struct sysentvec elf64_freebsd_sysvec = {
.sv_syscallnames = syscallnames,
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
+ .sv_trap = NULL,
};
static Elf64_Brandinfo freebsd_brand_info = {
diff --git a/sys/sparc64/sparc64/machdep.c b/sys/sparc64/sparc64/machdep.c
index dd6f31c..e49e449 100644
--- a/sys/sparc64/sparc64/machdep.c
+++ b/sys/sparc64/sparc64/machdep.c
@@ -383,7 +383,8 @@ sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec)
kmdp = preload_search_by_type("elf kernel");
if (kmdp != NULL) {
boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int);
- kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *);
+ init_static_kenv(MD_FETCH(kmdp, MODINFOMD_ENVP, char *),
+ 0);
end = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t);
kernel_tlb_slots = MD_FETCH(kmdp, MODINFOMD_DTLB_SLOTS,
int);
diff --git a/sys/sys/conf.h b/sys/sys/conf.h
index d72b58b..06c38c1 100644
--- a/sys/sys/conf.h
+++ b/sys/sys/conf.h
@@ -297,9 +297,9 @@ void setconf(void);
#define dev2unit(d) ((d)->si_drv0)
-typedef void (*cdevpriv_dtr_t)(void *data);
+typedef void d_priv_dtor_t(void *data);
int devfs_get_cdevpriv(void **datap);
-int devfs_set_cdevpriv(void *priv, cdevpriv_dtr_t dtr);
+int devfs_set_cdevpriv(void *priv, d_priv_dtor_t *dtr);
void devfs_clear_cdevpriv(void);
void devfs_fpdrop(struct file *fp); /* XXX This is not public KPI */
diff --git a/sys/sys/elf32.h b/sys/sys/elf32.h
index 62bf7be..03a546c 100644
--- a/sys/sys/elf32.h
+++ b/sys/sys/elf32.h
@@ -70,6 +70,18 @@ typedef struct {
} Elf32_Ehdr;
/*
+ * Shared object information, found in SHT_MIPS_LIBLIST.
+ */
+
+typedef struct {
+ Elf32_Word l_name; /* The name of a shared object. */
+ Elf32_Word l_time_stamp; /* 32-bit timestamp. */
+ Elf32_Word l_checksum; /* Checksum of visible symbols, sizes. */
+ Elf32_Word l_version; /* Interface version string index. */
+ Elf32_Word l_flags; /* Flags (LL_*). */
+} Elf32_Lib;
+
+/*
* Section header.
*/
diff --git a/sys/sys/elf64.h b/sys/sys/elf64.h
index 4ec7d34..f069619 100644
--- a/sys/sys/elf64.h
+++ b/sys/sys/elf64.h
@@ -79,6 +79,18 @@ typedef struct {
} Elf64_Ehdr;
/*
+ * Shared object information, found in SHT_MIPS_LIBLIST.
+ */
+
+typedef struct {
+ Elf64_Word l_name; /* The name of a shared object. */
+ Elf64_Word l_time_stamp; /* 64-bit timestamp. */
+ Elf64_Word l_checksum; /* Checksum of visible symbols, sizes. */
+ Elf64_Word l_version; /* Interface version string index. */
+ Elf64_Word l_flags; /* Flags (LL_*). */
+} Elf64_Lib;
+
+/*
* Section header.
*/
diff --git a/sys/sys/elf_common.h b/sys/sys/elf_common.h
index 1947d11..d6ca101 100644
--- a/sys/sys/elf_common.h
+++ b/sys/sys/elf_common.h
@@ -50,6 +50,61 @@ typedef struct {
} Elf_Note;
/*
+ * Option kinds.
+ */
+#define ODK_NULL 0 /* undefined */
+#define ODK_REGINFO 1 /* register usage info */
+#define ODK_EXCEPTIONS 2 /* exception processing info */
+#define ODK_PAD 3 /* section padding */
+#define ODK_HWPATCH 4 /* hardware patch applied */
+#define ODK_FILL 5 /* fill value used by the linker */
+#define ODK_TAGS 6 /* reserved space for tools */
+#define ODK_HWAND 7 /* hardware AND patch applied */
+#define ODK_HWOR 8 /* hardware OR patch applied */
+#define ODK_GP_GROUP 9 /* GP group for text/data sections */
+#define ODK_IDENT 10 /* ID information */
+#define ODK_PAGESIZE 11 /* page size information */
+
+/*
+ * ODK_EXCEPTIONS info field masks.
+ */
+#define OEX_FPU_MIN 0x0000001f /* min FPU exception required */
+#define OEX_FPU_MAX 0x00001f00 /* max FPU exception allowed */
+#define OEX_PAGE0 0x00010000 /* page zero must be mapped */
+#define OEX_SMM 0x00020000 /* run in sequential memory mode */
+#define OEX_PRECISEFP 0x00040000 /* run in precise FP exception mode */
+#define OEX_DISMISS 0x00080000 /* dismiss invalid address traps */
+
+/*
+ * ODK_PAD info field masks.
+ */
+#define OPAD_PREFIX 0x0001
+#define OPAD_POSTFIX 0x0002
+#define OPAD_SYMBOL 0x0004
+
+/*
+ * ODK_HWPATCH info field masks.
+ */
+#define OHW_R4KEOP 0x00000001 /* patch for R4000 branch at end-of-page bug */
+#define OHW_R8KPFETCH 0x00000002 /* R8000 prefetch bug may occur */
+#define OHW_R5KEOP 0x00000004 /* patch for R5000 branch at end-of-page bug */
+#define OHW_R5KCVTL 0x00000008 /* R5000 cvt.[ds].l bug: clean == 1 */
+#define OHW_R10KLDL 0x00000010UL /* need patch for R10000 misaligned load */
+
+/*
+ * ODK_HWAND/ODK_HWOR info field and hwp_flags[12] masks.
+ */
+#define OHWA0_R4KEOP_CHECKED 0x00000001 /* object checked for R4000 end-of-page bug */
+#define OHWA0_R4KEOP_CLEAN 0x00000002 /* object verified clean for R4000 end-of-page bug */
+#define OHWO0_FIXADE 0x00000001 /* object requires call to fixade */
+
+/*
+ * ODK_IDENT/ODK_GP_GROUP info field masks.
+ */
+#define OGP_GROUP 0x0000ffff /* GP group number */
+#define OGP_SELF 0x00010000 /* GP group is self-contained */
+
+/*
* The header for GNU-style hash sections.
*/
@@ -121,6 +176,7 @@ typedef struct {
#define ELFOSABI_SYSV ELFOSABI_NONE /* symbol used in old spec */
#define ELFOSABI_MONTEREY ELFOSABI_AIX /* Monterey */
+#define ELFOSABI_GNU ELFOSABI_LINUX
/* e_ident */
#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \
@@ -249,6 +305,60 @@ typedef struct {
#define EM_ALPHA_STD 41 /* Digital Alpha (standard value). */
#define EM_ALPHA 0x9026 /* Alpha (written in the absence of an ABI) */
+/**
+ * e_flags
+ */
+#define EF_ARM_RELEXEC 0x1
+#define EF_ARM_HASENTRY 0x2
+#define EF_ARM_SYMSARESORTED 0x4
+#define EF_ARM_DYNSYMSUSESEGIDX 0x8
+#define EF_ARM_MAPSYMSFIRST 0x10
+#define EF_ARM_LE8 0x00400000
+#define EF_ARM_BE8 0x00800000
+#define EF_ARM_EABIMASK 0xFF000000
+#define EF_ARM_EABI_UNKNOWN 0x00000000
+#define EF_ARM_EABI_VER1 0x01000000
+#define EF_ARM_EABI_VER2 0x02000000
+#define EF_ARM_EABI_VER3 0x03000000
+#define EF_ARM_EABI_VER4 0x04000000
+#define EF_ARM_EABI_VER5 0x05000000
+#define EF_ARM_INTERWORK 0x00000004
+#define EF_ARM_APCS_26 0x00000008
+#define EF_ARM_APCS_FLOAT 0x00000010
+#define EF_ARM_PIC 0x00000020
+#define EF_ARM_ALIGN8 0x00000040
+#define EF_ARM_NEW_ABI 0x00000080
+#define EF_ARM_OLD_ABI 0x00000100
+#define EF_ARM_SOFT_FLOAT 0x00000200
+#define EF_ARM_VFP_FLOAT 0x00000400
+#define EF_ARM_MAVERICK_FLOAT 0x00000800
+
+#define EF_MIPS_NOREORDER 0x00000001
+#define EF_MIPS_PIC 0x00000002 /* Contains PIC code */
+#define EF_MIPS_CPIC 0x00000004 /* STD PIC calling sequence */
+#define EF_MIPS_UCODE 0x00000010
+#define EF_MIPS_ABI2 0x00000020 /* N32 */
+#define EF_MIPS_OPTIONS_FIRST 0x00000080
+#define EF_MIPS_ARCH_ASE 0x0F000000 /* Architectural extensions */
+#define EF_MIPS_ARCH_ASE_MDMX 0x08000000 /* MDMX multimedia extension */
+#define EF_MIPS_ARCH_ASE_M16 0x04000000 /* MIPS-16 ISA extensions */
+#define EF_MIPS_ARCH 0xF0000000 /* Architecture field */
+
+#define EF_PPC_EMB 0x80000000
+#define EF_PPC_RELOCATABLE 0x00010000
+#define EF_PPC_RELOCATABLE_LIB 0x00008000
+
+#define EF_SPARC_EXT_MASK 0x00ffff00
+#define EF_SPARC_32PLUS 0x00000100
+#define EF_SPARC_SUN_US1 0x00000200
+#define EF_SPARC_HAL_R1 0x00000200
+#define EF_SPARC_SUN_US3 0x00000800
+
+#define EF_SPARCV9_MM 0x00000003
+#define EF_SPARCV9_TSO 0x00000000
+#define EF_SPARCV9_PSO 0x00000001
+#define EF_SPARCV9_RMO 0x00000002
+
/* Special section indexes. */
#define SHN_UNDEF 0 /* Undefined, missing, irrelevant. */
#define SHN_LORESERVE 0xff00 /* First of reserved range. */
@@ -286,6 +396,7 @@ typedef struct {
#define SHT_LOSUNW 0x6ffffff4
#define SHT_SUNW_dof 0x6ffffff4
#define SHT_SUNW_cap 0x6ffffff5
+#define SHT_GNU_ATTRIBUTES 0x6ffffff5
#define SHT_SUNW_SIGNATURE 0x6ffffff6
#define SHT_GNU_HASH 0x6ffffff6
#define SHT_GNU_LIBLIST 0x6ffffff7
@@ -305,6 +416,7 @@ typedef struct {
#define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */
#define SHT_LOPROC 0x70000000 /* reserved range for processor */
#define SHT_AMD64_UNWIND 0x70000001 /* unwind information */
+
#define SHT_ARM_EXIDX 0x70000001 /* Exception index table. */
#define SHT_ARM_PREEMPTMAP 0x70000002 /* BPABI DLL dynamic linking
pre-emption map. */
@@ -312,9 +424,39 @@ typedef struct {
attributes. */
#define SHT_ARM_DEBUGOVERLAY 0x70000004 /* See DBGOVL for details. */
#define SHT_ARM_OVERLAYSECTION 0x70000005 /* See DBGOVL for details. */
+#define SHT_MIPS_LIBLIST 0x70000000
+#define SHT_MIPS_MSYM 0x70000001
+#define SHT_MIPS_CONFLICT 0x70000002
+#define SHT_MIPS_GPTAB 0x70000003
+#define SHT_MIPS_UCODE 0x70000004
+#define SHT_MIPS_DEBUG 0x70000005
#define SHT_MIPS_REGINFO 0x70000006
+#define SHT_MIPS_PACKAGE 0x70000007
+#define SHT_MIPS_PACKSYM 0x70000008
+#define SHT_MIPS_RELD 0x70000009
+#define SHT_MIPS_IFACE 0x7000000b
+#define SHT_MIPS_CONTENT 0x7000000c
#define SHT_MIPS_OPTIONS 0x7000000d
+#define SHT_MIPS_DELTASYM 0x7000001b
+#define SHT_MIPS_DELTAINST 0x7000001c
+#define SHT_MIPS_DELTACLASS 0x7000001d
#define SHT_MIPS_DWARF 0x7000001e /* MIPS gcc uses MIPS_DWARF */
+#define SHT_MIPS_DELTADECL 0x7000001f
+#define SHT_MIPS_SYMBOL_LIB 0x70000020
+#define SHT_MIPS_EVENTS 0x70000021
+#define SHT_MIPS_TRANSLATE 0x70000022
+#define SHT_MIPS_PIXIE 0x70000023
+#define SHT_MIPS_XLATE 0x70000024
+#define SHT_MIPS_XLATE_DEBUG 0x70000025
+#define SHT_MIPS_WHIRL 0x70000026
+#define SHT_MIPS_EH_REGION 0x70000027
+#define SHT_MIPS_XLATE_OLD 0x70000028
+#define SHT_MIPS_PDR_EXCEPTION 0x70000029
+#define SHT_MIPS_ABIFLAGS 0x7000002a
+
+#define SHT_SPARC_GOTDATA 0x70000000
+
+#define SHTORDERED
#define SHT_HIPROC 0x7fffffff /* specific section header types */
#define SHT_LOUSER 0x80000000 /* reserved range for application */
#define SHT_HIUSER 0xffffffff /* specific indexes */
@@ -440,11 +582,15 @@ typedef struct {
* Dyn.d_un.d_val field of the Elf*_Dyn structure.
*/
#define DT_VALRNGLO 0x6ffffd00
+#define DT_GNU_PRELINKED 0x6ffffdf5 /* prelinking timestamp */
+#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* size of conflict section */
+#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* size of library list */
#define DT_CHECKSUM 0x6ffffdf8 /* elf checksum */
#define DT_PLTPADSZ 0x6ffffdf9 /* pltpadding size */
#define DT_MOVEENT 0x6ffffdfa /* move table entry size */
#define DT_MOVESZ 0x6ffffdfb /* move table size */
#define DT_FEATURE 0x6ffffdfc /* feature holder */
+#define DT_FEATURE_1 DT_FEATURE
#define DT_POSFLAG_1 0x6ffffdfd /* flags for DT_* entries, effecting */
/* the following DT_* entry. */
/* See DF_P1_* definitions */
@@ -461,6 +607,8 @@ typedef struct {
*/
#define DT_ADDRRNGLO 0x6ffffe00
#define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table */
+#define DT_GNU_CONFLICT 0x6ffffef8 /* address of conflict section */
+#define DT_GNU_LIBLIST 0x6ffffef9 /* address of library list */
#define DT_CONFIG 0x6ffffefa /* configuration information */
#define DT_DEPAUDIT 0x6ffffefb /* dependency auditing */
#define DT_AUDIT 0x6ffffefc /* object auditing */
@@ -479,7 +627,67 @@ typedef struct {
#define DT_VERNEEDNUM 0x6fffffff /* Number of elems in verneed section */
#define DT_LOPROC 0x70000000 /* First processor-specific type. */
+
+#define DT_ARM_SYMTABSZ 0x70000001
+#define DT_ARM_PREEMPTMAP 0x70000002
+
+#define DT_SPARC_REGISTER 0x70000001
#define DT_DEPRECATED_SPARC_REGISTER 0x7000001
+
+#define DT_MIPS_RLD_VERSION 0x70000001
+#define DT_MIPS_TIME_STAMP 0x70000002
+#define DT_MIPS_ICHECKSUM 0x70000003
+#define DT_MIPS_IVERSION 0x70000004
+#define DT_MIPS_FLAGS 0x70000005
+#define DT_MIPS_BASE_ADDRESS 0x70000006
+#define DT_MIPS_CONFLICT 0x70000008
+#define DT_MIPS_LIBLIST 0x70000009
+#define DT_MIPS_LOCAL_GOTNO 0x7000000a
+#define DT_MIPS_CONFLICTNO 0x7000000b
+#define DT_MIPS_LIBLISTNO 0x70000010
+#define DT_MIPS_SYMTABNO 0x70000011
+#define DT_MIPS_UNREFEXTNO 0x70000012
+#define DT_MIPS_GOTSYM 0x70000013
+#define DT_MIPS_HIPAGENO 0x70000014
+#define DT_MIPS_RLD_MAP 0x70000016
+#define DT_MIPS_DELTA_CLASS 0x70000017
+#define DT_MIPS_DELTA_CLASS_NO 0x70000018
+#define DT_MIPS_DELTA_INSTANCE 0x70000019
+#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001A
+#define DT_MIPS_DELTA_RELOC 0x7000001B
+#define DT_MIPS_DELTA_RELOC_NO 0x7000001C
+#define DT_MIPS_DELTA_SYM 0x7000001D
+#define DT_MIPS_DELTA_SYM_NO 0x7000001E
+#define DT_MIPS_DELTA_CLASSSYM 0x70000020
+#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021
+#define DT_MIPS_CXX_FLAGS 0x70000022
+#define DT_MIPS_PIXIE_INIT 0x70000023
+#define DT_MIPS_SYMBOL_LIB 0x70000024
+#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025
+#define DT_MIPS_LOCAL_GOTIDX 0x70000026
+#define DT_MIPS_HIDDEN_GOTIDX 0x70000027
+#define DT_MIPS_PROTECTED_GOTIDX 0x70000028
+#define DT_MIPS_OPTIONS 0x70000029
+#define DT_MIPS_INTERFACE 0x7000002A
+#define DT_MIPS_DYNSTR_ALIGN 0x7000002B
+#define DT_MIPS_INTERFACE_SIZE 0x7000002C
+#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002D
+#define DT_MIPS_PERF_SUFFIX 0x7000002E
+#define DT_MIPS_COMPACT_SIZE 0x7000002F
+#define DT_MIPS_GP_VALUE 0x70000030
+#define DT_MIPS_AUX_DYNAMIC 0x70000031
+#define DT_MIPS_PLTGOT 0x70000032
+#define DT_MIPS_RLD_OBJ_UPDATE 0x70000033
+#define DT_MIPS_RWPLT 0x70000034
+
+#define DT_PPC_GOT 0x70000000
+#define DT_PPC_TLSOPT 0x70000001
+
+#define DT_PPC64_GLINK 0x70000000
+#define DT_PPC64_OPD 0x70000001
+#define DT_PPC64_OPDSZ 0x70000002
+#define DT_PPC64_TLSOPT 0x70000003
+
#define DT_AUXILIARY 0x7ffffffd /* shared library auxiliary name */
#define DT_USED 0x7ffffffe /* ignored - same as needed */
#define DT_FILTER 0x7fffffff /* shared library filter name */
@@ -510,6 +718,15 @@ typedef struct {
#define DF_1_INTERPOSE 0x00000400 /* Interpose all objects but main */
#define DF_1_NODEFLIB 0x00000800 /* Do not search default paths */
+/* Values for l_flags. */
+#define LL_NONE 0x0 /* no flags */
+#define LL_EXACT_MATCH 0x1 /* require an exact match */
+#define LL_IGNORE_INT_VER 0x2 /* ignore version incompatibilities */
+#define LL_REQUIRE_MINOR 0x4
+#define LL_EXPORTS 0x8
+#define LL_DELAY_LOAD 0x10
+#define LL_DELTA 0x20
+
/* Values for n_type. Used in core files. */
#define NT_PRSTATUS 1 /* Process status. */
#define NT_FPREGSET 2 /* Floating point registers. */
diff --git a/sys/sys/sysent.h b/sys/sys/sysent.h
index a93d552..8436ba3 100644
--- a/sys/sys/sysent.h
+++ b/sys/sys/sysent.h
@@ -131,6 +131,7 @@ struct sysentvec {
void *sv_shared_page_obj;
void (*sv_schedtail)(struct thread *);
void (*sv_thread_detach)(struct thread *);
+ int (*sv_trap)(struct thread *);
};
#define SV_ILP32 0x000100
diff --git a/sys/vm/vm_kern.c b/sys/vm/vm_kern.c
index 291d0dd..d605c23 100644
--- a/sys/vm/vm_kern.c
+++ b/sys/vm/vm_kern.c
@@ -94,6 +94,9 @@ vm_map_t pipe_map;
const void *zero_region;
CTASSERT((ZERO_REGION_SIZE & PAGE_MASK) == 0);
+/* NB: Used by kernel debuggers. */
+const u_long vm_maxuser_address = VM_MAXUSER_ADDRESS;
+
SYSCTL_ULONG(_vm, OID_AUTO, min_kernel_address, CTLFLAG_RD,
SYSCTL_NULL_ULONG_PTR, VM_MIN_KERNEL_ADDRESS, "Min kernel address");
diff --git a/sys/x86/include/metadata.h b/sys/x86/include/metadata.h
new file mode 100644
index 0000000..e13eba0
--- /dev/null
+++ b/sys/x86/include/metadata.h
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 2003 Peter Wemm <peter@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _MACHINE_METADATA_H_
+#define _MACHINE_METADATA_H_
+
+#define MODINFOMD_SMAP 0x1001
+#define MODINFOMD_SMAP_XATTR 0x1002
+#define MODINFOMD_DTBP 0x1003
+#define MODINFOMD_EFI_MAP 0x1004
+#define MODINFOMD_EFI_FB 0x1005
+#define MODINFOMD_MODULEP 0x1006
+
+struct efi_map_header {
+ uint64_t memory_size;
+ uint64_t descriptor_size;
+ uint32_t descriptor_version;
+};
+
+struct efi_fb {
+ uint64_t fb_addr;
+ uint64_t fb_size;
+ uint32_t fb_height;
+ uint32_t fb_width;
+ uint32_t fb_stride;
+ uint32_t fb_mask_red;
+ uint32_t fb_mask_green;
+ uint32_t fb_mask_blue;
+ uint32_t fb_mask_reserved;
+};
+
+#endif /* !_MACHINE_METADATA_H_ */
diff --git a/sys/x86/x86/busdma_bounce.c b/sys/x86/x86/busdma_bounce.c
index 38c9f1e..bb63397 100644
--- a/sys/x86/x86/busdma_bounce.c
+++ b/sys/x86/x86/busdma_bounce.c
@@ -402,14 +402,14 @@ bounce_bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
/*
* XXX:
- * (dmat->alignment < dmat->maxsize) is just a quick hack; the exact
+ * (dmat->alignment <= dmat->maxsize) is just a quick hack; the exact
* alignment guarantees of malloc need to be nailed down, and the
* code below should be rewritten to take that into account.
*
* In the meantime, we'll warn the user if malloc gets it wrong.
*/
if ((dmat->common.maxsize <= PAGE_SIZE) &&
- (dmat->common.alignment < dmat->common.maxsize) &&
+ (dmat->common.alignment <= dmat->common.maxsize) &&
dmat->common.lowaddr >= ptoa((vm_paddr_t)Maxmem) &&
attr == VM_MEMATTR_DEFAULT) {
*vaddr = malloc(dmat->common.maxsize, M_DEVBUF, mflags);
OpenPOWER on IntegriCloud