summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhrs <hrs@FreeBSD.org>2011-06-05 12:27:34 +0000
committerhrs <hrs@FreeBSD.org>2011-06-05 12:27:34 +0000
commit8ff65f2104c6b6188f7a86fc8b074b5d9d8cf576 (patch)
treebe9323d9ac7dde0b1af11cdbcfae206542a1c222
parentecae8238dfcc956729cb43702018343ad85e6ba4 (diff)
parent58bf7d3104c5e5f32bfd96ca36c8551c7d94fa53 (diff)
downloadFreeBSD-src-8ff65f2104c6b6188f7a86fc8b074b5d9d8cf576.zip
FreeBSD-src-8ff65f2104c6b6188f7a86fc8b074b5d9d8cf576.tar.gz
Merge from HEAD@222712.
-rw-r--r--bin/sh/alias.c2
-rw-r--r--bin/sh/eval.c2
-rw-r--r--bin/sh/input.c2
-rw-r--r--bin/sh/jobs.c4
-rw-r--r--bin/sh/main.c2
-rw-r--r--bin/sh/options.c6
-rw-r--r--contrib/binutils/ld/emulparams/elf64bmip-defs.sh10
-rw-r--r--contrib/compiler-rt/CREDITS.TXT3
-rw-r--r--contrib/compiler-rt/LICENSE.TXT53
-rw-r--r--contrib/compiler-rt/README.txt8
-rw-r--r--contrib/compiler-rt/lib/abi.h23
-rw-r--r--contrib/compiler-rt/lib/absvdi2.c7
-rw-r--r--contrib/compiler-rt/lib/absvsi2.c9
-rw-r--r--contrib/compiler-rt/lib/absvti2.c4
-rw-r--r--contrib/compiler-rt/lib/adddf3.c22
-rw-r--r--contrib/compiler-rt/lib/addsf3.c29
-rw-r--r--contrib/compiler-rt/lib/addvdi3.c7
-rw-r--r--contrib/compiler-rt/lib/addvsi3.c7
-rw-r--r--contrib/compiler-rt/lib/addvti3.c4
-rw-r--r--contrib/compiler-rt/lib/apple_versioning.c145
-rw-r--r--contrib/compiler-rt/lib/arm/adddf3vfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/addsf3vfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/bswapdi2.S4
-rw-r--r--contrib/compiler-rt/lib/arm/bswapsi2.S4
-rw-r--r--contrib/compiler-rt/lib/arm/comparesf2.S4
-rw-r--r--contrib/compiler-rt/lib/arm/divdf3vfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/divmodsi4.S47
-rw-r--r--contrib/compiler-rt/lib/arm/divsf3vfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/divsi3.S41
-rw-r--r--contrib/compiler-rt/lib/arm/eqdf2vfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/eqsf2vfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/extendsfdf2vfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/fixdfsivfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/fixsfsivfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/fixunsdfsivfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/fixunssfsivfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/floatsidfvfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/floatsisfvfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/floatunssidfvfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/floatunssisfvfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/gedf2vfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/gesf2vfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/gtdf2vfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/gtsf2vfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/ledf2vfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/lesf2vfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/ltdf2vfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/ltsf2vfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/modsi3.S67
-rw-r--r--contrib/compiler-rt/lib/arm/muldf3vfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/mulsf3vfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/nedf2vfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/negdf2vfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/negsf2vfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/nesf2vfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/restore_vfp_d8_d15_regs.S4
-rw-r--r--contrib/compiler-rt/lib/arm/save_vfp_d8_d15_regs.S4
-rw-r--r--contrib/compiler-rt/lib/arm/softfloat-alias.list21
-rw-r--r--contrib/compiler-rt/lib/arm/subdf3vfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/subsf3vfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/switch16.S4
-rw-r--r--contrib/compiler-rt/lib/arm/switch32.S4
-rw-r--r--contrib/compiler-rt/lib/arm/switch8.S4
-rw-r--r--contrib/compiler-rt/lib/arm/switchu8.S4
-rw-r--r--contrib/compiler-rt/lib/arm/sync_synchronize.S4
-rw-r--r--contrib/compiler-rt/lib/arm/truncdfsf2vfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/udivmodsi4.S80
-rw-r--r--contrib/compiler-rt/lib/arm/udivsi3.S80
-rw-r--r--contrib/compiler-rt/lib/arm/umodsi3.S58
-rw-r--r--contrib/compiler-rt/lib/arm/unorddf2vfp.S4
-rw-r--r--contrib/compiler-rt/lib/arm/unordsf2vfp.S4
-rw-r--r--contrib/compiler-rt/lib/ashldi3.c9
-rw-r--r--contrib/compiler-rt/lib/ashlti3.c4
-rw-r--r--contrib/compiler-rt/lib/ashrdi3.c9
-rw-r--r--contrib/compiler-rt/lib/ashrti3.c4
-rw-r--r--contrib/compiler-rt/lib/assembly.h47
-rw-r--r--contrib/compiler-rt/lib/clear_cache.c4
-rw-r--r--contrib/compiler-rt/lib/clzdi2.c9
-rw-r--r--contrib/compiler-rt/lib/clzsi2.c9
-rw-r--r--contrib/compiler-rt/lib/clzti2.c4
-rw-r--r--contrib/compiler-rt/lib/cmpdi2.c11
-rw-r--r--contrib/compiler-rt/lib/cmpti2.c4
-rw-r--r--contrib/compiler-rt/lib/comparedf2.c4
-rw-r--r--contrib/compiler-rt/lib/comparesf2.c4
-rw-r--r--contrib/compiler-rt/lib/ctzdi2.c7
-rw-r--r--contrib/compiler-rt/lib/ctzsi2.c7
-rw-r--r--contrib/compiler-rt/lib/ctzti2.c4
-rw-r--r--contrib/compiler-rt/lib/divdc3.c4
-rw-r--r--contrib/compiler-rt/lib/divdf3.c7
-rw-r--r--contrib/compiler-rt/lib/divdi3.c9
-rw-r--r--contrib/compiler-rt/lib/divmoddi4.c30
-rw-r--r--contrib/compiler-rt/lib/divmodsi4.c31
-rw-r--r--contrib/compiler-rt/lib/divsc3.c4
-rw-r--r--contrib/compiler-rt/lib/divsf3.c7
-rw-r--r--contrib/compiler-rt/lib/divsi3.c11
-rw-r--r--contrib/compiler-rt/lib/divti3.c4
-rw-r--r--contrib/compiler-rt/lib/divxc3.c4
-rw-r--r--contrib/compiler-rt/lib/enable_execute_stack.c4
-rw-r--r--contrib/compiler-rt/lib/endianness.h4
-rw-r--r--contrib/compiler-rt/lib/eprintf.c4
-rw-r--r--contrib/compiler-rt/lib/extendsfdf2.c8
-rw-r--r--contrib/compiler-rt/lib/ffsdi2.c7
-rw-r--r--contrib/compiler-rt/lib/ffsti2.c4
-rw-r--r--contrib/compiler-rt/lib/fixdfdi.c7
-rw-r--r--contrib/compiler-rt/lib/fixdfsi.c9
-rw-r--r--contrib/compiler-rt/lib/fixdfti.c4
-rw-r--r--contrib/compiler-rt/lib/fixsfdi.c9
-rw-r--r--contrib/compiler-rt/lib/fixsfsi.c11
-rw-r--r--contrib/compiler-rt/lib/fixsfti.c4
-rw-r--r--contrib/compiler-rt/lib/fixunsdfdi.c9
-rw-r--r--contrib/compiler-rt/lib/fixunsdfsi.c9
-rw-r--r--contrib/compiler-rt/lib/fixunsdfti.c4
-rw-r--r--contrib/compiler-rt/lib/fixunssfdi.c10
-rw-r--r--contrib/compiler-rt/lib/fixunssfsi.c9
-rw-r--r--contrib/compiler-rt/lib/fixunssfti.c4
-rw-r--r--contrib/compiler-rt/lib/fixunsxfdi.c4
-rw-r--r--contrib/compiler-rt/lib/fixunsxfsi.c4
-rw-r--r--contrib/compiler-rt/lib/fixunsxfti.c4
-rw-r--r--contrib/compiler-rt/lib/fixxfdi.c4
-rw-r--r--contrib/compiler-rt/lib/fixxfti.c4
-rw-r--r--contrib/compiler-rt/lib/floatdidf.c11
-rw-r--r--contrib/compiler-rt/lib/floatdisf.c12
-rw-r--r--contrib/compiler-rt/lib/floatdixf.c4
-rw-r--r--contrib/compiler-rt/lib/floatsidf.c9
-rw-r--r--contrib/compiler-rt/lib/floatsisf.c9
-rw-r--r--contrib/compiler-rt/lib/floattidf.c4
-rw-r--r--contrib/compiler-rt/lib/floattisf.c4
-rw-r--r--contrib/compiler-rt/lib/floattixf.c4
-rw-r--r--contrib/compiler-rt/lib/floatundidf.c14
-rw-r--r--contrib/compiler-rt/lib/floatundisf.c12
-rw-r--r--contrib/compiler-rt/lib/floatundixf.c4
-rw-r--r--contrib/compiler-rt/lib/floatunsidf.c9
-rw-r--r--contrib/compiler-rt/lib/floatunsisf.c9
-rw-r--r--contrib/compiler-rt/lib/floatuntidf.c4
-rw-r--r--contrib/compiler-rt/lib/floatuntisf.c4
-rw-r--r--contrib/compiler-rt/lib/floatuntixf.c4
-rw-r--r--contrib/compiler-rt/lib/fp_lib.h4
-rw-r--r--contrib/compiler-rt/lib/gcc_personality_v0.c4
-rw-r--r--contrib/compiler-rt/lib/i386/ashldi3.S4
-rw-r--r--contrib/compiler-rt/lib/i386/ashrdi3.S4
-rw-r--r--contrib/compiler-rt/lib/i386/divdi3.S4
-rw-r--r--contrib/compiler-rt/lib/i386/floatdidf.S4
-rw-r--r--contrib/compiler-rt/lib/i386/floatdisf.S4
-rw-r--r--contrib/compiler-rt/lib/i386/floatdixf.S4
-rw-r--r--contrib/compiler-rt/lib/i386/floatundidf.S4
-rw-r--r--contrib/compiler-rt/lib/i386/floatundisf.S4
-rw-r--r--contrib/compiler-rt/lib/i386/floatundixf.S4
-rw-r--r--contrib/compiler-rt/lib/i386/lshrdi3.S4
-rw-r--r--contrib/compiler-rt/lib/i386/moddi3.S4
-rw-r--r--contrib/compiler-rt/lib/i386/muldi3.S4
-rw-r--r--contrib/compiler-rt/lib/i386/udivdi3.S4
-rw-r--r--contrib/compiler-rt/lib/i386/umoddi3.S4
-rw-r--r--contrib/compiler-rt/lib/int_lib.h5
-rw-r--r--contrib/compiler-rt/lib/lshrdi3.c9
-rw-r--r--contrib/compiler-rt/lib/lshrti3.c4
-rw-r--r--contrib/compiler-rt/lib/moddi3.c9
-rw-r--r--contrib/compiler-rt/lib/modsi3.c11
-rw-r--r--contrib/compiler-rt/lib/modti3.c4
-rw-r--r--contrib/compiler-rt/lib/muldc3.c4
-rw-r--r--contrib/compiler-rt/lib/muldf3.c10
-rw-r--r--contrib/compiler-rt/lib/muldi3.c11
-rw-r--r--contrib/compiler-rt/lib/mulsc3.c4
-rw-r--r--contrib/compiler-rt/lib/mulsf3.c10
-rw-r--r--contrib/compiler-rt/lib/multi3.c4
-rw-r--r--contrib/compiler-rt/lib/mulvdi3.c4
-rw-r--r--contrib/compiler-rt/lib/mulvsi3.c4
-rw-r--r--contrib/compiler-rt/lib/mulvti3.c4
-rw-r--r--contrib/compiler-rt/lib/mulxc3.c4
-rw-r--r--contrib/compiler-rt/lib/negdf2.c7
-rw-r--r--contrib/compiler-rt/lib/negdi2.c4
-rw-r--r--contrib/compiler-rt/lib/negsf2.c10
-rw-r--r--contrib/compiler-rt/lib/negti2.c4
-rw-r--r--contrib/compiler-rt/lib/negvdi2.c7
-rw-r--r--contrib/compiler-rt/lib/negvsi2.c7
-rw-r--r--contrib/compiler-rt/lib/negvti2.c4
-rw-r--r--contrib/compiler-rt/lib/paritydi2.c9
-rw-r--r--contrib/compiler-rt/lib/paritysi2.c7
-rw-r--r--contrib/compiler-rt/lib/parityti2.c4
-rw-r--r--contrib/compiler-rt/lib/popcountdi2.c7
-rw-r--r--contrib/compiler-rt/lib/popcountsi2.c7
-rw-r--r--contrib/compiler-rt/lib/popcountti2.c4
-rw-r--r--contrib/compiler-rt/lib/powidf2.c7
-rw-r--r--contrib/compiler-rt/lib/powisf2.c7
-rw-r--r--contrib/compiler-rt/lib/powitf2.c4
-rw-r--r--contrib/compiler-rt/lib/powixf2.c4
-rw-r--r--contrib/compiler-rt/lib/ppc/restFP.S4
-rw-r--r--contrib/compiler-rt/lib/ppc/saveFP.S4
-rw-r--r--contrib/compiler-rt/lib/subdf3.c30
-rw-r--r--contrib/compiler-rt/lib/subsf3.c29
-rw-r--r--contrib/compiler-rt/lib/subvdi3.c9
-rw-r--r--contrib/compiler-rt/lib/subvsi3.c9
-rw-r--r--contrib/compiler-rt/lib/subvti3.c4
-rw-r--r--contrib/compiler-rt/lib/trampoline_setup.c4
-rw-r--r--contrib/compiler-rt/lib/truncdfsf2.c11
-rw-r--r--contrib/compiler-rt/lib/ucmpdi2.c7
-rw-r--r--contrib/compiler-rt/lib/ucmpti2.c4
-rw-r--r--contrib/compiler-rt/lib/udivdi3.c9
-rw-r--r--contrib/compiler-rt/lib/udivmoddi4.c9
-rw-r--r--contrib/compiler-rt/lib/udivmodsi4.c31
-rw-r--r--contrib/compiler-rt/lib/udivmodti4.c4
-rw-r--r--contrib/compiler-rt/lib/udivsi3.c9
-rw-r--r--contrib/compiler-rt/lib/udivti3.c4
-rw-r--r--contrib/compiler-rt/lib/umoddi3.c9
-rw-r--r--contrib/compiler-rt/lib/umodsi3.c9
-rw-r--r--contrib/compiler-rt/lib/umodti3.c4
-rw-r--r--contrib/compiler-rt/lib/x86_64/floatundidf.S4
-rw-r--r--contrib/compiler-rt/lib/x86_64/floatundisf.S4
-rw-r--r--contrib/compiler-rt/lib/x86_64/floatundixf.S4
-rw-r--r--contrib/groff/tmac/troffrc8
-rw-r--r--contrib/libpcap/pcap-bpf.c1
-rw-r--r--contrib/ntp/ntpd/ntp_io.c9
-rw-r--r--contrib/top/commands.c1
-rw-r--r--contrib/top/machine.h1
-rw-r--r--contrib/top/top.X22
-rw-r--r--contrib/top/top.c24
-rw-r--r--etc/defaults/rc.conf2
-rw-r--r--etc/network.subr28
-rw-r--r--lib/libc/gen/posix_spawn.c7
-rw-r--r--lib/libc/iconv/iconvctl.36
-rw-r--r--lib/libcompiler_rt/Makefile5
-rw-r--r--lib/msun/ld128/e_rem_pio2l.h5
-rw-r--r--lib/msun/ld80/e_rem_pio2l.h5
-rw-r--r--lib/msun/src/s_cosl.c1
-rw-r--r--lib/msun/src/s_sinl.c1
-rw-r--r--lib/msun/src/s_tanl.c1
-rw-r--r--sbin/geom/class/part/geom_part.c51
-rw-r--r--sbin/geom/class/part/gpart.8171
-rw-r--r--sbin/hastd/primary.c2
-rw-r--r--sbin/hastd/proto_common.c16
-rw-r--r--sbin/ifconfig/Makefile12
-rw-r--r--sbin/ifconfig/af_inet.c2
-rw-r--r--sbin/ifconfig/af_inet6.c3
-rw-r--r--sbin/ifconfig/ifconfig.810
-rw-r--r--sbin/ifconfig/ifconfig.c27
-rw-r--r--sbin/ipfw/ipfw.89
-rw-r--r--sbin/ipfw/ipfw2.c21
-rw-r--r--sbin/setkey/setkey.85
-rw-r--r--sbin/umount/umount.85
-rw-r--r--sbin/umount/umount.c7
-rw-r--r--share/man/man4/Makefile3
-rw-r--r--share/man/man4/ath.415
-rw-r--r--share/man/man4/ath_ahb.460
-rw-r--r--share/man/man4/ath_hal.414
-rw-r--r--share/man/man4/ath_pci.457
-rw-r--r--share/man/man4/bwn.46
-rw-r--r--share/man/man4/em.428
-rw-r--r--share/man/man4/igb.428
-rw-r--r--share/man/man4/mps.426
-rw-r--r--share/man/man4/stf.4129
-rw-r--r--share/man/man4/ucom.41
-rw-r--r--share/man/man4/uep.410
-rw-r--r--share/man/man4/umcs.497
-rw-r--r--share/man/man4/vge.49
-rw-r--r--share/man/man7/c99.74
-rw-r--r--share/man/man7/ports.74
-rw-r--r--share/man/man7/release.76
-rw-r--r--share/man/man9/bus_adjust_resource.918
-rw-r--r--share/misc/mdoc.template1
-rw-r--r--share/mk/bsd.doc.mk6
-rw-r--r--sys/boot/forth/check-password.4th.82
-rw-r--r--sys/boot/ia64/common/Makefile1
-rw-r--r--sys/boot/powerpc/ofw/Makefile1
-rw-r--r--sys/boot/powerpc/ps3/Makefile3
-rw-r--r--sys/boot/sparc64/loader/Makefile3
-rw-r--r--sys/cam/ata/ata_da.c129
-rw-r--r--sys/cddl/compat/opensolaris/kern/opensolaris.c3
-rw-r--r--sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c5
-rw-r--r--sys/cddl/compat/opensolaris/sys/time.h17
-rw-r--r--sys/conf/files10
-rw-r--r--sys/conf/files.powerpc7
-rw-r--r--sys/contrib/dev/acpica/changes.txt129
-rw-r--r--sys/contrib/dev/acpica/debugger/dbexec.c405
-rw-r--r--sys/contrib/dev/acpica/debugger/dbinput.c112
-rw-r--r--sys/contrib/dev/acpica/debugger/dbutils.c7
-rw-r--r--sys/contrib/dev/acpica/debugger/dbxface.c8
-rw-r--r--sys/contrib/dev/acpica/include/acconfig.h3
-rw-r--r--sys/contrib/dev/acpica/include/acdebug.h7
-rw-r--r--sys/contrib/dev/acpica/include/acglobal.h9
-rw-r--r--sys/contrib/dev/acpica/include/aclocal.h2
-rw-r--r--sys/contrib/dev/acpica/include/acpiosxf.h6
-rw-r--r--sys/contrib/dev/acpica/include/acpixf.h2
-rw-r--r--sys/contrib/dev/acpica/include/acpredef.h1
-rw-r--r--sys/contrib/dev/acpica/osunixxf.c24
-rw-r--r--sys/contrib/dev/acpica/tables/tbinstal.c26
-rw-r--r--sys/contrib/pf/net/pf.c47
-rw-r--r--sys/contrib/pf/net/pf_ioctl.c5
-rw-r--r--sys/contrib/pf/net/pf_norm.c2
-rw-r--r--sys/dev/acpica/Osd/OsdDebug.c23
-rw-r--r--sys/dev/ath/ath_dfs/null/dfs_null.c160
-rw-r--r--sys/dev/ath/ath_hal/ah.c6
-rw-r--r--sys/dev/ath/ath_hal/ah.h51
-rw-r--r--sys/dev/ath/ath_hal/ah_desc.h3
-rw-r--r--sys/dev/ath/ath_hal/ah_internal.h2
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212.h4
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212_attach.c5
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212_misc.c65
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212reg.h1
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416.h4
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_attach.c6
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_misc.c132
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416phy.h19
-rw-r--r--sys/dev/ath/ath_hal/ar9001/ar9130_attach.c1
-rw-r--r--sys/dev/ath/ath_hal/ar9001/ar9160_attach.c1
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9280_attach.c2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9285_attach.c1
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9287_attach.c3
-rw-r--r--sys/dev/ath/if_ath.c82
-rw-r--r--sys/dev/ath/if_ath_tx_ht.c20
-rw-r--r--sys/dev/ath/if_athdfs.h47
-rw-r--r--sys/dev/ath/if_athvar.h16
-rw-r--r--sys/dev/cxgbe/adapter.h23
-rw-r--r--sys/dev/cxgbe/common/common.h2
-rw-r--r--sys/dev/cxgbe/common/jhash.h140
-rw-r--r--sys/dev/cxgbe/common/t4fw_interface.h237
-rw-r--r--sys/dev/cxgbe/offload.h18
-rw-r--r--sys/dev/cxgbe/osdep.h1
-rw-r--r--sys/dev/cxgbe/t4_ioctl.h2
-rw-r--r--sys/dev/cxgbe/t4_l2t.c361
-rw-r--r--sys/dev/cxgbe/t4_l2t.h71
-rw-r--r--sys/dev/cxgbe/t4_main.c347
-rw-r--r--sys/dev/cxgbe/t4_sge.c381
-rw-r--r--sys/dev/iicbus/ad7417.c537
-rw-r--r--sys/dev/iicbus/ds1775.c105
-rw-r--r--sys/dev/iicbus/max6690.c113
-rw-r--r--sys/dev/ipw/if_ipw.c2
-rw-r--r--sys/dev/iwi/if_iwi.c2
-rw-r--r--sys/dev/iwn/if_iwn.c23
-rw-r--r--sys/dev/ixgbe/LICENSE2
-rw-r--r--sys/dev/ixgbe/README267
-rw-r--r--sys/dev/ixgbe/ixgbe.c79
-rw-r--r--sys/dev/ixgbe/ixv.c58
-rw-r--r--sys/dev/mfi/mfi.c18
-rw-r--r--sys/dev/mfi/mfireg.h4
-rw-r--r--sys/dev/mmc/mmc.c22
-rw-r--r--sys/dev/mmc/mmcvar.h2
-rw-r--r--sys/dev/msk/if_msk.c2
-rw-r--r--sys/dev/nfe/if_nfe.c2
-rw-r--r--sys/dev/puc/pucdata.c40
-rw-r--r--sys/dev/sdhci/sdhci.c28
-rw-r--r--sys/dev/usb/net/if_axe.c21
-rw-r--r--sys/dev/usb/serial/umcs.c1075
-rw-r--r--sys/dev/usb/serial/umcs.h644
-rw-r--r--sys/dev/usb/usb_process.c7
-rw-r--r--sys/dev/usb/usbdevs2
-rw-r--r--sys/dev/wpi/if_wpi.c2
-rw-r--r--sys/fs/nfsclient/nfs_clbio.c15
-rw-r--r--sys/fs/nfsclient/nfs_clvnops.c13
-rw-r--r--sys/fs/nfsserver/nfs_nfsdport.c30
-rw-r--r--sys/fs/nwfs/nwfs_io.c11
-rw-r--r--sys/fs/smbfs/smbfs_io.c11
-rw-r--r--sys/geom/geom_disk.c6
-rw-r--r--sys/geom/geom_dump.c6
-rw-r--r--sys/geom/part/g_part.c17
-rw-r--r--sys/i386/pci/pci_cfgreg.c2
-rw-r--r--sys/ia64/ia64/machdep.c2
-rw-r--r--sys/ia64/ia64/mp_machdep.c8
-rw-r--r--sys/ia64/ia64/pmap.c2
-rw-r--r--sys/kern/kern_idle.c2
-rw-r--r--sys/kern/sched_4bsd.c4
-rw-r--r--sys/kern/subr_kdb.c2
-rw-r--r--sys/kern/subr_msgbuf.c191
-rw-r--r--sys/kern/subr_pcpu.c6
-rw-r--r--sys/kern/subr_prf.c157
-rw-r--r--sys/kern/uipc_socket.c14
-rw-r--r--sys/mips/cavium/octeon_ebt3000_cf.c331
-rw-r--r--sys/mips/mips/mp_machdep.c2
-rw-r--r--sys/modules/ath/Makefile4
-rw-r--r--sys/modules/cxgbe/if_cxgbe/Makefile2
-rw-r--r--sys/modules/usb/Makefile2
-rw-r--r--sys/modules/usb/umcs/Makefile36
-rw-r--r--sys/net/if_ethersubr.c42
-rw-r--r--sys/net/if_stf.c922
-rw-r--r--sys/net/if_tun.c17
-rw-r--r--sys/net/netisr.c2
-rw-r--r--sys/net80211/ieee80211_ht.c12
-rw-r--r--sys/net80211/ieee80211_output.c13
-rw-r--r--sys/netinet/in_pcb.c148
-rw-r--r--sys/netinet/in_pcb.h56
-rw-r--r--sys/netinet/ip_divert.c8
-rw-r--r--sys/netinet/ipfw/ip_dummynet.c10
-rw-r--r--sys/netinet/ipfw/ip_fw2.c66
-rw-r--r--sys/netinet/ipfw/ip_fw_dynamic.c3
-rw-r--r--sys/netinet/ipfw/ip_fw_sockopt.c3
-rw-r--r--sys/netinet/raw_ip.c29
-rw-r--r--sys/netinet/sctp_indata.c43
-rw-r--r--sys/netinet/sctp_indata.h5
-rw-r--r--sys/netinet/sctputil.c65
-rw-r--r--sys/netinet/sctputil.h14
-rw-r--r--sys/netinet/siftr.c22
-rw-r--r--sys/netinet/tcp_input.c240
-rw-r--r--sys/netinet/tcp_subr.c50
-rw-r--r--sys/netinet/tcp_syncache.c13
-rw-r--r--sys/netinet/tcp_timer.c2
-rw-r--r--sys/netinet/tcp_usrreq.c98
-rw-r--r--sys/netinet/udp_usrreq.c136
-rw-r--r--sys/netinet6/in6_pcb.c105
-rw-r--r--sys/netinet6/in6_pcb.h16
-rw-r--r--sys/netinet6/in6_src.c2
-rw-r--r--sys/netinet6/udp6_usrreq.c78
-rw-r--r--sys/nfsclient/nfs_bio.c8
-rw-r--r--sys/nfsclient/nfs_vfsops.c12
-rw-r--r--sys/powerpc/aim/interrupt.c4
-rw-r--r--sys/powerpc/aim/locore32.S13
-rw-r--r--sys/powerpc/aim/locore64.S134
-rw-r--r--sys/powerpc/aim/machdep.c29
-rw-r--r--sys/powerpc/aim/mmu_oea.c20
-rw-r--r--sys/powerpc/aim/mmu_oea64.c30
-rw-r--r--sys/powerpc/aim/moea64_native.c6
-rw-r--r--sys/powerpc/aim/mp_cpudep.c5
-rw-r--r--sys/powerpc/aim/slb.c26
-rw-r--r--sys/powerpc/aim/trap_subr64.S46
-rw-r--r--sys/powerpc/booke/pmap.c4
-rw-r--r--sys/powerpc/conf/GENERIC2
-rw-r--r--sys/powerpc/conf/GENERIC641
-rw-r--r--sys/powerpc/conf/NOTES2
-rw-r--r--sys/powerpc/include/rtas.h61
-rw-r--r--sys/powerpc/include/slb.h2
-rw-r--r--sys/powerpc/ofw/ofw_machdep.c187
-rw-r--r--sys/powerpc/ofw/ofw_real.c7
-rw-r--r--sys/powerpc/ofw/ofwcall32.S154
-rw-r--r--sys/powerpc/ofw/ofwcall64.S290
-rw-r--r--sys/powerpc/ofw/ofwmagic.S (renamed from sys/powerpc/aim/ofwmagic.S)0
-rw-r--r--sys/powerpc/ofw/rtas.c243
-rw-r--r--sys/powerpc/powermac/fcu.c219
-rw-r--r--sys/powerpc/powermac/powermac_thermal.c17
-rw-r--r--sys/powerpc/powermac/powermac_thermal.h2
-rw-r--r--sys/powerpc/powermac/smu.c2
-rw-r--r--sys/powerpc/powermac/smusat.c2
-rw-r--r--sys/powerpc/powermac/windtunnel.c216
-rw-r--r--sys/powerpc/powerpc/mp_machdep.c6
-rw-r--r--sys/sparc64/sparc64/mp_machdep.c2
-rw-r--r--sys/sparc64/sparc64/pmap.c2
-rw-r--r--sys/sys/mbuf.h40
-rw-r--r--sys/sys/msgbuf.h21
-rw-r--r--sys/sys/pcpu.h4
-rw-r--r--sys/teken/libteken/teken.332
-rw-r--r--sys/vm/vm_object.c15
-rw-r--r--sys/vm/vnode_pager.c19
-rw-r--r--sys/vm/vnode_pager.h3
-rw-r--r--tools/regression/bin/sh/builtins/alias.1.stderr2
-rw-r--r--tools/regression/bin/sh/builtins/set1.032
-rw-r--r--tools/regression/bin/sh/execution/set-n1.07
-rw-r--r--tools/regression/bin/sh/execution/set-n2.05
-rw-r--r--tools/regression/bin/sh/execution/set-n3.04
-rw-r--r--tools/regression/bin/sh/execution/set-n4.03
-rw-r--r--tools/regression/bin/sh/parser/func2.06
-rw-r--r--tools/regression/bin/sh/parser/func3.06
-rw-r--r--tools/regression/netinet/ipdivert/Makefile11
-rw-r--r--tools/regression/netinet/ipdivert/ipdivert.c166
-rw-r--r--tools/regression/netinet/tcpconnect/tcpconnect.c1
-rw-r--r--tools/regression/netinet/tcpdrop/tcpdrop.c81
-rw-r--r--tools/regression/netinet/tcpfullwindowrst/tcpfullwindowrsttest.c1
-rw-r--r--tools/regression/netinet/tcpsocktimewait/tcpsocktimewait.c123
-rw-r--r--tools/regression/netinet/udpconnectjail/udpconnectjail.c11
-rw-r--r--tools/tools/nanobsd/nanobsd.sh2
-rw-r--r--usr.bin/find/main.c2
-rw-r--r--usr.bin/fstat/fuser.120
-rw-r--r--usr.bin/man/man.126
-rw-r--r--usr.bin/man/man.conf.55
-rwxr-xr-xusr.bin/man/man.sh90
-rw-r--r--usr.bin/rctl/rctl.82
-rw-r--r--usr.bin/tftp/main.c6
-rw-r--r--usr.bin/top/machine.c7
-rw-r--r--usr.bin/top/top.local.14
-rw-r--r--usr.sbin/bsdinstall/scripts/Makefile3
-rwxr-xr-xusr.sbin/bsdinstall/scripts/auto2
-rwxr-xr-xusr.sbin/bsdinstall/scripts/netconfig168
-rwxr-xr-xusr.sbin/bsdinstall/scripts/netconfig_ipv485
-rwxr-xr-xusr.sbin/bsdinstall/scripts/netconfig_ipv6149
-rw-r--r--usr.sbin/jail/Makefile3
-rw-r--r--usr.sbin/jail/jail.c76
-rw-r--r--usr.sbin/jls/Makefile9
-rw-r--r--usr.sbin/jls/jls.c76
-rw-r--r--usr.sbin/kbdmap/kbdmap.c2
-rw-r--r--usr.sbin/mfiutil/mfi_evt.c8
-rw-r--r--usr.sbin/mountd/mountd.c243
-rwxr-xr-xusr.sbin/pc-sysinstall/backend-query/enable-net.sh57
-rwxr-xr-xusr.sbin/pc-sysinstall/backend-query/test-netup.sh25
-rwxr-xr-xusr.sbin/pc-sysinstall/backend/functions-networking.sh195
-rw-r--r--usr.sbin/rpc.lockd/lockd.c249
-rw-r--r--usr.sbin/rpc.statd/statd.c240
-rw-r--r--usr.sbin/rtsold/rtsol.c2
-rw-r--r--usr.sbin/usbdump/usbdump.88
483 files changed, 13127 insertions, 3250 deletions
diff --git a/bin/sh/alias.c b/bin/sh/alias.c
index 4662519..929c68e 100644
--- a/bin/sh/alias.c
+++ b/bin/sh/alias.c
@@ -238,7 +238,7 @@ aliascmd(int argc, char **argv)
while ((n = *++argv) != NULL) {
if ((v = strchr(n+1, '=')) == NULL) /* n+1: funny ksh stuff */
if ((ap = lookupalias(n, 0)) == NULL) {
- warning("%s not found", n);
+ warning("%s: not found", n);
ret = 1;
} else
printalias(ap);
diff --git a/bin/sh/eval.c b/bin/sh/eval.c
index a50c53f..404de33 100644
--- a/bin/sh/eval.c
+++ b/bin/sh/eval.c
@@ -165,7 +165,7 @@ evalstring(char *s, int flags)
setstackmark(&smark);
setinputstring(s, 1);
while ((n = parsecmd(0)) != NEOF) {
- if (n != NULL) {
+ if (n != NULL && !nflag) {
if (flags_exit && preadateof())
evaltree(n, flags | EV_EXIT);
else
diff --git a/bin/sh/input.c b/bin/sh/input.c
index e7baed3..c8b1a45 100644
--- a/bin/sh/input.c
+++ b/bin/sh/input.c
@@ -403,7 +403,7 @@ setinputfile(const char *fname, int push)
INTOFF;
if ((fd = open(fname, O_RDONLY)) < 0)
- error("Can't open %s: %s", fname, strerror(errno));
+ error("cannot open %s: %s", fname, strerror(errno));
if (fd < 10) {
fd2 = fcntl(fd, F_DUPFD, 10);
close(fd);
diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c
index f4f1dac..434af22 100644
--- a/bin/sh/jobs.c
+++ b/bin/sh/jobs.c
@@ -820,7 +820,7 @@ forkshell(struct job *jp, union node *n, int mode)
! fd0_redirected_p ()) {
close(0);
if (open(_PATH_DEVNULL, O_RDONLY) != 0)
- error("Can't open %s: %s",
+ error("cannot open %s: %s",
_PATH_DEVNULL, strerror(errno));
}
}
@@ -832,7 +832,7 @@ forkshell(struct job *jp, union node *n, int mode)
! fd0_redirected_p ()) {
close(0);
if (open(_PATH_DEVNULL, O_RDONLY) != 0)
- error("Can't open %s: %s",
+ error("cannot open %s: %s",
_PATH_DEVNULL, strerror(errno));
}
}
diff --git a/bin/sh/main.c b/bin/sh/main.c
index 408d37c..9cef1b0 100644
--- a/bin/sh/main.c
+++ b/bin/sh/main.c
@@ -264,7 +264,7 @@ readcmdfile(const char *name)
if ((fd = open(name, O_RDONLY)) >= 0)
setinputfd(fd, 1);
else
- error("Can't open %s: %s", name, strerror(errno));
+ error("cannot open %s: %s", name, strerror(errno));
INTON;
cmdloop(0);
popfile();
diff --git a/bin/sh/options.c b/bin/sh/options.c
index a99fe81..60c8852 100644
--- a/bin/sh/options.c
+++ b/bin/sh/options.c
@@ -83,6 +83,7 @@ void
procargs(int argc, char **argv)
{
int i;
+ char *scriptname;
argptr = argv;
if (argc > 0)
@@ -105,8 +106,9 @@ procargs(int argc, char **argv)
optlist[i].val = 0;
arg0 = argv[0];
if (sflag == 0 && minusc == NULL) {
- commandname = arg0 = *argptr++;
- setinputfile(commandname, 0);
+ scriptname = *argptr++;
+ setinputfile(scriptname, 0);
+ commandname = arg0 = scriptname;
}
/* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
if (argptr && minusc && *argptr)
diff --git a/contrib/binutils/ld/emulparams/elf64bmip-defs.sh b/contrib/binutils/ld/emulparams/elf64bmip-defs.sh
index 110f892..73094be 100644
--- a/contrib/binutils/ld/emulparams/elf64bmip-defs.sh
+++ b/contrib/binutils/ld/emulparams/elf64bmip-defs.sh
@@ -1,3 +1,11 @@
. ${srcdir}/emulparams/elf32bmipn32-defs.sh
COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)"
-INITIAL_READONLY_SECTIONS=".MIPS.options : { *(.MIPS.options) }"
+
+# elf32bmipn32-defs.sh use .reginfo, n64 ABI should use .MIPS.options,
+# override INITIAL_READONLY_SECTIONS to do this.
+INITIAL_READONLY_SECTIONS=
+if test -z "${CREATE_SHLIB}"; then
+ INITIAL_READONLY_SECTIONS=".interp ${RELOCATING-0} : { *(.interp) }"
+fi
+INITIAL_READONLY_SECTIONS="${INITIAL_READONLY_SECTIONS}
+ .MIPS.options ${RELOCATING-0} : { *(.MIPS.options) }"
diff --git a/contrib/compiler-rt/CREDITS.TXT b/contrib/compiler-rt/CREDITS.TXT
index 8b07b82..818f4fa 100644
--- a/contrib/compiler-rt/CREDITS.TXT
+++ b/contrib/compiler-rt/CREDITS.TXT
@@ -19,3 +19,6 @@ W: http://www.auroraux.org
D: CMake'ify Compiler-RT build system
D: Maintain Solaris & AuroraUX ports of Compiler-RT
+N: Howard Hinnant
+E: hhinnant@apple.com
+D: Architect and primary author of compiler-rt
diff --git a/contrib/compiler-rt/LICENSE.TXT b/contrib/compiler-rt/LICENSE.TXT
index a5e1345..2552e8c 100644
--- a/contrib/compiler-rt/LICENSE.TXT
+++ b/contrib/compiler-rt/LICENSE.TXT
@@ -1,10 +1,21 @@
==============================================================================
-LLVM Release License
+compiler_rt License
==============================================================================
+
+The compiler_rt library is dual licensed under both the University of Illinois
+"BSD-Like" license and the MIT license. As a user of this code you may choose
+to use it under either license. As a contributor, you agree to allow your code
+to be used under both.
+
+Full text of the relevant licenses is included below.
+
+==============================================================================
+
University of Illinois/NCSA
Open Source License
-Copyright (c) 2003-2009 University of Illinois at Urbana-Champaign.
+Copyright (c) 2009-2010 by the contributors listed in CREDITS.TXT
+
All rights reserved.
Developed by:
@@ -43,21 +54,23 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
SOFTWARE.
==============================================================================
-Copyrights and Licenses for Third Party Software Distributed with LLVM:
-==============================================================================
-The LLVM software contains code written by third parties. Such software will
-have its own individual LICENSE.TXT file in the directory in which it appears.
-This file will describe the copyrights, license, and restrictions which apply
-to that code.
-
-The disclaimer of warranty in the University of Illinois Open Source License
-applies to all code in the LLVM Distribution, and nothing in any of the
-other licenses gives permission to use the names of the LLVM Team or the
-University of Illinois to endorse or promote products derived from this
-Software.
-
-The following pieces of software have additional or alternate copyrights,
-licenses, and/or restrictions:
-
-Program Directory
-------- ---------
+
+Copyright (c) 2009-2010 by the contributors listed in CREDITS.TXT
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/contrib/compiler-rt/README.txt b/contrib/compiler-rt/README.txt
index ab389d2..cbeb10c 100644
--- a/contrib/compiler-rt/README.txt
+++ b/contrib/compiler-rt/README.txt
@@ -77,8 +77,12 @@ ti_int __modti3 (ti_int a, ti_int b); // a % b signed
su_int __umodsi3 (su_int a, su_int b); // a % b unsigned
du_int __umoddi3 (du_int a, du_int b); // a % b unsigned
tu_int __umodti3 (tu_int a, tu_int b); // a % b unsigned
-du_int __udivmoddi4(du_int a, du_int b, du_int* rem); // a / b, *rem = a % b
-tu_int __udivmodti4(tu_int a, tu_int b, tu_int* rem); // a / b, *rem = a % b
+du_int __udivmoddi4(du_int a, du_int b, du_int* rem); // a / b, *rem = a % b unsigned
+tu_int __udivmodti4(tu_int a, tu_int b, tu_int* rem); // a / b, *rem = a % b unsigned
+su_int __udivmodsi4(su_int a, su_int b, su_int* rem); // a / b, *rem = a % b unsigned
+si_int __divmodsi4(si_int a, si_int b, si_int* rem); // a / b, *rem = a % b signed
+
+
// Integral arithmetic with trapping overflow
diff --git a/contrib/compiler-rt/lib/abi.h b/contrib/compiler-rt/lib/abi.h
new file mode 100644
index 0000000..2534317
--- /dev/null
+++ b/contrib/compiler-rt/lib/abi.h
@@ -0,0 +1,23 @@
+/* ===------ abi.h - configuration header for compiler-rt -----------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ *
+ * This file is a configuration header for compiler-rt.
+ * This file is not part of the interface of this library.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+
+#if __ARM_EABI__
+# define ARM_EABI_FNALIAS(aeabi_name, name) \
+ void __aeabi_##aeabi_name() __attribute__((alias("__" #name)));
+# define COMPILER_RT_ABI __attribute__((pcs("aapcs")))
+#else
+# define ARM_EABI_FNALIAS(aeabi_name, name)
+# define COMPILER_RT_ABI
+#endif
diff --git a/contrib/compiler-rt/lib/absvdi2.c b/contrib/compiler-rt/lib/absvdi2.c
index 919afd1..9c5d4a2 100644
--- a/contrib/compiler-rt/lib/absvdi2.c
+++ b/contrib/compiler-rt/lib/absvdi2.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
*===----------------------------------------------------------------------===
*
@@ -11,6 +11,7 @@
*
*===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
#include <stdlib.h>
@@ -19,7 +20,7 @@
/* Effects: aborts if abs(x) < 0 */
-di_int
+COMPILER_RT_ABI di_int
__absvdi2(di_int a)
{
const int N = (int)(sizeof(di_int) * CHAR_BIT);
diff --git a/contrib/compiler-rt/lib/absvsi2.c b/contrib/compiler-rt/lib/absvsi2.c
index a2c8e3f..80a1a78 100644
--- a/contrib/compiler-rt/lib/absvsi2.c
+++ b/contrib/compiler-rt/lib/absvsi2.c
@@ -2,15 +2,16 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
* This file implements __absvsi2 for the compiler_rt library.
*
* ===----------------------------------------------------------------------===
- */
+ */
+#include "abi.h"
#include "int_lib.h"
#include <stdlib.h>
@@ -19,7 +20,7 @@
/* Effects: aborts if abs(x) < 0 */
-si_int
+COMPILER_RT_ABI si_int
__absvsi2(si_int a)
{
const int N = (int)(sizeof(si_int) * CHAR_BIT);
diff --git a/contrib/compiler-rt/lib/absvti2.c b/contrib/compiler-rt/lib/absvti2.c
index 0978122..9e73a26 100644
--- a/contrib/compiler-rt/lib/absvti2.c
+++ b/contrib/compiler-rt/lib/absvti2.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/adddf3.c b/contrib/compiler-rt/lib/adddf3.c
index 1ec43dc..3cc997b 100644
--- a/contrib/compiler-rt/lib/adddf3.c
+++ b/contrib/compiler-rt/lib/adddf3.c
@@ -1,21 +1,26 @@
-//===-- lib/adddf3.c - Double-precision addition and subtraction --*- C -*-===//
+//===-- lib/adddf3.c - Double-precision addition ------------------*- C -*-===//
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
-// This file implements double-precision soft-float addition and subtraction
-// with the IEEE-754 default rounding (to nearest, ties to even).
+// This file implements double-precision soft-float addition with the IEEE-754
+// default rounding (to nearest, ties to even).
//
//===----------------------------------------------------------------------===//
+#include "abi.h"
+
#define DOUBLE_PRECISION
#include "fp_lib.h"
-fp_t __adddf3(fp_t a, fp_t b) {
+ARM_EABI_FNALIAS(dadd, adddf3);
+
+COMPILER_RT_ABI fp_t
+__adddf3(fp_t a, fp_t b) {
rep_t aRep = toRep(a);
rep_t bRep = toRep(b);
@@ -147,8 +152,3 @@ fp_t __adddf3(fp_t a, fp_t b) {
if (roundGuardSticky == 0x4) result += result & 1;
return fromRep(result);
}
-
-// Subtraction; flip the sign bit of b and add.
-fp_t __subdf3(fp_t a, fp_t b) {
- return __adddf3(a, fromRep(toRep(b) ^ signBit));
-}
diff --git a/contrib/compiler-rt/lib/addsf3.c b/contrib/compiler-rt/lib/addsf3.c
index fec14e8..20610ef 100644
--- a/contrib/compiler-rt/lib/addsf3.c
+++ b/contrib/compiler-rt/lib/addsf3.c
@@ -1,20 +1,24 @@
-//===-- lib/addsf3.c - Single-precision addition and subtraction --*- C -*-===//
+//===-- lib/addsf3.c - Single-precision addition ------------------*- C -*-===//
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
-// This file implements single-precision soft-float addition and subtraction
-// with the IEEE-754 default rounding (to nearest, ties to even).
+// This file implements single-precision soft-float addition with the IEEE-754
+// default rounding (to nearest, ties to even).
//
//===----------------------------------------------------------------------===//
+#include "abi.h"
+
#define SINGLE_PRECISION
#include "fp_lib.h"
+ARM_EABI_FNALIAS(fadd, addsf3);
+
fp_t __addsf3(fp_t a, fp_t b) {
rep_t aRep = toRep(a);
@@ -147,18 +151,3 @@ fp_t __addsf3(fp_t a, fp_t b) {
if (roundGuardSticky == 0x4) result += result & 1;
return fromRep(result);
}
-
-// Subtraction; flip the sign bit of b and add.
-fp_t __subsf3(fp_t a, fp_t b) {
- return __addsf3(a, fromRep(toRep(b) ^ signBit));
-}
-
-
-
-
-
-
-
-
-
-
diff --git a/contrib/compiler-rt/lib/addvdi3.c b/contrib/compiler-rt/lib/addvdi3.c
index 53ab102..51ad397 100644
--- a/contrib/compiler-rt/lib/addvdi3.c
+++ b/contrib/compiler-rt/lib/addvdi3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,6 +11,7 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
#include <stdlib.h>
@@ -19,7 +20,7 @@
/* Effects: aborts if a + b overflows */
-di_int
+COMPILER_RT_ABI di_int
__addvdi3(di_int a, di_int b)
{
di_int s = a + b;
diff --git a/contrib/compiler-rt/lib/addvsi3.c b/contrib/compiler-rt/lib/addvsi3.c
index 22cd315..c18f7bd 100644
--- a/contrib/compiler-rt/lib/addvsi3.c
+++ b/contrib/compiler-rt/lib/addvsi3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,6 +11,7 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
#include <stdlib.h>
@@ -19,7 +20,7 @@
/* Effects: aborts if a + b overflows */
-si_int
+COMPILER_RT_ABI si_int
__addvsi3(si_int a, si_int b)
{
si_int s = a + b;
diff --git a/contrib/compiler-rt/lib/addvti3.c b/contrib/compiler-rt/lib/addvti3.c
index 3df1a74..ba220f5 100644
--- a/contrib/compiler-rt/lib/addvti3.c
+++ b/contrib/compiler-rt/lib/addvti3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/apple_versioning.c b/contrib/compiler-rt/lib/apple_versioning.c
index 0360026..e838d72 100644
--- a/contrib/compiler-rt/lib/apple_versioning.c
+++ b/contrib/compiler-rt/lib/apple_versioning.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*/
@@ -143,6 +143,147 @@ NOT_HERE_BEFORE_10_6(__gcc_qsub)
NOT_HERE_BEFORE_10_6(__trampoline_setup)
#endif /* __ppc__ */
+#if __arm__ && __DYNAMIC__
+ #define NOT_HERE_UNTIL_AFTER_4_3(sym) \
+ extern const char sym##_tmp1 __asm("$ld$hide$os3.0$_" #sym ); \
+ __attribute__((visibility("default"))) const char sym##_tmp1 = 0; \
+ extern const char sym##_tmp2 __asm("$ld$hide$os3.1$_" #sym ); \
+ __attribute__((visibility("default"))) const char sym##_tmp2 = 0; \
+ extern const char sym##_tmp3 __asm("$ld$hide$os3.2$_" #sym ); \
+ __attribute__((visibility("default"))) const char sym##_tmp3 = 0; \
+ extern const char sym##_tmp4 __asm("$ld$hide$os4.0$_" #sym ); \
+ __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \
+ extern const char sym##_tmp5 __asm("$ld$hide$os4.1$_" #sym ); \
+ __attribute__((visibility("default"))) const char sym##_tmp5 = 0; \
+ extern const char sym##_tmp6 __asm("$ld$hide$os4.2$_" #sym ); \
+ __attribute__((visibility("default"))) const char sym##_tmp6 = 0; \
+ extern const char sym##_tmp7 __asm("$ld$hide$os4.3$_" #sym ); \
+ __attribute__((visibility("default"))) const char sym##_tmp7 = 0;
+
+NOT_HERE_UNTIL_AFTER_4_3(__absvdi2)
+NOT_HERE_UNTIL_AFTER_4_3(__absvsi2)
+NOT_HERE_UNTIL_AFTER_4_3(__adddf3)
+NOT_HERE_UNTIL_AFTER_4_3(__adddf3vfp)
+NOT_HERE_UNTIL_AFTER_4_3(__addsf3)
+NOT_HERE_UNTIL_AFTER_4_3(__addsf3vfp)
+NOT_HERE_UNTIL_AFTER_4_3(__addvdi3)
+NOT_HERE_UNTIL_AFTER_4_3(__addvsi3)
+NOT_HERE_UNTIL_AFTER_4_3(__ashldi3)
+NOT_HERE_UNTIL_AFTER_4_3(__ashrdi3)
+NOT_HERE_UNTIL_AFTER_4_3(__bswapdi2)
+NOT_HERE_UNTIL_AFTER_4_3(__bswapsi2)
+NOT_HERE_UNTIL_AFTER_4_3(__clzdi2)
+NOT_HERE_UNTIL_AFTER_4_3(__clzsi2)
+NOT_HERE_UNTIL_AFTER_4_3(__cmpdi2)
+NOT_HERE_UNTIL_AFTER_4_3(__ctzdi2)
+NOT_HERE_UNTIL_AFTER_4_3(__ctzsi2)
+NOT_HERE_UNTIL_AFTER_4_3(__divdc3)
+NOT_HERE_UNTIL_AFTER_4_3(__divdf3)
+NOT_HERE_UNTIL_AFTER_4_3(__divdf3vfp)
+NOT_HERE_UNTIL_AFTER_4_3(__divdi3)
+NOT_HERE_UNTIL_AFTER_4_3(__divsc3)
+NOT_HERE_UNTIL_AFTER_4_3(__divsf3)
+NOT_HERE_UNTIL_AFTER_4_3(__divsf3vfp)
+NOT_HERE_UNTIL_AFTER_4_3(__divsi3)
+NOT_HERE_UNTIL_AFTER_4_3(__eqdf2)
+NOT_HERE_UNTIL_AFTER_4_3(__eqdf2vfp)
+NOT_HERE_UNTIL_AFTER_4_3(__eqsf2)
+NOT_HERE_UNTIL_AFTER_4_3(__eqsf2vfp)
+NOT_HERE_UNTIL_AFTER_4_3(__extendsfdf2)
+NOT_HERE_UNTIL_AFTER_4_3(__extendsfdf2vfp)
+NOT_HERE_UNTIL_AFTER_4_3(__ffsdi2)
+NOT_HERE_UNTIL_AFTER_4_3(__fixdfdi)
+NOT_HERE_UNTIL_AFTER_4_3(__fixdfsi)
+NOT_HERE_UNTIL_AFTER_4_3(__fixdfsivfp)
+NOT_HERE_UNTIL_AFTER_4_3(__fixsfdi)
+NOT_HERE_UNTIL_AFTER_4_3(__fixsfsi)
+NOT_HERE_UNTIL_AFTER_4_3(__fixsfsivfp)
+NOT_HERE_UNTIL_AFTER_4_3(__fixunsdfdi)
+NOT_HERE_UNTIL_AFTER_4_3(__fixunsdfsi)
+NOT_HERE_UNTIL_AFTER_4_3(__fixunsdfsivfp)
+NOT_HERE_UNTIL_AFTER_4_3(__fixunssfdi)
+NOT_HERE_UNTIL_AFTER_4_3(__fixunssfsi)
+NOT_HERE_UNTIL_AFTER_4_3(__fixunssfsivfp)
+NOT_HERE_UNTIL_AFTER_4_3(__floatdidf)
+NOT_HERE_UNTIL_AFTER_4_3(__floatdisf)
+NOT_HERE_UNTIL_AFTER_4_3(__floatsidf)
+NOT_HERE_UNTIL_AFTER_4_3(__floatsidfvfp)
+NOT_HERE_UNTIL_AFTER_4_3(__floatsisf)
+NOT_HERE_UNTIL_AFTER_4_3(__floatsisfvfp)
+NOT_HERE_UNTIL_AFTER_4_3(__floatundidf)
+NOT_HERE_UNTIL_AFTER_4_3(__floatundisf)
+NOT_HERE_UNTIL_AFTER_4_3(__floatunsidf)
+NOT_HERE_UNTIL_AFTER_4_3(__floatunsisf)
+NOT_HERE_UNTIL_AFTER_4_3(__floatunssidfvfp)
+NOT_HERE_UNTIL_AFTER_4_3(__floatunssisfvfp)
+NOT_HERE_UNTIL_AFTER_4_3(__gedf2)
+NOT_HERE_UNTIL_AFTER_4_3(__gedf2vfp)
+NOT_HERE_UNTIL_AFTER_4_3(__gesf2)
+NOT_HERE_UNTIL_AFTER_4_3(__gesf2vfp)
+NOT_HERE_UNTIL_AFTER_4_3(__gtdf2)
+NOT_HERE_UNTIL_AFTER_4_3(__gtdf2vfp)
+NOT_HERE_UNTIL_AFTER_4_3(__gtsf2)
+NOT_HERE_UNTIL_AFTER_4_3(__gtsf2vfp)
+NOT_HERE_UNTIL_AFTER_4_3(__ledf2)
+NOT_HERE_UNTIL_AFTER_4_3(__ledf2vfp)
+NOT_HERE_UNTIL_AFTER_4_3(__lesf2)
+NOT_HERE_UNTIL_AFTER_4_3(__lesf2vfp)
+NOT_HERE_UNTIL_AFTER_4_3(__lshrdi3)
+NOT_HERE_UNTIL_AFTER_4_3(__ltdf2)
+NOT_HERE_UNTIL_AFTER_4_3(__ltdf2vfp)
+NOT_HERE_UNTIL_AFTER_4_3(__ltsf2)
+NOT_HERE_UNTIL_AFTER_4_3(__ltsf2vfp)
+NOT_HERE_UNTIL_AFTER_4_3(__moddi3)
+NOT_HERE_UNTIL_AFTER_4_3(__modsi3)
+NOT_HERE_UNTIL_AFTER_4_3(__muldc3)
+NOT_HERE_UNTIL_AFTER_4_3(__muldf3)
+NOT_HERE_UNTIL_AFTER_4_3(__muldf3vfp)
+NOT_HERE_UNTIL_AFTER_4_3(__muldi3)
+NOT_HERE_UNTIL_AFTER_4_3(__mulsc3)
+NOT_HERE_UNTIL_AFTER_4_3(__mulsf3)
+NOT_HERE_UNTIL_AFTER_4_3(__mulsf3vfp)
+NOT_HERE_UNTIL_AFTER_4_3(__mulvdi3)
+NOT_HERE_UNTIL_AFTER_4_3(__mulvsi3)
+NOT_HERE_UNTIL_AFTER_4_3(__nedf2)
+NOT_HERE_UNTIL_AFTER_4_3(__nedf2vfp)
+NOT_HERE_UNTIL_AFTER_4_3(__negdi2)
+NOT_HERE_UNTIL_AFTER_4_3(__negvdi2)
+NOT_HERE_UNTIL_AFTER_4_3(__negvsi2)
+NOT_HERE_UNTIL_AFTER_4_3(__nesf2)
+NOT_HERE_UNTIL_AFTER_4_3(__nesf2vfp)
+NOT_HERE_UNTIL_AFTER_4_3(__paritydi2)
+NOT_HERE_UNTIL_AFTER_4_3(__paritysi2)
+NOT_HERE_UNTIL_AFTER_4_3(__popcountdi2)
+NOT_HERE_UNTIL_AFTER_4_3(__popcountsi2)
+NOT_HERE_UNTIL_AFTER_4_3(__powidf2)
+NOT_HERE_UNTIL_AFTER_4_3(__powisf2)
+NOT_HERE_UNTIL_AFTER_4_3(__subdf3)
+NOT_HERE_UNTIL_AFTER_4_3(__subdf3vfp)
+NOT_HERE_UNTIL_AFTER_4_3(__subsf3)
+NOT_HERE_UNTIL_AFTER_4_3(__subsf3vfp)
+NOT_HERE_UNTIL_AFTER_4_3(__subvdi3)
+NOT_HERE_UNTIL_AFTER_4_3(__subvsi3)
+NOT_HERE_UNTIL_AFTER_4_3(__truncdfsf2)
+NOT_HERE_UNTIL_AFTER_4_3(__truncdfsf2vfp)
+NOT_HERE_UNTIL_AFTER_4_3(__ucmpdi2)
+NOT_HERE_UNTIL_AFTER_4_3(__udivdi3)
+NOT_HERE_UNTIL_AFTER_4_3(__udivmoddi4)
+NOT_HERE_UNTIL_AFTER_4_3(__udivsi3)
+NOT_HERE_UNTIL_AFTER_4_3(__umoddi3)
+NOT_HERE_UNTIL_AFTER_4_3(__umodsi3)
+NOT_HERE_UNTIL_AFTER_4_3(__unorddf2)
+NOT_HERE_UNTIL_AFTER_4_3(__unorddf2vfp)
+NOT_HERE_UNTIL_AFTER_4_3(__unordsf2)
+NOT_HERE_UNTIL_AFTER_4_3(__unordsf2vfp)
+
+NOT_HERE_UNTIL_AFTER_4_3(__divmodsi4)
+NOT_HERE_UNTIL_AFTER_4_3(__udivmodsi4)
+#endif // __arm__ && __DYNAMIC__
+
+
+
+
+
#else /* !__APPLE__ */
extern int avoid_empty_file;
diff --git a/contrib/compiler-rt/lib/arm/adddf3vfp.S b/contrib/compiler-rt/lib/arm/adddf3vfp.S
index 5e705e3..cced1e0 100644
--- a/contrib/compiler-rt/lib/arm/adddf3vfp.S
+++ b/contrib/compiler-rt/lib/arm/adddf3vfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/addsf3vfp.S b/contrib/compiler-rt/lib/arm/addsf3vfp.S
index 36d509c..b747528 100644
--- a/contrib/compiler-rt/lib/arm/addsf3vfp.S
+++ b/contrib/compiler-rt/lib/arm/addsf3vfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/bswapdi2.S b/contrib/compiler-rt/lib/arm/bswapdi2.S
index d3ca33a..a0283e1 100644
--- a/contrib/compiler-rt/lib/arm/bswapdi2.S
+++ b/contrib/compiler-rt/lib/arm/bswapdi2.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/bswapsi2.S b/contrib/compiler-rt/lib/arm/bswapsi2.S
index 0a0c073..4c3af1f 100644
--- a/contrib/compiler-rt/lib/arm/bswapsi2.S
+++ b/contrib/compiler-rt/lib/arm/bswapsi2.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/comparesf2.S b/contrib/compiler-rt/lib/arm/comparesf2.S
index f21e0bcd..ee18203 100644
--- a/contrib/compiler-rt/lib/arm/comparesf2.S
+++ b/contrib/compiler-rt/lib/arm/comparesf2.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
diff --git a/contrib/compiler-rt/lib/arm/divdf3vfp.S b/contrib/compiler-rt/lib/arm/divdf3vfp.S
index e43baa3..74ef0ea 100644
--- a/contrib/compiler-rt/lib/arm/divdf3vfp.S
+++ b/contrib/compiler-rt/lib/arm/divdf3vfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/divmodsi4.S b/contrib/compiler-rt/lib/arm/divmodsi4.S
new file mode 100644
index 0000000..cec39a7
--- /dev/null
+++ b/contrib/compiler-rt/lib/arm/divmodsi4.S
@@ -0,0 +1,47 @@
+/*===-- divmodsi4.S - 32-bit signed integer divide and modulus ------------===//
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ *===----------------------------------------------------------------------===//
+ *
+ * This file implements the __divmodsi4 (32-bit signed integer divide and
+ * modulus) function for the ARM architecture. A naive digit-by-digit
+ * computation is employed for simplicity.
+ *
+ *===----------------------------------------------------------------------===*/
+
+#include "../assembly.h"
+
+#define ESTABLISH_FRAME \
+ push {r4-r7, lr} ;\
+ add r7, sp, #12
+#define CLEAR_FRAME_AND_RETURN \
+ pop {r4-r7, pc}
+
+.syntax unified
+.align 3
+DEFINE_COMPILERRT_FUNCTION(__divmodsi4)
+ ESTABLISH_FRAME
+// Set aside the sign of the quotient and modulus, and the address for the
+// modulus.
+ eor r4, r0, r1
+ mov r5, r0
+ mov r6, r2
+// Take the absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31).
+ eor ip, r0, r0, asr #31
+ eor lr, r1, r1, asr #31
+ sub r0, ip, r0, asr #31
+ sub r1, lr, r1, asr #31
+// Unsigned divmod:
+ bl SYMBOL_NAME(__udivmodsi4)
+// Apply the sign of quotient and modulus
+ ldr r1, [r6]
+ eor r0, r0, r4, asr #31
+ eor r1, r1, r5, asr #31
+ sub r0, r0, r4, asr #31
+ sub r1, r1, r5, asr #31
+ str r1, [r6]
+ CLEAR_FRAME_AND_RETURN
diff --git a/contrib/compiler-rt/lib/arm/divsf3vfp.S b/contrib/compiler-rt/lib/arm/divsf3vfp.S
index d96c930..9eefcf31e 100644
--- a/contrib/compiler-rt/lib/arm/divsf3vfp.S
+++ b/contrib/compiler-rt/lib/arm/divsf3vfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/divsi3.S b/contrib/compiler-rt/lib/arm/divsi3.S
new file mode 100644
index 0000000..00e6181
--- /dev/null
+++ b/contrib/compiler-rt/lib/arm/divsi3.S
@@ -0,0 +1,41 @@
+/*===-- divsi3.S - 32-bit signed integer divide ---------------------------===//
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ *===----------------------------------------------------------------------===//
+ *
+ * This file implements the __divsi3 (32-bit signed integer divide) function
+ * for the ARM architecture as a wrapper around the unsigned routine.
+ *
+ *===----------------------------------------------------------------------===*/
+
+#include "../assembly.h"
+
+#define ESTABLISH_FRAME \
+ push {r4, r7, lr} ;\
+ add r7, sp, #4
+#define CLEAR_FRAME_AND_RETURN \
+ pop {r4, r7, pc}
+
+.syntax unified
+.align 3
+// Ok, APCS and AAPCS agree on 32 bit args, so it's safe to use the same routine.
+DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_idiv, __divsi3)
+DEFINE_COMPILERRT_FUNCTION(__divsi3)
+ ESTABLISH_FRAME
+// Set aside the sign of the quotient.
+ eor r4, r0, r1
+// Take absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31).
+ eor r2, r0, r0, asr #31
+ eor r3, r1, r1, asr #31
+ sub r0, r2, r0, asr #31
+ sub r1, r3, r1, asr #31
+// abs(a) / abs(b)
+ bl SYMBOL_NAME(__udivsi3)
+// Apply sign of quotient to result and return.
+ eor r0, r0, r4, asr #31
+ sub r0, r0, r4, asr #31
+ CLEAR_FRAME_AND_RETURN
diff --git a/contrib/compiler-rt/lib/arm/eqdf2vfp.S b/contrib/compiler-rt/lib/arm/eqdf2vfp.S
index d4384ec..2998a76 100644
--- a/contrib/compiler-rt/lib/arm/eqdf2vfp.S
+++ b/contrib/compiler-rt/lib/arm/eqdf2vfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/eqsf2vfp.S b/contrib/compiler-rt/lib/arm/eqsf2vfp.S
index 07355a3..927566e 100644
--- a/contrib/compiler-rt/lib/arm/eqsf2vfp.S
+++ b/contrib/compiler-rt/lib/arm/eqsf2vfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/extendsfdf2vfp.S b/contrib/compiler-rt/lib/arm/extendsfdf2vfp.S
index 4343a7e..b1aa88e 100644
--- a/contrib/compiler-rt/lib/arm/extendsfdf2vfp.S
+++ b/contrib/compiler-rt/lib/arm/extendsfdf2vfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/fixdfsivfp.S b/contrib/compiler-rt/lib/arm/fixdfsivfp.S
index 30458cc..0285a17 100644
--- a/contrib/compiler-rt/lib/arm/fixdfsivfp.S
+++ b/contrib/compiler-rt/lib/arm/fixdfsivfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/fixsfsivfp.S b/contrib/compiler-rt/lib/arm/fixsfsivfp.S
index ce6f18e..d05ba74 100644
--- a/contrib/compiler-rt/lib/arm/fixsfsivfp.S
+++ b/contrib/compiler-rt/lib/arm/fixsfsivfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/fixunsdfsivfp.S b/contrib/compiler-rt/lib/arm/fixunsdfsivfp.S
index 7e766c0..ddb703c 100644
--- a/contrib/compiler-rt/lib/arm/fixunsdfsivfp.S
+++ b/contrib/compiler-rt/lib/arm/fixunsdfsivfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/fixunssfsivfp.S b/contrib/compiler-rt/lib/arm/fixunssfsivfp.S
index ba2344f..afbb64f 100644
--- a/contrib/compiler-rt/lib/arm/fixunssfsivfp.S
+++ b/contrib/compiler-rt/lib/arm/fixunssfsivfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/floatsidfvfp.S b/contrib/compiler-rt/lib/arm/floatsidfvfp.S
index 5ed4ace..fe3366a 100644
--- a/contrib/compiler-rt/lib/arm/floatsidfvfp.S
+++ b/contrib/compiler-rt/lib/arm/floatsidfvfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/floatsisfvfp.S b/contrib/compiler-rt/lib/arm/floatsisfvfp.S
index 0114c78..5b41610 100644
--- a/contrib/compiler-rt/lib/arm/floatsisfvfp.S
+++ b/contrib/compiler-rt/lib/arm/floatsisfvfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/floatunssidfvfp.S b/contrib/compiler-rt/lib/arm/floatunssidfvfp.S
index d1bfe3a..9b22a6f 100644
--- a/contrib/compiler-rt/lib/arm/floatunssidfvfp.S
+++ b/contrib/compiler-rt/lib/arm/floatunssidfvfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/floatunssisfvfp.S b/contrib/compiler-rt/lib/arm/floatunssisfvfp.S
index 0b73577..44d5e93 100644
--- a/contrib/compiler-rt/lib/arm/floatunssisfvfp.S
+++ b/contrib/compiler-rt/lib/arm/floatunssisfvfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/gedf2vfp.S b/contrib/compiler-rt/lib/arm/gedf2vfp.S
index 6ab856f..9993f52 100644
--- a/contrib/compiler-rt/lib/arm/gedf2vfp.S
+++ b/contrib/compiler-rt/lib/arm/gedf2vfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/gesf2vfp.S b/contrib/compiler-rt/lib/arm/gesf2vfp.S
index b00d821..9ce1682 100644
--- a/contrib/compiler-rt/lib/arm/gesf2vfp.S
+++ b/contrib/compiler-rt/lib/arm/gesf2vfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/gtdf2vfp.S b/contrib/compiler-rt/lib/arm/gtdf2vfp.S
index 65594c7..8a049c8 100644
--- a/contrib/compiler-rt/lib/arm/gtdf2vfp.S
+++ b/contrib/compiler-rt/lib/arm/gtdf2vfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/gtsf2vfp.S b/contrib/compiler-rt/lib/arm/gtsf2vfp.S
index 53ef2a0..1ffe1ec 100644
--- a/contrib/compiler-rt/lib/arm/gtsf2vfp.S
+++ b/contrib/compiler-rt/lib/arm/gtsf2vfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/ledf2vfp.S b/contrib/compiler-rt/lib/arm/ledf2vfp.S
index 327a7d5..a04d0f2 100644
--- a/contrib/compiler-rt/lib/arm/ledf2vfp.S
+++ b/contrib/compiler-rt/lib/arm/ledf2vfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/lesf2vfp.S b/contrib/compiler-rt/lib/arm/lesf2vfp.S
index b7e05da..3011200 100644
--- a/contrib/compiler-rt/lib/arm/lesf2vfp.S
+++ b/contrib/compiler-rt/lib/arm/lesf2vfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/ltdf2vfp.S b/contrib/compiler-rt/lib/arm/ltdf2vfp.S
index 55dfd80..87144a8 100644
--- a/contrib/compiler-rt/lib/arm/ltdf2vfp.S
+++ b/contrib/compiler-rt/lib/arm/ltdf2vfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/ltsf2vfp.S b/contrib/compiler-rt/lib/arm/ltsf2vfp.S
index 3816a71..ca06ae2 100644
--- a/contrib/compiler-rt/lib/arm/ltsf2vfp.S
+++ b/contrib/compiler-rt/lib/arm/ltsf2vfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/modsi3.S b/contrib/compiler-rt/lib/arm/modsi3.S
index 64a3afd..a4cd2ee 100644
--- a/contrib/compiler-rt/lib/arm/modsi3.S
+++ b/contrib/compiler-rt/lib/arm/modsi3.S
@@ -1,36 +1,39 @@
-//===-------- modsi3.S - Implement modsi3 ---------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
+/*===-- modsi3.S - 32-bit signed integer modulus --------------------------===//
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ *===----------------------------------------------------------------------===//
+ *
+ * This file implements the __modsi3 (32-bit signed integer modulus) function
+ * for the ARM architecture as a wrapper around the unsigned routine.
+ *
+ *===----------------------------------------------------------------------===*/
#include "../assembly.h"
-//
-// extern int32_t __modsi3(int32_t a, int32_t b);
-//
-// Returns the remainder when dividing two 32-bit signed integers.
-// Conceptually, the function is: { return a - (a / b) * b; }
-// But if you write that in C, llvm compiles it to a call to __modsi3...
-//
- .align 2
-DEFINE_COMPILERRT_FUNCTION(__modsi3)
- push {r4, r5, r7, lr}
- add r7, sp, #8 // set stack frame
- mov r5, r0 // save a
- mov r4, r1 // save b
- bl ___divsi3 // compute a/b
-#if __ARM_ARCH_7A__
- mls r0, r4, r0, r5 // mulitple result * b and subtract from a
-#else
- // before armv7, does not have "mls" instruction
- mul r3, r0, r4 // multiple result * b
- sub r0, r5, r3 // a - result
-#endif
- pop {r4, r5, r7, pc}
-
-
+#define ESTABLISH_FRAME \
+ push {r4, r7, lr} ;\
+ add r7, sp, #4
+#define CLEAR_FRAME_AND_RETURN \
+ pop {r4, r7, pc}
+.syntax unified
+.align 3
+DEFINE_COMPILERRT_FUNCTION(__modsi3)
+ ESTABLISH_FRAME
+ // Set aside the sign of the dividend.
+ mov r4, r0
+ // Take absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31).
+ eor r2, r0, r0, asr #31
+ eor r3, r1, r1, asr #31
+ sub r0, r2, r0, asr #31
+ sub r1, r3, r1, asr #31
+ // abs(a) % abs(b)
+ bl SYMBOL_NAME(__umodsi3)
+ // Apply sign of dividend to result and return.
+ eor r0, r0, r4, asr #31
+ sub r0, r0, r4, asr #31
+ CLEAR_FRAME_AND_RETURN
diff --git a/contrib/compiler-rt/lib/arm/muldf3vfp.S b/contrib/compiler-rt/lib/arm/muldf3vfp.S
index cb503d3..96bba06 100644
--- a/contrib/compiler-rt/lib/arm/muldf3vfp.S
+++ b/contrib/compiler-rt/lib/arm/muldf3vfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/mulsf3vfp.S b/contrib/compiler-rt/lib/arm/mulsf3vfp.S
index 49b4d1d..c56991d 100644
--- a/contrib/compiler-rt/lib/arm/mulsf3vfp.S
+++ b/contrib/compiler-rt/lib/arm/mulsf3vfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/nedf2vfp.S b/contrib/compiler-rt/lib/arm/nedf2vfp.S
index 813864e..a02b09c 100644
--- a/contrib/compiler-rt/lib/arm/nedf2vfp.S
+++ b/contrib/compiler-rt/lib/arm/nedf2vfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/negdf2vfp.S b/contrib/compiler-rt/lib/arm/negdf2vfp.S
index 80139754..100f4fd 100644
--- a/contrib/compiler-rt/lib/arm/negdf2vfp.S
+++ b/contrib/compiler-rt/lib/arm/negdf2vfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/negsf2vfp.S b/contrib/compiler-rt/lib/arm/negsf2vfp.S
index 243c086..f96c8ad 100644
--- a/contrib/compiler-rt/lib/arm/negsf2vfp.S
+++ b/contrib/compiler-rt/lib/arm/negsf2vfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/nesf2vfp.S b/contrib/compiler-rt/lib/arm/nesf2vfp.S
index d470afa..d620549 100644
--- a/contrib/compiler-rt/lib/arm/nesf2vfp.S
+++ b/contrib/compiler-rt/lib/arm/nesf2vfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/restore_vfp_d8_d15_regs.S b/contrib/compiler-rt/lib/arm/restore_vfp_d8_d15_regs.S
index 25404cd..7f441db 100644
--- a/contrib/compiler-rt/lib/arm/restore_vfp_d8_d15_regs.S
+++ b/contrib/compiler-rt/lib/arm/restore_vfp_d8_d15_regs.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/save_vfp_d8_d15_regs.S b/contrib/compiler-rt/lib/arm/save_vfp_d8_d15_regs.S
index 92de61b..fbd21ba 100644
--- a/contrib/compiler-rt/lib/arm/save_vfp_d8_d15_regs.S
+++ b/contrib/compiler-rt/lib/arm/save_vfp_d8_d15_regs.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/softfloat-alias.list b/contrib/compiler-rt/lib/arm/softfloat-alias.list
new file mode 100644
index 0000000..cc6a4b3c
--- /dev/null
+++ b/contrib/compiler-rt/lib/arm/softfloat-alias.list
@@ -0,0 +1,21 @@
+#
+# These are soft float functions which can be
+# aliased to the *vfp functions on arm processors
+# that support floating point instructions.
+#
+___adddf3vfp ___adddf3
+___addsf3vfp ___addsf3
+___divdf3vfp ___divdf3
+___divsf3vfp ___divsf3
+___extendsfdf2vfp ___extendsfdf2
+___fixdfsivfp ___fixdfsi
+___fixsfsivfp ___fixsfsi
+___floatsidfvfp ___floatsidf
+___floatsisfvfp ___floatsisf
+___muldf3vfp ___muldf3
+___mulsf3vfp ___mulsf3
+___subdf3vfp ___subdf3
+___subsf3vfp ___subsf3
+___truncdfsf2vfp ___truncdfsf2
+___floatunssidfvfp ___floatunsidf
+___floatunssisfvfp ___floatunsisf
diff --git a/contrib/compiler-rt/lib/arm/subdf3vfp.S b/contrib/compiler-rt/lib/arm/subdf3vfp.S
index 8841600..ff53b30 100644
--- a/contrib/compiler-rt/lib/arm/subdf3vfp.S
+++ b/contrib/compiler-rt/lib/arm/subdf3vfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/subsf3vfp.S b/contrib/compiler-rt/lib/arm/subsf3vfp.S
index 4ead9c23..238f3f0 100644
--- a/contrib/compiler-rt/lib/arm/subsf3vfp.S
+++ b/contrib/compiler-rt/lib/arm/subsf3vfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/switch16.S b/contrib/compiler-rt/lib/arm/switch16.S
index 05c7b98..e8f08c4 100644
--- a/contrib/compiler-rt/lib/arm/switch16.S
+++ b/contrib/compiler-rt/lib/arm/switch16.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/switch32.S b/contrib/compiler-rt/lib/arm/switch32.S
index a127cb7..7008fcc 100644
--- a/contrib/compiler-rt/lib/arm/switch32.S
+++ b/contrib/compiler-rt/lib/arm/switch32.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/switch8.S b/contrib/compiler-rt/lib/arm/switch8.S
index d05f6ac..e784b40 100644
--- a/contrib/compiler-rt/lib/arm/switch8.S
+++ b/contrib/compiler-rt/lib/arm/switch8.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/switchu8.S b/contrib/compiler-rt/lib/arm/switchu8.S
index faffddb..19bed2f 100644
--- a/contrib/compiler-rt/lib/arm/switchu8.S
+++ b/contrib/compiler-rt/lib/arm/switchu8.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/sync_synchronize.S b/contrib/compiler-rt/lib/arm/sync_synchronize.S
index 76fdab1..06dade9 100644
--- a/contrib/compiler-rt/lib/arm/sync_synchronize.S
+++ b/contrib/compiler-rt/lib/arm/sync_synchronize.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/truncdfsf2vfp.S b/contrib/compiler-rt/lib/arm/truncdfsf2vfp.S
index 5725e25..6e55c7f 100644
--- a/contrib/compiler-rt/lib/arm/truncdfsf2vfp.S
+++ b/contrib/compiler-rt/lib/arm/truncdfsf2vfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/udivmodsi4.S b/contrib/compiler-rt/lib/arm/udivmodsi4.S
new file mode 100644
index 0000000..d164a75
--- /dev/null
+++ b/contrib/compiler-rt/lib/arm/udivmodsi4.S
@@ -0,0 +1,80 @@
+/*===-- udivmodsi4.S - 32-bit unsigned integer divide and modulus ---------===//
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ *===----------------------------------------------------------------------===//
+ *
+ * This file implements the __udivmodsi4 (32-bit unsigned integer divide and
+ * modulus) function for the ARM architecture. A naive digit-by-digit
+ * computation is employed for simplicity.
+ *
+ *===----------------------------------------------------------------------===*/
+
+#include "../assembly.h"
+
+#define ESTABLISH_FRAME \
+ push {r4, r7, lr} ;\
+ add r7, sp, #4
+#define CLEAR_FRAME_AND_RETURN \
+ pop {r4, r7, pc}
+
+#define a r0
+#define b r1
+#define i r3
+#define r r4
+#define q ip
+#define one lr
+
+.syntax unified
+.align 3
+DEFINE_COMPILERRT_FUNCTION(__udivmodsi4)
+// We use a simple digit by digit algorithm; before we get into the actual
+// divide loop, we must calculate the left-shift amount necessary to align
+// the MSB of the divisor with that of the dividend (If this shift is
+// negative, then the result is zero, and we early out). We also conjure a
+// bit mask of 1 to use in constructing the quotient, and initialize the
+// quotient to zero.
+ ESTABLISH_FRAME
+ clz r4, a
+ tst b, b // detect divide-by-zero
+ clz r3, b
+ mov q, #0
+ beq LOCAL_LABEL(return) // return 0 if b is zero.
+ mov one, #1
+ subs i, r3, r4
+ blt LOCAL_LABEL(return) // return 0 if MSB(a) < MSB(b)
+
+LOCAL_LABEL(mainLoop):
+// This loop basically implements the following:
+//
+// do {
+// if (a >= b << i) {
+// a -= b << i;
+// q |= 1 << i;
+// if (a == 0) break;
+// }
+// } while (--i)
+//
+// Note that this does not perform the final iteration (i == 0); by doing it
+// this way, we can merge the two branches which is a substantial win for
+// such a tight loop on current ARM architectures.
+ subs r, a, b, lsl i
+ orrhs q, q,one, lsl i
+ movhs a, r
+ subsne i, i, #1
+ bhi LOCAL_LABEL(mainLoop)
+
+// Do the final test subtraction and update of quotient (i == 0), as it is
+// not performed in the main loop.
+ subs r, a, b
+ orrhs q, #1
+ movhs a, r
+
+LOCAL_LABEL(return):
+// Store the remainder, and move the quotient to r0, then return.
+ str a, [r2]
+ mov r0, q
+ CLEAR_FRAME_AND_RETURN
diff --git a/contrib/compiler-rt/lib/arm/udivsi3.S b/contrib/compiler-rt/lib/arm/udivsi3.S
new file mode 100644
index 0000000..6d89665
--- /dev/null
+++ b/contrib/compiler-rt/lib/arm/udivsi3.S
@@ -0,0 +1,80 @@
+/*===-- udivsi3.S - 32-bit unsigned integer divide ------------------------===//
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ *===----------------------------------------------------------------------===//
+ *
+ * This file implements the __udivsi3 (32-bit unsigned integer divide)
+ * function for the ARM architecture. A naive digit-by-digit computation is
+ * employed for simplicity.
+ *
+ *===----------------------------------------------------------------------===*/
+
+#include "../assembly.h"
+
+#define ESTABLISH_FRAME \
+ push {r7, lr} ;\
+ mov r7, sp
+#define CLEAR_FRAME_AND_RETURN \
+ pop {r7, pc}
+
+#define a r0
+#define b r1
+#define r r2
+#define i r3
+#define q ip
+#define one lr
+
+.syntax unified
+.align 3
+// Ok, APCS and AAPCS agree on 32 bit args, so it's safe to use the same routine.
+DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_uidiv, __udivsi3)
+DEFINE_COMPILERRT_FUNCTION(__udivsi3)
+// We use a simple digit by digit algorithm; before we get into the actual
+// divide loop, we must calculate the left-shift amount necessary to align
+// the MSB of the divisor with that of the dividend (If this shift is
+// negative, then the result is zero, and we early out). We also conjure a
+// bit mask of 1 to use in constructing the quotient, and initialize the
+// quotient to zero.
+ ESTABLISH_FRAME
+ clz r2, a
+ tst b, b // detect divide-by-zero
+ clz r3, b
+ mov q, #0
+ beq LOCAL_LABEL(return) // return 0 if b is zero.
+ mov one, #1
+ subs i, r3, r2
+ blt LOCAL_LABEL(return) // return 0 if MSB(a) < MSB(b)
+
+LOCAL_LABEL(mainLoop):
+// This loop basically implements the following:
+//
+// do {
+// if (a >= b << i) {
+// a -= b << i;
+// q |= 1 << i;
+// if (a == 0) break;
+// }
+// } while (--i)
+//
+// Note that this does not perform the final iteration (i == 0); by doing it
+// this way, we can merge the two branches which is a substantial win for
+// such a tight loop on current ARM architectures.
+ subs r, a, b, lsl i
+ orrhs q, q,one, lsl i
+ movhs a, r
+ subsne i, i, #1
+ bhi LOCAL_LABEL(mainLoop)
+
+// Do the final test subtraction and update of quotient (i == 0), as it is
+// not performed in the main loop.
+ subs r, a, b
+ orrhs q, #1
+
+LOCAL_LABEL(return):
+// Move the quotient to r0 and return.
+ mov r0, q
+ CLEAR_FRAME_AND_RETURN
diff --git a/contrib/compiler-rt/lib/arm/umodsi3.S b/contrib/compiler-rt/lib/arm/umodsi3.S
new file mode 100644
index 0000000..3a2ab2b
--- /dev/null
+++ b/contrib/compiler-rt/lib/arm/umodsi3.S
@@ -0,0 +1,58 @@
+/*===-- umodsi3.S - 32-bit unsigned integer modulus -----------------------===//
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ *===----------------------------------------------------------------------===//
+ *
+ * This file implements the __umodsi3 (32-bit unsigned integer modulus)
+ * function for the ARM architecture. A naive digit-by-digit computation is
+ * employed for simplicity.
+ *
+ *===----------------------------------------------------------------------===*/
+
+#include "../assembly.h"
+
+#define a r0
+#define b r1
+#define r r2
+#define i r3
+
+.syntax unified
+.align 3
+DEFINE_COMPILERRT_FUNCTION(__umodsi3)
+// We use a simple digit by digit algorithm; before we get into the actual
+// divide loop, we must calculate the left-shift amount necessary to align
+// the MSB of the divisor with that of the dividend.
+ clz r2, a
+ tst b, b // detect b == 0
+ clz r3, b
+ bxeq lr // return a if b == 0
+ subs i, r3, r2
+ bxlt lr // return a if MSB(a) < MSB(b)
+
+LOCAL_LABEL(mainLoop):
+// This loop basically implements the following:
+//
+// do {
+// if (a >= b << i) {
+// a -= b << i;
+// if (a == 0) break;
+// }
+// } while (--i)
+//
+// Note that this does not perform the final iteration (i == 0); by doing it
+// this way, we can merge the two branches which is a substantial win for
+// such a tight loop on current ARM architectures.
+ subs r, a, b, lsl i
+ movhs a, r
+ subsne i, i, #1
+ bhi LOCAL_LABEL(mainLoop)
+
+// Do the final test subtraction and update of remainder (i == 0), as it is
+// not performed in the main loop.
+ subs r, a, b
+ movhs a, r
+ bx lr
diff --git a/contrib/compiler-rt/lib/arm/unorddf2vfp.S b/contrib/compiler-rt/lib/arm/unorddf2vfp.S
index de00b07..9b52131 100644
--- a/contrib/compiler-rt/lib/arm/unorddf2vfp.S
+++ b/contrib/compiler-rt/lib/arm/unorddf2vfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/arm/unordsf2vfp.S b/contrib/compiler-rt/lib/arm/unordsf2vfp.S
index ab291a8..e486533 100644
--- a/contrib/compiler-rt/lib/arm/unordsf2vfp.S
+++ b/contrib/compiler-rt/lib/arm/unordsf2vfp.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/ashldi3.c b/contrib/compiler-rt/lib/ashldi3.c
index 993f71c..adce4e2 100644
--- a/contrib/compiler-rt/lib/ashldi3.c
+++ b/contrib/compiler-rt/lib/ashldi3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,6 +11,7 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
@@ -18,7 +19,9 @@
/* Precondition: 0 <= b < bits_in_dword */
-di_int
+ARM_EABI_FNALIAS(llsl, ashldi3);
+
+COMPILER_RT_ABI di_int
__ashldi3(di_int a, si_int b)
{
const int bits_in_word = (int)(sizeof(si_int) * CHAR_BIT);
diff --git a/contrib/compiler-rt/lib/ashlti3.c b/contrib/compiler-rt/lib/ashlti3.c
index 317de66..7042b53 100644
--- a/contrib/compiler-rt/lib/ashlti3.c
+++ b/contrib/compiler-rt/lib/ashlti3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/ashrdi3.c b/contrib/compiler-rt/lib/ashrdi3.c
index 8e27a11..03692a3 100644
--- a/contrib/compiler-rt/lib/ashrdi3.c
+++ b/contrib/compiler-rt/lib/ashrdi3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,6 +11,7 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
@@ -18,7 +19,9 @@
/* Precondition: 0 <= b < bits_in_dword */
-di_int
+ARM_EABI_FNALIAS(lasr, ashrdi3);
+
+COMPILER_RT_ABI di_int
__ashrdi3(di_int a, si_int b)
{
const int bits_in_word = (int)(sizeof(si_int) * CHAR_BIT);
diff --git a/contrib/compiler-rt/lib/ashrti3.c b/contrib/compiler-rt/lib/ashrti3.c
index 4eab247..4d16230 100644
--- a/contrib/compiler-rt/lib/ashrti3.c
+++ b/contrib/compiler-rt/lib/ashrti3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/assembly.h b/contrib/compiler-rt/lib/assembly.h
index c124e19..0ce83ac 100644
--- a/contrib/compiler-rt/lib/assembly.h
+++ b/contrib/compiler-rt/lib/assembly.h
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -22,33 +22,48 @@
#define SEPARATOR ;
#endif
-/* We can't use __USER_LABEL_PREFIX__ here, it isn't possible to concatenate the
- *values* of two macros. This is quite brittle, though. */
#if defined(__APPLE__)
-#define SYMBOL_NAME(name) _##name
+#define HIDDEN_DIRECTIVE .private_extern
+#define LOCAL_LABEL(name) L_##name
#else
-#define SYMBOL_NAME(name) name
+#define HIDDEN_DIRECTIVE .hidden
+#define LOCAL_LABEL(name) .L_##name
#endif
+#define GLUE2(a, b) a ## b
+#define GLUE(a, b) GLUE2(a, b)
+#define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name)
+
#ifdef VISIBILITY_HIDDEN
-#define DEFINE_COMPILERRT_FUNCTION(name) \
- .globl SYMBOL_NAME(name) SEPARATOR \
- .hidden SYMBOL_NAME(name) SEPARATOR \
+#define DEFINE_COMPILERRT_FUNCTION(name) \
+ .globl SYMBOL_NAME(name) SEPARATOR \
+ HIDDEN_DIRECTIVE SYMBOL_NAME(name) SEPARATOR \
SYMBOL_NAME(name):
#else
-#define DEFINE_COMPILERRT_FUNCTION(name) \
- .globl SYMBOL_NAME(name) SEPARATOR \
+#define DEFINE_COMPILERRT_FUNCTION(name) \
+ .globl SYMBOL_NAME(name) SEPARATOR \
SYMBOL_NAME(name):
#endif
-#define DEFINE_COMPILERRT_PRIVATE_FUNCTION(name) \
- .globl SYMBOL_NAME(name) SEPARATOR \
- .hidden SYMBOL_NAME(name) SEPARATOR \
+#define DEFINE_COMPILERRT_PRIVATE_FUNCTION(name) \
+ .globl SYMBOL_NAME(name) SEPARATOR \
+ HIDDEN_DIRECTIVE SYMBOL_NAME(name) SEPARATOR \
SYMBOL_NAME(name):
#define DEFINE_COMPILERRT_PRIVATE_FUNCTION_UNMANGLED(name) \
- .globl name SEPARATOR \
- .hidden name SEPARATOR \
+ .globl name SEPARATOR \
+ HIDDEN_DIRECTIVE name SEPARATOR \
name:
+#define DEFINE_COMPILERRT_FUNCTION_ALIAS(name, target) \
+ .globl SYMBOL_NAME(name) SEPARATOR \
+ .set SYMBOL_NAME(name), SYMBOL_NAME(target) SEPARATOR
+
+#if defined (__ARM_EABI__)
+# define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name) \
+ DEFINE_COMPILERRT_FUNCTION_ALIAS(aeabi_name, name)
+#else
+# define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name)
+#endif
+
#endif /* COMPILERRT_ASSEMBLY_H */
diff --git a/contrib/compiler-rt/lib/clear_cache.c b/contrib/compiler-rt/lib/clear_cache.c
index 43db37a..7b59a7f 100644
--- a/contrib/compiler-rt/lib/clear_cache.c
+++ b/contrib/compiler-rt/lib/clear_cache.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*/
diff --git a/contrib/compiler-rt/lib/clzdi2.c b/contrib/compiler-rt/lib/clzdi2.c
index ea95396..c281945 100644
--- a/contrib/compiler-rt/lib/clzdi2.c
+++ b/contrib/compiler-rt/lib/clzdi2.c
@@ -1,9 +1,9 @@
/* ===-- clzdi2.c - Implement __clzdi2 -------------------------------------===
*
- * The LLVM Compiler Infrastructure
+ * The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,6 +11,7 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
@@ -18,7 +19,7 @@
/* Precondition: a != 0 */
-si_int
+COMPILER_RT_ABI si_int
__clzdi2(di_int a)
{
dwords x;
diff --git a/contrib/compiler-rt/lib/clzsi2.c b/contrib/compiler-rt/lib/clzsi2.c
index 7e14af2..d0a6aea 100644
--- a/contrib/compiler-rt/lib/clzsi2.c
+++ b/contrib/compiler-rt/lib/clzsi2.c
@@ -1,9 +1,9 @@
/* ===-- clzsi2.c - Implement __clzsi2 -------------------------------------===
*
- * The LLVM Compiler Infrastructure
+ * The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,6 +11,7 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
@@ -18,7 +19,7 @@
/* Precondition: a != 0 */
-si_int
+COMPILER_RT_ABI si_int
__clzsi2(si_int a)
{
su_int x = (su_int)a;
diff --git a/contrib/compiler-rt/lib/clzti2.c b/contrib/compiler-rt/lib/clzti2.c
index 805688f..7a650eb 100644
--- a/contrib/compiler-rt/lib/clzti2.c
+++ b/contrib/compiler-rt/lib/clzti2.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/cmpdi2.c b/contrib/compiler-rt/lib/cmpdi2.c
index 0b87352..999c3d2 100644
--- a/contrib/compiler-rt/lib/cmpdi2.c
+++ b/contrib/compiler-rt/lib/cmpdi2.c
@@ -2,24 +2,25 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
- *
+ *
* This file implements __cmpdi2 for the compiler_rt library.
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
-/* Returns: if (a < b) returns 0
+/* Returns: if (a < b) returns 0
* if (a == b) returns 1
* if (a > b) returns 2
*/
-si_int
+COMPILER_RT_ABI si_int
__cmpdi2(di_int a, di_int b)
{
dwords x;
diff --git a/contrib/compiler-rt/lib/cmpti2.c b/contrib/compiler-rt/lib/cmpti2.c
index 90b3b75..b156fce 100644
--- a/contrib/compiler-rt/lib/cmpti2.c
+++ b/contrib/compiler-rt/lib/cmpti2.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/comparedf2.c b/contrib/compiler-rt/lib/comparedf2.c
index 5c5ee9d..fe35fd8 100644
--- a/contrib/compiler-rt/lib/comparedf2.c
+++ b/contrib/compiler-rt/lib/comparedf2.c
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
diff --git a/contrib/compiler-rt/lib/comparesf2.c b/contrib/compiler-rt/lib/comparesf2.c
index fd05724..3f2e358 100644
--- a/contrib/compiler-rt/lib/comparesf2.c
+++ b/contrib/compiler-rt/lib/comparesf2.c
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
diff --git a/contrib/compiler-rt/lib/ctzdi2.c b/contrib/compiler-rt/lib/ctzdi2.c
index b49f2c7..b3d37d0 100644
--- a/contrib/compiler-rt/lib/ctzdi2.c
+++ b/contrib/compiler-rt/lib/ctzdi2.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,6 +11,7 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
@@ -18,7 +19,7 @@
/* Precondition: a != 0 */
-si_int
+COMPILER_RT_ABI si_int
__ctzdi2(di_int a)
{
dwords x;
diff --git a/contrib/compiler-rt/lib/ctzsi2.c b/contrib/compiler-rt/lib/ctzsi2.c
index 30d34c8..2ff0e5d 100644
--- a/contrib/compiler-rt/lib/ctzsi2.c
+++ b/contrib/compiler-rt/lib/ctzsi2.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,6 +11,7 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
@@ -18,7 +19,7 @@
/* Precondition: a != 0 */
-si_int
+COMPILER_RT_ABI si_int
__ctzsi2(si_int a)
{
su_int x = (su_int)a;
diff --git a/contrib/compiler-rt/lib/ctzti2.c b/contrib/compiler-rt/lib/ctzti2.c
index f2d41fe..1c9508f 100644
--- a/contrib/compiler-rt/lib/ctzti2.c
+++ b/contrib/compiler-rt/lib/ctzti2.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/divdc3.c b/contrib/compiler-rt/lib/divdc3.c
index c96aefd..5f63298 100644
--- a/contrib/compiler-rt/lib/divdc3.c
+++ b/contrib/compiler-rt/lib/divdc3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/divdf3.c b/contrib/compiler-rt/lib/divdf3.c
index 21b8f09..925abd5 100644
--- a/contrib/compiler-rt/lib/divdf3.c
+++ b/contrib/compiler-rt/lib/divdf3.c
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
@@ -15,10 +15,13 @@
// underflow with correct rounding.
//
//===----------------------------------------------------------------------===//
+#include "abi.h"
#define DOUBLE_PRECISION
#include "fp_lib.h"
+ARM_EABI_FNALIAS(ddiv, divdf3);
+
fp_t __divdf3(fp_t a, fp_t b) {
const unsigned int aExponent = toRep(a) >> significandBits & maxExponent;
diff --git a/contrib/compiler-rt/lib/divdi3.c b/contrib/compiler-rt/lib/divdi3.c
index fccfb8b..d62df56 100644
--- a/contrib/compiler-rt/lib/divdi3.c
+++ b/contrib/compiler-rt/lib/divdi3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,14 +11,15 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
-du_int __udivmoddi4(du_int a, du_int b, du_int* rem);
+du_int COMPILER_RT_ABI __udivmoddi4(du_int a, du_int b, du_int* rem);
/* Returns: a / b */
-di_int
+COMPILER_RT_ABI di_int
__divdi3(di_int a, di_int b)
{
const int bits_in_dword_m1 = (int)(sizeof(di_int) * CHAR_BIT) - 1;
diff --git a/contrib/compiler-rt/lib/divmoddi4.c b/contrib/compiler-rt/lib/divmoddi4.c
new file mode 100644
index 0000000..d3ca745
--- /dev/null
+++ b/contrib/compiler-rt/lib/divmoddi4.c
@@ -0,0 +1,30 @@
+/*===-- divmoddi4.c - Implement __divmoddi4 --------------------------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ *
+ * This file implements __divmoddi4 for the compiler_rt library.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+#include "abi.h"
+
+#include "int_lib.h"
+
+extern COMPILER_RT_ABI di_int __divdi3(di_int a, di_int b);
+
+ARM_EABI_FNALIAS(ldivmod, divmoddi4);
+
+/* Returns: a / b, *rem = a % b */
+
+COMPILER_RT_ABI di_int
+__divmoddi4(di_int a, di_int b, di_int* rem)
+{
+ di_int d = __divdi3(a,b);
+ *rem = a - (d*b);
+ return d;
+}
diff --git a/contrib/compiler-rt/lib/divmodsi4.c b/contrib/compiler-rt/lib/divmodsi4.c
new file mode 100644
index 0000000..4dc1978
--- /dev/null
+++ b/contrib/compiler-rt/lib/divmodsi4.c
@@ -0,0 +1,31 @@
+/*===-- divmodsi4.c - Implement __divmodsi4 --------------------------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ *
+ * This file implements __divmodsi4 for the compiler_rt library.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+#include "abi.h"
+
+#include "int_lib.h"
+
+extern COMPILER_RT_ABI si_int __divsi3(si_int a, si_int b);
+
+
+/* Returns: a / b, *rem = a % b */
+
+COMPILER_RT_ABI si_int
+__divmodsi4(si_int a, si_int b, si_int* rem)
+{
+ si_int d = __divsi3(a,b);
+ *rem = a - (d*b);
+ return d;
+}
+
+
diff --git a/contrib/compiler-rt/lib/divsc3.c b/contrib/compiler-rt/lib/divsc3.c
index c38c863..a05f429 100644
--- a/contrib/compiler-rt/lib/divsc3.c
+++ b/contrib/compiler-rt/lib/divsc3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/divsf3.c b/contrib/compiler-rt/lib/divsf3.c
index 03b7311..b733307 100644
--- a/contrib/compiler-rt/lib/divsf3.c
+++ b/contrib/compiler-rt/lib/divsf3.c
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
@@ -15,10 +15,13 @@
// underflow with correct rounding.
//
//===----------------------------------------------------------------------===//
+#include "abi.h"
#define SINGLE_PRECISION
#include "fp_lib.h"
+ARM_EABI_FNALIAS(fdiv, divsf3);
+
fp_t __divsf3(fp_t a, fp_t b) {
const unsigned int aExponent = toRep(a) >> significandBits & maxExponent;
diff --git a/contrib/compiler-rt/lib/divsi3.c b/contrib/compiler-rt/lib/divsi3.c
index 0eff6ef..01ef274 100644
--- a/contrib/compiler-rt/lib/divsi3.c
+++ b/contrib/compiler-rt/lib/divsi3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,14 +11,17 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
-su_int __udivsi3(su_int n, su_int d);
+su_int COMPILER_RT_ABI __udivsi3(su_int n, su_int d);
/* Returns: a / b */
-si_int
+ARM_EABI_FNALIAS(idiv, divsi3);
+
+COMPILER_RT_ABI si_int
__divsi3(si_int a, si_int b)
{
const int bits_in_word_m1 = (int)(sizeof(si_int) * CHAR_BIT) - 1;
diff --git a/contrib/compiler-rt/lib/divti3.c b/contrib/compiler-rt/lib/divti3.c
index c752f6c..4ec3fa3 100644
--- a/contrib/compiler-rt/lib/divti3.c
+++ b/contrib/compiler-rt/lib/divti3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/divxc3.c b/contrib/compiler-rt/lib/divxc3.c
index 03357ae..f054d40 100644
--- a/contrib/compiler-rt/lib/divxc3.c
+++ b/contrib/compiler-rt/lib/divxc3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/enable_execute_stack.c b/contrib/compiler-rt/lib/enable_execute_stack.c
index 193e7db..7ab8e8d 100644
--- a/contrib/compiler-rt/lib/enable_execute_stack.c
+++ b/contrib/compiler-rt/lib/enable_execute_stack.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*/
diff --git a/contrib/compiler-rt/lib/endianness.h b/contrib/compiler-rt/lib/endianness.h
index 6d2587d..9b7e7c1 100644
--- a/contrib/compiler-rt/lib/endianness.h
+++ b/contrib/compiler-rt/lib/endianness.h
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/eprintf.c b/contrib/compiler-rt/lib/eprintf.c
index 786fe6a..7c79174 100644
--- a/contrib/compiler-rt/lib/eprintf.c
+++ b/contrib/compiler-rt/lib/eprintf.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*/
diff --git a/contrib/compiler-rt/lib/extendsfdf2.c b/contrib/compiler-rt/lib/extendsfdf2.c
index 025eb95..c0b628d 100644
--- a/contrib/compiler-rt/lib/extendsfdf2.c
+++ b/contrib/compiler-rt/lib/extendsfdf2.c
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
@@ -41,6 +41,8 @@
#include <stdint.h>
#include <limits.h>
+#include "abi.h"
+
typedef float src_t;
typedef uint32_t src_rep_t;
#define SRC_REP_C UINT32_C
@@ -67,6 +69,8 @@ static inline dst_t dstFromRep(dst_rep_t x) {
// End helper routines. Conversion implementation follows.
+ARM_EABI_FNALIAS(f2d, extendsfdf2);
+
dst_t __extendsfdf2(src_t a) {
// Various constants whose values follow from the type parameters.
diff --git a/contrib/compiler-rt/lib/ffsdi2.c b/contrib/compiler-rt/lib/ffsdi2.c
index 8c03d19..89f1b7b 100644
--- a/contrib/compiler-rt/lib/ffsdi2.c
+++ b/contrib/compiler-rt/lib/ffsdi2.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,6 +11,7 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
@@ -18,7 +19,7 @@
* the value zero if a is zero. The least significant bit is index one.
*/
-si_int
+COMPILER_RT_ABI si_int
__ffsdi2(di_int a)
{
dwords x;
diff --git a/contrib/compiler-rt/lib/ffsti2.c b/contrib/compiler-rt/lib/ffsti2.c
index 0139eb1..948c696 100644
--- a/contrib/compiler-rt/lib/ffsti2.c
+++ b/contrib/compiler-rt/lib/ffsti2.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/fixdfdi.c b/contrib/compiler-rt/lib/fixdfdi.c
index 3d3116c..85a456d 100644
--- a/contrib/compiler-rt/lib/fixdfdi.c
+++ b/contrib/compiler-rt/lib/fixdfdi.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,6 +11,7 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
@@ -23,6 +24,8 @@
/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
+ARM_EABI_FNALIAS(d2lz, fixdfdi);
+
di_int
__fixdfdi(double a)
{
diff --git a/contrib/compiler-rt/lib/fixdfsi.c b/contrib/compiler-rt/lib/fixdfsi.c
index 7d17aed..fbcf147 100644
--- a/contrib/compiler-rt/lib/fixdfsi.c
+++ b/contrib/compiler-rt/lib/fixdfsi.c
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
@@ -12,10 +12,15 @@
// conversion is undefined for out of range values in the C standard.
//
//===----------------------------------------------------------------------===//
+#include "abi.h"
#define DOUBLE_PRECISION
#include "fp_lib.h"
+#include "int_lib.h"
+
+ARM_EABI_FNALIAS(d2iz, fixdfsi);
+
int __fixdfsi(fp_t a) {
// Break a into sign, exponent, significand
diff --git a/contrib/compiler-rt/lib/fixdfti.c b/contrib/compiler-rt/lib/fixdfti.c
index 359b84e..4140d14 100644
--- a/contrib/compiler-rt/lib/fixdfti.c
+++ b/contrib/compiler-rt/lib/fixdfti.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/fixsfdi.c b/contrib/compiler-rt/lib/fixsfdi.c
index 08f1524..d80e33e 100644
--- a/contrib/compiler-rt/lib/fixsfdi.c
+++ b/contrib/compiler-rt/lib/fixsfdi.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,6 +11,7 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
@@ -23,7 +24,9 @@
/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
-di_int
+ARM_EABI_FNALIAS(d2lz, fixsfdi);
+
+COMPILER_RT_ABI di_int
__fixsfdi(float a)
{
float_bits fb;
diff --git a/contrib/compiler-rt/lib/fixsfsi.c b/contrib/compiler-rt/lib/fixsfsi.c
index ff79377..67749a5 100644
--- a/contrib/compiler-rt/lib/fixsfsi.c
+++ b/contrib/compiler-rt/lib/fixsfsi.c
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
@@ -12,12 +12,15 @@
// conversion is undefined for out of range values in the C standard.
//
//===----------------------------------------------------------------------===//
+#include "abi.h"
#define SINGLE_PRECISION
#include "fp_lib.h"
-int __fixsfsi(fp_t a) {
-
+ARM_EABI_FNALIAS(f2iz, fixsfsi);
+
+COMPILER_RT_ABI int
+__fixsfsi(fp_t a) {
// Break a into sign, exponent, significand
const rep_t aRep = toRep(a);
const rep_t aAbs = aRep & absMask;
diff --git a/contrib/compiler-rt/lib/fixsfti.c b/contrib/compiler-rt/lib/fixsfti.c
index 95992fe..c64e5ae 100644
--- a/contrib/compiler-rt/lib/fixsfti.c
+++ b/contrib/compiler-rt/lib/fixsfti.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/fixunsdfdi.c b/contrib/compiler-rt/lib/fixunsdfdi.c
index bdcee13..d80b84a 100644
--- a/contrib/compiler-rt/lib/fixunsdfdi.c
+++ b/contrib/compiler-rt/lib/fixunsdfdi.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,6 +11,7 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
@@ -26,7 +27,9 @@
/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
-du_int
+ARM_EABI_FNALIAS(d2ulz, fixunsdfdi);
+
+COMPILER_RT_ABI du_int
__fixunsdfdi(double a)
{
double_bits fb;
diff --git a/contrib/compiler-rt/lib/fixunsdfsi.c b/contrib/compiler-rt/lib/fixunsdfsi.c
index a0cba79..ecdfb5d 100644
--- a/contrib/compiler-rt/lib/fixunsdfsi.c
+++ b/contrib/compiler-rt/lib/fixunsdfsi.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,6 +11,7 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
@@ -26,7 +27,9 @@
/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
-su_int
+ARM_EABI_FNALIAS(d2uiz, fixunsdfsi);
+
+COMPILER_RT_ABI su_int
__fixunsdfsi(double a)
{
double_bits fb;
diff --git a/contrib/compiler-rt/lib/fixunsdfti.c b/contrib/compiler-rt/lib/fixunsdfti.c
index c1cd72d..524a207 100644
--- a/contrib/compiler-rt/lib/fixunsdfti.c
+++ b/contrib/compiler-rt/lib/fixunsdfti.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/fixunssfdi.c b/contrib/compiler-rt/lib/fixunssfdi.c
index 3837bd8..1506420 100644
--- a/contrib/compiler-rt/lib/fixunssfdi.c
+++ b/contrib/compiler-rt/lib/fixunssfdi.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,9 +11,9 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
-
/* Returns: convert a to a unsigned long long, rounding toward zero.
* Negative values all become zero.
*/
@@ -26,7 +26,9 @@
/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
-du_int
+ARM_EABI_FNALIAS(f2ulz, fixunssfdi);
+
+COMPILER_RT_ABI du_int
__fixunssfdi(float a)
{
float_bits fb;
diff --git a/contrib/compiler-rt/lib/fixunssfsi.c b/contrib/compiler-rt/lib/fixunssfsi.c
index a001cd4..dbaa511 100644
--- a/contrib/compiler-rt/lib/fixunssfsi.c
+++ b/contrib/compiler-rt/lib/fixunssfsi.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,6 +11,7 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
@@ -26,7 +27,9 @@
/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
-su_int
+ARM_EABI_FNALIAS(f2uiz, fixunssfsi);
+
+COMPILER_RT_ABI su_int
__fixunssfsi(float a)
{
float_bits fb;
diff --git a/contrib/compiler-rt/lib/fixunssfti.c b/contrib/compiler-rt/lib/fixunssfti.c
index 20b7e76..b807910 100644
--- a/contrib/compiler-rt/lib/fixunssfti.c
+++ b/contrib/compiler-rt/lib/fixunssfti.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/fixunsxfdi.c b/contrib/compiler-rt/lib/fixunsxfdi.c
index 872727b..6c817d8e 100644
--- a/contrib/compiler-rt/lib/fixunsxfdi.c
+++ b/contrib/compiler-rt/lib/fixunsxfdi.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/fixunsxfsi.c b/contrib/compiler-rt/lib/fixunsxfsi.c
index c9a607a..b9da86c 100644
--- a/contrib/compiler-rt/lib/fixunsxfsi.c
+++ b/contrib/compiler-rt/lib/fixunsxfsi.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/fixunsxfti.c b/contrib/compiler-rt/lib/fixunsxfti.c
index d0bd512..f0e16db 100644
--- a/contrib/compiler-rt/lib/fixunsxfti.c
+++ b/contrib/compiler-rt/lib/fixunsxfti.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/fixxfdi.c b/contrib/compiler-rt/lib/fixxfdi.c
index de6f818..9592ce4 100644
--- a/contrib/compiler-rt/lib/fixxfdi.c
+++ b/contrib/compiler-rt/lib/fixxfdi.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/fixxfti.c b/contrib/compiler-rt/lib/fixxfti.c
index c224801..1022770 100644
--- a/contrib/compiler-rt/lib/fixxfti.c
+++ b/contrib/compiler-rt/lib/fixxfti.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/floatdidf.c b/contrib/compiler-rt/lib/floatdidf.c
index a0f501b..5ba9526 100644
--- a/contrib/compiler-rt/lib/floatdidf.c
+++ b/contrib/compiler-rt/lib/floatdidf.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
*===----------------------------------------------------------------------===
*
@@ -11,6 +11,7 @@
*
*===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
#include <float.h>
@@ -23,13 +24,15 @@
/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
+ARM_EABI_FNALIAS(l2d, floatdidf);
+
#ifndef __SOFT_FP__
/* Support for systems that have hardware floating-point; we'll set the inexact flag
* as a side-effect of this computation.
*/
#include <stdint.h>
-double
+COMPILER_RT_ABI double
__floatdidf(di_int a)
{
static const double twop52 = 0x1.0p52;
@@ -49,7 +52,7 @@ __floatdidf(di_int a)
* set, and we don't want to code-gen to an unknown soft-float implementation.
*/
-double
+COMPILER_RT_ABI double
__floatdidf(di_int a)
{
if (a == 0)
diff --git a/contrib/compiler-rt/lib/floatdisf.c b/contrib/compiler-rt/lib/floatdisf.c
index 1925f15..4dc13ca 100644
--- a/contrib/compiler-rt/lib/floatdisf.c
+++ b/contrib/compiler-rt/lib/floatdisf.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
*===----------------------------------------------------------------------===
*
@@ -12,7 +12,7 @@
*===----------------------------------------------------------------------===
*/
-#include "int_lib.h"
+#include "abi.h"
#include <float.h>
/* Returns: convert a to a float, rounding toward even.*/
@@ -23,7 +23,11 @@
/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
-float
+#include "int_lib.h"
+
+ARM_EABI_FNALIAS(l2f, floatdisf);
+
+COMPILER_RT_ABI float
__floatdisf(di_int a)
{
if (a == 0)
diff --git a/contrib/compiler-rt/lib/floatdixf.c b/contrib/compiler-rt/lib/floatdixf.c
index bfda367..ebf62db 100644
--- a/contrib/compiler-rt/lib/floatdixf.c
+++ b/contrib/compiler-rt/lib/floatdixf.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/floatsidf.c b/contrib/compiler-rt/lib/floatsidf.c
index a13ab8f..7227335 100644
--- a/contrib/compiler-rt/lib/floatsidf.c
+++ b/contrib/compiler-rt/lib/floatsidf.c
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
@@ -12,10 +12,15 @@
// mode.
//
//===----------------------------------------------------------------------===//
+#include "abi.h"
#define DOUBLE_PRECISION
#include "fp_lib.h"
+#include "int_lib.h"
+
+ARM_EABI_FNALIAS(i2d, floatsidf);
+
fp_t __floatsidf(int a) {
const int aWidth = sizeof a * CHAR_BIT;
diff --git a/contrib/compiler-rt/lib/floatsisf.c b/contrib/compiler-rt/lib/floatsisf.c
index 4a62975..e5250ff 100644
--- a/contrib/compiler-rt/lib/floatsisf.c
+++ b/contrib/compiler-rt/lib/floatsisf.c
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
@@ -12,10 +12,15 @@
// mode.
//
//===----------------------------------------------------------------------===//
+#include "abi.h"
#define SINGLE_PRECISION
#include "fp_lib.h"
+#include "int_lib.h"
+
+ARM_EABI_FNALIAS(i2f, floatsisf);
+
fp_t __floatsisf(int a) {
const int aWidth = sizeof a * CHAR_BIT;
diff --git a/contrib/compiler-rt/lib/floattidf.c b/contrib/compiler-rt/lib/floattidf.c
index 274f585..f61844d 100644
--- a/contrib/compiler-rt/lib/floattidf.c
+++ b/contrib/compiler-rt/lib/floattidf.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/floattisf.c b/contrib/compiler-rt/lib/floattisf.c
index 72f3748..7eb761d 100644
--- a/contrib/compiler-rt/lib/floattisf.c
+++ b/contrib/compiler-rt/lib/floattisf.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/floattixf.c b/contrib/compiler-rt/lib/floattixf.c
index 77d9060..e4bcb5f 100644
--- a/contrib/compiler-rt/lib/floattixf.c
+++ b/contrib/compiler-rt/lib/floattixf.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/floatundidf.c b/contrib/compiler-rt/lib/floatundidf.c
index 1f304c5..e74e9d8 100644
--- a/contrib/compiler-rt/lib/floatundidf.c
+++ b/contrib/compiler-rt/lib/floatundidf.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -12,7 +12,7 @@
* ===----------------------------------------------------------------------===
*/
-#include "int_lib.h"
+#include "abi.h"
#include <float.h>
/* Returns: convert a to a double, rounding toward even. */
@@ -23,6 +23,10 @@
/* seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm */
+#include "int_lib.h"
+
+ARM_EABI_FNALIAS(ul2d, floatundidf);
+
#ifndef __SOFT_FP__
/* Support for systems that have hardware floating-point; we'll set the inexact flag
* as a side-effect of this computation.
@@ -30,7 +34,7 @@
#include <stdint.h>
-double
+COMPILER_RT_ABI double
__floatundidf(du_int a)
{
static const double twop52 = 0x1.0p52;
@@ -52,7 +56,7 @@ __floatundidf(du_int a)
* set, and we don't want to code-gen to an unknown soft-float implementation.
*/
-double
+COMPILER_RT_ABI double
__floatundidf(du_int a)
{
if (a == 0)
diff --git a/contrib/compiler-rt/lib/floatundisf.c b/contrib/compiler-rt/lib/floatundisf.c
index 79b4b82..eea45a7 100644
--- a/contrib/compiler-rt/lib/floatundisf.c
+++ b/contrib/compiler-rt/lib/floatundisf.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -12,7 +12,7 @@
*===----------------------------------------------------------------------===
*/
-#include "int_lib.h"
+#include "abi.h"
#include <float.h>
/* Returns: convert a to a float, rounding toward even. */
@@ -23,7 +23,11 @@
/* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
-float
+#include "int_lib.h"
+
+ARM_EABI_FNALIAS(ul2f, floatundisf);
+
+COMPILER_RT_ABI float
__floatundisf(du_int a)
{
if (a == 0)
diff --git a/contrib/compiler-rt/lib/floatundixf.c b/contrib/compiler-rt/lib/floatundixf.c
index bc9582f..64f7662 100644
--- a/contrib/compiler-rt/lib/floatundixf.c
+++ b/contrib/compiler-rt/lib/floatundixf.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/floatunsidf.c b/contrib/compiler-rt/lib/floatunsidf.c
index 05242c1..3756299 100644
--- a/contrib/compiler-rt/lib/floatunsidf.c
+++ b/contrib/compiler-rt/lib/floatunsidf.c
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
@@ -12,10 +12,15 @@
// mode.
//
//===----------------------------------------------------------------------===//
+#include "abi.h"
#define DOUBLE_PRECISION
#include "fp_lib.h"
+#include "int_lib.h"
+
+ARM_EABI_FNALIAS(ui2d, floatunsidf);
+
fp_t __floatunsidf(unsigned int a) {
const int aWidth = sizeof a * CHAR_BIT;
diff --git a/contrib/compiler-rt/lib/floatunsisf.c b/contrib/compiler-rt/lib/floatunsisf.c
index 31c0644..14ef103 100644
--- a/contrib/compiler-rt/lib/floatunsisf.c
+++ b/contrib/compiler-rt/lib/floatunsisf.c
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
@@ -12,10 +12,15 @@
// mode.
//
//===----------------------------------------------------------------------===//
+#include "abi.h"
#define SINGLE_PRECISION
#include "fp_lib.h"
+#include "int_lib.h"
+
+ARM_EABI_FNALIAS(ui2f, floatunsisf);
+
fp_t __floatunsisf(unsigned int a) {
const int aWidth = sizeof a * CHAR_BIT;
diff --git a/contrib/compiler-rt/lib/floatuntidf.c b/contrib/compiler-rt/lib/floatuntidf.c
index 51d8b28..bab7483 100644
--- a/contrib/compiler-rt/lib/floatuntidf.c
+++ b/contrib/compiler-rt/lib/floatuntidf.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/floatuntisf.c b/contrib/compiler-rt/lib/floatuntisf.c
index 328f39b..0ab6d7e 100644
--- a/contrib/compiler-rt/lib/floatuntisf.c
+++ b/contrib/compiler-rt/lib/floatuntisf.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/floatuntixf.c b/contrib/compiler-rt/lib/floatuntixf.c
index e82d0c1..a84709a 100644
--- a/contrib/compiler-rt/lib/floatuntixf.c
+++ b/contrib/compiler-rt/lib/floatuntixf.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/fp_lib.h b/contrib/compiler-rt/lib/fp_lib.h
index eac670d..6c9455a 100644
--- a/contrib/compiler-rt/lib/fp_lib.h
+++ b/contrib/compiler-rt/lib/fp_lib.h
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
diff --git a/contrib/compiler-rt/lib/gcc_personality_v0.c b/contrib/compiler-rt/lib/gcc_personality_v0.c
index 5940190..c840eef 100644
--- a/contrib/compiler-rt/lib/gcc_personality_v0.c
+++ b/contrib/compiler-rt/lib/gcc_personality_v0.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/i386/ashldi3.S b/contrib/compiler-rt/lib/i386/ashldi3.S
index af6f98b..5488ad6 100644
--- a/contrib/compiler-rt/lib/i386/ashldi3.S
+++ b/contrib/compiler-rt/lib/i386/ashldi3.S
@@ -1,5 +1,5 @@
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
#include "../assembly.h"
diff --git a/contrib/compiler-rt/lib/i386/ashrdi3.S b/contrib/compiler-rt/lib/i386/ashrdi3.S
index 346f9b1..b1445dd 100644
--- a/contrib/compiler-rt/lib/i386/ashrdi3.S
+++ b/contrib/compiler-rt/lib/i386/ashrdi3.S
@@ -1,5 +1,5 @@
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
#include "../assembly.h"
diff --git a/contrib/compiler-rt/lib/i386/divdi3.S b/contrib/compiler-rt/lib/i386/divdi3.S
index 5ad530c..69593e3 100644
--- a/contrib/compiler-rt/lib/i386/divdi3.S
+++ b/contrib/compiler-rt/lib/i386/divdi3.S
@@ -1,5 +1,5 @@
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
#include "../assembly.h"
diff --git a/contrib/compiler-rt/lib/i386/floatdidf.S b/contrib/compiler-rt/lib/i386/floatdidf.S
index 3a526ea..a953d26 100644
--- a/contrib/compiler-rt/lib/i386/floatdidf.S
+++ b/contrib/compiler-rt/lib/i386/floatdidf.S
@@ -1,5 +1,5 @@
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
#include "../assembly.h"
diff --git a/contrib/compiler-rt/lib/i386/floatdisf.S b/contrib/compiler-rt/lib/i386/floatdisf.S
index 741e4a6..a98a46e 100644
--- a/contrib/compiler-rt/lib/i386/floatdisf.S
+++ b/contrib/compiler-rt/lib/i386/floatdisf.S
@@ -1,5 +1,5 @@
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
#include "../assembly.h"
diff --git a/contrib/compiler-rt/lib/i386/floatdixf.S b/contrib/compiler-rt/lib/i386/floatdixf.S
index f0271ab..412976f 100644
--- a/contrib/compiler-rt/lib/i386/floatdixf.S
+++ b/contrib/compiler-rt/lib/i386/floatdixf.S
@@ -1,5 +1,5 @@
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
#include "../assembly.h"
diff --git a/contrib/compiler-rt/lib/i386/floatundidf.S b/contrib/compiler-rt/lib/i386/floatundidf.S
index 7186a35..6bba7e1 100644
--- a/contrib/compiler-rt/lib/i386/floatundidf.S
+++ b/contrib/compiler-rt/lib/i386/floatundidf.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
diff --git a/contrib/compiler-rt/lib/i386/floatundisf.S b/contrib/compiler-rt/lib/i386/floatundisf.S
index 070820c..1afd1d4 100644
--- a/contrib/compiler-rt/lib/i386/floatundisf.S
+++ b/contrib/compiler-rt/lib/i386/floatundisf.S
@@ -1,5 +1,5 @@
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
#include "../assembly.h"
diff --git a/contrib/compiler-rt/lib/i386/floatundixf.S b/contrib/compiler-rt/lib/i386/floatundixf.S
index 2cf6d5c..6e6710b 100644
--- a/contrib/compiler-rt/lib/i386/floatundixf.S
+++ b/contrib/compiler-rt/lib/i386/floatundixf.S
@@ -1,5 +1,5 @@
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
#include "../assembly.h"
diff --git a/contrib/compiler-rt/lib/i386/lshrdi3.S b/contrib/compiler-rt/lib/i386/lshrdi3.S
index 74937d2..cf411f2 100644
--- a/contrib/compiler-rt/lib/i386/lshrdi3.S
+++ b/contrib/compiler-rt/lib/i386/lshrdi3.S
@@ -1,5 +1,5 @@
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
#include "../assembly.h"
diff --git a/contrib/compiler-rt/lib/i386/moddi3.S b/contrib/compiler-rt/lib/i386/moddi3.S
index 85f5b38..8839cfc 100644
--- a/contrib/compiler-rt/lib/i386/moddi3.S
+++ b/contrib/compiler-rt/lib/i386/moddi3.S
@@ -1,5 +1,5 @@
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
#include "../assembly.h"
diff --git a/contrib/compiler-rt/lib/i386/muldi3.S b/contrib/compiler-rt/lib/i386/muldi3.S
index 5f99f6a..e56a355 100644
--- a/contrib/compiler-rt/lib/i386/muldi3.S
+++ b/contrib/compiler-rt/lib/i386/muldi3.S
@@ -1,5 +1,5 @@
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
#include "../assembly.h"
diff --git a/contrib/compiler-rt/lib/i386/udivdi3.S b/contrib/compiler-rt/lib/i386/udivdi3.S
index 77936f8..5abeaea 100644
--- a/contrib/compiler-rt/lib/i386/udivdi3.S
+++ b/contrib/compiler-rt/lib/i386/udivdi3.S
@@ -1,5 +1,5 @@
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
#include "../assembly.h"
diff --git a/contrib/compiler-rt/lib/i386/umoddi3.S b/contrib/compiler-rt/lib/i386/umoddi3.S
index 3cf8aeb..7fd8485 100644
--- a/contrib/compiler-rt/lib/i386/umoddi3.S
+++ b/contrib/compiler-rt/lib/i386/umoddi3.S
@@ -1,5 +1,5 @@
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
#include "../assembly.h"
diff --git a/contrib/compiler-rt/lib/int_lib.h b/contrib/compiler-rt/lib/int_lib.h
index 912a12f..e1fd6b7 100644
--- a/contrib/compiler-rt/lib/int_lib.h
+++ b/contrib/compiler-rt/lib/int_lib.h
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -20,6 +20,7 @@
/* Assumption: right shift of signed negative is arithmetic shift */
#include <limits.h>
+#include <stdint.h>
#include "endianness.h"
#include <math.h>
diff --git a/contrib/compiler-rt/lib/lshrdi3.c b/contrib/compiler-rt/lib/lshrdi3.c
index 57484ee..911edb1 100644
--- a/contrib/compiler-rt/lib/lshrdi3.c
+++ b/contrib/compiler-rt/lib/lshrdi3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,6 +11,7 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
@@ -18,7 +19,9 @@
/* Precondition: 0 <= b < bits_in_dword */
-di_int
+ARM_EABI_FNALIAS(llsr, lshrdi3);
+
+COMPILER_RT_ABI di_int
__lshrdi3(di_int a, si_int b)
{
const int bits_in_word = (int)(sizeof(si_int) * CHAR_BIT);
diff --git a/contrib/compiler-rt/lib/lshrti3.c b/contrib/compiler-rt/lib/lshrti3.c
index 3272c9c..5fdd99e 100644
--- a/contrib/compiler-rt/lib/lshrti3.c
+++ b/contrib/compiler-rt/lib/lshrti3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/moddi3.c b/contrib/compiler-rt/lib/moddi3.c
index 4533555..af0a8083 100644
--- a/contrib/compiler-rt/lib/moddi3.c
+++ b/contrib/compiler-rt/lib/moddi3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,14 +11,15 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
-du_int __udivmoddi4(du_int a, du_int b, du_int* rem);
+COMPILER_RT_ABI du_int __udivmoddi4(du_int a, du_int b, du_int* rem);
/* Returns: a % b */
-di_int
+COMPILER_RT_ABI di_int
__moddi3(di_int a, di_int b)
{
const int bits_in_dword_m1 = (int)(sizeof(di_int) * CHAR_BIT) - 1;
diff --git a/contrib/compiler-rt/lib/modsi3.c b/contrib/compiler-rt/lib/modsi3.c
index c9214a2..05ce806 100644
--- a/contrib/compiler-rt/lib/modsi3.c
+++ b/contrib/compiler-rt/lib/modsi3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,13 +11,16 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
+su_int COMPILER_RT_ABI __divsi3(si_int a, si_int b);
+
/* Returns: a % b */
-si_int
+COMPILER_RT_ABI si_int
__modsi3(si_int a, si_int b)
{
- return a - (a / b) * b;
+ return a - __divsi3(a, b) * b;
}
diff --git a/contrib/compiler-rt/lib/modti3.c b/contrib/compiler-rt/lib/modti3.c
index 75d688e..dbe5e94 100644
--- a/contrib/compiler-rt/lib/modti3.c
+++ b/contrib/compiler-rt/lib/modti3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/muldc3.c b/contrib/compiler-rt/lib/muldc3.c
index c048d84..9f9bd2a 100644
--- a/contrib/compiler-rt/lib/muldc3.c
+++ b/contrib/compiler-rt/lib/muldc3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/muldf3.c b/contrib/compiler-rt/lib/muldf3.c
index 63a473e..f402cfb 100644
--- a/contrib/compiler-rt/lib/muldf3.c
+++ b/contrib/compiler-rt/lib/muldf3.c
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
@@ -11,11 +11,15 @@
// with the IEEE-754 default rounding (to nearest, ties to even).
//
//===----------------------------------------------------------------------===//
+#include "abi.h"
#define DOUBLE_PRECISION
#include "fp_lib.h"
-fp_t __muldf3(fp_t a, fp_t b) {
+ARM_EABI_FNALIAS(dmul, muldf3);
+
+COMPILER_RT_ABI fp_t
+__muldf3(fp_t a, fp_t b) {
const unsigned int aExponent = toRep(a) >> significandBits & maxExponent;
const unsigned int bExponent = toRep(b) >> significandBits & maxExponent;
diff --git a/contrib/compiler-rt/lib/muldi3.c b/contrib/compiler-rt/lib/muldi3.c
index 38963b7..e6322bf 100644
--- a/contrib/compiler-rt/lib/muldi3.c
+++ b/contrib/compiler-rt/lib/muldi3.c
@@ -2,15 +2,16 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
* This file implements __muldi3 for the compiler_rt library.
*
* ===----------------------------------------------------------------------===
- */
+ */
+#include "abi.h"
#include "int_lib.h"
@@ -40,7 +41,9 @@ __muldsi3(su_int a, su_int b)
/* Returns: a * b */
-di_int
+ARM_EABI_FNALIAS(lmul, muldi3);
+
+COMPILER_RT_ABI di_int
__muldi3(di_int a, di_int b)
{
dwords x;
diff --git a/contrib/compiler-rt/lib/mulsc3.c b/contrib/compiler-rt/lib/mulsc3.c
index c7b9f64..a878ba1 100644
--- a/contrib/compiler-rt/lib/mulsc3.c
+++ b/contrib/compiler-rt/lib/mulsc3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/mulsf3.c b/contrib/compiler-rt/lib/mulsf3.c
index 6bd2f9d..bf46e14 100644
--- a/contrib/compiler-rt/lib/mulsf3.c
+++ b/contrib/compiler-rt/lib/mulsf3.c
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
@@ -11,11 +11,15 @@
// with the IEEE-754 default rounding (to nearest, ties to even).
//
//===----------------------------------------------------------------------===//
+#include "abi.h"
#define SINGLE_PRECISION
#include "fp_lib.h"
-fp_t __mulsf3(fp_t a, fp_t b) {
+ARM_EABI_FNALIAS(fmul, mulsf3);
+
+COMPILER_RT_ABI fp_t
+__mulsf3(fp_t a, fp_t b) {
const unsigned int aExponent = toRep(a) >> significandBits & maxExponent;
const unsigned int bExponent = toRep(b) >> significandBits & maxExponent;
diff --git a/contrib/compiler-rt/lib/multi3.c b/contrib/compiler-rt/lib/multi3.c
index 13a3867..ad8ab3f 100644
--- a/contrib/compiler-rt/lib/multi3.c
+++ b/contrib/compiler-rt/lib/multi3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
diff --git a/contrib/compiler-rt/lib/mulvdi3.c b/contrib/compiler-rt/lib/mulvdi3.c
index 295ae18..fcbb5b3 100644
--- a/contrib/compiler-rt/lib/mulvdi3.c
+++ b/contrib/compiler-rt/lib/mulvdi3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/mulvsi3.c b/contrib/compiler-rt/lib/mulvsi3.c
index b4a509b..6271cd4 100644
--- a/contrib/compiler-rt/lib/mulvsi3.c
+++ b/contrib/compiler-rt/lib/mulvsi3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/mulvti3.c b/contrib/compiler-rt/lib/mulvti3.c
index 778222e..7da9187 100644
--- a/contrib/compiler-rt/lib/mulvti3.c
+++ b/contrib/compiler-rt/lib/mulvti3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/mulxc3.c b/contrib/compiler-rt/lib/mulxc3.c
index 94895f2..b5ae865 100644
--- a/contrib/compiler-rt/lib/mulxc3.c
+++ b/contrib/compiler-rt/lib/mulxc3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/negdf2.c b/contrib/compiler-rt/lib/negdf2.c
index 527b068..b47f397 100644
--- a/contrib/compiler-rt/lib/negdf2.c
+++ b/contrib/compiler-rt/lib/negdf2.c
@@ -2,18 +2,21 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements double-precision soft-float negation.
//
//===----------------------------------------------------------------------===//
+#include "abi.h"
#define DOUBLE_PRECISION
#include "fp_lib.h"
+ARM_EABI_FNALIAS(dneg, negdf2);
+
fp_t __negdf2(fp_t a) {
return fromRep(toRep(a) ^ signBit);
}
diff --git a/contrib/compiler-rt/lib/negdi2.c b/contrib/compiler-rt/lib/negdi2.c
index 707b0dd..b000dda 100644
--- a/contrib/compiler-rt/lib/negdi2.c
+++ b/contrib/compiler-rt/lib/negdi2.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/negsf2.c b/contrib/compiler-rt/lib/negsf2.c
index 5e91e87..98f9fc0 100644
--- a/contrib/compiler-rt/lib/negsf2.c
+++ b/contrib/compiler-rt/lib/negsf2.c
@@ -2,18 +2,22 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements single-precision soft-float negation.
//
//===----------------------------------------------------------------------===//
+#include "abi.h"
#define SINGLE_PRECISION
#include "fp_lib.h"
-fp_t __negsf2(fp_t a) {
+ARM_EABI_FNALIAS(fneg, negsf2);
+
+COMPILER_RT_ABI fp_t
+__negsf2(fp_t a) {
return fromRep(toRep(a) ^ signBit);
}
diff --git a/contrib/compiler-rt/lib/negti2.c b/contrib/compiler-rt/lib/negti2.c
index 6ce6a04..774e808 100644
--- a/contrib/compiler-rt/lib/negti2.c
+++ b/contrib/compiler-rt/lib/negti2.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/negvdi2.c b/contrib/compiler-rt/lib/negvdi2.c
index 0baf377..aafaa9d 100644
--- a/contrib/compiler-rt/lib/negvdi2.c
+++ b/contrib/compiler-rt/lib/negvdi2.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,6 +11,7 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
#include <stdlib.h>
@@ -19,7 +20,7 @@
/* Effects: aborts if -a overflows */
-di_int
+COMPILER_RT_ABI di_int
__negvdi2(di_int a)
{
const di_int MIN = (di_int)1 << ((int)(sizeof(di_int) * CHAR_BIT)-1);
diff --git a/contrib/compiler-rt/lib/negvsi2.c b/contrib/compiler-rt/lib/negvsi2.c
index e5a36a5..559ea18 100644
--- a/contrib/compiler-rt/lib/negvsi2.c
+++ b/contrib/compiler-rt/lib/negvsi2.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,6 +11,7 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
#include <stdlib.h>
@@ -19,7 +20,7 @@
/* Effects: aborts if -a overflows */
-si_int
+COMPILER_RT_ABI si_int
__negvsi2(si_int a)
{
const si_int MIN = (si_int)1 << ((int)(sizeof(si_int) * CHAR_BIT)-1);
diff --git a/contrib/compiler-rt/lib/negvti2.c b/contrib/compiler-rt/lib/negvti2.c
index d56e1e3..d931305 100644
--- a/contrib/compiler-rt/lib/negvti2.c
+++ b/contrib/compiler-rt/lib/negvti2.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
*===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/paritydi2.c b/contrib/compiler-rt/lib/paritydi2.c
index 90e5559..e7bebf6 100644
--- a/contrib/compiler-rt/lib/paritydi2.c
+++ b/contrib/compiler-rt/lib/paritydi2.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,14 +11,15 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
/* Returns: 1 if number of bits is odd else returns 0 */
-si_int __paritysi2(si_int a);
+si_int COMPILER_RT_ABI __paritysi2(si_int a);
-si_int
+COMPILER_RT_ABI si_int
__paritydi2(di_int a)
{
dwords x;
diff --git a/contrib/compiler-rt/lib/paritysi2.c b/contrib/compiler-rt/lib/paritysi2.c
index ba05782..64d509f 100644
--- a/contrib/compiler-rt/lib/paritysi2.c
+++ b/contrib/compiler-rt/lib/paritysi2.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,12 +11,13 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
/* Returns: 1 if number of bits is odd else returns 0 */
-si_int
+COMPILER_RT_ABI si_int
__paritysi2(si_int a)
{
su_int x = (su_int)a;
diff --git a/contrib/compiler-rt/lib/parityti2.c b/contrib/compiler-rt/lib/parityti2.c
index 650d417..8f85745 100644
--- a/contrib/compiler-rt/lib/parityti2.c
+++ b/contrib/compiler-rt/lib/parityti2.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/popcountdi2.c b/contrib/compiler-rt/lib/popcountdi2.c
index 78b6d88..136fc04 100644
--- a/contrib/compiler-rt/lib/popcountdi2.c
+++ b/contrib/compiler-rt/lib/popcountdi2.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,12 +11,13 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
/* Returns: count of 1 bits */
-si_int
+COMPILER_RT_ABI si_int
__popcountdi2(di_int a)
{
du_int x2 = (du_int)a;
diff --git a/contrib/compiler-rt/lib/popcountsi2.c b/contrib/compiler-rt/lib/popcountsi2.c
index 4f092ee..bfaa3ff 100644
--- a/contrib/compiler-rt/lib/popcountsi2.c
+++ b/contrib/compiler-rt/lib/popcountsi2.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,12 +11,13 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
/* Returns: count of 1 bits */
-si_int
+COMPILER_RT_ABI si_int
__popcountsi2(si_int a)
{
su_int x = (su_int)a;
diff --git a/contrib/compiler-rt/lib/popcountti2.c b/contrib/compiler-rt/lib/popcountti2.c
index 16f89b7..68d9427 100644
--- a/contrib/compiler-rt/lib/popcountti2.c
+++ b/contrib/compiler-rt/lib/popcountti2.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/powidf2.c b/contrib/compiler-rt/lib/powidf2.c
index 37972b6..2e211eb 100644
--- a/contrib/compiler-rt/lib/powidf2.c
+++ b/contrib/compiler-rt/lib/powidf2.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,12 +11,13 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
/* Returns: a ^ b */
-double
+COMPILER_RT_ABI double
__powidf2(double a, si_int b)
{
const int recip = b < 0;
diff --git a/contrib/compiler-rt/lib/powisf2.c b/contrib/compiler-rt/lib/powisf2.c
index ace08c2..e6b43b3 100644
--- a/contrib/compiler-rt/lib/powisf2.c
+++ b/contrib/compiler-rt/lib/powisf2.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,12 +11,13 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
/* Returns: a ^ b */
-float
+COMPILER_RT_ABI float
__powisf2(float a, si_int b)
{
const int recip = b < 0;
diff --git a/contrib/compiler-rt/lib/powitf2.c b/contrib/compiler-rt/lib/powitf2.c
index 3dacbf6..189632c 100644
--- a/contrib/compiler-rt/lib/powitf2.c
+++ b/contrib/compiler-rt/lib/powitf2.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/powixf2.c b/contrib/compiler-rt/lib/powixf2.c
index 1a816e9..f050964 100644
--- a/contrib/compiler-rt/lib/powixf2.c
+++ b/contrib/compiler-rt/lib/powixf2.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/ppc/restFP.S b/contrib/compiler-rt/lib/ppc/restFP.S
index 00919c8..9503289 100644
--- a/contrib/compiler-rt/lib/ppc/restFP.S
+++ b/contrib/compiler-rt/lib/ppc/restFP.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/ppc/saveFP.S b/contrib/compiler-rt/lib/ppc/saveFP.S
index 302da6e..72bd459 100644
--- a/contrib/compiler-rt/lib/ppc/saveFP.S
+++ b/contrib/compiler-rt/lib/ppc/saveFP.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
diff --git a/contrib/compiler-rt/lib/subdf3.c b/contrib/compiler-rt/lib/subdf3.c
new file mode 100644
index 0000000..825e3c6
--- /dev/null
+++ b/contrib/compiler-rt/lib/subdf3.c
@@ -0,0 +1,30 @@
+//===-- lib/adddf3.c - Double-precision subtraction ---------------*- C -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements double-precision soft-float subtraction with the
+// IEEE-754 default rounding (to nearest, ties to even).
+//
+//===----------------------------------------------------------------------===//
+#include "abi.h"
+
+#define DOUBLE_PRECISION
+#include "fp_lib.h"
+
+fp_t COMPILER_RT_ABI __adddf3(fp_t a, fp_t b);
+
+
+ARM_EABI_FNALIAS(dsub, subdf3);
+
+// Subtraction; flip the sign bit of b and add.
+COMPILER_RT_ABI fp_t
+__subdf3(fp_t a, fp_t b) {
+ return __adddf3(a, fromRep(toRep(b) ^ signBit));
+}
+
+/* FIXME: rsub for ARM EABI */
diff --git a/contrib/compiler-rt/lib/subsf3.c b/contrib/compiler-rt/lib/subsf3.c
new file mode 100644
index 0000000..625376a
--- /dev/null
+++ b/contrib/compiler-rt/lib/subsf3.c
@@ -0,0 +1,29 @@
+//===-- lib/subsf3.c - Single-precision subtraction ---------------*- C -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements single-precision soft-float subtraction with the
+// IEEE-754 default rounding (to nearest, ties to even).
+//
+//===----------------------------------------------------------------------===//
+#include "abi.h"
+
+#define SINGLE_PRECISION
+#include "fp_lib.h"
+
+fp_t COMPILER_RT_ABI __addsf3(fp_t a, fp_t b);
+
+ARM_EABI_FNALIAS(fsub, subsf3);
+
+// Subtraction; flip the sign bit of b and add.
+COMPILER_RT_ABI fp_t
+__subsf3(fp_t a, fp_t b) {
+ return __addsf3(a, fromRep(toRep(b) ^ signBit));
+}
+
+/* FIXME: rsub for ARM EABI */
diff --git a/contrib/compiler-rt/lib/subvdi3.c b/contrib/compiler-rt/lib/subvdi3.c
index e4926b8..36b51ad 100644
--- a/contrib/compiler-rt/lib/subvdi3.c
+++ b/contrib/compiler-rt/lib/subvdi3.c
@@ -1,9 +1,9 @@
/* ===-- subvdi3.c - Implement __subvdi3 -----------------------------------===
*
- * The LLVM Compiler Infrastructure
+ * The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,6 +11,7 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
#include <stdlib.h>
@@ -19,7 +20,7 @@
/* Effects: aborts if a - b overflows */
-di_int
+COMPILER_RT_ABI di_int
__subvdi3(di_int a, di_int b)
{
di_int s = a - b;
diff --git a/contrib/compiler-rt/lib/subvsi3.c b/contrib/compiler-rt/lib/subvsi3.c
index ce39c81..03983f7 100644
--- a/contrib/compiler-rt/lib/subvsi3.c
+++ b/contrib/compiler-rt/lib/subvsi3.c
@@ -1,9 +1,9 @@
/* ===-- subvsi3.c - Implement __subvsi3 -----------------------------------===
*
- * The LLVM Compiler Infrastructure
+ * The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,6 +11,7 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
#include <stdlib.h>
@@ -19,7 +20,7 @@
/* Effects: aborts if a - b overflows */
-si_int
+COMPILER_RT_ABI si_int
__subvsi3(si_int a, si_int b)
{
si_int s = a - b;
diff --git a/contrib/compiler-rt/lib/subvti3.c b/contrib/compiler-rt/lib/subvti3.c
index 55b7925..5d693dc 100644
--- a/contrib/compiler-rt/lib/subvti3.c
+++ b/contrib/compiler-rt/lib/subvti3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/trampoline_setup.c b/contrib/compiler-rt/lib/trampoline_setup.c
index a2f49a4..a22199e 100644
--- a/contrib/compiler-rt/lib/trampoline_setup.c
+++ b/contrib/compiler-rt/lib/trampoline_setup.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*/
diff --git a/contrib/compiler-rt/lib/truncdfsf2.c b/contrib/compiler-rt/lib/truncdfsf2.c
index d289cb9..1dbf02f 100644
--- a/contrib/compiler-rt/lib/truncdfsf2.c
+++ b/contrib/compiler-rt/lib/truncdfsf2.c
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
@@ -41,6 +41,8 @@
#include <limits.h>
#include <stdbool.h>
+#include "abi.h"
+
typedef double src_t;
typedef uint64_t src_rep_t;
#define SRC_REP_C UINT64_C
@@ -66,7 +68,10 @@ static inline dst_t dstFromRep(dst_rep_t x) {
// End helper routines. Conversion implementation follows.
-dst_t __truncdfsf2(src_t a) {
+ARM_EABI_FNALIAS(d2f, truncdfsf2);
+
+COMPILER_RT_ABI dst_t
+__truncdfsf2(src_t a) {
// Various constants whose values follow from the type parameters.
// Any reasonable optimizer will fold and propagate all of these.
diff --git a/contrib/compiler-rt/lib/ucmpdi2.c b/contrib/compiler-rt/lib/ucmpdi2.c
index d2900ca..f2d3f99 100644
--- a/contrib/compiler-rt/lib/ucmpdi2.c
+++ b/contrib/compiler-rt/lib/ucmpdi2.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,6 +11,7 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
@@ -19,7 +20,7 @@
* if (a > b) returns 2
*/
-si_int
+COMPILER_RT_ABI si_int
__ucmpdi2(du_int a, du_int b)
{
udwords x;
diff --git a/contrib/compiler-rt/lib/ucmpti2.c b/contrib/compiler-rt/lib/ucmpti2.c
index 0e7eea3..11137c5 100644
--- a/contrib/compiler-rt/lib/ucmpti2.c
+++ b/contrib/compiler-rt/lib/ucmpti2.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/udivdi3.c b/contrib/compiler-rt/lib/udivdi3.c
index 25d1df6..bbd551a 100644
--- a/contrib/compiler-rt/lib/udivdi3.c
+++ b/contrib/compiler-rt/lib/udivdi3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,14 +11,15 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
-du_int __udivmoddi4(du_int a, du_int b, du_int* rem);
+du_int COMPILER_RT_ABI __udivmoddi4(du_int a, du_int b, du_int* rem);
/* Returns: a / b */
-du_int
+COMPILER_RT_ABI du_int
__udivdi3(du_int a, du_int b)
{
return __udivmoddi4(a, b, 0);
diff --git a/contrib/compiler-rt/lib/udivmoddi4.c b/contrib/compiler-rt/lib/udivmoddi4.c
index 9274230..c5db21c 100644
--- a/contrib/compiler-rt/lib/udivmoddi4.c
+++ b/contrib/compiler-rt/lib/udivmoddi4.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,6 +11,7 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
@@ -20,7 +21,9 @@
/* Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide */
-du_int
+ARM_EABI_FNALIAS(uldivmod, udivmoddi4);
+
+COMPILER_RT_ABI du_int
__udivmoddi4(du_int a, du_int b, du_int* rem)
{
const unsigned n_uword_bits = sizeof(su_int) * CHAR_BIT;
diff --git a/contrib/compiler-rt/lib/udivmodsi4.c b/contrib/compiler-rt/lib/udivmodsi4.c
new file mode 100644
index 0000000..2a3ee27
--- /dev/null
+++ b/contrib/compiler-rt/lib/udivmodsi4.c
@@ -0,0 +1,31 @@
+/*===-- udivmodsi4.c - Implement __udivmodsi4 ------------------------------===
+ *
+ * The LLVM Compiler Infrastructure
+ *
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
+ *
+ * ===----------------------------------------------------------------------===
+ *
+ * This file implements __udivmodsi4 for the compiler_rt library.
+ *
+ * ===----------------------------------------------------------------------===
+ */
+#include "abi.h"
+
+#include "int_lib.h"
+
+extern su_int COMPILER_RT_ABI __udivsi3(su_int n, su_int d);
+
+
+/* Returns: a / b, *rem = a % b */
+
+COMPILER_RT_ABI su_int
+__udivmodsi4(su_int a, su_int b, su_int* rem)
+{
+ si_int d = __udivsi3(a,b);
+ *rem = a - (d*b);
+ return d;
+}
+
+
diff --git a/contrib/compiler-rt/lib/udivmodti4.c b/contrib/compiler-rt/lib/udivmodti4.c
index 53b4072..d1e19ed 100644
--- a/contrib/compiler-rt/lib/udivmodti4.c
+++ b/contrib/compiler-rt/lib/udivmodti4.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/udivsi3.c b/contrib/compiler-rt/lib/udivsi3.c
index 70528b6..721ae89 100644
--- a/contrib/compiler-rt/lib/udivsi3.c
+++ b/contrib/compiler-rt/lib/udivsi3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,6 +11,7 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
@@ -18,7 +19,9 @@
/* Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide */
-su_int
+ARM_EABI_FNALIAS(uidiv, udivsi3);
+
+COMPILER_RT_ABI su_int
__udivsi3(su_int n, su_int d)
{
const unsigned n_uword_bits = sizeof(su_int) * CHAR_BIT;
diff --git a/contrib/compiler-rt/lib/udivti3.c b/contrib/compiler-rt/lib/udivti3.c
index fb810fd..7405a0f 100644
--- a/contrib/compiler-rt/lib/udivti3.c
+++ b/contrib/compiler-rt/lib/udivti3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/umoddi3.c b/contrib/compiler-rt/lib/umoddi3.c
index 807bb5ce..9de1a64 100644
--- a/contrib/compiler-rt/lib/umoddi3.c
+++ b/contrib/compiler-rt/lib/umoddi3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,14 +11,15 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
-du_int __udivmoddi4(du_int a, du_int b, du_int* rem);
+du_int COMPILER_RT_ABI __udivmoddi4(du_int a, du_int b, du_int* rem);
/* Returns: a % b */
-du_int
+COMPILER_RT_ABI du_int
__umoddi3(du_int a, du_int b)
{
du_int r;
diff --git a/contrib/compiler-rt/lib/umodsi3.c b/contrib/compiler-rt/lib/umodsi3.c
index ead7737..569b7fc 100644
--- a/contrib/compiler-rt/lib/umodsi3.c
+++ b/contrib/compiler-rt/lib/umodsi3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
@@ -11,14 +11,15 @@
*
* ===----------------------------------------------------------------------===
*/
+#include "abi.h"
#include "int_lib.h"
/* Returns: a % b */
-su_int __udivsi3(su_int a, su_int b);
+su_int COMPILER_RT_ABI __udivsi3(su_int a, su_int b);
-su_int
+COMPILER_RT_ABI su_int
__umodsi3(su_int a, su_int b)
{
return a - __udivsi3(a, b) * b;
diff --git a/contrib/compiler-rt/lib/umodti3.c b/contrib/compiler-rt/lib/umodti3.c
index 6c8a758..8f20c5f 100644
--- a/contrib/compiler-rt/lib/umodti3.c
+++ b/contrib/compiler-rt/lib/umodti3.c
@@ -2,8 +2,8 @@
*
* The LLVM Compiler Infrastructure
*
- * This file is distributed under the University of Illinois Open Source
- * License. See LICENSE.TXT for details.
+ * This file is dual licensed under the MIT and the University of Illinois Open
+ * Source Licenses. See LICENSE.TXT for details.
*
* ===----------------------------------------------------------------------===
*
diff --git a/contrib/compiler-rt/lib/x86_64/floatundidf.S b/contrib/compiler-rt/lib/x86_64/floatundidf.S
index 6e684b2..1be553b 100644
--- a/contrib/compiler-rt/lib/x86_64/floatundidf.S
+++ b/contrib/compiler-rt/lib/x86_64/floatundidf.S
@@ -2,8 +2,8 @@
//
// The LLVM Compiler Infrastructure
//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
diff --git a/contrib/compiler-rt/lib/x86_64/floatundisf.S b/contrib/compiler-rt/lib/x86_64/floatundisf.S
index fe20963..89d3f07 100644
--- a/contrib/compiler-rt/lib/x86_64/floatundisf.S
+++ b/contrib/compiler-rt/lib/x86_64/floatundisf.S
@@ -1,5 +1,5 @@
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
#include "../assembly.h"
diff --git a/contrib/compiler-rt/lib/x86_64/floatundixf.S b/contrib/compiler-rt/lib/x86_64/floatundixf.S
index 246f026..a7243f2 100644
--- a/contrib/compiler-rt/lib/x86_64/floatundixf.S
+++ b/contrib/compiler-rt/lib/x86_64/floatundixf.S
@@ -1,5 +1,5 @@
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
#include "../assembly.h"
diff --git a/contrib/groff/tmac/troffrc b/contrib/groff/tmac/troffrc
index 5defe8a..92b5fad 100644
--- a/contrib/groff/tmac/troffrc
+++ b/contrib/groff/tmac/troffrc
@@ -50,12 +50,4 @@ troffrc!X100 troffrc!X100-12 troffrc!lj4 troff!lbp troffrc!html
.\" Handle paper formats
.do mso papersize.tmac
.
-.\" Disable SGR support in grotty(1).
-.if n \{\
-. do nop \X'tty: sgr 0'
-. sp -1
-. nr nl 0-1
-. nr % -1
-.\}
-.
.\" Don't let blank lines creep in here.
diff --git a/contrib/libpcap/pcap-bpf.c b/contrib/libpcap/pcap-bpf.c
index 10dcfd1..5e3d3ea 100644
--- a/contrib/libpcap/pcap-bpf.c
+++ b/contrib/libpcap/pcap-bpf.c
@@ -1281,6 +1281,7 @@ pcap_cleanup_bpf(pcap_t *p)
munmap(p->md.zbuf1, p->md.zbufsize);
if (p->md.zbuf2 != MAP_FAILED && p->md.zbuf2 != NULL)
munmap(p->md.zbuf2, p->md.zbufsize);
+ p->buffer = NULL;
}
#endif
if (p->md.device != NULL) {
diff --git a/contrib/ntp/ntpd/ntp_io.c b/contrib/ntp/ntpd/ntp_io.c
index 71ee15f..8dac3c4 100644
--- a/contrib/ntp/ntpd/ntp_io.c
+++ b/contrib/ntp/ntpd/ntp_io.c
@@ -1753,7 +1753,12 @@ void
enable_multicast_if(struct interface *iface, struct sockaddr_storage *maddr)
{
#ifdef MCAST
+#ifdef IP_MULTICAST_LOOP
/*u_char*/ TYPEOF_IP_MULTICAST_LOOP off = 0;
+#endif
+#ifdef IPV6_MULTICAST_LOOP
+ u_int off6 = 0; /* RFC 3493, 5.2. defines type unsigned int */
+#endif
switch (maddr->ss_family)
{
@@ -1797,9 +1802,9 @@ enable_multicast_if(struct interface *iface, struct sockaddr_storage *maddr)
* Don't send back to itself, but allow it to fail to set it
*/
if (setsockopt(iface->fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
- (char *) &off, sizeof(off)) == -1) {
+ (char *) &off6, sizeof(off6)) == -1) {
netsyslog(LOG_ERR,
- "setsockopt IP_MULTICAST_LOOP failure: %m on socket %d, addr %s for multicast address %s",
+ "setsockopt IPV6_MULTICAST_LOOP failure: %m on socket %d, addr %s for multicast address %s",
iface->fd, stoa(&iface->sin), stoa(maddr));
}
#endif
diff --git a/contrib/top/commands.c b/contrib/top/commands.c
index 47f4a2e..7891068 100644
--- a/contrib/top/commands.c
+++ b/contrib/top/commands.c
@@ -94,6 +94,7 @@ S - toggle the displaying of system processes\n\
a - toggle the displaying of process titles\n\
t - toggle the display of this process\n\
u - display processes for only one user (+ selects all users)\n\
+z - toggle the displaying of the system idle process\n\
\n\
\n", stdout);
}
diff --git a/contrib/top/machine.h b/contrib/top/machine.h
index a09424c..3e1af16 100644
--- a/contrib/top/machine.h
+++ b/contrib/top/machine.h
@@ -65,6 +65,7 @@ struct process_select
int uid; /* only this uid (unless uid == -1) */
int wcpu; /* show weighted cpu */
int jail; /* show jail ID */
+ int kidle; /* show per-CPU idle threads */
char *command; /* only this command (unless == NULL) */
};
diff --git a/contrib/top/top.X b/contrib/top/top.X
index 830e50d..41c3d78 100644
--- a/contrib/top/top.X
+++ b/contrib/top/top.X
@@ -10,7 +10,7 @@ top \- display and update information about the top cpu processes
.SH SYNOPSIS
.B top
[
-.B \-abCHIijnPqStuv
+.B \-abCHIijnPqStuvz
] [
.BI \-d count
] [
@@ -89,6 +89,10 @@ Use \*(lqbatch\*(rq mode. In this mode, all input from the terminal is
ignored. Interrupt characters (such as ^C and ^\e) still have an effect.
This is the default on a dumb terminal, or when the output is not a terminal.
.TP
+.B \-H
+Display each thread for a multithreaded process individually.
+By default a single summary line is displayed for each process.
+.TP
.B \-i
Use \*(lqinteractive\*(rq mode. In this mode, any input is immediately
read for processing. See the section on \*(lqInteractive Mode\*(rq
@@ -142,6 +146,9 @@ Write version number information to stderr then exit immediately.
No other processing takes place when this option is used. To see current
revision information while top is running, use the help command \*(lq?\*(rq.
.TP
+.B \-z
+Do not display the system idle process.
+.TP
.BI \-d count
Show only
.I count
@@ -289,6 +296,9 @@ or
.BR r enice
command.
.TP
+.B H
+Toggle the display of threads.
+.TP
.B i
(or
.BR I )
@@ -303,6 +313,9 @@ ID.
Toggle the display of the
.I top
process.
+.TP
+.B z
+Toggle the display of the system idle process.
.SH "THE DISPLAY"
The actual display varies depending on the specific variant of Unix
that the machine is running. This description may not exactly match
@@ -352,8 +365,11 @@ the order of the processes, and
COMMAND is the name of the command that the process is currently running
(if the process is swapped out, this column is marked \*(lq<swapped>\*(rq).
.SH NOTES
-The \*(lqABANDONED\*(rq state (known in the kernel as \*(lqSWAIT\*(rq) was
-abandoned, thus the name. A process should never end up in this state.
+If a process is in the \*(lqSLEEP\*(rq or \*(lqLOCK\*(rq state,
+the state column will report the name of the event or lock on which the
+process is waiting.
+Lock names are prefixed with an asterisk \*(lq*\*(rq while sleep events
+are not.
.SH AUTHOR
William LeFebvre, EECS Department, Northwestern University
.SH ENVIRONMENT
diff --git a/contrib/top/top.c b/contrib/top/top.c
index 762efaa..6673a27 100644
--- a/contrib/top/top.c
+++ b/contrib/top/top.c
@@ -196,9 +196,9 @@ char *argv[];
fd_set readfds;
#ifdef ORDER
- static char command_chars[] = "\f qh?en#sdkriIutHmSCajo";
+ static char command_chars[] = "\f qh?en#sdkriIutHmSCajzo";
#else
- static char command_chars[] = "\f qh?en#sdkriIutHmSCaj";
+ static char command_chars[] = "\f qh?en#sdkriIutHmSCajz";
#endif
/* these defines enumerate the "strchr"s of the commands in command_chars */
#define CMD_redraw 0
@@ -224,8 +224,9 @@ char *argv[];
#define CMD_wcputog 19
#define CMD_showargs 20
#define CMD_jidtog 21
+#define CMD_kidletog 22
#ifdef ORDER
-#define CMD_order 22
+#define CMD_order 23
#endif
/* set the buffer for stdout */
@@ -258,6 +259,7 @@ char *argv[];
ps.thread = No;
ps.wcpu = 1;
ps.jail = No;
+ ps.kidle = Yes;
ps.command = NULL;
/* get preset options from the environment */
@@ -283,7 +285,7 @@ char *argv[];
optind = 1;
}
- while ((i = getopt(ac, av, "CSIHPabijnquvs:d:U:m:o:t")) != EOF)
+ while ((i = getopt(ac, av, "CSIHPabijnquvzs:d:U:m:o:t")) != EOF)
{
switch(i)
{
@@ -412,10 +414,14 @@ char *argv[];
pcpu_stats = Yes;
break;
+ case 'z':
+ ps.kidle = !ps.kidle;
+ break;
+
default:
fprintf(stderr,
"Top version %s\n"
-"Usage: %s [-abCHIijnPqStuv] [-d count] [-m io | cpu] [-o field] [-s time]\n"
+"Usage: %s [-abCHIijnPqStuvz] [-d count] [-m io | cpu] [-o field] [-s time]\n"
" [-U username] [number]\n",
version_string(), myname);
exit(1);
@@ -1075,7 +1081,13 @@ restart:
reset_display();
putchar('\r');
break;
-
+ case CMD_kidletog:
+ ps.kidle = !ps.kidle;
+ new_message(MT_standout | MT_delayed,
+ " %sisplaying system idle process.",
+ ps.kidle ? "D" : "Not d");
+ putchar('\r');
+ break;
default:
new_message(MT_standout, " BAD CASE IN SWITCH!");
putchar('\r');
diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf
index 21007d6..0fa9004 100644
--- a/etc/defaults/rc.conf
+++ b/etc/defaults/rc.conf
@@ -210,7 +210,7 @@ icmp_log_redirect="NO" # Set to YES to log ICMP REDIRECT packets
network_interfaces="auto" # List of network interfaces (or "auto").
cloned_interfaces="" # List of cloned network interfaces to create.
#cloned_interfaces="gif0 gif1 gif2 gif3" # Pre-cloning GENERIC config.
-ifconfig_lo0="inet 127.0.0.1" # default loopback device configuration.
+#ifconfig_lo0="inet 127.0.0.1" # default loopback device configuration.
#ifconfig_lo0_alias0="inet 127.0.0.254 netmask 0xffffffff" # Sample alias entry.
#ifconfig_ed0_ipx="ipx 0x00010010" # Sample IPX address family entry.
#ifconfig_ed0_ipv6="inet6 2001:db8:1::1 prefixlen 64" # Sample IPv6 addr entry
diff --git a/etc/network.subr b/etc/network.subr
index 8185c5a..64fb0fe 100644
--- a/etc/network.subr
+++ b/etc/network.subr
@@ -44,9 +44,9 @@ ifn_start()
ifscript_up ${ifn} && cfg=0
ifconfig_up ${ifn} && cfg=0
- ipv4_up ${ifn} && cfg=0
- ipv6_up ${ifn} && cfg=0
- ipx_up ${ifn} && cfg=0
+ afexists inet && ipv4_up ${ifn} && cfg=0
+ afexists inet6 && ipv6_up ${ifn} && cfg=0
+ afexists ipx && ipx_up ${ifn} && cfg=0
childif_create ${ifn} && cfg=0
return $cfg
@@ -64,9 +64,9 @@ ifn_stop()
[ -z "$ifn" ] && err 1 "ifn_stop called without an interface"
- ipx_down ${ifn} && cfg=0
- ipv6_down ${ifn} && cfg=0
- ipv4_down ${ifn} && cfg=0
+ afexists ipx && ipx_down ${ifn} && cfg=0
+ afexists inet6 && ipv6_down ${ifn} && cfg=0
+ afexists inet && ipv4_down ${ifn} && cfg=0
ifconfig_down ${ifn} && cfg=0
ifscript_down ${ifn} && cfg=0
childif_destroy ${ifn} && cfg=0
@@ -86,6 +86,11 @@ ifconfig_up()
local _cfg _ipv6_opts ifconfig_args
_cfg=1
+ # Make sure lo0 always comes up.
+ if [ "$1" = "lo0" ]; then
+ _cfg=0
+ fi
+
# ifconfig_IF
ifconfig_args=`ifconfig_getargs $1`
if [ -n "${ifconfig_args}" ]; then
@@ -351,10 +356,10 @@ afexists()
case ${_af} in
inet)
- ${SYSCTL_N} net.inet > /dev/null 2>&1
+ ${SYSCTL_N} kern.features.inet > /dev/null 2>&1
;;
inet6)
- ${SYSCTL_N} net.inet6 > /dev/null 2>&1
+ ${SYSCTL_N} kern.features.inet6 > /dev/null 2>&1
;;
ipx)
${SYSCTL_N} net.ipx > /dev/null 2>&1
@@ -512,6 +517,13 @@ ipv4_up()
_if=$1
_ret=1
+ # Add 127.0.0.1/8 to lo0 unless otherwise specified.
+ if [ "${_if}" = "lo0" ]; then
+ ifconfig_args=`ifconfig_getargs ${_if}`
+ if [ -z "${ifconfig_args}" ]; then
+ ifconfig ${_if} inet 127.0.0.1/8 alias
+ fi
+ fi
ifalias_up ${_if} inet && _ret=0
ipv4_addrs_common ${_if} alias && _ret=0
diff --git a/lib/libc/gen/posix_spawn.c b/lib/libc/gen/posix_spawn.c
index 20f2c16..58044b3 100644
--- a/lib/libc/gen/posix_spawn.c
+++ b/lib/libc/gen/posix_spawn.c
@@ -163,11 +163,8 @@ process_file_actions_entry(posix_spawn_file_actions_entry_t *fae)
return (errno);
break;
case FAE_CLOSE:
- /* Perform a close() */
- if (_close(fae->fae_fildes) != 0) {
- if (errno == EBADF)
- return (EBADF);
- }
+ /* Perform a close(), do not fail if already closed */
+ (void)_close(fae->fae_fildes);
break;
}
return (0);
diff --git a/lib/libc/iconv/iconvctl.3 b/lib/libc/iconv/iconvctl.3
index 29007c1..30fc0aa 100644
--- a/lib/libc/iconv/iconvctl.3
+++ b/lib/libc/iconv/iconvctl.3
@@ -150,6 +150,9 @@ facility is a non-standard extension, which appeared in
the GNU implementation and was adopted in
.Fx 9
for compatibility's sake.
+.Sh AUTHORS
+This manual page was written by
+.An Gabor Kovesdan Aq gabor@FreeBSD.org .
.Sh BUGS
Transliteration is enabled in this implementation by default, so it
is impossible by design to turn it off.
@@ -157,6 +160,3 @@ Accordingly, trying to turn it off will always fail and \-1 will be
returned.
Getting the transliteration state will always succeed and indicate
that it is turned on, though.
-.Sh AUTHORS
-This manual page was written by
-.An Gabor Kovesdan Aq gabor@FreeBSD.org .
diff --git a/lib/libcompiler_rt/Makefile b/lib/libcompiler_rt/Makefile
index dcfcf74..3a501f5 100644
--- a/lib/libcompiler_rt/Makefile
+++ b/lib/libcompiler_rt/Makefile
@@ -41,6 +41,8 @@ SRCF= absvdi2 \
ctzti2 \
divdc3 \
divdi3 \
+ divmoddi4 \
+ divmodsi4 \
divsc3 \
divti3 \
divxc3 \
@@ -114,6 +116,7 @@ SRCF= absvdi2 \
ucmpti2 \
udivdi3 \
udivmoddi4 \
+ udivmodsi4 \
udivmodti4 \
udivti3 \
umoddi3 \
@@ -134,6 +137,8 @@ SRCF+= adddf3 \
modsi3 \
muldf3 \
mulsf3 \
+ subdf3 \
+ subsf3 \
truncdfsf2 \
udivsi3 \
umodsi3
diff --git a/lib/msun/ld128/e_rem_pio2l.h b/lib/msun/ld128/e_rem_pio2l.h
index d223627..5d78c4d 100644
--- a/lib/msun/ld128/e_rem_pio2l.h
+++ b/lib/msun/ld128/e_rem_pio2l.h
@@ -58,10 +58,7 @@ pio2_2t = 2.0670321098263988236496903051604844e-43L, /* 0x127044533e63a0105df5
pio2_3 = 2.0670321098263988236499468110329591e-43L, /* 0x127044533e63a0105e00000000000.0p-254 */
pio2_3t = -2.5650587247459238361625433492959285e-65L; /* -0x159c4ec64ddaeb5f78671cbfb2210.0p-327 */
-#ifdef INLINE_REM_PIO2L
-static inline __always_inline
-#endif
-int
+static inline __always_inline int
__ieee754_rem_pio2l(long double x, long double *y)
{
union IEEEl2bits u,u1;
diff --git a/lib/msun/ld80/e_rem_pio2l.h b/lib/msun/ld80/e_rem_pio2l.h
index cfe3fb9..81a5ab6 100644
--- a/lib/msun/ld80/e_rem_pio2l.h
+++ b/lib/msun/ld80/e_rem_pio2l.h
@@ -70,10 +70,7 @@ pio2_2t = 6.36831716351095013979e-25L, /* 0xc51701b839a25205.0p-144 */
pio2_3t = -2.75299651904407171810e-37L; /* -0xbb5bf6c7ddd660ce.0p-185 */
#endif
-#ifdef INLINE_REM_PIO2L
-static inline __always_inline
-#endif
-int
+static inline __always_inline int
__ieee754_rem_pio2l(long double x, long double *y)
{
union IEEEl2bits u,u1;
diff --git a/lib/msun/src/s_cosl.c b/lib/msun/src/s_cosl.c
index 77611c1..8d43626 100644
--- a/lib/msun/src/s_cosl.c
+++ b/lib/msun/src/s_cosl.c
@@ -35,7 +35,6 @@ __FBSDID("$FreeBSD$");
#include <float.h>
#include "math.h"
-#define INLINE_REM_PIO2L
#include "math_private.h"
#if LDBL_MANT_DIG == 64
#include "../ld80/e_rem_pio2l.h"
diff --git a/lib/msun/src/s_sinl.c b/lib/msun/src/s_sinl.c
index 19d9572..919deb9 100644
--- a/lib/msun/src/s_sinl.c
+++ b/lib/msun/src/s_sinl.c
@@ -30,7 +30,6 @@ __FBSDID("$FreeBSD$");
#include <float.h>
#include "math.h"
-#define INLINE_REM_PIO2L
#include "math_private.h"
#if LDBL_MANT_DIG == 64
#include "../ld80/e_rem_pio2l.h"
diff --git a/lib/msun/src/s_tanl.c b/lib/msun/src/s_tanl.c
index 3cf4a69..9562cf8 100644
--- a/lib/msun/src/s_tanl.c
+++ b/lib/msun/src/s_tanl.c
@@ -36,7 +36,6 @@ __FBSDID("$FreeBSD$");
#include <float.h>
#include "math.h"
-#define INLINE_REM_PIO2L
#include "math_private.h"
#if LDBL_MANT_DIG == 64
#include "../ld80/e_rem_pio2l.h"
diff --git a/sbin/geom/class/part/geom_part.c b/sbin/geom/class/part/geom_part.c
index 93b28ac..ae9f4b7 100644
--- a/sbin/geom/class/part/geom_part.c
+++ b/sbin/geom/class/part/geom_part.c
@@ -306,7 +306,7 @@ gpart_autofill_resize(struct gctl_req *req)
struct ggeom *gp;
struct gprovider *pp;
off_t last, size, start, new_size;
- off_t lba, new_lba, alignment;
+ off_t lba, new_lba, alignment, offset;
const char *s;
int error, idx;
@@ -341,6 +341,9 @@ gpart_autofill_resize(struct gctl_req *req)
errc(EXIT_FAILURE, error, "Invalid alignment param");
if (alignment == 0)
errx(EXIT_FAILURE, "Invalid alignment param");
+ lba = pp->lg_stripesize / pp->lg_sectorsize;
+ if (lba > 0)
+ alignment = g_lcm(lba, alignment);
}
error = gctl_delete_param(req, "alignment");
if (error)
@@ -356,12 +359,10 @@ gpart_autofill_resize(struct gctl_req *req)
/* no autofill necessary. */
if (alignment == 1)
goto done;
- if (new_size > alignment)
- new_size = ALIGNDOWN(new_size, alignment);
}
+ offset = pp->lg_stripeoffset / pp->lg_sectorsize;
last = (off_t)strtoimax(find_geomcfg(gp, "last"), NULL, 0);
- last = ALIGNDOWN(last, alignment);
LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
s = find_provcfg(pp, "index");
if (s == NULL)
@@ -375,24 +376,32 @@ gpart_autofill_resize(struct gctl_req *req)
s = find_provcfg(pp, "start");
start = (off_t)strtoimax(s, NULL, 0);
s = find_provcfg(pp, "end");
- lba = (off_t)strtoimax(s, NULL, 0) + 1;
+ lba = (off_t)strtoimax(s, NULL, 0);
+ size = lba - start + 1;
- if (lba > last) {
- geom_deletetree(&mesh);
- return (ENOSPC);
+ if (new_size > 0 && new_size <= size) {
+ /* The start offset may be not aligned, so we align the end
+ * offset and then calculate the size.
+ */
+ new_size = ALIGNDOWN(start + offset + new_size,
+ alignment) - start - offset;
+ goto done;
}
- size = lba - start;
- pp = find_provider(gp, lba);
- if (pp == NULL)
- new_size = ALIGNDOWN(last - start + 1, alignment);
- else {
+
+ pp = find_provider(gp, lba + 1);
+ if (pp == NULL) {
+ new_size = ALIGNDOWN(last + offset + 1, alignment) -
+ start - offset;
+ if (new_size < size)
+ return (ENOSPC);
+ } else {
s = find_provcfg(pp, "start");
new_lba = (off_t)strtoimax(s, NULL, 0);
/*
* Is there any free space between current and
* next providers?
*/
- new_lba = ALIGNUP(new_lba, alignment);
+ new_lba = ALIGNDOWN(new_lba + offset, alignment) - offset;
if (new_lba > lba)
new_size = new_lba - start;
else {
@@ -482,10 +491,16 @@ gpart_autofill(struct gctl_req *req)
if (has_size && has_start && !has_alignment)
goto done;
- /* Adjust parameters to offset value for better alignment */
- s = find_provcfg(pp, "offset");
- offset = (s == NULL) ? 0:
- (off_t)strtoimax(s, NULL, 0) / pp->lg_sectorsize;
+ /*
+ * If stripesize is not zero, then recalculate alignment value.
+ * Use LCM from stripesize and user specified alignment.
+ */
+ len = pp->lg_stripesize / pp->lg_sectorsize;
+ if (len > 0 )
+ alignment = g_lcm(len, alignment);
+
+ /* Adjust parameters to stripeoffset */
+ offset = pp->lg_stripeoffset / pp->lg_sectorsize;
start = ALIGNUP(start + offset, alignment);
if (size + offset > alignment)
size = ALIGNDOWN(size + offset, alignment);
diff --git a/sbin/geom/class/part/gpart.8 b/sbin/geom/class/part/gpart.8
index dff881e..940620c 100644
--- a/sbin/geom/class/part/gpart.8
+++ b/sbin/geom/class/part/gpart.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 27, 2011
+.Dd May 30, 2011
.Dt GPART 8
.Os
.Sh NAME
@@ -61,7 +61,8 @@ which is used to define a logical partition.
The
.Dv GEOM_PART_EBR_COMPAT
option enables backward compatibility for partition names
-in the EBR scheme. Also it makes impossible any types of actions
+in the EBR scheme.
+Also it makes impossible any types of actions
with such partitions.
The
.Dv GEOM_PART_GPT
@@ -170,7 +171,7 @@ utility:
.\" ==== SHOW ====
.Nm
.Cm show
-.Op Fl l | Fl r
+.Op Fl l | r
.Op Fl p
.Op Ar geom ...
.\" ==== UNDO ====
@@ -200,11 +201,14 @@ The partition begins on the logical block address given by the
option.
Its size is given by the
.Fl s Ar size
-option. SI unit suffixes are allowed. One or both
+option.
+SI unit suffixes are allowed.
+One or both
.Fl b
and
.Fl s
-options can be omitted. If so they are automatically calculated.
+options can be omitted.
+If so they are automatically calculated.
The type of the partition is given by the
.Fl t Ar type
option.
@@ -399,7 +403,7 @@ about its use.
Recover corrupt partition's scheme metadata on the geom
.Ar geom .
See the section entitled
-.Sx "RECOVERING"
+.Sx RECOVERING
below for the additional information.
.Pp
Additional options include:
@@ -453,7 +457,7 @@ action and given from standard input.
Only partition table may be restored.
This action does not affect content of partitions.
This mean that you should copy your data from backup after restoring
-partition table and write bootcode again if it is needed.
+partition table and write bootcode again if it is needed.
.Pp
Additional options include:
.Bl -tag -width 10n
@@ -474,7 +478,7 @@ about its use.
.It Cm set
Set the named attribute on the partition entry.
See the section entitled
-.Sx "ATTRIBUTES"
+.Sx ATTRIBUTES
below for a list of available attributes.
.Pp
Additional options include:
@@ -511,7 +515,7 @@ action and can be used to undo any changes that have not been committed.
.It Cm unset
Clear the named attribute on the partition entry.
See the section entitled
-.Sx "ATTRIBUTES"
+.Sx ATTRIBUTES
below for a list of available attributes.
.Pp
Additional options include:
@@ -616,75 +620,75 @@ by GPT.
.El
.Sh ATTRIBUTES
The scheme-specific attributes for EBR:
-.Bl -tag -width ".Ar active"
-.It Ar active
+.Bl -tag -width ".Cm active"
+.It Cm active
.El
.Pp
The scheme-specific attributes for GPT:
-.Bl -tag -width ".Ar bootfailed"
-.It Ar bootme
+.Bl -tag -width ".Cm bootfailed"
+.It Cm bootme
When set, the
.Nm gptboot
stage 1 boot loader will try to boot the system from this partition.
Multiple partitions might be marked with the
-.Ar bootme
+.Cm bootme
attribute.
In such scenario the
.Nm gptboot
will try all
-.Ar bootme
+.Cm bootme
partitions one by one, until the next boot stage is successfully entered.
-.It Ar bootonce
+.It Cm bootonce
Setting this attribute automatically sets the
-.Ar bootme
+.Cm bootme
attribute.
When set, the
.Nm gptboot
stage 1 boot loader will try to boot the system from this partition only once.
Partitions with both
-.Ar bootonce
+.Cm bootonce
and
-.Ar bootme
+.Cm bootme
attributes are tried before partitions with only the
-.Ar bootme
+.Cm bootme
attribute.
Before
-.Ar bootonce
+.Cm bootonce
partition is tried, the
.Nm gptboot
removes the
-.Ar bootme
+.Cm bootme
attribute and tries to execute the next boot stage.
If it fails, the
-.Ar bootonce
+.Cm bootonce
attribute that is now alone is replaced with the
-.Ar bootfailed
+.Cm bootfailed
attribute.
If the execution of the next boot stage succeeds, but the system is not fully
booted, the
.Nm gptboot
will look for
-.Ar bootonce
+.Cm bootonce
attributes alone (without the
-.Ar bootme
+.Cm bootme
attribute) on the next system boot and will replace those with the
-.Ar bootfailed
+.Cm bootfailed
attribute.
If the system is fully booted, the
.Pa /etc/rc.d/gptboot
start-up script will look for partition with the
-.Ar bootonce
+.Cm bootonce
attribute alone, will remove the attribute and log that the system was
successfully booted from this partition.
There should be at most one
-.Ar bootonce
+.Cm bootonce
partition when system is successfully booted.
Multiple partitions might be marked with the
-.Ar bootonce
+.Cm bootonce
and
-.Ar bootme
+.Cm bootme
attribute pairs.
-.It Ar bootfailed
+.It Cm bootfailed
This attribute should not be manually managed.
It is managed by the
.Nm gptboot
@@ -692,24 +696,24 @@ stage 1 boot loader and the
.Pa /etc/rc.d/gptboot
start-up script.
This attribute is used to mark partitions that had the
-.Ar bootonce
+.Cm bootonce
attribute set, but we failed to boot from them.
Once we successfully boot, the
.Pa /etc/rc.d/gptboot
script will log all the partitions we failed to boot from and will remove the
-.Ar bootfailed
+.Cm bootfailed
attributes.
.El
.Pp
The scheme-specific attributes for MBR:
-.Bl -tag -width ".Ar active"
-.It Ar active
+.Bl -tag -width ".Cm active"
+.It Cm active
.El
.Pp
The scheme-specific attributes for PC98:
-.Bl -tag -width ".Ar bootable"
-.It Ar active
-.It Ar bootable
+.Bl -tag -width ".Cm bootable"
+.It Cm active
+.It Cm bootable
.El
.Sh OPERATIONAL FLAGS
Actions other than the
@@ -747,7 +751,7 @@ reports about corruption.
Any changes in corrupt table are prohibited except
.Cm destroy
and
-.Cm recover .
+.Cm recover .
.Pp
In case when only first sector is corrupt kernel can not detect GPT even
if partition table is not corrupt.
@@ -771,16 +775,15 @@ GEOM: provider: the secondary GPT table is corrupt or invalid.
GEOM: provider: using the primary only -- recovery suggested.
.Ed
.Pp
-Also
-.Cm gpart
-commands like
-.Cm show ,
-.Cm status
+Also
+.Nm
+commands like
+.Cm show , status
and
.Cm list
will report about corrupt table.
.Pp
-In case when the size of device has changed (e.g. volume expansion) the
+In case when the size of device has changed (e.g.\& volume expansion) the
secondary GPT header will become located not in the last sector.
This is not a metadata corruption, but it is dangerous because any
corruption of the primary GPT will lead to lost of partition table.
@@ -789,29 +792,47 @@ Kernel reports about this problem with message:
GEOM: provider: the secondary GPT header is not in the last LBA.
.Ed
.Pp
-A corrupt table can be recovered with
-.Cm gpart recover
+A corrupt table can be recovered with
+.Cm recover
command.
-This command does reconstruction of corrupt metadata using
+This command does reconstruction of corrupt metadata using
known valid metadata.
Also it can relocate secondary GPT to the end of device.
.Pp
-.Pa NOTE :
-The GEOM class PART can detect the same partition table on different GEOM
+.Em NOTE :
+The GEOM class PART can detect the same partition table on different GEOM
providers and some of them will be marked as corrupt.
Be careful when choosing a provider for recovering.
If you choose incorrectly you can destroy the metadata of another GEOM class,
-e.g. GEOM MIRROR or GEOM LABEL.
+e.g.\& GEOM MIRROR or GEOM LABEL.
+.Sh SYSCTL VARIABLES
+The following
+.Xr sysctl 8
+variables can be used to control the behavior of the
+.Nm PART
+GEOM class.
+The default value is shown next to each variable.
+.Bl -tag -width indent
+.It Va kern.geom.part.check_integrity : No 1
+This variable controls the behaviour of metadata integrity checks.
+When integrity checks are enabled
+.Nm PART
+GEOM class verifies all generic partition parameters that it gets from the
+disk metadata.
+If some inconsistency is detected, partition table will be
+rejected with a diagnostic message:
+.Sy "GEOM_PART: Integrity check failed (provider, scheme)" .
+.El
.Sh EXIT STATUS
Exit status is 0 on success, and 1 if the command fails.
.Sh EXAMPLES
Create GPT scheme on
-.Pa ad0 .
+.Pa ad0 :
.Bd -literal -offset indent
/sbin/gpart create -s GPT ad0
.Ed
.Pp
-Embed GPT bootstrap code into protective MBR.
+Embed GPT bootstrap code into protective MBR:
.Bd -literal -offset indent
/sbin/gpart bootcode -b /boot/pmbr ad0
.Ed
@@ -837,15 +858,19 @@ future need (e.g.\& from a ZFS partition).
.Pp
Create a 512MB-sized
.Cm freebsd-ufs
-partition that would contain UFS where the system boots from.
+partition that would contain UFS where the system boots from:
.Bd -literal -offset indent
/sbin/gpart add -b 162 -s 1048576 -t freebsd-ufs ad0
.Ed
.Pp
Create MBR scheme on
.Pa ada0 ,
-then create 30GB-sized FreeBSD slice, mark it active and
-install boot0 boot manager:
+then create 30GB-sized
+.Fx
+slice, mark it active and
+install
+.Nm boot0
+boot manager:
.Bd -literal -offset indent
/sbin/gpart create -s MBR ada0
/sbin/gpart add -t freebsd -s 30G ada0
@@ -853,7 +878,11 @@ install boot0 boot manager:
/sbin/gpart bootcode -b /boot/boot0 ada0
.Ed
.Pp
-Now create BSD scheme (BSD label) with ability to have up to 20 partitions:
+Now create
+.Bx
+scheme
+.Pf ( Bx
+label) with ability to have up to 20 partitions:
.Bd -literal -offset indent
/sbin/gpart create -s BSD -n 20 ada0s1
.Ed
@@ -864,20 +893,22 @@ Create 1GB-sized UFS partition and 4GB-sized swap partition:
/sbin/gpart add -t freebsd-swap -s 4G ada0s1
.Ed
.Pp
-Install bootstrap code for the BSD label:
+Install bootstrap code for the
+.Bx
+label:
.Bd -literal -offset indent
/sbin/gpart bootcode -b /boot/boot ada0s1
.Ed
.Pp
Create VTOC8 scheme on
-.Pa da0 .
+.Pa da0 :
.Bd -literal -offset indent
/sbin/gpart create -s VTOC8 da0
.Ed
.Pp
Create a 512MB-sized
.Cm freebsd-ufs
-partition that would contain UFS where the system boots from.
+partition that would contain UFS where the system boots from:
.Bd -literal -offset indent
/sbin/gpart add -s 512M -t freebsd-ufs da0
.Ed
@@ -889,29 +920,29 @@ partition that would contain UFS and aligned on 4KB boundaries:
/sbin/gpart add -s 15G -t freebsd-ufs -a 4k da0
.Ed
.Pp
-After having created all required partitions, embed bootstrap code into them.
+After having created all required partitions, embed bootstrap code into them:
.Bd -literal -offset indent
/sbin/gpart bootcode -p /boot/boot1 da0
.Ed
.Pp
Create backup of partition table from
-.Pa da0
+.Pa da0 :
.Bd -literal -offset indent
/sbin/gpart backup da0 > da0.backup
.Ed
.Pp
Restore partition table from backup to
-.Pa da0
+.Pa da0 :
.Bd -literal -offset indent
/sbin/gpart restore -l da0 < /mnt/da0.backup
.Ed
.Pp
-Clone partition table from
-.Pa ada0
-to
-.Pa ada1
-and
-.Pa ada2
+Clone partition table from
+.Pa ada0
+to
+.Pa ada1
+and
+.Pa ada2 :
.Bd -literal -offset indent
/sbin/gpart backup ada0 | /sbin/gpart restore -F ada1 ada2
.Ed
diff --git a/sbin/hastd/primary.c b/sbin/hastd/primary.c
index 1f6585c..abda5cb 100644
--- a/sbin/hastd/primary.c
+++ b/sbin/hastd/primary.c
@@ -1243,7 +1243,7 @@ local_send_thread(void *arg)
ggio->gctl_offset + res->hr_localoff);
if (ret == ggio->gctl_length)
hio->hio_errors[ncomp] = 0;
- else {
+ else if (!ISSYNCREQ(hio)) {
/*
* If READ failed, try to read from remote node.
*/
diff --git a/sbin/hastd/proto_common.c b/sbin/hastd/proto_common.c
index 183b4e4..1f541da 100644
--- a/sbin/hastd/proto_common.c
+++ b/sbin/hastd/proto_common.c
@@ -194,6 +194,8 @@ int
proto_common_recv(int sock, unsigned char *data, size_t size, int *fdp)
{
ssize_t done;
+ size_t total_done, recvsize;
+ unsigned char *dp;
PJDLOG_ASSERT(sock >= 0);
@@ -210,9 +212,19 @@ proto_common_recv(int sock, unsigned char *data, size_t size, int *fdp)
PJDLOG_ASSERT(data != NULL);
PJDLOG_ASSERT(size > 0);
+ total_done = 0;
+ dp = data;
do {
- done = recv(sock, data, size, MSG_WAITALL);
- } while (done == -1 && errno == EINTR);
+ recvsize = size - total_done;
+ recvsize = recvsize < MAX_SEND_SIZE ? recvsize : MAX_SEND_SIZE;
+ done = recv(sock, dp, recvsize, MSG_WAITALL);
+ if (done == -1 && errno == EINTR)
+ continue;
+ if (done <= 0)
+ break;
+ total_done += done;
+ dp += done;
+ } while (total_done < size);
if (done == 0) {
return (ENOTCONN);
} else if (done < 0) {
diff --git a/sbin/ifconfig/Makefile b/sbin/ifconfig/Makefile
index 77491f2..461de71 100644
--- a/sbin/ifconfig/Makefile
+++ b/sbin/ifconfig/Makefile
@@ -15,10 +15,16 @@ SRCS= ifconfig.c # base support
# of the toolchain.
#
SRCS+= af_link.c # LLC support
+.if ${MK_INET_SUPPORT} != "no"
SRCS+= af_inet.c # IPv4 support
+.endif
+.if ${MK_INET6_SUPPORT} != "no"
SRCS+= af_inet6.c # IPv6 support
+.endif
SRCS+= af_atalk.c # AppleTalk support
+.if ${MK_INET6_SUPPORT} != "no"
SRCS+= af_nd6.c # ND6 support
+.endif
SRCS+= ifclone.c # clone device support
SRCS+= ifmac.c # MAC support
@@ -38,6 +44,12 @@ SRCS+= ifpfsync.c # pfsync(4) support
SRCS+= ifbridge.c # bridge support
SRCS+= iflagg.c # lagg support
+.if ${MK_INET6_SUPPORT} != "no"
+CFLAGS+= -DINET6
+.endif
+.if ${MK_INET_SUPPORT} != "no"
+CFLAGS+= -DINET
+.endif
.if ${MK_IPX_SUPPORT} != "no" && !defined(RELEASE_CRUNCH)
SRCS+= af_ipx.c # IPX support
DPADD+= ${LIBIPX}
diff --git a/sbin/ifconfig/af_inet.c b/sbin/ifconfig/af_inet.c
index 2e27114..6b4d735 100644
--- a/sbin/ifconfig/af_inet.c
+++ b/sbin/ifconfig/af_inet.c
@@ -200,5 +200,7 @@ static struct afswtch af_inet = {
static __constructor void
inet_ctor(void)
{
+ if (!feature_present("inet"))
+ return;
af_register(&af_inet);
}
diff --git a/sbin/ifconfig/af_inet6.c b/sbin/ifconfig/af_inet6.c
index 3418ba5..7fdca0d 100644
--- a/sbin/ifconfig/af_inet6.c
+++ b/sbin/ifconfig/af_inet6.c
@@ -545,6 +545,9 @@ inet6_ctor(void)
#define N(a) (sizeof(a) / sizeof(a[0]))
size_t i;
+ if (!feature_present("inet6"))
+ return;
+
for (i = 0; i < N(inet6_cmds); i++)
cmd_register(&inet6_cmds[i]);
af_register(&af_inet6);
diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8
index e28178a..45cf59b 100644
--- a/sbin/ifconfig/ifconfig.8
+++ b/sbin/ifconfig/ifconfig.8
@@ -28,7 +28,7 @@
.\" From: @(#)ifconfig.8 8.3 (Berkeley) 1/5/94
.\" $FreeBSD$
.\"
-.Dd March 20, 2011
+.Dd May 31, 2011
.Dt IFCONFIG 8
.Os
.Sh NAME
@@ -42,7 +42,7 @@
.Op Fl n
.Ar interface
.Op Cm create
-.Op Ar address_family
+.Ar address_family
.Oo
.Ar address
.Op Ar dest_address
@@ -165,8 +165,10 @@ and
.Dq link .
.\" and
.\" .Dq ns .
-The default is
-.Dq inet .
+The default if available is
+.Dq inet
+or otherwise
+.Dq link .
.Dq ether
and
.Dq lladdr
diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c
index 7c5d351..2963b9f 100644
--- a/sbin/ifconfig/ifconfig.c
+++ b/sbin/ifconfig/ifconfig.c
@@ -220,8 +220,10 @@ main(int argc, char *argv[])
ifindex = 0;
if (argc == 1) {
afp = af_getbyname(*argv);
- if (afp == NULL)
+ if (afp == NULL) {
+ warnx("Address family '%s' unknown.", *argv);
usage();
+ }
if (afp->af_name != NULL)
argc--, argv++;
/* leave with afp non-zero */
@@ -484,7 +486,28 @@ ifconfig(int argc, char *const *argv, int iscreate, const struct afswtch *uafp)
int s;
strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
- afp = uafp != NULL ? uafp : af_getbyname("inet");
+ afp = NULL;
+ if (uafp != NULL)
+ afp = uafp;
+ /*
+ * This is the historical "accident" allowing users to configure IPv4
+ * addresses without the "inet" keyword which while a nice feature has
+ * proven to complicate other things. We cannot remove this but only
+ * make sure we will never have a similar implicit default for IPv6 or
+ * any other address familiy. We need a fallback though for
+ * ifconfig IF up/down etc. to work without INET support as people
+ * never used ifconfig IF link up/down, etc. either.
+ */
+#ifdef INET
+ if (afp == NULL && feature_present("inet"))
+ afp = af_getbyname("inet");
+#endif
+ if (afp == NULL)
+ afp = af_getbyname("link");
+ if (afp == NULL) {
+ warnx("Please specify an address_family.");
+ usage();
+ }
top:
ifr.ifr_addr.sa_family =
afp->af_af == AF_LINK || afp->af_af == AF_UNSPEC ?
diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8
index 710996b..fa9c543 100644
--- a/sbin/ipfw/ipfw.8
+++ b/sbin/ipfw/ipfw.8
@@ -1,7 +1,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd July 27, 2010
+.Dd May 30, 2011
.Dt IPFW 8
.Os
.Sh NAME
@@ -871,13 +871,16 @@ for more information on
and
.Cm ngtee
actions.
-.It Cm setfib Ar fibnum
+.It Cm setfib Ar fibnum | tablearg
The packet is tagged so as to use the FIB (routing table)
.Ar fibnum
in any subsequent forwarding decisions.
Initially this is limited to the values 0 through 15, see
.Xr setfib 1 .
Processing continues at the next rule.
+It is possible to use the
+.Cm tablearg
+keyword with a setfib. If tablearg value is not within compiled FIB range packet fib is set to 0.
.It Cm reass
Queue and reassemble ip fragments.
If the packet is not fragmented, counters are updated and processing continues with the next rule.
@@ -1711,7 +1714,7 @@ is used.
The
.Cm tablearg
argument can be used with the following actions:
-.Cm nat, pipe , queue, divert, tee, netgraph, ngtee, fwd, skipto
+.Cm nat, pipe , queue, divert, tee, netgraph, ngtee, fwd, skipto, setfib,
action parameters:
.Cm tag, untag,
rule options:
diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c
index ad871fe..3e85de3 100644
--- a/sbin/ipfw/ipfw2.c
+++ b/sbin/ipfw/ipfw2.c
@@ -2835,14 +2835,19 @@ chkarg:
size_t intsize = sizeof(int);
action->opcode = O_SETFIB;
- NEED1("missing fib number");
- action->arg1 = strtoul(*av, NULL, 10);
- if (sysctlbyname("net.fibs", &numfibs, &intsize, NULL, 0) == -1)
- errx(EX_DATAERR, "fibs not suported.\n");
- if (action->arg1 >= numfibs) /* Temporary */
- errx(EX_DATAERR, "fib too large.\n");
- av++;
- break;
+ NEED1("missing fib number");
+ if (_substrcmp(*av, "tablearg") == 0) {
+ action->arg1 = IP_FW_TABLEARG;
+ } else {
+ action->arg1 = strtoul(*av, NULL, 10);
+ if (sysctlbyname("net.fibs", &numfibs, &intsize,
+ NULL, 0) == -1)
+ errx(EX_DATAERR, "fibs not suported.\n");
+ if (action->arg1 >= numfibs) /* Temporary */
+ errx(EX_DATAERR, "fib too large.\n");
+ }
+ av++;
+ break;
}
case TOK_REASS:
diff --git a/sbin/setkey/setkey.8 b/sbin/setkey/setkey.8
index 7103e1f..f53683e 100644
--- a/sbin/setkey/setkey.8
+++ b/sbin/setkey/setkey.8
@@ -441,13 +441,14 @@ protocols other than TCP, UDP and ICMP may not be suitable to use with IPsec.
.It Ar policy
.Ar policy
is expressed in one of the following three formats:
-.Bd -ragged -offset indent
+.Pp
+.Bl -tag -compact
.It Fl P Ar direction Li discard
.It Fl P Ar direction Li none
.It Xo Fl P Ar direction Li ipsec
.Ar protocol/mode/src-dst/level Op ...
.Xc
-.Ed
+.El
.Pp
The direction of a policy must be specified as
one of:
diff --git a/sbin/umount/umount.8 b/sbin/umount/umount.8
index 91231a7..cb3a97b 100644
--- a/sbin/umount/umount.8
+++ b/sbin/umount/umount.8
@@ -28,7 +28,7 @@
.\" @(#)umount.8 8.2 (Berkeley) 5/8/95
.\" $FreeBSD$
.\"
-.Dd July 18, 2003
+.Dd May 31, 2011
.Dt UMOUNT 8
.Os
.Sh NAME
@@ -78,6 +78,9 @@ The file system is forcibly unmounted.
Active special devices continue to work,
but all other files return errors if further accesses are attempted.
The root file system cannot be forcibly unmounted.
+For NFS, a forced dismount can take up to 1 minute or more to
+complete against an unresponsive server and may throw away
+data not yet written to the server for this case.
.It Fl h Ar host
Only file systems mounted from the specified host will be
unmounted.
diff --git a/sbin/umount/umount.c b/sbin/umount/umount.c
index 911666f..9b75449 100644
--- a/sbin/umount/umount.c
+++ b/sbin/umount/umount.c
@@ -90,9 +90,6 @@ main(int argc, char *argv[])
struct statfs *mntbuf, *sfs;
struct addrinfo hints;
- /* Start disks transferring immediately. */
- sync();
-
all = errs = 0;
while ((ch = getopt(argc, argv, "AaF:fh:t:v")) != -1)
switch (ch) {
@@ -127,6 +124,10 @@ main(int argc, char *argv[])
argc -= optind;
argv += optind;
+ /* Start disks transferring immediately. */
+ if ((fflag & MNT_FORCE) == 0)
+ sync();
+
if ((argc == 0 && !all) || (argc != 0 && all))
usage();
diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile
index f71da84..7ccccfb 100644
--- a/share/man/man4/Makefile
+++ b/share/man/man4/Makefile
@@ -46,7 +46,9 @@ MAN= aac.4 \
atapicam.4 \
ataraid.4 \
ath.4 \
+ ath_ahb.4 \
ath_hal.4 \
+ ath_pci.4 \
atkbd.4 \
atkbdc.4 \
${_atp.4} \
@@ -473,6 +475,7 @@ MAN= aac.4 \
ukbd.4 \
ulpt.4 \
umass.4 \
+ umcs.4 \
umct.4 \
umodem.4 \
ums.4 \
diff --git a/share/man/man4/ath.4 b/share/man/man4/ath.4
index 7579546..fadf192 100644
--- a/share/man/man4/ath.4
+++ b/share/man/man4/ath.4
@@ -40,6 +40,7 @@ place the following lines in your
kernel configuration file:
.Bd -ragged -offset indent
.Cd "device ath"
+.Cd "device ath_pci"
.Cd "device ath_hal"
.Cd "options AH_SUPPORT_AR5416"
.Cd "device ath_rate_sample"
@@ -51,6 +52,7 @@ module at boot time, place the following line in
.Xr loader.conf 5 :
.Bd -literal -offset indent
if_ath_load="YES"
+if_ath_pci_load="YES"
.Ed
.Sh DESCRIPTION
The
@@ -64,6 +66,19 @@ Supported features include 802.11 and 802.3 frames, power management, BSS,
IBSS, MBSS, TDMA, and host-based access point operation modes.
All host/device interaction is via DMA.
.Pp
+Please note that from FreeBSD-9.0, the
+.Nm
+driver does not include the PCI/PCIe bus glue.
+The same driver supports multiple underlying bus types, including PCI/PCIe,
+but also embedded (AHB) and USB in the future.
+.Pp
+To enable use for PCI/PCIe systems, see the
+.Xr ath_pci 4
+driver.
+For embedded systems which use the AHB to connect the wireless MAC, see the
+.Xr ath_ahb 4
+driver.
+.Pp
The
.Nm
driver encapsulates all IP and ARP traffic as 802.11 frames, however
diff --git a/share/man/man4/ath_ahb.4 b/share/man/man4/ath_ahb.4
new file mode 100644
index 0000000..6688dc2
--- /dev/null
+++ b/share/man/man4/ath_ahb.4
@@ -0,0 +1,60 @@
+.\"-
+.\" Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd
+.\" All rights reserved.
+.\""
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer,
+.\" without modification.
+.\" 2. Redistributions in binary form must reproduce at minimum a disclaimer
+.\" similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+.\" redistribution must be conditioned upon including a substantially
+.\" similar Disclaimer requirement for further binary redistribution.
+.\"
+.\" NO WARRANTY
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+.\" LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+.\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+.\" THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+.\"
+.\" $FreeBSD$
+.\"/
+.Dd May 30, 2011
+.Dt ATH_AHB 4
+.Os
+.Sh NAME
+.Nm ath_ahb
+.Nd "Atheros AHB device glue"
+.Sh SYNOPSIS
+.Cd "device ath_ahb"
+.Sh DESCRIPTION
+This module provides the AHB bus glue needed for the devices supported
+by the
+.Xr ath 4
+and
+.Xr ath_hal 4
+drivers.
+.Pp
+This is only relevant for embedded System-on-Chip (SoC) devices such as
+the Atheros AR913x series, which include an Atheros wireless MAC on-die.
+.Sh SEE ALSO
+.Xr ath 4
+.Xr ath_hal 4
+.Sh HISTORY
+The
+.Nm
+module first appeared in
+.Fx 9.0 .
+.Sh BUGS
+See
+.Xr ath 4
+for known bugs.
diff --git a/share/man/man4/ath_hal.4 b/share/man/man4/ath_hal.4
index 4422a0d..c1ad779 100644
--- a/share/man/man4/ath_hal.4
+++ b/share/man/man4/ath_hal.4
@@ -51,14 +51,17 @@ or
.\".Cd "device ath_ar5312"
.\".Cd "device ath_rf2136"
.\".Cd "device ath_rf2137"
+.Cd "device ath_ar9130"
.Cd "device ath_ar9160"
.Cd "device ath_ar9280"
+.Cd "device ath_ar9285"
+.Cd "device ath_ar9287"
.Cd "options AH_SUPPORT_AR5416"
.Sh DESCRIPTION
The hal provides hardware support for wireless network adapters based on
the Atheros AR5210, AR5211, AR5212, AR5213, AR2413, AR2417, AR2425,
-AR5413, AR5416, AR5418, AR5424, AR9160, AR9220, AR9280, and AR9285 chips
-(and companion RF/baseband parts).
+AR5413, AR5416, AR5418, AR5424, AR9160, AR9220, AR9280, AR9285 and AR9287
+chips (and companion RF/baseband parts).
This code is part of the
.Xr ath 4
driver but configured separately to allow fine-grained control
@@ -66,14 +69,15 @@ over the set of chips supported.
Selecting
.Nm
enables support for all PCI and Cardbus devices.
-Note this includes AR5416, AR9160, AR9220, AR9280 and AR9285 devices
-and must be accompanied by the
+Note this includes AR5416, AR5418, AR9130, AR9160, AR9220, AR9280, AR9285
+and AR9287 devices and must be accompanied by the
AH_SUPPORT_AR5416
option to enable the extended hardware descriptor format used by
AR5416 and later devices.
.Pp
Some devices come in Cardbus/MiniPCI/PCI format.
-Others (AR9280, AR9285) come in PCIe, Mini-PCIe or ExpressCard format.
+Others (for example AR2413, AR2427, AR5418, AR9280, AR9285, AR9287) come in
+PCIe, Mini-PCIe or ExpressCard format.
.Pp
Historically this code has been released in a binary-only form
and packaged as a separate module.
diff --git a/share/man/man4/ath_pci.4 b/share/man/man4/ath_pci.4
new file mode 100644
index 0000000..814e535
--- /dev/null
+++ b/share/man/man4/ath_pci.4
@@ -0,0 +1,57 @@
+.\"-
+.\" Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd
+.\" All rights reserved.
+.\""
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer,
+.\" without modification.
+.\" 2. Redistributions in binary form must reproduce at minimum a disclaimer
+.\" similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+.\" redistribution must be conditioned upon including a substantially
+.\" similar Disclaimer requirement for further binary redistribution.
+.\"
+.\" NO WARRANTY
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+.\" LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+.\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+.\" THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+.\"
+.\" $FreeBSD$
+.\"/
+.Dd May 30, 2011
+.Dt ATH_PCI 4
+.Os
+.Sh NAME
+.Nm ath_pci
+.Nd "Atheros PCI device glue"
+.Sh SYNOPSIS
+.Cd "device ath_pci"
+.Sh DESCRIPTION
+This module provides the PCI/PCIe bus glue needed for the devices supported
+by the
+.Xr ath 4
+and
+.Xr ath_hal 4
+drivers.
+.Sh SEE ALSO
+.Xr ath 4
+.Xr ath_hal 4
+.Sh HISTORY
+The
+.Nm
+module first appeared in
+.Fx 9.0 .
+.Sh BUGS
+See
+.Xr ath 4
+for known bugs.
diff --git a/share/man/man4/bwn.4 b/share/man/man4/bwn.4
index 81452c7..a2ff5c4 100644
--- a/share/man/man4/bwn.4
+++ b/share/man/man4/bwn.4
@@ -142,9 +142,6 @@ The
.Nm
driver first appeared in
.Fx 8.1 .
-.Sh CAVEATS
-Some LP PHY devices have DMA operation problems that in that case try to
-use PIO mode.
.Sh AUTHORS
.An -nosplit
The
@@ -155,3 +152,6 @@ driver was written by
.\".Sh BUGS
.\"Some card based on the BCM4306 and BCM4309 chips do not work properly
.\"on channel 1, 2 and 3.
+.Sh CAVEATS
+Some LP PHY devices have DMA operation problems that in that case try to
+use PIO mode.
diff --git a/share/man/man4/em.4 b/share/man/man4/em.4
index ecde44d..842f9ee 100644
--- a/share/man/man4/em.4
+++ b/share/man/man4/em.4
@@ -227,6 +227,20 @@ If
is non-zero, this tunable limits the maximum delay in which a transmit
interrupt is generated.
.El
+.Sh FILES
+.Bl -tag -width /dev/led/em*
+.It Pa /dev/led/em*
+identification LED device nodes
+.El
+.Sh EXAMPLES
+Make the identification LED of em0 blink:
+.Pp
+.Dl "echo f2 > /dev/led/em0"
+.Pp
+Turn the identification LED of em0 off again:
+.Pp
+.Dl "echo 0 > /dev/led/em0"
+.Pp
.Sh DIAGNOSTICS
.Bl -diag
.It "em%d: Unable to allocate bus resource: memory"
@@ -246,20 +260,6 @@ If an issue is identified with the released source code on the supported kernel
with a supported adapter, email the specific information related to the
issue to
.Aq freebsdnic@mailbox.intel.com .
-.Sh FILES
-.Bl -tag -width /dev/led/em*
-.It Pa /dev/led/em*
-identification LED device nodes
-.El
-.Sh EXAMPLES
-Make the identification LED of em0 blink:
-.Pp
-.Dl "echo f2 > /dev/led/em0"
-.Pp
-Turn the identification LED of em0 off again:
-.Pp
-.Dl "echo 0 > /dev/led/em0"
-.Pp
.Sh SEE ALSO
.Xr altq 4 ,
.Xr arp 4 ,
diff --git a/share/man/man4/igb.4 b/share/man/man4/igb.4
index 65012d2..70db340 100644
--- a/share/man/man4/igb.4
+++ b/share/man/man4/igb.4
@@ -161,6 +161,20 @@ The minimum is 80, and the maximum is 4096.
If set to 1, enable Adaptive Interrupt Moderation.
The default is to enable Adaptive Interrupt Moderation.
.El
+.Sh FILES
+.Bl -tag -width /dev/led/igb*
+.It Pa /dev/led/igb*
+identification LED device nodes
+.El
+.Sh EXAMPLES
+Make the identification LED of igb0 blink:
+.Pp
+.Dl "echo f2 > /dev/led/igb0"
+.Pp
+Turn the identification LED of igb0 off again:
+.Pp
+.Dl "echo 0 > /dev/led/igb0"
+.Pp
.Sh DIAGNOSTICS
.Bl -diag
.It "igb%d: Unable to allocate bus resource: memory"
@@ -180,20 +194,6 @@ If an issue is identified with the released source code on the supported kernel
with a supported adapter, email the specific information related to the
issue to
.Aq freebsdnic@mailbox.intel.com .
-.Sh FILES
-.Bl -tag -width /dev/led/igb*
-.It Pa /dev/led/igb*
-identification LED device nodes
-.El
-.Sh EXAMPLES
-Make the identification LED of igb0 blink:
-.Pp
-.Dl "echo f2 > /dev/led/igb0"
-.Pp
-Turn the identification LED of igb0 off again:
-.Pp
-.Dl "echo 0 > /dev/led/igb0"
-.Pp
.Sh SEE ALSO
.Xr altq 4 ,
.Xr arp 4 ,
diff --git a/share/man/man4/mps.4 b/share/man/man4/mps.4
index c6dd527..e22bf15 100644
--- a/share/man/man4/mps.4
+++ b/share/man/man4/mps.4
@@ -143,6 +143,19 @@ Enable prints for controller events.
.Xr sa 4 ,
.Xr scsi 4 ,
.Xr targ 4
+.Sh HISTORY
+The
+.Nm
+driver first appeared in
+.Fx 9.0 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+driver was originally written by
+.An Scott Long Aq scottl@FreeBSD.org .
+This man page was written by
+.An Ken Merry Aq ken@FreeBSD.org .
.Sh BUGS
This driver is still in development, it has only been tested on the amd64
architecture and has some known shortcomings:
@@ -158,16 +171,3 @@ times, without user intervention.
.It
The error recovery code isn't complete.
.El
-.Sh HISTORY
-The
-.Nm
-driver first appeared in
-.Fx 9.0 .
-.Sh AUTHORS
-.An -nosplit
-The
-.Nm
-driver was originally written by
-.An Scott Long Aq scottl@FreeBSD.org .
-This man page was written by
-.An Ken Merry Aq ken@FreeBSD.org .
diff --git a/share/man/man4/stf.4 b/share/man/man4/stf.4
index 660e33e..fb2617a 100644
--- a/share/man/man4/stf.4
+++ b/share/man/man4/stf.4
@@ -1,6 +1,7 @@
.\" $KAME: stf.4,v 1.35 2001/05/02 06:24:49 itojun Exp $
.\"
.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+.\" Copyright (c) 2010 Hiroki Sato <hrs@FreeBSD.org>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -29,7 +30,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd April 27, 2001
+.Dd September 23, 2010
.Dt STF 4
.Os
.Sh NAME
@@ -42,21 +43,11 @@ tunnel interface
.Sh DESCRIPTION
The
.Nm
-interface supports
-.Dq 6to4
-IPv6 in IPv4 encapsulation.
-It can tunnel IPv6 traffic over IPv4, as specified in
-.Li RFC3056 .
-.Pp
-For ordinary nodes in 6to4 site, you do not need
-.Nm
-interface.
-The
-.Nm
-interface is necessary for site border router
-(called
-.Dq 6to4 router
-in the specification).
+interface supports IPv6 in IPv4 encapsulation by
+tunneling IPv6 traffic over IPv4, as specified in
+.Li RFC3056 Pq 6to4
+and
+.Li RFC5569 Pq 6rd .
.Pp
Each
.Nm
@@ -72,12 +63,28 @@ variable in
.Pp
Due to the way 6to4 protocol is specified,
.Nm
-interface requires certain configuration to work properly.
+interface requires certain configuration to work properly. Two
+different protocols defined in RFC3056 and RFC5569 are basically the
+same as each other except for address handling, so
+.Nm
+decides its behavior based on the configured IPv6 addresses as
+explained in the following.
+The
+.Nm
+interface can be configured with multiple IPv6 addresses including
+both 6to4 and 6rd.
+.Sh RFC3056 (a.k.a. 6to4)
Single
-(no more than 1)
-valid 6to4 address needs to be configured to the interface.
-.Dq A valid 6to4 address
-is an address which has the following properties.
+.Pq no more than 1 valid 6to4 address needs to be configured to the interface.
+.Dq a valid 6to4 address
+is an address which has the following properties. For ordinary nodes
+in 6to4 site, you do not need
+.Nm
+interface; it is necessary only for site border router
+(called
+.Dq 6to4 router
+in the specification).
+.Pp
If any of the following properties are not satisfied,
.Nm
raises runtime error on packet transmission.
@@ -110,6 +117,78 @@ you may want to configure IPv6 prefix length as
.Nm
interface will check the IPv4 source address on packets,
if the IPv6 prefix length is larger than 16.
+.Sh RFC5569 (a.k.a. 6rd)
+The
+.Nm
+interface works in the 6rd mode when one or more IPv6 addresses that
+consists of an IPv6 prefix and 32-bit IPv4 part with a prefix length
+equal to or shorter than 64. In 6rd protocol, an IPv6 address
+.Li 2001:db8:c000:205::1/32
+means the following, for example:
+.Bl -bullet
+.It
+The 6rd relay prefix is
+.Li 2001:db8::/32 .
+.It
+The 6rd router's IPv4 address is
+.Li 192.0.2.5 .
+.El
+.Pp
+As you can see the IPv4 address is embedded in the IPv6 address just
+after the prefix. While you can choose an IPv6 prefix length other
+than 32, it must be from 0 to 32.
+.Pp
+Assuming this address is configured on the
+.Nm
+interface, it does the following:
+.Bl -bullet
+.It
+An incoming IPv6 packet on
+.Nm
+will be encapsuled in an IPv4 packet with the source address
+.Li 192.0.2.5
+and then the IPv4 packet is delivered based on the IPv4 routing table.
+The IPv4 destination address is calculated from the destination
+address of the original IPv6 packet in the same way as the source.
+.It
+An incoming IPv4 packet which encapsules an IPv6 packet whose
+destination address matches a 6rd prefix with embedded IPv4 address
+configured on the
+.Nm
+interface, the IPv6 packet will be decapsulated and delivered based on
+the IPv6 routing table. Note that
+.Nm
+interface normally has a route which covers whole range of a 6rd relay
+prefix, the delivered IPv6 packet can return to
+.Nm
+if there is no more specific route. In that case, the returned packet
+will be discarded silently.
+.El
+.\" XXX: example configuration will be added
+.\" .Pp
+.\" By using this interface, you can configure a 6rd domain. For simplicity,
+.\" we assume the following here:
+.\" .Bl -bullet
+.\" .It
+.\" A 6rd Customer, who has an IPv6/IPv4 LAN and an IPv4-only access
+.\" toward network of his Internet Service Provider. The Customer has
+.\" a router called
+.\" .Dq CE Pq Customer Edge
+.\" Router, which can communicate between his LAN and the ISP over IPv4
+.\" and encapsulate
+.\" his networks.
+.\" .It
+.\" A 6rd Provider, who provides IPv6 Internet reachability by using 6rd
+.\" protocol. The Provider offers access to a router called
+.\" .Dq PE Pq Provider Edge
+.\" Router, which can communicate with
+.\" .El
+.\" .Pp
+.\" A 6rd customer
+.\" needs to configure
+.\" .Nm
+.\" on his CE (Customer Edge) router.
+.Sh Other Functionality of the Interface
.Pp
.Nm
can be configured to be ECN friendly.
@@ -147,9 +226,6 @@ Packets with IPv4 multicast address as outer IPv4 source/destination
Packets with limited broadcast address as outer IPv4 source/destination
.Pq Li 255.0.0.0/8
.It
-Packets with private address as outer IPv4 source/destination
-.Pq Li 10.0.0.0/8 , 172.16.0.0/12 , 192.168.0.0/16
-.It
Packets with subnet broadcast address as outer IPv4 source/destination.
The check is made against subnet broadcast addresses for
all of the directly connected subnets.
@@ -164,6 +240,11 @@ The same set of rules are applied against the IPv4 address embedded into
inner IPv6 address, if the IPv6 address matches 6to4 prefix.
.El
.Pp
+In addition to them, packets with private address as outer IPv4
+source/destination
+.Pq Li 10.0.0.0/8 , 172.16.0.0/12 , 192.168.0.0/16
+are filtered out only in the 6to4 mode.
+.Pp
It is recommended to filter/audit
incoming IPv4 packet with IP protocol number 41, as necessary.
It is also recommended to filter/audit encapsulated IPv6 packets as well.
diff --git a/share/man/man4/ucom.4 b/share/man/man4/ucom.4
index ff891cb..8898872 100644
--- a/share/man/man4/ucom.4
+++ b/share/man/man4/ucom.4
@@ -78,6 +78,7 @@ multiple external ports.
.Xr uark 4 ,
.Xr uchcom 4 ,
.Xr uftdi 4 ,
+.Xr umcs 4 ,
.Xr umct 4 ,
.Xr umodem 4 ,
.Xr uplcom 4 ,
diff --git a/share/man/man4/uep.4 b/share/man/man4/uep.4
index 62dc51a..74b65f3 100644
--- a/share/man/man4/uep.4
+++ b/share/man/man4/uep.4
@@ -57,11 +57,6 @@ To get mouse working in
.Xr X 7 ,
one needs to install
.Pa ports/x11-drivers/xf86-input-egalax .
-.Sh BUGS
-.Nm
-can't act like
-.Xr sysmouse 4 ,
-since the latter does not support absolute motion events.
.Sh FILES
.Nm
creates a blocking pseudo\-device file,
@@ -77,3 +72,8 @@ The
.Nm
driver was written by
.An Gleb Smirnoff Aq glebius@FreeBSD.org
+.Sh BUGS
+.Nm
+can't act like
+.Xr sysmouse 4 ,
+since the latter does not support absolute motion events.
diff --git a/share/man/man4/umcs.4 b/share/man/man4/umcs.4
new file mode 100644
index 0000000..f57b084
--- /dev/null
+++ b/share/man/man4/umcs.4
@@ -0,0 +1,97 @@
+.\"
+.\" Copyright (c) 2010 Lev Serebryakov <lev@FreeBSD.org>.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Lennart Augustsson.
+.\"
+.\" 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 NETBSD FOUNDATION, INC. 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 FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd December 10, 2010
+.Dt UMCS 4
+.Os
+.Sh NAME
+.Nm umcs
+.Nd USB support for serial adapters based on the MCS7820 and MCS7840 chips
+.Sh SYNOPSIS
+To compile this driver into the kernel,
+place the following lines in your
+kernel configuration file:
+.Bd -ragged -offset indent
+.Cd "device umcs"
+.Ed
+.Pp
+Alternatively, to load the driver as a
+module at boot time, place the following line in
+.Xr loader.conf 5 :
+.Bd -literal -offset indent
+umcs_load="YES"
+.Ed
+.Sh DESCRIPTION
+The
+.Nm
+driver provides support for various multiport serial adapters based on the MosCom
+MCS7820 and MCS7840 chips. They are 2- or 4-port adapters with full-featured
+16550-compatible UARTs and very flexible baud generators. Also, these chips
+support RS422/RS485 and IrDA oprations.
+.Pp
+The device is accessed through the
+.Xr ucom 4
+driver which makes it behave like a
+.Xr tty 4 .
+.Pp
+Different ports on device are presented as sub-units, like
+.Pa /dev/ttyU0.1
+and
+.Pa /dev/ttyU0.2
+.Sh HARDWARE
+The
+.Nm
+driver was tested on the following adapters:
+.Pp
+.Bl -bullet -compact
+.It
+ST Lab U-360 two-port serial USB adapter
+.It
+ST Lab U-400 four-port serial USB adapter
+.El
+.Sh SEE ALSO
+.Xr tty 4 ,
+.Xr ucom 4 ,
+.Xr usb 4
+.Sh BUGS
+This driver doesn't support access to any fine tunes of
+chip, like RS522/RS485 mode, non-standard baudrates, etc.
+.Sh HISTORY
+The
+.Nm
+driver
+appeared in ports since December of 2010.
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+driver was written by
+.An Lev Serebryakov
+.Aq lev@FreeBSD.org .
diff --git a/share/man/man4/vge.4 b/share/man/man4/vge.4
index ae0206a..3ab9bce 100644
--- a/share/man/man4/vge.4
+++ b/share/man/man4/vge.4
@@ -30,7 +30,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd November 23, 2010
+.Dd May 29, 2011
.Dt VGE 4
.Os
.Sh NAME
@@ -66,13 +66,14 @@ The MAC supports TCP/IP hardware
checksums (IPv4 only), TCP large send, VLAN tag insertion and stripping,
as well as VLAN filtering, a 64-entry CAM filter and a 64-entry VLAN filter,
64-bit multicast hash filter, 4 separate transmit DMA queues, flow control
-and jumbo frames up to 16K in size.
+and jumbo frames (not on VT6130/VT6132) up to 16K in size.
The Velocity family controllers have a 16K receive FIFO and 48K transmit FIFO.
.Pp
The
.Nm
driver takes advantage of the controller's checksum offload and VLAN
-tagging features, as well as the jumbo frame and CAM filter support.
+tagging features, as well as the jumbo frame (except VT6130/VT6132) and CAM
+filter support.
The CAM filter is used for multicast address filtering to provide
64 perfect multicast address filter support.
If it is necessary for the interface to join more than 64 multicast
@@ -81,6 +82,8 @@ groups, the driver will switch over to using the hash filter.
The jumbo frame support can be enabled by setting the interface MTU
to any value larger than the default of 1500 bytes, up to a maximum
of 9000 bytes.
+Jumbo frames are disabled on the VT6130/VT6132 controllers because the TX
+MAC will hang when trying to send a frame that is larger than 4K.
The receive and transmit checksum offload support
can be toggled on and off using the
.Xr ifconfig 8
diff --git a/share/man/man7/c99.7 b/share/man/man7/c99.7
index 1b76442..8c7d5e2 100644
--- a/share/man/man7/c99.7
+++ b/share/man/man7/c99.7
@@ -23,7 +23,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd June 17, 2010
+.Dd May 30, 2011
.Dt C 7
.Os
.Sh NAME
@@ -122,7 +122,7 @@ Support for variable length arrays
New high-precision integer type named long long int, and other integer types
defined in stdint.h
.It
-New boolen data type implemented in stdbool.h
+New boolean data type implemented in stdbool.h
.It
One line comments taken from the C++ language
.It
diff --git a/share/man/man7/ports.7 b/share/man/man7/ports.7
index 2344a4d..975b825 100644
--- a/share/man/man7/ports.7
+++ b/share/man/man7/ports.7
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 25, 2011
+.Dd May 30, 2011
.Dt PORTS 7
.Os
.Sh NAME
@@ -479,6 +479,8 @@ Of course, these ports may not work as expected, but if you really know
what you are doing and are sure about installing a forbidden port, then
.Va NO_IGNORE
lets you do it.
+.It Va NO_CHECKSUM
+If defined, skip verifying the port's checksum.
.It Va TRYBROKEN
If defined, attempt to build a port even if it is marked as
.Aq Va BROKEN .
diff --git a/share/man/man7/release.7 b/share/man/man7/release.7
index 6eeda83..f2ca0c8 100644
--- a/share/man/man7/release.7
+++ b/share/man/man7/release.7
@@ -65,7 +65,9 @@ and should have experience upgrading systems from source.
The release build process requires that
.Pa /usr/obj
be populated with the output of
-.Dq Li "make buildworld" .
+.Dq Li "make buildworld"
+and
+.Dq Li "make buildkernel" .
This is necessary to provide the object files for the release or, when
using
.Pa generate-release.sh ,
@@ -294,7 +296,7 @@ The following sequence of commands can be used to build a
cd /usr
svn co svn://svn.freebsd.org/base/head src
cd src
-make buildworld
+make buildworld buildkernel
cd release
make release
make install DESTDIR=/var/freebsd-snapshot
diff --git a/share/man/man9/bus_adjust_resource.9 b/share/man/man9/bus_adjust_resource.9
index 519974b..be4adae 100644
--- a/share/man/man9/bus_adjust_resource.9
+++ b/share/man/man9/bus_adjust_resource.9
@@ -67,6 +67,15 @@ It is the caller's responsibility to enforce any such requirements.
The
.Fn bus_adjust_resource
method returns zero on success or an error code on failure.
+.Sh EXAMPLES
+Grow an existing memory resource by 4096 bytes.
+.Bd -literal
+ struct resource *res;
+ int error;
+
+ error = bus_adjust_resource(dev, SYS_RES_MEMORY, res,
+ rman_get_start(res), rman_get_end(res) + 0x1000);
+.Ed
.Sh ERRORS
.Fn bus_adjust_resource
will fail if:
@@ -85,15 +94,6 @@ The new address range does not overlap with the existing address range of
.It Bq Er EBUSY
The new address range conflicts with another allocated resource.
.El
-.Sh EXAMPLES
-Grow an existing memory resource by 4096 bytes.
-.Bd -literal
- struct resource *res;
- int error;
-
- error = bus_adjust_resource(dev, SYS_RES_MEMORY, res,
- rman_get_start(res), rman_get_end(res) + 0x1000);
-.Ed
.Sh SEE ALSO
.Xr bus_alloc_resource 9 ,
.Xr bus_release_resource 9 ,
diff --git a/share/misc/mdoc.template b/share/misc/mdoc.template
index 63ba47d..30a5b8e 100644
--- a/share/misc/mdoc.template
+++ b/share/misc/mdoc.template
@@ -33,3 +33,4 @@
.\" .Sh HISTORY
.\" .Sh AUTHORS
.\" .Sh BUGS
+.\" .Sh SECURITY CONSIDERATIONS
diff --git a/share/mk/bsd.doc.mk b/share/mk/bsd.doc.mk
index 539d4c3..49b2d9b 100644
--- a/share/mk/bsd.doc.mk
+++ b/share/mk/bsd.doc.mk
@@ -54,10 +54,10 @@ INDXBIB?= indxbib
PIC?= pic
REFER?= refer
.for _dev in ${PRINTERDEVICE:Mascii}
-ROFF.ascii?= groff -Tascii ${TRFLAGS} -mtty-char ${MACROS} -o${PAGES}
+ROFF.ascii?= groff -Tascii -P-c ${TRFLAGS} -mtty-char ${MACROS} ${PAGES:C/^/-o/1}
.endfor
.for _dev in ${PRINTERDEVICE:Nascii}
-ROFF.${_dev}?= groff -T${_dev} ${TRFLAGS} ${MACROS} -o${PAGES}
+ROFF.${_dev}?= groff -T${_dev} ${TRFLAGS} ${MACROS} ${PAGES:C/^/-o/1}
.endfor
SOELIM?= soelim
TBL?= tbl
@@ -94,8 +94,6 @@ DFILE.${_dev}= ${DOC}.${_dev}${DCOMPRESS_EXT}
.endif
.endfor
-PAGES?= 1-
-
UNROFF?= unroff
HTML_SPLIT?= yes
UNROFFFLAGS?= -fhtml
diff --git a/sys/boot/forth/check-password.4th.8 b/sys/boot/forth/check-password.4th.8
index 95b2654..ec2323e 100644
--- a/sys/boot/forth/check-password.4th.8
+++ b/sys/boot/forth/check-password.4th.8
@@ -67,7 +67,7 @@ variable in
.Pp
Subsequent calls after a successful password
has been entered will not cause reprompting
-.Nd the function will silently return.
+\(em the function will silently return.
.El
.Pp
The environment variables that effect its behavior are:
diff --git a/sys/boot/ia64/common/Makefile b/sys/boot/ia64/common/Makefile
index d153612..f16f13d 100644
--- a/sys/boot/ia64/common/Makefile
+++ b/sys/boot/ia64/common/Makefile
@@ -33,6 +33,7 @@ loader.help: help.common
.PATH: ${.CURDIR}/../../forth
FILES+= loader.4th support.4th loader.conf
+FILES+= screen.4th frames.4th
FILES+= beastie.4th brand.4th check-password.4th color.4th delay.4th
FILES+= menu.4th menu-commands.4th shortcuts.4th version.4th
.if !exists(${DESTDIR}/boot/loader.rc)
diff --git a/sys/boot/powerpc/ofw/Makefile b/sys/boot/powerpc/ofw/Makefile
index aab4d15..079f552 100644
--- a/sys/boot/powerpc/ofw/Makefile
+++ b/sys/boot/powerpc/ofw/Makefile
@@ -103,6 +103,7 @@ loader.help: help.common help.ofw
.PATH: ${.CURDIR}/../../forth
FILES= loader.help loader.4th support.4th loader.conf
+FILES+= screen.4th frames.4th
FILES+= beastie.4th brand.4th check-password.4th color.4th delay.4th
FILES+= menu.4th menu-commands.4th shortcuts.4th version.4th
FILESDIR_loader.conf= /boot/defaults
diff --git a/sys/boot/powerpc/ps3/Makefile b/sys/boot/powerpc/ps3/Makefile
index 03cc8de..b05470b 100644
--- a/sys/boot/powerpc/ps3/Makefile
+++ b/sys/boot/powerpc/ps3/Makefile
@@ -113,8 +113,9 @@ loader.help: help.common help.ps3
.PATH: ${.CURDIR}/../../forth
FILES= loader.help loader.4th support.4th loader.conf
+FILES+= screen.4th frames.4th
FILES+= beastie.4th brand.4th check-password.4th color.4th delay.4th
-FILES+= menu.4th menu-commands.4th shortcuts.4th version.4th
+FILES+= menu.4th menu-commands.4th shortcuts.4th version.4th
FILESDIR_loader.conf= /boot/defaults
.if !exists(${DESTDIR}/boot/loader.rc)
diff --git a/sys/boot/sparc64/loader/Makefile b/sys/boot/sparc64/loader/Makefile
index 038794d..d32fbab 100644
--- a/sys/boot/sparc64/loader/Makefile
+++ b/sys/boot/sparc64/loader/Makefile
@@ -84,8 +84,9 @@ loader.help: help.common help.sparc64
.PATH: ${.CURDIR}/../../forth
FILES= loader.help loader.4th support.4th loader.conf
+FILES+= screen.4th frames.4th
FILES+= beastie.4th brand.4th check-password.4th color.4th delay.4th
-FILES+= menu.4th menu-commands.4th shortcuts.4th version.4th
+FILES+= menu.4th menu-commands.4th shortcuts.4th version.4th
FILESDIR_loader.conf= /boot/defaults
.if !exists(${DESTDIR}/boot/loader.rc)
diff --git a/sys/cam/ata/ata_da.c b/sys/cam/ata/ata_da.c
index 128bb8b..8e93302 100644
--- a/sys/cam/ata/ata_da.c
+++ b/sys/cam/ata/ata_da.c
@@ -89,7 +89,8 @@ typedef enum {
} ada_flags;
typedef enum {
- ADA_Q_NONE = 0x00
+ ADA_Q_NONE = 0x00,
+ ADA_Q_4K = 0x01,
} ada_quirks;
typedef enum {
@@ -113,11 +114,12 @@ struct disk_params {
u_int64_t sectors; /* Total number sectors */
};
-#define TRIM_MAX_BLOCKS 4
-#define TRIM_MAX_RANGES TRIM_MAX_BLOCKS * 64
+#define TRIM_MAX_BLOCKS 8
+#define TRIM_MAX_RANGES (TRIM_MAX_BLOCKS * 64)
+#define TRIM_MAX_BIOS (TRIM_MAX_RANGES * 4)
struct trim_request {
uint8_t data[TRIM_MAX_RANGES * 8];
- struct bio *bps[TRIM_MAX_RANGES];
+ struct bio *bps[TRIM_MAX_BIOS];
};
struct ada_softc {
@@ -154,6 +156,86 @@ struct ada_quirk_entry {
static struct ada_quirk_entry ada_quirk_table[] =
{
{
+ /* Hitachi Advanced Format (4k) drives */
+ { T_DIRECT, SIP_MEDIA_FIXED, "*", "Hitachi H??????????E3*", "*" },
+ /*quirks*/ADA_Q_4K
+ },
+ {
+ /* Samsung Advanced Format (4k) drives */
+ { T_DIRECT, SIP_MEDIA_FIXED, "*", "SAMSUNG HD204UI*", "*" },
+ /*quirks*/ADA_Q_4K
+ },
+ {
+ /* Seagate Barracuda Green Advanced Format (4k) drives */
+ { T_DIRECT, SIP_MEDIA_FIXED, "*", "ST????DL*", "*" },
+ /*quirks*/ADA_Q_4K
+ },
+ {
+ /* Seagate Momentus Advanced Format (4k) drives */
+ { T_DIRECT, SIP_MEDIA_FIXED, "*", "ST9500423AS*", "*" },
+ /*quirks*/ADA_Q_4K
+ },
+ {
+ /* Seagate Momentus Advanced Format (4k) drives */
+ { T_DIRECT, SIP_MEDIA_FIXED, "*", "ST9500424AS*", "*" },
+ /*quirks*/ADA_Q_4K
+ },
+ {
+ /* Seagate Momentus Advanced Format (4k) drives */
+ { T_DIRECT, SIP_MEDIA_FIXED, "*", "ST9750420AS*", "*" },
+ /*quirks*/ADA_Q_4K
+ },
+ {
+ /* Seagate Momentus Advanced Format (4k) drives */
+ { T_DIRECT, SIP_MEDIA_FIXED, "*", "ST9750422AS*", "*" },
+ /*quirks*/ADA_Q_4K
+ },
+ {
+ /* Seagate Momentus Thin Advanced Format (4k) drives */
+ { T_DIRECT, SIP_MEDIA_FIXED, "*", "ST???LT*", "*" },
+ /*quirks*/ADA_Q_4K
+ },
+ {
+ /* WDC Caviar Green Advanced Format (4k) drives */
+ { T_DIRECT, SIP_MEDIA_FIXED, "*", "WDC WD????RS*", "*" },
+ /*quirks*/ADA_Q_4K
+ },
+ {
+ /* WDC Caviar Green Advanced Format (4k) drives */
+ { T_DIRECT, SIP_MEDIA_FIXED, "*", "WDC WD????RX*", "*" },
+ /*quirks*/ADA_Q_4K
+ },
+ {
+ /* WDC Caviar Green Advanced Format (4k) drives */
+ { T_DIRECT, SIP_MEDIA_FIXED, "*", "WDC WD??????RS*", "*" },
+ /*quirks*/ADA_Q_4K
+ },
+ {
+ /* WDC Caviar Green Advanced Format (4k) drives */
+ { T_DIRECT, SIP_MEDIA_FIXED, "*", "WDC WD??????RX*", "*" },
+ /*quirks*/ADA_Q_4K
+ },
+ {
+ /* WDC Scorpio Black Advanced Format (4k) drives */
+ { T_DIRECT, SIP_MEDIA_FIXED, "*", "WDC WD???PKT*", "*" },
+ /*quirks*/ADA_Q_4K
+ },
+ {
+ /* WDC Scorpio Black Advanced Format (4k) drives */
+ { T_DIRECT, SIP_MEDIA_FIXED, "*", "WDC WD?????PKT*", "*" },
+ /*quirks*/ADA_Q_4K
+ },
+ {
+ /* WDC Scorpio Blue Advanced Format (4k) drives */
+ { T_DIRECT, SIP_MEDIA_FIXED, "*", "WDC WD???PVT*", "*" },
+ /*quirks*/ADA_Q_4K
+ },
+ {
+ /* WDC Scorpio Blue Advanced Format (4k) drives */
+ { T_DIRECT, SIP_MEDIA_FIXED, "*", "WDC WD?????PVT*", "*" },
+ /*quirks*/ADA_Q_4K
+ },
+ {
/* Default */
{
T_ANY, SIP_MEDIA_REMOVABLE|SIP_MEDIA_FIXED,
@@ -740,7 +822,7 @@ adaregister(struct cam_periph *periph, void *arg)
struct disk_params *dp;
caddr_t match;
u_int maxio;
- int legacy_id;
+ int legacy_id, quirks;
cgd = (struct ccb_getdev *)arg;
if (periph == NULL) {
@@ -815,6 +897,11 @@ adaregister(struct cam_periph *periph, void *arg)
*/
(void)cam_periph_hold(periph, PRIBIO);
mtx_unlock(periph->sim->mtx);
+ snprintf(announce_buf, sizeof(announce_buf),
+ "kern.cam.ada.%d.quirks", periph->unit_number);
+ quirks = softc->quirks;
+ TUNABLE_INT_FETCH(announce_buf, &quirks);
+ softc->quirks = quirks;
softc->write_cache = -1;
snprintf(announce_buf, sizeof(announce_buf),
"kern.cam.ada.%d.write_cache", periph->unit_number);
@@ -870,6 +957,9 @@ adaregister(struct cam_periph *periph, void *arg)
softc->disk->d_stripeoffset = (softc->disk->d_stripesize -
ata_logical_sector_offset(&cgd->ident_data)) %
softc->disk->d_stripesize;
+ } else if (softc->quirks & ADA_Q_4K) {
+ softc->disk->d_stripesize = 4096;
+ softc->disk->d_stripeoffset = 0;
}
softc->disk->d_fwsectors = softc->params.secs_per_track;
softc->disk->d_fwheads = softc->params.heads;
@@ -978,7 +1068,8 @@ adastart(struct cam_periph *periph, union ccb *start_ccb)
(bp = bioq_first(&softc->trim_queue)) != 0) {
struct trim_request *req = &softc->trim_req;
struct bio *bp1;
- int bps = 0, ranges = 0;
+ uint64_t lastlba = (uint64_t)-1;
+ int bps = 0, c, lastcount = 0, off, ranges = 0;
softc->trim_running = 1;
bzero(req, sizeof(*req));
@@ -989,10 +1080,22 @@ adastart(struct cam_periph *periph, union ccb *start_ccb)
softc->params.secsize;
bioq_remove(&softc->trim_queue, bp1);
- while (count > 0) {
- int c = min(count, 0xffff);
- int off = ranges * 8;
+ /* Try to extend the previous range. */
+ if (lba == lastlba) {
+ c = min(count, 0xffff - lastcount);
+ lastcount += c;
+ off = (ranges - 1) * 8;
+ req->data[off + 6] = lastcount & 0xff;
+ req->data[off + 7] =
+ (lastcount >> 8) & 0xff;
+ count -= c;
+ lba += c;
+ }
+
+ while (count > 0) {
+ c = min(count, 0xffff);
+ off = ranges * 8;
req->data[off + 0] = lba & 0xff;
req->data[off + 1] = (lba >> 8) & 0xff;
req->data[off + 2] = (lba >> 16) & 0xff;
@@ -1003,11 +1106,14 @@ adastart(struct cam_periph *periph, union ccb *start_ccb)
req->data[off + 7] = (c >> 8) & 0xff;
lba += c;
count -= c;
+ lastcount = c;
ranges++;
}
+ lastlba = lba;
req->bps[bps++] = bp1;
bp1 = bioq_first(&softc->trim_queue);
- if (bp1 == NULL ||
+ if (bps >= TRIM_MAX_BIOS ||
+ bp1 == NULL ||
bp1->bio_bcount / softc->params.secsize >
(softc->trim_max_ranges - ranges) * 0xffff)
break;
@@ -1281,8 +1387,7 @@ adadone(struct cam_periph *periph, union ccb *done_ccb)
(struct trim_request *)ataio->data_ptr;
int i;
- for (i = 1; i < softc->trim_max_ranges &&
- req->bps[i]; i++) {
+ for (i = 1; i < TRIM_MAX_BIOS && req->bps[i]; i++) {
struct bio *bp1 = req->bps[i];
bp1->bio_resid = bp->bio_resid;
diff --git a/sys/cddl/compat/opensolaris/kern/opensolaris.c b/sys/cddl/compat/opensolaris/kern/opensolaris.c
index 54118eb..640b2f3 100644
--- a/sys/cddl/compat/opensolaris/kern/opensolaris.c
+++ b/sys/cddl/compat/opensolaris/kern/opensolaris.c
@@ -40,6 +40,7 @@
cpu_core_t cpu_core[MAXCPU];
kmutex_t cpu_lock;
solaris_cpu_t solaris_cpu[MAXCPU];
+int nsec_per_tick;
/*
* OpenSolaris subsystem initialisation.
@@ -60,6 +61,8 @@ opensolaris_load(void *dummy)
}
mutex_init(&cpu_lock, "OpenSolaris CPU lock", MUTEX_DEFAULT, NULL);
+
+ nsec_per_tick = NANOSEC / hz;
}
SYSINIT(opensolaris_register, SI_SUB_OPENSOLARIS, SI_ORDER_FIRST, opensolaris_load, NULL);
diff --git a/sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c b/sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c
index be9f4ec..a266eca 100644
--- a/sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c
+++ b/sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c
@@ -172,6 +172,11 @@ mount_snapshot(kthread_t *td, vnode_t **vpp, const char *fstype, char *fspath,
*/
mp->mnt_flag |= MNT_RDONLY;
/*
+ * We don't want snapshots to allow access to vulnerable setuid
+ * programs, so we turn off setuid when mounting snapshots.
+ */
+ mp->mnt_flag |= MNT_NOSUID;
+ /*
* We don't want snapshots to be visible in regular
* mount(8) and df(1) output.
*/
diff --git a/sys/cddl/compat/opensolaris/sys/time.h b/sys/cddl/compat/opensolaris/sys/time.h
index 05db50e..8e8a99d 100644
--- a/sys/cddl/compat/opensolaris/sys/time.h
+++ b/sys/cddl/compat/opensolaris/sys/time.h
@@ -62,8 +62,21 @@ gethrtime(void) {
#define gethrestime(ts) getnanotime(ts)
#define gethrtime_waitfree() gethrtime()
-#define ddi_get_lbolt() ((gethrtime() * hz) / NANOSEC)
-#define ddi_get_lbolt64() (int64_t)((gethrtime() * hz) / NANOSEC)
+extern int nsec_per_tick; /* nanoseconds per clock tick */
+
+static __inline int64_t
+ddi_get_lbolt64(void)
+{
+
+ return (gethrtime() / nsec_per_tick);
+}
+
+static __inline clock_t
+ddi_get_lbolt(void)
+{
+
+ return (ddi_get_lbolt64());
+}
#else
diff --git a/sys/conf/files b/sys/conf/files
index c4e214b..59286a5 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -846,7 +846,10 @@ dev/ath/ath_rate/onoe/onoe.c optional ath_rate_onoe \
compile-with "${NORMAL_C} -I$S/dev/ath"
dev/ath/ath_rate/sample/sample.c optional ath_rate_sample \
compile-with "${NORMAL_C} -I$S/dev/ath"
-#
+# ath DFS modules
+dev/ath/ath_dfs/null/dfs_null.c optional ath \
+ compile-with "${NORMAL_C} -I$S/dev/ath"
+#
dev/bce/if_bce.c optional bce
dev/bfe/if_bfe.c optional bfe
dev/bge/if_bge.c optional bge
@@ -917,6 +920,8 @@ dev/cxgbe/t4_main.c optional cxgbe pci \
compile-with "${NORMAL_C} -I$S/dev/cxgbe"
dev/cxgbe/t4_sge.c optional cxgbe pci \
compile-with "${NORMAL_C} -I$S/dev/cxgbe"
+dev/cxgbe/t4_l2t.c optional cxgbe pci \
+ compile-with "${NORMAL_C} -I$S/dev/cxgbe"
dev/cxgbe/common/t4_hw.c optional cxgbe pci \
compile-with "${NORMAL_C} -I$S/dev/cxgbe"
dev/cy/cy.c optional cy
@@ -1953,6 +1958,7 @@ dev/usb/serial/uftdi.c optional uftdi
dev/usb/serial/ugensa.c optional ugensa
dev/usb/serial/uipaq.c optional uipaq
dev/usb/serial/ulpt.c optional ulpt
+dev/usb/serial/umcs.c optional umcs
dev/usb/serial/umct.c optional umct
dev/usb/serial/umodem.c optional umodem
dev/usb/serial/umoscom.c optional umoscom
@@ -1962,7 +1968,7 @@ dev/usb/serial/uvisor.c optional uvisor
dev/usb/serial/uvscom.c optional uvscom
dev/usb/serial/usb_serial.c optional ucom | u3g | uark | ubsa | ubser | \
uchcom | ucycom | ufoma | uftdi | \
- ugensa | uipaq | umct | \
+ ugensa | uipaq | umcs | umct | \
umodem | umoscom | uplcom | uslcom | \
uvisor | uvscom
#
diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc
index 7e72b19..7226c8f 100644
--- a/sys/conf/files.powerpc
+++ b/sys/conf/files.powerpc
@@ -27,6 +27,7 @@ dev/cfi/cfi_bus_fdt.c optional cfi fdt
dev/fb/fb.c optional sc
dev/fdt/fdt_powerpc.c optional fdt
dev/hwpmc/hwpmc_powerpc.c optional hwpmc
+dev/iicbus/ad7417.c optional ad7417 powermac
dev/iicbus/ds1775.c optional ds1775 powermac
dev/iicbus/max6690.c optional max6690 powermac
dev/kbd/kbd.c optional sc
@@ -86,7 +87,6 @@ powerpc/aim/moea64_if.m optional aim
powerpc/aim/moea64_native.c optional aim
powerpc/aim/mp_cpudep.c optional aim smp
powerpc/aim/nexus.c optional aim
-powerpc/aim/ofwmagic.S optional aim
powerpc/aim/slb.c optional aim powerpc64
powerpc/aim/swtch32.S optional aim powerpc
powerpc/aim/swtch64.S optional aim powerpc64
@@ -136,6 +136,10 @@ powerpc/ofw/ofw_pcibus.c optional pci aim
powerpc/ofw/ofw_pcib_pci.c optional pci aim
powerpc/ofw/ofw_real.c optional aim
powerpc/ofw/ofw_syscons.c optional sc aim
+powerpc/ofw/ofwcall32.S optional aim powerpc
+powerpc/ofw/ofwcall64.S optional aim powerpc64
+powerpc/ofw/ofwmagic.S optional aim
+powerpc/ofw/rtas.c optional aim
powerpc/powermac/ata_kauai.c optional powermac ata | powermac atamacio
powerpc/powermac/ata_macio.c optional powermac ata | powermac atamacio
powerpc/powermac/ata_dbdma.c optional powermac ata | powermac atamacio
@@ -158,6 +162,7 @@ powerpc/powermac/smusat.c optional powermac smu
powerpc/powermac/uninorth.c optional powermac
powerpc/powermac/uninorthpci.c optional powermac pci
powerpc/powermac/vcoregpio.c optional powermac
+powerpc/powermac/windtunnel.c optional powermac windtunnel
powerpc/powerpc/altivec.c optional aim
powerpc/powerpc/atomic.S standard
powerpc/powerpc/autoconf.c standard
diff --git a/sys/contrib/dev/acpica/changes.txt b/sys/contrib/dev/acpica/changes.txt
index 68dda91..f53fd42 100644
--- a/sys/contrib/dev/acpica/changes.txt
+++ b/sys/contrib/dev/acpica/changes.txt
@@ -1,31 +1,99 @@
----------------------------------------
+27 May 2011. Summary of changes for version 20110527:
+
+This release is available at www.acpica.org/downloads
+
+1) ACPI CA Core Subsystem:
+
+ASL Load() operator: Reinstate most restrictions on the incoming ACPI table
+signature. Now, only allow SSDT, OEMx, and a null signature. History:
+ 1) Originally, we checked the table signature for "SSDT" or "PSDT".
+ (PSDT is now obsolete.)
+ 2) We added support for OEMx tables, signature "OEM" plus a fourth
+ "don't care" character.
+ 3) Valid tables were encountered with a null signature, so we just
+ gave up on validating the signature, (05/2008).
+ 4) We encountered non-AML tables such as the MADT, which caused
+ interpreter errors and kernel faults. So now, we once again allow
+ only SSDT, OEMx, and now, also a null signature. (05/2011).
+
+Added the missing _TDL predefined name to the global name list in order to
+enable validation. Affects both the core ACPICA code and the iASL compiler.
+
+Example Code and Data Size: These are the sizes for the OS-independent
+acpica.lib produced by the Microsoft Visual C++ 9.0 32-bit compiler. The debug
+version of the code includes the debug output trace mechanism and has a much
+larger code and data size.
+
+ Previous Release (VC 9.0):
+ Non-Debug Version: 90.0K Code, 23.8K Data, 113.8K Total
+ Debug Version: 164.5K Code, 68.0K Data, 232.5K Total
+ Current Release (VC 9.0):
+ Non-Debug Version: 90.1K Code, 23.9K Data, 114.0K Total
+ Debug Version: 165.6K Code, 68.4K Data, 234.0K Total
+
+2) iASL Compiler/Disassembler and Tools:
+
+Debugger/AcpiExec: Implemented support for "complex" method arguments on the
+debugger command line. This adds support beyond simple integers -- including
+Strings, Buffers, and Packages. Includes support for nested packages.
+Increased the default command line buffer size to accommodate these arguments.
+See the ACPICA reference for details and syntax. ACPICA BZ 917.
+
+Debugger/AcpiExec: Implemented support for "default" method arguments for the
+Execute/Debug command. Now, the debugger will always invoke a control method
+with the required number of arguments -- even if the command line specifies
+none or insufficient arguments. It uses default integer values for any missing
+arguments. Also fixes a bug where only six method arguments maximum were
+supported instead of the required seven.
+
+Debugger/AcpiExec: Add a maximum buffer length parameter to AcpiOsGetLine and
+also return status in order to prevent buffer overruns. See the ACPICA
+reference for details and syntax. ACPICA BZ 921
+
+iASL: Cleaned up support for Berkeley yacc. A general cleanup of code and
+makefiles to simplify support for the two different but similar parser
+generators, bison and yacc.
+
+Updated the generic unix makefile for gcc 4. The default gcc version is now
+expected to be 4 or greater, since options specific to gcc 4 are used.
+
+----------------------------------------
13 April 2011. Summary of changes for version 20110413:
1) ACPI CA Core Subsystem:
Implemented support to execute a so-called "orphan" _REG method under the EC
-device. This change will force the execution of a _REG method underneath the EC
+device. This change will force the execution of a _REG method underneath the
+EC
device even if there is no corresponding operation region of type
EmbeddedControl. Fixes a problem seen on some machines and apparently is
compatible with Windows behavior. ACPICA BZ 875.
Added more predefined methods that are eligible for automatic NULL package
-element removal. This change adds another group of predefined names to the list
+element removal. This change adds another group of predefined names to the
+list
of names that can be repaired by having NULL package elements dynamically
removed. This group are those methods that return a single variable-length
package containing simple data types such as integers, buffers, strings. This
-includes: _ALx, _BCL, _CID,_ DOD, _EDL, _FIX, _PCL, _PLD, _PMD, _PRx, _PSL, _Sx,
+includes: _ALx, _BCL, _CID,_ DOD, _EDL, _FIX, _PCL, _PLD, _PMD, _PRx, _PSL,
+_Sx,
and _TZD. ACPICA BZ 914.
-Split and segregated all internal global lock functions to a new file, evglock.c.
+Split and segregated all internal global lock functions to a new file,
+evglock.c.
-Updated internal address SpaceID for DataTable regions. Moved this internal space
-id in preparation for ACPI 5.0 changes that will include some new space IDs. This
+Updated internal address SpaceID for DataTable regions. Moved this internal
+space
+id in preparation for ACPI 5.0 changes that will include some new space IDs.
+This
change should not affect user/host code.
-Example Code and Data Size: These are the sizes for the OS-independent acpica.lib
+Example Code and Data Size: These are the sizes for the OS-independent
+acpica.lib
produced by the Microsoft Visual C++ 9.0 32-bit compiler. The debug version of
-the code includes the debug output trace mechanism and has a much larger code and
+the code includes the debug output trace mechanism and has a much larger code
+and
data size.
Previous Release (VC 9.0):
@@ -40,34 +108,44 @@ data size.
iASL/DTC: Major update for new grammar features. Allow generic data types in
custom ACPI tables. Field names are now optional. Any line can be split to
multiple lines using the continuation char (\). Large buffers now use line-
-continuation character(s) and no colon on the continuation lines. See the grammar
+continuation character(s) and no colon on the continuation lines. See the
+grammar
update in the iASL compiler reference. ACPI BZ 910,911. Lin Ming, Bob Moore.
iASL: Mark ASL "Return()" and the simple "Return" as "Null" return statements.
-Since the parser stuffs a "zero" as the return value for these statements (due to
+Since the parser stuffs a "zero" as the return value for these statements (due
+to
the underlying AML grammar), they were seen as "return with value" by the iASL
semantic checking. They are now seen correctly as "null" return statements.
iASL: Check if a_REG declaration has a corresponding Operation Region. Adds a
check for each _REG to ensure that there is in fact a corresponding operation
-region declaration in the same scope. If not, the _REG method is not very useful
+region declaration in the same scope. If not, the _REG method is not very
+useful
since it probably won't be executed. ACPICA BZ 915.
-iASL/DTC: Finish support for expression evaluation. Added a new expression parser
-that implements c-style operator precedence and parenthesization. ACPICA bugzilla
+iASL/DTC: Finish support for expression evaluation. Added a new expression
+parser
+that implements c-style operator precedence and parenthesization. ACPICA
+bugzilla
908.
-Disassembler/DTC: Remove support for () and <> style comments in data tables. Now
-that DTC has full expression support, we don't want to have comment strings that
-start with a parentheses or a less-than symbol. Now, only the standard /* and //
+Disassembler/DTC: Remove support for () and <> style comments in data tables.
+Now
+that DTC has full expression support, we don't want to have comment strings
+that
+start with a parentheses or a less-than symbol. Now, only the standard /* and
+//
comments are supported, as well as the bracket [] comments.
-AcpiXtract: Fix for RSDP and dynamic SSDT extraction. These tables have "unusual"
+AcpiXtract: Fix for RSDP and dynamic SSDT extraction. These tables have
+"unusual"
headers in the acpidump file. Update the header validation to support these
tables. Problem introduced in previous AcpiXtract version in the change to
support "wrong checksum" error messages emitted by acpidump utility.
-iASL: Add a * option to generate all template files (as a synonym for ALL) as in
+iASL: Add a * option to generate all template files (as a synonym for ALL) as
+in
"iasl -T *" or "iasl -T ALL".
iASL/DTC: Do not abort compiler on fatal errors. We do not want to completely
@@ -81,7 +159,8 @@ invocation.
1) ACPI CA Core Subsystem:
Fixed a problem caused by a _PRW method appearing at the namespace root scope
-during the setup of wake GPEs. A fault could occur if a _PRW directly under the
+during the setup of wake GPEs. A fault could occur if a _PRW directly under
+the
root object was passed to the AcpiSetupGpeForWake interface. Lin Ming.
Implemented support for "spurious" Global Lock interrupts. On some systems, a
@@ -89,9 +168,11 @@ global lock interrupt can occur without the pending flag being set. Upon a GL
interrupt, we now ensure that a thread is actually waiting for the lock before
signaling GL availability. Rafael Wysocki, Bob Moore.
-Example Code and Data Size: These are the sizes for the OS-independent acpica.lib
+Example Code and Data Size: These are the sizes for the OS-independent
+acpica.lib
produced by the Microsoft Visual C++ 9.0 32-bit compiler. The debug version of
-the code includes the debug output trace mechanism and has a much larger code and
+the code includes the debug output trace mechanism and has a much larger code
+and
data size.
Previous Release (VC 9.0):
@@ -108,14 +189,16 @@ header files, disassembler, table compiler, and template generator. Bob Moore,
Lin Ming.
AcpiXtract: Correctly handle embedded comments and messages from AcpiDump.
-Apparently some or all versions of acpidump will occasionally emit a comment like
+Apparently some or all versions of acpidump will occasionally emit a comment
+like
"Wrong checksum", etc., into the dump file. This was causing problems for
AcpiXtract. ACPICA BZ 905.
iASL: Fix the Linux makefile by removing an inadvertent double file inclusion.
ACPICA BZ 913.
-AcpiExec: Update installation of operation region handlers. Install one handler
+AcpiExec: Update installation of operation region handlers. Install one
+handler
for a user-defined address space. This is used by the ASL test suite (ASLTS).
----------------------------------------
diff --git a/sys/contrib/dev/acpica/debugger/dbexec.c b/sys/contrib/dev/acpica/debugger/dbexec.c
index 3d46335..eb0dde2 100644
--- a/sys/contrib/dev/acpica/debugger/dbexec.c
+++ b/sys/contrib/dev/acpica/debugger/dbexec.c
@@ -53,7 +53,8 @@
ACPI_MODULE_NAME ("dbexec")
-static ACPI_DB_METHOD_INFO AcpiGbl_DbMethodInfo;
+static ACPI_DB_METHOD_INFO AcpiGbl_DbMethodInfo;
+#define DB_DEFAULT_PKG_ELEMENTS 33
/* Local prototypes */
@@ -81,6 +82,348 @@ AcpiDbExecutionWalk (
void *Context,
void **ReturnValue);
+static ACPI_STATUS
+AcpiDbHexCharToValue (
+ int HexChar,
+ UINT8 *ReturnValue);
+
+static ACPI_STATUS
+AcpiDbConvertToPackage (
+ char *String,
+ ACPI_OBJECT *Object);
+
+static ACPI_STATUS
+AcpiDbConvertToObject (
+ ACPI_OBJECT_TYPE Type,
+ char *String,
+ ACPI_OBJECT *Object);
+
+static void
+AcpiDbDeleteObjects (
+ UINT32 Count,
+ ACPI_OBJECT *Objects);
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiDbHexCharToValue
+ *
+ * PARAMETERS: HexChar - Ascii Hex digit, 0-9|a-f|A-F
+ * ReturnValue - Where the converted value is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Convert a single hex character to a 4-bit number (0-16).
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+AcpiDbHexCharToValue (
+ int HexChar,
+ UINT8 *ReturnValue)
+{
+ UINT8 Value;
+
+
+ /* Digit must be ascii [0-9a-fA-F] */
+
+ if (!ACPI_IS_XDIGIT (HexChar))
+ {
+ return (AE_BAD_HEX_CONSTANT);
+ }
+
+ if (HexChar <= 0x39)
+ {
+ Value = (UINT8) (HexChar - 0x30);
+ }
+ else
+ {
+ Value = (UINT8) (ACPI_TOUPPER (HexChar) - 0x37);
+ }
+
+ *ReturnValue = Value;
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiDbHexByteToBinary
+ *
+ * PARAMETERS: HexByte - Double hex digit (0x00 - 0xFF) in format:
+ * HiByte then LoByte.
+ * ReturnValue - Where the converted value is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Convert two hex characters to an 8 bit number (0 - 255).
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+AcpiDbHexByteToBinary (
+ char *HexByte,
+ UINT8 *ReturnValue)
+{
+ UINT8 Local0;
+ UINT8 Local1;
+ ACPI_STATUS Status;
+
+
+ /* High byte */
+
+ Status = AcpiDbHexCharToValue (HexByte[0], &Local0);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ /* Low byte */
+
+ Status = AcpiDbHexCharToValue (HexByte[1], &Local1);
+ if (ACPI_FAILURE (Status))
+ {
+ return (Status);
+ }
+
+ *ReturnValue = (UINT8) ((Local0 << 4) | Local1);
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiDbConvertToBuffer
+ *
+ * PARAMETERS: String - Input string to be converted
+ * Object - Where the buffer object is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Convert a string to a buffer object. String is treated a list
+ * of buffer elements, each separated by a space or comma.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+AcpiDbConvertToBuffer (
+ char *String,
+ ACPI_OBJECT *Object)
+{
+ UINT32 i;
+ UINT32 j;
+ UINT32 Length;
+ UINT8 *Buffer;
+ ACPI_STATUS Status;
+
+
+ /* Generate the final buffer length */
+
+ for (i = 0, Length = 0; String[i];)
+ {
+ i+=2;
+ Length++;
+
+ while (String[i] &&
+ ((String[i] == ',') || (String[i] == ' ')))
+ {
+ i++;
+ }
+ }
+
+ Buffer = ACPI_ALLOCATE (Length);
+ if (!Buffer)
+ {
+ return (AE_NO_MEMORY);
+ }
+
+ /* Convert the command line bytes to the buffer */
+
+ for (i = 0, j = 0; String[i];)
+ {
+ Status = AcpiDbHexByteToBinary (&String[i], &Buffer[j]);
+ if (ACPI_FAILURE (Status))
+ {
+ ACPI_FREE (Buffer);
+ return (Status);
+ }
+
+ j++;
+ i+=2;
+ while (String[i] &&
+ ((String[i] == ',') || (String[i] == ' ')))
+ {
+ i++;
+ }
+ }
+
+ Object->Type = ACPI_TYPE_BUFFER;
+ Object->Buffer.Pointer = Buffer;
+ Object->Buffer.Length = Length;
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiDbConvertToPackage
+ *
+ * PARAMETERS: String - Input string to be converted
+ * Object - Where the package object is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Convert a string to a package object. Handles nested packages
+ * via recursion with AcpiDbConvertToObject.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+AcpiDbConvertToPackage (
+ char *String,
+ ACPI_OBJECT *Object)
+{
+ char *This;
+ char *Next;
+ UINT32 i;
+ ACPI_OBJECT_TYPE Type;
+ ACPI_OBJECT *Elements;
+ ACPI_STATUS Status;
+
+
+ Elements = ACPI_ALLOCATE_ZEROED (
+ DB_DEFAULT_PKG_ELEMENTS * sizeof (ACPI_OBJECT));
+
+ This = String;
+ for (i = 0; i < (DB_DEFAULT_PKG_ELEMENTS - 1); i++)
+ {
+ This = AcpiDbGetNextToken (This, &Next, &Type);
+ if (!This)
+ {
+ break;
+ }
+
+ /* Recursive call to convert each package element */
+
+ Status = AcpiDbConvertToObject (Type, This, &Elements[i]);
+ if (ACPI_FAILURE (Status))
+ {
+ AcpiDbDeleteObjects (i + 1, Elements);
+ ACPI_FREE (Elements);
+ return (Status);
+ }
+
+ This = Next;
+ }
+
+ Object->Type = ACPI_TYPE_PACKAGE;
+ Object->Package.Count = i;
+ Object->Package.Elements = Elements;
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiDbConvertToObject
+ *
+ * PARAMETERS: Type - Object type as determined by parser
+ * String - Input string to be converted
+ * Object - Where the new object is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Convert a typed and tokenized string to an ACPI_OBJECT. Typing:
+ * 1) String objects were surrounded by quotes.
+ * 2) Buffer objects were surrounded by parentheses.
+ * 3) Package objects were surrounded by brackets "[]".
+ * 4) All standalone tokens are treated as integers.
+ *
+ ******************************************************************************/
+
+static ACPI_STATUS
+AcpiDbConvertToObject (
+ ACPI_OBJECT_TYPE Type,
+ char *String,
+ ACPI_OBJECT *Object)
+{
+ ACPI_STATUS Status = AE_OK;
+
+
+ switch (Type)
+ {
+ case ACPI_TYPE_STRING:
+ Object->Type = ACPI_TYPE_STRING;
+ Object->String.Pointer = String;
+ Object->String.Length = (UINT32) ACPI_STRLEN (String);
+ break;
+
+ case ACPI_TYPE_BUFFER:
+ Status = AcpiDbConvertToBuffer (String, Object);
+ break;
+
+ case ACPI_TYPE_PACKAGE:
+ Status = AcpiDbConvertToPackage (String, Object);
+ break;
+
+ default:
+ Object->Type = ACPI_TYPE_INTEGER;
+ Status = AcpiUtStrtoul64 (String, 16, &Object->Integer.Value);
+ break;
+ }
+
+ return (Status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiDbDeleteObjects
+ *
+ * PARAMETERS: Count - Count of objects in the list
+ * Objects - Array of ACPI_OBJECTs to be deleted
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Delete a list of ACPI_OBJECTS. Handles packages and nested
+ * packages via recursion.
+ *
+ ******************************************************************************/
+
+static void
+AcpiDbDeleteObjects (
+ UINT32 Count,
+ ACPI_OBJECT *Objects)
+{
+ UINT32 i;
+
+
+ for (i = 0; i < Count; i++)
+ {
+ switch (Objects[i].Type)
+ {
+ case ACPI_TYPE_BUFFER:
+ ACPI_FREE (Objects[i].Buffer.Pointer);
+ break;
+
+ case ACPI_TYPE_PACKAGE:
+
+ /* Recursive call to delete package elements */
+
+ AcpiDbDeleteObjects (Objects[i].Package.Count,
+ Objects[i].Package.Elements);
+
+ /* Free the elements array */
+
+ ACPI_FREE (Objects[i].Package.Elements);
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
/*******************************************************************************
*
@@ -104,8 +447,8 @@ AcpiDbExecuteMethod (
ACPI_OBJECT_LIST ParamObjects;
ACPI_OBJECT Params[ACPI_METHOD_NUM_ARGS];
ACPI_HANDLE Handle;
- UINT32 i;
ACPI_DEVICE_INFO *ObjInfo;
+ UINT32 i;
ACPI_FUNCTION_TRACE (DbExecuteMethod);
@@ -139,25 +482,37 @@ AcpiDbExecuteMethod (
{
/* Are there arguments to the method? */
+ i = 0;
if (Info->Args && Info->Args[0])
{
- for (i = 0; Info->Args[i] &&
+ /* Get arguments passed on the command line */
+
+ for (; Info->Args[i] &&
(i < ACPI_METHOD_NUM_ARGS) &&
(i < ObjInfo->ParamCount);
i++)
{
- Params[i].Type = ACPI_TYPE_INTEGER;
- Params[i].Integer.Value = ACPI_STRTOUL (Info->Args[i], NULL, 16);
- }
+ /* Convert input string (token) to an actual ACPI_OBJECT */
- ParamObjects.Pointer = Params;
- ParamObjects.Count = i;
+ Status = AcpiDbConvertToObject (Info->Types[i],
+ Info->Args[i], &Params[i]);
+ if (ACPI_FAILURE (Status))
+ {
+ ACPI_EXCEPTION ((AE_INFO, Status,
+ "While parsing method arguments"));
+ goto Cleanup;
+ }
+ }
}
- else
+
+ /* Create additional "default" parameters as needed */
+
+ if (i < ObjInfo->ParamCount)
{
- /* Setup default parameters */
+ AcpiOsPrintf ("Adding %u arguments containing default values\n",
+ ObjInfo->ParamCount - i);
- for (i = 0; i < ObjInfo->ParamCount; i++)
+ for (; i < ObjInfo->ParamCount; i++)
{
switch (i)
{
@@ -181,13 +536,11 @@ AcpiDbExecuteMethod (
break;
}
}
-
- ParamObjects.Pointer = Params;
- ParamObjects.Count = ObjInfo->ParamCount;
}
- }
- ACPI_FREE (ObjInfo);
+ ParamObjects.Count = ObjInfo->ParamCount;
+ ParamObjects.Pointer = Params;
+ }
/* Prepare for a return object of arbitrary size */
@@ -198,7 +551,7 @@ AcpiDbExecuteMethod (
AcpiGbl_MethodExecuting = TRUE;
Status = AcpiEvaluateObject (NULL,
- Info->Pathname, &ParamObjects, ReturnObj);
+ Info->Pathname, &ParamObjects, ReturnObj);
AcpiGbl_CmSingleStep = FALSE;
AcpiGbl_MethodExecuting = FALSE;
@@ -206,16 +559,20 @@ AcpiDbExecuteMethod (
if (ACPI_FAILURE (Status))
{
ACPI_EXCEPTION ((AE_INFO, Status,
- "while executing %s from debugger", Info->Pathname));
+ "while executing %s from debugger", Info->Pathname));
if (Status == AE_BUFFER_OVERFLOW)
{
ACPI_ERROR ((AE_INFO,
- "Possible overflow of internal debugger buffer (size 0x%X needed 0x%X)",
+ "Possible overflow of internal debugger buffer (size 0x%X needed 0x%X)",
ACPI_DEBUG_BUFFER_SIZE, (UINT32) ReturnObj->Length));
}
}
+Cleanup:
+ AcpiDbDeleteObjects (ObjInfo->ParamCount, Params);
+ ACPI_FREE (ObjInfo);
+
return_ACPI_STATUS (Status);
}
@@ -380,6 +737,7 @@ void
AcpiDbExecute (
char *Name,
char **Args,
+ ACPI_OBJECT_TYPE *Types,
UINT32 Flags)
{
ACPI_STATUS Status;
@@ -417,6 +775,7 @@ AcpiDbExecute (
AcpiUtStrupr (NameString);
AcpiGbl_DbMethodInfo.Name = NameString;
AcpiGbl_DbMethodInfo.Args = Args;
+ AcpiGbl_DbMethodInfo.Types = Types;
AcpiGbl_DbMethodInfo.Flags = Flags;
ReturnObj.Pointer = NULL;
@@ -529,6 +888,8 @@ AcpiDbMethodThread (
LocalInfo.Arguments[2] = LocalInfo.IndexOfThreadStr;
LocalInfo.Arguments[3] = NULL;
+ LocalInfo.Types = LocalInfo.ArgTypes;
+
(void) AcpiOsSignalSemaphore (Info->InfoGate, 1);
for (i = 0; i < Info->NumLoops; i++)
@@ -696,6 +1057,12 @@ AcpiDbCreateExecutionThreads (
AcpiGbl_DbMethodInfo.Arguments[1] = AcpiGbl_DbMethodInfo.IdOfThreadStr;
AcpiGbl_DbMethodInfo.Arguments[2] = AcpiGbl_DbMethodInfo.IndexOfThreadStr;
AcpiGbl_DbMethodInfo.Arguments[3] = NULL;
+
+ AcpiGbl_DbMethodInfo.Types = AcpiGbl_DbMethodInfo.ArgTypes;
+ AcpiGbl_DbMethodInfo.ArgTypes[0] = ACPI_TYPE_INTEGER;
+ AcpiGbl_DbMethodInfo.ArgTypes[1] = ACPI_TYPE_INTEGER;
+ AcpiGbl_DbMethodInfo.ArgTypes[2] = ACPI_TYPE_INTEGER;
+
AcpiDbUInt32ToHexString (NumThreads, AcpiGbl_DbMethodInfo.NumThreadsStr);
AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo);
diff --git a/sys/contrib/dev/acpica/debugger/dbinput.c b/sys/contrib/dev/acpica/debugger/dbinput.c
index 5b8e70a..7d8bbb7 100644
--- a/sys/contrib/dev/acpica/debugger/dbinput.c
+++ b/sys/contrib/dev/acpica/debugger/dbinput.c
@@ -54,11 +54,6 @@
/* Local prototypes */
-static char *
-AcpiDbGetNextToken (
- char *String,
- char **Next);
-
static UINT32
AcpiDbGetLine (
char *InputBuffer);
@@ -285,6 +280,10 @@ AcpiDbDisplayHelp (
AcpiOsPrintf (" Call Run to next control method invocation\n");
AcpiOsPrintf (" Debug <Namepath> [Arguments] Single Step a control method\n");
AcpiOsPrintf (" Execute <Namepath> [Arguments] Execute control method\n");
+ AcpiOsPrintf (" Hex Integer Integer method argument\n");
+ AcpiOsPrintf (" \"Ascii String\" String method argument\n");
+ AcpiOsPrintf (" (Byte List) Buffer method argument\n");
+ AcpiOsPrintf (" [Package Element List] Package method argument\n");
AcpiOsPrintf (" Go Allow method to run to completion\n");
AcpiOsPrintf (" Information Display info about the current method\n");
AcpiOsPrintf (" Into Step into (not over) a method call\n");
@@ -318,12 +317,15 @@ AcpiDbDisplayHelp (
*
******************************************************************************/
-static char *
+char *
AcpiDbGetNextToken (
char *String,
- char **Next)
+ char **Next,
+ ACPI_OBJECT_TYPE *ReturnType)
{
char *Start;
+ UINT32 Depth;
+ ACPI_OBJECT_TYPE Type = ACPI_TYPE_INTEGER;
/* At end of buffer? */
@@ -333,7 +335,7 @@ AcpiDbGetNextToken (
return (NULL);
}
- /* Get rid of any spaces at the beginning */
+ /* Remove any spaces at the beginning */
if (*String == ' ')
{
@@ -348,22 +350,88 @@ AcpiDbGetNextToken (
}
}
- if (*String == '"')
+ switch (*String)
{
+ case '"':
+
/* This is a quoted string, scan until closing quote */
String++;
Start = String;
+ Type = ACPI_TYPE_STRING;
- /* Find end of token */
+ /* Find end of string */
while (*String && (*String != '"'))
{
String++;
}
- }
- else
- {
+ break;
+
+ case '(':
+
+ /* This is the start of a buffer, scan until closing paren */
+
+ String++;
+ Start = String;
+ Type = ACPI_TYPE_BUFFER;
+
+ /* Find end of buffer */
+
+ while (*String && (*String != ')'))
+ {
+ String++;
+ }
+ break;
+
+ case '[':
+
+ /* This is the start of a package, scan until closing bracket */
+
+ String++;
+ Depth = 1;
+ Start = String;
+ Type = ACPI_TYPE_PACKAGE;
+
+ /* Find end of package (closing bracket) */
+
+ while (*String)
+ {
+ /* Handle String package elements */
+
+ if (*String == '"')
+ {
+ /* Find end of string */
+
+ String++;
+ while (*String && (*String != '"'))
+ {
+ String++;
+ }
+ if (!(*String))
+ {
+ break;
+ }
+ }
+ else if (*String == '[')
+ {
+ Depth++; /* A nested package declaration */
+ }
+ else if (*String == ']')
+ {
+ Depth--;
+ if (Depth == 0) /* Found final package closing bracket */
+ {
+ break;
+ }
+ }
+
+ String++;
+ }
+ break;
+
+ default:
+
Start = String;
/* Find end of token */
@@ -372,6 +440,7 @@ AcpiDbGetNextToken (
{
String++;
}
+ break;
}
if (!(*String))
@@ -384,6 +453,7 @@ AcpiDbGetNextToken (
*Next = String + 1;
}
+ *ReturnType = Type;
return (Start);
}
@@ -416,7 +486,8 @@ AcpiDbGetLine (
This = AcpiGbl_DbParsedBuf;
for (i = 0; i < ACPI_DEBUGGER_MAX_ARGS; i++)
{
- AcpiGbl_DbArgs[i] = AcpiDbGetNextToken (This, &Next);
+ AcpiGbl_DbArgs[i] = AcpiDbGetNextToken (This, &Next,
+ &AcpiGbl_DbArgTypes[i]);
if (!AcpiGbl_DbArgs[i])
{
break;
@@ -575,7 +646,8 @@ AcpiDbCommandDispatch (
break;
case CMD_DEBUG:
- AcpiDbExecute (AcpiGbl_DbArgs[1], &AcpiGbl_DbArgs[2], EX_SINGLE_STEP);
+ AcpiDbExecute (AcpiGbl_DbArgs[1],
+ &AcpiGbl_DbArgs[2], &AcpiGbl_DbArgTypes[2], EX_SINGLE_STEP);
break;
case CMD_DISASSEMBLE:
@@ -601,7 +673,7 @@ AcpiDbCommandDispatch (
case CMD_EXECUTE:
AcpiDbExecute (AcpiGbl_DbArgs[1],
- &AcpiGbl_DbArgs[2], EX_NO_SINGLE_STEP);
+ &AcpiGbl_DbArgs[2], &AcpiGbl_DbArgTypes[2], EX_NO_SINGLE_STEP);
break;
case CMD_FIND:
@@ -961,7 +1033,13 @@ AcpiDbUserCommands (
/* Get the user input line */
- (void) AcpiOsGetLine (AcpiGbl_DbLineBuf);
+ Status = AcpiOsGetLine (AcpiGbl_DbLineBuf,
+ ACPI_DB_LINE_BUFFER_SIZE, NULL);
+ if (ACPI_FAILURE (Status))
+ {
+ ACPI_EXCEPTION ((AE_INFO, Status, "While parsing command line"));
+ return (Status);
+ }
/* Check for single or multithreaded debug */
diff --git a/sys/contrib/dev/acpica/debugger/dbutils.c b/sys/contrib/dev/acpica/debugger/dbutils.c
index 8385fc8..bed52e6 100644
--- a/sys/contrib/dev/acpica/debugger/dbutils.c
+++ b/sys/contrib/dev/acpica/debugger/dbutils.c
@@ -382,7 +382,7 @@ AcpiDbUInt32ToHexString (
UINT32 Value,
char *Buffer)
{
- UINT8 i;
+ int i;
if (Value == 0)
@@ -391,10 +391,9 @@ AcpiDbUInt32ToHexString (
return;
}
- ACPI_STRCPY (Buffer, "0x");
- Buffer[10] = '\0';
+ Buffer[8] = '\0';
- for (i = 9; i > 1; i--)
+ for (i = 7; i >= 0; i--)
{
Buffer[i] = Converter [Value & 0x0F];
Value = Value >> 4;
diff --git a/sys/contrib/dev/acpica/debugger/dbxface.c b/sys/contrib/dev/acpica/debugger/dbxface.c
index 2f3708a..e8602bc 100644
--- a/sys/contrib/dev/acpica/debugger/dbxface.c
+++ b/sys/contrib/dev/acpica/debugger/dbxface.c
@@ -137,7 +137,13 @@ AcpiDbStartCommand (
/* Get the user input line */
- (void) AcpiOsGetLine (AcpiGbl_DbLineBuf);
+ Status = AcpiOsGetLine (AcpiGbl_DbLineBuf,
+ ACPI_DB_LINE_BUFFER_SIZE, NULL);
+ if (ACPI_FAILURE (Status))
+ {
+ ACPI_EXCEPTION ((AE_INFO, Status, "While parsing command line"));
+ return (Status);
+ }
}
Status = AcpiDbCommandDispatch (AcpiGbl_DbLineBuf, WalkState, Op);
diff --git a/sys/contrib/dev/acpica/include/acconfig.h b/sys/contrib/dev/acpica/include/acconfig.h
index 4b05ed3..7a2107a 100644
--- a/sys/contrib/dev/acpica/include/acconfig.h
+++ b/sys/contrib/dev/acpica/include/acconfig.h
@@ -200,7 +200,8 @@
*
*****************************************************************************/
-#define ACPI_DEBUGGER_MAX_ARGS 8 /* Must be max method args + 1 */
+#define ACPI_DEBUGGER_MAX_ARGS ACPI_METHOD_NUM_ARGS + 2 /* Max command line arguments */
+#define ACPI_DB_LINE_BUFFER_SIZE 512
#define ACPI_DEBUGGER_COMMAND_PROMPT '-'
#define ACPI_DEBUGGER_EXECUTE_PROMPT '%'
diff --git a/sys/contrib/dev/acpica/include/acdebug.h b/sys/contrib/dev/acpica/include/acdebug.h
index 9b4822d..2c1fe73 100644
--- a/sys/contrib/dev/acpica/include/acdebug.h
+++ b/sys/contrib/dev/acpica/include/acdebug.h
@@ -277,6 +277,7 @@ void
AcpiDbExecute (
char *Name,
char **Args,
+ ACPI_OBJECT_TYPE *Types,
UINT32 Flags);
void
@@ -357,6 +358,12 @@ AcpiDbUserCommands (
char Prompt,
ACPI_PARSE_OBJECT *Op);
+char *
+AcpiDbGetNextToken (
+ char *String,
+ char **Next,
+ ACPI_OBJECT_TYPE *ReturnType);
+
/*
* dbstats - Generation and display of ACPI table statistics
diff --git a/sys/contrib/dev/acpica/include/acglobal.h b/sys/contrib/dev/acpica/include/acglobal.h
index fc20994..ebbae0f 100644
--- a/sys/contrib/dev/acpica/include/acglobal.h
+++ b/sys/contrib/dev/acpica/include/acglobal.h
@@ -425,10 +425,11 @@ ACPI_EXTERN BOOLEAN AcpiGbl_DbOpt_ini_methods;
ACPI_EXTERN BOOLEAN AcpiGbl_DbOpt_NoRegionSupport;
ACPI_EXTERN char *AcpiGbl_DbArgs[ACPI_DEBUGGER_MAX_ARGS];
-ACPI_EXTERN char AcpiGbl_DbLineBuf[80];
-ACPI_EXTERN char AcpiGbl_DbParsedBuf[80];
-ACPI_EXTERN char AcpiGbl_DbScopeBuf[40];
-ACPI_EXTERN char AcpiGbl_DbDebugFilename[40];
+ACPI_EXTERN ACPI_OBJECT_TYPE AcpiGbl_DbArgTypes[ACPI_DEBUGGER_MAX_ARGS];
+ACPI_EXTERN char AcpiGbl_DbLineBuf[ACPI_DB_LINE_BUFFER_SIZE];
+ACPI_EXTERN char AcpiGbl_DbParsedBuf[ACPI_DB_LINE_BUFFER_SIZE];
+ACPI_EXTERN char AcpiGbl_DbScopeBuf[80];
+ACPI_EXTERN char AcpiGbl_DbDebugFilename[80];
ACPI_EXTERN BOOLEAN AcpiGbl_DbOutputToFile;
ACPI_EXTERN char *AcpiGbl_DbBuffer;
ACPI_EXTERN char *AcpiGbl_DbFilename;
diff --git a/sys/contrib/dev/acpica/include/aclocal.h b/sys/contrib/dev/acpica/include/aclocal.h
index bdefb76..2eb6fc2 100644
--- a/sys/contrib/dev/acpica/include/aclocal.h
+++ b/sys/contrib/dev/acpica/include/aclocal.h
@@ -1198,6 +1198,7 @@ typedef struct acpi_db_method_info
UINT32 NumLoops;
char Pathname[128];
char **Args;
+ ACPI_OBJECT_TYPE *Types;
/*
* Arguments to be passed to method for the command
@@ -1206,6 +1207,7 @@ typedef struct acpi_db_method_info
* Index of current thread inside all them created.
*/
char InitArgs;
+ ACPI_OBJECT_TYPE ArgTypes[4];
char *Arguments[4];
char NumThreadsStr[11];
char IdOfThreadStr[11];
diff --git a/sys/contrib/dev/acpica/include/acpiosxf.h b/sys/contrib/dev/acpica/include/acpiosxf.h
index 53605ad..43ca582 100644
--- a/sys/contrib/dev/acpica/include/acpiosxf.h
+++ b/sys/contrib/dev/acpica/include/acpiosxf.h
@@ -376,9 +376,11 @@ AcpiOsRedirectOutput (
/*
* Debug input
*/
-UINT32
+ACPI_STATUS
AcpiOsGetLine (
- char *Buffer);
+ char *Buffer,
+ UINT32 BufferLength,
+ UINT32 *BytesRead);
/*
diff --git a/sys/contrib/dev/acpica/include/acpixf.h b/sys/contrib/dev/acpica/include/acpixf.h
index 891ccf3..1755261 100644
--- a/sys/contrib/dev/acpica/include/acpixf.h
+++ b/sys/contrib/dev/acpica/include/acpixf.h
@@ -48,7 +48,7 @@
/* Current ACPICA subsystem version in YYYYMMDD format */
-#define ACPI_CA_VERSION 0x20110413
+#define ACPI_CA_VERSION 0x20110527
#include <contrib/dev/acpica/include/actypes.h>
#include <contrib/dev/acpica/include/actbl.h>
diff --git a/sys/contrib/dev/acpica/include/acpredef.h b/sys/contrib/dev/acpica/include/acpredef.h
index 884f118..0496767 100644
--- a/sys/contrib/dev/acpica/include/acpredef.h
+++ b/sys/contrib/dev/acpica/include/acpredef.h
@@ -470,6 +470,7 @@ static const ACPI_PREDEFINED_INFO PredefinedNames[] =
{{"_SWS", 0, ACPI_RTYPE_INTEGER}},
{{"_TC1", 0, ACPI_RTYPE_INTEGER}},
{{"_TC2", 0, ACPI_RTYPE_INTEGER}},
+ {{"_TDL", 0, ACPI_RTYPE_INTEGER}},
{{"_TIP", 1, ACPI_RTYPE_INTEGER}},
{{"_TIV", 1, ACPI_RTYPE_INTEGER}},
{{"_TMP", 0, ACPI_RTYPE_INTEGER}},
diff --git a/sys/contrib/dev/acpica/osunixxf.c b/sys/contrib/dev/acpica/osunixxf.c
index 0983bd4..f486c27 100644
--- a/sys/contrib/dev/acpica/osunixxf.c
+++ b/sys/contrib/dev/acpica/osunixxf.c
@@ -311,18 +311,21 @@ AcpiOsVprintf (
*
* FUNCTION: AcpiOsGetLine
*
- * PARAMETERS: fmt - Standard printf format
- * args - Argument list
+ * PARAMETERS: Buffer - Where to return the command line
+ * BufferLength - Maximum length of Buffer
+ * BytesRead - Where the actual byte count is returned
*
- * RETURN: Actual bytes read
+ * RETURN: Status and actual bytes read
*
* DESCRIPTION: Formatted input with argument list pointer
*
*****************************************************************************/
-UINT32
+ACPI_STATUS
AcpiOsGetLine (
- char *Buffer)
+ char *Buffer,
+ UINT32 BufferLength,
+ UINT32 *BytesRead)
{
UINT8 Temp;
UINT32 i;
@@ -330,6 +333,11 @@ AcpiOsGetLine (
for (i = 0; ; i++)
{
+ if (i >= BufferLength)
+ {
+ return (AE_BUFFER_OVERFLOW);
+ }
+
scanf ("%1c", &Temp);
if (!Temp || Temp == '\n')
{
@@ -345,7 +353,11 @@ AcpiOsGetLine (
/* Return the number of bytes in the string */
- return (i);
+ if (BytesRead)
+ {
+ *BytesRead = i;
+ }
+ return (AE_OK);
}
diff --git a/sys/contrib/dev/acpica/tables/tbinstal.c b/sys/contrib/dev/acpica/tables/tbinstal.c
index 8e2199f..8697fa1 100644
--- a/sys/contrib/dev/acpica/tables/tbinstal.c
+++ b/sys/contrib/dev/acpica/tables/tbinstal.c
@@ -144,12 +144,28 @@ AcpiTbAddTable (
}
/*
- * Originally, we checked the table signature for "SSDT" or "PSDT" here.
- * Next, we added support for OEMx tables, signature "OEM".
- * Valid tables were encountered with a null signature, so we've just
- * given up on validating the signature, since it seems to be a waste
- * of code. The original code was removed (05/2008).
+ * Validate the incoming table signature.
+ *
+ * 1) Originally, we checked the table signature for "SSDT" or "PSDT".
+ * 2) We added support for OEMx tables, signature "OEM".
+ * 3) Valid tables were encountered with a null signature, so we just
+ * gave up on validating the signature, (05/2008).
+ * 4) We encountered non-AML tables such as the MADT, which caused
+ * interpreter errors and kernel faults. So now, we once again allow
+ * only "SSDT", "OEMx", and now, also a null signature. (05/2011).
*/
+ if ((TableDesc->Pointer->Signature[0] != 0x00) &&
+ (!ACPI_COMPARE_NAME (TableDesc->Pointer->Signature, ACPI_SIG_SSDT)) &&
+ (ACPI_STRNCMP (TableDesc->Pointer->Signature, "OEM", 3)))
+ {
+ ACPI_ERROR ((AE_INFO,
+ "Table has invalid signature [%4.4s] (0x%8.8X), must be SSDT or OEMx",
+ AcpiUtValidAcpiName (*(UINT32 *) TableDesc->Pointer->Signature) ?
+ TableDesc->Pointer->Signature : "????",
+ *(UINT32 *) TableDesc->Pointer->Signature));
+
+ return_ACPI_STATUS (AE_BAD_SIGNATURE);
+ }
(void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
diff --git a/sys/contrib/pf/net/pf.c b/sys/contrib/pf/net/pf.c
index d65ab8d..135d734 100644
--- a/sys/contrib/pf/net/pf.c
+++ b/sys/contrib/pf/net/pf.c
@@ -3034,16 +3034,18 @@ pf_socket_lookup(int direction, struct pf_pdesc *pd)
#ifdef INET
case AF_INET:
#ifdef __FreeBSD__
- INP_INFO_RLOCK(pi); /* XXX LOR */
- inp = in_pcblookup_hash(pi, saddr->v4, sport, daddr->v4,
- dport, 0, NULL);
+ /*
+ * XXXRW: would be nice if we had an mbuf here so that we
+ * could use in_pcblookup_mbuf().
+ */
+ inp = in_pcblookup(pi, saddr->v4, sport, daddr->v4,
+ dport, INPLOOKUP_RLOCKPCB, NULL);
if (inp == NULL) {
- inp = in_pcblookup_hash(pi, saddr->v4, sport,
- daddr->v4, dport, INPLOOKUP_WILDCARD, NULL);
- if(inp == NULL) {
- INP_INFO_RUNLOCK(pi);
+ inp = in_pcblookup(pi, saddr->v4, sport,
+ daddr->v4, dport, INPLOOKUP_WILDCARD |
+ INPLOOKUP_RLOCKPCB, NULL);
+ if (inp == NULL)
return (-1);
- }
}
#else
inp = in_pcbhashlookup(tb, saddr->v4, sport, daddr->v4, dport);
@@ -3058,16 +3060,18 @@ pf_socket_lookup(int direction, struct pf_pdesc *pd)
#ifdef INET6
case AF_INET6:
#ifdef __FreeBSD__
- INP_INFO_RLOCK(pi);
- inp = in6_pcblookup_hash(pi, &saddr->v6, sport,
- &daddr->v6, dport, 0, NULL);
+ /*
+ * XXXRW: would be nice if we had an mbuf here so that we
+ * could use in6_pcblookup_mbuf().
+ */
+ inp = in6_pcblookup(pi, &saddr->v6, sport,
+ &daddr->v6, dport, INPLOOKUP_RLOCKPCB, NULL);
if (inp == NULL) {
- inp = in6_pcblookup_hash(pi, &saddr->v6, sport,
- &daddr->v6, dport, INPLOOKUP_WILDCARD, NULL);
- if (inp == NULL) {
- INP_INFO_RUNLOCK(pi);
+ inp = in6_pcblookup(pi, &saddr->v6, sport,
+ &daddr->v6, dport, INPLOOKUP_WILDCARD |
+ INPLOOKUP_RLOCKPCB, NULL);
+ if (inp == NULL)
return (-1);
- }
}
#else
inp = in6_pcbhashlookup(tb, &saddr->v6, sport, &daddr->v6,
@@ -3085,9 +3089,10 @@ pf_socket_lookup(int direction, struct pf_pdesc *pd)
return (-1);
}
#ifdef __FreeBSD__
+ INP_RLOCK_ASSERT(inp);
pd->lookup.uid = inp->inp_cred->cr_uid;
pd->lookup.gid = inp->inp_cred->cr_groups[0];
- INP_INFO_RUNLOCK(pi);
+ INP_RUNLOCK(inp);
#else
pd->lookup.uid = inp->inp_socket->so_euid;
pd->lookup.gid = inp->inp_socket->so_egid;
@@ -6135,9 +6140,11 @@ pf_routable(struct pf_addr *addr, sa_family_t af, struct pfi_kif *kif)
#ifdef __FreeBSD__
/* XXX MRT not always INET */ /* stick with table 0 though */
+#ifdef INET
if (af == AF_INET)
in_rtalloc_ign((struct route *)&ro, 0, 0);
else
+#endif
rtalloc_ign((struct route *)&ro, 0);
#else /* ! __FreeBSD__ */
rtalloc_noclone((struct route *)&ro, NO_CLONING);
@@ -6217,9 +6224,11 @@ pf_rtlabel_match(struct pf_addr *addr, sa_family_t af, struct pf_addr_wrap *aw)
# ifdef RTF_PRCLONING
rtalloc_ign((struct route *)&ro, (RTF_CLONING|RTF_PRCLONING));
# else /* !RTF_PRCLONING */
+#ifdef INET
if (af == AF_INET)
in_rtalloc_ign((struct route *)&ro, 0, 0);
else
+#endif
rtalloc_ign((struct route *)&ro, 0);
# endif
#else /* ! __FreeBSD__ */
@@ -6792,11 +6801,13 @@ pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p, sa_family_t a
KMOD_UDPSTAT_INC(udps_badsum);
break;
}
+#ifdef INET
case IPPROTO_ICMP:
{
KMOD_ICMPSTAT_INC(icps_checksum);
break;
}
+#endif
#ifdef INET6
case IPPROTO_ICMPV6:
{
@@ -6892,9 +6903,11 @@ pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p,
case IPPROTO_UDP:
KMOD_UDPSTAT_INC(udps_badsum);
break;
+#ifdef INET
case IPPROTO_ICMP:
KMOD_ICMPSTAT_INC(icps_checksum);
break;
+#endif
#ifdef INET6
case IPPROTO_ICMPV6:
KMOD_ICMP6STAT_INC(icp6s_checksum);
diff --git a/sys/contrib/pf/net/pf_ioctl.c b/sys/contrib/pf/net/pf_ioctl.c
index 2a66fd8..c41fcc6 100644
--- a/sys/contrib/pf/net/pf_ioctl.c
+++ b/sys/contrib/pf/net/pf_ioctl.c
@@ -3735,9 +3735,12 @@ pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
*/
int chk;
- /* We need a proper CSUM befor we start (s. OpenBSD ip_output) */
+ /* We need a proper CSUM before we start (s. OpenBSD ip_output) */
if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+#ifdef INET
+ /* XXX-BZ copy&paste error from r126261? */
in_delayed_cksum(*m);
+#endif
(*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
}
chk = pf_test6(PF_OUT, ifp, m, NULL, inp);
diff --git a/sys/contrib/pf/net/pf_norm.c b/sys/contrib/pf/net/pf_norm.c
index 32ba9f4..cd6d65a 100644
--- a/sys/contrib/pf/net/pf_norm.c
+++ b/sys/contrib/pf/net/pf_norm.c
@@ -949,6 +949,7 @@ pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
return (NULL);
}
+#ifdef INET
int
pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
struct pf_pdesc *pd)
@@ -1198,6 +1199,7 @@ pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
return (PF_DROP);
}
+#endif
#ifdef INET6
int
diff --git a/sys/dev/acpica/Osd/OsdDebug.c b/sys/dev/acpica/Osd/OsdDebug.c
index 8425357..0547f75 100644
--- a/sys/dev/acpica/Osd/OsdDebug.c
+++ b/sys/dev/acpica/Osd/OsdDebug.c
@@ -47,20 +47,23 @@ __FBSDID("$FreeBSD$");
#include <dev/acpica/acpivar.h>
-UINT32
-AcpiOsGetLine(char *Buffer)
+ACPI_STATUS
+AcpiOsGetLine(char *Buffer, UINT32 BufferLength, UINT32 *BytesRead)
{
#ifdef DDB
- char *cp;
+ char *cp;
- db_readline(Buffer, 80);
- for (cp = Buffer; *cp != 0; cp++)
- if (*cp == '\n')
- *cp = 0;
- return (AE_OK);
+ cp = Buffer;
+ if (db_readline(Buffer, BufferLength) > 0)
+ while (*cp != '\0' && *cp != '\n' && *cp != '\r')
+ cp++;
+ *cp = '\0';
+ if (BytesRead != NULL)
+ *BytesRead = cp - Buffer;
+ return (AE_OK);
#else
- printf("AcpiOsGetLine called but no input support");
- return (AE_NOT_EXIST);
+ printf("AcpiOsGetLine called but no input support");
+ return (AE_NOT_EXIST);
#endif /* DDB */
}
diff --git a/sys/dev/ath/ath_dfs/null/dfs_null.c b/sys/dev/ath/ath_dfs/null/dfs_null.c
new file mode 100644
index 0000000..2f050a4
--- /dev/null
+++ b/sys/dev/ath/ath_dfs/null/dfs_null.c
@@ -0,0 +1,160 @@
+/*-
+ * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * $FreeBSD$
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * This implements an empty DFS module.
+ */
+#include "opt_inet.h"
+#include "opt_wlan.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sysctl.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/errno.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/bus.h>
+
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h> /* XXX for ether_sprintf */
+
+#include <net80211/ieee80211_var.h>
+
+#include <net/bpf.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#endif
+
+#include <dev/ath/if_athvar.h>
+#include <dev/ath/if_athdfs.h>
+
+#include <dev/ath/ath_hal/ah_desc.h>
+
+/*
+ * Methods which are required
+ */
+
+/*
+ * Attach DFS to the given interface
+ */
+int
+ath_dfs_attach(struct ath_softc *sc)
+{
+ return 1;
+}
+
+/*
+ * Detach DFS from the given interface
+ */
+int
+ath_dfs_detach(struct ath_softc *sc)
+{
+ return 1;
+}
+
+/*
+ * Enable radar check
+ */
+void
+ath_dfs_radar_enable(struct ath_softc *sc, struct ieee80211_channel *chan)
+{
+ /* Check if the current channel is radar-enabled */
+ if (! IEEE80211_IS_CHAN_DFS(chan))
+ return;
+}
+
+/*
+ * Process DFS related PHY errors
+ */
+void
+ath_dfs_process_phy_err(struct ath_softc *sc, const char *buf,
+ uint64_t tsf, struct ath_rx_status *rxstat)
+{
+
+}
+
+/*
+ * Process the radar events and determine whether a DFS event has occured.
+ *
+ * This is designed to run outside of the RX processing path.
+ * The RX path will call ath_dfs_tasklet_needed() to see whether
+ * the task/callback running this routine needs to be called.
+ */
+int
+ath_dfs_process_radar_event(struct ath_softc *sc,
+ struct ieee80211_channel *chan)
+{
+ return 0;
+}
+
+/*
+ * Determine whether the the DFS check task needs to be queued.
+ *
+ * This is called in the RX task when the current batch of packets
+ * have been received. It will return whether there are any radar
+ * events for ath_dfs_process_radar_event() to handle.
+ */
+int
+ath_dfs_tasklet_needed(struct ath_softc *sc, struct ieee80211_channel *chan)
+{
+ return 0;
+}
+
+/*
+ * Handle ioctl requests from the diagnostic interface
+ */
+int
+ath_ioctl_phyerr(struct ath_softc *sc, struct ath_diag *ad)
+{
+ return 1;
+}
+
+/*
+ * Get the current DFS thresholds from the HAL
+ */
+int
+ath_dfs_get_thresholds(struct ath_softc *sc, HAL_PHYERR_PARAM *param)
+{
+ ath_hal_getdfsthresh(sc->sc_ah, param);
+ return 1;
+}
diff --git a/sys/dev/ath/ath_hal/ah.c b/sys/dev/ath/ath_hal/ah.c
index e84f9b3..647f322 100644
--- a/sys/dev/ath/ath_hal/ah.c
+++ b/sys/dev/ath/ath_hal/ah.c
@@ -610,6 +610,10 @@ ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
return HAL_OK;
case HAL_CAP_4ADDR_AGGR:
return pCap->hal4AddrAggrSupport ? HAL_OK : HAL_ENOTSUPP;
+ case HAL_CAP_EXT_CHAN_DFS:
+ return pCap->halExtChanDfsSupport ? HAL_OK : HAL_ENOTSUPP;
+ case HAL_CAP_COMBINED_RADAR_RSSI:
+ return pCap->halUseCombinedRadarRssi ? HAL_OK : HAL_ENOTSUPP;
case HAL_CAP_AUTO_SLEEP:
return pCap->halAutoSleepSupport ? HAL_OK : HAL_ENOTSUPP;
case HAL_CAP_MBSSID_AGGR_SUPPORT:
@@ -626,6 +630,8 @@ ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
case HAL_CAP_RXTSTAMP_PREC: /* rx desc tstamp precision (bits) */
*result = pCap->halTstampPrecision;
return HAL_OK;
+ case HAL_CAP_ENHANCED_DFS_SUPPORT:
+ return pCap->halEnhancedDfsSupport ? HAL_OK : HAL_ENOTSUPP;
/* FreeBSD-specific entries for now */
case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */
diff --git a/sys/dev/ath/ath_hal/ah.h b/sys/dev/ath/ath_hal/ah.h
index 7bf2843..165d919 100644
--- a/sys/dev/ath/ath_hal/ah.h
+++ b/sys/dev/ath/ath_hal/ah.h
@@ -121,6 +121,9 @@ typedef enum {
HAL_CAP_RTS_AGGR_LIMIT = 42, /* aggregation limit with RTS */
HAL_CAP_4ADDR_AGGR = 43, /* hardware is capable of 4addr aggregation */
+ HAL_CAP_DFS_DMN = 44, /* current DFS domain */
+ HAL_CAP_EXT_CHAN_DFS = 45, /* DFS support for extension channel */
+ HAL_CAP_COMBINED_RADAR_RSSI = 46, /* Is combined RSSI for radar accurate */
HAL_CAP_AUTO_SLEEP = 48, /* hardware can go to network sleep
automatically after waking up to receive TIM */
@@ -133,6 +136,7 @@ typedef enum {
HAL_CAP_HT20_SGI = 96, /* hardware supports HT20 short GI */
HAL_CAP_RXTSTAMP_PREC = 100, /* rx desc tstamp precision (bits) */
+ HAL_CAP_ENHANCED_DFS_SUPPORT = 117, /* hardware supports enhanced DFS */
/* The following are private to the FreeBSD HAL (224 onward) */
@@ -703,6 +707,44 @@ typedef enum {
HAL_CAP_INTMIT_SPUR_IMMUNITY_LEVEL = 6
} HAL_CAP_INTMIT_CMD;
+typedef struct {
+ int32_t pe_firpwr; /* FIR pwr out threshold */
+ int32_t pe_rrssi; /* Radar rssi thresh */
+ int32_t pe_height; /* Pulse height thresh */
+ int32_t pe_prssi; /* Pulse rssi thresh */
+ int32_t pe_inband; /* Inband thresh */
+
+ /* The following params are only for AR5413 and later */
+ u_int32_t pe_relpwr; /* Relative power threshold in 0.5dB steps */
+ u_int32_t pe_relstep; /* Pulse Relative step threshold in 0.5dB steps */
+ u_int32_t pe_maxlen; /* Max length of radar sign in 0.8us units */
+ HAL_BOOL pe_usefir128; /* Use the average in-band power measured over 128 cycles */
+ HAL_BOOL pe_blockradar; /*
+ * Enable to block radar check if pkt detect is done via OFDM
+ * weak signal detect or pkt is detected immediately after tx
+ * to rx transition
+ */
+ HAL_BOOL pe_enmaxrssi; /*
+ * Enable to use the max rssi instead of the last rssi during
+ * fine gain changes for radar detection
+ */
+ HAL_BOOL pe_extchannel; /* Enable DFS on ext channel */
+} HAL_PHYERR_PARAM;
+
+#define HAL_PHYERR_PARAM_NOVAL 65535
+#define HAL_PHYERR_PARAM_ENABLE 0x8000 /* Enable/Disable if applicable */
+
+
+/*
+ * Flag for setting QUIET period
+ */
+typedef enum {
+ HAL_QUIET_DISABLE = 0x0,
+ HAL_QUIET_ENABLE = 0x1,
+ HAL_QUIET_ADD_CURRENT_TSF = 0x2, /* add current TSF to next_start offset */
+ HAL_QUIET_ADD_SWBA_RESP_TIME = 0x4, /* add beacon response time to next_start offset */
+} HAL_QUIET_FLAG;
+
/*
* Hardware Access Layer (HAL) API.
*
@@ -877,6 +919,15 @@ struct ath_hal {
u_int __ahdecl(*ah_getCTSTimeout)(struct ath_hal*);
HAL_BOOL __ahdecl(*ah_setDecompMask)(struct ath_hal*, uint16_t, int);
void __ahdecl(*ah_setCoverageClass)(struct ath_hal*, uint8_t, int);
+ HAL_STATUS __ahdecl(*ah_setQuiet)(struct ath_hal *ah, uint32_t period,
+ uint32_t duration, uint32_t nextStart,
+ HAL_QUIET_FLAG flag);
+
+ /* DFS functions */
+ void __ahdecl(*ah_enableDfs)(struct ath_hal *ah,
+ HAL_PHYERR_PARAM *pe);
+ void __ahdecl(*ah_getDfsThresh)(struct ath_hal *ah,
+ HAL_PHYERR_PARAM *pe);
/* Key Cache Functions */
uint32_t __ahdecl(*ah_getKeyCacheSize)(struct ath_hal*);
diff --git a/sys/dev/ath/ath_hal/ah_desc.h b/sys/dev/ath/ath_hal/ah_desc.h
index ff6f40c..bd3e6a8 100644
--- a/sys/dev/ath/ath_hal/ah_desc.h
+++ b/sys/dev/ath/ath_hal/ah_desc.h
@@ -144,7 +144,7 @@ enum {
HAL_PHYERR_RADAR = 5, /* Radar detect */
HAL_PHYERR_SERVICE = 6, /* Illegal service */
HAL_PHYERR_TOR = 7, /* Transmit override receive */
- /* NB: these are specific to the 5212 */
+ /* NB: these are specific to the 5212 and later */
HAL_PHYERR_OFDM_TIMING = 17, /* */
HAL_PHYERR_OFDM_SIGNAL_PARITY = 18, /* */
HAL_PHYERR_OFDM_RATE_ILLEGAL = 19, /* */
@@ -152,6 +152,7 @@ enum {
HAL_PHYERR_OFDM_POWER_DROP = 21, /* */
HAL_PHYERR_OFDM_SERVICE = 22, /* */
HAL_PHYERR_OFDM_RESTART = 23, /* */
+ HAL_PHYERR_FALSE_RADAR_EXT = 24, /* */
HAL_PHYERR_CCK_TIMING = 25, /* */
HAL_PHYERR_CCK_HEADER_CRC = 26, /* */
HAL_PHYERR_CCK_RATE_ILLEGAL = 27, /* */
diff --git a/sys/dev/ath/ath_hal/ah_internal.h b/sys/dev/ath/ath_hal/ah_internal.h
index b994eab..d66c9d8 100644
--- a/sys/dev/ath/ath_hal/ah_internal.h
+++ b/sys/dev/ath/ath_hal/ah_internal.h
@@ -200,8 +200,10 @@ typedef struct {
halRifsTxSupport : 1,
hal4AddrAggrSupport : 1,
halExtChanDfsSupport : 1,
+ halUseCombinedRadarRssi : 1,
halForcePpmSupport : 1,
halEnhancedPmSupport : 1,
+ halEnhancedDfsSupport : 1,
halMbssidAggrSupport : 1,
halBssidMatchSupport : 1,
hal4kbSplitTransSupport : 1,
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212.h b/sys/dev/ath/ath_hal/ar5212/ar5212.h
index 5bdfcb4..16394a3 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212.h
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212.h
@@ -506,6 +506,8 @@ extern HAL_BOOL ar5212SetCapability(struct ath_hal *, HAL_CAPABILITY_TYPE,
extern HAL_BOOL ar5212GetDiagState(struct ath_hal *ah, int request,
const void *args, uint32_t argsize,
void **result, uint32_t *resultsize);
+extern HAL_STATUS ar5212SetQuiet(struct ath_hal *ah, uint32_t period,
+ uint32_t duration, uint32_t nextStart, HAL_QUIET_FLAG flag);
extern HAL_BOOL ar5212SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode,
int setChip);
@@ -618,5 +620,7 @@ extern void ar5212AniReset(struct ath_hal *, const struct ieee80211_channel *,
extern HAL_BOOL ar5212IsNFCalInProgress(struct ath_hal *ah);
extern HAL_BOOL ar5212WaitNFCalComplete(struct ath_hal *ah, int i);
+extern void ar5212EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe);
+extern void ar5212GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe);
#endif /* _ATH_AR5212_H_ */
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c b/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c
index 5f85522..5999a60 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c
@@ -127,6 +127,11 @@ static const struct ath_hal_private ar5212hal = {{
.ah_getCTSTimeout = ar5212GetCTSTimeout,
.ah_setDecompMask = ar5212SetDecompMask,
.ah_setCoverageClass = ar5212SetCoverageClass,
+ .ah_setQuiet = ar5212SetQuiet,
+
+ /* DFS Functions */
+ .ah_enableDfs = ar5212EnableDfs,
+ .ah_getDfsThresh = ar5212GetDfsThresh,
/* Key Cache Functions */
.ah_getKeyCacheSize = ar5212GetKeyCacheSize,
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c b/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c
index 518d079..276671d 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c
@@ -634,6 +634,20 @@ ar5212SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now)
}
}
+HAL_STATUS
+ar5212SetQuiet(struct ath_hal *ah, uint32_t period, uint32_t duration,
+ uint32_t nextStart, HAL_QUIET_FLAG flag)
+{
+ OS_REG_WRITE(ah, AR_QUIET2, period | (duration << AR_QUIET2_QUIET_DUR_S));
+ if (flag & HAL_QUIET_ENABLE) {
+ OS_REG_WRITE(ah, AR_QUIET1, nextStart | (1 << 16));
+ }
+ else {
+ OS_REG_WRITE(ah, AR_QUIET1, nextStart);
+ }
+ return HAL_OK;
+}
+
void
ar5212SetPCUConfig(struct ath_hal *ah)
{
@@ -1115,3 +1129,54 @@ ar5212WaitNFCalComplete(struct ath_hal *ah, int i)
}
return AH_FALSE;
}
+
+void
+ar5212EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
+{
+ uint32_t val;
+ val = OS_REG_READ(ah, AR_PHY_RADAR_0);
+
+ if (pe->pe_firpwr != HAL_PHYERR_PARAM_NOVAL) {
+ val &= ~AR_PHY_RADAR_0_FIRPWR;
+ val |= SM(pe->pe_firpwr, AR_PHY_RADAR_0_FIRPWR);
+ }
+ if (pe->pe_rrssi != HAL_PHYERR_PARAM_NOVAL) {
+ val &= ~AR_PHY_RADAR_0_RRSSI;
+ val |= SM(pe->pe_rrssi, AR_PHY_RADAR_0_RRSSI);
+ }
+ if (pe->pe_height != HAL_PHYERR_PARAM_NOVAL) {
+ val &= ~AR_PHY_RADAR_0_HEIGHT;
+ val |= SM(pe->pe_height, AR_PHY_RADAR_0_HEIGHT);
+ }
+ if (pe->pe_prssi != HAL_PHYERR_PARAM_NOVAL) {
+ val &= ~AR_PHY_RADAR_0_PRSSI;
+ val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI);
+ }
+ if (pe->pe_inband != HAL_PHYERR_PARAM_NOVAL) {
+ val &= ~AR_PHY_RADAR_0_INBAND;
+ val |= SM(pe->pe_inband, AR_PHY_RADAR_0_INBAND);
+ }
+ OS_REG_WRITE(ah, AR_PHY_RADAR_0, val | AR_PHY_RADAR_0_ENA);
+}
+
+void
+ar5212GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
+{
+ uint32_t val,temp;
+
+ val = OS_REG_READ(ah, AR_PHY_RADAR_0);
+
+ temp = MS(val,AR_PHY_RADAR_0_FIRPWR);
+ temp |= 0xFFFFFF80;
+ pe->pe_firpwr = temp;
+ pe->pe_rrssi = MS(val, AR_PHY_RADAR_0_RRSSI);
+ pe->pe_height = MS(val, AR_PHY_RADAR_0_HEIGHT);
+ pe->pe_prssi = MS(val, AR_PHY_RADAR_0_PRSSI);
+ pe->pe_inband = MS(val, AR_PHY_RADAR_0_INBAND);
+
+ pe->pe_relpwr = 0;
+ pe->pe_relstep = 0;
+ pe->pe_maxlen = 0;
+ pe->pe_extchannel = AH_FALSE;
+}
+
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212reg.h b/sys/dev/ath/ath_hal/ar5212/ar5212reg.h
index f99b203..15c1a58 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212reg.h
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212reg.h
@@ -300,6 +300,7 @@
#define AR_QUIET1_NEXT_QUIET 0xffff
#define AR_QUIET1_QUIET_ENABLE 0x10000 /* Enable Quiet time operation */
#define AR_QUIET1_QUIET_ACK_CTS_ENABLE 0x20000 /* Do we ack/cts during quiet period */
+#define AR_QUIET1_QUIET_ACK_CTS_ENABLE_S 17
#define AR_QUIET2 0x8100 /* More Quiet time programming */
#define AR_QUIET2_QUIET_PER_S 0 /* Periodicity of quiet period (TU) */
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416.h b/sys/dev/ath/ath_hal/ar5416/ar5416.h
index 5327296..510afe0 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416.h
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416.h
@@ -194,6 +194,8 @@ extern uint32_t ar5416Get11nExtBusy(struct ath_hal *ah);
extern void ar5416Set11nMac2040(struct ath_hal *ah, HAL_HT_MACMODE mode);
extern HAL_HT_RXCLEAR ar5416Get11nRxClear(struct ath_hal *ah);
extern void ar5416Set11nRxClear(struct ath_hal *ah, HAL_HT_RXCLEAR rxclear);
+extern HAL_STATUS ar5416SetQuiet(struct ath_hal *ah, uint32_t period,
+ uint32_t duration, uint32_t nextStart, HAL_QUIET_FLAG flag);
extern HAL_STATUS ar5416GetCapability(struct ath_hal *ah,
HAL_CAPABILITY_TYPE type, uint32_t capability, uint32_t *result);
extern HAL_BOOL ar5416GetDiagState(struct ath_hal *ah, int request,
@@ -201,6 +203,8 @@ extern HAL_BOOL ar5416GetDiagState(struct ath_hal *ah, int request,
void **result, uint32_t *resultsize);
extern HAL_BOOL ar5416SetRifsDelay(struct ath_hal *ah,
const struct ieee80211_channel *chan, HAL_BOOL enable);
+extern void ar5416EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe);
+extern void ar5416GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe);
extern HAL_BOOL ar5416SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode,
int setChip);
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c
index dc1a5ff..22d05ff 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c
@@ -139,10 +139,15 @@ ar5416InitState(struct ath_hal_5416 *ahp5416, uint16_t devid, HAL_SOFTC sc,
ah->ah_setAntennaSwitch = ar5416SetAntennaSwitch;
ah->ah_setDecompMask = ar5416SetDecompMask;
ah->ah_setCoverageClass = ar5416SetCoverageClass;
+ ah->ah_setQuiet = ar5416SetQuiet;
ah->ah_resetKeyCacheEntry = ar5416ResetKeyCacheEntry;
ah->ah_setKeyCacheEntry = ar5416SetKeyCacheEntry;
+ /* DFS Functions */
+ ah->ah_enableDfs = ar5416EnableDfs;
+ ah->ah_getDfsThresh = ar5416GetDfsThresh;
+
/* Power Management Functions */
ah->ah_setPowerMode = ar5416SetPowerMode;
@@ -878,6 +883,7 @@ ar5416FillCapabilityInfo(struct ath_hal *ah)
pCap->halBssidMatchSupport = AH_TRUE;
pCap->halGTTSupport = AH_TRUE;
pCap->halCSTSupport = AH_TRUE;
+ pCap->halEnhancedDfsSupport = AH_FALSE;
if (ath_hal_eepromGetFlag(ah, AR_EEP_RFKILL) &&
ath_hal_eepromGet(ah, AR_EEP_RFSILENT, &ahpriv->ah_rfsilent) == HAL_OK) {
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c b/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c
index 8f18c46..2c08730 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c
@@ -273,6 +273,35 @@ ar5416Set11nRxClear(struct ath_hal *ah, HAL_HT_RXCLEAR rxclear)
}
}
+/* XXX shouldn't be here! */
+#define TU_TO_USEC(_tu) ((_tu) << 10)
+
+HAL_STATUS
+ar5416SetQuiet(struct ath_hal *ah, uint32_t period, uint32_t duration,
+ uint32_t nextStart, HAL_QUIET_FLAG flag)
+{
+ uint32_t period_us = TU_TO_USEC(period); /* convert to us unit */
+ uint32_t nextStart_us = TU_TO_USEC(nextStart); /* convert to us unit */
+ if (flag & HAL_QUIET_ENABLE) {
+ if ((!nextStart) || (flag & HAL_QUIET_ADD_CURRENT_TSF)) {
+ /* Add the nextStart offset to the current TSF */
+ nextStart_us += OS_REG_READ(ah, AR_TSF_L32);
+ }
+ if (flag & HAL_QUIET_ADD_SWBA_RESP_TIME) {
+ nextStart_us += ath_hal_sw_beacon_response_time;
+ }
+ OS_REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);
+ OS_REG_WRITE(ah, AR_QUIET2, SM(duration, AR_QUIET2_QUIET_DUR));
+ OS_REG_WRITE(ah, AR_QUIET_PERIOD, period_us);
+ OS_REG_WRITE(ah, AR_NEXT_QUIET, nextStart_us);
+ OS_REG_SET_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET);
+ } else {
+ OS_REG_CLR_BIT(ah, AR_TIMER_MODE, AR_TIMER_MODE_QUIET);
+ }
+ return HAL_OK;
+}
+#undef TU_TO_USEC
+
HAL_STATUS
ar5416GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
uint32_t capability, uint32_t *result)
@@ -560,3 +589,106 @@ ar5416DetectBBHang(struct ath_hal *ah)
#undef N
}
#undef NUM_STATUS_READS
+
+/*
+ * Get the radar parameter values and return them in the pe
+ * structure
+ */
+void
+ar5416GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
+{
+ uint32_t val, temp;
+
+ val = OS_REG_READ(ah, AR_PHY_RADAR_0);
+
+ temp = MS(val,AR_PHY_RADAR_0_FIRPWR);
+ temp |= 0xFFFFFF80;
+ pe->pe_firpwr = temp;
+ pe->pe_rrssi = MS(val, AR_PHY_RADAR_0_RRSSI);
+ pe->pe_height = MS(val, AR_PHY_RADAR_0_HEIGHT);
+ pe->pe_prssi = MS(val, AR_PHY_RADAR_0_PRSSI);
+ pe->pe_inband = MS(val, AR_PHY_RADAR_0_INBAND);
+
+ val = OS_REG_READ(ah, AR_PHY_RADAR_1);
+ temp = val & AR_PHY_RADAR_1_RELPWR_ENA;
+ pe->pe_relpwr = MS(val, AR_PHY_RADAR_1_RELPWR_THRESH);
+ if (temp)
+ pe->pe_relpwr |= HAL_PHYERR_PARAM_ENABLE;
+ temp = val & AR_PHY_RADAR_1_RELSTEP_CHECK;
+ pe->pe_relstep = MS(val, AR_PHY_RADAR_1_RELSTEP_THRESH);
+ if (temp)
+ pe->pe_relstep |= HAL_PHYERR_PARAM_ENABLE;
+ pe->pe_maxlen = MS(val, AR_PHY_RADAR_1_MAXLEN);
+ pe->pe_extchannel = !! (OS_REG_READ(ah, AR_PHY_RADAR_EXT) &
+ AR_PHY_RADAR_EXT_ENA);
+}
+
+/*
+ * Enable radar detection and set the radar parameters per the
+ * values in pe
+ */
+void
+ar5416EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
+{
+ uint32_t val;
+
+ val = OS_REG_READ(ah, AR_PHY_RADAR_0);
+
+ if (pe->pe_firpwr != HAL_PHYERR_PARAM_NOVAL) {
+ val &= ~AR_PHY_RADAR_0_FIRPWR;
+ val |= SM(pe->pe_firpwr, AR_PHY_RADAR_0_FIRPWR);
+ }
+ if (pe->pe_rrssi != HAL_PHYERR_PARAM_NOVAL) {
+ val &= ~AR_PHY_RADAR_0_RRSSI;
+ val |= SM(pe->pe_rrssi, AR_PHY_RADAR_0_RRSSI);
+ }
+ if (pe->pe_height != HAL_PHYERR_PARAM_NOVAL) {
+ val &= ~AR_PHY_RADAR_0_HEIGHT;
+ val |= SM(pe->pe_height, AR_PHY_RADAR_0_HEIGHT);
+ }
+ if (pe->pe_prssi != HAL_PHYERR_PARAM_NOVAL) {
+ val &= ~AR_PHY_RADAR_0_PRSSI;
+ val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI);
+ }
+ if (pe->pe_inband != HAL_PHYERR_PARAM_NOVAL) {
+ val &= ~AR_PHY_RADAR_0_INBAND;
+ val |= SM(pe->pe_inband, AR_PHY_RADAR_0_INBAND);
+ }
+
+ /*Enable FFT data*/
+ val |= AR_PHY_RADAR_0_FFT_ENA;
+
+ OS_REG_WRITE(ah, AR_PHY_RADAR_0, val | AR_PHY_RADAR_0_ENA);
+
+ val = OS_REG_READ(ah, AR_PHY_RADAR_1);
+ val |= (AR_PHY_RADAR_1_MAX_RRSSI | AR_PHY_RADAR_1_BLOCK_CHECK);
+
+ if (pe->pe_maxlen != HAL_PHYERR_PARAM_NOVAL) {
+ val &= ~AR_PHY_RADAR_1_MAXLEN;
+ val |= SM(pe->pe_maxlen, AR_PHY_RADAR_1_MAXLEN);
+ }
+ OS_REG_WRITE(ah, AR_PHY_RADAR_1, val);
+
+ /*
+ * Enable HT/40 if the upper layer asks;
+ * it should check the channel is HT/40 and HAL_CAP_EXT_CHAN_DFS
+ * is available.
+ */
+ if (pe->pe_extchannel)
+ OS_REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
+ else
+ OS_REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
+
+ if (pe->pe_relstep != HAL_PHYERR_PARAM_NOVAL) {
+ val = OS_REG_READ(ah, AR_PHY_RADAR_1);
+ val &= ~AR_PHY_RADAR_1_RELSTEP_THRESH;
+ val |= SM(pe->pe_relstep, AR_PHY_RADAR_1_RELSTEP_THRESH);
+ OS_REG_WRITE(ah, AR_PHY_RADAR_1, val);
+ }
+ if (pe->pe_relpwr != HAL_PHYERR_PARAM_NOVAL) {
+ val = OS_REG_READ(ah, AR_PHY_RADAR_1);
+ val &= ~AR_PHY_RADAR_1_RELPWR_THRESH;
+ val |= SM(pe->pe_relpwr, AR_PHY_RADAR_1_RELPWR_THRESH);
+ OS_REG_WRITE(ah, AR_PHY_RADAR_1, val);
+ }
+}
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416phy.h b/sys/dev/ath/ath_hal/ar5416/ar5416phy.h
index 2c419d7..d7a5e0b 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416phy.h
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416phy.h
@@ -21,6 +21,25 @@
#include "ar5212/ar5212phy.h"
+/* For AR_PHY_RADAR0 */
+#define AR_PHY_RADAR_0_FFT_ENA 0x80000000
+
+#define AR_PHY_RADAR_EXT 0x9940
+#define AR_PHY_RADAR_EXT_ENA 0x00004000
+
+#define AR_PHY_RADAR_1 0x9958
+#define AR_PHY_RADAR_1_RELPWR_ENA 0x00800000
+#define AR_PHY_RADAR_1_USE_FIR128 0x00400000
+#define AR_PHY_RADAR_1_RELPWR_THRESH 0x003F0000
+#define AR_PHY_RADAR_1_RELPWR_THRESH_S 16
+#define AR_PHY_RADAR_1_BLOCK_CHECK 0x00008000
+#define AR_PHY_RADAR_1_MAX_RRSSI 0x00004000
+#define AR_PHY_RADAR_1_RELSTEP_CHECK 0x00002000
+#define AR_PHY_RADAR_1_RELSTEP_THRESH 0x00001F00
+#define AR_PHY_RADAR_1_RELSTEP_THRESH_S 8
+#define AR_PHY_RADAR_1_MAXLEN 0x000000FF
+#define AR_PHY_RADAR_1_MAXLEN_S 0
+
#define AR_PHY_CHIP_ID_REV_0 0x80 /* 5416 Rev 0 (owl 1.0) BB */
#define AR_PHY_CHIP_ID_REV_1 0x81 /* 5416 Rev 1 (owl 2.0) BB */
diff --git a/sys/dev/ath/ath_hal/ar9001/ar9130_attach.c b/sys/dev/ath/ath_hal/ar9001/ar9130_attach.c
index 49a5f5e..2a3f3f0 100644
--- a/sys/dev/ath/ath_hal/ar9001/ar9130_attach.c
+++ b/sys/dev/ath/ath_hal/ar9001/ar9130_attach.c
@@ -289,6 +289,7 @@ ar9130FillCapabilityInfo(struct ath_hal *ah)
pCap->halRifsTxSupport = AH_TRUE;
pCap->halRtsAggrLimit = 64*1024; /* 802.11n max */
pCap->halExtChanDfsSupport = AH_TRUE;
+ pCap->halUseCombinedRadarRssi = AH_TRUE;
pCap->halAutoSleepSupport = AH_FALSE; /* XXX? */
/*
* MBSSID aggregation is broken in Howl v1.1, v1.2, v1.3
diff --git a/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c b/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c
index 0d950d2..44a549d 100644
--- a/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c
+++ b/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c
@@ -293,6 +293,7 @@ ar9160FillCapabilityInfo(struct ath_hal *ah)
pCap->halRifsTxSupport = AH_TRUE;
pCap->halRtsAggrLimit = 64*1024; /* 802.11n max */
pCap->halExtChanDfsSupport = AH_TRUE;
+ pCap->halUseCombinedRadarRssi = AH_TRUE;
pCap->halAutoSleepSupport = AH_FALSE; /* XXX? */
pCap->halMbssidAggrSupport = AH_TRUE;
pCap->hal4AddrAggrSupport = AH_TRUE;
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c b/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c
index 77b9f58..ebe3be1 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c
+++ b/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c
@@ -783,6 +783,7 @@ ar9280FillCapabilityInfo(struct ath_hal *ah)
pCap->halRifsTxSupport = AH_TRUE;
pCap->halRtsAggrLimit = 64*1024; /* 802.11n max */
pCap->halExtChanDfsSupport = AH_TRUE;
+ pCap->halUseCombinedRadarRssi = AH_TRUE;
#if 0
/* XXX bluetooth */
pCap->halBtCoexSupport = AH_TRUE;
@@ -804,6 +805,7 @@ ar9280FillCapabilityInfo(struct ath_hal *ah)
}
pCap->halRxStbcSupport = 1;
pCap->halTxStbcSupport = 1;
+ pCap->halEnhancedDfsSupport = AH_TRUE;
return AH_TRUE;
}
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c b/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c
index 111bea2..9120313 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c
+++ b/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c
@@ -414,6 +414,7 @@ ar9285FillCapabilityInfo(struct ath_hal *ah)
pCap->halRifsTxSupport = AH_TRUE;
pCap->halRtsAggrLimit = 64*1024; /* 802.11n max */
pCap->halExtChanDfsSupport = AH_TRUE;
+ pCap->halUseCombinedRadarRssi = AH_TRUE;
#if 0
/* XXX bluetooth */
pCap->halBtCoexSupport = AH_TRUE;
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c b/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c
index fdf1f96..9cbe0a5 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c
+++ b/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c
@@ -430,6 +430,7 @@ ar9287FillCapabilityInfo(struct ath_hal *ah)
pCap->halRifsTxSupport = AH_TRUE;
pCap->halRtsAggrLimit = 64*1024; /* 802.11n max */
pCap->halExtChanDfsSupport = AH_TRUE;
+ pCap->halUseCombinedRadarRssi = AH_TRUE;
#if 0
/* XXX bluetooth */
pCap->halBtCoexSupport = AH_TRUE;
@@ -447,6 +448,8 @@ ar9287FillCapabilityInfo(struct ath_hal *ah)
/* Hardware supports short-GI w/ 20MHz */
pCap->halHTSGI20Support = 1;
+ pCap->halEnhancedDfsSupport = AH_TRUE;
+
return AH_TRUE;
}
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c
index 5527098..6c7b0e7 100644
--- a/sys/dev/ath/if_ath.c
+++ b/sys/dev/ath/if_ath.c
@@ -95,11 +95,13 @@ __FBSDID("$FreeBSD$");
#include <dev/ath/if_ath_tx.h>
#include <dev/ath/if_ath_sysctl.h>
#include <dev/ath/if_ath_keycache.h>
+#include <dev/ath/if_athdfs.h>
#ifdef ATH_TX99_DIAG
#include <dev/ath/ath_tx99/ath_tx99.h>
#endif
+
/*
* ATH_BCBUF determines the number of vap's that can transmit
* beacons and also (currently) the number of vap's that can
@@ -199,6 +201,8 @@ static void ath_setcurmode(struct ath_softc *, enum ieee80211_phymode);
static void ath_announce(struct ath_softc *);
+static void ath_dfs_tasklet(void *, int);
+
#ifdef IEEE80211_SUPPORT_TDMA
static void ath_tdma_settimers(struct ath_softc *sc, u_int32_t nexttbtt,
u_int32_t bintval);
@@ -471,6 +475,16 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
goto bad2;
}
+ /* Attach DFS module */
+ if (! ath_dfs_attach(sc)) {
+ device_printf(sc->sc_dev, "%s: unable to attach DFS\n", __func__);
+ error = EIO;
+ goto bad2;
+ }
+
+ /* Start DFS processing tasklet */
+ TASK_INIT(&sc->sc_dfstask, 0, ath_dfs_tasklet, sc);
+
sc->sc_blinking = 0;
sc->sc_ledstate = 1;
sc->sc_ledon = 0; /* low true */
@@ -771,6 +785,8 @@ ath_detach(struct ath_softc *sc)
sc->sc_tx99->detach(sc->sc_tx99);
#endif
ath_rate_detach(sc->sc_rc);
+
+ ath_dfs_detach(sc);
ath_desc_free(sc);
ath_tx_cleanup(sc);
ath_hal_detach(sc->sc_ah); /* NB: sets chip in full sleep */
@@ -984,6 +1000,21 @@ ath_vap_create(struct ieee80211com *ic,
avp->av_bmiss = vap->iv_bmiss;
vap->iv_bmiss = ath_bmiss_vap;
+ /* Set default parameters */
+
+ /*
+ * Anything earlier than some AR9300 series MACs don't
+ * support a smaller MPDU density.
+ */
+ vap->iv_ampdu_density = IEEE80211_HTCAP_MPDUDENSITY_8;
+ /*
+ * All NICs can handle the maximum size, however
+ * AR5416 based MACs can only TX aggregates w/ RTS
+ * protection when the total aggregate size is <= 8k.
+ * However, for now that's enforced by the TX path.
+ */
+ vap->iv_ampdu_rxmax = IEEE80211_HTCAP_MAXRXAMPDU_64K;
+
avp->av_bslot = -1;
if (needbeacon) {
/*
@@ -1230,6 +1261,10 @@ ath_resume(struct ath_softc *sc)
sc->sc_curchan != NULL ? sc->sc_curchan : ic->ic_curchan,
AH_FALSE, &status);
ath_reset_keycache(sc);
+
+ /* Let DFS at it in case it's a DFS channel */
+ ath_dfs_radar_enable(sc, ic->ic_curchan);
+
if (sc->sc_resume_up) {
if (ic->ic_opmode == IEEE80211_M_STA) {
ath_init(sc);
@@ -1539,6 +1574,9 @@ ath_init(void *arg)
}
ath_chan_change(sc, ic->ic_curchan);
+ /* Let DFS at it in case it's a DFS channel */
+ ath_dfs_radar_enable(sc, ic->ic_curchan);
+
/*
* Likewise this is set during reset so update
* state cached in the driver.
@@ -1684,6 +1722,10 @@ ath_reset(struct ifnet *ifp)
if_printf(ifp, "%s: unable to reset hardware; hal status %u\n",
__func__, status);
sc->sc_diversity = ath_hal_getdiversity(ah);
+
+ /* Let DFS at it in case it's a DFS channel */
+ ath_dfs_radar_enable(sc, ic->ic_curchan);
+
if (ath_startrecv(sc) != 0) /* restart recv */
if_printf(ifp, "%s: unable to start recv logic\n", __func__);
/*
@@ -1975,6 +2017,10 @@ ath_calcrxfilter(struct ath_softc *sc)
if (ic->ic_opmode == IEEE80211_M_MONITOR)
rfilt |= HAL_RX_FILTER_CONTROL;
+ if (sc->sc_dodfs) {
+ rfilt |= HAL_RX_FILTER_PHYRADAR;
+ }
+
/*
* Enable RX of compressed BAR frames only when doing
* 802.11n. Required for A-MPDU.
@@ -3426,6 +3472,17 @@ ath_rx_proc(void *arg, int npending)
sc->sc_stats.ast_rx_fifoerr++;
if (rs->rs_status & HAL_RXERR_PHY) {
sc->sc_stats.ast_rx_phyerr++;
+ /* Process DFS radar events */
+ if ((rs->rs_phyerr == HAL_PHYERR_RADAR) ||
+ (rs->rs_phyerr == HAL_PHYERR_FALSE_RADAR_EXT)) {
+ /* Since we're touching the frame data, sync it */
+ bus_dmamap_sync(sc->sc_dmat,
+ bf->bf_dmamap,
+ BUS_DMASYNC_POSTREAD);
+ /* Now pass it to the radar processing code */
+ ath_dfs_process_phy_err(sc, mtod(m, char *), tsf, rs);
+ }
+
/* Be suitably paranoid about receiving phy errors out of the stats array bounds */
if (rs->rs_phyerr < 64)
sc->sc_stats.ast_rx_phy[rs->rs_phyerr]++;
@@ -3667,6 +3724,10 @@ rx_next:
if (ngood)
sc->sc_lastrx = tsf;
+ /* Queue DFS tasklet if needed */
+ if (ath_dfs_tasklet_needed(sc, sc->sc_curchan))
+ taskqueue_enqueue(sc->sc_tq, &sc->sc_dfstask);
+
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
#ifdef IEEE80211_SUPPORT_SUPERG
ieee80211_ff_age_all(ic, 100);
@@ -4384,6 +4445,9 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan)
}
sc->sc_diversity = ath_hal_getdiversity(ah);
+ /* Let DFS at it in case it's a DFS channel */
+ ath_dfs_radar_enable(sc, ic->ic_curchan);
+
/*
* Re-enable rx framework.
*/
@@ -5650,5 +5714,23 @@ ath_tdma_beacon_send(struct ath_softc *sc, struct ieee80211vap *vap)
}
#endif /* IEEE80211_SUPPORT_TDMA */
+static void
+ath_dfs_tasklet(void *p, int npending)
+{
+ struct ath_softc *sc = (struct ath_softc *) p;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+
+ /*
+ * If previous processing has found a radar event,
+ * signal this to the net80211 layer to begin DFS
+ * processing.
+ */
+ if (ath_dfs_process_radar_event(sc, sc->sc_curchan)) {
+ /* DFS event found, initiate channel change */
+ ieee80211_dfs_notify_radar(ic, sc->sc_curchan);
+ }
+}
+
MODULE_VERSION(if_ath, 1);
MODULE_DEPEND(if_ath, wlan, 1, 1, 1); /* 802.11 media layer */
diff --git a/sys/dev/ath/if_ath_tx_ht.c b/sys/dev/ath/if_ath_tx_ht.c
index f4ade31..348a1499 100644
--- a/sys/dev/ath/if_ath_tx_ht.c
+++ b/sys/dev/ath/if_ath_tx_ht.c
@@ -136,15 +136,23 @@ ath_rateseries_setup(struct ath_softc *sc, struct ieee80211_node *ni,
*/
if (ni->ni_chw == 40)
series[i].RateFlags |= HAL_RATESERIES_2040;
-#if 0
+
/*
- * The hardware only supports short-gi in 40mhz mode -
- * if later hardware supports it in 20mhz mode, be sure
- * to add the relevant check here.
+ * Set short-GI only if the node has advertised it
+ * the channel width is suitable, and we support it.
+ * We don't currently have a "negotiated" set of bits -
+ * ni_htcap is what the remote end sends, not what this
+ * node is capable of.
*/
- if (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40)
+ if (ni->ni_chw == 40 &&
+ ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 &&
+ ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40)
+ series[i].RateFlags |= HAL_RATESERIES_HALFGI;
+
+ if (ni->ni_chw == 20 &&
+ ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 &&
+ ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20)
series[i].RateFlags |= HAL_RATESERIES_HALFGI;
-#endif
series[i].Rate = rt->info[rix[i]].rateCode;
diff --git a/sys/dev/ath/if_athdfs.h b/sys/dev/ath/if_athdfs.h
new file mode 100644
index 0000000..88ee7fc
--- /dev/null
+++ b/sys/dev/ath/if_athdfs.h
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
+ *
+ * $FreeBSD$
+ */
+#ifndef __IF_ATHDFS_H__
+#define __IF_ATHDFS_H__
+
+extern int ath_dfs_attach(struct ath_softc *sc);
+extern int ath_dfs_detach(struct ath_softc *sc);
+extern void ath_dfs_radar_enable(struct ath_softc *,
+ struct ieee80211_channel *chan);
+extern void ath_dfs_process_phy_err(struct ath_softc *sc, const char *buf,
+ uint64_t tsf, struct ath_rx_status *rxstat);
+extern int ath_dfs_process_radar_event(struct ath_softc *sc,
+ struct ieee80211_channel *chan);
+extern int ath_dfs_tasklet_needed(struct ath_softc *sc,
+ struct ieee80211_channel *chan);
+extern int ath_ioctl_phyerr(struct ath_softc *sc, struct ath_diag *ad);
+extern int ath_dfs_get_thresholds(struct ath_softc *sc, HAL_PHYERR_PARAM *param);
+
+#endif /* __IF_ATHDFS_H__ */
diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h
index 6353847..97666c5 100644
--- a/sys/dev/ath/if_athvar.h
+++ b/sys/dev/ath/if_athvar.h
@@ -357,6 +357,11 @@ struct ath_softc {
uint16_t *sc_eepromdata; /* Local eeprom data, if AR9100 */
int sc_txchainmask; /* currently configured TX chainmask */
int sc_rxchainmask; /* currently configured RX chainmask */
+
+ /* DFS related state */
+ void *sc_dfs; /* Used by an optional DFS module */
+ int sc_dodfs; /* Whether to enable DFS rx filter bits */
+ struct task sc_dfstask; /* DFS processing task */
};
#define ATH_LOCK_INIT(_sc) \
@@ -694,6 +699,17 @@ void ath_intr(void *);
#define ath_hal_set11nburstduration(_ah, _ds, _dur) \
((*(_ah)->ah_set11nBurstDuration)((_ah), (_ds), (_dur)))
+/*
+ * This is badly-named; you need to set the correct parameters
+ * to begin to receive useful radar events; and even then
+ * it doesn't "enable" DFS. See the ath_dfs/null/ module for
+ * more information.
+ */
+#define ath_hal_enabledfs(_ah, _param) \
+ ((*(_ah)->ah_enableDfs)((_ah), (_param)))
+#define ath_hal_getdfsthresh(_ah, _param) \
+ ((*(_ah)->ah_getDfsThresh)((_ah), (_param)))
+
#define ath_hal_gpioCfgOutput(_ah, _gpio, _type) \
((*(_ah)->ah_gpioCfgOutput)((_ah), (_gpio), (_type)))
#define ath_hal_gpioset(_ah, _gpio, _b) \
diff --git a/sys/dev/cxgbe/adapter.h b/sys/dev/cxgbe/adapter.h
index 6b48325..0b33b67 100644
--- a/sys/dev/cxgbe/adapter.h
+++ b/sys/dev/cxgbe/adapter.h
@@ -110,6 +110,9 @@ enum {
FW_IQ_QSIZE = 256,
FW_IQ_ESIZE = 64, /* At least 64 mandated by the firmware spec */
+ INTR_IQ_QSIZE = 64,
+ INTR_IQ_ESIZE = 64, /* Handles some CPLs too, do not reduce */
+
CTRL_EQ_QSIZE = 128,
CTRL_EQ_ESIZE = 64,
@@ -141,7 +144,7 @@ enum {
/* adapter flags */
FULL_INIT_DONE = (1 << 0),
FW_OK = (1 << 1),
- INTR_FWD = (1 << 2),
+ INTR_SHARED = (1 << 2), /* one set of intrq's for all ports */
CXGBE_BUSY = (1 << 9),
@@ -384,17 +387,16 @@ struct sge_ctrlq {
/* stats for common events first */
- uint64_t total_wrs; /* # of work requests sent down this queue */
/* stats for not-that-common events */
uint32_t no_desc; /* out of hardware descriptors */
- uint32_t too_long; /* WR longer than hardware max */
} __aligned(CACHE_LINE_SIZE);
struct sge {
uint16_t timer_val[SGE_NTIMERS];
uint8_t counter_val[SGE_NCOUNTERS];
+ int fl_starve_threshold;
int nrxq; /* total rx queues (all ports and the rest) */
int ntxq; /* total tx queues (all ports and the rest) */
@@ -403,7 +405,7 @@ struct sge {
struct sge_iq fwq; /* Firmware event queue */
struct sge_ctrlq *ctrlq;/* Control queues */
- struct sge_iq *fiq; /* Forwarded interrupt queues (INTR_FWD) */
+ struct sge_iq *intrq; /* Interrupt queues */
struct sge_txq *txq; /* NIC tx queues */
struct sge_rxq *rxq; /* NIC rx queues */
@@ -445,6 +447,7 @@ struct adapter {
struct port_info *port[MAX_NPORTS];
uint8_t chan_map[NCHAN];
+ struct l2t_data *l2t; /* L2 table */
struct tid_info tids;
int registered_device_map;
@@ -456,7 +459,9 @@ struct adapter {
struct t4_virt_res vres;
struct sysctl_ctx_list ctx; /* from first_port_up to last_port_down */
+ struct sysctl_oid *oid_fwq;
struct sysctl_oid *oid_ctrlq;
+ struct sysctl_oid *oid_intrq;
struct mtx sc_lock;
char lockname[16];
@@ -502,7 +507,10 @@ struct adapter {
rxq = &pi->adapter->sge.rxq[pi->first_rxq]; \
for (iter = 0; iter < pi->nrxq; ++iter, ++rxq)
-#define NFIQ(sc) ((sc)->intr_count > 1 ? (sc)->intr_count - 1 : 1)
+/* One for errors, one for firmware events */
+#define T4_EXTRA_INTR 2
+#define NINTRQ(sc) ((sc)->intr_count > T4_EXTRA_INTR ? \
+ (sc)->intr_count - T4_EXTRA_INTR : 1)
static inline uint32_t
t4_read_reg(struct adapter *sc, uint32_t reg)
@@ -599,12 +607,9 @@ int t4_teardown_adapter_queues(struct adapter *);
int t4_setup_eth_queues(struct port_info *);
int t4_teardown_eth_queues(struct port_info *);
void t4_intr_all(void *);
-void t4_intr_fwd(void *);
+void t4_intr(void *);
void t4_intr_err(void *);
void t4_intr_evt(void *);
-void t4_intr_data(void *);
-void t4_evt_rx(void *);
-void t4_eth_rx(void *);
int t4_mgmt_tx(struct adapter *, struct mbuf *);
int t4_eth_tx(struct ifnet *, struct sge_txq *, struct mbuf *);
void t4_update_fl_bufsize(struct ifnet *);
diff --git a/sys/dev/cxgbe/common/common.h b/sys/dev/cxgbe/common/common.h
index fa5ac9f..913be9b 100644
--- a/sys/dev/cxgbe/common/common.h
+++ b/sys/dev/cxgbe/common/common.h
@@ -54,7 +54,7 @@ enum {
#define FW_VERSION_MAJOR 1
#define FW_VERSION_MINOR 3
-#define FW_VERSION_MICRO 8
+#define FW_VERSION_MICRO 10
struct port_stats {
u64 tx_octets; /* total # of octets in good frames */
diff --git a/sys/dev/cxgbe/common/jhash.h b/sys/dev/cxgbe/common/jhash.h
new file mode 100644
index 0000000..4546b7b
--- /dev/null
+++ b/sys/dev/cxgbe/common/jhash.h
@@ -0,0 +1,140 @@
+#ifndef _JHASH_H
+#define _JHASH_H
+
+/* jhash.h: Jenkins hash support.
+ *
+ * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net)
+ *
+ * http://burtleburtle.net/bob/hash/
+ *
+ * These are the credits from Bob's sources:
+ *
+ * lookup2.c, by Bob Jenkins, December 1996, Public Domain.
+ * hash(), hash2(), hash3, and mix() are externally useful functions.
+ * Routines to test the hash are included if SELF_TEST is defined.
+ * You can use this free for any purpose. It has no warranty.
+ *
+ * $FreeBSD$
+ */
+
+/* NOTE: Arguments are modified. */
+#define __jhash_mix(a, b, c) \
+{ \
+ a -= b; a -= c; a ^= (c>>13); \
+ b -= c; b -= a; b ^= (a<<8); \
+ c -= a; c -= b; c ^= (b>>13); \
+ a -= b; a -= c; a ^= (c>>12); \
+ b -= c; b -= a; b ^= (a<<16); \
+ c -= a; c -= b; c ^= (b>>5); \
+ a -= b; a -= c; a ^= (c>>3); \
+ b -= c; b -= a; b ^= (a<<10); \
+ c -= a; c -= b; c ^= (b>>15); \
+}
+
+/* The golden ration: an arbitrary value */
+#define JHASH_GOLDEN_RATIO 0x9e3779b9
+
+/* The most generic version, hashes an arbitrary sequence
+ * of bytes. No alignment or length assumptions are made about
+ * the input key.
+ */
+static inline u32 jhash(const void *key, u32 length, u32 initval)
+{
+ u32 a, b, c, len;
+ const u8 *k = key;
+
+ len = length;
+ a = b = JHASH_GOLDEN_RATIO;
+ c = initval;
+
+ while (len >= 12) {
+ a += (k[0] +((u32)k[1]<<8) +((u32)k[2]<<16) +((u32)k[3]<<24));
+ b += (k[4] +((u32)k[5]<<8) +((u32)k[6]<<16) +((u32)k[7]<<24));
+ c += (k[8] +((u32)k[9]<<8) +((u32)k[10]<<16)+((u32)k[11]<<24));
+
+ __jhash_mix(a,b,c);
+
+ k += 12;
+ len -= 12;
+ }
+
+ c += length;
+ switch (len) {
+ case 11: c += ((u32)k[10]<<24);
+ case 10: c += ((u32)k[9]<<16);
+ case 9 : c += ((u32)k[8]<<8);
+ case 8 : b += ((u32)k[7]<<24);
+ case 7 : b += ((u32)k[6]<<16);
+ case 6 : b += ((u32)k[5]<<8);
+ case 5 : b += k[4];
+ case 4 : a += ((u32)k[3]<<24);
+ case 3 : a += ((u32)k[2]<<16);
+ case 2 : a += ((u32)k[1]<<8);
+ case 1 : a += k[0];
+ };
+
+ __jhash_mix(a,b,c);
+
+ return c;
+}
+
+/* A special optimized version that handles 1 or more of u32s.
+ * The length parameter here is the number of u32s in the key.
+ */
+static inline u32 jhash2(u32 *k, u32 length, u32 initval)
+{
+ u32 a, b, c, len;
+
+ a = b = JHASH_GOLDEN_RATIO;
+ c = initval;
+ len = length;
+
+ while (len >= 3) {
+ a += k[0];
+ b += k[1];
+ c += k[2];
+ __jhash_mix(a, b, c);
+ k += 3; len -= 3;
+ }
+
+ c += length * 4;
+
+ switch (len) {
+ case 2 : b += k[1];
+ case 1 : a += k[0];
+ };
+
+ __jhash_mix(a,b,c);
+
+ return c;
+}
+
+
+/* A special ultra-optimized versions that knows they are hashing exactly
+ * 3, 2 or 1 word(s).
+ *
+ * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
+ * done at the end is not done here.
+ */
+static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval)
+{
+ a += JHASH_GOLDEN_RATIO;
+ b += JHASH_GOLDEN_RATIO;
+ c += initval;
+
+ __jhash_mix(a, b, c);
+
+ return c;
+}
+
+static inline u32 jhash_2words(u32 a, u32 b, u32 initval)
+{
+ return jhash_3words(a, b, 0, initval);
+}
+
+static inline u32 jhash_1word(u32 a, u32 initval)
+{
+ return jhash_3words(a, 0, 0, initval);
+}
+
+#endif /* _JHASH_H */
diff --git a/sys/dev/cxgbe/common/t4fw_interface.h b/sys/dev/cxgbe/common/t4fw_interface.h
index 88126be..3eb9615 100644
--- a/sys/dev/cxgbe/common/t4fw_interface.h
+++ b/sys/dev/cxgbe/common/t4fw_interface.h
@@ -43,6 +43,7 @@ enum fw_retval {
FW_ENOMEM = 12, /* out of memory */
FW_EFAULT = 14, /* bad address; fw bad */
FW_EBUSY = 16, /* resource busy */
+ FW_EEXIST = 17, /* File exists */
FW_EINVAL = 22, /* invalid argument */
FW_ENOSYS = 38, /* functionality not implemented */
FW_EPROTO = 71, /* protocol error */
@@ -59,6 +60,8 @@ enum fw_retval {
FW_FCOE_NO_XCHG = 136, /* */
FW_SCSI_RSP_ERR = 137, /* */
FW_ERR_RDEV_IMPL_LOGO = 138, /* */
+ FW_SCSI_UNDER_FLOW_ERR = 139, /* */
+ FW_SCSI_OVER_FLOW_ERR = 140, /* */
};
/******************************************************************************
@@ -85,7 +88,8 @@ enum fw_wr_opcodes {
FW_RI_FR_NSMR_WR = 0x19,
FW_RI_INV_LSTAG_WR = 0x1a,
FW_RI_WR = 0x0d,
- FW_LASTC2E_WR = 0x4a
+ FW_ISCSI_NODE_WR = 0x4a,
+ FW_LASTC2E_WR = 0x4b
};
/*
@@ -514,7 +518,7 @@ struct fw_eth_tx_pkts_wr {
__be32 r3;
__be16 plen;
__u8 npkt;
- __u8 r4;
+ __u8 type;
};
struct fw_eq_flush_wr {
@@ -1465,6 +1469,65 @@ struct fw_ri_wr {
#define G_FW_RI_WR_P2PTYPE(x) \
(((x) >> S_FW_RI_WR_P2PTYPE) & M_FW_RI_WR_P2PTYPE)
+#ifdef FOISCSI
+struct fw_iscsi_node_wr {
+ __u8 opcode;
+ __u8 subop;
+ __u8 node_attr_to_compl;
+ __u8 len16;
+ __u8 status;
+ __u8 r2;
+ __be16 immd_len;
+ __be64 cookie;
+ __be32 node_id;
+ __be32 ctrl_handle;
+ __be32 io_handle;
+ __be32 r3;
+};
+
+#define S_FW_ISCSI_NODE_WR_NODE_ATTR 7
+#define M_FW_ISCSI_NODE_WR_NODE_ATTR 0x1
+#define V_FW_ISCSI_NODE_WR_NODE_ATTR(x) ((x) << S_FW_ISCSI_NODE_WR_NODE_ATTR)
+#define G_FW_ISCSI_NODE_WR_NODE_ATTR(x) \
+ (((x) >> S_FW_ISCSI_NODE_WR_NODE_ATTR) & M_FW_ISCSI_NODE_WR_NODE_ATTR)
+#define F_FW_ISCSI_NODE_WR_NODE_ATTR V_FW_ISCSI_NODE_WR_NODE_ATTR(1U)
+
+#define S_FW_ISCSI_NODE_WR_SESS_ATTR 6
+#define M_FW_ISCSI_NODE_WR_SESS_ATTR 0x1
+#define V_FW_ISCSI_NODE_WR_SESS_ATTR(x) ((x) << S_FW_ISCSI_NODE_WR_SESS_ATTR)
+#define G_FW_ISCSI_NODE_WR_SESS_ATTR(x) \
+ (((x) >> S_FW_ISCSI_NODE_WR_SESS_ATTR) & M_FW_ISCSI_NODE_WR_SESS_ATTR)
+#define F_FW_ISCSI_NODE_WR_SESS_ATTR V_FW_ISCSI_NODE_WR_SESS_ATTR(1U)
+
+#define S_FW_ISCSI_NODE_WR_CONN_ATTR 5
+#define M_FW_ISCSI_NODE_WR_CONN_ATTR 0x1
+#define V_FW_ISCSI_NODE_WR_CONN_ATTR(x) ((x) << S_FW_ISCSI_NODE_WR_CONN_ATTR)
+#define G_FW_ISCSI_NODE_WR_CONN_ATTR(x) \
+ (((x) >> S_FW_ISCSI_NODE_WR_CONN_ATTR) & M_FW_ISCSI_NODE_WR_CONN_ATTR)
+#define F_FW_ISCSI_NODE_WR_CONN_ATTR V_FW_ISCSI_NODE_WR_CONN_ATTR(1U)
+
+#define S_FW_ISCSI_NODE_WR_TGT_ATTR 4
+#define M_FW_ISCSI_NODE_WR_TGT_ATTR 0x1
+#define V_FW_ISCSI_NODE_WR_TGT_ATTR(x) ((x) << S_FW_ISCSI_NODE_WR_TGT_ATTR)
+#define G_FW_ISCSI_NODE_WR_TGT_ATTR(x) \
+ (((x) >> S_FW_ISCSI_NODE_WR_TGT_ATTR) & M_FW_ISCSI_NODE_WR_TGT_ATTR)
+#define F_FW_ISCSI_NODE_WR_TGT_ATTR V_FW_ISCSI_NODE_WR_TGT_ATTR(1U)
+
+#define S_FW_ISCSI_NODE_WR_NODE_TYPE 3
+#define M_FW_ISCSI_NODE_WR_NODE_TYPE 0x1
+#define V_FW_ISCSI_NODE_WR_NODE_TYPE(x) ((x) << S_FW_ISCSI_NODE_WR_NODE_TYPE)
+#define G_FW_ISCSI_NODE_WR_NODE_TYPE(x) \
+ (((x) >> S_FW_ISCSI_NODE_WR_NODE_TYPE) & M_FW_ISCSI_NODE_WR_NODE_TYPE)
+#define F_FW_ISCSI_NODE_WR_NODE_TYPE V_FW_ISCSI_NODE_WR_NODE_TYPE(1U)
+
+#define S_FW_ISCSI_NODE_WR_COMPL 0
+#define M_FW_ISCSI_NODE_WR_COMPL 0x1
+#define V_FW_ISCSI_NODE_WR_COMPL(x) ((x) << S_FW_ISCSI_NODE_WR_COMPL)
+#define G_FW_ISCSI_NODE_WR_COMPL(x) \
+ (((x) >> S_FW_ISCSI_NODE_WR_COMPL) & M_FW_ISCSI_NODE_WR_COMPL)
+#define F_FW_ISCSI_NODE_WR_COMPL V_FW_ISCSI_NODE_WR_COMPL(1U)
+
+#endif
/******************************************************************************
* C O M M A N D s
@@ -1511,6 +1574,7 @@ enum fw_cmd_opcodes {
FW_RSS_VI_CONFIG_CMD = 0x23,
FW_SCHED_CMD = 0x24,
FW_DEVLOG_CMD = 0x25,
+ FW_NETIF_CMD = 0x26,
FW_LASTC2E_CMD = 0x40,
FW_ERROR_CMD = 0x80,
FW_DEBUG_CMD = 0x81,
@@ -1941,6 +2005,8 @@ enum fw_caps_config_iscsi {
FW_CAPS_CONFIG_ISCSI_TARGET_PDU = 0x00000002,
FW_CAPS_CONFIG_ISCSI_INITIATOR_CNXOFLD = 0x00000004,
FW_CAPS_CONFIG_ISCSI_TARGET_CNXOFLD = 0x00000008,
+ FW_CAPS_CONFIG_ISCSI_INITIATOR_SSNOFLD = 0x00000010,
+ FW_CAPS_CONFIG_ISCSI_TARGET_SSNOFLD = 0x00000020,
};
enum fw_caps_config_fcoe {
@@ -3941,6 +4007,39 @@ enum fw_port_cap {
FW_PORT_CAP_TECHKX4 = 0x2000,
};
+#define S_FW_PORT_AUXLINFO_MDI 3
+#define M_FW_PORT_AUXLINFO_MDI 0x3
+#define V_FW_PORT_AUXLINFO_MDI(x) ((x) << S_FW_PORT_AUXLINFO_MDI)
+#define G_FW_PORT_AUXLINFO_MDI(x) \
+ (((x) >> S_FW_PORT_AUXLINFO_MDI) & M_FW_PORT_AUXLINFO_MDI)
+
+#define S_FW_PORT_AUXLINFO_KX4 2
+#define M_FW_PORT_AUXLINFO_KX4 0x1
+#define V_FW_PORT_AUXLINFO_KX4(x) ((x) << S_FW_PORT_AUXLINFO_KX4)
+#define G_FW_PORT_AUXLINFO_KX4(x) \
+ (((x) >> S_FW_PORT_AUXLINFO_KX4) & M_FW_PORT_AUXLINFO_KX4)
+#define F_FW_PORT_AUXLINFO_KX4 V_FW_PORT_AUXLINFO_KX4(1U)
+
+#define S_FW_PORT_AUXLINFO_KR 1
+#define M_FW_PORT_AUXLINFO_KR 0x1
+#define V_FW_PORT_AUXLINFO_KR(x) ((x) << S_FW_PORT_AUXLINFO_KR)
+#define G_FW_PORT_AUXLINFO_KR(x) \
+ (((x) >> S_FW_PORT_AUXLINFO_KR) & M_FW_PORT_AUXLINFO_KR)
+#define F_FW_PORT_AUXLINFO_KR V_FW_PORT_AUXLINFO_KR(1U)
+
+#define S_FW_PORT_AUXLINFO_FEC 0
+#define M_FW_PORT_AUXLINFO_FEC 0x1
+#define V_FW_PORT_AUXLINFO_FEC(x) ((x) << S_FW_PORT_AUXLINFO_FEC)
+#define G_FW_PORT_AUXLINFO_FEC(x) \
+ (((x) >> S_FW_PORT_AUXLINFO_FEC) & M_FW_PORT_AUXLINFO_FEC)
+#define F_FW_PORT_AUXLINFO_FEC V_FW_PORT_AUXLINFO_FEC(1U)
+
+#define S_FW_PORT_RCAP_AUX 11
+#define M_FW_PORT_RCAP_AUX 0x7
+#define V_FW_PORT_RCAP_AUX(x) ((x) << S_FW_PORT_RCAP_AUX)
+#define G_FW_PORT_RCAP_AUX(x) \
+ (((x) >> S_FW_PORT_RCAP_AUX) & M_FW_PORT_RCAP_AUX)
+
#define S_FW_PORT_CAP_SPEED 0
#define M_FW_PORT_CAP_SPEED 0x3f
#define V_FW_PORT_CAP_SPEED(x) ((x) << S_FW_PORT_CAP_SPEED)
@@ -4002,11 +4101,23 @@ enum fw_port_l2cfg_ctlbf {
FW_PORT_L2_CTLBF_MTU = 0x40
};
+enum fw_port_dcb_cfg {
+ FW_PORT_DCB_CFG_PG = 0x01,
+ FW_PORT_DCB_CFG_PFC = 0x02,
+ FW_PORT_DCB_CFG_APPL = 0x04
+};
+
+enum fw_port_dcb_cfg_rc {
+ FW_PORT_DCB_CFG_SUCCESS = 0x0,
+ FW_PORT_DCB_CFG_ERROR = 0x1
+};
+
enum fw_port_dcb_type {
FW_PORT_DCB_TYPE_PGID = 0x00,
FW_PORT_DCB_TYPE_PGRATE = 0x01,
FW_PORT_DCB_TYPE_PRIORATE = 0x02,
- FW_PORT_DCB_TYPE_PFC = 0x03
+ FW_PORT_DCB_TYPE_PFC = 0x03,
+ FW_PORT_DCB_TYPE_APP_ID = 0x04,
};
struct fw_port_cmd {
@@ -4038,7 +4149,7 @@ struct fw_port_cmd {
__be16 acap;
__be16 mtu;
__u8 cbllen;
- __u8 r7;
+ __u8 auxlinfo;
__be32 r8;
__be64 r9;
} info;
@@ -4068,6 +4179,14 @@ struct fw_port_cmd {
__be16 r10[3];
__be64 r11;
} pfc;
+ struct fw_port_app_priority {
+ __u8 type;
+ __u8 r10_lo[3];
+ __u8 prio;
+ __u8 sel;
+ __be16 protocolid;
+ __u8 r12[8];
+ } app_priority;
} dcb;
} u;
};
@@ -5232,6 +5351,116 @@ struct fw_devlog_cmd {
(((x) >> S_FW_DEVLOG_CMD_MEMADDR16_DEVLOG) & \
M_FW_DEVLOG_CMD_MEMADDR16_DEVLOG)
+struct fw_netif_cmd {
+ __be32 op_portid;
+ __be32 retval_to_len16;
+ __be32 add_to_ipv4gw;
+ __be32 vlanid_mtuval;
+ __be32 gwaddr;
+ __be32 addr;
+ __be32 nmask;
+ __be32 bcaddr;
+};
+
+#define S_FW_NETIF_CMD_PORTID 0
+#define M_FW_NETIF_CMD_PORTID 0xf
+#define V_FW_NETIF_CMD_PORTID(x) ((x) << S_FW_NETIF_CMD_PORTID)
+#define G_FW_NETIF_CMD_PORTID(x) \
+ (((x) >> S_FW_NETIF_CMD_PORTID) & M_FW_NETIF_CMD_PORTID)
+
+#define S_FW_NETIF_CMD_RETVAL 24
+#define M_FW_NETIF_CMD_RETVAL 0xff
+#define V_FW_NETIF_CMD_RETVAL(x) ((x) << S_FW_NETIF_CMD_RETVAL)
+#define G_FW_NETIF_CMD_RETVAL(x) \
+ (((x) >> S_FW_NETIF_CMD_RETVAL) & M_FW_NETIF_CMD_RETVAL)
+
+#define S_FW_NETIF_CMD_IFIDX 16
+#define M_FW_NETIF_CMD_IFIDX 0xff
+#define V_FW_NETIF_CMD_IFIDX(x) ((x) << S_FW_NETIF_CMD_IFIDX)
+#define G_FW_NETIF_CMD_IFIDX(x) \
+ (((x) >> S_FW_NETIF_CMD_IFIDX) & M_FW_NETIF_CMD_IFIDX)
+
+#define S_FW_NETIF_CMD_LEN16 0
+#define M_FW_NETIF_CMD_LEN16 0xff
+#define V_FW_NETIF_CMD_LEN16(x) ((x) << S_FW_NETIF_CMD_LEN16)
+#define G_FW_NETIF_CMD_LEN16(x) \
+ (((x) >> S_FW_NETIF_CMD_LEN16) & M_FW_NETIF_CMD_LEN16)
+
+#define S_FW_NETIF_CMD_ADD 31
+#define M_FW_NETIF_CMD_ADD 0x1
+#define V_FW_NETIF_CMD_ADD(x) ((x) << S_FW_NETIF_CMD_ADD)
+#define G_FW_NETIF_CMD_ADD(x) \
+ (((x) >> S_FW_NETIF_CMD_ADD) & M_FW_NETIF_CMD_ADD)
+#define F_FW_NETIF_CMD_ADD V_FW_NETIF_CMD_ADD(1U)
+
+#define S_FW_NETIF_CMD_LINK 30
+#define M_FW_NETIF_CMD_LINK 0x1
+#define V_FW_NETIF_CMD_LINK(x) ((x) << S_FW_NETIF_CMD_LINK)
+#define G_FW_NETIF_CMD_LINK(x) \
+ (((x) >> S_FW_NETIF_CMD_LINK) & M_FW_NETIF_CMD_LINK)
+#define F_FW_NETIF_CMD_LINK V_FW_NETIF_CMD_LINK(1U)
+
+#define S_FW_NETIF_CMD_VLAN 29
+#define M_FW_NETIF_CMD_VLAN 0x1
+#define V_FW_NETIF_CMD_VLAN(x) ((x) << S_FW_NETIF_CMD_VLAN)
+#define G_FW_NETIF_CMD_VLAN(x) \
+ (((x) >> S_FW_NETIF_CMD_VLAN) & M_FW_NETIF_CMD_VLAN)
+#define F_FW_NETIF_CMD_VLAN V_FW_NETIF_CMD_VLAN(1U)
+
+#define S_FW_NETIF_CMD_MTU 28
+#define M_FW_NETIF_CMD_MTU 0x1
+#define V_FW_NETIF_CMD_MTU(x) ((x) << S_FW_NETIF_CMD_MTU)
+#define G_FW_NETIF_CMD_MTU(x) \
+ (((x) >> S_FW_NETIF_CMD_MTU) & M_FW_NETIF_CMD_MTU)
+#define F_FW_NETIF_CMD_MTU V_FW_NETIF_CMD_MTU(1U)
+
+#define S_FW_NETIF_CMD_DHCP 27
+#define M_FW_NETIF_CMD_DHCP 0x1
+#define V_FW_NETIF_CMD_DHCP(x) ((x) << S_FW_NETIF_CMD_DHCP)
+#define G_FW_NETIF_CMD_DHCP(x) \
+ (((x) >> S_FW_NETIF_CMD_DHCP) & M_FW_NETIF_CMD_DHCP)
+#define F_FW_NETIF_CMD_DHCP V_FW_NETIF_CMD_DHCP(1U)
+
+#define S_FW_NETIF_CMD_IPV4BCADDR 3
+#define M_FW_NETIF_CMD_IPV4BCADDR 0x1
+#define V_FW_NETIF_CMD_IPV4BCADDR(x) ((x) << S_FW_NETIF_CMD_IPV4BCADDR)
+#define G_FW_NETIF_CMD_IPV4BCADDR(x) \
+ (((x) >> S_FW_NETIF_CMD_IPV4BCADDR) & M_FW_NETIF_CMD_IPV4BCADDR)
+#define F_FW_NETIF_CMD_IPV4BCADDR V_FW_NETIF_CMD_IPV4BCADDR(1U)
+
+#define S_FW_NETIF_CMD_IPV4NMASK 2
+#define M_FW_NETIF_CMD_IPV4NMASK 0x1
+#define V_FW_NETIF_CMD_IPV4NMASK(x) ((x) << S_FW_NETIF_CMD_IPV4NMASK)
+#define G_FW_NETIF_CMD_IPV4NMASK(x) \
+ (((x) >> S_FW_NETIF_CMD_IPV4NMASK) & M_FW_NETIF_CMD_IPV4NMASK)
+#define F_FW_NETIF_CMD_IPV4NMASK V_FW_NETIF_CMD_IPV4NMASK(1U)
+
+#define S_FW_NETIF_CMD_IPV4ADDR 1
+#define M_FW_NETIF_CMD_IPV4ADDR 0x1
+#define V_FW_NETIF_CMD_IPV4ADDR(x) ((x) << S_FW_NETIF_CMD_IPV4ADDR)
+#define G_FW_NETIF_CMD_IPV4ADDR(x) \
+ (((x) >> S_FW_NETIF_CMD_IPV4ADDR) & M_FW_NETIF_CMD_IPV4ADDR)
+#define F_FW_NETIF_CMD_IPV4ADDR V_FW_NETIF_CMD_IPV4ADDR(1U)
+
+#define S_FW_NETIF_CMD_IPV4GW 0
+#define M_FW_NETIF_CMD_IPV4GW 0x1
+#define V_FW_NETIF_CMD_IPV4GW(x) ((x) << S_FW_NETIF_CMD_IPV4GW)
+#define G_FW_NETIF_CMD_IPV4GW(x) \
+ (((x) >> S_FW_NETIF_CMD_IPV4GW) & M_FW_NETIF_CMD_IPV4GW)
+#define F_FW_NETIF_CMD_IPV4GW V_FW_NETIF_CMD_IPV4GW(1U)
+
+#define S_FW_NETIF_CMD_VLANID 16
+#define M_FW_NETIF_CMD_VLANID 0xfff
+#define V_FW_NETIF_CMD_VLANID(x) ((x) << S_FW_NETIF_CMD_VLANID)
+#define G_FW_NETIF_CMD_VLANID(x) \
+ (((x) >> S_FW_NETIF_CMD_VLANID) & M_FW_NETIF_CMD_VLANID)
+
+#define S_FW_NETIF_CMD_MTUVAL 0
+#define M_FW_NETIF_CMD_MTUVAL 0xffff
+#define V_FW_NETIF_CMD_MTUVAL(x) ((x) << S_FW_NETIF_CMD_MTUVAL)
+#define G_FW_NETIF_CMD_MTUVAL(x) \
+ (((x) >> S_FW_NETIF_CMD_MTUVAL) & M_FW_NETIF_CMD_MTUVAL)
+
enum fw_error_type {
FW_ERROR_TYPE_EXCEPTION = 0x0,
FW_ERROR_TYPE_HWMODULE = 0x1,
diff --git a/sys/dev/cxgbe/offload.h b/sys/dev/cxgbe/offload.h
index fa58853..f31b840 100644
--- a/sys/dev/cxgbe/offload.h
+++ b/sys/dev/cxgbe/offload.h
@@ -31,6 +31,24 @@
#ifndef __T4_OFFLOAD_H__
#define __T4_OFFLOAD_H__
+/* CPL message priority levels */
+enum {
+ CPL_PRIORITY_DATA = 0, /* data messages */
+ CPL_PRIORITY_SETUP = 1, /* connection setup messages */
+ CPL_PRIORITY_TEARDOWN = 0, /* connection teardown messages */
+ CPL_PRIORITY_LISTEN = 1, /* listen start/stop messages */
+ CPL_PRIORITY_ACK = 1, /* RX ACK messages */
+ CPL_PRIORITY_CONTROL = 1 /* control messages */
+};
+
+#define INIT_TP_WR(w, tid) do { \
+ (w)->wr.wr_hi = htonl(V_FW_WR_OP(FW_TP_WR) | \
+ V_FW_WR_IMMDLEN(sizeof(*w) - sizeof(w->wr))); \
+ (w)->wr.wr_mid = htonl(V_FW_WR_LEN16(DIV_ROUND_UP(sizeof(*w), 16)) | \
+ V_FW_WR_FLOWID(tid)); \
+ (w)->wr.wr_lo = cpu_to_be64(0); \
+} while (0)
+
/*
* Max # of ATIDs. The absolute HW max is 16K but we keep it lower.
*/
diff --git a/sys/dev/cxgbe/osdep.h b/sys/dev/cxgbe/osdep.h
index 438a434..bde1eb4 100644
--- a/sys/dev/cxgbe/osdep.h
+++ b/sys/dev/cxgbe/osdep.h
@@ -82,6 +82,7 @@ typedef boolean_t bool;
#define DIV_ROUND_UP(x, y) howmany(x, y)
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#define container_of(p, s, f) ((s *)(((uint8_t *)(p)) - offsetof(s, f)))
#define swab16(x) bswap16(x)
#define swab32(x) bswap32(x)
diff --git a/sys/dev/cxgbe/t4_ioctl.h b/sys/dev/cxgbe/t4_ioctl.h
index 8f1d133..a0b489f 100644
--- a/sys/dev/cxgbe/t4_ioctl.h
+++ b/sys/dev/cxgbe/t4_ioctl.h
@@ -178,6 +178,8 @@ struct t4_filter_specification {
struct t4_filter {
uint32_t idx;
+ uint16_t l2tidx;
+ uint16_t smtidx;
uint64_t hits;
struct t4_filter_specification fs;
};
diff --git a/sys/dev/cxgbe/t4_l2t.c b/sys/dev/cxgbe/t4_l2t.c
new file mode 100644
index 0000000..31197b8
--- /dev/null
+++ b/sys/dev/cxgbe/t4_l2t.c
@@ -0,0 +1,361 @@
+/*-
+ * Copyright (c) 2011 Chelsio Communications, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_inet.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/rwlock.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/ethernet.h>
+#include <net/if_vlan_var.h>
+#include <net/if_dl.h>
+#include <net/if_llatbl.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/in_var.h>
+#include <netinet/if_ether.h>
+
+#include "common/common.h"
+#include "common/jhash.h"
+#include "common/t4_msg.h"
+#include "offload.h"
+#include "t4_l2t.h"
+
+/* identifies sync vs async L2T_WRITE_REQs */
+#define S_SYNC_WR 12
+#define V_SYNC_WR(x) ((x) << S_SYNC_WR)
+#define F_SYNC_WR V_SYNC_WR(1)
+
+enum {
+ L2T_STATE_VALID, /* entry is up to date */
+ L2T_STATE_STALE, /* entry may be used but needs revalidation */
+ L2T_STATE_RESOLVING, /* entry needs address resolution */
+ L2T_STATE_SYNC_WRITE, /* synchronous write of entry underway */
+
+ /* when state is one of the below the entry is not hashed */
+ L2T_STATE_SWITCHING, /* entry is being used by a switching filter */
+ L2T_STATE_UNUSED /* entry not in use */
+};
+
+struct l2t_data {
+ struct rwlock lock;
+ volatile int nfree; /* number of free entries */
+ struct l2t_entry *rover;/* starting point for next allocation */
+ struct l2t_entry l2tab[L2T_SIZE];
+};
+
+/*
+ * Module locking notes: There is a RW lock protecting the L2 table as a
+ * whole plus a spinlock per L2T entry. Entry lookups and allocations happen
+ * under the protection of the table lock, individual entry changes happen
+ * while holding that entry's spinlock. The table lock nests outside the
+ * entry locks. Allocations of new entries take the table lock as writers so
+ * no other lookups can happen while allocating new entries. Entry updates
+ * take the table lock as readers so multiple entries can be updated in
+ * parallel. An L2T entry can be dropped by decrementing its reference count
+ * and therefore can happen in parallel with entry allocation but no entry
+ * can change state or increment its ref count during allocation as both of
+ * these perform lookups.
+ *
+ * Note: We do not take refereces to ifnets in this module because both
+ * the TOE and the sockets already hold references to the interfaces and the
+ * lifetime of an L2T entry is fully contained in the lifetime of the TOE.
+ */
+static inline unsigned int
+vlan_prio(const struct l2t_entry *e)
+{
+ return e->vlan >> 13;
+}
+
+static inline void
+l2t_hold(struct l2t_data *d, struct l2t_entry *e)
+{
+ if (atomic_fetchadd_int(&e->refcnt, 1) == 0) /* 0 -> 1 transition */
+ atomic_add_int(&d->nfree, -1);
+}
+
+/*
+ * To avoid having to check address families we do not allow v4 and v6
+ * neighbors to be on the same hash chain. We keep v4 entries in the first
+ * half of available hash buckets and v6 in the second.
+ */
+enum {
+ L2T_SZ_HALF = L2T_SIZE / 2,
+ L2T_HASH_MASK = L2T_SZ_HALF - 1
+};
+
+static inline unsigned int
+arp_hash(const uint32_t *key, int ifindex)
+{
+ return jhash_2words(*key, ifindex, 0) & L2T_HASH_MASK;
+}
+
+static inline unsigned int
+ipv6_hash(const uint32_t *key, int ifindex)
+{
+ uint32_t xor = key[0] ^ key[1] ^ key[2] ^ key[3];
+
+ return L2T_SZ_HALF + (jhash_2words(xor, ifindex, 0) & L2T_HASH_MASK);
+}
+
+static inline unsigned int
+addr_hash(const uint32_t *addr, int addr_len, int ifindex)
+{
+ return addr_len == 4 ? arp_hash(addr, ifindex) :
+ ipv6_hash(addr, ifindex);
+}
+
+/*
+ * Checks if an L2T entry is for the given IP/IPv6 address. It does not check
+ * whether the L2T entry and the address are of the same address family.
+ * Callers ensure an address is only checked against L2T entries of the same
+ * family, something made trivial by the separation of IP and IPv6 hash chains
+ * mentioned above. Returns 0 if there's a match,
+ */
+static inline int
+addreq(const struct l2t_entry *e, const uint32_t *addr)
+{
+ if (e->v6)
+ return (e->addr[0] ^ addr[0]) | (e->addr[1] ^ addr[1]) |
+ (e->addr[2] ^ addr[2]) | (e->addr[3] ^ addr[3]);
+ return e->addr[0] ^ addr[0];
+}
+
+/*
+ * Write an L2T entry. Must be called with the entry locked (XXX: really?).
+ * The write may be synchronous or asynchronous.
+ */
+static int
+write_l2e(struct adapter *sc, struct l2t_entry *e, int sync)
+{
+ struct mbuf *m;
+ struct cpl_l2t_write_req *req;
+
+ if ((m = m_gethdr(M_NOWAIT, MT_DATA)) == NULL)
+ return (ENOMEM);
+
+ req = mtod(m, struct cpl_l2t_write_req *);
+ m->m_pkthdr.len = m->m_len = sizeof(*req);
+
+ INIT_TP_WR(req, 0);
+ OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_L2T_WRITE_REQ, e->idx |
+ V_SYNC_WR(sync) | V_TID_QID(sc->sge.fwq.abs_id)));
+ req->params = htons(V_L2T_W_PORT(e->lport) | V_L2T_W_NOREPLY(!sync));
+ req->l2t_idx = htons(e->idx);
+ req->vlan = htons(e->vlan);
+ memcpy(req->dst_mac, e->dmac, sizeof(req->dst_mac));
+
+ t4_mgmt_tx(sc, m);
+
+ if (sync && e->state != L2T_STATE_SWITCHING)
+ e->state = L2T_STATE_SYNC_WRITE;
+
+ return (0);
+}
+
+/*
+ * Add a packet to an L2T entry's queue of packets awaiting resolution.
+ * Must be called with the entry's lock held.
+ */
+static inline void
+arpq_enqueue(struct l2t_entry *e, struct mbuf *m)
+{
+ mtx_assert(&e->lock, MA_OWNED);
+
+ m->m_next = NULL;
+ if (e->arpq_head)
+ e->arpq_tail->m_next = m;
+ else
+ e->arpq_head = m;
+ e->arpq_tail = m;
+}
+
+/*
+ * Allocate a free L2T entry. Must be called with l2t_data.lock held.
+ */
+static struct l2t_entry *
+alloc_l2e(struct l2t_data *d)
+{
+ struct l2t_entry *end, *e, **p;
+
+ rw_assert(&d->lock, RA_WLOCKED);
+
+ if (!atomic_load_acq_int(&d->nfree))
+ return (NULL);
+
+ /* there's definitely a free entry */
+ for (e = d->rover, end = &d->l2tab[L2T_SIZE]; e != end; ++e)
+ if (atomic_load_acq_int(&e->refcnt) == 0)
+ goto found;
+
+ for (e = d->l2tab; atomic_load_acq_int(&e->refcnt); ++e) ;
+found:
+ d->rover = e + 1;
+ atomic_add_int(&d->nfree, -1);
+
+ /*
+ * The entry we found may be an inactive entry that is
+ * presently in the hash table. We need to remove it.
+ */
+ if (e->state < L2T_STATE_SWITCHING) {
+ for (p = &d->l2tab[e->hash].first; *p; p = &(*p)->next) {
+ if (*p == e) {
+ *p = e->next;
+ e->next = NULL;
+ break;
+ }
+ }
+ }
+
+ e->state = L2T_STATE_UNUSED;
+ return e;
+}
+
+/*
+ * Called when an L2T entry has no more users. The entry is left in the hash
+ * table since it is likely to be reused but we also bump nfree to indicate
+ * that the entry can be reallocated for a different neighbor. We also drop
+ * the existing neighbor reference in case the neighbor is going away and is
+ * waiting on our reference.
+ *
+ * Because entries can be reallocated to other neighbors once their ref count
+ * drops to 0 we need to take the entry's lock to avoid races with a new
+ * incarnation.
+ */
+static void
+t4_l2e_free(struct l2t_entry *e)
+{
+ struct llentry *lle = NULL;
+ struct l2t_data *d;
+
+ mtx_lock(&e->lock);
+ if (atomic_load_acq_int(&e->refcnt) == 0) { /* hasn't been recycled */
+ lle = e->lle;
+ e->lle = NULL;
+ /*
+ * Don't need to worry about the arpq, an L2T entry can't be
+ * released if any packets are waiting for resolution as we
+ * need to be able to communicate with the device to close a
+ * connection.
+ */
+ }
+ mtx_unlock(&e->lock);
+
+ d = container_of(e, struct l2t_data, l2tab[e->idx]);
+ atomic_add_int(&d->nfree, 1);
+
+ if (lle)
+ LLE_FREE(lle);
+}
+
+void
+t4_l2t_release(struct l2t_entry *e)
+{
+ if (atomic_fetchadd_int(&e->refcnt, -1) == 1)
+ t4_l2e_free(e);
+}
+
+/*
+ * Allocate an L2T entry for use by a switching rule. Such need to be
+ * explicitly freed and while busy they are not on any hash chain, so normal
+ * address resolution updates do not see them.
+ */
+struct l2t_entry *
+t4_l2t_alloc_switching(struct l2t_data *d)
+{
+ struct l2t_entry *e;
+
+ rw_rlock(&d->lock);
+ e = alloc_l2e(d);
+ if (e) {
+ mtx_lock(&e->lock); /* avoid race with t4_l2t_free */
+ e->state = L2T_STATE_SWITCHING;
+ atomic_store_rel_int(&e->refcnt, 1);
+ mtx_unlock(&e->lock);
+ }
+ rw_runlock(&d->lock);
+ return e;
+}
+
+/*
+ * Sets/updates the contents of a switching L2T entry that has been allocated
+ * with an earlier call to @t4_l2t_alloc_switching.
+ */
+int
+t4_l2t_set_switching(struct adapter *sc, struct l2t_entry *e, uint16_t vlan,
+ uint8_t port, uint8_t *eth_addr)
+{
+ e->vlan = vlan;
+ e->lport = port;
+ memcpy(e->dmac, eth_addr, ETHER_ADDR_LEN);
+ return write_l2e(sc, e, 0);
+}
+
+struct l2t_data *
+t4_init_l2t(int flags)
+{
+ int i;
+ struct l2t_data *d;
+
+ d = malloc(sizeof(*d), M_CXGBE, M_ZERO | flags);
+ if (!d)
+ return (NULL);
+
+ d->rover = d->l2tab;
+ atomic_store_rel_int(&d->nfree, L2T_SIZE);
+ rw_init(&d->lock, "L2T");
+
+ for (i = 0; i < L2T_SIZE; i++) {
+ d->l2tab[i].idx = i;
+ d->l2tab[i].state = L2T_STATE_UNUSED;
+ mtx_init(&d->l2tab[i].lock, "L2T_E", NULL, MTX_DEF);
+ atomic_store_rel_int(&d->l2tab[i].refcnt, 0);
+ }
+
+ return (d);
+}
+
+int
+t4_free_l2t(struct l2t_data *d)
+{
+ int i;
+
+ for (i = 0; i < L2T_SIZE; i++)
+ mtx_destroy(&d->l2tab[i].lock);
+ rw_destroy(&d->lock);
+ free(d, M_CXGBE);
+
+ return (0);
+}
diff --git a/sys/dev/cxgbe/t4_l2t.h b/sys/dev/cxgbe/t4_l2t.h
new file mode 100644
index 0000000..c5520c6
--- /dev/null
+++ b/sys/dev/cxgbe/t4_l2t.h
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (c) 2011 Chelsio Communications, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ *
+ */
+
+#ifndef __T4_L2T_H
+#define __T4_L2T_H
+
+enum { L2T_SIZE = 4096 }; /* # of L2T entries */
+
+/*
+ * Each L2T entry plays multiple roles. First of all, it keeps state for the
+ * corresponding entry of the HW L2 table and maintains a queue of offload
+ * packets awaiting address resolution. Second, it is a node of a hash table
+ * chain, where the nodes of the chain are linked together through their next
+ * pointer. Finally, each node is a bucket of a hash table, pointing to the
+ * first element in its chain through its first pointer.
+ */
+struct l2t_entry {
+ uint16_t state; /* entry state */
+ uint16_t idx; /* entry index */
+ uint32_t addr[4]; /* next hop IP or IPv6 address */
+ struct ifnet *ifp; /* outgoing interface */
+ uint16_t smt_idx; /* SMT index */
+ uint16_t vlan; /* VLAN TCI (id: 0-11, prio: 13-15) */
+ int ifindex; /* interface index */
+ struct llentry *lle; /* llentry for next hop */
+ struct l2t_entry *first; /* start of hash chain */
+ struct l2t_entry *next; /* next l2t_entry on chain */
+ struct mbuf *arpq_head; /* list of mbufs awaiting resolution */
+ struct mbuf *arpq_tail;
+ struct mtx lock;
+ volatile uint32_t refcnt; /* entry reference count */
+ uint16_t hash; /* hash bucket the entry is on */
+ uint8_t v6; /* whether entry is for IPv6 */
+ uint8_t lport; /* associated offload logical port */
+ uint8_t dmac[ETHER_ADDR_LEN]; /* next hop's MAC address */
+};
+
+struct l2t_data *t4_init_l2t(int);
+int t4_free_l2t(struct l2t_data *);
+struct l2t_entry *t4_l2t_alloc_switching(struct l2t_data *);
+int t4_l2t_set_switching(struct adapter *, struct l2t_entry *, uint16_t,
+ uint8_t, uint8_t *);
+void t4_l2t_release(struct l2t_entry *);
+
+#endif /* __T4_L2T_H */
diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c
index 469af8d..90e5001 100644
--- a/sys/dev/cxgbe/t4_main.c
+++ b/sys/dev/cxgbe/t4_main.c
@@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
#include "common/t4_regs_values.h"
#include "common/t4fw_interface.h"
#include "t4_ioctl.h"
+#include "t4_l2t.h"
/* T4 bus driver interface */
static int t4_probe(device_t);
@@ -213,12 +214,12 @@ SYSCTL_UINT(_hw_cxgbe, OID_AUTO, interrupt_types, CTLFLAG_RDTUN, &intr_types, 0,
"interrupt types allowed (bits 0, 1, 2 = INTx, MSI, MSI-X respectively)");
/*
- * Force the driver to use interrupt forwarding.
+ * Force the driver to use the same set of interrupts for all ports.
*/
-static int intr_fwd = 0;
-TUNABLE_INT("hw.cxgbe.interrupt_forwarding", &intr_fwd);
-SYSCTL_UINT(_hw_cxgbe, OID_AUTO, interrupt_forwarding, CTLFLAG_RDTUN,
- &intr_fwd, 0, "always use forwarded interrupts");
+static int intr_shared = 0;
+TUNABLE_INT("hw.cxgbe.interrupts_shared", &intr_shared);
+SYSCTL_UINT(_hw_cxgbe, OID_AUTO, interrupts_shared, CTLFLAG_RDTUN,
+ &intr_shared, 0, "interrupts shared between all ports");
static unsigned int filter_mode = HW_TPL_FR_MT_PR_IV_P_FC;
TUNABLE_INT("hw.cxgbe.filter_mode", &filter_mode);
@@ -228,7 +229,7 @@ SYSCTL_UINT(_hw_cxgbe, OID_AUTO, filter_mode, CTLFLAG_RDTUN,
struct intrs_and_queues {
int intr_type; /* INTx, MSI, or MSI-X */
int nirq; /* Number of vectors */
- int intr_fwd; /* Interrupts forwarded */
+ int intr_shared; /* Interrupts shared between all ports */
int ntxq10g; /* # of NIC txq's for each 10G port */
int nrxq10g; /* # of NIC rxq's for each 10G port */
int ntxq1g; /* # of NIC txq's for each 1G port */
@@ -240,6 +241,7 @@ struct filter_entry {
uint32_t locked:1; /* filter is administratively locked */
uint32_t pending:1; /* filter action is pending firmware reply */
uint32_t smtidx:8; /* Source MAC Table index for smac */
+ struct l2t_entry *l2t; /* Layer Two Table entry for dmac */
struct t4_filter_specification fs;
};
@@ -269,6 +271,7 @@ static void setup_memwin(struct adapter *);
static int cfg_itype_and_nqueues(struct adapter *, int, int,
struct intrs_and_queues *);
static int prep_firmware(struct adapter *);
+static int get_devlog_params(struct adapter *, struct devlog_params *);
static int get_capabilities(struct adapter *, struct fw_caps_config_cmd *);
static int get_params(struct adapter *, struct fw_caps_config_cmd *);
static void t4_set_desc(struct adapter *);
@@ -295,16 +298,18 @@ static int sysctl_holdoff_pktc_idx(SYSCTL_HANDLER_ARGS);
static int sysctl_qsize_rxq(SYSCTL_HANDLER_ARGS);
static int sysctl_qsize_txq(SYSCTL_HANDLER_ARGS);
static int sysctl_handle_t4_reg64(SYSCTL_HANDLER_ARGS);
+static int sysctl_devlog(SYSCTL_HANDLER_ARGS);
static inline void txq_start(struct ifnet *, struct sge_txq *);
static uint32_t fconf_to_mode(uint32_t);
static uint32_t mode_to_fconf(uint32_t);
static uint32_t fspec_to_fconf(struct t4_filter_specification *);
static int get_filter_mode(struct adapter *, uint32_t *);
static int set_filter_mode(struct adapter *, uint32_t);
+static inline uint64_t get_filter_hits(struct adapter *, uint32_t);
static int get_filter(struct adapter *, struct t4_filter *);
static int set_filter(struct adapter *, struct t4_filter *);
static int del_filter(struct adapter *, struct t4_filter *);
-static void clear_filter(struct adapter *, struct filter_entry *);
+static void clear_filter(struct filter_entry *);
static int set_filter_wr(struct adapter *, int);
static int del_filter_wr(struct adapter *, int);
void filter_rpl(struct adapter *, const struct cpl_set_tcb_rpl *);
@@ -400,6 +405,9 @@ t4_attach(device_t dev)
if (rc != 0)
goto done; /* error message displayed already */
+ /* Read firmware devlog parameters */
+ (void) get_devlog_params(sc, &sc->params.devlog);
+
/* Get device capabilities and select which ones we'll use */
rc = get_capabilities(sc, &caps);
if (rc != 0) {
@@ -484,6 +492,8 @@ t4_attach(device_t dev)
V_RXTSHIFTMAXR2(15) | V_PERSHIFTBACKOFFMAX(8) | V_PERSHIFTMAX(8) |
V_KEEPALIVEMAXR1(4) | V_KEEPALIVEMAXR2(9));
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);
setup_memwin(sc);
@@ -514,8 +524,8 @@ t4_attach(device_t dev)
device_printf(dev, "unable to initialize port %d: %d\n",
i, rc);
free(pi, M_CXGBE);
- sc->port[i] = NULL; /* indicates init failed */
- continue;
+ sc->port[i] = NULL;
+ goto done;
}
snprintf(pi->lockname, sizeof(pi->lockname), "%sp%d",
@@ -582,15 +592,15 @@ t4_attach(device_t dev)
s->nrxq = n10g * iaq.nrxq10g + n1g * iaq.nrxq1g;
s->ntxq = n10g * iaq.ntxq10g + n1g * iaq.ntxq1g;
s->neq = s->ntxq + s->nrxq; /* the free list in an rxq is an eq */
- s->neq += NCHAN; /* control queues, 1 per hw channel */
+ s->neq += sc->params.nports; /* control queues, 1 per port */
s->niq = s->nrxq + 1; /* 1 extra for firmware event queue */
- if (iaq.intr_fwd) {
- sc->flags |= INTR_FWD;
- s->niq += NFIQ(sc); /* forwarded interrupt queues */
- s->fiq = malloc(NFIQ(sc) * sizeof(struct sge_iq), M_CXGBE,
- M_ZERO | M_WAITOK);
- }
- s->ctrlq = malloc(NCHAN * sizeof(struct sge_ctrlq), M_CXGBE,
+ if (iaq.intr_shared)
+ sc->flags |= INTR_SHARED;
+ s->niq += NINTRQ(sc); /* interrupt queues */
+
+ s->intrq = malloc(NINTRQ(sc) * sizeof(struct sge_iq), M_CXGBE,
+ M_ZERO | M_WAITOK);
+ s->ctrlq = malloc(sc->params.nports * sizeof(struct sge_ctrlq), M_CXGBE,
M_ZERO | M_WAITOK);
s->rxq = malloc(s->nrxq * sizeof(struct sge_rxq), M_CXGBE,
M_ZERO | M_WAITOK);
@@ -604,6 +614,8 @@ t4_attach(device_t dev)
sc->irq = malloc(sc->intr_count * sizeof(struct irq), M_CXGBE,
M_ZERO | M_WAITOK);
+ sc->l2t = t4_init_l2t(M_WAITOK);
+
t4_sysctls(sc);
/*
@@ -691,11 +703,14 @@ t4_detach(device_t dev)
bus_release_resource(dev, SYS_RES_MEMORY, sc->msix_rid,
sc->msix_res);
+ if (sc->l2t)
+ t4_free_l2t(sc->l2t);
+
free(sc->irq, M_CXGBE);
free(sc->sge.rxq, M_CXGBE);
free(sc->sge.txq, M_CXGBE);
free(sc->sge.ctrlq, M_CXGBE);
- free(sc->sge.fiq, M_CXGBE);
+ free(sc->sge.intrq, M_CXGBE);
free(sc->sge.iqmap, M_CXGBE);
free(sc->sge.eqmap, M_CXGBE);
free(sc->tids.ftid_tab, M_CXGBE);
@@ -1231,33 +1246,32 @@ cfg_itype_and_nqueues(struct adapter *sc, int n10g, int n1g,
nrxq10g = min(nc, max_nrxq_10g);
nrxq1g = min(nc, max_nrxq_1g);
- /* Extra 2 is for a) error interrupt b) firmware event */
- iaq->nirq = n10g * nrxq10g + n1g * nrxq1g + 2;
- if (iaq->nirq <= navail && intr_fwd == 0) {
+ iaq->nirq = n10g * nrxq10g + n1g * nrxq1g + T4_EXTRA_INTR;
+ if (iaq->nirq <= navail && intr_shared == 0) {
if (itype == INTR_MSI && !powerof2(iaq->nirq))
- goto fwd;
+ goto share;
/* One for err, one for fwq, and one for each rxq */
- iaq->intr_fwd = 0;
+ iaq->intr_shared = 0;
iaq->nrxq10g = nrxq10g;
iaq->nrxq1g = nrxq1g;
} else {
-fwd:
- iaq->intr_fwd = 1;
+share:
+ iaq->intr_shared = 1;
- if (navail > nc) {
+ if (navail >= nc + T4_EXTRA_INTR) {
if (itype == INTR_MSIX)
- navail = nc + 1;
+ navail = nc + T4_EXTRA_INTR;
/* navail is and must remain a pow2 for MSI */
if (itype == INTR_MSI) {
KASSERT(powerof2(navail),
("%d not power of 2", navail));
- while (navail / 2 > nc)
+ while (navail / 2 >= nc + T4_EXTRA_INTR)
navail /= 2;
}
}
@@ -1290,7 +1304,7 @@ fwd:
* the kernel is willing to allocate (it's in navail).
*/
pci_release_msi(sc->dev);
- goto fwd;
+ goto share;
}
device_printf(sc->dev,
@@ -1414,6 +1428,34 @@ prep_firmware(struct adapter *sc)
}
static int
+get_devlog_params(struct adapter *sc, struct devlog_params *dlog)
+{
+ struct fw_devlog_cmd devlog_cmd;
+ uint32_t meminfo;
+ int rc;
+
+ bzero(&devlog_cmd, sizeof(devlog_cmd));
+ devlog_cmd.op_to_write = htobe32(V_FW_CMD_OP(FW_DEVLOG_CMD) |
+ F_FW_CMD_REQUEST | F_FW_CMD_READ);
+ devlog_cmd.retval_len16 = htobe32(FW_LEN16(devlog_cmd));
+ rc = -t4_wr_mbox(sc, sc->mbox, &devlog_cmd, sizeof(devlog_cmd),
+ &devlog_cmd);
+ if (rc != 0) {
+ device_printf(sc->dev,
+ "failed to get devlog parameters: %d.\n", rc);
+ bzero(dlog, sizeof (*dlog));
+ return (rc);
+ }
+
+ meminfo = be32toh(devlog_cmd.memtype_devlog_memaddr16_devlog);
+ dlog->memtype = G_FW_DEVLOG_CMD_MEMTYPE_DEVLOG(meminfo);
+ dlog->start = G_FW_DEVLOG_CMD_MEMADDR16_DEVLOG(meminfo) << 4;
+ dlog->size = be32toh(devlog_cmd.memsize_devlog);
+
+ return (0);
+}
+
+static int
get_capabilities(struct adapter *sc, struct fw_caps_config_cmd *caps)
{
int rc;
@@ -1923,16 +1965,18 @@ cxgbe_uninit_synchronized(struct port_info *pi)
return (0);
}
-#define T4_ALLOC_IRQ(sc, irqid, rid, handler, arg, name) do { \
- rc = t4_alloc_irq(sc, &sc->irq[irqid], rid, handler, arg, name); \
+#define T4_ALLOC_IRQ(sc, irq, rid, handler, arg, name) do { \
+ rc = t4_alloc_irq(sc, irq, rid, handler, arg, name); \
if (rc != 0) \
goto done; \
} while (0)
static int
first_port_up(struct adapter *sc)
{
- int rc, i;
- char name[8];
+ int rc, i, rid, p, q;
+ char s[8];
+ struct irq *irq;
+ struct sge_iq *intrq;
ADAPTER_LOCK_ASSERT_NOTOWNED(sc);
@@ -1946,39 +1990,52 @@ first_port_up(struct adapter *sc)
/*
* Setup interrupts.
*/
+ irq = &sc->irq[0];
+ rid = sc->intr_type == INTR_INTX ? 0 : 1;
if (sc->intr_count == 1) {
- KASSERT(sc->flags & INTR_FWD,
- ("%s: single interrupt but not forwarded?", __func__));
- T4_ALLOC_IRQ(sc, 0, 0, t4_intr_all, sc, "all");
+ KASSERT(sc->flags & INTR_SHARED,
+ ("%s: single interrupt but not shared?", __func__));
+
+ T4_ALLOC_IRQ(sc, irq, rid, t4_intr_all, sc, "all");
} else {
/* Multiple interrupts. The first one is always error intr */
- T4_ALLOC_IRQ(sc, 0, 1, t4_intr_err, sc, "err");
-
- if (sc->flags & INTR_FWD) {
- /* The rest are shared by the fwq and all data intr */
- for (i = 1; i < sc->intr_count; i++) {
- snprintf(name, sizeof(name), "mux%d", i - 1);
- T4_ALLOC_IRQ(sc, i, i + 1, t4_intr_fwd,
- &sc->sge.fiq[i - 1], name);
+ T4_ALLOC_IRQ(sc, irq, rid, t4_intr_err, sc, "err");
+ irq++;
+ rid++;
+
+ /* Firmware event queue normally has an interrupt of its own */
+ if (sc->intr_count > T4_EXTRA_INTR) {
+ T4_ALLOC_IRQ(sc, irq, rid, t4_intr_evt, &sc->sge.fwq,
+ "evt");
+ irq++;
+ rid++;
+ }
+
+ intrq = &sc->sge.intrq[0];
+ if (sc->flags & INTR_SHARED) {
+
+ /* All ports share these interrupt queues */
+
+ for (i = 0; i < NINTRQ(sc); i++) {
+ snprintf(s, sizeof(s), "*.%d", i);
+ T4_ALLOC_IRQ(sc, irq, rid, t4_intr, intrq, s);
+ irq++;
+ rid++;
+ intrq++;
}
} else {
- struct port_info *pi;
- int p, q;
- T4_ALLOC_IRQ(sc, 1, 2, t4_intr_evt, &sc->sge.fwq,
- "evt");
+ /* Each port has its own set of interrupt queues */
- p = q = 0;
- pi = sc->port[p];
- for (i = 2; i < sc->intr_count; i++) {
- snprintf(name, sizeof(name), "p%dq%d", p, q);
- if (++q >= pi->nrxq) {
- p++;
- q = 0;
- pi = sc->port[p];
+ for (p = 0; p < sc->params.nports; p++) {
+ for (q = 0; q < sc->port[p]->nrxq; q++) {
+ snprintf(s, sizeof(s), "%d.%d", p, q);
+ T4_ALLOC_IRQ(sc, irq, rid, t4_intr,
+ intrq, s);
+ irq++;
+ rid++;
+ intrq++;
}
- T4_ALLOC_IRQ(sc, i, i + 1, t4_intr_data,
- &sc->sge.rxq[i - 2], name);
}
}
}
@@ -2366,6 +2423,10 @@ t4_sysctls(struct adapter *sc)
CTLTYPE_STRING | CTLFLAG_RD, &intr_pktcount, sizeof(intr_pktcount),
sysctl_int_array, "A", "interrupt holdoff packet counter values");
+ SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "devlog",
+ CTLTYPE_STRING | CTLFLAG_RD, sc, 0,
+ sysctl_devlog, "A", "device log");
+
return (0);
}
@@ -2709,6 +2770,120 @@ sysctl_handle_t4_reg64(SYSCTL_HANDLER_ARGS)
return (sysctl_handle_64(oidp, &val, 0, req));
}
+const char *devlog_level_strings[] = {
+ [FW_DEVLOG_LEVEL_EMERG] = "EMERG",
+ [FW_DEVLOG_LEVEL_CRIT] = "CRIT",
+ [FW_DEVLOG_LEVEL_ERR] = "ERR",
+ [FW_DEVLOG_LEVEL_NOTICE] = "NOTICE",
+ [FW_DEVLOG_LEVEL_INFO] = "INFO",
+ [FW_DEVLOG_LEVEL_DEBUG] = "DEBUG"
+};
+
+const char *devlog_facility_strings[] = {
+ [FW_DEVLOG_FACILITY_CORE] = "CORE",
+ [FW_DEVLOG_FACILITY_SCHED] = "SCHED",
+ [FW_DEVLOG_FACILITY_TIMER] = "TIMER",
+ [FW_DEVLOG_FACILITY_RES] = "RES",
+ [FW_DEVLOG_FACILITY_HW] = "HW",
+ [FW_DEVLOG_FACILITY_FLR] = "FLR",
+ [FW_DEVLOG_FACILITY_DMAQ] = "DMAQ",
+ [FW_DEVLOG_FACILITY_PHY] = "PHY",
+ [FW_DEVLOG_FACILITY_MAC] = "MAC",
+ [FW_DEVLOG_FACILITY_PORT] = "PORT",
+ [FW_DEVLOG_FACILITY_VI] = "VI",
+ [FW_DEVLOG_FACILITY_FILTER] = "FILTER",
+ [FW_DEVLOG_FACILITY_ACL] = "ACL",
+ [FW_DEVLOG_FACILITY_TM] = "TM",
+ [FW_DEVLOG_FACILITY_QFC] = "QFC",
+ [FW_DEVLOG_FACILITY_DCB] = "DCB",
+ [FW_DEVLOG_FACILITY_ETH] = "ETH",
+ [FW_DEVLOG_FACILITY_OFLD] = "OFLD",
+ [FW_DEVLOG_FACILITY_RI] = "RI",
+ [FW_DEVLOG_FACILITY_ISCSI] = "ISCSI",
+ [FW_DEVLOG_FACILITY_FCOE] = "FCOE",
+ [FW_DEVLOG_FACILITY_FOISCSI] = "FOISCSI",
+ [FW_DEVLOG_FACILITY_FOFCOE] = "FOFCOE"
+};
+
+static int
+sysctl_devlog(SYSCTL_HANDLER_ARGS)
+{
+ struct adapter *sc = arg1;
+ struct devlog_params *dparams = &sc->params.devlog;
+ struct fw_devlog_e *buf, *e;
+ int i, j, rc, nentries, first = 0;
+ struct sbuf *sb;
+ uint64_t ftstamp = UINT64_MAX;
+
+ if (dparams->start == 0)
+ return (ENXIO);
+
+ nentries = dparams->size / sizeof(struct fw_devlog_e);
+
+ buf = malloc(dparams->size, M_CXGBE, M_NOWAIT);
+ if (buf == NULL)
+ return (ENOMEM);
+
+ rc = -t4_mem_read(sc, dparams->memtype, dparams->start, dparams->size,
+ (void *)buf);
+ if (rc != 0)
+ goto done;
+
+ for (i = 0; i < nentries; i++) {
+ e = &buf[i];
+
+ if (e->timestamp == 0)
+ break; /* end */
+
+ e->timestamp = be64toh(e->timestamp);
+ e->seqno = be32toh(e->seqno);
+ for (j = 0; j < 8; j++)
+ e->params[j] = be32toh(e->params[j]);
+
+ if (e->timestamp < ftstamp) {
+ ftstamp = e->timestamp;
+ first = i;
+ }
+ }
+
+ if (buf[first].timestamp == 0)
+ goto done; /* nothing in the log */
+
+ rc = sysctl_wire_old_buffer(req, 0);
+ if (rc != 0)
+ goto done;
+
+ sb = sbuf_new_for_sysctl(NULL, NULL, 4096, req);
+ sbuf_printf(sb, "\n%10s %15s %8s %8s %s\n",
+ "Seq#", "Tstamp", "Level", "Facility", "Message");
+
+ i = first;
+ do {
+ e = &buf[i];
+ if (e->timestamp == 0)
+ break; /* end */
+
+ sbuf_printf(sb, "%10d %15ju %8s %8s ",
+ e->seqno, e->timestamp,
+ (e->level < ARRAY_SIZE(devlog_level_strings) ?
+ devlog_level_strings[e->level] : "UNKNOWN"),
+ (e->facility < ARRAY_SIZE(devlog_facility_strings) ?
+ devlog_facility_strings[e->facility] : "UNKNOWN"));
+ sbuf_printf(sb, e->fmt, e->params[0], e->params[1],
+ e->params[2], e->params[3], e->params[4],
+ e->params[5], e->params[6], e->params[7]);
+
+ if (++i == nentries)
+ i = 0;
+ } while (i != first);
+
+ rc = sbuf_finish(sb);
+ sbuf_delete(sb);
+done:
+ free(buf, M_CXGBE);
+ return (rc);
+}
+
static inline void
txq_start(struct ifnet *ifp, struct sge_txq *txq)
{
@@ -2892,6 +3067,20 @@ done:
return (rc);
}
+static inline uint64_t
+get_filter_hits(struct adapter *sc, uint32_t fid)
+{
+ uint32_t tcb_base = t4_read_reg(sc, A_TP_CMM_TCB_BASE);
+ uint64_t hits;
+
+ t4_write_reg(sc, PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_OFFSET, 0),
+ tcb_base + (fid + sc->tids.ftid_base) * TCB_SIZE);
+ t4_read_reg(sc, PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_OFFSET, 0));
+ hits = t4_read_reg64(sc, MEMWIN0_BASE + 16);
+
+ return (be64toh(hits));
+}
+
static int
get_filter(struct adapter *sc, struct t4_filter *t)
{
@@ -2913,8 +3102,13 @@ get_filter(struct adapter *sc, struct t4_filter *t)
for (i = t->idx; i < nfilters; i++, f++) {
if (f->valid) {
t->idx = i;
+ t->l2tidx = f->l2t ? f->l2t->idx : 0;
+ t->smtidx = f->smtidx;
+ if (f->fs.hitcnts)
+ t->hits = get_filter_hits(sc, t->idx);
+ else
+ t->hits = UINT64_MAX;
t->fs = f->fs;
- t->hits = 0; /* XXX implement */
return (0);
}
@@ -3034,11 +3228,12 @@ del_filter(struct adapter *sc, struct t4_filter *t)
return (0);
}
-/* XXX: L2T */
static void
-clear_filter(struct adapter *sc, struct filter_entry *f)
+clear_filter(struct filter_entry *f)
{
- (void) sc;
+ if (f->l2t)
+ t4_l2t_release(f->l2t);
+
bzero(f, sizeof (*f));
}
@@ -3053,8 +3248,18 @@ set_filter_wr(struct adapter *sc, int fidx)
ADAPTER_LOCK_ASSERT_OWNED(sc);
- if (f->fs.newdmac || f->fs.newvlan)
- return (ENOTSUP); /* XXX: fix after L2T code */
+ if (f->fs.newdmac || f->fs.newvlan) {
+ /* This filter needs an L2T entry; allocate one. */
+ f->l2t = t4_l2t_alloc_switching(sc->l2t);
+ if (f->l2t == NULL)
+ return (EAGAIN);
+ if (t4_l2t_set_switching(sc, f->l2t, f->fs.vlan, f->fs.eport,
+ f->fs.dmac)) {
+ t4_l2t_release(f->l2t);
+ f->l2t = NULL;
+ return (ENOMEM);
+ }
+ }
ftid = sc->tids.ftid_base + fidx;
@@ -3089,7 +3294,7 @@ set_filter_wr(struct adapter *sc, int fidx)
V_FW_FILTER_WR_HITCNTS(f->fs.hitcnts) |
V_FW_FILTER_WR_TXCHAN(f->fs.eport) |
V_FW_FILTER_WR_PRIO(f->fs.prio) |
- V_FW_FILTER_WR_L2TIX(0)); /* XXX: L2T */
+ V_FW_FILTER_WR_L2TIX(f->l2t ? f->l2t->idx : 0));
fwr->ethtype = htobe16(f->fs.val.ethtype);
fwr->ethtypem = htobe16(f->fs.mask.ethtype);
fwr->frag_to_ovlan_vldm =
@@ -3101,7 +3306,7 @@ set_filter_wr(struct adapter *sc, int fidx)
V_FW_FILTER_WR_OVLAN_VLDM(f->fs.mask.ovlan_vld));
fwr->smac_sel = 0;
fwr->rx_chan_rx_rpl_iq = htobe16(V_FW_FILTER_WR_RX_CHAN(0) |
- V_FW_FILTER_WR_RX_RPL_IQ(sc->sge.fwq.abs_id));
+ V_FW_FILTER_WR_RX_RPL_IQ(sc->sge.intrq[0].abs_id));
fwr->maci_to_matchtypem =
htobe32(V_FW_FILTER_WR_MACI(f->fs.val.macidx) |
V_FW_FILTER_WR_MACIM(f->fs.mask.macidx) |
@@ -3136,7 +3341,7 @@ set_filter_wr(struct adapter *sc, int fidx)
if (rc != 0) {
sc->tids.ftids_in_use--;
m_freem(m);
- clear_filter(sc, f);
+ clear_filter(f);
}
return (rc);
}
@@ -3161,7 +3366,7 @@ del_filter_wr(struct adapter *sc, int fidx)
m->m_len = m->m_pkthdr.len = sizeof(*fwr);
bzero(fwr, sizeof (*fwr));
- t4_mk_filtdelwr(ftid, fwr, sc->sge.fwq.abs_id);
+ t4_mk_filtdelwr(ftid, fwr, sc->sge.intrq[0].abs_id);
f->pending = 1;
rc = t4_mgmt_tx(sc, m);
@@ -3188,12 +3393,12 @@ filter_rpl(struct adapter *sc, const struct cpl_set_tcb_rpl *rpl)
* Clear the filter when we get confirmation from the
* hardware that the filter has been deleted.
*/
- clear_filter(sc, f);
+ clear_filter(f);
sc->tids.ftids_in_use--;
} else if (rc == FW_FILTER_WR_SMT_TBL_FULL) {
device_printf(sc->dev,
"filter %u setup failed due to full SMT\n", idx);
- clear_filter(sc, f);
+ clear_filter(f);
sc->tids.ftids_in_use--;
} else if (rc == FW_FILTER_WR_FLT_ADDED) {
f->smtidx = (be64toh(rpl->oldval) >> 24) & 0xff;
@@ -3206,7 +3411,7 @@ filter_rpl(struct adapter *sc, const struct cpl_set_tcb_rpl *rpl)
*/
device_printf(sc->dev,
"filter %u setup failed with error %u\n", idx, rc);
- clear_filter(sc, f);
+ clear_filter(f);
sc->tids.ftids_in_use--;
}
}
diff --git a/sys/dev/cxgbe/t4_sge.c b/sys/dev/cxgbe/t4_sge.c
index a0ef172..b3e3567 100644
--- a/sys/dev/cxgbe/t4_sge.c
+++ b/sys/dev/cxgbe/t4_sge.c
@@ -91,6 +91,8 @@ struct sgl {
bus_dma_segment_t seg[TX_SGL_SEGS];
};
+static void t4_evt_rx(void *);
+static void t4_eth_rx(void *);
static inline void init_iq(struct sge_iq *, struct adapter *, int, int, int,
int, iq_intr_handler_t *, char *);
static inline void init_fl(struct sge_fl *, int, char *);
@@ -102,8 +104,10 @@ static int free_ring(struct adapter *, bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
static int alloc_iq_fl(struct port_info *, struct sge_iq *, struct sge_fl *,
int, int);
static int free_iq_fl(struct port_info *, struct sge_iq *, struct sge_fl *);
-static int alloc_iq(struct sge_iq *, int);
-static int free_iq(struct sge_iq *);
+static int alloc_intrq(struct adapter *, int, int, int);
+static int free_intrq(struct sge_iq *);
+static int alloc_fwq(struct adapter *, int);
+static int free_fwq(struct sge_iq *);
static int alloc_rxq(struct port_info *, struct sge_rxq *, int, int);
static int free_rxq(struct port_info *, struct sge_rxq *);
static int alloc_ctrlq(struct adapter *, struct sge_ctrlq *, int);
@@ -139,9 +143,10 @@ static void write_eqflush_wr(struct sge_eq *);
static __be64 get_flit(bus_dma_segment_t *, int, int);
static int handle_sge_egr_update(struct adapter *,
const struct cpl_sge_egr_update *);
+static void handle_cpl(struct adapter *, struct sge_iq *);
static int ctrl_tx(struct adapter *, struct sge_ctrlq *, struct mbuf *);
-static int sysctl_abs_id(SYSCTL_HANDLER_ARGS);
+static int sysctl_uint16(SYSCTL_HANDLER_ARGS);
extern void filter_rpl(struct adapter *, const struct cpl_set_tcb_rpl *);
@@ -198,6 +203,9 @@ t4_sge_init(struct adapter *sc)
FL_BUF_SIZE(i));
}
+ i = t4_read_reg(sc, A_SGE_CONM_CTRL);
+ s->fl_starve_threshold = G_EGRTHRESHOLD(i) * 2 + 1;
+
t4_write_reg(sc, A_SGE_INGRESS_RX_THRESHOLD,
V_THRESHOLD_0(s->counter_val[0]) |
V_THRESHOLD_1(s->counter_val[1]) |
@@ -243,8 +251,7 @@ t4_destroy_dma_tag(struct adapter *sc)
/*
* Allocate and initialize the firmware event queue, control queues, and the
- * forwarded interrupt queues (if any). The adapter owns all these queues as
- * they are not associated with any particular port.
+ * interrupt queues. The adapter owns all of these queues.
*
* Returns errno on failure. Resources allocated up to that point may still be
* allocated. Caller is responsible for cleanup in case this function fails.
@@ -252,8 +259,8 @@ t4_destroy_dma_tag(struct adapter *sc)
int
t4_setup_adapter_queues(struct adapter *sc)
{
- int i, rc;
- struct sge_iq *iq, *fwq;
+ int i, j, rc, intr_idx, qsize;
+ struct sge_iq *iq;
struct sge_ctrlq *ctrlq;
iq_intr_handler_t *handler;
char name[16];
@@ -264,47 +271,76 @@ t4_setup_adapter_queues(struct adapter *sc)
struct sysctl_oid *oid = device_get_sysctl_tree(sc->dev);
struct sysctl_oid_list *children = SYSCTL_CHILDREN(oid);
+ sc->oid_fwq = SYSCTL_ADD_NODE(&sc->ctx, children, OID_AUTO,
+ "fwq", CTLFLAG_RD, NULL, "firmware event queue");
sc->oid_ctrlq = SYSCTL_ADD_NODE(&sc->ctx, children, OID_AUTO,
"ctrlq", CTLFLAG_RD, NULL, "ctrl queues");
+ sc->oid_intrq = SYSCTL_ADD_NODE(&sc->ctx, children, OID_AUTO,
+ "intrq", CTLFLAG_RD, NULL, "interrupt queues");
}
- fwq = &sc->sge.fwq;
- if (sc->flags & INTR_FWD) {
- iq = &sc->sge.fiq[0];
-
- /*
- * Forwarded interrupt queues - allocate 1 if there's only 1
- * vector available, one less than the number of vectors
- * otherwise (the first vector is reserved for the error
- * interrupt in that case).
- */
- i = sc->intr_count > 1 ? 1 : 0;
- for (; i < sc->intr_count; i++, iq++) {
-
- snprintf(name, sizeof(name), "%s fiq%d",
+ /*
+ * Interrupt queues
+ */
+ intr_idx = sc->intr_count - NINTRQ(sc);
+ if (sc->flags & INTR_SHARED) {
+ qsize = max((sc->sge.nrxq + 1) * 2, INTR_IQ_QSIZE);
+ for (i = 0; i < NINTRQ(sc); i++, intr_idx++) {
+ snprintf(name, sizeof(name), "%s intrq%d",
device_get_nameunit(sc->dev), i);
- init_iq(iq, sc, 0, 0, (sc->sge.nrxq + 1) * 2, 16, NULL,
- name);
- rc = alloc_iq(iq, i);
+ iq = &sc->sge.intrq[i];
+ init_iq(iq, sc, 0, 0, qsize, INTR_IQ_ESIZE, NULL, name);
+ rc = alloc_intrq(sc, i % sc->params.nports, i,
+ intr_idx);
+
if (rc != 0) {
device_printf(sc->dev,
- "failed to create fwd intr queue %d: %d\n",
- i, rc);
+ "failed to create %s: %d\n", name, rc);
return (rc);
}
}
-
- handler = t4_evt_rx;
- i = 0; /* forward fwq's interrupt to the first fiq */
} else {
- handler = NULL;
- i = 1; /* fwq should use vector 1 (0 is used by error) */
+ int qidx = 0;
+ struct port_info *pi;
+
+ for (i = 0; i < sc->params.nports; i++) {
+ pi = sc->port[i];
+ qsize = max((pi->nrxq + 1) * 2, INTR_IQ_QSIZE);
+ for (j = 0; j < pi->nrxq; j++, qidx++, intr_idx++) {
+ snprintf(name, sizeof(name), "%s intrq%d",
+ device_get_nameunit(pi->dev), j);
+
+ iq = &sc->sge.intrq[qidx];
+ init_iq(iq, sc, 0, 0, qsize, INTR_IQ_ESIZE,
+ NULL, name);
+ rc = alloc_intrq(sc, i, qidx, intr_idx);
+
+ if (rc != 0) {
+ device_printf(sc->dev,
+ "failed to create %s: %d\n",
+ name, rc);
+ return (rc);
+ }
+ }
+ }
}
+ /*
+ * Firmware event queue
+ */
snprintf(name, sizeof(name), "%s fwq", device_get_nameunit(sc->dev));
- init_iq(fwq, sc, 0, 0, FW_IQ_QSIZE, FW_IQ_ESIZE, handler, name);
- rc = alloc_iq(fwq, i);
+ if (sc->intr_count > T4_EXTRA_INTR) {
+ handler = NULL;
+ intr_idx = 1;
+ } else {
+ handler = t4_evt_rx;
+ intr_idx = 0;
+ }
+
+ iq = &sc->sge.fwq;
+ init_iq(iq, sc, 0, 0, FW_IQ_QSIZE, FW_IQ_ESIZE, handler, name);
+ rc = alloc_fwq(sc, intr_idx);
if (rc != 0) {
device_printf(sc->dev,
"failed to create firmware event queue: %d\n", rc);
@@ -313,10 +349,10 @@ t4_setup_adapter_queues(struct adapter *sc)
}
/*
- * Control queues - one per hardware channel.
+ * Control queues - one per port.
*/
ctrlq = &sc->sge.ctrlq[0];
- for (i = 0; i < NCHAN; i++, ctrlq++) {
+ for (i = 0; i < sc->params.nports; i++, ctrlq++) {
snprintf(name, sizeof(name), "%s ctrlq%d",
device_get_nameunit(sc->dev), i);
init_eq(&ctrlq->eq, CTRL_EQ_QSIZE, name);
@@ -344,21 +380,22 @@ t4_teardown_adapter_queues(struct adapter *sc)
ADAPTER_LOCK_ASSERT_NOTOWNED(sc);
/* Do this before freeing the queues */
- if (sc->oid_ctrlq) {
+ if (sc->oid_fwq || sc->oid_ctrlq || sc->oid_intrq) {
sysctl_ctx_free(&sc->ctx);
+ sc->oid_fwq = NULL;
sc->oid_ctrlq = NULL;
+ sc->oid_intrq = NULL;
}
- for (i = 0; i < NCHAN; i++)
+ for (i = 0; i < sc->params.nports; i++)
free_ctrlq(sc, &sc->sge.ctrlq[i]);
iq = &sc->sge.fwq;
- free_iq(iq);
- if (sc->flags & INTR_FWD) {
- for (i = 0; i < NFIQ(sc); i++) {
- iq = &sc->sge.fiq[i];
- free_iq(iq);
- }
+ free_fwq(iq);
+
+ for (i = 0; i < NINTRQ(sc); i++) {
+ iq = &sc->sge.intrq[i];
+ free_intrq(iq);
}
return (0);
@@ -388,23 +425,19 @@ t4_setup_eth_queues(struct port_info *pi)
snprintf(name, sizeof(name), "%s rxq%d-iq",
device_get_nameunit(pi->dev), i);
init_iq(&rxq->iq, sc, pi->tmr_idx, pi->pktc_idx,
- pi->qsize_rxq, RX_IQ_ESIZE,
- sc->flags & INTR_FWD ? t4_eth_rx : NULL, name);
+ pi->qsize_rxq, RX_IQ_ESIZE, t4_eth_rx, name);
snprintf(name, sizeof(name), "%s rxq%d-fl",
device_get_nameunit(pi->dev), i);
init_fl(&rxq->fl, pi->qsize_rxq / 8, name);
- if (sc->flags & INTR_FWD)
- intr_idx = (pi->first_rxq + i) % NFIQ(sc);
- else
- intr_idx = pi->first_rxq + i + 2;
+ intr_idx = pi->first_rxq + i;
+ if (sc->flags & INTR_SHARED)
+ intr_idx %= NINTRQ(sc);
rc = alloc_rxq(pi, rxq, intr_idx, i);
if (rc != 0)
goto done;
-
- intr_idx++;
}
for_each_txq(pi, i, txq) {
@@ -452,25 +485,26 @@ t4_teardown_eth_queues(struct port_info *pi)
return (0);
}
-/* Deals with errors and forwarded interrupts */
+/* Deals with errors and the first (and only) interrupt queue */
void
t4_intr_all(void *arg)
{
struct adapter *sc = arg;
t4_intr_err(arg);
- t4_intr_fwd(&sc->sge.fiq[0]);
+ t4_intr(&sc->sge.intrq[0]);
}
-/* Deals with forwarded interrupts on the given ingress queue */
+/* Deals with interrupts, and a few CPLs, on the given interrupt queue */
void
-t4_intr_fwd(void *arg)
+t4_intr(void *arg)
{
struct sge_iq *iq = arg, *q;
struct adapter *sc = iq->adapter;
struct rsp_ctrl *ctrl;
+ const struct rss_header *rss;
int ndesc_pending = 0, ndesc_total = 0;
- int qid;
+ int qid, rsp_type;
if (!atomic_cmpset_32(&iq->state, IQS_IDLE, IQS_BUSY))
return;
@@ -479,17 +513,23 @@ t4_intr_fwd(void *arg)
rmb();
- /* Only interrupt muxing expected on this queue */
- KASSERT(G_RSPD_TYPE(ctrl->u.type_gen) == X_RSPD_TYPE_INTR,
- ("unexpected event on forwarded interrupt queue: %x",
- G_RSPD_TYPE(ctrl->u.type_gen)));
+ rss = (const void *)iq->cdesc;
+ rsp_type = G_RSPD_TYPE(ctrl->u.type_gen);
+
+ if (__predict_false(rsp_type == X_RSPD_TYPE_CPL)) {
+ handle_cpl(sc, iq);
+ goto nextdesc;
+ }
qid = ntohl(ctrl->pldbuflen_qid) - sc->sge.iq_start;
q = sc->sge.iqmap[qid];
- q->handler(q);
+ if (atomic_cmpset_32(&q->state, IQS_IDLE, IQS_BUSY)) {
+ q->handler(q);
+ atomic_cmpset_32(&q->state, IQS_BUSY, IQS_IDLE);
+ }
- ndesc_total++;
+nextdesc: ndesc_total++;
if (++ndesc_pending >= iq->qsize / 4) {
t4_write_reg(sc, MYPF_REG(A_SGE_PF_GTS),
V_CIDXINC(ndesc_pending) |
@@ -514,9 +554,7 @@ t4_intr_err(void *arg)
{
struct adapter *sc = arg;
- if (sc->intr_type == INTR_INTX)
- t4_write_reg(sc, MYPF_REG(A_PCIE_PF_CLI), 0);
-
+ t4_write_reg(sc, MYPF_REG(A_PCIE_PF_CLI), 0);
t4_slow_intr_handler(sc);
}
@@ -526,70 +564,32 @@ t4_intr_evt(void *arg)
{
struct sge_iq *iq = arg;
- if (!atomic_cmpset_32(&iq->state, IQS_IDLE, IQS_BUSY))
- return;
-
- t4_evt_rx(arg);
-
- atomic_cmpset_32(&iq->state, IQS_BUSY, IQS_IDLE);
-}
-
-void
-t4_intr_data(void *arg)
-{
- struct sge_iq *iq = arg;
-
- if (!atomic_cmpset_32(&iq->state, IQS_IDLE, IQS_BUSY))
- return;
-
- t4_eth_rx(arg);
-
- atomic_cmpset_32(&iq->state, IQS_BUSY, IQS_IDLE);
+ if (atomic_cmpset_32(&iq->state, IQS_IDLE, IQS_BUSY)) {
+ t4_evt_rx(arg);
+ atomic_cmpset_32(&iq->state, IQS_BUSY, IQS_IDLE);
+ }
}
-void
+static void
t4_evt_rx(void *arg)
{
struct sge_iq *iq = arg;
struct adapter *sc = iq->adapter;
struct rsp_ctrl *ctrl;
- const struct rss_header *rss;
int ndesc_pending = 0, ndesc_total = 0;
KASSERT(iq == &sc->sge.fwq, ("%s: unexpected ingress queue", __func__));
while (is_new_response(iq, &ctrl)) {
+ int rsp_type;
rmb();
- rss = (const void *)iq->cdesc;
-
- /* Should only get CPL on this queue */
- KASSERT(G_RSPD_TYPE(ctrl->u.type_gen) == X_RSPD_TYPE_CPL,
- ("%s: unexpected type %d", __func__,
- G_RSPD_TYPE(ctrl->u.type_gen)));
+ rsp_type = G_RSPD_TYPE(ctrl->u.type_gen);
+ if (__predict_false(rsp_type != X_RSPD_TYPE_CPL))
+ panic("%s: unexpected rsp_type %d", __func__, rsp_type);
- switch (rss->opcode) {
- case CPL_FW4_MSG:
- case CPL_FW6_MSG: {
- const struct cpl_fw6_msg *cpl;
-
- cpl = (const void *)(rss + 1);
- if (cpl->type == FW6_TYPE_CMD_RPL)
- t4_handle_fw_rpl(sc, cpl->data);
-
- break;
- }
- case CPL_SGE_EGR_UPDATE:
- handle_sge_egr_update(sc, (const void *)(rss + 1));
- break;
- case CPL_SET_TCB_RPL:
- filter_rpl(sc, (const void *) (rss + 1));
- break;
- default:
- device_printf(sc->dev,
- "can't handle CPL opcode %d.", rss->opcode);
- }
+ handle_cpl(sc, iq);
ndesc_total++;
if (++ndesc_pending >= iq->qsize / 4) {
@@ -600,6 +600,7 @@ t4_evt_rx(void *arg)
V_QINTR_TIMER_IDX(X_TIMERREG_UPDATE_CIDX)));
ndesc_pending = 0;
}
+
iq_next(iq);
}
@@ -613,7 +614,7 @@ t4_evt_rx(void *arg)
#define RX_COPY_THRESHOLD MINCLSIZE
#endif
-void
+static void
t4_eth_rx(void *arg)
{
struct sge_rxq *rxq = arg;
@@ -644,17 +645,9 @@ t4_eth_rx(void *arg)
rss = (const void *)iq->cdesc;
i = G_RSPD_TYPE(ctrl->u.type_gen);
- if (__predict_false(i == X_RSPD_TYPE_CPL)) {
-
- /* Can't be anything except an egress update */
- KASSERT(rss->opcode == CPL_SGE_EGR_UPDATE,
- ("%s: unexpected CPL %x", __func__, rss->opcode));
-
- handle_sge_egr_update(sc, (const void *)(rss + 1));
- goto nextdesc;
- }
KASSERT(i == X_RSPD_TYPE_FLBUF && rss->opcode == CPL_RX_PKT,
- ("%s: unexpected CPL %x rsp %d", __func__, rss->opcode, i));
+ ("%s: unexpected type %d CPL opcode 0x%x",
+ __func__, i, rss->opcode));
sd_next = sd + 1;
if (__predict_false(fl->cidx + 1 == fl->cap))
@@ -786,16 +779,15 @@ t4_eth_rx(void *arg)
refill_fl(sc, fl, 64, 32);
FL_UNLOCK(fl);
-nextdesc: ndescs++;
- iq_next(iq);
-
- if (ndescs > 32) {
+ if (++ndescs > 32) {
t4_write_reg(sc, MYPF_REG(A_SGE_PF_GTS),
V_CIDXINC(ndescs) |
V_INGRESSQID((u32)iq->cntxt_id) |
V_SEINTARM(V_QINTR_TIMER_IDX(X_TIMERREG_UPDATE_CIDX)));
ndescs = 0;
}
+
+ iq_next(iq);
}
#ifdef INET
@@ -1008,7 +1000,7 @@ t4_update_fl_bufsize(struct ifnet *ifp)
/*
* A non-NULL handler indicates this iq will not receive direct interrupts, the
- * handler will be invoked by a forwarded interrupt queue.
+ * handler will be invoked by an interrupt queue.
*/
static inline void
init_iq(struct sge_iq *iq, struct adapter *sc, int tmr_idx, int pktc_idx,
@@ -1100,7 +1092,7 @@ free_ring(struct adapter *sc, bus_dma_tag_t tag, bus_dmamap_t map,
*
* If the ingress queue will take interrupts directly (iq->handler == NULL) then
* the intr_idx specifies the vector, starting from 0. Otherwise it specifies
- * the index of the queue to which its interrupts will be forwarded.
+ * the index of the interrupt queue to which its interrupts will be forwarded.
*/
static int
alloc_iq_fl(struct port_info *pi, struct sge_iq *iq, struct sge_fl *fl,
@@ -1112,10 +1104,6 @@ alloc_iq_fl(struct port_info *pi, struct sge_iq *iq, struct sge_fl *fl,
struct adapter *sc = iq->adapter;
__be32 v = 0;
- /* The adapter queues are nominally allocated in port[0]'s name */
- if (pi == NULL)
- pi = sc->port[0];
-
len = iq->qsize * iq->esize;
rc = alloc_ring(sc, len, &iq->desc_tag, &iq->desc_map, &iq->ba,
(void **)&iq->desc);
@@ -1135,10 +1123,10 @@ alloc_iq_fl(struct port_info *pi, struct sge_iq *iq, struct sge_fl *fl,
v |= F_FW_IQ_CMD_IQASYNCH;
if (iq->handler) {
- KASSERT(intr_idx < NFIQ(sc),
+ KASSERT(intr_idx < NINTRQ(sc),
("%s: invalid indirect intr_idx %d", __func__, intr_idx));
v |= F_FW_IQ_CMD_IQANDST;
- v |= V_FW_IQ_CMD_IQANDSTINDEX(sc->sge.fiq[intr_idx].abs_id);
+ v |= V_FW_IQ_CMD_IQANDSTINDEX(sc->sge.intrq[intr_idx].abs_id);
} else {
KASSERT(intr_idx < sc->intr_count,
("%s: invalid direct intr_idx %d", __func__, intr_idx));
@@ -1248,7 +1236,8 @@ alloc_iq_fl(struct port_info *pi, struct sge_iq *iq, struct sge_fl *fl,
sc->sge.eqmap[cntxt_id] = (void *)fl;
FL_LOCK(fl);
- refill_fl(sc, fl, -1, 8);
+ /* Just enough to make sure it doesn't starve right away. */
+ refill_fl(sc, fl, roundup(sc->sge.fl_starve_threshold, 8), 8);
FL_UNLOCK(fl);
}
@@ -1333,13 +1322,61 @@ free_iq_fl(struct port_info *pi, struct sge_iq *iq, struct sge_fl *fl)
}
static int
-alloc_iq(struct sge_iq *iq, int intr_idx)
+alloc_intrq(struct adapter *sc, int port_idx, int intrq_idx, int intr_idx)
{
- return alloc_iq_fl(NULL, iq, NULL, intr_idx, -1);
+ int rc;
+ struct sysctl_oid *oid;
+ struct sysctl_oid_list *children;
+ char name[16];
+ struct sge_iq *intrq = &sc->sge.intrq[intrq_idx];
+
+ rc = alloc_iq_fl(sc->port[port_idx], intrq, NULL, intr_idx, -1);
+ if (rc != 0)
+ return (rc);
+
+ children = SYSCTL_CHILDREN(sc->oid_intrq);
+
+ snprintf(name, sizeof(name), "%d", intrq_idx);
+ oid = SYSCTL_ADD_NODE(&sc->ctx, children, OID_AUTO, name, CTLFLAG_RD,
+ NULL, "interrupt queue");
+ children = SYSCTL_CHILDREN(oid);
+
+ SYSCTL_ADD_PROC(&sc->ctx, children, OID_AUTO, "cidx",
+ CTLTYPE_INT | CTLFLAG_RD, &intrq->cidx, 0, sysctl_uint16, "I",
+ "consumer index");
+
+ return (rc);
}
static int
-free_iq(struct sge_iq *iq)
+free_intrq(struct sge_iq *iq)
+{
+ return free_iq_fl(NULL, iq, NULL);
+
+}
+
+static int
+alloc_fwq(struct adapter *sc, int intr_idx)
+{
+ int rc;
+ struct sysctl_oid_list *children;
+ struct sge_iq *fwq = &sc->sge.fwq;
+
+ rc = alloc_iq_fl(sc->port[0], fwq, NULL, intr_idx, -1);
+ if (rc != 0)
+ return (rc);
+
+ children = SYSCTL_CHILDREN(sc->oid_fwq);
+
+ SYSCTL_ADD_PROC(&sc->ctx, children, OID_AUTO, "cidx",
+ CTLTYPE_INT | CTLFLAG_RD, &fwq->cidx, 0, sysctl_uint16, "I",
+ "consumer index");
+
+ return (rc);
+}
+
+static int
+free_fwq(struct sge_iq *iq)
{
return free_iq_fl(NULL, iq, NULL);
}
@@ -1356,6 +1393,10 @@ alloc_rxq(struct port_info *pi, struct sge_rxq *rxq, int intr_idx, int idx)
if (rc != 0)
return (rc);
+ FL_LOCK(&rxq->fl);
+ refill_fl(pi->adapter, &rxq->fl, rxq->fl.needed / 8, 8);
+ FL_UNLOCK(&rxq->fl);
+
#ifdef INET
rc = tcp_lro_init(&rxq->lro);
if (rc != 0)
@@ -1375,7 +1416,7 @@ alloc_rxq(struct port_info *pi, struct sge_rxq *rxq, int intr_idx, int idx)
children = SYSCTL_CHILDREN(oid);
SYSCTL_ADD_PROC(&pi->ctx, children, OID_AUTO, "abs_id",
- CTLTYPE_INT | CTLFLAG_RD, &rxq->iq.abs_id, 0, sysctl_abs_id, "I",
+ CTLTYPE_INT | CTLFLAG_RD, &rxq->iq.abs_id, 0, sysctl_uint16, "I",
"absolute id of the queue");
#ifdef INET
SYSCTL_ADD_INT(&pi->ctx, children, OID_AUTO, "lro_queued", CTLFLAG_RD,
@@ -1433,7 +1474,10 @@ alloc_ctrlq(struct adapter *sc, struct sge_ctrlq *ctrlq, int idx)
eq->cap = eq->qsize - SPG_LEN / CTRL_EQ_ESIZE;
eq->spg = (void *)&eq->desc[eq->cap];
eq->avail = eq->cap - 1; /* one less to avoid cidx = pidx */
- eq->iqid = sc->sge.fwq.cntxt_id;
+ if (sc->flags & INTR_SHARED)
+ eq->iqid = sc->sge.intrq[idx % NINTRQ(sc)].cntxt_id;
+ else
+ eq->iqid = sc->sge.intrq[sc->port[idx]->first_rxq].cntxt_id;
bzero(&c, sizeof(c));
@@ -1446,8 +1490,8 @@ alloc_ctrlq(struct adapter *sc, struct sge_ctrlq *ctrlq, int idx)
c.physeqid_pkd = htobe32(0);
c.fetchszm_to_iqid =
htobe32(V_FW_EQ_CTRL_CMD_HOSTFCMODE(X_HOSTFCMODE_STATUS_PAGE) |
- V_FW_EQ_CTRL_CMD_PCIECHN(idx) | F_FW_EQ_CTRL_CMD_FETCHRO |
- V_FW_EQ_CTRL_CMD_IQID(eq->iqid));
+ V_FW_EQ_CTRL_CMD_PCIECHN(sc->port[idx]->tx_chan) |
+ F_FW_EQ_CTRL_CMD_FETCHRO | V_FW_EQ_CTRL_CMD_IQID(eq->iqid));
c.dcaen_to_eqsize =
htobe32(V_FW_EQ_CTRL_CMD_FBMIN(X_FETCHBURSTMIN_64B) |
V_FW_EQ_CTRL_CMD_FBMAX(X_FETCHBURSTMAX_512B) |
@@ -1479,13 +1523,12 @@ alloc_ctrlq(struct adapter *sc, struct sge_ctrlq *ctrlq, int idx)
NULL, "ctrl queue");
children = SYSCTL_CHILDREN(oid);
- SYSCTL_ADD_UQUAD(&sc->ctx, children, OID_AUTO, "total_wrs", CTLFLAG_RD,
- &ctrlq->total_wrs, "total # of work requests");
+ SYSCTL_ADD_PROC(&sc->ctx, children, OID_AUTO, "pidx",
+ CTLTYPE_INT | CTLFLAG_RD, &ctrlq->eq.pidx, 0, sysctl_uint16, "I",
+ "producer index");
SYSCTL_ADD_UINT(&sc->ctx, children, OID_AUTO, "no_desc", CTLFLAG_RD,
&ctrlq->no_desc, 0,
"# of times ctrlq ran out of hardware descriptors");
- SYSCTL_ADD_UINT(&sc->ctx, children, OID_AUTO, "too_long", CTLFLAG_RD,
- &ctrlq->too_long, 0, "# of oversized work requests");
return (rc);
}
@@ -1526,6 +1569,7 @@ alloc_txq(struct port_info *pi, struct sge_txq *txq, int idx)
char name[16];
struct sysctl_oid *oid;
struct sysctl_oid_list *children;
+ struct sge_iq *intrq;
txq->ifp = pi->ifp;
TASK_INIT(&txq->resume_tx, 0, cxgbe_txq_start, txq);
@@ -1544,7 +1588,12 @@ alloc_txq(struct port_info *pi, struct sge_txq *txq, int idx)
txq->sdesc = malloc(eq->cap * sizeof(struct tx_sdesc), M_CXGBE,
M_ZERO | M_WAITOK);
txq->br = buf_ring_alloc(eq->qsize, M_CXGBE, M_WAITOK, &eq->eq_lock);
- eq->iqid = sc->sge.rxq[pi->first_rxq].iq.cntxt_id;
+
+ intrq = &sc->sge.intrq[0];
+ if (sc->flags & INTR_SHARED)
+ eq->iqid = intrq[(pi->first_txq + idx) % NINTRQ(sc)].cntxt_id;
+ else
+ eq->iqid = intrq[pi->first_rxq + (idx % pi->nrxq)].cntxt_id;
rc = bus_dma_tag_create(sc->dmat, 1, 0, BUS_SPACE_MAXADDR,
BUS_SPACE_MAXADDR, NULL, NULL, 64 * 1024, TX_SGL_SEGS,
@@ -2324,7 +2373,7 @@ write_txpkts_wr(struct sge_txq *txq, struct txpkts *txpkts)
wr->equiq_to_len16 = htobe32(ctrl);
wr->plen = htobe16(txpkts->plen);
wr->npkt = txpkts->npkt;
- wr->r3 = wr->r4 = 0;
+ wr->r3 = wr->type = 0;
/* Everything else already written */
@@ -2695,6 +2744,32 @@ handle_sge_egr_update(struct adapter *sc, const struct cpl_sge_egr_update *cpl)
return (0);
}
+static void
+handle_cpl(struct adapter *sc, struct sge_iq *iq)
+{
+ const struct rss_header *rss = (const void *)iq->cdesc;
+ const struct cpl_fw6_msg *cpl = (const void *)(rss + 1);
+
+ switch (rss->opcode) {
+ case CPL_FW4_MSG:
+ case CPL_FW6_MSG:
+ if (cpl->type == FW6_TYPE_CMD_RPL)
+ t4_handle_fw_rpl(sc, cpl->data);
+ break;
+
+ case CPL_SGE_EGR_UPDATE:
+ handle_sge_egr_update(sc, (const void *)cpl);
+ break;
+
+ case CPL_SET_TCB_RPL:
+ filter_rpl(sc, (const void *)cpl);
+ break;
+
+ default:
+ panic("%s: unexpected CPL opcode 0x%x", __func__, rss->opcode);
+ }
+}
+
/*
* m0 is freed on successful transmission.
*/
@@ -2710,7 +2785,8 @@ ctrl_tx(struct adapter *sc, struct sge_ctrlq *ctrlq, struct mbuf *m0)
M_ASSERTPKTHDR(m0);
if (m0->m_pkthdr.len > SGE_MAX_WR_LEN) {
- ctrlq->too_long++;
+ log(LOG_ERR, "%s: %s work request too long (%d)",
+ device_get_nameunit(sc->dev), __func__, m0->m_pkthdr.len);
return (EMSGSIZE);
}
ndesc = howmany(m0->m_pkthdr.len, CTRL_EQ_ESIZE);
@@ -2738,7 +2814,6 @@ ctrl_tx(struct adapter *sc, struct sge_ctrlq *ctrlq, struct mbuf *m0)
eq->pidx -= eq->cap;
eq->pending += ndesc;
- ctrlq->total_wrs++;
ring_eq_db(sc, eq);
failed:
EQ_UNLOCK(eq);
@@ -2749,7 +2824,7 @@ failed:
}
static int
-sysctl_abs_id(SYSCTL_HANDLER_ARGS)
+sysctl_uint16(SYSCTL_HANDLER_ARGS)
{
uint16_t *id = arg1;
int i = *id;
diff --git a/sys/dev/iicbus/ad7417.c b/sys/dev/iicbus/ad7417.c
new file mode 100644
index 0000000..084b9f5
--- /dev/null
+++ b/sys/dev/iicbus/ad7417.c
@@ -0,0 +1,537 @@
+/*-
+ * Copyright (c) 2010 Andreas Tobler
+ * 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$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/callout.h>
+#include <sys/conf.h>
+#include <sys/cpu.h>
+#include <sys/ctype.h>
+#include <sys/kernel.h>
+#include <sys/reboot.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+#include <sys/limits.h>
+
+#include <machine/bus.h>
+#include <machine/md_var.h>
+
+#include <dev/iicbus/iicbus.h>
+#include <dev/iicbus/iiconf.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <powerpc/powermac/powermac_thermal.h>
+
+#define FCU_ZERO_C_TO_K 2732
+
+/* CPU A/B sensors, temp and adc: AD7417. */
+
+#define AD7417_TEMP 0x00
+#define AD7417_CONFIG 0x01
+#define AD7417_ADC 0x04
+#define AD7417_CONFIG2 0x05
+#define AD7417_CONFMASK 0xe0
+
+uint8_t adc741x_config;
+
+struct ad7417_sensor {
+ struct pmac_therm therm;
+ device_t dev;
+ int id;
+ enum {
+ ADC7417_TEMP_SENSOR,
+ ADC7417_ADC_SENSOR
+ } type;
+};
+
+/* Regular bus attachment functions */
+static int ad7417_probe(device_t);
+static int ad7417_attach(device_t);
+
+/* Utility functions */
+static int ad7417_sensor_sysctl(SYSCTL_HANDLER_ARGS);
+static int ad7417_write(device_t dev, uint32_t addr, uint8_t reg,
+ uint8_t *buf, int len);
+static int ad7417_read_1(device_t dev, uint32_t addr, uint8_t reg,
+ uint8_t *data);
+static int ad7417_read_2(device_t dev, uint32_t addr, uint8_t reg,
+ uint16_t *data);
+static int ad7417_diode_read(struct ad7417_sensor *sens);
+static int ad7417_adc_read(struct ad7417_sensor *sens);
+static int ad7417_sensor_read(struct ad7417_sensor *sens);
+
+struct ad7417_softc {
+ device_t sc_dev;
+ uint32_t sc_addr;
+ struct ad7417_sensor *sc_sensors;
+ int sc_nsensors;
+};
+static device_method_t ad7417_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ad7417_probe),
+ DEVMETHOD(device_attach, ad7417_attach),
+ { 0, 0 },
+};
+
+static driver_t ad7417_driver = {
+ "ad7417",
+ ad7417_methods,
+ sizeof(struct ad7417_softc)
+};
+
+static devclass_t ad7417_devclass;
+
+DRIVER_MODULE(ad7417, iicbus, ad7417_driver, ad7417_devclass, 0, 0);
+MALLOC_DEFINE(M_AD7417, "ad7417", "Supply-Monitor AD7417");
+
+
+static int
+ad7417_write(device_t dev, uint32_t addr, uint8_t reg, uint8_t *buff, int len)
+{
+ unsigned char buf[4];
+ struct iic_msg msg[] = {
+ { addr, IIC_M_WR, 0, buf }
+ };
+
+ msg[0].len = len + 1;
+ buf[0] = reg;
+ memcpy(buf + 1, buff, len);
+
+ if (iicbus_transfer(dev, msg, 1) != 0) {
+ device_printf(dev, "iicbus write failed\n");
+ return (EIO);
+ }
+
+ return (0);
+
+}
+
+static int
+ad7417_read_1(device_t dev, uint32_t addr, uint8_t reg, uint8_t *data)
+{
+ uint8_t buf[4];
+
+ struct iic_msg msg[2] = {
+ { addr, IIC_M_WR | IIC_M_NOSTOP, 1, &reg },
+ { addr, IIC_M_RD, 1, buf },
+ };
+
+ if (iicbus_transfer(dev, msg, 2) != 0) {
+ device_printf(dev, "iicbus read failed\n");
+ return (EIO);
+ }
+
+ *data = *((uint8_t*)buf);
+
+ return (0);
+}
+
+static int
+ad7417_read_2(device_t dev, uint32_t addr, uint8_t reg, uint16_t *data)
+{
+ uint8_t buf[4];
+
+ struct iic_msg msg[2] = {
+ { addr, IIC_M_WR | IIC_M_NOSTOP, 1, &reg },
+ { addr, IIC_M_RD, 2, buf },
+ };
+
+ if (iicbus_transfer(dev, msg, 2) != 0) {
+ device_printf(dev, "iicbus read failed\n");
+ return (EIO);
+ }
+
+ *data = *((uint16_t*)buf);
+
+ return (0);
+}
+
+static int
+ad7417_init_adc(device_t dev, uint32_t addr)
+{
+ uint8_t buf;
+
+ adc741x_config = 0;
+ /* Clear Config2 */
+ buf = 0;
+ ad7417_write(dev, addr, AD7417_CONFIG2, &buf, 1);
+
+ /* Read & cache Config1 */
+ buf = 0;
+ ad7417_write(dev, addr, AD7417_CONFIG, &buf, 1);
+
+ ad7417_read_1(dev, addr, AD7417_CONFIG, &buf);
+ adc741x_config = (uint8_t)buf;
+
+ /* Disable shutdown mode */
+ adc741x_config &= 0xfe;
+ buf = adc741x_config;
+ ad7417_write(dev, addr, AD7417_CONFIG, &buf, 1);
+
+ return (0);
+
+}
+static int
+ad7417_probe(device_t dev)
+{
+ const char *name, *compatible;
+ struct ad7417_softc *sc;
+
+ name = ofw_bus_get_name(dev);
+ compatible = ofw_bus_get_compat(dev);
+
+ if (!name)
+ return (ENXIO);
+
+ if (strcmp(name, "supply-monitor") != 0 ||
+ strcmp(compatible, "ad7417") != 0)
+ return (ENXIO);
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+ sc->sc_addr = iicbus_get_addr(dev);
+
+ device_set_desc(dev, "Supply-Monitor AD7417");
+
+ return (0);
+}
+
+/*
+ * This function returns the number of sensors. If we call it the second time
+ * and we have allocated memory for sc->sc_sensors, we fill in the properties.
+ */
+static int
+ad7417_fill_sensor_prop(device_t dev)
+{
+ phandle_t child;
+ struct ad7417_softc *sc;
+ u_int id[10];
+ char location[96];
+ char type[32];
+ int i = 0, j, len = 0, prop_len, prev_len = 0;
+
+ sc = device_get_softc(dev);
+
+ child = ofw_bus_get_node(dev);
+
+ /* Fill the sensor location property. */
+ prop_len = OF_getprop(child, "hwsensor-location", location,
+ sizeof(location));
+ while (len < prop_len) {
+ if (sc->sc_sensors != NULL)
+ strcpy(sc->sc_sensors[i].therm.name, location + len);
+ prev_len = strlen(location + len) + 1;
+ len += prev_len;
+ i++;
+ }
+ if (sc->sc_sensors == NULL)
+ return (i);
+
+ /* Fill the sensor type property. */
+ len = 0;
+ i = 0;
+ prev_len = 0;
+ prop_len = OF_getprop(child, "hwsensor-type", type, sizeof(type));
+ while (len < prop_len) {
+ if (strcmp(type + len, "temperature") == 0)
+ sc->sc_sensors[i].type = ADC7417_TEMP_SENSOR;
+ else
+ sc->sc_sensors[i].type = ADC7417_ADC_SENSOR;
+ prev_len = strlen(type + len) + 1;
+ len += prev_len;
+ i++;
+ }
+
+ /* Fill the sensor id property. Taken from OF. */
+ prop_len = OF_getprop(child, "hwsensor-id", id, sizeof(id));
+ for (j = 0; j < i; j++)
+ sc->sc_sensors[j].id = id[j];
+
+ /* Fill the sensor zone property. Taken from OF. */
+ prop_len = OF_getprop(child, "hwsensor-zone", id, sizeof(id));
+ for (j = 0; j < i; j++)
+ sc->sc_sensors[j].therm.zone = id[j];
+
+ /* Finish setting up sensor properties */
+ for (j = 0; j < i; j++) {
+ sc->sc_sensors[j].dev = dev;
+
+ /* HACK: Apple wired a random diode to the ADC line */
+ if (strstr(sc->sc_sensors[j].therm.name, "DIODE TEMP")
+ != NULL) {
+ sc->sc_sensors[j].type = ADC7417_TEMP_SENSOR;
+ sc->sc_sensors[j].therm.read =
+ (int (*)(struct pmac_therm *))(ad7417_diode_read);
+ } else {
+ sc->sc_sensors[j].therm.read =
+ (int (*)(struct pmac_therm *))(ad7417_sensor_read);
+ }
+
+ if (sc->sc_sensors[j].type != ADC7417_TEMP_SENSOR)
+ continue;
+
+ /* Make up some ranges */
+ sc->sc_sensors[j].therm.target_temp = 500 + 2732;
+ sc->sc_sensors[j].therm.max_temp = 900 + 2732;
+
+ pmac_thermal_sensor_register(&sc->sc_sensors[j].therm);
+ }
+
+ return (i);
+}
+
+static int
+ad7417_attach(device_t dev)
+{
+ struct ad7417_softc *sc;
+ struct sysctl_oid *oid, *sensroot_oid;
+ struct sysctl_ctx_list *ctx;
+ char sysctl_name[32];
+ int i, j;
+ const char *unit;
+ const char *desc;
+
+ sc = device_get_softc(dev);
+
+ sc->sc_nsensors = 0;
+
+ /* Count the actual number of sensors. */
+ sc->sc_nsensors = ad7417_fill_sensor_prop(dev);
+
+ device_printf(dev, "%d sensors detected.\n", sc->sc_nsensors);
+
+ if (sc->sc_nsensors == 0)
+ device_printf(dev, "WARNING: No AD7417 sensors detected!\n");
+
+ sc->sc_sensors = malloc (sc->sc_nsensors * sizeof(struct ad7417_sensor),
+ M_AD7417, M_WAITOK | M_ZERO);
+
+ ctx = device_get_sysctl_ctx(dev);
+ sensroot_oid = SYSCTL_ADD_NODE(ctx,
+ SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "sensor",
+ CTLFLAG_RD, 0, "AD7417 Sensor Information");
+
+ /* Now we can fill the properties into the allocated struct. */
+ sc->sc_nsensors = ad7417_fill_sensor_prop(dev);
+
+ /* Add sysctls for the sensors. */
+ for (i = 0; i < sc->sc_nsensors; i++) {
+ for (j = 0; j < strlen(sc->sc_sensors[i].therm.name); j++) {
+ sysctl_name[j] =
+ tolower(sc->sc_sensors[i].therm.name[j]);
+ if (isspace(sysctl_name[j]))
+ sysctl_name[j] = '_';
+ }
+ sysctl_name[j] = 0;
+
+ oid = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(sensroot_oid),
+ OID_AUTO,
+ sysctl_name, CTLFLAG_RD, 0,
+ "Sensor Information");
+
+ if (sc->sc_sensors[i].type == ADC7417_TEMP_SENSOR) {
+ unit = "temp";
+ desc = "Sensor temp in C";
+ } else {
+ unit = "volt";
+ desc = "Sensor Volt in V";
+ }
+ /* I use i to pass the sensor id. */
+ SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ unit, CTLTYPE_INT | CTLFLAG_RD, dev,
+ i, ad7417_sensor_sysctl,
+ sc->sc_sensors[i].type == ADC7417_TEMP_SENSOR ?
+ "IK" : "I", desc);
+ }
+ /* Dump sensor location, ID & type. */
+ if (bootverbose) {
+ device_printf(dev, "Sensors\n");
+ for (i = 0; i < sc->sc_nsensors; i++) {
+ device_printf(dev, "Location: %s ID: %d type: %d\n",
+ sc->sc_sensors[i].therm.name,
+ sc->sc_sensors[i].id,
+ sc->sc_sensors[i].type);
+ }
+ }
+
+ return (0);
+}
+
+static int
+ad7417_get_temp(device_t dev, uint32_t addr, int *temp)
+{
+ uint16_t buf[2];
+ uint16_t read;
+
+ ad7417_read_2(dev, addr, AD7417_TEMP, buf);
+ read = *((int16_t*)buf);
+
+ /* The ADC is 10 bit, the resolution is 0.25 C.
+ The temperature is in tenth kelvin.
+ */
+ *temp = (((int16_t)(read & 0xffc0)) >> 6) * 25 / 10;
+ return (0);
+}
+
+static int
+ad7417_get_adc(device_t dev, uint32_t addr, unsigned int *value,
+ uint8_t chan)
+{
+ uint8_t cfg1, tmp;
+ uint16_t read, buf[2];
+
+ ad7417_read_1(dev, addr, AD7417_CONFIG, &cfg1);
+
+ tmp = chan << 5;
+
+ cfg1 = (cfg1 & ~AD7417_CONFMASK) | (tmp & AD7417_CONFMASK);
+
+ ad7417_write(dev, addr, AD7417_CONFIG, &cfg1, 1);
+
+ ad7417_read_2(dev, addr, AD7417_ADC, buf);
+
+ read = *((uint16_t*)buf);
+
+ *value = ((uint32_t)read) >> 6;
+
+ return (0);
+}
+
+static int
+ad7417_diode_read(struct ad7417_sensor *sens)
+{
+ static int eeprom_read = 0;
+ static cell_t eeprom[2][40];
+ phandle_t eeprom_node;
+ int rawval, diode_slope, diode_offset;
+ int temp;
+
+ if (!eeprom_read) {
+ eeprom_node = OF_finddevice("/u3/i2c/cpuid@a0");
+ OF_getprop(eeprom_node, "cpuid", eeprom[0], sizeof(eeprom[0]));
+ eeprom_node = OF_finddevice("/u3/i2c/cpuid@a2");
+ OF_getprop(eeprom_node, "cpuid", eeprom[1], sizeof(eeprom[1]));
+ eeprom_read = 1;
+ }
+
+ rawval = ad7417_adc_read(sens);
+ if (strstr(sens->therm.name, "CPU B") != NULL) {
+ diode_slope = eeprom[1][0x11] >> 16;
+ diode_offset = (int16_t)(eeprom[1][0x11] & 0xffff) << 12;
+ } else {
+ diode_slope = eeprom[0][0x11] >> 16;
+ diode_offset = (int16_t)(eeprom[0][0x11] & 0xffff) << 12;
+ }
+
+ temp = (rawval*diode_slope + diode_offset) >> 2;
+ temp = (10*(temp >> 16)) + ((10*(temp & 0xffff)) >> 16);
+
+ return (temp + FCU_ZERO_C_TO_K);
+}
+
+static int
+ad7417_adc_read(struct ad7417_sensor *sens)
+{
+ struct ad7417_softc *sc;
+ uint8_t chan;
+ int temp;
+
+ sc = device_get_softc(sens->dev);
+
+ switch (sens->id) {
+ case 11:
+ case 16:
+ chan = 1;
+ break;
+ case 12:
+ case 17:
+ chan = 2;
+ break;
+ case 13:
+ case 18:
+ chan = 3;
+ break;
+ case 14:
+ case 19:
+ chan = 4;
+ break;
+ default:
+ chan = 1;
+ }
+
+ ad7417_get_adc(sc->sc_dev, sc->sc_addr, &temp, chan);
+
+ return (temp);
+}
+
+
+static int
+ad7417_sensor_read(struct ad7417_sensor *sens)
+{
+ struct ad7417_softc *sc;
+ int temp;
+
+ sc = device_get_softc(sens->dev);
+
+ /* Init the ADC. */
+ ad7417_init_adc(sc->sc_dev, sc->sc_addr);
+
+ if (sens->type == ADC7417_TEMP_SENSOR) {
+ ad7417_get_temp(sc->sc_dev, sc->sc_addr, &temp);
+ temp += FCU_ZERO_C_TO_K;
+ } else {
+ temp = ad7417_adc_read(sens);
+ }
+ return (temp);
+}
+
+static int
+ad7417_sensor_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ device_t dev;
+ struct ad7417_softc *sc;
+ struct ad7417_sensor *sens;
+ int value = 0;
+ int error;
+
+ dev = arg1;
+ sc = device_get_softc(dev);
+ sens = &sc->sc_sensors[arg2];
+
+ value = sens->therm.read(&sens->therm);
+ if (value < 0)
+ return (ENXIO);
+
+ error = sysctl_handle_int(oidp, &value, 0, req);
+
+ return (error);
+}
diff --git a/sys/dev/iicbus/ds1775.c b/sys/dev/iicbus/ds1775.c
index 0edc074..23ad6f4 100644
--- a/sys/dev/iicbus/ds1775.c
+++ b/sys/dev/iicbus/ds1775.c
@@ -49,33 +49,29 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
-
-#define FCU_ZERO_C_TO_K 2732
+#include <powerpc/powermac/powermac_thermal.h>
/* Drivebay sensor: LM75/DS1775. */
#define DS1775_TEMP 0x0
-struct ds1775_sensor {
- char location[32];
-};
-
/* Regular bus attachment functions */
static int ds1775_probe(device_t);
static int ds1775_attach(device_t);
+struct ds1775_softc {
+ struct pmac_therm sc_sensor;
+ device_t sc_dev;
+ struct intr_config_hook enum_hook;
+ uint32_t sc_addr;
+};
+
/* Utility functions */
+static int ds1775_sensor_read(struct ds1775_softc *sc);
static int ds1775_sensor_sysctl(SYSCTL_HANDLER_ARGS);
static void ds1775_start(void *xdev);
static int ds1775_read_2(device_t dev, uint32_t addr, uint8_t reg,
uint16_t *data);
-struct ds1775_softc {
- device_t sc_dev;
- struct intr_config_hook enum_hook;
- uint32_t sc_addr;
- struct ds1775_sensor *sc_sensors;
-
-};
static device_method_t ds1775_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, ds1775_probe),
@@ -92,26 +88,33 @@ static driver_t ds1775_driver = {
static devclass_t ds1775_devclass;
DRIVER_MODULE(ds1755, iicbus, ds1775_driver, ds1775_devclass, 0, 0);
-MALLOC_DEFINE(M_DS1775, "ds1775", "Temp-Monitor DS1775");
static int
ds1775_read_2(device_t dev, uint32_t addr, uint8_t reg, uint16_t *data)
{
uint8_t buf[4];
+ int err, try = 0;
struct iic_msg msg[2] = {
{ addr, IIC_M_WR | IIC_M_NOSTOP, 1, &reg },
{ addr, IIC_M_RD, 2, buf },
};
- if (iicbus_transfer(dev, msg, 2) != 0) {
- device_printf(dev, "iicbus read failed\n");
- return (EIO);
+ for (;;)
+ {
+ err = iicbus_transfer(dev, msg, 2);
+ if (err != 0)
+ goto retry;
+
+ *data = *((uint16_t*)buf);
+ return (0);
+ retry:
+ if (++try > 5) {
+ device_printf(dev, "iicbus read failed\n");
+ return (-1);
+ }
+ pause("ds1775_read_2", hz);
}
-
- *data = *((uint16_t*)buf);
-
- return (0);
}
static int
@@ -169,7 +172,6 @@ ds1775_start(void *xdev)
{
phandle_t child;
struct ds1775_softc *sc;
- struct ds1775_sensor *sens;
struct sysctl_oid *sensroot_oid;
struct sysctl_ctx_list *ctx;
ssize_t plen;
@@ -183,30 +185,43 @@ ds1775_start(void *xdev)
child = ofw_bus_get_node(dev);
- sc->sc_sensors = malloc (sizeof(struct ds1775_sensor),
- M_DS1775, M_WAITOK | M_ZERO);
-
- sens = sc->sc_sensors;
-
ctx = device_get_sysctl_ctx(dev);
sensroot_oid = device_get_sysctl_tree(dev);
- plen = OF_getprop(child, "hwsensor-location", sens->location,
- sizeof(sens->location));
+ if (OF_getprop(child, "hwsensor-zone", &sc->sc_sensor.zone,
+ sizeof(int)) < 0)
+ sc->sc_sensor.zone = 0;
+
+ plen = OF_getprop(child, "hwsensor-location", sc->sc_sensor.name,
+ sizeof(sc->sc_sensor.name));
units = "C";
if (plen == -1) {
strcpy(sysctl_name, "sensor");
} else {
- for (i = 0; i < strlen(sens->location); i++) {
- sysctl_name[i] = tolower(sens->location[i]);
+ for (i = 0; i < strlen(sc->sc_sensor.name); i++) {
+ sysctl_name[i] = tolower(sc->sc_sensor.name[i]);
if (isspace(sysctl_name[i]))
sysctl_name[i] = '_';
}
sysctl_name[i] = 0;
}
- sprintf(sysctl_desc,"%s (%s)", sens->location, units);
+ /* Make up target temperatures. These are low, for the drive bay. */
+ if (sc->sc_sensor.zone == 0) {
+ sc->sc_sensor.target_temp = 500 + ZERO_C_TO_K;
+ sc->sc_sensor.max_temp = 600 + ZERO_C_TO_K;
+ }
+ else {
+ sc->sc_sensor.target_temp = 300 + ZERO_C_TO_K;
+ sc->sc_sensor.max_temp = 600 + ZERO_C_TO_K;
+ }
+
+ sc->sc_sensor.read =
+ (int (*)(struct pmac_therm *sc))(ds1775_sensor_read);
+ pmac_thermal_sensor_register(&sc->sc_sensor);
+
+ sprintf(sysctl_desc,"%s (%s)", sc->sc_sensor.name, units);
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(sensroot_oid), OID_AUTO,
sysctl_name,
CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev,
@@ -216,44 +231,38 @@ ds1775_start(void *xdev)
}
static int
-ds1775_sensor_read(device_t dev, struct ds1775_sensor *sens, int *temp)
+ds1775_sensor_read(struct ds1775_softc *sc)
{
- struct ds1775_softc *sc;
uint16_t buf[2];
uint16_t read;
+ int err;
- sc = device_get_softc(dev);
-
- ds1775_read_2(sc->sc_dev, sc->sc_addr, DS1775_TEMP, buf);
+ err = ds1775_read_2(sc->sc_dev, sc->sc_addr, DS1775_TEMP, buf);
+ if (err < 0)
+ return (-1);
read = *((int16_t *)buf);
/* The default mode of the ADC is 9 bit, the resolution is 0.5 C per
bit. The temperature is in tenth kelvin.
*/
- *temp = ((int16_t)(read) >> 7) * 5;
-
- return (0);
+ return (((int16_t)(read) >> 7) * 5 + ZERO_C_TO_K);
}
+
static int
ds1775_sensor_sysctl(SYSCTL_HANDLER_ARGS)
{
device_t dev;
struct ds1775_softc *sc;
- struct ds1775_sensor *sens;
- int value;
int error;
unsigned int temp;
dev = arg1;
sc = device_get_softc(dev);
- sens = &sc->sc_sensors[arg2];
- error = ds1775_sensor_read(dev, sens, &value);
- if (error != 0)
- return (error);
-
- temp = value + FCU_ZERO_C_TO_K;
+ temp = ds1775_sensor_read(sc);
+ if (temp < 0)
+ return (EIO);
error = sysctl_handle_int(oidp, &temp, 0, req);
diff --git a/sys/dev/iicbus/max6690.c b/sys/dev/iicbus/max6690.c
index cbfdc26..83f3b50 100644
--- a/sys/dev/iicbus/max6690.c
+++ b/sys/dev/iicbus/max6690.c
@@ -49,20 +49,22 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
-
-#define FCU_ZERO_C_TO_K 2732
+#include <powerpc/powermac/powermac_thermal.h>
/* Inlet, Backside, U3 Heatsink sensor: MAX6690. */
#define MAX6690_INT_TEMP 0x0
#define MAX6690_EXT_TEMP 0x1
+#define MAX6690_RSL_STATUS 0x2
#define MAX6690_EEXT_TEMP 0x10
#define MAX6690_IEXT_TEMP 0x11
#define MAX6690_TEMP_MASK 0xe0
struct max6690_sensor {
+ struct pmac_therm therm;
+ device_t dev;
+
int id;
- char location[32];
};
/* Regular bus attachment functions */
@@ -70,10 +72,11 @@ static int max6690_probe(device_t);
static int max6690_attach(device_t);
/* Utility functions */
+static int max6690_sensor_read(struct max6690_sensor *sens);
static int max6690_sensor_sysctl(SYSCTL_HANDLER_ARGS);
static void max6690_start(void *xdev);
-static int max6690_read_1(device_t dev, uint32_t addr, uint8_t reg,
- uint8_t *data);
+static int max6690_read(device_t dev, uint32_t addr, uint8_t reg,
+ uint8_t *data);
struct max6690_softc {
device_t sc_dev;
@@ -101,23 +104,43 @@ DRIVER_MODULE(max6690, iicbus, max6690_driver, max6690_devclass, 0, 0);
MALLOC_DEFINE(M_MAX6690, "max6690", "Temp-Monitor MAX6690");
static int
-max6690_read_1(device_t dev, uint32_t addr, uint8_t reg, uint8_t *data)
+max6690_read(device_t dev, uint32_t addr, uint8_t reg, uint8_t *data)
{
uint8_t buf[4];
-
- struct iic_msg msg[2] = {
+ uint8_t busy[1], rsl;
+ int err, try = 0;
+
+ /* Busy register RSL. */
+ rsl = MAX6690_RSL_STATUS;
+ /* first read the status register, 0x2. If busy, retry. */
+ struct iic_msg msg[4] = {
+ { addr, IIC_M_WR | IIC_M_NOSTOP, 1, &rsl },
+ { addr, IIC_M_RD, 1, busy },
{ addr, IIC_M_WR | IIC_M_NOSTOP, 1, &reg },
{ addr, IIC_M_RD, 1, buf },
};
- if (iicbus_transfer(dev, msg, 2) != 0) {
- device_printf(dev, "iicbus read failed\n");
- return (EIO);
+ for (;;)
+ {
+ err = iicbus_transfer(dev, msg, 4);
+ if (err != 0)
+ goto retry;
+ if (busy[0] & 0x80)
+ goto retry;
+ /* Check for invalid value and retry. */
+ if (buf[0] == 0xff)
+ goto retry;
+
+ *data = *((uint8_t*)buf);
+ return (0);
+
+ retry:
+ if (++try > 5) {
+ device_printf(dev, "iicbus read failed\n");
+ return (-1);
+ }
+ pause("max6690_read", hz);
}
-
- *data = *((uint8_t*)buf);
-
- return (0);
}
static int
@@ -167,7 +190,7 @@ max6690_fill_sensor_prop(device_t dev)
sizeof(location));
while (len < prop_len) {
if (sc->sc_sensors != NULL)
- strcpy(sc->sc_sensors[i].location, location + len);
+ strcpy(sc->sc_sensors[i].therm.name, location + len);
prev_len = strlen(location + len) + 1;
len += prev_len;
i++;
@@ -180,6 +203,22 @@ max6690_fill_sensor_prop(device_t dev)
for (j = 0; j < i; j++)
sc->sc_sensors[j].id = (id[j] & 0xf);
+ /* Fill the sensor zone property. */
+ prop_len = OF_getprop(child, "hwsensor-zone", id, sizeof(id));
+ for (j = 0; j < i; j++)
+ sc->sc_sensors[j].therm.zone = id[j];
+
+ /* Set up remaining sensor properties */
+ for (j = 0; j < i; j++) {
+ sc->sc_sensors[j].dev = dev;
+
+ sc->sc_sensors[j].therm.target_temp = 400 + ZERO_C_TO_K;
+ sc->sc_sensors[j].therm.max_temp = 800 + ZERO_C_TO_K;
+
+ sc->sc_sensors[j].therm.read =
+ (int (*)(struct pmac_therm *))(max6690_sensor_read);
+ }
+
return (i);
}
static int
@@ -240,10 +279,15 @@ max6690_start(void *xdev)
/* Now we can fill the properties into the allocated struct. */
sc->sc_nsensors = max6690_fill_sensor_prop(dev);
+ /* Register with powermac_thermal */
+ for (i = 0; i < sc->sc_nsensors; i++)
+ pmac_thermal_sensor_register(&sc->sc_sensors[i].therm);
+
/* Add sysctls for the sensors. */
for (i = 0; i < sc->sc_nsensors; i++) {
- for (j = 0; j < strlen(sc->sc_sensors[i].location); j++) {
- sysctl_name[j] = tolower(sc->sc_sensors[i].location[j]);
+ for (j = 0; j < strlen(sc->sc_sensors[i].therm.name); j++) {
+ sysctl_name[j] =
+ tolower(sc->sc_sensors[i].therm.name[j]);
if (isspace(sysctl_name[j]))
sysctl_name[j] = '_';
}
@@ -265,7 +309,7 @@ max6690_start(void *xdev)
device_printf(dev, "Sensors\n");
for (i = 0; i < sc->sc_nsensors; i++) {
device_printf(dev, "Location : %s ID: %d\n",
- sc->sc_sensors[i].location,
+ sc->sc_sensors[i].therm.name,
sc->sc_sensors[i].id);
}
}
@@ -274,16 +318,18 @@ max6690_start(void *xdev)
}
static int
-max6690_sensor_read(device_t dev, struct max6690_sensor *sens, int *temp)
+max6690_sensor_read(struct max6690_sensor *sens)
{
uint8_t reg_int = 0, reg_ext = 0;
- uint8_t integer;
- uint8_t fraction;
+ uint8_t integer = 0;
+ uint8_t fraction = 0;
+ int err, temp;
+
struct max6690_softc *sc;
- sc = device_get_softc(dev);
+ sc = device_get_softc(sens->dev);
- /* The internal sensor id's are even, the external ar odd. */
+ /* The internal sensor id's are even, the external are odd. */
if ((sens->id % 2) == 0) {
reg_int = MAX6690_INT_TEMP;
reg_ext = MAX6690_IEXT_TEMP;
@@ -292,18 +338,20 @@ max6690_sensor_read(device_t dev, struct max6690_sensor *sens, int *temp)
reg_ext = MAX6690_EEXT_TEMP;
}
- max6690_read_1(sc->sc_dev, sc->sc_addr, reg_int, &integer);
+ err = max6690_read(sc->sc_dev, sc->sc_addr, reg_int, &integer);
+ err = max6690_read(sc->sc_dev, sc->sc_addr, reg_ext, &fraction);
- max6690_read_1(sc->sc_dev, sc->sc_addr, reg_ext, &fraction);
+ if (err < 0)
+ return (-1);
fraction &= MAX6690_TEMP_MASK;
/* The temperature is in tenth kelvin, the fractional part resolution
is 0.125.
*/
- *temp = (integer * 10) + (fraction >> 5) * 10 / 8;
+ temp = (integer * 10) + (fraction >> 5) * 10 / 8;
- return (0);
+ return (temp + ZERO_C_TO_K);
}
static int
@@ -312,7 +360,6 @@ max6690_sensor_sysctl(SYSCTL_HANDLER_ARGS)
device_t dev;
struct max6690_softc *sc;
struct max6690_sensor *sens;
- int value = 0;
int error;
unsigned int temp;
@@ -320,11 +367,9 @@ max6690_sensor_sysctl(SYSCTL_HANDLER_ARGS)
sc = device_get_softc(dev);
sens = &sc->sc_sensors[arg2];
- error = max6690_sensor_read(dev, sens, &value);
- if (error != 0)
- return (error);
-
- temp = value + FCU_ZERO_C_TO_K;
+ temp = max6690_sensor_read(sens);
+ if (temp < 0)
+ return (EIO);
error = sysctl_handle_int(oidp, &temp, 0, req);
diff --git a/sys/dev/ipw/if_ipw.c b/sys/dev/ipw/if_ipw.c
index db76bfa..7560430 100644
--- a/sys/dev/ipw/if_ipw.c
+++ b/sys/dev/ipw/if_ipw.c
@@ -199,6 +199,8 @@ static devclass_t ipw_devclass;
DRIVER_MODULE(ipw, pci, ipw_driver, ipw_devclass, 0, 0);
+MODULE_VERSION(ipw, 1);
+
static int
ipw_probe(device_t dev)
{
diff --git a/sys/dev/iwi/if_iwi.c b/sys/dev/iwi/if_iwi.c
index dc81309..73b861c 100644
--- a/sys/dev/iwi/if_iwi.c
+++ b/sys/dev/iwi/if_iwi.c
@@ -232,6 +232,8 @@ static devclass_t iwi_devclass;
DRIVER_MODULE(iwi, pci, iwi_driver, iwi_devclass, 0, 0);
+MODULE_VERSION(iwi, 1);
+
static __inline uint8_t
MEM_READ_1(struct iwi_softc *sc, uint32_t addr)
{
diff --git a/sys/dev/iwn/if_iwn.c b/sys/dev/iwn/if_iwn.c
index 29e391f..f905311 100644
--- a/sys/dev/iwn/if_iwn.c
+++ b/sys/dev/iwn/if_iwn.c
@@ -401,6 +401,8 @@ static devclass_t iwn_devclass;
DRIVER_MODULE(iwn, pci, iwn_driver, iwn_devclass, 0, 0);
+MODULE_VERSION(iwn, 1);
+
MODULE_DEPEND(iwn, firmware, 1, 1, 1);
MODULE_DEPEND(iwn, pci, 1, 1, 1);
MODULE_DEPEND(iwn, wlan, 1, 1, 1);
@@ -565,6 +567,7 @@ iwn_attach(device_t dev)
ic->ic_caps =
IEEE80211_C_STA /* station mode supported */
| IEEE80211_C_MONITOR /* monitor mode supported */
+ | IEEE80211_C_BGSCAN /* background scanning */
| IEEE80211_C_TXPMGT /* tx power management */
| IEEE80211_C_SHSLOT /* short slot time supported */
| IEEE80211_C_WPA
@@ -574,8 +577,6 @@ iwn_attach(device_t dev)
#endif
| IEEE80211_C_WME /* WME */
;
- if (sc->hw_type != IWN_HW_REV_TYPE_4965)
- ic->ic_caps |= IEEE80211_C_BGSCAN; /* background scanning */
/* Read MAC address, channels, etc from EEPROM. */
if ((error = iwn_read_eeprom(sc, macaddr)) != 0) {
@@ -605,9 +606,9 @@ iwn_attach(device_t dev)
ic->ic_htcaps =
IEEE80211_HTCAP_SMPS_OFF /* SMPS mode disabled */
| IEEE80211_HTCAP_SHORTGI20 /* short GI in 20MHz */
-#ifdef notyet
| IEEE80211_HTCAP_CHWIDTH40 /* 40MHz channel width*/
| IEEE80211_HTCAP_SHORTGI40 /* short GI in 40MHz */
+#ifdef notyet
| IEEE80211_HTCAP_GREENFIELD
#if IWN_RBUF_SIZE == 8192
| IEEE80211_HTCAP_MAXAMSDU_7935 /* max A-MSDU length */
@@ -3313,7 +3314,8 @@ iwn_tx_data(struct iwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni)
}
ac = M_WME_GETAC(m);
- if (IEEE80211_AMPDU_RUNNING(&ni->ni_tx_ampdu[ac])) {
+ if (IEEE80211_QOS_HAS_SEQ(wh) &&
+ IEEE80211_AMPDU_RUNNING(&ni->ni_tx_ampdu[ac])) {
struct ieee80211_tx_ampdu *tap = &ni->ni_tx_ampdu[ac];
ring = &sc->txq[*(int *)tap->txa_private];
@@ -5159,7 +5161,7 @@ iwn_scan(struct iwn_softc *sc)
if (IEEE80211_IS_CHAN_A(ic->ic_curchan) &&
sc->hw_type == IWN_HW_REV_TYPE_4965) {
/* Ant A must be avoided in 5GHz because of an HW bug. */
- rxchain |= IWN_RXCHAIN_FORCE_SEL(IWN_ANT_BC);
+ rxchain |= IWN_RXCHAIN_FORCE_SEL(IWN_ANT_B);
} else /* Use all available RX antennas. */
rxchain |= IWN_RXCHAIN_FORCE_SEL(sc->rxchainmask);
hdr->rxchain = htole16(rxchain);
@@ -5170,14 +5172,19 @@ iwn_scan(struct iwn_softc *sc)
tx->id = sc->broadcast_id;
tx->lifetime = htole32(IWN_LIFETIME_INFINITE);
- if (IEEE80211_IS_CHAN_A(ic->ic_curchan)) {
+ if (IEEE80211_IS_CHAN_5GHZ(ic->ic_curchan)) {
/* Send probe requests at 6Mbps. */
tx->rate = htole32(0xd);
rs = &ic->ic_sup_rates[IEEE80211_MODE_11A];
} else {
hdr->flags = htole32(IWN_RXON_24GHZ | IWN_RXON_AUTO);
- /* Send probe requests at 1Mbps. */
- tx->rate = htole32(10 | IWN_RFLAG_CCK);
+ if (sc->hw_type == IWN_HW_REV_TYPE_4965 &&
+ sc->rxon.associd && sc->rxon.chan > 14)
+ tx->rate = htole32(0xd);
+ else {
+ /* Send probe requests at 1Mbps. */
+ tx->rate = htole32(10 | IWN_RFLAG_CCK);
+ }
rs = &ic->ic_sup_rates[IEEE80211_MODE_11G];
}
/* Use the first valid TX antenna. */
diff --git a/sys/dev/ixgbe/LICENSE b/sys/dev/ixgbe/LICENSE
index 0cf44c8..0d4f1db 100644
--- a/sys/dev/ixgbe/LICENSE
+++ b/sys/dev/ixgbe/LICENSE
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2011, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/ixgbe/README b/sys/dev/ixgbe/README
index 0b27deb..5e4921f 100644
--- a/sys/dev/ixgbe/README
+++ b/sys/dev/ixgbe/README
@@ -1,8 +1,8 @@
-FreeBSD Driver for 10 Gigabit PCI Express Server Adapters
-=============================================
+FreeBSD Driver for Intel(R) Ethernet 10 Gigabit PCI Express Server Adapters
+============================================================================
/*$FreeBSD$*/
-May 14, 2008
+November 12, 2010
Contents
@@ -11,15 +11,15 @@ Contents
- Overview
- Supported Adapters
- Building and Installation
-- Additional Configurations
+- Additional Configurations and Tuning
- Known Limitations
Overview
========
-This file describes the FreeBSD* driver for the 10 Gigabit PCIE Family of
-Adapters. Drivers has been developed for use with FreeBSD 7 or later.
+This file describes the FreeBSD* driver for the Intel(R) Ethernet 10 Gigabit
+Family of Adapters. Driver has been developed for use with FreeBSD 7.2 or later.
For questions related to hardware requirements, refer to the documentation
supplied with your Intel 10GbE adapter. All hardware requirements listed
@@ -29,100 +29,98 @@ apply to use with FreeBSD.
Supported Adapters
==================
-The following Intel network adapters are compatible with the drivers in this
-release:
-
-Controller Adapter Name Physical Layer
----------- ------------ --------------
-82598EB Intel(R) 10 Gigabit XF SR/AF 10G Base -LR (850 nm optical fiber)
- Dual Port Server Adapter 10G Base -SR (1310 nm optical fiber)
-82598EB Intel(R) 10 Gigabit XF SR/LR
- Server Adapter
- Intel(R) 82598EB 10 Gigabit AF
- Network Connection
- Intel(R) 82598EB 10 Gigabit AT
- CX4 Network Connection
+The driver in this release is compatible with 82598 and 82599-based Intel
+Network Connections.
+SFP+ Devices with Pluggable Optics
+----------------------------------
-Building and Installation
-=========================
+82599-BASED ADAPTERS
-NOTE: You must have kernel sources installed in order to compile the driver
- module.
-
- In the instructions below, x.x.x is the driver version as indicated in
- the name of the driver tar.
-
-1. Move the base driver tar file to the directory of your choice. For
- example, use /home/username/ixgbe or /usr/local/src/ixgbe.
-
-2. Untar/unzip the archive:
- tar xfz ixgbe-x.x.x.tar.gz
-
-3. To install man page:
- cd ixgbe-x.x.x
- gzip -c ixgbe.4 > /usr/share/man/man4/ixgbee.4.gz
-
-4. To load the driver onto a running system:
- cd ixgbe-x.x.x/src
- make load
-
-5. To assign an IP address to the interface, enter the following:
- ifconfig ix<interface_num> <IP_address>
-
-6. Verify that the interface works. Enter the following, where <IP_address>
- is the IP address for another machine on the same subnet as the interface
- that is being tested:
- ping <IP_address>
-
-7. If you want the driver to load automatically when the system is booted:
-
- cd ixgbe-x.x.x/src
- make
- make install
-
- Edit /boot/loader.conf, and add the following line:
- ixgbe_load="YES"
-
- OR
-
- compile the driver into the kernel (see item 8).
-
-
- Edit /etc/rc.conf, and create the appropriate ifconfig_ixgbe<interface_num>
- entry:
-
- ifconfig_ix<interface_num>="<ifconfig_settings>"
-
- Example usage:
-
- ifconfig_ix0="inet 192.168.10.1 netmask 255.255.255.0"
-
- NOTE: For assistance, see the ifconfig man page.
-
-8. If you want to compile the driver into the kernel, enter:
-
- FreeBSD 7 or later:
-
- cd ixgbe-x.x.x/src
-
- cp *.[ch] /usr/src/sys/dev/ixgbe
-
- cp Makefile.kernel /usr/src/sys/modules/ixgbe/Makefile
-
- Edit the kernel configuration file (i.e., GENERIC or MYKERNEL) in
- /usr/src/sys/i386/conf (replace "i386" with the appropriate system
- architecture if necessary), and ensure the following line is present:
-
- device ixgbe
-
- Compile and install the kernel. The system must be reboot for the kernel
- updates to take affect. For additional information on compiling the kernel,
- consult the FreeBSD operating system documentation.
+NOTE: If your 82599-based Intel(R) Ethernet Network Adapter came with Intel
+optics, or is an Intel(R) Ethernet Server Adapter X520-2, then it only supports
+Intel optics and/or the direct attach cables listed below.
+When 82599-based SFP+ devices are connected back to back, they should be set to
+the same Speed setting via Ethtool. Results may vary if you mix speed settings.
+
+Supplier Type Part Numbers
+
+SR Modules
+Intel DUAL RATE 1G/10G SFP+ SR (bailed) FTLX8571D3BCV-IT
+Intel DUAL RATE 1G/10G SFP+ SR (bailed) AFBR-703SDZ-IN2
+Intel DUAL RATE 1G/10G SFP+ SR (bailed) AFBR-703SDDZ-IN1
+LR Modules
+Intel DUAL RATE 1G/10G SFP+ LR (bailed) FTLX1471D3BCV-IT
+Intel DUAL RATE 1G/10G SFP+ LR (bailed) AFCT-701SDZ-IN2
+Intel DUAL RATE 1G/10G SFP+ LR (bailed) AFCT-701SDDZ-IN1
+
+The following is a list of 3rd party SFP+ modules and direct attach cables that
+have received some testing. Not all modules are applicable to all devices.
+
+Supplier Type Part Numbers
+
+Finisar SFP+ SR bailed, 10g single rate FTLX8571D3BCL
+Avago SFP+ SR bailed, 10g single rate AFBR-700SDZ
+Finisar SFP+ LR bailed, 10g single rate FTLX8571D3BCV-IT
+
+Finisar DUAL RATE 1G/10G SFP+ SR (No Bail) FTLX8571D3QCV-IT
+Avago DUAL RATE 1G/10G SFP+ SR (No Bail) AFBR-703SDZ-IN1
+Finisar DUAL RATE 1G/10G SFP+ LR (No Bail) FTLX1471D3QCV-IT
+Avago DUAL RATE 1G/10G SFP+ LR (No Bail) AFCT-701SDZ-IN1
+Finistar 1000BASE-T SFP FCLF8522P2BTL
+Avago 1000BASE-T SFP ABCU-5710RZ
+
+82599-based adapters support all passive and active limiting direct attach
+cables that comply with SFF-8431 v4.1 and SFF-8472 v10.4 specifications.
+
+Laser turns off for SFP+ when ifconfig down
+--------------------------------------------------------
+"ifconfig down" turns off the laser for 82599-based SFP+ fiber adapters.
+"ifconfig up" turns on the later.
+
+82598-BASED ADAPTERS
+
+NOTES for 82598-Based Adapters:
+- Intel(R) Ethernet Network Adapters that support removable optical modules
+ only support their original module type (i.e., the Intel(R) 10 Gigabit SR
+ Dual Port Express Module only supports SR optical modules). If you plug
+ in a different type of module, the driver will not load.
+- Hot Swapping/hot plugging optical modules is not supported.
+- Only single speed, 10 gigabit modules are supported.
+- LAN on Motherboard (LOMs) may support DA, SR, or LR modules. Other module
+ types are not supported. Please see your system documentation for details.
+
+The following is a list of 3rd party SFP+ modules and direct attach cables that have
+received some testing. Not all modules are applicable to all devices.
+
+Supplier Type Part Numbers
+
+Finisar SFP+ SR bailed, 10g single rate FTLX8571D3BCL
+Avago SFP+ SR bailed, 10g single rate AFBR-700SDZ
+Finisar SFP+ LR bailed, 10g single rate FTLX1471D3BCL
+
+82598-based adapters support all passive direct attach cables that comply
+with SFF-8431 v4.1 and SFF-8472 v10.4 specifications. Active direct attach
+cables are not supported.
+
+Third party optic modules and cables referred to above are listed only for the
+purpose of highlighting third party specifications and potential compatibility,
+and are not recommendations or endorsements or sponsorship of any third party's
+product by Intel. Intel is not endorsing or promoting products made by any
+third party and the third party reference is provided only to share information
+regarding certain optic modules and cables with the above specifications. There
+may be other manufacturers or suppliers, producing or supplying optic modules
+and cables with similar or matching descriptions. Customers must use their own
+discretion and diligence to purchase optic modules and cables from any third
+party of their choice. Customer are solely responsible for assessing the
+suitability of the product and/or devices and for the selection of the vendor
+for purchasing any product. INTEL ASSUMES NO LIABILITY WHATSOEVER, AND INTEL
+DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY, RELATING TO SALE AND/OR USE OF
+SUCH THIRD PARTY PRODUCTS OR SELECTION OF VENDOR BY CUSTOMERS.
Configuration and Tuning
-=========================
+========================
The driver supports Transmit/Receive Checksum Offload and Jumbo Frames on
all 10 Gigabit adapters.
@@ -143,7 +141,7 @@ all 10 Gigabit adapters.
The Jumbo Frames MTU range for Intel Adapters is 1500 to 16114. The default
MTU range is 1500. To modify the setting, enter the following:
- ifconfig ix <interface_num> <hostname or IP address> mtu 9000
+ ifconfig ix<interface_num> <hostname or IP address> mtu 9000
To confirm an interface's MTU value, use the ifconfig command. To confirm
the MTU used between two specific devices, use:
@@ -200,6 +198,8 @@ all 10 Gigabit adapters.
TSO
---
+ TSO is enabled by default.
+
To disable:
ifconfig <interface_num> -tso
@@ -209,23 +209,21 @@ all 10 Gigabit adapters.
ifconfig <interface_num> tso
LRO
- ___
+ ---
- Large Receive Offload is available in version 1.4.4, it is on
- by default. It can be toggled off and on by using:
- sysctl dev.ix.X.enable_lro=[0,1]
+ Large Receive Offload is available in the driver; it is on by default.
+ It can be disabled by using:
+ ifconfig <interface_num> -lro
+ To enable:
+ ifconfig <interface_num> lro
- NOTE: when changing this feature you MUST be sure the interface
- is reinitialized, it is easy to do this with ifconfig down/up.
- The LRO code will ultimately move into the kernel stack code,
- but for this first release it was included with the driver.
Important system configuration changes:
---------------------------------------
- When there is a choice run on a 64bit OS rather than 32, it makes
- a significant difference in improvement.
-
+ When there is a choice run on a 64bit OS rather than 32, it makes a
+ significant difference in improvement.
+
The default scheduler SCHED_4BSD is not smart about SMP locality issues.
Significant improvement can be achieved by switching to the ULE scheduler.
@@ -233,34 +231,79 @@ all 10 Gigabit adapters.
SCHED_ULE. Note that this is only advisable on FreeBSD 7, on 6.X there have
been stability problems with ULE.
- Change the file /etc/sysctl.conf, add the line:
+ The interface can generate high number of interrupts. To avoid running
+ into the limit set by the kernel, adjust hw.intr_storm_threshold
+ setting using sysctl:
- hw.intr_storm_threshold: 8000 (the default is 1000)
+ sysctl hw.intr_storm_threshold=9000 (the default is 1000)
+
+ For this change to take effect on boot, edit /etc/sysctl.conf and add the
+ line:
+ hw.intr_storm_threshold=9000
+
+ If you still see Interrupt Storm detected messages, increase the limit to a
+ higher number.
Best throughput results are seen with a large MTU; use 9000 if possible.
- The default number of descriptors is 256, increasing this to 1024 or even
- 2048 may improve performance.
+ The default number of descriptors is 1024, increasing this to 2K or even
+ 4K may improve performance in some workloads, but change carefully.
Known Limitations
=================
+
+For known hardware and troubleshooting issues, refer to the following website.
+
+ http://support.intel.com/support/go/network/adapter/home.htm
+
+Either select the link for your adapter or perform a search for the adapter
+number. The adapter's page lists many issues. For a complete list of hardware
+issues download your adapter's user guide and read the Release Notes.
+
+ UDP stress test with 10GbE driver
+ ---------------------------------
Under small packets UDP stress test with 10GbE driver, the FreeBSD system
will drop UDP packets due to the fullness of socket buffers. You may want
to change the driver's Flow Control variables to the minimum value for
controlling packet reception.
+ Attempting to configure larger MTUs with a large numbers of processors may
+ generate the error message "ix0:could not setup receive structures"
+ --------------------------------------------------------------------------
+ When using the ixgbe driver with RSS autoconfigured based on the number of
+ cores (the default setting) and that number is larger than 4, increase the
+ memory resources allocated for the mbuf pool as follows:
+
+ Add to the sysctl.conf file for the system:
+
+ kern.ipc.nmbclusters=262144
+ kern.ipc.nmbjumbop=262144
+
+ Lower than expected performance on dual port 10GbE devices
+ ----------------------------------------------------------
+ Some PCI-E x8 slots are actually configured as x4 slots. These slots have
+ insufficient bandwidth for full 10Gbe line rate with dual port 10GbE devices.
+ The driver can detect this situation and will write the following message in
+ the system log: "PCI-Express bandwidth available for this card is not
+ sufficient for optimal performance. For optimal performance a x8 PCI-Express
+ slot is required."
+
+ If this error occurs, moving your adapter to a true x8 slot will resolve the
+ issue.
+
+
Support
=======
For general information and support, go to the Intel support website at:
- http://support.intel.com
+ www.intel.com/support/
If an issue is identified with the released source code on the supported
kernel with a supported adapter, email the specific information related to
-the issue to freebsd@intel.com.
+the issue to freebsd@intel.com
diff --git a/sys/dev/ixgbe/ixgbe.c b/sys/dev/ixgbe/ixgbe.c
index f58adbe..a382a53 100644
--- a/sys/dev/ixgbe/ixgbe.c
+++ b/sys/dev/ixgbe/ixgbe.c
@@ -34,6 +34,7 @@
#ifdef HAVE_KERNEL_OPTION_HEADERS
#include "opt_inet.h"
+#include "opt_inet6.h"
#endif
#include "ixgbe.h"
@@ -46,7 +47,7 @@ int ixgbe_display_debug_stats = 0;
/*********************************************************************
* Driver version
*********************************************************************/
-char ixgbe_driver_version[] = "2.3.10";
+char ixgbe_driver_version[] = "2.3.11";
/*********************************************************************
* PCI Device ID Table
@@ -318,7 +319,7 @@ static int fdir_pballoc = 1;
* ixgbe_probe determines if the driver should be loaded on
* adapter based on PCI vendor/device id of the adapter.
*
- * return 0 on success, positive on failure
+ * return BUS_PROBE_DEFAULT on success, positive on failure
*********************************************************************/
static int
@@ -357,7 +358,7 @@ ixgbe_probe(device_t dev)
ixgbe_driver_version);
device_set_desc_copy(dev, adapter_name);
++ixgbe_total_ports;
- return (0);
+ return (BUS_PROBE_DEFAULT);
}
ent++;
}
@@ -385,6 +386,11 @@ ixgbe_attach(device_t dev)
INIT_DEBUGOUT("ixgbe_attach: begin");
+ if (resource_disabled("ixgbe", device_get_unit(dev))) {
+ device_printf(dev, "Disabled by device hint\n");
+ return (ENXIO);
+ }
+
/* Allocate, clear, and link in our adapter structure */
adapter = device_get_softc(dev);
adapter->dev = adapter->osdep.dev = dev;
@@ -862,8 +868,9 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
{
struct adapter *adapter = ifp->if_softc;
struct ifreq *ifr = (struct ifreq *) data;
-#ifdef INET
+#if defined(INET) || defined(INET6)
struct ifaddr *ifa = (struct ifaddr *)data;
+ bool avoid_reset = FALSE;
#endif
int error = 0;
@@ -871,26 +878,28 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
case SIOCSIFADDR:
#ifdef INET
- if (ifa->ifa_addr->sa_family == AF_INET) {
- /*
- * Since resetting hardware takes a very long time
- * and results in link renegotiation we only
- * initialize the hardware only when it is absolutely
- * required.
- */
+ if (ifa->ifa_addr->sa_family == AF_INET)
+ avoid_reset = TRUE;
+#endif
+#ifdef INET6
+ if (ifa->ifa_addr->sa_family == AF_INET6)
+ avoid_reset = TRUE;
+#endif
+#if defined(INET) || defined(INET6)
+ /*
+ ** Calling init results in link renegotiation,
+ ** so we avoid doing it when possible.
+ */
+ if (avoid_reset) {
ifp->if_flags |= IFF_UP;
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- IXGBE_CORE_LOCK(adapter);
- ixgbe_init_locked(adapter);
- IXGBE_CORE_UNLOCK(adapter);
- }
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
+ ixgbe_init(adapter);
if (!(ifp->if_flags & IFF_NOARP))
arp_ifinit(ifp, ifa);
} else
-#endif
error = ether_ioctl(ifp, command, data);
break;
-
+#endif
case SIOCSIFMTU:
IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)");
if (ifr->ifr_mtu > IXGBE_MAX_FRAME_SIZE - ETHER_HDR_LEN) {
@@ -951,6 +960,8 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
if (mask & IFCAP_VLAN_HWFILTER)
ifp->if_capenable ^= IFCAP_VLAN_HWFILTER;
+ if (mask & IFCAP_VLAN_HWTSO)
+ ifp->if_capenable ^= IFCAP_VLAN_HWTSO;
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
IXGBE_CORE_LOCK(adapter);
ixgbe_init_locked(adapter);
@@ -1338,7 +1349,7 @@ ixgbe_legacy_irq(void *arg)
/*********************************************************************
*
- * MSI Queue Interrupt Service routine
+ * MSIX Queue Interrupt Service routine
*
**********************************************************************/
void
@@ -1357,6 +1368,17 @@ ixgbe_msix_que(void *arg)
IXGBE_TX_LOCK(txr);
more_tx = ixgbe_txeof(txr);
+ /*
+ ** Make certain that if the stack
+ ** has anything queued the task gets
+ ** scheduled to handle it.
+ */
+#if __FreeBSD_version < 800000
+ if (!IFQ_DRV_IS_EMPTY(&adapter->ifp->if_snd))
+#else
+ if (!drbr_empty(adapter->ifp, txr->br))
+#endif
+ more_tx = 1;
IXGBE_TX_UNLOCK(txr);
/* Do AIM now? */
@@ -1570,7 +1592,7 @@ ixgbe_xmit(struct tx_ring *txr, struct mbuf **m_headp)
struct mbuf *m_head;
bus_dma_segment_t segs[adapter->num_segs];
bus_dmamap_t map;
- struct ixgbe_tx_buf *txbuf, *txbuf_mapped;
+ struct ixgbe_tx_buf *txbuf;
union ixgbe_adv_tx_desc *txd = NULL;
m_head = *m_headp;
@@ -1589,7 +1611,6 @@ ixgbe_xmit(struct tx_ring *txr, struct mbuf **m_headp)
*/
first = txr->next_avail_desc;
txbuf = &txr->tx_buffers[first];
- txbuf_mapped = txbuf;
map = txbuf->map;
/*
@@ -1708,6 +1729,8 @@ ixgbe_xmit(struct tx_ring *txr, struct mbuf **m_headp)
txr->next_avail_desc = i;
txbuf->m_head = m_head;
+ /* Swap the dma map between the first and last descriptor */
+ txr->tx_buffers[first].map = txbuf->map;
txbuf->map = map;
bus_dmamap_sync(txr->txtag, map, BUS_DMASYNC_PREWRITE);
@@ -2265,7 +2288,9 @@ ixgbe_setup_msix(struct adapter *adapter)
msi:
msgs = pci_msi_count(dev);
if (msgs == 1 && pci_alloc_msi(dev, &msgs) == 0)
- device_printf(adapter->dev,"Using MSI interrupt\n");
+ device_printf(adapter->dev,"Using an MSI interrupt\n");
+ else
+ device_printf(adapter->dev,"Using a Legacy interrupt\n");
return (msgs);
}
@@ -2412,19 +2437,21 @@ ixgbe_setup_interface(device_t dev, struct adapter *adapter)
ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_TSO4 | IFCAP_VLAN_HWCSUM;
- ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU;
ifp->if_capabilities |= IFCAP_JUMBO_MTU;
+ ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING
+ | IFCAP_VLAN_HWTSO
+ | IFCAP_VLAN_MTU;
ifp->if_capenable = ifp->if_capabilities;
/* Don't enable LRO by default */
ifp->if_capabilities |= IFCAP_LRO;
/*
- ** Dont turn this on by default, if vlans are
+ ** Don't turn this on by default, if vlans are
** created on another pseudo device (eg. lagg)
** then vlan events are not passed thru, breaking
** operation, but with HW FILTER off it works. If
- ** using vlans directly on the em driver you can
+ ** using vlans directly on the ixgbe driver you can
** enable this and get full hardware tag filtering.
*/
ifp->if_capabilities |= IFCAP_VLAN_HWFILTER;
@@ -5333,7 +5360,7 @@ ixgbe_add_rx_process_limit(struct adapter *adapter, const char *name,
static int
ixgbe_set_advertise(SYSCTL_HANDLER_ARGS)
{
- int error;
+ int error = 0;
struct adapter *adapter;
struct ixgbe_hw *hw;
ixgbe_link_speed speed, last;
diff --git a/sys/dev/ixgbe/ixv.c b/sys/dev/ixgbe/ixv.c
index f9f910a..e52a527 100644
--- a/sys/dev/ixgbe/ixv.c
+++ b/sys/dev/ixgbe/ixv.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2010, Intel Corporation
+ Copyright (c) 2001-2011, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -33,7 +33,8 @@
/*$FreeBSD$*/
#ifdef HAVE_KERNEL_OPTION_HEADERS
-#include "opt_device_polling.h"
+#include "opt_inet.h"
+#include "opt_inet6.h"
#endif
#include "ixv.h"
@@ -41,7 +42,7 @@
/*********************************************************************
* Driver version
*********************************************************************/
-char ixv_driver_version[] = "1.0.0";
+char ixv_driver_version[] = "1.0.1";
/*********************************************************************
* PCI Device ID Table
@@ -234,7 +235,7 @@ static u32 ixv_shadow_vfta[VFTA_SIZE];
* ixv_probe determines if the driver should be loaded on
* adapter based on PCI vendor/device id of the adapter.
*
- * return 0 on success, positive on failure
+ * return BUS_PROBE_DEFAULT on success, positive on failure
*********************************************************************/
static int
@@ -271,7 +272,7 @@ ixv_probe(device_t dev)
ixv_strings[ent->index],
ixv_driver_version);
device_set_desc_copy(dev, adapter_name);
- return (0);
+ return (BUS_PROBE_DEFAULT);
}
ent++;
}
@@ -297,6 +298,11 @@ ixv_attach(device_t dev)
INIT_DEBUGOUT("ixv_attach: begin");
+ if (resource_disabled("ixgbe", device_get_unit(dev))) {
+ device_printf(dev, "Disabled by device hint\n");
+ return (ENXIO);
+ }
+
/* Allocate, clear, and link in our adapter structure */
adapter = device_get_softc(dev);
adapter->dev = adapter->osdep.dev = dev;
@@ -690,10 +696,38 @@ ixv_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
{
struct adapter *adapter = ifp->if_softc;
struct ifreq *ifr = (struct ifreq *) data;
+#if defined(INET) || defined(INET6)
+ struct ifaddr *ifa = (struct ifaddr *) data;
+ bool avoid_reset = FALSE;
+#endif
int error = 0;
switch (command) {
+ case SIOCSIFADDR:
+#ifdef INET
+ if (ifa->ifa_addr->sa_family == AF_INET)
+ avoid_reset = TRUE;
+#endif
+#ifdef INET6
+ if (ifa->ifa_addr->sa_family == AF_INET6)
+ avoid_reset = TRUE;
+#endif
+#if defined(INET) || defined(INET6)
+ /*
+ ** Calling init results in link renegotiation,
+ ** so we avoid doing it when possible.
+ */
+ if (avoid_reset) {
+ ifp->if_flags |= IFF_UP;
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
+ ixv_init(adapter);
+ if (!(ifp->if_flags & IFF_NOARP))
+ arp_ifinit(ifp, ifa);
+ } else
+ error = ether_ioctl(ifp, command, data);
+ break;
+#endif
case SIOCSIFMTU:
IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)");
if (ifr->ifr_mtu > IXV_MAX_FRAME_SIZE - ETHER_HDR_LEN) {
@@ -1161,7 +1195,7 @@ ixv_xmit(struct tx_ring *txr, struct mbuf **m_headp)
struct mbuf *m_head;
bus_dma_segment_t segs[32];
bus_dmamap_t map;
- struct ixv_tx_buf *txbuf, *txbuf_mapped;
+ struct ixv_tx_buf *txbuf;
union ixgbe_adv_tx_desc *txd = NULL;
m_head = *m_headp;
@@ -1180,7 +1214,6 @@ ixv_xmit(struct tx_ring *txr, struct mbuf **m_headp)
*/
first = txr->next_avail_desc;
txbuf = &txr->tx_buffers[first];
- txbuf_mapped = txbuf;
map = txbuf->map;
/*
@@ -1283,6 +1316,7 @@ ixv_xmit(struct tx_ring *txr, struct mbuf **m_headp)
txr->next_avail_desc = i;
txbuf->m_head = m_head;
+ txr->tx_buffers[first].map = txbuf->map;
txbuf->map = map;
bus_dmamap_sync(txr->txtag, map, BUS_DMASYNC_PREWRITE);
@@ -1820,11 +1854,15 @@ ixv_setup_interface(device_t dev, struct adapter *adapter)
ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_TSO4 | IFCAP_VLAN_HWCSUM;
- ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU;
- ifp->if_capabilities |= IFCAP_JUMBO_MTU | IFCAP_LRO;
-
+ ifp->if_capabilities |= IFCAP_JUMBO_MTU;
+ ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING
+ | IFCAP_VLAN_HWTSO
+ | IFCAP_VLAN_MTU;
ifp->if_capenable = ifp->if_capabilities;
+ /* Don't enable LRO by default */
+ ifp->if_capabilities |= IFCAP_LRO;
+
/*
* Specify the media types supported by this adapter and register
* callbacks to update media and link information
diff --git a/sys/dev/mfi/mfi.c b/sys/dev/mfi/mfi.c
index eb18ffe..1962648 100644
--- a/sys/dev/mfi/mfi.c
+++ b/sys/dev/mfi/mfi.c
@@ -788,7 +788,7 @@ mfi_aen_setup(struct mfi_softc *sc, uint32_t seq_start)
class_locale.members.reserved = 0;
class_locale.members.locale = mfi_event_locale;
- class_locale.members.class = mfi_event_class;
+ class_locale.members.evt_class = mfi_event_class;
if (seq_start == 0) {
error = mfi_get_log_state(sc, &log_state);
@@ -1082,8 +1082,8 @@ mfi_decode_evt(struct mfi_softc *sc, struct mfi_evt_detail *detail)
{
device_printf(sc->mfi_dev, "%d (%s/0x%04x/%s) - %s\n", detail->seq,
- format_timestamp(detail->time), detail->class.members.locale,
- format_class(detail->class.members.class), detail->description);
+ format_timestamp(detail->time), detail->evt_class.members.locale,
+ format_class(detail->evt_class.members.evt_class), detail->description);
}
static int
@@ -1099,16 +1099,16 @@ mfi_aen_register(struct mfi_softc *sc, int seq, int locale)
if (sc->mfi_aen_cm != NULL) {
prior_aen.word =
((uint32_t *)&sc->mfi_aen_cm->cm_frame->dcmd.mbox)[1];
- if (prior_aen.members.class <= current_aen.members.class &&
+ if (prior_aen.members.evt_class <= current_aen.members.evt_class &&
!((prior_aen.members.locale & current_aen.members.locale)
^current_aen.members.locale)) {
return (0);
} else {
prior_aen.members.locale |= current_aen.members.locale;
- if (prior_aen.members.class
- < current_aen.members.class)
- current_aen.members.class =
- prior_aen.members.class;
+ if (prior_aen.members.evt_class
+ < current_aen.members.evt_class)
+ current_aen.members.evt_class =
+ prior_aen.members.evt_class;
mfi_abort(sc, sc->mfi_aen_cm);
}
}
@@ -1199,7 +1199,7 @@ mfi_parse_entries(struct mfi_softc *sc, int start_seq, int stop_seq)
class_locale.members.reserved = 0;
class_locale.members.locale = mfi_event_locale;
- class_locale.members.class = mfi_event_class;
+ class_locale.members.evt_class = mfi_event_class;
size = sizeof(struct mfi_evt_list) + sizeof(struct mfi_evt_detail)
* (MAX_EVENTS - 1);
diff --git a/sys/dev/mfi/mfireg.h b/sys/dev/mfi/mfireg.h
index e08a16d..efee827 100644
--- a/sys/dev/mfi/mfireg.h
+++ b/sys/dev/mfi/mfireg.h
@@ -719,7 +719,7 @@ union mfi_evt {
struct {
uint16_t locale;
uint8_t reserved;
- int8_t class;
+ int8_t evt_class;
} members;
uint32_t word;
} __packed;
@@ -755,7 +755,7 @@ struct mfi_evt_detail {
uint32_t seq;
uint32_t time;
uint32_t code;
- union mfi_evt class;
+ union mfi_evt evt_class;
uint8_t arg_type;
uint8_t reserved1[15];
diff --git a/sys/dev/mmc/mmc.c b/sys/dev/mmc/mmc.c
index 45ddd56..6ff47c3 100644
--- a/sys/dev/mmc/mmc.c
+++ b/sys/dev/mmc/mmc.c
@@ -1445,37 +1445,37 @@ mmc_read_ivar(device_t bus, device_t child, int which, uintptr_t *result)
default:
return (EINVAL);
case MMC_IVAR_DSR_IMP:
- *(int *)result = ivar->csd.dsr_imp;
+ *result = ivar->csd.dsr_imp;
break;
case MMC_IVAR_MEDIA_SIZE:
- *(off_t *)result = ivar->sec_count;
+ *result = ivar->sec_count;
break;
case MMC_IVAR_RCA:
- *(int *)result = ivar->rca;
+ *result = ivar->rca;
break;
case MMC_IVAR_SECTOR_SIZE:
- *(int *)result = MMC_SECTOR_SIZE;
+ *result = MMC_SECTOR_SIZE;
break;
case MMC_IVAR_TRAN_SPEED:
- *(int *)result = mmcbr_get_clock(bus);
+ *result = mmcbr_get_clock(bus);
break;
case MMC_IVAR_READ_ONLY:
- *(int *)result = ivar->read_only;
+ *result = ivar->read_only;
break;
case MMC_IVAR_HIGH_CAP:
- *(int *)result = ivar->high_cap;
+ *result = ivar->high_cap;
break;
case MMC_IVAR_CARD_TYPE:
- *(int *)result = ivar->mode;
+ *result = ivar->mode;
break;
case MMC_IVAR_BUS_WIDTH:
- *(int *)result = ivar->bus_width;
+ *result = ivar->bus_width;
break;
case MMC_IVAR_ERASE_SECTOR:
- *(int *)result = ivar->erase_sector;
+ *result = ivar->erase_sector;
break;
case MMC_IVAR_MAX_DATA:
- *(int *)result = mmcbr_get_max_data(bus);
+ *result = mmcbr_get_max_data(bus);
break;
}
return (0);
diff --git a/sys/dev/mmc/mmcvar.h b/sys/dev/mmc/mmcvar.h
index 9126439..a28d3ac 100644
--- a/sys/dev/mmc/mmcvar.h
+++ b/sys/dev/mmc/mmcvar.h
@@ -79,7 +79,7 @@ enum mmc_device_ivars {
__BUS_ACCESSOR(mmc, var, MMC, ivar, type)
MMC_ACCESSOR(dsr_imp, DSR_IMP, int)
-MMC_ACCESSOR(media_size, MEDIA_SIZE, off_t)
+MMC_ACCESSOR(media_size, MEDIA_SIZE, long)
MMC_ACCESSOR(rca, RCA, int)
MMC_ACCESSOR(sector_size, SECTOR_SIZE, int)
MMC_ACCESSOR(tran_speed, TRAN_SPEED, int)
diff --git a/sys/dev/msk/if_msk.c b/sys/dev/msk/if_msk.c
index 23538f7..be4ac5d 100644
--- a/sys/dev/msk/if_msk.c
+++ b/sys/dev/msk/if_msk.c
@@ -566,7 +566,7 @@ msk_miibus_statchg(device_t dev)
msk_phy_writereg(sc_if, PHY_ADDR_MARV, PHY_MARV_INT_MASK, 0);
/* Disable Rx/Tx MAC. */
gmac = GMAC_READ_2(sc, sc_if->msk_port, GM_GP_CTRL);
- if ((GM_GPCR_RX_ENA | GM_GPCR_TX_ENA) != 0) {
+ if ((gmac & (GM_GPCR_RX_ENA | GM_GPCR_TX_ENA)) != 0) {
gmac &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
GMAC_WRITE_2(sc, sc_if->msk_port, GM_GP_CTRL, gmac);
/* Read again to ensure writing. */
diff --git a/sys/dev/nfe/if_nfe.c b/sys/dev/nfe/if_nfe.c
index 6cdfa34..28a3c01 100644
--- a/sys/dev/nfe/if_nfe.c
+++ b/sys/dev/nfe/if_nfe.c
@@ -1889,7 +1889,7 @@ nfe_int_task(void *arg, int pending)
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
NFE_UNLOCK(sc);
- nfe_enable_intr(sc);
+ nfe_disable_intr(sc);
return;
}
diff --git a/sys/dev/puc/pucdata.c b/sys/dev/puc/pucdata.c
index 3869786..a56971e 100644
--- a/sys/dev/puc/pucdata.c
+++ b/sys/dev/puc/pucdata.c
@@ -48,8 +48,8 @@ __FBSDID("$FreeBSD$");
#include <dev/puc/puc_bfe.h>
static puc_config_f puc_config_amc;
-static puc_config_f puc_config_cronyx;
static puc_config_f puc_config_diva;
+static puc_config_f puc_config_exar;
static puc_config_f puc_config_icbook;
static puc_config_f puc_config_quatech;
static puc_config_f puc_config_syba;
@@ -548,11 +548,25 @@ const struct puc_cfg puc_pci_devices[] = {
PUC_PORT_8S, 0x18, 0, 8,
},
+ { 0x13a8, 0x0152, 0xffff, 0,
+ "Exar XR17C/D152",
+ DEFAULT_RCLK * 8,
+ PUC_PORT_2S, 0x10, 0, -1,
+ .config_function = puc_config_exar
+ },
+
+ { 0x13a8, 0x0154, 0xffff, 0,
+ "Exar XR17C154",
+ DEFAULT_RCLK * 8,
+ PUC_PORT_4S, 0x10, 0, -1,
+ .config_function = puc_config_exar
+ },
+
{ 0x13a8, 0x0158, 0xffff, 0,
- "Cronyx Omega2-PCI",
+ "Exar XR17C158",
DEFAULT_RCLK * 8,
PUC_PORT_8S, 0x10, 0, -1,
- .config_function = puc_config_cronyx
+ .config_function = puc_config_exar
},
{ 0x13a8, 0x0258, 0xffff, 0,
@@ -1014,28 +1028,28 @@ puc_config_amc(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port,
}
static int
-puc_config_cronyx(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port,
+puc_config_diva(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port,
intptr_t *res)
{
+ const struct puc_cfg *cfg = sc->sc_cfg;
+
if (cmd == PUC_CFG_GET_OFS) {
- *res = port * 0x200;
+ if (cfg->subdevice == 0x1282) /* Everest SP */
+ port <<= 1;
+ else if (cfg->subdevice == 0x104b) /* Maestro SP2 */
+ port = (port == 3) ? 4 : port;
+ *res = port * 8 + ((port > 2) ? 0x18 : 0);
return (0);
}
return (ENXIO);
}
static int
-puc_config_diva(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port,
+puc_config_exar(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port,
intptr_t *res)
{
- const struct puc_cfg *cfg = sc->sc_cfg;
-
if (cmd == PUC_CFG_GET_OFS) {
- if (cfg->subdevice == 0x1282) /* Everest SP */
- port <<= 1;
- else if (cfg->subdevice == 0x104b) /* Maestro SP2 */
- port = (port == 3) ? 4 : port;
- *res = port * 8 + ((port > 2) ? 0x18 : 0);
+ *res = port * 0x200;
return (0);
}
return (ENXIO);
diff --git a/sys/dev/sdhci/sdhci.c b/sys/dev/sdhci/sdhci.c
index 6bbc25f..24cba57 100644
--- a/sys/dev/sdhci/sdhci.c
+++ b/sys/dev/sdhci/sdhci.c
@@ -1443,46 +1443,46 @@ sdhci_read_ivar(device_t bus, device_t child, int which, uintptr_t *result)
default:
return (EINVAL);
case MMCBR_IVAR_BUS_MODE:
- *(int *)result = slot->host.ios.bus_mode;
+ *result = slot->host.ios.bus_mode;
break;
case MMCBR_IVAR_BUS_WIDTH:
- *(int *)result = slot->host.ios.bus_width;
+ *result = slot->host.ios.bus_width;
break;
case MMCBR_IVAR_CHIP_SELECT:
- *(int *)result = slot->host.ios.chip_select;
+ *result = slot->host.ios.chip_select;
break;
case MMCBR_IVAR_CLOCK:
- *(int *)result = slot->host.ios.clock;
+ *result = slot->host.ios.clock;
break;
case MMCBR_IVAR_F_MIN:
- *(int *)result = slot->host.f_min;
+ *result = slot->host.f_min;
break;
case MMCBR_IVAR_F_MAX:
- *(int *)result = slot->host.f_max;
+ *result = slot->host.f_max;
break;
case MMCBR_IVAR_HOST_OCR:
- *(int *)result = slot->host.host_ocr;
+ *result = slot->host.host_ocr;
break;
case MMCBR_IVAR_MODE:
- *(int *)result = slot->host.mode;
+ *result = slot->host.mode;
break;
case MMCBR_IVAR_OCR:
- *(int *)result = slot->host.ocr;
+ *result = slot->host.ocr;
break;
case MMCBR_IVAR_POWER_MODE:
- *(int *)result = slot->host.ios.power_mode;
+ *result = slot->host.ios.power_mode;
break;
case MMCBR_IVAR_VDD:
- *(int *)result = slot->host.ios.vdd;
+ *result = slot->host.ios.vdd;
break;
case MMCBR_IVAR_CAPS:
- *(int *)result = slot->host.caps;
+ *result = slot->host.caps;
break;
case MMCBR_IVAR_TIMING:
- *(int *)result = slot->host.ios.timing;
+ *result = slot->host.ios.timing;
break;
case MMCBR_IVAR_MAX_DATA:
- *(int *)result = 65535;
+ *result = 65535;
break;
}
return (0);
diff --git a/sys/dev/usb/net/if_axe.c b/sys/dev/usb/net/if_axe.c
index fbe63de..00d1c0b 100644
--- a/sys/dev/usb/net/if_axe.c
+++ b/sys/dev/usb/net/if_axe.c
@@ -514,7 +514,7 @@ static void
axe_ax88178_init(struct axe_softc *sc)
{
struct usb_ether *ue;
- int gpio0, phymode;
+ int gpio0, ledmode, phymode;
uint16_t eeprom, val;
ue = &sc->sc_ue;
@@ -528,9 +528,11 @@ axe_ax88178_init(struct axe_softc *sc)
if (eeprom == 0xffff) {
phymode = AXE_PHY_MODE_MARVELL;
gpio0 = 1;
+ ledmode = 0;
} else {
phymode = eeprom & 0x7f;
gpio0 = (eeprom & 0x80) ? 0 : 1;
+ ledmode = eeprom >> 8;
}
if (bootverbose)
@@ -548,9 +550,22 @@ axe_ax88178_init(struct axe_softc *sc)
AXE_GPIO_WRITE(AXE_GPIO0_EN | AXE_GPIO2_EN, hz / 4);
AXE_GPIO_WRITE(AXE_GPIO0_EN | AXE_GPIO2 | AXE_GPIO2_EN,
hz / 32);
- } else
+ } else {
AXE_GPIO_WRITE(AXE_GPIO_RELOAD_EEPROM | AXE_GPIO1 |
- AXE_GPIO1_EN, hz / 32);
+ AXE_GPIO1_EN, hz / 3);
+ if (ledmode == 1) {
+ AXE_GPIO_WRITE(AXE_GPIO1_EN, hz / 3);
+ AXE_GPIO_WRITE(AXE_GPIO1 | AXE_GPIO1_EN,
+ hz / 3);
+ } else {
+ AXE_GPIO_WRITE(AXE_GPIO1 | AXE_GPIO1_EN |
+ AXE_GPIO2 | AXE_GPIO2_EN, hz / 32);
+ AXE_GPIO_WRITE(AXE_GPIO1 | AXE_GPIO1_EN |
+ AXE_GPIO2_EN, hz / 4);
+ AXE_GPIO_WRITE(AXE_GPIO1 | AXE_GPIO1_EN |
+ AXE_GPIO2 | AXE_GPIO2_EN, hz / 32);
+ }
+ }
break;
case AXE_PHY_MODE_CICADA:
case AXE_PHY_MODE_CICADA_V2:
diff --git a/sys/dev/usb/serial/umcs.c b/sys/dev/usb/serial/umcs.c
new file mode 100644
index 0000000..c74044e
--- /dev/null
+++ b/sys/dev/usb/serial/umcs.c
@@ -0,0 +1,1075 @@
+/*-
+ * Copyright (c) 2010 Lev Serebryakov <lev@FreeBSD.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * This driver supports several multiport USB-to-RS232 serial adapters driven
+ * by MosChip mos7820 and mos7840, bridge chips.
+ * The adapters are sold under many different brand names.
+ *
+ * Datasheets are available at MosChip www site at
+ * http://www.moschip.com. The datasheets don't contain full
+ * programming information for the chip.
+ *
+ * It is nornal to have only two enabled ports in devices, based on
+ * quad-port mos7840.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#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/linker_set.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 <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdi_util.h>
+#include <dev/usb/usb_cdc.h>
+#include "usbdevs.h"
+
+#define USB_DEBUG_VAR umcs_debug
+#include <dev/usb/usb_debug.h>
+#include <dev/usb/usb_process.h>
+
+#include <dev/usb/serial/usb_serial.h>
+
+#include <dev/usb/serial/umcs.h>
+
+#define UMCS7840_MODVER 1
+
+#ifdef USB_DEBUG
+static int umcs_debug = 0;
+
+SYSCTL_NODE(_hw_usb, OID_AUTO, umcs, CTLFLAG_RW, 0, "USB umcs quadport serial adapter");
+SYSCTL_INT(_hw_usb_umcs, OID_AUTO, debug, CTLFLAG_RW, &umcs_debug, 0, "Debug level");
+#endif /* USB_DEBUG */
+
+
+/*
+ * Two-port devices (both with 7820 chip and 7840 chip configured as two-port)
+ * have ports 0 and 2, with ports 1 and 3 omitted.
+ * So,PHYSICAL port numbers (indexes) on two-port device will be 0 and 2.
+ * This driver trys to use physical numbers as much as possible.
+ */
+
+/*
+ * Indexed by PHYSICAL port number.
+ * Pack non-regular registers to array to easier if-less access.
+ */
+struct umcs7840_port_registers {
+ uint8_t reg_sp; /* SP register. */
+ uint8_t reg_control; /* CONTROL register. */
+ uint8_t reg_dcr; /* DCR0 register. DCR1 & DCR2 can be
+ * calculated */
+};
+
+static const struct umcs7840_port_registers umcs7840_port_registers[UMCS7840_MAX_PORTS] = {
+ {.reg_sp = MCS7840_DEV_REG_SP1,.reg_control = MCS7840_DEV_REG_CONTROL1,.reg_dcr = MCS7840_DEV_REG_DCR0_1},
+ {.reg_sp = MCS7840_DEV_REG_SP2,.reg_control = MCS7840_DEV_REG_CONTROL2,.reg_dcr = MCS7840_DEV_REG_DCR0_2},
+ {.reg_sp = MCS7840_DEV_REG_SP3,.reg_control = MCS7840_DEV_REG_CONTROL3,.reg_dcr = MCS7840_DEV_REG_DCR0_3},
+ {.reg_sp = MCS7840_DEV_REG_SP4,.reg_control = MCS7840_DEV_REG_CONTROL4,.reg_dcr = MCS7840_DEV_REG_DCR0_4},
+};
+
+enum {
+ UMCS7840_BULK_RD_EP,
+ UMCS7840_BULK_WR_EP,
+ UMCS7840_N_TRANSFERS
+};
+
+struct umcs7840_softc_oneport {
+ struct usb_xfer *sc_xfer[UMCS7840_N_TRANSFERS]; /* Control structures
+ * for two transfers */
+
+ uint8_t sc_lcr; /* local line control register */
+ uint8_t sc_mcr; /* local modem control register */
+ uint8_t sc_lsr; /* local line status register */
+ uint8_t sc_msr; /* local modem status register */
+};
+
+struct umcs7840_softc {
+ struct ucom_super_softc sc_super_ucom;
+ struct ucom_softc sc_ucom[UMCS7840_MAX_PORTS]; /* Need to be continuous
+ * array, so indexed by
+ * LOGICAL port
+ * (subunit) number */
+
+ struct usb_xfer *sc_intr_xfer; /* Interrupt endpoint */
+
+ device_t sc_dev; /* Device for error prints */
+ struct usb_device *sc_udev; /* USB Device for all operations */
+ struct mtx sc_mtx; /* ucom requires this */
+
+ uint8_t sc_driver_done; /* Flag when enumeration is finished */
+
+ uint8_t sc_numports; /* Number of ports (subunits) */
+ struct umcs7840_softc_oneport sc_ports[UMCS7840_MAX_PORTS]; /* Indexed by PHYSICAL
+ * port number. */
+};
+
+/* prototypes */
+static usb_error_t umcs7840_get_reg_sync(struct umcs7840_softc *, uint8_t, uint8_t *);
+static usb_error_t umcs7840_set_reg_sync(struct umcs7840_softc *, uint8_t, uint8_t);
+static usb_error_t umcs7840_get_UART_reg_sync(struct umcs7840_softc *, uint8_t, uint8_t, uint8_t *);
+static usb_error_t umcs7840_set_UART_reg_sync(struct umcs7840_softc *, uint8_t, uint8_t, uint8_t);
+
+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_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);
+static void umcs7840_cfg_set_break(struct ucom_softc *, uint8_t);
+static void umcs7840_cfg_param(struct ucom_softc *, struct termios *);
+static void umcs7840_cfg_open(struct ucom_softc *);
+static void umcs7840_cfg_close(struct ucom_softc *);
+
+static int umcs7840_pre_param(struct ucom_softc *, struct termios *);
+
+static void umcs7840_start_read(struct ucom_softc *);
+static void umcs7840_stop_read(struct ucom_softc *);
+
+static void umcs7840_start_write(struct ucom_softc *);
+static void umcs7840_stop_write(struct ucom_softc *);
+
+static void umcs7840_poll(struct ucom_softc *ucom);
+
+static device_probe_t umcs7840_probe;
+static device_attach_t umcs7840_attach;
+static device_detach_t umcs7840_detach;
+
+static usb_callback_t umcs7840_intr_callback;
+static usb_callback_t umcs7840_read_callback1;
+static usb_callback_t umcs7840_read_callback2;
+static usb_callback_t umcs7840_read_callback3;
+static usb_callback_t umcs7840_read_callback4;
+static usb_callback_t umcs7840_write_callback1;
+static usb_callback_t umcs7840_write_callback2;
+static usb_callback_t umcs7840_write_callback3;
+static usb_callback_t umcs7840_write_callback4;
+
+static void umcs7840_read_callbackN(struct usb_xfer *, usb_error_t, uint8_t);
+static void umcs7840_write_callbackN(struct usb_xfer *, usb_error_t, uint8_t);
+
+/* Indexed by LOGICAL port number (subunit), so two-port device uses 0 & 1 */
+static usb_callback_t *umcs7840_rw_callbacks[UMCS7840_MAX_PORTS][UMCS7840_N_TRANSFERS] = {
+ {&umcs7840_read_callback1, &umcs7840_write_callback1},
+ {&umcs7840_read_callback2, &umcs7840_write_callback2},
+ {&umcs7840_read_callback3, &umcs7840_write_callback3},
+ {&umcs7840_read_callback4, &umcs7840_write_callback4},
+};
+
+static const struct usb_config umcs7840_bulk_config_data[UMCS7840_N_TRANSFERS] = {
+ [UMCS7840_BULK_RD_EP] = {
+ .type = UE_BULK,
+ .endpoint = 0x01,
+ .direction = UE_DIR_IN,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .bufsize = 0, /* use wMaxPacketSize */
+ .callback = &umcs7840_read_callback1,
+ .if_index = 0,
+ },
+
+ [UMCS7840_BULK_WR_EP] = {
+ .type = UE_BULK,
+ .endpoint = 0x02,
+ .direction = UE_DIR_OUT,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .bufsize = 0, /* use wMaxPacketSize */
+ .callback = &umcs7840_write_callback1,
+ .if_index = 0,
+ },
+};
+
+static const struct usb_config umcs7840_intr_config_data[1] = {
+ [0] = {
+ .type = UE_INTERRUPT,
+ .endpoint = 0x09,
+ .direction = UE_DIR_IN,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .bufsize = 0, /* use wMaxPacketSize */
+ .callback = &umcs7840_intr_callback,
+ .if_index = 0,
+ },
+};
+
+static struct ucom_callback umcs7840_callback = {
+ .ucom_cfg_get_status = &umcs7840_cfg_get_status,
+
+ .ucom_cfg_set_dtr = &umcs7840_cfg_set_dtr,
+ .ucom_cfg_set_rts = &umcs7840_cfg_set_rts,
+ .ucom_cfg_set_break = &umcs7840_cfg_set_break,
+
+ .ucom_cfg_param = &umcs7840_cfg_param,
+ .ucom_cfg_open = &umcs7840_cfg_open,
+ .ucom_cfg_close = &umcs7840_cfg_close,
+
+ .ucom_pre_param = &umcs7840_pre_param,
+
+ .ucom_start_read = &umcs7840_start_read,
+ .ucom_stop_read = &umcs7840_stop_read,
+
+ .ucom_start_write = &umcs7840_start_write,
+ .ucom_stop_write = &umcs7840_stop_write,
+
+ .ucom_poll = &umcs7840_poll,
+};
+
+static const struct usb_device_id umcs7840_devs[] = {
+ {USB_VPI(USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7820, 0)},
+ {USB_VPI(USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7840, 0)},
+};
+
+static device_method_t umcs7840_methods[] = {
+ DEVMETHOD(device_probe, umcs7840_probe),
+ DEVMETHOD(device_attach, umcs7840_attach),
+ DEVMETHOD(device_detach, umcs7840_detach),
+ {0, 0}
+};
+
+static devclass_t umcs7840_devclass;
+
+static driver_t umcs7840_driver = {
+ .name = "umcs7840",
+ .methods = umcs7840_methods,
+ .size = sizeof(struct umcs7840_softc),
+};
+
+DRIVER_MODULE(umcs7840, uhub, umcs7840_driver, umcs7840_devclass, 0, 0);
+MODULE_DEPEND(umcs7840, ucom, 1, 1, 1);
+MODULE_DEPEND(umcs7840, usb, 1, 1, 1);
+MODULE_VERSION(umcs7840, UMCS7840_MODVER);
+
+static int
+umcs7840_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 != MCS7840_CONFIG_INDEX)
+ return (ENXIO);
+ if (uaa->info.bIfaceIndex != MCS7840_IFACE_INDEX)
+ return (ENXIO);
+ return (usbd_lookup_id_by_uaa(umcs7840_devs, sizeof(umcs7840_devs), uaa));
+}
+
+static int
+umcs7840_attach(device_t dev)
+{
+ struct usb_config umcs7840_config_tmp[UMCS7840_N_TRANSFERS];
+ struct usb_attach_arg *uaa = device_get_ivars(dev);
+ struct umcs7840_softc *sc = device_get_softc(dev);
+
+ uint8_t iface_index = MCS7840_IFACE_INDEX;
+ int error;
+ int subunit;
+ int n;
+ uint8_t data;
+
+ for (n = 0; n < UMCS7840_N_TRANSFERS; ++n)
+ umcs7840_config_tmp[n] = umcs7840_bulk_config_data[n];
+
+ device_set_usb_desc(dev);
+ mtx_init(&sc->sc_mtx, "umcs7840", NULL, MTX_DEF);
+
+ sc->sc_dev = dev;
+ sc->sc_udev = uaa->device;
+
+ /*
+ * Get number of ports
+ * Documentation (full datasheet) says, that number of ports is
+ * set as MCS7840_DEV_MODE_SELECT24S bit in MODE R/Only
+ * register. But vendor driver uses these undocumented
+ * register & bit.
+ *
+ * Experiments show, that MODE register can have `0'
+ * (4 ports) bit on 2-port device, so use vendor driver's way.
+ *
+ * Also, see notes in header file for these constants.
+ */
+ umcs7840_get_reg_sync(sc, MCS7840_DEV_REG_GPIO, &data);
+ if (data & MCS7840_DEV_GPIO_4PORTS) {
+ sc->sc_numports = 4;
+ /* Store physical port numbers in sc_portno */
+ sc->sc_ucom[0].sc_portno = 0;
+ sc->sc_ucom[1].sc_portno = 1;
+ sc->sc_ucom[2].sc_portno = 2;
+ sc->sc_ucom[3].sc_portno = 3;
+ } else {
+ sc->sc_numports = 2;
+ /* Store physical port numbers in sc_portno */
+ sc->sc_ucom[0].sc_portno = 0;
+ sc->sc_ucom[1].sc_portno = 2; /* '1' is skipped */
+ }
+ device_printf(dev, "Chip mcs%04x, found %d active ports\n", uaa->info.idProduct, sc->sc_numports);
+ if (!umcs7840_get_reg_sync(sc, MCS7840_DEV_REG_MODE, &data)) {
+ device_printf(dev, "On-die confguration: RST: active %s, HRD: %s, PLL: %s, POR: %s, Ports: %s, EEPROM write %s, IrDA is %savailable\n",
+ (data & MCS7840_DEV_MODE_RESET) ? "low" : "high",
+ (data & MCS7840_DEV_MODE_SER_PRSNT) ? "yes" : "no",
+ (data & MCS7840_DEV_MODE_PLLBYPASS) ? "bypassed" : "avail",
+ (data & MCS7840_DEV_MODE_PORBYPASS) ? "bypassed" : "avail",
+ (data & MCS7840_DEV_MODE_SELECT24S) ? "2" : "4",
+ (data & MCS7840_DEV_MODE_EEPROMWR) ? "enabled" : "disabled",
+ (data & MCS7840_DEV_MODE_IRDA) ? "" : "not ");
+ }
+ /* Setup all transfers */
+ for (subunit = 0; subunit < sc->sc_numports; ++subunit) {
+ for (n = 0; n < UMCS7840_N_TRANSFERS; ++n) {
+ /* Set endpoint address */
+ umcs7840_config_tmp[n].endpoint = umcs7840_bulk_config_data[n].endpoint + 2 * sc->sc_ucom[subunit].sc_portno;
+ umcs7840_config_tmp[n].callback = umcs7840_rw_callbacks[subunit][n];
+ }
+ error = usbd_transfer_setup(uaa->device,
+ &iface_index, sc->sc_ports[sc->sc_ucom[subunit].sc_portno].sc_xfer, umcs7840_config_tmp,
+ UMCS7840_N_TRANSFERS, sc, &sc->sc_mtx);
+ if (error) {
+ device_printf(dev, "allocating USB transfers failed for subunit %d of %d\n",
+ subunit + 1, sc->sc_numports);
+ goto detach;
+ }
+ }
+ error = usbd_transfer_setup(uaa->device,
+ &iface_index, &sc->sc_intr_xfer, umcs7840_intr_config_data,
+ 1, sc, &sc->sc_mtx);
+ if (error) {
+ device_printf(dev, "allocating USB transfers failed for interrupt\n");
+ goto detach;
+ }
+ /* clear stall at first run */
+ mtx_lock(&sc->sc_mtx);
+ for (subunit = 0; subunit < sc->sc_numports; ++subunit) {
+ usbd_xfer_set_stall(sc->sc_ports[sc->sc_ucom[subunit].sc_portno].sc_xfer[UMCS7840_BULK_RD_EP]);
+ usbd_xfer_set_stall(sc->sc_ports[sc->sc_ucom[subunit].sc_portno].sc_xfer[UMCS7840_BULK_WR_EP]);
+ }
+ mtx_unlock(&sc->sc_mtx);
+
+ error = ucom_attach(&sc->sc_super_ucom, sc->sc_ucom, sc->sc_numports, sc,
+ &umcs7840_callback, &sc->sc_mtx);
+ if (error)
+ goto detach;
+
+ ucom_set_pnpinfo_usb(&sc->sc_super_ucom, dev);
+
+ return (0);
+
+detach:
+ umcs7840_detach(dev);
+ return (ENXIO);
+}
+
+static int
+umcs7840_detach(device_t dev)
+{
+ struct umcs7840_softc *sc = device_get_softc(dev);
+ int subunit;
+
+ ucom_detach(&sc->sc_super_ucom, sc->sc_ucom);
+
+ for (subunit = 0; subunit < sc->sc_numports; ++subunit)
+ 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);
+}
+
+static void
+umcs7840_cfg_open(struct ucom_softc *ucom)
+{
+ struct umcs7840_softc *sc = ucom->sc_parent;
+ uint16_t pn = ucom->sc_portno;
+ uint8_t data;
+
+ /* If it very first open, finish global configuration */
+ if (!sc->sc_driver_done) {
+ /*
+ * USB enumeration is finished, pass internal memory to FIFOs
+ * If it is done in the end of "attach", kernel panics.
+ */
+ if (umcs7840_get_reg_sync(sc, MCS7840_DEV_REG_CONTROL1, &data))
+ return;
+ data |= MCS7840_DEV_CONTROL1_DRIVER_DONE;
+ if (umcs7840_set_reg_sync(sc, MCS7840_DEV_REG_CONTROL1, data))
+ return;
+ sc->sc_driver_done = 1;
+ }
+ /* Toggle reset bit on-off */
+ if (umcs7840_get_reg_sync(sc, umcs7840_port_registers[pn].reg_sp, &data))
+ return;
+ data |= MCS7840_DEV_SPx_UART_RESET;
+ if (umcs7840_set_reg_sync(sc, umcs7840_port_registers[pn].reg_sp, data))
+ return;
+ data &= ~MCS7840_DEV_SPx_UART_RESET;
+ if (umcs7840_set_reg_sync(sc, umcs7840_port_registers[pn].reg_sp, data))
+ return;
+
+ /* Set RS-232 mode */
+ if (umcs7840_set_UART_reg_sync(sc, pn, MCS7840_UART_REG_SCRATCHPAD, MCS7840_UART_SCRATCHPAD_RS232))
+ return;
+
+ /* Disable RX on time of initialization */
+ if (umcs7840_get_reg_sync(sc, umcs7840_port_registers[pn].reg_control, &data))
+ return;
+ data |= MCS7840_DEV_CONTROLx_RX_DISABLE;
+ if (umcs7840_set_reg_sync(sc, umcs7840_port_registers[pn].reg_control, data))
+ return;
+
+ /* Disable all interrupts */
+ if (umcs7840_set_UART_reg_sync(sc, pn, MCS7840_UART_REG_IER, 0))
+ return;
+
+ /* Reset FIFO -- documented */
+ if (umcs7840_set_UART_reg_sync(sc, pn, MCS7840_UART_REG_FCR, 0))
+ return;
+ if (umcs7840_set_UART_reg_sync(sc, pn, MCS7840_UART_REG_FCR,
+ MCS7840_UART_FCR_ENABLE | MCS7840_UART_FCR_FLUSHRHR |
+ MCS7840_UART_FCR_FLUSHTHR | MCS7840_UART_FCR_RTL_1_14))
+ return;
+
+ /* Set 8 bit, no parity, 1 stop bit -- documented */
+ sc->sc_ports[pn].sc_lcr = MCS7840_UART_LCR_DATALEN8 | MCS7840_UART_LCR_STOPB1;
+ if (umcs7840_set_UART_reg_sync(sc, pn, MCS7840_UART_REG_LCR, sc->sc_ports[pn].sc_lcr))
+ return;
+
+ /*
+ * Enable DTR/RTS on modem control, enable modem interrupts --
+ * documented
+ */
+ sc->sc_ports[pn].sc_mcr = MCS7840_UART_MCR_DTR | MCS7840_UART_MCR_RTS | MCS7840_UART_MCR_IE;
+ if (umcs7840_set_UART_reg_sync(sc, pn, MCS7840_UART_REG_MCR, sc->sc_ports[pn].sc_mcr))
+ return;
+
+ /* Clearing Bulkin and Bulkout FIFO */
+ if (umcs7840_get_reg_sync(sc, umcs7840_port_registers[pn].reg_sp, &data))
+ return;
+ data |= MCS7840_DEV_SPx_RESET_OUT_FIFO | MCS7840_DEV_SPx_RESET_IN_FIFO;
+ if (umcs7840_set_reg_sync(sc, umcs7840_port_registers[pn].reg_sp, data))
+ return;
+ data &= ~(MCS7840_DEV_SPx_RESET_OUT_FIFO | MCS7840_DEV_SPx_RESET_IN_FIFO);
+ if (umcs7840_set_reg_sync(sc, umcs7840_port_registers[pn].reg_sp, data))
+ return;
+
+ /* Set speed 9600 */
+ if (umcs7840_set_baudrate(sc, pn, 9600))
+ return;
+
+
+ /* Finally enable all interrupts -- documented */
+ /*
+ * Copied from vendor driver, I don't know why we should read LCR
+ * here
+ */
+ if (umcs7840_get_UART_reg_sync(sc, pn, MCS7840_UART_REG_LCR, &sc->sc_ports[pn].sc_lcr))
+ return;
+ if (umcs7840_set_UART_reg_sync(sc, pn, MCS7840_UART_REG_IER,
+ MCS7840_UART_IER_RXSTAT | MCS7840_UART_IER_MODEM))
+ return;
+
+ /* Enable RX */
+ if (umcs7840_get_reg_sync(sc, umcs7840_port_registers[pn].reg_control, &data))
+ return;
+ data &= ~MCS7840_DEV_CONTROLx_RX_DISABLE;
+ if (umcs7840_set_reg_sync(sc, umcs7840_port_registers[pn].reg_control, data))
+ return;
+
+ /* Read LSR & MSR */
+ if (umcs7840_get_UART_reg_sync(sc, pn, MCS7840_UART_REG_LSR, &sc->sc_ports[pn].sc_lsr))
+ return;
+ if (umcs7840_get_UART_reg_sync(sc, pn, MCS7840_UART_REG_MSR, &sc->sc_ports[pn].sc_msr))
+ return;
+ DPRINTF("Port %d has been opened, LSR=%02x MSR=%02x\n", pn, sc->sc_ports[pn].sc_lsr, sc->sc_ports[pn].sc_msr);
+}
+
+static void
+umcs7840_cfg_close(struct ucom_softc *ucom)
+{
+ struct umcs7840_softc *sc = ucom->sc_parent;
+ uint16_t pn = ucom->sc_portno;
+ uint8_t data;
+
+ umcs7840_stop_read(ucom);
+ umcs7840_stop_write(ucom);
+
+ umcs7840_set_UART_reg_sync(sc, pn, MCS7840_UART_REG_MCR, 0);
+ umcs7840_set_UART_reg_sync(sc, pn, MCS7840_UART_REG_IER, 0);
+
+ /* Disable RX */
+ if (umcs7840_get_reg_sync(sc, umcs7840_port_registers[pn].reg_control, &data))
+ return;
+ data |= MCS7840_DEV_CONTROLx_RX_DISABLE;
+ if (umcs7840_set_reg_sync(sc, umcs7840_port_registers[pn].reg_control, data))
+ return;
+ DPRINTF("Port %d has been closed\n", pn);
+}
+
+static void
+umcs7840_cfg_set_dtr(struct ucom_softc *ucom, uint8_t onoff)
+{
+ struct umcs7840_softc *sc = ucom->sc_parent;
+ uint8_t pn = ucom->sc_portno;
+
+ if (onoff)
+ sc->sc_ports[pn].sc_mcr |= MCS7840_UART_MCR_DTR;
+ else
+ sc->sc_ports[pn].sc_mcr &= ~MCS7840_UART_MCR_DTR;
+
+ umcs7840_set_UART_reg_sync(sc, pn, MCS7840_UART_REG_MCR, sc->sc_ports[pn].sc_mcr);
+ DPRINTF("Port %d DTR set to: %s\n", pn, onoff ? "on" : "off");
+}
+
+static void
+umcs7840_cfg_set_rts(struct ucom_softc *ucom, uint8_t onoff)
+{
+ struct umcs7840_softc *sc = ucom->sc_parent;
+ uint8_t pn = ucom->sc_portno;
+
+ if (onoff)
+ sc->sc_ports[pn].sc_mcr |= MCS7840_UART_MCR_RTS;
+ else
+ sc->sc_ports[pn].sc_mcr &= ~MCS7840_UART_MCR_RTS;
+
+ umcs7840_set_UART_reg_sync(sc, pn, MCS7840_UART_REG_MCR, sc->sc_ports[pn].sc_mcr);
+ DPRINTF("Port %d RTS set to: %s\n", pn, onoff ? "on" : "off");
+}
+
+static void
+umcs7840_cfg_set_break(struct ucom_softc *ucom, uint8_t onoff)
+{
+ struct umcs7840_softc *sc = ucom->sc_parent;
+ uint8_t pn = ucom->sc_portno;
+
+ if (onoff)
+ sc->sc_ports[pn].sc_lcr |= MCS7840_UART_LCR_BREAK;
+ else
+ sc->sc_ports[pn].sc_lcr &= ~MCS7840_UART_LCR_BREAK;
+
+ umcs7840_set_UART_reg_sync(sc, pn, MCS7840_UART_REG_LCR, sc->sc_ports[pn].sc_lcr);
+ DPRINTF("Port %d BREAK set to: %s\n", pn, onoff ? "on" : "off");
+}
+
+
+static void
+umcs7840_cfg_param(struct ucom_softc *ucom, struct termios *t)
+{
+ struct umcs7840_softc *sc = ucom->sc_parent;
+ uint8_t pn = ucom->sc_portno;
+ uint8_t lcr = sc->sc_ports[pn].sc_lcr;
+ uint8_t mcr = sc->sc_ports[pn].sc_mcr;
+
+ DPRINTF("Port %d config:\n", pn);
+ if (t->c_cflag & CSTOPB) {
+ DPRINTF(" 2 stop bits\n");
+ lcr |= MCS7840_UART_LCR_STOPB2;
+ } else {
+ lcr |= MCS7840_UART_LCR_STOPB1;
+ DPRINTF(" 1 stop bit\n");
+ }
+
+ lcr &= ~MCS7840_UART_LCR_PARITYMASK;
+ if (t->c_cflag & PARENB) {
+ lcr |= MCS7840_UART_LCR_PARITYON;
+ if (t->c_cflag & PARODD) {
+ lcr = MCS7840_UART_LCR_PARITYODD;
+ DPRINTF(" parity on - odd\n");
+ } else {
+ lcr = MCS7840_UART_LCR_PARITYEVEN;
+ DPRINTF(" parity on - even\n");
+ }
+ } else {
+ lcr &= ~MCS7840_UART_LCR_PARITYON;
+ DPRINTF(" parity off\n");
+ }
+
+ lcr &= ~MCS7840_UART_LCR_DATALENMASK;
+ switch (t->c_cflag & CSIZE) {
+ case CS5:
+ lcr |= MCS7840_UART_LCR_DATALEN5;
+ DPRINTF(" 5 bit\n");
+ break;
+ case CS6:
+ lcr |= MCS7840_UART_LCR_DATALEN6;
+ DPRINTF(" 6 bit\n");
+ break;
+ case CS7:
+ lcr |= MCS7840_UART_LCR_DATALEN7;
+ DPRINTF(" 7 bit\n");
+ break;
+ case CS8:
+ lcr |= MCS7840_UART_LCR_DATALEN8;
+ DPRINTF(" 8 bit\n");
+ break;
+ }
+
+ if (t->c_cflag & CRTSCTS) {
+ mcr |= MCS7840_UART_MCR_CTSRTS;
+ DPRINTF(" CTS/RTS\n");
+ } else
+ mcr &= ~MCS7840_UART_MCR_CTSRTS;
+
+ if (t->c_cflag & (CDTR_IFLOW | CDSR_OFLOW)) {
+ mcr |= MCS7840_UART_MCR_DTRDSR;
+ DPRINTF(" DTR/DSR\n");
+ } else
+ mcr &= ~MCS7840_UART_MCR_DTRDSR;
+
+ sc->sc_ports[pn].sc_lcr = lcr;
+ umcs7840_set_UART_reg_sync(sc, pn, MCS7840_UART_REG_LCR, sc->sc_ports[pn].sc_lcr);
+ DPRINTF("Port %d LCR=%02x\n", pn, sc->sc_ports[pn].sc_lcr);
+
+ sc->sc_ports[pn].sc_mcr = mcr;
+ umcs7840_set_UART_reg_sync(sc, pn, MCS7840_UART_REG_MCR, sc->sc_ports[pn].sc_mcr);
+ DPRINTF("Port %d MCR=%02x\n", pn, sc->sc_ports[pn].sc_mcr);
+
+ umcs7840_set_baudrate(sc, pn, t->c_ospeed);
+}
+
+
+static int
+umcs7840_pre_param(struct ucom_softc *ucom, struct termios *t)
+{
+ uint8_t clk;
+ uint16_t divisor;
+
+ if (umcs7840_calc_baudrate(t->c_ospeed, &divisor, &clk) || !divisor)
+ return (EINVAL);
+ return (0);
+}
+
+static void
+umcs7840_start_read(struct ucom_softc *ucom)
+{
+ struct umcs7840_softc *sc = ucom->sc_parent;
+ uint8_t pn = ucom->sc_portno;
+
+ /* Start interrupt transfer */
+ usbd_transfer_start(sc->sc_intr_xfer);
+
+ /* Start read transfer */
+ usbd_transfer_start(sc->sc_ports[pn].sc_xfer[UMCS7840_BULK_RD_EP]);
+}
+
+static void
+umcs7840_stop_read(struct ucom_softc *ucom)
+{
+ struct umcs7840_softc *sc = ucom->sc_parent;
+ uint8_t pn = ucom->sc_portno;
+
+ /* Stop read transfer */
+ usbd_transfer_stop(sc->sc_ports[pn].sc_xfer[UMCS7840_BULK_RD_EP]);
+}
+
+static void
+umcs7840_start_write(struct ucom_softc *ucom)
+{
+ struct umcs7840_softc *sc = ucom->sc_parent;
+ uint8_t pn = ucom->sc_portno;
+
+ /* Start interrupt transfer */
+ usbd_transfer_start(sc->sc_intr_xfer);
+
+ /* Start write transfer */
+ usbd_transfer_start(sc->sc_ports[pn].sc_xfer[UMCS7840_BULK_WR_EP]);
+}
+
+static void
+umcs7840_stop_write(struct ucom_softc *ucom)
+{
+ struct umcs7840_softc *sc = ucom->sc_parent;
+ uint8_t pn = ucom->sc_portno;
+
+ /* Stop write transfer */
+ usbd_transfer_stop(sc->sc_ports[pn].sc_xfer[UMCS7840_BULK_WR_EP]);
+}
+
+static void
+umcs7840_cfg_get_status(struct ucom_softc *ucom, uint8_t *lsr, uint8_t *msr)
+{
+ struct umcs7840_softc *sc = ucom->sc_parent;
+
+ *lsr = sc->sc_ports[ucom->sc_portno].sc_lsr;
+ *msr = sc->sc_ports[ucom->sc_portno].sc_msr;
+ DPRINTF("Port %d status: LSR=%02x MSR=%02x\n", ucom->sc_portno, *lsr, *msr);
+}
+
+static void
+umcs7840_intr_callback(struct usb_xfer *xfer, usb_error_t error)
+{
+ struct umcs7840_softc *sc = usbd_xfer_softc(xfer);
+ struct usb_page_cache *pc;
+ uint8_t buf[13];
+ int actlen;
+ int subunit;
+
+ usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
+
+ switch (USB_GET_STATE(xfer)) {
+ case USB_ST_TRANSFERRED:
+ if (actlen == 5 || actlen == 13) {
+ pc = usbd_xfer_get_frame(xfer, 0);
+ usbd_copy_out(pc, 0, buf, actlen);
+ /* Check status of all ports */
+ for (subunit = 0; subunit < sc->sc_numports; ++subunit) {
+ uint8_t pn = sc->sc_ucom[subunit].sc_portno;
+
+ if (buf[pn] & MCS7840_UART_ISR_NOPENDING)
+ continue;
+ DPRINTF("Port %d has pending interrupt: %02x (FIFO: %02x)\n", pn, buf[pn] & MCS7840_UART_ISR_INTMASK, buf[pn] & (~MCS7840_UART_ISR_INTMASK));
+ switch (buf[pn] & MCS7840_UART_ISR_INTMASK) {
+ case MCS7840_UART_ISR_RXERR:
+ case MCS7840_UART_ISR_RXHASDATA:
+ case MCS7840_UART_ISR_RXTIMEOUT:
+ /* Read new LSR */
+ if (umcs7840_get_UART_reg_sync(sc, pn, MCS7840_UART_REG_LSR, &sc->sc_ports[pn].sc_lsr))
+ break; /* Inner switch */
+ ucom_status_change(&sc->sc_ucom[subunit]);
+ /* Inner switch */
+ break;
+ case MCS7840_UART_ISR_TXEMPTY:
+ /* Do nothing */
+ break; /* Inner switch */
+ case MCS7840_UART_ISR_MSCHANGE:
+ /* Read new MSR */
+ if (umcs7840_get_UART_reg_sync(sc, pn, MCS7840_UART_REG_MSR, &sc->sc_ports[pn].sc_msr))
+ break; /* Inner switch */
+ DPRINTF("Port %d: new MSR %02x\n", pn, sc->sc_ports[pn].sc_msr);
+ ucom_status_change(&sc->sc_ucom[subunit]);
+ break;
+ }
+ }
+ } else
+ device_printf(sc->sc_dev, "Invalid interrupt data length %d", actlen);
+ /* FALLTHROUGH */
+ case USB_ST_SETUP:
+tr_setup:
+ usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
+ usbd_transfer_submit(xfer);
+ return;
+
+ default: /* Error */
+ if (error != USB_ERR_CANCELLED) {
+ /* try to clear stall first */
+ usbd_xfer_set_stall(xfer);
+ goto tr_setup;
+ }
+ return;
+ }
+}
+
+static void
+umcs7840_read_callback1(struct usb_xfer *xfer, usb_error_t error)
+{
+ umcs7840_read_callbackN(xfer, error, 0);
+}
+
+static void
+umcs7840_read_callback2(struct usb_xfer *xfer, usb_error_t error)
+{
+ umcs7840_read_callbackN(xfer, error, 1);
+}
+static void
+umcs7840_read_callback3(struct usb_xfer *xfer, usb_error_t error)
+{
+ umcs7840_read_callbackN(xfer, error, 2);
+}
+
+static void
+umcs7840_read_callback4(struct usb_xfer *xfer, usb_error_t error)
+{
+ umcs7840_read_callbackN(xfer, error, 3);
+}
+
+static void
+umcs7840_read_callbackN(struct usb_xfer *xfer, usb_error_t error, uint8_t subunit)
+{
+ struct umcs7840_softc *sc = usbd_xfer_softc(xfer);
+ struct ucom_softc *ucom = &sc->sc_ucom[subunit];
+ struct usb_page_cache *pc;
+ int actlen;
+
+ usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
+
+ DPRINTF("Port %d read, state = %d, data length = %d\n", ucom->sc_portno, USB_GET_STATE(xfer), actlen);
+
+ switch (USB_GET_STATE(xfer)) {
+ case USB_ST_TRANSFERRED:
+ pc = usbd_xfer_get_frame(xfer, 0);
+ ucom_put_data(ucom, pc, 0, actlen);
+ /* FALLTHROUGH */
+ case USB_ST_SETUP:
+tr_setup:
+ usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
+ usbd_transfer_submit(xfer);
+ return;
+
+ default: /* Error */
+ if (error != USB_ERR_CANCELLED) {
+ /* try to clear stall first */
+ usbd_xfer_set_stall(xfer);
+ goto tr_setup;
+ }
+ return;
+ }
+}
+
+static void
+umcs7840_write_callback1(struct usb_xfer *xfer, usb_error_t error)
+{
+ umcs7840_write_callbackN(xfer, error, 0);
+}
+
+static void
+umcs7840_write_callback2(struct usb_xfer *xfer, usb_error_t error)
+{
+ umcs7840_write_callbackN(xfer, error, 1);
+}
+
+static void
+umcs7840_write_callback3(struct usb_xfer *xfer, usb_error_t error)
+{
+ umcs7840_write_callbackN(xfer, error, 2);
+}
+
+static void
+umcs7840_write_callback4(struct usb_xfer *xfer, usb_error_t error)
+{
+ umcs7840_write_callbackN(xfer, error, 3);
+}
+
+static void
+umcs7840_write_callbackN(struct usb_xfer *xfer, usb_error_t error, uint8_t subunit)
+{
+ struct umcs7840_softc *sc = usbd_xfer_softc(xfer);
+ struct ucom_softc *ucom = &sc->sc_ucom[subunit];
+ struct usb_page_cache *pc;
+ uint32_t actlen;
+
+ DPRINTF("Port %d write, state = %d\n", ucom->sc_portno, USB_GET_STATE(xfer));
+
+ switch (USB_GET_STATE(xfer)) {
+ case USB_ST_SETUP:
+ case USB_ST_TRANSFERRED:
+tr_setup:
+ pc = usbd_xfer_get_frame(xfer, 0);
+ if (ucom_get_data(ucom, pc, 0, usbd_xfer_max_len(xfer), &actlen)) {
+ DPRINTF("Port %d write, has %d bytes\n", ucom->sc_portno, actlen);
+ usbd_xfer_set_frame_len(xfer, 0, actlen);
+ usbd_transfer_submit(xfer);
+ }
+ return;
+
+ default: /* Error */
+ if (error != USB_ERR_CANCELLED) {
+ /* try to clear stall first */
+ usbd_xfer_set_stall(xfer);
+ goto tr_setup;
+ }
+ return;
+ }
+}
+
+static void
+umcs7840_poll(struct ucom_softc *ucom)
+{
+ struct umcs7840_softc *sc = ucom->sc_parent;
+
+ DPRINTF("Port %d poll\n", ucom->sc_portno);
+ usbd_transfer_poll(sc->sc_ports[ucom->sc_portno].sc_xfer, UMCS7840_N_TRANSFERS);
+ usbd_transfer_poll(&sc->sc_intr_xfer, 1);
+}
+
+static usb_error_t
+umcs7840_get_reg_sync(struct umcs7840_softc *sc, uint8_t reg, uint8_t *data)
+{
+ struct usb_device_request req;
+ usb_error_t err;
+ uint16_t len;
+
+ req.bmRequestType = UT_READ_VENDOR_DEVICE;
+ req.bRequest = MCS7840_RDREQ;
+ USETW(req.wValue, 0);
+ USETW(req.wIndex, reg);
+ USETW(req.wLength, UMCS7840_READ_LENGTH);
+
+ err = usbd_do_request_proc(sc->sc_udev, &sc->sc_super_ucom.sc_tq, &req, (void *)data, 0, &len, UMCS7840_CTRL_TIMEOUT);
+ if (err == USB_ERR_NORMAL_COMPLETION && len != 1) {
+ device_printf(sc->sc_dev, "Reading register %d failed: invalid length %d\n", reg, len);
+ return (USB_ERR_INVAL);
+ } else if (err)
+ device_printf(sc->sc_dev, "Reading register %d failed: %s\n", reg, usbd_errstr(err));
+ return (err);
+}
+
+static usb_error_t
+umcs7840_set_reg_sync(struct umcs7840_softc *sc, uint8_t reg, uint8_t data)
+{
+ struct usb_device_request req;
+ usb_error_t err;
+
+ req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req.bRequest = MCS7840_WRREQ;
+ USETW(req.wValue, data);
+ USETW(req.wIndex, reg);
+ USETW(req.wLength, 0);
+
+ err = usbd_do_request_proc(sc->sc_udev, &sc->sc_super_ucom.sc_tq, &req, NULL, 0, NULL, UMCS7840_CTRL_TIMEOUT);
+ if (err)
+ device_printf(sc->sc_dev, "Writing register %d failed: %s\n", reg, usbd_errstr(err));
+
+ return (err);
+}
+
+static usb_error_t
+umcs7840_get_UART_reg_sync(struct umcs7840_softc *sc, uint8_t portno, uint8_t reg, uint8_t *data)
+{
+ struct usb_device_request req;
+ uint16_t wVal;
+ usb_error_t err;
+ uint16_t len;
+
+ /* portno is port number */
+ wVal = ((uint16_t)(portno + 1)) << 8;
+
+ req.bmRequestType = UT_READ_VENDOR_DEVICE;
+ req.bRequest = MCS7840_RDREQ;
+ USETW(req.wValue, wVal);
+ USETW(req.wIndex, reg);
+ USETW(req.wLength, UMCS7840_READ_LENGTH);
+
+ err = usbd_do_request_proc(sc->sc_udev, &sc->sc_super_ucom.sc_tq, &req, (void *)data, 0, &len, UMCS7840_CTRL_TIMEOUT);
+ if (err == USB_ERR_NORMAL_COMPLETION && len != 1) {
+ device_printf(sc->sc_dev, "Reading UART%d register %d failed: invalid length %d\n", portno, reg, len);
+ return (USB_ERR_INVAL);
+ } else if (err)
+ device_printf(sc->sc_dev, "Reading UART%d register %d failed: %s\n", portno, reg, usbd_errstr(err));
+ return (err);
+}
+
+static usb_error_t
+umcs7840_set_UART_reg_sync(struct umcs7840_softc *sc, uint8_t portno, uint8_t reg, uint8_t data)
+{
+ struct usb_device_request req;
+ usb_error_t err;
+ uint16_t wVal;
+
+ /* portno is port number */
+ wVal = ((uint16_t)(portno + 1)) << 8 | data;
+
+ req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req.bRequest = MCS7840_WRREQ;
+ USETW(req.wValue, wVal);
+ USETW(req.wIndex, reg);
+ USETW(req.wLength, 0);
+
+ err = usbd_do_request_proc(sc->sc_udev, &sc->sc_super_ucom.sc_tq, &req, NULL, 0, NULL, UMCS7840_CTRL_TIMEOUT);
+ if (err)
+ device_printf(sc->sc_dev, "Writing UART%d register %d failed: %s\n", portno, reg, usbd_errstr(err));
+ return (err);
+}
+
+static usb_error_t
+umcs7840_set_baudrate(struct umcs7840_softc *sc, uint8_t portno, uint32_t rate)
+{
+ usb_error_t err;
+ uint16_t divisor;
+ uint8_t clk;
+ uint8_t data;
+
+ if (umcs7840_calc_baudrate(rate, &divisor, &clk)) {
+ DPRINTF("Port %d bad speed: %d\n", portno, rate);
+ return (-1);
+ }
+ if (divisor == 0 || (clk & MCS7840_DEV_SPx_CLOCK_MASK) != clk) {
+ DPRINTF("Port %d bad speed calculation: %d\n", portno, rate);
+ return (-1);
+ }
+ DPRINTF("Port %d set speed: %d (%02x / %d)\n", portno, rate, clk, divisor);
+
+ /* Set clock source for standard BAUD frequences */
+ err = umcs7840_get_reg_sync(sc, umcs7840_port_registers[portno].reg_sp, &data);
+ if (err)
+ return (err);
+ data &= MCS7840_DEV_SPx_CLOCK_MASK;
+ data |= clk;
+ err = umcs7840_set_reg_sync(sc, umcs7840_port_registers[portno].reg_sp, data);
+ if (err)
+ return (err);
+
+ /* Set divider */
+ sc->sc_ports[portno].sc_lcr |= MCS7840_UART_LCR_DIVISORS;
+ err = umcs7840_set_UART_reg_sync(sc, portno, MCS7840_UART_REG_LCR, sc->sc_ports[portno].sc_lcr);
+ if (err)
+ return (err);
+
+ err = umcs7840_set_UART_reg_sync(sc, portno, MCS7840_UART_REG_DLL, (uint8_t)(divisor & 0xff));
+ if (err)
+ return (err);
+ err = umcs7840_set_UART_reg_sync(sc, portno, MCS7840_UART_REG_DLM, (uint8_t)((divisor >> 8) & 0xff));
+ if (err)
+ return (err);
+
+ /* Turn off access to DLL/DLM registers of UART */
+ sc->sc_ports[portno].sc_lcr &= ~MCS7840_UART_LCR_DIVISORS;
+ err = umcs7840_set_UART_reg_sync(sc, portno, MCS7840_UART_REG_LCR, sc->sc_ports[portno].sc_lcr);
+ if (err)
+ return (err);
+ return (0);
+}
+
+/* Maximum speeds for standard frequences, when PLL is not used */
+static const uint32_t umcs7840_baudrate_divisors[] = {0, 115200, 230400, 403200, 460800, 806400, 921600, 1572864, 3145728,};
+static const uint8_t umcs7840_baudrate_divisors_len = sizeof(umcs7840_baudrate_divisors) / sizeof(umcs7840_baudrate_divisors[0]);
+
+static usb_error_t
+umcs7840_calc_baudrate(uint32_t rate, uint16_t *divisor, uint8_t *clk)
+{
+ uint8_t i = 0;
+
+ if (rate > umcs7840_baudrate_divisors[umcs7840_baudrate_divisors_len - 1])
+ return (-1);
+
+ for (i = 0; i < umcs7840_baudrate_divisors_len - 1 &&
+ !(rate > umcs7840_baudrate_divisors[i] && rate <= umcs7840_baudrate_divisors[i + 1]); ++i);
+ *divisor = umcs7840_baudrate_divisors[i + 1] / rate;
+ /* 0x00 .. 0x70 */
+ *clk = i << MCS7840_DEV_SPx_CLOCK_SHIFT;
+ return (0);
+}
diff --git a/sys/dev/usb/serial/umcs.h b/sys/dev/usb/serial/umcs.h
new file mode 100644
index 0000000..310b4af
--- /dev/null
+++ b/sys/dev/usb/serial/umcs.h
@@ -0,0 +1,644 @@
+/* $FreeBSD$ */
+/*-
+ * Copyright (c) 2010 Lev Serebryakov <lev@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.
+ */
+#ifndef _UMCS7840_H_
+#define _UMCS7840_H_
+
+#define UMCS7840_MAX_PORTS 4
+
+#define UMCS7840_READ_LENGTH 1 /* bytes */
+#define UMCS7840_CTRL_TIMEOUT 500 /* ms */
+
+/* Read/Wrtire registers vendor commands */
+#define MCS7840_RDREQ 0x0d
+#define MCS7840_WRREQ 0x0e
+
+/* Read/Wrtie EEPROM values */
+#define MCS7840_EEPROM_RW_WVALUE 0x0900
+
+/*
+ * All these registers are documented only in full datasheet,
+ * which can be requested from MosChip tech support.
+ */
+#define MCS7840_DEV_REG_SP1 0x00 /* Options for for UART 1, R/W */
+#define MCS7840_DEV_REG_CONTROL1 0x01 /* Control bits for UART 1,
+ * R/W */
+#define MCS7840_DEV_REG_PINPONGHIGH 0x02 /* High bits of ping-pong
+ * register, R/W */
+#define MCS7840_DEV_REG_PINPONGLOW 0x03 /* Low bits of ping-pong
+ * register, R/W */
+/* DCRx_1 Registers goes here (see below, they are documented) */
+#define MCS7840_DEV_REG_GPIO 0x07 /* GPIO_0 and GPIO_1 bits,
+ * undocumented, see notes
+ * below R/W */
+#define MCS7840_DEV_REG_SP2 0x08 /* Options for for UART 2, R/W */
+#define MCS7840_DEV_REG_CONTROL2 0x09 /* Control bits for UART 2,
+ * R/W */
+#define MCS7840_DEV_REG_SP3 0x0a /* Options for for UART 3, R/W */
+#define MCS7840_DEV_REG_CONTROL3 0x0b /* Control bits for UART 3,
+ * R/W */
+#define MCS7840_DEV_REG_SP4 0x0c /* Options for for UART 4, R/W */
+#define MCS7840_DEV_REG_CONTROL4 0x0d /* Control bits for UART 4,
+ * R/W */
+#define MCS7840_DEV_REG_PLL_DIV_M 0x0e /* Pre-diviedr for PLL, R/W */
+#define MCS7840_DEV_REG_UNKNOWN1 0x0f /* NOT MENTIONED AND NOT USED */
+#define MCS7840_DEV_REG_PLL_DIV_N 0x10 /* Loop divider for PLL, R/W */
+#define MCS7840_DEV_REG_CLOCK_MUX 0x12 /* PLL input clock & Interrupt
+ * endpoint control, R/W */
+#define MCS7840_DEV_REG_UNKNOWN2 0x11 /* NOT MENTIONED AND NOT USED */
+#define MCS7840_DEV_REG_CLOCK_SELECT12 0x13 /* Clock source for ports 1 &
+ * 2, R/W */
+#define MCS7840_DEV_REG_CLOCK_SELECT34 0x14 /* Clock source for ports 3 &
+ * 4, R/W */
+#define MCS7840_DEV_REG_UNKNOWN3 0x15 /* NOT MENTIONED AND NOT USED */
+/* DCRx_2-DCRx_4 Registers goes here (see below, they are documented) */
+#define MCS7840_DEV_REG_UNKNOWN4 0x1f /* NOT MENTIONED AND NOT USED */
+#define MCS7840_DEV_REG_UNKNOWN5 0x20 /* NOT MENTIONED AND NOT USED */
+#define MCS7840_DEV_REG_UNKNOWN6 0x21 /* NOT MENTIONED AND NOT USED */
+#define MCS7840_DEV_REG_UNKNOWN7 0x22 /* NOT MENTIONED AND NOT USED */
+#define MCS7840_DEV_REG_UNKNOWN8 0x23 /* NOT MENTIONED AND NOT USED */
+#define MCS7840_DEV_REG_UNKNOWN9 0x24 /* NOT MENTIONED AND NOT USED */
+#define MCS7840_DEV_REG_UNKNOWNA 0x25 /* NOT MENTIONED AND NOT USED */
+#define MCS7840_DEV_REG_UNKNOWNB 0x26 /* NOT MENTIONED AND NOT USED */
+#define MCS7840_DEV_REG_UNKNOWNC 0x27 /* NOT MENTIONED AND NOT USED */
+#define MCS7840_DEV_REG_UNKNOWND 0x28 /* NOT MENTIONED AND NOT USED */
+#define MCS7840_DEV_REG_UNKNOWNE 0x29 /* NOT MENTIONED AND NOT USED */
+#define MCS7840_DEV_REG_UNKNOWNF 0x2a /* NOT MENTIONED AND NOT USED */
+#define MCS7840_DEV_REG_MODE 0x2b /* Hardware configuration,
+ * R/Only */
+#define MCS7840_DEV_REG_SP1_ICG 0x2c /* Inter character gap
+ * configuration for Port 1,
+ * R/W */
+#define MCS7840_DEV_REG_SP2_ICG 0x2d /* Inter character gap
+ * configuration for Port 2,
+ * R/W */
+#define MCS7840_DEV_REG_SP3_ICG 0x2e /* Inter character gap
+ * configuration for Port 3,
+ * R/W */
+#define MCS7840_DEV_REG_SP4_ICG 0x2f /* Inter character gap
+ * configuration for Port 4,
+ * R/W */
+#define MCS7840_DEV_REG_RX_SAMPLING12 0x30 /* RX sampling for ports 1 &
+ * 2, R/W */
+#define MCS7840_DEV_REG_RX_SAMPLING34 0x31 /* RX sampling for ports 3 &
+ * 4, R/W */
+#define MCS7840_DEV_REG_BI_FIFO_STAT1 0x32 /* Bulk-In FIFO Stat for Port
+ * 1, contains number of
+ * availiable bytes, R/Only */
+#define MCS7840_DEV_REG_BO_FIFO_STAT1 0x33 /* Bulk-out FIFO Stat for Port
+ * 1, contains number of
+ * availiable bytes, R/Only */
+#define MCS7840_DEV_REG_BI_FIFO_STAT2 0x34 /* Bulk-In FIFO Stat for Port
+ * 2, contains number of
+ * availiable bytes, R/Only */
+#define MCS7840_DEV_REG_BO_FIFO_STAT2 0x35 /* Bulk-out FIFO Stat for Port
+ * 2, contains number of
+ * availiable bytes, R/Only */
+#define MCS7840_DEV_REG_BI_FIFO_STAT3 0x36 /* Bulk-In FIFO Stat for Port
+ * 3, contains number of
+ * availiable bytes, R/Only */
+#define MCS7840_DEV_REG_BO_FIFO_STAT3 0x37 /* Bulk-out FIFO Stat for Port
+ * 3, contains number of
+ * availiable bytes, R/Only */
+#define MCS7840_DEV_REG_BI_FIFO_STAT4 0x38 /* Bulk-In FIFO Stat for Port
+ * 4, contains number of
+ * availiable bytes, R/Only */
+#define MCS7840_DEV_REG_BO_FIFO_STAT4 0x39 /* Bulk-out FIFO Stat for Port
+ * 4, contains number of
+ * availiable bytes, R/Only */
+#define MCS7840_DEV_REG_ZERO_PERIOD1 0x3a /* Period between zero out
+ * frames for Port 1, R/W */
+#define MCS7840_DEV_REG_ZERO_PERIOD2 0x3b /* Period between zero out
+ * frames for Port 1, R/W */
+#define MCS7840_DEV_REG_ZERO_PERIOD3 0x3c /* Period between zero out
+ * frames for Port 1, R/W */
+#define MCS7840_DEV_REG_ZERO_PERIOD4 0x3d /* Period between zero out
+ * frames for Port 1, R/W */
+#define MCS7840_DEV_REG_ZERO_ENABLE 0x3e /* Enable/disable of zero out
+ * frames, R/W */
+#define MCS7840_DEV_REG_THR_VAL_LOW1 0x3f /* Low 8 bits of threshhold
+ * value for Bulk-Out for Port
+ * 1, R/W */
+#define MCS7840_DEV_REG_THR_VAL_HIGH1 0x40 /* High 1 bit of threshhold
+ * value for Bulk-Out and
+ * enable flag for Port 1, R/W */
+#define MCS7840_DEV_REG_THR_VAL_LOW2 0x41 /* Low 8 bits of threshhold
+ * value for Bulk-Out for Port
+ * 2, R/W */
+#define MCS7840_DEV_REG_THR_VAL_HIGH2 0x42 /* High 1 bit of threshhold
+ * value for Bulk-Out and
+ * enable flag for Port 2, R/W */
+#define MCS7840_DEV_REG_THR_VAL_LOW3 0x43 /* Low 8 bits of threshhold
+ * value for Bulk-Out for Port
+ * 3, R/W */
+#define MCS7840_DEV_REG_THR_VAL_HIGH3 0x44 /* High 1 bit of threshhold
+ * value for Bulk-Out and
+ * enable flag for Port 3, R/W */
+#define MCS7840_DEV_REG_THR_VAL_LOW4 0x45 /* Low 8 bits of threshhold
+ * value for Bulk-Out for Port
+ * 4, R/W */
+#define MCS7840_DEV_REG_THR_VAL_HIGH4 0x46 /* High 1 bit of threshhold
+ * value for Bulk-Out and
+ * enable flag for Port 4, R/W */
+
+/* Bits for SPx registers */
+#define MCS7840_DEV_SPx_LOOP_PIPES 0x01 /* Loop Bulk-Out FIFO to the
+ * Bulk-In FIFO, default = 0 */
+#define MCS7840_DEV_SPx_SKIP_ERR_DATA 0x02 /* Drop data bytes from UART,
+ * which were recevied with
+ * errors, default = 0 */
+#define MCS7840_DEV_SPx_RESET_OUT_FIFO 0x04 /* Reset Bulk-Out FIFO */
+#define MCS7840_DEV_SPx_RESET_IN_FIFO 0x08 /* Reset Bulk-In FIFO */
+#define MCS7840_DEV_SPx_CLOCK_MASK 0x70 /* Mask to extract Baud CLK
+ * source */
+#define MCS7840_DEV_SPx_CLOCK_X1 0x00 /* CLK = 1.8432Mhz, max speed
+ * = 115200 bps, default */
+#define MCS7840_DEV_SPx_CLOCK_X2 0x10 /* CLK = 3.6864Mhz, max speed
+ * = 230400 bps */
+#define MCS7840_DEV_SPx_CLOCK_X35 0x20 /* CLK = 6.4512Mhz, max speed
+ * = 403200 bps */
+#define MCS7840_DEV_SPx_CLOCK_X4 0x30 /* CLK = 7.3728Mhz, max speed
+ * = 460800 bps */
+#define MCS7840_DEV_SPx_CLOCK_X7 0x40 /* CLK = 12.9024Mhz, max speed
+ * = 806400 bps */
+#define MCS7840_DEV_SPx_CLOCK_X8 0x50 /* CLK = 14.7456Mhz, max speed
+ * = 921600 bps */
+#define MCS7840_DEV_SPx_CLOCK_24MHZ 0x60 /* CLK = 24.0000Mhz, max speed
+ * = 1.5 Mbps */
+#define MCS7840_DEV_SPx_CLOCK_48MHZ 0x70 /* CLK = 48.0000Mhz, max speed
+ * = 3.0 Mbps */
+#define MCS7840_DEV_SPx_CLOCK_SHIFT 4 /* Value 0..7 can be shifted
+ * to get clock value */
+#define MCS7840_DEV_SPx_UART_RESET 0x80 /* Reset UART */
+
+/* Bits for CONTROLx registers */
+#define MCS7840_DEV_CONTROLx_HWFC 0x01 /* Enable hardware flow
+ * control (when power
+ * down? It is unclear
+ * in documents),
+ * default = 0 */
+#define MCS7840_DEV_CONTROLx_UNUNSED1 0x02 /* Reserved */
+#define MCS7840_DEV_CONTROLx_CTS_ENABLE 0x04 /* CTS changes are
+ * translated to MSR,
+ * default = 0 */
+#define MCS7840_DEV_CONTROLx_UNUSED2 0x08 /* Reserved for ports
+ * 2,3,4 */
+#define MCS7840_DEV_CONTROL1_DRIVER_DONE 0x08 /* USB enumerating is
+ * finished, USB
+ * enumeration memory
+ * can be used as FIFOs */
+#define MCS7840_DEV_CONTROLx_RX_NEGATE 0x10 /* Negate RX input,
+ * works for IrDA mode
+ * only, default = 0 */
+#define MCS7840_DEV_CONTROLx_RX_DISABLE 0x20 /* Disable RX logic,
+ * works only for
+ * RS-232/RS-485 mode,
+ * default = 0 */
+#define MCS7840_DEV_CONTROLx_FSM_CONTROL 0x40 /* Disable RX FSM when
+ * TX is in progress,
+ * works for IrDA mode
+ * only, default = 0 */
+#define MCS7840_DEV_CONTROLx_UNUSED3 0x80 /* Reserved */
+
+/*
+ * Bits for PINPONGx registers
+ * These registers control how often two input buffers
+ * for Bulk-In FIFOs are swapped. One of buffers is used
+ * for USB trnasfer, other for receiving data from UART.
+ * Exact meaning of 15 bit value in these registers is unknown
+ */
+#define MCS7840_DEV_PINPONGHIGH_MULT 128 /* Only 7 bits in PINPONGLOW
+ * register */
+#define MCS7840_DEV_PINPONGLOW_BITS 7 /* Only 7 bits in PINPONGLOW
+ * register */
+
+/*
+ * THIS ONE IS UNDOCUMENTED IN FULL DATASHEET, but e-mail from tech support
+ * confirms, that it is register for GPIO_0 and GPIO_1 data input/output.
+ * Chips has 2 GPIO, but first one (lower bit) MUST be used by device
+ * authors as "number of port" indicator, grounded (0) for two-port
+ * devices and pulled-up to 1 for 4-port devices.
+ */
+#define MCS7840_DEV_GPIO_4PORTS 0x01 /* Device has 4 ports
+ * configured */
+#define MCS7840_DEV_GPIO_GPIO_0 0x01 /* The same as above */
+#define MCS7840_DEV_GPIO_GPIO_1 0x02 /* GPIO_1 data */
+
+/*
+ * Constants for PLL dividers
+ * Ouptut frequency of PLL is:
+ * Fout = (N/M) * Fin.
+ * Default PLL input frequency Fin is 12Mhz (on-chip).
+ */
+#define MCS7840_DEV_PLL_DIV_M_BITS 6 /* Number of useful bits for M
+ * divider */
+#define MCS7840_DEV_PLL_DIV_M_MASK 0x3f /* Mask for M divider */
+#define MCS7840_DEV_PLL_DIV_M_MIN 1 /* Minimum value for M, 0 is
+ * forbidden */
+#define MCS7840_DEV_PLL_DIV_M_DEF 1 /* Default value for M */
+#define MCS7840_DEV_PLL_DIV_M_MAX 63 /* Maximum value for M */
+#define MCS7840_DEV_PLL_DIV_N_BITS 6 /* Number of useful bits for N
+ * divider */
+#define MCS7840_DEV_PLL_DIV_N_MASK 0x3f /* Mask for N divider */
+#define MCS7840_DEV_PLL_DIV_N_MIN 1 /* Minimum value for N, 0 is
+ * forbidden */
+#define MCS7840_DEV_PLL_DIV_N_DEF 8 /* Default value for N */
+#define MCS7840_DEV_PLL_DIV_N_MAX 63 /* Maximum value for N */
+
+/* Bits for CLOCK_MUX register */
+#define MCS7840_DEV_CLOCK_MUX_INPUTMASK 0x03 /* Mask to extract PLL clock
+ * input */
+#define MCS7840_DEV_CLOCK_MUX_IN12MHZ 0x00 /* 12Mhz PLL input, default */
+#define MCS7840_DEV_CLOCK_MUX_INEXTRN 0x01 /* External (device-depended)
+ * PLL input */
+#define MCS7840_DEV_CLOCK_MUX_INRSV1 0x02 /* Reserved */
+#define MCS7840_DEV_CLOCK_MUX_INRSV2 0x03 /* Reserved */
+#define MCS7840_DEV_CLOCK_MUX_PLLHIGH 0x04 /* 0 = PLL Output is
+ * 20MHz-100MHz (default), 1 =
+ * 100MHz-300MHz range */
+#define MCS7840_DEV_CLOCK_MUX_INTRFIFOS 0x08 /* Enable additional 8 bytes
+ * fro Interrupt USB pipe with
+ * USB FIFOs statuses, default
+ * = 0 */
+#define MCS7840_DEV_CLOCK_MUX_RESERVED1 0x10 /* Unused */
+#define MCS7840_DEV_CLOCK_MUX_RESERVED2 0x20 /* Unused */
+#define MCS7840_DEV_CLOCK_MUX_RESERVED3 0x40 /* Unused */
+#define MCS7840_DEV_CLOCK_MUX_RESERVED4 0x80 /* Unused */
+
+/* Bits for CLOCK_SELECTxx registers */
+#define MCS7840_DEV_CLOCK_SELECT1_MASK 0x07 /* Bits for port 1 in
+ * CLOCK_SELECT12 */
+#define MCS7840_DEV_CLOCK_SELECT1_SHIFT 0 /* Shift for port 1in
+ * CLOCK_SELECT12 */
+#define MCS7840_DEV_CLOCK_SELECT2_MASK 0x38 /* Bits for port 2 in
+ * CLOCK_SELECT12 */
+#define MCS7840_DEV_CLOCK_SELECT2_SHIFT 3 /* Shift for port 2 in
+ * CLOCK_SELECT12 */
+#define MCS7840_DEV_CLOCK_SELECT3_MASK 0x07 /* Bits for port 3 in
+ * CLOCK_SELECT23 */
+#define MCS7840_DEV_CLOCK_SELECT3_SHIFT 0 /* Shift for port 3 in
+ * CLOCK_SELECT23 */
+#define MCS7840_DEV_CLOCK_SELECT4_MASK 0x38 /* Bits for port 4 in
+ * CLOCK_SELECT23 */
+#define MCS7840_DEV_CLOCK_SELECT4_SHIFT 3 /* Shift for port 4 in
+ * CLOCK_SELECT23 */
+#define MCS7840_DEV_CLOCK_SELECT_STD 0x00 /* STANDARD baudrate derived
+ * from 96Mhz, default for all
+ * ports */
+#define MCS7840_DEV_CLOCK_SELECT_30MHZ 0x01 /* 30Mhz */
+#define MCS7840_DEV_CLOCK_SELECT_96MHZ 0x02 /* 96Mhz direct */
+#define MCS7840_DEV_CLOCK_SELECT_120MHZ 0x03 /* 120Mhz */
+#define MCS7840_DEV_CLOCK_SELECT_PLL 0x04 /* PLL output (see for M and N
+ * dividers) */
+#define MCS7840_DEV_CLOCK_SELECT_EXT 0x05 /* External clock input
+ * (device-dependend) */
+#define MCS7840_DEV_CLOCK_SELECT_RES1 0x06 /* Unused */
+#define MCS7840_DEV_CLOCK_SELECT_RES2 0x07 /* Unused */
+
+/* Bits for MODE register */
+#define MCS7840_DEV_MODE_RESERVED1 0x01 /* Unused */
+#define MCS7840_DEV_MODE_RESET 0x02 /* 0: RESET = Active High
+ * (default), 1: Reserved (?) */
+#define MCS7840_DEV_MODE_SER_PRSNT 0x04 /* 0: Reserved, 1: Do not use
+ * hardocded values (default)
+ * (?) */
+#define MCS7840_DEV_MODE_PLLBYPASS 0x08 /* 1: PLL output is bypassed,
+ * default = 0 */
+#define MCS7840_DEV_MODE_PORBYPASS 0x10 /* 1: Power-On Reset is
+ * bypassed, default = 0 */
+#define MCS7840_DEV_MODE_SELECT24S 0x20 /* 0: 4 Serial Ports / IrDA
+ * active, 1: 2 Serial Ports /
+ * IrDA active */
+#define MCS7840_DEV_MODE_EEPROMWR 0x40 /* EEPROM write is enabled,
+ * default */
+#define MCS7840_DEV_MODE_IRDA 0x80 /* IrDA mode is activated
+ * (could be turned on),
+ * default */
+
+/* Bits for SPx ICG */
+#define MCS7840_DEV_SPx_ICG_DEF 0x24 /* All 8 bits is used as
+ * number of BAUD clocks of
+ * pause */
+
+/*
+ * Bits for RX_SAMPLINGxx registers
+ * These registers control when bit value will be sampled within
+ * the baud period.
+ * 0 is very beginning of period, 15 is very end, 7 is the middle.
+ */
+#define MCS7840_DEV_RX_SAMPLING1_MASK 0x0f /* Bits for port 1 in
+ * RX_SAMPLING12 */
+#define MCS7840_DEV_RX_SAMPLING1_SHIFT 0 /* Shift for port 1in
+ * RX_SAMPLING12 */
+#define MCS7840_DEV_RX_SAMPLING2_MASK 0xf0 /* Bits for port 2 in
+ * RX_SAMPLING12 */
+#define MCS7840_DEV_RX_SAMPLING2_SHIFT 4 /* Shift for port 2 in
+ * RX_SAMPLING12 */
+#define MCS7840_DEV_RX_SAMPLING3_MASK 0x0f /* Bits for port 3 in
+ * RX_SAMPLING23 */
+#define MCS7840_DEV_RX_SAMPLING3_SHIFT 0 /* Shift for port 3 in
+ * RX_SAMPLING23 */
+#define MCS7840_DEV_RX_SAMPLING4_MASK 0xf0 /* Bits for port 4 in
+ * RX_SAMPLING23 */
+#define MCS7840_DEV_RX_SAMPLING4_SHIFT 4 /* Shift for port 4 in
+ * RX_SAMPLING23 */
+#define MCS7840_DEV_RX_SAMPLINGx_MIN 0 /* Max for any RX Sampling */
+#define MCS7840_DEV_RX_SAMPLINGx_DEF 7 /* Default for any RX
+ * Sampling, center of period */
+#define MCS7840_DEV_RX_SAMPLINGx_MAX 15 /* Min for any RX Sampling */
+
+/* Bits for ZERO_PERIODx */
+#define MCS7840_DEV_ZERO_PERIODx_DEF 20 /* Number of Bulk-in requests
+ * befor sending zero-sized
+ * reply */
+
+/* Bits for ZERO_ENABLE */
+#define MCS7840_DEV_ZERO_ENABLE_PORT1 0x01 /* Enable of sending
+ * zero-sized replies for port
+ * 1, default */
+#define MCS7840_DEV_ZERO_ENABLE_PORT2 0x02 /* Enable of sending
+ * zero-sized replies for port
+ * 2, default */
+#define MCS7840_DEV_ZERO_ENABLE_PORT3 0x04 /* Enable of sending
+ * zero-sized replies for port
+ * 3, default */
+#define MCS7840_DEV_ZERO_ENABLE_PORT4 0x08 /* Enable of sending
+ * zero-sized replies for port
+ * 4, default */
+
+/* Bits for THR_VAL_HIGHx */
+#define MCS7840_DEV_THR_VAL_HIGH_MASK 0x01 /* Only one bit is used */
+#define MCS7840_DEV_THR_VAL_HIGH_MUL 256 /* This one bit is means "256" */
+#define MCS7840_DEV_THR_VAL_HIGH_SHIFT 8 /* This one bit is means "256" */
+#define MCS7840_DEV_THR_VAL_HIGH_ENABLE 0x80 /* Enable threshold */
+
+/* These are documented in "public" datasheet */
+#define MCS7840_DEV_REG_DCR0_1 0x04 /* Device contol register 0 for Port
+ * 1, R/W */
+#define MCS7840_DEV_REG_DCR1_1 0x05 /* Device contol register 1 for Port
+ * 1, R/W */
+#define MCS7840_DEV_REG_DCR2_1 0x06 /* Device contol register 2 for Port
+ * 1, R/W */
+#define MCS7840_DEV_REG_DCR0_2 0x16 /* Device contol register 0 for Port
+ * 2, R/W */
+#define MCS7840_DEV_REG_DCR1_2 0x17 /* Device contol register 1 for Port
+ * 2, R/W */
+#define MCS7840_DEV_REG_DCR2_2 0x18 /* Device contol register 2 for Port
+ * 2, R/W */
+#define MCS7840_DEV_REG_DCR0_3 0x19 /* Device contol register 0 for Port
+ * 3, R/W */
+#define MCS7840_DEV_REG_DCR1_3 0x1a /* Device contol register 1 for Port
+ * 3, R/W */
+#define MCS7840_DEV_REG_DCR2_3 0x1b /* Device contol register 2 for Port
+ * 3, R/W */
+#define MCS7840_DEV_REG_DCR0_4 0x1c /* Device contol register 0 for Port
+ * 4, R/W */
+#define MCS7840_DEV_REG_DCR1_4 0x1d /* Device contol register 1 for Port
+ * 4, R/W */
+#define MCS7840_DEV_REG_DCR2_4 0x1e /* Device contol register 2 for Port
+ * 4, R/W */
+
+/* Bits of DCR0 registers, documented in datasheet */
+#define MCS7840_DEV_DCR0_PWRSAVE 0x01 /* Shutdown transiver
+ * when USB Suspend is
+ * engaged, default = 1 */
+#define MCS7840_DEV_DCR0_RESERVED1 0x02 /* Unused */
+#define MCS7840_DEV_DCR0_GPIO_MODE_MASK 0x0c /* GPIO Mode bits, WORKS
+ * ONLY FOR PORT 1 */
+#define MCS7840_DEV_DCR0_GPIO_MODE_IN 0x00 /* GPIO Mode - Input
+ * (0b00), WORKS ONLY
+ * FOR PORT 1 */
+#define MCS7840_DEV_DCR0_GPIO_MODE_OUT 0x08 /* GPIO Mode - Input
+ * (0b10), WORKS ONLY
+ * FOR PORT 1 */
+#define MCS7840_DEV_DCR0_RTS_ACTIVE_HIGH 0x10 /* RTS Active is HIGH,
+ * default = 0 (low) */
+#define MCS7840_DEV_DCR0_RTS_AUTO 0x20 /* RTS is controlled by
+ * state of TX buffer,
+ * default = 0
+ * (controlled by MCR) */
+#define MCS7840_DEV_DCR0_IRDA 0x40 /* IrDA mode */
+#define MCS7840_DEV_DCR0_RESERVED2 0x80 /* Unused */
+
+/* Bits of DCR1 registers, documented in datasheet */
+#define MCS7840_DEV_DCR1_GPIO_CURRENT_MASK 0x03 /* Mask to extract GPIO
+ * current value, WORKS
+ * ONLY FOR PORT 1 */
+#define MCS7840_DEV_DCR1_GPIO_CURRENT_6MA 0x00 /* GPIO output current
+ * 6mA, WORKS ONLY FOR
+ * PORT 1 */
+#define MCS7840_DEV_DCR1_GPIO_CURRENT_8MA 0x01 /* GPIO output current
+ * 8mA, defauilt, WORKS
+ * ONLY FOR PORT 1 */
+#define MCS7840_DEV_DCR1_GPIO_CURRENT_10MA 0x02 /* GPIO output current
+ * 10mA, WORKS ONLY FOR
+ * PORT 1 */
+#define MCS7840_DEV_DCR1_GPIO_CURRENT_12MA 0x03 /* GPIO output current
+ * 12mA, WORKS ONLY FOR
+ * PORT 1 */
+#define MCS7840_DEV_DCR1_UART_CURRENT_MASK 0x0c /* Mask to extract UART
+ * signals current value */
+#define MCS7840_DEV_DCR1_UART_CURRENT_6MA 0x00 /* UART output current
+ * 6mA */
+#define MCS7840_DEV_DCR1_UART_CURRENT_8MA 0x04 /* UART output current
+ * 8mA, defauilt */
+#define MCS7840_DEV_DCR1_UART_CURRENT_10MA 0x08 /* UART output current
+ * 10mA */
+#define MCS7840_DEV_DCR1_UART_CURRENT_12MA 0x0c /* UART output current
+ * 12mA */
+#define MCS7840_DEV_DCR1_WAKEUP_DISABLE 0x10 /* Disable Remote USB
+ * Wakeup */
+#define MCS7840_DEV_DCR1_PLLPWRDOWN_DISABLE 0x20 /* Disable PLL power
+ * down when not needed,
+ * WORKS ONLY FOR PORT 1 */
+#define MCS7840_DEV_DCR1_LONG_INTERRUPT 0x40 /* Enable 13 bytes of
+ * interrupt data, with
+ * FIFO statistics,
+ * WORKS ONLY FOR PORT 1 */
+#define MCS7840_DEV_DCR1_RESERVED1 0x80 /* Unused */
+
+/*
+ * Bits of DCR2 registers, documented in datasheet
+ * Wakeup will work only if DCR0_IRDA = 0 (RS-xxx mode) and
+ * DCR1_WAKEUP_DISABLE = 0 (wakeup enabled).
+ */
+#define MCS7840_DEV_DCR2_WAKEUP_CTS 0x01 /* Wakeup on CTS change,
+ * default = 0 */
+#define MCS7840_DEV_DCR2_WAKEUP_DCD 0x02 /* Wakeup on DCD change,
+ * default = 0 */
+#define MCS7840_DEV_DCR2_WAKEUP_RI 0x04 /* Wakeup on RI change,
+ * default = 1 */
+#define MCS7840_DEV_DCR2_WAKEUP_DSR 0x08 /* Wakeup on DSR change,
+ * default = 0 */
+#define MCS7840_DEV_DCR2_WAKEUP_RXD 0x10 /* Wakeup on RX Data change,
+ * default = 0 */
+#define MCS7840_DEV_DCR2_WAKEUP_RESUME 0x20 /* Wakeup issues RESUME
+ * signal, DISCONNECT
+ * otherwise, default = 1 */
+#define MCS7840_DEV_DCR2_RESERVED1 0x40 /* Unused */
+#define MCS7840_DEV_DCR2_SHDN_POLARITY 0x80 /* 0: Pin 12 Active Low, 1:
+ * Pin 12 Active High, default
+ * = 0 */
+
+/* Interrupt endpoint bytes & bits */
+#define MCS7840_IEP_FIFO_STATUS_INDEX 5
+/*
+ * Thesse can be calculated as "1 << portnumber" for Bulk-out and
+ * "1 << (portnumber+1)" for Bulk-in
+ */
+#define MCS7840_IEP_BO_PORT1_HASDATA 0x01
+#define MCS7840_IEP_BI_PORT1_HASDATA 0x02
+#define MCS7840_IEP_BO_PORT2_HASDATA 0x04
+#define MCS7840_IEP_BI_PORT2_HASDATA 0x08
+#define MCS7840_IEP_BO_PORT3_HASDATA 0x10
+#define MCS7840_IEP_BI_PORT3_HASDATA 0x20
+#define MCS7840_IEP_BO_PORT4_HASDATA 0x40
+#define MCS7840_IEP_BI_PORT4_HASDATA 0x80
+
+/* Documented UART registers (fully compatible with 16550 UART) */
+#define MCS7840_UART_REG_THR 0x00 /* Transmitter Holding
+ * Register W/Only */
+#define MCS7840_UART_REG_RHR 0x00 /* Receiver Holding Register
+ * R/Only */
+#define MCS7840_UART_REG_IER 0x01 /* Interrupt enable register -
+ * R/W */
+#define MCS7840_UART_REG_FCR 0x02 /* FIFO Control register -
+ * W/Only */
+#define MCS7840_UART_REG_ISR 0x02 /* Interrupt Status Registter
+ * R/Only */
+#define MCS7840_UART_REG_LCR 0x03 /* Line control register R/W */
+#define MCS7840_UART_REG_MCR 0x04 /* Modem control register R/W */
+#define MCS7840_UART_REG_LSR 0x05 /* Line status register R/Only */
+#define MCS7840_UART_REG_MSR 0x06 /* Modem status register
+ * R/Only */
+#define MCS7840_UART_REG_SCRATCHPAD 0x07 /* Scratch pad register */
+
+#define MCS7840_UART_REG_DLL 0x00 /* Low bits of BAUD divider */
+#define MCS7840_UART_REG_DLM 0x01 /* High bits of BAUD divider */
+
+/* IER bits */
+#define MCS7840_UART_IER_RXREADY 0x01 /* RX Ready interrumpt mask */
+#define MCS7840_UART_IER_TXREADY 0x02 /* TX Ready interrumpt mask */
+#define MCS7840_UART_IER_RXSTAT 0x04 /* RX Status interrumpt mask */
+#define MCS7840_UART_IER_MODEM 0x08 /* Modem status change
+ * interrumpt mask */
+#define MCS7840_UART_IER_SLEEP 0x10 /* SLEEP enable */
+
+/* FCR bits */
+#define MCS7840_UART_FCR_ENABLE 0x01 /* Enable FIFO */
+#define MCS7840_UART_FCR_FLUSHRHR 0x02 /* Flush RHR and FIFO */
+#define MCS7840_UART_FCR_FLUSHTHR 0x04 /* Flush THR and FIFO */
+#define MCS7840_UART_FCR_RTLMASK 0xa0 /* Mask to select RHR
+ * Interrupt Trigger level */
+#define MCS7840_UART_FCR_RTL_1_1 0x00 /* L1 = 1, L2 = 1 */
+#define MCS7840_UART_FCR_RTL_1_4 0x40 /* L1 = 1, L2 = 4 */
+#define MCS7840_UART_FCR_RTL_1_8 0x80 /* L1 = 1, L2 = 8 */
+#define MCS7840_UART_FCR_RTL_1_14 0xa0 /* L1 = 1, L2 = 14 */
+
+/* ISR bits */
+#define MCS7840_UART_ISR_NOPENDING 0x01 /* No interrupt pending */
+#define MCS7840_UART_ISR_INTMASK 0x3f /* Mask to select interrupt
+ * source */
+#define MCS7840_UART_ISR_RXERR 0x06 /* Recevir error */
+#define MCS7840_UART_ISR_RXHASDATA 0x04 /* Recevier has data */
+#define MCS7840_UART_ISR_RXTIMEOUT 0x0c /* Recevier timeout */
+#define MCS7840_UART_ISR_TXEMPTY 0x02 /* Transmitter empty */
+#define MCS7840_UART_ISR_MSCHANGE 0x00 /* Modem status change */
+
+/* LCR bits */
+#define MCS7840_UART_LCR_DATALENMASK 0x03 /* Mask for data length */
+#define MCS7840_UART_LCR_DATALEN5 0x00 /* 5 data bits */
+#define MCS7840_UART_LCR_DATALEN6 0x01 /* 6 data bits */
+#define MCS7840_UART_LCR_DATALEN7 0x02 /* 7 data bits */
+#define MCS7840_UART_LCR_DATALEN8 0x03 /* 8 data bits */
+
+#define MCS7840_UART_LCR_STOPBMASK 0x04 /* Mask for stop bits */
+#define MCS7840_UART_LCR_STOPB1 0x00 /* 1 stop bit in any case */
+#define MCS7840_UART_LCR_STOPB2 0x04 /* 1.5-2 stop bits depends on
+ * data length */
+
+#define MCS7840_UART_LCR_PARITYMASK 0x38 /* Mask for all parity data */
+#define MCS7840_UART_LCR_PARITYON 0x08 /* Parity ON/OFF - ON */
+#define MCS7840_UART_LCR_PARITYODD 0x00 /* Parity Odd */
+#define MCS7840_UART_LCR_PARITYEVEN 0x10 /* Parity Even */
+#define MCS7840_UART_LCR_PARITYODD 0x00 /* Parity Odd */
+#define MCS7840_UART_LCR_PARITYFORCE 0x20 /* Force parity odd/even */
+
+#define MCS7840_UART_LCR_BREAK 0x40 /* Send BREAK */
+#define MCS7840_UART_LCR_DIVISORS 0x80 /* Map DLL/DLM instead of
+ * xHR/IER */
+
+/* LSR bits */
+#define MCS7840_UART_LSR_RHRAVAIL 0x01 /* Data available for read */
+#define MCS7840_UART_LSR_RHROVERRUN 0x02 /* Data FIFO/register overflow */
+#define MCS7840_UART_LSR_PARITYERR 0x04 /* Parity error */
+#define MCS7840_UART_LSR_FRAMEERR 0x10 /* Framing error */
+#define MCS7840_UART_LSR_BREAKERR 0x20 /* BREAK sigmal received */
+#define MCS7840_UART_LSR_THREMPTY 0x40 /* THR register is empty,
+ * ready for transmit */
+#define MCS7840_UART_LSR_HASERR 0x80 /* Has error in receiver FIFO */
+
+/* MCR bits */
+#define MCS7840_UART_MCR_DTR 0x01 /* Force DTR to be active
+ * (low) */
+#define MCS7840_UART_MCR_RTS 0x02 /* Force RTS to be active
+ * (low) */
+#define MCS7840_UART_MCR_IE 0x04 /* Enable interrupts (from
+ * code, not documented) */
+#define MCS7840_UART_MCR_LOOPBACK 0x10 /* Enable local loopback test
+ * mode */
+#define MCS7840_UART_MCR_CTSRTS 0x20 /* Enable CTS/RTS flow control
+ * in 550 (FIFO) mode */
+#define MCS7840_UART_MCR_DTRDSR 0x40 /* Enable DTR/DSR flow control
+ * in 550 (FIFO) mode */
+#define MCS7840_UART_MCR_DCD 0x80 /* Enable DCD flow control in
+ * 550 (FIFO) mode */
+
+/* MSR bits */
+#define MCS7840_UART_MSR_DELTACTS 0x01 /* CTS was changed since last
+ * read */
+#define MCS7840_UART_MSR_DELTADSR 0x02 /* DSR was changed since last
+ * read */
+#define MCS7840_UART_MSR_DELTARI 0x04 /* RI was changed from low to
+ * high since last read */
+#define MCS7840_UART_MSR_DELTADCD 0x08 /* DCD was changed since last
+ * read */
+#define MCS7840_UART_MSR_NEGCTS 0x10 /* Negated CTS signal */
+#define MCS7840_UART_MSR_NEGDSR 0x20 /* Negated DSR signal */
+#define MCS7840_UART_MSR_NEGRI 0x40 /* Negated RI signal */
+#define MCS7840_UART_MSR_NEGDCD 0x80 /* Negated DCD signal */
+
+/* SCRATCHPAD bits */
+#define MCS7840_UART_SCRATCHPAD_RS232 0x00 /* RS-485 disabled */
+#define MCS7840_UART_SCRATCHPAD_RS485_DTRRX 0x80 /* RS-485 mode, DTR High
+ * = RX */
+#define MCS7840_UART_SCRATCHPAD_RS485_DTRTX 0xc0 /* RS-485 mode, DTR High
+ * = TX */
+
+#define MCS7840_CONFIG_INDEX 0
+#define MCS7840_IFACE_INDEX 0
+
+#endif
diff --git a/sys/dev/usb/usb_process.c b/sys/dev/usb/usb_process.c
index 0509ec2..051ded9 100644
--- a/sys/dev/usb/usb_process.c
+++ b/sys/dev/usb/usb_process.c
@@ -360,7 +360,12 @@ usb_proc_is_gone(struct usb_process *up)
if (up->up_gone)
return (1);
- mtx_assert(up->up_mtx, MA_OWNED);
+ /*
+ * Allow calls when up_mtx is NULL, before the USB process
+ * structure is initialised.
+ */
+ if (up->up_mtx != NULL)
+ mtx_assert(up->up_mtx, MA_OWNED);
return (0);
}
diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs
index eb49eb2..a970206 100644
--- a/sys/dev/usb/usbdevs
+++ b/sys/dev/usb/usbdevs
@@ -2273,7 +2273,9 @@ product MOBILITY EASIDOCK 0x0304 EasiDock Ethernet
/* MosChip products */
product MOSCHIP MCS7703 0x7703 MCS7703 Serial Port Adapter
product MOSCHIP MCS7730 0x7730 MCS7730 Ethernet
+product MOSCHIP MCS7820 0x7820 MCS7820 Serial Port Adapter
product MOSCHIP MCS7830 0x7830 MCS7830 Ethernet
+product MOSCHIP MCS7840 0x7840 MCS7840 Serial Port Adapter
/* Motorola products */
product MOTOROLA MC141555 0x1555 MC141555 hub controller
diff --git a/sys/dev/wpi/if_wpi.c b/sys/dev/wpi/if_wpi.c
index e1fffe1..38ebb7e 100644
--- a/sys/dev/wpi/if_wpi.c
+++ b/sys/dev/wpi/if_wpi.c
@@ -273,6 +273,8 @@ static devclass_t wpi_devclass;
DRIVER_MODULE(wpi, pci, wpi_driver, wpi_devclass, 0, 0);
+MODULE_VERSION(wpi, 1);
+
static const uint8_t wpi_ridx_to_plcp[] = {
/* OFDM: IEEE Std 802.11a-1999, pp. 14 Table 80 */
/* R1-R4 (ral/ural is R4-R1) */
diff --git a/sys/fs/nfsclient/nfs_clbio.c b/sys/fs/nfsclient/nfs_clbio.c
index fee8b05..95138ec 100644
--- a/sys/fs/nfsclient/nfs_clbio.c
+++ b/sys/fs/nfsclient/nfs_clbio.c
@@ -302,7 +302,7 @@ ncl_putpages(struct vop_putpages_args *ap)
}
for (i = 0; i < npages; i++)
- rtvals[i] = VM_PAGER_AGAIN;
+ rtvals[i] = VM_PAGER_ERROR;
/*
* When putting pages, do not extend file past EOF.
@@ -345,16 +345,9 @@ ncl_putpages(struct vop_putpages_args *ap)
pmap_qremove(kva, npages);
relpbuf(bp, &ncl_pbuf_freecnt);
- if (!error) {
- int nwritten = round_page(count - uio.uio_resid) / PAGE_SIZE;
- for (i = 0; i < nwritten; i++) {
- rtvals[i] = VM_PAGER_OK;
- vm_page_undirty(pages[i]);
- }
- if (must_commit) {
- ncl_clearcommit(vp->v_mount);
- }
- }
+ vnode_pager_undirty_pages(pages, rtvals, count - uio.uio_resid);
+ if (must_commit)
+ ncl_clearcommit(vp->v_mount);
return rtvals[0];
}
diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c
index 3ec12ca..984724d 100644
--- a/sys/fs/nfsclient/nfs_clvnops.c
+++ b/sys/fs/nfsclient/nfs_clvnops.c
@@ -3293,7 +3293,13 @@ nfs_pathconf(struct vop_pathconf_args *ap)
struct thread *td = curthread;
int attrflag, error;
- if (NFS_ISV34(vp)) {
+ if (NFS_ISV4(vp) || (NFS_ISV3(vp) && (ap->a_name == _PC_LINK_MAX ||
+ ap->a_name == _PC_NAME_MAX || ap->a_name == _PC_CHOWN_RESTRICTED ||
+ ap->a_name == _PC_NO_TRUNC))) {
+ /*
+ * Since only the above 4 a_names are returned by the NFSv3
+ * Pathconf RPC, there is no point in doing it for others.
+ */
error = nfsrpc_pathconf(vp, &pc, td->td_ucred, td, &nfsva,
&attrflag, NULL);
if (attrflag != 0)
@@ -3302,7 +3308,10 @@ nfs_pathconf(struct vop_pathconf_args *ap)
if (error != 0)
return (error);
} else {
- /* For NFSv2, just fake them. */
+ /*
+ * For NFSv2 (or NFSv3 when not one of the above 4 a_names),
+ * just fake them.
+ */
pc.pc_linkmax = LINK_MAX;
pc.pc_namemax = NFS_MAXNAMLEN;
pc.pc_notrunc = 1;
diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c
index d62be99..5b96729 100644
--- a/sys/fs/nfsserver/nfs_nfsdport.c
+++ b/sys/fs/nfsserver/nfs_nfsdport.c
@@ -2592,6 +2592,36 @@ nfsvno_pathconf(struct vnode *vp, int flag, register_t *retf,
int error;
error = VOP_PATHCONF(vp, flag, retf);
+ if (error == EOPNOTSUPP || error == EINVAL) {
+ /*
+ * Some file systems return EINVAL for name arguments not
+ * supported and some return EOPNOTSUPP for this case.
+ * So the NFSv3 Pathconf RPC doesn't fail for these cases,
+ * just fake them.
+ */
+ switch (flag) {
+ case _PC_LINK_MAX:
+ *retf = LINK_MAX;
+ break;
+ case _PC_NAME_MAX:
+ *retf = NAME_MAX;
+ break;
+ case _PC_CHOWN_RESTRICTED:
+ *retf = 1;
+ break;
+ case _PC_NO_TRUNC:
+ *retf = 1;
+ break;
+ default:
+ /*
+ * Only happens if a _PC_xxx is added to the server,
+ * but this isn't updated.
+ */
+ *retf = 0;
+ printf("nfsrvd pathconf flag=%d not supp\n", flag);
+ };
+ error = 0;
+ }
return (error);
}
diff --git a/sys/fs/nwfs/nwfs_io.c b/sys/fs/nwfs/nwfs_io.c
index 141c52e..d764f79 100644
--- a/sys/fs/nwfs/nwfs_io.c
+++ b/sys/fs/nwfs/nwfs_io.c
@@ -544,7 +544,7 @@ nwfs_putpages(ap)
npages = btoc(count);
for (i = 0; i < npages; i++) {
- rtvals[i] = VM_PAGER_AGAIN;
+ rtvals[i] = VM_PAGER_ERROR;
}
bp = getpbuf(&nwfs_pbuf_freecnt);
@@ -569,13 +569,8 @@ nwfs_putpages(ap)
pmap_qremove(kva, npages);
relpbuf(bp, &nwfs_pbuf_freecnt);
- if (!error) {
- int nwritten = round_page(count - uio.uio_resid) / PAGE_SIZE;
- for (i = 0; i < nwritten; i++) {
- rtvals[i] = VM_PAGER_OK;
- vm_page_undirty(pages[i]);
- }
- }
+ if (!error)
+ vnode_pager_undirty_pages(pages, rtvals, count - uio.uio_resid);
return rtvals[0];
#endif /* NWFS_RWCACHE */
}
diff --git a/sys/fs/smbfs/smbfs_io.c b/sys/fs/smbfs/smbfs_io.c
index 6c02fc6..4599a6f 100644
--- a/sys/fs/smbfs/smbfs_io.c
+++ b/sys/fs/smbfs/smbfs_io.c
@@ -609,7 +609,7 @@ smbfs_putpages(ap)
npages = btoc(count);
for (i = 0; i < npages; i++) {
- rtvals[i] = VM_PAGER_AGAIN;
+ rtvals[i] = VM_PAGER_ERROR;
}
bp = getpbuf(&smbfs_pbuf_freecnt);
@@ -639,13 +639,8 @@ smbfs_putpages(ap)
relpbuf(bp, &smbfs_pbuf_freecnt);
- if (!error) {
- int nwritten = round_page(count - uio.uio_resid) / PAGE_SIZE;
- for (i = 0; i < nwritten; i++) {
- rtvals[i] = VM_PAGER_OK;
- vm_page_undirty(pages[i]);
- }
- }
+ if (!error)
+ vnode_pager_undirty_pages(pages, rtvals, count - uio.uio_resid);
return rtvals[0];
#endif /* SMBFS_RWGENERIC */
}
diff --git a/sys/geom/geom_disk.c b/sys/geom/geom_disk.c
index a051772..e663e3d 100644
--- a/sys/geom/geom_disk.c
+++ b/sys/geom/geom_disk.c
@@ -154,6 +154,12 @@ g_disk_access(struct g_provider *pp, int r, int w, int e)
}
pp->mediasize = dp->d_mediasize;
pp->sectorsize = dp->d_sectorsize;
+ if (dp->d_flags & DISKFLAG_CANDELETE)
+ pp->flags |= G_PF_CANDELETE;
+ else
+ pp->flags &= ~G_PF_CANDELETE;
+ pp->stripeoffset = dp->d_stripeoffset;
+ pp->stripesize = dp->d_stripesize;
dp->d_flags |= DISKFLAG_OPEN;
if (dp->d_maxsize == 0) {
printf("WARNING: Disk drive %s%d has no d_maxsize\n",
diff --git a/sys/geom/geom_dump.c b/sys/geom/geom_dump.c
index d1e56d6..6f678cf 100644
--- a/sys/geom/geom_dump.c
+++ b/sys/geom/geom_dump.c
@@ -207,10 +207,8 @@ g_conf_provider(struct sbuf *sb, struct g_provider *pp)
sbuf_printf(sb, "\t <mediasize>%jd</mediasize>\n",
(intmax_t)pp->mediasize);
sbuf_printf(sb, "\t <sectorsize>%u</sectorsize>\n", pp->sectorsize);
- if (pp->stripesize > 0) {
- sbuf_printf(sb, "\t <stripesize>%u</stripesize>\n", pp->stripesize);
- sbuf_printf(sb, "\t <stripeoffset>%u</stripeoffset>\n", pp->stripeoffset);
- }
+ sbuf_printf(sb, "\t <stripesize>%u</stripesize>\n", pp->stripesize);
+ sbuf_printf(sb, "\t <stripeoffset>%u</stripeoffset>\n", pp->stripeoffset);
if (pp->geom->flags & G_GEOM_WITHER)
;
else if (pp->geom->dumpconf != NULL) {
diff --git a/sys/geom/part/g_part.c b/sys/geom/part/g_part.c
index a3f8575..f24e7b5 100644
--- a/sys/geom/part/g_part.c
+++ b/sys/geom/part/g_part.c
@@ -248,6 +248,7 @@ g_part_check_integrity(struct g_part_table *table, struct g_consumer *cp)
{
struct g_part_entry *e1, *e2;
struct g_provider *pp;
+ off_t offset;
int failed;
failed = 0;
@@ -294,6 +295,16 @@ g_part_check_integrity(struct g_part_table *table, struct g_consumer *cp)
(intmax_t)table->gpt_last);
failed++;
}
+ if (pp->stripesize > 0) {
+ offset = e1->gpe_start * pp->sectorsize;
+ if (e1->gpe_offset > offset)
+ offset = e1->gpe_offset;
+ if ((offset + pp->stripeoffset) % pp->stripesize) {
+ DPRINTF("partition %d is not aligned on %u "
+ "bytes\n", e1->gpe_index, pp->stripesize);
+ /* Don't treat this as a critical failure */
+ }
+ }
e2 = e1;
while ((e2 = LIST_NEXT(e2, gpe_entry)) != NULL) {
if (e2->gpe_deleted || e2->gpe_internal)
@@ -723,7 +734,11 @@ g_part_ctl_add(struct gctl_req *req, struct g_part_parms *gpp)
if (gpp->gpp_parms & G_PART_PARM_OUTPUT) {
sb = sbuf_new_auto();
G_PART_FULLNAME(table, entry, sb, gp->name);
- sbuf_cat(sb, " added\n");
+ if (pp->stripesize > 0 && entry->gpe_pp->stripeoffset != 0)
+ sbuf_printf(sb, " added, but partition is not "
+ "aligned on %u bytes\n", pp->stripesize);
+ else
+ sbuf_cat(sb, " added\n");
sbuf_finish(sb);
gctl_set_param(req, "output", sbuf_data(sb), sbuf_len(sb) + 1);
sbuf_delete(sb);
diff --git a/sys/i386/pci/pci_cfgreg.c b/sys/i386/pci/pci_cfgreg.c
index ae56990..ac641a8 100644
--- a/sys/i386/pci/pci_cfgreg.c
+++ b/sys/i386/pci/pci_cfgreg.c
@@ -553,7 +553,7 @@ pcie_cfgregopen(uint64_t base, uint8_t minbus, uint8_t maxbus)
(uintmax_t)base);
#ifdef SMP
- SLIST_FOREACH(pc, &cpuhead, pc_allcpu)
+ STAILQ_FOREACH(pc, &cpuhead, pc_allcpu)
#endif
{
diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c
index 41d2211..7252865 100644
--- a/sys/ia64/ia64/machdep.c
+++ b/sys/ia64/ia64/machdep.c
@@ -316,7 +316,7 @@ cpu_startup(void *dummy)
/*
* Create sysctl tree for per-CPU information.
*/
- SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
+ STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
snprintf(nodename, sizeof(nodename), "%u", pc->pc_cpuid);
sysctl_ctx_init(&pc->pc_md.sysctl_ctx);
pc->pc_md.sysctl_tree = SYSCTL_ADD_NODE(&pc->pc_md.sysctl_ctx,
diff --git a/sys/ia64/ia64/mp_machdep.c b/sys/ia64/ia64/mp_machdep.c
index 5804f8c..b6b0bef 100644
--- a/sys/ia64/ia64/mp_machdep.c
+++ b/sys/ia64/ia64/mp_machdep.c
@@ -357,7 +357,7 @@ cpu_mp_start()
/* Keep 'em spinning until we unleash them... */
ia64_ap_state.as_spin = 1;
- SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
+ STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
pc->pc_md.current_pmap = kernel_pmap;
pc->pc_other_cpus = all_cpus & ~pc->pc_cpumask;
/* The BSP is obviously running already. */
@@ -424,7 +424,7 @@ cpu_mp_unleash(void *dummy)
cpus = 0;
smp_cpus = 0;
- SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
+ STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
cpus++;
if (pc->pc_md.awake) {
kproc_create(ia64_store_mca_state, pc, NULL, 0, 0,
@@ -462,7 +462,7 @@ ipi_selected(cpumask_t cpus, int ipi)
{
struct pcpu *pc;
- SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
+ STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
if (cpus & pc->pc_cpumask)
ipi_send(pc, ipi);
}
@@ -486,7 +486,7 @@ ipi_all_but_self(int ipi)
{
struct pcpu *pc;
- SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
+ STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
if (pc != pcpup)
ipi_send(pc, ipi);
}
diff --git a/sys/ia64/ia64/pmap.c b/sys/ia64/ia64/pmap.c
index 5f10ad6..411d53a 100644
--- a/sys/ia64/ia64/pmap.c
+++ b/sys/ia64/ia64/pmap.c
@@ -535,7 +535,7 @@ pmap_invalidate_page(vm_offset_t va)
critical_enter();
vhpt_ofs = ia64_thash(va) - PCPU_GET(md.vhpt);
tag = ia64_ttag(va);
- SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
+ STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
pte = (struct ia64_lpte *)(pc->pc_md.vhpt + vhpt_ofs);
atomic_cmpset_64(&pte->tag, tag, 1UL << 63);
}
diff --git a/sys/kern/kern_idle.c b/sys/kern/kern_idle.c
index af12d7d..f412d17 100644
--- a/sys/kern/kern_idle.c
+++ b/sys/kern/kern_idle.c
@@ -60,7 +60,7 @@ idle_setup(void *dummy)
p = NULL; /* start with no idle process */
#ifdef SMP
- SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
+ STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
#endif
#ifdef SMP
error = kproc_kthread_add(sched_idletd, NULL, &p, &td,
diff --git a/sys/kern/sched_4bsd.c b/sys/kern/sched_4bsd.c
index fef9e25..519cae5 100644
--- a/sys/kern/sched_4bsd.c
+++ b/sys/kern/sched_4bsd.c
@@ -1081,7 +1081,7 @@ forward_wakeup(int cpunum)
dontuse = me | stopped_cpus | hlt_cpus_mask;
map2 = 0;
if (forward_wakeup_use_loop) {
- SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
+ STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
id = pc->pc_cpumask;
if ((id & dontuse) == 0 &&
pc->pc_curthread == pc->pc_idlethread) {
@@ -1112,7 +1112,7 @@ forward_wakeup(int cpunum)
}
if (map) {
forward_wakeups_delivered++;
- SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
+ STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
id = pc->pc_cpumask;
if ((map & id) == 0)
continue;
diff --git a/sys/kern/subr_kdb.c b/sys/kern/subr_kdb.c
index 342c5ca..5d68ae2 100644
--- a/sys/kern/subr_kdb.c
+++ b/sys/kern/subr_kdb.c
@@ -412,7 +412,7 @@ kdb_thr_ctx(struct thread *thr)
return (&kdb_pcb);
#if defined(SMP) && defined(KDB_STOPPEDPCB)
- SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
+ STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
if (pc->pc_curthread == thr && (stopped_cpus & pc->pc_cpumask))
return (KDB_STOPPEDPCB(pc));
}
diff --git a/sys/kern/subr_msgbuf.c b/sys/kern/subr_msgbuf.c
index 14cd39d..cd9c551 100644
--- a/sys/kern/subr_msgbuf.c
+++ b/sys/kern/subr_msgbuf.c
@@ -31,8 +31,16 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
#include <sys/msgbuf.h>
+/*
+ * Maximum number conversion buffer length: uintmax_t in base 2, plus <>
+ * around the priority, and a terminating NUL.
+ */
+#define MAXPRIBUF (sizeof(intmax_t) * NBBY + 3)
+
/* Read/write sequence numbers are modulo a multiple of the buffer size. */
#define SEQMOD(size) ((size) * 16)
@@ -51,6 +59,10 @@ msgbuf_init(struct msgbuf *mbp, void *ptr, int size)
mbp->msg_seqmod = SEQMOD(size);
msgbuf_clear(mbp);
mbp->msg_magic = MSG_MAGIC;
+ mbp->msg_lastpri = -1;
+ mbp->msg_needsnl = 0;
+ bzero(&mbp->msg_lock, sizeof(mbp->msg_lock));
+ mtx_init(&mbp->msg_lock, "msgbuf", NULL, MTX_SPIN);
}
/*
@@ -80,6 +92,12 @@ msgbuf_reinit(struct msgbuf *mbp, void *ptr, int size)
}
msgbuf_clear(mbp);
}
+
+ mbp->msg_lastpri = -1;
+ /* Assume that the old message buffer didn't end in a newline. */
+ mbp->msg_needsnl = 1;
+ bzero(&mbp->msg_lock, sizeof(mbp->msg_lock));
+ mtx_init(&mbp->msg_lock, "msgbuf", NULL, MTX_SPIN);
}
/*
@@ -110,25 +128,140 @@ msgbuf_getcount(struct msgbuf *mbp)
}
/*
- * Append a character to a message buffer. This function can be
- * considered fully reentrant so long as the number of concurrent
- * callers is less than the number of characters in the buffer.
- * However, the message buffer is only guaranteed to be consistent
- * for reading when there are no callers in this function.
+ * Add a character into the message buffer, and update the checksum and
+ * sequence number.
+ *
+ * The caller should hold the message buffer spinlock.
+ */
+static inline void
+msgbuf_do_addchar(struct msgbuf *mbp, u_int *seq, int c)
+{
+ u_int pos;
+
+ /* Make sure we properly wrap the sequence number. */
+ pos = MSGBUF_SEQ_TO_POS(mbp, *seq);
+
+ mbp->msg_cksum += (u_int)c -
+ (u_int)(u_char)mbp->msg_ptr[pos];
+
+ mbp->msg_ptr[pos] = c;
+
+ *seq = MSGBUF_SEQNORM(mbp, *seq + 1);
+}
+
+/*
+ * Append a character to a message buffer.
*/
void
msgbuf_addchar(struct msgbuf *mbp, int c)
{
- u_int new_seq, pos, seq;
-
- do {
- seq = mbp->msg_wseq;
- new_seq = MSGBUF_SEQNORM(mbp, seq + 1);
- } while (atomic_cmpset_rel_int(&mbp->msg_wseq, seq, new_seq) == 0);
- pos = MSGBUF_SEQ_TO_POS(mbp, seq);
- atomic_add_int(&mbp->msg_cksum, (u_int)(u_char)c -
- (u_int)(u_char)mbp->msg_ptr[pos]);
- mbp->msg_ptr[pos] = c;
+ mtx_lock_spin(&mbp->msg_lock);
+
+ msgbuf_do_addchar(mbp, &mbp->msg_wseq, c);
+
+ mtx_unlock_spin(&mbp->msg_lock);
+}
+
+/*
+ * Append a NUL-terminated string with a priority to a message buffer.
+ * Filter carriage returns if the caller requests it.
+ *
+ * XXX The carriage return filtering behavior is present in the
+ * msglogchar() API, however testing has shown that we don't seem to send
+ * carriage returns down this path. So do we still need it?
+ */
+void
+msgbuf_addstr(struct msgbuf *mbp, int pri, char *str, int filter_cr)
+{
+ u_int seq;
+ size_t len, prefix_len;
+ char prefix[MAXPRIBUF];
+ int nl, i;
+
+ len = strlen(str);
+ prefix_len = 0;
+ nl = 0;
+
+ /* If we have a zero-length string, no need to do anything. */
+ if (len == 0)
+ return;
+
+ mtx_lock_spin(&mbp->msg_lock);
+
+ /*
+ * If this is true, we may need to insert a new priority sequence,
+ * so prepare the prefix.
+ */
+ if (pri != -1)
+ prefix_len = sprintf(prefix, "<%d>", pri);
+
+ /*
+ * Starting write sequence number.
+ */
+ seq = mbp->msg_wseq;
+
+ /*
+ * Whenever there is a change in priority, we have to insert a
+ * newline, and a priority prefix if the priority is not -1. Here
+ * we detect whether there was a priority change, and whether we
+ * did not end with a newline. If that is the case, we need to
+ * insert a newline before this string.
+ */
+ if (mbp->msg_lastpri != pri && mbp->msg_needsnl != 0) {
+
+ msgbuf_do_addchar(mbp, &seq, '\n');
+ mbp->msg_needsnl = 0;
+ }
+
+ for (i = 0; i < len; i++) {
+ /*
+ * If we just had a newline, and the priority is not -1
+ * (and therefore prefix_len != 0), then we need a priority
+ * prefix for this line.
+ */
+ if (mbp->msg_needsnl == 0 && prefix_len != 0) {
+ int j;
+
+ for (j = 0; j < prefix_len; j++)
+ msgbuf_do_addchar(mbp, &seq, prefix[j]);
+ }
+
+ /*
+ * Don't copy carriage returns if the caller requested
+ * filtering.
+ *
+ * XXX This matches the behavior of msglogchar(), but is it
+ * necessary? Testing has shown that we don't seem to get
+ * carriage returns here.
+ */
+ if ((filter_cr != 0) && (str[i] == '\r'))
+ continue;
+
+ /*
+ * Clear this flag if we see a newline. This affects whether
+ * we need to insert a new prefix or insert a newline later.
+ */
+ if (str[i] == '\n')
+ mbp->msg_needsnl = 0;
+ else
+ mbp->msg_needsnl = 1;
+
+ msgbuf_do_addchar(mbp, &seq, str[i]);
+ }
+ /*
+ * Update the write sequence number for the actual number of
+ * characters we put in the message buffer. (Depends on whether
+ * carriage returns are filtered.)
+ */
+ mbp->msg_wseq = seq;
+
+ /*
+ * Set the last priority.
+ */
+ mbp->msg_lastpri = pri;
+
+ mtx_unlock_spin(&mbp->msg_lock);
+
}
/*
@@ -141,14 +274,21 @@ msgbuf_getchar(struct msgbuf *mbp)
u_int len, wseq;
int c;
+ mtx_lock_spin(&mbp->msg_lock);
+
wseq = mbp->msg_wseq;
len = MSGBUF_SEQSUB(mbp, wseq, mbp->msg_rseq);
- if (len == 0)
+ if (len == 0) {
+ mtx_unlock_spin(&mbp->msg_lock);
return (-1);
+ }
if (len > mbp->msg_size)
mbp->msg_rseq = MSGBUF_SEQNORM(mbp, wseq - mbp->msg_size);
c = (u_char)mbp->msg_ptr[MSGBUF_SEQ_TO_POS(mbp, mbp->msg_rseq)];
mbp->msg_rseq = MSGBUF_SEQNORM(mbp, mbp->msg_rseq + 1);
+
+ mtx_unlock_spin(&mbp->msg_lock);
+
return (c);
}
@@ -161,10 +301,14 @@ msgbuf_getbytes(struct msgbuf *mbp, char *buf, int buflen)
{
u_int len, pos, wseq;
+ mtx_lock_spin(&mbp->msg_lock);
+
wseq = mbp->msg_wseq;
len = MSGBUF_SEQSUB(mbp, wseq, mbp->msg_rseq);
- if (len == 0)
+ if (len == 0) {
+ mtx_unlock_spin(&mbp->msg_lock);
return (0);
+ }
if (len > mbp->msg_size) {
mbp->msg_rseq = MSGBUF_SEQNORM(mbp, wseq - mbp->msg_size);
len = mbp->msg_size;
@@ -175,6 +319,9 @@ msgbuf_getbytes(struct msgbuf *mbp, char *buf, int buflen)
bcopy(&mbp->msg_ptr[pos], buf, len);
mbp->msg_rseq = MSGBUF_SEQNORM(mbp, mbp->msg_rseq + len);
+
+ mtx_unlock_spin(&mbp->msg_lock);
+
return (len);
}
@@ -193,16 +340,21 @@ msgbuf_peekbytes(struct msgbuf *mbp, char *buf, int buflen, u_int *seqp)
{
u_int len, pos, wseq;
+ mtx_lock_spin(&mbp->msg_lock);
+
if (buf == NULL) {
/* Just initialise *seqp. */
*seqp = MSGBUF_SEQNORM(mbp, mbp->msg_wseq - mbp->msg_size);
+ mtx_unlock_spin(&mbp->msg_lock);
return (0);
}
wseq = mbp->msg_wseq;
len = MSGBUF_SEQSUB(mbp, wseq, *seqp);
- if (len == 0)
+ if (len == 0) {
+ mtx_unlock_spin(&mbp->msg_lock);
return (0);
+ }
if (len > mbp->msg_size) {
*seqp = MSGBUF_SEQNORM(mbp, wseq - mbp->msg_size);
len = mbp->msg_size;
@@ -212,6 +364,9 @@ msgbuf_peekbytes(struct msgbuf *mbp, char *buf, int buflen, u_int *seqp)
len = min(len, (u_int)buflen);
bcopy(&mbp->msg_ptr[MSGBUF_SEQ_TO_POS(mbp, *seqp)], buf, len);
*seqp = MSGBUF_SEQNORM(mbp, *seqp + len);
+
+ mtx_unlock_spin(&mbp->msg_lock);
+
return (len);
}
diff --git a/sys/kern/subr_pcpu.c b/sys/kern/subr_pcpu.c
index de5cafc..5cb4f26 100644
--- a/sys/kern/subr_pcpu.c
+++ b/sys/kern/subr_pcpu.c
@@ -74,7 +74,7 @@ static TAILQ_HEAD(, dpcpu_free) dpcpu_head = TAILQ_HEAD_INITIALIZER(dpcpu_head);
static struct sx dpcpu_lock;
uintptr_t dpcpu_off[MAXCPU];
struct pcpu *cpuid_to_pcpu[MAXCPU];
-struct cpuhead cpuhead = SLIST_HEAD_INITIALIZER(cpuhead);
+struct cpuhead cpuhead = STAILQ_HEAD_INITIALIZER(cpuhead);
/*
* Initialize the MI portions of a struct pcpu.
@@ -89,7 +89,7 @@ pcpu_init(struct pcpu *pcpu, int cpuid, size_t size)
pcpu->pc_cpuid = cpuid;
pcpu->pc_cpumask = 1 << cpuid;
cpuid_to_pcpu[cpuid] = pcpu;
- SLIST_INSERT_HEAD(&cpuhead, pcpu, pc_allcpu);
+ STAILQ_INSERT_TAIL(&cpuhead, pcpu, pc_allcpu);
cpu_pcpu_init(pcpu, cpuid, size);
pcpu->pc_rm_queue.rmq_next = &pcpu->pc_rm_queue;
pcpu->pc_rm_queue.rmq_prev = &pcpu->pc_rm_queue;
@@ -245,7 +245,7 @@ void
pcpu_destroy(struct pcpu *pcpu)
{
- SLIST_REMOVE(&cpuhead, pcpu, pcpu, pc_allcpu);
+ STAILQ_REMOVE(&cpuhead, pcpu, pcpu, pc_allcpu);
cpuid_to_pcpu[pcpu->pc_cpuid] = NULL;
dpcpu_off[pcpu->pc_cpuid] = 0;
}
diff --git a/sys/kern/subr_prf.c b/sys/kern/subr_prf.c
index d0d2ad7..3334837 100644
--- a/sys/kern/subr_prf.c
+++ b/sys/kern/subr_prf.c
@@ -94,6 +94,7 @@ struct snprintf_arg {
extern int log_open;
static void msglogchar(int c, int pri);
+static void msglogstr(char *str, int pri, int filter_cr);
static void putchar(int ch, void *arg);
static char *ksprintn(char *nbuf, uintmax_t num, int base, int *len, int upper);
static void snprintf_func(int ch, void *arg);
@@ -106,6 +107,14 @@ TUNABLE_INT("kern.log_console_output", &log_console_output);
SYSCTL_INT(_kern, OID_AUTO, log_console_output, CTLFLAG_RW,
&log_console_output, 0, "Duplicate console output to the syslog.");
+/*
+ * See the comment in log_console() below for more explanation of this.
+ */
+static int log_console_add_linefeed = 0;
+TUNABLE_INT("kern.log_console_add_linefeed", &log_console_add_linefeed);
+SYSCTL_INT(_kern, OID_AUTO, log_console_add_linefeed, CTLFLAG_RW,
+ &log_console_add_linefeed, 0, "log_console() adds extra newlines.");
+
static int always_console_output = 0;
TUNABLE_INT("kern.always_console_output", &always_console_output);
SYSCTL_INT(_kern, OID_AUTO, always_console_output, CTLFLAG_RW,
@@ -240,16 +249,37 @@ log(int level, const char *fmt, ...)
{
va_list ap;
struct putchar_arg pca;
+#ifdef PRINTF_BUFR_SIZE
+ char bufr[PRINTF_BUFR_SIZE];
+#endif
pca.tty = NULL;
pca.pri = level;
pca.flags = log_open ? TOLOG : TOCONS;
+#ifdef PRINTF_BUFR_SIZE
+ pca.p_bufr = bufr;
+ pca.p_next = pca.p_bufr;
+ pca.n_bufr = sizeof(bufr);
+ pca.remain = sizeof(bufr);
+ *pca.p_next = '\0';
+#else
pca.p_bufr = NULL;
+#endif
va_start(ap, fmt);
kvprintf(fmt, putchar, &pca, 10, ap);
va_end(ap);
+#ifdef PRINTF_BUFR_SIZE
+ /* Write any buffered console/log output: */
+ if (*pca.p_bufr != '\0') {
+ if (pca.flags & TOLOG)
+ msglogstr(pca.p_bufr, level, /*filter_cr*/1);
+
+ if (pca.flags & TOCONS)
+ cnputs(pca.p_bufr);
+ }
+#endif
msgbuftrigger = 1;
}
@@ -258,7 +288,7 @@ log(int level, const char *fmt, ...)
void
log_console(struct uio *uio)
{
- int c, i, error, nl;
+ int c, error, nl;
char *consbuffer;
int pri;
@@ -271,20 +301,48 @@ log_console(struct uio *uio)
nl = 0;
while (uio->uio_resid > 0) {
- c = imin(uio->uio_resid, CONSCHUNK);
+ c = imin(uio->uio_resid, CONSCHUNK - 1);
error = uiomove(consbuffer, c, uio);
if (error != 0)
break;
- for (i = 0; i < c; i++) {
- msglogchar(consbuffer[i], pri);
- if (consbuffer[i] == '\n')
- nl = 1;
- else
- nl = 0;
- }
+ /* Make sure we're NUL-terminated */
+ consbuffer[c] = '\0';
+ if (consbuffer[c - 1] == '\n')
+ nl = 1;
+ else
+ nl = 0;
+ msglogstr(consbuffer, pri, /*filter_cr*/ 1);
+ }
+ /*
+ * The previous behavior in log_console() is preserved when
+ * log_console_add_linefeed is non-zero. For that behavior, if an
+ * individual console write came in that was not terminated with a
+ * line feed, it would add a line feed.
+ *
+ * This results in different data in the message buffer than
+ * appears on the system console (which doesn't add extra line feed
+ * characters).
+ *
+ * A number of programs and rc scripts write a line feed, or a period
+ * and a line feed when they have completed their operation. On
+ * the console, this looks seamless, but when displayed with
+ * 'dmesg -a', you wind up with output that looks like this:
+ *
+ * Updating motd:
+ * .
+ *
+ * On the console, it looks like this:
+ * Updating motd:.
+ *
+ * We could add logic to detect that situation, or just not insert
+ * the extra newlines. Set the kern.log_console_add_linefeed
+ * sysctl/tunable variable to get the old behavior.
+ */
+ if (!nl && log_console_add_linefeed) {
+ consbuffer[0] = '\n';
+ consbuffer[1] = '\0';
+ msglogstr(consbuffer, pri, /*filter_cr*/ 1);
}
- if (!nl)
- msglogchar('\n', pri);
msgbuftrigger = 1;
free(uio, M_IOV);
free(consbuffer, M_TEMP);
@@ -330,9 +388,11 @@ vprintf(const char *fmt, va_list ap)
retval = kvprintf(fmt, putchar, &pca, 10, ap);
#ifdef PRINTF_BUFR_SIZE
- /* Write any buffered console output: */
- if (*pca.p_bufr != '\0')
+ /* Write any buffered console/log output: */
+ if (*pca.p_bufr != '\0') {
cnputs(pca.p_bufr);
+ msglogstr(pca.p_bufr, pca.pri, /*filter_cr*/ 1);
+ }
#endif
if (!panicstr)
@@ -342,18 +402,18 @@ vprintf(const char *fmt, va_list ap)
}
static void
-putcons(int c, struct putchar_arg *ap)
+putbuf(int c, struct putchar_arg *ap)
{
/* Check if no console output buffer was provided. */
- if (ap->p_bufr == NULL)
+ if (ap->p_bufr == NULL) {
/* Output direct to the console. */
- cnputc(c);
- else {
+ if (ap->flags & TOCONS)
+ cnputc(c);
+
+ if (ap->flags & TOLOG)
+ msglogchar(c, ap->pri);
+ } else {
/* Buffer the character: */
- if (c == '\n') {
- *ap->p_next++ = '\r';
- ap->remain--;
- }
*ap->p_next++ = c;
ap->remain--;
@@ -361,12 +421,35 @@ putcons(int c, struct putchar_arg *ap)
*ap->p_next = '\0';
/* Check if the buffer needs to be flushed. */
- if (ap->remain < 3 || c == '\n') {
- cnputs(ap->p_bufr);
+ if (ap->remain == 2 || c == '\n') {
+
+ if (ap->flags & TOLOG)
+ msglogstr(ap->p_bufr, ap->pri, /*filter_cr*/1);
+
+ if (ap->flags & TOCONS) {
+ if ((panicstr == NULL) && (constty != NULL))
+ msgbuf_addstr(&consmsgbuf, -1,
+ ap->p_bufr, /*filter_cr*/ 0);
+
+ if ((constty == NULL) ||(always_console_output))
+ cnputs(ap->p_bufr);
+ }
+
ap->p_next = ap->p_bufr;
ap->remain = ap->n_bufr;
*ap->p_next = '\0';
}
+
+ /*
+ * Since we fill the buffer up one character at a time,
+ * this should not happen. We should always catch it when
+ * ap->remain == 2 (if not sooner due to a newline), flush
+ * the buffer and move on. One way this could happen is
+ * if someone sets PRINTF_BUFR_SIZE to 1 or something
+ * similarly silly.
+ */
+ KASSERT(ap->remain > 2, ("Bad buffer logic, remain = %zd",
+ ap->remain));
}
}
@@ -381,26 +464,25 @@ putchar(int c, void *arg)
struct putchar_arg *ap = (struct putchar_arg*) arg;
struct tty *tp = ap->tty;
int flags = ap->flags;
+ int putbuf_done = 0;
/* Don't use the tty code after a panic or while in ddb. */
if (kdb_active) {
if (c != '\0')
cnputc(c);
- } else if (panicstr || ((flags & TOCONS) && constty == NULL)) {
- if (c != '\0')
- putcons(c, ap);
} else {
- if ((flags & TOTTY) && tp != NULL)
+ if ((panicstr == NULL) && (flags & TOTTY) && (tp != NULL))
tty_putchar(tp, c);
+
if (flags & TOCONS) {
- if (constty != NULL)
- msgbuf_addchar(&consmsgbuf, c);
- if (always_console_output && c != '\0')
- putcons(c, ap);
+ putbuf(c, ap);
+ putbuf_done = 1;
}
}
- if ((flags & TOLOG))
- msglogchar(c, ap->pri);
+ if ((flags & TOLOG) && (putbuf_done == 0)) {
+ if (c != '\0')
+ putbuf(c, ap);
+ }
}
/*
@@ -890,6 +972,15 @@ msglogchar(int c, int pri)
}
}
+static void
+msglogstr(char *str, int pri, int filter_cr)
+{
+ if (!msgbufmapped)
+ return;
+
+ msgbuf_addstr(msgbufp, pri, str, filter_cr);
+}
+
void
msgbufinit(void *ptr, int size)
{
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index 54a050f..3334fc2 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -1845,10 +1845,16 @@ dontblock:
}
SBLASTRECORDCHK(&so->so_rcv);
SBLASTMBUFCHK(&so->so_rcv);
- error = sbwait(&so->so_rcv);
- if (error) {
- SOCKBUF_UNLOCK(&so->so_rcv);
- goto release;
+ /*
+ * We could receive some data while was notifying
+ * the protocol. Skip blocking in this case.
+ */
+ if (so->so_rcv.sb_mb == NULL) {
+ error = sbwait(&so->so_rcv);
+ if (error) {
+ SOCKBUF_UNLOCK(&so->so_rcv);
+ goto release;
+ }
}
m = so->so_rcv.sb_mb;
if (m != NULL)
diff --git a/sys/mips/cavium/octeon_ebt3000_cf.c b/sys/mips/cavium/octeon_ebt3000_cf.c
index 7955d19..f5a44c4 100644
--- a/sys/mips/cavium/octeon_ebt3000_cf.c
+++ b/sys/mips/cavium/octeon_ebt3000_cf.c
@@ -104,12 +104,40 @@ __FBSDID("$FreeBSD$");
extern cvmx_bootinfo_t *octeon_bootinfo;
/* Globals */
-int bus_width;
+/*
+ * There's three bus types supported by this driver.
+ *
+ * CF_8 -- Traditional PC Card IDE interface on an 8-bit wide bus. We assume
+ * the bool loader has configure attribute memory properly. We then access
+ * the device like old-school 8-bit IDE card (which is all a traditional PC Card
+ * interface really is).
+ * CF_16 -- Traditional PC Card IDE interface on a 16-bit wide bus. Registers on
+ * this bus are 16-bits wide too. When accessing registers in the task file, you
+ * have to do it in 16-bit chunks, and worry about masking out what you don't want
+ * or ORing together the traditional 8-bit values. We assume the bootloader does
+ * the right attribute memory initialization dance.
+ * CF_TRUE_IDE_8 - CF Card wired to True IDE mode. There's no Attribute memory
+ * space at all. Instead all the traditional 8-bit registers are there, but
+ * on a 16-bit bus where addr0 isn't wired. This means we need to read/write them
+ * 16-bit chunks, but only the lower 8 bits are valid. We do not (and can not)
+ * access this like CF_16 with the comingled registers. Yet we can't access
+ * this like CF_8 because of the register offset. Except the TF_DATA register
+ * appears to be full width?
+ */
void *base_addr;
+int bus_type;
+#define CF_8 1 /* 8-bit bus, no offsets - PC Card */
+#define CF_16 2 /* 16-bit bus, registers shared - PC Card */
+#define CF_TRUE_IDE_8 3 /* 16-bit bus, only lower 8-bits, TrueIDE */
+const char *const cf_type[] = {
+ "impossible type",
+ "CF 8-bit",
+ "CF 16-bit",
+ "True IDE"
+};
/* Device softc */
struct cf_priv {
-
device_t dev;
struct drive_param *drive_param;
@@ -230,9 +258,65 @@ static void cf_start (struct bio *bp)
static int cf_ioctl (struct g_provider *pp, u_long cmd, void *data, int fflag, struct thread *td)
{
- return (0);
+ return (0);
+}
+
+
+static uint8_t cf_inb_8(int port)
+{
+ /*
+ * Traditional 8-bit PC Card/CF bus access.
+ */
+ if (bus_type == CF_8) {
+ volatile uint8_t *task_file = (volatile uint8_t *)base_addr;
+ return task_file[port];
+ }
+
+ /*
+ * True IDE access. lower 8 bits on a 16-bit bus (see above).
+ */
+ volatile uint16_t *task_file = (volatile uint16_t *)base_addr;
+ return task_file[port] & 0xff;
+}
+
+static void cf_outb_8(int port, uint8_t val)
+{
+ /*
+ * Traditional 8-bit PC Card/CF bus access.
+ */
+ if (bus_type == CF_8) {
+ volatile uint8_t *task_file = (volatile uint8_t *)base_addr;
+ task_file[port] = val;
+ }
+
+ /*
+ * True IDE access. lower 8 bits on a 16-bit bus (see above).
+ */
+ volatile uint16_t *task_file = (volatile uint16_t *)base_addr;
+ task_file[port] = val & 0xff;
+}
+
+static uint8_t cf_inb_16(int port)
+{
+ volatile uint16_t *task_file = (volatile uint16_t *)base_addr;
+ uint16_t val = task_file[port / 2];
+ if (port & 1)
+ return (val >> 8) & 0xff;
+ return val & 0xff;
}
+static uint16_t cf_inw_16(int port)
+{
+ volatile uint16_t *task_file = (volatile uint16_t *)base_addr;
+ uint16_t val = task_file[port / 2];
+ return val;
+}
+
+static void cf_outw_16(int port, uint16_t val)
+{
+ volatile uint16_t *task_file = (volatile uint16_t *)base_addr;
+ task_file[port / 2] = val;
+}
/* ------------------------------------------------------------------- *
* cf_cmd_read() *
@@ -264,25 +348,29 @@ static int cf_cmd_read (uint32_t nr_sectors, uint32_t start_sector, void *buf)
return (error);
}
- if (bus_width == 8) {
- volatile uint8_t *task_file = (volatile uint8_t*)base_addr;
- volatile uint8_t dummy;
+ switch (bus_type)
+ {
+ case CF_8:
for (count = 0; count < SECTOR_SIZE; count++) {
- *ptr_8++ = task_file[TF_DATA];
- if ((count & 0xf) == 0) dummy = task_file[TF_STATUS];
+ *ptr_8++ = cf_inb_8(TF_DATA);
+ if ((count & 0xf) == 0)
+ (void)cf_inb_8(TF_STATUS);
}
- } else {
- volatile uint16_t *task_file = (volatile uint16_t*)base_addr;
- volatile uint16_t dummy;
+ break;
+ case CF_TRUE_IDE_8:
+ case CF_16:
+ default:
for (count = 0; count < SECTOR_SIZE; count+=2) {
uint16_t temp;
- temp = task_file[TF_DATA];
+ temp = cf_inw_16(TF_DATA);
*ptr_16++ = SWAP_SHORT(temp);
- if ((count & 0xf) == 0) dummy = task_file[TF_STATUS/2];
+ if ((count & 0xf) == 0)
+ (void)cf_inb_16(TF_STATUS);
}
+ break;
}
- lba ++;
+ lba++;
}
#ifdef OCTEON_VISUAL_CF_0
octeon_led_write_char(0, ' ');
@@ -320,28 +408,28 @@ static int cf_cmd_write (uint32_t nr_sectors, uint32_t start_sector, void *buf)
return (error);
}
- if (bus_width == 8) {
- volatile uint8_t *task_file;
- volatile uint8_t dummy;
-
- task_file = (volatile uint8_t *) base_addr;
+ switch (bus_type)
+ {
+ case CF_8:
for (count = 0; count < SECTOR_SIZE; count++) {
- task_file[TF_DATA] = *ptr_8++;
- if ((count & 0xf) == 0) dummy = task_file[TF_STATUS];
+ cf_outb_8(TF_DATA, *ptr_8++);
+ if ((count & 0xf) == 0)
+ (void)cf_inb_8(TF_STATUS);
}
- } else {
- volatile uint16_t *task_file;
- volatile uint16_t dummy;
-
- task_file = (volatile uint16_t *) base_addr;
+ break;
+ case CF_TRUE_IDE_8:
+ case CF_16:
+ default:
for (count = 0; count < SECTOR_SIZE; count+=2) {
uint16_t temp = *ptr_16++;
- task_file[TF_DATA] = SWAP_SHORT(temp);
- if ((count & 0xf) == 0) dummy = task_file[TF_STATUS/2];
+ cf_outw_16(TF_DATA, SWAP_SHORT(temp));
+ if ((count & 0xf) == 0)
+ (void)cf_inb_16(TF_STATUS);
}
+ break;
}
- lba ++;
+ lba++;
}
#ifdef OCTEON_VISUAL_CF_1
octeon_led_write_char(1, ' ');
@@ -361,59 +449,32 @@ static int cf_cmd_write (uint32_t nr_sectors, uint32_t start_sector, void *buf)
static int cf_cmd_identify (void)
{
int count;
- uint8_t status;
int error;
- if (bus_width == 8) {
- volatile uint8_t *task_file;
-
- task_file = (volatile uint8_t *) base_addr;
-
- while ((status = task_file[TF_STATUS]) & STATUS_BSY) {
- DELAY(WAIT_DELAY);
- }
-
- task_file[TF_SECTOR_COUNT] = 0;
- task_file[TF_SECTOR_NUMBER] = 0;
- task_file[TF_CYL_LSB] = 0;
- task_file[TF_CYL_MSB] = 0;
- task_file[TF_DRV_HEAD] = 0;
- task_file[TF_COMMAND] = CMD_IDENTIFY;
-
- error = cf_wait_busy();
- if (error == 0) {
- for (count = 0; count < SECTOR_SIZE; count++)
- drive_param.u.buf[count] = task_file[TF_DATA];
- }
- } else {
- volatile uint16_t *task_file;
-
- task_file = (volatile uint16_t *) base_addr;
-
- while ((status = (task_file[TF_STATUS/2]>>8)) & STATUS_BSY) {
- DELAY(WAIT_DELAY);
- }
-
- task_file[TF_SECTOR_COUNT/2] = 0; /* this includes TF_SECTOR_NUMBER */
- task_file[TF_CYL_LSB/2] = 0; /* this includes TF_CYL_MSB */
- task_file[TF_DRV_HEAD/2] = 0 | (CMD_IDENTIFY<<8); /* this includes TF_COMMAND */
-
- error = cf_wait_busy();
- if (error == 0) {
- for (count = 0; count < SECTOR_SIZE; count+=2) {
- uint16_t temp;
- temp = task_file[TF_DATA];
-
- /* endianess will be swapped below */
- drive_param.u.buf[count] = (temp & 0xff);
- drive_param.u.buf[count+1] = (temp & 0xff00)>>8;
- }
- }
- }
+ error = cf_send_cmd(0, CMD_IDENTIFY);
if (error != 0) {
printf("%s: identify failed: %d\n", __func__, error);
return (error);
}
+ switch (bus_type)
+ {
+ case CF_8:
+ for (count = 0; count < SECTOR_SIZE; count++)
+ drive_param.u.buf[count] = cf_inb_8(TF_DATA);
+ break;
+ case CF_TRUE_IDE_8:
+ case CF_16:
+ default:
+ for (count = 0; count < SECTOR_SIZE; count += 2) {
+ uint16_t temp;
+ temp = cf_inw_16(TF_DATA);
+
+ /* endianess will be swapped below */
+ drive_param.u.buf[count] = (temp & 0xff);
+ drive_param.u.buf[count + 1] = (temp & 0xff00) >> 8;
+ }
+ break;
+ }
cf_swap_ascii(drive_param.u.driveid.model, drive_param.model);
@@ -423,6 +484,7 @@ static int cf_cmd_identify (void)
drive_param.sec_track = SWAP_SHORT (drive_param.u.driveid.current_sectors);
drive_param.nr_sectors = (uint32_t)SWAP_SHORT (drive_param.u.driveid.lba_size_1) |
((uint32_t)SWAP_SHORT (drive_param.u.driveid.lba_size_2));
+ printf("cf0: <%s> %lld sectors\n", drive_param.model, (long long)drive_param.nr_sectors);
return (0);
}
@@ -437,37 +499,27 @@ static int cf_cmd_identify (void)
*/
static int cf_send_cmd (uint32_t lba, uint8_t cmd)
{
- uint8_t status;
-
- if (bus_width == 8) {
- volatile uint8_t *task_file;
-
- task_file = (volatile uint8_t *) base_addr;
-
- while ( (status = task_file[TF_STATUS]) & STATUS_BSY) {
+ switch (bus_type)
+ {
+ case CF_8:
+ case CF_TRUE_IDE_8:
+ while (cf_inb_8(TF_STATUS) & STATUS_BSY)
DELAY(WAIT_DELAY);
- }
-
- task_file[TF_SECTOR_COUNT] = 1;
- task_file[TF_SECTOR_NUMBER] = (lba & 0xff);
- task_file[TF_CYL_LSB] = ((lba >> 8) & 0xff);
- task_file[TF_CYL_MSB] = ((lba >> 16) & 0xff);
- task_file[TF_DRV_HEAD] = ((lba >> 24) & 0xff) | 0xe0;
- task_file[TF_COMMAND] = cmd;
-
- } else {
- volatile uint16_t *task_file;
-
- task_file = (volatile uint16_t *) base_addr;
-
- while ( (status = (task_file[TF_STATUS/2]>>8)) & STATUS_BSY) {
+ cf_outb_8(TF_SECTOR_COUNT, 1);
+ cf_outb_8(TF_SECTOR_NUMBER, lba & 0xff);
+ cf_outb_8(TF_CYL_LSB, (lba >> 8) & 0xff);
+ cf_outb_8(TF_CYL_MSB, (lba >> 16) & 0xff);
+ cf_outb_8(TF_DRV_HEAD, ((lba >> 24) & 0xff) | 0xe0);
+ cf_outb_8(TF_COMMAND, cmd);
+ break;
+ case CF_16:
+ default:
+ while (cf_inb_16(TF_STATUS) & STATUS_BSY)
DELAY(WAIT_DELAY);
- }
-
- task_file[TF_SECTOR_COUNT/2] = 1 | ((lba & 0xff) << 8);
- task_file[TF_CYL_LSB/2] = ((lba >> 8) & 0xff) | (((lba >> 16) & 0xff) << 8);
- task_file[TF_DRV_HEAD/2] = (((lba >> 24) & 0xff) | 0xe0) | (cmd << 8);
-
+ cf_outw_16(TF_SECTOR_COUNT, 1 | ((lba & 0xff) << 8));
+ cf_outw_16(TF_CYL_LSB, ((lba >> 8) & 0xff) | (((lba >> 16) & 0xff) << 8));
+ cf_outw_16(TF_DRV_HEAD, (((lba >> 24) & 0xff) | 0xe0) | (cmd << 8));
+ break;
}
return (cf_wait_busy());
@@ -499,32 +551,32 @@ static int cf_wait_busy (void)
octeon_led_run_wheel(&where0, 2);
#endif
- if (bus_width == 8) {
- volatile uint8_t *task_file;
- task_file = (volatile uint8_t *)base_addr;
-
- status = task_file[TF_STATUS];
+ switch (bus_type)
+ {
+ case CF_8:
+ case CF_TRUE_IDE_8:
+ status = cf_inb_8(TF_STATUS);
while ((status & STATUS_BSY) == STATUS_BSY) {
if ((status & STATUS_DF) != 0) {
printf("%s: device fault (status=%x)\n", __func__, status);
return (EIO);
}
DELAY(WAIT_DELAY);
- status = task_file[TF_STATUS];
+ status = cf_inb_8(TF_STATUS);
}
- } else {
- volatile uint16_t *task_file;
- task_file = (volatile uint16_t *)base_addr;
-
- status = task_file[TF_STATUS/2]>>8;
+ break;
+ case CF_16:
+ default:
+ status = cf_inb_16(TF_STATUS);
while ((status & STATUS_BSY) == STATUS_BSY) {
if ((status & STATUS_DF) != 0) {
printf("%s: device fault (status=%x)\n", __func__, status);
return (EIO);
}
DELAY(WAIT_DELAY);
- status = (uint8_t)(task_file[TF_STATUS/2]>>8);
+ status = cf_inb_16(TF_STATUS);
}
+ break;
}
if ((status & STATUS_DRQ) == 0) {
printf("%s: device not ready (status=%x)\n", __func__, status);
@@ -550,9 +602,8 @@ static void cf_swap_ascii (unsigned char str1[], char str2[])
{
int i;
- for(i = 0; i < MODEL_STR_SIZE; i++) {
- str2[i] = str1[i^1];
- }
+ for(i = 0; i < MODEL_STR_SIZE; i++)
+ str2[i] = str1[i ^ 1];
}
@@ -562,7 +613,8 @@ static void cf_swap_ascii (unsigned char str1[], char str2[])
static int cf_probe (device_t dev)
{
- if (octeon_is_simulation()) return 1;
+ if (octeon_is_simulation())
+ return (ENXIO);
if (device_get_unit(dev) != 0) {
panic("can't attach more devices\n");
@@ -582,9 +634,9 @@ static int cf_probe (device_t dev)
* inserted.
*
*/
+typedef unsigned long long llu;
static void cf_identify (driver_t *drv, device_t parent)
{
- uint8_t status;
int bus_region;
int count = 0;
cvmx_mio_boot_reg_cfgx_t cfg;
@@ -599,34 +651,39 @@ static void cf_identify (driver_t *drv, device_t parent)
cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(bus_region));
if (cfg.s.base == octeon_bootinfo->compact_flash_common_base_addr >> 16)
{
- bus_width = (cfg.s.width) ? 16: 8;
- printf("Compact flash found in bootbus region %d (%d bit).\n", bus_region, bus_width);
+ if (octeon_bootinfo->compact_flash_attribute_base_addr == 0)
+ bus_type = CF_TRUE_IDE_8;
+ else
+ bus_type = (cfg.s.width) ? CF_16 : CF_8;
+ printf("Compact flash found in bootbus region %d (%s).\n", bus_region, cf_type[bus_type]);
break;
}
}
- if (bus_width == 8) {
- volatile uint8_t *task_file;
- task_file = (volatile uint8_t *) base_addr;
+ switch (bus_type)
+ {
+ case CF_8:
+ case CF_TRUE_IDE_8:
/* Check if CF is inserted */
- while ( (status = task_file[TF_STATUS]) & STATUS_BSY){
- if ((count++) == NR_TRIES ) {
+ while (cf_inb_8(TF_STATUS) & STATUS_BSY) {
+ if ((count++) == NR_TRIES ) {
printf("Compact Flash not present\n");
return;
}
DELAY(WAIT_DELAY);
}
- } else {
- volatile uint16_t *task_file;
- task_file = (volatile uint16_t *) base_addr;
+ break;
+ case CF_16:
+ default:
/* Check if CF is inserted */
- while ( (status = (task_file[TF_STATUS/2]>>8)) & STATUS_BSY){
- if ((count++) == NR_TRIES ) {
+ while (cf_inb_16(TF_STATUS) & STATUS_BSY) {
+ if ((count++) == NR_TRIES ) {
printf("Compact Flash not present\n");
return;
}
DELAY(WAIT_DELAY);
}
+ break;
}
BUS_ADD_CHILD(parent, 0, "cf", 0);
@@ -655,7 +712,7 @@ static int cf_attach_geom (void *arg, int flag)
* ------------------------------------------------------------------- */
static void cf_attach_geom_proxy (void *arg, int flag)
{
- cf_attach_geom(arg, flag);
+ cf_attach_geom(arg, flag);
}
@@ -668,7 +725,8 @@ static int cf_attach (device_t dev)
{
struct cf_priv *cf_priv;
- if (octeon_is_simulation()) return 1;
+ if (octeon_is_simulation())
+ return (ENXIO);
cf_priv = device_get_softc(dev);
cf_priv->dev = dev;
@@ -701,4 +759,3 @@ static driver_t cf_driver = {
static devclass_t cf_devclass;
DRIVER_MODULE(cf, nexus, cf_driver, cf_devclass, 0, 0);
-
diff --git a/sys/mips/mips/mp_machdep.c b/sys/mips/mips/mp_machdep.c
index e945736..7191b37 100644
--- a/sys/mips/mips/mp_machdep.c
+++ b/sys/mips/mips/mp_machdep.c
@@ -86,7 +86,7 @@ ipi_selected(cpumask_t cpus, int ipi)
CTR3(KTR_SMP, "%s: cpus: %x, ipi: %x\n", __func__, cpus, ipi);
- SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
+ STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
if ((cpus & pc->pc_cpumask) != 0)
ipi_send(pc, ipi);
}
diff --git a/sys/modules/ath/Makefile b/sys/modules/ath/Makefile
index 6b093a9..49f7fa6 100644
--- a/sys/modules/ath/Makefile
+++ b/sys/modules/ath/Makefile
@@ -134,6 +134,10 @@ SRCS+= onoe.c
SRCS+= amrr.c
.endif
+# DFS
+.PATH: ${.CURDIR}/../../dev/ath/ath_dfs/null
+SRCS+= dfs_null.c
+
CFLAGS+= -I. -I${.CURDIR}/../../dev/ath -I${.CURDIR}/../../dev/ath/ath_hal
opt_ah.h:
diff --git a/sys/modules/cxgbe/if_cxgbe/Makefile b/sys/modules/cxgbe/if_cxgbe/Makefile
index a524cde..ac1d22c 100644
--- a/sys/modules/cxgbe/if_cxgbe/Makefile
+++ b/sys/modules/cxgbe/if_cxgbe/Makefile
@@ -6,7 +6,7 @@ CXGBE = ${.CURDIR}/../../../dev/cxgbe
.PATH: ${CXGBE} ${CXGBE}/common
KMOD = if_cxgbe
-SRCS = t4_main.c t4_sge.c
+SRCS = t4_main.c t4_sge.c t4_l2t.c
SRCS+= t4_hw.c
SRCS+= device_if.h bus_if.h pci_if.h
SRCS+= opt_inet.h
diff --git a/sys/modules/usb/Makefile b/sys/modules/usb/Makefile
index 38f56cb..6288d66 100644
--- a/sys/modules/usb/Makefile
+++ b/sys/modules/usb/Makefile
@@ -30,7 +30,7 @@ SUBDIR += ehci musb ohci uhci xhci uss820dci ${_at91dci} ${_atmegadci}
SUBDIR += rum run uath upgt ural zyd ${_urtw}
SUBDIR += atp uhid ukbd ums udbp ufm uep
SUBDIR += ucom u3g uark ubsa ubser uchcom ucycom ufoma uftdi ugensa uipaq ulpt \
- umct umodem umoscom uplcom uslcom uvisor uvscom
+ umct umcs umodem umoscom uplcom uslcom uvisor uvscom
SUBDIR += uether aue axe cdce cue kue mos rue udav uhso ipheth
SUBDIR += usfs umass urio
SUBDIR += quirk template
diff --git a/sys/modules/usb/umcs/Makefile b/sys/modules/usb/umcs/Makefile
new file mode 100644
index 0000000..be75fb5
--- /dev/null
+++ b/sys/modules/usb/umcs/Makefile
@@ -0,0 +1,36 @@
+#
+# $FreeBSD$
+#
+# Copyright (c) 2011 Hans Petter Selasky. 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/serial
+
+KMOD= umcs
+SRCS= opt_bus.h opt_usb.h device_if.h bus_if.h usb_if.h usbdevs.h \
+ umcs.c
+
+.include <bsd.kmod.mk>
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index 5e5a548..be90f5a 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -561,7 +561,7 @@ ether_ipfw_chk(struct mbuf **m0, struct ifnet *dst, int shared)
* mbuf chain m with the ethernet header at the front.
*/
static void
-ether_input(struct ifnet *ifp, struct mbuf *m)
+ether_input_internal(struct ifnet *ifp, struct mbuf *m)
{
struct ether_header *eh;
u_short etype;
@@ -755,6 +755,46 @@ ether_input(struct ifnet *ifp, struct mbuf *m)
}
/*
+ * Ethernet input dispatch; by default, direct dispatch here regardless of
+ * global configuration.
+ */
+static void
+ether_nh_input(struct mbuf *m)
+{
+
+ ether_input_internal(m->m_pkthdr.rcvif, m);
+}
+
+static struct netisr_handler ether_nh = {
+ .nh_name = "ether",
+ .nh_handler = ether_nh_input,
+ .nh_proto = NETISR_ETHER,
+ .nh_policy = NETISR_POLICY_SOURCE,
+ .nh_dispatch = NETISR_DISPATCH_DIRECT,
+};
+
+static void
+ether_init(__unused void *arg)
+{
+
+ netisr_register(&ether_nh);
+}
+SYSINIT(ether, SI_SUB_INIT_IF, SI_ORDER_ANY, ether_init, NULL);
+
+static void
+ether_input(struct ifnet *ifp, struct mbuf *m)
+{
+
+ /*
+ * We will rely on rcvif being set properly in the deferred context,
+ * so assert it is correct here.
+ */
+ KASSERT(m->m_pkthdr.rcvif == ifp, ("%s: ifnet mismatch", __func__));
+
+ netisr_dispatch(NETISR_ETHER, m);
+}
+
+/*
* Upper layer processing for a received Ethernet packet.
*/
void
diff --git a/sys/net/if_stf.c b/sys/net/if_stf.c
index 1ef5581..4f904a5 100644
--- a/sys/net/if_stf.c
+++ b/sys/net/if_stf.c
@@ -3,6 +3,7 @@
/*-
* Copyright (C) 2000 WIDE Project.
+ * Copyright (c) 2010 Hiroki Sato <hrs@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,7 +32,7 @@
*/
/*
- * 6to4 interface, based on RFC3056.
+ * 6to4 interface, based on RFC3056 + 6rd (RFC5569) support.
*
* 6to4 interface is NOT capable of link-layer (I mean, IPv4) multicasting.
* There is no address mapping defined from IPv6 multicast address to IPv4
@@ -60,7 +61,7 @@
* ICMPv6:
* - Redirects cannot be used due to the lack of link-local address.
*
- * stf interface does not have, and will not need, a link-local address.
+ * stf interface does not have, and will not need, a link-local address.
* It seems to have no real benefit and does not help the above symptoms much.
* Even if we assign link-locals to interface, we cannot really
* use link-local unicast/multicast on top of 6to4 cloud (since there's no
@@ -72,6 +73,12 @@
* http://playground.iijlab.net/i-d/draft-itojun-ipv6-transition-abuse-00.txt
* for details. The code tries to filter out some of malicious packets.
* Note that there is no way to be 100% secure.
+ *
+ * 6rd (RFC5569) extension is enabled when an IPv6 GUA other than
+ * 2002::/16 is assigned. The stf(4) recognizes a 32-bit just after
+ * prefixlen as the IPv4 address of the 6rd customer site. The
+ * prefixlen must be shorter than 32.
+ *
*/
#include "opt_inet.h"
@@ -120,15 +127,41 @@
#include <security/mac/mac_framework.h>
+#define STF_DEBUG 1
+#define ip_sprintf(buf, a) \
+ sprintf(buf, "%d.%d.%d.%d", \
+ (ntohl((a)->s_addr)>>24)&0xFF, \
+ (ntohl((a)->s_addr)>>16)&0xFF, \
+ (ntohl((a)->s_addr)>>8)&0xFF, \
+ (ntohl((a)->s_addr))&0xFF);
+#if STF_DEBUG
+#define DEBUG_PRINTF(a, ...) \
+ do { \
+ if (V_stf_debug >= a) \
+ printf(__VA_ARGS__); \
+ } while (0)
+#else
+#define DEBUG_PRINTF(a, ...)
+#endif
+
SYSCTL_DECL(_net_link);
SYSCTL_NODE(_net_link, IFT_STF, stf, CTLFLAG_RW, 0, "6to4 Interface");
-static int stf_route_cache = 1;
-SYSCTL_INT(_net_link_stf, OID_AUTO, route_cache, CTLFLAG_RW,
- &stf_route_cache, 0, "Caching of IPv4 routes for 6to4 Output");
+static VNET_DEFINE(int, stf_route_cache) = 1;
+#define V_stf_route_cache VNET(stf_route_cache)
+SYSCTL_VNET_INT(_net_link_stf, OID_AUTO, route_cache, CTLFLAG_RW,
+ &VNET_NAME(stf_route_cache), 0,
+ "Enable caching of IPv4 routes for 6to4 output.");
+
+#if STF_DEBUG
+static VNET_DEFINE(int, stf_debug) = 0;
+#define V_stf_debug VNET(stf_debug)
+SYSCTL_VNET_INT(_net_link_stf, OID_AUTO, stf_debug, CTLFLAG_RW,
+ &VNET_NAME(stf_debug), 0,
+ "Enable displaying verbose debug message of stf interfaces");
+#endif
#define STFNAME "stf"
-#define STFUNIT 0
#define IN6_IS_ADDR_6TO4(x) (ntohs((x)->s6_addr16[0]) == 0x2002)
@@ -145,17 +178,27 @@ struct stf_softc {
struct route_in6 __sc_ro6; /* just for safety */
} __sc_ro46;
#define sc_ro __sc_ro46.__sc_ro4
- struct mtx sc_ro_mtx;
+ struct mtx sc_mtx;
u_int sc_fibnum;
const struct encaptab *encap_cookie;
+ u_int sc_flags;
+ eventhandler_tag sc_ifaddr_event_tag;
+ LIST_ENTRY(stf_softc) stf_list;
};
#define STF2IFP(sc) ((sc)->sc_ifp)
-/*
- * Note that mutable fields in the softc are not currently locked.
- * We do lock sc_ro in stf_output though.
- */
+static struct mtx stf_mtx;
static MALLOC_DEFINE(M_STF, STFNAME, "6to4 Tunnel Interface");
+static VNET_DEFINE(LIST_HEAD(, stf_softc), stf_softc_list);
+#define V_stf_softc_list VNET(stf_softc_list)
+
+#define STF_LOCK_INIT(sc) mtx_init(&(sc)->sc_mtx, "stf softc", \
+ NULL, MTX_DEF);
+#define STF_LOCK_DESTROY(sc) mtx_destroy(&(sc)->sc_mtx)
+#define STF_LOCK(sc) mtx_lock(&(sc)->sc_mtx)
+#define STF_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
+#define STF_LOCK_ASSERT(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED)
+
static const int ip_stf_ttl = 40;
extern struct domain inetdomain;
@@ -170,8 +213,6 @@ struct protosw in_stf_protosw = {
.pr_usrreqs = &rip_usrreqs
};
-static char *stfnames[] = {"stf0", "stf", "6to4", NULL};
-
static int stfmodevent(module_t, int, void *);
static int stf_encapcheck(const struct mbuf *, int, int, void *);
static struct in6_ifaddr *stf_getsrcifa6(struct ifnet *);
@@ -184,68 +225,47 @@ static int stf_checkaddr6(struct stf_softc *, struct in6_addr *,
struct ifnet *);
static void stf_rtrequest(int, struct rtentry *, struct rt_addrinfo *);
static int stf_ioctl(struct ifnet *, u_long, caddr_t);
+static int stf_is_up(struct ifnet *);
-static int stf_clone_match(struct if_clone *, const char *);
-static int stf_clone_create(struct if_clone *, char *, size_t, caddr_t);
-static int stf_clone_destroy(struct if_clone *, struct ifnet *);
-struct if_clone stf_cloner = IFC_CLONE_INITIALIZER(STFNAME, NULL, 0,
- NULL, stf_clone_match, stf_clone_create, stf_clone_destroy);
+#define STF_GETIN4_USE_CACHE 1
+static struct sockaddr_in *stf_getin4addr(struct sockaddr_in *,
+ struct ifaddr *,
+ int);
+static struct sockaddr_in *stf_getin4addr_in6(struct sockaddr_in *,
+ struct ifaddr *,
+ struct in6_addr *);
+static struct sockaddr_in *stf_getin4addr_sin6(struct sockaddr_in *,
+ struct ifaddr *,
+ struct sockaddr_in6 *);
+static void stf_ifaddr_change(void *, struct ifnet *);
-static int
-stf_clone_match(struct if_clone *ifc, const char *name)
-{
- int i;
-
- for(i = 0; stfnames[i] != NULL; i++) {
- if (strcmp(stfnames[i], name) == 0)
- return (1);
- }
+static int stf_clone_create(struct if_clone *, int, caddr_t);
+static void stf_clone_destroy(struct ifnet *);
- return (0);
-}
+IFC_SIMPLE_DECLARE(stf, 0);
static int
-stf_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
+stf_clone_create(struct if_clone *ifc, int unit, caddr_t params)
{
- int err, unit;
struct stf_softc *sc;
struct ifnet *ifp;
- /*
- * We can only have one unit, but since unit allocation is
- * already locked, we use it to keep from allocating extra
- * interfaces.
- */
- unit = STFUNIT;
- err = ifc_alloc_unit(ifc, &unit);
- if (err != 0)
- return (err);
-
sc = malloc(sizeof(struct stf_softc), M_STF, M_WAITOK | M_ZERO);
+ sc->sc_fibnum = curthread->td_proc->p_fibnum;
ifp = STF2IFP(sc) = if_alloc(IFT_STF);
- if (ifp == NULL) {
+ if (sc->sc_ifp == NULL) {
free(sc, M_STF);
- ifc_free_unit(ifc, unit);
- return (ENOSPC);
+ return (ENOMEM);
}
+ STF_LOCK_INIT(sc);
ifp->if_softc = sc;
- sc->sc_fibnum = curthread->td_proc->p_fibnum;
-
- /*
- * Set the name manually rather then using if_initname because
- * we don't conform to the default naming convention for interfaces.
- */
- strlcpy(ifp->if_xname, name, IFNAMSIZ);
- ifp->if_dname = ifc->ifc_name;
- ifp->if_dunit = IF_DUNIT_NONE;
+ if_initname(ifp, ifc->ifc_name, unit);
- mtx_init(&(sc)->sc_ro_mtx, "stf ro", NULL, MTX_DEF);
sc->encap_cookie = encap_attach_func(AF_INET, IPPROTO_IPV6,
stf_encapcheck, &in_stf_protosw, sc);
if (sc->encap_cookie == NULL) {
if_printf(ifp, "attach failed\n");
free(sc, M_STF);
- ifc_free_unit(ifc, unit);
return (ENOMEM);
}
@@ -255,41 +275,63 @@ stf_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
ifp->if_snd.ifq_maxlen = ifqmaxlen;
if_attach(ifp);
bpfattach(ifp, DLT_NULL, sizeof(u_int32_t));
+
+ mtx_lock(&stf_mtx);
+ LIST_INSERT_HEAD(&V_stf_softc_list, sc, stf_list);
+ mtx_unlock(&stf_mtx);
+
+ sc->sc_ifaddr_event_tag = EVENTHANDLER_REGISTER(ifaddr_event,
+ stf_ifaddr_change,
+ NULL,
+ EVENTHANDLER_PRI_ANY);
return (0);
}
-static int
-stf_clone_destroy(struct if_clone *ifc, struct ifnet *ifp)
+static void
+stf_clone_destroy(struct ifnet *ifp)
{
struct stf_softc *sc = ifp->if_softc;
int err;
+ mtx_lock(&stf_mtx);
+ LIST_REMOVE(sc, stf_list);
+ mtx_unlock(&stf_mtx);
+
+ EVENTHANDLER_DEREGISTER(ifaddr_event, sc->sc_ifaddr_event_tag);
+
err = encap_detach(sc->encap_cookie);
KASSERT(err == 0, ("Unexpected error detaching encap_cookie"));
- mtx_destroy(&(sc)->sc_ro_mtx);
bpfdetach(ifp);
if_detach(ifp);
if_free(ifp);
+ STF_LOCK_DESTROY(sc);
free(sc, M_STF);
- ifc_free_unit(ifc, STFUNIT);
- return (0);
+ return;
}
+static void
+vnet_stf_init(const void *unused __unused)
+{
+
+ LIST_INIT(&V_stf_softc_list);
+}
+VNET_SYSINIT(vnet_stf_init, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, vnet_stf_init,
+ NULL);
+
static int
-stfmodevent(mod, type, data)
- module_t mod;
- int type;
- void *data;
+stfmodevent(module_t mod, int type, void *data)
{
switch (type) {
case MOD_LOAD:
+ mtx_init(&stf_mtx, "stf_mtx", NULL, MTX_DEF);
if_clone_attach(&stf_cloner);
break;
case MOD_UNLOAD:
if_clone_detach(&stf_cloner);
+ mtx_destroy(&stf_mtx);
break;
default:
return (EOPNOTSUPP);
@@ -305,28 +347,31 @@ static moduledata_t stf_mod = {
};
DECLARE_MODULE(if_stf, stf_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
+MODULE_VERSION(if_stf, 1);
static int
-stf_encapcheck(m, off, proto, arg)
- const struct mbuf *m;
- int off;
- int proto;
- void *arg;
+stf_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
{
struct ip ip;
struct in6_ifaddr *ia6;
+ struct sockaddr_in ia6_in4addr;
+ struct sockaddr_in ia6_in4mask;
+ struct sockaddr_in *sin;
struct stf_softc *sc;
- struct in_addr a, b, mask;
+ struct ifnet *ifp;
+ int ret = 0;
+ DEBUG_PRINTF(1, "%s: enter\n", __func__);
sc = (struct stf_softc *)arg;
if (sc == NULL)
return 0;
+ ifp = STF2IFP(sc);
- if ((STF2IFP(sc)->if_flags & IFF_UP) == 0)
+ if ((ifp->if_flags & IFF_UP) == 0)
return 0;
/* IFF_LINK0 means "no decapsulation" */
- if ((STF2IFP(sc)->if_flags & IFF_LINK0) != 0)
+ if ((ifp->if_flags & IFF_LINK0) != 0)
return 0;
if (proto != IPPROTO_IPV6)
@@ -338,86 +383,162 @@ stf_encapcheck(m, off, proto, arg)
if (ip.ip_v != 4)
return 0;
- ia6 = stf_getsrcifa6(STF2IFP(sc));
+ /* Lookup an ia6 whose IPv4 addr encoded in the IPv6 addr is valid. */
+ ia6 = stf_getsrcifa6(ifp);
if (ia6 == NULL)
return 0;
+ sin = stf_getin4addr(&ia6_in4addr, &ia6->ia_ifa, STF_GETIN4_USE_CACHE);
+ if (sin == NULL)
+ return 0;
+#if STF_DEBUG
+ {
+ char buf[INET6_ADDRSTRLEN + 1];
+ memset(&buf, 0, sizeof(buf));
+
+ ip6_sprintf(buf, &satosin6(ia6->ia_ifa.ifa_addr)->sin6_addr);
+ DEBUG_PRINTF(1, "%s: ia6->ia_ifa.ifa_addr = %s\n", __func__, buf);
+ ip6_sprintf(buf, &ia6->ia_addr.sin6_addr);
+ DEBUG_PRINTF(1, "%s: ia6->ia_addr = %s\n", __func__, buf);
+ ip6_sprintf(buf, &satosin6(ia6->ia_ifa.ifa_netmask)->sin6_addr);
+ DEBUG_PRINTF(1, "%s: ia6->ia_ifa.ifa_netmask = %s\n", __func__, buf);
+ ip6_sprintf(buf, &ia6->ia_prefixmask.sin6_addr);
+ DEBUG_PRINTF(1, "%s: ia6->ia_prefixmask = %s\n", __func__, buf);
+
+ ip_sprintf(buf, &ia6_in4addr.sin_addr);
+ DEBUG_PRINTF(1, "%s: ia6_in4addr.sin_addr = %s\n", __func__, buf);
+ ip_sprintf(buf, &ip.ip_src);
+ DEBUG_PRINTF(1, "%s: ip.ip_src = %s\n", __func__, buf);
+ ip_sprintf(buf, &ip.ip_dst);
+ DEBUG_PRINTF(1, "%s: ip.ip_dst = %s\n", __func__, buf);
+ }
+#endif
/*
* check if IPv4 dst matches the IPv4 address derived from the
* local 6to4 address.
* success on: dst = 10.1.1.1, ia6->ia_addr = 2002:0a01:0101:...
*/
- if (bcmp(GET_V4(&ia6->ia_addr.sin6_addr), &ip.ip_dst,
- sizeof(ip.ip_dst)) != 0) {
- ifa_free(&ia6->ia_ifa);
- return 0;
+ DEBUG_PRINTF(1, "%s: check1: ia6_in4addr.sin_addr == ip.ip_dst?\n", __func__);
+ if (ia6_in4addr.sin_addr.s_addr != ip.ip_dst.s_addr) {
+ DEBUG_PRINTF(1, "%s: check1: false. Ignore this packet.\n", __func__);
+ goto freeit;
}
- /*
- * check if IPv4 src matches the IPv4 address derived from the
- * local 6to4 address masked by prefixmask.
- * success on: src = 10.1.1.1, ia6->ia_addr = 2002:0a00:.../24
- * fail on: src = 10.1.1.1, ia6->ia_addr = 2002:0b00:.../24
- */
- bzero(&a, sizeof(a));
- bcopy(GET_V4(&ia6->ia_addr.sin6_addr), &a, sizeof(a));
- bcopy(GET_V4(&ia6->ia_prefixmask.sin6_addr), &mask, sizeof(mask));
- ifa_free(&ia6->ia_ifa);
- a.s_addr &= mask.s_addr;
- b = ip.ip_src;
- b.s_addr &= mask.s_addr;
- if (a.s_addr != b.s_addr)
- return 0;
+ DEBUG_PRINTF(1, "%s: check2: ia6->ia_addr is 2002::/16?\n", __func__);
+ if (IN6_IS_ADDR_6TO4(&ia6->ia_addr.sin6_addr)) {
+ /* 6to4 (RFC 3056) */
+ /*
+ * check if IPv4 src matches the IPv4 address derived
+ * from the local 6to4 address masked by prefixmask.
+ * success on: src = 10.1.1.1, ia6->ia_addr = 2002:0a00:.../24
+ * fail on: src = 10.1.1.1, ia6->ia_addr = 2002:0b00:.../24
+ */
+ DEBUG_PRINTF(1, "%s: check2: true.\n", __func__);
+
+ memcpy(&ia6_in4mask.sin_addr,
+ GET_V4(&ia6->ia_prefixmask.sin6_addr),
+ sizeof(ia6_in4mask));
+#if STF_DEBUG
+ {
+ char buf[INET6_ADDRSTRLEN + 1];
+ memset(&buf, 0, sizeof(buf));
+
+ ip_sprintf(buf, &ia6_in4addr.sin_addr);
+ DEBUG_PRINTF(1, "%s: ia6->ia_addr = %s\n",
+ __func__, buf);
+ ip_sprintf(buf, &ip.ip_src);
+ DEBUG_PRINTF(1, "%s: ip.ip_src = %s\n",
+ __func__, buf);
+ ip_sprintf(buf, &ia6_in4mask.sin_addr);
+ DEBUG_PRINTF(1, "%s: ia6->ia_prefixmask = %s\n",
+ __func__, buf);
+
+ DEBUG_PRINTF(1, "%s: check3: ia6_in4addr.sin_addr & mask == ip.ip_src & mask\n",
+ __func__);
+ }
+#endif
+ if ((ia6_in4addr.sin_addr.s_addr & ia6_in4mask.sin_addr.s_addr) !=
+ (ip.ip_src.s_addr & ia6_in4mask.sin_addr.s_addr)) {
+ DEBUG_PRINTF(1, "%s: check3: false. Ignore this packet.\n",
+ __func__);
+ goto freeit;
+ }
+ } else {
+ /* 6rd (RFC 5569) */
+ DEBUG_PRINTF(1, "%s: check2: false. 6rd.\n", __func__);
+ /*
+ * No restriction on the src address in the case of
+ * 6rd because the stf(4) interface always has a
+ * prefix which covers whole of IPv4 src address
+ * range. So, stf_output() will catch all of
+ * 6rd-capsuled IPv4 traffic with suspicious inner dst
+ * IPv4 address (i.e. the IPv6 destination address is
+ * one the admin does not like to route to outside),
+ * and then it discard them silently.
+ */
+ }
+ DEBUG_PRINTF(1, "%s: all clear!\n", __func__);
/* stf interface makes single side match only */
- return 32;
+ ret = 32;
+freeit:
+ ifa_free(&ia6->ia_ifa);
+
+ return (ret);
}
static struct in6_ifaddr *
-stf_getsrcifa6(ifp)
- struct ifnet *ifp;
+stf_getsrcifa6(struct ifnet *ifp)
{
- struct ifaddr *ia;
+ struct ifaddr *ifa;
struct in_ifaddr *ia4;
- struct sockaddr_in6 *sin6;
- struct in_addr in;
+ struct sockaddr_in *sin;
+ struct sockaddr_in in4;
if_addr_rlock(ifp);
- TAILQ_FOREACH(ia, &ifp->if_addrhead, ifa_link) {
- if (ia->ifa_addr->sa_family != AF_INET6)
+ TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ if (ifa->ifa_addr->sa_family != AF_INET6)
continue;
- sin6 = (struct sockaddr_in6 *)ia->ifa_addr;
- if (!IN6_IS_ADDR_6TO4(&sin6->sin6_addr))
+ if ((sin = stf_getin4addr(&in4, ifa,
+ STF_GETIN4_USE_CACHE)) == NULL)
continue;
-
- bcopy(GET_V4(&sin6->sin6_addr), &in, sizeof(in));
- LIST_FOREACH(ia4, INADDR_HASH(in.s_addr), ia_hash)
- if (ia4->ia_addr.sin_addr.s_addr == in.s_addr)
+ LIST_FOREACH(ia4, INADDR_HASH(sin->sin_addr.s_addr), ia_hash)
+ if (ia4->ia_addr.sin_addr.s_addr == sin->sin_addr.s_addr)
break;
if (ia4 == NULL)
continue;
- ifa_ref(ia);
+#if STF_DEBUG
+ {
+ char buf[INET6_ADDRSTRLEN + 1];
+ memset(&buf, 0, sizeof(buf));
+
+ ip6_sprintf(buf, &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr);
+ DEBUG_PRINTF(1, "%s: ifa->ifa_addr->sin6_addr = %s\n",
+ __func__, buf);
+ ip_sprintf(buf, &ia4->ia_addr.sin_addr);
+ DEBUG_PRINTF(1, "%s: ia4->ia_addr.sin_addr = %s\n",
+ __func__, buf);
+ }
+#endif
+ ifa_ref(ifa);
if_addr_runlock(ifp);
- return (struct in6_ifaddr *)ia;
+ return (ifatoia6(ifa));
}
if_addr_runlock(ifp);
+
return NULL;
}
static int
-stf_output(ifp, m, dst, ro)
- struct ifnet *ifp;
- struct mbuf *m;
- struct sockaddr *dst;
- struct route *ro;
+stf_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct route *ro)
{
struct stf_softc *sc;
struct sockaddr_in6 *dst6;
struct route *cached_route;
- struct in_addr in4;
- caddr_t ptr;
+ struct sockaddr_in *sin;
+ struct sockaddr_in in4;
struct sockaddr_in *dst4;
u_int8_t tos;
struct ip *ip;
@@ -479,20 +600,28 @@ stf_output(ifp, m, dst, ro)
/*
* Pickup the right outer dst addr from the list of candidates.
* ip6_dst has priority as it may be able to give us shorter IPv4 hops.
+ * ip6_dst: destination addr in the packet header.
+ * dst6: destination addr specified in function argument.
*/
- ptr = NULL;
- if (IN6_IS_ADDR_6TO4(&ip6->ip6_dst))
- ptr = GET_V4(&ip6->ip6_dst);
- else if (IN6_IS_ADDR_6TO4(&dst6->sin6_addr))
- ptr = GET_V4(&dst6->sin6_addr);
- else {
+ DEBUG_PRINTF(1, "%s: dst addr selection\n", __func__);
+ sin = stf_getin4addr_in6(&in4, &ia6->ia_ifa, &ip6->ip6_dst);
+ if (sin == NULL)
+ sin = stf_getin4addr_in6(&in4, &ia6->ia_ifa, &dst6->sin6_addr);
+ if (sin == NULL) {
ifa_free(&ia6->ia_ifa);
m_freem(m);
ifp->if_oerrors++;
return ENETUNREACH;
}
- bcopy(ptr, &in4, sizeof(in4));
+#if STF_DEBUG
+ {
+ char buf[INET6_ADDRSTRLEN + 1];
+ memset(&buf, 0, sizeof(buf));
+ ip_sprintf(buf, &sin->sin_addr);
+ DEBUG_PRINTF(1, "%s: ip_dst = %s\n", __func__, buf);
+ }
+#endif
if (bpf_peers_present(ifp->if_bpf)) {
/*
* We need to prepend the address family as
@@ -516,11 +645,26 @@ stf_output(ifp, m, dst, ro)
ip = mtod(m, struct ip *);
bzero(ip, sizeof(*ip));
+ bcopy(&in4.sin_addr, &ip->ip_dst, sizeof(ip->ip_dst));
- bcopy(GET_V4(&((struct sockaddr_in6 *)&ia6->ia_addr)->sin6_addr),
- &ip->ip_src, sizeof(ip->ip_src));
+ sin = stf_getin4addr_sin6(&in4, &ia6->ia_ifa, &ia6->ia_addr);
+ if (sin == NULL) {
+ ifa_free(&ia6->ia_ifa);
+ m_freem(m);
+ ifp->if_oerrors++;
+ return ENETUNREACH;
+ }
+ bcopy(&in4.sin_addr, &ip->ip_src, sizeof(ip->ip_src));
+#if STF_DEBUG
+ {
+ char buf[INET6_ADDRSTRLEN + 1];
+ memset(&buf, 0, sizeof(buf));
+
+ ip_sprintf(buf, &ip->ip_src);
+ DEBUG_PRINTF(1, "%s: ip_src = %s\n", __func__, buf);
+ }
+#endif
ifa_free(&ia6->ia_ifa);
- bcopy(&in4, &ip->ip_dst, sizeof(ip->ip_dst));
ip->ip_p = IPPROTO_IPV6;
ip->ip_ttl = ip_stf_ttl;
ip->ip_len = m->m_pkthdr.len; /*host order*/
@@ -529,7 +673,7 @@ stf_output(ifp, m, dst, ro)
else
ip_ecn_ingress(ECN_NOCARE, &ip->ip_tos, &tos);
- if (!stf_route_cache) {
+ if (!V_stf_route_cache) {
cached_route = NULL;
goto sendit;
}
@@ -537,7 +681,7 @@ stf_output(ifp, m, dst, ro)
/*
* Do we have a cached route?
*/
- mtx_lock(&(sc)->sc_ro_mtx);
+ STF_LOCK(sc);
dst4 = (struct sockaddr_in *)&sc->sc_ro.ro_dst;
if (dst4->sin_family != AF_INET ||
bcmp(&dst4->sin_addr, &ip->ip_dst, sizeof(ip->ip_dst)) != 0) {
@@ -555,8 +699,15 @@ stf_output(ifp, m, dst, ro)
rtalloc_fib(&sc->sc_ro, sc->sc_fibnum);
if (sc->sc_ro.ro_rt == NULL) {
m_freem(m);
- mtx_unlock(&(sc)->sc_ro_mtx);
ifp->if_oerrors++;
+ STF_UNLOCK(sc);
+ return ENETUNREACH;
+ }
+ if (sc->sc_ro.ro_rt->rt_ifp == ifp) {
+ /* infinite loop detection */
+ m_free(m);
+ ifp->if_oerrors++;
+ STF_UNLOCK(sc);
return ENETUNREACH;
}
}
@@ -565,34 +716,31 @@ stf_output(ifp, m, dst, ro)
sendit:
M_SETFIB(m, sc->sc_fibnum);
ifp->if_opackets++;
+ DEBUG_PRINTF(1, "%s: ip_output dispatch.\n", __func__);
error = ip_output(m, NULL, cached_route, 0, NULL, NULL);
if (cached_route != NULL)
- mtx_unlock(&(sc)->sc_ro_mtx);
+ STF_UNLOCK(sc);
return error;
}
static int
-isrfc1918addr(in)
- struct in_addr *in;
+isrfc1918addr(struct in_addr *in)
{
/*
* returns 1 if private address range:
* 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16
*/
- if ((ntohl(in->s_addr) & 0xff000000) >> 24 == 10 ||
- (ntohl(in->s_addr) & 0xfff00000) >> 16 == 172 * 256 + 16 ||
- (ntohl(in->s_addr) & 0xffff0000) >> 16 == 192 * 256 + 168)
+ if ((ntohl(in->s_addr) & 0xff000000) == 10 << 24 ||
+ (ntohl(in->s_addr) & 0xfff00000) == (172 * 256 + 16) << 16 ||
+ (ntohl(in->s_addr) & 0xffff0000) == (192 * 256 + 168) << 16 )
return 1;
return 0;
}
static int
-stf_checkaddr4(sc, in, inifp)
- struct stf_softc *sc;
- struct in_addr *in;
- struct ifnet *inifp; /* incoming interface */
+stf_checkaddr4(struct stf_softc *sc, struct in_addr *in, struct ifnet *inifp)
{
struct in_ifaddr *ia4;
@@ -608,20 +756,10 @@ stf_checkaddr4(sc, in, inifp)
}
/*
- * reject packets with private address range.
- * (requirement from RFC3056 section 2 1st paragraph)
- */
- if (isrfc1918addr(in))
- return -1;
-
- /*
* reject packets with broadcast
*/
IN_IFADDR_RLOCK();
- for (ia4 = TAILQ_FIRST(&V_in_ifaddrhead);
- ia4;
- ia4 = TAILQ_NEXT(ia4, ia_link))
- {
+ TAILQ_FOREACH(ia4, &V_in_ifaddrhead, ia_link) {
if ((ia4->ia_ifa.ifa_ifp->if_flags & IFF_BROADCAST) == 0)
continue;
if (in->s_addr == ia4->ia_broadaddr.sin_addr.s_addr) {
@@ -640,7 +778,7 @@ stf_checkaddr4(sc, in, inifp)
bzero(&sin, sizeof(sin));
sin.sin_family = AF_INET;
- sin.sin_len = sizeof(struct sockaddr_in);
+ sin.sin_len = sizeof(sin);
sin.sin_addr = *in;
rt = rtalloc1_fib((struct sockaddr *)&sin, 0,
0UL, sc->sc_fibnum);
@@ -661,10 +799,7 @@ stf_checkaddr4(sc, in, inifp)
}
static int
-stf_checkaddr6(sc, in6, inifp)
- struct stf_softc *sc;
- struct in6_addr *in6;
- struct ifnet *inifp; /* incoming interface */
+stf_checkaddr6(struct stf_softc *sc, struct in6_addr *in6, struct ifnet *inifp)
{
/*
* check 6to4 addresses
@@ -688,9 +823,7 @@ stf_checkaddr6(sc, in6, inifp)
}
void
-in_stf_input(m, off)
- struct mbuf *m;
- int off;
+in_stf_input(struct mbuf *m, int off)
{
int proto;
struct stf_softc *sc;
@@ -698,6 +831,7 @@ in_stf_input(m, off)
struct ip6_hdr *ip6;
u_int8_t otos, itos;
struct ifnet *ifp;
+ struct route_in6 rin6;
proto = mtod(m, struct ip *)->ip_p;
@@ -721,6 +855,17 @@ in_stf_input(m, off)
mac_ifnet_create_mbuf(ifp, m);
#endif
+#if STF_DEBUG
+ {
+ char buf[INET6_ADDRSTRLEN + 1];
+ memset(&buf, 0, sizeof(buf));
+
+ ip_sprintf(buf, &ip->ip_dst);
+ DEBUG_PRINTF(1, "%s: ip->ip_dst = %s\n", __func__, buf);
+ ip_sprintf(buf, &ip->ip_src);
+ DEBUG_PRINTF(1, "%s: ip->ip_src = %s\n", __func__, buf);
+ }
+#endif
/*
* perform sanity check against outer src/dst.
* for source, perform ingress filter as well.
@@ -741,6 +886,17 @@ in_stf_input(m, off)
}
ip6 = mtod(m, struct ip6_hdr *);
+#if STF_DEBUG
+ {
+ char buf[INET6_ADDRSTRLEN + 1];
+ memset(&buf, 0, sizeof(buf));
+
+ ip6_sprintf(buf, &ip6->ip6_dst);
+ DEBUG_PRINTF(1, "%s: ip6->ip6_dst = %s\n", __func__, buf);
+ ip6_sprintf(buf, &ip6->ip6_src);
+ DEBUG_PRINTF(1, "%s: ip6->ip6_src = %s\n", __func__, buf);
+ }
+#endif
/*
* perform sanity check against inner src/dst.
* for source, perform ingress filter as well.
@@ -751,6 +907,41 @@ in_stf_input(m, off)
return;
}
+ /*
+ * reject packets with private address range.
+ * (requirement from RFC3056 section 2 1st paragraph)
+ */
+ if ((IN6_IS_ADDR_6TO4(&ip6->ip6_src) && isrfc1918addr(&ip->ip_src)) ||
+ (IN6_IS_ADDR_6TO4(&ip6->ip6_dst) && isrfc1918addr(&ip->ip_dst))) {
+ m_freem(m);
+ return;
+ }
+
+ /*
+ * Ignore if the destination is the same stf interface because
+ * all of valid IPv6 outgoing traffic should go interfaces
+ * except for it.
+ */
+ memset(&rin6, 0, sizeof(rin6));
+ rin6.ro_dst.sin6_len = sizeof(rin6.ro_dst);
+ rin6.ro_dst.sin6_family = AF_INET6;
+ memcpy(&rin6.ro_dst.sin6_addr, &ip6->ip6_dst,
+ sizeof(rin6.ro_dst.sin6_addr));
+ rtalloc((struct route *)&rin6);
+ if (rin6.ro_rt == NULL) {
+ DEBUG_PRINTF(1, "%s: no IPv6 dst. Ignored.\n", __func__);
+ m_free(m);
+ return;
+ }
+ if ((rin6.ro_rt->rt_ifp == ifp) &&
+ (!IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, &rin6.ro_dst.sin6_addr))) {
+ DEBUG_PRINTF(1, "%s: IPv6 dst is the same stf. Ignored.\n", __func__);
+ RTFREE(rin6.ro_rt);
+ m_free(m);
+ return;
+ }
+ RTFREE(rin6.ro_rt);
+
itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
if ((ifp->if_flags & IFF_LINK1) != 0)
ip_ecn_egress(ECN_ALLOWED, &otos, &itos);
@@ -760,7 +951,7 @@ in_stf_input(m, off)
ip6->ip6_flow |= htonl((u_int32_t)itos << 20);
m->m_pkthdr.rcvif = ifp;
-
+
if (bpf_peers_present(ifp->if_bpf)) {
/*
* We need to prepend the address family as
@@ -773,6 +964,7 @@ in_stf_input(m, off)
bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m);
}
+ DEBUG_PRINTF(1, "%s: netisr_dispatch(NETISR_IPV6)\n", __func__);
/*
* Put the packet to the network layer input queue according to the
* specified address family.
@@ -786,50 +978,424 @@ in_stf_input(m, off)
/* ARGSUSED */
static void
-stf_rtrequest(cmd, rt, info)
- int cmd;
- struct rtentry *rt;
- struct rt_addrinfo *info;
+stf_rtrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info)
{
+
RT_LOCK_ASSERT(rt);
rt->rt_rmx.rmx_mtu = IPV6_MMTU;
}
+/* Check whether we have at least one instance with IFF_UP. */
static int
-stf_ioctl(ifp, cmd, data)
- struct ifnet *ifp;
- u_long cmd;
- caddr_t data;
+stf_is_up(struct ifnet *ifp)
+{
+ struct stf_softc *scp;
+ struct stf_softc *sc_cur;
+ struct stf_softc *sc_is_up;
+
+ sc_is_up = NULL;
+ if ((sc_cur = ifp->if_softc) == NULL)
+ return (EINVAL);
+
+ mtx_lock(&stf_mtx);
+ LIST_FOREACH(scp, &V_stf_softc_list, stf_list) {
+ if (scp == sc_cur)
+ continue;
+ if ((STF2IFP(scp)->if_flags & IFF_UP) != 0) {
+ sc_is_up = scp;
+ break;
+ }
+ }
+ mtx_unlock(&stf_mtx);
+
+ /* We already has at least one instance with IFF_UP. */
+ if (stf_is_up != NULL)
+ return (ENOSPC);
+
+ return (0);
+}
+
+static struct sockaddr_in *
+stf_getin4addr_in6(struct sockaddr_in *sin,
+ struct ifaddr *ifa,
+ struct in6_addr *in6)
+{
+ struct sockaddr_in6 sin6;
+
+ DEBUG_PRINTF(1, "%s: enter.\n", __func__);
+ if (ifa == NULL || in6 == NULL)
+ return NULL;
+
+ memset(&sin6, 0, sizeof(sin6));
+ memcpy(&sin6.sin6_addr, in6, sizeof(sin6.sin6_addr));
+ sin6.sin6_len = sizeof(sin6);
+ sin6.sin6_family = AF_INET6;
+
+ return(stf_getin4addr_sin6(sin, ifa, &sin6));
+}
+
+static struct sockaddr_in *
+stf_getin4addr_sin6(struct sockaddr_in *sin,
+ struct ifaddr *ifa,
+ struct sockaddr_in6 *sin6)
+{
+ struct in6_ifaddr ia6;
+ int i;
+
+ DEBUG_PRINTF(1, "%s: enter.\n", __func__);
+ if (ifa == NULL || sin6 == NULL)
+ return NULL;
+
+ memset(&ia6, 0, sizeof(ia6));
+ memcpy(&ia6, ifatoia6(ifa), sizeof(ia6));
+
+ /*
+ * Use prefixmask information from ifa, and
+ * address information from sin6.
+ */
+ ia6.ia_addr.sin6_family = AF_INET6;
+ ia6.ia_ifa.ifa_addr = (struct sockaddr *)&ia6.ia_addr;
+ ia6.ia_ifa.ifa_dstaddr = NULL;
+ ia6.ia_ifa.ifa_netmask = (struct sockaddr *)&ia6.ia_prefixmask;
+
+#if STF_DEBUG
+ {
+ char buf[INET6_ADDRSTRLEN + 1];
+ memset(&buf, 0, sizeof(buf));
+
+ ip6_sprintf(buf, &sin6->sin6_addr);
+ DEBUG_PRINTF(1, "%s: sin6->sin6_addr = %s\n", __func__, buf);
+ ip6_sprintf(buf, &ia6.ia_addr.sin6_addr);
+ DEBUG_PRINTF(1, "%s: ia6.ia_addr.sin6_addr = %s\n", __func__, buf);
+ ip6_sprintf(buf, &ia6.ia_prefixmask.sin6_addr);
+ DEBUG_PRINTF(1, "%s: ia6.ia_prefixmask.sin6_addr = %s\n", __func__, buf);
+ }
+#endif
+
+ /*
+ * When (src addr & src mask) != (dst (sin6) addr & src mask),
+ * the dst is not in the 6rd domain. The IPv4 address must
+ * not be used.
+ */
+ for (i = 0; i < sizeof(ia6.ia_addr.sin6_addr); i++) {
+ if ((((u_char *)&ia6.ia_addr.sin6_addr)[i] &
+ ((u_char *)&ia6.ia_prefixmask.sin6_addr)[i])
+ !=
+ (((u_char *)&sin6->sin6_addr)[i] &
+ ((u_char *)&ia6.ia_prefixmask.sin6_addr)[i]))
+ return NULL;
+ }
+
+ /* After the mask check, overwrite ia6.ia_addr with sin6. */
+ memcpy(&ia6.ia_addr, sin6, sizeof(ia6.ia_addr));
+ return(stf_getin4addr(sin, (struct ifaddr *)&ia6, 0));
+}
+
+static struct sockaddr_in *
+stf_getin4addr(struct sockaddr_in *sin,
+ struct ifaddr *ifa,
+ int flags)
+{
+ struct in_addr *in;
+ struct sockaddr_in6 *sin6;
+ struct sockaddr_in6 *sin6d;
+ struct in6_ifaddr *ia6;
+
+ DEBUG_PRINTF(1, "%s: enter.\n", __func__);
+ if (ifa == NULL ||
+ ifa->ifa_addr == NULL ||
+ ifa->ifa_addr->sa_family != AF_INET6)
+ return NULL;
+
+ sin6 = satosin6(ifa->ifa_addr);
+ ia6 = ifatoia6(ifa);
+
+ if (ifa->ifa_dstaddr != NULL) {
+ switch (ifa->ifa_dstaddr->sa_family) {
+ case AF_INET6:
+ sin6d = satosin6(ifa->ifa_dstaddr);
+ if (IN6_IS_ADDR_UNSPECIFIED(&sin6d->sin6_addr))
+ break;
+ if (IN6_IS_ADDR_V4COMPAT(&sin6d->sin6_addr)) {
+ memset(sin, 0, sizeof(*sin));
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr =
+ *(const u_int32_t *)(const void *)(&sin6d->sin6_addr.s6_addr[12]);
+ if (flags & STF_GETIN4_USE_CACHE) {
+ /*
+ * XXX: ifa_dstaddr is used as a cache of the
+ * extracted IPv4 address.
+ */
+ memcpy(sin, satosin(ifa->ifa_dstaddr), sizeof(*sin));
+ ifa->ifa_dstaddr->sa_family = AF_INET;
+ }
+#if STF_DEBUG
+ {
+ char buf[INET6_ADDRSTRLEN + 1];
+ memset(&buf, 0, sizeof(buf));
+
+ ip_sprintf(buf, &sin->sin_addr);
+ DEBUG_PRINTF(1, "%s: specified dst address was used = %s\n", __func__, buf);
+ }
+#endif
+ return (sin);
+ } else {
+ DEBUG_PRINTF(1, "Not a V4COMPAT address!\n");
+ return (NULL);
+ }
+ /* NOT REACHED */
+ break;
+ case AF_INET:
+ if (flags & STF_GETIN4_USE_CACHE) {
+ /*
+ * XXX: ifa_dstaddr is used as a cache of the
+ * extracted IPv4 address.
+ */
+ memcpy(sin, satosin(ifa->ifa_dstaddr), sizeof(*sin));
+ ifa->ifa_dstaddr->sa_family = AF_INET;
+#if STF_DEBUG
+ {
+ char buf[INET6_ADDRSTRLEN + 1];
+ memset(&buf, 0, sizeof(buf));
+
+ ip_sprintf(buf, &sin->sin_addr);
+ DEBUG_PRINTF(1, "%s: cached address was used = %s\n", __func__, buf);
+ }
+#endif
+ return (sin);
+ }
+ }
+ }
+ memset(sin, 0, sizeof(*sin));
+ in = &sin->sin_addr;
+
+#if STF_DEBUG
+ {
+ char buf[INET6_ADDRSTRLEN + 1];
+ memset(&buf, 0, sizeof(buf));
+
+ ip6_sprintf(buf, &sin6->sin6_addr);
+ DEBUG_PRINTF(1, "%s: sin6->sin6_addr = %s\n", __func__, buf);
+ }
+#endif
+
+ if (IN6_IS_ADDR_6TO4(&sin6->sin6_addr)) {
+ /* 6to4 (RFC 3056) */
+ bcopy(GET_V4(&sin6->sin6_addr), in, sizeof(*in));
+ if (isrfc1918addr(in))
+ return NULL;
+ } else {
+ /* 6rd (RFC 5569) */
+ struct in6_addr buf;
+ u_char *p = (u_char *)&buf;
+ u_char *q = (u_char *)in;
+ u_int residue = 0;
+ u_char mask;
+ int i;
+ u_int plen;
+
+ /*
+ * 6rd-relays IPv6 prefix is located at a 32-bit just
+ * after the prefix edge.
+ */
+ plen = in6_mask2len(&satosin6(ifa->ifa_netmask)->sin6_addr, NULL);
+ if (32 < plen)
+ return NULL;
+
+ memcpy(&buf, &sin6->sin6_addr, sizeof(buf));
+ p += plen / 8;
+ residue = plen % 8;
+ mask = ~((u_char)(-1) >> residue);
+
+ /*
+ * The p points head of the IPv4 address part in
+ * bytes. The residue is a bit-shift factor when
+ * prefixlen is not a multiple of 8.
+ */
+ for (i = 0; i < 4; i++) {
+ DEBUG_PRINTF(2, "p[%d] = %d\n", i, p[i]);
+ DEBUG_PRINTF(2, "residue = %d\n", residue);
+ if (residue) {
+ p[i] <<= residue;
+ DEBUG_PRINTF(2, "p[%d] << residue = %d\n",
+ i, p[i]);
+ DEBUG_PRINTF(2, "mask = %x\n",
+ mask);
+ DEBUG_PRINTF(2, "p[%d + 1] & mask = %d\n",
+ i, p[i + 1] & mask);
+ DEBUG_PRINTF(2, "p[%d + 1] & mask >> (8 - residue) = %d\n",
+ i, (p[i + 1] & mask) >> (8-residue));
+ p[i] |= ((p[i+1] & mask) >> (8 - residue));
+ }
+ q[i] = p[i];
+ }
+ }
+#if STF_DEBUG
+ {
+ char buf[INET6_ADDRSTRLEN + 1];
+ memset(&buf, 0, sizeof(buf));
+
+ ip_sprintf(buf, in);
+ DEBUG_PRINTF(1, "%s: in->in_addr = %s\n", __func__, buf);
+ DEBUG_PRINTF(1, "%s: leave\n", __func__);
+ }
+#endif
+ if (flags & STF_GETIN4_USE_CACHE) {
+ DEBUG_PRINTF(1, "%s: try to memset 0 to ia_dstaddr.\n", __func__);
+ memset(&ia6->ia_dstaddr, 0, sizeof(ia6->ia_dstaddr));
+ DEBUG_PRINTF(1, "%s: try to access ifa->ifa_dstaddr.\n", __func__);
+ ifa->ifa_dstaddr = (struct sockaddr *)&ia6->ia_dstaddr;
+ DEBUG_PRINTF(1, "%s: try to memcpy ifa->ifa_dstaddr.\n", __func__);
+ memcpy((struct sockaddr_in *)ifa->ifa_dstaddr,
+ sin, sizeof(struct sockaddr_in));
+ DEBUG_PRINTF(1, "%s: try to set sa_family.\n", __func__);
+ ifa->ifa_dstaddr->sa_family = AF_INET;
+ DEBUG_PRINTF(1, "%s: in->in_addr is stored in ifa_dstaddr.\n",
+ __func__);
+ }
+ return (sin);
+}
+
+static void
+stf_ifaddr_change(void *arg __unused, struct ifnet *ifp)
+{
+ struct sockaddr_in in4;
+ struct ifaddr *ifa;
+
+ DEBUG_PRINTF(1, "%s: enter.\n", __func__);
+
+ if_addr_rlock(ifp);
+ TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
+ if (ifa->ifa_addr == NULL)
+ continue;
+ if (ifa->ifa_addr->sa_family != AF_INET6)
+ continue;
+ if (ifa->ifa_dstaddr != NULL) {
+ DEBUG_PRINTF(1, "%s: ifa->ifa_dstaddr != NULL!.\n", __func__);
+
+#if STF_DEBUG
+ {
+ char buf[INET6_ADDRSTRLEN + 1];
+ memset(&buf, 0, sizeof(buf));
+
+ ip6_sprintf(buf, &satosin6(ifa->ifa_addr)->sin6_addr);
+ DEBUG_PRINTF(1, "%s: ifa_addr = %s\n", __func__, buf);
+ }
+#endif
+ switch (ifa->ifa_dstaddr->sa_family) {
+ case AF_INET:
+#if STF_DEBUG
+ {
+ char buf[INET6_ADDRSTRLEN + 1];
+ memset(&buf, 0, sizeof(buf));
+
+ ip_sprintf(buf, &satosin(ifa->ifa_dstaddr)->sin_addr);
+ DEBUG_PRINTF(1, "%s: ifa_dstaddr = %s\n", __func__, buf);
+ }
+#endif
+ continue;
+ case AF_INET6:
+#if STF_DEBUG
+ {
+ char buf[INET6_ADDRSTRLEN + 1];
+ memset(&buf, 0, sizeof(buf));
+
+ ip6_sprintf(buf, &satosin6(ifa->ifa_dstaddr)->sin6_addr);
+ DEBUG_PRINTF(1, "%s: ifa_dstaddr = %s\n", __func__, buf);
+ }
+#endif
+ if (IN6_IS_ADDR_V4COMPAT(&satosin6(ifa->ifa_dstaddr)->sin6_addr)) {
+ }
+ if (!IN6_IS_ADDR_UNSPECIFIED(&satosin6(ifa->ifa_dstaddr)->sin6_addr))
+ continue;
+ }
+ }
+ DEBUG_PRINTF(1, "%s: ifa->ifa_dstaddr == NULL or ::!.\n", __func__);
+ /*
+ * Extract IPv4 address from IPv6 address,
+ * then store it into ifa_dstaddr as the
+ * destination.
+ */
+ if (stf_getin4addr(&in4, ifa, STF_GETIN4_USE_CACHE) == NULL) {
+ ifatoia6(ifa)->ia_flags |= IN6_IFF_DETACHED;
+ continue;
+ }
+ }
+ if_addr_runlock(ifp);
+}
+
+static int
+stf_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
struct ifaddr *ifa;
struct ifreq *ifr;
- struct sockaddr_in6 *sin6;
- struct in_addr addr;
+/*
+ struct in6_aliasreq *ifra6;
+*/
+ struct in6_aliasreq ifra;
+/*
+ struct sockaddr_in6 *sa6;
+*/
int error;
+ memset(&ifra, 0, sizeof(ifra));
+ /*
+ * Sanity check: if more than two interfaces have IFF_UP, do
+ * if_down() for all of them except for the specified one.
+ */
+ if (ifp->if_flags & IFF_UP) {
+ struct stf_softc *sc_cur = ifp->if_softc;
+ struct stf_softc *sc;
+
+ mtx_lock(&stf_mtx);
+ LIST_FOREACH(sc, &V_stf_softc_list, stf_list) {
+ if (sc == sc_cur)
+ continue;
+ if ((STF2IFP(sc)->if_flags & IFF_UP) != 0) {
+ if_printf(STF2IFP(sc),
+ "marked as DOWN because at least "
+ "one instance of stf(4) is already "
+ "working.\n");
+ if_down(STF2IFP(sc));
+ }
+ }
+ mtx_unlock(&stf_mtx);
+ }
+
error = 0;
switch (cmd) {
case SIOCSIFADDR:
+ DEBUG_PRINTF(1, "enter SIOCSIFADDR.\n");
ifa = (struct ifaddr *)data;
if (ifa == NULL || ifa->ifa_addr->sa_family != AF_INET6) {
error = EAFNOSUPPORT;
break;
}
- sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
- if (!IN6_IS_ADDR_6TO4(&sin6->sin6_addr)) {
- error = EINVAL;
+ ifa->ifa_rtrequest = stf_rtrequest;
+ ifp->if_flags |= IFF_UP;
+ break;
+
+/*
+ case STFSSRDADDR:
+ ifra6 = (struct in6_aliasreq *)data;
+ if (ifra6 == NULL || ifra6->ifra_addr->sa_family != AF_INET6) {
+ error = EAFNOSUPPORT;
break;
}
- bcopy(GET_V4(&sin6->sin6_addr), &addr, sizeof(addr));
- if (isrfc1918addr(&addr)) {
- error = EINVAL;
+ sa6 = &ifra6->ifra_addr;
+ if (ifra6->ifra_dstaddr->sa_family != AF_INET) {
+ error = EAFNOSUPPORT;
break;
}
-
- ifa->ifa_rtrequest = stf_rtrequest;
- ifp->if_flags |= IFF_UP;
+ memcpy(&ifra.ifra_addr, sa6, sizeof(ifra.ifra_addr));
+ error = in6_control(NULL, SIOCAIFADDR_IN6, (caddr_t)&ifra, ifp, curthread);
+ if (error)
+ return (error);
+
break;
-
+
+ case STFDSRDADDR:
+*/
case SIOCADDMULTI:
case SIOCDELMULTI:
ifr = (struct ifreq *)data;
diff --git a/sys/net/if_tun.c b/sys/net/if_tun.c
index 4e727d9..49a5249 100644
--- a/sys/net/if_tun.c
+++ b/sys/net/if_tun.c
@@ -126,7 +126,7 @@ static void tunclone(void *arg, struct ucred *cred, char *name,
int namelen, struct cdev **dev);
static void tuncreate(const char *name, struct cdev *dev);
static int tunifioctl(struct ifnet *, u_long, caddr_t);
-static int tuninit(struct ifnet *);
+static void tuninit(struct ifnet *);
static int tunmodevent(module_t, int, void *);
static int tunoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
struct route *ro);
@@ -494,14 +494,13 @@ tunclose(struct cdev *dev, int foo, int bar, struct thread *td)
return (0);
}
-static int
+static void
tuninit(struct ifnet *ifp)
{
struct tun_softc *tp = ifp->if_softc;
#ifdef INET
struct ifaddr *ifa;
#endif
- int error = 0;
TUNDEBUG(ifp, "tuninit\n");
@@ -528,7 +527,6 @@ tuninit(struct ifnet *ifp)
if_addr_runlock(ifp);
#endif
mtx_unlock(&tp->tun_mtx);
- return (error);
}
/*
@@ -552,12 +550,12 @@ tunifioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
mtx_unlock(&tp->tun_mtx);
break;
case SIOCSIFADDR:
- error = tuninit(ifp);
- TUNDEBUG(ifp, "address set, error=%d\n", error);
+ tuninit(ifp);
+ TUNDEBUG(ifp, "address set\n");
break;
case SIOCSIFDSTADDR:
- error = tuninit(ifp);
- TUNDEBUG(ifp, "destination address set, error=%d\n", error);
+ tuninit(ifp);
+ TUNDEBUG(ifp, "destination address set\n");
break;
case SIOCSIFMTU:
ifp->if_mtu = ifr->ifr_mtu;
@@ -857,7 +855,6 @@ tunwrite(struct cdev *dev, struct uio *uio, int flag)
struct tun_softc *tp = dev->si_drv1;
struct ifnet *ifp = TUN2IFP(tp);
struct mbuf *m;
- int error = 0;
uint32_t family;
int isr;
@@ -877,7 +874,7 @@ tunwrite(struct cdev *dev, struct uio *uio, int flag)
if ((m = m_uiotombuf(uio, M_DONTWAIT, 0, 0, M_PKTHDR)) == NULL) {
ifp->if_ierrors++;
- return (error);
+ return (ENOBUFS);
}
m->m_pkthdr.rcvif = ifp;
diff --git a/sys/net/netisr.c b/sys/net/netisr.c
index 67ec160..127cf67 100644
--- a/sys/net/netisr.c
+++ b/sys/net/netisr.c
@@ -1221,7 +1221,7 @@ netisr_start(void *arg)
{
struct pcpu *pc;
- SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
+ STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
if (nws_count >= netisr_maxthreads)
break;
/* XXXRW: Is skipping absent CPUs still required here? */
diff --git a/sys/net80211/ieee80211_ht.c b/sys/net80211/ieee80211_ht.c
index 8c4d7d3..c9d8448 100644
--- a/sys/net80211/ieee80211_ht.c
+++ b/sys/net80211/ieee80211_ht.c
@@ -2520,6 +2520,7 @@ ieee80211_add_htcap_body(uint8_t *frm, struct ieee80211_node *ni)
frm[1] = (v) >> 8; \
frm += 2; \
} while (0)
+ struct ieee80211com *ic = ni->ni_ic;
struct ieee80211vap *vap = ni->ni_vap;
uint16_t caps, extcaps;
int rxmax, density;
@@ -2543,6 +2544,17 @@ ieee80211_add_htcap_body(uint8_t *frm, struct ieee80211_node *ni)
/* use advertised setting (XXX locally constraint) */
rxmax = MS(ni->ni_htparam, IEEE80211_HTCAP_MAXRXAMPDU);
density = MS(ni->ni_htparam, IEEE80211_HTCAP_MPDUDENSITY);
+
+ /*
+ * NB: Hardware might support HT40 on some but not all
+ * channels. We can't determine this earlier because only
+ * after association the channel is upgraded to HT based
+ * on the negotiated capabilities.
+ */
+ if (ni->ni_chan != IEEE80211_CHAN_ANYC &&
+ findhtchan(ic, ni->ni_chan, IEEE80211_CHAN_HT40U) == NULL &&
+ findhtchan(ic, ni->ni_chan, IEEE80211_CHAN_HT40D) == NULL)
+ caps &= ~IEEE80211_HTCAP_CHWIDTH40;
} else {
/* override 20/40 use based on current channel */
if (IEEE80211_IS_CHAN_HT40(ni->ni_chan))
diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c
index b689310..6020144 100644
--- a/sys/net80211/ieee80211_output.c
+++ b/sys/net80211/ieee80211_output.c
@@ -516,6 +516,7 @@ ieee80211_send_setup(
{
#define WH4(wh) ((struct ieee80211_frame_addr4 *)wh)
struct ieee80211vap *vap = ni->ni_vap;
+ struct ieee80211_tx_ampdu *tap;
struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);
ieee80211_seq seqno;
@@ -583,9 +584,15 @@ ieee80211_send_setup(
}
*(uint16_t *)&wh->i_dur[0] = 0;
- seqno = ni->ni_txseqs[tid]++;
- *(uint16_t *)&wh->i_seq[0] = htole16(seqno << IEEE80211_SEQ_SEQ_SHIFT);
- M_SEQNO_SET(m, seqno);
+ tap = &ni->ni_tx_ampdu[TID_TO_WME_AC(tid)];
+ if (tid != IEEE80211_NONQOS_TID && IEEE80211_AMPDU_RUNNING(tap))
+ m->m_flags |= M_AMPDU_MPDU;
+ else {
+ seqno = ni->ni_txseqs[tid]++;
+ *(uint16_t *)&wh->i_seq[0] =
+ htole16(seqno << IEEE80211_SEQ_SEQ_SHIFT);
+ M_SEQNO_SET(m, seqno);
+ }
if (IEEE80211_IS_MULTICAST(wh->i_addr1))
m->m_flags |= M_MCAST;
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 85e31dc..4aa998f 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -128,8 +128,12 @@ static VNET_DEFINE(int, ipport_tcplastcount);
#define V_ipport_tcplastcount VNET(ipport_tcplastcount)
static void in_pcbremlists(struct inpcb *inp);
-
#ifdef INET
+static struct inpcb *in_pcblookup_hash_locked(struct inpcbinfo *pcbinfo,
+ struct in_addr faddr, u_int fport_arg,
+ struct in_addr laddr, u_int lport_arg,
+ int lookupflags, struct ifnet *ifp);
+
#define RANGECHK(var, min, max) \
if ((var) < (min)) { (var) = (min); } \
else if ((var) > (max)) { (var) = (max); }
@@ -212,11 +216,13 @@ in_pcbinfo_init(struct inpcbinfo *pcbinfo, const char *name,
{
INP_INFO_LOCK_INIT(pcbinfo, name);
+ INP_HASH_LOCK_INIT(pcbinfo, "pcbinfohash"); /* XXXRW: argument? */
#ifdef VIMAGE
pcbinfo->ipi_vnet = curvnet;
#endif
pcbinfo->ipi_listhead = listhead;
LIST_INIT(pcbinfo->ipi_listhead);
+ pcbinfo->ipi_count = 0;
pcbinfo->ipi_hashbase = hashinit(hash_nelements, M_PCB,
&pcbinfo->ipi_hashmask);
pcbinfo->ipi_porthashbase = hashinit(porthash_nelements, M_PCB,
@@ -234,10 +240,14 @@ void
in_pcbinfo_destroy(struct inpcbinfo *pcbinfo)
{
+ KASSERT(pcbinfo->ipi_count == 0,
+ ("%s: ipi_count = %u", __func__, pcbinfo->ipi_count));
+
hashdestroy(pcbinfo->ipi_hashbase, M_PCB, pcbinfo->ipi_hashmask);
hashdestroy(pcbinfo->ipi_porthashbase, M_PCB,
pcbinfo->ipi_porthashmask);
uma_zdestroy(pcbinfo->ipi_zone);
+ INP_HASH_LOCK_DESTROY(pcbinfo);
INP_INFO_LOCK_DESTROY(pcbinfo);
}
@@ -309,8 +319,8 @@ in_pcbbind(struct inpcb *inp, struct sockaddr *nam, struct ucred *cred)
{
int anonport, error;
- INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
INP_WLOCK_ASSERT(inp);
+ INP_HASH_WLOCK_ASSERT(inp->inp_pcbinfo);
if (inp->inp_lport != 0 || inp->inp_laddr.s_addr != INADDR_ANY)
return (EINVAL);
@@ -351,8 +361,8 @@ in_pcb_lport(struct inpcb *inp, struct in_addr *laddrp, u_short *lportp,
* Because no actual state changes occur here, a global write lock on
* the pcbinfo isn't required.
*/
- INP_INFO_LOCK_ASSERT(pcbinfo);
INP_LOCK_ASSERT(inp);
+ INP_HASH_LOCK_ASSERT(pcbinfo);
if (inp->inp_flags & INP_HIGHPORT) {
first = V_ipport_hifirstauto; /* sysctl */
@@ -473,11 +483,10 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,
int error;
/*
- * Because no actual state changes occur here, a global write lock on
- * the pcbinfo isn't required.
+ * No state changes, so read locks are sufficient here.
*/
- INP_INFO_LOCK_ASSERT(pcbinfo);
INP_LOCK_ASSERT(inp);
+ INP_HASH_LOCK_ASSERT(pcbinfo);
if (TAILQ_EMPTY(&V_in_ifaddrhead)) /* XXX broken! */
return (EADDRNOTAVAIL);
@@ -612,14 +621,15 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,
* then pick one.
*/
int
-in_pcbconnect(struct inpcb *inp, struct sockaddr *nam, struct ucred *cred)
+in_pcbconnect_mbuf(struct inpcb *inp, struct sockaddr *nam,
+ struct ucred *cred, struct mbuf *m)
{
u_short lport, fport;
in_addr_t laddr, faddr;
int anonport, error;
- INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
INP_WLOCK_ASSERT(inp);
+ INP_HASH_WLOCK_ASSERT(inp->inp_pcbinfo);
lport = inp->inp_lport;
laddr = inp->inp_laddr.s_addr;
@@ -645,13 +655,20 @@ in_pcbconnect(struct inpcb *inp, struct sockaddr *nam, struct ucred *cred)
inp->inp_laddr.s_addr = laddr;
inp->inp_faddr.s_addr = faddr;
inp->inp_fport = fport;
- in_pcbrehash(inp);
+ in_pcbrehash_mbuf(inp, m);
if (anonport)
inp->inp_flags |= INP_ANONPORT;
return (0);
}
+int
+in_pcbconnect(struct inpcb *inp, struct sockaddr *nam, struct ucred *cred)
+{
+
+ return (in_pcbconnect_mbuf(inp, nam, cred, NULL));
+}
+
/*
* Do proper source address selection on an unbound socket in case
* of connect. Take jails into account as well.
@@ -907,8 +924,8 @@ in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam,
* Because a global state change doesn't actually occur here, a read
* lock is sufficient.
*/
- INP_INFO_LOCK_ASSERT(inp->inp_pcbinfo);
INP_LOCK_ASSERT(inp);
+ INP_HASH_LOCK_ASSERT(inp->inp_pcbinfo);
if (oinpp != NULL)
*oinpp = NULL;
@@ -983,8 +1000,8 @@ in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam,
if (error)
return (error);
}
- oinp = in_pcblookup_hash(inp->inp_pcbinfo, faddr, fport, laddr, lport,
- 0, NULL);
+ oinp = in_pcblookup_hash_locked(inp->inp_pcbinfo, faddr, fport,
+ laddr, lport, 0, NULL);
if (oinp != NULL) {
if (oinpp != NULL)
*oinpp = oinp;
@@ -1007,8 +1024,8 @@ void
in_pcbdisconnect(struct inpcb *inp)
{
- INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
INP_WLOCK_ASSERT(inp);
+ INP_HASH_WLOCK_ASSERT(inp->inp_pcbinfo);
inp->inp_faddr.s_addr = INADDR_ANY;
inp->inp_fport = 0;
@@ -1187,19 +1204,24 @@ void
in_pcbdrop(struct inpcb *inp)
{
- INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
INP_WLOCK_ASSERT(inp);
+ /*
+ * XXXRW: Possibly we should protect the setting of INP_DROPPED with
+ * the hash lock...?
+ */
inp->inp_flags |= INP_DROPPED;
if (inp->inp_flags & INP_INHASHLIST) {
struct inpcbport *phd = inp->inp_phd;
+ INP_HASH_WLOCK(inp->inp_pcbinfo);
LIST_REMOVE(inp, inp_hash);
LIST_REMOVE(inp, inp_portlist);
if (LIST_FIRST(&phd->phd_pcblist) == NULL) {
LIST_REMOVE(phd, phd_hash);
free(phd, M_PCB);
}
+ INP_HASH_WUNLOCK(inp->inp_pcbinfo);
inp->inp_flags &= ~INP_INHASHLIST;
}
}
@@ -1328,7 +1350,8 @@ in_pcbpurgeif0(struct inpcbinfo *pcbinfo, struct ifnet *ifp)
}
/*
- * Lookup a PCB based on the local address and port.
+ * Lookup a PCB based on the local address and port. Caller must hold the
+ * hash lock. No inpcb locks or references are acquired.
*/
#define INP_LOOKUP_MAPPED_PCB_COST 3
struct inpcb *
@@ -1346,7 +1369,7 @@ in_pcblookup_local(struct inpcbinfo *pcbinfo, struct in_addr laddr,
KASSERT((lookupflags & ~(INPLOOKUP_WILDCARD)) == 0,
("%s: invalid lookup flags %d", __func__, lookupflags));
- INP_INFO_LOCK_ASSERT(pcbinfo);
+ INP_HASH_LOCK_ASSERT(pcbinfo);
if ((lookupflags & INPLOOKUP_WILDCARD) == 0) {
struct inpcbhead *head;
@@ -1450,10 +1473,12 @@ in_pcblookup_local(struct inpcbinfo *pcbinfo, struct in_addr laddr,
#undef INP_LOOKUP_MAPPED_PCB_COST
/*
- * Lookup PCB in hash list.
+ * Lookup PCB in hash list, using pcbinfo tables. This variation assumes
+ * that the caller has locked the hash list, and will not perform any further
+ * locking or reference operations on either the hash list or the connection.
*/
-struct inpcb *
-in_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in_addr faddr,
+static struct inpcb *
+in_pcblookup_hash_locked(struct inpcbinfo *pcbinfo, struct in_addr faddr,
u_int fport_arg, struct in_addr laddr, u_int lport_arg, int lookupflags,
struct ifnet *ifp)
{
@@ -1464,7 +1489,7 @@ in_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in_addr faddr,
KASSERT((lookupflags & ~(INPLOOKUP_WILDCARD)) == 0,
("%s: invalid lookup flags %d", __func__, lookupflags));
- INP_INFO_LOCK_ASSERT(pcbinfo);
+ INP_HASH_LOCK_ASSERT(pcbinfo);
/*
* First look for an exact match.
@@ -1574,6 +1599,72 @@ in_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in_addr faddr,
return (NULL);
}
+
+/*
+ * Lookup PCB in hash list, using pcbinfo tables. This variation locks the
+ * hash list lock, and will return the inpcb locked (i.e., requires
+ * INPLOOKUP_LOCKPCB).
+ */
+static struct inpcb *
+in_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in_addr faddr,
+ u_int fport, struct in_addr laddr, u_int lport, int lookupflags,
+ struct ifnet *ifp)
+{
+ struct inpcb *inp;
+
+ INP_HASH_RLOCK(pcbinfo);
+ inp = in_pcblookup_hash_locked(pcbinfo, faddr, fport, laddr, lport,
+ (lookupflags & ~(INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB)), ifp);
+ if (inp != NULL) {
+ in_pcbref(inp);
+ INP_HASH_RUNLOCK(pcbinfo);
+ if (lookupflags & INPLOOKUP_WLOCKPCB) {
+ INP_WLOCK(inp);
+ if (in_pcbrele_wlocked(inp))
+ return (NULL);
+ } else if (lookupflags & INPLOOKUP_RLOCKPCB) {
+ INP_RLOCK(inp);
+ if (in_pcbrele_rlocked(inp))
+ return (NULL);
+ } else
+ panic("%s: locking bug", __func__);
+ } else
+ INP_HASH_RUNLOCK(pcbinfo);
+ return (inp);
+}
+
+/*
+ * Public inpcb lookup routines, accepting a 4-tuple, and optionally, an mbuf
+ * from which a pre-calculated hash value may be extracted.
+ */
+struct inpcb *
+in_pcblookup(struct inpcbinfo *pcbinfo, struct in_addr faddr, u_int fport,
+ struct in_addr laddr, u_int lport, int lookupflags, struct ifnet *ifp)
+{
+
+ KASSERT((lookupflags & ~INPLOOKUP_MASK) == 0,
+ ("%s: invalid lookup flags %d", __func__, lookupflags));
+ KASSERT((lookupflags & (INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB)) != 0,
+ ("%s: LOCKPCB not set", __func__));
+
+ return (in_pcblookup_hash(pcbinfo, faddr, fport, laddr, lport,
+ lookupflags, ifp));
+}
+
+struct inpcb *
+in_pcblookup_mbuf(struct inpcbinfo *pcbinfo, struct in_addr faddr,
+ u_int fport, struct in_addr laddr, u_int lport, int lookupflags,
+ struct ifnet *ifp, struct mbuf *m)
+{
+
+ KASSERT((lookupflags & ~INPLOOKUP_MASK) == 0,
+ ("%s: invalid lookup flags %d", __func__, lookupflags));
+ KASSERT((lookupflags & (INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB)) != 0,
+ ("%s: LOCKPCB not set", __func__));
+
+ return (in_pcblookup_hash(pcbinfo, faddr, fport, laddr, lport,
+ lookupflags, ifp));
+}
#endif /* INET */
/*
@@ -1588,8 +1679,9 @@ in_pcbinshash(struct inpcb *inp)
struct inpcbport *phd;
u_int32_t hashkey_faddr;
- INP_INFO_WLOCK_ASSERT(pcbinfo);
INP_WLOCK_ASSERT(inp);
+ INP_HASH_WLOCK_ASSERT(pcbinfo);
+
KASSERT((inp->inp_flags & INP_INHASHLIST) == 0,
("in_pcbinshash: INP_INHASHLIST"));
@@ -1639,14 +1731,15 @@ in_pcbinshash(struct inpcb *inp)
* not change after in_pcbinshash() has been called.
*/
void
-in_pcbrehash(struct inpcb *inp)
+in_pcbrehash_mbuf(struct inpcb *inp, struct mbuf *m)
{
struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
struct inpcbhead *head;
u_int32_t hashkey_faddr;
- INP_INFO_WLOCK_ASSERT(pcbinfo);
INP_WLOCK_ASSERT(inp);
+ INP_HASH_WLOCK_ASSERT(pcbinfo);
+
KASSERT(inp->inp_flags & INP_INHASHLIST,
("in_pcbrehash: !INP_INHASHLIST"));
@@ -1664,6 +1757,13 @@ in_pcbrehash(struct inpcb *inp)
LIST_INSERT_HEAD(head, inp, inp_hash);
}
+void
+in_pcbrehash(struct inpcb *inp)
+{
+
+ in_pcbrehash_mbuf(inp, NULL);
+}
+
/*
* Remove PCB from various lists.
*/
@@ -1679,12 +1779,14 @@ in_pcbremlists(struct inpcb *inp)
if (inp->inp_flags & INP_INHASHLIST) {
struct inpcbport *phd = inp->inp_phd;
+ INP_HASH_WLOCK(pcbinfo);
LIST_REMOVE(inp, inp_hash);
LIST_REMOVE(inp, inp_portlist);
if (LIST_FIRST(&phd->phd_pcblist) == NULL) {
LIST_REMOVE(phd, phd_hash);
free(phd, M_PCB);
}
+ INP_HASH_WUNLOCK(pcbinfo);
inp->inp_flags &= ~INP_INHASHLIST;
}
LIST_REMOVE(inp, inp_list);
diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h
index 14d4ea2..809bc05 100644
--- a/sys/netinet/in_pcb.h
+++ b/sys/netinet/in_pcb.h
@@ -268,22 +268,22 @@ struct inpcbport {
* Global data structure for each high-level protocol (UDP, TCP, ...) in both
* IPv4 and IPv6. Holds inpcb lists and information for managing them.
*
- * Each pcbinfo is protected by ipi_lock, covering mutable global fields (such
- * as the global pcb list) and hashed lookup tables. The lock order is:
+ * Each pcbinfo is protected by two locks: ipi_lock and ipi_hash_lock,
+ * the former covering mutable global fields (such as the global pcb list),
+ * and the latter covering the hashed lookup tables. The lock order is:
*
- * ipi_lock (before) inpcb locks
+ * ipi_lock (before) inpcb locks (before) ipi_hash_lock
*
* Locking key:
*
* (c) Constant or nearly constant after initialisation
* (g) Locked by ipi_lock
- * (h) Read using either ipi_lock or inpcb lock; write requires both.
+ * (h) Read using either ipi_hash_lock or inpcb lock; write requires both.
* (x) Synchronisation properties poorly defined
*/
struct inpcbinfo {
/*
- * Global lock protecting global inpcb list, inpcb count, hash tables,
- * etc.
+ * Global lock protecting global inpcb list, inpcb count, etc.
*/
struct rwlock ipi_lock;
@@ -312,17 +312,22 @@ struct inpcbinfo {
struct uma_zone *ipi_zone; /* (c) */
/*
+ * Global lock protecting hash lookup tables.
+ */
+ struct rwlock ipi_hash_lock;
+
+ /*
* Global hash of inpcbs, hashed by local and foreign addresses and
* port numbers.
*/
- struct inpcbhead *ipi_hashbase; /* (g) */
- u_long ipi_hashmask; /* (g) */
+ struct inpcbhead *ipi_hashbase; /* (h) */
+ u_long ipi_hashmask; /* (h) */
/*
* Global hash of inpcbs, hashed by only local port number.
*/
- struct inpcbporthead *ipi_porthashbase; /* (g) */
- u_long ipi_porthashmask; /* (g) */
+ struct inpcbporthead *ipi_porthashbase; /* (h) */
+ u_long ipi_porthashmask; /* (h) */
/*
* Pointer to network stack instance
@@ -406,6 +411,18 @@ void inp_4tuple_get(struct inpcb *inp, uint32_t *laddr, uint16_t *lp,
#define INP_INFO_WLOCK_ASSERT(ipi) rw_assert(&(ipi)->ipi_lock, RA_WLOCKED)
#define INP_INFO_UNLOCK_ASSERT(ipi) rw_assert(&(ipi)->ipi_lock, RA_UNLOCKED)
+#define INP_HASH_LOCK_INIT(ipi, d) \
+ rw_init_flags(&(ipi)->ipi_hash_lock, (d), 0)
+#define INP_HASH_LOCK_DESTROY(ipi) rw_destroy(&(ipi)->ipi_hash_lock)
+#define INP_HASH_RLOCK(ipi) rw_rlock(&(ipi)->ipi_hash_lock)
+#define INP_HASH_WLOCK(ipi) rw_wlock(&(ipi)->ipi_hash_lock)
+#define INP_HASH_RUNLOCK(ipi) rw_runlock(&(ipi)->ipi_hash_lock)
+#define INP_HASH_WUNLOCK(ipi) rw_wunlock(&(ipi)->ipi_hash_lock)
+#define INP_HASH_LOCK_ASSERT(ipi) rw_assert(&(ipi)->ipi_hash_lock, \
+ RA_LOCKED)
+#define INP_HASH_WLOCK_ASSERT(ipi) rw_assert(&(ipi)->ipi_hash_lock, \
+ RA_WLOCKED)
+
#define INP_PCBHASH(faddr, lport, fport, mask) \
(((faddr) ^ ((faddr) >> 16) ^ ntohs((lport) ^ (fport))) & (mask))
#define INP_PCBPORTHASH(lport, mask) \
@@ -466,7 +483,16 @@ void inp_4tuple_get(struct inpcb *inp, uint32_t *laddr, uint16_t *lp,
#define INP_LLE_VALID 0x00000001 /* cached lle is valid */
#define INP_RT_VALID 0x00000002 /* cached rtentry is valid */
-#define INPLOOKUP_WILDCARD 1
+/*
+ * Flags passed to in_pcblookup*() functions.
+ */
+#define INPLOOKUP_WILDCARD 0x00000001 /* Allow wildcard sockets. */
+#define INPLOOKUP_RLOCKPCB 0x00000002 /* Return inpcb read-locked. */
+#define INPLOOKUP_WLOCKPCB 0x00000004 /* Return inpcb write-locked. */
+
+#define INPLOOKUP_MASK (INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB | \
+ INPLOOKUP_WLOCKPCB)
+
#define sotoinpcb(so) ((struct inpcb *)(so)->so_pcb)
#define sotoin6pcb(so) sotoinpcb(so) /* for KAME src sync over BSD*'s */
@@ -515,6 +541,8 @@ int in_pcb_lport(struct inpcb *, struct in_addr *, u_short *,
int in_pcbbind_setup(struct inpcb *, struct sockaddr *, in_addr_t *,
u_short *, struct ucred *);
int in_pcbconnect(struct inpcb *, struct sockaddr *, struct ucred *);
+int in_pcbconnect_mbuf(struct inpcb *, struct sockaddr *, struct ucred *,
+ struct mbuf *);
int in_pcbconnect_setup(struct inpcb *, struct sockaddr *, in_addr_t *,
u_short *, in_addr_t *, u_short *, struct inpcb **,
struct ucred *);
@@ -527,12 +555,16 @@ struct inpcb *
in_pcblookup_local(struct inpcbinfo *,
struct in_addr, u_short, int, struct ucred *);
struct inpcb *
- in_pcblookup_hash(struct inpcbinfo *, struct in_addr, u_int,
+ in_pcblookup(struct inpcbinfo *, struct in_addr, u_int,
struct in_addr, u_int, int, struct ifnet *);
+struct inpcb *
+ in_pcblookup_mbuf(struct inpcbinfo *, struct in_addr, u_int,
+ struct in_addr, u_int, int, struct ifnet *, struct mbuf *);
void in_pcbnotifyall(struct inpcbinfo *pcbinfo, struct in_addr,
int, struct inpcb *(*)(struct inpcb *, int));
void in_pcbref(struct inpcb *);
void in_pcbrehash(struct inpcb *);
+void in_pcbrehash_mbuf(struct inpcb *, struct mbuf *);
int in_pcbrele(struct inpcb *);
int in_pcbrele_rlocked(struct inpcb *);
int in_pcbrele_wlocked(struct inpcb *);
diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c
index de88556..6f5bce7 100644
--- a/sys/netinet/ip_divert.c
+++ b/sys/netinet/ip_divert.c
@@ -530,7 +530,9 @@ div_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
((struct sockaddr_in *)nam)->sin_addr.s_addr = INADDR_ANY;
INP_INFO_WLOCK(&V_divcbinfo);
INP_WLOCK(inp);
+ INP_HASH_WLOCK(&V_divcbinfo);
error = in_pcbbind(inp, nam, td->td_ucred);
+ INP_HASH_WUNLOCK(&V_divcbinfo);
INP_WUNLOCK(inp);
INP_INFO_WUNLOCK(&V_divcbinfo);
return error;
@@ -659,9 +661,9 @@ div_pcblist(SYSCTL_HANDLER_ARGS)
INP_INFO_WLOCK(&V_divcbinfo);
for (i = 0; i < n; i++) {
inp = inp_list[i];
- INP_WLOCK(inp);
- if (!in_pcbrele(inp))
- INP_WUNLOCK(inp);
+ INP_RLOCK(inp);
+ if (!in_pcbrele_rlocked(inp))
+ INP_RUNLOCK(inp);
}
INP_INFO_WUNLOCK(&V_divcbinfo);
diff --git a/sys/netinet/ipfw/ip_dummynet.c b/sys/netinet/ipfw/ip_dummynet.c
index ba6e892..e23ba3a 100644
--- a/sys/netinet/ipfw/ip_dummynet.c
+++ b/sys/netinet/ipfw/ip_dummynet.c
@@ -1045,7 +1045,7 @@ config_red(struct dn_fsk *fs)
fs->w_q = fs->fs.w_q;
fs->max_p = fs->fs.max_p;
- D("called");
+ ND("called");
/* Doing stuff that was in userland */
i = fs->sched->link.bandwidth;
s = (i <= 0) ? 0 :
@@ -1109,7 +1109,7 @@ config_red(struct dn_fsk *fs)
if (dn_cfg.red_max_pkt_size < 1)
dn_cfg.red_max_pkt_size = 1500;
fs->max_pkt_size = dn_cfg.red_max_pkt_size;
- D("exit");
+ ND("exit");
return 0;
}
@@ -2176,7 +2176,7 @@ ip_dn_destroy(int last)
DN_BH_WLOCK();
if (last) {
- printf("%s removing last instance\n", __FUNCTION__);
+ ND("removing last instance\n");
ip_dn_ctl_ptr = NULL;
ip_dn_io_ptr = NULL;
}
@@ -2256,13 +2256,13 @@ unload_dn_sched(struct dn_alg *s)
struct dn_alg *tmp, *r;
int err = EINVAL;
- D("called for %s", s->name);
+ ND("called for %s", s->name);
DN_BH_WLOCK();
SLIST_FOREACH_SAFE(r, &dn_cfg.schedlist, next, tmp) {
if (strcmp(s->name, r->name) != 0)
continue;
- D("ref_count = %d", r->ref_count);
+ ND("ref_count = %d", r->ref_count);
err = (r->ref_count != 0) ? EBUSY : 0;
if (err == 0)
SLIST_REMOVE(&dn_cfg.schedlist, r, dn_alg, next);
diff --git a/sys/netinet/ipfw/ip_fw2.c b/sys/netinet/ipfw/ip_fw2.c
index 9a75cf5..b4d3abb 100644
--- a/sys/netinet/ipfw/ip_fw2.c
+++ b/sys/netinet/ipfw/ip_fw2.c
@@ -657,7 +657,7 @@ check_uidgid(ipfw_insn_u32 *insn, int proto, struct ifnet *oif,
(struct bsd_ucred *)uc, ugid_lookupp, ((struct mbuf *)inp)->m_skb);
#else /* FreeBSD */
struct inpcbinfo *pi;
- int wildcard;
+ int lookupflags;
struct inpcb *pcb;
int match;
@@ -682,30 +682,31 @@ check_uidgid(ipfw_insn_u32 *insn, int proto, struct ifnet *oif,
if (*ugid_lookupp == -1)
return (0);
if (proto == IPPROTO_TCP) {
- wildcard = 0;
+ lookupflags = 0;
pi = &V_tcbinfo;
} else if (proto == IPPROTO_UDP) {
- wildcard = INPLOOKUP_WILDCARD;
+ lookupflags = INPLOOKUP_WILDCARD;
pi = &V_udbinfo;
} else
return 0;
+ lookupflags |= INPLOOKUP_RLOCKPCB;
match = 0;
if (*ugid_lookupp == 0) {
- INP_INFO_RLOCK(pi);
pcb = (oif) ?
- in_pcblookup_hash(pi,
+ in_pcblookup(pi,
dst_ip, htons(dst_port),
src_ip, htons(src_port),
- wildcard, oif) :
- in_pcblookup_hash(pi,
+ lookupflags, oif) :
+ in_pcblookup(pi,
src_ip, htons(src_port),
dst_ip, htons(dst_port),
- wildcard, NULL);
+ lookupflags, NULL);
if (pcb != NULL) {
+ INP_RLOCK_ASSERT(pcb);
*uc = crhold(pcb->inp_cred);
*ugid_lookupp = 1;
+ INP_RUNLOCK(pcb);
}
- INP_INFO_RUNLOCK(pi);
if (*ugid_lookupp == 0) {
/*
* We tried and failed, set the variable to -1
@@ -1827,21 +1828,32 @@ do { \
else
break;
+ /*
+ * XXXRW: so_user_cookie should almost
+ * certainly be inp_user_cookie?
+ */
+
/* For incomming packet, lookup up the
inpcb using the src/dest ip/port tuple */
if (inp == NULL) {
- INP_INFO_RLOCK(pi);
- inp = in_pcblookup_hash(pi,
+ inp = in_pcblookup(pi,
src_ip, htons(src_port),
dst_ip, htons(dst_port),
- 0, NULL);
- INP_INFO_RUNLOCK(pi);
- }
-
- if (inp && inp->inp_socket) {
- tablearg = inp->inp_socket->so_user_cookie;
- if (tablearg)
- match = 1;
+ INPLOOKUP_RLOCKPCB, NULL);
+ if (inp != NULL) {
+ tablearg =
+ inp->inp_socket->so_user_cookie;
+ if (tablearg)
+ match = 1;
+ INP_RUNLOCK(inp);
+ }
+ } else {
+ if (inp->inp_socket) {
+ tablearg =
+ inp->inp_socket->so_user_cookie;
+ if (tablearg)
+ match = 1;
+ }
}
break;
}
@@ -2106,7 +2118,8 @@ do { \
case O_FORWARD_IP:
if (args->eh) /* not valid on layer2 pkts */
break;
- if (!q || dyn_dir == MATCH_FORWARD) {
+ if (q == NULL || q->rule != f ||
+ dyn_dir == MATCH_FORWARD) {
struct sockaddr_in *sa;
sa = &(((ipfw_insn_sa *)cmd)->sa);
if (sa->sin_addr.s_addr == INADDR_ANY) {
@@ -2137,14 +2150,21 @@ do { \
done = 1; /* exit outer loop */
break;
- case O_SETFIB:
+ case O_SETFIB: {
+ uint32_t fib;
+
f->pcnt++; /* update stats */
f->bcnt += pktlen;
f->timestamp = time_uptime;
- M_SETFIB(m, cmd->arg1);
- args->f_id.fib = cmd->arg1;
+ fib = (cmd->arg1 == IP_FW_TABLEARG) ? tablearg:
+ cmd->arg1;
+ if (fib >= rt_numfibs)
+ fib = 0;
+ M_SETFIB(m, fib);
+ args->f_id.fib = fib;
l = 0; /* exit inner loop */
break;
+ }
case O_NAT:
if (!IPFW_NAT_LOADED) {
diff --git a/sys/netinet/ipfw/ip_fw_dynamic.c b/sys/netinet/ipfw/ip_fw_dynamic.c
index 7f0feb4..0bc4cc1 100644
--- a/sys/netinet/ipfw/ip_fw_dynamic.c
+++ b/sys/netinet/ipfw/ip_fw_dynamic.c
@@ -753,11 +753,12 @@ ipfw_install_state(struct ip_fw *rule, ipfw_insn_limit *cmd,
q = lookup_dyn_rule_locked(&args->f_id, NULL, NULL);
if (q != NULL) { /* should never occur */
+ DEB(
if (last_log != time_uptime) {
last_log = time_uptime;
printf("ipfw: %s: entry already present, done\n",
__func__);
- }
+ })
IPFW_DYN_UNLOCK();
return (0);
}
diff --git a/sys/netinet/ipfw/ip_fw_sockopt.c b/sys/netinet/ipfw/ip_fw_sockopt.c
index 0c903ee..f81d57d 100644
--- a/sys/netinet/ipfw/ip_fw_sockopt.c
+++ b/sys/netinet/ipfw/ip_fw_sockopt.c
@@ -606,7 +606,8 @@ check_ipfw_struct(struct ip_fw *rule, int size)
case O_SETFIB:
if (cmdlen != F_INSN_SIZE(ipfw_insn))
goto bad_size;
- if (cmd->arg1 >= rt_numfibs) {
+ if ((cmd->arg1 != IP_FW_TABLEARG) &&
+ (cmd->arg1 >= rt_numfibs)) {
printf("ipfw: invalid fib number %d\n",
cmd->arg1);
return EINVAL;
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
index be099a8..635f08f 100644
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -226,7 +226,7 @@ rip_append(struct inpcb *last, struct ip *ip, struct mbuf *n,
{
int policyfail = 0;
- INP_RLOCK_ASSERT(last);
+ INP_LOCK_ASSERT(last);
#ifdef IPSEC
/* check AH/ESP integrity. */
@@ -834,16 +834,19 @@ rip_detach(struct socket *so)
static void
rip_dodisconnect(struct socket *so, struct inpcb *inp)
{
+ struct inpcbinfo *pcbinfo;
- INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
- INP_WLOCK_ASSERT(inp);
-
+ pcbinfo = inp->inp_pcbinfo;
+ INP_INFO_WLOCK(pcbinfo);
+ INP_WLOCK(inp);
rip_delhash(inp);
inp->inp_faddr.s_addr = INADDR_ANY;
rip_inshash(inp);
SOCK_LOCK(so);
so->so_state &= ~SS_ISCONNECTED;
SOCK_UNLOCK(so);
+ INP_WUNLOCK(inp);
+ INP_INFO_WUNLOCK(pcbinfo);
}
static void
@@ -854,11 +857,7 @@ rip_abort(struct socket *so)
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("rip_abort: inp == NULL"));
- INP_INFO_WLOCK(&V_ripcbinfo);
- INP_WLOCK(inp);
rip_dodisconnect(so, inp);
- INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_ripcbinfo);
}
static void
@@ -869,11 +868,7 @@ rip_close(struct socket *so)
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("rip_close: inp == NULL"));
- INP_INFO_WLOCK(&V_ripcbinfo);
- INP_WLOCK(inp);
rip_dodisconnect(so, inp);
- INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_ripcbinfo);
}
static int
@@ -887,11 +882,7 @@ rip_disconnect(struct socket *so)
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("rip_disconnect: inp == NULL"));
- INP_INFO_WLOCK(&V_ripcbinfo);
- INP_WLOCK(inp);
rip_dodisconnect(so, inp);
- INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_ripcbinfo);
return (0);
}
@@ -1077,9 +1068,9 @@ rip_pcblist(SYSCTL_HANDLER_ARGS)
INP_INFO_WLOCK(&V_ripcbinfo);
for (i = 0; i < n; i++) {
inp = inp_list[i];
- INP_WLOCK(inp);
- if (!in_pcbrele(inp))
- INP_WUNLOCK(inp);
+ INP_RLOCK(inp);
+ if (!in_pcbrele_rlocked(inp))
+ INP_RUNLOCK(inp);
}
INP_INFO_WUNLOCK(&V_ripcbinfo);
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c
index 9734aea..155e55c 100644
--- a/sys/netinet/sctp_indata.c
+++ b/sys/netinet/sctp_indata.c
@@ -247,49 +247,6 @@ sctp_build_ctl_nchunk(struct sctp_inpcb *inp,
}
-char *
-sctp_build_ctl_cchunk(struct sctp_inpcb *inp,
- int *control_len,
- struct sctp_sndrcvinfo *sinfo)
-{
- struct sctp_sndrcvinfo *outinfo;
- struct cmsghdr *cmh;
- char *buf;
- int len;
- int use_extended = 0;
-
- if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT)) {
- /* user does not want the sndrcv ctl */
- return (NULL);
- }
- if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO)) {
- use_extended = 1;
- len = CMSG_LEN(sizeof(struct sctp_extrcvinfo));
- } else {
- len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
- }
- SCTP_MALLOC(buf, char *, len, SCTP_M_CMSG);
- if (buf == NULL) {
- /* No space */
- return (buf);
- }
- /* We need a CMSG header followed by the struct */
- cmh = (struct cmsghdr *)buf;
- outinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmh);
- cmh->cmsg_level = IPPROTO_SCTP;
- if (use_extended) {
- cmh->cmsg_type = SCTP_EXTRCV;
- cmh->cmsg_len = len;
- memcpy(outinfo, sinfo, len);
- } else {
- cmh->cmsg_type = SCTP_SNDRCV;
- cmh->cmsg_len = len;
- *outinfo = *sinfo;
- }
- *control_len = len;
- return (buf);
-}
-
static void
sctp_mark_non_revokable(struct sctp_association *asoc, uint32_t tsn)
{
diff --git a/sys/netinet/sctp_indata.h b/sys/netinet/sctp_indata.h
index 34090df..1dbd364 100644
--- a/sys/netinet/sctp_indata.h
+++ b/sys/netinet/sctp_indata.h
@@ -83,11 +83,6 @@ struct mbuf *
sctp_build_ctl_nchunk(struct sctp_inpcb *inp,
struct sctp_sndrcvinfo *sinfo);
-char *
-sctp_build_ctl_cchunk(struct sctp_inpcb *inp,
- int *control_len,
- struct sctp_sndrcvinfo *sinfo);
-
void sctp_set_rwnd(struct sctp_tcb *, struct sctp_association *);
uint32_t
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index 39df039..8f04bf1 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -6184,71 +6184,6 @@ sctp_soreceive(struct socket *so,
}
-int
-sctp_l_soreceive(struct socket *so,
- struct sockaddr **name,
- struct uio *uio,
- char **controlp,
- int *controllen,
- int *flag)
-{
- int error, fromlen;
- uint8_t sockbuf[256];
- struct sockaddr *from;
- struct sctp_extrcvinfo sinfo;
- int filling_sinfo = 1;
- struct sctp_inpcb *inp;
-
- inp = (struct sctp_inpcb *)so->so_pcb;
- /* pickup the assoc we are reading from */
- if (inp == NULL) {
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
- return (EINVAL);
- }
- if ((sctp_is_feature_off(inp,
- SCTP_PCB_FLAGS_RECVDATAIOEVNT)) ||
- (controlp == NULL)) {
- /* user does not want the sndrcv ctl */
- filling_sinfo = 0;
- }
- if (name) {
- from = (struct sockaddr *)sockbuf;
- fromlen = sizeof(sockbuf);
- from->sa_len = 0;
- } else {
- from = NULL;
- fromlen = 0;
- }
-
- error = sctp_sorecvmsg(so, uio,
- (struct mbuf **)NULL,
- from, fromlen, flag,
- (struct sctp_sndrcvinfo *)&sinfo,
- filling_sinfo);
- if ((controlp) && (filling_sinfo)) {
- /*
- * copy back the sinfo in a CMSG format note that the caller
- * has reponsibility for freeing the memory.
- */
- if (filling_sinfo)
- *controlp = sctp_build_ctl_cchunk(inp,
- controllen,
- (struct sctp_sndrcvinfo *)&sinfo);
- }
- if (name) {
- /* copy back the address info */
- if (from && from->sa_len) {
- *name = sodupsockaddr(from, M_WAIT);
- } else {
- *name = NULL;
- }
- }
- return (error);
-}
-
-
-
-
diff --git a/sys/netinet/sctputil.h b/sys/netinet/sctputil.h
index 69983e0..460adc7 100644
--- a/sys/netinet/sctputil.h
+++ b/sys/netinet/sctputil.h
@@ -328,20 +328,6 @@ sctp_soreceive(struct socket *so, struct sockaddr **psa,
struct mbuf **controlp,
int *flagsp);
-
-/* For those not passing mbufs, this does the
- * translations for you. Caller owns memory
- * of size controllen returned in controlp.
- */
-int
-sctp_l_soreceive(struct socket *so,
- struct sockaddr **name,
- struct uio *uio,
- char **controlp,
- int *controllen,
- int *flag);
-
-
void
sctp_misc_ints(uint8_t from, uint32_t a, uint32_t b, uint32_t c, uint32_t d);
diff --git a/sys/netinet/siftr.c b/sys/netinet/siftr.c
index 9d11262..6145a54 100644
--- a/sys/netinet/siftr.c
+++ b/sys/netinet/siftr.c
@@ -696,17 +696,16 @@ siftr_findinpcb(int ipver, struct ip *ip, struct mbuf *m, uint16_t sport,
/* We need the tcbinfo lock. */
INP_INFO_UNLOCK_ASSERT(&V_tcbinfo);
- INP_INFO_RLOCK(&V_tcbinfo);
if (dir == PFIL_IN)
inp = (ipver == INP_IPV4 ?
- in_pcblookup_hash(&V_tcbinfo, ip->ip_src, sport, ip->ip_dst,
- dport, 0, m->m_pkthdr.rcvif)
+ in_pcblookup(&V_tcbinfo, ip->ip_src, sport, ip->ip_dst,
+ dport, INPLOOKUP_RLOCKPCB, m->m_pkthdr.rcvif)
:
#ifdef SIFTR_IPV6
- in6_pcblookup_hash(&V_tcbinfo,
+ in6_pcblookup(&V_tcbinfo,
&((struct ip6_hdr *)ip)->ip6_src, sport,
- &((struct ip6_hdr *)ip)->ip6_dst, dport, 0,
+ &((struct ip6_hdr *)ip)->ip6_dst, dport, INPLOOKUP_RLOCKPCB,
m->m_pkthdr.rcvif)
#else
NULL
@@ -715,13 +714,13 @@ siftr_findinpcb(int ipver, struct ip *ip, struct mbuf *m, uint16_t sport,
else
inp = (ipver == INP_IPV4 ?
- in_pcblookup_hash(&V_tcbinfo, ip->ip_dst, dport, ip->ip_src,
- sport, 0, m->m_pkthdr.rcvif)
+ in_pcblookup(&V_tcbinfo, ip->ip_dst, dport, ip->ip_src,
+ sport, INPLOOKUP_RLOCKPCB, m->m_pkthdr.rcvif)
:
#ifdef SIFTR_IPV6
- in6_pcblookup_hash(&V_tcbinfo,
+ in6_pcblookup(&V_tcbinfo,
&((struct ip6_hdr *)ip)->ip6_dst, dport,
- &((struct ip6_hdr *)ip)->ip6_src, sport, 0,
+ &((struct ip6_hdr *)ip)->ip6_src, sport, INPLOOKUP_RLOCKPCB,
m->m_pkthdr.rcvif)
#else
NULL
@@ -734,12 +733,7 @@ siftr_findinpcb(int ipver, struct ip *ip, struct mbuf *m, uint16_t sport,
ss->nskip_in_inpcb++;
else
ss->nskip_out_inpcb++;
- } else {
- /* Acquire the inpcb lock. */
- INP_UNLOCK_ASSERT(inp);
- INP_RLOCK(inp);
}
- INP_INFO_RUNLOCK(&V_tcbinfo);
return (inp);
}
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 1a94d0a..e3e9aa6 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -5,6 +5,7 @@
* Swinburne University of Technology, Melbourne, Australia.
* Copyright (c) 2009-2010 Lawrence Stewart <lstewart@freebsd.org>
* Copyright (c) 2010 The FreeBSD Foundation
+ * Copyright (c) 2010-2011 Juniper Networks, Inc.
* All rights reserved.
*
* Portions of this software were developed at the Centre for Advanced Internet
@@ -16,6 +17,9 @@
* Internet Architectures, Swinburne University of Technology, Melbourne,
* Australia by David Hayes under sponsorship from the FreeBSD Foundation.
*
+ * Portions of this software were developed by Robert N. M. Watson under
+ * contract to Juniper Networks, Inc.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -197,10 +201,6 @@ SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, recvbuf_max, CTLFLAG_RW,
&VNET_NAME(tcp_autorcvbuf_max), 0,
"Max size of automatic receive buffer");
-int tcp_read_locking = 1;
-SYSCTL_INT(_net_inet_tcp, OID_AUTO, read_locking, CTLFLAG_RW,
- &tcp_read_locking, 0, "Enable read locking strategy");
-
VNET_DEFINE(struct inpcbhead, tcb);
#define tcb6 tcb /* for KAME src sync over BSD*'s */
VNET_DEFINE(struct inpcbinfo, tcbinfo);
@@ -591,8 +591,7 @@ tcp_input(struct mbuf *m, int off0)
char *s = NULL; /* address and port logging */
int ti_locked;
#define TI_UNLOCKED 1
-#define TI_RLOCKED 2
-#define TI_WLOCKED 3
+#define TI_WLOCKED 2
#ifdef TCPDEBUG
/*
@@ -756,30 +755,25 @@ tcp_input(struct mbuf *m, int off0)
drop_hdrlen = off0 + off;
/*
- * Locate pcb for segment, which requires a lock on tcbinfo.
- * Optimisticaly acquire a global read lock rather than a write lock
- * unless header flags necessarily imply a state change. There are
- * two cases where we might discover later we need a write lock
- * despite the flags: ACKs moving a connection out of the syncache,
- * and ACKs for a connection in TIMEWAIT.
+ * Locate pcb for segment; if we're likely to add or remove a
+ * connection then first acquire pcbinfo lock. There are two cases
+ * where we might discover later we need a write lock despite the
+ * flags: ACKs moving a connection out of the syncache, and ACKs for
+ * a connection in TIMEWAIT.
*/
- if ((thflags & (TH_SYN | TH_FIN | TH_RST)) != 0 ||
- tcp_read_locking == 0) {
+ if ((thflags & (TH_SYN | TH_FIN | TH_RST)) != 0) {
INP_INFO_WLOCK(&V_tcbinfo);
ti_locked = TI_WLOCKED;
- } else {
- INP_INFO_RLOCK(&V_tcbinfo);
- ti_locked = TI_RLOCKED;
- }
+ } else
+ ti_locked = TI_UNLOCKED;
findpcb:
#ifdef INVARIANTS
- if (ti_locked == TI_RLOCKED)
- INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
- else if (ti_locked == TI_WLOCKED)
+ if (ti_locked == TI_WLOCKED) {
INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
- else
- panic("%s: findpcb ti_locked %d\n", __func__, ti_locked);
+ } else {
+ INP_INFO_UNLOCK_ASSERT(&V_tcbinfo);
+ }
#endif
#ifdef INET
@@ -797,20 +791,20 @@ findpcb:
* Transparently forwarded. Pretend to be the destination.
* already got one like this?
*/
- inp = in_pcblookup_hash(&V_tcbinfo,
- ip->ip_src, th->th_sport,
- ip->ip_dst, th->th_dport,
- 0, m->m_pkthdr.rcvif);
+ inp = in_pcblookup_mbuf(&V_tcbinfo, ip->ip_src, th->th_sport,
+ ip->ip_dst, th->th_dport, INPLOOKUP_WLOCKPCB,
+ m->m_pkthdr.rcvif, m);
if (!inp) {
- /* It's new. Try to find the ambushing socket. */
- inp = in_pcblookup_hash(&V_tcbinfo,
- ip->ip_src, th->th_sport,
- next_hop->sin_addr,
- next_hop->sin_port ?
- ntohs(next_hop->sin_port) :
- th->th_dport,
- INPLOOKUP_WILDCARD,
- m->m_pkthdr.rcvif);
+ /*
+ * It's new. Try to find the ambushing socket.
+ * Because we've rewritten the destination address,
+ * any hardware-generated hash is ignored.
+ */
+ inp = in_pcblookup(&V_tcbinfo, ip->ip_src,
+ th->th_sport, next_hop->sin_addr,
+ next_hop->sin_port ? ntohs(next_hop->sin_port) :
+ th->th_dport, INPLOOKUP_WILDCARD |
+ INPLOOKUP_WLOCKPCB, m->m_pkthdr.rcvif);
}
/* Remove the tag from the packet. We don't need it anymore. */
m_tag_delete(m, fwd_tag);
@@ -820,21 +814,19 @@ findpcb:
{
#ifdef INET6
if (isipv6)
- inp = in6_pcblookup_hash(&V_tcbinfo,
- &ip6->ip6_src, th->th_sport,
- &ip6->ip6_dst, th->th_dport,
- INPLOOKUP_WILDCARD,
- m->m_pkthdr.rcvif);
+ inp = in6_pcblookup_mbuf(&V_tcbinfo, &ip6->ip6_src,
+ th->th_sport, &ip6->ip6_dst, th->th_dport,
+ INPLOOKUP_WILDCARD | INPLOOKUP_WLOCKPCB,
+ m->m_pkthdr.rcvif, m);
#endif
#if defined(INET) && defined(INET6)
else
#endif
#ifdef INET
- inp = in_pcblookup_hash(&V_tcbinfo,
- ip->ip_src, th->th_sport,
- ip->ip_dst, th->th_dport,
- INPLOOKUP_WILDCARD,
- m->m_pkthdr.rcvif);
+ inp = in_pcblookup_mbuf(&V_tcbinfo, ip->ip_src,
+ th->th_sport, ip->ip_dst, th->th_dport,
+ INPLOOKUP_WILDCARD | INPLOOKUP_WLOCKPCB,
+ m->m_pkthdr.rcvif, m);
#endif
}
@@ -865,7 +857,7 @@ findpcb:
rstreason = BANDLIM_RST_CLOSEDPORT;
goto dropwithreset;
}
- INP_WLOCK(inp);
+ INP_WLOCK_ASSERT(inp);
if (!(inp->inp_flags & INP_HW_FLOWID)
&& (m->m_flags & M_FLOWID)
&& ((inp->inp_socket == NULL)
@@ -906,28 +898,26 @@ findpcb:
* legitimate new connection attempt the old INPCB gets removed and
* we can try again to find a listening socket.
*
- * At this point, due to earlier optimism, we may hold a read lock on
- * the inpcbinfo, rather than a write lock. If so, we need to
- * upgrade, or if that fails, acquire a reference on the inpcb, drop
- * all locks, acquire a global write lock, and then re-acquire the
- * inpcb lock. We may at that point discover that another thread has
- * tried to free the inpcb, in which case we need to loop back and
- * try to find a new inpcb to deliver to.
+ * At this point, due to earlier optimism, we may hold only an inpcb
+ * lock, and not the inpcbinfo write lock. If so, we need to try to
+ * acquire it, or if that fails, acquire a reference on the inpcb,
+ * drop all locks, acquire a global write lock, and then re-acquire
+ * the inpcb lock. We may at that point discover that another thread
+ * has tried to free the inpcb, in which case we need to loop back
+ * and try to find a new inpcb to deliver to.
+ *
+ * XXXRW: It may be time to rethink timewait locking.
*/
relocked:
if (inp->inp_flags & INP_TIMEWAIT) {
- KASSERT(ti_locked == TI_RLOCKED || ti_locked == TI_WLOCKED,
- ("%s: INP_TIMEWAIT ti_locked %d", __func__, ti_locked));
-
- if (ti_locked == TI_RLOCKED) {
- if (INP_INFO_TRY_UPGRADE(&V_tcbinfo) == 0) {
+ if (ti_locked == TI_UNLOCKED) {
+ if (INP_INFO_TRY_WLOCK(&V_tcbinfo) == 0) {
in_pcbref(inp);
INP_WUNLOCK(inp);
- INP_INFO_RUNLOCK(&V_tcbinfo);
INP_INFO_WLOCK(&V_tcbinfo);
ti_locked = TI_WLOCKED;
INP_WLOCK(inp);
- if (in_pcbrele(inp)) {
+ if (in_pcbrele_wlocked(inp)) {
inp = NULL;
goto findpcb;
}
@@ -975,26 +965,24 @@ relocked:
/*
* We've identified a valid inpcb, but it could be that we need an
- * inpcbinfo write lock and have only a read lock. In this case,
- * attempt to upgrade/relock using the same strategy as the TIMEWAIT
- * case above. If we relock, we have to jump back to 'relocked' as
- * the connection might now be in TIMEWAIT.
+ * inpcbinfo write lock but don't hold it. In this case, attempt to
+ * acquire using the same strategy as the TIMEWAIT case above. If we
+ * relock, we have to jump back to 'relocked' as the connection might
+ * now be in TIMEWAIT.
*/
- if (tp->t_state != TCPS_ESTABLISHED ||
- (thflags & (TH_SYN | TH_FIN | TH_RST)) != 0 ||
- tcp_read_locking == 0) {
- KASSERT(ti_locked == TI_RLOCKED || ti_locked == TI_WLOCKED,
- ("%s: upgrade check ti_locked %d", __func__, ti_locked));
-
- if (ti_locked == TI_RLOCKED) {
- if (INP_INFO_TRY_UPGRADE(&V_tcbinfo) == 0) {
+#ifdef INVARIANTS
+ if ((thflags & (TH_SYN | TH_FIN | TH_RST)) != 0)
+ INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
+#endif
+ if (tp->t_state != TCPS_ESTABLISHED) {
+ if (ti_locked == TI_UNLOCKED) {
+ if (INP_INFO_TRY_WLOCK(&V_tcbinfo) == 0) {
in_pcbref(inp);
INP_WUNLOCK(inp);
- INP_INFO_RUNLOCK(&V_tcbinfo);
INP_INFO_WLOCK(&V_tcbinfo);
ti_locked = TI_WLOCKED;
INP_WLOCK(inp);
- if (in_pcbrele(inp)) {
+ if (in_pcbrele_wlocked(inp)) {
inp = NULL;
goto findpcb;
}
@@ -1027,13 +1015,16 @@ relocked:
/*
* When the socket is accepting connections (the INPCB is in LISTEN
* state) we look into the SYN cache if this is a new connection
- * attempt or the completion of a previous one.
+ * attempt or the completion of a previous one. Because listen
+ * sockets are never in TCPS_ESTABLISHED, the V_tcbinfo lock will be
+ * held in this case.
*/
if (so->so_options & SO_ACCEPTCONN) {
struct in_conninfo inc;
KASSERT(tp->t_state == TCPS_LISTEN, ("%s: so accepting but "
"tp not listening", __func__));
+ INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
bzero(&inc, sizeof(inc));
#ifdef INET6
@@ -1371,13 +1362,17 @@ relocked:
return;
dropwithreset:
- if (ti_locked == TI_RLOCKED)
- INP_INFO_RUNLOCK(&V_tcbinfo);
- else if (ti_locked == TI_WLOCKED)
+ if (ti_locked == TI_WLOCKED) {
INP_INFO_WUNLOCK(&V_tcbinfo);
- else
- panic("%s: dropwithreset ti_locked %d", __func__, ti_locked);
- ti_locked = TI_UNLOCKED;
+ ti_locked = TI_UNLOCKED;
+ }
+#ifdef INVARIANTS
+ else {
+ KASSERT(ti_locked == TI_UNLOCKED, ("%s: dropwithreset "
+ "ti_locked: %d", __func__, ti_locked));
+ INP_INFO_UNLOCK_ASSERT(&V_tcbinfo);
+ }
+#endif
if (inp != NULL) {
tcp_dropwithreset(m, th, tp, tlen, rstreason);
@@ -1388,13 +1383,17 @@ dropwithreset:
goto drop;
dropunlock:
- if (ti_locked == TI_RLOCKED)
- INP_INFO_RUNLOCK(&V_tcbinfo);
- else if (ti_locked == TI_WLOCKED)
+ if (ti_locked == TI_WLOCKED) {
INP_INFO_WUNLOCK(&V_tcbinfo);
- else
- panic("%s: dropunlock ti_locked %d", __func__, ti_locked);
- ti_locked = TI_UNLOCKED;
+ ti_locked = TI_UNLOCKED;
+ }
+#ifdef INVARIANTS
+ else {
+ KASSERT(ti_locked == TI_UNLOCKED, ("%s: dropunlock "
+ "ti_locked: %d", __func__, ti_locked));
+ INP_INFO_UNLOCK_ASSERT(&V_tcbinfo);
+ }
+#endif
if (inp != NULL)
INP_WUNLOCK(inp);
@@ -1449,13 +1448,13 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
} else {
#ifdef INVARIANTS
- if (ti_locked == TI_RLOCKED)
- INP_INFO_RLOCK_ASSERT(&V_tcbinfo);
- else if (ti_locked == TI_WLOCKED)
+ if (ti_locked == TI_WLOCKED)
INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
- else
- panic("%s: ti_locked %d for EST", __func__,
- ti_locked);
+ else {
+ KASSERT(ti_locked == TI_UNLOCKED, ("%s: EST "
+ "ti_locked: %d", __func__, ti_locked));
+ INP_INFO_UNLOCK_ASSERT(&V_tcbinfo);
+ }
#endif
}
INP_WLOCK_ASSERT(tp->t_inpcb);
@@ -1601,13 +1600,8 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
/*
* This is a pure ack for outstanding data.
*/
- if (ti_locked == TI_RLOCKED)
- INP_INFO_RUNLOCK(&V_tcbinfo);
- else if (ti_locked == TI_WLOCKED)
+ if (ti_locked == TI_WLOCKED)
INP_INFO_WUNLOCK(&V_tcbinfo);
- else
- panic("%s: ti_locked %d on pure ACK",
- __func__, ti_locked);
ti_locked = TI_UNLOCKED;
TCPSTAT_INC(tcps_predack);
@@ -1708,13 +1702,8 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
* nothing on the reassembly queue and we have enough
* buffer space to take it.
*/
- if (ti_locked == TI_RLOCKED)
- INP_INFO_RUNLOCK(&V_tcbinfo);
- else if (ti_locked == TI_WLOCKED)
+ if (ti_locked == TI_WLOCKED)
INP_INFO_WUNLOCK(&V_tcbinfo);
- else
- panic("%s: ti_locked %d on pure data "
- "segment", __func__, ti_locked);
ti_locked = TI_UNLOCKED;
/* Clean receiver SACK report if present */
@@ -2550,9 +2539,6 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
}
process_ACK:
- INP_INFO_LOCK_ASSERT(&V_tcbinfo);
- KASSERT(ti_locked == TI_RLOCKED || ti_locked == TI_WLOCKED,
- ("tcp_input: process_ACK ti_locked %d", ti_locked));
INP_WLOCK_ASSERT(tp->t_inpcb);
acked = BYTES_THIS_ACK(tp, th);
@@ -2716,9 +2702,6 @@ process_ACK:
}
step6:
- INP_INFO_LOCK_ASSERT(&V_tcbinfo);
- KASSERT(ti_locked == TI_RLOCKED || ti_locked == TI_WLOCKED,
- ("tcp_do_segment: step6 ti_locked %d", ti_locked));
INP_WLOCK_ASSERT(tp->t_inpcb);
/*
@@ -2804,9 +2787,6 @@ step6:
tp->rcv_up = tp->rcv_nxt;
}
dodata: /* XXX */
- INP_INFO_LOCK_ASSERT(&V_tcbinfo);
- KASSERT(ti_locked == TI_RLOCKED || ti_locked == TI_WLOCKED,
- ("tcp_do_segment: dodata ti_locked %d", ti_locked));
INP_WLOCK_ASSERT(tp->t_inpcb);
/*
@@ -2938,13 +2918,8 @@ dodata: /* XXX */
return;
}
}
- if (ti_locked == TI_RLOCKED)
- INP_INFO_RUNLOCK(&V_tcbinfo);
- else if (ti_locked == TI_WLOCKED)
+ if (ti_locked == TI_WLOCKED)
INP_INFO_WUNLOCK(&V_tcbinfo);
- else
- panic("%s: dodata epilogue ti_locked %d", __func__,
- ti_locked);
ti_locked = TI_UNLOCKED;
#ifdef TCPDEBUG
@@ -2973,9 +2948,6 @@ check_delack:
return;
dropafterack:
- KASSERT(ti_locked == TI_RLOCKED || ti_locked == TI_WLOCKED,
- ("tcp_do_segment: dropafterack ti_locked %d", ti_locked));
-
/*
* Generate an ACK dropping incoming segment if it occupies
* sequence space, where the ACK reflects our state.
@@ -3002,13 +2974,8 @@ dropafterack:
tcp_trace(TA_DROP, ostate, tp, (void *)tcp_saveipgen,
&tcp_savetcp, 0);
#endif
- if (ti_locked == TI_RLOCKED)
- INP_INFO_RUNLOCK(&V_tcbinfo);
- else if (ti_locked == TI_WLOCKED)
+ if (ti_locked == TI_WLOCKED)
INP_INFO_WUNLOCK(&V_tcbinfo);
- else
- panic("%s: dropafterack epilogue ti_locked %d", __func__,
- ti_locked);
ti_locked = TI_UNLOCKED;
tp->t_flags |= TF_ACKNOW;
@@ -3018,12 +2985,8 @@ dropafterack:
return;
dropwithreset:
- if (ti_locked == TI_RLOCKED)
- INP_INFO_RUNLOCK(&V_tcbinfo);
- else if (ti_locked == TI_WLOCKED)
+ if (ti_locked == TI_WLOCKED)
INP_INFO_WUNLOCK(&V_tcbinfo);
- else
- panic("%s: dropwithreset ti_locked %d", __func__, ti_locked);
ti_locked = TI_UNLOCKED;
if (tp != NULL) {
@@ -3034,15 +2997,14 @@ dropwithreset:
return;
drop:
- if (ti_locked == TI_RLOCKED)
- INP_INFO_RUNLOCK(&V_tcbinfo);
- else if (ti_locked == TI_WLOCKED)
+ if (ti_locked == TI_WLOCKED) {
INP_INFO_WUNLOCK(&V_tcbinfo);
+ ti_locked = TI_UNLOCKED;
+ }
#ifdef INVARIANTS
else
INP_INFO_UNLOCK_ASSERT(&V_tcbinfo);
#endif
- ti_locked = TI_UNLOCKED;
/*
* Drop space held by incoming segment and return.
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 2c013be..06854ec 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -1184,9 +1184,9 @@ tcp_pcblist(SYSCTL_HANDLER_ARGS)
INP_INFO_WLOCK(&V_tcbinfo);
for (i = 0; i < n; i++) {
inp = inp_list[i];
- INP_WLOCK(inp);
- if (!in_pcbrele(inp))
- INP_WUNLOCK(inp);
+ INP_RLOCK(inp);
+ if (!in_pcbrele_rlocked(inp))
+ INP_RUNLOCK(inp);
}
INP_INFO_WUNLOCK(&V_tcbinfo);
@@ -1228,12 +1228,9 @@ tcp_getcred(SYSCTL_HANDLER_ARGS)
error = SYSCTL_IN(req, addrs, sizeof(addrs));
if (error)
return (error);
- INP_INFO_RLOCK(&V_tcbinfo);
- inp = in_pcblookup_hash(&V_tcbinfo, addrs[1].sin_addr,
- addrs[1].sin_port, addrs[0].sin_addr, addrs[0].sin_port, 0, NULL);
+ inp = in_pcblookup(&V_tcbinfo, addrs[1].sin_addr, addrs[1].sin_port,
+ addrs[0].sin_addr, addrs[0].sin_port, INPLOOKUP_RLOCKPCB, NULL);
if (inp != NULL) {
- INP_RLOCK(inp);
- INP_INFO_RUNLOCK(&V_tcbinfo);
if (inp->inp_socket == NULL)
error = ENOENT;
if (error == 0)
@@ -1241,10 +1238,8 @@ tcp_getcred(SYSCTL_HANDLER_ARGS)
if (error == 0)
cru2x(inp->inp_cred, &xuc);
INP_RUNLOCK(inp);
- } else {
- INP_INFO_RUNLOCK(&V_tcbinfo);
+ } else
error = ENOENT;
- }
if (error == 0)
error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
return (error);
@@ -1286,23 +1281,20 @@ tcp6_getcred(SYSCTL_HANDLER_ARGS)
return (EINVAL);
}
- INP_INFO_RLOCK(&V_tcbinfo);
#ifdef INET
if (mapped == 1)
- inp = in_pcblookup_hash(&V_tcbinfo,
+ inp = in_pcblookup(&V_tcbinfo,
*(struct in_addr *)&addrs[1].sin6_addr.s6_addr[12],
addrs[1].sin6_port,
*(struct in_addr *)&addrs[0].sin6_addr.s6_addr[12],
- addrs[0].sin6_port,
- 0, NULL);
+ addrs[0].sin6_port, INPLOOKUP_RLOCKPCB, NULL);
else
#endif
- inp = in6_pcblookup_hash(&V_tcbinfo,
+ inp = in6_pcblookup(&V_tcbinfo,
&addrs[1].sin6_addr, addrs[1].sin6_port,
- &addrs[0].sin6_addr, addrs[0].sin6_port, 0, NULL);
+ &addrs[0].sin6_addr, addrs[0].sin6_port,
+ INPLOOKUP_RLOCKPCB, NULL);
if (inp != NULL) {
- INP_RLOCK(inp);
- INP_INFO_RUNLOCK(&V_tcbinfo);
if (inp->inp_socket == NULL)
error = ENOENT;
if (error == 0)
@@ -1310,10 +1302,8 @@ tcp6_getcred(SYSCTL_HANDLER_ARGS)
if (error == 0)
cru2x(inp->inp_cred, &xuc);
INP_RUNLOCK(inp);
- } else {
- INP_INFO_RUNLOCK(&V_tcbinfo);
+ } else
error = ENOENT;
- }
if (error == 0)
error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
return (error);
@@ -1374,10 +1364,9 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
th = (struct tcphdr *)((caddr_t)ip
+ (ip->ip_hl << 2));
INP_INFO_WLOCK(&V_tcbinfo);
- inp = in_pcblookup_hash(&V_tcbinfo, faddr, th->th_dport,
- ip->ip_src, th->th_sport, 0, NULL);
+ inp = in_pcblookup(&V_tcbinfo, faddr, th->th_dport,
+ ip->ip_src, th->th_sport, INPLOOKUP_WLOCKPCB, NULL);
if (inp != NULL) {
- INP_WLOCK(inp);
if (!(inp->inp_flags & INP_TIMEWAIT) &&
!(inp->inp_flags & INP_DROPPED) &&
!(inp->inp_socket == NULL)) {
@@ -2154,20 +2143,19 @@ sysctl_drop(SYSCTL_HANDLER_ARGS)
switch (addrs[0].ss_family) {
#ifdef INET6
case AF_INET6:
- inp = in6_pcblookup_hash(&V_tcbinfo, &fin6->sin6_addr,
- fin6->sin6_port, &lin6->sin6_addr, lin6->sin6_port, 0,
- NULL);
+ inp = in6_pcblookup(&V_tcbinfo, &fin6->sin6_addr,
+ fin6->sin6_port, &lin6->sin6_addr, lin6->sin6_port,
+ INPLOOKUP_WLOCKPCB, NULL);
break;
#endif
#ifdef INET
case AF_INET:
- inp = in_pcblookup_hash(&V_tcbinfo, fin->sin_addr,
- fin->sin_port, lin->sin_addr, lin->sin_port, 0, NULL);
+ inp = in_pcblookup(&V_tcbinfo, fin->sin_addr, fin->sin_port,
+ lin->sin_addr, lin->sin_port, INPLOOKUP_WLOCKPCB, NULL);
break;
#endif
}
if (inp != NULL) {
- INP_WLOCK(inp);
if (inp->inp_flags & INP_TIMEWAIT) {
/*
* XXXRW: There currently exists a state where an
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index 8262f43..5125134 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -661,6 +661,7 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
inp = sotoinpcb(so);
inp->inp_inc.inc_fibnum = so->so_fibnum;
INP_WLOCK(inp);
+ INP_HASH_WLOCK(&V_tcbinfo);
/* Insert new socket into PCB hash list. */
inp->inp_inc.inc_flags = sc->sc_inc.inc_flags;
@@ -694,6 +695,7 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
s, __func__, error);
free(s, M_TCPLOG);
}
+ INP_HASH_WUNLOCK(&V_tcbinfo);
goto abort;
}
#ifdef IPSEC
@@ -728,8 +730,8 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
laddr6 = inp->in6p_laddr;
if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
inp->in6p_laddr = sc->sc_inc.inc6_laddr;
- if ((error = in6_pcbconnect(inp, (struct sockaddr *)&sin6,
- thread0.td_ucred)) != 0) {
+ if ((error = in6_pcbconnect_mbuf(inp, (struct sockaddr *)&sin6,
+ thread0.td_ucred, m)) != 0) {
inp->in6p_laddr = laddr6;
if ((s = tcp_log_addrs(&sc->sc_inc, NULL, NULL, NULL))) {
log(LOG_DEBUG, "%s; %s: in6_pcbconnect failed "
@@ -737,6 +739,7 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
s, __func__, error);
free(s, M_TCPLOG);
}
+ INP_HASH_WUNLOCK(&V_tcbinfo);
goto abort;
}
/* Override flowlabel from in6_pcbconnect. */
@@ -767,8 +770,8 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
laddr = inp->inp_laddr;
if (inp->inp_laddr.s_addr == INADDR_ANY)
inp->inp_laddr = sc->sc_inc.inc_laddr;
- if ((error = in_pcbconnect(inp, (struct sockaddr *)&sin,
- thread0.td_ucred)) != 0) {
+ if ((error = in_pcbconnect_mbuf(inp, (struct sockaddr *)&sin,
+ thread0.td_ucred, m)) != 0) {
inp->inp_laddr = laddr;
if ((s = tcp_log_addrs(&sc->sc_inc, NULL, NULL, NULL))) {
log(LOG_DEBUG, "%s; %s: in_pcbconnect failed "
@@ -776,10 +779,12 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
s, __func__, error);
free(s, M_TCPLOG);
}
+ INP_HASH_WUNLOCK(&V_tcbinfo);
goto abort;
}
}
#endif /* INET */
+ INP_HASH_WUNLOCK(&V_tcbinfo);
tp = intotcpcb(inp);
tp->t_state = TCPS_SYN_RECEIVED;
tp->iss = sc->sc_iss;
diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c
index 5c2c5c2..73984c7 100644
--- a/sys/netinet/tcp_timer.c
+++ b/sys/netinet/tcp_timer.c
@@ -490,7 +490,7 @@ tcp_timer_rexmt(void * xtp)
INP_WUNLOCK(inp);
INP_INFO_WLOCK(&V_tcbinfo);
INP_WLOCK(inp);
- if (in_pcbrele(inp)) {
+ if (in_pcbrele_wlocked(inp)) {
INP_INFO_WUNLOCK(&V_tcbinfo);
CURVNET_RESTORE();
return;
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index 318fe27..96cb1e4 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -2,8 +2,12 @@
* Copyright (c) 1982, 1986, 1988, 1993
* The Regents of the University of California.
* Copyright (c) 2006-2007 Robert N. M. Watson
+ * Copyright (c) 2010-2011 Juniper Networks, Inc.
* All rights reserved.
*
+ * Portions of this software were developed by Robert N. M. Watson under
+ * contract to Juniper Networks, Inc.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -251,7 +255,6 @@ tcp_usr_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
return (EAFNOSUPPORT);
TCPDEBUG0;
- INP_INFO_WLOCK(&V_tcbinfo);
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp_usr_bind: inp == NULL"));
INP_WLOCK(inp);
@@ -261,11 +264,12 @@ tcp_usr_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
}
tp = intotcpcb(inp);
TCPDEBUG1();
+ INP_HASH_WLOCK(&V_tcbinfo);
error = in_pcbbind(inp, nam, td->td_ucred);
+ INP_HASH_WUNLOCK(&V_tcbinfo);
out:
TCPDEBUG2(PRU_BIND);
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
return (error);
}
@@ -292,7 +296,6 @@ tcp6_usr_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
return (EAFNOSUPPORT);
TCPDEBUG0;
- INP_INFO_WLOCK(&V_tcbinfo);
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp6_usr_bind: inp == NULL"));
INP_WLOCK(inp);
@@ -302,6 +305,7 @@ tcp6_usr_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
}
tp = intotcpcb(inp);
TCPDEBUG1();
+ INP_HASH_WLOCK(&V_tcbinfo);
inp->inp_vflag &= ~INP_IPV4;
inp->inp_vflag |= INP_IPV6;
#ifdef INET
@@ -316,15 +320,16 @@ tcp6_usr_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
inp->inp_vflag &= ~INP_IPV6;
error = in_pcbbind(inp, (struct sockaddr *)&sin,
td->td_ucred);
+ INP_HASH_WUNLOCK(&V_tcbinfo);
goto out;
}
}
#endif
error = in6_pcbbind(inp, nam, td->td_ucred);
+ INP_HASH_WUNLOCK(&V_tcbinfo);
out:
TCPDEBUG2(PRU_BIND);
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
return (error);
}
#endif /* INET6 */
@@ -341,7 +346,6 @@ tcp_usr_listen(struct socket *so, int backlog, struct thread *td)
struct tcpcb *tp = NULL;
TCPDEBUG0;
- INP_INFO_WLOCK(&V_tcbinfo);
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp_usr_listen: inp == NULL"));
INP_WLOCK(inp);
@@ -353,8 +357,10 @@ tcp_usr_listen(struct socket *so, int backlog, struct thread *td)
TCPDEBUG1();
SOCK_LOCK(so);
error = solisten_proto_check(so);
+ INP_HASH_WLOCK(&V_tcbinfo);
if (error == 0 && inp->inp_lport == 0)
error = in_pcbbind(inp, (struct sockaddr *)0, td->td_ucred);
+ INP_HASH_WUNLOCK(&V_tcbinfo);
if (error == 0) {
tp->t_state = TCPS_LISTEN;
solisten_proto(so, backlog);
@@ -365,7 +371,6 @@ tcp_usr_listen(struct socket *so, int backlog, struct thread *td)
out:
TCPDEBUG2(PRU_LISTEN);
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
return (error);
}
#endif /* INET */
@@ -379,7 +384,6 @@ tcp6_usr_listen(struct socket *so, int backlog, struct thread *td)
struct tcpcb *tp = NULL;
TCPDEBUG0;
- INP_INFO_WLOCK(&V_tcbinfo);
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp6_usr_listen: inp == NULL"));
INP_WLOCK(inp);
@@ -391,12 +395,14 @@ tcp6_usr_listen(struct socket *so, int backlog, struct thread *td)
TCPDEBUG1();
SOCK_LOCK(so);
error = solisten_proto_check(so);
+ INP_HASH_WLOCK(&V_tcbinfo);
if (error == 0 && inp->inp_lport == 0) {
inp->inp_vflag &= ~INP_IPV4;
if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0)
inp->inp_vflag |= INP_IPV4;
error = in6_pcbbind(inp, (struct sockaddr *)0, td->td_ucred);
}
+ INP_HASH_WUNLOCK(&V_tcbinfo);
if (error == 0) {
tp->t_state = TCPS_LISTEN;
solisten_proto(so, backlog);
@@ -406,7 +412,6 @@ tcp6_usr_listen(struct socket *so, int backlog, struct thread *td)
out:
TCPDEBUG2(PRU_LISTEN);
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
return (error);
}
#endif /* INET6 */
@@ -440,7 +445,6 @@ tcp_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
return (error);
TCPDEBUG0;
- INP_INFO_WLOCK(&V_tcbinfo);
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp_usr_connect: inp == NULL"));
INP_WLOCK(inp);
@@ -456,7 +460,6 @@ tcp_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
out:
TCPDEBUG2(PRU_CONNECT);
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
return (error);
}
#endif /* INET */
@@ -482,7 +485,6 @@ tcp6_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
&& IN6_IS_ADDR_MULTICAST(&sin6p->sin6_addr))
return (EAFNOSUPPORT);
- INP_INFO_WLOCK(&V_tcbinfo);
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp6_usr_connect: inp == NULL"));
INP_WLOCK(inp);
@@ -493,6 +495,11 @@ tcp6_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
tp = intotcpcb(inp);
TCPDEBUG1();
#ifdef INET
+ /*
+ * XXXRW: Some confusion: V4/V6 flags relate to binding, and
+ * therefore probably require the hash lock, which isn't held here.
+ * Is this a significant problem?
+ */
if (IN6_IS_ADDR_V4MAPPED(&sin6p->sin6_addr)) {
struct sockaddr_in sin;
@@ -525,7 +532,6 @@ tcp6_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
out:
TCPDEBUG2(PRU_CONNECT);
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_tcbinfo);
return (error);
}
#endif /* INET6 */
@@ -639,6 +645,7 @@ tcp6_usr_accept(struct socket *so, struct sockaddr **nam)
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp6_usr_accept: inp == NULL"));
+ INP_INFO_RLOCK(&V_tcbinfo);
INP_WLOCK(inp);
if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
error = ECONNABORTED;
@@ -664,6 +671,7 @@ tcp6_usr_accept(struct socket *so, struct sockaddr **nam)
out:
TCPDEBUG2(PRU_ACCEPT);
INP_WUNLOCK(inp);
+ INP_INFO_RUNLOCK(&V_tcbinfo);
if (error == 0) {
if (v4)
*nam = in6_v4mapsin6_sockaddr(port, &addr);
@@ -750,25 +758,17 @@ tcp_usr_send(struct socket *so, int flags, struct mbuf *m,
int error = 0;
struct inpcb *inp;
struct tcpcb *tp = NULL;
- int headlocked = 0;
#ifdef INET6
int isipv6;
#endif
TCPDEBUG0;
/*
- * We require the pcbinfo lock in two cases:
- *
- * (1) An implied connect is taking place, which can result in
- * binding IPs and ports and hence modification of the pcb hash
- * chains.
- *
- * (2) PRUS_EOF is set, resulting in explicit close on the send.
+ * We require the pcbinfo lock if we will close the socket as part of
+ * this call.
*/
- if ((nam != NULL) || (flags & PRUS_EOF)) {
+ if (flags & PRUS_EOF)
INP_INFO_WLOCK(&V_tcbinfo);
- headlocked = 1;
- }
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp_usr_send: inp == NULL"));
INP_WLOCK(inp);
@@ -805,7 +805,6 @@ tcp_usr_send(struct socket *so, int flags, struct mbuf *m,
* initialize maxseg/maxopd using peer's cached
* MSS.
*/
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
#ifdef INET6
if (isipv6)
error = tcp6_connect(tp, nam, td);
@@ -830,10 +829,6 @@ tcp_usr_send(struct socket *so, int flags, struct mbuf *m,
socantsendmore(so);
tcp_usrclosed(tp);
}
- if (headlocked) {
- INP_INFO_WUNLOCK(&V_tcbinfo);
- headlocked = 0;
- }
if (!(inp->inp_flags & INP_DROPPED)) {
if (flags & PRUS_MORETOCOME)
tp->t_flags |= TF_MORETOCOME;
@@ -869,7 +864,6 @@ tcp_usr_send(struct socket *so, int flags, struct mbuf *m,
* initialize maxseg/maxopd using peer's cached
* MSS.
*/
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
#ifdef INET6
if (isipv6)
error = tcp6_connect(tp, nam, td);
@@ -884,11 +878,6 @@ tcp_usr_send(struct socket *so, int flags, struct mbuf *m,
goto out;
tp->snd_wnd = TTCP_CLIENT_SND_WND;
tcp_mss(tp, -1);
- INP_INFO_WUNLOCK(&V_tcbinfo);
- headlocked = 0;
- } else if (nam) {
- INP_INFO_WUNLOCK(&V_tcbinfo);
- headlocked = 0;
}
tp->snd_up = tp->snd_una + so->so_snd.sb_cc;
tp->t_flags |= TF_FORCEDATA;
@@ -899,7 +888,7 @@ out:
TCPDEBUG2((flags & PRUS_OOB) ? PRU_SENDOOB :
((flags & PRUS_EOF) ? PRU_SEND_EOF : PRU_SEND));
INP_WUNLOCK(inp);
- if (headlocked)
+ if (flags & PRUS_EOF)
INP_INFO_WUNLOCK(&V_tcbinfo);
return (error);
}
@@ -1087,13 +1076,13 @@ tcp_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
u_short lport;
int error;
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
INP_WLOCK_ASSERT(inp);
+ INP_HASH_WLOCK(&V_tcbinfo);
if (inp->inp_lport == 0) {
error = in_pcbbind(inp, (struct sockaddr *)0, td->td_ucred);
if (error)
- return error;
+ goto out;
}
/*
@@ -1106,11 +1095,14 @@ tcp_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
error = in_pcbconnect_setup(inp, nam, &laddr.s_addr, &lport,
&inp->inp_faddr.s_addr, &inp->inp_fport, &oinp, td->td_ucred);
if (error && oinp == NULL)
- return error;
- if (oinp)
- return EADDRINUSE;
+ goto out;
+ if (oinp) {
+ error = EADDRINUSE;
+ goto out;
+ }
inp->inp_laddr = laddr;
in_pcbrehash(inp);
+ INP_HASH_WUNLOCK(&V_tcbinfo);
/*
* Compute window scaling to request:
@@ -1129,6 +1121,10 @@ tcp_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
tcp_sendseqinit(tp);
return 0;
+
+out:
+ INP_HASH_WUNLOCK(&V_tcbinfo);
+ return (error);
}
#endif /* INET */
@@ -1142,13 +1138,13 @@ tcp6_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
struct in6_addr addr6;
int error;
- INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
INP_WLOCK_ASSERT(inp);
+ INP_HASH_WLOCK(&V_tcbinfo);
if (inp->inp_lport == 0) {
error = in6_pcbbind(inp, (struct sockaddr *)0, td->td_ucred);
if (error)
- return error;
+ goto out;
}
/*
@@ -1156,18 +1152,23 @@ tcp6_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
* earlier incarnation of this same connection still in
* TIME_WAIT state, creating an ADDRINUSE error.
* in6_pcbladdr() also handles scope zone IDs.
+ *
+ * XXXRW: We wouldn't need to expose in6_pcblookup_hash_locked()
+ * outside of in6_pcb.c if there were an in6_pcbconnect_setup().
*/
error = in6_pcbladdr(inp, nam, &addr6);
if (error)
- return error;
- oinp = in6_pcblookup_hash(inp->inp_pcbinfo,
+ goto out;
+ oinp = in6_pcblookup_hash_locked(inp->inp_pcbinfo,
&sin6->sin6_addr, sin6->sin6_port,
IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)
? &addr6
: &inp->in6p_laddr,
inp->inp_lport, 0, NULL);
- if (oinp)
- return EADDRINUSE;
+ if (oinp) {
+ error = EADDRINUSE;
+ goto out;
+ }
if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
inp->in6p_laddr = addr6;
inp->in6p_faddr = sin6->sin6_addr;
@@ -1178,6 +1179,7 @@ tcp6_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
inp->inp_flow |=
(htonl(ip6_randomflowlabel()) & IPV6_FLOWLABEL_MASK);
in_pcbrehash(inp);
+ INP_HASH_WUNLOCK(&V_tcbinfo);
/* Compute window scaling to request. */
while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
@@ -1192,6 +1194,10 @@ tcp6_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
tcp_sendseqinit(tp);
return 0;
+
+out:
+ INP_HASH_WUNLOCK(&V_tcbinfo);
+ return error;
}
#endif /* INET6 */
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index c3503e6..fd864c0 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -2,8 +2,12 @@
* Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
* The Regents of the University of California.
* Copyright (c) 2008 Robert N. M. Watson
+ * Copyright (c) 2010-2011 Juniper Networks, Inc.
* All rights reserved.
*
+ * Portions of this software were developed by Robert N. M. Watson under
+ * contract to Juniper Networks, Inc.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -253,7 +257,7 @@ udp_append(struct inpcb *inp, struct ip *ip, struct mbuf *n, int off,
#endif
struct udpcb *up;
- INP_RLOCK_ASSERT(inp);
+ INP_LOCK_ASSERT(inp);
/*
* Engage the tunneling protocol.
@@ -458,12 +462,12 @@ udp_input(struct mbuf *m, int off)
}
#endif
- INP_INFO_RLOCK(&V_udbinfo);
if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) ||
in_broadcast(ip->ip_dst, ifp)) {
struct inpcb *last;
struct ip_moptions *imo;
+ INP_INFO_RLOCK(&V_udbinfo);
last = NULL;
LIST_FOREACH(inp, &V_udb, inp_list) {
if (inp->inp_lport != uh->uh_dport)
@@ -485,6 +489,13 @@ udp_input(struct mbuf *m, int off)
INP_RLOCK(inp);
/*
+ * XXXRW: Because we weren't holding either the inpcb
+ * or the hash lock when we checked for a match
+ * before, we should probably recheck now that the
+ * inpcb lock is held.
+ */
+
+ /*
* Handle socket delivery policy for any-source
* and source-specific multicast. [RFC3678]
*/
@@ -542,7 +553,10 @@ udp_input(struct mbuf *m, int off)
* or multicast datgram.)
*/
UDPSTAT_INC(udps_noportbcast);
- goto badheadlocked;
+ if (inp)
+ INP_RUNLOCK(inp);
+ INP_INFO_RUNLOCK(&V_udbinfo);
+ goto badunlocked;
}
udp_append(last, ip, m, iphlen, &udp_in);
INP_RUNLOCK(last);
@@ -553,8 +567,9 @@ udp_input(struct mbuf *m, int off)
/*
* Locate pcb for datagram.
*/
- inp = in_pcblookup_hash(&V_udbinfo, ip->ip_src, uh->uh_sport,
- ip->ip_dst, uh->uh_dport, 1, ifp);
+ inp = in_pcblookup_mbuf(&V_udbinfo, ip->ip_src, uh->uh_sport,
+ ip->ip_dst, uh->uh_dport, INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB,
+ ifp, m);
if (inp == NULL) {
if (udp_log_in_vain) {
char buf[4*sizeof "123"];
@@ -568,36 +583,31 @@ udp_input(struct mbuf *m, int off)
UDPSTAT_INC(udps_noport);
if (m->m_flags & (M_BCAST | M_MCAST)) {
UDPSTAT_INC(udps_noportbcast);
- goto badheadlocked;
+ goto badunlocked;
}
if (V_udp_blackhole)
- goto badheadlocked;
+ goto badunlocked;
if (badport_bandlim(BANDLIM_ICMP_UNREACH) < 0)
- goto badheadlocked;
+ goto badunlocked;
*ip = save_ip;
ip->ip_len += iphlen;
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
- INP_INFO_RUNLOCK(&V_udbinfo);
return;
}
/*
* Check the minimum TTL for socket.
*/
- INP_RLOCK(inp);
- INP_INFO_RUNLOCK(&V_udbinfo);
+ INP_RLOCK_ASSERT(inp);
if (inp->inp_ip_minttl && inp->inp_ip_minttl > ip->ip_ttl) {
INP_RUNLOCK(inp);
- goto badunlocked;
+ m_freem(m);
+ return;
}
udp_append(inp, ip, m, iphlen, &udp_in);
INP_RUNLOCK(inp);
return;
-badheadlocked:
- if (inp)
- INP_RUNLOCK(inp);
- INP_INFO_RUNLOCK(&V_udbinfo);
badunlocked:
m_freem(m);
}
@@ -656,17 +666,15 @@ udp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
return;
if (ip != NULL) {
uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2));
- INP_INFO_RLOCK(&V_udbinfo);
- inp = in_pcblookup_hash(&V_udbinfo, faddr, uh->uh_dport,
- ip->ip_src, uh->uh_sport, 0, NULL);
+ inp = in_pcblookup(&V_udbinfo, faddr, uh->uh_dport,
+ ip->ip_src, uh->uh_sport, INPLOOKUP_RLOCKPCB, NULL);
if (inp != NULL) {
- INP_RLOCK(inp);
+ INP_RLOCK_ASSERT(inp);
if (inp->inp_socket != NULL) {
udp_notify(inp, inetctlerrmap[cmd]);
}
INP_RUNLOCK(inp);
}
- INP_INFO_RUNLOCK(&V_udbinfo);
} else
in_pcbnotifyall(&V_udbinfo, faddr, inetctlerrmap[cmd],
udp_notify);
@@ -756,9 +764,9 @@ udp_pcblist(SYSCTL_HANDLER_ARGS)
INP_INFO_WLOCK(&V_udbinfo);
for (i = 0; i < n; i++) {
inp = inp_list[i];
- INP_WLOCK(inp);
- if (!in_pcbrele(inp))
- INP_WUNLOCK(inp);
+ INP_RLOCK(inp);
+ if (!in_pcbrele_rlocked(inp))
+ INP_RUNLOCK(inp);
}
INP_INFO_WUNLOCK(&V_udbinfo);
@@ -799,12 +807,11 @@ udp_getcred(SYSCTL_HANDLER_ARGS)
error = SYSCTL_IN(req, addrs, sizeof(addrs));
if (error)
return (error);
- INP_INFO_RLOCK(&V_udbinfo);
- inp = in_pcblookup_hash(&V_udbinfo, addrs[1].sin_addr, addrs[1].sin_port,
- addrs[0].sin_addr, addrs[0].sin_port, 1, NULL);
+ inp = in_pcblookup(&V_udbinfo, addrs[1].sin_addr, addrs[1].sin_port,
+ addrs[0].sin_addr, addrs[0].sin_port,
+ INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB, NULL);
if (inp != NULL) {
- INP_RLOCK(inp);
- INP_INFO_RUNLOCK(&V_udbinfo);
+ INP_RLOCK_ASSERT(inp);
if (inp->inp_socket == NULL)
error = ENOENT;
if (error == 0)
@@ -812,10 +819,8 @@ udp_getcred(SYSCTL_HANDLER_ARGS)
if (error == 0)
cru2x(inp->inp_cred, &xuc);
INP_RUNLOCK(inp);
- } else {
- INP_INFO_RUNLOCK(&V_udbinfo);
+ } else
error = ENOENT;
- }
if (error == 0)
error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
return (error);
@@ -924,6 +929,9 @@ udp_ctloutput(struct socket *so, struct sockopt *sopt)
}
#ifdef INET
+#define UH_WLOCKED 2
+#define UH_RLOCKED 1
+#define UH_UNLOCKED 0
static int
udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
struct mbuf *control, struct thread *td)
@@ -1016,29 +1024,27 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
* conservative locks than required the second time around, so later
* assertions have to accept that. Further analysis of the number of
* misses under contention is required.
+ *
+ * XXXRW: Check that hash locking update here is correct.
*/
sin = (struct sockaddr_in *)addr;
INP_RLOCK(inp);
if (sin != NULL &&
(inp->inp_laddr.s_addr == INADDR_ANY && inp->inp_lport == 0)) {
INP_RUNLOCK(inp);
- INP_INFO_WLOCK(&V_udbinfo);
INP_WLOCK(inp);
- unlock_udbinfo = 2;
+ INP_HASH_WLOCK(&V_udbinfo);
+ unlock_udbinfo = UH_WLOCKED;
} else if ((sin != NULL && (
(sin->sin_addr.s_addr == INADDR_ANY) ||
(sin->sin_addr.s_addr == INADDR_BROADCAST) ||
(inp->inp_laddr.s_addr == INADDR_ANY) ||
(inp->inp_lport == 0))) ||
(src.sin_family == AF_INET)) {
- if (!INP_INFO_TRY_RLOCK(&V_udbinfo)) {
- INP_RUNLOCK(inp);
- INP_INFO_RLOCK(&V_udbinfo);
- INP_RLOCK(inp);
- }
- unlock_udbinfo = 1;
+ INP_HASH_RLOCK(&V_udbinfo);
+ unlock_udbinfo = UH_RLOCKED;
} else
- unlock_udbinfo = 0;
+ unlock_udbinfo = UH_UNLOCKED;
/*
* If the IP_SENDSRCADDR control message was specified, override the
@@ -1048,7 +1054,7 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
laddr = inp->inp_laddr;
lport = inp->inp_lport;
if (src.sin_family == AF_INET) {
- INP_INFO_LOCK_ASSERT(&V_udbinfo);
+ INP_HASH_LOCK_ASSERT(&V_udbinfo);
if ((lport == 0) ||
(laddr.s_addr == INADDR_ANY &&
src.sin_addr.s_addr == INADDR_ANY)) {
@@ -1099,7 +1105,7 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
inp->inp_lport == 0 ||
sin->sin_addr.s_addr == INADDR_ANY ||
sin->sin_addr.s_addr == INADDR_BROADCAST) {
- INP_INFO_LOCK_ASSERT(&V_udbinfo);
+ INP_HASH_LOCK_ASSERT(&V_udbinfo);
error = in_pcbconnect_setup(inp, addr, &laddr.s_addr,
&lport, &faddr.s_addr, &fport, NULL,
td->td_ucred);
@@ -1113,8 +1119,8 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
/* Commit the local port if newly assigned. */
if (inp->inp_laddr.s_addr == INADDR_ANY &&
inp->inp_lport == 0) {
- INP_INFO_WLOCK_ASSERT(&V_udbinfo);
INP_WLOCK_ASSERT(inp);
+ INP_HASH_WLOCK_ASSERT(&V_udbinfo);
/*
* Remember addr if jailed, to prevent
* rebinding.
@@ -1209,25 +1215,25 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
((struct ip *)ui)->ip_tos = inp->inp_ip_tos; /* XXX */
UDPSTAT_INC(udps_opackets);
- if (unlock_udbinfo == 2)
- INP_INFO_WUNLOCK(&V_udbinfo);
- else if (unlock_udbinfo == 1)
- INP_INFO_RUNLOCK(&V_udbinfo);
+ if (unlock_udbinfo == UH_WLOCKED)
+ INP_HASH_WUNLOCK(&V_udbinfo);
+ else if (unlock_udbinfo == UH_RLOCKED)
+ INP_HASH_RUNLOCK(&V_udbinfo);
error = ip_output(m, inp->inp_options, NULL, ipflags,
inp->inp_moptions, inp);
- if (unlock_udbinfo == 2)
+ if (unlock_udbinfo == UH_WLOCKED)
INP_WUNLOCK(inp);
else
INP_RUNLOCK(inp);
return (error);
release:
- if (unlock_udbinfo == 2) {
+ if (unlock_udbinfo == UH_WLOCKED) {
+ INP_HASH_WUNLOCK(&V_udbinfo);
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_udbinfo);
- } else if (unlock_udbinfo == 1) {
+ } else if (unlock_udbinfo == UH_RLOCKED) {
+ INP_HASH_RUNLOCK(&V_udbinfo);
INP_RUNLOCK(inp);
- INP_INFO_RUNLOCK(&V_udbinfo);
} else
INP_RUNLOCK(inp);
m_freem(m);
@@ -1376,15 +1382,15 @@ udp_abort(struct socket *so)
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("udp_abort: inp == NULL"));
- INP_INFO_WLOCK(&V_udbinfo);
INP_WLOCK(inp);
if (inp->inp_faddr.s_addr != INADDR_ANY) {
+ INP_HASH_WLOCK(&V_udbinfo);
in_pcbdisconnect(inp);
inp->inp_laddr.s_addr = INADDR_ANY;
+ INP_HASH_WUNLOCK(&V_udbinfo);
soisdisconnected(so);
}
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_udbinfo);
}
static int
@@ -1453,11 +1459,11 @@ udp_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("udp_bind: inp == NULL"));
- INP_INFO_WLOCK(&V_udbinfo);
INP_WLOCK(inp);
+ INP_HASH_WLOCK(&V_udbinfo);
error = in_pcbbind(inp, nam, td->td_ucred);
+ INP_HASH_WUNLOCK(&V_udbinfo);
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_udbinfo);
return (error);
}
@@ -1468,15 +1474,15 @@ udp_close(struct socket *so)
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("udp_close: inp == NULL"));
- INP_INFO_WLOCK(&V_udbinfo);
INP_WLOCK(inp);
if (inp->inp_faddr.s_addr != INADDR_ANY) {
+ INP_HASH_WLOCK(&V_udbinfo);
in_pcbdisconnect(inp);
inp->inp_laddr.s_addr = INADDR_ANY;
+ INP_HASH_WUNLOCK(&V_udbinfo);
soisdisconnected(so);
}
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_udbinfo);
}
static int
@@ -1488,25 +1494,23 @@ udp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("udp_connect: inp == NULL"));
- INP_INFO_WLOCK(&V_udbinfo);
INP_WLOCK(inp);
if (inp->inp_faddr.s_addr != INADDR_ANY) {
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_udbinfo);
return (EISCONN);
}
sin = (struct sockaddr_in *)nam;
error = prison_remote_ip4(td->td_ucred, &sin->sin_addr);
if (error != 0) {
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_udbinfo);
return (error);
}
+ INP_HASH_WLOCK(&V_udbinfo);
error = in_pcbconnect(inp, nam, td->td_ucred);
+ INP_HASH_WUNLOCK(&V_udbinfo);
if (error == 0)
soisconnected(so);
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_udbinfo);
return (error);
}
@@ -1538,21 +1542,19 @@ udp_disconnect(struct socket *so)
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("udp_disconnect: inp == NULL"));
- INP_INFO_WLOCK(&V_udbinfo);
INP_WLOCK(inp);
if (inp->inp_faddr.s_addr == INADDR_ANY) {
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_udbinfo);
return (ENOTCONN);
}
-
+ INP_HASH_WLOCK(&V_udbinfo);
in_pcbdisconnect(inp);
inp->inp_laddr.s_addr = INADDR_ANY;
+ INP_HASH_WUNLOCK(&V_udbinfo);
SOCK_LOCK(so);
so->so_state &= ~SS_ISCONNECTED; /* XXX */
SOCK_UNLOCK(so);
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_udbinfo);
return (0);
}
diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c
index eacce8c..da73f21 100644
--- a/sys/netinet6/in6_pcb.c
+++ b/sys/netinet6/in6_pcb.c
@@ -1,7 +1,11 @@
/*-
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * Copyright (c) 2010-2011 Juniper Networks, Inc.
* All rights reserved.
*
+ * Portions of this software were developed by Robert N. M. Watson under
+ * contract to Juniper Networks, Inc.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -114,8 +118,8 @@ in6_pcbbind(register struct inpcb *inp, struct sockaddr *nam,
int error, lookupflags = 0;
int reuseport = (so->so_options & SO_REUSEPORT);
- INP_INFO_WLOCK_ASSERT(pcbinfo);
INP_WLOCK_ASSERT(inp);
+ INP_HASH_WLOCK_ASSERT(pcbinfo);
if (TAILQ_EMPTY(&V_in6_ifaddrhead)) /* XXX broken! */
return (EADDRNOTAVAIL);
@@ -298,8 +302,8 @@ in6_pcbladdr(register struct inpcb *inp, struct sockaddr *nam,
int scope_ambiguous = 0;
struct in6_addr in6a;
- INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
INP_WLOCK_ASSERT(inp);
+ INP_HASH_WLOCK_ASSERT(inp->inp_pcbinfo); /* XXXRW: why? */
if (nam->sa_len != sizeof (*sin6))
return (EINVAL);
@@ -360,15 +364,16 @@ in6_pcbladdr(register struct inpcb *inp, struct sockaddr *nam,
* then pick one.
*/
int
-in6_pcbconnect(register struct inpcb *inp, struct sockaddr *nam,
- struct ucred *cred)
+in6_pcbconnect_mbuf(register struct inpcb *inp, struct sockaddr *nam,
+ struct ucred *cred, struct mbuf *m)
{
+ struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
register struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam;
struct in6_addr addr6;
int error;
- INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
INP_WLOCK_ASSERT(inp);
+ INP_HASH_WLOCK_ASSERT(pcbinfo);
/*
* Call inner routine, to assign local interface address.
@@ -377,7 +382,7 @@ in6_pcbconnect(register struct inpcb *inp, struct sockaddr *nam,
if ((error = in6_pcbladdr(inp, nam, &addr6)) != 0)
return (error);
- if (in6_pcblookup_hash(inp->inp_pcbinfo, &sin6->sin6_addr,
+ if (in6_pcblookup_hash_locked(pcbinfo, &sin6->sin6_addr,
sin6->sin6_port,
IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)
? &addr6 : &inp->in6p_laddr,
@@ -400,17 +405,24 @@ in6_pcbconnect(register struct inpcb *inp, struct sockaddr *nam,
inp->inp_flow |=
(htonl(ip6_randomflowlabel()) & IPV6_FLOWLABEL_MASK);
- in_pcbrehash(inp);
+ in_pcbrehash_mbuf(inp, m);
return (0);
}
+int
+in6_pcbconnect(struct inpcb *inp, struct sockaddr *nam, struct ucred *cred)
+{
+
+ return (in6_pcbconnect_mbuf(inp, nam, cred, NULL));
+}
+
void
in6_pcbdisconnect(struct inpcb *inp)
{
- INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
INP_WLOCK_ASSERT(inp);
+ INP_HASH_WLOCK_ASSERT(inp->inp_pcbinfo);
bzero((caddr_t)&inp->in6p_faddr, sizeof(inp->in6p_faddr));
inp->inp_fport = 0;
@@ -649,7 +661,8 @@ in6_pcbnotify(struct inpcbinfo *pcbinfo, struct sockaddr *dst,
}
/*
- * Lookup a PCB based on the local address and port.
+ * Lookup a PCB based on the local address and port. Caller must hold the
+ * hash lock. No inpcb locks or references are acquired.
*/
struct inpcb *
in6_pcblookup_local(struct inpcbinfo *pcbinfo, struct in6_addr *laddr,
@@ -661,7 +674,7 @@ in6_pcblookup_local(struct inpcbinfo *pcbinfo, struct in6_addr *laddr,
KASSERT((lookupflags & ~(INPLOOKUP_WILDCARD)) == 0,
("%s: invalid lookup flags %d", __func__, lookupflags));
- INP_INFO_WLOCK_ASSERT(pcbinfo);
+ INP_HASH_WLOCK_ASSERT(pcbinfo);
if ((lookupflags & INPLOOKUP_WILDCARD) == 0) {
struct inpcbhead *head;
@@ -818,9 +831,9 @@ in6_rtchange(struct inpcb *inp, int errno)
* Lookup PCB in hash list.
*/
struct inpcb *
-in6_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in6_addr *faddr,
- u_int fport_arg, struct in6_addr *laddr, u_int lport_arg, int lookupflags,
- struct ifnet *ifp)
+in6_pcblookup_hash_locked(struct inpcbinfo *pcbinfo, struct in6_addr *faddr,
+ u_int fport_arg, struct in6_addr *laddr, u_int lport_arg,
+ int lookupflags, struct ifnet *ifp)
{
struct inpcbhead *head;
struct inpcb *inp, *tmpinp;
@@ -830,7 +843,7 @@ in6_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in6_addr *faddr,
KASSERT((lookupflags & ~(INPLOOKUP_WILDCARD)) == 0,
("%s: invalid lookup flags %d", __func__, lookupflags));
- INP_INFO_LOCK_ASSERT(pcbinfo);
+ INP_HASH_LOCK_ASSERT(pcbinfo);
if (faithprefix_p != NULL)
faith = (*faithprefix_p)(laddr);
@@ -934,6 +947,70 @@ in6_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in6_addr *faddr,
return (NULL);
}
+/*
+ * Lookup PCB in hash list, using pcbinfo tables. This variation locks the
+ * hash list lock, and will return the inpcb locked (i.e., requires
+ * INPLOOKUP_LOCKPCB).
+ */
+static struct inpcb *
+in6_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in6_addr *faddr,
+ u_int fport, struct in6_addr *laddr, u_int lport, int lookupflags,
+ struct ifnet *ifp)
+{
+ struct inpcb *inp;
+
+ INP_HASH_RLOCK(pcbinfo);
+ inp = in6_pcblookup_hash_locked(pcbinfo, faddr, fport, laddr, lport,
+ (lookupflags & ~(INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB)), ifp);
+ if (inp != NULL) {
+ in_pcbref(inp);
+ INP_HASH_RUNLOCK(pcbinfo);
+ if (lookupflags & INPLOOKUP_WLOCKPCB) {
+ INP_WLOCK(inp);
+ if (in_pcbrele_wlocked(inp))
+ return (NULL);
+ } else if (lookupflags & INPLOOKUP_RLOCKPCB) {
+ INP_RLOCK(inp);
+ if (in_pcbrele_rlocked(inp))
+ return (NULL);
+ } else
+ panic("%s: locking bug", __func__);
+ } else
+ INP_HASH_RUNLOCK(pcbinfo);
+ return (inp);
+}
+
+/*
+ * Public inpcb lookup routines, accepting a 4-tuple, and optionally, an mbuf
+ * from which a pre-calculated hash value may be extracted.
+ */
+struct inpcb *
+in6_pcblookup(struct inpcbinfo *pcbinfo, struct in6_addr *faddr, u_int fport,
+ struct in6_addr *laddr, u_int lport, int lookupflags, struct ifnet *ifp)
+{
+ KASSERT((lookupflags & ~INPLOOKUP_MASK) == 0,
+ ("%s: invalid lookup flags %d", __func__, lookupflags));
+ KASSERT((lookupflags & (INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB)) != 0,
+ ("%s: LOCKPCB not set", __func__));
+
+ return (in6_pcblookup_hash(pcbinfo, faddr, fport, laddr, lport,
+ lookupflags, ifp));
+}
+
+struct inpcb *
+in6_pcblookup_mbuf(struct inpcbinfo *pcbinfo, struct in6_addr *faddr,
+ u_int fport, struct in6_addr *laddr, u_int lport, int lookupflags,
+ struct ifnet *ifp, struct mbuf *m)
+{
+ KASSERT((lookupflags & ~INPLOOKUP_MASK) == 0,
+ ("%s: invalid lookup flags %d", __func__, lookupflags));
+ KASSERT((lookupflags & (INPLOOKUP_RLOCKPCB | INPLOOKUP_WLOCKPCB)) != 0,
+ ("%s: LOCKPCB not set", __func__));
+
+ return (in6_pcblookup_hash(pcbinfo, faddr, fport, laddr, lport,
+ lookupflags, ifp));
+}
+
void
init_sin6(struct sockaddr_in6 *sin6, struct mbuf *m)
{
diff --git a/sys/netinet6/in6_pcb.h b/sys/netinet6/in6_pcb.h
index c54a8cf..cf24704 100644
--- a/sys/netinet6/in6_pcb.h
+++ b/sys/netinet6/in6_pcb.h
@@ -73,6 +73,8 @@ void in6_pcbpurgeif0 __P((struct inpcbinfo *, struct ifnet *));
void in6_losing __P((struct inpcb *));
int in6_pcbbind __P((struct inpcb *, struct sockaddr *, struct ucred *));
int in6_pcbconnect __P((struct inpcb *, struct sockaddr *, struct ucred *));
+int in6_pcbconnect_mbuf __P((struct inpcb *, struct sockaddr *,
+ struct ucred *, struct mbuf *));
void in6_pcbdisconnect __P((struct inpcb *));
int in6_pcbladdr(struct inpcb *, struct sockaddr *, struct in6_addr *);
struct inpcb *
@@ -80,9 +82,17 @@ struct inpcb *
struct in6_addr *, u_short, int,
struct ucred *));
struct inpcb *
- in6_pcblookup_hash __P((struct inpcbinfo *,
- struct in6_addr *, u_int, struct in6_addr *,
- u_int, int, struct ifnet *));
+ in6_pcblookup __P((struct inpcbinfo *, struct in6_addr *,
+ u_int, struct in6_addr *, u_int, int,
+ struct ifnet *));
+struct inpcb *
+ in6_pcblookup_hash_locked __P((struct inpcbinfo *, struct in6_addr *,
+ u_int, struct in6_addr *, u_int, int,
+ struct ifnet *));
+struct inpcb *
+ in6_pcblookup_mbuf __P((struct inpcbinfo *, struct in6_addr *,
+ u_int, struct in6_addr *, u_int, int,
+ struct ifnet *ifp, struct mbuf *));
void in6_pcbnotify __P((struct inpcbinfo *, struct sockaddr *,
u_int, const struct sockaddr *, u_int, int, void *,
struct inpcb *(*)(struct inpcb *, int)));
diff --git a/sys/netinet6/in6_src.c b/sys/netinet6/in6_src.c
index 5202e09..c802bfc 100644
--- a/sys/netinet6/in6_src.c
+++ b/sys/netinet6/in6_src.c
@@ -856,8 +856,8 @@ in6_pcbsetport(struct in6_addr *laddr, struct inpcb *inp, struct ucred *cred)
struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
#endif
- INP_INFO_WLOCK_ASSERT(pcbinfo);
INP_WLOCK_ASSERT(inp);
+ INP_HASH_WLOCK_ASSERT(pcbinfo);
error = prison_local_ip6(cred, laddr,
((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0));
diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c
index d574c19..6723007 100644
--- a/sys/netinet6/udp6_usrreq.c
+++ b/sys/netinet6/udp6_usrreq.c
@@ -1,7 +1,11 @@
/*-
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * Copyright (c) 2010-2011 Juniper Networks, Inc.
* All rights reserved.
*
+ * Portions of this software were developed by Robert N. M. Watson under
+ * contract to Juniper Networks, Inc.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -231,11 +235,11 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
init_sin6(&fromsa, m);
fromsa.sin6_port = uh->uh_sport;
- INP_INFO_RLOCK(&V_udbinfo);
if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
struct inpcb *last;
struct ip6_moptions *imo;
+ INP_INFO_RLOCK(&V_udbinfo);
/*
* In the event that laddr should be set to the link-local
* address (this happens in RIPng), the multicast address
@@ -273,6 +277,13 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
}
/*
+ * XXXRW: Because we weren't holding either the inpcb
+ * or the hash lock when we checked for a match
+ * before, we should probably recheck now that the
+ * inpcb lock is (supposed to be) held.
+ */
+
+ /*
* Handle socket delivery policy for any-source
* and source-specific multicast. [RFC3678]
*/
@@ -366,8 +377,9 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
/*
* Locate pcb for datagram.
*/
- inp = in6_pcblookup_hash(&V_udbinfo, &ip6->ip6_src, uh->uh_sport,
- &ip6->ip6_dst, uh->uh_dport, 1, m->m_pkthdr.rcvif);
+ inp = in6_pcblookup_mbuf(&V_udbinfo, &ip6->ip6_src, uh->uh_sport,
+ &ip6->ip6_dst, uh->uh_dport, INPLOOKUP_WILDCARD |
+ INPLOOKUP_RLOCKPCB, m->m_pkthdr.rcvif, m);
if (inp == NULL) {
if (udp_log_in_vain) {
char ip6bufs[INET6_ADDRSTRLEN];
@@ -384,9 +396,8 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
if (m->m_flags & M_MCAST) {
printf("UDP6: M_MCAST is set in a unicast packet.\n");
UDPSTAT_INC(udps_noportmcast);
- goto badheadlocked;
+ goto badunlocked;
}
- INP_INFO_RUNLOCK(&V_udbinfo);
if (V_udp_blackhole)
goto badunlocked;
if (badport_bandlim(BANDLIM_ICMP6_UNREACH) < 0)
@@ -394,8 +405,7 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
icmp6_error(m, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0);
return (IPPROTO_DONE);
}
- INP_RLOCK(inp);
- INP_INFO_RUNLOCK(&V_udbinfo);
+ INP_RLOCK_ASSERT(inp);
up = intoudpcb(inp);
if (up->u_tun_func == NULL) {
udp6_append(inp, m, off, &fromsa);
@@ -505,13 +515,11 @@ udp6_getcred(SYSCTL_HANDLER_ARGS)
(error = sa6_embedscope(&addrs[1], V_ip6_use_defzone)) != 0) {
return (error);
}
- INP_INFO_RLOCK(&V_udbinfo);
- inp = in6_pcblookup_hash(&V_udbinfo, &addrs[1].sin6_addr,
- addrs[1].sin6_port, &addrs[0].sin6_addr, addrs[0].sin6_port, 1,
- NULL);
+ inp = in6_pcblookup(&V_udbinfo, &addrs[1].sin6_addr,
+ addrs[1].sin6_port, &addrs[0].sin6_addr, addrs[0].sin6_port,
+ INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB, NULL);
if (inp != NULL) {
- INP_RLOCK(inp);
- INP_INFO_RUNLOCK(&V_udbinfo);
+ INP_RLOCK_ASSERT(inp);
if (inp->inp_socket == NULL)
error = ENOENT;
if (error == 0)
@@ -520,10 +528,8 @@ udp6_getcred(SYSCTL_HANDLER_ARGS)
if (error == 0)
cru2x(inp->inp_cred, &xuc);
INP_RUNLOCK(inp);
- } else {
- INP_INFO_RUNLOCK(&V_udbinfo);
+ } else
error = ENOENT;
- }
if (error == 0)
error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
return (error);
@@ -552,6 +558,7 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
struct sockaddr_in6 tmp;
INP_WLOCK_ASSERT(inp);
+ INP_HASH_WLOCK_ASSERT(inp->inp_pcbinfo);
if (addr6) {
/* addr6 has been validated in udp6_send(). */
@@ -772,15 +779,15 @@ udp6_abort(struct socket *so)
}
#endif
- INP_INFO_WLOCK(&V_udbinfo);
INP_WLOCK(inp);
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
+ INP_HASH_WLOCK(&V_udbinfo);
in6_pcbdisconnect(inp);
inp->in6p_laddr = in6addr_any;
+ INP_HASH_WUNLOCK(&V_udbinfo);
soisdisconnected(so);
}
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_udbinfo);
}
static int
@@ -838,8 +845,8 @@ udp6_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("udp6_bind: inp == NULL"));
- INP_INFO_WLOCK(&V_udbinfo);
INP_WLOCK(inp);
+ INP_HASH_WLOCK(&V_udbinfo);
inp->inp_vflag &= ~INP_IPV4;
inp->inp_vflag |= INP_IPV6;
if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) {
@@ -867,8 +874,8 @@ udp6_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
#ifdef INET
out:
#endif
+ INP_HASH_WUNLOCK(&V_udbinfo);
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_udbinfo);
return (error);
}
@@ -889,15 +896,15 @@ udp6_close(struct socket *so)
return;
}
#endif
- INP_INFO_WLOCK(&V_udbinfo);
INP_WLOCK(inp);
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
+ INP_HASH_WLOCK(&V_udbinfo);
in6_pcbdisconnect(inp);
inp->in6p_laddr = in6addr_any;
+ INP_HASH_WUNLOCK(&V_udbinfo);
soisdisconnected(so);
}
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_udbinfo);
}
static int
@@ -911,7 +918,9 @@ udp6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
sin6 = (struct sockaddr_in6 *)nam;
KASSERT(inp != NULL, ("udp6_connect: inp == NULL"));
- INP_INFO_WLOCK(&V_udbinfo);
+ /*
+ * XXXRW: Need to clarify locking of v4/v6 flags.
+ */
INP_WLOCK(inp);
#ifdef INET
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
@@ -931,8 +940,10 @@ udp6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
error = prison_remote_ip4(td->td_ucred, &sin.sin_addr);
if (error != 0)
goto out;
+ INP_HASH_WLOCK(&V_udbinfo);
error = in_pcbconnect(inp, (struct sockaddr *)&sin,
td->td_ucred);
+ INP_HASH_WUNLOCK(&V_udbinfo);
if (error == 0)
soisconnected(so);
goto out;
@@ -947,12 +958,13 @@ udp6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
error = prison_remote_ip6(td->td_ucred, &sin6->sin6_addr);
if (error != 0)
goto out;
+ INP_HASH_WLOCK(&V_udbinfo);
error = in6_pcbconnect(inp, nam, td->td_ucred);
+ INP_HASH_WUNLOCK(&V_udbinfo);
if (error == 0)
soisconnected(so);
out:
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_udbinfo);
return (error);
}
@@ -984,32 +996,32 @@ udp6_disconnect(struct socket *so)
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("udp6_disconnect: inp == NULL"));
- INP_INFO_WLOCK(&V_udbinfo);
- INP_WLOCK(inp);
-
#ifdef INET
if (inp->inp_vflag & INP_IPV4) {
struct pr_usrreqs *pru;
pru = inetsw[ip_protox[IPPROTO_UDP]].pr_usrreqs;
- error = (*pru->pru_disconnect)(so);
- goto out;
+ (void)(*pru->pru_disconnect)(so);
+ return (0);
}
#endif
+ INP_WLOCK(inp);
+
if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
error = ENOTCONN;
goto out;
}
+ INP_HASH_WLOCK(&V_udbinfo);
in6_pcbdisconnect(inp);
inp->in6p_laddr = in6addr_any;
+ INP_HASH_WUNLOCK(&V_udbinfo);
SOCK_LOCK(so);
so->so_state &= ~SS_ISCONNECTED; /* XXX */
SOCK_UNLOCK(so);
out:
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_udbinfo);
return (0);
}
@@ -1023,7 +1035,6 @@ udp6_send(struct socket *so, int flags, struct mbuf *m,
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("udp6_send: inp == NULL"));
- INP_INFO_WLOCK(&V_udbinfo);
INP_WLOCK(inp);
if (addr) {
if (addr->sa_len != sizeof(struct sockaddr_in6)) {
@@ -1060,7 +1071,6 @@ udp6_send(struct socket *so, int flags, struct mbuf *m,
* select the UDPv4 output routine are invalidated?
*/
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_udbinfo);
if (sin6)
in6_sin6_2_sin_in_sock(addr);
pru = inetsw[ip_protox[IPPROTO_UDP]].pr_usrreqs;
@@ -1073,16 +1083,16 @@ udp6_send(struct socket *so, int flags, struct mbuf *m,
#ifdef MAC
mac_inpcb_create_mbuf(inp, m);
#endif
+ INP_HASH_WLOCK(&V_udbinfo);
error = udp6_output(inp, m, addr, control, td);
+ INP_HASH_WUNLOCK(&V_udbinfo);
#ifdef INET
#endif
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_udbinfo);
return (error);
bad:
INP_WUNLOCK(inp);
- INP_INFO_WUNLOCK(&V_udbinfo);
m_freem(m);
return (error);
}
diff --git a/sys/nfsclient/nfs_bio.c b/sys/nfsclient/nfs_bio.c
index 9a777c8..da8a2ec 100644
--- a/sys/nfsclient/nfs_bio.c
+++ b/sys/nfsclient/nfs_bio.c
@@ -300,7 +300,7 @@ nfs_putpages(struct vop_putpages_args *ap)
}
for (i = 0; i < npages; i++)
- rtvals[i] = VM_PAGER_AGAIN;
+ rtvals[i] = VM_PAGER_ERROR;
/*
* When putting pages, do not extend file past EOF.
@@ -344,11 +344,7 @@ nfs_putpages(struct vop_putpages_args *ap)
relpbuf(bp, &nfs_pbuf_freecnt);
if (!error) {
- int nwritten = round_page(count - uio.uio_resid) / PAGE_SIZE;
- for (i = 0; i < nwritten; i++) {
- rtvals[i] = VM_PAGER_OK;
- vm_page_undirty(pages[i]);
- }
+ vnode_pager_undirty_pages(pages, rtvals, count - uio.uio_resid);
if (must_commit) {
nfs_clearcommit(vp->v_mount);
}
diff --git a/sys/nfsclient/nfs_vfsops.c b/sys/nfsclient/nfs_vfsops.c
index 79659d0..8498ee4 100644
--- a/sys/nfsclient/nfs_vfsops.c
+++ b/sys/nfsclient/nfs_vfsops.c
@@ -1408,10 +1408,20 @@ nfs_sync(struct mount *mp, int waitfor)
td = curthread;
+ MNT_ILOCK(mp);
+ /*
+ * If a forced dismount is in progress, return from here so that
+ * the umount(2) syscall doesn't get stuck in VFS_SYNC() before
+ * calling VFS_UNMOUNT().
+ */
+ if ((mp->mnt_kern_flag & MNTK_UNMOUNTF) != 0) {
+ MNT_IUNLOCK(mp);
+ return (EBADF);
+ }
+
/*
* Force stale buffer cache information to be flushed.
*/
- MNT_ILOCK(mp);
loop:
MNT_VNODE_FOREACH(vp, mp, mvp) {
VI_LOCK(vp);
diff --git a/sys/powerpc/aim/interrupt.c b/sys/powerpc/aim/interrupt.c
index b06fb92..d1e3655 100644
--- a/sys/powerpc/aim/interrupt.c
+++ b/sys/powerpc/aim/interrupt.c
@@ -100,10 +100,8 @@ powerpc_interrupt(struct trapframe *framep)
default:
/* Re-enable interrupts if applicable. */
ee = framep->srr1 & PSL_EE;
- if (ee != 0) {
+ if (ee != 0)
mtmsr(mfmsr() | ee);
- isync();
- }
trap(framep);
}
}
diff --git a/sys/powerpc/aim/locore32.S b/sys/powerpc/aim/locore32.S
index 64bf81e..35ea99b 100644
--- a/sys/powerpc/aim/locore32.S
+++ b/sys/powerpc/aim/locore32.S
@@ -87,9 +87,6 @@ GLOBAL(tmpstk)
GLOBAL(esym)
.long 0 /* end of symbol table */
-GLOBAL(ofmsr)
- .long 0, 0, 0, 0, 0 /* msr/sprg0-3 used in Open Firmware */
-
#define INTRCNT_COUNT 256 /* max(HROWPIC_IRQMAX,OPENPIC_IRQMAX) */
GLOBAL(intrnames)
.space INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
@@ -99,16 +96,6 @@ GLOBAL(intrcnt)
.space INTRCNT_COUNT * 4 * 2
GLOBAL(eintrcnt)
-/*
- * File-scope for locore.S
- */
-idle_u:
- .long 0 /* fake uarea during idle after exit */
-openfirmware_entry:
- .long 0 /* Open Firmware entry point */
-srsave:
- .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-
.text
.globl btext
btext:
diff --git a/sys/powerpc/aim/locore64.S b/sys/powerpc/aim/locore64.S
index acdc8a1..c200b4c 100644
--- a/sys/powerpc/aim/locore64.S
+++ b/sys/powerpc/aim/locore64.S
@@ -75,8 +75,7 @@
.globl kernbase
.set kernbase, KERNBASE
-#define TMPSTKSZ 8192 /* 8K temporary stack */
-#define OFWSTKSZ 4096 /* 4K Open Firmware stack */
+#define TMPSTKSZ 16384 /* 16K temporary stack */
/*
* Globals
@@ -85,14 +84,9 @@
.align 4
GLOBAL(tmpstk)
.space TMPSTKSZ
-GLOBAL(ofwstk)
- .space OFWSTKSZ
GLOBAL(esym)
.llong 0 /* end of symbol table */
-GLOBAL(ofmsr)
- .llong 0, 0, 0, 0, 0 /* msr/sprg0-3 used in Open Firmware */
-
#define INTRCNT_COUNT 256 /* max(HROWPIC_IRQMAX,OPENPIC_IRQMAX) */
GLOBAL(intrnames)
.space INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
@@ -102,16 +96,6 @@ GLOBAL(intrcnt)
.space INTRCNT_COUNT * 4 * 2
GLOBAL(eintrcnt)
-/*
- * File-scope for locore.S
- */
-idle_u:
- .llong 0 /* fake uarea during idle after exit */
-openfirmware_entry:
- .llong 0 /* Open Firmware entry point */
-srsave:
- .llong 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-
.text
.globl btext
btext:
@@ -208,122 +192,6 @@ tocbase:
.llong .TOC.@tocbase
/*
- * Open Firmware Real-mode Entry Point. This is a huge pain.
- */
-
-ASENTRY(ofw_32bit_mode_entry)
- mflr %r0
- std %r0,16(%r1)
- stdu %r1,-208(%r1)
-
- /*
- * We need to save the following, because OF's register save/
- * restore code assumes that the contents of registers are
- * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These
- * get placed in that order in the stack.
- */
-
- mfcr %r4
- std %r4,48(%r1)
- std %r13,56(%r1)
- std %r14,64(%r1)
- std %r15,72(%r1)
- std %r16,80(%r1)
- std %r17,88(%r1)
- std %r18,96(%r1)
- std %r19,104(%r1)
- std %r20,112(%r1)
- std %r21,120(%r1)
- std %r22,128(%r1)
- std %r23,136(%r1)
- std %r24,144(%r1)
- std %r25,152(%r1)
- std %r26,160(%r1)
- std %r27,168(%r1)
- std %r28,176(%r1)
- std %r29,184(%r1)
- std %r30,192(%r1)
- std %r31,200(%r1)
-
- /* Record the old MSR */
- mfmsr %r6
-
- /* read client interface handler */
- lis %r4,openfirmware_entry@ha
- ld %r4,openfirmware_entry@l(%r4)
-
- /*
- * Set the MSR to the OF value. This has the side effect of disabling
- * exceptions, which is important for the next few steps.
- */
-
- lis %r5,ofmsr@ha
- ld %r5,ofmsr@l(%r5)
- mtmsrd %r5
- isync
-
- /*
- * Set up OF stack. This needs to be accessible in real mode and
- * use the 32-bit ABI stack frame format. The pointer to the current
- * kernel stack is placed at the very top of the stack along with
- * the old MSR so we can get them back later.
- */
- mr %r5,%r1
- lis %r1,(ofwstk+OFWSTKSZ-32)@ha
- addi %r1,%r1,(ofwstk+OFWSTKSZ-32)@l
- std %r5,8(%r1) /* Save real stack pointer */
- std %r2,16(%r1) /* Save old TOC */
- std %r6,24(%r1) /* Save old MSR */
- li %r5,0
- stw %r5,4(%r1)
- stw %r5,0(%r1)
-
- /* Finally, branch to OF */
- mtctr %r4
- bctrl
-
- /* Reload stack pointer and MSR from the OFW stack */
- ld %r6,24(%r1)
- ld %r2,16(%r1)
- ld %r1,8(%r1)
-
- /* Now set the real MSR */
- mtmsrd %r6
- isync
-
- /* Sign-extend the return value from OF */
- extsw %r3,%r3
-
- /* Restore all the non-volatile registers */
- ld %r5,48(%r1)
- mtcr %r5
- ld %r13,56(%r1)
- ld %r14,64(%r1)
- ld %r15,72(%r1)
- ld %r16,80(%r1)
- ld %r17,88(%r1)
- ld %r18,96(%r1)
- ld %r19,104(%r1)
- ld %r20,112(%r1)
- ld %r21,120(%r1)
- ld %r22,128(%r1)
- ld %r23,136(%r1)
- ld %r24,144(%r1)
- ld %r25,152(%r1)
- ld %r26,160(%r1)
- ld %r27,168(%r1)
- ld %r28,176(%r1)
- ld %r29,184(%r1)
- ld %r30,192(%r1)
- ld %r31,200(%r1)
-
- /* Restore the stack and link register */
- ld %r1,0(%r1)
- ld %r0,16(%r1)
- mtlr %r0
- blr
-
-/*
* int setfault()
*
* Similar to setjmp to setup for handling faults on accesses to user memory.
diff --git a/sys/powerpc/aim/machdep.c b/sys/powerpc/aim/machdep.c
index 65c9db1..3ccae91 100644
--- a/sys/powerpc/aim/machdep.c
+++ b/sys/powerpc/aim/machdep.c
@@ -132,6 +132,7 @@ extern vm_offset_t ksym_start, ksym_end;
int cold = 1;
#ifdef __powerpc64__
+extern int n_slbs;
int cacheline_size = 128;
#else
int cacheline_size = 32;
@@ -251,7 +252,6 @@ powerpc_init(vm_offset_t startkernel, vm_offset_t endkernel,
vm_offset_t basekernel, void *mdp)
{
struct pcpu *pc;
- vm_offset_t end;
void *generictrap;
size_t trap_offset;
void *kmdp;
@@ -263,7 +263,6 @@ powerpc_init(vm_offset_t startkernel, vm_offset_t endkernel,
int ppc64;
#endif
- end = 0;
kmdp = NULL;
trap_offset = 0;
cacheline_warn = 0;
@@ -279,7 +278,8 @@ powerpc_init(vm_offset_t startkernel, vm_offset_t endkernel,
if (kmdp != NULL) {
boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int);
kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *);
- end = MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t);
+ endkernel = ulmax(endkernel, MD_FETCH(kmdp,
+ MODINFOMD_KERNEND, vm_offset_t));
#ifdef DDB
ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t);
ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t);
@@ -338,13 +338,13 @@ powerpc_init(vm_offset_t startkernel, vm_offset_t endkernel,
kdb_init();
- /*
- * PowerPC 970 CPUs have a misfeature requested by Apple that makes
- * them pretend they have a 32-byte cacheline. Turn this off
- * before we measure the cacheline size.
- */
-
+ /* Various very early CPU fix ups */
switch (mfpvr() >> 16) {
+ /*
+ * PowerPC 970 CPUs have a misfeature requested by Apple that
+ * makes them pretend they have a 32-byte cacheline. Turn this
+ * off before we measure the cacheline size.
+ */
case IBM970:
case IBM970FX:
case IBM970MP:
@@ -353,6 +353,12 @@ powerpc_init(vm_offset_t startkernel, vm_offset_t endkernel,
scratch &= ~HID5_970_DCBZ_SIZE_HI;
mtspr(SPR_HID5, scratch);
break;
+ #ifdef __powerpc64__
+ case IBMPOWER7:
+ /* XXX: get from ibm,slb-size in device tree */
+ n_slbs = 32;
+ break;
+ #endif
}
/*
@@ -368,7 +374,6 @@ powerpc_init(vm_offset_t startkernel, vm_offset_t endkernel,
msr = mfmsr();
mtmsr((msr & ~(PSL_IR | PSL_DR)) | PSL_RI);
- isync();
/*
* Measure the cacheline size using dcbz
@@ -503,7 +508,6 @@ powerpc_init(vm_offset_t startkernel, vm_offset_t endkernel,
* Restore MSR
*/
mtmsr(msr);
- isync();
/* Warn if cachline size was not determined */
if (cacheline_warn == 1) {
@@ -527,8 +531,7 @@ powerpc_init(vm_offset_t startkernel, vm_offset_t endkernel,
pmap_mmu_install(MMU_TYPE_OEA, BUS_PROBE_GENERIC);
pmap_bootstrap(startkernel, endkernel);
- mtmsr(mfmsr() | PSL_IR|PSL_DR|PSL_ME|PSL_RI);
- isync();
+ mtmsr(PSL_KERNSET & ~PSL_EE);
/*
* Initialize params/tunables that are derived from memsize
diff --git a/sys/powerpc/aim/mmu_oea.c b/sys/powerpc/aim/mmu_oea.c
index 30435f5..51c6f8a 100644
--- a/sys/powerpc/aim/mmu_oea.c
+++ b/sys/powerpc/aim/mmu_oea.c
@@ -584,26 +584,9 @@ moea_pte_change(struct pte *pt, struct pte *pvo_pt, vm_offset_t va)
/*
* Quick sort callout for comparing memory regions.
*/
-static int mr_cmp(const void *a, const void *b);
static int om_cmp(const void *a, const void *b);
static int
-mr_cmp(const void *a, const void *b)
-{
- const struct mem_region *regiona;
- const struct mem_region *regionb;
-
- regiona = a;
- regionb = b;
- if (regiona->mr_start < regionb->mr_start)
- return (-1);
- else if (regiona->mr_start > regionb->mr_start)
- return (1);
- else
- return (0);
-}
-
-static int
om_cmp(const void *a, const void *b)
{
const struct ofw_map *mapa;
@@ -720,7 +703,6 @@ moea_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
mem_regions(&pregions, &pregions_sz, &regions, &regions_sz);
CTR0(KTR_PMAP, "moea_bootstrap: physical memory");
- qsort(pregions, pregions_sz, sizeof(*pregions), mr_cmp);
for (i = 0; i < pregions_sz; i++) {
vm_offset_t pa;
vm_offset_t end;
@@ -749,7 +731,7 @@ moea_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
if (sizeof(phys_avail)/sizeof(phys_avail[0]) < regions_sz)
panic("moea_bootstrap: phys_avail too small");
- qsort(regions, regions_sz, sizeof(*regions), mr_cmp);
+
phys_avail_count = 0;
physsz = 0;
hwphyssz = 0;
diff --git a/sys/powerpc/aim/mmu_oea64.c b/sys/powerpc/aim/mmu_oea64.c
index c33a094..12a1201 100644
--- a/sys/powerpc/aim/mmu_oea64.c
+++ b/sys/powerpc/aim/mmu_oea64.c
@@ -162,8 +162,8 @@ __FBSDID("$FreeBSD$");
void moea64_release_vsid(uint64_t vsid);
uintptr_t moea64_get_unique_vsid(void);
-#define DISABLE_TRANS(msr) msr = mfmsr(); mtmsr(msr & ~PSL_DR); isync()
-#define ENABLE_TRANS(msr) mtmsr(msr); isync()
+#define DISABLE_TRANS(msr) msr = mfmsr(); mtmsr(msr & ~PSL_DR)
+#define ENABLE_TRANS(msr) mtmsr(msr)
#define VSID_MAKE(sr, hash) ((sr) | (((hash) & 0xfffff) << 4))
#define VSID_TO_HASH(vsid) (((vsid) >> 4) & 0xfffff)
@@ -473,26 +473,9 @@ moea64_calc_wimg(vm_offset_t pa, vm_memattr_t ma)
/*
* Quick sort callout for comparing memory regions.
*/
-static int mr_cmp(const void *a, const void *b);
static int om_cmp(const void *a, const void *b);
static int
-mr_cmp(const void *a, const void *b)
-{
- const struct mem_region *regiona;
- const struct mem_region *regionb;
-
- regiona = a;
- regionb = b;
- if (regiona->mr_start < regionb->mr_start)
- return (-1);
- else if (regiona->mr_start > regionb->mr_start)
- return (1);
- else
- return (0);
-}
-
-static int
om_cmp(const void *a, const void *b)
{
const struct ofw_map *mapa;
@@ -707,10 +690,9 @@ moea64_early_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelen
mem_regions(&pregions, &pregions_sz, &regions, &regions_sz);
CTR0(KTR_PMAP, "moea64_bootstrap: physical memory");
- qsort(pregions, pregions_sz, sizeof(*pregions), mr_cmp);
if (sizeof(phys_avail)/sizeof(phys_avail[0]) < regions_sz)
panic("moea64_bootstrap: phys_avail too small");
- qsort(regions, regions_sz, sizeof(*regions), mr_cmp);
+
phys_avail_count = 0;
physsz = 0;
hwphyssz = 0;
@@ -895,7 +877,7 @@ moea64_late_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend
* Initialize MMU and remap early physical mappings
*/
MMU_CPU_BOOTSTRAP(mmup,0);
- mtmsr(mfmsr() | PSL_DR | PSL_IR); isync();
+ mtmsr(mfmsr() | PSL_DR | PSL_IR);
pmap_bootstrapped++;
bs_remap_earlyboot();
@@ -2580,8 +2562,8 @@ moea64_sync_icache(mmu_t mmu, pmap_t pm, vm_offset_t va, vm_size_t sz)
lim = round_page(va);
len = MIN(lim - va, sz);
pvo = moea64_pvo_find_va(pm, va & ~ADDR_POFF);
- if (pvo != NULL) {
- pa = (pvo->pvo_pte.pte.pte_lo & LPTE_RPGN) |
+ if (pvo != NULL && !(pvo->pvo_pte.lpte.pte_lo & LPTE_I)) {
+ pa = (pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN) |
(va & ADDR_POFF);
moea64_syncicache(mmu, pm, va, pa, len);
}
diff --git a/sys/powerpc/aim/moea64_native.c b/sys/powerpc/aim/moea64_native.c
index bca51ab..9e5174f 100644
--- a/sys/powerpc/aim/moea64_native.c
+++ b/sys/powerpc/aim/moea64_native.c
@@ -185,8 +185,8 @@ TLBIE(uint64_t vpn) {
mtx_unlock_spin(&tlbie_mutex);
}
-#define DISABLE_TRANS(msr) msr = mfmsr(); mtmsr(msr & ~PSL_DR); isync()
-#define ENABLE_TRANS(msr) mtmsr(msr); isync()
+#define DISABLE_TRANS(msr) msr = mfmsr(); mtmsr(msr & ~PSL_DR)
+#define ENABLE_TRANS(msr) mtmsr(msr)
/*
* PTEG data.
@@ -344,7 +344,7 @@ moea64_cpu_bootstrap_native(mmu_t mmup, int ap)
* Initialize segment registers and MMU
*/
- mtmsr(mfmsr() & ~PSL_DR & ~PSL_IR); isync();
+ mtmsr(mfmsr() & ~PSL_DR & ~PSL_IR);
/*
* Install kernel SLB entries
diff --git a/sys/powerpc/aim/mp_cpudep.c b/sys/powerpc/aim/mp_cpudep.c
index 3ee22f3..d617fde 100644
--- a/sys/powerpc/aim/mp_cpudep.c
+++ b/sys/powerpc/aim/mp_cpudep.c
@@ -87,7 +87,6 @@ cpudep_ap_bootstrap(void)
msr = PSL_KERNSET & ~PSL_EE;
mtmsr(msr);
- isync();
pcpup->pc_curthread = pcpup->pc_idlethread;
pcpup->pc_curpcb = pcpup->pc_curthread->td_pcb;
@@ -344,6 +343,10 @@ cpudep_ap_setup()
break;
default:
+#ifdef __powerpc64__
+ if (!(mfmsr() & PSL_HV)) /* Rely on HV to have set things up */
+ break;
+#endif
printf("WARNING: Unknown CPU type. Cache performace may be "
"suboptimal.\n");
break;
diff --git a/sys/powerpc/aim/slb.c b/sys/powerpc/aim/slb.c
index 1fafbb4..df493b4 100644
--- a/sys/powerpc/aim/slb.c
+++ b/sys/powerpc/aim/slb.c
@@ -51,8 +51,9 @@ uintptr_t moea64_get_unique_vsid(void);
void moea64_release_vsid(uint64_t vsid);
static void slb_zone_init(void *);
-uma_zone_t slbt_zone;
-uma_zone_t slb_cache_zone;
+static uma_zone_t slbt_zone;
+static uma_zone_t slb_cache_zone;
+int n_slbs = 64;
SYSINIT(slb_zone_init, SI_SUB_KMEM, SI_ORDER_ANY, slb_zone_init, NULL);
@@ -426,16 +427,18 @@ slb_insert_kernel(uint64_t slbe, uint64_t slbv)
/* Check for an unused slot, abusing the user slot as a full flag */
if (slbcache[USER_SLB_SLOT].slbe == 0) {
- for (i = 0; i < USER_SLB_SLOT; i++) {
+ for (i = 0; i < n_slbs; i++) {
+ if (i == USER_SLB_SLOT)
+ continue;
if (!(slbcache[i].slbe & SLBE_VALID))
goto fillkernslb;
}
- if (i == USER_SLB_SLOT)
+ if (i == n_slbs)
slbcache[USER_SLB_SLOT].slbe = 1;
}
- for (i = mftb() % 64, j = 0; j < 64; j++, i = (i+1) % 64) {
+ for (i = mftb() % n_slbs, j = 0; j < n_slbs; j++, i = (i+1) % n_slbs) {
if (i == USER_SLB_SLOT)
continue;
@@ -443,9 +446,11 @@ slb_insert_kernel(uint64_t slbe, uint64_t slbv)
break;
}
- KASSERT(j < 64, ("All kernel SLB slots locked!"));
+ KASSERT(j < n_slbs, ("All kernel SLB slots locked!"));
fillkernslb:
+ KASSERT(i != USER_SLB_SLOT,
+ ("Filling user SLB slot with a kernel mapping"));
slbcache[i].slbv = slbv;
slbcache[i].slbe = slbe | (uint64_t)i;
@@ -466,11 +471,11 @@ slb_insert_user(pmap_t pm, struct slb *slb)
PMAP_LOCK_ASSERT(pm, MA_OWNED);
- if (pm->pm_slb_len < 64) {
+ if (pm->pm_slb_len < n_slbs) {
i = pm->pm_slb_len;
pm->pm_slb_len++;
} else {
- i = mftb() % 64;
+ i = mftb() % n_slbs;
}
/* Note that this replacement is atomic with respect to trap_subr */
@@ -521,8 +526,9 @@ slb_zone_init(void *dummy)
slbt_zone = uma_zcreate("SLB tree node", sizeof(struct slbtnode),
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM);
- slb_cache_zone = uma_zcreate("SLB cache", 64*sizeof(struct slb *),
- NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_VM);
+ slb_cache_zone = uma_zcreate("SLB cache",
+ (n_slbs + 1)*sizeof(struct slb *), NULL, NULL, NULL, NULL,
+ UMA_ALIGN_PTR, UMA_ZONE_VM);
if (platform_real_maxaddr() != VM_MAX_ADDRESS) {
uma_zone_set_allocf(slb_cache_zone, slb_uma_real_alloc);
diff --git a/sys/powerpc/aim/trap_subr64.S b/sys/powerpc/aim/trap_subr64.S
index 7156edb..5d4148a 100644
--- a/sys/powerpc/aim/trap_subr64.S
+++ b/sys/powerpc/aim/trap_subr64.S
@@ -53,55 +53,53 @@
* User SRs are loaded through a pointer to the current pmap.
*/
restore_usersrs:
- GET_CPUINFO(%r28);
- ld %r28,PC_USERSLB(%r28);
+ GET_CPUINFO(%r28)
+ ld %r28,PC_USERSLB(%r28)
li %r29, 0 /* Set the counter to zero */
slbia
slbmfee %r31,%r29
clrrdi %r31,%r31,28
slbie %r31
-instuserslb:
- ld %r31, 0(%r28); /* Load SLB entry pointer */
- cmpli 0, %r31, 0; /* If NULL, stop */
- beqlr;
+1: ld %r31, 0(%r28) /* Load SLB entry pointer */
+ cmpli 0, %r31, 0 /* If NULL, stop */
+ beqlr
ld %r30, 0(%r31) /* Load SLBV */
ld %r31, 8(%r31) /* Load SLBE */
or %r31, %r31, %r29 /* Set SLBE slot */
- slbmte %r30, %r31; /* Install SLB entry */
+ slbmte %r30, %r31 /* Install SLB entry */
- addi %r28, %r28, 8; /* Advance pointer */
- addi %r29, %r29, 1;
- cmpli 0, %r29, 64; /* Repeat if we are not at the end */
- blt instuserslb;
- blr;
+ addi %r28, %r28, 8 /* Advance pointer */
+ addi %r29, %r29, 1
+ b 1b /* Repeat */
/*
* Kernel SRs are loaded directly from the PCPU fields
*/
restore_kernsrs:
- GET_CPUINFO(%r28);
- addi %r28,%r28,PC_KERNSLB;
+ GET_CPUINFO(%r28)
+ addi %r28,%r28,PC_KERNSLB
li %r29, 0 /* Set the counter to zero */
slbia
slbmfee %r31,%r29
clrrdi %r31,%r31,28
slbie %r31
-instkernslb:
- ld %r31, 8(%r28); /* Load SLBE */
+1: cmpli 0, %r29, USER_SLB_SLOT /* Skip the user slot */
+ beq- 2f
- cmpli 0, %r31, 0; /* If SLBE is not valid, stop */
- beqlr;
+ ld %r31, 8(%r28) /* Load SLBE */
+ cmpli 0, %r31, 0 /* If SLBE is not valid, stop */
+ beqlr
ld %r30, 0(%r28) /* Load SLBV */
- slbmte %r30, %r31; /* Install SLB entry */
+ slbmte %r30, %r31 /* Install SLB entry */
- addi %r28, %r28, 16; /* Advance pointer */
- addi %r29, %r29, 1;
- cmpli 0, %r29, USER_SLB_SLOT; /* Repeat if we are not at the end */
- blt instkernslb;
- blr;
+2: addi %r28, %r28, 16 /* Advance pointer */
+ addi %r29, %r29, 1
+ cmpli 0, %r29, 64 /* Repeat if we are not at the end */
+ blt 1b
+ blr
/*
* FRAME_SETUP assumes:
diff --git a/sys/powerpc/booke/pmap.c b/sys/powerpc/booke/pmap.c
index aff7901..cabe58f 100644
--- a/sys/powerpc/booke/pmap.c
+++ b/sys/powerpc/booke/pmap.c
@@ -390,7 +390,7 @@ tlb_miss_lock(void)
if (!smp_started)
return;
- SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
+ STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
if (pc != pcpup) {
CTR3(KTR_PMAP, "%s: tlb miss LOCK of CPU=%d, "
@@ -416,7 +416,7 @@ tlb_miss_unlock(void)
if (!smp_started)
return;
- SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
+ STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
if (pc != pcpup) {
CTR2(KTR_PMAP, "%s: tlb miss UNLOCK of CPU=%d",
__func__, pc->pc_cpuid);
diff --git a/sys/powerpc/conf/GENERIC b/sys/powerpc/conf/GENERIC
index d221a97..54d4639 100644
--- a/sys/powerpc/conf/GENERIC
+++ b/sys/powerpc/conf/GENERIC
@@ -174,11 +174,13 @@ device sbp # SCSI over FireWire (Requires scbus and da)
device fwe # Ethernet over FireWire (non-standard!)
# Misc
+device ad7417 # PowerMac7,2 temperature sensor
device ds1775 # PowerMac7,2 temperature sensor
device fcu # Apple Fan Control Unit
device max6690 # PowerMac7,2 temperature sensor
device powermac_nvram # Open Firmware configuration NVRAM
device smu # Apple System Management Unit
+device windtunnel # Apple G4 MDD fan controller
# ADB support
device adb
diff --git a/sys/powerpc/conf/GENERIC64 b/sys/powerpc/conf/GENERIC64
index d7526b3..ab4a0dc 100644
--- a/sys/powerpc/conf/GENERIC64
+++ b/sys/powerpc/conf/GENERIC64
@@ -175,6 +175,7 @@ device sbp # SCSI over FireWire (Requires scbus and da)
device fwe # Ethernet over FireWire (non-standard!)
# Misc
+device ad7417 # PowerMac7,2 temperature sensor
device ds1775 # PowerMac7,2 temperature sensor
device fcu # Apple Fan Control Unit
device max6690 # PowerMac7,2 temperature sensor
diff --git a/sys/powerpc/conf/NOTES b/sys/powerpc/conf/NOTES
index b80a817..0045763 100644
--- a/sys/powerpc/conf/NOTES
+++ b/sys/powerpc/conf/NOTES
@@ -39,6 +39,7 @@ device kiic # Apple Keywest I2C Controller
device ofwd # Open Firmware disks
device adb # Apple Desktop Bus
device cuda # VIA-CUDA ADB interface
+device ad7417 # PowerMac7,2 temperature sensor
device ds1775 # PowerMac7,2 temperature sensor
device fcu # Apple Fan Control Unit
device max6690 # PowerMac7,2 temperature sensor
@@ -46,6 +47,7 @@ device pmu # Apple Power Management Unit
device smu # Apple System Management Unit
device snd_ai2s # Apple I2S Audio
device snd_davbus # Apple Davbus Audio
+device windtunnel # Apple G4 MDD fan controller
#####################################################################
diff --git a/sys/powerpc/include/rtas.h b/sys/powerpc/include/rtas.h
new file mode 100644
index 0000000..5b18632
--- /dev/null
+++ b/sys/powerpc/include/rtas.h
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c) 2011 Nathan Whitehorn
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _MACHINE_RTAS_H_
+#define _MACHINE_RTAS_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <dev/ofw/openfirm.h>
+
+/*
+ * RTAS functions are defined by 32-bit integer tokens. These vary from
+ * system to system, and can be looked up from their standardized names
+ * using rtas_token_lookup(). If RTAS is not available, rtas_token_lookup()
+ * and rtas_call_method() return -1; this can be checked in advance using
+ * rtas_exists(). Otherwise, rtas_call_method() returns one of the RTAS
+ * status codes from the bottom of this file.
+ */
+
+int rtas_exists(void);
+int rtas_call_method(cell_t token, int nargs, int nreturns, ...);
+cell_t rtas_token_lookup(const char *method);
+
+/* RTAS Status Codes: see CHRP or PAPR specification */
+#define RTAS_OK 0
+#define RTAS_HW_ERROR -1
+#define RTAS_BUSY -2
+#define RTAS_PARAM_ERROR -3
+#define RTAS_STATE_CHANGE -7
+#define RTAS_VENDOR_BEGIN 9000
+#define RTAS_EXTENDED_DELAY 9900
+#define RTAS_ISOLATION_ERROR -9000
+#define RTAS_VENDOR_ERROR_BEGIN -9004
+
+#endif /* _MACHINE_RTAS_H_ */
+
diff --git a/sys/powerpc/include/slb.h b/sys/powerpc/include/slb.h
index f675e15..637110c 100644
--- a/sys/powerpc/include/slb.h
+++ b/sys/powerpc/include/slb.h
@@ -65,7 +65,7 @@
/*
* User segment for copyin/out
*/
-#define USER_SLB_SLOT 63
+#define USER_SLB_SLOT 0
#define USER_SLB_SLBE (((USER_ADDR >> ADDR_SR_SHFT) << SLBE_ESID_SHIFT) | \
SLBE_VALID | USER_SLB_SLOT)
diff --git a/sys/powerpc/ofw/ofw_machdep.c b/sys/powerpc/ofw/ofw_machdep.c
index 9af4051..fcdc953 100644
--- a/sys/powerpc/ofw/ofw_machdep.c
+++ b/sys/powerpc/ofw/ofw_machdep.c
@@ -60,17 +60,15 @@ __FBSDID("$FreeBSD$");
#include <machine/platform.h>
#include <machine/ofw_machdep.h>
-#define OFMEM_REGIONS 32
-static struct mem_region OFmem[OFMEM_REGIONS + 1], OFavail[OFMEM_REGIONS + 3];
-static struct mem_region OFfree[OFMEM_REGIONS + 3];
-static int nOFmem;
+static struct mem_region OFmem[PHYS_AVAIL_SZ], OFavail[PHYS_AVAIL_SZ];
+static struct mem_region OFfree[PHYS_AVAIL_SZ];
extern register_t ofmsr[5];
-static int (*ofwcall)(void *);
+extern void *openfirmware_entry;
static void *fdt;
int ofw_real_mode;
-int ofw_32bit_mode_entry(void *);
+int ofwcall(void *);
static void ofw_quiesce(void);
static int openfirmware(void *args);
@@ -134,11 +132,32 @@ memr_merge(struct mem_region *from, struct mem_region *to)
to->mr_size = end - to->mr_start;
}
+/*
+ * Quick sort callout for comparing memory regions.
+ */
+static int mr_cmp(const void *a, const void *b);
+
+static int
+mr_cmp(const void *a, const void *b)
+{
+ const struct mem_region *regiona;
+ const struct mem_region *regionb;
+
+ regiona = a;
+ regionb = b;
+ if (regiona->mr_start < regionb->mr_start)
+ return (-1);
+ else if (regiona->mr_start > regionb->mr_start)
+ return (1);
+ else
+ return (0);
+}
+
static int
parse_ofw_memory(phandle_t node, const char *prop, struct mem_region *output)
{
cell_t address_cells, size_cells;
- cell_t OFmem[4*(OFMEM_REGIONS + 1)];
+ cell_t OFmem[4 * PHYS_AVAIL_SZ];
int sz, i, j;
int apple_hack_mode;
phandle_t phandle;
@@ -174,8 +193,8 @@ parse_ofw_memory(phandle_t node, const char *prop, struct mem_region *output)
/*
* Get memory.
*/
- if ((node == -1) || (sz = OF_getprop(node, prop,
- OFmem, sizeof(OFmem[0]) * 4 * OFMEM_REGIONS)) <= 0)
+ if (node == -1 || (sz = OF_getprop(node, prop,
+ OFmem, sizeof(OFmem))) <= 0)
panic("Physical memory map not found");
i = 0;
@@ -225,7 +244,7 @@ parse_ofw_memory(phandle_t node, const char *prop, struct mem_region *output)
#ifdef __powerpc64__
if (apple_hack_mode) {
/* Add in regions above 4 GB to the available list */
- struct mem_region himem[OFMEM_REGIONS];
+ struct mem_region himem[16];
int hisz;
hisz = parse_ofw_memory(node, "reg", himem);
@@ -243,6 +262,81 @@ parse_ofw_memory(phandle_t node, const char *prop, struct mem_region *output)
return (sz);
}
+static int
+parse_drconf_memory(int *msz, int *asz, struct mem_region *ofmem,
+ struct mem_region *ofavail)
+{
+ phandle_t phandle;
+ vm_offset_t base;
+ int i, idx, len, lasz, lmsz, res;
+ uint32_t lmb_size[2];
+ unsigned long *dmem, flags;
+
+ lmsz = *msz;
+ lasz = *asz;
+
+ phandle = OF_finddevice("/ibm,dynamic-reconfiguration-memory");
+ if (phandle == -1)
+ /* No drconf node, return. */
+ return (0);
+
+ res = OF_getprop(phandle, "ibm,lmb-size", lmb_size, sizeof(lmb_size));
+ if (res == -1)
+ return (0);
+
+ /* Parse the /ibm,dynamic-memory.
+ The first position gives the # of entries. The next two words
+ reflect the address of the memory block. The next four words are
+ the DRC index, reserved, list index and flags.
+ (see PAPR C.6.6.2 ibm,dynamic-reconfiguration-memory)
+
+ #el Addr DRC-idx res list-idx flags
+ -------------------------------------------------
+ | 4 | 8 | 4 | 4 | 4 | 4 |....
+ -------------------------------------------------
+ */
+
+ len = OF_getproplen(phandle, "ibm,dynamic-memory");
+ if (len > 0) {
+
+ /* We have to use a variable length array on the stack
+ since we have very limited stack space.
+ */
+ cell_t arr[len/sizeof(cell_t)];
+
+ res = OF_getprop(phandle, "ibm,dynamic-memory", &arr,
+ sizeof(arr));
+ if (res == -1)
+ return (0);
+
+ /* Number of elements */
+ idx = arr[0];
+
+ /* First address. */
+ dmem = (void*)&arr[1];
+
+ for (i = 0; i < idx; i++) {
+ base = *dmem;
+ dmem += 2;
+ flags = *dmem;
+ /* Use region only if available and not reserved. */
+ if ((flags & 0x8) && !(flags & 0x80)) {
+ ofmem[lmsz].mr_start = base;
+ ofmem[lmsz].mr_size = (vm_size_t)lmb_size[1];
+ ofavail[lasz].mr_start = base;
+ ofavail[lasz].mr_size = (vm_size_t)lmb_size[1];
+ lmsz++;
+ lasz++;
+ }
+ dmem++;
+ }
+ }
+
+ *msz = lmsz;
+ *asz = lasz;
+
+ return (1);
+}
/*
* This is called during powerpc_init, before the system is really initialized.
* It shall provide the total and the available regions of RAM.
@@ -255,31 +349,62 @@ ofw_mem_regions(struct mem_region **memp, int *memsz,
struct mem_region **availp, int *availsz)
{
phandle_t phandle;
+ vm_offset_t maxphysaddr;
int asz, msz, fsz;
- int i, j;
+ int i, j, res;
int still_merging;
+ char name[31];
asz = msz = 0;
/*
- * Get memory.
+ * Get memory from all the /memory nodes.
*/
- phandle = OF_finddevice("/memory");
- if (phandle == -1)
- phandle = OF_finddevice("/memory@0");
+ for (phandle = OF_child(OF_peer(0)); phandle != 0;
+ phandle = OF_peer(phandle)) {
+ if (OF_getprop(phandle, "name", name, sizeof(name)) <= 0)
+ continue;
+ if (strncmp(name, "memory", sizeof(name)) != 0)
+ continue;
+
+ res = parse_ofw_memory(phandle, "reg", &OFmem[msz]);
+ msz += res/sizeof(struct mem_region);
+ if (OF_getproplen(phandle, "available") >= 0)
+ res = parse_ofw_memory(phandle, "available",
+ &OFavail[asz]);
+ else
+ res = parse_ofw_memory(phandle, "reg", &OFavail[asz]);
+ asz += res/sizeof(struct mem_region);
+ }
+
+ /* Check for memory in ibm,dynamic-reconfiguration-memory */
+ parse_drconf_memory(&msz, &asz, OFmem, OFavail);
- msz = parse_ofw_memory(phandle, "reg", OFmem);
- nOFmem = msz / sizeof(struct mem_region);
- asz = parse_ofw_memory(phandle, "available", OFavail);
+ qsort(OFmem, msz, sizeof(*OFmem), mr_cmp);
+ qsort(OFavail, asz, sizeof(*OFavail), mr_cmp);
*memp = OFmem;
- *memsz = nOFmem;
-
+ *memsz = msz;
+
+ /*
+ * On some firmwares (SLOF), some memory may be marked available that
+ * doesn't actually exist. This manifests as an extension of the last
+ * available segment past the end of physical memory, so truncate that
+ * one.
+ */
+ maxphysaddr = 0;
+ for (i = 0; i < msz; i++)
+ if (OFmem[i].mr_start + OFmem[i].mr_size > maxphysaddr)
+ maxphysaddr = OFmem[i].mr_start + OFmem[i].mr_size;
+
+ if (OFavail[asz - 1].mr_start + OFavail[asz - 1].mr_size > maxphysaddr)
+ OFavail[asz - 1].mr_size = maxphysaddr -
+ OFavail[asz - 1].mr_start;
+
/*
* OFavail may have overlapping regions - collapse these
* and copy out remaining regions to OFfree
*/
- asz /= sizeof(struct mem_region);
do {
still_merging = FALSE;
for (i = 0; i < asz; i++) {
@@ -318,19 +443,6 @@ OF_initial_setup(void *fdt_ptr, void *junk, int (*openfirm)(void *))
else
ofw_real_mode = 1;
- ofwcall = NULL;
-
- #ifdef __powerpc64__
- /*
- * For PPC64, we need to use some hand-written
- * asm trampolines to get to OF.
- */
- if (openfirm != NULL)
- ofwcall = ofw_32bit_mode_entry;
- #else
- ofwcall = openfirm;
- #endif
-
fdt = fdt_ptr;
#ifdef FDT_DTB_STATIC
@@ -345,7 +457,7 @@ OF_bootstrap()
{
boolean_t status = FALSE;
- if (ofwcall != NULL) {
+ if (openfirmware_entry != NULL) {
if (ofw_real_mode) {
status = OF_install(OFW_STD_REAL, 0);
} else {
@@ -481,12 +593,7 @@ openfirmware(void *args)
int result;
#ifdef SMP
struct ofw_rv_args rv_args;
- #endif
-
- if (pmap_bootstrapped && ofw_real_mode)
- args = (void *)pmap_kextract((vm_offset_t)args);
- #ifdef SMP
rv_args.args = args;
rv_args.in_progress = 1;
smp_rendezvous(smp_no_rendevous_barrier, ofw_rendezvous_dispatch,
diff --git a/sys/powerpc/ofw/ofw_real.c b/sys/powerpc/ofw/ofw_real.c
index 617f9be..1fc2ed1 100644
--- a/sys/powerpc/ofw/ofw_real.c
+++ b/sys/powerpc/ofw/ofw_real.c
@@ -205,13 +205,14 @@ ofw_real_bounce_alloc(void *junk)
/*
* Allocate a page of contiguous, wired physical memory that can
- * fit into a 32-bit address space.
+ * fit into a 32-bit address space and accessed from real mode.
*/
mtx_lock(&of_bounce_mtx);
- of_bounce_virt = contigmalloc(PAGE_SIZE, M_OFWREAL, 0,
- 0, BUS_SPACE_MAXADDR_32BIT, PAGE_SIZE, PAGE_SIZE);
+ of_bounce_virt = contigmalloc(PAGE_SIZE, M_OFWREAL, 0, 0,
+ ulmin(platform_real_maxaddr(), BUS_SPACE_MAXADDR_32BIT), PAGE_SIZE,
+ PAGE_SIZE);
of_bounce_phys = vtophys(of_bounce_virt);
of_bounce_size = PAGE_SIZE;
diff --git a/sys/powerpc/ofw/ofwcall32.S b/sys/powerpc/ofw/ofwcall32.S
new file mode 100644
index 0000000..06cc105
--- /dev/null
+++ b/sys/powerpc/ofw/ofwcall32.S
@@ -0,0 +1,154 @@
+/*-
+ * Copyright (C) 2009-2011 Nathan Whitehorn
+ * 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 TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/syscall.h>
+
+#include <machine/trap.h>
+#include <machine/param.h>
+#include <machine/spr.h>
+#include <machine/asm.h>
+
+#define OFWSTKSZ 4096 /* 4K Open Firmware stack */
+
+/*
+ * Globals
+ */
+ .data
+GLOBAL(ofmsr)
+ .long 0, 0, 0, 0, 0 /* msr/sprg0-3 used in Open Firmware */
+GLOBAL(rtasmsr)
+ .long 0
+GLOBAL(openfirmware_entry)
+ .long 0 /* Open Firmware entry point */
+GLOBAL(rtas_entry)
+ .long 0 /* RTAS entry point */
+
+ .align 4
+ofwstk:
+ .space OFWSTKSZ
+rtas_regsave:
+ .space 4
+
+/*
+ * Open Firmware Entry Point. May need to enter real mode.
+ *
+ * C prototype: int ofwcall(void *callbuffer);
+ */
+
+ASENTRY(ofwcall)
+ mflr %r0
+ stw %r0,4(%r1)
+
+ /* Record the old MSR */
+ mfmsr %r6
+
+ /* read client interface handler */
+ lis %r4,openfirmware_entry@ha
+ lwz %r4,openfirmware_entry@l(%r4)
+
+ /*
+ * Set the MSR to the OF value. This has the side effect of disabling
+ * exceptions, which prevents preemption later.
+ */
+
+ lis %r5,ofmsr@ha
+ lwz %r5,ofmsr@l(%r5)
+ mtmsr %r5
+ isync
+
+ /*
+ * Set up OF stack. This needs to be potentially accessible in real mode
+ * The pointer to the current kernel stack is placed at the very
+ * top of the stack along with the old MSR so we can get them back
+ * later.
+ */
+ mr %r5,%r1
+ lis %r1,(ofwstk+OFWSTKSZ-16)@ha
+ addi %r1,%r1,(ofwstk+OFWSTKSZ-16)@l
+ stw %r5,8(%r1) /* Save real stack pointer */
+ stw %r6,12(%r1) /* Save old MSR */
+ li %r5,0
+ stw %r5,4(%r1)
+ stw %r5,0(%r1)
+
+ /* Finally, branch to OF */
+ mtctr %r4
+ bctrl
+
+ /* Reload stack pointer and MSR from the OFW stack */
+ lwz %r6,12(%r1)
+ lwz %r1,8(%r1)
+
+ /* Now set the real MSR */
+ mtmsr %r6
+ isync
+
+ /* Return */
+ lwz %r0,4(%r1)
+ mtlr %r0
+ blr
+
+/*
+ * RTAS Entry Point. Similar to the OF one, but simpler (no separate stack)
+ *
+ * C prototype: int rtascall(void *callbuffer, void *rtas_privdat);
+ */
+
+ASENTRY(rtascall)
+ mflr %r0
+ stw %r0,4(%r1)
+
+ /* Record the old MSR to real-mode-accessible area */
+ mfmsr %r0
+ lis %r5,rtas_regsave@ha
+ stw %r0,rtas_regsave@l(%r5)
+
+ /* read client interface handler */
+ lis %r5,rtas_entry@ha
+ lwz %r5,rtas_entry@l(%r5)
+
+ /* Set the MSR to the RTAS value */
+ lis %r6,rtasmsr@ha
+ lwz %r6,rtasmsr@l(%r6)
+ mtmsr %r6
+ isync
+
+ /* Branch to RTAS */
+ mtctr %r5
+ bctrl
+
+ /* Now set the MSR back */
+ lis %r6,rtas_regsave@ha
+ lwz %r6,rtas_regsave@l(%r6)
+ mtmsr %r6
+ isync
+
+ /* And return */
+ lwz %r0,4(%r1)
+ mtlr %r0
+ blr
+
diff --git a/sys/powerpc/ofw/ofwcall64.S b/sys/powerpc/ofw/ofwcall64.S
new file mode 100644
index 0000000..1fb78e8
--- /dev/null
+++ b/sys/powerpc/ofw/ofwcall64.S
@@ -0,0 +1,290 @@
+/*-
+ * Copyright (C) 2009-2011 Nathan Whitehorn
+ * 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 TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/syscall.h>
+
+#include <machine/trap.h>
+#include <machine/param.h>
+#include <machine/spr.h>
+#include <machine/asm.h>
+
+#define OFWSTKSZ 4096 /* 4K Open Firmware stack */
+
+/*
+ * Globals
+ */
+ .data
+ .align 4
+ofwstk:
+ .space OFWSTKSZ
+rtas_regsave:
+ .space 24 /* 3 * sizeof(register_t) */
+GLOBAL(ofmsr)
+ .llong 0, 0, 0, 0, 0 /* msr/sprg0-3 used in Open Firmware */
+GLOBAL(rtasmsr)
+ .llong 0
+GLOBAL(openfirmware_entry)
+ .llong 0 /* Open Firmware entry point */
+GLOBAL(rtas_entry)
+ .llong 0 /* RTAS entry point */
+
+/*
+ * Open Firmware Real-mode Entry Point. This is a huge pain.
+ */
+
+ASENTRY(ofwcall)
+ mflr %r0
+ std %r0,16(%r1)
+ stdu %r1,-208(%r1)
+
+ /*
+ * We need to save the following, because OF's register save/
+ * restore code assumes that the contents of registers are
+ * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These
+ * get placed in that order in the stack.
+ */
+
+ mfcr %r4
+ std %r4,48(%r1)
+ std %r13,56(%r1)
+ std %r14,64(%r1)
+ std %r15,72(%r1)
+ std %r16,80(%r1)
+ std %r17,88(%r1)
+ std %r18,96(%r1)
+ std %r19,104(%r1)
+ std %r20,112(%r1)
+ std %r21,120(%r1)
+ std %r22,128(%r1)
+ std %r23,136(%r1)
+ std %r24,144(%r1)
+ std %r25,152(%r1)
+ std %r26,160(%r1)
+ std %r27,168(%r1)
+ std %r28,176(%r1)
+ std %r29,184(%r1)
+ std %r30,192(%r1)
+ std %r31,200(%r1)
+
+ /* Record the old MSR */
+ mfmsr %r6
+
+ /* read client interface handler */
+ lis %r4,openfirmware_entry@ha
+ ld %r4,openfirmware_entry@l(%r4)
+
+ /*
+ * Set the MSR to the OF value. This has the side effect of disabling
+ * exceptions, which is important for the next few steps.
+ */
+
+ lis %r5,ofmsr@ha
+ ld %r5,ofmsr@l(%r5)
+ mtmsrd %r5
+ isync
+
+ /*
+ * Set up OF stack. This needs to be accessible in real mode and
+ * use the 32-bit ABI stack frame format. The pointer to the current
+ * kernel stack is placed at the very top of the stack along with
+ * the old MSR so we can get them back later.
+ */
+ mr %r5,%r1
+ lis %r1,(ofwstk+OFWSTKSZ-32)@ha
+ addi %r1,%r1,(ofwstk+OFWSTKSZ-32)@l
+ std %r5,8(%r1) /* Save real stack pointer */
+ std %r2,16(%r1) /* Save old TOC */
+ std %r6,24(%r1) /* Save old MSR */
+ li %r5,0
+ stw %r5,4(%r1)
+ stw %r5,0(%r1)
+
+ /* Finally, branch to OF */
+ mtctr %r4
+ bctrl
+
+ /* Reload stack pointer and MSR from the OFW stack */
+ ld %r6,24(%r1)
+ ld %r2,16(%r1)
+ ld %r1,8(%r1)
+
+ /* Now set the real MSR */
+ mtmsrd %r6
+ isync
+
+ /* Sign-extend the return value from OF */
+ extsw %r3,%r3
+
+ /* Restore all the non-volatile registers */
+ ld %r5,48(%r1)
+ mtcr %r5
+ ld %r13,56(%r1)
+ ld %r14,64(%r1)
+ ld %r15,72(%r1)
+ ld %r16,80(%r1)
+ ld %r17,88(%r1)
+ ld %r18,96(%r1)
+ ld %r19,104(%r1)
+ ld %r20,112(%r1)
+ ld %r21,120(%r1)
+ ld %r22,128(%r1)
+ ld %r23,136(%r1)
+ ld %r24,144(%r1)
+ ld %r25,152(%r1)
+ ld %r26,160(%r1)
+ ld %r27,168(%r1)
+ ld %r28,176(%r1)
+ ld %r29,184(%r1)
+ ld %r30,192(%r1)
+ ld %r31,200(%r1)
+
+ /* Restore the stack and link register */
+ ld %r1,0(%r1)
+ ld %r0,16(%r1)
+ mtlr %r0
+ blr
+
+/*
+ * RTAS 32-bit Entry Point. Similar to the OF one, but simpler (no separate
+ * stack)
+ *
+ * C prototype: int rtascall(void *callbuffer, void *rtas_privdat);
+ */
+
+ASENTRY(rtascall)
+ mflr %r0
+ std %r0,16(%r1)
+ stdu %r1,-208(%r1)
+
+ /*
+ * We need to save the following, because RTAS's register save/
+ * restore code assumes that the contents of registers are
+ * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These
+ * get placed in that order in the stack.
+ */
+
+ mfcr %r5
+ std %r5,48(%r1)
+ std %r13,56(%r1)
+ std %r14,64(%r1)
+ std %r15,72(%r1)
+ std %r16,80(%r1)
+ std %r17,88(%r1)
+ std %r18,96(%r1)
+ std %r19,104(%r1)
+ std %r20,112(%r1)
+ std %r21,120(%r1)
+ std %r22,128(%r1)
+ std %r23,136(%r1)
+ std %r24,144(%r1)
+ std %r25,152(%r1)
+ std %r26,160(%r1)
+ std %r27,168(%r1)
+ std %r28,176(%r1)
+ std %r29,184(%r1)
+ std %r30,192(%r1)
+ std %r31,200(%r1)
+
+ /* Record the old MSR */
+ mfmsr %r6
+
+ /* read client interface handler */
+ lis %r5,rtas_entry@ha
+ ld %r5,rtas_entry@l(%r5)
+
+ /*
+ * Set the MSR to the RTAS value. This has the side effect of disabling
+ * exceptions, which is important for the next few steps.
+ */
+
+ lis %r7,rtasmsr@ha
+ ld %r7,rtasmsr@l(%r7)
+ mtmsrd %r7
+ isync
+
+ /*
+ * Set up RTAS register save area, so that we can get back all of
+ * our 64-bit pointers. Save our stack pointer, the TOC, and the MSR.
+ * Put this in r1, since RTAS is obliged to save it. Kernel globals
+ * are below 4 GB, so this is safe.
+ */
+ mr %r7,%r1
+ lis %r1,rtas_regsave@ha
+ addi %r1,%r1,rtas_regsave@l
+ std %r7,0(%r1) /* Save 64-bit stack pointer */
+ std %r2,8(%r1) /* Save TOC */
+ std %r6,16(%r1) /* Save MSR */
+
+ /* Finally, branch to RTAS */
+ mtctr %r5
+ bctrl
+
+ /*
+ * Reload stack pointer and MSR from the reg save area in r1. We are
+ * running in 32-bit mode at this point, so it doesn't matter if r1
+ * has become sign-extended.
+ */
+ ld %r6,16(%r1)
+ ld %r2,8(%r1)
+ ld %r1,0(%r1)
+
+ /* Now set the real MSR */
+ mtmsrd %r6
+ isync
+
+ /* Sign-extend the return value from RTAS */
+ extsw %r3,%r3
+
+ /* Restore all the non-volatile registers */
+ ld %r5,48(%r1)
+ mtcr %r5
+ ld %r13,56(%r1)
+ ld %r14,64(%r1)
+ ld %r15,72(%r1)
+ ld %r16,80(%r1)
+ ld %r17,88(%r1)
+ ld %r18,96(%r1)
+ ld %r19,104(%r1)
+ ld %r20,112(%r1)
+ ld %r21,120(%r1)
+ ld %r22,128(%r1)
+ ld %r23,136(%r1)
+ ld %r24,144(%r1)
+ ld %r25,152(%r1)
+ ld %r26,160(%r1)
+ ld %r27,168(%r1)
+ ld %r28,176(%r1)
+ ld %r29,184(%r1)
+ ld %r30,192(%r1)
+ ld %r31,200(%r1)
+
+ /* Restore the stack and link register */
+ ld %r1,0(%r1)
+ ld %r0,16(%r1)
+ mtlr %r0
+ blr
+
diff --git a/sys/powerpc/aim/ofwmagic.S b/sys/powerpc/ofw/ofwmagic.S
index f44f1e5..f44f1e5 100644
--- a/sys/powerpc/aim/ofwmagic.S
+++ b/sys/powerpc/ofw/ofwmagic.S
diff --git a/sys/powerpc/ofw/rtas.c b/sys/powerpc/ofw/rtas.c
new file mode 100644
index 0000000..59692c9
--- /dev/null
+++ b/sys/powerpc/ofw/rtas.c
@@ -0,0 +1,243 @@
+/*-
+ * Copyright (c) 2011 Nathan Whitehorn
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/systm.h>
+
+#include <vm/vm.h>
+#include <vm/vm_page.h>
+#include <vm/pmap.h>
+
+#include <machine/bus.h>
+#include <machine/md_var.h>
+#include <machine/pmap.h>
+#include <machine/rtas.h>
+#include <machine/stdarg.h>
+
+#include <dev/ofw/openfirm.h>
+
+MALLOC_DEFINE(M_RTAS, "rtas", "Run Time Abstraction Service");
+
+static vm_offset_t rtas_bounce_phys;
+static caddr_t rtas_bounce_virt;
+static off_t rtas_bounce_offset;
+static size_t rtas_bounce_size;
+static uintptr_t rtas_private_data;
+static struct mtx rtas_mtx;
+static phandle_t rtas;
+
+/* From ofwcall.S */
+int rtascall(vm_offset_t callbuffer, uintptr_t rtas_privdat);
+extern uintptr_t rtas_entry;
+extern register_t rtasmsr;
+
+/*
+ * After the VM is up, allocate RTAS memory and instantiate it
+ */
+
+static void rtas_setup(void *);
+
+SYSINIT(rtas_setup, SI_SUB_KMEM, SI_ORDER_ANY, rtas_setup, NULL);
+
+static void
+rtas_setup(void *junk)
+{
+ ihandle_t rtasi;
+ cell_t rtas_size = 0, rtas_ptr;
+ char path[31];
+ int result;
+
+ rtas = OF_finddevice("/rtas");
+ if (rtas == -1) {
+ rtas = 0;
+ return;
+ }
+ OF_package_to_path(rtas, path, sizeof(path));
+ rtasi = OF_open(path);
+ if (rtasi == 0) {
+ rtas = 0;
+ printf("Error initializing RTAS: could not open node\n");
+ return;
+ }
+
+ mtx_init(&rtas_mtx, "RTAS", MTX_DEF, 0);
+
+ /* RTAS must be called with everything turned off in MSR */
+ rtasmsr = mfmsr();
+ rtasmsr &= ~(PSL_IR | PSL_DR | PSL_EE | PSL_SE);
+ #ifdef __powerpc64__
+ rtasmsr &= ~PSL_SF;
+ #endif
+
+ /*
+ * Allocate rtas_size + one page of contiguous, wired physical memory
+ * that can fit into a 32-bit address space and accessed from real mode.
+ * This is used both to bounce arguments and for RTAS private data.
+ *
+ * It must be 4KB-aligned and not cross a 256 MB boundary.
+ */
+
+ OF_getprop(rtas, "rtas-size", &rtas_size, sizeof(rtas_size));
+ rtas_size = round_page(rtas_size);
+ rtas_bounce_virt = contigmalloc(rtas_size + PAGE_SIZE, M_RTAS, 0, 0,
+ ulmin(platform_real_maxaddr(), BUS_SPACE_MAXADDR_32BIT),
+ 4096, 256*1024*1024);
+
+ rtas_private_data = vtophys(rtas_bounce_virt);
+ rtas_bounce_virt += rtas_size; /* Actual bounce area */
+ rtas_bounce_phys = vtophys(rtas_bounce_virt);
+ rtas_bounce_size = PAGE_SIZE;
+
+ /*
+ * Instantiate RTAS. We always use the 32-bit version.
+ */
+
+ result = OF_call_method("instantiate-rtas", rtasi, 1, 1,
+ (cell_t)rtas_private_data, &rtas_ptr);
+ OF_close(rtasi);
+
+ if (result != 0) {
+ rtas = 0;
+ rtas_ptr = 0;
+ printf("Error initializing RTAS (%d)\n", result);
+ return;
+ }
+
+ rtas_entry = (uintptr_t)(rtas_ptr);
+}
+
+static cell_t
+rtas_real_map(const void *buf, size_t len)
+{
+ cell_t phys;
+
+ mtx_assert(&rtas_mtx, MA_OWNED);
+
+ /*
+ * Make sure the bounce page offset satisfies any reasonable
+ * alignment constraint.
+ */
+ rtas_bounce_offset += sizeof(register_t) -
+ (rtas_bounce_offset % sizeof(register_t));
+
+ if (rtas_bounce_offset + len > rtas_bounce_size) {
+ panic("Oversize RTAS call!");
+ return 0;
+ }
+
+ if (buf != NULL)
+ memcpy(rtas_bounce_virt + rtas_bounce_offset, buf, len);
+ else
+ return (0);
+
+ phys = rtas_bounce_phys + rtas_bounce_offset;
+ rtas_bounce_offset += len;
+
+ return (phys);
+}
+
+static void
+rtas_real_unmap(cell_t physaddr, void *buf, size_t len)
+{
+ mtx_assert(&rtas_mtx, MA_OWNED);
+
+ if (physaddr == 0)
+ return;
+
+ memcpy(buf, rtas_bounce_virt + (physaddr - rtas_bounce_phys), len);
+}
+
+/* Check if we have RTAS */
+int
+rtas_exists(void)
+{
+ return (rtas != 0);
+}
+
+/* Call an RTAS method by token */
+int
+rtas_call_method(cell_t token, int nargs, int nreturns, ...)
+{
+ vm_offset_t argsptr;
+ va_list ap;
+ struct {
+ cell_t token;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t args_n_results[12];
+ } args;
+ int n, result;
+
+ if (!rtas_exists() || nargs + nreturns > 12)
+ return (-1);
+
+ args.token = token;
+ va_start(ap, nreturns);
+
+ mtx_lock(&rtas_mtx);
+ rtas_bounce_offset = 0;
+
+ args.nargs = nargs;
+ args.nreturns = nreturns;
+
+ for (n = 0; n < nargs; n++)
+ args.args_n_results[n] = va_arg(ap, cell_t);
+
+ argsptr = rtas_real_map(&args, sizeof(args));
+ result = rtascall(argsptr, rtas_private_data);
+ rtas_real_unmap(argsptr, &args, sizeof(args));
+ mtx_unlock(&rtas_mtx);
+
+ if (result < 0)
+ return (result);
+
+ for (n = nargs; n < nargs + nreturns; n++)
+ *va_arg(ap, cell_t *) = args.args_n_results[n];
+ return (result);
+}
+
+/* Look up an RTAS token */
+cell_t
+rtas_token_lookup(const char *method)
+{
+ cell_t token;
+
+ if (!rtas_exists())
+ return (-1);
+
+ if (OF_getprop(rtas, method, &token, sizeof(token)) == -1)
+ return (-1);
+
+ return (token);
+}
+
+
diff --git a/sys/powerpc/powermac/fcu.c b/sys/powerpc/powermac/fcu.c
index 004b4db..7ac9b1b 100644
--- a/sys/powerpc/powermac/fcu.c
+++ b/sys/powerpc/powermac/fcu.c
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus.h>
+#include <powerpc/powermac/powermac_thermal.h>
/* FCU registers
* /u3@0,f8000000/i2c@f8001000/fan@15e
@@ -66,10 +67,10 @@ __FBSDID("$FreeBSD$");
#define FCU_PWM_SGET(x) 0x30 + (x) * 2 /* Set or get PWM. */
struct fcu_fan {
+ struct pmac_fan fan;
+ device_t dev;
+
int id;
- cell_t min;
- cell_t max;
- char location[32];
enum {
FCU_FAN_RPM,
FCU_FAN_PWM
@@ -103,9 +104,9 @@ static int fcu_attach(device_t);
/* Utility functions */
static void fcu_attach_fans(device_t dev);
static int fcu_fill_fan_prop(device_t dev);
-static int fcu_fan_set_rpm(device_t dev, struct fcu_fan *fan, int rpm);
-static int fcu_fan_get_rpm(device_t dev, struct fcu_fan *fan, int *rpm);
-static int fcu_fan_set_pwm(device_t dev, struct fcu_fan *fan, int pwm);
+static int fcu_fan_set_rpm(struct fcu_fan *fan, int rpm);
+static int fcu_fan_get_rpm(struct fcu_fan *fan);
+static int fcu_fan_set_pwm(struct fcu_fan *fan, int pwm);
static int fcu_fan_get_pwm(device_t dev, struct fcu_fan *fan, int *pwm,
int *rpm);
static int fcu_fanrpm_sysctl(SYSCTL_HANDLER_ARGS);
@@ -137,6 +138,8 @@ fcu_write(device_t dev, uint32_t addr, uint8_t reg, uint8_t *buff,
int len)
{
unsigned char buf[4];
+ int try = 0;
+
struct iic_msg msg[] = {
{ addr, IIC_M_WR, 0, buf }
};
@@ -144,33 +147,46 @@ fcu_write(device_t dev, uint32_t addr, uint8_t reg, uint8_t *buff,
msg[0].len = len + 1;
buf[0] = reg;
memcpy(buf + 1, buff, len);
- if (iicbus_transfer(dev, msg, 1) != 0) {
- device_printf(dev, "iicbus write failed\n");
- return (EIO);
- }
- return (0);
+ for (;;)
+ {
+ if (iicbus_transfer(dev, msg, 1) == 0)
+ return (0);
+ if (++try > 5) {
+ device_printf(dev, "iicbus write failed\n");
+ return (-1);
+ }
+ pause("fcu_write", hz);
+ }
}
static int
fcu_read_1(device_t dev, uint32_t addr, uint8_t reg, uint8_t *data)
{
uint8_t buf[4];
+ int err, try = 0;
struct iic_msg msg[2] = {
{ addr, IIC_M_WR | IIC_M_NOSTOP, 1, &reg },
{ addr, IIC_M_RD, 1, buf },
};
- if (iicbus_transfer(dev, msg, 2) != 0) {
- device_printf(dev, "iicbus read failed\n");
- return (EIO);
+ for (;;)
+ {
+ err = iicbus_transfer(dev, msg, 2);
+ if (err != 0)
+ goto retry;
+
+ *data = *((uint8_t*)buf);
+ return (0);
+ retry:
+ if (++try > 5) {
+ device_printf(dev, "iicbus read failed\n");
+ return (-1);
+ }
+ pause("fcu_read_1", hz);
}
-
- *data = *((uint8_t*)buf);
-
- return (0);
}
static int
@@ -249,95 +265,102 @@ fcu_start(void *xdev)
}
static int
-fcu_fan_set_rpm(device_t dev, struct fcu_fan *fan, int rpm)
+fcu_fan_set_rpm(struct fcu_fan *fan, int rpm)
{
uint8_t reg;
struct fcu_softc *sc;
unsigned char buf[2];
- sc = device_get_softc(dev);
+ sc = device_get_softc(fan->dev);
/* Clamp to allowed range */
- rpm = max(fan->min, rpm);
- rpm = min(fan->max, rpm);
+ rpm = max(fan->fan.min_rpm, rpm);
+ rpm = min(fan->fan.max_rpm, rpm);
if (fan->type == FCU_FAN_RPM) {
reg = FCU_RPM_SET(fan->id);
fan->setpoint = rpm;
} else {
- device_printf(dev, "Unknown fan type: %d\n", fan->type);
- return (EIO);
+ device_printf(fan->dev, "Unknown fan type: %d\n", fan->type);
+ return (-1);
}
buf[0] = rpm >> (8 - fcu_rpm_shift);
buf[1] = rpm << fcu_rpm_shift;
- fcu_write(sc->sc_dev, sc->sc_addr, reg, buf, 2);
+ if (fcu_write(sc->sc_dev, sc->sc_addr, reg, buf, 2) < 0)
+ return (-1);
return (0);
}
static int
-fcu_fan_get_rpm(device_t dev, struct fcu_fan *fan, int *rpm)
+fcu_fan_get_rpm(struct fcu_fan *fan)
{
uint8_t reg;
struct fcu_softc *sc;
uint8_t buff[2] = { 0, 0 };
uint8_t active = 0, avail = 0, fail = 0;
+ int rpm;
- sc = device_get_softc(dev);
+ sc = device_get_softc(fan->dev);
if (fan->type == FCU_FAN_RPM) {
/* Check if the fan is available. */
reg = FCU_RPM_AVAILABLE;
- fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &avail);
+ if (fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &avail) < 0)
+ return (-1);
if ((avail & (1 << fan->id)) == 0) {
- device_printf(dev, "RPM Fan not available ID: %d\n",
- fan->id);
- return (EIO);
+ device_printf(fan->dev,
+ "RPM Fan not available ID: %d\n", fan->id);
+ return (-1);
}
/* Check if we have a failed fan. */
reg = FCU_RPM_FAIL;
- fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &fail);
+ if (fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &fail) < 0)
+ return (-1);
if ((fail & (1 << fan->id)) != 0) {
- device_printf(dev, "RPM Fan failed ID: %d\n", fan->id);
- return (EIO);
+ device_printf(fan->dev,
+ "RPM Fan failed ID: %d\n", fan->id);
+ return (-1);
}
/* Check if fan is active. */
reg = FCU_RPM_ACTIVE;
- fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &active);
+ if (fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &active) < 0)
+ return (-1);
if ((active & (1 << fan->id)) == 0) {
- device_printf(dev, "RPM Fan not active ID: %d\n",
+ device_printf(fan->dev, "RPM Fan not active ID: %d\n",
fan->id);
- return (ENXIO);
+ return (-1);
}
reg = FCU_RPM_READ(fan->id);
} else {
- device_printf(dev, "Unknown fan type: %d\n", fan->type);
- return (EIO);
+ device_printf(fan->dev, "Unknown fan type: %d\n", fan->type);
+ return (-1);
}
/* It seems that we can read the fans rpm. */
- fcu_read_1(sc->sc_dev, sc->sc_addr, reg, buff);
+ if (fcu_read_1(sc->sc_dev, sc->sc_addr, reg, buff) < 0)
+ return (-1);
- *rpm = (buff[0] << (8 - fcu_rpm_shift)) | buff[1] >> fcu_rpm_shift;
+ rpm = (buff[0] << (8 - fcu_rpm_shift)) | buff[1] >> fcu_rpm_shift;
- return (0);
+ return (rpm);
}
static int
-fcu_fan_set_pwm(device_t dev, struct fcu_fan *fan, int pwm)
+fcu_fan_set_pwm(struct fcu_fan *fan, int pwm)
{
uint8_t reg;
struct fcu_softc *sc;
uint8_t buf[2];
- sc = device_get_softc(dev);
+ sc = device_get_softc(fan->dev);
/* Clamp to allowed range */
- pwm = max(fan->min, pwm);
- pwm = min(fan->max, pwm);
+ pwm = max(fan->fan.min_rpm, pwm);
+ pwm = min(fan->fan.max_rpm, pwm);
if (fan->type == FCU_FAN_PWM) {
reg = FCU_PWM_SGET(fan->id);
@@ -347,14 +370,14 @@ fcu_fan_set_pwm(device_t dev, struct fcu_fan *fan, int pwm)
pwm = 30;
fan->setpoint = pwm;
} else {
- device_printf(dev, "Unknown fan type: %d\n", fan->type);
+ device_printf(fan->dev, "Unknown fan type: %d\n", fan->type);
return (EIO);
}
buf[0] = (pwm * 2550) / 1000;
- fcu_write(sc->sc_dev, sc->sc_addr, reg, buf, 1);
-
+ if (fcu_write(sc->sc_dev, sc->sc_addr, reg, buf, 1) < 0)
+ return (-1);
return (0);
}
@@ -371,26 +394,29 @@ fcu_fan_get_pwm(device_t dev, struct fcu_fan *fan, int *pwm, int *rpm)
if (fan->type == FCU_FAN_PWM) {
/* Check if the fan is available. */
reg = FCU_PWM_AVAILABLE;
- fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &avail);
+ if (fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &avail) < 0)
+ return (-1);
if ((avail & (1 << fan->id)) == 0) {
device_printf(dev, "PWM Fan not available ID: %d\n",
fan->id);
- return (EIO);
+ return (-1);
}
/* Check if we have a failed fan. */
reg = FCU_PWM_FAIL;
- fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &fail);
+ if (fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &fail) < 0)
+ return (-1);
if ((fail & (1 << fan->id)) != 0) {
device_printf(dev, "PWM Fan failed ID: %d\n", fan->id);
- return (EIO);
+ return (-1);
}
/* Check if fan is active. */
reg = FCU_PWM_ACTIVE;
- fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &active);
+ if (fcu_read_1(sc->sc_dev, sc->sc_addr, reg, &active) < 0)
+ return (-1);
if ((active & (1 << fan->id)) == 0) {
device_printf(dev, "PWM Fan not active ID: %d\n",
fan->id);
- return (ENXIO);
+ return (-1);
}
reg = FCU_PWM_SGET(fan->id);
} else {
@@ -399,13 +425,16 @@ fcu_fan_get_pwm(device_t dev, struct fcu_fan *fan, int *pwm, int *rpm)
}
/* It seems that we can read the fans pwm. */
- fcu_read_1(sc->sc_dev, sc->sc_addr, reg, buf);
+ if (fcu_read_1(sc->sc_dev, sc->sc_addr, reg, buf) < 0)
+ return (-1);
*pwm = (buf[0] * 1000) / 2550;
/* Now read the rpm. */
reg = FCU_PWM_RPM(fan->id);
- fcu_read_1(sc->sc_dev, sc->sc_addr, reg, buf);
+ if (fcu_read_1(sc->sc_dev, sc->sc_addr, reg, buf) < 0)
+ return (-1);
+
*rpm = (buf[0] << (8 - fcu_rpm_shift)) | buf[1] >> fcu_rpm_shift;
return (0);
@@ -434,7 +463,7 @@ fcu_fill_fan_prop(device_t dev)
sizeof(location));
while (len < prop_len) {
if (sc->sc_fans != NULL) {
- strcpy(sc->sc_fans[i].location, location + len);
+ strcpy(sc->sc_fans[i].fan.name, location + len);
}
prev_len = strlen(location + len) + 1;
len += prev_len;
@@ -463,6 +492,33 @@ fcu_fill_fan_prop(device_t dev)
for (j = 0; j < i; j++)
sc->sc_fans[j].id = ((id[j] >> 8) & 0x0f) % 8;
+ /* Fill the fan zone property. */
+ prop_len = OF_getprop(child, "hwctrl-zone", id, sizeof(id));
+ for (j = 0; j < i; j++)
+ sc->sc_fans[j].fan.zone = id[j];
+
+ /* Finish setting up fan properties */
+ for (j = 0; j < i; j++) {
+ sc->sc_fans[j].dev = sc->sc_dev;
+ if (sc->sc_fans[j].type == FCU_FAN_RPM) {
+ sc->sc_fans[j].fan.min_rpm = 4800 >> fcu_rpm_shift;
+ sc->sc_fans[j].fan.max_rpm = 56000 >> fcu_rpm_shift;
+ sc->sc_fans[j].setpoint =
+ fcu_fan_get_rpm(&sc->sc_fans[j]);
+ sc->sc_fans[j].fan.read =
+ (int (*)(struct pmac_fan *))(fcu_fan_get_rpm);
+ sc->sc_fans[j].fan.set =
+ (int (*)(struct pmac_fan *, int))(fcu_fan_set_rpm);
+ } else {
+ sc->sc_fans[j].fan.min_rpm = 40; /* Percent */
+ sc->sc_fans[j].fan.max_rpm = 100;
+ sc->sc_fans[j].fan.read = NULL;
+ sc->sc_fans[j].fan.set =
+ (int (*)(struct pmac_fan *, int))(fcu_fan_set_pwm);
+ }
+ sc->sc_fans[j].fan.default_rpm = sc->sc_fans[j].fan.max_rpm;
+ }
+
return (i);
}
@@ -472,16 +528,20 @@ fcu_fanrpm_sysctl(SYSCTL_HANDLER_ARGS)
device_t fcu;
struct fcu_softc *sc;
struct fcu_fan *fan;
- int rpm = 0, pwm = 0, error;
+ int rpm = 0, pwm = 0, error = 0;
fcu = arg1;
sc = device_get_softc(fcu);
fan = &sc->sc_fans[arg2 & 0x00ff];
if (fan->type == FCU_FAN_RPM) {
- fcu_fan_get_rpm(fcu, fan, &rpm);
+ rpm = fcu_fan_get_rpm(fan);
+ if (rpm < 0)
+ return (-1);
error = sysctl_handle_int(oidp, &rpm, 0, req);
} else {
- fcu_fan_get_pwm(fcu, fan, &pwm, &rpm);
+ error = fcu_fan_get_pwm(fcu, fan, &pwm, &rpm);
+ if (error < 0)
+ return (-1);
switch (arg2 & 0xff00) {
case FCU_PWM_SYSCTL_PWM:
@@ -504,9 +564,9 @@ fcu_fanrpm_sysctl(SYSCTL_HANDLER_ARGS)
return (error);
if (fan->type == FCU_FAN_RPM)
- return (fcu_fan_set_rpm(fcu, fan, rpm));
+ return (fcu_fan_set_rpm(fan, rpm));
else
- return (fcu_fan_set_pwm(fcu, fan, pwm));
+ return (fcu_fan_set_pwm(fan, pwm));
}
static void
@@ -543,39 +603,36 @@ fcu_attach_fans(device_t dev)
/* Now we can fill the properties into the allocated struct. */
sc->sc_nfans = fcu_fill_fan_prop(dev);
+ /* Register fans with pmac_thermal */
+ for (i = 0; i < sc->sc_nfans; i++)
+ pmac_thermal_fan_register(&sc->sc_fans[i].fan);
+
/* Add sysctls for the fans. */
for (i = 0; i < sc->sc_nfans; i++) {
- for (j = 0; j < strlen(sc->sc_fans[i].location); j++) {
- sysctl_name[j] = tolower(sc->sc_fans[i].location[j]);
+ for (j = 0; j < strlen(sc->sc_fans[i].fan.name); j++) {
+ sysctl_name[j] = tolower(sc->sc_fans[i].fan.name[j]);
if (isspace(sysctl_name[j]))
sysctl_name[j] = '_';
}
sysctl_name[j] = 0;
if (sc->sc_fans[i].type == FCU_FAN_RPM) {
- sc->sc_fans[i].min = 2400 >> fcu_rpm_shift;
- sc->sc_fans[i].max = 56000 >> fcu_rpm_shift;
- fcu_fan_get_rpm(dev, &sc->sc_fans[i],
- &sc->sc_fans[i].setpoint);
-
oid = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(fanroot_oid),
OID_AUTO, sysctl_name,
CTLFLAG_RD, 0, "Fan Information");
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
"minrpm", CTLTYPE_INT | CTLFLAG_RD,
- &(sc->sc_fans[i].min), sizeof(cell_t),
- "Minimum allowed RPM");
+ &(sc->sc_fans[i].fan.min_rpm),
+ sizeof(int), "Minimum allowed RPM");
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
"maxrpm", CTLTYPE_INT | CTLFLAG_RD,
- &(sc->sc_fans[i].max), sizeof(cell_t),
- "Maximum allowed RPM");
+ &(sc->sc_fans[i].fan.max_rpm),
+ sizeof(int), "Maximum allowed RPM");
/* I use i to pass the fan id. */
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
"rpm", CTLTYPE_INT | CTLFLAG_RW, dev, i,
fcu_fanrpm_sysctl, "I", "Fan RPM");
} else {
- sc->sc_fans[i].min = 30;
- sc->sc_fans[i].max = 100;
fcu_fan_get_pwm(dev, &sc->sc_fans[i],
&sc->sc_fans[i].setpoint,
&sc->sc_fans[i].rpm);
@@ -585,12 +642,12 @@ fcu_attach_fans(device_t dev)
CTLFLAG_RD, 0, "Fan Information");
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
"minpwm", CTLTYPE_INT | CTLFLAG_RD,
- &(sc->sc_fans[i].min), sizeof(cell_t),
- "Minimum allowed PWM in %");
+ &(sc->sc_fans[i].fan.min_rpm),
+ sizeof(int), "Minimum allowed PWM in %");
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
"maxpwm", CTLTYPE_INT | CTLFLAG_RD,
- &(sc->sc_fans[i].max), sizeof(cell_t),
- "Maximum allowed PWM in %");
+ &(sc->sc_fans[i].fan.max_rpm),
+ sizeof(int), "Maximum allowed PWM in %");
/* I use i to pass the fan id or'ed with the type
* of info I want to display/modify.
*/
@@ -610,7 +667,7 @@ fcu_attach_fans(device_t dev)
device_printf(dev, "Fans\n");
for (i = 0; i < sc->sc_nfans; i++) {
device_printf(dev, "Location: %s type: %d ID: %d "
- "RPM: %d\n", sc->sc_fans[i].location,
+ "RPM: %d\n", sc->sc_fans[i].fan.name,
sc->sc_fans[i].type, sc->sc_fans[i].id,
(sc->sc_fans[i].type == FCU_FAN_RPM) ?
sc->sc_fans[i].setpoint :
diff --git a/sys/powerpc/powermac/powermac_thermal.c b/sys/powerpc/powermac/powermac_thermal.c
index 89637ca..9c1f59d 100644
--- a/sys/powerpc/powermac/powermac_thermal.c
+++ b/sys/powerpc/powermac/powermac_thermal.c
@@ -79,7 +79,7 @@ fan_management_proc(void)
{
/* Nothing to manage? */
if (SLIST_EMPTY(&fans))
- return;
+ kproc_exit(0);
while (1) {
pmac_therm_manage_fans();
@@ -94,20 +94,25 @@ pmac_therm_manage_fans(void)
struct pmac_fan_le *fan;
int average_excess, max_excess_zone, frac_excess;
int nsens, nsens_zone;
+ int temp;
if (!enable_pmac_thermal)
return;
/* Read all the sensors */
SLIST_FOREACH(sensor, &sensors, entries) {
- sensor->last_val = sensor->sensor->read(sensor->sensor);
+ temp = sensor->sensor->read(sensor->sensor);
+ if (temp > 0) /* Use the previous temp in case of error */
+ sensor->last_val = temp;
+
if (sensor->last_val > sensor->sensor->max_temp) {
printf("WARNING: Current temperature (%s: %d.%d C) "
"exceeds critical temperature (%d.%d C)! "
"Shutting down!\n", sensor->sensor->name,
- sensor->last_val / 10, sensor->last_val % 10,
- sensor->sensor->max_temp / 10,
- sensor->sensor->max_temp % 10);
+ (sensor->last_val - ZERO_C_TO_K) / 10,
+ (sensor->last_val - ZERO_C_TO_K) % 10,
+ (sensor->sensor->max_temp - ZERO_C_TO_K) / 10,
+ (sensor->sensor->max_temp - ZERO_C_TO_K) % 10);
shutdown_nice(RB_POWEROFF);
}
}
@@ -121,6 +126,8 @@ pmac_therm_manage_fans(void)
sensor->sensor->target_temp)*100 /
(sensor->sensor->max_temp -
sensor->sensor->target_temp);
+ if (frac_excess < 0)
+ frac_excess = 0;
if (sensor->sensor->zone == fan->fan->zone) {
max_excess_zone = imax(max_excess_zone,
frac_excess);
diff --git a/sys/powerpc/powermac/powermac_thermal.h b/sys/powerpc/powermac/powermac_thermal.h
index 43bd629..424c612 100644
--- a/sys/powerpc/powermac/powermac_thermal.h
+++ b/sys/powerpc/powermac/powermac_thermal.h
@@ -29,6 +29,8 @@
#ifndef _POWERPC_POWERMAC_POWERMAC_THERMAL_H
#define _POWERPC_POWERMAC_POWERMAC_THERMAL_H
+#define ZERO_C_TO_K 2732
+
struct pmac_fan {
int min_rpm, max_rpm, default_rpm;
diff --git a/sys/powerpc/powermac/smu.c b/sys/powerpc/powermac/smu.c
index 09025b1..ede97a1 100644
--- a/sys/powerpc/powermac/smu.c
+++ b/sys/powerpc/powermac/smu.c
@@ -854,7 +854,7 @@ smu_sensor_read(struct smu_sensor *sens)
value <<= 1;
/* Convert from 16.16 fixed point degC into integer 0.1 K. */
- value = 10*(value >> 16) + 2732;
+ value = 10*(value >> 16) + ((10*(value & 0xffff)) >> 16) + 2732;
break;
case SMU_VOLTAGE_SENSOR:
value *= sc->sc_cpu_volt_scale;
diff --git a/sys/powerpc/powermac/smusat.c b/sys/powerpc/powermac/smusat.c
index 886cd4f..fcaa9ed 100644
--- a/sys/powerpc/powermac/smusat.c
+++ b/sys/powerpc/powermac/smusat.c
@@ -235,7 +235,7 @@ smusat_sensor_read(struct smu_sensor *sens)
/* 16.16 */
value <<= 10;
/* From 16.16 to 0.1 C */
- value = 10*(value >> 16) + 2732;
+ value = 10*(value >> 16) + ((10*(value & 0xffff)) >> 16) + 2732;
break;
case SMU_VOLTAGE_SENSOR:
/* 16.16 */
diff --git a/sys/powerpc/powermac/windtunnel.c b/sys/powerpc/powermac/windtunnel.c
new file mode 100644
index 0000000..b4aeca3
--- /dev/null
+++ b/sys/powerpc/powermac/windtunnel.c
@@ -0,0 +1,216 @@
+/*-
+ * Copyright (c) 2011 Justin Hibbits
+ * Copyright (c) 2010 Andreas Tobler
+ * 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$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/callout.h>
+#include <sys/conf.h>
+#include <sys/cpu.h>
+#include <sys/ctype.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/limits.h>
+#include <sys/reboot.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+#include <sys/unistd.h>
+
+#include <machine/bus.h>
+#include <machine/md_var.h>
+
+#include <dev/iicbus/iicbus.h>
+#include <dev/iicbus/iiconf.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <powerpc/powermac/powermac_thermal.h>
+
+struct adm1030_softc {
+ struct pmac_fan fan;
+ device_t sc_dev;
+ struct intr_config_hook enum_hook;
+ uint32_t sc_addr;
+ phandle_t sc_thermostat_phandle;
+ device_t sc_thermostat_dev;
+};
+
+/* Regular bus attachment functions */
+static int adm1030_probe(device_t);
+static int adm1030_attach(device_t);
+
+/* Utility functions */
+static void adm1030_start(void *xdev);
+static int adm1030_write_byte(device_t dev, uint32_t addr, uint8_t reg, uint8_t buf);
+static int adm1030_set(struct adm1030_softc *fan, int pwm);
+
+static device_method_t adm1030_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, adm1030_probe),
+ DEVMETHOD(device_attach, adm1030_attach),
+ {0, 0},
+};
+
+static driver_t adm1030_driver = {
+ "adm1030",
+ adm1030_methods,
+ sizeof(struct adm1030_softc)
+};
+
+static devclass_t adm1030_devclass;
+
+DRIVER_MODULE(adm1030, iicbus, adm1030_driver, adm1030_devclass, 0, 0);
+
+static int
+adm1030_write_byte(device_t dev, uint32_t addr, uint8_t reg, uint8_t byte)
+{
+ unsigned char buf[4];
+ int try = 0;
+
+ struct iic_msg msg[] = {
+ {addr, IIC_M_WR, 0, buf}
+ };
+
+ msg[0].len = 2;
+ buf[0] = reg;
+ buf[1] = byte;
+
+ for (;;)
+ {
+ if (iicbus_transfer(dev, msg, 1) == 0)
+ return (0);
+
+ if (++try > 5) {
+ device_printf(dev, "iicbus write failed\n");
+ return (-1);
+ }
+ pause("adm1030_write_byte", hz);
+ }
+}
+
+static int
+adm1030_probe(device_t dev)
+{
+ const char *name, *compatible;
+ struct adm1030_softc *sc;
+ phandle_t handle;
+ phandle_t thermostat;
+
+ name = ofw_bus_get_name(dev);
+ compatible = ofw_bus_get_compat(dev);
+ handle = ofw_bus_get_node(dev);
+
+ if (!name)
+ return (ENXIO);
+
+ if (strcmp(name, "fan") != 0 || strcmp(compatible, "adm1030") != 0)
+ return (ENXIO);
+
+ /* This driver can only be used if there's an associated temp sensor. */
+ if (OF_getprop(handle, "platform-getTemp", &thermostat, sizeof(thermostat)) < 0)
+ return (ENXIO);
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+ sc->sc_addr = iicbus_get_addr(dev);
+
+ device_set_desc(dev, "G4 MDD Fan driver");
+
+ return (0);
+}
+
+static int
+adm1030_attach(device_t dev)
+{
+ struct adm1030_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ sc->enum_hook.ich_func = adm1030_start;
+ sc->enum_hook.ich_arg = dev;
+
+ /*
+ * We have to wait until interrupts are enabled. I2C read and write
+ * only works if the interrupts are available. The unin/i2c is
+ * controlled by the htpic on unin. But this is not the master. The
+ * openpic on mac-io is controlling the htpic. This one gets attached
+ * after the mac-io probing and then the interrupts will be
+ * available.
+ */
+
+ if (config_intrhook_establish(&sc->enum_hook) != 0)
+ return (ENOMEM);
+
+ return (0);
+}
+
+static void
+adm1030_start(void *xdev)
+{
+ struct adm1030_softc *sc;
+
+ device_t dev = (device_t) xdev;
+
+ sc = device_get_softc(dev);
+
+ /* Start the adm1030 device. */
+ adm1030_write_byte(sc->sc_dev, sc->sc_addr, 0x1, 0x1);
+ adm1030_write_byte(sc->sc_dev, sc->sc_addr, 0x0, 0x95);
+ adm1030_write_byte(sc->sc_dev, sc->sc_addr, 0x23, 0x91);
+
+ /* Use the RPM fields as PWM duty cycles. */
+ sc->fan.min_rpm = 0;
+ sc->fan.max_rpm = 15;
+ sc->fan.default_rpm = 2;
+
+ strcpy(sc->fan.name, "MDD Case fan");
+ sc->fan.zone = 0;
+ sc->fan.read = NULL;
+ sc->fan.set = (int (*)(struct pmac_fan *, int))adm1030_set;
+ config_intrhook_disestablish(&sc->enum_hook);
+
+ pmac_thermal_fan_register(&sc->fan);
+}
+
+static int adm1030_set(struct adm1030_softc *fan, int pwm)
+{
+ /* Clamp the PWM to 0-0xF, one nibble. */
+ if (pwm > 0xF)
+ pwm = 0xF;
+ if (pwm < 0)
+ pwm = 0;
+
+ if (adm1030_write_byte(fan->sc_dev, fan->sc_addr, 0x22, pwm) < 0)
+ return (-1);
+
+ return (0);
+}
+
diff --git a/sys/powerpc/powerpc/mp_machdep.c b/sys/powerpc/powerpc/mp_machdep.c
index 02920da..577d4dc 100644
--- a/sys/powerpc/powerpc/mp_machdep.c
+++ b/sys/powerpc/powerpc/mp_machdep.c
@@ -212,7 +212,7 @@ cpu_mp_unleash(void *dummy)
cpus = 0;
smp_cpus = 0;
- SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
+ STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
cpus++;
pc->pc_other_cpus = all_cpus & ~pc->pc_cpumask;
if (!pc->pc_bsp) {
@@ -347,7 +347,7 @@ ipi_selected(cpumask_t cpus, int ipi)
{
struct pcpu *pc;
- SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
+ STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
if (cpus & pc->pc_cpumask)
ipi_send(pc, ipi);
}
@@ -367,7 +367,7 @@ ipi_all_but_self(int ipi)
{
struct pcpu *pc;
- SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
+ STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
if (pc != pcpup)
ipi_send(pc, ipi);
}
diff --git a/sys/sparc64/sparc64/mp_machdep.c b/sys/sparc64/sparc64/mp_machdep.c
index 8700f89..4d9151e 100644
--- a/sys/sparc64/sparc64/mp_machdep.c
+++ b/sys/sparc64/sparc64/mp_machdep.c
@@ -383,7 +383,7 @@ cpu_mp_unleash(void *v)
ctx_inc = (TLB_CTX_USER_MAX - 1) / mp_ncpus;
csa = &cpu_start_args;
csa->csa_count = mp_ncpus;
- SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
+ STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
pc->pc_tlb_ctx = ctx_min;
pc->pc_tlb_ctx_min = ctx_min;
pc->pc_tlb_ctx_max = ctx_min + ctx_inc;
diff --git a/sys/sparc64/sparc64/pmap.c b/sys/sparc64/sparc64/pmap.c
index 09482b9..c34fc45 100644
--- a/sys/sparc64/sparc64/pmap.c
+++ b/sys/sparc64/sparc64/pmap.c
@@ -1278,7 +1278,7 @@ pmap_release(pmap_t pm)
* to a kernel thread, leaving the pmap pointer unchanged.
*/
mtx_lock_spin(&sched_lock);
- SLIST_FOREACH(pc, &cpuhead, pc_allcpu)
+ STAILQ_FOREACH(pc, &cpuhead, pc_allcpu)
if (pc->pc_pmap == pm)
pc->pc_pmap = NULL;
mtx_unlock_spin(&sched_lock);
diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h
index 654f145..c2b7081 100644
--- a/sys/sys/mbuf.h
+++ b/sys/sys/mbuf.h
@@ -199,7 +199,9 @@ struct mbuf {
#define M_PROTO6 0x00080000 /* protocol-specific */
#define M_PROTO7 0x00100000 /* protocol-specific */
#define M_PROTO8 0x00200000 /* protocol-specific */
-#define M_FLOWID 0x00400000 /* flowid is valid */
+#define M_FLOWID 0x00400000 /* deprecated: flowid is valid */
+#define M_HASHTYPEBITS 0x0F000000 /* mask of bits holding flowid hash type */
+
/*
* For RELENG_{6,7} steal these flags for limited multiple routing table
* support. In RELENG_8 and beyond, use just one flag and a tag.
@@ -215,11 +217,45 @@ struct mbuf {
(M_PROTO1|M_PROTO2|M_PROTO3|M_PROTO4|M_PROTO5|M_PROTO6|M_PROTO7|M_PROTO8)
/*
+ * Network interface cards are able to hash protocol fields (such as IPv4
+ * addresses and TCP port numbers) classify packets into flows. These flows
+ * can then be used to maintain ordering while delivering packets to the OS
+ * via parallel input queues, as well as to provide a stateless affinity
+ * model. NIC drivers can pass up the hash via m->m_pkthdr.flowid, and set
+ * m_flag fields to indicate how the hash should be interpreted by the
+ * network stack.
+ *
+ * Most NICs support RSS, which provides ordering and explicit affinity, and
+ * use the hash m_flag bits to indicate what header fields were covered by
+ * the hash. M_HASHTYPE_OPAQUE can be set by non-RSS cards or configurations
+ * that provide an opaque flow identifier, allowing for ordering and
+ * distribution without explicit affinity.
+ */
+#define M_HASHTYPE_SHIFT 24
+#define M_HASHTYPE_NONE 0x0
+#define M_HASHTYPE_RSS_IPV4 0x1 /* IPv4 2-tuple */
+#define M_HASHTYPE_RSS_TCP_IPV4 0x2 /* TCPv4 4-tuple */
+#define M_HASHTYPE_RSS_IPV6 0x3 /* IPv6 2-tuple */
+#define M_HASHTYPE_RSS_TCP_IPV6 0x4 /* TCPv6 4-tuple */
+#define M_HASHTYPE_RSS_IPV6_EX 0x5 /* IPv6 2-tuple + ext hdrs */
+#define M_HASHTYPE_RSS_TCP_IPV6_EX 0x6 /* TCPv6 4-tiple + ext hdrs */
+#define M_HASHTYPE_OPAQUE 0xf /* ordering, not affinity */
+
+#define M_HASHTYPE_CLEAR(m) (m)->m_flags &= ~(M_HASHTYPEBITS)
+#define M_HASHTYPE_GET(m) (((m)->m_flags & M_HASHTYPEBITS) >> \
+ M_HASHTYPE_SHIFT)
+#define M_HASHTYPE_SET(m, v) do { \
+ (m)->m_flags &= ~M_HASHTYPEBITS; \
+ (m)->m_flags |= ((v) << M_HASHTYPE_SHIFT); \
+} while (0)
+#define M_HASHTYPE_TEST(m, v) (M_HASHTYPE_GET(m) == (v))
+
+/*
* Flags preserved when copying m_pkthdr.
*/
#define M_COPYFLAGS \
(M_PKTHDR|M_EOR|M_RDONLY|M_PROTOFLAGS|M_SKIP_FIREWALL|M_BCAST|M_MCAST|\
- M_FRAG|M_FIRSTFRAG|M_LASTFRAG|M_VLANTAG|M_PROMISC|M_FIB)
+ M_FRAG|M_FIRSTFRAG|M_LASTFRAG|M_VLANTAG|M_PROMISC|M_FIB|M_HASHTYPEBITS)
/*
* External buffer types: identify ext_buf type.
diff --git a/sys/sys/msgbuf.h b/sys/sys/msgbuf.h
index 8435c68..67f80a5 100644
--- a/sys/sys/msgbuf.h
+++ b/sys/sys/msgbuf.h
@@ -33,15 +33,21 @@
#ifndef _SYS_MSGBUF_H_
#define _SYS_MSGBUF_H_
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
struct msgbuf {
- char *msg_ptr; /* pointer to buffer */
+ char *msg_ptr; /* pointer to buffer */
#define MSG_MAGIC 0x063062
- u_int msg_magic;
- u_int msg_size; /* size of buffer area */
- u_int msg_wseq; /* write sequence number */
- u_int msg_rseq; /* read sequence number */
- u_int msg_cksum; /* checksum of contents */
- u_int msg_seqmod; /* range for sequence numbers */
+ u_int msg_magic;
+ u_int msg_size; /* size of buffer area */
+ u_int msg_wseq; /* write sequence number */
+ u_int msg_rseq; /* read sequence number */
+ u_int msg_cksum; /* checksum of contents */
+ u_int msg_seqmod; /* range for sequence numbers */
+ int msg_lastpri; /* saved priority value */
+ int msg_needsnl; /* set when newline needed */
+ struct mtx msg_lock; /* mutex to protect the buffer */
};
/* Normalise a sequence number or a difference between sequence numbers. */
@@ -59,6 +65,7 @@ extern struct mtx msgbuf_lock;
void msgbufinit(void *ptr, int size);
void msgbuf_addchar(struct msgbuf *mbp, int c);
+void msgbuf_addstr(struct msgbuf *mbp, int pri, char *str, int filter_cr);
void msgbuf_clear(struct msgbuf *mbp);
void msgbuf_copy(struct msgbuf *src, struct msgbuf *dst);
int msgbuf_getbytes(struct msgbuf *mbp, char *buf, int buflen);
diff --git a/sys/sys/pcpu.h b/sys/sys/pcpu.h
index ad1cf33..0bb2cbd 100644
--- a/sys/sys/pcpu.h
+++ b/sys/sys/pcpu.h
@@ -164,7 +164,7 @@ struct pcpu {
u_int pc_cpuid; /* This cpu number */
cpumask_t pc_cpumask; /* This cpu mask */
cpumask_t pc_other_cpus; /* Mask of all other cpus */
- SLIST_ENTRY(pcpu) pc_allcpu;
+ STAILQ_ENTRY(pcpu) pc_allcpu;
struct lock_list_entry *pc_spinlocks;
#ifdef KTR
char pc_name[PCPU_NAME_LEN]; /* String name for KTR */
@@ -201,7 +201,7 @@ struct pcpu {
#ifdef _KERNEL
-SLIST_HEAD(cpuhead, pcpu);
+STAILQ_HEAD(cpuhead, pcpu);
extern struct cpuhead cpuhead;
extern struct pcpu *cpuid_to_pcpu[MAXCPU];
diff --git a/sys/teken/libteken/teken.3 b/sys/teken/libteken/teken.3
index bcc0db0..2a9b291 100644
--- a/sys/teken/libteken/teken.3
+++ b/sys/teken/libteken/teken.3
@@ -185,22 +185,6 @@ function switches terminal emulation to
which is used by versions of
.Fx
prior to 9.0.
-.Sh SECURITY CONSIDERATIONS
-The
-.Fn tf_respond
-callback is used to respond to device status requests commands generated
-by an application.
-In the past, there have been various security issues, where a malicious
-application sends a device status request before termination, causing
-the generated response to be interpreted by applications such as
-.Xr sh 1 .
-.Pp
-.Nm
-only implements a small subset of responses which are unlikely to cause
-any harm.
-Still, it is advised to leave
-.Fn tf_respond
-unimplemented.
.Sh SEE ALSO
.Xr ncurses 3 ,
.Xr termcap 3 ,
@@ -218,3 +202,19 @@ the
library appeared in userspace.
.Sh AUTHORS
.An Ed Schouten Aq ed@FreeBSD.org
+.Sh SECURITY CONSIDERATIONS
+The
+.Fn tf_respond
+callback is used to respond to device status requests commands generated
+by an application.
+In the past, there have been various security issues, where a malicious
+application sends a device status request before termination, causing
+the generated response to be interpreted by applications such as
+.Xr sh 1 .
+.Pp
+.Nm
+only implements a small subset of responses which are unlikely to cause
+any harm.
+Still, it is advised to leave
+.Fn tf_respond
+unimplemented.
diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c
index dbcac85..1a3d398 100644
--- a/sys/vm/vm_object.c
+++ b/sys/vm/vm_object.c
@@ -852,6 +852,21 @@ rescan:
flags, &clearobjflags);
if (object->generation != curgeneration)
goto rescan;
+
+ /*
+ * If the VOP_PUTPAGES() did a truncated write, so
+ * that even the first page of the run is not fully
+ * written, vm_pageout_flush() returns 0 as the run
+ * length. Since the condition that caused truncated
+ * write may be permanent, e.g. exhausted free space,
+ * accepting n == 0 would cause an infinite loop.
+ *
+ * Forwarding the iterator leaves the unwritten page
+ * behind, but there is not much we can do there if
+ * filesystem refuses to write it.
+ */
+ if (n == 0)
+ n = 1;
np = vm_page_find_least(object, pi + n);
}
#if 0
diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c
index f497d41..98a5be0 100644
--- a/sys/vm/vnode_pager.c
+++ b/sys/vm/vnode_pager.c
@@ -1089,7 +1089,7 @@ vnode_pager_generic_putpages(struct vnode *vp, vm_page_t *ma, int bytecount,
count = bytecount / PAGE_SIZE;
for (i = 0; i < count; i++)
- rtvals[i] = VM_PAGER_AGAIN;
+ rtvals[i] = VM_PAGER_ERROR;
if ((int64_t)ma[0]->pindex < 0) {
printf("vnode_pager_putpages: attempt to write meta-data!!! -- 0x%lx(%lx)\n",
@@ -1191,3 +1191,20 @@ vnode_pager_generic_putpages(struct vnode *vp, vm_page_t *ma, int bytecount,
}
return rtvals[0];
}
+
+void
+vnode_pager_undirty_pages(vm_page_t *ma, int *rtvals, int written)
+{
+ int i, pos;
+
+ for (i = 0, pos = 0; pos < written; i++, pos += PAGE_SIZE) {
+ if (pos < trunc_page(written)) {
+ rtvals[i] = VM_PAGER_OK;
+ vm_page_undirty(ma[i]);
+ } else {
+ /* Partially written page. */
+ rtvals[i] = VM_PAGER_AGAIN;
+ vm_page_clear_dirty(ma[i], 0, written & PAGE_MASK);
+ }
+ }
+}
diff --git a/sys/vm/vnode_pager.h b/sys/vm/vnode_pager.h
index 88ae306..5e3d5eb 100644
--- a/sys/vm/vnode_pager.h
+++ b/sys/vm/vnode_pager.h
@@ -49,5 +49,8 @@ int vnode_pager_generic_getpages(struct vnode *vp, vm_page_t *m,
int vnode_pager_generic_putpages(struct vnode *vp, vm_page_t *m,
int count, boolean_t sync,
int *rtvals);
+
+void vnode_pager_undirty_pages(vm_page_t *ma, int *rtvals, int written);
+
#endif /* _KERNEL */
#endif /* _VNODE_PAGER_ */
diff --git a/tools/regression/bin/sh/builtins/alias.1.stderr b/tools/regression/bin/sh/builtins/alias.1.stderr
index 5ea01d5..c9f4011 100644
--- a/tools/regression/bin/sh/builtins/alias.1.stderr
+++ b/tools/regression/bin/sh/builtins/alias.1.stderr
@@ -1 +1 @@
-alias: foo not found
+alias: foo: not found
diff --git a/tools/regression/bin/sh/builtins/set1.0 b/tools/regression/bin/sh/builtins/set1.0
new file mode 100644
index 0000000..fc39fad
--- /dev/null
+++ b/tools/regression/bin/sh/builtins/set1.0
@@ -0,0 +1,32 @@
+# $FreeBSD$
+
+set +C
+set +f
+set -e
+
+settings=$(set +o)
+set -C
+set -f
+set +e
+case $- in
+*C*) ;;
+*) echo missing C ;;
+esac
+case $- in
+*f*) ;;
+*) echo missing C ;;
+esac
+case $- in
+*e*) echo bad e ;;
+esac
+eval "$settings"
+case $- in
+*C*) echo bad C ;;
+esac
+case $- in
+*f*) echo bad f ;;
+esac
+case $- in
+*e*) ;;
+*) echo missing e ;;
+esac
diff --git a/tools/regression/bin/sh/execution/set-n1.0 b/tools/regression/bin/sh/execution/set-n1.0
new file mode 100644
index 0000000..14c9b93
--- /dev/null
+++ b/tools/regression/bin/sh/execution/set-n1.0
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+v=$( ($SH -n <<'EOF'
+for
+EOF
+) 2>&1 >/dev/null)
+[ $? -ne 0 ] && [ -n "$v" ]
diff --git a/tools/regression/bin/sh/execution/set-n2.0 b/tools/regression/bin/sh/execution/set-n2.0
new file mode 100644
index 0000000..c7f3162
--- /dev/null
+++ b/tools/regression/bin/sh/execution/set-n2.0
@@ -0,0 +1,5 @@
+# $FreeBSD$
+
+$SH -n <<'EOF'
+echo bad
+EOF
diff --git a/tools/regression/bin/sh/execution/set-n3.0 b/tools/regression/bin/sh/execution/set-n3.0
new file mode 100644
index 0000000..24a9159
--- /dev/null
+++ b/tools/regression/bin/sh/execution/set-n3.0
@@ -0,0 +1,4 @@
+# $FreeBSD$
+
+v=$( ($SH -nc 'for') 2>&1 >/dev/null)
+[ $? -ne 0 ] && [ -n "$v" ]
diff --git a/tools/regression/bin/sh/execution/set-n4.0 b/tools/regression/bin/sh/execution/set-n4.0
new file mode 100644
index 0000000..3698508
--- /dev/null
+++ b/tools/regression/bin/sh/execution/set-n4.0
@@ -0,0 +1,3 @@
+# $FreeBSD$
+
+$SH -nc 'echo bad'
diff --git a/tools/regression/bin/sh/parser/func2.0 b/tools/regression/bin/sh/parser/func2.0
new file mode 100644
index 0000000..5fd4dda
--- /dev/null
+++ b/tools/regression/bin/sh/parser/func2.0
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+f() { return 42; }
+f() { return 3; } &
+f
+[ $? -eq 42 ]
diff --git a/tools/regression/bin/sh/parser/func3.0 b/tools/regression/bin/sh/parser/func3.0
new file mode 100644
index 0000000..dcac732
--- /dev/null
+++ b/tools/regression/bin/sh/parser/func3.0
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+name=/var/empty/nosuch
+f() { true; } <$name
+name=/dev/null
+f
diff --git a/tools/regression/netinet/ipdivert/Makefile b/tools/regression/netinet/ipdivert/Makefile
new file mode 100644
index 0000000..385620b
--- /dev/null
+++ b/tools/regression/netinet/ipdivert/Makefile
@@ -0,0 +1,11 @@
+#
+# $FreeBSD$
+#
+
+PROG= ipdivert
+SRCS= ipdivert.c
+NO_MAN=
+
+WARNS?= 2
+
+.include <bsd.prog.mk>
diff --git a/tools/regression/netinet/ipdivert/ipdivert.c b/tools/regression/netinet/ipdivert/ipdivert.c
new file mode 100644
index 0000000..0d58491
--- /dev/null
+++ b/tools/regression/netinet/ipdivert/ipdivert.c
@@ -0,0 +1,166 @@
+/*-
+ * Copyright (c) 2010-2011 Juniper Networks, Inc.
+ * All rights reserved.
+ *
+ * This software was developed by Robert N. M. Watson under contract
+ * to Juniper Networks, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * This is a test tool for IP divert sockets. For the time being, it just
+ * exercise creation and binding of sockets, rather than their divert
+ * behaviour. It would be highly desirable to broaden this test tool to
+ * include packet injection and diversion.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void
+ok(const char *test)
+{
+
+ fprintf(stderr, "%s: OK\n", test);
+}
+
+static void
+fail(const char *test, const char *note)
+{
+
+ fprintf(stderr, "%s - %s: FAIL (%s)\n", test, note, strerror(errno));
+ exit(1);
+}
+
+static void
+failx(const char *test, const char *note)
+{
+
+ fprintf(stderr, "%s - %s: FAIL\n", test, note);
+ exit(1);
+}
+
+static int
+ipdivert_create(const char *test)
+{
+ int s;
+
+ s = socket(PF_INET, SOCK_RAW, IPPROTO_DIVERT);
+ if (s < 0)
+ fail(test, "socket");
+ return (s);
+}
+
+static void
+ipdivert_close(const char *test, int s)
+{
+
+ if (close(s) < 0)
+ fail(test, "close");
+}
+
+static void
+ipdivert_bind(const char *test, int s, u_short port, int expect)
+{
+ struct sockaddr_in sin;
+ int err;
+
+ bzero(&sin, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = htonl(INADDR_ANY);
+ sin.sin_port = htons(port);
+
+ err = bind(s, (struct sockaddr *)&sin, sizeof(sin));
+ if (err < 0) {
+ if (expect == 0)
+ fail(test, "bind");
+ if (errno != expect)
+ fail(test, "bind");
+ } else {
+ if (expect != 0)
+ failx(test, "bind");
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ const char *test;
+ int s1, s2;
+
+ /*
+ * First test: create and close an IP divert socket.
+ */
+ test = "create_close";
+ s1 = ipdivert_create(test);
+ ipdivert_close(test, s1);
+ ok(test);
+
+ /*
+ * Second test: create, bind, and close an IP divert socket.
+ */
+ test = "create_bind_close";
+ s1 = ipdivert_create(test);
+ ipdivert_bind(test, s1, 1000, 0);
+ ipdivert_close(test, s1);
+ ok(test);
+
+ /*
+ * Third test: create two sockets, bind to different ports, and close.
+ * This should succeed due to non-conflict on the port numbers.
+ */
+ test = "create2_bind2_close2";
+ s1 = ipdivert_create(test);
+ s2 = ipdivert_create(test);
+ ipdivert_bind(test, s1, 1000, 0);
+ ipdivert_bind(test, s2, 1001, 0);
+ ipdivert_close(test, s1);
+ ipdivert_close(test, s2);
+ ok(test);
+
+ /*
+ * Fourth test: create two sockets, bind to the *same* port, and
+ * close. This should fail due to conflicting port numbers.
+ */
+ test = "create2_bind2_conflict_close2";
+ s1 = ipdivert_create(test);
+ s2 = ipdivert_create(test);
+ ipdivert_bind(test, s1, 1000, 0);
+ ipdivert_bind(test, s2, 1000, EADDRINUSE);
+ ipdivert_close(test, s1);
+ ipdivert_close(test, s2);
+ ok(test);
+
+ return (0);
+}
diff --git a/tools/regression/netinet/tcpconnect/tcpconnect.c b/tools/regression/netinet/tcpconnect/tcpconnect.c
index b9942d1..1257f66 100644
--- a/tools/regression/netinet/tcpconnect/tcpconnect.c
+++ b/tools/regression/netinet/tcpconnect/tcpconnect.c
@@ -34,6 +34,7 @@
#include <arpa/inet.h>
+#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
diff --git a/tools/regression/netinet/tcpdrop/tcpdrop.c b/tools/regression/netinet/tcpdrop/tcpdrop.c
index bf78d55..e6b7f43 100644
--- a/tools/regression/netinet/tcpdrop/tcpdrop.c
+++ b/tools/regression/netinet/tcpdrop/tcpdrop.c
@@ -1,7 +1,11 @@
/*-
* Copyright (c) 2006 Robert N. M. Watson
+ * Copyright (c) 2011 Juniper Networks, Inc.
* All rights reserved.
*
+ * Portions of this software were developed by Robert N. M. Watson under
+ * contract to Juniper Networks, Inc.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -46,8 +50,6 @@
#include <string.h>
#include <unistd.h>
-#define TCP_PORT 9001
-
static int
tcp_drop(struct sockaddr_in *sin_local, struct sockaddr_in *sin_remote)
{
@@ -66,41 +68,12 @@ tcp_drop(struct sockaddr_in *sin_local, struct sockaddr_in *sin_remote)
}
static void
-tcp_server(pid_t partner)
+tcp_server(pid_t partner, int listen_fd)
{
- int error, listen_fd, accept_fd;
- struct sockaddr_in sin;
+ int error, accept_fd;
ssize_t len;
char ch;
- listen_fd = socket(PF_INET, SOCK_STREAM, 0);
- if (listen_fd < 0) {
- error = errno;
- (void)kill(partner, SIGTERM);
- errno = error;
- err(-1, "tcp_server: socket");
- }
-
- bzero(&sin, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_len = sizeof(sin);
- sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- sin.sin_port = htons(TCP_PORT);
-
- if (bind(listen_fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
- error = errno;
- (void)kill(partner, SIGTERM);
- errno = error;
- err(-1, "tcp_server: bind");
- }
-
- if (listen(listen_fd, -1) < 0) {
- error = errno;
- (void)kill(partner, SIGTERM);
- errno = error;
- err(-1, "tcp_server: listen");
- }
-
accept_fd = accept(listen_fd, NULL, NULL);
if (accept_fd < 0) {
error = errno;
@@ -146,7 +119,7 @@ tcp_server(pid_t partner)
}
static void
-tcp_client(pid_t partner)
+tcp_client(pid_t partner, u_short port)
{
struct sockaddr_in sin, sin_local;
int error, sock;
@@ -168,7 +141,7 @@ tcp_client(pid_t partner)
sin.sin_family = AF_INET;
sin.sin_len = sizeof(sin);
sin.sin_addr.s_addr = ntohl(INADDR_LOOPBACK);
- sin.sin_port = htons(TCP_PORT);
+ sin.sin_port = port;
if (connect(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
error = errno;
@@ -230,6 +203,40 @@ int
main(int argc, char *argv[])
{
pid_t child_pid, parent_pid;
+ struct sockaddr_in sin;
+ int listen_fd;
+ u_short port;
+ socklen_t len;
+
+ listen_fd = socket(PF_INET, SOCK_STREAM, 0);
+ if (listen_fd < 0)
+ err(-1, "socket");
+
+ /*
+ * We use the loopback, but let the kernel select a port for the
+ * server socket.
+ */
+ bzero(&sin, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof(sin);
+ sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+ if (bind(listen_fd, (struct sockaddr *)&sin, sizeof(sin)) < 0)
+ err(-1, "bind");
+
+ if (listen(listen_fd, -1) < 0)
+ err(-1, "listen");
+
+ /*
+ * Query the port so that the client can use it.
+ */
+ bzero(&sin, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof(sin);
+ if (getsockname(listen_fd, (struct sockaddr *)&sin, &len) < 0)
+ err(-1, "getsockname");
+ port = sin.sin_port;
+ printf("Using port %d\n", ntohs(port));
if (signal(SIGCHLD, SIG_IGN) == SIG_ERR)
err(-1, "signal");
@@ -240,9 +247,9 @@ main(int argc, char *argv[])
err(-1, "fork");
if (child_pid == 0) {
child_pid = getpid();
- tcp_server(parent_pid);
+ tcp_server(parent_pid, listen_fd);
} else
- tcp_client(child_pid);
+ tcp_client(child_pid, port);
return (0);
}
diff --git a/tools/regression/netinet/tcpfullwindowrst/tcpfullwindowrsttest.c b/tools/regression/netinet/tcpfullwindowrst/tcpfullwindowrsttest.c
index ac86b9e..6e4ac03 100644
--- a/tools/regression/netinet/tcpfullwindowrst/tcpfullwindowrsttest.c
+++ b/tools/regression/netinet/tcpfullwindowrst/tcpfullwindowrsttest.c
@@ -35,6 +35,7 @@ $FreeBSD$
#include <poll.h>
#include <unistd.h>
#include <signal.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
diff --git a/tools/regression/netinet/tcpsocktimewait/tcpsocktimewait.c b/tools/regression/netinet/tcpsocktimewait/tcpsocktimewait.c
index a5e6542..3025468 100644
--- a/tools/regression/netinet/tcpsocktimewait/tcpsocktimewait.c
+++ b/tools/regression/netinet/tcpsocktimewait/tcpsocktimewait.c
@@ -1,7 +1,11 @@
/*-
* Copyright (c) 2006 Robert N. M. Watson
+ * Copyright (c) 2011 Juniper Networks, Inc.
* All rights reserved.
*
+ * Portions of this software were developed by Robert N. M. Watson under
+ * contract to Juniper Networks, Inc.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -41,45 +45,15 @@
#include <err.h>
#include <errno.h>
#include <signal.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#define TCP_PORT 9001
-
static void
-tcp_server(pid_t partner)
+tcp_server(pid_t partner, int listen_fd)
{
- int error, listen_fd, accept_fd;
- struct sockaddr_in sin;
-
- listen_fd = socket(PF_INET, SOCK_STREAM, 0);
- if (listen_fd < 0) {
- error = errno;
- (void)kill(partner, SIGTERM);
- errno = error;
- err(-1, "tcp_server: socket");
- }
-
- bzero(&sin, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_len = sizeof(sin);
- sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- sin.sin_port = htons(TCP_PORT);
-
- if (bind(listen_fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
- error = errno;
- (void)kill(partner, SIGTERM);
- errno = error;
- err(-1, "tcp_server: bind");
- }
-
- if (listen(listen_fd, -1) < 0) {
- error = errno;
- (void)kill(partner, SIGTERM);
- errno = error;
- err(-1, "tcp_server: listen");
- }
+ int error, accept_fd;
accept_fd = accept(listen_fd, NULL, NULL);
if (accept_fd < 0) {
@@ -93,7 +67,7 @@ tcp_server(pid_t partner)
}
static void
-tcp_client(pid_t partner, int secs)
+tcp_client(pid_t partner, u_short port, int secs)
{
struct sockaddr_in sin;
int error, sock;
@@ -112,7 +86,7 @@ tcp_client(pid_t partner, int secs)
sin.sin_family = AF_INET;
sin.sin_len = sizeof(sin);
sin.sin_addr.s_addr = ntohl(INADDR_LOOPBACK);
- sin.sin_port = htons(TCP_PORT);
+ sin.sin_port = port;
if (connect(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
error = errno;
@@ -135,7 +109,11 @@ tcp_client(pid_t partner, int secs)
int
main(int argc, char *argv[])
{
+ struct sockaddr_in sin;
pid_t child_pid, parent_pid;
+ int listen_fd;
+ socklen_t len;
+ u_short port;
if (signal(SIGCHLD, SIG_IGN) == SIG_ERR)
err(-1, "signal");
@@ -144,29 +122,96 @@ main(int argc, char *argv[])
* Run the whole thing twice: once, with a short sleep in the client,
* so that we close before time wait runs out, and once with a long
* sleep so that the time wait terminates while the socket is open.
+ * We don't reuse listen sockets between runs.
+ */
+ listen_fd = socket(PF_INET, SOCK_STREAM, 0);
+ if (listen_fd < 0)
+ err(-1, "socket");
+
+ /*
+ * We use the loopback, but let the kernel select a port for the
+ * server socket.
+ */
+ bzero(&sin, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof(sin);
+ sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+ if (bind(listen_fd, (struct sockaddr *)&sin, sizeof(sin)) < 0)
+ err(-1, "bind");
+
+ if (listen(listen_fd, -1) < 0)
+ err(-1, "listen");
+
+ /*
+ * Query the port so that the client can use it.
*/
+ bzero(&sin, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof(sin);
+ len = sizeof(sin);
+ if (getsockname(listen_fd, (struct sockaddr *)&sin, &len) < 0)
+ err(-1, "getsockname");
+ port = sin.sin_port;
+ printf("Using port %d\n", ntohs(port));
+
parent_pid = getpid();
child_pid = fork();
if (child_pid < 0)
err(-1, "fork");
if (child_pid == 0) {
child_pid = getpid();
- tcp_server(child_pid);
+ tcp_server(child_pid, listen_fd);
exit(0);
} else
- tcp_client(parent_pid, 1);
+ tcp_client(parent_pid, port, 1);
(void)kill(child_pid, SIGTERM);
+ close(listen_fd);
sleep(5);
+ /*
+ * Start again, this time long sleep.
+ */
+ listen_fd = socket(PF_INET, SOCK_STREAM, 0);
+ if (listen_fd < 0)
+ err(-1, "socket");
+
+ /*
+ * We use the loopback, but let the kernel select a port for the
+ * server socket.
+ */
+ bzero(&sin, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof(sin);
+ sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+ if (bind(listen_fd, (struct sockaddr *)&sin, sizeof(sin)) < 0)
+ err(-1, "bind");
+
+ if (listen(listen_fd, -1) < 0)
+ err(-1, "listen");
+
+ /*
+ * Query the port so that the client can use it.
+ */
+ bzero(&sin, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof(sin);
+ len = sizeof(sin);
+ if (getsockname(listen_fd, (struct sockaddr *)&sin, &len) < 0)
+ err(-1, "getsockname");
+ port = sin.sin_port;
+ printf("Using port %d\n", ntohs(port));
+
parent_pid = getpid();
child_pid = fork();
if (child_pid < 0)
err(-1, "fork");
if (child_pid == 0) {
child_pid = getpid();
- tcp_server(parent_pid);
+ tcp_server(parent_pid, listen_fd);
} else
- tcp_client(child_pid, 800);
+ tcp_client(child_pid, port, 800);
return (0);
}
diff --git a/tools/regression/netinet/udpconnectjail/udpconnectjail.c b/tools/regression/netinet/udpconnectjail/udpconnectjail.c
index 7151ca4..718836c 100644
--- a/tools/regression/netinet/udpconnectjail/udpconnectjail.c
+++ b/tools/regression/netinet/udpconnectjail/udpconnectjail.c
@@ -77,6 +77,7 @@ main(int argc, __unused char *argv[])
{
struct sockaddr_in sin;
struct jail thejail;
+ struct in_addr ia4;
if (argc != 1)
usage();
@@ -94,12 +95,18 @@ main(int argc, __unused char *argv[])
/*
* Now re-run in a jail.
+ * XXX-BZ should switch to jail_set(2).
*/
+ ia4.s_addr = htonl(INADDR_LOOPBACK);
+
bzero(&thejail, sizeof(thejail));
- thejail.version = 0;
+ thejail.version = JAIL_API_VERSION;
thejail.path = "/";
thejail.hostname = "jail";
- thejail.ip_number = INADDR_LOOPBACK;
+ thejail.jailname = "udpconnectjail";
+ thejail.ip4s = 1;
+ thejail.ip4 = &ia4;
+
if (jail(&thejail) < 0)
errx(-1, "jail: %s", strerror(errno));
test("in jail", &sin);
diff --git a/tools/tools/nanobsd/nanobsd.sh b/tools/tools/nanobsd/nanobsd.sh
index 2d2a4e7..c3e96b3 100644
--- a/tools/tools/nanobsd/nanobsd.sh
+++ b/tools/tools/nanobsd/nanobsd.sh
@@ -418,7 +418,7 @@ populate_slice ( ) (
echo "Creating ${dev} with ${dir} (mounting on ${mnt})"
newfs_part $dev $mnt $lbl
cd ${dir}
- find . -print | grep -Ev '/(CVS|\.svn)' | cpio -Ldumpv ${mnt}
+ find . -print | grep -Ev '/(CVS|\.svn)' | cpio -dumpv ${mnt}
df -i ${mnt}
umount ${mnt}
)
diff --git a/usr.bin/find/main.c b/usr.bin/find/main.c
index 2c11936..d901623 100644
--- a/usr.bin/find/main.c
+++ b/usr.bin/find/main.c
@@ -120,7 +120,7 @@ main(int argc, char *argv[])
break;
case '?':
default:
- break;
+ usage();
}
argc -= optind;
diff --git a/usr.bin/fstat/fuser.1 b/usr.bin/fstat/fuser.1
index a844939..90252f6 100644
--- a/usr.bin/fstat/fuser.1
+++ b/usr.bin/fstat/fuser.1
@@ -130,6 +130,16 @@ The
.Nm
utility is expected to conform to
.St -p1003.1-2004 .
+.Sh HISTORY
+The
+.Nm
+utility appeared in
+.Fx 9.0 .
+.Sh AUTHORS
+The
+.Nm
+utility and this manual page was written by
+.An Stanislav Sedov Aq stas@FreeBSD.org .
.Sh BUGS
Since
.Nm
@@ -141,13 +151,3 @@ interface the report will be limited to filesystems the
.Nm
utility knows about (currently only cd9660, devfs, nfs, ntfs, nwfs, udf,
ufs and zfs).
-.Sh HISTORY
-The
-.Nm
-utility appeared in
-.Fx 9.0 .
-.Sh AUTHORS
-The
-.Nm
-utility and this manual page was written by
-.An Stanislav Sedov Aq stas@FreeBSD.org .
diff --git a/usr.bin/man/man.1 b/usr.bin/man/man.1
index 58f43e5..a9002ec 100644
--- a/usr.bin/man/man.1
+++ b/usr.bin/man/man.1
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 1, 2010
+.Dd June 3, 2011
.Dt MAN 1
.Os
.Sh NAME
@@ -73,8 +73,12 @@ environment variable.
.It Fl P Ar pager
Use specified pager.
Defaults to
+.Ic "less -sR"
+if color support is enabled, or
.Ic "more -s" .
Overrides the
+.Ev MANPAGER
+environment variable, which in turn overrides the
.Ev PAGER
environment variable.
.It Fl S Ar mansect
@@ -283,9 +287,25 @@ Restricts manual sections searched to the specified colon delimited list.
Corresponds to the
.Fl S
option.
-.It Ev PAGER
+.It Ev MANWIDTH
+If set to a numeric value, used as the width manpages should be displayed.
+Otherwise, if set to a special value
+.Dq Li tty ,
+and output is to a terminal,
+the pages may be displayed over the whole width of the screen.
+.It Ev MANCOLOR
+If set, enables color support.
+.It Ev MANPAGER
Program used to display files.
-If unset,
+.Pp
+If unset, and color support is enabled,
+.Ic "less -sR"
+is used.
+.Pp
+If unset, and color support is disabled, then
+.Ev PAGER
+is used.
+If that has no value either,
.Ic "more -s"
is used.
.El
diff --git a/usr.bin/man/man.conf.5 b/usr.bin/man/man.conf.5
index 6326bc1..24f8226 100644
--- a/usr.bin/man/man.conf.5
+++ b/usr.bin/man/man.conf.5
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 1, 2010
+.Dd June 3, 2011
.Os
.Dt MAN.CONF 5
.Sh NAME
@@ -72,7 +72,6 @@ For pages in a given language, overriding the default toolset for
display is supported via the following definitions:
.Bl -tag -offset indent -compact
.It EQN Ns _ Ns Va LANG
-.It COL Ns _ Ns Va LANG
.It NROFF Ns _ Ns Va LANG
.It PIC Ns _ Ns Va LANG
.It TBL Ns _ Ns Va LANG
@@ -112,7 +111,7 @@ with the following contents:
.Bd -literal -offset indent
# Setup Japanese toolset
MANLOCALE ja_JP.eucJP
-EQN_JA /usr/local/bin/gepn
+EQN_JA /usr/local/bin/geqn
PIC_JA /usr/local/bin/gpic
TBL_JA /usr/local/bin/gtbl
NROFF_JA /usr/local/bin/groff -man -dlang=ja_JP.eucJP
diff --git a/usr.bin/man/man.sh b/usr.bin/man/man.sh
index f1c91ee..98749a6 100755
--- a/usr.bin/man/man.sh
+++ b/usr.bin/man/man.sh
@@ -112,7 +112,11 @@ check_man() {
setup_cattool $manpage
decho " Found manpage $manpage"
- if exists "$2" && is_newer $found $manpage; then
+ if [ -n "${use_width}" ]; then
+ # non-standard width
+ unset use_cat
+ decho " Skipping catpage: non-standard page width"
+ elif exists "$2" && is_newer $found $manpage; then
# cat page found and is newer, use that
use_cat=yes
catpage=$found
@@ -275,7 +279,7 @@ man_check_for_so() {
# Usage: man_display_page
# Display either the manpage or catpage depending on the use_cat variable
man_display_page() {
- local EQN COL NROFF PIC TBL TROFF REFER VGRIND
+ local EQN NROFF PIC TBL TROFF REFER VGRIND
local IFS l nroff_dev pipeline preproc_arg tool
# We are called with IFS set to colon. This causes really weird
@@ -290,10 +294,10 @@ man_display_page() {
ret=0
else
if [ $debug -gt 0 ]; then
- decho "Command: $cattool $catpage | $PAGER"
+ decho "Command: $cattool $catpage | $MANPAGER"
ret=0
else
- eval "$cattool $catpage | $PAGER"
+ eval "$cattool $catpage | $MANPAGER"
ret=$?
fi
fi
@@ -343,7 +347,7 @@ man_display_page() {
# Allow language specific calls to override the default
# set of utilities.
l=$(echo $man_lang | tr [:lower:] [:upper:])
- for tool in EQN COL NROFF PIC TBL TROFF REFER VGRIND; do
+ for tool in EQN NROFF PIC TBL TROFF REFER VGRIND; do
eval "$tool=\${${tool}_$l:-\$$tool}"
done
;;
@@ -352,6 +356,14 @@ man_display_page() {
;;
esac
+ if [ -z "$MANCOLOR" ]; then
+ NROFF="$NROFF -P-c"
+ fi
+
+ if [ -n "${use_width}" ]; then
+ NROFF="$NROFF -rLL=${use_width}n -rLT=${use_width}n"
+ fi
+
if [ -n "$MANROFFSEQ" ]; then
set -- -$MANROFFSEQ
while getopts 'egprtv' preproc_arg; do
@@ -360,7 +372,7 @@ man_display_page() {
g) ;; # Ignore for compatability.
p) pipeline="$pipeline | $PIC" ;;
r) pipeline="$pipeline | $REFER" ;;
- t) pipeline="$pipeline | $TBL"; use_col=yes ;;
+ t) pipeline="$pipeline | $TBL" ;;
v) pipeline="$pipeline | $VGRIND" ;;
*) usage ;;
esac
@@ -369,19 +381,12 @@ man_display_page() {
pipeline="${pipeline#" | "}"
else
pipeline="$TBL"
- use_col=yes
fi
if [ -n "$tflag" ]; then
pipeline="$pipeline | $TROFF"
else
- pipeline="$pipeline | $NROFF"
-
- if [ -n "$use_col" ]; then
- pipeline="$pipeline | $COL"
- fi
-
- pipeline="$pipeline | $PAGER"
+ pipeline="$pipeline | $NROFF | $MANPAGER"
fi
if [ $debug -gt 0 ]; then
@@ -483,7 +488,7 @@ man_parse_args() {
while getopts 'M:P:S:adfhkm:op:tw' cmd_arg; do
case "${cmd_arg}" in
M) MANPATH=$OPTARG ;;
- P) PAGER=$OPTARG ;;
+ P) MANPAGER=$OPTARG ;;
S) MANSECT=$OPTARG ;;
a) aflag=aflag ;;
d) debug=$(( $debug + 1 )) ;;
@@ -562,6 +567,35 @@ man_setup() {
build_manpath
man_setup_locale
+ man_setup_width
+}
+
+# Usage: man_setup_width
+# Set up page width.
+man_setup_width() {
+ local sizes
+
+ unset use_width
+ case "$MANWIDTH" in
+ [0-9]*)
+ if [ "$MANWIDTH" -gt 0 2>/dev/null ]; then
+ use_width=$MANWIDTH
+ fi
+ ;;
+ [Tt][Tt][Yy])
+ if { sizes=$($STTY size 0>&3 2>/dev/null); } 3>&1; then
+ set -- $sizes
+ if [ $2 -gt 80 ]; then
+ use_width=$(($2-2))
+ fi
+ fi
+ ;;
+ esac
+ if [ -n "$use_width" ]; then
+ decho "Using non-standard page width: ${use_width}"
+ else
+ decho 'Using standard page width'
+ fi
}
# Usage: man_setup_locale
@@ -667,7 +701,7 @@ parse_file() {
manlocales="$manlocales:$tstr"
;;
MANCONFIG*) decho " MANCONFIG" 3
- trim "${line#MANCONF}"
+ trim "${line#MANCONFIG}"
config_local="$tstr"
;;
# Set variables in the form of FOO_BAR
@@ -778,7 +812,7 @@ search_whatis() {
bad=${bad#\\n}
if [ -n "$good" ]; then
- echo -e "$good" | $PAGER
+ echo -e "$good" | $MANPAGER
fi
if [ -n "$bad" ]; then
@@ -802,13 +836,21 @@ setup_cattool() {
}
# Usage: setup_pager
-# Correctly sets $PAGER
+# Correctly sets $MANPAGER
setup_pager() {
# Setup pager.
- if [ -z "$PAGER" ]; then
- PAGER="more -s"
+ if [ -z "$MANPAGER" ]; then
+ if [ -n "$MANCOLOR" ]; then
+ MANPAGER="less -sR"
+ else
+ if [ -n "$PAGER" ]; then
+ MANPAGER="$PAGER"
+ else
+ MANPAGER="more -s"
+ fi
+ fi
fi
- decho "Using pager: $PAGER"
+ decho "Using pager: $MANPAGER"
}
# Usage: trim string
@@ -891,15 +933,15 @@ do_whatis() {
# User's PATH setting decides on the groff-suite to pick up.
EQN=eqn
-NROFF='groff -S -P-c -Wall -mtty-char -man'
+NROFF='groff -S -P-h -Wall -mtty-char -man'
PIC=pic
REFER=refer
TBL=tbl
-TROFF='groff -S -P-c -man'
+TROFF='groff -S -man'
VGRIND=vgrind
-COL=/usr/bin/col
LOCALE=/usr/bin/locale
+STTY=/bin/stty
SYSCTL=/sbin/sysctl
debug=0
diff --git a/usr.bin/rctl/rctl.8 b/usr.bin/rctl/rctl.8
index a31adac..98c9d4e 100644
--- a/usr.bin/rctl/rctl.8
+++ b/usr.bin/rctl/rctl.8
@@ -82,7 +82,7 @@ Use unit suffixes: Byte, Kilobyte, Megabyte,
Gigabyte, Terabyte and Petabyte.
.It Fl n
Display user IDs numerically rather than converting them to a user name.
-.Pp
+.El
.Sh RULE SYNTAX
Syntax for a rule is subject:subject-id:resource:action=amount/per.
.Pp
diff --git a/usr.bin/tftp/main.c b/usr.bin/tftp/main.c
index 989a5ae..e2954c8 100644
--- a/usr.bin/tftp/main.c
+++ b/usr.bin/tftp/main.c
@@ -155,7 +155,7 @@ static struct cmd cmdtab[] = {
{ "options", setoptions,
"enable or disable RFC2347 style options" },
{ "help", help, "print help information" },
- { "packetdrop", setpacketdrop, "artifical packetloss feature" },
+ { "packetdrop", setpacketdrop, "artificial packetloss feature" },
{ "?", help, "print help information" },
{ NULL, NULL, NULL }
};
@@ -955,7 +955,7 @@ setblocksize(int argc, char *argv[])
if (!options_rfc_enabled)
printf("RFC2347 style options are not enabled "
- "(but proceding anyway)\n");
+ "(but proceeding anyway)\n");
if (argc != 1) {
int size = atoi(argv[1]);
@@ -993,7 +993,7 @@ setblocksize2(int argc, char *argv[])
if (!options_rfc_enabled || !options_extra_enabled)
printf(
"RFC2347 style or non-RFC defined options are not enabled "
- "(but proceding anyway)\n");
+ "(but proceeding anyway)\n");
if (argc != 1) {
int size = atoi(argv[1]);
diff --git a/usr.bin/top/machine.c b/usr.bin/top/machine.c
index f98f64e..4c55682 100644
--- a/usr.bin/top/machine.c
+++ b/usr.bin/top/machine.c
@@ -624,6 +624,7 @@ get_process_info(struct system_info *si, struct process_select *sel,
int show_system;
int show_uid;
int show_command;
+ int show_kidle;
/*
* Save the previous process info.
@@ -664,6 +665,7 @@ get_process_info(struct system_info *si, struct process_select *sel,
show_system = sel->system;
show_uid = sel->uid != -1;
show_command = sel->command != NULL;
+ show_kidle = sel->kidle;
/* count up process states and get pointers to interesting procs */
total_procs = 0;
@@ -705,6 +707,11 @@ get_process_info(struct system_info *si, struct process_select *sel,
/* skip idle or non-running processes */
continue;
+ if (displaymode == DISP_CPU && !show_kidle &&
+ pp->ki_tdflags & TDF_IDLETD)
+ /* skip kernel idle process */
+ continue;
+
if (displaymode == DISP_IO && !show_idle && p_io == 0)
/* skip processes that aren't doing I/O */
continue;
diff --git a/usr.bin/top/top.local.1 b/usr.bin/top/top.local.1
index d7705e8..015b969 100644
--- a/usr.bin/top/top.local.1
+++ b/usr.bin/top/top.local.1
@@ -1,10 +1,6 @@
.\" $FreeBSD$
.SH "FreeBSD NOTES"
-.SH DISPLAY OF THREADS
-The '-H' option will toggle the display of kernel visible thread contexts.
-At runtime the 'H' key will toggle this mode. The default is OFF.
-
.SH DESCRIPTION OF MEMORY
Mem: 9220K Active, 1M Inact, 3284K Wired, 1M Cache, 2M Buf, 1320K Free
Swap: 91M Total, 79M Free, 13% Inuse, 80K In, 104K Out
diff --git a/usr.sbin/bsdinstall/scripts/Makefile b/usr.sbin/bsdinstall/scripts/Makefile
index 8ad6744..e32fda6 100644
--- a/usr.sbin/bsdinstall/scripts/Makefile
+++ b/usr.sbin/bsdinstall/scripts/Makefile
@@ -1,7 +1,8 @@
# $FreeBSD$
SCRIPTS= auto adduser checksum config hostname jail keymap mirrorselect \
- mount netconfig rootpass services time umount wlanconfig
+ mount netconfig netconfig_ipv4 netconfig_ipv6 rootpass services \
+ time umount wlanconfig
BINDIR= /usr/libexec/bsdinstall
NO_MAN= true
diff --git a/usr.sbin/bsdinstall/scripts/auto b/usr.sbin/bsdinstall/scripts/auto
index 6a0e9b5..bdc5fc4 100755
--- a/usr.sbin/bsdinstall/scripts/auto
+++ b/usr.sbin/bsdinstall/scripts/auto
@@ -199,7 +199,7 @@ finalconfig() {
clear
echo This shell is operating in a chroot in the new system. \
When finished making configuration changes, type \"exit\".
- chroot "$BSDINSTALL_CHROOT" /bin/sh
+ chroot "$BSDINSTALL_CHROOT" /bin/sh 2>&1
# Don't hose local rc.conf changes
cp $BSDINSTALL_CHROOT/etc/rc.conf $BSDINSTALL_TMPETC/rc.conf.manual
finalconfig
diff --git a/usr.sbin/bsdinstall/scripts/netconfig b/usr.sbin/bsdinstall/scripts/netconfig
index 0374d12..b78e330 100755
--- a/usr.sbin/bsdinstall/scripts/netconfig
+++ b/usr.sbin/bsdinstall/scripts/netconfig
@@ -2,6 +2,11 @@
#-
# Copyright (c) 2011 Nathan Whitehorn
# All rights reserved.
+# Copyright (c) 2011 The FreeBSD Foundation
+# All rights reserved.
+#
+# Portions of this software were developed by Bjoern Zeeb
+# under sponsorship from the FreeBSD Foundation.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -36,8 +41,6 @@ DIALOG_TAGS=""
: ${DIALOG_ITEM_HELP=4}
: ${DIALOG_ESC=255}
-echo -n > $BSDINSTALL_TMPETC/rc.conf.net
-
for IF in `ifconfig -l`; do
test "$IF" = "lo0" && continue
(ifconfig -g wlan | egrep -wq $IF) && continue
@@ -51,12 +54,14 @@ INTERFACE=`echo $DIALOG_TAGS | xargs dialog --backtitle 'FreeBSD Installer' --ti
if [ $? -eq $DIALOG_CANCEL ]; then exit 1; fi
exec 3>&-
+: > $BSDINSTALL_TMPETC/._rc.conf.net
+
# Do a dirty check to see if this a wireless interface -- there should be a
# better way
IFCONFIG_PREFIX=""
if ifconfig $INTERFACE | grep -q 'media: IEEE 802.11 Wireless'; then
NEXT_WLAN_IFACE=wlan0 # XXX
- echo wlans_$INTERFACE=\"$NEXT_WLAN_IFACE\" >> $BSDINSTALL_TMPETC/rc.conf.net
+ echo wlans_$INTERFACE=\"$NEXT_WLAN_IFACE\" >> $BSDINSTALL_TMPETC/._rc.conf.net
IFCONFIG_PREFIX="WPA "
if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then
ifconfig $NEXT_WLAN_IFACE create wlandev $INTERFACE
@@ -66,56 +71,129 @@ if ifconfig $INTERFACE | grep -q 'media: IEEE 802.11 Wireless'; then
INTERFACE="$NEXT_WLAN_IFACE"
fi
-dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' --yesno 'Would you like to use DHCP to configure this interface?' 0 0
-if [ $? -eq $DIALOG_OK ]; then
- echo ifconfig_$INTERFACE=\"${IFCONFIG_PREFIX}DHCP\" >> $BSDINSTALL_TMPETC/rc.conf.net
+IPV6_AVAIL=0
+IPV4_AVAIL=0
+sysctl -N kern.features.inet6 > /dev/null 2>&1
+case $? in
+0) IPV6_AVAIL=1 ;;
+esac
+sysctl -N kern.features.inet > /dev/null 2>&1
+case $? in
+0) IPV4_AVAIL=1 ;;
+esac
- if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then
- dialog --backtitle 'FreeBSD Installer' --infobox "Acquiring DHCP lease..." 0 0
- dhclient $INTERFACE 2>> $BSDINSTALL_LOG
- if [ $? -ne 0 ]; then
- dialog --backtitle 'FreeBSD Installer' --msgbox "DHCP lease acquisition failed." 0 0
- exec $0
- fi
+if [ ${IPV4_AVAIL} -eq 1 ]; then
+ dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' \
+ --yesno 'Would you like to configure IPv4 for this interface?' 0 0
+ if [ $? -eq $DIALOG_OK ]; then
+ bsdinstall netconfig_ipv4 ${INTERFACE} "${IFCONFIG_PREFIX}" || \
+ exec $0
+ else
+ IPV4_AVAIL=0
+ fi
+fi
+# In case wlanconfig left an option and we do not support IPv4 we need to write
+# it out on its own. We cannot write it out with IPv6 as that suffix.
+if [ ${IPV4_AVAIL} -eq 0 -a -n ${IFCONFIG_PREFIX} ]; then
+ echo ifconfig_${INTERFACE}=\"${IFCONFIG_PREFIX}\" >> $BSDINSTALL_TMPETC/._rc.conf.net
+fi
+if [ ${IPV6_AVAIL} -eq 1 ]; then
+ dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' \
+ --yesno 'Would you like to configure IPv6 for this interface?' 0 0
+ if [ $? -eq $DIALOG_OK ]; then
+ bsdinstall netconfig_ipv6 ${INTERFACE} || exec $0
+ else
+ IPV6_AVAIL=0
fi
- exit 0
fi
-IP_ADDRESS=`ifconfig $INTERFACE inet | awk '/inet/ {printf("%s\n", $2); }'`
-NETMASK=`ifconfig $INTERFACE inet | awk '/inet/ {printf("%s\n", $4); }'`
-ROUTER=`netstat -rn -f inet | awk '/default/ {printf("%s\n", $2);}'`
+SEARCH=""
+IP4_1=""
+IP4_2=""
+IP6_1=""
+IP6_2=""
+while read key value; do
+ case "${key}" in
+ search) SEARCH="${value}" ;;
+ nameserver) # is more trick as we have to distinguish v4 and v6
+ case "${value}" in
+ [0-9]*\.[0-9]*\.[0-9]*\.[0-9]*)
+ if [ -z "${IP4_1}" ] ; then
+ IP4_1="${value}"
+ elif [ -z "${IP4_2}" ]; then
+ IP4_2="${value}"
+ fi
+ ;;
+ [0-9A-Fa-f:]*:*)
+ if [ -z "${IP6_1}" ] ; then
+ IP6_1="${value}"
+ elif [ -z "${IP6_2}" ]; then
+ IP6_2="${value}"
+ fi
+ ;;
+ esac
+ ;;
+ # ignore others
+ esac
+done < ${BSDINSTALL_TMPETC}/resolv.conf
+
+RESOLV=""
+if [ ${IPV6_AVAIL} -eq 1 -a ${IPV4_AVAIL} -eq 1 ]; then
+ RESOLV="
+ 'Search' 1 0 \"${SEARCH}\" 1 16 50 0 0
+ 'Nameserver' 2 0 \"Nameserver\" 2 16 50 0 2
+ 'IPv6 DNS #1' 2 0 \"${IP6_1}\" 2 16 50 0 0
+ 'IPv6 DNS #2' 3 0 \"${IP6_2}\" 3 16 50 0 0
+ 'IPv4 DNS #1' 4 0 \"${IP4_1}\" 4 16 16 0 0
+ 'IPv4 DNS #2' 5 0 \"${IP4_2}\" 5 16 16 0 0"
+elif [ ${IPV6_AVAIL} -eq 1 ]; then
+ RESOLV="
+ 'Search' 1 0 \"${SEARCH}\" 1 16 50 0 0
+ 'Nameserver' 2 0 \"Nameserver\" 2 16 50 0 2
+ 'IPv6 DNS #1' 2 0 \"${IP6_1}\" 2 16 50 0 0
+ 'IPv6 DNS #2' 3 0 \"${IP6_2}\" 3 16 50 0 0"
+elif [ ${IPV4_AVAIL} -eq 1 ]; then
+ RESOLV="
+ 'Search' 1 0 \"${SEARCH}\" 1 16 50 0 0
+ 'Nameserver' 2 0 \"Nameserver\" 2 16 50 0 2
+ 'IPv4 DNS #1' 2 0 \"${IP4_1}\" 2 16 16 0 0
+ 'IPv4 DNS #2' 3 0 \"${IP4_2}\" 3 16 16 0 0"
+else
+ exit 0
+fi
exec 3>&1
-IF_CONFIG=$(dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' --form 'Static Network Interface Configuration' 0 0 0 \
- 'IP Address' 1 0 "$IP_ADDRESS" 1 20 16 0 \
- 'Subnet Mask' 2 0 "$NETMASK" 2 20 16 0 \
- 'Default Router' 3 0 "$ROUTER" 3 20 16 0 \
- \
- 'Nameserver' 5 0 "" 5 20 16 0 \
- 'Search Domain' 6 0 "" 6 20 20 0 \
+RESOLV=$(echo "${RESOLV}" | xargs dialog --backtitle 'FreeBSD Installer' \
+ --title 'Network Configuration' \
+ --mixedform 'Resovler Configuration' 0 0 0 \
2>&1 1>&3)
if [ $? -eq $DIALOG_CANCEL ]; then exec $0; fi
exec 3>&-
-echo $INTERFACE $IF_CONFIG |
- awk -v prefix="$IFCONFIG_PREFIX" '{
- printf("ifconfig_%s=\"%s%s netmask %s\"\n", $1, prefix, $2, $3);
- printf("defaultrouter=\"%s\"\n", $4);
- }' >> $BSDINSTALL_TMPETC/rc.conf.net
-
-if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then
- . $BSDINSTALL_TMPETC/rc.conf.net
- ifconfig $INTERFACE `eval echo \\\$ifconfig_$INTERFACE`
- route delete default
- route add default $defaultrouter
-fi
-
-
-echo $IF_CONFIG |
- awk '{
- if ($4 != "")
- printf("nameserver %s\n", $4);
- if ($5 != "")
- printf("search %s\n", $5);
- }' > $BSDINSTALL_TMPETC/resolv.conf
+echo ${RESOLV} | tr ' ' '\n' | \
+awk '
+BEGIN {
+ search=-1;
+}
+{
+ if (/^[[:space:]]+$/) {
+ next;
+ }
+ if (/^Nameserver$/) {
+ printf "\n";
+ search=0;
+ next;
+ }
+ if (search == -1) {
+ printf "search ";
+ search=1;
+ }
+ if (search > 0) {
+ printf "%s%s", (search > 1) ? " " : "", $1;
+ search++;
+ next;
+ }
+ printf "nameserver %s\n", $1;
+}' > ${BSDINSTALL_TMPETC}/resolv.conf
+mv $BSDINSTALL_TMPETC/._rc.conf.net $BSDINSTALL_TMPETC/rc.conf.net
diff --git a/usr.sbin/bsdinstall/scripts/netconfig_ipv4 b/usr.sbin/bsdinstall/scripts/netconfig_ipv4
new file mode 100755
index 0000000..72dc0ee
--- /dev/null
+++ b/usr.sbin/bsdinstall/scripts/netconfig_ipv4
@@ -0,0 +1,85 @@
+#!/bin/sh
+#-
+# Copyright (c) 2011 Nathan Whitehorn
+# 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$
+
+: ${DIALOG_OK=0}
+: ${DIALOG_CANCEL=1}
+: ${DIALOG_HELP=2}
+: ${DIALOG_EXTRA=3}
+: ${DIALOG_ITEM_HELP=4}
+: ${DIALOG_ESC=255}
+
+INTERFACE=$1
+IFCONFIG_PREFIX="$2"
+case "${INTERFACE}" in
+"") dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' \
+ --msgbox 'No interface specified for IPv4 configuration.' 0 0
+ exit 1
+ ;;
+esac
+
+dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' --yesno 'Would you like to use DHCP to configure this interface?' 0 0
+if [ $? -eq $DIALOG_OK ]; then
+ echo ifconfig_$INTERFACE=\"${IFCONFIG_PREFIX}DHCP\" >> $BSDINSTALL_TMPETC/._rc.conf.net
+
+ if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then
+ dialog --backtitle 'FreeBSD Installer' --infobox "Acquiring DHCP lease..." 0 0
+ dhclient $INTERFACE 2>> $BSDINSTALL_LOG
+ if [ $? -ne 0 ]; then
+ dialog --backtitle 'FreeBSD Installer' --msgbox "DHCP lease acquisition failed." 0 0
+ exec $0 ${INTERFACE} "${IFCONFIG_PREFIX}"
+ fi
+ fi
+ exit 0
+fi
+
+IP_ADDRESS=`ifconfig $INTERFACE inet | awk '/inet/ {printf("%s\n", $2); }'`
+NETMASK=`ifconfig $INTERFACE inet | awk '/inet/ {printf("%s\n", $4); }'`
+ROUTER=`netstat -rn -f inet | awk '/default/ {printf("%s\n", $2);}'`
+
+exec 3>&1
+IF_CONFIG=$(dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' --form 'Static Network Interface Configuration' 0 0 0 \
+ 'IP Address' 1 0 "$IP_ADDRESS" 1 20 16 0 \
+ 'Subnet Mask' 2 0 "$NETMASK" 2 20 16 0 \
+ 'Default Router' 3 0 "$ROUTER" 3 20 16 0 \
+2>&1 1>&3)
+if [ $? -eq $DIALOG_CANCEL ]; then exit 1; fi
+exec 3>&-
+
+echo $INTERFACE $IF_CONFIG |
+ awk -v prefix="$IFCONFIG_PREFIX" '{
+ printf("ifconfig_%s=\"%s inet %s netmask %s\"\n", $1, prefix, $2, $3);
+ printf("defaultrouter=\"%s\"\n", $4);
+ }' >> $BSDINSTALL_TMPETC/._rc.conf.net
+
+if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then
+ . $BSDINSTALL_TMPETC/._rc.conf.net
+ ifconfig $INTERFACE inet `eval echo \\\$ifconfig_$INTERFACE`
+ route delete -inet default
+ route add -inet default $defaultrouter
+fi
+
diff --git a/usr.sbin/bsdinstall/scripts/netconfig_ipv6 b/usr.sbin/bsdinstall/scripts/netconfig_ipv6
new file mode 100755
index 0000000..70bd203
--- /dev/null
+++ b/usr.sbin/bsdinstall/scripts/netconfig_ipv6
@@ -0,0 +1,149 @@
+#!/bin/sh
+#-
+# Copyright (c) 2011 Nathan Whitehorn
+# All rights reserved.
+# Copyright (c) 2011 The FreeBSD Foundation
+# All rights reserved.
+#
+# Portions of this software were developed by Bjoern Zeeb
+# under sponsorship from the FreeBSD Foundation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+
+#
+# TODO:
+# - Add -R /sbin/resolvconf to rtsol once support is in tree.
+# - Add DHCPv6 support once FreeBSD ships with it.
+#
+
+: ${DIALOG_OK=0}
+: ${DIALOG_CANCEL=1}
+: ${DIALOG_HELP=2}
+: ${DIALOG_EXTRA=3}
+: ${DIALOG_ITEM_HELP=4}
+: ${DIALOG_ESC=255}
+
+INTERFACE=$1
+case "${INTERFACE}" in
+"") dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' \
+ --msgbox 'No interface specified for IPv6 configuration.' 0 0
+ exit 1
+ ;;
+esac
+
+AGAIN=""
+while : ; do
+ MSG="Would you like to try stateless address autoconfiguration (SLAAC)${AGAIN}?"
+ dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' \
+ --yesno "${MSG}" 0 0
+ if [ $? -eq $DIALOG_OK ]; then
+ if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then
+ dialog --backtitle 'FreeBSD Installer' \
+ --infobox "Sending Router Solicitation ..." 0 0
+ ifconfig ${INTERFACE} inet6 -ifdisabled accept_rtadv up
+ rtsol -F $INTERFACE 2>> $BSDINSTALL_LOG
+ if [ $? -ne 0 ]; then
+ dialog --backtitle 'FreeBSD Installer' --msgbox "SLAAC failed." 0 0
+ AGAIN=" again"
+ continue
+ fi
+ fi
+ echo ifconfig_${INTERFACE}_ipv6=\"inet6 accept_rtadv\" >> $BSDINSTALL_TMPETC/._rc.conf.net
+ exit 0
+ else
+ break
+ fi
+done
+
+ROUTER6=`netstat -Wrn -f inet6 | awk '/default/ {printf("%s\n", $2);}'`
+ADDRS=`ifconfig ${INTERFACE} inet6 | \
+awk -v dfr="${ROUTER6}" '
+BEGIN {
+ n=0;
+}
+{
+ if (/inet6/) {
+ if (match($2, "^fe80:")) { next; };
+ # For the moment ignore all but the first address; it might confuse the user.
+ if (n > 0) { next; };
+ n++;
+ printf "\"IPv6 Address\" %d 0 \"%s/%s\" %d 16 50 0 0 ", n, $2, $4, n;
+ }
+}
+END {
+ if (n == 0) {
+ n++;
+ printf "\"IPv6 Address\" %d 0 \"\" %d 16 50 0 0 ", n, n;
+ }
+ n++;
+ # Nasty trick adding a (hidden, same y) read-only field as a marker
+ # to separate interface address(es) from the default router.
+ printf "\"Default Router\" %d 0 \"%s\" %d 16 50 0 2 ", n, "DefaultRouter", n;
+ printf "\"Default Router\" %d 0 \"%s\" %d 16 50 0 0 ", n, dfr, n;
+}'`
+
+exec 3>&1
+IF_CONFIG=$(echo ${ADDRS} | xargs dialog --backtitle 'FreeBSD Installer' \
+ --title 'Network Configuration' \
+ --mixedform 'Static IPv6 Network Interface Configuration' 0 0 0 \
+2>&1 1>&3)
+if [ $? -eq $DIALOG_CANCEL ]; then exit 1; fi
+exec 3>&-
+
+echo ${IF_CONFIG} | tr ' ' '\n' | \
+awk -v iface="${INTERFACE}" '
+BEGIN {
+ dfr=0;
+ count=0;
+}
+{
+ if (/^[[:space:]]+$/) {
+ next;
+ }
+ if (/DefaultRouter/) {
+ dfr=1;
+ next;
+ }
+ if (dfr == 1) {
+ printf("ipv6_defaultrouter=\"%s\"\n", $1);
+ next;
+ }
+ if (count > 0) {
+ # Ignore all but the first IP address for now.
+ next;
+ }
+ count++;
+ if (!match($1, "/")) {
+ sub("$", "/64", $1);
+ }
+ printf("ifconfig_%s_ipv6=\"inet6 %s\"\n", iface, $1);
+}' >> $BSDINSTALL_TMPETC/._rc.conf.net
+
+if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then
+ . $BSDINSTALL_TMPETC/._rc.conf.net
+ ifconfig ${INTERFACE} `eval echo \\\$ifconfig_${INTERFACE}_ipv6`
+ route delete default
+ route add default ${ipv6_defaultrouter}
+fi
+
diff --git a/usr.sbin/jail/Makefile b/usr.sbin/jail/Makefile
index de35dcf..52d237b 100644
--- a/usr.sbin/jail/Makefile
+++ b/usr.sbin/jail/Makefile
@@ -10,5 +10,8 @@ LDADD= -ljail -lutil
.if ${MK_INET6_SUPPORT} != "no"
CFLAGS+= -DINET6
.endif
+.if ${MK_INET_SUPPORT} != "no"
+CFLAGS+= -DINET
+.endif
.include <bsd.prog.mk>
diff --git a/usr.sbin/jail/jail.c b/usr.sbin/jail/jail.c
index 0722bfd..fc4f71c 100644
--- a/usr.sbin/jail/jail.c
+++ b/usr.sbin/jail/jail.c
@@ -54,12 +54,18 @@ static struct jailparam *params;
static char **param_values;
static int nparams;
-static char *ip4_addr;
#ifdef INET6
+static int ip6_ok;
static char *ip6_addr;
#endif
+#ifdef INET
+static int ip4_ok;
+static char *ip4_addr;
+#endif
+#if defined(INET6) || defined(INET)
static void add_ip_addr(char **addrp, char *newaddr);
+#endif
#ifdef INET6
static void add_ip_addr46(char *newaddr);
#endif
@@ -194,6 +200,13 @@ main(int argc, char **argv)
if (uflag)
GET_USER_INFO;
+#ifdef INET6
+ ip6_ok = feature_present("inet6");
+#endif
+#ifdef INET
+ ip4_ok = feature_present("inet");
+#endif
+
if (jailname)
set_param("name", jailname);
if (securelevel)
@@ -207,10 +220,12 @@ main(int argc, char **argv)
break;
}
if (hflag) {
+#ifdef INET
if (!strncmp(argv[i], "ip4.addr=", 9)) {
add_ip_addr(&ip4_addr, argv[i] + 9);
break;
}
+#endif
#ifdef INET6
if (!strncmp(argv[i], "ip6.addr=", 9)) {
add_ip_addr(&ip6_addr, argv[i] + 9);
@@ -231,12 +246,14 @@ main(int argc, char **argv)
set_param("host.hostname", argv[1]);
if (hflag)
add_ip_addrinfo(0, argv[1]);
+#if defined(INET6) || defined(INET)
if (argv[2][0] != '\0')
#ifdef INET6
add_ip_addr46(argv[2]);
#else
add_ip_addr(&ip4_addr, argv[2]);
#endif
+#endif
cmdarg = 3;
/* Emulate the defaults from security.jail.* sysctls */
sysvallen = sizeof(sysval);
@@ -259,8 +276,10 @@ main(int argc, char **argv)
}
}
}
+#ifdef INET
if (ip4_addr != NULL)
set_param("ip4.addr", ip4_addr);
+#endif
#ifdef INET6
if (ip6_addr != NULL)
set_param("ip6.addr", ip6_addr);
@@ -297,14 +316,19 @@ main(int argc, char **argv)
for (i = 0; i < nparams; i++)
if (!strcmp(params[i].jp_name, "path"))
break;
-#ifdef INET6
+#if defined(INET6) && defined(INET)
fprintf(fp, "%d\t%s\t%s\t%s%s%s\t%s\n",
jid, i < nparams
? (char *)params[i].jp_value : argv[0],
argv[1], ip4_addr ? ip4_addr : "",
ip4_addr && ip4_addr[0] && ip6_addr && ip6_addr[0]
? "," : "", ip6_addr ? ip6_addr : "", argv[3]);
-#else
+#elif defined(INET6)
+ fprintf(fp, "%d\t%s\t%s\t%s\t%s\n",
+ jid, i < nparams
+ ? (char *)params[i].jp_value : argv[0],
+ argv[1], ip6_addr ? ip6_addr : "", argv[3]);
+#elif defined(INET)
fprintf(fp, "%d\t%s\t%s\t%s\t%s\n",
jid, i < nparams
? (char *)params[i].jp_value : argv[0],
@@ -348,6 +372,7 @@ main(int argc, char **argv)
err(1, "execvp: %s", argv[cmdarg]);
}
+#if defined(INET6) || defined(INET)
static void
add_ip_addr(char **addrp, char *value)
{
@@ -368,6 +393,7 @@ add_ip_addr(char **addrp, char *value)
*addrp = addr;
}
}
+#endif
#ifdef INET6
static void
@@ -391,23 +417,24 @@ static void
add_ip_addrinfo(int ai_flags, char *value)
{
struct addrinfo hints, *ai0, *ai;
- struct in_addr addr4;
- size_t size;
- int error, ip4ok;
- int mib[4];
+ int error;
+#ifdef INET
char avalue4[INET_ADDRSTRLEN];
+ struct in_addr addr4;
+#endif
#ifdef INET6
- struct in6_addr addr6;
- int ip6ok;
char avalue6[INET6_ADDRSTRLEN];
+ struct in6_addr addr6;
#endif
/* Look up the hostname (or get the address) */
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = SOCK_STREAM;
-#ifdef INET6
+#if defined(INET6) && defined(INET)
hints.ai_family = PF_UNSPEC;
-#else
+#elif defined(INET6)
+ hints.ai_family = PF_INET6;
+#elif defined(INET)
hints.ai_family = PF_INET;
#endif
hints.ai_flags = ai_flags;
@@ -415,32 +442,12 @@ add_ip_addrinfo(int ai_flags, char *value)
if (error != 0)
errx(1, "hostname %s: %s", value, gai_strerror(error));
- /*
- * Silently ignore unsupported address families from DNS lookups.
- * But if this is a numeric address, let the kernel give the error.
- */
- if (ai_flags & AI_NUMERICHOST)
- ip4ok =
-#ifdef INET6
- ip6ok =
-#endif
- 1;
- else {
- size = 4;
- ip4ok = (sysctlnametomib("security.jail.param.ip4", mib,
- &size) == 0);
-#ifdef INET6
- size = 4;
- ip6ok = (sysctlnametomib("security.jail.param.ip6", mib,
- &size) == 0);
-#endif
- }
-
/* Convert the addresses to ASCII so set_param can convert them back. */
for (ai = ai0; ai; ai = ai->ai_next)
switch (ai->ai_family) {
+#ifdef INET
case AF_INET:
- if (!ip4ok)
+ if (!ip4_ok && (ai_flags & AI_NUMERICHOST) == 0)
break;
memcpy(&addr4, &((struct sockaddr_in *)
(void *)ai->ai_addr)->sin_addr, sizeof(addr4));
@@ -449,9 +456,10 @@ add_ip_addrinfo(int ai_flags, char *value)
err(1, "inet_ntop");
add_ip_addr(&ip4_addr, avalue4);
break;
+#endif
#ifdef INET6
case AF_INET6:
- if (!ip6ok)
+ if (!ip6_ok && (ai_flags & AI_NUMERICHOST) == 0)
break;
memcpy(&addr6, &((struct sockaddr_in6 *)
(void *)ai->ai_addr)->sin6_addr, sizeof(addr6));
diff --git a/usr.sbin/jls/Makefile b/usr.sbin/jls/Makefile
index e1157af..b297cc4 100644
--- a/usr.sbin/jls/Makefile
+++ b/usr.sbin/jls/Makefile
@@ -1,8 +1,17 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
PROG= jls
MAN= jls.8
DPADD= ${LIBJAIL}
LDADD= -ljail
+.if ${MK_INET6_SUPPORT} != "no"
+CFLAGS+= -DINET6
+.endif
+.if ${MK_INET_SUPPORT} != "no"
+CFLAGS+= -DINET
+.endif
+
.include <bsd.prog.mk>
diff --git a/usr.sbin/jls/jls.c b/usr.sbin/jls/jls.c
index 2c1655b..14aa6af 100644
--- a/usr.sbin/jls/jls.c
+++ b/usr.sbin/jls/jls.c
@@ -59,6 +59,12 @@ __FBSDID("$FreeBSD$");
static struct jailparam *params;
static int *param_parent;
static int nparams;
+#ifdef INET6
+static int ip6_ok;
+#endif
+#ifdef INET
+static int ip4_ok;
+#endif
static int add_param(const char *name, void *value, size_t valuelen,
struct jailparam *source, unsigned flags);
@@ -112,6 +118,13 @@ main(int argc, char **argv)
errx(1, "usage: jls [-dhnqv] [-j jail] [param ...]");
}
+#ifdef INET6
+ ip6_ok = feature_present("inet6");
+#endif
+#ifdef INET
+ ip4_ok = feature_present("inet");
+#endif
+
/* Add the parameters to print. */
if (optind == argc) {
if (pflags & (PRINT_HEADER | PRINT_NAMEVAL))
@@ -124,13 +137,24 @@ main(int argc, char **argv)
add_param("name", NULL, (size_t)0, NULL, JP_USER);
add_param("dying", NULL, (size_t)0, NULL, JP_USER);
add_param("cpuset.id", NULL, (size_t)0, NULL, JP_USER);
- add_param("ip4.addr", NULL, (size_t)0, NULL, JP_USER);
- add_param("ip6.addr", NULL, (size_t)0, NULL,
- JP_USER | JP_OPT);
+#ifdef INET
+ if (ip4_ok)
+ add_param("ip4.addr", NULL, (size_t)0, NULL,
+ JP_USER);
+#endif
+#ifdef INET6
+ if (ip6_ok)
+ add_param("ip6.addr", NULL, (size_t)0, NULL,
+ JP_USER | JP_OPT);
+#endif
} else {
pflags |= PRINT_DEFAULT;
add_param("jid", NULL, (size_t)0, NULL, JP_USER);
- add_param("ip4.addr", NULL, (size_t)0, NULL, JP_USER);
+#ifdef INET
+ if (ip4_ok)
+ add_param("ip4.addr", NULL, (size_t)0, NULL,
+ JP_USER);
+#endif
add_param("host.hostname", NULL, (size_t)0, NULL,
JP_USER);
add_param("path", NULL, (size_t)0, NULL, JP_USER);
@@ -327,7 +351,7 @@ print_jail(int pflags, int jflags)
{
char *nname;
char **param_values;
- int i, ai, jid, count, spc;
+ int i, ai, jid, count, n, spc;
char ipbuf[INET6_ADDRSTRLEN];
jid = jailparam_get(params, nparams, jflags);
@@ -345,31 +369,45 @@ print_jail(int pflags, int jflags)
*(int *)params[4].jp_value ? "DYING" : "ACTIVE",
"",
*(int *)params[5].jp_value);
- count = params[6].jp_valuelen / sizeof(struct in_addr);
- for (ai = 0; ai < count; ai++)
- if (inet_ntop(AF_INET,
- &((struct in_addr *)params[6].jp_value)[ai],
- ipbuf, sizeof(ipbuf)) == NULL)
- err(1, "inet_ntop");
- else
- printf("%6s %-15.15s\n", "", ipbuf);
- if (!strcmp(params[7].jp_name, "ip6.addr")) {
- count = params[7].jp_valuelen / sizeof(struct in6_addr);
+ n = 6;
+#ifdef INET
+ if (ip4_ok && !strcmp(params[n].jp_name, "ip.addr")) {
+ count = params[n].jp_valuelen / sizeof(struct in_addr);
+ for (ai = 0; ai < count; ai++)
+ if (inet_ntop(AF_INET,
+ &((struct in_addr *)params[n].jp_value)[ai],
+ ipbuf, sizeof(ipbuf)) == NULL)
+ err(1, "inet_ntop");
+ else
+ printf("%6s %-15.15s\n", "", ipbuf);
+ n++;
+ }
+#endif
+#ifdef INET6
+ if (ip6_ok && !strcmp(params[n].jp_name, "ip6.addr")) {
+ count = params[n].jp_valuelen / sizeof(struct in6_addr);
for (ai = 0; ai < count; ai++)
if (inet_ntop(AF_INET6,
- &((struct in6_addr *)params[7].jp_value)[ai],
+ &((struct in6_addr *)
+ params[n].jp_value)[ai],
ipbuf, sizeof(ipbuf)) == NULL)
err(1, "inet_ntop");
else
printf("%6s %s\n", "", ipbuf);
+ n++;
}
+#endif
} else if (pflags & PRINT_DEFAULT)
printf("%6d %-15.15s %-29.29s %.74s\n",
*(int *)params[0].jp_value,
- params[1].jp_valuelen == 0 ? "-"
+#ifdef INET
+ (!ip4_ok || params[1].jp_valuelen == 0) ? "-"
: inet_ntoa(*(struct in_addr *)params[1].jp_value),
- (char *)params[2].jp_value,
- (char *)params[3].jp_value);
+#else
+ "-"
+#endif
+ (char *)params[2-!ip4_ok].jp_value,
+ (char *)params[3-!ip4_ok].jp_value);
else {
param_values = alloca(nparams * sizeof(*param_values));
for (i = 0; i < nparams; i++) {
diff --git a/usr.sbin/kbdmap/kbdmap.c b/usr.sbin/kbdmap/kbdmap.c
index 93c5a08..c993389 100644
--- a/usr.sbin/kbdmap/kbdmap.c
+++ b/usr.sbin/kbdmap/kbdmap.c
@@ -226,10 +226,10 @@ get_font(void)
}
}
}
+ fclose(fp);
} else
fprintf(stderr, "Could not open %s for reading\n", sysconfig);
- fclose(fp);
return fnt;
}
diff --git a/usr.sbin/mfiutil/mfi_evt.c b/usr.sbin/mfiutil/mfi_evt.c
index b9288d8..a8a8775 100644
--- a/usr.sbin/mfiutil/mfi_evt.c
+++ b/usr.sbin/mfiutil/mfi_evt.c
@@ -362,8 +362,8 @@ mfi_decode_evt(int fd, struct mfi_evt_detail *detail, int verbose)
{
printf("%5d (%s/%s/%s) - ", detail->seq, format_timestamp(detail->time),
- format_locale(detail->class.members.locale),
- format_class(detail->class.members.class));
+ format_locale(detail->evt_class.members.locale),
+ format_class(detail->evt_class.members.evt_class));
switch (detail->arg_type) {
case MR_EVT_ARGS_NONE:
break;
@@ -557,7 +557,7 @@ show_events(int ac, char **av)
num_events = 15;
filter.members.reserved = 0;
filter.members.locale = MFI_EVT_LOCALE_ALL;
- filter.members.class = MFI_EVT_CLASS_WARNING;
+ filter.members.evt_class = MFI_EVT_CLASS_WARNING;
start = info.boot_seq_num;
stop = info.newest_seq_num;
verbose = 0;
@@ -567,7 +567,7 @@ show_events(int ac, char **av)
while ((ch = getopt(ac, av, "c:l:n:v")) != -1) {
switch (ch) {
case 'c':
- if (parse_class(optarg, &filter.members.class) < 0) {
+ if (parse_class(optarg, &filter.members.evt_class) < 0) {
error = errno;
warn("Error parsing event class");
return (error);
diff --git a/usr.sbin/mountd/mountd.c b/usr.sbin/mountd/mountd.c
index 65bf44f..01a27eb 100644
--- a/usr.sbin/mountd/mountd.c
+++ b/usr.sbin/mountd/mountd.c
@@ -158,6 +158,8 @@ struct fhreturn {
int *fhr_secflavors;
};
+#define GETPORT_MAXTRY 20 /* Max tries to get a port # */
+
/* Global defs */
char *add_expdir(struct dirlist **, char *, int);
void add_dlist(struct dirlist **, struct dirlist *,
@@ -167,7 +169,9 @@ int check_dirpath(char *);
int check_options(struct dirlist *);
int checkmask(struct sockaddr *sa);
int chk_host(struct dirlist *, struct sockaddr *, int *, int *);
-void create_service(struct netconfig *nconf);
+static int create_service(struct netconfig *nconf);
+static void complete_service(struct netconfig *nconf, char *port_str);
+static void clearout_service(void);
void del_mlist(char *hostp, char *dirp);
struct dirlist *dirp_search(struct dirlist *, char *);
int do_mount(struct exportlist *, struct grouplist *, int,
@@ -233,6 +237,10 @@ int got_sighup = 0;
int xcreated = 0;
char *svcport_str = NULL;
+static int mallocd_svcport = 0;
+static int *sock_fd;
+static int sock_fdcnt;
+static int sock_fdpos;
int opt_flags;
static int have_v6 = 1;
@@ -281,6 +289,8 @@ main(int argc, char **argv)
in_port_t svcport;
int c, k, s;
int maxrec = RPC_MAXDATASIZE;
+ int attempt_cnt, port_len, port_pos, ret;
+ char **port_list;
/* Check that another mountd isn't already running. */
pfh = pidfile_open(_PATH_MOUNTDPID, 0600, &otherpid);
@@ -451,17 +461,97 @@ main(int argc, char **argv)
hosts[nhosts - 1] = "127.0.0.1";
}
+ attempt_cnt = 1;
+ sock_fdcnt = 0;
+ sock_fd = NULL;
+ port_list = NULL;
+ port_len = 0;
nc_handle = setnetconfig();
while ((nconf = getnetconfig(nc_handle))) {
if (nconf->nc_flag & NC_VISIBLE) {
if (have_v6 == 0 && strcmp(nconf->nc_protofmly,
"inet6") == 0) {
/* DO NOTHING */
+ } else {
+ ret = create_service(nconf);
+ if (ret == 1)
+ /* Ignore this call */
+ continue;
+ if (ret < 0) {
+ /*
+ * Failed to bind port, so close off
+ * all sockets created and try again
+ * if the port# was dynamically
+ * assigned via bind(2).
+ */
+ clearout_service();
+ if (mallocd_svcport != 0 &&
+ attempt_cnt < GETPORT_MAXTRY) {
+ free(svcport_str);
+ svcport_str = NULL;
+ mallocd_svcport = 0;
+ } else {
+ errno = EADDRINUSE;
+ syslog(LOG_ERR,
+ "bindresvport_sa: %m");
+ exit(1);
+ }
+
+ /* Start over at the first service. */
+ free(sock_fd);
+ sock_fdcnt = 0;
+ sock_fd = NULL;
+ nc_handle = setnetconfig();
+ attempt_cnt++;
+ } else if (mallocd_svcport != 0 &&
+ attempt_cnt == GETPORT_MAXTRY) {
+ /*
+ * For the last attempt, allow
+ * different port #s for each nconf
+ * by saving the svcport_str and
+ * setting it back to NULL.
+ */
+ port_list = realloc(port_list,
+ (port_len + 1) * sizeof(char *));
+ if (port_list == NULL)
+ out_of_mem();
+ port_list[port_len++] = svcport_str;
+ svcport_str = NULL;
+ mallocd_svcport = 0;
+ }
+ }
+ }
+ }
+
+ /*
+ * Successfully bound the ports, so call complete_service() to
+ * do the rest of the setup on the service(s).
+ */
+ sock_fdpos = 0;
+ port_pos = 0;
+ nc_handle = setnetconfig();
+ while ((nconf = getnetconfig(nc_handle))) {
+ if (nconf->nc_flag & NC_VISIBLE) {
+ if (have_v6 == 0 && strcmp(nconf->nc_protofmly,
+ "inet6") == 0) {
+ /* DO NOTHING */
+ } else if (port_list != NULL) {
+ if (port_pos >= port_len) {
+ syslog(LOG_ERR, "too many port#s");
+ exit(1);
+ }
+ complete_service(nconf, port_list[port_pos++]);
} else
- create_service(nconf);
+ complete_service(nconf, svcport_str);
}
}
endnetconfig(nc_handle);
+ free(sock_fd);
+ if (port_list != NULL) {
+ for (port_pos = 0; port_pos < port_len; port_pos++)
+ free(port_list[port_pos]);
+ free(port_list);
+ }
if (xcreated == 0) {
syslog(LOG_ERR, "could not create any services");
@@ -491,30 +581,31 @@ main(int argc, char **argv)
/*
* This routine creates and binds sockets on the appropriate
- * addresses. It gets called one time for each transport and
- * registrates the service with rpcbind on that trasport.
+ * addresses. It gets called one time for each transport.
+ * It returns 0 upon success, 1 for ingore the call and -1 to indicate
+ * bind failed with EADDRINUSE.
+ * Any file descriptors that have been created are stored in sock_fd and
+ * the total count of them is maintained in sock_fdcnt.
*/
-void
+static int
create_service(struct netconfig *nconf)
{
struct addrinfo hints, *res = NULL;
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
struct __rpc_sockinfo si;
- struct netbuf servaddr;
- SVCXPRT *transp = NULL;
int aicode;
int fd;
int nhostsbak;
int one = 1;
int r;
- int registered = 0;
u_int32_t host_addr[4]; /* IPv4 or IPv6 */
+ int mallocd_res;
if ((nconf->nc_semantics != NC_TPI_CLTS) &&
(nconf->nc_semantics != NC_TPI_COTS) &&
(nconf->nc_semantics != NC_TPI_COTS_ORD))
- return; /* not my type */
+ return (1); /* not my type */
/*
* XXX - using RPC library internal functions.
@@ -522,7 +613,7 @@ create_service(struct netconfig *nconf)
if (!__rpc_nconf2sockinfo(nconf, &si)) {
syslog(LOG_ERR, "cannot get information for %s",
nconf->nc_netid);
- return;
+ return (1);
}
/* Get mountd's address on this transport */
@@ -538,6 +629,12 @@ create_service(struct netconfig *nconf)
nhostsbak = nhosts;
while (nhostsbak > 0) {
--nhostsbak;
+ sock_fd = realloc(sock_fd, (sock_fdcnt + 1) * sizeof(int));
+ if (sock_fd == NULL)
+ out_of_mem();
+ sock_fd[sock_fdcnt++] = -1; /* Set invalid for now. */
+ mallocd_res = 0;
+
/*
* XXX - using RPC library internal functions.
*/
@@ -549,14 +646,16 @@ create_service(struct netconfig *nconf)
syslog(non_fatal ? LOG_DEBUG : LOG_ERR,
"cannot create socket for %s", nconf->nc_netid);
- return;
+ if (non_fatal != 0)
+ continue;
+ exit(1);
}
switch (hints.ai_family) {
case AF_INET:
if (inet_pton(AF_INET, hosts[nhostsbak],
host_addr) == 1) {
- hints.ai_flags &= AI_NUMERICHOST;
+ hints.ai_flags |= AI_NUMERICHOST;
} else {
/*
* Skip if we have an AF_INET6 address.
@@ -571,7 +670,7 @@ create_service(struct netconfig *nconf)
case AF_INET6:
if (inet_pton(AF_INET6, hosts[nhostsbak],
host_addr) == 1) {
- hints.ai_flags &= AI_NUMERICHOST;
+ hints.ai_flags |= AI_NUMERICHOST;
} else {
/*
* Skip if we have an AF_INET address.
@@ -607,6 +706,7 @@ create_service(struct netconfig *nconf)
res = malloc(sizeof(struct addrinfo));
if (res == NULL)
out_of_mem();
+ mallocd_res = 1;
res->ai_flags = hints.ai_flags;
res->ai_family = hints.ai_family;
res->ai_protocol = hints.ai_protocol;
@@ -620,7 +720,7 @@ create_service(struct netconfig *nconf)
sin->sin_addr.s_addr = htonl(INADDR_ANY);
res->ai_addr = (struct sockaddr*) sin;
res->ai_addrlen = (socklen_t)
- sizeof(res->ai_addr);
+ sizeof(struct sockaddr_in);
break;
case AF_INET6:
sin6 = malloc(sizeof(struct sockaddr_in6));
@@ -631,10 +731,12 @@ create_service(struct netconfig *nconf)
sin6->sin6_addr = in6addr_any;
res->ai_addr = (struct sockaddr*) sin6;
res->ai_addrlen = (socklen_t)
- sizeof(res->ai_addr);
- break;
- default:
+ sizeof(struct sockaddr_in6);
break;
+ default:
+ syslog(LOG_ERR, "bad addr fam %d",
+ res->ai_family);
+ exit(1);
}
} else {
if ((aicode = getaddrinfo(NULL, svcport_str,
@@ -643,6 +745,7 @@ create_service(struct netconfig *nconf)
"cannot get local address for %s: %s",
nconf->nc_netid,
gai_strerror(aicode));
+ close(fd);
continue;
}
}
@@ -652,16 +755,91 @@ create_service(struct netconfig *nconf)
syslog(LOG_ERR,
"cannot get local address for %s: %s",
nconf->nc_netid, gai_strerror(aicode));
+ close(fd);
continue;
}
}
+ /* Store the fd. */
+ sock_fd[sock_fdcnt - 1] = fd;
+
+ /* Now, attempt the bind. */
r = bindresvport_sa(fd, res->ai_addr);
if (r != 0) {
+ if (errno == EADDRINUSE && mallocd_svcport != 0) {
+ if (mallocd_res != 0) {
+ free(res->ai_addr);
+ free(res);
+ } else
+ freeaddrinfo(res);
+ return (-1);
+ }
syslog(LOG_ERR, "bindresvport_sa: %m");
exit(1);
}
+ if (svcport_str == NULL) {
+ svcport_str = malloc(NI_MAXSERV * sizeof(char));
+ if (svcport_str == NULL)
+ out_of_mem();
+ mallocd_svcport = 1;
+
+ if (getnameinfo(res->ai_addr,
+ res->ai_addr->sa_len, NULL, NI_MAXHOST,
+ svcport_str, NI_MAXSERV * sizeof(char),
+ NI_NUMERICHOST | NI_NUMERICSERV))
+ errx(1, "Cannot get port number");
+ }
+ if (mallocd_res != 0) {
+ free(res->ai_addr);
+ free(res);
+ } else
+ freeaddrinfo(res);
+ res = NULL;
+ }
+ return (0);
+}
+
+/*
+ * Called after all the create_service() calls have succeeded, to complete
+ * the setup and registration.
+ */
+static void
+complete_service(struct netconfig *nconf, char *port_str)
+{
+ struct addrinfo hints, *res = NULL;
+ struct __rpc_sockinfo si;
+ struct netbuf servaddr;
+ SVCXPRT *transp = NULL;
+ int aicode, fd, nhostsbak;
+ int registered = 0;
+
+ if ((nconf->nc_semantics != NC_TPI_CLTS) &&
+ (nconf->nc_semantics != NC_TPI_COTS) &&
+ (nconf->nc_semantics != NC_TPI_COTS_ORD))
+ return; /* not my type */
+
+ /*
+ * XXX - using RPC library internal functions.
+ */
+ if (!__rpc_nconf2sockinfo(nconf, &si)) {
+ syslog(LOG_ERR, "cannot get information for %s",
+ nconf->nc_netid);
+ return;
+ }
+
+ nhostsbak = nhosts;
+ while (nhostsbak > 0) {
+ --nhostsbak;
+ if (sock_fdpos >= sock_fdcnt) {
+ /* Should never happen. */
+ syslog(LOG_ERR, "Ran out of socket fd's");
+ return;
+ }
+ fd = sock_fd[sock_fdpos++];
+ if (fd < 0)
+ continue;
+
if (nconf->nc_semantics != NC_TPI_CLTS)
listen(fd, SOMAXCONN);
@@ -696,19 +874,7 @@ create_service(struct netconfig *nconf)
hints.ai_socktype = si.si_socktype;
hints.ai_protocol = si.si_proto;
- if (svcport_str == NULL) {
- svcport_str = malloc(NI_MAXSERV * sizeof(char));
- if (svcport_str == NULL)
- out_of_mem();
-
- if (getnameinfo(res->ai_addr,
- res->ai_addr->sa_len, NULL, NI_MAXHOST,
- svcport_str, NI_MAXSERV * sizeof(char),
- NI_NUMERICHOST | NI_NUMERICSERV))
- errx(1, "Cannot get port number");
- }
-
- if((aicode = getaddrinfo(NULL, svcport_str, &hints,
+ if ((aicode = getaddrinfo(NULL, port_str, &hints,
&res)) != 0) {
syslog(LOG_ERR, "cannot get local address: %s",
gai_strerror(aicode));
@@ -728,6 +894,23 @@ create_service(struct netconfig *nconf)
} /* end while */
}
+/*
+ * Clear out sockets after a failure to bind one of them, so that the
+ * cycle of socket creation/binding can start anew.
+ */
+static void
+clearout_service(void)
+{
+ int i;
+
+ for (i = 0; i < sock_fdcnt; i++) {
+ if (sock_fd[i] >= 0) {
+ shutdown(sock_fd[i], SHUT_RDWR);
+ close(sock_fd[i]);
+ }
+ }
+}
+
static void
usage(void)
{
diff --git a/usr.sbin/pc-sysinstall/backend-query/enable-net.sh b/usr.sbin/pc-sysinstall/backend-query/enable-net.sh
index 3c73550..8cd72a1 100755
--- a/usr.sbin/pc-sysinstall/backend-query/enable-net.sh
+++ b/usr.sbin/pc-sysinstall/backend-query/enable-net.sh
@@ -1,6 +1,11 @@
#!/bin/sh
#-
# Copyright (c) 2010 iXsystems, Inc. All rights reserved.
+# Copyright (c) 2011 The FreeBSD Foundation
+# All rights reserved.
+#
+# Portions of this software were developed by Bjoern Zeeb
+# under sponsorship from the FreeBSD Foundation.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -40,23 +45,67 @@ NETMASK="$3"
DNS="$4"
GATEWAY="$5"
MIRRORFETCH="$6"
+IPV6="$7"
+IPV6GATE="$8"
+IPV6DNS="$9"
if [ -z "${NIC}" ]
then
- echo "ERROR: Usage enable-net <nic> <ip> <netmask> <dns> <gateway>"
+ echo "ERROR: Usage enable-net <nic> <ip> <netmask> <dns> <gateway> <ipv6> " \
+ "<ipv6gateway> <ipv6dns>"
exit 150
fi
if [ "$NIC" = "AUTO-DHCP" ]
then
enable_auto_dhcp
+elif [ "$NIC" = "IPv6-SLAAC" ]
+then
+ enable_auto_slaac
+ # In addition, if static values were defined, add them as well.
+ # We might not get DNS information from RAs, for example.
+ if [ -n "${IPV6}" ]; then
+ VAL=""
+ get_first_wired_nic
+ if [ -n "${VAL}" ]; then
+ ifconfig ${VAL} inet6 ${IPV6} alias
+ fi
+ fi
+ # Append only here.
+ if [ -n "${IPV6DNS}" ]; then
+ echo "nameserver ${IPV6DNS}" >>/etc/resolv.conf
+ fi
+ # Do not
+ if [ -n "${IPV6GATE}" ]; then
+ # Check if we have a default route already to not overwrite.
+ if ! route -n get -inet6 default > /dev/null 2>&1 ; then
+ route add -inet6 default ${IPV6GATE}
+ fi
+ fi
else
echo "Enabling NIC: $NIC"
- ifconfig ${NIC} ${IP} ${NETMASK}
+ if [ -n "${IP}" ]; then
+ ifconfig ${NIC} inet ${IP} ${NETMASK}
+ fi
+ if [ -n "${IPV6}" ]; then
+ ifconfig ${NIC} inet6 ${IPV6} alias
+ fi
- echo "nameserver ${DNS}" >/etc/resolv.conf
+ # Keep default from IPv4-only support times and clear the resolv.conf file.
+ : > /etc/resolv.conf
+ if [ -n "${DNS}" ]; then
+ echo "nameserver ${DNS}" >>/etc/resolv.conf
+ fi
+ if [ -n "${IPV6DNS}" ]; then
+ echo "nameserver ${IPV6DNS}" >>/etc/resolv.conf
+ fi
- route add default ${GATE}
+ if [ -n "${GATE}" ]; then
+ route add -inet default ${GATE}
+ fi
+ if [ -n "${IPV6GATE}" ]; then
+ route add -inet6 default ${IPV6GATE}
+ fi
fi
case ${MIRRORFETCH} in
diff --git a/usr.sbin/pc-sysinstall/backend-query/test-netup.sh b/usr.sbin/pc-sysinstall/backend-query/test-netup.sh
index 4c8304e..e0a3eba 100755
--- a/usr.sbin/pc-sysinstall/backend-query/test-netup.sh
+++ b/usr.sbin/pc-sysinstall/backend-query/test-netup.sh
@@ -1,6 +1,11 @@
#!/bin/sh
#-
# Copyright (c) 2010 iXsystems, Inc. All rights reserved.
+# Copyright (c) 2011 The FreeBSD Foundation
+# All rights reserved.
+#
+# Portions of this software were developed by Bjoern Zeeb
+# under sponsorship from the FreeBSD Foundation.#
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -26,8 +31,8 @@
# $FreeBSD$
-# Script which tests "fetch" when using a network connection, and saves
-# if we are using direct connect, or need FTP passive mode
+# Script which tries to ping "home" to see if Internet connectivity is
+# available.
#############################################################################
rm ${TMPDIR}/.testftp >/dev/null 2>/dev/null
@@ -39,12 +44,26 @@ then
exit 0
fi
+ping6 -c 2 www.pcbsd.org >/dev/null 2>/dev/null
+if [ "$?" = "0" ]
+then
+ echo "ftp: Up"
+ exit 0
+fi
+
ping -c 2 www.freebsd.org >/dev/null 2>/dev/null
if [ "$?" = "0" ]
then
echo "ftp: Up"
exit 0
fi
-
+
+ping6 -c 2 www.freebsd.org >/dev/null 2>/dev/null
+if [ "$?" = "0" ]
+then
+ echo "ftp: Up"
+ exit 0
+fi
+
echo "ftp: Down"
exit 1
diff --git a/usr.sbin/pc-sysinstall/backend/functions-networking.sh b/usr.sbin/pc-sysinstall/backend/functions-networking.sh
index d12a9cc..bdd5a1a 100755
--- a/usr.sbin/pc-sysinstall/backend/functions-networking.sh
+++ b/usr.sbin/pc-sysinstall/backend/functions-networking.sh
@@ -1,6 +1,11 @@
#!/bin/sh
#-
# Copyright (c) 2010 iXsystems, Inc. All rights reserved.
+# Copyright (c) 2011 The FreeBSD Foundation
+# All rights reserved.
+#
+# Portions of this software were developed by Bjoern Zeeb
+# under sponsorship from the FreeBSD Foundation.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -119,6 +124,61 @@ save_auto_dhcp()
enable_dhcp_all
};
+# Function which simply enables iPv6 SLAAC on all detected nics
+enable_slaac_all()
+{
+ rm ${TMPDIR}/.niclist >/dev/null 2>/dev/null
+ # start by getting a list of nics on this system
+ ${QUERYDIR}/detect-nics.sh > ${TMPDIR}/.niclist
+ if [ -e "${TMPDIR}/.niclist" ]
+ then
+ echo "# Auto-Enabled NICs from pc-sysinstall" >>${FSMNT}/etc/rc.conf
+ WLANCOUNT="0"
+ while read line
+ do
+ NIC="`echo $line | cut -d ':' -f 1`"
+ DESC="`echo $line | cut -d ':' -f 2`"
+ echo_log "Setting $NIC to acceptign RAs on the system."
+ check_is_wifi ${NIC}
+ if [ $? -eq 0 ]
+ then
+ # We have a wifi device, setup a wlan* entry for it
+ # Given we cannot have DHCP and SLAAC the same time currently
+ # it's save to just duplicate.
+ WLAN="wlan${WLANCOUNT}"
+ echo "wlans_${NIC}=\"${WLAN}\"" >>${FSMNT}/etc/rc.conf
+ #echo "ifconfig_${NIC}=\"up\"" >>${FSMNT}/etc/rc.conf
+ echo "ifconfig_${WLAN}=\"inet6 accept_rtadv\"" >>${FSMNT}/etc/rc.conf
+ CNIC="${WLAN}"
+ WLANCOUNT=$((WLANCOUNT+1))
+ else
+ #echo "ifconfig_${NIC}=\"up\"" >>${FSMNT}/etc/rc.conf
+ echo "ifconfig_${NIC}_ipv6=\"inet6 accept_rtadv\"" >>${FSMNT}/etc/rc.conf
+ CNIC="${NIC}"
+ fi
+
+ done < ${TMPDIR}/.niclist
+ fi
+
+ # Given we cannot yet rely on RAs to provide DNS information as much
+ # as we can in the DHCP world, we should append a given nameserver.
+ : > ${FSMNT}/etc/resolv.conf
+ get_value_from_cfg netSaveIPv6NameServer
+ NAMESERVER="${VAL}"
+ if [ -n "${NAMESERVER}" ]
+ then
+ echo "nameserver ${NAMESERVER}" >>${FSMNT}/etc/resolv.conf
+ fi
+
+};
+
+
+# Function which detects available nics, and enables IPv6 SLAAC on them
+save_auto_slaac()
+{
+ enable_slaac_all
+};
+
# Function which saves a manual nic setup to the installed system
save_manual_nic()
@@ -137,21 +197,41 @@ save_manual_nic()
fi
# If we get here, we have a manual setup, lets do so now
+ IFARGS=""
+ IF6ARGS=""
# Set the manual IP
- IFARGS="inet ${NETIP}"
-
- # Check if we have a netmask to set
- get_value_from_cfg netSaveMask
- NETMASK="${VAL}"
- if [ -n "${NETMASK}" ]
+ if [ -n "${NETIP}" ]
then
- IFARGS="${IFARGS} netmask ${NETMASK}"
+ IFARGS="inet ${NETIP}"
+
+ # Check if we have a netmask to set
+ get_value_from_cfg netSaveMask
+ NETMASK="${VAL}"
+ if [ -n "${NETMASK}" ]
+ then
+ IFARGS="${IFARGS} netmask ${NETMASK}"
+ fi
fi
+ get_value_from_cfg netSaveIPv6
+ NETIP6="${VAL}"
+ if [ -n "${NETIP6}" ]
+ then
+ # Make sure we have one inet6 prefix.
+ IF6ARGS=`echo "${NETIP6}" | awk '{ if ("^inet6 ") { print $0; } else
+ { printf "inet6 %s", $0; } }'`
+ fi
echo "# Auto-Enabled NICs from pc-sysinstall" >>${FSMNT}/etc/rc.conf
- echo "ifconfig_${NIC}=\"${IFARGS}\"" >>${FSMNT}/etc/rc.conf
+ if [ -n "${IFARGS}" ]
+ then
+ echo "ifconfig_${NIC}=\"${IFARGS}\"" >>${FSMNT}/etc/rc.conf
+ fi
+ if [ -n "${IF6ARGS}" ]
+ then
+ echo "ifconfig_${NIC}_ipv6=\"${IF6ARGS}\"" >>${FSMNT}/etc/rc.conf
+ fi
# Check if we have a default router to set
get_value_from_cfg netSaveDefaultRouter
@@ -160,15 +240,28 @@ save_manual_nic()
then
echo "defaultrouter=\"${NETROUTE}\"" >>${FSMNT}/etc/rc.conf
fi
+ get_value_from_cfg netSaveIPv6DefaultRouter
+ NETROUTE="${VAL}"
+ if [ -n "${NETROUTE}" ]
+ then
+ echo "ipv6_defaultrouter=\"${NETROUTE}\"" >>${FSMNT}/etc/rc.conf
+ fi
# Check if we have a nameserver to enable
+ : > ${FSMNT}/etc/resolv.conf
get_value_from_cfg netSaveNameServer
NAMESERVER="${VAL}"
if [ -n "${NAMESERVER}" ]
then
- echo "nameserver ${NAMESERVER}" >${FSMNT}/etc/resolv.conf
+ echo "nameserver ${NAMESERVER}" >>${FSMNT}/etc/resolv.conf
fi
-
+ get_value_from_cfg netSaveIPv6NameServer
+ NAMESERVER="${VAL}"
+ if [ -n "${NAMESERVER}" ]
+ then
+ echo "nameserver ${NAMESERVER}" >>${FSMNT}/etc/resolv.conf
+ fi
+
};
# Function which determines if a nic is active / up
@@ -208,6 +301,31 @@ enable_auto_dhcp()
};
+# Function which detects available nics, and runs rtsol on them.
+enable_auto_slaac()
+{
+
+ # start by getting a list of nics on this system
+ ${QUERYDIR}/detect-nics.sh > ${TMPDIR}/.niclist
+ ALLNICS=""
+ while read line
+ do
+ NIC="`echo $line | cut -d ':' -f 1`"
+ DESC="`echo $line | cut -d ':' -f 2`"
+
+ is_nic_active "${NIC}"
+ if [ $? -eq 0 ] ; then
+ echo_log "Will try IPv6 SLAAC on $NIC $DESC"
+ ifconfig ${NIC} inet6 -ifdisabled accept_rtadv up
+ ALLNICS="${ALLNICS} ${NIC}"
+ fi
+ done < ${TMPDIR}/.niclist
+
+ # XXX once we support it in-tree call /sbin/resovconf here.
+ echo_log "Running rtsol on ${ALLNICS}"
+ rtsol -F ${ALLNICS} >/dev/null 2>/dev/null
+}
+
# Get the mac address of a target NIC
get_nic_mac()
{
@@ -236,15 +354,20 @@ enable_manual_nic()
# If we get here, we have a manual setup, lets do so now
- # Set the manual IP
- rc_halt "ifconfig ${NIC} ${NETIP}"
+ # IPv4:
- # Check if we have a netmask to set
- get_value_from_cfg netMask
- NETMASK="${VAL}"
- if [ -n "${NETMASK}" ]
+ # Set the manual IP
+ if [ -n "${NETIP}" ]
then
- rc_halt "ifconfig ${NIC} netmask ${NETMASK}"
+ # Check if we have a netmask to set
+ get_value_from_cfg netMask
+ NETMASK="${VAL}"
+ if [ -n "${NETMASK}" ]
+ then
+ rc_halt "ifconfig inet ${NIC} netmask ${NETMASK}"
+ else
+ rc_halt "ifconfig inet ${NIC} ${NETIP}"
+ fi
fi
# Check if we have a default router to set
@@ -252,18 +375,42 @@ enable_manual_nic()
NETROUTE="${VAL}"
if [ -n "${NETROUTE}" ]
then
- rc_halt "route add default ${NETROUTE}"
+ rc_halt "route add -inet default ${NETROUTE}"
+ fi
+
+ # IPv6:
+
+ # Set static IPv6 address
+ get_value_from_cfg netIPv6
+ NETIP="${VAL}"
+ if [ -n ${NETIP} ]
+ then
+ rc_halt "ifconfig inet6 ${NIC} ${NETIP} -ifdisabled up"
+ fi
+
+ # Default router
+ get_value_from_cfg netIPv6DefaultRouter
+ NETROUTE="${VAL}"
+ if [ -n "${NETROUTE}" ]
+ then
+ rc_halt "route add -inet6 default ${NETROUTE}"
fi
# Check if we have a nameserver to enable
+ : >/etc/resolv.conf
get_value_from_cfg netNameServer
NAMESERVER="${VAL}"
if [ -n "${NAMESERVER}" ]
then
- echo "nameserver ${NAMESERVER}" >/etc/resolv.conf
+ echo "nameserver ${NAMESERVER}" >>/etc/resolv.conf
fi
-
-
+ get_value_from_cfg netIPv6NameServer
+ NAMESERVER="${VAL}"
+ if [ -n "${NAMESERVER}" ]
+ then
+ echo "nameserver ${NAMESERVER}" >>/etc/resolv.conf
+ fi
+
};
@@ -281,6 +428,9 @@ start_networking()
if [ "$NETDEV" = "AUTO-DHCP" ]
then
enable_auto_dhcp
+ elif [ "$NETDEV" = "IPv6-SLAAC" ]
+ then
+ enable_auto_slaac
else
enable_manual_nic ${NETDEV}
fi
@@ -304,6 +454,9 @@ save_networking_install()
if [ "$NETDEV" = "AUTO-DHCP" ]
then
save_auto_dhcp
+ elif [ "$NETDEV" = "IPv6-SLAAC" ]
+ then
+ save_auto_slaac
else
save_manual_nic ${NETDEV}
fi
diff --git a/usr.sbin/rpc.lockd/lockd.c b/usr.sbin/rpc.lockd/lockd.c
index fb9e536..b3402ff 100644
--- a/usr.sbin/rpc.lockd/lockd.c
+++ b/usr.sbin/rpc.lockd/lockd.c
@@ -74,6 +74,8 @@ __RCSID("$NetBSD: lockd.c,v 1.7 2000/08/12 18:08:44 thorpej Exp $");
#include "lockd.h"
#include <rpcsvc/nlm_prot.h>
+#define GETPORT_MAXTRY 20 /* Max tries to get a port # */
+
int debug_level = 0; /* 0 = no debugging syslog() calls */
int _rpcsvcdirty = 0;
@@ -84,13 +86,19 @@ int kernel_lockd_client;
pid_t client_pid;
struct mon mon_host;
char **hosts, *svcport_str = NULL;
+static int mallocd_svcport = 0;
+static int *sock_fd;
+static int sock_fdcnt;
+static int sock_fdpos;
int nhosts = 0;
int xcreated = 0;
char **addrs; /* actually (netid, uaddr) pairs */
int naddrs; /* count of how many (netid, uaddr) pairs */
char localhost[] = "localhost";
-void create_service(struct netconfig *nconf);
+static int create_service(struct netconfig *nconf);
+static void complete_service(struct netconfig *nconf, char *port_str);
+static void clearout_service(void);
void lookup_addresses(struct netconfig *nconf);
void init_nsm(void);
void nlm_prog_0(struct svc_req *, SVCXPRT *);
@@ -119,6 +127,8 @@ main(int argc, char **argv)
int have_v6 = 1;
int maxrec = RPC_MAXDATASIZE;
in_port_t svcport = 0;
+ int attempt_cnt, port_len, port_pos, ret;
+ char **port_list;
while ((ch = getopt(argc, argv, "d:g:h:p:")) != (-1)) {
switch (ch) {
@@ -309,6 +319,11 @@ main(int argc, char **argv)
}
endnetconfig(nc_handle);
} else {
+ attempt_cnt = 1;
+ sock_fdcnt = 0;
+ sock_fd = NULL;
+ port_list = NULL;
+ port_len = 0;
nc_handle = setnetconfig();
while ((nconf = getnetconfig(nc_handle))) {
/* We want to listen only on udp6, tcp6, udp, tcp transports */
@@ -317,11 +332,96 @@ main(int argc, char **argv)
if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) {
/* DO NOTHING */
} else {
- create_service(nconf);
+ ret = create_service(nconf);
+ if (ret == 1)
+ /* Ignore this call */
+ continue;
+ if (ret < 0) {
+ /*
+ * Failed to bind port, so close
+ * off all sockets created and
+ * try again if the port# was
+ * dynamically assigned via
+ * bind(2).
+ */
+ clearout_service();
+ if (mallocd_svcport != 0 &&
+ attempt_cnt <
+ GETPORT_MAXTRY) {
+ free(svcport_str);
+ svcport_str = NULL;
+ mallocd_svcport = 0;
+ } else {
+ errno = EADDRINUSE;
+ syslog(LOG_ERR,
+ "bindresvport_sa: %m");
+ exit(1);
+ }
+
+ /*
+ * Start over at the first
+ * service.
+ */
+ free(sock_fd);
+ sock_fdcnt = 0;
+ sock_fd = NULL;
+ nc_handle = setnetconfig();
+ attempt_cnt++;
+ } else if (mallocd_svcport != 0 &&
+ attempt_cnt == GETPORT_MAXTRY) {
+ /*
+ * For the last attempt, allow
+ * different port #s for each
+ * nconf by saving the
+ * svcport_str and setting it
+ * back to NULL.
+ */
+ port_list = realloc(port_list,
+ (port_len + 1) *
+ sizeof(char *));
+ if (port_list == NULL)
+ out_of_mem();
+ port_list[port_len++] =
+ svcport_str;
+ svcport_str = NULL;
+ mallocd_svcport = 0;
+ }
}
}
}
+
+ /*
+ * Successfully bound the ports, so call complete_service() to
+ * do the rest of the setup on the service(s).
+ */
+ sock_fdpos = 0;
+ port_pos = 0;
+ nc_handle = setnetconfig();
+ while ((nconf = getnetconfig(nc_handle))) {
+ /* We want to listen only on udp6, tcp6, udp, tcp transports */
+ if (nconf->nc_flag & NC_VISIBLE) {
+ /* Skip if there's no IPv6 support */
+ if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) {
+ /* DO NOTHING */
+ } else if (port_list != NULL) {
+ if (port_pos >= port_len) {
+ syslog(LOG_ERR,
+ "too many port#s");
+ exit(1);
+ }
+ complete_service(nconf,
+ port_list[port_pos++]);
+ } else
+ complete_service(nconf, svcport_str);
+ }
+ }
endnetconfig(nc_handle);
+ free(sock_fd);
+ if (port_list != NULL) {
+ for (port_pos = 0; port_pos < port_len; port_pos++)
+ free(port_list[port_pos]);
+ free(port_list);
+ }
}
/*
@@ -386,29 +486,30 @@ main(int argc, char **argv)
/*
* This routine creates and binds sockets on the appropriate
- * addresses. It gets called one time for each transport and
- * registrates the service with rpcbind on that trasport.
+ * addresses. It gets called one time for each transport.
+ * It returns 0 upon success, 1 for ingore the call and -1 to indicate
+ * bind failed with EADDRINUSE.
+ * Any file descriptors that have been created are stored in sock_fd and
+ * the total count of them is maintained in sock_fdcnt.
*/
-void
+static int
create_service(struct netconfig *nconf)
{
struct addrinfo hints, *res = NULL;
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
struct __rpc_sockinfo si;
- struct netbuf servaddr;
- SVCXPRT *transp = NULL;
int aicode;
int fd;
int nhostsbak;
int r;
- int registered = 0;
u_int32_t host_addr[4]; /* IPv4 or IPv6 */
+ int mallocd_res;
if ((nconf->nc_semantics != NC_TPI_CLTS) &&
(nconf->nc_semantics != NC_TPI_COTS) &&
(nconf->nc_semantics != NC_TPI_COTS_ORD))
- return; /* not my type */
+ return (1); /* not my type */
/*
* XXX - using RPC library internal functions.
@@ -416,7 +517,7 @@ create_service(struct netconfig *nconf)
if (!__rpc_nconf2sockinfo(nconf, &si)) {
syslog(LOG_ERR, "cannot get information for %s",
nconf->nc_netid);
- return;
+ return (1);
}
/* Get rpc.statd's address on this transport */
@@ -432,6 +533,11 @@ create_service(struct netconfig *nconf)
nhostsbak = nhosts;
while (nhostsbak > 0) {
--nhostsbak;
+ sock_fd = realloc(sock_fd, (sock_fdcnt + 1) * sizeof(int));
+ if (sock_fd == NULL)
+ out_of_mem();
+ sock_fd[sock_fdcnt++] = -1; /* Set invalid for now. */
+ mallocd_res = 0;
/*
* XXX - using RPC library internal functions.
@@ -446,7 +552,7 @@ create_service(struct netconfig *nconf)
case AF_INET:
if (inet_pton(AF_INET, hosts[nhostsbak],
host_addr) == 1) {
- hints.ai_flags &= AI_NUMERICHOST;
+ hints.ai_flags |= AI_NUMERICHOST;
} else {
/*
* Skip if we have an AF_INET6 address.
@@ -461,7 +567,7 @@ create_service(struct netconfig *nconf)
case AF_INET6:
if (inet_pton(AF_INET6, hosts[nhostsbak],
host_addr) == 1) {
- hints.ai_flags &= AI_NUMERICHOST;
+ hints.ai_flags |= AI_NUMERICHOST;
} else {
/*
* Skip if we have an AF_INET address.
@@ -485,6 +591,7 @@ create_service(struct netconfig *nconf)
res = malloc(sizeof(struct addrinfo));
if (res == NULL)
out_of_mem();
+ mallocd_res = 1;
res->ai_flags = hints.ai_flags;
res->ai_family = hints.ai_family;
res->ai_protocol = hints.ai_protocol;
@@ -498,7 +605,7 @@ create_service(struct netconfig *nconf)
sin->sin_addr.s_addr = htonl(INADDR_ANY);
res->ai_addr = (struct sockaddr*) sin;
res->ai_addrlen = (socklen_t)
- sizeof(res->ai_addr);
+ sizeof(struct sockaddr_in);
break;
case AF_INET6:
sin6 = malloc(sizeof(struct sockaddr_in6));
@@ -508,10 +615,14 @@ create_service(struct netconfig *nconf)
sin6->sin6_port = htons(0);
sin6->sin6_addr = in6addr_any;
res->ai_addr = (struct sockaddr*) sin6;
- res->ai_addrlen = (socklen_t) sizeof(res->ai_addr);
+ res->ai_addrlen = (socklen_t)
+ sizeof(struct sockaddr_in6);
break;
default:
- break;
+ syslog(LOG_ERR,
+ "bad addr fam %d",
+ res->ai_family);
+ exit(1);
}
} else {
if ((aicode = getaddrinfo(NULL, svcport_str,
@@ -520,6 +631,7 @@ create_service(struct netconfig *nconf)
"cannot get local address for %s: %s",
nconf->nc_netid,
gai_strerror(aicode));
+ close(fd);
continue;
}
}
@@ -529,16 +641,92 @@ create_service(struct netconfig *nconf)
syslog(LOG_ERR,
"cannot get local address for %s: %s",
nconf->nc_netid, gai_strerror(aicode));
+ close(fd);
continue;
}
}
+
+ /* Store the fd. */
+ sock_fd[sock_fdcnt - 1] = fd;
+
+ /* Now, attempt the bind. */
r = bindresvport_sa(fd, res->ai_addr);
if (r != 0) {
+ if (errno == EADDRINUSE && mallocd_svcport != 0) {
+ if (mallocd_res != 0) {
+ free(res->ai_addr);
+ free(res);
+ } else
+ freeaddrinfo(res);
+ return (-1);
+ }
syslog(LOG_ERR, "bindresvport_sa: %m");
exit(1);
}
+ if (svcport_str == NULL) {
+ svcport_str = malloc(NI_MAXSERV * sizeof(char));
+ if (svcport_str == NULL)
+ out_of_mem();
+ mallocd_svcport = 1;
+
+ if (getnameinfo(res->ai_addr,
+ res->ai_addr->sa_len, NULL, NI_MAXHOST,
+ svcport_str, NI_MAXSERV * sizeof(char),
+ NI_NUMERICHOST | NI_NUMERICSERV))
+ errx(1, "Cannot get port number");
+ }
+ if (mallocd_res != 0) {
+ free(res->ai_addr);
+ free(res);
+ } else
+ freeaddrinfo(res);
+ res = NULL;
+ }
+ return (0);
+}
+
+/*
+ * Called after all the create_service() calls have succeeded, to complete
+ * the setup and registration.
+ */
+static void
+complete_service(struct netconfig *nconf, char *port_str)
+{
+ struct addrinfo hints, *res = NULL;
+ struct __rpc_sockinfo si;
+ struct netbuf servaddr;
+ SVCXPRT *transp = NULL;
+ int aicode, fd, nhostsbak;
+ int registered = 0;
+
+ if ((nconf->nc_semantics != NC_TPI_CLTS) &&
+ (nconf->nc_semantics != NC_TPI_COTS) &&
+ (nconf->nc_semantics != NC_TPI_COTS_ORD))
+ return; /* not my type */
+
+ /*
+ * XXX - using RPC library internal functions.
+ */
+ if (!__rpc_nconf2sockinfo(nconf, &si)) {
+ syslog(LOG_ERR, "cannot get information for %s",
+ nconf->nc_netid);
+ return;
+ }
+
+ nhostsbak = nhosts;
+ while (nhostsbak > 0) {
+ --nhostsbak;
+ if (sock_fdpos >= sock_fdcnt) {
+ /* Should never happen. */
+ syslog(LOG_ERR, "Ran out of socket fd's");
+ return;
+ }
+ fd = sock_fd[sock_fdpos++];
+ if (fd < 0)
+ continue;
+
if (nconf->nc_semantics != NC_TPI_CLTS)
listen(fd, SOMAXCONN);
@@ -582,19 +770,7 @@ create_service(struct netconfig *nconf)
hints.ai_socktype = si.si_socktype;
hints.ai_protocol = si.si_proto;
- if (svcport_str == NULL) {
- svcport_str = malloc(NI_MAXSERV * sizeof(char));
- if (svcport_str == NULL)
- out_of_mem();
-
- if (getnameinfo(res->ai_addr,
- res->ai_addr->sa_len, NULL, NI_MAXHOST,
- svcport_str, NI_MAXSERV * sizeof(char),
- NI_NUMERICHOST | NI_NUMERICSERV))
- errx(1, "Cannot get port number");
- }
-
- if((aicode = getaddrinfo(NULL, svcport_str, &hints,
+ if ((aicode = getaddrinfo(NULL, port_str, &hints,
&res)) != 0) {
syslog(LOG_ERR, "cannot get local address: %s",
gai_strerror(aicode));
@@ -617,6 +793,23 @@ create_service(struct netconfig *nconf)
}
/*
+ * Clear out sockets after a failure to bind one of them, so that the
+ * cycle of socket creation/binding can start anew.
+ */
+static void
+clearout_service(void)
+{
+ int i;
+
+ for (i = 0; i < sock_fdcnt; i++) {
+ if (sock_fd[i] >= 0) {
+ shutdown(sock_fd[i], SHUT_RDWR);
+ close(sock_fd[i]);
+ }
+ }
+}
+
+/*
* Look up addresses for the kernel to create transports for.
*/
void
diff --git a/usr.sbin/rpc.statd/statd.c b/usr.sbin/rpc.statd/statd.c
index b8b4311..ff537f8 100644
--- a/usr.sbin/rpc.statd/statd.c
+++ b/usr.sbin/rpc.statd/statd.c
@@ -39,6 +39,7 @@
__FBSDID("$FreeBSD$");
#include <err.h>
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <rpc/rpc.h>
@@ -55,13 +56,21 @@ __FBSDID("$FreeBSD$");
#include <unistd.h>
#include "statd.h"
+#define GETPORT_MAXTRY 20 /* Max tries to get a port # */
+
int debug = 0; /* Controls syslog() calls for debug messages */
char **hosts, *svcport_str = NULL;
int nhosts = 0;
int xcreated = 0;
-
-void create_service(struct netconfig *nconf);
+static int mallocd_svcport = 0;
+static int *sock_fd;
+static int sock_fdcnt;
+static int sock_fdpos;
+
+static int create_service(struct netconfig *nconf);
+static void complete_service(struct netconfig *nconf, char *port_str);
+static void clearout_service(void);
static void handle_sigchld(int sig);
void out_of_mem(void);
@@ -78,6 +87,8 @@ main(int argc, char **argv)
char *endptr, **hosts_bak;
int have_v6 = 1;
int maxrec = RPC_MAXDATASIZE;
+ int attempt_cnt, port_len, port_pos, ret;
+ char **port_list;
while ((ch = getopt(argc, argv, "dh:p:")) != -1)
switch (ch) {
@@ -176,6 +187,11 @@ main(int argc, char **argv)
hosts[nhosts - 1] = "127.0.0.1";
}
+ attempt_cnt = 1;
+ sock_fdcnt = 0;
+ sock_fd = NULL;
+ port_list = NULL;
+ port_len = 0;
nc_handle = setnetconfig();
while ((nconf = getnetconfig(nc_handle))) {
/* We want to listen only on udp6, tcp6, udp, tcp transports */
@@ -184,11 +200,87 @@ main(int argc, char **argv)
if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) {
/* DO NOTHING */
} else {
- create_service(nconf);
+ ret = create_service(nconf);
+ if (ret == 1)
+ /* Ignore this call */
+ continue;
+ if (ret < 0) {
+ /*
+ * Failed to bind port, so close off
+ * all sockets created and try again
+ * if the port# was dynamically
+ * assigned via bind(2).
+ */
+ clearout_service();
+ if (mallocd_svcport != 0 &&
+ attempt_cnt < GETPORT_MAXTRY) {
+ free(svcport_str);
+ svcport_str = NULL;
+ mallocd_svcport = 0;
+ } else {
+ errno = EADDRINUSE;
+ syslog(LOG_ERR,
+ "bindresvport_sa: %m");
+ exit(1);
+ }
+
+ /* Start over at the first service. */
+ free(sock_fd);
+ sock_fdcnt = 0;
+ sock_fd = NULL;
+ nc_handle = setnetconfig();
+ attempt_cnt++;
+ } else if (mallocd_svcport != 0 &&
+ attempt_cnt == GETPORT_MAXTRY) {
+ /*
+ * For the last attempt, allow
+ * different port #s for each nconf
+ * by saving the svcport_str and
+ * setting it back to NULL.
+ */
+ port_list = realloc(port_list,
+ (port_len + 1) * sizeof(char *));
+ if (port_list == NULL)
+ out_of_mem();
+ port_list[port_len++] = svcport_str;
+ svcport_str = NULL;
+ mallocd_svcport = 0;
+ }
}
}
}
+
+ /*
+ * Successfully bound the ports, so call complete_service() to
+ * do the rest of the setup on the service(s).
+ */
+ sock_fdpos = 0;
+ port_pos = 0;
+ nc_handle = setnetconfig();
+ while ((nconf = getnetconfig(nc_handle))) {
+ /* We want to listen only on udp6, tcp6, udp, tcp transports */
+ if (nconf->nc_flag & NC_VISIBLE) {
+ /* Skip if there's no IPv6 support */
+ if (have_v6 == 0 && strcmp(nconf->nc_protofmly, "inet6") == 0) {
+ /* DO NOTHING */
+ } else if (port_list != NULL) {
+ if (port_pos >= port_len) {
+ syslog(LOG_ERR, "too many port#s");
+ exit(1);
+ }
+ complete_service(nconf, port_list[port_pos++]);
+ } else
+ complete_service(nconf, svcport_str);
+ }
+ }
endnetconfig(nc_handle);
+ free(sock_fd);
+ if (port_list != NULL) {
+ for (port_pos = 0; port_pos < port_len; port_pos++)
+ free(port_list[port_pos]);
+ free(port_list);
+ }
+
init_file("/var/db/statd.status");
/* Note that it is NOT sensible to run this program from inetd - the */
@@ -215,29 +307,30 @@ main(int argc, char **argv)
/*
* This routine creates and binds sockets on the appropriate
- * addresses. It gets called one time for each transport and
- * registrates the service with rpcbind on that trasport.
+ * addresses. It gets called one time for each transport.
+ * It returns 0 upon success, 1 for ingore the call and -1 to indicate
+ * bind failed with EADDRINUSE.
+ * Any file descriptors that have been created are stored in sock_fd and
+ * the total count of them is maintained in sock_fdcnt.
*/
-void
+static int
create_service(struct netconfig *nconf)
{
struct addrinfo hints, *res = NULL;
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
struct __rpc_sockinfo si;
- struct netbuf servaddr;
- SVCXPRT *transp = NULL;
int aicode;
int fd;
int nhostsbak;
int r;
- int registered = 0;
u_int32_t host_addr[4]; /* IPv4 or IPv6 */
+ int mallocd_res;
if ((nconf->nc_semantics != NC_TPI_CLTS) &&
(nconf->nc_semantics != NC_TPI_COTS) &&
(nconf->nc_semantics != NC_TPI_COTS_ORD))
- return; /* not my type */
+ return (1); /* not my type */
/*
* XXX - using RPC library internal functions.
@@ -245,7 +338,7 @@ create_service(struct netconfig *nconf)
if (!__rpc_nconf2sockinfo(nconf, &si)) {
syslog(LOG_ERR, "cannot get information for %s",
nconf->nc_netid);
- return;
+ return (1);
}
/* Get rpc.statd's address on this transport */
@@ -261,6 +354,11 @@ create_service(struct netconfig *nconf)
nhostsbak = nhosts;
while (nhostsbak > 0) {
--nhostsbak;
+ sock_fd = realloc(sock_fd, (sock_fdcnt + 1) * sizeof(int));
+ if (sock_fd == NULL)
+ out_of_mem();
+ sock_fd[sock_fdcnt++] = -1; /* Set invalid for now. */
+ mallocd_res = 0;
/*
* XXX - using RPC library internal functions.
@@ -274,7 +372,7 @@ create_service(struct netconfig *nconf)
case AF_INET:
if (inet_pton(AF_INET, hosts[nhostsbak],
host_addr) == 1) {
- hints.ai_flags &= AI_NUMERICHOST;
+ hints.ai_flags |= AI_NUMERICHOST;
} else {
/*
* Skip if we have an AF_INET6 address.
@@ -289,7 +387,7 @@ create_service(struct netconfig *nconf)
case AF_INET6:
if (inet_pton(AF_INET6, hosts[nhostsbak],
host_addr) == 1) {
- hints.ai_flags &= AI_NUMERICHOST;
+ hints.ai_flags |= AI_NUMERICHOST;
} else {
/*
* Skip if we have an AF_INET address.
@@ -313,6 +411,7 @@ create_service(struct netconfig *nconf)
res = malloc(sizeof(struct addrinfo));
if (res == NULL)
out_of_mem();
+ mallocd_res = 1;
res->ai_flags = hints.ai_flags;
res->ai_family = hints.ai_family;
res->ai_protocol = hints.ai_protocol;
@@ -326,7 +425,7 @@ create_service(struct netconfig *nconf)
sin->sin_addr.s_addr = htonl(INADDR_ANY);
res->ai_addr = (struct sockaddr*) sin;
res->ai_addrlen = (socklen_t)
- sizeof(res->ai_addr);
+ sizeof(struct sockaddr_in);
break;
case AF_INET6:
sin6 = malloc(sizeof(struct sockaddr_in6));
@@ -336,10 +435,13 @@ create_service(struct netconfig *nconf)
sin6->sin6_port = htons(0);
sin6->sin6_addr = in6addr_any;
res->ai_addr = (struct sockaddr*) sin6;
- res->ai_addrlen = (socklen_t) sizeof(res->ai_addr);
+ res->ai_addrlen = (socklen_t)
+ sizeof(struct sockaddr_in6);
break;
default:
- break;
+ syslog(LOG_ERR, "bad addr fam %d",
+ res->ai_family);
+ exit(1);
}
} else {
if ((aicode = getaddrinfo(NULL, svcport_str,
@@ -348,6 +450,7 @@ create_service(struct netconfig *nconf)
"cannot get local address for %s: %s",
nconf->nc_netid,
gai_strerror(aicode));
+ close(fd);
continue;
}
}
@@ -357,16 +460,91 @@ create_service(struct netconfig *nconf)
syslog(LOG_ERR,
"cannot get local address for %s: %s",
nconf->nc_netid, gai_strerror(aicode));
+ close(fd);
continue;
}
}
+ /* Store the fd. */
+ sock_fd[sock_fdcnt - 1] = fd;
+
+ /* Now, attempt the bind. */
r = bindresvport_sa(fd, res->ai_addr);
if (r != 0) {
+ if (errno == EADDRINUSE && mallocd_svcport != 0) {
+ if (mallocd_res != 0) {
+ free(res->ai_addr);
+ free(res);
+ } else
+ freeaddrinfo(res);
+ return (-1);
+ }
syslog(LOG_ERR, "bindresvport_sa: %m");
exit(1);
}
+ if (svcport_str == NULL) {
+ svcport_str = malloc(NI_MAXSERV * sizeof(char));
+ if (svcport_str == NULL)
+ out_of_mem();
+ mallocd_svcport = 1;
+
+ if (getnameinfo(res->ai_addr,
+ res->ai_addr->sa_len, NULL, NI_MAXHOST,
+ svcport_str, NI_MAXSERV * sizeof(char),
+ NI_NUMERICHOST | NI_NUMERICSERV))
+ errx(1, "Cannot get port number");
+ }
+ if (mallocd_res != 0) {
+ free(res->ai_addr);
+ free(res);
+ } else
+ freeaddrinfo(res);
+ res = NULL;
+ }
+ return (0);
+}
+
+/*
+ * Called after all the create_service() calls have succeeded, to complete
+ * the setup and registration.
+ */
+static void
+complete_service(struct netconfig *nconf, char *port_str)
+{
+ struct addrinfo hints, *res = NULL;
+ struct __rpc_sockinfo si;
+ struct netbuf servaddr;
+ SVCXPRT *transp = NULL;
+ int aicode, fd, nhostsbak;
+ int registered = 0;
+
+ if ((nconf->nc_semantics != NC_TPI_CLTS) &&
+ (nconf->nc_semantics != NC_TPI_COTS) &&
+ (nconf->nc_semantics != NC_TPI_COTS_ORD))
+ return; /* not my type */
+
+ /*
+ * XXX - using RPC library internal functions.
+ */
+ if (!__rpc_nconf2sockinfo(nconf, &si)) {
+ syslog(LOG_ERR, "cannot get information for %s",
+ nconf->nc_netid);
+ return;
+ }
+
+ nhostsbak = nhosts;
+ while (nhostsbak > 0) {
+ --nhostsbak;
+ if (sock_fdpos >= sock_fdcnt) {
+ /* Should never happen. */
+ syslog(LOG_ERR, "Ran out of socket fd's");
+ return;
+ }
+ fd = sock_fd[sock_fdpos++];
+ if (fd < 0)
+ continue;
+
if (nconf->nc_semantics != NC_TPI_CLTS)
listen(fd, SOMAXCONN);
@@ -397,19 +575,8 @@ create_service(struct netconfig *nconf)
hints.ai_socktype = si.si_socktype;
hints.ai_protocol = si.si_proto;
- if (svcport_str == NULL) {
- svcport_str = malloc(NI_MAXSERV * sizeof(char));
- if (svcport_str == NULL)
- out_of_mem();
-
- if (getnameinfo(res->ai_addr,
- res->ai_addr->sa_len, NULL, NI_MAXHOST,
- svcport_str, NI_MAXSERV * sizeof(char),
- NI_NUMERICHOST | NI_NUMERICSERV))
- errx(1, "Cannot get port number");
- }
- if((aicode = getaddrinfo(NULL, svcport_str, &hints,
+ if ((aicode = getaddrinfo(NULL, port_str, &hints,
&res)) != 0) {
syslog(LOG_ERR, "cannot get local address: %s",
gai_strerror(aicode));
@@ -428,6 +595,23 @@ create_service(struct netconfig *nconf)
} /* end while */
}
+/*
+ * Clear out sockets after a failure to bind one of them, so that the
+ * cycle of socket creation/binding can start anew.
+ */
+static void
+clearout_service(void)
+{
+ int i;
+
+ for (i = 0; i < sock_fdcnt; i++) {
+ if (sock_fd[i] >= 0) {
+ shutdown(sock_fd[i], SHUT_RDWR);
+ close(sock_fd[i]);
+ }
+ }
+}
+
static void
usage()
{
diff --git a/usr.sbin/rtsold/rtsol.c b/usr.sbin/rtsold/rtsol.c
index 76ebe96..afa935e 100644
--- a/usr.sbin/rtsold/rtsol.c
+++ b/usr.sbin/rtsold/rtsol.c
@@ -247,7 +247,7 @@ rtsol_input(int s)
struct nd_opt_rdnss *rdnss;
struct nd_opt_dnssl *dnssl;
size_t len;
- char nsbuf[INET6_ADDRSTRLEN + 1 + IFNAMSIZ + 1 + 1];
+ char nsbuf[INET6_ADDRSTRLEN + 1 + IFNAMSIZ + 1];
char dname[NI_MAXHOST];
struct timeval now;
struct timeval lifetime;
diff --git a/usr.sbin/usbdump/usbdump.8 b/usr.sbin/usbdump/usbdump.8
index a02f34e..104c3b3 100644
--- a/usr.sbin/usbdump/usbdump.8
+++ b/usr.sbin/usbdump/usbdump.8
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd December 4, 2010
+.Dd May 31, 2011
.Dt USBDUMP 8
.Os
.Sh NAME
@@ -63,16 +63,16 @@ Write the raw packets to
.Ar file .
.El
.Sh EXAMPLES
-Captures USB raw packets on usbus2:
+Capture the USB raw packets on usbus2:
.Pp
.Dl "usbdump -i usbus2 -s 256 -v"
.Pp
-Dumps the USB raw packets of usbus2 into the file without packet
+Dump the USB raw packets of usbus2 into the file without packet
size limit:
.Pp
.Dl "usbdump -i usbus2 -s 0 -w /tmp/dump_pkts"
.Pp
-Read the USB raw packets from previous file:
+Read and display the USB raw packets from previous file:
.Pp
.Dl "usbdump -r /tmp/dump_pkts -v"
.Sh OUTPUT FORMAT
OpenPOWER on IntegriCloud