[Zrouter-src-freebsd] ZRouter.org: push to FreeBSD HEAD tree
zrouter-src-freebsd at zrouter.org
zrouter-src-freebsd at zrouter.org
Wed Aug 15 08:45:57 UTC 2012
details: http://zrouter.org/hg/FreeBSD/head//rev/49889ad5ef1f
changeset: 525:49889ad5ef1f
user: Aleksandr Rybalko <ray at ddteam.net>
date: Wed Aug 15 11:46:11 2012 +0300
description:
FreeBSD HEAD @svn r239290.
diffstat:
head/Makefile | 6 +-
head/Makefile.inc1 | 4 +-
head/cddl/contrib/opensolaris/cmd/zfs/zfs.8 | 12 +-
head/contrib/binutils/bfd/config.bfd | 8 +
head/contrib/binutils/config.sub | 2 +-
head/contrib/binutils/gas/config/tc-arm.c | 4 +
head/contrib/gcc/config/arm/freebsd.h | 16 +-
head/gnu/usr.bin/binutils/Makefile.inc0 | 6 +-
head/gnu/usr.bin/binutils/as/Makefile | 6 +-
head/gnu/usr.bin/binutils/ld/Makefile.arm | 4 +-
head/gnu/usr.bin/binutils/libbfd/Makefile.arm | 6 +-
head/gnu/usr.bin/cc/Makefile.inc | 7 +-
head/gnu/usr.bin/cc/Makefile.tgt | 6 +-
head/gnu/usr.bin/gdb/Makefile.inc | 4 +-
head/gnu/usr.bin/gdb/libgdb/Makefile | 4 +-
head/lib/libc/arm/gen/__aeabi_read_tp.S | 8 +-
head/lib/libc/arm/gen/_set_tp.c | 6 +-
head/lib/libc/gen/Makefile.inc | 4 +-
head/lib/libc/gen/aux.c | 186 --
head/lib/libc/gen/auxv.c | 186 ++
head/lib/libthr/arch/arm/include/pthread_md.h | 16 +-
head/lib/libthr/thread/thr_cond.c | 18 +-
head/lib/libthr/thread/thr_kern.c | 9 +-
head/lib/libthr/thread/thr_mutex.c | 18 +-
head/lib/libthr/thread/thr_private.h | 10 +-
head/lib/libthr/thread/thr_umtx.h | 18 +-
head/lib/libusb/libusb20.3 | 15 +-
head/lib/libusb/libusb20.c | 11 +-
head/lib/libusb/libusb20.h | 3 +-
head/lib/libusb/libusb20_int.h | 4 +-
head/lib/libusb/libusb20_ugen20.c | 34 +-
head/lib/msun/src/e_rem_pio2.c | 8 +-
head/lib/msun/src/e_rem_pio2f.c | 10 +-
head/lib/msun/src/k_cosf.c | 8 +-
head/lib/msun/src/k_sinf.c | 8 +-
head/lib/msun/src/k_tanf.c | 8 +-
head/lib/msun/src/math_private.h | 27 +-
head/libexec/rtld-elf/arm/reloc.c | 17 +-
head/libexec/rtld-elf/rtld.c | 36 +-
head/share/man/man4/sched_ule.4 | 7 +-
head/share/mk/bsd.cpu.mk | 9 +-
head/share/mk/bsd.endian.mk | 4 +-
head/share/mk/sys.mk | 4 +-
head/sys/amd64/amd64/mp_machdep.c | 18 +-
head/sys/amd64/amd64/trap.c | 24 +-
head/sys/amd64/conf/XENHVM | 4 +-
head/sys/amd64/ia32/ia32_sigtramp.S | 33 +-
head/sys/amd64/ia32/ia32_syscall.c | 4 +-
head/sys/amd64/include/param.h | 10 +-
head/sys/boot/common/disk.c | 35 +-
head/sys/boot/common/disk.h | 7 +-
head/sys/boot/common/loader.8 | 33 +-
head/sys/boot/fdt/dts/beaglebone.dts | 197 ++
head/sys/boot/fdt/dts/db88f78160.dts | 311 ++++
head/sys/boot/fdt/dts/ea3250.dts | 270 +++
head/sys/boot/fdt/dts/pandaboard.dts | 184 ++
head/sys/boot/fdt/dts/trimslice.dts | 143 +
head/sys/boot/i386/libi386/biosdisk.c | 6 +-
head/sys/cam/scsi/scsi_all.h | 3 +-
head/sys/cam/scsi/scsi_enc.c | 22 +-
head/sys/cam/scsi/scsi_enc_safte.c | 12 +-
head/sys/cam/scsi/scsi_enc_ses.c | 60 +-
head/sys/compat/freebsd32/freebsd32_proto.h | 4 +-
head/sys/compat/freebsd32/freebsd32_syscall.h | 6 +-
head/sys/compat/freebsd32/freebsd32_syscalls.c | 6 +-
head/sys/compat/freebsd32/freebsd32_sysent.c | 6 +-
head/sys/compat/freebsd32/syscalls.master | 5 +-
head/sys/conf/Makefile.arm | 6 +-
head/sys/conf/files | 6 +-
head/sys/conf/files.arm | 11 +-
head/sys/conf/kern.pre.mk | 4 +-
head/sys/conf/kmod.mk | 4 +-
head/sys/conf/options.arm | 28 +-
head/sys/conf/options.mips | 6 +-
head/sys/dev/ath/if_ath_tx.c | 62 +-
head/sys/dev/cxgbe/t4_main.c | 9 +-
head/sys/dev/cxgbe/t4_sge.c | 129 +-
head/sys/dev/fdt/fdt_common.c | 94 +-
head/sys/dev/fdt/fdt_common.h | 5 +-
head/sys/dev/fdt/fdtbus.c | 4 +-
head/sys/dev/fdt/simplebus.c | 18 +-
head/sys/dev/isp/isp.c | 4 +-
head/sys/dev/isp/isp_freebsd.c | 31 +-
head/sys/dev/isp/isp_pci.c | 24 +-
head/sys/dev/mge/if_mge.c | 110 +-
head/sys/dev/mge/if_mgevar.h | 4 +-
head/sys/dev/mii/miidevs | 6 +-
head/sys/dev/mii/smcphy.c | 5 +-
head/sys/dev/mii/smscphy.c | 237 +++
head/sys/dev/mmc/mmc.c | 3 +-
head/sys/dev/netmap/ixgbe_netmap.h | 15 +-
head/sys/dev/ofw/ofw_iicbus.c | 9 +-
head/sys/dev/re/if_re.c | 6 +-
head/sys/dev/sound/macio/snapper.c | 4 +-
head/sys/dev/sound/pci/hda/hdaa.c | 11 +-
head/sys/dev/twe/twe.c | 162 +-
head/sys/dev/twe/twe_compat.h | 52 +-
head/sys/dev/twe/twe_freebsd.c | 145 +-
head/sys/dev/twe/twevar.h | 25 +-
head/sys/dev/uart/uart.h | 3 +-
head/sys/dev/uart/uart_bus_fdt.c | 23 +-
head/sys/dev/uart/uart_dev_lpc.c | 891 ++++++++++++
head/sys/dev/uart/uart_subr.c | 3 +-
head/sys/dev/usb/controller/at91dci.c | 15 +-
head/sys/dev/usb/controller/atmegadci.c | 15 +-
head/sys/dev/usb/controller/avr32dci.c | 15 +-
head/sys/dev/usb/controller/dotg.c | 49 +-
head/sys/dev/usb/controller/dotgreg.h | 11 +
head/sys/dev/usb/controller/dwc_otg.c | 15 +-
head/sys/dev/usb/controller/musb_otg.c | 15 +-
head/sys/dev/usb/controller/uss820dci.c | 15 +-
head/sys/dev/usb/controller/xhci.c | 125 +-
head/sys/dev/usb/controller/xhci.h | 21 +-
head/sys/dev/usb/net/if_smsc.c | 1756 ++++++++++++++++++++++++
head/sys/dev/usb/net/if_smscreg.h | 277 +++
head/sys/dev/usb/net/if_usie.c | 30 +-
head/sys/dev/usb/net/uhso.c | 30 +-
head/sys/dev/usb/quirk/usb_quirk.c | 1 +
head/sys/dev/usb/serial/u3g.c | 37 +-
head/sys/dev/usb/serial/uark.c | 30 +-
head/sys/dev/usb/serial/ubsa.c | 30 +-
head/sys/dev/usb/serial/ubser.c | 34 +-
head/sys/dev/usb/serial/uchcom.c | 31 +-
head/sys/dev/usb/serial/ucycom.c | 34 +-
head/sys/dev/usb/serial/ufoma.c | 34 +-
head/sys/dev/usb/serial/uftdi.c | 34 +-
head/sys/dev/usb/serial/ugensa.c | 30 +-
head/sys/dev/usb/serial/uipaq.c | 30 +-
head/sys/dev/usb/serial/ulpt.c | 4 +-
head/sys/dev/usb/serial/umcs.c | 30 +-
head/sys/dev/usb/serial/umct.c | 34 +-
head/sys/dev/usb/serial/umodem.c | 30 +-
head/sys/dev/usb/serial/umoscom.c | 30 +-
head/sys/dev/usb/serial/uplcom.c | 30 +-
head/sys/dev/usb/serial/usb_serial.c | 238 ++-
head/sys/dev/usb/serial/usb_serial.h | 17 +-
head/sys/dev/usb/serial/uslcom.c | 141 +-
head/sys/dev/usb/serial/uvisor.c | 30 +-
head/sys/dev/usb/serial/uvscom.c | 30 +-
head/sys/dev/usb/usb.h | 22 +-
head/sys/dev/usb/usb_controller.h | 9 +-
head/sys/dev/usb/usb_core.h | 3 +-
head/sys/dev/usb/usb_debug.c | 8 +-
head/sys/dev/usb/usb_device.c | 112 +-
head/sys/dev/usb/usb_device.h | 4 +-
head/sys/dev/usb/usb_freebsd.h | 4 +-
head/sys/dev/usb/usb_generic.c | 8 +-
head/sys/dev/usb/usb_hub.c | 10 +-
head/sys/dev/usb/usb_ioctl.h | 8 +-
head/sys/dev/usb/usb_msctest.c | 44 +-
head/sys/dev/usb/usb_request.c | 11 +-
head/sys/dev/usb/usb_transfer.c | 47 +-
head/sys/dev/usb/usbdevs | 3 +-
head/sys/dev/usb/usbdi.h | 14 +-
head/sys/fs/nfsclient/nfs_clbio.c | 14 +-
head/sys/fs/nwfs/nwfs_io.c | 4 +-
head/sys/fs/smbfs/smbfs_io.c | 4 +-
head/sys/geom/eli/g_eli_key_cache.c | 29 +-
head/sys/geom/raid/g_raid.c | 4 +-
head/sys/i386/conf/XENHVM | 4 +-
head/sys/i386/i386/mp_machdep.c | 18 +-
head/sys/i386/include/param.h | 10 +-
head/sys/kern/device_if.m | 13 +-
head/sys/kern/kern_environment.c | 14 +-
head/sys/kern/kern_umtx.c | 28 +-
head/sys/kern/ksched.c | 4 +-
head/sys/kern/sched_4bsd.c | 47 +-
head/sys/kern/sched_ule.c | 100 +-
head/sys/kern/subr_bus.c | 20 +-
head/sys/mips/atheros/ar71xx_gpio.c | 130 +-
head/sys/mips/atheros/ar71xx_gpiovar.h | 6 +-
head/sys/mips/atheros/ar71xxreg.h | 12 +-
head/sys/mips/cavium/octopci.c | 24 +
head/sys/mips/cavium/octopci_bus_space.c | 13 +-
head/sys/mips/include/pmap.h | 28 +-
head/sys/mips/mips/pmap.c | 641 +++++---
head/sys/mips/rt305x/rt305x_gpio.c | 3 +-
head/sys/modules/Makefile | 4 +-
head/sys/modules/cpsw/Makefile | 8 +
head/sys/modules/cxgbe/if_cxgbe/Makefile | 17 +-
head/sys/modules/cxgbe/tom/Makefile | 12 +-
head/sys/modules/mii/Makefile | 5 +-
head/sys/modules/usb/smsc/Makefile | 37 +
head/sys/nfsclient/nfs_bio.c | 14 +-
head/sys/sys/bus.h | 3 +-
head/sys/sys/param.h | 4 +-
head/sys/vm/vm_mmap.c | 31 +-
head/sys/vm/vm_page.c | 12 +-
head/sys/vm/vm_page.h | 4 +-
head/sys/vm/vnode_pager.c | 4 +-
head/usr.bin/xlint/Makefile.inc | 4 +-
head/usr.sbin/lpr/lpd/lpd.8 | 4 +-
192 files changed, 7703 insertions(+), 1614 deletions(-)
diffs (16370 lines):
diff -r a301a330526b -r 49889ad5ef1f head/Makefile
--- a/head/Makefile Wed Aug 15 11:16:36 2012 +0300
+++ b/head/Makefile Wed Aug 15 11:46:11 2012 +0300
@@ -1,5 +1,5 @@
#
-# $FreeBSD: head/Makefile 238051 2012-07-03 06:41:00Z obrien $
+# $FreeBSD: head/Makefile 239272 2012-08-15 03:21:56Z gonzo $
#
# The user-driven targets are:
#
@@ -135,7 +135,7 @@
_TARGET_ARCH= ${TARGET:S/pc98/i386/}
.elif !defined(TARGET) && defined(TARGET_ARCH) && \
${TARGET_ARCH} != ${MACHINE_ARCH}
-_TARGET= ${TARGET_ARCH:C/mips(n32|64)?(el)?/mips/:C/armeb/arm/}
+_TARGET= ${TARGET_ARCH:C/mips(n32|64)?(el)?/mips/:C/arm(v6)?(eb)?/arm/}
.endif
# Legacy names, for another transition period mips:mips(n32|64)?eb -> mips:mips\1
.if defined(TARGET) && defined(TARGET_ARCH) && \
@@ -329,7 +329,7 @@
#
.if make(universe) || make(universe_kernels) || make(tinderbox) || make(targets)
TARGETS?=amd64 arm i386 ia64 mips pc98 powerpc sparc64
-TARGET_ARCHES_arm?= arm armeb
+TARGET_ARCHES_arm?= arm armeb armv6 armv6eb
TARGET_ARCHES_mips?= mipsel mips mips64el mips64 mipsn32
TARGET_ARCHES_powerpc?= powerpc powerpc64
TARGET_ARCHES_pc98?= i386
diff -r a301a330526b -r 49889ad5ef1f head/Makefile.inc1
--- a/head/Makefile.inc1 Wed Aug 15 11:16:36 2012 +0300
+++ b/head/Makefile.inc1 Wed Aug 15 11:46:11 2012 +0300
@@ -1,5 +1,5 @@
#
-# $FreeBSD: head/Makefile.inc1 238926 2012-07-30 23:14:24Z mm $
+# $FreeBSD: head/Makefile.inc1 239272 2012-08-15 03:21:56Z gonzo $
#
# Make command line options:
# -DNO_CLEANDIR run ${MAKE} clean, instead of ${MAKE} cleandir
@@ -138,7 +138,7 @@
VERSION+= ${OSRELDATE}
.endif
-KNOWN_ARCHES?= amd64 arm armeb/arm i386 i386/pc98 ia64 mips mipsel/mips mips64el/mips mips64/mips mipsn32el/mips mipsn32/mips powerpc powerpc64/powerpc sparc64
+KNOWN_ARCHES?= amd64 arm armeb/arm armv6/arm armv6eb/arm i386 i386/pc98 ia64 mips mipsel/mips mips64el/mips mips64/mips mipsn32el/mips mipsn32/mips powerpc powerpc64/powerpc sparc64
.if ${TARGET} == ${TARGET_ARCH}
_t= ${TARGET}
.else
diff -r a301a330526b -r 49889ad5ef1f head/cddl/contrib/opensolaris/cmd/zfs/zfs.8
--- a/head/cddl/contrib/opensolaris/cmd/zfs/zfs.8 Wed Aug 15 11:16:36 2012 +0300
+++ b/head/cddl/contrib/opensolaris/cmd/zfs/zfs.8 Wed Aug 15 11:46:11 2012 +0300
@@ -23,9 +23,9 @@
.\" Copyright (c) 2012, Joyent, Inc. All rights reserved.
.\" Copyright (c) 2011, Pawel Jakub Dawidek <pjd at FreeBSD.org>
.\"
-.\" $FreeBSD: head/cddl/contrib/opensolaris/cmd/zfs/zfs.8 235222 2012-05-10 10:39:45Z mm $
+.\" $FreeBSD: head/cddl/contrib/opensolaris/cmd/zfs/zfs.8 239217 2012-08-12 20:30:15Z gjb $
.\"
-.Dd April 22, 2012
+.Dd August 12, 2012
.Dt ZFS 8
.Os
.Sh NAME
@@ -2249,7 +2249,7 @@
is received. If the
.Fl F
flag is specified when this stream is received, snapshots and file systems that
- do not exist on the sending side are destroyed.
+do not exist on the sending side are destroyed.
.It Fl D
Generate a deduplicated stream. Blocks which would have been sent multiple
times in the send stream will only be sent once. The receiving system must
@@ -3028,9 +3028,9 @@
.Li # Ic zfs destroy -r pool/users at 7daysago
.Li # Ic zfs rename -r pool/users at 6daysago @7daysago
.Li # Ic zfs rename -r pool/users at 5daysago @6daysago
-.Li # Ic zfs rename -r pool/users at yesterday @5daysago
-.Li # Ic zfs rename -r pool/users at yesterday @4daysago
-.Li # Ic zfs rename -r pool/users at yesterday @3daysago
+.Li # Ic zfs rename -r pool/users at 4daysago @5daysago
+.Li # Ic zfs rename -r pool/users at 3daysago @4daysago
+.Li # Ic zfs rename -r pool/users at 2daysago @3daysago
.Li # Ic zfs rename -r pool/users at yesterday @2daysago
.Li # Ic zfs rename -r pool/users at today @yesterday
.Li # Ic zfs snapshot -r pool/users at today
diff -r a301a330526b -r 49889ad5ef1f head/contrib/binutils/bfd/config.bfd
--- a/head/contrib/binutils/bfd/config.bfd Wed Aug 15 11:16:36 2012 +0300
+++ b/head/contrib/binutils/bfd/config.bfd Wed Aug 15 11:46:11 2012 +0300
@@ -277,6 +277,14 @@
targ_defvec=bfd_elf32_bigarm_vec
targ_selvecs=bfd_elf32_littlearm_vec
;;
+ armv6eb-*-freebsd*)
+ targ_defvec=bfd_elf32_bigarm_vec
+ targ_selvecs=bfd_elf32_littlearm_vec
+ ;;
+ armv6-*-freebsd*)
+ targ_defvec=bfd_elf32_littlearm_vec
+ targ_selvecs=bfd_elf32_bigarm_vec
+ ;;
arm-*-elf | arm-*-freebsd* | arm*-*-linux-* | arm*-*-conix* | \
arm*-*-uclinux* | arm-*-kfreebsd*-gnu | \
arm*-*-eabi* )
diff -r a301a330526b -r 49889ad5ef1f head/contrib/binutils/config.sub
--- a/head/contrib/binutils/config.sub Wed Aug 15 11:16:36 2012 +0300
+++ b/head/contrib/binutils/config.sub Wed Aug 15 11:46:11 2012 +0300
@@ -241,7 +241,7 @@
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
| am33_2.0 \
- | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+ | arc | arm | arm[bl]e | arme[lb] | armv[23456] | armv[345][lb] | avr | avr32 \
| bfin \
| c4x | clipper \
| d10v | d30v | dlx | dsp16xx \
diff -r a301a330526b -r 49889ad5ef1f head/contrib/binutils/gas/config/tc-arm.c
--- a/head/contrib/binutils/gas/config/tc-arm.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/contrib/binutils/gas/config/tc-arm.c Wed Aug 15 11:46:11 2012 +0300
@@ -20008,6 +20008,9 @@
{"cortex-a8", ARM_ARCH_V7A, ARM_FEATURE(0, FPU_VFP_V3
| FPU_NEON_EXT_V1),
NULL},
+ {"cortex-a9", ARM_ARCH_V7A, ARM_FEATURE(0, FPU_VFP_V3
+ | FPU_NEON_EXT_V1),
+ NULL},
{"cortex-r4", ARM_ARCH_V7R, FPU_NONE, NULL},
{"cortex-m3", ARM_ARCH_V7M, FPU_NONE, NULL},
/* ??? XSCALE is really an architecture. */
@@ -20106,6 +20109,7 @@
{"vfp", FPU_ARCH_VFP_V2},
{"vfp9", FPU_ARCH_VFP_V2},
{"vfp3", FPU_ARCH_VFP_V3},
+ {"vfpv3", FPU_ARCH_VFP_V3},
{"vfp10", FPU_ARCH_VFP_V2},
{"vfp10-r0", FPU_ARCH_VFP_V1},
{"vfpxd", FPU_ARCH_VFP_V1xD},
diff -r a301a330526b -r 49889ad5ef1f head/contrib/gcc/config/arm/freebsd.h
--- a/head/contrib/gcc/config/arm/freebsd.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/contrib/gcc/config/arm/freebsd.h Wed Aug 15 11:46:11 2012 +0300
@@ -56,8 +56,6 @@
/************************[ Target stuff ]***********************************/
-#undef TARGET_VERSION
-#define TARGET_VERSION fprintf (stderr, " (FreeBSD/StrongARM ELF)");
#ifndef TARGET_ENDIAN_DEFAULT
#define TARGET_ENDIAN_DEFAULT 0
@@ -87,8 +85,22 @@
/* We use the GCC defaults here. */
#undef WCHAR_TYPE
+#if defined(FREEBSD_ARCH_armv6)
+#undef SUBTARGET_CPU_DEFAULT
+#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm1176jzs
+#undef FBSD_TARGET_CPU_CPP_BUILTINS
+#define FBSD_TARGET_CPU_CPP_BUILTINS() \
+ do { \
+ builtin_define ("__FreeBSD_ARCH_armv6__"); \
+ } while (0)
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (FreeBSD/armv6 ELF)");
+#else
#undef SUBTARGET_CPU_DEFAULT
#define SUBTARGET_CPU_DEFAULT TARGET_CPU_strongarm
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (FreeBSD/StrongARM ELF)");
+#endif
/* FreeBSD does its profiling differently to the Acorn compiler. We
don't need a word following the mcount call; and to skip it
diff -r a301a330526b -r 49889ad5ef1f head/gnu/usr.bin/binutils/Makefile.inc0
--- a/head/gnu/usr.bin/binutils/Makefile.inc0 Wed Aug 15 11:16:36 2012 +0300
+++ b/head/gnu/usr.bin/binutils/Makefile.inc0 Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD: head/gnu/usr.bin/binutils/Makefile.inc0 233644 2012-03-29 02:54:35Z jmallett $
+# $FreeBSD: head/gnu/usr.bin/binutils/Makefile.inc0 239272 2012-08-15 03:21:56Z gonzo $
#
# This is included explicitly at the top of each sub-Makefile. We can't
# use the normal "Makefile.inc" mechanism, because we need some of these
@@ -7,7 +7,7 @@
VERSION= "2.17.50 [FreeBSD] 2007-07-03"
.if defined(TARGET_ARCH)
-TARGET_CPUARCH=${TARGET_ARCH:C/mips(n32|64)?(el)?/mips/:C/armeb/arm/:C/powerpc64/powerpc/}
+TARGET_CPUARCH=${TARGET_ARCH:C/mips(n32|64)?(el)?/mips/:C/arm(v6)?(eb)?/arm/:C/powerpc64/powerpc/}
.else
TARGET_CPUARCH=${MACHINE_CPUARCH}
.endif
@@ -16,7 +16,7 @@
TARGET_OS?= freebsd
BINUTILS_ARCH=${TARGET_ARCH:C/amd64/x86_64/}
TARGET_TUPLE?= ${BINUTILS_ARCH}-${TARGET_VENDOR}-${TARGET_OS}
-.if ${TARGET_ARCH} == "armeb" || \
+.if ${TARGET_ARCH} == "armeb" || ${TARGET_ARCH} == "armv6eb" || \
(${TARGET_CPUARCH} == "mips" && ${TARGET_ARCH:Mmips*el} == "")
TARGET_BIG_ENDIAN=t
.endif
diff -r a301a330526b -r 49889ad5ef1f head/gnu/usr.bin/binutils/as/Makefile
--- a/head/gnu/usr.bin/binutils/as/Makefile Wed Aug 15 11:16:36 2012 +0300
+++ b/head/gnu/usr.bin/binutils/as/Makefile Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD: head/gnu/usr.bin/binutils/as/Makefile 234782 2012-04-29 09:32:44Z kib $
+# $FreeBSD: head/gnu/usr.bin/binutils/as/Makefile 239272 2012-08-15 03:21:56Z gonzo $
# BINDIR
@@ -42,6 +42,10 @@
# DEO: why not used?
#SRCS+= itbl-ops.c
+.if ${TARGET_ARCH} == "armv6" || ${TARGET_ARCH} == "armv6eb"
+CFLAGS+= -DCPU_DEFAULT=ARM_ARCH_V6K
+.endif
+
.if ${TARGET_CPUARCH} == "mips"
SRCS+= itbl-ops.c itbl-parse.y itbl-lex.l
.if ${TARGET_ARCH:Mmips64*} != ""
diff -r a301a330526b -r 49889ad5ef1f head/gnu/usr.bin/binutils/ld/Makefile.arm
--- a/head/gnu/usr.bin/binutils/ld/Makefile.arm Wed Aug 15 11:16:36 2012 +0300
+++ b/head/gnu/usr.bin/binutils/ld/Makefile.arm Wed Aug 15 11:46:11 2012 +0300
@@ -1,6 +1,6 @@
-# $FreeBSD$
+# $FreeBSD: head/gnu/usr.bin/binutils/ld/Makefile.arm 239272 2012-08-15 03:21:56Z gonzo $
-.if ${TARGET_ARCH} == "armeb"
+.if ${TARGET_ARCH} == "armeb" || ${TARGET_ARCH} == "armv6eb"
NATIVE_EMULATION= armelfb_fbsd
.else
NATIVE_EMULATION= armelf_fbsd
diff -r a301a330526b -r 49889ad5ef1f head/gnu/usr.bin/binutils/libbfd/Makefile.arm
--- a/head/gnu/usr.bin/binutils/libbfd/Makefile.arm Wed Aug 15 11:16:36 2012 +0300
+++ b/head/gnu/usr.bin/binutils/libbfd/Makefile.arm Wed Aug 15 11:46:11 2012 +0300
@@ -1,6 +1,6 @@
-# $FreeBSD$
+# $FreeBSD: head/gnu/usr.bin/binutils/libbfd/Makefile.arm 239272 2012-08-15 03:21:56Z gonzo $
-.if ${TARGET_ARCH} == "armeb"
+.if ${TARGET_ARCH} == "armeb" || ${TARGET_ARCH} == "armv6eb"
DEFAULT_VECTOR= bfd_elf32_bigarm_vec
.else
DEFAULT_VECTOR= bfd_elf32_littlearm_vec
@@ -14,7 +14,7 @@
elflink.c
VECS+= ${DEFAULT_VECTOR}
-.if ${TARGET_ARCH} == "armeb"
+.if ${TARGET_ARCH} == "armeb" || ${TARGET_ARCH} == "armv6eb"
VECS+= bfd_elf32_littlearm_vec
.else
VECS+= bfd_elf32_bigarm_vec
diff -r a301a330526b -r 49889ad5ef1f head/gnu/usr.bin/cc/Makefile.inc
--- a/head/gnu/usr.bin/cc/Makefile.inc Wed Aug 15 11:16:36 2012 +0300
+++ b/head/gnu/usr.bin/cc/Makefile.inc Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/gnu/usr.bin/cc/Makefile.inc 239272 2012-08-15 03:21:56Z gonzo $
.include "../Makefile.inc"
@@ -26,9 +26,12 @@
CFLAGS+= -DCROSS_COMPILE
.endif
-.if ${TARGET_ARCH} == "armeb"
+.if ${TARGET_ARCH} == "armeb" || ${TARGET_ARCH} == "armv6eb"
CFLAGS += -DTARGET_ENDIAN_DEFAULT=MASK_BIG_END
.endif
+.if ${TARGET_ARCH} == "armv6" || ${TARGET_ARCH} == "armv6eb"
+CFLAGS += -DFREEBSD_ARCH_armv6
+.endif
.if ${TARGET_CPUARCH} == "mips"
.if ${TARGET_ARCH:Mmips*el} != ""
diff -r a301a330526b -r 49889ad5ef1f head/gnu/usr.bin/cc/Makefile.tgt
--- a/head/gnu/usr.bin/cc/Makefile.tgt Wed Aug 15 11:16:36 2012 +0300
+++ b/head/gnu/usr.bin/cc/Makefile.tgt Wed Aug 15 11:46:11 2012 +0300
@@ -1,10 +1,10 @@
-# $FreeBSD: head/gnu/usr.bin/cc/Makefile.tgt 233644 2012-03-29 02:54:35Z jmallett $
+# $FreeBSD: head/gnu/usr.bin/cc/Makefile.tgt 239272 2012-08-15 03:21:56Z gonzo $
# These assignments duplicate much of the functionality of
# MACHINE_CPUARCH, but there's no easy way to export make functions...
.if defined(TARGET_ARCH)
-TARGET_CPUARCH=${TARGET_ARCH:C/mips(n32|64)?(el)?/mips/:C/armeb/arm/:C/powerpc64/powerpc/}
+TARGET_CPUARCH=${TARGET_ARCH:C/mips(n32|64)?(el)?/mips/:C/arm(v6)?(eb)?/arm/:C/powerpc64/powerpc/}
.else
TARGET_CPUARCH=${MACHINE_CPUARCH}
.endif
@@ -17,7 +17,7 @@
.if ${TARGET_ARCH} == "sparc64"
TARGET_CPU_DEFAULT= TARGET_CPU_ultrasparc
.endif
-.if ${TARGET_ARCH} == "armeb" || \
+.if ${TARGET_ARCH} == "armeb" || ${TARGET_ARCH} == "armv6eb" || \
(${TARGET_CPUARCH} == "mips" && ${TARGET_ARCH:Mmips*el} == "")
TARGET_BIG_ENDIAN=t
.endif
diff -r a301a330526b -r 49889ad5ef1f head/gnu/usr.bin/gdb/Makefile.inc
--- a/head/gnu/usr.bin/gdb/Makefile.inc Wed Aug 15 11:16:36 2012 +0300
+++ b/head/gnu/usr.bin/gdb/Makefile.inc Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD: head/gnu/usr.bin/gdb/Makefile.inc 233644 2012-03-29 02:54:35Z jmallett $
+# $FreeBSD: head/gnu/usr.bin/gdb/Makefile.inc 239272 2012-08-15 03:21:56Z gonzo $
VERSION= "6.1.1 [FreeBSD]"
VENDOR= marcel
@@ -20,7 +20,7 @@
# MACHINE_CPUARCH, but there's no easy way to export make functions...
.if defined(TARGET_ARCH)
-TARGET_CPUARCH=${TARGET_ARCH:C/mips(n32|64)?(el)?/mips/:C/armeb/arm/:C/powerpc64/powerpc/}
+TARGET_CPUARCH=${TARGET_ARCH:C/mips(n32|64)?(el)?/mips/:C/arm(v6)?(eb)?/arm/:C/powerpc64/powerpc/}
.else
TARGET_CPUARCH=${MACHINE_CPUARCH}
.endif
diff -r a301a330526b -r 49889ad5ef1f head/gnu/usr.bin/gdb/libgdb/Makefile
--- a/head/gnu/usr.bin/gdb/libgdb/Makefile Wed Aug 15 11:16:36 2012 +0300
+++ b/head/gnu/usr.bin/gdb/libgdb/Makefile Wed Aug 15 11:46:11 2012 +0300
@@ -1,10 +1,10 @@
-# $FreeBSD: head/gnu/usr.bin/gdb/libgdb/Makefile 233644 2012-03-29 02:54:35Z jmallett $
+# $FreeBSD: head/gnu/usr.bin/gdb/libgdb/Makefile 239272 2012-08-15 03:21:56Z gonzo $
# These assignments duplicate much of the functionality of
# MACHINE_CPUARCH, but there's no easy way to export make functions...
.if defined(TARGET_ARCH)
-TARGET_CPUARCH=${TARGET_ARCH:C/mips(n32|64)?(el)?/mips/:C/armeb/arm/:C/powerpc64/powerpc/}
+TARGET_CPUARCH=${TARGET_ARCH:C/mips(n32|64)?(el)?/mips/:C/arm(v6)?(eb)?/arm/:C/powerpc64/powerpc/}
.else
TARGET_CPUARCH=${MACHINE_CPUARCH}
.endif
diff -r a301a330526b -r 49889ad5ef1f head/lib/libc/arm/gen/__aeabi_read_tp.S
--- a/head/lib/libc/arm/gen/__aeabi_read_tp.S Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/libc/arm/gen/__aeabi_read_tp.S Wed Aug 15 11:46:11 2012 +0300
@@ -26,15 +26,21 @@
*/
#include <machine/asm.h>
-__FBSDID("$FreeBSD: head/lib/libc/arm/gen/__aeabi_read_tp.S 234337 2012-04-16 09:38:20Z andrew $");
+__FBSDID("$FreeBSD: head/lib/libc/arm/gen/__aeabi_read_tp.S 239271 2012-08-15 03:09:00Z gonzo $");
#include <machine/sysarch.h>
ENTRY(__aeabi_read_tp)
+#ifdef ARM_TP_ADDRESS
ldr r0, .Larm_tp_address
ldr r0, [r0]
+#else
+ mrc p15, 0, r0, c13, c0, 3
+#endif
RET
+#ifdef ARM_TP_ADDRESS
.Larm_tp_address:
.word ARM_TP_ADDRESS
+#endif
diff -r a301a330526b -r 49889ad5ef1f head/lib/libc/arm/gen/_set_tp.c
--- a/head/lib/libc/arm/gen/_set_tp.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/libc/arm/gen/_set_tp.c Wed Aug 15 11:46:11 2012 +0300
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/lib/libc/arm/gen/_set_tp.c 233107 2012-03-18 08:08:06Z gonzo $
+ * $FreeBSD: head/lib/libc/arm/gen/_set_tp.c 239271 2012-08-15 03:09:00Z gonzo $
*/
#include <string.h>
@@ -35,5 +35,9 @@
_set_tp(void *tp)
{
+#ifdef ARM_TP_ADDRESS
*((struct tcb **)ARM_TP_ADDRESS) = tp;
+#else
+ sysarch(ARM_SET_TP, tp);
+#endif
}
diff -r a301a330526b -r 49889ad5ef1f head/lib/libc/gen/Makefile.inc
--- a/head/lib/libc/gen/Makefile.inc Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/libc/gen/Makefile.inc Wed Aug 15 11:46:11 2012 +0300
@@ -1,5 +1,5 @@
# @(#)Makefile.inc 8.6 (Berkeley) 5/4/95
-# $FreeBSD: head/lib/libc/gen/Makefile.inc 235647 2012-05-19 12:44:27Z gleb $
+# $FreeBSD: head/lib/libc/gen/Makefile.inc 239193 2012-08-11 12:07:24Z ed $
# machine-independent gen sources
.PATH: ${.CURDIR}/${LIBC_ARCH}/gen ${.CURDIR}/gen
@@ -7,7 +7,7 @@
SRCS+= __getosreldate.c __xuname.c \
_once_stub.c _pthread_stubs.c _rand48.c _spinlock_stub.c \
_thread_init.c \
- alarm.c arc4random.c assert.c aux.c basename.c check_utility_compat.c \
+ alarm.c arc4random.c assert.c auxv.c basename.c check_utility_compat.c \
clock.c closedir.c confstr.c \
crypt.c ctermid.c daemon.c devname.c dirfd.c dirname.c disklabel.c \
dlfcn.c drand48.c elf_utils.c erand48.c err.c errlst.c errno.c \
diff -r a301a330526b -r 49889ad5ef1f head/lib/libc/gen/aux.c
--- a/head/lib/libc/gen/aux.c Wed Aug 15 11:16:36 2012 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,186 +0,0 @@
-/*-
- * Copyright 2010, 2012 Konstantin Belousov <kib at 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 ``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.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/libc/gen/aux.c 237434 2012-06-22 07:13:30Z kib $");
-
-#include "namespace.h"
-#include <elf.h>
-#include <errno.h>
-#include <link.h>
-#include <pthread.h>
-#include <string.h>
-#include "un-namespace.h"
-#include "libc_private.h"
-
-extern char **environ;
-extern int _DYNAMIC;
-#pragma weak _DYNAMIC
-
-void *__elf_aux_vector;
-static pthread_once_t aux_vector_once = PTHREAD_ONCE_INIT;
-
-static void
-init_aux_vector_once(void)
-{
- Elf_Addr *sp;
-
- sp = (Elf_Addr *)environ;
- while (*sp++ != 0)
- ;
- __elf_aux_vector = (Elf_Auxinfo *)sp;
-}
-
-void
-__init_elf_aux_vector(void)
-{
-
- if (&_DYNAMIC != NULL)
- return;
- _once(&aux_vector_once, init_aux_vector_once);
-}
-
-static pthread_once_t aux_once = PTHREAD_ONCE_INIT;
-static int pagesize, osreldate, canary_len, ncpus, pagesizes_len;
-static char *canary, *pagesizes;
-static void *timekeep;
-
-static void
-init_aux(void)
-{
- Elf_Auxinfo *aux;
-
- for (aux = __elf_aux_vector; aux->a_type != AT_NULL; aux++) {
- switch (aux->a_type) {
- case AT_CANARY:
- canary = (char *)(aux->a_un.a_ptr);
- break;
-
- case AT_CANARYLEN:
- canary_len = aux->a_un.a_val;
- break;
-
- case AT_PAGESIZES:
- pagesizes = (char *)(aux->a_un.a_ptr);
- break;
-
- case AT_PAGESIZESLEN:
- pagesizes_len = aux->a_un.a_val;
- break;
-
- case AT_PAGESZ:
- pagesize = aux->a_un.a_val;
- break;
-
- case AT_OSRELDATE:
- osreldate = aux->a_un.a_val;
- break;
-
- case AT_NCPUS:
- ncpus = aux->a_un.a_val;
- break;
-
- case AT_TIMEKEEP:
- timekeep = aux->a_un.a_ptr;
- break;
- }
- }
-}
-
-int
-_elf_aux_info(int aux, void *buf, int buflen)
-{
- int res;
-
- __init_elf_aux_vector();
- if (__elf_aux_vector == NULL)
- return (ENOSYS);
- _once(&aux_once, init_aux);
-
- switch (aux) {
- case AT_CANARY:
- if (canary != NULL && canary_len >= buflen) {
- memcpy(buf, canary, buflen);
- memset(canary, 0, canary_len);
- canary = NULL;
- res = 0;
- } else
- res = ENOENT;
- break;
- case AT_PAGESIZES:
- if (pagesizes != NULL && pagesizes_len >= buflen) {
- memcpy(buf, pagesizes, buflen);
- res = 0;
- } else
- res = ENOENT;
- break;
-
- case AT_PAGESZ:
- if (buflen == sizeof(int)) {
- if (pagesize != 0) {
- *(int *)buf = pagesize;
- res = 0;
- } else
- res = ENOENT;
- } else
- res = EINVAL;
- break;
- case AT_OSRELDATE:
- if (buflen == sizeof(int)) {
- if (osreldate != 0) {
- *(int *)buf = osreldate;
- res = 0;
- } else
- res = ENOENT;
- } else
- res = EINVAL;
- break;
- case AT_NCPUS:
- if (buflen == sizeof(int)) {
- if (ncpus != 0) {
- *(int *)buf = ncpus;
- res = 0;
- } else
- res = ENOENT;
- } else
- res = EINVAL;
- break;
- case AT_TIMEKEEP:
- if (buflen == sizeof(void *)) {
- if (timekeep != NULL) {
- *(void **)buf = timekeep;
- res = 0;
- } else
- res = ENOENT;
- } else
- res = EINVAL;
- break;
- default:
- res = ENOENT;
- break;
- }
- return (res);
-}
diff -r a301a330526b -r 49889ad5ef1f head/lib/libc/gen/auxv.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/lib/libc/gen/auxv.c Wed Aug 15 11:46:11 2012 +0300
@@ -0,0 +1,186 @@
+/*-
+ * Copyright 2010, 2012 Konstantin Belousov <kib at 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 ``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.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/lib/libc/gen/auxv.c 239193 2012-08-11 12:07:24Z ed $");
+
+#include "namespace.h"
+#include <elf.h>
+#include <errno.h>
+#include <link.h>
+#include <pthread.h>
+#include <string.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+
+extern char **environ;
+extern int _DYNAMIC;
+#pragma weak _DYNAMIC
+
+void *__elf_aux_vector;
+static pthread_once_t aux_vector_once = PTHREAD_ONCE_INIT;
+
+static void
+init_aux_vector_once(void)
+{
+ Elf_Addr *sp;
+
+ sp = (Elf_Addr *)environ;
+ while (*sp++ != 0)
+ ;
+ __elf_aux_vector = (Elf_Auxinfo *)sp;
+}
+
+void
+__init_elf_aux_vector(void)
+{
+
+ if (&_DYNAMIC != NULL)
+ return;
+ _once(&aux_vector_once, init_aux_vector_once);
+}
+
+static pthread_once_t aux_once = PTHREAD_ONCE_INIT;
+static int pagesize, osreldate, canary_len, ncpus, pagesizes_len;
+static char *canary, *pagesizes;
+static void *timekeep;
+
+static void
+init_aux(void)
+{
+ Elf_Auxinfo *aux;
+
+ for (aux = __elf_aux_vector; aux->a_type != AT_NULL; aux++) {
+ switch (aux->a_type) {
+ case AT_CANARY:
+ canary = (char *)(aux->a_un.a_ptr);
+ break;
+
+ case AT_CANARYLEN:
+ canary_len = aux->a_un.a_val;
+ break;
+
+ case AT_PAGESIZES:
+ pagesizes = (char *)(aux->a_un.a_ptr);
+ break;
+
+ case AT_PAGESIZESLEN:
+ pagesizes_len = aux->a_un.a_val;
+ break;
+
+ case AT_PAGESZ:
+ pagesize = aux->a_un.a_val;
+ break;
+
+ case AT_OSRELDATE:
+ osreldate = aux->a_un.a_val;
+ break;
+
+ case AT_NCPUS:
+ ncpus = aux->a_un.a_val;
+ break;
+
+ case AT_TIMEKEEP:
+ timekeep = aux->a_un.a_ptr;
+ break;
+ }
+ }
+}
+
+int
+_elf_aux_info(int aux, void *buf, int buflen)
+{
+ int res;
+
+ __init_elf_aux_vector();
+ if (__elf_aux_vector == NULL)
+ return (ENOSYS);
+ _once(&aux_once, init_aux);
+
+ switch (aux) {
+ case AT_CANARY:
+ if (canary != NULL && canary_len >= buflen) {
+ memcpy(buf, canary, buflen);
+ memset(canary, 0, canary_len);
+ canary = NULL;
+ res = 0;
+ } else
+ res = ENOENT;
+ break;
+ case AT_PAGESIZES:
+ if (pagesizes != NULL && pagesizes_len >= buflen) {
+ memcpy(buf, pagesizes, buflen);
+ res = 0;
+ } else
+ res = ENOENT;
+ break;
+
+ case AT_PAGESZ:
+ if (buflen == sizeof(int)) {
+ if (pagesize != 0) {
+ *(int *)buf = pagesize;
+ res = 0;
+ } else
+ res = ENOENT;
+ } else
+ res = EINVAL;
+ break;
+ case AT_OSRELDATE:
+ if (buflen == sizeof(int)) {
+ if (osreldate != 0) {
+ *(int *)buf = osreldate;
+ res = 0;
+ } else
+ res = ENOENT;
+ } else
+ res = EINVAL;
+ break;
+ case AT_NCPUS:
+ if (buflen == sizeof(int)) {
+ if (ncpus != 0) {
+ *(int *)buf = ncpus;
+ res = 0;
+ } else
+ res = ENOENT;
+ } else
+ res = EINVAL;
+ break;
+ case AT_TIMEKEEP:
+ if (buflen == sizeof(void *)) {
+ if (timekeep != NULL) {
+ *(void **)buf = timekeep;
+ res = 0;
+ } else
+ res = ENOENT;
+ } else
+ res = EINVAL;
+ break;
+ default:
+ res = ENOENT;
+ break;
+ }
+ return (res);
+}
diff -r a301a330526b -r 49889ad5ef1f head/lib/libthr/arch/arm/include/pthread_md.h
--- a/head/lib/libthr/arch/arm/include/pthread_md.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/libthr/arch/arm/include/pthread_md.h Wed Aug 15 11:46:11 2012 +0300
@@ -23,7 +23,7 @@
* (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: head/lib/libthr/arch/arm/include/pthread_md.h 231619 2012-02-14 00:17:43Z gonzo $
+ * $FreeBSD: head/lib/libthr/arch/arm/include/pthread_md.h 239270 2012-08-15 03:08:29Z gonzo $
*/
/*
@@ -57,7 +57,11 @@
static __inline void
_tcb_set(struct tcb *tcb)
{
- *((struct tcb **)ARM_TP_ADDRESS) = tcb;
+#ifdef ARM_TP_ADDRESS
+ *((struct tcb **)ARM_TP_ADDRESS) = tcb; /* avoids a system call */
+#else
+ sysarch(ARM_SET_TP, tcb);
+#endif
}
/*
@@ -66,7 +70,15 @@
static __inline struct tcb *
_tcb_get(void)
{
+#ifdef ARM_TP_ADDRESS
return (*((struct tcb **)ARM_TP_ADDRESS));
+#else
+ struct tcb *tcb;
+
+ __asm __volatile("mrc p15, 0, %0, c13, c0, 3" \
+ : "=r" (tcb));
+ return (tcb);
+#endif
}
extern struct pthread *_thr_initial;
diff -r a301a330526b -r 49889ad5ef1f head/lib/libthr/thread/thr_cond.c
--- a/head/lib/libthr/thread/thr_cond.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/libthr/thread/thr_cond.c Wed Aug 15 11:46:11 2012 +0300
@@ -23,7 +23,7 @@
* (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$
+ * $FreeBSD: head/lib/libthr/thread/thr_cond.c 239206 2012-08-12 00:56:56Z davidxu $
*/
#include "namespace.h"
@@ -217,6 +217,7 @@
struct sleepqueue *sq;
int recurse;
int error;
+ int defered;
if (curthread->wchan != NULL)
PANIC("thread was already on queue.");
@@ -230,13 +231,24 @@
* us to check it without locking in pthread_cond_signal().
*/
cvp->__has_user_waiters = 1;
- curthread->will_sleep = 1;
- (void)_mutex_cv_unlock(mp, &recurse);
+ defered = 0;
+ (void)_mutex_cv_unlock(mp, &recurse, &defered);
curthread->mutex_obj = mp;
_sleepq_add(cvp, curthread);
for(;;) {
_thr_clear_wake(curthread);
_sleepq_unlock(cvp);
+ if (defered) {
+ defered = 0;
+ if ((mp->m_lock.m_owner & UMUTEX_CONTESTED) == 0)
+ (void)_umtx_op_err(&mp->m_lock, UMTX_OP_MUTEX_WAKE2,
+ mp->m_lock.m_flags, 0, 0);
+ }
+ if (curthread->nwaiter_defer > 0) {
+ _thr_wake_all(curthread->defer_waiters,
+ curthread->nwaiter_defer);
+ curthread->nwaiter_defer = 0;
+ }
if (cancel) {
_thr_cancel_enter2(curthread, 0);
diff -r a301a330526b -r 49889ad5ef1f head/lib/libthr/thread/thr_kern.c
--- a/head/lib/libthr/thread/thr_kern.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/libthr/thread/thr_kern.c Wed Aug 15 11:46:11 2012 +0300
@@ -24,7 +24,7 @@
* (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$
+ * $FreeBSD: head/lib/libthr/thread/thr_kern.c 239200 2012-08-11 23:17:02Z davidxu $
*/
#include <sys/types.h>
@@ -199,13 +199,6 @@
const struct timespec *abstime)
{
- curthread->will_sleep = 0;
- if (curthread->nwaiter_defer > 0) {
- _thr_wake_all(curthread->defer_waiters,
- curthread->nwaiter_defer);
- curthread->nwaiter_defer = 0;
- }
-
if (curthread->wake_addr->value != 0)
return (0);
diff -r a301a330526b -r 49889ad5ef1f head/lib/libthr/thread/thr_mutex.c
--- a/head/lib/libthr/thread/thr_mutex.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/libthr/thread/thr_mutex.c Wed Aug 15 11:46:11 2012 +0300
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/lib/libthr/thread/thr_mutex.c 236135 2012-05-27 01:24:51Z davidxu $
+ * $FreeBSD: head/lib/libthr/thread/thr_mutex.c 239200 2012-08-11 23:17:02Z davidxu $
*/
#include "namespace.h"
@@ -92,7 +92,7 @@
static int mutex_self_trylock(pthread_mutex_t);
static int mutex_self_lock(pthread_mutex_t,
const struct timespec *abstime);
-static int mutex_unlock_common(struct pthread_mutex *, int);
+static int mutex_unlock_common(struct pthread_mutex *, int, int *);
static int mutex_lock_sleep(struct pthread *, pthread_mutex_t,
const struct timespec *);
@@ -461,7 +461,7 @@
struct pthread_mutex *mp;
mp = *mutex;
- return (mutex_unlock_common(mp, 0));
+ return (mutex_unlock_common(mp, 0, NULL));
}
int
@@ -476,7 +476,7 @@
}
int
-_mutex_cv_unlock(struct pthread_mutex *m, int *count)
+_mutex_cv_unlock(struct pthread_mutex *m, int *count, int *defer)
{
/*
@@ -484,7 +484,7 @@
*/
*count = m->m_count;
m->m_count = 0;
- (void)mutex_unlock_common(m, 1);
+ (void)mutex_unlock_common(m, 1, defer);
return (0);
}
@@ -629,7 +629,7 @@
}
static int
-mutex_unlock_common(struct pthread_mutex *m, int cv)
+mutex_unlock_common(struct pthread_mutex *m, int cv, int *mtx_defer)
{
struct pthread *curthread = _get_curthread();
uint32_t id;
@@ -657,12 +657,12 @@
defered = 1;
m->m_flags &= ~PMUTEX_FLAG_DEFERED;
} else
- defered = 0;
+ defered = 0;
DEQUEUE_MUTEX(curthread, m);
- _thr_umutex_unlock(&m->m_lock, id);
+ _thr_umutex_unlock2(&m->m_lock, id, mtx_defer);
- if (curthread->will_sleep == 0 && defered) {
+ if (mtx_defer == NULL && defered) {
_thr_wake_all(curthread->defer_waiters,
curthread->nwaiter_defer);
curthread->nwaiter_defer = 0;
diff -r a301a330526b -r 49889ad5ef1f head/lib/libthr/thread/thr_private.h
--- a/head/lib/libthr/thread/thr_private.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/libthr/thread/thr_private.h Wed Aug 15 11:46:11 2012 +0300
@@ -26,7 +26,7 @@
* (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: head/lib/libthr/thread/thr_private.h 234947 2012-05-03 09:17:31Z davidxu $
+ * $FreeBSD: head/lib/libthr/thread/thr_private.h 239200 2012-08-11 23:17:02Z davidxu $
*/
#ifndef _THR_PRIVATE_H
@@ -727,10 +727,10 @@
*/
__BEGIN_DECLS
int _thr_setthreaded(int) __hidden;
-int _mutex_cv_lock(struct pthread_mutex *, int count) __hidden;
-int _mutex_cv_unlock(struct pthread_mutex *, int *count) __hidden;
-int _mutex_cv_attach(struct pthread_mutex *, int count) __hidden;
-int _mutex_cv_detach(struct pthread_mutex *, int *count) __hidden;
+int _mutex_cv_lock(struct pthread_mutex *, int) __hidden;
+int _mutex_cv_unlock(struct pthread_mutex *, int *, int *) __hidden;
+int _mutex_cv_attach(struct pthread_mutex *, int) __hidden;
+int _mutex_cv_detach(struct pthread_mutex *, int *) __hidden;
int _mutex_owned(struct pthread *, const struct pthread_mutex *) __hidden;
int _mutex_reinit(pthread_mutex_t *) __hidden;
void _mutex_fork(struct pthread *curthread) __hidden;
diff -r a301a330526b -r 49889ad5ef1f head/lib/libthr/thread/thr_umtx.h
--- a/head/lib/libthr/thread/thr_umtx.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/libthr/thread/thr_umtx.h Wed Aug 15 11:46:11 2012 +0300
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/lib/libthr/thread/thr_umtx.h 233912 2012-04-05 02:24:08Z davidxu $
+ * $FreeBSD: head/lib/libthr/thread/thr_umtx.h 239200 2012-08-11 23:17:02Z davidxu $
*/
#ifndef _THR_FBSD_UMTX_H_
@@ -120,7 +120,7 @@
}
static inline int
-_thr_umutex_unlock(struct umutex *mtx, uint32_t id)
+_thr_umutex_unlock2(struct umutex *mtx, uint32_t id, int *defer)
{
uint32_t flags = mtx->m_flags;
@@ -132,8 +132,12 @@
return (EPERM);
} while (__predict_false(!atomic_cmpset_rel_32(&mtx->m_owner,
owner, UMUTEX_UNOWNED)));
- if ((owner & UMUTEX_CONTESTED))
- (void)_umtx_op_err(mtx, UMTX_OP_MUTEX_WAKE2, flags, 0, 0);
+ if ((owner & UMUTEX_CONTESTED)) {
+ if (defer == NULL)
+ (void)_umtx_op_err(mtx, UMTX_OP_MUTEX_WAKE2, flags, 0, 0);
+ else
+ *defer = 1;
+ }
return (0);
}
if (atomic_cmpset_rel_32(&mtx->m_owner, id, UMUTEX_UNOWNED))
@@ -142,6 +146,12 @@
}
static inline int
+_thr_umutex_unlock(struct umutex *mtx, uint32_t id)
+{
+ return _thr_umutex_unlock2(mtx, id, NULL);
+}
+
+static inline int
_thr_rwlock_tryrdlock(struct urwlock *rwlock, int flags)
{
int32_t state;
diff -r a301a330526b -r 49889ad5ef1f head/lib/libusb/libusb20.3
--- a/head/lib/libusb/libusb20.3 Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/libusb/libusb20.3 Wed Aug 15 11:46:11 2012 +0300
@@ -24,9 +24,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: head/lib/libusb/libusb20.3 236438 2012-06-02 08:47:26Z joel $
+.\" $FreeBSD: head/lib/libusb/libusb20.3 239239 2012-08-13 18:10:52Z hselasky $
.\"
-.Dd October 14, 2010
+.Dd August 13, 2012
.Dt LIBUSB20 3
.Os
.Sh NAME
@@ -48,6 +48,7 @@
.Fn libusb20_tr_close "struct libusb20_transfer *xfer"
.Ft int
.Fn libusb20_tr_open "struct libusb20_transfer *xfer" "uint32_t max_buf_size" "uint32_t max_frame_count" "uint8_t ep_no"
+.Fn libusb20_tr_open_stream "struct libusb20_transfer *xfer" "uint32_t max_buf_size" "uint32_t max_frame_count" "uint8_t ep_no" "uint16_t stream_id"
.Ft struct libusb20_transfer*
.Fn libusb20_tr_get_pointer "struct libusb20_device *pdev" "uint16_t tr_index"
.Ft uint16_t
@@ -284,6 +285,16 @@
.
.Pp
.
+.Fn libusb20_tr_open_stream
+is identical to
+.Fn libusb20_tr_open
+except that a stream ID can be specified for BULK endpoints having
+such a feature.
+.Fn libusb20_tr_open
+can be used to open stream ID zero.
+.
+.Pp
+.
.Fn libusb20_tr_get_pointer
will return a pointer to the allocated USB transfer according to the
.Fa pdev
diff -r a301a330526b -r 49889ad5ef1f head/lib/libusb/libusb20.c
--- a/head/lib/libusb/libusb20.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/libusb/libusb20.c Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/lib/libusb/libusb20.c 234491 2012-04-20 14:29:45Z hselasky $ */
+/* $FreeBSD: head/lib/libusb/libusb20.c 239239 2012-08-13 18:10:52Z hselasky $ */
/*-
* Copyright (c) 2008-2009 Hans Petter Selasky. All rights reserved.
*
@@ -155,6 +155,13 @@
libusb20_tr_open(struct libusb20_transfer *xfer, uint32_t MaxBufSize,
uint32_t MaxFrameCount, uint8_t ep_no)
{
+ return (libusb20_tr_open_stream(xfer, MaxBufSize, MaxFrameCount, ep_no, 0));
+}
+
+int
+libusb20_tr_open_stream(struct libusb20_transfer *xfer, uint32_t MaxBufSize,
+ uint32_t MaxFrameCount, uint8_t ep_no, uint16_t stream_id)
+{
uint32_t size;
uint8_t pre_scale;
int error;
@@ -188,7 +195,7 @@
memset(xfer->ppBuffer, 0, size);
error = xfer->pdev->methods->tr_open(xfer, MaxBufSize,
- MaxFrameCount, ep_no, pre_scale);
+ MaxFrameCount, ep_no, stream_id, pre_scale);
if (error) {
free(xfer->ppBuffer);
diff -r a301a330526b -r 49889ad5ef1f head/lib/libusb/libusb20.h
--- a/head/lib/libusb/libusb20.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/libusb/libusb20.h Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/lib/libusb/libusb20.h 225659 2011-09-19 08:52:06Z hselasky $ */
+/* $FreeBSD: head/lib/libusb/libusb20.h 239239 2012-08-13 18:10:52Z hselasky $ */
/*-
* Copyright (c) 2008-2009 Hans Petter Selasky. All rights reserved.
* Copyright (c) 2007-2008 Daniel Drake. All rights reserved.
@@ -202,6 +202,7 @@
/* USB transfer operations */
int libusb20_tr_close(struct libusb20_transfer *xfer);
int libusb20_tr_open(struct libusb20_transfer *xfer, uint32_t max_buf_size, uint32_t max_frame_count, uint8_t ep_no);
+int libusb20_tr_open_stream(struct libusb20_transfer *xfer, uint32_t max_buf_size, uint32_t max_frame_count, uint8_t ep_no, uint16_t stream_id);
struct libusb20_transfer *libusb20_tr_get_pointer(struct libusb20_device *pdev, uint16_t tr_index);
uint16_t libusb20_tr_get_time_complete(struct libusb20_transfer *xfer);
uint32_t libusb20_tr_get_actual_frames(struct libusb20_transfer *xfer);
diff -r a301a330526b -r 49889ad5ef1f head/lib/libusb/libusb20_int.h
--- a/head/lib/libusb/libusb20_int.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/libusb/libusb20_int.h Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/lib/libusb/libusb20_int.h 223495 2011-06-24 11:14:09Z hselasky $ */
+/* $FreeBSD: head/lib/libusb/libusb20_int.h 239239 2012-08-13 18:10:52Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -110,7 +110,7 @@
typedef int (libusb20_check_connected_t)(struct libusb20_device *pdev);
/* USB transfer specific */
-typedef int (libusb20_tr_open_t)(struct libusb20_transfer *xfer, uint32_t MaxBufSize, uint32_t MaxFrameCount, uint8_t ep_no, uint8_t pre_scale);
+typedef int (libusb20_tr_open_t)(struct libusb20_transfer *xfer, uint32_t MaxBufSize, uint32_t MaxFrameCount, uint8_t ep_no, uint16_t stream_id, uint8_t pre_scale);
typedef int (libusb20_tr_close_t)(struct libusb20_transfer *xfer);
typedef int (libusb20_tr_clear_stall_sync_t)(struct libusb20_transfer *xfer);
typedef void (libusb20_tr_submit_t)(struct libusb20_transfer *xfer);
diff -r a301a330526b -r 49889ad5ef1f head/lib/libusb/libusb20_ugen20.c
--- a/head/lib/libusb/libusb20_ugen20.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/libusb/libusb20_ugen20.c Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/lib/libusb/libusb20_ugen20.c 234491 2012-04-20 14:29:45Z hselasky $ */
+/* $FreeBSD: head/lib/libusb/libusb20_ugen20.c 239239 2012-08-13 18:10:52Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -741,9 +741,13 @@
static int
ugen20_tr_open(struct libusb20_transfer *xfer, uint32_t MaxBufSize,
- uint32_t MaxFrameCount, uint8_t ep_no, uint8_t pre_scale)
+ uint32_t MaxFrameCount, uint8_t ep_no, uint16_t stream_id,
+ uint8_t pre_scale)
{
- struct usb_fs_open temp;
+ union {
+ struct usb_fs_open fs_open;
+ struct usb_fs_open_stream fs_open_stream;
+ } temp;
struct usb_fs_endpoint *fsep;
if (pre_scale)
@@ -754,20 +758,26 @@
fsep = xfer->pdev->privBeData;
fsep += xfer->trIndex;
- temp.max_bufsize = MaxBufSize;
- temp.max_frames = MaxFrameCount;
- temp.ep_index = xfer->trIndex;
- temp.ep_no = ep_no;
+ temp.fs_open.max_bufsize = MaxBufSize;
+ temp.fs_open.max_frames = MaxFrameCount;
+ temp.fs_open.ep_index = xfer->trIndex;
+ temp.fs_open.ep_no = ep_no;
- if (ioctl(xfer->pdev->file, USB_FS_OPEN, &temp)) {
- return (LIBUSB20_ERROR_INVALID_PARAM);
+ if (stream_id != 0) {
+ temp.fs_open_stream.stream_id = stream_id;
+
+ if (ioctl(xfer->pdev->file, USB_FS_OPEN_STREAM, &temp.fs_open_stream))
+ return (LIBUSB20_ERROR_INVALID_PARAM);
+ } else {
+ if (ioctl(xfer->pdev->file, USB_FS_OPEN, &temp.fs_open))
+ return (LIBUSB20_ERROR_INVALID_PARAM);
}
/* maximums might have changed - update */
- xfer->maxFrames = temp.max_frames;
+ xfer->maxFrames = temp.fs_open.max_frames;
/* "max_bufsize" should be multiple of "max_packet_length" */
- xfer->maxTotalLength = temp.max_bufsize;
- xfer->maxPacketLen = temp.max_packet_length;
+ xfer->maxTotalLength = temp.fs_open.max_bufsize;
+ xfer->maxPacketLen = temp.fs_open.max_packet_length;
/* setup buffer and length lists using zero copy */
fsep->ppBuffer = libusb20_pass_ptr(xfer->ppBuffer);
diff -r a301a330526b -r 49889ad5ef1f head/lib/msun/src/e_rem_pio2.c
--- a/head/lib/msun/src/e_rem_pio2.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/msun/src/e_rem_pio2.c Wed Aug 15 11:46:11 2012 +0300
@@ -14,7 +14,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/lib/msun/src/e_rem_pio2.c 223302 2011-06-19 17:07:58Z kargl $");
+__FBSDID("$FreeBSD: head/lib/msun/src/e_rem_pio2.c 239195 2012-08-11 15:47:22Z dim $");
/* __ieee754_rem_pio2(x,y)
*
@@ -48,10 +48,10 @@
pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */
pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
-#ifndef INLINE_REM_PIO2
-extern
+#ifdef INLINE_REM_PIO2
+static __inline __always_inline
#endif
-__inline int
+int
__ieee754_rem_pio2(double x, double *y)
{
double z,w,t,r,fn;
diff -r a301a330526b -r 49889ad5ef1f head/lib/msun/src/e_rem_pio2f.c
--- a/head/lib/msun/src/e_rem_pio2f.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/msun/src/e_rem_pio2f.c Wed Aug 15 11:46:11 2012 +0300
@@ -15,7 +15,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/lib/msun/src/e_rem_pio2f.c 239195 2012-08-11 15:47:22Z dim $");
/* __ieee754_rem_pio2f(x,y)
*
@@ -31,7 +31,7 @@
/*
* invpio2: 53 bits of 2/pi
- * pio2_1: first 33 bit of pi/2
+ * pio2_1: first 25 bits of pi/2
* pio2_1t: pi/2 - pio2_1
*/
@@ -40,10 +40,10 @@
pio2_1 = 1.57079631090164184570e+00, /* 0x3FF921FB, 0x50000000 */
pio2_1t = 1.58932547735281966916e-08; /* 0x3E5110b4, 0x611A6263 */
-#ifndef INLINE_REM_PIO2F
-extern
+#ifdef INLINE_REM_PIO2F
+static __inline __always_inline
#endif
-__inline int
+int
__ieee754_rem_pio2f(float x, double *y)
{
double w,r,fn;
diff -r a301a330526b -r 49889ad5ef1f head/lib/msun/src/k_cosf.c
--- a/head/lib/msun/src/k_cosf.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/msun/src/k_cosf.c Wed Aug 15 11:46:11 2012 +0300
@@ -16,7 +16,7 @@
#ifndef INLINE_KERNEL_COSDF
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/lib/msun/src/k_cosf.c 239192 2012-08-11 11:13:48Z dim $");
#endif
#include "math.h"
@@ -30,10 +30,10 @@
C2 = -0x16c087e80f1e27.0p-62, /* -0.00138867637746099294692 */
C3 = 0x199342e0ee5069.0p-68; /* 0.0000243904487962774090654 */
-#ifndef INLINE_KERNEL_COSDF
-extern
+#ifdef INLINE_KERNEL_COSDF
+static __inline
#endif
-__inline float
+float
__kernel_cosdf(double x)
{
double r, w, z;
diff -r a301a330526b -r 49889ad5ef1f head/lib/msun/src/k_sinf.c
--- a/head/lib/msun/src/k_sinf.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/msun/src/k_sinf.c Wed Aug 15 11:46:11 2012 +0300
@@ -16,7 +16,7 @@
#ifndef INLINE_KERNEL_SINDF
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/lib/msun/src/k_sinf.c 239192 2012-08-11 11:13:48Z dim $");
#endif
#include "math.h"
@@ -29,10 +29,10 @@
S3 = -0x1a00f9e2cae774.0p-65, /* -0.000198393348360966317347 */
S4 = 0x16cd878c3b46a7.0p-71; /* 0.0000027183114939898219064 */
-#ifndef INLINE_KERNEL_SINDF
-extern
+#ifdef INLINE_KERNEL_SINDF
+static __inline
#endif
-__inline float
+float
__kernel_sindf(double x)
{
double r, s, w, z;
diff -r a301a330526b -r 49889ad5ef1f head/lib/msun/src/k_tanf.c
--- a/head/lib/msun/src/k_tanf.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/msun/src/k_tanf.c Wed Aug 15 11:46:11 2012 +0300
@@ -15,7 +15,7 @@
#ifndef INLINE_KERNEL_TANDF
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/lib/msun/src/k_tanf.c 239192 2012-08-11 11:13:48Z dim $");
#endif
#include "math.h"
@@ -32,10 +32,10 @@
0x1362b9bf971bcd.0p-59, /* 0.00946564784943673166728 */
};
-#ifndef INLINE_KERNEL_TANDF
-extern
+#ifdef INLINE_KERNEL_TANDF
+static __inline
#endif
-__inline float
+float
__kernel_tandf(double x, int iy)
{
double z,r,w,s,t,u;
diff -r a301a330526b -r 49889ad5ef1f head/lib/msun/src/math_private.h
--- a/head/lib/msun/src/math_private.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/lib/msun/src/math_private.h Wed Aug 15 11:46:11 2012 +0300
@@ -11,7 +11,7 @@
/*
* from: @(#)fdlibm.h 5.1 93/09/24
- * $FreeBSD: head/lib/msun/src/math_private.h 238722 2012-07-23 19:13:55Z kargl $
+ * $FreeBSD: head/lib/msun/src/math_private.h 239192 2012-08-11 11:13:48Z dim $
*/
#ifndef _MATH_PRIVATE_H_
@@ -431,10 +431,9 @@
int __kernel_rem_pio2(double*,double*,int,int,int);
/* double precision kernel functions */
-#ifdef INLINE_REM_PIO2
-__inline
+#ifndef INLINE_REM_PIO2
+int __ieee754_rem_pio2(double,double*);
#endif
-int __ieee754_rem_pio2(double,double*);
double __kernel_sin(double,double,int);
double __kernel_cos(double,double);
double __kernel_tan(double,double,int);
@@ -444,22 +443,18 @@
#endif
/* float precision kernel functions */
-#ifdef INLINE_REM_PIO2F
-__inline
+#ifndef INLINE_REM_PIO2F
+int __ieee754_rem_pio2f(float,double*);
#endif
-int __ieee754_rem_pio2f(float,double*);
-#ifdef INLINE_KERNEL_SINDF
-__inline
+#ifndef INLINE_KERNEL_SINDF
+float __kernel_sindf(double);
#endif
-float __kernel_sindf(double);
-#ifdef INLINE_KERNEL_COSDF
-__inline
+#ifndef INLINE_KERNEL_COSDF
+float __kernel_cosdf(double);
#endif
-float __kernel_cosdf(double);
-#ifdef INLINE_KERNEL_TANDF
-__inline
+#ifndef INLINE_KERNEL_TANDF
+float __kernel_tandf(double,int);
#endif
-float __kernel_tandf(double,int);
float __ldexp_expf(float,int);
#ifdef _COMPLEX_H
float complex __ldexp_cexpf(float complex,int);
diff -r a301a330526b -r 49889ad5ef1f head/libexec/rtld-elf/arm/reloc.c
--- a/head/libexec/rtld-elf/arm/reloc.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/libexec/rtld-elf/arm/reloc.c Wed Aug 15 11:46:11 2012 +0300
@@ -1,7 +1,7 @@
/* $NetBSD: mdreloc.c,v 1.23 2003/07/26 15:04:38 mrg Exp $ */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/libexec/rtld-elf/arm/reloc.c 234841 2012-04-30 13:31:10Z kib $");
+__FBSDID("$FreeBSD: head/libexec/rtld-elf/arm/reloc.c 239269 2012-08-15 03:07:41Z gonzo $");
#include <sys/param.h>
#include <sys/mman.h>
@@ -433,7 +433,9 @@
void
allocate_initial_tls(Obj_Entry *objs)
{
+#ifdef ARM_TP_ADDRESS
void **_tp = (void **)ARM_TP_ADDRESS;
+#endif
/*
* Fix the size of the static TLS block by using the maximum
@@ -443,16 +445,27 @@
tls_static_space = tls_last_offset + tls_last_size + RTLD_STATIC_TLS_EXTRA;
+#ifdef ARM_TP_ADDRESS
(*_tp) = (void *) allocate_tls(objs, NULL, TLS_TCB_SIZE, 8);
+#else
+ sysarch(ARM_SET_TP, allocate_tls(objs, NULL, TLS_TCB_SIZE, 8));
+#endif
}
void *
__tls_get_addr(tls_index* ti)
{
+ char *p;
+#ifdef ARM_TP_ADDRESS
void **_tp = (void **)ARM_TP_ADDRESS;
- char *p;
p = tls_get_addr_common((Elf_Addr **)(*_tp), ti->ti_module, ti->ti_offset);
+#else
+ void *_tp;
+ __asm __volatile("mrc p15, 0, %0, c13, c0, 3" \
+ : "=r" (_tp));
+ p = tls_get_addr_common((Elf_Addr **)(_tp), ti->ti_module, ti->ti_offset);
+#endif
return (p);
}
diff -r a301a330526b -r 49889ad5ef1f head/libexec/rtld-elf/rtld.c
--- a/head/libexec/rtld-elf/rtld.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/libexec/rtld-elf/rtld.c Wed Aug 15 11:46:11 2012 +0300
@@ -25,7 +25,7 @@
* (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: head/libexec/rtld-elf/rtld.c 238471 2012-07-15 10:53:48Z kib $
+ * $FreeBSD: head/libexec/rtld-elf/rtld.c 239253 2012-08-14 13:28:30Z kan $
*/
/*
@@ -1743,6 +1743,26 @@
root->dag_inited = true;
}
+static void
+process_nodelete(Obj_Entry *root)
+{
+ const Objlist_Entry *elm;
+
+ /*
+ * Walk over object DAG and process every dependent object that
+ * is marked as DF_1_NODELETE. They need to grow their own DAG,
+ * which then should have its reference upped separately.
+ */
+ STAILQ_FOREACH(elm, &root->dagmembers, link) {
+ if (elm->obj != NULL && elm->obj->z_nodelete &&
+ !elm->obj->ref_nodel) {
+ dbg("obj %s nodelete", elm->obj->path);
+ init_dag(elm->obj);
+ ref_dag(elm->obj);
+ elm->obj->ref_nodel = true;
+ }
+ }
+}
/*
* Initialize the dynamic linker. The argument is the address at which
* the dynamic linker has been mapped into memory. The primary task of
@@ -1932,12 +1952,6 @@
flags & ~RTLD_LO_NOLOAD);
if (obj1 == NULL && !ld_tracing && (flags & RTLD_LO_FILTEES) == 0)
return (-1);
- if (obj1 != NULL && obj1->z_nodelete && !obj1->ref_nodel) {
- dbg("obj %s nodelete", obj1->path);
- init_dag(obj1);
- ref_dag(obj1);
- obj1->ref_nodel = true;
- }
}
return (0);
}
@@ -2833,8 +2847,14 @@
/* Make list of init functions to call. */
initlist_add_objects(obj, &obj->next, &initlist);
}
+ /*
+ * Process all no_delete objects here, given them own
+ * DAGs to prevent their dependencies from being unloaded.
+ * This has to be done after we have loaded all of the
+ * dependencies, so that we do not miss any.
+ */
+ process_nodelete(obj);
} else {
-
/*
* Bump the reference counts for objects on this DAG. If
* this is the first dlopen() call for the object that was
diff -r a301a330526b -r 49889ad5ef1f head/share/man/man4/sched_ule.4
--- a/head/share/man/man4/sched_ule.4 Wed Aug 15 11:16:36 2012 +0300
+++ b/head/share/man/man4/sched_ule.4 Wed Aug 15 11:46:11 2012 +0300
@@ -22,9 +22,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD$
+.\" $FreeBSD: head/share/man/man4/sched_ule.4 239185 2012-08-10 19:02:49Z mav $
.\"
-.Dd January 21, 2008
+.Dd August 10, 2012
.Dt SCHED_ULE 4
.Os
.Sh NAME
@@ -59,6 +59,9 @@
.Bl -tag -width indent
.It Va kern.sched.name
This read-only sysctl reports the name of the active scheduler.
+.It Va kern.sched.quantum
+This read-write sysctl reports or sets the length of the quantum (in
+micro-seconds) granted to a thread.
.El
.Sh SEE ALSO
.Xr sched_4bsd 4 ,
diff -r a301a330526b -r 49889ad5ef1f head/share/mk/bsd.cpu.mk
--- a/head/share/mk/bsd.cpu.mk Wed Aug 15 11:16:36 2012 +0300
+++ b/head/share/mk/bsd.cpu.mk Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD: head/share/mk/bsd.cpu.mk 220863 2011-04-19 18:09:21Z dim $
+# $FreeBSD: head/share/mk/bsd.cpu.mk 239272 2012-08-15 03:21:56Z gonzo $
# Set default CPU compile flags and baseline CPUTYPE for each arch. The
# compile flags must support the minimum CPU type for each architecture but
@@ -99,8 +99,13 @@
#_CPUCFLAGS = -mcpu=xscale
#_CPUCFLAGS = -march=armv5te -D__XSCALE__
_CPUCFLAGS = -march=armv5te -mtune=xscale -D__XSCALE__
+_CPUCFLAGS = -march=armv5te -D__XSCALE__ -DARM_WANT_TP_ADDRESS
+. elif ${CPUTYPE} == "armv6"
+_CPUCFLAGS = -march=${CPUTYPE} -DARM_ARCH_6=1
+. elif ${CPUTYPE} == "cortexa"
+_CPUCFLAGS = -march=armv6 -DARM_ARCH_6=1 -mfpu=vfp
. else
-_CPUCFLAGS = -mcpu=${CPUTYPE}
+_CPUCFLAGS = -mcpu=${CPUTYPE} -DARM_WANT_TP_ADDRESS
. endif
. elif ${MACHINE_ARCH} == "powerpc"
. if ${CPUTYPE} == "e500"
diff -r a301a330526b -r 49889ad5ef1f head/share/mk/bsd.endian.mk
--- a/head/share/mk/bsd.endian.mk Wed Aug 15 11:16:36 2012 +0300
+++ b/head/share/mk/bsd.endian.mk Wed Aug 15 11:46:11 2012 +0300
@@ -1,15 +1,17 @@
-# $FreeBSD: head/share/mk/bsd.endian.mk 233644 2012-03-29 02:54:35Z jmallett $
+# $FreeBSD: head/share/mk/bsd.endian.mk 239272 2012-08-15 03:21:56Z gonzo $
.if ${MACHINE_ARCH} == "amd64" || \
${MACHINE_ARCH} == "i386" || \
${MACHINE_ARCH} == "ia64" || \
${MACHINE_ARCH} == "arm" || \
+ ${MACHINE_ARCH} == "armv6" || \
${MACHINE_ARCH:Mmips*el} != ""
TARGET_ENDIANNESS= 1234
.elif ${MACHINE_ARCH} == "powerpc" || \
${MACHINE_ARCH} == "powerpc64" || \
${MACHINE_ARCH} == "sparc64" || \
${MACHINE_ARCH} == "armeb" || \
+ ${MACHINE_ARCH} == "armv6eb" || \
${MACHINE_ARCH:Mmips*} != ""
TARGET_ENDIANNESS= 4321
.endif
diff -r a301a330526b -r 49889ad5ef1f head/share/mk/sys.mk
--- a/head/share/mk/sys.mk Wed Aug 15 11:16:36 2012 +0300
+++ b/head/share/mk/sys.mk Wed Aug 15 11:46:11 2012 +0300
@@ -1,5 +1,5 @@
# from: @(#)sys.mk 8.2 (Berkeley) 3/21/94
-# $FreeBSD: head/share/mk/sys.mk 234575 2012-04-22 17:14:11Z imp $
+# $FreeBSD: head/share/mk/sys.mk 239272 2012-08-15 03:21:56Z gonzo $
unix ?= We run FreeBSD, not UNIX.
.FreeBSD ?= true
@@ -13,7 +13,7 @@
# and/or endian. This is called MACHINE_CPU in NetBSD, but that's used
# for something different in FreeBSD.
#
-MACHINE_CPUARCH=${MACHINE_ARCH:C/mips(n32|64)?(el)?/mips/:C/armeb/arm/:C/powerpc64/powerpc/}
+MACHINE_CPUARCH=${MACHINE_ARCH:C/mips(n32|64)?(el)?/mips/:C/arm(v6)?(eb)?/arm/:C/powerpc64/powerpc/}
.endif
# If the special target .POSIX appears (without prerequisites or
diff -r a301a330526b -r 49889ad5ef1f head/sys/amd64/amd64/mp_machdep.c
--- a/head/sys/amd64/amd64/mp_machdep.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/amd64/amd64/mp_machdep.c Wed Aug 15 11:46:11 2012 +0300
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/amd64/amd64/mp_machdep.c 237037 2012-06-13 22:53:56Z jkim $");
+__FBSDID("$FreeBSD: head/sys/amd64/amd64/mp_machdep.c 239241 2012-08-13 18:52:51Z jhb $");
#include "opt_cpu.h"
#include "opt_kstack_pages.h"
@@ -1036,26 +1036,15 @@
{
/*
- * first we do an INIT/RESET IPI this INIT IPI might be run, reseting
+ * first we do an INIT IPI: this INIT IPI might be run, resetting
* and running the target CPU. OR this INIT IPI might be latched (P5
* bug), CPU waiting for STARTUP IPI. OR this INIT IPI might be
* ignored.
*/
-
- /* do an INIT IPI: assert RESET */
lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
APIC_LEVEL_ASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_INIT, apic_id);
-
- /* wait for pending status end */
lapic_ipi_wait(-1);
-
- /* do an INIT IPI: deassert RESET */
- lapic_ipi_raw(APIC_DEST_ALLESELF | APIC_TRIGMOD_LEVEL |
- APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_INIT, 0);
-
- /* wait for pending status end */
DELAY(10000); /* wait ~10mS */
- lapic_ipi_wait(-1);
/*
* next we do a STARTUP IPI: the previous INIT IPI might still be
@@ -1065,8 +1054,6 @@
* run. OR the previous INIT IPI was ignored. and this STARTUP IPI
* will run.
*/
-
- /* do a STARTUP IPI */
lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
vector, apic_id);
@@ -1079,7 +1066,6 @@
* this STARTUP IPI will be ignored, as only ONE STARTUP IPI is
* recognized after hardware RESET or INIT IPI.
*/
-
lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
vector, apic_id);
diff -r a301a330526b -r 49889ad5ef1f head/sys/amd64/amd64/trap.c
--- a/head/sys/amd64/amd64/trap.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/amd64/amd64/trap.c Wed Aug 15 11:46:11 2012 +0300
@@ -38,7 +38,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/amd64/amd64/trap.c 238623 2012-07-19 19:09:12Z kib $");
+__FBSDID("$FreeBSD: head/sys/amd64/amd64/trap.c 239252 2012-08-14 12:15:01Z kib $");
/*
* AMD64 Trap and System call handling
@@ -176,9 +176,14 @@
SYSCTL_INT(_machdep, OID_AUTO, panic_on_nmi, CTLFLAG_RW,
&panic_on_nmi, 0, "Panic on NMI");
TUNABLE_INT("machdep.panic_on_nmi", &panic_on_nmi);
-static int prot_fault_translation = 0;
+static int prot_fault_translation;
SYSCTL_INT(_machdep, OID_AUTO, prot_fault_translation, CTLFLAG_RW,
- &prot_fault_translation, 0, "Select signal to deliver on protection fault");
+ &prot_fault_translation, 0,
+ "Select signal to deliver on protection fault");
+static int uprintf_signal;
+SYSCTL_INT(_machdep, OID_AUTO, uprintf_signal, CTLFLAG_RW,
+ &uprintf_signal, 0,
+ "Print debugging information on trap signal to ctty");
/*
* Exception, fault, and trap interface to the FreeBSD kernel.
@@ -610,6 +615,19 @@
ksi.ksi_code = ucode;
ksi.ksi_trapno = type;
ksi.ksi_addr = (void *)addr;
+ if (uprintf_signal) {
+ uprintf("pid %d comm %s: signal %d err %lx code %d type %d "
+ "addr 0x%lx <%02x %02x %02x %02x %02x %02x %02x %02x>\n",
+ p->p_pid, p->p_comm, i, frame->tf_err, ucode, type, addr,
+ fubyte((void *)(frame->tf_rip + 0)),
+ fubyte((void *)(frame->tf_rip + 1)),
+ fubyte((void *)(frame->tf_rip + 2)),
+ fubyte((void *)(frame->tf_rip + 3)),
+ fubyte((void *)(frame->tf_rip + 4)),
+ fubyte((void *)(frame->tf_rip + 5)),
+ fubyte((void *)(frame->tf_rip + 6)),
+ fubyte((void *)(frame->tf_rip + 7)));
+ }
trapsignal(td, &ksi);
user:
diff -r a301a330526b -r 49889ad5ef1f head/sys/amd64/conf/XENHVM
--- a/head/sys/amd64/conf/XENHVM Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/amd64/conf/XENHVM Wed Aug 15 11:46:11 2012 +0300
@@ -1,13 +1,11 @@
#
# XENHVM -- Xen HVM kernel configuration file for FreeBSD/amd64
#
-# $FreeBSD$
+# $FreeBSD: head/sys/amd64/conf/XENHVM 239228 2012-08-13 07:36:57Z cperciva $
#
include GENERIC
ident XENHVM
-makeoptions MODULES_OVERRIDE=""
-
#
# Adaptive locks rely on a lock-free pointer read to determine the run state
# of the thread holding a lock when under contention; under a virtualisation
diff -r a301a330526b -r 49889ad5ef1f head/sys/amd64/ia32/ia32_sigtramp.S
--- a/head/sys/amd64/ia32/ia32_sigtramp.S Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/amd64/ia32/ia32_sigtramp.S Wed Aug 15 11:46:11 2012 +0300
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/sys/amd64/ia32/ia32_sigtramp.S 223254 2011-06-18 12:13:28Z kib $
+ * $FreeBSD: head/sys/amd64/ia32/ia32_sigtramp.S 239251 2012-08-14 12:13:27Z kib $
*/
#include "opt_compat.h"
@@ -91,8 +91,29 @@
*/
ALIGN_TEXT
lcall_tramp:
+ .code64
+ /*
+ * There, we are in 64bit mode and need to return to 32bit.
+ * First, convert call frame from 64 to 32 bit format.
+ */
+ pushq %rax
+ movl 16(%rsp),%eax
+ movl %eax,20(%rsp) /* ret %cs */
+ movl 8(%rsp),%eax
+ movl %eax,16(%rsp) /* ret %rip -> %eip */
+ popq %rax
+ addq $8,%rsp
+ /* Now return to 32bit */
+ pushq $0x33 /* _ucode32sel UPL */
+ callq 1f
+1:
+ addq $2f-1b,(%rsp)
+ lretq
+2:
+ /* Back in 32bit mode */
+ .code32
cmpl $SYS_vfork,%eax
- je 2f
+ je 4f
pushl %ebp
movl %esp,%ebp
pushl 0x24(%ebp) /* arg 6 */
@@ -101,19 +122,19 @@
pushl 0x18(%ebp)
pushl 0x14(%ebp)
pushl 0x10(%ebp) /* arg 1 */
- pushl 0xc(%ebp) /* gap */
+ pushl 0xc(%ebp) /* gap */
int $0x80
leavel
-1:
+3:
lretl
-2:
+4:
/*
* vfork handling is special and relies on the libc stub saving
* the return ip in %ecx. If vfork failed, then there is no
* child which can corrupt the frame created by call gate.
*/
int $0x80
- jb 1b
+ jb 3b
addl $8,%esp
jmpl *%ecx
#endif
diff -r a301a330526b -r 49889ad5ef1f head/sys/amd64/ia32/ia32_syscall.c
--- a/head/sys/amd64/ia32/ia32_syscall.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/amd64/ia32/ia32_syscall.c Wed Aug 15 11:46:11 2012 +0300
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/amd64/ia32/ia32_syscall.c 225474 2011-09-11 16:05:09Z kib $");
+__FBSDID("$FreeBSD: head/sys/amd64/ia32/ia32_syscall.c 239251 2012-08-14 12:13:27Z kib $");
/*
* 386 Trap and System call handling
@@ -244,7 +244,7 @@
bzero(ssd, sizeof(*ssd));
ssd->gd_looffset = lcall_addr;
ssd->gd_hioffset = lcall_addr >> 16;
- ssd->gd_selector = _ucode32sel;
+ ssd->gd_selector = _ucodesel;
ssd->gd_type = SDT_SYSCGT;
ssd->gd_dpl = SEL_UPL;
ssd->gd_p = 1;
diff -r a301a330526b -r 49889ad5ef1f head/sys/amd64/include/param.h
--- a/head/sys/amd64/include/param.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/amd64/include/param.h Wed Aug 15 11:46:11 2012 +0300
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)param.h 8.1 (Berkeley) 6/10/93
- * $FreeBSD: head/sys/amd64/include/param.h 224217 2011-07-19 13:00:30Z attilio $
+ * $FreeBSD: head/sys/amd64/include/param.h 239255 2012-08-14 17:01:21Z des $
*/
@@ -123,14 +123,6 @@
#define KSTACK_GUARD_PAGES 1 /* pages of kstack guard; 0 disables */
/*
- * Ceiling on amount of swblock kva space, can be changed via
- * the kern.maxswzone /boot/loader.conf variable.
- */
-#ifndef VM_SWZONE_SIZE_MAX
-#define VM_SWZONE_SIZE_MAX (32 * 1024 * 1024)
-#endif
-
-/*
* Mach derived conversion macros
*/
#define round_page(x) ((((unsigned long)(x)) + PAGE_MASK) & ~(PAGE_MASK))
diff -r a301a330526b -r 49889ad5ef1f head/sys/boot/common/disk.c
--- a/head/sys/boot/common/disk.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/boot/common/disk.c Wed Aug 15 11:46:11 2012 +0300
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/boot/common/disk.c 239058 2012-08-05 12:15:15Z ae $");
+__FBSDID("$FreeBSD: head/sys/boot/common/disk.c 239232 2012-08-13 13:33:21Z ae $");
#include <sys/disk.h>
#include <stand.h>
@@ -162,7 +162,7 @@
dev->d_opendata = od;
od->mediasize = mediasize;
od->sectorsize = sectorsize;
- DEBUG("open '%s', unit %d slice %d partition %d",
+ DEBUG("%s unit %d, slice %d, partition %d",
disk_fmtdev(dev), dev->d_unit, dev->d_slice, dev->d_partition);
/* Determine disk layout. */
@@ -173,16 +173,30 @@
rc = ENXIO;
goto out;
}
- if (dev->d_slice > 0) {
+ if (ptable_gettype(od->table) == PTABLE_BSD &&
+ dev->d_partition >= 0) {
+ /* It doesn't matter what value has d_slice */
+ rc = ptable_getpart(od->table, &part, dev->d_partition);
+ if (rc == 0)
+ dev->d_offset = part.start;
+ } else if (dev->d_slice > 0) {
/* Try to get information about partition */
rc = ptable_getpart(od->table, &part, dev->d_slice);
if (rc != 0) /* Partition doesn't exist */
goto out;
dev->d_offset = part.start;
- if (dev->d_partition == -1 ||
- dev->d_partition == 255)
+ if (dev->d_partition == 255)
goto out; /* Nothing more to do */
-
+ if (dev->d_partition == -1) {
+ /*
+ * If we are looking at a BSD slice, and the
+ * partition is < 0, assume the 'a' partition.
+ */
+ if (part.type == PART_FREEBSD)
+ dev->d_partition = 0;
+ else
+ goto out;
+ }
/* Try to read BSD label */
table = ptable_open(dev, part.end - part.start + 1,
od->sectorsize, ptblread);
@@ -206,10 +220,14 @@
out:
if (table != NULL)
ptable_close(table);
+
if (rc != 0) {
if (od->table != NULL)
ptable_close(od->table);
free(od);
+ DEBUG("%s could not open", disk_fmtdev(dev));
+ } else {
+ DEBUG("%s offset %lld", disk_fmtdev(dev), dev->d_offset);
}
return (rc);
}
@@ -220,6 +238,7 @@
struct open_disk *od;
od = (struct open_disk *)dev->d_opendata;
+ DEBUG("%s closed", disk_fmtdev(dev));
ptable_close(od->table);
free(od);
return (0);
@@ -242,9 +261,9 @@
#ifdef LOADER_MBR_SUPPORT
cp += sprintf(cp, "s%d", dev->d_slice);
#endif
- if (dev->d_partition >= 0)
- cp += sprintf(cp, "%c", dev->d_partition + 'a');
}
+ if (dev->d_partition >= 0)
+ cp += sprintf(cp, "%c", dev->d_partition + 'a');
strcat(cp, ":");
return (buf);
}
diff -r a301a330526b -r 49889ad5ef1f head/sys/boot/common/disk.h
--- a/head/sys/boot/common/disk.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/boot/common/disk.h Wed Aug 15 11:46:11 2012 +0300
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/sys/boot/common/disk.h 239058 2012-08-05 12:15:15Z ae $
+ * $FreeBSD: head/sys/boot/common/disk.h 239230 2012-08-13 13:08:30Z ae $
*/
/*
@@ -45,6 +45,11 @@
* d_slice = MBR slice number (typically 1..4)
* d_partition = disklabel partition (typically 0..7)
*
+ * BSD disklabel partition on the true dedicated disk:
+ *
+ * d_slice = -1
+ * d_partition = disklabel partition (typically 0..7)
+ *
* GPT partition:
*
* d_slice = GPT partition number (typically 1..N)
diff -r a301a330526b -r 49889ad5ef1f head/sys/boot/common/loader.8
--- a/head/sys/boot/common/loader.8 Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/boot/common/loader.8 Wed Aug 15 11:46:11 2012 +0300
@@ -22,7 +22,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: head/sys/boot/common/loader.8 235873 2012-05-24 02:24:03Z wblock $
+.\" $FreeBSD: head/sys/boot/common/loader.8 239255 2012-08-14 17:01:21Z des $
.\"
.Dd January 7, 2012
.Dt LOADER 8
@@ -613,17 +613,26 @@
for details.
.It Va kern.maxswzone
Limits the amount of KVM to be used to hold swap
-meta information, which directly governs the
-maximum amount of swap the system can support.
-This value is specified in bytes of KVA space
-and defaults to 32MBytes on i386 and amd64.
-Care should be taken
-to not reduce this value such that the actual
-amount of configured swap exceeds 1/2 the
-kernel-supported swap.
-The default of 32MB allows
-the kernel to support a maximum of ~7GB of swap.
-Only change
+metadata, which directly governs the
+maximum amount of swap the system can support,
+at the rate of approximately 200 MB of swap space
+per 1 MB of metadata.
+This value is specified in bytes of KVA space.
+If no value is provided, the system allocates
+enough memory to handle an amount of swap
+that corresponds to eight times the amount of
+physical memory present in the system.
+.Pp
+Note that swap metadata can be fragmented,
+which means that the system can run out of
+space before it reaches the theoretical limit.
+Therefore, care should be taken to not configure
+more swap than approximately half of the
+theoretical maximum.
+.Pp
+Running out of space for swap metadata can leave
+the system in an unrecoverable state.
+Therefore, you should only change
this parameter if you need to greatly extend the
KVM reservation for other resources such as the
buffer cache or
diff -r a301a330526b -r 49889ad5ef1f head/sys/boot/fdt/dts/beaglebone.dts
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/boot/fdt/dts/beaglebone.dts Wed Aug 15 11:46:11 2012 +0300
@@ -0,0 +1,197 @@
+/*-
+ * Copyright (c) 2012 Damjan Marion <dmarion at 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: head/sys/boot/fdt/dts/beaglebone.dts 239281 2012-08-15 06:31:32Z gonzo $
+ */
+
+/dts-v1/;
+
+/ {
+ model = "beaglebone";
+ compatible = "beaglebone", "ti,am335x";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ interrupt-parent = <&AINTC>;
+
+ aliases {
+ soc = &SOC;
+ uart0 = &uart0;
+ };
+
+ memory {
+ device_type = "memory";
+ reg = < 0x80000000 0x10000000 >; /* 256MB RAM */
+ };
+
+ SOC: am335x {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges;
+ bus-frequency = <0>;
+
+ AINTC: interrupt-controller at 48200000 {
+ compatible = "ti,aintc";
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ reg = < 0x48200000 0x1000 >;
+ };
+
+ scm at 44e10000 {
+ compatible = "ti,scm";
+ reg = < 0x44e10000 0x2000 >;
+ /* Set of triplets < padname, muxname, padstate> */
+ scm-pad-config =
+ /* I2C0 */
+ "I2C0_SDA", "I2C0_SDA","i2c",
+ "I2C0_SCL", "I2C0_SCL","i2c",
+ /* Ethernet */
+ "MII1_RX_ER", "gmii1_rxerr", "input_pulldown",
+ "MII1_TX_EN", "gmii1_txen", "output",
+ "MII1_RX_DV", "gmii1_rxdv", "input_pulldown",
+ "MII1_TXD3", "gmii1_txd3", "output",
+ "MII1_TXD2", "gmii1_txd2", "output",
+ "MII1_TXD1", "gmii1_txd1", "output",
+ "MII1_TXD0", "gmii1_txd0", "output",
+ "MII1_TX_CLK", "gmii1_txclk", "input_pulldown",
+ "MII1_RX_CLK", "gmii1_rxclk", "input_pulldown",
+ "MII1_RXD3", "gmii1_rxd3", "input_pulldown",
+ "MII1_RXD2", "gmii1_rxd2", "input_pulldown",
+ "MII1_RXD1", "gmii1_rxd1", "input_pulldown",
+ "MII1_RXD0", "gmii1_rxd0", "input_pulldown",
+ "MDIO", "mdio_data", "input_pullup",
+ "MDC", "mdio_clk", "output_pullup",
+ /* MMCSD0 */
+ "MMC0_CMD", "mmc0_cmd", "input_pullup",
+ "MMC0_CLK", "mmc0_clk", "input_pullup",
+ "MMC0_DAT0", "mmc0_dat0", "input_pullup",
+ "MMC0_DAT1", "mmc0_dat1", "input_pullup",
+ "MMC0_DAT2", "mmc0_dat2", "input_pullup",
+ "MMC0_DAT3", "mmc0_dat3", "input_pullup";
+ };
+
+ prcm at 44E00000 {
+ compatible = "am335x,prcm";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = < 0x44E00000 0x1300 >;
+ };
+
+ dmtimers at 44E05000 {
+ compatible = "ti,am335x-dmtimer";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = < 0x44E05000 0x1000
+ 0x44E31000 0x1000
+ 0x48040000 0x1000
+ 0x48042000 0x1000
+ 0x48044000 0x1000
+ 0x48046000 0x1000
+ 0x48048000 0x1000
+ 0x4804A000 0x1000 >;
+ interrupts = < 66 67 68 69 92 93 94 95 >;
+ interrupt-parent = <&AINTC>;
+ };
+
+ GPIO: gpio {
+ #gpio-cells = <3>;
+ compatible = "ti,gpio";
+ gpio-controller;
+ reg =< 0x44E07000 0x1000
+ 0x4804C000 0x1000
+ 0x481AC000 0x1000
+ 0x481AE000 0x1000 >;
+ interrupts = < 17 19 21 23 >;
+ interrupt-parent = <&AINTC>;
+ };
+
+
+ uart0: serial at 44E09000 {
+ compatible = "ns16550";
+ reg = <0x44E09000 0x1000>;
+ reg-shift = <2>;
+ interrupts = < 72 >;
+ interrupt-parent = <&AINTC>;
+ clock-frequency = < 48000000 >; /* FIXME */
+ };
+
+ edma3 at 49000000 {
+ compatible = "ti,edma3";
+ reg =< 0x49000000 0x100000 /* Channel Controller Regs */
+ 0x49800000 0x100000 /* Transfer Controller 0 Regs */
+ 0x49900000 0x100000 /* Transfer Controller 1 Regs */
+ 0x49a00000 0x100000 >; /* Transfer Controller 2 Regs */
+ interrupts = <12 13 14>;
+ interrupt-parent = <&AINTC>;
+ };
+
+ mmchs0 at 4809C000 {
+ compatible = "ti,mmchs";
+ reg =<0x48060000 0x1000 >;
+ interrupts = <64>;
+ interrupt-parent = <&AINTC>;
+ mmchs-device-id = <0>;
+ };
+
+ enet0: ethernet at 4A100000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "ti,cpsw";
+ reg = <0x4A100000 0x3000>;
+ interrupts = <40 41 42 43>;
+ interrupt-parent = <&AINTC>;
+ phy-handle = <&phy0>;
+ mdio at 0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "ti,cpsw-mdio";
+ phy0: ethernet-phy at 0 {
+ reg = <0x0>;
+ };
+ };
+ };
+
+ i2c0: i2c at 44e0b000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "ti,i2c";
+ reg =< 0x44e0b000 0x1000 >;
+ interrupts = <70>;
+ interrupt-parent = <&AINTC>;
+ i2c-device-id = <0>;
+ pmic at 24 {
+ compatible = "ti,am335x-pmic";
+ reg = <0x24>;
+ };
+ };
+ };
+
+ chosen {
+ stdin = "uart0";
+ stdout = "uart0";
+ };
+};
diff -r a301a330526b -r 49889ad5ef1f head/sys/boot/fdt/dts/db88f78160.dts
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/boot/fdt/dts/db88f78160.dts Wed Aug 15 11:46:11 2012 +0300
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2010 The FreeBSD Foundation
+ * Copyright (c) 2010-2011 Semihalf
+ * 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.
+ *
+ * Marvell DB-88F78160 Device Tree Source.
+ *
+ * $FreeBSD: head/sys/boot/fdt/dts/db88f78160.dts 239277 2012-08-15 05:15:49Z gonzo $
+ */
+
+/dts-v1/;
+
+/ {
+ model = "mrvl,DB-78160";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ aliases {
+ serial0 = &serial0;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu at 0 {
+ device_type = "cpu";
+ compatible = "ARM,88VS584";
+ reg = <0x0>;
+ d-cache-line-size = <32>; // 32 bytes
+ i-cache-line-size = <32>; // 32 bytes
+ d-cache-size = <0x8000>; // L1, 32K
+ i-cache-size = <0x8000>; // L1, 32K
+ timebase-frequency = <0>;
+ bus-frequency = <200000000>;
+ clock-frequency = <0>;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x40000000>; // 2G at 0x0
+ };
+
+ soc78160 at d0000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges = <0x0 0xd0000000 0x00100000>;
+ bus-frequency = <0>;
+
+
+ MPIC: mpic at 20a00 {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ reg = <0x20a00 0x500 0x21000 0x800>;
+ compatible = "mrvl,mpic";
+ };
+
+ rtc at 10300 {
+ compatible = "mrvl,rtc";
+ reg = <0x10300 0x08>;
+ };
+
+ timer at 21840 {
+ compatible = "mrvl,timer";
+ reg = <0x21840 0x30>;
+ interrupts = <5>;
+ interrupt-parent = <&MPIC>;
+ mrvl,has-wdt;
+ };
+
+ twsi at 11000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "mrvl,twsi";
+ reg = <0x11000 0x20>;
+ interrupts = <31>;
+ interrupt-parent = <&MPIC>;
+ };
+
+ twsi at 11100 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "mrvl,twsi";
+ reg = <0x11100 0x20>;
+ interrupts = <32>;
+ interrupt-parent = <&MPIC>;
+ };
+
+ serial0: serial at 12000 {
+ compatible = "ns16550";
+ reg = <0x12000 0x20>;
+ reg-shift = <2>;
+ current-speed = <115200>;
+ clock-frequency = <200000000>;
+ interrupts = <41>;
+ interrupt-parent = <&MPIC>;
+ };
+
+ serial1: serial at 12100 {
+ compatible = "ns16550";
+ reg = <0x12100 0x20>;
+ reg-shift = <2>;
+ current-speed = <115200>;
+ clock-frequency = <200000000>;
+ interrupts = <42>;
+ interrupt-parent = <&MPIC>;
+ };
+
+ serial2: serial at 12200 {
+ compatible = "ns16550";
+ reg = <0x12200 0x20>;
+ reg-shift = <2>;
+ current-speed = <115200>;
+ clock-frequency = <200000000>;
+ interrupts = <43>;
+ interrupt-parent = <&MPIC>;
+ };
+
+ serial3: serial at 12300 {
+ compatible = "ns16550";
+ reg = <0x12300 0x20>;
+ reg-shift = <2>;
+ current-speed = <115200>;
+ clock-frequency = <200000000>;
+ interrupts = <44>;
+ interrupt-parent = <&MPIC>;
+ };
+
+ MPP: mpp at 10000 {
+ #pin-cells = <2>;
+ compatible = "mrvl,mpp";
+ reg = <0x18000 0x34>;
+ pin-count = <68>;
+ pin-map = <
+ 0 1 /* MPP[0]: GE1_TXCLK */
+ 1 1 /* MPP[1]: GE1_TXCTL */
+ 2 1 /* MPP[2]: GE1_RXCTL */
+ 3 1 /* MPP[3]: GE1_RXCLK */
+ 4 1 /* MPP[4]: GE1_TXD[0] */
+ 5 1 /* MPP[5]: GE1_TXD[1] */
+ 6 1 /* MPP[6]: GE1_TXD[2] */
+ 7 1 /* MPP[7]: GE1_TXD[3] */
+ 8 1 /* MPP[8]: GE1_RXD[0] */
+ 9 1 /* MPP[9]: GE1_RXD[1] */
+ 10 1 /* MPP[10]: GE1_RXD[2] */
+ 11 1 /* MPP[11]: GE1_RXD[3] */
+ 12 2 /* MPP[13]: SYSRST_OUTn */
+ 13 2 /* MPP[13]: SYSRST_OUTn */
+ 14 2 /* MPP[14]: SATA1_ACTn */
+ 15 2 /* MPP[15]: SATA0_ACTn */
+ 16 2 /* MPP[16]: UA2_TXD */
+ 17 2 /* MPP[17]: UA2_RXD */
+ 18 2 /* MPP[18]: <UNKNOWN> */
+ 19 2 /* MPP[19]: <UNKNOWN> */
+ 20 2 /* MPP[20]: <UNKNOWN> */
+ 21 2 /* MPP[21]: <UNKNOWN> */
+ 22 2 /* MPP[22]: UA3_TXD */
+ 23 2
+ 24 0
+ 25 0
+ 26 0
+ 27 0
+ 28 4
+ 29 0
+ 30 1
+ 31 1
+ 32 1
+ 33 1
+ 34 1
+ 35 1
+ 36 1
+ 37 1
+ 38 1
+ 39 1
+ 40 0
+ 41 3
+ 42 1
+ 43 1
+ 44 2
+ 45 2
+ 46 4
+ 47 3
+ 48 0
+ 49 1
+ 50 1
+ 51 1
+ 52 1
+ 53 1
+ 54 1
+ 55 1
+ 56 1
+ 57 0
+ 58 1
+ 59 1
+ 60 1
+ 61 1
+ 62 1
+ 63 1
+ 64 1
+ 65 1
+ 66 1
+ 67 2 >;
+ };
+
+ usb at 50000 {
+ compatible = "mrvl,usb-ehci", "usb-ehci";
+ reg = <0x50000 0x1000>;
+ interrupts = <124 45>;
+ interrupt-parent = <&MPIC>;
+ };
+
+ usb at 51000 {
+ compatible = "mrvl,usb-ehci", "usb-ehci";
+ reg = <0x51000 0x1000>;
+ interrupts = <124 46>;
+ interrupt-parent = <&MPIC>;
+ };
+
+ usb at 52000 {
+ compatible = "mrvl,usb-ehci", "usb-ehci";
+ reg = <0x52000 0x1000>;
+ interrupts = <124 47>;
+ interrupt-parent = <&MPIC>;
+ };
+
+ enet0: ethernet at 72000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ model = "V2";
+ compatible = "mrvl,ge";
+ reg = <0x72000 0x2000>;
+ ranges = <0x0 0x72000 0x2000>;
+ local-mac-address = [ 00 04 01 07 84 60 ];
+ interrupts = <67 68 122 >;
+ interrupt-parent = <&MPIC>;
+ phy-handle = <&phy0>;
+ has-neta;
+
+ mdio at 0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "mrvl,mdio";
+
+ phy0: ethernet-phy at 0 {
+ reg = <0x0>;
+ };
+ phy1: ethernet-phy at 1 {
+ reg = <0x1>;
+ };
+ phy2: ethernet-phy at 2 {
+ reg = <0x19>;
+ };
+ phy3: ethernet-phy at 3 {
+ reg = <0x1b>;
+ };
+ };
+ };
+ };
+
+ pci0: pcie at f1040000 {
+ compatible = "mrvl,pcie";
+ device_type = "pci";
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ reg = <0xf1040000 0x2000>;
+ bus-range = <0 255>;
+ ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x20000000
+ 0x01000000 0x0 0x00000000 0xa0000000 0x0 0x08000000>;
+ clock-frequency = <33333333>;
+ interrupt-parent = <&MPIC>;
+ interrupts = <58>;
+ interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
+ interrupt-map = <
+ 0x0800 0x0 0x0 0x1 &MPIC 0x20
+ 0x0800 0x0 0x0 0x2 &MPIC 0x21
+ 0x0800 0x0 0x0 0x3 &MPIC 0x22
+ 0x0800 0x0 0x0 0x4 &MPIC 0x23
+ >;
+ };
+
+ chosen {
+ stdin = "serial0";
+ stdout = "serial0";
+ stddbg = "serial0";
+ };
+};
diff -r a301a330526b -r 49889ad5ef1f head/sys/boot/fdt/dts/ea3250.dts
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/boot/fdt/dts/ea3250.dts Wed Aug 15 11:46:11 2012 +0300
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2011 Jakub Klama <jceel at FreeBSD.org>
+ *
+ * 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.
+ *
+ * Embedded Artists LPC3250-Kit Device Tree Source.
+ *
+ * $FreeBSD: head/sys/boot/fdt/dts/ea3250.dts 239278 2012-08-15 05:37:10Z gonzo $
+ */
+
+/dts-v1/;
+
+/ {
+ model = "ea,LPC3250-KIT";
+ compatible = "LPC3250-KIT";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ aliases {
+ soc = &soc;
+ serial4 = &serial4;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu at 0 {
+ device_type = "cpu";
+ compatible = "ARM,926EJ-S";
+ reg = <0x0>;
+ d-cache-line-size = <32>; // 32 bytes
+ i-cache-line-size = <32>; // 32 bytes
+ d-cache-size = <0x4000>; // L1, 16K
+ i-cache-size = <0x4000>; // L1, 16K
+ timebase-frequency = <0>;
+ bus-frequency = <0>;
+ clock-frequency = <0>;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x80000000 0x4000000>; // 64M at 0x80000000
+ };
+
+ soc: ahb7 at 40000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges = <0x0 0x40000000 0x10000000>;
+ bus-frequency = <13000000>;
+
+ pwr at 4000 {
+ compatible = "lpc,pwr";
+ reg = <0x4000 0x4000>;
+ };
+
+ PIC: pic at 8000 {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ reg = <0x8000 0xc000>;
+ compatible = "lpc,pic";
+ };
+
+ timer at 44000 {
+ compatible = "lpc,timer";
+ reg = <0x44000 0x4000
+ 0x4c000 0x4000>;
+ interrupts = <16 17>;
+ interrupt-parent = <&PIC>;
+ };
+
+ rtc at 24000 {
+ compatible = "lpc,rtc";
+ reg = <0x24000 0x4000>;
+ interrupts = <52>;
+ interrupt-parent = <&PIC>;
+ };
+
+ serial0: serial at 14000 {
+ compatible = "lpc,hsuart";
+ status = "disabled";
+ reg = <0x14000 0x20>;
+ reg-shift = <2>;
+ clock-frequency = <0>;
+ interrupts = <26>;
+ interrupt-parent = <&PIC>;
+ };
+
+ serial1: serial at 18000 {
+ compatible = "lpc,hsuart";
+ status = "disabled";
+ reg = <0x18000 0x20>;
+ reg-shift = <2>;
+ clock-frequency = <0>;
+ interrupts = <25>;
+ interrupt-parent = <&PIC>;
+ };
+
+ serial2: serial at 80000 {
+ compatible = "lpc,uart";
+ status = "disabled";
+ reg = <0x80000 0x20>;
+ reg-shift = <2>;
+ clock-frequency = <13000000>;
+ interrupts = <7>;
+ interrupt-parent = <&PIC>;
+ };
+
+ serial3: serial at 88000 {
+ compatible = "lpc,uart";
+ status = "disabled";
+ reg = <0x88000 0x20>;
+ reg-shift = <2>;
+ clock-frequency = <13000000>;
+ interrupts = <8>;
+ interrupt-parent = <&PIC>;
+ };
+
+ serial4: serial at 90000 {
+ compatible = "lpc,uart";
+ reg = <0x90000 0x20>;
+ reg-shift = <2>;
+ clock-frequency = <13000000>;
+ current-speed = <115200>;
+ interrupts = <9>;
+ interrupt-parent = <&PIC>;
+ };
+
+ serial5: serial at 98000 {
+ compatible = "lpc,uart";
+ status = "disabled";
+ reg = <0x98000 0x20>;
+ reg-shift = <2>;
+ clock-frequency = <13000000>;
+ interrupts = <10>;
+ interrupt-parent = <&PIC>;
+ };
+
+ serial6: serial at 1c000 {
+ compatible = "lpc,uart";
+ status = "disabled";
+ reg = <0x1c000 0x20>;
+ reg-shift = <2>;
+ clock-frequency = <0>;
+ interrupts = <24>;
+ interrupt-parent = <&PIC>;
+ };
+
+ gpio at 28000 {
+ compatible = "lpc,gpio";
+ reg = <0x28000 0x4000>;
+ };
+ };
+
+ ahb6 at 30000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges = <0x0 0x30000000 0x10000000>;
+
+ dmac at 1000000 {
+ compatible = "lpc,dmac";
+ reg = <0x1000000 0x20000>;
+ interrupts = <28>;
+ interrupt-parent = <&PIC>;
+ };
+
+ usb at 1020000 {
+ compatible = "lpc,usb-ohci", "usb-ohci";
+ reg = <0x1020000 0x20000>;
+ interrupts = <59>;
+ interrupt-parent = <&PIC>;
+ };
+
+ lpcfb at 1040000 {
+ compatible = "lpc,fb";
+ reg = <0x1040000 0x20000>;
+ interrupts = <14>;
+ interrupt-parent = <&PIC>;
+
+ /* Screen parameters: */
+ is-tft = <1>;
+ horizontal-resolution = <240>;
+ vertical-resolution = <320>;
+ bits-per-pixel = <16>;
+ pixel-clock = <121654>;
+ left-margin = <28>;
+ right-margin = <10>;
+ upper-margin = <2>;
+ lower-margin = <2>;
+ hsync-len = <3>;
+ vsync-len = <2>;
+ };
+
+ lpe at 1060000 {
+ compatible = "lpc,ethernet";
+ reg = <0x1060000 0x20000>;
+ interrupts = <29>;
+ interrupt-parent = <&PIC>;
+ local-mac-address = [ 00 1a f1 01 1f 23 ];
+
+ mdio at 0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "lpc,mdio";
+
+ phy0: ethernet-phy at 0 {
+ reg = <0x0>;
+ };
+ };
+
+ };
+ };
+
+ ahb5 at 20000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges = <0x0 0x20000000 0x10000000>;
+
+ spi0 at 84000 {
+ compatible = "lpc,spi";
+ reg = <0x84000 0x4000>;
+ interrupts = <20>;
+ interrupt-parent = <&PIC>;
+ };
+
+ spi1 at 8c000 {
+ compatible = "lpc,spi";
+ status = "disabled";
+ reg = <0x8c000 0x4000>;
+ interrupts = <21>;
+ interrupt-parent = <&PIC>;
+ };
+
+ lpcmmc at 98000 {
+ compatible = "lpc,mmc";
+ reg = <0x98000 0x4000>;
+ interrupts = <15 13>;
+ interrupt-parent = <&PIC>;
+ };
+ };
+
+ chosen {
+ stdin = "serial4";
+ stdout = "serial4";
+ };
+};
diff -r a301a330526b -r 49889ad5ef1f head/sys/boot/fdt/dts/pandaboard.dts
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/boot/fdt/dts/pandaboard.dts Wed Aug 15 11:46:11 2012 +0300
@@ -0,0 +1,184 @@
+/*-
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Developed by Damjan Marion <damjan.marion at gmail.com>
+ *
+ * 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: head/sys/boot/fdt/dts/pandaboard.dts 239281 2012-08-15 06:31:32Z gonzo $
+ */
+
+/dts-v1/;
+
+/ {
+ model = "pandaboard";
+ compatible = "pandaboard", "ti,omap4430";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ interrupt-parent = <&GIC>;
+
+ aliases {
+ soc = &SOC;
+ uart3 = &uart3;
+ };
+
+ memory {
+ device_type = "memory";
+ reg = < 0x80000000 0x40000000 >; /* 1GB RAM at 0x0 */
+ };
+
+ SOC: omap4430 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges;
+ bus-frequency = <0>;
+
+ GIC: interrupt-controller at 48241000 {
+ compatible = "arm,gic";
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ reg = < 0x48241000 0x1000 >, /* Distributor Registers */
+ < 0x48240100 0x0100 >; /* CPU Interface Registers */
+ };
+
+ pl310 at 48242000 {
+ compatible = "arm,pl310";
+ reg = < 0x48242000 0x1000 >;
+ };
+ mp_tmr at 48240200 {
+ compatible = "arm,mpcore-timers";
+ clock-frequency = < 504000000 >;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = < 0x48240200 0x100 >, /* Global Timer Registers */
+ < 0x48240600 0x100 >; /* Private Timer Registers */
+ interrupts = < 27 29 >;
+ interrupt-parent = < &GIC >;
+ };
+
+ uart3: serial at 48020000 {
+ compatible = "ns16550";
+ reg = <0x48020000 0x1000>;
+ reg-shift = <2>;
+ interrupts = < 106 >;
+ interrupt-parent = <&GIC>;
+ clock-frequency = < 48000000 >; /* 48Mhz clock for all uarts */
+ /* (techref 17.3.1.1) */
+ };
+
+ scm at 4a100000 {
+ compatible = "ti,scm";
+ reg = < 0x4a100000 0x1000 >;
+ /* Set of triplets < padname, muxname, padstate> */
+ scm-pad-config =
+ "ag19", "usbb1_ulpiphy_stp", "output",
+ "ae18", "usbb1_ulpiphy_clk", "input_pulldown",
+ "af19", "usbb1_ulpiphy_dir", "input_pulldown",
+ "ae19", "usbb1_ulpiphy_nxt", "input_pulldown",
+ "af18", "usbb1_ulpiphy_dat0", "input_pulldown",
+ "ag18", "usbb1_ulpiphy_dat1", "input_pulldown",
+ "ae17", "usbb1_ulpiphy_dat2", "input_pulldown",
+ "af17", "usbb1_ulpiphy_dat3", "input_pulldown",
+ "ah17", "usbb1_ulpiphy_dat4", "input_pulldown",
+ "ae16", "usbb1_ulpiphy_dat5", "input_pulldown",
+ "af16", "usbb1_ulpiphy_dat6", "input_pulldown",
+ "ag16", "usbb1_ulpiphy_dat7", "input_pulldown";
+ };
+
+ omap4_prcm at 4a306000 {
+ compatible = "ti,omap4_prcm";
+ reg =< 0x4a306000 0x2000
+ 0x4a004000 0x1000
+ 0x4a008000 0x8000>;
+ };
+
+ GPIO: gpio {
+ #gpio-cells = <3>;
+ compatible = "ti,gpio";
+ gpio-controller;
+ reg =< 0x4a310000 0x1000
+ 0x48055000 0x1000
+ 0x48057000 0x1000
+ 0x48059000 0x1000
+ 0x4805b000 0x1000
+ 0x4805d000 0x1000>;
+ interrupts = <61 62 63 64 65 66>;
+ interrupt-parent = <&GIC>;
+ };
+
+ ehci {
+ compatible = "ti,usb-ehci", "usb-ehci";
+ /*
+ * USB port PHY configuration is a tuple: <mode, reset, gpio_pin>
+ * mode is one of the following values:
+ * 0 - unknown
+ * 1 - PHY
+ * 2 - TLL
+ * 3 - HSIC
+ *
+ * reset indicates (if non-zero) if port reset is required
+ * gpio_pin - GPIO pin that is used to perform reset
+ */
+ phy-config = < 1 0 0
+ 0 0 0
+ 0 0 0>;
+ reg = < 0x4a064c00 0x100 /* EHCI regs */
+ 0x4a064000 0x700 /* UHH regs */
+ 0x4a062000 0x1000>; /* TLL regs */
+ interrupts = <109>;
+ interrupt-parent = <&GIC>;
+ };
+
+ I2C1: i2c at x48070000 {
+ compatible = "ti,i2c";
+ reg =< 0x48070000 0x100 >;
+ interrupts = <88>;
+ interrupt-parent = <&GIC>;
+ i2c-device-id = <1>;
+ };
+
+ sdma at x48070000 {
+ compatible = "ti,sdma";
+ reg =< 0x4A056000 0x1000 >;
+ interrupts = <44 45 46 47>;
+ interrupt-parent = <&GIC>;
+ };
+
+ mmc at x4809C000 {
+ compatible = "ti,mmchs";
+ reg =<0x4809C000 0x1000 >;
+ interrupts = <115>;
+ interrupt-parent = <&GIC>;
+ mmchs-device-id = <1>;
+ };
+
+ };
+
+ chosen {
+ stdin = "uart3";
+ stdout = "uart3";
+ };
+};
diff -r a301a330526b -r 49889ad5ef1f head/sys/boot/fdt/dts/trimslice.dts
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/boot/fdt/dts/trimslice.dts Wed Aug 15 11:46:11 2012 +0300
@@ -0,0 +1,143 @@
+/*-
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Developed by Damjan Marion <damjan.marion at gmail.com>
+ *
+ * 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: head/sys/boot/fdt/dts/trimslice.dts 239280 2012-08-15 06:06:43Z gonzo $
+ */
+
+/dts-v1/;
+
+/ {
+ model = "CompuLab TrimSlice";
+ compatible = "compulab,trimslice", "nvidia,tegra20";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ interrupt-parent = <&GIC>;
+
+ aliases {
+ serial0 = &serial0;
+ soc = &SOC;
+ };
+
+ memory {
+ device_type = "memory";
+ reg = < 0x00000000 0x40000000 >; /* 1GB RAM at 0x0 */
+ };
+
+
+ SOC: tegra20 at 0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges;
+ bus-frequency = <0>;
+
+ GIC: interrupt-controller at 50041000 {
+ compatible = "arm,gic";
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ reg = < 0x50041000 0x1000 >, /* Distributor Registers */
+ < 0x50040100 0x0100 >; /* CPU Interface Registers */
+ };
+ mp_tmr at 50040200 {
+ compatible = "arm,mpcore-timers";
+ clock-frequency = < 50040200 >;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = < 0x50040200 0x100 >, /* Global Timer Registers */
+ < 0x50040600 0x100 >; /* Private Timer Registers */
+ interrupts = < 27 29 >;
+ interrupt-parent = < &GIC >;
+ };
+
+ tmr1 at 60005000 {
+ compatible = "nvidia,tegra2-timer";
+ reg = <0x60005000 0x8>;
+ interrupts = < 32 >;
+ interrupt-parent = <&GIC>;
+ };
+
+ tmr2 at 60005008 {
+ compatible = "nvidia,tegra2-timer";
+ reg = <0x60005008 0x8>;
+ interrupts = < 33 >;
+ interrupt-parent = <&GIC>;
+ };
+
+ tmrus at 60005010 {
+ compatible = "nvidia,tegra2-timestamp";
+ reg = <0x60005010 0x8>;
+ };
+
+ tmr3 at 60005050 {
+ compatible = "nvidia,tegra2-timer";
+ reg = <0x60005050 0x8>;
+ interrupts = < 73 >;
+ interrupt-parent = <&GIC>;
+ };
+
+ tmr4 at 60005058 {
+ compatible = "nvidia,tegra2-timer";
+ reg = <0x60005058 0x8>;
+ interrupts = < 74 >;
+ interrupt-parent = <&GIC>;
+ };
+
+ serial0: serial at 70006000 {
+ compatible = "ns16550";
+ reg = <0x70006000 0x40>;
+ reg-shift = <2>;
+ interrupts = < 68 >;
+ interrupt-parent = <&GIC>;
+ clock-frequency = < 215654400 >;
+ };
+
+ serial1: serial at 70006040 {
+ compatible = "ns16550";
+ reg = <0x70006040 0x40>;
+ reg-shift = <2>;
+ interrupts = < 69 >;
+ interrupt-parent = <&GIC>;
+ clock-frequency = < 215654400 >;
+ };
+
+ serial2: serial at 70006200 {
+ compatible = "ns16550";
+ reg = <0x70006200 0x100>;
+ reg-shift = <2>;
+ interrupts = < 78 >;
+ interrupt-parent = <&GIC>;
+ clock-frequency = < 215654400 >;
+ };
+ };
+
+ chosen {
+ stdin = "serial0";
+ stdout = "serial0";
+ };
+};
diff -r a301a330526b -r 49889ad5ef1f head/sys/boot/i386/libi386/biosdisk.c
--- a/head/sys/boot/i386/libi386/biosdisk.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/boot/i386/libi386/biosdisk.c Wed Aug 15 11:46:11 2012 +0300
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/boot/i386/libi386/biosdisk.c 239066 2012-08-05 14:37:48Z ae $");
+__FBSDID("$FreeBSD: head/sys/boot/i386/libi386/biosdisk.c 239243 2012-08-13 21:04:01Z dim $");
/*
* BIOS disk device handling.
@@ -215,6 +215,8 @@
bd->bd_hds, bd->bd_sec);
/* Determine if we can use EDD with this device. */
+ v86.ctl = V86_FLAGS;
+ v86.addr = 0x13;
v86.eax = 0x4100;
v86.edx = bd->bd_unit;
v86.ebx = 0x55aa;
@@ -240,6 +242,8 @@
bd->bd_sectors = params.sectors;
bd->bd_sectorsize = params.sector_size;
}
+ DEBUG("unit 0x%x flags %x, sectors %llu, sectorsize %u",
+ bd->bd_unit, bd->bd_flags, bd->bd_sectors, bd->bd_sectorsize);
return (1);
}
diff -r a301a330526b -r 49889ad5ef1f head/sys/cam/scsi/scsi_all.h
--- a/head/sys/cam/scsi/scsi_all.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/cam/scsi/scsi_all.h Wed Aug 15 11:46:11 2012 +0300
@@ -14,7 +14,7 @@
*
* Ported to run under 386BSD by Julian Elischer (julian at tfs.com) Sept 1992
*
- * $FreeBSD: head/sys/cam/scsi/scsi_all.h 237478 2012-06-23 12:32:53Z mav $
+ * $FreeBSD: head/sys/cam/scsi/scsi_all.h 239212 2012-08-12 16:58:38Z mjacob $
*/
/*
@@ -984,6 +984,7 @@
#define WRITE_10 0x2A
#define POSITION_TO_ELEMENT 0x2B
#define WRITE_VERIFY_10 0x2E
+#define VERIFY_10 0x2F
#define SYNCHRONIZE_CACHE 0x35
#define READ_DEFECT_DATA_10 0x37
#define WRITE_BUFFER 0x3B
diff -r a301a330526b -r 49889ad5ef1f head/sys/cam/scsi/scsi_enc.c
--- a/head/sys/cam/scsi/scsi_enc.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/cam/scsi/scsi_enc.c Wed Aug 15 11:46:11 2012 +0300
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_enc.c 238894 2012-07-30 03:00:58Z bz $");
+__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_enc.c 239213 2012-08-12 17:01:07Z mjacob $");
#include <sys/param.h>
@@ -60,9 +60,6 @@
/* Enclosure type independent driver */
-#define SEN_ID "UNISYS SUN_SEN"
-#define SEN_ID_LEN 24
-
static d_open_t enc_open;
static d_close_t enc_close;
static d_ioctl_t enc_ioctl;
@@ -83,7 +80,7 @@
TAILQ_HEAD_INITIALIZER(encdriver.units), /* generation */ 0
};
-PERIPHDRIVER_DECLARE(enc, encdriver);
+PERIPHDRIVER_DECLARE(ses, encdriver);
static struct cdevsw enc_cdevsw = {
.d_version = D_VERSION,
@@ -630,9 +627,8 @@
/*
* Is this a device that supports enclosure services?
*
- * It's a a pretty simple ruleset- if it is device type 0x0D (13), it's
- * an ENC device. If it happens to be an old UNISYS SEN device, we can
- * handle that too.
+ * It's a a pretty simple ruleset- if it is device type
+ * 0x0D (13), it's an ENCLOSURE device.
*/
#define SAFTE_START 44
@@ -659,13 +655,9 @@
iqd = (unsigned char *)&cgd->inq_data;
buflen = min(sizeof(cgd->inq_data),
SID_ADDITIONAL_LENGTH(&cgd->inq_data));
- if (buflen < 8+SEN_ID_LEN)
- return (ENC_NONE);
if ((iqd[0] & 0x1f) == T_ENCLOSURE) {
- if (STRNCMP(&iqd[8], SEN_ID, SEN_ID_LEN) == 0) {
- return (ENC_SEN);
- } else if ((iqd[2] & 0x7) > 2) {
+ if ((iqd[2] & 0x7) > 2) {
return (ENC_SES);
} else {
return (ENC_SES_SCSI2);
@@ -920,7 +912,6 @@
case ENC_SEMB_SAFT:
err = safte_softc_init(enc);
break;
- case ENC_SEN:
case ENC_NONE:
default:
ENC_FREE(enc);
@@ -997,9 +988,6 @@
case ENC_SES_PASSTHROUGH:
tname = "ENC Passthrough Device";
break;
- case ENC_SEN:
- tname = "UNISYS SEN Device (NOT HANDLED YET)";
- break;
case ENC_SAFT:
tname = "SAF-TE Compliant Device";
break;
diff -r a301a330526b -r 49889ad5ef1f head/sys/cam/scsi/scsi_enc_safte.c
--- a/head/sys/cam/scsi/scsi_enc_safte.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/cam/scsi/scsi_enc_safte.c Wed Aug 15 11:46:11 2012 +0300
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_enc_safte.c 238894 2012-07-30 03:00:58Z bz $");
+__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_enc_safte.c 239213 2012-08-12 17:01:07Z mjacob $");
#include <sys/param.h>
@@ -220,7 +220,7 @@
static char *safte_2little = "Too Little Data Returned (%d) at line %d\n";
#define SAFT_BAIL(r, x) \
if ((r) >= (x)) { \
- ENC_LOG(enc, safte_2little, x, __LINE__);\
+ ENC_VLOG(enc, safte_2little, x, __LINE__);\
return (EIO); \
}
@@ -269,7 +269,7 @@
if (error != 0)
return (error);
if (xfer_len < 6) {
- ENC_LOG(enc, "too little data (%d) for configuration\n",
+ ENC_VLOG(enc, "too little data (%d) for configuration\n",
xfer_len);
return (EIO);
}
@@ -435,7 +435,7 @@
break;
default:
cache->elm_map[oid].encstat[0] = SES_OBJSTAT_UNSUPPORTED;
- ENC_LOG(enc, "Unknown fan%d status 0x%x\n", i,
+ ENC_VLOG(enc, "Unknown fan%d status 0x%x\n", i,
buf[r] & 0xff);
break;
}
@@ -495,7 +495,7 @@
cfg->enc_status |= SES_ENCSTAT_INFO;
break;
default:
- ENC_LOG(enc, "unknown power supply %d status (0x%x)\n",
+ ENC_VLOG(enc, "unknown power supply %d status (0x%x)\n",
i, buf[r] & 0xff);
break;
}
@@ -543,7 +543,7 @@
default:
cache->elm_map[oid].encstat[0] =
SES_OBJSTAT_UNSUPPORTED;
- ENC_LOG(enc, "unknown lock status 0x%x\n",
+ ENC_VLOG(enc, "unknown lock status 0x%x\n",
buf[r] & 0xff);
break;
}
diff -r a301a330526b -r 49889ad5ef1f head/sys/cam/scsi/scsi_enc_ses.c
--- a/head/sys/cam/scsi/scsi_enc_ses.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/cam/scsi/scsi_enc_ses.c Wed Aug 15 11:46:11 2012 +0300
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_enc_ses.c 238894 2012-07-30 03:00:58Z bz $");
+__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_enc_ses.c 239213 2012-08-12 17:01:07Z mjacob $");
#include <sys/param.h>
@@ -1175,7 +1175,7 @@
err = cam_periph_runccb(ccb, enc_error, ENC_CFLAGS,
ENC_FLAGS|SF_QUIET_IR, NULL);
if (ccb->ccb_h.status != CAM_REQ_CMP) {
- ENC_LOG(enc, "Timed Completion Unsupported\n");
+ ENC_VLOG(enc, "Timed Completion Unsupported\n");
goto release;
}
@@ -1198,7 +1198,7 @@
err = cam_periph_runccb(ccb, enc_error, ENC_CFLAGS, ENC_FLAGS, NULL);
if (ccb->ccb_h.status != CAM_REQ_CMP) {
- ENC_LOG(enc, "Timed Completion Set Failed\n");
+ ENC_VLOG(enc, "Timed Completion Set Failed\n");
goto release;
}
@@ -1244,14 +1244,14 @@
goto out;
}
if (xfer_len < sizeof(*page)) {
- ENC_LOG(enc, "Unable to parse Diag Pages List Header\n");
+ ENC_VLOG(enc, "Unable to parse Diag Pages List Header\n");
err = EIO;
goto out;
}
page = (struct scsi_diag_page *)*bufp;
length = scsi_2btoul(page->length);
if (length + offsetof(struct scsi_diag_page, params) > xfer_len) {
- ENC_LOG(enc, "Diag Pages List Too Long\n");
+ ENC_VLOG(enc, "Diag Pages List Too Long\n");
goto out;
}
ENC_DLOG(enc, "%s: page length %d, xfer_len %d\n",
@@ -1318,7 +1318,7 @@
goto out;
}
if (xfer_len < sizeof(cfg_page->hdr)) {
- ENC_LOG(enc, "Unable to parse SES Config Header\n");
+ ENC_VLOG(enc, "Unable to parse SES Config Header\n");
err = EIO;
goto out;
}
@@ -1326,7 +1326,7 @@
cfg_page = (struct ses_cfg_page *)buf;
length = ses_page_length(&cfg_page->hdr);
if (length > xfer_len) {
- ENC_LOG(enc, "Enclosure Config Page Too Long\n");
+ ENC_VLOG(enc, "Enclosure Config Page Too Long\n");
goto out;
}
last_valid_byte = &buf[length - 1];
@@ -1377,7 +1377,7 @@
while (cur_subenc <= last_subenc) {
if (!ses_enc_desc_is_complete(buf_subenc, last_valid_byte)) {
- ENC_LOG(enc, "Enclosure %d Beyond End of "
+ ENC_VLOG(enc, "Enclosure %d Beyond End of "
"Descriptors\n", cur_subenc - subencs);
err = EIO;
goto out;
@@ -1416,7 +1416,7 @@
sestype = ses_types;
while (cur_buf_type <= last_buf_type) {
if (&cur_buf_type->etype_txt_len > last_valid_byte) {
- ENC_LOG(enc, "Runt Enclosure Type Header %d\n",
+ ENC_VLOG(enc, "Runt Enclosure Type Header %d\n",
sestype - ses_types);
err = EIO;
goto out;
@@ -1424,7 +1424,7 @@
sestype->hdr = cur_buf_type;
sestype->text = type_text;
type_text += cur_buf_type->etype_txt_len;
- ENC_LOG(enc, " Type Desc[%d]: Type 0x%x, MaxElt %d, In Subenc "
+ ENC_VLOG(enc, " Type Desc[%d]: Type 0x%x, MaxElt %d, In Subenc "
"%d, Text Length %d: %.*s\n", sestype - ses_types,
sestype->hdr->etype_elm_type, sestype->hdr->etype_maxelt,
sestype->hdr->etype_subenc, sestype->hdr->etype_txt_len,
@@ -1529,12 +1529,12 @@
* could happen... Need to use dynamic discovery of the size.
*/
if (length > xfer_len) {
- ENC_LOG(enc, "Enclosure Status Page Too Long\n");
+ ENC_VLOG(enc, "Enclosure Status Page Too Long\n");
goto out;
}
/* Make sure the length contains at least one header and status */
if (length < (sizeof(*page) + sizeof(*page->elements))) {
- ENC_LOG(enc, "Enclosure Status Page Too Short\n");
+ ENC_VLOG(enc, "Enclosure Status Page Too Short\n");
goto out;
}
@@ -1576,11 +1576,11 @@
}
if (ses_iter_next(&iter) != NULL) {
- ENC_LOG(enc, "Status page, length insufficient for "
+ ENC_VLOG(enc, "Status page, length insufficient for "
"expected number of objects\n");
} else {
if (cur_stat <= last_stat)
- ENC_LOG(enc, "Status page, exhausted objects before "
+ ENC_VLOG(enc, "Status page, exhausted objects before "
"exhausing page\n");
enc_update_request(enc, SES_PUBLISH_CACHE);
err = 0;
@@ -1706,11 +1706,11 @@
ENC_DLOG(enc, "Additional Element Status Page Length 0x%x\n", length);
/* Make sure the length includes at least one header. */
if (length < sizeof(*hdr)+sizeof(struct ses_elm_addlstatus_base_hdr)) {
- ENC_LOG(enc, "Runt Additional Element Status Page\n");
+ ENC_VLOG(enc, "Runt Additional Element Status Page\n");
goto out;
}
if (length > xfer_len) {
- ENC_LOG(enc, "Additional Element Status Page Too Long\n");
+ ENC_VLOG(enc, "Additional Element Status Page Too Long\n");
goto out;
}
@@ -1763,7 +1763,7 @@
if (iter.individual_element_index > expected_index
&& status_type == TYPE_ADDLSTATUS_MANDATORY) {
- ENC_LOG(enc, "%s: provided element "
+ ENC_VLOG(enc, "%s: provided element "
"index %d skips mandatory status "
" element at index %d\n",
__func__, eip_hdr->element_index,
@@ -1784,7 +1784,7 @@
/* Make sure the descriptor is within bounds */
if ((offset + elmpriv->addl.hdr->length) > length) {
- ENC_LOG(enc, "Element %d Beyond End "
+ ENC_VLOG(enc, "Element %d Beyond End "
"of Additional Element Status Descriptors\n",
iter.global_element_index);
err = EIO;
@@ -1814,7 +1814,7 @@
iter.global_element_index);
break;
default:
- ENC_LOG(enc, "Element %d: Unknown Additional Element "
+ ENC_VLOG(enc, "Element %d: Unknown Additional Element "
"Protocol 0x%x\n", iter.global_element_index,
ses_elm_addlstatus_proto(elmpriv->addl.hdr));
goto out;
@@ -1931,11 +1931,11 @@
phdr = &ses_cache->elm_descs_page->hdr;
plength = ses_page_length(phdr);
if (xfer_len < sizeof(struct ses_page_hdr)) {
- ENC_LOG(enc, "Runt Element Descriptor Page\n");
+ ENC_VLOG(enc, "Runt Element Descriptor Page\n");
goto out;
}
if (plength > xfer_len) {
- ENC_LOG(enc, "Element Descriptor Page Too Long\n");
+ ENC_VLOG(enc, "Element Descriptor Page Too Long\n");
goto out;
}
@@ -1953,7 +1953,7 @@
&& (element = ses_iter_next(&iter)) != NULL) {
if ((offset + sizeof(struct ses_elm_desc_hdr)) > plength) {
- ENC_LOG(enc, "Element %d Descriptor Header Past "
+ ENC_VLOG(enc, "Element %d Descriptor Header Past "
"End of Buffer\n", iter.global_element_index);
goto out;
}
@@ -1963,7 +1963,7 @@
iter.global_element_index, iter.type_index,
iter.type_element_index, length, offset);
if ((offset + sizeof(*hdr) + length) > plength) {
- ENC_LOG(enc, "Element%d Descriptor Past "
+ ENC_VLOG(enc, "Element%d Descriptor Past "
"End of Buffer\n", iter.global_element_index);
goto out;
}
@@ -2138,7 +2138,7 @@
ses_get_elm_addlstatus_fc(enc_softc_t *enc, enc_cache_t *enc_cache,
uint8_t *buf, int bufsiz)
{
- ENC_LOG(enc, "FC Device Support Stubbed in Additional Status Page\n");
+ ENC_VLOG(enc, "FC Device Support Stubbed in Additional Status Page\n");
return (ENODEV);
}
@@ -2385,7 +2385,7 @@
physz = addl->proto_hdr.sas->base_hdr.num_phys;
physz *= sizeof(struct ses_elm_sas_device_phy);
if (physz > (bufsiz - offset + 4)) {
- ENC_LOG(enc, "Element %d Device Phy List Beyond End Of Buffer\n",
+ ENC_VLOG(enc, "Element %d Device Phy List Beyond End Of Buffer\n",
nobj);
err = EIO;
goto out;
@@ -2440,7 +2440,7 @@
physz = addl->proto_hdr.sas->base_hdr.num_phys *
sizeof(struct ses_elm_sas_expander_phy);
if (physz > (bufsiz - offset)) {
- ENC_LOG(enc, "Element %d: Expander Phy List Beyond "
+ ENC_VLOG(enc, "Element %d: Expander Phy List Beyond "
"End Of Buffer\n", nobj);
err = EIO;
goto out;
@@ -2452,7 +2452,7 @@
physz = addl->proto_hdr.sas->base_hdr.num_phys *
sizeof(struct ses_elm_sas_port_phy);
if (physz > (bufsiz - offset + 4)) {
- ENC_LOG(enc, "Element %d: Port Phy List Beyond End "
+ ENC_VLOG(enc, "Element %d: Port Phy List Beyond End "
"Of Buffer\n", nobj);
err = EIO;
goto out;
@@ -2504,7 +2504,7 @@
case ELMTYP_ARRAY_DEV:
break;
default:
- ENC_LOG(enc, "Element %d has Additional Status type 0, "
+ ENC_VLOG(enc, "Element %d has Additional Status type 0, "
"invalid for SES element type 0x%x\n", nobj,
ses_cache->ses_types[tidx].hdr->etype_elm_type);
err = ENODEV;
@@ -2522,7 +2522,7 @@
case ELMTYP_ESCC:
break;
default:
- ENC_LOG(enc, "Element %d has Additional Status type 1, "
+ ENC_VLOG(enc, "Element %d has Additional Status type 1, "
"invalid for SES element type 0x%x\n", nobj,
ses_cache->ses_types[tidx].hdr->etype_elm_type);
err = ENODEV;
@@ -2532,7 +2532,7 @@
bufsiz, eip, nobj);
break;
default:
- ENC_LOG(enc, "Element %d of type 0x%x has Additional Status "
+ ENC_VLOG(enc, "Element %d of type 0x%x has Additional Status "
"of unknown type 0x%x\n", nobj,
ses_cache->ses_types[tidx].hdr->etype_elm_type, dtype);
err = ENODEV;
diff -r a301a330526b -r 49889ad5ef1f head/sys/compat/freebsd32/freebsd32_proto.h
--- a/head/sys/compat/freebsd32/freebsd32_proto.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/compat/freebsd32/freebsd32_proto.h Wed Aug 15 11:46:11 2012 +0300
@@ -2,8 +2,8 @@
* System call prototypes.
*
* DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: head/sys/compat/freebsd32/freebsd32_proto.h 236027 2012-05-25 21:52:57Z ed $
- * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 236026 2012-05-25 21:50:48Z ed
+ * $FreeBSD: head/sys/compat/freebsd32/freebsd32_proto.h 239249 2012-08-14 12:09:36Z kib $
+ * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 239248 2012-08-14 12:09:09Z kib
*/
#ifndef _FREEBSD32_SYSPROTO_H_
diff -r a301a330526b -r 49889ad5ef1f head/sys/compat/freebsd32/freebsd32_syscall.h
--- a/head/sys/compat/freebsd32/freebsd32_syscall.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/compat/freebsd32/freebsd32_syscall.h Wed Aug 15 11:46:11 2012 +0300
@@ -2,8 +2,8 @@
* System call numbers.
*
* DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: head/sys/compat/freebsd32/freebsd32_syscall.h 236027 2012-05-25 21:52:57Z ed $
- * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 236026 2012-05-25 21:50:48Z ed
+ * $FreeBSD: head/sys/compat/freebsd32/freebsd32_syscall.h 239249 2012-08-14 12:09:36Z kib $
+ * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 239248 2012-08-14 12:09:09Z kib
*/
#define FREEBSD32_SYS_syscall 0
@@ -77,7 +77,7 @@
/* 68 is obsolete vwrite */
#define FREEBSD32_SYS_sbrk 69
#define FREEBSD32_SYS_sstk 70
- /* 71 is obsolete ommap */
+ /* 71 is old mmap */
#define FREEBSD32_SYS_vadvise 72
#define FREEBSD32_SYS_munmap 73
#define FREEBSD32_SYS_freebsd32_mprotect 74
diff -r a301a330526b -r 49889ad5ef1f head/sys/compat/freebsd32/freebsd32_syscalls.c
--- a/head/sys/compat/freebsd32/freebsd32_syscalls.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/compat/freebsd32/freebsd32_syscalls.c Wed Aug 15 11:46:11 2012 +0300
@@ -2,8 +2,8 @@
* System call names.
*
* DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: head/sys/compat/freebsd32/freebsd32_syscalls.c 236027 2012-05-25 21:52:57Z ed $
- * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 236026 2012-05-25 21:50:48Z ed
+ * $FreeBSD: head/sys/compat/freebsd32/freebsd32_syscalls.c 239249 2012-08-14 12:09:36Z kib $
+ * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 239248 2012-08-14 12:09:09Z kib
*/
const char *freebsd32_syscallnames[] = {
@@ -81,7 +81,7 @@
"obs_vwrite", /* 68 = obsolete vwrite */
"sbrk", /* 69 = sbrk */
"sstk", /* 70 = sstk */
- "obs_ommap", /* 71 = obsolete ommap */
+ "compat.mmap", /* 71 = old mmap */
"vadvise", /* 72 = vadvise */
"munmap", /* 73 = munmap */
"freebsd32_mprotect", /* 74 = freebsd32_mprotect */
diff -r a301a330526b -r 49889ad5ef1f head/sys/compat/freebsd32/freebsd32_sysent.c
--- a/head/sys/compat/freebsd32/freebsd32_sysent.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/compat/freebsd32/freebsd32_sysent.c Wed Aug 15 11:46:11 2012 +0300
@@ -2,8 +2,8 @@
* System call switch table.
*
* DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: head/sys/compat/freebsd32/freebsd32_sysent.c 236027 2012-05-25 21:52:57Z ed $
- * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 236026 2012-05-25 21:50:48Z ed
+ * $FreeBSD: head/sys/compat/freebsd32/freebsd32_sysent.c 239249 2012-08-14 12:09:36Z kib $
+ * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 239248 2012-08-14 12:09:09Z kib
*/
#include "opt_compat.h"
@@ -118,7 +118,7 @@
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 68 = obsolete vwrite */
{ AS(sbrk_args), (sy_call_t *)sys_sbrk, AUE_SBRK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 69 = sbrk */
{ AS(sstk_args), (sy_call_t *)sys_sstk, AUE_SSTK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 70 = sstk */
- { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 71 = obsolete ommap */
+ { compat(AS(ommap_args),mmap), AUE_MMAP, NULL, 0, 0, 0, SY_THR_STATIC }, /* 71 = old mmap */
{ AS(ovadvise_args), (sy_call_t *)sys_ovadvise, AUE_O_VADVISE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 72 = vadvise */
{ AS(munmap_args), (sy_call_t *)sys_munmap, AUE_MUNMAP, NULL, 0, 0, 0, SY_THR_STATIC }, /* 73 = munmap */
{ AS(freebsd32_mprotect_args), (sy_call_t *)freebsd32_mprotect, AUE_MPROTECT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 74 = freebsd32_mprotect */
diff -r a301a330526b -r 49889ad5ef1f head/sys/compat/freebsd32/syscalls.master
--- a/head/sys/compat/freebsd32/syscalls.master Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/compat/freebsd32/syscalls.master Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
- $FreeBSD: head/sys/compat/freebsd32/syscalls.master 236026 2012-05-25 21:50:48Z ed $
+ $FreeBSD: head/sys/compat/freebsd32/syscalls.master 239248 2012-08-14 12:09:09Z kib $
; from: @(#)syscalls.master 8.2 (Berkeley) 1/13/94
; from: src/sys/kern/syscalls.master 1.107
;
@@ -168,7 +168,8 @@
68 AUE_NULL OBSOL vwrite
69 AUE_SBRK NOPROTO { int sbrk(int incr); }
70 AUE_SSTK NOPROTO { int sstk(int incr); }
-71 AUE_MMAP OBSOL ommap
+71 AUE_MMAP COMPAT|NOPROTO { int mmap(void *addr, int len, \
+ int prot, int flags, int fd, int pos); }
72 AUE_O_VADVISE NOPROTO { int ovadvise(int anom); } vadvise \
ovadvise_args int
73 AUE_MUNMAP NOPROTO { int munmap(void *addr, size_t len); }
diff -r a301a330526b -r 49889ad5ef1f head/sys/conf/Makefile.arm
--- a/head/sys/conf/Makefile.arm Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/conf/Makefile.arm Wed Aug 15 11:46:11 2012 +0300
@@ -1,7 +1,7 @@
# Makefile.arm -- with config changes.
# Copyright 1990 W. Jolitz
# from: @(#)Makefile.i386 7.1 5/10/91
-# $FreeBSD: head/sys/conf/Makefile.arm 238464 2012-07-15 05:38:43Z imp $
+# $FreeBSD: head/sys/conf/Makefile.arm 239268 2012-08-15 03:03:03Z gonzo $
#
# Makefile for FreeBSD
#
@@ -75,7 +75,9 @@
$S/$M/$M/cpufunc_asm_sa1.S $S/$M/$M/cpufunc_asm_arm10.S \
$S/$M/$M/cpufunc_asm_xscale.S $S/$M/$M/cpufunc_asm.S \
$S/$M/$M/cpufunc_asm_xscale_c3.S $S/$M/$M/cpufunc_asm_armv5_ec.S \
- $S/$M/$M/cpufunc_asm_sheeva.S $S/$M/$M/cpufunc_asm_fa526.S
+ $S/$M/$M/cpufunc_asm_fa526.S $S/$M/$M/cpufunc_asm_sheeva.S \
+ $S/$M/$M/cpufunc_asm_pj4b.S $S/$M/$M/cpufunc_asm_armv7.S
+
KERNEL_EXTRA=trampoline
KERNEL_EXTRA_INSTALL=kernel.gz.tramp
trampoline: ${KERNEL_KO}.tramp
diff -r a301a330526b -r 49889ad5ef1f head/sys/conf/files
--- a/head/sys/conf/files Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/conf/files Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD: head/sys/conf/files 239009 2012-08-03 14:00:26Z luigi $
+# $FreeBSD: head/sys/conf/files 239275 2012-08-15 04:03:55Z gonzo $
#
# The long compile-with and dependency lines are required because of
# limitations in config: backslash-newline doesn't work in strings, and
@@ -1615,6 +1615,7 @@
dev/mii/rlphy.c optional miibus | rlphy
dev/mii/rlswitch.c optional rlswitch
dev/mii/smcphy.c optional miibus | smcphy
+dev/mii/smscphy.c optional miibus | smscphy
dev/mii/tdkphy.c optional miibus | tdkphy
dev/mii/tlphy.c optional miibus | tlphy
dev/mii/truephy.c optional miibus | truephy
@@ -2135,11 +2136,12 @@
dev/usb/net/if_kue.c optional kue
dev/usb/net/if_mos.c optional mos
dev/usb/net/if_rue.c optional rue
+dev/usb/net/if_smsc.c optional smsc
dev/usb/net/if_udav.c optional udav
dev/usb/net/if_usie.c optional usie
dev/usb/net/ruephy.c optional rue
dev/usb/net/usb_ethernet.c optional aue | axe | cdce | cue | kue | mos | \
- rue | udav
+ rue | smsc | udav
dev/usb/net/uhso.c optional uhso
#
# USB WLAN drivers
diff -r a301a330526b -r 49889ad5ef1f head/sys/conf/files.arm
--- a/head/sys/conf/files.arm Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/conf/files.arm Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD: head/sys/conf/files.arm 237433 2012-06-22 07:06:40Z kib $
+# $FreeBSD: head/sys/conf/files.arm 239268 2012-08-15 03:03:03Z gonzo $
crypto/blowfish/bf_enc.c optional crypto | ipsec
crypto/des/des_enc.c optional crypto | ipsec | netsmb
arm/arm/autoconf.c standard
@@ -7,7 +7,8 @@
arm/arm/blockio.S standard
arm/arm/bootconfig.c standard
arm/arm/bus_space_asm_generic.S standard
-arm/arm/busdma_machdep.c standard
+arm/arm/busdma_machdep.c optional cpu_arm9 | cpu_arm9e | cpu_fa526 | cpu_sa1100 | cpu_sa1110 | cpu_xscale_80219 | cpu_xscale_80321 | cpu_xscale_81342 | cpu_xscale_ixp425 | cpu_xscale_ixp435 | cpu_xscale_pxa2x0
+arm/arm/busdma_machdep-v6.c optional cpu_arm11 | cpu_cortexa | cpu_mv_pj4b
arm/arm/copystr.S standard
arm/arm/cpufunc.c standard
arm/arm/cpufunc_asm.S standard
@@ -31,8 +32,11 @@
arm/arm/machdep.c standard
arm/arm/mem.c optional mem
arm/arm/minidump_machdep.c optional mem
+arm/arm/mp_machdep.c optional smp
arm/arm/nexus.c standard
-arm/arm/pmap.c standard
+arm/arm/pl310.c optional pl310
+arm/arm/pmap.c optional cpu_arm9 | cpu_arm9e | cpu_fa526 | cpu_sa1100 | cpu_sa1110 | cpu_xscale_80219 | cpu_xscale_80321 | cpu_xscale_81342 | cpu_xscale_ixp425 | cpu_xscale_ixp435 | cpu_xscale_pxa2x0
+arm/arm/pmap-v6.c optional cpu_arm11 | cpu_cortexa | cpu_mv_pj4b
arm/arm/setcpsr.S standard
arm/arm/setstack.s standard
arm/arm/stack_machdep.c optional ddb | stack
@@ -44,6 +48,7 @@
arm/arm/undefined.c standard
arm/arm/vectors.S standard
arm/arm/vm_machdep.c standard
+arm/arm/vfp.c optional vfp
arm/fpe-arm/armfpe_glue.S optional armfpe
arm/fpe-arm/armfpe_init.c optional armfpe
arm/fpe-arm/armfpe.S optional armfpe
diff -r a301a330526b -r 49889ad5ef1f head/sys/conf/kern.pre.mk
--- a/head/sys/conf/kern.pre.mk Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/conf/kern.pre.mk Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD: head/sys/conf/kern.pre.mk 233644 2012-03-29 02:54:35Z jmallett $
+# $FreeBSD: head/sys/conf/kern.pre.mk 239272 2012-08-15 03:21:56Z gonzo $
# Part of a unified Makefile for building kernels. This part contains all
# of the definitions that need to be before %BEFORE_DEPEND.
@@ -6,7 +6,7 @@
.include <bsd.own.mk>
# backwards compat option for older systems.
-MACHINE_CPUARCH?=${MACHINE_ARCH:C/mips(n32|64)?(el)?/mips/:C/armeb/arm/:C/powerpc64/powerpc/}
+MACHINE_CPUARCH?=${MACHINE_ARCH:C/mips(n32|64)?(el)?/mips/:C/arm(v6)?(eb)?/arm/:C/powerpc64/powerpc/}
# Can be overridden by makeoptions or /etc/make.conf
KERNEL_KO?= kernel
diff -r a301a330526b -r 49889ad5ef1f head/sys/conf/kmod.mk
--- a/head/sys/conf/kmod.mk Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/conf/kmod.mk Wed Aug 15 11:46:11 2012 +0300
@@ -1,5 +1,5 @@
# From: @(#)bsd.prog.mk 5.26 (Berkeley) 6/25/91
-# $FreeBSD: head/sys/conf/kmod.mk 238050 2012-07-03 05:01:00Z obrien $
+# $FreeBSD: head/sys/conf/kmod.mk 239272 2012-08-15 03:21:56Z gonzo $
#
# The include file <bsd.kmod.mk> handles building and installing loadable
# kernel modules.
@@ -61,7 +61,7 @@
#
# backwards compat option for older systems.
-MACHINE_CPUARCH?=${MACHINE_ARCH:C/mips(n32|64)?(el)?/mips/:C/armeb/arm/:C/powerpc64/powerpc/}
+MACHINE_CPUARCH?=${MACHINE_ARCH:C/mips(n32|64)?(el)?/mips/:C/arm(v6)?(eb)?/arm/:C/powerpc64/powerpc/}
AWK?= awk
KMODLOAD?= /sbin/kldload
diff -r a301a330526b -r 49889ad5ef1f head/sys/conf/options.arm
--- a/head/sys/conf/options.arm Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/conf/options.arm Wed Aug 15 11:46:11 2012 +0300
@@ -1,15 +1,23 @@
-#$FreeBSD: head/sys/conf/options.arm 238189 2012-07-07 05:02:39Z imp $
+#$FreeBSD: head/sys/conf/options.arm 239268 2012-08-15 03:03:03Z gonzo $
ARM9_CACHE_WRITE_THROUGH opt_global.h
ARM_CACHE_LOCK_ENABLE opt_global.h
ARMFPE opt_global.h
ARM_KERN_DIRECTMAP opt_vm.h
+ARM_L2_PIPT opt_global.h
ARM_MANY_BOARD opt_global.h
ARM_USE_SMALL_ALLOC opt_global.h
+ARM_VFP_SUPPORT opt_global.h
+ARM_WANT_TP_ADDRESS opt_global.h
COUNTS_PER_SEC opt_timer.h
+CPU_ARM9 opt_global.h
+CPU_ARM9E opt_global.h
+CPU_ARM11 opt_global.h
+CPU_CORTEXA opt_global.h
+CPU_FA526 opt_global.h
+CPU_FA626TE opt_global.h
+CPU_MV_PJ4B opt_global.h
CPU_SA1100 opt_global.h
CPU_SA1110 opt_global.h
-CPU_ARM9 opt_global.h
-CPU_ARM9E opt_global.h
CPU_XSCALE_80219 opt_global.h
CPU_XSCALE_80321 opt_global.h
CPU_XSCALE_81342 opt_global.h
@@ -17,24 +25,34 @@
CPU_XSCALE_IXP435 opt_global.h
CPU_XSCALE_PXA2X0 opt_global.h
FLASHADDR opt_global.h
+IPI_IRQ_START opt_smp.h
+IPI_IRQ_END opt_smp.h
FREEBSD_BOOT_LOADER opt_global.h
IXP4XX_FLASH_SIZE opt_global.h
KERNPHYSADDR opt_global.h
KERNVIRTADDR opt_global.h
LINUX_BOOT_ABI opt_global.h
LOADERRAMADDR opt_global.h
+NO_EVENTTIMERS opt_timer.h
PHYSADDR opt_global.h
QEMU_WORKAROUNDS opt_global.h
+SOC_MV_ARMADAXP opt_global.h
SOC_MV_DISCOVERY opt_global.h
+SOC_MV_DOVE opt_global.h
+SOC_MV_FREY opt_global.h
SOC_MV_KIRKWOOD opt_global.h
+SOC_MV_LOKIPLUS opt_global.h
SOC_MV_ORION opt_global.h
+SOC_OMAP3 opt_global.h
+SOC_OMAP4 opt_global.h
+SOC_TI_AM335X opt_global.h
+SOC_TEGRA2 opt_global.h
STARTUP_PAGETABLE_ADDR opt_global.h
XSCALE_CACHE_READ_WRITE_ALLOCATE opt_global.h
XSACLE_DISABLE_CCNT opt_timer.h
VERBOSE_INIT_ARM opt_global.h
+VM_MAXUSER_ADDRESS opt_global.h
AT91_ATE_USE_RMII opt_at91.h
AT91_MCI_HAS_4WIRE opt_at91.h
AT91_MCI_SLOT_B opt_at91.h
AT91C_MAIN_CLOCK opt_at91.h
-CPU_FA526 opt_global.h
-CPU_FA626TE opt_global.h
diff -r a301a330526b -r 49889ad5ef1f head/sys/conf/options.mips
--- a/head/sys/conf/options.mips Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/conf/options.mips Wed Aug 15 11:46:11 2012 +0300
@@ -26,7 +26,7 @@
# SUCH DAMAGE.
#
# JNPR: options.mips,v 1.2 2006/09/15 12:52:34
-# $FreeBSD: head/sys/conf/options.mips 234862 2012-05-01 06:18:30Z adrian $
+# $FreeBSD: head/sys/conf/options.mips 239236 2012-08-13 17:38:38Z alc $
CPU_MIPS4KC opt_global.h
CPU_MIPS32 opt_global.h
@@ -77,3 +77,7 @@
IF_RT_PHY_SUPPORT opt_if_rt.h
IF_RT_RING_DATA_COUNT opt_if_rt.h
+#
+# Options that affect the pmap.
+#
+PV_STATS opt_pmap.h
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/ath/if_ath_tx.c
--- a/head/sys/dev/ath/if_ath_tx.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/ath/if_ath_tx.c Wed Aug 15 11:46:11 2012 +0300
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_tx.c 239205 2012-08-12 00:46:15Z adrian $");
+__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_tx.c 239290 2012-08-15 08:14:16Z adrian $");
/*
* Driver for the Atheros Wireless LAN controller.
@@ -302,9 +302,10 @@
{
struct ath_hal *ah = sc->sc_ah;
struct ath_desc *ds, *ds0;
- int i;
+ int i, bp, dsp;
HAL_DMA_ADDR bufAddrList[4];
uint32_t segLenList[4];
+ int numTxMaps = 1;
/*
* XXX There's txdma and txdma_mgmt; the descriptor
@@ -315,20 +316,47 @@
/*
* Fillin the remainder of the descriptor info.
*/
+
+ /*
+ * For now the HAL doesn't implement halNumTxMaps for non-EDMA
+ * (ie it's 0.) So just work around it.
+ *
+ * XXX TODO: populate halNumTxMaps for each HAL chip and
+ * then undo this hack.
+ */
+ if (sc->sc_ah->ah_magic == 0x19741014)
+ numTxMaps = 4;
+
+ /*
+ * For EDMA and later chips ensure the TX map is fully populated
+ * before advancing to the next descriptor.
+ */
ds0 = ds = bf->bf_desc;
- for (i = 0; i < bf->bf_nseg; i++, ds++) {
- bufAddrList[0] = bf->bf_segs[i].ds_addr;
- segLenList[0] = bf->bf_segs[i].ds_len;
-
- /* Blank this out until multi-buf support is added for AR9300 */
- bufAddrList[1] = bufAddrList[2] = bufAddrList[3] = 0;
- segLenList[1] = segLenList[2] = segLenList[3] = 0;
+ bp = dsp = 0;
+ bzero(bufAddrList, sizeof(bufAddrList));
+ bzero(segLenList, sizeof(segLenList));
+ for (i = 0; i < bf->bf_nseg; i++) {
+ bufAddrList[bp] = bf->bf_segs[i].ds_addr;
+ segLenList[bp] = bf->bf_segs[i].ds_len;
+ bp++;
+
+ /*
+ * Go to the next segment if this isn't the last segment
+ * and there's space in the current TX map.
+ */
+ if ((i != bf->bf_nseg - 1) && (bp < numTxMaps))
+ continue;
+
+ /*
+ * Last segment or we're out of buffer pointers.
+ */
+ bp = 0;
if (i == bf->bf_nseg - 1)
ath_hal_settxdesclink(ah, ds, 0);
else
ath_hal_settxdesclink(ah, ds,
- bf->bf_daddr + dd->dd_descsize * (i + 1));
+ bf->bf_daddr + dd->dd_descsize * (dsp + 1));
/*
* XXX this assumes that bfs_txq is the actual destination
@@ -339,7 +367,7 @@
ath_hal_filltxdesc(ah, ds
, bufAddrList
, segLenList
- , 0 /* XXX desc id */
+ , bf->bf_descid /* XXX desc id */
, bf->bf_state.bfs_txq->axq_qnum /* XXX multicast? */
, i == 0 /* first segment */
, i == bf->bf_nseg - 1 /* last segment */
@@ -350,6 +378,18 @@
__func__, i, ds->ds_link, ds->ds_data,
ds->ds_ctl0, ds->ds_ctl1, ds->ds_hw[0], ds->ds_hw[1]);
bf->bf_lastds = ds;
+
+ /*
+ * Don't forget to skip to the next descriptor.
+ */
+ ds++;
+ dsp++;
+
+ /*
+ * .. and don't forget to blank these out!
+ */
+ bzero(bufAddrList, sizeof(bufAddrList));
+ bzero(segLenList, sizeof(segLenList));
}
bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, BUS_DMASYNC_PREWRITE);
}
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/cxgbe/t4_main.c
--- a/head/sys/dev/cxgbe/t4_main.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/cxgbe/t4_main.c Wed Aug 15 11:46:11 2012 +0300
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/cxgbe/t4_main.c 238054 2012-07-03 06:56:11Z np $");
+__FBSDID("$FreeBSD: head/sys/dev/cxgbe/t4_main.c 239259 2012-08-14 22:15:12Z np $");
#include "opt_inet.h"
#include "opt_inet6.h"
@@ -517,7 +517,9 @@
sc->params.b_wnd);
t4_write_reg(sc, A_ULP_RX_TDDP_PSZ, V_HPZ0(PAGE_SHIFT - 12));
t4_set_reg_field(sc, A_TP_PARA_REG3, F_TUNNELCNGDROP0 |
- F_TUNNELCNGDROP1 | F_TUNNELCNGDROP2 | F_TUNNELCNGDROP3, 0);
+ F_TUNNELCNGDROP1 | F_TUNNELCNGDROP2 | F_TUNNELCNGDROP3,
+ F_TUNNELCNGDROP0 | F_TUNNELCNGDROP1 | F_TUNNELCNGDROP2 |
+ F_TUNNELCNGDROP3);
t4_set_reg_field(sc, A_TP_PARA_REG5,
V_INDICATESIZE(M_INDICATESIZE) |
F_REARMDDPOFFSET | F_RESETDDPOFFSET,
@@ -2942,7 +2944,8 @@
ifp->if_omcasts = s->tx_mcast_frames - s->tx_pause;
ifp->if_imcasts = s->rx_mcast_frames - s->rx_pause;
ifp->if_iqdrops = s->rx_ovflow0 + s->rx_ovflow1 + s->rx_ovflow2 +
- s->rx_ovflow3;
+ s->rx_ovflow3 + s->rx_trunc0 + s->rx_trunc1 + s->rx_trunc2 +
+ s->rx_trunc3;
drops = s->tx_drop;
for_each_txq(pi, i, txq)
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/cxgbe/t4_sge.c
--- a/head/sys/dev/cxgbe/t4_sge.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/cxgbe/t4_sge.c Wed Aug 15 11:46:11 2012 +0300
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/cxgbe/t4_sge.c 238313 2012-07-09 21:53:50Z np $");
+__FBSDID("$FreeBSD: head/sys/dev/cxgbe/t4_sge.c 239266 2012-08-15 01:03:13Z np $");
#include "opt_inet.h"
#include "opt_inet6.h"
@@ -68,12 +68,37 @@
#define FL_BUF_TYPE(x) (fl_buf_info[x].type)
#define FL_BUF_ZONE(x) (fl_buf_info[x].zone)
-enum {
- FL_PKTSHIFT = 2
-};
-
-static int fl_pad = CACHE_LINE_SIZE;
-static int spg_len = 64;
+/*
+ * Ethernet frames are DMA'd at this byte offset into the freelist buffer.
+ * 0-7 are valid values.
+ */
+static int fl_pktshift = 2;
+TUNABLE_INT("hw.cxgbe.fl_pktshift", &fl_pktshift);
+
+/*
+ * Pad ethernet payload up to this boundary.
+ * -1: driver should figure out a good value.
+ * Any power of 2, from 32 to 4096 (both inclusive) is a valid value.
+ */
+static int fl_pad = -1;
+TUNABLE_INT("hw.cxgbe.fl_pad", &fl_pad);
+
+/*
+ * Status page length.
+ * -1: driver should figure out a good value.
+ * 64 or 128 are the only other valid values.
+ */
+static int spg_len = -1;
+TUNABLE_INT("hw.cxgbe.spg_len", &spg_len);
+
+/*
+ * Congestion drops.
+ * -1: no congestion feedback (not recommended).
+ * 0: backpressure the channel instead of dropping packets right away.
+ * 1: no backpressure, drop packets for the congested queue immediately.
+ */
+static int cong_drop = 0;
+TUNABLE_INT("hw.cxgbe.cong_drop", &cong_drop);
/* Used to track coalesced tx work request */
struct txpkts {
@@ -170,7 +195,8 @@
#endif
/*
- * Called on MOD_LOAD and fills up fl_buf_info[].
+ * Called on MOD_LOAD. Fills up fl_buf_info[] and validates/calculates the SGE
+ * tunables.
*/
void
t4_sge_modload(void)
@@ -191,10 +217,49 @@
FL_BUF_ZONE(i) = m_getzone(bufsize[i]);
}
+ if (fl_pktshift < 0 || fl_pktshift > 7) {
+ printf("Invalid hw.cxgbe.fl_pktshift value (%d),"
+ " using 2 instead.\n", fl_pktshift);
+ fl_pktshift = 2;
+ }
+
+ if (fl_pad < 32 || fl_pad > 4096 || !powerof2(fl_pad)) {
+ int pad;
+
#if defined(__i386__) || defined(__amd64__)
- fl_pad = max(cpu_clflush_line_size, 32);
- spg_len = cpu_clflush_line_size > 64 ? 128 : 64;
+ pad = max(cpu_clflush_line_size, 32);
+#else
+ pad = max(CACHE_LINE_SIZE, 32);
#endif
+ pad = min(pad, 4096);
+
+ if (fl_pad != -1) {
+ printf("Invalid hw.cxgbe.fl_pad value (%d),"
+ " using %d instead.\n", fl_pad, pad);
+ }
+ fl_pad = pad;
+ }
+
+ if (spg_len != 64 && spg_len != 128) {
+ int len;
+
+#if defined(__i386__) || defined(__amd64__)
+ len = cpu_clflush_line_size > 64 ? 128 : 64;
+#else
+ len = 64;
+#endif
+ if (spg_len != -1) {
+ printf("Invalid hw.cxgbe.spg_len value (%d),"
+ " using %d instead.\n", spg_len, len);
+ }
+ spg_len = len;
+ }
+
+ if (cong_drop < -1 || cong_drop > 1) {
+ printf("Invalid hw.cxgbe.cong_drop value (%d),"
+ " using 0 instead.\n", cong_drop);
+ cong_drop = 0;
+ }
}
/**
@@ -215,7 +280,7 @@
ctrl_mask = V_PKTSHIFT(M_PKTSHIFT) | F_RXPKTCPLMODE |
V_INGPADBOUNDARY(M_INGPADBOUNDARY) |
F_EGRSTATUSPAGESIZE;
- ctrl_val = V_PKTSHIFT(FL_PKTSHIFT) | F_RXPKTCPLMODE |
+ ctrl_val = V_PKTSHIFT(fl_pktshift) | F_RXPKTCPLMODE |
V_INGPADBOUNDARY(ilog2(fl_pad) - 5) |
V_EGRSTATUSPAGESIZE(spg_len == 128);
@@ -477,6 +542,18 @@
return (iq);
}
+static inline int
+mtu_to_bufsize(int mtu)
+{
+ int bufsize;
+
+ /* large enough for a frame even when VLAN extraction is disabled */
+ bufsize = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN + mtu;
+ bufsize = roundup(bufsize + fl_pktshift, fl_pad);
+
+ return (bufsize);
+}
+
int
t4_setup_port_queues(struct port_info *pi)
{
@@ -493,6 +570,7 @@
struct adapter *sc = pi->adapter;
struct sysctl_oid *oid = device_get_sysctl_tree(pi->dev);
struct sysctl_oid_list *children = SYSCTL_CHILDREN(oid);
+ int bufsize = mtu_to_bufsize(pi->ifp->if_mtu);
oid = SYSCTL_ADD_NODE(&pi->ctx, children, OID_AUTO, "rxq", CTLFLAG_RD,
NULL, "rx queues");
@@ -522,7 +600,7 @@
snprintf(name, sizeof(name), "%s rxq%d-fl",
device_get_nameunit(pi->dev), i);
- init_fl(&rxq->fl, pi->qsize_rxq / 8, pi->ifp->if_mtu, name);
+ init_fl(&rxq->fl, pi->qsize_rxq / 8, bufsize, name);
if (sc->flags & INTR_DIRECT
#ifdef TCP_OFFLOAD
@@ -1050,9 +1128,9 @@
KASSERT(m0 != NULL, ("%s: no payload with opcode %02x", __func__,
rss->opcode));
- m0->m_pkthdr.len -= FL_PKTSHIFT;
- m0->m_len -= FL_PKTSHIFT;
- m0->m_data += FL_PKTSHIFT;
+ m0->m_pkthdr.len -= fl_pktshift;
+ m0->m_len -= fl_pktshift;
+ m0->m_data += fl_pktshift;
m0->m_pkthdr.rcvif = ifp;
m0->m_flags |= M_FLOWID;
@@ -1386,11 +1464,8 @@
struct port_info *pi = ifp->if_softc;
struct sge_rxq *rxq;
struct sge_fl *fl;
- int i, bufsize;
-
- /* large enough for a frame even when VLAN extraction is disabled */
- bufsize = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN + ifp->if_mtu;
- bufsize = roundup(bufsize + FL_PKTSHIFT, fl_pad);
+ int i, bufsize = mtu_to_bufsize(ifp->if_mtu);
+
for_each_rxq(pi, i, rxq) {
fl = &rxq->fl;
@@ -1793,6 +1868,18 @@
return free_wrq(sc, &sc->sge.mgmtq);
}
+static inline int
+tnl_cong(struct port_info *pi)
+{
+
+ if (cong_drop == -1)
+ return (-1);
+ else if (cong_drop == 1)
+ return (0);
+ else
+ return (1 << pi->tx_chan);
+}
+
static int
alloc_rxq(struct port_info *pi, struct sge_rxq *rxq, int intr_idx, int idx,
struct sysctl_oid *oid)
@@ -1801,7 +1888,7 @@
struct sysctl_oid_list *children;
char name[16];
- rc = alloc_iq_fl(pi, &rxq->iq, &rxq->fl, intr_idx, 1 << pi->tx_chan);
+ rc = alloc_iq_fl(pi, &rxq->iq, &rxq->fl, intr_idx, tnl_cong(pi));
if (rc != 0)
return (rc);
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/fdt/fdt_common.c
--- a/head/sys/dev/fdt/fdt_common.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/fdt/fdt_common.c Wed Aug 15 11:46:11 2012 +0300
@@ -28,13 +28,14 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/fdt/fdt_common.c 232518 2012-03-04 19:22:52Z raj $");
+__FBSDID("$FreeBSD: head/sys/dev/fdt/fdt_common.c 239274 2012-08-15 03:49:10Z gonzo $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/bus.h>
+#include <sys/limits.h>
#include <machine/fdt.h>
#include <machine/resource.h>
@@ -63,30 +64,12 @@
vm_offset_t fdt_immr_size;
int
-fdt_immr_addr(vm_offset_t immr_va)
+fdt_get_range(phandle_t node, int range_id, u_long *base, u_long *size)
{
pcell_t ranges[6], *rangesptr;
- phandle_t node;
- u_long base, size;
pcell_t addr_cells, size_cells, par_addr_cells;
int len, tuple_size, tuples;
- /*
- * Try to access the SOC node directly i.e. through /aliases/.
- */
- if ((node = OF_finddevice("soc")) != -1)
- if (fdt_is_compatible_strict(node, "simple-bus"))
- goto moveon;
- /*
- * Find the node the long way.
- */
- if ((node = OF_finddevice("/")) == -1)
- return (ENXIO);
-
- if ((node = fdt_find_compatible(node, "simple-bus", 1)) == 0)
- return (ENXIO);
-
-moveon:
if ((fdt_addrsize_cells(node, &addr_cells, &size_cells)) != 0)
return (ENXIO);
/*
@@ -99,6 +82,14 @@
len = OF_getproplen(node, "ranges");
if (len > sizeof(ranges))
return (ENOMEM);
+ if (len == 0) {
+ *base = 0;
+ *size = ULONG_MAX;
+ return (0);
+ }
+
+ if (!(range_id < len))
+ return (ERANGE);
if (OF_getprop(node, "ranges", ranges, sizeof(ranges)) <= 0)
return (EINVAL);
@@ -111,21 +102,48 @@
addr_cells, size_cells)) {
return (ERANGE);
}
- base = 0;
- size = 0;
- rangesptr = &ranges[0];
+ *base = 0;
+ *size = 0;
+ rangesptr = &ranges[range_id];
- base = fdt_data_get((void *)rangesptr, addr_cells);
+ *base = fdt_data_get((void *)rangesptr, addr_cells);
rangesptr += addr_cells;
- base += fdt_data_get((void *)rangesptr, par_addr_cells);
+ *base += fdt_data_get((void *)rangesptr, par_addr_cells);
rangesptr += par_addr_cells;
- size = fdt_data_get((void *)rangesptr, size_cells);
+ *size = fdt_data_get((void *)rangesptr, size_cells);
+ return (0);
+}
- fdt_immr_pa = base;
- fdt_immr_va = immr_va;
- fdt_immr_size = size;
+int
+fdt_immr_addr(vm_offset_t immr_va)
+{
+ phandle_t node;
+ u_long base, size;
+ int r;
- return (0);
+ /*
+ * Try to access the SOC node directly i.e. through /aliases/.
+ */
+ if ((node = OF_finddevice("soc")) != 0)
+ if (fdt_is_compatible_strict(node, "simple-bus"))
+ goto moveon;
+ /*
+ * Find the node the long way.
+ */
+ if ((node = OF_finddevice("/")) == 0)
+ return (ENXIO);
+
+ if ((node = fdt_find_compatible(node, "simple-bus", 1)) == 0)
+ return (ENXIO);
+
+moveon:
+ if ((r = fdt_get_range(node, 0, &base, &size)) == 0) {
+ fdt_immr_pa = base;
+ fdt_immr_va = immr_va;
+ fdt_immr_size = size;
+ }
+
+ return (r);
}
/*
@@ -401,16 +419,19 @@
}
int
-fdt_reg_to_rl(phandle_t node, struct resource_list *rl, u_long base)
+fdt_reg_to_rl(phandle_t node, struct resource_list *rl)
{
u_long start, end, count;
pcell_t *reg, *regptr;
pcell_t addr_cells, size_cells;
int tuple_size, tuples;
int i, rv;
+ long vaddr;
+ long busaddr, bussize;
if (fdt_addrsize_cells(OF_parent(node), &addr_cells, &size_cells) != 0)
return (ENXIO);
+ fdt_get_range(OF_parent(node), 0, &busaddr, &bussize);
tuple_size = sizeof(pcell_t) * (addr_cells + size_cells);
tuples = OF_getprop_alloc(node, "reg", tuple_size, (void **)®);
@@ -432,14 +453,15 @@
reg += addr_cells + size_cells;
/* Calculate address range relative to base. */
- start &= 0x000ffffful;
- start = base + start;
- end = start + count - 1;
+ start += busaddr;
+ if (bus_space_map(fdtbus_bs_tag, start, count, 0, &vaddr) != 0)
+ panic("Couldn't map the device memory");
+ end = vaddr + count - 1;
- debugf("reg addr start = %lx, end = %lx, count = %lx\n", start,
+ debugf("reg addr start = %lx, end = %lx, count = %lx\n", vaddr,
end, count);
- resource_list_add(rl, SYS_RES_MEMORY, i, start, end,
+ resource_list_add(rl, SYS_RES_MEMORY, i, vaddr, end,
count);
}
rv = 0;
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/fdt/fdt_common.h
--- a/head/sys/dev/fdt/fdt_common.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/fdt/fdt_common.h Wed Aug 15 11:46:11 2012 +0300
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/sys/dev/fdt/fdt_common.h 235778 2012-05-22 08:33:14Z gber $
+ * $FreeBSD: head/sys/dev/fdt/fdt_common.h 239274 2012-08-15 03:49:10Z gonzo $
*/
#ifndef _FDT_COMMON_H_
@@ -91,6 +91,7 @@
phandle_t fdt_find_compatible(phandle_t, const char *, int);
int fdt_get_mem_regions(struct mem_region *, int *, uint32_t *);
int fdt_get_phyaddr(phandle_t, device_t, int *, void **);
+int fdt_get_range(phandle_t, int, u_long *, u_long *);
int fdt_immr_addr(vm_offset_t);
int fdt_regsize(phandle_t, u_long *, u_long *);
int fdt_intr_decode(phandle_t, pcell_t *, int *, int *, int *);
@@ -107,7 +108,7 @@
struct fdt_pci_range *);
int fdt_pci_route_intr(int, int, int, int, struct fdt_pci_intr *, int *);
int fdt_ranges_verify(pcell_t *, int, int, int, int);
-int fdt_reg_to_rl(phandle_t, struct resource_list *, u_long);
+int fdt_reg_to_rl(phandle_t, struct resource_list *);
int fdt_pm(phandle_t);
#endif /* _FDT_COMMON_H_ */
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/fdt/fdtbus.c
--- a/head/sys/dev/fdt/fdtbus.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/fdt/fdtbus.c Wed Aug 15 11:46:11 2012 +0300
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/fdt/fdtbus.c 238043 2012-07-02 23:49:29Z marcel $");
+__FBSDID("$FreeBSD: head/sys/dev/fdt/fdtbus.c 239274 2012-08-15 03:49:10Z gonzo $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -289,7 +289,7 @@
resource_list_init(&di->di_res);
- if (fdt_reg_to_rl(node, &di->di_res, fdt_immr_va)) {
+ if (fdt_reg_to_rl(node, &di->di_res)) {
device_printf(child, "could not process 'reg' property\n");
newbus_device_destroy(child);
child = NULL;
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/fdt/simplebus.c
--- a/head/sys/dev/fdt/simplebus.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/fdt/simplebus.c Wed Aug 15 11:46:11 2012 +0300
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/fdt/simplebus.c 238044 2012-07-02 23:53:08Z marcel $");
+__FBSDID("$FreeBSD: head/sys/dev/fdt/simplebus.c 239274 2012-08-15 03:49:10Z gonzo $");
#include "opt_platform.h"
#include <sys/param.h>
@@ -61,9 +61,6 @@
struct simplebus_softc {
int sc_addr_cells;
int sc_size_cells;
- u_long sc_start_pa;
- u_long sc_start_va;
- u_long sc_size;
};
struct simplebus_devinfo {
@@ -155,10 +152,6 @@
sc = device_get_softc(dev);
- sc->sc_start_pa = fdt_immr_pa;
- sc->sc_start_va = fdt_immr_va;
- sc->sc_size = fdt_immr_size;
-
/*
* Walk simple-bus and add direct subordinates as our children.
*/
@@ -182,10 +175,11 @@
}
resource_list_init(&di->di_res);
-
- if (fdt_reg_to_rl(dt_child, &di->di_res, sc->sc_start_va)) {
- device_printf(dev, "%s: could not process 'reg' "
+ if (fdt_reg_to_rl(dt_child, &di->di_res)) {
+ device_printf(dev,
+ "%s: could not process 'reg' "
"property\n", di->di_ofw.obd_name);
+ /* XXX should unmap */
ofw_bus_gen_destroy_devinfo(&di->di_ofw);
free(di, M_SIMPLEBUS);
continue;
@@ -195,6 +189,7 @@
device_printf(dev, "%s: could not process "
"'interrupts' property\n", di->di_ofw.obd_name);
resource_list_free(&di->di_res);
+ /* XXX should unmap */
ofw_bus_gen_destroy_devinfo(&di->di_ofw);
free(di, M_SIMPLEBUS);
continue;
@@ -206,6 +201,7 @@
device_printf(dev, "could not add child: %s\n",
di->di_ofw.obd_name);
resource_list_free(&di->di_res);
+ /* XXX should unmap */
ofw_bus_gen_destroy_devinfo(&di->di_ofw);
free(di, M_SIMPLEBUS);
continue;
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/isp/isp.c
--- a/head/sys/dev/isp/isp.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/isp/isp.c Wed Aug 15 11:46:11 2012 +0300
@@ -47,7 +47,7 @@
#endif
#ifdef __FreeBSD__
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/isp/isp.c 238869 2012-07-28 20:06:29Z mjacob $");
+__FBSDID("$FreeBSD: head/sys/dev/isp/isp.c 239219 2012-08-12 20:49:25Z mjacob $");
#include <dev/isp/isp_freebsd.h>
#endif
#ifdef __OpenBSD__
@@ -939,7 +939,7 @@
MBSINIT(&mbs, MBOX_WRITE_RAM_WORD, MBLOGNONE, 0);
mbs.param[1] = code_org;
mbs.param[2] = ucd.np[0];
- isp_prt(isp, ISP_LOGDEBUG1, "WRITE RAM %u words at load address 0x%x\n", ucd.np[3], code_org);
+ isp_prt(isp, ISP_LOGDEBUG1, "WRITE RAM %u words at load address 0x%x", ucd.np[3], code_org);
isp_mboxcmd(isp, &mbs);
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
isp_prt(isp, ISP_LOGERR, "F/W download failed at word %d", isp->isp_mbxwrk1 - code_org);
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/isp/isp_freebsd.c
--- a/head/sys/dev/isp/isp_freebsd.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/isp/isp_freebsd.c Wed Aug 15 11:46:11 2012 +0300
@@ -28,7 +28,7 @@
* Platform (FreeBSD) dependent common attachment code for Qlogic adapters.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/isp/isp_freebsd.c 239143 2012-08-08 18:24:33Z mjacob $");
+__FBSDID("$FreeBSD: head/sys/dev/isp/isp_freebsd.c 239218 2012-08-12 20:45:47Z mjacob $");
#include <dev/isp/isp_freebsd.h>
#include <sys/unistd.h>
#include <sys/kthread.h>
@@ -779,8 +779,13 @@
isp_free_pcmd(ispsoftc_t *isp, union ccb *ccb)
{
if (ISP_PCMD(ccb)) {
- memset(ISP_PCMD(ccb), 0, sizeof (struct isp_pcmd));
- ((struct isp_pcmd *)ISP_PCMD(ccb))->next = isp->isp_osinfo.pcmd_free;
+#ifdef ISP_TARGET_MODE
+ PISP_PCMD(ccb)->datalen = 0;
+ PISP_PCMD(ccb)->totslen = 0;
+ PISP_PCMD(ccb)->cumslen = 0;
+ PISP_PCMD(ccb)->crn = 0;
+#endif
+ PISP_PCMD(ccb)->next = isp->isp_osinfo.pcmd_free;
isp->isp_osinfo.pcmd_free = ISP_PCMD(ccb);
ISP_PCMD(ccb) = NULL;
}
@@ -6326,12 +6331,20 @@
int
isp_fcp_next_crn(ispsoftc_t *isp, uint8_t *crnp, XS_T *cmd)
{
- uint32_t chan = XS_CHANNEL(cmd);
- uint32_t tgt = XS_TGT(cmd);
- uint32_t lun = XS_LUN(cmd);
- struct isp_fc *fc = &isp->isp_osinfo.pc.fc[chan];
- int idx = NEXUS_HASH(tgt, lun);
- struct isp_nexus *nxp = fc->nexus_hash[idx];
+ uint32_t chan, tgt, lun;
+ struct isp_fc *fc;
+ struct isp_nexus *nxp;
+ int idx;
+
+ if (isp->isp_type < ISP_HA_FC_2300)
+ return (0);
+
+ chan = XS_CHANNEL(cmd);
+ tgt = XS_TGT(cmd);
+ lun = XS_LUN(cmd);
+ fc = &isp->isp_osinfo.pc.fc[chan];
+ idx = NEXUS_HASH(tgt, lun);
+ nxp = fc->nexus_hash[idx];
while (nxp) {
if (nxp->tgt == tgt && nxp->lun == lun)
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/isp/isp_pci.c
--- a/head/sys/dev/isp/isp_pci.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/isp/isp_pci.c Wed Aug 15 11:46:11 2012 +0300
@@ -28,7 +28,7 @@
* FreeBSD Version.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/isp/isp_pci.c 239010 2012-08-03 14:25:35Z mjacob $");
+__FBSDID("$FreeBSD: head/sys/dev/isp/isp_pci.c 239218 2012-08-12 20:45:47Z mjacob $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -1690,18 +1690,20 @@
bus_dma_tag_destroy(fc->tdmat);
goto bad;
}
- for (i = 0; i < INITIAL_NEXUS_COUNT; i++) {
- struct isp_nexus *n = malloc(sizeof (struct isp_nexus), M_DEVBUF, M_NOWAIT | M_ZERO);
- if (n == NULL) {
- while (fc->nexus_free_list) {
- n = fc->nexus_free_list;
- fc->nexus_free_list = n->next;
- free(n, M_DEVBUF);
+ if (isp->isp_type >= ISP_HA_FC_2300) {
+ for (i = 0; i < INITIAL_NEXUS_COUNT; i++) {
+ struct isp_nexus *n = malloc(sizeof (struct isp_nexus), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (n == NULL) {
+ while (fc->nexus_free_list) {
+ n = fc->nexus_free_list;
+ fc->nexus_free_list = n->next;
+ free(n, M_DEVBUF);
+ }
+ goto bad;
}
- goto bad;
+ n->next = fc->nexus_free_list;
+ fc->nexus_free_list = n;
}
- n->next = fc->nexus_free_list;
- fc->nexus_free_list = n;
}
}
}
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/mge/if_mge.c
--- a/head/sys/dev/mge/if_mge.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/mge/if_mge.c Wed Aug 15 11:46:11 2012 +0300
@@ -34,7 +34,7 @@
#endif
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/mge/if_mge.c 238873 2012-07-28 21:56:24Z hrs $");
+__FBSDID("$FreeBSD: head/sys/dev/mge/if_mge.c 239276 2012-08-15 04:07:18Z gonzo $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -104,7 +104,10 @@
static void mge_ver_params(struct mge_softc *sc);
static void mge_intrs_ctrl(struct mge_softc *sc, int enable);
+static void mge_intr_rxtx(void *arg);
static void mge_intr_rx(void *arg);
+static void mge_intr_rx_check(struct mge_softc *sc, uint32_t int_cause,
+ uint32_t int_cause_ext);
static int mge_intr_rx_locked(struct mge_softc *sc, int count);
static void mge_intr_tx(void *arg);
static void mge_intr_tx_locked(struct mge_softc *sc);
@@ -171,15 +174,14 @@
{ SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE },
{ SYS_RES_IRQ, 1, RF_ACTIVE | RF_SHAREABLE },
{ SYS_RES_IRQ, 2, RF_ACTIVE | RF_SHAREABLE },
- { SYS_RES_IRQ, 3, RF_ACTIVE | RF_SHAREABLE },
- { SYS_RES_IRQ, 4, RF_ACTIVE | RF_SHAREABLE },
{ -1, 0 }
};
static struct {
driver_intr_t *handler;
char * description;
-} mge_intrs[MGE_INTR_COUNT] = {
+} mge_intrs[MGE_INTR_COUNT + 1] = {
+ { mge_intr_rxtx,"GbE aggregated interrupt" },
{ mge_intr_rx, "GbE receive interrupt" },
{ mge_intr_tx, "GbE transmit interrupt" },
{ mge_intr_misc,"GbE misc interrupt" },
@@ -258,10 +260,11 @@
uint32_t d, r;
soc_id(&d, &r);
- if (d == MV_DEV_88F6281 ||
+ if (d == MV_DEV_88F6281 || d == MV_DEV_88F6781 ||
d == MV_DEV_88F6282 ||
d == MV_DEV_MV78100 ||
- d == MV_DEV_MV78100_Z0) {
+ d == MV_DEV_MV78100_Z0 ||
+ (d & MV_DEV_FAMILY_MASK) == MV_DEV_DISCOVERY) {
sc->mge_ver = 2;
sc->mge_mtu = 0x4e8;
sc->mge_tfut_ipg_max = 0xFFFF;
@@ -278,6 +281,15 @@
sc->mge_tx_tok_cfg = 0x3FFFFFFF;
sc->mge_tx_tok_cnt = 0x3FFFFFFF;
}
+ if (d == MV_DEV_88RC8180)
+ sc->mge_intr_cnt = 1;
+ else
+ sc->mge_intr_cnt = 2;
+
+ if (d == MV_DEV_MV78160 || d == MV_DEV_MV78260 || d == MV_DEV_MV78460)
+ sc->mge_hw_csum = 0;
+ else
+ sc->mge_hw_csum = 1;
}
static void
@@ -442,7 +454,7 @@
/* Allocate a busdma tag for mbufs. */
error = bus_dma_tag_create(bus_get_dma_tag(sc->dev), /* parent */
- 8, 0, /* alignment, boundary */
+ 1, 0, /* alignment, boundary */
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filtfunc, filtfuncarg */
@@ -681,9 +693,12 @@
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
ifp->if_softc = sc;
ifp->if_flags = IFF_SIMPLEX | IFF_MULTICAST | IFF_BROADCAST;
- ifp->if_capabilities = IFCAP_HWCSUM | IFCAP_VLAN_MTU;
+ ifp->if_capabilities = IFCAP_VLAN_MTU;
+ if (sc->mge_hw_csum) {
+ ifp->if_capabilities |= IFCAP_HWCSUM;
+ ifp->if_hwassist = MGE_CHECKSUM_FEATURES;
+ }
ifp->if_capenable = ifp->if_capabilities;
- ifp->if_hwassist = MGE_CHECKSUM_FEATURES;
#ifdef DEVICE_POLLING
/* Advertise that polling is supported */
@@ -717,13 +732,15 @@
MGE_WRITE(sc, MGE_REG_PHYDEV, miisc->mii_phy);
/* Attach interrupt handlers */
- for (i = 0; i < 2; ++i) {
- error = bus_setup_intr(dev, sc->res[1 + i],
- INTR_TYPE_NET | INTR_MPSAFE, NULL, *mge_intrs[i].handler,
- sc, &sc->ih_cookie[i]);
+ /* TODO: review flags, in part. mark RX as INTR_ENTROPY ? */
+ for (i = 1; i <= sc->mge_intr_cnt; ++i) {
+ error = bus_setup_intr(dev, sc->res[i],
+ INTR_TYPE_NET | INTR_MPSAFE,
+ NULL, *mge_intrs[(sc->mge_intr_cnt == 1 ? 0 : i)].handler,
+ sc, &sc->ih_cookie[i - 1]);
if (error) {
device_printf(dev, "could not setup %s\n",
- mge_intrs[i].description);
+ mge_intrs[(sc->mge_intr_cnt == 1 ? 0 : i)].description);
mge_detach(dev);
return (error);
}
@@ -748,14 +765,14 @@
callout_drain(&sc->wd_callout);
/* Stop and release all interrupts */
- for (i = 0; i < 2; ++i) {
+ for (i = 0; i < sc->mge_intr_cnt; ++i) {
if (!sc->ih_cookie[i])
continue;
error = bus_teardown_intr(dev, sc->res[1 + i], sc->ih_cookie[i]);
if (error)
device_printf(dev, "could not release %s\n",
- mge_intrs[i].description);
+ mge_intrs[(sc->mge_intr_cnt == 1 ? 0 : i + 1)].description);
}
/* Detach network interface */
@@ -983,6 +1000,41 @@
}
static void
+mge_intr_rxtx(void *arg)
+{
+ struct mge_softc *sc = arg;
+ uint32_t int_cause, int_cause_ext;
+
+ MGE_GLOBAL_LOCK(sc);
+
+#ifdef DEVICE_POLLING
+ if (sc->ifp->if_capenable & IFCAP_POLLING) {
+ MGE_GLOBAL_UNLOCK(sc);
+ return;
+ }
+#endif
+
+ /* Get interrupt cause */
+ int_cause = MGE_READ(sc, MGE_PORT_INT_CAUSE);
+ int_cause_ext = MGE_READ(sc, MGE_PORT_INT_CAUSE_EXT);
+
+ /* Check for Transmit interrupt */
+ if (int_cause_ext & (MGE_PORT_INT_EXT_TXBUF0 |
+ MGE_PORT_INT_EXT_TXUR)) {
+ MGE_WRITE(sc, MGE_PORT_INT_CAUSE_EXT, ~(int_cause_ext &
+ (MGE_PORT_INT_EXT_TXBUF0 | MGE_PORT_INT_EXT_TXUR)));
+ mge_intr_tx_locked(sc);
+ }
+
+ MGE_TRANSMIT_UNLOCK(sc);
+
+ /* Check for Receive interrupt */
+ mge_intr_rx_check(sc, int_cause, int_cause_ext);
+
+ MGE_RECEIVE_UNLOCK(sc);
+}
+
+static void
mge_intr_err(void *arg)
{
struct mge_softc *sc = arg;
@@ -1020,11 +1072,20 @@
int_cause = MGE_READ(sc, MGE_PORT_INT_CAUSE);
int_cause_ext = MGE_READ(sc, MGE_PORT_INT_CAUSE_EXT);
+ mge_intr_rx_check(sc, int_cause, int_cause_ext);
+
+ MGE_RECEIVE_UNLOCK(sc);
+}
+
+static void
+mge_intr_rx_check(struct mge_softc *sc, uint32_t int_cause,
+ uint32_t int_cause_ext)
+{
/* Check for resource error */
if (int_cause & MGE_PORT_INT_RXERRQ0) {
mge_reinit_rx(sc);
MGE_WRITE(sc, MGE_PORT_INT_CAUSE,
- int_cause & ~MGE_PORT_INT_RXERRQ0);
+ ~(int_cause & MGE_PORT_INT_RXERRQ0));
}
int_cause &= MGE_PORT_INT_RXQ0;
@@ -1035,11 +1096,8 @@
MGE_WRITE(sc, MGE_PORT_INT_CAUSE_EXT, ~int_cause_ext);
mge_intr_rx_locked(sc, -1);
}
-
- MGE_RECEIVE_UNLOCK(sc);
}
-
static int
mge_intr_rx_locked(struct mge_softc *sc, int count)
{
@@ -1130,8 +1188,8 @@
/* Ack the interrupt */
int_cause_ext = MGE_READ(sc, MGE_PORT_INT_CAUSE_EXT);
- MGE_WRITE(sc, MGE_PORT_INT_CAUSE_EXT,
- int_cause_ext & ~MGE_PORT_INT_EXT_TXBUF0);
+ MGE_WRITE(sc, MGE_PORT_INT_CAUSE_EXT, ~(int_cause_ext &
+ (MGE_PORT_INT_EXT_TXBUF0 | MGE_PORT_INT_EXT_TXUR)));
mge_intr_tx_locked(sc);
@@ -1401,12 +1459,12 @@
dw->mge_desc->byte_count = segs[seg].ds_len;
dw->mge_desc->buffer = segs[seg].ds_addr;
dw->buffer = m0;
- dw->mge_desc->cmd_status = MGE_TX_LAST | MGE_TX_FIRST |
+ dw->mge_desc->cmd_status = 0;
+ if (seg == 0)
+ mge_offload_setup_descriptor(sc, dw);
+ dw->mge_desc->cmd_status |= MGE_TX_LAST | MGE_TX_FIRST |
MGE_TX_ETH_CRC | MGE_TX_EN_INT | MGE_TX_PADDING |
MGE_DMA_OWNED;
-
- if (seg == 0)
- mge_offload_setup_descriptor(sc, dw);
}
bus_dmamap_sync(sc->mge_desc_dtag, dw->desc_dmap,
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/mge/if_mgevar.h
--- a/head/sys/dev/mge/if_mgevar.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/mge/if_mgevar.h Wed Aug 15 11:46:11 2012 +0300
@@ -28,7 +28,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/sys/dev/mge/if_mgevar.h 232518 2012-03-04 19:22:52Z raj $
+ * $FreeBSD: head/sys/dev/mge/if_mgevar.h 239276 2012-08-15 04:07:18Z gonzo $
*/
#ifndef __IF_MGE_H__
@@ -103,6 +103,8 @@
uint32_t mge_tx_tok_cnt;
uint16_t mge_mtu;
int mge_ver;
+ int mge_intr_cnt;
+ uint8_t mge_hw_csum;
struct mge_softc *phy_sc;
};
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/mii/miidevs
--- a/head/sys/dev/mii/miidevs Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/mii/miidevs Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-$FreeBSD: head/sys/dev/mii/miidevs 235999 2012-05-25 15:05:17Z raj $
+$FreeBSD: head/sys/dev/mii/miidevs 239275 2012-08-15 04:03:55Z gonzo $
/*$NetBSD: miidevs,v 1.105 2011/11/25 23:28:14 jakllsch Exp $*/
/*-
@@ -70,6 +70,7 @@
oui REALTEK 0x00e04c RealTek Semicondctor
oui SEEQ 0x00a07d Seeq Technology
oui SIS 0x00e006 Silicon Integrated Systems
+oui SMC 0x00800f SMC
oui TI 0x080028 Texas Instruments
oui TSC 0x00c039 TDK Semiconductor
oui VITESSE 0x0001c1 Vitesse Semiconductor
@@ -331,3 +332,6 @@
/* XaQti Corp. PHYs */
model xxXAQTI XMACII 0x0000 XaQti Corp. XMAC II gigabit interface
+
+/* SMC */
+model SMC LAN8710A 0x000F SMC LAN8710A 10/100 interface
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/mii/smcphy.c
--- a/head/sys/dev/mii/smcphy.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/mii/smcphy.c Wed Aug 15 11:46:11 2012 +0300
@@ -23,10 +23,11 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/mii/smcphy.c 232015 2012-02-23 01:20:21Z yongari $");
+__FBSDID("$FreeBSD: head/sys/dev/mii/smcphy.c 239275 2012-08-15 04:03:55Z gonzo $");
/*
- * Driver for the internal PHY on the SMSC LAN91C111.
+ * Driver for the SEEQ 80220 and 84220.
+ * (Originally developed for the internal PHY on the SMSC LAN91C111.)
*/
#include <sys/param.h>
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/mii/smscphy.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/mii/smscphy.c Wed Aug 15 11:46:11 2012 +0300
@@ -0,0 +1,237 @@
+/*-
+ * Copyright (c) 2006 Benno Rice. 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/sys/dev/mii/smscphy.c 239275 2012-08-15 04:03:55Z gonzo $");
+
+/*
+ * Driver for the SMSC LAN8710A
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/errno.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+#include "miidevs.h"
+
+#include "miibus_if.h"
+
+static int smscphy_probe(device_t);
+static int smscphy_attach(device_t);
+
+static int smscphy_service(struct mii_softc *, struct mii_data *, int);
+static void smscphy_auto(struct mii_softc *, int);
+static void smscphy_status(struct mii_softc *);
+
+static device_method_t smscphy_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_probe, smscphy_probe),
+ DEVMETHOD(device_attach, smscphy_attach),
+ DEVMETHOD(device_detach, mii_phy_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD_END
+};
+
+static devclass_t smscphy_devclass;
+
+static driver_t smscphy_driver = {
+ "smscphy",
+ smscphy_methods,
+ sizeof(struct mii_softc)
+};
+
+DRIVER_MODULE(smscphy, miibus, smscphy_driver, smscphy_devclass, 0, 0);
+
+static const struct mii_phydesc smscphys[] = {
+ MII_PHY_DESC(SMC, LAN8710A),
+ MII_PHY_END
+};
+
+static const struct mii_phy_funcs smscphy_funcs = {
+ smscphy_service,
+ smscphy_status,
+ mii_phy_reset
+};
+
+static int
+smscphy_probe(device_t dev)
+{
+
+ return (mii_phy_dev_probe(dev, smscphys, BUS_PROBE_DEFAULT));
+}
+
+static int
+smscphy_attach(device_t dev)
+{
+ struct mii_softc *sc;
+ struct mii_attach_args *ma;
+ const struct mii_phy_funcs *mpf;
+
+ sc = device_get_softc(dev);
+ ma = device_get_ivars(dev);
+ mpf = &smscphy_funcs;
+ mii_phy_dev_attach(dev, MIIF_NOISOLATE | MIIF_NOMANPAUSE, mpf, 1);
+ mii_phy_setmedia(sc);
+
+ return (0);
+}
+
+static int
+smscphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
+{
+ struct ifmedia_entry *ife;
+ int reg;
+
+ ife = mii->mii_media.ifm_cur;
+
+ switch (cmd) {
+ case MII_POLLSTAT:
+ break;
+
+ case MII_MEDIACHG:
+ /*
+ * If the interface is not up, don't do anything.
+ */
+ if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
+ break;
+
+ switch (IFM_SUBTYPE(ife->ifm_media)) {
+ case IFM_AUTO:
+ smscphy_auto(sc, ife->ifm_media);
+ break;
+
+ default:
+ mii_phy_setmedia(sc);
+ break;
+ }
+
+ break;
+
+ case MII_TICK:
+ if ((mii->mii_ifp->if_flags & IFF_UP) == 0) {
+ return (0);
+ }
+
+ if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) {
+ break;
+ }
+
+ /* I have no idea why BMCR_ISO gets set. */
+ reg = PHY_READ(sc, MII_BMCR);
+ if (reg & BMCR_ISO) {
+ PHY_WRITE(sc, MII_BMCR, reg & ~BMCR_ISO);
+ }
+
+ reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
+ if (reg & BMSR_LINK) {
+ sc->mii_ticks = 0;
+ break;
+ }
+
+ if (++sc->mii_ticks <= MII_ANEGTICKS) {
+ break;
+ }
+
+ sc->mii_ticks = 0;
+ PHY_RESET(sc);
+ smscphy_auto(sc, ife->ifm_media);
+ break;
+ }
+
+ /* Update the media status. */
+ PHY_STATUS(sc);
+
+ /* Callback if something changed. */
+ mii_phy_update(sc, cmd);
+ return (0);
+}
+
+static void
+smscphy_auto(struct mii_softc *sc, int media)
+{
+ uint16_t anar;
+
+ anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA;
+ if ((media & IFM_FLOW) != 0 || (sc->mii_flags & MIIF_FORCEPAUSE) != 0)
+ anar |= ANAR_FC;
+ PHY_WRITE(sc, MII_ANAR, anar);
+ /* Apparently this helps. */
+ anar = PHY_READ(sc, MII_ANAR);
+ PHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG);
+}
+
+static void
+smscphy_status(struct mii_softc *sc)
+{
+ struct mii_data *mii;
+ uint32_t bmcr, bmsr, status;
+
+ mii = sc->mii_pdata;
+ mii->mii_media_status = IFM_AVALID;
+ mii->mii_media_active = IFM_ETHER;
+
+ bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
+ if ((bmsr & BMSR_LINK) != 0)
+ mii->mii_media_status |= IFM_ACTIVE;
+
+ bmcr = PHY_READ(sc, MII_BMCR);
+ if ((bmcr & BMCR_ISO) != 0) {
+ mii->mii_media_active |= IFM_NONE;
+ mii->mii_media_status = 0;
+ return;
+ }
+
+ if ((bmcr & BMCR_LOOP) != 0)
+ mii->mii_media_active |= IFM_LOOP;
+
+ if ((bmcr & BMCR_AUTOEN) != 0) {
+ if ((bmsr & BMSR_ACOMP) == 0) {
+ /* Erg, still trying, I guess... */
+ mii->mii_media_active |= IFM_NONE;
+ return;
+ }
+ }
+
+ status = PHY_READ(sc, 0x1F);
+ if (status & 0x0008)
+ mii->mii_media_active |= IFM_100_TX;
+ else
+ mii->mii_media_active |= IFM_10_T;
+ if (status & 0x0010)
+ mii->mii_media_active |= IFM_FDX | mii_phy_flowstatus(sc);
+ else
+ mii->mii_media_active |= IFM_HDX;
+}
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/mmc/mmc.c
--- a/head/sys/dev/mmc/mmc.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/mmc/mmc.c Wed Aug 15 11:46:11 2012 +0300
@@ -51,7 +51,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/mmc/mmc.c 236491 2012-06-02 20:47:00Z marius $");
+__FBSDID("$FreeBSD: head/sys/dev/mmc/mmc.c 239281 2012-08-15 06:31:32Z gonzo $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -1730,5 +1730,6 @@
};
static devclass_t mmc_devclass;
+DRIVER_MODULE(mmc, ti_mmchs, mmc_driver, mmc_devclass, NULL, NULL);
DRIVER_MODULE(mmc, at91_mci, mmc_driver, mmc_devclass, NULL, NULL);
DRIVER_MODULE(mmc, sdhci, mmc_driver, mmc_devclass, NULL, NULL);
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/netmap/ixgbe_netmap.h
--- a/head/sys/dev/netmap/ixgbe_netmap.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/netmap/ixgbe_netmap.h Wed Aug 15 11:46:11 2012 +0300
@@ -24,7 +24,7 @@
*/
/*
- * $FreeBSD: head/sys/dev/netmap/ixgbe_netmap.h 238985 2012-08-02 11:59:43Z luigi $
+ * $FreeBSD: head/sys/dev/netmap/ixgbe_netmap.h 239242 2012-08-13 19:14:45Z emaste $
* $Id: ixgbe_netmap.h 10627 2012-02-23 19:37:15Z luigi $
*
* netmap modifications for ixgbe
@@ -198,14 +198,17 @@
* Reconcile kernel and user view of the transmit ring.
* This routine might be called frequently so it must be efficient.
*
- * Userspace has filled tx slots up to ring->cur (excluded).
- * The last unused slot previously known to the kernel was kring->nkr_hwcur,
- * and the last interrupt reported kring->nr_hwavail slots available.
+ * ring->cur holds the userspace view of the current ring index. Userspace
+ * has filled the tx slots from the previous call's ring->cur up to but not
+ * including ring->cur for this call. In this function the kernel updates
+ * kring->nr_hwcur to ring->cur, thus slots [kring->nr_hwcur, ring->cur) are
+ * now ready to transmit. At the last interrupt kring->nr_hwavail slots were
+ * available.
*
* This function runs under lock (acquired from the caller or internally).
* It must first update ring->avail to what the kernel knows,
- * subtract the newly used slots (ring->cur - kring->nkr_hwcur)
- * from both avail and nr_hwavail, and set ring->nkr_hwcur = ring->cur
+ * subtract the newly used slots (ring->cur - kring->nr_hwcur)
+ * from both avail and nr_hwavail, and set ring->nr_hwcur = ring->cur
* issuing a dmamap_sync on all slots.
*
* Since ring comes from userspace, its content must be read only once,
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/ofw/ofw_iicbus.c
--- a/head/sys/dev/ofw/ofw_iicbus.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/ofw/ofw_iicbus.c Wed Aug 15 11:46:11 2012 +0300
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/ofw/ofw_iicbus.c 233018 2012-03-15 22:53:39Z nwhitehorn $");
+__FBSDID("$FreeBSD: head/sys/dev/ofw/ofw_iicbus.c 239273 2012-08-15 03:33:57Z gonzo $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -35,6 +35,7 @@
#include <sys/module.h>
#include <sys/mutex.h>
+#include <dev/fdt/fdt_common.h>
#include <dev/iicbus/iicbus.h>
#include <dev/iicbus/iiconf.h>
#include <dev/ofw/ofw_bus.h>
@@ -101,6 +102,7 @@
struct iicbus_softc *sc = IICBUS_SOFTC(dev);
struct ofw_iicbus_devinfo *dinfo;
phandle_t child;
+ pcell_t paddr;
device_t childdev;
uint32_t addr;
@@ -121,10 +123,11 @@
* property, then try the reg property. It moves around
* on different systems.
*/
- if (OF_getprop(child, "i2c-address", &addr, sizeof(addr)) == -1)
- if (OF_getprop(child, "reg", &addr, sizeof(addr)) == -1)
+ if (OF_getprop(child, "i2c-address", &paddr, sizeof(paddr)) == -1)
+ if (OF_getprop(child, "reg", &paddr, sizeof(paddr)) == -1)
continue;
+ addr = fdt32_to_cpu(paddr);
/*
* Now set up the I2C and OFW bus layer devinfo and add it
* to the bus.
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/re/if_re.c
--- a/head/sys/dev/re/if_re.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/re/if_re.c Wed Aug 15 11:46:11 2012 +0300
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/re/if_re.c 237547 2012-06-25 05:47:12Z kevlo $");
+__FBSDID("$FreeBSD: head/sys/dev/re/if_re.c 239234 2012-08-13 16:03:30Z emaste $");
/*
* RealTek 8139C+/8169/8169S/8110S/8168/8111/8101E PCI NIC driver
@@ -2112,8 +2112,8 @@
ifp = sc->rl_ifp;
#ifdef DEV_NETMAP
if (ifp->if_capenable & IFCAP_NETMAP) {
- NA(ifp)->rx_rings->nr_kflags |= NKR_PENDINTR;
- selwakeuppri(&NA(ifp)->rx_rings->si, PI_NET);
+ NA(ifp)->rx_rings[0].nr_kflags |= NKR_PENDINTR;
+ selwakeuppri(&NA(ifp)->rx_rings[0].si, PI_NET);
return 0;
}
#endif /* DEV_NETMAP */
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/sound/macio/snapper.c
--- a/head/sys/dev/sound/macio/snapper.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/sound/macio/snapper.c Wed Aug 15 11:46:11 2012 +0300
@@ -22,7 +22,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/sound/macio/snapper.c 239245 2012-08-14 05:16:35Z andreast $
*/
/*-
* Copyright (c) 2002, 2003 Tsubai Masanari. All rights reserved.
@@ -174,7 +174,7 @@
#define SNAPPER_MCR1_W_16 0x00 /* 16 bit */
#define SNAPPER_MCR1_W_18 0x01 /* 18 bit */
#define SNAPPER_MCR1_W_20 0x02 /* 20 bit */
-#define SNAPPER_MCR1_W_24 0x03 /* 20 bit */
+#define SNAPPER_MCR1_W_24 0x03 /* 24 bit */
#define SNAPPER_MCR2_DL 0x80 /* Download */
#define SNAPPER_MCR2_AP 0x02 /* All pass mode */
#define SNAPPER_ACR_ADM 0x80 /* ADC output mode */
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/sound/pci/hda/hdaa.c
--- a/head/sys/dev/sound/pci/hda/hdaa.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/sound/pci/hda/hdaa.c Wed Aug 15 11:46:11 2012 +0300
@@ -45,7 +45,7 @@
#include "mixer_if.h"
-SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdaa.c 238022 2012-07-02 20:25:50Z mav $");
+SND_DECLARE_FILE("$FreeBSD: head/sys/dev/sound/pci/hda/hdaa.c 239254 2012-08-14 14:07:34Z mav $");
#define hdaa_lock(devinfo) snd_mtxlock((devinfo)->lock)
#define hdaa_unlock(devinfo) snd_mtxunlock((devinfo)->lock)
@@ -3068,8 +3068,7 @@
if ((only == 0 || only == w->nid) && (w->nid >= min) &&
(onlylength == 0 || onlylength == depth)) {
m = w->nid;
- if (length != NULL)
- *length = depth;
+ *length = depth;
}
break;
case HDA_PARAM_AUDIO_WIDGET_CAP_TYPE_PIN_COMPLEX:
@@ -3092,12 +3091,12 @@
j, mixed, min, only, depth + 1,
length, onlylength)) != 0) {
if (m == 0 || ret < m ||
- (ret == m && length != NULL &&
- *length < lm)) {
+ (ret == m && *length < lm)) {
m = ret;
im = i;
lm = *length;
- }
+ } else
+ *length = lm;
if (only)
break;
}
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/twe/twe.c
--- a/head/sys/dev/twe/twe.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/twe/twe.c Wed Aug 15 11:46:11 2012 +0300
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/twe/twe.c 239244 2012-08-13 21:29:34Z jhb $
*/
/*
@@ -151,8 +151,11 @@
/*
* Put command onto the freelist.
*/
+ TWE_IO_LOCK(sc);
twe_release_request(tr);
+ TWE_IO_UNLOCK(sc);
}
+ TWE_IO_LOCK(sc);
/*
* Check status register for errors, clear them.
@@ -164,6 +167,7 @@
* Wait for the controller to come ready.
*/
if (twe_wait_status(sc, TWE_STATUS_MICROCONTROLLER_READY, 60)) {
+ TWE_IO_UNLOCK(sc);
twe_printf(sc, "microcontroller not ready\n");
return(ENXIO);
}
@@ -185,6 +189,7 @@
if (!twe_soft_reset(sc))
break; /* reset process complete */
}
+ TWE_IO_UNLOCK(sc);
/* did we give up? */
if (i >= TWE_MAX_RESET_TRIES) {
twe_printf(sc, "can't initialise controller, giving up\n");
@@ -203,14 +208,17 @@
TWE_Param *drives = NULL, *param = NULL;
TWE_Array_Descriptor *ud;
+ TWE_CONFIG_ASSERT_LOCKED(sc);
if (unit < 0 || unit > TWE_MAX_UNITS)
return (EINVAL);
/*
* The controller is in a safe state, so try to find drives attached to it.
*/
+ TWE_IO_LOCK(sc);
if ((drives = twe_get_param(sc, TWE_PARAM_UNITSUMMARY, TWE_PARAM_UNITSUMMARY_Status,
TWE_MAX_UNITS, NULL)) == NULL) {
+ TWE_IO_UNLOCK(sc);
twe_printf(sc, "can't detect attached units\n");
return (EIO);
}
@@ -218,6 +226,7 @@
dr = &sc->twe_drive[unit];
/* check that the drive is online */
if (!(drives->data[unit] & TWE_PARAM_UNITSTATUS_Online)) {
+ TWE_IO_UNLOCK(sc);
error = ENXIO;
goto out;
}
@@ -225,21 +234,25 @@
table = TWE_PARAM_UNITINFO + unit;
if (twe_get_param_4(sc, table, TWE_PARAM_UNITINFO_Capacity, &dr->td_size)) {
+ TWE_IO_UNLOCK(sc);
twe_printf(sc, "error fetching capacity for unit %d\n", unit);
error = EIO;
goto out;
}
if (twe_get_param_1(sc, table, TWE_PARAM_UNITINFO_Status, &dr->td_state)) {
+ TWE_IO_UNLOCK(sc);
twe_printf(sc, "error fetching state for unit %d\n", unit);
error = EIO;
goto out;
}
if (twe_get_param_2(sc, table, TWE_PARAM_UNITINFO_DescriptorSize, &dsize)) {
+ TWE_IO_UNLOCK(sc);
twe_printf(sc, "error fetching descriptor size for unit %d\n", unit);
error = EIO;
goto out;
}
if ((param = twe_get_param(sc, table, TWE_PARAM_UNITINFO_Descriptor, dsize - 3, NULL)) == NULL) {
+ TWE_IO_UNLOCK(sc);
twe_printf(sc, "error fetching descriptor for unit %d\n", unit);
error = EIO;
goto out;
@@ -258,6 +271,7 @@
}
dr->td_cylinders = dr->td_size / (dr->td_heads * dr->td_sectors);
dr->td_twe_unit = unit;
+ TWE_IO_UNLOCK(sc);
error = twe_attach_drive(sc, dr);
@@ -274,6 +288,7 @@
{
int error;
+ TWE_CONFIG_ASSERT_LOCKED(sc);
if (unit < 0 || unit >= TWE_MAX_UNITS)
return (ENXIO);
@@ -295,12 +310,15 @@
/*
* Scan for drives
*/
+ TWE_CONFIG_LOCK(sc);
for (i = 0; i < TWE_MAX_UNITS; i++)
twe_add_unit(sc, i);
+ TWE_CONFIG_UNLOCK(sc);
/*
* Initialise connection with controller.
*/
+ TWE_IO_LOCK(sc);
twe_init_connection(sc, TWE_INIT_MESSAGE_CREDITS);
#ifdef TWE_SHUTDOWN_NOTIFICATION
@@ -319,6 +337,7 @@
* Finally enable interrupts.
*/
twe_enable_interrupts(sc);
+ TWE_IO_UNLOCK(sc);
}
/********************************************************************************
@@ -330,6 +349,7 @@
/*
* Mark the controller as shutting down, and disable any further interrupts.
*/
+ TWE_IO_ASSERT_LOCKED(sc);
sc->twe_state |= TWE_STATE_SHUTDOWN;
twe_disable_interrupts(sc);
@@ -385,6 +405,7 @@
debug_called(4);
+ TWE_IO_ASSERT_LOCKED(sc);
if (sc->twe_state & (TWE_STATE_CTLR_BUSY | TWE_STATE_FRZN))
return;
@@ -500,15 +521,32 @@
u_int16_t *aen_code = (u_int16_t *)addr;
struct twe_request *tr;
u_int8_t srid;
- int s, error;
+ int error;
+ size_t tr_length;
error = 0;
switch(ioctlcmd) {
/* handle a command from userspace */
case TWEIO_COMMAND:
+ /*
+ * if there's a data buffer, allocate and copy it in.
+ * Must be in multipled of 512 bytes.
+ */
+ tr_length = roundup2(tu->tu_size, 512);
+ if (tr_length > 0) {
+ data = malloc(tr_length, M_DEVBUF, M_WAITOK);
+ error = copyin(tu->tu_data, data, tu->tu_size);
+ if (error) {
+ free(data, M_DEVBUF);
+ break;
+ }
+ } else
+ data = NULL;
+
/* get a request */
+ TWE_IO_LOCK(sc);
while (twe_get_request(sc, &tr))
- tsleep(sc, PPAUSE, "twioctl", hz);
+ mtx_sleep(sc, &sc->twe_io_lock, PPAUSE, "twioctl", hz);
/*
* Save the command's request ID, copy the user-supplied command in,
@@ -519,23 +557,15 @@
bcopy(&tu->tu_command, cmd, sizeof(TWE_Command));
cmd->generic.request_id = srid;
- /*
- * if there's a data buffer, allocate and copy it in.
- * Must be in multipled of 512 bytes.
- */
- tr->tr_length = (tu->tu_size + 511) & ~511;
+ tr->tr_length = tr_length;
+ tr->tr_data = data;
if (tr->tr_length > 0) {
- if ((tr->tr_data = malloc(tr->tr_length, M_DEVBUF, M_WAITOK)) == NULL) {
- error = ENOMEM;
- goto cmd_done;
- }
- if ((error = copyin(tu->tu_data, tr->tr_data, tu->tu_size)) != 0)
- goto cmd_done;
tr->tr_flags |= TWE_CMD_DATAIN | TWE_CMD_DATAOUT;
}
/* run the command */
error = twe_wait_request(tr);
+ TWE_IO_UNLOCK(sc);
if (error)
goto cmd_done;
@@ -550,8 +580,9 @@
/* free resources */
if (tr->tr_data != NULL)
free(tr->tr_data, M_DEVBUF);
- if (tr != NULL)
- twe_release_request(tr);
+ TWE_IO_LOCK(sc);
+ twe_release_request(tr);
+ TWE_IO_UNLOCK(sc);
break;
@@ -564,7 +595,9 @@
case TWEQ_READY:
case TWEQ_BUSY:
case TWEQ_COMPLETE:
+ TWE_IO_LOCK(sc);
bcopy(&sc->twe_qstat[ts->ts_item], &ts->ts_qstat, sizeof(struct twe_qstat));
+ TWE_IO_UNLOCK(sc);
break;
#endif
default:
@@ -575,22 +608,28 @@
/* poll for an AEN */
case TWEIO_AEN_POLL:
+ TWE_IO_LOCK(sc);
*aen_code = twe_dequeue_aen(sc);
+ TWE_IO_UNLOCK(sc);
break;
/* wait for another AEN to show up */
case TWEIO_AEN_WAIT:
- s = splbio();
+ TWE_IO_LOCK(sc);
while ((*aen_code = twe_dequeue_aen(sc)) == TWE_AEN_QUEUE_EMPTY) {
- error = tsleep(&sc->twe_aen_queue, PRIBIO | PCATCH, "tweaen", 0);
+ error = mtx_sleep(&sc->twe_aen_queue, &sc->twe_io_lock, PRIBIO | PCATCH,
+ "tweaen", 0);
if (error == EINTR)
break;
}
- splx(s);
+ TWE_IO_UNLOCK(sc);
break;
case TWEIO_GET_PARAM:
- if ((param = twe_get_param(sc, tp->tp_table_id, tp->tp_param_id, tp->tp_size, NULL)) == NULL) {
+ TWE_IO_LOCK(sc);
+ param = twe_get_param(sc, tp->tp_table_id, tp->tp_param_id, tp->tp_size, NULL);
+ TWE_IO_UNLOCK(sc);
+ if (param == NULL) {
twe_printf(sc, "TWEIO_GET_PARAM failed for 0x%x/0x%x/%d\n",
tp->tp_table_id, tp->tp_param_id, tp->tp_size);
error = EINVAL;
@@ -607,26 +646,32 @@
break;
case TWEIO_SET_PARAM:
- if ((data = malloc(tp->tp_size, M_DEVBUF, M_WAITOK)) == NULL) {
- error = ENOMEM;
- } else {
- error = copyin(tp->tp_data, data, tp->tp_size);
- if (error == 0)
- error = twe_set_param(sc, tp->tp_table_id, tp->tp_param_id, tp->tp_size, data);
- free(data, M_DEVBUF);
+ data = malloc(tp->tp_size, M_DEVBUF, M_WAITOK);
+ error = copyin(tp->tp_data, data, tp->tp_size);
+ if (error == 0) {
+ TWE_IO_LOCK(sc);
+ error = twe_set_param(sc, tp->tp_table_id, tp->tp_param_id, tp->tp_size, data);
+ TWE_IO_UNLOCK(sc);
}
+ free(data, M_DEVBUF);
break;
case TWEIO_RESET:
+ TWE_IO_LOCK(sc);
twe_reset(sc);
+ TWE_IO_UNLOCK(sc);
break;
case TWEIO_ADD_UNIT:
+ TWE_CONFIG_LOCK(sc);
error = twe_add_unit(sc, td->td_unit);
+ TWE_CONFIG_UNLOCK(sc);
break;
case TWEIO_DEL_UNIT:
+ TWE_CONFIG_LOCK(sc);
error = twe_del_unit(sc, td->td_unit);
+ TWE_CONFIG_UNLOCK(sc);
break;
/* XXX implement ATA PASSTHROUGH */
@@ -724,6 +769,7 @@
debug_called(4);
+ TWE_IO_ASSERT_LOCKED(sc);
tr = NULL;
param = NULL;
@@ -817,6 +863,7 @@
debug_called(4);
+ TWE_IO_ASSERT_LOCKED(sc);
tr = NULL;
param = NULL;
error = ENOMEM;
@@ -874,6 +921,8 @@
debug_called(4);
+ TWE_IO_ASSERT_LOCKED(sc);
+
/* get a command */
if (twe_get_request(sc, &tr))
return(0);
@@ -903,18 +952,16 @@
static int
twe_wait_request(struct twe_request *tr)
{
- int s;
debug_called(4);
+ TWE_IO_ASSERT_LOCKED(tr->tr_sc);
tr->tr_flags |= TWE_CMD_SLEEPER;
tr->tr_status = TWE_CMD_BUSY;
twe_enqueue_ready(tr);
twe_startio(tr->tr_sc);
- s = splbio();
while (tr->tr_status == TWE_CMD_BUSY)
- tsleep(tr, PRIBIO, "twewait", 0);
- splx(s);
+ mtx_sleep(tr, &tr->tr_sc->twe_io_lock, PRIBIO, "twewait", 0);
return(tr->tr_status != TWE_CMD_COMPLETE);
}
@@ -991,12 +1038,12 @@
twe_reset(struct twe_softc *sc)
{
struct twe_request *tr;
- int i, s;
+ int i;
/*
* Sleep for a short period to allow AENs to be signalled.
*/
- tsleep(sc, PRIBIO, "twereset", hz);
+ mtx_sleep(sc, &sc->twe_io_lock, PRIBIO, "twereset", hz);
/*
* Disable interrupts from the controller, and mask any accidental entry
@@ -1004,7 +1051,6 @@
*/
twe_printf(sc, "controller reset in progress...\n");
twe_disable_interrupts(sc);
- s = splbio();
/*
* Try to soft-reset the controller.
@@ -1036,11 +1082,9 @@
* Kick the controller to start things going again, then re-enable interrupts.
*/
twe_startio(sc);
- twe_enable_interrupts(sc);
twe_printf(sc, "controller reset done, %d commands restarted\n", i);
out:
- splx(s);
twe_enable_interrupts(sc);
}
@@ -1060,11 +1104,14 @@
{
struct twe_softc *sc = tr->tr_sc;
TWE_Command *cmd;
- int i, s, done;
+ int i;
u_int32_t status_reg;
debug_called(4);
+ if (!dumping)
+ TWE_IO_ASSERT_LOCKED(sc);
+
/* mark the command as currently being processed */
tr->tr_status = TWE_CMD_BUSY;
cmd = TWE_FIND_COMMAND(tr);
@@ -1075,8 +1122,7 @@
* XXX it might be more efficient to return EBUSY immediately
* and let the command be rescheduled.
*/
- for (i = 100000, done = 0; (i > 0) && !done; i--) {
- s = splbio();
+ for (i = 100000; (i > 0); i--) {
/* check to see if we can post a command */
status_reg = TWE_STATUS(sc);
@@ -1086,7 +1132,7 @@
twe_enqueue_busy(tr);
TWE_COMMAND_QUEUE(sc, TWE_FIND_COMMANDPHYS(tr));
- done = 1;
+
/* move command to work queue */
#ifdef TWE_DEBUG
if (tr->tr_complete != NULL) {
@@ -1097,14 +1143,10 @@
debug(3, "queued request %d for polling caller", cmd->generic.request_id);
}
#endif
+ return(0);
}
- splx(s); /* drop spl to allow completion interrupts */
}
- /* command is enqueued */
- if (done)
- return(0);
-
/*
* We couldn't get the controller to take the command; try submitting it again later.
* This should only happen if something is wrong with the controller, or if we have
@@ -1125,14 +1167,13 @@
TWE_Response_Queue rq;
TWE_Command *cmd;
struct twe_request *tr;
- int s, found;
+ int found;
u_int32_t status_reg;
debug_called(5);
/* loop collecting completed commands */
found = 0;
- s = splbio();
for (;;) {
status_reg = TWE_STATUS(sc);
twe_check_bits(sc, status_reg); /* XXX should this fail? */
@@ -1155,7 +1196,6 @@
break; /* no response ready */
}
}
- splx(s);
/* if we've completed any commands, try posting some more */
if (found)
@@ -1259,6 +1299,7 @@
debug_called(2);
+ TWE_IO_ASSERT_LOCKED(sc);
TWE_SOFT_RESET(sc);
if (twe_wait_status(sc, TWE_STATUS_ATTENTION_INTERRUPT, 30)) {
@@ -1396,6 +1437,7 @@
{
u_int16_t aen;
+ TWE_IO_ASSERT_LOCKED(sc);
for (;;) {
if (twe_get_param_2(sc, TWE_PARAM_AEN, TWE_PARAM_AEN_UnitCode, &aen))
return(1);
@@ -1417,14 +1459,14 @@
twe_enqueue_aen(struct twe_softc *sc, u_int16_t aen)
{
char *msg;
- int s, next, nextnext;
+ int next, nextnext;
debug_called(4);
+ TWE_IO_ASSERT_LOCKED(sc);
if ((msg = twe_format_aen(sc, aen)) != NULL)
twe_printf(sc, "AEN: <%s>\n", msg);
- s = splbio();
/* enqueue the AEN */
next = ((sc->twe_aen_head + 1) % TWE_Q_LENGTH);
nextnext = ((sc->twe_aen_head + 2) % TWE_Q_LENGTH);
@@ -1447,7 +1489,6 @@
sc->twe_wait_aen = -1;
wakeup(&sc->twe_wait_aen);
}
- splx(s);
}
/********************************************************************************
@@ -1462,6 +1503,7 @@
debug_called(4);
+ TWE_IO_ASSERT_LOCKED(sc);
if (sc->twe_aen_tail == sc->twe_aen_head) {
result = TWE_AEN_QUEUE_EMPTY;
} else {
@@ -1479,15 +1521,13 @@
static int
twe_find_aen(struct twe_softc *sc, u_int16_t aen)
{
- int i, s, missing;
+ int i, missing;
missing = 1;
- s = splbio();
for (i = sc->twe_aen_tail; (i != sc->twe_aen_head) && missing; i = (i + 1) % TWE_Q_LENGTH) {
if (sc->twe_aen_queue[i] == aen)
missing = 0;
}
- splx(s);
return(missing);
}
@@ -1504,22 +1544,20 @@
twe_wait_aen(struct twe_softc *sc, int aen, int timeout)
{
time_t expiry;
- int found, s;
+ int found;
debug_called(4);
expiry = time_second + timeout;
found = 0;
- s = splbio();
sc->twe_wait_aen = aen;
do {
twe_fetch_aen(sc);
- tsleep(&sc->twe_wait_aen, PZERO, "twewaen", hz);
+ mtx_sleep(&sc->twe_wait_aen, &sc->twe_io_lock, PZERO, "twewaen", hz);
if (sc->twe_wait_aen == -1)
found = 1;
} while ((time_second <= expiry) && !found);
- splx(s);
return(!found);
}
#endif
@@ -1541,6 +1579,9 @@
TWE_Command *cmd;
debug_called(4);
+ if (!dumping)
+ TWE_IO_ASSERT_LOCKED(sc);
+
/* try to reuse an old buffer */
*tr = twe_dequeue_free(sc);
@@ -1567,6 +1608,8 @@
{
debug_called(4);
+ if (!dumping)
+ TWE_IO_ASSERT_LOCKED(tr->tr_sc);
if (tr->tr_private != NULL)
twe_panic(tr->tr_sc, "tr_private != NULL");
twe_enqueue_free(tr);
@@ -1591,6 +1634,8 @@
debug_called(2);
+ TWE_IO_LOCK(sc);
+
/* get the port count */
twe_get_param_1(sc, TWE_PARAM_CONTROLLER, TWE_PARAM_CONTROLLER_PortCount, &ports);
@@ -1641,6 +1686,7 @@
if (p[0])
free(p[0], M_DEVBUF);
}
+ TWE_IO_UNLOCK(sc);
}
/********************************************************************************
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/twe/twe_compat.h
--- a/head/sys/dev/twe/twe_compat.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/twe/twe_compat.h Wed Aug 15 11:46:11 2012 +0300
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/twe/twe_compat.h 239244 2012-08-13 21:29:34Z jhb $
*/
/*
* Portability and compatibility interfaces.
@@ -43,8 +43,11 @@
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
+#include <sys/lock.h>
#include <sys/module.h>
+#include <sys/mutex.h>
#include <sys/sysctl.h>
+#include <sys/sx.h>
#include <sys/bus.h>
#include <sys/conf.h>
@@ -65,10 +68,10 @@
/*
* Wrappers for bus-space actions
*/
-#define TWE_CONTROL(sc, val) bus_space_write_4((sc)->twe_btag, (sc)->twe_bhandle, 0x0, (u_int32_t)val)
-#define TWE_STATUS(sc) (u_int32_t)bus_space_read_4((sc)->twe_btag, (sc)->twe_bhandle, 0x4)
-#define TWE_COMMAND_QUEUE(sc, val) bus_space_write_4((sc)->twe_btag, (sc)->twe_bhandle, 0x8, (u_int32_t)val)
-#define TWE_RESPONSE_QUEUE(sc) (TWE_Response_Queue)bus_space_read_4((sc)->twe_btag, (sc)->twe_bhandle, 0xc)
+#define TWE_CONTROL(sc, val) bus_write_4((sc)->twe_io, 0x0, (u_int32_t)val)
+#define TWE_STATUS(sc) (u_int32_t)bus_read_4((sc)->twe_io, 0x4)
+#define TWE_COMMAND_QUEUE(sc, val) bus_write_4((sc)->twe_io, 0x8, (u_int32_t)val)
+#define TWE_RESPONSE_QUEUE(sc) (TWE_Response_Queue)bus_read_4((sc)->twe_io, 0xc)
/*
* FreeBSD-specific softc elements
@@ -79,8 +82,6 @@
device_t twe_dev; /* bus device */ \
struct cdev *twe_dev_t; /* control device */ \
struct resource *twe_io; /* register interface window */ \
- bus_space_handle_t twe_bhandle; /* bus space handle */ \
- bus_space_tag_t twe_btag; /* bus space tag */ \
bus_dma_tag_t twe_parent_dmat; /* parent DMA tag */ \
bus_dma_tag_t twe_buffer_dmat; /* data buffer DMA tag */ \
bus_dma_tag_t twe_cmd_dmat; /* command buffer DMA tag */ \
@@ -91,8 +92,8 @@
void *twe_cmd; /* command structures */ \
void *twe_immediate; /* immediate commands */ \
bus_dmamap_t twe_immediate_map; \
- struct sysctl_ctx_list sysctl_ctx; \
- struct sysctl_oid *sysctl_tree;
+ struct mtx twe_io_lock; \
+ struct sx twe_config_lock;
/*
* FreeBSD-specific request elements
@@ -107,31 +108,6 @@
#define twe_printf(sc, fmt, args...) device_printf(sc->twe_dev, fmt , ##args)
#define twed_printf(twed, fmt, args...) device_printf(twed->twed_dev, fmt , ##args)
-#if __FreeBSD_version < 500003
-# include <machine/clock.h>
-# define INTR_ENTROPY 0
-# define FREEBSD_4
-
-# include <sys/buf.h> /* old buf style */
-typedef struct buf twe_bio;
-typedef struct buf_queue_head twe_bioq;
-# define TWE_BIO_QINIT(bq) bufq_init(&bq);
-# define TWE_BIO_QINSERT(bq, bp) bufq_insert_tail(&bq, bp)
-# define TWE_BIO_QFIRST(bq) bufq_first(&bq)
-# define TWE_BIO_QREMOVE(bq, bp) bufq_remove(&bq, bp)
-# define TWE_BIO_IS_READ(bp) ((bp)->b_flags & B_READ)
-# define TWE_BIO_DATA(bp) (bp)->b_data
-# define TWE_BIO_LENGTH(bp) (bp)->b_bcount
-# define TWE_BIO_LBA(bp) (bp)->b_pblkno
-# define TWE_BIO_SOFTC(bp) (bp)->b_dev->si_drv1
-# define TWE_BIO_UNIT(bp) *(int *)((bp)->b_dev->si_drv2)
-# define TWE_BIO_SET_ERROR(bp, err) do { (bp)->b_error = err; (bp)->b_flags |= B_ERROR;} while(0)
-# define TWE_BIO_HAS_ERROR(bp) ((bp)->b_flags & B_ERROR)
-# define TWE_BIO_RESID(bp) (bp)->b_resid
-# define TWE_BIO_DONE(bp) biodone(bp)
-# define TWE_BIO_STATS_START(bp) devstat_start_transaction(&((struct twed_softc *)TWE_BIO_SOFTC(bp))->twed_stats)
-# define TWE_BIO_STATS_END(bp) devstat_end_transaction_buf(&((struct twed_softc *)TWE_BIO_SOFTC(bp))->twed_stats, bp)
-#else
# include <sys/bio.h>
# include <geom/geom_disk.h>
typedef struct bio twe_bio;
@@ -152,7 +128,13 @@
# define TWE_BIO_DONE(bp) biodone(bp)
# define TWE_BIO_STATS_START(bp)
# define TWE_BIO_STATS_END(bp)
-#endif
+
+#define TWE_IO_LOCK(sc) mtx_lock(&(sc)->twe_io_lock)
+#define TWE_IO_UNLOCK(sc) mtx_unlock(&(sc)->twe_io_lock)
+#define TWE_IO_ASSERT_LOCKED(sc) mtx_assert(&(sc)->twe_io_lock, MA_OWNED)
+#define TWE_CONFIG_LOCK(sc) sx_xlock(&(sc)->twe_config_lock)
+#define TWE_CONFIG_UNLOCK(sc) sx_xunlock(&(sc)->twe_config_lock)
+#define TWE_CONFIG_ASSERT_LOCKED(sc) sx_assert(&(sc)->twe_config_lock, SA_XLOCKED)
#endif /* FreeBSD */
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/twe/twe_freebsd.c
--- a/head/sys/dev/twe/twe_freebsd.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/twe/twe_freebsd.c Wed Aug 15 11:46:11 2012 +0300
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/twe/twe_freebsd.c 232854 2012-03-12 08:03:51Z scottl $");
+__FBSDID("$FreeBSD: head/sys/dev/twe/twe_freebsd.c 239244 2012-08-13 21:29:34Z jhb $");
/*
* FreeBSD-specific code.
@@ -69,7 +69,6 @@
static struct cdevsw twe_cdevsw = {
.d_version = D_VERSION,
- .d_flags = D_NEEDGIANT,
.d_open = twe_open,
.d_close = twe_close,
.d_ioctl = twe_ioctl_wrapper,
@@ -84,7 +83,13 @@
{
struct twe_softc *sc = (struct twe_softc *)dev->si_drv1;
+ TWE_IO_LOCK(sc);
+ if (sc->twe_state & TWE_STATE_DETACHING) {
+ TWE_IO_UNLOCK(sc);
+ return (ENXIO);
+ }
sc->twe_state |= TWE_STATE_OPEN;
+ TWE_IO_UNLOCK(sc);
return(0);
}
@@ -96,7 +101,9 @@
{
struct twe_softc *sc = (struct twe_softc *)dev->si_drv1;
+ TWE_IO_LOCK(sc);
sc->twe_state &= ~TWE_STATE_OPEN;
+ TWE_IO_UNLOCK(sc);
return (0);
}
@@ -172,8 +179,8 @@
twe_attach(device_t dev)
{
struct twe_softc *sc;
+ struct sysctl_oid *sysctl_tree;
int rid, error;
- u_int32_t command;
debug_called(4);
@@ -182,32 +189,30 @@
*/
sc = device_get_softc(dev);
sc->twe_dev = dev;
+ mtx_init(&sc->twe_io_lock, "twe I/O", NULL, MTX_DEF);
+ sx_init(&sc->twe_config_lock, "twe config");
- sysctl_ctx_init(&sc->sysctl_ctx);
- sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx,
+ /*
+ * XXX: This sysctl tree must stay at hw.tweX rather than using
+ * the device_get_sysctl_tree() created by new-bus because
+ * existing 3rd party binary tools such as tw_cli and 3dm2 use the
+ * existence of this sysctl node to discover controllers.
+ */
+ sysctl_tree = SYSCTL_ADD_NODE(device_get_sysctl_ctx(dev),
SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
device_get_nameunit(dev), CTLFLAG_RD, 0, "");
- if (sc->sysctl_tree == NULL) {
+ if (sysctl_tree == NULL) {
twe_printf(sc, "cannot add sysctl tree node\n");
return (ENXIO);
}
- SYSCTL_ADD_STRING(&sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree),
+ SYSCTL_ADD_STRING(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(sysctl_tree),
OID_AUTO, "driver_version", CTLFLAG_RD, TWE_DRIVER_VERSION_STRING, 0,
"TWE driver version");
/*
- * Make sure we are going to be able to talk to this board.
- */
- command = pci_read_config(dev, PCIR_COMMAND, 2);
- if ((command & PCIM_CMD_PORTEN) == 0) {
- twe_printf(sc, "register window not available\n");
- return(ENXIO);
- }
- /*
* Force the busmaster enable bit on, in case the BIOS forgot.
*/
- command |= PCIM_CMD_BUSMASTEREN;
- pci_write_config(dev, PCIR_COMMAND, command, 2);
+ pci_enable_busmaster(dev);
/*
* Allocate the PCI register window.
@@ -219,8 +224,6 @@
twe_free(sc);
return(ENXIO);
}
- sc->twe_btag = rman_get_bustag(sc->twe_io);
- sc->twe_bhandle = rman_get_bushandle(sc->twe_io);
/*
* Allocate the parent bus DMA tag appropriate for PCI.
@@ -251,7 +254,7 @@
twe_free(sc);
return(ENXIO);
}
- if (bus_setup_intr(sc->twe_dev, sc->twe_irq, INTR_TYPE_BIO | INTR_ENTROPY,
+ if (bus_setup_intr(sc->twe_dev, sc->twe_irq, INTR_TYPE_BIO | INTR_ENTROPY | INTR_MPSAFE,
NULL, twe_pci_intr, sc, &sc->twe_intr)) {
twe_printf(sc, "can't set up interrupt\n");
twe_free(sc);
@@ -302,7 +305,7 @@
BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
BUS_DMA_ALLOCNOW, /* flags */
busdma_lock_mutex, /* lockfunc */
- &Giant, /* lockarg */
+ &sc->twe_io_lock, /* lockarg */
&sc->twe_buffer_dmat)) {
twe_printf(sc, "can't allocate data buffer DMA tag\n");
twe_free(sc);
@@ -424,7 +427,8 @@
if (sc->twe_dev_t != (struct cdev *)NULL)
destroy_dev(sc->twe_dev_t);
- sysctl_ctx_free(&sc->sysctl_ctx);
+ sx_destroy(&sc->twe_config_lock);
+ mtx_destroy(&sc->twe_io_lock);
}
/********************************************************************************
@@ -434,27 +438,30 @@
twe_detach(device_t dev)
{
struct twe_softc *sc = device_get_softc(dev);
- int s, error;
debug_called(4);
- error = EBUSY;
- s = splbio();
- if (sc->twe_state & TWE_STATE_OPEN)
- goto out;
+ TWE_IO_LOCK(sc);
+ if (sc->twe_state & TWE_STATE_OPEN) {
+ TWE_IO_UNLOCK(sc);
+ return (EBUSY);
+ }
+ sc->twe_state |= TWE_STATE_DETACHING;
+ TWE_IO_UNLOCK(sc);
/*
* Shut the controller down.
*/
- if (twe_shutdown(dev))
- goto out;
+ if (twe_shutdown(dev)) {
+ TWE_IO_LOCK(sc);
+ sc->twe_state &= ~TWE_STATE_DETACHING;
+ TWE_IO_UNLOCK(sc);
+ return (EBUSY);
+ }
twe_free(sc);
- error = 0;
- out:
- splx(s);
- return(error);
+ return(0);
}
/********************************************************************************
@@ -467,30 +474,32 @@
twe_shutdown(device_t dev)
{
struct twe_softc *sc = device_get_softc(dev);
- int i, s, error = 0;
+ int i, error = 0;
debug_called(4);
- s = splbio();
-
/*
* Delete all our child devices.
*/
+ TWE_CONFIG_LOCK(sc);
for (i = 0; i < TWE_MAX_UNITS; i++) {
if (sc->twe_drive[i].td_disk != 0) {
- if ((error = twe_detach_drive(sc, i)) != 0)
- goto out;
+ if ((error = twe_detach_drive(sc, i)) != 0) {
+ TWE_CONFIG_UNLOCK(sc);
+ return (error);
+ }
}
}
+ TWE_CONFIG_UNLOCK(sc);
/*
* Bring the controller down.
*/
+ TWE_IO_LOCK(sc);
twe_deinit(sc);
+ TWE_IO_UNLOCK(sc);
-out:
- splx(s);
- return(error);
+ return(0);
}
/********************************************************************************
@@ -500,15 +509,14 @@
twe_suspend(device_t dev)
{
struct twe_softc *sc = device_get_softc(dev);
- int s;
debug_called(4);
- s = splbio();
+ TWE_IO_LOCK(sc);
sc->twe_state |= TWE_STATE_SUSPEND;
twe_disable_interrupts(sc);
- splx(s);
+ TWE_IO_UNLOCK(sc);
return(0);
}
@@ -523,8 +531,10 @@
debug_called(4);
+ TWE_IO_LOCK(sc);
sc->twe_state &= ~TWE_STATE_SUSPEND;
twe_enable_interrupts(sc);
+ TWE_IO_UNLOCK(sc);
return(0);
}
@@ -536,7 +546,11 @@
static void
twe_pci_intr(void *arg)
{
- twe_intr((struct twe_softc *)arg);
+ struct twe_softc *sc = arg;
+
+ TWE_IO_LOCK(sc);
+ twe_intr(sc);
+ TWE_IO_UNLOCK(sc);
}
/********************************************************************************
@@ -565,8 +579,10 @@
char buf[80];
int error;
+ mtx_lock(&Giant);
dr->td_disk = device_add_child(sc->twe_dev, NULL, -1);
if (dr->td_disk == NULL) {
+ mtx_unlock(&Giant);
twe_printf(sc, "Cannot add unit\n");
return (EIO);
}
@@ -582,7 +598,9 @@
twe_describe_code(twe_table_unitstate, dr->td_state & TWE_PARAM_UNITSTATUS_MASK));
device_set_desc_copy(dr->td_disk, buf);
- if ((error = bus_generic_attach(sc->twe_dev)) != 0) {
+ error = device_probe_and_attach(dr->td_disk);
+ mtx_unlock(&Giant);
+ if (error != 0) {
twe_printf(sc, "Cannot attach unit to controller. error = %d\n", error);
return (EIO);
}
@@ -599,7 +617,11 @@
{
int error = 0;
- if ((error = device_delete_child(sc->twe_dev, sc->twe_drive[unit].td_disk)) != 0) {
+ TWE_CONFIG_ASSERT_LOCKED(sc);
+ mtx_lock(&Giant);
+ error = device_delete_child(sc->twe_dev, sc->twe_drive[unit].td_disk);
+ mtx_unlock(&Giant);
+ if (error != 0) {
twe_printf(sc, "failed to delete unit %d\n", unit);
return(error);
}
@@ -671,10 +693,6 @@
* Disk device control interface.
*/
-#ifdef FREEBSD_4
-static int disks_registered = 0;
-#endif
-
/********************************************************************************
* Handle open from generic layer.
*
@@ -724,10 +742,12 @@
TWE_BIO_STATS_START(bp);
/* queue the bio on the controller */
+ TWE_IO_LOCK(sc->twed_controller);
twe_enqueue_bio(sc->twed_controller, bp);
/* poke the controller to start I/O */
twe_startio(sc->twed_controller);
+ TWE_IO_UNLOCK(sc->twed_controller);
return;
}
@@ -827,14 +847,9 @@
sc->twed_disk->d_fwsectors = sc->twed_drive->td_sectors;
sc->twed_disk->d_fwheads = sc->twed_drive->td_heads;
sc->twed_disk->d_unit = sc->twed_drive->td_sys_unit;
- sc->twed_disk->d_flags = DISKFLAG_NEEDSGIANT;
disk_create(sc->twed_disk, DISK_VERSION);
-#ifdef FREEBSD_4
- disks_registered++;
-#endif
-
/* set the maximum I/O size to the theoretical maximum allowed by the S/G list size */
return (0);
@@ -855,10 +870,6 @@
disk_destroy(sc->twed_disk);
-#ifdef FREEBSD_4
- if (--disks_registered == 0)
- cdevsw_remove(&tweddisk_cdevsw);
-#endif
return(0);
}
@@ -878,11 +889,7 @@
{
struct twe_request *tr;
- if ((tr = malloc(sizeof(struct twe_request), TWE_MALLOC_CLASS, M_WAITOK)) == NULL) {
- twe_printf(sc, "unable to allocate memory for tag %d\n", tag);
- return(NULL);
- }
- bzero(tr, sizeof(*tr));
+ tr = malloc(sizeof(struct twe_request), TWE_MALLOC_CLASS, M_WAITOK | M_ZERO);
tr->tr_sc = sc;
tr->tr_tag = tag;
if (bus_dmamap_create(sc->twe_buffer_dmat, 0, &tr->tr_dmamap)) {
@@ -1044,6 +1051,8 @@
debug_called(4);
+ if (!dumping)
+ TWE_IO_ASSERT_LOCKED(sc);
if (sc->twe_state & (TWE_STATE_CTLR_BUSY | TWE_STATE_FRZN)) {
twe_requeue_ready(tr);
return (EBUSY);
@@ -1101,6 +1110,8 @@
debug_called(4);
+ if (!dumping)
+ TWE_IO_ASSERT_LOCKED(sc);
bus_dmamap_sync(sc->twe_cmd_dmat, sc->twe_cmdmap, BUS_DMASYNC_POSTWRITE);
/*
@@ -1153,12 +1164,10 @@
twe_report(void)
{
struct twe_softc *sc;
- int i, s;
+ int i;
- s = splbio();
for (i = 0; (sc = devclass_get_softc(twe_devclass, i)) != NULL; i++)
twe_print_controller(sc);
printf("twed: total bio count in %u out %u\n", twed_bio_in, twed_bio_out);
- splx(s);
}
#endif
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/twe/twevar.h
--- a/head/sys/dev/twe/twevar.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/twe/twevar.h Wed Aug 15 11:46:11 2012 +0300
@@ -24,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/dev/twe/twevar.h 239244 2012-08-13 21:29:34Z jhb $
*/
#define TWE_DRIVER_VERSION_STRING "1.50.01.002"
@@ -134,6 +134,7 @@
#define TWE_STATE_SUSPEND (1<<3) /* controller is suspended */
#define TWE_STATE_FRZN (1<<4) /* got EINPROGRESS */
#define TWE_STATE_CTLR_BUSY (1<<5) /* controller cmd queue full */
+#define TWE_STATE_DETACHING (1<<6) /* controller is being shut down */
int twe_host_id;
struct twe_qstat twe_qstat[TWEQ_COUNT]; /* queue statistics */
@@ -209,46 +210,31 @@
static __inline void \
twe_enqueue_ ## name (struct twe_request *tr) \
{ \
- int s; \
- \
- s = splbio(); \
TAILQ_INSERT_TAIL(&tr->tr_sc->twe_ ## name, tr, tr_link); \
TWEQ_ADD(tr->tr_sc, index); \
- splx(s); \
} \
static __inline void \
twe_requeue_ ## name (struct twe_request *tr) \
{ \
- int s; \
- \
- s = splbio(); \
TAILQ_INSERT_HEAD(&tr->tr_sc->twe_ ## name, tr, tr_link); \
TWEQ_ADD(tr->tr_sc, index); \
- splx(s); \
} \
static __inline struct twe_request * \
twe_dequeue_ ## name (struct twe_softc *sc) \
{ \
struct twe_request *tr; \
- int s; \
\
- s = splbio(); \
if ((tr = TAILQ_FIRST(&sc->twe_ ## name)) != NULL) { \
TAILQ_REMOVE(&sc->twe_ ## name, tr, tr_link); \
TWEQ_REMOVE(sc, index); \
} \
- splx(s); \
return(tr); \
} \
static __inline void \
twe_remove_ ## name (struct twe_request *tr) \
{ \
- int s; \
- \
- s = splbio(); \
TAILQ_REMOVE(&tr->tr_sc->twe_ ## name, tr, tr_link); \
TWEQ_REMOVE(tr->tr_sc, index); \
- splx(s); \
}
TWEQ_REQUEST_QUEUE(free, TWEQ_FREE)
@@ -269,25 +255,18 @@
static __inline void
twe_enqueue_bio(struct twe_softc *sc, twe_bio *bp)
{
- int s;
-
- s = splbio();
TWE_BIO_QINSERT(sc->twe_bioq, bp);
TWEQ_ADD(sc, TWEQ_BIO);
- splx(s);
}
static __inline twe_bio *
twe_dequeue_bio(struct twe_softc *sc)
{
- int s;
twe_bio *bp;
- s = splbio();
if ((bp = TWE_BIO_QFIRST(sc->twe_bioq)) != NULL) {
TWE_BIO_QREMOVE(sc->twe_bioq, bp);
TWEQ_REMOVE(sc, TWEQ_BIO);
}
- splx(s);
return(bp);
}
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/uart/uart.h
--- a/head/sys/dev/uart/uart.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/uart/uart.h Wed Aug 15 11:46:11 2012 +0300
@@ -23,7 +23,7 @@
* (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$
+ * $FreeBSD: head/sys/dev/uart/uart.h 239278 2012-08-15 05:37:10Z gonzo $
*/
#ifndef _DEV_UART_H_
@@ -69,6 +69,7 @@
extern struct uart_class uart_sab82532_class __attribute__((weak));
extern struct uart_class uart_sbbc_class __attribute__((weak));
extern struct uart_class uart_z8530_class __attribute__((weak));
+extern struct uart_class uart_lpc_class __attribute__((weak));
#ifdef PC98
struct uart_class *uart_pc98_getdev(u_long port);
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/uart/uart_bus_fdt.c
--- a/head/sys/dev/uart/uart_bus_fdt.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/uart/uart_bus_fdt.c Wed Aug 15 11:46:11 2012 +0300
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/uart/uart_bus_fdt.c 228983 2011-12-30 03:57:17Z marcel $");
+__FBSDID("$FreeBSD: head/sys/dev/uart/uart_bus_fdt.c 239278 2012-08-15 05:37:10Z gonzo $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -100,12 +100,14 @@
pcell_t clock, shift;
int err;
- if (!ofw_bus_is_compatible(dev, "ns16550"))
+ sc = device_get_softc(dev);
+ if (ofw_bus_is_compatible(dev, "ns16550"))
+ sc->sc_class = &uart_ns8250_class;
+ else if (ofw_bus_is_compatible(dev, "lpc,uart"))
+ sc->sc_class = &uart_lpc_class;
+ else
return (ENXIO);
- sc = device_get_softc(dev);
- sc->sc_class = &uart_ns8250_class;
-
node = ofw_bus_get_node(dev);
if ((err = uart_fdt_get_clock(node, &clock)) != 0)
@@ -137,7 +139,7 @@
struct uart_class *class;
phandle_t node, chosen;
pcell_t shift, br, rclk;
- u_long start, size;
+ u_long start, size, pbase, psize;
int err;
uart_bus_space_mem = fdtbus_bs_tag;
@@ -180,7 +182,10 @@
/*
* Finalize configuration.
*/
- class = &uart_quicc_class;
+ if (fdt_is_compatible(node, "quicc"))
+ class = &uart_quicc_class;
+ if (fdt_is_compatible(node, "lpc"))
+ class = &uart_lpc_class;
if (fdt_is_compatible(node, "ns16550"))
class = &uart_ns8250_class;
@@ -197,7 +202,9 @@
err = fdt_regsize(node, &start, &size);
if (err)
return (ENXIO);
- start += fdt_immr_va;
+
+ fdt_get_range(OF_parent(node), 0, &pbase, &psize);
+ start += pbase;
return (bus_space_map(di->bas.bst, start, size, 0, &di->bas.bsh));
}
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/uart/uart_dev_lpc.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/uart/uart_dev_lpc.c Wed Aug 15 11:46:11 2012 +0300
@@ -0,0 +1,891 @@
+/*-
+ * Copyright (c) 2003 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/sys/dev/uart/uart_dev_lpc.c 239278 2012-08-15 05:37:10Z gonzo $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <machine/bus.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_cpu.h>
+#include <dev/uart/uart_bus.h>
+
+#include <dev/ic/ns16550.h>
+#include <arm/lpc/lpcreg.h>
+
+#include "uart_if.h"
+
+#define DEFAULT_RCLK (13 * 1000 * 1000)
+#define LPC_UART_NO(_bas) (((_bas->bsh) - LPC_UART_BASE) >> 15)
+
+#define lpc_ns8250_get_auxreg(_bas, _reg) \
+ bus_space_read_4((_bas)->bst, LPC_UART_CONTROL_BASE, _reg)
+#define lpc_ns8250_set_auxreg(_bas, _reg, _val) \
+ bus_space_write_4((_bas)->bst, LPC_UART_CONTROL_BASE, _reg, _val);
+#define lpc_ns8250_get_clkreg(_bas, _reg) \
+ bus_space_read_4((_bas)->bst, LPC_CLKPWR_BASE, (_reg))
+#define lpc_ns8250_set_clkreg(_bas, _reg, _val) \
+ bus_space_write_4((_bas)->bst, LPC_CLKPWR_BASE, (_reg), (_val))
+
+/*
+ * Clear pending interrupts. THRE is cleared by reading IIR. Data
+ * that may have been received gets lost here.
+ */
+static void
+lpc_ns8250_clrint(struct uart_bas *bas)
+{
+ uint8_t iir, lsr;
+
+ iir = uart_getreg(bas, REG_IIR);
+ while ((iir & IIR_NOPEND) == 0) {
+ iir &= IIR_IMASK;
+ if (iir == IIR_RLS) {
+ lsr = uart_getreg(bas, REG_LSR);
+ if (lsr & (LSR_BI|LSR_FE|LSR_PE))
+ (void)uart_getreg(bas, REG_DATA);
+ } else if (iir == IIR_RXRDY || iir == IIR_RXTOUT)
+ (void)uart_getreg(bas, REG_DATA);
+ else if (iir == IIR_MLSC)
+ (void)uart_getreg(bas, REG_MSR);
+ uart_barrier(bas);
+ iir = uart_getreg(bas, REG_IIR);
+ }
+}
+
+static int
+lpc_ns8250_delay(struct uart_bas *bas)
+{
+ uint32_t uclk;
+ int x, y;
+
+ uclk = lpc_ns8250_get_clkreg(bas, LPC_CLKPWR_UART_U5CLK);
+
+ x = (uclk >> 8) & 0xff;
+ y = uclk & 0xff;
+
+ return (16000000 / (bas->rclk * x / y));
+}
+
+static void
+lpc_ns8250_divisor(int rclk, int baudrate, int *x, int *y)
+{
+
+ switch (baudrate) {
+ case 2400:
+ *x = 1;
+ *y = 255;
+ return;
+ case 4800:
+ *x = 1;
+ *y = 169;
+ return;
+ case 9600:
+ *x = 3;
+ *y = 254;
+ return;
+ case 19200:
+ *x = 3;
+ *y = 127;
+ return;
+ case 38400:
+ *x = 6;
+ *y = 127;
+ return;
+ case 57600:
+ *x = 9;
+ *y = 127;
+ return;
+ default:
+ case 115200:
+ *x = 19;
+ *y = 134;
+ return;
+ case 230400:
+ *x = 19;
+ *y = 67;
+ return;
+ case 460800:
+ *x = 38;
+ *y = 67;
+ return;
+ }
+}
+
+static int
+lpc_ns8250_drain(struct uart_bas *bas, int what)
+{
+ int delay, limit;
+
+ delay = lpc_ns8250_delay(bas);
+
+ if (what & UART_DRAIN_TRANSMITTER) {
+ /*
+ * Pick an arbitrary high limit to avoid getting stuck in
+ * an infinite loop when the hardware is broken. Make the
+ * limit high enough to handle large FIFOs.
+ */
+ limit = 10*1024;
+ while ((uart_getreg(bas, REG_LSR) & LSR_TEMT) == 0 && --limit)
+ DELAY(delay);
+ if (limit == 0) {
+ /* printf("lpc_ns8250: transmitter appears stuck... "); */
+ return (EIO);
+ }
+ }
+
+ if (what & UART_DRAIN_RECEIVER) {
+ /*
+ * Pick an arbitrary high limit to avoid getting stuck in
+ * an infinite loop when the hardware is broken. Make the
+ * limit high enough to handle large FIFOs and integrated
+ * UARTs. The HP rx2600 for example has 3 UARTs on the
+ * management board that tend to get a lot of data send
+ * to it when the UART is first activated.
+ */
+ limit=10*4096;
+ while ((uart_getreg(bas, REG_LSR) & LSR_RXRDY) && --limit) {
+ (void)uart_getreg(bas, REG_DATA);
+ uart_barrier(bas);
+ DELAY(delay << 2);
+ }
+ if (limit == 0) {
+ /* printf("lpc_ns8250: receiver appears broken... "); */
+ return (EIO);
+ }
+ }
+
+ return (0);
+}
+
+/*
+ * We can only flush UARTs with FIFOs. UARTs without FIFOs should be
+ * drained. WARNING: this function clobbers the FIFO setting!
+ */
+static void
+lpc_ns8250_flush(struct uart_bas *bas, int what)
+{
+ uint8_t fcr;
+
+ fcr = FCR_ENABLE;
+ if (what & UART_FLUSH_TRANSMITTER)
+ fcr |= FCR_XMT_RST;
+ if (what & UART_FLUSH_RECEIVER)
+ fcr |= FCR_RCV_RST;
+ uart_setreg(bas, REG_FCR, fcr);
+ uart_barrier(bas);
+}
+
+static int
+lpc_ns8250_param(struct uart_bas *bas, int baudrate, int databits, int stopbits,
+ int parity)
+{
+ int xdiv, ydiv;
+ uint8_t lcr;
+
+ lcr = 0;
+ if (databits >= 8)
+ lcr |= LCR_8BITS;
+ else if (databits == 7)
+ lcr |= LCR_7BITS;
+ else if (databits == 6)
+ lcr |= LCR_6BITS;
+ else
+ lcr |= LCR_5BITS;
+ if (stopbits > 1)
+ lcr |= LCR_STOPB;
+ lcr |= parity << 3;
+
+ /* Set baudrate. */
+ if (baudrate > 0) {
+ uart_setreg(bas, REG_LCR, lcr | LCR_DLAB);
+ uart_barrier(bas);
+ uart_setreg(bas, REG_DLL, 0x00);
+ uart_setreg(bas, REG_DLH, 0x00);
+ uart_barrier(bas);
+
+ lpc_ns8250_divisor(bas->rclk, baudrate, &xdiv, &ydiv);
+ lpc_ns8250_set_clkreg(bas,
+ LPC_CLKPWR_UART_U5CLK,
+ LPC_CLKPWR_UART_UCLK_X(xdiv) |
+ LPC_CLKPWR_UART_UCLK_Y(ydiv));
+ }
+
+ /* Set LCR and clear DLAB. */
+ uart_setreg(bas, REG_LCR, lcr);
+ uart_barrier(bas);
+ return (0);
+}
+
+/*
+ * Low-level UART interface.
+ */
+static int lpc_ns8250_probe(struct uart_bas *bas);
+static void lpc_ns8250_init(struct uart_bas *bas, int, int, int, int);
+static void lpc_ns8250_term(struct uart_bas *bas);
+static void lpc_ns8250_putc(struct uart_bas *bas, int);
+static int lpc_ns8250_rxready(struct uart_bas *bas);
+static int lpc_ns8250_getc(struct uart_bas *bas, struct mtx *);
+
+static struct uart_ops uart_lpc_ns8250_ops = {
+ .probe = lpc_ns8250_probe,
+ .init = lpc_ns8250_init,
+ .term = lpc_ns8250_term,
+ .putc = lpc_ns8250_putc,
+ .rxready = lpc_ns8250_rxready,
+ .getc = lpc_ns8250_getc,
+};
+
+static int
+lpc_ns8250_probe(struct uart_bas *bas)
+{
+#if 0
+ u_char val;
+
+ /* Check known 0 bits that don't depend on DLAB. */
+ val = uart_getreg(bas, REG_IIR);
+ if (val & 0x30)
+ return (ENXIO);
+ /*
+ * Bit 6 of the MCR (= 0x40) appears to be 1 for the Sun1699
+ * chip, but otherwise doesn't seem to have a function. In
+ * other words, uart(4) works regardless. Ignore that bit so
+ * the probe succeeds.
+ */
+ val = uart_getreg(bas, REG_MCR);
+ if (val & 0xa0)
+ return (ENXIO);
+#endif
+ return (0);
+}
+
+static void
+lpc_ns8250_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
+ int parity)
+{
+ u_char ier;
+ u_long clkmode;
+
+ /* Enable UART clock */
+ clkmode = lpc_ns8250_get_auxreg(bas, LPC_UART_CLKMODE);
+ lpc_ns8250_set_auxreg(bas, LPC_UART_CLKMODE,
+ clkmode | LPC_UART_CLKMODE_UART5(1));
+#if 0
+ /* Work around H/W bug */
+ uart_setreg(bas, REG_DATA, 0x00);
+#endif
+ if (bas->rclk == 0)
+ bas->rclk = DEFAULT_RCLK;
+ lpc_ns8250_param(bas, baudrate, databits, stopbits, parity);
+
+ /* Disable all interrupt sources. */
+ /*
+ * We use 0xe0 instead of 0xf0 as the mask because the XScale PXA
+ * UARTs split the receive time-out interrupt bit out separately as
+ * 0x10. This gets handled by ier_mask and ier_rxbits below.
+ */
+ ier = uart_getreg(bas, REG_IER) & 0xe0;
+ uart_setreg(bas, REG_IER, ier);
+ uart_barrier(bas);
+
+ /* Disable the FIFO (if present). */
+ uart_setreg(bas, REG_FCR, 0);
+ uart_barrier(bas);
+
+ /* Set RTS & DTR. */
+ uart_setreg(bas, REG_MCR, MCR_IE | MCR_RTS | MCR_DTR);
+ uart_barrier(bas);
+
+ lpc_ns8250_clrint(bas);
+}
+
+static void
+lpc_ns8250_term(struct uart_bas *bas)
+{
+
+ /* Clear RTS & DTR. */
+ uart_setreg(bas, REG_MCR, MCR_IE);
+ uart_barrier(bas);
+}
+
+static void
+lpc_ns8250_putc(struct uart_bas *bas, int c)
+{
+ int limit;
+
+ limit = 250000;
+ while ((uart_getreg(bas, REG_LSR) & LSR_THRE) == 0 && --limit)
+ DELAY(4);
+ uart_setreg(bas, REG_DATA, c);
+ uart_barrier(bas);
+ limit = 250000;
+ while ((uart_getreg(bas, REG_LSR) & LSR_TEMT) == 0 && --limit)
+ DELAY(4);
+}
+
+static int
+lpc_ns8250_rxready(struct uart_bas *bas)
+{
+
+ return ((uart_getreg(bas, REG_LSR) & LSR_RXRDY) != 0 ? 1 : 0);
+}
+
+static int
+lpc_ns8250_getc(struct uart_bas *bas, struct mtx *hwmtx)
+{
+ int c;
+
+ uart_lock(hwmtx);
+
+ while ((uart_getreg(bas, REG_LSR) & LSR_RXRDY) == 0) {
+ uart_unlock(hwmtx);
+ DELAY(4);
+ uart_lock(hwmtx);
+ }
+
+ c = uart_getreg(bas, REG_DATA);
+
+ uart_unlock(hwmtx);
+
+ return (c);
+}
+
+/*
+ * High-level UART interface.
+ */
+struct lpc_ns8250_softc {
+ struct uart_softc base;
+ uint8_t fcr;
+ uint8_t ier;
+ uint8_t mcr;
+
+ uint8_t ier_mask;
+ uint8_t ier_rxbits;
+};
+
+static int lpc_ns8250_bus_attach(struct uart_softc *);
+static int lpc_ns8250_bus_detach(struct uart_softc *);
+static int lpc_ns8250_bus_flush(struct uart_softc *, int);
+static int lpc_ns8250_bus_getsig(struct uart_softc *);
+static int lpc_ns8250_bus_ioctl(struct uart_softc *, int, intptr_t);
+static int lpc_ns8250_bus_ipend(struct uart_softc *);
+static int lpc_ns8250_bus_param(struct uart_softc *, int, int, int, int);
+static int lpc_ns8250_bus_probe(struct uart_softc *);
+static int lpc_ns8250_bus_receive(struct uart_softc *);
+static int lpc_ns8250_bus_setsig(struct uart_softc *, int);
+static int lpc_ns8250_bus_transmit(struct uart_softc *);
+
+static kobj_method_t lpc_ns8250_methods[] = {
+ KOBJMETHOD(uart_attach, lpc_ns8250_bus_attach),
+ KOBJMETHOD(uart_detach, lpc_ns8250_bus_detach),
+ KOBJMETHOD(uart_flush, lpc_ns8250_bus_flush),
+ KOBJMETHOD(uart_getsig, lpc_ns8250_bus_getsig),
+ KOBJMETHOD(uart_ioctl, lpc_ns8250_bus_ioctl),
+ KOBJMETHOD(uart_ipend, lpc_ns8250_bus_ipend),
+ KOBJMETHOD(uart_param, lpc_ns8250_bus_param),
+ KOBJMETHOD(uart_probe, lpc_ns8250_bus_probe),
+ KOBJMETHOD(uart_receive, lpc_ns8250_bus_receive),
+ KOBJMETHOD(uart_setsig, lpc_ns8250_bus_setsig),
+ KOBJMETHOD(uart_transmit, lpc_ns8250_bus_transmit),
+ { 0, 0 }
+};
+
+struct uart_class uart_lpc_class = {
+ "lpc_ns8250",
+ lpc_ns8250_methods,
+ sizeof(struct lpc_ns8250_softc),
+ .uc_ops = &uart_lpc_ns8250_ops,
+ .uc_range = 8,
+ .uc_rclk = DEFAULT_RCLK
+};
+
+#define SIGCHG(c, i, s, d) \
+ if (c) { \
+ i |= (i & s) ? s : s | d; \
+ } else { \
+ i = (i & s) ? (i & ~s) | d : i; \
+ }
+
+static int
+lpc_ns8250_bus_attach(struct uart_softc *sc)
+{
+ struct lpc_ns8250_softc *lpc_ns8250 = (struct lpc_ns8250_softc*)sc;
+ struct uart_bas *bas;
+ unsigned int ivar;
+
+ bas = &sc->sc_bas;
+
+ lpc_ns8250->mcr = uart_getreg(bas, REG_MCR);
+ lpc_ns8250->fcr = FCR_ENABLE | FCR_DMA;
+ if (!resource_int_value("uart", device_get_unit(sc->sc_dev), "flags",
+ &ivar)) {
+ if (UART_FLAGS_FCR_RX_LOW(ivar))
+ lpc_ns8250->fcr |= FCR_RX_LOW;
+ else if (UART_FLAGS_FCR_RX_MEDL(ivar))
+ lpc_ns8250->fcr |= FCR_RX_MEDL;
+ else if (UART_FLAGS_FCR_RX_HIGH(ivar))
+ lpc_ns8250->fcr |= FCR_RX_HIGH;
+ else
+ lpc_ns8250->fcr |= FCR_RX_MEDH;
+ } else
+ lpc_ns8250->fcr |= FCR_RX_HIGH;
+
+ /* Get IER mask */
+ ivar = 0xf0;
+ resource_int_value("uart", device_get_unit(sc->sc_dev), "ier_mask",
+ &ivar);
+ lpc_ns8250->ier_mask = (uint8_t)(ivar & 0xff);
+
+ /* Get IER RX interrupt bits */
+ ivar = IER_EMSC | IER_ERLS | IER_ERXRDY;
+ resource_int_value("uart", device_get_unit(sc->sc_dev), "ier_rxbits",
+ &ivar);
+ lpc_ns8250->ier_rxbits = (uint8_t)(ivar & 0xff);
+
+ uart_setreg(bas, REG_FCR, lpc_ns8250->fcr);
+ uart_barrier(bas);
+ lpc_ns8250_bus_flush(sc, UART_FLUSH_RECEIVER|UART_FLUSH_TRANSMITTER);
+
+ if (lpc_ns8250->mcr & MCR_DTR)
+ sc->sc_hwsig |= SER_DTR;
+ if (lpc_ns8250->mcr & MCR_RTS)
+ sc->sc_hwsig |= SER_RTS;
+ lpc_ns8250_bus_getsig(sc);
+
+ lpc_ns8250_clrint(bas);
+ lpc_ns8250->ier = uart_getreg(bas, REG_IER) & lpc_ns8250->ier_mask;
+ lpc_ns8250->ier |= lpc_ns8250->ier_rxbits;
+ uart_setreg(bas, REG_IER, lpc_ns8250->ier);
+ uart_barrier(bas);
+
+ return (0);
+}
+
+static int
+lpc_ns8250_bus_detach(struct uart_softc *sc)
+{
+ struct lpc_ns8250_softc *lpc_ns8250;
+ struct uart_bas *bas;
+ u_char ier;
+
+ lpc_ns8250 = (struct lpc_ns8250_softc *)sc;
+ bas = &sc->sc_bas;
+ ier = uart_getreg(bas, REG_IER) & lpc_ns8250->ier_mask;
+ uart_setreg(bas, REG_IER, ier);
+ uart_barrier(bas);
+ lpc_ns8250_clrint(bas);
+ return (0);
+}
+
+static int
+lpc_ns8250_bus_flush(struct uart_softc *sc, int what)
+{
+ struct lpc_ns8250_softc *lpc_ns8250 = (struct lpc_ns8250_softc*)sc;
+ struct uart_bas *bas;
+ int error;
+
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+ if (sc->sc_rxfifosz > 1) {
+ lpc_ns8250_flush(bas, what);
+ uart_setreg(bas, REG_FCR, lpc_ns8250->fcr);
+ uart_barrier(bas);
+ error = 0;
+ } else
+ error = lpc_ns8250_drain(bas, what);
+ uart_unlock(sc->sc_hwmtx);
+ return (error);
+}
+
+static int
+lpc_ns8250_bus_getsig(struct uart_softc *sc)
+{
+ uint32_t new, old, sig;
+ uint8_t msr;
+
+ 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));
+ return (sig);
+}
+
+static int
+lpc_ns8250_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
+{
+ struct uart_bas *bas;
+ int baudrate, divisor, error;
+ uint8_t efr, lcr;
+
+ bas = &sc->sc_bas;
+ error = 0;
+ uart_lock(sc->sc_hwmtx);
+ switch (request) {
+ case UART_IOCTL_BREAK:
+ lcr = uart_getreg(bas, REG_LCR);
+ if (data)
+ lcr |= LCR_SBREAK;
+ else
+ lcr &= ~LCR_SBREAK;
+ uart_setreg(bas, REG_LCR, lcr);
+ uart_barrier(bas);
+ break;
+ case UART_IOCTL_IFLOW:
+ lcr = uart_getreg(bas, REG_LCR);
+ uart_barrier(bas);
+ uart_setreg(bas, REG_LCR, 0xbf);
+ uart_barrier(bas);
+ efr = uart_getreg(bas, REG_EFR);
+ if (data)
+ efr |= EFR_RTS;
+ else
+ efr &= ~EFR_RTS;
+ uart_setreg(bas, REG_EFR, efr);
+ uart_barrier(bas);
+ uart_setreg(bas, REG_LCR, lcr);
+ uart_barrier(bas);
+ break;
+ case UART_IOCTL_OFLOW:
+ lcr = uart_getreg(bas, REG_LCR);
+ uart_barrier(bas);
+ uart_setreg(bas, REG_LCR, 0xbf);
+ uart_barrier(bas);
+ efr = uart_getreg(bas, REG_EFR);
+ if (data)
+ efr |= EFR_CTS;
+ else
+ efr &= ~EFR_CTS;
+ uart_setreg(bas, REG_EFR, efr);
+ uart_barrier(bas);
+ uart_setreg(bas, REG_LCR, lcr);
+ uart_barrier(bas);
+ break;
+ case UART_IOCTL_BAUD:
+ lcr = uart_getreg(bas, REG_LCR);
+ uart_setreg(bas, REG_LCR, lcr | LCR_DLAB);
+ uart_barrier(bas);
+ divisor = uart_getreg(bas, REG_DLL) |
+ (uart_getreg(bas, REG_DLH) << 8);
+ uart_barrier(bas);
+ uart_setreg(bas, REG_LCR, lcr);
+ uart_barrier(bas);
+ baudrate = (divisor > 0) ? bas->rclk / divisor / 16 : 0;
+ if (baudrate > 0)
+ *(int*)data = baudrate;
+ else
+ error = ENXIO;
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ uart_unlock(sc->sc_hwmtx);
+ return (error);
+}
+
+static int
+lpc_ns8250_bus_ipend(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+ struct lpc_ns8250_softc *lpc_ns8250;
+ int ipend;
+ uint8_t iir, lsr;
+
+ lpc_ns8250 = (struct lpc_ns8250_softc *)sc;
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+ iir = uart_getreg(bas, REG_IIR);
+ if (iir & IIR_NOPEND) {
+ uart_unlock(sc->sc_hwmtx);
+ return (0);
+ }
+ ipend = 0;
+ if (iir & IIR_RXRDY) {
+ lsr = uart_getreg(bas, REG_LSR);
+ if (lsr & LSR_OE)
+ ipend |= SER_INT_OVERRUN;
+ if (lsr & LSR_BI)
+ ipend |= SER_INT_BREAK;
+ if (lsr & LSR_RXRDY)
+ ipend |= SER_INT_RXREADY;
+ } else {
+ if (iir & IIR_TXRDY) {
+ ipend |= SER_INT_TXIDLE;
+ uart_setreg(bas, REG_IER, lpc_ns8250->ier);
+ } else
+ ipend |= SER_INT_SIGCHG;
+ }
+ if (ipend == 0)
+ lpc_ns8250_clrint(bas);
+ uart_unlock(sc->sc_hwmtx);
+ return (ipend);
+}
+
+static int
+lpc_ns8250_bus_param(struct uart_softc *sc, int baudrate, int databits,
+ int stopbits, int parity)
+{
+ struct uart_bas *bas;
+ int error;
+
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+ error = lpc_ns8250_param(bas, baudrate, databits, stopbits, parity);
+ uart_unlock(sc->sc_hwmtx);
+ return (error);
+}
+
+static int
+lpc_ns8250_bus_probe(struct uart_softc *sc)
+{
+ struct lpc_ns8250_softc *lpc_ns8250;
+ struct uart_bas *bas;
+ int count, delay, error, limit;
+ uint8_t lsr, mcr, ier;
+
+ lpc_ns8250 = (struct lpc_ns8250_softc *)sc;
+ bas = &sc->sc_bas;
+
+ error = lpc_ns8250_probe(bas);
+ if (error)
+ return (error);
+
+ mcr = MCR_IE;
+ if (sc->sc_sysdev == NULL) {
+ /* By using lpc_ns8250_init() we also set DTR and RTS. */
+ lpc_ns8250_init(bas, 115200, 8, 1, UART_PARITY_NONE);
+ } else
+ mcr |= MCR_DTR | MCR_RTS;
+
+ error = lpc_ns8250_drain(bas, UART_DRAIN_TRANSMITTER);
+ if (error)
+ return (error);
+
+ /*
+ * Set loopback mode. This avoids having garbage on the wire and
+ * also allows us send and receive data. We set DTR and RTS to
+ * avoid the possibility that automatic flow-control prevents
+ * any data from being sent.
+ */
+ uart_setreg(bas, REG_MCR, MCR_LOOPBACK | MCR_IE | MCR_DTR | MCR_RTS);
+ uart_barrier(bas);
+
+ /*
+ * Enable FIFOs. And check that the UART has them. If not, we're
+ * done. Since this is the first time we enable the FIFOs, we reset
+ * them.
+ */
+ uart_setreg(bas, REG_FCR, FCR_ENABLE);
+ uart_barrier(bas);
+ if (!(uart_getreg(bas, REG_IIR) & IIR_FIFO_MASK)) {
+ /*
+ * NS16450 or INS8250. We don't bother to differentiate
+ * between them. They're too old to be interesting.
+ */
+ uart_setreg(bas, REG_MCR, mcr);
+ uart_barrier(bas);
+ sc->sc_rxfifosz = sc->sc_txfifosz = 1;
+ device_set_desc(sc->sc_dev, "8250 or 16450 or compatible");
+ return (0);
+ }
+
+ uart_setreg(bas, REG_FCR, FCR_ENABLE | FCR_XMT_RST | FCR_RCV_RST);
+ uart_barrier(bas);
+
+ count = 0;
+ delay = lpc_ns8250_delay(bas);
+
+ /* We have FIFOs. Drain the transmitter and receiver. */
+ error = lpc_ns8250_drain(bas, UART_DRAIN_RECEIVER|UART_DRAIN_TRANSMITTER);
+ if (error) {
+ uart_setreg(bas, REG_MCR, mcr);
+ uart_setreg(bas, REG_FCR, 0);
+ uart_barrier(bas);
+ goto done;
+ }
+
+ /*
+ * We should have a sufficiently clean "pipe" to determine the
+ * size of the FIFOs. We send as much characters as is reasonable
+ * and wait for the overflow bit in the LSR register to be
+ * asserted, counting the characters as we send them. Based on
+ * that count we know the FIFO size.
+ */
+ do {
+ uart_setreg(bas, REG_DATA, 0);
+ uart_barrier(bas);
+ count++;
+
+ limit = 30;
+ lsr = 0;
+ /*
+ * LSR bits are cleared upon read, so we must accumulate
+ * them to be able to test LSR_OE below.
+ */
+ while (((lsr |= uart_getreg(bas, REG_LSR)) & LSR_TEMT) == 0 &&
+ --limit)
+ DELAY(delay);
+ if (limit == 0) {
+ ier = uart_getreg(bas, REG_IER) & lpc_ns8250->ier_mask;
+ uart_setreg(bas, REG_IER, ier);
+ uart_setreg(bas, REG_MCR, mcr);
+ uart_setreg(bas, REG_FCR, 0);
+ uart_barrier(bas);
+ count = 0;
+ goto done;
+ }
+ } while ((lsr & LSR_OE) == 0 && count < 130);
+ count--;
+
+ uart_setreg(bas, REG_MCR, mcr);
+
+ /* Reset FIFOs. */
+ lpc_ns8250_flush(bas, UART_FLUSH_RECEIVER|UART_FLUSH_TRANSMITTER);
+
+done:
+ sc->sc_rxfifosz = 64;
+ device_set_desc(sc->sc_dev, "LPC32x0 UART with FIFOs");
+
+ /*
+ * Force the Tx FIFO size to 16 bytes for now. We don't program the
+ * Tx trigger. Also, we assume that all data has been sent when the
+ * interrupt happens.
+ */
+ sc->sc_txfifosz = 16;
+
+#if 0
+ /*
+ * XXX there are some issues related to hardware flow control and
+ * it's likely that uart(4) is the cause. This basicly needs more
+ * investigation, but we avoid using for hardware flow control
+ * until then.
+ */
+ /* 16650s or higher have automatic flow control. */
+ if (sc->sc_rxfifosz > 16) {
+ sc->sc_hwiflow = 1;
+ sc->sc_hwoflow = 1;
+ }
+#endif
+ return (0);
+}
+
+static int
+lpc_ns8250_bus_receive(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+ int xc;
+ uint8_t lsr;
+
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+ lsr = uart_getreg(bas, REG_LSR);
+ while (lsr & LSR_RXRDY) {
+ if (uart_rx_full(sc)) {
+ sc->sc_rxbuf[sc->sc_rxput] = UART_STAT_OVERRUN;
+ break;
+ }
+ xc = uart_getreg(bas, REG_DATA);
+ if (lsr & LSR_FE)
+ xc |= UART_STAT_FRAMERR;
+ if (lsr & LSR_PE)
+ xc |= UART_STAT_PARERR;
+ uart_rx_put(sc, xc);
+ lsr = uart_getreg(bas, REG_LSR);
+ }
+ /* Discard everything left in the Rx FIFO. */
+ while (lsr & LSR_RXRDY) {
+ (void)uart_getreg(bas, REG_DATA);
+ uart_barrier(bas);
+ lsr = uart_getreg(bas, REG_LSR);
+ }
+ uart_unlock(sc->sc_hwmtx);
+ return (0);
+}
+
+static int
+lpc_ns8250_bus_setsig(struct uart_softc *sc, int sig)
+{
+ struct lpc_ns8250_softc *lpc_ns8250 = (struct lpc_ns8250_softc*)sc;
+ struct uart_bas *bas;
+ uint32_t new, old;
+
+ bas = &sc->sc_bas;
+ do {
+ old = sc->sc_hwsig;
+ new = old;
+ if (sig & SER_DDTR) {
+ SIGCHG(sig & SER_DTR, new, SER_DTR,
+ SER_DDTR);
+ }
+ if (sig & SER_DRTS) {
+ SIGCHG(sig & SER_RTS, new, SER_RTS,
+ SER_DRTS);
+ }
+ } while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
+ uart_lock(sc->sc_hwmtx);
+ lpc_ns8250->mcr &= ~(MCR_DTR|MCR_RTS);
+ if (new & SER_DTR)
+ lpc_ns8250->mcr |= MCR_DTR;
+ if (new & SER_RTS)
+ lpc_ns8250->mcr |= MCR_RTS;
+ uart_setreg(bas, REG_MCR, lpc_ns8250->mcr);
+ uart_barrier(bas);
+ uart_unlock(sc->sc_hwmtx);
+ return (0);
+}
+
+static int
+lpc_ns8250_bus_transmit(struct uart_softc *sc)
+{
+ struct lpc_ns8250_softc *lpc_ns8250 = (struct lpc_ns8250_softc*)sc;
+ struct uart_bas *bas;
+ int i;
+
+ bas = &sc->sc_bas;
+ uart_lock(sc->sc_hwmtx);
+ while ((uart_getreg(bas, REG_LSR) & LSR_THRE) == 0)
+ ;
+ uart_setreg(bas, REG_IER, lpc_ns8250->ier | IER_ETXRDY);
+ uart_barrier(bas);
+ for (i = 0; i < sc->sc_txdatasz; i++) {
+ uart_setreg(bas, REG_DATA, sc->sc_txbuf[i]);
+ uart_barrier(bas);
+ }
+ sc->sc_txbusy = 1;
+ uart_unlock(sc->sc_hwmtx);
+ return (0);
+}
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/uart/uart_subr.c
--- a/head/sys/dev/uart/uart_subr.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/uart/uart_subr.c Wed Aug 15 11:46:11 2012 +0300
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/uart/uart_subr.c 228468 2011-12-13 13:32:56Z ed $");
+__FBSDID("$FreeBSD: head/sys/dev/uart/uart_subr.c 239278 2012-08-15 05:37:10Z gonzo $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -52,6 +52,7 @@
&uart_ns8250_class,
&uart_sab82532_class,
&uart_z8530_class,
+ &uart_lpc_class,
};
static size_t uart_nclasses = sizeof(uart_classes) / sizeof(uart_classes[0]);
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/controller/at91dci.c
--- a/head/sys/dev/usb/controller/at91dci.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/controller/at91dci.c Wed Aug 15 11:46:11 2012 +0300
@@ -1,5 +1,5 @@
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/controller/at91dci.c 233774 2012-04-02 10:50:42Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/controller/at91dci.c 239215 2012-08-12 19:58:56Z hselasky $");
/*-
* Copyright (c) 2007-2008 Hans Petter Selasky. All rights reserved.
@@ -1226,7 +1226,13 @@
}
static void
-at91dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
+at91dci_xfer_stall(struct usb_xfer *xfer)
+{
+ at91dci_device_done(xfer, USB_ERR_STALLED);
+}
+
+static void
+at91dci_set_stall(struct usb_device *udev,
struct usb_endpoint *ep, uint8_t *did_stall)
{
struct at91dci_softc *sc;
@@ -1237,10 +1243,6 @@
DPRINTFN(5, "endpoint=%p\n", ep);
- if (xfer) {
- /* cancel any ongoing transfers */
- at91dci_device_done(xfer, USB_ERR_STALLED);
- }
/* set FORCESTALL */
sc = AT9100_DCI_BUS2SC(udev->bus);
csr_reg = (ep->edesc->bEndpointAddress & UE_ADDR);
@@ -2332,6 +2334,7 @@
.xfer_unsetup = &at91dci_xfer_unsetup,
.get_hw_ep_profile = &at91dci_get_hw_ep_profile,
.set_stall = &at91dci_set_stall,
+ .xfer_stall = &at91dci_xfer_stall,
.clear_stall = &at91dci_clear_stall,
.roothub_exec = &at91dci_roothub_exec,
.xfer_poll = &at91dci_do_poll,
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/controller/atmegadci.c
--- a/head/sys/dev/usb/controller/atmegadci.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/controller/atmegadci.c Wed Aug 15 11:46:11 2012 +0300
@@ -1,5 +1,5 @@
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/controller/atmegadci.c 233774 2012-04-02 10:50:42Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/controller/atmegadci.c 239214 2012-08-12 17:53:06Z hselasky $");
/*-
* Copyright (c) 2009 Hans Petter Selasky. All rights reserved.
@@ -1113,7 +1113,13 @@
}
static void
-atmegadci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
+atmegadci_xfer_stall(struct usb_xfer *xfer)
+{
+ atmegadci_device_done(xfer, USB_ERR_STALLED);
+}
+
+static void
+atmegadci_set_stall(struct usb_device *udev,
struct usb_endpoint *ep, uint8_t *did_stall)
{
struct atmegadci_softc *sc;
@@ -1123,10 +1129,6 @@
DPRINTFN(5, "endpoint=%p\n", ep);
- if (xfer) {
- /* cancel any ongoing transfers */
- atmegadci_device_done(xfer, USB_ERR_STALLED);
- }
sc = ATMEGA_BUS2SC(udev->bus);
/* get endpoint number */
ep_no = (ep->edesc->bEndpointAddress & UE_ADDR);
@@ -2151,6 +2153,7 @@
.xfer_setup = &atmegadci_xfer_setup,
.xfer_unsetup = &atmegadci_xfer_unsetup,
.get_hw_ep_profile = &atmegadci_get_hw_ep_profile,
+ .xfer_stall = &atmegadci_xfer_stall,
.set_stall = &atmegadci_set_stall,
.clear_stall = &atmegadci_clear_stall,
.roothub_exec = &atmegadci_roothub_exec,
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/controller/avr32dci.c
--- a/head/sys/dev/usb/controller/avr32dci.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/controller/avr32dci.c Wed Aug 15 11:46:11 2012 +0300
@@ -1,5 +1,5 @@
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/controller/avr32dci.c 233774 2012-04-02 10:50:42Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/controller/avr32dci.c 239214 2012-08-12 17:53:06Z hselasky $");
/*-
* Copyright (c) 2009 Hans Petter Selasky. All rights reserved.
@@ -1080,7 +1080,13 @@
}
static void
-avr32dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
+avr32dci_xfer_stall(struct usb_xfer *xfer)
+{
+ avr32dci_device_done(xfer, USB_ERR_STALLED);
+}
+
+static void
+avr32dci_set_stall(struct usb_device *udev,
struct usb_endpoint *pipe, uint8_t *did_stall)
{
struct avr32dci_softc *sc;
@@ -1090,10 +1096,6 @@
DPRINTFN(5, "pipe=%p\n", pipe);
- if (xfer) {
- /* cancel any ongoing transfers */
- avr32dci_device_done(xfer, USB_ERR_STALLED);
- }
sc = AVR32_BUS2SC(udev->bus);
/* get endpoint number */
ep_no = (pipe->edesc->bEndpointAddress & UE_ADDR);
@@ -2096,6 +2098,7 @@
.xfer_setup = &avr32dci_xfer_setup,
.xfer_unsetup = &avr32dci_xfer_unsetup,
.get_hw_ep_profile = &avr32dci_get_hw_ep_profile,
+ .xfer_stall = &avr32dci_xfer_stall,
.set_stall = &avr32dci_set_stall,
.clear_stall = &avr32dci_clear_stall,
.roothub_exec = &avr32dci_roothub_exec,
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/controller/dotg.c
--- a/head/sys/dev/usb/controller/dotg.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/controller/dotg.c Wed Aug 15 11:46:11 2012 +0300
@@ -490,7 +490,7 @@
else if (hcint & HCINT_FRMOVRUN) {
td->qh->split_sc_frame = -1;
- WRITE4(sc, DOTG_HCINT(channel), hcchar | HCCHAR_CHDIS);
+ WRITE4(sc, DOTG_HCCHAR(channel), hcchar | HCCHAR_CHDIS);
dotg_complete_cb(DOTG_COMPLETE_FRAMEERR, 0, td);
}
@@ -657,11 +657,11 @@
return (EIO);
}
- SETFIELD32(sc, DOTG_GINTMSK, GINTMSK_SOFMSK, 1);
+ //SETFIELD32(sc, DOTG_GINTMSK, GINTMSK_SOFMSK, 1);
hcint = READ4(sc, DOTG_HCINT(td->channel));
WRITE4(sc, DOTG_HCINT(td->channel), hcint);
- WRITE4(sc, DOTG_HCINTMSK(td->channel), 0x7ff);
+// WRITE4(sc, DOTG_HCINTMSK(td->channel), HCINTMSK_ANY);
td->qh->this_xfersize = xfersize;
@@ -695,10 +695,11 @@
WRITEDMA(sc, td->channel,
(unsigned int *)(td->qh->fixup_phys + td->qh->fixup_off));
- WRITE4(sc, DOTG_HAINTMSK,
+ WRITE4(sc, DOTG_HAINTMSK,
(READ4(sc, DOTG_HAINTMSK) | (1<<td->channel)));
- WRITE4(sc, DOTG_HCINTMSK(td->channel),
+ WRITE4(sc, DOTG_HCINTMSK(td->channel),
HCINTMSK_CHHLTDMSK|HCINTMSK_AHBERRMSK);
+ WRITE4(sc, DOTG_HCINTMSK(td->channel), HCINTMSK_ANY);
WRITE4(sc, DOTG_HCSPLT(td->channel), hcsplt);
WRITE4(sc, DOTG_HCTSIZ(td->channel), hctsiz);
@@ -756,13 +757,13 @@
/* get softc */
sc = td->qh->sc;
-#ifdef USB_DEBUG
- if (dotgdebug) {
- DPRINTF("\n");
- hexdump((uint8_t *)MIPS_PHYS_TO_KSEG1(td->qh->fixup_phys),
- 8, 0, 0);
- }
-#endif
+//#ifdef USB_DEBUG
+// if (dotgdebug) {
+// DPRINTF("\n");
+// hexdump((uint8_t *)MIPS_PHYS_TO_KSEG1(td->qh->fixup_phys),
+// 8, 0, 0);
+// }
+//#endif
int ret = configure_channel(td, 8, HCTSIZ_PID_SETUP, HCCHAR_EPDIR_OUT);
if (ret != 0)
@@ -1034,9 +1035,9 @@
/*---------------------------------------------------------------*/
DPRINTF("+++++++++++++++++ rem=%d\n", rem);
-#ifdef USB_DEBUG
- if (dotgdebug == 0x0fffffff) hexdump((uint8_t *)MIPS_PHYS_TO_KSEG1(td->qh->fixup_phys), rem, 0, 0);
-#endif
+//#ifdef USB_DEBUG
+// if (dotgdebug == 0x0fffffff) hexdump((uint8_t *)MIPS_PHYS_TO_KSEG1(td->qh->fixup_phys), rem, 0, 0);
+//#endif
DPRINTF("\n");
int ret = configure_channel(td, rem, td->qh->ep_toggle_next?HCTSIZ_PID_DATA1:HCTSIZ_PID_DATA0, HCCHAR_EPDIR_OUT);
@@ -1100,9 +1101,9 @@
usb_pc_cpu_invalidate(td->qh->fixup_pc);
DPRINTF("\n");
-#ifdef USB_DEBUG
- if (dotgdebug == 0x0fffffff) hexdump((uint8_t *)MIPS_PHYS_TO_KSEG1(td->qh->fixup_phys), td->qh->fixup_actlen, 0, 0);
-#endif
+//#ifdef USB_DEBUG
+// if (dotgdebug == 0x0fffffff) hexdump((uint8_t *)MIPS_PHYS_TO_KSEG1(td->qh->fixup_phys), td->qh->fixup_actlen, 0, 0);
+//#endif
DPRINTF("\n");
/* verify transfer length */
@@ -1366,10 +1367,11 @@
uhub_root_intr(&sc->sc_bus, sc->sc_hub_idata, sizeof(sc->sc_hub_idata));
}
+
{
uint32_t haint = READ4(sc, DOTG_HAINT);
WRITE4(sc, DOTG_HAINT, haint);
- haint &= ((1<<sc->channels) - 1);
+ haint &= ((1 << sc->channels) - 1);
while (haint) {
int channel;
for (channel = 0; channel < sc->channels; channel ++)
@@ -1381,7 +1383,7 @@
}
- WRITE4(sc, DOTG_GINTSTS, gintsts);
+// WRITE4(sc, DOTG_GINTSTS, gintsts);
repeat:
TAILQ_FOREACH(xfer, &sc->sc_bus.intr_q.head, wait_entry) {
@@ -1517,8 +1519,8 @@
CP;
/* Enable interrupts */
tmp = READ4(sc, DOTG_GINTMSK);
-// tmp &= ~(GINTMSK_SOFMSK); ////
- tmp |= (GINTMSK_SOFMSK);
+// tmp |= (GINTMSK_SOFMSK);
+ tmp &= ~(GINTMSK_SOFMSK);
tmp |= (GINTMSK_OTGINTMSK | GINTMSK_MODEMISMSK | GINTMSK_HCHINTMSK);
WRITE4(sc, DOTG_GINTMSK, tmp);
@@ -2427,7 +2429,7 @@
if (usbd_transfer_setup_sub_malloc(
parm, &pc, sizeof(struct dotg_qh),
- USB_HOST_ALIGN, 1)) {
+ USB_HOST_ALIGN*4, 1)) { //XXX
parm->err = USB_ERR_NOMEM;
return;
}
@@ -2551,6 +2553,7 @@
static void
dotg_xfer_unsetup(struct usb_xfer *xfer)
{
+ return;
}
static void
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/controller/dotgreg.h
--- a/head/sys/dev/usb/controller/dotgreg.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/controller/dotgreg.h Wed Aug 15 11:46:11 2012 +0300
@@ -479,6 +479,17 @@
#define HCINTMSK_AHBERRMSK (1<<2)
#define HCINTMSK_CHHLTDMSK (1<<1)
#define HCINTMSK_XFERCOMPLMSK (1<<0)
+#define HCINTMSK_ANY (HCINTMSK_DATATGLERRMSK | \
+ HCINTMSK_FRMOVRUNMSK | \
+ HCINTMSK_BBLERRMSK | \
+ HCINTMSK_XACTERRMSK | \
+ HCINTMSK_NYETMSK | \
+ HCINTMSK_ACKMSK | \
+ HCINTMSK_NAKMSK | \
+ HCINTMSK_STALLMSK | \
+ HCINTMSK_AHBERRMSK | \
+ HCINTMSK_CHHLTDMSK | \
+ HCINTMSK_XFERCOMPLMSK)
#define HCTSIZ_DOPNG (1<<31)
#define HCTSIZ_PID_SHIFT 29
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/controller/dwc_otg.c
--- a/head/sys/dev/usb/controller/dwc_otg.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/controller/dwc_otg.c Wed Aug 15 11:46:11 2012 +0300
@@ -42,7 +42,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/controller/dwc_otg.c 233774 2012-04-02 10:50:42Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/controller/dwc_otg.c 239214 2012-08-12 17:53:06Z hselasky $");
#include <sys/stdint.h>
#include <sys/stddef.h>
@@ -1524,7 +1524,13 @@
}
static void
-dwc_otg_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
+dwc_otg_xfer_stall(struct usb_xfer *xfer)
+{
+ dwc_otg_device_done(xfer, USB_ERR_STALLED);
+}
+
+static void
+dwc_otg_set_stall(struct usb_device *udev,
struct usb_endpoint *ep, uint8_t *did_stall)
{
struct dwc_otg_softc *sc;
@@ -1534,10 +1540,6 @@
USB_BUS_LOCK_ASSERT(udev->bus, MA_OWNED);
- if (xfer) {
- /* cancel any ongoing transfers */
- dwc_otg_device_done(xfer, USB_ERR_STALLED);
- }
sc = DWC_OTG_BUS2SC(udev->bus);
/* get endpoint address */
@@ -2625,6 +2627,7 @@
.xfer_setup = &dwc_otg_xfer_setup,
.xfer_unsetup = &dwc_otg_xfer_unsetup,
.get_hw_ep_profile = &dwc_otg_get_hw_ep_profile,
+ .xfer_stall = &dwc_otg_xfer_stall,
.set_stall = &dwc_otg_set_stall,
.clear_stall = &dwc_otg_clear_stall,
.roothub_exec = &dwc_otg_roothub_exec,
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/controller/musb_otg.c
--- a/head/sys/dev/usb/controller/musb_otg.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/controller/musb_otg.c Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/controller/musb_otg.c 233774 2012-04-02 10:50:42Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/controller/musb_otg.c 239214 2012-08-12 17:53:06Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -1472,7 +1472,13 @@
}
static void
-musbotg_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
+musbotg_xfer_stall(struct usb_xfer *xfer)
+{
+ musbotg_device_done(xfer, USB_ERR_STALLED);
+}
+
+static void
+musbotg_set_stall(struct usb_device *udev,
struct usb_endpoint *ep, uint8_t *did_stall)
{
struct musbotg_softc *sc;
@@ -1482,10 +1488,6 @@
DPRINTFN(4, "endpoint=%p\n", ep);
- if (xfer) {
- /* cancel any ongoing transfers */
- musbotg_device_done(xfer, USB_ERR_STALLED);
- }
/* set FORCESTALL */
sc = MUSBOTG_BUS2SC(udev->bus);
@@ -2801,6 +2803,7 @@
.xfer_setup = &musbotg_xfer_setup,
.xfer_unsetup = &musbotg_xfer_unsetup,
.get_hw_ep_profile = &musbotg_get_hw_ep_profile,
+ .xfer_stall = &musbotg_xfer_stall,
.set_stall = &musbotg_set_stall,
.clear_stall = &musbotg_clear_stall,
.roothub_exec = &musbotg_roothub_exec,
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/controller/uss820dci.c
--- a/head/sys/dev/usb/controller/uss820dci.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/controller/uss820dci.c Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/controller/uss820dci.c 233774 2012-04-02 10:50:42Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/controller/uss820dci.c 239214 2012-08-12 17:53:06Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky <hselasky at FreeBSD.org>
* All rights reserved.
@@ -1210,7 +1210,13 @@
}
static void
-uss820dci_set_stall(struct usb_device *udev, struct usb_xfer *xfer,
+uss820dci_xfer_stall(struct usb_xfer *xfer)
+{
+ uss820dci_device_done(xfer, USB_ERR_STALLED);
+}
+
+static void
+uss820dci_set_stall(struct usb_device *udev,
struct usb_endpoint *ep, uint8_t *did_stall)
{
struct uss820dci_softc *sc;
@@ -1223,10 +1229,6 @@
DPRINTFN(5, "endpoint=%p\n", ep);
- if (xfer) {
- /* cancel any ongoing transfers */
- uss820dci_device_done(xfer, USB_ERR_STALLED);
- }
/* set FORCESTALL */
sc = USS820_DCI_BUS2SC(udev->bus);
ep_no = (ep->edesc->bEndpointAddress & UE_ADDR);
@@ -2385,6 +2387,7 @@
.xfer_setup = &uss820dci_xfer_setup,
.xfer_unsetup = &uss820dci_xfer_unsetup,
.get_hw_ep_profile = &uss820dci_get_hw_ep_profile,
+ .xfer_stall = &uss820dci_xfer_stall,
.set_stall = &uss820dci_set_stall,
.clear_stall = &uss820dci_clear_stall,
.roothub_exec = &uss820dci_roothub_exec,
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/controller/xhci.c
--- a/head/sys/dev/usb/controller/xhci.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/controller/xhci.c Wed Aug 15 11:46:11 2012 +0300
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/controller/xhci.c 234803 2012-04-29 17:12:33Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/controller/xhci.c 239214 2012-08-12 17:53:06Z hselasky $");
#include <sys/stdint.h>
#include <sys/stddef.h>
@@ -128,7 +128,7 @@
static usb_error_t xhci_configure_device(struct usb_device *);
static usb_error_t xhci_configure_endpoint(struct usb_device *,
struct usb_endpoint_descriptor *, uint64_t, uint16_t,
- uint8_t, uint8_t, uint8_t, uint16_t, uint16_t);
+ uint8_t, uint8_t, uint8_t, uint16_t, uint16_t, uint8_t);
static usb_error_t xhci_configure_mask(struct usb_device *,
uint32_t, uint8_t);
static usb_error_t xhci_cmd_evaluate_ctx(struct xhci_softc *,
@@ -1245,7 +1245,7 @@
&udev->ctrl_ep_desc);
err = xhci_configure_endpoint(udev,
&udev->ctrl_ep_desc, pepext->physaddr,
- 0, 1, 1, 0, mps, mps);
+ 0, 1, 1, 0, mps, mps, USB_EP_MODE_DEFAULT);
if (err != 0) {
DPRINTF("Could not configure default endpoint\n");
@@ -1800,7 +1800,8 @@
/* compute multiplier for ISOCHRONOUS transfers */
mult = xfer->endpoint->ecomp ?
- (xfer->endpoint->ecomp->bmAttributes & 3) : 0;
+ UE_GET_SS_ISO_MULT(xfer->endpoint->ecomp->bmAttributes)
+ : 0;
/* check for USB 2.0 multiplier */
if (mult == 0) {
mult = (xfer->endpoint->edesc->
@@ -2055,7 +2056,8 @@
xhci_configure_endpoint(struct usb_device *udev,
struct usb_endpoint_descriptor *edesc, uint64_t ring_addr,
uint16_t interval, uint8_t max_packet_count, uint8_t mult,
- uint8_t fps_shift, uint16_t max_packet_size, uint16_t max_frame_size)
+ uint8_t fps_shift, uint16_t max_packet_size,
+ uint16_t max_frame_size, uint8_t ep_mode)
{
struct usb_page_search buf_inp;
struct xhci_softc *sc = XHCI_BUS2SC(udev->bus);
@@ -2090,9 +2092,20 @@
if (mult == 0)
return (USB_ERR_BAD_BUFSIZE);
- temp = XHCI_EPCTX_0_EPSTATE_SET(0) |
- XHCI_EPCTX_0_MAXP_STREAMS_SET(0) |
- XHCI_EPCTX_0_LSA_SET(0);
+ if (ep_mode == USB_EP_MODE_STREAMS) {
+ temp = XHCI_EPCTX_0_EPSTATE_SET(0) |
+ XHCI_EPCTX_0_MAXP_STREAMS_SET(XHCI_MAX_STREAMS_LOG - 1) |
+ XHCI_EPCTX_0_LSA_SET(1);
+
+ ring_addr += sizeof(struct xhci_trb) *
+ XHCI_MAX_TRANSFERS * XHCI_MAX_STREAMS;
+ } else {
+ temp = XHCI_EPCTX_0_EPSTATE_SET(0) |
+ XHCI_EPCTX_0_MAXP_STREAMS_SET(0) |
+ XHCI_EPCTX_0_LSA_SET(0);
+
+ ring_addr |= XHCI_EPCTX_2_DCS_SET(1);
+ }
switch (udev->speed) {
case USB_SPEED_FULL:
@@ -2160,9 +2173,6 @@
temp |= XHCI_EPCTX_1_EPTYPE_SET(4);
xhci_ctx_set_le32(sc, &pinp->ctx_ep[epno - 1].dwEpCtx1, temp);
-
- ring_addr |= XHCI_EPCTX_2_DCS_SET(1);
-
xhci_ctx_set_le64(sc, &pinp->ctx_ep[epno - 1].qwEpCtx2, ring_addr);
switch (edesc->bmAttributes & UE_XFERTYPE) {
@@ -2195,21 +2205,42 @@
{
struct xhci_endpoint_ext *pepext;
struct usb_endpoint_ss_comp_descriptor *ecomp;
+ usb_stream_t x;
pepext = xhci_get_endpoint_ext(xfer->xroot->udev,
xfer->endpoint->edesc);
ecomp = xfer->endpoint->ecomp;
- pepext->trb[0].dwTrb3 = 0; /* halt any transfers */
+ for (x = 0; x != XHCI_MAX_STREAMS; x++) {
+ uint64_t temp;
+
+ /* halt any transfers */
+ pepext->trb[x * XHCI_MAX_TRANSFERS].dwTrb3 = 0;
+
+ /* compute start of TRB ring for stream "x" */
+ temp = pepext->physaddr +
+ (x * XHCI_MAX_TRANSFERS * sizeof(struct xhci_trb)) +
+ XHCI_SCTX_0_SCT_SEC_TR_RING;
+
+ /* make tree structure */
+ pepext->trb[(XHCI_MAX_TRANSFERS *
+ XHCI_MAX_STREAMS) + x].qwTrb0 = htole64(temp);
+
+ /* reserved fields */
+ pepext->trb[(XHCI_MAX_TRANSFERS *
+ XHCI_MAX_STREAMS) + x].dwTrb2 = 0;
+ pepext->trb[(XHCI_MAX_TRANSFERS *
+ XHCI_MAX_STREAMS) + x].dwTrb3 = 0;
+ }
usb_pc_cpu_flush(pepext->page_cache);
return (xhci_configure_endpoint(xfer->xroot->udev,
xfer->endpoint->edesc, pepext->physaddr,
xfer->interval, xfer->max_packet_count,
- (ecomp != NULL) ? (ecomp->bmAttributes & 3) + 1 : 1,
+ (ecomp != NULL) ? UE_GET_SS_ISO_MULT(ecomp->bmAttributes) + 1 : 1,
usbd_xfer_get_fps_shift(xfer), xfer->max_packet_size,
- xfer->max_frame_size));
+ xfer->max_frame_size, xfer->endpoint->ep_mode));
}
static usb_error_t
@@ -2500,7 +2531,8 @@
pc = &sc->sc_hw.devs[index].endpoint_pc;
- usbd_get_page(pc, (uintptr_t)&((struct xhci_dev_endpoint_trbs *)0)->trb[epno][0], &buf_ep);
+ usbd_get_page(pc, (uintptr_t)&((struct xhci_dev_endpoint_trbs *)0)->
+ trb[epno][0], &buf_ep);
pepext = &sc->sc_hw.devs[index].endp[epno];
pepext->page_cache = pc;
@@ -2539,7 +2571,7 @@
pepext = xhci_get_endpoint_ext(xfer->xroot->udev,
xfer->endpoint->edesc);
- pepext->trb_used--;
+ pepext->trb_used[xfer->stream_id]--;
pepext->xfer[xfer->qh_pos] = NULL;
@@ -2557,12 +2589,15 @@
struct xhci_td *td_last;
struct xhci_endpoint_ext *pepext;
uint64_t addr;
+ usb_stream_t id;
uint8_t i;
uint8_t inext;
uint8_t trb_limit;
DPRINTFN(8, "\n");
+ id = xfer->stream_id;
+
/* check if already inserted */
if (xfer->flags_int.bandwidth_reclaimed) {
DPRINTFN(8, "Already in schedule\n");
@@ -2588,7 +2623,7 @@
break;
}
- if (pepext->trb_used >= trb_limit) {
+ if (pepext->trb_used[id] >= trb_limit) {
DPRINTFN(8, "Too many TDs queued.\n");
return (USB_ERR_NOMEM);
}
@@ -2605,10 +2640,10 @@
return (0);
}
- pepext->trb_used++;
+ pepext->trb_used[id]++;
/* get current TRB index */
- i = pepext->trb_index;
+ i = pepext->trb_index[id];
/* get next TRB index */
inext = (i + 1);
@@ -2617,8 +2652,12 @@
if (inext >= (XHCI_MAX_TRANSFERS - 1))
inext = 0;
+ /* offset for stream */
+ i += id * XHCI_MAX_TRANSFERS;
+ inext += id * XHCI_MAX_TRANSFERS;
+
/* compute terminating return address */
- addr += inext * sizeof(struct xhci_trb);
+ addr += (inext * sizeof(struct xhci_trb));
/* update next pointer of last link TRB */
td_last->td_trb[td_last->ntrb].qwTrb0 = htole64(addr);
@@ -2662,7 +2701,7 @@
xfer->flags_int.bandwidth_reclaimed = 1;
- pepext->trb_index = inext;
+ pepext->trb_index[id] = inext;
xhci_endpoint_doorbell(xfer);
@@ -2750,12 +2789,12 @@
static void
xhci_device_generic_multi_enter(struct usb_endpoint *ep,
- struct usb_xfer *enter_xfer)
+ usb_stream_t stream_id, struct usb_xfer *enter_xfer)
{
struct usb_xfer *xfer;
/* check if there is a current transfer */
- xfer = ep->endpoint_q.curr;
+ xfer = ep->endpoint_q[stream_id].curr;
if (xfer == NULL)
return;
@@ -2767,7 +2806,7 @@
if (!xfer->flags_int.bandwidth_reclaimed)
return;
- xfer = TAILQ_FIRST(&ep->endpoint_q.head);
+ xfer = TAILQ_FIRST(&ep->endpoint_q[stream_id].head);
if (xfer == NULL) {
/*
* In case of enter we have to consider that the
@@ -2792,7 +2831,8 @@
/* setup TD's and QH */
xhci_setup_generic_chain(xfer);
- xhci_device_generic_multi_enter(xfer->endpoint, xfer);
+ xhci_device_generic_multi_enter(xfer->endpoint,
+ xfer->stream_id, xfer);
}
static void
@@ -2804,7 +2844,8 @@
xhci_transfer_insert(xfer);
/* try to multi buffer */
- xhci_device_generic_multi_enter(xfer->endpoint, NULL);
+ xhci_device_generic_multi_enter(xfer->endpoint,
+ xfer->stream_id, NULL);
/* add transfer last on interrupt queue */
usbd_transfer_enqueue(&xfer->xroot->bus->intr_q, xfer);
@@ -3465,6 +3506,7 @@
struct usb_endpoint_descriptor *edesc;
struct usb_page_cache *pcinp;
usb_error_t err;
+ usb_stream_t stream_id;
uint8_t index;
uint8_t epno;
@@ -3481,6 +3523,7 @@
edesc = xfer->endpoint->edesc;
epno = edesc->bEndpointAddress;
+ stream_id = xfer->stream_id;
if ((edesc->bmAttributes & UE_XFERTYPE) == UE_CONTROL)
epno |= UE_DIR_IN;
@@ -3516,8 +3559,10 @@
if (err != 0)
DPRINTF("Could not reset endpoint %u\n", epno);
- err = xhci_cmd_set_tr_dequeue_ptr(sc, pepext->physaddr |
- XHCI_EPCTX_2_DCS_SET(1), 0, epno, index);
+ err = xhci_cmd_set_tr_dequeue_ptr(sc,
+ (pepext->physaddr + (stream_id * sizeof(struct xhci_trb) *
+ XHCI_MAX_TRANSFERS)) | XHCI_EPCTX_2_DCS_SET(1),
+ stream_id, epno, index);
if (err != 0)
DPRINTF("Could not set dequeue ptr for endpoint %u\n", epno);
@@ -3615,7 +3660,8 @@
/* check if halted is still cleared */
if (pepext->trb_halted == 0) {
pepext->trb_running = 1;
- pepext->trb_index = 0;
+ memset(pepext->trb_index, 0,
+ sizeof(pepext->trb_index));
}
goto restart;
}
@@ -3639,7 +3685,8 @@
xhci_transfer_insert(xfer);
/* try to multi buffer */
- xhci_device_generic_multi_enter(xfer->endpoint, NULL);
+ xhci_device_generic_multi_enter(xfer->endpoint,
+ xfer->stream_id, NULL);
}
}
@@ -3946,6 +3993,23 @@
XHCI_CMD_UNLOCK(sc);
}
+static usb_error_t
+xhci_set_endpoint_mode(struct usb_device *udev, struct usb_endpoint *ep,
+ uint8_t ep_mode)
+{
+ switch (ep_mode) {
+ case USB_EP_MODE_DEFAULT:
+ return (0);
+ case USB_EP_MODE_STREAMS:
+ if ((ep->edesc->bmAttributes & UE_XFERTYPE) != UE_BULK ||
+ udev->speed != USB_SPEED_SUPER)
+ return (USB_ERR_INVAL);
+ return (0);
+ default:
+ return (USB_ERR_INVAL);
+ }
+}
+
struct usb_bus_methods xhci_bus_methods = {
.endpoint_init = xhci_ep_init,
.endpoint_uninit = xhci_ep_uninit,
@@ -3964,4 +4028,5 @@
.clear_stall = xhci_ep_clear_stall,
.device_state_change = xhci_device_state_change,
.set_hw_power_sleep = xhci_set_hw_power_sleep,
+ .set_endpoint_mode = xhci_set_endpoint_mode,
};
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/controller/xhci.h
--- a/head/sys/dev/usb/controller/xhci.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/controller/xhci.h Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/controller/xhci.h 229086 2011-12-31 13:34:42Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/controller/xhci.h 239214 2012-08-12 17:53:06Z hselasky $ */
/*-
* Copyright (c) 2010 Hans Petter Selasky. All rights reserved.
@@ -35,7 +35,15 @@
#define XHCI_MAX_COMMANDS (16 * 1)
#define XHCI_MAX_RSEG 1
#define XHCI_MAX_TRANSFERS 4
-
+#if USB_MAX_EP_STREAMS == 8
+#define XHCI_MAX_STREAMS 8
+#define XHCI_MAX_STREAMS_LOG 3
+#elif USB_MAX_EP_STREAMS == 1
+#define XHCI_MAX_STREAMS 1
+#define XHCI_MAX_STREAMS_LOG 0
+#else
+#error "The USB_MAX_EP_STREAMS value is not supported."
+#endif
#define XHCI_DEV_CTX_ADDR_ALIGN 64 /* bytes */
#define XHCI_DEV_CTX_ALIGN 64 /* bytes */
#define XHCI_INPUT_CTX_ALIGN 64 /* bytes */
@@ -307,7 +315,8 @@
} __aligned(4);
struct xhci_dev_endpoint_trbs {
- struct xhci_trb trb[XHCI_MAX_ENDPOINTS][XHCI_MAX_TRANSFERS];
+ struct xhci_trb trb[XHCI_MAX_ENDPOINTS]
+ [(XHCI_MAX_STREAMS * XHCI_MAX_TRANSFERS) + XHCI_MAX_STREAMS];
};
#define XHCI_TD_PAGE_NBUF 17 /* units, room enough for 64Kbytes */
@@ -353,11 +362,11 @@
struct xhci_endpoint_ext {
struct xhci_trb *trb;
- struct usb_xfer *xfer[XHCI_MAX_TRANSFERS - 1];
+ struct usb_xfer *xfer[XHCI_MAX_TRANSFERS * XHCI_MAX_STREAMS];
struct usb_page_cache *page_cache;
uint64_t physaddr;
- uint8_t trb_used;
- uint8_t trb_index;
+ uint8_t trb_used[XHCI_MAX_STREAMS];
+ uint8_t trb_index[XHCI_MAX_STREAMS];
uint8_t trb_halted;
uint8_t trb_running;
};
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/net/if_smsc.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/usb/net/if_smsc.c Wed Aug 15 11:46:11 2012 +0300
@@ -0,0 +1,1756 @@
+/*-
+ * Copyright (c) 2012
+ * Ben Gray <bgray at 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 ``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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/sys/dev/usb/net/if_smsc.c 239275 2012-08-15 04:03:55Z gonzo $");
+
+/*
+ * SMSC LAN9xxx devices (http://www.smsc.com/)
+ *
+ * The LAN9500 & LAN9500A devices are stand-alone USB to Ethernet chips that
+ * support USB 2.0 and 10/100 Mbps Ethernet.
+ *
+ * The LAN951x devices are an integrated USB hub and USB to Ethernet adapter.
+ * The driver only covers the Ethernet part, the standard USB hub driver
+ * supports the hub part.
+ *
+ * This driver is closely modelled on the Linux driver written and copyrighted
+ * by SMSC.
+ *
+ *
+ *
+ *
+ * H/W TCP & UDP Checksum Offloading
+ * ---------------------------------
+ * The chip supports both tx and rx offloading of UDP & TCP checksums, this
+ * feature can be dynamically enabled/disabled.
+ *
+ * RX checksuming is performed across bytes after the IPv4 header to the end of
+ * the Ethernet frame, this means if the frame is padded with non-zero values
+ * the H/W checksum will be incorrect, however the rx code compensates for this.
+ *
+ * TX checksuming is more complicated, the device requires a special header to
+ * be prefixed onto the start of the frame which indicates the start and end
+ * positions of the UDP or TCP frame. This requires the driver to manually
+ * go through the packet data and decode the headers prior to sending.
+ * On Linux they generally provide cues to the location of the csum and the
+ * area to calculate it over, on FreeBSD we seem to have to do it all ourselves,
+ * hence this is not as optimal and therefore h/w tX checksum is currently not
+ * implemented.
+ *
+ */
+#include <sys/stdint.h>
+#include <sys/stddef.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/condvar.h>
+#include <sys/sysctl.h>
+#include <sys/sx.h>
+#include <sys/unistd.h>
+#include <sys/callout.h>
+#include <sys/malloc.h>
+#include <sys/priv.h>
+#include <sys/random.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdi_util.h>
+#include "usbdevs.h"
+
+#define USB_DEBUG_VAR smsc_debug
+#include <dev/usb/usb_debug.h>
+#include <dev/usb/usb_process.h>
+
+#include <dev/usb/usb_device.h>
+#include <dev/usb/net/usb_ethernet.h>
+#include "if_smscreg.h"
+
+#ifdef USB_DEBUG
+static int smsc_debug = 0;
+
+SYSCTL_NODE(_hw_usb, OID_AUTO, smsc, CTLFLAG_RW, 0, "USB smsc");
+SYSCTL_INT(_hw_usb_smsc, OID_AUTO, debug, CTLFLAG_RW, &smsc_debug, 0,
+ "Debug level");
+#endif
+
+/*
+ * Various supported device vendors/products.
+ */
+static const struct usb_device_id smsc_devs[] = {
+#define SMSC_DEV(p,i) { USB_VPI(USB_VENDOR_SMC2, USB_PRODUCT_SMC2_##p, i) }
+ SMSC_DEV(LAN9514_ETH, 0),
+#undef SMSC_DEV
+};
+
+
+#ifdef USB_DEBUG
+#define smsc_dbg_printf(sc, fmt, args...) \
+ do { \
+ if (smsc_debug > 0) \
+ device_printf((sc)->sc_ue.ue_dev, "debug: " fmt, ##args); \
+ } while(0)
+#else
+#define smsc_dbg_printf(sc, fmt, args...)
+#endif
+
+#define smsc_warn_printf(sc, fmt, args...) \
+ device_printf((sc)->sc_ue.ue_dev, "warning: " fmt, ##args)
+
+#define smsc_err_printf(sc, fmt, args...) \
+ device_printf((sc)->sc_ue.ue_dev, "error: " fmt, ##args)
+
+
+#define ETHER_IS_ZERO(addr) \
+ (!(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]))
+
+#define ETHER_IS_VALID(addr) \
+ (!ETHER_IS_MULTICAST(addr) && !ETHER_IS_ZERO(addr))
+
+static device_probe_t smsc_probe;
+static device_attach_t smsc_attach;
+static device_detach_t smsc_detach;
+
+static usb_callback_t smsc_bulk_read_callback;
+static usb_callback_t smsc_bulk_write_callback;
+
+static miibus_readreg_t smsc_miibus_readreg;
+static miibus_writereg_t smsc_miibus_writereg;
+static miibus_statchg_t smsc_miibus_statchg;
+
+#if __FreeBSD_version > 1000000
+static int smsc_attach_post_sub(struct usb_ether *ue);
+#endif
+static uether_fn_t smsc_attach_post;
+static uether_fn_t smsc_init;
+static uether_fn_t smsc_stop;
+static uether_fn_t smsc_start;
+static uether_fn_t smsc_tick;
+static uether_fn_t smsc_setmulti;
+static uether_fn_t smsc_setpromisc;
+
+static int smsc_ifmedia_upd(struct ifnet *);
+static void smsc_ifmedia_sts(struct ifnet *, struct ifmediareq *);
+
+static int smsc_chip_init(struct smsc_softc *sc);
+static int smsc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
+
+static const struct usb_config smsc_config[SMSC_N_TRANSFER] = {
+
+ [SMSC_BULK_DT_WR] = {
+ .type = UE_BULK,
+ .endpoint = UE_ADDR_ANY,
+ .direction = UE_DIR_OUT,
+ .frames = 16,
+ .bufsize = 16 * (MCLBYTES + 16),
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .callback = smsc_bulk_write_callback,
+ .timeout = 10000, /* 10 seconds */
+ },
+
+ [SMSC_BULK_DT_RD] = {
+ .type = UE_BULK,
+ .endpoint = UE_ADDR_ANY,
+ .direction = UE_DIR_IN,
+ .bufsize = 20480, /* bytes */
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = smsc_bulk_read_callback,
+ .timeout = 0, /* no timeout */
+ },
+
+ /* The SMSC chip supports an interrupt endpoints, however they aren't
+ * needed as we poll on the MII status.
+ */
+};
+
+static const struct usb_ether_methods smsc_ue_methods = {
+ .ue_attach_post = smsc_attach_post,
+#if __FreeBSD_version > 1000000
+ .ue_attach_post_sub = smsc_attach_post_sub,
+#endif
+ .ue_start = smsc_start,
+ .ue_ioctl = smsc_ioctl,
+ .ue_init = smsc_init,
+ .ue_stop = smsc_stop,
+ .ue_tick = smsc_tick,
+ .ue_setmulti = smsc_setmulti,
+ .ue_setpromisc = smsc_setpromisc,
+ .ue_mii_upd = smsc_ifmedia_upd,
+ .ue_mii_sts = smsc_ifmedia_sts,
+};
+
+/**
+ * smsc_read_reg - Reads a 32-bit register on the device
+ * @sc: driver soft context
+ * @off: offset of the register
+ * @data: pointer a value that will be populated with the register value
+ *
+ * LOCKING:
+ * The device lock must be held before calling this function.
+ *
+ * RETURNS:
+ * 0 on success, a USB_ERR_?? error code on failure.
+ */
+static int
+smsc_read_reg(struct smsc_softc *sc, uint32_t off, uint32_t *data)
+{
+ struct usb_device_request req;
+ uint32_t buf;
+ usb_error_t err;
+
+ SMSC_LOCK_ASSERT(sc, MA_OWNED);
+
+ req.bmRequestType = UT_READ_VENDOR_DEVICE;
+ req.bRequest = SMSC_UR_READ_REG;
+ USETW(req.wValue, 0);
+ USETW(req.wIndex, off);
+ USETW(req.wLength, 4);
+
+ err = uether_do_request(&sc->sc_ue, &req, &buf, 1000);
+ if (err != 0)
+ smsc_warn_printf(sc, "Failed to read register 0x%0x\n", off);
+
+ *data = le32toh(buf);
+
+ return (err);
+}
+
+/**
+ * smsc_write_reg - Writes a 32-bit register on the device
+ * @sc: driver soft context
+ * @off: offset of the register
+ * @data: the 32-bit value to write into the register
+ *
+ * LOCKING:
+ * The device lock must be held before calling this function.
+ *
+ * RETURNS:
+ * 0 on success, a USB_ERR_?? error code on failure.
+ */
+static int
+smsc_write_reg(struct smsc_softc *sc, uint32_t off, uint32_t data)
+{
+ struct usb_device_request req;
+ uint32_t buf;
+ usb_error_t err;
+
+ SMSC_LOCK_ASSERT(sc, MA_OWNED);
+
+ buf = htole32(data);
+
+ req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req.bRequest = SMSC_UR_WRITE_REG;
+ USETW(req.wValue, 0);
+ USETW(req.wIndex, off);
+ USETW(req.wLength, 4);
+
+ err = uether_do_request(&sc->sc_ue, &req, &buf, 1000);
+ if (err != 0)
+ smsc_warn_printf(sc, "Failed to write register 0x%0x\n", off);
+
+ return (err);
+}
+
+/**
+ * smsc_wait_for_bits - Polls on a register value until bits are cleared
+ * @sc: soft context
+ * @reg: offset of the register
+ * @bits: if the bits are clear the function returns
+ *
+ * LOCKING:
+ * The device lock must be held before calling this function.
+ *
+ * RETURNS:
+ * 0 on success, or a USB_ERR_?? error code on failure.
+ */
+static int
+smsc_wait_for_bits(struct smsc_softc *sc, uint32_t reg, uint32_t bits)
+{
+ usb_ticks_t start_ticks;
+ usb_ticks_t max_ticks = USB_MS_TO_TICKS(1000);
+ uint32_t val;
+ int err;
+
+ SMSC_LOCK_ASSERT(sc, MA_OWNED);
+
+ start_ticks = (usb_ticks_t)ticks;
+ do {
+ if ((err = smsc_read_reg(sc, reg, &val)) != 0)
+ return (err);
+ if (!(val & bits))
+ return (0);
+
+ uether_pause(&sc->sc_ue, hz / 100);
+ } while ((ticks - start_ticks) < max_ticks);
+
+ return (USB_ERR_TIMEOUT);
+}
+
+/**
+ * smsc_eeprom_read - Reads the attached EEPROM
+ * @sc: soft context
+ * @off: the eeprom address offset
+ * @buf: stores the bytes
+ * @buflen: the number of bytes to read
+ *
+ * Simply reads bytes from an attached eeprom.
+ *
+ * LOCKING:
+ * The function takes and releases the device lock if it is not already held.
+ *
+ * RETURNS:
+ * 0 on success, or a USB_ERR_?? error code on failure.
+ */
+static int
+smsc_eeprom_read(struct smsc_softc *sc, uint16_t off, uint8_t *buf, uint16_t buflen)
+{
+ usb_ticks_t start_ticks;
+ usb_ticks_t max_ticks = USB_MS_TO_TICKS(1000);
+ int err;
+ int locked;
+ uint32_t val;
+ uint16_t i;
+
+ locked = mtx_owned(&sc->sc_mtx);
+ if (!locked)
+ SMSC_LOCK(sc);
+
+ err = smsc_wait_for_bits(sc, SMSC_EEPROM_CMD, SMSC_EEPROM_CMD_BUSY);
+ if (err != 0) {
+ smsc_warn_printf(sc, "eeprom busy, failed to read data\n");
+ goto done;
+ }
+
+ /* start reading the bytes, one at a time */
+ for (i = 0; i < buflen; i++) {
+
+ val = SMSC_EEPROM_CMD_BUSY | (SMSC_EEPROM_CMD_ADDR_MASK & (off + i));
+ if ((err = smsc_write_reg(sc, SMSC_EEPROM_CMD, val)) != 0)
+ goto done;
+
+ start_ticks = (usb_ticks_t)ticks;
+ do {
+ if ((err = smsc_read_reg(sc, SMSC_EEPROM_CMD, &val)) != 0)
+ goto done;
+ if (!(val & SMSC_EEPROM_CMD_BUSY) || (val & SMSC_EEPROM_CMD_TIMEOUT))
+ break;
+
+ uether_pause(&sc->sc_ue, hz / 100);
+ } while ((ticks - start_ticks) < max_ticks);
+
+ if (val & (SMSC_EEPROM_CMD_BUSY | SMSC_EEPROM_CMD_TIMEOUT)) {
+ smsc_warn_printf(sc, "eeprom command failed\n");
+ err = USB_ERR_IOERROR;
+ break;
+ }
+
+ if ((err = smsc_read_reg(sc, SMSC_EEPROM_DATA, &val)) != 0)
+ goto done;
+
+ buf[i] = (val & 0xff);
+ }
+
+done:
+ if (!locked)
+ SMSC_UNLOCK(sc);
+
+ return (err);
+}
+
+/**
+ * smsc_miibus_readreg - Reads a MII/MDIO register
+ * @dev: usb ether device
+ * @phy: the number of phy reading from
+ * @reg: the register address
+ *
+ * Attempts to read a phy register over the MII bus.
+ *
+ * LOCKING:
+ * Takes and releases the device mutex lock if not already held.
+ *
+ * RETURNS:
+ * Returns the 16-bits read from the MII register, if this function fails 0
+ * is returned.
+ */
+static int
+smsc_miibus_readreg(device_t dev, int phy, int reg)
+{
+ struct smsc_softc *sc = device_get_softc(dev);
+ int locked;
+ uint32_t addr;
+ uint32_t val = 0;
+
+ locked = mtx_owned(&sc->sc_mtx);
+ if (!locked)
+ SMSC_LOCK(sc);
+
+ if (smsc_wait_for_bits(sc, SMSC_MII_ADDR, SMSC_MII_BUSY) != 0) {
+ smsc_warn_printf(sc, "MII is busy\n");
+ goto done;
+ }
+
+ addr = (phy << 11) | (reg << 6) | SMSC_MII_READ;
+ smsc_write_reg(sc, SMSC_MII_ADDR, addr);
+
+ if (smsc_wait_for_bits(sc, SMSC_MII_ADDR, SMSC_MII_BUSY) != 0)
+ smsc_warn_printf(sc, "MII read timeout\n");
+
+ smsc_read_reg(sc, SMSC_MII_DATA, &val);
+ val = le32toh(val);
+
+done:
+ if (!locked)
+ SMSC_UNLOCK(sc);
+
+ return (val & 0xFFFF);
+}
+
+/**
+ * smsc_miibus_writereg - Writes a MII/MDIO register
+ * @dev: usb ether device
+ * @phy: the number of phy writing to
+ * @reg: the register address
+ * @val: the value to write
+ *
+ * Attempts to write a phy register over the MII bus.
+ *
+ * LOCKING:
+ * Takes and releases the device mutex lock if not already held.
+ *
+ * RETURNS:
+ * Always returns 0 regardless of success or failure.
+ */
+static int
+smsc_miibus_writereg(device_t dev, int phy, int reg, int val)
+{
+ struct smsc_softc *sc = device_get_softc(dev);
+ int locked;
+ uint32_t addr;
+
+ if (sc->sc_phyno != phy)
+ return (0);
+
+ locked = mtx_owned(&sc->sc_mtx);
+ if (!locked)
+ SMSC_LOCK(sc);
+
+ if (smsc_wait_for_bits(sc, SMSC_MII_ADDR, SMSC_MII_BUSY) != 0) {
+ smsc_warn_printf(sc, "MII is busy\n");
+ goto done;
+ }
+
+ val = htole32(val);
+ smsc_write_reg(sc, SMSC_MII_DATA, val);
+
+ addr = (phy << 11) | (reg << 6) | SMSC_MII_WRITE;
+ smsc_write_reg(sc, SMSC_MII_ADDR, addr);
+
+ if (smsc_wait_for_bits(sc, SMSC_MII_ADDR, SMSC_MII_BUSY) != 0)
+ smsc_warn_printf(sc, "MII write timeout\n");
+
+done:
+ if (!locked)
+ SMSC_UNLOCK(sc);
+ return (0);
+}
+
+
+
+/**
+ * smsc_miibus_statchg - Called to detect phy status change
+ * @dev: usb ether device
+ *
+ * This function is called periodically by the system to poll for status
+ * changes of the link.
+ *
+ * LOCKING:
+ * Takes and releases the device mutex lock if not already held.
+ */
+static void
+smsc_miibus_statchg(device_t dev)
+{
+ struct smsc_softc *sc = device_get_softc(dev);
+ struct mii_data *mii = uether_getmii(&sc->sc_ue);
+ struct ifnet *ifp;
+ int locked;
+ int err;
+ uint32_t flow;
+ uint32_t afc_cfg;
+
+ locked = mtx_owned(&sc->sc_mtx);
+ if (!locked)
+ SMSC_LOCK(sc);
+
+ ifp = uether_getifp(&sc->sc_ue);
+ if (mii == NULL || ifp == NULL ||
+ (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ goto done;
+
+ /* Use the MII status to determine link status */
+ sc->sc_flags &= ~SMSC_FLAG_LINK;
+ if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) ==
+ (IFM_ACTIVE | IFM_AVALID)) {
+ switch (IFM_SUBTYPE(mii->mii_media_active)) {
+ case IFM_10_T:
+ case IFM_100_TX:
+ sc->sc_flags |= SMSC_FLAG_LINK;
+ break;
+ case IFM_1000_T:
+ /* Gigabit ethernet not supported by chipset */
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* Lost link, do nothing. */
+ if ((sc->sc_flags & SMSC_FLAG_LINK) == 0) {
+ smsc_dbg_printf(sc, "link flag not set\n");
+ goto done;
+ }
+
+ err = smsc_read_reg(sc, SMSC_AFC_CFG, &afc_cfg);
+ if (err) {
+ smsc_warn_printf(sc, "failed to read initial AFC_CFG, error %d\n", err);
+ goto done;
+ }
+
+ /* Enable/disable full duplex operation and TX/RX pause */
+ if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) {
+ smsc_dbg_printf(sc, "full duplex operation\n");
+ sc->sc_mac_csr &= ~SMSC_MAC_CSR_RCVOWN;
+ sc->sc_mac_csr |= SMSC_MAC_CSR_FDPX;
+
+ if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_RXPAUSE) != 0)
+ flow = 0xffff0002;
+ else
+ flow = 0;
+
+ if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_TXPAUSE) != 0)
+ afc_cfg |= 0xf;
+ else
+ afc_cfg &= ~0xf;
+
+ } else {
+ smsc_dbg_printf(sc, "half duplex operation\n");
+ sc->sc_mac_csr &= ~SMSC_MAC_CSR_FDPX;
+ sc->sc_mac_csr |= SMSC_MAC_CSR_RCVOWN;
+
+ flow = 0;
+ afc_cfg |= 0xf;
+ }
+
+ err = smsc_write_reg(sc, SMSC_MAC_CSR, sc->sc_mac_csr);
+ err += smsc_write_reg(sc, SMSC_FLOW, flow);
+ err += smsc_write_reg(sc, SMSC_AFC_CFG, afc_cfg);
+ if (err)
+ smsc_warn_printf(sc, "media change failed, error %d\n", err);
+
+done:
+ if (!locked)
+ SMSC_UNLOCK(sc);
+}
+
+/**
+ * smsc_ifmedia_upd - Set media options
+ * @ifp: interface pointer
+ *
+ * Basically boilerplate code that simply calls the mii functions to set the
+ * media options.
+ *
+ * LOCKING:
+ * The device lock must be held before this function is called.
+ *
+ * RETURNS:
+ * Returns 0 on success or a negative error code.
+ */
+static int
+smsc_ifmedia_upd(struct ifnet *ifp)
+{
+ struct smsc_softc *sc = ifp->if_softc;
+ struct mii_data *mii = uether_getmii(&sc->sc_ue);
+ int err;
+
+ SMSC_LOCK_ASSERT(sc, MA_OWNED);
+
+ if (mii->mii_instance) {
+ struct mii_softc *miisc;
+
+ LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
+ mii_phy_reset(miisc);
+ }
+ err = mii_mediachg(mii);
+ return (err);
+}
+
+/**
+ * smsc_ifmedia_sts - Report current media status
+ * @ifp: inet interface pointer
+ * @ifmr: interface media request
+ *
+ * Basically boilerplate code that simply calls the mii functions to get the
+ * media status.
+ *
+ * LOCKING:
+ * Internally takes and releases the device lock.
+ */
+static void
+smsc_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+ struct smsc_softc *sc = ifp->if_softc;
+ struct mii_data *mii = uether_getmii(&sc->sc_ue);
+
+ SMSC_LOCK(sc);
+
+ mii_pollstat(mii);
+
+ SMSC_UNLOCK(sc);
+
+ ifmr->ifm_active = mii->mii_media_active;
+ ifmr->ifm_status = mii->mii_media_status;
+}
+
+/**
+ * smsc_hash - Calculate the hash of a mac address
+ * @addr: The mac address to calculate the hash on
+ *
+ * This function is used when configuring a range of m'cast mac addresses to
+ * filter on. The hash of the mac address is put in the device's mac hash
+ * table.
+ *
+ * RETURNS:
+ * Returns a value from 0-63 value which is the hash of the mac address.
+ */
+static inline uint32_t
+smsc_hash(uint8_t addr[ETHER_ADDR_LEN])
+{
+ return (ether_crc32_be(addr, ETHER_ADDR_LEN) >> 26) & 0x3f;
+}
+
+/**
+ * smsc_setmulti - Setup multicast
+ * @ue: usb ethernet device context
+ *
+ * Tells the device to either accept frames with a multicast mac address, a
+ * select group of m'cast mac addresses or just the devices mac address.
+ *
+ * LOCKING:
+ * Should be called with the SMSC lock held.
+ */
+static void
+smsc_setmulti(struct usb_ether *ue)
+{
+ struct smsc_softc *sc = uether_getsc(ue);
+ struct ifnet *ifp = uether_getifp(ue);
+ struct ifmultiaddr *ifma;
+ uint32_t hashtbl[2] = { 0, 0 };
+ uint32_t hash;
+
+ SMSC_LOCK_ASSERT(sc, MA_OWNED);
+
+ if (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) {
+ smsc_dbg_printf(sc, "receive all multicast enabled\n");
+ sc->sc_mac_csr |= SMSC_MAC_CSR_MCPAS;
+ sc->sc_mac_csr &= ~SMSC_MAC_CSR_HPFILT;
+
+ } else {
+ /* Take the lock of the mac address list before hashing each of them */
+ if_maddr_rlock(ifp);
+
+ if (!TAILQ_EMPTY(&ifp->if_multiaddrs)) {
+ /* We are filtering on a set of address so calculate hashes of each
+ * of the address and set the corresponding bits in the register.
+ */
+ sc->sc_mac_csr |= SMSC_MAC_CSR_HPFILT;
+ sc->sc_mac_csr &= ~(SMSC_MAC_CSR_PRMS | SMSC_MAC_CSR_MCPAS);
+
+ TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+ if (ifma->ifma_addr->sa_family != AF_LINK)
+ continue;
+
+ hash = smsc_hash(LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
+ hashtbl[hash >> 5] |= 1 << (hash & 0x1F);
+ }
+ } else {
+ /* Only receive packets with destination set to our mac address */
+ sc->sc_mac_csr &= ~(SMSC_MAC_CSR_MCPAS | SMSC_MAC_CSR_HPFILT);
+ }
+
+ if_maddr_runlock(ifp);
+
+ /* Debug */
+ if (sc->sc_mac_csr & SMSC_MAC_CSR_HPFILT)
+ smsc_dbg_printf(sc, "receive select group of macs\n");
+ else
+ smsc_dbg_printf(sc, "receive own packets only\n");
+ }
+
+ /* Write the hash table and mac control registers */
+ smsc_write_reg(sc, SMSC_HASHH, hashtbl[1]);
+ smsc_write_reg(sc, SMSC_HASHL, hashtbl[0]);
+ smsc_write_reg(sc, SMSC_MAC_CSR, sc->sc_mac_csr);
+}
+
+
+/**
+ * smsc_setpromisc - Enables/disables promiscuous mode
+ * @ue: usb ethernet device context
+ *
+ * LOCKING:
+ * Should be called with the SMSC lock held.
+ */
+static void
+smsc_setpromisc(struct usb_ether *ue)
+{
+ struct smsc_softc *sc = uether_getsc(ue);
+ struct ifnet *ifp = uether_getifp(ue);
+
+ smsc_dbg_printf(sc, "promiscuous mode %sabled\n",
+ (ifp->if_flags & IFF_PROMISC) ? "en" : "dis");
+
+ SMSC_LOCK_ASSERT(sc, MA_OWNED);
+
+ if (ifp->if_flags & IFF_PROMISC)
+ sc->sc_mac_csr |= SMSC_MAC_CSR_PRMS;
+ else
+ sc->sc_mac_csr &= ~SMSC_MAC_CSR_PRMS;
+
+ smsc_write_reg(sc, SMSC_MAC_CSR, sc->sc_mac_csr);
+}
+
+
+/**
+ * smsc_sethwcsum - Enable or disable H/W UDP and TCP checksumming
+ * @sc: driver soft context
+ *
+ * LOCKING:
+ * Should be called with the SMSC lock held.
+ *
+ * RETURNS:
+ * Returns 0 on success or a negative error code.
+ */
+static int smsc_sethwcsum(struct smsc_softc *sc)
+{
+ struct ifnet *ifp = uether_getifp(&sc->sc_ue);
+ uint32_t val;
+ int err;
+
+ if (!ifp)
+ return (-EIO);
+
+ SMSC_LOCK_ASSERT(sc, MA_OWNED);
+
+ err = smsc_read_reg(sc, SMSC_COE_CTRL, &val);
+ if (err != 0) {
+ smsc_warn_printf(sc, "failed to read SMSC_COE_CTRL (err=%d)\n", err);
+ return (err);
+ }
+
+ /* Enable/disable the Rx checksum */
+ if ((ifp->if_capabilities & ifp->if_capenable) & IFCAP_RXCSUM)
+ val |= SMSC_COE_CTRL_RX_EN;
+ else
+ val &= ~SMSC_COE_CTRL_RX_EN;
+
+ /* Enable/disable the Tx checksum (currently not supported) */
+ if ((ifp->if_capabilities & ifp->if_capenable) & IFCAP_TXCSUM)
+ val |= SMSC_COE_CTRL_TX_EN;
+ else
+ val &= ~SMSC_COE_CTRL_TX_EN;
+
+ err = smsc_write_reg(sc, SMSC_COE_CTRL, val);
+ if (err != 0) {
+ smsc_warn_printf(sc, "failed to write SMSC_COE_CTRL (err=%d)\n", err);
+ return (err);
+ }
+
+ return (0);
+}
+
+
+/**
+ * smsc_setmacaddress - Sets the mac address in the device
+ * @sc: driver soft context
+ * @addr: pointer to array contain at least 6 bytes of the mac
+ *
+ * Writes the MAC address into the device, usually the MAC is programmed with
+ * values from the EEPROM.
+ *
+ * LOCKING:
+ * Should be called with the SMSC lock held.
+ *
+ * RETURNS:
+ * Returns 0 on success or a negative error code.
+ */
+static int
+smsc_setmacaddress(struct smsc_softc *sc, const uint8_t *addr)
+{
+ int err;
+ uint32_t val;
+
+ smsc_dbg_printf(sc, "setting mac address to %02x:%02x:%02x:%02x:%02x:%02x\n",
+ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+
+ SMSC_LOCK_ASSERT(sc, MA_OWNED);
+
+ val = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
+ if ((err = smsc_write_reg(sc, SMSC_MAC_ADDRL, val)) != 0)
+ goto done;
+
+ val = (addr[5] << 8) | addr[4];
+ err = smsc_write_reg(sc, SMSC_MAC_ADDRH, val);
+
+done:
+ return (err);
+}
+
+/**
+ * smsc_reset - Reset the SMSC chip
+ * @sc: device soft context
+ *
+ * LOCKING:
+ * Should be called with the SMSC lock held.
+ */
+static void
+smsc_reset(struct smsc_softc *sc)
+{
+ struct usb_config_descriptor *cd;
+ usb_error_t err;
+
+ cd = usbd_get_config_descriptor(sc->sc_ue.ue_udev);
+
+ err = usbd_req_set_config(sc->sc_ue.ue_udev, &sc->sc_mtx,
+ cd->bConfigurationValue);
+ if (err)
+ smsc_warn_printf(sc, "reset failed (ignored)\n");
+
+ /* Wait a little while for the chip to get its brains in order. */
+ uether_pause(&sc->sc_ue, hz / 100);
+
+ /* Reinitialize controller to achieve full reset. */
+ smsc_chip_init(sc);
+}
+
+
+/**
+ * smsc_init - Initialises the LAN95xx chip
+ * @ue: USB ether interface
+ *
+ * Called when the interface is brought up (i.e. ifconfig ue0 up), this
+ * initialise the interface and the rx/tx pipes.
+ *
+ * LOCKING:
+ * Should be called with the SMSC lock held.
+ */
+static void
+smsc_init(struct usb_ether *ue)
+{
+ struct smsc_softc *sc = uether_getsc(ue);
+ struct ifnet *ifp = uether_getifp(ue);
+
+ SMSC_LOCK_ASSERT(sc, MA_OWNED);
+
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+ return;
+
+ /* Cancel pending I/O */
+ smsc_stop(ue);
+
+#if __FreeBSD_version <= 1000000
+ /* On earlier versions this was the first place we could tell the system
+ * that we supported h/w csuming, however this is only called after the
+ * the interface has been brought up - not ideal.
+ */
+ if (!(ifp->if_capabilities & IFCAP_RXCSUM)) {
+ ifp->if_capabilities |= IFCAP_RXCSUM;
+ ifp->if_capenable |= IFCAP_RXCSUM;
+ ifp->if_hwassist = 0;
+ }
+
+ /* TX checksuming is disabled for now
+ ifp->if_capabilities |= IFCAP_TXCSUM;
+ ifp->if_capenable |= IFCAP_TXCSUM;
+ ifp->if_hwassist = CSUM_TCP | CSUM_UDP;
+ */
+#endif
+
+ /* Reset the ethernet interface. */
+ smsc_reset(sc);
+
+ /* Load the multicast filter. */
+ smsc_setmulti(ue);
+
+ /* TCP/UDP checksum offload engines. */
+ smsc_sethwcsum(sc);
+
+ usbd_xfer_set_stall(sc->sc_xfer[SMSC_BULK_DT_WR]);
+
+ /* Indicate we are up and running. */
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+
+ /* Switch to selected media. */
+ smsc_ifmedia_upd(ifp);
+ smsc_start(ue);
+}
+
+/**
+ * smsc_bulk_read_callback - Read callback used to process the USB URB
+ * @xfer: the USB transfer
+ * @error:
+ *
+ * Reads the URB data which can contain one or more ethernet frames, the
+ * frames are copyed into a mbuf and given to the system.
+ *
+ * LOCKING:
+ * No locking required, doesn't access internal driver settings.
+ */
+static void
+smsc_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
+{
+ struct smsc_softc *sc = usbd_xfer_softc(xfer);
+ struct usb_ether *ue = &sc->sc_ue;
+ struct ifnet *ifp = uether_getifp(ue);
+ struct mbuf *m;
+ struct usb_page_cache *pc;
+ uint32_t rxhdr;
+ uint16_t pktlen;
+ int off;
+ int actlen;
+
+ usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
+ smsc_dbg_printf(sc, "rx : actlen %d\n", actlen);
+
+ switch (USB_GET_STATE(xfer)) {
+ case USB_ST_TRANSFERRED:
+
+ /* There is always a zero length frame after bringing the IF up */
+ if (actlen < (sizeof(rxhdr) + ETHER_CRC_LEN))
+ goto tr_setup;
+
+ /* There maybe multiple packets in the USB frame, each will have a
+ * header and each needs to have it's own mbuf allocated and populated
+ * for it.
+ */
+ pc = usbd_xfer_get_frame(xfer, 0);
+ off = 0;
+
+ while (off < actlen) {
+
+ /* The frame header is always aligned on a 4 byte boundary */
+ off = ((off + 0x3) & ~0x3);
+
+ usbd_copy_out(pc, off, &rxhdr, sizeof(rxhdr));
+ off += (sizeof(rxhdr) + ETHER_ALIGN);
+ rxhdr = le32toh(rxhdr);
+
+ pktlen = (uint16_t)SMSC_RX_STAT_FRM_LENGTH(rxhdr);
+
+ smsc_dbg_printf(sc, "rx : rxhdr 0x%08x : pktlen %d : actlen %d : "
+ "off %d\n", rxhdr, pktlen, actlen, off);
+
+
+ if (rxhdr & SMSC_RX_STAT_ERROR) {
+ smsc_dbg_printf(sc, "rx error (hdr 0x%08x)\n", rxhdr);
+ ifp->if_ierrors++;
+ if (rxhdr & SMSC_RX_STAT_COLLISION)
+ ifp->if_collisions++;
+ } else {
+
+ /* Check if the ethernet frame is too big or too small */
+ if ((pktlen < ETHER_HDR_LEN) || (pktlen > (actlen - off)))
+ goto tr_setup;
+
+ /* Create a new mbuf to store the packet in */
+ m = uether_newbuf();
+ if (m == NULL) {
+ smsc_warn_printf(sc, "failed to create new mbuf\n");
+ ifp->if_iqdrops++;
+ goto tr_setup;
+ }
+
+ usbd_copy_out(pc, off, mtod(m, uint8_t *), pktlen);
+
+ /* Check if RX TCP/UDP checksumming is being offloaded */
+ if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) {
+
+ /* Remove the extra 2 bytes of the csum */
+ pktlen -= 2;
+
+ /* The checksum appears to be simplistically calculated
+ * over the udp/tcp header and data up to the end of the
+ * eth frame. Which means if the eth frame is padded
+ * the csum calculation is incorrectly performed over
+ * the padding bytes as well. Therefore to be safe we
+ * ignore the H/W csum on frames less than or equal to
+ * 64 bytes.
+ */
+ if (pktlen > ETHER_MIN_LEN) {
+
+ /* Indicate the UDP/TCP csum has been calculated */
+ m->m_pkthdr.csum_flags |= CSUM_DATA_VALID;
+
+ /* Copy the TCP/UDP checksum from the last 2 bytes
+ * of the transfer and put in the csum_data field.
+ */
+ usbd_copy_out(pc, (off + pktlen),
+ &m->m_pkthdr.csum_data, 2);
+
+ /* The data is copied in network order, but the
+ * csum algorithm in the kernel expects it to be
+ * in host network order.
+ */
+ m->m_pkthdr.csum_data = ntohs(m->m_pkthdr.csum_data);
+
+ smsc_dbg_printf(sc, "RX checksum offloaded (0x%04x)\n",
+ m->m_pkthdr.csum_data);
+ }
+
+ /* Need to adjust the offset as well or we'll be off
+ * by 2 because the csum is removed from the packet
+ * length.
+ */
+ off += 2;
+ }
+
+ /* Finally enqueue the mbuf on the receive queue */
+ uether_rxmbuf(ue, m, pktlen);
+ }
+
+ /* Update the offset to move to the next potential packet */
+ off += pktlen;
+ }
+
+ /* FALLTHROUGH */
+
+ case USB_ST_SETUP:
+tr_setup:
+ usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
+ usbd_transfer_submit(xfer);
+ uether_rxflush(ue);
+ return;
+
+ default:
+ if (error != USB_ERR_CANCELLED) {
+ smsc_warn_printf(sc, "bulk read error, %s\n", usbd_errstr(error));
+ usbd_xfer_set_stall(xfer);
+ goto tr_setup;
+ }
+ return;
+ }
+}
+
+/**
+ * smsc_bulk_write_callback - Write callback used to send ethernet frame(s)
+ * @xfer: the USB transfer
+ * @error: error code if the transfers is in an errored state
+ *
+ * The main write function that pulls ethernet frames off the queue and sends
+ * them out.
+ *
+ * LOCKING:
+ *
+ */
+static void
+smsc_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
+{
+ struct smsc_softc *sc = usbd_xfer_softc(xfer);
+ struct ifnet *ifp = uether_getifp(&sc->sc_ue);
+ struct usb_page_cache *pc;
+ struct mbuf *m;
+ uint32_t txhdr;
+ uint32_t frm_len = 0;
+ int nframes;
+
+ switch (USB_GET_STATE(xfer)) {
+ case USB_ST_TRANSFERRED:
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ /* FALLTHROUGH */
+
+ case USB_ST_SETUP:
+tr_setup:
+ if ((sc->sc_flags & SMSC_FLAG_LINK) == 0 ||
+ (ifp->if_drv_flags & IFF_DRV_OACTIVE) != 0) {
+ /* Don't send anything if there is no link or controller is busy. */
+ return;
+ }
+
+ for (nframes = 0; nframes < 16 &&
+ !IFQ_DRV_IS_EMPTY(&ifp->if_snd); nframes++) {
+ IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
+ if (m == NULL)
+ break;
+ usbd_xfer_set_frame_offset(xfer, nframes * MCLBYTES,
+ nframes);
+ frm_len = 0;
+ pc = usbd_xfer_get_frame(xfer, nframes);
+
+ /* Each frame is prefixed with two 32-bit values describing the
+ * length of the packet and buffer.
+ */
+ txhdr = SMSC_TX_CTRL_0_BUF_SIZE(m->m_pkthdr.len) |
+ SMSC_TX_CTRL_0_FIRST_SEG | SMSC_TX_CTRL_0_LAST_SEG;
+ txhdr = htole32(txhdr);
+ usbd_copy_in(pc, 0, &txhdr, sizeof(txhdr));
+
+ txhdr = SMSC_TX_CTRL_1_PKT_LENGTH(m->m_pkthdr.len);
+ txhdr = htole32(txhdr);
+ usbd_copy_in(pc, 4, &txhdr, sizeof(txhdr));
+
+ frm_len += 8;
+
+ /* Next copy in the actual packet */
+ usbd_m_copy_in(pc, frm_len, m, 0, m->m_pkthdr.len);
+ frm_len += m->m_pkthdr.len;
+
+ ifp->if_opackets++;
+
+ /* If there's a BPF listener, bounce a copy of this frame to him */
+ BPF_MTAP(ifp, m);
+
+ m_freem(m);
+
+ /* Set frame length. */
+ usbd_xfer_set_frame_len(xfer, nframes, frm_len);
+ }
+ if (nframes != 0) {
+ usbd_xfer_set_frames(xfer, nframes);
+ usbd_transfer_submit(xfer);
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ }
+ return;
+
+ default:
+ ifp->if_oerrors++;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+
+ if (error != USB_ERR_CANCELLED) {
+ smsc_err_printf(sc, "usb error on tx: %s\n", usbd_errstr(error));
+ usbd_xfer_set_stall(xfer);
+ goto tr_setup;
+ }
+ return;
+ }
+}
+
+/**
+ * smsc_tick - Called periodically to monitor the state of the LAN95xx chip
+ * @ue: USB ether interface
+ *
+ * Simply calls the mii status functions to check the state of the link.
+ *
+ * LOCKING:
+ * Should be called with the SMSC lock held.
+ */
+static void
+smsc_tick(struct usb_ether *ue)
+{
+ struct smsc_softc *sc = uether_getsc(ue);
+ struct mii_data *mii = uether_getmii(&sc->sc_ue);;
+
+ SMSC_LOCK_ASSERT(sc, MA_OWNED);
+
+ mii_tick(mii);
+ if ((sc->sc_flags & SMSC_FLAG_LINK) == 0) {
+ smsc_miibus_statchg(ue->ue_dev);
+ if ((sc->sc_flags & SMSC_FLAG_LINK) != 0)
+ smsc_start(ue);
+ }
+}
+
+/**
+ * smsc_start - Starts communication with the LAN95xx chip
+ * @ue: USB ether interface
+ *
+ *
+ *
+ */
+static void
+smsc_start(struct usb_ether *ue)
+{
+ struct smsc_softc *sc = uether_getsc(ue);
+
+ /*
+ * start the USB transfers, if not already started:
+ */
+ usbd_transfer_start(sc->sc_xfer[SMSC_BULK_DT_RD]);
+ usbd_transfer_start(sc->sc_xfer[SMSC_BULK_DT_WR]);
+}
+
+/**
+ * smsc_stop - Stops communication with the LAN95xx chip
+ * @ue: USB ether interface
+ *
+ *
+ *
+ */
+static void
+smsc_stop(struct usb_ether *ue)
+{
+ struct smsc_softc *sc = uether_getsc(ue);
+ struct ifnet *ifp = uether_getifp(ue);
+
+ SMSC_LOCK_ASSERT(sc, MA_OWNED);
+
+ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ sc->sc_flags &= ~SMSC_FLAG_LINK;
+
+ /*
+ * stop all the transfers, if not already stopped:
+ */
+ usbd_transfer_stop(sc->sc_xfer[SMSC_BULK_DT_WR]);
+ usbd_transfer_stop(sc->sc_xfer[SMSC_BULK_DT_RD]);
+}
+
+/**
+ * smsc_phy_init - Initialises the in-built SMSC phy
+ * @sc: driver soft context
+ *
+ * Resets the PHY part of the chip and then initialises it to default
+ * values. The 'link down' and 'auto-negotiation complete' interrupts
+ * from the PHY are also enabled, however we don't monitor the interrupt
+ * endpoints for the moment.
+ *
+ * RETURNS:
+ * Returns 0 on success or EIO if failed to reset the PHY.
+ */
+static int
+smsc_phy_init(struct smsc_softc *sc)
+{
+ int bmcr;
+ usb_ticks_t start_ticks;
+ usb_ticks_t max_ticks = USB_MS_TO_TICKS(1000);
+
+ SMSC_LOCK_ASSERT(sc, MA_OWNED);
+
+ /* Reset phy and wait for reset to complete */
+ smsc_miibus_writereg(sc->sc_ue.ue_dev, sc->sc_phyno, MII_BMCR, BMCR_RESET);
+
+ start_ticks = ticks;
+ do {
+ uether_pause(&sc->sc_ue, hz / 100);
+ bmcr = smsc_miibus_readreg(sc->sc_ue.ue_dev, sc->sc_phyno, MII_BMCR);
+ } while ((bmcr & MII_BMCR) && ((ticks - start_ticks) < max_ticks));
+
+ if ((ticks - start_ticks) >= max_ticks) {
+ smsc_err_printf(sc, "PHY reset timed-out");
+ return (EIO);
+ }
+
+ smsc_miibus_writereg(sc->sc_ue.ue_dev, sc->sc_phyno, MII_ANAR,
+ ANAR_10 | ANAR_10_FD | ANAR_TX | ANAR_TX_FD | /* all modes */
+ ANAR_CSMA |
+ ANAR_FC |
+ ANAR_PAUSE_ASYM);
+
+ /* Setup the phy to interrupt when the link goes down or autoneg completes */
+ smsc_miibus_readreg(sc->sc_ue.ue_dev, sc->sc_phyno, SMSC_PHY_INTR_STAT);
+ smsc_miibus_writereg(sc->sc_ue.ue_dev, sc->sc_phyno, SMSC_PHY_INTR_MASK,
+ (SMSC_PHY_INTR_ANEG_COMP | SMSC_PHY_INTR_LINK_DOWN));
+
+ /* Restart auto-negotation */
+ bmcr = smsc_miibus_readreg(sc->sc_ue.ue_dev, sc->sc_phyno, MII_BMCR);
+ bmcr |= BMCR_STARTNEG;
+ smsc_miibus_writereg(sc->sc_ue.ue_dev, sc->sc_phyno, MII_BMCR, bmcr);
+
+ return (0);
+}
+
+
+/**
+ * smsc_chip_init - Initialises the chip after power on
+ * @sc: driver soft context
+ *
+ * This initialisation sequence is modelled on the procedure in the Linux
+ * driver.
+ *
+ * RETURNS:
+ * Returns 0 on success or an error code on failure.
+ */
+static int
+smsc_chip_init(struct smsc_softc *sc)
+{
+ int err;
+ int locked;
+ uint32_t reg_val;
+ int burst_cap;
+
+ locked = mtx_owned(&sc->sc_mtx);
+ if (!locked)
+ SMSC_LOCK(sc);
+
+ /* Enter H/W config mode */
+ smsc_write_reg(sc, SMSC_HW_CFG, SMSC_HW_CFG_LRST);
+
+ if ((err = smsc_wait_for_bits(sc, SMSC_HW_CFG, SMSC_HW_CFG_LRST)) != 0) {
+ smsc_warn_printf(sc, "timed-out waiting for reset to complete\n");
+ goto init_failed;
+ }
+
+ /* Reset the PHY */
+ smsc_write_reg(sc, SMSC_PM_CTRL, SMSC_PM_CTRL_PHY_RST);
+
+ if ((err = smsc_wait_for_bits(sc, SMSC_PM_CTRL, SMSC_PM_CTRL_PHY_RST) != 0)) {
+ smsc_warn_printf(sc, "timed-out waiting for phy reset to complete\n");
+ goto init_failed;
+ }
+
+ /* Set the mac address */
+ if ((err = smsc_setmacaddress(sc, sc->sc_ue.ue_eaddr)) != 0) {
+ smsc_warn_printf(sc, "failed to set the MAC address\n");
+ goto init_failed;
+ }
+
+ /* Don't know what the HW_CFG_BIR bit is, but following the reset sequence
+ * as used in the Linux driver.
+ */
+ if ((err = smsc_read_reg(sc, SMSC_HW_CFG, ®_val)) != 0) {
+ smsc_warn_printf(sc, "failed to read HW_CFG: %d\n", err);
+ goto init_failed;
+ }
+ reg_val |= SMSC_HW_CFG_BIR;
+ smsc_write_reg(sc, SMSC_HW_CFG, reg_val);
+
+ /* There is a so called 'turbo mode' that the linux driver supports, it
+ * seems to allow you to jam multiple frames per Rx transaction. By default
+ * this driver supports that and therefore allows multiple frames per URB.
+ *
+ * The xfer buffer size needs to reflect this as well, therefore based on
+ * the calculations in the Linux driver the RX bufsize is set to 18944,
+ * bufsz = (16 * 1024 + 5 * 512)
+ *
+ * Burst capability is the number of URBs that can be in a burst of data/
+ * ethernet frames.
+ */
+ if (usbd_get_speed(sc->sc_ue.ue_udev) == USB_SPEED_HIGH)
+ burst_cap = 37;
+ else
+ burst_cap = 128;
+
+ smsc_write_reg(sc, SMSC_BURST_CAP, burst_cap);
+
+ /* Set the default bulk in delay (magic value from Linux driver) */
+ smsc_write_reg(sc, SMSC_BULK_IN_DLY, 0x00002000);
+
+
+
+ /*
+ * Initialise the RX interface
+ */
+ if ((err = smsc_read_reg(sc, SMSC_HW_CFG, ®_val)) < 0) {
+ smsc_warn_printf(sc, "failed to read HW_CFG: (err = %d)\n", err);
+ goto init_failed;
+ }
+
+ /* Adjust the packet offset in the buffer (designed to try and align IP
+ * header on 4 byte boundary)
+ */
+ reg_val &= ~SMSC_HW_CFG_RXDOFF;
+ reg_val |= (ETHER_ALIGN << 9) & SMSC_HW_CFG_RXDOFF;
+
+ /* The following setings are used for 'turbo mode', a.k.a multiple frames
+ * per Rx transaction (again info taken form Linux driver).
+ */
+ reg_val |= (SMSC_HW_CFG_MEF | SMSC_HW_CFG_BCE);
+
+ smsc_write_reg(sc, SMSC_HW_CFG, reg_val);
+
+ /* Clear the status register ? */
+ smsc_write_reg(sc, SMSC_INTR_STATUS, 0xffffffff);
+
+ /* Read and display the revision register */
+ if ((err = smsc_read_reg(sc, SMSC_ID_REV, &sc->sc_rev_id)) < 0) {
+ smsc_warn_printf(sc, "failed to read ID_REV (err = %d)\n", err);
+ goto init_failed;
+ }
+
+ device_printf(sc->sc_ue.ue_dev, "chip 0x%04lx, rev. %04lx\n",
+ (sc->sc_rev_id & SMSC_ID_REV_CHIP_ID_MASK) >> 16,
+ (sc->sc_rev_id & SMSC_ID_REV_CHIP_REV_MASK));
+
+ /* GPIO/LED setup */
+ reg_val = SMSC_LED_GPIO_CFG_SPD_LED | SMSC_LED_GPIO_CFG_LNK_LED |
+ SMSC_LED_GPIO_CFG_FDX_LED;
+ smsc_write_reg(sc, SMSC_LED_GPIO_CFG, reg_val);
+
+ /*
+ * Initialise the TX interface
+ */
+ smsc_write_reg(sc, SMSC_FLOW, 0);
+
+ smsc_write_reg(sc, SMSC_AFC_CFG, AFC_CFG_DEFAULT);
+
+ /* Read the current MAC configuration */
+ if ((err = smsc_read_reg(sc, SMSC_MAC_CSR, &sc->sc_mac_csr)) < 0) {
+ smsc_warn_printf(sc, "failed to read MAC_CSR (err=%d)\n", err);
+ goto init_failed;
+ }
+
+ /* Vlan */
+ smsc_write_reg(sc, SMSC_VLAN1, (uint32_t)ETHERTYPE_VLAN);
+
+ /*
+ * Initialise the PHY
+ */
+ if ((err = smsc_phy_init(sc)) != 0)
+ goto init_failed;
+
+
+ /*
+ * Start TX
+ */
+ sc->sc_mac_csr |= SMSC_MAC_CSR_TXEN;
+ smsc_write_reg(sc, SMSC_MAC_CSR, sc->sc_mac_csr);
+ smsc_write_reg(sc, SMSC_TX_CFG, SMSC_TX_CFG_ON);
+
+ /*
+ * Start RX
+ */
+ sc->sc_mac_csr |= SMSC_MAC_CSR_RXEN;
+ smsc_write_reg(sc, SMSC_MAC_CSR, sc->sc_mac_csr);
+
+ if (!locked)
+ SMSC_UNLOCK(sc);
+
+ return (0);
+
+init_failed:
+ if (!locked)
+ SMSC_UNLOCK(sc);
+
+ smsc_err_printf(sc, "smsc_chip_init failed (err=%d)\n", err);
+ return (err);
+}
+
+
+/**
+ * smsc_ioctl - ioctl function for the device
+ * @ifp: interface pointer
+ * @cmd: the ioctl command
+ * @data: data passed in the ioctl call, typically a pointer to struct ifreq.
+ *
+ * The ioctl routine is overridden to detect change requests for the H/W
+ * checksum capabilities.
+ *
+ * RETURNS:
+ * 0 on success and an error code on failure.
+ */
+static int
+smsc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+{
+ struct usb_ether *ue = ifp->if_softc;
+ struct smsc_softc *sc;
+ struct ifreq *ifr;
+ int rc;
+ int mask;
+ int reinit;
+
+ if (cmd == SIOCSIFCAP) {
+
+ sc = uether_getsc(ue);
+ ifr = (struct ifreq *)data;
+
+ SMSC_LOCK(sc);
+
+ rc = 0;
+ reinit = 0;
+
+ mask = ifr->ifr_reqcap ^ ifp->if_capenable;
+
+ /* Modify the RX CSUM enable bits */
+ if ((mask & IFCAP_RXCSUM) != 0 &&
+ (ifp->if_capabilities & IFCAP_RXCSUM) != 0) {
+ ifp->if_capenable ^= IFCAP_RXCSUM;
+
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ reinit = 1;
+ }
+ }
+
+ SMSC_UNLOCK(sc);
+ if (reinit)
+#if __FreeBSD_version > 1000000
+ uether_init(ue);
+#else
+ ifp->if_init(ue);
+#endif
+
+ } else {
+ rc = uether_ioctl(ifp, cmd, data);
+ }
+
+ return (rc);
+}
+
+
+/**
+ * smsc_attach_post - Called after the driver attached to the USB interface
+ * @ue: the USB ethernet device
+ *
+ * This is where the chip is intialised for the first time. This is different
+ * from the smsc_init() function in that that one is designed to setup the
+ * H/W to match the UE settings and can be called after a reset.
+ *
+ *
+ */
+static void
+smsc_attach_post(struct usb_ether *ue)
+{
+ struct smsc_softc *sc = uether_getsc(ue);
+ uint32_t mac_h, mac_l;
+ int err;
+
+ smsc_dbg_printf(sc, "smsc_attach_post\n");
+
+ /* Setup some of the basics */
+ sc->sc_phyno = 1;
+
+
+ /* Attempt to get the mac address, if an EEPROM is not attached this
+ * will just return FF:FF:FF:FF:FF:FF, so in such cases we invent a MAC
+ * address based on urandom.
+ */
+ memset(sc->sc_ue.ue_eaddr, 0xff, ETHER_ADDR_LEN);
+
+ /* Check if there is already a MAC address in the register */
+ if ((smsc_read_reg(sc, SMSC_MAC_ADDRL, &mac_l) == 0) &&
+ (smsc_read_reg(sc, SMSC_MAC_ADDRH, &mac_h) == 0)) {
+ sc->sc_ue.ue_eaddr[5] = (uint8_t)((mac_h >> 8) & 0xff);
+ sc->sc_ue.ue_eaddr[4] = (uint8_t)((mac_h) & 0xff);
+ sc->sc_ue.ue_eaddr[3] = (uint8_t)((mac_l >> 24) & 0xff);
+ sc->sc_ue.ue_eaddr[2] = (uint8_t)((mac_l >> 16) & 0xff);
+ sc->sc_ue.ue_eaddr[1] = (uint8_t)((mac_l >> 8) & 0xff);
+ sc->sc_ue.ue_eaddr[0] = (uint8_t)((mac_l) & 0xff);
+ }
+
+ /* MAC address is not set so try to read from EEPROM, if that fails generate
+ * a random MAC address.
+ */
+ if (!ETHER_IS_VALID(sc->sc_ue.ue_eaddr)) {
+
+ err = smsc_eeprom_read(sc, 0x01, sc->sc_ue.ue_eaddr, ETHER_ADDR_LEN);
+ if ((err != 0) || (!ETHER_IS_VALID(sc->sc_ue.ue_eaddr))) {
+
+ read_random(sc->sc_ue.ue_eaddr, ETHER_ADDR_LEN);
+ sc->sc_ue.ue_eaddr[0] &= ~0x01; /* unicast */
+ sc->sc_ue.ue_eaddr[0] |= 0x02; /* locally administered */
+ }
+ }
+
+ /* Initialise the chip for the first time */
+ smsc_chip_init(sc);
+}
+
+
+/**
+ * smsc_attach_post_sub - Called after the driver attached to the USB interface
+ * @ue: the USB ethernet device
+ *
+ * Most of this is boilerplate code and copied from the base USB ethernet
+ * driver. It has been overriden so that we can indicate to the system that
+ * the chip supports H/W checksumming.
+ *
+ * RETURNS:
+ * Returns 0 on success or a negative error code.
+ */
+#if __FreeBSD_version > 1000000
+static int
+smsc_attach_post_sub(struct usb_ether *ue)
+{
+ struct smsc_softc *sc;
+ struct ifnet *ifp;
+ int error;
+
+ sc = uether_getsc(ue);
+ ifp = ue->ue_ifp;
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_start = uether_start;
+ ifp->if_ioctl = smsc_ioctl;
+ ifp->if_init = uether_init;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
+ ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
+ IFQ_SET_READY(&ifp->if_snd);
+
+ /* The chip supports TCP/UDP checksum offloading on TX and RX paths, however
+ * currently only RX checksum is supported in the driver (see top of file).
+ */
+ ifp->if_capabilities |= IFCAP_RXCSUM;
+ ifp->if_hwassist = 0;
+
+ /* TX checksuming is disabled (for now?)
+ ifp->if_capabilities |= IFCAP_TXCSUM;
+ ifp->if_capenable |= IFCAP_TXCSUM;
+ ifp->if_hwassist = CSUM_TCP | CSUM_UDP;
+ */
+
+ ifp->if_capenable = ifp->if_capabilities;
+
+ mtx_lock(&Giant);
+ error = mii_attach(ue->ue_dev, &ue->ue_miibus, ifp,
+ uether_ifmedia_upd, ue->ue_methods->ue_mii_sts,
+ BMSR_DEFCAPMASK, sc->sc_phyno, MII_OFFSET_ANY, 0);
+ mtx_unlock(&Giant);
+
+ return (error);
+}
+#endif /* __FreeBSD_version > 1000000 */
+
+
+/**
+ * smsc_probe - Probe the interface.
+ * @dev: smsc device handle
+ *
+ * Checks if the device is a match for this driver.
+ *
+ * RETURNS:
+ * Returns 0 on success or an error code on failure.
+ */
+static int
+smsc_probe(device_t dev)
+{
+ struct usb_attach_arg *uaa = device_get_ivars(dev);
+
+ if (uaa->usb_mode != USB_MODE_HOST)
+ return (ENXIO);
+ if (uaa->info.bConfigIndex != SMSC_CONFIG_INDEX)
+ return (ENXIO);
+ if (uaa->info.bIfaceIndex != SMSC_IFACE_IDX)
+ return (ENXIO);
+
+ return (usbd_lookup_id_by_uaa(smsc_devs, sizeof(smsc_devs), uaa));
+}
+
+
+/**
+ * smsc_attach - Attach the interface.
+ * @dev: smsc device handle
+ *
+ * Allocate softc structures, do ifmedia setup and ethernet/BPF attach.
+ *
+ * RETURNS:
+ * Returns 0 on success or a negative error code.
+ */
+static int
+smsc_attach(device_t dev)
+{
+ struct usb_attach_arg *uaa = device_get_ivars(dev);
+ struct smsc_softc *sc = device_get_softc(dev);
+ struct usb_ether *ue = &sc->sc_ue;
+ uint8_t iface_index;
+ int err;
+
+ sc->sc_flags = USB_GET_DRIVER_INFO(uaa);
+
+ device_set_usb_desc(dev);
+
+ mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+
+ /* Setup the endpoints for the SMSC LAN95xx device(s) */
+ iface_index = SMSC_IFACE_IDX;
+ err = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
+ smsc_config, SMSC_N_TRANSFER, sc, &sc->sc_mtx);
+ if (err) {
+ device_printf(dev, "error: allocating USB transfers failed\n");
+ goto detach;
+ }
+
+ ue->ue_sc = sc;
+ ue->ue_dev = dev;
+ ue->ue_udev = uaa->device;
+ ue->ue_mtx = &sc->sc_mtx;
+ ue->ue_methods = &smsc_ue_methods;
+
+ err = uether_ifattach(ue);
+ if (err) {
+ device_printf(dev, "error: could not attach interface\n");
+ goto detach;
+ }
+ return (0); /* success */
+
+detach:
+ smsc_detach(dev);
+ return (ENXIO); /* failure */
+}
+
+/**
+ * smsc_detach - Detach the interface.
+ * @dev: smsc device handle
+ *
+ * RETURNS:
+ * Returns 0.
+ */
+static int
+smsc_detach(device_t dev)
+{
+ struct smsc_softc *sc = device_get_softc(dev);
+ struct usb_ether *ue = &sc->sc_ue;
+
+ usbd_transfer_unsetup(sc->sc_xfer, SMSC_N_TRANSFER);
+ uether_ifdetach(ue);
+ mtx_destroy(&sc->sc_mtx);
+
+ return (0);
+}
+
+static device_method_t smsc_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, smsc_probe),
+ DEVMETHOD(device_attach, smsc_attach),
+ DEVMETHOD(device_detach, smsc_detach),
+
+ /* bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_driver_added, bus_generic_driver_added),
+
+ /* MII interface */
+ DEVMETHOD(miibus_readreg, smsc_miibus_readreg),
+ DEVMETHOD(miibus_writereg, smsc_miibus_writereg),
+ DEVMETHOD(miibus_statchg, smsc_miibus_statchg),
+
+ {0, 0}
+};
+
+static driver_t smsc_driver = {
+ .name = "smsc",
+ .methods = smsc_methods,
+ .size = sizeof(struct smsc_softc),
+};
+
+static devclass_t smsc_devclass;
+
+DRIVER_MODULE(smsc, uhub, smsc_driver, smsc_devclass, NULL, 0);
+DRIVER_MODULE(miibus, smsc, miibus_driver, miibus_devclass, 0, 0);
+MODULE_DEPEND(smsc, uether, 1, 1, 1);
+MODULE_DEPEND(smsc, usb, 1, 1, 1);
+MODULE_DEPEND(smsc, ether, 1, 1, 1);
+MODULE_DEPEND(smsc, miibus, 1, 1, 1);
+MODULE_VERSION(smsc, 1);
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/net/if_smscreg.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/dev/usb/net/if_smscreg.h Wed Aug 15 11:46:11 2012 +0300
@@ -0,0 +1,277 @@
+/*-
+ * Copyright (c) 2012
+ * Ben Gray <bgray at 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 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 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: head/sys/dev/usb/net/if_smscreg.h 239275 2012-08-15 04:03:55Z gonzo $
+ */
+#ifndef _IF_SMSCREG_H_
+#define _IF_SMSCREG_H_
+
+/*
+ * Definitions for the SMSC LAN9514 and LAN9514 USB to ethernet controllers.
+ *
+ * This information was gleaned from the SMSC driver in the linux kernel, where
+ * it is Copyrighted (C) 2007-2008 SMSC.
+ *
+ */
+
+/**
+ * TRANSMIT FRAMES
+ * ---------------
+ * Tx frames are prefixed with an 8-byte header which describes the frame
+ *
+ * 4 bytes 4 bytes variable
+ * +------------+------------+--- . . . . . . . . . . . . ---+
+ * | TX_CTRL_0 | TX_CTRL_1 | Ethernet frame data |
+ * +------------+------------+--- . . . . . . . . . . . . ---+
+ *
+ * Where the headers have the following fields:
+ *
+ * TX_CTRL_0 <20:16> Data offset
+ * TX_CTRL_0 <13> First segment of frame indicator
+ * TX_CTRL_0 <12> Last segment of frame indicator
+ * TX_CTRL_0 <10:0> Buffer size (?)
+ *
+ * TX_CTRL_1 <14> Perform H/W checksuming on IP packets
+ * TX_CTRL_1 <13> Disable automatic ethernet CRC generation
+ * TX_CTRL_1 <12> Disable padding (?)
+ * TX_CTRL_1 <10:0> Packet byte length
+ *
+ */
+#define SMSC_TX_CTRL_0_OFFSET(x) (((x) & 0x1FUL) << 16)
+#define SMSC_TX_CTRL_0_FIRST_SEG (0x1UL << 13)
+#define SMSC_TX_CTRL_0_LAST_SEG (0x1UL << 12)
+#define SMSC_TX_CTRL_0_BUF_SIZE(x) ((x) & 0x000007FFUL)
+
+#define SMSC_TX_CTRL_1_CSUM_ENABLE (0x1UL << 14)
+#define SMSC_TX_CTRL_1_CRC_DISABLE (0x1UL << 13)
+#define SMSC_TX_CTRL_1_PADDING_DISABLE (0x1UL << 12)
+#define SMSC_TX_CTRL_1_PKT_LENGTH(x) ((x) & 0x000007FFUL)
+
+/**
+ * RECEIVE FRAMES
+ * --------------
+ * Rx frames are prefixed with an 4-byte status header which describes any
+ * errors with the frame as well as things like the length
+ *
+ * 4 bytes variable
+ * +------------+--- . . . . . . . . . . . . ---+
+ * | RX_STAT | Ethernet frame data |
+ * +------------+--- . . . . . . . . . . . . ---+
+ *
+ * Where the status header has the following fields:
+ *
+ * RX_STAT <30> Filter Fail
+ * RX_STAT <29:16> Frame Length
+ * RX_STAT <15> Error Summary
+ * RX_STAT <13> Broadcast Frame
+ * RX_STAT <12> Length Error
+ * RX_STAT <11> Runt Frame
+ * RX_STAT <10> Multicast Frame
+ * RX_STAT <7> Frame too long
+ * RX_STAT <6> Collision Seen
+ * RX_STAT <5> Frame Type
+ * RX_STAT <4> Receive Watchdog
+ * RX_STAT <3> Mii Error
+ * RX_STAT <2> Dribbling
+ * RX_STAT <1> CRC Error
+ *
+ */
+#define SMSC_RX_STAT_FILTER_FAIL (0x1UL << 30)
+#define SMSC_RX_STAT_FRM_LENGTH(x) (((x) >> 16) & 0x3FFFUL)
+#define SMSC_RX_STAT_ERROR (0x1UL << 15)
+#define SMSC_RX_STAT_BROADCAST (0x1UL << 13)
+#define SMSC_RX_STAT_LENGTH_ERROR (0x1UL << 12)
+#define SMSC_RX_STAT_RUNT (0x1UL << 11)
+#define SMSC_RX_STAT_MULTICAST (0x1UL << 10)
+#define SMSC_RX_STAT_FRM_TO_LONG (0x1UL << 7)
+#define SMSC_RX_STAT_COLLISION (0x1UL << 6)
+#define SMSC_RX_STAT_FRM_TYPE (0x1UL << 5)
+#define SMSC_RX_STAT_WATCHDOG (0x1UL << 4)
+#define SMSC_RX_STAT_MII_ERROR (0x1UL << 3)
+#define SMSC_RX_STAT_DRIBBLING (0x1UL << 2)
+#define SMSC_RX_STAT_CRC_ERROR (0x1UL << 1)
+
+/**
+ * REGISTERS
+ *
+ */
+#define SMSC_ID_REV 0x000
+#define SMSC_INTR_STATUS 0x008
+#define SMSC_RX_CFG 0x00C
+#define SMSC_TX_CFG 0x010
+#define SMSC_HW_CFG 0x014
+#define SMSC_PM_CTRL 0x020
+#define SMSC_LED_GPIO_CFG 0x024
+#define SMSC_GPIO_CFG 0x028
+#define SMSC_AFC_CFG 0x02C
+#define SMSC_EEPROM_CMD 0x030
+#define SMSC_EEPROM_DATA 0x034
+#define SMSC_BURST_CAP 0x038
+#define SMSC_GPIO_WAKE 0x064
+#define SMSC_INTR_CFG 0x068
+#define SMSC_BULK_IN_DLY 0x06C
+#define SMSC_MAC_CSR 0x100
+#define SMSC_MAC_ADDRH 0x104
+#define SMSC_MAC_ADDRL 0x108
+#define SMSC_HASHH 0x10C
+#define SMSC_HASHL 0x110
+#define SMSC_MII_ADDR 0x114
+#define SMSC_MII_DATA 0x118
+#define SMSC_FLOW 0x11C
+#define SMSC_VLAN1 0x120
+#define SMSC_VLAN2 0x124
+#define SMSC_WUFF 0x128
+#define SMSC_WUCSR 0x12C
+#define SMSC_COE_CTRL 0x130
+
+/* ID / Revision register */
+#define SMSC_ID_REV_CHIP_ID_MASK 0xFFFF0000UL
+#define SMSC_ID_REV_CHIP_REV_MASK 0x0000FFFFUL
+
+#define SMSC_RX_FIFO_FLUSH (0x1UL << 0)
+
+#define SMSC_TX_CFG_ON (0x1UL << 2)
+#define SMSC_TX_CFG_STOP (0x1UL << 1)
+#define SMSC_TX_CFG_FIFO_FLUSH (0x1UL << 0)
+
+#define SMSC_HW_CFG_BIR (0x1UL << 12)
+#define SMSC_HW_CFG_LEDB (0x1UL << 11)
+#define SMSC_HW_CFG_RXDOFF (0x3UL << 9) /* RX pkt alignment */
+#define SMSC_HW_CFG_DRP (0x1UL << 6)
+#define SMSC_HW_CFG_MEF (0x1UL << 5)
+#define SMSC_HW_CFG_LRST (0x1UL << 3) /* Lite reset */
+#define SMSC_HW_CFG_PSEL (0x1UL << 2)
+#define SMSC_HW_CFG_BCE (0x1UL << 1)
+#define SMSC_HW_CFG_SRST (0x1UL << 0)
+
+#define SMSC_PM_CTRL_PHY_RST (0x1UL << 4) /* PHY reset */
+
+#define SMSC_LED_GPIO_CFG_SPD_LED (0x1UL << 24)
+#define SMSC_LED_GPIO_CFG_LNK_LED (0x1UL << 20)
+#define SMSC_LED_GPIO_CFG_FDX_LED (0x1UL << 16)
+
+/* Hi watermark = 15.5Kb (~10 mtu pkts) */
+/* low watermark = 3k (~2 mtu pkts) */
+/* backpressure duration = ~ 350us */
+/* Apply FC on any frame. */
+#define AFC_CFG_DEFAULT (0x00F830A1)
+
+#define SMSC_EEPROM_CMD_BUSY (0x1UL << 31)
+#define SMSC_EEPROM_CMD_MASK (0x7UL << 28)
+#define SMSC_EEPROM_CMD_READ (0x0UL << 28)
+#define SMSC_EEPROM_CMD_WRITE (0x3UL << 28)
+#define SMSC_EEPROM_CMD_ERASE (0x5UL << 28)
+#define SMSC_EEPROM_CMD_RELOAD (0x7UL << 28)
+#define SMSC_EEPROM_CMD_TIMEOUT (0x1UL << 10)
+#define SMSC_EEPROM_CMD_ADDR_MASK 0x000001FFUL
+
+/* MAC Control and Status Register */
+#define SMSC_MAC_CSR_RCVOWN (0x1UL << 23) /* Half duplex */
+#define SMSC_MAC_CSR_LOOPBK (0x1UL << 21) /* Loopback */
+#define SMSC_MAC_CSR_FDPX (0x1UL << 20) /* Full duplex */
+#define SMSC_MAC_CSR_MCPAS (0x1UL << 19) /* Multicast mode */
+#define SMSC_MAC_CSR_PRMS (0x1UL << 18) /* Promiscuous mode */
+#define SMSC_MAC_CSR_INVFILT (0x1UL << 17) /* Inverse filtering */
+#define SMSC_MAC_CSR_PASSBAD (0x1UL << 16) /* Pass on bad frames */
+#define SMSC_MAC_CSR_HPFILT (0x1UL << 13) /* Hash filtering */
+#define SMSC_MAC_CSR_BCAST (0x1UL << 11) /* Broadcast */
+#define SMSC_MAC_CSR_TXEN (0x1UL << 3) /* TX enable */
+#define SMSC_MAC_CSR_RXEN (0x1UL << 2) /* RX enable */
+
+/* Interrupt control register */
+#define SMSC_INTR_NTEP (0x1UL << 31)
+#define SMSC_INTR_MACRTO (0x1UL << 19)
+#define SMSC_INTR_TX_STOP (0x1UL << 17)
+#define SMSC_INTR_RX_STOP (0x1UL << 16)
+#define SMSC_INTR_PHY_INT (0x1UL << 15)
+#define SMSC_INTR_TXE (0x1UL << 14)
+#define SMSC_INTR_TDFU (0x1UL << 13)
+#define SMSC_INTR_TDFO (0x1UL << 12)
+#define SMSC_INTR_RXDF (0x1UL << 11)
+#define SMSC_INTR_GPIOS 0x000007FFUL
+
+/* Phy MII interface register */
+#define SMSC_MII_WRITE (0x1UL << 1)
+#define SMSC_MII_READ (0x0UL << 1)
+#define SMSC_MII_BUSY (0x1UL << 0)
+
+/* H/W checksum register */
+#define SMSC_COE_CTRL_TX_EN (0x1UL << 16) /* Tx H/W csum enable */
+#define SMSC_COE_CTRL_RX_MODE (0x1UL << 1)
+#define SMSC_COE_CTRL_RX_EN (0x1UL << 0) /* Rx H/W csum enable */
+
+/* Registers on the phy, accessed via MII/MDIO */
+#define SMSC_PHY_INTR_STAT (29)
+#define SMSC_PHY_INTR_MASK (30)
+
+#define SMSC_PHY_INTR_ENERGY_ON (0x1U << 7)
+#define SMSC_PHY_INTR_ANEG_COMP (0x1U << 6)
+#define SMSC_PHY_INTR_REMOTE_FAULT (0x1U << 5)
+#define SMSC_PHY_INTR_LINK_DOWN (0x1U << 4)
+
+/* USB Vendor Requests */
+#define SMSC_UR_WRITE_REG 0xA0
+#define SMSC_UR_READ_REG 0xA1
+#define SMSC_UR_GET_STATS 0xA2
+
+#define SMSC_CONFIG_INDEX 0 /* config number 1 */
+#define SMSC_IFACE_IDX 0
+
+/*
+ * USB endpoints.
+ */
+enum {
+ SMSC_BULK_DT_RD,
+ SMSC_BULK_DT_WR,
+ /* the LAN9514 device does support interrupt endpoints, however I couldn't
+ * get then to work reliably and since they are unneeded (poll the mii
+ * status) they are unused.
+ * SMSC_INTR_DT_WR,
+ * SMSC_INTR_DT_RD,
+ */
+ SMSC_N_TRANSFER,
+};
+
+struct smsc_softc {
+ struct usb_ether sc_ue;
+ struct mtx sc_mtx;
+ struct usb_xfer *sc_xfer[SMSC_N_TRANSFER];
+ int sc_phyno;
+
+ /* The following stores the settings in the mac control (MAC_CSR) register */
+ uint32_t sc_mac_csr;
+ uint32_t sc_rev_id;
+
+ uint32_t sc_flags;
+#define SMSC_FLAG_LINK 0x0001
+#define SMSC_FLAG_LAN9514 0x1000 /* LAN9514 */
+};
+
+#define SMSC_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define SMSC_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define SMSC_LOCK_ASSERT(_sc, t) mtx_assert(&(_sc)->sc_mtx, t)
+
+#endif /* _IF_SMSCREG_H_ */
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/net/if_usie.c
--- a/head/sys/dev/usb/net/if_usie.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/net/if_usie.c Wed Aug 15 11:46:11 2012 +0300
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/net/if_usie.c 233774 2012-04-02 10:50:42Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/net/if_usie.c 239180 2012-08-10 15:29:41Z hselasky $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -95,7 +95,9 @@
static device_probe_t usie_probe;
static device_attach_t usie_attach;
static device_detach_t usie_detach;
+static device_free_softc_t usie_free_softc;
+static void usie_free(struct ucom_softc *);
static void usie_uc_update_line_state(struct ucom_softc *, uint8_t);
static void usie_uc_cfg_get_status(struct ucom_softc *, uint8_t *, uint8_t *);
static void usie_uc_cfg_set_dtr(struct ucom_softc *, uint8_t);
@@ -189,7 +191,8 @@
DEVMETHOD(device_probe, usie_probe),
DEVMETHOD(device_attach, usie_attach),
DEVMETHOD(device_detach, usie_detach),
- {0, 0}
+ DEVMETHOD(device_free_softc, usie_free_softc),
+ DEVMETHOD_END
};
static driver_t usie_driver = {
@@ -216,6 +219,7 @@
.ucom_stop_read = &usie_uc_stop_read,
.ucom_start_write = &usie_uc_start_write,
.ucom_stop_write = &usie_uc_stop_write,
+ .ucom_free = &usie_free,
};
static void
@@ -298,6 +302,7 @@
sc->sc_dev = self;
mtx_init(&sc->sc_mtx, "usie", MTX_NETWORK_LOCK, MTX_DEF);
+ ucom_ref(&sc->sc_super_ucom);
TASK_INIT(&sc->sc_if_status_task, 0, usie_if_status_cb, sc);
TASK_INIT(&sc->sc_if_sync_task, 0, usie_if_sync_cb, sc);
@@ -482,11 +487,30 @@
for (x = 0; x != USIE_UCOM_MAX; x++)
usbd_transfer_unsetup(sc->sc_uc_xfer[x], USIE_UC_N_XFER);
- mtx_destroy(&sc->sc_mtx);
return (0);
}
+UCOM_UNLOAD_DRAIN(usie);
+
+static void
+usie_free_softc(device_t dev, void *arg)
+{
+ struct usie_softc *sc = arg;
+
+ if (ucom_unref(&sc->sc_super_ucom)) {
+ if (mtx_initialized(&sc->sc_mtx))
+ mtx_destroy(&sc->sc_mtx);
+ device_free_softc(dev, sc);
+ }
+}
+
+static void
+usie_free(struct ucom_softc *ucom)
+{
+ usie_free_softc(NULL, ucom->sc_parent);
+}
+
static void
usie_uc_update_line_state(struct ucom_softc *ucom, uint8_t ls)
{
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/net/uhso.c
--- a/head/sys/dev/usb/net/uhso.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/net/uhso.c Wed Aug 15 11:46:11 2012 +0300
@@ -24,7 +24,7 @@
*
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/net/uhso.c 233774 2012-04-02 10:50:42Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/net/uhso.c 239180 2012-08-10 15:29:41Z hselasky $");
#include <sys/param.h>
#include <sys/types.h>
@@ -455,6 +455,7 @@
static int uhso_radio_sysctl(SYSCTL_HANDLER_ARGS);
static int uhso_radio_ctrl(struct uhso_softc *, int);
+static void uhso_free(struct ucom_softc *);
static void uhso_ucom_start_read(struct ucom_softc *);
static void uhso_ucom_stop_read(struct ucom_softc *);
static void uhso_ucom_start_write(struct ucom_softc *);
@@ -473,11 +474,13 @@
static device_probe_t uhso_probe;
static device_attach_t uhso_attach;
static device_detach_t uhso_detach;
+static device_free_softc_t uhso_free_softc;
static device_method_t uhso_methods[] = {
DEVMETHOD(device_probe, uhso_probe),
DEVMETHOD(device_attach, uhso_attach),
DEVMETHOD(device_detach, uhso_detach),
+ DEVMETHOD(device_free_softc, uhso_free_softc),
{ 0, 0 }
};
@@ -500,7 +503,8 @@
.ucom_start_read = uhso_ucom_start_read,
.ucom_stop_read = uhso_ucom_stop_read,
.ucom_start_write = uhso_ucom_start_write,
- .ucom_stop_write = uhso_ucom_stop_write
+ .ucom_stop_write = uhso_ucom_stop_write,
+ .ucom_free = &uhso_free,
};
static int
@@ -552,6 +556,7 @@
sc->sc_dev = self;
sc->sc_udev = uaa->device;
mtx_init(&sc->sc_mtx, "uhso", NULL, MTX_DEF);
+ ucom_ref(&sc->sc_super_ucom);
sc->sc_ucom = NULL;
sc->sc_ttys = 0;
@@ -692,10 +697,29 @@
usbd_transfer_unsetup(sc->sc_if_xfer, UHSO_IFNET_MAX);
}
- mtx_destroy(&sc->sc_mtx);
return (0);
}
+UCOM_UNLOAD_DRAIN(uhso);
+
+static void
+uhso_free_softc(device_t dev, void *arg)
+{
+ struct uhso_softc *sc = arg;
+
+ if (ucom_unref(&sc->sc_super_ucom)) {
+ if (mtx_initialized(&sc->sc_mtx))
+ mtx_destroy(&sc->sc_mtx);
+ device_free_softc(dev, sc);
+ }
+}
+
+static void
+uhso_free(struct ucom_softc *ucom)
+{
+ uhso_free_softc(NULL, ucom->sc_parent);
+}
+
static void
uhso_test_autoinst(void *arg, struct usb_device *udev,
struct usb_attach_arg *uaa)
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/quirk/usb_quirk.c
--- a/head/sys/dev/usb/quirk/usb_quirk.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/quirk/usb_quirk.c Wed Aug 15 11:46:11 2012 +0300
@@ -449,6 +449,7 @@
USB_QUIRK(TOSHIBA, TRANSMEMORY, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(VIALABS, USB30SATABRIDGE, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
+ USB_QUIRK(WETELECOM, ZEROCD, 0x0000, 0xffff, UQ_CFG_INDEX_1),
/* Non-standard USB MIDI devices */
USB_QUIRK(ROLAND, UM1, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/u3g.c
--- a/head/sys/dev/usb/serial/u3g.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/u3g.c Wed Aug 15 11:46:11 2012 +0300
@@ -16,7 +16,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD: head/sys/dev/usb/serial/u3g.c 238717 2012-07-23 14:22:45Z rea $
+ * $FreeBSD: head/sys/dev/usb/serial/u3g.c 239182 2012-08-10 17:43:20Z hselasky $
*/
/*
@@ -124,10 +124,12 @@
static device_probe_t u3g_probe;
static device_attach_t u3g_attach;
static device_detach_t u3g_detach;
+static device_free_softc_t u3g_free_softc;
static usb_callback_t u3g_write_callback;
static usb_callback_t u3g_read_callback;
+static void u3g_free(struct ucom_softc *ucom);
static void u3g_start_read(struct ucom_softc *ucom);
static void u3g_stop_read(struct ucom_softc *ucom);
static void u3g_start_write(struct ucom_softc *ucom);
@@ -170,13 +172,15 @@
.ucom_stop_write = &u3g_stop_write,
.ucom_cfg_set_dtr = &u3g_cfg_set_dtr,
.ucom_cfg_set_rts = &u3g_cfg_set_rts,
+ .ucom_free = &u3g_free,
};
static device_method_t u3g_methods[] = {
DEVMETHOD(device_probe, u3g_probe),
DEVMETHOD(device_attach, u3g_attach),
DEVMETHOD(device_detach, u3g_detach),
- {0, 0}
+ DEVMETHOD(device_free_softc, u3g_free_softc),
+ DEVMETHOD_END
};
static devclass_t u3g_devclass;
@@ -536,6 +540,7 @@
U3G_DEV(TOSHIBA, HSDPA, 0),
U3G_DEV(YISO, C893, 0),
U3G_DEV(LONGCHEER, MBD_100HU, 0),
+ U3G_DEV(WETELECOM, WM_D300, 0),
/* Autoinstallers */
U3G_DEV(NOVATEL, ZEROCD, U3GINIT_SCSIEJECT),
U3G_DEV(OPTION, GTICON322, U3GINIT_REZERO),
@@ -819,6 +824,7 @@
device_set_usb_desc(dev);
mtx_init(&sc->sc_mtx, "u3g", NULL, MTX_DEF);
+ ucom_ref(&sc->sc_super_ucom);
sc->sc_udev = uaa->device;
@@ -908,11 +914,12 @@
for (subunit = 0; subunit != U3G_MAXPORTS; subunit++)
usbd_transfer_unsetup(sc->sc_xfer[subunit], U3G_N_TRANSFER);
- mtx_destroy(&sc->sc_mtx);
return (0);
}
+UCOM_UNLOAD_DRAIN(u3g);
+
static void
u3g_cfg_request(struct u3g_softc *sc, uint8_t index, uint16_t value)
{
@@ -970,13 +977,30 @@
}
static void
+u3g_free_softc(device_t dev, void *arg)
+{
+ struct u3g_softc *sc = arg;
+
+ if (ucom_unref(&sc->sc_super_ucom)) {
+ if (mtx_initialized(&sc->sc_mtx))
+ mtx_destroy(&sc->sc_mtx);
+ device_free_softc(dev, sc);
+ }
+}
+
+static void
+u3g_free(struct ucom_softc *ucom)
+{
+ u3g_free_softc(NULL, ucom->sc_parent);
+}
+
+static void
u3g_start_read(struct ucom_softc *ucom)
{
struct u3g_softc *sc = ucom->sc_parent;
/* start read endpoint */
usbd_transfer_start(sc->sc_xfer[ucom->sc_subunit][U3G_BULK_RD]);
- return;
}
static void
@@ -986,7 +1010,6 @@
/* stop read endpoint */
usbd_transfer_stop(sc->sc_xfer[ucom->sc_subunit][U3G_BULK_RD]);
- return;
}
static void
@@ -995,7 +1018,6 @@
struct u3g_softc *sc = ucom->sc_parent;
usbd_transfer_start(sc->sc_xfer[ucom->sc_subunit][U3G_BULK_WR]);
- return;
}
static void
@@ -1004,7 +1026,6 @@
struct u3g_softc *sc = ucom->sc_parent;
usbd_transfer_stop(sc->sc_xfer[ucom->sc_subunit][U3G_BULK_WR]);
- return;
}
static void
@@ -1033,7 +1054,6 @@
}
break;
}
- return;
}
static void
@@ -1064,5 +1084,4 @@
}
break;
}
- return;
}
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/uark.c
--- a/head/sys/dev/usb/serial/uark.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/uark.c Wed Aug 15 11:46:11 2012 +0300
@@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $FreeBSD: head/sys/dev/usb/serial/uark.c 223486 2011-06-24 02:30:02Z hselasky $
+ * $FreeBSD: head/sys/dev/usb/serial/uark.c 239180 2012-08-10 15:29:41Z hselasky $
*/
/*
@@ -99,10 +99,12 @@
static device_probe_t uark_probe;
static device_attach_t uark_attach;
static device_detach_t uark_detach;
+static device_free_softc_t uark_free_softc;
static usb_callback_t uark_bulk_write_callback;
static usb_callback_t uark_bulk_read_callback;
+static void uark_free(struct ucom_softc *);
static void uark_start_read(struct ucom_softc *);
static void uark_stop_read(struct ucom_softc *);
static void uark_start_write(struct ucom_softc *);
@@ -147,6 +149,7 @@
.ucom_start_write = &uark_start_write,
.ucom_stop_write = &uark_stop_write,
.ucom_poll = &uark_poll,
+ .ucom_free = &uark_free,
};
static device_method_t uark_methods[] = {
@@ -154,7 +157,8 @@
DEVMETHOD(device_probe, uark_probe),
DEVMETHOD(device_attach, uark_attach),
DEVMETHOD(device_detach, uark_detach),
- {0, 0}
+ DEVMETHOD(device_free_softc, uark_free_softc),
+ DEVMETHOD_END
};
static devclass_t uark_devclass;
@@ -201,6 +205,7 @@
device_set_usb_desc(dev);
mtx_init(&sc->sc_mtx, "uark", NULL, MTX_DEF);
+ ucom_ref(&sc->sc_super_ucom);
sc->sc_udev = uaa->device;
@@ -242,11 +247,30 @@
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
usbd_transfer_unsetup(sc->sc_xfer, UARK_N_TRANSFER);
- mtx_destroy(&sc->sc_mtx);
return (0);
}
+UCOM_UNLOAD_DRAIN(uark);
+
+static void
+uark_free_softc(device_t dev, void *arg)
+{
+ struct uark_softc *sc = arg;
+
+ if (ucom_unref(&sc->sc_super_ucom)) {
+ if (mtx_initialized(&sc->sc_mtx))
+ mtx_destroy(&sc->sc_mtx);
+ device_free_softc(dev, sc);
+ }
+}
+
+static void
+uark_free(struct ucom_softc *ucom)
+{
+ uark_free_softc(NULL, ucom->sc_parent);
+}
+
static void
uark_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
{
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/ubsa.c
--- a/head/sys/dev/usb/serial/ubsa.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/ubsa.c Wed Aug 15 11:46:11 2012 +0300
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/ubsa.c 233774 2012-04-02 10:50:42Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/ubsa.c 239180 2012-08-10 15:29:41Z hselasky $");
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -176,12 +176,14 @@
static device_probe_t ubsa_probe;
static device_attach_t ubsa_attach;
static device_detach_t ubsa_detach;
+static device_free_softc_t ubsa_free_softc;
static usb_callback_t ubsa_write_callback;
static usb_callback_t ubsa_read_callback;
static usb_callback_t ubsa_intr_callback;
static void ubsa_cfg_request(struct ubsa_softc *, uint8_t, uint16_t);
+static void ubsa_free(struct ucom_softc *);
static void ubsa_cfg_set_dtr(struct ucom_softc *, uint8_t);
static void ubsa_cfg_set_rts(struct ucom_softc *, uint8_t);
static void ubsa_cfg_set_break(struct ucom_softc *, uint8_t);
@@ -237,6 +239,7 @@
.ucom_start_write = &ubsa_start_write,
.ucom_stop_write = &ubsa_stop_write,
.ucom_poll = &ubsa_poll,
+ .ucom_free = &ubsa_free,
};
static const STRUCT_USB_HOST_ID ubsa_devs[] = {
@@ -262,7 +265,8 @@
DEVMETHOD(device_probe, ubsa_probe),
DEVMETHOD(device_attach, ubsa_attach),
DEVMETHOD(device_detach, ubsa_detach),
- {0, 0}
+ DEVMETHOD(device_free_softc, ubsa_free_softc),
+ DEVMETHOD_END
};
static devclass_t ubsa_devclass;
@@ -306,6 +310,7 @@
device_set_usb_desc(dev);
mtx_init(&sc->sc_mtx, "ubsa", NULL, MTX_DEF);
+ ucom_ref(&sc->sc_super_ucom);
sc->sc_udev = uaa->device;
sc->sc_iface_no = uaa->info.bIfaceNum;
@@ -348,11 +353,30 @@
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
usbd_transfer_unsetup(sc->sc_xfer, UBSA_N_TRANSFER);
- mtx_destroy(&sc->sc_mtx);
return (0);
}
+UCOM_UNLOAD_DRAIN(ubsa);
+
+static void
+ubsa_free_softc(device_t dev, void *arg)
+{
+ struct ubsa_softc *sc = arg;
+
+ if (ucom_unref(&sc->sc_super_ucom)) {
+ if (mtx_initialized(&sc->sc_mtx))
+ mtx_destroy(&sc->sc_mtx);
+ device_free_softc(dev, sc);
+ }
+}
+
+static void
+ubsa_free(struct ucom_softc *ucom)
+{
+ ubsa_free_softc(NULL, ucom->sc_parent);
+}
+
static void
ubsa_cfg_request(struct ubsa_softc *sc, uint8_t index, uint16_t value)
{
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/ubser.c
--- a/head/sys/dev/usb/serial/ubser.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/ubser.c Wed Aug 15 11:46:11 2012 +0300
@@ -70,7 +70,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/ubser.c 227309 2011-11-07 15:43:11Z ed $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/ubser.c 239181 2012-08-10 17:42:14Z hselasky $");
/*
* BWCT serial adapter driver
@@ -141,7 +141,6 @@
uint8_t sc_iface_no;
uint8_t sc_iface_index;
uint8_t sc_curr_tx_unit;
- uint8_t sc_name[16];
};
/* prototypes */
@@ -149,10 +148,12 @@
static device_probe_t ubser_probe;
static device_attach_t ubser_attach;
static device_detach_t ubser_detach;
+static device_free_softc_t ubser_free_softc;
static usb_callback_t ubser_write_callback;
static usb_callback_t ubser_read_callback;
+static void ubser_free(struct ucom_softc *);
static int ubser_pre_param(struct ucom_softc *, struct termios *);
static void ubser_cfg_set_break(struct ucom_softc *, uint8_t);
static void ubser_cfg_get_status(struct ucom_softc *, uint8_t *,
@@ -193,13 +194,15 @@
.ucom_start_write = &ubser_start_write,
.ucom_stop_write = &ubser_stop_write,
.ucom_poll = &ubser_poll,
+ .ucom_free = &ubser_free,
};
static device_method_t ubser_methods[] = {
DEVMETHOD(device_probe, ubser_probe),
DEVMETHOD(device_attach, ubser_attach),
DEVMETHOD(device_detach, ubser_detach),
- {0, 0}
+ DEVMETHOD(device_free_softc, ubser_free_softc),
+ DEVMETHOD_END
};
static devclass_t ubser_devclass;
@@ -243,9 +246,7 @@
device_set_usb_desc(dev);
mtx_init(&sc->sc_mtx, "ubser", NULL, MTX_DEF);
-
- snprintf(sc->sc_name, sizeof(sc->sc_name), "%s",
- device_get_nameunit(dev));
+ ucom_ref(&sc->sc_super_ucom);
sc->sc_iface_no = uaa->info.bIfaceNum;
sc->sc_iface_index = uaa->info.bIfaceIndex;
@@ -319,11 +320,30 @@
ucom_detach(&sc->sc_super_ucom, sc->sc_ucom);
usbd_transfer_unsetup(sc->sc_xfer, UBSER_N_TRANSFER);
- mtx_destroy(&sc->sc_mtx);
return (0);
}
+UCOM_UNLOAD_DRAIN(ubser);
+
+static void
+ubser_free_softc(device_t dev, void *arg)
+{
+ struct ubser_softc *sc = arg;
+
+ if (ucom_unref(&sc->sc_super_ucom)) {
+ if (mtx_initialized(&sc->sc_mtx))
+ mtx_destroy(&sc->sc_mtx);
+ device_free_softc(dev, sc);
+ }
+}
+
+static void
+ubser_free(struct ucom_softc *ucom)
+{
+ ubser_free_softc(NULL, ucom->sc_parent);
+}
+
static int
ubser_pre_param(struct ucom_softc *ucom, struct termios *t)
{
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/uchcom.c
--- a/head/sys/dev/usb/serial/uchcom.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/uchcom.c Wed Aug 15 11:46:11 2012 +0300
@@ -63,7 +63,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/uchcom.c 233774 2012-04-02 10:50:42Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/uchcom.c 239180 2012-08-10 15:29:41Z hselasky $");
/*
* Driver for WinChipHead CH341/340, the worst USB-serial chip in the
@@ -211,6 +211,7 @@
/* protypes */
+static void uchcom_free(struct ucom_softc *);
static int uchcom_pre_param(struct ucom_softc *, struct termios *);
static void uchcom_cfg_get_status(struct ucom_softc *, uint8_t *,
uint8_t *);
@@ -234,6 +235,7 @@
static device_probe_t uchcom_probe;
static device_attach_t uchcom_attach;
static device_detach_t uchcom_detach;
+static device_free_softc_t uchcom_free_softc;
static usb_callback_t uchcom_intr_callback;
static usb_callback_t uchcom_write_callback;
@@ -282,6 +284,7 @@
.ucom_start_write = &uchcom_start_write,
.ucom_stop_write = &uchcom_stop_write,
.ucom_poll = &uchcom_poll,
+ .ucom_free = &uchcom_free,
};
/* ----------------------------------------------------------------------
@@ -319,6 +322,7 @@
device_set_usb_desc(dev);
mtx_init(&sc->sc_mtx, "uchcom", NULL, MTX_DEF);
+ ucom_ref(&sc->sc_super_ucom);
sc->sc_udev = uaa->device;
@@ -371,11 +375,30 @@
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
usbd_transfer_unsetup(sc->sc_xfer, UCHCOM_N_TRANSFER);
- mtx_destroy(&sc->sc_mtx);
return (0);
}
+UCOM_UNLOAD_DRAIN(uchcom);
+
+static void
+uchcom_free_softc(device_t dev, void *arg)
+{
+ struct uchcom_softc *sc = arg;
+
+ if (ucom_unref(&sc->sc_super_ucom)) {
+ if (mtx_initialized(&sc->sc_mtx))
+ mtx_destroy(&sc->sc_mtx);
+ device_free_softc(dev, sc);
+ }
+}
+
+static void
+uchcom_free(struct ucom_softc *ucom)
+{
+ uchcom_free_softc(NULL, ucom->sc_parent);
+}
+
/* ----------------------------------------------------------------------
* low level i/o
*/
@@ -841,8 +864,8 @@
DEVMETHOD(device_probe, uchcom_probe),
DEVMETHOD(device_attach, uchcom_attach),
DEVMETHOD(device_detach, uchcom_detach),
-
- {0, 0}
+ DEVMETHOD(device_free_softc, uchcom_free_softc),
+ DEVMETHOD_END
};
static driver_t uchcom_driver = {
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/ucycom.c
--- a/head/sys/dev/usb/serial/ucycom.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/ucycom.c Wed Aug 15 11:46:11 2012 +0300
@@ -1,5 +1,5 @@
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/ucycom.c 233774 2012-04-02 10:50:42Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/ucycom.c 239181 2012-08-10 17:42:14Z hselasky $");
/*-
* Copyright (c) 2004 Dag-Erling Coïdan Smørgrav
@@ -101,7 +101,6 @@
#define UCYCOM_CFG_STOPB 0x08
#define UCYCOM_CFG_DATAB 0x03
uint8_t sc_ist; /* status flags from last input */
- uint8_t sc_name[16];
uint8_t sc_iface_no;
uint8_t sc_temp_cfg[32];
};
@@ -111,10 +110,12 @@
static device_probe_t ucycom_probe;
static device_attach_t ucycom_attach;
static device_detach_t ucycom_detach;
+static device_free_softc_t ucycom_free_softc;
static usb_callback_t ucycom_ctrl_write_callback;
static usb_callback_t ucycom_intr_read_callback;
+static void ucycom_free(struct ucom_softc *);
static void ucycom_cfg_open(struct ucom_softc *);
static void ucycom_start_read(struct ucom_softc *);
static void ucycom_stop_read(struct ucom_softc *);
@@ -155,13 +156,15 @@
.ucom_start_write = &ucycom_start_write,
.ucom_stop_write = &ucycom_stop_write,
.ucom_poll = &ucycom_poll,
+ .ucom_free = &ucycom_free,
};
static device_method_t ucycom_methods[] = {
DEVMETHOD(device_probe, ucycom_probe),
DEVMETHOD(device_attach, ucycom_attach),
DEVMETHOD(device_detach, ucycom_detach),
- {0, 0}
+ DEVMETHOD(device_free_softc, ucycom_free_softc),
+ DEVMETHOD_END
};
static devclass_t ucycom_devclass;
@@ -218,9 +221,7 @@
device_set_usb_desc(dev);
mtx_init(&sc->sc_mtx, "ucycom", NULL, MTX_DEF);
-
- snprintf(sc->sc_name, sizeof(sc->sc_name),
- "%s", device_get_nameunit(dev));
+ ucom_ref(&sc->sc_super_ucom);
DPRINTF("\n");
@@ -297,11 +298,30 @@
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
usbd_transfer_unsetup(sc->sc_xfer, UCYCOM_N_TRANSFER);
- mtx_destroy(&sc->sc_mtx);
return (0);
}
+UCOM_UNLOAD_DRAIN(ucycom);
+
+static void
+ucycom_free_softc(device_t dev, void *arg)
+{
+ struct ucycom_softc *sc = arg;
+
+ if (ucom_unref(&sc->sc_super_ucom)) {
+ if (mtx_initialized(&sc->sc_mtx))
+ mtx_destroy(&sc->sc_mtx);
+ device_free_softc(dev, sc);
+ }
+}
+
+static void
+ucycom_free(struct ucom_softc *ucom)
+{
+ ucycom_free_softc(NULL, ucom->sc_parent);
+}
+
static void
ucycom_cfg_open(struct ucom_softc *ucom)
{
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/ufoma.c
--- a/head/sys/dev/usb/serial/ufoma.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/ufoma.c Wed Aug 15 11:46:11 2012 +0300
@@ -1,7 +1,7 @@
/* $NetBSD: umodem.c,v 1.45 2002/09/23 05:51:23 simonb Exp $ */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/ufoma.c 233774 2012-04-02 10:50:42Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/ufoma.c 239181 2012-08-10 17:42:14Z hselasky $");
#define UFOMA_HANDSFREE
/*-
* Copyright (c) 2005, Takanori Watanabe
@@ -195,7 +195,6 @@
uint8_t sc_msr;
uint8_t sc_modetoactivate;
uint8_t sc_currentmode;
- uint8_t sc_name[16];
};
/* prototypes */
@@ -203,6 +202,7 @@
static device_probe_t ufoma_probe;
static device_attach_t ufoma_attach;
static device_detach_t ufoma_detach;
+static device_free_softc_t ufoma_free_softc;
static usb_callback_t ufoma_ctrl_read_callback;
static usb_callback_t ufoma_ctrl_write_callback;
@@ -214,6 +214,7 @@
struct usb_interface_descriptor *, uint8_t, uint8_t);
static void ufoma_cfg_link_state(struct ufoma_softc *);
static void ufoma_cfg_activate_state(struct ufoma_softc *, uint16_t);
+static void ufoma_free(struct ucom_softc *);
static void ufoma_cfg_open(struct ucom_softc *);
static void ufoma_cfg_close(struct ucom_softc *);
static void ufoma_cfg_set_break(struct ucom_softc *, uint8_t);
@@ -304,6 +305,7 @@
.ucom_start_write = &ufoma_start_write,
.ucom_stop_write = &ufoma_stop_write,
.ucom_poll = &ufoma_poll,
+ .ucom_free = &ufoma_free,
};
static device_method_t ufoma_methods[] = {
@@ -311,7 +313,8 @@
DEVMETHOD(device_probe, ufoma_probe),
DEVMETHOD(device_attach, ufoma_attach),
DEVMETHOD(device_detach, ufoma_detach),
- {0, 0}
+ DEVMETHOD(device_free_softc, ufoma_free_softc),
+ DEVMETHOD_END
};
static devclass_t ufoma_devclass;
@@ -385,13 +388,11 @@
sc->sc_unit = device_get_unit(dev);
mtx_init(&sc->sc_mtx, "ufoma", NULL, MTX_DEF);
+ ucom_ref(&sc->sc_super_ucom);
cv_init(&sc->sc_cv, "CWAIT");
device_set_usb_desc(dev);
- snprintf(sc->sc_name, sizeof(sc->sc_name),
- "%s", device_get_nameunit(dev));
-
DPRINTF("\n");
/* setup control transfers */
@@ -495,12 +496,31 @@
if (sc->sc_modetable) {
free(sc->sc_modetable, M_USBDEV);
}
- mtx_destroy(&sc->sc_mtx);
cv_destroy(&sc->sc_cv);
return (0);
}
+UCOM_UNLOAD_DRAIN(ufoma);
+
+static void
+ufoma_free_softc(device_t dev, void *arg)
+{
+ struct ufoma_softc *sc = arg;
+
+ if (ucom_unref(&sc->sc_super_ucom)) {
+ if (mtx_initialized(&sc->sc_mtx))
+ mtx_destroy(&sc->sc_mtx);
+ device_free_softc(dev, sc);
+ }
+}
+
+static void
+ufoma_free(struct ucom_softc *ucom)
+{
+ ufoma_free_softc(NULL, ucom->sc_parent);
+}
+
static void *
ufoma_get_intconf(struct usb_config_descriptor *cd, struct usb_interface_descriptor *id,
uint8_t type, uint8_t subtype)
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/uftdi.c
--- a/head/sys/dev/usb/serial/uftdi.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/uftdi.c Wed Aug 15 11:46:11 2012 +0300
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/uftdi.c 239055 2012-08-05 11:50:56Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/uftdi.c 239181 2012-08-10 17:42:14Z hselasky $");
/*
* NOTE: all function names beginning like "uftdi_cfg_" can only
@@ -110,8 +110,6 @@
uint8_t sc_hdrlen;
uint8_t sc_msr;
uint8_t sc_lsr;
-
- uint8_t sc_name[16];
};
struct uftdi_param_config {
@@ -127,10 +125,12 @@
static device_probe_t uftdi_probe;
static device_attach_t uftdi_attach;
static device_detach_t uftdi_detach;
+static device_free_softc_t uftdi_free_softc;
static usb_callback_t uftdi_write_callback;
static usb_callback_t uftdi_read_callback;
+static void uftdi_free(struct ucom_softc *);
static void uftdi_cfg_open(struct ucom_softc *);
static void uftdi_cfg_set_dtr(struct ucom_softc *, uint8_t);
static void uftdi_cfg_set_rts(struct ucom_softc *, uint8_t);
@@ -182,6 +182,7 @@
.ucom_start_write = &uftdi_start_write,
.ucom_stop_write = &uftdi_stop_write,
.ucom_poll = &uftdi_poll,
+ .ucom_free = &uftdi_free,
};
static device_method_t uftdi_methods[] = {
@@ -189,7 +190,7 @@
DEVMETHOD(device_probe, uftdi_probe),
DEVMETHOD(device_attach, uftdi_attach),
DEVMETHOD(device_detach, uftdi_detach),
-
+ DEVMETHOD(device_free_softc, uftdi_free_softc),
DEVMETHOD_END
};
@@ -885,9 +886,7 @@
device_set_usb_desc(dev);
mtx_init(&sc->sc_mtx, "uftdi", NULL, MTX_DEF);
-
- snprintf(sc->sc_name, sizeof(sc->sc_name),
- "%s", device_get_nameunit(dev));
+ ucom_ref(&sc->sc_super_ucom);
DPRINTF("\n");
@@ -960,11 +959,30 @@
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
usbd_transfer_unsetup(sc->sc_xfer, UFTDI_N_TRANSFER);
- mtx_destroy(&sc->sc_mtx);
return (0);
}
+UCOM_UNLOAD_DRAIN(uftdi);
+
+static void
+uftdi_free_softc(device_t dev, void *arg)
+{
+ struct uftdi_softc *sc = arg;
+
+ if (ucom_unref(&sc->sc_super_ucom)) {
+ if (mtx_initialized(&sc->sc_mtx))
+ mtx_destroy(&sc->sc_mtx);
+ device_free_softc(dev, sc);
+ }
+}
+
+static void
+uftdi_free(struct ucom_softc *ucom)
+{
+ uftdi_free_softc(NULL, ucom->sc_parent);
+}
+
static void
uftdi_cfg_open(struct ucom_softc *ucom)
{
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/ugensa.c
--- a/head/sys/dev/usb/serial/ugensa.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/ugensa.c Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/serial/ugensa.c 223486 2011-06-24 02:30:02Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/serial/ugensa.c 239180 2012-08-10 15:29:41Z hselasky $ */
/* $NetBSD: ugensa.c,v 1.9.2.1 2007/03/24 14:55:50 yamt Exp $ */
/*
@@ -94,10 +94,12 @@
static device_probe_t ugensa_probe;
static device_attach_t ugensa_attach;
static device_detach_t ugensa_detach;
+static device_free_softc_t ugensa_free_softc;
static usb_callback_t ugensa_bulk_write_callback;
static usb_callback_t ugensa_bulk_read_callback;
+static void ugensa_free(struct ucom_softc *);
static void ugensa_start_read(struct ucom_softc *);
static void ugensa_stop_read(struct ucom_softc *);
static void ugensa_start_write(struct ucom_softc *);
@@ -131,6 +133,7 @@
.ucom_start_write = &ugensa_start_write,
.ucom_stop_write = &ugensa_stop_write,
.ucom_poll = &ugensa_poll,
+ .ucom_free = &ugensa_free,
};
static device_method_t ugensa_methods[] = {
@@ -138,7 +141,8 @@
DEVMETHOD(device_probe, ugensa_probe),
DEVMETHOD(device_attach, ugensa_attach),
DEVMETHOD(device_detach, ugensa_detach),
- {0, 0}
+ DEVMETHOD(device_free_softc, ugensa_free_softc),
+ DEVMETHOD_END
};
static devclass_t ugensa_devclass;
@@ -192,6 +196,7 @@
device_set_usb_desc(dev);
mtx_init(&sc->sc_mtx, "ugensa", NULL, MTX_DEF);
+ ucom_ref(&sc->sc_super_ucom);
/* Figure out how many interfaces this device has got */
for (cnt = 0; cnt < UGENSA_IFACE_MAX; cnt++) {
@@ -266,11 +271,30 @@
for (x = 0; x < sc->sc_niface; x++) {
usbd_transfer_unsetup(sc->sc_sub[x].sc_xfer, UGENSA_N_TRANSFER);
}
- mtx_destroy(&sc->sc_mtx);
return (0);
}
+UCOM_UNLOAD_DRAIN(ugensa);
+
+static void
+ugensa_free_softc(device_t dev, void *arg)
+{
+ struct ugensa_softc *sc = arg;
+
+ if (ucom_unref(&sc->sc_super_ucom)) {
+ if (mtx_initialized(&sc->sc_mtx))
+ mtx_destroy(&sc->sc_mtx);
+ device_free_softc(dev, sc);
+ }
+}
+
+static void
+ugensa_free(struct ucom_softc *ucom)
+{
+ ugensa_free_softc(NULL, ucom->sc_parent);
+}
+
static void
ugensa_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
{
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/uipaq.c
--- a/head/sys/dev/usb/serial/uipaq.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/uipaq.c Wed Aug 15 11:46:11 2012 +0300
@@ -42,7 +42,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/uipaq.c 223486 2011-06-24 02:30:02Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/uipaq.c 239180 2012-08-10 15:29:41Z hselasky $");
#include <sys/stdint.h>
#include <sys/stddef.h>
@@ -103,10 +103,12 @@
static device_probe_t uipaq_probe;
static device_attach_t uipaq_attach;
static device_detach_t uipaq_detach;
+static device_free_softc_t uipaq_free_softc;
static usb_callback_t uipaq_write_callback;
static usb_callback_t uipaq_read_callback;
+static void uipaq_free(struct ucom_softc *);
static void uipaq_start_read(struct ucom_softc *);
static void uipaq_stop_read(struct ucom_softc *);
static void uipaq_start_write(struct ucom_softc *);
@@ -146,6 +148,7 @@
.ucom_start_write = &uipaq_start_write,
.ucom_stop_write = &uipaq_stop_write,
.ucom_poll = &uipaq_poll,
+ .ucom_free = &uipaq_free,
};
/*
@@ -1070,7 +1073,8 @@
DEVMETHOD(device_probe, uipaq_probe),
DEVMETHOD(device_attach, uipaq_attach),
DEVMETHOD(device_detach, uipaq_detach),
- {0, 0}
+ DEVMETHOD(device_free_softc, uipaq_free_softc),
+ DEVMETHOD_END
};
static devclass_t uipaq_devclass;
@@ -1121,6 +1125,7 @@
device_set_usb_desc(dev);
mtx_init(&sc->sc_mtx, "uipaq", NULL, MTX_DEF);
+ ucom_ref(&sc->sc_super_ucom);
/*
* Send magic bytes, cribbed from Linux ipaq driver that
@@ -1176,11 +1181,30 @@
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
usbd_transfer_unsetup(sc->sc_xfer, UIPAQ_N_TRANSFER);
- mtx_destroy(&sc->sc_mtx);
return (0);
}
+UCOM_UNLOAD_DRAIN(uipaq);
+
+static void
+uipaq_free_softc(device_t dev, void *arg)
+{
+ struct uipaq_softc *sc = arg;
+
+ if (ucom_unref(&sc->sc_super_ucom)) {
+ if (mtx_initialized(&sc->sc_mtx))
+ mtx_destroy(&sc->sc_mtx);
+ device_free_softc(dev, sc);
+ }
+}
+
+static void
+uipaq_free(struct ucom_softc *ucom)
+{
+ uipaq_free_softc(NULL, ucom->sc_parent);
+}
+
static void
uipaq_start_read(struct ucom_softc *ucom)
{
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/ulpt.c
--- a/head/sys/dev/usb/serial/ulpt.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/ulpt.c Wed Aug 15 11:46:11 2012 +0300
@@ -1,5 +1,5 @@
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/ulpt.c 233774 2012-04-02 10:50:42Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/ulpt.c 239180 2012-08-10 15:29:41Z hselasky $");
/* $NetBSD: ulpt.c,v 1.60 2003/10/04 21:19:50 augustss Exp $ */
@@ -747,7 +747,7 @@
DEVMETHOD(device_probe, ulpt_probe),
DEVMETHOD(device_attach, ulpt_attach),
DEVMETHOD(device_detach, ulpt_detach),
- {0, 0}
+ DEVMETHOD_END
};
static driver_t ulpt_driver = {
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/umcs.c
--- a/head/sys/dev/usb/serial/umcs.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/umcs.c Wed Aug 15 11:46:11 2012 +0300
@@ -38,7 +38,7 @@
*
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/umcs.c 227309 2011-11-07 15:43:11Z ed $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/umcs.c 239180 2012-08-10 15:29:41Z hselasky $");
#include <sys/stdint.h>
#include <sys/stddef.h>
@@ -154,6 +154,7 @@
static usb_error_t umcs7840_set_baudrate(struct umcs7840_softc *, uint8_t, uint32_t);
static usb_error_t umcs7840_calc_baudrate(uint32_t rate, uint16_t *, uint8_t *);
+static void umcs7840_free(struct ucom_softc *);
static void umcs7840_cfg_get_status(struct ucom_softc *, uint8_t *, uint8_t *);
static void umcs7840_cfg_set_dtr(struct ucom_softc *, uint8_t);
static void umcs7840_cfg_set_rts(struct ucom_softc *, uint8_t);
@@ -175,6 +176,7 @@
static device_probe_t umcs7840_probe;
static device_attach_t umcs7840_attach;
static device_detach_t umcs7840_detach;
+static device_free_softc_t umcs7840_free_softc;
static usb_callback_t umcs7840_intr_callback;
static usb_callback_t umcs7840_read_callback1;
@@ -251,6 +253,7 @@
.ucom_stop_write = &umcs7840_stop_write,
.ucom_poll = &umcs7840_poll,
+ .ucom_free = &umcs7840_free,
};
static const STRUCT_USB_HOST_ID umcs7840_devs[] = {
@@ -262,7 +265,8 @@
DEVMETHOD(device_probe, umcs7840_probe),
DEVMETHOD(device_attach, umcs7840_attach),
DEVMETHOD(device_detach, umcs7840_detach),
- {0, 0}
+ DEVMETHOD(device_free_softc, umcs7840_free_softc),
+ DEVMETHOD_END
};
static devclass_t umcs7840_devclass;
@@ -310,6 +314,7 @@
device_set_usb_desc(dev);
mtx_init(&sc->sc_mtx, "umcs7840", NULL, MTX_DEF);
+ ucom_ref(&sc->sc_super_ucom);
sc->sc_dev = dev;
sc->sc_udev = uaa->device;
@@ -408,10 +413,29 @@
usbd_transfer_unsetup(sc->sc_ports[sc->sc_ucom[subunit].sc_portno].sc_xfer, UMCS7840_N_TRANSFERS);
usbd_transfer_unsetup(&sc->sc_intr_xfer, 1);
- mtx_destroy(&sc->sc_mtx);
return (0);
}
+UCOM_UNLOAD_DRAIN(umcs7840);
+
+static void
+umcs7840_free_softc(device_t dev, void *arg)
+{
+ struct umcs7840_softc *sc = arg;
+
+ if (ucom_unref(&sc->sc_super_ucom)) {
+ if (mtx_initialized(&sc->sc_mtx))
+ mtx_destroy(&sc->sc_mtx);
+ device_free_softc(dev, sc);
+ }
+}
+
+static void
+umcs7840_free(struct ucom_softc *ucom)
+{
+ umcs7840_free_softc(NULL, ucom->sc_parent);
+}
+
static void
umcs7840_cfg_open(struct ucom_softc *ucom)
{
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/umct.c
--- a/head/sys/dev/usb/serial/umct.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/umct.c Wed Aug 15 11:46:11 2012 +0300
@@ -1,5 +1,5 @@
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/umct.c 223486 2011-06-24 02:30:02Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/umct.c 239181 2012-08-10 17:42:14Z hselasky $");
/*-
* Copyright (c) 2003 Scott Long
@@ -115,7 +115,6 @@
uint8_t sc_mcr;
uint8_t sc_iface_no;
uint8_t sc_swap_cb;
- uint8_t sc_name[16];
};
/* prototypes */
@@ -123,6 +122,7 @@
static device_probe_t umct_probe;
static device_attach_t umct_attach;
static device_detach_t umct_detach;
+static device_free_softc_t umct_free_softc;
static usb_callback_t umct_intr_callback;
static usb_callback_t umct_intr_callback_sub;
@@ -132,6 +132,7 @@
static void umct_cfg_do_request(struct umct_softc *sc, uint8_t request,
uint16_t len, uint32_t value);
+static void umct_free(struct ucom_softc *);
static void umct_cfg_get_status(struct ucom_softc *, uint8_t *,
uint8_t *);
static void umct_cfg_set_break(struct ucom_softc *, uint8_t);
@@ -190,6 +191,7 @@
.ucom_start_write = &umct_start_write,
.ucom_stop_write = &umct_stop_write,
.ucom_poll = &umct_poll,
+ .ucom_free = &umct_free,
};
static const STRUCT_USB_HOST_ID umct_devs[] = {
@@ -204,7 +206,8 @@
DEVMETHOD(device_probe, umct_probe),
DEVMETHOD(device_attach, umct_attach),
DEVMETHOD(device_detach, umct_detach),
- {0, 0}
+ DEVMETHOD(device_free_softc, umct_free_softc),
+ DEVMETHOD_END
};
static devclass_t umct_devclass;
@@ -251,9 +254,7 @@
device_set_usb_desc(dev);
mtx_init(&sc->sc_mtx, "umct", NULL, MTX_DEF);
-
- snprintf(sc->sc_name, sizeof(sc->sc_name),
- "%s", device_get_nameunit(dev));
+ ucom_ref(&sc->sc_super_ucom);
sc->sc_iface_no = uaa->info.bIfaceNum;
@@ -312,11 +313,30 @@
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
usbd_transfer_unsetup(sc->sc_xfer, UMCT_N_TRANSFER);
- mtx_destroy(&sc->sc_mtx);
return (0);
}
+UCOM_UNLOAD_DRAIN(umct);
+
+static void
+umct_free_softc(device_t dev, void *arg)
+{
+ struct umct_softc *sc = arg;
+
+ if (ucom_unref(&sc->sc_super_ucom)) {
+ if (mtx_initialized(&sc->sc_mtx))
+ mtx_destroy(&sc->sc_mtx);
+ device_free_softc(dev, sc);
+ }
+}
+
+static void
+umct_free(struct ucom_softc *ucom)
+{
+ umct_free_softc(NULL, ucom->sc_parent);
+}
+
static void
umct_cfg_do_request(struct umct_softc *sc, uint8_t request,
uint16_t len, uint32_t value)
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/umodem.c
--- a/head/sys/dev/usb/serial/umodem.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/umodem.c Wed Aug 15 11:46:11 2012 +0300
@@ -1,7 +1,7 @@
/* $NetBSD: umodem.c,v 1.45 2002/09/23 05:51:23 simonb Exp $ */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/umodem.c 234418 2012-04-18 12:50:13Z thomas $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/umodem.c 239180 2012-08-10 15:29:41Z hselasky $");
/*-
* Copyright (c) 2003, M. Warner Losh <imp at FreeBSD.org>.
@@ -178,11 +178,13 @@
static device_probe_t umodem_probe;
static device_attach_t umodem_attach;
static device_detach_t umodem_detach;
+static device_free_softc_t umodem_free_softc;
static usb_callback_t umodem_intr_callback;
static usb_callback_t umodem_write_callback;
static usb_callback_t umodem_read_callback;
+static void umodem_free(struct ucom_softc *);
static void umodem_start_read(struct ucom_softc *);
static void umodem_stop_read(struct ucom_softc *);
static void umodem_start_write(struct ucom_softc *);
@@ -250,13 +252,15 @@
.ucom_start_write = &umodem_start_write,
.ucom_stop_write = &umodem_stop_write,
.ucom_poll = &umodem_poll,
+ .ucom_free = &umodem_free,
};
static device_method_t umodem_methods[] = {
DEVMETHOD(device_probe, umodem_probe),
DEVMETHOD(device_attach, umodem_attach),
DEVMETHOD(device_detach, umodem_detach),
- {0, 0}
+ DEVMETHOD(device_free_softc, umodem_free_softc),
+ DEVMETHOD_END
};
static devclass_t umodem_devclass;
@@ -302,6 +306,7 @@
device_set_usb_desc(dev);
mtx_init(&sc->sc_mtx, "umodem", NULL, MTX_DEF);
+ ucom_ref(&sc->sc_super_ucom);
sc->sc_ctrl_iface_no = uaa->info.bIfaceNum;
sc->sc_iface_index[1] = uaa->info.bIfaceIndex;
@@ -875,11 +880,30 @@
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
usbd_transfer_unsetup(sc->sc_xfer, UMODEM_N_TRANSFER);
- mtx_destroy(&sc->sc_mtx);
return (0);
}
+UCOM_UNLOAD_DRAIN(umodem);
+
+static void
+umodem_free_softc(device_t dev, void *arg)
+{
+ struct umodem_softc *sc = arg;
+
+ if (ucom_unref(&sc->sc_super_ucom)) {
+ if (mtx_initialized(&sc->sc_mtx))
+ mtx_destroy(&sc->sc_mtx);
+ device_free_softc(dev, sc);
+ }
+}
+
+static void
+umodem_free(struct ucom_softc *ucom)
+{
+ umodem_free_softc(NULL, ucom->sc_parent);
+}
+
static void
umodem_poll(struct ucom_softc *ucom)
{
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/umoscom.c
--- a/head/sys/dev/usb/serial/umoscom.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/umoscom.c Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/serial/umoscom.c 227309 2011-11-07 15:43:11Z ed $ */
+/* $FreeBSD: head/sys/dev/usb/serial/umoscom.c 239180 2012-08-10 15:29:41Z hselasky $ */
/* $OpenBSD: umoscom.c,v 1.2 2006/10/26 06:02:43 jsg Exp $ */
/*
@@ -189,11 +189,13 @@
static device_probe_t umoscom_probe;
static device_attach_t umoscom_attach;
static device_detach_t umoscom_detach;
+static device_free_softc_t umoscom_free_softc;
static usb_callback_t umoscom_write_callback;
static usb_callback_t umoscom_read_callback;
static usb_callback_t umoscom_intr_callback;
+static void umoscom_free(struct ucom_softc *);
static void umoscom_cfg_open(struct ucom_softc *);
static void umoscom_cfg_close(struct ucom_softc *);
static void umoscom_cfg_set_break(struct ucom_softc *, uint8_t);
@@ -258,13 +260,15 @@
.ucom_start_write = &umoscom_start_write,
.ucom_stop_write = &umoscom_stop_write,
.ucom_poll = &umoscom_poll,
+ .ucom_free = &umoscom_free,
};
static device_method_t umoscom_methods[] = {
DEVMETHOD(device_probe, umoscom_probe),
DEVMETHOD(device_attach, umoscom_attach),
DEVMETHOD(device_detach, umoscom_detach),
- {0, 0}
+ DEVMETHOD(device_free_softc, umoscom_free_softc),
+ DEVMETHOD_END
};
static devclass_t umoscom_devclass;
@@ -317,6 +321,7 @@
device_printf(dev, "<MOSCHIP USB Serial Port Adapter>\n");
mtx_init(&sc->sc_mtx, "umoscom", NULL, MTX_DEF);
+ ucom_ref(&sc->sc_super_ucom);
iface_index = UMOSCOM_IFACE_INDEX;
error = usbd_transfer_setup(uaa->device, &iface_index,
@@ -354,11 +359,30 @@
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
usbd_transfer_unsetup(sc->sc_xfer, UMOSCOM_N_TRANSFER);
- mtx_destroy(&sc->sc_mtx);
return (0);
}
+UCOM_UNLOAD_DRAIN(umoscom);
+
+static void
+umoscom_free_softc(device_t dev, void *arg)
+{
+ struct umoscom_softc *sc = arg;
+
+ if (ucom_unref(&sc->sc_super_ucom)) {
+ if (mtx_initialized(&sc->sc_mtx))
+ mtx_destroy(&sc->sc_mtx);
+ device_free_softc(dev, sc);
+ }
+}
+
+static void
+umoscom_free(struct ucom_softc *ucom)
+{
+ umoscom_free_softc(NULL, ucom->sc_parent);
+}
+
static void
umoscom_cfg_open(struct ucom_softc *ucom)
{
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/uplcom.c
--- a/head/sys/dev/usb/serial/uplcom.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/uplcom.c Wed Aug 15 11:46:11 2012 +0300
@@ -1,7 +1,7 @@
/* $NetBSD: uplcom.c,v 1.21 2001/11/13 06:24:56 lukem Exp $ */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/uplcom.c 238766 2012-07-25 11:33:43Z gavin $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/uplcom.c 239180 2012-08-10 15:29:41Z hselasky $");
/*-
* Copyright (c) 2001-2003, 2005 Shunsuke Akiyama <akiyama at jp.FreeBSD.org>.
@@ -176,6 +176,7 @@
static usb_error_t uplcom_pl2303_do(struct usb_device *, int8_t, uint8_t,
uint16_t, uint16_t, uint16_t);
static int uplcom_pl2303_init(struct usb_device *, uint8_t);
+static void uplcom_free(struct ucom_softc *);
static void uplcom_cfg_set_dtr(struct ucom_softc *, uint8_t);
static void uplcom_cfg_set_rts(struct ucom_softc *, uint8_t);
static void uplcom_cfg_set_break(struct ucom_softc *, uint8_t);
@@ -192,6 +193,7 @@
static device_probe_t uplcom_probe;
static device_attach_t uplcom_attach;
static device_detach_t uplcom_detach;
+static device_free_softc_t uplcom_free_softc;
static usb_callback_t uplcom_intr_callback;
static usb_callback_t uplcom_write_callback;
@@ -242,6 +244,7 @@
.ucom_start_write = &uplcom_start_write,
.ucom_stop_write = &uplcom_stop_write,
.ucom_poll = &uplcom_poll,
+ .ucom_free = &uplcom_free,
};
#define UPLCOM_DEV(v,p) \
@@ -315,7 +318,8 @@
DEVMETHOD(device_probe, uplcom_probe),
DEVMETHOD(device_attach, uplcom_attach),
DEVMETHOD(device_detach, uplcom_detach),
- {0, 0}
+ DEVMETHOD(device_free_softc, uplcom_free_softc),
+ DEVMETHOD_END
};
static devclass_t uplcom_devclass;
@@ -364,6 +368,7 @@
device_set_usb_desc(dev);
mtx_init(&sc->sc_mtx, "uplcom", NULL, MTX_DEF);
+ ucom_ref(&sc->sc_super_ucom);
DPRINTF("sc = %p\n", sc);
@@ -465,11 +470,30 @@
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
usbd_transfer_unsetup(sc->sc_xfer, UPLCOM_N_TRANSFER);
- mtx_destroy(&sc->sc_mtx);
return (0);
}
+UCOM_UNLOAD_DRAIN(uplcom);
+
+static void
+uplcom_free_softc(device_t dev, void *arg)
+{
+ struct uplcom_softc *sc = arg;
+
+ if (ucom_unref(&sc->sc_super_ucom)) {
+ if (mtx_initialized(&sc->sc_mtx))
+ mtx_destroy(&sc->sc_mtx);
+ device_free_softc(dev, sc);
+ }
+}
+
+static void
+uplcom_free(struct ucom_softc *ucom)
+{
+ uplcom_free_softc(NULL, ucom->sc_parent);
+}
+
static usb_error_t
uplcom_reset(struct uplcom_softc *sc, struct usb_device *udev)
{
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/usb_serial.c
--- a/head/sys/dev/usb/serial/usb_serial.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/usb_serial.c Wed Aug 15 11:46:11 2012 +0300
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/usb_serial.c 233774 2012-04-02 10:50:42Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/usb_serial.c 239179 2012-08-10 15:21:12Z hselasky $");
/*-
* Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
@@ -146,7 +146,7 @@
static int ucom_unit_alloc(void);
static void ucom_unit_free(int);
static int ucom_attach_tty(struct ucom_super_softc *, struct ucom_softc *);
-static void ucom_detach_tty(struct ucom_softc *);
+static void ucom_detach_tty(struct ucom_super_softc *, struct ucom_softc *);
static void ucom_queue_command(struct ucom_softc *,
usb_proc_callback_t *, struct termios *pt,
struct usb_proc_msg *t0, struct usb_proc_msg *t1);
@@ -178,13 +178,37 @@
MODULE_DEPEND(ucom, usb, 1, 1, 1);
MODULE_VERSION(ucom, 1);
-#define UCOM_UNIT_MAX 128 /* limits size of ucom_bitmap */
+#define UCOM_UNIT_MAX 128 /* maximum number of units */
+#define UCOM_TTY_PREFIX "U"
-static uint8_t ucom_bitmap[(UCOM_UNIT_MAX + 7) / 8];
-static struct mtx ucom_bitmap_mtx;
-MTX_SYSINIT(ucom_bitmap_mtx, &ucom_bitmap_mtx, "ucom bitmap", MTX_DEF);
+static struct unrhdr *ucom_unrhdr;
+static struct mtx ucom_mtx;
+static int ucom_close_refs;
-#define UCOM_TTY_PREFIX "U"
+static void
+ucom_init(void *arg)
+{
+ DPRINTF("\n");
+ ucom_unrhdr = new_unrhdr(0, UCOM_UNIT_MAX - 1, NULL);
+ mtx_init(&ucom_mtx, "UCOM MTX", NULL, MTX_DEF);
+}
+SYSINIT(ucom_init, SI_SUB_KLD - 1, SI_ORDER_ANY, ucom_init, NULL);
+
+static void
+ucom_uninit(void *arg)
+{
+ struct unrhdr *hdr;
+ hdr = ucom_unrhdr;
+ ucom_unrhdr = NULL;
+
+ DPRINTF("\n");
+
+ if (hdr != NULL)
+ delete_unrhdr(hdr);
+
+ mtx_destroy(&ucom_mtx);
+}
+SYSUNINIT(ucom_uninit, SI_SUB_KLD - 2, SI_ORDER_ANY, ucom_uninit, NULL);
/*
* Mark a unit number (the X in cuaUX) as in use.
@@ -197,21 +221,14 @@
{
int unit;
- mtx_lock(&ucom_bitmap_mtx);
-
- for (unit = 0; unit < UCOM_UNIT_MAX; unit++) {
- if ((ucom_bitmap[unit / 8] & (1 << (unit % 8))) == 0) {
- ucom_bitmap[unit / 8] |= (1 << (unit % 8));
- break;
- }
+ /* sanity checks */
+ if (ucom_unrhdr == NULL) {
+ DPRINTF("ucom_unrhdr is NULL\n");
+ return (-1);
}
-
- mtx_unlock(&ucom_bitmap_mtx);
-
- if (unit == UCOM_UNIT_MAX)
- return -1;
- else
- return unit;
+ unit = alloc_unr(ucom_unrhdr);
+ DPRINTF("unit %d is allocated\n", unit);
+ return (unit);
}
/*
@@ -220,11 +237,13 @@
static void
ucom_unit_free(int unit)
{
- mtx_lock(&ucom_bitmap_mtx);
-
- ucom_bitmap[unit / 8] &= ~(1 << (unit % 8));
-
- mtx_unlock(&ucom_bitmap_mtx);
+ /* sanity checks */
+ if (unit < 0 || unit >= UCOM_UNIT_MAX || ucom_unrhdr == NULL) {
+ DPRINTF("cannot free unit number\n");
+ return;
+ }
+ DPRINTF("unit %d is freed\n", unit);
+ free_unr(ucom_unrhdr, unit);
}
/*
@@ -244,7 +263,8 @@
if ((sc == NULL) ||
(subunits <= 0) ||
- (callback == NULL)) {
+ (callback == NULL) ||
+ (mtx == NULL)) {
return (EINVAL);
}
@@ -265,6 +285,11 @@
}
ssc->sc_subunits = subunits;
+ if (callback->ucom_free == NULL) {
+ ssc->sc_wait_refs = 1;
+ ucom_ref(ssc);
+ }
+
for (subunit = 0; subunit < ssc->sc_subunits; subunit++) {
sc[subunit].sc_subunit = subunit;
sc[subunit].sc_super = ssc;
@@ -277,6 +302,10 @@
ucom_detach(ssc, &sc[0]);
return (error);
}
+ /* increment reference count */
+ ucom_ref(ssc);
+
+ /* set subunit attached */
sc[subunit].sc_flag |= UCOM_FLAG_ATTACHED;
}
@@ -313,14 +342,41 @@
for (subunit = 0; subunit < ssc->sc_subunits; subunit++) {
if (sc[subunit].sc_flag & UCOM_FLAG_ATTACHED) {
- ucom_detach_tty(&sc[subunit]);
+ ucom_detach_tty(ssc, &sc[subunit]);
/* avoid duplicate detach */
sc[subunit].sc_flag &= ~UCOM_FLAG_ATTACHED;
}
}
- ucom_unit_free(ssc->sc_unit);
usb_proc_free(&ssc->sc_tq);
+
+ if (ssc->sc_wait_refs != 0) {
+ ucom_unref(ssc);
+ ucom_drain(ssc);
+ }
+}
+
+void
+ucom_drain(struct ucom_super_softc *ssc)
+{
+ mtx_lock(&ucom_mtx);
+ while (ssc->sc_refs >= 2) {
+ printf("ucom: Waiting for a TTY device to close.\n");
+ usb_pause_mtx(&ucom_mtx, hz);
+ }
+ mtx_unlock(&ucom_mtx);
+}
+
+void
+ucom_drain_all(void *arg)
+{
+ mtx_lock(&ucom_mtx);
+ while (ucom_close_refs > 0) {
+ printf("ucom: Waiting for all detached TTY "
+ "devices to have open fds closed.\n");
+ usb_pause_mtx(&ucom_mtx, hz);
+ }
+ mtx_unlock(&ucom_mtx);
}
static int
@@ -349,7 +405,6 @@
sc->sc_tty = tp;
DPRINTF("ttycreate: %s\n", buf);
- cv_init(&sc->sc_cv, "ucom");
/* Check if this device should be a console */
if ((ucom_cons_softc == NULL) &&
@@ -366,7 +421,7 @@
t.c_ospeed = t.c_ispeed;
t.c_cflag = CS8;
- mtx_lock(ucom_cons_softc->sc_mtx);
+ UCOM_MTX_LOCK(ucom_cons_softc);
ucom_cons_rx_low = 0;
ucom_cons_rx_high = 0;
ucom_cons_tx_low = 0;
@@ -374,56 +429,55 @@
sc->sc_flag |= UCOM_FLAG_CONSOLE;
ucom_open(ucom_cons_softc->sc_tty);
ucom_param(ucom_cons_softc->sc_tty, &t);
- mtx_unlock(ucom_cons_softc->sc_mtx);
+ UCOM_MTX_UNLOCK(ucom_cons_softc);
}
return (0);
}
static void
-ucom_detach_tty(struct ucom_softc *sc)
+ucom_detach_tty(struct ucom_super_softc *ssc, struct ucom_softc *sc)
{
struct tty *tp = sc->sc_tty;
DPRINTF("sc = %p, tp = %p\n", sc, sc->sc_tty);
if (sc->sc_flag & UCOM_FLAG_CONSOLE) {
- mtx_lock(ucom_cons_softc->sc_mtx);
+ UCOM_MTX_LOCK(ucom_cons_softc);
ucom_close(ucom_cons_softc->sc_tty);
sc->sc_flag &= ~UCOM_FLAG_CONSOLE;
- mtx_unlock(ucom_cons_softc->sc_mtx);
+ UCOM_MTX_UNLOCK(ucom_cons_softc);
ucom_cons_softc = NULL;
}
/* the config thread has been stopped when we get here */
- mtx_lock(sc->sc_mtx);
+ UCOM_MTX_LOCK(sc);
sc->sc_flag |= UCOM_FLAG_GONE;
sc->sc_flag &= ~(UCOM_FLAG_HL_READY | UCOM_FLAG_LL_READY);
- mtx_unlock(sc->sc_mtx);
+ UCOM_MTX_UNLOCK(sc);
+
if (tp) {
+ mtx_lock(&ucom_mtx);
+ ucom_close_refs++;
+ mtx_unlock(&ucom_mtx);
+
tty_lock(tp);
ucom_close(tp); /* close, if any */
tty_rel_gone(tp);
- mtx_lock(sc->sc_mtx);
- /* Wait for the callback after the TTY is torn down */
- while (sc->sc_ttyfreed == 0)
- cv_wait(&sc->sc_cv, sc->sc_mtx);
+ UCOM_MTX_LOCK(sc);
/*
* make sure that read and write transfers are stopped
*/
- if (sc->sc_callback->ucom_stop_read) {
+ if (sc->sc_callback->ucom_stop_read)
(sc->sc_callback->ucom_stop_read) (sc);
- }
- if (sc->sc_callback->ucom_stop_write) {
+ if (sc->sc_callback->ucom_stop_write)
(sc->sc_callback->ucom_stop_write) (sc);
- }
- mtx_unlock(sc->sc_mtx);
+ UCOM_MTX_UNLOCK(sc);
}
- cv_destroy(&sc->sc_cv);
}
void
@@ -469,7 +523,7 @@
struct ucom_super_softc *ssc = sc->sc_super;
struct ucom_param_task *task;
- mtx_assert(sc->sc_mtx, MA_OWNED);
+ UCOM_MTX_ASSERT(sc, MA_OWNED);
if (usb_proc_is_gone(&ssc->sc_tq)) {
DPRINTF("proc is gone\n");
@@ -513,7 +567,7 @@
{
struct tty *tp = sc->sc_tty;
- mtx_assert(sc->sc_mtx, MA_OWNED);
+ UCOM_MTX_ASSERT(sc, MA_OWNED);
DPRINTF("\n");
@@ -614,7 +668,7 @@
struct ucom_softc *sc = tty_softc(tp);
int error;
- mtx_assert(sc->sc_mtx, MA_OWNED);
+ UCOM_MTX_ASSERT(sc, MA_OWNED);
if (sc->sc_flag & UCOM_FLAG_GONE) {
return (ENXIO);
@@ -692,7 +746,7 @@
{
struct ucom_softc *sc = tty_softc(tp);
- mtx_assert(sc->sc_mtx, MA_OWNED);
+ UCOM_MTX_ASSERT(sc, MA_OWNED);
DPRINTF("tp=%p\n", tp);
@@ -719,7 +773,7 @@
struct ucom_softc *sc = tty_softc(tp);
int error;
- mtx_assert(sc->sc_mtx, MA_OWNED);
+ UCOM_MTX_ASSERT(sc, MA_OWNED);
if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
return (EIO);
@@ -763,7 +817,7 @@
struct ucom_softc *sc = tty_softc(tp);
uint8_t onoff;
- mtx_assert(sc->sc_mtx, MA_OWNED);
+ UCOM_MTX_ASSERT(sc, MA_OWNED);
if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
return (0);
@@ -882,7 +936,7 @@
ucom_line_state(struct ucom_softc *sc,
uint8_t set_bits, uint8_t clear_bits)
{
- mtx_assert(sc->sc_mtx, MA_OWNED);
+ UCOM_MTX_ASSERT(sc, MA_OWNED);
if (!(sc->sc_flag & UCOM_FLAG_HL_READY)) {
return;
@@ -960,7 +1014,7 @@
tp = sc->sc_tty;
- mtx_assert(sc->sc_mtx, MA_OWNED);
+ UCOM_MTX_ASSERT(sc, MA_OWNED);
if (!(sc->sc_flag & UCOM_FLAG_LL_READY)) {
return;
@@ -1022,7 +1076,7 @@
void
ucom_status_change(struct ucom_softc *sc)
{
- mtx_assert(sc->sc_mtx, MA_OWNED);
+ UCOM_MTX_ASSERT(sc, MA_OWNED);
if (sc->sc_flag & UCOM_FLAG_CONSOLE)
return; /* not supported */
@@ -1064,7 +1118,7 @@
uint8_t opened;
int error;
- mtx_assert(sc->sc_mtx, MA_OWNED);
+ UCOM_MTX_ASSERT(sc, MA_OWNED);
opened = 0;
error = 0;
@@ -1131,7 +1185,7 @@
{
struct ucom_softc *sc = tty_softc(tp);
- mtx_assert(sc->sc_mtx, MA_OWNED);
+ UCOM_MTX_ASSERT(sc, MA_OWNED);
DPRINTF("sc = %p\n", sc);
@@ -1158,7 +1212,7 @@
uint32_t cnt;
uint32_t offset_orig;
- mtx_assert(sc->sc_mtx, MA_OWNED);
+ UCOM_MTX_ASSERT(sc, MA_OWNED);
if (sc->sc_flag & UCOM_FLAG_CONSOLE) {
unsigned int temp;
@@ -1237,7 +1291,7 @@
char *buf;
uint32_t cnt;
- mtx_assert(sc->sc_mtx, MA_OWNED);
+ UCOM_MTX_ASSERT(sc, MA_OWNED);
if (sc->sc_flag & UCOM_FLAG_CONSOLE) {
unsigned int temp;
@@ -1318,10 +1372,14 @@
{
struct ucom_softc *sc = xsc;
- mtx_lock(sc->sc_mtx);
- sc->sc_ttyfreed = 1;
- cv_signal(&sc->sc_cv);
- mtx_unlock(sc->sc_mtx);
+ if (sc->sc_callback->ucom_free != NULL)
+ sc->sc_callback->ucom_free(sc);
+ else
+ ucom_unref(sc->sc_super);
+
+ mtx_lock(&ucom_mtx);
+ ucom_close_refs--;
+ mtx_unlock(&ucom_mtx);
}
static cn_probe_t ucom_cnprobe;
@@ -1374,7 +1432,7 @@
if (sc == NULL)
return (-1);
- mtx_lock(sc->sc_mtx);
+ UCOM_MTX_LOCK(sc);
if (ucom_cons_rx_low != ucom_cons_rx_high) {
c = ucom_cons_rx_buf[ucom_cons_rx_low];
@@ -1387,7 +1445,7 @@
/* start USB transfers */
ucom_outwakeup(sc->sc_tty);
- mtx_unlock(sc->sc_mtx);
+ UCOM_MTX_UNLOCK(sc);
/* poll if necessary */
if (kdb_active && sc->sc_callback->ucom_poll)
@@ -1407,7 +1465,7 @@
repeat:
- mtx_lock(sc->sc_mtx);
+ UCOM_MTX_LOCK(sc);
/* compute maximum TX length */
@@ -1423,7 +1481,7 @@
/* start USB transfers */
ucom_outwakeup(sc->sc_tty);
- mtx_unlock(sc->sc_mtx);
+ UCOM_MTX_UNLOCK(sc);
/* poll if necessary */
if (kdb_active && sc->sc_callback->ucom_poll) {
@@ -1434,6 +1492,50 @@
}
}
+/*------------------------------------------------------------------------*
+ * ucom_ref
+ *
+ * This function will increment the super UCOM reference count.
+ *------------------------------------------------------------------------*/
+void
+ucom_ref(struct ucom_super_softc *ssc)
+{
+ mtx_lock(&ucom_mtx);
+ ssc->sc_refs++;
+ mtx_unlock(&ucom_mtx);
+}
+
+/*------------------------------------------------------------------------*
+ * ucom_unref
+ *
+ * This function will decrement the super UCOM reference count.
+ *
+ * Return values:
+ * 0: UCOM structures are still referenced.
+ * Else: UCOM structures are no longer referenced.
+ *------------------------------------------------------------------------*/
+int
+ucom_unref(struct ucom_super_softc *ssc)
+{
+ int retval;
+ int free_unit;
+
+ mtx_lock(&ucom_mtx);
+ retval = (ssc->sc_refs < 2);
+ free_unit = (ssc->sc_refs == 1);
+ ssc->sc_refs--;
+ mtx_unlock(&ucom_mtx);
+
+ /*
+ * This function might be called when the "ssc" is only zero
+ * initialized and in that case the unit number should not be
+ * freed.
+ */
+ if (free_unit)
+ ucom_unit_free(ssc->sc_unit);
+ return (retval);
+}
+
#if defined(GDB)
#include <gdb/gdb.h>
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/usb_serial.h
--- a/head/sys/dev/usb/serial/usb_serial.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/usb_serial.h Wed Aug 15 11:46:11 2012 +0300
@@ -1,5 +1,5 @@
/* $NetBSD: ucomvar.h,v 1.9 2001/01/23 21:56:17 augustss Exp $ */
-/* $FreeBSD: head/sys/dev/usb/serial/usb_serial.h 233774 2012-04-02 10:50:42Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/serial/usb_serial.h 239179 2012-08-10 15:21:12Z hselasky $ */
/*-
* Copyright (c) 2001-2002, Shunsuke Akiyama <akiyama at jp.FreeBSD.org>.
@@ -107,6 +107,7 @@
void (*ucom_stop_write) (struct ucom_softc *);
void (*ucom_tty_name) (struct ucom_softc *, char *pbuf, uint16_t buflen, uint16_t unit, uint16_t subunit);
void (*ucom_poll) (struct ucom_softc *);
+ void (*ucom_free) (struct ucom_softc *);
};
/* Line status register */
@@ -135,6 +136,8 @@
struct usb_process sc_tq;
int sc_unit;
int sc_subunits;
+ int sc_refs;
+ int sc_wait_refs;
struct sysctl_oid *sc_sysctl_ttyname;
struct sysctl_oid *sc_sysctl_ttyports;
char sc_ttyname[16];
@@ -158,7 +161,6 @@
struct ucom_cfg_task sc_line_state_task[2];
struct ucom_cfg_task sc_status_task[2];
struct ucom_param_task sc_param_task[2];
- struct cv sc_cv;
/* Used to set "UCOM_FLAG_GP_DATA" flag: */
struct usb_proc_msg *sc_last_start_xfer;
const struct ucom_callback *sc_callback;
@@ -179,7 +181,6 @@
uint8_t sc_lsr;
uint8_t sc_msr;
uint8_t sc_mcr;
- uint8_t sc_ttyfreed; /* set when TTY has been freed */
/* programmed line state bits */
uint8_t sc_pls_set; /* set bits */
uint8_t sc_pls_clr; /* cleared bits */
@@ -190,6 +191,12 @@
#define UCOM_LS_RING 0x08
};
+#define UCOM_MTX_ASSERT(sc, what) mtx_assert((sc)->sc_mtx, what)
+#define UCOM_MTX_LOCK(sc) mtx_lock((sc)->sc_mtx)
+#define UCOM_MTX_UNLOCK(sc) mtx_unlock((sc)->sc_mtx)
+#define UCOM_UNLOAD_DRAIN(x) \
+SYSUNINIT(var, SI_SUB_KLD - 3, SI_ORDER_ANY, ucom_drain_all, 0)
+
#define ucom_cfg_do_request(udev,com,req,ptr,flags,timo) \
usbd_do_request_proc(udev,&(com)->sc_super->sc_tq,req,ptr,flags,NULL,timo)
@@ -204,4 +211,8 @@
void ucom_put_data(struct ucom_softc *, struct usb_page_cache *,
uint32_t, uint32_t);
uint8_t ucom_cfg_is_gone(struct ucom_softc *);
+void ucom_drain(struct ucom_super_softc *);
+void ucom_drain_all(void *);
+void ucom_ref(struct ucom_super_softc *);
+int ucom_unref(struct ucom_super_softc *);
#endif /* _USB_SERIAL_H_ */
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/uslcom.c
--- a/head/sys/dev/usb/serial/uslcom.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/uslcom.c Wed Aug 15 11:46:11 2012 +0300
@@ -1,7 +1,7 @@
/* $OpenBSD: uslcom.c,v 1.17 2007/11/24 10:52:12 jsg Exp $ */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/uslcom.c 239050 2012-08-05 08:56:29Z hselasky $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/uslcom.c 239260 2012-08-14 22:21:46Z gavin $");
/*
* Copyright (c) 2006 Jonathan Gray <jsg at openbsd.org>
@@ -19,6 +19,12 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/*
+ * Driver for Silicon Laboratories CP2101/CP2102/CP2103/CP2104/CP2105
+ * USB-Serial adapters. Based on datasheet AN571, publicly available from
+ * http://www.silabs.com/Support%20Documents/TechnicalDocs/AN571.pdf
+ */
+
#include <sys/stdint.h>
#include <sys/stddef.h>
#include <sys/param.h>
@@ -61,55 +67,54 @@
#define USLCOM_BULK_BUF_SIZE 1024
#define USLCOM_CONFIG_INDEX 0
-#define USLCOM_SET_DATA_BITS(x) ((x) << 8)
-
/* Request types */
#define USLCOM_WRITE 0x41
#define USLCOM_READ 0xc1
/* Request codes */
-#define USLCOM_UART 0x00
-#define USLCOM_SET_BAUD_DIV 0x01
-#define USLCOM_DATA 0x03
-#define USLCOM_BREAK 0x05
-#define USLCOM_CTRL 0x07
-#define USLCOM_RCTRL 0x08
-#define USLCOM_SET_FLOWCTRL 0x13
-#define USLCOM_SET_BAUD_RATE 0x1e
+#define USLCOM_IFC_ENABLE 0x00
+#define USLCOM_SET_BAUDDIV 0x01
+#define USLCOM_SET_LINE_CTL 0x03
+#define USLCOM_SET_BREAK 0x05
+#define USLCOM_SET_MHS 0x07
+#define USLCOM_GET_MDMSTS 0x08
+#define USLCOM_SET_FLOW 0x13
+#define USLCOM_SET_BAUDRATE 0x1e
#define USLCOM_VENDOR_SPECIFIC 0xff
-/* USLCOM_UART values */
-#define USLCOM_UART_DISABLE 0x00
-#define USLCOM_UART_ENABLE 0x01
+/* USLCOM_IFC_ENABLE values */
+#define USLCOM_IFC_ENABLE_DIS 0x00
+#define USLCOM_IFC_ENABLE_EN 0x01
-/* USLCOM_CTRL/USLCOM_RCTRL values */
-#define USLCOM_CTRL_DTR_ON 0x0001
-#define USLCOM_CTRL_DTR_SET 0x0100
-#define USLCOM_CTRL_RTS_ON 0x0002
-#define USLCOM_CTRL_RTS_SET 0x0200
-#define USLCOM_CTRL_CTS 0x0010
-#define USLCOM_CTRL_DSR 0x0020
-#define USLCOM_CTRL_RI 0x0040
-#define USLCOM_CTRL_DCD 0x0080
+/* USLCOM_SET_MHS/USLCOM_GET_MDMSTS values */
+#define USLCOM_MHS_DTR_ON 0x0001
+#define USLCOM_MHS_DTR_SET 0x0100
+#define USLCOM_MHS_RTS_ON 0x0002
+#define USLCOM_MHS_RTS_SET 0x0200
+#define USLCOM_MHS_CTS 0x0010
+#define USLCOM_MHS_DSR 0x0020
+#define USLCOM_MHS_RI 0x0040
+#define USLCOM_MHS_DCD 0x0080
-/* USLCOM_SET_BAUD_DIV values */
-#define USLCOM_BAUD_REF 3686400 /* 3.6864 MHz */
+/* USLCOM_SET_BAUDDIV values */
+#define USLCOM_BAUDDIV_REF 3686400 /* 3.6864 MHz */
-/* USLCOM_DATA values */
+/* USLCOM_SET_LINE_CTL values */
#define USLCOM_STOP_BITS_1 0x00
#define USLCOM_STOP_BITS_2 0x02
#define USLCOM_PARITY_NONE 0x00
#define USLCOM_PARITY_ODD 0x10
#define USLCOM_PARITY_EVEN 0x20
+#define USLCOM_SET_DATA_BITS(x) ((x) << 8)
-/* USLCOM_BREAK values */
-#define USLCOM_BREAK_OFF 0x00
-#define USLCOM_BREAK_ON 0x01
+/* USLCOM_SET_BREAK values */
+#define USLCOM_SET_BREAK_OFF 0x00
+#define USLCOM_SET_BREAK_ON 0x01
-/* USLCOM_SET_FLOWCTRL values - 1st word */
+/* USLCOM_SET_FLOW values - 1st word */
#define USLCOM_FLOW_DTR_ON 0x00000001 /* DTR static active */
#define USLCOM_FLOW_CTS_HS 0x00000008 /* CTS handshake */
-/* USLCOM_SET_FLOWCTRL values - 2nd word */
+/* USLCOM_SET_FLOW values - 2nd word */
#define USLCOM_FLOW_RTS_ON 0x00000040 /* RTS static active */
#define USLCOM_FLOW_RTS_HS 0x00000080 /* RTS handshake */
@@ -141,11 +146,13 @@
static device_probe_t uslcom_probe;
static device_attach_t uslcom_attach;
static device_detach_t uslcom_detach;
+static device_free_softc_t uslcom_free_softc;
static usb_callback_t uslcom_write_callback;
static usb_callback_t uslcom_read_callback;
static usb_callback_t uslcom_control_callback;
+static void uslcom_free(struct ucom_softc *);
static void uslcom_open(struct ucom_softc *);
static void uslcom_close(struct ucom_softc *);
static void uslcom_set_dtr(struct ucom_softc *, uint8_t);
@@ -207,6 +214,7 @@
.ucom_start_write = &uslcom_start_write,
.ucom_stop_write = &uslcom_stop_write,
.ucom_poll = &uslcom_poll,
+ .ucom_free = &uslcom_free,
};
static const STRUCT_USB_HOST_ID uslcom_devs[] = {
@@ -323,7 +331,8 @@
DEVMETHOD(device_probe, uslcom_probe),
DEVMETHOD(device_attach, uslcom_attach),
DEVMETHOD(device_detach, uslcom_detach),
- {0, 0}
+ DEVMETHOD(device_free_softc, uslcom_free_softc),
+ DEVMETHOD_END
};
static devclass_t uslcom_devclass;
@@ -379,6 +388,7 @@
device_set_usb_desc(dev);
mtx_init(&sc->sc_mtx, "uslcom", NULL, MTX_DEF);
+ ucom_ref(&sc->sc_super_ucom);
usb_callout_init_mtx(&sc->sc_watchdog, &sc->sc_mtx, 0);
sc->sc_udev = uaa->device;
@@ -424,11 +434,30 @@
usbd_transfer_unsetup(sc->sc_xfer, USLCOM_N_TRANSFER);
usb_callout_drain(&sc->sc_watchdog);
- mtx_destroy(&sc->sc_mtx);
return (0);
}
+UCOM_UNLOAD_DRAIN(uslcom);
+
+static void
+uslcom_free_softc(device_t dev, void *arg)
+{
+ struct uslcom_softc *sc = arg;
+
+ if (ucom_unref(&sc->sc_super_ucom)) {
+ if (mtx_initialized(&sc->sc_mtx))
+ mtx_destroy(&sc->sc_mtx);
+ device_free_softc(dev, sc);
+ }
+}
+
+static void
+uslcom_free(struct ucom_softc *ucom)
+{
+ uslcom_free_softc(NULL, ucom->sc_parent);
+}
+
static void
uslcom_open(struct ucom_softc *ucom)
{
@@ -436,8 +465,8 @@
struct usb_device_request req;
req.bmRequestType = USLCOM_WRITE;
- req.bRequest = USLCOM_UART;
- USETW(req.wValue, USLCOM_UART_ENABLE);
+ req.bRequest = USLCOM_IFC_ENABLE;
+ USETW(req.wValue, USLCOM_IFC_ENABLE_EN);
USETW(req.wIndex, sc->sc_iface_no);
USETW(req.wLength, 0);
@@ -460,8 +489,8 @@
usb_callout_stop(&sc->sc_watchdog);
req.bmRequestType = USLCOM_WRITE;
- req.bRequest = USLCOM_UART;
- USETW(req.wValue, USLCOM_UART_DISABLE);
+ req.bRequest = USLCOM_IFC_ENABLE;
+ USETW(req.wValue, USLCOM_IFC_ENABLE_DIS);
USETW(req.wIndex, sc->sc_iface_no);
USETW(req.wLength, 0);
@@ -480,11 +509,11 @@
DPRINTF("onoff = %d\n", onoff);
- ctl = onoff ? USLCOM_CTRL_DTR_ON : 0;
- ctl |= USLCOM_CTRL_DTR_SET;
+ ctl = onoff ? USLCOM_MHS_DTR_ON : 0;
+ ctl |= USLCOM_MHS_DTR_SET;
req.bmRequestType = USLCOM_WRITE;
- req.bRequest = USLCOM_CTRL;
+ req.bRequest = USLCOM_SET_MHS;
USETW(req.wValue, ctl);
USETW(req.wIndex, sc->sc_iface_no);
USETW(req.wLength, 0);
@@ -504,11 +533,11 @@
DPRINTF("onoff = %d\n", onoff);
- ctl = onoff ? USLCOM_CTRL_RTS_ON : 0;
- ctl |= USLCOM_CTRL_RTS_SET;
+ ctl = onoff ? USLCOM_MHS_RTS_ON : 0;
+ ctl |= USLCOM_MHS_RTS_SET;
req.bmRequestType = USLCOM_WRITE;
- req.bRequest = USLCOM_CTRL;
+ req.bRequest = USLCOM_SET_MHS;
USETW(req.wValue, ctl);
USETW(req.wIndex, sc->sc_iface_no);
USETW(req.wLength, 0);
@@ -539,7 +568,7 @@
baudrate = t->c_ospeed;
req.bmRequestType = USLCOM_WRITE;
- req.bRequest = USLCOM_SET_BAUD_RATE;
+ req.bRequest = USLCOM_SET_BAUDRATE;
USETW(req.wValue, 0);
USETW(req.wIndex, sc->sc_iface_no);
USETW(req.wLength, sizeof(baudrate));
@@ -576,7 +605,7 @@
}
req.bmRequestType = USLCOM_WRITE;
- req.bRequest = USLCOM_DATA;
+ req.bRequest = USLCOM_SET_LINE_CTL;
USETW(req.wValue, data);
USETW(req.wIndex, sc->sc_iface_no);
USETW(req.wLength, 0);
@@ -589,16 +618,14 @@
if (t->c_cflag & CRTSCTS) {
flowctrl[0] = htole32(USLCOM_FLOW_DTR_ON | USLCOM_FLOW_CTS_HS);
flowctrl[1] = htole32(USLCOM_FLOW_RTS_HS);
- flowctrl[2] = 0;
- flowctrl[3] = 0;
} else {
flowctrl[0] = htole32(USLCOM_FLOW_DTR_ON);
flowctrl[1] = htole32(USLCOM_FLOW_RTS_ON);
- flowctrl[2] = 0;
- flowctrl[3] = 0;
}
+ flowctrl[2] = 0;
+ flowctrl[3] = 0;
req.bmRequestType = USLCOM_WRITE;
- req.bRequest = USLCOM_SET_FLOWCTRL;
+ req.bRequest = USLCOM_SET_FLOW;
USETW(req.wValue, 0);
USETW(req.wIndex, sc->sc_iface_no);
USETW(req.wLength, sizeof(flowctrl));
@@ -625,10 +652,10 @@
{
struct uslcom_softc *sc = ucom->sc_parent;
struct usb_device_request req;
- uint16_t brk = onoff ? USLCOM_BREAK_ON : USLCOM_BREAK_OFF;
+ uint16_t brk = onoff ? USLCOM_SET_BREAK_ON : USLCOM_SET_BREAK_OFF;
req.bmRequestType = USLCOM_WRITE;
- req.bRequest = USLCOM_BREAK;
+ req.bRequest = USLCOM_SET_BREAK;
USETW(req.wValue, brk);
USETW(req.wIndex, sc->sc_iface_no);
USETW(req.wLength, 0);
@@ -763,13 +790,13 @@
case USB_ST_TRANSFERRED:
pc = usbd_xfer_get_frame(xfer, 1);
usbd_copy_out(pc, 0, &buf, sizeof(buf));
- if (buf & USLCOM_CTRL_CTS)
+ if (buf & USLCOM_MHS_CTS)
msr |= SER_CTS;
- if (buf & USLCOM_CTRL_DSR)
+ if (buf & USLCOM_MHS_DSR)
msr |= SER_DSR;
- if (buf & USLCOM_CTRL_RI)
+ if (buf & USLCOM_MHS_RI)
msr |= SER_RI;
- if (buf & USLCOM_CTRL_DCD)
+ if (buf & USLCOM_MHS_DCD)
msr |= SER_DCD;
if (msr != sc->sc_msr) {
@@ -782,7 +809,7 @@
case USB_ST_SETUP:
req.bmRequestType = USLCOM_READ;
- req.bRequest = USLCOM_RCTRL;
+ req.bRequest = USLCOM_GET_MDMSTS;
USETW(req.wValue, 0);
USETW(req.wIndex, sc->sc_iface_no);
USETW(req.wLength, sizeof(buf));
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/uvisor.c
--- a/head/sys/dev/usb/serial/uvisor.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/uvisor.c Wed Aug 15 11:46:11 2012 +0300
@@ -1,5 +1,5 @@
/* $NetBSD: uvisor.c,v 1.9 2001/01/23 14:04:14 augustss Exp $ */
-/* $FreeBSD: head/sys/dev/usb/serial/uvisor.c 227461 2011-11-12 08:16:45Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/serial/uvisor.c 239180 2012-08-10 15:29:41Z hselasky $ */
/* Also already merged from NetBSD:
* $NetBSD: uvisor.c,v 1.12 2001/11/13 06:24:57 lukem Exp $
@@ -189,12 +189,14 @@
static device_probe_t uvisor_probe;
static device_attach_t uvisor_attach;
static device_detach_t uvisor_detach;
+static device_free_softc_t uvisor_free_softc;
static usb_callback_t uvisor_write_callback;
static usb_callback_t uvisor_read_callback;
static usb_error_t uvisor_init(struct uvisor_softc *, struct usb_device *,
struct usb_config *);
+static void uvisor_free(struct ucom_softc *);
static void uvisor_cfg_open(struct ucom_softc *);
static void uvisor_cfg_close(struct ucom_softc *);
static void uvisor_start_read(struct ucom_softc *);
@@ -231,13 +233,15 @@
.ucom_stop_read = &uvisor_stop_read,
.ucom_start_write = &uvisor_start_write,
.ucom_stop_write = &uvisor_stop_write,
+ .ucom_free = &uvisor_free,
};
static device_method_t uvisor_methods[] = {
DEVMETHOD(device_probe, uvisor_probe),
DEVMETHOD(device_attach, uvisor_attach),
DEVMETHOD(device_detach, uvisor_detach),
- {0, 0}
+ DEVMETHOD(device_free_softc, uvisor_free_softc),
+ DEVMETHOD_END
};
static devclass_t uvisor_devclass;
@@ -317,6 +321,7 @@
device_set_usb_desc(dev);
mtx_init(&sc->sc_mtx, "uvisor", NULL, MTX_DEF);
+ ucom_ref(&sc->sc_super_ucom);
sc->sc_udev = uaa->device;
@@ -365,11 +370,30 @@
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
usbd_transfer_unsetup(sc->sc_xfer, UVISOR_N_TRANSFER);
- mtx_destroy(&sc->sc_mtx);
return (0);
}
+UCOM_UNLOAD_DRAIN(uvisor);
+
+static void
+uvisor_free_softc(device_t dev, void *arg)
+{
+ struct uvisor_softc *sc = arg;
+
+ if (ucom_unref(&sc->sc_super_ucom)) {
+ if (mtx_initialized(&sc->sc_mtx))
+ mtx_destroy(&sc->sc_mtx);
+ device_free_softc(dev, sc);
+ }
+}
+
+static void
+uvisor_free(struct ucom_softc *ucom)
+{
+ uvisor_free_softc(NULL, ucom->sc_parent);
+}
+
static usb_error_t
uvisor_init(struct uvisor_softc *sc, struct usb_device *udev, struct usb_config *config)
{
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/serial/uvscom.c
--- a/head/sys/dev/usb/serial/uvscom.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/serial/uvscom.c Wed Aug 15 11:46:11 2012 +0300
@@ -1,7 +1,7 @@
/* $NetBSD: usb/uvscom.c,v 1.1 2002/03/19 15:08:42 augustss Exp $ */
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/dev/usb/serial/uvscom.c 227309 2011-11-07 15:43:11Z ed $");
+__FBSDID("$FreeBSD: head/sys/dev/usb/serial/uvscom.c 239180 2012-08-10 15:29:41Z hselasky $");
/*-
* Copyright (c) 2001-2003, 2005 Shunsuke Akiyama <akiyama at jp.FreeBSD.org>.
@@ -163,11 +163,13 @@
static device_probe_t uvscom_probe;
static device_attach_t uvscom_attach;
static device_detach_t uvscom_detach;
+static device_free_softc_t uvscom_free_softc;
static usb_callback_t uvscom_write_callback;
static usb_callback_t uvscom_read_callback;
static usb_callback_t uvscom_intr_callback;
+static void uvscom_free(struct ucom_softc *);
static void uvscom_cfg_set_dtr(struct ucom_softc *, uint8_t);
static void uvscom_cfg_set_rts(struct ucom_softc *, uint8_t);
static void uvscom_cfg_set_break(struct ucom_softc *, uint8_t);
@@ -231,6 +233,7 @@
.ucom_start_write = &uvscom_start_write,
.ucom_stop_write = &uvscom_stop_write,
.ucom_poll = &uvscom_poll,
+ .ucom_free = &uvscom_free,
};
static const STRUCT_USB_HOST_ID uvscom_devs[] = {
@@ -250,7 +253,8 @@
DEVMETHOD(device_probe, uvscom_probe),
DEVMETHOD(device_attach, uvscom_attach),
DEVMETHOD(device_detach, uvscom_detach),
- {0, 0}
+ DEVMETHOD(device_free_softc, uvscom_free_softc),
+ DEVMETHOD_END
};
static devclass_t uvscom_devclass;
@@ -292,6 +296,7 @@
device_set_usb_desc(dev);
mtx_init(&sc->sc_mtx, "uvscom", NULL, MTX_DEF);
+ ucom_ref(&sc->sc_super_ucom);
sc->sc_udev = uaa->device;
@@ -348,11 +353,30 @@
ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom);
usbd_transfer_unsetup(sc->sc_xfer, UVSCOM_N_TRANSFER);
- mtx_destroy(&sc->sc_mtx);
return (0);
}
+UCOM_UNLOAD_DRAIN(uvscom);
+
+static void
+uvscom_free_softc(device_t dev, void *arg)
+{
+ struct uvscom_softc *sc = arg;
+
+ if (ucom_unref(&sc->sc_super_ucom)) {
+ if (mtx_initialized(&sc->sc_mtx))
+ mtx_destroy(&sc->sc_mtx);
+ device_free_softc(dev, sc);
+ }
+}
+
+static void
+uvscom_free(struct ucom_softc *ucom)
+{
+ uvscom_free_softc(NULL, ucom->sc_parent);
+}
+
static void
uvscom_write_callback(struct usb_xfer *xfer, usb_error_t error)
{
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usb.h
--- a/head/sys/dev/usb/usb.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usb.h Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/usb.h 233771 2012-04-02 07:51:30Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/usb.h 239214 2012-08-12 17:53:06Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
* Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
@@ -546,6 +546,8 @@
uByte bDescriptorType;
uByte bMaxBurst;
uByte bmAttributes;
+#define UE_GET_BULK_STREAMS(x) ((x) & 0x0F)
+#define UE_GET_SS_ISO_MULT(x) ((x) & 0x03)
uWord wBytesPerInterval;
} __packed;
typedef struct usb_endpoint_ss_comp_descriptor
@@ -744,7 +746,7 @@
#define USB_REV_MAX (USB_REV_3_0+1)
/*
- * Supported host contoller modes.
+ * Supported host controller modes.
*/
enum usb_hc_mode {
USB_MODE_HOST, /* initiates transfers */
@@ -754,7 +756,7 @@
#define USB_MODE_MAX (USB_MODE_DUAL+1)
/*
- * The "USB_MODE" macros defines all the supported device states.
+ * The "USB_STATE" enums define all the supported device states.
*/
enum usb_dev_state {
USB_STATE_DETACHED,
@@ -764,4 +766,18 @@
USB_STATE_CONFIGURED,
};
#define USB_STATE_MAX (USB_STATE_CONFIGURED+1)
+
+/*
+ * The "USB_EP_MODE" macros define all the currently supported
+ * endpoint modes.
+ */
+enum usb_ep_mode {
+ USB_EP_MODE_DEFAULT,
+ USB_EP_MODE_STREAMS, /* USB3.0 specific */
+ USB_EP_MODE_HW_MASS_STORAGE,
+ USB_EP_MODE_HW_SERIAL,
+ USB_EP_MODE_HW_ETHERNET_CDC,
+ USB_EP_MODE_HW_ETHERNET_NCM,
+ USB_EP_MODE_MAX
+};
#endif /* _USB_STANDARD_H_ */
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usb_controller.h
--- a/head/sys/dev/usb/usb_controller.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usb_controller.h Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/usb_controller.h 234803 2012-04-29 17:12:33Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/usb_controller.h 239214 2012-08-12 17:53:06Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -108,7 +108,8 @@
/* USB Device mode only - Mandatory */
void (*get_hw_ep_profile) (struct usb_device *udev, const struct usb_hw_ep_profile **ppf, uint8_t ep_addr);
- void (*set_stall) (struct usb_device *udev, struct usb_xfer *xfer, struct usb_endpoint *ep, uint8_t *did_stall);
+ void (*xfer_stall) (struct usb_xfer *xfer);
+ void (*set_stall) (struct usb_device *udev, struct usb_endpoint *ep, uint8_t *did_stall);
/* USB Device mode mandatory. USB Host mode optional. */
@@ -143,6 +144,10 @@
/* Optional for host mode */
usb_error_t (*set_address) (struct usb_device *, struct mtx *, uint16_t);
+
+ /* Optional for device and host mode */
+
+ usb_error_t (*set_endpoint_mode) (struct usb_device *, struct usb_endpoint *, uint8_t);
};
/*
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usb_core.h
--- a/head/sys/dev/usb/usb_core.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usb_core.h Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD$ */
+/* $FreeBSD: head/sys/dev/usb/usb_core.h 239214 2012-08-12 17:53:06Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -151,6 +151,7 @@
usb_frcount_t nframes; /* number of USB frames to transfer */
usb_frcount_t aframes; /* actual number of USB frames
* transferred */
+ usb_stream_t stream_id; /* USB3.0 specific field */
uint16_t max_packet_size;
uint16_t max_frame_size;
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usb_debug.c
--- a/head/sys/dev/usb/usb_debug.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usb_debug.c Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD$ */
+/* $FreeBSD: head/sys/dev/usb/usb_debug.c 239214 2012-08-12 17:53:06Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -113,10 +113,12 @@
usb_dump_queue(struct usb_endpoint *ep)
{
struct usb_xfer *xfer;
+ usb_stream_t x;
printf("usb_dump_queue: endpoint=%p xfer: ", ep);
- TAILQ_FOREACH(xfer, &ep->endpoint_q.head, wait_entry) {
- printf(" %p", xfer);
+ for (x = 0; x != USB_MAX_EP_STREAMS; x++) {
+ TAILQ_FOREACH(xfer, &ep->endpoint_q[x].head, wait_entry)
+ printf(" %p", xfer);
}
printf("\n");
}
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usb_device.c
--- a/head/sys/dev/usb/usb_device.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usb_device.c Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/usb_device.c 236407 2012-06-01 16:30:54Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/usb_device.c 239240 2012-08-13 18:34:04Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -79,6 +79,8 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#include <dev/led/led.h>
+
/* function prototypes */
static void usb_init_endpoint(struct usb_device *, uint8_t,
@@ -202,7 +204,7 @@
/*
* The default endpoint is always present and is checked separately:
*/
- if ((udev->ctrl_ep.edesc) &&
+ if ((udev->ctrl_ep.edesc != NULL) &&
((udev->ctrl_ep.edesc->bEndpointAddress & EA_MASK) == ea_val)) {
ep = &udev->ctrl_ep;
goto found;
@@ -320,7 +322,7 @@
* address" and "any direction" returns the first endpoint of the
* interface. "iface_index" and "direction" is ignored:
*/
- if ((udev->ctrl_ep.edesc) &&
+ if ((udev->ctrl_ep.edesc != NULL) &&
((udev->ctrl_ep.edesc->bEndpointAddress & ea_mask) == ea_val) &&
((udev->ctrl_ep.edesc->bmAttributes & type_mask) == type_val) &&
(!index)) {
@@ -355,7 +357,6 @@
return (USB_ERR_NORMAL_COMPLETION);
}
-
/*------------------------------------------------------------------------*
* usb_init_endpoint
*
@@ -370,6 +371,7 @@
struct usb_endpoint *ep)
{
struct usb_bus_methods *methods;
+ usb_stream_t x;
methods = udev->bus->methods;
@@ -379,13 +381,26 @@
ep->edesc = edesc;
ep->ecomp = ecomp;
ep->iface_index = iface_index;
- TAILQ_INIT(&ep->endpoint_q.head);
- ep->endpoint_q.command = &usbd_pipe_start;
+
+ /* setup USB stream queues */
+ for (x = 0; x != USB_MAX_EP_STREAMS; x++) {
+ TAILQ_INIT(&ep->endpoint_q[x].head);
+ ep->endpoint_q[x].command = &usbd_pipe_start;
+ }
/* the pipe is not supported by the hardware */
if (ep->methods == NULL)
return;
+ /* check for SUPER-speed streams mode endpoint */
+ if (udev->speed == USB_SPEED_SUPER && ecomp != NULL &&
+ (edesc->bmAttributes & UE_XFERTYPE) == UE_BULK &&
+ (UE_GET_BULK_STREAMS(ecomp->bmAttributes) != 0)) {
+ usbd_set_endpoint_mode(udev, ep, USB_EP_MODE_STREAMS);
+ } else {
+ usbd_set_endpoint_mode(udev, ep, USB_EP_MODE_DEFAULT);
+ }
+
/* clear stall, if any */
if (methods->clear_stall != NULL) {
USB_BUS_LOCK(udev->bus);
@@ -933,6 +948,7 @@
uint8_t do_stall)
{
struct usb_xfer *xfer;
+ usb_stream_t x;
uint8_t et;
uint8_t was_stalled;
@@ -975,18 +991,22 @@
if (do_stall || (!was_stalled)) {
if (!was_stalled) {
- /* lookup the current USB transfer, if any */
- xfer = ep->endpoint_q.curr;
- } else {
- xfer = NULL;
+ for (x = 0; x != USB_MAX_EP_STREAMS; x++) {
+ /* lookup the current USB transfer, if any */
+ xfer = ep->endpoint_q[x].curr;
+ if (xfer != NULL) {
+ /*
+ * The "xfer_stall" method
+ * will complete the USB
+ * transfer like in case of a
+ * timeout setting the error
+ * code "USB_ERR_STALLED".
+ */
+ (udev->bus->methods->xfer_stall) (xfer);
+ }
+ }
}
-
- /*
- * If "xfer" is non-NULL the "set_stall" method will
- * complete the USB transfer like in case of a timeout
- * setting the error code "USB_ERR_STALLED".
- */
- (udev->bus->methods->set_stall) (udev, xfer, ep, &do_stall);
+ (udev->bus->methods->set_stall) (udev, ep, &do_stall);
}
if (!do_stall) {
ep->toggle_next = 0; /* reset data toggle */
@@ -994,8 +1014,11 @@
(udev->bus->methods->clear_stall) (udev, ep);
- /* start up the current or next transfer, if any */
- usb_command_wrapper(&ep->endpoint_q, ep->endpoint_q.curr);
+ /* start the current or next transfer, if any */
+ for (x = 0; x != USB_MAX_EP_STREAMS; x++) {
+ usb_command_wrapper(&ep->endpoint_q[x],
+ ep->endpoint_q[x].curr);
+ }
}
USB_BUS_UNLOCK(udev->bus);
return (0);
@@ -1891,6 +1914,9 @@
#if USB_HAVE_DEVCTL
usb_notify_addq("ATTACH", udev);
#endif
+ /* Enable USB LED if new device is not USB HUB */
+ if (udev->ddesc.bDeviceClass != UDCLASS_HUB)
+ led_set("usb", "0");
done:
if (err) {
/*
@@ -2050,6 +2076,10 @@
bus = udev->bus;
usb_set_device_state(udev, USB_STATE_DETACHED);
+ /* Disable USB LED if new device is not USB HUB */
+ if (udev->ddesc.bDeviceClass != UDCLASS_HUB)
+ led_set("usb", "1");
+
#if USB_HAVE_DEVCTL
usb_notify_addq("DETACH", udev);
#endif
@@ -2745,3 +2775,47 @@
}
return (USB_ERR_NOMEM);
}
+
+/*
+ * The following function is used to select the endpoint mode. It
+ * should not be called outside enumeration context.
+ */
+
+usb_error_t
+usbd_set_endpoint_mode(struct usb_device *udev, struct usb_endpoint *ep,
+ uint8_t ep_mode)
+{
+ usb_error_t error;
+ uint8_t do_unlock;
+
+ /* automatic locking */
+ if (usbd_enum_is_locked(udev)) {
+ do_unlock = 0;
+ } else {
+ do_unlock = 1;
+ usbd_enum_lock(udev);
+ }
+
+ if (udev->bus->methods->set_endpoint_mode != NULL) {
+ error = (udev->bus->methods->set_endpoint_mode) (
+ udev, ep, ep_mode);
+ } else if (ep_mode != USB_EP_MODE_DEFAULT) {
+ error = USB_ERR_INVAL;
+ } else {
+ error = 0;
+ }
+
+ /* only set new mode regardless of error */
+ ep->ep_mode = ep_mode;
+
+ if (do_unlock)
+ usbd_enum_unlock(udev);
+
+ return (error);
+}
+
+uint8_t
+usbd_get_endpoint_mode(struct usb_device *udev, struct usb_endpoint *ep)
+{
+ return (ep->ep_mode);
+}
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usb_device.h
--- a/head/sys/dev/usb/usb_device.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usb_device.h Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/usb_device.h 225350 2011-09-02 18:50:44Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/usb_device.h 239176 2012-08-10 14:44:04Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -33,7 +33,7 @@
#define USB_CTRL_XFER_MAX 2
-/* "usb_parse_config()" commands */
+/* "usb_config_parse()" commands */
#define USB_CFG_ALLOC 0
#define USB_CFG_FREE 1
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usb_freebsd.h
--- a/head/sys/dev/usb/usb_freebsd.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usb_freebsd.h Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/usb_freebsd.h 225350 2011-09-02 18:50:44Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/usb_freebsd.h 239214 2012-08-12 17:53:06Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -60,6 +60,7 @@
#define USB_MAX_DEVICES 128 /* units */
#define USB_IFACE_MAX 32 /* units */
#define USB_FIFO_MAX 128 /* units */
+#define USB_MAX_EP_STREAMS 8 /* units */
#define USB_MAX_FS_ISOC_FRAMES_PER_XFER (120) /* units */
#define USB_MAX_HS_ISOC_FRAMES_PER_XFER (8*120) /* units */
@@ -76,5 +77,6 @@
typedef uint32_t usb_size_t; /* bytes */
typedef uint32_t usb_ticks_t; /* system defined */
typedef uint16_t usb_power_mask_t; /* see "USB_HW_POWER_XXX" */
+typedef uint16_t usb_stream_t; /* stream ID */
#endif /* _USB_FREEBSD_H_ */
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usb_generic.c
--- a/head/sys/dev/usb/usb_generic.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usb_generic.c Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/usb_generic.c 236407 2012-06-01 16:30:54Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/usb_generic.c 239238 2012-08-13 18:09:19Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -253,6 +253,7 @@
usb_config[0].type = ed->bmAttributes & UE_XFERTYPE;
usb_config[0].endpoint = ed->bEndpointAddress & UE_ADDR;
+ usb_config[0].stream_id = 0; /* XXX support more stream ID's */
usb_config[0].direction = UE_DIR_TX;
usb_config[0].interval = USB_DEFAULT_INTERVAL;
usb_config[0].flags.proxy_buffer = 1;
@@ -321,6 +322,7 @@
usb_config[0].type = ed->bmAttributes & UE_XFERTYPE;
usb_config[0].endpoint = ed->bEndpointAddress & UE_ADDR;
+ usb_config[0].stream_id = 0; /* XXX support more stream ID's */
usb_config[0].direction = UE_DIR_RX;
usb_config[0].interval = USB_DEFAULT_INTERVAL;
usb_config[0].flags.proxy_buffer = 1;
@@ -1391,6 +1393,7 @@
struct usb_fs_start *pstart;
struct usb_fs_stop *pstop;
struct usb_fs_open *popen;
+ struct usb_fs_open_stream *popen_stream;
struct usb_fs_close *pclose;
struct usb_fs_clear_stall_sync *pstall;
void *addr;
@@ -1455,6 +1458,7 @@
break;
case USB_FS_OPEN:
+ case USB_FS_OPEN_STREAM:
if (u.popen->ep_index >= f->fs_ep_max) {
error = EINVAL;
break;
@@ -1506,6 +1510,8 @@
usb_config[0].frames = u.popen->max_frames;
usb_config[0].bufsize = u.popen->max_bufsize;
usb_config[0].usb_mode = USB_MODE_DUAL; /* both modes */
+ if (cmd == USB_FS_OPEN_STREAM)
+ usb_config[0].stream_id = u.popen_stream->stream_id;
if (usb_config[0].type == UE_CONTROL) {
if (f->udev->flags.usb_mode != USB_MODE_HOST) {
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usb_hub.c
--- a/head/sys/dev/usb/usb_hub.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usb_hub.c Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/usb_hub.c 234803 2012-04-29 17:12:33Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/usb_hub.c 239214 2012-08-12 17:53:06Z hselasky $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
* Copyright (c) 1998 Lennart Augustsson. All rights reserved.
@@ -1757,9 +1757,11 @@
data_len += len;
}
- /* check double buffered transfers */
-
- TAILQ_FOREACH(pipe_xfer, &xfer->endpoint->endpoint_q.head,
+ /*
+ * Check double buffered transfers. Only stream ID
+ * equal to zero is valid here!
+ */
+ TAILQ_FOREACH(pipe_xfer, &xfer->endpoint->endpoint_q[0].head,
wait_entry) {
/* skip self, if any */
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usb_ioctl.h
--- a/head/sys/dev/usb/usb_ioctl.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usb_ioctl.h Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/usb_ioctl.h 227463 2011-11-12 08:40:52Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/usb_ioctl.h 239238 2012-08-13 18:09:19Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
* Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
@@ -206,6 +206,11 @@
uint8_t ep_no; /* bEndpointNumber */
};
+struct usb_fs_open_stream {
+ struct usb_fs_open fs_open;
+ uint16_t stream_id;
+};
+
struct usb_fs_close {
uint8_t ep_index;
};
@@ -302,6 +307,7 @@
#define USB_FS_OPEN _IOWR('U', 197, struct usb_fs_open)
#define USB_FS_CLOSE _IOW ('U', 198, struct usb_fs_close)
#define USB_FS_CLEAR_STALL_SYNC _IOW ('U', 199, struct usb_fs_clear_stall_sync)
+#define USB_FS_OPEN_STREAM _IOWR('U', 200, struct usb_fs_open_stream)
/* USB quirk system interface */
#define USB_DEV_QUIRK_GET _IOWR('Q', 0, struct usb_gen_quirk)
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usb_msctest.c
--- a/head/sys/dev/usb/usb_msctest.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usb_msctest.c Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/usb_msctest.c 233774 2012-04-02 10:50:42Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/usb_msctest.c 239237 2012-08-13 18:00:34Z hselasky $ */
/*-
* Copyright (c) 2008,2011 Hans Petter Selasky. All rights reserved.
*
@@ -103,6 +103,8 @@
0x00, 0x00, 0x00, 0x00 };
static uint8_t scsi_request_sense[] = { 0x03, 0x00, 0x00, 0x00, 0x12, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static uint8_t scsi_read_capacity[] = { 0x25, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 };
#define BULK_SIZE 64 /* dummy */
#define ERR_CSW_FAILED -1
@@ -652,7 +654,7 @@
}
is_no_direct = 1;
- for (timeout = 4; timeout; timeout--) {
+ for (timeout = 4; timeout != 0; timeout--) {
err = bbb_command_start(sc, DIR_IN, 0, sc->buffer,
SCSI_INQ_LEN, &scsi_inquiry, sizeof(scsi_inquiry),
USB_MS_HZ);
@@ -681,7 +683,9 @@
if (err != ERR_CSW_FAILED)
goto error;
}
+ timeout = 1;
+retry_sync_cache:
err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
&scsi_sync_cache, sizeof(scsi_sync_cache),
USB_MS_HZ);
@@ -694,6 +698,42 @@
DPRINTF("Device doesn't handle synchronize cache\n");
usbd_add_dynamic_quirk(udev, UQ_MSC_NO_SYNC_CACHE);
+
+ } else {
+
+ /*
+ * Certain Kingston memory sticks fail the first
+ * read capacity after a synchronize cache command
+ * has been issued. Disable the synchronize cache
+ * command for such devices.
+ */
+
+ err = bbb_command_start(sc, DIR_IN, 0, sc->buffer, 8,
+ &scsi_read_capacity, sizeof(scsi_read_capacity),
+ USB_MS_HZ);
+
+ if (err != 0) {
+ if (err != ERR_CSW_FAILED)
+ goto error;
+
+ err = bbb_command_start(sc, DIR_IN, 0, sc->buffer, 8,
+ &scsi_read_capacity, sizeof(scsi_read_capacity),
+ USB_MS_HZ);
+
+ if (err == 0) {
+ if (timeout--)
+ goto retry_sync_cache;
+
+ DPRINTF("Device most likely doesn't "
+ "handle synchronize cache\n");
+
+ usbd_add_dynamic_quirk(udev,
+ UQ_MSC_NO_SYNC_CACHE);
+ } else {
+ if (err != ERR_CSW_FAILED)
+ goto error;
+ }
+ }
}
/* clear sense status of any failed commands on the device */
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usb_request.c
--- a/head/sys/dev/usb/usb_request.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usb_request.c Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/usb_request.c 233774 2012-04-02 10:50:42Z hselasky $ */
+/* $FreeBSD: head/sys/dev/usb/usb_request.c 239214 2012-08-12 17:53:06Z hselasky $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
* Copyright (c) 1998 Lennart Augustsson. All rights reserved.
@@ -228,6 +228,7 @@
struct usb_endpoint *ep;
struct usb_endpoint *ep_end;
struct usb_endpoint *ep_first;
+ usb_stream_t x;
uint8_t to;
udev = xfer->xroot->udev;
@@ -255,9 +256,11 @@
ep->is_stalled = 0;
/* some hardware needs a callback to clear the data toggle */
usbd_clear_stall_locked(udev, ep);
- /* start up the current or next transfer, if any */
- usb_command_wrapper(&ep->endpoint_q,
- ep->endpoint_q.curr);
+ for (x = 0; x != USB_MAX_EP_STREAMS; x++) {
+ /* start the current or next transfer, if any */
+ usb_command_wrapper(&ep->endpoint_q[x],
+ ep->endpoint_q[x].curr);
+ }
}
ep++;
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usb_transfer.c
--- a/head/sys/dev/usb/usb_transfer.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usb_transfer.c Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/sys/dev/usb/usb_transfer.c 236070 2012-05-26 08:33:53Z marius $ */
+/* $FreeBSD: head/sys/dev/usb/usb_transfer.c 239214 2012-08-12 17:53:06Z hselasky $ */
/*-
* Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
*
@@ -358,7 +358,8 @@
switch (type) {
case UE_ISOCHRONOUS:
case UE_INTERRUPT:
- xfer->max_packet_count += (xfer->max_packet_size >> 11) & 3;
+ xfer->max_packet_count +=
+ (xfer->max_packet_size >> 11) & 3;
/* check for invalid max packet count */
if (xfer->max_packet_count > 3)
@@ -387,7 +388,8 @@
if (ecomp != NULL) {
uint8_t mult;
- mult = (ecomp->bmAttributes & 3) + 1;
+ mult = UE_GET_SS_ISO_MULT(
+ ecomp->bmAttributes) + 1;
if (mult > 3)
mult = 3;
@@ -946,7 +948,20 @@
ep = usbd_get_endpoint(udev,
ifaces[setup->if_index], setup);
- if ((ep == NULL) || (ep->methods == NULL)) {
+ /*
+ * Check that the USB PIPE is valid and that
+ * the endpoint mode is proper.
+ *
+ * Make sure we don't allocate a streams
+ * transfer when such a combination is not
+ * valid.
+ */
+ if ((ep == NULL) || (ep->methods == NULL) ||
+ ((ep->ep_mode != USB_EP_MODE_STREAMS) &&
+ (ep->ep_mode != USB_EP_MODE_DEFAULT)) ||
+ (setup->stream_id != 0 &&
+ (setup->stream_id >= USB_MAX_EP_STREAMS ||
+ (ep->ep_mode != USB_EP_MODE_STREAMS)))) {
if (setup->flags.no_pipe_ok)
continue;
if ((setup->usb_mode != USB_MODE_DUAL) &&
@@ -990,6 +1005,9 @@
/* set transfer endpoint pointer */
xfer->endpoint = ep;
+ /* set transfer stream ID */
+ xfer->stream_id = setup->stream_id;
+
parm.size[0] += sizeof(xfer[0]);
parm.methods = xfer->endpoint->methods;
parm.curr_xfer = xfer;
@@ -1575,7 +1593,8 @@
USB_BUS_LOCK(bus);
xfer->flags_int.can_cancel_immed = 1;
/* start the transfer */
- usb_command_wrapper(&xfer->endpoint->endpoint_q, xfer);
+ usb_command_wrapper(&xfer->endpoint->
+ endpoint_q[xfer->stream_id], xfer);
USB_BUS_UNLOCK(bus);
return;
}
@@ -1696,7 +1715,7 @@
}
/* start the transfer */
- usb_command_wrapper(&ep->endpoint_q, xfer);
+ usb_command_wrapper(&ep->endpoint_q[xfer->stream_id], xfer);
USB_BUS_UNLOCK(xfer->xroot->bus);
}
@@ -1817,8 +1836,9 @@
* If the current USB transfer is completing we need
* to start the next one:
*/
- if (ep->endpoint_q.curr == xfer) {
- usb_command_wrapper(&ep->endpoint_q, NULL);
+ if (ep->endpoint_q[xfer->stream_id].curr == xfer) {
+ usb_command_wrapper(
+ &ep->endpoint_q[xfer->stream_id], NULL);
}
}
@@ -2533,7 +2553,7 @@
if (udev->flags.usb_mode == USB_MODE_DEVICE) {
(udev->bus->methods->set_stall) (
- udev, NULL, ep, &did_stall);
+ udev, ep, &did_stall);
} else if (udev->ctrl_xfer[1]) {
info = udev->ctrl_xfer[1]->xroot;
usb_proc_msignal(
@@ -2800,10 +2820,11 @@
* next one:
*/
USB_BUS_LOCK(bus);
- if (ep->endpoint_q.curr == xfer) {
- usb_command_wrapper(&ep->endpoint_q, NULL);
-
- if (ep->endpoint_q.curr || TAILQ_FIRST(&ep->endpoint_q.head)) {
+ if (ep->endpoint_q[xfer->stream_id].curr == xfer) {
+ usb_command_wrapper(&ep->endpoint_q[xfer->stream_id], NULL);
+
+ if (ep->endpoint_q[xfer->stream_id].curr != NULL ||
+ TAILQ_FIRST(&ep->endpoint_q[xfer->stream_id].head) != NULL) {
/* there is another USB transfer waiting */
} else {
/* this is the last USB transfer */
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usbdevs
--- a/head/sys/dev/usb/usbdevs Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usbdevs Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-$FreeBSD: head/sys/dev/usb/usbdevs 239055 2012-08-05 11:50:56Z hselasky $
+$FreeBSD: head/sys/dev/usb/usbdevs 239275 2012-08-15 04:03:55Z gonzo $
/* $NetBSD: usbdevs,v 1.392 2004/12/29 08:38:44 imp Exp $ */
/*-
@@ -3858,6 +3858,7 @@
product SMC2 2020HUB 0x2020 USB Hub
product SMC2 2514HUB 0x2514 USB Hub
product SMC3 2662WUSB 0xa002 2662W-AR Wireless
+product SMC2 LAN9514_ETH 0xec00 USB/Ethernet
/* SOHOware products */
product SOHOWARE NUB100 0x9100 10/100 USB Ethernet
diff -r a301a330526b -r 49889ad5ef1f head/sys/dev/usb/usbdi.h
--- a/head/sys/dev/usb/usbdi.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/dev/usb/usbdi.h Wed Aug 15 11:46:11 2012 +0300
@@ -21,7 +21,7 @@
* (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: head/sys/dev/usb/usbdi.h 233774 2012-04-02 10:50:42Z hselasky $
+ * $FreeBSD: head/sys/dev/usb/usbdi.h 239214 2012-08-12 17:53:06Z hselasky $
*/
#ifndef _USB_USBDI_H_
#define _USB_USBDI_H_
@@ -133,7 +133,8 @@
* USB endpoint.
*/
struct usb_endpoint {
- struct usb_xfer_queue endpoint_q; /* queue of USB transfers */
+ /* queue of USB transfers */
+ struct usb_xfer_queue endpoint_q[USB_MAX_EP_STREAMS];
struct usb_endpoint_descriptor *edesc;
struct usb_endpoint_ss_comp_descriptor *ecomp;
@@ -156,6 +157,10 @@
uint8_t usb_smask; /* USB start mask */
uint8_t usb_cmask; /* USB complete mask */
uint8_t usb_uframe; /* USB microframe */
+
+ /* USB endpoint mode, see USB_EP_MODE_XXX */
+
+ uint8_t ep_mode;
};
/*
@@ -220,6 +225,7 @@
#define USB_DEFAULT_INTERVAL 0
usb_timeout_t timeout; /* transfer timeout in milliseconds */
struct usb_xfer_flags flags; /* transfer flags */
+ usb_stream_t stream_id; /* USB3.0 specific */
enum usb_hc_mode usb_mode; /* host or device mode */
uint8_t type; /* pipe type */
uint8_t endpoint; /* pipe number */
@@ -477,6 +483,10 @@
uint8_t iface_index, const char *pnpinfo);
usb_error_t usbd_add_dynamic_quirk(struct usb_device *udev,
uint16_t quirk);
+usb_error_t usbd_set_endpoint_mode(struct usb_device *udev,
+ struct usb_endpoint *ep, uint8_t ep_mode);
+uint8_t usbd_get_endpoint_mode(struct usb_device *udev,
+ struct usb_endpoint *ep);
const struct usb_device_id *usbd_lookup_id_by_info(
const struct usb_device_id *id, usb_size_t sizeof_id,
diff -r a301a330526b -r 49889ad5ef1f head/sys/fs/nfsclient/nfs_clbio.c
--- a/head/sys/fs/nfsclient/nfs_clbio.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/fs/nfsclient/nfs_clbio.c Wed Aug 15 11:46:11 2012 +0300
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/fs/nfsclient/nfs_clbio.c 239065 2012-08-05 14:11:42Z kib $");
+__FBSDID("$FreeBSD: head/sys/fs/nfsclient/nfs_clbio.c 239246 2012-08-14 11:45:47Z kib $");
#include "opt_kdtrace.h"
@@ -218,14 +218,18 @@
("nfs_getpages: page %p is dirty", m));
} else {
/*
- * Read operation was short. If no error occured
- * we may have hit a zero-fill section. We simply
- * leave valid set to 0.
+ * Read operation was short. If no error
+ * occured we may have hit a zero-fill
+ * section. We leave valid set to 0, and page
+ * is freed by vm_page_readahead_finish() if
+ * its index is not equal to requested, or
+ * page is zeroed and set valid by
+ * vm_pager_get_pages() for requested page.
*/
;
}
if (i != ap->a_reqpage)
- vm_page_readahead_finish(m, error);
+ vm_page_readahead_finish(m);
}
VM_OBJECT_UNLOCK(object);
return (0);
diff -r a301a330526b -r 49889ad5ef1f head/sys/fs/nwfs/nwfs_io.c
--- a/head/sys/fs/nwfs/nwfs_io.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/fs/nwfs/nwfs_io.c Wed Aug 15 11:46:11 2012 +0300
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/sys/fs/nwfs/nwfs_io.c 239065 2012-08-05 14:11:42Z kib $
+ * $FreeBSD: head/sys/fs/nwfs/nwfs_io.c 239246 2012-08-14 11:45:47Z kib $
*
*/
#include <sys/param.h>
@@ -459,7 +459,7 @@
}
if (i != ap->a_reqpage)
- vm_page_readahead_finish(m, error);
+ vm_page_readahead_finish(m);
}
VM_OBJECT_UNLOCK(object);
return 0;
diff -r a301a330526b -r 49889ad5ef1f head/sys/fs/smbfs/smbfs_io.c
--- a/head/sys/fs/smbfs/smbfs_io.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/fs/smbfs/smbfs_io.c Wed Aug 15 11:46:11 2012 +0300
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/sys/fs/smbfs/smbfs_io.c 239065 2012-08-05 14:11:42Z kib $
+ * $FreeBSD: head/sys/fs/smbfs/smbfs_io.c 239246 2012-08-14 11:45:47Z kib $
*
*/
#include <sys/param.h>
@@ -523,7 +523,7 @@
}
if (i != reqpage)
- vm_page_readahead_finish(m, error);
+ vm_page_readahead_finish(m);
}
VM_OBJECT_UNLOCK(object);
return 0;
diff -r a301a330526b -r 49889ad5ef1f head/sys/geom/eli/g_eli_key_cache.c
--- a/head/sys/geom/eli/g_eli_key_cache.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/geom/eli/g_eli_key_cache.c Wed Aug 15 11:46:11 2012 +0300
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/geom/eli/g_eli_key_cache.c 238116 2012-07-04 17:54:17Z pjd $");
+__FBSDID("$FreeBSD: head/sys/geom/eli/g_eli_key_cache.c 239184 2012-08-10 18:43:29Z pjd $");
#include <sys/param.h>
#include <sys/kernel.h>
@@ -193,24 +193,24 @@
void
g_eli_key_init(struct g_eli_softc *sc)
{
+ uint8_t *mkey;
mtx_lock(&sc->sc_ekeys_lock);
+
+ mkey = sc->sc_mkey + sizeof(sc->sc_ivkey);
+ if ((sc->sc_flags & G_ELI_FLAG_AUTH) == 0)
+ bcopy(mkey, sc->sc_ekey, G_ELI_DATAKEYLEN);
+ else {
+ /*
+ * The encryption key is: ekey = HMAC_SHA512(Data-Key, 0x10)
+ */
+ g_eli_crypto_hmac(mkey, G_ELI_MAXKEYLEN, "\x10", 1,
+ sc->sc_ekey, 0);
+ }
+
if ((sc->sc_flags & G_ELI_FLAG_SINGLE_KEY) != 0) {
- uint8_t *mkey;
-
- mkey = sc->sc_mkey + sizeof(sc->sc_ivkey);
-
sc->sc_ekeys_total = 1;
sc->sc_ekeys_allocated = 0;
- if ((sc->sc_flags & G_ELI_FLAG_AUTH) == 0)
- bcopy(mkey, sc->sc_ekey, G_ELI_DATAKEYLEN);
- else {
- /*
- * The encryption key is: ekey = HMAC_SHA512(Data-Key, 0x10)
- */
- g_eli_crypto_hmac(mkey, G_ELI_MAXKEYLEN, "\x10", 1,
- sc->sc_ekey, 0);
- }
} else {
off_t mediasize;
size_t blocksize;
@@ -241,6 +241,7 @@
(uintmax_t)sc->sc_ekeys_allocated));
}
}
+
mtx_unlock(&sc->sc_ekeys_lock);
}
diff -r a301a330526b -r 49889ad5ef1f head/sys/geom/raid/g_raid.c
--- a/head/sys/geom/raid/g_raid.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/geom/raid/g_raid.c Wed Aug 15 11:46:11 2012 +0300
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/geom/raid/g_raid.c 235076 2012-05-06 11:32:36Z mav $");
+__FBSDID("$FreeBSD: head/sys/geom/raid/g_raid.c 239175 2012-08-10 13:36:33Z mav $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -218,6 +218,8 @@
switch (event) {
case G_RAID_SUBDISK_E_NEW:
return ("NEW");
+ case G_RAID_SUBDISK_E_FAILED:
+ return ("FAILED");
case G_RAID_SUBDISK_E_DISCONNECTED:
return ("DISCONNECTED");
default:
diff -r a301a330526b -r 49889ad5ef1f head/sys/i386/conf/XENHVM
--- a/head/sys/i386/conf/XENHVM Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/i386/conf/XENHVM Wed Aug 15 11:46:11 2012 +0300
@@ -1,13 +1,11 @@
#
# XENHVM -- Xen HVM kernel configuration file for FreeBSD/i386
#
-# $FreeBSD: head/sys/i386/conf/XENHVM 230185 2012-01-16 02:42:41Z cperciva $
+# $FreeBSD: head/sys/i386/conf/XENHVM 239228 2012-08-13 07:36:57Z cperciva $
#
include GENERIC
ident XENHVM
-makeoptions MODULES_OVERRIDE=""
-
#
# Adaptive locks rely on a lock-free pointer read to determine the run state
# of the thread holding a lock when under contention; under a virtualisation
diff -r a301a330526b -r 49889ad5ef1f head/sys/i386/i386/mp_machdep.c
--- a/head/sys/i386/i386/mp_machdep.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/i386/i386/mp_machdep.c Wed Aug 15 11:46:11 2012 +0300
@@ -24,7 +24,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/i386/i386/mp_machdep.c 236938 2012-06-12 00:14:54Z iwasaki $");
+__FBSDID("$FreeBSD: head/sys/i386/i386/mp_machdep.c 239241 2012-08-13 18:52:51Z jhb $");
#include "opt_apic.h"
#include "opt_cpu.h"
@@ -1136,26 +1136,15 @@
{
/*
- * first we do an INIT/RESET IPI this INIT IPI might be run, reseting
+ * first we do an INIT IPI: this INIT IPI might be run, resetting
* and running the target CPU. OR this INIT IPI might be latched (P5
* bug), CPU waiting for STARTUP IPI. OR this INIT IPI might be
* ignored.
*/
-
- /* do an INIT IPI: assert RESET */
lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
APIC_LEVEL_ASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_INIT, apic_id);
-
- /* wait for pending status end */
lapic_ipi_wait(-1);
-
- /* do an INIT IPI: deassert RESET */
- lapic_ipi_raw(APIC_DEST_ALLESELF | APIC_TRIGMOD_LEVEL |
- APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_INIT, 0);
-
- /* wait for pending status end */
DELAY(10000); /* wait ~10mS */
- lapic_ipi_wait(-1);
/*
* next we do a STARTUP IPI: the previous INIT IPI might still be
@@ -1165,8 +1154,6 @@
* run. OR the previous INIT IPI was ignored. and this STARTUP IPI
* will run.
*/
-
- /* do a STARTUP IPI */
lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
vector, apic_id);
@@ -1179,7 +1166,6 @@
* this STARTUP IPI will be ignored, as only ONE STARTUP IPI is
* recognized after hardware RESET or INIT IPI.
*/
-
lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
vector, apic_id);
diff -r a301a330526b -r 49889ad5ef1f head/sys/i386/include/param.h
--- a/head/sys/i386/include/param.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/i386/include/param.h Wed Aug 15 11:46:11 2012 +0300
@@ -30,7 +30,7 @@
* SUCH DAMAGE.
*
* from: @(#)param.h 5.8 (Berkeley) 6/28/91
- * $FreeBSD: head/sys/i386/include/param.h 224207 2011-07-19 00:37:24Z attilio $
+ * $FreeBSD: head/sys/i386/include/param.h 239255 2012-08-14 17:01:21Z des $
*/
#include <machine/_align.h>
@@ -123,14 +123,6 @@
#define KSTACK_GUARD_PAGES 1 /* pages of kstack guard; 0 disables */
/*
- * Ceiling on amount of swblock kva space, can be changed via
- * the kern.maxswzone /boot/loader.conf variable.
- */
-#ifndef VM_SWZONE_SIZE_MAX
-#define VM_SWZONE_SIZE_MAX (32 * 1024 * 1024)
-#endif
-
-/*
* Ceiling on size of buffer cache (really only effects write queueing,
* the VM page cache is not effected), can be changed via
* the kern.maxbcache /boot/loader.conf variable.
diff -r a301a330526b -r 49889ad5ef1f head/sys/kern/device_if.m
--- a/head/sys/kern/device_if.m Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/kern/device_if.m Wed Aug 15 11:46:11 2012 +0300
@@ -23,7 +23,7 @@
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# $FreeBSD: head/sys/kern/device_if.m 222253 2011-05-24 13:22:40Z jhb $
+# $FreeBSD: head/sys/kern/device_if.m 239178 2012-08-10 15:02:49Z hselasky $
#
#include <sys/bus.h>
@@ -316,3 +316,14 @@
METHOD int quiesce {
device_t dev;
} DEFAULT null_quiesce;
+
+/**
+ * @brief Free the device softc
+ *
+ * @param _dev device pointer
+ * @param _softc pointer to softc
+ */
+METHOD void free_softc {
+ device_t _dev;
+ void *_softc;
+} DEFAULT device_free_softc;
diff -r a301a330526b -r 49889ad5ef1f head/sys/kern/kern_environment.c
--- a/head/sys/kern/kern_environment.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/kern/kern_environment.c Wed Aug 15 11:46:11 2012 +0300
@@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/kern/kern_environment.c 225617 2011-09-16 13:58:51Z kmacy $");
+__FBSDID("$FreeBSD: head/sys/kern/kern_environment.c 239257 2012-08-14 19:16:30Z jh $");
#include <sys/types.h>
#include <sys/param.h>
@@ -143,9 +143,9 @@
break;
}
- name = malloc(KENV_MNAMELEN, M_TEMP, M_WAITOK);
+ name = malloc(KENV_MNAMELEN + 1, M_TEMP, M_WAITOK);
- error = copyinstr(uap->name, name, KENV_MNAMELEN, NULL);
+ error = copyinstr(uap->name, name, KENV_MNAMELEN + 1, NULL);
if (error)
goto done;
@@ -176,8 +176,8 @@
error = EINVAL;
goto done;
}
- if (len > KENV_MVALLEN)
- len = KENV_MVALLEN;
+ if (len > KENV_MVALLEN + 1)
+ len = KENV_MVALLEN + 1;
value = malloc(len, M_TEMP, M_WAITOK);
error = copyinstr(uap->value, value, len, NULL);
if (error) {
@@ -389,10 +389,10 @@
KENV_CHECK;
namelen = strlen(name) + 1;
- if (namelen > KENV_MNAMELEN)
+ if (namelen > KENV_MNAMELEN + 1)
return (-1);
vallen = strlen(value) + 1;
- if (vallen > KENV_MVALLEN)
+ if (vallen > KENV_MVALLEN + 1)
return (-1);
buf = malloc(namelen + vallen, M_KENV, M_WAITOK);
sprintf(buf, "%s=%s", name, value);
diff -r a301a330526b -r 49889ad5ef1f head/sys/kern/kern_umtx.c
--- a/head/sys/kern/kern_umtx.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/kern/kern_umtx.c Wed Aug 15 11:46:11 2012 +0300
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/kern/kern_umtx.c 234302 2012-04-14 23:53:31Z davide $");
+__FBSDID("$FreeBSD: head/sys/kern/kern_umtx.c 239202 2012-08-11 23:48:39Z davidxu $");
#include "opt_compat.h"
#include "opt_umtx_profiling.h"
@@ -587,11 +587,10 @@
&umtxtime->_timeout);
}
-static int
+static inline void
abs_timeout_update(struct abs_timeout *timo)
{
kern_clock_gettime(curthread, timo->clockid, &timo->cur);
- return (timespeccmp(&timo->cur, &timo->end, >=));
}
static int
@@ -599,6 +598,8 @@
{
struct timespec tts;
+ if (timespeccmp(&timo->end, &timo->cur, <=))
+ return (-1);
tts = timo->end;
timespecsub(&tts, &timo->cur);
return (tstohz(&tts));
@@ -609,26 +610,29 @@
* thread was removed from umtx queue.
*/
static inline int
-umtxq_sleep(struct umtx_q *uq, const char *wmesg, struct abs_timeout *timo)
+umtxq_sleep(struct umtx_q *uq, const char *wmesg, struct abs_timeout *abstime)
{
struct umtxq_chain *uc;
- int error;
+ int error, timo;
uc = umtxq_getchain(&uq->uq_key);
UMTXQ_LOCKED_ASSERT(uc);
for (;;) {
if (!(uq->uq_flags & UQF_UMTXQ))
return (0);
- error = msleep(uq, &uc->uc_lock, PCATCH, wmesg,
- timo == NULL ? 0 : abs_timeout_gethz(timo));
- if (error != EWOULDBLOCK)
- break;
- umtxq_unlock(&uq->uq_key);
- if (abs_timeout_update(timo)) {
- error = ETIMEDOUT;
+ if (abstime != NULL) {
+ timo = abs_timeout_gethz(abstime);
+ if (timo < 0)
+ return (ETIMEDOUT);
+ } else
+ timo = 0;
+ error = msleep(uq, &uc->uc_lock, PCATCH | PDROP, wmesg, timo);
+ if (error != EWOULDBLOCK) {
umtxq_lock(&uq->uq_key);
break;
}
+ if (abstime != NULL)
+ abs_timeout_update(abstime);
umtxq_lock(&uq->uq_key);
}
return (error);
diff -r a301a330526b -r 49889ad5ef1f head/sys/kern/ksched.c
--- a/head/sys/kern/ksched.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/kern/ksched.c Wed Aug 15 11:46:11 2012 +0300
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/kern/ksched.c 222802 2011-06-07 02:50:14Z davidxu $");
+__FBSDID("$FreeBSD: head/sys/kern/ksched.c 239183 2012-08-10 18:19:57Z mav $");
#include "opt_posix.h"
@@ -64,7 +64,7 @@
struct ksched *ksched= p31b_malloc(sizeof(*ksched));
ksched->rr_interval.tv_sec = 0;
- ksched->rr_interval.tv_nsec = 1000000000L / sched_rr_interval();
+ ksched->rr_interval.tv_nsec = 1000000000L / hz * sched_rr_interval();
*p = ksched;
return 0;
diff -r a301a330526b -r 49889ad5ef1f head/sys/kern/sched_4bsd.c
--- a/head/sys/kern/sched_4bsd.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/kern/sched_4bsd.c Wed Aug 15 11:46:11 2012 +0300
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/kern/sched_4bsd.c 239157 2012-08-09 19:26:13Z mav $");
+__FBSDID("$FreeBSD: head/sys/kern/sched_4bsd.c 239196 2012-08-11 20:24:39Z mav $");
#include "opt_hwpmc_hooks.h"
#include "opt_sched.h"
@@ -119,9 +119,9 @@
static struct td_sched td_sched0;
struct mtx sched_lock;
-static int realstathz; /* stathz is sometimes 0 and run off of hz. */
+static int realstathz = 127; /* stathz is sometimes 0 and run off of hz. */
static int sched_tdcnt; /* Total runnable threads in the system. */
-static int sched_slice = 1; /* Thread run time before rescheduling. */
+static int sched_slice = 12; /* Thread run time before rescheduling. */
static void setup_runqs(void);
static void schedcpu(void);
@@ -185,12 +185,33 @@
runq_init(&runq);
}
+static int
+sysctl_kern_quantum(SYSCTL_HANDLER_ARGS)
+{
+ int error, new_val, period;
+
+ period = 1000000 / realstathz;
+ new_val = period * sched_slice;
+ error = sysctl_handle_int(oidp, &new_val, 0, req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+ if (new_val <= 0)
+ return (EINVAL);
+ sched_slice = imax(1, (new_val + period / 2) / period);
+ hogticks = imax(1, (2 * hz * sched_slice + realstathz / 2) /
+ realstathz);
+ return (0);
+}
+
SYSCTL_NODE(_kern, OID_AUTO, sched, CTLFLAG_RD, 0, "Scheduler");
SYSCTL_STRING(_kern_sched, OID_AUTO, name, CTLFLAG_RD, "4BSD", 0,
"Scheduler name");
+SYSCTL_PROC(_kern_sched, OID_AUTO, quantum, CTLTYPE_INT | CTLFLAG_RW,
+ NULL, 0, sysctl_kern_quantum, "I",
+ "Quantum for timeshare threads in microseconds");
SYSCTL_INT(_kern_sched, OID_AUTO, slice, CTLFLAG_RW, &sched_slice, 0,
- "Slice size for timeshare threads");
+ "Quantum for timeshare threads in stathz ticks");
#ifdef SMP
/* Enable forwarding of wakeups to all other cpus */
static SYSCTL_NODE(_kern_sched, OID_AUTO, ipiwakeup, CTLFLAG_RD, NULL,
@@ -629,21 +650,15 @@
static void
sched_setup(void *dummy)
{
+
setup_runqs();
- /*
- * To avoid divide-by-zero, we set realstathz a dummy value
- * in case which sched_clock() called before sched_initticks().
- */
- realstathz = hz;
- sched_slice = realstathz / 10; /* ~100ms */
-
/* Account for thread0. */
sched_load_add();
}
/*
- * This routine determines the sched_slice after stathz and hz are setup.
+ * This routine determines time constants after stathz and hz are setup.
*/
static void
sched_initticks(void *dummy)
@@ -651,6 +666,8 @@
realstathz = stathz ? stathz : hz;
sched_slice = realstathz / 10; /* ~100ms */
+ hogticks = imax(1, (2 * hz * sched_slice + realstathz / 2) /
+ realstathz);
}
/* External interfaces start here */
@@ -689,7 +706,7 @@
{
/* Convert sched_slice from stathz to hz. */
- return (hz / (realstathz / sched_slice));
+ return (imax(1, (sched_slice * hz + realstathz / 2) / realstathz));
}
/*
@@ -724,9 +741,9 @@
/*
* Force a context switch if the current thread has used up a full
- * quantum (default quantum is 100ms).
+ * time slice (default is 100ms).
*/
- if (!TD_IS_IDLETHREAD(td) && (--ts->ts_slice <= 0)) {
+ if (!TD_IS_IDLETHREAD(td) && --ts->ts_slice <= 0) {
ts->ts_slice = sched_slice;
td->td_flags |= TDF_NEEDRESCHED | TDF_SLICEEND;
}
diff -r a301a330526b -r 49889ad5ef1f head/sys/kern/sched_ule.c
--- a/head/sys/kern/sched_ule.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/kern/sched_ule.c Wed Aug 15 11:46:11 2012 +0300
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/kern/sched_ule.c 239157 2012-08-09 19:26:13Z mav $");
+__FBSDID("$FreeBSD: head/sys/kern/sched_ule.c 239196 2012-08-11 20:24:39Z mav $");
#include "opt_hwpmc_hooks.h"
#include "opt_kdtrace.h"
@@ -201,9 +201,9 @@
* preempt_thresh: Priority threshold for preemption and remote IPIs.
*/
static int sched_interact = SCHED_INTERACT_THRESH;
-static int realstathz;
-static int tickincr;
-static int sched_slice = 1;
+static int realstathz = 127;
+static int tickincr = 8 << SCHED_TICK_SHIFT;;
+static int sched_slice = 12;
#ifdef PREEMPTION
#ifdef FULL_PREEMPTION
static int preempt_thresh = PRI_MAX_IDLE;
@@ -1363,13 +1363,6 @@
#else
tdq_setup(tdq);
#endif
- /*
- * To avoid divide-by-zero, we set realstathz a dummy value
- * in case which sched_clock() called before sched_initticks().
- */
- realstathz = hz;
- sched_slice = (realstathz/10); /* ~100ms */
- tickincr = 1 << SCHED_TICK_SHIFT;
/* Add thread0's load since it's running. */
TDQ_LOCK(tdq);
@@ -1380,7 +1373,7 @@
}
/*
- * This routine determines the tickincr after stathz and hz are setup.
+ * This routine determines time constants after stathz and hz are setup.
*/
/* ARGSUSED */
static void
@@ -1389,7 +1382,9 @@
int incr;
realstathz = stathz ? stathz : hz;
- sched_slice = (realstathz/10); /* ~100ms */
+ sched_slice = realstathz / 10; /* ~100ms */
+ hogticks = imax(1, (2 * hz * sched_slice + realstathz / 2) /
+ realstathz);
/*
* tickincr is shifted out by 10 to avoid rounding errors due to
@@ -1409,16 +1404,10 @@
* what realstathz is.
*/
balance_interval = realstathz;
- /*
- * Set steal thresh to roughly log2(mp_ncpu) but no greater than 4.
- * This prevents excess thrashing on large machines and excess idle
- * on smaller machines.
- */
- steal_thresh = min(fls(mp_ncpus) - 1, 3);
affinity = SCHED_AFFINITY_DEFAULT;
#endif
if (sched_idlespinthresh < 0)
- sched_idlespinthresh = max(16, 2 * hz / realstathz);
+ sched_idlespinthresh = imax(16, 2 * hz / realstathz);
}
@@ -1606,8 +1595,8 @@
sched_rr_interval(void)
{
- /* Convert sched_slice to hz */
- return (hz/(realstathz/sched_slice));
+ /* Convert sched_slice from stathz to hz. */
+ return (imax(1, (sched_slice * hz + realstathz / 2) / realstathz));
}
/*
@@ -2231,16 +2220,15 @@
sched_interact_update(td);
sched_priority(td);
}
+
/*
- * We used up one time slice.
+ * Force a context switch if the current thread has used up a full
+ * time slice (default is 100ms).
*/
- if (--ts->ts_slice > 0)
- return;
- /*
- * We're out of time, force a requeue at userret().
- */
- ts->ts_slice = sched_slice;
- td->td_flags |= TDF_NEEDRESCHED | TDF_SLICEEND;
+ if (!TD_IS_IDLETHREAD(td) && --ts->ts_slice <= 0) {
+ ts->ts_slice = sched_slice;
+ td->td_flags |= TDF_NEEDRESCHED | TDF_SLICEEND;
+ }
}
/*
@@ -2795,21 +2783,44 @@
#endif
+static int
+sysctl_kern_quantum(SYSCTL_HANDLER_ARGS)
+{
+ int error, new_val, period;
+
+ period = 1000000 / realstathz;
+ new_val = period * sched_slice;
+ error = sysctl_handle_int(oidp, &new_val, 0, req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+ if (new_val <= 0)
+ return (EINVAL);
+ sched_slice = imax(1, (new_val + period / 2) / period);
+ hogticks = imax(1, (2 * hz * sched_slice + realstathz / 2) /
+ realstathz);
+ return (0);
+}
+
SYSCTL_NODE(_kern, OID_AUTO, sched, CTLFLAG_RW, 0, "Scheduler");
SYSCTL_STRING(_kern_sched, OID_AUTO, name, CTLFLAG_RD, "ULE", 0,
"Scheduler name");
+SYSCTL_PROC(_kern_sched, OID_AUTO, quantum, CTLTYPE_INT | CTLFLAG_RW,
+ NULL, 0, sysctl_kern_quantum, "I",
+ "Quantum for timeshare threads in microseconds");
SYSCTL_INT(_kern_sched, OID_AUTO, slice, CTLFLAG_RW, &sched_slice, 0,
- "Slice size for timeshare threads");
+ "Quantum for timeshare threads in stathz ticks");
SYSCTL_INT(_kern_sched, OID_AUTO, interact, CTLFLAG_RW, &sched_interact, 0,
- "Interactivity score threshold");
-SYSCTL_INT(_kern_sched, OID_AUTO, preempt_thresh, CTLFLAG_RW, &preempt_thresh,
- 0,"Min priority for preemption, lower priorities have greater precedence");
-SYSCTL_INT(_kern_sched, OID_AUTO, static_boost, CTLFLAG_RW, &static_boost,
- 0,"Controls whether static kernel priorities are assigned to sleeping threads.");
-SYSCTL_INT(_kern_sched, OID_AUTO, idlespins, CTLFLAG_RW, &sched_idlespins,
- 0,"Number of times idle will spin waiting for new work.");
-SYSCTL_INT(_kern_sched, OID_AUTO, idlespinthresh, CTLFLAG_RW, &sched_idlespinthresh,
- 0,"Threshold before we will permit idle spinning.");
+ "Interactivity score threshold");
+SYSCTL_INT(_kern_sched, OID_AUTO, preempt_thresh, CTLFLAG_RW,
+ &preempt_thresh, 0,
+ "Maximal (lowest) priority for preemption");
+SYSCTL_INT(_kern_sched, OID_AUTO, static_boost, CTLFLAG_RW, &static_boost, 0,
+ "Assign static kernel priorities to sleeping threads");
+SYSCTL_INT(_kern_sched, OID_AUTO, idlespins, CTLFLAG_RW, &sched_idlespins, 0,
+ "Number of times idle thread will spin waiting for new work");
+SYSCTL_INT(_kern_sched, OID_AUTO, idlespinthresh, CTLFLAG_RW,
+ &sched_idlespinthresh, 0,
+ "Threshold before we will permit idle thread spinning");
#ifdef SMP
SYSCTL_INT(_kern_sched, OID_AUTO, affinity, CTLFLAG_RW, &affinity, 0,
"Number of hz ticks to keep thread affinity for");
@@ -2817,17 +2828,14 @@
"Enables the long-term load balancer");
SYSCTL_INT(_kern_sched, OID_AUTO, balance_interval, CTLFLAG_RW,
&balance_interval, 0,
- "Average frequency in stathz ticks to run the long-term balancer");
+ "Average period in stathz ticks to run the long-term balancer");
SYSCTL_INT(_kern_sched, OID_AUTO, steal_idle, CTLFLAG_RW, &steal_idle, 0,
"Attempts to steal work from other cores before idling");
SYSCTL_INT(_kern_sched, OID_AUTO, steal_thresh, CTLFLAG_RW, &steal_thresh, 0,
- "Minimum load on remote cpu before we'll steal");
-
-/* Retrieve SMP topology */
+ "Minimum load on remote CPU before we'll steal");
SYSCTL_PROC(_kern_sched, OID_AUTO, topology_spec, CTLTYPE_STRING |
- CTLFLAG_RD, NULL, 0, sysctl_kern_sched_topology_spec, "A",
+ CTLFLAG_RD, NULL, 0, sysctl_kern_sched_topology_spec, "A",
"XML dump of detected CPU topology");
-
#endif
/* ps compat. All cpu percentages from ULE are weighted. */
diff -r a301a330526b -r 49889ad5ef1f head/sys/kern/subr_bus.c
--- a/head/sys/kern/subr_bus.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/kern/subr_bus.c Wed Aug 15 11:46:11 2012 +0300
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/kern/subr_bus.c 235978 2012-05-25 07:32:26Z avg $");
+__FBSDID("$FreeBSD: head/sys/kern/subr_bus.c 239178 2012-08-10 15:02:49Z hselasky $");
#include "opt_bus.h"
@@ -2505,8 +2505,8 @@
void
device_set_softc(device_t dev, void *softc)
{
- if (dev->softc && !(dev->flags & DF_EXTERNALSOFTC))
- free(dev->softc, M_BUS_SC);
+ if (dev->softc != NULL && !(dev->flags & DF_EXTERNALSOFTC))
+ DEVICE_FREE_SOFTC(dev, dev->softc);
dev->softc = softc;
if (dev->softc)
dev->flags |= DF_EXTERNALSOFTC;
@@ -2703,8 +2703,8 @@
if (dev->driver == driver)
return (0);
- if (dev->softc && !(dev->flags & DF_EXTERNALSOFTC)) {
- free(dev->softc, M_BUS_SC);
+ if (dev->softc != NULL && !(dev->flags & DF_EXTERNALSOFTC)) {
+ DEVICE_FREE_SOFTC(dev, dev->softc);
dev->softc = NULL;
}
device_set_desc(dev, NULL);
@@ -4899,3 +4899,13 @@
return (0);
return (bus_release_resource(dev, type, rman_get_rid(r), r));
}
+
+/*
+ * The "dev" argument passed to "device_free_softc()" is allowed to be
+ * NULL, if the device freeing the soft is not available.
+ */
+void
+device_free_softc(device_t dev, void *softc)
+{
+ free(softc, M_BUS_SC);
+}
diff -r a301a330526b -r 49889ad5ef1f head/sys/mips/atheros/ar71xx_gpio.c
--- a/head/sys/mips/atheros/ar71xx_gpio.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/mips/atheros/ar71xx_gpio.c Wed Aug 15 11:46:11 2012 +0300
@@ -53,7 +53,12 @@
#include "gpio_if.h"
-#define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)
+#ifndef GPIO_PIN_REPORT
+#define GPIO_PIN_REPORT 0x0400 /* report interrupt on pin */
+#endif
+
+#define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \
+ GPIO_PIN_REPORT)
/*
* Helpers
@@ -87,6 +92,10 @@
static int ar71xx_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val);
static int ar71xx_gpio_pin_toggle(device_t dev, uint32_t pin);
+static int ar71xx_gpio_register_irq_handler(device_t dev, device_t bus,
+ int (*isr)(device_t bus, device_t dev, int pin, int rise));
+static int ar71xx_gpio_unregister_irq_handler(device_t dev, device_t bus);
+
static void
ar71xx_gpio_function_enable(struct ar71xx_gpio_softc *sc, uint32_t mask)
{
@@ -127,6 +136,32 @@
}
}
+ /* Don't touch Polarity for INVIN when we !IN */
+ if (flags & GPIO_PIN_INPUT) {
+ if (flags & GPIO_PIN_INVIN) {
+ pin->gp_flags |= GPIO_PIN_INVIN;
+ GPIO_SET_BITS(sc, AR71XX_GPIO_INT_POLARITY, mask);
+ }
+ else {
+ pin->gp_flags &= ~GPIO_PIN_INVIN;
+ GPIO_CLEAR_BITS(sc, AR71XX_GPIO_INT_POLARITY, mask);
+ }
+ }
+
+ if (flags & GPIO_PIN_REPORT) {
+ pin->gp_flags |= GPIO_PIN_REPORT;
+ GPIO_SET_BITS(sc, AR71XX_GPIO_INT, mask);
+ GPIO_SET_BITS(sc, AR71XX_GPIO_INT_MASK, mask);
+ device_printf(sc->dev, "Will report interrupt on pin %d\n",
+ pin->gp_pin);
+
+ }
+ else {
+ pin->gp_flags &= ~GPIO_PIN_REPORT;
+ GPIO_CLEAR_BITS(sc, AR71XX_GPIO_INT, mask);
+ GPIO_CLEAR_BITS(sc, AR71XX_GPIO_INT_MASK, mask);
+ }
+
GPIO_UNLOCK(sc);
}
@@ -313,9 +348,32 @@
static int
ar71xx_gpio_filter(void *arg)
{
+ struct ar71xx_gpio_softc *sc = arg;
+ uint32_t i;
+ uint64_t input, value;
- /* TODO: something useful */
- return (FILTER_STRAY);
+ /* Read all reported pins */
+ input = GPIO_READ(sc, AR71XX_GPIO_INT_PENDING);
+ /* Clear int status */
+ GPIO_WRITE(sc, AR71XX_GPIO_INT_PENDING, input);
+ /* Clear report for OUTs */
+ input &= ~GPIO_READ(sc, AR71XX_GPIO_OE);
+ value = input & GPIO_READ(sc, AR71XX_GPIO_IN);
+
+ if (!input)
+ return (FILTER_HANDLED);
+
+ for ( i = 0; i < sc->npins; i ++ )
+ {
+ /* Next if output pin */
+ if ( !(( input >> i) & 1) ) continue;
+
+ if (!sc->isr) continue;
+
+ sc->isr(sc->bus, sc->dev, i, (value >> i) & 1);
+ }
+
+ return (FILTER_HANDLED);
}
@@ -323,7 +381,9 @@
static void
ar71xx_gpio_intr(void *arg)
{
- struct ar71xx_gpio_softc *sc = arg;
+ struct ar71xx_gpio_softc *sc;
+
+ sc = arg;
GPIO_LOCK(sc);
/* TODO: something useful */
GPIO_UNLOCK(sc);
@@ -342,7 +402,7 @@
{
struct ar71xx_gpio_softc *sc = device_get_softc(dev);
int error = 0;
- int i, j, npins;
+ int i, j;
int mask, pinon;
int old = 0;
@@ -392,7 +452,17 @@
}
/* Handle previous behaviour */
if (old == 0) {
- ar71xx_gpio_function_enable(sc, AR724X_GPIO_FUNC_JTAG_DISABLE);
+ switch (ar71xx_soc) {
+ case AR71XX_SOC_AR7240:
+ case AR71XX_SOC_AR7241:
+ case AR71XX_SOC_AR7242:
+ ar71xx_gpio_function_enable(sc,
+ AR724X_GPIO_FUNC_JTAG_DISABLE);
+ break;
+ default:
+ /* Nothing to do */
+ break;
+ }
}
/* Configure all pins as input */
@@ -400,17 +470,21 @@
GPIO_WRITE(sc, AR71XX_GPIO_INT_MASK, 0);
/* Initialise all pins specified in the mask, up to the pin count */
- (void) ar71xx_gpio_pin_max(dev, &npins);
+ (void) ar71xx_gpio_pin_max(dev, &sc->npins);
/* gpio_pin_max method return max ID, but not count, so increment */
- npins ++;
+ sc->npins ++;
+
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
"pinmask", &mask) != 0)
- mask = ((1 << npins) - 1);
+ mask = ((1 << sc->npins) - 1);
+
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
"pinon", &pinon) != 0)
pinon = 0;
+
device_printf(dev, "gpio pinmask=0x%x\n", mask);
- for (i = 0, j = 0; j < npins; j++) {
+
+ for (i = 0, j = 0; j < sc->npins; j++) {
if ((mask & (1 << j)) == 0)
continue;
snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME,
@@ -418,15 +492,18 @@
sc->gpio_pins[i].gp_pin = j;
sc->gpio_pins[i].gp_caps = DEFAULT_CAPS;
sc->gpio_pins[i].gp_flags = 0;
- ar71xx_gpio_pin_configure(sc, &sc->gpio_pins[i], DEFAULT_CAPS);
+ ar71xx_gpio_pin_configure(sc, &sc->gpio_pins[i], GPIO_PIN_INPUT);
i++;
}
+
sc->gpio_npins = i;
+
for (i = 0; i < sc->gpio_npins; i++) {
j = sc->gpio_pins[i].gp_pin;
if ((pinon & (1 << j)) != 0)
ar71xx_gpio_pin_set(dev, j, 1);
}
+
device_add_child(dev, "gpiobus", device_get_unit(dev));
return (bus_generic_attach(dev));
}
@@ -451,6 +528,33 @@
return(0);
}
+static int
+ar71xx_gpio_register_irq_handler(device_t dev, device_t bus,
+ int (*isr)(device_t bus, device_t dev, int pin, int rise))
+{
+ struct ar71xx_gpio_softc *sc = device_get_softc(dev);
+
+ if (sc->isr)
+ /* We already have ISR, use unregister first */
+ return (-1);
+
+ sc->bus = bus;
+ sc->isr = isr;
+
+ return (0);
+}
+
+static int
+ar71xx_gpio_unregister_irq_handler(device_t dev, device_t bus)
+{
+ struct ar71xx_gpio_softc *sc = device_get_softc(dev);
+
+ sc->isr = 0;
+ sc->bus = 0;
+
+ return (0);
+}
+
static device_method_t ar71xx_gpio_methods[] = {
DEVMETHOD(device_probe, ar71xx_gpio_probe),
DEVMETHOD(device_attach, ar71xx_gpio_attach),
@@ -465,6 +569,10 @@
DEVMETHOD(gpio_pin_get, ar71xx_gpio_pin_get),
DEVMETHOD(gpio_pin_set, ar71xx_gpio_pin_set),
DEVMETHOD(gpio_pin_toggle, ar71xx_gpio_pin_toggle),
+ DEVMETHOD(gpio_register_irq_handler,
+ ar71xx_gpio_register_irq_handler),
+ DEVMETHOD(gpio_unregister_irq_handler,
+ ar71xx_gpio_unregister_irq_handler),
DEVMETHOD_END
};
diff -r a301a330526b -r 49889ad5ef1f head/sys/mips/atheros/ar71xx_gpiovar.h
--- a/head/sys/mips/atheros/ar71xx_gpiovar.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/mips/atheros/ar71xx_gpiovar.h Wed Aug 15 11:46:11 2012 +0300
@@ -63,8 +63,12 @@
struct resource *gpio_irq_res;
int gpio_irq_rid;
void *gpio_ih;
- int gpio_npins;
+ int npins; /* Number of all pins */
+ int gpio_npins; /* Number of configured pins */
struct gpio_pin gpio_pins[AR91XX_GPIO_PINS];
+ device_t bus;
+ int (*isr)(device_t bus, device_t dev, int pin,
+ int rise);
};
#endif /* __AR71XX_GPIOVAR_H__ */
diff -r a301a330526b -r 49889ad5ef1f head/sys/mips/atheros/ar71xxreg.h
--- a/head/sys/mips/atheros/ar71xxreg.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/mips/atheros/ar71xxreg.h Wed Aug 15 11:46:11 2012 +0300
@@ -145,7 +145,11 @@
#define AR71XX_GPIO_CLEAR 0x10
#define AR71XX_GPIO_INT 0x14
#define AR71XX_GPIO_INT_TYPE 0x18
+#define GPIO_INT_TYPE_EDGE 0
+#define GPIO_INT_TYPE_LEVEL 1
#define AR71XX_GPIO_INT_POLARITY 0x1c
+#define GPIO_INT_POLARITY_NORM 0
+#define GPIO_INT_POLARITY_INV 1
#define AR71XX_GPIO_INT_PENDING 0x20
#define AR71XX_GPIO_INT_MASK 0x24
#define AR71XX_GPIO_FUNCTION 0x28
@@ -158,7 +162,13 @@
/* CS1 is shared with GPIO_0 */
#define GPIO_FUNC_UART_EN (1 << 8)
#define GPIO_FUNC_USB_OC_EN (1 << 4)
-#define GPIO_FUNC_XXX2 (1 << 1) /* XXX: must be 724x */
+#define GPIO_FUNC_724x_SWLED4 (1 << 7)
+#define GPIO_FUNC_724x_SWLED3 (1 << 6)
+#define GPIO_FUNC_724x_SWLED2 (1 << 5)
+#define GPIO_FUNC_724x_SWLED1 (1 << 4)
+#define GPIO_FUNC_724x_SWLED0 (1 << 3)
+#define GPIO_FUNC_UART_RTS_CTS (1 << 2)
+#define GPIO_FUNC_UART_9_10 (1 << 1) /* XXX: must be 724x */
#define GPIO_FUNC_USB_CLK_EN (0)
#define AR71XX_BASE_FREQ 40000000
diff -r a301a330526b -r 49889ad5ef1f head/sys/mips/cavium/octopci.c
--- a/head/sys/mips/cavium/octopci.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/mips/cavium/octopci.c Wed Aug 15 11:46:11 2012 +0300
@@ -71,6 +71,8 @@
unsigned sc_domain;
unsigned sc_bus;
+// bus_dma_tag_t sc_pci_dmat; /* PCI DMA tag pointer */
+
bus_addr_t sc_io_base;
unsigned sc_io_next;
struct rman sc_io;
@@ -80,6 +82,15 @@
struct rman sc_mem1;
};
+//static bus_dma_tag_t
+//octopci_pci_get_dma_tag(device_t bus, device_t child)
+//{
+// struct octopci_softc *sc;
+//
+// sc = device_get_softc(bus);
+// return (sc->sc_pci_dmat);
+//}
+
static void octopci_identify(driver_t *, device_t);
static int octopci_probe(device_t);
static int octopci_attach(device_t);
@@ -203,6 +214,11 @@
subbus = octopci_init_bus(dev, sc->sc_bus);
octopci_write_config(dev, sc->sc_bus, 0, 0, PCIR_SUBBUS_1, subbus, 1);
+// if (bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0,
+// 0x003fffff, ~0, NULL, NULL, 0x003fffff,
+// 0xff, 0x003fffff, 0, NULL, NULL, &sc->sc_pci_dmat) != 0)
+// panic("%s: bus_dma_tag_create failed", __func__);
+
device_add_child(dev, "pci", device_get_unit(dev));
return (bus_generic_attach(dev));
@@ -457,6 +473,12 @@
}
break;
#endif
+ case CVMX_BOARD_TYPE_CUST_DLINK_DSR500:
+ case CVMX_BOARD_TYPE_CUST_DLINK_DSR500N:
+ case CVMX_BOARD_TYPE_CUST_DLINK_DSR1000:
+ case CVMX_BOARD_TYPE_CUST_DLINK_DSR1000N:
+ return (OCTEON_IRQ_PCI_INT0 + pin + 1);
+ break;
default:
break;
}
@@ -893,6 +915,7 @@
pci_cfg56.s.dpere = 1;
pci_cfg56.s.ncp = 0xe8;
pci_cfg56.s.pxcid = 7;
+ pci_cfg56.s.mmbc = 1;
NPI_WRITE(CVMX_NPI_PCI_CFG56, pci_cfg56.u32);
NPI_READ(CVMX_NPI_PCI_CFG56);
}
@@ -970,6 +993,7 @@
DEVMETHOD(bus_deactivate_resource,bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+// DEVMETHOD(bus_get_dma_tag, octopci_pci_get_dma_tag),
DEVMETHOD(bus_add_child, bus_generic_add_child),
diff -r a301a330526b -r 49889ad5ef1f head/sys/mips/cavium/octopci_bus_space.c
--- a/head/sys/mips/cavium/octopci_bus_space.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/mips/cavium/octopci_bus_space.c Wed Aug 15 11:46:11 2012 +0300
@@ -218,6 +218,7 @@
{
*bshp = addr;
+// *bshp = addr | 0x1000000000000000ull;
return (0);
}
@@ -244,7 +245,7 @@
bus_size_t offset)
{
- return (rd8(handle + offset));
+ return (rd8((handle + offset) | 0x1000000000000000ull));
}
uint16_t
@@ -252,7 +253,7 @@
bus_size_t offset)
{
- return (rd16(handle + offset));
+ return (rd16((handle + offset) | 0x1000000000000000ull));
}
uint32_t
@@ -260,7 +261,7 @@
bus_size_t offset)
{
- return (rd32(handle + offset));
+ return (rd32((handle + offset) | 0x1000000000000000ull));
}
@@ -344,7 +345,7 @@
bus_size_t offset, uint8_t value)
{
- wr8(bsh + offset, value);
+ wr8((bsh + offset) | 0x1000000000000000ull, value);
}
void
@@ -352,7 +353,7 @@
bus_size_t offset, uint16_t value)
{
- wr16(bsh + offset, value);
+ wr16((bsh + offset) | 0x1000000000000000ull, value);
}
void
@@ -360,7 +361,7 @@
bus_size_t offset, uint32_t value)
{
- wr32(bsh + offset, value);
+ wr32((bsh + offset) | 0x1000000000000000ull, value);
}
/*
diff -r a301a330526b -r 49889ad5ef1f head/sys/mips/include/pmap.h
--- a/head/sys/mips/include/pmap.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/mips/include/pmap.h Wed Aug 15 11:46:11 2012 +0300
@@ -40,7 +40,7 @@
* from: @(#)pmap.h 7.4 (Berkeley) 5/12/91
* from: src/sys/i386/include/pmap.h,v 1.65.2.2 2000/11/30 01:54:42 peter
* JNPR: pmap.h,v 1.7.2.1 2007/09/10 07:44:12 girish
- * $FreeBSD: head/sys/mips/include/pmap.h 239152 2012-08-09 16:38:17Z alc $
+ * $FreeBSD: head/sys/mips/include/pmap.h 239236 2012-08-13 17:38:38Z alc $
*/
#ifndef _MACHINE_PMAP_H_
@@ -66,9 +66,9 @@
* Pmap stuff
*/
struct pv_entry;
+struct pv_chunk;
struct md_page {
- int pv_list_count;
int pv_flags;
TAILQ_HEAD(, pv_entry) pv_list;
};
@@ -82,8 +82,7 @@
struct pmap {
pd_entry_t *pm_segtab; /* KVA of segment table */
- TAILQ_HEAD(, pv_entry) pm_pvlist; /* list of mappings in
- * pmap */
+ TAILQ_HEAD(, pv_chunk) pm_pvchunk; /* list of mappings in pmap */
cpuset_t pm_active; /* active on cpus */
struct {
u_int32_t asid:ASID_BITS; /* TLB address space tag */
@@ -121,13 +120,30 @@
* mappings of that page. An entry is a pv_entry_t, the list is pv_table.
*/
typedef struct pv_entry {
- pmap_t pv_pmap; /* pmap where mapping lies */
vm_offset_t pv_va; /* virtual address for mapping */
TAILQ_ENTRY(pv_entry) pv_list;
- TAILQ_ENTRY(pv_entry) pv_plist;
} *pv_entry_t;
/*
+ * pv_entries are allocated in chunks per-process. This avoids the
+ * need to track per-pmap assignments.
+ */
+#ifdef __mips_n64
+#define _NPCM 3
+#define _NPCPV 168
+#else
+#define _NPCM 11
+#define _NPCPV 336
+#endif
+struct pv_chunk {
+ pmap_t pc_pmap;
+ TAILQ_ENTRY(pv_chunk) pc_list;
+ u_long pc_map[_NPCM]; /* bitmap; 1 = free */
+ TAILQ_ENTRY(pv_chunk) pc_lru;
+ struct pv_entry pc_pventry[_NPCPV];
+};
+
+/*
* physmem_desc[] is a superset of phys_avail[] and describes all the
* memory present in the system.
*
diff -r a301a330526b -r 49889ad5ef1f head/sys/mips/mips/pmap.c
--- a/head/sys/mips/mips/pmap.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/mips/mips/pmap.c Wed Aug 15 11:46:11 2012 +0300
@@ -66,9 +66,10 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/mips/mips/pmap.c 239170 2012-08-10 05:00:50Z alc $");
+__FBSDID("$FreeBSD: head/sys/mips/mips/pmap.c 239236 2012-08-13 17:38:38Z alc $");
#include "opt_ddb.h"
+#include "opt_pmap.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -77,6 +78,7 @@
#include <sys/vmmeter.h>
#include <sys/mman.h>
#include <sys/smp.h>
+#include <sys/sysctl.h>
#ifdef DDB
#include <ddb/ddb.h>
#endif
@@ -116,6 +118,12 @@
#define PMAP_INLINE
#endif
+#ifdef PV_STATS
+#define PV_STAT(x) do { x ; } while (0)
+#else
+#define PV_STAT(x) do { } while (0)
+#endif
+
/*
* Get PDEs and PTEs for user/kernel address space
*/
@@ -152,12 +160,13 @@
/*
* Data for the pv entry allocation mechanism
*/
-static uma_zone_t pvzone;
-static struct vm_object pvzone_obj;
-static int pv_entry_count = 0, pv_entry_max = 0, pv_entry_high_water = 0;
-
-static PMAP_INLINE void free_pv_entry(pv_entry_t pv);
-static pv_entry_t get_pv_entry(pmap_t locked_pmap);
+static TAILQ_HEAD(pch, pv_chunk) pv_chunks = TAILQ_HEAD_INITIALIZER(pv_chunks);
+static int pv_entry_count;
+
+static void free_pv_chunk(struct pv_chunk *pc);
+static void free_pv_entry(pmap_t pmap, pv_entry_t pv);
+static pv_entry_t get_pv_entry(pmap_t pmap, boolean_t try);
+static vm_page_t pmap_pv_reclaim(pmap_t locked_pmap);
static void pmap_pvh_free(struct md_page *pvh, pmap_t pmap, vm_offset_t va);
static pv_entry_t pmap_pvh_remove(struct md_page *pvh, pmap_t pmap,
vm_offset_t va);
@@ -472,7 +481,7 @@
PMAP_LOCK_INIT(kernel_pmap);
kernel_pmap->pm_segtab = kernel_segmap;
CPU_FILL(&kernel_pmap->pm_active);
- TAILQ_INIT(&kernel_pmap->pm_pvlist);
+ TAILQ_INIT(&kernel_pmap->pm_pvchunk);
kernel_pmap->pm_asid[0].asid = PMAP_ASID_RESERVED;
kernel_pmap->pm_asid[0].gen = 0;
kernel_vm_end += nkpt * NPTEPG * PAGE_SIZE;
@@ -591,7 +600,6 @@
{
TAILQ_INIT(&m->md.pv_list);
- m->md.pv_list_count = 0;
m->md.pv_flags = 0;
}
@@ -599,23 +607,10 @@
* Initialize the pmap module.
* Called by vm_init, to initialize any structures that the pmap
* system needs to map virtual memory.
- * pmap_init has been enhanced to support in a fairly consistant
- * way, discontiguous physical memory.
*/
void
pmap_init(void)
{
-
- /*
- * Initialize the address space (zone) for the pv entries. Set a
- * high water mark so that the system can recover from excessive
- * numbers of pv entries.
- */
- pvzone = uma_zcreate("PV ENTRY", sizeof(struct pv_entry), NULL, NULL,
- NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM | UMA_ZONE_NOFREE);
- pv_entry_max = PMAP_SHPGPERPROC * maxproc + cnt.v_page_count;
- pv_entry_high_water = 9 * (pv_entry_max / 10);
- uma_zone_set_obj(pvzone, &pvzone_obj, pv_entry_max);
}
/***************************************************
@@ -1012,7 +1007,7 @@
pmap->pm_asid[i].gen = 0;
}
PCPU_SET(curpmap, pmap);
- TAILQ_INIT(&pmap->pm_pvlist);
+ TAILQ_INIT(&pmap->pm_pvchunk);
bzero(&pmap->pm_stats, sizeof pmap->pm_stats);
}
@@ -1070,7 +1065,7 @@
pmap->pm_asid[i].asid = PMAP_ASID_RESERVED;
pmap->pm_asid[i].gen = 0;
}
- TAILQ_INIT(&pmap->pm_pvlist);
+ TAILQ_INIT(&pmap->pm_pvchunk);
bzero(&pmap->pm_stats, sizeof pmap->pm_stats);
return (1);
@@ -1296,127 +1291,320 @@
}
/***************************************************
-* page management routines.
+ * page management routines.
***************************************************/
+CTASSERT(sizeof(struct pv_chunk) == PAGE_SIZE);
+#ifdef __mips_n64
+CTASSERT(_NPCM == 3);
+CTASSERT(_NPCPV == 168);
+#else
+CTASSERT(_NPCM == 11);
+CTASSERT(_NPCPV == 336);
+#endif
+
+static __inline struct pv_chunk *
+pv_to_chunk(pv_entry_t pv)
+{
+
+ return ((struct pv_chunk *)((uintptr_t)pv & ~(uintptr_t)PAGE_MASK));
+}
+
+#define PV_PMAP(pv) (pv_to_chunk(pv)->pc_pmap)
+
+#ifdef __mips_n64
+#define PC_FREE0_1 0xfffffffffffffffful
+#define PC_FREE2 0x000000fffffffffful
+#else
+#define PC_FREE0_9 0xfffffffful /* Free values for index 0 through 9 */
+#define PC_FREE10 0x0000fffful /* Free values for index 10 */
+#endif
+
+static const u_long pc_freemask[_NPCM] = {
+#ifdef __mips_n64
+ PC_FREE0_1, PC_FREE0_1, PC_FREE2
+#else
+ PC_FREE0_9, PC_FREE0_9, PC_FREE0_9,
+ PC_FREE0_9, PC_FREE0_9, PC_FREE0_9,
+ PC_FREE0_9, PC_FREE0_9, PC_FREE0_9,
+ PC_FREE0_9, PC_FREE10
+#endif
+};
+
+static SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD, 0, "VM/pmap parameters");
+
+SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_count, CTLFLAG_RD, &pv_entry_count, 0,
+ "Current number of pv entries");
+
+#ifdef PV_STATS
+static int pc_chunk_count, pc_chunk_allocs, pc_chunk_frees, pc_chunk_tryfail;
+
+SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_count, CTLFLAG_RD, &pc_chunk_count, 0,
+ "Current number of pv entry chunks");
+SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_allocs, CTLFLAG_RD, &pc_chunk_allocs, 0,
+ "Current number of pv entry chunks allocated");
+SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_frees, CTLFLAG_RD, &pc_chunk_frees, 0,
+ "Current number of pv entry chunks frees");
+SYSCTL_INT(_vm_pmap, OID_AUTO, pc_chunk_tryfail, CTLFLAG_RD, &pc_chunk_tryfail, 0,
+ "Number of times tried to get a chunk page but failed.");
+
+static long pv_entry_frees, pv_entry_allocs;
+static int pv_entry_spare;
+
+SYSCTL_LONG(_vm_pmap, OID_AUTO, pv_entry_frees, CTLFLAG_RD, &pv_entry_frees, 0,
+ "Current number of pv entry frees");
+SYSCTL_LONG(_vm_pmap, OID_AUTO, pv_entry_allocs, CTLFLAG_RD, &pv_entry_allocs, 0,
+ "Current number of pv entry allocs");
+SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_spare, CTLFLAG_RD, &pv_entry_spare, 0,
+ "Current number of spare pv entries");
+#endif
+
+/*
+ * We are in a serious low memory condition. Resort to
+ * drastic measures to free some pages so we can allocate
+ * another pv entry chunk.
+ */
+static vm_page_t
+pmap_pv_reclaim(pmap_t locked_pmap)
+{
+ struct pch newtail;
+ struct pv_chunk *pc;
+ pd_entry_t *pde;
+ pmap_t pmap;
+ pt_entry_t *pte, oldpte;
+ pv_entry_t pv;
+ vm_offset_t va;
+ vm_page_t m, m_pc;
+ u_long inuse;
+ int bit, field, freed, idx;
+
+ PMAP_LOCK_ASSERT(locked_pmap, MA_OWNED);
+ pmap = NULL;
+ m_pc = NULL;
+ TAILQ_INIT(&newtail);
+ while ((pc = TAILQ_FIRST(&pv_chunks)) != NULL) {
+ TAILQ_REMOVE(&pv_chunks, pc, pc_lru);
+ if (pmap != pc->pc_pmap) {
+ if (pmap != NULL) {
+ pmap_invalidate_all(pmap);
+ if (pmap != locked_pmap)
+ PMAP_UNLOCK(pmap);
+ }
+ pmap = pc->pc_pmap;
+ /* Avoid deadlock and lock recursion. */
+ if (pmap > locked_pmap)
+ PMAP_LOCK(pmap);
+ else if (pmap != locked_pmap && !PMAP_TRYLOCK(pmap)) {
+ pmap = NULL;
+ TAILQ_INSERT_TAIL(&newtail, pc, pc_lru);
+ continue;
+ }
+ }
+
+ /*
+ * Destroy every non-wired, 4 KB page mapping in the chunk.
+ */
+ freed = 0;
+ for (field = 0; field < _NPCM; field++) {
+ for (inuse = ~pc->pc_map[field] & pc_freemask[field];
+ inuse != 0; inuse &= ~(1UL << bit)) {
+ bit = ffsl(inuse) - 1;
+ idx = field * sizeof(inuse) * NBBY + bit;
+ pv = &pc->pc_pventry[idx];
+ va = pv->pv_va;
+ pde = pmap_pde(pmap, va);
+ KASSERT(pde != NULL && *pde != 0,
+ ("pmap_pv_reclaim: pde"));
+ pte = pmap_pde_to_pte(pde, va);
+ oldpte = *pte;
+ KASSERT(!pte_test(&oldpte, PTE_W),
+ ("wired pte for unwired page"));
+ if (is_kernel_pmap(pmap))
+ *pte = PTE_G;
+ else
+ *pte = 0;
+ pmap_invalidate_page(pmap, va);
+ m = PHYS_TO_VM_PAGE(TLBLO_PTE_TO_PA(oldpte));
+ if (pte_test(&oldpte, PTE_D))
+ vm_page_dirty(m);
+ if (m->md.pv_flags & PV_TABLE_REF)
+ vm_page_aflag_set(m, PGA_REFERENCED);
+ TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
+ if (TAILQ_EMPTY(&m->md.pv_list)) {
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
+ m->md.pv_flags &= ~(PV_TABLE_REF |
+ PV_TABLE_MOD);
+ }
+ pc->pc_map[field] |= 1UL << bit;
+ pmap_unuse_pt(pmap, va, *pde);
+ freed++;
+ }
+ }
+ if (freed == 0) {
+ TAILQ_INSERT_TAIL(&newtail, pc, pc_lru);
+ continue;
+ }
+ /* Every freed mapping is for a 4 KB page. */
+ pmap->pm_stats.resident_count -= freed;
+ PV_STAT(pv_entry_frees += freed);
+ PV_STAT(pv_entry_spare += freed);
+ pv_entry_count -= freed;
+ TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
+ for (field = 0; field < _NPCM; field++)
+ if (pc->pc_map[field] != pc_freemask[field]) {
+ TAILQ_INSERT_HEAD(&pmap->pm_pvchunk, pc,
+ pc_list);
+ TAILQ_INSERT_TAIL(&newtail, pc, pc_lru);
+
+ /*
+ * One freed pv entry in locked_pmap is
+ * sufficient.
+ */
+ if (pmap == locked_pmap)
+ goto out;
+ break;
+ }
+ if (field == _NPCM) {
+ PV_STAT(pv_entry_spare -= _NPCPV);
+ PV_STAT(pc_chunk_count--);
+ PV_STAT(pc_chunk_frees++);
+ /* Entire chunk is free; return it. */
+ m_pc = PHYS_TO_VM_PAGE(MIPS_DIRECT_TO_PHYS(
+ (vm_offset_t)pc));
+ break;
+ }
+ }
+out:
+ TAILQ_CONCAT(&pv_chunks, &newtail, pc_lru);
+ if (pmap != NULL) {
+ pmap_invalidate_all(pmap);
+ if (pmap != locked_pmap)
+ PMAP_UNLOCK(pmap);
+ }
+ return (m_pc);
+}
+
/*
* free the pv_entry back to the free list
*/
-static PMAP_INLINE void
-free_pv_entry(pv_entry_t pv)
+static void
+free_pv_entry(pmap_t pmap, pv_entry_t pv)
{
-
+ struct pv_chunk *pc;
+ int bit, field, idx;
+
+ mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+ PV_STAT(pv_entry_frees++);
+ PV_STAT(pv_entry_spare++);
pv_entry_count--;
- uma_zfree(pvzone, pv);
+ pc = pv_to_chunk(pv);
+ idx = pv - &pc->pc_pventry[0];
+ field = idx / (sizeof(u_long) * NBBY);
+ bit = idx % (sizeof(u_long) * NBBY);
+ pc->pc_map[field] |= 1ul << bit;
+ for (idx = 0; idx < _NPCM; idx++)
+ if (pc->pc_map[idx] != pc_freemask[idx]) {
+ /*
+ * 98% of the time, pc is already at the head of the
+ * list. If it isn't already, move it to the head.
+ */
+ if (__predict_false(TAILQ_FIRST(&pmap->pm_pvchunk) !=
+ pc)) {
+ TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
+ TAILQ_INSERT_HEAD(&pmap->pm_pvchunk, pc,
+ pc_list);
+ }
+ return;
+ }
+ TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
+ free_pv_chunk(pc);
+}
+
+static void
+free_pv_chunk(struct pv_chunk *pc)
+{
+ vm_page_t m;
+
+ TAILQ_REMOVE(&pv_chunks, pc, pc_lru);
+ PV_STAT(pv_entry_spare -= _NPCPV);
+ PV_STAT(pc_chunk_count--);
+ PV_STAT(pc_chunk_frees++);
+ /* entire chunk is free, return it */
+ m = PHYS_TO_VM_PAGE(MIPS_DIRECT_TO_PHYS((vm_offset_t)pc));
+ vm_page_unwire(m, 0);
+ vm_page_free(m);
}
/*
* get a new pv_entry, allocating a block from the system
* when needed.
- * the memory allocation is performed bypassing the malloc code
- * because of the possibility of allocations at interrupt time.
*/
static pv_entry_t
-get_pv_entry(pmap_t locked_pmap)
+get_pv_entry(pmap_t pmap, boolean_t try)
{
- static const struct timeval printinterval = { 60, 0 };
- static struct timeval lastprint;
- struct vpgqueues *vpq;
- pd_entry_t *pde;
- pt_entry_t *pte, oldpte;
- pmap_t pmap;
- pv_entry_t allocated_pv, next_pv, pv;
- vm_offset_t va;
+ struct pv_chunk *pc;
+ pv_entry_t pv;
vm_page_t m;
-
- PMAP_LOCK_ASSERT(locked_pmap, MA_OWNED);
+ int bit, field, idx;
+
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
- allocated_pv = uma_zalloc(pvzone, M_NOWAIT);
- if (allocated_pv != NULL) {
- pv_entry_count++;
- if (pv_entry_count > pv_entry_high_water)
- pagedaemon_wakeup();
- else
- return (allocated_pv);
- }
- /*
- * Reclaim pv entries: At first, destroy mappings to inactive
- * pages. After that, if a pv entry is still needed, destroy
- * mappings to active pages.
- */
- if (ratecheck(&lastprint, &printinterval))
- printf("Approaching the limit on PV entries, "
- "increase the vm.pmap.shpgperproc tunable.\n");
- vpq = &vm_page_queues[PQ_INACTIVE];
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+ PV_STAT(pv_entry_allocs++);
+ pv_entry_count++;
retry:
- TAILQ_FOREACH(m, &vpq->pl, pageq) {
- if ((m->flags & PG_MARKER) != 0 || m->hold_count || m->busy)
- continue;
- TAILQ_FOREACH_SAFE(pv, &m->md.pv_list, pv_list, next_pv) {
- va = pv->pv_va;
- pmap = pv->pv_pmap;
- /* Avoid deadlock and lock recursion. */
- if (pmap > locked_pmap)
- PMAP_LOCK(pmap);
- else if (pmap != locked_pmap && !PMAP_TRYLOCK(pmap))
- continue;
- pmap->pm_stats.resident_count--;
- pde = pmap_pde(pmap, va);
- KASSERT(pde != NULL && *pde != 0,
- ("get_pv_entry: pde"));
- pte = pmap_pde_to_pte(pde, va);
- oldpte = *pte;
- if (is_kernel_pmap(pmap))
- *pte = PTE_G;
- else
- *pte = 0;
- KASSERT(!pte_test(&oldpte, PTE_W),
- ("wired pte for unwired page"));
- if (m->md.pv_flags & PV_TABLE_REF)
- vm_page_aflag_set(m, PGA_REFERENCED);
- if (pte_test(&oldpte, PTE_D))
- vm_page_dirty(m);
- pmap_invalidate_page(pmap, va);
- TAILQ_REMOVE(&pmap->pm_pvlist, pv, pv_plist);
- m->md.pv_list_count--;
- TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
- pmap_unuse_pt(pmap, va, *pde);
- if (pmap != locked_pmap)
- PMAP_UNLOCK(pmap);
- if (allocated_pv == NULL)
- allocated_pv = pv;
- else
- free_pv_entry(pv);
+ pc = TAILQ_FIRST(&pmap->pm_pvchunk);
+ if (pc != NULL) {
+ for (field = 0; field < _NPCM; field++) {
+ if (pc->pc_map[field]) {
+ bit = ffsl(pc->pc_map[field]) - 1;
+ break;
+ }
}
- if (TAILQ_EMPTY(&m->md.pv_list)) {
- vm_page_aflag_clear(m, PGA_WRITEABLE);
- m->md.pv_flags &= ~(PV_TABLE_REF | PV_TABLE_MOD);
+ if (field < _NPCM) {
+ idx = field * sizeof(pc->pc_map[field]) * NBBY + bit;
+ pv = &pc->pc_pventry[idx];
+ pc->pc_map[field] &= ~(1ul << bit);
+ /* If this was the last item, move it to tail */
+ for (field = 0; field < _NPCM; field++)
+ if (pc->pc_map[field] != 0) {
+ PV_STAT(pv_entry_spare--);
+ return (pv); /* not full, return */
+ }
+ TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
+ TAILQ_INSERT_TAIL(&pmap->pm_pvchunk, pc, pc_list);
+ PV_STAT(pv_entry_spare--);
+ return (pv);
}
}
- if (allocated_pv == NULL) {
- if (vpq == &vm_page_queues[PQ_INACTIVE]) {
- vpq = &vm_page_queues[PQ_ACTIVE];
+ /* No free items, allocate another chunk */
+ m = vm_page_alloc_freelist(VM_FREELIST_DIRECT, VM_ALLOC_NORMAL |
+ VM_ALLOC_WIRED);
+ if (m == NULL) {
+ if (try) {
+ pv_entry_count--;
+ PV_STAT(pc_chunk_tryfail++);
+ return (NULL);
+ }
+ m = pmap_pv_reclaim(pmap);
+ if (m == NULL)
goto retry;
- }
- panic("get_pv_entry: increase the vm.pmap.shpgperproc tunable");
}
- return (allocated_pv);
+ PV_STAT(pc_chunk_count++);
+ PV_STAT(pc_chunk_allocs++);
+ pc = (struct pv_chunk *)MIPS_PHYS_TO_DIRECT(VM_PAGE_TO_PHYS(m));
+ pc->pc_pmap = pmap;
+ pc->pc_map[0] = pc_freemask[0] & ~1ul; /* preallocated bit 0 */
+ for (field = 1; field < _NPCM; field++)
+ pc->pc_map[field] = pc_freemask[field];
+ TAILQ_INSERT_TAIL(&pv_chunks, pc, pc_lru);
+ pv = &pc->pc_pventry[0];
+ TAILQ_INSERT_HEAD(&pmap->pm_pvchunk, pc, pc_list);
+ PV_STAT(pv_entry_spare += _NPCPV - 1);
+ return (pv);
}
/*
- * Revision 1.370
- *
- * Move pmap_collect() out of the machine-dependent code, rename it
- * to reflect its new location, and add page queue and flag locking.
- *
- * Notes: (1) alpha, i386, and ia64 had identical implementations
- * of pmap_collect() in terms of machine-independent interfaces;
- * (2) sparc64 doesn't require it; (3) powerpc had it as a TODO.
- *
- * MIPS implementation was identical to alpha [Junos 8.2]
- */
-
-/*
* If it is the first entry on the list, it is actually
* in the header and we must copy the following entry up
* to the header. Otherwise we must search the list for
@@ -1428,23 +1616,12 @@
{
pv_entry_t pv;
- PMAP_LOCK_ASSERT(pmap, MA_OWNED);
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
- if (pvh->pv_list_count < pmap->pm_stats.resident_count) {
- TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) {
- if (pmap == pv->pv_pmap && va == pv->pv_va)
- break;
+ TAILQ_FOREACH(pv, &pvh->pv_list, pv_list) {
+ if (pmap == PV_PMAP(pv) && va == pv->pv_va) {
+ TAILQ_REMOVE(&pvh->pv_list, pv, pv_list);
+ break;
}
- } else {
- TAILQ_FOREACH(pv, &pmap->pm_pvlist, pv_plist) {
- if (va == pv->pv_va)
- break;
- }
- }
- if (pv != NULL) {
- TAILQ_REMOVE(&pvh->pv_list, pv, pv_list);
- pvh->pv_list_count--;
- TAILQ_REMOVE(&pmap->pm_pvlist, pv, pv_plist);
}
return (pv);
}
@@ -1458,7 +1635,7 @@
KASSERT(pv != NULL, ("pmap_pvh_free: pv not found, pa %lx va %lx",
(u_long)VM_PAGE_TO_PHYS(member2struct(vm_page, md, pvh)),
(u_long)va));
- free_pv_entry(pv);
+ free_pv_entry(pmap, pv);
}
static void
@@ -1482,14 +1659,9 @@
PMAP_LOCK_ASSERT(pmap, MA_OWNED);
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
- if (pv_entry_count < pv_entry_high_water &&
- (pv = uma_zalloc(pvzone, M_NOWAIT)) != NULL) {
- pv_entry_count++;
+ if ((pv = get_pv_entry(pmap, TRUE)) != NULL) {
pv->pv_va = va;
- pv->pv_pmap = pmap;
- TAILQ_INSERT_TAIL(&pmap->pm_pvlist, pv, pv_plist);
TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_list);
- m->md.pv_list_count++;
return (TRUE);
} else
return (FALSE);
@@ -1648,6 +1820,7 @@
pmap_remove_all(vm_page_t m)
{
pv_entry_t pv;
+ pmap_t pmap;
pd_entry_t *pde;
pt_entry_t *pte, tpte;
@@ -1659,29 +1832,30 @@
vm_page_aflag_set(m, PGA_REFERENCED);
while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) {
- PMAP_LOCK(pv->pv_pmap);
+ pmap = PV_PMAP(pv);
+ PMAP_LOCK(pmap);
/*
* If it's last mapping writeback all caches from
* the page being destroyed
*/
- if (m->md.pv_list_count == 1)
+ if (TAILQ_NEXT(pv, pv_list) == NULL)
mips_dcache_wbinv_range_index(pv->pv_va, PAGE_SIZE);
- pv->pv_pmap->pm_stats.resident_count--;
-
- pde = pmap_pde(pv->pv_pmap, pv->pv_va);
+ pmap->pm_stats.resident_count--;
+
+ pde = pmap_pde(pmap, pv->pv_va);
KASSERT(pde != NULL && *pde != 0, ("pmap_remove_all: pde"));
pte = pmap_pde_to_pte(pde, pv->pv_va);
tpte = *pte;
- if (is_kernel_pmap(pv->pv_pmap))
+ if (is_kernel_pmap(pmap))
*pte = PTE_G;
else
*pte = 0;
if (pte_test(&tpte, PTE_W))
- pv->pv_pmap->pm_stats.wired_count--;
+ pmap->pm_stats.wired_count--;
/*
* Update the vm_page_t clean and reference bits.
@@ -1692,14 +1866,12 @@
__func__, (void *)pv->pv_va, (uintmax_t)tpte));
vm_page_dirty(m);
}
- pmap_invalidate_page(pv->pv_pmap, pv->pv_va);
-
- TAILQ_REMOVE(&pv->pv_pmap->pm_pvlist, pv, pv_plist);
+ pmap_invalidate_page(pmap, pv->pv_va);
+
TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
- m->md.pv_list_count--;
- pmap_unuse_pt(pv->pv_pmap, pv->pv_va, *pde);
- PMAP_UNLOCK(pv->pv_pmap);
- free_pv_entry(pv);
+ pmap_unuse_pt(pmap, pv->pv_va, *pde);
+ free_pv_entry(pmap, pv);
+ PMAP_UNLOCK(pmap);
}
vm_page_aflag_clear(m, PGA_WRITEABLE);
@@ -1894,14 +2066,11 @@
KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva,
("pmap_enter: managed mapping within the clean submap"));
if (pv == NULL)
- pv = get_pv_entry(pmap);
+ pv = get_pv_entry(pmap, FALSE);
pv->pv_va = va;
- pv->pv_pmap = pmap;
- TAILQ_INSERT_TAIL(&pmap->pm_pvlist, pv, pv_plist);
TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_list);
- m->md.pv_list_count++;
} else if (pv != NULL)
- free_pv_entry(pv);
+ free_pv_entry(pmap, pv);
/*
* Increment counters
@@ -2397,7 +2566,7 @@
rv = FALSE;
vm_page_lock_queues();
TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
- if (pv->pv_pmap == pmap) {
+ if (PV_PMAP(pv) == pmap) {
rv = TRUE;
break;
}
@@ -2422,8 +2591,11 @@
{
pd_entry_t *pde;
pt_entry_t *pte, tpte;
- pv_entry_t pv, npv;
+ pv_entry_t pv;
vm_page_t m;
+ struct pv_chunk *pc, *npc;
+ u_long inuse, bitmask;
+ int allfree, bit, field, idx;
if (pmap != vmspace_pmap(curthread->td_proc->p_vmspace)) {
printf("warning: pmap_remove_pages called with non-current pmap\n");
@@ -2431,46 +2603,61 @@
}
vm_page_lock_queues();
PMAP_LOCK(pmap);
- for (pv = TAILQ_FIRST(&pmap->pm_pvlist); pv != NULL; pv = npv) {
-
- pde = pmap_pde(pmap, pv->pv_va);
- KASSERT(pde != NULL && *pde != 0, ("pmap_remove_pages: pde"));
- pte = pmap_pde_to_pte(pde, pv->pv_va);
- if (!pte_test(pte, PTE_V))
- panic("pmap_remove_pages: page on pm_pvlist has no pte");
- tpte = *pte;
+ TAILQ_FOREACH_SAFE(pc, &pmap->pm_pvchunk, pc_list, npc) {
+ allfree = 1;
+ for (field = 0; field < _NPCM; field++) {
+ inuse = ~pc->pc_map[field] & pc_freemask[field];
+ while (inuse != 0) {
+ bit = ffsl(inuse) - 1;
+ bitmask = 1UL << bit;
+ idx = field * sizeof(inuse) * NBBY + bit;
+ pv = &pc->pc_pventry[idx];
+ inuse &= ~bitmask;
+
+ pde = pmap_pde(pmap, pv->pv_va);
+ KASSERT(pde != NULL && *pde != 0,
+ ("pmap_remove_pages: pde"));
+ pte = pmap_pde_to_pte(pde, pv->pv_va);
+ if (!pte_test(pte, PTE_V))
+ panic("pmap_remove_pages: bad pte");
+ tpte = *pte;
/*
* We cannot remove wired pages from a process' mapping at this time
*/
- if (pte_test(&tpte, PTE_W)) {
- npv = TAILQ_NEXT(pv, pv_plist);
- continue;
+ if (pte_test(&tpte, PTE_W)) {
+ allfree = 0;
+ continue;
+ }
+ *pte = is_kernel_pmap(pmap) ? PTE_G : 0;
+
+ m = PHYS_TO_VM_PAGE(TLBLO_PTE_TO_PA(tpte));
+ KASSERT(m != NULL,
+ ("pmap_remove_pages: bad tpte %#jx",
+ (uintmax_t)tpte));
+
+ /*
+ * Update the vm_page_t clean and reference bits.
+ */
+ if (pte_test(&tpte, PTE_D))
+ vm_page_dirty(m);
+
+ /* Mark free */
+ PV_STAT(pv_entry_frees++);
+ PV_STAT(pv_entry_spare++);
+ pv_entry_count--;
+ pc->pc_map[field] |= bitmask;
+ pmap->pm_stats.resident_count--;
+ TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
+ if (TAILQ_EMPTY(&m->md.pv_list))
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
+ pmap_unuse_pt(pmap, pv->pv_va, *pde);
+ }
}
- *pte = is_kernel_pmap(pmap) ? PTE_G : 0;
-
- m = PHYS_TO_VM_PAGE(TLBLO_PTE_TO_PA(tpte));
- KASSERT(m != NULL,
- ("pmap_remove_pages: bad tpte %#jx", (uintmax_t)tpte));
-
- pmap->pm_stats.resident_count--;
-
- /*
- * Update the vm_page_t clean and reference bits.
- */
- if (pte_test(&tpte, PTE_D)) {
- vm_page_dirty(m);
+ if (allfree) {
+ TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
+ free_pv_chunk(pc);
}
- npv = TAILQ_NEXT(pv, pv_plist);
- TAILQ_REMOVE(&pmap->pm_pvlist, pv, pv_plist);
-
- m->md.pv_list_count--;
- TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
- if (TAILQ_FIRST(&m->md.pv_list) == NULL) {
- vm_page_aflag_clear(m, PGA_WRITEABLE);
- }
- pmap_unuse_pt(pmap, pv->pv_va, *pde);
- free_pv_entry(pv);
}
pmap_invalidate_all(pmap);
PMAP_UNLOCK(pmap);
@@ -2486,21 +2673,20 @@
pmap_testbit(vm_page_t m, int bit)
{
pv_entry_t pv;
+ pmap_t pmap;
pt_entry_t *pte;
boolean_t rv = FALSE;
if (m->oflags & VPO_UNMANAGED)
return (rv);
- if (TAILQ_FIRST(&m->md.pv_list) == NULL)
- return (rv);
-
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
- PMAP_LOCK(pv->pv_pmap);
- pte = pmap_pte(pv->pv_pmap, pv->pv_va);
+ pmap = PV_PMAP(pv);
+ PMAP_LOCK(pmap);
+ pte = pmap_pte(pmap, pv->pv_va);
rv = pte_test(pte, bit);
- PMAP_UNLOCK(pv->pv_pmap);
+ PMAP_UNLOCK(pmap);
if (rv)
break;
}
@@ -2514,6 +2700,7 @@
pmap_changebit(vm_page_t m, int bit, boolean_t setem)
{
pv_entry_t pv;
+ pmap_t pmap;
pt_entry_t *pte;
if (m->oflags & VPO_UNMANAGED)
@@ -2525,11 +2712,12 @@
* setting RO do we need to clear the VAC?
*/
TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
- PMAP_LOCK(pv->pv_pmap);
- pte = pmap_pte(pv->pv_pmap, pv->pv_va);
+ pmap = PV_PMAP(pv);
+ PMAP_LOCK(pmap);
+ pte = pmap_pte(pmap, pv->pv_va);
if (setem) {
*pte |= bit;
- pmap_update_page(pv->pv_pmap, pv->pv_va, *pte);
+ pmap_update_page(pmap, pv->pv_va, *pte);
} else {
pt_entry_t pbits = *pte;
@@ -2541,10 +2729,10 @@
} else {
*pte = pbits & ~bit;
}
- pmap_update_page(pv->pv_pmap, pv->pv_va, *pte);
+ pmap_update_page(pmap, pv->pv_va, *pte);
}
}
- PMAP_UNLOCK(pv->pv_pmap);
+ PMAP_UNLOCK(pmap);
}
if (!setem && bit == PTE_D)
vm_page_aflag_clear(m, PGA_WRITEABLE);
@@ -2569,7 +2757,7 @@
return (count);
vm_page_lock_queues();
TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
- pmap = pv->pv_pmap;
+ pmap = PV_PMAP(pv);
PMAP_LOCK(pmap);
pte = pmap_pte(pmap, pv->pv_va);
if (pte_test(pte, PTE_W))
@@ -2586,9 +2774,9 @@
void
pmap_remove_write(vm_page_t m)
{
- pv_entry_t pv, npv;
- vm_offset_t va;
- pt_entry_t *pte;
+ pmap_t pmap;
+ pt_entry_t pbits, *pte;
+ pv_entry_t pv;
KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_remove_write: page %p is not managed", m));
@@ -2602,20 +2790,25 @@
if ((m->oflags & VPO_BUSY) == 0 &&
(m->aflags & PGA_WRITEABLE) == 0)
return;
-
- /*
- * Loop over all current mappings setting/clearing as appropos.
- */
vm_page_lock_queues();
- for (pv = TAILQ_FIRST(&m->md.pv_list); pv; pv = npv) {
- npv = TAILQ_NEXT(pv, pv_plist);
- pte = pmap_pte(pv->pv_pmap, pv->pv_va);
- if (pte == NULL || !pte_test(pte, PTE_V))
- panic("page on pm_pvlist has no pte");
-
- va = pv->pv_va;
- pmap_protect(pv->pv_pmap, va, va + PAGE_SIZE,
- VM_PROT_READ | VM_PROT_EXECUTE);
+ TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
+ pmap = PV_PMAP(pv);
+ PMAP_LOCK(pmap);
+ pte = pmap_pte(pmap, pv->pv_va);
+ KASSERT(pte != NULL && pte_test(pte, PTE_V),
+ ("page on pv_list has no pte"));
+ pbits = *pte;
+ if (pte_test(&pbits, PTE_D)) {
+ pte_clear(&pbits, PTE_D);
+ vm_page_dirty(m);
+ m->md.pv_flags &= ~PV_TABLE_MOD;
+ }
+ pte_set(&pbits, PTE_RO);
+ if (pbits != *pte) {
+ *pte = pbits;
+ pmap_update_page(pmap, pv->pv_va, pbits);
+ }
+ PMAP_UNLOCK(pmap);
}
vm_page_aflag_clear(m, PGA_WRITEABLE);
vm_page_unlock_queues();
diff -r a301a330526b -r 49889ad5ef1f head/sys/mips/rt305x/rt305x_gpio.c
--- a/head/sys/mips/rt305x/rt305x_gpio.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/mips/rt305x/rt305x_gpio.c Wed Aug 15 11:46:11 2012 +0300
@@ -141,7 +141,6 @@
}
}
-
if (flags & GPIO_PIN_REPORT) {
pin->gp_flags |= GPIO_PIN_REPORT;
GPIO_BIT_SET(sc, pin->gp_pin, RENA);
@@ -574,7 +573,7 @@
rt305x_gpio_register_irq_handler),
DEVMETHOD(gpio_unregister_irq_handler,
rt305x_gpio_unregister_irq_handler),
- {0, 0},
+ DEVMETHOD_END
};
static driver_t rt305x_gpio_driver = {
diff -r a301a330526b -r 49889ad5ef1f head/sys/modules/Makefile
--- a/head/sys/modules/Makefile Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/modules/Makefile Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD: head/sys/modules/Makefile 238026 2012-07-02 20:36:26Z marcel $
+# $FreeBSD: head/sys/modules/Makefile 239281 2012-08-15 06:31:32Z gonzo $
.include <bsd.own.mk>
@@ -72,6 +72,7 @@
${_coff} \
${_coretemp} \
${_cp} \
+ ${_cpsw} \
${_cpuctl} \
${_cpufreq} \
${_crypto} \
@@ -743,6 +744,7 @@
.if ${MACHINE_CPUARCH} == "arm"
_cfi= cfi
+_cpsw= cpsw
.endif
.if ${MACHINE_CPUARCH} == "ia64"
diff -r a301a330526b -r 49889ad5ef1f head/sys/modules/cpsw/Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/modules/cpsw/Makefile Wed Aug 15 11:46:11 2012 +0300
@@ -0,0 +1,8 @@
+# $FreeBSD: head/sys/modules/cpsw/Makefile 239281 2012-08-15 06:31:32Z gonzo $
+
+.PATH: ${.CURDIR}/../../arm/ti/cpsw
+
+KMOD= if_cpsw
+SRCS= if_cpsw.c device_if.h bus_if.h ofw_bus_if.h miibus_if.h
+
+.include <bsd.kmod.mk>
diff -r a301a330526b -r 49889ad5ef1f head/sys/modules/cxgbe/if_cxgbe/Makefile
--- a/head/sys/modules/cxgbe/if_cxgbe/Makefile Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/modules/cxgbe/if_cxgbe/Makefile Wed Aug 15 11:46:11 2012 +0300
@@ -1,7 +1,9 @@
#
-# $FreeBSD: head/sys/modules/cxgbe/if_cxgbe/Makefile 237819 2012-06-29 19:51:06Z np $
+# $FreeBSD: head/sys/modules/cxgbe/if_cxgbe/Makefile 239264 2012-08-14 23:08:49Z np $
#
+.include <bsd.own.mk>
+
CXGBE = ${.CURDIR}/../../../dev/cxgbe
.PATH: ${CXGBE} ${CXGBE}/common
@@ -17,4 +19,17 @@
# Provide the timestamp of a packet in its header mbuf.
#CFLAGS+= -DT4_PKT_TIMESTAMP
+.if !defined(KERNBUILDDIR)
+.if ${MK_INET_SUPPORT} != "no"
+opt_inet.h:
+ @echo "#define INET 1" > ${.TARGET}
+ @echo "#define TCP_OFFLOAD 1" >> ${.TARGET}
+.endif
+
+.if ${MK_INET6_SUPPORT} != "no"
+opt_inet6.h:
+ @echo "#define INET6 1" > ${.TARGET}
+.endif
+.endif
+
.include <bsd.kmod.mk>
diff -r a301a330526b -r 49889ad5ef1f head/sys/modules/cxgbe/tom/Makefile
--- a/head/sys/modules/cxgbe/tom/Makefile Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/modules/cxgbe/tom/Makefile Wed Aug 15 11:46:11 2012 +0300
@@ -1,7 +1,9 @@
#
-# $FreeBSD: head/sys/modules/cxgbe/tom/Makefile 237263 2012-06-19 07:34:13Z np $
+# $FreeBSD: head/sys/modules/cxgbe/tom/Makefile 239264 2012-08-14 23:08:49Z np $
#
+.include <bsd.own.mk>
+
CXGBE = ${.CURDIR}/../../../dev/cxgbe
.PATH: ${CXGBE}/tom
@@ -12,4 +14,12 @@
CFLAGS+= -I${CXGBE}
+.if !defined(KERNBUILDDIR)
+.if ${MK_INET_SUPPORT} != "no"
+opt_inet.h:
+ echo "#define INET 1" > ${.TARGET}
+ echo "#define TCP_OFFLOAD 1" >> ${.TARGET}
+.endif
+.endif
+
.include <bsd.kmod.mk>
diff -r a301a330526b -r 49889ad5ef1f head/sys/modules/mii/Makefile
--- a/head/sys/modules/mii/Makefile Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/modules/mii/Makefile Wed Aug 15 11:46:11 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD: head/sys/modules/mii/Makefile 232016 2012-02-23 01:22:40Z yongari $
+# $FreeBSD: head/sys/modules/mii/Makefile 239275 2012-08-15 04:03:55Z gonzo $
.PATH: ${.CURDIR}/../../dev/mii
@@ -8,7 +8,8 @@
SRCS+= e1000phy.c gentbi.c icsphy.c ip1000phy.c jmphy.c lxtphy.c
SRCS+= miibus_if.c miibus_if.h mii.c miidevs.h mii_bitbang.c mii_physubr.c
SRCS+= mlphy.c nsgphy.c nsphy.c nsphyter.c pci_if.h pnaphy.c qsphy.c
-SRCS+= rdcphy.c rgephy.c rlphy.c smcphy.c tdkphy.c tlphy.c truephy.c
+SRCS+= rdcphy.c rgephy.c rlphy.c smcphy.c
+SRCS+= smscphy.c tdkphy.c tlphy.c truephy.c
SRCS+= ukphy.c ukphy_subr.c
SRCS+= xmphy.c
diff -r a301a330526b -r 49889ad5ef1f head/sys/modules/usb/smsc/Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/modules/usb/smsc/Makefile Wed Aug 15 11:46:11 2012 +0300
@@ -0,0 +1,37 @@
+#
+# $FreeBSD: head/sys/modules/usb/smsc/Makefile 239275 2012-08-15 04:03:55Z gonzo $
+#
+# Copyright (c) 2011 Ben Gray. 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.
+#
+
+S= ${.CURDIR}/../../..
+
+.PATH: $S/dev/usb/net
+
+KMOD= if_smsc
+SRCS= opt_bus.h opt_usb.h device_if.h bus_if.h usb_if.h usbdevs.h \
+ miibus_if.h opt_inet.h \
+ if_smsc.c
+
+.include <bsd.kmod.mk>
diff -r a301a330526b -r 49889ad5ef1f head/sys/nfsclient/nfs_bio.c
--- a/head/sys/nfsclient/nfs_bio.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/nfsclient/nfs_bio.c Wed Aug 15 11:46:11 2012 +0300
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/nfsclient/nfs_bio.c 239065 2012-08-05 14:11:42Z kib $");
+__FBSDID("$FreeBSD: head/sys/nfsclient/nfs_bio.c 239246 2012-08-14 11:45:47Z kib $");
#include "opt_kdtrace.h"
@@ -212,14 +212,18 @@
("nfs_getpages: page %p is dirty", m));
} else {
/*
- * Read operation was short. If no error occured
- * we may have hit a zero-fill section. We simply
- * leave valid set to 0.
+ * Read operation was short. If no error
+ * occured we may have hit a zero-fill
+ * section. We leave valid set to 0, and page
+ * is freed by vm_page_readahead_finish() if
+ * its index is not equal to requested, or
+ * page is zeroed and set valid by
+ * vm_pager_get_pages() for requested page.
*/
;
}
if (i != ap->a_reqpage)
- vm_page_readahead_finish(m, error);
+ vm_page_readahead_finish(m);
}
VM_OBJECT_UNLOCK(object);
return (0);
diff -r a301a330526b -r 49889ad5ef1f head/sys/sys/bus.h
--- a/head/sys/sys/bus.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/sys/bus.h Wed Aug 15 11:46:11 2012 +0300
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/sys/sys/bus.h 239046 2012-08-05 06:15:12Z andreast $
+ * $FreeBSD: head/sys/sys/bus.h 239178 2012-08-10 15:02:49Z hselasky $
*/
#ifndef _SYS_BUS_H_
@@ -492,6 +492,7 @@
int device_shutdown(device_t dev);
void device_unbusy(device_t dev);
void device_verbose(device_t dev);
+void device_free_softc(device_t dev, void *softc);
/*
* Access functions for devclass.
diff -r a301a330526b -r 49889ad5ef1f head/sys/sys/param.h
--- a/head/sys/sys/param.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/sys/param.h Wed Aug 15 11:46:11 2012 +0300
@@ -32,7 +32,7 @@
* SUCH DAMAGE.
*
* @(#)param.h 8.3 (Berkeley) 4/4/95
- * $FreeBSD: head/sys/sys/param.h 238405 2012-07-12 19:30:53Z jkim $
+ * $FreeBSD: head/sys/sys/param.h 239214 2012-08-12 17:53:06Z hselasky $
*/
#ifndef _SYS_PARAM_H_
@@ -58,7 +58,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 1000015 /* Master, propagated to newvers */
+#define __FreeBSD_version 1000017 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
diff -r a301a330526b -r 49889ad5ef1f head/sys/vm/vm_mmap.c
--- a/head/sys/vm/vm_mmap.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/vm/vm_mmap.c Wed Aug 15 11:46:11 2012 +0300
@@ -41,7 +41,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/vm/vm_mmap.c 234556 2012-04-21 18:36:53Z kib $");
+__FBSDID("$FreeBSD: head/sys/vm/vm_mmap.c 239250 2012-08-14 12:11:48Z kib $");
#include "opt_compat.h"
#include "opt_hwpmc_hooks.h"
@@ -207,11 +207,23 @@
fp = NULL;
- /* Make sure mapping fits into numeric range, etc. */
- if ((uap->len == 0 && !SV_CURPROC_FLAG(SV_AOUT) &&
- curproc->p_osrel >= P_OSREL_MAP_ANON) ||
- ((flags & MAP_ANON) && (uap->fd != -1 || pos != 0)))
- return (EINVAL);
+ /*
+ * Enforce the constraints.
+ * Mapping of length 0 is only allowed for old binaries.
+ * Anonymous mapping shall specify -1 as filedescriptor and
+ * zero position for new code. Be nice to ancient a.out
+ * binaries and correct pos for anonymous mapping, since old
+ * ld.so sometimes issues anonymous map requests with non-zero
+ * pos.
+ */
+ if (!SV_CURPROC_FLAG(SV_AOUT)) {
+ if ((uap->len == 0 && curproc->p_osrel >= P_OSREL_MAP_ANON) ||
+ ((flags & MAP_ANON) != 0 && (uap->fd != -1 || pos != 0)))
+ return (EINVAL);
+ } else {
+ if ((flags & MAP_ANON) != 0)
+ pos = 0;
+ }
if (flags & MAP_STACK) {
if ((uap->fd != -1) ||
@@ -441,6 +453,13 @@
nargs.addr = uap->addr;
nargs.len = uap->len;
nargs.prot = cvtbsdprot[uap->prot & 0x7];
+#ifdef COMPAT_FREEBSD32
+#if defined(__amd64__) || defined(__ia64__)
+ if (i386_read_exec && SV_PROC_FLAG(td->td_proc, SV_ILP32) &&
+ nargs.prot != 0)
+ nargs.prot |= PROT_EXEC;
+#endif
+#endif
nargs.flags = 0;
if (uap->flags & OMAP_ANON)
nargs.flags |= MAP_ANON;
diff -r a301a330526b -r 49889ad5ef1f head/sys/vm/vm_page.c
--- a/head/sys/vm/vm_page.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/vm/vm_page.c Wed Aug 15 11:46:11 2012 +0300
@@ -77,7 +77,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/vm/vm_page.c 239040 2012-08-04 18:16:43Z kib $");
+__FBSDID("$FreeBSD: head/sys/vm/vm_page.c 239246 2012-08-14 11:45:47Z kib $");
#include "opt_vm.h"
@@ -699,10 +699,10 @@
* array which is not the request page.
*/
void
-vm_page_readahead_finish(vm_page_t m, int error)
+vm_page_readahead_finish(vm_page_t m)
{
- if (error == 0) {
+ if (m->valid != 0) {
/*
* Since the page is not the requested page, whether
* it should be activated or deactivated is not
@@ -721,6 +721,12 @@
}
vm_page_wakeup(m);
} else {
+ /*
+ * Free the completely invalid page. Such page state
+ * occurs due to the short read operation which did
+ * not covered our page at all, or in case when a read
+ * error happens.
+ */
vm_page_lock(m);
vm_page_free(m);
vm_page_unlock(m);
diff -r a301a330526b -r 49889ad5ef1f head/sys/vm/vm_page.h
--- a/head/sys/vm/vm_page.h Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/vm/vm_page.h Wed Aug 15 11:46:11 2012 +0300
@@ -57,7 +57,7 @@
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*
- * $FreeBSD: head/sys/vm/vm_page.h 239065 2012-08-05 14:11:42Z kib $
+ * $FreeBSD: head/sys/vm/vm_page.h 239246 2012-08-14 11:45:47Z kib $
*/
/*
@@ -388,7 +388,7 @@
int vm_page_pa_tryrelock(pmap_t, vm_paddr_t, vm_paddr_t *);
vm_page_t vm_page_prev(vm_page_t m);
void vm_page_putfake(vm_page_t m);
-void vm_page_readahead_finish(vm_page_t m, int error);
+void vm_page_readahead_finish(vm_page_t m);
void vm_page_reference(vm_page_t m);
void vm_page_remove (vm_page_t);
void vm_page_rename (vm_page_t, vm_object_t, vm_pindex_t);
diff -r a301a330526b -r 49889ad5ef1f head/sys/vm/vnode_pager.c
--- a/head/sys/vm/vnode_pager.c Wed Aug 15 11:16:36 2012 +0300
+++ b/head/sys/vm/vnode_pager.c Wed Aug 15 11:46:11 2012 +0300
@@ -51,7 +51,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/vm/vnode_pager.c 239065 2012-08-05 14:11:42Z kib $");
+__FBSDID("$FreeBSD: head/sys/vm/vnode_pager.c 239246 2012-08-14 11:45:47Z kib $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -987,7 +987,7 @@
}
if (i != reqpage)
- vm_page_readahead_finish(mt, error);
+ vm_page_readahead_finish(mt);
}
VM_OBJECT_UNLOCK(object);
if (error) {
diff -r a301a330526b -r 49889ad5ef1f head/usr.bin/xlint/Makefile.inc
--- a/head/usr.bin/xlint/Makefile.inc Wed Aug 15 11:16:36 2012 +0300
+++ b/head/usr.bin/xlint/Makefile.inc Wed Aug 15 11:46:11 2012 +0300
@@ -1,5 +1,5 @@
# $NetBSD: Makefile.inc,v 1.8 2002/02/04 00:18:32 thorpej Exp $
-# $FreeBSD: head/usr.bin/xlint/Makefile.inc 233644 2012-03-29 02:54:35Z jmallett $
+# $FreeBSD: head/usr.bin/xlint/Makefile.inc 239272 2012-08-15 03:21:56Z gonzo $
WARNS?= 0
@@ -8,7 +8,7 @@
# These assignments duplicate much of the functionality of
# MACHINE_CPUARCH, but there's no easy way to export make functions...
.if defined(TARGET_ARCH)
-TARGET_CPUARCH= ${TARGET_ARCH:C/mips(n32|64)?(el)?/mips/:C/armeb/arm/}
+TARGET_CPUARCH= ${TARGET_ARCH:C/mips(n32|64)?(el)?/mips/:C/arm(v6)?(eb)?/arm/}
.else
TARGET_CPUARCH= ${MACHINE_CPUARCH}
TARGET_ARCH= ${MACHINE_ARCH}
diff -r a301a330526b -r 49889ad5ef1f head/usr.sbin/lpr/lpd/lpd.8
--- a/head/usr.sbin/lpr/lpd/lpd.8 Wed Aug 15 11:16:36 2012 +0300
+++ b/head/usr.sbin/lpr/lpd/lpd.8 Wed Aug 15 11:46:11 2012 +0300
@@ -26,7 +26,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)lpd.8 8.3 (Berkeley) 4/19/94
-.\" $FreeBSD$
+.\" $FreeBSD: head/usr.sbin/lpr/lpd/lpd.8 239233 2012-08-13 15:16:25Z wblock $
.\"
.Dd June 6, 2001
.Dt LPD 8
@@ -152,7 +152,7 @@
.Pp
The file
.Em minfree
-in each spool directory contains the number of disk blocks to leave free
+in each spool directory contains the number of kilobytes to leave free
so that the line printer queue will not completely fill the disk.
The
.Em minfree
More information about the Zrouter-src-freebsd
mailing list