summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--Makefile.inc1111
-rw-r--r--Makefile.libcompat46
-rw-r--r--ObsoleteFiles.inc3
-rw-r--r--UPDATING9
-rw-r--r--bin/csh/Makefile2
-rw-r--r--bin/freebsd-version/freebsd-version.13
-rw-r--r--bin/sh/tests/builtins/Makefile1
-rw-r--r--bin/sh/tests/builtins/trap17.010
-rw-r--r--bin/sh/trap.c5
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c5
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c3
-rw-r--r--cddl/contrib/opensolaris/lib/libzpool/common/kernel.c7
-rw-r--r--cddl/contrib/opensolaris/lib/libzpool/common/sys/zfs_context.h3
-rw-r--r--contrib/bmake/ChangeLog17
-rw-r--r--contrib/bmake/Makefile6
-rw-r--r--contrib/bmake/bmake.15
-rw-r--r--contrib/bmake/bmake.cat14
-rw-r--r--contrib/bmake/make.15
-rw-r--r--contrib/bmake/meta.c10
-rw-r--r--contrib/bmake/mk/ChangeLog23
-rw-r--r--contrib/bmake/mk/dirdeps.mk13
-rw-r--r--contrib/bmake/mk/install-mk4
-rw-r--r--contrib/bmake/mk/meta.autodep.mk4
-rw-r--r--contrib/bmake/mk/meta.stage.mk4
-rw-r--r--contrib/bmake/mk/sys.dependfile.mk4
-rw-r--r--contrib/bmake/parse.c7
-rw-r--r--contrib/bmake/suff.c27
-rw-r--r--contrib/bmake/var.c10
-rw-r--r--contrib/bsnmp/snmp_mibII/mibII_tcp.c16
-rw-r--r--contrib/byacc/CHANGES27
-rw-r--r--contrib/byacc/MANIFEST2
-rw-r--r--contrib/byacc/VERSION2
-rw-r--r--contrib/byacc/aclocal.m415
-rwxr-xr-xcontrib/byacc/config.guess27
-rwxr-xr-xcontrib/byacc/config.sub25
-rw-r--r--contrib/byacc/main.c30
-rw-r--r--contrib/byacc/package/byacc.spec4
-rw-r--r--contrib/byacc/package/debian/changelog6
-rw-r--r--contrib/byacc/package/debian/copyright4
-rw-r--r--contrib/byacc/package/mingw-byacc.spec4
-rw-r--r--contrib/byacc/package/pkgsrc/Makefile4
-rw-r--r--contrib/byacc/reader.c4
-rw-r--r--contrib/elftoolchain/elfcopy/elfcopy.h3
-rw-r--r--contrib/elftoolchain/elfcopy/segments.c270
-rw-r--r--contrib/libc++/include/__config34
-rw-r--r--contrib/libcxxrt/guard.cc2
-rw-r--r--contrib/libxo/bin/Makefile.am29
-rw-r--r--contrib/libxo/bin/Zaliases29
-rwxr-xr-xcontrib/libxo/bin/setup.sh33
-rw-r--r--contrib/libxo/build/.create0
-rwxr-xr-xcontrib/libxo/install-sh366
-rw-r--r--contrib/libxo/libxo/xo_config.h.in246
-rw-r--r--contrib/llvm/include/llvm/Support/ThreadPool.h1
-rw-r--r--contrib/llvm/lib/Target/X86/X86ISelLowering.cpp2
-rw-r--r--contrib/ofed/libcxgb4/src/cq.c2
-rw-r--r--contrib/ofed/libcxgb4/src/dev.c7
-rw-r--r--contrib/ofed/libcxgb4/src/libcxgb4.h5
-rw-r--r--contrib/ofed/libcxgb4/src/qp.c2
-rw-r--r--contrib/ofed/libcxgb4/src/t4.h12
-rw-r--r--contrib/ofed/libcxgb4/src/verbs.c22
-rw-r--r--contrib/ofed/management/infiniband-diags/src/ibnetdiscover.c4
-rw-r--r--contrib/ofed/management/opensm/include/vendor/osm_vendor.h2
-rw-r--r--etc/autofs/special_hosts4
-rwxr-xr-xetc/autofs/special_media25
-rw-r--r--etc/mtree/BSD.usr.dist2
-rwxr-xr-xetc/rc.d/msgs22
-rwxr-xr-xetc/rc.d/pf6
-rw-r--r--gnu/lib/csu/Makefile1
-rw-r--r--include/paths.h1
-rw-r--r--include/stdlib.h2
-rw-r--r--kerberos5/Makefile2
-rw-r--r--kerberos5/lib/libroken/Makefile1
-rw-r--r--lib/clang/libllvmsupport/Makefile1
-rw-r--r--lib/csu/powerpc64/Makefile3
-rw-r--r--lib/libc/Makefile3
-rw-r--r--lib/libc/aarch64/Symbol.map2
-rw-r--r--lib/libc/amd64/Symbol.map2
-rw-r--r--lib/libc/arm/Symbol.map3
-rw-r--r--lib/libc/db/mpool/Makefile.inc5
-rw-r--r--lib/libc/gen/Makefile.inc6
-rw-r--r--lib/libc/i386/Symbol.map2
-rw-r--r--lib/libc/iconv/Makefile.inc6
-rw-r--r--lib/libc/locale/euc.c6
-rw-r--r--lib/libc/locale/mskanji.c2
-rw-r--r--lib/libc/mips/Symbol.map3
-rw-r--r--lib/libc/net/Makefile.inc1
-rw-r--r--lib/libc/posix1e/Makefile.inc4
-rw-r--r--lib/libc/powerpc/Symbol.map3
-rw-r--r--lib/libc/powerpc64/Symbol.map3
-rw-r--r--lib/libc/riscv/Symbol.map2
-rw-r--r--lib/libc/secure/Makefile.inc7
-rw-r--r--lib/libc/sparc64/Symbol.map3
-rw-r--r--lib/libc/stdio/open_memstream.34
-rw-r--r--lib/libc/stdtime/Makefile.inc1
-rw-r--r--lib/libc/sys/aio_return.24
-rw-r--r--lib/libc/sys/aio_waitcomplete.24
-rw-r--r--lib/libc/sys/ktrace.24
-rw-r--r--lib/libc/sys/modfind.22
-rw-r--r--lib/libc/sys/ptrace.22
-rw-r--r--lib/libc/tests/ssp/Makefile2
-rw-r--r--lib/libclang_rt/asan_dynamic/Makefile1
-rw-r--r--lib/libcxxrt/Makefile5
-rw-r--r--lib/libdevinfo/Makefile2
-rw-r--r--lib/libfetch/fetch.328
-rw-r--r--lib/libkvm/kvm_amd64.c2
-rw-r--r--lib/libstand/Makefile2
-rw-r--r--lib/libstand/bootp.c8
-rw-r--r--lib/libstand/bootp.h1
-rw-r--r--lib/libstand/bswap.c57
-rw-r--r--lib/libstand/globals.c3
-rw-r--r--lib/libstand/net.h1
-rw-r--r--lib/libstand/stand.h5
-rw-r--r--lib/libsysdecode/errno.c2
-rw-r--r--lib/libthr/Makefile2
-rw-r--r--lib/libthr/thread/thr_fork.c6
-rw-r--r--lib/libthr/thread/thr_init.c26
-rw-r--r--lib/libthr/thread/thr_mutex.c75
-rw-r--r--lib/libthr/thread/thr_private.h11
-rw-r--r--lib/libthr/thread/thr_pshared.c14
-rw-r--r--lib/libthr/thread/thr_pspinlock.c107
-rw-r--r--lib/libthr/thread/thr_rtld.c1
-rw-r--r--lib/libxo/Makefile2
-rw-r--r--lib/libxo/tests/Makefile9
-rw-r--r--lib/libxo/xo_config.h (renamed from contrib/libxo/libxo/xo_config.h)0
-rw-r--r--lib/libz/Makefile1
-rw-r--r--lib/msun/arm/Makefile.inc2
-rw-r--r--lib/ncurses/ncurses/Makefile6
-rw-r--r--libexec/dma/Makefile.inc2
-rw-r--r--libexec/dma/dmagent/Makefile7
-rw-r--r--libexec/rtld-elf/Makefile3
-rw-r--r--release/doc/en_US.ISO8859-1/relnotes/article.xml5
-rw-r--r--release/picobsd/build/Makefile.conf3
-rw-r--r--sbin/atm/atmconfig/atmconfig.83
-rw-r--r--sbin/casperd/Makefile18
-rw-r--r--sbin/devd/devd.cc21
-rw-r--r--sbin/devd/devd.conf.511
-rw-r--r--sbin/ifconfig/ifieee80211.c95
-rw-r--r--sbin/ifconfig/sfp.c28
-rw-r--r--sbin/kldstat/Makefile.depend1
-rw-r--r--sbin/kldstat/kldstat.84
-rw-r--r--sbin/kldstat/kldstat.c30
-rw-r--r--sbin/ping/ping.c4
-rw-r--r--sbin/restore/tape.c1
-rw-r--r--secure/Makefile2
-rw-r--r--share/dtrace/Makefile6
-rw-r--r--share/dtrace/mbuf.d210
-rw-r--r--share/man/man4/amdsbwd.46
-rw-r--r--share/man/man4/capsicum.42
-rw-r--r--share/man/man4/cfi.45
-rw-r--r--share/man/man4/cyapa.44
-rw-r--r--share/man/man4/ddb.42
-rw-r--r--share/man/man4/filemon.455
-rw-r--r--share/man/man4/iscsi_initiator.42
-rw-r--r--share/man/man4/lagg.42
-rw-r--r--share/man/man4/pcm.42
-rw-r--r--share/man/man4/sppp.41
-rw-r--r--share/man/man4/uart.42
-rw-r--r--share/man/man4/udl.41
-rw-r--r--share/man/man4/vxlan.44
-rw-r--r--share/man/man4/wbwd.449
-rw-r--r--share/man/man5/make.conf.58
-rw-r--r--share/man/man5/periodic.conf.58
-rw-r--r--share/man/man5/src.conf.517
-rw-r--r--share/man/man7/build.723
-rw-r--r--share/man/man7/hier.74
-rw-r--r--share/man/man7/ports.76
-rw-r--r--share/man/man9/Makefile6
-rw-r--r--share/man/man9/SYSCALL_MODULE.915
-rw-r--r--share/man/man9/counter.948
-rw-r--r--share/man/man9/fail.991
-rw-r--r--share/man/man9/kqueue.92
-rw-r--r--share/man/man9/netisr.92
-rw-r--r--share/man/man9/osd.964
-rw-r--r--share/man/man9/rwlock.919
-rw-r--r--share/man/man9/sx.922
-rw-r--r--share/misc/bsd-family-tree10
-rw-r--r--share/misc/pci_vendors899
-rw-r--r--share/mk/bsd.README8
-rw-r--r--share/mk/bsd.clang-analyze.mk15
-rw-r--r--share/mk/bsd.cpu.mk15
-rw-r--r--share/mk/bsd.dep.mk57
-rw-r--r--share/mk/bsd.lib.mk44
-rw-r--r--share/mk/bsd.opts.mk7
-rw-r--r--share/mk/bsd.prog.mk8
-rw-r--r--share/mk/bsd.progs.mk2
-rw-r--r--share/mk/bsd.sys.mk5
-rw-r--r--share/mk/dirdeps.mk13
-rw-r--r--share/mk/local.dirdeps.mk9
-rw-r--r--share/mk/local.meta.sys.mk5
-rw-r--r--share/mk/local.sys.mk4
-rw-r--r--share/mk/meta.stage.mk4
-rw-r--r--share/mk/src.opts.mk1
-rw-r--r--sys/amd64/amd64/autoconf.c132
-rw-r--r--sys/amd64/amd64/sys_machdep.c4
-rw-r--r--sys/amd64/amd64/vm_machdep.c7
-rw-r--r--sys/amd64/cloudabi64/cloudabi64_sysvec.c1
-rw-r--r--sys/amd64/conf/GENERIC.hints1
-rw-r--r--sys/amd64/include/intr_machdep.h2
-rw-r--r--sys/amd64/include/md_var.h3
-rw-r--r--sys/amd64/linux32/linux32_dummy.c1
-rw-r--r--sys/amd64/linux32/linux32_proto.h6
-rw-r--r--sys/amd64/linux32/linux32_syscall.h2
-rw-r--r--sys/amd64/linux32/linux32_syscalls.c2
-rw-r--r--sys/amd64/linux32/linux32_sysent.c4
-rw-r--r--sys/amd64/linux32/linux32_systrace_args.c22
-rw-r--r--sys/amd64/linux32/syscalls.master2
-rw-r--r--sys/arm/allwinner/a10_gpio.c12
-rw-r--r--sys/arm/allwinner/a10_hdmi.c49
-rw-r--r--sys/arm/allwinner/a10_mmc.c1
-rw-r--r--sys/arm/allwinner/allwinner_machdep.c17
-rw-r--r--sys/arm/amlogic/aml8726/aml8726_mmc.c1
-rw-r--r--sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c1
-rw-r--r--sys/arm/arm/gic.c508
-rw-r--r--sys/arm/arm/machdep.c120
-rw-r--r--sys/arm/arm/machdep_intr.c176
-rw-r--r--sys/arm/arm/mp_machdep.c24
-rw-r--r--sys/arm/arm/nexus.c18
-rw-r--r--sys/arm/arm/vm_machdep.c6
-rw-r--r--sys/arm/at91/at91.c6
-rw-r--r--sys/arm/at91/at91_mci.c1
-rw-r--r--sys/arm/at91/at91_pinctrl.c4
-rw-r--r--sys/arm/at91/board_tsc4370.c2
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_common.c23
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_sdhci.c1
-rw-r--r--sys/arm/broadcom/bcm2835/std.rpi1
-rw-r--r--sys/arm/cavium/cns11xx/econa.c6
-rw-r--r--sys/arm/conf/A102
-rw-r--r--sys/arm/conf/A202
-rw-r--r--sys/arm/conf/ARMADA38X3
-rw-r--r--sys/arm/conf/ATMEL5
-rw-r--r--sys/arm/conf/BEAGLEBONE6
-rw-r--r--sys/arm/conf/CNS11XXNAS5
-rw-r--r--sys/arm/conf/EFIKA_MX3
-rw-r--r--sys/arm/conf/ETHERNUT53
-rw-r--r--sys/arm/conf/IMX533
-rw-r--r--sys/arm/conf/JETSON-TK137
-rw-r--r--sys/arm/conf/NOTES4
-rw-r--r--sys/arm/conf/RK31884
-rw-r--r--sys/arm/conf/SAM9260EK3
-rw-r--r--sys/arm/conf/TEGRA124157
-rw-r--r--sys/arm/conf/std.arm1
-rw-r--r--sys/arm/conf/std.armv62
-rw-r--r--sys/arm/freescale/imx/imx_gpio.c327
-rw-r--r--sys/arm/freescale/imx/imx_sdhci.c1
-rw-r--r--sys/arm/include/atags.h2
-rw-r--r--sys/arm/include/intr.h13
-rw-r--r--sys/arm/include/machdep.h3
-rw-r--r--sys/arm/include/smp.h2
-rw-r--r--sys/arm/lpc/lpc_mmc.c1
-rw-r--r--sys/arm/mv/files.mv1
-rw-r--r--sys/arm/mv/mpic.c166
-rw-r--r--sys/arm/mv/mv_localbus.c4
-rw-r--r--sys/arm/nvidia/as3722.c411
-rw-r--r--sys/arm/nvidia/as3722.h323
-rw-r--r--sys/arm/nvidia/as3722_gpio.c577
-rw-r--r--sys/arm/nvidia/as3722_regulators.c811
-rw-r--r--sys/arm/nvidia/as3722_rtc.c115
-rw-r--r--sys/arm/nvidia/tegra124/files.tegra12457
-rw-r--r--sys/arm/nvidia/tegra124/std.tegra12414
-rw-r--r--sys/arm/nvidia/tegra124/tegra124_car.c613
-rw-r--r--sys/arm/nvidia/tegra124/tegra124_car.h337
-rw-r--r--sys/arm/nvidia/tegra124/tegra124_clk_per.c810
-rw-r--r--sys/arm/nvidia/tegra124/tegra124_clk_pll.c1066
-rw-r--r--sys/arm/nvidia/tegra124/tegra124_clk_super.c265
-rw-r--r--sys/arm/nvidia/tegra124/tegra124_coretemp.c273
-rw-r--r--sys/arm/nvidia/tegra124/tegra124_cpufreq.c583
-rw-r--r--sys/arm/nvidia/tegra124/tegra124_machdep.c173
-rw-r--r--sys/arm/nvidia/tegra124/tegra124_mp.c127
-rw-r--r--sys/arm/nvidia/tegra124/tegra124_mp.h (renamed from sys/compat/cloudabi/cloudabi_syscalldefs.h)27
-rw-r--r--sys/arm/nvidia/tegra124/tegra124_pmc.c566
-rw-r--r--sys/arm/nvidia/tegra124/tegra124_xusbpadctl.c603
-rw-r--r--sys/arm/nvidia/tegra_abpmisc.c194
-rw-r--r--sys/arm/nvidia/tegra_ahci.c627
-rw-r--r--sys/arm/nvidia/tegra_efuse.c368
-rw-r--r--sys/arm/nvidia/tegra_efuse.h61
-rw-r--r--sys/arm/nvidia/tegra_ehci.c322
-rw-r--r--sys/arm/nvidia/tegra_gpio.c480
-rw-r--r--sys/arm/nvidia/tegra_i2c.c804
-rw-r--r--sys/arm/nvidia/tegra_lic.c288
-rw-r--r--sys/arm/nvidia/tegra_pcie.c1691
-rw-r--r--sys/arm/nvidia/tegra_pinmux.c804
-rw-r--r--sys/arm/nvidia/tegra_pmc.h115
-rw-r--r--sys/arm/nvidia/tegra_rtc.c303
-rw-r--r--sys/arm/nvidia/tegra_sdhci.c465
-rw-r--r--sys/arm/nvidia/tegra_soctherm.c696
-rw-r--r--sys/arm/nvidia/tegra_soctherm_if.m42
-rw-r--r--sys/arm/nvidia/tegra_uart.c251
-rw-r--r--sys/arm/nvidia/tegra_usbphy.c839
-rw-r--r--sys/arm/ti/aintc.c178
-rw-r--r--sys/arm/ti/am335x/am335x_prcm.c10
-rw-r--r--sys/arm/ti/cpsw/if_cpsw.c1735
-rw-r--r--sys/arm/ti/cpsw/if_cpswreg.h213
-rw-r--r--sys/arm/ti/cpsw/if_cpswvar.h82
-rw-r--r--sys/arm/ti/files.ti1
-rw-r--r--sys/arm/ti/omap4/omap4_gpio.c1
-rw-r--r--sys/arm/ti/omap4/omap4_wugen.c64
-rw-r--r--sys/arm/ti/ti_adc.c14
-rw-r--r--sys/arm/ti/ti_gpio.c340
-rw-r--r--sys/arm/ti/ti_gpio.h19
-rw-r--r--sys/arm/ti/ti_hwmods.c3
-rw-r--r--sys/arm/ti/ti_prcm.h4
-rw-r--r--sys/arm/ti/ti_sdhci.c1
-rw-r--r--sys/arm/ti/ti_spi.c582
-rw-r--r--sys/arm/ti/ti_spireg.h97
-rw-r--r--sys/arm/ti/ti_spivar.h71
-rw-r--r--sys/arm/xscale/ixp425/avila_ata.c2
-rw-r--r--sys/arm/xscale/ixp425/ixp425.c8
-rw-r--r--sys/arm/xscale/pxa/pxa_obio.c6
-rw-r--r--sys/arm/xscale/pxa/pxa_smi.c4
-rw-r--r--sys/arm64/arm64/bzero.S206
-rw-r--r--sys/arm64/arm64/copyinout.S136
-rw-r--r--sys/arm64/arm64/exception.S4
-rw-r--r--sys/arm64/arm64/genassym.c2
-rw-r--r--sys/arm64/arm64/gic.c46
-rw-r--r--sys/arm64/arm64/intr_machdep.c8
-rw-r--r--sys/arm64/arm64/locore.S52
-rw-r--r--sys/arm64/arm64/machdep.c39
-rw-r--r--sys/arm64/arm64/minidump_machdep.c6
-rw-r--r--sys/arm64/arm64/mp_machdep.c89
-rw-r--r--sys/arm64/arm64/nexus.c12
-rw-r--r--sys/arm64/arm64/pmap.c812
-rw-r--r--sys/arm64/arm64/support.S36
-rw-r--r--sys/arm64/arm64/swtch.S4
-rw-r--r--sys/arm64/arm64/vm_machdep.c4
-rw-r--r--sys/arm64/cloudabi64/cloudabi64_sysvec.c1
-rw-r--r--sys/arm64/include/armreg.h6
-rw-r--r--sys/arm64/include/cpu.h4
-rw-r--r--sys/arm64/include/intr.h10
-rw-r--r--sys/arm64/include/machdep.h2
-rw-r--r--sys/arm64/include/pcb.h2
-rw-r--r--sys/arm64/include/pmap.h6
-rw-r--r--sys/arm64/include/pte.h19
-rw-r--r--sys/arm64/include/smp.h2
-rw-r--r--sys/arm64/include/vmparam.h2
-rw-r--r--sys/boot/Makefile.amd641
-rw-r--r--sys/boot/Makefile.i3861
-rw-r--r--sys/boot/common/dev_net.c6
-rw-r--r--sys/boot/common/disk.c2
-rw-r--r--sys/boot/common/disk.h1
-rw-r--r--sys/boot/common/gpt.c2
-rw-r--r--sys/boot/common/gpt.h2
-rw-r--r--sys/boot/efi/Makefile8
-rw-r--r--sys/boot/fdt/dts/arm/bcm2836.dtsi17
-rw-r--r--sys/boot/fdt/dts/arm/beaglebone-black.dts20
-rw-r--r--sys/boot/fdt/dts/arm/tegra124-jetson-tk1-fbsd.dts (renamed from sys/dev/filemon/filemon_lock.c)51
-rw-r--r--sys/boot/geli/Makefile52
-rw-r--r--sys/boot/geli/Makefile.depend (renamed from sbin/casperd/Makefile.depend)13
-rw-r--r--sys/boot/geli/geliboot.c292
-rw-r--r--sys/boot/geli/geliboot.h86
-rw-r--r--sys/boot/geli/geliboot_crypto.c135
-rw-r--r--sys/boot/geli/pwgets.c83
-rw-r--r--sys/boot/i386/boot0/Makefile1
-rw-r--r--sys/boot/i386/boot2/Makefile1
-rw-r--r--sys/boot/i386/btx/btx/Makefile1
-rw-r--r--sys/boot/i386/btx/btxldr/Makefile1
-rw-r--r--sys/boot/i386/cdboot/Makefile1
-rw-r--r--sys/boot/i386/common/bootargs.h6
-rw-r--r--sys/boot/i386/common/cons.c7
-rw-r--r--sys/boot/i386/common/drv.c2
-rw-r--r--sys/boot/i386/common/drv.h2
-rw-r--r--sys/boot/i386/gptboot/Makefile17
-rw-r--r--sys/boot/i386/gptboot/Makefile.depend4
-rw-r--r--sys/boot/i386/gptboot/gptboot.c221
-rw-r--r--sys/boot/i386/gptzfsboot/Makefile15
-rw-r--r--sys/boot/i386/gptzfsboot/Makefile.depend3
-rw-r--r--sys/boot/i386/libi386/Makefile7
-rw-r--r--sys/boot/i386/libi386/Makefile.depend1
-rw-r--r--sys/boot/i386/libi386/biosdisk.c178
-rw-r--r--sys/boot/i386/libi386/pxe.c5
-rw-r--r--sys/boot/i386/loader/Makefile11
-rw-r--r--sys/boot/i386/loader/Makefile.depend1
-rw-r--r--sys/boot/i386/loader/main.c31
-rw-r--r--sys/boot/i386/pxeldr/Makefile1
-rw-r--r--sys/boot/i386/zfsboot/Makefile1
-rw-r--r--sys/boot/i386/zfsboot/zfsboot.c119
-rw-r--r--sys/boot/i386/zfsloader/Makefile.depend1
-rw-r--r--sys/boot/pc98/boot2/Makefile1
-rw-r--r--sys/boot/pc98/btx/btx/Makefile1
-rw-r--r--sys/boot/pc98/btx/btxldr/Makefile1
-rw-r--r--sys/boot/pc98/cdboot/Makefile1
-rw-r--r--sys/boot/zfs/libzfs.h1
-rw-r--r--sys/cam/ata/ata_da.c15
-rw-r--r--sys/cam/cam_ccb.h7
-rw-r--r--sys/cam/scsi/scsi_ch.c3
-rw-r--r--sys/cam/scsi/scsi_da.c15
-rw-r--r--sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c1
-rw-r--r--sys/cddl/compat/opensolaris/sys/vfs.h11
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c4
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/gfs.c4
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c18
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_prop.c13
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c33
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c4
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c4
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c14
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c68
-rw-r--r--sys/cddl/dev/dtrace/aarch64/dtrace_subr.c2
-rw-r--r--sys/cddl/dev/dtrace/amd64/dtrace_subr.c3
-rw-r--r--sys/cddl/dev/dtrace/arm/dtrace_subr.c2
-rw-r--r--sys/cddl/dev/dtrace/i386/dtrace_subr.c2
-rw-r--r--sys/cddl/dev/dtrace/mips/dtrace_subr.c2
-rw-r--r--sys/cddl/dev/dtrace/powerpc/dtrace_subr.c2
-rw-r--r--sys/compat/cloudabi/cloudabi_clock.c3
-rw-r--r--sys/compat/cloudabi/cloudabi_errno.c3
-rw-r--r--sys/compat/cloudabi/cloudabi_fd.c3
-rw-r--r--sys/compat/cloudabi/cloudabi_file.c21
-rw-r--r--sys/compat/cloudabi/cloudabi_futex.c25
-rw-r--r--sys/compat/cloudabi/cloudabi_mem.c3
-rw-r--r--sys/compat/cloudabi/cloudabi_proc.c3
-rw-r--r--sys/compat/cloudabi/cloudabi_proto.h4
-rw-r--r--sys/compat/cloudabi/cloudabi_sock.c20
-rw-r--r--sys/compat/cloudabi/cloudabi_thread.c3
-rw-r--r--sys/compat/cloudabi/cloudabi_util.h8
-rw-r--r--sys/compat/cloudabi64/Makefile6
-rw-r--r--sys/compat/cloudabi64/cloudabi64_fd.c3
-rw-r--r--sys/compat/cloudabi64/cloudabi64_module.c4
-rw-r--r--sys/compat/cloudabi64/cloudabi64_poll.c9
-rw-r--r--sys/compat/cloudabi64/cloudabi64_proto.h44
-rw-r--r--sys/compat/cloudabi64/cloudabi64_sock.c7
-rw-r--r--sys/compat/cloudabi64/cloudabi64_syscall.h2
-rw-r--r--sys/compat/cloudabi64/cloudabi64_syscalls.c2
-rw-r--r--sys/compat/cloudabi64/cloudabi64_sysent.c4
-rw-r--r--sys/compat/cloudabi64/cloudabi64_systrace_args.c80
-rw-r--r--sys/compat/cloudabi64/cloudabi64_thread.c3
-rw-r--r--sys/compat/cloudabi64/cloudabi64_util.h2
-rw-r--r--sys/compat/freebsd32/freebsd32_misc.c15
-rw-r--r--sys/compat/linux/linux_event.c21
-rw-r--r--sys/compat/linux/linux_mib.c47
-rw-r--r--sys/compat/linux/linux_misc.c44
-rw-r--r--sys/compat/linux/linux_socket.c40
-rw-r--r--sys/compat/linux/linux_stats.c59
-rw-r--r--sys/compat/linuxkpi/common/include/linux/bitops.h4
-rw-r--r--sys/compat/linuxkpi/common/include/linux/jiffies.h10
-rw-r--r--sys/compat/linuxkpi/common/include/linux/list.h1
-rw-r--r--sys/compat/linuxkpi/common/include/linux/wait.h47
-rw-r--r--sys/compat/linuxkpi/common/src/linux_compat.c10
-rw-r--r--sys/compat/ndis/kern_ndis.c4
-rw-r--r--sys/conf/NOTES3
-rw-r--r--sys/conf/files61
-rw-r--r--sys/conf/files.amd646
-rw-r--r--sys/conf/files.arm2
-rw-r--r--sys/conf/files.arm642
-rw-r--r--sys/conf/files.i3867
-rw-r--r--sys/conf/files.mips3
-rw-r--r--sys/conf/files.pc984
-rw-r--r--sys/conf/files.powerpc2
-rw-r--r--sys/conf/files.sparc646
-rw-r--r--sys/conf/kern.opts.mk10
-rw-r--r--sys/conf/kern.post.mk49
-rw-r--r--sys/conf/kern.pre.mk23
-rw-r--r--sys/conf/kmod.mk5
-rw-r--r--sys/contrib/cloudabi/cloudabi64_types.h225
-rw-r--r--sys/contrib/cloudabi/cloudabi_types_common.h463
-rw-r--r--sys/contrib/cloudabi/syscalldefs_md.h255
-rw-r--r--sys/contrib/cloudabi/syscalldefs_mi.h476
-rw-r--r--sys/contrib/cloudabi/syscalls.master (renamed from sys/compat/cloudabi64/syscalls.master)218
-rw-r--r--sys/contrib/rdma/krping/krping.c10
-rw-r--r--sys/ddb/db_ps.c12
-rw-r--r--sys/dev/acpica/acpi.c12
-rw-r--r--sys/dev/acpica/acpi_hpet.c2
-rw-r--r--sys/dev/acpica/acpi_timer.c2
-rw-r--r--sys/dev/advansys/adv_isa.c2
-rw-r--r--sys/dev/ahci/ahci.c2
-rw-r--r--sys/dev/ahci/ahci.h4
-rw-r--r--sys/dev/ahci/ahci_pci.c5
-rw-r--r--sys/dev/amdsbwd/amdsbwd.c20
-rw-r--r--sys/dev/arcmsr/arcmsr.c23
-rw-r--r--sys/dev/ata/ata-lowlevel.c2
-rw-r--r--sys/dev/ath/if_ath_lna_div.c2
-rw-r--r--sys/dev/atkbdc/atkbdc_subr.c2
-rw-r--r--sys/dev/bhnd/bhnd.c4
-rw-r--r--sys/dev/bhnd/bhndb/bhndb.c4
-rw-r--r--sys/dev/bwn/if_bwn.c8
-rw-r--r--sys/dev/bxe/bxe.c94
-rw-r--r--sys/dev/bxe/bxe.h11
-rw-r--r--sys/dev/cardbus/cardbus_cis.c3
-rw-r--r--sys/dev/ctau/if_ct.c6
-rw-r--r--sys/dev/cxgb/cxgb_sge.c6
-rw-r--r--sys/dev/cxgbe/adapter.h22
-rw-r--r--sys/dev/cxgbe/common/t4_hw.c15
-rw-r--r--sys/dev/cxgbe/firmware/t4fw_cfg.txt157
-rw-r--r--sys/dev/cxgbe/firmware/t5fw_cfg.txt197
-rw-r--r--sys/dev/cxgbe/iw_cxgbe/cm.c271
-rw-r--r--sys/dev/cxgbe/iw_cxgbe/cq.c6
-rw-r--r--sys/dev/cxgbe/iw_cxgbe/iw_cxgbe.h14
-rw-r--r--sys/dev/cxgbe/iw_cxgbe/mem.c34
-rw-r--r--sys/dev/cxgbe/iw_cxgbe/qp.c16
-rw-r--r--sys/dev/cxgbe/iw_cxgbe/t4.h3
-rw-r--r--sys/dev/cxgbe/iw_cxgbe/user.h1
-rw-r--r--sys/dev/cxgbe/offload.h2
-rw-r--r--sys/dev/cxgbe/t4_main.c46
-rw-r--r--sys/dev/cxgbe/t4_sge.c9
-rw-r--r--sys/dev/drm2/i915/i915_gem.c24
-rw-r--r--sys/dev/drm2/i915/intel_pm.c30
-rw-r--r--sys/dev/drm2/ttm/ttm_bo_vm.c27
-rw-r--r--sys/dev/e1000/if_igb.c60
-rw-r--r--sys/dev/e1000/if_igb.h6
-rw-r--r--sys/dev/ed/if_ed_3c503.c2
-rw-r--r--sys/dev/ed/if_ed_cbus.c22
-rw-r--r--sys/dev/extres/clk/clk.c79
-rw-r--r--sys/dev/extres/clk/clk.h3
-rw-r--r--sys/dev/extres/clk/clk_bus.c93
-rw-r--r--sys/dev/extres/clk/clk_div.c13
-rw-r--r--sys/dev/extres/clk/clk_fixed.c194
-rw-r--r--sys/dev/extres/clk/clk_fixed.h3
-rw-r--r--sys/dev/extres/clk/clk_gate.c13
-rw-r--r--sys/dev/extres/clk/clk_mux.c16
-rw-r--r--sys/dev/extres/clk/clkdev_if.m85
-rw-r--r--sys/dev/extres/phy/phy.c235
-rw-r--r--sys/dev/extres/phy/phy.h63
-rw-r--r--sys/dev/extres/phy/phy_if.m84
-rw-r--r--sys/dev/extres/regulator/regdev_if.m56
-rw-r--r--sys/dev/extres/regulator/regnode_if.m82
-rw-r--r--sys/dev/extres/regulator/regulator.c984
-rw-r--r--sys/dev/extres/regulator/regulator.h127
-rw-r--r--sys/dev/extres/regulator/regulator_bus.c89
-rw-r--r--sys/dev/extres/regulator/regulator_fixed.c456
-rw-r--r--sys/dev/extres/regulator/regulator_fixed.h (renamed from sys/compat/cloudabi64/cloudabi64_syscalldefs.h)29
-rw-r--r--sys/dev/fdt/fdt_common.c13
-rw-r--r--sys/dev/fdt/fdt_common.h1
-rw-r--r--sys/dev/fdt/simplebus.c6
-rw-r--r--sys/dev/filemon/filemon.c356
-rw-r--r--sys/dev/filemon/filemon_wrapper.c423
-rw-r--r--sys/dev/flash/mx25l.c127
-rw-r--r--sys/dev/flash/mx25lreg.h2
-rw-r--r--sys/dev/gpio/gpiobus.c4
-rw-r--r--sys/dev/gpio/ofw_gpiobus.c3
-rw-r--r--sys/dev/hyperv/include/hyperv.h2
-rw-r--r--sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c50
-rw-r--r--sys/dev/hyperv/utilities/hv_heartbeat.c4
-rw-r--r--sys/dev/hyperv/utilities/hv_kvp.c33
-rw-r--r--sys/dev/hyperv/utilities/hv_shutdown.c4
-rw-r--r--sys/dev/hyperv/utilities/hv_timesync.c4
-rw-r--r--sys/dev/hyperv/vmbus/hv_connection.c40
-rw-r--r--sys/dev/hyperv/vmbus/hv_et.c2
-rw-r--r--sys/dev/hyperv/vmbus/hv_hv.c30
-rw-r--r--sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c110
-rw-r--r--sys/dev/hyperv/vmbus/hv_vmbus_priv.h8
-rw-r--r--sys/dev/ichwd/ichwd.c14
-rw-r--r--sys/dev/iicbus/iicbus.c2
-rw-r--r--sys/dev/iir/iir.c6
-rw-r--r--sys/dev/iir/iir_pci.c2
-rw-r--r--sys/dev/ipmi/ipmi.c53
-rw-r--r--sys/dev/isci/isci_controller.c10
-rw-r--r--sys/dev/isci/isci_io_request.c18
-rw-r--r--sys/dev/iscsi/iscsi.c3
-rw-r--r--sys/dev/iwn/if_iwn.c18
-rw-r--r--sys/dev/ixgbe/if_ix.c8
-rw-r--r--sys/dev/ixgbe/ix_txrx.c6
-rw-r--r--sys/dev/ixl/ixl_txrx.c6
-rw-r--r--sys/dev/le/lebuffer_sbus.c4
-rw-r--r--sys/dev/mca/mca_bus.c12
-rw-r--r--sys/dev/mfi/mfi.c4
-rw-r--r--sys/dev/mlx5/mlx5_en/mlx5_en_rx.c8
-rw-r--r--sys/dev/mmc/host/dwmmc.c1
-rw-r--r--sys/dev/mmc/mmc.c2
-rw-r--r--sys/dev/mmc/mmcreg.h7
-rw-r--r--sys/dev/mvs/mvs_pci.c2
-rw-r--r--sys/dev/mvs/mvs_soc.c2
-rw-r--r--sys/dev/mxge/if_mxge.c12
-rw-r--r--sys/dev/ncr/ncr.c14
-rw-r--r--sys/dev/nctgpio/nctgpio.c802
-rw-r--r--sys/dev/netmap/netmap_generic.c3
-rw-r--r--sys/dev/oce/oce_if.c6
-rw-r--r--sys/dev/ofw/ofw_iicbus.c6
-rw-r--r--sys/dev/ofw/ofwbus.c4
-rw-r--r--sys/dev/ofw/ofwpci.c628
-rw-r--r--sys/dev/ofw/ofwpci.h83
-rw-r--r--sys/dev/pccard/pccard.c34
-rw-r--r--sys/dev/pccard/pccard_cis.c12
-rw-r--r--sys/dev/pccbb/pccbb.c10
-rw-r--r--sys/dev/pccbb/pccbb_pci.c2
-rw-r--r--sys/dev/pci/pci.c22
-rw-r--r--sys/dev/pci/pci_host_generic.c6
-rw-r--r--sys/dev/pci/pci_pci.c34
-rw-r--r--sys/dev/pci/pci_subr.c8
-rw-r--r--sys/dev/ppbus/vpo.c16
-rw-r--r--sys/dev/ppc/ppc.c4
-rw-r--r--sys/dev/proto/proto_bus_isa.c2
-rw-r--r--sys/dev/qlxgb/qla_isr.c7
-rw-r--r--sys/dev/qlxge/qls_isr.c7
-rw-r--r--sys/dev/random/random_harvestq.c3
-rw-r--r--sys/dev/sdhci/sdhci_fdt.c1
-rw-r--r--sys/dev/sdhci/sdhci_pci.c1
-rw-r--r--sys/dev/sfxge/sfxge_mcdi.c5
-rw-r--r--sys/dev/sfxge/sfxge_nvram.c5
-rw-r--r--sys/dev/siba/siba.c4
-rw-r--r--sys/dev/siis/siis.c2
-rw-r--r--sys/dev/sound/isa/ad1816.c4
-rw-r--r--sys/dev/sound/isa/ess.c6
-rw-r--r--sys/dev/sound/isa/mss.c4
-rw-r--r--sys/dev/sound/isa/sb16.c4
-rw-r--r--sys/dev/sound/isa/sb8.c2
-rw-r--r--sys/dev/sound/pci/als4000.c2
-rw-r--r--sys/dev/sound/pci/atiixp.c2
-rw-r--r--sys/dev/sound/pci/aureal.c2
-rw-r--r--sys/dev/sound/pci/cmi.c2
-rw-r--r--sys/dev/sound/pci/cs4281.c2
-rw-r--r--sys/dev/sound/pci/csapcm.c2
-rw-r--r--sys/dev/sound/pci/ds1.c2
-rw-r--r--sys/dev/sound/pci/emu10k1.c2
-rw-r--r--sys/dev/sound/pci/emu10kx.c2
-rw-r--r--sys/dev/sound/pci/envy24.c2
-rw-r--r--sys/dev/sound/pci/envy24ht.c2
-rw-r--r--sys/dev/sound/pci/es137x.c2
-rw-r--r--sys/dev/sound/pci/fm801.c2
-rw-r--r--sys/dev/sound/pci/hda/hdac.c2
-rw-r--r--sys/dev/sound/pci/hda/hdac.h4
-rw-r--r--sys/dev/sound/pci/hdspe-pcm.c2
-rw-r--r--sys/dev/sound/pci/ich.c2
-rw-r--r--sys/dev/sound/pci/maestro.c2
-rw-r--r--sys/dev/sound/pci/maestro3.c2
-rw-r--r--sys/dev/sound/pci/neomagic.c2
-rw-r--r--sys/dev/sound/pci/solo.c2
-rw-r--r--sys/dev/sound/pci/t4dwave.c2
-rw-r--r--sys/dev/sound/pci/via8233.c2
-rw-r--r--sys/dev/sound/pci/via82c686.c2
-rw-r--r--sys/dev/sound/pci/vibes.c4
-rw-r--r--sys/dev/uart/uart_dev_ns8250.c13
-rw-r--r--sys/dev/uart/uart_dev_snps.c283
-rw-r--r--sys/dev/urtwn/if_urtwn.c (renamed from sys/dev/usb/wlan/if_urtwn.c)137
-rw-r--r--sys/dev/urtwn/if_urtwnreg.h (renamed from sys/dev/usb/wlan/if_urtwnreg.h)0
-rw-r--r--sys/dev/urtwn/if_urtwnvar.h (renamed from sys/dev/usb/wlan/if_urtwnvar.h)0
-rw-r--r--sys/dev/usb/controller/ehci_pci.c6
-rw-r--r--sys/dev/usb/controller/ohci_pci.c3
-rw-r--r--sys/dev/usb/controller/uhci_pci.c6
-rw-r--r--sys/dev/usb/controller/xhci_pci.c5
-rw-r--r--sys/dev/usb/usb_busdma.c27
-rw-r--r--sys/dev/usb/usbdevs1
-rw-r--r--sys/dev/usb/video/udl.c3
-rw-r--r--sys/dev/usb/wlan/if_rum.c275
-rw-r--r--sys/dev/usb/wlan/if_rumreg.h13
-rw-r--r--sys/dev/usb/wlan/if_rumvar.h10
-rw-r--r--sys/dev/vnic/nic_main.c24
-rw-r--r--sys/dev/vnic/nicvf_main.c26
-rw-r--r--sys/dev/vnic/nicvf_queues.c123
-rw-r--r--sys/dev/vnic/nicvf_queues.h2
-rw-r--r--sys/dev/vnic/thunder_bgx_fdt.c22
-rw-r--r--sys/dev/vt/hw/vga/vt_vga.c8
-rw-r--r--sys/dev/vxge/vxge.c9
-rw-r--r--sys/dev/wbwd/wbwd.c390
-rw-r--r--sys/dev/wl/if_wl.c2
-rw-r--r--sys/dev/wpi/if_wpi.c53
-rw-r--r--sys/dev/wpi/if_wpivar.h4
-rw-r--r--sys/dev/xe/if_xe.c4
-rw-r--r--sys/dev/xe/if_xe_pccard.c2
-rw-r--r--sys/dev/xen/blkfront/blkfront.c28
-rw-r--r--sys/dev/xen/blkfront/block.h7
-rw-r--r--sys/dev/xen/netfront/netfront.c7
-rw-r--r--sys/fs/autofs/autofs.c10
-rw-r--r--sys/fs/autofs/autofs.h7
-rw-r--r--sys/fs/autofs/autofs_vfsops.c9
-rw-r--r--sys/fs/autofs/autofs_vnops.c40
-rw-r--r--sys/fs/cd9660/cd9660_vnops.c6
-rw-r--r--sys/fs/ext2fs/ext2_alloc.c4
-rw-r--r--sys/fs/ext2fs/ext2_dinode.h1
-rw-r--r--sys/fs/ext2fs/ext2fs.h63
-rw-r--r--sys/geom/sched/g_sched.c3
-rw-r--r--sys/i386/conf/GENERIC.hints1
-rw-r--r--sys/i386/i386/vm_machdep.c7
-rw-r--r--sys/i386/include/intr_machdep.h2
-rw-r--r--sys/i386/include/md_var.h1
-rw-r--r--sys/i386/linux/linux_dummy.c1
-rw-r--r--sys/i386/linux/linux_proto.h6
-rw-r--r--sys/i386/linux/linux_syscall.h2
-rw-r--r--sys/i386/linux/linux_syscalls.c2
-rw-r--r--sys/i386/linux/linux_sysent.c4
-rw-r--r--sys/i386/linux/linux_systrace_args.c22
-rw-r--r--sys/i386/linux/syscalls.master2
-rw-r--r--sys/isa/isa_common.c8
-rw-r--r--sys/kern/imgact_binmisc.c13
-rw-r--r--sys/kern/imgact_elf.c4
-rw-r--r--sys/kern/init_sysent.c2
-rw-r--r--sys/kern/kern_condvar.c48
-rw-r--r--sys/kern/kern_descrip.c4
-rw-r--r--sys/kern/kern_exec.c4
-rw-r--r--sys/kern/kern_fail.c782
-rw-r--r--sys/kern/kern_linker.c2
-rw-r--r--sys/kern/kern_mbuf.c11
-rw-r--r--sys/kern/kern_osd.c263
-rw-r--r--sys/kern/kern_racct.c149
-rw-r--r--sys/kern/kern_rctl.c75
-rw-r--r--sys/kern/kern_sendfile.c56
-rw-r--r--sys/kern/kern_synch.c25
-rw-r--r--sys/kern/pic_if.m112
-rw-r--r--sys/kern/subr_bus.c32
-rw-r--r--sys/kern/subr_counter.c25
-rw-r--r--sys/kern/subr_intr.c534
-rw-r--r--sys/kern/subr_rman.c50
-rw-r--r--sys/kern/subr_sleepqueue.c121
-rw-r--r--sys/kern/subr_smp.c248
-rw-r--r--sys/kern/sys_generic.c24
-rw-r--r--sys/kern/syscalls.c2
-rw-r--r--sys/kern/syscalls.master4
-rw-r--r--sys/kern/systrace_args.c4
-rw-r--r--sys/kern/uipc_mbuf.c47
-rw-r--r--sys/kern/uipc_socket.c2
-rw-r--r--sys/kern/vfs_aio.c49
-rw-r--r--sys/kern/vfs_export.c4
-rw-r--r--sys/kern/vfs_mountroot.c3
-rw-r--r--sys/mips/atheros/apb.c6
-rw-r--r--sys/mips/beri/beri_simplebus.c4
-rw-r--r--sys/mips/mips/mips_pic.c7
-rw-r--r--sys/mips/mips/nexus.c8
-rw-r--r--sys/mips/nlm/xlp_pci.c2
-rw-r--r--sys/mips/nlm/xlp_simplebus.c4
-rw-r--r--sys/mips/rmi/iodi.c6
-rw-r--r--sys/mips/rmi/xlr_pci.c2
-rw-r--r--sys/mips/rt305x/obio.c4
-rw-r--r--sys/modules/Makefile5
-rw-r--r--sys/modules/nctgpio/Makefile8
-rw-r--r--sys/modules/pflog/Makefile5
-rw-r--r--sys/modules/pfsync/Makefile5
-rw-r--r--sys/modules/urtwn/Makefile (renamed from sys/modules/usb/urtwn/Makefile)5
-rw-r--r--sys/modules/urtwnfw/Makefile (renamed from sys/modules/usb/urtwnfw/Makefile)0
-rw-r--r--sys/modules/urtwnfw/Makefile.inc (renamed from sys/modules/usb/urtwnfw/Makefile.inc)2
-rw-r--r--sys/modules/urtwnfw/urtwnrtl8188eu/Makefile (renamed from sys/modules/usb/urtwnfw/urtwnrtl8188eu/Makefile)0
-rw-r--r--sys/modules/urtwnfw/urtwnrtl8192cT/Makefile (renamed from sys/modules/usb/urtwnfw/urtwnrtl8192cT/Makefile)0
-rw-r--r--sys/modules/urtwnfw/urtwnrtl8192cU/Makefile (renamed from sys/modules/usb/urtwnfw/urtwnrtl8192cU/Makefile)0
-rw-r--r--sys/modules/usb/Makefile2
-rw-r--r--sys/modules/wtap/Makefile5
-rw-r--r--sys/net/ethernet.h1
-rw-r--r--sys/net/if_debug.c2
-rw-r--r--sys/net/route.c11
-rw-r--r--sys/net/route.h23
-rw-r--r--sys/net/route_var.h2
-rw-r--r--sys/net/rtsock.c2
-rw-r--r--sys/net80211/ieee80211.h187
-rw-r--r--sys/net80211/ieee80211_amrr.c31
-rw-r--r--sys/net80211/ieee80211_dfs.c2
-rw-r--r--sys/net80211/ieee80211_freebsd.h8
-rw-r--r--sys/net80211/ieee80211_ht.c2
-rw-r--r--sys/net80211/ieee80211_hwmp.c6
-rw-r--r--sys/net80211/ieee80211_input.c5
-rw-r--r--sys/net80211/ieee80211_ioctl.h5
-rw-r--r--sys/net80211/ieee80211_node.c2
-rw-r--r--sys/net80211/ieee80211_power.c2
-rw-r--r--sys/net80211/ieee80211_proto.c7
-rw-r--r--sys/net80211/ieee80211_ratectl.c41
-rw-r--r--sys/net80211/ieee80211_ratectl.h11
-rw-r--r--sys/net80211/ieee80211_scan_sta.c4
-rw-r--r--sys/net80211/ieee80211_scan_sw.c10
-rw-r--r--sys/net80211/ieee80211_sta.c43
-rw-r--r--sys/net80211/ieee80211_wds.c3
-rw-r--r--sys/netinet/in_pcb.c22
-rw-r--r--sys/netinet/in_pcb.h10
-rw-r--r--sys/netinet/in_pcbgroup.c1
-rw-r--r--sys/netinet/ip_output.c29
-rw-r--r--sys/netinet/sctp_cc_functions.c12
-rw-r--r--sys/netinet/sctp_constants.h2
-rw-r--r--sys/netinet/sctp_indata.c20
-rw-r--r--sys/netinet/sctp_input.c10
-rw-r--r--sys/netinet/sctp_output.c68
-rw-r--r--sys/netinet/sctp_pcb.c4
-rw-r--r--sys/netinet/sctp_ss_functions.c2
-rw-r--r--sys/netinet/sctp_timer.c4
-rw-r--r--sys/netinet/sctp_usrreq.c26
-rw-r--r--sys/netinet/sctputil.c70
-rw-r--r--sys/netinet/sctputil.h5
-rw-r--r--sys/netinet/tcp_input.c29
-rw-r--r--sys/netinet/tcp_lro.c68
-rw-r--r--sys/netinet/tcp_lro.h8
-rw-r--r--sys/netinet/tcp_output.c12
-rw-r--r--sys/netinet/tcp_subr.c24
-rw-r--r--sys/netinet/tcp_syncache.c6
-rw-r--r--sys/netinet/tcp_timer.c2
-rw-r--r--sys/netinet/tcp_timewait.c2
-rw-r--r--sys/netinet/tcp_usrreq.c2
-rw-r--r--sys/netinet/tcp_var.h16
-rw-r--r--sys/netinet/udp_usrreq.c42
-rw-r--r--sys/netinet6/in6.c2
-rw-r--r--sys/netinet6/in6_ifattach.c26
-rw-r--r--sys/netinet6/in6_ifattach.h1
-rw-r--r--sys/netinet6/in6_pcb.c15
-rw-r--r--sys/netinet6/in6_pcbgroup.c1
-rw-r--r--sys/netinet6/in6_src.c42
-rw-r--r--sys/netinet6/ip6_input.c35
-rw-r--r--sys/netinet6/ip6_output.c19
-rw-r--r--sys/netinet6/nd6.c62
-rw-r--r--sys/netinet6/nd6.h5
-rw-r--r--sys/netinet6/nd6_nbr.c31
-rw-r--r--sys/netinet6/nd6_rtr.c60
-rw-r--r--sys/netinet6/udp6_usrreq.c4
-rw-r--r--sys/netipsec/ipsec_output.c2
-rw-r--r--sys/netpfil/pf/pf.c10
-rw-r--r--sys/nfs/bootp_subr.c94
-rw-r--r--sys/nfs/nfs_diskless.c1
-rw-r--r--sys/ofed/drivers/infiniband/core/iwcm.c5
-rw-r--r--sys/ofed/drivers/infiniband/ulp/ipoib/ipoib.h2
-rw-r--r--sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c5
-rw-r--r--sys/ofed/drivers/net/mlx4/en_port.c5
-rw-r--r--sys/ofed/drivers/net/mlx4/en_rx.c11
-rw-r--r--sys/ofed/drivers/net/mlx4/en_tx.c2
-rw-r--r--sys/pc98/pc98/canbus.c6
-rw-r--r--sys/powerpc/include/bus.h5
-rw-r--r--sys/powerpc/mpc85xx/fsl_sdhc.c2
-rw-r--r--sys/powerpc/mpc85xx/lbc.c8
-rw-r--r--sys/powerpc/mpc85xx/pci_mpc85xx.c3
-rw-r--r--sys/powerpc/ofw/ofw_pci.c8
-rw-r--r--sys/powerpc/powermac/cpcht.c2
-rw-r--r--sys/powerpc/powermac/grackle.c5
-rw-r--r--sys/powerpc/powermac/macgpio.c4
-rw-r--r--sys/powerpc/powermac/macio.c8
-rw-r--r--sys/powerpc/powermac/uninorth.c10
-rw-r--r--sys/powerpc/powermac/uninorthpci.c5
-rw-r--r--sys/powerpc/powermac/uninorthvar.h2
-rw-r--r--sys/powerpc/powerpc/nexus.c2
-rw-r--r--sys/powerpc/ps3/ps3bus.c4
-rw-r--r--sys/powerpc/pseries/rtas_pci.c5
-rw-r--r--sys/powerpc/pseries/vdevice.c2
-rw-r--r--sys/powerpc/psim/iobus.c2
-rw-r--r--sys/rpc/rpc_generic.c8
-rw-r--r--sys/rpc/svc.c2
-rw-r--r--sys/sparc64/central/central.c2
-rw-r--r--sys/sparc64/ebus/ebus.c4
-rw-r--r--sys/sparc64/fhc/fhc.c4
-rw-r--r--sys/sparc64/pci/apb.c10
-rw-r--r--sys/sparc64/sbus/dma_sbus.c4
-rw-r--r--sys/sparc64/sbus/sbus.c4
-rw-r--r--sys/sparc64/sparc64/nexus.c4
-rw-r--r--sys/sparc64/sparc64/upa.c4
-rw-r--r--sys/sys/_types.h2
-rw-r--r--sys/sys/aio.h2
-rw-r--r--sys/sys/bus.h1
-rw-r--r--sys/sys/fail.h246
-rw-r--r--sys/sys/file.h6
-rw-r--r--sys/sys/intr.h131
-rw-r--r--sys/sys/libkern.h10
-rw-r--r--sys/sys/mbuf.h54
-rw-r--r--sys/sys/osd.h8
-rw-r--r--sys/sys/param.h2
-rw-r--r--sys/sys/proc.h3
-rw-r--r--sys/sys/racct.h5
-rw-r--r--sys/sys/sleepqueue.h6
-rw-r--r--sys/sys/smp.h68
-rw-r--r--sys/sys/socket.h1
-rw-r--r--sys/sys/syscall.h2
-rw-r--r--sys/sys/syscall.mk2
-rw-r--r--sys/sys/sysctl.h26
-rw-r--r--sys/sys/sysproto.h2
-rw-r--r--sys/sys/systm.h17
-rw-r--r--sys/ufs/ffs/ffs_alloc.c6
-rw-r--r--sys/ufs/ffs/ffs_softdep.c2
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c13
-rw-r--r--sys/ufs/ufs/ufs_extattr.c2
-rw-r--r--sys/ufs/ufs/ufsmount.h9
-rw-r--r--sys/x86/include/apicreg.h5
-rw-r--r--sys/x86/include/specialreg.h4
-rw-r--r--sys/x86/include/x86_var.h7
-rw-r--r--sys/x86/x86/autoconf.c (renamed from sys/i386/i386/autoconf.c)11
-rw-r--r--sys/x86/x86/intr_machdep.c15
-rw-r--r--sys/x86/x86/io_apic.c8
-rw-r--r--sys/x86/x86/local_apic.c275
-rw-r--r--sys/x86/x86/mp_x86.c767
-rw-r--r--sys/x86/x86/nexus.c6
-rw-r--r--targets/Makefile.xtras21
-rw-r--r--targets/pseudo/hosttools/Makefile.depend36
-rw-r--r--targets/pseudo/hosttools/Makefile.depend.host31
-rw-r--r--targets/pseudo/userland/misc/Makefile.depend1
-rw-r--r--tests/sys/aio/aio_test.c74
-rw-r--r--tests/sys/geom/class/geom_subr.sh10
-rw-r--r--tools/build/mk/OptionalObsoleteFiles.inc1
-rw-r--r--tools/build/options/WITHOUT_FAST_DEPEND5
-rw-r--r--tools/build/options/WITH_CCACHE_BUILD3
-rw-r--r--tools/build/options/WITH_FAST_DEPEND7
-rwxr-xr-xtools/tinder.sh2
-rwxr-xr-xtools/tools/nanobsd/defaults.sh30
-rwxr-xr-xtools/tools/nanobsd/nanobsd.sh2
-rw-r--r--tools/tools/net80211/wlanstats/main.c4
-rw-r--r--tools/tools/net80211/wlanstats/wlanstats.c2
-rw-r--r--tools/tools/vt/setfont/Makefile6
-rw-r--r--tools/tools/vt/setfont/setfont.c89
-rw-r--r--usr.bin/bmake/Makefile4
-rw-r--r--usr.bin/fetch/fetch.133
-rw-r--r--usr.bin/finger/sprint.c2
-rw-r--r--usr.bin/ktrace/ktrace.15
-rw-r--r--usr.bin/localedef/ctype.c4
-rw-r--r--usr.bin/netstat/inet.c28
-rw-r--r--usr.bin/netstat/main.c25
-rw-r--r--usr.bin/netstat/netstat.h6
-rw-r--r--usr.bin/netstat/nlist_symbols1
-rw-r--r--usr.bin/netstat/route.c1
-rw-r--r--usr.bin/showmount/showmount.89
-rw-r--r--usr.bin/showmount/showmount.c34
-rw-r--r--usr.bin/truss/syscalls.c4
-rw-r--r--usr.bin/vtfontcvt/vtfontcvt.c5
-rw-r--r--usr.bin/whois/whois.c10
-rw-r--r--usr.bin/xo/Makefile5
-rw-r--r--usr.sbin/Makefile2
-rw-r--r--usr.sbin/autofs/log.c15
-rw-r--r--usr.sbin/bhyve/pci_emul.c1
-rw-r--r--usr.sbin/bluetooth/bthidd/kbd.c30
-rwxr-xr-xusr.sbin/bsdinstall/scripts/zfsboot10
-rw-r--r--usr.sbin/ctld/log.c15
-rw-r--r--usr.sbin/devinfo/devinfo.c4
-rw-r--r--usr.sbin/iscsid/iscsid.c6
-rw-r--r--usr.sbin/iscsid/log.c15
-rw-r--r--usr.sbin/kbdcontrol/kbdcontrol.19
-rw-r--r--usr.sbin/kbdcontrol/kbdcontrol.c87
-rw-r--r--usr.sbin/mtest/mtest.c2
-rw-r--r--usr.sbin/ndiscvt/ndisgen.sh5
-rw-r--r--usr.sbin/pciconf/cap.c72
-rw-r--r--usr.sbin/pw/cpdir.c1
-rw-r--r--usr.sbin/pw/pw.820
-rw-r--r--usr.sbin/pw/pw_user.c2
-rw-r--r--usr.sbin/pw/pw_utils.c3
-rw-r--r--usr.sbin/pw/pw_vpw.c1
-rw-r--r--usr.sbin/sesutil/eltsub.c4
-rw-r--r--usr.sbin/sesutil/sesutil.c1
-rw-r--r--usr.sbin/uathload/Makefile22
-rw-r--r--usr.sbin/uathload/uathload.c28
912 files changed, 38260 insertions, 8557 deletions
diff --git a/Makefile b/Makefile
index a0ac974..cde0f2c 100644
--- a/Makefile
+++ b/Makefile
@@ -124,7 +124,7 @@ TGTS= all all-man buildenv buildenvvars buildkernel buildworld \
installworld kernel-toolchain libraries lint maninstall \
obj objlink rerelease showconfig tags toolchain update \
_worldtmp _legacy _bootstrap-tools _cleanobj _obj \
- _build-tools _cross-tools _includes _libraries _depend \
+ _build-tools _cross-tools _includes _libraries \
build32 distribute32 install32 build32 distribute32 install32 \
builddtb xdev xdev-build xdev-install \
xdev-links native-xtools stageworld stagekernel stage-packages \
diff --git a/Makefile.inc1 b/Makefile.inc1
index 890ee64..1eda64b 100644
--- a/Makefile.inc1
+++ b/Makefile.inc1
@@ -7,10 +7,9 @@
# -DDB_FROM_SRC use the user/group databases in src/etc instead of
# the system database when installing.
# -DNO_SHARE do not go into share subdir
-# -DKERNFAST define NO_KERNEL{CONFIG,CLEAN,DEPEND,OBJ}
+# -DKERNFAST define NO_KERNEL{CONFIG,CLEAN,OBJ}
# -DNO_KERNELCONFIG do not run config in ${MAKE} buildkernel
# -DNO_KERNELCLEAN do not run ${MAKE} clean in ${MAKE} buildkernel
-# -DNO_KERNELDEPEND do not run ${MAKE} depend in ${MAKE} buildkernel
# -DNO_KERNELOBJ do not run ${MAKE} obj in ${MAKE} buildkernel
# -DNO_PORTSUPDATE do not update ports in ${MAKE} update
# -DNO_ROOT install without using root privilege
@@ -145,16 +144,6 @@ CLEANDIR= clean cleandepend
CLEANDIR= cleandir
.endif
-# FAST_DEPEND can skip depend tree-walks.
-.if ${MK_FAST_DEPEND} == "yes"
-NO_DEPEND= t
-NO_KERNELDEPEND=t
-.endif
-# Ensure shell checks later have a value.
-.if defined(NO_DEPEND)
-NO_DEPEND= t
-.endif
-
LOCAL_TOOL_DIRS?=
PACKAGEDIR?= ${DESTDIR}/${DISTDIR}
@@ -380,7 +369,6 @@ KTMAKE= TOOLS_PREFIX=${WORLDTMP} MAKEOBJDIRPREFIX=${WORLDTMP} \
# world stage
WMAKEENV= ${CROSSENV} \
- _LDSCRIPTROOT= \
INSTALL="sh ${.CURDIR}/tools/install.sh" \
PATH=${TMPPATH}
@@ -427,22 +415,22 @@ X${BINUTIL}?= ${${BINUTIL}}
.endif
.endfor
CROSSENV+= CC="${XCC} ${XCFLAGS}" CXX="${XCXX} ${XCFLAGS} ${XCXXFLAGS}" \
- DEPFLAGS="${DEPFLAGS}" \
CPP="${XCPP} ${XCFLAGS}" \
AS="${XAS}" AR="${XAR}" LD="${XLD}" NM=${XNM} \
OBJDUMP=${XOBJDUMP} OBJCOPY="${XOBJCOPY}" \
RANLIB=${XRANLIB} STRINGS=${XSTRINGS} \
SIZE="${XSIZE}"
-.if ${XCC:N${CCACHE_BIN}:M/*}
-.if defined(CROSS_BINUTILS_PREFIX)
+.if defined(CROSS_BINUTILS_PREFIX) && exists(${CROSS_BINUTILS_PREFIX})
# In the case of xdev-build tools, CROSS_BINUTILS_PREFIX won't be a
-# directory, but the compiler will look in the right place for it's
+# directory, but the compiler will look in the right place for its
# tools so we don't need to tell it where to look.
-.if exists(${CROSS_BINUTILS_PREFIX})
BFLAGS+= -B${CROSS_BINUTILS_PREFIX}
.endif
-.else
+
+# External compiler needs sysroot and target flags.
+.if ${XCC:N${CCACHE_BIN}:M/*} || ${MK_CROSS_COMPILER} == "no"
+.if !defined(CROSS_BINUTILS_PREFIX) || !exists(${CROSS_BINUTILS_PREFIX})
BFLAGS+= -B${WORLDTMP}/usr/bin
.endif
.if ${TARGET} == "arm"
@@ -453,26 +441,23 @@ TARGET_ABI= gnueabi
.endif
.endif
.if defined(X_COMPILER_TYPE) && ${X_COMPILER_TYPE} == gcc
+# GCC requires -isystem and -L when using a cross-compiler.
XCFLAGS+= -isystem ${WORLDTMP}/usr/include -L${WORLDTMP}/usr/lib
-XCXXFLAGS+= -I${WORLDTMP}/usr/include/c++/v1 -std=gnu++11 -L${WORLDTMP}/../lib/libc++
-# XXX: DEPFLAGS is a workaround for not properly passing CXXFLAGS to sub-makes
-# due to CXX="${XCXX} ${XCXXFLAGS}". bsd.dep.mk does use CXXFLAGS when
-# building C++ files so this can come out if passing CXXFLAGS down is fixed.
-DEPFLAGS+= -I${WORLDTMP}/usr/include/c++/v1
+# Force using libc++ for external GCC.
+XCXXFLAGS+= -isystem ${WORLDTMP}/usr/include/c++/v1 -std=c++11 \
+ -nostdinc++ -L${WORLDTMP}/../lib/libc++
.else
TARGET_ABI?= unknown
TARGET_TRIPLE?= ${TARGET_ARCH:C/amd64/x86_64/}-${TARGET_ABI}-freebsd11.0
XCFLAGS+= -target ${TARGET_TRIPLE}
.endif
-XCFLAGS+= --sysroot=${WORLDTMP} ${BFLAGS}
-XCXXFLAGS+= --sysroot=${WORLDTMP} ${BFLAGS}
+XCFLAGS+= --sysroot=${WORLDTMP}
.else
-.if defined(CROSS_BINUTILS_PREFIX) && exists(${CROSS_BINUTILS_PREFIX})
-BFLAGS+= -B${CROSS_BINUTILS_PREFIX}
+.endif # ${XCC:M/*} || ${MK_CROSS_COMPILER} == "no"
+
+.if !empty(BFLAGS)
XCFLAGS+= ${BFLAGS}
-XCXXFLAGS+= ${BFLAGS}
.endif
-.endif # ${XCC:M/*}
.if ${MK_LIB32} != "no" && (${TARGET_ARCH} == "amd64" || \
${TARGET_ARCH} == "powerpc64")
@@ -645,9 +630,9 @@ _includes:
# Special handling for SUBDIR_OVERRIDE in buildworld as they most likely need
# headers from default SUBDIR. Do SUBDIR_OVERRIDE includes last.
${_+_}cd ${.CURDIR}; ${WMAKE} SUBDIR_OVERRIDE= SHARED=symlinks \
- includes
+ MK_INCLUDES=yes includes
.if !empty(SUBDIR_OVERRIDE) && make(buildworld)
- ${_+_}cd ${.CURDIR}; ${WMAKE} SHARED=symlinks includes
+ ${_+_}cd ${.CURDIR}; ${WMAKE} MK_INCLUDES=yes SHARED=symlinks includes
.endif
_libraries:
@echo
@@ -657,16 +642,10 @@ _libraries:
${_+_}cd ${.CURDIR}; \
${WMAKE} -DNO_FSCHG MK_HTML=no -DNO_LINT MK_MAN=no \
MK_PROFILE=no MK_TESTS=no MK_TESTS_SUPPORT=${MK_TESTS} libraries
-_depend:
- @echo
- @echo "--------------------------------------------------------------"
- @echo ">>> stage 4.3: make dependencies"
- @echo "--------------------------------------------------------------"
- ${_+_}cd ${.CURDIR}; ${WMAKE} depend
everything:
@echo
@echo "--------------------------------------------------------------"
- @echo ">>> stage 4.4: building everything"
+ @echo ">>> stage 4.3: building everything"
@echo "--------------------------------------------------------------"
${_+_}cd ${.CURDIR}; _PARALLEL_SUBDIR_OK=1 ${WMAKE} all
@@ -677,9 +656,6 @@ WMAKE_TGTS+= _bootstrap-tools
.endif
WMAKE_TGTS+= _cleanobj _obj _build-tools _cross-tools
WMAKE_TGTS+= _includes _libraries
-.if !defined(NO_DEPEND)
-WMAKE_TGTS+= _depend
-.endif
WMAKE_TGTS+= everything
.if defined(LIBCOMPAT) && empty(SUBDIR_OVERRIDE)
WMAKE_TGTS+= build${libcompat}
@@ -722,7 +698,7 @@ buildenv: .PHONY
@cd ${BUILDENV_DIR} && env ${WMAKEENV} BUILDENV=1 ${BUILDENV_SHELL} \
|| true
-TOOLCHAIN_TGTS= ${WMAKE_TGTS:N_depend:Neverything:Nbuild${libcompat}}
+TOOLCHAIN_TGTS= ${WMAKE_TGTS:Neverything:Nbuild${libcompat}}
toolchain: ${TOOLCHAIN_TGTS}
kernel-toolchain: ${TOOLCHAIN_TGTS:N_includes:N_libraries}
@@ -1034,7 +1010,6 @@ distrib-dirs distribution: .MAKE .PHONY
.if defined(KERNFAST)
NO_KERNELCLEAN= t
NO_KERNELCONFIG= t
-NO_KERNELDEPEND= t
NO_KERNELOBJ= t
# Shortcut for KERNCONF=Blah -DKERNFAST is now KERNFAST=Blah
.if !defined(KERNCONF) && ${KERNFAST} != "1"
@@ -1116,16 +1091,9 @@ buildkernel: .MAKE .PHONY
@echo ">>> stage 2.3: build tools"
@echo "--------------------------------------------------------------"
${_+_}cd ${.CURDIR}; ${KTMAKE} kernel-tools
-.if !defined(NO_KERNELDEPEND)
@echo
@echo "--------------------------------------------------------------"
- @echo ">>> stage 3.1: making dependencies"
- @echo "--------------------------------------------------------------"
- ${_+_}cd ${KRNLOBJDIR}/${_kernel}; ${KMAKE} depend -DNO_MODULES_OBJ
-.endif
- @echo
- @echo "--------------------------------------------------------------"
- @echo ">>> stage 3.2: building everything"
+ @echo ">>> stage 3.1: building everything"
@echo "--------------------------------------------------------------"
${_+_}cd ${KRNLOBJDIR}/${_kernel}; ${KMAKE} all -DNO_MODULES_OBJ
@echo "--------------------------------------------------------------"
@@ -1459,11 +1427,10 @@ legacy:
false
.endif
.for _tool in tools/build ${_elftoolchain_libs}
- ${_+_}@${ECHODIR} "===> ${_tool} (obj,includes,depend,all,install)"; \
+ ${_+_}@${ECHODIR} "===> ${_tool} (obj,includes,all,install)"; \
cd ${.CURDIR}/${_tool}; \
${MAKE} DIRPRFX=${_tool}/ obj; \
${MAKE} DIRPRFX=${_tool}/ DESTDIR=${MAKEOBJDIRPREFIX}/legacy includes; \
- if [ -z "${NO_DEPEND}" ]; then ${MAKE} DIRPRFX=${_tool}/ depend; fi; \
${MAKE} DIRPRFX=${_tool}/ all; \
${MAKE} DIRPRFX=${_tool}/ DESTDIR=${MAKEOBJDIRPREFIX}/legacy install
.endfor
@@ -1533,6 +1500,11 @@ _crunch= usr.sbin/crunch
_awk= usr.bin/awk
.endif
+# r296926 -P keymap search path
+.if ${BOOTSTRAPPING} < 1100103
+_kbdcontrol= usr.sbin/kbdcontrol
+.endif
+
_yacc= lib/liby \
usr.bin/yacc
@@ -1597,6 +1569,7 @@ bootstrap-tools: .PHONY
${_awk} \
${_cat} \
${_dd} \
+ ${_kbdcontrol} \
usr.bin/lorder \
${_libopenbsd} \
${_makewhatis} \
@@ -1613,10 +1586,9 @@ bootstrap-tools: .PHONY
${_vtfontcvt} \
usr.bin/localedef
${_bt}-${_tool}: .PHONY .MAKE
- ${_+_}@${ECHODIR} "===> ${_tool} (obj,depend,all,install)"; \
+ ${_+_}@${ECHODIR} "===> ${_tool} (obj,all,install)"; \
cd ${.CURDIR}/${_tool}; \
${MAKE} DIRPRFX=${_tool}/ obj; \
- if [ -z "${NO_DEPEND}" ]; then ${MAKE} DIRPRFX=${_tool}/ depend; fi; \
${MAKE} DIRPRFX=${_tool}/ all; \
${MAKE} DIRPRFX=${_tool}/ DESTDIR=${MAKEOBJDIRPREFIX}/legacy install
@@ -1662,10 +1634,9 @@ build-tools: build-tools_${_tool}
.for _tool in \
${_gcc_tools}
build-tools_${_tool}: .PHONY
- ${_+_}@${ECHODIR} "===> ${_tool} (obj,depend,all)"; \
+ ${_+_}@${ECHODIR} "===> ${_tool} (obj,all)"; \
cd ${.CURDIR}/${_tool}; \
${MAKE} DIRPRFX=${_tool}/ obj; \
- if [ -z "${NO_DEPEND}" ]; then ${MAKE} DIRPRFX=${_tool}/ depend; fi; \
${MAKE} DIRPRFX=${_tool}/ all
build-tools: build-tools_${_tool}
.endfor
@@ -1746,10 +1717,9 @@ cross-tools: .MAKE .PHONY
${_btxld} \
${_crunchide} \
${_usb_tools}
- ${_+_}@${ECHODIR} "===> ${_tool} (obj,depend,all,install)"; \
+ ${_+_}@${ECHODIR} "===> ${_tool} (obj,all,install)"; \
cd ${.CURDIR}/${_tool}; \
${MAKE} DIRPRFX=${_tool}/ obj; \
- if [ -z "${NO_DEPEND}" ]; then ${MAKE} DIRPRFX=${_tool}/ depend; fi; \
${MAKE} DIRPRFX=${_tool}/ all; \
${MAKE} DIRPRFX=${_tool}/ DESTDIR=${MAKEOBJDIRPREFIX} install
.endfor
@@ -1778,10 +1748,9 @@ NXBMAKE= ${NXBENV} ${MAKE} \
native-xtools: .PHONY
.if ${MK_GCC_BOOTSTRAP} != "no"
mkdir -p ${OBJTREE}/gperf_for_gcc/usr/bin
- ${_+_}@${ECHODIR} "===> ${_gperf} (obj,depend,all,install)"; \
+ ${_+_}@${ECHODIR} "===> ${_gperf} (obj,all,install)"; \
cd ${.CURDIR}/${_gperf}; \
${NXBMAKE} DIRPRFX=${_gperf}/ obj; \
- if [ -z "${NO_DEPEND}" ]; then ${NXBMAKE} DIRPRFX=${_gperf}/ depend; fi; \
${NXBMAKE} DIRPRFX=${_gperf}/ all; \
${NXBMAKE} DIRPRFX=${_gperf}/ DESTDIR=${OBJTREE}/gperf_for_gcc install
.endif
@@ -1853,10 +1822,9 @@ native-xtools: .PHONY
usr.bin/xz \
usr.bin/yacc \
usr.sbin/chown
- ${_+_}@${ECHODIR} "===> ${_tool} (obj,depend,all,install)"; \
+ ${_+_}@${ECHODIR} "===> ${_tool} (obj,all,install)"; \
cd ${.CURDIR}/${_tool}; \
${NXBMAKE} DIRPRFX=${_tool}/ obj; \
- if [ -z "${NO_DEPEND}" ]; then ${NXBMAKE} DIRPRFX=${_tool}/ depend; fi; \
${NXBMAKE} DIRPRFX=${_tool}/ all; \
${NXBMAKE} DIRPRFX=${_tool}/ DESTDIR=${NXBDESTDIR} install
.endfor
@@ -2092,10 +2060,9 @@ gnu/lib/libdialog__L: lib/msun__L lib/ncurses/ncursesw__L
.for _lib in ${_prereq_libs}
${_lib}__PL: .PHONY .MAKE
.if exists(${.CURDIR}/${_lib})
- ${_+_}@${ECHODIR} "===> ${_lib} (obj,depend,all,install)"; \
+ ${_+_}@${ECHODIR} "===> ${_lib} (obj,all,install)"; \
cd ${.CURDIR}/${_lib}; \
${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ obj; \
- if [ -z "${NO_DEPEND}" ]; then ${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ depend; fi; \
${MAKE} MK_TESTS=no MK_PROFILE=no -DNO_PIC \
DIRPRFX=${_lib}/ all; \
${MAKE} MK_TESTS=no MK_PROFILE=no -DNO_PIC \
@@ -2106,10 +2073,9 @@ ${_lib}__PL: .PHONY .MAKE
.for _lib in ${_startup_libs} ${_prebuild_libs:Nlib/libpam} ${_generic_libs}
${_lib}__L: .PHONY .MAKE
.if exists(${.CURDIR}/${_lib})
- ${_+_}@${ECHODIR} "===> ${_lib} (obj,depend,all,install)"; \
+ ${_+_}@${ECHODIR} "===> ${_lib} (obj,all,install)"; \
cd ${.CURDIR}/${_lib}; \
${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ obj; \
- if [ -z "${NO_DEPEND}" ]; then ${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ depend; fi; \
${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ all; \
${MAKE} MK_TESTS=no DIRPRFX=${_lib}/ install
.endif
@@ -2119,10 +2085,9 @@ ${_lib}__L: .PHONY .MAKE
# static PAM library, and dynamic PAM library before dynamic PAM
# modules.
lib/libpam__L: .PHONY .MAKE
- ${_+_}@${ECHODIR} "===> lib/libpam (obj,depend,all,install)"; \
+ ${_+_}@${ECHODIR} "===> lib/libpam (obj,all,install)"; \
cd ${.CURDIR}/lib/libpam; \
${MAKE} MK_TESTS=no DIRPRFX=lib/libpam/ obj; \
- if [ -z "${NO_DEPEND}" ]; then ${MAKE} MK_TESTS=no DIRPRFX=lib/libpam/ depend; fi; \
${MAKE} MK_TESTS=no DIRPRFX=lib/libpam/ \
-D_NO_LIBPAM_SO_YET all; \
${MAKE} MK_TESTS=no DIRPRFX=lib/libpam/ \
@@ -2417,10 +2382,9 @@ _xb-bootstrap-tools: .PHONY
.for _tool in \
${_clang_tblgen} \
${_gperf}
- ${_+_}@${ECHODIR} "===> ${_tool} (obj,depend,all,install)"; \
+ ${_+_}@${ECHODIR} "===> ${_tool} (obj,all,install)"; \
cd ${.CURDIR}/${_tool}; \
${CDMAKE} DIRPRFX=${_tool}/ obj; \
- if [ -z "${NO_DEPEND}" ]; then ${CDMAKE} DIRPRFX=${_tool}/ depend; fi; \
${CDMAKE} DIRPRFX=${_tool}/ all; \
${CDMAKE} DIRPRFX=${_tool}/ DESTDIR=${CDTMP} install
.endfor
@@ -2437,10 +2401,9 @@ _xb-cross-tools: .PHONY
${_clang_libs} \
${_clang} \
${_cc}
- ${_+_}@${ECHODIR} "===> xdev ${_tool} (obj,depend,all)"; \
+ ${_+_}@${ECHODIR} "===> xdev ${_tool} (obj,all)"; \
cd ${.CURDIR}/${_tool}; \
${CDMAKE} DIRPRFX=${_tool}/ obj; \
- if [ -z "${NO_DEPEND}" ]; then ${CDMAKE} DIRPRFX=${_tool}/ depend; fi; \
${CDMAKE} DIRPRFX=${_tool}/ all
.endfor
diff --git a/Makefile.libcompat b/Makefile.libcompat
index 8a336b9..3ab962f 100644
--- a/Makefile.libcompat
+++ b/Makefile.libcompat
@@ -52,7 +52,8 @@ LIBSOFTWMAKEFLAGS= -DCOMPAT_SOFTFP
# Generic code for each type.
# Set defaults based on type.
libcompat= ${LIBCOMPAT:tl}
-_LIBCOMPAT_MAKEVARS= _OBJTREE TMP CPUFLAGS CFLAGS WMAKEENV WMAKEFLAGS WMAKE
+_LIBCOMPAT_MAKEVARS= _OBJTREE TMP CPUFLAGS CFLAGS CXXFLAGS WMAKEENV \
+ WMAKEFLAGS WMAKE
.for _var in ${_LIBCOMPAT_MAKEVARS}
.if !empty(LIB${LIBCOMPAT}${_var})
LIBCOMPAT${_var}?= ${LIB${LIBCOMPAT}${_var}}
@@ -64,22 +65,32 @@ LIBCOMPAT_OBJTREE?= ${OBJTREE}${.CURDIR}/world${libcompat}
LIBCOMPATTMP?= ${OBJTREE}${.CURDIR}/lib${libcompat}
LIBCOMPATCFLAGS+= ${LIBCOMPATCPUFLAGS} \
- -isystem ${LIBCOMPATTMP}/usr/include/ \
-L${LIBCOMPATTMP}/usr/lib${libcompat} \
- -B${LIBCOMPATTMP}/usr/lib${libcompat}
+ --sysroot=${LIBCOMPATTMP} \
+ ${BFLAGS}
+
+# -B is needed to find /usr/lib32/crti.o for GCC and /usr/libsoft/crti.o for
+# Clang/GCC.
+LIBCOMPATCFLAGS+= -B${LIBCOMPATTMP}/usr/lib${libcompat}
+# GCC requires -isystem when using a cross-compiler.
+LIBCOMPATCFLAGS+= -isystem ${LIBCOMPATTMP}/usr/include
+
+.if defined(X_COMPILER_TYPE) && ${X_COMPILER_TYPE} == gcc
+# Force using libc++ for external GCC.
+LIBCOMPATCXXFLAGS+= -isystem ${LIBCOMPATTMP}/usr/include/c++/v1 -std=c++11 \
+ -nostdinc++ -L${LIBCOMPAT_OBJTREE}${.CURDIR}/lib/libc++
+.endif
# Yes, the flags are redundant.
LIBCOMPATWMAKEENV+= MAKEOBJDIRPREFIX=${LIBCOMPAT_OBJTREE} \
- _LDSCRIPTROOT=${LIBCOMPATTMP} \
INSTALL="sh ${.CURDIR}/tools/install.sh" \
PATH=${TMPPATH} \
LIBDIR=/usr/lib${libcompat} \
SHLIBDIR=/usr/lib${libcompat} \
DTRACE="${LIB$COMPATDTRACE:U${DTRACE}}"
LIBCOMPATWMAKEFLAGS+= CC="${XCC} ${LIBCOMPATCFLAGS}" \
- CXX="${XCXX} ${LIBCOMPATCFLAGS}" \
+ CXX="${XCXX} ${LIBCOMPATCFLAGS} ${LIBCOMPATCXXFLAGS}" \
DESTDIR=${LIBCOMPATTMP} \
- -DLIBRARIES_ONLY \
-DNO_CPU_CFLAGS \
MK_CTF=no \
-DNO_LINT \
@@ -87,17 +98,19 @@ LIBCOMPATWMAKEFLAGS+= CC="${XCC} ${LIBCOMPATCFLAGS}" \
LIBCOMPATWMAKE+= ${LIBCOMPATWMAKEENV} ${MAKE} ${LIBCOMPATWMAKEFLAGS} \
MK_MAN=no MK_HTML=no
LIBCOMPATIMAKE+= ${LIBCOMPATWMAKE:NINSTALL=*:NDESTDIR=*:N_LDSCRIPTROOT=*} \
- MK_TOOLCHAIN=no ${IMAKE_INSTALL}
-
-.if ${XCC:N${CCACHE_BIN}:M/*}
-LIBCOMPATCFLAGS+= --sysroot=${WORLDTMP}
-.endif
+ MK_TOOLCHAIN=no ${IMAKE_INSTALL} \
+ -DLIBRARIES_ONLY
_LC_LIBDIRS.yes= lib gnu/lib
_LC_LIBDIRS.${MK_CDDL:tl}+= cddl/lib
_LC_LIBDIRS.${MK_CRYPT:tl}+= secure/lib
_LC_LIBDIRS.${MK_KERBEROS:tl}+= kerberos5/lib
+_LC_INCDIRS= \
+ include \
+ lib/ncurses/ncursesw \
+ ${_LC_LIBDIRS.yes}
+
# Shared logic
build${libcompat}: .PHONY
@echo
@@ -120,13 +133,10 @@ build${libcompat}: .PHONY
mkdir -p ${WORLDTMP}
ln -sf ${.CURDIR}/sys ${WORLDTMP}
.for _t in obj includes
- ${_+_}cd ${.CURDIR}/include; ${LIBCOMPATWMAKE} DIRPRFX=include/ ${_t}
-.for _dir in ${_LC_LIBDIRS.yes}
- ${_+_}cd ${.CURDIR}/${_dir}; ${LIBCOMPATWMAKE} DIRPRFX=${_dir}/ ${_t}
-.endfor
+.for _dir in ${_LC_INCDIRS}
+ ${_+_}cd ${.CURDIR}/${_dir}; ${LIBCOMPATWMAKE} MK_INCLUDES=yes \
+ DIRPRFX=${_dir}/ ${_t}
.endfor
-.for _dir in usr.bin/lex/lib
- ${_+_}cd ${.CURDIR}/${_dir}; ${LIBCOMPATWMAKE} DIRPRFX=${_dir}/ obj
.endfor
.for _dir in lib/ncurses/ncurses lib/ncurses/ncursesw lib/libmagic
${_+_}cd ${.CURDIR}/${_dir}; \
@@ -139,7 +149,7 @@ build${libcompat}: .PHONY
${_+_}cd ${.CURDIR}; \
${LIBCOMPATWMAKE} -f Makefile.inc1 -DNO_FSCHG libraries
.if ${libcompat} == "32"
-.for _t in obj depend all
+.for _t in obj all
${_+_}cd ${.CURDIR}/libexec/rtld-elf; PROG=ld-elf32.so.1 ${LIBCOMPATWMAKE} \
-DNO_FSCHG DIRPRFX=libexec/rtld-elf/ ${_t}
${_+_}cd ${.CURDIR}/usr.bin/ldd; PROG=ldd32 ${LIBCOMPATWMAKE} \
diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc
index 13c9156..5f29f4b 100644
--- a/ObsoleteFiles.inc
+++ b/ObsoleteFiles.inc
@@ -38,6 +38,9 @@
# xargs -n1 | sort | uniq -d;
# done
+# 20160317: rman_res_t size bump to uintmax_t
+OLD_LIBS+=usr/lib/libdevinfo.so.5
+OLD_LIBS+=usr/lib32/libdevinfo.so.5
# 20160305: new clang import which bumps version from 3.7.1 to 3.8.0.
OLD_FILES+=usr/bin/macho-dump
OLD_FILES+=usr/lib/clang/3.7.1/include/sanitizer/allocator_interface.h
diff --git a/UPDATING b/UPDATING
index d3e4545..2e4c37b 100644
--- a/UPDATING
+++ b/UPDATING
@@ -31,6 +31,15 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 11.x IS SLOW:
disable the most expensive debugging functionality run
"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
+20160330:
+ The FAST_DEPEND build option has been removed and its functionality is
+ now the one true way. The old mkdep(1) style of 'make depend' has
+ been removed. See 20160311 for further details.
+
+20160317:
+ Resource range types have grown from unsigned long to uintmax_t. All
+ drivers, and anything using libdevinfo, need to be recompiled.
+
20160311:
WITH_FAST_DEPEND is now enabled by default for in-tree and out-of-tree
builds. It no longer runs mkdep(1) during 'make depend', and the
diff --git a/bin/csh/Makefile b/bin/csh/Makefile
index 0c364c1..aa3b83b 100644
--- a/bin/csh/Makefile
+++ b/bin/csh/Makefile
@@ -141,7 +141,7 @@ tc.const.h: tc.const.c sh.char.h config.h config_f.h sh.types.h sh.err.h
@echo '/* Do not edit this file, make creates it. */' > ${.TARGET}
@echo '#ifndef _h_tc_const' >> ${.TARGET}
@echo '#define _h_tc_const' >> ${.TARGET}
- ${CC} -E ${CFLAGS:C/-DHAVE_ICONV//} ${.ALLSRC} -D_h_tc_const | \
+ ${CC:N${CCACHE_BIN}} -E ${CFLAGS:C/-DHAVE_ICONV//} ${.ALLSRC} -D_h_tc_const | \
grep 'Char STR' | \
sed -e 's/Char \([a-zA-Z0-9_]*\)\(.*\)/extern Char \1[];/' | \
sort >> ${.TARGET}
diff --git a/bin/freebsd-version/freebsd-version.1 b/bin/freebsd-version/freebsd-version.1
index 7e471bf..a4247ff 100644
--- a/bin/freebsd-version/freebsd-version.1
+++ b/bin/freebsd-version/freebsd-version.1
@@ -110,8 +110,7 @@ env ROOT=/mnt /mnt/bin/freebsd-version -ku
.Ed
.Sh SEE ALSO
.Xr uname 1 ,
-.Xr loader.conf 5 ,
-.Xr freebsd-version 8
+.Xr loader.conf 5
.Sh HISTORY
The
.Nm
diff --git a/bin/sh/tests/builtins/Makefile b/bin/sh/tests/builtins/Makefile
index 11cea5f..b323daf 100644
--- a/bin/sh/tests/builtins/Makefile
+++ b/bin/sh/tests/builtins/Makefile
@@ -152,6 +152,7 @@ FILES+= trap13.0
FILES+= trap14.0
FILES+= trap15.0
FILES+= trap16.0
+FILES+= trap17.0
FILES+= trap2.0
FILES+= trap3.0
FILES+= trap4.0
diff --git a/bin/sh/tests/builtins/trap17.0 b/bin/sh/tests/builtins/trap17.0
new file mode 100644
index 0000000..89be893
--- /dev/null
+++ b/bin/sh/tests/builtins/trap17.0
@@ -0,0 +1,10 @@
+# $FreeBSD$
+# This use-after-free bug probably needs non-default settings to show up.
+
+v1=nothing v2=nothing
+trap 'trap "echo bad" USR1
+v1=trap_received
+v2=trap_invoked
+:' USR1
+kill -USR1 "$$"
+[ "$v1.$v2" = trap_received.trap_invoked ]
diff --git a/bin/sh/trap.c b/bin/sh/trap.c
index f562e27..8bfebc1 100644
--- a/bin/sh/trap.c
+++ b/bin/sh/trap.c
@@ -412,6 +412,7 @@ onsig(int signo)
void
dotrap(void)
{
+ struct stackmark smark;
int i;
int savestatus, prev_evalskip, prev_skipcount;
@@ -445,7 +446,9 @@ dotrap(void)
last_trapsig = i;
savestatus = exitstatus;
- evalstring(trap[i], 0);
+ setstackmark(&smark);
+ evalstring(stsavestr(trap[i]), 0);
+ popstackmark(&smark);
/*
* If such a command was not
diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
index 504db96..4ed7c2b 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_dataset.c
@@ -1633,8 +1633,9 @@ zfs_prop_set_list(zfs_handle_t *zhp, nvlist_t *props)
* its canmount property to 'on' or 'noauto'. We only use
* the changelist logic to unmount when setting canmount=off.
*/
- if (!(prop == ZFS_PROP_CANMOUNT &&
- fnvpair_value_uint64(elem) != ZFS_CANMOUNT_OFF)) {
+ if (prop != ZFS_PROP_CANMOUNT ||
+ (fnvpair_value_uint64(elem) == ZFS_CANMOUNT_OFF &&
+ zfs_is_mounted(zhp, NULL))) {
cls[cl_idx] = changelist_gather(zhp, prop, 0, 0);
if (cls[cl_idx] == NULL)
goto error;
diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c
index 723cd42..eb9a9dd 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_sendrecv.c
@@ -3479,7 +3479,8 @@ zfs_receive_one(libzfs_handle_t *hdl, int infd, const char *tosnap,
}
if (clp) {
- err |= changelist_postfix(clp);
+ if (!flags->nomount)
+ err |= changelist_postfix(clp);
changelist_free(clp);
}
diff --git a/cddl/contrib/opensolaris/lib/libzpool/common/kernel.c b/cddl/contrib/opensolaris/lib/libzpool/common/kernel.c
index 126a7c1..56d7bf3 100644
--- a/cddl/contrib/opensolaris/lib/libzpool/common/kernel.c
+++ b/cddl/contrib/opensolaris/lib/libzpool/common/kernel.c
@@ -366,10 +366,13 @@ cv_timedwait_hires(kcondvar_t *cv, kmutex_t *mp, hrtime_t tim, hrtime_t res,
timestruc_t ts;
hrtime_t delta;
- ASSERT(flag == 0);
+ ASSERT(flag == 0 || flag == CALLOUT_FLAG_ABSOLUTE);
top:
- delta = tim - gethrtime();
+ delta = tim;
+ if (flag & CALLOUT_FLAG_ABSOLUTE)
+ delta -= gethrtime();
+
if (delta <= 0)
return (-1);
diff --git a/cddl/contrib/opensolaris/lib/libzpool/common/sys/zfs_context.h b/cddl/contrib/opensolaris/lib/libzpool/common/sys/zfs_context.h
index 22774af..f11174f 100644
--- a/cddl/contrib/opensolaris/lib/libzpool/common/sys/zfs_context.h
+++ b/cddl/contrib/opensolaris/lib/libzpool/common/sys/zfs_context.h
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2015 by Delphix. All rights reserved.
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
*/
/*
@@ -324,6 +324,7 @@ extern gid_t *crgetgroups(cred_t *cr);
typedef cond_t kcondvar_t;
#define CV_DEFAULT USYNC_THREAD
+#define CALLOUT_FLAG_ABSOLUTE 0x2
extern void cv_init(kcondvar_t *cv, char *name, int type, void *arg);
extern void cv_destroy(kcondvar_t *cv);
diff --git a/contrib/bmake/ChangeLog b/contrib/bmake/ChangeLog
index 78b5a7e..6f47f1a 100644
--- a/contrib/bmake/ChangeLog
+++ b/contrib/bmake/ChangeLog
@@ -1,3 +1,20 @@
+2016-03-15 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * Makefile (_MAKE_VERSION): 20160315
+ Merge with NetBSD make, pick up
+ o fix handling of archive members
+
+2016-03-13 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * Makefile (_MAKE_VERSION): rename variable to avoid interference
+ with checks for ${MAKE_VERSION}
+
+2016-03-10 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * Makefile (MAKE_VERSION): 20160310
+ Merge with NetBSD make, pick up
+ o meta.c: treat missing Read file same as Write, incase we Delete it.
+
2016-03-07 Simon J. Gerraty <sjg@bad.crufty.net>
* Makefile (MAKE_VERSION): 20160307
diff --git a/contrib/bmake/Makefile b/contrib/bmake/Makefile
index 730e15d..87f6254 100644
--- a/contrib/bmake/Makefile
+++ b/contrib/bmake/Makefile
@@ -1,7 +1,7 @@
-# $Id: Makefile,v 1.55 2016/03/07 22:02:47 sjg Exp $
+# $Id: Makefile,v 1.58 2016/03/15 23:39:12 sjg Exp $
# Base version on src date
-MAKE_VERSION= 20160307
+_MAKE_VERSION= 20160315
PROG= bmake
@@ -76,7 +76,7 @@ CFLAGS+= ${CPPFLAGS}
CFLAGS+= -D_PATH_DEFSYSPATH=\"${DEFAULT_SYS_PATH}\"
CFLAGS+= -I. -I${srcdir} ${XDEFS} -DMAKE_NATIVE
CFLAGS+= ${COPTS.${.ALLSRC:M*.c:T:u}}
-COPTS.main.c+= "-DMAKE_VERSION=\"${MAKE_VERSION}\""
+COPTS.main.c+= "-DMAKE_VERSION=\"${_MAKE_VERSION}\""
# meta mode can be useful even without filemon
FILEMON_H ?= /usr/include/dev/filemon/filemon.h
diff --git a/contrib/bmake/bmake.1 b/contrib/bmake/bmake.1
index 603481e..915963c 100644
--- a/contrib/bmake/bmake.1
+++ b/contrib/bmake/bmake.1
@@ -1,4 +1,4 @@
-.\" $NetBSD: make.1,v 1.254 2016/02/20 01:43:28 wiz Exp $
+.\" $NetBSD: make.1,v 1.255 2016/03/14 07:42:15 matthias Exp $
.\"
.\" Copyright (c) 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -685,6 +685,9 @@ or it will not be recognized.
.It Va .TARGET
The name of the target; also known as
.Ql Va @ .
+For compatibility with other makes this is an alias for
+.Ic .ARCHIVE
+in archive member rules.
.El
.Pp
The shorter forms
diff --git a/contrib/bmake/bmake.cat1 b/contrib/bmake/bmake.cat1
index b6159a8..091bdd4 100644
--- a/contrib/bmake/bmake.cat1
+++ b/contrib/bmake/bmake.cat1
@@ -438,7 +438,9 @@ VVAARRIIAABBLLEE AASSSSIIGGNNMMEENNTTSS
suffixes declared with ..SSUUFFFFIIXXEESS or it will not be recog-
nized.
- _._T_A_R_G_E_T The name of the target; also known as `_@'.
+ _._T_A_R_G_E_T The name of the target; also known as `_@'. For compati-
+ bility with other makes this is an alias for ..AARRCCHHIIVVEE in
+ archive member rules.
The shorter forms (`_>', `_!', `_<', `_%', `_?', `_*', and `_@') are permitted
for backward compatibility with historical makefiles and legacy POSIX
diff --git a/contrib/bmake/make.1 b/contrib/bmake/make.1
index ecece48..07b2320 100644
--- a/contrib/bmake/make.1
+++ b/contrib/bmake/make.1
@@ -1,4 +1,4 @@
-.\" $NetBSD: make.1,v 1.254 2016/02/20 01:43:28 wiz Exp $
+.\" $NetBSD: make.1,v 1.255 2016/03/14 07:42:15 matthias Exp $
.\"
.\" Copyright (c) 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -685,6 +685,9 @@ or it will not be recognized.
.It Va .TARGET
The name of the target; also known as
.Ql Va @ .
+For compatibility with other makes this is an alias for
+.Ic .ARCHIVE
+in archive member rules.
.El
.Pp
The shorter forms
diff --git a/contrib/bmake/meta.c b/contrib/bmake/meta.c
index f4acbde..4faf836 100644
--- a/contrib/bmake/meta.c
+++ b/contrib/bmake/meta.c
@@ -1,4 +1,4 @@
-/* $NetBSD: meta.c,v 1.53 2016/03/07 21:45:43 christos Exp $ */
+/* $NetBSD: meta.c,v 1.54 2016/03/11 07:01:21 sjg Exp $ */
/*
* Implement 'meta' mode.
@@ -1190,7 +1190,8 @@ meta_oodate(GNode *gn, Boolean oodate)
if ((link_src != NULL && lstat(p, &fs) < 0) ||
(link_src == NULL && stat(p, &fs) < 0)) {
- Lst_AtEnd(missingFiles, bmake_strdup(p));
+ if (Lst_Find(missingFiles, p, string_match) == NULL)
+ Lst_AtEnd(missingFiles, bmake_strdup(p));
}
break;
check_link_src:
@@ -1281,9 +1282,8 @@ meta_oodate(GNode *gn, Boolean oodate)
* A referenced file outside of CWD is missing.
* We cannot catch every eventuality here...
*/
- if (DEBUG(META))
- fprintf(debug_file, "%s: %d: file '%s' may have moved?...\n", fname, lineno, p);
- oodate = TRUE;
+ if (Lst_Find(missingFiles, p, string_match) == NULL)
+ Lst_AtEnd(missingFiles, bmake_strdup(p));
}
}
if (buf[0] == 'E') {
diff --git a/contrib/bmake/mk/ChangeLog b/contrib/bmake/mk/ChangeLog
index f84b5c5..50d6719 100644
--- a/contrib/bmake/mk/ChangeLog
+++ b/contrib/bmake/mk/ChangeLog
@@ -1,3 +1,26 @@
+2016-03-15 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): 20160315
+
+ * meta.stage.mk (LN_CP_SCRIPT): do not ln(1) if we have to chmod(1)
+ normally only applies to scripts.
+
+ * dirdeps.mk: NO_DIRDEPS_BELOW to supress DIRDEPS below RELDIR as
+ well as outside it.
+
+2016-03-10 Simon J. Gerraty <sjg@bad.crufty.net>
+
+ * install-mk (MK_VERSION): 20160310
+
+ * dirdeps.mk: use targets rather than a list to track DIRDEPS that
+ we have processed; the list gets very inefficient as number of
+ DIRDEPS gets large.
+
+ * sys.dependfile.mk: fix comment wrt MACHINE
+
+ * meta.autodep.mk: ignore staged DPADDs when bootstrapping.
+ patch from Bryan Drewery
+
2016-03-02 Simon J. Gerraty <sjg@bad.crufty.net>
* meta2deps.sh: don't ignore subdirs.
diff --git a/contrib/bmake/mk/dirdeps.mk b/contrib/bmake/mk/dirdeps.mk
index ec37e35..c235076 100644
--- a/contrib/bmake/mk/dirdeps.mk
+++ b/contrib/bmake/mk/dirdeps.mk
@@ -1,4 +1,4 @@
-# $Id: dirdeps.mk,v 1.59 2016/02/26 23:32:29 sjg Exp $
+# $Id: dirdeps.mk,v 1.62 2016/03/16 00:11:53 sjg Exp $
# Copyright (c) 2010-2013, Juniper Networks, Inc.
# All rights reserved.
@@ -135,7 +135,6 @@ start_utc := ${now_utc}
# make sure these are empty to start with
_DEP_TARGET_SPEC =
-_DIRDEP_CHECKED =
# If TARGET_SPEC_VARS is other than just MACHINE
# it should be set by sys.mk or similar by now.
@@ -225,7 +224,7 @@ _DEP_TARGET_SPEC = ${_last_dependfile:${M_dep_qual_fixes:ts:}:E}
.endif
.if !empty(_last_dependfile)
# record that we've read dependfile for this
-_DIRDEP_CHECKED += ${_CURDIR}.${TARGET_SPEC}
+_dirdeps_checked.${_CURDIR}.${TARGET_SPEC}:
.endif
.endif
@@ -306,8 +305,10 @@ DEP_SKIP_DIR = ${SKIP_DIR} \
NSkipDir = ${DEP_SKIP_DIR:${M_ListToSkip}}
.if defined(NO_DIRDEPS) || defined(NODIRDEPS) || defined(WITHOUT_DIRDEPS)
-# confine ourselves to the original dir
+# confine ourselves to the original dir and below.
DIRDEPS_FILTER += M${_DEP_RELDIR}*
+.elif defined(NO_DIRDEPS_BELOW)
+DIRDEPS_FILTER += M${_DEP_RELDIR}
.endif
# this is what we run below
@@ -597,9 +598,9 @@ ${_this_dir}.$m: ${_build_dirs:M*.$m:N${_this_dir}.$m}
# Now find more dependencies - and recurse.
.for d in ${_build_all_dirs}
-.if ${_DIRDEP_CHECKED:M$d} == ""
+.if !target(_dirdeps_checked.$d)
# once only
-_DIRDEP_CHECKED += $d
+_dirdeps_checked.$d:
.if ${_debug_search}
.info checking $d
.endif
diff --git a/contrib/bmake/mk/install-mk b/contrib/bmake/mk/install-mk
index 64b238f..3076609 100644
--- a/contrib/bmake/mk/install-mk
+++ b/contrib/bmake/mk/install-mk
@@ -55,7 +55,7 @@
# Simon J. Gerraty <sjg@crufty.net>
# RCSid:
-# $Id: install-mk,v 1.121 2016/02/27 00:23:02 sjg Exp $
+# $Id: install-mk,v 1.123 2016/03/16 00:13:16 sjg Exp $
#
# @(#) Copyright (c) 1994 Simon J. Gerraty
#
@@ -70,7 +70,7 @@
# sjg@crufty.net
#
-MK_VERSION=20160226
+MK_VERSION=20160315
OWNER=
GROUP=
MODE=444
diff --git a/contrib/bmake/mk/meta.autodep.mk b/contrib/bmake/mk/meta.autodep.mk
index 5f70564..831e89f 100644
--- a/contrib/bmake/mk/meta.autodep.mk
+++ b/contrib/bmake/mk/meta.autodep.mk
@@ -1,4 +1,4 @@
-# $Id: meta.autodep.mk,v 1.40 2016/02/22 22:44:58 sjg Exp $
+# $Id: meta.autodep.mk,v 1.41 2016/03/11 01:29:38 sjg Exp $
#
# @(#) Copyright (c) 2010, Simon J. Gerraty
@@ -195,7 +195,7 @@ gendirdeps: ${_DEPENDFILE}
# The pseudo machine "host" is used for HOST_TARGET
DIRDEPS += \
${DPADD:M${_OBJTOP}*:H:C,${_OBJTOP}[^/]*/,,:N.:O:u} \
- ${DPADD:M${_OBJROOT}*:N${_OBJTOP}*:H:S,${_OBJROOT},,:C,^([^/]+)/(.*),\2.\1,:S,${HOST_TARGET}$,host,:N.*:O:u}
+ ${DPADD:M${_OBJROOT}*:N${_OBJTOP}*:N${STAGE_ROOT:U${_OBJTOP}}/*:H:S,${_OBJROOT},,:C,^([^/]+)/(.*),\2.\1,:S,${HOST_TARGET}$,host,:N.*:O:u}
.endif
.endif
diff --git a/contrib/bmake/mk/meta.stage.mk b/contrib/bmake/mk/meta.stage.mk
index 0355d66..c6c7227 100644
--- a/contrib/bmake/mk/meta.stage.mk
+++ b/contrib/bmake/mk/meta.stage.mk
@@ -1,4 +1,4 @@
-# $Id: meta.stage.mk,v 1.43 2016/02/24 18:46:32 sjg Exp $
+# $Id: meta.stage.mk,v 1.44 2016/03/16 18:21:23 sjg Exp $
#
# @(#) Copyright (c) 2011, Simon J. Gerraty
#
@@ -58,7 +58,7 @@ GENDIRDEPS_FILTER += Nnot-empty-is-important \
LN_CP_SCRIPT = LnCp() { \
rm -f $$2 2> /dev/null; \
- ln $$1 $$2 2> /dev/null || \
+ { [ -z "$$mode" ] && ln $$1 $$2 2> /dev/null; } || \
cp -p $$1 $$2; }
# a staging conflict should cause an error
diff --git a/contrib/bmake/mk/sys.dependfile.mk b/contrib/bmake/mk/sys.dependfile.mk
index b4d79f7..5389c24 100644
--- a/contrib/bmake/mk/sys.dependfile.mk
+++ b/contrib/bmake/mk/sys.dependfile.mk
@@ -1,4 +1,4 @@
-# $Id: sys.dependfile.mk,v 1.7 2016/02/20 01:57:39 sjg Exp $
+# $Id: sys.dependfile.mk,v 1.8 2016/03/11 01:34:13 sjg Exp $
#
# @(#) Copyright (c) 2012, Simon J. Gerraty
#
@@ -48,7 +48,7 @@ _e := ${.MAKE.DEPENDFILE_PREFERENCE:@m@${exists($m):?$m:}@}
# MACHINE specific depend files are supported, but *not* default.
# If any already exist, we should follow suit.
_aml = ${ALL_MACHINE_LIST:Uarm amd64 i386 powerpc:N${MACHINE}} ${MACHINE}
-# MACHINE must be the last entry in _aml ;-)
+# make sure we restore MACHINE
_m := ${MACHINE}
_e := ${_aml:@MACHINE@${.MAKE.DEPENDFILE_PREFERENCE:@m@${exists($m):?$m:}@}@}
MACHINE := ${_m}
diff --git a/contrib/bmake/parse.c b/contrib/bmake/parse.c
index 2a22c0b..03275e2 100644
--- a/contrib/bmake/parse.c
+++ b/contrib/bmake/parse.c
@@ -1,4 +1,4 @@
-/* $NetBSD: parse.c,v 1.212 2016/02/19 06:19:06 sjg Exp $ */
+/* $NetBSD: parse.c,v 1.213 2016/03/11 13:54:47 matthias Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: parse.c,v 1.212 2016/02/19 06:19:06 sjg Exp $";
+static char rcsid[] = "$NetBSD: parse.c,v 1.213 2016/03/11 13:54:47 matthias Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)parse.c 8.3 (Berkeley) 3/19/94";
#else
-__RCSID("$NetBSD: parse.c,v 1.212 2016/02/19 06:19:06 sjg Exp $");
+__RCSID("$NetBSD: parse.c,v 1.213 2016/03/11 13:54:47 matthias Exp $");
#endif
#endif /* not lint */
#endif
@@ -1261,6 +1261,7 @@ ParseDoDependency(char *line)
goto out;
} else {
/* Done with this word; on to the next. */
+ cp = line;
continue;
}
}
diff --git a/contrib/bmake/suff.c b/contrib/bmake/suff.c
index 98bd447..97f745b 100644
--- a/contrib/bmake/suff.c
+++ b/contrib/bmake/suff.c
@@ -1,4 +1,4 @@
-/* $NetBSD: suff.c,v 1.78 2016/02/18 18:29:14 christos Exp $ */
+/* $NetBSD: suff.c,v 1.81 2016/03/15 18:30:14 matthias Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: suff.c,v 1.78 2016/02/18 18:29:14 christos Exp $";
+static char rcsid[] = "$NetBSD: suff.c,v 1.81 2016/03/15 18:30:14 matthias Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)suff.c 8.4 (Berkeley) 3/21/94";
#else
-__RCSID("$NetBSD: suff.c,v 1.78 2016/02/18 18:29:14 christos Exp $");
+__RCSID("$NetBSD: suff.c,v 1.81 2016/03/15 18:30:14 matthias Exp $");
#endif
#endif /* not lint */
#endif
@@ -1894,6 +1894,7 @@ SuffFindArchiveDeps(GNode *gn, Lst slst)
TARGET, /* Must be first */
PREFIX, /* Must be second */
};
+ LstNode ln, nln; /* Next suffix node to check */
int i; /* Index into copy and vals */
Suff *ms; /* Suffix descriptor for member */
char *name; /* Start of member's name */
@@ -1955,6 +1956,20 @@ SuffFindArchiveDeps(GNode *gn, Lst slst)
Var_Set(MEMBER, name, gn, 0);
Var_Set(ARCHIVE, gn->name, gn, 0);
+ /*
+ * Set $@ for compatibility with other makes
+ */
+ Var_Set(TARGET, gn->name, gn, 0);
+
+ /*
+ * Now we've got the important local variables set, expand any sources
+ * that still contain variables or wildcards in their names.
+ */
+ for (ln = Lst_First(gn->children); ln != NULL; ln = nln) {
+ nln = Lst_Succ(ln);
+ SuffExpandChildren(ln, gn);
+ }
+
if (ms != NULL) {
/*
* Member has a known suffix, so look for a transformation rule from
@@ -1962,7 +1977,6 @@ SuffFindArchiveDeps(GNode *gn, Lst slst)
* through the entire list, we just look at suffixes to which the
* member's suffix may be transformed...
*/
- LstNode ln;
SuffixCmpData sd; /* Search string data */
/*
@@ -2002,9 +2016,10 @@ SuffFindArchiveDeps(GNode *gn, Lst slst)
/*
* Flag the member as such so we remember to look in the archive for
- * its modification time.
+ * its modification time. The OP_JOIN | OP_MADE is needed because this
+ * target should never get made.
*/
- mem->type |= OP_MEMBER;
+ mem->type |= OP_MEMBER | OP_JOIN | OP_MADE;
}
/*-
diff --git a/contrib/bmake/var.c b/contrib/bmake/var.c
index 36ba6de..98b868a 100644
--- a/contrib/bmake/var.c
+++ b/contrib/bmake/var.c
@@ -1,4 +1,4 @@
-/* $NetBSD: var.c,v 1.206 2016/03/07 20:20:35 sjg Exp $ */
+/* $NetBSD: var.c,v 1.207 2016/03/11 15:12:39 matthias Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -69,14 +69,14 @@
*/
#ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: var.c,v 1.206 2016/03/07 20:20:35 sjg Exp $";
+static char rcsid[] = "$NetBSD: var.c,v 1.207 2016/03/11 15:12:39 matthias Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 3/19/94";
#else
-__RCSID("$NetBSD: var.c,v 1.206 2016/03/07 20:20:35 sjg Exp $");
+__RCSID("$NetBSD: var.c,v 1.207 2016/03/11 15:12:39 matthias Exp $");
#endif
#endif /* not lint */
#endif
@@ -3699,11 +3699,11 @@ Var_Parse(const char *str, GNode *ctxt, int flags,
case '@':
return UNCONST("$(.TARGET)");
case '%':
- return UNCONST("$(.ARCHIVE)");
+ return UNCONST("$(.MEMBER)");
case '*':
return UNCONST("$(.PREFIX)");
case '!':
- return UNCONST("$(.MEMBER)");
+ return UNCONST("$(.ARCHIVE)");
}
}
/*
diff --git a/contrib/bsnmp/snmp_mibII/mibII_tcp.c b/contrib/bsnmp/snmp_mibII/mibII_tcp.c
index c798bae..913a537 100644
--- a/contrib/bsnmp/snmp_mibII/mibII_tcp.c
+++ b/contrib/bsnmp/snmp_mibII/mibII_tcp.c
@@ -47,6 +47,7 @@ struct tcp_index {
static uint64_t tcp_tick;
static uint64_t tcp_stats_tick;
static struct tcpstat tcpstat;
+static uint64_t tcps_states[TCP_NSTATES];
static struct xinpgen *xinpgen;
static size_t xinpgen_len;
static u_int tcp_total;
@@ -78,6 +79,17 @@ fetch_tcp_stats(void)
return (-1);
}
+ len = sizeof(tcps_states);
+ if (sysctlbyname("net.inet.tcp.states", &tcps_states, &len, NULL,
+ 0) == -1) {
+ syslog(LOG_ERR, "net.inet.tcp.states: %m");
+ return (-1);
+ }
+ if (len != sizeof(tcps_states)) {
+ syslog(LOG_ERR, "net.inet.tcp.states: wrong size");
+ return (-1);
+ }
+
tcp_stats_tick = get_ticks();
return (0);
@@ -231,8 +243,8 @@ op_tcp(struct snmp_context *ctx __unused, struct snmp_value *value,
break;
case LEAF_tcpCurrEstab:
- value->v.uint32 = tcpstat.tcps_states[TCPS_ESTABLISHED] +
- tcpstat.tcps_states[TCPS_CLOSE_WAIT];
+ value->v.uint32 = tcps_states[TCPS_ESTABLISHED] +
+ tcps_states[TCPS_CLOSE_WAIT];
break;
case LEAF_tcpInSegs:
diff --git a/contrib/byacc/CHANGES b/contrib/byacc/CHANGES
index a61b2f22f..1c3f442 100644
--- a/contrib/byacc/CHANGES
+++ b/contrib/byacc/CHANGES
@@ -1,3 +1,28 @@
+2016-03-24 Thomas E. Dickey <tom@invisible-island.net>
+
+ * reader.c: unused variable
+
+ * package/pkgsrc/Makefile, package/debian/copyright: bump
+
+2016-03-24 Jung-uk.Kim
+
+ * main.c:
+ correct logic for finding output suffix in the "-o" option, which matched
+ the first occurrence of ".c" in the name in 2005-08-13 changes rather than
+ at the end of the filename (patch by Jung-uk Kim)
+
+2016-03-24 Thomas E. Dickey <tom@invisible-island.net>
+
+ * aclocal.m4:
+ update CF_WITH_MAN2HTML to use configured shell rather than /bin/sh
+
+ * VERSION, package/byacc.spec, package/debian/changelog, package/mingw-byacc.spec, package/pkgsrc/Makefile:
+ bump
+
+2016-01-25 Thomas E. Dickey <tom@invisible-island.net>
+
+ * config.guess, config.sub: 2016-01-01
+
2015-07-10 Thomas E. Dickey <tom@invisible-island.net>
* lr0.c: fix a duplicate-free in the leak-checking
@@ -2275,7 +2300,7 @@
* vmsbuild.com: original version
-2000-02-23 Thomas E. Dickey <dickey@invisible-island.net>
+2000-02-23 dickey
* test/RCS, RCS: PERMIT FILE
diff --git a/contrib/byacc/MANIFEST b/contrib/byacc/MANIFEST
index 0ee8f35..7d7e534 100644
--- a/contrib/byacc/MANIFEST
+++ b/contrib/byacc/MANIFEST
@@ -1,4 +1,4 @@
-MANIFEST for byacc-20150711, version t20150711
+MANIFEST for byacc-20160324, version t20160324
--------------------------------------------------------------------------------
MANIFEST this file
ACKNOWLEDGEMENTS original version of byacc - 1993
diff --git a/contrib/byacc/VERSION b/contrib/byacc/VERSION
index 58eff60..9be4062 100644
--- a/contrib/byacc/VERSION
+++ b/contrib/byacc/VERSION
@@ -1 +1 @@
-20150711
+20160324
diff --git a/contrib/byacc/aclocal.m4 b/contrib/byacc/aclocal.m4
index 41358a2..f98d089 100644
--- a/contrib/byacc/aclocal.m4
+++ b/contrib/byacc/aclocal.m4
@@ -1,7 +1,7 @@
-dnl $Id: aclocal.m4,v 1.38 2015/07/05 22:16:23 tom Exp $
+dnl $Id: aclocal.m4,v 1.39 2016/03/25 00:06:44 tom Exp $
dnl Macros for byacc configure script (Thomas E. Dickey)
dnl ---------------------------------------------------------------------------
-dnl Copyright 2004-2014,2015 Thomas E. Dickey
+dnl Copyright 2004-2015,2016 Thomas E. Dickey
dnl
dnl Permission is hereby granted, free of charge, to any person obtaining a
dnl copy of this software and associated documentation files (the
@@ -1121,7 +1121,7 @@ if test "$with_dmalloc" = yes ; then
fi
])dnl
dnl ---------------------------------------------------------------------------
-dnl CF_WITH_MAN2HTML version: 4 updated: 2015/05/03 19:10:48
+dnl CF_WITH_MAN2HTML version: 5 updated: 2015/08/20 04:51:36
dnl ----------------
dnl Check for man2html and groff. Optionally prefer man2html over groff.
dnl Generate a shell script which hides the differences between the two.
@@ -1157,7 +1157,7 @@ esac
MAN2HTML_TEMP="man2html.tmp"
cat >$MAN2HTML_TEMP <<CF_EOF
-#!/bin/sh
+#!$SHELL
# Temporary script generated by CF_WITH_MAN2HTML
# Convert inputs to html, sending result to standard output.
#
@@ -1184,7 +1184,7 @@ then
MAN2HTML_NOTE="$GROFF_NOTE"
MAN2HTML_PATH="$GROFF_PATH"
cat >>$MAN2HTML_TEMP <<CF_EOF
-/bin/sh -c "tbl \${ROOT}.\${TYPE} | $GROFF_PATH -P -o0 -I\${ROOT}_ -Thtml -\${MACS}"
+$SHELL -c "tbl \${ROOT}.\${TYPE} | $GROFF_PATH -P -o0 -I\${ROOT}_ -Thtml -\${MACS}"
CF_EOF
else
MAN2HTML_NOTE=""
@@ -1287,7 +1287,7 @@ fi
fi
])dnl
dnl ---------------------------------------------------------------------------
-dnl CF_XOPEN_SOURCE version: 49 updated: 2015/04/12 15:39:00
+dnl CF_XOPEN_SOURCE version: 50 updated: 2015/10/17 19:03:33
dnl ---------------
dnl Try to get _XOPEN_SOURCE defined properly that we can use POSIX functions,
dnl or adapt to the vendor's definitions to get equivalent functionality,
@@ -1357,6 +1357,9 @@ case $host_os in
(openbsd*)
# setting _XOPEN_SOURCE breaks xterm on OpenBSD 2.8, is not needed for ncursesw
;;
+(os2*)
+ cf_XOPEN_SOURCE=
+ ;;
(osf[[45]]*)
cf_xopen_source="-D_OSF_SOURCE"
;;
diff --git a/contrib/byacc/config.guess b/contrib/byacc/config.guess
index f7eb141..dcd5149 100755
--- a/contrib/byacc/config.guess
+++ b/contrib/byacc/config.guess
@@ -1,8 +1,8 @@
#! /bin/sh
# Attempt to guess a canonical system name.
-# Copyright 1992-2015 Free Software Foundation, Inc.
+# Copyright 1992-2016 Free Software Foundation, Inc.
-timestamp='2015-03-04'
+timestamp='2016-01-01'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -27,7 +27,7 @@ timestamp='2015-03-04'
# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
#
# You can get the latest version of this script from:
-# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
#
# Please send patches to <config-patches@gnu.org>.
@@ -50,7 +50,7 @@ version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
-Copyright 1992-2015 Free Software Foundation, Inc.
+Copyright 1992-2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -221,7 +221,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
release='-gnu'
;;
*)
- release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2`
;;
esac
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
@@ -249,6 +249,9 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
*:MirBSD:*:*)
echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
exit ;;
+ *:Sortix:*:*)
+ echo ${UNAME_MACHINE}-unknown-sortix
+ exit ;;
alpha:OSF1:*:*)
case $UNAME_RELEASE in
*4.0)
@@ -962,6 +965,9 @@ EOF
ia64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
+ k1om:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
m32r*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
@@ -1038,7 +1044,7 @@ EOF
echo ${UNAME_MACHINE}-dec-linux-${LIBC}
exit ;;
x86_64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ echo ${UNAME_MACHINE}-pc-linux-${LIBC}
exit ;;
xtensa*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
@@ -1117,7 +1123,7 @@ EOF
# uname -m prints for DJGPP always 'pc', but it prints nothing about
# the processor, so we play safe by assuming i586.
# Note: whatever this is, it MUST be the same as what config.sub
- # prints for the "djgpp" host, or else GDB configury will decide that
+ # prints for the "djgpp" host, or else GDB configure will decide that
# this is a cross-build.
echo i586-pc-msdosdjgpp
exit ;;
@@ -1387,6 +1393,9 @@ EOF
x86_64:VMkernel:*:*)
echo ${UNAME_MACHINE}-unknown-esx
exit ;;
+ amd64:Isilon\ OneFS:*:*)
+ echo x86_64-unknown-onefs
+ exit ;;
esac
cat >&2 <<EOF
@@ -1396,9 +1405,9 @@ This script, last modified $timestamp, has failed to recognize
the operating system you are using. It is advised that you
download the most up to date version of the config scripts from
- http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
and
- http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
If the version you run ($0) is already up to date, please
send the following data and any information you think might be
diff --git a/contrib/byacc/config.sub b/contrib/byacc/config.sub
index 8f1229c..da6d1b6 100755
--- a/contrib/byacc/config.sub
+++ b/contrib/byacc/config.sub
@@ -1,8 +1,8 @@
#! /bin/sh
# Configuration validation subroutine script.
-# Copyright 1992-2015 Free Software Foundation, Inc.
+# Copyright 1992-2016 Free Software Foundation, Inc.
-timestamp='2015-03-08'
+timestamp='2016-01-01'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -33,7 +33,7 @@ timestamp='2015-03-08'
# Otherwise, we print the canonical config type on stdout and succeed.
# You can get the latest version of this script from:
-# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
@@ -53,8 +53,7 @@ timestamp='2015-03-08'
me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
-Usage: $0 [OPTION] CPU-MFR-OPSYS
- $0 [OPTION] ALIAS
+Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
Canonicalize a configuration name.
@@ -68,7 +67,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
-Copyright 1992-2015 Free Software Foundation, Inc.
+Copyright 1992-2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -255,6 +254,7 @@ case $basic_machine in
| arc | arceb \
| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
| avr | avr32 \
+ | ba \
| be32 | be64 \
| bfin \
| c4x | c8051 | clipper \
@@ -305,7 +305,7 @@ case $basic_machine in
| riscv32 | riscv64 \
| rl78 | rx \
| score \
- | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
@@ -376,6 +376,7 @@ case $basic_machine in
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* | avr32-* \
+ | ba-* \
| be32-* | be64-* \
| bfin-* | bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* \
@@ -428,12 +429,13 @@ case $basic_machine in
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
| pyramid-* \
+ | riscv32-* | riscv64-* \
| rl78-* | romp-* | rs6000-* | rx-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
| sparclite-* \
- | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \
| tahoe-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
| tile*-* \
@@ -518,7 +520,7 @@ case $basic_machine in
basic_machine=i386-pc
os=-aros
;;
- asmjs)
+ asmjs)
basic_machine=asmjs-unknown
;;
aux)
@@ -1376,7 +1378,7 @@ case $os in
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
| -sym* | -kopensolaris* | -plan9* \
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
- | -aos* | -aros* | -cloudabi* \
+ | -aos* | -aros* | -cloudabi* | -sortix* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
@@ -1396,7 +1398,8 @@ case $os in
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
- | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
+ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
+ | -onefs* | -tirtos*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
diff --git a/contrib/byacc/main.c b/contrib/byacc/main.c
index 620ce3f..37889c3 100644
--- a/contrib/byacc/main.c
+++ b/contrib/byacc/main.c
@@ -1,4 +1,4 @@
-/* $Id: main.c,v 1.55 2015/07/11 00:34:19 tom Exp $ */
+/* $Id: main.c,v 1.56 2016/03/25 00:16:28 Jung-uk.Kim Exp $ */
#include <signal.h>
#ifndef _WIN32
@@ -410,32 +410,46 @@ alloc_file_name(size_t len, const char *suffix)
return result;
}
+static char *
+find_suffix(char *name, const char *suffix)
+{
+ size_t len = strlen(name);
+ size_t slen = strlen(suffix);
+ if (len >= slen)
+ {
+ name += len - slen;
+ if (strcmp(name, suffix) == 0)
+ return name;
+ }
+ return NULL;
+}
+
static void
create_file_names(void)
{
size_t len;
const char *defines_suffix;
const char *externs_suffix;
- char *prefix;
+ char *suffix;
- prefix = NULL;
+ suffix = NULL;
defines_suffix = DEFINES_SUFFIX;
externs_suffix = EXTERNS_SUFFIX;
/* compute the file_prefix from the user provided output_file_name */
if (output_file_name != 0)
{
- if (!(prefix = strstr(output_file_name, OUTPUT_SUFFIX))
- && (prefix = strstr(output_file_name, ".c")))
+ if (!(suffix = find_suffix(output_file_name, OUTPUT_SUFFIX))
+ && (suffix = find_suffix(output_file_name, ".c")))
{
defines_suffix = ".h";
externs_suffix = ".i";
}
}
- if (prefix != NULL)
+ if (suffix != NULL)
{
- len = (size_t) (prefix - output_file_name);
+ len = (size_t) (suffix - output_file_name);
file_prefix = TMALLOC(char, len + 1);
NO_SPACE(file_prefix);
strncpy(file_prefix, output_file_name, len)[len] = 0;
@@ -477,7 +491,7 @@ create_file_names(void)
CREATE_FILE_NAME(graph_file_name, GRAPH_SUFFIX);
}
- if (prefix != NULL)
+ if (suffix != NULL)
{
FREE(file_prefix);
}
diff --git a/contrib/byacc/package/byacc.spec b/contrib/byacc/package/byacc.spec
index 47fc25f..c18affa 100644
--- a/contrib/byacc/package/byacc.spec
+++ b/contrib/byacc/package/byacc.spec
@@ -1,8 +1,8 @@
Summary: byacc - public domain Berkeley LALR Yacc parser generator
%define AppProgram byacc
-%define AppVersion 20150711
+%define AppVersion 20160324
%define UseProgram yacc
-# $XTermId: byacc.spec,v 1.28 2015/07/11 00:53:15 tom Exp $
+# $XTermId: byacc.spec,v 1.29 2016/03/24 23:55:52 tom Exp $
Name: %{AppProgram}
Version: %{AppVersion}
Release: 1
diff --git a/contrib/byacc/package/debian/changelog b/contrib/byacc/package/debian/changelog
index 4c01294..91b9c18 100644
--- a/contrib/byacc/package/debian/changelog
+++ b/contrib/byacc/package/debian/changelog
@@ -1,3 +1,9 @@
+byacc (20160324) unstable; urgency=low
+
+ * maintenance updates
+
+ -- Thomas E. Dickey <dickey@invisible-island.net> Thu, 24 Mar 2016 19:55:52 -0400
+
byacc (20150711) unstable; urgency=low
* maintenance updates
diff --git a/contrib/byacc/package/debian/copyright b/contrib/byacc/package/debian/copyright
index 77e9447..77ab795 100644
--- a/contrib/byacc/package/debian/copyright
+++ b/contrib/byacc/package/debian/copyright
@@ -1,4 +1,4 @@
-Upstream source http://dickey.his.com/byacc/byacc.html
+Upstream source http://invisible-island.net/byacc/byacc.html
Berkeley Yacc is in the public domain; changes made to it by the current
maintainer are likewise unrestricted. That applies to most of the files.
@@ -36,7 +36,7 @@ skeleton.c with the bug report. Do not expect rapid responses.
Files: aclocal.m4
Licence: other-BSD
-Copyright: 2004-2014,2015 by Thomas E. Dickey
+Copyright: 2004-2015,2016 by Thomas E. Dickey
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
diff --git a/contrib/byacc/package/mingw-byacc.spec b/contrib/byacc/package/mingw-byacc.spec
index 94071b4..6ec6649 100644
--- a/contrib/byacc/package/mingw-byacc.spec
+++ b/contrib/byacc/package/mingw-byacc.spec
@@ -1,8 +1,8 @@
Summary: byacc - public domain Berkeley LALR Yacc parser generator
%define AppProgram byacc
-%define AppVersion 20150711
+%define AppVersion 20160324
%define UseProgram yacc
-# $XTermId: mingw-byacc.spec,v 1.10 2015/07/11 00:53:15 tom Exp $
+# $XTermId: mingw-byacc.spec,v 1.11 2016/03/24 23:55:52 tom Exp $
Name: %{AppProgram}
Version: %{AppVersion}
Release: 1
diff --git a/contrib/byacc/package/pkgsrc/Makefile b/contrib/byacc/package/pkgsrc/Makefile
index 473942b..bb568d1 100644
--- a/contrib/byacc/package/pkgsrc/Makefile
+++ b/contrib/byacc/package/pkgsrc/Makefile
@@ -1,14 +1,14 @@
# $NetBSD: Makefile,v 1.9 2008/07/24 17:13:00 tonnerre Exp $
#
-DISTNAME= byacc-20150711
+DISTNAME= byacc-20160324
PKGREVISION= 1
CATEGORIES= devel
MASTER_SITES= ftp://invisible-island.net/byacc/
EXTRACT_SUFX= .tgz
MAINTAINER= pkgsrc-users@NetBSD.org
-HOMEPAGE= http://dickey.his.com/byacc/byacc.html
+HOMEPAGE= http://invisible-island.net/byacc/byacc.html
COMMENT= Berkeley Yacc
PKG_DESTDIR_SUPPORT= user-destdir
diff --git a/contrib/byacc/reader.c b/contrib/byacc/reader.c
index 563a2e8..502e4a2 100644
--- a/contrib/byacc/reader.c
+++ b/contrib/byacc/reader.c
@@ -1,4 +1,4 @@
-/* $Id: reader.c,v 1.59 2015/07/11 00:39:03 tom Exp $ */
+/* $Id: reader.c,v 1.60 2016/03/25 00:51:07 tom Exp $ */
#include "defs.h"
@@ -895,7 +895,7 @@ copy_param(int k)
}
buf[i--] = '\0';
- i = trim_blanks(buf);
+ (void)trim_blanks(buf);
comma = buf - 1;
do
diff --git a/contrib/elftoolchain/elfcopy/elfcopy.h b/contrib/elftoolchain/elfcopy/elfcopy.h
index 614c0e7..f88aaf4 100644
--- a/contrib/elftoolchain/elfcopy/elfcopy.h
+++ b/contrib/elftoolchain/elfcopy/elfcopy.h
@@ -139,7 +139,8 @@ struct section {
/* Internal data structure for segments. */
struct segment {
- uint64_t addr; /* load addr */
+ uint64_t vaddr; /* virtual addr (VMA) */
+ uint64_t paddr; /* physical addr (LMA) */
uint64_t off; /* file offset */
uint64_t fsz; /* file size */
uint64_t msz; /* memory size */
diff --git a/contrib/elftoolchain/elfcopy/segments.c b/contrib/elftoolchain/elfcopy/segments.c
index 8ce0b83..78782a4 100644
--- a/contrib/elftoolchain/elfcopy/segments.c
+++ b/contrib/elftoolchain/elfcopy/segments.c
@@ -72,12 +72,12 @@ add_to_inseg_list(struct elfcopy *ecp, struct section *s)
*/
loadable = 0;
STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) {
- if (s->off < seg->off || (s->vma < seg->addr && !s->pseudo))
+ if (s->off < seg->off || (s->vma < seg->vaddr && !s->pseudo))
continue;
if (s->off + s->sz > seg->off + seg->fsz &&
s->type != SHT_NOBITS)
continue;
- if (s->vma + s->sz > seg->addr + seg->msz)
+ if (s->vma + s->sz > seg->vaddr + seg->msz)
continue;
insert_to_inseg_list(seg, s);
@@ -85,7 +85,12 @@ add_to_inseg_list(struct elfcopy *ecp, struct section *s)
s->seg = seg;
else if (seg->type == PT_TLS)
s->seg_tls = seg;
- s->lma = seg->addr + (s->off - seg->off);
+ if (s->pseudo)
+ s->vma = seg->vaddr + (s->off - seg->off);
+ if (seg->paddr > 0)
+ s->lma = seg->paddr + (s->off - seg->off);
+ else
+ s->lma = 0;
loadable = 1;
}
@@ -98,7 +103,7 @@ adjust_addr(struct elfcopy *ecp)
struct section *s, *s0;
struct segment *seg;
struct sec_action *sac;
- uint64_t dl, lma, start, end;
+ uint64_t dl, vma, lma, start, end;
int found, i;
/*
@@ -110,59 +115,52 @@ adjust_addr(struct elfcopy *ecp)
if (!s->loadable)
continue;
+ /* Apply global VMA adjustment. */
+ if (ecp->change_addr != 0)
+ s->vma += ecp->change_addr;
+
/* Apply global LMA adjustment. */
- if (ecp->change_addr != 0 && s->seg != NULL)
+ if (ecp->change_addr != 0 && s->seg != NULL &&
+ s->seg->paddr > 0)
s->lma += ecp->change_addr;
-
- if (!s->pseudo) {
- /* Apply global VMA adjustment. */
- if (ecp->change_addr != 0)
- s->vma += ecp->change_addr;
-
- /* Apply section VMA adjustment. */
- sac = lookup_sec_act(ecp, s->name, 0);
- if (sac == NULL)
- continue;
- if (sac->setvma)
- s->vma = sac->vma;
- if (sac->vma_adjust != 0)
- s->vma += sac->vma_adjust;
- }
}
/*
- * Apply sections LMA change in the second iteration.
+ * Apply sections VMA change in the second iteration.
*/
TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
- /*
- * Only loadable section that's inside a segment can have
- * LMA adjusted.
- */
- if (!s->loadable || s->seg == NULL)
+ if (!s->loadable)
continue;
/*
- * Check if there is a LMA change request for this
+ * Check if there is a VMA change request for this
* section.
*/
sac = lookup_sec_act(ecp, s->name, 0);
if (sac == NULL)
continue;
- if (!sac->setlma && sac->lma_adjust == 0)
+ vma = s->vma;
+ if (sac->setvma)
+ vma = sac->vma;
+ if (sac->vma_adjust != 0)
+ vma += sac->vma_adjust;
+ if (vma == s->vma)
continue;
- lma = s->lma;
- if (sac->setlma)
- lma = sac->lma;
- if (sac->lma_adjust != 0)
- lma += sac->lma_adjust;
- if (lma == s->lma)
+
+ /*
+ * No need to make segment adjustment if the section doesn't
+ * belong to any segment.
+ */
+ if (s->seg == NULL) {
+ s->vma = vma;
continue;
+ }
/*
- * Check if the LMA change is viable.
+ * Check if the VMA change is viable.
*
- * 1. Check if the new LMA is properly aligned accroding to
+ * 1. Check if the new VMA is properly aligned accroding to
* section alignment.
*
* 2. Compute the new extent of segment that contains this
@@ -170,37 +168,36 @@ adjust_addr(struct elfcopy *ecp)
* segments.
*/
#ifdef DEBUG
- printf("LMA for section %s: %#jx\n", s->name, lma);
+ printf("VMA for section %s: %#jx\n", s->name, vma);
#endif
- if (lma % s->align != 0)
- errx(EXIT_FAILURE, "The load address %#jx for "
+ if (vma % s->align != 0)
+ errx(EXIT_FAILURE, "The VMA %#jx for "
"section %s is not aligned to %ju",
- (uintmax_t) lma, s->name, (uintmax_t) s->align);
+ (uintmax_t) vma, s->name, (uintmax_t) s->align);
- if (lma < s->lma) {
+ if (vma < s->vma) {
/* Move section to lower address. */
- if (lma < s->lma - s->seg->addr)
+ if (vma < s->vma - s->seg->vaddr)
errx(EXIT_FAILURE, "Not enough space to move "
- "section %s load address to %#jx", s->name,
- (uintmax_t) lma);
- start = lma - (s->lma - s->seg->addr);
+ "section %s VMA to %#jx", s->name,
+ (uintmax_t) vma);
+ start = vma - (s->vma - s->seg->vaddr);
if (s == s->seg->v_sec[s->seg->nsec - 1])
end = start + s->seg->msz;
else
- end = s->seg->addr + s->seg->msz;
-
+ end = s->seg->vaddr + s->seg->msz;
} else {
/* Move section to upper address. */
if (s == s->seg->v_sec[0])
- start = lma;
+ start = vma;
else
- start = s->seg->addr;
- end = lma + (s->seg->addr + s->seg->msz - s->lma);
+ start = s->seg->vaddr;
+ end = vma + (s->seg->vaddr + s->seg->msz - s->vma);
if (end < start)
errx(EXIT_FAILURE, "Not enough space to move "
- "section %s load address to %#jx", s->name,
- (uintmax_t) lma);
+ "section %s VMA to %#jx", s->name,
+ (uintmax_t) vma);
}
#ifdef DEBUG
@@ -211,34 +208,34 @@ adjust_addr(struct elfcopy *ecp)
STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) {
if (seg == s->seg || seg->type != PT_LOAD)
continue;
- if (start > seg->addr + seg->msz)
+ if (start > seg->vaddr + seg->msz)
continue;
- if (end < seg->addr)
+ if (end < seg->vaddr)
continue;
errx(EXIT_FAILURE, "The extent of segment containing "
"section %s overlaps with segment(%#jx,%#jx)",
- s->name, (uintmax_t) seg->addr,
- (uintmax_t) (seg->addr + seg->msz));
+ s->name, (uintmax_t) seg->vaddr,
+ (uintmax_t) (seg->vaddr + seg->msz));
}
/*
- * Update section LMA and file offset.
+ * Update section VMA and file offset.
*/
- if (lma < s->lma) {
+ if (vma < s->vma) {
/*
- * To move a section to lower load address, we decrease
- * the load addresses of the section and all the
- * sections that are before it, and we increase the
- * file offsets of all the sections that are after it.
+ * To move a section to lower VMA, we decrease
+ * the VMA of the section and all the sections that
+ * are before it, and we increase the file offsets
+ * of all the sections that are after it.
*/
- dl = s->lma - lma;
+ dl = s->vma - vma;
for (i = 0; i < s->seg->nsec; i++) {
s0 = s->seg->v_sec[i];
- s0->lma -= dl;
+ s0->vma -= dl;
#ifdef DEBUG
- printf("section %s LMA set to %#jx\n",
- s0->name, (uintmax_t) s0->lma);
+ printf("section %s VMA set to %#jx\n",
+ s0->name, (uintmax_t) s0->vma);
#endif
if (s0 == s)
break;
@@ -253,13 +250,13 @@ adjust_addr(struct elfcopy *ecp)
}
} else {
/*
- * To move a section to upper load address, we increase
- * the load addresses of the section and all the
- * sections that are after it, and we increase the
- * their file offsets too unless the section in question
+ * To move a section to upper VMA, we increase
+ * the VMA of the section and all the sections that
+ * are after it, and we increase the their file
+ * offsets too unless the section in question
* is the first in its containing segment.
*/
- dl = lma - s->lma;
+ dl = vma - s->vma;
for (i = 0; i < s->seg->nsec; i++)
if (s->seg->v_sec[i] == s)
break;
@@ -269,9 +266,9 @@ adjust_addr(struct elfcopy *ecp)
s->name);
for (; i < s->seg->nsec; i++) {
s0 = s->seg->v_sec[i];
- s0->lma += dl;
+ s0->vma += dl;
#ifdef DEBUG
- printf("section %s LMA set to %#jx\n",
+ printf("section %s VMA set to %#jx\n",
s0->name, (uintmax_t) s0->lma);
#endif
if (s != s->seg->v_sec[0]) {
@@ -292,9 +289,8 @@ adjust_addr(struct elfcopy *ecp)
if (ecp->pad_to != 0) {
/*
- * Find the section with highest load address.
+ * Find the section with highest VMA.
*/
-
s = NULL;
STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) {
if (seg->type != PT_LOAD)
@@ -308,26 +304,113 @@ adjust_addr(struct elfcopy *ecp)
s = seg->v_sec[i];
else {
s0 = seg->v_sec[i];
- if (s0->lma > s->lma)
+ if (s0->vma > s->vma)
s = s0;
}
}
if (s == NULL)
- goto issue_warn;
+ goto adjust_lma;
/* No need to pad if the pad_to address is lower. */
- if (ecp->pad_to <= s->lma + s->sz)
- goto issue_warn;
+ if (ecp->pad_to <= s->vma + s->sz)
+ goto adjust_lma;
- s->pad_sz = ecp->pad_to - (s->lma + s->sz);
+ s->pad_sz = ecp->pad_to - (s->vma + s->sz);
#ifdef DEBUG
- printf("pad section %s load to address %#jx by %#jx\n", s->name,
+ printf("pad section %s VMA to address %#jx by %#jx\n", s->name,
(uintmax_t) ecp->pad_to, (uintmax_t) s->pad_sz);
#endif
}
-issue_warn:
+
+adjust_lma:
+
+ /*
+ * Apply sections LMA change in the third iteration.
+ */
+ TAILQ_FOREACH(s, &ecp->v_sec, sec_list) {
+
+ /*
+ * Only loadable section that's inside a segment can have
+ * LMA adjusted. Also, if LMA of the containing segment is
+ * set to 0, it probably means we should ignore the LMA.
+ */
+ if (!s->loadable || s->seg == NULL || s->seg->paddr == 0)
+ continue;
+
+ /*
+ * Check if there is a LMA change request for this
+ * section.
+ */
+ sac = lookup_sec_act(ecp, s->name, 0);
+ if (sac == NULL)
+ continue;
+ if (!sac->setlma && sac->lma_adjust == 0)
+ continue;
+ lma = s->lma;
+ if (sac->setlma)
+ lma = sac->lma;
+ if (sac->lma_adjust != 0)
+ lma += sac->lma_adjust;
+ if (lma == s->lma)
+ continue;
+
+#ifdef DEBUG
+ printf("LMA for section %s: %#jx\n", s->name, lma);
+#endif
+
+ /* Check alignment. */
+ if (lma % s->align != 0)
+ errx(EXIT_FAILURE, "The LMA %#jx for "
+ "section %s is not aligned to %ju",
+ (uintmax_t) lma, s->name, (uintmax_t) s->align);
+
+ /*
+ * Update section LMA.
+ */
+
+ if (lma < s->lma) {
+ /*
+ * To move a section to lower LMA, we decrease
+ * the LMA of the section and all the sections that
+ * are before it.
+ */
+ dl = s->lma - lma;
+ for (i = 0; i < s->seg->nsec; i++) {
+ s0 = s->seg->v_sec[i];
+ s0->lma -= dl;
+#ifdef DEBUG
+ printf("section %s LMA set to %#jx\n",
+ s0->name, (uintmax_t) s0->lma);
+#endif
+ if (s0 == s)
+ break;
+ }
+ } else {
+ /*
+ * To move a section to upper LMA, we increase
+ * the LMA of the section and all the sections that
+ * are after it.
+ */
+ dl = lma - s->lma;
+ for (i = 0; i < s->seg->nsec; i++)
+ if (s->seg->v_sec[i] == s)
+ break;
+ if (i >= s->seg->nsec)
+ errx(EXIT_FAILURE, "Internal: section `%s' not"
+ " found in its containing segement",
+ s->name);
+ for (; i < s->seg->nsec; i++) {
+ s0 = s->seg->v_sec[i];
+ s0->lma += dl;
+#ifdef DEBUG
+ printf("section %s LMA set to %#jx\n",
+ s0->name, (uintmax_t) s0->lma);
+#endif
+ }
+ }
+ }
/*
* Issue a warning if there are VMA/LMA adjust requests for
@@ -408,7 +491,8 @@ setup_phdr(struct elfcopy *ecp)
elf_errmsg(-1));
if ((seg = calloc(1, sizeof(*seg))) == NULL)
err(EXIT_FAILURE, "calloc failed");
- seg->addr = iphdr.p_vaddr;
+ seg->vaddr = iphdr.p_vaddr;
+ seg->paddr = iphdr.p_paddr;
seg->off = iphdr.p_offset;
seg->fsz = iphdr.p_filesz;
seg->msz = iphdr.p_memsz;
@@ -429,20 +513,30 @@ copy_phdr(struct elfcopy *ecp)
if (seg->type == PT_PHDR) {
if (!TAILQ_EMPTY(&ecp->v_sec)) {
s = TAILQ_FIRST(&ecp->v_sec);
- if (s->pseudo)
- seg->addr = s->lma +
+ if (s->pseudo) {
+ seg->vaddr = s->vma +
+ gelf_fsize(ecp->eout, ELF_T_EHDR,
+ 1, EV_CURRENT);
+ seg->paddr = s->lma +
gelf_fsize(ecp->eout, ELF_T_EHDR,
1, EV_CURRENT);
+ }
}
seg->fsz = seg->msz = gelf_fsize(ecp->eout, ELF_T_PHDR,
ecp->ophnum, EV_CURRENT);
continue;
}
+ if (seg->nsec > 0) {
+ s = seg->v_sec[0];
+ seg->vaddr = s->vma;
+ seg->paddr = s->lma;
+ }
+
seg->fsz = seg->msz = 0;
for (i = 0; i < seg->nsec; i++) {
s = seg->v_sec[i];
- seg->msz = s->vma + s->sz - seg->addr;
+ seg->msz = s->vma + s->sz - seg->vaddr;
if (s->type != SHT_NOBITS)
seg->fsz = s->off + s->sz - seg->off;
}
@@ -481,8 +575,8 @@ copy_phdr(struct elfcopy *ecp)
elf_errmsg(-1));
ophdr.p_type = iphdr.p_type;
- ophdr.p_vaddr = seg->addr;
- ophdr.p_paddr = seg->addr;
+ ophdr.p_vaddr = seg->vaddr;
+ ophdr.p_paddr = seg->paddr;
ophdr.p_flags = iphdr.p_flags;
ophdr.p_align = iphdr.p_align;
ophdr.p_offset = seg->off;
diff --git a/contrib/libc++/include/__config b/contrib/libc++/include/__config
index 051d12c..fe9eec4 100644
--- a/contrib/libc++/include/__config
+++ b/contrib/libc++/include/__config
@@ -364,14 +364,8 @@ typedef __char32_t char32_t;
#endif
#endif
-#if (__has_feature(cxx_noexcept))
-# define _NOEXCEPT noexcept
-# define _NOEXCEPT_(x) noexcept(x)
-# define _NOEXCEPT_OR_FALSE(x) noexcept(x)
-#else
-# define _NOEXCEPT throw()
-# define _NOEXCEPT_(x)
-# define _NOEXCEPT_OR_FALSE(x) false
+#if !(__has_feature(cxx_noexcept))
+#define _LIBCPP_HAS_NO_NOEXCEPT
#endif
#if __has_feature(underlying_type)
@@ -439,10 +433,6 @@ namespace std {
#define _LIBCPP_HAS_NO_VARIABLE_TEMPLATES
#endif
-#define _NOEXCEPT throw()
-#define _NOEXCEPT_(x)
-#define _NOEXCEPT_OR_FALSE(x) false
-
#ifndef __GXX_EXPERIMENTAL_CXX0X__
#define _LIBCPP_HAS_NO_ADVANCED_SFINAE
@@ -456,6 +446,7 @@ namespace std {
#define _LIBCPP_HAS_NO_RVALUE_REFERENCES
#define _LIBCPP_HAS_NO_ALWAYS_INLINE_VARIADICS
#define _LIBCPP_HAS_NO_STRONG_ENUMS
+#define _LIBCPP_HAS_NO_NOEXCEPT
#else // __GXX_EXPERIMENTAL_CXX0X__
@@ -479,6 +470,7 @@ namespace std {
#endif // _GNUC_VER < 404
#if _GNUC_VER < 406
+#define _LIBCPP_HAS_NO_NOEXCEPT
#define _LIBCPP_HAS_NO_NULLPTR
#endif
@@ -513,15 +505,14 @@ using namespace _LIBCPP_NAMESPACE __attribute__((__strong__));
#define _LIBCPP_HAS_NO_UNICODE_CHARS
#define _LIBCPP_HAS_NO_DELETED_FUNCTIONS
#define _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS
+#define _LIBCPP_HAS_NO_NOEXCEPT
#define __alignof__ __alignof
#define _LIBCPP_NORETURN __declspec(noreturn)
#define _LIBCPP_UNUSED
#define _ALIGNAS(x) __declspec(align(x))
#define _LIBCPP_HAS_NO_VARIADICS
-#define _NOEXCEPT throw ()
-#define _NOEXCEPT_(x)
-#define _NOEXCEPT_OR_FALSE(x) false
+
#define _LIBCPP_BEGIN_NAMESPACE_STD namespace std {
#define _LIBCPP_END_NAMESPACE_STD }
@@ -541,14 +532,11 @@ namespace std {
#define _LIBCPP_NORETURN __attribute__((noreturn))
#define _LIBCPP_UNUSED
-#define _NOEXCEPT throw()
-#define _NOEXCEPT_(x)
-#define _NOEXCEPT_OR_FALSE(x) false
-
#define _LIBCPP_HAS_NO_TEMPLATE_ALIASES
#define _LIBCPP_HAS_NO_ADVANCED_SFINAE
#define _LIBCPP_HAS_NO_ALWAYS_INLINE_VARIADICS
#define _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS
+#define _LIBCPP_HAS_NO_NOEXCEPT
#define _LIBCPP_HAS_NO_NULLPTR
#define _LIBCPP_HAS_NO_UNICODE_CHARS
#define _LIBCPP_HAS_IS_BASE_OF
@@ -572,6 +560,14 @@ namespace std {
#endif // __clang__ || __GNUC__ || _MSC_VER || __IBMCPP__
+#ifndef _LIBCPP_HAS_NO_NOEXCEPT
+# define _NOEXCEPT noexcept
+# define _NOEXCEPT_(x) noexcept(x)
+#else
+# define _NOEXCEPT throw()
+# define _NOEXCEPT_(x)
+#endif
+
#ifdef _LIBCPP_HAS_NO_UNICODE_CHARS
typedef unsigned short char16_t;
typedef unsigned int char32_t;
diff --git a/contrib/libcxxrt/guard.cc b/contrib/libcxxrt/guard.cc
index f1c4c69..34d294c 100644
--- a/contrib/libcxxrt/guard.cc
+++ b/contrib/libcxxrt/guard.cc
@@ -101,7 +101,7 @@ typedef struct {
uint32_t init_half;
uint32_t lock_half;
} guard_t;
-_Static_assert(sizeof(guard_t) == sizeof(uint64_t), "");
+static_assert(sizeof(guard_t) == sizeof(uint64_t), "");
static const uint32_t LOCKED = 1;
static const uint32_t INITIALISED = static_cast<guard_lock_t>(1) << 24;
# endif
diff --git a/contrib/libxo/bin/Makefile.am b/contrib/libxo/bin/Makefile.am
deleted file mode 100644
index 3bda1be..0000000
--- a/contrib/libxo/bin/Makefile.am
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Copyright 2013, Juniper Networks, Inc.
-# All rights reserved.
-# This SOFTWARE is licensed under the LICENSE provided in the
-# ../Copyright file. By downloading, installing, copying, or otherwise
-# using the SOFTWARE, you agree to be bound by the terms of that
-# LICENSE.
-
-ACLOCAL_AMFLAGS = -I m4
-
-EXTRA_DIST = gt setup.sh
-
-GT_INSTALL_DIR = ${prefix}/bin
-GT_INSTALL_FILES = gt
-
-install-data-hook:
- @echo "Installing gt ... "
- @-mkdir -p ${GT_INSTALL_DIR}
- @for file in ${GT_INSTALL_FILES} ; do \
- if [ -f $$file ]; then \
- rfile=$$file ; \
- else \
- rfile=${srcdir}/$$file ; \
- fi ; \
- mdir=${GT_INSTALL_DIR}/ ; \
- mkdir -p $$mdir ; \
- cp $$rfile $$mdir/ ; \
- done
- @${CHMOD} a+x ${GT_INSTALL_DIR}/gt
diff --git a/contrib/libxo/bin/Zaliases b/contrib/libxo/bin/Zaliases
deleted file mode 100644
index 04cdec7..0000000
--- a/contrib/libxo/bin/Zaliases
+++ /dev/null
@@ -1,29 +0,0 @@
-set top_src=`pwd`
-alias Zautoreconf "(cd $top_src ; autoreconf)"
-
-set opts=' \
---with-libslax-prefix=/Users/phil/work/root \
---enable-debug \
---enable-warnings \
---enable-printflike \
---with-gettext=/opt/local \
---prefix ${HOME}/work/root \
-'
-set opts=`echo $opts`
-
-setenv CONFIGURE_OPTS "$opts"
-setenv ADB_PATH $top_src/build/libxo/.libs
-
-alias Zconfigure "(cd $top_src/build; ../configure $opts)"
-alias Zbuild "(cd $top_src/build; make \!* )"
-alias mi "(cd $top_src/build; make && make install); ."
-
-mkdir -p build
-cd build
-
-
-alias xx 'cc -I.. -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith -Werror -Waggregate-return -Wcast-align -Wcast-qual -Wchar-subscripts -Wcomment -Wformat -Wimplicit -Wmissing-declarations -Wnested-externs -Wparentheses -Wreturn-type -Wshadow -Wswitch -Wtrigraphs -Wuninitialized -Wunused -Wwrite-strings -fno-inline-functions-called-once -g -O2 -o xtest -DUNIT_TEST libxo.c'
-
-alias mm "make CFLAGS='-O0 -g'"
-
-alias mmi 'mm && mi'
diff --git a/contrib/libxo/bin/setup.sh b/contrib/libxo/bin/setup.sh
deleted file mode 100755
index f49dd48..0000000
--- a/contrib/libxo/bin/setup.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# Copyright 2013, Juniper Networks, Inc.
-# All rights reserved.
-# This SOFTWARE is licensed under the LICENSE provided in the
-# ../Copyright file. By downloading, installing, copying, or otherwise
-# using the SOFTWARE, you agree to be bound by the terms of that
-# LICENSE.
-
-
-if [ ! -f configure ]; then
- vers=`autoreconf --version | head -1`
- echo "Using" $vers
-
- mkdir -p m4
-
- autoreconf --install
-
- if [ ! -f configure ]; then
- echo "Failed to create configure script"
- exit 1
- fi
-fi
-
-echo "Creating build directory ..."
-mkdir build
-
-echo "Setup is complete. To build libslax:"
-
-echo " 1) Type 'cd build ; ../configure' to configure libslax"
-echo " 2) Type 'make' to build libslax"
-echo " 3) Type 'make install' to install libslax"
-
-exit 0
diff --git a/contrib/libxo/build/.create b/contrib/libxo/build/.create
deleted file mode 100644
index e69de29..0000000
--- a/contrib/libxo/build/.create
+++ /dev/null
diff --git a/contrib/libxo/install-sh b/contrib/libxo/install-sh
index 377bb86..0b0fdcb 100755
--- a/contrib/libxo/install-sh
+++ b/contrib/libxo/install-sh
@@ -1,7 +1,7 @@
#!/bin/sh
# install - install a program, script, or datafile
-scriptversion=2011-11-20.07; # UTC
+scriptversion=2013-12-25.23; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
@@ -41,19 +41,15 @@ scriptversion=2011-11-20.07; # UTC
# This script is compatible with the BSD install script, but was written
# from scratch.
+tab=' '
nl='
'
-IFS=" "" $nl"
+IFS=" $tab$nl"
-# set DOITPROG to echo to test this script
+# Set DOITPROG to "echo" to test this script.
-# Don't use :- since 4.3BSD and earlier shells don't like it.
doit=${DOITPROG-}
-if test -z "$doit"; then
- doit_exec=exec
-else
- doit_exec=$doit
-fi
+doit_exec=${doit:-exec}
# Put in absolute file names if you don't have them in your path;
# or use environment vars.
@@ -68,17 +64,6 @@ mvprog=${MVPROG-mv}
rmprog=${RMPROG-rm}
stripprog=${STRIPPROG-strip}
-posix_glob='?'
-initialize_posix_glob='
- test "$posix_glob" != "?" || {
- if (set -f) 2>/dev/null; then
- posix_glob=
- else
- posix_glob=:
- fi
- }
-'
-
posix_mkdir=
# Desired mode of installed file.
@@ -97,7 +82,7 @@ dir_arg=
dst_arg=
copy_on_change=false
-no_target_directory=
+is_target_a_directory=possibly
usage="\
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
@@ -137,46 +122,57 @@ while test $# -ne 0; do
-d) dir_arg=true;;
-g) chgrpcmd="$chgrpprog $2"
- shift;;
+ shift;;
--help) echo "$usage"; exit $?;;
-m) mode=$2
- case $mode in
- *' '* | *' '* | *'
-'* | *'*'* | *'?'* | *'['*)
- echo "$0: invalid mode: $mode" >&2
- exit 1;;
- esac
- shift;;
+ case $mode in
+ *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
+ echo "$0: invalid mode: $mode" >&2
+ exit 1;;
+ esac
+ shift;;
-o) chowncmd="$chownprog $2"
- shift;;
+ shift;;
-s) stripcmd=$stripprog;;
- -t) dst_arg=$2
- # Protect names problematic for 'test' and other utilities.
- case $dst_arg in
- -* | [=\(\)!]) dst_arg=./$dst_arg;;
- esac
- shift;;
+ -t)
+ is_target_a_directory=always
+ dst_arg=$2
+ # Protect names problematic for 'test' and other utilities.
+ case $dst_arg in
+ -* | [=\(\)!]) dst_arg=./$dst_arg;;
+ esac
+ shift;;
- -T) no_target_directory=true;;
+ -T) is_target_a_directory=never;;
--version) echo "$0 $scriptversion"; exit $?;;
- --) shift
- break;;
+ --) shift
+ break;;
- -*) echo "$0: invalid option: $1" >&2
- exit 1;;
+ -*) echo "$0: invalid option: $1" >&2
+ exit 1;;
*) break;;
esac
shift
done
+# We allow the use of options -d and -T together, by making -d
+# take the precedence; this is for compatibility with GNU install.
+
+if test -n "$dir_arg"; then
+ if test -n "$dst_arg"; then
+ echo "$0: target directory not allowed when installing a directory." >&2
+ exit 1
+ fi
+fi
+
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
# When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified.
@@ -208,6 +204,15 @@ if test $# -eq 0; then
fi
if test -z "$dir_arg"; then
+ if test $# -gt 1 || test "$is_target_a_directory" = always; then
+ if test ! -d "$dst_arg"; then
+ echo "$0: $dst_arg: Is not a directory." >&2
+ exit 1
+ fi
+ fi
+fi
+
+if test -z "$dir_arg"; then
do_exit='(exit $ret); exit $ret'
trap "ret=129; $do_exit" 1
trap "ret=130; $do_exit" 2
@@ -223,16 +228,16 @@ if test -z "$dir_arg"; then
*[0-7])
if test -z "$stripcmd"; then
- u_plus_rw=
+ u_plus_rw=
else
- u_plus_rw='% 200'
+ u_plus_rw='% 200'
fi
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
*)
if test -z "$stripcmd"; then
- u_plus_rw=
+ u_plus_rw=
else
- u_plus_rw=,u+rw
+ u_plus_rw=,u+rw
fi
cp_umask=$mode$u_plus_rw;;
esac
@@ -269,41 +274,15 @@ do
# If destination is a directory, append the input filename; won't work
# if double slashes aren't ignored.
if test -d "$dst"; then
- if test -n "$no_target_directory"; then
- echo "$0: $dst_arg: Is a directory" >&2
- exit 1
+ if test "$is_target_a_directory" = never; then
+ echo "$0: $dst_arg: Is a directory" >&2
+ exit 1
fi
dstdir=$dst
dst=$dstdir/`basename "$src"`
dstdir_status=0
else
- # Prefer dirname, but fall back on a substitute if dirname fails.
- dstdir=`
- (dirname "$dst") 2>/dev/null ||
- expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$dst" : 'X\(//\)[^/]' \| \
- X"$dst" : 'X\(//\)$' \| \
- X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
- echo X"$dst" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
- s//\1/
- q
- }
- /^X\(\/\/\)[^/].*/{
- s//\1/
- q
- }
- /^X\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'
- `
-
+ dstdir=`dirname "$dst"`
test -d "$dstdir"
dstdir_status=$?
fi
@@ -314,74 +293,74 @@ do
if test $dstdir_status != 0; then
case $posix_mkdir in
'')
- # Create intermediate dirs using mode 755 as modified by the umask.
- # This is like FreeBSD 'install' as of 1997-10-28.
- umask=`umask`
- case $stripcmd.$umask in
- # Optimize common cases.
- *[2367][2367]) mkdir_umask=$umask;;
- .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
-
- *[0-7])
- mkdir_umask=`expr $umask + 22 \
- - $umask % 100 % 40 + $umask % 20 \
- - $umask % 10 % 4 + $umask % 2
- `;;
- *) mkdir_umask=$umask,go-w;;
- esac
-
- # With -d, create the new directory with the user-specified mode.
- # Otherwise, rely on $mkdir_umask.
- if test -n "$dir_arg"; then
- mkdir_mode=-m$mode
- else
- mkdir_mode=
- fi
-
- posix_mkdir=false
- case $umask in
- *[123567][0-7][0-7])
- # POSIX mkdir -p sets u+wx bits regardless of umask, which
- # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
- ;;
- *)
- tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
- trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
-
- if (umask $mkdir_umask &&
- exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
- then
- if test -z "$dir_arg" || {
- # Check for POSIX incompatibilities with -m.
- # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
- # other-writable bit of parent directory when it shouldn't.
- # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
- ls_ld_tmpdir=`ls -ld "$tmpdir"`
- case $ls_ld_tmpdir in
- d????-?r-*) different_mode=700;;
- d????-?--*) different_mode=755;;
- *) false;;
- esac &&
- $mkdirprog -m$different_mode -p -- "$tmpdir" && {
- ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
- test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
- }
- }
- then posix_mkdir=:
- fi
- rmdir "$tmpdir/d" "$tmpdir"
- else
- # Remove any dirs left behind by ancient mkdir implementations.
- rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
- fi
- trap '' 0;;
- esac;;
+ # Create intermediate dirs using mode 755 as modified by the umask.
+ # This is like FreeBSD 'install' as of 1997-10-28.
+ umask=`umask`
+ case $stripcmd.$umask in
+ # Optimize common cases.
+ *[2367][2367]) mkdir_umask=$umask;;
+ .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+ *[0-7])
+ mkdir_umask=`expr $umask + 22 \
+ - $umask % 100 % 40 + $umask % 20 \
+ - $umask % 10 % 4 + $umask % 2
+ `;;
+ *) mkdir_umask=$umask,go-w;;
+ esac
+
+ # With -d, create the new directory with the user-specified mode.
+ # Otherwise, rely on $mkdir_umask.
+ if test -n "$dir_arg"; then
+ mkdir_mode=-m$mode
+ else
+ mkdir_mode=
+ fi
+
+ posix_mkdir=false
+ case $umask in
+ *[123567][0-7][0-7])
+ # POSIX mkdir -p sets u+wx bits regardless of umask, which
+ # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+ ;;
+ *)
+ tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+ if (umask $mkdir_umask &&
+ exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+ then
+ if test -z "$dir_arg" || {
+ # Check for POSIX incompatibilities with -m.
+ # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+ # other-writable bit of parent directory when it shouldn't.
+ # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+ ls_ld_tmpdir=`ls -ld "$tmpdir"`
+ case $ls_ld_tmpdir in
+ d????-?r-*) different_mode=700;;
+ d????-?--*) different_mode=755;;
+ *) false;;
+ esac &&
+ $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+ ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+ test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+ }
+ }
+ then posix_mkdir=:
+ fi
+ rmdir "$tmpdir/d" "$tmpdir"
+ else
+ # Remove any dirs left behind by ancient mkdir implementations.
+ rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+ fi
+ trap '' 0;;
+ esac;;
esac
if
$posix_mkdir && (
- umask $mkdir_umask &&
- $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+ umask $mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
)
then :
else
@@ -391,53 +370,51 @@ do
# directory the slow way, step by step, checking for races as we go.
case $dstdir in
- /*) prefix='/';;
- [-=\(\)!]*) prefix='./';;
- *) prefix='';;
+ /*) prefix='/';;
+ [-=\(\)!]*) prefix='./';;
+ *) prefix='';;
esac
- eval "$initialize_posix_glob"
-
oIFS=$IFS
IFS=/
- $posix_glob set -f
+ set -f
set fnord $dstdir
shift
- $posix_glob set +f
+ set +f
IFS=$oIFS
prefixes=
for d
do
- test X"$d" = X && continue
-
- prefix=$prefix$d
- if test -d "$prefix"; then
- prefixes=
- else
- if $posix_mkdir; then
- (umask=$mkdir_umask &&
- $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
- # Don't fail if two instances are running concurrently.
- test -d "$prefix" || exit 1
- else
- case $prefix in
- *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
- *) qprefix=$prefix;;
- esac
- prefixes="$prefixes '$qprefix'"
- fi
- fi
- prefix=$prefix/
+ test X"$d" = X && continue
+
+ prefix=$prefix$d
+ if test -d "$prefix"; then
+ prefixes=
+ else
+ if $posix_mkdir; then
+ (umask=$mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+ # Don't fail if two instances are running concurrently.
+ test -d "$prefix" || exit 1
+ else
+ case $prefix in
+ *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) qprefix=$prefix;;
+ esac
+ prefixes="$prefixes '$qprefix'"
+ fi
+ fi
+ prefix=$prefix/
done
if test -n "$prefixes"; then
- # Don't fail if two instances are running concurrently.
- (umask $mkdir_umask &&
- eval "\$doit_exec \$mkdirprog $prefixes") ||
- test -d "$dstdir" || exit 1
- obsolete_mkdir_used=true
+ # Don't fail if two instances are running concurrently.
+ (umask $mkdir_umask &&
+ eval "\$doit_exec \$mkdirprog $prefixes") ||
+ test -d "$dstdir" || exit 1
+ obsolete_mkdir_used=true
fi
fi
fi
@@ -472,15 +449,12 @@ do
# If -C, don't bother to copy if it wouldn't change the file.
if $copy_on_change &&
- old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
- new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
-
- eval "$initialize_posix_glob" &&
- $posix_glob set -f &&
+ old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
+ new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
+ set -f &&
set X $old && old=:$2:$4:$5:$6 &&
set X $new && new=:$2:$4:$5:$6 &&
- $posix_glob set +f &&
-
+ set +f &&
test "$old" = "$new" &&
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
then
@@ -493,24 +467,24 @@ do
# to itself, or perhaps because mv is so ancient that it does not
# support -f.
{
- # Now remove or move aside any old file at destination location.
- # We try this two ways since rm can't unlink itself on some
- # systems and the destination file might be busy for other
- # reasons. In this case, the final cleanup might fail but the new
- # file should still install successfully.
- {
- test ! -f "$dst" ||
- $doit $rmcmd -f "$dst" 2>/dev/null ||
- { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
- { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
- } ||
- { echo "$0: cannot unlink or rename $dst" >&2
- (exit 1); exit 1
- }
- } &&
-
- # Now rename the file to the real destination.
- $doit $mvcmd "$dsttmp" "$dst"
+ # Now remove or move aside any old file at destination location.
+ # We try this two ways since rm can't unlink itself on some
+ # systems and the destination file might be busy for other
+ # reasons. In this case, the final cleanup might fail but the new
+ # file should still install successfully.
+ {
+ test ! -f "$dst" ||
+ $doit $rmcmd -f "$dst" 2>/dev/null ||
+ { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+ { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+ } ||
+ { echo "$0: cannot unlink or rename $dst" >&2
+ (exit 1); exit 1
+ }
+ } &&
+
+ # Now rename the file to the real destination.
+ $doit $mvcmd "$dsttmp" "$dst"
}
fi || exit 1
diff --git a/contrib/libxo/libxo/xo_config.h.in b/contrib/libxo/libxo/xo_config.h.in
new file mode 100644
index 0000000..614e7fe
--- /dev/null
+++ b/contrib/libxo/libxo/xo_config.h.in
@@ -0,0 +1,246 @@
+/* libxo/xo_config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
+ systems. This function is required for `alloca.c' support on those systems.
+ */
+#undef CRAY_STACKSEG_END
+
+/* Define to 1 if using `alloca.c'. */
+#undef C_ALLOCA
+
+/* Define to 1 if you have `alloca', as a function or macro. */
+#undef HAVE_ALLOCA
+
+/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+ */
+#undef HAVE_ALLOCA_H
+
+/* Define to 1 if you have the `asprintf' function. */
+#undef HAVE_ASPRINTF
+
+/* Define to 1 if you have the `bzero' function. */
+#undef HAVE_BZERO
+
+/* Define to 1 if you have the `ctime' function. */
+#undef HAVE_CTIME
+
+/* Define to 1 if you have the <ctype.h> header file. */
+#undef HAVE_CTYPE_H
+
+/* Define to 1 if you have the declaration of `__isthreaded', and to 0 if you
+ don't. */
+#undef HAVE_DECL___ISTHREADED
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the `dlfunc' function. */
+#undef HAVE_DLFUNC
+
+/* Define to 1 if you have the <errno.h> header file. */
+#undef HAVE_ERRNO_H
+
+/* Define to 1 if you have the `fdopen' function. */
+#undef HAVE_FDOPEN
+
+/* Define to 1 if you have the `flock' function. */
+#undef HAVE_FLOCK
+
+/* Define to 1 if you have the `getpass' function. */
+#undef HAVE_GETPASS
+
+/* Define to 1 if you have the `getprogname' function. */
+#undef HAVE_GETPROGNAME
+
+/* Define to 1 if you have the `getrusage' function. */
+#undef HAVE_GETRUSAGE
+
+/* gettext(3) */
+#undef HAVE_GETTEXT
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#undef HAVE_GETTIMEOFDAY
+
+/* humanize_number(3) */
+#undef HAVE_HUMANIZE_NUMBER
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the `crypto' library (-lcrypto). */
+#undef HAVE_LIBCRYPTO
+
+/* Define to 1 if you have the `m' library (-lm). */
+#undef HAVE_LIBM
+
+/* Define to 1 if you have the <libutil.h> header file. */
+#undef HAVE_LIBUTIL_H
+
+/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
+ to 0 otherwise. */
+#undef HAVE_MALLOC
+
+/* Define to 1 if you have the `memmove' function. */
+#undef HAVE_MEMMOVE
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Support printflike */
+#undef HAVE_PRINTFLIKE
+
+/* Define to 1 if your system has a GNU libc compatible `realloc' function,
+ and to 0 otherwise. */
+#undef HAVE_REALLOC
+
+/* Define to 1 if you have the `srand' function. */
+#undef HAVE_SRAND
+
+/* Define to 1 if you have the `sranddev' function. */
+#undef HAVE_SRANDDEV
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdio_ext.h> header file. */
+#undef HAVE_STDIO_EXT_H
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#undef HAVE_STDIO_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <stdtime/tzfile.h> header file. */
+#undef HAVE_STDTIME_TZFILE_H
+
+/* Define to 1 if you have the `strchr' function. */
+#undef HAVE_STRCHR
+
+/* Define to 1 if you have the `strcspn' function. */
+#undef HAVE_STRCSPN
+
+/* Define to 1 if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strlcpy' function. */
+#undef HAVE_STRLCPY
+
+/* Define to 1 if you have the `strspn' function. */
+#undef HAVE_STRSPN
+
+/* Have struct sockaddr_un.sun_len */
+#undef HAVE_SUN_LEN
+
+/* Define to 1 if you have the `sysctlbyname' function. */
+#undef HAVE_SYSCTLBYNAME
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/sysctl.h> header file. */
+#undef HAVE_SYS_SYSCTL_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <threads.h> header file. */
+#undef HAVE_THREADS_H
+
+/* thread-local setting */
+#undef HAVE_THREAD_LOCAL
+
+/* Define to 1 if you have the <tzfile.h> header file. */
+#undef HAVE_TZFILE_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `__flbf' function. */
+#undef HAVE___FLBF
+
+/* Enable debugging */
+#undef LIBXO_DEBUG
+
+/* Enable text-only rendering */
+#undef LIBXO_TEXT_ONLY
+
+/* Version number as dotted value */
+#undef LIBXO_VERSION
+
+/* Version number extra information */
+#undef LIBXO_VERSION_EXTRA
+
+/* Version number as a number */
+#undef LIBXO_VERSION_NUMBER
+
+/* Version number as string */
+#undef LIBXO_VERSION_STRING
+
+/* Enable local wcwidth implementation */
+#undef LIBXO_WCWIDTH
+
+/* Define to the sub-directory where libtool stores uninstalled libraries. */
+#undef LT_OBJDIR
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at runtime.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown */
+#undef STACK_DIRECTION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to rpl_malloc if the replacement function should be used. */
+#undef malloc
+
+/* Define to rpl_realloc if the replacement function should be used. */
+#undef realloc
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef size_t
diff --git a/contrib/llvm/include/llvm/Support/ThreadPool.h b/contrib/llvm/include/llvm/Support/ThreadPool.h
index 745334d..665cec2 100644
--- a/contrib/llvm/include/llvm/Support/ThreadPool.h
+++ b/contrib/llvm/include/llvm/Support/ThreadPool.h
@@ -33,6 +33,7 @@
#pragma warning(pop)
#endif
+#include <atomic>
#include <condition_variable>
#include <functional>
#include <memory>
diff --git a/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp b/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp
index dd9966f..25288a7 100644
--- a/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/contrib/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -22242,7 +22242,7 @@ X86TargetLowering::EmitLoweredTLSAddr(MachineInstr *MI,
// Emit CALLSEQ_START right before the instruction.
unsigned AdjStackDown = TII.getCallFrameSetupOpcode();
MachineInstrBuilder CallseqStart =
- BuildMI(MF, DL, TII.get(AdjStackDown)).addImm(0);
+ BuildMI(MF, DL, TII.get(AdjStackDown)).addImm(0).addImm(0);
BB->insert(MachineBasicBlock::iterator(MI), CallseqStart);
// Emit CALLSEQ_END right after the instruction.
diff --git a/contrib/ofed/libcxgb4/src/cq.c b/contrib/ofed/libcxgb4/src/cq.c
index f028a22..ed5b66b 100644
--- a/contrib/ofed/libcxgb4/src/cq.c
+++ b/contrib/ofed/libcxgb4/src/cq.c
@@ -697,7 +697,7 @@ static int c4iw_poll_cq_one(struct c4iw_cq *chp, struct ibv_wc *wc)
default:
PDBG("Unexpected cqe_status 0x%x for QPID=0x%0x\n",
CQE_STATUS(&cqe), CQE_QPID(&cqe));
- ret = -EINVAL;
+ wc->status = IBV_WC_FATAL_ERR;
}
}
if (wc->status && wc->status != IBV_WC_WR_FLUSH_ERR)
diff --git a/contrib/ofed/libcxgb4/src/dev.c b/contrib/ofed/libcxgb4/src/dev.c
index 322fa0c..33c10de 100644
--- a/contrib/ofed/libcxgb4/src/dev.c
+++ b/contrib/ofed/libcxgb4/src/dev.c
@@ -54,7 +54,6 @@
struct { \
unsigned vendor; \
unsigned device; \
- unsigned chip_version; \
} hca_table[] = {
#define CH_PCI_DEVICE_ID_FUNCTION \
@@ -64,7 +63,6 @@
{ \
.vendor = PCI_VENDOR_ID_CHELSIO, \
.device = (__DeviceID), \
- .chip_version = CHELSIO_PCI_ID_CHIP_VERSION(__DeviceID), \
}
#define CH_PCI_DEVICE_ID_TABLE_DEFINE_END \
@@ -493,7 +491,8 @@ found:
}
PDBG("%s found vendor %d device %d type %d\n",
- __FUNCTION__, vendor, device, hca_table[i].chip_version);
+ __FUNCTION__, vendor, device,
+ CHELSIO_PCI_ID_CHIP_VERSION(hca_table[i].device));
dev = calloc(1, sizeof *dev);
if (!dev) {
@@ -502,7 +501,7 @@ found:
pthread_spin_init(&dev->lock, PTHREAD_PROCESS_PRIVATE);
dev->ibv_dev.ops = c4iw_dev_ops;
- dev->chip_version = hca_table[i].chip_version;
+ dev->chip_version = CHELSIO_PCI_ID_CHIP_VERSION(hca_table[i].device);
dev->abi_version = abi_version;
PDBG("%s device claimed\n", __FUNCTION__);
diff --git a/contrib/ofed/libcxgb4/src/libcxgb4.h b/contrib/ofed/libcxgb4/src/libcxgb4.h
index 7110aa3..30afcf3 100644
--- a/contrib/ofed/libcxgb4/src/libcxgb4.h
+++ b/contrib/ofed/libcxgb4/src/libcxgb4.h
@@ -69,6 +69,11 @@ static inline int dev_is_t5(struct c4iw_dev *dev)
return dev->chip_version == CHELSIO_T5;
}
+static inline int dev_is_t4(struct c4iw_dev *dev)
+{
+ return dev->chip_version == CHELSIO_T4;
+}
+
struct c4iw_context {
struct ibv_context ibv_ctx;
struct t4_dev_status_page *status_page;
diff --git a/contrib/ofed/libcxgb4/src/qp.c b/contrib/ofed/libcxgb4/src/qp.c
index 9a86291..71cc49b 100644
--- a/contrib/ofed/libcxgb4/src/qp.c
+++ b/contrib/ofed/libcxgb4/src/qp.c
@@ -362,7 +362,7 @@ int c4iw_post_send(struct ibv_qp *ibqp, struct ibv_send_wr *wr,
err = build_rdma_read(wqe, wr, &len16);
if (err)
break;
- swsqe->read_len = wr->sg_list[0].length;
+ swsqe->read_len = wr->sg_list ? wr->sg_list[0].length : 0;
if (!qhp->wq.sq.oldest_read)
qhp->wq.sq.oldest_read = swsqe;
break;
diff --git a/contrib/ofed/libcxgb4/src/t4.h b/contrib/ofed/libcxgb4/src/t4.h
index ce48244..c5120a6 100644
--- a/contrib/ofed/libcxgb4/src/t4.h
+++ b/contrib/ofed/libcxgb4/src/t4.h
@@ -328,6 +328,7 @@ struct t4_sq {
volatile u32 *udb;
size_t memsize;
u32 qid;
+ u32 bar2_qid;
void *ma_sync;
u16 in_use;
u16 size;
@@ -336,6 +337,7 @@ struct t4_sq {
u16 wq_pidx;
u16 flags;
short flush_cidx;
+ int wc_reg_available;
};
struct t4_swrqe {
@@ -348,6 +350,7 @@ struct t4_rq {
volatile u32 *udb;
size_t memsize;
u32 qid;
+ u32 bar2_qid;
u32 msn;
u32 rqt_hwaddr;
u16 rqt_size;
@@ -356,6 +359,7 @@ struct t4_rq {
u16 cidx;
u16 pidx;
u16 wq_pidx;
+ int wc_reg_available;
};
struct t4_wq {
@@ -485,14 +489,14 @@ static inline void t4_ring_sq_db(struct t4_wq *wq, u16 inc, u8 t5, u8 len16,
{
wc_wmb();
if (t5) {
- if (t5_en_wc && inc == 1) {
+ if (t5_en_wc && inc == 1 && wq->sq.wc_reg_available) {
PDBG("%s: WC wq->sq.pidx = %d; len16=%d\n",
__func__, wq->sq.pidx, len16);
copy_wqe_to_udb(wq->sq.udb + 14, wqe);
} else {
PDBG("%s: DB wq->sq.pidx = %d; len16=%d\n",
__func__, wq->sq.pidx, len16);
- writel(V_PIDX_T5(inc), wq->sq.udb);
+ writel(V_QID(wq->sq.bar2_qid) | V_PIDX_T5(inc), wq->sq.udb);
}
wc_wmb();
return;
@@ -518,14 +522,14 @@ static inline void t4_ring_rq_db(struct t4_wq *wq, u16 inc, u8 t5, u8 len16,
{
wc_wmb();
if (t5) {
- if (t5_en_wc && inc == 1) {
+ if (t5_en_wc && inc == 1 && wq->sq.wc_reg_available) {
PDBG("%s: WC wq->rq.pidx = %d; len16=%d\n",
__func__, wq->rq.pidx, len16);
copy_wqe_to_udb(wq->rq.udb + 14, wqe);
} else {
PDBG("%s: DB wq->rq.pidx = %d; len16=%d\n",
__func__, wq->rq.pidx, len16);
- writel(V_PIDX_T5(inc), wq->rq.udb);
+ writel(V_QID(wq->rq.bar2_qid) | V_PIDX_T5(inc), wq->rq.udb);
}
wc_wmb();
return;
diff --git a/contrib/ofed/libcxgb4/src/verbs.c b/contrib/ofed/libcxgb4/src/verbs.c
index 93d1e49..4d2a69d 100644
--- a/contrib/ofed/libcxgb4/src/verbs.c
+++ b/contrib/ofed/libcxgb4/src/verbs.c
@@ -213,7 +213,7 @@ struct ibv_cq *c4iw_create_cq(struct ibv_context *context, int cqe,
goto err3;
if (dev_is_t5(chp->rhp))
- chp->cq.ugts += 3;
+ chp->cq.ugts += 5;
else
chp->cq.ugts += 1;
chp->cq.sw_queue = calloc(chp->cq.size, sizeof *chp->cq.queue);
@@ -460,8 +460,14 @@ static struct ibv_qp *create_qp(struct ibv_pd *pd,
goto err3;
}
qhp->wq.sq.udb = dbva;
- if (dev_is_t5(qhp->rhp)) {
- qhp->wq.sq.udb += (128*(qhp->wq.sq.qid & qhp->wq.qid_mask))/4;
+ if (!dev_is_t4(qhp->rhp)) {
+ unsigned long segment_offset = 128 * (qhp->wq.sq.qid & qhp->wq.qid_mask);
+
+ if (segment_offset < c4iw_page_size) {
+ qhp->wq.sq.udb += segment_offset / 4;
+ qhp->wq.sq.wc_reg_available = 1;
+ } else
+ qhp->wq.sq.bar2_qid = qhp->wq.sq.qid & qhp->wq.qid_mask;
qhp->wq.sq.udb += 2;
}
@@ -479,8 +485,14 @@ static struct ibv_qp *create_qp(struct ibv_pd *pd,
if (dbva == MAP_FAILED)
goto err5;
qhp->wq.rq.udb = dbva;
- if (dev_is_t5(qhp->rhp)) {
- qhp->wq.rq.udb += (128*(qhp->wq.rq.qid & qhp->wq.qid_mask))/4;
+ if (!dev_is_t4(qhp->rhp)) {
+ unsigned long segment_offset = 128 * (qhp->wq.rq.qid & qhp->wq.qid_mask);
+
+ if (segment_offset < c4iw_page_size) {
+ qhp->wq.rq.udb += segment_offset / 4;
+ qhp->wq.rq.wc_reg_available = 1;
+ } else
+ qhp->wq.rq.bar2_qid = qhp->wq.rq.qid & qhp->wq.qid_mask;
qhp->wq.rq.udb += 2;
}
qhp->wq.rq.queue = mmap(NULL, qhp->wq.rq.memsize,
diff --git a/contrib/ofed/management/infiniband-diags/src/ibnetdiscover.c b/contrib/ofed/management/infiniband-diags/src/ibnetdiscover.c
index 5e092f7..a79aa3e 100644
--- a/contrib/ofed/management/infiniband-diags/src/ibnetdiscover.c
+++ b/contrib/ofed/management/infiniband-diags/src/ibnetdiscover.c
@@ -731,7 +731,7 @@ dump_topology(int listtype, int group)
}
fprintf(f, "\n# Spine Nodes");
- for (n = 1; n <= (SPINES_MAX_NUM+1); n++) {
+ for (n = 1; n <= (SPINES_MAX_NUM); n++) {
if (ch->spinenode[n]) {
out_switch(ch->spinenode[n], group, chname);
for (port = ch->spinenode[n]->ports; port; port = port->next, i++)
@@ -740,7 +740,7 @@ dump_topology(int listtype, int group)
}
}
fprintf(f, "\n# Line Nodes");
- for (n = 1; n <= (LINES_MAX_NUM+1); n++) {
+ for (n = 1; n <= (LINES_MAX_NUM); n++) {
if (ch->linenode[n]) {
out_switch(ch->linenode[n], group, chname);
for (port = ch->linenode[n]->ports; port; port = port->next, i++)
diff --git a/contrib/ofed/management/opensm/include/vendor/osm_vendor.h b/contrib/ofed/management/opensm/include/vendor/osm_vendor.h
index 4d0ae4c..3cde781 100644
--- a/contrib/ofed/management/opensm/include/vendor/osm_vendor.h
+++ b/contrib/ofed/management/opensm/include/vendor/osm_vendor.h
@@ -65,7 +65,7 @@
#include <vendor/osm_vendor_ibumad.h>
#elif defined( OSM_VENDOR_INTF_AL )
#include <vendor/osm_vendor_al.h>
-#elif
+#else
#error No MAD Interface selected!
#error Choose an interface in osm_config.h
#endif
diff --git a/etc/autofs/special_hosts b/etc/autofs/special_hosts
index f81449d..c498546 100644
--- a/etc/autofs/special_hosts
+++ b/etc/autofs/special_hosts
@@ -10,8 +10,8 @@ if [ $# -eq 0 ]; then
exit 0
fi
-out=`showmount -e "$1"`
+out=`showmount -E "$1"`
[ $? -eq 0 ] || exit 1
echo "$out" | awk -v host="$1" \
- 'NR > 1 { printf "%s\t%s:%s ", $1, host, $1 } END { printf "\n" }'
+ '{ printf "\"%s\"\t\"%s:%s\" ", $0, host, $0 } END { printf "\n" }'
diff --git a/etc/autofs/special_media b/etc/autofs/special_media
index 32f9478..1e2c255 100755
--- a/etc/autofs/special_media
+++ b/etc/autofs/special_media
@@ -21,6 +21,7 @@ print_available() {
_label="${_fstype_and_label#* }"
# Replace plus signs and slashes with minuses;
# leading plus signs have special meaning in maps,
+ # and multi-component keys are just not supported.
_label="$(echo ${_label} | sed 's,[+/],-,g')"
echo "${_label}"
continue
@@ -31,6 +32,26 @@ print_available() {
}
# Print a single map entry.
+print_map_entry() {
+ local _fstype _p
+
+ _fstype="$1"
+ _p="$2"
+
+ if [ "${_fstype}" = "ntfs" ]; then
+ if [ -f "/usr/local/bin/ntfs-3g" ]; then
+ echo "-mountprog=/usr/local/bin/ntfs-3g,fstype=${_fstype},nosuid :/dev/${_p}"
+ else
+ /usr/bin/logger -p info -t "special_media[$$]" \
+ "Cannot mount ${_fstype} formatted device /dev/${_p}: Install sysutils/fusefs-ntfs first"
+ exit 1
+ fi
+ else
+ echo "-fstype=${_fstype},nosuid :/dev/${_p}"
+ fi
+}
+
+# Determine map entry contents for the given key and print out the entry.
print_one() {
local _fstype _fstype_and_label _label _key _p
@@ -38,7 +59,7 @@ print_one() {
_fstype="$(fstyp "/dev/${_key}" 2> /dev/null)"
if [ $? -eq 0 ]; then
- echo "-fstype=${_fstype},nosuid :/dev/${_key}"
+ print_map_entry "${_fstype}" "${_key}"
return
fi
@@ -66,7 +87,7 @@ print_one() {
continue
fi
- echo "-fstype=${_fstype},nosuid :/dev/${_p}"
+ print_map_entry "${_fstype}" "${_p}"
done
# No matching device - don't print anything, autofs will handle it.
diff --git a/etc/mtree/BSD.usr.dist b/etc/mtree/BSD.usr.dist
index 12a4ef6..44e9c3e 100644
--- a/etc/mtree/BSD.usr.dist
+++ b/etc/mtree/BSD.usr.dist
@@ -428,6 +428,8 @@
uefisign
..
..
+ firmware
+ ..
games
fortune
..
diff --git a/etc/rc.d/msgs b/etc/rc.d/msgs
index 6031acc..8bcc26c 100755
--- a/etc/rc.d/msgs
+++ b/etc/rc.d/msgs
@@ -6,8 +6,20 @@
# PROVIDE: msgs
# REQUIRE: LOGIN
-# Make a bounds file for msgs(1) if there isn't one already
-#
-if [ -d /var/msgs -a ! -f /var/msgs/bounds -a ! -L /var/msgs/bounds ]; then
- echo 0 > /var/msgs/bounds
-fi
+. /etc/rc.subr
+
+name="msgs"
+start_cmd="msgs_start"
+stop_cmd=":"
+
+msgs_start()
+{
+ # Make a bounds file for msgs(1) if there isn't one already
+ #
+ if [ -d /var/msgs -a ! -f /var/msgs/bounds -a ! -L /var/msgs/bounds ]; then
+ echo 0 > /var/msgs/bounds
+ fi
+}
+
+load_rc_config $name
+run_rc_command "$1"
diff --git a/etc/rc.d/pf b/etc/rc.d/pf
index 8dcc40d..323e639 100755
--- a/etc/rc.d/pf
+++ b/etc/rc.d/pf
@@ -66,7 +66,11 @@ pf_resync()
pf_status()
{
- $pf_program -s info
+ if ! [ -c /dev/pf ] ; then
+ echo "pf.ko is not loaded"
+ else
+ $pf_program -s info
+ fi
}
run_rc_command "$1"
diff --git a/gnu/lib/csu/Makefile b/gnu/lib/csu/Makefile
index 92d49dc..431baac 100644
--- a/gnu/lib/csu/Makefile
+++ b/gnu/lib/csu/Makefile
@@ -22,7 +22,6 @@ CFLAGS+= -fno-inline-functions -fno-exceptions \
CFLAGS+= -I${GCCLIB}/include -I${GCCDIR}/config -I${GCCDIR} -I. \
-I${CCDIR}/cc_tools
CRTS_CFLAGS= -DCRTSTUFFS_O -DSHARED ${PICFLAG}
-MKDEP= -DCRT_BEGIN
.if ${TARGET_CPUARCH} == "arm"
CFLAGS+= -DTARGET_ARM_EABI
diff --git a/include/paths.h b/include/paths.h
index af18c26..3fa54dc 100644
--- a/include/paths.h
+++ b/include/paths.h
@@ -56,6 +56,7 @@
#define _PATH_DRUM "/dev/drum"
#define _PATH_ESDB "/usr/share/i18n/esdb"
#define _PATH_ETC "/etc"
+#define _PATH_FIRMWARE "/usr/share/firmware"
#define _PATH_FTPUSERS "/etc/ftpusers"
#define _PATH_FWMEM "/dev/fwmem"
#define _PATH_GBDE "/sbin/gbde"
diff --git a/include/stdlib.h b/include/stdlib.h
index d5506ff..8a645c0 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -125,7 +125,7 @@ size_t wcstombs(char * __restrict, const wchar_t * __restrict, size_t);
*
* (The only other extension made by C99 in thie header is _Exit().)
*/
-#if __ISO_C_VISIBLE >= 1999
+#if __ISO_C_VISIBLE >= 1999 || defined(__cplusplus)
#ifdef __LONG_LONG_SUPPORTED
/* LONGLONG */
typedef struct {
diff --git a/kerberos5/Makefile b/kerberos5/Makefile
index c93126d..e78084f 100644
--- a/kerberos5/Makefile
+++ b/kerberos5/Makefile
@@ -14,7 +14,6 @@ kerberize:
cd ${.CURDIR}/../${entry}; \
${MAKE} cleandir; \
${MAKE} obj; \
- ${MAKE} depend; \
${MAKE} all; \
${MAKE} install
.endfor
@@ -25,7 +24,6 @@ dekerberize:
cd ${.CURDIR}/../${entry}; \
${MAKE} MK_KERBEROS=no cleandir; \
${MAKE} MK_KERBEROS=no obj; \
- ${MAKE} MK_KERBEROS=no depend; \
${MAKE} MK_KERBEROS=no all; \
${MAKE} MK_KERBEROS=no install
.endfor
diff --git a/kerberos5/lib/libroken/Makefile b/kerberos5/lib/libroken/Makefile
index aade99a..8bd27e6 100644
--- a/kerberos5/lib/libroken/Makefile
+++ b/kerberos5/lib/libroken/Makefile
@@ -76,7 +76,6 @@ SRCS= base64.c \
write_pid.c \
xfree.c
-CPPFLAGS+= -DBUILD_ROKEN_LIB
CFLAGS+=-I${KRB5DIR}/lib/roken -I.
CLEANFILES= roken.h
diff --git a/lib/clang/libllvmsupport/Makefile b/lib/clang/libllvmsupport/Makefile
index c828073..cc6c688 100644
--- a/lib/clang/libllvmsupport/Makefile
+++ b/lib/clang/libllvmsupport/Makefile
@@ -113,4 +113,3 @@ SRCS+= StringPool.cpp
# Ugly hack to work around CLOCK_PROCESS_CPUTIME_ID not being properly defined
# between r239347 and r245428.
CXXFLAGS.Process.cpp= -DCLOCK_PROCESS_CPUTIME_ID=15
-CXXFLAGS+= ${CXXFLAGS.${.IMPSRC:T}}
diff --git a/lib/csu/powerpc64/Makefile b/lib/csu/powerpc64/Makefile
index 09b643e..a97ef1e 100644
--- a/lib/csu/powerpc64/Makefile
+++ b/lib/csu/powerpc64/Makefile
@@ -13,8 +13,11 @@ CFLAGS+= -I${.CURDIR}/../common \
# clang doesn't support -mlongcall, and testing shows a clang linked with a
# clang-built csu segfaults, this must currently be compiled with gcc. Once
# clang supports -mlongcall, or we get a fixed ld, this can be revisited.
+.include <bsd.compiler.mk>
+.if ${COMPILER_TYPE} != "gcc"
CC:= gcc
COMPILER_TYPE:= gcc
+.endif
FILES= ${OBJS}
FILESMODE= ${LIBMODE}
diff --git a/lib/libc/Makefile b/lib/libc/Makefile
index 17b9720..3b72a1b 100644
--- a/lib/libc/Makefile
+++ b/lib/libc/Makefile
@@ -6,6 +6,9 @@ SHLIBDIR?= /lib
.include <src.opts.mk>
+# Force building of libc_pic.a
+MK_TOOLCHAIN= yes
+
LIBC_SRCTOP?= ${.CURDIR}
# Pick the current architecture directory for libc. In general, this is
diff --git a/lib/libc/aarch64/Symbol.map b/lib/libc/aarch64/Symbol.map
index 84c38d8..0c00ec2 100644
--- a/lib/libc/aarch64/Symbol.map
+++ b/lib/libc/aarch64/Symbol.map
@@ -36,7 +36,5 @@ FBSD_1.0 {
FBSDprivate_1.0 {
_set_tp;
_end;
- curbrk;
- minbrk;
__makecontext;
};
diff --git a/lib/libc/amd64/Symbol.map b/lib/libc/amd64/Symbol.map
index bbf6113..5354d66 100644
--- a/lib/libc/amd64/Symbol.map
+++ b/lib/libc/amd64/Symbol.map
@@ -63,8 +63,6 @@ FBSDprivate_1.0 {
__signalcontext;
signalcontext;
__siglongjmp;
- .curbrk;
- .minbrk;
_brk;
_end;
__sys_vfork;
diff --git a/lib/libc/arm/Symbol.map b/lib/libc/arm/Symbol.map
index cf65492..3c5c80f 100644
--- a/lib/libc/arm/Symbol.map
+++ b/lib/libc/arm/Symbol.map
@@ -29,7 +29,6 @@ FBSD_1.0 {
ntohs;
vfork;
brk;
- cerror; /* XXX - Should this be .cerror (see sys/cerror.S)? */
sbrk;
};
@@ -60,8 +59,6 @@ FBSDprivate_1.0 {
_vfork;
_brk;
_end;
- curbrk;
- minbrk;
_sbrk;
/* softfloat */
diff --git a/lib/libc/db/mpool/Makefile.inc b/lib/libc/db/mpool/Makefile.inc
index bab7e6d..76ec0eb 100644
--- a/lib/libc/db/mpool/Makefile.inc
+++ b/lib/libc/db/mpool/Makefile.inc
@@ -3,4 +3,7 @@
.PATH: ${LIBC_SRCTOP}/db/mpool
-SRCS+= mpool.c mpool-compat.c
+SRCS+= mpool.c
+.if ${MK_SYMVER} == yes
+SRCS+= mpool-compat.c
+.endif
diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc
index 7de8ce3..a68f5c7 100644
--- a/lib/libc/gen/Makefile.inc
+++ b/lib/libc/gen/Makefile.inc
@@ -49,7 +49,6 @@ SRCS+= __getosreldate.c \
fstab.c \
ftok.c \
fts.c \
- fts-compat.c \
ftw.c \
getbootfile.c \
getbsize.c \
@@ -137,7 +136,6 @@ SRCS+= __getosreldate.c \
ualarm.c \
ulimit.c \
uname.c \
- unvis-compat.c \
usleep.c \
utime.c \
utxdb.c \
@@ -147,6 +145,10 @@ SRCS+= __getosreldate.c \
waitpid.c \
waitid.c \
wordexp.c
+.if ${MK_SYMVER} == yes
+SRCS+= fts-compat.c \
+ unvis-compat.c
+.endif
.PATH: ${LIBC_SRCTOP}/../../contrib/libc-pwcache
SRCS+= pwcache.c pwcache.h
diff --git a/lib/libc/i386/Symbol.map b/lib/libc/i386/Symbol.map
index 78be4c4..20dbc3e 100644
--- a/lib/libc/i386/Symbol.map
+++ b/lib/libc/i386/Symbol.map
@@ -64,6 +64,4 @@ FBSDprivate_1.0 {
_vfork;
_end;
_brk;
- .curbrk;
- .minbrk;
};
diff --git a/lib/libc/iconv/Makefile.inc b/lib/libc/iconv/Makefile.inc
index 5442f79..3b24737 100644
--- a/lib/libc/iconv/Makefile.inc
+++ b/lib/libc/iconv/Makefile.inc
@@ -14,7 +14,11 @@ SRCS+= citrus_bcs.c citrus_bcs_strtol.c citrus_bcs_strtoul.c \
citrus_esdb.c citrus_hash.c citrus_iconv.c citrus_lookup.c \
citrus_lookup_factory.c citrus_mapper.c citrus_memstream.c \
citrus_mmap.c citrus_module.c citrus_none.c citrus_pivot_factory.c \
- citrus_prop.c citrus_stdenc.c bsd_iconv.c iconv_compat.c
+ citrus_prop.c citrus_stdenc.c bsd_iconv.c
+.if ${MK_SYMVER} == yes
+SRCS+= iconv_compat.c
+.endif
+
SYM_MAPS+= ${LIBC_SRCTOP}/iconv/Symbol.map
.if ${MK_ICONV} == yes
diff --git a/lib/libc/locale/euc.c b/lib/libc/locale/euc.c
index c2a2e3b..2fe4046 100644
--- a/lib/libc/locale/euc.c
+++ b/lib/libc/locale/euc.c
@@ -132,7 +132,7 @@ _EUC_CN_init(struct xlocale_ctype *l, _RuneLocale *rl)
l->runes = rl;
l->__mb_cur_max = 4;
- l->__mb_sb_limit = 256;
+ l->__mb_sb_limit = 128;
return (0);
}
@@ -226,7 +226,7 @@ _EUC_JP_init(struct xlocale_ctype *l, _RuneLocale *rl)
l->runes = rl;
l->__mb_cur_max = 3;
- l->__mb_sb_limit = 196;
+ l->__mb_sb_limit = 128;
return (0);
}
@@ -273,7 +273,7 @@ _EUC_TW_init(struct xlocale_ctype *l, _RuneLocale *rl)
l->runes = rl;
l->__mb_cur_max = 4;
- l->__mb_sb_limit = 256;
+ l->__mb_sb_limit = 128;
return (0);
}
diff --git a/lib/libc/locale/mskanji.c b/lib/libc/locale/mskanji.c
index dc2d0e1..c7da4b5 100644
--- a/lib/libc/locale/mskanji.c
+++ b/lib/libc/locale/mskanji.c
@@ -83,7 +83,7 @@ _MSKanji_init(struct xlocale_ctype *l, _RuneLocale *rl)
l->__mbsinit = _MSKanji_mbsinit;
l->runes = rl;
l->__mb_cur_max = 2;
- l->__mb_sb_limit = 256;
+ l->__mb_sb_limit = 224;
return (0);
}
diff --git a/lib/libc/mips/Symbol.map b/lib/libc/mips/Symbol.map
index d7fbd0a..3868080 100644
--- a/lib/libc/mips/Symbol.map
+++ b/lib/libc/mips/Symbol.map
@@ -28,7 +28,6 @@ FBSD_1.0 {
ntohs;
vfork;
brk;
- cerror; /* XXX - Should this be .cerror (see sys/cerror.S)? */
sbrk;
};
@@ -52,8 +51,6 @@ FBSDprivate_1.0 {
__sys_vfork;
_vfork;
_end;
- __curbrk;
- minbrk;
_brk;
_sbrk;
diff --git a/lib/libc/net/Makefile.inc b/lib/libc/net/Makefile.inc
index 6f51f08..304c465 100644
--- a/lib/libc/net/Makefile.inc
+++ b/lib/libc/net/Makefile.inc
@@ -35,7 +35,6 @@ YFLAGS+=-p_nsyy
LFLAGS+=-P_nsyy
CFLAGS.nslexer.c= -DYY_BUF_SIZE=1024
-CFLAGS+= ${CFLAGS.${.IMPSRC:T}}
MAN+= byteorder.3 ethers.3 eui64.3 \
getaddrinfo.3 gai_strerror.3 gethostbyname.3 \
diff --git a/lib/libc/posix1e/Makefile.inc b/lib/libc/posix1e/Makefile.inc
index 2cc4158..85fed32 100644
--- a/lib/libc/posix1e/Makefile.inc
+++ b/lib/libc/posix1e/Makefile.inc
@@ -11,7 +11,6 @@ subr_acl_nfs4.c: ${LIBC_SRCTOP}/../../sys/kern/subr_acl_nfs4.c
SRCS+= acl_branding.c \
acl_calc_mask.c \
acl_copy.c \
- acl_compat.c \
acl_delete.c \
acl_delete_entry.c \
acl_entry.c \
@@ -36,6 +35,9 @@ SRCS+= acl_branding.c \
mac_get.c \
mac_set.c \
subr_acl_nfs4.c
+.if ${MK_SYMVER} == yes
+SRCS+= acl_compat.c
+.endif
SYM_MAPS+=${LIBC_SRCTOP}/posix1e/Symbol.map
diff --git a/lib/libc/powerpc/Symbol.map b/lib/libc/powerpc/Symbol.map
index 10b7c57..f695c81 100644
--- a/lib/libc/powerpc/Symbol.map
+++ b/lib/libc/powerpc/Symbol.map
@@ -56,7 +56,4 @@ FBSDprivate_1.0 {
__signalcontext;
__syncicache;
_end;
- .curbrk;
- .minbrk;
- .cerror;
};
diff --git a/lib/libc/powerpc64/Symbol.map b/lib/libc/powerpc64/Symbol.map
index 018a193..c429e84 100644
--- a/lib/libc/powerpc64/Symbol.map
+++ b/lib/libc/powerpc64/Symbol.map
@@ -52,7 +52,4 @@ FBSDprivate_1.0 {
__signalcontext;
__syncicache;
_end;
- _curbrk;
- _minbrk;
- _cerror;
};
diff --git a/lib/libc/riscv/Symbol.map b/lib/libc/riscv/Symbol.map
index 84c38d8..0c00ec2 100644
--- a/lib/libc/riscv/Symbol.map
+++ b/lib/libc/riscv/Symbol.map
@@ -36,7 +36,5 @@ FBSD_1.0 {
FBSDprivate_1.0 {
_set_tp;
_end;
- curbrk;
- minbrk;
__makecontext;
};
diff --git a/lib/libc/secure/Makefile.inc b/lib/libc/secure/Makefile.inc
index 6f18bde..e2e75c7 100644
--- a/lib/libc/secure/Makefile.inc
+++ b/lib/libc/secure/Makefile.inc
@@ -5,8 +5,9 @@
.PATH: ${LIBC_SRCTOP}/secure
# Sources common to both syscall interfaces:
-SRCS+= \
- stack_protector.c \
- stack_protector_compat.c
+SRCS+= stack_protector.c
+.if ${MK_SYMVER} == yes
+SRCS+= stack_protector_compat.c
+.endif
SYM_MAPS+= ${LIBC_SRCTOP}/secure/Symbol.map
diff --git a/lib/libc/sparc64/Symbol.map b/lib/libc/sparc64/Symbol.map
index 4f90486..1dc3d15 100644
--- a/lib/libc/sparc64/Symbol.map
+++ b/lib/libc/sparc64/Symbol.map
@@ -80,11 +80,8 @@ FBSDprivate_1.0 {
signalcontext;
__signalcontext;
__siglongjmp;
- .curbrk;
- .minbrk;
__sys_brk;
_brk;
- .cerror;
__sys_exect;
_exect;
_end;
diff --git a/lib/libc/stdio/open_memstream.3 b/lib/libc/stdio/open_memstream.3
index 1a0cb07..8e2c1e9 100644
--- a/lib/libc/stdio/open_memstream.3
+++ b/lib/libc/stdio/open_memstream.3
@@ -144,8 +144,8 @@ Memory for the stream or buffer could not be allocated.
.Xr fopen 3 ,
.Xr free 3 ,
.Xr fseek 3 ,
-.Xr sbuf 3 ,
-.Xr stdio 3
+.Xr stdio 3 ,
+.Xr sbuf 9
.Sh STANDARDS
The
.Fn open_memstream
diff --git a/lib/libc/stdtime/Makefile.inc b/lib/libc/stdtime/Makefile.inc
index 3220cc9..9b53ba5 100644
--- a/lib/libc/stdtime/Makefile.inc
+++ b/lib/libc/stdtime/Makefile.inc
@@ -12,7 +12,6 @@ SYM_MAPS+= ${LIBC_SRCTOP}/stdtime/Symbol.map
CFLAGS+= -I${LIBC_SRCTOP}/../../contrib/tzcode/stdtime -I${LIBC_SRCTOP}/stdtime
CFLAGS.localtime.c= -fwrapv
-CFLAGS+= ${CFLAGS.${.IMPSRC:T}}
MAN+= ctime.3 strftime.3 strptime.3 time2posix.3
MAN+= tzfile.5
diff --git a/lib/libc/sys/aio_return.2 b/lib/libc/sys/aio_return.2
index 2ef6c25..df55873 100644
--- a/lib/libc/sys/aio_return.2
+++ b/lib/libc/sys/aio_return.2
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd October 7, 2006
+.Dd March 21, 2016
.Dt AIO_RETURN 2
.Os
.Sh NAME
@@ -34,7 +34,7 @@
.Lb libc
.Sh SYNOPSIS
.In aio.h
-.Ft int
+.Ft ssize_t
.Fn aio_return "struct aiocb *iocb"
.Sh DESCRIPTION
The
diff --git a/lib/libc/sys/aio_waitcomplete.2 b/lib/libc/sys/aio_waitcomplete.2
index 885b3d7..66e7208 100644
--- a/lib/libc/sys/aio_waitcomplete.2
+++ b/lib/libc/sys/aio_waitcomplete.2
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd January 19, 2000
+.Dd March 21, 2016
.Dt AIO_WAITCOMPLETE 2
.Os
.Sh NAME
@@ -34,7 +34,7 @@
.Lb libc
.Sh SYNOPSIS
.In aio.h
-.Ft int
+.Ft ssize_t
.Fn aio_waitcomplete "struct aiocb **iocbp" "struct timespec *timeout"
.Sh DESCRIPTION
The
diff --git a/lib/libc/sys/ktrace.2 b/lib/libc/sys/ktrace.2
index 4e5d92a..b02a672 100644
--- a/lib/libc/sys/ktrace.2
+++ b/lib/libc/sys/ktrace.2
@@ -28,7 +28,7 @@
.\" @(#)ktrace.2 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd October 10, 2011
+.Dd March 31, 2016
.Dt KTRACE 2
.Os
.Sh NAME
@@ -94,6 +94,8 @@ generate much output).
.It KTRFAC_PROCCTOR Ta "Trace process construction."
.It KTRFAC_PROCDTOR Ta "Trace process destruction."
.It KTRFAC_CAPFAIL Ta "Trace capability failures."
+.It KTRFAC_FAULT Ta "Trace page faults."
+.It KTRFAC_FAULTEND Ta "Trace the end of page faults."
.It KTRFAC_INHERIT Ta "Inherit tracing to future children."
.El
.Pp
diff --git a/lib/libc/sys/modfind.2 b/lib/libc/sys/modfind.2
index 3f48579..38d09c4 100644
--- a/lib/libc/sys/modfind.2
+++ b/lib/libc/sys/modfind.2
@@ -49,7 +49,7 @@ The
.Fn modfind
system call
returns the modid of the kernel module referenced by
-.Fa file .
+.Fa modname .
Upon error,
.Fn modfind
returns -1 and sets
diff --git a/lib/libc/sys/ptrace.2 b/lib/libc/sys/ptrace.2
index 786f457..10ad660 100644
--- a/lib/libc/sys/ptrace.2
+++ b/lib/libc/sys/ptrace.2
@@ -103,7 +103,7 @@ be ignored.
If the child was created by
.Xr vfork 2
system call or
-.Xr rfork(2)
+.Xr rfork 2
call with the
.Dv RFMEM
flag specified, the debugging events are reported to the parent
diff --git a/lib/libc/tests/ssp/Makefile b/lib/libc/tests/ssp/Makefile
index 09adf97..11ccca9 100644
--- a/lib/libc/tests/ssp/Makefile
+++ b/lib/libc/tests/ssp/Makefile
@@ -36,7 +36,7 @@ PROGS+= h_memset
#
# sanitizer is not tested or supported for ARM right now. sbruno
.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
-.if ${COMPILER_TYPE} == "clang"
+.if ${COMPILER_TYPE} == "clang" && ${MK_TOOLCHAIN} == "yes"
.if ${COMPILER_VERSION} < 30500 || 30700 <= ${COMPILER_VERSION}
PROGS+= h_raw
.endif
diff --git a/lib/libclang_rt/asan_dynamic/Makefile b/lib/libclang_rt/asan_dynamic/Makefile
index 8be3903..8bd44e7 100644
--- a/lib/libclang_rt/asan_dynamic/Makefile
+++ b/lib/libclang_rt/asan_dynamic/Makefile
@@ -101,4 +101,3 @@ CXXFLAGS.ubsan_handlers_cxx.cc= -frtti
CXXFLAGS.ubsan_type_hash.cc= -frtti
CXXFLAGS.ubsan_type_hash_itanium.cc= -frtti
CXXFLAGS.ubsan_type_hash_win.cc= -frtti
-CXXFLAGS+= ${CXXFLAGS.${.IMPSRC:T}}
diff --git a/lib/libcxxrt/Makefile b/lib/libcxxrt/Makefile
index 8f3d9c5..15420a6 100644
--- a/lib/libcxxrt/Makefile
+++ b/lib/libcxxrt/Makefile
@@ -21,7 +21,10 @@ SRCS+= libelftc_dem_gnu3.c\
guard.cc
WARNS= 0
-CFLAGS+= -I${SRCDIR}
+CFLAGS+= -I${SRCDIR} -nostdinc++
+.if empty(CXXFLAGS:M-std=*)
+CXXFLAGS+= -std=c++11
+.endif
VERSION_MAP= ${.CURDIR}/Version.map
.include <bsd.lib.mk>
diff --git a/lib/libdevinfo/Makefile b/lib/libdevinfo/Makefile
index 6c0927e..4849c7a 100644
--- a/lib/libdevinfo/Makefile
+++ b/lib/libdevinfo/Makefile
@@ -6,6 +6,8 @@ SRCS= devinfo.c
INCS= devinfo.h
MAN= devinfo.3
+SHLIB_MAJOR= 6
+
WARNS?= 3
.include <bsd.lib.mk>
diff --git a/lib/libfetch/fetch.3 b/lib/libfetch/fetch.3
index 0ad9166..e04917e 100644
--- a/lib/libfetch/fetch.3
+++ b/lib/libfetch/fetch.3
@@ -1,6 +1,6 @@
.\"-
.\" Copyright (c) 1998-2013 Dag-Erling Smørgrav
-.\" Copyright (c) 2013 Michael Gmelin <freebsd@grem.de>
+.\" Copyright (c) 2013-2016 Michael Gmelin <freebsd@grem.de>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -26,7 +26,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd November 29, 2015
+.Dd March 18, 2016
.Dt FETCH 3
.Os
.Sh NAME
@@ -396,8 +396,15 @@ is currently unimplemented.
.Sh HTTPS SCHEME
Based on HTTP SCHEME.
By default the peer is verified using the CA bundle located in
-.Pa /etc/ssl/cert.pem .
-The file may contain multiple CA certificates.
+.Pa /usr/local/etc/ssl/cert.pem .
+If this file does not exist,
+.Pa /etc/ssl/cert.pem
+is used instead.
+If neither file exists, and
+.Ev SSL_CA_CERT_PATH
+has not been set,
+OpenSSL's default CA cert and path settings apply.
+The certificate bundle can contain multiple CA certificates.
A common source of a current CA bundle is
.Pa \%security/ca_root_nss .
.Pp
@@ -428,10 +435,11 @@ Client certificate based authentication is supported.
The environment variable
.Ev SSL_CLIENT_CERT_FILE
should be set to point to a file containing key and client certificate
-to be used in PEM format. In case the key is stored in a separate
-file, the environment variable
+to be used in PEM format.
+When a PEM-format key is in a separate file from the client certificate,
+the environment variable
.Ev SSL_CLIENT_KEY_FILE
-can be set to point to the key in PEM format.
+can be set to point to the key file.
In case the key uses a password, the user will be prompted on standard
input (see
.Xr PEM 3 ) .
@@ -531,7 +539,7 @@ Invalid URL
.El
.Pp
The accompanying error message includes a protocol-specific error code
-and message, e.g.\& "File is not available (404 Not Found)"
+and message, like "File is not available (404 Not Found)"
.Sh ENVIRONMENT
.Bl -tag -width ".Ev FETCH_BIND_ADDRESS"
.It Ev FETCH_BIND_ADDRESS
@@ -648,8 +656,7 @@ for compatibility.
Allow SSL version 3 when negotiating the connection (not recommended).
.It Ev SSL_CA_CERT_FILE
CA certificate bundle containing trusted CA certificates.
-Default value:
-.Pa /etc/ssl/cert.pem .
+Default value: See HTTPS SCHEME above.
.It Ev SSL_CA_CERT_PATH
Path containing trusted CA hashes.
.It Ev SSL_CLIENT_CERT_FILE
@@ -717,7 +724,6 @@ SSL_CA_CERT_FILE=/path/to/myca.pem
.Ed
.Sh SEE ALSO
.Xr fetch 1 ,
-.Xr ftpio 3 ,
.Xr ip 4
.Rs
.%A J. Postel
diff --git a/lib/libkvm/kvm_amd64.c b/lib/libkvm/kvm_amd64.c
index 1ba17f1..70789f4 100644
--- a/lib/libkvm/kvm_amd64.c
+++ b/lib/libkvm/kvm_amd64.c
@@ -227,7 +227,7 @@ _amd64_vatop(kvm_t *kd, kvaddr_t va, off_t *pa)
/*
* No next-level page table; pdpe describes one 1GB page.
*/
- a = (pde & AMD64_PG_1GB_FRAME) + (va & AMD64_PDPMASK);
+ a = (pdpe & AMD64_PG_1GB_FRAME) + (va & AMD64_PDPMASK);
s = _kvm_pa2off(kd, a, pa);
if (s == 0) {
_kvm_err(kd, kd->program,
diff --git a/lib/libstand/Makefile b/lib/libstand/Makefile
index 835b535..0ebcaf1 100644
--- a/lib/libstand/Makefile
+++ b/lib/libstand/Makefile
@@ -26,7 +26,7 @@ WARNS?= 0
CFLAGS+= -I${LIBSTAND_SRC}
# standalone components and stuff we have modified locally
-SRCS+= gzguts.h zutil.h __main.c assert.c bcd.c bswap.c environment.c getopt.c gets.c \
+SRCS+= gzguts.h zutil.h __main.c assert.c bcd.c environment.c getopt.c gets.c \
globals.c pager.c printf.c strdup.c strerror.c strtol.c strtoul.c random.c \
sbrk.c twiddle.c zalloc.c zalloc_malloc.c
diff --git a/lib/libstand/bootp.c b/lib/libstand/bootp.c
index 1af7bd5..f3bc816 100644
--- a/lib/libstand/bootp.c
+++ b/lib/libstand/bootp.c
@@ -39,6 +39,7 @@
__FBSDID("$FreeBSD$");
#include <sys/types.h>
+#include <sys/endian.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
@@ -393,6 +394,13 @@ vend_rfc1048(cp, len)
val = (const char *)cp;
strlcpy(hostname, val, sizeof(hostname));
}
+ if (tag == TAG_INTF_MTU) {
+ if ((val = getenv("dhcp.interface-mtu")) != NULL) {
+ intf_mtu = (u_int)strtoul(val, NULL, 0);
+ } else {
+ intf_mtu = be16dec(cp);
+ }
+ }
#ifdef SUPPORT_DHCP
if (tag == TAG_DHCP_MSGTYPE) {
if(*cp != expected_dhcpmsgtype)
diff --git a/lib/libstand/bootp.h b/lib/libstand/bootp.h
index ed9101f..47e5649 100644
--- a/lib/libstand/bootp.h
+++ b/lib/libstand/bootp.h
@@ -91,6 +91,7 @@ struct bootp {
#define TAG_DOMAINNAME ((unsigned char) 15)
#define TAG_SWAPSERVER ((unsigned char) 16)
#define TAG_ROOTPATH ((unsigned char) 17)
+#define TAG_INTF_MTU ((unsigned char) 26)
#ifdef SUPPORT_DHCP
#define TAG_REQ_ADDR ((unsigned char) 50)
diff --git a/lib/libstand/bswap.c b/lib/libstand/bswap.c
deleted file mode 100644
index 308edda..0000000
--- a/lib/libstand/bswap.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Written by Manuel Bouyer <bouyer@netbsd.org>.
- * Public domain.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char *rcsid = "$NetBSD: bswap32.c,v 1.1 1997/10/09 15:42:33 bouyer Exp $";
-static char *rcsid = "$NetBSD: bswap64.c,v 1.3 2009/03/16 05:59:21 cegger Exp $";
-#endif
-
-#include <sys/types.h>
-
-#undef bswap32
-#undef bswap64
-
-u_int32_t bswap32(u_int32_t x);
-u_int64_t bswap64(u_int64_t x);
-
-u_int32_t
-bswap32(u_int32_t x)
-{
- return ((x << 24) & 0xff000000 ) |
- ((x << 8) & 0x00ff0000 ) |
- ((x >> 8) & 0x0000ff00 ) |
- ((x >> 24) & 0x000000ff );
-}
-
-u_int64_t
-bswap64(u_int64_t x)
-{
-#ifdef __LP64__
- /*
- * Assume we have wide enough registers to do it without touching
- * memory.
- */
- return ( (x << 56) & 0xff00000000000000UL ) |
- ( (x << 40) & 0x00ff000000000000UL ) |
- ( (x << 24) & 0x0000ff0000000000UL ) |
- ( (x << 8) & 0x000000ff00000000UL ) |
- ( (x >> 8) & 0x00000000ff000000UL ) |
- ( (x >> 24) & 0x0000000000ff0000UL ) |
- ( (x >> 40) & 0x000000000000ff00UL ) |
- ( (x >> 56) & 0x00000000000000ffUL );
-#else
- /*
- * Split the operation in two 32bit steps.
- */
- u_int32_t tl, th;
-
- th = bswap32((u_int32_t)(x & 0x00000000ffffffffULL));
- tl = bswap32((u_int32_t)((x >> 32) & 0x00000000ffffffffULL));
- return ((u_int64_t)th << 32) | tl;
-#endif
-}
diff --git a/lib/libstand/globals.c b/lib/libstand/globals.c
index 0310823..f2c6240 100644
--- a/lib/libstand/globals.c
+++ b/lib/libstand/globals.c
@@ -30,7 +30,8 @@ struct in_addr myip; /* my ip address */
struct in_addr nameip; /* DNS server ip address */
struct in_addr rootip; /* root ip address */
struct in_addr swapip; /* swap ip address */
-struct in_addr gateip; /* swap ip address */
+struct in_addr gateip; /* gateway ip address */
n_long netmask = 0xffffff00; /* subnet or net mask */
+u_int intf_mtu; /* interface mtu from bootp/dhcp */
int errno; /* our old friend */
diff --git a/lib/libstand/net.h b/lib/libstand/net.h
index 94f2aab..ce7df49 100644
--- a/lib/libstand/net.h
+++ b/lib/libstand/net.h
@@ -83,6 +83,7 @@ extern struct in_addr swapip;
extern struct in_addr gateip;
extern struct in_addr nameip;
extern n_long netmask;
+extern u_int intf_mtu;
extern int debug; /* defined in the machdep sources */
diff --git a/lib/libstand/stand.h b/lib/libstand/stand.h
index 22ee319..a841523 100644
--- a/lib/libstand/stand.h
+++ b/lib/libstand/stand.h
@@ -335,11 +335,6 @@ static __inline quad_t qmin(quad_t a, quad_t b) { return (a < b ? a : b); }
static __inline u_long ulmax(u_long a, u_long b) { return (a > b ? a : b); }
static __inline u_long ulmin(u_long a, u_long b) { return (a < b ? a : b); }
-/* swaps (undocumented, useful?) */
-#ifdef __i386__
-extern u_int32_t bswap32(u_int32_t x);
-extern u_int64_t bswap64(u_int64_t x);
-#endif
/* null functions for device/filesystem switches (undocumented) */
extern int nodev(void);
diff --git a/lib/libsysdecode/errno.c b/lib/libsysdecode/errno.c
index 1e863bb..c21d216 100644
--- a/lib/libsysdecode/errno.c
+++ b/lib/libsysdecode/errno.c
@@ -56,7 +56,7 @@ static int bsd_to_linux_errno[ELAST + 1] = {
#endif
#if defined(__aarch64__) || defined(__amd64__)
-#include <compat/cloudabi/cloudabi_syscalldefs.h>
+#include <contrib/cloudabi/cloudabi_types_common.h>
static const int cloudabi_errno_table[] = {
[CLOUDABI_E2BIG] = E2BIG,
diff --git a/lib/libthr/Makefile b/lib/libthr/Makefile
index 7a080e0..517a30f 100644
--- a/lib/libthr/Makefile
+++ b/lib/libthr/Makefile
@@ -39,7 +39,7 @@ SYMBOL_MAPS=${.CURDIR}/pthread.map
MAN= libthr.3
-# enable extra internal consistancy checks
+# enable extra internal consistency checks
CFLAGS+=-D_PTHREADS_INVARIANTS
PRECIOUSLIB=
diff --git a/lib/libthr/thread/thr_fork.c b/lib/libthr/thread/thr_fork.c
index 7256b68..531e09c 100644
--- a/lib/libthr/thread/thr_fork.c
+++ b/lib/libthr/thread/thr_fork.c
@@ -168,6 +168,7 @@ __thr_fork(void)
if (_thr_isthreaded() != 0) {
was_threaded = 1;
_malloc_prefork();
+ __thr_pshared_atfork_pre();
_rtld_atfork_pre(rtld_locks);
} else {
was_threaded = 0;
@@ -202,8 +203,10 @@ __thr_fork(void)
_thr_signal_postfork_child();
- if (was_threaded)
+ if (was_threaded) {
_rtld_atfork_post(rtld_locks);
+ __thr_pshared_atfork_post();
+ }
_thr_setthreaded(0);
/* reinitalize library. */
@@ -236,6 +239,7 @@ __thr_fork(void)
if (was_threaded) {
_rtld_atfork_post(rtld_locks);
+ __thr_pshared_atfork_post();
_malloc_postfork();
}
diff --git a/lib/libthr/thread/thr_init.c b/lib/libthr/thread/thr_init.c
index 3c81299..c9f30ab 100644
--- a/lib/libthr/thread/thr_init.c
+++ b/lib/libthr/thread/thr_init.c
@@ -108,7 +108,6 @@ struct pthread_cond_attr _pthread_condattr_default = {
.c_clockid = CLOCK_REALTIME
};
-pid_t _thr_pid;
int _thr_is_smp = 0;
size_t _thr_guard_default;
size_t _thr_stack_default = THR_STACK_DEFAULT;
@@ -305,7 +304,7 @@ _thread_init_hack(void)
void
_libpthread_init(struct pthread *curthread)
{
- int fd, first, dlopened;
+ int first, dlopened;
/* Check if this function has already been called: */
if ((_thr_initial != NULL) && (curthread == NULL))
@@ -321,27 +320,6 @@ _libpthread_init(struct pthread *curthread)
memcpy(__thr_jtable, jmp_table, sizeof(jmp_table));
__thr_interpose_libc();
- /*
- * Check for the special case of this process running as
- * or in place of init as pid = 1:
- */
- if ((_thr_pid = getpid()) == 1) {
- /*
- * Setup a new session for this process which is
- * assumed to be running as root.
- */
- if (setsid() == -1)
- PANIC("Can't set session ID");
- if (revoke(_PATH_CONSOLE) != 0)
- PANIC("Can't revoke console");
- if ((fd = __sys_openat(AT_FDCWD, _PATH_CONSOLE, O_RDWR)) < 0)
- PANIC("Can't open console");
- if (setlogin("root") == -1)
- PANIC("Can't set login to root");
- if (_ioctl(fd, TIOCSCTTY, (char *) NULL) == -1)
- PANIC("Can't set controlling terminal");
- }
-
/* Initialize pthread private data. */
init_private();
@@ -466,7 +444,6 @@ init_private(void)
_thr_once_init();
_thr_spinlock_init();
_thr_list_init();
- __thr_pshared_init();
_thr_wake_addr_init();
_sleepq_init();
_single_thread = NULL;
@@ -477,6 +454,7 @@ init_private(void)
* e.g. after a fork().
*/
if (init_once == 0) {
+ __thr_pshared_init();
/* Find the stack top */
mib[0] = CTL_KERN;
mib[1] = KERN_USRSTACK;
diff --git a/lib/libthr/thread/thr_mutex.c b/lib/libthr/thread/thr_mutex.c
index 30a8be2..865e4cf 100644
--- a/lib/libthr/thread/thr_mutex.c
+++ b/lib/libthr/thread/thr_mutex.c
@@ -38,6 +38,7 @@
* $FreeBSD$
*/
+#include <stdbool.h>
#include "namespace.h"
#include <stdlib.h>
#include <errno.h>
@@ -124,8 +125,14 @@ mutex_assert_is_owned(struct pthread_mutex *m)
{
#if defined(_PTHREADS_INVARIANTS)
- if (__predict_false(m->m_qe.tqe_prev == NULL))
- PANIC("mutex is not on list");
+ if (__predict_false(m->m_qe.tqe_prev == NULL)) {
+ char msg[128];
+ snprintf(msg, sizeof(msg),
+ "mutex %p own %#x %#x is not on list %p %p",
+ m, m->m_lock.m_owner, m->m_owner, m->m_qe.tqe_prev,
+ m->m_qe.tqe_next);
+ PANIC(msg);
+ }
#endif
}
@@ -135,8 +142,14 @@ mutex_assert_not_owned(struct pthread_mutex *m)
#if defined(_PTHREADS_INVARIANTS)
if (__predict_false(m->m_qe.tqe_prev != NULL ||
- m->m_qe.tqe_next != NULL))
- PANIC("mutex is on list");
+ m->m_qe.tqe_next != NULL)) {
+ char msg[128];
+ snprintf(msg, sizeof(msg),
+ "mutex %p own %#x %#x is on list %p %p",
+ m, m->m_lock.m_owner, m->m_owner, m->m_qe.tqe_prev,
+ m->m_qe.tqe_next);
+ PANIC(msg);
+ }
#endif
}
@@ -252,6 +265,51 @@ set_inherited_priority(struct pthread *curthread, struct pthread_mutex *m)
m->m_lock.m_ceilings[1] = -1;
}
+static void
+shared_mutex_init(struct pthread_mutex *pmtx, const struct
+ pthread_mutex_attr *mutex_attr)
+{
+ static const struct pthread_mutex_attr foobar_mutex_attr = {
+ .m_type = PTHREAD_MUTEX_DEFAULT,
+ .m_protocol = PTHREAD_PRIO_NONE,
+ .m_ceiling = 0,
+ .m_pshared = PTHREAD_PROCESS_SHARED
+ };
+ bool done;
+
+ /*
+ * Hack to allow multiple pthread_mutex_init() calls on the
+ * same process-shared mutex. We rely on kernel allocating
+ * zeroed offpage for the mutex, i.e. the
+ * PMUTEX_INITSTAGE_ALLOC value must be zero.
+ */
+ for (done = false; !done;) {
+ switch (pmtx->m_ps) {
+ case PMUTEX_INITSTAGE_DONE:
+ atomic_thread_fence_acq();
+ done = true;
+ break;
+ case PMUTEX_INITSTAGE_ALLOC:
+ if (atomic_cmpset_int(&pmtx->m_ps,
+ PMUTEX_INITSTAGE_ALLOC, PMUTEX_INITSTAGE_BUSY)) {
+ if (mutex_attr == NULL)
+ mutex_attr = &foobar_mutex_attr;
+ mutex_init_body(pmtx, mutex_attr);
+ atomic_store_rel_int(&pmtx->m_ps,
+ PMUTEX_INITSTAGE_DONE);
+ done = true;
+ }
+ break;
+ case PMUTEX_INITSTAGE_BUSY:
+ _pthread_yield();
+ break;
+ default:
+ PANIC("corrupted offpage");
+ break;
+ }
+ }
+}
+
int
__pthread_mutex_init(pthread_mutex_t *mutex,
const pthread_mutexattr_t *mutex_attr)
@@ -273,7 +331,7 @@ __pthread_mutex_init(pthread_mutex_t *mutex,
if (pmtx == NULL)
return (EFAULT);
*mutex = THR_PSHARED_PTR;
- mutex_init_body(pmtx, *mutex_attr);
+ shared_mutex_init(pmtx, *mutex_attr);
return (0);
}
@@ -414,6 +472,7 @@ check_and_init_mutex(pthread_mutex_t *mutex, struct pthread_mutex **m)
*m = __thr_pshared_offpage(mutex, 0);
if (*m == NULL)
ret = EINVAL;
+ shared_mutex_init(*m, NULL);
} else if (__predict_false(*m <= THR_MUTEX_DESTROYED)) {
if (*m == THR_MUTEX_DESTROYED) {
ret = EINVAL;
@@ -576,6 +635,7 @@ _pthread_mutex_unlock(pthread_mutex_t *mutex)
mp = __thr_pshared_offpage(mutex, 0);
if (mp == NULL)
return (EINVAL);
+ shared_mutex_init(mp, NULL);
} else {
mp = *mutex;
}
@@ -803,6 +863,7 @@ _pthread_mutex_getprioceiling(pthread_mutex_t *mutex,
m = __thr_pshared_offpage(mutex, 0);
if (m == NULL)
return (EINVAL);
+ shared_mutex_init(m, NULL);
} else {
m = *mutex;
if (m <= THR_MUTEX_DESTROYED)
@@ -827,6 +888,7 @@ _pthread_mutex_setprioceiling(pthread_mutex_t *mutex,
m = __thr_pshared_offpage(mutex, 0);
if (m == NULL)
return (EINVAL);
+ shared_mutex_init(m, NULL);
} else {
m = *mutex;
if (m <= THR_MUTEX_DESTROYED)
@@ -930,12 +992,13 @@ __pthread_mutex_setyieldloops_np(pthread_mutex_t *mutex, int count)
int
_pthread_mutex_isowned_np(pthread_mutex_t *mutex)
{
- struct pthread_mutex *m;
+ struct pthread_mutex *m;
if (*mutex == THR_PSHARED_PTR) {
m = __thr_pshared_offpage(mutex, 0);
if (m == NULL)
return (0);
+ shared_mutex_init(m, NULL);
} else {
m = *mutex;
if (m <= THR_MUTEX_DESTROYED)
diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h
index 31f8e6c..f35d3cd 100644
--- a/lib/libthr/thread/thr_private.h
+++ b/lib/libthr/thread/thr_private.h
@@ -146,6 +146,13 @@ TAILQ_HEAD(mutex_queue, pthread_mutex);
#define MAX_DEFER_WAITERS 50
+/*
+ * Values for pthread_mutex m_ps indicator.
+ */
+#define PMUTEX_INITSTAGE_ALLOC 0
+#define PMUTEX_INITSTAGE_BUSY 1
+#define PMUTEX_INITSTAGE_DONE 2
+
struct pthread_mutex {
/*
* Lock for accesses to this structure.
@@ -156,6 +163,7 @@ struct pthread_mutex {
int m_count;
int m_spinloops;
int m_yieldloops;
+ int m_ps; /* pshared init stage */
/*
* Link for all mutexes a thread currently owns, of the same
* prio type.
@@ -717,7 +725,6 @@ extern struct pthread_cond_attr _pthread_condattr_default __hidden;
extern struct pthread_prio _thr_priorities[] __hidden;
-extern pid_t _thr_pid __hidden;
extern int _thr_is_smp __hidden;
extern size_t _thr_guard_default __hidden;
@@ -952,6 +959,8 @@ void _tcb_dtor(struct tcb *);
void __thr_pshared_init(void) __hidden;
void *__thr_pshared_offpage(void *key, int doalloc) __hidden;
void __thr_pshared_destroy(void *key) __hidden;
+void __thr_pshared_atfork_pre(void) __hidden;
+void __thr_pshared_atfork_post(void) __hidden;
__END_DECLS
diff --git a/lib/libthr/thread/thr_pshared.c b/lib/libthr/thread/thr_pshared.c
index e8ccf1c..8371478 100644
--- a/lib/libthr/thread/thr_pshared.c
+++ b/lib/libthr/thread/thr_pshared.c
@@ -252,3 +252,17 @@ __thr_pshared_destroy(void *key)
pshared_clean(key, val);
pshared_gc(curthread);
}
+
+void
+__thr_pshared_atfork_pre(void)
+{
+
+ _thr_rwl_rdlock(&pshared_lock);
+}
+
+void
+__thr_pshared_atfork_post(void)
+{
+
+ _thr_rwl_unlock(&pshared_lock);
+}
diff --git a/lib/libthr/thread/thr_pspinlock.c b/lib/libthr/thread/thr_pspinlock.c
index 9e1f96e..1c9b412 100644
--- a/lib/libthr/thread/thr_pspinlock.c
+++ b/lib/libthr/thread/thr_pspinlock.c
@@ -1,7 +1,11 @@
/*-
* Copyright (c) 2003 David Xu <davidxu@freebsd.org>
+ * Copyright (c) 2016 The FreeBSD Foundation
* All rights reserved.
*
+ * Portions of this software were developed by Konstantin Belousov
+ * 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:
@@ -46,93 +50,100 @@ int
_pthread_spin_init(pthread_spinlock_t *lock, int pshared)
{
struct pthread_spinlock *lck;
- int ret;
- if (lock == NULL || pshared != PTHREAD_PROCESS_PRIVATE)
- ret = EINVAL;
- else if ((lck = malloc(sizeof(struct pthread_spinlock))) == NULL)
- ret = ENOMEM;
- else {
- _thr_umutex_init(&lck->s_lock);
+ if (lock == NULL)
+ return (EINVAL);
+ if (pshared == PTHREAD_PROCESS_PRIVATE) {
+ lck = malloc(sizeof(struct pthread_spinlock));
+ if (lck == NULL)
+ return (ENOMEM);
*lock = lck;
- ret = 0;
+ } else if (pshared == PTHREAD_PROCESS_SHARED) {
+ lck = __thr_pshared_offpage(lock, 1);
+ if (lck == NULL)
+ return (EFAULT);
+ *lock = THR_PSHARED_PTR;
+ } else {
+ return (EINVAL);
}
-
- return (ret);
+ _thr_umutex_init(&lck->s_lock);
+ return (0);
}
int
_pthread_spin_destroy(pthread_spinlock_t *lock)
{
+ void *l;
int ret;
- if (lock == NULL || *lock == NULL)
+ if (lock == NULL || *lock == NULL) {
ret = EINVAL;
- else {
+ } else if (*lock == THR_PSHARED_PTR) {
+ l = __thr_pshared_offpage(lock, 0);
+ if (l != NULL)
+ __thr_pshared_destroy(l);
+ ret = 0;
+ } else {
free(*lock);
*lock = NULL;
ret = 0;
}
-
return (ret);
}
int
_pthread_spin_trylock(pthread_spinlock_t *lock)
{
- struct pthread *curthread = _get_curthread();
struct pthread_spinlock *lck;
- int ret;
- if (lock == NULL || (lck = *lock) == NULL)
- ret = EINVAL;
- else
- ret = THR_UMUTEX_TRYLOCK(curthread, &lck->s_lock);
- return (ret);
+ if (lock == NULL || *lock == NULL)
+ return (EINVAL);
+ lck = *lock == THR_PSHARED_PTR ? __thr_pshared_offpage(lock, 0) : *lock;
+ if (lck == NULL)
+ return (EINVAL);
+ return (THR_UMUTEX_TRYLOCK(_get_curthread(), &lck->s_lock));
}
int
_pthread_spin_lock(pthread_spinlock_t *lock)
{
- struct pthread *curthread = _get_curthread();
+ struct pthread *curthread;
struct pthread_spinlock *lck;
- int ret, count;
-
- if (lock == NULL || (lck = *lock) == NULL)
- ret = EINVAL;
- else {
- count = SPIN_COUNT;
- while ((ret = THR_UMUTEX_TRYLOCK(curthread, &lck->s_lock)) != 0) {
- while (lck->s_lock.m_owner) {
- if (!_thr_is_smp) {
+ int count;
+
+ if (lock == NULL)
+ return (EINVAL);
+ lck = *lock == THR_PSHARED_PTR ? __thr_pshared_offpage(lock, 0) : *lock;
+ if (lck == NULL)
+ return (EINVAL);
+
+ curthread = _get_curthread();
+ count = SPIN_COUNT;
+ while (THR_UMUTEX_TRYLOCK(curthread, &lck->s_lock) != 0) {
+ while (lck->s_lock.m_owner) {
+ if (!_thr_is_smp) {
+ _pthread_yield();
+ } else {
+ CPU_SPINWAIT;
+ if (--count <= 0) {
+ count = SPIN_COUNT;
_pthread_yield();
- } else {
- CPU_SPINWAIT;
-
- if (--count <= 0) {
- count = SPIN_COUNT;
- _pthread_yield();
- }
}
}
}
- ret = 0;
}
-
- return (ret);
+ return (0);
}
int
_pthread_spin_unlock(pthread_spinlock_t *lock)
{
- struct pthread *curthread = _get_curthread();
struct pthread_spinlock *lck;
- int ret;
- if (lock == NULL || (lck = *lock) == NULL)
- ret = EINVAL;
- else {
- ret = THR_UMUTEX_UNLOCK(curthread, &lck->s_lock);
- }
- return (ret);
+ if (lock == NULL)
+ return (EINVAL);
+ lck = *lock == THR_PSHARED_PTR ? __thr_pshared_offpage(lock, 0) : *lock;
+ if (lck == NULL)
+ return (EINVAL);
+ return (THR_UMUTEX_UNLOCK(_get_curthread(), &lck->s_lock));
}
diff --git a/lib/libthr/thread/thr_rtld.c b/lib/libthr/thread/thr_rtld.c
index cb20098..6c407d1 100644
--- a/lib/libthr/thread/thr_rtld.c
+++ b/lib/libthr/thread/thr_rtld.c
@@ -227,6 +227,7 @@ _thr_rtld_init(void)
_rtld_atfork_post(NULL);
_malloc_prefork();
_malloc_postfork();
+ getpid();
syscall(SYS_getpid);
/* mask signals, also force to resolve __sys_sigprocmask PLT */
diff --git a/lib/libxo/Makefile b/lib/libxo/Makefile
index 2f3f167..040db75 100644
--- a/lib/libxo/Makefile
+++ b/lib/libxo/Makefile
@@ -14,7 +14,7 @@ SHLIB_MAJOR=0
SRCS= libxo.c xo_encoder.c xo_syslog.c
-CFLAGS+=-I${LIBXOSRC}/libxo
+CFLAGS+=-I${LIBXOSRC}/libxo -I${.CURDIR}
CFLAGS+=-DXO_ENCODERDIR=\"/usr/lib/libxo/encoder\"
INCS= xo.h xo_encoder.h
diff --git a/lib/libxo/tests/Makefile b/lib/libxo/tests/Makefile
index 43f2e9d..de59ada 100644
--- a/lib/libxo/tests/Makefile
+++ b/lib/libxo/tests/Makefile
@@ -244,10 +244,15 @@ PROGS+= test_09
PROGS+= test_10
PROGS+= test_11
-CFLAGS+= -I${LIBXOSRC}/libxo
+CFLAGS+= -I${LIBXOSRC}/libxo -I${.CURDIR:H}
-LIBADD= xo
+LIBADD= xo util
SUBDIR+= encoder
+.if ${MACHINE} == "host"
+# make it easy to test without install
+TESTSDIR= ${.OBJDIR}
+.endif
+
.include <bsd.test.mk>
diff --git a/contrib/libxo/libxo/xo_config.h b/lib/libxo/xo_config.h
index 9177962..9177962 100644
--- a/contrib/libxo/libxo/xo_config.h
+++ b/lib/libxo/xo_config.h
diff --git a/lib/libz/Makefile b/lib/libz/Makefile
index 6a372bb..8f67885 100644
--- a/lib/libz/Makefile
+++ b/lib/libz/Makefile
@@ -76,4 +76,3 @@ FILESDIR= ${LIBDATADIR}/pkgconfig
## XXX: clang integrated-as doesn't grok .intel_syntax directives yet
#ACFLAGS.gvmat64.S= ${CLANG_NO_IAS}
-#ACFLAGS+= ${ACFLAGS.${.IMPSRC:T}}
diff --git a/lib/msun/arm/Makefile.inc b/lib/msun/arm/Makefile.inc
index e86997c..535d5ea 100644
--- a/lib/msun/arm/Makefile.inc
+++ b/lib/msun/arm/Makefile.inc
@@ -8,5 +8,3 @@ ARCH_SRCS = fenv-softfp.c fenv-vfp.c
.endif
CFLAGS.fenv-vfp.c= -mfpu=vfp -mfloat-abi=softfp
-CFLAGS+= ${CFLAGS.${.IMPSRC:T}}
-
diff --git a/lib/ncurses/ncurses/Makefile b/lib/ncurses/ncurses/Makefile
index cf9053c..6d720ed 100644
--- a/lib/ncurses/ncurses/Makefile
+++ b/lib/ncurses/ncurses/Makefile
@@ -332,7 +332,7 @@ codes.c: MKcodes.awk
${AWK} -f ${NCURSES_DIR}/ncurses/tinfo/MKcodes.awk bigstrings=${USE_BIG_STRINGS} ${NCURSES_DIR}/include/Caps > codes.c
lib_gen.c: MKlib_gen.sh curses.h
- LC_ALL=C sh ${NCURSES_DIR}/ncurses/base/MKlib_gen.sh "${CC} -E ${CFLAGS}" \
+ LC_ALL=C sh ${NCURSES_DIR}/ncurses/base/MKlib_gen.sh "${CC:N${CCACHE_BIN}} -E ${CFLAGS}" \
"${AWK}" generated < curses.h >$@
lib_keyname.c: keys.list MKkeyname.awk
@@ -347,14 +347,14 @@ comp_captab.c: MKcaptab.sh MKcaptab.awk Caps make_hash
${NCURSES_DIR}/include/Caps > comp_captab.c
expanded.c: MKexpanded.sh
- sh ${NCURSES_DIR}/ncurses/tty/MKexpanded.sh "${CC} -E" ${CFLAGS} >expanded.c
+ sh ${NCURSES_DIR}/ncurses/tty/MKexpanded.sh "${CC:N${CCACHE_BIN}} -E" ${CFLAGS} >expanded.c
fallback.c: MKfallback.sh
sh ${NCURSES_DIR}/ncurses/tinfo/MKfallback.sh > fallback.c
# Generated headers
nomacros.h: MKlib_gen.sh curses.h
- LC_ALL=C sh ${NCURSES_DIR}/ncurses/base/MKlib_gen.sh "${CC} -E ${CFLAGS}" \
+ LC_ALL=C sh ${NCURSES_DIR}/ncurses/base/MKlib_gen.sh "${CC:N${CCACHE_BIN}} -E ${CFLAGS}" \
"${AWK}" generated < curses.h | fgrep undef > $@
init_keytry.h: keys.list make_keys
diff --git a/libexec/dma/Makefile.inc b/libexec/dma/Makefile.inc
index 4db4bf1..ec5eba8 100644
--- a/libexec/dma/Makefile.inc
+++ b/libexec/dma/Makefile.inc
@@ -4,7 +4,7 @@
DMA_SOURCES= ${.CURDIR}/../../../contrib/dma
.PATH: ${DMA_SOURCES}
-CFLAGS= -I${DMA_SOURCES} \
+CFLAGS+= -I${DMA_SOURCES} \
-DHAVE_REALLOCF -DHAVE_STRLCPY -DHAVE_GETPROGNAME \
-DCONF_PATH='"/etc/dma"' \
-DLIBEXEC_PATH='"/usr/libexec"' -DDMA_VERSION='"v0.10"' \
diff --git a/libexec/dma/dmagent/Makefile b/libexec/dma/dmagent/Makefile
index 6f7e8b0..1875177 100644
--- a/libexec/dma/dmagent/Makefile
+++ b/libexec/dma/dmagent/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+.include <src.opts.mk>
+
LIBADD= ssl crypto
PROG= dma
@@ -22,6 +24,11 @@ YFLAGS+= -i
CLEANFILES= aliases_parse.i
FILES= mailer.conf
FILESDIR= ${SHAREDIR}/examples/dma
+.if ${MK_SENDMAIL} == no
+CONFGROUPS= CONFS MAILER
+MAILERDIR= /etc/mail
+MAILER= mailer.conf
+.endif
BINMODE= 2555
diff --git a/libexec/rtld-elf/Makefile b/libexec/rtld-elf/Makefile
index e2ebcce..6ae9130 100644
--- a/libexec/rtld-elf/Makefile
+++ b/libexec/rtld-elf/Makefile
@@ -49,6 +49,9 @@ CFLAGS+= -fvisibility=hidden
.endif
LDFLAGS+= -shared -Wl,-Bsymbolic
LIBADD= c_pic
+.if ${MK_TOOLCHAIN} == "no"
+LDFLAGS+= -L${LIBCDIR}
+.endif
.if ${MACHINE_CPUARCH} == "arm"
# Some of the required math functions (div & mod) are implemented in
diff --git a/release/doc/en_US.ISO8859-1/relnotes/article.xml b/release/doc/en_US.ISO8859-1/relnotes/article.xml
index f860409..ec98197 100644
--- a/release/doc/en_US.ISO8859-1/relnotes/article.xml
+++ b/release/doc/en_US.ISO8859-1/relnotes/article.xml
@@ -1168,6 +1168,11 @@
<para revision="288310">The &man.ctl.4; driver has been updated
to support CD-ROM and removable devices.</para>
+
+ <para contrib="sponsor" sponsor="&ix;">The &man.isp.4; driver has
+ been updated and improved: added support for 16Gbps FC cards,
+ improved target mode support, completed Multi-ID (NPIV)
+ functionality.</para>
</sect2>
<sect2 xml:id="drivers-network">
diff --git a/release/picobsd/build/Makefile.conf b/release/picobsd/build/Makefile.conf
index 7340663..1521b78 100644
--- a/release/picobsd/build/Makefile.conf
+++ b/release/picobsd/build/Makefile.conf
@@ -43,8 +43,7 @@ do_a_make_in_the_kernel_directory_anyways:
(cd ${COMPILE}; ${BINMAKE} KERNEL=kernel ${MODULES} )
${COMPILE}: ${CONF}/${CONFFILE}
- (cd ${CONF}; ${CONFIG} -d ${COMPILE} ${CONFFILE}; \
- cd ${COMPILE}; ${BINMAKE} KERNEL=kernel ${MODULES} depend )
+ cd ${CONF}; ${CONFIG} -d ${COMPILE} ${CONFFILE}
${CONF}/${CONFFILE}: ${KERNCONF}
# -mkdir -p ${CONF} # XXX not needed yet.
diff --git a/sbin/atm/atmconfig/atmconfig.8 b/sbin/atm/atmconfig/atmconfig.8
index dc765ca..3a03b0a 100644
--- a/sbin/atm/atmconfig/atmconfig.8
+++ b/sbin/atm/atmconfig/atmconfig.8
@@ -313,7 +313,6 @@ List all NATM routes.
.El
.Sh SEE ALSO
.Xr natm 4 ,
-.Xr natmip 4 ,
-.Xr atm 8
+.Xr natmip 4
.Sh AUTHORS
.An Hartmut Brandt Aq Mt harti@FreeBSD.org
diff --git a/sbin/casperd/Makefile b/sbin/casperd/Makefile
deleted file mode 100644
index 698263c..0000000
--- a/sbin/casperd/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-# $FreeBSD$
-
-PACKAGE=casper
-PROG= casperd
-
-SRCS= casperd.c zygote.c
-
-LIBADD= casper nv pjdlog util
-
-MAN= casperd.8
-
-CFLAGS+=-I${.CURDIR}
-CFLAGS+=-I${.CURDIR}/../../lib/libcapsicum
-CFLAGS+=-I${.CURDIR}/../../lib/libcasper
-CFLAGS+=-I${.CURDIR}/../../lib/libnv
-CFLAGS+=-I${.CURDIR}/../../lib/libpjdlog
-
-.include <bsd.prog.mk>
diff --git a/sbin/devd/devd.cc b/sbin/devd/devd.cc
index 203d750..b2aea19 100644
--- a/sbin/devd/devd.cc
+++ b/sbin/devd/devd.cc
@@ -648,8 +648,8 @@ config::expand_one(const char *&src, string &dst)
return;
}
- // $[^A-Za-z] -> $\1
- if (!isalpha(*src)) {
+ // $[^-A-Za-z_*] -> $\1
+ if (!isalpha(*src) && *src != '_' && *src != '-' && *src != '*') {
dst += '$';
dst += *src++;
return;
@@ -788,15 +788,30 @@ process_event(char *buffer)
{
char type;
char *sp;
+ struct timeval tv;
+ char *timestr;
sp = buffer + 1;
devdlog(LOG_INFO, "Processing event '%s'\n", buffer);
type = *buffer++;
cfg.push_var_table();
- // No match doesn't have a device, and the format is a little
+ // $* is the entire line
+ cfg.set_variable("*", buffer - 1);
+ // $_ is the entire line without the initial character
+ cfg.set_variable("_", buffer);
+
+ // Save the time this happened (as approximated by when we got
+ // around to processing it).
+ gettimeofday(&tv, NULL);
+ asprintf(&timestr, "%jd.%06ld", (uintmax_t)tv.tv_sec, tv.tv_usec);
+ cfg.set_variable("timestamp", timestr);
+ free(timestr);
+
+ // Match doesn't have a device, and the format is a little
// different, so handle it separately.
switch (type) {
case notify:
+ //! (k=v)*
sp = cfg.set_vars(sp);
break;
case nomatch:
diff --git a/sbin/devd/devd.conf.5 b/sbin/devd/devd.conf.5
index 86570fb..83c4c76 100644
--- a/sbin/devd/devd.conf.5
+++ b/sbin/devd/devd.conf.5
@@ -41,7 +41,7 @@
.\" ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
.\" SOFTWARE.
.\"
-.Dd July 11, 2015
+.Dd March 28, 2016
.Dt DEVD.CONF 5
.Os
.Sh NAME
@@ -234,10 +234,19 @@ A partial list of variables and their possible values that can be used together
with the
.Ic match
statement.
+The variables are published by the bus based on characteristics of the device
+that generated the event (for device events).
+Variables for other classes of events are dependent on those events.
.Pp
.Bl -tag -width ".Li manufacturer" -compact
.It Ic Variable
.Ic Description
+.It Li *
+The entire message from the current event
+.It Li _
+The entire message from the current event, after the initial type character
+.It Li timestamp
+The time this event was processed, in seconds since 1970 dot fraction
.It Li bus
Device name of parent bus.
.It Li cdev
diff --git a/sbin/ifconfig/ifieee80211.c b/sbin/ifconfig/ifieee80211.c
index 5ababf3..84daec9 100644
--- a/sbin/ifconfig/ifieee80211.c
+++ b/sbin/ifconfig/ifieee80211.c
@@ -2534,6 +2534,45 @@ printwmeinfo(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
}
static void
+printvhtcap(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+{
+ printf("%s", tag);
+ if (verbose) {
+ const struct ieee80211_ie_vhtcap *vhtcap =
+ (const struct ieee80211_ie_vhtcap *) ie;
+ uint32_t vhtcap_info = LE_READ_4(&vhtcap->vht_cap_info);
+
+ printf("<cap 0x%08x", vhtcap_info);
+ printf(" rx_mcs_map 0x%x",
+ LE_READ_2(&vhtcap->supp_mcs.rx_mcs_map));
+ printf(" rx_highest %d",
+ LE_READ_2(&vhtcap->supp_mcs.rx_highest) & 0x1fff);
+ printf(" tx_mcs_map 0x%x",
+ LE_READ_2(&vhtcap->supp_mcs.tx_mcs_map));
+ printf(" tx_highest %d",
+ LE_READ_2(&vhtcap->supp_mcs.tx_highest) & 0x1fff);
+
+ printf(">");
+ }
+}
+
+static void
+printvhtinfo(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+{
+ printf("%s", tag);
+ if (verbose) {
+ const struct ieee80211_ie_vht_operation *vhtinfo =
+ (const struct ieee80211_ie_vht_operation *) ie;
+
+ printf("<chw %d freq1_idx %d freq2_idx %d basic_mcs_set 0x%04x>",
+ vhtinfo->chan_width,
+ vhtinfo->center_freq_seg1_idx,
+ vhtinfo->center_freq_seg2_idx,
+ LE_READ_2(&vhtinfo->basic_mcs_set));
+ }
+}
+
+static void
printhtcap(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
{
printf("%s", tag);
@@ -2674,6 +2713,40 @@ do { \
#undef MATCHOUI
}
+static void
+printbssload(const char *tag, const uint8_t *ie, size_t ielen, int maxlen)
+{
+ printf("%s", tag);
+ if (verbose) {
+ const struct ieee80211_bss_load_ie *bssload =
+ (const struct ieee80211_bss_load_ie *) ie;
+ printf("<sta count %d, chan load %d, aac %d>",
+ LE_READ_2(&bssload->sta_count),
+ bssload->chan_load,
+ bssload->aac);
+ }
+}
+
+static void
+printapchanrep(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+{
+ printf("%s", tag);
+ if (verbose) {
+ const struct ieee80211_ap_chan_report_ie *ap =
+ (const struct ieee80211_ap_chan_report_ie *) ie;
+ const char *sep = "";
+ int i;
+
+ printf("<class %u, chan:[", ap->i_class);
+
+ for (i = 3; i < ielen; i++) {
+ printf("%s%u", sep, ie[i]);
+ sep = ",";
+ }
+ printf("]>");
+ }
+}
+
static const char *
wpa_cipher(const u_int8_t *sel)
{
@@ -3018,14 +3091,6 @@ printcountry(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
printf(">");
}
-/* unaligned little endian access */
-#define LE_READ_4(p) \
- ((u_int32_t) \
- ((((const u_int8_t *)(p))[0] ) | \
- (((const u_int8_t *)(p))[1] << 8) | \
- (((const u_int8_t *)(p))[2] << 16) | \
- (((const u_int8_t *)(p))[3] << 24)))
-
static __inline int
iswpaoui(const u_int8_t *frm)
{
@@ -3084,9 +3149,9 @@ iename(int elemid)
case IEEE80211_ELEMID_MEASREP: return " MEASREP";
case IEEE80211_ELEMID_QUIET: return " QUIET";
case IEEE80211_ELEMID_IBSSDFS: return " IBSSDFS";
- case IEEE80211_ELEMID_APCHANREP:return " APCHANREP";
case IEEE80211_ELEMID_TPC: return " TPC";
case IEEE80211_ELEMID_CCKM: return " CCKM";
+ case IEEE80211_ELEMID_VHT_PWR_ENV: return " VHTPWRENV";
}
return " ???";
}
@@ -3151,6 +3216,18 @@ printies(const u_int8_t *vp, int ielen, int maxcols)
case IEEE80211_ELEMID_MESHCONF:
printmeshconf(" MESHCONF", vp, 2+vp[1], maxcols);
break;
+ case IEEE80211_ELEMID_VHT_CAP:
+ printvhtcap(" VHTCAP", vp, 2+vp[1], maxcols);
+ break;
+ case IEEE80211_ELEMID_VHT_OPMODE:
+ printvhtinfo(" VHTOPMODE", vp, 2+vp[1], maxcols);
+ break;
+ case IEEE80211_ELEMID_BSSLOAD:
+ printbssload(" BSSLOAD", vp, 2+vp[1], maxcols);
+ break;
+ case IEEE80211_ELEMID_APCHANREP:
+ printapchanrep(" APCHANREP", vp, 2+vp[1], maxcols);
+ break;
default:
if (verbose)
printie(iename(vp[0]), vp, 2+vp[1], maxcols);
diff --git a/sbin/ifconfig/sfp.c b/sbin/ifconfig/sfp.c
index 306140a..d92ee2c 100644
--- a/sbin/ifconfig/sfp.c
+++ b/sbin/ifconfig/sfp.c
@@ -625,14 +625,17 @@ get_sfp_voltage(struct i2c_info *ii, char *buf, size_t size)
convert_sff_voltage(buf, size, xbuf);
}
-static void
+static int
get_qsfp_temp(struct i2c_info *ii, char *buf, size_t size)
{
uint8_t xbuf[2];
memset(xbuf, 0, sizeof(xbuf));
read_i2c(ii, SFF_8436_BASE, SFF_8436_TEMP, 2, xbuf);
+ if ((xbuf[0] == 0xFF && xbuf[1] == 0xFF) || (xbuf[0] == 0 && xbuf[1] == 0))
+ return (-1);
convert_sff_temp(buf, size, xbuf);
+ return (0);
}
static void
@@ -779,22 +782,9 @@ static void
print_qsfp_status(struct i2c_info *ii, int verbose)
{
char buf[80], buf2[40], buf3[40];
- uint8_t diag_type;
uint32_t bitrate;
int i;
- /* Read diagnostic monitoring type */
- read_i2c(ii, SFF_8436_BASE, SFF_8436_DIAG_TYPE, 1, (caddr_t)&diag_type);
- if (ii->error != 0)
- return;
-
- /*
- * Read monitoring data it is supplied.
- * XXX: It is not exactly clear from standard
- * how one can specify lack of measurements (passive cables case).
- */
- if (diag_type != 0)
- ii->do_diag = 1;
ii->qsfp = 1;
/* Transceiver type */
@@ -817,9 +807,13 @@ print_qsfp_status(struct i2c_info *ii, int verbose)
printf("\tnominal bitrate: %u Mbps\n", bitrate);
}
- /* Request current measurements if they are provided: */
- if (ii->do_diag != 0) {
- get_qsfp_temp(ii, buf, sizeof(buf));
+ /*
+ * The standards in this area are not clear when the
+ * additional measurements are present or not. Use a valid
+ * temperature reading as an indicator for the presence of
+ * voltage and TX/RX power measurements.
+ */
+ if (get_qsfp_temp(ii, buf, sizeof(buf)) == 0) {
get_qsfp_voltage(ii, buf2, sizeof(buf2));
printf("\tmodule temperature: %s voltage: %s\n", buf, buf2);
for (i = 1; i <= 4; i++) {
diff --git a/sbin/kldstat/Makefile.depend b/sbin/kldstat/Makefile.depend
index 0f77a15..58f9a33 100644
--- a/sbin/kldstat/Makefile.depend
+++ b/sbin/kldstat/Makefile.depend
@@ -5,6 +5,7 @@ DIRDEPS = \
gnu/lib/csu \
gnu/lib/libgcc \
include \
+ include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
diff --git a/sbin/kldstat/kldstat.8 b/sbin/kldstat/kldstat.8
index 2ea9ca4..0091826 100644
--- a/sbin/kldstat/kldstat.8
+++ b/sbin/kldstat/kldstat.8
@@ -36,10 +36,12 @@
.Op Fl h
.Op Fl q
.Op Fl v
+.Op Fl d
.Op Fl i Ar id
.Op Fl n Ar filename
.Nm
.Op Fl q
+.Op Fl d
.Op Fl m Ar modname
.Sh DESCRIPTION
The
@@ -54,6 +56,8 @@ Display the size field in a human-readable form, using unit suffixes
instead of hex values.
.It Fl v
Be more verbose.
+.It Fl d
+Show the module specific data (as int, unsigned int and unsigned long)
.It Fl i Ar id
Display the status of only the file with this ID.
.It Fl n Ar filename
diff --git a/sbin/kldstat/kldstat.c b/sbin/kldstat/kldstat.c
index c48024f..3ae7518 100644
--- a/sbin/kldstat/kldstat.c
+++ b/sbin/kldstat/kldstat.c
@@ -36,19 +36,28 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/module.h>
#include <sys/linker.h>
+#include <strings.h>
#define POINTER_WIDTH ((int)(sizeof(void *) * 2 + 2))
+static int showdata = 0;
+
static void
printmod(int modid)
{
struct module_stat stat;
+ bzero(&stat, sizeof(stat));
stat.version = sizeof(struct module_stat);
if (modstat(modid, &stat) < 0)
warn("can't stat module id %d", modid);
else
- printf("\t\t%2d %s\n", stat.id, stat.name);
+ if (showdata) {
+ printf("\t\t%2d %s (%d, %u, 0x%lx)\n", stat.id, stat.name,
+ stat.data.intval, stat.data.uintval, stat.data.ulongval);
+ } else {
+ printf("\t\t%2d %s\n", stat.id, stat.name);
+ }
}
static void
@@ -88,8 +97,8 @@ printfile(int fileid, int verbose, int humanized)
static void
usage(void)
{
- fprintf(stderr, "usage: kldstat [-h] [-q] [-v] [-i id] [-n filename]\n");
- fprintf(stderr, " kldstat [-q] [-m modname]\n");
+ fprintf(stderr, "usage: kldstata[-d] [-h] [-q] [-v] [-i id] [-n filename]\n");
+ fprintf(stderr, " kldstat [-d] [-q] [-m modname]\n");
exit(1);
}
@@ -105,8 +114,11 @@ main(int argc, char** argv)
char* modname = NULL;
char* p;
- while ((c = getopt(argc, argv, "hi:m:n:qv")) != -1)
+ while ((c = getopt(argc, argv, "dhi:m:n:qv")) != -1)
switch (c) {
+ case 'd':
+ showdata = 1;
+ break;
case 'h':
humanized = 1;
break;
@@ -152,8 +164,14 @@ main(int argc, char** argv)
if (modstat(modid, &stat) < 0)
warn("can't stat module id %d", modid);
else {
- printf("Id Refs Name\n");
- printf("%3d %4d %s\n", stat.id, stat.refs, stat.name);
+ if (showdata) {
+ printf("Id Refs Name data..(int, uint, ulong)\n");
+ printf("%3d %4d %s (%d, %u, 0x%lx)\n", stat.id, stat.refs, stat.name,
+ stat.data.intval, stat.data.uintval, stat.data.ulongval);
+ } else {
+ printf("Id Refs Name\n");
+ printf("%3d %4d %s\n", stat.id, stat.refs, stat.name);
+ }
}
return 0;
diff --git a/sbin/ping/ping.c b/sbin/ping/ping.c
index a5f8602..e7df6ca 100644
--- a/sbin/ping/ping.c
+++ b/sbin/ping/ping.c
@@ -794,7 +794,7 @@ main(int argc, char *const *argv)
#endif
if (sweepmax) {
if (sweepmin > sweepmax)
- errx(EX_USAGE, "Maximum packet size must be no less than the minimum packet size");
+ errx(EX_USAGE, "Maximum packet size must be no less than the minimum packet size");
if (datalen != DEFDATALEN)
errx(EX_USAGE, "Packet size and ping sweep are mutually exclusive");
@@ -1201,7 +1201,7 @@ pr_pack(char *buf, int cc, struct sockaddr_in *from, struct timeval *tv)
if (options & F_MASK) {
/* Just prentend this cast isn't ugly */
(void)printf(" mask=%s",
- pr_addr(*(struct in_addr *)&(icp->icmp_mask)));
+ inet_ntoa(*(struct in_addr *)&(icp->icmp_mask)));
}
if (options & F_TIME) {
(void)printf(" tso=%s", pr_ntime(icp->icmp_otime));
diff --git a/sbin/restore/tape.c b/sbin/restore/tape.c
index 7a60cf4..2f97231 100644
--- a/sbin/restore/tape.c
+++ b/sbin/restore/tape.c
@@ -340,6 +340,7 @@ getvol(long nextvol)
}
if (volno == 1)
return;
+ newvol = 0;
goto gethdr;
}
again:
diff --git a/secure/Makefile b/secure/Makefile
index 0b8ec01..c3b2c87 100644
--- a/secure/Makefile
+++ b/secure/Makefile
@@ -24,7 +24,6 @@ secure: .MAKE .PHONY
cd ${.CURDIR}/../${entry}; \
${MAKE} cleandir; \
${MAKE} obj; \
- ${MAKE} depend; \
${MAKE} all; \
${MAKE} install
.endfor
@@ -35,7 +34,6 @@ insecure: .MAKE .PHONY
cd ${.CURDIR}/../${entry}; \
${MAKE} MK_CRYPT=no cleandir; \
${MAKE} MK_CRYPT=no obj; \
- ${MAKE} MK_CRYPT=no depend; \
${MAKE} MK_CRYPT=no all; \
${MAKE} MK_CRYPT=no install
.endfor
diff --git a/share/dtrace/Makefile b/share/dtrace/Makefile
index 8daa75b..98b18fa 100644
--- a/share/dtrace/Makefile
+++ b/share/dtrace/Makefile
@@ -30,4 +30,10 @@ SCRIPTS= blocking \
SCRIPTSDIR= ${SHAREDIR}/dtrace
+DSRCS= mbuf.d
+
+FILES= ${DSRCS}
+FILESDIR= /usr/lib/dtrace
+FILESMODE= ${NOBINMODE}
+
.include <bsd.prog.mk>
diff --git a/share/dtrace/mbuf.d b/share/dtrace/mbuf.d
new file mode 100644
index 0000000..f858459
--- /dev/null
+++ b/share/dtrace/mbuf.d
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2016 George V. Neville-Neil
+ * 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$
+ *
+ * Translators and flags for the mbuf structure. FreeBSD specific code.
+ *
+ */
+
+#pragma D depends_on module kernel
+
+/*
+ * mbuf flags of global significance and layer crossing.
+ * Those of only protocol/layer specific significance are to be mapped
+ * to M_PROTO[1-12] and cleared at layer handoff boundaries.
+ * NB: Limited to the lower 24 bits.
+ */
+
+#pragma D binding "1.6.3" M_EXT
+inline int M_EXT = 0x00000001; /* has associated external storage */
+#pragma D binding "1.6.3" M_PKTHDR
+inline int M_PKTHDR = 0x00000002; /* start of record */
+#pragma D binding "1.6.3" M_EOR
+inline int M_EOR = 0x00000004; /* end of record */
+#pragma D binding "1.6.3" M_RDONLY
+inline int M_RDONLY = 0x00000008; /* associated data is marked read-only */
+#pragma D binding "1.6.3" M_BCAST
+inline int M_BCAST = 0x00000010; /* send/received as link-level broadcast */
+#pragma D binding "1.6.3" M_MCAST
+inline int M_MCAST = 0x00000020; /* send/received as link-level multicast */
+#pragma D binding "1.6.3" M_PROMISC
+inline int M_PROMISC = 0x00000040; /* packet was not for us */
+#pragma D binding "1.6.3" M_VLANTAG
+inline int M_VLANTAG = 0x00000080; /* ether_vtag is valid */
+#pragma D binding "1.6.3" M_UNUSED_8
+inline int M_UNUSED_8 = 0x00000100; /* --available-- */
+#pragma D binding "1.6.3" M_NOFREE
+inline int M_NOFREE = 0x00000200; /* do not free mbuf, embedded in cluster */
+
+#pragma D binding "1.6.3" M_PROTO1
+inline int M_PROTO1 = 0x00001000; /* protocol-specific */
+#pragma D binding "1.6.3" M_PROTO2
+inline int M_PROTO2 = 0x00002000; /* protocol-specific */
+#pragma D binding "1.6.3" M_PROTO3
+inline int M_PROTO3 = 0x00004000; /* protocol-specific */
+#pragma D binding "1.6.3" M_PROTO4
+inline int M_PROTO4 = 0x00008000; /* protocol-specific */
+#pragma D binding "1.6.3" M_PROTO5
+inline int M_PROTO5 = 0x00010000; /* protocol-specific */
+#pragma D binding "1.6.3" M_PROTO6
+inline int M_PROTO6 = 0x00020000; /* protocol-specific */
+#pragma D binding "1.6.3" M_PROTO7
+inline int M_PROTO7 = 0x00040000; /* protocol-specific */
+#pragma D binding "1.6.3" M_PROTO8
+inline int M_PROTO8 = 0x00080000; /* protocol-specific */
+#pragma D binding "1.6.3" M_PROTO9
+inline int M_PROTO9 = 0x00100000; /* protocol-specific */
+#pragma D binding "1.6.3" M_PROTO10
+inline int M_PROTO10 = 0x00200000; /* protocol-specific */
+#pragma D binding "1.6.3" M_PROTO11
+inline int M_PROTO11 = 0x00400000; /* protocol-specific */
+#pragma D binding "1.6.3" M_PROTO12
+inline int M_PROTO12 = 0x00800000; /* protocol-specific */
+
+#pragma D binding "1.6.3" mbufflags_string
+inline string mbufflags_string[uint32_t flags] =
+ flags & M_EXT ? "M_EXT" :
+ flags & M_PKTHDR ? "M_PKTHDR" :
+ flags & M_EOR ? "M_EOR" :
+ flags & M_RDONLY ? "M_RDONLY" :
+ flags & M_BCAST ? "M_BCAST" :
+ flags & M_MCAST ? "M_MCAST" :
+ flags & M_PROMISC ? "M_PROMISC" :
+ flags & M_VLANTAG ? "M_VLANTAG" :
+ flags & M_UNUSED_8 ? "M_UNUSED_8" :
+ flags & M_NOFREE ? "M_NOFREE" :
+ flags & M_PROTO1 ? "M_PROTO1" :
+ flags & M_PROTO2 ? "M_PROTO2" :
+ flags & M_PROTO3 ? "M_PROTO3" :
+ flags & M_PROTO4 ? "M_PROTO4" :
+ flags & M_PROTO5 ? "M_PROTO5" :
+ flags & M_PROTO6 ? "M_PROTO6" :
+ flags & M_PROTO7 ? "M_PROTO7" :
+ flags & M_PROTO8 ? "M_PROTO8" :
+ flags & M_PROTO9 ? "M_PROTO9" :
+ flags & M_PROTO10 ? "M_PROTO10" :
+ flags & M_PROTO11 ? "M_PROTO11" :
+ flags & M_PROTO12 ? "M_PROTO12" :
+ "none" ;
+
+/*
+ * Packet tag structure (see below for details).
+ */
+typedef struct m_tag {
+ u_int16_t m_tag_id; /* Tag ID */
+ u_int16_t m_tag_len; /* Length of data */
+ u_int32_t m_tag_cookie; /* ABI/Module ID */
+} m_tag_t;
+
+/*
+ * Record/packet header in first mbuf of chain; valid only if M_PKTHDR is set.
+ * Size ILP32: 48
+ * LP64: 56
+ * Compile-time assertions in uipc_mbuf.c test these values to ensure that
+ * they are correct.
+ */
+typedef struct pkthdr {
+/* struct ifnet *rcvif; */ /* rcv interface */
+ int32_t len; /* total packet length */
+
+ /* Layer crossing persistent information. */
+ uint32_t flowid; /* packet's 4-tuple system */
+ uint64_t csum_flags; /* checksum and offload features */
+ uint16_t fibnum; /* this packet should use this fib */
+ uint8_t cosqos; /* class/quality of service */
+ uint8_t rsstype; /* hash type */
+} pkthdr_t;
+
+/*
+ * Description of external storage mapped into mbuf; valid only if M_EXT is
+ * set.
+ * Size ILP32: 28
+ * LP64: 48
+ * Compile-time assertions in uipc_mbuf.c test these values to ensure that
+ * they are correct.
+ */
+typedef struct m_ext {
+ volatile u_int *ext_cnt; /* pointer to ref count info */
+ caddr_t ext_buf; /* start of buffer */
+ uint32_t ext_size; /* size of buffer, for ext_free */
+ uint32_t ext_type:8, /* type of external storage */
+ ext_flags:24; /* external storage mbuf flags */
+ void *ext_arg1; /* optional argument pointer */
+ void *ext_arg2; /* optional argument pointer */
+} m_ext_t;
+
+/*
+ * The core of the mbuf object along with some shortcut defines for practical
+ * purposes.
+ */
+struct mbuf {
+ uintptr_t mbuf_addr;
+ /*
+ * Header present at the beginning of every mbuf.
+ * Size ILP32: 24
+ * LP64: 32
+ * Compile-time assertions in uipc_mbuf.c test these values to ensure
+ * that they are correct.
+ */
+ caddr_t m_data; /* location of data */
+ int32_t m_len; /* amount of data in this mbuf */
+ uint32_t m_type:8, /* type of data in this mbuf */
+ m_flags:24; /* flags; see below */
+ /*
+ * A set of optional headers (packet header, external storage header)
+ * and internal data storage. Historically, these arrays were sized
+ * to MHLEN (space left after a packet header) and MLEN (space left
+ * after only a regular mbuf header); they are now variable size in
+ * order to support future work on variable-size mbufs.
+ */
+ /* union { */
+ /* struct { */
+ /* struct pkthdr m_pkthdr; */
+ /* union { */
+ /* struct m_ext m_ext; */
+ /* char m_pktdat[0]; */
+ /* }; */
+ /* }; */
+ /* char m_dat[0]; */
+ /* }; */
+ char *m_dat;
+};
+
+typedef struct mbufinfo {
+ uintptr_t mbuf_addr;
+ caddr_t m_data;
+ int32_t m_len;
+ uint8_t m_type;
+ uint32_t m_flags;
+} mbufinfo_t;
+
+translator mbufinfo_t < struct mbuf *p > {
+ mbuf_addr = (uintptr_t)p;
+ m_data = p->m_data;
+ m_len = p->m_len;
+ m_type = p->m_type & 0xff000000;
+ m_flags = p->m_type & 0x00ffffff;
+};
diff --git a/share/man/man4/amdsbwd.4 b/share/man/man4/amdsbwd.4
index 429ca44..656921a 100644
--- a/share/man/man4/amdsbwd.4
+++ b/share/man/man4/amdsbwd.4
@@ -25,12 +25,12 @@
.\"
.\" $FreeBSD$
.\"
-.Dd June 7, 2011
+.Dd March 29, 2016
.Dt AMDSBWD 4
.Os
.Sh NAME
.Nm amdsbwd
-.Nd device driver for the AMD SB600/SB7xx/SB8xx watchdog timers
+.Nd device driver for the AMD southbridge watchdog timers
.Sh SYNOPSIS
To compile this driver into the kernel,
place the following line in your
@@ -51,7 +51,7 @@ The
driver provides
.Xr watchdog 4
support for the watchdog timers present on
-AMD SB600, SB7xx and SB8xx southbridges.
+AMD SB600, SB7xx, SB8xx and SB9xx southbridges and Axx FCHs.
.Sh SEE ALSO
.Xr watchdog 4 ,
.Xr watchdog 8 ,
diff --git a/share/man/man4/capsicum.4 b/share/man/man4/capsicum.4
index afdf586..aa1568e 100644
--- a/share/man/man4/capsicum.4
+++ b/share/man/man4/capsicum.4
@@ -105,7 +105,7 @@ associated with file descriptors; described in greater detail in
.Xr write 2 ,
.Xr cap_rights_get 3 ,
.Xr casper 3 ,
-.Xr procdesc 4 ,
+.Xr procdesc 4
.Sh HISTORY
.Nm
first appeared in
diff --git a/share/man/man4/cfi.4 b/share/man/man4/cfi.4
index c5a9703..7dee561 100644
--- a/share/man/man4/cfi.4
+++ b/share/man/man4/cfi.4
@@ -50,8 +50,8 @@ In
.Pp
In DTS file:
.Cd flash@74000000 {
-.Cd " compatible =" Qo cfi-flash Qc ;
-.Cd " reg = <0x74000000 0x4000000>;"
+.Cd " compatible =" Qo cfi-flash Qc ;
+.Cd " reg = <0x74000000 0x4000000>;"
.Cd };
.Sh DESCRIPTION
The
@@ -72,7 +72,6 @@ Additional support for write-once bits to switch part of Intel StrataFlash
devices to read-only can be enabled by the
.Cd CFI_ARMEDANDDANGEROUS
kernel option.
-.El
.Sh SEE ALSO
.Xr led 4
.Sh HISTORY
diff --git a/share/man/man4/cyapa.4 b/share/man/man4/cyapa.4
index 5ecc9d7..dc312f4 100644
--- a/share/man/man4/cyapa.4
+++ b/share/man/man4/cyapa.4
@@ -175,9 +175,9 @@ file:
.Dl debug.cyapa_enable_tapclick=2
.Sh SEE ALSO
.Xr ig4 4 ,
-.Xr moused 4 ,
.Xr smbus 4 ,
-.Xr sysmouse 4
+.Xr sysmouse 4 ,
+.Xr moused 8
.Sh AUTHORS
.An -nosplit
The original
diff --git a/share/man/man4/ddb.4 b/share/man/man4/ddb.4
index 04df724..087b916 100644
--- a/share/man/man4/ddb.4
+++ b/share/man/man4/ddb.4
@@ -1132,7 +1132,7 @@ abbreviations.
.Nm
supports a basic output capture facility, which can be used to retrieve the
results of debugging commands from userspace using
-.Xr sysctl 2 .
+.Xr sysctl 3 .
.Ic capture on
enables output capture;
.Ic capture off
diff --git a/share/man/man4/filemon.4 b/share/man/man4/filemon.4
index 3287a47..0f1b60e 100644
--- a/share/man/man4/filemon.4
+++ b/share/man/man4/filemon.4
@@ -31,7 +31,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 9, 2016
+.Dd March 22, 2016
.Dt FILEMON 4
.Os
.Sh NAME
@@ -51,7 +51,7 @@ calls.
.Pp
.Nm
is not intended to be a security auditing tool.
-Many syscalls are not tracked and binaries of foreign ABI will not be fully
+Many system calls are not tracked and binaries of foreign ABI will not be fully
audited.
It is intended for auditing of processes for the purpose of determining its
dependencies in an efficient and easily parsable format.
@@ -64,6 +64,9 @@ to handle incremental builds more smartly.
System calls are denoted using the following single letters:
.Pp
.Bl -tag -width indent -compact
+.It Ql A
+.Xr openat 2 .
+The next log entry may be lacking an absolute path or be inaccurate.
.It Ql C
.Xr chdir 2
.It Ql D
@@ -82,11 +85,13 @@ System calls are denoted using the following single letters:
.Xr rename 2
.It Ql R
.Xr open 2
+or
+.Xr openat 2
for read
-.It Ql S
-.Xr stat 2
.It Ql W
.Xr open 2
+or
+.Xr openat 2
for write
.It Ql X
.Xr _exit 2
@@ -116,6 +121,10 @@ Each takes a single argument.
Write the internal tracing buffer to the supplied open file descriptor.
.It Dv FILEMON_SET_PID
Child process ID to trace.
+This should normally be done under the control of a parent in the child after
+.Xr fork 2
+but before anything else.
+See the example below.
.El
.Sh RETURN VALUES
.\" .Rv -std ioctl
@@ -138,6 +147,35 @@ The
.Nm
handle is already associated with a file descriptor.
.El
+.Pp
+The
+.Fn ioctl
+system call
+with
+.Dv FILEMON_SET_PID
+will fail if:
+.Bl -tag -width Er
+.It Bq Er ESRCH
+No process having the specified process ID exists.
+.It Bq Er EBUSY
+The process ID specified is already being traced and was not the current
+process.
+.El
+.Pp
+The
+.Fn close
+system call on the filemon file descriptor may fail with the errors from
+.Xr write 2
+if any error is encountered while writing the log.
+It may also fail if:
+.Bl -tag -width Er
+.It Bq Er EFAULT
+An invalid address was used for a traced system call argument, resulting in
+no log entry for the system call.
+.It Bq Er ENAMETOOLONG
+An argument for a traced system call was too long, resulting in
+no log entry for the system call.
+.El
.Sh FILES
.Bl -tag -width ".Pa /dev/filemon"
.It Pa /dev/filemon
@@ -199,14 +237,5 @@ A
device appeared in
.Fx 9.1 .
.Sh BUGS
-Loading
-.Nm
-may reduce system performance for the noted syscalls.
-.Pp
-Only children of the set process are logged.
-Processes can escape being traced by double forking.
-This is not seen as a problem as the intended use is build monitoring, which
-does not make sense to have daemons for.
-.Pp
Unloading the module may panic the system, thus requires using
.Ic kldunload -f .
diff --git a/share/man/man4/iscsi_initiator.4 b/share/man/man4/iscsi_initiator.4
index df03e6a..a393392 100644
--- a/share/man/man4/iscsi_initiator.4
+++ b/share/man/man4/iscsi_initiator.4
@@ -57,7 +57,7 @@ instead.
The
.Nm
implements the kernel side of the Internet SCSI (iSCSI) network
-protocol standard, the user land companion is
+protocol standard, the userland companion is
.Xr iscontrol 8 ,
and permits access to remote
.Em virtual
diff --git a/share/man/man4/lagg.4 b/share/man/man4/lagg.4
index c1a1bef..71f9221 100644
--- a/share/man/man4/lagg.4
+++ b/share/man/man4/lagg.4
@@ -166,7 +166,7 @@ Gigabit Ethernet interfaces:
192.168.1.1 netmask 255.255.255.0
.Ed
.Pp
-Create a link aggregation using ROUNDROBIN with two
+Create a link aggregation using ROUNDROBIN with two
.Xr bge 4
Gigabit Ethernet interfaces and set the limit of 500 packets
per interface:
diff --git a/share/man/man4/pcm.4 b/share/man/man4/pcm.4
index 78ab5b2..aca6edd 100644
--- a/share/man/man4/pcm.4
+++ b/share/man/man4/pcm.4
@@ -233,7 +233,7 @@ Most bridge device drivers are still missing multichannel matrixing
support, but in most cases this should be trivial to implement.
Use the
.Va dev.pcm.%d.[play|rec].vchanformat
-.Xr sysctl(8)
+.Xr sysctl 8
to adjust the number of channels used.
The current multichannel interleaved structure and arrangement was
implemented by inspecting various popular UNIX applications.
diff --git a/share/man/man4/sppp.4 b/share/man/man4/sppp.4
index 00700d8..0420bb4 100644
--- a/share/man/man4/sppp.4
+++ b/share/man/man4/sppp.4
@@ -175,7 +175,6 @@ take place.
.Sh SEE ALSO
.Xr inet 4 ,
.Xr intro 4 ,
-.Xr ppp 4 ,
.Xr ifconfig 8 ,
.Xr spppcontrol 8
.Rs
diff --git a/share/man/man4/uart.4 b/share/man/man4/uart.4
index 811deb9..cbf8e08 100644
--- a/share/man/man4/uart.4
+++ b/share/man/man4/uart.4
@@ -188,7 +188,7 @@ Capture pulses on the CTS line.
Capture pulses on the DCD line.
.El
.Pp
-The following values may be ORed with the capture mode to configure
+The following values may be ORed with the capture mode to configure
capture processing options:
.Bl -tag -compact -offset "mmmm" -width "mmmm"
.It 0x10
diff --git a/share/man/man4/udl.4 b/share/man/man4/udl.4
index 2699cc7..572fe8f 100644
--- a/share/man/man4/udl.4
+++ b/share/man/man4/udl.4
@@ -62,6 +62,7 @@ The following devices should work:
.It Sunweit USB to DVI
.It Unitek Y-2240 USB to DVI
.It VideoHome NBdock1920
+.It i-tec USB 2.0 Docking Station (USBDVIDOCK)
.El
.Sh SEE ALSO
.Xr usb 4
diff --git a/share/man/man4/vxlan.4 b/share/man/man4/vxlan.4
index 167d5b0..15b40e6 100644
--- a/share/man/man4/vxlan.4
+++ b/share/man/man4/vxlan.4
@@ -217,9 +217,9 @@ interface can be configured with
.Sh SEE ALSO
.Xr inet 4 ,
.Xr inet6 4 ,
+.Xr vlan 4 ,
.Xr ifconfig 8 ,
-.Xr sysctl 8 ,
-.Xr vlan 8
+.Xr sysctl 8
.Rs
.%A "M. Mahalingam"
.%A "et al"
diff --git a/share/man/man4/wbwd.4 b/share/man/man4/wbwd.4
index 058a407..800f627 100644
--- a/share/man/man4/wbwd.4
+++ b/share/man/man4/wbwd.4
@@ -25,12 +25,12 @@
.\"
.\" $FreeBSD$
.\"
-.Dd December 28, 2012
+.Dd March 24, 2016
.Dt WBWD 4
.Os
.Sh NAME
.Nm wbwd
-.Nd device driver for watchdog timer found on Winbond Super I/O chips
+.Nd device driver for Winbond/Nuvoton Super I/O chips watchdog timer
.Sh SYNOPSIS
To compile this driver into the kernel, place the following line in your
kernel configuration file:
@@ -50,18 +50,51 @@ The
driver provides
.Xr watchdog 4
support for the watchdog interrupt timer present on at least the following
-Winbond Super I/O chips:
-.Pp
+Super I/O chips:
.Bl -bullet -compact
.It
-83627HF/F/HG/G Rev. G
+Winbond 83627HF/F/HG/G
+.It
+Winbond 83627S
+.It
+Winbond 83697HF
+.It
+Winbond 83697UG
+.It
+Winbond 83637HF
+.It
+Winbond 83627THF
+.It
+Winbond 83687THF
+.It
+Winbond 83627EHF
+.It
+Winbond 83627DHG
.It
-83627HF/F/HG/G Rev. J
+Winbond 83627UHG
.It
-83627HF/F/HG/G Rev. UD-A
+Winbond 83667HG
.It
-83627DHG IC ver. 5
+Winbond 83627DHG-P
+.It
+Winbond 83667HG-B
+.It
+Nuvoton NCT6775
+.It
+Nuvoton NCT6776
+.It
+Nuvoton NCT6102
+.It
+Nuvoton NCT6779
+.It
+Nuvoton NCT6791
+.It
+Nuvoton NCT6792
.El
+.Pp
+Driver may be forced to attach to unknown chips by adding to
+.Pa /boot/device.hints :
+.Cd hint.wbwd.0.at="isa"
.Sh SYSCTL VARIABLES
The
.Nm
diff --git a/share/man/man5/make.conf.5 b/share/man/man5/make.conf.5
index d1fc461..24ebffb 100644
--- a/share/man/man5/make.conf.5
+++ b/share/man/man5/make.conf.5
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 24, 2016
+.Dd March 29, 2016
.Dt MAKE.CONF 5
.Os
.Sh NAME
@@ -294,12 +294,6 @@ Set this to skip running
.Xr config 8
during
.Dq Li "${MAKE} buildkernel" .
-.It Va NO_KERNELDEPEND
-.Pq Vt bool
-Set this to skip running
-.Dq Li "${MAKE} depend"
-during
-.Dq Li "${MAKE} buildkernel" .
.It Va NO_KERNELOBJ
.Pq Vt bool
Set this to skip running
diff --git a/share/man/man5/periodic.conf.5 b/share/man/man5/periodic.conf.5
index a8dee31..cb9a8b0 100644
--- a/share/man/man5/periodic.conf.5
+++ b/share/man/man5/periodic.conf.5
@@ -617,7 +617,7 @@ Weekly counterpart of
Set to
.Dq Li YES
if you want to use
-.Xr pkg_version 1
+.Xr pkg-version 8
to list installed packages which are out of date.
.It Va pkg_version
.Pq Vt str
@@ -628,7 +628,7 @@ is set to
this variable specifies the program that is used to determine the out of
date packages.
If unset, the
-.Xr pkg_version 1
+.Xr pkg-version 8
program is used.
As an example, this variable might be set to
.Dq Li portversion
@@ -642,7 +642,7 @@ This variable specifies the
file from
.Pa /usr/ports
that should be used by
-.Xr pkg_version 1 .
+.Xr pkg-version 8 .
Because the dependency tree may be substantially different between versions of
.Fx ,
there may be more than one
@@ -975,7 +975,6 @@ is shared or distributed.
.Xr msgs 1 ,
.Xr netstat 1 ,
.Xr nice 1 ,
-.Xr pkg_version 1 ,
.Xr login.conf 5 ,
.Xr rc.conf 5 ,
.Xr ac 8 ,
@@ -983,6 +982,7 @@ is shared or distributed.
.Xr dump 8 ,
.Xr newsyslog 8 ,
.Xr periodic 8 ,
+.Xr pkg-version 8 ,
.Xr sendmail 8
.Sh HISTORY
The
diff --git a/share/man/man5/src.conf.5 b/share/man/man5/src.conf.5
index b6d9bb4..68e1621 100644
--- a/share/man/man5/src.conf.5
+++ b/share/man/man5/src.conf.5
@@ -1,7 +1,7 @@
.\" DO NOT EDIT-- this file is automatically generated.
.\" from FreeBSD: head/tools/build/options/makeman 292283 2015-12-15 18:42:30Z bdrewery
.\" $FreeBSD$
-.Dd March 11, 2016
+.Dd March 30, 2016
.Dt SRC.CONF 5
.Os
.Sh NAME
@@ -248,7 +248,7 @@ Set to not build Capsicum support into system programs.
.\" from FreeBSD: head/tools/build/options/WITHOUT_CASPER 258838 2013-12-02 08:21:28Z pjd
Set to not build Casper program and related libraries.
.It Va WITH_CCACHE_BUILD
-.\" from FreeBSD: head/tools/build/options/WITH_CCACHE_BUILD 290526 2015-11-08 00:50:18Z bdrewery
+.\" from FreeBSD: head/tools/build/options/WITH_CCACHE_BUILD 297436 2016-03-30 23:53:12Z bdrewery
Set to use
.Xr ccache 1
for the build.
@@ -274,9 +274,6 @@ when using an external compiler.
The
.Sy CCACHE_CPP2
option is used for Clang but not GCC.
-ccache works best when combined with the
-.Sy WITH_FAST_DEPEND
-option.
.Pp
Sharing a cache between multiple work directories requires using a layout
similar to
@@ -517,8 +514,6 @@ When set, it also enforces the following options:
.Pp
.Bl -item -compact
.It
-.Va WITH_FAST_DEPEND
-.It
.Va WITH_INSTALL_AS_USER
.El
.Pp
@@ -618,12 +613,6 @@ An alternate bootstrap tool chain must be provided.
.\" from FreeBSD: head/tools/build/options/WITHOUT_EXAMPLES 156938 2006-03-21 09:06:24Z ru
Set to avoid installing examples to
.Pa /usr/share/examples/ .
-.It Va WITHOUT_FAST_DEPEND
-.\" from FreeBSD: head/tools/build/options/WITHOUT_FAST_DEPEND 296669 2016-03-11 17:00:42Z bdrewery
-Set to use the historical
-.Xr mkdep 1
-for the "make depend" phase of the build.
-This option is deprecated and will be removed soon.
.It Va WITHOUT_FDT
.\" from FreeBSD: head/tools/build/options/WITHOUT_FDT 221539 2011-05-06 19:10:27Z ru
Set to not build Flattened Device Tree support as part of the base system.
@@ -1459,6 +1448,8 @@ When set, it also enforces the following options:
.Va WITHOUT_GDB
.It
.Va WITHOUT_INCLUDES
+.It
+.Va WITHOUT_LLDB
.El
.It Va WITHOUT_UNBOUND
.\" from FreeBSD: head/tools/build/options/WITHOUT_UNBOUND 255597 2013-09-15 14:51:23Z des
diff --git a/share/man/man7/build.7 b/share/man/man7/build.7
index 985c165..36603da 100644
--- a/share/man/man7/build.7
+++ b/share/man/man7/build.7
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 26, 2016
+.Dd March 29, 2016
.Dt BUILD 7
.Os
.Sh NAME
@@ -122,11 +122,13 @@ test suite on installed world.
.It Cm clean
Remove any files created during the build process.
.It Cm cleandepend
-Remove the file
-.Pa ${.OBJDIR}/${DEPENDFILE}
-generated by a prior
+Remove the
+.Pa ${.OBJDIR}/${DEPENDFILE}*
+files generated by prior
+.Dq Li "make"
+and
.Dq Li "make depend"
-step.
+steps.
.It Cm cleandir
Remove the canonical object directory if it exists, or perform
actions equivalent to
@@ -146,6 +148,8 @@ and the second one will clean up
.It Cm depend
Generate a list of build dependencies in file
.Pa ${.OBJDIR}/${DEPENDFILE} .
+Per-object dependencies are generated at build time and stored in
+.Pa ${.OBJDIR}/${DEPENDFILE}.${OBJ} .
.It Cm install
Install the results of the build to the appropriate location in the
installation directory hierarchy specified in variable
@@ -412,7 +416,6 @@ If set, the build target
defaults to setting
.Va NO_KERNELCLEAN ,
.Va NO_KERNELCONFIG ,
-.Va NO_KERNELDEPEND
and
.Va NO_KERNELOBJ .
When set to a value other than
@@ -527,7 +530,7 @@ using the
.Fl D
option of
.Xr make 1 :
-.Bl -tag -width ".Va -DNO_KERNELDEPEND"
+.Bl -tag -width ".Va -DNO_KERNELCONFIG"
.It Va NO_CLEANDIR
If set, the build targets that clean parts of the object tree use the
equivalent of
@@ -565,12 +568,6 @@ If set, the build process does not run
as part of the
.Cm buildkernel
target.
-.It Va NO_KERNELDEPEND
-If set, the build process does not run
-.Dq make depend
-as part of the
-.Cm buildkernel
-target.
.It Va NO_KERNELOBJ
If set, the build process does not run
.Dq make obj
diff --git a/share/man/man7/hier.7 b/share/man/man7/hier.7
index 9def562..ed2cf87 100644
--- a/share/man/man7/hier.7
+++ b/share/man/man7/hier.7
@@ -28,7 +28,7 @@
.\" @(#)hier.7 8.1 (Berkeley) 6/5/93
.\" $FreeBSD$
.\"
-.Dd October 2, 2015
+.Dd March 15, 2016
.Dt HIER 7
.Os
.Sh NAME
@@ -545,6 +545,8 @@ Chinese translations of documents in /usr/share/doc
.Pp
.It Pa examples/
various examples for users and programmers
+.It Pa firmware/
+Firmware images loaded by userland programs
.It Pa games/
ASCII text files used by various games
.It Pa groff_font/
diff --git a/share/man/man7/ports.7 b/share/man/man7/ports.7
index a73914b..99d5665 100644
--- a/share/man/man7/ports.7
+++ b/share/man/man7/ports.7
@@ -214,12 +214,12 @@ portion never recurses
(this is perhaps a bug).
.It Cm reinstall
Use this to restore a port after using
-.Xr pkg_delete 1
+.Xr pkg-delete 8
when you should have used
.Cm deinstall .
.It Cm deinstall
Remove an installed port from the system, similar to
-.Xr pkg_delete 1 .
+.Xr pkg-delete 8 .
.It Cm deinstall-all
Remove all installed ports with the same
.Va PKGORIGIN
@@ -231,7 +231,7 @@ The package is a
.Pa .tbz
file that you can use to
install the port on other machines with
-.Xr pkg_add 1 .
+.Xr pkg-add 8 .
If the directory specified by
.Va PACKAGES
does not exist, the package will be put into the current directory.
diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile
index fa768f5..702fafa 100644
--- a/share/man/man9/Makefile
+++ b/share/man/man9/Makefile
@@ -641,7 +641,11 @@ MLINKS+=counter.9 counter_u64_alloc.9 \
counter.9 counter_exit.9 \
counter.9 counter_u64_add_protected.9 \
counter.9 counter_u64_fetch.9 \
- counter.9 counter_u64_zero.9
+ counter.9 counter_u64_zero.9 \
+ counter.9 SYSCTL_COUNTER_U64.9 \
+ counter.9 SYSCTL_ADD_COUNTER_U64.9 \
+ counter.9 SYSCTL_COUNTER_U64_ARRAY.9 \
+ counter.9 SYSCTL_ADD_COUNTER_U64_ARRAY.9
MLINKS+=cpuset.9 CPUSET_T_INITIALIZER.9 \
cpuset.9 CPUSET_FSET.9 \
cpuset.9 CPU_CLR.9 \
diff --git a/share/man/man9/SYSCALL_MODULE.9 b/share/man/man9/SYSCALL_MODULE.9
index eb90aeb..8fc92aa 100644
--- a/share/man/man9/SYSCALL_MODULE.9
+++ b/share/man/man9/SYSCALL_MODULE.9
@@ -57,6 +57,10 @@ A pointer to an
which saves the offset in
.Vt "struct sysent"
where the syscall is allocated.
+If the location pointed to by
+.Fa offset
+holds a non 0 number it will be used if possible.
+If it holds 0 then one will be assigned.
.It Fa new_sysent
is a pointer to a structure that specifies the function implementing
the syscall and the number of arguments this function needs (see
@@ -72,6 +76,17 @@ The argument passed to the callback functions of the
.Fa evh
event handler when it is called.
.El
+.Pp
+The syscall number assigned to the module can be retrieved using the
+.Xr modstat 3
+and
+.Xr modfind 3
+library functions in libc.
+The MACRO
+.Fn SYSCALL_MODULE_HELPER
+includes
+.Fn SYSCALL_MODULE
+and much of its boilerplate code.
.Sh EXAMPLES
A minimal example for a syscall module can be found in
.Pa /usr/share/examples/kld/syscall/module/syscall.c .
diff --git a/share/man/man9/counter.9 b/share/man/man9/counter.9
index f703ccf..0fcf2ad 100644
--- a/share/man/man9/counter.9
+++ b/share/man/man9/counter.9
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 7, 2014
+.Dd March 14, 2016
.Dt COUNTER 9
.Os
.Sh NAME
@@ -54,6 +54,8 @@
.In sys/sysctl.h
.Fn SYSCTL_COUNTER_U64 parent nbr name access ptr descr
.Fn SYSCTL_ADD_COUNTER_U64 ctx parent nbr name access ptr descr
+.Fn SYSCTL_COUNTER_U64_ARRAY parent nbr name access ptr len descr
+.Fn SYSCTL_ADD_COUNTER_U64_ARRAY ctx parent nbr name access ptr len descr
.Sh DESCRIPTION
.Nm
is a generic facility to create counters
@@ -150,6 +152,40 @@ argument should be a pointer to allocated
A read of the oid returns value obtained through
.Fn counter_u64_fetch .
Any write to the oid zeroes it.
+.It Fn SYSCTL_COUNTER_U64_ARRAY parent nbr name access ptr len descr
+Declare a static
+.Xr sysctl
+oid that would represent an array of
+.Nm .
+The
+.Fa ptr
+argument should be a pointer to allocated array of
+.Vt counter_u64_t's .
+The
+.Fa len
+argument should specify number of elements in the array.
+A read of the oid returns len-sized array of
+.Vt uint64_t
+values obtained through
+.Fn counter_u64_fetch .
+Any write to the oid zeroes all array elements.
+.It Fn SYSCTL_ADD_COUNTER_U64_ARRAY ctx parent nbr name access ptr len descr
+Create a
+.Xr sysctl
+oid that would represent an array of
+.Nm .
+The
+.Fa ptr
+argument should be a pointer to allocated array of
+.Vt counter_u64_t's .
+The
+.Fa len
+argument should specify number of elements in the array.
+A read of the oid returns len-sized array of
+.Vt uint64_t
+values obtained through
+.Fn counter_u64_fetch .
+Any write to the oid zeroes all array elements.
.El
.Sh IMPLEMENTATION DETAILS
On all architectures
@@ -179,6 +215,16 @@ amd64 single-instruction implementation.
On some architectures updating a counter require a
.Xr critical 9
section.
+.Sh EXAMPLES
+The following example creates a static counter array exported to
+userspace through a sysctl:
+.Bd -literal -offset indent
+#define MY_SIZE 8
+static counter_u64_t array[MY_SIZE];
+SYSCTL_COUNTER_U64_ARRAY(_debug, OID_AUTO, counter_array, CTLFLAG_RW,
+ &array[0], MY_SIZE, "Test counter array");
+.Ed
+.Pp
.Sh SEE ALSO
.Xr atomic 9 ,
.Xr critical 9 ,
diff --git a/share/man/man9/fail.9 b/share/man/man9/fail.9
index 8dbba1b..cf62365 100644
--- a/share/man/man9/fail.9
+++ b/share/man/man9/fail.9
@@ -26,25 +26,31 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 10, 2009
+.Dd March 15, 2016
.Dt FAIL 9
.Os
.Sh NAME
.Nm KFAIL_POINT_CODE ,
+.Nm KFAIL_POINT_CODE_FLAGS ,
+.Nm KFAIL_POINT_CODE_COND ,
.Nm KFAIL_POINT_RETURN ,
.Nm KFAIL_POINT_RETURN_VOID ,
.Nm KFAIL_POINT_ERROR ,
.Nm KFAIL_POINT_GOTO ,
+.Nm KFAIL_POINT_SLEEP_CALLBACKS ,
.Nm fail_point ,
.Nm DEBUG_FP
.Nd fail points
.Sh SYNOPSIS
.In sys/fail.h
.Fn KFAIL_POINT_CODE "parent" "name" "code"
+.Fn KFAIL_POINT_CODE_FLAGS "parent" "name" "flags" "code"
+.Fn KFAIL_POINT_CODE_COND "parent" "name" "cond" "flags" "code"
.Fn KFAIL_POINT_RETURN "parent" "name"
.Fn KFAIL_POINT_RETURN_VOID "parent" "name"
.Fn KFAIL_POINT_ERROR "parent" "name" "error_var"
.Fn KFAIL_POINT_GOTO "parent" "name" "error_var" "label"
+.Fn KFAIL_POINT_SLEEP_CALLBACKS "parent" "name" "pre_func" "pre_arg" "post_func" "post_arg" "code"
.Sh DESCRIPTION
Fail points are used to add code points where errors may be injected
in a user controlled fashion.
@@ -77,6 +83,42 @@ argument, the evaluation of
is derived from the
.Fn return
value set in the sysctl MIB.
+.Pp
+Additionally,
+.Fn KFAIL_POINT_CODE_FLAGS
+provides a
+.Fa flags
+argument which controls the fail point's behaviour.
+This can be used to e.g., mark the fail point's context as non-sleepable,
+which causes the
+.Sy sleep
+action to be coerced to a busy wait.
+The supported flags are:
+.Bl -ohang -offset indent
+.It FAIL_POINT_USE_TIMEOUT_PATH
+Rather than sleeping on a
+.Fn sleep
+call, just fire the post-sleep function after a timeout fires.
+.It FAIL_POINT_NONSLEEPABLE
+Mark the fail point as being in a non-sleepable context, which coerces
+.Fn sleep
+calls to
+.Fn delay
+calls.
+.El
+.Pp
+Likewise,
+.Fn KFAIL_POINT_CODE_COND
+supplies a
+.Fa cond
+argument, which allows you to set the condition under which the fail point's
+code may fire.
+This is equivalent to:
+.Bd -literal
+ if (cond)
+ KFAIL_POINT_CODE_FLAGS(...);
+
+.Ed
See
.Sx SYSCTL VARIABLES
below.
@@ -107,26 +149,12 @@ Many base kernel MIBs can be found in the
tree (referenced in code by
.Sy DEBUG_FP ) .
.Pp
-The sysctl variable may be set using the following grammar:
+The sysctl variable may be set in a number of ways:
.Bd -literal
- <fail_point> ::
- <term> ( "->" <term> )*
-
- <term> ::
- ( (<float> "%") | (<integer> "*" ) )*
- <type>
- [ "(" <integer> ")" ]
- [ "[pid " <integer> "]" ]
-
- <float> ::
- <integer> [ "." <integer> ] |
- "." <integer>
-
- <type> ::
- "off" | "return" | "sleep" | "panic" | "break" | "print"
+ [<pct>%][<cnt>*]<type>[(args...)][-><more terms>]
.Ed
.Pp
-The <type> argument specifies which action to take:
+The <type> argument specifies which action to take; it can be one of:
.Bl -tag -width ".Dv return"
.It Sy off
Take no action (does not trigger fail point code)
@@ -140,13 +168,23 @@ Panic
Break into the debugger, or trap if there is no debugger support
.It Sy print
Print that the fail point executed
+.It Sy pause
+Threads sleep at the fail point until the fail point is set to
+.Sy off
+.It Sy yield
+Thread yields the cpu when the fail point is evaluated
+.It Sy delay
+Similar to sleep, but busy waits the cpu.
+(Useful in non-sleepable contexts.)
.El
.Pp
-The <float>% and <integer>* modifiers prior to <type> control when
+The <pct>% and <cnt>* modifiers prior to <type> control when
<type> is executed.
-The <float>% form (e.g. "1.2%") can be used to specify a
+The <pct>% form (e.g. "1.2%") can be used to specify a
probability that <type> will execute.
-The <integer>* form (e.g. "5*") can be used to specify the number of
+This is a decimal in the range (0, 100] which can specify up to
+1/10,000% precision.
+The <cnt>* form (e.g. "5*") can be used to specify the number of
times <type> should be executed before this <term> is disabled.
Only the last probability and the last count are used if multiple
are specified, i.e. "1.2%2%" is the same as "2%".
@@ -191,6 +229,10 @@ Return 5 once, when pid 1234 executes the fail point.
.Sh AUTHORS
.An -nosplit
This manual page was written by
+.Pp
+.An Matthew Bryan Aq Mt matthew.bryan@isilon.com
+and
+.Pp
.An Zach Loafman Aq Mt zml@FreeBSD.org .
.Sh CAVEATS
It is easy to shoot yourself in the foot by setting fail points too
@@ -206,3 +248,10 @@ Currently,
.Fn fail_point_eval
does not verify whether the context is appropriate for calling
.Fn msleep .
+You can force it to evaluate a
+.Sy sleep
+action as a
+.Sy delay
+action by specifying the
+.Sy FAIL_POINT_NONSLEEPABLE
+flag at the point the fail point is declared.
diff --git a/share/man/man9/kqueue.9 b/share/man/man9/kqueue.9
index a8137bd..ff379d1 100644
--- a/share/man/man9/kqueue.9
+++ b/share/man/man9/kqueue.9
@@ -372,7 +372,7 @@ The function
will not be called, and the
.Vt knote
will not be returned on the next scan.
-Using this function could leak user land resources if a process uses the
+Using this function could leak userland resources if a process uses the
.Vt knote
to track resources.
.Pp
diff --git a/share/man/man9/netisr.9 b/share/man/man9/netisr.9
index 6d79c57..63112be 100644
--- a/share/man/man9/netisr.9
+++ b/share/man/man9/netisr.9
@@ -120,7 +120,7 @@ whose fields are defined as follows:
.Bl -tag -width "netisr_handler_t nh_handler"
.It Vt "const char *" Va nh_name
Unique character string name of the protocol, which may be included in
-.Xr sysctl 2
+.Xr sysctl 3
MIB names, so should not contain whitespace.
.It Vt netisr_handler_t Va nh_handler
Protocol handler function that will be invoked on each packet received for
diff --git a/share/man/man9/osd.9 b/share/man/man9/osd.9
index e8260fe..c27b5d9 100644
--- a/share/man/man9/osd.9
+++ b/share/man/man9/osd.9
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd January 5, 2011
+.Dd March 30, 2016
.Dt OSD 9
.Os
.Sh NAME
@@ -33,6 +33,9 @@
.Nm osd_register ,
.Nm osd_deregister ,
.Nm osd_set ,
+.Nm osd_reserve ,
+.Nm osd_set_reserved ,
+.Nm osd_free_reserved ,
.Nm osd_get ,
.Nm osd_del ,
.Nm osd_call ,
@@ -63,6 +66,22 @@
.Fa "void *value"
.Fc
.Ft void *
+.Fo osd_reserve
+.Fa "u_int slot"
+.Fc
+.Ft int
+.Fo osd_set_reserved
+.Fa "u_int type"
+.Fa "struct osd *osd"
+.Fa "u_int slot"
+.Fa "void *rsv"
+.Fa "void *value"
+.Fc
+.Ft void
+.Fo osd_free_reserved
+.Fa "void *rsv"
+.Fc
+.Ft void *
.Fo osd_get
.Fa "u_int type"
.Fa "struct osd *osd"
@@ -198,6 +217,15 @@ argument points to a data object to associate with
.Fa osd .
.Pp
The
+.Fn osd_set_reserved
+function does the same as
+.Fn osd_set ,
+but with an extra argument
+.Fa rsv
+that is internal-use memory previously allocated via
+.Fn osd_reserve .
+.Pp
+The
.Fn osd_get
function returns the data pointer associated with a kernel data structure's
.Vt struct osd
@@ -324,6 +352,24 @@ will proceed without any
.Xr realloc 9
calls.
.Pp
+It is possible for
+.Fn osd_set
+to fail to allocate this array. To ensure that such allocation succeeds,
+.Fn osd_reserve
+may be called (in a non-blocking context), and it will pre-allocate the
+memory via
+.Xr malloc 9
+with M_WAITOK.
+Then this pre-allocated memory is passed to
+.Fn osd_set_reserved ,
+which will use it if necessary or otherwise discard it.
+The memory may also be explicitly discarded by calling
+.Fn osd_free_reserved .
+As this method always allocates memory whether or not it is ultimately needed,
+it should be used only rarely, such as in the unlikely event that
+.Fn osd_set
+fails.
+.Pp
The
.Nm
API is geared towards slot identifiers storing pointers to the same underlying
@@ -359,15 +405,27 @@ the kernel including most fast paths.
returns the slot identifier for the newly registered data type.
.Pp
.Fn osd_set
-returns zero on success or ENOMEM if the specified type/slot identifier pair
+and
+.Fn osd_set_reserved
+return zero on success or ENOMEM if the specified type/slot identifier pair
triggered an internal
.Xr realloc 9
-which failed.
+which failed
+.Fn ( osd_set_reserved
+will always succeed when
+.Fa rsv
+is non-NULL).
.Pp
.Fn osd_get
returns the data pointer for the specified type/slot identifier pair, or NULL if
the slot has not been initialised yet.
.Pp
+.Fn osd_reserve
+returns a pointer suitable for passing to
+.Fn osd_set_reserved
+or
+.Fn osd_free_reserved .
+.Pp
.Fn osd_call
returns zero if no method is run or the method for each slot runs successfully.
If a method for a slot returns non-zero,
diff --git a/share/man/man9/rwlock.9 b/share/man/man9/rwlock.9
index 7598826..9ee16fc 100644
--- a/share/man/man9/rwlock.9
+++ b/share/man/man9/rwlock.9
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd December 13, 2014
+.Dd March 28, 2016
.Dt RWLOCK 9
.Os
.Sh NAME
@@ -313,18 +313,19 @@ facility was written by
This manual page was written by
.An "Gleb Smirnoff" .
.Sh BUGS
-If
+A kernel without
.Dv WITNESS
-is not included in the kernel,
-then it is impossible to assert that the current thread does or does not
-hold a read lock.
-In the
-.Pf non- Dv WITNESS
-case, the
+cannot assert whether the current thread does or does not hold a read lock.
.Dv RA_LOCKED
and
.Dv RA_RLOCKED
-assertions merely check that some thread holds a read lock.
+can only assert that
+.Em any
+thread holds a read lock.
+They cannot ensure that the current thread holds a read lock.
+Further,
+.Dv RA_UNLOCKED
+can only assert that the current thread does not hold a write lock.
.Pp
Reader/writer is a bit of an awkward name.
An
diff --git a/share/man/man9/sx.9 b/share/man/man9/sx.9
index a9931a9..f09584a 100644
--- a/share/man/man9/sx.9
+++ b/share/man/man9/sx.9
@@ -26,7 +26,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 13, 2016
+.Dd March 28, 2016
.Dt SX 9
.Os
.Sh NAME
@@ -320,16 +320,16 @@ end up sleeping while holding a mutex, which is not allowed.
.Xr rwlock 9 ,
.Xr sema 9
.Sh BUGS
-Currently there is no way to assert that a lock is not held.
-This is not possible in the
-.No non- Ns Dv WITNESS
-case for asserting that this thread
-does not hold a shared lock.
-In the
-.No non- Ns Dv WITNESS
-case, the
+A kernel without
+.Dv WITNESS
+cannot assert whether the current thread does or does not hold a shared lock.
.Dv SA_LOCKED
and
.Dv SA_SLOCKED
-assertions merely check that some thread holds a shared lock.
-They do not ensure that the current thread holds a shared lock.
+can only assert that
+.Em any
+thread holds a shared lock.
+They cannot ensure that the current thread holds a shared lock.
+Further,
+.Dv SA_UNLOCKED
+can only assert that the current thread does not hold an exclusive lock.
diff --git a/share/misc/bsd-family-tree b/share/misc/bsd-family-tree
index e4790ae..57d08f3 100644
--- a/share/misc/bsd-family-tree
+++ b/share/misc/bsd-family-tree
@@ -333,9 +333,11 @@ FreeBSD 5.2 | | | |
| | | | | DragonFly 4.2.0
| FreeBSD | | | |
| 10.2 | | | |
- | OS X NetBSD 7.0 | |
- | 10.11 | OpenBSD 5.8 |
- | | | | DragonFly 4.4.1
+ | | OS X NetBSD 7.0 | |
+ | | 10.11 | OpenBSD 5.8 |
+ | | | | | DragonFly 4.4.1
+ | FreeBSD | | OpenBSD 5.9 |
+ | 10.3 | | | |
| | | | |
FreeBSD 11 -current | NetBSD -current OpenBSD -current DragonFly -current
| | | | |
@@ -683,6 +685,8 @@ NetBSD 7.0 2015-09-25 [NBD]
OS X 10.11 2015-09-30 [APL]
OpenBSD 5.8 2015-10-18 [OBD]
DragonFly 4.4.1 2015-12-07 [DFB]
+OpenBSD 5.9 2016-03-29 [OBD]
+FreeBSD 10.3 2016-04-04 [FBD]
Bibliography
------------------------
diff --git a/share/misc/pci_vendors b/share/misc/pci_vendors
index a4a8b76..5ccce0f 100644
--- a/share/misc/pci_vendors
+++ b/share/misc/pci_vendors
@@ -3,11 +3,11 @@
#
# List of PCI ID's
#
-# Version: 2015.07.31
-# Date: 2015-07-31 03:15:02
+# Version: 2016.02.27
+# Date: 2016-02-27 03:15:01
#
-# Maintained by Martin Mares <mj@ucw.cz> and other volunteers from the
-# PCI ID Project at http://pci-ids.ucw.cz/.
+# Maintained by Albert Pool, Martin Mares, and other volunteers from
+# the PCI ID Project at http://pci-ids.ucw.cz/.
#
# New data are always welcome, especially if they are accurate. If you have
# anything to contribute, please follow the instructions at the web site.
@@ -23,6 +23,7 @@
# device device_name <-- single tab
# subvendor subdevice subsystem_name <-- two tabs
+0001 SafeNet (wrong ID)
0010 Allied Telesis, Inc (Wrong ID)
# This is a relabelled RTL-8139
8139 AT-2500TX V3 Ethernet
@@ -287,6 +288,10 @@
0050 SAS1064 PCI-X Fusion-MPT SAS
1028 1f04 SAS 5/E
1028 1f09 SAS 5i/R
+ 0052 MegaRAID SAS-3 3216/3224 [Cutlass]
+ 0053 MegaRAID SAS-3 3216/3224 [Cutlass]
+ 1000 9350 MegaRAID SAS 9341-16i
+ 1000 9351 MegaRAID SAS 9341-24i
0054 SAS1068 PCI-X Fusion-MPT SAS
1028 1f04 SAS 5/E Adapter Controller
1028 1f05 SAS 5/i Adapter Controller
@@ -364,6 +369,7 @@
1028 1f4c PERC H330 Mini (for blades)
1028 1f4d PERC H330 Embedded (for monolithic)
1054 306a SAS 3004 iMR ROMB
+ 1d49 04db ServeRAID M1210 SAS/SATA Controller
0060 MegaRAID SAS 1078
1000 1006 MegaRAID SAS 8888ELP
1000 100a MegaRAID SAS 8708ELP
@@ -482,6 +488,8 @@
0085 SAS2208 PCI-Express Fusion-MPT SAS-2
0086 SAS2308 PCI-Express Fusion-MPT SAS-2
0087 SAS2308 PCI-Express Fusion-MPT SAS-2
+ 1000 3020 9207-8i SAS2.1 HBA
+ 1000 3040 9207-8e SAS2.1 HBA
1590 0044 H220i
008f 53c875J
1092 8000 FirePort 40 SCSI Controller
@@ -494,6 +502,21 @@
0097 SAS3008 PCI-Express Fusion-MPT SAS-3
1028 1f45 12GB/s HBA internal
1028 1f46 12Gbps HBA
+ 00c0 SAS3324 PCI-Express Fusion-MPT SAS-3
+ 00c1 SAS3324 PCI-Express Fusion-MPT SAS-3
+ 00c2 SAS3324 PCI-Express Fusion-MPT SAS-3
+ 00c3 SAS3324 PCI-Express Fusion-MPT SAS-3
+ 00c4 SAS3224 PCI-Express Fusion-MPT SAS-3
+ 00c5 SAS3316 PCI-Express Fusion-MPT SAS-3
+ 00c6 SAS3316 PCI-Express Fusion-MPT SAS-3
+ 00c7 SAS3316 PCI-Express Fusion-MPT SAS-3
+ 00c8 SAS3316 PCI-Express Fusion-MPT SAS-3
+ 00c9 SAS3216 PCI-Express Fusion-MPT SAS-3
+ 00ce MegaRAID SAS-3 3316 [Intruder]
+ 1000 9371 MegaRAID SAS 9361-16i
+ 1000 9390 MegaRAID SAS 9380-8i8e
+ 00cf MegaRAID SAS-3 3324 [Intruder]
+ 1000 9370 MegaRAID SAS 9361-24i
0407 MegaRAID
1000 0530 MegaRAID 530 SCSI 320-0X RAID Controller
1000 0531 MegaRAID 531 SCSI 320-4X RAID Controller
@@ -1260,7 +1283,7 @@
5652 RV410/M26 [Mobility Radeon X700]
5653 RV410/M26 [Mobility Radeon X700]
1025 0080 Aspire 5024WLMi
- 103c 0940 HP Compaq NW8240 Mobile Workstation
+ 103c 0940 Compaq NW8240 Mobile Workstation
5654 264VT [Mach64 VT]
1002 5654 Mach64VT Reference
5655 264VT3 [Mach64 VT3]
@@ -1515,6 +1538,12 @@
1462 3271 Radeon R9 360 OEM
1682 7360 Radeon R7 360
6660 Sun XT [Radeon HD 8670A/8670M/8690M / R5 M330]
+ 1028 05ea Radeon HD 8670M
+ 1028 06bf Radeon R5 M335
+ 103c 1970 Radeon HD 8670M
+ 103c 80be Radeon R5 M330
+ 103c 8136 Radeon R5 M330
+ 17aa 3804 Radeon R5 M330
17aa 3809 Radeon R5 M330
17aa 390c Radeon R5 M330
6663 Sun PRO [Radeon HD 8570A/8570M]
@@ -2075,6 +2104,7 @@
1458 228c R9 290X WindForce 3X
1458 228d R9 290X WindForce 3X OC
1458 2290 R9 290X WindForce 3X
+ 1458 22c1 Grenada PRO [Radeon R9 390]
1462 3070 R9 290X Lightning
1462 3071 R9 290X Lightning
1462 3072 R9 290X Lightning LE
@@ -2103,7 +2133,7 @@
1002 0310 FirePro S7000
1002 0420 Radeon Sky 500
6809 Pitcairn LE GL [FirePro W5000]
- 6810 Curacao XT [Radeon R7 370 / R9 270X/370 OEM]
+ 6810 Curacao XT / Trinidad XT [Radeon R7 370 / R9 270X/370X]
148c 0908 Radeon R9 370 OEM
1682 7370 Radeon R7 370
6811 Curacao PRO [Radeon R7 370 / R9 270/370 OEM]
@@ -2743,20 +2773,42 @@
174b e180 Radeon HD 7350
17af 3015 Radeon HD 7350
68fe Cedar LE
- 6900 Topaz XT [Radeon R7 M260/M265]
- 1028 0640 Radeon R7 M265
+ 6900 Topaz XT [Radeon R7 M260/M265 / M340/M360]
+ 1025 1056 Radeon R7 M360 / R8 M365DX
+ 1028 0640 Radeon R7 M260/M265
+ 1028 0643 Radeon R7 M260/M265
+ 1028 067f Radeon R7 M260
+ 1028 130a Radeon R7 M260
+ 103c 2263 Radeon R7 M260
103c 2269 Radeon R7 M260
+ 103c 22c6 Radeon R7 M260
103c 22c8 Radeon R7 M260
+ 103c 808c Radeon R7 M260
+ 103c 8099 Radeon R7 M360
+ 103c 80b5 Radeon R7 M360
+ 103c 80b9 Radeon R7 M360
+ 103c 811c Radeon R7 M340
+ 10cf 1906 Radeon R7 M260
+ 1170 9979 Radeon R7 M360
1179 f903 Radeon R7 M260
+ 1179 f922 Radeon R7 M260
+ 1179 f923 Radeon R7 M260
1179 f934 Radeon R7 M260
+ 17aa 3822 Radeon R7 M360
+ 17aa 3824 Radeon R7 M360
+ 17aa 5021 Radeon R7 M260
6901 Topaz PRO [Radeon R5 M255]
+ 103c 1318 Radeon R6 M255DX
6921 Amethyst XT [Radeon R9 M295X]
- 6929 Tonga PRO GL [FirePro Series]
+ 6929 Tonga XT GL [FirePro S7150]
692b Tonga PRO GL [FirePro W7100]
- 692f Tonga XT GL [FirePro W8100]
- 6938 Amethyst XT [Radeon R9 M295X Mac Edition]
+ 692f Tonga XTV GL [FirePro S7150V]
+ 6938 Tonga XT / Amethyst XT [Radeon R9 380X / R9 M295X Mac Edition]
+ 174b e308 Radeon R9 380X Nitro 4G D5
6939 Tonga PRO [Radeon R9 285/380]
148c 9380 Radeon R9 380
+# Make naming scheme consistent
+ 174b e308 Radeon R9 380 Nitro 4G D5
700f RS100 AGP Bridge
7010 RS200/RS250 AGP Bridge
7100 R520 [Radeon X1800 XT]
@@ -2877,7 +2929,11 @@
72a8 RV570 [Radeon X1950 GT] (Secondary)
72b1 RV560 [Radeon X1650 XT] (Secondary)
72b3 RV560 [Radeon X1650 GT] (Secondary)
- 7300 Fiji XT [Radeon R9 FURY X]
+ 7300 Fiji [Radeon R9 FURY / NANO Series]
+ 1002 0b36 Radeon R9 FURY X / NANO
+ 1043 049e Radeon R9 FURY
+ 1043 04a0 Radeon R9 FURY X
+ 174b e329 Radeon R9 FURY
7833 RS350 Host Bridge
7834 RS350 [Radeon 9100 PRO/XT IGP]
7835 RS350M [Mobility Radeon 9000 IGP]
@@ -3144,10 +3200,12 @@
985f Mullins
9874 Carrizo
9900 Trinity [Radeon HD 7660G]
+ 103c 1985 Pavilion 17-e163sg Notebook PC
# AMD A10-5800K CPU
9901 Trinity [Radeon HD 7660D]
9902 Trinity HDMI Audio Controller
103c 194e ProBook 455 G1 Notebook
+ 103c 1985 Pavilion 17-e163sg Notebook PC
9903 Trinity [Radeon HD 7640G]
103c 194e ProBook 455 G1 Notebook
103c 1952 ProBook 455 G1 Notebook
@@ -3168,6 +3226,8 @@
9917 Trinity [Radeon HD 7620G]
9918 Trinity [Radeon HD 7600G]
9919 Trinity [Radeon HD 7500G]
+ 9920 Liverpool Graphics
+ 9921 Liverpool HDMI/DP Audio Controller
9990 Trinity [Radeon HD 7520G]
9991 Trinity [Radeon HD 7540D]
9992 Trinity [Radeon HD 7420G]
@@ -3214,6 +3274,11 @@
174b aa98 Radeon HD 6450 1GB DDR3
aaa0 Tahiti XT HDMI Audio [Radeon HD 7970 Series]
aab0 Cape Verde/Pitcairn HDMI Audio [Radeon HD 7700/7800 Series]
+ aac0 Tobago HDMI Audio [Radeon R7 360 / R9 360 OEM]
+ aac8 Hawaii HDMI Audio
+# I have a Tonga card and this is the HDMI Audio part
+ aad8 Tonga HDMI Audio [Radeon R9 285/380]
+ 174b aad8 Radeon R9 285/380 HDMI Audio
ac00 Theater 600 Pro
ac02 TV Wonder HD 600 PCIe
ac12 Theater HD T507 (DVB-T) TV tuner/capture device
@@ -3630,9 +3695,12 @@
1014 049a PCIe3 x16 SAS RAID Internal Adapter 6Gb (57EE)
1014 04c7 PCIe3 x 8 Cache SAS RAID Internal Adapter 6GB(2CCA)
1014 04c8 PCIe3 x 8 Cache SAS RAID Internal Adapter 6GB(2CD2)
- 1014 0c49 PCIe3 x 8 Cache SAS RAID Internal Adapter 6GB(2CCD)
+ 1014 04c9 PCIe3 x 8 Cache SAS RAID Internal Adapter 6GB(2CCD)
044b GenWQE Accelerator Adapter
04aa Flash Adapter 90 (PCIe2 0.9TB)
+ 04da PCI-E IPR SAS+ Adapter (ASIC)
+ 1014 04fb PCIe3 x16 20GB Cache 12Gb Quad SAS RAID+ Adapter(580B)
+ 1014 04fc PCIe3 x8 12Gb Quad SAS RAID+ Adapter(580A)
3022 QLA3022 Network Adapter
4022 QLA3022 Network Adapter
ffff MPIC-2 interrupt controller
@@ -3727,9 +3795,12 @@
1404 Family 15h (Models 10h-1fh) Processor Function 4
1405 Family 15h (Models 10h-1fh) Processor Function 5
1410 Family 15h (Models 10h-1fh) Processor Root Complex
+ 103c 1985 Pavilion 17-e163sg Notebook PC
1412 Family 15h (Models 10h-1fh) Processor Root Port
+ 1022 1234 Trinity A-series APU
1413 Family 15h (Models 10h-1fh) Processor Root Port
1414 Family 15h (Models 10h-1fh) Processor Root Port
+ 1022 1234 Trinity A-series APU
1415 Family 15h (Models 10h-1fh) Processor Root Port
1416 Family 15h (Models 10h-1fh) Processor Root Port
1417 Family 15h (Models 10h-1fh) Processor Root Port
@@ -3744,7 +3815,11 @@
1422 Family 15h (Models 30h-3fh) Processor Root Complex
1423 Family 15h (Models 30h-3fh) I/O Memory Management Unit
1426 Family 15h (Models 30h-3fh) Processor Root Port
+ 1436 Liverpool Processor Root Complex
+ 1437 Liverpool I/O Memory Management Unit
+ 1438 Liverpool Processor Root Port
1439 Family 16h Processor Functions 5:1
+ 145b Zeppelin Non-Transparent Bridge
1510 Family 14h Processor Root Complex
174b 1001 PURE Fusion Mini
1512 Family 14h Processor Root Port
@@ -3890,27 +3965,34 @@
7802 FCH SATA Controller [RAID mode]
7803 FCH SATA Controller [RAID mode]
7804 FCH SATA Controller [AHCI mode]
+ 103c 1985 Pavilion 17-e163sg Notebook PC
7805 FCH SATA Controller [RAID mode]
7806 FCH SD Flash Controller
7807 FCH USB OHCI Controller
103c 194e ProBook 455 G1 Notebook
+ 103c 1985 Pavilion 17-e163sg Notebook PC
7808 FCH USB EHCI Controller
103c 194e ProBook 455 G1 Notebook
+ 103c 1985 Pavilion 17-e163sg Notebook PC
7809 FCH USB OHCI Controller
103c 194e ProBook 455 G1 Notebook
780b FCH SMBus Controller
103c 194e ProBook 455 G1 Notebook
+ 103c 1985 Pavilion 17-e163sg Notebook PC
780c FCH IDE Controller
780d FCH Azalia Controller
103c 194e ProBook 455 G1 Notebook
+ 103c 1985 Pavilion 17-e163sg Notebook PC
1043 8444 F2A85-M Series
780e FCH LPC Bridge
103c 194e ProBook 455 G1 Notebook
+ 103c 1985 Pavilion 17-e163sg Notebook PC
780f FCH PCI Bridge
7812 FCH USB XHCI Controller
7813 FCH SD Flash Controller
7814 FCH USB XHCI Controller
103c 194e ProBook 455 G1 Notebook
+ 103c 1985 Pavilion 17-e163sg Notebook PC
7900 FCH SATA Controller [IDE mode]
7901 FCH SATA Controller [AHCI mode]
7902 FCH SATA Controller [RAID mode]
@@ -3923,6 +4005,7 @@
790f FCH PCI Bridge
7914 FCH USB XHCI Controller
9600 RS780 Host Bridge
+ 1043 82ee M378A-CM Motherboard
1043 82f1 M3A78-EH Motherboard
9601 RS880 Host Bridge
1019 2120 A785GM-M
@@ -4479,6 +4562,7 @@
103c 1293 USB add-in card
103c 1294 USB 2.0 add-in card
1179 0001 USB
+ 1186 0035 DUB-C2 USB 2.0 2-port 32-bit cardbus controller
12ee 7000 Root Hub
14c2 0105 PTI-205N USB 2.0 Host Controller
1799 0001 Root Hub
@@ -4510,6 +4594,7 @@
00ce uPD72871 [Firewarden] IEEE1394a OHCI 1.0 Link/1-port PHY Controller
00df Vr4131
00e0 uPD72010x USB 2.0 Controller
+ 1186 f100 DUB-C2 USB 2.0 2-port 32-bit cardbus controller
12ee 7001 Root hub
14c2 0205 PTI-205N USB 2.0 Host Controller
1799 0002 Root Hub
@@ -4796,30 +4881,30 @@
103c 3212 Smart Array E200
3239 Smart Array Gen9 Controllers
103c 21bd P244br
- 103c 21be Smart Array
+ 103c 21be P741m
103c 21bf H240ar
103c 21c0 P440ar
- 103c 21c1 Smart Array
+ 103c 21c1 P840ar
103c 21c2 P440
103c 21c3 P441
103c 21c4 Smart Array
- 103c 21c5 Smart Array
+ 103c 21c5 P841
103c 21c6 H244br
103c 21c7 H240
103c 21c8 H241
103c 21c9 Smart Array
- 103c 21ca Smart Array
+ 103c 21ca P246br
103c 21cb P840
103c 21cc Smart Array
- 103c 21cd Smart Array
- 103c 21ce Smart Array
+ 103c 21cd P240nr
+ 103c 21ce H240nr
323a Smart Array G6 controllers
103c 3241 Smart Array P212
103c 3243 Smart Array P410
103c 3245 Smart Array P410i
103c 3247 Smart Array P411
103c 3249 Smart Array P812
- 103c 324a HP Smart Array 712m (Mezzanine RAID controller)
+ 103c 324a Smart Array 712m (Mezzanine RAID controller)
103c 324b Smart Array P711m (Mezzanine RAID controller)
323b Smart Array Gen8 Controllers
103c 3350 P222
@@ -5140,6 +5225,7 @@
803b 5-in-1 Multimedia Card Reader (SD/MMC/MS/MS PRO/xD)
103c 309f nx9420
103c 30a3 Compaq nw8440
+ 104d 8212 VAIO VGN-N21E
104d 902d VAIO VGN-NR120E
803c PCIxx12 SDA Standard Compliant SD Host Controller
103c 309f nx9420
@@ -5171,6 +5257,7 @@
1395 2201 WL22-PC
16ab 8501 WL-8305 IEEE802.11b+ Wireless LAN PCI Adapter
8401 ACX 100 22Mbps Wireless Interface
+ 8888 Multicore DSP+ARM KeyStone II SOC
9000 Wireless Interface (of unknown type)
9065 TMS320DM642
9066 ACX 111 54Mbps Wireless Interface
@@ -5294,6 +5381,14 @@
8056 Rockwell HCF 56K modem
808a Memory Stick Controller
81ce SxS Pro memory card
+ 908f Aeolia ACPI
+ 909e Aeolia Ethernet Controller (Marvell Yukon 2 Family)
+ 909f Aeolia SATA AHCI Controller
+ 90a0 Aeolia SD/MMC Host Controller
+ 90a1 Aeolia PCI Express Glue and Miscellaneous Devices
+ 90a2 Aeolia DMA Controller
+ 90a3 Aeolia Memory (DDR3/SPM)
+ 90a4 Aeolia USB 3.0 xHCI Host Controller
104e Oak Technology, Inc
0017 OTI-64017
0107 OTI-107 [Spitfire]
@@ -5435,7 +5530,6 @@
6400 MPC190 Security Processor (S1 family, encryption)
6405 MPC184 Security Processor (S1 family)
1058 Electronics & Telecommunications RSH
-# Formerly: Teknor Industrial Computers Inc
1059 Kontron
105a Promise Technology, Inc.
0d30 PDC20265 (FastTrak100 Lite/Ultra100)
@@ -5701,6 +5795,7 @@
0074 U4 HT Bridge
# should be 14e4:1645
1645 Broadcom NetXtreme BCM5701 Gigabit Ethernet
+ 2001 PCI Express SSD
106c Hynix Semiconductor
8139 8139c 100BaseTX Ethernet Controller
8801 Dual Pentium ISA/PCI Motherboard
@@ -5757,13 +5852,52 @@
101e 8493 QLA12160 on AMI MegaRAID
1240 ISP1240 SCSI Host Adapter
1280 ISP1280 SCSI Host Adapter
+ 1634 FastLinQ QL45000 Series 40GbE Controller
+ 1077 e4f1 FastLinQ QL45212H 40GbE Adapter
+ 1077 e4f2 FastLinQ QL45211H 40GbE Adapter
+ 1077 e4f3 FastLinQ QL45412H 40GbE Adapter
+ 1077 e4f4 FastLinQ QL45411H 40GbE Adapter
+ 1644 FastLinQ QL45000 Series 100GbE Controller
+ 1077 e4f8 FastLinQ QL45611H 100GbE Adapter
+ 1656 FastLinQ QL45000 Series 25GbE Controller
+ 1077 e4f6 FastLinQ QL45211H 25GbE Adapter
+ 1077 e4f7 FastLinQ QL45212H 25GbE Adapter
+ 165c FastLinQ QL45000 Series 40GbE Controller (FCoE)
+ 1077 e4f1 FastLinQ QL45462H 40GbE FCoE Adapter
+ 1077 e4f2 FastLinQ QL45461H 40GbE FCoE Adapter
+ 165e FastLinQ QL45000 Series 40GbE Controller (iSCSI)
+ 1077 e4f1 FastLinQ QL45462H 40GbE iSCSI Adapter
+ 1077 e4f2 FastLinQ QL45461H 40GbE iSCSI Adapter
+ 1664 FastLinQ QL45000 Series Gigabit Ethernet Controller (SR-IOV VF)
+ 1077 e4f1 FastLinQ QL45462H 40GbE Adapter (SR-IOV VF)
+ 1077 e4f2 FastLinQ QL45461H 40GbE Adapter (SR-IOV VF)
+ 1077 e4f3 FastLinQ QL45412H 40GbE Adapter (SR-IOV VF)
+ 1077 e4f4 FastLinQ QL45411H 40GbE Adapter (SR-IOV VF)
+ 1077 e4f6 FastLinQ QL45211H 25GbE Adapter (SR-IOV VF)
+ 1077 e4f7 FastLinQ QL45212H 25GbE Adapter (SR-IOV VF)
+ 1077 e4f8 FastLinQ QL45611H 100GbE Adapter (SR-IOV VF)
2020 ISP2020A Fast!SCSI Basic Adapter
2031 ISP8324-based 16Gb Fibre Channel to PCI Express Adapter
+ 103c 17e7 HP SN1000Q 16Gb Single Port Fibre Channel Adapter
+ 103c 17e8 HP SN1000Q 16Gb Dual Port Fibre Channel Adapter
+ 103c 1939 HP QMH2672 16Gb Dual Port Fibre Channel Adapter
103c 8002 3830C 16G Fibre Channel Host Bus Adapter
+ 2071 ISP2714-based 16/32Gb Fibre Channel to PCIe Adapter
+ 1077 0283 QLE2764 Quad Port 32Gb Fibre Channel to PCIe Adapter
+ 1077 029e QLE2694 Quad Port 16Gb Fibre Channel to PCIe Adapter
+ 1077 02a2 QLE2694L Quad Port 16Gb Fibre Channel to PCIe Adapter
+ 1077 02ad QLE2694U Quad Port 16/32Gb Fibre Channel to PCIe Adapter
2100 QLA2100 64-bit Fibre Channel Adapter
1077 0001 QLA2100 64-bit Fibre Channel Adapter
2200 QLA2200 64-bit Fibre Channel Adapter
1077 0002 QLA2200
+ 2261 ISP2722-based 16/32Gb Fibre Channel to PCIe Adapter
+ 1077 0299 QLE2740 Single Port 32Gb Fibre Channel to PCIe Adapter
+ 1077 029a QLE2742 Dual Port 32Gb Fibre Channel to PCIe Adapter
+ 1077 029b QLE2690 Single Port 16Gb Fibre Channel to PCIe Adapter
+ 1077 029c QLE2692 Dual Port 16Gb Fibre Channel to PCIe Adapter
+ 1590 00f9 HPE StoreFabric SN1100Q 16Gb Single Port Fibre Channel Host Bus Adapter
+ 1590 00fa HPE StoreFabric SN1100Q 16Gb Dual Port Fibre Channel Host Bus Adapter
2300 QLA2300 64-bit Fibre Channel Adapter
2312 ISP2312-based 2Gb Fibre Channel to PCI-X HBA
103c 0131 2Gb Fibre Channel - Single port [A7538A]
@@ -5777,6 +5911,7 @@
2532 ISP2532-based 8Gb Fibre Channel to PCI Express HBA
103c 3262 StorageWorks 81Q
1077 0167 QME2572 Dual Port FC8 HBA Mezzanine
+ 1590 00fc HPE StoreFabric 84Q 8Gb Quad Port Fibre Channel Host Bus Adapter
3022 ISP4022-based Ethernet NIC
3032 ISP4032-based Ethernet IPv6 NIC
4010 ISP4010-based iSCSI TOE HBA
@@ -5994,6 +6129,7 @@
1093 National Instruments
0160 PCI-DIO-96
0162 PCI-MIO-16XE-50
+ 0fe1 PXI-8320
1150 PCI-6533 (PCI-DIO-32HS)
1170 PCI-MIO-16XE-10
1180 PCI-MIO-16E-1
@@ -6085,7 +6221,10 @@
7004 PXI-6551
700b PXI-5421
700c PCI-5421
+ 701a VXIpc-87xB
+ 701b VXIpc-770
7023 PXI-2593
+ 7027 PCI-MXI-2 Universal
702c PXI-7831R
702d PCI-7831R
702e PXI-7811R
@@ -6354,6 +6493,7 @@
731d PXI-2536
7322 PXIe-6124
7327 PXI-6529
+ 732c VXI-8360T
7331 PXIe-5602
7332 PXIe-5601
7333 PXI-5900
@@ -6493,6 +6633,7 @@
75e5 PXI-6683
75e6 PXI-6683H
75ef PXIe-5632
+ 761c VXI-8360LT
761f PXI-2540
7620 PXIe-2540
7621 PXI-2541
@@ -6523,6 +6664,7 @@
76a3 PXIe-6535B
76a4 PXIe-6536B
76a5 PXIe-6537B
+ 783e PXI-8368
9020 PXI-2501
9030 PXI-2503
9040 PXI-2527
@@ -6532,6 +6674,7 @@
9080 PXI-2580
9090 PCI-4021
90a0 PXI-4021
+ a001 PCI-MXI-2
b001 PCI-1408
b011 PXI-1408
b021 PCI-1424
@@ -6621,7 +6764,9 @@
1093 762b PXIe-4138
1093 762c PXIe-4144
1093 762d PXIe-4145
+ 1093 762e PXIe-5606
1093 7644 PXIe-4841
+ 1093 764a PCIe-8237R-S
1093 7658 PXIe-5162 (4CH)
1093 76ab PXIe-4322
1093 76ad PXIe-4112
@@ -6629,14 +6774,25 @@
1093 76b5 PXIe-7971R
1093 76b6 PXIe-7972R
1093 76b7 PXIe-7975R
+ 1093 76b8 PXIe-5696
+ 1093 76b9 PXIe-5654
1093 76c8 PXIe-6614
1093 76c9 PXIe-6612
1093 76cb PXIe-5646R
1093 76cc PXIe-5162 (2CH)
+ 1093 76ce CVS-1459
1093 76d0 PXIe-5160 (2CH)
1093 76d1 PXIe-5160 (4CH)
1093 76dc PXIe-4610
+ 1093 76ec PXIe-2524
+ 1093 76ed PXIe-2525
+ 1093 76ee PXIe-2526
+ 1093 76ef PXIe-2737
+ 1093 76f0 PXIe-2738
+ 1093 76f1 PXIe-2739
1093 76fb PCIe-1473R-LX110
+ 1093 76fc PXIe-5105
+ 1093 76fd PXIe-5114
1093 76fe PXIe-5644R
1093 76ff PXIe-5644R
1093 7700 PXIe-5644R
@@ -6645,24 +6801,49 @@
1093 7703 PXIe-5645R
1093 770c PXIe-4139
1093 7711 PXIe-4464
+ 1093 7712 PXIe-4463
1093 7716 PCIe-6612
+ 1093 771d Unconfigured CA4 Switch
1093 771e PXIe-4339
1093 7735 cRIO-9033
+ 1093 773e PXIe-5624R
1093 774b cRIO-9031
1093 774d cRIO-9034
1093 7755 cRIO-9030
+ 1093 7768 PXIe-2747
+ 1093 7769 PXIe-2748
+ 1093 776a PXIe-2746
1093 7777 PXIe-7976R
1093 7782 PXIe-5646R
1093 7783 PXIe-5646R
1093 7784 PXIe-5646R
+ 1093 7790 PXIe-5170R (4CH)
+ 1093 7791 PXIe-5170R (8CH)
+ 1093 7793 PXIe-5171R (8CH)
1093 77a5 PXIe-6345
1093 77a6 PXIe-6355
1093 77a7 PXIe-6365
1093 77a8 PXIe-6375
+ 1093 77aa CVS-1458
+ 1093 77ad IC-3173
1093 77b4 PXIe-7820R
1093 77b5 PXIe-7821R
1093 77b6 PXIe-7822R
1093 77b9 cRIO-9038
+ 1093 77ba PXIe-4136
+ 1093 77bb PXIe-4137
+ 1093 77c0 PXIe-5624R
+ 1093 77c1 PXIe-5624R
+ 1093 77c2 PXIe-5624R
+ 1093 77ca PXIe-6738
+ 1093 77cb PXIe-6739
+ 1093 77db cRIO-9035
+ 1093 77dc cRIO-9036
+ 1093 77dd cRIO-9039
+ 1093 7802 PXIe-4302
+ 1093 7803 PXIe-4303
+ 1093 7805 PXIe-4305
+ 1093 788e PXIe-4304
c801 PCI-GPIB
c811 PCI-GPIB+
c821 PXI-GPIB
@@ -6700,6 +6881,13 @@
e251 PXI-8460 (2 ports)
e261 PCI-CAN/DS
e271 PXI-8462
+ f110 VMEpc-650
+ f120 VXIpc-650
+ fe00 VXIpc-87x
+ fe41 VXIpc-860
+ fe51 VXIpc-74x
+ fe61 VXIpc-850
+ fe70 VXIpc-880
1094 First International Computers [FIC]
# nee CMD Technology Inc
1095 Silicon Image, Inc.
@@ -7073,6 +7261,7 @@
8747 PEX 8747 48-Lane, 5-Port PCI Express Gen 3 (8.0 GT/s) Switch
# This is the Non-Transparent-Bridge Virtualized Port as presented by the PLX PEX 8732 chip, the physical bridges show up at 10b5:8732
87b0 PEX 8732 32-lane, 8-Port PCI Express Gen 3 (8.0 GT/s) Switch
+ 1093 7761 PXIe-8830mc
9016 PLX 9016 8-port serial controller
9030 PCI9030 32-bit 33MHz PCI <-> IOBus Bridge
10b5 2695 Hilscher CIF50-PB/DPS Profibus
@@ -7084,6 +7273,7 @@
10b5 3025 Alpermann+Velte PCL PCI L (3V/5V): Timecode Reader Board
10b5 3068 Alpermann+Velte PCL PCI HD (3V/5V): Timecode Reader Board
10b5 3463 Alpermann+Velte PCL PCI D (v2) (3V/5V): Timecode Reader Board
+ 10b5 3591 PLURA PCL PCI L (v2) (3.3V/5V): Time Code Reader Board
12fe 0111 CPCI-ASIO4 (ESD 4-port Serial Interface Board)
1369 9c01 VX222v2
1369 9d01 VX222-Mic
@@ -7096,7 +7286,7 @@
1369 a801 LCM200
1397 3136 4xS0-ISDN PCI Adapter
1397 3137 S2M-E1-ISDN PCI Adapter
- 1518 0200 Kontron ThinkIO-C
+ 1518 0200 ThinkIO-C
15ed 1002 MCCS 8-port Serial Hot Swap
15ed 1003 MCCS 16-port Serial Hot Swap
# MIL-STD-1553B Board
@@ -8751,7 +8941,7 @@
0446 MCP65 SMBus
103c 30cf Pavilion dv9668eg Laptop
0447 MCP65 SMU
- 103c 30cf Pavilion dv9668eg Laptop
+ 103c 30cf Pavilion dv9500/9600/9700 series
0448 MCP65 IDE
103c 30cf Pavilion dv9668eg Laptop
0449 MCP65 PCI bridge
@@ -9575,6 +9765,7 @@
0f00 GF108 [GeForce GT 630]
0f01 GF108 [GeForce GT 620]
0f02 GF108 [GeForce GT 730]
+ 0f06 GF108 [GeForce GT 730]
0fbb GM204 High Definition Audio Controller
0fc0 GK107 [GeForce GT 640 OEM]
0fc1 GK107 [GeForce GT 640]
@@ -9619,6 +9810,7 @@
0fea GK107M [GeForce GT 755M Mac Edition]
0fec GK107M [GeForce 710A]
0fed GK107M [GeForce 820M]
+ 0fee GK107M [GeForce 810M]
0fef GK107GL [GRID K340]
0ff1 GK107 [NVS 1000]
0ff2 GK107GL [GRID K1]
@@ -9747,6 +9939,7 @@
10c5 GT218 [GeForce 405]
10d8 GT218 [NVS 300]
1140 GF117M [GeForce 610M/710M/810M/820M / GT 620M/625M/630M/720M]
+ 1019 0799 GeForce 820M
1019 999f GeForce GT 720M
1025 0600 GeForce GT 620M
1025 0606 GeForce GT 620M
@@ -9846,6 +10039,7 @@
1028 065e GeForce 820M
1028 0662 GeForce 820M
1028 068d GeForce 820M
+ 1028 06c1 GeForce 820M
103c 18ef GeForce GT 630M
103c 18f9 GeForce GT 630M
103c 18fb GeForce GT 630M
@@ -10052,12 +10246,18 @@
1854 0180 GeForce 710M
1854 0190 GeForce GT 720M
1854 0192 GeForce GT 720M
+ 1854 0224 GeForce 820M
+ 1b0a 01c0 GeForce 820M
1b0a 20dd GeForce GT 620M
1b0a 20df GeForce GT 620M
1b0a 210e GeForce 820M
1b0a 2202 GeForce GT 720M
1b0a 90d7 GeForce 820M
1b0a 90dd GeForce 820M
+ 1b50 5530 GeForce 820M
+ 1b6c 5531 GeForce GT 720M
+ 1bab 0106 GeForce 820M
+ 1d05 1013 GeForce 810M
1180 GK104 [GeForce GTX 680]
1043 83f1 GTX680-DC2-2GD5
3842 3682 GeForce GTX 680 Mac Edition
@@ -10185,6 +10385,7 @@
1287 GK208 [GeForce GT 730]
1288 GK208 [GeForce GT 720]
1289 GK208 [GeForce GT 710]
+ 128b GK208 [GeForce GT 710]
1290 GK208M [GeForce GT 730M]
103c 2afa GeForce GT 730A
103c 2b04 GeForce GT 730A
@@ -10209,7 +10410,7 @@
1296 GK208M [GeForce 825M]
1298 GK208M [GeForce GT 720M]
1299 GK208M [GeForce 920M]
- 129a GK208GL [N16V-GL]
+ 129a GK208M [GeForce 910M]
12a0 GK208
12b9 GK208GLM [Quadro K610M]
12ba GK208GLM [Quadro K510M]
@@ -10222,6 +10423,9 @@
1344 GM108M [GeForce 845M]
1346 GM108M [GeForce 930M]
1347 GM108M [GeForce 940M]
+ 1348 GM108M [GeForce 945A]
+ 1349 GM108M [GeForce 930M]
+ 134d GM108M [GeForce 940MX]
137a GM108GLM [Quadro K620M]
137d GM108M [GeForce 940A]
1380 GM107 [GeForce GTX 750 Ti]
@@ -10236,12 +10440,19 @@
1393 GM107M [GeForce 840M]
1398 GM107M [GeForce 845M]
139a GM107M [GeForce GTX 950M]
+ 17aa 362c GeForce GTX 950A
+ 17aa 362f GeForce GTX 950A
+ 17aa 363f GeForce GTX 950A
+ 17aa 3640 GeForce GTX 950A
+ 17aa 36b9 GeForce GTX 950A
139b GM107M [GeForce GTX 960M]
+ 103c 2b4c GeForce GTX 960A
139c GM107M [GeForce 940M]
13b0 GM107GLM [Quadro M2000M]
13b1 GM107GLM [Quadro M1000M]
13b2 GM107GLM [Quadro M600M]
13b3 GM107GLM [Quadro K2200M]
+ 13b9 GM107GL [NVS 810]
13ba GM107GL [Quadro K2200]
13bb GM107GL [Quadro K620]
13bc GM107GL [Quadro K1200]
@@ -10254,23 +10465,35 @@
13d7 GM204M [GeForce GTX 980M]
13d8 GM204M [GeForce GTX 970M]
13d9 GM204M [GeForce GTX 965M]
+ 13da GM204M [GeForce GTX 980]
13f0 GM204GL [Quadro M5000]
13f1 GM204GL [Quadro M4000]
13f2 GM204GL [Tesla M60]
+ 13f3 GM204GL [Tesla M6]
+ 13f8 GM204GLM [Quadro M5000M]
+ 13f9 GM204GLM [Quadro M4000M]
+ 13fa GM204GLM [Quadro M3000M]
1401 GM206 [GeForce GTX 960]
+ 1402 GM206 [GeForce GTX 950]
+ 1407 GM206 [GeForce GTX 750 v2]
+ 1427 GM206M [GeForce GTX 965M]
+ 1431 GM206GL [Tesla M4]
1617 GM204M [GeForce GTX 980M]
1618 GM204M [GeForce GTX 970M]
1619 GM204M [GeForce GTX 965M]
+ 161a GM204M [GeForce GTX 980]
+ 1667 GM204M [GeForce GTX 965M]
17c2 GM200 [GeForce GTX TITAN X]
17c8 GM200 [GeForce GTX 980 Ti]
17f0 GM200GL [Quadro M6000]
+ 17fd GM200GL [Tesla M40]
10df Emulex Corporation
0720 OneConnect NIC (Skyhawk)
- 103c 1934 HP FlexFabric 20Gb 2-port 650M Adapter
- 103c 1935 HP FlexFabric 20Gb 2-port 650FLB Adapter
- 103c 21d4 HP StoreFabric CN1200E 10Gb Converged Network Adapter
- 103c 220a HP FlexFabric 10Gb 2-port 556FLR-SFP+ Adapter
- 103c 803f HP Ethernet 10Gb 2-port 557SFP+ Adapter
+ 103c 1934 FlexFabric 20Gb 2-port 650M Adapter
+ 103c 1935 FlexFabric 20Gb 2-port 650FLB Adapter
+ 103c 21d4 StoreFabric CN1200E 10Gb Converged Network Adapter
+ 103c 220a FlexFabric 10Gb 2-port 556FLR-SFP+ Adapter
+ 103c 803f Ethernet 10Gb 2-port 557SFP+ Adapter
17aa 1056 ThinkServer OCm14102-UX-L AnyFabric
17aa 1057 ThinkServer OCm14104-UX-L AnyFabric
17aa 1059 ThinkServer OCm14104-UT-L AnyFabric
@@ -10308,6 +10531,7 @@
f0e5 Zephyr LightPulse Fibre Channel Host Adapter
f0f5 Neptune LightPulse Fibre Channel Host Adapter
f100 Saturn-X: LightPulse Fibre Channel Host Adapter
+ 103c 3282 8Gb Dual-port PCI-e FC HBA
f111 Saturn-X LightPulse Fibre Channel Host Adapter
f112 Saturn-X LightPulse Fibre Channel Host Adapter
f180 LPSe12002 EmulexSecure Fibre Channel Adapter
@@ -10423,8 +10647,14 @@
5229 RTS5229 PCI Express Card Reader
1025 0813 Aspire R7-571
103c 194e ProBook 455 G1 Notebook
+ 103c 1985 Pavilion 17-e163sg Notebook PC
+ 522a RTS522A PCI Express Card Reader
5249 RTS5249 PCI Express Card Reader
103c 1909 ZBook 15
+ 524a RTS524A PCI Express Card Reader
+ 5250 RTS5250 PCI Express Card Reader
+ 525a RTS525A PCI Express Card Reader
+ 5286 RTS5286 PCI Express Card Reader
5288 RTS5288 PCI Express Card Reader
5289 RTL8411 PCI Express Card Reader
1043 1457 K55A Laptop
@@ -10438,11 +10668,12 @@
8129 RTL-8129
10ec 8129 RT8129 Fast Ethernet Adapter
11ec 8129 RTL8111/8168 PCIe Gigabit Ethernet (misconfigured)
- 8136 RTL8101E/RTL8102E PCI Express Fast Ethernet controller
+ 8136 RTL8101/2/6E PCI Express Fast/Gigabit Ethernet controller
+ 103c 1985 Pavilion 17-e163sg Notebook PC
103c 2ab1 Pavilion p6774
103c 30cc Pavilion dv6700
1179 ff64 RTL8102E PCI-E Fast Ethernet NIC
- 17c0 1053 AzureWave AW-NE766 802.11B/G/N Mini PCIe Card Model RT2700E
+ 17c0 1053 RTL8101e Medion WIM 2210 Notebook PC [MD96850]
8138 RT8139 (B/C) Cardbus Fast Ethernet Adapter
10ec 8138 RT8139 (B/C) Fast Ethernet Adapter
8139 RTL-8100/8101L/8139 PCI Fast Ethernet Adapter
@@ -10511,7 +10742,7 @@
1043 11f5 A6J-Q008
1043 16d5 U6V/U31J laptop
1043 81aa P5B
- 1043 82c6 M3A78-EH Motherboard
+ 1043 82c6 M3A78 Series Motherboard
1043 83a3 M4A785TD Motherboard
1043 8432 P8P67 and other motherboards
1043 8505 P8 series motherboard
@@ -10581,7 +10812,6 @@
0405 Wildcard TE405P (2nd Gen)
0410 Wildcard TE410P (2nd Gen)
0600 Xilinx 6 Designs (Xilinx IP)
- 2b00 Zomojo Zcard
3fc0 RME Digi96
3fc1 RME Digi96/8
3fc2 RME Digi96/8 Pro
@@ -10775,6 +11005,8 @@
127d 0000 CineView II
8485 EM8485 REALmagic DVD/MPEG-4 A/V Decoder
8486 EM8486 REALmagic DVD/MPEG-4 A/V Decoder
+# Found in Cisco DMP-4305G
+ c621 EM8621L Digital Media Processor
c622 EM8622L MPEG-4.10 (H.264) and SMPTE 421M (VC-1) A/V Decoder
1106 VIA Technologies, Inc.
0102 Embedded VIA Ethernet Controller
@@ -11010,6 +11242,7 @@
1043 8095 A7V8X Motherboard (Realtek ALC650 codec)
1043 80a1 A7V8X-X Motherboard
1043 80b0 A7V600/K8V-X/K8V Deluxe motherboard (ADI AD1980 codec [SoundMAX])
+ 1043 80f3 ASUSTek SK8V motherboard
1043 810d Asus P5VD1-X (AD1888 codec [SoundMax])
1043 812a A8V Deluxe motherboard (Realtek ALC850 codec)
10ec 8168 High Definition Audio
@@ -11989,6 +12222,7 @@
1137 012c VIC 1340 Dual 40Gb MLOM
1137 012e VIC 1227 Dual 10Gb SFP+ PCIe
1137 0137 VIC 1380 Dual 40Gb Mezzanine
+ 1137 014d VIC 1385 Dual 40Gb PCIe
0041 VIC PCIe Downstream Port
0042 VIC Management Controller
1137 0047 VIC P81E PCIe Management Controller
@@ -11996,6 +12230,7 @@
1137 00cd VIC 1285 PCIe Management Controller
1137 00ce VIC 1225T PCIe Management Controller
1137 012e VIC 1227 PCIe Management Controller
+ 1137 014d VIC 1385 PCIe Management Controller
0043 VIC Ethernet NIC
1137 0047 VIC P81E PCIe Ethernet NIC
1137 0048 VIC M81KR Mezzanine Ethernet NIC
@@ -12008,6 +12243,7 @@
1137 012c VIC 1340 MLOM Ethernet NIC
1137 012e VIC 1227 PCIe Ethernet NIC
1137 0137 VIC 1380 Mezzanine Ethernet NIC
+ 1137 014d VIC 1385 PCIe Ethernet NIC
0044 VIC Ethernet NIC Dynamic
1137 0047 VIC P81E PCIe Ethernet NIC Dynamic
1137 0048 VIC M81KR Mezzanine Ethernet NIC Dynamic
@@ -12020,6 +12256,7 @@
1137 012c VIC 1340 MLOM Ethernet NIC Dynamic
1137 012e VIC 1227 PCIe Ethernet NIC Dynamic
1137 0137 VIC 1380 Mezzanine Ethernet NIC Dynamic
+ 1137 014d VIC 1385 PCIe Ethernet NIC Dynamic
0045 VIC FCoE HBA
1137 0047 VIC P81E PCIe FCoE HBA
1137 0048 VIC M81KR Mezzanine FCoE HBA
@@ -12032,6 +12269,7 @@
1137 012c VIC 1340 MLOM FCoE HBA
1137 012e VIC 1227 PCIe FCoE HBA
1137 0137 VIC 1380 Mezzanine FCoE HBA
+ 1137 014d VIC 1385 PCIe FCoE HBA
0046 VIC SCSI Controller
1137 012a VIC M4308 SCSI Controller
004e VIC 82 PCIe Upstream Port
@@ -12040,6 +12278,7 @@
1137 012a VIC M4308 Dual 40Gb
1137 012c VIC 1340 Dual 40Gb MLOM
1137 0137 VIC 1380 Dual 40Gb Mezzanine
+ 1137 014d VIC 1385 Dual 40Gb PCIe
00cf VIC Userspace NIC
1137 004f VIC 1280 Mezzanine Userspace NIC
1137 0084 VIC 1240 MLOM Userspace NIC
@@ -12053,7 +12292,7 @@
1138 Ziatech Corporation
8905 8905 [STD 32 Bridge]
1139 Dynamic Pictures, Inc
- 0001 VGA Compatable 3D Graphics
+ 0001 VGA Compatible 3D Graphics
113a FWB Inc
113b Network Computing Devices
113c Cyclone Microsystems, Inc.
@@ -12467,6 +12706,7 @@
144d c006 vpr Matrix 170B4 CardBus bridge
0476 RL5c476 II
1014 0185 ThinkPad A/T/X Series
+ 1014 0555 ThinkPad X41
1014 056c ThinkPad Z60t
1028 014f Latitude X300 laptop
1028 0188 Inspiron 6000 laptop
@@ -12513,14 +12753,14 @@
103c 30b5 Presario V3242AU
103c 30b7 Presario V6133CL
103c 30cc Pavilion dv6700
- 103c 30cf Pavilion dv9668eg Laptop
+ 103c 30cf Pavilion dv9500/9600/9700 series
1043 1237 A6J-Q008
1043 1967 V6800V
144d c018 X20 IV
17aa 20ca ThinkPad T61
0811 R5C811
0822 R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter
- 1014 0556 ThinkPad X60s / Z60t
+ 1014 0556 ThinkPad X40 / X41 / X60s / Z60t
1014 0598 ThinkPad Z60m
1025 0121 Aspire 5920G
1028 0188 Inspiron 6000 laptop
@@ -12559,6 +12799,7 @@
1028 024f Dell Latitude e6500
103c 03b5 Presario V3242AU
103c 30b7 Presario V6133CL
+ 103c 30cf Pavilion dv9500/9600/9700 series
1183 0843 Alienware Aurora m9700
0852 xD-Picture Card Controller
1025 0121 Aspire 5920G
@@ -12686,7 +12927,6 @@
1198 Lambda Systems Inc
1199 Attachmate Corporation
0101 Advanced ISCA/PCI Adapter
- 6832 Sierra Wireless MC8780 Device
119a Mind Share, Inc.
119b Omega Micro Inc.
1221 82C092G
@@ -13721,14 +13961,14 @@
1273 Hughes Network Systems
0002 DirecPC
1274 Ensoniq
- 1171 ES1373 [AudioPCI] (also Creative Labs CT5803)
- 1371 ES1371 / Creative Labs CT2518 [AudioPCI-97]
+ 1171 ES1373 / Creative Labs CT5803 [AudioPCI]
+ 1371 ES1371 / Creative Labs CT2518/ES1373
0e11 0024 AudioPCI on Motherboard Compaq Deskpro
0e11 b1a7 ES1371, ES1373 AudioPCI
1033 80ac ES1371, ES1373 AudioPCI
1042 1854 Tazer
107b 8054 Tabor2
- 1274 1371 AudioPCI 64V/128 / Creative Sound Blaster CT4810
+ 1274 1371 AudioPCI 64V/128 / Creative CT4810/CT5803/CT5806 [Sound Blaster PCI]
1274 8001 CT4751 board
1462 6470 ES1371, ES1373 AudioPCI On Motherboard MS-6147 1.1A
1462 6560 ES1371, ES1373 AudioPCI On Motherboard MS-6156 1.10
@@ -13779,10 +14019,10 @@
8086 5643 ES1371, ES1373 AudioPCI On Motherboard Vancouver
8086 5753 ES1371, ES1373 AudioPCI On Motherboard WS440BX
5000 ES1370 [AudioPCI]
- 5880 5880B [AudioPCI]
- 1274 2000 Creative Sound Blaster AudioPCI128
+ 5880 5880B / Creative Labs CT5880
+ 1274 2000 Creative CT4810 [Sound Blaster AudioPCI 128]
1274 2003 Creative SoundBlaster AudioPCI 128
- 1274 5880 Creative Sound Blaster AudioPCI128
+ 1274 5880 Creative CT4750 [Sound Blaster PCI 128]
1274 8001 Sound Blaster 16PCI 4.1ch
1458 a000 5880 AudioPCI On Motherboard 6OXET
1462 6880 5880 AudioPCI On Motherboard MS-6188 1.00
@@ -13948,9 +14188,10 @@
8213 IT8213 IDE Controller
1458 b000 GA-EG45M-DS2H Mainboard
8330 IT8330G
- 8872 IT8874F PCI Dual Serial Port Controller
+ 8872 IT887xF PCI to ISA I/O chip with SMB, GPIO, Serial or Parallel Port
8888 IT8888F/G PCI to ISA Bridge with SMB [Golden Gate]
8889 IT8889F PCI to ISA Bridge
+ 8893 IT8893E PCIe to PCI Bridge
e886 IT8330G
1284 Sahara Networks, Inc.
1285 Platform Technologies, Inc.
@@ -15032,6 +15273,8 @@
1752 PCI-1752
1754 PCI-1754
1756 PCI-1756
+# FPGA bridge to two SJA1000
+ c302 MIOe-3680 2-Port CAN-Bus MIOe Module with Isolation Protection
13ff Silicon Spice Inc
1400 Artx Inc
1401 9432 TX
@@ -15171,7 +15414,6 @@
1412 VIA Technologies Inc.
1712 ICE1712 [Envy24] PCI Multi-Channel I/O Controller
1412 1712 Hoontech ST Audio DSP 24
- 1412 3632 M-Audio Delta Audiophile 192
1412 d630 M-Audio Delta 1010
1412 d631 M-Audio Delta DiO
1412 d632 M-Audio Delta 66
@@ -15196,6 +15438,7 @@
1412 1724 Albatron PX865PE 7.1
1412 3630 M-Audio Revolution 7.1
1412 3631 M-Audio Revolution 5.1
+ 1412 3632 M-Audio Audiophile 192
153b 1145 Aureon 7.1 Space
153b 1147 Aureon 5.1 Sky
153b 1150 PHASE 22
@@ -15443,7 +15686,7 @@
5011 T520-LL-CR Unified Wire Ethernet Controller
5012 T560-CR Unified Wire Ethernet Controller
5013 T580-CHR Unified Wire Ethernet Controller
- 5014 T580-LP-SO-CR Unified Wire Ethernet Controller
+ 5014 T580-SO-CR Unified Wire Ethernet Controller
5015 T502-BT Unified Wire Ethernet Controller
5016 T580-OCP-SO Unified Wire Ethernet Controller
5017 T520-OCP-SO Unified Wire Ethernet Controller
@@ -15460,6 +15703,15 @@
5090 T540-5090 Unified Wire Ethernet Controller
5091 T522-5091 Unified Wire Ethernet Controller
5092 T520-5092 Unified Wire Ethernet Controller
+ 5093 T580-5093 Unified Wire Ethernet Controller
+ 5094 T540-5094 Unified Wire Ethernet Controller
+ 5095 T540-5095 Unified Wire Ethernet Controller
+ 5096 T580-5096 Unified Wire Ethernet Controller
+ 5097 T520-5097 Unified Wire Ethernet Controller
+ 5098 T580-5098 Unified Wire Ethernet Controller
+ 5099 T580-5099 Unified Wire Ethernet Controller
+ 509a T520-509A Unified Wire Ethernet Controller
+ 509b T540-509B Unified Wire Ethernet Controller
5401 T520-CR Unified Wire Ethernet Controller
5402 T522-CR Unified Wire Ethernet Controller
5403 T540-CR Unified Wire Ethernet Controller
@@ -15479,7 +15731,7 @@
5411 T520-LL-CR Unified Wire Ethernet Controller
5412 T560-CR Unified Wire Ethernet Controller
5413 T580-CHR Unified Wire Ethernet Controller
- 5414 T580-LP-SO-CR Unified Wire Ethernet Controller
+ 5414 T580-SO-CR Unified Wire Ethernet Controller
5415 T502-BT Unified Wire Ethernet Controller
5416 T580-OCP-SO Unified Wire Ethernet Controller
5417 T520-OCP-SO Unified Wire Ethernet Controller
@@ -15496,6 +15748,15 @@
5490 T540-5090 Unified Wire Ethernet Controller
5491 T522-5091 Unified Wire Ethernet Controller
5492 T520-5092 Unified Wire Ethernet Controller
+ 5493 T580-5093 Unified Wire Ethernet Controller
+ 5494 T540-5094 Unified Wire Ethernet Controller
+ 5495 T540-5095 Unified Wire Ethernet Controller
+ 5496 T580-5096 Unified Wire Ethernet Controller
+ 5497 T520-5097 Unified Wire Ethernet Controller
+ 5498 T580-5098 Unified Wire Ethernet Controller
+ 5499 T580-5099 Unified Wire Ethernet Controller
+ 549a T520-509A Unified Wire Ethernet Controller
+ 549b T540-509B Unified Wire Ethernet Controller
5501 T520-CR Unified Wire Storage Controller
5502 T522-CR Unified Wire Storage Controller
5503 T540-CR Unified Wire Storage Controller
@@ -15515,7 +15776,7 @@
5511 T520-LL-CR Unified Wire Storage Controller
5512 T560-CR Unified Wire Storage Controller
5513 T580-CHR Unified Wire Storage Controller
- 5514 T580-LP-SO-CR Unified Wire Storage Controller
+ 5514 T580-SO-CR Unified Wire Storage Controller
5515 T502-BT Unified Wire Storage Controller
5516 T580-OCP-SO Unified Wire Storage Controller
5517 T520-OCP-SO Unified Wire Storage Controller
@@ -15532,6 +15793,15 @@
5590 T540-5090 Unified Wire Storage Controller
5591 T522-5091 Unified Wire Storage Controller
5592 T520-5092 Unified Wire Storage Controller
+ 5593 T580-5093 Unified Wire Storage Controller
+ 5594 T540-5094 Unified Wire Storage Controller
+ 5595 T540-5095 Unified Wire Storage Controller
+ 5596 T580-5096 Unified Wire Storage Controller
+ 5597 T520-5097 Unified Wire Storage Controller
+ 5598 T580-5098 Unified Wire Storage Controller
+ 5599 T580-5099 Unified Wire Storage Controller
+ 559a T520-509A Unified Wire Storage Controller
+ 559b T540-509B Unified Wire Storage Controller
5601 T520-CR Unified Wire Storage Controller
5602 T522-CR Unified Wire Storage Controller
5603 T540-CR Unified Wire Storage Controller
@@ -15551,7 +15821,7 @@
5611 T520-LL-CR Unified Wire Storage Controller
5612 T560-CR Unified Wire Storage Controller
5613 T580-CHR Unified Wire Storage Controller
- 5614 T580-LP-SO-CR Unified Wire Storage Controller
+ 5614 T580-SO-CR Unified Wire Storage Controller
5615 T502-BT Unified Wire Storage Controller
5616 T580-OCP-SO Unified Wire Storage Controller
5617 T520-OCP-SO Unified Wire Storage Controller
@@ -15568,6 +15838,15 @@
5690 T540-5090 Unified Wire Storage Controller
5691 T522-5091 Unified Wire Storage Controller
5692 T520-5092 Unified Wire Storage Controller
+ 5693 T580-5093 Unified Wire Storage Controller
+ 5694 T540-5094 Unified Wire Storage Controller
+ 5695 T540-5095 Unified Wire Storage Controller
+ 5696 T580-5096 Unified Wire Storage Controller
+ 5697 T520-5097 Unified Wire Storage Controller
+ 5698 T580-5098 Unified Wire Storage Controller
+ 5699 T580-5099 Unified Wire Storage Controller
+ 569a T520-509A Unified Wire Storage Controller
+ 569b T540-509B Unified Wire Storage Controller
5701 T520-CR Unified Wire Ethernet Controller
5702 T522-CR Unified Wire Ethernet Controller
5703 T540-CR Unified Wire Ethernet Controller
@@ -15587,7 +15866,7 @@
5711 T520-LL-CR Unified Wire Ethernet Controller
5712 T560-CR Unified Wire Ethernet Controller
5713 T580-CR Unified Wire Ethernet Controller
- 5714 T580-LP-SO-CR Unified Wire Ethernet Controller
+ 5714 T580-SO-CR Unified Wire Ethernet Controller
5715 T502-BT Unified Wire Ethernet Controller
5780 T540-5080 Unified Wire Ethernet Controller
5781 T540-5081 Unified Wire Ethernet Controller
@@ -15602,6 +15881,11 @@
5790 T540-5090 Unified Wire Ethernet Controller
5791 T522-5091 Unified Wire Ethernet Controller
5792 T520-5092 Unified Wire Ethernet Controller
+ 5793 T580-5093 Unified Wire Ethernet Controller
+ 5794 T540-5094 Unified Wire Ethernet Controller
+ 5795 T540-5095 Unified Wire Ethernet Controller
+ 5796 T580-5096 Unified Wire Ethernet Controller
+ 5797 T520-5097 Unified Wire Ethernet Controller
5801 T520-CR Unified Wire Ethernet Controller [VF]
5802 T522-CR Unified Wire Ethernet Controller [VF]
5803 T540-CR Unified Wire Ethernet Controller [VF]
@@ -15621,7 +15905,7 @@
5811 T520-LL-CR Unified Wire Ethernet Controller [VF]
5812 T560-CR Unified Wire Ethernet Controller [VF]
5813 T580-CHR Unified Wire Ethernet Controller [VF]
- 5814 T580-LP-SO-CR Unified Wire Ethernet Controller [VF]
+ 5814 T580-SO-CR Unified Wire Ethernet Controller [VF]
5815 T502-BT Unified Wire Ethernet Controller [VF]
5816 T580-OCP-SO Unified Wire Ethernet Controller [VF]
5817 T520-OCP-SO Unified Wire Ethernet Controller [VF]
@@ -15638,6 +15922,15 @@
5890 T540-5090 Unified Wire Ethernet Controller [VF]
5891 T522-5091 Unified Wire Ethernet Controller [VF]
5892 T520-5092 Unified Wire Ethernet Controller [VF]
+ 5893 T580-5093 Unified Wire Ethernet Controller [VF]
+ 5894 T540-5094 Unified Wire Ethernet Controller [VF]
+ 5895 T540-5095 Unified Wire Ethernet Controller [VF]
+ 5896 T580-5096 Unified Wire Ethernet Controller [VF]
+ 5897 T520-5097 Unified Wire Ethernet Controller [VF]
+ 5898 T580-5098 Unified Wire Ethernet Controller [VF]
+ 5899 T580-5099 Unified Wire Ethernet Controller [VF]
+ 589a T520-509A Unified Wire Ethernet Controller [VF]
+ 589b T540-509B Unified Wire Ethernet Controller [VF]
a000 PE10K Unified Wire Ethernet Controller
1426 Storage Technology Corp.
1427 Better On-Line Solutions
@@ -15701,12 +15994,15 @@
9111 PCI-9111
9113 PCI-9113
9114 PCI-9114
+# 2-16 MB SRAM, 4x UART, I2C, misc I/O
+ a001 ADi-BSEC
# nee Loronix Information Systems Inc.
144b Verint Systems Inc.
144c Catalina Research Inc
144d Samsung Electronics Co Ltd
1600 Apple PCIe SSD
a800 XP941 PCIe SSD
+ a802 NVMe SSD Controller
a820 NVMe SSD Controller 171X
1028 1f95 Express Flash NVMe XS1715 SSD 400GB
1028 1f96 Express Flash NVMe XS1715 SSD 800GB
@@ -15717,6 +16013,12 @@
1028 1fbb Express Flash NVMe SM1715 1.6TB SFF
1028 1fbc Express Flash NVMe SM1715 1.6TB AIC
a821 NVMe SSD Controller 172X
+ 1028 1fb7 Express Flash NVMe PM1725 3.2TB SFF
+ 1028 1fb8 Express Flash NVMe PM1725 3.2TB AIC
+ 1028 1fb9 Express Flash NVMe PM1725 6.4TB AIC
+ 1028 1fc1 Express Flash NVMe PM1725 800GB SFF
+ 1028 1fc2 Express Flash NVMe PM1725 1.6TB SFF
+ 1028 1fc4 Express Flash NVMe PM1725 1.6TB AIC
144e OLITEC
144f Askey Computer Corp.
1450 Octave Communications Ind.
@@ -15787,7 +16089,6 @@
1485 ERMA - Electronic GmBH
1486 L3 Communications Telemetry & Instrumentation
1487 MARQUETTE Medical Systems
-1488 KONTRON Electronik GmBH
1489 KYE Systems Corporation
148a OPTO
148b INNOMEDIALOGIC Inc.
@@ -15826,9 +16127,9 @@
14a1 Systembase Co Ltd
14a2 Millennium Engineering Inc
14a3 Maverick Networks
-# registered as GVC/BCM Advanced Research
-14a4 Broadcom Corporation (Wrong ID)
- 4318 BCM4318 [AirForce One 54g] 802.11g Wireless LAN Controller
+14a4 Lite-On Technology Corporation
+# Wrong vendor ID used
+ 4318 Broadcom BCM4318 [AirForce One 54g] 802.11g WLAN Controller
14a5 XIONICS Document Technologies Inc
14a6 INOVA Computers GmBH & Co KG
14a7 MYTHOS Systems Inc
@@ -16118,6 +16419,7 @@
1656 NetXtreme BCM5718 Gigabit Ethernet PCIe
1657 NetXtreme BCM5719 Gigabit Ethernet PCIe
103c 169d Ethernet 1Gb 4-port 331FLR Adapter
+ 103c 22be Ethernet 1Gb 4-port 331i Adapter
1659 NetXtreme BCM5721 Gigabit Ethernet PCI Express
1014 02c6 eServer xSeries server mainboard
1028 01e6 PowerEdge 860
@@ -16186,9 +16488,9 @@
167b NetXtreme BCM5755 Gigabit Ethernet PCI Express
103c 280a DC5750 Microtower
167d NetXtreme BCM5751M Gigabit Ethernet PCI Express
- 1014 0577 ThinkPad Z60t
- 103c 0934 HP nx8220
- 103c 0940 HP Compaq nw8240 Mobile Workstation
+ 1014 0577 ThinkPad X41 / Z60t
+ 103c 0934 nx8220
+ 103c 0940 Compaq nw8240 Mobile Workstation
17aa 2081 ThinkPad R60e
167e NetXtreme BCM5751F Fast Ethernet PCI Express
167f NetLink BCM5787F Fast Ethernet PCI Express
@@ -16211,15 +16513,15 @@
168d NetXtreme II BCM57840 10/20 Gigabit Ethernet
168e NetXtreme II BCM57810 10 Gigabit Ethernet
103c 1798 Flex-10 10Gb 2-port 530FLB Adapter [Meru]
- 103c 17a5 HP Flex-10 10Gb 2-port 530M Adapter
- 103c 18d3 HP Ethernet 10Gb 2-port 530T Adapter
- 103c 1930 HP FlexFabric 10Gb 2-port 534FLR-SFP+ Adapter
- 103c 1931 HP StoreFabric CN1100R Dual Port Converged Network Adapter
- 103c 1932 HP FlexFabric 10Gb 2-port 534FLB Adapter
- 103c 1933 HP FlexFabric 10Gb 2-port 534M Adapter
- 103c 193a HP FlexFabric 10Gb 2-port 533FLR-T Adapter
- 103c 3382 HP Ethernet 10Gb 2-port 530FLR-SFP+ Adapter
- 103c 339d HP Ethernet 10Gb 2-port 530SFP+ Adapter
+ 103c 17a5 Flex-10 10Gb 2-port 530M Adapter
+ 103c 18d3 Ethernet 10Gb 2-port 530T Adapter
+ 103c 1930 FlexFabric 10Gb 2-port 534FLR-SFP+ Adapter
+ 103c 1931 StoreFabric CN1100R Dual Port Converged Network Adapter
+ 103c 1932 FlexFabric 10Gb 2-port 534FLB Adapter
+ 103c 1933 FlexFabric 10Gb 2-port 534M Adapter
+ 103c 193a FlexFabric 10Gb 2-port 533FLR-T Adapter
+ 103c 3382 Ethernet 10Gb 2-port 530FLR-SFP+ Adapter
+ 103c 339d Ethernet 10Gb 2-port 530SFP+ Adapter
1690 NetXtreme BCM57760 Gigabit Ethernet PCIe
1691 NetLink BCM57788 Gigabit Ethernet PCIe
1028 04aa XPS 8300
@@ -16245,14 +16547,14 @@
16a0 NetLink BCM5785 Fast Ethernet
16a1 BCM57840 NetXtreme II 10 Gigabit Ethernet
16a2 BCM57840 NetXtreme II 10/20-Gigabit Ethernet
- 103c 1916 HP FlexFabric 20Gb 2-port 630FLB Adapter
- 103c 1917 HP FlexFabric 20Gb 2-port 630M Adapter
+ 103c 1916 FlexFabric 20Gb 2-port 630FLB Adapter
+ 103c 1917 FlexFabric 20Gb 2-port 630M Adapter
103c 2231 3820C 10/20Gb Converged Network Adapter
103c 22fa FlexFabric 10Gb 2-port 536FLB Adapter
16a3 NetXtreme BCM57786 Gigabit Ethernet PCIe
16a4 BCM57840 NetXtreme II Ethernet Multi Function
- 103c 1916 HP NPAR 20Gb 2-port 630FLB Adapter
- 103c 1917 HP NPAR 20Gb 2-port 630M Adapter
+ 103c 1916 NPAR 20Gb 2-port 630FLB Adapter
+ 103c 1917 NPAR 20Gb 2-port 630M Adapter
103c 2231 3820C 10/20Gb Converged Network Adapter (NPAR 1.5)
103c 22fa FlexFabric 10Gb 2-port 536FLB Adapter (NPAR 1.5)
# The Broadcom 57800 device has two 1Gig ports and two 10Gig ports. The subsystem information can be used to differentiate.
@@ -16298,32 +16600,32 @@
103c 703b NC373i Integrated Multifunction Gigabit Server Adapter
103c 703d NC373F PCI Express Multifunction Gigabit Server Adapter
16ad NetXtreme II BCM57840 10/20 Gigabit Ethernet Virtual Function
- 103c 1916 HP FlexFabric 20Gb 2-port 630FLB Adapter
- 103c 1917 HP FlexFabric 20Gb 2-port 630M Adapter
+ 103c 1916 FlexFabric 20Gb 2-port 630FLB Adapter
+ 103c 1917 FlexFabric 20Gb 2-port 630M Adapter
103c 2231 3820C 10/20Gb Converged Network Adapter (SR-IOV VF)
103c 22fa FlexFabric 10Gb 2-port 536FLB Adapter (SR-IOV VF)
16ae NetXtreme II BCM57810 10 Gigabit Ethernet Multi Function
- 103c 1798 HP NPAR 10Gb 2-port 530FLB Adapter
- 103c 17a5 HP NPAR 10Gb 2-port 530M Adapter
- 103c 18d3 HP NPAR 10Gb 2-port 530T Adapter
- 103c 1930 HP NPAR 10Gb 2-port 534FLR-SFP+ Adapter
- 103c 1931 HP NPAR CN1100R Dual Port Converged Network Adapter
- 103c 1932 HP NPAR 10Gb 2-port 534FLB Adapter
- 103c 1933 HP NPAR 10Gb 2-port 534M Adapter
- 103c 193a HP NPAR 10Gb 2-port 533FLR-T Adapter
- 103c 3382 HP NPAR 10Gb 2-port 530FLR-SFP+ Adapter
- 103c 339d HP NPAR 10Gb 2-port 530SFP+ Adapter
+ 103c 1798 NPAR 10Gb 2-port 530FLB Adapter
+ 103c 17a5 NPAR 10Gb 2-port 530M Adapter
+ 103c 18d3 NPAR 10Gb 2-port 530T Adapter
+ 103c 1930 NPAR 10Gb 2-port 534FLR-SFP+ Adapter
+ 103c 1931 NPAR CN1100R Dual Port Converged Network Adapter
+ 103c 1932 NPAR 10Gb 2-port 534FLB Adapter
+ 103c 1933 NPAR 10Gb 2-port 534M Adapter
+ 103c 193a NPAR 10Gb 2-port 533FLR-T Adapter
+ 103c 3382 NPAR 10Gb 2-port 530FLR-SFP+ Adapter
+ 103c 339d NPAR 10Gb 2-port 530SFP+ Adapter
16af NetXtreme II BCM57810 10 Gigabit Ethernet Virtual Function
- 103c 1798 HP Flex-10 10Gb 2-port 530FLB Adapter
- 103c 17a5 HP Flex-10 10Gb 2-port 530M Adapter
- 103c 18d3 HP Ethernet 10Gb 2-port 530T Adapter
- 103c 1930 HP FlexFabric 10Gb 2-port 534FLR-SFP+ Adapter
- 103c 1931 HP StoreFabric CN1100R Dual Port Converged Network Adapter
- 103c 1932 HP FlexFabric 10Gb 2-port 534FLB Adapter
- 103c 1933 HP FlexFabric 10Gb 2-port 534M Adapter
- 103c 193a HP FlexFabric 10Gb 2-port 533FLR-T Adapter
- 103c 3382 HP Ethernet 10Gb 2-port 530FLR-SFP+ Adapter
- 103c 339d HP Ethernet 10Gb 2-port 530SFP+ Adapter
+ 103c 1798 Flex-10 10Gb 2-port 530FLB Adapter
+ 103c 17a5 Flex-10 10Gb 2-port 530M Adapter
+ 103c 18d3 Ethernet 10Gb 2-port 530T Adapter
+ 103c 1930 FlexFabric 10Gb 2-port 534FLR-SFP+ Adapter
+ 103c 1931 StoreFabric CN1100R Dual Port Converged Network Adapter
+ 103c 1932 FlexFabric 10Gb 2-port 534FLB Adapter
+ 103c 1933 FlexFabric 10Gb 2-port 534M Adapter
+ 103c 193a FlexFabric 10Gb 2-port 533FLR-T Adapter
+ 103c 3382 Ethernet 10Gb 2-port 530FLR-SFP+ Adapter
+ 103c 339d Ethernet 10Gb 2-port 530SFP+ Adapter
16b0 NetXtreme BCM57761 Gigabit Ethernet PCIe
16b1 NetLink BCM57781 Gigabit Ethernet PCIe
1849 96b1 Z77 Extreme4 motherboard
@@ -16348,6 +16650,14 @@
103c 1321 Core I/O LAN/SCSI Combo [AB314A]
14e4 0009 NetXtreme BCM5703 1000Base-T
14e4 000a NetXtreme BCM5703 1000Base-SX
+ 16c8 BCM57301 NetXtreme-C Single-port 10Gb Ethernet
+ 16c9 BCM57302 NetXtreme-C Dual-port 10Gb/25Gb Ethernet
+ 16ca BCM57304 NetXtreme-C Dual-port 10Gb/25Gb/40Gb/50Gb Ethernet
+ 16cb BCM57304 NetXtreme-C Ethernet Virtual Function
+ 16d0 BCM57402 NetXtreme-E Dual-port 10Gb Ethernet
+ 16d1 BCM57404 NetXtreme-E Dual-port 10Gb/25Gb Ethernet
+ 16d2 BCM57406 NetXtreme-E Dual-port 10GBase-T Ethernet
+ 16d3 BCM57404 NetXtreme-E Ethernet Virtual Function
16dd NetLink BCM5781 Gigabit Ethernet PCI Express
16f3 NetXtreme BCM5727 Gigabit Ethernet PCIe
16f7 NetXtreme BCM5753 Gigabit Ethernet PCI Express
@@ -16548,6 +16858,7 @@
43a0 BCM4360 802.11ac Wireless Network Adapter
43a1 BCM4360 802.11ac Wireless Network Adapter
43a2 BCM4360 802.11ac Wireless Network Adapter
+ 43a3 BCM4350 802.11ac Wireless Network Adapter
43a9 BCM43217 802.11b/g/n
43aa BCM43131 802.11b/g/n
43b1 BCM4352 802.11ac Wireless Network Adapter
@@ -16562,6 +16873,7 @@
4401 BCM4401 100Base-T
1025 0035 TravelMate 660
1025 0064 Extensa 3000 series laptop
+ 1028 8127 Dimension 2400
103c 08b0 tc1100 tablet
1043 80a8 A7V8X motherboard
4402 BCM4402 Integrated 10/100BaseT
@@ -16778,6 +17090,8 @@
2464 HSF 56k Data/Fax/Voice Modem (Mob SmartDAA)
2465 HSF 56k Data/Fax/Voice/Spkp (w/HS) Modem (Mob SmartDAA)
2466 HSF 56k Data/Fax/Voice/Spkp Modem (Mob SmartDAA)
+ 2702 HSFi modem RD01-D270
+ 1028 8d88 SmartHSFi V92 56K PCI Modem
2f00 HSF 56k HSFi Modem
13e0 8d84 IBM HSFi V.90
13e0 8d85 Compaq Stinger
@@ -16972,8 +17286,8 @@
1320 10bd SURECOM EP-320X-S 100/10M Ethernet PCI Adapter
0891 MTD-8xx 100/10M Ethernet PCI Adapter
1517 ECHOTEK Corp
-# nee PEP MODULAR Computers GmbH
-1518 Kontron Modular Computers GmbH
+# old ID, now 1059
+1518 Kontron
1519 TELEFON AKTIEBOLAGET LM Ericsson
151a Globetek
1002 PCI-1002
@@ -17194,8 +17508,8 @@
158d Point Multimedia Systems
158e Lara Technology Inc
158f Ditect Coop
-# nee 3PAR Inc.
-1590 Hewlett-Packard Company
+# formerly 3PAR Inc.
+1590 Hewlett Packard Enterprise
0001 Eagle Cluster Manager
0002 Osprey Cluster Manager
0003 Harrier Cluster Manager
@@ -17263,6 +17577,9 @@
01ff MT27600 Family [Connect-IB Flash Recovery]
0209 MT27700 Family [ConnectX-4 Flash Recovery]
020b MT27710 Family [ConnectX-4 Lx Flash Recovery]
+ 020d MT28800 Family [ConnectX-5 Flash Recovery]
+ 0262 MT27710 [ConnectX-4 Lx Programmable] EN
+ 0263 MT27710 [ConnectX-4 Lx Programmable Virtual Function] EN
1002 MT25400 Family [ConnectX-2 Virtual Function]
1003 MT27500 Family [ConnectX-3]
103c 1777 InfiniBand FDR/EN 10/40Gb Dual Port 544FLR-QSFP Adapter (Rev Cx)
@@ -17276,6 +17593,7 @@
1007 MT27520 Family [ConnectX-3 Pro]
103c 22f3 InfiniBand FDR/Ethernet 10Gb/40Gb 2-port 544+QSFP Adapter
103c 22f4 InfiniBand FDR/Ethernet 10Gb/40Gb 2-port 544+FLR-QSFP Adapter
+ 103c 801f Ethernet 10G 2-port 546SFP+ Adapter
117c 0090 FastFrame NQ41
117c 0091 FastFrame NQ42
117c 0092 FastFrame NQ11
@@ -17294,8 +17612,17 @@
1014 MT27700 Family [ConnectX-4 Virtual Function]
1015 MT27710 Family [ConnectX-4 Lx]
1016 MT27710 Family [ConnectX-4 Lx Virtual Function]
- 1017 MT27640 Family
- 1018 MT27641 Family
+ 1017 MT27800 Family [ConnectX-5, PCIe 3.0]
+ 1018 MT28800 Family [ConnectX-5 Virtual Function]
+ 1019 MT28800 Family [ConnectX-5, PCIe 4.0]
+ 101a MT28830
+ 101b MT28831
+ 101c MT28840
+ 101d MT28841
+ 101e MT28850
+ 101f MT28851
+ 1020 MT28860
+ 1021 MT28861
5274 MT21108 InfiniBridge
5a44 MT23108 InfiniHost
5a45 MT23108 [Infinihost HCA Flash Recovery]
@@ -17321,9 +17648,20 @@
15b3 0018 HP 10 GbE PCI-e G2 Dual-Port NIC (rev C1)
675a MT25408 [ConnectX EN 10GigE 10GBaseT, PCIe Gen2 5GT/s]
6764 MT26468 [ConnectX EN 10GigE, PCIe 2.0 5GT/s Virtualization+]
- 103c 3313 HP NC542m Dual Port Flex-10 10GbE BLc Adapter
+ 103c 3313 NC542m Dual Port Flex-10 10GbE BLc Adapter
676e MT26478 [ConnectX EN 40GigE, PCIe 2.0 5GT/s]
6778 MT26488 [ConnectX VPI PCIe 2.0 5GT/s - IB DDR / 10GigE Virtualization+]
+ 7101 NPS-400 configuration and management interface
+ 7102 NPS-400 network interface PF
+ 7103 NPS-400 network interface VF
+ 7121 NPS-600 configuration and management interface
+ 7122 NPS-600 network interface PF
+ 7123 NPS-600 network interface VF
+# SwitchX-2, 40GbE switch
+ c738 MT51136
+ caf1 ConnectX-4 CAPI Function
+# Spectrum, 100GbE Switch
+ cb84 MT52100
15b4 CCI/TRIAD
15b5 Cimetrics Inc
15b6 Texas Memory Systems Inc
@@ -17502,15 +17840,15 @@
1642 Bitland(ShenZhen) Information Technology Co., Ltd.
1657 Brocade Communications Systems, Inc.
0013 425/825/42B/82B 4Gbps/8Gbps PCIe dual port FC HBA
- 103c 1742 HP 82B 8Gbps dual port FC HBA
- 103c 1744 HP 42B 4Gbps dual port FC HBA
+ 103c 1742 82B 8Gbps dual port FC HBA
+ 103c 1744 42B 4Gbps dual port FC HBA
1657 0014 425/825 4Gbps/8Gbps PCIe dual port FC HBA
0014 1010/1020/1007/1741 10Gbps CNA
1657 0014 1010/1020/1007/1741 10Gbps CNA - FCOE
1657 0015 1010/1020/1007/1741 10Gbps CNA - LL
0017 415/815/41B/81B 4Gbps/8Gbps PCIe single port FC HBA
- 103c 1741 HP 41B 4Gbps single port FC HBA
- 103c 1743 HP 81B 8Gbps single port FC HBA
+ 103c 1741 41B 4Gbps single port FC HBA
+ 103c 1743 81B 8Gbps single port FC HBA
1657 0014 415/815 4Gbps/8Gbps single port PCIe FC HBA
0021 804 8Gbps FC HBA for HP Bladesystem c-class
# AnyIO Adapter
@@ -17797,6 +18135,7 @@
0777 4005 SR71-15 802.11an Mini PCI Adapter
1186 3a7a DWA-552 802.11n Xtreme N Desktop Adapter (rev A2)
1186 3a7d DWA-552 802.11n Xtreme N Desktop Adapter (rev A3)
+ 168c 2096 Compex WLM200NX / Wistron DNMA-92
002a AR928X Wireless Network Adapter (PCI-Express)
0777 4f05 SR71-X 802.11abgn Wireless ExpressCard Adapter [AR9280]
103c 3041 AR5BHB92-H 802.11abgn Wireless Half-size Mini PCIe Card [AR9280]
@@ -17837,8 +18176,10 @@
1a56 2000 Killer Wireless-N 1102 Half-size Mini PCIe Card [AR9382]
1a56 2001 Killer Wireless-N 1103 Half-size Mini PCIe Card [AR9380]
0032 AR9485 Wireless Network Adapter
+ 1028 0208 Wireless 1506 WLAN Half Mini-Card
103c 1838 AR9485/HB125 802.11bgn 1×1 Wi-Fi Adapter
105b e044 Unex DHXA-225
+ 1a3b 1186 AW-NE186H
0033 AR9580 Wireless Network Adapter
0034 AR9462 Wireless Network Adapter
1a56 2003 Killer Wireless-N 1202 Half-size Mini PCIe Card
@@ -17849,6 +18190,9 @@
003c QCA986x/988x 802.11ac Wireless Network Adapter
003e QCA6174 802.11ac Wireless Network Adapter
1a56 1525 Killer N1525 Wireless-AC
+ 0040 QCA9980/9990 802.11ac Wireless Network Adapter
+ 0041 QCA6164 802.11ac Wireless Network Adapter
+ 0050 QCA9887 802.11ac Wireless Network Adapter
0207 AR5210 Wireless Network Adapter [AR5000 802.11a]
1014 AR5212 802.11abg NIC
1014 058a ThinkPad 11a/b/g Wireless LAN Mini Express Adapter (AR5BXB6)
@@ -17874,6 +18218,8 @@
0001 SafeXcel 1140
000a SafeXcel 1841
1141 SafeXcel 1141
+# misused vendor ID 0001
+ 0001 0001 SafeXcel 1141 v. 1.1
1841 SafeXcel 1842
16af SparkLAN Communications, Inc.
16b4 Aspex Semiconductor Ltd
@@ -18139,6 +18485,8 @@
6816 TW6816 multimedia video controller
# channel 8 of 8
6817 TW6816 multimedia video controller
+# Example MuniPCI-E card: http://www.commell.com.tw/product/surveillance/MPX-6864.htm
+ 6864 TW6864 multimedia video controller
1799 Belkin
6001 F5D6001 Wireless PCI Card [Realtek RTL8180]
6020 F5D6020 v3000 Wireless PCMCIA Card [Realtek RTL8180]
@@ -18192,6 +18540,11 @@
1170 ARC-1170 24-Port PCI-X to SATA RAID Controller
1201 ARC-1200 2-Port PCI-Express to SATA II RAID Controller
1210 ARC-1210 4-Port PCI-Express to SATA RAID Controller
+ 1214 ARC-12x4 PCIe 2.0 to SAS/SATA 6Gb RAID Controller
+ 17d3 1214 ARC-1214 4-Port PCIe 2.0 to SAS/SATA 6Gb RAID Controller
+ 17d3 1224 ARC-1224 8-Port PCIe 2.0 to SAS/SATA 6Gb RAID Controller
+ 17d3 1264 ARC-1264 12/16 Port PCIe 2.0 to SATA 6Gb RAID Controller
+ 17d3 1284 ARC-1284 24 Port PCIe 2.0 to SATA 6Gb RAID Controller
1220 ARC-1220 8-Port PCI-Express to SATA RAID Controller
1222 ARC-1222 8-Port PCI-Express to SAS/SATA II RAID Controller
1230 ARC-1230 12-Port PCI-Express to SATA RAID Controller
@@ -18199,9 +18552,22 @@
1280 ARC-1280/1280ML 24-Port PCI-Express to SATA II RAID Controller
17d3 1221 ARC-1221 8-Port PCI-Express to SATA RAID Controller
1300 ARC-1300ix-16 16-Port PCI-Express to SAS Non-RAID Host Adapter
- 1680 ARC-1680 8 port PCIe/PCI-X to SAS/SATA II RAID Controller
+ 1320 ARC-1320 8/16 Port PCIe 2.0 to SAS/SATA 6Gb Non-RAID Host Adapter
+ 1330 ARC-1330 16 Port PCIe 3.0 to SAS/SATA 12Gb Non-RAID Host Adapter
+ 1680 ARC-1680 series PCIe to SAS/SATA 3Gb RAID Controller
17d3 1212 ARC-1212 4-Port PCIe to SAS/SATA II RAID Controller
- 1880 ARC-1880 8/12 port PCIe/PCI-X to SAS/SATA II RAID Controller
+ 17d3 1222 ARC-1222 8-Port PCIe to SAS/SATA 3Gb RAID Controller
+ 17d3 1680 ARC-1680 8/12/16/24 Port PCIe to SAS/SATA 3Gb RAID Controller
+ 1880 ARC-188x series PCIe 2.0/3.0 to SAS/SATA 6/12Gb RAID Controller
+ 17d3 1213 ARC-1213 4-Port PCIe 2.0 to SAS/SATA 6Gb RAID Controller
+ 17d3 1215 ARC-1215 4-Port PCIe 3.0 to SAS/SATA 6Gb RAID Controller
+ 17d3 1216 ARC-1216 4-Port PCIe 3.0 to SAS/SATA 12Gb RAID Controller
+ 17d3 1223 ARC-1223 8-Port PCIe 2.0 to SAS/SATA 6Gb RAID Controller
+ 17d3 1225 ARC-1225 8-Port PCIe 3.0 to SAS/SATA 6Gb RAID Controller
+ 17d3 1226 ARC-1226 8-Port PCIe 3.0 to SAS/SATA 12Gb RAID Controller
+ 17d3 1880 ARC-1880 8/12/16/24 Port PCIe 2.0 to SAS/SATA 6Gb RAID Controller
+ 17d3 1882 ARC-1882 8/12/16/24 Port PCIe 3.0 to SAS/SATA 6Gb RAID Controller
+ 17d3 1883 ARC-1883 8/12/16/24 Port PCIe 3.0 to SAS/SATA 12Gb RAID Controller
# nee Neterion Inc., previously S2io Inc.
17d5 Exar Corp.
5731 Xframe 10-Gigabit Ethernet PCI-X
@@ -18308,6 +18674,7 @@
13d1 abe3 miniPCI Pluscom 802.11 a/b/g
1458 e933 GN-WI01GS
1458 e934 GN-WP01GS
+ 1462 b833 MP54G5 (MS-6833B)
1737 0055 WMP54G v4.1
1799 700e F5D7000 v6000 Wireless G Desktop Card
1799 701e F5D7010 v6000 Wireless G Notebook Card
@@ -18353,6 +18720,7 @@
5390 RT5390 Wireless 802.11n 1T/1R PCIe
103c 1636 U98Z077.00 Half-size Mini PCIe Card
5392 RT5392 PCIe Wireless Network Adapter
+ 539b RT5390R 802.11bgn PCIe Wireless Network Adapter
539f RT5390 [802.11 b/g/n 1T1R G-band PCI Express Single Chip]
103c 1637 Pavilion DM1Z-3000 PCIe wireless card
5592 RT5592 PCIe Wireless Network Adapter
@@ -18381,6 +18749,8 @@
1849 ASRock Incorporation
184a Thales Computers
1100 MAX II cPLD
+1850 Advantest Corporation
+ 0048 EK220-66401 Computer Interface Card
1851 Microtune, Inc.
1852 Anritsu Corp.
1853 SMSC Automotive Infotainment System Group
@@ -18544,6 +18914,7 @@
0135 NT20E2-PTP Network Adapter 2x10Gb
0145 NT40E3-4-PTP Network Adapter 4x10Gb
0155 NT100E3-1-PTP Network Adapter 1x100Gb
+ 0165 NT80E3-2-PTP Network Adapter 2x40Gb
0175 NT20E3-2-PTP Network Adapter 2x10Gb
18f6 NextIO
1000 [Nexsis] Switch Virtual P2P PCIe Bridge
@@ -18605,6 +18976,9 @@
0013 SH7757 PCIe Switch [PS]
0014 uPD720201 USB 3.0 Host Controller
0015 uPD720202 USB 3.0 Host Controller
+ 001a SH7758 PCIe-PCI Bridge [PPB]
+ 001b SH7758 PCIe End-Point [PBI]
+ 001d SH7758 PCIe Switch [PS]
1919 Soltek Computer Inc.
1923 Sangoma Technologies Corp.
0040 A200/Remora FXO/FXS Analog AFT card
@@ -18688,13 +19062,16 @@
1924 8007 SFN7322F-R2 Precision Time SFP+ Server Adapter
1924 8009 SFN7x22F-R2 Flareon Ultra 7000 Series 10G Adapter
1924 800a SFN7x02F-R2 Flareon 7000 Series 10G Adapter
- 1924 800b SFN7x22F-R3 Flareon Ultra 7000 Series 10G Adapter
1924 800c SFN7x22F-R3 Flareon Ultra 7000 Series 10G Adapter
1924 800d SFN7x02F-R3 Flareon 7000 Series 10G Adapter
+ 1924 8010 SFA7942Q-R1 QSFP+ AOE Adapter
0923 SFC9140
1924 800b SFN7x42Q-R1 Flareon Ultra 7000 Series 10/40G Adapter
1924 800e SFN7x42Q-R2 Flareon Ultra 7000 Series 10/40G Adapter
1924 800f SFN7xx4F-R1 Flareon Ultra 7000 Series 10G Adapter
+ 0a03 SFC9220
+ 1924 8012 SFN8522-R1 Flareon Ultra 8000 Series 10G Adapter
+ 1924 8014 SFN8542-R1 Flareon Ultra 8000 Series 10/40G Adapter
1803 SFC9020 Virtual Function [Solarstorm]
1813 SFL9021 Virtual Function [Solarstorm]
1903 SFC9120 Virtual Function
@@ -18827,6 +19204,8 @@
1a56 1201 Killer E2100 Gigabit Ethernet Controller
# PCIe interface for emulator
fc02 RedStone
+# CFI device over PCIe
+ fc03 CFI
1958 Faster Technology, LLC.
1959 PA Semi, Inc
a000 PA6T Core
@@ -18861,6 +19240,7 @@
1073 AR8151 v1.0 Gigabit Ethernet
1083 AR8151 v2.0 Gigabit Ethernet
1090 AR8162 Fast Ethernet
+ 1043 108d VivoBook X202E, X202EV
1091 AR8161 Gigabit Ethernet
1043 1477 N56VZ
10a0 QCA8172 Fast Ethernet
@@ -18870,6 +19250,7 @@
2062 AR8152 v2.0 Fast Ethernet
# E2200, E2201, E2205
e091 Killer E220x Gigabit Ethernet Controller
+ e0a1 Killer E2400 Gigabit Ethernet Controller
196a Sensory Networks Inc.
0101 NodalCore C-1000 Content Classification Accelerator
0102 NodalCore C-2000 Content Classification Accelerator
@@ -18931,6 +19312,7 @@
8521 AU8521 TV card
# nee ServerEngines Corp.
19a2 Emulex Corporation
+ 0120 x1 PCIe Gen2 Bridge[Pilot4]
0200 BladeEngine 10Gb PCI-E iSCSI adapter
0201 BladeEngine 10Gb PCIe Network Adapter
0211 BladeEngine2 10Gb Gen2 PCIe Network Adapter
@@ -19075,6 +19457,7 @@
0001 Vulcan SP HT6210 10-Gigabit Ethernet (rev 02)
1a88 MEN Mikro Elektronik
4d45 Multifunction IP core
+1a8a StarBridge, Inc.
1a8c Verigy Pte. Ltd.
1100 E8001-66443 PCI Express CIC
1a8e DRS Technologies
@@ -19260,6 +19643,8 @@
1b85 OCZ Technology Group, Inc.
1041 RevoDrive 3 X2 PCI-Express SSD 240 GB (Marvell Controller)
8788 RevoDrive Hybrid
+1b94 Signatec / Dynamic Signals Corp
+ e400 PX14400 Dual Xilinx Virtex5 based Digitizer
1b96 Western Digital
1b9a XAVi Technologies Corp.
1bad ReFLEX CES
@@ -19277,6 +19662,12 @@
1bb1 6511 Nytro XH6550-2GB DRAM
# 8GB variant of Nytro PCIe controller
1bb1 6512 Nytro XH6550-8GB DRAM
+# 1.5 TB Nytro PCIe controller
+ 1bb1 6521 Nytro XP6500-8A1536 1.5TB
+# 2TB Nytro PCIe controller
+ 1bb1 6522 Nytro XP6500-8A2048
+# 4TB Nytro PCIe controller
+ 1bb1 6523 Nytro XP6500-8A4096
1bb3 Bluecherry
4304 BC-04120A MPEG4 4 port video encoder / decoder
4309 BC-08240A MPEG4 4 port video encoder / decoder
@@ -19299,6 +19690,7 @@
1101 OmniBus II PCIe Multi-Protocol Interface Card
1102 OmniBusBox II Multi-Protocol Interface Core
1103 OmniBus II cPCIe/PXIe Multi-Protocol Interface Card
+1bd4 Inspur Electronic Information Industry Co., Ltd.
1bee IXXAT Automation GmbH
0003 CAN-IB200/PCIe
1bf4 VTI Instruments Corporation
@@ -19322,6 +19714,8 @@
00a4 FBC4XGG3 Capture 4x10Gb
00a5 FBC2XLG Capture 2x40Gb
00a6 FBC1CG Capture 1x100Gb
+ 00a9 FBC2XGHH Capture 2x10Gb
+ 00af Capture slave device
# Used on V120 VME Crate Controller
1c32 Highland Technology, Inc.
1c33 Daktronics, Inc
@@ -19334,6 +19728,12 @@
# A Western Digital Subsidiary
1c58 HGST, Inc.
0003 Ultrastar SN100 Series NVMe SSD
+ 1014 04f5 PCIe3 1.6TB NVMe Adapter
+ 1014 04f6 PCIe3 3.2TB NVMe Adapter
+# http://www.nicevt.ru/ (in Russian)
+1c63 Science and Research Centre of Computer Technology (JSC "NICEVT")
+# http://www.radiotec.ru/catalog.php?cat=jr8&art=14109
+ 0008 K1927BB1Ya [EC8430] Angara Interconnection Network Adapter
1c7e TTTech Computertechnik AG
0200 zFAS Debug Port
1c7f Elektrobit Austria GmbH
@@ -19345,11 +19745,21 @@
0100 CAN-PCIe-02
1cd2 SesKion GmbH
0301 Simulyzer-RT CompactPCI Serial DIO-1 card
+ 0302 Simulyzer-RT CompactPCI Serial PSI5-ECU-1 card
+ 0303 Simulyzer-RT CompactPCI Serial PSI5-SIM-1 card
+ 0304 Simulyzer-RT CompactPCI Serial PWR-ANA-1 card
+1cdd secunet Security Networks AG
1ce4 Exablaze
0001 ExaNIC X4
0002 ExaNIC X2
+ 0003 ExaNIC X10
+ 0004 ExaNIC X10-GM
+ 0005 ExaNIC X40
1cf7 Subspace Dynamics
1d00 Pure Storage
+1d1d CNEX Labs
+ 1f1f QEMU NVM Express LightNVM Controller
+ 2807 8800 series NVMe SSD
# CEM Solutions Pvt. Ltd.
1d21 Allo
1d26 Kalray Inc.
@@ -19358,8 +19768,10 @@
1d40 Techman Electronics (Changshu) Co., Ltd.
1d44 DPT
a400 PM2x24/PM3224
+1d49 Lenovo
1d5c Fantasia Trading LLC
1d61 Technobox, Inc.
+1d62 Nebbiolo Technologies
1d65 Imagine Communications Corp.
04de Taurus/McKinley
1d6c Atomic Rules LLC
@@ -19418,6 +19830,7 @@
1186 2900 DXE-810T 10GBase-T Ethernet Adapter
1fc9 3015 Ethernet Adapter
4026 TN9610 10GbE SFP+ Ethernet Adapter
+ 4027 TN9710 10GBase-T/NBASE-T Ethernet Adapter
1fcc StreamLabs
f416 MS416
fb01 MH4LM
@@ -19445,7 +19858,9 @@
2955 Connectix Virtual PC
6e61 OHCI USB 1.1 controller
2a15 3D Vision(???)
+2bd8 ROPEX Industrie-Elektronik GmbH
3000 Hansol Electronics Inc.
+3112 Satelco Ingenieria S.A.
3142 Post Impression Systems.
31ab Zonet
1faa ZEW1602 802.11b/g Wireless Adapter
@@ -19488,6 +19903,7 @@
1140 VR-12-PCI
# multiport serial board
1141 PCI-485(422)
+ 1142 PCI-CAN2
3842 eVga.com. Corp.
38ef 4Links
3d3d 3DLabs
@@ -19931,6 +20347,10 @@
5431 AuzenTech, Inc.
544c Teralogic Inc
0350 TL880-based HDTV/ATSC tuner
+544d TBS Technologies
+ 6178 DVB-S2 4 Tuner PCIe Card
+ 544d 6904 TBS6904 DVB-S2 Quad Tuner PCIe Card
+ 544d 6905 TBS6905 DVB-S2 Quad Tuner PCIe Card
5452 SCANLAB AG
3443 RTC4
5455 Technische University Berlin
@@ -20014,12 +20434,14 @@
0044 Core Processor DRAM Controller
1025 0347 Aspire 7740G
1025 0487 TravelMate 5742
+ 1028 040a Latitude E6410
144d c06a R730 Laptop
17c0 10d2 Medion Akoya E7214 Notebook PC [MD98410]
e4bf 50c1 PC1-GROOVE
0045 Core Processor PCI Express x16 Root Port
17c0 10d2 Medion Akoya E7214 Notebook PC [MD98410]
0046 Core Processor Integrated Graphics Controller
+ 1028 040a Latitude E6410
144d c06a R730 Laptop
17c0 10d9 Medion Akoya E7214 Notebook PC [MD98410]
e4bf 50c1 PC1-GROOVE
@@ -20125,13 +20547,16 @@
0153 3rd Gen Core Processor Thermal Subsystem
1043 1517 Zenbook Prime UX31A
0154 3rd Gen Core processor DRAM Controller
+ 1025 0806 Aspire E1-470G
1025 0813 Aspire R7-571
103c 17f6 ProBook 4540s
+ 1043 108d VivoBook X202EV
1043 1477 N56VZ
1043 1517 Zenbook Prime UX31A
0155 Xeon E3-1200 v2/3rd Gen Core processor PCI Express Root Port
8086 2010 Server Board S1200BTS
0156 3rd Gen Core processor Graphics Controller
+ 1043 108d VivoBook X202EV
0158 Xeon E3-1200 v2/Ivy Bridge DRAM Controller
1043 844d P8 series motherboard
8086 2010 Server Board S1200BTS
@@ -20505,6 +20930,8 @@
8086 3705 DC P3500 SSD [2.5" SFF]
8086 3709 DC P3600 SSD [Add-in Card]
8086 370a DC P3600 SSD [2.5" SFF]
+ 8086 370d SSD 750 Series [Add-in Card]
+ 8086 370e SSD 750 Series [2.5" SFF]
095a Wireless 7265
# Stone Peak 2 AC
8086 1010 Dual Band Wireless-AC 7265
@@ -20842,7 +21269,8 @@
0f28 Atom Processor Z36xxx/Z37xxx Series LPE Audio Controller
0f31 Atom Processor Z36xxx/Z37xxx Series Graphics & Display
0f34 Atom Processor Z36xxx/Z37xxx Series USB EHCI
- 0f35 Atom Processor Z36xxx/Z37xxx Series USB xHCI
+ 0f35 Atom Processor Z36xxx/Z37xxx, Celeron N2000 Series USB xHCI
+ 1025 0936 Aspire ES1
0f37 Atom Processor Z36xxx/Z37xxx Series OTG USB Device
0f38 Atom Processor Z36xxx/Z37xxx Series Camera ISP
0f40 Atom Processor Z36xxx/Z37xxx Series LPIO2 DMA Controller
@@ -21196,7 +21624,7 @@
8086 1199 PRO/1000 GT Quad Port Server Adapter
10b6 82598 10GbE PCI-Express Ethernet Controller
10b9 82572EI Gigabit Ethernet Controller (Copper)
- 103c 704a HP 110T PCIe Gigabit Server Adapter
+ 103c 704a 110T PCIe Gigabit Server Adapter
8086 1083 PRO/1000 PT Desktop Adapter
8086 1093 PRO/1000 PT Desktop Adapter
10ba 80003ES2LAN Gigabit Ethernet Controller (Copper)
@@ -21311,6 +21739,7 @@
1028 1f63 10GbE 2P X520k bNDC
103c 17d2 Ethernet 10Gb 2-port 560M Adapter
103c 18d0 Ethernet 10Gb 2-port 560FLB Adapter
+ 1059 0111 T4007 10GbE interface
8086 000c Ethernet X520 10GbE Dual Port KX4-KR Mezz
10f9 82599 10 Gigabit Dual Port Network Connection
10fb 82599ES 10-Gigabit SFI/SFP+ Network Connection
@@ -21324,6 +21753,7 @@
108e 7b11 Ethernet Server Adapter X520-2
1734 11a9 10 Gigabit Dual Port Network Connection
17aa 1071 ThinkServer X520-2 AnyFabric
+ 17aa 4007 82599ES 10-Gigabit SFI/SFP+ Network Connection
8086 0002 Ethernet Server Adapter X520-DA2
8086 0003 Ethernet Server Adapter X520-2
8086 0006 Ethernet Server Adapter X520-1
@@ -21339,14 +21769,14 @@
1025 1016 Travelmate 612 TX
1043 8027 TUSL2-C Mainboard
104d 80df Vaio PCG-FX403
- 8086 4532 D815EEA2 mainboard
+ 8086 4532 Desktop Board D815EEA2/D815EFV
8086 4557 D815EGEW Mainboard
1131 82815 815 Chipset AGP Bridge
1132 82815 Chipset Graphics Controller (CGC)
1025 1016 Travelmate 612 TX
103c 2001 e-pc 40
104d 80df Vaio PCG-FX403
- 8086 4532 D815EEA2 Mainboard
+ 8086 4532 Desktop Board D815EEA2/D815EFV
8086 4541 D815EEA Motherboard
8086 4557 D815EGEW Mainboard
1161 82806AA PCI64 Hub Advanced Programmable Interrupt Controller
@@ -21578,6 +22008,7 @@
150f 82580 Gigabit Fiber Network Connection
1510 82580 Gigabit Backplane Connection
1511 82580 Gigabit SFP Connection
+ 1513 CV82524 Thunderbolt Controller [Light Ridge 4C 2010]
1514 Ethernet X520 10GbE Dual Port KX4 Mezz
8086 000b Ethernet X520 10GbE Dual Port KX4 Mezz
1515 X540 Ethernet Controller Virtual Function
@@ -21587,6 +22018,8 @@
1517 82599ES 10 Gigabit Network Connection
1137 006a UCS CNA M61KR-I Intel Converged Network Adapter
1518 82576NS SerDes Gigabit Network Connection
+ 151a DSL2310 Thunderbolt Controller [Eagle Ridge 2C 2011]
+ 151b CVL2510 Thunderbolt Controller [Light Peak 2C 2010]
151c 82599 10 Gigabit TN Network Connection
108e 7b13 Dual 10GBASE-T LP
1520 I350 Ethernet Controller Virtual Function
@@ -21610,6 +22043,7 @@
1093 775b PCIe-8237 Ethernet Adapter
10a9 802a UV2-BaseIO dual-port GbE
17aa 1074 ThinkServer I350-T4 AnyFabric
+ 17aa 4005 I350 Gigabit Network Connection
8086 0001 Ethernet Server Adapter I350-T4
8086 0002 Ethernet Server Adapter I350-T2
8086 00a1 Ethernet Server Adapter I350-T4
@@ -21652,6 +22086,7 @@
108e 7b15 Sun Dual Port 10 GbE PCIe 2.0 Low Profile Adapter, Base-T
1137 00bf Ethernet Converged Network Adapter X540-T2
17aa 1073 ThinkServer X540-T2 AnyFabric
+ 17aa 4006 Ethernet Controller 10-Gigabit X540-AT2
8086 0001 Ethernet Converged Network Adapter X540-T2
8086 0002 Ethernet Converged Network Adapter X540-T1
8086 001a Ethernet Converged Network Adapter X540-T2
@@ -21671,14 +22106,18 @@
8086 0002 Ethernet Server Adapter I210-T1
1536 I210 Gigabit Fiber Network Connection
1537 I210 Gigabit Backplane Connection
+ 1059 0110 T4005 1GbE interface
+ 1059 0111 T4007 1GbE interface
+ 1059 0120 T4008 1GbE interface
1538 I210 Gigabit Network Connection
1539 I211 Gigabit Network Connection
153a Ethernet Connection I217-LM
103c 1909 ZBook 15
17aa 220e ThinkPad T440p
153b Ethernet Connection I217-V
- 1547 DSL3510 Thunderbolt Port [Cactus Ridge]
- 1549 DSL3510 Thunderbolt Controller [Cactus Ridge]
+ 1547 DSL3510 Thunderbolt Controller [Cactus Ridge 4C 2012]
+ 1548 DSL3310 Thunderbolt Controller [Cactus Ridge 2C 2012]
+ 1549 DSL2210 Thunderbolt Controller [Port Ridge 1C 2011]
154a Ethernet Server Adapter X520-4
8086 011a Ethernet Converged Network Adapter X520-4
8086 011b Ethernet Converged Network Adapter X520-4
@@ -21687,6 +22126,7 @@
154d Ethernet 10G 2P X520 Adapter
8086 7b11 10GbE 2P X520 Adapter
1557 82599 10 Gigabit Network Connection
+ 17aa 4008 82599EN 10 Gigabit Network Connection
8086 0001 Ethernet OCP Server Adapter X520-1
1558 Ethernet Converged Network Adapter X520-Q1
8086 011a Ethernet Converged Network Adapter X520-Q1
@@ -21700,11 +22140,25 @@
8086 0001 Ethernet Server Bypass Adapter X520-SR2
8086 0002 Ethernet Server Bypass Adapter X520-LR2
1560 Ethernet Controller X540
+ 1563 Ethernet Controller 10G X550T
+ 8086 0001 Ethernet Converged Network Adapter X550-T2
+ 8086 001a Ethernet Converged Network Adapter X550-T2
+ 1566 DSL4410 Thunderbolt NHI [Redwood Ridge 2C 2013]
+ 1567 DSL4410 Thunderbolt Bridge [Redwood Ridge 2C 2013]
+ 1568 DSL4510 Thunderbolt NHI [Redwood Ridge 4C 2013]
+ 1569 DSL4510 Thunderbolt Bridge [Redwood Ridge 4C 2013]
+ 156a DSL5320 Thunderbolt 2 NHI [Falcon Ridge 2C 2013]
+ 156b DSL5320 Thunderbolt 2 Bridge [Falcon Ridge 2C 2013]
+ 156c DSL5520 Thunderbolt 2 NHI [Falcon Ridge 4C 2013]
+ 156d DSL5520 Thunderbolt 2 Bridge [Falcon Ridge 4C 2013]
156f Ethernet Connection I219-LM
1570 Ethernet Connection I219-V
1571 XL710/X710 Virtual Function
1572 Ethernet Controller X710 for 10GbE SFP+
+ 1028 0000 Ethernet 10G X710 rNDC
1028 1f99 Ethernet 10G 4P X710/I350 rNDC
+ 1028 1f9c Ethernet 10G 4P X710 SFP+ rNDC
+ 103c 0000 Ethernet 10Gb 562SFP+ Adapter
103c 22fc HP Ethernet 10Gb 2-port 562FLR-SFP+ Adapter
103c 22fd HP Ethernet 10Gb 2-port 562SFP+ Adapter
1137 0000 Ethernet Converged NIC X710-4
@@ -21725,28 +22179,39 @@
8086 000d Ethernet Controller X710 for 10GbE SFP+
8086 4005 Ethernet Controller XL710 for 10 Gigabit SFP+
8086 4006 Ethernet Controller X710 for 10GbE SFP+
+ 1575 DSL5110 Thunderbolt NHI [Falcon Ridge LP 2014]
+ 1576 DSL5110 Thunderbolt Bridge [Falcon Ridge LP 2014]
+ 1577 DSL6540 Thunderbolt 3 NHI [Alpine Ridge 4C 2015]
+ 1578 DSL6540 Thunderbolt 3 Bridge [Alpine Ridge 4C 2015]
157b I210 Gigabit Network Connection
157c I210 Gigabit Backplane Connection
+ 157d DSL6340 Thunderbolt 3 NHI [Alpine Ridge 2C 2015]
+ 157e DSL6340 Thunderbolt 3 Bridge [Alpine Ridge 2C 2015]
1580 Ethernet Controller XL710 for 40GbE backplane
1581 Ethernet Controller X710 for 10GbE backplane
+ 1028 0000 Ethernet 10G X710-k bNDC
1028 1f98 Ethernet 10G 4P X710-k bNDC
+ 1028 1f9e Ethernet 10G 2P X710-k bNDC
+ 8086 0000 Ethernet Converged Network Adapter XL710-Q2
1583 Ethernet Controller XL710 for 40GbE QSFP+
1028 0000 Ethernet 40G 2P XL710 QSFP+ rNDC
1028 1f9f Ethernet 40G 2P XL710 QSFP+ rNDC
- 108e 0000 Oracle 10 Gb and 40 Gb Ethernet Adapter
- 108e 7b1b Oracle 10 Gb and 40 Gb Ethernet Adapter
+ 108e 0000 10 Gb/40 Gb Ethernet Adapter
+ 108e 7b1b 10 Gb/40 Gb Ethernet Adapter
1137 0000 Ethernet Converged NIC XL710-Q2
1137 013c Ethernet Converged NIC XL710-Q2
8086 0000 Ethernet Converged Network Adapter XL710-Q2
8086 0001 Ethernet Converged Network Adapter XL710-Q2
8086 0002 Ethernet Converged Network Adapter XL710-Q2
8086 0003 Ethernet I/O Module XL710-Q2
+ 8086 0004 Ethernet Server Adapter XL710-Q2OCP
8086 0006 Ethernet Converged Network Adapter XL710-Q2
1584 Ethernet Controller XL710 for 40GbE QSFP+
8086 0000 Ethernet Converged Network Adapter XL710-Q1
8086 0001 Ethernet Converged Network Adapter XL710-Q1
8086 0002 Ethernet Converged Network Adapter XL710-Q1
8086 0003 Ethernet I/O Module XL710-Q1
+ 8086 0004 Ethernet Server Adapter XL710-Q1OCP
1585 Ethernet Controller X710 for 10GbE QSFP+
1586 Ethernet Controller X710 for 10GBASE-T
108e 0000 Ethernet Controller X710 for 10GBASE-T
@@ -21754,7 +22219,6 @@
1587 Ethernet Controller XL710 for 20GbE backplane
103c 0000 HP Flex-20 20Gb 2-port 660FLB Adapter
103c 22fe HP Flex-20 20Gb 2-port 660FLB Adapter
- 103c 22ff HP Flex-20 20Gb 2-port 660M Adapter
1588 Ethernet Controller XL710 for 20GbE backplane
103c 0000 HP Flex-20 20Gb 2-port 660M Adapter
103c 22ff HP Flex-20 20Gb 2-port 660M Adapter
@@ -21770,15 +22234,26 @@
15a5 Ethernet Switch FM10000 Host Virtual Interface
15a8 Ethernet Connection X552 Virtual Function
15aa Ethernet Connection X552 10 GbE Backplane
+ 1059 0120 T4008 10GbE interface
15ab Ethernet Connection X552 10 GbE Backplane
15ac Ethernet Connection X552 10 GbE SFP+
15ad Ethernet Connection X552/X557-AT 10GBASE-T
+ 15ae Ethernet Connection X552 1000BASE-T
+ 15b6 DSL6540 USB 3.1 Controller [Alpine Ridge]
15b7 Ethernet Connection (2) I219-LM
15b8 Ethernet Connection (2) I219-V
+ 15b9 Ethernet Connection (3) I219-LM
+ 15d1 Ethernet Controller 10G X550T
+ 8086 0002 Ethernet Converged Network Adapter X550-T1
+ 8086 00a2 Ethernet Converged Network Adapter X550-T1
+ 15d6 Ethernet Connection (5) I219-V
+ 15d7 Ethernet Connection (4) I219-LM
+ 15d8 Ethernet Connection (4) I219-V
+ 15e3 Ethernet Connection (5) I219-LM
1600 Broadwell-U Host Bridge -OPI
1601 Broadwell-U PCI Express x16 Controller
1602 Broadwell-U Integrated Graphics
- 1603 Broadwell-U Camarillo Device
+ 1603 Broadwell-U Processor Thermal Subsystem
1604 Broadwell-U Host Bridge -OPI
1605 Broadwell-U PCI Express x8 Controller
1606 Broadwell-U Integrated Graphics
@@ -21813,25 +22288,27 @@
163b Broadwell-U Integrated Graphics
163d Broadwell-U Integrated Graphics
163e Broadwell-U Integrated Graphics
- 1900 Sky Lake Host Bridge/DRAM Registers
- 1901 Sky Lake PCIe Controller (x16)
- 1904 Sky Lake Host Bridge/DRAM Registers
- 1905 Sky Lake PCIe Controller (x8)
- 1908 Sky Lake Host Bridge/DRAM Registers
- 1909 Sky Lake PCIe Controller (x4)
- 190c Sky Lake Host Bridge/DRAM Registers
- 190f Sky Lake Host Bridge/DRAM Registers
- 1910 Sky Lake Host Bridge/DRAM Registers
- 1911 Sky Lake Gaussian Mixture Model
- 1912 Sky Lake Integrated Graphics
- 1916 Sky Lake Integrated Graphics
- 1918 Sky Lake Host Bridge/DRAM Registers
- 1919 Sky Lake Imaging Unit
- 191e Sky Lake Integrated Graphics
- 191f Sky Lake Host Bridge/DRAM Registers
- 1926 Sky Lake Integrated Graphics
- 1932 Sky Lake Integrated Graphics
- 193b Sky Lake Integrated Graphics
+ 1900 Skylake Host Bridge/DRAM Registers
+ 1901 Skylake PCIe Controller (x16)
+ 1903 Skylake Processor Thermal Subsystem
+ 1904 Skylake Host Bridge/DRAM Registers
+ 1905 Skylake PCIe Controller (x8)
+ 1908 Skylake Host Bridge/DRAM Registers
+ 1909 Skylake PCIe Controller (x4)
+ 190c Skylake Host Bridge/DRAM Registers
+ 190f Skylake Host Bridge/DRAM Registers
+ 1910 Skylake Host Bridge/DRAM Registers
+ 1911 Skylake Gaussian Mixture Model
+ 1912 Skylake Integrated Graphics
+ 1916 Skylake Integrated Graphics
+ 1918 Skylake Host Bridge/DRAM Registers
+ 1919 Skylake Imaging Unit
+ 191b Skylake Integrated Graphics
+ 191e Skylake Integrated Graphics
+ 191f Skylake Host Bridge/DRAM Registers
+ 1926 Skylake Integrated Graphics
+ 1932 Skylake Integrated Graphics
+ 193b Skylake Integrated Graphics
1960 80960RP (i960RP) Microprocessor
101e 0431 MegaRAID 431 RAID Controller
101e 0438 MegaRAID 438 Ultra2 LVD RAID Controller
@@ -21859,6 +22336,7 @@
e4bf 3100 CX1-BAND
1962 80960RM (i960RM) Microprocessor
105a 0000 SuperTrak SX6000 I2O CPU
+ 19df DNV SMBus controller
1a21 82840 840 [Carmel] Chipset Host Bridge (Hub A)
1a23 82840 840 [Carmel] Chipset AGP Bridge
1a24 82840 840 [Carmel] Chipset PCI Bridge (Hub B)
@@ -22075,6 +22553,7 @@
1043 84ca P8 series motherboard
1849 1e02 Motherboard
1e03 7 Series Chipset Family 6-port SATA Controller [AHCI mode]
+ 1043 108d VivoBook X202EV
1043 1477 N56VZ
1043 1517 Zenbook Prime UX31A
1e04 7 Series/C210 Series Chipset Family SATA Controller [RAID mode]
@@ -22085,15 +22564,18 @@
1e09 7 Series Chipset Family 2-port SATA Controller [IDE mode]
1e0e 7 Series/C210 Series Chipset Family SATA Controller [RAID mode]
1e10 7 Series/C210 Series Chipset Family PCI Express Root Port 1
+ 1043 108d VivoBook X202EV
1043 1477 N56VZ
1043 1517 Zenbook Prime UX31A
1043 84ca P8H77-I Motherboard
1849 1e10 Motherboard
1e12 7 Series/C210 Series Chipset Family PCI Express Root Port 2
+ 1043 108d VivoBook X202EV
1043 1477 N56VZ
1043 1517 Zenbook Prime UX31A
1e14 7 Series/C210 Series Chipset Family PCI Express Root Port 3
1e16 7 Series/C210 Series Chipset Family PCI Express Root Port 4
+ 1043 108d VivoBook X202EV
1043 1477 N56VZ
1849 1618 Z77 Extreme4 motherboard
1e18 7 Series/C210 Series Chipset Family PCI Express Root Port 5
@@ -22105,12 +22587,15 @@
1e1e 7 Series/C210 Series Chipset Family PCI Express Root Port 8
1849 1e1e Motherboard
1e20 7 Series/C210 Series Chipset Family High Definition Audio Controller
+ 1028 054b Dell XPS One 2710
+ 1043 108d VivoBook X202EV
1043 1477 N56VZ
1043 1517 Zenbook Prime UX31A
1043 8415 P8H77-I Motherboard
1043 8445 ASUS P8Z77-V LX Motherboard
1849 1898 Z77 Extreme4 motherboard
1e22 7 Series/C210 Series Chipset Family SMBus Controller
+ 1043 108d VivoBook X202EV
1043 1477 N56VZ
1043 1517 Zenbook Prime UX31A
1043 84ca P8 series motherboard
@@ -22119,23 +22604,27 @@
1043 1517 Zenbook Prime UX31A
1e25 7 Series/C210 Series Chipset Family DMI to PCI Bridge
1e26 7 Series/C210 Series Chipset Family USB Enhanced Host Controller #1
+ 1043 108d VivoBook X202EV
1043 1477 N56VZ
1043 1517 Zenbook Prime UX31A
1043 84ca P8 series motherboard
1849 1e26 Motherboard
1e2d 7 Series/C210 Series Chipset Family USB Enhanced Host Controller #2
+ 1043 108d VivoBook X202EV
1043 1477 N56VZ
1043 1517 Zenbook Prime UX31A
1043 84ca P8 series motherboard
1849 1e2d Motherboard
1e31 7 Series/C210 Series Chipset Family USB xHCI Host Controller
103c 17ab ProBook 6570b
+ 1043 108d VivoBook X202EV
1043 1477 N56VZ
1043 1517 Zenbook Prime UX31A
1043 84ca P8 series motherboard
1849 1e31 Motherboard
1e33 7 Series/C210 Series Chipset Family LAN Controller
1e3a 7 Series/C210 Series Chipset Family MEI Controller #1
+ 1043 108d VivoBook X202EV
1043 1477 N56VZ
1043 1517 Zenbook Prime UX31A
1043 84ca P8 series motherboard
@@ -22178,6 +22667,7 @@
1e5c 7 Series Chipset Family LPC Controller
1e5d HM75 Express Chipset LPC Controller
1e5e 7 Series Chipset Family LPC Controller
+ 1043 108d VivoBook X202EV
1e5f 7 Series Chipset Family LPC Controller
1f00 Atom processor C2000 SoC Transaction Router
1f01 Atom processor C2000 SoC Transaction Router
@@ -22351,7 +22841,7 @@
104d 80df Vaio PCG-FX403
147b 0505 BL7 motherboard
147b 0507 TH7II-RAID
- 8086 4532 D815EEA2 mainboard
+ 8086 4532 Desktop Board D815EEA2/D815EFV
8086 4557 D815EGEW Mainboard
8086 5744 S845WD1-E mainboard
2443 82801BA/BAM SMBus Controller
@@ -22366,7 +22856,7 @@
147b 0505 BL7 motherboard
147b 0507 TH7II-RAID
15d9 3280 Supermicro P4SBE Mainboard
- 8086 4532 D815EEA2 mainboard
+ 8086 4532 Desktop Board D815EEA2/D815EFV
8086 4557 D815EGEW Mainboard
8086 5744 S845WD1-E mainboard
2444 82801BA/BAM UHCI USB 1.1 Controller #2
@@ -22379,7 +22869,7 @@
104d 80df Vaio PCG-FX403
147b 0505 BL7 motherboard
147b 0507 TH7II-RAID
- 8086 4532 D815EEA2 mainboard
+ 8086 4532 Desktop Board D815EEA2/D815EFV
8086 5744 S845WD1-E mainboard
2445 82801BA/BAM AC'97 Audio Controller
0e11 000b Compaq Deskpro EN Audio
@@ -22393,12 +22883,14 @@
147b 0505 BL7 motherboard
147b 0507 TH7II-RAID
8086 4557 D815EGEW Mainboard
+ 8086 4656 Desktop Board D815EFV
2446 82801BA/BAM AC'97 Modem Controller
1025 1016 Travelmate 612 TX
104d 80df Vaio PCG-FX403
2448 82801 Mobile PCI Bridge
+ 1028 040a Latitude E6410
1028 040b Latitude E6510
- 103c 0934 HP Compaq nw8240 Mobile Workstation
+ 103c 0934 Compaq nw8240 Mobile Workstation
103c 099c NX6110/NC6120
103c 309f Compaq nx9420 Notebook
103c 30a3 Compaq nw8440
@@ -22461,7 +22953,7 @@
147b 0505 BL7 motherboard
147b 0507 TH7II-RAID
15d9 3280 Supermicro P4SBE Mainboard
- 8086 4532 D815EEA2 mainboard
+ 8086 4532 Desktop Board D815EEA2/D815EFV
8086 4557 D815EGEW Mainboard
8086 5744 S845WD1-E mainboard
244c 82801BAM ISA Bridge (LPC)
@@ -22555,6 +23047,7 @@
1025 005a TravelMate 290
1025 0064 Extensa 3000 series laptop: Intel 82801DBM (ICH4-M)
1028 0126 Optiplex GX260
+ 1028 0160 Dimension 2400
1028 0163 Latitude D505
1028 018d Inspiron 700m/710m
1028 0196 Inspiron 5160
@@ -22582,6 +23075,7 @@
1025 0064 Extensa 3000 series laptop: Intel 82801DBM (ICH4-M)
1028 0126 Optiplex GX260
1028 014f Latitude X300
+ 1028 0160 Dimension 2400
1028 018d Inspiron 700m/710m
103c 088c NC8000 laptop
103c 0890 NC6000 laptop
@@ -22603,6 +23097,7 @@
1025 005a TravelMate 290
1025 0064 Extensa 3000 series laptop: Intel 82801DBM (ICH4-M)
1028 0126 Optiplex GX260
+ 1028 0160 Dimension 2400
1028 0163 Latitude D505
1028 018d Inspiron 700m/710m
1028 0196 Inspiron 5160
@@ -22630,6 +23125,7 @@
1028 0139 Latitude D400
1028 014f Latitude X300
1028 0152 Latitude D500
+ 1028 0160 Dimension 2400
1028 0163 Latitude D505
1028 018d Inspiron 700m/710m [SigmaTel STAC9750,51]
1028 0196 Inspiron 5160
@@ -22646,7 +23142,6 @@
1462 5800 845PE Max (MS-6580)
1734 1005 D1451 (SCENIC N300, i845GV) Sigmatel STAC9750T
1734 1055 Amilo M1420
- 8086 24c5 Dell Dimension 2400
24c6 82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller
1014 0524 ThinkPad T4x Series
1014 0525 ThinkPad
@@ -22672,6 +23167,7 @@
1025 005a TravelMate 290
1025 0064 Extensa 3000 series laptop: Intel 82801DBM (ICH4-M)
1028 0126 Optiplex GX260
+ 1028 0160 Dimension 2400
1028 0163 Latitude D505
1028 018d Inspiron 700m/710m
1028 0196 Inspiron 5160
@@ -22708,6 +23204,7 @@
24cb 82801DB (ICH4) IDE Controller
1014 0267 NetVista A30p
1028 0126 Optiplex GX260
+ 1028 0160 Dimension 2400
1043 8089 P4B533
114a 0582 PC8 onboard IDE
1458 24c2 GA-8PE667 Ultra
@@ -22728,6 +23225,7 @@
1028 0126 Optiplex GX260
1028 0139 Latitude D400
1028 0152 Latitude D500
+ 1028 0160 Dimension 2400
1028 0163 Latitude D505
1028 018d Inspiron 700m/710m
1028 0196 Inspiron 5160
@@ -22935,6 +23433,12 @@
24df 82801ER (ICH5R) SATA Controller
1028 0168 Precision Workstation 670 Mainboard
24f0 Omni-Path HFI Silicon 100 Series [discrete]
+ 10a9 802e Omni-path HFI 100 Series, 1-port
+ 10a9 802f Omni-path HFI 100 Series, 2-port
+ 8086 2628 Omni-Path HFI Adapter 100 Series, 1 Port, PCIe x16
+ 8086 2629 Omni-Path HFI Adapter 100 Series, 1 Port, PCIe x8
+ 8086 262a Omni-Path HFI Adapter 100 Series, 2 Ports, Split PCIe x16
+ 8086 262d Omni-Path HFI Adapter 100 Series, 1 Port, PCIe x16, IO Module AHWKPTP100HF
24f1 Omni-Path HFI Silicon 100 Series [integrated]
24f3 Wireless 8260
# Snow Field Peak AC
@@ -22989,6 +23493,7 @@
2562 82845G/GL[Brookdale-G]/GE Chipset Integrated Graphics Device
0e11 00b9 Evo D510 SFF
1014 0267 NetVista A30p
+ 1028 0160 Dimension 2400
1734 1003 D1521 Mainboard (Fujitsu-Siemens)
1734 1004 D1451 Mainboard (SCENIC N300, i845GV)
2570 82865G/PE/P DRAM Controller/Host-Hub Interface
@@ -23033,7 +23538,7 @@
2589 E7220/E7221 PCI Express Root Port
258a E7221 Integrated Graphics Controller
2590 Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller
- 1014 0575 ThinkPad Z60t
+ 1014 0575 ThinkPad X41 / Z60t
1028 0182 Dell Latitude C610
103c 0934 Compaq nw8240/nx8220
103c 099c NX6110/NC6120
@@ -23043,8 +23548,9 @@
e4bf 0cd3 CD3-JIVE
e4bf 58b1 XB1
2591 Mobile 915GM/PM Express PCI Express Root Port
- 103c 0934 HP Compaq nw8240 Mobile Workstation
+ 103c 0934 Compaq nw8240 Mobile Workstation
2592 Mobile 915GM/GMS/910GML Express Graphics Controller
+ 1014 0582 ThinkPad X41
103c 099c NX6110/NC6120
103c 308a NC6220
1043 1881 GMA 900 915GM Integrated Graphics
@@ -23217,6 +23723,7 @@
e4bf 0cd3 CD3-JIVE
e4bf 58b1 XB1
2641 82801FBM (ICH6M) LPC Interface Bridge
+ 1014 0568 ThinkPad X41
103c 0934 Compaq nw8240/nx8220
103c 099c NX6110/NC6120
2642 82801FW/FRW (ICH6W/ICH6RW) LPC Interface Bridge
@@ -23232,7 +23739,9 @@
1028 0177 Dimension 8400
1462 7028 915P/G Neo2
2653 82801FBM (ICH6M) SATA Controller
+ 1014 056a ThinkPad X41
2658 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1
+ 1014 0565 ThinkPad X41
1028 0177 Dimension 8400
1028 0179 Optiplex GX280
103c 0934 Compaq nw8240/nx8220
@@ -23245,6 +23754,7 @@
e4bf 0cd3 CD3-JIVE
e4bf 58b1 XB1
2659 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2
+ 1014 0565 ThinkPad X41
1028 0177 Dimension 8400
1028 0179 Optiplex GX280
103c 0934 Compaq nw8240/nx8220
@@ -23257,6 +23767,7 @@
e4bf 0cd3 CD3-JIVE
e4bf 58b1 XB1
265a 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3
+ 1014 0565 ThinkPad X41
1028 0177 Dimension 8400
1028 0179 Optiplex GX280
103c 0934 Compaq nw8240/nx8220
@@ -23269,6 +23780,7 @@
e4bf 0cd3 CD3-JIVE
e4bf 58b1 XB1
265b 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4
+ 1014 0565 ThinkPad X41
1028 0177 Dimension 8400
1028 0179 Optiplex GX280
103c 099c NX6110/NC6120
@@ -23280,6 +23792,7 @@
e4bf 0cd3 CD3-JIVE
e4bf 58b1 XB1
265c 82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller
+ 1014 0566 ThinkPad X41
1028 0177 Dimension 8400
1028 0179 Optiplex GX280
103c 0934 Compaq nw8240/nx8220
@@ -23293,13 +23806,13 @@
e4bf 0cd3 CD3-JIVE
e4bf 58b1 XB1
2660 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 1
- 103c 0934 HP Compaq nw8240 Mobile Workstation
+ 103c 0934 Compaq nw8240 Mobile Workstation
103c 099c NX6110/NC6120
e4bf 0ccd CCD-CALYPSO
e4bf 0cd3 CD3-JIVE
e4bf 58b1 XB1
2662 82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 2
- 103c 0934 HP Compaq nw8240 Mobile Workstation
+ 103c 0934 Compaq nw8240 Mobile Workstation
e4bf 0ccd CCD-CALYPSO
e4bf 0cd3 CD3-JIVE
e4bf 58b1 XB1
@@ -23320,6 +23833,7 @@
1462 7028 915P/G Neo2
1af4 1100 QEMU Virtual Machine
266a 82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller
+ 1014 056b ThinkPad X41
1028 0177 Dimension 8400
1028 0179 Optiplex GX280
1043 80a6 P5GD1-VW Mainboard
@@ -23335,6 +23849,7 @@
103c 0934 Compaq nw8240/nx8220
103c 099c NX6110/NC6120
266e 82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller
+ 1014 0581 ThinkPad X41
1025 006a Realtek ALC 655 codec (in Acer TravelMate 2410 serie laptop)
1028 0177 Dimension 8400
1028 0179 Optiplex GX280
@@ -23451,6 +23966,7 @@
1043 2582 P5GD1-VW Mainboard
1734 105b Scenic W620
2792 Mobile 915GM/GMS/910GML Express Graphics Controller
+ 1014 0582 ThinkPad X41
103c 099c NX6110/NC6120
1043 1881 GMA 900 915GM Integrated Graphics
e4bf 0ccd CCD-CALYPSO
@@ -23960,7 +24476,7 @@
1028 01f9 Dell Latitude D630
1028 01ff Dell Precision M4300
1028 0256 Studio 1735
- 103c 2802 HP Compaq dc7700p
+ 103c 2802 Compaq dc7700p
103c 30c0 Compaq 6710b
103c 30c1 Compaq 6910p
103c 30cc Pavilion dv6700
@@ -24761,6 +25277,8 @@
8086 4010 Dual Band Wireless AC 3165
# Stone Peak 1x1
8086 4210 Dual Band Wireless AC 3165
+# Stone Peak 1x1
+ 3166 Intel Dual Band Wireless-AC 3165 Plus Bluetooth
3200 GD31244 PCI-X SATA HBA
1775 c200 C2K onboard SATA host bus adapter
3310 IOP348 I/O Processor
@@ -25156,34 +25674,35 @@
3a7c 82801JD/DO (ICH10 Family) Gigabit Ethernet Controller
3b00 5 Series/3400 Series Chipset LPC Interface Controller
3b01 Mobile 5 Series Chipset LPC Interface Controller
- 3b02 5 Series Chipset LPC Interface Controller
- 3b03 Mobile 5 Series Chipset LPC Interface Controller
+ 3b02 P55 Chipset LPC Interface Controller
+ 3b03 PM55 Chipset LPC Interface Controller
3b04 5 Series Chipset LPC Interface Controller
3b05 Mobile 5 Series Chipset LPC Interface Controller
- 3b06 5 Series Chipset LPC Interface Controller
- 3b07 Mobile 5 Series Chipset LPC Interface Controller
+ 3b06 H55 Chipset LPC Interface Controller
+ 3b07 QM57 Chipset LPC Interface Controller
+ 1028 040a Latitude E6410
1028 040b Latitude E6510
e4bf 50c1 PC1-GROOVE
- 3b08 5 Series Chipset LPC Interface Controller
- 3b09 Mobile 5 Series Chipset LPC Interface Controller
+ 3b08 H57 Chipset LPC Interface Controller
+ 3b09 HM55 Chipset LPC Interface Controller
1025 0347 Aspire 7740G
144d c06a R730 Laptop
17c0 10d2 Medion Akoya E7214 Notebook PC [MD98410]
- 3b0a 5 Series Chipset LPC Interface Controller
+ 3b0a Q57 Chipset LPC Interface Controller
1028 02da OptiPlex 980
15d9 060d C7SIM-Q Motherboard
- 3b0b Mobile 5 Series Chipset LPC Interface Controller
+ 3b0b HM57 Chipset LPC Interface Controller
3b0c 5 Series Chipset LPC Interface Controller
3b0d 5 Series/3400 Series Chipset LPC Interface Controller
3b0e 5 Series/3400 Series Chipset LPC Interface Controller
- 3b0f 5 Series/3400 Series Chipset LPC Interface Controller
+ 3b0f QS57 Chipset LPC Interface Controller
3b10 5 Series/3400 Series Chipset LPC Interface Controller
3b11 5 Series/3400 Series Chipset LPC Interface Controller
3b12 3400 Series Chipset LPC Interface Controller
3b13 5 Series/3400 Series Chipset LPC Interface Controller
- 3b14 3400 Series Chipset LPC Interface Controller
+ 3b14 3420 Chipset LPC Interface Controller
3b15 5 Series/3400 Series Chipset LPC Interface Controller
- 3b16 3400 Series Chipset LPC Interface Controller
+ 3b16 3450 Chipset LPC Interface Controller
3b17 5 Series/3400 Series Chipset LPC Interface Controller
3b18 5 Series/3400 Series Chipset LPC Interface Controller
3b19 5 Series/3400 Series Chipset LPC Interface Controller
@@ -25200,7 +25719,7 @@
15d9 060d C7SIM-Q Motherboard
3b23 5 Series/3400 Series Chipset 4 port SATA AHCI Controller
3b25 5 Series/3400 Series Chipset SATA RAID Controller
- 103c 3118 HP Smart Array B110i SATA RAID Controller
+ 103c 3118 Smart Array B110i SATA RAID Controller
3b26 5 Series/3400 Series Chipset 2 port SATA IDE Controller
3b28 5 Series/3400 Series Chipset 4 port SATA IDE Controller
144d c06a R730 Laptop
@@ -25217,11 +25736,13 @@
3b2e 5 Series/3400 Series Chipset 4 port SATA IDE Controller
e4bf 50c1 PC1-GROOVE
3b2f 5 Series/3400 Series Chipset 6 port SATA AHCI Controller
+ 1028 040a Latitude E6410
1028 040b Latitude E6510
e4bf 50c1 PC1-GROOVE
3b30 5 Series/3400 Series Chipset SMBus Controller
1025 0347 Aspire 7740G
1028 02da OptiPlex 980
+ 1028 040a Latitude E6410
1028 040b Latitude E6510
144d c06a R730 Laptop
15d9 060d C7SIM-Q Motherboard
@@ -25229,11 +25750,13 @@
e4bf 50c1 PC1-GROOVE
3b32 5 Series/3400 Series Chipset Thermal Subsystem
1025 0347 Aspire 7740G
+ 1028 040a Latitude E6410
144d c06a R730 Laptop
17c0 10d2 Medion Akoya E7214 Notebook PC [MD98410]
3b34 5 Series/3400 Series Chipset USB2 Enhanced Host Controller
1025 0347 Aspire 7740G
1028 02da OptiPlex 980
+ 1028 040a Latitude E6410
1028 040b Latitude E6510
144d c06a R730 Laptop
15d9 060d C7SIM-Q Motherboard
@@ -25248,6 +25771,7 @@
3b3c 5 Series/3400 Series Chipset USB2 Enhanced Host Controller
1025 0347 Aspire 7740G
1028 02da OptiPlex 980
+ 1028 040a Latitude E6410
1028 040b Latitude E6510
144d c06a R730 Laptop
15d9 060d C7SIM-Q Motherboard
@@ -25259,19 +25783,23 @@
3b41 5 Series/3400 Series Chipset LAN Controller
3b42 5 Series/3400 Series Chipset PCI Express Root Port 1
1028 02da OptiPlex 980
+ 1028 040a Latitude E6410
1028 040b Latitude E6510
144d c06a R730 Laptop
15d9 060d C7SIM-Q Motherboard
17c0 10d2 Medion Akoya E7214 Notebook PC [MD98410]
3b44 5 Series/3400 Series Chipset PCI Express Root Port 2
+ 1028 040a Latitude E6410
1028 040b Latitude E6510
15d9 060d C7SIM-Q Motherboard
17c0 10d2 Medion Akoya E7214 Notebook PC [MD98410]
3b46 5 Series/3400 Series Chipset PCI Express Root Port 3
+ 1028 040a Latitude E6410
1028 040b Latitude E6510
144d c06a R730 Laptop
17c0 10d2 Medion Akoya E7214 Notebook PC [MD98410]
3b48 5 Series/3400 Series Chipset PCI Express Root Port 4
+ 1028 040a Latitude E6410
1028 040b Latitude E6510
144d c06a R730 Laptop
3b4a 5 Series/3400 Series Chipset PCI Express Root Port 5
@@ -25284,7 +25812,9 @@
3b56 5 Series/3400 Series Chipset High Definition Audio
1025 0347 Aspire 7740G
1028 02da OptiPlex 980
+ 1028 040a Latitude E6410
1028 040b Latitude E6510
+ 1043 1373 ASUSTek G73-series gaming laptop
144d c06a R730 Laptop
15d9 060d C7SIM-Q Motherboard
17c0 10d2 Medion Akoya E7214 Notebook PC [MD98410]
@@ -25549,6 +26079,7 @@
530d 80310 (IOP) IO Processor
5845 QEMU NVM Express Controller
1af4 1100 QEMU Virtual Machine
+ 5ad4 Broxton SMBus Controller
65c0 5100 Chipset Memory Controller Hub
65e2 5100 Chipset PCI Express x4 Port 2
65e3 5100 Chipset PCI Express x4 Port 3
@@ -25626,6 +26157,10 @@
6f45 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 2 Debug
6f46 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 2 Debug
6f47 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D QPI Link 2 Debug
+ 6f50 Xeon Processor D Family QuickData Technology Register DMA Channel 0
+ 6f51 Xeon Processor D Family QuickData Technology Register DMA Channel 1
+ 6f52 Xeon Processor D Family QuickData Technology Register DMA Channel 2
+ 6f53 Xeon Processor D Family QuickData Technology Register DMA Channel 3
6f60 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Home Agent 1
6f68 Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Target Address/Thermal/RAS
6f6a Xeon E7 v4/Xeon E5 v4/Xeon E3 v4/Xeon D Channel Target Address Decoder
@@ -26119,10 +26654,12 @@
9c23 8 Series CHAP Counters
9c24 8 Series Thermal
9c26 8 Series USB EHCI #1
+ 17aa 220c T440s
17aa 2214 ThinkPad X240
9c2d 8 Series USB EHCI #2
9c31 8 Series USB xHCI HC
17aa 2214 ThinkPad X240
+ 8086 7270 Apple MacBookAir6,2 / MacBookPro11,1
9c35 8 Series SDIO Controller
9c36 8 Series Audio DSP Controller
9c3a 8 Series HECI #0
@@ -26181,6 +26718,29 @@
9ce4 Wildcat Point-LP Serial IO UART Controller #1
9ce5 Wildcat Point-LP Serial IO GSPI Controller #0
9ce6 Wildcat Point-LP Serial IO GSPI Controller #1
+ 9d03 Sunrise Point-LP SATA Controller [AHCI mode]
+ 9d14 Sunrise Point-LP PCI Express Root Port #5
+ 9d15 Sunrise Point-LP PCI Express Root Port #6
+ 9d21 Sunrise Point-LP PMC
+ 9d23 Sunrise Point-LP SMBus
+ 9d27 Sunrise Point-LP Serial IO UART Controller #0
+ 9d28 Sunrise Point-LP Serial IO UART Controller #1
+ 9d29 Sunrise Point-LP Serial IO SPI Controller #0
+ 9d2a Sunrise Point-LP Serial IO SPI Controller #1
+ 9d2d Sunrise Point-LP Secure Digital IO Controller
+ 9d2f Sunrise Point-LP USB 3.0 xHCI Controller
+ 9d31 Sunrise Point-LP Thermal subsystem
+ 9d3a Sunrise Point-LP CSME HECI #1
+ 9d48 Sunrise Point-LP LPC Controller
+ 9d60 Sunrise Point-LP Serial IO I2C Controller #0
+ 8086 9d60 100 Series PCH/Sunrise Point PCH I2C0 [Skylake/Kaby Lake LPSS I2C]
+ 9d61 Sunrise Point-LP Serial IO I2C Controller #1
+ 9d62 Sunrise Point-LP Serial IO I2C Controller #2
+ 9d63 Sunrise Point-LP Serial IO I2C Controller #3
+ 9d64 Sunrise Point-LP Serial IO I2C Controller #4
+ 9d65 Sunrise Point-LP Serial IO I2C Controller #5
+ 9d66 Sunrise Point-LP Serial IO UART Controller #2
+ 9d70 Sunrise Point-LP HD Audio
a000 Atom Processor D4xx/D5xx/N4xx/N5xx DMI Bridge
1458 5000 GA-D525TUD
8086 4f4d DeskTop Board D510MO
@@ -26198,6 +26758,7 @@
a012 Atom Processor D4xx/D5xx/N4xx/N5xx Integrated Graphics Controller
144d c072 Notebook N150P
a013 Atom Processor D4xx/D5xx/N4xx/N5xx CHAPS counter
+ a102 Sunrise Point-H SATA controller [AHCI mode]
a103 Sunrise Point-H SATA Controller [AHCI mode]
a105 Sunrise Point-H SATA Controller [RAID mode]
a107 Sunrise Point-H SATA Controller [RAID mode]
@@ -26225,10 +26786,10 @@
a124 Sunrise Point-H SPI Controller
a125 Sunrise Point-H Gigabit Ethernet Controller
a126 Sunrise Point-H Northpeak
- a127 Sunrise Point-H LPSS UART #0
- a128 Sunrise Point-H LPSS UART #1
- a129 Sunrise Point-H LPSS SPI #0
- a12a Sunrise Point-H LPSS SPI #1
+ a127 Sunrise Point-H Serial IO UART #0
+ a128 Sunrise Point-H Serial IO UART #1
+ a129 Sunrise Point-H Serial IO SPI #0
+ a12a Sunrise Point-H Serial IO SPI #1
a12f Sunrise Point-H USB 3.0 xHCI Controller
a130 Sunrise Point-H USB Device Controller (OTG)
a131 Sunrise Point-H Thermal subsystem
@@ -26271,9 +26832,9 @@
a15d Sunrise Point-H LPC Controller
a15e Sunrise Point-H LPC Controller
a15f Sunrise Point-H LPC Controller
- a160 Sunrise Point-H LPSS I2C Controller #0
- a161 Sunrise Point-H LPSS I2C Controller #1
- a166 Sunrise Point-H LPSS UART Controller #2
+ a160 Sunrise Point-H Serial IO I2C Controller #0
+ a161 Sunrise Point-H Serial IO I2C Controller #1
+ a166 Sunrise Point-H Serial IO UART Controller #2
a167 Sunrise Point-H PCI Root Port #17
a168 Sunrise Point-H PCI Root Port #18
a169 Sunrise Point-H PCI Root Port #19
@@ -26372,7 +26933,7 @@
8686 ScaleMP
1010 vSMPowered system controller [vSMP CTL]
8800 Trigem Computer Inc.
- 2008 Video assistent component
+ 2008 Video assistant component
8866 T-Square Design Inc.
8888 Silicon Magic
8912 TRX
@@ -26950,6 +27511,7 @@ dada Datapath Limited
1153 VisionDVI-DL
1154 VisionSDI2
db10 Diablo Technologies
+dc93 Dawicontrol GmbH
dcba Dynamic Engineering
0046 PCIe Altera Cyclone IV
# VPX format Receiver Controller Board
@@ -26985,6 +27547,9 @@ deaf Middle Digital Inc.
9052 PC Weasel Watchdog Timer
# formerly SoftHard Technology Ltd.
deda XIMEA
+ 4001 Camera CB
+# Thunderbolt based camera MT family
+ 4021 Camera MT
e000 Winbond
e000 W89C940
e159 Tiger Jet Network Inc.
diff --git a/share/mk/bsd.README b/share/mk/bsd.README
index 1ae1510..bda9a8c 100644
--- a/share/mk/bsd.README
+++ b/share/mk/bsd.README
@@ -120,6 +120,10 @@ object.
The following variables are common:
+ACFLAGS.${SRC}
+ Flags dependent on source file name.
+CFLAGS.${SRC}
+ Flags dependent on source file name.
CFLAGS.${COMPILER_TYPE}
Flags dependent on compiler added to CXXFLAGS.
CFLAGS.${MACHINE_ARCH}
@@ -131,6 +135,8 @@ CXXFLAGS.${COMPILER_TYPE}
Flags dependent on compiler added to CXXFLAGS.
CXXFLAGS.${MACHINE_ARCH}
Architectural flags added to CXXFLAGS.
+CXXFLAGS.${SRC}
+ Flags dependent on source file name.
COMPILER_FEATURES
A list of features that the compiler supports. Zero or
more of:
@@ -309,7 +315,7 @@ PROGS_CXX PROG and PROGS_CXX in one Makefile. To define
SRCS.bar= bar_src.c
The supported variables are BINDIR BINGRP BINMODE BINOWN
- CFLAGS CPPFLAGS CXXFLAGS DPADD DPLIBS DPSRCS LDADD
+ CFLAGS CXXFLAGS DPADD DPSRCS LDADD
LDFLAGS LIBADD MAN MLINKS PROGNAME SRCS.
PROGNAME The name that the above program will be installed as, if
diff --git a/share/mk/bsd.clang-analyze.mk b/share/mk/bsd.clang-analyze.mk
index 61321b5..b375332 100644
--- a/share/mk/bsd.clang-analyze.mk
+++ b/share/mk/bsd.clang-analyze.mk
@@ -58,14 +58,12 @@ CLANG_ANALYZE_CXXFLAGS= ${CXXFLAGS:N-Wa,--fatal-warnings}
.c.clang-analyzer:
${CC:N${CCACHE_BIN}} ${CLANG_ANALYZE_FLAGS} \
- ${CLANG_ANALYZE_CFLAGS} ${CPPFLAGS} \
- ${COPTS.${.IMPSRC:T}} ${CPUFLAGS.${.IMPSRC:T}} \
- ${CPPFLAGS.${.IMPSRC:T}} ${.IMPSRC}
+ ${CLANG_ANALYZE_CFLAGS} \
+ ${.IMPSRC}
.cc.clang-analyzer .cpp.clang-analyzer .cxx.clang-analyzer .C.clang-analyzer:
${CXX:N${CCACHE_BIN}} ${CLANG_ANALYZE_CXX_FLAGS} \
- ${CLANG_ANALYZE_CXXFLAGS} ${CPPFLAGS} \
- ${COPTS.${.IMPSRC:T}} ${CPUFLAGS.${.IMPSRC:T}} \
- ${CPPFLAGS.${.IMPSRC:T}} ${.IMPSRC}
+ ${CLANG_ANALYZE_CXXFLAGS} \
+ ${.IMPSRC}
CLANG_ANALYZE_SRCS= \
${SRCS:M*.[cC]} ${SRCS:M*.cc} \
@@ -85,10 +83,7 @@ ${__obj}: ${OBJS_DEPEND_GUESS}
${__obj}: ${OBJS_DEPEND_GUESS.${__obj}}
.endfor
-.if ${MK_FAST_DEPEND} == "yes"
-beforeanalyze: depend
-.endif
-beforeanalyze: .PHONY
+beforeanalyze: depend .PHONY
.if !defined(_RECURSING_PROGS) && !empty(CLANG_ANALYZE_SRCS) && \
${CLANG_ANALYZE_OUTPUT} != "text"
mkdir -p ${CLANG_ANALYZE_OUTPUT_DIR}
diff --git a/share/mk/bsd.cpu.mk b/share/mk/bsd.cpu.mk
index d54a354..11a469d 100644
--- a/share/mk/bsd.cpu.mk
+++ b/share/mk/bsd.cpu.mk
@@ -108,21 +108,24 @@ _CPUCFLAGS = -march=${CPUTYPE}
#XXX: gcc doesn't seem to like -mcpu=xscale, and dies while rebuilding itself
#_CPUCFLAGS = -mcpu=xscale
_CPUCFLAGS = -march=armv5te -D__XSCALE__
-. elif ${CPUTYPE} == "armv6"
+. elif ${CPUTYPE:M*soft*} != ""
+_CPUCFLAGS = -mfloat-abi=softfp
+. elif ${CPUTYPE} == "armv6"
+# Not sure we still need ARM_ARCH_6=1 here.
_CPUCFLAGS = -march=${CPUTYPE} -DARM_ARCH_6=1
-. elif ${CPUTYPE} == "cortexa"
+. elif ${CPUTYPE} == "cortexa"
_CPUCFLAGS = -march=armv7 -DARM_ARCH_6=1 -mfpu=vfp
-. elif ${CPUTYPE:Marmv[4567]*} != ""
+. elif ${CPUTYPE:Marmv[4567]*} != ""
# Handle all the armvX types that FreeBSD runs:
# armv4, armv4t, armv5, armv5te, armv6, armv6t2, armv7, armv7-a, armv7ve
# they require -march=. All the others require -mcpu=.
_CPUCFLAGS = -march=${CPUTYPE}
-. else
+. else
# Common values for FreeBSD
-# arm:
+# arm: (any arm v4 or v5 processor you are targetting)
# arm920t, arm926ej-s, marvell-pj4, fa526, fa626,
# fa606te, fa626te, fa726te
-# armv6:
+# armv6: (any arm v7 or v8 processor you are targetting and the arm1176jzf-s)
# arm1176jzf-s, generic-armv7-a, cortex-a5, cortex-a7, cortex-a8,
# cortex-a9, cortex-a12, cortex-a15, cortex-a17, cortex-a53, cortex-a57,
# cortex-a72, exynos-m1
diff --git a/share/mk/bsd.dep.mk b/share/mk/bsd.dep.mk
index 92c10a4..50ed33c 100644
--- a/share/mk/bsd.dep.mk
+++ b/share/mk/bsd.dep.mk
@@ -20,10 +20,6 @@
#
# HTAGSFLAGS Options for htags(1) [not set]
#
-# MKDEP Options for ${MKDEPCMD} [not set]
-#
-# MKDEPCMD Makefile dependency list program [mkdep]
-#
# SRCS List of source files (c, c++, assembler)
#
# DPSRCS List of source files which are needed for generating
@@ -54,13 +50,6 @@ CTAGSFLAGS?=
GTAGSFLAGS?= -o
HTAGSFLAGS?=
-_MKDEPCC:= ${CC:N${CCACHE_BIN}}
-# XXX: DEPFLAGS can come out once Makefile.inc1 properly passes down
-# CXXFLAGS.
-.if !empty(DEPFLAGS)
-_MKDEPCC+= ${DEPFLAGS}
-.endif
-MKDEPCMD?= CC='${_MKDEPCC}' mkdep
.if ${MK_DIRDEPS_BUILD} == "no"
.MAKE.DEPENDFILE= ${DEPENDFILE}
.endif
@@ -95,9 +84,6 @@ CLEANFILES?=
.for _S in ${SRCS:N*.[dhly]}
OBJS_DEPEND_GUESS.${_S:R}.o= ${_S}
-.if ${MK_FAST_DEPEND} == "no" && !exists(${.OBJDIR}/${DEPENDFILE})
-${_S:R}.o: ${OBJS_DEPEND_GUESS.${_S:R}.o}
-.endif
.endfor
# Lexical analyzers
@@ -106,9 +92,6 @@ ${_S:R}.o: ${OBJS_DEPEND_GUESS.${_S:R}.o}
${_LC}: ${_LSRC}
${LEX} ${LFLAGS} -o${.TARGET} ${.ALLSRC}
OBJS_DEPEND_GUESS.${_LC:R}.o= ${_LC}
-.if ${MK_FAST_DEPEND} == "no" && !exists(${.OBJDIR}/${DEPENDFILE})
-${_LC:R}.o: ${OBJS_DEPEND_GUESS.${_LC:R}.o}
-.endif
SRCS:= ${SRCS:S/${_LSRC}/${_LC}/}
CLEANFILES+= ${_LC}
.endfor
@@ -138,9 +121,6 @@ ${_YC}: ${_YSRC}
${YACC} ${YFLAGS} -o ${_YC} ${.ALLSRC}
.endif
OBJS_DEPEND_GUESS.${_YC:R}.o= ${_YC}
-.if ${MK_FAST_DEPEND} == "no" && !exists(${.OBJDIR}/${DEPENDFILE})
-${_YC:R}.o: ${OBJS_DEPEND_GUESS.${_YC:R}.o}
-.endif
.endfor
.endfor
@@ -175,7 +155,6 @@ ${_D}.po: ${_DSRC} ${POBJS:S/^${_D}.po$//}
.if !empty(.MAKE.MODE:Mmeta) && empty(.MAKE.MODE:Mnofilemon)
_meta_filemon= 1
.endif
-.if ${MK_FAST_DEPEND} == "yes"
.if ${MAKE_VERSION} < 20160220
DEPEND_MP?= -MP
.endif
@@ -210,7 +189,6 @@ CFLAGS+= ${DEPEND_CFLAGS}
.endfor
.endif # !defined(_SKIP_READ_DEPEND)
.endif # !defined(_meta_filemon)
-.endif # ${MK_FAST_DEPEND} == "yes"
.endif # defined(SRCS)
.if ${MK_DIRDEPS_BUILD} == "yes"
@@ -230,7 +208,6 @@ afterdepend: beforedepend
# Guess some dependencies for when no ${DEPENDFILE}.OBJ is generated yet.
# For meta+filemon the .meta file is checked for since it is the dependency
# file used.
-.if ${MK_FAST_DEPEND} == "yes"
.for __obj in ${DEPENDOBJS:O:u}
.if (defined(_meta_filemon) && !exists(${.OBJDIR}/${__obj}.meta)) || \
(!defined(_meta_filemon) && !exists(${.OBJDIR}/${DEPENDFILE}.${__obj}))
@@ -245,7 +222,6 @@ ${__obj}: ${OBJS_DEPEND_GUESS.${__obj}}
.if ${MK_DIRDEPS_BUILD} == "no" || ${.MAKE.LEVEL} > 0
beforebuild: depend
.endif
-.endif # ${MK_FAST_DEPEND} == "yes"
.if !target(depend)
.if defined(SRCS)
@@ -254,41 +230,14 @@ depend: beforedepend ${DEPENDFILE} afterdepend
# Tell bmake not to look for generated files via .PATH
.NOPATH: ${DEPENDFILE} ${DEPENDFILES_OBJS}
-.if ${MK_FAST_DEPEND} == "no"
-# Capture -include from CFLAGS.
-# This could be simpler with bmake :tW but needs to support fmake for MFC.
-_CFLAGS_INCLUDES= ${CFLAGS:Q:S/\\ /,/g:C/-include,/-include%/g:C/,/ /g:M-include*:C/%/ /g}
-_CXXFLAGS_INCLUDES= ${CXXFLAGS:Q:S/\\ /,/g:C/-include,/-include%/g:C/,/ /g:M-include*:C/%/ /g}
-
-# Different types of sources are compiled with slightly different flags.
-# Split up the sources, and filter out headers and non-applicable flags.
-MKDEP_CFLAGS= ${CFLAGS:M-nostdinc*} ${CFLAGS:M-[BIDU]*} ${CFLAGS:M-std=*} \
- ${CFLAGS:M-ansi} ${_CFLAGS_INCLUDES}
-MKDEP_CXXFLAGS= ${CXXFLAGS:M-nostdinc*} ${CXXFLAGS:M-[BIDU]*} \
- ${CXXFLAGS:M-std=*} ${CXXFLAGS:M-ansi} ${CXXFLAGS:M-stdlib=*} \
- ${_CXXFLAGS_INCLUDES}
-.endif # ${MK_FAST_DEPEND} == "no"
-
DPSRCS+= ${SRCS}
-# FAST_DEPEND will only generate a .depend if _EXTRADEPEND is used but
-# the target is created to allow 'make depend' to generate files.
+# A .depend file will only be generated if there are commands in
+# beforedepend/_EXTRADEPEND/afterdepend. The target is kept
+# to allow 'make depend' to generate files.
${DEPENDFILE}: ${DPSRCS}
.if exists(${.OBJDIR}/${DEPENDFILE})
rm -f ${DEPENDFILE}
.endif
-.if ${MK_FAST_DEPEND} == "no"
-.if !empty(DPSRCS:M*.[cS])
- ${MKDEPCMD} -f ${DEPENDFILE} -a ${MKDEP} \
- ${MKDEP_CFLAGS} ${.ALLSRC:M*.[cS]}
-.endif
-.if !empty(DPSRCS:M*.cc) || !empty(DPSRCS:M*.C) || !empty(DPSRCS:M*.cpp) || \
- !empty(DPSRCS:M*.cxx)
- ${MKDEPCMD} -f ${DEPENDFILE} -a ${MKDEP} \
- ${MKDEP_CXXFLAGS} \
- ${.ALLSRC:M*.cc} ${.ALLSRC:M*.C} ${.ALLSRC:M*.cpp} ${.ALLSRC:M*.cxx}
-.else
-.endif
-.endif # ${MK_FAST_DEPEND} == "no"
.if target(_EXTRADEPEND)
_EXTRADEPEND: .USE
${DEPENDFILE}: _EXTRADEPEND
diff --git a/share/mk/bsd.lib.mk b/share/mk/bsd.lib.mk
index 29a95e5..2169925 100644
--- a/share/mk/bsd.lib.mk
+++ b/share/mk/bsd.lib.mk
@@ -226,27 +226,10 @@ ${SHLIB_NAME_FULL}: beforelinking
.endif
.if defined(SHLIB_LINK)
-# ${_LDSCRIPTROOT} is needed when cross-building
-# and when building 32 bits library shims.
-#
-# ${_LDSCRIPTROOT} is the directory prefix that will be used when generating
-# ld(1) scripts. The crosstools' ld is configured to lookup libraries in an
-# alternative directory which is called "sysroot", so during buildworld binaries
-# won't be linked against the running system libraries but against the ones of
-# the current source tree. ${_LDSCRIPTROOT} behavior is twisted because of
-# the location where we store them:
-# - 64 bits libs are located under sysroot, so ${_LDSCRIPTROOT} must be empty
-# because ld(1) will manage to find them from sysroot;
-# - 32 bits shims are not, so ${_LDSCRIPTROOT} is used to specify their full
-# path, outside of sysroot.
-# Note that ld(1) scripts are generated both during buildworld and
-# installworld; in the later case ${_LDSCRIPTROOT} must be obviously empty
-# because on the target system, libraries are meant to be looked up from /.
.if defined(SHLIB_LDSCRIPT) && !empty(SHLIB_LDSCRIPT) && exists(${.CURDIR}/${SHLIB_LDSCRIPT})
${SHLIB_LINK:R}.ld: ${.CURDIR}/${SHLIB_LDSCRIPT}
- sed -e 's,@@SHLIB@@,${_LDSCRIPTROOT}${_SHLIBDIR}/${SHLIB_NAME},g' \
- -e 's,@@LIBDIR@@,${_LDSCRIPTROOT}${_LIBDIR},g' \
- -e 's,/[^ ]*/,,g' \
+ sed -e 's,@@SHLIB@@,${_SHLIBDIR}/${SHLIB_NAME},g' \
+ -e 's,@@LIBDIR@@,${_LIBDIR},g' \
${.ALLSRC} > ${.TARGET}
${SHLIB_NAME_FULL}: ${SHLIB_LINK:R}.ld
@@ -317,12 +300,6 @@ all: all-man
.endif
_EXTRADEPEND:
-.if ${MK_FAST_DEPEND} == "no"
- @TMP=_depend$$$$; \
- sed -e 's/^\([^\.]*\).o[ ]*:/\1.o \1.po \1.So:/' < ${DEPENDFILE} \
- > $$TMP; \
- mv $$TMP ${DEPENDFILE}
-.endif
.if !defined(NO_EXTRADEPEND) && defined(SHLIB_NAME)
.if defined(DPADD) && !empty(DPADD)
echo ${SHLIB_NAME_FULL}: ${DPADD} >> ${DEPENDFILE}
@@ -452,23 +429,6 @@ OBJS_DEPEND_GUESS.${_S:R}.So= ${_S}
.endif
.include <bsd.dep.mk>
-
-.if ${MK_FAST_DEPEND} == "no" && !exists(${.OBJDIR}/${DEPENDFILE})
-.if defined(LIB) && !empty(LIB)
-${OBJS} ${STATICOBJS} ${POBJS}: ${OBJS_DEPEND_GUESS}
-.for _S in ${SRCS:N*.[hly]}
-${_S:R}.po: ${OBJS_DEPEND_GUESS.${_S:R}.po}
-.endfor
-.endif
-.if defined(SHLIB_NAME) || \
- defined(INSTALL_PIC_ARCHIVE) && defined(LIB) && !empty(LIB)
-${SOBJS}: ${OBJS_DEPEND_GUESS}
-.for _S in ${SRCS:N*.[hly]}
-${_S:R}.So: ${OBJS_DEPEND_GUESS.${_S:R}.So}
-.endfor
-.endif
-.endif
-
.include <bsd.clang-analyze.mk>
.include <bsd.obj.mk>
.include <bsd.sys.mk>
diff --git a/share/mk/bsd.opts.mk b/share/mk/bsd.opts.mk
index 0fae155..3e321f3 100644
--- a/share/mk/bsd.opts.mk
+++ b/share/mk/bsd.opts.mk
@@ -52,7 +52,6 @@ __DEFAULT_YES_OPTIONS = \
ASSERT_DEBUG \
DEBUG_FILES \
DOCCOMPRESS \
- FAST_DEPEND \
INCLUDES \
INSTALLLIB \
KERBEROS \
@@ -79,12 +78,6 @@ __DEFAULT_DEPENDENT_OPTIONS = \
STAGING_PROG/STAGING \
-# Enable FAST_DEPEND by default for the meta build.
-.if !empty(.MAKE.MODE:Mmeta)
-__DEFAULT_YES_OPTIONS+= FAST_DEPEND
-__DEFAULT_NO_OPTIONS:= ${__DEFAULT_NO_OPTIONS:NFAST_DEPEND}
-.endif
-
.include <bsd.mkopt.mk>
#
diff --git a/share/mk/bsd.prog.mk b/share/mk/bsd.prog.mk
index 30c37ca..742eba9 100644
--- a/share/mk/bsd.prog.mk
+++ b/share/mk/bsd.prog.mk
@@ -8,6 +8,7 @@
# XXX The use of COPTS in modern makefiles is discouraged.
.if defined(COPTS)
+.warning ${.CURDIR}: COPTS should be CFLAGS.
CFLAGS+=${COPTS}
.endif
@@ -289,13 +290,6 @@ OBJS_DEPEND_GUESS+= ${SRCS:M*.h}
.endif
.include <bsd.dep.mk>
-
-.if defined(PROG)
-.if ${MK_FAST_DEPEND} == "no" && !exists(${.OBJDIR}/${DEPENDFILE})
-${OBJS}: ${OBJS_DEPEND_GUESS}
-.endif
-.endif
-
.include <bsd.clang-analyze.mk>
.include <bsd.obj.mk>
.include <bsd.sys.mk>
diff --git a/share/mk/bsd.progs.mk b/share/mk/bsd.progs.mk
index c5639b4..00dd566 100644
--- a/share/mk/bsd.progs.mk
+++ b/share/mk/bsd.progs.mk
@@ -24,7 +24,7 @@ PROGS += ${PROGS_CXX}
# just one of many
PROG_OVERRIDE_VARS += BINDIR BINGRP BINOWN BINMODE DPSRCS MAN NO_WERROR \
PROGNAME SRCS WARNS
-PROG_VARS += CFLAGS CPPFLAGS CXXFLAGS DPADD DPLIBS LDADD LIBADD LINKS \
+PROG_VARS += CFLAGS CXXFLAGS DPADD LDADD LIBADD LINKS \
LDFLAGS MLINKS ${PROG_OVERRIDE_VARS}
.for v in ${PROG_VARS:O:u}
.if empty(${PROG_OVERRIDE_VARS:M$v})
diff --git a/share/mk/bsd.sys.mk b/share/mk/bsd.sys.mk
index cf53d86..8471699 100644
--- a/share/mk/bsd.sys.mk
+++ b/share/mk/bsd.sys.mk
@@ -174,6 +174,10 @@ CFLAGS+= ${CWARNFLAGS.${.IMPSRC:T}}
CFLAGS+= ${CFLAGS.${COMPILER_TYPE}}
CXXFLAGS+= ${CXXFLAGS.${COMPILER_TYPE}}
+ACFLAGS+= ${ACFLAGS.${.IMPSRC:T}}
+CFLAGS+= ${CFLAGS.${.IMPSRC:T}}
+CXXFLAGS+= ${CXXFLAGS.${.IMPSRC:T}}
+
# Tell bmake not to mistake standard targets for things to be searched for
# or expect to ever be up-to-date.
PHONY_NOTMAIN = analyze afterdepend afterinstall all beforedepend beforeinstall \
@@ -231,7 +235,6 @@ stage_files.shlib: ${_LIBS:M*.so.*}
.endif
.if defined(SHLIB_LINK) && commands(${SHLIB_LINK:R}.ld)
-_LDSCRIPTROOT?= ${STAGE_OBJTOP}
STAGE_AS_SETS+= ldscript
STAGE_AS.ldscript+= ${SHLIB_LINK:R}.ld
stage_as.ldscript: ${SHLIB_LINK:R}.ld
diff --git a/share/mk/dirdeps.mk b/share/mk/dirdeps.mk
index efc729c..a97d489 100644
--- a/share/mk/dirdeps.mk
+++ b/share/mk/dirdeps.mk
@@ -1,5 +1,5 @@
# $FreeBSD$
-# $Id: dirdeps.mk,v 1.59 2016/02/26 23:32:29 sjg Exp $
+# $Id: dirdeps.mk,v 1.62 2016/03/16 00:11:53 sjg Exp $
# Copyright (c) 2010-2013, Juniper Networks, Inc.
# All rights reserved.
@@ -136,7 +136,6 @@ start_utc := ${now_utc}
# make sure these are empty to start with
_DEP_TARGET_SPEC =
-_DIRDEP_CHECKED =
# If TARGET_SPEC_VARS is other than just MACHINE
# it should be set by sys.mk or similar by now.
@@ -226,7 +225,7 @@ _DEP_TARGET_SPEC = ${_last_dependfile:${M_dep_qual_fixes:ts:}:E}
.endif
.if !empty(_last_dependfile)
# record that we've read dependfile for this
-_DIRDEP_CHECKED += ${_CURDIR}.${TARGET_SPEC}
+_dirdeps_checked.${_CURDIR}.${TARGET_SPEC}:
.endif
.endif
@@ -307,8 +306,10 @@ DEP_SKIP_DIR = ${SKIP_DIR} \
NSkipDir = ${DEP_SKIP_DIR:${M_ListToSkip}}
.if defined(NO_DIRDEPS) || defined(NODIRDEPS) || defined(WITHOUT_DIRDEPS)
-# confine ourselves to the original dir
+# confine ourselves to the original dir and below.
DIRDEPS_FILTER += M${_DEP_RELDIR}*
+.elif defined(NO_DIRDEPS_BELOW)
+DIRDEPS_FILTER += M${_DEP_RELDIR}
.endif
# this is what we run below
@@ -598,9 +599,9 @@ ${_this_dir}.$m: ${_build_dirs:M*.$m:N${_this_dir}.$m}
# Now find more dependencies - and recurse.
.for d in ${_build_all_dirs}
-.if ${_DIRDEP_CHECKED:M$d} == ""
+.if !target(_dirdeps_checked.$d)
# once only
-_DIRDEP_CHECKED += $d
+_dirdeps_checked.$d:
.if ${_debug_search}
.info checking $d
.endif
diff --git a/share/mk/local.dirdeps.mk b/share/mk/local.dirdeps.mk
index af7cf77..d5d9e40 100644
--- a/share/mk/local.dirdeps.mk
+++ b/share/mk/local.dirdeps.mk
@@ -9,15 +9,6 @@
# DEP_MACHINE is set before we get here, this may not be.
DEP_RELDIR ?= ${RELDIR}
-.if ${.TARGETS:Uall:M*/*} && empty(DIRDEPS)
-# This little trick let's us do
-#
-# mk -f dirdeps.mk some/dir.i386,bsd
-#
-DIRDEPS := ${.TARGETS:M*/*}
-${.TARGETS:Nall}: all
-.endif
-
# making universe is special
.if defined(UNIVERSE_GUARD)
# these should be done by now
diff --git a/share/mk/local.meta.sys.mk b/share/mk/local.meta.sys.mk
index 14bfb64..e55d68d 100644
--- a/share/mk/local.meta.sys.mk
+++ b/share/mk/local.meta.sys.mk
@@ -6,12 +6,11 @@
# we need this until there is an alternative
MK_INSTALL_AS_USER= yes
-MK_FAST_DEPEND= yes
_default_makeobjdir=$${.CURDIR:S,^$${SRCTOP},$${OBJTOP},}
.if empty(OBJROOT) || ${.MAKE.LEVEL} == 0
-.if defined(MAKEOBJDIRPREFIX)
+.if defined(MAKEOBJDIRPREFIX) && !empty(MAKEOBJDIRPREFIX)
# put things approximately where they want
OBJROOT:=${MAKEOBJDIRPREFIX}${SRCTOP}/
MAKEOBJDIRPREFIX=
@@ -180,7 +179,7 @@ STAGE_INCSDIR= ${STAGE_OBJTOP}${INCSDIR:U/include}
# the target is usually an absolute path
STAGE_SYMLINKS_DIR= ${STAGE_OBJTOP}
-LDFLAGS_LAST+= -Wl,-rpath-link -Wl,${STAGE_LIBDIR}
+LDFLAGS_LAST+= -Wl,-rpath-link,${STAGE_LIBDIR}
.if ${MK_SYSROOT} == "yes"
SYSROOT?= ${STAGE_OBJTOP}
.else
diff --git a/share/mk/local.sys.mk b/share/mk/local.sys.mk
index ae022a1..ced441f 100644
--- a/share/mk/local.sys.mk
+++ b/share/mk/local.sys.mk
@@ -23,6 +23,10 @@ MAKE_PRINT_VAR_ON_ERROR += .MAKE.MAKEFILES .PATH
.endif
.endif
+.if !empty(.OBJDIR)
+OBJTOP?= ${.OBJDIR:S,${.CURDIR},,}${SRCTOP}
+.endif
+
.include "src.sys.mk"
.if ${.MAKE.MODE:Mmeta*} != ""
diff --git a/share/mk/meta.stage.mk b/share/mk/meta.stage.mk
index e315828..0baddba 100644
--- a/share/mk/meta.stage.mk
+++ b/share/mk/meta.stage.mk
@@ -1,5 +1,5 @@
# $FreeBSD$
-# $Id: meta.stage.mk,v 1.43 2016/02/24 18:46:32 sjg Exp $
+# $Id: meta.stage.mk,v 1.44 2016/03/16 18:21:23 sjg Exp $
#
# @(#) Copyright (c) 2011, Simon J. Gerraty
#
@@ -59,7 +59,7 @@ GENDIRDEPS_FILTER += Nnot-empty-is-important \
LN_CP_SCRIPT = LnCp() { \
rm -f $$2 2> /dev/null; \
- ln $$1 $$2 2> /dev/null || \
+ { [ -z "$$mode" ] && ln $$1 $$2 2> /dev/null; } || \
cp -p $$1 $$2; }
# a staging conflict should cause an error
diff --git a/share/mk/src.opts.mk b/share/mk/src.opts.mk
index a3d6a0c..8518b71 100644
--- a/share/mk/src.opts.mk
+++ b/share/mk/src.opts.mk
@@ -355,6 +355,7 @@ MK_CLANG:= no
MK_GCC:= no
MK_GDB:= no
MK_INCLUDES:= no
+MK_LLDB:= no
.endif
.if ${MK_CLANG} == "no"
diff --git a/sys/amd64/amd64/autoconf.c b/sys/amd64/amd64/autoconf.c
deleted file mode 100644
index ee32740..0000000
--- a/sys/amd64/amd64/autoconf.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/*-
- * Copyright (c) 1990 The Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * William Jolitz.
- *
- * 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.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
- *
- * from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*
- * Setup the system to run on the current machine.
- *
- * Configure() is called at boot time and initializes the vba
- * device tables and the memory controller monitoring. Available
- * devices are determined (from possibilities mentioned in ioconf.c),
- * and the drivers are initialized.
- */
-#include "opt_bootp.h"
-#include "opt_isa.h"
-#include "opt_bus.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/conf.h>
-#include <sys/reboot.h>
-#include <sys/kernel.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/cons.h>
-
-#include <sys/socket.h>
-#include <net/if.h>
-#include <net/if_dl.h>
-#include <net/if_types.h>
-#include <net/if_var.h>
-#include <net/ethernet.h>
-#include <netinet/in.h>
-
-#include <machine/md_var.h>
-
-#ifdef DEV_ISA
-#include <isa/isavar.h>
-
-device_t isa_bus_device = 0;
-#endif
-
-static void configure_first(void *);
-static void configure(void *);
-static void configure_final(void *);
-
-SYSINIT(configure1, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure_first, NULL);
-/* SI_ORDER_SECOND is hookable */
-SYSINIT(configure2, SI_SUB_CONFIGURE, SI_ORDER_THIRD, configure, NULL);
-/* SI_ORDER_MIDDLE is hookable */
-SYSINIT(configure3, SI_SUB_CONFIGURE, SI_ORDER_ANY, configure_final, NULL);
-
-/*
- * Determine i/o configuration for a machine.
- */
-static void
-configure_first(dummy)
- void *dummy;
-{
-
- /* nexus0 is the top of the amd64 device tree */
- device_add_child(root_bus, "nexus", 0);
-}
-
-static void
-configure(dummy)
- void *dummy;
-{
-
- /*
- * Enable interrupts on the processor. The interrupts are still
- * disabled in the interrupt controllers until interrupt handlers
- * are registered.
- */
- enable_intr();
-
- /* initialize new bus architecture */
- root_bus_configure();
-
-#ifdef DEV_ISA
- /*
- * Explicitly probe and attach ISA last. The isa bus saves
- * it's device node at attach time for us here.
- */
- if (isa_bus_device)
- isa_probe_children(isa_bus_device);
-#endif
-}
-
-static void
-configure_final(dummy)
- void *dummy;
-{
-
- cninit_finish();
- if (bootverbose)
- printf("Device configuration finished.\n");
- cold = 0;
-}
diff --git a/sys/amd64/amd64/sys_machdep.c b/sys/amd64/amd64/sys_machdep.c
index 7d9a748..7f6c50e 100644
--- a/sys/amd64/amd64/sys_machdep.c
+++ b/sys/amd64/amd64/sys_machdep.c
@@ -580,8 +580,8 @@ amd64_set_ldt(td, uap, descs)
struct i386_ldt_args *uap;
struct user_segment_descriptor *descs;
{
- int error = 0, i;
- int largest_ld;
+ int error = 0;
+ unsigned int largest_ld, i;
struct mdproc *mdp = &td->td_proc->p_md;
struct proc_ldt *pldt;
struct user_segment_descriptor *dp;
diff --git a/sys/amd64/amd64/vm_machdep.c b/sys/amd64/amd64/vm_machdep.c
index 13241ac..ee6dccd 100644
--- a/sys/amd64/amd64/vm_machdep.c
+++ b/sys/amd64/amd64/vm_machdep.c
@@ -102,8 +102,8 @@ get_pcb_user_save_td(struct thread *td)
vm_offset_t p;
p = td->td_kstack + td->td_kstack_pages * PAGE_SIZE -
- cpu_max_ext_state_size;
- KASSERT((p % 64) == 0, ("Unaligned pcb_user_save area"));
+ roundup2(cpu_max_ext_state_size, XSAVE_AREA_ALIGN);
+ KASSERT((p % XSAVE_AREA_ALIGN) == 0, ("Unaligned pcb_user_save area"));
return ((struct savefpu *)p);
}
@@ -122,7 +122,8 @@ get_pcb_td(struct thread *td)
vm_offset_t p;
p = td->td_kstack + td->td_kstack_pages * PAGE_SIZE -
- cpu_max_ext_state_size - sizeof(struct pcb);
+ roundup2(cpu_max_ext_state_size, XSAVE_AREA_ALIGN) -
+ sizeof(struct pcb);
return ((struct pcb *)p);
}
diff --git a/sys/amd64/cloudabi64/cloudabi64_sysvec.c b/sys/amd64/cloudabi64/cloudabi64_sysvec.c
index 7075488..16d3ef9 100644
--- a/sys/amd64/cloudabi64/cloudabi64_sysvec.c
+++ b/sys/amd64/cloudabi64/cloudabi64_sysvec.c
@@ -156,5 +156,6 @@ Elf64_Brandinfo cloudabi64_brand = {
.brand = ELFOSABI_CLOUDABI,
.machine = EM_X86_64,
.sysvec = &cloudabi64_elf_sysvec,
+ .flags = BI_CAN_EXEC_DYN,
.compat_3_brand = "CloudABI",
};
diff --git a/sys/amd64/conf/GENERIC.hints b/sys/amd64/conf/GENERIC.hints
index 39beae1..31311d0 100644
--- a/sys/amd64/conf/GENERIC.hints
+++ b/sys/amd64/conf/GENERIC.hints
@@ -30,6 +30,5 @@ hint.atrtc.0.irq="8"
hint.attimer.0.at="isa"
hint.attimer.0.port="0x40"
hint.attimer.0.irq="0"
-hint.wbwd.0.at="isa"
hint.acpi_throttle.0.disabled="1"
hint.p4tcc.0.disabled="1"
diff --git a/sys/amd64/include/intr_machdep.h b/sys/amd64/include/intr_machdep.h
index d37c795..22f9a49 100644
--- a/sys/amd64/include/intr_machdep.h
+++ b/sys/amd64/include/intr_machdep.h
@@ -83,7 +83,7 @@
#ifndef LOCORE
-typedef void inthand_t(u_int cs, u_int ef, u_int esp, u_int ss);
+typedef void inthand_t(void);
#define IDTVEC(name) __CONCAT(X,name)
diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h
index ddeb257..e4c50eb 100644
--- a/sys/amd64/include/md_var.h
+++ b/sys/amd64/include/md_var.h
@@ -36,9 +36,6 @@
extern uint64_t *vm_page_dump;
-/* XXX */
-typedef void alias_for_inthand_t(u_int cs, u_int ef, u_int esp, u_int ss);
-
struct savefpu;
void amd64_db_resume_dbreg(void);
diff --git a/sys/amd64/linux32/linux32_dummy.c b/sys/amd64/linux32/linux32_dummy.c
index e4e9f50..1104651 100644
--- a/sys/amd64/linux32/linux32_dummy.c
+++ b/sys/amd64/linux32/linux32_dummy.c
@@ -69,7 +69,6 @@ DUMMY(mincore);
DUMMY(ptrace);
DUMMY(lookup_dcookie);
DUMMY(remap_file_pages);
-DUMMY(fstatfs64);
DUMMY(mbind);
DUMMY(get_mempolicy);
DUMMY(set_mempolicy);
diff --git a/sys/amd64/linux32/linux32_proto.h b/sys/amd64/linux32/linux32_proto.h
index e76384f..fd74495 100644
--- a/sys/amd64/linux32/linux32_proto.h
+++ b/sys/amd64/linux32/linux32_proto.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/amd64/linux32/syscalls.master 293907 2016-01-14 10:13:58Z glebius
+ * created from FreeBSD: head/sys/amd64/linux32/syscalls.master 297061 2016-03-20 13:21:20Z dchagin
*/
#ifndef _LINUX32_SYSPROTO_H_
@@ -844,7 +844,9 @@ struct linux_statfs64_args {
char buf_l_[PADL_(struct l_statfs64_buf *)]; struct l_statfs64_buf * buf; char buf_r_[PADR_(struct l_statfs64_buf *)];
};
struct linux_fstatfs64_args {
- register_t dummy;
+ char fd_l_[PADL_(l_uint)]; l_uint fd; char fd_r_[PADR_(l_uint)];
+ char bufsize_l_[PADL_(size_t)]; size_t bufsize; char bufsize_r_[PADR_(size_t)];
+ char buf_l_[PADL_(struct l_statfs64_buf *)]; struct l_statfs64_buf * buf; char buf_r_[PADR_(struct l_statfs64_buf *)];
};
struct linux_tgkill_args {
char tgid_l_[PADL_(int)]; int tgid; char tgid_r_[PADR_(int)];
diff --git a/sys/amd64/linux32/linux32_syscall.h b/sys/amd64/linux32/linux32_syscall.h
index 990adf3..f213377 100644
--- a/sys/amd64/linux32/linux32_syscall.h
+++ b/sys/amd64/linux32/linux32_syscall.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/amd64/linux32/syscalls.master 293907 2016-01-14 10:13:58Z glebius
+ * created from FreeBSD: head/sys/amd64/linux32/syscalls.master 297061 2016-03-20 13:21:20Z dchagin
*/
#define LINUX32_SYS_linux_exit 1
diff --git a/sys/amd64/linux32/linux32_syscalls.c b/sys/amd64/linux32/linux32_syscalls.c
index 79b96a7..beb6efc 100644
--- a/sys/amd64/linux32/linux32_syscalls.c
+++ b/sys/amd64/linux32/linux32_syscalls.c
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/amd64/linux32/syscalls.master 293907 2016-01-14 10:13:58Z glebius
+ * created from FreeBSD: head/sys/amd64/linux32/syscalls.master 297061 2016-03-20 13:21:20Z dchagin
*/
const char *linux32_syscallnames[] = {
diff --git a/sys/amd64/linux32/linux32_sysent.c b/sys/amd64/linux32/linux32_sysent.c
index 7d6d220..baa9baa 100644
--- a/sys/amd64/linux32/linux32_sysent.c
+++ b/sys/amd64/linux32/linux32_sysent.c
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/amd64/linux32/syscalls.master 293907 2016-01-14 10:13:58Z glebius
+ * created from FreeBSD: head/sys/amd64/linux32/syscalls.master 297061 2016-03-20 13:21:20Z dchagin
*/
#include "opt_compat.h"
@@ -288,7 +288,7 @@ struct sysent linux32_sysent[] = {
{ AS(linux_clock_getres_args), (sy_call_t *)linux_clock_getres, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 266 = linux_clock_getres */
{ AS(linux_clock_nanosleep_args), (sy_call_t *)linux_clock_nanosleep, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 267 = linux_clock_nanosleep */
{ AS(linux_statfs64_args), (sy_call_t *)linux_statfs64, AUE_STATFS, NULL, 0, 0, 0, SY_THR_STATIC }, /* 268 = linux_statfs64 */
- { 0, (sy_call_t *)linux_fstatfs64, AUE_FSTATFS, NULL, 0, 0, 0, SY_THR_STATIC }, /* 269 = linux_fstatfs64 */
+ { AS(linux_fstatfs64_args), (sy_call_t *)linux_fstatfs64, AUE_FSTATFS, NULL, 0, 0, 0, SY_THR_STATIC }, /* 269 = linux_fstatfs64 */
{ AS(linux_tgkill_args), (sy_call_t *)linux_tgkill, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 270 = linux_tgkill */
{ AS(linux_utimes_args), (sy_call_t *)linux_utimes, AUE_UTIMES, NULL, 0, 0, 0, SY_THR_STATIC }, /* 271 = linux_utimes */
{ AS(linux_fadvise64_64_args), (sy_call_t *)linux_fadvise64_64, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 272 = linux_fadvise64_64 */
diff --git a/sys/amd64/linux32/linux32_systrace_args.c b/sys/amd64/linux32/linux32_systrace_args.c
index 80889bf..fc4c89a 100644
--- a/sys/amd64/linux32/linux32_systrace_args.c
+++ b/sys/amd64/linux32/linux32_systrace_args.c
@@ -1820,7 +1820,11 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
}
/* linux_fstatfs64 */
case 269: {
- *n_args = 0;
+ struct linux_fstatfs64_args *p = params;
+ iarg[0] = p->fd; /* l_uint */
+ uarg[1] = p->bufsize; /* size_t */
+ uarg[2] = (intptr_t) p->buf; /* struct l_statfs64_buf * */
+ *n_args = 3;
break;
}
/* linux_tgkill */
@@ -5118,6 +5122,19 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
break;
/* linux_fstatfs64 */
case 269:
+ switch(ndx) {
+ case 0:
+ p = "l_uint";
+ break;
+ case 1:
+ p = "size_t";
+ break;
+ case 2:
+ p = "struct l_statfs64_buf *";
+ break;
+ default:
+ break;
+ };
break;
/* linux_tgkill */
case 270:
@@ -6878,6 +6895,9 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
break;
/* linux_fstatfs64 */
case 269:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
/* linux_tgkill */
case 270:
if (ndx == 0 || ndx == 1)
diff --git a/sys/amd64/linux32/syscalls.master b/sys/amd64/linux32/syscalls.master
index 0396b30..e40247e 100644
--- a/sys/amd64/linux32/syscalls.master
+++ b/sys/amd64/linux32/syscalls.master
@@ -450,7 +450,7 @@
267 AUE_NULL STD { int linux_clock_nanosleep(clockid_t which, int flags, \
struct l_timespec *rqtp, struct l_timespec *rmtp); }
268 AUE_STATFS STD { int linux_statfs64(char *path, size_t bufsize, struct l_statfs64_buf *buf); }
-269 AUE_FSTATFS STD { int linux_fstatfs64(void); }
+269 AUE_FSTATFS STD { int linux_fstatfs64(l_uint fd, size_t bufsize, struct l_statfs64_buf *buf); }
270 AUE_NULL STD { int linux_tgkill(int tgid, int pid, int sig); }
271 AUE_UTIMES STD { int linux_utimes(char *fname, \
struct l_timeval *tptr); }
diff --git a/sys/arm/allwinner/a10_gpio.c b/sys/arm/allwinner/a10_gpio.c
index df774b3..0eae992 100644
--- a/sys/arm/allwinner/a10_gpio.c
+++ b/sys/arm/allwinner/a10_gpio.c
@@ -136,8 +136,6 @@ extern const struct allwinner_padconf a31s_padconf;
#define A10_GPIO_GP_INT_STA 0x214
#define A10_GPIO_GP_INT_DEB 0x218
-static struct a10_gpio_softc *a10_gpio_sc;
-
#define A10_GPIO_WRITE(_sc, _off, _val) \
bus_space_write_4(_sc->sc_bst, _sc->sc_bsh, _off, _val)
#define A10_GPIO_READ(_sc, _off) \
@@ -562,12 +560,6 @@ a10_gpio_attach(device_t dev)
/* Node is not a GPIO controller. */
goto fail;
- a10_gpio_sc = sc;
- sc->sc_busdev = gpiobus_attach_bus(dev);
- if (sc->sc_busdev == NULL)
- goto fail;
-
-
/* Use the right pin data for the current SoC */
switch (allwinner_soc_type()) {
#ifdef SOC_ALLWINNER_A10
@@ -594,6 +586,10 @@ a10_gpio_attach(device_t dev)
return (ENOENT);
}
+ sc->sc_busdev = gpiobus_attach_bus(dev);
+ if (sc->sc_busdev == NULL)
+ goto fail;
+
/*
* Register as a pinctrl device
*/
diff --git a/sys/arm/allwinner/a10_hdmi.c b/sys/arm/allwinner/a10_hdmi.c
index 9bb9869..ff86fa0 100644
--- a/sys/arm/allwinner/a10_hdmi.c
+++ b/sys/arm/allwinner/a10_hdmi.c
@@ -195,6 +195,15 @@ __FBSDID("$FreeBSD$");
#define CEA_TAG_ID 0x02
#define CEA_DTD 0x03
#define DTD_BASIC_AUDIO (1 << 6)
+#define CEA_REV 0x02
+#define CEA_DATA_OFF 0x03
+#define CEA_DATA_START 4
+#define BLOCK_TAG(x) (((x) >> 5) & 0x7)
+#define BLOCK_TAG_VSDB 3
+#define BLOCK_LEN(x) ((x) & 0x1f)
+#define HDMI_VSDB_MINLEN 5
+#define HDMI_OUI "\x03\x0c\x00"
+#define HDMI_OUI_LEN 3
struct a10hdmi_softc {
struct resource *res;
@@ -372,6 +381,41 @@ a10hdmi_ddc_read(struct a10hdmi_softc *sc, int block, uint8_t *edid)
return (0);
}
+static int
+a10hdmi_detect_hdmi_vsdb(uint8_t *edid)
+{
+ int off, p, btag, blen;
+
+ if (edid[EXT_TAG] != CEA_TAG_ID)
+ return (0);
+
+ off = edid[CEA_DATA_OFF];
+
+ /* CEA data block collection starts at byte 4 */
+ if (off <= CEA_DATA_START)
+ return (0);
+
+ /* Parse the CEA data blocks */
+ for (p = CEA_DATA_START; p < off;) {
+ btag = BLOCK_TAG(edid[p]);
+ blen = BLOCK_LEN(edid[p]);
+
+ /* Make sure the length is sane */
+ if (p + blen + 1 > off)
+ break;
+
+ /* Look for a VSDB with the HDMI 24-bit IEEE registration ID */
+ if (btag == BLOCK_TAG_VSDB && blen >= HDMI_VSDB_MINLEN &&
+ memcmp(&edid[p + 1], HDMI_OUI, HDMI_OUI_LEN) == 0)
+ return (1);
+
+ /* Next data block */
+ p += (1 + blen);
+ }
+
+ return (0);
+}
+
static void
a10hdmi_detect_hdmi(struct a10hdmi_softc *sc, int *phdmi, int *paudio)
{
@@ -389,7 +433,7 @@ a10hdmi_detect_hdmi(struct a10hdmi_softc *sc, int *phdmi, int *paudio)
if (a10hdmi_ddc_read(sc, block, edid) != 0)
return;
- if (edid[EXT_TAG] == CEA_TAG_ID) {
+ if (a10hdmi_detect_hdmi_vsdb(edid) != 0) {
*phdmi = 1;
*paudio = ((edid[CEA_DTD] & DTD_BASIC_AUDIO) != 0);
return;
@@ -518,6 +562,9 @@ a10hdmi_set_videomode(device_t dev, const struct videomode *mode)
PLLCTRL0_VCO_S);
/* Setup display settings */
+ if (bootverbose)
+ device_printf(dev, "HDMI: %s, Audio: %s\n",
+ sc->has_hdmi ? "yes" : "no", sc->has_audio ? "yes" : "no");
val = 0;
if (sc->has_hdmi)
val |= VID_CTRL_HDMI_MODE;
diff --git a/sys/arm/allwinner/a10_mmc.c b/sys/arm/allwinner/a10_mmc.c
index b236c4b..dc341dd 100644
--- a/sys/arm/allwinner/a10_mmc.c
+++ b/sys/arm/allwinner/a10_mmc.c
@@ -943,3 +943,4 @@ static driver_t a10_mmc_driver = {
DRIVER_MODULE(a10_mmc, simplebus, a10_mmc_driver, a10_mmc_devclass, 0, 0);
DRIVER_MODULE(mmc, a10_mmc, mmc_driver, mmc_devclass, NULL, NULL);
+MODULE_DEPEND(a10_mmc, mmc, 1, 1, 1);
diff --git a/sys/arm/allwinner/allwinner_machdep.c b/sys/arm/allwinner/allwinner_machdep.c
index 549fdcb..7159acd 100644
--- a/sys/arm/allwinner/allwinner_machdep.c
+++ b/sys/arm/allwinner/allwinner_machdep.c
@@ -140,6 +140,7 @@ cpu_reset()
while (1);
}
+#if defined(SOC_ALLWINNER_A10)
static platform_method_t a10_methods[] = {
PLATFORMMETHOD(platform_attach, a10_attach),
PLATFORMMETHOD(platform_lastaddr, allwinner_lastaddr),
@@ -147,7 +148,10 @@ static platform_method_t a10_methods[] = {
PLATFORMMETHOD_END,
};
+FDT_PLATFORM_DEF(a10, "a10", 0, "allwinner,sun4i-a10");
+#endif
+#if defined(SOC_ALLWINNER_A20)
static platform_method_t a20_methods[] = {
PLATFORMMETHOD(platform_attach, a20_attach),
PLATFORMMETHOD(platform_lastaddr, allwinner_lastaddr),
@@ -159,7 +163,10 @@ static platform_method_t a20_methods[] = {
#endif
PLATFORMMETHOD_END,
};
+FDT_PLATFORM_DEF(a20, "a20", 0, "allwinner,sun7i-a20");
+#endif
+#if defined(SOC_ALLWINNER_A31)
static platform_method_t a31_methods[] = {
PLATFORMMETHOD(platform_attach, a31_attach),
PLATFORMMETHOD(platform_lastaddr, allwinner_lastaddr),
@@ -171,7 +178,10 @@ static platform_method_t a31_methods[] = {
#endif
PLATFORMMETHOD_END,
};
+FDT_PLATFORM_DEF(a31, "a31", 0, "allwinner,sun6i-a31");
+#endif
+#if defined(SOC_ALLWINNER_A31S)
static platform_method_t a31s_methods[] = {
PLATFORMMETHOD(platform_attach, a31s_attach),
PLATFORMMETHOD(platform_lastaddr, allwinner_lastaddr),
@@ -183,6 +193,8 @@ static platform_method_t a31s_methods[] = {
#endif
PLATFORMMETHOD_END,
};
+FDT_PLATFORM_DEF(a31s, "a31s", 0, "allwinner,sun6i-a31s");
+#endif
u_int
allwinner_soc_type(void)
@@ -195,8 +207,3 @@ allwinner_soc_family(void)
{
return (soc_family);
}
-
-FDT_PLATFORM_DEF(a10, "a10", 0, "allwinner,sun4i-a10");
-FDT_PLATFORM_DEF(a20, "a20", 0, "allwinner,sun7i-a20");
-FDT_PLATFORM_DEF(a31, "a31", 0, "allwinner,sun6i-a31");
-FDT_PLATFORM_DEF(a31s, "a31s", 0, "allwinner,sun6i-a31s");
diff --git a/sys/arm/amlogic/aml8726/aml8726_mmc.c b/sys/arm/amlogic/aml8726/aml8726_mmc.c
index a7cc9c1..0e24975 100644
--- a/sys/arm/amlogic/aml8726/aml8726_mmc.c
+++ b/sys/arm/amlogic/aml8726/aml8726_mmc.c
@@ -1099,3 +1099,4 @@ DRIVER_MODULE(aml8726_mmc, simplebus, aml8726_mmc_driver,
aml8726_mmc_devclass, 0, 0);
MODULE_DEPEND(aml8726_mmc, aml8726_gpio, 1, 1, 1);
DRIVER_MODULE(mmc, aml8726_mmc, mmc_driver, mmc_devclass, NULL, NULL);
+MODULE_DEPEND(aml8726_mmc, mmc, 1, 1, 1);
diff --git a/sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c b/sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c
index fc6a66e..3daa99f 100644
--- a/sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c
+++ b/sys/arm/amlogic/aml8726/aml8726_sdxc-m8.c
@@ -1378,3 +1378,4 @@ DRIVER_MODULE(aml8726_sdxc, simplebus, aml8726_sdxc_driver,
aml8726_sdxc_devclass, 0, 0);
MODULE_DEPEND(aml8726_sdxc, aml8726_gpio, 1, 1, 1);
DRIVER_MODULE(mmc, aml8726_sdxc, mmc_driver, mmc_devclass, NULL, NULL);
+MODULE_DEPEND(aml8726_sdxc, mmc, 1, 1, 1);
diff --git a/sys/arm/arm/gic.c b/sys/arm/arm/gic.c
index cf72820..23b9577 100644
--- a/sys/arm/arm/gic.c
+++ b/sys/arm/arm/gic.c
@@ -36,8 +36,6 @@ __FBSDID("$FreeBSD$");
#include "opt_platform.h"
-#include "opt_platform.h"
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
@@ -86,6 +84,7 @@ __FBSDID("$FreeBSD$");
#define GICD_ITARGETSR(n) (0x0800 + ((n) * 4)) /* v1 ICDIPTR */
#define GICD_ICFGR(n) (0x0C00 + ((n) * 4)) /* v1 ICDICFR */
#define GICD_SGIR(n) (0x0F00 + ((n) * 4)) /* v1 ICDSGIR */
+#define GICD_SGI_TARGET_SHIFT 16
/* CPU Registers */
#define GICC_CTLR 0x0000 /* v1 ICCICR */
@@ -118,16 +117,28 @@ __FBSDID("$FreeBSD$");
#endif
#ifdef ARM_INTRNG
+struct gic_irqsrc {
+ struct intr_irqsrc gi_isrc;
+ uint32_t gi_irq;
+ enum intr_polarity gi_pol;
+ enum intr_trigger gi_trig;
+};
+
static u_int gic_irq_cpu;
static int arm_gic_intr(void *);
-static int arm_gic_bind(device_t dev, struct intr_irqsrc *isrc);
+static int arm_gic_bind_intr(device_t dev, struct intr_irqsrc *isrc);
+
+#ifdef SMP
+u_int sgi_to_ipi[GIC_LAST_SGI - GIC_FIRST_SGI + 1];
+u_int sgi_first_unused = GIC_FIRST_SGI;
+#endif
#endif
struct arm_gic_softc {
device_t gic_dev;
#ifdef ARM_INTRNG
void * gic_intrhand;
- struct intr_irqsrc ** gic_irqs;
+ struct gic_irqsrc * gic_irqs;
#endif
struct resource * gic_res[3];
bus_space_tag_t gic_c_bst;
@@ -142,6 +153,10 @@ struct arm_gic_softc {
#endif
};
+#ifdef ARM_INTRNG
+#define GIC_INTR_ISRC(sc, irq) (&sc->gic_irqs[irq].gi_isrc)
+#endif
+
static struct resource_spec arm_gic_spec[] = {
{ SYS_RES_MEMORY, 0, RF_ACTIVE }, /* Distributor registers */
{ SYS_RES_MEMORY, 1, RF_ACTIVE }, /* CPU Interrupt Intf. registers */
@@ -151,6 +166,8 @@ static struct resource_spec arm_gic_spec[] = {
{ -1, 0 }
};
+static u_int arm_gic_map[MAXCPU];
+
static struct arm_gic_softc *gic_sc = NULL;
#define gic_c_read_4(_sc, _reg) \
@@ -210,6 +227,29 @@ gic_irq_mask(struct arm_gic_softc *sc, u_int irq)
}
#endif
+static uint8_t
+gic_cpu_mask(struct arm_gic_softc *sc)
+{
+ uint32_t mask;
+ int i;
+
+ /* Read the current cpuid mask by reading ITARGETSR{0..7} */
+ for (i = 0; i < 8; i++) {
+ mask = gic_d_read_4(sc, GICD_ITARGETSR(i));
+ if (mask != 0)
+ break;
+ }
+ /* No mask found, assume we are on CPU interface 0 */
+ if (mask == 0)
+ return (1);
+
+ /* Collect the mask in the lower byte */
+ mask |= mask >> 16;
+ mask |= mask >> 8;
+
+ return (mask);
+}
+
#ifdef SMP
#ifdef ARM_INTRNG
static void
@@ -219,6 +259,9 @@ arm_gic_init_secondary(device_t dev)
struct intr_irqsrc *isrc;
u_int irq;
+ /* Set the mask so we can find this CPU to send it IPIs */
+ arm_gic_map[PCPU_GET(cpuid)] = gic_cpu_mask(sc);
+
for (irq = 0; irq < sc->nirqs; irq += 4)
gic_d_write_4(sc, GICD_IPRIORITYR(irq >> 2), 0);
@@ -238,7 +281,7 @@ arm_gic_init_secondary(device_t dev)
/* Unmask attached SGI interrupts. */
for (irq = GIC_FIRST_SGI; irq <= GIC_LAST_SGI; irq++) {
- isrc = sc->gic_irqs[irq];
+ isrc = GIC_INTR_ISRC(sc, irq);
if (isrc != NULL && isrc->isrc_handlers != 0) {
CPU_SET(PCPU_GET(cpuid), &isrc->isrc_cpu);
gic_irq_unmask(sc, irq);
@@ -247,7 +290,7 @@ arm_gic_init_secondary(device_t dev)
/* Unmask attached PPI interrupts. */
for (irq = GIC_FIRST_PPI; irq <= GIC_LAST_PPI; irq++) {
- isrc = sc->gic_irqs[irq];
+ isrc = GIC_INTR_ISRC(sc, irq);
if (isrc == NULL || isrc->isrc_handlers == 0)
continue;
if (isrc->isrc_flags & INTR_ISRCF_BOUND) {
@@ -266,6 +309,9 @@ arm_gic_init_secondary(device_t dev)
struct arm_gic_softc *sc = device_get_softc(dev);
int i;
+ /* Set the mask so we can find this CPU to send it IPIs */
+ arm_gic_map[PCPU_GET(cpuid)] = gic_cpu_mask(sc);
+
for (i = 0; i < sc->nirqs; i += 4)
gic_d_write_4(sc, GICD_IPRIORITYR(i >> 2), 0);
@@ -364,6 +410,46 @@ gic_xref(device_t dev)
return (0);
#endif
}
+
+static int
+arm_gic_register_isrcs(struct arm_gic_softc *sc, uint32_t num)
+{
+ int error;
+ uint32_t irq;
+ struct gic_irqsrc *irqs;
+ struct intr_irqsrc *isrc;
+ const char *name;
+
+ irqs = malloc(num * sizeof(struct gic_irqsrc), M_DEVBUF,
+ M_WAITOK | M_ZERO);
+
+ name = device_get_nameunit(sc->gic_dev);
+ for (irq = 0; irq < num; irq++) {
+ irqs[irq].gi_irq = irq;
+ irqs[irq].gi_pol = INTR_POLARITY_CONFORM;
+ irqs[irq].gi_trig = INTR_TRIGGER_CONFORM;
+
+ isrc = &irqs[irq].gi_isrc;
+ if (irq <= GIC_LAST_SGI) {
+ error = intr_isrc_register(isrc, sc->gic_dev,
+ INTR_ISRCF_IPI, "%s,i%u", name, irq - GIC_FIRST_SGI);
+ } else if (irq <= GIC_LAST_PPI) {
+ error = intr_isrc_register(isrc, sc->gic_dev,
+ INTR_ISRCF_PPI, "%s,p%u", name, irq - GIC_FIRST_PPI);
+ } else {
+ error = intr_isrc_register(isrc, sc->gic_dev, 0,
+ "%s,s%u", name, irq - GIC_FIRST_SPI);
+ }
+ if (error != 0) {
+ /* XXX call intr_isrc_deregister() */
+ free(irqs, M_DEVBUF);
+ return (error);
+ }
+ }
+ sc->gic_irqs = irqs;
+ sc->nirqs = num;
+ return (0);
+}
#endif
static int
@@ -371,7 +457,7 @@ arm_gic_attach(device_t dev)
{
struct arm_gic_softc *sc;
int i;
- uint32_t icciidr;
+ uint32_t icciidr, mask, nirqs;
#ifdef ARM_INTRNG
phandle_t pxref;
intptr_t xref = gic_xref(dev);
@@ -405,13 +491,17 @@ arm_gic_attach(device_t dev)
gic_d_write_4(sc, GICD_CTLR, 0x00);
/* Get the number of interrupts */
- sc->nirqs = gic_d_read_4(sc, GICD_TYPER);
- sc->nirqs = 32 * ((sc->nirqs & 0x1f) + 1);
+ nirqs = gic_d_read_4(sc, GICD_TYPER);
+ nirqs = 32 * ((nirqs & 0x1f) + 1);
#ifdef ARM_INTRNG
- sc->gic_irqs = malloc(sc->nirqs * sizeof (*sc->gic_irqs), M_DEVBUF,
- M_WAITOK | M_ZERO);
+ if (arm_gic_register_isrcs(sc, nirqs)) {
+ device_printf(dev, "could not register irqs\n");
+ goto cleanup;
+ }
#else
+ sc->nirqs = nirqs;
+
/* Set up function pointers */
arm_post_filter = gic_post_filter;
arm_config_irq = gic_config_irq;
@@ -432,10 +522,19 @@ arm_gic_attach(device_t dev)
gic_d_write_4(sc, GICD_ICENABLER(i >> 5), 0xFFFFFFFF);
}
+ /* Find the current cpu mask */
+ mask = gic_cpu_mask(sc);
+ /* Set the mask so we can find this CPU to send it IPIs */
+ arm_gic_map[PCPU_GET(cpuid)] = mask;
+ /* Set all four targets to this cpu */
+ mask |= mask << 8;
+ mask |= mask << 16;
+
for (i = 0; i < sc->nirqs; i += 4) {
gic_d_write_4(sc, GICD_IPRIORITYR(i >> 2), 0);
- gic_d_write_4(sc, GICD_ITARGETSR(i >> 2),
- 1 << 0 | 1 << 8 | 1 << 16 | 1 << 24);
+ if (i > 32) {
+ gic_d_write_4(sc, GICD_ITARGETSR(i >> 2), mask);
+ }
}
/* Set all the interrupts to be in Group 0 (secure) */
@@ -473,20 +572,20 @@ arm_gic_attach(device_t dev)
if (intr_pic_claim_root(dev, xref, arm_gic_intr, sc,
GIC_LAST_SGI - GIC_FIRST_SGI + 1) != 0) {
device_printf(dev, "could not set PIC as a root\n");
- intr_pic_unregister(dev, xref);
+ intr_pic_deregister(dev, xref);
goto cleanup;
}
} else {
if (sc->gic_res[2] == NULL) {
device_printf(dev,
"not root PIC must have defined interrupt\n");
- intr_pic_unregister(dev, xref);
+ intr_pic_deregister(dev, xref);
goto cleanup;
}
if (bus_setup_intr(dev, sc->gic_res[2], INTR_TYPE_CLK,
arm_gic_intr, NULL, sc, &sc->gic_intrhand)) {
device_printf(dev, "could not setup irq handler\n");
- intr_pic_unregister(dev, xref);
+ intr_pic_deregister(dev, xref);
goto cleanup;
}
}
@@ -510,7 +609,7 @@ static int
arm_gic_intr(void *arg)
{
struct arm_gic_softc *sc = arg;
- struct intr_irqsrc *isrc;
+ struct gic_irqsrc *gi;
uint32_t irq_active_reg, irq;
struct trapframe *tf;
@@ -546,14 +645,7 @@ arm_gic_intr(void *arg)
tf = curthread->td_intr_frame;
dispatch_irq:
- isrc = sc->gic_irqs[irq];
- if (isrc == NULL) {
- device_printf(sc->gic_dev, "Stray interrupt %u detected\n", irq);
- gic_irq_mask(sc, irq);
- gic_c_write_4(sc, GICC_EOIR, irq_active_reg);
- goto next_irq;
- }
-
+ gi = sc->gic_irqs + irq;
/*
* Note that GIC_FIRST_SGI is zero and is not used in 'if' statement
* as compiler complains that comparing u_int >= 0 is always true.
@@ -562,7 +654,7 @@ dispatch_irq:
#ifdef SMP
/* Call EOI for all IPI before dispatch. */
gic_c_write_4(sc, GICC_EOIR, irq_active_reg);
- intr_ipi_dispatch(isrc, tf);
+ intr_ipi_dispatch(sgi_to_ipi[gi->gi_irq], tf);
goto next_irq;
#else
device_printf(sc->gic_dev, "SGI %u on UP system detected\n",
@@ -575,10 +667,15 @@ dispatch_irq:
#ifdef GIC_DEBUG_SPURIOUS
sc->last_irq[PCPU_GET(cpuid)] = irq;
#endif
- if (isrc->isrc_trig == INTR_TRIGGER_EDGE)
+ if (gi->gi_trig == INTR_TRIGGER_EDGE)
gic_c_write_4(sc, GICC_EOIR, irq_active_reg);
- intr_irq_dispatch(isrc, tf);
+ if (intr_isrc_dispatch(&gi->gi_isrc, tf) != 0) {
+ gic_irq_mask(sc, irq);
+ if (gi->gi_trig != INTR_TRIGGER_EDGE)
+ gic_c_write_4(sc, GICC_EOIR, irq_active_reg);
+ device_printf(sc->gic_dev, "Stray irq %u disabled\n", irq);
+ }
next_irq:
arm_irq_memory_barrier(irq);
@@ -590,52 +687,6 @@ next_irq:
return (FILTER_HANDLED);
}
-static int
-gic_attach_isrc(struct arm_gic_softc *sc, struct intr_irqsrc *isrc, u_int irq)
-{
- const char *name;
-
- /*
- * 1. The link between ISRC and controller must be set atomically.
- * 2. Just do things only once in rare case when consumers
- * of shared interrupt came here at the same moment.
- */
- mtx_lock_spin(&sc->mutex);
- if (sc->gic_irqs[irq] != NULL) {
- mtx_unlock_spin(&sc->mutex);
- return (sc->gic_irqs[irq] == isrc ? 0 : EEXIST);
- }
- sc->gic_irqs[irq] = isrc;
- isrc->isrc_data = irq;
- mtx_unlock_spin(&sc->mutex);
-
- name = device_get_nameunit(sc->gic_dev);
- if (irq <= GIC_LAST_SGI)
- intr_irq_set_name(isrc, "%s,i%u", name, irq - GIC_FIRST_SGI);
- else if (irq <= GIC_LAST_PPI)
- intr_irq_set_name(isrc, "%s,p%u", name, irq - GIC_FIRST_PPI);
- else
- intr_irq_set_name(isrc, "%s,s%u", name, irq - GIC_FIRST_SPI);
- return (0);
-}
-
-static int
-gic_detach_isrc(struct arm_gic_softc *sc, struct intr_irqsrc *isrc, u_int irq)
-{
-
- mtx_lock_spin(&sc->mutex);
- if (sc->gic_irqs[irq] != isrc) {
- mtx_unlock_spin(&sc->mutex);
- return (sc->gic_irqs[irq] == NULL ? 0 : EINVAL);
- }
- sc->gic_irqs[irq] = NULL;
- isrc->isrc_data = 0;
- mtx_unlock_spin(&sc->mutex);
-
- intr_irq_set_name(isrc, "");
- return (0);
-}
-
static void
gic_config(struct arm_gic_softc *sc, u_int irq, enum intr_trigger trig,
enum intr_polarity pol)
@@ -693,127 +744,163 @@ gic_bind(struct arm_gic_softc *sc, u_int irq, cpuset_t *cpus)
return (0);
}
+#ifdef FDT
static int
-gic_irq_from_nspc(struct arm_gic_softc *sc, u_int type, u_int num, u_int *irqp)
+gic_map_fdt(device_t dev, u_int ncells, pcell_t *cells, u_int *irqp,
+ enum intr_polarity *polp, enum intr_trigger *trigp)
{
- switch (type) {
- case INTR_IRQ_NSPC_PLAIN:
- *irqp = num;
- return (*irqp < sc->nirqs ? 0 : EINVAL);
+ if (ncells == 1) {
+ *irqp = cells[0];
+ *polp = INTR_POLARITY_CONFORM;
+ *trigp = INTR_TRIGGER_CONFORM;
+ return (0);
+ }
+ if (ncells == 3) {
+ u_int irq, tripol;
- case INTR_IRQ_NSPC_IRQ:
- *irqp = num + GIC_FIRST_PPI;
- return (*irqp < sc->nirqs ? 0 : EINVAL);
+ /*
+ * The 1st cell is the interrupt type:
+ * 0 = SPI
+ * 1 = PPI
+ * The 2nd cell contains the interrupt number:
+ * [0 - 987] for SPI
+ * [0 - 15] for PPI
+ * The 3rd cell is the flags, encoded as follows:
+ * bits[3:0] trigger type and level flags
+ * 1 = low-to-high edge triggered
+ * 2 = high-to-low edge triggered
+ * 4 = active high level-sensitive
+ * 8 = active low level-sensitive
+ * bits[15:8] PPI interrupt cpu mask
+ * Each bit corresponds to each of the 8 possible cpus
+ * attached to the GIC. A bit set to '1' indicated
+ * the interrupt is wired to that CPU.
+ */
+ switch (cells[0]) {
+ case 0:
+ irq = GIC_FIRST_SPI + cells[1];
+ /* SPI irq is checked later. */
+ break;
+ case 1:
+ irq = GIC_FIRST_PPI + cells[1];
+ if (irq > GIC_LAST_PPI) {
+ device_printf(dev, "unsupported PPI interrupt "
+ "number %u\n", cells[1]);
+ return (EINVAL);
+ }
+ break;
+ default:
+ device_printf(dev, "unsupported interrupt type "
+ "configuration %u\n", cells[0]);
+ return (EINVAL);
+ }
- case INTR_IRQ_NSPC_IPI:
- *irqp = num + GIC_FIRST_SGI;
- return (*irqp < GIC_LAST_SGI ? 0 : EINVAL);
+ tripol = cells[2] & 0xff;
+ if (tripol & 0xf0 || (tripol & 0x0a && cells[0] == 0))
+ device_printf(dev, "unsupported trigger/polarity "
+ "configuration 0x%02x\n", tripol);
- default:
- return (EINVAL);
+ *irqp = irq;
+ *polp = INTR_POLARITY_CONFORM;
+ *trigp = tripol & 0x03 ? INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL;
+ return (0);
}
+ return (EINVAL);
}
+#endif
static int
-gic_map_nspc(struct arm_gic_softc *sc, struct intr_irqsrc *isrc, u_int *irqp)
-{
- int error;
-
- error = gic_irq_from_nspc(sc, isrc->isrc_nspc_type, isrc->isrc_nspc_num,
- irqp);
- if (error != 0)
- return (error);
- return (gic_attach_isrc(sc, isrc, *irqp));
-}
-
-#ifdef FDT
-static int
-gic_map_fdt(struct arm_gic_softc *sc, struct intr_irqsrc *isrc, u_int *irqp)
+gic_map_intr(device_t dev, struct intr_map_data *data, u_int *irqp,
+ enum intr_polarity *polp, enum intr_trigger *trigp)
{
- u_int irq, tripol;
- enum intr_trigger trig;
+ u_int irq;
enum intr_polarity pol;
- int error;
-
- if (isrc->isrc_ncells == 1) {
- irq = isrc->isrc_cells[0];
- pol = INTR_POLARITY_CONFORM;
- trig = INTR_TRIGGER_CONFORM;
- } else if (isrc->isrc_ncells == 3) {
- if (isrc->isrc_cells[0] == 0)
- irq = isrc->isrc_cells[1] + GIC_FIRST_SPI;
- else
- irq = isrc->isrc_cells[1] + GIC_FIRST_PPI;
+ enum intr_trigger trig;
+ struct arm_gic_softc *sc;
- /*
- * In intr[2], bits[3:0] are trigger type and level flags.
- * 1 = low-to-high edge triggered
- * 2 = high-to-low edge triggered
- * 4 = active high level-sensitive
- * 8 = active low level-sensitive
- * The hardware only supports active-high-level or rising-edge.
- */
- tripol = isrc->isrc_cells[2];
- if (tripol & 0x0a && irq >= GIC_FIRST_SPI) {
- device_printf(sc->gic_dev,
- "unsupported trigger/polarity configuration "
- "0x%02x\n", tripol & 0x0f);
- }
- pol = INTR_POLARITY_CONFORM;
- if (tripol & 0x03)
- trig = INTR_TRIGGER_EDGE;
- else
- trig = INTR_TRIGGER_LEVEL;
- } else
+ sc = device_get_softc(dev);
+ switch (data->type) {
+#ifdef FDT
+ case INTR_MAP_DATA_FDT:
+ if (gic_map_fdt(dev, data->fdt.ncells, data->fdt.cells, &irq,
+ &pol, &trig) != 0)
+ return (EINVAL);
+ break;
+#endif
+ default:
return (EINVAL);
+ }
if (irq >= sc->nirqs)
return (EINVAL);
-
- error = gic_attach_isrc(sc, isrc, irq);
- if (error != 0)
- return (error);
-
- isrc->isrc_nspc_type = INTR_IRQ_NSPC_PLAIN;
- isrc->isrc_nspc_num = irq;
- isrc->isrc_trig = trig;
- isrc->isrc_pol = pol;
+ if (pol != INTR_POLARITY_CONFORM && pol != INTR_POLARITY_LOW &&
+ pol != INTR_POLARITY_HIGH)
+ return (EINVAL);
+ if (trig != INTR_TRIGGER_CONFORM && trig != INTR_TRIGGER_EDGE &&
+ trig != INTR_TRIGGER_LEVEL)
+ return (EINVAL);
*irqp = irq;
+ if (polp != NULL)
+ *polp = pol;
+ if (trigp != NULL)
+ *trigp = trig;
return (0);
}
-#endif
static int
-arm_gic_register(device_t dev, struct intr_irqsrc *isrc, boolean_t *is_percpu)
+arm_gic_map_intr(device_t dev, struct intr_map_data *data,
+ struct intr_irqsrc **isrcp)
{
- struct arm_gic_softc *sc = device_get_softc(dev);
- u_int irq;
int error;
+ u_int irq;
+ struct arm_gic_softc *sc;
- if (isrc->isrc_type == INTR_ISRCT_NAMESPACE)
- error = gic_map_nspc(sc, isrc, &irq);
-#ifdef FDT
- else if (isrc->isrc_type == INTR_ISRCT_FDT)
- error = gic_map_fdt(sc, isrc, &irq);
-#endif
- else
- return (EINVAL);
-
- if (error == 0)
- *is_percpu = irq < GIC_FIRST_SPI ? TRUE : FALSE;
+ error = gic_map_intr(dev, data, &irq, NULL, NULL);
+ if (error == 0) {
+ sc = device_get_softc(dev);
+ *isrcp = GIC_INTR_ISRC(sc, irq);
+ }
return (error);
}
-static void
-arm_gic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
+static int
+arm_gic_setup_intr(device_t dev, struct intr_irqsrc *isrc,
+ struct resource *res, struct intr_map_data *data)
{
struct arm_gic_softc *sc = device_get_softc(dev);
- u_int irq = isrc->isrc_data;
+ struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc;
+ u_int irq;
+ enum intr_trigger trig;
+ enum intr_polarity pol;
- if (isrc->isrc_trig == INTR_TRIGGER_CONFORM)
- isrc->isrc_trig = INTR_TRIGGER_LEVEL;
+ if (data == NULL)
+ return (ENOTSUP);
+
+ /* Get config for resource. */
+ if (gic_map_intr(dev, data, &irq, &pol, &trig))
+ return (EINVAL);
+
+ if (gi->gi_irq != irq)
+ return (EINVAL);
+
+ /* Compare config if this is not first setup. */
+ if (isrc->isrc_handlers != 0) {
+ if ((pol != INTR_POLARITY_CONFORM && pol != gi->gi_pol) ||
+ (trig != INTR_TRIGGER_CONFORM && trig != gi->gi_trig))
+ return (EINVAL);
+ else
+ return (0);
+ }
+
+ if (pol == INTR_POLARITY_CONFORM)
+ pol = INTR_POLARITY_LOW; /* just pick some */
+ if (trig == INTR_TRIGGER_CONFORM)
+ trig = INTR_TRIGGER_EDGE; /* just pick some */
+
+ gi->gi_pol = pol;
+ gi->gi_trig = trig;
/*
* XXX - In case that per CPU interrupt is going to be enabled in time
@@ -822,48 +909,54 @@ arm_gic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
* pic_enable_source() and pic_disable_source() should act on
* per CPU basis only. Thus, it should be solved here somehow.
*/
- if (isrc->isrc_flags & INTR_ISRCF_PERCPU)
+ if (isrc->isrc_flags & INTR_ISRCF_PPI)
CPU_SET(PCPU_GET(cpuid), &isrc->isrc_cpu);
- gic_config(sc, irq, isrc->isrc_trig, isrc->isrc_pol);
- arm_gic_bind(dev, isrc);
+ gic_config(sc, gi->gi_irq, trig, pol);
+ arm_gic_bind_intr(dev, isrc);
+ return (0);
}
-static void
-arm_gic_enable_source(device_t dev, struct intr_irqsrc *isrc)
+static int
+arm_gic_teardown_intr(device_t dev, struct intr_irqsrc *isrc,
+ struct resource *res, struct intr_map_data *data)
{
- struct arm_gic_softc *sc = device_get_softc(dev);
- u_int irq = isrc->isrc_data;
+ struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc;
- arm_irq_memory_barrier(irq);
- gic_irq_unmask(sc, irq);
+ if (isrc->isrc_handlers == 0) {
+ gi->gi_pol = INTR_POLARITY_CONFORM;
+ gi->gi_trig = INTR_TRIGGER_CONFORM;
+ }
+ return (0);
}
static void
-arm_gic_disable_source(device_t dev, struct intr_irqsrc *isrc)
+arm_gic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
{
struct arm_gic_softc *sc = device_get_softc(dev);
- u_int irq = isrc->isrc_data;
+ struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc;
- gic_irq_mask(sc, irq);
+ arm_irq_memory_barrier(gi->gi_irq);
+ gic_irq_unmask(sc, gi->gi_irq);
}
-static int
-arm_gic_unregister(device_t dev, struct intr_irqsrc *isrc)
+static void
+arm_gic_disable_intr(device_t dev, struct intr_irqsrc *isrc)
{
struct arm_gic_softc *sc = device_get_softc(dev);
- u_int irq = isrc->isrc_data;
+ struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc;
- return (gic_detach_isrc(sc, isrc, irq));
+ gic_irq_mask(sc, gi->gi_irq);
}
static void
arm_gic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
{
struct arm_gic_softc *sc = device_get_softc(dev);
+ struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc;
- arm_gic_disable_source(dev, isrc);
- gic_c_write_4(sc, GICC_EOIR, isrc->isrc_data);
+ arm_gic_disable_intr(dev, isrc);
+ gic_c_write_4(sc, GICC_EOIR, gi->gi_irq);
}
static void
@@ -871,52 +964,66 @@ arm_gic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
{
arm_irq_memory_barrier(0);
- arm_gic_enable_source(dev, isrc);
+ arm_gic_enable_intr(dev, isrc);
}
static void
arm_gic_post_filter(device_t dev, struct intr_irqsrc *isrc)
{
struct arm_gic_softc *sc = device_get_softc(dev);
+ struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc;
/* EOI for edge-triggered done earlier. */
- if (isrc->isrc_trig == INTR_TRIGGER_EDGE)
+ if (gi->gi_trig == INTR_TRIGGER_EDGE)
return;
arm_irq_memory_barrier(0);
- gic_c_write_4(sc, GICC_EOIR, isrc->isrc_data);
+ gic_c_write_4(sc, GICC_EOIR, gi->gi_irq);
}
static int
-arm_gic_bind(device_t dev, struct intr_irqsrc *isrc)
+arm_gic_bind_intr(device_t dev, struct intr_irqsrc *isrc)
{
struct arm_gic_softc *sc = device_get_softc(dev);
- uint32_t irq = isrc->isrc_data;
+ struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc;
- if (irq < GIC_FIRST_SPI)
+ if (gi->gi_irq < GIC_FIRST_SPI)
return (EINVAL);
if (CPU_EMPTY(&isrc->isrc_cpu)) {
gic_irq_cpu = intr_irq_next_cpu(gic_irq_cpu, &all_cpus);
CPU_SETOF(gic_irq_cpu, &isrc->isrc_cpu);
}
- return (gic_bind(sc, irq, &isrc->isrc_cpu));
+ return (gic_bind(sc, gi->gi_irq, &isrc->isrc_cpu));
}
#ifdef SMP
static void
-arm_gic_ipi_send(device_t dev, struct intr_irqsrc *isrc, cpuset_t cpus)
+arm_gic_ipi_send(device_t dev, struct intr_irqsrc *isrc, cpuset_t cpus,
+ u_int ipi)
{
struct arm_gic_softc *sc = device_get_softc(dev);
- uint32_t irq, val = 0, i;
-
- irq = isrc->isrc_data;
+ struct gic_irqsrc *gi = (struct gic_irqsrc *)isrc;
+ uint32_t val = 0, i;
for (i = 0; i < MAXCPU; i++)
if (CPU_ISSET(i, &cpus))
- val |= 1 << (16 + i);
+ val |= arm_gic_map[i] << GICD_SGI_TARGET_SHIFT;
+
+ gic_d_write_4(sc, GICD_SGIR(0), val | gi->gi_irq);
+}
+
+static int
+arm_gic_ipi_setup(device_t dev, u_int ipi, struct intr_irqsrc **isrcp)
+{
+ struct arm_gic_softc *sc = device_get_softc(dev);
- gic_d_write_4(sc, GICD_SGIR(0), val | irq);
+ if (sgi_first_unused > GIC_LAST_SGI)
+ return (ENOSPC);
+
+ *isrcp = GIC_INTR_ISRC(sc, sgi_first_unused);
+ sgi_to_ipi[sgi_first_unused++] = ipi;
+ return (0);
}
#endif
#else
@@ -1029,7 +1136,7 @@ arm_gic_ipi_send(device_t dev, cpuset_t cpus, u_int ipi)
for (i = 0; i < MAXCPU; i++)
if (CPU_ISSET(i, &cpus))
- val |= 1 << (16 + i);
+ val |= arm_gic_map[i] << GICD_SGI_TARGET_SHIFT;
gic_d_write_4(sc, GICD_SGIR(0), val | ipi);
}
@@ -1134,18 +1241,19 @@ static device_method_t arm_gic_methods[] = {
DEVMETHOD(device_attach, arm_gic_attach),
#ifdef ARM_INTRNG
/* Interrupt controller interface */
- DEVMETHOD(pic_disable_source, arm_gic_disable_source),
+ DEVMETHOD(pic_disable_intr, arm_gic_disable_intr),
DEVMETHOD(pic_enable_intr, arm_gic_enable_intr),
- DEVMETHOD(pic_enable_source, arm_gic_enable_source),
+ DEVMETHOD(pic_map_intr, arm_gic_map_intr),
+ DEVMETHOD(pic_setup_intr, arm_gic_setup_intr),
+ DEVMETHOD(pic_teardown_intr, arm_gic_teardown_intr),
DEVMETHOD(pic_post_filter, arm_gic_post_filter),
DEVMETHOD(pic_post_ithread, arm_gic_post_ithread),
DEVMETHOD(pic_pre_ithread, arm_gic_pre_ithread),
- DEVMETHOD(pic_register, arm_gic_register),
- DEVMETHOD(pic_unregister, arm_gic_unregister),
#ifdef SMP
- DEVMETHOD(pic_bind, arm_gic_bind),
+ DEVMETHOD(pic_bind_intr, arm_gic_bind_intr),
DEVMETHOD(pic_init_secondary, arm_gic_init_secondary),
DEVMETHOD(pic_ipi_send, arm_gic_ipi_send),
+ DEVMETHOD(pic_ipi_setup, arm_gic_ipi_setup),
#endif
#endif
{ 0, 0 }
diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c
index e2310f1..ad0e699 100644
--- a/sys/arm/arm/machdep.c
+++ b/sys/arm/arm/machdep.c
@@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/cons.h>
#include <sys/cpu.h>
+#include <sys/ctype.h>
#include <sys/efi.h>
#include <sys/exec.h>
#include <sys/imgact.h>
@@ -74,6 +75,7 @@ __FBSDID("$FreeBSD$");
#include <sys/pcpu.h>
#include <sys/ptrace.h>
#include <sys/reboot.h>
+#include <sys/boot.h>
#include <sys/rwlock.h>
#include <sys/sched.h>
#include <sys/signalvar.h>
@@ -115,6 +117,7 @@ __FBSDID("$FreeBSD$");
#include <machine/sysarch.h>
#ifdef FDT
+#include <contrib/libfdt/libfdt.h>
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/openfirm.h>
#endif
@@ -178,6 +181,12 @@ DB_SHOW_COMMAND(vtop, db_show_vtop)
#define debugf(fmt, args...)
#endif
+#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
+ defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7) || \
+ defined(COMPAT_FREEBSD9)
+#error FreeBSD/arm doesn't provide compatibility with releases prior to 10
+#endif
+
struct pcpu __pcpu[MAXCPU];
struct pcpu *pcpup = &__pcpu[0];
@@ -225,6 +234,7 @@ static struct pv_addr kernelstack;
#if defined(LINUX_BOOT_ABI)
#define LBABI_MAX_BANKS 10
+#define CMDLINE_GUARD "FreeBSD:"
uint32_t board_id;
struct arm_lbabi_tag *atag_list;
char linux_command_line[LBABI_MAX_COMMAND_LINE + 1];
@@ -953,7 +963,8 @@ makectx(struct trapframe *tf, struct pcb *pcb)
* Fake up a boot descriptor table
*/
vm_offset_t
-fake_preload_metadata(struct arm_boot_params *abp __unused)
+fake_preload_metadata(struct arm_boot_params *abp __unused, void *dtb_ptr,
+ size_t dtb_size)
{
#ifdef DDB
vm_offset_t zstart = 0, zend = 0;
@@ -991,6 +1002,16 @@ fake_preload_metadata(struct arm_boot_params *abp __unused)
} else
#endif
lastaddr = (vm_offset_t)&end;
+ if (dtb_ptr != NULL) {
+ /* Copy DTB to KVA space and insert it into module chain. */
+ lastaddr = roundup(lastaddr, sizeof(int));
+ fake_preload[i++] = MODINFO_METADATA | MODINFOMD_DTBP;
+ fake_preload[i++] = sizeof(uint32_t);
+ fake_preload[i++] = (uint32_t)lastaddr;
+ memmove((void *)lastaddr, dtb_ptr, dtb_size);
+ lastaddr += dtb_size;
+ lastaddr = roundup(lastaddr, sizeof(int));
+ }
fake_preload[i++] = 0;
fake_preload[i] = 0;
preload_metadata = (void *)fake_preload;
@@ -1011,26 +1032,83 @@ pcpu0_init(void)
}
#if defined(LINUX_BOOT_ABI)
+
+/* Convert the U-Boot command line into FreeBSD kenv and boot options. */
+static void
+cmdline_set_env(char *cmdline, const char *guard)
+{
+ char *cmdline_next, *env;
+ size_t size, guard_len;
+ int i;
+
+ size = strlen(cmdline);
+ /* Skip leading spaces. */
+ for (; isspace(*cmdline) && (size > 0); cmdline++)
+ size--;
+
+ /* Test and remove guard. */
+ if (guard != NULL && guard[0] != '\0') {
+ guard_len = strlen(guard);
+ if (strncasecmp(cmdline, guard, guard_len) != 0)
+ return;
+ cmdline += guard_len;
+ size -= guard_len;
+ }
+
+ /* Skip leading spaces. */
+ for (; isspace(*cmdline) && (size > 0); cmdline++)
+ size--;
+
+ /* Replace ',' with '\0'. */
+ /* TODO: implement escaping for ',' character. */
+ cmdline_next = cmdline;
+ while(strsep(&cmdline_next, ",") != NULL)
+ ;
+ init_static_kenv(cmdline, 0);
+ /* Parse boothowto. */
+ for (i = 0; howto_names[i].ev != NULL; i++) {
+ env = kern_getenv(howto_names[i].ev);
+ if (env != NULL) {
+ if (strtoul(env, NULL, 10) != 0)
+ boothowto |= howto_names[i].mask;
+ freeenv(env);
+ }
+ }
+}
+
vm_offset_t
linux_parse_boot_param(struct arm_boot_params *abp)
{
struct arm_lbabi_tag *walker;
uint32_t revision;
uint64_t serial;
+ int size;
+ vm_offset_t lastaddr;
+#ifdef FDT
+ struct fdt_header *dtb_ptr;
+ uint32_t dtb_size;
+#endif
/*
* Linux boot ABI: r0 = 0, r1 is the board type (!= 0) and r2
* is atags or dtb pointer. If all of these aren't satisfied,
- * then punt.
+ * then punt. Unfortunately, it looks like DT enabled kernels
+ * doesn't uses board type and U-Boot delivers 0 in r1 for them.
*/
- if (!(abp->abp_r0 == 0 && abp->abp_r1 != 0 && abp->abp_r2 != 0))
- return 0;
+ if (abp->abp_r0 != 0 || abp->abp_r2 == 0)
+ return (0);
+#ifdef FDT
+ /* Test if r2 point to valid DTB. */
+ dtb_ptr = (struct fdt_header *)abp->abp_r2;
+ if (fdt_check_header(dtb_ptr) == 0) {
+ dtb_size = fdt_totalsize(dtb_ptr);
+ return (fake_preload_metadata(abp, dtb_ptr, dtb_size));
+ }
+#endif
board_id = abp->abp_r1;
- walker = (struct arm_lbabi_tag *)
- (abp->abp_r2 + KERNVIRTADDR - abp->abp_physaddr);
+ walker = (struct arm_lbabi_tag *)abp->abp_r2;
- /* xxx - Need to also look for binary device tree */
if (ATAG_TAG(walker) != ATAG_CORE)
return 0;
@@ -1046,8 +1124,9 @@ linux_parse_boot_param(struct arm_boot_params *abp)
case ATAG_INITRD2:
break;
case ATAG_SERIAL:
- serial = walker->u.tag_sn.low |
- ((uint64_t)walker->u.tag_sn.high << 32);
+ serial = walker->u.tag_sn.high;
+ serial <<= 32;
+ serial |= walker->u.tag_sn.low;
board_set_serial(serial);
break;
case ATAG_REVISION:
@@ -1055,9 +1134,12 @@ linux_parse_boot_param(struct arm_boot_params *abp)
board_set_revision(revision);
break;
case ATAG_CMDLINE:
- /* XXX open question: Parse this for boothowto? */
- bcopy(walker->u.tag_cmd.command, linux_command_line,
- ATAG_SIZE(walker));
+ size = ATAG_SIZE(walker) -
+ sizeof(struct arm_lbabi_header);
+ size = min(size, LBABI_MAX_COMMAND_LINE);
+ strncpy(linux_command_line, walker->u.tag_cmd.command,
+ size);
+ linux_command_line[size] = '\0';
break;
default:
break;
@@ -1069,9 +1151,9 @@ linux_parse_boot_param(struct arm_boot_params *abp)
bcopy(atag_list, atags,
(char *)walker - (char *)atag_list + ATAG_SIZE(walker));
- init_static_kenv(NULL, 0);
-
- return fake_preload_metadata(abp);
+ lastaddr = fake_preload_metadata(abp, NULL, 0);
+ cmdline_set_env(linux_command_line, CMDLINE_GUARD);
+ return lastaddr;
}
#endif
@@ -1129,7 +1211,7 @@ default_parse_boot_param(struct arm_boot_params *abp)
return lastaddr;
#endif
/* Fall back to hardcoded metadata. */
- lastaddr = fake_preload_metadata(abp);
+ lastaddr = fake_preload_metadata(abp, NULL, 0);
return lastaddr;
}
@@ -1747,6 +1829,12 @@ initarm(struct arm_boot_params *abp)
if (OF_init((void *)dtbp) != 0)
panic("OF_init failed with the found device tree");
+#if defined(LINUX_BOOT_ABI)
+ if (loader_envp == NULL && fdt_get_chosen_bootargs(linux_command_line,
+ LBABI_MAX_COMMAND_LINE) == 0)
+ cmdline_set_env(linux_command_line, CMDLINE_GUARD);
+#endif
+
#ifdef EFI
efihdr = (struct efi_map_header *)preload_search_info(kmdp,
MODINFO_METADATA | MODINFOMD_EFI_MAP);
diff --git a/sys/arm/arm/machdep_intr.c b/sys/arm/arm/machdep_intr.c
index 875f05e..504d262 100644
--- a/sys/arm/arm/machdep_intr.c
+++ b/sys/arm/arm/machdep_intr.c
@@ -1,8 +1,6 @@
-/* $NetBSD: intr.c,v 1.12 2003/07/15 00:24:41 lukem Exp $ */
-
/*-
- * Copyright (c) 2004 Olivier Houchard.
- * Copyright (c) 1994-1998 Mark Brinicombe.
+ * Copyright (c) 2015-2016 Svatopluk Kraus
+ * Copyright (c) 2015-2016 Michal Meloun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -13,27 +11,18 @@
* 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Mark Brinicombe
- * for the NetBSD Project.
- * 4. The name of the company nor the name of the author may be used to
- * endorse or promote products derived from this software without specific
- * prior written permission.
*
- * 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 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)
+ * 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.
- *
- * Soft interrupt and other generic interrupt functions.
*/
#include "opt_platform.h"
@@ -64,8 +53,18 @@ __FBSDID("$FreeBSD$");
#include "pic_if.h"
#ifdef SMP
-static struct intr_irqsrc ipi_sources[INTR_IPI_COUNT];
-static u_int ipi_next_num;
+#define INTR_IPI_NAMELEN (MAXCOMLEN + 1)
+
+struct intr_ipi {
+ intr_ipi_handler_t * ii_handler;
+ void * ii_handler_arg;
+ intr_ipi_send_t * ii_send;
+ void * ii_send_arg;
+ char ii_name[INTR_IPI_NAMELEN];
+ u_long * ii_count;
+};
+
+static struct intr_ipi ipi_sources[INTR_IPI_COUNT];
#endif
#endif
@@ -134,10 +133,7 @@ arm_irq_memory_barrier(uintptr_t irq)
#ifdef ARM_INTRNG
#ifdef SMP
-/*
- * Lookup IPI source.
- */
-static struct intr_irqsrc *
+static inline struct intr_ipi *
intr_ipi_lookup(u_int ipi)
{
@@ -147,112 +143,90 @@ intr_ipi_lookup(u_int ipi)
return (&ipi_sources[ipi]);
}
-/*
- * interrupt controller dispatch function for IPIs. It should
- * be called straight from the interrupt controller, when associated
- * interrupt source is learned. Or from anybody who has an interrupt
- * source mapped.
- */
void
-intr_ipi_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf)
+intr_ipi_dispatch(u_int ipi, struct trapframe *tf)
{
void *arg;
+ struct intr_ipi *ii;
- KASSERT(isrc != NULL, ("%s: no source", __func__));
+ ii = intr_ipi_lookup(ipi);
+ if (ii->ii_count == NULL)
+ panic("%s: not setup IPI %u", __func__, ipi);
- intr_ipi_increment_count(isrc->isrc_count, PCPU_GET(cpuid));
+ intr_ipi_increment_count(ii->ii_count, PCPU_GET(cpuid));
/*
* Supply ipi filter with trapframe argument
* if none is registered.
*/
- arg = isrc->isrc_arg != NULL ? isrc->isrc_arg : tf;
- isrc->isrc_ipifilter(arg);
+ arg = ii->ii_handler_arg != NULL ? ii->ii_handler_arg : tf;
+ ii->ii_handler(arg);
}
-/*
- * Map IPI into interrupt controller.
- *
- * Not SMP coherent.
- */
-static int
-ipi_map(struct intr_irqsrc *isrc, u_int ipi)
+void
+intr_ipi_send(cpuset_t cpus, u_int ipi)
{
- boolean_t is_percpu;
- int error;
-
- if (ipi >= INTR_IPI_COUNT)
- panic("%s: no such IPI %u", __func__, ipi);
-
- KASSERT(intr_irq_root_dev != NULL, ("%s: no root attached", __func__));
+ struct intr_ipi *ii;
- isrc->isrc_type = INTR_ISRCT_NAMESPACE;
- isrc->isrc_nspc_type = INTR_IRQ_NSPC_IPI;
- isrc->isrc_nspc_num = ipi_next_num;
+ ii = intr_ipi_lookup(ipi);
+ if (ii->ii_count == NULL)
+ panic("%s: not setup IPI %u", __func__, ipi);
- error = PIC_REGISTER(intr_irq_root_dev, isrc, &is_percpu);
- if (error == 0) {
- isrc->isrc_dev = intr_irq_root_dev;
- ipi_next_num++;
- }
- return (error);
+ ii->ii_send(ii->ii_send_arg, cpus, ipi);
}
-/*
- * Setup IPI handler to interrupt source.
- *
- * Note that there could be more ways how to send and receive IPIs
- * on a platform like fast interrupts for example. In that case,
- * one can call this function with ASIF_NOALLOC flag set and then
- * call intr_ipi_dispatch() when appropriate.
- *
- * Not SMP coherent.
- */
-int
-intr_ipi_set_handler(u_int ipi, const char *name, intr_ipi_filter_t *filter,
- void *arg, u_int flags)
+void
+intr_ipi_setup(u_int ipi, const char *name, intr_ipi_handler_t *hand,
+ void *h_arg, intr_ipi_send_t *send, void *s_arg)
{
- struct intr_irqsrc *isrc;
- int error;
+ struct intr_ipi *ii;
- if (filter == NULL)
- return(EINVAL);
+ ii = intr_ipi_lookup(ipi);
- isrc = intr_ipi_lookup(ipi);
- if (isrc->isrc_ipifilter != NULL)
- return (EEXIST);
+ KASSERT(hand != NULL, ("%s: ipi %u no handler", __func__, ipi));
+ KASSERT(send != NULL, ("%s: ipi %u no sender", __func__, ipi));
+ KASSERT(ii->ii_count == NULL, ("%s: ipi %u reused", __func__, ipi));
- if ((flags & AISHF_NOALLOC) == 0) {
- error = ipi_map(isrc, ipi);
- if (error != 0)
- return (error);
- }
+ ii->ii_handler = hand;
+ ii->ii_handler_arg = h_arg;
+ ii->ii_send = send;
+ ii->ii_send_arg = s_arg;
+ strlcpy(ii->ii_name, name, INTR_IPI_NAMELEN);
+ ii->ii_count = intr_ipi_setup_counters(name);
+}
- isrc->isrc_ipifilter = filter;
- isrc->isrc_arg = arg;
- isrc->isrc_handlers = 1;
- isrc->isrc_count = intr_ipi_setup_counters(name);
- isrc->isrc_index = 0; /* it should not be used in IPI case */
+/*
+ * Send IPI thru interrupt controller.
+ */
+static void
+pic_ipi_send(void *arg, cpuset_t cpus, u_int ipi)
+{
- if (isrc->isrc_dev != NULL) {
- PIC_ENABLE_INTR(isrc->isrc_dev, isrc);
- PIC_ENABLE_SOURCE(isrc->isrc_dev, isrc);
- }
- return (0);
+ KASSERT(intr_irq_root_dev != NULL, ("%s: no root attached", __func__));
+ PIC_IPI_SEND(intr_irq_root_dev, arg, cpus, ipi);
}
/*
- * Send IPI thru interrupt controller.
+ * Setup IPI handler on interrupt controller.
+ *
+ * Not SMP coherent.
*/
-void
-pic_ipi_send(cpuset_t cpus, u_int ipi)
+int
+intr_pic_ipi_setup(u_int ipi, const char *name, intr_ipi_handler_t *hand,
+ void *arg)
{
+ int error;
struct intr_irqsrc *isrc;
- isrc = intr_ipi_lookup(ipi);
-
KASSERT(intr_irq_root_dev != NULL, ("%s: no root attached", __func__));
- PIC_IPI_SEND(intr_irq_root_dev, isrc, cpus);
+
+ error = PIC_IPI_SETUP(intr_irq_root_dev, ipi, &isrc);
+ if (error != 0)
+ return (error);
+
+ isrc->isrc_handlers++;
+ intr_ipi_setup(ipi, name, hand, arg, pic_ipi_send, isrc);
+ return (0);
}
#endif
#endif
diff --git a/sys/arm/arm/mp_machdep.c b/sys/arm/arm/mp_machdep.c
index 41958a8..699881c 100644
--- a/sys/arm/arm/mp_machdep.c
+++ b/sys/arm/arm/mp_machdep.c
@@ -429,12 +429,11 @@ release_aps(void *dummy __unused)
return;
#ifdef ARM_INTRNG
- intr_ipi_set_handler(IPI_RENDEZVOUS, "rendezvous", ipi_rendezvous, NULL, 0);
- intr_ipi_set_handler(IPI_AST, "ast", ipi_ast, NULL, 0);
- intr_ipi_set_handler(IPI_STOP, "stop", ipi_stop, NULL, 0);
- intr_ipi_set_handler(IPI_PREEMPT, "preempt", ipi_preempt, NULL, 0);
- intr_ipi_set_handler(IPI_HARDCLOCK, "hardclock", ipi_hardclock, NULL, 0);
-
+ intr_pic_ipi_setup(IPI_RENDEZVOUS, "rendezvous", ipi_rendezvous, NULL);
+ intr_pic_ipi_setup(IPI_AST, "ast", ipi_ast, NULL);
+ intr_pic_ipi_setup(IPI_STOP, "stop", ipi_stop, NULL);
+ intr_pic_ipi_setup(IPI_PREEMPT, "preempt", ipi_preempt, NULL);
+ intr_pic_ipi_setup(IPI_HARDCLOCK, "hardclock", ipi_hardclock, NULL);
#else
#ifdef IPI_IRQ_START
start = IPI_IRQ_START;
@@ -502,7 +501,11 @@ ipi_all_but_self(u_int ipi)
other_cpus = all_cpus;
CPU_CLR(PCPU_GET(cpuid), &other_cpus);
CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
+#ifdef ARM_INTRNG
+ intr_ipi_send(other_cpus, ipi);
+#else
pic_ipi_send(other_cpus, ipi);
+#endif
}
void
@@ -514,7 +517,11 @@ ipi_cpu(int cpu, u_int ipi)
CPU_SET(cpu, &cpus);
CTR3(KTR_SMP, "%s: cpu: %d, ipi: %x", __func__, cpu, ipi);
+#ifdef ARM_INTRNG
+ intr_ipi_send(cpus, ipi);
+#else
pic_ipi_send(cpus, ipi);
+#endif
}
void
@@ -522,6 +529,9 @@ ipi_selected(cpuset_t cpus, u_int ipi)
{
CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
+#ifdef ARM_INTRNG
+ intr_ipi_send(cpus, ipi);
+#else
pic_ipi_send(cpus, ipi);
+#endif
}
-
diff --git a/sys/arm/arm/nexus.c b/sys/arm/arm/nexus.c
index 035e81f..b718c1d 100644
--- a/sys/arm/arm/nexus.c
+++ b/sys/arm/arm/nexus.c
@@ -281,7 +281,8 @@ nexus_config_intr(device_t dev, int irq, enum intr_trigger trig,
int ret = ENODEV;
#ifdef ARM_INTRNG
- ret = intr_irq_config(irq, trig, pol);
+ device_printf(dev, "bus_config_intr is obsolete and not supported!\n");
+ ret = EOPNOTSUPP;
#else
if (arm_config_irq)
ret = (*arm_config_irq)(irq, trig, pol);
@@ -293,22 +294,23 @@ static int
nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
driver_filter_t *filt, driver_intr_t *intr, void *arg, void **cookiep)
{
+#ifndef ARM_INTRNG
int irq;
+#endif
if ((rman_get_flags(res) & RF_SHAREABLE) == 0)
flags |= INTR_EXCL;
- for (irq = rman_get_start(res); irq <= rman_get_end(res); irq++) {
#ifdef ARM_INTRNG
- intr_irq_add_handler(child, filt, intr, arg, irq, flags,
- cookiep);
+ return(intr_setup_irq(child, res, filt, intr, arg, flags, cookiep));
#else
+ for (irq = rman_get_start(res); irq <= rman_get_end(res); irq++) {
arm_setup_irqhandler(device_get_nameunit(child),
filt, intr, arg, irq, flags, cookiep);
arm_unmask_irq(irq);
-#endif
}
return (0);
+#endif
}
static int
@@ -316,7 +318,7 @@ nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih)
{
#ifdef ARM_INTRNG
- return (intr_irq_remove_handler(child, rman_get_start(r), ih));
+ return (intr_teardown_irq(child, r, ih));
#else
return (arm_remove_irqhandler(rman_get_start(r), ih));
#endif
@@ -328,7 +330,7 @@ nexus_describe_intr(device_t dev, device_t child, struct resource *irq,
void *cookie, const char *descr)
{
- return (intr_irq_describe(rman_get_start(irq), cookie, descr));
+ return (intr_describe_irq(child, irq, cookie, descr));
}
#ifdef SMP
@@ -336,7 +338,7 @@ static int
nexus_bind_intr(device_t dev, device_t child, struct resource *irq, int cpu)
{
- return (intr_irq_bind(rman_get_start(irq), cpu));
+ return (intr_bind_irq(child, irq, cpu));
}
#endif
#endif
diff --git a/sys/arm/arm/vm_machdep.c b/sys/arm/arm/vm_machdep.c
index 70d6c70..fdab1c6 100644
--- a/sys/arm/arm/vm_machdep.c
+++ b/sys/arm/arm/vm_machdep.c
@@ -191,11 +191,7 @@ cpu_set_syscall_retval(struct thread *td, int error)
register_t code = ap[_QUAD_LOWWORD];
if (td->td_proc->p_sysent->sv_mask)
code &= td->td_proc->p_sysent->sv_mask;
- fixup = (
-#if defined(COMPAT_FREEBSD6) && defined(SYS_freebsd6_lseek)
- code != SYS_freebsd6_lseek &&
-#endif
- code != SYS_lseek) ? 1 : 0;
+ fixup = (code != SYS_lseek);
}
#endif
diff --git a/sys/arm/at91/at91.c b/sys/arm/at91/at91.c
index 0947ec7..34c19d7 100644
--- a/sys/arm/at91/at91.c
+++ b/sys/arm/at91/at91.c
@@ -281,9 +281,9 @@ at91_print_child(device_t dev, device_t child)
retval += bus_print_child_header(dev, child);
- retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx");
- retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
- retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+ retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#jx");
+ retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
+ retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
if (device_get_flags(dev))
retval += printf(" flags %#x", device_get_flags(dev));
diff --git a/sys/arm/at91/at91_mci.c b/sys/arm/at91/at91_mci.c
index 5bab815..ba6040f 100644
--- a/sys/arm/at91/at91_mci.c
+++ b/sys/arm/at91/at91_mci.c
@@ -1412,3 +1412,4 @@ DRIVER_MODULE(at91_mci, atmelarm, at91_mci_driver, at91_mci_devclass, NULL,
NULL);
#endif
DRIVER_MODULE(mmc, at91_mci, mmc_driver, mmc_devclass, NULL, NULL);
+MODULE_DEPEND(at91_mci, mmc, 1, 1, 1);
diff --git a/sys/arm/at91/at91_pinctrl.c b/sys/arm/at91/at91_pinctrl.c
index e5652d1..b795d91 100644
--- a/sys/arm/at91/at91_pinctrl.c
+++ b/sys/arm/at91/at91_pinctrl.c
@@ -330,8 +330,8 @@ pinctrl_print_res(struct pinctrl_devinfo *di)
int rv;
rv = 0;
- rv += resource_list_print_type(&di->rl, "mem", SYS_RES_MEMORY, "%#lx");
- rv += resource_list_print_type(&di->rl, "irq", SYS_RES_IRQ, "%ld");
+ rv += resource_list_print_type(&di->rl, "mem", SYS_RES_MEMORY, "%#jx");
+ rv += resource_list_print_type(&di->rl, "irq", SYS_RES_IRQ, "%jd");
return (rv);
}
diff --git a/sys/arm/at91/board_tsc4370.c b/sys/arm/at91/board_tsc4370.c
index 1bc0426..9c0658b 100644
--- a/sys/arm/at91/board_tsc4370.c
+++ b/sys/arm/at91/board_tsc4370.c
@@ -601,7 +601,7 @@ parse_boot_param(struct arm_boot_params *abp)
inkernel_bootinfo = *(struct tsc_bootinfo *)(abp->abp_r1);
}
- return fake_preload_metadata(abp);
+ return fake_preload_metadata(abp, NULL, 0);
}
ARM_BOARD(NONE, "TSC4370 Controller Board");
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_common.c b/sys/arm/broadcom/bcm2835/bcm2835_common.c
index 08f01a8..bcb84b7 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_common.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_common.c
@@ -56,14 +56,21 @@ fdt_intc_decode_ic(phandle_t node, pcell_t *intr, int *interrupt, int *trig,
int *pol)
{
- if (!fdt_is_compatible(node, "broadcom,bcm2835-armctrl-ic"))
- return (ENXIO);
-
- *interrupt = fdt32_to_cpu(intr[0]);
- *trig = INTR_TRIGGER_CONFORM;
- *pol = INTR_POLARITY_CONFORM;
-
- return (0);
+ if (fdt_is_compatible(node, "broadcom,bcm2835-armctrl-ic")) {
+ *interrupt = fdt32_to_cpu(intr[0]);
+ *trig = INTR_TRIGGER_CONFORM;
+ *pol = INTR_POLARITY_CONFORM;
+ return (0);
+ }
+#ifdef SOC_BCM2836
+ if (fdt_is_compatible(node, "brcm,bcm2836-l1-intc")) {
+ *interrupt = fdt32_to_cpu(intr[0]) + 72;
+ *trig = INTR_TRIGGER_CONFORM;
+ *pol = INTR_POLARITY_CONFORM;
+ return (0);
+ }
+#endif
+ return (ENXIO);
}
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c
index 981d73b..700edcc 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c
@@ -672,3 +672,4 @@ static driver_t bcm_sdhci_driver = {
DRIVER_MODULE(sdhci_bcm, simplebus, bcm_sdhci_driver, bcm_sdhci_devclass, 0, 0);
MODULE_DEPEND(sdhci_bcm, sdhci, 1, 1, 1);
DRIVER_MODULE(mmc, sdhci_bcm, mmc_driver, mmc_devclass, NULL, NULL);
+MODULE_DEPEND(sdhci_bcm, mmc, 1, 1, 1);
diff --git a/sys/arm/broadcom/bcm2835/std.rpi b/sys/arm/broadcom/bcm2835/std.rpi
index c53c720..793eab1 100644
--- a/sys/arm/broadcom/bcm2835/std.rpi
+++ b/sys/arm/broadcom/bcm2835/std.rpi
@@ -2,5 +2,4 @@
options KERNVIRTADDR=0xc0100000
makeoptions KERNVIRTADDR=0xc0100000
-options FREEBSD_BOOT_LOADER
options LINUX_BOOT_ABI
diff --git a/sys/arm/cavium/cns11xx/econa.c b/sys/arm/cavium/cns11xx/econa.c
index d3dbf06..df49f1f 100644
--- a/sys/arm/cavium/cns11xx/econa.c
+++ b/sys/arm/cavium/cns11xx/econa.c
@@ -526,9 +526,9 @@ econa_print_child(device_t dev, device_t child)
retval += bus_print_child_header(dev, child);
- retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx");
- retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
- retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+ retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#jx");
+ retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
+ retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
if (device_get_flags(dev))
retval += printf(" flags %#x", device_get_flags(dev));
diff --git a/sys/arm/conf/A10 b/sys/arm/conf/A10
index 678b564..31a5e24 100644
--- a/sys/arm/conf/A10
+++ b/sys/arm/conf/A10
@@ -61,7 +61,7 @@ device ahci # AHCI-compatible SATA controllers
# Console and misc
device uart
-device uart_ns8250
+device uart_snps
device pty
device snp
device md
diff --git a/sys/arm/conf/A20 b/sys/arm/conf/A20
index 9c7983c..ad3b29a 100644
--- a/sys/arm/conf/A20
+++ b/sys/arm/conf/A20
@@ -71,7 +71,7 @@ device ahci # AHCI-compatible SATA controllers
# Console and misc
device uart
-device uart_ns8250
+device uart_snps
device pty
device snp
device md
diff --git a/sys/arm/conf/ARMADA38X b/sys/arm/conf/ARMADA38X
index 7cc7702..13c3aa2 100644
--- a/sys/arm/conf/ARMADA38X
+++ b/sys/arm/conf/ARMADA38X
@@ -23,7 +23,6 @@ options SCHED_ULE # ULE scheduler
#options SCHED_4BSD # 4BSD scheduler
options SMP
-options ARM_INTRNG
# Debugging
#options DEBUG
@@ -49,7 +48,7 @@ device md
# Serial ports
device uart
-device uart_ns8250
+device uart_snps
# Network
device ether
diff --git a/sys/arm/conf/ATMEL b/sys/arm/conf/ATMEL
index f86f8e8..63cd785 100644
--- a/sys/arm/conf/ATMEL
+++ b/sys/arm/conf/ATMEL
@@ -57,11 +57,6 @@ options GEOM_PART_BSD # BSD partition scheme
options GEOM_PART_MBR # MBR partition scheme
options GEOM_PART_GPT # GUID Partition Tables.
options GEOM_LABEL # Provides labelization
-options COMPAT_FREEBSD5 # Compatible with FreeBSD5
-options COMPAT_FREEBSD6 # Compatible with FreeBSD6
-options COMPAT_FREEBSD7 # Compatible with FreeBSD7
-options COMPAT_FREEBSD9 # Compatible with FreeBSD9
-options COMPAT_FREEBSD10 # Compatible with FreeBSD10
options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
options KTRACE # ktrace(1) support
options STACK # stack(9) support
diff --git a/sys/arm/conf/BEAGLEBONE b/sys/arm/conf/BEAGLEBONE
index 3950e17..1885c0c 100644
--- a/sys/arm/conf/BEAGLEBONE
+++ b/sys/arm/conf/BEAGLEBONE
@@ -28,6 +28,8 @@ include "../ti/am335x/std.am335x"
makeoptions MODULES_EXTRA="dtb/am335x am335x_dmtpps"
+options ARM_INTRNG
+
options HZ=100
options SCHED_4BSD # 4BSD scheduler
options PLATFORM
@@ -87,6 +89,10 @@ device gpio
device gpioled
device gpiobacklight
+# SPI
+device ti_spi
+device spibus
+
# ADC support
device ti_adc
diff --git a/sys/arm/conf/CNS11XXNAS b/sys/arm/conf/CNS11XXNAS
index 2bb5920..6fc8876 100644
--- a/sys/arm/conf/CNS11XXNAS
+++ b/sys/arm/conf/CNS11XXNAS
@@ -46,11 +46,6 @@ options DDB # Enable the kernel debugger
#options DIAGNOSTIC
-#options COMPAT_FREEBSD5
-#options COMPAT_FREEBSD6
-#options COMPAT_FREEBSD7n
-
-
options SCHED_ULE # ULE scheduler
#options SCHED_4BSD # 4BSD scheduler
options GEOM_PART_BSD # BSD partition scheme
diff --git a/sys/arm/conf/EFIKA_MX b/sys/arm/conf/EFIKA_MX
index 7f978b2..8b4b4aa 100644
--- a/sys/arm/conf/EFIKA_MX
+++ b/sys/arm/conf/EFIKA_MX
@@ -30,9 +30,6 @@ options SOC_IMX51
options SCHED_4BSD # 4BSD scheduler
#options MD_ROOT # MD is a potential root device
#options NFSD # Network Filesystem Server
-#options COMPAT_FREEBSD5 # Compatible with FreeBSD5
-#options COMPAT_FREEBSD6 # Compatible with FreeBSD6
-#options COMPAT_FREEBSD7 # Compatible with FreeBSD7
options PLATFORM
options INCLUDE_CONFIG_FILE # Include this file in kernel
diff --git a/sys/arm/conf/ETHERNUT5 b/sys/arm/conf/ETHERNUT5
index 4604ff2..e54513b 100644
--- a/sys/arm/conf/ETHERNUT5
+++ b/sys/arm/conf/ETHERNUT5
@@ -53,9 +53,6 @@ options GEOM_PART_BSD # BSD partition scheme
options GEOM_PART_MBR # MBR partition scheme
#options GEOM_PART_GPT # GUID Partition Tables.
#options GEOM_LABEL # Provides labelization
-#options COMPAT_FREEBSD5 # Compatible with FreeBSD5
-#options COMPAT_FREEBSD6 # Compatible with FreeBSD6
-#options COMPAT_FREEBSD7 # Compatible with FreeBSD7
options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
options KTRACE # ktrace(1) support
#options STACK # stack(9) support
diff --git a/sys/arm/conf/IMX53 b/sys/arm/conf/IMX53
index 9724375..e320562 100644
--- a/sys/arm/conf/IMX53
+++ b/sys/arm/conf/IMX53
@@ -27,9 +27,6 @@ options SOC_IMX53
options SCHED_4BSD # 4BSD scheduler
#options NFSD # Network Filesystem Server
-#options COMPAT_FREEBSD5 # Compatible with FreeBSD5
-#options COMPAT_FREEBSD6 # Compatible with FreeBSD6
-#options COMPAT_FREEBSD7 # Compatible with FreeBSD7
options PLATFORM
options INCLUDE_CONFIG_FILE # Include this file in kernel
diff --git a/sys/arm/conf/JETSON-TK1 b/sys/arm/conf/JETSON-TK1
new file mode 100644
index 0000000..242e835
--- /dev/null
+++ b/sys/arm/conf/JETSON-TK1
@@ -0,0 +1,37 @@
+# Kernel configuration for Jetson TK1 board
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD$
+
+#NO_UNIVERSE
+
+include "TEGRA124"
+ident JETSON-TK1
+
+# Flattened Device Tree
+options FDT_DTB_STATIC
+makeoptions FDT_DTS_FILE=tegra124-jetson-tk1-fbsd.dts
+
+makeoptions MODULES_OVERRIDE=""
+#options BOOTVERBOSE
+#options BOOTHOWTO=RB_SINGLE
+
+#options ROOTDEVNAME=\"ufs:mmcsd0s2a\"
+options ROOTDEVNAME=\"ufs:ada0s1a\"
+
+# CTF doesn't works yet
+makeoptions WITHOUT_CTF=1
diff --git a/sys/arm/conf/NOTES b/sys/arm/conf/NOTES
index d32e6d6..3cd43af 100644
--- a/sys/arm/conf/NOTES
+++ b/sys/arm/conf/NOTES
@@ -58,6 +58,10 @@ nooptions SMP
nooptions MAXCPU
nooptions COMPAT_FREEBSD4
+nooptions COMPAT_FREEBSD5
+nooptions COMPAT_FREEBSD6
+nooptions COMPAT_FREEBSD7
+nooptions COMPAT_FREEBSD9
nooption PPC_PROBE_CHIPSET
nodevice fdc
diff --git a/sys/arm/conf/RK3188 b/sys/arm/conf/RK3188
index 49c8eae..ec6ddb8 100644
--- a/sys/arm/conf/RK3188
+++ b/sys/arm/conf/RK3188
@@ -59,7 +59,7 @@ device dwmmc
# Console and misc
device uart
-device uart_ns8250
+device uart_snps
device pty
device snp
device md
@@ -101,8 +101,6 @@ device wlan # 802.11 support
device wlan_wep # 802.11 WEP support
device wlan_ccmp # 802.11 CCMP support
device wlan_tkip # 802.11 TKIP support
-device urtwn
-device urtwnfw
device firmware # Used by the above
# USB Ethernet support, requires miibus
diff --git a/sys/arm/conf/SAM9260EK b/sys/arm/conf/SAM9260EK
index 1edee77..7248046 100644
--- a/sys/arm/conf/SAM9260EK
+++ b/sys/arm/conf/SAM9260EK
@@ -64,9 +64,6 @@ options GEOM_PART_BSD # BSD partition scheme
options GEOM_PART_MBR # MBR partition scheme
#options GEOM_PART_GPT # GUID Partition Tables.
#options GEOM_LABEL # Provides labelization
-#options COMPAT_FREEBSD5 # Compatible with FreeBSD5
-#options COMPAT_FREEBSD6 # Compatible with FreeBSD6
-#options COMPAT_FREEBSD7 # Compatible with FreeBSD7
options SCSI_DELAY=5000 # Delay (in ms) before probing SCSI
options KTRACE # ktrace(1) support
#options STACK # stack(9) support
diff --git a/sys/arm/conf/TEGRA124 b/sys/arm/conf/TEGRA124
new file mode 100644
index 0000000..1b3ec3f
--- /dev/null
+++ b/sys/arm/conf/TEGRA124
@@ -0,0 +1,157 @@
+#
+# Kernel configuration for NVIDIA Tegra124 based boards.
+#
+# For more information on this file, please read the config(5) manual page,
+# and/or the handbook section on Kernel Configuration Files:
+#
+# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
+#
+# The handbook is also available locally in /usr/share/doc/handbook
+# if you've installed the doc distribution, otherwise always see the
+# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
+# latest information.
+#
+# An exhaustive list of options and more detailed explanations of the
+# device lines is also present in the ../../conf/NOTES and NOTES files.
+# If you are in doubt as to the purpose or necessity of a line, check first
+# in NOTES.
+#
+# $FreeBSD$
+
+include "std.armv6"
+include "../nvidia/tegra124/std.tegra124"
+
+ident TEGRA124
+
+options HZ=100 # Scheduling quantum is 10 milliseconds.
+options SCHED_ULE # ULE scheduler
+options PLATFORM # Platform based SoC
+options PLATFORM_SMP
+options SMP # Enable multiple cores
+options LINUX_BOOT_ABI
+
+# Debugging for use in -current
+makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols
+options BREAK_TO_DEBUGGER
+options ALT_BREAK_TO_DEBUGGER
+#options VERBOSE_SYSINIT # Enable verbose sysinit messages
+options KDB # Enable kernel debugger support
+# For minimum debugger support (stable branch) use:
+#options KDB_TRACE # Print a stack trace for a panic
+# For full debugger support use this instead:
+options DDB # Enable the kernel debugger
+options INVARIANTS # Enable calls of extra sanity checking
+options INVARIANT_SUPPORT # Extra sanity checks of internal structures, required by INVARIANTS
+options WITNESS # Enable checks to detect deadlocks and cycles
+options WITNESS_SKIPSPIN # Don't run witness on spinlocks for speed
+
+# Interrupt controller
+device gic
+
+# ARM Generic Timer
+device generic_timer
+
+# EXT_RESOURCES pseudo devices
+options EXT_RESOURCES
+device clk
+device phy
+device hwreset
+device regulator
+
+# Pseudo devices.
+device loop # Network loopback
+device random # Entropy device
+device vlan # 802.1Q VLAN support
+#device tun # Packet tunnel.
+device md # Memory "disks"
+#device gif # IPv6 and IPv4 tunneling
+#device firmware # firmware assist module
+device ether # Ethernet support
+device miibus # Required for ethernet
+device bpf # Berkeley packet filter (required for DHCP)
+
+
+# General-purpose input/output
+device gpio
+#device gpioled
+
+# I2C support
+device iic
+device iicbus
+device icee
+
+# Serial (COM) ports
+device uart # Multi-uart driver
+device uart_ns8250
+
+# MMC/SD/SDIO Card slot support
+device sdhci # SD controller
+device mmc # SD/MMC protocol
+device mmcsd # SDCard disk device
+
+# ATA controllers
+device ahci # AHCI-compatible SATA controllers
+
+# SCSI peripherals
+device scbus # SCSI bus (required for ATA/SCSI)
+device da # Direct Access (disks)
+device cd # CD
+device pass # Passthrough device (direct ATA/SCSI access)
+
+# USB support
+options USB_HOST_ALIGN=64 # Align usb buffers to cache line size.
+options USB_DEBUG # enable debug msgs
+device ehci # EHCI USB interface
+device usb # USB Bus (required)
+device umass # Disks/Mass storage - Requires scbus and da
+device uhid # "Human Interface Devices"
+#device u3g # USB modems
+device ukbd # Allow keyboard like HIDs to control console
+device ums # USB mouse
+
+# USB Ethernet, requires miibus
+#device aue # ADMtek USB Ethernet
+#device axe # ASIX Electronics USB Ethernet
+#device cdce # Generic USB over Ethernet
+#device cue # CATC USB Ethernet
+#device kue # Kawasaki LSI USB Ethernet
+#device rue # RealTek RTL8150 USB Ethernet
+#device udav # Davicom DM9601E USB
+
+# USB Wireless
+#device rum # Ralink Technology RT2501USB wireless NICs
+
+# Wireless NIC cards
+#device wlan # 802.11 support
+#device wlan_wep # 802.11 WEP support
+#device wlan_ccmp # 802.11 CCMP support
+#device wlan_tkip # 802.11 TKIP support
+#device wlan_amrr # AMRR transmit rate control algorithm
+
+# PCI
+options NEW_PCIB
+device pci
+
+# PCI Ethernet NICs that use the common MII bus controller code.
+# NOTE: Be sure to keep the 'device miibus' line in order to use these NICs!
+device re # RealTek 8139C+/8169/8169S/8110S
+
+# DRM2
+#device fbd
+#device vt
+#device splash
+#device kbdmux
+#device drm2
+
+# Sound
+#device sound
+#device snd_hda
+
+# Flattened Device Tree
+options FDT # Configure using FDT/DTB data
+device fdt_pinctrl
+
+# SoC-specific devices
+
+#device hwpmc
+#options HWPMC_HOOKS
diff --git a/sys/arm/conf/std.arm b/sys/arm/conf/std.arm
index 88675f0..b9ac640 100644
--- a/sys/arm/conf/std.arm
+++ b/sys/arm/conf/std.arm
@@ -2,4 +2,5 @@
#
# $FreeBSD$
+options COMPAT_FREEBSD10 # Compatible with FreeBSD10
diff --git a/sys/arm/conf/std.armv6 b/sys/arm/conf/std.armv6
index 142c7d3..4dc4906 100644
--- a/sys/arm/conf/std.armv6
+++ b/sys/arm/conf/std.armv6
@@ -39,6 +39,8 @@ options KBD_INSTALL_CDEV # install a CDEV entry in /dev
options FREEBSD_BOOT_LOADER # Process metadata passed from loader(8)
options VFP # Enable floating point hardware support
+options COMPAT_FREEBSD10 # Compatible with FreeBSD10
+
# DTrace support
options KDTRACE_HOOKS # Kernel DTrace hooks
options DDB_CTF # all architectures - kernel ELF linker loads CTF data
diff --git a/sys/arm/freescale/imx/imx_gpio.c b/sys/arm/freescale/imx/imx_gpio.c
index 3c81e28..cdff020 100644
--- a/sys/arm/freescale/imx/imx_gpio.c
+++ b/sys/arm/freescale/imx/imx_gpio.c
@@ -91,6 +91,15 @@ __FBSDID("$FreeBSD$");
#define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)
#define NGPIO 32
+#ifdef ARM_INTRNG
+struct gpio_irqsrc {
+ struct intr_irqsrc gi_isrc;
+ u_int gi_irq;
+ enum intr_polarity gi_pol;
+ enum intr_trigger gi_trig;
+};
+#endif
+
struct imx51_gpio_softc {
device_t dev;
device_t sc_busdev;
@@ -101,7 +110,9 @@ struct imx51_gpio_softc {
bus_space_handle_t sc_ioh;
int gpio_npins;
struct gpio_pin gpio_pins[NGPIO];
- struct intr_irqsrc *gpio_pic_irqsrc[NGPIO];
+#ifdef ARM_INTRNG
+ struct gpio_irqsrc gpio_pic_irqsrc[NGPIO];
+#endif
};
static struct ofw_compat_data compat_data[] = {
@@ -145,8 +156,30 @@ static int imx51_gpio_pin_get(device_t, uint32_t, unsigned int *);
static int imx51_gpio_pin_toggle(device_t, uint32_t pin);
#ifdef ARM_INTRNG
+static int
+gpio_pic_teardown_intr(device_t dev, struct intr_irqsrc *isrc,
+ struct resource *res, struct intr_map_data *data)
+{
+ struct imx51_gpio_softc *sc;
+ struct gpio_irqsrc *gi;
+
+ sc = device_get_softc(dev);
+ if (isrc->isrc_handlers == 0) {
+ gi = (struct gpio_irqsrc *)isrc;
+ gi->gi_pol = INTR_POLARITY_CONFORM;
+ gi->gi_trig = INTR_TRIGGER_CONFORM;
+
+ // XXX Not sure this is necessary
+ mtx_lock_spin(&sc->sc_mtx);
+ CLEAR4(sc, IMX_GPIO_IMR_REG, (1U << gi->gi_irq));
+ WRITE4(sc, IMX_GPIO_ISR_REG, (1U << gi->gi_irq));
+ mtx_unlock_spin(&sc->sc_mtx);
+ }
+ return (0);
+}
+
/*
- * this is teardown_intr
+ * this is mask_intr
*/
static void
gpio_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc)
@@ -155,55 +188,143 @@ gpio_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc)
u_int irq;
sc = device_get_softc(dev);
- irq = isrc->isrc_data;
+ irq = ((struct gpio_irqsrc *)isrc)->gi_irq;
- // XXX Not sure this is necessary
mtx_lock_spin(&sc->sc_mtx);
CLEAR4(sc, IMX_GPIO_IMR_REG, (1U << irq));
- WRITE4(sc, IMX_GPIO_ISR_REG, (1U << irq));
mtx_unlock_spin(&sc->sc_mtx);
}
-/*
- * this is mask_intr
- */
-static void
-gpio_pic_disable_source(device_t dev, struct intr_irqsrc *isrc)
+static int
+gpio_pic_map_fdt(device_t dev, u_int ncells, pcell_t *cells, u_int *irqp,
+ enum intr_polarity *polp, enum intr_trigger *trigp)
{
struct imx51_gpio_softc *sc;
+ u_int irq, tripol;
+ enum intr_polarity pol;
+ enum intr_trigger trig;
sc = device_get_softc(dev);
- mtx_lock_spin(&sc->sc_mtx);
- CLEAR4(sc, IMX_GPIO_IMR_REG, (1U << isrc->isrc_data));
- mtx_unlock_spin(&sc->sc_mtx);
+ /*
+ * From devicetree/bindings/gpio/fsl-imx-gpio.txt:
+ * #interrupt-cells: 2. The first cell is the GPIO number. The second
+ * cell bits[3:0] is used to specify trigger type and level flags:
+ * 1 = low-to-high edge triggered.
+ * 2 = high-to-low edge triggered.
+ * 4 = active high level-sensitive.
+ * 8 = active low level-sensitive.
+ * We can do any single one of these modes, but nothing in combo.
+ */
+
+ if (ncells != 2) {
+ device_printf(sc->dev, "Invalid #interrupt-cells");
+ return (EINVAL);
+ }
+
+ irq = cells[0];
+ tripol = cells[1];
+ if (irq >= sc->gpio_npins) {
+ device_printf(sc->dev, "Invalid interrupt number %d", irq);
+ return (EINVAL);
+ }
+ switch (tripol) {
+ case 1:
+ trig = INTR_TRIGGER_EDGE;
+ pol = INTR_POLARITY_HIGH;
+ break;
+ case 2:
+ trig = INTR_TRIGGER_EDGE;
+ pol = INTR_POLARITY_LOW;
+ break;
+ case 4:
+ trig = INTR_TRIGGER_LEVEL;
+ pol = INTR_POLARITY_HIGH;
+ break;
+ case 8:
+ trig = INTR_TRIGGER_LEVEL;
+ pol = INTR_POLARITY_LOW;
+ break;
+ default:
+ device_printf(sc->dev, "unsupported trigger/polarity 0x%2x\n",
+ tripol);
+ return (ENOTSUP);
+ }
+ *irqp = irq;
+ if (polp != NULL)
+ *polp = pol;
+ if (trigp != NULL)
+ *trigp = trig;
+ return (0);
}
-/*
- * this is setup_intr
- */
-static void
-gpio_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
+static int
+gpio_pic_map_intr(device_t dev, struct intr_map_data *data,
+ struct intr_irqsrc **isrcp)
+{
+ int error;
+ u_int irq;
+ struct imx51_gpio_softc *sc;
+
+ if (data->type != INTR_MAP_DATA_FDT)
+ return (ENOTSUP);
+
+ error = gpio_pic_map_fdt(dev, data->fdt.ncells, data->fdt.cells, &irq,
+ NULL, NULL);
+ if (error == 0) {
+ sc = device_get_softc(dev);
+ *isrcp = &sc->gpio_pic_irqsrc[irq].gi_isrc;
+ }
+ return (error);
+}
+
+static int
+gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc,
+ struct resource *res, struct intr_map_data *data)
{
struct imx51_gpio_softc *sc;
- int icfg;
+ struct gpio_irqsrc *gi;
+ int error, icfg;
u_int irq, reg, shift, wrk;
+ enum intr_trigger trig;
+ enum intr_polarity pol;
sc = device_get_softc(dev);
+ gi = (struct gpio_irqsrc *)isrc;
+
+ /* Get config for interrupt. */
+ if (data == NULL || data->type != INTR_MAP_DATA_FDT)
+ return (ENOTSUP);
+ error = gpio_pic_map_fdt(dev, data->fdt.ncells, data->fdt.cells, &irq,
+ &pol, &trig);
+ if (error != 0)
+ return (error);
+ if (gi->gi_irq != irq)
+ return (EINVAL);
- if (isrc->isrc_trig == INTR_TRIGGER_LEVEL) {
- if (isrc->isrc_pol == INTR_POLARITY_LOW)
+ /* Compare config if this is not first setup. */
+ if (isrc->isrc_handlers != 0) {
+ if (pol != gi->gi_pol || trig != gi->gi_trig)
+ return (EINVAL);
+ else
+ return (0);
+ }
+
+ gi->gi_pol = pol;
+ gi->gi_trig = trig;
+
+ if (trig == INTR_TRIGGER_LEVEL) {
+ if (pol == INTR_POLARITY_LOW)
icfg = GPIO_ICR_COND_LOW;
else
icfg = GPIO_ICR_COND_HIGH;
} else {
- if (isrc->isrc_pol == INTR_POLARITY_HIGH)
+ if (pol == INTR_POLARITY_HIGH)
icfg = GPIO_ICR_COND_FALL;
else
icfg = GPIO_ICR_COND_RISE;
}
- irq = isrc->isrc_data;
if (irq < 16) {
reg = IMX_GPIO_ICR1_REG;
shift = 2 * irq;
@@ -220,20 +341,23 @@ gpio_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
wrk |= icfg << shift;
WRITE4(sc, reg, wrk);
mtx_unlock_spin(&sc->sc_mtx);
+ return (0);
}
/*
* this is unmask_intr
*/
static void
-gpio_pic_enable_source(device_t dev, struct intr_irqsrc *isrc)
+gpio_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
{
struct imx51_gpio_softc *sc;
+ u_int irq;
sc = device_get_softc(dev);
+ irq = ((struct gpio_irqsrc *)isrc)->gi_irq;
mtx_lock_spin(&sc->sc_mtx);
- SET4(sc, IMX_GPIO_IMR_REG, (1U << isrc->isrc_data));
+ SET4(sc, IMX_GPIO_IMR_REG, (1U << irq));
mtx_unlock_spin(&sc->sc_mtx);
}
@@ -241,12 +365,14 @@ static void
gpio_pic_post_filter(device_t dev, struct intr_irqsrc *isrc)
{
struct imx51_gpio_softc *sc;
+ u_int irq;
sc = device_get_softc(dev);
+ irq = ((struct gpio_irqsrc *)isrc)->gi_irq;
arm_irq_memory_barrier(0);
/* EOI. W1C reg so no r-m-w, no locking needed. */
- WRITE4(sc, IMX_GPIO_ISR_REG, (1U << isrc->isrc_data));
+ WRITE4(sc, IMX_GPIO_ISR_REG, (1U << irq));
}
static void
@@ -254,119 +380,21 @@ gpio_pic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
{
arm_irq_memory_barrier(0);
- gpio_pic_enable_source(dev, isrc);
+ gpio_pic_enable_intr(dev, isrc);
}
static void
gpio_pic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
{
- gpio_pic_disable_source(dev, isrc);
-}
-
-/*
- * intrng calls this to make a new isrc known to us.
- */
-static int
-gpio_pic_register(device_t dev, struct intr_irqsrc *isrc, boolean_t *is_percpu)
-{
- struct imx51_gpio_softc *sc;
- u_int irq, tripol;
-
- sc = device_get_softc(dev);
-
- /*
- * From devicetree/bindings/gpio/fsl-imx-gpio.txt:
- * #interrupt-cells: 2. The first cell is the GPIO number. The second
- * cell bits[3:0] is used to specify trigger type and level flags:
- * 1 = low-to-high edge triggered.
- * 2 = high-to-low edge triggered.
- * 4 = active high level-sensitive.
- * 8 = active low level-sensitive.
- * We can do any single one of these modes, but nothing in combo.
- */
-
- if (isrc->isrc_ncells != 2) {
- device_printf(sc->dev, "Invalid #interrupt-cells");
- return (EINVAL);
- }
-
- irq = isrc->isrc_cells[0];
- tripol = isrc->isrc_cells[1];
- if (irq >= sc->gpio_npins) {
- device_printf(sc->dev, "Invalid interrupt number %d", irq);
- return (EINVAL);
- }
- switch (tripol)
- {
- case 1:
- isrc->isrc_trig = INTR_TRIGGER_EDGE;
- isrc->isrc_pol = INTR_POLARITY_HIGH;
- break;
- case 2:
- isrc->isrc_trig = INTR_TRIGGER_EDGE;
- isrc->isrc_pol = INTR_POLARITY_LOW;
- break;
- case 4:
- isrc->isrc_trig = INTR_TRIGGER_LEVEL;
- isrc->isrc_pol = INTR_POLARITY_HIGH;
- break;
- case 8:
- isrc->isrc_trig = INTR_TRIGGER_LEVEL;
- isrc->isrc_pol = INTR_POLARITY_LOW;
- break;
- default:
- device_printf(sc->dev, "unsupported trigger/polarity 0x%2x\n",
- tripol);
- return (ENOTSUP);
- }
- isrc->isrc_nspc_type = INTR_IRQ_NSPC_PLAIN;
- isrc->isrc_nspc_num = irq;
-
- /*
- * 1. The link between ISRC and controller must be set atomically.
- * 2. Just do things only once in rare case when consumers
- * of shared interrupt came here at the same moment.
- */
- mtx_lock_spin(&sc->sc_mtx);
- if (sc->gpio_pic_irqsrc[irq] != NULL) {
- mtx_unlock_spin(&sc->sc_mtx);
- return (sc->gpio_pic_irqsrc[irq] == isrc ? 0 : EEXIST);
- }
- sc->gpio_pic_irqsrc[irq] = isrc;
- isrc->isrc_data = irq;
- mtx_unlock_spin(&sc->sc_mtx);
-
- intr_irq_set_name(isrc, "%s,%u", device_get_nameunit(sc->dev), irq);
- return (0);
-}
-
-static int
-gpio_pic_unregister(device_t dev, struct intr_irqsrc *isrc)
-{
- struct imx51_gpio_softc *sc;
- u_int irq;
-
- sc = device_get_softc(dev);
-
- mtx_lock_spin(&sc->sc_mtx);
- irq = isrc->isrc_data;
- if (sc->gpio_pic_irqsrc[irq] != isrc) {
- mtx_unlock_spin(&sc->sc_mtx);
- return (sc->gpio_pic_irqsrc[irq] == NULL ? 0 : EINVAL);
- }
- sc->gpio_pic_irqsrc[irq] = NULL;
- isrc->isrc_data = 0;
- mtx_unlock_spin(&sc->sc_mtx);
-
- intr_irq_set_name(isrc, "");
- return (0);
+ gpio_pic_disable_intr(dev, isrc);
}
static int
gpio_pic_filter(void *arg)
{
struct imx51_gpio_softc *sc;
+ struct intr_irqsrc *isrc;
uint32_t i, interrupts;
sc = arg;
@@ -377,14 +405,43 @@ gpio_pic_filter(void *arg)
for (i = 0; interrupts != 0; i++, interrupts >>= 1) {
if ((interrupts & 0x1) == 0)
continue;
- if (sc->gpio_pic_irqsrc[i])
- intr_irq_dispatch(sc->gpio_pic_irqsrc[i], curthread->td_intr_frame);
- else
- device_printf(sc->dev, "spurious interrupt %d\n", i);
+ isrc = &sc->gpio_pic_irqsrc[i].gi_isrc;
+ if (intr_isrc_dispatch(isrc, curthread->td_intr_frame) != 0) {
+ gpio_pic_disable_intr(sc->dev, isrc);
+ gpio_pic_post_filter(sc->dev, isrc);
+ device_printf(sc->dev, "Stray irq %u disabled\n", i);
+ }
}
return (FILTER_HANDLED);
}
+
+/*
+ * register our isrcs into intrng to make it known about them.
+ */
+static int
+gpio_pic_register_isrcs(struct imx51_gpio_softc *sc)
+{
+ int error;
+ uint32_t irq;
+ const char *name;
+
+ name = device_get_nameunit(sc->dev);
+ for (irq = 0; irq < NGPIO; irq++) {
+ sc->gpio_pic_irqsrc[irq].gi_irq = irq;
+ sc->gpio_pic_irqsrc[irq].gi_pol = INTR_POLARITY_CONFORM;
+ sc->gpio_pic_irqsrc[irq].gi_trig = INTR_TRIGGER_CONFORM;
+
+ error = intr_isrc_register(&sc->gpio_pic_irqsrc[irq].gi_isrc,
+ sc->dev, 0, "%s,%u", name, irq);
+ if (error != 0) {
+ /* XXX call intr_isrc_deregister() */
+ device_printf(sc->dev, "%s failed", __func__);
+ return (error);
+ }
+ }
+ return (0);
+}
#endif
/*
@@ -656,6 +713,7 @@ imx51_gpio_attach(device_t dev)
}
#ifdef ARM_INTRNG
+ gpio_pic_register_isrcs(sc);
intr_pic_register(dev, OF_xref_from_node(ofw_bus_get_node(dev)));
#endif
sc->sc_busdev = gpiobus_attach_bus(dev);
@@ -695,14 +753,13 @@ static device_method_t imx51_gpio_methods[] = {
#ifdef ARM_INTRNG
/* Interrupt controller interface */
DEVMETHOD(pic_disable_intr, gpio_pic_disable_intr),
- DEVMETHOD(pic_disable_source, gpio_pic_disable_source),
DEVMETHOD(pic_enable_intr, gpio_pic_enable_intr),
- DEVMETHOD(pic_enable_source, gpio_pic_enable_source),
+ DEVMETHOD(pic_map_intr, gpio_pic_map_intr),
+ DEVMETHOD(pic_setup_intr, gpio_pic_setup_intr),
+ DEVMETHOD(pic_teardown_intr, gpio_pic_teardown_intr),
DEVMETHOD(pic_post_filter, gpio_pic_post_filter),
DEVMETHOD(pic_post_ithread, gpio_pic_post_ithread),
DEVMETHOD(pic_pre_ithread, gpio_pic_pre_ithread),
- DEVMETHOD(pic_register, gpio_pic_register),
- DEVMETHOD(pic_unregister, gpio_pic_unregister),
#endif
/* GPIO protocol */
diff --git a/sys/arm/freescale/imx/imx_sdhci.c b/sys/arm/freescale/imx/imx_sdhci.c
index fa9d8ed..2dc41db 100644
--- a/sys/arm/freescale/imx/imx_sdhci.c
+++ b/sys/arm/freescale/imx/imx_sdhci.c
@@ -836,3 +836,4 @@ static driver_t imx_sdhci_driver = {
DRIVER_MODULE(sdhci_imx, simplebus, imx_sdhci_driver, imx_sdhci_devclass, 0, 0);
MODULE_DEPEND(sdhci_imx, sdhci, 1, 1, 1);
DRIVER_MODULE(mmc, sdhci_imx, mmc_driver, mmc_devclass, NULL, NULL);
+MODULE_DEPEND(sdhci_imx, mmc, 1, 1, 1);
diff --git a/sys/arm/include/atags.h b/sys/arm/include/atags.h
index 3665890..6d400af 100644
--- a/sys/arm/include/atags.h
+++ b/sys/arm/include/atags.h
@@ -123,7 +123,7 @@ struct arm_lbabi_tag
};
#define ATAG_TAG(a) (a)->tag_hdr.tag
-#define ATAG_SIZE(a) (a)->tag_hdr.size
+#define ATAG_SIZE(a) ((a)->tag_hdr.size * sizeof(uint32_t))
#define ATAG_NEXT(a) (struct arm_lbabi_tag *)((char *)(a) + ATAG_SIZE(a))
#endif /* __MACHINE_ATAGS_H__ */
diff --git a/sys/arm/include/intr.h b/sys/arm/include/intr.h
index 74d7e4d..e81bc7d 100644
--- a/sys/arm/include/intr.h
+++ b/sys/arm/include/intr.h
@@ -52,14 +52,17 @@
#include <sys/intr.h>
#ifdef SMP
-void intr_ipi_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf);
+typedef void intr_ipi_send_t(void *, cpuset_t, u_int);
+typedef void intr_ipi_handler_t(void *);
-#define AISHF_NOALLOC 0x0001
+void intr_ipi_dispatch(u_int, struct trapframe *);
+void intr_ipi_send(cpuset_t, u_int);
-int intr_ipi_set_handler(u_int ipi, const char *name, intr_ipi_filter_t *filter,
- void *arg, u_int flags);
-#endif
+void intr_ipi_setup(u_int, const char *, intr_ipi_handler_t *, void *,
+ intr_ipi_send_t *, void *);
+int intr_pic_ipi_setup(u_int, const char *, intr_ipi_handler_t *, void *);
+#endif
#else /* ARM_INTRNG */
/* XXX move to std.* files? */
diff --git a/sys/arm/include/machdep.h b/sys/arm/include/machdep.h
index 36c2f44..b156efe 100644
--- a/sys/arm/include/machdep.h
+++ b/sys/arm/include/machdep.h
@@ -37,7 +37,8 @@ struct arm_boot_params;
vm_offset_t default_parse_boot_param(struct arm_boot_params *abp);
vm_offset_t freebsd_parse_boot_param(struct arm_boot_params *abp);
vm_offset_t linux_parse_boot_param(struct arm_boot_params *abp);
-vm_offset_t fake_preload_metadata(struct arm_boot_params *abp);
+vm_offset_t fake_preload_metadata(struct arm_boot_params *abp,
+ void *dtb_ptr, size_t dtb_size);
vm_offset_t parse_boot_param(struct arm_boot_params *abp);
void arm_generic_initclocks(void);
diff --git a/sys/arm/include/smp.h b/sys/arm/include/smp.h
index e4d6385..e685cc3 100644
--- a/sys/arm/include/smp.h
+++ b/sys/arm/include/smp.h
@@ -37,8 +37,8 @@ void ipi_cpu(int cpu, u_int ipi);
void ipi_selected(cpuset_t cpus, u_int ipi);
/* PIC interface */
-void pic_ipi_send(cpuset_t cpus, u_int ipi);
#ifndef ARM_INTRNG
+void pic_ipi_send(cpuset_t cpus, u_int ipi);
void pic_ipi_clear(int ipi);
int pic_ipi_read(int arg);
#endif
diff --git a/sys/arm/lpc/lpc_mmc.c b/sys/arm/lpc/lpc_mmc.c
index ad3b6aa..6c33215 100644
--- a/sys/arm/lpc/lpc_mmc.c
+++ b/sys/arm/lpc/lpc_mmc.c
@@ -776,3 +776,4 @@ static driver_t lpc_mmc_driver = {
DRIVER_MODULE(lpcmmc, simplebus, lpc_mmc_driver, lpc_mmc_devclass, 0, 0);
DRIVER_MODULE(mmc, lpcmmc, mmc_driver, mmc_devclass, NULL, NULL);
+MODULE_DEPEND(lpcmmc, mmc, 1, 1, 1);
diff --git a/sys/arm/mv/files.mv b/sys/arm/mv/files.mv
index 635173d..8c303c6 100644
--- a/sys/arm/mv/files.mv
+++ b/sys/arm/mv/files.mv
@@ -26,6 +26,7 @@ dev/mge/if_mge.c optional mge
dev/nand/nfc_mv.c optional nand
dev/mvs/mvs_soc.c optional mvs
dev/uart/uart_dev_ns8250.c optional uart
+dev/uart/uart_dev_snps.c optional uart
dev/usb/controller/ehci_mv.c optional ehci
dev/usb/controller/xhci_mv.c optional xhci
diff --git a/sys/arm/mv/mpic.c b/sys/arm/mv/mpic.c
index e81820c..4f246a4 100644
--- a/sys/arm/mv/mpic.c
+++ b/sys/arm/mv/mpic.c
@@ -74,7 +74,7 @@ __FBSDID("$FreeBSD$");
#define MPIC_INT_ERR 4
#define MPIC_INT_MSI 96
-#define IRQ_MASK 0x3ff
+#define MPIC_IRQ_MASK 0x3ff
#define MPIC_CTRL 0x0
#define MPIC_SOFT_INT 0x4
@@ -98,6 +98,13 @@ __FBSDID("$FreeBSD$");
#define MPIC_PPI 32
+#ifdef ARM_INTRNG
+struct mv_mpic_irqsrc {
+ struct intr_irqsrc mmi_isrc;
+ u_int mmi_irq;
+};
+#endif
+
struct mv_mpic_softc {
device_t sc_dev;
struct resource * mpic_res[4];
@@ -108,8 +115,9 @@ struct mv_mpic_softc {
bus_space_tag_t drbl_bst;
bus_space_handle_t drbl_bsh;
struct mtx mtx;
-
- struct intr_irqsrc ** mpic_isrcs;
+#ifdef ARM_INTRNG
+ struct mv_mpic_irqsrc * mpic_isrcs;
+#endif
int nirqs;
void * intr_hand;
};
@@ -177,6 +185,40 @@ mv_mpic_probe(device_t dev)
return (0);
}
+#ifdef ARM_INTRNG
+static int
+mv_mpic_register_isrcs(struct mv_mpic_softc *sc)
+{
+ int error;
+ uint32_t irq;
+ struct intr_irqsrc *isrc;
+ const char *name;
+
+ sc->mpic_isrcs = malloc(sc->nirqs * sizeof (*sc->mpic_isrcs), M_DEVBUF,
+ M_WAITOK | M_ZERO);
+
+ name = device_get_nameunit(sc->sc_dev);
+ for (irq = 0; irq < sc->nirqs; irq++) {
+ sc->mpic_isrcs[irq].mmi_irq = irq;
+
+ isrc = &sc->mpic_isrcs[irq].mmi_isrc;
+ if (irq < MPIC_PPI) {
+ error = intr_isrc_register(isrc, sc->sc_dev,
+ INTR_ISRCF_PPI, "%s", name);
+ } else {
+ error = intr_isrc_register(isrc, sc->sc_dev, 0, "%s",
+ name);
+ }
+ if (error != 0) {
+ /* XXX call intr_isrc_deregister() */
+ device_printf(sc->sc_dev, "%s failed", __func__);
+ return (error);
+ }
+ }
+ return (0);
+}
+#endif
+
static int
mv_mpic_attach(device_t dev)
{
@@ -227,9 +269,11 @@ mv_mpic_attach(device_t dev)
sc->nirqs = MPIC_CTRL_NIRQS(val);
#ifdef ARM_INTRNG
- sc->mpic_isrcs = malloc(sc->nirqs * sizeof (*sc->mpic_isrcs), M_DEVBUF,
- M_WAITOK | M_ZERO);
-
+ if (mv_mpic_register_isrcs(sc) != 0) {
+ device_printf(dev, "could not register PIC ISRCs\n");
+ bus_release_resources(dev, mv_mpic_spec, sc->mpic_res);
+ return (ENXIO);
+ }
if (intr_pic_register(dev, OF_xref_from_device(dev)) != 0) {
device_printf(dev, "could not register PIC\n");
bus_release_resources(dev, mv_mpic_spec, sc->mpic_res);
@@ -247,14 +291,11 @@ static int
mpic_intr(void *arg)
{
struct mv_mpic_softc *sc;
- struct trapframe *tf;
- struct intr_irqsrc *isrc;
uint32_t cause, irqsrc;
unsigned int irq;
u_int cpuid;
sc = arg;
- tf = curthread->td_intr_frame;
cpuid = PCPU_GET(cpuid);
irq = 0;
@@ -264,117 +305,64 @@ mpic_intr(void *arg)
irqsrc = MPIC_READ(sc, MPIC_INT_CTL(irq));
if ((irqsrc & MPIC_INT_IRQ_FIQ_MASK(cpuid)) == 0)
continue;
- isrc = sc->mpic_isrcs[irq];
- if (isrc == NULL) {
- device_printf(sc->sc_dev, "Stray interrupt %u detected\n", irq);
+ if (intr_isrc_dispatch(&sc->mpic_isrcs[irq].mmi_isrc,
+ curthread->td_intr_frame) != 0) {
mpic_mask_irq(irq);
- continue;
+ device_printf(sc->sc_dev, "Stray irq %u "
+ "disabled\n", irq);
}
- intr_irq_dispatch(isrc, tf);
}
}
return (FILTER_HANDLED);
}
-static int
-mpic_attach_isrc(struct mv_mpic_softc *sc, struct intr_irqsrc *isrc, u_int irq)
+static void
+mpic_disable_intr(device_t dev, struct intr_irqsrc *isrc)
{
- const char *name;
-
- mtx_lock_spin(&sc->mtx);
- if (sc->mpic_isrcs[irq] != NULL) {
- mtx_unlock_spin(&sc->mtx);
- return (sc->mpic_isrcs[irq] == isrc ? 0 : EEXIST);
- }
- sc->mpic_isrcs[irq] = isrc;
- isrc->isrc_data = irq;
- mtx_unlock_spin(&sc->mtx);
-
- name = device_get_nameunit(sc->sc_dev);
- intr_irq_set_name(isrc, "%s", name);
+ u_int irq;
- return (0);
+ irq = ((struct mv_mpic_irqsrc *)isrc)->mmi_irq;
+ mpic_mask_irq(irq);
}
-#ifdef FDT
-static int
-mpic_map_fdt(struct mv_mpic_softc *sc, struct intr_irqsrc *isrc, u_int *irqp)
+static void
+mpic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
{
u_int irq;
- int error;
-
- if (isrc->isrc_ncells != 1)
- return (EINVAL);
- irq = isrc->isrc_cells[0];
-
- error = mpic_attach_isrc(sc, isrc, irq);
- if (error != 0)
- return (error);
-
- isrc->isrc_nspc_num = irq;
- isrc->isrc_trig = INTR_TRIGGER_CONFORM;
- isrc->isrc_pol = INTR_POLARITY_CONFORM;
- isrc->isrc_nspc_type = INTR_IRQ_NSPC_PLAIN;
-
- *irqp = irq;
-
- return (0);
+ irq = ((struct mv_mpic_irqsrc *)isrc)->mmi_irq;
+ mpic_unmask_irq(irq);
}
-#endif
static int
-mpic_register(device_t dev, struct intr_irqsrc *isrc, boolean_t *is_percpu)
+mpic_map_intr(device_t dev, struct intr_map_data *data,
+ struct intr_irqsrc **isrcp)
{
struct mv_mpic_softc *sc;
- int error;
- u_int irq = 0;
sc = device_get_softc(dev);
-#ifdef FDT
- if (isrc->isrc_type == INTR_ISRCT_FDT)
- error = mpic_map_fdt(sc, isrc, &irq);
- else
-#endif
- error = EINVAL;
-
- if (error == 0)
- *is_percpu = irq < MPIC_PPI;
-
- return (error);
-}
-
-static void
-mpic_disable_source(device_t dev, struct intr_irqsrc *isrc)
-{
- u_int irq;
+ if (data->type != INTR_MAP_DATA_FDT || data->fdt.ncells !=1 ||
+ data->fdt.cells[0] >= sc->nirqs)
+ return (EINVAL);
- irq = isrc->isrc_data;
- mpic_mask_irq(irq);
+ *isrcp = &sc->mpic_isrcs[data->fdt.cells[0]].mmi_isrc;
+ return (0);
}
static void
-mpic_enable_source(device_t dev, struct intr_irqsrc *isrc)
-{
- u_int irq;
-
- irq = isrc->isrc_data;
- mpic_unmask_irq(irq);
-}
-static void
mpic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
{
- mpic_disable_source(dev, isrc);
+ mpic_disable_intr(dev, isrc);
}
static void
mpic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
{
- mpic_enable_source(dev, isrc);
+ mpic_enable_intr(dev, isrc);
}
#endif
@@ -383,9 +371,9 @@ static device_method_t mv_mpic_methods[] = {
DEVMETHOD(device_attach, mv_mpic_attach),
#ifdef ARM_INTRNG
- DEVMETHOD(pic_register, mpic_register),
- DEVMETHOD(pic_disable_source, mpic_disable_source),
- DEVMETHOD(pic_enable_source, mpic_enable_source),
+ DEVMETHOD(pic_disable_intr, mpic_disable_intr),
+ DEVMETHOD(pic_enable_intr, mpic_enable_intr),
+ DEVMETHOD(pic_map_intr, mpic_map_intr),
DEVMETHOD(pic_post_ithread, mpic_post_ithread),
DEVMETHOD(pic_pre_ithread, mpic_pre_ithread),
#endif
@@ -409,10 +397,10 @@ arm_get_next_irq(int last)
{
u_int irq, next = -1;
- irq = mv_mpic_get_cause() & IRQ_MASK;
+ irq = mv_mpic_get_cause() & MPIC_IRQ_MASK;
CTR2(KTR_INTR, "%s: irq:%#x", __func__, irq);
- if (irq != IRQ_MASK) {
+ if (irq != MPIC_IRQ_MASK) {
if (irq == MPIC_INT_ERR)
irq = mv_mpic_get_cause_err();
if (irq == MPIC_INT_MSI)
diff --git a/sys/arm/mv/mv_localbus.c b/sys/arm/mv/mv_localbus.c
index 936bc18..fabb694 100644
--- a/sys/arm/mv/mv_localbus.c
+++ b/sys/arm/mv/mv_localbus.c
@@ -323,8 +323,8 @@ localbus_print_child(device_t dev, device_t child)
rv = 0;
rv += bus_print_child_header(dev, child);
- rv += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
- rv += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+ rv += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
+ rv += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
rv += bus_print_child_footer(dev, child);
return (rv);
diff --git a/sys/arm/nvidia/as3722.c b/sys/arm/nvidia/as3722.c
new file mode 100644
index 0000000..3a03322
--- /dev/null
+++ b/sys/arm/nvidia/as3722.c
@@ -0,0 +1,411 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * AS3722 PMIC driver
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/gpio.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/sx.h>
+
+#include <machine/bus.h>
+
+#include <dev/extres/regulator/regulator.h>
+#include <dev/fdt/fdt_pinctrl.h>
+#include <dev/gpio/gpiobusvar.h>
+#include <dev/iicbus/iiconf.h>
+#include <dev/iicbus/iicbus.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <gnu/dts/include/dt-bindings/mfd/as3722.h>
+
+#include "clock_if.h"
+#include "regdev_if.h"
+
+#include "as3722.h"
+
+static struct ofw_compat_data compat_data[] = {
+ {"ams,as3722", 1},
+ {NULL, 0},
+};
+
+#define LOCK(_sc) sx_xlock(&(_sc)->lock)
+#define UNLOCK(_sc) sx_xunlock(&(_sc)->lock)
+#define LOCK_INIT(_sc) sx_init(&(_sc)->lock, "as3722")
+#define LOCK_DESTROY(_sc) sx_destroy(&(_sc)->lock);
+#define ASSERT_LOCKED(_sc) sx_assert(&(_sc)->lock, SA_XLOCKED);
+#define ASSERT_UNLOCKED(_sc) sx_assert(&(_sc)->lock, SA_UNLOCKED);
+
+#define AS3722_DEVICE_ID 0x0C
+
+/*
+ * Raw register access function.
+ */
+int
+as3722_read(struct as3722_softc *sc, uint8_t reg, uint8_t *val)
+{
+ uint8_t addr;
+ int rv;
+ struct iic_msg msgs[2] = {
+ {0, IIC_M_WR, 1, &addr},
+ {0, IIC_M_RD, 1, val},
+ };
+
+ msgs[0].slave = sc->bus_addr;
+ msgs[1].slave = sc->bus_addr;
+ addr = reg;
+
+ rv = iicbus_transfer(sc->dev, msgs, 2);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Error when reading reg 0x%02X, rv: %d\n", reg, rv);
+ return (EIO);
+ }
+
+ return (0);
+}
+
+int as3722_read_buf(struct as3722_softc *sc, uint8_t reg, uint8_t *buf,
+ size_t size)
+{
+ uint8_t addr;
+ int rv;
+ struct iic_msg msgs[2] = {
+ {0, IIC_M_WR, 1, &addr},
+ {0, IIC_M_RD, size, buf},
+ };
+
+ msgs[0].slave = sc->bus_addr;
+ msgs[1].slave = sc->bus_addr;
+ addr = reg;
+
+ rv = iicbus_transfer(sc->dev, msgs, 2);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Error when reading reg 0x%02X, rv: %d\n", reg, rv);
+ return (EIO);
+ }
+
+ return (0);
+}
+
+int
+as3722_write(struct as3722_softc *sc, uint8_t reg, uint8_t val)
+{
+ uint8_t data[2];
+ int rv;
+
+ struct iic_msg msgs[1] = {
+ {0, IIC_M_WR, 2, data},
+ };
+
+ msgs[0].slave = sc->bus_addr;
+ data[0] = reg;
+ data[1] = val;
+
+ rv = iicbus_transfer(sc->dev, msgs, 1);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Error when writing reg 0x%02X, rv: %d\n", reg, rv);
+ return (EIO);
+ }
+ return (0);
+}
+
+int as3722_write_buf(struct as3722_softc *sc, uint8_t reg, uint8_t *buf,
+ size_t size)
+{
+ uint8_t data[1];
+ int rv;
+ struct iic_msg msgs[2] = {
+ {0, IIC_M_WR, 1, data},
+ {0, IIC_M_WR | IIC_M_NOSTART, size, buf},
+ };
+
+ msgs[0].slave = sc->bus_addr;
+ msgs[1].slave = sc->bus_addr;
+ data[0] = reg;
+
+ rv = iicbus_transfer(sc->dev, msgs, 2);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Error when writing reg 0x%02X, rv: %d\n", reg, rv);
+ return (EIO);
+ }
+ return (0);
+}
+
+int
+as3722_modify(struct as3722_softc *sc, uint8_t reg, uint8_t clear, uint8_t set)
+{
+ uint8_t val;
+ int rv;
+
+ rv = as3722_read(sc, reg, &val);
+ if (rv != 0)
+ return (rv);
+
+ val &= ~clear;
+ val |= set;
+
+ rv = as3722_write(sc, reg, val);
+ if (rv != 0)
+ return (rv);
+
+ return (0);
+}
+
+static int
+as3722_get_version(struct as3722_softc *sc)
+{
+ uint8_t reg;
+ int rv;
+
+ /* Verify AS3722 ID and version. */
+ rv = RD1(sc, AS3722_ASIC_ID1, &reg);
+ if (rv != 0)
+ return (ENXIO);
+
+ if (reg != AS3722_DEVICE_ID) {
+ device_printf(sc->dev, "Invalid chip ID is 0x%x\n", reg);
+ return (ENXIO);
+ }
+
+ rv = RD1(sc, AS3722_ASIC_ID2, &sc->chip_rev);
+ if (rv != 0)
+ return (ENXIO);
+
+ if (bootverbose)
+ device_printf(sc->dev, "AS3722 rev: 0x%x\n", sc->chip_rev);
+ return (0);
+}
+
+static int
+as3722_init(struct as3722_softc *sc)
+{
+ uint32_t reg;
+ int rv;
+
+ reg = 0;
+ if (sc->int_pullup)
+ reg |= AS3722_INT_PULL_UP;
+ if (sc->i2c_pullup)
+ reg |= AS3722_I2C_PULL_UP;
+
+ rv = RM1(sc, AS3722_IO_VOLTAGE,
+ AS3722_INT_PULL_UP | AS3722_I2C_PULL_UP, reg);
+ if (rv != 0)
+ return (ENXIO);
+
+ /* mask interrupts */
+ rv = WR1(sc, AS3722_INTERRUPT_MASK1, 0);
+ if (rv != 0)
+ return (ENXIO);
+ rv = WR1(sc, AS3722_INTERRUPT_MASK2, 0);
+ if (rv != 0)
+ return (ENXIO);
+ rv = WR1(sc, AS3722_INTERRUPT_MASK3, 0);
+ if (rv != 0)
+ return (ENXIO);
+ rv = WR1(sc, AS3722_INTERRUPT_MASK4, 0);
+ if (rv != 0)
+ return (ENXIO);
+ return (0);
+}
+
+static int
+as3722_parse_fdt(struct as3722_softc *sc, phandle_t node)
+{
+
+ sc->int_pullup =
+ OF_hasprop(node, "ams,enable-internal-int-pullup") ? 1 : 0;
+ sc->i2c_pullup =
+ OF_hasprop(node, "ams,enable-internal-i2c-pullup") ? 1 : 0;
+ return 0;
+}
+
+static void
+as3722_intr(void *arg)
+{
+ struct as3722_softc *sc;
+
+ sc = (struct as3722_softc *)arg;
+ /* XXX Finish temperature alarms. */
+}
+
+static int
+as3722_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
+ return (ENXIO);
+
+ device_set_desc(dev, "AS3722 PMIC");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+as3722_attach(device_t dev)
+{
+ struct as3722_softc *sc;
+ const char *dname;
+ int dunit, rv, rid;
+ phandle_t node;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ sc->bus_addr = iicbus_get_addr(dev);
+ node = ofw_bus_get_node(sc->dev);
+ dname = device_get_name(dev);
+ dunit = device_get_unit(dev);
+ rv = 0;
+ LOCK_INIT(sc);
+
+ rid = 0;
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (sc->irq_res == NULL) {
+ device_printf(dev, "Cannot allocate interrupt.\n");
+ rv = ENXIO;
+ goto fail;
+ }
+
+ rv = as3722_parse_fdt(sc, node);
+ if (rv != 0)
+ goto fail;
+ rv = as3722_get_version(sc);
+ if (rv != 0)
+ goto fail;
+ rv = as3722_init(sc);
+ if (rv != 0)
+ goto fail;
+ rv = as3722_regulator_attach(sc, node);
+ if (rv != 0)
+ goto fail;
+ rv = as3722_gpio_attach(sc, node);
+ if (rv != 0)
+ goto fail;
+ rv = as3722_rtc_attach(sc, node);
+ if (rv != 0)
+ goto fail;
+
+ fdt_pinctrl_register(dev, NULL);
+ fdt_pinctrl_configure_by_name(dev, "default");
+
+ /* Setup interrupt. */
+ rv = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
+ NULL, as3722_intr, sc, &sc->irq_h);
+ if (rv) {
+ device_printf(dev, "Cannot setup interrupt.\n");
+ goto fail;
+ }
+ return (bus_generic_attach(dev));
+
+fail:
+ if (sc->irq_h != NULL)
+ bus_teardown_intr(dev, sc->irq_res, sc->irq_h);
+ if (sc->irq_res != NULL)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
+ LOCK_DESTROY(sc);
+ return (rv);
+}
+
+static int
+as3722_detach(device_t dev)
+{
+ struct as3722_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (sc->irq_h != NULL)
+ bus_teardown_intr(dev, sc->irq_res, sc->irq_h);
+ if (sc->irq_res != NULL)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
+ LOCK_DESTROY(sc);
+
+ return (bus_generic_detach(dev));
+}
+
+static phandle_t
+as3722_gpio_get_node(device_t bus, device_t dev)
+{
+
+ /* We only have one child, the GPIO bus, which needs our own node. */
+ return (ofw_bus_get_node(bus));
+}
+
+static device_method_t as3722_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, as3722_probe),
+ DEVMETHOD(device_attach, as3722_attach),
+ DEVMETHOD(device_detach, as3722_detach),
+
+ /* Regdev interface */
+ DEVMETHOD(regdev_map, as3722_regulator_map),
+
+ /* RTC interface */
+ DEVMETHOD(clock_gettime, as3722_rtc_gettime),
+ DEVMETHOD(clock_settime, as3722_rtc_settime),
+
+ /* GPIO protocol interface */
+ DEVMETHOD(gpio_get_bus, as3722_gpio_get_bus),
+ DEVMETHOD(gpio_pin_max, as3722_gpio_pin_max),
+ DEVMETHOD(gpio_pin_getname, as3722_gpio_pin_getname),
+ DEVMETHOD(gpio_pin_getflags, as3722_gpio_pin_getflags),
+ DEVMETHOD(gpio_pin_getcaps, as3722_gpio_pin_getcaps),
+ DEVMETHOD(gpio_pin_setflags, as3722_gpio_pin_setflags),
+ DEVMETHOD(gpio_pin_get, as3722_gpio_pin_get),
+ DEVMETHOD(gpio_pin_set, as3722_gpio_pin_set),
+ DEVMETHOD(gpio_pin_toggle, as3722_gpio_pin_toggle),
+ DEVMETHOD(gpio_map_gpios, as3722_gpio_map_gpios),
+
+ /* fdt_pinctrl interface */
+ DEVMETHOD(fdt_pinctrl_configure, as3722_pinmux_configure),
+
+ /* ofw_bus interface */
+ DEVMETHOD(ofw_bus_get_node, as3722_gpio_get_node),
+
+ DEVMETHOD_END
+};
+
+static devclass_t as3722_devclass;
+DEFINE_CLASS_0(gpio, as3722_driver, as3722_methods,
+ sizeof(struct as3722_softc));
+EARLY_DRIVER_MODULE(as3722, iicbus, as3722_driver, as3722_devclass,
+ 0, 0, 74);
diff --git a/sys/arm/nvidia/as3722.h b/sys/arm/nvidia/as3722.h
new file mode 100644
index 0000000..c559a8a
--- /dev/null
+++ b/sys/arm/nvidia/as3722.h
@@ -0,0 +1,323 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _AS3722_H_
+
+#include <sys/clock.h>
+
+#define AS3722_SD0_VOLTAGE 0x00
+#define AS3722_SD_VSEL_MASK 0x7F /* For all SD */
+#define AS3722_SD0_VSEL_MIN 0x01
+#define AS3722_SD0_VSEL_MAX 0x5A
+#define AS3722_SD0_VSEL_LOW_VOL_MAX 0x6E
+
+#define AS3722_SD1_VOLTAGE 0x01
+#define AS3722_SD2_VOLTAGE 0x02
+#define AS3722_SD2_VSEL_MIN 0x01
+#define AS3722_SD2_VSEL_MAX 0x7F
+#define AS3722_SD3_VOLTAGE 0x03
+#define AS3722_SD4_VOLTAGE 0x04
+#define AS3722_SD5_VOLTAGE 0x05
+#define AS3722_SD6_VOLTAGE 0x06
+#define AS3722_GPIO0_CONTROL 0x08
+#define AS3722_GPIO_INVERT 0x80
+#define AS3722_GPIO_IOSF_MASK 0x0F
+#define AS3722_GPIO_IOSF_SHIFT 3
+#define AS3722_GPIO_MODE_MASK 0x07
+#define AS3722_GPIO_MODE_SHIFT 0
+
+#define AS3722_GPIO1_CONTROL 0x09
+#define AS3722_GPIO2_CONTROL 0x0A
+#define AS3722_GPIO3_CONTROL 0x0B
+#define AS3722_GPIO4_CONTROL 0x0C
+#define AS3722_GPIO5_CONTROL 0x0D
+#define AS3722_GPIO6_CONTROL 0x0E
+#define AS3722_GPIO7_CONTROL 0x0F
+#define AS3722_LDO0_VOLTAGE 0x10
+#define AS3722_LDO0_VSEL_MASK 0x1F
+#define AS3722_LDO0_VSEL_MIN 0x01
+#define AS3722_LDO0_VSEL_MAX 0x12
+#define AS3722_LDO0_NUM_VOLT 0x12
+
+#define AS3722_LDO1_VOLTAGE 0x11
+#define AS3722_LDO_VSEL_MASK 0x7F
+#define AS3722_LDO_VSEL_MIN 0x01
+#define AS3722_LDO_VSEL_MAX 0x7F
+#define AS3722_LDO_VSEL_DNU_MIN 0x25
+#define AS3722_LDO_VSEL_DNU_MAX 0x3F
+#define AS3722_LDO_NUM_VOLT 0x80
+
+#define AS3722_LDO2_VOLTAGE 0x12
+#define AS3722_LDO3_VOLTAGE 0x13
+#define AS3722_LDO3_VSEL_MASK 0x3F
+#define AS3722_LDO3_VSEL_MIN 0x01
+#define AS3722_LDO3_VSEL_MAX 0x2D
+#define AS3722_LDO3_NUM_VOLT 0x2D
+#define AS3722_LDO3_MODE_MASK (0x3 << 6)
+#define AS3722_LDO3_MODE_GET(x) (((x) >> 6) & 0x3)
+#define AS3722_LDO3_MODE(x) (((x) & 0x3) << 6)
+#define AS3722_LDO3_MODE_PMOS AS3722_LDO3_MODE(0)
+#define AS3722_LDO3_MODE_PMOS_TRACKING AS3722_LDO3_MODE(1)
+#define AS3722_LDO3_MODE_NMOS AS3722_LDO3_MODE(2)
+#define AS3722_LDO3_MODE_SWITCH AS3722_LDO3_MODE(3)
+
+#define AS3722_LDO4_VOLTAGE 0x14
+#define AS3722_LDO5_VOLTAGE 0x15
+#define AS3722_LDO6_VOLTAGE 0x16
+#define AS3722_LDO6_SEL_BYPASS 0x3F
+#define AS3722_LDO7_VOLTAGE 0x17
+#define AS3722_LDO9_VOLTAGE 0x19
+#define AS3722_LDO10_VOLTAGE 0x1A
+#define AS3722_LDO11_VOLTAGE 0x1B
+#define AS3722_LDO3_SETTINGS 0x1D
+#define AS3722_GPIO_DEB1 0x1E
+#define AS3722_GPIO_DEB2 0x1F
+#define AS3722_GPIO_SIGNAL_OUT 0x20
+#define AS3722_GPIO_SIGNAL_IN 0x21
+#define AS3722_REG_SEQU_MOD1 0x22
+#define AS3722_REG_SEQU_MOD2 0x23
+#define AS3722_REG_SEQU_MOD3 0x24
+#define AS3722_SD_PHSW_CTRL 0x27
+#define AS3722_SD_PHSW_STATUS 0x28
+
+#define AS3722_SD0_CONTROL 0x29
+#define AS3722_SD0_MODE_FAST (1 << 4)
+
+#define AS3722_SD1_CONTROL 0x2A
+#define AS3722_SD1_MODE_FAST (1 << 4)
+
+#define AS3722_SDMPH_CONTROL 0x2B
+#define AS3722_SD23_CONTROL 0x2C
+#define AS3722_SD3_MODE_FAST (1 << 6)
+#define AS3722_SD2_MODE_FAST (1 << 2)
+
+#define AS3722_SD4_CONTROL 0x2D
+#define AS3722_SD4_MODE_FAST (1 << 2)
+
+#define AS3722_SD5_CONTROL 0x2E
+#define AS3722_SD5_MODE_FAST (1 << 2)
+
+#define AS3722_SD6_CONTROL 0x2F
+#define AS3722_SD6_MODE_FAST (1 << 4)
+
+#define AS3722_SD_DVM 0x30
+#define AS3722_RESET_REASON 0x31
+#define AS3722_BATTERY_VOLTAGE_MONITOR 0x32
+#define AS3722_STARTUP_CONTROL 0x33
+#define AS3722_RESET_TIMER 0x34
+#define AS3722_REFERENCE_CONTROL 0x35
+#define AS3722_RESET_CONTROL 0x36
+#define AS3722_OVERTEMPERATURE_CONTROL 0x37
+#define AS3722_WATCHDOG_CONTROL 0x38
+#define AS3722_REG_STANDBY_MOD1 0x39
+#define AS3722_REG_STANDBY_MOD2 0x3A
+#define AS3722_REG_STANDBY_MOD3 0x3B
+#define AS3722_ENABLE_CTRL1 0x3C
+#define AS3722_SD3_EXT_ENABLE_MASK 0xC0
+#define AS3722_SD2_EXT_ENABLE_MASK 0x30
+#define AS3722_SD1_EXT_ENABLE_MASK 0x0C
+#define AS3722_SD0_EXT_ENABLE_MASK 0x03
+
+#define AS3722_ENABLE_CTRL2 0x3D
+#define AS3722_SD6_EXT_ENABLE_MASK 0x30
+#define AS3722_SD5_EXT_ENABLE_MASK 0x0C
+#define AS3722_SD4_EXT_ENABLE_MASK 0x03
+
+#define AS3722_ENABLE_CTRL3 0x3E
+#define AS3722_LDO3_EXT_ENABLE_MASK 0xC0
+#define AS3722_LDO2_EXT_ENABLE_MASK 0x30
+#define AS3722_LDO1_EXT_ENABLE_MASK 0x0C
+#define AS3722_LDO0_EXT_ENABLE_MASK 0x03
+
+#define AS3722_ENABLE_CTRL4 0x3F
+#define AS3722_LDO7_EXT_ENABLE_MASK 0xC0
+#define AS3722_LDO6_EXT_ENABLE_MASK 0x30
+#define AS3722_LDO5_EXT_ENABLE_MASK 0x0C
+#define AS3722_LDO4_EXT_ENABLE_MASK 0x03
+
+#define AS3722_ENABLE_CTRL5 0x40
+#define AS3722_LDO11_EXT_ENABLE_MASK 0xC0
+#define AS3722_LDO10_EXT_ENABLE_MASK 0x30
+#define AS3722_LDO9_EXT_ENABLE_MASK 0x0C
+
+#define AS3722_PWM_CONTROL_L 0x41
+#define AS3722_PWM_CONTROL_H 0x42
+#define AS3722_WATCHDOG_TIMER 0x46
+#define AS3722_WATCHDOG_SOFTWARE_SIGNAL 0x48
+#define AS3722_IO_VOLTAGE 0x49
+#define AS3722_I2C_PULL_UP (1 << 4)
+#define AS3722_INT_PULL_UP (1 << 5)
+
+#define AS3722_BATTERY_VOLTAGE_MONITOR2 0x4A
+#define AS3722_SD_CONTROL 0x4D
+#define AS3722_SDN_CTRL(x) (1 << (x))
+
+#define AS3722_LDO_CONTROL0 0x4E
+#define AS3722_LDO7_CTRL (1 << 7)
+#define AS3722_LDO6_CTRL (1 << 6)
+#define AS3722_LDO5_CTRL (1 << 5)
+#define AS3722_LDO4_CTRL (1 << 4)
+#define AS3722_LDO3_CTRL (1 << 3)
+#define AS3722_LDO2_CTRL (1 << 2)
+#define AS3722_LDO1_CTRL (1 << 1)
+#define AS3722_LDO0_CTRL (1 << 0)
+
+#define AS3722_LDO_CONTROL1 0x4F
+#define AS3722_LDO11_CTRL (1 << 3)
+#define AS3722_LDO10_CTRL (1 << 2)
+#define AS3722_LDO9_CTRL (1 << 1)
+
+#define AS3722_SD0_PROTECT 0x50
+#define AS3722_SD6_PROTECT 0x51
+#define AS3722_PWM_VCONTROL1 0x52
+#define AS3722_PWM_VCONTROL2 0x53
+#define AS3722_PWM_VCONTROL3 0x54
+#define AS3722_PWM_VCONTROL4 0x55
+#define AS3722_BB_CHARGER 0x57
+#define AS3722_CTRL_SEQU1 0x58
+#define AS3722_CTRL_SEQU2 0x59
+#define AS3722_OV_CURRENT 0x5A
+#define AS3722_OV_CURRENT_DEB 0x5B
+#define AS3722_SDLV_DEB 0x5C
+#define AS3722_OC_PG_CTRL 0x5D
+#define AS3722_OC_PG_CTRL2 0x5E
+#define AS3722_CTRL_STATUS 0x5F
+#define AS3722_RTC_CONTROL 0x60
+#define AS3722_RTC_AM_PM_MODE (1 << 7)
+#define AS3722_RTC_CLK32K_OUT_EN (1 << 5)
+#define AS3722_RTC_IRQ_MODE (1 << 3)
+#define AS3722_RTC_ON (1 << 2)
+#define AS3722_RTC_ALARM_WAKEUP_EN (1 << 1)
+#define AS3722_RTC_REP_WAKEUP_EN (1 << 0)
+
+#define AS3722_RTC_SECOND 0x61
+#define AS3722_RTC_MINUTE 0x62
+#define AS3722_RTC_HOUR 0x63
+#define AS3722_RTC_DAY 0x64
+#define AS3722_RTC_MONTH 0x65
+#define AS3722_RTC_YEAR 0x66
+#define AS3722_RTC_ALARM_SECOND 0x67
+#define AS3722_RTC_ALARM_MINUTE 0x68
+#define AS3722_RTC_ALARM_HOUR 0x69
+#define AS3722_RTC_ALARM_DAY 0x6A
+#define AS3722_RTC_ALARM_MONTH 0x6B
+#define AS3722_RTC_ALARM_YEAR 0x6C
+#define AS3722_SRAM 0x6D
+#define AS3722_RTC_ACCESS 0x6F
+#define AS3722_REG_STATUS 0x73
+#define AS3722_INTERRUPT_MASK1 0x74
+#define AS3722_INTERRUPT_MASK2 0x75
+#define AS3722_INTERRUPT_MASK3 0x76
+#define AS3722_INTERRUPT_MASK4 0x77
+#define AS3722_INTERRUPT_STATUS1 0x78
+#define AS3722_INTERRUPT_STATUS2 0x79
+#define AS3722_INTERRUPT_STATUS3 0x7A
+#define AS3722_INTERRUPT_STATUS4 0x7B
+#define AS3722_TEMP_STATUS 0x7D
+#define AS3722_ADC0_CONTROL 0x80
+#define AS3722_ADC1_CONTROL 0x81
+#define AS3722_ADC0_MSB_RESULT 0x82
+#define AS3722_ADC0_LSB_RESULT 0x83
+#define AS3722_ADC1_MSB_RESULT 0x84
+#define AS3722_ADC1_LSB_RESULT 0x85
+#define AS3722_ADC1_THRESHOLD_HI_MSB 0x86
+#define AS3722_ADC1_THRESHOLD_HI_LSB 0x87
+#define AS3722_ADC1_THRESHOLD_LO_MSB 0x88
+#define AS3722_ADC1_THRESHOLD_LO_LSB 0x89
+#define AS3722_ADC_CONFIGURATION 0x8A
+#define AS3722_ASIC_ID1 0x90
+#define AS3722_ASIC_ID2 0x91
+#define AS3722_LOCK 0x9E
+#define AS3722_FUSE7 0x9E
+#define AS3722_FUSE7_SD0_LOW_VOLTAGE (1 << 4)
+
+struct as3722_reg_sc;
+struct as3722_gpio_pin;
+
+struct as3722_softc {
+ device_t dev;
+ struct sx lock;
+ int bus_addr;
+ struct resource *irq_res;
+ void *irq_h;
+
+ uint8_t chip_rev;
+ int int_pullup;
+ int i2c_pullup;
+
+ /* Regulators. */
+ struct as3722_reg_sc **regs;
+ int nregs;
+
+ /* GPIO */
+ device_t gpio_busdev;
+ struct as3722_gpio_pin **gpio_pins;
+ int gpio_npins;
+ struct sx gpio_lock;
+
+};
+
+#define RD1(sc, reg, val) as3722_read(sc, reg, val)
+#define WR1(sc, reg, val) as3722_write(sc, reg, val)
+#define RM1(sc, reg, clr, set) as3722_modify(sc, reg, clr, set)
+
+int as3722_read(struct as3722_softc *sc, uint8_t reg, uint8_t *val);
+int as3722_write(struct as3722_softc *sc, uint8_t reg, uint8_t val);
+int as3722_modify(struct as3722_softc *sc, uint8_t reg, uint8_t clear,
+ uint8_t set);
+int as3722_read_buf(struct as3722_softc *sc, uint8_t reg, uint8_t *buf,
+ size_t size);
+int as3722_write_buf(struct as3722_softc *sc, uint8_t reg, uint8_t *buf,
+ size_t size);
+
+/* Regulators */
+int as3722_regulator_attach(struct as3722_softc *sc, phandle_t node);
+int as3722_regulator_map(device_t dev, phandle_t xref, int ncells,
+ pcell_t *cells, int *num);
+
+/* RTC */
+int as3722_rtc_attach(struct as3722_softc *sc, phandle_t node);
+int as3722_rtc_gettime(device_t dev, struct timespec *ts);
+int as3722_rtc_settime(device_t dev, struct timespec *ts);
+
+/* GPIO */
+device_t as3722_gpio_get_bus(device_t dev);
+int as3722_gpio_pin_max(device_t dev, int *maxpin);
+int as3722_gpio_pin_getname(device_t dev, uint32_t pin, char *name);
+int as3722_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags);
+int as3722_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps);
+int as3722_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags);
+int as3722_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value);
+int as3722_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val);
+int as3722_gpio_pin_toggle(device_t dev, uint32_t pin);
+int as3722_gpio_map_gpios(device_t dev, phandle_t pdev, phandle_t gparent,
+ int gcells, pcell_t *gpios, uint32_t *pin, uint32_t *flags);
+int as3722_gpio_attach(struct as3722_softc *sc, phandle_t node);
+int as3722_pinmux_configure(device_t dev, phandle_t cfgxref);
+
+#endif /* _AS3722_H_ */
diff --git a/sys/arm/nvidia/as3722_gpio.c b/sys/arm/nvidia/as3722_gpio.c
new file mode 100644
index 0000000..8e53bce
--- /dev/null
+++ b/sys/arm/nvidia/as3722_gpio.c
@@ -0,0 +1,577 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/gpio.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/sx.h>
+
+#include <machine/bus.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/gpio/gpiobusvar.h>
+
+#include "as3722.h"
+
+MALLOC_DEFINE(M_AS3722_GPIO, "AS3722 gpio", "AS3722 GPIO");
+
+/* AS3722_GPIOx_CONTROL MODE and IOSF definition. */
+#define AS3722_IOSF_GPIO 0x00
+#define AS3722_IOSF_INTERRUPT_OUT 0x01
+#define AS3722_IOSF_VSUP_VBAT_LOW_UNDEBOUNCE_OUT 0x02
+#define AS3722_IOSF_GPIO_IN_INTERRUPT 0x03
+#define AS3722_IOSF_PWM_IN 0x04
+#define AS3722_IOSF_VOLTAGE_IN_STANDBY 0x05
+#define AS3722_IOSF_OC_PG_SD0 0x06
+#define AS3722_IOSF_POWERGOOD_OUT 0x07
+#define AS3722_IOSF_CLK32K_OUT 0x08
+#define AS3722_IOSF_WATCHDOG_IN 0x09
+#define AS3722_IOSF_SOFT_RESET_IN 0x0b
+#define AS3722_IOSF_PWM_OUT 0x0c
+#define AS3722_IOSF_VSUP_VBAT_LOW_DEBOUNCE_OUT 0x0d
+#define AS3722_IOSF_OC_PG_SD6 0x0e
+
+#define AS3722_MODE_INPUT 0
+#define AS3722_MODE_PUSH_PULL 1
+#define AS3722_MODE_OPEN_DRAIN 2
+#define AS3722_MODE_TRISTATE 3
+#define AS3722_MODE_INPUT_PULL_UP_LV 4
+#define AS3722_MODE_INPUT_PULL_DOWN 5
+#define AS3722_MODE_OPEN_DRAIN_LV 6
+#define AS3722_MODE_PUSH_PULL_LV 7
+
+#define NGPIO 8
+
+#define GPIO_LOCK(_sc) sx_slock(&(_sc)->gpio_lock)
+#define GPIO_UNLOCK(_sc) sx_unlock(&(_sc)->gpio_lock)
+#define GPIO_ASSERT(_sc) sx_assert(&(_sc)->gpio_lock, SA_LOCKED)
+
+#define AS3722_CFG_BIAS_DISABLE 0x0001
+#define AS3722_CFG_BIAS_PULL_UP 0x0002
+#define AS3722_CFG_BIAS_PULL_DOWN 0x0004
+#define AS3722_CFG_BIAS_HIGH_IMPEDANCE 0x0008
+#define AS3722_CFG_OPEN_DRAIN 0x0010
+
+static const struct {
+ const char *name;
+ int config; /* AS3722_CFG_ */
+} as3722_cfg_names[] = {
+ {"bias-disable", AS3722_CFG_BIAS_DISABLE},
+ {"bias-pull-up", AS3722_CFG_BIAS_PULL_UP},
+ {"bias-pull-down", AS3722_CFG_BIAS_PULL_DOWN},
+ {"bias-high-impedance", AS3722_CFG_BIAS_HIGH_IMPEDANCE},
+ {"drive-open-drain", AS3722_CFG_OPEN_DRAIN},
+};
+
+static struct {
+ const char *name;
+ int fnc_val;
+} as3722_fnc_table[] = {
+ {"gpio", AS3722_IOSF_GPIO},
+ {"interrupt-out", AS3722_IOSF_INTERRUPT_OUT},
+ {"vsup-vbat-low-undebounce-out", AS3722_IOSF_VSUP_VBAT_LOW_UNDEBOUNCE_OUT},
+ {"gpio-in-interrupt", AS3722_IOSF_GPIO_IN_INTERRUPT},
+ {"pwm-in", AS3722_IOSF_PWM_IN},
+ {"voltage-in-standby", AS3722_IOSF_VOLTAGE_IN_STANDBY},
+ {"oc-pg-sd0", AS3722_IOSF_OC_PG_SD0},
+ {"powergood-out", AS3722_IOSF_POWERGOOD_OUT},
+ {"clk32k-out", AS3722_IOSF_CLK32K_OUT},
+ {"watchdog-in", AS3722_IOSF_WATCHDOG_IN},
+ {"soft-reset-in", AS3722_IOSF_SOFT_RESET_IN},
+ {"pwm-out", AS3722_IOSF_PWM_OUT},
+ {"vsup-vbat-low-debounce-out", AS3722_IOSF_VSUP_VBAT_LOW_DEBOUNCE_OUT},
+ {"oc-pg-sd6", AS3722_IOSF_OC_PG_SD6},
+};
+
+struct as3722_pincfg {
+ char *function;
+ int flags;
+};
+
+struct as3722_gpio_pin {
+ int pin_caps;
+ uint8_t pin_ctrl_reg;
+ char pin_name[GPIOMAXNAME];
+ int pin_cfg_flags;
+};
+
+
+/* --------------------------------------------------------------------------
+ *
+ * Pinmux functions.
+ */
+static int
+as3722_pinmux_get_function(struct as3722_softc *sc, char *name)
+{
+ int i;
+
+ for (i = 0; i < nitems(as3722_fnc_table); i++) {
+ if (strcmp(as3722_fnc_table[i].name, name) == 0)
+ return (as3722_fnc_table[i].fnc_val);
+ }
+ return (-1);
+}
+
+
+
+static int
+as3722_pinmux_config_node(struct as3722_softc *sc, char *pin_name,
+ struct as3722_pincfg *cfg)
+{
+ uint8_t ctrl;
+ int rv, fnc, pin;
+
+ for (pin = 0; pin < sc->gpio_npins; pin++) {
+ if (strcmp(sc->gpio_pins[pin]->pin_name, pin_name) == 0)
+ break;
+ }
+ if (pin >= sc->gpio_npins) {
+ device_printf(sc->dev, "Unknown pin: %s\n", pin_name);
+ return (ENXIO);
+ }
+
+ ctrl = sc->gpio_pins[pin]->pin_ctrl_reg;
+ sc->gpio_pins[pin]->pin_cfg_flags = cfg->flags;
+ if (cfg->function != NULL) {
+ fnc = as3722_pinmux_get_function(sc, cfg->function);
+ if (fnc == -1) {
+ device_printf(sc->dev,
+ "Unknown function %s for pin %s\n", cfg->function,
+ sc->gpio_pins[pin]->pin_name);
+ return (ENXIO);
+ }
+ switch (fnc) {
+ case AS3722_IOSF_INTERRUPT_OUT:
+ case AS3722_IOSF_VSUP_VBAT_LOW_UNDEBOUNCE_OUT:
+ case AS3722_IOSF_OC_PG_SD0:
+ case AS3722_IOSF_POWERGOOD_OUT:
+ case AS3722_IOSF_CLK32K_OUT:
+ case AS3722_IOSF_PWM_OUT:
+ case AS3722_IOSF_OC_PG_SD6:
+ ctrl &= ~(AS3722_GPIO_MODE_MASK <<
+ AS3722_GPIO_MODE_SHIFT);
+ ctrl |= AS3722_MODE_PUSH_PULL << AS3722_GPIO_MODE_SHIFT;
+ /* XXX Handle flags (OC + pullup) */
+ break;
+ case AS3722_IOSF_GPIO_IN_INTERRUPT:
+ case AS3722_IOSF_PWM_IN:
+ case AS3722_IOSF_VOLTAGE_IN_STANDBY:
+ case AS3722_IOSF_WATCHDOG_IN:
+ case AS3722_IOSF_SOFT_RESET_IN:
+ ctrl &= ~(AS3722_GPIO_MODE_MASK <<
+ AS3722_GPIO_MODE_SHIFT);
+ ctrl |= AS3722_MODE_INPUT << AS3722_GPIO_MODE_SHIFT;
+ /* XXX Handle flags (pulldown + pullup) */
+
+ default:
+ break;
+ }
+ ctrl &= ~(AS3722_GPIO_IOSF_MASK << AS3722_GPIO_IOSF_SHIFT);
+ ctrl |= fnc << AS3722_GPIO_IOSF_SHIFT;
+ }
+ rv = 0;
+ if (ctrl != sc->gpio_pins[pin]->pin_ctrl_reg) {
+ rv = WR1(sc, AS3722_GPIO0_CONTROL + pin, ctrl);
+ sc->gpio_pins[pin]->pin_ctrl_reg = ctrl;
+ }
+ return (rv);
+}
+
+static int
+as3722_pinmux_read_node(struct as3722_softc *sc, phandle_t node,
+ struct as3722_pincfg *cfg, char **pins, int *lpins)
+{
+ int rv, i;
+
+ *lpins = OF_getprop_alloc(node, "pins", 1, (void **)pins);
+ if (*lpins <= 0)
+ return (ENOENT);
+
+ /* Read function (mux) settings. */
+ rv = OF_getprop_alloc(node, "function", 1, (void **)&cfg->function);
+ if (rv <= 0)
+ cfg->function = NULL;
+
+ /* Read boolean properties. */
+ for (i = 0; i < nitems(as3722_cfg_names); i++) {
+ if (OF_hasprop(node, as3722_cfg_names[i].name))
+ cfg->flags |= as3722_cfg_names[i].config;
+ }
+ return (0);
+}
+
+static int
+as3722_pinmux_process_node(struct as3722_softc *sc, phandle_t node)
+{
+ struct as3722_pincfg cfg;
+ char *pins, *pname;
+ int i, len, lpins, rv;
+
+ rv = as3722_pinmux_read_node(sc, node, &cfg, &pins, &lpins);
+ if (rv != 0)
+ return (rv);
+
+ len = 0;
+ pname = pins;
+ do {
+ i = strlen(pname) + 1;
+ rv = as3722_pinmux_config_node(sc, pname, &cfg);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot configure pin: %s: %d\n", pname, rv);
+ }
+ len += i;
+ pname += i;
+ } while (len < lpins);
+
+ if (pins != NULL)
+ free(pins, M_OFWPROP);
+ if (cfg.function != NULL)
+ free(cfg.function, M_OFWPROP);
+
+ return (rv);
+}
+
+int as3722_pinmux_configure(device_t dev, phandle_t cfgxref)
+{
+ struct as3722_softc *sc;
+ phandle_t node, cfgnode;
+ int rv;
+
+ sc = device_get_softc(dev);
+ cfgnode = OF_node_from_xref(cfgxref);
+
+ for (node = OF_child(cfgnode); node != 0; node = OF_peer(node)) {
+ if (!fdt_is_enabled(node))
+ continue;
+ rv = as3722_pinmux_process_node(sc, node);
+ if (rv != 0)
+ device_printf(dev, "Failed to process pinmux");
+
+ }
+ return (0);
+}
+
+/* --------------------------------------------------------------------------
+ *
+ * GPIO
+ */
+device_t
+as3722_gpio_get_bus(device_t dev)
+{
+ struct as3722_softc *sc;
+
+ sc = device_get_softc(dev);
+ return (sc->gpio_busdev);
+}
+
+int
+as3722_gpio_pin_max(device_t dev, int *maxpin)
+{
+
+ *maxpin = NGPIO - 1;
+ return (0);
+}
+
+int
+as3722_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
+{
+ struct as3722_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (pin >= sc->gpio_npins)
+ return (EINVAL);
+ GPIO_LOCK(sc);
+ *caps = sc->gpio_pins[pin]->pin_caps;
+ GPIO_UNLOCK(sc);
+ return (0);
+}
+
+int
+as3722_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
+{
+ struct as3722_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (pin >= sc->gpio_npins)
+ return (EINVAL);
+ GPIO_LOCK(sc);
+ memcpy(name, sc->gpio_pins[pin]->pin_name, GPIOMAXNAME);
+ GPIO_UNLOCK(sc);
+ return (0);
+}
+
+int
+as3722_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *out_flags)
+{
+ struct as3722_softc *sc;
+ uint8_t tmp, mode, iosf;
+ uint32_t flags;
+ bool inverted;
+
+ sc = device_get_softc(dev);
+ if (pin >= sc->gpio_npins)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ tmp = sc->gpio_pins[pin]->pin_ctrl_reg;
+ GPIO_UNLOCK(sc);
+ iosf = (tmp >> AS3722_GPIO_IOSF_SHIFT) & AS3722_GPIO_IOSF_MASK;
+ mode = (tmp >> AS3722_GPIO_MODE_SHIFT) & AS3722_GPIO_MODE_MASK;
+ inverted = (tmp & AS3722_GPIO_INVERT) != 0;
+ /* Is pin in GPIO mode ? */
+ if (iosf != AS3722_IOSF_GPIO)
+ return (ENXIO);
+
+ flags = 0;
+ switch (mode) {
+ case AS3722_MODE_INPUT:
+ flags = GPIO_PIN_INPUT;
+ break;
+ case AS3722_MODE_PUSH_PULL:
+ case AS3722_MODE_PUSH_PULL_LV:
+ flags = GPIO_PIN_OUTPUT;
+ break;
+ case AS3722_MODE_OPEN_DRAIN:
+ case AS3722_MODE_OPEN_DRAIN_LV:
+ flags = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_OPENDRAIN;
+ break;
+ case AS3722_MODE_TRISTATE:
+ flags = GPIO_PIN_TRISTATE;
+ break;
+ case AS3722_MODE_INPUT_PULL_UP_LV:
+ flags = GPIO_PIN_INPUT | GPIO_PIN_PULLUP;
+ break;
+
+ case AS3722_MODE_INPUT_PULL_DOWN:
+ flags = GPIO_PIN_OUTPUT | GPIO_PIN_PULLDOWN;
+ break;
+ }
+ if (inverted)
+ flags |= GPIO_PIN_INVIN | GPIO_PIN_INVOUT;
+ *out_flags = flags;
+ return (0);
+}
+
+static int
+as3722_gpio_get_mode(struct as3722_softc *sc, uint32_t pin, uint32_t gpio_flags)
+{
+ uint8_t ctrl;
+ int flags;
+
+ ctrl = sc->gpio_pins[pin]->pin_ctrl_reg;
+ flags = sc->gpio_pins[pin]->pin_cfg_flags;
+
+ /* Tristate mode. */
+ if (flags & AS3722_CFG_BIAS_HIGH_IMPEDANCE ||
+ gpio_flags & GPIO_PIN_TRISTATE)
+ return (AS3722_MODE_TRISTATE);
+
+ /* Open drain modes. */
+ if (flags & AS3722_CFG_OPEN_DRAIN || gpio_flags & GPIO_PIN_OPENDRAIN) {
+ /* Only pull up have effect */
+ if (flags & AS3722_CFG_BIAS_PULL_UP ||
+ gpio_flags & GPIO_PIN_PULLUP)
+ return (AS3722_MODE_OPEN_DRAIN_LV);
+ return (AS3722_MODE_OPEN_DRAIN);
+ }
+ /* Input modes. */
+ if (gpio_flags & GPIO_PIN_INPUT) {
+ /* Accept pull up or pull down. */
+ if (flags & AS3722_CFG_BIAS_PULL_UP ||
+ gpio_flags & GPIO_PIN_PULLUP)
+ return (AS3722_MODE_INPUT_PULL_UP_LV);
+
+ if (flags & AS3722_CFG_BIAS_PULL_DOWN ||
+ gpio_flags & GPIO_PIN_PULLDOWN)
+ return (AS3722_MODE_INPUT_PULL_DOWN);
+ return (AS3722_MODE_INPUT);
+ }
+ /*
+ * Output modes.
+ * Pull down is used as indicator of low voltage output.
+ */
+ if (flags & AS3722_CFG_BIAS_PULL_DOWN ||
+ gpio_flags & GPIO_PIN_PULLDOWN)
+ return (AS3722_MODE_PUSH_PULL_LV);
+ return (AS3722_MODE_PUSH_PULL);
+}
+
+int
+as3722_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
+{
+ struct as3722_softc *sc;
+ uint8_t ctrl, mode, iosf;
+ int rv;
+
+ sc = device_get_softc(dev);
+ if (pin >= sc->gpio_npins)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ ctrl = sc->gpio_pins[pin]->pin_ctrl_reg;
+ iosf = (ctrl >> AS3722_GPIO_IOSF_SHIFT) & AS3722_GPIO_IOSF_MASK;
+ /* Is pin in GPIO mode ? */
+ if (iosf != AS3722_IOSF_GPIO) {
+ GPIO_UNLOCK(sc);
+ return (ENXIO);
+ }
+ mode = as3722_gpio_get_mode(sc, pin, flags);
+ ctrl &= ~(AS3722_GPIO_MODE_MASK << AS3722_GPIO_MODE_SHIFT);
+ ctrl |= AS3722_MODE_PUSH_PULL << AS3722_GPIO_MODE_SHIFT;
+ rv = 0;
+ if (ctrl != sc->gpio_pins[pin]->pin_ctrl_reg) {
+ rv = WR1(sc, AS3722_GPIO0_CONTROL + pin, ctrl);
+ sc->gpio_pins[pin]->pin_ctrl_reg = ctrl;
+ }
+ GPIO_UNLOCK(sc);
+ return (rv);
+}
+
+int
+as3722_gpio_pin_set(device_t dev, uint32_t pin, uint32_t val)
+{
+ struct as3722_softc *sc;
+ uint8_t tmp;
+ int rv;
+
+ sc = device_get_softc(dev);
+ if (pin >= sc->gpio_npins)
+ return (EINVAL);
+
+ tmp = (val != 0) ? 1 : 0;
+ if (sc->gpio_pins[pin]->pin_ctrl_reg & AS3722_GPIO_INVERT)
+ tmp ^= 1;
+
+ GPIO_LOCK(sc);
+ rv = RM1(sc, AS3722_GPIO_SIGNAL_OUT, (1 << pin), (tmp << pin));
+ GPIO_UNLOCK(sc);
+ return (rv);
+}
+
+int
+as3722_gpio_pin_get(device_t dev, uint32_t pin, uint32_t *val)
+{
+ struct as3722_softc *sc;
+ uint8_t tmp, mode, ctrl;
+ int rv;
+
+ sc = device_get_softc(dev);
+ if (pin >= sc->gpio_npins)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ ctrl = sc->gpio_pins[pin]->pin_ctrl_reg;
+ mode = (ctrl >> AS3722_GPIO_MODE_SHIFT) & AS3722_GPIO_MODE_MASK;
+ if ((mode == AS3722_MODE_PUSH_PULL) ||
+ (mode == AS3722_MODE_PUSH_PULL_LV))
+ rv = RD1(sc, AS3722_GPIO_SIGNAL_OUT, &tmp);
+ else
+ rv = RD1(sc, AS3722_GPIO_SIGNAL_IN, &tmp);
+ GPIO_UNLOCK(sc);
+ if (rv != 0)
+ return (rv);
+
+ *val = tmp & (1 << pin) ? 1 : 0;
+ if (ctrl & AS3722_GPIO_INVERT)
+ *val ^= 1;
+ return (0);
+}
+
+int
+as3722_gpio_pin_toggle(device_t dev, uint32_t pin)
+{
+ struct as3722_softc *sc;
+ uint8_t tmp;
+ int rv;
+
+ sc = device_get_softc(dev);
+ if (pin >= sc->gpio_npins)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ rv = RD1(sc, AS3722_GPIO_SIGNAL_OUT, &tmp);
+ if (rv != 0) {
+ GPIO_UNLOCK(sc);
+ return (rv);
+ }
+ tmp ^= (1 <<pin);
+ rv = RM1(sc, AS3722_GPIO_SIGNAL_OUT, (1 << pin), tmp);
+ GPIO_UNLOCK(sc);
+ return (0);
+}
+
+int
+as3722_gpio_map_gpios(device_t dev, phandle_t pdev, phandle_t gparent,
+ int gcells, pcell_t *gpios, uint32_t *pin, uint32_t *flags)
+{
+
+ if (gcells != 2)
+ return (ERANGE);
+ *pin = gpios[0];
+ *flags= gpios[1];
+ return (0);
+}
+
+int
+as3722_gpio_attach(struct as3722_softc *sc, phandle_t node)
+{
+ struct as3722_gpio_pin *pin;
+ int i, rv;
+
+ sx_init(&sc->gpio_lock, "AS3722 GPIO lock");
+ sc->gpio_npins = NGPIO;
+ sc->gpio_pins = malloc(sizeof(struct as3722_gpio_pin *) *
+ sc->gpio_npins, M_AS3722_GPIO, M_WAITOK | M_ZERO);
+
+
+ sc->gpio_busdev = gpiobus_attach_bus(sc->dev);
+ if (sc->gpio_busdev == NULL)
+ return (ENXIO);
+ for (i = 0; i < sc->gpio_npins; i++) {
+ sc->gpio_pins[i] = malloc(sizeof(struct as3722_gpio_pin),
+ M_AS3722_GPIO, M_WAITOK | M_ZERO);
+ pin = sc->gpio_pins[i];
+ sprintf(pin->pin_name, "gpio%d", i);
+ pin->pin_caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |
+ GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL | GPIO_PIN_TRISTATE |
+ GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN | GPIO_PIN_INVIN |
+ GPIO_PIN_INVOUT;
+ rv = RD1(sc, AS3722_GPIO0_CONTROL + i, &pin->pin_ctrl_reg);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot read configuration for pin %s\n",
+ sc->gpio_pins[i]->pin_name);
+ }
+ }
+ return (0);
+}
diff --git a/sys/arm/nvidia/as3722_regulators.c b/sys/arm/nvidia/as3722_regulators.c
new file mode 100644
index 0000000..0bca8e1
--- /dev/null
+++ b/sys/arm/nvidia/as3722_regulators.c
@@ -0,0 +1,811 @@
+/*-
+ * Copyright 2016 Michal Meloun <mmel@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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/gpio.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/sx.h>
+
+#include <machine/bus.h>
+
+#include <dev/extres/regulator/regulator.h>
+#include <dev/gpio/gpiobusvar.h>
+
+#include <gnu/dts/include/dt-bindings/mfd/as3722.h>
+
+#include "as3722.h"
+
+MALLOC_DEFINE(M_AS3722_REG, "AS3722 regulator", "AS3722 power regulator");
+
+#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
+
+enum as3722_reg_id {
+ AS3722_REG_ID_SD0,
+ AS3722_REG_ID_SD1,
+ AS3722_REG_ID_SD2,
+ AS3722_REG_ID_SD3,
+ AS3722_REG_ID_SD4,
+ AS3722_REG_ID_SD5,
+ AS3722_REG_ID_SD6,
+ AS3722_REG_ID_LDO0,
+ AS3722_REG_ID_LDO1,
+ AS3722_REG_ID_LDO2,
+ AS3722_REG_ID_LDO3,
+ AS3722_REG_ID_LDO4,
+ AS3722_REG_ID_LDO5,
+ AS3722_REG_ID_LDO6,
+ AS3722_REG_ID_LDO7,
+ AS3722_REG_ID_LDO9,
+ AS3722_REG_ID_LDO10,
+ AS3722_REG_ID_LDO11,
+};
+
+struct regulator_range {
+ u_int min_uvolt;
+ u_int step_uvolt;
+ u_int min_sel;
+ u_int max_sel;
+};
+
+
+/* Regulator HW definition. */
+struct reg_def {
+ intptr_t id; /* ID */
+ char *name; /* Regulator name */
+ char *supply_name; /* Source property name */
+ uint8_t volt_reg;
+ uint8_t volt_vsel_mask;
+ uint8_t enable_reg;
+ uint8_t enable_mask;
+ uint8_t ext_enable_reg;
+ uint8_t ext_enable_mask;
+ struct regulator_range *ranges;
+ int nranges;
+};
+
+struct as3722_reg_sc {
+ struct regnode *regnode;
+ struct as3722_softc *base_sc;
+ struct reg_def *def;
+ phandle_t xref;
+
+ struct regnode_std_param *param;
+ int ext_control;
+ int enable_tracking;
+
+ int enable_usec;
+};
+
+#define RANGE_INIT(_min_sel, _max_sel, _min_uvolt, _step_uvolt) \
+{ \
+ .min_sel = _min_sel, \
+ .max_sel = _max_sel, \
+ .min_uvolt = _min_uvolt, \
+ .step_uvolt = _step_uvolt, \
+}
+
+static struct regulator_range as3722_sd016_ranges[] = {
+ RANGE_INIT(0x00, 0x00, 0, 0),
+ RANGE_INIT(0x01, 0x5A, 610000, 10000),
+};
+
+static struct regulator_range as3722_sd0_lv_ranges[] = {
+ RANGE_INIT(0x00, 0x00, 0, 0),
+ RANGE_INIT(0x01, 0x6E, 410000, 10000),
+};
+
+static struct regulator_range as3722_sd_ranges[] = {
+ RANGE_INIT(0x00, 0x00, 0, 0),
+ RANGE_INIT(0x01, 0x40, 612500, 12500),
+ RANGE_INIT(0x41, 0x70, 1425000, 25000),
+ RANGE_INIT(0x71, 0x7F, 2650000, 50000),
+};
+
+static struct regulator_range as3722_ldo3_ranges[] = {
+ RANGE_INIT(0x00, 0x00, 0, 0),
+ RANGE_INIT(0x01, 0x2D, 620000, 20000),
+};
+
+static struct regulator_range as3722_ldo_ranges[] = {
+ RANGE_INIT(0x00, 0x00, 0, 0),
+ RANGE_INIT(0x01, 0x24, 825000, 25000),
+ RANGE_INIT(0x40, 0x7F, 1725000, 25000),
+};
+
+static struct reg_def as3722s_def[] = {
+ {
+ .id = AS3722_REG_ID_SD0,
+ .name = "sd0",
+ .volt_reg = AS3722_SD0_VOLTAGE,
+ .volt_vsel_mask = AS3722_SD_VSEL_MASK,
+ .enable_reg = AS3722_SD_CONTROL,
+ .enable_mask = AS3722_SDN_CTRL(0),
+ .ext_enable_reg = AS3722_ENABLE_CTRL1,
+ .ext_enable_mask = AS3722_SD0_EXT_ENABLE_MASK,
+ .ranges = as3722_sd016_ranges,
+ .nranges = nitems(as3722_sd016_ranges),
+ },
+ {
+ .id = AS3722_REG_ID_SD1,
+ .name = "sd1",
+ .volt_reg = AS3722_SD1_VOLTAGE,
+ .volt_vsel_mask = AS3722_SD_VSEL_MASK,
+ .enable_reg = AS3722_SD_CONTROL,
+ .enable_mask = AS3722_SDN_CTRL(1),
+ .ext_enable_reg = AS3722_ENABLE_CTRL1,
+ .ext_enable_mask = AS3722_SD1_EXT_ENABLE_MASK,
+ .ranges = as3722_sd_ranges,
+ .nranges = nitems(as3722_sd_ranges),
+ },
+ {
+ .id = AS3722_REG_ID_SD2,
+ .name = "sd2",
+ .supply_name = "vsup-sd2",
+ .volt_reg = AS3722_SD2_VOLTAGE,
+ .volt_vsel_mask = AS3722_SD_VSEL_MASK,
+ .enable_reg = AS3722_SD_CONTROL,
+ .enable_mask = AS3722_SDN_CTRL(2),
+ .ext_enable_reg = AS3722_ENABLE_CTRL1,
+ .ext_enable_mask = AS3722_SD2_EXT_ENABLE_MASK,
+ .ranges = as3722_sd_ranges,
+ .nranges = nitems(as3722_sd_ranges),
+ },
+ {
+ .id = AS3722_REG_ID_SD3,
+ .name = "sd3",
+ .supply_name = "vsup-sd3",
+ .volt_reg = AS3722_SD3_VOLTAGE,
+ .volt_vsel_mask = AS3722_SD_VSEL_MASK,
+ .enable_reg = AS3722_SD_CONTROL,
+ .enable_mask = AS3722_SDN_CTRL(3),
+ .ext_enable_reg = AS3722_ENABLE_CTRL1,
+ .ext_enable_mask = AS3722_SD3_EXT_ENABLE_MASK,
+ .ranges = as3722_sd_ranges,
+ .nranges = nitems(as3722_sd_ranges),
+ },
+ {
+ .id = AS3722_REG_ID_SD4,
+ .name = "sd4",
+ .supply_name = "vsup-sd4",
+ .volt_reg = AS3722_SD4_VOLTAGE,
+ .volt_vsel_mask = AS3722_SD_VSEL_MASK,
+ .enable_reg = AS3722_SD_CONTROL,
+ .enable_mask = AS3722_SDN_CTRL(4),
+ .ext_enable_reg = AS3722_ENABLE_CTRL2,
+ .ext_enable_mask = AS3722_SD4_EXT_ENABLE_MASK,
+ .ranges = as3722_sd_ranges,
+ .nranges = nitems(as3722_sd_ranges),
+ },
+ {
+ .id = AS3722_REG_ID_SD5,
+ .name = "sd5",
+ .supply_name = "vsup-sd5",
+ .volt_reg = AS3722_SD5_VOLTAGE,
+ .volt_vsel_mask = AS3722_SD_VSEL_MASK,
+ .enable_reg = AS3722_SD_CONTROL,
+ .enable_mask = AS3722_SDN_CTRL(5),
+ .ext_enable_reg = AS3722_ENABLE_CTRL2,
+ .ext_enable_mask = AS3722_SD5_EXT_ENABLE_MASK,
+ .ranges = as3722_sd_ranges,
+ .nranges = nitems(as3722_sd_ranges),
+ },
+ {
+ .id = AS3722_REG_ID_SD6,
+ .name = "sd6",
+ .volt_reg = AS3722_SD6_VOLTAGE,
+ .volt_vsel_mask = AS3722_SD_VSEL_MASK,
+ .enable_reg = AS3722_SD_CONTROL,
+ .enable_mask = AS3722_SDN_CTRL(6),
+ .ext_enable_reg = AS3722_ENABLE_CTRL2,
+ .ext_enable_mask = AS3722_SD6_EXT_ENABLE_MASK,
+ .ranges = as3722_sd016_ranges,
+ .nranges = nitems(as3722_sd016_ranges),
+ },
+ {
+ .id = AS3722_REG_ID_LDO0,
+ .name = "ldo0",
+ .supply_name = "vin-ldo0",
+ .volt_reg = AS3722_LDO0_VOLTAGE,
+ .volt_vsel_mask = AS3722_LDO0_VSEL_MASK,
+ .enable_reg = AS3722_LDO_CONTROL0,
+ .enable_mask = AS3722_LDO0_CTRL,
+ .ext_enable_reg = AS3722_ENABLE_CTRL3,
+ .ext_enable_mask = AS3722_LDO0_EXT_ENABLE_MASK,
+ .ranges = as3722_ldo_ranges,
+ .nranges = nitems(as3722_ldo_ranges),
+ },
+ {
+ .id = AS3722_REG_ID_LDO1,
+ .name = "ldo1",
+ .supply_name = "vin-ldo1-6",
+ .volt_reg = AS3722_LDO1_VOLTAGE,
+ .volt_vsel_mask = AS3722_LDO_VSEL_MASK,
+ .enable_reg = AS3722_LDO_CONTROL0,
+ .enable_mask = AS3722_LDO1_CTRL,
+ .ext_enable_reg = AS3722_ENABLE_CTRL3,
+ .ext_enable_mask = AS3722_LDO1_EXT_ENABLE_MASK,
+ .ranges = as3722_ldo_ranges,
+ .nranges = nitems(as3722_ldo_ranges),
+ },
+ {
+ .id = AS3722_REG_ID_LDO2,
+ .name = "ldo2",
+ .supply_name = "vin-ldo2-5-7",
+ .volt_reg = AS3722_LDO2_VOLTAGE,
+ .volt_vsel_mask = AS3722_LDO_VSEL_MASK,
+ .enable_reg = AS3722_LDO_CONTROL0,
+ .enable_mask = AS3722_LDO2_CTRL,
+ .ext_enable_reg = AS3722_ENABLE_CTRL3,
+ .ext_enable_mask = AS3722_LDO2_EXT_ENABLE_MASK,
+ .ranges = as3722_ldo_ranges,
+ .nranges = nitems(as3722_ldo_ranges),
+ },
+ {
+ .id = AS3722_REG_ID_LDO3,
+ .name = "ldo3",
+ .supply_name = "vin-ldo3-4",
+ .volt_reg = AS3722_LDO3_VOLTAGE,
+ .volt_vsel_mask = AS3722_LDO3_VSEL_MASK,
+ .enable_reg = AS3722_LDO_CONTROL0,
+ .enable_mask = AS3722_LDO3_CTRL,
+ .ext_enable_reg = AS3722_ENABLE_CTRL3,
+ .ext_enable_mask = AS3722_LDO3_EXT_ENABLE_MASK,
+ .ranges = as3722_ldo3_ranges,
+ .nranges = nitems(as3722_ldo3_ranges),
+ },
+ {
+ .id = AS3722_REG_ID_LDO4,
+ .name = "ldo4",
+ .supply_name = "vin-ldo3-4",
+ .volt_reg = AS3722_LDO4_VOLTAGE,
+ .volt_vsel_mask = AS3722_LDO_VSEL_MASK,
+ .enable_reg = AS3722_LDO_CONTROL0,
+ .enable_mask = AS3722_LDO4_CTRL,
+ .ext_enable_reg = AS3722_ENABLE_CTRL4,
+ .ext_enable_mask = AS3722_LDO4_EXT_ENABLE_MASK,
+ .ranges = as3722_ldo_ranges,
+ .nranges = nitems(as3722_ldo_ranges),
+ },
+ {
+ .id = AS3722_REG_ID_LDO5,
+ .name = "ldo5",
+ .supply_name = "vin-ldo2-5-7",
+ .volt_reg = AS3722_LDO5_VOLTAGE,
+ .volt_vsel_mask = AS3722_LDO_VSEL_MASK,
+ .enable_reg = AS3722_LDO_CONTROL0,
+ .enable_mask = AS3722_LDO5_CTRL,
+ .ext_enable_reg = AS3722_ENABLE_CTRL4,
+ .ext_enable_mask = AS3722_LDO5_EXT_ENABLE_MASK,
+ .ranges = as3722_ldo_ranges,
+ .nranges = nitems(as3722_ldo_ranges),
+ },
+ {
+ .id = AS3722_REG_ID_LDO6,
+ .name = "ldo6",
+ .supply_name = "vin-ldo1-6",
+ .volt_reg = AS3722_LDO6_VOLTAGE,
+ .volt_vsel_mask = AS3722_LDO_VSEL_MASK,
+ .enable_reg = AS3722_LDO_CONTROL0,
+ .enable_mask = AS3722_LDO6_CTRL,
+ .ext_enable_reg = AS3722_ENABLE_CTRL4,
+ .ext_enable_mask = AS3722_LDO6_EXT_ENABLE_MASK,
+ .ranges = as3722_ldo_ranges,
+ .nranges = nitems(as3722_ldo_ranges),
+ },
+ {
+ .id = AS3722_REG_ID_LDO7,
+ .name = "ldo7",
+ .supply_name = "vin-ldo2-5-7",
+ .volt_reg = AS3722_LDO7_VOLTAGE,
+ .volt_vsel_mask = AS3722_LDO_VSEL_MASK,
+ .enable_reg = AS3722_LDO_CONTROL0,
+ .enable_mask = AS3722_LDO7_CTRL,
+ .ext_enable_reg = AS3722_ENABLE_CTRL4,
+ .ext_enable_mask = AS3722_LDO7_EXT_ENABLE_MASK,
+ .ranges = as3722_ldo_ranges,
+ .nranges = nitems(as3722_ldo_ranges),
+ },
+ {
+ .id = AS3722_REG_ID_LDO9,
+ .name = "ldo9",
+ .supply_name = "vin-ldo9-10",
+ .volt_reg = AS3722_LDO9_VOLTAGE,
+ .volt_vsel_mask = AS3722_LDO_VSEL_MASK,
+ .enable_reg = AS3722_LDO_CONTROL1,
+ .enable_mask = AS3722_LDO9_CTRL,
+ .ext_enable_reg = AS3722_ENABLE_CTRL5,
+ .ext_enable_mask = AS3722_LDO9_EXT_ENABLE_MASK,
+ .ranges = as3722_ldo_ranges,
+ .nranges = nitems(as3722_ldo_ranges),
+ },
+ {
+ .id = AS3722_REG_ID_LDO10,
+ .name = "ldo10",
+ .supply_name = "vin-ldo9-10",
+ .volt_reg = AS3722_LDO10_VOLTAGE,
+ .volt_vsel_mask = AS3722_LDO_VSEL_MASK,
+ .enable_reg = AS3722_LDO_CONTROL1,
+ .enable_mask = AS3722_LDO10_CTRL,
+ .ext_enable_reg = AS3722_ENABLE_CTRL5,
+ .ext_enable_mask = AS3722_LDO10_EXT_ENABLE_MASK,
+ .ranges = as3722_ldo_ranges,
+ .nranges = nitems(as3722_ldo_ranges),
+ },
+ {
+ .id = AS3722_REG_ID_LDO11,
+ .name = "ldo11",
+ .supply_name = "vin-ldo11",
+ .volt_reg = AS3722_LDO11_VOLTAGE,
+ .volt_vsel_mask = AS3722_LDO_VSEL_MASK,
+ .enable_reg = AS3722_LDO_CONTROL1,
+ .enable_mask = AS3722_LDO11_CTRL,
+ .ext_enable_reg = AS3722_ENABLE_CTRL5,
+ .ext_enable_mask = AS3722_LDO11_EXT_ENABLE_MASK,
+ .ranges = as3722_ldo_ranges,
+ .nranges = nitems(as3722_ldo_ranges),
+ },
+};
+
+
+struct as3722_regnode_init_def {
+ struct regnode_init_def reg_init_def;
+ int ext_control;
+ int enable_tracking;
+};
+
+static int as3722_regnode_init(struct regnode *regnode);
+static int as3722_regnode_enable(struct regnode *regnode, bool enable,
+ int *udelay);
+static int as3722_regnode_set_volt(struct regnode *regnode, int min_uvolt,
+ int max_uvolt, int *udelay);
+static int as3722_regnode_get_volt(struct regnode *regnode, int *uvolt);
+static regnode_method_t as3722_regnode_methods[] = {
+ /* Regulator interface */
+ REGNODEMETHOD(regnode_init, as3722_regnode_init),
+ REGNODEMETHOD(regnode_enable, as3722_regnode_enable),
+ REGNODEMETHOD(regnode_set_voltage, as3722_regnode_set_volt),
+ REGNODEMETHOD(regnode_get_voltage, as3722_regnode_get_volt),
+ REGNODEMETHOD_END
+};
+DEFINE_CLASS_1(as3722_regnode, as3722_regnode_class, as3722_regnode_methods,
+ sizeof(struct as3722_reg_sc), regnode_class);
+
+static int
+regulator_range_sel_to_volt(struct as3722_reg_sc *sc, uint8_t sel, int *volt)
+{
+ struct regulator_range *range;
+ struct reg_def *def;
+ int i;
+
+ def = sc->def;
+ if (def->nranges == 0)
+ panic("Voltage regulator have zero ranges\n");
+
+ for (i = 0; i < def->nranges ; i++) {
+ range = def->ranges + i;
+
+ if (!(sel >= range->min_sel &&
+ sel <= range->max_sel))
+ continue;
+
+ sel -= range->min_sel;
+
+ *volt = range->min_uvolt + sel * range->step_uvolt;
+ return (0);
+ }
+
+ return (ERANGE);
+}
+
+static int
+regulator_range_volt_to_sel(struct as3722_reg_sc *sc, int min_uvolt,
+ int max_uvolt, uint8_t *out_sel)
+{
+ struct regulator_range *range;
+ struct reg_def *def;
+ uint8_t sel;
+ int uvolt;
+ int rv, i;
+
+ def = sc->def;
+ if (def->nranges == 0)
+ panic("Voltage regulator have zero ranges\n");
+
+ for (i = 0; i < def->nranges; i++) {
+ range = def->ranges + i;
+ uvolt = range->min_uvolt +
+ (range->max_sel - range->min_sel) * range->step_uvolt;
+
+ if ((min_uvolt > uvolt) ||
+ (max_uvolt < range->min_uvolt))
+ continue;
+
+ if (min_uvolt <= range->min_uvolt)
+ min_uvolt = range->min_uvolt;
+
+ /* If step is zero then range is fixed voltage range. */
+ if (range->step_uvolt == 0)
+ sel = 0;
+ else
+ sel = DIV_ROUND_UP(min_uvolt - range->min_uvolt,
+ range->step_uvolt);
+
+
+ sel += range->min_sel;
+
+ break;
+ }
+
+ if (i >= def->nranges)
+ return (ERANGE);
+
+ /* Verify new settings. */
+ rv = regulator_range_sel_to_volt(sc, sel, &uvolt);
+ if (rv != 0)
+ return (rv);
+ if ((uvolt < min_uvolt) || (uvolt > max_uvolt))
+ return (ERANGE);
+
+ *out_sel = sel;
+ return (0);
+}
+
+
+static int
+as3722_read_sel(struct as3722_reg_sc *sc, uint8_t *sel)
+{
+ int rv;
+
+ rv = RD1(sc->base_sc, sc->def->volt_reg, sel);
+ if (rv != 0)
+ return (rv);
+ *sel &= sc->def->volt_vsel_mask;
+ *sel >>= ffs(sc->def->volt_vsel_mask) - 1;
+ return (0);
+}
+
+static int
+as3722_write_sel(struct as3722_reg_sc *sc, uint8_t sel)
+{
+ int rv;
+
+ sel <<= ffs(sc->def->volt_vsel_mask) - 1;
+ sel &= sc->def->volt_vsel_mask;
+
+ rv = RM1(sc->base_sc, sc->def->volt_reg,
+ sc->def->volt_vsel_mask, sel);
+ if (rv != 0)
+ return (rv);
+ return (rv);
+}
+
+static bool
+as3722_sd0_is_low_voltage(struct as3722_reg_sc *sc)
+{
+ uint8_t val;
+ int rv;
+
+ rv = RD1(sc->base_sc, AS3722_FUSE7, &val);
+ if (rv != 0)
+ return (rv);
+ return (val & AS3722_FUSE7_SD0_LOW_VOLTAGE ? true : false);
+}
+
+static int
+as3722_reg_extreg_setup(struct as3722_reg_sc *sc, int ext_pwr_ctrl)
+{
+ uint8_t val;
+ int rv;
+
+ val = ext_pwr_ctrl << (ffs(sc->def->ext_enable_mask) - 1);
+ rv = RM1(sc->base_sc, sc->def->ext_enable_reg,
+ sc->def->ext_enable_mask, val);
+ return (rv);
+}
+
+static int
+as3722_reg_enable(struct as3722_reg_sc *sc)
+{
+ int rv;
+
+ rv = RM1(sc->base_sc, sc->def->enable_reg,
+ sc->def->enable_mask, sc->def->enable_mask);
+ return (rv);
+}
+
+static int
+as3722_reg_disable(struct as3722_reg_sc *sc)
+{
+ int rv;
+
+ rv = RM1(sc->base_sc, sc->def->enable_reg,
+ sc->def->enable_mask, 0);
+ return (rv);
+}
+
+static int
+as3722_regnode_init(struct regnode *regnode)
+{
+ struct as3722_reg_sc *sc;
+ int rv;
+
+ sc = regnode_get_softc(regnode);
+
+ sc->enable_usec = 500;
+ if (sc->def->id == AS3722_REG_ID_SD0) {
+ if (as3722_sd0_is_low_voltage(sc)) {
+ sc->def->ranges = as3722_sd0_lv_ranges;
+ sc->def->nranges = nitems(as3722_sd0_lv_ranges);
+ }
+ sc->enable_usec = 600;
+ } else if (sc->def->id == AS3722_REG_ID_LDO3) {
+ if (sc->enable_tracking) {
+ rv = RM1(sc->base_sc, sc->def->volt_reg,
+ AS3722_LDO3_MODE_MASK,
+ AS3722_LDO3_MODE_PMOS_TRACKING);
+ if (rv < 0) {
+ device_printf(sc->base_sc->dev,
+ "LDO3 tracking failed: %d\n", rv);
+ return (rv);
+ }
+ }
+ }
+
+ if (sc->ext_control) {
+
+ rv = as3722_reg_enable(sc);
+ if (rv < 0) {
+ device_printf(sc->base_sc->dev,
+ "Failed to enable %s regulator: %d\n",
+ sc->def->name, rv);
+ return (rv);
+ }
+ rv = as3722_reg_extreg_setup(sc, sc->ext_control);
+ if (rv < 0) {
+ device_printf(sc->base_sc->dev,
+ "%s ext control failed: %d", sc->def->name, rv);
+ return (rv);
+ }
+ }
+ return (0);
+}
+
+static void
+as3722_fdt_parse(struct as3722_softc *sc, phandle_t node, struct reg_def *def,
+struct as3722_regnode_init_def *init_def)
+{
+ int rv;
+ phandle_t parent, supply_node;
+ char prop_name[64]; /* Maximum OFW property name length. */
+
+ rv = regulator_parse_ofw_stdparam(sc->dev, node,
+ &init_def->reg_init_def);
+
+ rv = OF_getencprop(node, "ams,ext-control", &init_def->ext_control,
+ sizeof(init_def->ext_control));
+ if (rv <= 0)
+ init_def->ext_control = 0;
+ if (init_def->ext_control > 3) {
+ device_printf(sc->dev,
+ "Invalid value for ams,ext-control property: %d\n",
+ init_def->ext_control);
+ init_def->ext_control = 0;
+ }
+ if (OF_hasprop(node, "ams,enable-tracking"))
+ init_def->enable_tracking = 1;
+
+
+ /* Get parent supply. */
+ if (def->supply_name == NULL)
+ return;
+
+ parent = OF_parent(node);
+ snprintf(prop_name, sizeof(prop_name), "%s-supply",
+ def->supply_name);
+ rv = OF_getencprop(parent, prop_name, &supply_node,
+ sizeof(supply_node));
+ if (rv <= 0)
+ return;
+ supply_node = OF_node_from_xref(supply_node);
+ rv = OF_getprop_alloc(supply_node, "regulator-name", 1,
+ (void **)&init_def->reg_init_def.parent_name);
+ if (rv <= 0)
+ init_def->reg_init_def.parent_name = NULL;
+}
+
+static struct as3722_reg_sc *
+as3722_attach(struct as3722_softc *sc, phandle_t node, struct reg_def *def)
+{
+ struct as3722_reg_sc *reg_sc;
+ struct as3722_regnode_init_def init_def;
+ struct regnode *regnode;
+
+ bzero(&init_def, sizeof(init_def));
+
+ as3722_fdt_parse(sc, node, def, &init_def);
+ init_def.reg_init_def.id = def->id;
+ init_def.reg_init_def.ofw_node = node;
+ regnode = regnode_create(sc->dev, &as3722_regnode_class,
+ &init_def.reg_init_def);
+ if (regnode == NULL) {
+ device_printf(sc->dev, "Cannot create regulator.\n");
+ return (NULL);
+ }
+ reg_sc = regnode_get_softc(regnode);
+
+ /* Init regulator softc. */
+ reg_sc->regnode = regnode;
+ reg_sc->base_sc = sc;
+ reg_sc->def = def;
+ reg_sc->xref = OF_xref_from_node(node);
+
+ reg_sc->param = regnode_get_stdparam(regnode);
+ reg_sc->ext_control = init_def.ext_control;
+ reg_sc->enable_tracking = init_def.enable_tracking;
+
+ regnode_register(regnode);
+ if (bootverbose) {
+ int volt, rv;
+ regnode_topo_slock();
+ rv = regnode_get_voltage(regnode, &volt);
+ if (rv == ENODEV) {
+ device_printf(sc->dev,
+ " Regulator %s: parent doesn't exist yet.\n",
+ regnode_get_name(regnode));
+ } else if (rv != 0) {
+ device_printf(sc->dev,
+ " Regulator %s: voltage: INVALID!!!\n",
+ regnode_get_name(regnode));
+ } else {
+ device_printf(sc->dev,
+ " Regulator %s: voltage: %d uV\n",
+ regnode_get_name(regnode), volt);
+ }
+ regnode_topo_unlock();
+ }
+
+ return (reg_sc);
+}
+
+int
+as3722_regulator_attach(struct as3722_softc *sc, phandle_t node)
+{
+ struct as3722_reg_sc *reg;
+ phandle_t child, rnode;
+ int i;
+
+ rnode = ofw_bus_find_child(node, "regulators");
+ if (rnode <= 0) {
+ device_printf(sc->dev, " Cannot find regulators subnode\n");
+ return (ENXIO);
+ }
+
+ sc->nregs = nitems(as3722s_def);
+ sc->regs = malloc(sizeof(struct as3722_reg_sc *) * sc->nregs,
+ M_AS3722_REG, M_WAITOK | M_ZERO);
+
+
+ /* Attach all known regulators if exist in DT. */
+ for (i = 0; i < sc->nregs; i++) {
+ child = ofw_bus_find_child(rnode, as3722s_def[i].name);
+ if (child == 0) {
+ if (bootverbose)
+ device_printf(sc->dev,
+ "Regulator %s missing in DT\n",
+ as3722s_def[i].name);
+ continue;
+ }
+ reg = as3722_attach(sc, child, as3722s_def + i);
+ if (reg == NULL) {
+ device_printf(sc->dev, "Cannot attach regulator: %s\n",
+ as3722s_def[i].name);
+ return (ENXIO);
+ }
+ sc->regs[i] = reg;
+ }
+ return (0);
+}
+
+int
+as3722_regulator_map(device_t dev, phandle_t xref, int ncells,
+ pcell_t *cells, int *num)
+{
+ struct as3722_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+ for (i = 0; i < sc->nregs; i++) {
+ if (sc->regs[i] == NULL)
+ continue;
+ if (sc->regs[i]->xref == xref) {
+ *num = sc->regs[i]->def->id;
+ return (0);
+ }
+ }
+ return (ENXIO);
+}
+
+static int
+as3722_regnode_enable(struct regnode *regnode, bool val, int *udelay)
+{
+ struct as3722_reg_sc *sc;
+ int rv;
+
+ sc = regnode_get_softc(regnode);
+
+ if (val)
+ rv = as3722_reg_enable(sc);
+ else
+ rv = as3722_reg_disable(sc);
+ *udelay = sc->enable_usec;
+ return (rv);
+}
+
+static int
+as3722_regnode_set_volt(struct regnode *regnode, int min_uvolt, int max_uvolt,
+ int *udelay)
+{
+ struct as3722_reg_sc *sc;
+ uint8_t sel;
+ int rv;
+
+ sc = regnode_get_softc(regnode);
+
+ *udelay = 0;
+ rv = regulator_range_volt_to_sel(sc, min_uvolt, max_uvolt, &sel);
+ if (rv != 0)
+ return (rv);
+ rv = as3722_write_sel(sc, sel);
+ return (rv);
+
+}
+
+static int
+as3722_regnode_get_volt(struct regnode *regnode, int *uvolt)
+{
+ struct as3722_reg_sc *sc;
+ uint8_t sel;
+ int rv;
+
+ sc = regnode_get_softc(regnode);
+ rv = as3722_read_sel(sc, &sel);
+ if (rv != 0)
+ return (rv);
+
+ /* LDO6 have bypass. */
+ if (sc->def->id == AS3722_REG_ID_LDO6 && sel == AS3722_LDO6_SEL_BYPASS)
+ return (ENOENT);
+ rv = regulator_range_sel_to_volt(sc, sel, uvolt);
+ return (rv);
+}
diff --git a/sys/arm/nvidia/as3722_rtc.c b/sys/arm/nvidia/as3722_rtc.c
new file mode 100644
index 0000000..8f13104
--- /dev/null
+++ b/sys/arm/nvidia/as3722_rtc.c
@@ -0,0 +1,115 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/clock.h>
+#include <sys/kernel.h>
+
+#include <dev/ofw/ofw_bus.h>
+
+#include "clock_if.h"
+#include "as3722.h"
+
+#define AS3722_RTC_START_YEAR 2000
+
+int
+as3722_rtc_gettime(device_t dev, struct timespec *ts)
+{
+ struct as3722_softc *sc;
+ struct clocktime ct;
+ uint8_t buf[6];
+ int rv;
+
+ sc = device_get_softc(dev);
+
+ rv = as3722_read_buf(sc, AS3722_RTC_SECOND, buf, 6);
+ if (rv != 0) {
+ device_printf(sc->dev, "Failed to read RTC data\n");
+ return (rv);
+ }
+ ct.nsec = 0;
+ ct.sec = bcd2bin(buf[0] & 0x7F);
+ ct.min = bcd2bin(buf[1] & 0x7F);
+ ct.hour = bcd2bin(buf[2] & 0x3F);
+ ct.day = bcd2bin(buf[3] & 0x3F);
+ ct.mon = bcd2bin(buf[4] & 0x1F);
+ ct.year = bcd2bin(buf[5] & 0x7F) + AS3722_RTC_START_YEAR;
+ ct.dow = -1;
+
+ return clock_ct_to_ts(&ct, ts);
+}
+
+int
+as3722_rtc_settime(device_t dev, struct timespec *ts)
+{
+ struct as3722_softc *sc;
+ struct clocktime ct;
+ uint8_t buf[6];
+ int rv;
+
+ sc = device_get_softc(dev);
+ clock_ts_to_ct(ts, &ct);
+
+ if (ct.year < AS3722_RTC_START_YEAR)
+ return (EINVAL);
+
+ buf[0] = bin2bcd(ct.sec);
+ buf[1] = bin2bcd(ct.min);
+ buf[2] = bin2bcd(ct.hour);
+ buf[3] = bin2bcd(ct.day);
+ buf[4] = bin2bcd(ct.mon);
+ buf[5] = bin2bcd(ct.year - AS3722_RTC_START_YEAR);
+
+ rv = as3722_write_buf(sc, AS3722_RTC_SECOND, buf, 6);
+ if (rv != 0) {
+ device_printf(sc->dev, "Failed to write RTC data\n");
+ return (rv);
+ }
+ return (0);
+}
+
+int
+as3722_rtc_attach(struct as3722_softc *sc, phandle_t node)
+{
+ int rv;
+
+ /* Enable RTC, set 24 hours mode and alarms */
+ rv = RM1(sc, AS3722_RTC_CONTROL,
+ AS3722_RTC_ON | AS3722_RTC_ALARM_WAKEUP_EN | AS3722_RTC_AM_PM_MODE,
+ AS3722_RTC_ON | AS3722_RTC_ALARM_WAKEUP_EN);
+ if (rv < 0) {
+ device_printf(sc->dev, "Failed to initialize RTC controller\n");
+ return (ENXIO);
+ }
+ clock_register(sc->dev, 1000000);
+
+ return (0);
+}
diff --git a/sys/arm/nvidia/tegra124/files.tegra124 b/sys/arm/nvidia/tegra124/files.tegra124
new file mode 100644
index 0000000..d4d38f7
--- /dev/null
+++ b/sys/arm/nvidia/tegra124/files.tegra124
@@ -0,0 +1,57 @@
+# $FreeBSD$
+
+#
+# Standard ARM support.
+#
+kern/kern_clocksource.c standard
+dev/ofw/ofw_cpu.c optional fdt
+
+#
+# Standard tegra124 devices and support.
+#
+arm/nvidia/tegra124/tegra124_machdep.c standard
+arm/nvidia/tegra124/tegra124_mp.c optional smp
+arm/nvidia/tegra124/tegra124_car.c standard
+arm/nvidia/tegra124/tegra124_clk_pll.c standard
+arm/nvidia/tegra124/tegra124_clk_per.c standard
+arm/nvidia/tegra124/tegra124_clk_super.c standard
+arm/nvidia/tegra124/tegra124_xusbpadctl.c standard
+arm/nvidia/tegra124/tegra124_pmc.c standard
+arm/nvidia/tegra124/tegra124_cpufreq.c standard
+arm/nvidia/tegra124/tegra124_coretemp.c standard
+arm/nvidia/tegra_usbphy.c standard
+arm/nvidia/tegra_pinmux.c standard
+arm/nvidia/tegra_uart.c optional uart
+arm/nvidia/tegra_sdhci.c optional sdhci
+arm/nvidia/tegra_gpio.c optional gpio
+arm/nvidia/tegra_ehci.c optional ehci
+arm/nvidia/tegra_ahci.c optional ahci
+arm/nvidia/tegra_pcie.c optional pci
+arm/nvidia/tegra_i2c.c optional iic
+arm/nvidia/tegra_rtc.c standard
+arm/nvidia/tegra_abpmisc.c standard
+arm/nvidia/tegra_efuse.c standard
+arm/nvidia/tegra_soctherm_if.m standard
+arm/nvidia/tegra_soctherm.c standard
+arm/nvidia/tegra_lic.c standard
+#arm/nvidia/tegra_hda.c optional snd_hda
+#arm/nvidia/drm2/hdmi.c optional drm2
+#arm/nvidia/drm2/tegra_drm_if.m optional drm2
+#arm/nvidia/drm2/tegra_drm_subr.c optional drm2
+#arm/nvidia/drm2/tegra_host1x.c optional drm2
+#arm/nvidia/drm2/tegra_hdmi.c optional drm2
+#arm/nvidia/drm2/tegra_dc_if.m optional drm2
+#arm/nvidia/drm2/tegra_dc.c optional drm2
+#arm/nvidia/drm2/tegra_fb.c optional drm2
+#arm/nvidia/drm2/tegra_bo.c optional drm2
+#
+# Optional devices.
+#
+
+#
+# Temporary/ to be moved stuff
+#
+arm/nvidia/as3722.c optional iic
+arm/nvidia/as3722_regulators.c optional iic
+arm/nvidia/as3722_rtc.c optional iic
+arm/nvidia/as3722_gpio.c optional iic
diff --git a/sys/arm/nvidia/tegra124/std.tegra124 b/sys/arm/nvidia/tegra124/std.tegra124
new file mode 100644
index 0000000..127b001
--- /dev/null
+++ b/sys/arm/nvidia/tegra124/std.tegra124
@@ -0,0 +1,14 @@
+# $FreeBSD$
+cpu CPU_CORTEXA
+machine arm armv6
+makeoptions CONF_CFLAGS="-march=armv7a"
+
+options KERNVIRTADDR = 0xc0200000
+makeoptions KERNVIRTADDR = 0xc0200000
+
+options ARM_INTRNG
+
+options IPI_IRQ_START=0
+options IPI_IRQ_END=15
+
+files "../nvidia/tegra124/files.tegra124"
diff --git a/sys/arm/nvidia/tegra124/tegra124_car.c b/sys/arm/nvidia/tegra124/tegra124_car.c
new file mode 100644
index 0000000..c0e93c7
--- /dev/null
+++ b/sys/arm/nvidia/tegra124/tegra124_car.c
@@ -0,0 +1,613 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/kobj.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+
+#include <dev/extres/clk/clk_div.h>
+#include <dev/extres/clk/clk_fixed.h>
+#include <dev/extres/clk/clk_gate.h>
+#include <dev/extres/clk/clk_mux.h>
+#include <dev/extres/hwreset/hwreset.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <gnu/dts/include/dt-bindings/clock/tegra124-car.h>
+
+#include "clkdev_if.h"
+#include "hwreset_if.h"
+#include "tegra124_car.h"
+
+static struct ofw_compat_data compat_data[] = {
+ {"nvidia,tegra124-car", 1},
+ {NULL, 0},
+};
+
+#define PLIST(x) static const char *x[]
+
+/* Pure multiplexer. */
+#define MUX(_id, cname, plists, o, s, w) \
+{ \
+ .clkdef.id = _id, \
+ .clkdef.name = cname, \
+ .clkdef.parent_names = plists, \
+ .clkdef.parent_cnt = nitems(plists), \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
+ .offset = o, \
+ .shift = s, \
+ .width = w, \
+}
+
+/* Fractional divider (7.1). */
+#define DIV7_1(_id, cname, plist, o, s) \
+{ \
+ .clkdef.id = _id, \
+ .clkdef.name = cname, \
+ .clkdef.parent_names = (const char *[]){plist}, \
+ .clkdef.parent_cnt = 1, \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
+ .offset = o, \
+ .i_shift = (s) + 1, \
+ .i_width = 7, \
+ .f_shift = s, \
+ .f_width = 1, \
+}
+
+/* Integer divider. */
+#define DIV(_id, cname, plist, o, s, w, f) \
+{ \
+ .clkdef.id = _id, \
+ .clkdef.name = cname, \
+ .clkdef.parent_names = (const char *[]){plist}, \
+ .clkdef.parent_cnt = 1, \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
+ .offset = o, \
+ .i_shift = s, \
+ .i_width = w, \
+ .div_flags = f, \
+}
+
+/* Gate in PLL block. */
+#define GATE_PLL(_id, cname, plist, o, s) \
+{ \
+ .clkdef.id = _id, \
+ .clkdef.name = cname, \
+ .clkdef.parent_names = (const char *[]){plist}, \
+ .clkdef.parent_cnt = 1, \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
+ .offset = o, \
+ .shift = s, \
+ .mask = 3, \
+ .on_value = 3, \
+ .off_value = 0, \
+}
+
+/* Standard gate. */
+#define GATE(_id, cname, plist, o, s) \
+{ \
+ .clkdef.id = _id, \
+ .clkdef.name = cname, \
+ .clkdef.parent_names = (const char *[]){plist}, \
+ .clkdef.parent_cnt = 1, \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
+ .offset = o, \
+ .shift = s, \
+ .mask = 1, \
+ .on_value = 1, \
+ .off_value = 0, \
+}
+
+/* Inverted gate. */
+#define GATE_INV(_id, cname, plist, o, s) \
+{ \
+ .clkdef.id = _id, \
+ .clkdef.name = cname, \
+ .clkdef.parent_names = (const char *[]){plist}, \
+ .clkdef.parent_cnt = 1, \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
+ .offset = o, \
+ .shift = s, \
+ .mask = 1, \
+ .on_value = 0, \
+ .off_value = 1, \
+}
+
+/* Fixed rate clock. */
+#define FRATE(_id, cname, _freq) \
+{ \
+ .clkdef.id = _id, \
+ .clkdef.name = cname, \
+ .clkdef.parent_names = NULL, \
+ .clkdef.parent_cnt = 0, \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
+ .freq = _freq, \
+}
+
+/* Fixed rate multipier/divider. */
+#define FACT(_id, cname, pname, _mult, _div) \
+{ \
+ .clkdef.id = _id, \
+ .clkdef.name = cname, \
+ .clkdef.parent_names = (const char *[]){pname}, \
+ .clkdef.parent_cnt = 1, \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
+ .mult = _mult, \
+ .div = _div, \
+}
+
+static uint32_t osc_freqs[16] = {
+ [0] = 13000000,
+ [1] = 16800000,
+ [4] = 19200000,
+ [5] = 38400000,
+ [8] = 12000000,
+ [9] = 48000000,
+ [12] = 260000000,
+};
+
+
+/* Parent lists. */
+PLIST(mux_pll_srcs) = {"osc_div_clk", NULL, "pllP_out0", NULL}; /* FIXME */
+PLIST(mux_plle_src1) = {"osc_div_clk", "pllP_out0"};
+PLIST(mux_plle_src) = {"pllE_src1", "pllREFE_out"};
+PLIST(mux_plld_out0_plld2_out0) = {"pllD_out0", "pllD2_out0"};
+PLIST(mux_pllmcp_clkm) = {"pllM_out0", "pllC_out0", "pllP_out0", "clk_m",
+ "pllM_UD", "pllC2_out0", "pllC3_out0", "pllC_UD"};
+PLIST(mux_xusb_hs) = {"pc_xusb_ss", "pllU_60"};
+PLIST(mux_xusb_ss) = {"pc_xusb_ss", "osc_div_clk"};
+
+
+/* Clocks ajusted online. */
+static struct clk_fixed_def fixed_clk_m =
+ FRATE(0, "clk_m", 12000000);
+static struct clk_fixed_def fixed_osc_div_clk =
+ FACT(0, "osc_div_clk", "clk_m", 1, 1);
+
+static struct clk_fixed_def tegra124_fixed_clks[] = {
+ /* Core clocks. */
+ FRATE(0, "clk_s", 32768),
+ FACT(0, "clk_m_div2", "clk_m", 1, 2),
+ FACT(0, "clk_m_div4", "clk_m", 1, 3),
+ FACT(0, "pllU_60", "pllU_out", 1, 8),
+ FACT(0, "pllU_48", "pllU_out", 1, 10),
+ FACT(0, "pllU_12", "pllU_out", 1, 40),
+ FACT(TEGRA124_CLK_PLL_D_OUT0, "pllD_out0", "pllD_out", 1, 2),
+ FACT(TEGRA124_CLK_PLL_D2_OUT0, "pllD2_out0", "pllD2_out", 1, 1),
+ FACT(0, "pllX_out0", "pllX_out", 1, 2),
+ FACT(0, "pllC_UD", "pllC_out0", 1, 1),
+ FACT(0, "pllM_UD", "pllM_out0", 1, 1),
+
+ /* Audio clocks. */
+ FRATE(0, "audio0", 10000000),
+ FRATE(0, "audio1", 10000000),
+ FRATE(0, "audio2", 10000000),
+ FRATE(0, "audio3", 10000000),
+ FRATE(0, "audio4", 10000000),
+ FRATE(0, "ext_vimclk", 10000000),
+};
+
+
+static struct clk_mux_def tegra124_mux_clks[] = {
+ /* Core clocks. */
+ MUX(0, "pllD2_src", mux_pll_srcs, PLLD2_BASE, 25, 2),
+ MUX(0, "pllDP_src", mux_pll_srcs, PLLDP_BASE, 25, 2),
+ MUX(0, "pllC4_src", mux_pll_srcs, PLLC4_BASE, 25, 2),
+ MUX(0, "pllE_src1", mux_plle_src1, PLLE_AUX, 2, 1),
+ MUX(0, "pllE_src", mux_plle_src, PLLE_AUX, 28, 1),
+
+ /* Base peripheral clocks. */
+ MUX(0, "dsia_mux", mux_plld_out0_plld2_out0, PLLD_BASE, 25, 1),
+ MUX(0, "dsib_mux", mux_plld_out0_plld2_out0, PLLD2_BASE, 25, 1),
+ MUX(0, "emc_mux", mux_pllmcp_clkm, CLK_SOURCE_EMC, 29, 3),
+
+ /* USB. */
+ MUX(0, "xusb_hs", mux_xusb_hs, CLK_SOURCE_XUSB_SS, 25, 1),
+ MUX(0, "xusb_ss_mux", mux_xusb_ss, CLK_SOURCE_XUSB_SS, 24, 1),
+
+};
+
+
+static struct clk_gate_def tegra124_gate_clks[] = {
+ /* Core clocks. */
+ GATE_PLL(0, "pllC_out1", "pllC_out1_div", PLLC_OUT, 0),
+ GATE_PLL(0, "pllM_out1", "pllM_out1_div", PLLM_OUT, 0),
+ GATE_PLL(0, "pllU_480", "pllU_out", PLLU_BASE, 22),
+ GATE_PLL(0, "pllP_outX0", "pllP_outX0_div", PLLP_RESHIFT, 0),
+ GATE_PLL(0, "pllP_out1", "pllP_out1_div", PLLP_OUTA, 0),
+ GATE_PLL(0, "pllP_out2", "pllP_out2_div", PLLP_OUTA, 16),
+ GATE_PLL(0, "pllP_out3", "pllP_out3_div", PLLP_OUTB, 0),
+ GATE_PLL(0, "pllP_out4", "pllP_out4_div", PLLP_OUTB, 16),
+ GATE_PLL(0, "pllP_out5", "pllP_out5_div", PLLP_OUTC, 16),
+ GATE_PLL(0, "pllA_out0", "pllA_out1_div", PLLA_OUT, 0),
+
+ /* Base peripheral clocks. */
+ GATE(TEGRA124_CLK_CML0, "cml0", "pllE_out0", PLLE_AUX, 0),
+ GATE(TEGRA124_CLK_CML1, "cml1", "pllE_out0", PLLE_AUX, 1),
+ GATE_INV(TEGRA124_CLK_HCLK, "hclk", "hclk_div", CLK_SYSTEM_RATE, 7),
+ GATE_INV(TEGRA124_CLK_PCLK, "pclk", "pclk_div", CLK_SYSTEM_RATE, 3),
+};
+
+static struct clk_div_def tegra124_div_clks[] = {
+ /* Core clocks. */
+ DIV7_1(0, "pllC_out1_div", "pllC_out0", PLLC_OUT, 2),
+ DIV7_1(0, "pllM_out1_div", "pllM_out0", PLLM_OUT, 8),
+ DIV7_1(0, "pllP_outX0_div", "pllP_out0", PLLP_RESHIFT, 2),
+ DIV7_1(0, "pllP_out1_div", "pllP_out0", PLLP_OUTA, 8),
+ DIV7_1(0, "pllP_out2_div", "pllP_out0", PLLP_OUTA, 24),
+ DIV7_1(0, "pllP_out3_div", "pllP_out0", PLLP_OUTB, 8),
+ DIV7_1(0, "pllP_out4_div", "pllP_out0", PLLP_OUTB, 24),
+ DIV7_1(0, "pllP_out5_div", "pllP_out0", PLLP_OUTC, 24),
+ DIV7_1(0, "pllA_out1_div", "pllA_out", PLLA_OUT, 8),
+
+ /* Base peripheral clocks. */
+ DIV(0, "hclk_div", "sclk", CLK_SYSTEM_RATE, 4, 2, 0),
+ DIV(0, "pclk_div", "hclk", CLK_SYSTEM_RATE, 0, 2, 0),
+};
+
+/* Initial setup table. */
+static struct tegra124_init_item clk_init_table[] = {
+ /* clock, partent, frequency, enable */
+ {"uarta", "pllP_out0", 408000000, 0},
+ {"uartb", "pllP_out0", 408000000, 0},
+ {"uartc", "pllP_out0", 408000000, 0},
+ {"uartd", "pllP_out0", 408000000, 0},
+ {"pllA_out", NULL, 282240000, 1},
+ {"pllA_out0", NULL, 11289600, 1},
+ {"extperiph1", "pllA_out0", 0, 1},
+ {"i2s0", "pllA_out0", 11289600, 0},
+ {"i2s1", "pllA_out0", 11289600, 0},
+ {"i2s2", "pllA_out0", 11289600, 0},
+ {"i2s3", "pllA_out0", 11289600, 0},
+ {"i2s4", "pllA_out0", 11289600, 0},
+ {"vde", "pllP_out0", 0, 0},
+ {"host1x", "pllP_out0", 136000000, 1},
+ {"sclk", "pllP_out2", 102000000, 1},
+ {"dvfs_soc", "pllP_out0", 51000000, 1},
+ {"dvfs_ref", "pllP_out0", 51000000, 1},
+ {"pllC_out0", NULL, 600000000, 0},
+ {"pllC_out1", NULL, 100000000, 0},
+ {"spi4", "pllP_out0", 12000000, 1},
+ {"tsec", "pllC3_out0", 0, 0},
+ {"msenc", "pllC3_out0", 0, 0},
+ {"pllREFE_out", NULL, 672000000, 0},
+ {"pc_xusb_ss", "pllU_480", 120000000, 0},
+ {"xusb_ss", "pc_xusb_ss", 120000000, 0},
+ {"pc_xusb_fs", "pllU_48", 48000000, 0},
+ {"xusb_hs", "pllU_60", 60000000, 0},
+ {"pc_xusb_falcon", "pllREFE_out", 224000000, 0},
+ {"xusb_core_host", "pllREFE_out", 112000000, 0},
+ {"sata", "pllP_out0", 102000000, 0},
+ {"sata_oob", "pllP_out0", 204000000, 0},
+ {"sata_cold", NULL, 0, 1},
+ {"emc", NULL, 0, 1},
+ {"mselect", NULL, 0, 1},
+ {"csite", NULL, 0, 1},
+ {"tsensor", "clk_m", 400000, 0},
+
+ /* tegra124 only*/
+ {"soc_therm", "pllP_out0", 51000000, 0},
+ {"cclk_g", NULL, 0, 1},
+ {"hda", "pllP_out0", 102000000, 0},
+ {"hda2codec_2x", "pllP_out0", 48000000, 0},
+};
+
+static void
+init_divs(struct tegra124_car_softc *sc, struct clk_div_def *clks, int nclks)
+{
+ int i, rv;
+
+ for (i = 0; i < nclks; i++) {
+ rv = clknode_div_register(sc->clkdom, clks + i);
+ if (rv != 0)
+ panic("clk_div_register failed");
+ }
+}
+
+static void
+init_gates(struct tegra124_car_softc *sc, struct clk_gate_def *clks, int nclks)
+{
+ int i, rv;
+
+
+ for (i = 0; i < nclks; i++) {
+ rv = clknode_gate_register(sc->clkdom, clks + i);
+ if (rv != 0)
+ panic("clk_gate_register failed");
+ }
+}
+
+static void
+init_muxes(struct tegra124_car_softc *sc, struct clk_mux_def *clks, int nclks)
+{
+ int i, rv;
+
+
+ for (i = 0; i < nclks; i++) {
+ rv = clknode_mux_register(sc->clkdom, clks + i);
+ if (rv != 0)
+ panic("clk_mux_register failed");
+ }
+}
+
+static void
+init_fixeds(struct tegra124_car_softc *sc, struct clk_fixed_def *clks,
+ int nclks)
+{
+ int i, rv;
+ uint32_t val;
+ int osc_idx;
+
+ CLKDEV_READ_4(sc->dev, OSC_CTRL, &val);
+ osc_idx = val >> OSC_CTRL_OSC_FREQ_SHIFT;
+ fixed_clk_m.freq = osc_freqs[osc_idx];
+ if (fixed_clk_m.freq == 0)
+ panic("Undefined input frequency");
+ rv = clknode_fixed_register(sc->clkdom, &fixed_clk_m);
+ if (rv != 0) panic("clk_fixed_register failed");
+
+ val = (val >> OSC_CTRL_PLL_REF_DIV_SHIFT) & 3;
+ fixed_osc_div_clk.div = 1 << val;
+ rv = clknode_fixed_register(sc->clkdom, &fixed_osc_div_clk);
+ if (rv != 0) panic("clk_fixed_register failed");
+
+ for (i = 0; i < nclks; i++) {
+ rv = clknode_fixed_register(sc->clkdom, clks + i);
+ if (rv != 0)
+ panic("clk_fixed_register failed");
+ }
+}
+
+static void
+postinit_clock(struct tegra124_car_softc *sc)
+{
+ int i;
+ struct tegra124_init_item *tbl;
+ struct clknode *clknode;
+ int rv;
+
+ for (i = 0; i < nitems(clk_init_table); i++) {
+ tbl = &clk_init_table[i];
+
+ clknode = clknode_find_by_name(tbl->name);
+ if (clknode == NULL) {
+ device_printf(sc->dev, "Cannot find clock %s\n",
+ tbl->name);
+ continue;
+ }
+ if (tbl->parent != NULL) {
+ rv = clknode_set_parent_by_name(clknode, tbl->parent);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot set parent for %s (to %s): %d\n",
+ tbl->name, tbl->parent, rv);
+ continue;
+ }
+ }
+ if (tbl->frequency != 0) {
+ rv = clknode_set_freq(clknode, tbl->frequency, 0 , 9999);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot set frequency for %s: %d\n",
+ tbl->name, rv);
+ continue;
+ }
+ }
+ if (tbl->enable!= 0) {
+ rv = clknode_enable(clknode);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot enable %s: %d\n", tbl->name, rv);
+ continue;
+ }
+ }
+ }
+}
+
+static void
+register_clocks(device_t dev)
+{
+ struct tegra124_car_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->clkdom = clkdom_create(dev);
+ if (sc->clkdom == NULL)
+ panic("clkdom == NULL");
+
+ tegra124_init_plls(sc);
+ init_fixeds(sc, tegra124_fixed_clks, nitems(tegra124_fixed_clks));
+ init_muxes(sc, tegra124_mux_clks, nitems(tegra124_mux_clks));
+ init_divs(sc, tegra124_div_clks, nitems(tegra124_div_clks));
+ init_gates(sc, tegra124_gate_clks, nitems(tegra124_gate_clks));
+ tegra124_periph_clock(sc);
+ tegra124_super_mux_clock(sc);
+ clkdom_finit(sc->clkdom);
+ clkdom_xlock(sc->clkdom);
+ postinit_clock(sc);
+ clkdom_unlock(sc->clkdom);
+ if (bootverbose)
+ clkdom_dump(sc->clkdom);
+}
+
+static int
+tegra124_car_clkdev_read_4(device_t dev, bus_addr_t addr, uint32_t *val)
+{
+ struct tegra124_car_softc *sc;
+
+ sc = device_get_softc(dev);
+ *val = bus_read_4(sc->mem_res, addr);
+ return (0);
+}
+
+static int
+tegra124_car_clkdev_write_4(device_t dev, bus_addr_t addr, uint32_t val)
+{
+ struct tegra124_car_softc *sc;
+
+ sc = device_get_softc(dev);
+ bus_write_4(sc->mem_res, addr, val);
+ return (0);
+}
+
+static int
+tegra124_car_clkdev_modify_4(device_t dev, bus_addr_t addr, uint32_t clear_mask,
+ uint32_t set_mask)
+{
+ struct tegra124_car_softc *sc;
+ uint32_t reg;
+
+ sc = device_get_softc(dev);
+ reg = bus_read_4(sc->mem_res, addr);
+ reg &= ~clear_mask;
+ reg |= set_mask;
+ bus_write_4(sc->mem_res, addr, reg);
+ return (0);
+}
+
+static void
+tegra124_car_clkdev_device_lock(device_t dev)
+{
+ struct tegra124_car_softc *sc;
+
+ sc = device_get_softc(dev);
+ mtx_lock(&sc->mtx);
+}
+
+static void
+tegra124_car_clkdev_device_unlock(device_t dev)
+{
+ struct tegra124_car_softc *sc;
+
+ sc = device_get_softc(dev);
+ mtx_unlock(&sc->mtx);
+}
+
+static int
+tegra124_car_detach(device_t dev)
+{
+
+ device_printf(dev, "Error: Clock driver cannot be detached\n");
+ return (EBUSY);
+}
+
+static int
+tegra124_car_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) {
+ device_set_desc(dev, "Tegra Clock Driver");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+tegra124_car_attach(device_t dev)
+{
+ struct tegra124_car_softc *sc = device_get_softc(dev);
+ int rid, rv;
+
+ sc->dev = dev;
+
+ mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+ sc->type = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
+
+ /* Resource setup. */
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (!sc->mem_res) {
+ device_printf(dev, "cannot allocate memory resource\n");
+ rv = ENXIO;
+ goto fail;
+ }
+
+ register_clocks(dev);
+ hwreset_register_ofw_provider(dev);
+ return (0);
+
+fail:
+ if (sc->mem_res)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
+
+ return (rv);
+}
+
+static int
+tegra124_car_hwreset_assert(device_t dev, intptr_t id, bool value)
+{
+ struct tegra124_car_softc *sc = device_get_softc(dev);
+
+ return (tegra124_hwreset_by_idx(sc, id, value));
+}
+
+static device_method_t tegra124_car_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, tegra124_car_probe),
+ DEVMETHOD(device_attach, tegra124_car_attach),
+ DEVMETHOD(device_detach, tegra124_car_detach),
+
+ /* Clkdev interface*/
+ DEVMETHOD(clkdev_read_4, tegra124_car_clkdev_read_4),
+ DEVMETHOD(clkdev_write_4, tegra124_car_clkdev_write_4),
+ DEVMETHOD(clkdev_modify_4, tegra124_car_clkdev_modify_4),
+ DEVMETHOD(clkdev_device_lock, tegra124_car_clkdev_device_lock),
+ DEVMETHOD(clkdev_device_unlock, tegra124_car_clkdev_device_unlock),
+
+ /* Reset interface */
+ DEVMETHOD(hwreset_assert, tegra124_car_hwreset_assert),
+
+ DEVMETHOD_END
+};
+
+static devclass_t tegra124_car_devclass;
+
+static driver_t tegra124_car_driver = {
+ "tegra124_car",
+ tegra124_car_methods,
+ sizeof(struct tegra124_car_softc),
+};
+
+EARLY_DRIVER_MODULE(tegra124_car, simplebus, tegra124_car_driver,
+ tegra124_car_devclass, 0, 0, BUS_PASS_TIMER);
diff --git a/sys/arm/nvidia/tegra124/tegra124_car.h b/sys/arm/nvidia/tegra124/tegra124_car.h
new file mode 100644
index 0000000..b11742c
--- /dev/null
+++ b/sys/arm/nvidia/tegra124/tegra124_car.h
@@ -0,0 +1,337 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _TEGRA124_CAR_
+#define _TEGRA124_CAR_
+
+#include "clkdev_if.h"
+
+#define RD4(sc, reg, val) CLKDEV_READ_4((sc)->clkdev, reg, val)
+#define WR4(sc, reg, val) CLKDEV_WRITE_4((sc)->clkdev, reg, val)
+#define MD4(sc, reg, mask, set) CLKDEV_MODIFY_4((sc)->clkdev, reg, mask, set)
+#define DEVICE_LOCK(sc) CLKDEV_DEVICE_LOCK((sc)->clkdev)
+#define DEVICE_UNLOCK(sc) CLKDEV_DEVICE_UNLOCK((sc)->clkdev)
+
+#define RST_DEVICES_L 0x004
+#define RST_DEVICES_H 0x008
+#define RST_DEVICES_U 0x00C
+#define CLK_OUT_ENB_L 0x010
+#define CLK_OUT_ENB_H 0x014
+#define CLK_OUT_ENB_U 0x018
+#define CCLK_BURST_POLICY 0x020
+#define SUPER_CCLK_DIVIDER 0x024
+#define SCLK_BURST_POLICY 0x028
+#define SUPER_SCLK_DIVIDER 0x02c
+#define CLK_SYSTEM_RATE 0x030
+
+#define OSC_CTRL 0x050
+ #define OSC_CTRL_OSC_FREQ_SHIFT 28
+ #define OSC_CTRL_PLL_REF_DIV_SHIFT 26
+
+#define PLLE_SS_CNTL 0x068
+#define PLLE_SS_CNTL_SSCINCINTRV_MASK (0x3f << 24)
+#define PLLE_SS_CNTL_SSCINCINTRV_VAL (0x20 << 24)
+#define PLLE_SS_CNTL_SSCINC_MASK (0xff << 16)
+#define PLLE_SS_CNTL_SSCINC_VAL (0x1 << 16)
+#define PLLE_SS_CNTL_SSCINVERT (1 << 15)
+#define PLLE_SS_CNTL_SSCCENTER (1 << 14)
+#define PLLE_SS_CNTL_SSCBYP (1 << 12)
+#define PLLE_SS_CNTL_INTERP_RESET (1 << 11)
+#define PLLE_SS_CNTL_BYPASS_SS (1 << 10)
+#define PLLE_SS_CNTL_SSCMAX_MASK 0x1ff
+#define PLLE_SS_CNTL_SSCMAX_VAL 0x25
+#define PLLE_SS_CNTL_DISABLE (PLLE_SS_CNTL_BYPASS_SS | \
+ PLLE_SS_CNTL_INTERP_RESET | \
+ PLLE_SS_CNTL_SSCBYP)
+#define PLLE_SS_CNTL_COEFFICIENTS_MASK (PLLE_SS_CNTL_SSCMAX_MASK | \
+ PLLE_SS_CNTL_SSCINC_MASK | \
+ PLLE_SS_CNTL_SSCINCINTRV_MASK)
+#define PLLE_SS_CNTL_COEFFICIENTS_VAL (PLLE_SS_CNTL_SSCMAX_VAL | \
+ PLLE_SS_CNTL_SSCINC_VAL | \
+ PLLE_SS_CNTL_SSCINCINTRV_VAL)
+
+#define PLLC_BASE 0x080
+#define PLLC_OUT 0x084
+#define PLLC_MISC2 0x088
+#define PLLC_MISC 0x08c
+#define PLLM_BASE 0x090
+#define PLLM_OUT 0x094
+#define PLLM_MISC 0x09c
+#define PLLP_BASE 0x0a0
+#define PLLP_MISC 0x0ac
+#define PLLP_OUTA 0x0a4
+#define PLLP_OUTB 0x0a8
+#define PLLA_BASE 0x0b0
+#define PLLA_OUT 0x0b4
+#define PLLA_MISC 0x0bc
+#define PLLU_BASE 0x0c0
+#define PLLU_MISC 0x0cc
+#define PLLD_BASE 0x0d0
+#define PLLD_MISC 0x0dc
+#define PLLX_BASE 0x0e0
+#define PLLX_MISC 0x0e4
+#define PLLE_BASE 0x0e8
+#define PLLE_BASE_LOCK_OVERRIDE (1 << 29)
+#define PLLE_BASE_DIVCML_SHIFT 24
+#define PLLE_BASE_DIVCML_MASK 0xf
+
+#define PLLE_MISC 0x0ec
+#define PLLE_MISC_SETUP_BASE_SHIFT 16
+#define PLLE_MISC_SETUP_BASE_MASK (0xffff << PLLE_MISC_SETUP_BASE_SHIFT)
+#define PLLE_MISC_READY (1 << 15)
+#define PLLE_MISC_IDDQ_SWCTL (1 << 14)
+#define PLLE_MISC_IDDQ_OVERRIDE_VALUE (1 << 13)
+#define PLLE_MISC_LOCK (1 << 11)
+#define PLLE_MISC_REF_ENABLE (1 << 10)
+#define PLLE_MISC_LOCK_ENABLE (1 << 9)
+#define PLLE_MISC_PTS (1 << 8)
+#define PLLE_MISC_VREG_BG_CTRL_SHIFT 4
+#define PLLE_MISC_VREG_BG_CTRL_MASK (3 << PLLE_MISC_VREG_BG_CTRL_SHIFT)
+#define PLLE_MISC_VREG_CTRL_SHIFT 2
+#define PLLE_MISC_VREG_CTRL_MASK (2 << PLLE_MISC_VREG_CTRL_SHIFT)
+
+#define CLK_SOURCE_I2S1 0x100
+#define CLK_SOURCE_I2S2 0x104
+#define CLK_SOURCE_SPDIF_OUT 0x108
+#define CLK_SOURCE_SPDIF_IN 0x10c
+#define CLK_SOURCE_PWM 0x110
+#define CLK_SOURCE_SPI2 0x118
+#define CLK_SOURCE_SPI3 0x11c
+#define CLK_SOURCE_I2C1 0x124
+#define CLK_SOURCE_I2C5 0x128
+#define CLK_SOURCE_SPI1 0x134
+#define CLK_SOURCE_DISP1 0x138
+#define CLK_SOURCE_DISP2 0x13c
+#define CLK_SOURCE_ISP 0x144
+#define CLK_SOURCE_VI 0x148
+#define CLK_SOURCE_SDMMC1 0x150
+#define CLK_SOURCE_SDMMC2 0x154
+#define CLK_SOURCE_SDMMC4 0x164
+#define CLK_SOURCE_VFIR 0x168
+#define CLK_SOURCE_HSI 0x174
+#define CLK_SOURCE_UARTA 0x178
+#define CLK_SOURCE_UARTB 0x17c
+#define CLK_SOURCE_HOST1X 0x180
+#define CLK_SOURCE_HDMI 0x18c
+#define CLK_SOURCE_I2C2 0x198
+#define CLK_SOURCE_EMC 0x19c
+#define CLK_SOURCE_UARTC 0x1a0
+#define CLK_SOURCE_VI_SENSOR 0x1a8
+#define CLK_SOURCE_SPI4 0x1b4
+#define CLK_SOURCE_I2C3 0x1b8
+#define CLK_SOURCE_SDMMC3 0x1bc
+#define CLK_SOURCE_UARTD 0x1c0
+#define CLK_SOURCE_VDE 0x1c8
+#define CLK_SOURCE_OWR 0x1cc
+#define CLK_SOURCE_NOR 0x1d0
+#define CLK_SOURCE_CSITE 0x1d4
+#define CLK_SOURCE_I2S0 0x1d8
+#define CLK_SOURCE_DTV 0x1dc
+#define CLK_SOURCE_MSENC 0x1f0
+#define CLK_SOURCE_TSEC 0x1f4
+#define CLK_SOURCE_SPARE2 0x1f8
+
+#define CLK_OUT_ENB_X 0x280
+#define RST_DEVICES_X 0x28C
+
+#define RST_DEVICES_V 0x358
+#define RST_DEVICES_W 0x35C
+#define CLK_OUT_ENB_V 0x360
+#define CLK_OUT_ENB_W 0x364
+#define CCLKG_BURST_POLICY 0x368
+#define SUPER_CCLKG_DIVIDER 0x36C
+#define CCLKLP_BURST_POLICY 0x370
+#define SUPER_CCLKLP_DIVIDER 0x374
+
+#define CLK_SOURCE_MSELECT 0x3b4
+#define CLK_SOURCE_TSENSOR 0x3b8
+#define CLK_SOURCE_I2S3 0x3bc
+#define CLK_SOURCE_I2S4 0x3c0
+#define CLK_SOURCE_I2C4 0x3c4
+#define CLK_SOURCE_SPI5 0x3c8
+#define CLK_SOURCE_SPI6 0x3cc
+#define CLK_SOURCE_AUDIO 0x3d0
+#define CLK_SOURCE_DAM0 0x3d8
+#define CLK_SOURCE_DAM1 0x3dc
+#define CLK_SOURCE_DAM2 0x3e0
+#define CLK_SOURCE_HDA2CODEC_2X 0x3e4
+#define CLK_SOURCE_ACTMON 0x3e8
+#define CLK_SOURCE_EXTPERIPH1 0x3ec
+#define CLK_SOURCE_EXTPERIPH2 0x3f0
+#define CLK_SOURCE_EXTPERIPH3 0x3f4
+#define CLK_SOURCE_I2C_SLOW 0x3fc
+
+#define CLK_SOURCE_SYS 0x400
+#define CLK_SOURCE_SOR0 0x414
+#define CLK_SOURCE_SATA_OOB 0x420
+#define CLK_SOURCE_SATA 0x424
+#define CLK_SOURCE_HDA 0x428
+#define UTMIP_PLL_CFG0 0x480
+#define UTMIP_PLL_CFG1 0x484
+#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP (1 << 17)
+#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN (1 << 16)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP (1 << 15)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN (1 << 14)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN (1 << 12)
+#define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 6)
+#define UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0)
+
+#define UTMIP_PLL_CFG2 0x488
+#define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x) (((x) & 0x3f) << 18)
+#define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xffff) << 6)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN (1 << 4)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN (1 << 2)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN (1 << 0)
+
+#define PLLE_AUX 0x48c
+#define PLLE_AUX_PLLRE_SEL (1 << 28)
+#define PLLE_AUX_SEQ_START_STATE (1 << 25)
+#define PLLE_AUX_SEQ_ENABLE (1 << 24)
+#define PLLE_AUX_SS_SWCTL (1 << 6)
+#define PLLE_AUX_ENABLE_SWCTL (1 << 4)
+#define PLLE_AUX_USE_LOCKDET (1 << 3)
+#define PLLE_AUX_PLLP_SEL (1 << 2)
+
+#define SATA_PLL_CFG0 0x490
+#define SATA_PLL_CFG0_SEQ_START_STATE (1 << 25)
+#define SATA_PLL_CFG0_SEQ_ENABLE (1 << 24)
+#define SATA_PLL_CFG0_SEQ_PADPLL_PD_INPUT_VALUE (1 << 7)
+#define SATA_PLL_CFG0_SEQ_LANE_PD_INPUT_VALUE (1 << 6)
+#define SATA_PLL_CFG0_SEQ_RESET_INPUT_VALUE (1 << 5)
+#define SATA_PLL_CFG0_SEQ_IN_SWCTL (1 << 4)
+#define SATA_PLL_CFG0_PADPLL_USE_LOCKDET (1 << 2)
+#define SATA_PLL_CFG0_PADPLL_RESET_OVERRIDE_VALUE (1 << 1)
+#define SATA_PLL_CFG0_PADPLL_RESET_SWCTL (1 << 0)
+
+#define SATA_PLL_CFG1 0x494
+#define PCIE_PLL_CFG0 0x498
+#define PCIE_PLL_CFG0_SEQ_START_STATE (1 << 25)
+#define PCIE_PLL_CFG0_SEQ_ENABLE (1 << 24)
+
+#define PLLD2_BASE 0x4b8
+#define PLLD2_MISC 0x4bc
+#define UTMIP_PLL_CFG3 0x4c0
+#define PLLRE_BASE 0x4c4
+#define PLLRE_MISC 0x4c8
+#define PLLC2_BASE 0x4e8
+#define PLLC2_MISC 0x4ec
+#define PLLC3_BASE 0x4fc
+
+#define PLLC3_MISC 0x500
+#define PLLX_MISC2 0x514
+#define PLLX_MISC2 0x514
+#define PLLX_MISC3 0x518
+#define PLLX_MISC3_DYNRAMP_STEPB_MASK 0xFF
+#define PLLX_MISC3_DYNRAMP_STEPB_SHIFT 24
+#define PLLX_MISC3_DYNRAMP_STEPA_MASK 0xFF
+#define PLLX_MISC3_DYNRAMP_STEPA_SHIFT 16
+#define PLLX_MISC3_NDIV_NEW_MASK 0xFF
+#define PLLX_MISC3_NDIV_NEW_SHIFT 8
+#define PLLX_MISC3_EN_FSTLCK (1 << 5)
+#define PLLX_MISC3_LOCK_OVERRIDE (1 << 4)
+#define PLLX_MISC3_PLL_FREQLOCK (1 << 3)
+#define PLLX_MISC3_DYNRAMP_DONE (1 << 2)
+#define PLLX_MISC3_CLAMP_NDIV (1 << 1)
+#define PLLX_MISC3_EN_DYNRAMP (1 << 0)
+#define XUSBIO_PLL_CFG0 0x51c
+#define XUSBIO_PLL_CFG0_SEQ_START_STATE (1 << 25)
+#define XUSBIO_PLL_CFG0_SEQ_ENABLE (1 << 24)
+#define XUSBIO_PLL_CFG0_PADPLL_USE_LOCKDET (1 << 6)
+#define XUSBIO_PLL_CFG0_CLK_ENABLE_SWCTL (1 << 2)
+#define XUSBIO_PLL_CFG0_PADPLL_RESET_SWCTL (1 << 0)
+
+#define PLLP_RESHIFT 0x528
+#define UTMIPLL_HW_PWRDN_CFG0 0x52c
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE (1 << 25)
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE (1 << 24)
+#define UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET (1 << 6)
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_RESET_INPUT_VALUE (1 << 5)
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_IN_SWCTL (1 << 4)
+#define UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL (1 << 2)
+#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE (1 << 1)
+#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL (1 << 0)
+
+#define PLLDP_BASE 0x590
+#define PLLDP_MISC 0x594
+#define PLLC4_BASE 0x5a4
+#define PLLC4_MISC 0x5a8
+
+#define CLK_SOURCE_XUSB_CORE_HOST 0x600
+#define CLK_SOURCE_XUSB_FALCON 0x604
+#define CLK_SOURCE_XUSB_FS 0x608
+#define CLK_SOURCE_XUSB_CORE_DEV 0x60c
+#define CLK_SOURCE_XUSB_SS 0x610
+#define CLK_SOURCE_CILAB 0x614
+#define CLK_SOURCE_CILCD 0x618
+#define CLK_SOURCE_CILE 0x61c
+#define CLK_SOURCE_DSIA_LP 0x620
+#define CLK_SOURCE_DSIB_LP 0x624
+#define CLK_SOURCE_ENTROPY 0x628
+#define CLK_SOURCE_DVFS_REF 0x62c
+#define CLK_SOURCE_DVFS_SOC 0x630
+#define CLK_SOURCE_TRACECLKIN 0x634
+#define CLK_SOURCE_ADX 0x638
+#define CLK_SOURCE_AMX 0x63c
+#define CLK_SOURCE_EMC_LATENCY 0x640
+#define CLK_SOURCE_SOC_THERM 0x644
+#define CLK_SOURCE_VI_SENSOR2 0x658
+#define CLK_SOURCE_I2C6 0x65c
+#define CLK_SOURCE_EMC_DLL 0x664
+#define CLK_SOURCE_HDMI_AUDIO 0x668
+#define CLK_SOURCE_CLK72MHZ 0x66c
+#define CLK_SOURCE_ADX1 0x670
+#define CLK_SOURCE_AMX1 0x674
+#define CLK_SOURCE_VIC 0x678
+#define PLLP_OUTC 0x67c
+#define PLLP_MISC1 0x680
+
+
+struct tegra124_car_softc {
+ device_t dev;
+ struct resource * mem_res;
+ struct mtx mtx;
+ struct clkdom *clkdom;
+ int type;
+};
+
+struct tegra124_init_item {
+ char *name;
+ char *parent;
+ uint64_t frequency;
+ int enable;
+};
+
+void tegra124_init_plls(struct tegra124_car_softc *sc);
+
+void tegra124_periph_clock(struct tegra124_car_softc *sc);
+void tegra124_super_mux_clock(struct tegra124_car_softc *sc);
+
+int tegra124_hwreset_by_idx(struct tegra124_car_softc *sc, intptr_t idx,
+ bool reset);
+
+#endif /*_TEGRA124_CAR_*/ \ No newline at end of file
diff --git a/sys/arm/nvidia/tegra124/tegra124_clk_per.c b/sys/arm/nvidia/tegra124/tegra124_clk_per.c
new file mode 100644
index 0000000..65ae5d9
--- /dev/null
+++ b/sys/arm/nvidia/tegra124/tegra124_clk_per.c
@@ -0,0 +1,810 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+
+#include <dev/extres/clk/clk.h>
+
+#include <gnu/dts/include/dt-bindings/clock/tegra124-car.h>
+#include "tegra124_car.h"
+
+/* Bits in base register. */
+#define PERLCK_AMUX_MASK 0x0F
+#define PERLCK_AMUX_SHIFT 16
+#define PERLCK_AMUX_DIS (1 << 20)
+#define PERLCK_UDIV_DIS (1 << 24)
+#define PERLCK_ENA_MASK (1 << 28)
+#define PERLCK_MUX_SHIFT 29
+#define PERLCK_MUX_MASK 0x07
+
+
+struct periph_def {
+ struct clknode_init_def clkdef;
+ uint32_t base_reg;
+ uint32_t div_width;
+ uint32_t div_mask;
+ uint32_t div_f_width;
+ uint32_t div_f_mask;
+ uint32_t flags;
+};
+
+struct pgate_def {
+ struct clknode_init_def clkdef;
+ uint32_t idx;
+ uint32_t flags;
+};
+#define PLIST(x) static const char *x[]
+
+#define GATE(_id, cname, plist, _idx) \
+{ \
+ .clkdef.id = TEGRA124_CLK_##_id, \
+ .clkdef.name = cname, \
+ .clkdef.parent_names = (const char *[]){plist}, \
+ .clkdef.parent_cnt = 1, \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
+ .idx = _idx, \
+ .flags = 0, \
+}
+
+/* Sources for multiplexors. */
+PLIST(mux_a_N_audio_N_p_N_clkm) =
+ {"pllA_out0", NULL, "audio", NULL,
+ "pllP_out0", NULL, "clk_m"};
+PLIST(mux_a_N_audio0_N_p_N_clkm) =
+ {"pllA_out0", NULL, "audio0", NULL,
+ "pllP_out0", NULL, "clk_m"};
+PLIST(mux_a_N_audio1_N_p_N_clkm) =
+ {"pllA_out0", NULL, "audio1", NULL,
+ "pllP_out0", NULL, "clk_m"};
+PLIST(mux_a_N_audio2_N_p_N_clkm) =
+ {"pllA_out0", NULL, "audio2", NULL,
+ "pllP_out0", NULL, "clk_m"};
+PLIST(mux_a_N_audio3_N_p_N_clkm) =
+ {"pllA_out0", NULL, "audio3", NULL,
+ "pllP_out0", NULL, "clk_m"};
+PLIST(mux_a_N_audio4_N_p_N_clkm) =
+ {"pllA_out0", NULL, "audio4", NULL,
+ "pllP_out0", NULL, "clk_m"};
+PLIST(mux_a_clks_p_clkm_e) =
+ {"pllA_out0", "clk_s", "pllP_out0",
+ "clk_m", "pllE_out0"};
+PLIST(mux_a_c2_c_c3_p_N_clkm) =
+ {"pllA_out0", "pllC2_out0", "pllC_out0", "pllC3_out0",
+ "pllP_out0", NULL, "clk_m"};
+
+PLIST(mux_m_c_p_a_c2_c3) =
+ {"pllM_out0", "pllC_out0", "pllP_out0", "pllA_out0",
+ "pllC2_out0", "pllC3_out0"};
+PLIST(mux_m_c_p_a_c2_c3_clkm) =
+ {"pllM_out0", "pllC_out0", "pllP_out0", "pllA_out0",
+ "pllC2_out0", "pllC3_out0", "clk_m"};
+PLIST(mux_m_c_p_a_c2_c3_clkm_c4) =
+ {"pllM_out0", "pllC_out0", "pllP_out0", "pllA_out0",
+ "pllC2_out0", "pllC3_out0", "clk_m", "pllC4_out0"};
+PLIST(mux_m_c_p_clkm_mud_c2_c3) =
+ {"pllM_out0", "pllC_out0", "pllP_out0", "clk_m",
+ "pllM_UD", "pllC2_out0", "pllC3_out0"};
+PLIST(mux_m_c2_c_c3_p_N_a) =
+ {"pllM_out0", "pllC2_out0", "pllC_out0", "pllC3_out0",
+ "pllP_out0", NULL, "pllA_out0"};
+PLIST(mux_m_c2_c_c3_p_N_a_c4) =
+ {"pllM_out0", "pllC2_out0", "pllC_out0", "pllC3_out0",
+ NULL, "pllA_out0", "pllC4_out0"};
+
+PLIST(mux_p_N_c_N_N_N_clkm) =
+ {"pllP_out0", NULL, "pllC_out0", NULL,
+ NULL, NULL, "clk_m"};
+PLIST(mux_p_N_c_N_m_N_clkm) =
+ {"pllP_out0", NULL, "pllC_out0", NULL,
+ "pllM_out0", NULL, "clk_m"};
+PLIST(mux_p_c_c2_clkm) =
+ {"pllP_out0", "pllC_out0", "pllC2_out0", "clk_m"};
+PLIST(mux_p_c2_c_c3_m) =
+ {"pllP_out0", "pllC2_out0", "pllC_out0", "pllC3_out0",
+ "pllM_out0"};
+PLIST(mux_p_c2_c_c3_m_N_clkm) =
+ {"pllP_out0", "pllC2_out0", "pllC_out0", "pllC3_out0",
+ "pllM_out0", NULL, "clk_m"};
+PLIST(mux_p_c2_c_c3_m_e_clkm) =
+ {"pllP_out0", "pllC2_out0", "pllC_out0", "pllC3_out0",
+ "pllM_out0", "pllE_out0", "clk_m"};
+PLIST(mux_p_c2_c_c3_m_a_clkm) =
+ {"pllP_out0", "pllC2_out0", "pllC_out0", "pllC3_out0",
+ "pllM_out0", "pllA_out0", "clk_m"};
+PLIST(mux_p_c2_c_c3_m_clks_clkm) =
+ {"pllP_out0", "pllC2_out0", "pllC_out0", "pllC3_out0",
+ "pllM_out0", "clk_s", "clk_m"};
+PLIST(mux_p_c2_c_c3_clks_N_clkm) =
+ {"pllP_out0", "pllC2_out0", "pllC_out0", "pllC3_out0",
+ "clk_s", NULL, "clk_m"};
+PLIST(mux_p_c2_c_c3_clkm_N_clks) =
+ {"pllP_out0", "pllC2_out0", "pllC_out0", "pllC3_out0",
+ "clk_m", NULL, "clk_s"};
+PLIST(mux_p_clkm_clks_E) =
+ {"pllP_out0", "clk_m", "clk_s", "pllE_out0"};
+PLIST(mux_p_m_d_a_c_d2_clkm) =
+ {"pllP_out0", "pllM_out0", "pllD_out0", "pllA_out0",
+ "pllC_out0", "pllD2_out0", "clk_m"};
+
+PLIST(mux_clkm_N_u48_N_p_N_u480) =
+ {"clk_m", NULL, "pllU_48", NULL,
+ "pllP_out0", NULL, "pllU_480"};
+PLIST(mux_clkm_p_c2_c_c3_refre) =
+ {"clk_m", "pllP_out0", "pllC2_out0", "pllC_out0",
+ "pllC3_out0", "pllREFE_out"};
+PLIST(mux_clkm_refe_clks_u480_c_c2_c3_oscdiv) =
+ {"clk_m", "pllREFE_out", "clk_s", "pllU_480",
+ "pllC_out0", "pllC2_out0", "pllC3_out0", "osc_div_clk"};
+
+PLIST(mux_sep_audio) =
+ {"pllA_out0", "pllC2_out0", "pllC_out0", "pllC3_out0",
+ "pllP_out0", NULL, "clk_m", NULL,
+ "spdif_in", "i2s0", "i2s1", "i2s2",
+ "i2s4", "pllA_out0", "ext_vimclk"};
+
+static uint32_t clk_enabale_reg[] = {
+ CLK_OUT_ENB_L,
+ CLK_OUT_ENB_H,
+ CLK_OUT_ENB_U,
+ CLK_OUT_ENB_V,
+ CLK_OUT_ENB_W,
+ CLK_OUT_ENB_X,
+};
+
+static uint32_t clk_reset_reg[] = {
+ RST_DEVICES_L,
+ RST_DEVICES_H,
+ RST_DEVICES_U,
+ RST_DEVICES_V,
+ RST_DEVICES_W,
+ RST_DEVICES_X,
+};
+
+#define L(n) ((0 * 32) + (n))
+#define H(n) ((1 * 32) + (n))
+#define U(n) ((2 * 32) + (n))
+#define V(n) ((3 * 32) + (n))
+#define W(n) ((4 * 32) + (n))
+#define X(n) ((5 * 32) + (n))
+
+static struct pgate_def pgate_def[] = {
+ /* bank L -> 0-31 */
+ /* GATE(CPU, "cpu", "clk_m", L(0)), */
+ GATE(ISPB, "ispb", "clk_m", L(3)),
+ GATE(RTC, "rtc", "clk_s", L(4)),
+ GATE(TIMER, "timer", "clk_m", L(5)),
+ GATE(UARTA, "uarta", "pc_uarta" , L(6)),
+ GATE(UARTB, "uartb", "pc_uartb", L(7)),
+ GATE(VFIR, "vfir", "pc_vfir", L(7)),
+ /* GATE(GPIO, "gpio", "clk_m", L(8)), */
+ GATE(SDMMC2, "sdmmc2", "pc_sdmmc2", L(9)),
+ GATE(SPDIF_OUT, "spdif_out", "pc_spdif_out", L(10)),
+ GATE(SPDIF_IN, "spdif_in", "pc_spdif_in", L(10)),
+ GATE(I2S1, "i2s1", "pc_i2s1", L(11)),
+ GATE(I2C1, "i2c1", "pc_i2c1", L(12)),
+ GATE(SDMMC1, "sdmmc1", "pc_sdmmc1", L(14)),
+ GATE(SDMMC4, "sdmmc4", "pc_sdmmc4", L(15)),
+ GATE(PWM, "pwm", "pc_pwm", L(17)),
+ GATE(I2S2, "i2s2", "pc_i2s2", L(18)),
+ GATE(VI, "vi", "pc_vi", L(20)),
+ GATE(USBD, "usbd", "clk_m", L(22)),
+ GATE(ISP, "isp", "pc_isp", L(23)),
+ GATE(DISP2, "disp2", "pc_disp2", L(26)),
+ GATE(DISP1, "disp1", "pc_disp1", L(27)),
+ GATE(HOST1X, "host1x", "pc_host1x", L(28)),
+ GATE(VCP, "vcp", "clk_m", L(29)),
+ GATE(I2S0, "i2s0", "pc_i2s0", L(30)),
+ /* GATE(CACHE2, "ccache2", "clk_m", L(31)), */
+
+ /* bank H -> 32-63 */
+ GATE(MC, "mem", "clk_m", H(0)),
+ /* GATE(AHBDMA, "ahbdma", "clk_m", H(1)), */
+ GATE(APBDMA, "apbdma", "clk_m", H(2)),
+ GATE(KBC, "kbc", "clk_s", H(4)),
+ /* GATE(STAT_MON, "stat_mon", "clk_s", H(5)), */
+ /* GATE(PMC, "pmc", "clk_s", H(6)), */
+ GATE(FUSE, "fuse", "clk_m", H(7)),
+ GATE(KFUSE, "kfuse", "clk_m", H(8)),
+ GATE(SBC1, "spi1", "pc_spi1", H(9)),
+ GATE(NOR, "snor", "pc_snor", H(10)),
+ /* GATE(JTAG2TBC, "jtag2tbc", "clk_m", H(11)), */
+ GATE(SBC2, "spi2", "pc_spi2", H(12)),
+ GATE(SBC3, "spi3", "pc_spi3", H(14)),
+ GATE(I2C5, "i2c5", "pc_i2c5", H(15)),
+ GATE(DSIA, "dsia", "dsia_mux", H(16)),
+ GATE(MIPI, "hsi", "pc_hsi", H(18)),
+ GATE(HDMI, "hdmi", "pc_hdmi", H(19)),
+ GATE(CSI, "csi", "pllP_out3", H(20)),
+ GATE(I2C2, "i2c2", "pc_i2c2", H(22)),
+ GATE(UARTC, "uartc", "pc_uartc", H(23)),
+ GATE(MIPI_CAL, "mipi_cal", "clk_m", H(24)),
+ GATE(EMC, "emc", "emc_mux", H(25)),
+ GATE(USB2, "usb2", "clk_m", H(26)),
+ GATE(USB3, "usb3", "clk_m", H(27)),
+ GATE(VDE, "vde", "pc_vde", H(29)),
+ GATE(BSEA, "bsea", "clk_m", H(30)),
+ GATE(BSEV, "bsev", "clk_m", H(31)),
+
+ /* bank U -> 64-95 */
+ GATE(UARTD, "uartd", "pc_uartd", U(1)),
+ GATE(I2C3, "i2c3", "pc_i2c3", U(3)),
+ GATE(SBC4, "spi4", "pc_spi4", U(4)),
+ GATE(SDMMC3, "sdmmc3", "pc_sdmmc3", U(5)),
+ GATE(PCIE, "pcie", "clk_m", U(6)),
+ GATE(OWR, "owr", "pc_owr", U(7)),
+ GATE(AFI, "afi", "clk_m", U(8)),
+ GATE(CSITE, "csite", "pc_csite", U(9)),
+ /* GATE(AVPUCQ, "avpucq", clk_m, U(11)), */
+ GATE(TRACE, "traceclkin", "pc_traceclkin", U(13)),
+ GATE(SOC_THERM, "soc_therm", "pc_soc_therm", U(14)),
+ GATE(DTV, "dtv", "clk_m", U(15)),
+ GATE(I2CSLOW, "i2c_slow", "pc_i2c_slow", U(17)),
+ GATE(DSIB, "dsib", "dsib_mux", U(18)),
+ GATE(TSEC, "tsec", "pc_tsec", U(19)),
+ /* GATE(IRAMA, "irama", "clk_m", U(20)), */
+ /* GATE(IRAMB, "iramb", "clk_m", U(21)), */
+ /* GATE(IRAMC, "iramc", "clk_m", U(22)), */
+ /* GATE(IRAMD, "iramd", "clk_m", U(23)), */
+ /* GATE(CRAM2, "cram2", "clk_m", U(24)), */
+ GATE(XUSB_HOST, "xusb_core_host", "pc_xusb_core_host", U(25)),
+ /* GATE(M_DOUBLER, "m_doubler", "clk_m", U(26)), */
+ GATE(MSENC, "msenc", "pc_msenc", U(27)),
+ GATE(CSUS, "sus_out", "clk_m", U(28)),
+ /* GATE(DEVD2_OUT, "devd2_out", "clk_m", U(29)), */
+ /* GATE(DEVD1_OUT, "devd1_out", "clk_m", U(30)), */
+ GATE(XUSB_DEV_SRC, "xusb_core_dev", "pc_xusb_core_dev", U(31)),
+
+ /* bank V -> 96-127 */
+ /* GATE(CPUG, "cpug", "clk_m", V(0)), */
+ /* GATE(CPULP, "cpuLP", "clk_m", V(1)), */
+ GATE(MSELECT, "mselect", "pc_mselect", V(3)),
+ GATE(TSENSOR, "tsensor", "pc_tsensor", V(4)),
+ GATE(I2S3, "i2s3", "pc_i2s3", V(5)),
+ GATE(I2S4, "i2s4", "pc_i2s4", V(6)),
+ GATE(I2C4, "i2c4", "pc_i2c4", V(7)),
+ GATE(SBC5, "spi5", "pc_spi5", V(8)),
+ GATE(SBC6, "spi6", "pc_spi6", V(9)),
+ GATE(D_AUDIO, "audio", "pc_audio", V(10)),
+ GATE(APBIF, "apbif", "clk_m", V(11)),
+ GATE(DAM0, "dam0", "pc_dam0", V(12)),
+ GATE(DAM1, "dam1", "pc_dam1", V(13)),
+ GATE(DAM2, "dam2", "pc_dam2", V(14)),
+ GATE(HDA2CODEC_2X, "hda2codec_2x", "pc_hda2codec_2x", V(15)),
+ /* GATE(ATOMICS, "atomics", "clk_m", V(16)), */
+ /* GATE(SPDIF_DOUBLER, "spdif_doubler", "clk_m", V(22)), */
+ GATE(ACTMON, "actmon", "pc_actmon", V(23)),
+ GATE(EXTERN1, "extperiph1", "pc_extperiph1", V(24)),
+ GATE(EXTERN2, "extperiph2", "pc_extperiph2", V(25)),
+ GATE(EXTERN3, "extperiph3", "pc_extperiph3", V(26)),
+ GATE(SATA_OOB, "sata_oob", "pc_sata_oob", V(27)),
+ GATE(SATA, "sata", "pc_sata", V(28)),
+ GATE(HDA, "hda", "pc_hda", V(29)),
+
+ /* bank W -> 128-159*/
+ GATE(HDA2HDMI, "hda2hdmi", "clk_m", W(0)),
+ GATE(SATA_COLD, "sata_cold", "clk_m", W(1)), /* Reset only */
+ /* GATE(PCIERX0, "pcierx0", "clk_m", W(2)), */
+ /* GATE(PCIERX1, "pcierx1", "clk_m", W(3)), */
+ /* GATE(PCIERX2, "pcierx2", "clk_m", W(4)), */
+ /* GATE(PCIERX3, "pcierx3", "clk_m", W(5)), */
+ /* GATE(PCIERX4, "pcierx4", "clk_m", W(6)), */
+ /* GATE(PCIERX5, "pcierx5", "clk_m", W(7)), */
+ /* GATE(CEC, "cec", "clk_m", W(8)), */
+ /* GATE(PCIE2_IOBIST, "pcie2_iobist", "clk_m", W(9)), */
+ /* GATE(EMC_IOBIST, "emc_iobist", "clk_m", W(10)), */
+ /* GATE(HDMI_IOBIST, "hdmi_iobist", "clk_m", W(11)), */
+ /* GATE(SATA_IOBIST, "sata_iobist", "clk_m", W(12)), */
+ /* GATE(MIPI_IOBIST, "mipi_iobist", "clk_m", W(13)), */
+ /* GATE(XUSB_IOBIST, "xusb_iobist", "clk_m", W(15)), */
+ GATE(CILAB, "cilab", "pc_cilab", W(16)),
+ GATE(CILCD, "cilcd", "pc_cilcd", W(17)),
+ GATE(CILE, "cile", "pc_cile", W(18)),
+ GATE(DSIALP, "dsia_lp", "pc_dsia_lp", W(19)),
+ GATE(DSIBLP, "dsib_lp", "pc_dsib_lp", W(20)),
+ GATE(ENTROPY, "entropy", "pc_entropy", W(21)),
+ GATE(AMX, "amx", "pc_amx", W(25)),
+ GATE(ADX, "adx", "pc_adx", W(26)),
+ GATE(DFLL_REF, "dvfs_ref", "pc_dvfs_ref", X(27)),
+ GATE(DFLL_SOC, "dvfs_soc", "pc_dvfs_soc", X(27)),
+ GATE(XUSB_SS_SRC, "xusb_ss", "xusb_ss_mux", X(28)),
+ /* GATE(EMC_LATENCY, "emc_latency", "pc_emc_latency", X(29)), */
+
+ /* bank X -> 160-191*/
+ /* GATE(SPARE, "spare", "clk_m", X(0)), */
+ /* GATE(CAM_MCLK, "CAM_MCLK", "clk_m", X(4)), */
+ /* GATE(CAM_MCLK2, "CAM_MCLK2", "clk_m", X(5)), */
+ GATE(I2C6, "i2c6", "pc_i2c6", X(6)),
+ /* GATE(VIM2_CLK, "vim2_clk", clk_m, X(11)), */
+ /* GATE(EMC_DLL, "emc_dll", "pc_emc_dll", X(14)), */
+ GATE(HDMI_AUDIO, "hdmi_audio", "pc_hdmi_audio", X(16)),
+ GATE(CLK72MHZ, "clk72mhz", "pc_clk72mhz", X(17)),
+ GATE(VIC03, "vic", "pc_vic", X(18)),
+ GATE(ADX1, "adx1", "pc_adx1", X(20)),
+ GATE(DPAUX, "dpaux", "clk_m", X(21)),
+ GATE(SOR0_LVDS, "sor0", "pc_sor0", X(22)),
+ GATE(GPU, "gpu", "osc_div_clk", X(24)),
+ GATE(AMX1, "amx1", "pc_amx1", X(26)),
+};
+
+/* Peripheral clock clock */
+#define DCF_HAVE_MUX 0x0100 /* Block with multipexor */
+#define DCF_HAVE_ENA 0x0200 /* Block with enable bit */
+#define DCF_HAVE_DIV 0x0400 /* Block with divider */
+
+/* Mark block with additional bis / functionality. */
+#define DCF_IS_MASK 0x00FF
+#define DCF_IS_UART 0x0001
+#define DCF_IS_VI 0x0002
+#define DCF_IS_HOST1X 0x0003
+#define DCF_IS_XUSB_SS 0x0004
+#define DCF_IS_EMC_DLL 0x0005
+#define FDS_IS_SATA 0x0006
+#define DCF_IS_VIC 0x0007
+#define DCF_IS_AUDIO 0x0008
+#define DCF_IS_SOR0 0x0009
+
+/* Basic pheripheral clock */
+#define PER_CLK(_id, cn, pl, r, diw, fiw, f) \
+{ \
+ .clkdef.id = _id, \
+ .clkdef.name = cn, \
+ .clkdef.parent_names = pl, \
+ .clkdef.parent_cnt = nitems(pl), \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
+ .base_reg = r, \
+ .div_width = diw, \
+ .div_f_width = fiw, \
+ .flags = f, \
+}
+
+/* Mux with fractional 8.1 divider. */
+#define CLK_8_1(cn, pl, r, f) \
+ PER_CLK(0, cn, pl, r, 8, 1, (f) | DCF_HAVE_MUX | DCF_HAVE_DIV)
+/* Mux with fractional 16.1 divider. */
+#define CLK16_1(cn, pl, r, f) \
+ PER_CLK(0, cn, pl, r, 16, 1, (f) | DCF_HAVE_MUX | DCF_HAVE_DIV)
+/* Mux with integer 16bits divider. */
+#define CLK16_0(cn, pl, r, f) \
+ PER_CLK(0, cn, pl, r, 16, 0, (f) | DCF_HAVE_MUX | DCF_HAVE_DIV)
+/* Mux wihout divider. */
+#define CLK_0_0(cn, pl, r, f) \
+ PER_CLK(0, cn, pl, r, 0, 0, (f) | DCF_HAVE_MUX)
+
+static struct periph_def periph_def[] = {
+ CLK_8_1("pc_i2s1", mux_a_N_audio1_N_p_N_clkm, CLK_SOURCE_I2S1, DCF_HAVE_ENA),
+ CLK_8_1("pc_i2s2", mux_a_N_audio2_N_p_N_clkm, CLK_SOURCE_I2S2, DCF_HAVE_ENA),
+ CLK_8_1("pc_spdif_out", mux_a_N_audio_N_p_N_clkm, CLK_SOURCE_SPDIF_OUT, 0),
+ CLK_8_1("pc_spdif_in", mux_p_c2_c_c3_m, CLK_SOURCE_SPDIF_IN, 0),
+ CLK_8_1("pc_pwm", mux_p_c2_c_c3_clks_N_clkm, CLK_SOURCE_PWM, 0),
+ CLK_8_1("pc_spi2", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_SPI2, 0),
+ CLK_8_1("pc_spi3", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_SPI3, 0),
+ CLK16_0("pc_i2c5", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_I2C5, 0),
+ CLK16_0("pc_i2c1", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_I2C1, 0),
+ CLK_8_1("pc_spi1", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_SPI1, 0),
+ CLK_0_0("pc_disp1", mux_p_m_d_a_c_d2_clkm, CLK_SOURCE_DISP1, 0),
+ CLK_0_0("pc_disp2", mux_p_m_d_a_c_d2_clkm, CLK_SOURCE_DISP2, 0),
+ CLK_8_1("pc_isp", mux_m_c_p_a_c2_c3_clkm_c4, CLK_SOURCE_ISP, 0),
+ CLK_8_1("pc_vi", mux_m_c2_c_c3_p_N_a_c4, CLK_SOURCE_VI, DCF_IS_VI),
+ CLK_8_1("pc_sdmmc1", mux_p_c2_c_c3_m_e_clkm, CLK_SOURCE_SDMMC1, 0),
+ CLK_8_1("pc_sdmmc2", mux_p_c2_c_c3_m_e_clkm, CLK_SOURCE_SDMMC2, 0),
+ CLK_8_1("pc_sdmmc4", mux_p_c2_c_c3_m_e_clkm, CLK_SOURCE_SDMMC4, 0),
+ CLK_8_1("pc_vfir", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_VFIR, 0),
+ CLK_8_1("pc_hsi", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_HSI, 0),
+ CLK16_1("pc_uarta", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_UARTA, DCF_IS_UART),
+ CLK16_1("pc_uartb", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_UARTB, DCF_IS_UART),
+ CLK_8_1("pc_host1x", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_HOST1X, DCF_IS_HOST1X),
+ CLK_8_1("pc_hdmi", mux_p_m_d_a_c_d2_clkm, CLK_SOURCE_HDMI, 0),
+ CLK16_0("pc_i2c2", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_I2C2, 0),
+/* EMC 8 */
+ CLK16_1("pc_uartc", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_UARTC, DCF_IS_UART),
+ CLK_8_1("pc_vi_sensor", mux_m_c2_c_c3_p_N_a, CLK_SOURCE_VI_SENSOR, 0),
+ CLK_8_1("pc_spi4", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_SPI4, 0),
+ CLK16_0("pc_i2c3", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_I2C3, 0),
+ CLK_8_1("pc_sdmmc3", mux_p_c2_c_c3_m_e_clkm, CLK_SOURCE_SDMMC3, 0),
+ CLK16_1("pc_uartd", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_UARTD, DCF_IS_UART),
+ CLK_8_1("pc_vde", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_VDE, 0),
+ CLK_8_1("pc_owr", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_OWR, 0),
+ CLK_8_1("pc_snor", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_NOR, 0),
+ CLK_8_1("pc_csite", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_CSITE, 0),
+ CLK_8_1("pc_i2s0", mux_a_N_audio0_N_p_N_clkm, CLK_SOURCE_I2S0, 0),
+/* DTV xxx */
+ CLK_8_1("pc_msenc", mux_m_c2_c_c3_p_N_a, CLK_SOURCE_MSENC, 0),
+ CLK_8_1("pc_tsec", mux_p_c2_c_c3_m_a_clkm, CLK_SOURCE_TSEC, 0),
+/* SPARE2 */
+
+
+ CLK_8_1("pc_mselect", mux_p_c2_c_c3_m_clks_clkm, CLK_SOURCE_MSELECT, 0),
+ CLK_8_1("pc_tsensor", mux_p_c2_c_c3_clkm_N_clks, CLK_SOURCE_TSENSOR, 0),
+ CLK_8_1("pc_i2s3", mux_a_N_audio3_N_p_N_clkm, CLK_SOURCE_I2S3, DCF_HAVE_ENA),
+ CLK_8_1("pc_i2s4", mux_a_N_audio4_N_p_N_clkm, CLK_SOURCE_I2S4, DCF_HAVE_ENA),
+ CLK16_0("pc_i2c4", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_I2C4, 0),
+ CLK_8_1("pc_spi5", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_SPI5, 0),
+ CLK_8_1("pc_spi6", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_SPI6, 0),
+ CLK_8_1("pc_audio", mux_sep_audio, CLK_SOURCE_AUDIO, DCF_IS_AUDIO),
+ CLK_8_1("pc_dam0", mux_sep_audio, CLK_SOURCE_DAM0, DCF_IS_AUDIO),
+ CLK_8_1("pc_dam1", mux_sep_audio, CLK_SOURCE_DAM1, DCF_IS_AUDIO),
+ CLK_8_1("pc_dam2", mux_sep_audio, CLK_SOURCE_DAM2, DCF_IS_AUDIO),
+ CLK_8_1("pc_hda2codec_2x", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_HDA2CODEC_2X, 0),
+ CLK_8_1("pc_actmon", mux_p_c2_c_c3_clks_N_clkm, CLK_SOURCE_ACTMON, 0),
+ CLK_8_1("pc_extperiph1", mux_a_clks_p_clkm_e, CLK_SOURCE_EXTPERIPH1, 0),
+ CLK_8_1("pc_extperiph2", mux_a_clks_p_clkm_e, CLK_SOURCE_EXTPERIPH2, 0),
+ CLK_8_1("pc_extperiph3", mux_a_clks_p_clkm_e, CLK_SOURCE_EXTPERIPH3, 0),
+ CLK_8_1("pc_i2c_slow", mux_p_c2_c_c3_clks_N_clkm, CLK_SOURCE_I2C_SLOW, 0),
+/* SYS */
+ CLK_8_1("pc_sor0", mux_p_m_d_a_c_d2_clkm, CLK_SOURCE_SOR0, DCF_IS_SOR0),
+ CLK_8_1("pc_sata_oob", mux_p_N_c_N_m_N_clkm, CLK_SOURCE_SATA_OOB, 0),
+ CLK_8_1("pc_sata", mux_p_N_c_N_m_N_clkm, CLK_SOURCE_SATA, FDS_IS_SATA),
+ CLK_8_1("pc_hda", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_HDA, 0),
+
+
+ CLK_8_1("pc_xusb_core_host", mux_clkm_p_c2_c_c3_refre, CLK_SOURCE_XUSB_CORE_HOST, 0),
+ CLK_8_1("pc_xusb_falcon", mux_clkm_p_c2_c_c3_refre, CLK_SOURCE_XUSB_FALCON, 0),
+ CLK_8_1("pc_xusb_fs", mux_clkm_N_u48_N_p_N_u480, CLK_SOURCE_XUSB_FS, 0),
+ CLK_8_1("pc_xusb_core_dev", mux_clkm_p_c2_c_c3_refre, CLK_SOURCE_XUSB_CORE_DEV, 0),
+ CLK_8_1("pc_xusb_ss", mux_clkm_refe_clks_u480_c_c2_c3_oscdiv, CLK_SOURCE_XUSB_SS, DCF_IS_XUSB_SS),
+ CLK_8_1("pc_cilab", mux_p_N_c_N_N_N_clkm, CLK_SOURCE_CILAB, 0),
+ CLK_8_1("pc_cilcd", mux_p_N_c_N_N_N_clkm, CLK_SOURCE_CILCD, 0),
+ CLK_8_1("pc_cile", mux_p_N_c_N_N_N_clkm, CLK_SOURCE_CILE, 0),
+ CLK_8_1("pc_dsia_lp", mux_p_N_c_N_N_N_clkm, CLK_SOURCE_DSIA_LP, 0),
+ CLK_8_1("pc_dsib_lp", mux_p_N_c_N_N_N_clkm, CLK_SOURCE_DSIB_LP, 0),
+ CLK_8_1("pc_entropy", mux_p_clkm_clks_E, CLK_SOURCE_ENTROPY, 0),
+ CLK_8_1("pc_dvfs_ref", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_DVFS_REF, DCF_HAVE_ENA),
+ CLK_8_1("pc_dvfs_soc", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_DVFS_SOC, DCF_HAVE_ENA),
+ CLK_8_1("pc_traceclkin", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_TRACECLKIN, 0),
+ CLK_8_1("pc_adx", mux_a_c2_c_c3_p_N_clkm, CLK_SOURCE_ADX, DCF_HAVE_ENA),
+ CLK_8_1("pc_amx", mux_a_c2_c_c3_p_N_clkm, CLK_SOURCE_AMX, DCF_HAVE_ENA),
+ CLK_8_1("pc_emc_latency", mux_m_c_p_clkm_mud_c2_c3, CLK_SOURCE_EMC_LATENCY, 0),
+ CLK_8_1("pc_soc_therm", mux_m_c_p_a_c2_c3, CLK_SOURCE_SOC_THERM, 0),
+ CLK_8_1("pc_vi_sensor2", mux_m_c2_c_c3_p_N_a, CLK_SOURCE_VI_SENSOR2, 0),
+ CLK16_0("pc_i2c6", mux_p_c2_c_c3_m_N_clkm, CLK_SOURCE_I2C6, 0),
+ CLK_8_1("pc_emc_dll", mux_m_c_p_clkm_mud_c2_c3, CLK_SOURCE_EMC_DLL, DCF_IS_EMC_DLL),
+ CLK_8_1("pc_hdmi_audio", mux_p_c_c2_clkm, CLK_SOURCE_HDMI_AUDIO, 0),
+ CLK_8_1("pc_clk72mhz", mux_p_c_c2_clkm, CLK_SOURCE_CLK72MHZ, 0),
+ CLK_8_1("pc_adx1", mux_a_c2_c_c3_p_N_clkm, CLK_SOURCE_ADX1, DCF_HAVE_ENA),
+ CLK_8_1("pc_amx1", mux_a_c2_c_c3_p_N_clkm, CLK_SOURCE_AMX1, DCF_HAVE_ENA),
+ CLK_8_1("pc_vic", mux_m_c_p_a_c2_c3_clkm, CLK_SOURCE_VIC, DCF_IS_VIC),
+};
+
+static int periph_init(struct clknode *clk, device_t dev);
+static int periph_recalc(struct clknode *clk, uint64_t *freq);
+static int periph_set_freq(struct clknode *clk, uint64_t fin,
+ uint64_t *fout, int flags, int *stop);
+static int periph_set_mux(struct clknode *clk, int idx);
+
+struct periph_sc {
+ device_t clkdev;
+ uint32_t base_reg;
+ uint32_t div_shift;
+ uint32_t div_width;
+ uint32_t div_mask;
+ uint32_t div_f_width;
+ uint32_t div_f_mask;
+ uint32_t flags;
+
+ uint32_t divider;
+ int mux;
+};
+
+static clknode_method_t periph_methods[] = {
+ /* Device interface */
+ CLKNODEMETHOD(clknode_init, periph_init),
+ CLKNODEMETHOD(clknode_recalc_freq, periph_recalc),
+ CLKNODEMETHOD(clknode_set_freq, periph_set_freq),
+ CLKNODEMETHOD(clknode_set_mux, periph_set_mux),
+ CLKNODEMETHOD_END
+};
+DEFINE_CLASS_1(tegra124_periph, tegra124_periph_class, periph_methods,
+ sizeof(struct periph_sc), clknode_class);
+static int
+periph_init(struct clknode *clk, device_t dev)
+{
+ struct periph_sc *sc;
+ uint32_t reg;
+ sc = clknode_get_softc(clk);
+
+ DEVICE_LOCK(sc);
+ if (sc->flags & DCF_HAVE_ENA)
+ MD4(sc, sc->base_reg, PERLCK_ENA_MASK, PERLCK_ENA_MASK);
+
+ RD4(sc, sc->base_reg, &reg);
+ DEVICE_UNLOCK(sc);
+
+ /* Stnadard mux. */
+ if (sc->flags & DCF_HAVE_MUX)
+ sc->mux = (reg >> PERLCK_MUX_SHIFT) & PERLCK_MUX_MASK;
+ else
+ sc->mux = 0;
+ if (sc->flags & DCF_HAVE_DIV)
+ sc->divider = (reg & sc->div_mask) + 2;
+ else
+ sc->divider = 1;
+ if ((sc->flags & DCF_IS_MASK) == DCF_IS_UART) {
+ if (!(reg & PERLCK_UDIV_DIS))
+ sc->divider = 2;
+ }
+
+ /* AUDIO MUX */
+ if ((sc->flags & DCF_IS_MASK) == DCF_IS_AUDIO) {
+ if (!(reg & PERLCK_AMUX_DIS) && (sc->mux == 7)) {
+ sc->mux = 8 +
+ ((reg >> PERLCK_AMUX_SHIFT) & PERLCK_MUX_MASK);
+ }
+ }
+ clknode_init_parent_idx(clk, sc->mux);
+ return(0);
+}
+
+static int
+periph_set_mux(struct clknode *clk, int idx)
+{
+ struct periph_sc *sc;
+ uint32_t reg;
+
+
+ sc = clknode_get_softc(clk);
+ if (!(sc->flags & DCF_HAVE_MUX))
+ return (ENXIO);
+
+ sc->mux = idx;
+ DEVICE_LOCK(sc);
+ RD4(sc, sc->base_reg, &reg);
+ reg &= ~(PERLCK_MUX_MASK << PERLCK_MUX_SHIFT);
+ if ((sc->flags & DCF_IS_MASK) == DCF_IS_AUDIO) {
+ reg &= ~PERLCK_AMUX_DIS;
+ reg &= ~(PERLCK_MUX_MASK << PERLCK_AMUX_SHIFT);
+
+ if (idx <= 7) {
+ reg |= idx << PERLCK_MUX_SHIFT;
+ } else {
+ reg |= 7 << PERLCK_MUX_SHIFT;
+ reg |= (idx - 8) << PERLCK_AMUX_SHIFT;
+ }
+ } else {
+ reg |= idx << PERLCK_MUX_SHIFT;
+ }
+ WR4(sc, sc->base_reg, reg);
+ DEVICE_UNLOCK(sc);
+
+ return(0);
+}
+
+static int
+periph_recalc(struct clknode *clk, uint64_t *freq)
+{
+ struct periph_sc *sc;
+ uint32_t reg;
+
+ sc = clknode_get_softc(clk);
+
+ if (sc->flags & DCF_HAVE_DIV) {
+ DEVICE_LOCK(sc);
+ RD4(sc, sc->base_reg, &reg);
+ DEVICE_UNLOCK(sc);
+ *freq = (*freq << sc->div_f_width) / sc->divider;
+ }
+ return (0);
+}
+
+static int
+periph_set_freq(struct clknode *clk, uint64_t fin, uint64_t *fout,
+ int flags, int *stop)
+{
+ struct periph_sc *sc;
+ uint64_t tmp, divider;
+
+ sc = clknode_get_softc(clk);
+ if (!(sc->flags & DCF_HAVE_DIV)) {
+ *stop = 0;
+ return (0);
+ }
+
+ tmp = fin << sc->div_f_width;
+ divider = tmp / *fout;
+ if ((tmp % *fout) != 0)
+ divider++;
+
+ if (divider < (1 << sc->div_f_width))
+ divider = 1 << sc->div_f_width;
+
+ if ((*stop != 0) &&
+ ((flags & (CLK_SET_ROUND_UP | CLK_SET_ROUND_DOWN)) == 0) &&
+ (*fout != (tmp / divider)))
+ return (ERANGE);
+
+ if ((flags & CLK_SET_DRYRUN) == 0) {
+ DEVICE_LOCK(sc);
+ MD4(sc, sc->base_reg, sc->div_mask,
+ (divider - (1 << sc->div_f_width)));
+ DEVICE_UNLOCK(sc);
+ sc->divider = divider;
+ }
+ *fout = tmp / divider;
+ *stop = 1;
+ return (0);
+}
+
+static int
+periph_register(struct clkdom *clkdom, struct periph_def *clkdef)
+{
+ struct clknode *clk;
+ struct periph_sc *sc;
+
+ clk = clknode_create(clkdom, &tegra124_periph_class, &clkdef->clkdef);
+ if (clk == NULL)
+ return (1);
+
+ sc = clknode_get_softc(clk);
+ sc->clkdev = clknode_get_device(clk);
+ sc->base_reg = clkdef->base_reg;
+ sc->div_width = clkdef->div_width;
+ sc->div_mask = (1 <<clkdef->div_width) - 1;
+ sc->div_f_width = clkdef->div_f_width;
+ sc->div_f_mask = (1 <<clkdef->div_f_width) - 1;
+ sc->flags = clkdef->flags;
+
+ clknode_register(clkdom, clk);
+ return (0);
+}
+
+/* -------------------------------------------------------------------------- */
+static int pgate_init(struct clknode *clk, device_t dev);
+static int pgate_set_gate(struct clknode *clk, bool enable);
+
+struct pgate_sc {
+ device_t clkdev;
+ uint32_t idx;
+ uint32_t flags;
+ uint32_t enabled;
+
+};
+
+static clknode_method_t pgate_methods[] = {
+ /* Device interface */
+ CLKNODEMETHOD(clknode_init, pgate_init),
+ CLKNODEMETHOD(clknode_set_gate, pgate_set_gate),
+ CLKNODEMETHOD_END
+};
+DEFINE_CLASS_1(tegra124_pgate, tegra124_pgate_class, pgate_methods,
+ sizeof(struct pgate_sc), clknode_class);
+
+static uint32_t
+get_enable_reg(int idx)
+{
+ KASSERT(idx / 32 < nitems(clk_enabale_reg),
+ ("Invalid clock index for enable: %d", idx));
+ return (clk_enabale_reg[idx / 32]);
+}
+
+static uint32_t
+get_reset_reg(int idx)
+{
+ KASSERT(idx / 32 < nitems(clk_reset_reg),
+ ("Invalid clock index for reset: %d", idx));
+ return (clk_reset_reg[idx / 32]);
+}
+
+static int
+pgate_init(struct clknode *clk, device_t dev)
+{
+ struct pgate_sc *sc;
+ uint32_t ena_reg, rst_reg, mask;
+
+ sc = clknode_get_softc(clk);
+ mask = 1 << (sc->idx % 32);
+
+ DEVICE_LOCK(sc);
+ RD4(sc, get_enable_reg(sc->idx), &ena_reg);
+ RD4(sc, get_reset_reg(sc->idx), &rst_reg);
+ DEVICE_UNLOCK(sc);
+
+ sc->enabled = ena_reg & mask ? 1 : 0;
+ clknode_init_parent_idx(clk, 0);
+
+ return(0);
+}
+
+static int
+pgate_set_gate(struct clknode *clk, bool enable)
+{
+ struct pgate_sc *sc;
+ uint32_t reg, mask, base_reg;
+
+ sc = clknode_get_softc(clk);
+ mask = 1 << (sc->idx % 32);
+ sc->enabled = enable;
+ base_reg = get_enable_reg(sc->idx);
+
+ DEVICE_LOCK(sc);
+ MD4(sc, base_reg, mask, enable ? mask : 0);
+ RD4(sc, base_reg, &reg);
+ DEVICE_UNLOCK(sc);
+
+ DELAY(2);
+ return(0);
+}
+
+int
+tegra124_hwreset_by_idx(struct tegra124_car_softc *sc, intptr_t idx, bool reset)
+{
+ uint32_t reg, mask, reset_reg;
+
+ mask = 1 << (idx % 32);
+ reset_reg = get_reset_reg(idx);
+
+ CLKDEV_DEVICE_LOCK(sc->dev);
+ CLKDEV_MODIFY_4(sc->dev, reset_reg, mask, reset ? mask : 0);
+ CLKDEV_READ_4(sc->dev, reset_reg, &reg);
+ CLKDEV_DEVICE_UNLOCK(sc->dev);
+
+ return(0);
+}
+
+static int
+pgate_register(struct clkdom *clkdom, struct pgate_def *clkdef)
+{
+ struct clknode *clk;
+ struct pgate_sc *sc;
+
+ clk = clknode_create(clkdom, &tegra124_pgate_class, &clkdef->clkdef);
+ if (clk == NULL)
+ return (1);
+
+ sc = clknode_get_softc(clk);
+ sc->clkdev = clknode_get_device(clk);
+ sc->idx = clkdef->idx;
+ sc->flags = clkdef->flags;
+
+ clknode_register(clkdom, clk);
+ return (0);
+}
+
+void
+tegra124_periph_clock(struct tegra124_car_softc *sc)
+{
+ int i, rv;
+
+ for (i = 0; i < nitems(periph_def); i++) {
+ rv = periph_register(sc->clkdom, &periph_def[i]);
+ if (rv != 0)
+ panic("tegra124_periph_register failed");
+ }
+ for (i = 0; i < nitems(pgate_def); i++) {
+ rv = pgate_register(sc->clkdom, &pgate_def[i]);
+ if (rv != 0)
+ panic("tegra124_pgate_register failed");
+ }
+
+}
diff --git a/sys/arm/nvidia/tegra124/tegra124_clk_pll.c b/sys/arm/nvidia/tegra124/tegra124_clk_pll.c
new file mode 100644
index 0000000..6adfd32
--- /dev/null
+++ b/sys/arm/nvidia/tegra124/tegra124_clk_pll.c
@@ -0,0 +1,1066 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+
+#include <dev/extres/clk/clk.h>
+
+#include <gnu/dts/include/dt-bindings/clock/tegra124-car.h>
+#include "tegra124_car.h"
+
+/* #define TEGRA_PLL_DEBUG */
+#ifdef TEGRA_PLL_DEBUG
+#define dprintf(...) printf(__VA_ARGS__)
+#else
+#define dprintf(...)
+#endif
+
+/* All PLLs. */
+enum pll_type {
+ PLL_M,
+ PLL_X,
+ PLL_C,
+ PLL_C2,
+ PLL_C3,
+ PLL_C4,
+ PLL_P,
+ PLL_A,
+ PLL_U,
+ PLL_D,
+ PLL_D2,
+ PLL_DP,
+ PLL_E,
+ PLL_REFE};
+
+/* Common base register bits. */
+#define PLL_BASE_BYPASS (1U << 31)
+#define PLL_BASE_ENABLE (1 << 30)
+#define PLL_BASE_REFDISABLE (1 << 29)
+#define PLL_BASE_LOCK (1 << 27)
+#define PLL_BASE_DIVM_SHIFT 0
+#define PLL_BASE_DIVN_SHIFT 8
+
+#define PLLRE_MISC_LOCK (1 << 24)
+
+#define PLL_MISC_LOCK_ENABLE (1 << 18)
+#define PLLC_MISC_LOCK_ENABLE (1 << 24)
+#define PLLDU_MISC_LOCK_ENABLE (1 << 22)
+#define PLLRE_MISC_LOCK_ENABLE (1 << 30)
+#define PLLSS_MISC_LOCK_ENABLE (1 << 30)
+
+#define PLLC_IDDQ_BIT 26
+#define PLLX_IDDQ_BIT 3
+#define PLLRE_IDDQ_BIT 16
+#define PLLSS_IDDQ_BIT 19
+
+#define PLL_LOCK_TIMEOUT 1000
+
+/* Post divider <-> register value mapping. */
+struct pdiv_table {
+ uint32_t divider; /* real divider */
+ uint32_t value; /* register value */
+};
+
+/* Bits definition of M, N and P fields. */
+struct mnp_bits {
+ uint32_t m_width;
+ uint32_t n_width;
+ uint32_t p_width;
+ uint32_t p_shift;
+};
+
+struct clk_pll_def {
+ struct clknode_init_def clkdef;
+ enum pll_type type;
+ uint32_t base_reg;
+ uint32_t misc_reg;
+ uint32_t lock_mask;
+ uint32_t lock_enable;
+ uint32_t iddq_reg;
+ uint32_t iddq_mask;
+ uint32_t flags;
+ struct pdiv_table *pdiv_table;
+ struct mnp_bits mnp_bits;
+};
+
+#define PLL(_id, cname, pname) \
+ .clkdef.id = _id, \
+ .clkdef.name = cname, \
+ .clkdef.parent_names = (const char *[]){pname}, \
+ .clkdef.parent_cnt = 1, \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS
+
+/* Tegra K1 PLLs
+ PLLM: Clock source for EMC 2x clock
+ PLLX: Clock source for the fast CPU cluster and the shadow CPU
+ PLLC: Clock source for general use
+ PLLC2: Clock source for engine scaling
+ PLLC3: Clock source for engine scaling
+ PLLC4: Clock source for ISP/VI units
+ PLLP: Clock source for most peripherals
+ PLLA: Audio clock sources: (11.2896 MHz, 12.288 MHz, 24.576 MHz)
+ PLLU: Clock source for USB PHY, provides 12/60/480 MHz
+ PLLD: Clock sources for the DSI and display subsystem
+ PLLD2: Clock sources for the DSI and display subsystem
+ refPLLe:
+ PLLE: generate the 100 MHz reference clock for USB 3.0 (spread spectrum)
+ PLLDP: Clock source for eDP/LVDS (spread spectrum)
+
+ DFLLCPU: DFLL clock source for the fast CPU cluster
+ GPCPLL: Clock source for the GPU
+*/
+
+static struct pdiv_table pllm_map[] = {
+ {1, 0},
+ {2, 1},
+ {0, 0}
+};
+
+static struct pdiv_table pllxc_map[] = {
+ { 1, 0},
+ { 2, 1},
+ { 3, 2},
+ { 4, 3},
+ { 5, 4},
+ { 6, 5},
+ { 8, 6},
+ {10, 7},
+ {12, 8},
+ {16, 9},
+ {12, 10},
+ {16, 11},
+ {20, 12},
+ {24, 13},
+ {32, 14},
+ { 0, 0}
+};
+
+static struct pdiv_table pllc_map[] = {
+ { 1, 0},
+ { 2, 1},
+ { 3, 2},
+ { 4, 3},
+ { 6, 4},
+ { 8, 5},
+ {12, 6},
+ {16, 7},
+ { 0, 0}
+};
+
+static struct pdiv_table pll12g_ssd_esd_map[] = {
+ { 1, 0},
+ { 2, 1},
+ { 3, 2},
+ { 4, 3},
+ { 5, 4},
+ { 6, 5},
+ { 8, 6},
+ {10, 7},
+ {12, 8},
+ {16, 9},
+ {12, 10},
+ {16, 11},
+ {20, 12},
+ {24, 13},
+ {32, 14},
+ { 0, 0}
+};
+
+static struct pdiv_table pllu_map[] = {
+ {1, 1},
+ {2, 0},
+ {0, 0}
+};
+
+static struct clk_pll_def pll_clks[] = {
+/* PLLM: 880 MHz Clock source for EMC 2x clock */
+ {
+ PLL(TEGRA124_CLK_PLL_M, "pllM_out0", "osc_div_clk"),
+ .type = PLL_M,
+ .base_reg = PLLM_BASE,
+ .misc_reg = PLLM_MISC,
+ .lock_mask = PLL_BASE_LOCK,
+ .lock_enable = PLL_MISC_LOCK_ENABLE,
+ .pdiv_table = pllm_map,
+ .mnp_bits = {8, 8, 1, 20},
+ },
+/* PLLX: 1GHz Clock source for the fast CPU cluster and the shadow CPU */
+ {
+ PLL(TEGRA124_CLK_PLL_X, "pllX_out", "osc_div_clk"),
+ .type = PLL_X,
+ .base_reg = PLLX_BASE,
+ .misc_reg = PLLX_MISC,
+ .lock_mask = PLL_BASE_LOCK,
+ .lock_enable = PLL_MISC_LOCK_ENABLE,
+ .iddq_reg = PLLX_MISC3,
+ .iddq_mask = 1 << PLLX_IDDQ_BIT,
+ .pdiv_table = pllxc_map,
+ .mnp_bits = {8, 8, 4, 20},
+ },
+/* PLLC: 600 MHz Clock source for general use */
+ {
+ PLL(TEGRA124_CLK_PLL_C, "pllC_out0", "osc_div_clk"),
+ .type = PLL_C,
+ .base_reg = PLLC_BASE,
+ .misc_reg = PLLC_MISC,
+ .lock_mask = PLL_BASE_LOCK,
+ .lock_enable = PLLC_MISC_LOCK_ENABLE,
+ .iddq_reg = PLLC_MISC,
+ .iddq_mask = 1 << PLLC_IDDQ_BIT,
+ .pdiv_table = pllc_map,
+ .mnp_bits = {8, 8, 4, 20},
+ },
+/* PLLC2: 600 MHz Clock source for engine scaling */
+ {
+ PLL(TEGRA124_CLK_PLL_C2, "pllC2_out0", "osc_div_clk"),
+ .type = PLL_C2,
+ .base_reg = PLLC2_BASE,
+ .misc_reg = PLLC2_MISC,
+ .lock_mask = PLL_BASE_LOCK,
+ .lock_enable = PLL_MISC_LOCK_ENABLE,
+ .pdiv_table = pllc_map,
+ .mnp_bits = {2, 8, 3, 20},
+ },
+/* PLLC3: 600 MHz Clock source for engine scaling */
+ {
+ PLL(TEGRA124_CLK_PLL_C3, "pllC3_out0", "osc_div_clk"),
+ .type = PLL_C3,
+ .base_reg = PLLC3_BASE,
+ .misc_reg = PLLC3_MISC,
+ .lock_mask = PLL_BASE_LOCK,
+ .lock_enable = PLL_MISC_LOCK_ENABLE,
+ .pdiv_table = pllc_map,
+ .mnp_bits = {2, 8, 3, 20},
+ },
+/* PLLC4: 600 MHz Clock source for ISP/VI units */
+ {
+ PLL(TEGRA124_CLK_PLL_C4, "pllC4_out0", "pllC4_src"),
+ .type = PLL_C4,
+ .base_reg = PLLC4_BASE,
+ .misc_reg = PLLC4_MISC,
+ .lock_mask = PLL_BASE_LOCK,
+ .lock_enable = PLLSS_MISC_LOCK_ENABLE,
+ .iddq_reg = PLLC4_BASE,
+ .iddq_mask = 1 << PLLSS_IDDQ_BIT,
+ .pdiv_table = pll12g_ssd_esd_map,
+ .mnp_bits = {8, 8, 4, 20},
+ },
+/* PLLP: 408 MHz Clock source for most peripherals */
+ {
+ PLL(TEGRA124_CLK_PLL_P, "pllP_out0", "osc_div_clk"),
+ .type = PLL_P,
+ .base_reg = PLLP_BASE,
+ .misc_reg = PLLP_MISC,
+ .lock_mask = PLL_BASE_LOCK,
+ .lock_enable = PLL_MISC_LOCK_ENABLE,
+ .mnp_bits = {5, 10, 3, 20},
+ },
+/* PLLA: Audio clock sources: (11.2896 MHz, 12.288 MHz, 24.576 MHz) */
+ {
+ PLL(TEGRA124_CLK_PLL_A, "pllA_out", "pllP_out1"),
+ .type = PLL_A,
+ .base_reg = PLLA_BASE,
+ .misc_reg = PLLA_MISC,
+ .lock_mask = PLL_BASE_LOCK,
+ .lock_enable = PLL_MISC_LOCK_ENABLE,
+ .mnp_bits = {5, 10, 3, 20},
+ },
+/* PLLU: 480 MHz Clock source for USB PHY, provides 12/60/480 MHz */
+ {
+ PLL(TEGRA124_CLK_PLL_U, "pllU_out", "osc_div_clk"),
+ .type = PLL_U,
+ .base_reg = PLLU_BASE,
+ .misc_reg = PLLU_MISC,
+ .lock_mask = PLL_BASE_LOCK,
+ .lock_enable = PLLDU_MISC_LOCK_ENABLE,
+ .pdiv_table = pllu_map,
+ .mnp_bits = {5, 10, 1, 20},
+ },
+/* PLLD: 600 MHz Clock sources for the DSI and display subsystem */
+ {
+ PLL(TEGRA124_CLK_PLL_D, "pllD_out", "osc_div_clk"),
+ .type = PLL_D,
+ .base_reg = PLLD_BASE,
+ .misc_reg = PLLD_MISC,
+ .lock_mask = PLL_BASE_LOCK,
+ .lock_enable = PLL_MISC_LOCK_ENABLE,
+ .mnp_bits = {5, 11, 3, 20},
+ },
+/* PLLD2: 600 MHz Clock sources for the DSI and display subsystem */
+ {
+ PLL(TEGRA124_CLK_PLL_D2, "pllD2_out", "pllD2_src"),
+ .type = PLL_D2,
+ .base_reg = PLLD2_BASE,
+ .misc_reg = PLLD2_MISC,
+ .lock_mask = PLL_BASE_LOCK,
+ .lock_enable = PLLSS_MISC_LOCK_ENABLE,
+ .iddq_reg = PLLD2_BASE,
+ .iddq_mask = 1 << PLLSS_IDDQ_BIT,
+ .pdiv_table = pll12g_ssd_esd_map,
+ .mnp_bits = {8, 8, 4, 20},
+ },
+/* refPLLe: */
+ {
+ PLL(0, "pllREFE_out", "osc_div_clk"),
+ .type = PLL_REFE,
+ .base_reg = PLLRE_BASE,
+ .misc_reg = PLLRE_MISC,
+ .lock_mask = PLLRE_MISC_LOCK,
+ .lock_enable = PLLRE_MISC_LOCK_ENABLE,
+ .iddq_reg = PLLRE_MISC,
+ .iddq_mask = 1 << PLLRE_IDDQ_BIT,
+ .mnp_bits = {8, 8, 4, 16},
+ },
+/* PLLE: generate the 100 MHz reference clock for USB 3.0 (spread spectrum) */
+ {
+ PLL(TEGRA124_CLK_PLL_E, "pllE_out0", "pllE_src"),
+ .type = PLL_E,
+ .base_reg = PLLE_BASE,
+ .misc_reg = PLLE_MISC,
+ .lock_mask = PLLE_MISC_LOCK,
+ .lock_enable = PLLE_MISC_LOCK_ENABLE,
+ .mnp_bits = {8, 8, 4, 24},
+ },
+/* PLLDP: 600 MHz Clock source for eDP/LVDS (spread spectrum) */
+ {
+ PLL(0, "pllDP_out0", "pllDP_src"),
+ .type = PLL_DP,
+ .base_reg = PLLDP_BASE,
+ .misc_reg = PLLDP_MISC,
+ .lock_mask = PLL_BASE_LOCK,
+ .lock_enable = PLLSS_MISC_LOCK_ENABLE,
+ .iddq_reg = PLLDP_BASE,
+ .iddq_mask = 1 << PLLSS_IDDQ_BIT,
+ .pdiv_table = pll12g_ssd_esd_map,
+ .mnp_bits = {8, 8, 4, 20},
+ },
+};
+
+static int tegra124_pll_init(struct clknode *clk, device_t dev);
+static int tegra124_pll_set_gate(struct clknode *clk, bool enable);
+static int tegra124_pll_recalc(struct clknode *clk, uint64_t *freq);
+static int tegra124_pll_set_freq(struct clknode *clknode, uint64_t fin,
+ uint64_t *fout, int flags, int *stop);
+struct pll_sc {
+ device_t clkdev;
+ enum pll_type type;
+ uint32_t base_reg;
+ uint32_t misc_reg;
+ uint32_t lock_mask;
+ uint32_t lock_enable;
+ uint32_t iddq_reg;
+ uint32_t iddq_mask;
+ uint32_t flags;
+ struct pdiv_table *pdiv_table;
+ struct mnp_bits mnp_bits;
+};
+
+static clknode_method_t tegra124_pll_methods[] = {
+ /* Device interface */
+ CLKNODEMETHOD(clknode_init, tegra124_pll_init),
+ CLKNODEMETHOD(clknode_set_gate, tegra124_pll_set_gate),
+ CLKNODEMETHOD(clknode_recalc_freq, tegra124_pll_recalc),
+ CLKNODEMETHOD(clknode_set_freq, tegra124_pll_set_freq),
+ CLKNODEMETHOD_END
+};
+DEFINE_CLASS_1(tegra124_pll, tegra124_pll_class, tegra124_pll_methods,
+ sizeof(struct pll_sc), clknode_class);
+
+static int
+pll_enable(struct pll_sc *sc)
+{
+ uint32_t reg;
+
+
+ RD4(sc, sc->base_reg, &reg);
+ if (sc->type != PLL_E)
+ reg &= ~PLL_BASE_BYPASS;
+ reg |= PLL_BASE_ENABLE;
+ WR4(sc, sc->base_reg, reg);
+ return (0);
+}
+
+static int
+pll_disable(struct pll_sc *sc)
+{
+ uint32_t reg;
+
+ RD4(sc, sc->base_reg, &reg);
+ if (sc->type != PLL_E)
+ reg |= PLL_BASE_BYPASS;
+ reg &= ~PLL_BASE_ENABLE;
+ WR4(sc, sc->base_reg, reg);
+ return (0);
+}
+
+static uint32_t
+pdiv_to_reg(struct pll_sc *sc, uint32_t p_div)
+{
+ struct pdiv_table *tbl;
+
+ tbl = sc->pdiv_table;
+ if (tbl == NULL)
+ return (ffs(p_div));
+
+ while (tbl->divider != 0) {
+ if (p_div <= tbl->divider)
+ return (tbl->value);
+ tbl++;
+ }
+ return ~0;
+}
+
+static uint32_t
+reg_to_pdiv(struct pll_sc *sc, uint32_t reg)
+{
+ struct pdiv_table *tbl;
+
+ tbl = sc->pdiv_table;
+ if (tbl != NULL) {
+ while (tbl->divider) {
+ if (reg == tbl->value)
+ return (tbl->divider);
+ tbl++;
+ }
+ return (0);
+ }
+ return (1 << reg);
+}
+
+static uint32_t
+get_masked(uint32_t val, uint32_t shift, uint32_t width)
+{
+
+ return ((val >> shift) & ((1 << width) - 1));
+}
+
+static uint32_t
+set_masked(uint32_t val, uint32_t v, uint32_t shift, uint32_t width)
+{
+
+ val &= ~(((1 << width) - 1) << shift);
+ val |= (v & ((1 << width) - 1)) << shift;
+ return (val);
+}
+
+static void
+get_divisors(struct pll_sc *sc, uint32_t *m, uint32_t *n, uint32_t *p)
+{
+ uint32_t val;
+ struct mnp_bits *mnp_bits;
+
+ mnp_bits = &sc->mnp_bits;
+ RD4(sc, sc->base_reg, &val);
+ *m = get_masked(val, PLL_BASE_DIVM_SHIFT, mnp_bits->m_width);
+ *n = get_masked(val, PLL_BASE_DIVN_SHIFT, mnp_bits->n_width);
+ *p = get_masked(val, mnp_bits->p_shift, mnp_bits->p_width);
+}
+
+static uint32_t
+set_divisors(struct pll_sc *sc, uint32_t val, uint32_t m, uint32_t n,
+ uint32_t p)
+{
+ struct mnp_bits *mnp_bits;
+
+ mnp_bits = &sc->mnp_bits;
+ val = set_masked(val, m, PLL_BASE_DIVM_SHIFT, mnp_bits->m_width);
+ val = set_masked(val, n, PLL_BASE_DIVN_SHIFT, mnp_bits->n_width);
+ val = set_masked(val, p, mnp_bits->p_shift, mnp_bits->p_width);
+ return (val);
+}
+
+static bool
+is_locked(struct pll_sc *sc)
+{
+ uint32_t reg;
+
+ switch (sc->type) {
+ case PLL_REFE:
+ RD4(sc, sc->misc_reg, &reg);
+ reg &= PLLRE_MISC_LOCK;
+ break;
+
+ case PLL_E:
+ RD4(sc, sc->misc_reg, &reg);
+ reg &= PLLE_MISC_LOCK;
+ break;
+
+ default:
+ RD4(sc, sc->base_reg, &reg);
+ reg &= PLL_BASE_LOCK;
+ break;
+ }
+ return (reg != 0);
+}
+
+static int
+wait_for_lock(struct pll_sc *sc)
+{
+ int i;
+
+ for (i = PLL_LOCK_TIMEOUT / 10; i > 0; i--) {
+ if (is_locked(sc))
+ break;
+ DELAY(10);
+ }
+ if (i <= 0) {
+ printf("PLL lock timeout\n");
+ return (ETIMEDOUT);
+ }
+ return (0);
+}
+
+static int
+plle_enable(struct pll_sc *sc)
+{
+ uint32_t reg;
+ int rv;
+ struct mnp_bits *mnp_bits;
+ uint32_t pll_m = 1;
+ uint32_t pll_n = 200;
+ uint32_t pll_p = 13;
+ uint32_t pll_cml = 13;
+
+ mnp_bits = &sc->mnp_bits;
+
+
+ /* Disable lock override. */
+ RD4(sc, sc->base_reg, &reg);
+ reg &= ~PLLE_BASE_LOCK_OVERRIDE;
+ WR4(sc, sc->base_reg, reg);
+
+ RD4(sc, PLLE_AUX, &reg);
+ reg |= PLLE_AUX_ENABLE_SWCTL;
+ reg &= ~PLLE_AUX_SEQ_ENABLE;
+ WR4(sc, PLLE_AUX, reg);
+ DELAY(10);
+
+ RD4(sc, sc->misc_reg, &reg);
+ reg |= PLLE_MISC_LOCK_ENABLE;
+ reg |= PLLE_MISC_IDDQ_SWCTL;
+ reg &= ~PLLE_MISC_IDDQ_OVERRIDE_VALUE;
+ reg |= PLLE_MISC_PTS;
+ reg |= PLLE_MISC_VREG_BG_CTRL_MASK;
+ reg |= PLLE_MISC_VREG_CTRL_MASK;
+ WR4(sc, sc->misc_reg, reg);
+ DELAY(10);
+
+ RD4(sc, PLLE_SS_CNTL, &reg);
+ reg |= PLLE_SS_CNTL_DISABLE;
+ WR4(sc, PLLE_SS_CNTL, reg);
+
+ RD4(sc, sc->base_reg, &reg);
+ reg = set_divisors(sc, reg, pll_m, pll_n, pll_p);
+ reg &= ~(PLLE_BASE_DIVCML_MASK << PLLE_BASE_DIVCML_SHIFT);
+ reg |= pll_cml << PLLE_BASE_DIVCML_SHIFT;
+ WR4(sc, sc->base_reg, reg);
+ DELAY(10);
+
+ pll_enable(sc);
+ rv = wait_for_lock(sc);
+ if (rv != 0)
+ return (rv);
+
+ RD4(sc, PLLE_SS_CNTL, &reg);
+ reg &= ~PLLE_SS_CNTL_SSCCENTER;
+ reg &= ~PLLE_SS_CNTL_SSCINVERT;
+ reg &= ~PLLE_SS_CNTL_COEFFICIENTS_MASK;
+ reg |= PLLE_SS_CNTL_COEFFICIENTS_VAL;
+ WR4(sc, PLLE_SS_CNTL, reg);
+ reg &= ~PLLE_SS_CNTL_SSCBYP;
+ reg &= ~PLLE_SS_CNTL_BYPASS_SS;
+ WR4(sc, PLLE_SS_CNTL, reg);
+ DELAY(10);
+
+ reg &= ~PLLE_SS_CNTL_INTERP_RESET;
+ WR4(sc, PLLE_SS_CNTL, reg);
+ DELAY(10);
+
+ /* HW control of brick pll. */
+ RD4(sc, sc->misc_reg, &reg);
+ reg &= ~PLLE_MISC_IDDQ_SWCTL;
+ WR4(sc, sc->misc_reg, reg);
+
+ RD4(sc, PLLE_AUX, &reg);
+ reg |= PLLE_AUX_USE_LOCKDET;
+ reg |= PLLE_AUX_SEQ_START_STATE;
+ reg &= ~PLLE_AUX_ENABLE_SWCTL;
+ reg &= ~PLLE_AUX_SS_SWCTL;
+ WR4(sc, PLLE_AUX, reg);
+ reg |= PLLE_AUX_SEQ_START_STATE;
+ DELAY(10);
+ reg |= PLLE_AUX_SEQ_ENABLE;
+ WR4(sc, PLLE_AUX, reg);
+
+ RD4(sc, XUSBIO_PLL_CFG0, &reg);
+ reg |= XUSBIO_PLL_CFG0_PADPLL_USE_LOCKDET;
+ reg |= XUSBIO_PLL_CFG0_SEQ_START_STATE;
+ reg &= ~XUSBIO_PLL_CFG0_CLK_ENABLE_SWCTL;
+ reg &= ~XUSBIO_PLL_CFG0_PADPLL_RESET_SWCTL;
+ WR4(sc, XUSBIO_PLL_CFG0, reg);
+ DELAY(10);
+
+ reg |= XUSBIO_PLL_CFG0_SEQ_ENABLE;
+ WR4(sc, XUSBIO_PLL_CFG0, reg);
+
+
+ /* Enable HW control and unreset SATA PLL. */
+ RD4(sc, SATA_PLL_CFG0, &reg);
+ reg &= ~SATA_PLL_CFG0_PADPLL_RESET_SWCTL;
+ reg &= ~SATA_PLL_CFG0_PADPLL_RESET_OVERRIDE_VALUE;
+ reg |= SATA_PLL_CFG0_PADPLL_USE_LOCKDET;
+ reg &= ~SATA_PLL_CFG0_SEQ_IN_SWCTL;
+ reg &= ~SATA_PLL_CFG0_SEQ_RESET_INPUT_VALUE;
+ reg &= ~SATA_PLL_CFG0_SEQ_LANE_PD_INPUT_VALUE;
+ reg &= ~SATA_PLL_CFG0_SEQ_PADPLL_PD_INPUT_VALUE;
+ reg &= ~SATA_PLL_CFG0_SEQ_ENABLE;
+ reg |= SATA_PLL_CFG0_SEQ_START_STATE;
+ WR4(sc, SATA_PLL_CFG0, reg);
+ DELAY(10);
+ reg |= SATA_PLL_CFG0_SEQ_ENABLE;
+ WR4(sc, SATA_PLL_CFG0, reg);
+
+ /* Enable HW control of PCIe PLL. */
+ RD4(sc, PCIE_PLL_CFG0, &reg);
+ reg |= PCIE_PLL_CFG0_SEQ_ENABLE;
+ WR4(sc, PCIE_PLL_CFG0, reg);
+
+ return (0);
+}
+
+static int
+tegra124_pll_set_gate(struct clknode *clknode, bool enable)
+{
+ int rv;
+ struct pll_sc *sc;
+
+ sc = clknode_get_softc(clknode);
+ if (enable == 0) {
+ rv = pll_disable(sc);
+ return(rv);
+ }
+
+ if (sc->type == PLL_E)
+ rv = plle_enable(sc);
+ else
+ rv = pll_enable(sc);
+ return (rv);
+}
+
+static int
+pll_set_std(struct pll_sc *sc, uint64_t fin, uint64_t *fout, int flags,
+ uint32_t m, uint32_t n, uint32_t p)
+{
+ uint32_t reg;
+ struct mnp_bits *mnp_bits;
+ int rv;
+
+ mnp_bits = &sc->mnp_bits;
+ if (m >= (1 << mnp_bits->m_width))
+ return (ERANGE);
+ if (n >= (1 << mnp_bits->n_width))
+ return (ERANGE);
+ if (pdiv_to_reg(sc, p) >= (1 << mnp_bits->p_width))
+ return (ERANGE);
+
+ if (flags & CLK_SET_DRYRUN) {
+ if (((flags & (CLK_SET_ROUND_UP | CLK_SET_ROUND_DOWN)) == 0) &&
+ (*fout != (((fin / m) * n) /p)))
+ return (ERANGE);
+
+ *fout = ((fin / m) * n) /p;
+ return (0);
+ }
+
+ pll_disable(sc);
+
+ /* take pll out of IDDQ */
+ if (sc->iddq_reg != 0)
+ MD4(sc, sc->iddq_reg, sc->iddq_mask, 0);
+
+ RD4(sc, sc->base_reg, &reg);
+ reg = set_masked(reg, m, PLL_BASE_DIVM_SHIFT, mnp_bits->m_width);
+ reg = set_masked(reg, n, PLL_BASE_DIVN_SHIFT, mnp_bits->n_width);
+ reg = set_masked(reg, pdiv_to_reg(sc, p), mnp_bits->p_shift,
+ mnp_bits->p_width);
+ WR4(sc, sc->base_reg, reg);
+
+ /* Enable PLL. */
+ RD4(sc, sc->base_reg, &reg);
+ reg |= PLL_BASE_ENABLE;
+ WR4(sc, sc->base_reg, reg);
+
+ /* Enable lock detection. */
+ RD4(sc, sc->misc_reg, &reg);
+ reg |= sc->lock_enable;
+ WR4(sc, sc->misc_reg, reg);
+
+ rv = wait_for_lock(sc);
+ if (rv != 0) {
+ /* Disable PLL */
+ RD4(sc, sc->base_reg, &reg);
+ reg &= ~PLL_BASE_ENABLE;
+ WR4(sc, sc->base_reg, reg);
+ return (rv);
+ }
+ RD4(sc, sc->misc_reg, &reg);
+
+ pll_enable(sc);
+ *fout = ((fin / m) * n) / p;
+ return 0;
+}
+
+static int
+plla_set_freq(struct pll_sc *sc, uint64_t fin, uint64_t *fout, int flags)
+{
+ uint32_t m, n, p;
+
+ p = 1;
+ m = 5;
+ n = (*fout * p * m + fin / 2)/ fin;
+ dprintf("%s: m: %d, n: %d, p: %d\n", __func__, m, n, p);
+ return (pll_set_std(sc, fin, fout, flags, m, n, p));
+}
+
+static int
+pllc_set_freq(struct pll_sc *sc, uint64_t fin, uint64_t *fout, int flags)
+{
+ uint32_t m, n, p;
+
+
+ p = 2;
+ m = 1;
+ n = (*fout * p * m + fin / 2)/ fin;
+ dprintf("%s: m: %d, n: %d, p: %d\n", __func__, m, n, p);
+ return (pll_set_std( sc, fin, fout, flags, m, n, p));
+}
+
+static int
+plld2_set_freq(struct pll_sc *sc, uint64_t fin, uint64_t *fout, int flags)
+{
+ uint32_t m, n, p;
+
+ p = 2;
+ m = 1;
+ n = (*fout * p * m + fin / 2)/ fin;
+ dprintf("%s: m: %d, n: %d, p: %d\n", __func__, m, n, p);
+ return (pll_set_std(sc, fin, fout, flags, m, n, p));
+}
+
+
+
+static int
+pllrefe_set_freq(struct pll_sc *sc, uint64_t fin, uint64_t *fout, int flags)
+{
+ uint32_t m, n, p;
+
+ m = 1;
+ p = 1;
+ n = *fout * p * m / fin;
+ return (pll_set_std(sc, fin, fout, flags, m, n, p));
+}
+
+static int
+pllx_set_freq(struct pll_sc *sc, uint64_t fin, uint64_t *fout, int flags)
+{
+ uint32_t reg;
+ uint32_t m, n, p;
+ struct mnp_bits *mnp_bits;
+ int rv;
+
+ mnp_bits = &sc->mnp_bits;
+
+ p = 1;
+ m = 1;
+ n = (*fout * p * m + fin / 2)/ fin;
+ dprintf("%s: m: %d, n: %d, p: %d\n", __func__, m, n, p);
+
+ if (m >= (1 << mnp_bits->m_width))
+ return (ERANGE);
+ if (n >= (1 << mnp_bits->n_width))
+ return (ERANGE);
+ if (pdiv_to_reg(sc, p) >= (1 << mnp_bits->p_width))
+ return (ERANGE);
+
+ if (flags & CLK_SET_DRYRUN) {
+ if (((flags & (CLK_SET_ROUND_UP | CLK_SET_ROUND_DOWN)) == 0) &&
+ (*fout != (((fin / m) * n) /p)))
+ return (ERANGE);
+ *fout = ((fin / m) * n) /p;
+ return (0);
+ }
+
+ /* Set bypass. */
+ RD4(sc, sc->base_reg, &reg);
+ reg |= PLL_BASE_BYPASS;
+ WR4(sc, sc->base_reg, reg);
+ RD4(sc, sc->base_reg, &reg);
+ DELAY(100);
+
+ /* Set PLL. */
+ RD4(sc, sc->base_reg, &reg);
+ reg = set_masked(reg, m, PLL_BASE_DIVM_SHIFT, mnp_bits->m_width);
+ reg = set_masked(reg, n, PLL_BASE_DIVN_SHIFT, mnp_bits->n_width);
+ reg = set_masked(reg, pdiv_to_reg(sc, p), mnp_bits->p_shift,
+ mnp_bits->p_width);
+ WR4(sc, sc->base_reg, reg);
+ RD4(sc, sc->base_reg, &reg);
+ DELAY(100);
+
+ /* Enable PLL. */
+ RD4(sc, sc->base_reg, &reg);
+ reg |= PLL_BASE_ENABLE;
+ WR4(sc, sc->base_reg, reg);
+
+ /* Enable lock detection */
+ RD4(sc, sc->misc_reg, &reg);
+ reg |= sc->lock_enable;
+ WR4(sc, sc->misc_reg, reg);
+
+ rv = wait_for_lock(sc);
+ if (rv != 0) {
+ /* Disable PLL */
+ RD4(sc, sc->base_reg, &reg);
+ reg &= ~PLL_BASE_ENABLE;
+ WR4(sc, sc->base_reg, reg);
+ return (rv);
+ }
+ RD4(sc, sc->misc_reg, &reg);
+
+ /* Clear bypass. */
+ RD4(sc, sc->base_reg, &reg);
+ reg &= ~PLL_BASE_BYPASS;
+ WR4(sc, sc->base_reg, reg);
+ *fout = ((fin / m) * n) / p;
+ return (0);
+}
+
+static int
+tegra124_pll_set_freq(struct clknode *clknode, uint64_t fin, uint64_t *fout,
+ int flags, int *stop)
+{
+ *stop = 1;
+ int rv;
+ struct pll_sc *sc;
+
+ sc = clknode_get_softc(clknode);
+ dprintf("%s: Requested freq: %llu, input freq: %llu\n", __func__,
+ *fout, fin);
+ switch (sc->type) {
+ case PLL_A:
+ rv = plla_set_freq(sc, fin, fout, flags);
+ break;
+ case PLL_C:
+ rv = pllc_set_freq(sc, fin, fout, flags);
+ break;
+ case PLL_D2:
+ rv = plld2_set_freq(sc, fin, fout, flags);
+ break;
+
+ case PLL_REFE:
+ rv = pllrefe_set_freq(sc, fin, fout, flags);
+ break;
+
+ case PLL_X:
+ rv = pllx_set_freq(sc, fin, fout, flags);
+ break;
+
+ case PLL_U:
+ if (*fout == 480000000) /* PLLU is fixed to 480 MHz */
+ rv = 0;
+ else
+ rv = ERANGE;
+ break;
+ default:
+ rv = ENXIO;
+ break;
+ }
+ return (rv);
+}
+
+
+static int
+tegra124_pll_init(struct clknode *clk, device_t dev)
+{
+ struct pll_sc *sc;
+ uint32_t reg;
+
+ sc = clknode_get_softc(clk);
+
+ /* If PLL is enabled, enable lock detect too. */
+ RD4(sc, sc->base_reg, &reg);
+ if (reg & PLL_BASE_ENABLE) {
+ RD4(sc, sc->misc_reg, &reg);
+ reg |= sc->lock_enable;
+ WR4(sc, sc->misc_reg, reg);
+ }
+
+ clknode_init_parent_idx(clk, 0);
+ return(0);
+}
+
+static int
+tegra124_pll_recalc(struct clknode *clk, uint64_t *freq)
+{
+ struct pll_sc *sc;
+ uint32_t m, n, p, pr;
+ uint32_t reg, misc_reg;
+ int locked;
+
+ sc = clknode_get_softc(clk);
+
+ RD4(sc, sc->base_reg, &reg);
+ RD4(sc, sc->misc_reg, &misc_reg);
+
+ get_divisors(sc, &m, &n, &pr);
+ if (sc->type != PLL_E)
+ p = reg_to_pdiv(sc, pr);
+ else
+ p = 2 * (pr - 1);
+ locked = is_locked(sc);
+
+ dprintf("%s: %s (0x%08x, 0x%08x) - m: %d, n: %d, p: %d (%d): "
+ "e: %d, r: %d, o: %d - %s\n", __func__,
+ clknode_get_name(clk), reg, misc_reg, m, n, p, pr,
+ (reg >> 30) & 1, (reg >> 29) & 1, (reg >> 28) & 1,
+ locked ? "locked" : "unlocked");
+
+ if ((m == 0) || (n == 0) || (p == 0)) {
+ *freq = 0;
+ return (EINVAL);
+ }
+ *freq = ((*freq / m) * n) / p;
+ return (0);
+}
+
+static int
+pll_register(struct clkdom *clkdom, struct clk_pll_def *clkdef)
+{
+ struct clknode *clk;
+ struct pll_sc *sc;
+
+ clk = clknode_create(clkdom, &tegra124_pll_class, &clkdef->clkdef);
+ if (clk == NULL)
+ return (ENXIO);
+
+ sc = clknode_get_softc(clk);
+ sc->clkdev = clknode_get_device(clk);
+ sc->type = clkdef->type;
+ sc->base_reg = clkdef->base_reg;
+ sc->misc_reg = clkdef->misc_reg;
+ sc->lock_mask = clkdef->lock_mask;
+ sc->lock_enable = clkdef->lock_enable;
+ sc->iddq_reg = clkdef->iddq_reg;
+ sc->iddq_mask = clkdef->iddq_mask;
+ sc->flags = clkdef->flags;
+ sc->pdiv_table = clkdef->pdiv_table;
+ sc->mnp_bits = clkdef->mnp_bits;
+ clknode_register(clkdom, clk);
+ return (0);
+}
+
+static void config_utmi_pll(struct tegra124_car_softc *sc)
+{
+ uint32_t reg;
+ /*
+ * XXX Simplified UTMIP settings for 12MHz base clock.
+ */
+#define ENABLE_DELAY_COUNT 0x02
+#define STABLE_COUNT 0x2F
+#define ACTIVE_DELAY_COUNT 0x04
+#define XTAL_FREQ_COUNT 0x76
+
+ CLKDEV_READ_4(sc->dev, UTMIP_PLL_CFG2, &reg);
+ reg &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0);
+ reg |= UTMIP_PLL_CFG2_STABLE_COUNT(STABLE_COUNT);
+ reg &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0);
+ reg |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(ACTIVE_DELAY_COUNT);
+ reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN;
+ reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN;
+ reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN;
+ CLKDEV_WRITE_4(sc->dev, UTMIP_PLL_CFG2, reg);
+
+ CLKDEV_READ_4(sc->dev, UTMIP_PLL_CFG1, &reg);
+ reg &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0);
+ reg |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(ENABLE_DELAY_COUNT);
+ reg &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0);
+ reg |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(XTAL_FREQ_COUNT);
+ reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
+ reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN;
+ reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP;
+ reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN;
+ CLKDEV_WRITE_4(sc->dev, UTMIP_PLL_CFG1, reg);
+
+ /* Prepare UTMIP requencer. */
+ CLKDEV_READ_4(sc->dev, UTMIPLL_HW_PWRDN_CFG0, &reg);
+ reg |= UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET;
+ reg &= ~UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL;
+ reg |= UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE;
+ CLKDEV_WRITE_4(sc->dev, UTMIPLL_HW_PWRDN_CFG0, reg);
+
+ /* Powerup UTMIP. */
+ CLKDEV_READ_4(sc->dev, UTMIP_PLL_CFG1, &reg);
+ reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP;
+ reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
+ CLKDEV_WRITE_4(sc->dev, UTMIP_PLL_CFG1, reg);
+ DELAY(10);
+
+ /* SW override for UTMIPLL */
+ CLKDEV_READ_4(sc->dev, UTMIPLL_HW_PWRDN_CFG0, &reg);
+ reg |= UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL;
+ reg &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE;
+ CLKDEV_WRITE_4(sc->dev, UTMIPLL_HW_PWRDN_CFG0, reg);
+ DELAY(10);
+
+ /* HW control of UTMIPLL. */
+ CLKDEV_READ_4(sc->dev, UTMIPLL_HW_PWRDN_CFG0, &reg);
+ reg |= UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE;
+ CLKDEV_WRITE_4(sc->dev, UTMIPLL_HW_PWRDN_CFG0, reg);
+}
+
+void
+tegra124_init_plls(struct tegra124_car_softc *sc)
+{
+ int i, rv;
+
+ for (i = 0; i < nitems(pll_clks); i++) {
+ rv = pll_register(sc->clkdom, pll_clks + i);
+ if (rv != 0)
+ panic("pll_register failed");
+ }
+ config_utmi_pll(sc);
+
+}
diff --git a/sys/arm/nvidia/tegra124/tegra124_clk_super.c b/sys/arm/nvidia/tegra124/tegra124_clk_super.c
new file mode 100644
index 0000000..7f32eba
--- /dev/null
+++ b/sys/arm/nvidia/tegra124/tegra124_clk_super.c
@@ -0,0 +1,265 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+
+#include <dev/extres/clk/clk.h>
+
+#include <gnu/dts/include/dt-bindings/clock/tegra124-car.h>
+#include "tegra124_car.h"
+
+
+/* Flags */
+#define SMF_HAVE_DIVIDER_2 1
+
+struct super_mux_def {
+ struct clknode_init_def clkdef;
+ uint32_t base_reg;
+ uint32_t flags;
+ int src_pllx;
+ int src_div2;
+};
+
+#define PLIST(x) static const char *x[]
+#define SM(_id, cn, pl, r, x, d, f) \
+{ \
+ .clkdef.id = _id, \
+ .clkdef.name = cn, \
+ .clkdef.parent_names = pl, \
+ .clkdef.parent_cnt = nitems(pl), \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
+ .base_reg = r, \
+ .src_pllx = x, \
+ .src_div2 = d, \
+ .flags = f, \
+}
+
+PLIST(cclk_g_parents) = {
+ "clk_m", "pllC_out0", "clk_s", "pllM_out0",
+ "pllP_out0", "pllP_out4", "pllC2_out0", "pllC3_out0",
+ "pllX_out", NULL, NULL, NULL,
+ NULL, NULL, NULL,NULL, // "dfllCPU_out0"
+};
+
+PLIST(cclk_lp_parents) = {
+ "clk_m", "pllC_out0", "clk_s", "pllM_out0",
+ "pllP_out0", "pllP_out4", "pllC2_out0", "pllC3_out0",
+ "pllX_out", NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
+ "pllX_out0"
+};
+
+PLIST(sclk_parents) = {
+ "clk_m", "pllC_out1", "pllP_out4", "pllP_out0",
+ "pllP_out2", "pllC_out0", "clk_s", "pllM_out1",
+};
+
+static struct super_mux_def super_mux_def[] = {
+ SM(TEGRA124_CLK_CCLK_G, "cclk_g", cclk_g_parents, CCLKG_BURST_POLICY, 0, 0, 0),
+ SM(TEGRA124_CLK_CCLK_LP, "cclk_lp", cclk_lp_parents, CCLKLP_BURST_POLICY, 8, 16, SMF_HAVE_DIVIDER_2),
+ SM(TEGRA124_CLK_SCLK, "sclk", sclk_parents, SCLK_BURST_POLICY, 0, 0, 0),
+};
+
+static int super_mux_init(struct clknode *clk, device_t dev);
+static int super_mux_set_mux(struct clknode *clk, int idx);
+
+struct super_mux_sc {
+ device_t clkdev;
+ uint32_t base_reg;
+ int src_pllx;
+ int src_div2;
+ uint32_t flags;
+
+ int mux;
+};
+
+static clknode_method_t super_mux_methods[] = {
+ /* Device interface */
+ CLKNODEMETHOD(clknode_init, super_mux_init),
+ CLKNODEMETHOD(clknode_set_mux, super_mux_set_mux),
+ CLKNODEMETHOD_END
+};
+DEFINE_CLASS_1(tegra124_super_mux, tegra124_super_mux_class, super_mux_methods,
+ sizeof(struct super_mux_sc), clknode_class);
+
+/* Mux status. */
+#define SUPER_MUX_STATE_STDBY 0
+#define SUPER_MUX_STATE_IDLE 1
+#define SUPER_MUX_STATE_RUN 2
+#define SUPER_MUX_STATE_IRQ 3
+#define SUPER_MUX_STATE_FIQ 4
+
+/* Mux register bits. */
+#define SUPER_MUX_STATE_BIT_SHIFT 28
+#define SUPER_MUX_STATE_BIT_MASK 0xF
+/* State is Priority encoded */
+#define SUPER_MUX_STATE_BIT_STDBY 0x00
+#define SUPER_MUX_STATE_BIT_IDLE 0x01
+#define SUPER_MUX_STATE_BIT_RUN 0x02
+#define SUPER_MUX_STATE_BIT_IRQ 0x04
+#define SUPER_MUX_STATE_BIT_FIQ 0x08
+
+#define SUPER_MUX_MUX_WIDTH 4
+#define SUPER_MUX_LP_DIV2_BYPASS (1 << 16)
+
+static uint32_t
+super_mux_get_state(uint32_t reg)
+{
+ reg = (reg >> SUPER_MUX_STATE_BIT_SHIFT) & SUPER_MUX_STATE_BIT_MASK;
+ if (reg & SUPER_MUX_STATE_BIT_FIQ)
+ return (SUPER_MUX_STATE_FIQ);
+ if (reg & SUPER_MUX_STATE_BIT_IRQ)
+ return (SUPER_MUX_STATE_IRQ);
+ if (reg & SUPER_MUX_STATE_BIT_RUN)
+ return (SUPER_MUX_STATE_RUN);
+ if (reg & SUPER_MUX_STATE_BIT_IDLE)
+ return (SUPER_MUX_STATE_IDLE);
+ return (SUPER_MUX_STATE_STDBY);
+}
+
+static int
+super_mux_init(struct clknode *clk, device_t dev)
+{
+ struct super_mux_sc *sc;
+ uint32_t reg;
+ int shift, state;
+
+ sc = clknode_get_softc(clk);
+
+ DEVICE_LOCK(sc);
+ RD4(sc, sc->base_reg, &reg);
+ DEVICE_UNLOCK(sc);
+ state = super_mux_get_state(reg);
+
+ if ((state != SUPER_MUX_STATE_RUN) &&
+ (state != SUPER_MUX_STATE_IDLE)) {
+ panic("Unexpected super mux state: %u", state);
+ }
+
+ shift = state * SUPER_MUX_MUX_WIDTH;
+
+ sc->mux = (reg >> shift) & ((1 << SUPER_MUX_MUX_WIDTH) - 1);
+
+ /*
+ * CCLKLP uses PLLX/2 as source if LP_DIV2_BYPASS isn't set
+ * and source mux is set to PLLX.
+ */
+ if (sc->flags & SMF_HAVE_DIVIDER_2) {
+ if (((reg & SUPER_MUX_LP_DIV2_BYPASS) == 0) &&
+ (sc->mux == sc->src_pllx))
+ sc->mux = sc->src_div2;
+ }
+ clknode_init_parent_idx(clk, sc->mux);
+
+ return(0);
+}
+
+static int
+super_mux_set_mux(struct clknode *clk, int idx)
+{
+
+ struct super_mux_sc *sc;
+ int shift, state;
+ uint32_t reg, dummy;
+
+ sc = clknode_get_softc(clk);
+
+ DEVICE_LOCK(sc);
+ RD4(sc, sc->base_reg, &reg);
+ state = super_mux_get_state(reg);
+
+ if ((state != SUPER_MUX_STATE_RUN) &&
+ (state != SUPER_MUX_STATE_IDLE)) {
+ panic("Unexpected super mux state: %u", state);
+ }
+
+ shift = state * SUPER_MUX_MUX_WIDTH;
+ sc->mux = idx;
+ if (sc->flags & SMF_HAVE_DIVIDER_2) {
+ if (idx == sc->src_div2) {
+ idx = sc->src_pllx;
+ reg &= ~SUPER_MUX_LP_DIV2_BYPASS;
+ WR4(sc, sc->base_reg, reg);
+ RD4(sc, sc->base_reg, &dummy);
+ } else if (idx == sc->src_pllx) {
+ reg = SUPER_MUX_LP_DIV2_BYPASS;
+ WR4(sc, sc->base_reg, reg);
+ RD4(sc, sc->base_reg, &dummy);
+ }
+ }
+ reg &= ~(((1 << SUPER_MUX_MUX_WIDTH) - 1) << shift);
+ reg |= idx << shift;
+ WR4(sc, sc->base_reg, reg);
+ RD4(sc, sc->base_reg, &dummy);
+ DEVICE_UNLOCK(sc);
+
+ return(0);
+}
+
+static int
+super_mux_register(struct clkdom *clkdom, struct super_mux_def *clkdef)
+{
+ struct clknode *clk;
+ struct super_mux_sc *sc;
+
+ clk = clknode_create(clkdom, &tegra124_super_mux_class,
+ &clkdef->clkdef);
+ if (clk == NULL)
+ return (1);
+
+ sc = clknode_get_softc(clk);
+ sc->clkdev = clknode_get_device(clk);
+ sc->base_reg = clkdef->base_reg;
+ sc->src_pllx = clkdef->src_pllx;
+ sc->src_div2 = clkdef->src_div2;
+ sc->flags = clkdef->flags;
+
+ clknode_register(clkdom, clk);
+ return (0);
+}
+
+void
+tegra124_super_mux_clock(struct tegra124_car_softc *sc)
+{
+ int i, rv;
+
+ for (i = 0; i < nitems(super_mux_def); i++) {
+ rv = super_mux_register(sc->clkdom, &super_mux_def[i]);
+ if (rv != 0)
+ panic("super_mux_register failed");
+ }
+
+}
diff --git a/sys/arm/nvidia/tegra124/tegra124_coretemp.c b/sys/arm/nvidia/tegra124/tegra124_coretemp.c
new file mode 100644
index 0000000..c29fe8e
--- /dev/null
+++ b/sys/arm/nvidia/tegra124/tegra124_coretemp.c
@@ -0,0 +1,273 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/cpu.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/sysctl.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+
+#include <dev/extres/clk/clk.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "tegra_soctherm_if.h"
+
+
+enum therm_info {
+ CORETEMP_TEMP,
+ CORETEMP_DELTA,
+ CORETEMP_RESOLUTION,
+ CORETEMP_TJMAX,
+};
+
+struct tegra124_coretemp_softc {
+ device_t dev;
+ int overheat_log;
+ int core_max_temp;
+ int cpu_id;
+ device_t tsens_dev;
+ intptr_t tsens_id;
+};
+
+static int
+coretemp_get_val_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ device_t dev;
+ int val, temp, rv;
+ struct tegra124_coretemp_softc *sc;
+ enum therm_info type;
+ char stemp[16];
+
+
+ dev = (device_t) arg1;
+ sc = device_get_softc(dev);
+ type = arg2;
+
+
+ rv = TEGRA_SOCTHERM_GET_TEMPERATURE(sc->tsens_dev, sc->dev,
+ sc->tsens_id, &temp);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot read temperature sensor %d: %d\n",
+ sc->tsens_id, rv);
+ return (rv);
+ }
+
+ switch (type) {
+ case CORETEMP_TEMP:
+ val = temp / 100;
+ val += 2731;
+ break;
+ case CORETEMP_DELTA:
+ val = (sc->core_max_temp - temp) / 1000;
+ break;
+ case CORETEMP_RESOLUTION:
+ val = 1;
+ break;
+ case CORETEMP_TJMAX:
+ val = sc->core_max_temp / 100;
+ val += 2731;
+ break;
+ }
+
+
+ if ((temp > sc->core_max_temp) && !sc->overheat_log) {
+ sc->overheat_log = 1;
+
+ /*
+ * Check for Critical Temperature Status and Critical
+ * Temperature Log. It doesn't really matter if the
+ * current temperature is invalid because the "Critical
+ * Temperature Log" bit will tell us if the Critical
+ * Temperature has * been reached in past. It's not
+ * directly related to the current temperature.
+ *
+ * If we reach a critical level, allow devctl(4)
+ * to catch this and shutdown the system.
+ */
+ device_printf(dev, "critical temperature detected, "
+ "suggest system shutdown\n");
+ snprintf(stemp, sizeof(stemp), "%d", val);
+ devctl_notify("coretemp", "Thermal", stemp,
+ "notify=0xcc");
+ } else {
+ sc->overheat_log = 0;
+ }
+
+ return (sysctl_handle_int(oidp, 0, val, req));
+}
+
+static int
+tegra124_coretemp_ofw_parse(struct tegra124_coretemp_softc *sc)
+{
+ int rv, ncells;
+ phandle_t node, xnode;
+ pcell_t *cells;
+
+ node = OF_peer(0);
+ node = ofw_bus_find_child(node, "thermal-zones");
+ if (node <= 0) {
+ device_printf(sc->dev, "Cannot find 'thermal-zones'.\n");
+ return (ENXIO);
+ }
+
+ node = ofw_bus_find_child(node, "cpu");
+ if (node <= 0) {
+ device_printf(sc->dev, "Cannot find 'cpu'\n");
+ return (ENXIO);
+ }
+ rv = ofw_bus_parse_xref_list_alloc(node, "thermal-sensors",
+ "#thermal-sensor-cells", 0, &xnode, &ncells, &cells);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot parse 'thermal-sensors' property.\n");
+ return (ENXIO);
+ }
+ if (ncells != 1) {
+ device_printf(sc->dev,
+ "Invalid format of 'thermal-sensors' property(%d).\n",
+ ncells);
+ return (ENXIO);
+ }
+
+ sc->tsens_id = 0x100 + sc->cpu_id; //cells[0];
+ free(cells, M_OFWPROP);
+
+ sc->tsens_dev = OF_device_from_xref(xnode);
+ if (sc->tsens_dev == NULL) {
+ device_printf(sc->dev,
+ "Cannot find thermal sensors device.");
+ return (ENXIO);
+ }
+ return (0);
+}
+
+static void
+tegra124_coretemp_identify(driver_t *driver, device_t parent)
+{
+
+ if (device_find_child(parent, "tegra124_coretemp", -1) != NULL)
+ return;
+ if (BUS_ADD_CHILD(parent, 0, "tegra124_coretemp", -1) == NULL)
+ device_printf(parent, "add child failed\n");
+}
+
+static int
+tegra124_coretemp_probe(device_t dev)
+{
+
+ device_set_desc(dev, "CPU Frequency Control");
+ return (0);
+}
+
+static int
+tegra124_coretemp_attach(device_t dev)
+{
+ struct tegra124_coretemp_softc *sc;
+ device_t pdev;
+ struct sysctl_oid *oid;
+ struct sysctl_ctx_list *ctx;
+ int rv;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ sc->cpu_id = device_get_unit(dev);
+ sc->core_max_temp = 102000;
+ pdev = device_get_parent(dev);
+
+ rv = tegra124_coretemp_ofw_parse(sc);
+ if (rv != 0)
+ return (rv);
+
+ ctx = device_get_sysctl_ctx(dev);
+
+ oid = SYSCTL_ADD_NODE(ctx,
+ SYSCTL_CHILDREN(device_get_sysctl_tree(pdev)), OID_AUTO,
+ "coretemp", CTLFLAG_RD, NULL, "Per-CPU thermal information");
+
+ /*
+ * Add the MIBs to dev.cpu.N and dev.cpu.N.coretemp.
+ */
+ SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(device_get_sysctl_tree(pdev)),
+ OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ dev, CORETEMP_TEMP, coretemp_get_val_sysctl, "IK",
+ "Current temperature");
+ SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "delta",
+ CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, CORETEMP_DELTA,
+ coretemp_get_val_sysctl, "I",
+ "Delta between TCC activation and current temperature");
+ SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "resolution",
+ CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, CORETEMP_RESOLUTION,
+ coretemp_get_val_sysctl, "I",
+ "Resolution of CPU thermal sensor");
+ SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "tjmax",
+ CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, CORETEMP_TJMAX,
+ coretemp_get_val_sysctl, "IK",
+ "TCC activation temperature");
+
+ return (0);
+}
+
+static int
+tegra124_coretemp_detach(device_t dev)
+{
+ struct tegra124_coretemp_softc *sc;
+
+ sc = device_get_softc(dev);
+ return (0);
+}
+
+
+static device_method_t tegra124_coretemp_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_identify, tegra124_coretemp_identify),
+ DEVMETHOD(device_probe, tegra124_coretemp_probe),
+ DEVMETHOD(device_attach, tegra124_coretemp_attach),
+ DEVMETHOD(device_detach, tegra124_coretemp_detach),
+
+
+ DEVMETHOD_END
+};
+
+static devclass_t tegra124_coretemp_devclass;
+static driver_t tegra124_coretemp_driver = {
+ "tegra124_coretemp",
+ tegra124_coretemp_methods,
+ sizeof(struct tegra124_coretemp_softc),
+};
+
+DRIVER_MODULE(tegra124_coretemp, cpu, tegra124_coretemp_driver,
+ tegra124_coretemp_devclass, 0, 0);
diff --git a/sys/arm/nvidia/tegra124/tegra124_cpufreq.c b/sys/arm/nvidia/tegra124/tegra124_cpufreq.c
new file mode 100644
index 0000000..1227c81
--- /dev/null
+++ b/sys/arm/nvidia/tegra124/tegra124_cpufreq.c
@@ -0,0 +1,583 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/cpu.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+
+#include <machine/bus.h>
+#include <machine/cpu.h>
+
+#include <dev/extres/clk/clk.h>
+#include <dev/extres/regulator/regulator.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/nvidia/tegra_efuse.h>
+
+#include "cpufreq_if.h"
+
+#define XXX
+
+/* CPU voltage table entry */
+struct speedo_entry {
+ uint64_t freq; /* Frequency point */
+ int c0; /* Coeeficient values for */
+ int c1; /* quadratic equation: */
+ int c2; /* c2 * speedo^2 + c1 * speedo + c0 */
+};
+
+struct cpu_volt_def {
+ int min_uvolt; /* Min allowed CPU voltage */
+ int max_uvolt; /* Max allowed CPU voltage */
+ int step_uvolt; /* Step of CPU voltage */
+ int speedo_scale; /* Scaling factor for cvt */
+ int speedo_nitems; /* Size of speedo table */
+ struct speedo_entry *speedo_tbl; /* CPU voltage table */
+};
+
+struct cpu_speed_point {
+ uint64_t freq; /* Frequecy */
+ int uvolt; /* Requested voltage */
+};
+
+static struct speedo_entry tegra124_speedo_dpll_tbl[] =
+{
+ { 204000000ULL, 1112619, -29295, 402},
+ { 306000000ULL, 1150460, -30585, 402},
+ { 408000000ULL, 1190122, -31865, 402},
+ { 510000000ULL, 1231606, -33155, 402},
+ { 612000000ULL, 1274912, -34435, 402},
+ { 714000000ULL, 1320040, -35725, 402},
+ { 816000000ULL, 1366990, -37005, 402},
+ { 918000000ULL, 1415762, -38295, 402},
+ {1020000000ULL, 1466355, -39575, 402},
+ {1122000000ULL, 1518771, -40865, 402},
+ {1224000000ULL, 1573009, -42145, 402},
+ {1326000000ULL, 1629068, -43435, 402},
+ {1428000000ULL, 1686950, -44715, 402},
+ {1530000000ULL, 1746653, -46005, 402},
+ {1632000000ULL, 1808179, -47285, 402},
+ {1734000000ULL, 1871526, -48575, 402},
+ {1836000000ULL, 1936696, -49855, 402},
+ {1938000000ULL, 2003687, -51145, 402},
+ {2014500000ULL, 2054787, -52095, 402},
+ {2116500000ULL, 2124957, -53385, 402},
+ {2218500000ULL, 2196950, -54665, 402},
+ {2320500000ULL, 2270765, -55955, 402},
+ {2320500000ULL, 2270765, -55955, 402},
+ {2422500000ULL, 2346401, -57235, 402},
+ {2524500000ULL, 2437299, -58535, 402},
+};
+
+static struct cpu_volt_def tegra124_cpu_volt_dpll_def =
+{
+ .min_uvolt = 900000, /* 0.9 V */
+ .max_uvolt = 1260000, /* 1.26 */
+ .step_uvolt = 10000, /* 10 mV */
+ .speedo_scale = 100,
+ .speedo_nitems = nitems(tegra124_speedo_dpll_tbl),
+ .speedo_tbl = tegra124_speedo_dpll_tbl,
+};
+
+static struct speedo_entry tegra124_speedo_pllx_tbl[] =
+{
+ { 204000000ULL, 800000, 0, 0},
+ { 306000000ULL, 800000, 0, 0},
+ { 408000000ULL, 800000, 0, 0},
+ { 510000000ULL, 800000, 0, 0},
+ { 612000000ULL, 800000, 0, 0},
+ { 714000000ULL, 800000, 0, 0},
+ { 816000000ULL, 820000, 0, 0},
+ { 918000000ULL, 840000, 0, 0},
+ {1020000000ULL, 880000, 0, 0},
+ {1122000000ULL, 900000, 0, 0},
+ {1224000000ULL, 930000, 0, 0},
+ {1326000000ULL, 960000, 0, 0},
+ {1428000000ULL, 990000, 0, 0},
+ {1530000000ULL, 1020000, 0, 0},
+ {1632000000ULL, 1070000, 0, 0},
+ {1734000000ULL, 1100000, 0, 0},
+ {1836000000ULL, 1140000, 0, 0},
+ {1938000000ULL, 1180000, 0, 0},
+ {2014500000ULL, 1220000, 0, 0},
+ {2116500000ULL, 1260000, 0, 0},
+ {2218500000ULL, 1310000, 0, 0},
+ {2320500000ULL, 1360000, 0, 0},
+ {2397000000ULL, 1400000, 0, 0},
+ {2499000000ULL, 1400000, 0, 0},
+};
+
+
+static struct cpu_volt_def tegra124_cpu_volt_pllx_def =
+{
+ .min_uvolt = 900000, /* 0.9 V */
+ .max_uvolt = 1260000, /* 1.26 */
+ .step_uvolt = 10000, /* 10 mV */
+ .speedo_scale = 100,
+ .speedo_nitems = nitems(tegra124_speedo_pllx_tbl),
+ .speedo_tbl = tegra124_speedo_pllx_tbl,
+};
+
+static uint64_t cpu_freq_tbl[] = {
+ 204000000ULL,
+ 306000000ULL,
+ 408000000ULL,
+ 510000000ULL,
+ 612000000ULL,
+ 714000000ULL,
+ 816000000ULL,
+ 918000000ULL,
+ 1020000000ULL,
+ 1122000000ULL,
+ 1224000000ULL,
+ 1326000000ULL,
+ 1428000000ULL,
+ 1530000000ULL,
+ 1632000000ULL,
+ 1734000000ULL,
+ 1836000000ULL,
+ 1938000000ULL,
+ 2014000000ULL,
+ 2116000000ULL,
+ 2218000000ULL,
+ 2320000000ULL,
+ 2320000000ULL,
+ 2422000000ULL,
+ 2524000000ULL,
+};
+
+static uint64_t cpu_max_freq[] = {
+ 2014500000ULL,
+ 2320500000ULL,
+ 2116500000ULL,
+ 2524500000ULL,
+};
+
+struct tegra124_cpufreq_softc {
+ device_t dev;
+ phandle_t node;
+
+ regulator_t supply_vdd_cpu;
+ clk_t clk_cpu_g;
+ clk_t clk_cpu_lp;
+ clk_t clk_pll_x;
+ clk_t clk_pll_p;
+ clk_t clk_dfll;
+
+ int process_id;
+ int speedo_id;
+ int speedo_value;
+
+ uint64_t cpu_max_freq;
+ struct cpu_volt_def *cpu_def;
+ struct cpu_speed_point *speed_points;
+ int nspeed_points;
+
+ struct cpu_speed_point *act_speed_point;
+
+ int latency;
+};
+
+static int cpufreq_lowest_freq = 1;
+TUNABLE_INT("hw.tegra124.cpufreq.lowest_freq", &cpufreq_lowest_freq);
+
+#define DIV_ROUND_CLOSEST(val, div) (((val) + ((div) / 2)) / (div))
+
+#define ROUND_UP(val, div) ((((val) + ((div) - 1)) / (div)) * (div))
+#define ROUND_DOWN(val, div) (((val) / (div)) * (div))
+
+/*
+ * Compute requesetd voltage for given frequency and SoC process variations,
+ * - compute base voltage from speedo value using speedo table
+ * - round up voltage to next regulator step
+ * - clamp it to regulator limits
+ */
+static int
+freq_to_voltage(struct tegra124_cpufreq_softc *sc, uint64_t freq)
+{
+ int uv, scale, min_uvolt, max_uvolt, step_uvolt;
+ struct speedo_entry *ent;
+ int i;
+
+ /* Get speedo entry with higher frequency */
+ ent = NULL;
+ for (i = 0; i < sc->cpu_def->speedo_nitems; i++) {
+ if (sc->cpu_def->speedo_tbl[i].freq >= freq) {
+ ent = &sc->cpu_def->speedo_tbl[i];
+ break;
+ }
+ }
+ if (ent == NULL)
+ ent = &sc->cpu_def->speedo_tbl[sc->cpu_def->speedo_nitems - 1];
+ scale = sc->cpu_def->speedo_scale;
+
+
+ /* uV = (c2 * speedo / scale + c1) * speedo / scale + c0) */
+ uv = DIV_ROUND_CLOSEST(ent->c2 * sc->speedo_value, scale);
+ uv = DIV_ROUND_CLOSEST((uv + ent->c1) * sc->speedo_value, scale) +
+ ent->c0;
+ step_uvolt = sc->cpu_def->step_uvolt;
+ /* Round up it to next regulator step */
+ uv = ROUND_UP(uv, step_uvolt);
+
+ /* Clamp result */
+ min_uvolt = ROUND_UP(sc->cpu_def->min_uvolt, step_uvolt);
+ max_uvolt = ROUND_DOWN(sc->cpu_def->max_uvolt, step_uvolt);
+ if (uv < min_uvolt)
+ uv = min_uvolt;
+ if (uv > max_uvolt)
+ uv = max_uvolt;
+ return (uv);
+
+}
+
+static void
+build_speed_points(struct tegra124_cpufreq_softc *sc) {
+ int i;
+
+ sc->nspeed_points = nitems(cpu_freq_tbl);
+ sc->speed_points = malloc(sizeof(struct cpu_speed_point) *
+ sc->nspeed_points, M_DEVBUF, M_NOWAIT);
+ for (i = 0; i < sc->nspeed_points; i++) {
+ sc->speed_points[i].freq = cpu_freq_tbl[i];
+ sc->speed_points[i].uvolt = freq_to_voltage(sc,
+ cpu_freq_tbl[i]);
+ }
+}
+
+static struct cpu_speed_point *
+get_speed_point(struct tegra124_cpufreq_softc *sc, uint64_t freq)
+{
+ int i;
+
+ if (sc->speed_points[0].freq >= freq)
+ return (sc->speed_points + 0);
+
+ for (i = 0; i < sc->nspeed_points - 1; i++) {
+ if (sc->speed_points[i + 1].freq > freq)
+ return (sc->speed_points + i);
+ }
+
+ return (sc->speed_points + sc->nspeed_points - 1);
+}
+
+static int
+tegra124_cpufreq_settings(device_t dev, struct cf_setting *sets, int *count)
+{
+ struct tegra124_cpufreq_softc *sc;
+ int i, j, max_cnt;
+
+ if (sets == NULL || count == NULL)
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+ memset(sets, CPUFREQ_VAL_UNKNOWN, sizeof(*sets) * (*count));
+
+ max_cnt = min(sc->nspeed_points, *count);
+ for (i = 0, j = sc->nspeed_points - 1; j >= 0; j--) {
+ if (sc->cpu_max_freq < sc->speed_points[j].freq)
+ continue;
+ sets[i].freq = sc->speed_points[j].freq / 1000000;
+ sets[i].volts = sc->speed_points[j].uvolt / 1000;
+ sets[i].lat = sc->latency;
+ sets[i].dev = dev;
+ i++;
+ }
+ *count = i;
+
+ return (0);
+}
+
+static int
+set_cpu_freq(struct tegra124_cpufreq_softc *sc, uint64_t freq)
+{
+ struct cpu_speed_point *point;
+ int rv;
+
+ point = get_speed_point(sc, freq);
+
+ if (sc->act_speed_point->uvolt < point->uvolt) {
+ /* set cpu voltage */
+ rv = regulator_set_voltage(sc->supply_vdd_cpu,
+ point->uvolt, point->uvolt);
+ DELAY(10000);
+ if (rv != 0)
+ return (rv);
+ }
+ rv = clk_set_freq(sc->clk_cpu_g, point->freq, CLK_SET_ROUND_DOWN);
+ if (rv != 0) {
+ device_printf(sc->dev, "Can't set CPU clock frequency\n");
+ return (rv);
+ }
+
+ if (sc->act_speed_point->uvolt > point->uvolt) {
+ /* set cpu voltage */
+ rv = regulator_set_voltage(sc->supply_vdd_cpu,
+ point->uvolt, point->uvolt);
+ if (rv != 0)
+ return (rv);
+ }
+
+ sc->act_speed_point = point;
+
+ return (0);
+}
+
+static int
+tegra124_cpufreq_set(device_t dev, const struct cf_setting *cf)
+{
+ struct tegra124_cpufreq_softc *sc;
+ uint64_t freq;
+ int rv;
+
+ if (cf == NULL || cf->freq < 0)
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+
+ freq = cf->freq;
+ if (freq < cpufreq_lowest_freq)
+ freq = cpufreq_lowest_freq;
+ freq *= 1000000;
+ if (freq >= sc->cpu_max_freq)
+ freq = sc->cpu_max_freq;
+ rv = set_cpu_freq(sc, freq);
+
+ return (rv);
+}
+
+static int
+tegra124_cpufreq_get(device_t dev, struct cf_setting *cf)
+{
+ struct tegra124_cpufreq_softc *sc;
+
+ if (cf == NULL)
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+ memset(cf, CPUFREQ_VAL_UNKNOWN, sizeof(*cf));
+ cf->dev = NULL;
+ cf->freq = sc->act_speed_point->freq / 1000000;
+ cf->volts = sc->act_speed_point->uvolt / 1000;
+ /* Transition latency in us. */
+ cf->lat = sc->latency;
+ /* Driver providing this setting. */
+ cf->dev = dev;
+
+ return (0);
+}
+
+
+static int
+tegra124_cpufreq_type(device_t dev, int *type)
+{
+
+ if (type == NULL)
+ return (EINVAL);
+ *type = CPUFREQ_TYPE_ABSOLUTE;
+
+ return (0);
+}
+
+static int
+get_fdt_resources(struct tegra124_cpufreq_softc *sc, phandle_t node)
+{
+ int rv;
+ device_t parent_dev;
+
+ parent_dev = device_get_parent(sc->dev);
+ rv = regulator_get_by_ofw_property(parent_dev, "vdd-cpu-supply",
+ &sc->supply_vdd_cpu);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'vdd-cpu' regulator\n");
+ return (rv);
+ }
+
+ rv = clk_get_by_ofw_name(parent_dev, "cpu_g", &sc->clk_cpu_g);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'cpu_g' clock: %d\n", rv);
+ return (ENXIO);
+ }
+
+ rv = clk_get_by_ofw_name(parent_dev, "cpu_lp", &sc->clk_cpu_lp);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'cpu_lp' clock\n");
+ return (ENXIO);
+ }
+
+ rv = clk_get_by_ofw_name(parent_dev, "pll_x", &sc->clk_pll_x);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'pll_x' clock\n");
+ return (ENXIO);
+ }
+ rv = clk_get_by_ofw_name(parent_dev, "pll_p", &sc->clk_pll_p);
+ if (rv != 0) {
+ device_printf(parent_dev, "Cannot get 'pll_p' clock\n");
+ return (ENXIO);
+ }
+ rv = clk_get_by_ofw_name(parent_dev, "dfll", &sc->clk_dfll);
+ if (rv != 0) {
+ /* XXX DPLL is not implemented yet */
+/*
+ device_printf(sc->dev, "Cannot get 'dfll' clock\n");
+ return (ENXIO);
+*/
+ }
+ return (0);
+}
+
+static void
+tegra124_cpufreq_identify(driver_t *driver, device_t parent)
+{
+
+ if (device_find_child(parent, "tegra124_cpufreq", -1) != NULL)
+ return;
+ if (BUS_ADD_CHILD(parent, 0, "tegra124_cpufreq", -1) == NULL)
+ device_printf(parent, "add child failed\n");
+}
+
+static int
+tegra124_cpufreq_probe(device_t dev)
+{
+
+ if (device_get_unit(dev) != 0)
+ return (ENXIO);
+ device_set_desc(dev, "CPU Frequency Control");
+
+ return (0);
+}
+
+static int
+tegra124_cpufreq_attach(device_t dev)
+{
+ struct tegra124_cpufreq_softc *sc;
+ uint64_t freq;
+ int rv;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ sc->node = ofw_bus_get_node(device_get_parent(dev));
+
+ sc->process_id = tegra_sku_info.cpu_process_id;
+ sc->speedo_id = tegra_sku_info.cpu_speedo_id;
+ sc->speedo_value = tegra_sku_info.cpu_speedo_value;
+
+ /* Tegra 124 */
+ /* XXX DPLL is not implemented yet */
+ if (1)
+ sc->cpu_def = &tegra124_cpu_volt_pllx_def;
+ else
+ sc->cpu_def = &tegra124_cpu_volt_dpll_def;
+
+
+ rv = get_fdt_resources(sc, sc->node);
+ if (rv != 0) {
+ return (rv);
+ }
+
+ build_speed_points(sc);
+
+ rv = clk_get_freq(sc->clk_cpu_g, &freq);
+ if (rv != 0) {
+ device_printf(dev, "Can't get CPU clock frequency\n");
+ return (rv);
+ }
+ if (sc->speedo_id < nitems(cpu_max_freq))
+ sc->cpu_max_freq = cpu_max_freq[sc->speedo_id];
+ else
+ sc->cpu_max_freq = cpu_max_freq[0];
+ sc->act_speed_point = get_speed_point(sc, freq);
+
+ /* Set safe startup CPU frequency. */
+ rv = set_cpu_freq(sc, 1632000000);
+ if (rv != 0) {
+ device_printf(dev, "Can't set initial CPU clock frequency\n");
+ return (rv);
+ }
+
+ /* This device is controlled by cpufreq(4). */
+ cpufreq_register(dev);
+
+ return (0);
+}
+
+static int
+tegra124_cpufreq_detach(device_t dev)
+{
+ struct tegra124_cpufreq_softc *sc;
+
+ sc = device_get_softc(dev);
+ cpufreq_unregister(dev);
+
+ if (sc->supply_vdd_cpu != NULL)
+ regulator_release(sc->supply_vdd_cpu);
+
+ if (sc->clk_cpu_g != NULL)
+ clk_release(sc->clk_cpu_g);
+ if (sc->clk_cpu_lp != NULL)
+ clk_release(sc->clk_cpu_lp);
+ if (sc->clk_pll_x != NULL)
+ clk_release(sc->clk_pll_x);
+ if (sc->clk_pll_p != NULL)
+ clk_release(sc->clk_pll_p);
+ if (sc->clk_dfll != NULL)
+ clk_release(sc->clk_dfll);
+ return (0);
+}
+
+static device_method_t tegra124_cpufreq_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_identify, tegra124_cpufreq_identify),
+ DEVMETHOD(device_probe, tegra124_cpufreq_probe),
+ DEVMETHOD(device_attach, tegra124_cpufreq_attach),
+ DEVMETHOD(device_detach, tegra124_cpufreq_detach),
+
+ /* cpufreq interface */
+ DEVMETHOD(cpufreq_drv_set, tegra124_cpufreq_set),
+ DEVMETHOD(cpufreq_drv_get, tegra124_cpufreq_get),
+ DEVMETHOD(cpufreq_drv_settings, tegra124_cpufreq_settings),
+ DEVMETHOD(cpufreq_drv_type, tegra124_cpufreq_type),
+
+ DEVMETHOD_END
+};
+
+static devclass_t tegra124_cpufreq_devclass;
+static driver_t tegra124_cpufreq_driver = {
+ "tegra124_cpufreq",
+ tegra124_cpufreq_methods,
+ sizeof(struct tegra124_cpufreq_softc),
+};
+
+DRIVER_MODULE(tegra124_cpufreq, cpu, tegra124_cpufreq_driver,
+ tegra124_cpufreq_devclass, 0, 0);
diff --git a/sys/arm/nvidia/tegra124/tegra124_machdep.c b/sys/arm/nvidia/tegra124/tegra124_machdep.c
new file mode 100644
index 0000000..e74a05b
--- /dev/null
+++ b/sys/arm/nvidia/tegra124/tegra124_machdep.c
@@ -0,0 +1,173 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@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.
+ */
+
+#define _ARM32_BUS_DMA_PRIVATE
+#include "opt_platform.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/reboot.h>
+
+#include <vm/vm.h>
+
+#include <machine/bus.h>
+#include <machine/devmap.h>
+#include <machine/fdt.h>
+#include <machine/intr.h>
+#include <machine/machdep.h>
+#include <machine/platformvar.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/openfirm.h>
+
+#include <arm/nvidia/tegra124/tegra124_mp.h>
+
+#include "platform_if.h"
+
+#define PMC_PHYSBASE 0x7000e400
+#define PMC_SIZE 0x400
+#define PMC_CONTROL_REG 0x0
+#define PMC_SCRATCH0 0x50
+#define PMC_SCRATCH0_MODE_RECOVERY (1 << 31)
+#define PMC_SCRATCH0_MODE_BOOTLOADER (1 << 30)
+#define PMC_SCRATCH0_MODE_RCM (1 << 1)
+#define PMC_SCRATCH0_MODE_MASK (PMC_SCRATCH0_MODE_RECOVERY | \
+ PMC_SCRATCH0_MODE_BOOTLOADER | \
+ PMC_SCRATCH0_MODE_RCM)
+
+struct fdt_fixup_entry fdt_fixup_table[] = {
+ { NULL, NULL }
+};
+
+struct arm32_dma_range *
+bus_dma_get_range(void)
+{
+
+ return (NULL);
+}
+
+int
+bus_dma_get_range_nb(void)
+{
+
+ return (0);
+}
+
+static vm_offset_t
+tegra124_lastaddr(platform_t plat)
+{
+
+ return (arm_devmap_lastaddr());
+}
+
+static int
+tegra124_attach(platform_t plat)
+{
+
+ return (0);
+}
+
+static void
+tegra124_late_init(platform_t plat)
+{
+
+}
+
+/*
+ * Set up static device mappings.
+ *
+ */
+static int
+tegra124_devmap_init(platform_t plat)
+{
+
+ arm_devmap_add_entry(0x70000000, 0x01000000);
+ return (0);
+}
+
+void
+cpu_reset(void)
+{
+ bus_space_handle_t pmc;
+ uint32_t reg;
+
+ printf("Resetting...\n");
+ bus_space_map(fdtbus_bs_tag, PMC_PHYSBASE, PMC_SIZE, 0, &pmc);
+
+ reg = bus_space_read_4(fdtbus_bs_tag, pmc, PMC_SCRATCH0);
+ reg &= PMC_SCRATCH0_MODE_MASK;
+ bus_space_write_4(fdtbus_bs_tag, pmc, PMC_SCRATCH0,
+ reg | PMC_SCRATCH0_MODE_BOOTLOADER); /* boot to bootloader */
+ bus_space_read_4(fdtbus_bs_tag, pmc, PMC_SCRATCH0);
+
+ reg = bus_space_read_4(fdtbus_bs_tag, pmc, PMC_CONTROL_REG);
+ spinlock_enter();
+ dsb();
+ bus_space_write_4(fdtbus_bs_tag, pmc, PMC_CONTROL_REG, reg | 0x10);
+ bus_space_read_4(fdtbus_bs_tag, pmc, PMC_CONTROL_REG);
+ while(1)
+ ;
+
+}
+
+/*
+ * Early putc routine for EARLY_PRINTF support. To use, add to kernel config:
+ * option SOCDEV_PA=0x02000000
+ * option SOCDEV_VA=0x02000000
+ * option EARLY_PRINTF
+ */
+#if 0
+static void
+tegra124_early_putc(int c)
+{
+ volatile uint32_t * UART_STAT_REG = (uint32_t *)0x02020098;
+ volatile uint32_t * UART_TX_REG = (uint32_t *)0x02020040;
+ const uint32_t UART_TXRDY = (1 << 3);
+
+ while ((*UART_STAT_REG & UART_TXRDY) == 0)
+ continue;
+ *UART_TX_REG = c;
+}
+early_putc_t *early_putc = tegra124_early_putc;
+#endif
+
+static platform_method_t tegra124_methods[] = {
+ PLATFORMMETHOD(platform_attach, tegra124_attach),
+ PLATFORMMETHOD(platform_lastaddr, tegra124_lastaddr),
+ PLATFORMMETHOD(platform_devmap_init, tegra124_devmap_init),
+ PLATFORMMETHOD(platform_late_init, tegra124_late_init),
+#ifdef SMP
+ PLATFORMMETHOD(platform_mp_start_ap, tegra124_mp_start_ap),
+ PLATFORMMETHOD(platform_mp_setmaxid, tegra124_mp_setmaxid),
+#endif
+ PLATFORMMETHOD_END,
+};
+
+FDT_PLATFORM_DEF(tegra124, "Nvidia Jetson-TK1", 0, "nvidia,jetson-tk1");
diff --git a/sys/arm/nvidia/tegra124/tegra124_mp.c b/sys/arm/nvidia/tegra124/tegra124_mp.c
new file mode 100644
index 0000000..36b3b7c
--- /dev/null
+++ b/sys/arm/nvidia/tegra124/tegra124_mp.c
@@ -0,0 +1,127 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/smp.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/cpu.h>
+#include <machine/intr.h>
+#include <machine/fdt.h>
+#include <machine/smp.h>
+#include <machine/platformvar.h>
+#include <machine/pmap.h>
+
+#include <arm/nvidia/tegra124/tegra124_mp.h>
+
+#define PMC_PHYSBASE 0x7000e400
+#define PMC_SIZE 0x400
+#define PMC_CONTROL_REG 0x0
+#define PMC_PWRGATE_TOGGLE 0x30
+#define PCM_PWRGATE_TOGGLE_START (1 << 8)
+#define PMC_PWRGATE_STATUS 0x38
+
+#define TEGRA_EXCEPTION_VECTORS_BASE 0x6000F000 /* exception vectors */
+#define TEGRA_EXCEPTION_VECTORS_SIZE 1024
+#define TEGRA_EXCEPTION_VECTOR_ENTRY 0x100
+
+void
+tegra124_mp_setmaxid(platform_t plat)
+{
+ int ncpu;
+
+ /* If we've already set the global vars don't bother to do it again. */
+ if (mp_ncpus != 0)
+ return;
+
+ /* Read current CP15 Cache Size ID Register */
+ ncpu = cp15_l2ctlr_get();
+ ncpu = CPUV7_L2CTLR_NPROC(ncpu);
+
+ mp_ncpus = ncpu;
+ mp_maxid = ncpu - 1;
+}
+
+void
+tegra124_mp_start_ap(platform_t plat)
+{
+ bus_space_handle_t pmc;
+ bus_space_handle_t exvec;
+ int i;
+ uint32_t val;
+ uint32_t mask;
+
+ if (bus_space_map(fdtbus_bs_tag, PMC_PHYSBASE, PMC_SIZE, 0, &pmc) != 0)
+ panic("Couldn't map the PMC\n");
+ if (bus_space_map(fdtbus_bs_tag, TEGRA_EXCEPTION_VECTORS_BASE,
+ TEGRA_EXCEPTION_VECTORS_SIZE, 0, &exvec) != 0)
+ panic("Couldn't map the exception vectors\n");
+
+ bus_space_write_4(fdtbus_bs_tag, exvec , TEGRA_EXCEPTION_VECTOR_ENTRY,
+ pmap_kextract((vm_offset_t)mpentry));
+ bus_space_read_4(fdtbus_bs_tag, exvec , TEGRA_EXCEPTION_VECTOR_ENTRY);
+
+
+ /* Wait until POWERGATE is ready (max 20 APB cycles). */
+ do {
+ val = bus_space_read_4(fdtbus_bs_tag, pmc,
+ PMC_PWRGATE_TOGGLE);
+ } while ((val & PCM_PWRGATE_TOGGLE_START) != 0);
+
+ for (i = 1; i < mp_ncpus; i++) {
+ val = bus_space_read_4(fdtbus_bs_tag, pmc, PMC_PWRGATE_STATUS);
+ mask = 1 << (i + 8); /* cpu mask */
+ if ((val & mask) == 0) {
+ /* Wait until POWERGATE is ready (max 20 APB cycles). */
+ do {
+ val = bus_space_read_4(fdtbus_bs_tag, pmc,
+ PMC_PWRGATE_TOGGLE);
+ } while ((val & PCM_PWRGATE_TOGGLE_START) != 0);
+ bus_space_write_4(fdtbus_bs_tag, pmc,
+ PMC_PWRGATE_TOGGLE,
+ PCM_PWRGATE_TOGGLE_START | (8 + i));
+
+ /* Wait until CPU is powered */
+ do {
+ val = bus_space_read_4(fdtbus_bs_tag, pmc,
+ PMC_PWRGATE_STATUS);
+ } while ((val & mask) == 0);
+ }
+
+ }
+ armv7_sev();
+ bus_space_unmap(fdtbus_bs_tag, pmc, PMC_SIZE);
+ bus_space_unmap(fdtbus_bs_tag, exvec, TEGRA_EXCEPTION_VECTORS_SIZE);
+}
diff --git a/sys/compat/cloudabi/cloudabi_syscalldefs.h b/sys/arm/nvidia/tegra124/tegra124_mp.h
index fc86eff..57785aa 100644
--- a/sys/compat/cloudabi/cloudabi_syscalldefs.h
+++ b/sys/arm/nvidia/tegra124/tegra124_mp.h
@@ -1,5 +1,6 @@
/*-
- * Copyright (c) 2015 Nuxi, https://nuxi.nl/
+ * Copyright (c) 2016 Michal Meloun <mmel@FreeBSD.org>
+ * All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -25,24 +26,10 @@
* $FreeBSD$
*/
-#ifndef _CLOUDABI_SYSCALLDEFS_H_
-#define _CLOUDABI_SYSCALLDEFS_H_
+#ifndef _TEGRA124_MP_H_
+#define _TEGRA124_MP_H_
-#ifdef _KERNEL
-#include <sys/types.h>
-#include <sys/stdint.h>
+void tegra124_mp_setmaxid(platform_t plat);
+void tegra124_mp_start_ap(platform_t plat);
-#define alignas _Alignas
-#define alignof _Alignof
-#define static_assert _Static_assert
-#else
-#include <assert.h>
-#include <stdalign.h>
-#include <stddef.h>
-#include <stdint.h>
-#endif
-
-/* Import machine-independent CloudABI definitions. */
-#include <contrib/cloudabi/syscalldefs_mi.h>
-
-#endif
+#endif /*_TEGRA124_MP_H_*/ \ No newline at end of file
diff --git a/sys/arm/nvidia/tegra124/tegra124_pmc.c b/sys/arm/nvidia/tegra124/tegra124_pmc.c
new file mode 100644
index 0000000..7ff7307
--- /dev/null
+++ b/sys/arm/nvidia/tegra124/tegra124_pmc.c
@@ -0,0 +1,566 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+
+#include <dev/extres/clk/clk.h>
+#include <dev/extres/hwreset/hwreset.h>
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/nvidia/tegra_pmc.h>
+
+#define PMC_CNTRL 0x000
+#define PMC_CNTRL_CPUPWRGOOD_SEL_MASK (0x3 << 20)
+#define PMC_CNTRL_CPUPWRGOOD_SEL_SHIFT 20
+#define PMC_CNTRL_CPUPWRGOOD_EN (1 << 19)
+#define PMC_CNTRL_FUSE_OVERRIDE (1 << 18)
+#define PMC_CNTRL_INTR_POLARITY (1 << 17)
+#define PMC_CNTRL_CPU_PWRREQ_OE (1 << 16)
+#define PMC_CNTRL_CPU_PWRREQ_POLARITY (1 << 15)
+#define PMC_CNTRL_SIDE_EFFECT_LP0 (1 << 14)
+#define PMC_CNTRL_AOINIT (1 << 13)
+#define PMC_CNTRL_PWRGATE_DIS (1 << 12)
+#define PMC_CNTRL_SYSCLK_OE (1 << 11)
+#define PMC_CNTRL_SYSCLK_POLARITY (1 << 10)
+#define PMC_CNTRL_PWRREQ_OE (1 << 9)
+#define PMC_CNTRL_PWRREQ_POLARITY (1 << 8)
+#define PMC_CNTRL_BLINK_EN (1 << 7)
+#define PMC_CNTRL_GLITCHDET_DIS (1 << 6)
+#define PMC_CNTRL_LATCHWAKE_EN (1 << 5)
+#define PMC_CNTRL_MAIN_RST (1 << 4)
+#define PMC_CNTRL_KBC_RST (1 << 3)
+#define PMC_CNTRL_RTC_RST (1 << 2)
+#define PMC_CNTRL_RTC_CLK_DIS (1 << 1)
+#define PMC_CNTRL_KBC_CLK_DIS (1 << 0)
+
+#define PMC_DPD_SAMPLE 0x020
+
+#define PMC_CLAMP_STATUS 0x02C
+#define PMC_CLAMP_STATUS_PARTID(x) (1 << ((x) & 0x1F))
+
+#define PMC_PWRGATE_TOGGLE 0x030
+#define PMC_PWRGATE_TOGGLE_START (1 << 8)
+#define PMC_PWRGATE_TOGGLE_PARTID(x) (((x) & 0x1F) << 0)
+
+#define PMC_REMOVE_CLAMPING_CMD 0x034
+#define PMC_REMOVE_CLAMPING_CMD_PARTID(x) (1 << ((x) & 0x1F))
+
+#define PMC_PWRGATE_STATUS 0x038
+#define PMC_PWRGATE_STATUS_PARTID(x) (1 << ((x) & 0x1F))
+
+#define PMC_SCRATCH0 0x050
+#define PMC_SCRATCH0_MODE_RECOVERY (1 << 31)
+#define PMC_SCRATCH0_MODE_BOOTLOADER (1 << 30)
+#define PMC_SCRATCH0_MODE_RCM (1 << 1)
+#define PMC_SCRATCH0_MODE_MASK (PMC_SCRATCH0_MODE_RECOVERY | \
+ PMC_SCRATCH0_MODE_BOOTLOADER | \
+ PMC_SCRATCH0_MODE_RCM)
+
+#define PMC_CPUPWRGOOD_TIMER 0x0c8
+#define PMC_CPUPWROFF_TIMER 0x0cc
+
+#define PMC_SCRATCH41 0x140
+
+#define PMC_SENSOR_CTRL 0x1b0
+#define PMC_SENSOR_CTRL_BLOCK_SCRATCH_WRITE (1 << 2)
+#define PMC_SENSOR_CTRL_ENABLE_RST (1 << 1)
+#define PMC_SENSOR_CTRL_ENABLE_PG (1 << 0)
+
+#define PMC_IO_DPD_REQ 0x1b8
+#define PMC_IO_DPD_REQ_CODE_IDLE (0 << 30)
+#define PMC_IO_DPD_REQ_CODE_OFF (1 << 30)
+#define PMC_IO_DPD_REQ_CODE_ON (2 << 30)
+#define PMC_IO_DPD_REQ_CODE_MASK (3 << 30)
+
+#define PMC_IO_DPD_STATUS 0x1bc
+#define PMC_IO_DPD_STATUS_HDMI (1 << 28)
+#define PMC_IO_DPD2_REQ 0x1c0
+#define PMC_IO_DPD2_STATUS 0x1c4
+#define PMC_IO_DPD2_STATUS_HV (1 << 6)
+#define PMC_SEL_DPD_TIM 0x1c8
+
+#define PMC_SCRATCH54 0x258
+#define PMC_SCRATCH54_DATA_SHIFT 8
+#define PMC_SCRATCH54_ADDR_SHIFT 0
+
+#define PMC_SCRATCH55 0x25c
+#define PMC_SCRATCH55_RST_ENABLE (1 << 31)
+#define PMC_SCRATCH55_CNTRL_TYPE (1 << 30)
+#define PMC_SCRATCH55_CNTRL_ID_SHIFT 27
+#define PMC_SCRATCH55_CNTRL_ID_MASK 0x07
+#define PMC_SCRATCH55_PINMUX_SHIFT 24
+#define PMC_SCRATCH55_PINMUX_MASK 0x07
+#define PMC_SCRATCH55_CHECKSUM_SHIFT 16
+#define PMC_SCRATCH55_CHECKSUM_MASK 0xFF
+#define PMC_SCRATCH55_16BITOP (1 << 15)
+#define PMC_SCRATCH55_I2CSLV1_SHIFT 0
+#define PMC_SCRATCH55_I2CSLV1_MASK 0x7F
+
+#define PMC_GPU_RG_CNTRL 0x2d4
+
+#define WR4(_sc, _r, _v) bus_write_4((_sc)->mem_res, (_r), (_v))
+#define RD4(_sc, _r) bus_read_4((_sc)->mem_res, (_r))
+
+#define PMC_LOCK(_sc) mtx_lock(&(_sc)->mtx)
+#define PMC_UNLOCK(_sc) mtx_unlock(&(_sc)->mtx)
+#define PMC_LOCK_INIT(_sc) mtx_init(&(_sc)->mtx, \
+ device_get_nameunit(_sc->dev), "tegra124_pmc", MTX_DEF)
+#define PMC_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->mtx);
+#define PMC_ASSERT_LOCKED(_sc) mtx_assert(&(_sc)->mtx, MA_OWNED);
+#define PMC_ASSERT_UNLOCKED(_sc) mtx_assert(&(_sc)->mtx, MA_NOTOWNED);
+
+struct tegra124_pmc_softc {
+ device_t dev;
+ struct resource *mem_res;
+ clk_t clk;
+ struct mtx mtx;
+
+ uint32_t rate;
+ enum tegra_suspend_mode suspend_mode;
+ uint32_t cpu_good_time;
+ uint32_t cpu_off_time;
+ uint32_t core_osc_time;
+ uint32_t core_pmu_time;
+ uint32_t core_off_time;
+ int corereq_high;
+ int sysclkreq_high;
+ int combined_req;
+ int cpu_pwr_good_en;
+ uint32_t lp0_vec_phys;
+ uint32_t lp0_vec_size;
+};
+
+static struct ofw_compat_data compat_data[] = {
+ {"nvidia,tegra124-pmc", 1},
+ {NULL, 0},
+};
+
+static struct tegra124_pmc_softc *pmc_sc;
+
+static inline struct tegra124_pmc_softc *
+tegra124_pmc_get_sc(void)
+{
+ if (pmc_sc == NULL)
+ panic("To early call to Tegra PMC driver.\n");
+ return (pmc_sc);
+}
+
+static int
+tegra124_pmc_set_powergate(struct tegra124_pmc_softc *sc,
+ enum tegra_powergate_id id, int ena)
+{
+ uint32_t reg;
+ int i;
+
+ PMC_LOCK(sc);
+
+ reg = RD4(sc, PMC_PWRGATE_STATUS) & PMC_PWRGATE_STATUS_PARTID(id);
+ if (((reg != 0) && ena) || ((reg == 0) && !ena)) {
+ PMC_UNLOCK(sc);
+ return (0);
+ }
+
+ for (i = 100; i > 0; i--) {
+ reg = RD4(sc, PMC_PWRGATE_TOGGLE);
+ if ((reg & PMC_PWRGATE_TOGGLE_START) == 0)
+ break;
+ DELAY(1);
+ }
+ if (i <= 0)
+ device_printf(sc->dev,
+ "Timeout when waiting for TOGGLE_START\n");
+
+ WR4(sc, PMC_PWRGATE_TOGGLE,
+ PMC_PWRGATE_TOGGLE_START | PMC_PWRGATE_TOGGLE_PARTID(id));
+
+ for (i = 100; i > 0; i--) {
+ reg = RD4(sc, PMC_PWRGATE_TOGGLE);
+ if ((reg & PMC_PWRGATE_TOGGLE_START) == 0)
+ break;
+ DELAY(1);
+ }
+ if (i <= 0)
+ device_printf(sc->dev,
+ "Timeout when waiting for TOGGLE_START\n");
+ PMC_UNLOCK(sc);
+ return (0);
+}
+
+int
+tegra_powergate_remove_clamping(enum tegra_powergate_id id)
+{
+ struct tegra124_pmc_softc *sc;
+ uint32_t reg;
+ enum tegra_powergate_id swid;
+ int i;
+
+ sc = tegra124_pmc_get_sc();
+
+ if (id == TEGRA_POWERGATE_3D) {
+ WR4(sc, PMC_GPU_RG_CNTRL, 0);
+ return (0);
+ }
+
+ reg = RD4(sc, PMC_PWRGATE_STATUS);
+ if ((reg & PMC_PWRGATE_STATUS_PARTID(id)) == 0)
+ panic("Attempt to remove clamping for unpowered partition.\n");
+
+ if (id == TEGRA_POWERGATE_PCX)
+ swid = TEGRA_POWERGATE_VDE;
+ else if (id == TEGRA_POWERGATE_VDE)
+ swid = TEGRA_POWERGATE_PCX;
+ else
+ swid = id;
+ WR4(sc, PMC_REMOVE_CLAMPING_CMD, PMC_REMOVE_CLAMPING_CMD_PARTID(swid));
+
+ for (i = 100; i > 0; i--) {
+ reg = RD4(sc, PMC_REMOVE_CLAMPING_CMD);
+ if ((reg & PMC_REMOVE_CLAMPING_CMD_PARTID(swid)) == 0)
+ break;
+ DELAY(1);
+ }
+ if (i <= 0)
+ device_printf(sc->dev, "Timeout when remove clamping\n");
+
+ reg = RD4(sc, PMC_CLAMP_STATUS);
+ if ((reg & PMC_CLAMP_STATUS_PARTID(id)) != 0)
+ panic("Cannot remove clamping\n");
+
+ return (0);
+}
+
+int
+tegra_powergate_is_powered(enum tegra_powergate_id id)
+{
+ struct tegra124_pmc_softc *sc;
+ uint32_t reg;
+
+ sc = tegra124_pmc_get_sc();
+
+ reg = RD4(sc, PMC_PWRGATE_STATUS);
+ return ((reg & PMC_PWRGATE_STATUS_PARTID(id)) ? 1 : 0);
+}
+
+int
+tegra_powergate_power_on(enum tegra_powergate_id id)
+{
+ struct tegra124_pmc_softc *sc;
+ int rv, i;
+
+ sc = tegra124_pmc_get_sc();
+
+ rv = tegra124_pmc_set_powergate(sc, id, 1);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot set powergate: %d\n", id);
+ return (rv);
+ }
+
+ for (i = 100; i > 0; i--) {
+ if (tegra_powergate_is_powered(id))
+ break;
+ DELAY(1);
+ }
+ if (i <= 0)
+ device_printf(sc->dev, "Timeout when waiting on power up\n");
+
+ return (rv);
+}
+
+int
+tegra_powergate_power_off(enum tegra_powergate_id id)
+{
+ struct tegra124_pmc_softc *sc;
+ int rv, i;
+
+ sc = tegra124_pmc_get_sc();
+
+ rv = tegra124_pmc_set_powergate(sc, id, 0);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot set powergate: %d\n", id);
+ return (rv);
+ }
+ for (i = 100; i > 0; i--) {
+ if (!tegra_powergate_is_powered(id))
+ break;
+ DELAY(1);
+ }
+ if (i <= 0)
+ device_printf(sc->dev, "Timeout when waiting on power off\n");
+
+ return (rv);
+}
+
+int
+tegra_powergate_sequence_power_up(enum tegra_powergate_id id, clk_t clk,
+ hwreset_t rst)
+{
+ struct tegra124_pmc_softc *sc;
+ int rv;
+
+ sc = tegra124_pmc_get_sc();
+
+ rv = hwreset_assert(rst);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot assert reset\n");
+ return (rv);
+ }
+
+ rv = clk_stop(clk);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot stop clock\n");
+ goto clk_fail;
+ }
+
+ rv = tegra_powergate_power_on(id);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot power on powergate\n");
+ goto clk_fail;
+ }
+
+ rv = clk_enable(clk);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot enable clock\n");
+ goto clk_fail;
+ }
+ DELAY(20);
+
+ rv = tegra_powergate_remove_clamping(id);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot remove clamping\n");
+ goto fail;
+ }
+ rv = hwreset_deassert(rst);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot unreset reset\n");
+ goto fail;
+ }
+ return 0;
+
+fail:
+ clk_disable(clk);
+clk_fail:
+ hwreset_assert(rst);
+ tegra_powergate_power_off(id);
+ return (rv);
+}
+
+static int
+tegra124_pmc_parse_fdt(struct tegra124_pmc_softc *sc, phandle_t node)
+{
+ int rv;
+ uint32_t tmp;
+ uint32_t tmparr[2];
+
+ rv = OF_getencprop(node, "nvidia,suspend-mode", &tmp, sizeof(tmp));
+ if (rv > 0) {
+ switch (tmp) {
+ case 0:
+ sc->suspend_mode = TEGRA_SUSPEND_LP0;
+ break;
+
+ case 1:
+ sc->suspend_mode = TEGRA_SUSPEND_LP1;
+ break;
+
+ case 2:
+ sc->suspend_mode = TEGRA_SUSPEND_LP2;
+ break;
+
+ default:
+ sc->suspend_mode = TEGRA_SUSPEND_NONE;
+ break;
+ }
+ }
+
+ rv = OF_getencprop(node, "nvidia,cpu-pwr-good-time", &tmp, sizeof(tmp));
+ if (rv > 0) {
+ sc->cpu_good_time = tmp;
+ sc->suspend_mode = TEGRA_SUSPEND_NONE;
+ }
+
+ rv = OF_getencprop(node, "nvidia,cpu-pwr-off-time", &tmp, sizeof(tmp));
+ if (rv > 0) {
+ sc->cpu_off_time = tmp;
+ sc->suspend_mode = TEGRA_SUSPEND_NONE;
+ }
+
+ rv = OF_getencprop(node, "nvidia,core-pwr-good-time", tmparr,
+ sizeof(tmparr));
+ if (rv == sizeof(tmparr)) {
+ sc->core_osc_time = tmparr[0];
+ sc->core_pmu_time = tmparr[1];
+ sc->suspend_mode = TEGRA_SUSPEND_NONE;
+ }
+
+ rv = OF_getencprop(node, "nvidia,core-pwr-off-time", &tmp, sizeof(tmp));
+ if (rv > 0) {
+ sc->core_off_time = tmp;
+ sc->suspend_mode = TEGRA_SUSPEND_NONE;
+ }
+
+ sc->corereq_high =
+ OF_hasprop(node, "nvidia,core-power-req-active-high");
+ sc->sysclkreq_high =
+ OF_hasprop(node, "nvidia,sys-clock-req-active-high");
+ sc->combined_req =
+ OF_hasprop(node, "nvidia,combined-power-req");
+ sc->cpu_pwr_good_en =
+ OF_hasprop(node, "nvidia,cpu-pwr-good-en");
+
+ rv = OF_getencprop(node, "nvidia,lp0-vec", tmparr, sizeof(tmparr));
+ if (rv == sizeof(tmparr)) {
+
+ sc->lp0_vec_phys = tmparr[0];
+ sc->core_pmu_time = tmparr[1];
+ sc->lp0_vec_size = TEGRA_SUSPEND_NONE;
+ if (sc->suspend_mode == TEGRA_SUSPEND_LP0)
+ sc->suspend_mode = TEGRA_SUSPEND_LP1;
+ }
+ return 0;
+}
+
+static int
+tegra124_pmc_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
+ return (ENXIO);
+
+ device_set_desc(dev, "Tegra PMC");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+tegra124_pmc_detach(device_t dev)
+{
+
+ /* This device is always present. */
+ return (EBUSY);
+}
+
+static int
+tegra124_pmc_attach(device_t dev)
+{
+ struct tegra124_pmc_softc *sc;
+ int rid, rv;
+ uint32_t reg;
+ phandle_t node;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ node = ofw_bus_get_node(dev);
+
+ rv = tegra124_pmc_parse_fdt(sc, node);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot parse FDT data\n");
+ return (rv);
+ }
+
+ rv = clk_get_by_ofw_name(sc->dev, "pclk", &sc->clk);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get \"pclk\" clock\n");
+ return (ENXIO);
+ }
+
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev, "Cannot allocate memory resources\n");
+ return (ENXIO);
+ }
+
+ PMC_LOCK_INIT(sc);
+
+ /* Enable CPU power request. */
+ reg = RD4(sc, PMC_CNTRL);
+ reg |= PMC_CNTRL_CPU_PWRREQ_OE;
+ WR4(sc, PMC_CNTRL, reg);
+
+ /* Set sysclk output polarity */
+ reg = RD4(sc, PMC_CNTRL);
+ if (sc->sysclkreq_high)
+ reg &= ~PMC_CNTRL_SYSCLK_POLARITY;
+ else
+ reg |= PMC_CNTRL_SYSCLK_POLARITY;
+ WR4(sc, PMC_CNTRL, reg);
+
+ /* Enable sysclk request. */
+ reg = RD4(sc, PMC_CNTRL);
+ reg |= PMC_CNTRL_SYSCLK_OE;
+ WR4(sc, PMC_CNTRL, reg);
+
+ /*
+ * Remove HDMI from deep power down mode.
+ * XXX mote this to HDMI driver
+ */
+ reg = RD4(sc, PMC_IO_DPD_STATUS);
+ reg &= ~ PMC_IO_DPD_STATUS_HDMI;
+ WR4(sc, PMC_IO_DPD_STATUS, reg);
+
+ reg = RD4(sc, PMC_IO_DPD2_STATUS);
+ reg &= ~ PMC_IO_DPD2_STATUS_HV;
+ WR4(sc, PMC_IO_DPD2_STATUS, reg);
+
+ if (pmc_sc != NULL)
+ panic("tegra124_pmc: double driver attach");
+ pmc_sc = sc;
+ return (0);
+}
+
+static device_method_t tegra124_pmc_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, tegra124_pmc_probe),
+ DEVMETHOD(device_attach, tegra124_pmc_attach),
+ DEVMETHOD(device_detach, tegra124_pmc_detach),
+
+ DEVMETHOD_END
+};
+
+static driver_t tegra124_pmc_driver = {
+ "tegra124_pmc",
+ tegra124_pmc_methods,
+ sizeof(struct tegra124_pmc_softc),
+};
+
+static devclass_t tegra124_pmc_devclass;
+EARLY_DRIVER_MODULE(tegra124_pmc, simplebus, tegra124_pmc_driver,
+ tegra124_pmc_devclass, 0, 0, 70);
diff --git a/sys/arm/nvidia/tegra124/tegra124_xusbpadctl.c b/sys/arm/nvidia/tegra124/tegra124_xusbpadctl.c
new file mode 100644
index 0000000..e06d4bf
--- /dev/null
+++ b/sys/arm/nvidia/tegra124/tegra124_xusbpadctl.c
@@ -0,0 +1,603 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <dev/extres/hwreset/hwreset.h>
+#include <dev/extres/phy/phy.h>
+#include <dev/fdt/fdt_common.h>
+#include <dev/fdt/fdt_pinctrl.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <gnu/dts/include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
+
+#include "phy_if.h"
+
+#define XUSB_PADCTL_USB2_PAD_MUX 0x004
+
+#define XUSB_PADCTL_ELPG_PROGRAM 0x01C
+#define ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26)
+#define ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25)
+#define ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24)
+
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040
+#define IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19)
+#define IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK (0xf<< 12)
+#define IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1)
+
+#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x044
+#define IOPHY_PLL_P0_CTL2_REFCLKBUF_EN (1 << 6)
+#define IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5)
+#define IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4)
+
+
+#define XUSB_PADCTL_USB3_PAD_MUX 0x134
+
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138
+#define IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27)
+#define IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24)
+#define IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3)
+#define IOPHY_PLL_S0_CTL1_PLL_RST_L (1 << 1)
+#define IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0)
+
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2 0x13C
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL3 0x140
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL4 0x144
+
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148
+#define IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1)
+#define IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0)
+
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL2 0x14C
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL3 0x150
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL4 0x154
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL5 0x158
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL6 0x15C
+
+struct lane_cfg {
+ char *function;
+ char **lanes;
+ int iddq;
+};
+
+struct xusbpadctl_softc {
+ device_t dev;
+ struct resource *mem_res;
+ hwreset_t rst;
+ int phy_ena_cnt;
+};
+
+static struct ofw_compat_data compat_data[] = {
+ {"nvidia,tegra124-xusb-padctl", 1},
+ {NULL, 0},
+};
+
+struct padctl_lane {
+ const char *name;
+ bus_size_t reg;
+ uint32_t shift;
+ uint32_t mask;
+ int iddq;
+ char **mux;
+ int nmux;
+};
+
+static char *otg_mux[] = {"snps", "xusb", "uart", "rsvd"};
+static char *usb_mux[] = {"snps", "xusb"};
+static char *pci_mux[] = {"pcie", "usb3", "sata", "rsvd"};
+
+#define LANE(n, r, s, m, i, mx) \
+{ \
+ .name = n, \
+ .reg = r, \
+ .shift = s, \
+ .mask = m, \
+ .iddq = i, \
+ .mux = mx, \
+ .nmux = nitems(mx), \
+}
+
+static const struct padctl_lane lanes_tbl[] = {
+ LANE("otg-0", XUSB_PADCTL_USB2_PAD_MUX, 0, 0x3, -1, otg_mux),
+ LANE("otg-1", XUSB_PADCTL_USB2_PAD_MUX, 2, 0x3, -1, otg_mux),
+ LANE("otg-2", XUSB_PADCTL_USB2_PAD_MUX, 4, 0x3, -1, otg_mux),
+ LANE("ulpi-0", XUSB_PADCTL_USB2_PAD_MUX, 12, 0x1, -1, usb_mux),
+ LANE("hsic-0", XUSB_PADCTL_USB2_PAD_MUX, 14, 0x1, -1, usb_mux),
+ LANE("hsic-1", XUSB_PADCTL_USB2_PAD_MUX, 15, 0x1, -1, usb_mux),
+ LANE("pcie-0", XUSB_PADCTL_USB3_PAD_MUX, 16, 0x3, 1, pci_mux),
+ LANE("pcie-1", XUSB_PADCTL_USB3_PAD_MUX, 18, 0x3, 2, pci_mux),
+ LANE("pcie-2", XUSB_PADCTL_USB3_PAD_MUX, 20, 0x3, 3, pci_mux),
+ LANE("pcie-3", XUSB_PADCTL_USB3_PAD_MUX, 22, 0x3, 4, pci_mux),
+ LANE("pcie-4", XUSB_PADCTL_USB3_PAD_MUX, 24, 0x3, 5, pci_mux),
+ LANE("sata-0", XUSB_PADCTL_USB3_PAD_MUX, 26, 0x3, 6, pci_mux),
+};
+
+static int
+xusbpadctl_mux_function(const struct padctl_lane *lane, char *fnc_name)
+{
+ int i;
+
+ for (i = 0; i < lane->nmux; i++) {
+ if (strcmp(fnc_name, lane->mux[i]) == 0)
+ return (i);
+ }
+
+ return (-1);
+}
+
+static int
+xusbpadctl_config_lane(struct xusbpadctl_softc *sc, char *lane_name,
+ const struct padctl_lane *lane, struct lane_cfg *cfg)
+{
+
+ int tmp;
+ uint32_t reg;
+
+ reg = bus_read_4(sc->mem_res, lane->reg);
+ if (cfg->function != NULL) {
+ tmp = xusbpadctl_mux_function(lane, cfg->function);
+ if (tmp == -1) {
+ device_printf(sc->dev,
+ "Unknown function %s for lane %s\n", cfg->function,
+ lane_name);
+ return (EINVAL);
+ }
+ reg &= ~(lane->mask << lane->shift);
+ reg |= (tmp & lane->mask) << lane->shift;
+ }
+ if (cfg->iddq != -1) {
+ if (lane->iddq == -1) {
+ device_printf(sc->dev, "Invalid IDDQ for lane %s\n",
+ lane_name);
+ return (EINVAL);
+ }
+ if (cfg->iddq != 0)
+ reg &= ~(1 << lane->iddq);
+ else
+ reg |= 1 << lane->iddq;
+ }
+
+ bus_write_4(sc->mem_res, lane->reg, reg);
+ return (0);
+}
+
+static const struct padctl_lane *
+xusbpadctl_search_lane(char *lane_name)
+{
+ int i;
+
+ for (i = 0; i < nitems(lanes_tbl); i++) {
+ if (strcmp(lane_name, lanes_tbl[i].name) == 0)
+ return (&lanes_tbl[i]);
+ }
+
+ return (NULL);
+}
+
+static int
+xusbpadctl_config_node(struct xusbpadctl_softc *sc, char *lane_name,
+ struct lane_cfg *cfg)
+{
+ const struct padctl_lane *lane;
+ int rv;
+
+ lane = xusbpadctl_search_lane(lane_name);
+ if (lane == NULL) {
+ device_printf(sc->dev, "Unknown lane: %s\n", lane_name);
+ return (ENXIO);
+ }
+ rv = xusbpadctl_config_lane(sc, lane_name, lane, cfg);
+ return (rv);
+}
+
+static int
+xusbpadctl_read_node(struct xusbpadctl_softc *sc, phandle_t node,
+ struct lane_cfg *cfg, char **lanes, int *llanes)
+{
+ int rv;
+
+ *llanes = OF_getprop_alloc(node, "nvidia,lanes", 1, (void **)lanes);
+ if (*llanes <= 0)
+ return (ENOENT);
+
+ /* Read function (mux) settings. */
+ rv = OF_getprop_alloc(node, "nvidia,function", 1,
+ (void **)&cfg->function);
+ if (rv <= 0)
+ cfg->function = NULL;
+ /* Read numeric properties. */
+ rv = OF_getencprop(node, "nvidia,iddq", &cfg->iddq,
+ sizeof(cfg->iddq));
+ if (rv <= 0)
+ cfg->iddq = -1;
+ return (0);
+}
+
+static int
+xusbpadctl_process_node(struct xusbpadctl_softc *sc, phandle_t node)
+{
+ struct lane_cfg cfg;
+ char *lanes, *lname;
+ int i, len, llanes, rv;
+
+ rv = xusbpadctl_read_node(sc, node, &cfg, &lanes, &llanes);
+ if (rv != 0)
+ return (rv);
+
+ len = 0;
+ lname = lanes;
+ do {
+ i = strlen(lname) + 1;
+ rv = xusbpadctl_config_node(sc, lname, &cfg);
+ if (rv != 0)
+ device_printf(sc->dev,
+ "Cannot configure lane: %s: %d\n", lname, rv);
+
+ len += i;
+ lname += i;
+ } while (len < llanes);
+
+ if (lanes != NULL)
+ free(lanes, M_OFWPROP);
+ if (cfg.function != NULL)
+ free(cfg.function, M_OFWPROP);
+ return (rv);
+}
+
+
+static int
+xusbpadctl_pinctrl_cfg(device_t dev, phandle_t cfgxref)
+{
+ struct xusbpadctl_softc *sc;
+ phandle_t node, cfgnode;
+ int rv;
+
+ sc = device_get_softc(dev);
+ cfgnode = OF_node_from_xref(cfgxref);
+
+ rv = 0;
+ for (node = OF_child(cfgnode); node != 0; node = OF_peer(node)) {
+ if (!fdt_is_enabled(node))
+ continue;
+ rv = xusbpadctl_process_node(sc, node);
+ if (rv != 0)
+ return (rv);
+ }
+
+ return (rv);
+}
+
+static int
+xusbpadctl_phy_pcie_powerup(struct xusbpadctl_softc *sc)
+{
+ uint32_t reg;
+ int i;
+
+ reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+ reg &= ~IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK;
+ bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1, reg);
+ DELAY(100);
+
+ reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
+ reg |= IOPHY_PLL_P0_CTL2_REFCLKBUF_EN;
+ reg |= IOPHY_PLL_P0_CTL2_TXCLKREF_EN;
+ reg |= IOPHY_PLL_P0_CTL2_TXCLKREF_SEL;
+ bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL2, reg);
+ DELAY(100);
+
+ reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+ reg |= IOPHY_PLL_P0_CTL1_PLL_RST;
+ bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1, reg);
+ DELAY(100);
+
+ for (i = 0; i < 100; i++) {
+ reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+ if (reg & IOPHY_PLL_P0_CTL1_PLL0_LOCKDET)
+ return (0);
+ DELAY(10);
+ }
+
+ return (ETIMEDOUT);
+}
+
+
+static int
+xusbpadctl_phy_pcie_powerdown(struct xusbpadctl_softc *sc)
+{
+ uint32_t reg;
+
+ reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
+ reg &= ~IOPHY_PLL_P0_CTL1_PLL_RST;
+ bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_P0_CTL1, reg);
+ DELAY(100);
+ return (0);
+
+}
+
+static int
+xusbpadctl_phy_sata_powerup(struct xusbpadctl_softc *sc)
+{
+ uint32_t reg;
+ int i;
+
+ reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
+ reg &= ~IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
+ reg &= ~IOPHY_MISC_PAD_S0_CTL1_IDDQ;
+ bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1, reg);
+
+ reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+ reg &= ~IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
+ reg &= ~IOPHY_PLL_S0_CTL1_PLL_IDDQ;
+ bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
+
+ reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+ reg |= IOPHY_PLL_S0_CTL1_PLL1_MODE;
+ bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
+
+ reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+ reg |= IOPHY_PLL_S0_CTL1_PLL_RST_L;
+ bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
+
+ for (i = 100; i >= 0; i--) {
+ reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+ if (reg & IOPHY_PLL_S0_CTL1_PLL1_LOCKDET)
+ break;
+ DELAY(100);
+ }
+ if (i <= 0) {
+ device_printf(sc->dev, "Failed to power up SATA phy\n");
+ return (ETIMEDOUT);
+ }
+
+ return (0);
+}
+
+static int
+xusbpadctl_phy_sata_powerdown(struct xusbpadctl_softc *sc)
+{
+ uint32_t reg;
+
+ reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+ reg &= ~IOPHY_PLL_S0_CTL1_PLL_RST_L;
+ bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
+ DELAY(100);
+
+ reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+ reg &= ~IOPHY_PLL_S0_CTL1_PLL1_MODE;
+ bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
+ DELAY(100);
+
+ reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+ reg |= IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
+ reg |= IOPHY_PLL_S0_CTL1_PLL_IDDQ;
+ bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_PLL_S0_CTL1, reg);
+ DELAY(100);
+
+ reg = bus_read_4(sc->mem_res, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
+ reg |= IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
+ reg |= IOPHY_MISC_PAD_S0_CTL1_IDDQ;
+ bus_write_4(sc->mem_res, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1, reg);
+ DELAY(100);
+
+ return (0);
+}
+
+static int
+xusbpadctl_phy_powerup(struct xusbpadctl_softc *sc)
+{
+ uint32_t reg;
+
+ reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM);
+ reg &= ~ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
+ bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg);
+ DELAY(100);
+
+ reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM);
+ reg &= ~ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
+ bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg);
+ DELAY(100);
+
+ reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM);
+ reg &= ~ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
+ bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg);
+ DELAY(100);
+
+ return (0);
+}
+
+static int
+xusbpadctl_phy_powerdown(struct xusbpadctl_softc *sc)
+{
+ uint32_t reg;
+
+ reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM);
+ reg |= ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
+ bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg);
+ DELAY(100);
+
+ reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM);
+ reg |= ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
+ bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg);
+ DELAY(100);
+
+ reg = bus_read_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM);
+ reg |= ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
+ bus_write_4(sc->mem_res, XUSB_PADCTL_ELPG_PROGRAM, reg);
+ DELAY(100);
+
+ return (0);
+}
+
+static int
+xusbpadctl_phy_enable(device_t dev, intptr_t id, bool enable)
+{
+ struct xusbpadctl_softc *sc;
+ int rv;
+
+ sc = device_get_softc(dev);
+
+ if ((id != TEGRA_XUSB_PADCTL_PCIE) &&
+ (id != TEGRA_XUSB_PADCTL_SATA)) {
+ device_printf(dev, "Unknown phy: %d\n", id);
+ return (ENXIO);
+ }
+
+ rv = 0;
+ if (enable) {
+ if (sc->phy_ena_cnt == 0) {
+ rv = xusbpadctl_phy_powerup(sc);
+ if (rv != 0)
+ return (rv);
+ }
+ sc->phy_ena_cnt++;
+ }
+
+ if (id == TEGRA_XUSB_PADCTL_PCIE) {
+ if (enable)
+ rv = xusbpadctl_phy_pcie_powerup(sc);
+ else
+ rv = xusbpadctl_phy_pcie_powerdown(sc);
+ if (rv != 0)
+ return (rv);
+ } else if (id == TEGRA_XUSB_PADCTL_SATA) {
+ if (enable)
+ rv = xusbpadctl_phy_sata_powerup(sc);
+ else
+ rv = xusbpadctl_phy_sata_powerdown(sc);
+ if (rv != 0)
+ return (rv);
+ }
+ if (!enable) {
+ if (sc->phy_ena_cnt == 1) {
+ rv = xusbpadctl_phy_powerdown(sc);
+ if (rv != 0)
+ return (rv);
+ }
+ sc->phy_ena_cnt--;
+ }
+
+ return (0);
+}
+
+static int
+xusbpadctl_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
+ return (ENXIO);
+
+ device_set_desc(dev, "Tegra XUSB phy");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+xusbpadctl_detach(device_t dev)
+{
+
+ /* This device is always present. */
+ return (EBUSY);
+}
+
+static int
+xusbpadctl_attach(device_t dev)
+{
+ struct xusbpadctl_softc * sc;
+ int rid, rv;
+ phandle_t node;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev, "Cannot allocate memory resources\n");
+ return (ENXIO);
+ }
+
+ node = ofw_bus_get_node(dev);
+ rv = hwreset_get_by_ofw_name(dev, "padctl", &sc->rst);
+ if (rv != 0) {
+ device_printf(dev, "Cannot get 'padctl' reset: %d\n", rv);
+ return (rv);
+ }
+ rv = hwreset_deassert(sc->rst);
+ if (rv != 0) {
+ device_printf(dev, "Cannot unreset 'padctl' reset: %d\n", rv);
+ return (rv);
+ }
+
+ /* Register as a pinctrl device and use default configuration */
+ fdt_pinctrl_register(dev, NULL);
+ fdt_pinctrl_configure_by_name(dev, "default");
+ phy_register_provider(dev);
+
+ return (0);
+}
+
+
+static device_method_t tegra_xusbpadctl_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, xusbpadctl_probe),
+ DEVMETHOD(device_attach, xusbpadctl_attach),
+ DEVMETHOD(device_detach, xusbpadctl_detach),
+
+ /* fdt_pinctrl interface */
+ DEVMETHOD(fdt_pinctrl_configure, xusbpadctl_pinctrl_cfg),
+
+ /* phy interface */
+ DEVMETHOD(phy_enable, xusbpadctl_phy_enable),
+
+ DEVMETHOD_END
+};
+
+static driver_t tegra_xusbpadctl_driver = {
+ "tegra_xusbpadctl",
+ tegra_xusbpadctl_methods,
+ sizeof(struct xusbpadctl_softc),
+};
+
+static devclass_t tegra_xusbpadctl_devclass;
+
+EARLY_DRIVER_MODULE(tegra_xusbpadctl, simplebus, tegra_xusbpadctl_driver,
+ tegra_xusbpadctl_devclass, 0, 0, 73);
diff --git a/sys/arm/nvidia/tegra_abpmisc.c b/sys/arm/nvidia/tegra_abpmisc.c
new file mode 100644
index 0000000..83ee44f
--- /dev/null
+++ b/sys/arm/nvidia/tegra_abpmisc.c
@@ -0,0 +1,194 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * SoC misc configuration and indentification driver.
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/clock.h>
+#include <sys/kernel.h>
+#include <sys/limits.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/module.h>
+#include <sys/resource.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/nvidia/tegra_efuse.h>
+
+#define PMC_STRAPPING_OPT_A 0 /* 0x464 */
+
+#define PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT 4
+#define PMC_STRAPPING_OPT_A_RAM_CODE_MASK_LONG \
+ (0xf << PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT)
+#define PMC_STRAPPING_OPT_A_RAM_CODE_MASK_SHORT \
+ (0x3 << PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT)
+
+
+#define ABP_RD4(_sc, _r) bus_read_4((_sc)->abp_misc_res, (_r))
+#define STR_RD4(_sc, _r) bus_read_4((_sc)->strap_opt_res, (_r))
+
+static struct ofw_compat_data compat_data[] = {
+ {"nvidia,tegra124-apbmisc", 1},
+ {NULL, 0}
+};
+
+struct tegra_abpmisc_softc {
+ device_t dev;
+
+ struct resource *abp_misc_res;
+ struct resource *strap_opt_res;
+};
+
+static struct tegra_abpmisc_softc *dev_sc;
+
+static void
+tegra_abpmisc_read_revision(struct tegra_abpmisc_softc *sc)
+{
+ uint32_t id, chip_id, minor_rev;
+ int rev;
+
+ id = ABP_RD4(sc, 4);
+ chip_id = (id >> 8) & 0xff;
+ minor_rev = (id >> 16) & 0xf;
+
+ switch (minor_rev) {
+ case 1:
+ rev = TEGRA_REVISION_A01;
+ break;
+ case 2:
+ rev = TEGRA_REVISION_A02;
+ break;
+ case 3:
+ rev = TEGRA_REVISION_A03;
+ break;
+ case 4:
+ rev = TEGRA_REVISION_A04;
+ break;
+ default:
+ rev = TEGRA_REVISION_UNKNOWN;
+ }
+
+ tegra_sku_info.chip_id = chip_id;
+ tegra_sku_info.revision = rev;
+}
+
+static int
+tegra_abpmisc_probe(device_t dev)
+{
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+tegra_abpmisc_attach(device_t dev)
+{
+ int rid;
+ struct tegra_abpmisc_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ rid = 0;
+ sc->abp_misc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (sc->abp_misc_res == NULL) {
+ device_printf(dev, "Cannot map ABP misc registers.\n");
+ goto fail;
+ }
+
+ rid = 1;
+ sc->strap_opt_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->strap_opt_res == NULL) {
+ device_printf(dev, "Cannot map strapping options registers.\n");
+ goto fail;
+ }
+
+ tegra_abpmisc_read_revision(sc);
+
+ /* XXX - Hack - address collision with pinmux. */
+ if (sc->abp_misc_res != NULL) {
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->abp_misc_res);
+ sc->abp_misc_res = NULL;
+ }
+
+ dev_sc = sc;
+ return (bus_generic_attach(dev));
+
+fail:
+ if (sc->abp_misc_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->abp_misc_res);
+ if (sc->strap_opt_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, 1, sc->strap_opt_res);
+
+ return (ENXIO);
+}
+
+static int
+tegra_abpmisc_detach(device_t dev)
+{
+ struct tegra_abpmisc_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (sc->abp_misc_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->abp_misc_res);
+ if (sc->strap_opt_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, 1, sc->strap_opt_res);
+ return (bus_generic_detach(dev));
+}
+
+static device_method_t tegra_abpmisc_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, tegra_abpmisc_probe),
+ DEVMETHOD(device_attach, tegra_abpmisc_attach),
+ DEVMETHOD(device_detach, tegra_abpmisc_detach),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(tegra_abpmisc, tegra_abpmisc_driver, tegra_abpmisc_methods,
+ sizeof(struct tegra_abpmisc_softc));
+static devclass_t tegra_abpmisc_devclass;
+EARLY_DRIVER_MODULE(tegra_abpmisc, simplebus, tegra_abpmisc_driver,
+ tegra_abpmisc_devclass, 0, 0, BUS_PASS_TIMER);
diff --git a/sys/arm/nvidia/tegra_ahci.c b/sys/arm/nvidia/tegra_ahci.c
new file mode 100644
index 0000000..4afba17
--- /dev/null
+++ b/sys/arm/nvidia/tegra_ahci.c
@@ -0,0 +1,627 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * AHCI driver for Tegra SoCs.
+ */
+#include <sys/param.h>
+#include <sys/module.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <dev/ahci/ahci.h>
+#include <dev/extres/clk/clk.h>
+#include <dev/extres/hwreset/hwreset.h>
+#include <dev/extres/phy/phy.h>
+#include <dev/extres/regulator/regulator.h>
+#include <dev/fdt/fdt_common.h>
+#include <dev/fdt/fdt_pinctrl.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/nvidia/tegra_efuse.h>
+#include <arm/nvidia/tegra_pmc.h>
+
+#define AHCI_WR4(_sc, _r, _v) bus_write_4((_sc)->ctlr.r_mem, (_r), (_v))
+#define AHCI_RD4(_sc, _r) bus_read_4((_sc)->ctlr.r_mem, (_r))
+#define SATA_WR4(_sc, _r, _v) bus_write_4((_sc)->sata_mem, (_r), (_v))
+#define SATA_RD4(_sc, _r) bus_read_4((_sc)->sata_mem, (_r))
+
+static struct ofw_compat_data compat_data[] = {
+ {"nvidia,tegra124-ahci", 1},
+ {NULL, 0}
+};
+
+struct tegra_ahci_sc {
+ struct ahci_controller ctlr; /* Must be first */
+ device_t dev;
+ struct resource *sata_mem;
+ clk_t clk_sata;
+ clk_t clk_sata_oob;
+ clk_t clk_pll_e;
+ clk_t clk_cml;
+ hwreset_t hwreset_sata;
+ hwreset_t hwreset_sata_oob;
+ hwreset_t hwreset_sata_cold;
+ regulator_t supply_hvdd;
+ regulator_t supply_vddio;
+ regulator_t supply_avdd;
+ regulator_t supply_target_5v;
+ regulator_t supply_target_12v;
+ phy_t phy;
+};
+
+struct sata_pad_calibration {
+ uint32_t gen1_tx_amp;
+ uint32_t gen1_tx_peak;
+ uint32_t gen2_tx_amp;
+ uint32_t gen2_tx_peak;
+};
+
+static const struct sata_pad_calibration tegra124_pad_calibration[] = {
+ {0x18, 0x04, 0x18, 0x0a},
+ {0x0e, 0x04, 0x14, 0x0a},
+ {0x0e, 0x07, 0x1a, 0x0e},
+ {0x14, 0x0e, 0x1a, 0x0e},
+};
+
+#define SATA_CONFIGURATION 0x180
+#define SATA_CONFIGURATION_EN_FPCI (1 << 0)
+
+#define SATA_FPCI_BAR5 0x94
+#define SATA_FPCI_BAR5_START_SHIFT 4
+
+#define SATA_INTR_MASK 0x188
+#define SATA_INTR_MASK_IP_INT_MASK (1 << 16)
+
+#define SCFG_OFFSET 0x1000
+
+#define T_SATA0_CFG_1 0x04
+#define T_SATA0_CFG_1_IO_SPACE (1 << 0)
+#define T_SATA0_CFG_1_MEMORY_SPACE (1 << 1)
+#define T_SATA0_CFG_1_BUS_MASTER (1 << 2)
+#define T_SATA0_CFG_1_SERR (1 << 8)
+
+#define T_SATA0_CFG_9 0x24
+#define T_SATA0_CFG_9_BASE_ADDRESS_SHIFT 13
+
+#define T_SATA0_AHCI_HBA_CAP_BKDR 0x300
+#define T_SATA0_BKDOOR_CC 0x4a4
+#define T_SATA0_CFG_SATA 0x54c
+#define T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN (1 << 12)
+
+#define T_SATA0_CFG_MISC 0x550
+#define T_SATA0_INDEX 0x680
+
+#define T_SATA0_CHX_PHY_CTRL1_GEN1 0x690
+#define T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_MASK 0xff
+#define T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_SHIFT 8
+#define T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_MASK 0xff
+#define T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_SHIFT 0
+
+
+#define T_SATA0_CHX_PHY_CTRL1_GEN2 0x694
+#define T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_MASK 0xff
+#define T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_SHIFT 12
+#define T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_MASK 0xff
+#define T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_SHIFT 0
+
+#define T_SATA0_CHX_PHY_CTRL2 0x69c
+#define T_SATA0_CHX_PHY_CTRL2_CDR_CNTL_GEN1 0x23
+
+#define T_SATA0_CHX_PHY_CTRL11 0x6d0
+#define T_SATA0_CHX_PHY_CTRL11_GEN2_RX_EQ (0x2800 << 16)
+
+#define FUSE_SATA_CALIB 0x124
+#define FUSE_SATA_CALIB_MASK 0x3
+
+
+#define SATA_AUX_MISC_CNTL 0x1108
+#define SATA_AUX_PAD_PLL_CTRL_0 0x1120
+#define SATA_AUX_PAD_PLL_CTRL_1 0x1124
+#define SATA_AUX_PAD_PLL_CTRL_2 0x1128
+#define SATA_AUX_PAD_PLL_CTRL_3 0x112c
+
+#define T_AHCI_HBA_CCC_PORTS 0x0018
+#define T_AHCI_HBA_CAP_BKDR 0x00A0
+#define T_AHCI_HBA_CAP_BKDR_S64A (1 << 31)
+#define T_AHCI_HBA_CAP_BKDR_SNCQ (1 << 30)
+#define T_AHCI_HBA_CAP_BKDR_SSNTF (1 << 29)
+#define T_AHCI_HBA_CAP_BKDR_SMPS (1 << 28)
+#define T_AHCI_HBA_CAP_BKDR_SUPP_STG_SPUP (1 << 27)
+#define T_AHCI_HBA_CAP_BKDR_SALP (1 << 26)
+#define T_AHCI_HBA_CAP_BKDR_SAL (1 << 25)
+#define T_AHCI_HBA_CAP_BKDR_SUPP_CLO (1 << 24)
+#define T_AHCI_HBA_CAP_BKDR_INTF_SPD_SUPP(x) (((x) & 0xF) << 20)
+#define T_AHCI_HBA_CAP_BKDR_SUPP_NONZERO_OFFSET (1 << 19)
+#define T_AHCI_HBA_CAP_BKDR_SUPP_AHCI_ONLY (1 << 18)
+#define T_AHCI_HBA_CAP_BKDR_SUPP_PM (1 << 17)
+#define T_AHCI_HBA_CAP_BKDR_FIS_SWITCHING (1 << 16)
+#define T_AHCI_HBA_CAP_BKDR_PIO_MULT_DRQ_BLK (1 << 15)
+#define T_AHCI_HBA_CAP_BKDR_SLUMBER_ST_CAP (1 << 14)
+#define T_AHCI_HBA_CAP_BKDR_PARTIAL_ST_CAP (1 << 13)
+#define T_AHCI_HBA_CAP_BKDR_NUM_CMD_SLOTS(x) (((x) & 0x1F) << 8)
+#define T_AHCI_HBA_CAP_BKDR_CMD_CMPL_COALESING (1 << 7)
+#define T_AHCI_HBA_CAP_BKDR_ENCL_MGMT_SUPP (1 << 6)
+#define T_AHCI_HBA_CAP_BKDR_EXT_SATA (1 << 5)
+#define T_AHCI_HBA_CAP_BKDR_NUM_PORTS(x) (((x) & 0xF) << 0)
+
+#define T_AHCI_PORT_BKDR 0x0170
+
+#define T_AHCI_PORT_BKDR_PXDEVSLP_DETO_OVERRIDE_VAL(x) (((x) & 0xFF) << 24)
+#define T_AHCI_PORT_BKDR_PXDEVSLP_MDAT_OVERRIDE_VAL(x) (((x) & 0x1F) << 16)
+#define T_AHCI_PORT_BKDR_PXDEVSLP_DETO_OVERRIDE (1 << 15)
+#define T_AHCI_PORT_BKDR_PXDEVSLP_MDAT_OVERRIDE (1 << 14)
+#define T_AHCI_PORT_BKDR_PXDEVSLP_DM(x) (((x) & 0xF) << 10)
+#define T_AHCI_PORT_BKDR_PORT_UNCONNECTED (1 << 9)
+#define T_AHCI_PORT_BKDR_CLK_CLAMP_CTRL_CLAMP_THIS_CH (1 << 8)
+#define T_AHCI_PORT_BKDR_CLK_CLAMP_CTRL_TXRXCLK_UNCLAMP (1 << 7)
+#define T_AHCI_PORT_BKDR_CLK_CLAMP_CTRL_TXRXCLK_CLAMP (1 << 6)
+#define T_AHCI_PORT_BKDR_CLK_CLAMP_CTRL_DEVCLK_UNCLAMP (1 << 5)
+#define T_AHCI_PORT_BKDR_CLK_CLAMP_CTRL_DEVCLK_CLAMP (1 << 4)
+#define T_AHCI_PORT_BKDR_HOTPLUG_CAP (1 << 3)
+#define T_AHCI_PORT_BKDR_MECH_SWITCH (1 << 2)
+#define T_AHCI_PORT_BKDR_COLD_PRSN_DET (1 << 1)
+#define T_AHCI_PORT_BKDR_EXT_SATA_SUPP (1 << 0)
+
+static int
+get_fdt_resources(struct tegra_ahci_sc *sc, phandle_t node)
+{
+ int rv;
+
+
+ rv = regulator_get_by_ofw_property(sc->dev, "hvdd-supply",
+ &sc->supply_hvdd );
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'hvdd' regulator\n");
+ return (ENXIO);
+ }
+ rv = regulator_get_by_ofw_property(sc->dev, "vddio-supply",
+ &sc->supply_vddio);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'vddio' regulator\n");
+ return (ENXIO);
+ }
+ rv = regulator_get_by_ofw_property(sc->dev, "avdd-supply",
+ &sc->supply_avdd);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'avdd' regulator\n");
+ return (ENXIO);
+ }
+ rv = regulator_get_by_ofw_property(sc->dev, "target-5v-supply",
+ &sc->supply_target_5v);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'target-5v' regulator\n");
+ return (ENXIO);
+ }
+ rv = regulator_get_by_ofw_property(sc->dev, "target-12v-supply",
+ &sc->supply_target_12v);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'target-12v' regulator\n");
+ return (ENXIO);
+ }
+
+ rv = hwreset_get_by_ofw_name(sc->dev, "sata", &sc->hwreset_sata );
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'sata' reset\n");
+ return (ENXIO);
+ }
+ rv = hwreset_get_by_ofw_name(sc->dev, "sata-oob",
+ &sc->hwreset_sata_oob);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'sata oob' reset\n");
+ return (ENXIO);
+ }
+ rv = hwreset_get_by_ofw_name(sc->dev, "sata-cold",
+ &sc->hwreset_sata_cold);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'sata cold' reset\n");
+ return (ENXIO);
+ }
+
+ rv = phy_get_by_ofw_name(sc->dev, "sata-phy", &sc->phy);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'sata' phy\n");
+ return (ENXIO);
+ }
+
+ rv = clk_get_by_ofw_name(sc->dev, "sata", &sc->clk_sata);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'sata' clock\n");
+ return (ENXIO);
+ }
+ rv = clk_get_by_ofw_name(sc->dev, "sata-oob", &sc->clk_sata_oob);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'sata oob' clock\n");
+ return (ENXIO);
+ }
+ rv = clk_get_by_ofw_name(sc->dev, "cml1", &sc->clk_cml);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'cml1' clock\n");
+ return (ENXIO);
+ }
+ rv = clk_get_by_ofw_name(sc->dev, "pll_e", &sc->clk_pll_e);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'pll_e' clock\n");
+ return (ENXIO);
+ }
+ return (0);
+}
+
+static int
+enable_fdt_resources(struct tegra_ahci_sc *sc)
+{
+ int rv;
+
+ rv = regulator_enable(sc->supply_hvdd);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot enable 'hvdd' regulator\n");
+ return (rv);
+ }
+ rv = regulator_enable(sc->supply_vddio);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot enable 'vddio' regulator\n");
+ return (rv);
+ }
+ rv = regulator_enable(sc->supply_avdd);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot enable 'avdd' regulator\n");
+ return (rv);
+ }
+ rv = regulator_enable(sc->supply_target_5v);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot enable 'target-5v' regulator\n");
+ return (rv);
+ }
+ rv = regulator_enable(sc->supply_target_12v);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot enable 'sc->target-12v' regulator\n");
+ return (rv);
+ }
+
+ /* Stop clocks */
+ clk_stop(sc->clk_sata);
+ clk_stop(sc->clk_sata_oob);
+ tegra_powergate_power_off(TEGRA_POWERGATE_SAX);
+
+ rv = hwreset_assert(sc->hwreset_sata);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot assert 'sata' reset\n");
+ return (rv);
+ }
+ rv = hwreset_assert(sc->hwreset_sata_oob);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot assert 'sata oob' reset\n");
+ return (rv);
+ }
+
+ rv = hwreset_assert(sc->hwreset_sata_cold);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot assert 'sata cold' reset\n");
+ return (rv);
+ }
+ rv = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_SAX,
+ sc->clk_sata, sc->hwreset_sata);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot enable 'SAX' powergate\n");
+ return (rv);
+ }
+
+ rv = clk_enable(sc->clk_sata_oob);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot enable 'sata oob' clock\n");
+ return (rv);
+ }
+ rv = clk_enable(sc->clk_cml);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot enable 'cml' clock\n");
+ return (rv);
+ }
+ rv = clk_enable(sc->clk_pll_e);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot enable 'pll e' clock\n");
+ return (rv);
+ }
+
+ rv = hwreset_deassert(sc->hwreset_sata_cold);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot unreset 'sata cold' reset\n");
+ return (rv);
+ }
+ rv = hwreset_deassert(sc->hwreset_sata_oob);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot unreset 'sata oob' reset\n");
+ return (rv);
+ }
+
+ rv = phy_enable(sc->dev, sc->phy);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot enable SATA phy\n");
+ return (rv);
+ }
+
+ return (0);
+}
+
+static int
+tegra_ahci_ctrl_init(struct tegra_ahci_sc *sc)
+{
+ uint32_t val;
+ const struct sata_pad_calibration *calib;
+
+ val = SATA_RD4(sc, SATA_CONFIGURATION);
+ val |= SATA_CONFIGURATION_EN_FPCI;
+ SATA_WR4(sc, SATA_CONFIGURATION, val);
+
+
+ /* Pad calibration. */
+ val = tegra_fuse_read_4(FUSE_SATA_CALIB);
+ calib = tegra124_pad_calibration + (val & FUSE_SATA_CALIB_MASK);
+ SATA_WR4(sc, SCFG_OFFSET + T_SATA0_INDEX, 1);
+
+ val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL1_GEN1);
+ val &= ~(T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_MASK <<
+ T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_SHIFT);
+ val &= ~(T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_MASK <<
+ T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_SHIFT);
+ val |= calib->gen1_tx_amp << T_SATA0_CHX_PHY_CTRL1_GEN1_TX_AMP_SHIFT;
+ val |= calib->gen1_tx_peak << T_SATA0_CHX_PHY_CTRL1_GEN1_TX_PEAK_SHIFT;
+ SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL1_GEN1, val);
+
+ val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL1_GEN2);
+ val &= ~(T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_MASK <<
+ T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_SHIFT);
+ val &= ~(T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_MASK <<
+ T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_SHIFT);
+ val |= calib->gen2_tx_amp << T_SATA0_CHX_PHY_CTRL1_GEN2_TX_AMP_SHIFT;
+ val |= calib->gen2_tx_peak << T_SATA0_CHX_PHY_CTRL1_GEN2_TX_PEAK_SHIFT;
+ SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL1_GEN2, val);
+
+ SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL11,
+ T_SATA0_CHX_PHY_CTRL11_GEN2_RX_EQ);
+
+ SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CHX_PHY_CTRL2,
+ T_SATA0_CHX_PHY_CTRL2_CDR_CNTL_GEN1);
+
+ SATA_WR4(sc, SCFG_OFFSET + T_SATA0_INDEX, 0);
+
+ /* Set device ID. */
+ val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CFG_SATA);
+ val |= T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN;
+ SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CFG_SATA, val);
+
+ SATA_WR4(sc, SCFG_OFFSET + T_SATA0_BKDOOR_CC, 0x01060100);
+
+ val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CFG_SATA);
+ val &= ~T_SATA0_CFG_SATA_BACKDOOR_PROG_IF_EN;
+ SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CFG_SATA, val);
+
+ /* Enable IO & memory access, bus master mode */
+ val = SATA_RD4(sc, SCFG_OFFSET + T_SATA0_CFG_1);
+ val |= T_SATA0_CFG_1_IO_SPACE;
+ val |= T_SATA0_CFG_1_MEMORY_SPACE;
+ val |= T_SATA0_CFG_1_BUS_MASTER;
+ val |= T_SATA0_CFG_1_SERR;
+ SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CFG_1, val);
+
+ /* SATA MMIO. */
+ SATA_WR4(sc, SATA_FPCI_BAR5, 0x10000 << SATA_FPCI_BAR5_START_SHIFT);
+ /* AHCI bar */
+ SATA_WR4(sc, SCFG_OFFSET + T_SATA0_CFG_9,
+ 0x08000 << T_SATA0_CFG_9_BASE_ADDRESS_SHIFT);
+
+ /* Unmask interrupts. */
+ val = SATA_RD4(sc, SATA_INTR_MASK);
+ val |= SATA_INTR_MASK_IP_INT_MASK;
+ SATA_WR4(sc, SATA_INTR_MASK, val);
+
+ return (0);
+}
+
+static int
+tegra_ahci_ctlr_reset(device_t dev)
+{
+ struct tegra_ahci_sc *sc;
+ int rv;
+ uint32_t reg;
+
+ sc = device_get_softc(dev);
+ rv = ahci_ctlr_reset(dev);
+ if (rv != 0)
+ return (0);
+ AHCI_WR4(sc, T_AHCI_HBA_CCC_PORTS, 1);
+
+ /* Overwrite AHCI capabilites. */
+ reg = AHCI_RD4(sc, T_AHCI_HBA_CAP_BKDR);
+ reg &= ~T_AHCI_HBA_CAP_BKDR_NUM_PORTS(~0);
+ reg |= T_AHCI_HBA_CAP_BKDR_NUM_PORTS(0);
+ reg |= T_AHCI_HBA_CAP_BKDR_EXT_SATA;
+ reg |= T_AHCI_HBA_CAP_BKDR_ENCL_MGMT_SUPP;
+ reg |= T_AHCI_HBA_CAP_BKDR_CMD_CMPL_COALESING;
+ reg |= T_AHCI_HBA_CAP_BKDR_FIS_SWITCHING;
+ reg |= T_AHCI_HBA_CAP_BKDR_SUPP_PM;
+ reg |= T_AHCI_HBA_CAP_BKDR_SUPP_CLO;
+ reg |= T_AHCI_HBA_CAP_BKDR_SUPP_STG_SPUP;
+ AHCI_WR4(sc, T_AHCI_HBA_CAP_BKDR, reg);
+
+ /* Overwrite AHCI portcapabilites. */
+ reg = AHCI_RD4(sc, T_AHCI_PORT_BKDR);
+ reg |= T_AHCI_PORT_BKDR_COLD_PRSN_DET;
+ reg |= T_AHCI_PORT_BKDR_HOTPLUG_CAP;
+ reg |= T_AHCI_PORT_BKDR_EXT_SATA_SUPP;
+ AHCI_WR4(sc, T_AHCI_PORT_BKDR, reg);
+
+ return (0);
+}
+
+static int
+tegra_ahci_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
+ return (ENXIO);
+
+ device_set_desc_copy(dev, "AHCI SATA controller");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+tegra_ahci_attach(device_t dev)
+{
+ struct tegra_ahci_sc *sc;
+ struct ahci_controller *ctlr;
+ phandle_t node;
+ int rv, rid;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ ctlr = &sc->ctlr;
+ node = ofw_bus_get_node(dev);
+
+ ctlr->r_rid = 0;
+ ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &ctlr->r_rid, RF_ACTIVE);
+ if (ctlr->r_mem == NULL)
+ return (ENXIO);
+
+ rid = 1;
+ sc->sata_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &rid, RF_ACTIVE);
+ if (sc->sata_mem == NULL) {
+ rv = ENXIO;
+ goto fail;
+ }
+ rv = get_fdt_resources(sc, node);
+ if (rv != 0) {
+ device_printf(sc->dev, "Failed to allocate FDT resource(s)\n");
+ goto fail;
+ }
+
+ rv = enable_fdt_resources(sc);
+ if (rv != 0) {
+ device_printf(sc->dev, "Failed to enable FDT resource(s)\n");
+ goto fail;
+ }
+ rv = tegra_ahci_ctrl_init(sc);
+ if (rv != 0) {
+ device_printf(sc->dev, "Failed to initialize controller)\n");
+ goto fail;
+ }
+
+ /* Setup controller defaults. */
+ ctlr->msi = 0;
+ ctlr->numirqs = 1;
+ ctlr->ccc = 0;
+
+ /* Reset controller. */
+ rv = tegra_ahci_ctlr_reset(dev);
+ if (rv != 0)
+ goto fail;
+ rv = ahci_attach(dev);
+ return (rv);
+
+fail:
+ /* XXX FDT stuff */
+ if (sc->sata_mem != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, 1, sc->sata_mem);
+ if (ctlr->r_mem != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid,
+ ctlr->r_mem);
+ return (rv);
+}
+
+static int
+tegra_ahci_detach(device_t dev)
+{
+
+ ahci_detach(dev);
+ return (0);
+}
+
+static int
+tegra_ahci_suspend(device_t dev)
+{
+ struct tegra_ahci_sc *sc = device_get_softc(dev);
+
+ bus_generic_suspend(dev);
+ /* Disable interupts, so the state change(s) doesn't trigger. */
+ ATA_OUTL(sc->ctlr.r_mem, AHCI_GHC,
+ ATA_INL(sc->ctlr.r_mem, AHCI_GHC) & (~AHCI_GHC_IE));
+ return (0);
+}
+
+static int
+tegra_ahci_resume(device_t dev)
+{
+ int res;
+
+ if ((res = tegra_ahci_ctlr_reset(dev)) != 0)
+ return (res);
+ ahci_ctlr_setup(dev);
+ return (bus_generic_resume(dev));
+}
+
+devclass_t genahci_devclass;
+static device_method_t genahci_methods[] = {
+ DEVMETHOD(device_probe, tegra_ahci_probe),
+ DEVMETHOD(device_attach, tegra_ahci_attach),
+ DEVMETHOD(device_detach, tegra_ahci_detach),
+ DEVMETHOD(device_suspend, tegra_ahci_suspend),
+ DEVMETHOD(device_resume, tegra_ahci_resume),
+ DEVMETHOD(bus_print_child, ahci_print_child),
+ DEVMETHOD(bus_alloc_resource, ahci_alloc_resource),
+ DEVMETHOD(bus_release_resource, ahci_release_resource),
+ DEVMETHOD(bus_setup_intr, ahci_setup_intr),
+ DEVMETHOD(bus_teardown_intr, ahci_teardown_intr),
+ DEVMETHOD(bus_child_location_str, ahci_child_location_str),
+ DEVMETHOD(bus_get_dma_tag, ahci_get_dma_tag),
+
+ DEVMETHOD_END
+};
+static driver_t genahci_driver = {
+ "ahci",
+ genahci_methods,
+ sizeof(struct tegra_ahci_sc)
+};
+DRIVER_MODULE(genahci, simplebus, genahci_driver, genahci_devclass, NULL, NULL);
diff --git a/sys/arm/nvidia/tegra_efuse.c b/sys/arm/nvidia/tegra_efuse.c
new file mode 100644
index 0000000..ae3f9ef
--- /dev/null
+++ b/sys/arm/nvidia/tegra_efuse.c
@@ -0,0 +1,368 @@
+/*-
+ * Copyright (c) 2015 Michal Meloun
+ * 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/systm.h>
+#include <sys/bus.h>
+#include <sys/clock.h>
+#include <sys/kernel.h>
+#include <sys/limits.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/module.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <dev/extres/clk/clk.h>
+#include <dev/extres/hwreset/hwreset.h>
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/nvidia/tegra_efuse.h>
+
+
+#define RD4(_sc, _r) bus_read_4((_sc)->mem_res, (_sc)->fuse_begin + (_r))
+
+static struct ofw_compat_data compat_data[] = {
+ {"nvidia,tegra124-efuse", 1},
+ {NULL, 0}
+};
+
+struct tegra_efuse_softc {
+ device_t dev;
+ struct resource *mem_res;
+
+ int fuse_begin;
+ clk_t clk;
+ hwreset_t reset;
+};
+struct tegra_efuse_softc *dev_sc;
+
+struct tegra_sku_info tegra_sku_info;
+static char *tegra_rev_name[] = {
+ [TEGRA_REVISION_UNKNOWN] = "unknown",
+ [TEGRA_REVISION_A01] = "A01",
+ [TEGRA_REVISION_A02] = "A02",
+ [TEGRA_REVISION_A03] = "A03",
+ [TEGRA_REVISION_A03p] = "A03 prime",
+ [TEGRA_REVISION_A04] = "A04",
+};
+
+/* Tegra30 and later */
+#define FUSE_VENDOR_CODE 0x100
+#define FUSE_FAB_CODE 0x104
+#define FUSE_LOT_CODE_0 0x108
+#define FUSE_LOT_CODE_1 0x10c
+#define FUSE_WAFER_ID 0x110
+#define FUSE_X_COORDINATE 0x114
+#define FUSE_Y_COORDINATE 0x118
+
+/* ---------------------- Tegra 124 specific code & data --------------- */
+#define TEGRA124_FUSE_BEGIN 0x100
+
+#define TEGRA124_CPU_PROCESS_CORNERS 2
+#define TEGRA124_GPU_PROCESS_CORNERS 2
+#define TEGRA124_SOC_PROCESS_CORNERS 2
+
+#define TEGRA124_FUSE_SKU_INFO 0x10
+#define TEGRA124_FUSE_CPU_SPEEDO_0 0x14
+#define TEGRA124_FUSE_CPU_IDDQ 0x18
+#define TEGRA124_FUSE_FT_REV 0x28
+#define TEGRA124_FUSE_CPU_SPEEDO_1 0x2c
+#define TEGRA124_FUSE_CPU_SPEEDO_2 0x30
+#define TEGRA124_FUSE_SOC_SPEEDO_0 0x34
+#define TEGRA124_FUSE_SOC_SPEEDO_1 0x38
+#define TEGRA124_FUSE_SOC_SPEEDO_2 0x3c
+#define TEGRA124_FUSE_SOC_IDDQ 0x40
+#define TEGRA124_FUSE_GPU_IDDQ 0x128
+
+enum {
+ TEGRA124_THRESHOLD_INDEX_0,
+ TEGRA124_THRESHOLD_INDEX_1,
+ TEGRA124_THRESHOLD_INDEX_COUNT,
+};
+
+static uint32_t tegra124_cpu_process_speedos[][TEGRA124_CPU_PROCESS_CORNERS] =
+{
+ {2190, UINT_MAX},
+ {0, UINT_MAX},
+};
+
+static uint32_t tegra124_gpu_process_speedos[][TEGRA124_GPU_PROCESS_CORNERS] =
+{
+ {1965, UINT_MAX},
+ {0, UINT_MAX},
+};
+
+static uint32_t tegra124_soc_process_speedos[][TEGRA124_SOC_PROCESS_CORNERS] =
+{
+ {2101, UINT_MAX},
+ {0, UINT_MAX},
+};
+
+static void
+tegra124_rev_sku_to_speedo_ids(struct tegra_efuse_softc *sc,
+ struct tegra_sku_info *sku, int *threshold)
+{
+
+ /* Assign to default */
+ sku->cpu_speedo_id = 0;
+ sku->soc_speedo_id = 0;
+ sku->gpu_speedo_id = 0;
+ *threshold = TEGRA124_THRESHOLD_INDEX_0;
+
+ switch (sku->sku_id) {
+ case 0x00: /* Eng sku */
+ case 0x0F:
+ case 0x23:
+ /* Using the default */
+ break;
+ case 0x83:
+ sku->cpu_speedo_id = 2;
+ break;
+
+ case 0x1F:
+ case 0x87:
+ case 0x27:
+ sku->cpu_speedo_id = 2;
+ sku->soc_speedo_id = 0;
+ sku->gpu_speedo_id = 1;
+ *threshold = TEGRA124_THRESHOLD_INDEX_0;
+ break;
+ case 0x81:
+ case 0x21:
+ case 0x07:
+ sku->cpu_speedo_id = 1;
+ sku->soc_speedo_id = 1;
+ sku->gpu_speedo_id = 1;
+ *threshold = TEGRA124_THRESHOLD_INDEX_1;
+ break;
+ case 0x49:
+ case 0x4A:
+ case 0x48:
+ sku->cpu_speedo_id = 4;
+ sku->soc_speedo_id = 2;
+ sku->gpu_speedo_id = 3;
+ *threshold = TEGRA124_THRESHOLD_INDEX_1;
+ break;
+ default:
+ device_printf(sc->dev, " Unknown SKU ID %d\n", sku->sku_id);
+ break;
+ }
+}
+
+
+static void
+tegra124_init_speedo(struct tegra_efuse_softc *sc, struct tegra_sku_info *sku)
+{
+ int i, threshold;
+
+ sku->sku_id = RD4(sc, TEGRA124_FUSE_SKU_INFO);
+ sku->soc_iddq_value = RD4(sc, TEGRA124_FUSE_SOC_IDDQ);
+ sku->cpu_iddq_value = RD4(sc, TEGRA124_FUSE_CPU_IDDQ);
+ sku->gpu_iddq_value = RD4(sc, TEGRA124_FUSE_GPU_IDDQ);
+ sku->soc_speedo_value = RD4(sc, TEGRA124_FUSE_SOC_SPEEDO_0);
+ sku->cpu_speedo_value = RD4(sc, TEGRA124_FUSE_CPU_SPEEDO_0);
+ sku->gpu_speedo_value = RD4(sc, TEGRA124_FUSE_CPU_SPEEDO_2);
+
+ if (sku->cpu_speedo_value == 0) {
+ device_printf(sc->dev, "CPU Speedo value is not fused.\n");
+ return;
+ }
+
+ tegra124_rev_sku_to_speedo_ids(sc, sku, &threshold);
+
+ for (i = 0; i < TEGRA124_SOC_PROCESS_CORNERS; i++) {
+ if (sku->soc_speedo_value <
+ tegra124_soc_process_speedos[threshold][i])
+ break;
+ }
+ sku->soc_process_id = i;
+
+ for (i = 0; i < TEGRA124_CPU_PROCESS_CORNERS; i++) {
+ if (sku->cpu_speedo_value <
+ tegra124_cpu_process_speedos[threshold][i])
+ break;
+ }
+ sku->cpu_process_id = i;
+
+ for (i = 0; i < TEGRA124_GPU_PROCESS_CORNERS; i++) {
+ if (sku->gpu_speedo_value <
+ tegra124_gpu_process_speedos[threshold][i])
+ break;
+ }
+ sku->gpu_process_id = i;
+
+}
+
+/* ----------------- End of Tegra 124 specific code & data --------------- */
+
+uint32_t
+tegra_fuse_read_4(int addr) {
+
+ if (dev_sc == NULL)
+ panic("tegra_fuse_read_4 called too early");
+ return (RD4(dev_sc, addr));
+}
+
+
+static void
+tegra_efuse_dump_sku()
+{
+ printf(" TEGRA SKU Info:\n");
+ printf(" chip_id: %u\n", tegra_sku_info.chip_id);
+ printf(" sku_id: %u\n", tegra_sku_info.sku_id);
+ printf(" cpu_process_id: %u\n", tegra_sku_info.cpu_process_id);
+ printf(" cpu_speedo_id: %u\n", tegra_sku_info.cpu_speedo_id);
+ printf(" cpu_speedo_value: %u\n", tegra_sku_info.cpu_speedo_value);
+ printf(" cpu_iddq_value: %u\n", tegra_sku_info.cpu_iddq_value);
+ printf(" soc_process_id: %u\n", tegra_sku_info.soc_process_id);
+ printf(" soc_speedo_id: %u\n", tegra_sku_info.soc_speedo_id);
+ printf(" soc_speedo_value: %u\n", tegra_sku_info.soc_speedo_value);
+ printf(" soc_iddq_value: %u\n", tegra_sku_info.soc_iddq_value);
+ printf(" gpu_process_id: %u\n", tegra_sku_info.gpu_process_id);
+ printf(" gpu_speedo_id: %u\n", tegra_sku_info.gpu_speedo_id);
+ printf(" gpu_speedo_value: %u\n", tegra_sku_info.gpu_speedo_value);
+ printf(" gpu_iddq_value: %u\n", tegra_sku_info.gpu_iddq_value);
+ printf(" revision: %s\n", tegra_rev_name[tegra_sku_info.revision]);
+}
+
+static int
+tegra_efuse_probe(device_t dev)
+{
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+tegra_efuse_attach(device_t dev)
+{
+ int rv, rid;
+ phandle_t node;
+ struct tegra_efuse_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ node = ofw_bus_get_node(dev);
+
+ /* Get the memory resource for the register mapping. */
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev, "Cannot map registers.\n");
+ rv = ENXIO;
+ goto fail;
+ }
+
+ /* OFW resources. */
+ rv = clk_get_by_ofw_name(dev, "fuse", &sc->clk);
+ if (rv != 0) {
+ device_printf(dev, "Cannot get fuse clock: %d\n", rv);
+ goto fail;
+ }
+ rv = clk_enable(sc->clk);
+ if (rv != 0) {
+ device_printf(dev, "Cannot enable clock: %d\n", rv);
+ goto fail;
+ }
+ rv = hwreset_get_by_ofw_name(sc->dev, "fuse", &sc->reset);
+ if (rv != 0) {
+ device_printf(dev, "Cannot get fuse reset\n");
+ goto fail;
+ }
+ rv = hwreset_deassert(sc->reset);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot clear reset\n");
+ goto fail;
+ }
+
+ /* Tegra124 specific init. */
+ sc->fuse_begin = TEGRA124_FUSE_BEGIN;
+ tegra124_init_speedo(sc, &tegra_sku_info);
+
+ dev_sc = sc;
+
+ if (bootverbose)
+ tegra_efuse_dump_sku();
+ return (bus_generic_attach(dev));
+
+fail:
+ dev_sc = NULL;
+ if (sc->clk != NULL)
+ clk_release(sc->clk);
+ if (sc->reset != NULL)
+ hwreset_release(sc->reset);
+ if (sc->mem_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
+
+ return (rv);
+}
+
+static int
+tegra_efuse_detach(device_t dev)
+{
+ struct tegra_efuse_softc *sc;
+
+ sc = device_get_softc(dev);
+ dev_sc = NULL;
+ if (sc->clk != NULL)
+ clk_release(sc->clk);
+ if (sc->reset != NULL)
+ hwreset_release(sc->reset);
+ if (sc->mem_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
+
+ return (bus_generic_detach(dev));
+}
+
+static device_method_t tegra_efuse_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, tegra_efuse_probe),
+ DEVMETHOD(device_attach, tegra_efuse_attach),
+ DEVMETHOD(device_detach, tegra_efuse_detach),
+
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(tegra_efuse, tegra_efuse_driver, tegra_efuse_methods,
+ sizeof(struct tegra_efuse_softc));
+static devclass_t tegra_efuse_devclass;
+EARLY_DRIVER_MODULE(tegra_efuse, simplebus, tegra_efuse_driver,
+ tegra_efuse_devclass, 0, 0, BUS_PASS_TIMER);
diff --git a/sys/arm/nvidia/tegra_efuse.h b/sys/arm/nvidia/tegra_efuse.h
new file mode 100644
index 0000000..36804d06
--- /dev/null
+++ b/sys/arm/nvidia/tegra_efuse.h
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _TEGRA_EFUSE_H_
+
+enum tegra_revision {
+ TEGRA_REVISION_UNKNOWN = 0,
+ TEGRA_REVISION_A01,
+ TEGRA_REVISION_A02,
+ TEGRA_REVISION_A03,
+ TEGRA_REVISION_A03p,
+ TEGRA_REVISION_A04,
+};
+
+struct tegra_sku_info {
+ u_int chip_id;
+ u_int sku_id;
+ u_int cpu_process_id;
+ u_int cpu_speedo_id;
+ u_int cpu_speedo_value;
+ u_int cpu_iddq_value;
+ u_int soc_process_id;
+ u_int soc_speedo_id;
+ u_int soc_speedo_value;
+ u_int soc_iddq_value;
+ u_int gpu_process_id;
+ u_int gpu_speedo_id;
+ u_int gpu_speedo_value;
+ u_int gpu_iddq_value;
+ enum tegra_revision revision;
+};
+
+extern struct tegra_sku_info tegra_sku_info;
+uint32_t tegra_fuse_read_4(int addr);
+
+#endif /* _TEGRA_EFUSE_H_ */
diff --git a/sys/arm/nvidia/tegra_ehci.c b/sys/arm/nvidia/tegra_ehci.c
new file mode 100644
index 0000000..e7f7b22
--- /dev/null
+++ b/sys/arm/nvidia/tegra_ehci.c
@@ -0,0 +1,322 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * EHCI driver for Tegra SoCs.
+ */
+#include "opt_bus.h"
+#include "opt_platform.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <dev/extres/clk/clk.h>
+#include <dev/extres/hwreset/hwreset.h>
+#include <dev/extres/phy/phy.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_process.h>
+#include <dev/usb/usb_controller.h>
+#include <dev/usb/usb_bus.h>
+#include <dev/usb/controller/ehci.h>
+#include <dev/usb/controller/ehcireg.h>
+
+#include "usbdevs.h"
+
+#define TEGRA_EHCI_REG_OFF 0x100
+#define TEGRA_EHCI_REG_SIZE 0x100
+
+/* Compatible devices. */
+#define TEGRA124_EHCI 1
+static struct ofw_compat_data compat_data[] = {
+ {"nvidia,tegra124-ehci", (uintptr_t)TEGRA124_EHCI},
+ {NULL, 0},
+};
+
+struct tegra_ehci_softc {
+ ehci_softc_t ehci_softc;
+ device_t dev;
+ struct resource *ehci_mem_res; /* EHCI core regs. */
+ struct resource *ehci_irq_res; /* EHCI core IRQ. */
+ int usb_alloc_called;
+ clk_t clk;
+ phy_t phy;
+ hwreset_t reset;
+};
+
+static void
+tegra_ehci_post_reset(struct ehci_softc *ehci_softc)
+{
+ uint32_t usbmode;
+
+ /* Force HOST mode. */
+ usbmode = EOREAD4(ehci_softc, EHCI_USBMODE_LPM);
+ usbmode &= ~EHCI_UM_CM;
+ usbmode |= EHCI_UM_CM_HOST;
+ device_printf(ehci_softc->sc_bus.bdev, "set host controller mode\n");
+ EOWRITE4(ehci_softc, EHCI_USBMODE_LPM, usbmode);
+}
+
+static int
+tegra_ehci_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) {
+ device_set_desc(dev, "Nvidia Tegra EHCI controller");
+ return (BUS_PROBE_DEFAULT);
+ }
+ return (ENXIO);
+}
+
+static int
+tegra_ehci_detach(device_t dev)
+{
+ struct tegra_ehci_softc *sc;
+ ehci_softc_t *esc;
+
+ sc = device_get_softc(dev);
+
+ esc = &sc->ehci_softc;
+ if (sc->clk != NULL)
+ clk_release(sc->clk);
+ if (esc->sc_bus.bdev != NULL)
+ device_delete_child(dev, esc->sc_bus.bdev);
+ if (esc->sc_flags & EHCI_SCFLG_DONEINIT)
+ ehci_detach(esc);
+ if (esc->sc_intr_hdl != NULL)
+ bus_teardown_intr(dev, esc->sc_irq_res,
+ esc->sc_intr_hdl);
+ if (sc->ehci_irq_res != NULL)
+ bus_release_resource(dev, SYS_RES_IRQ, 0,
+ sc->ehci_irq_res);
+ if (sc->ehci_mem_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0,
+ sc->ehci_mem_res);
+ if (sc->usb_alloc_called)
+ usb_bus_mem_free_all(&esc->sc_bus, &ehci_iterate_hw_softc);
+
+ /* During module unload there are lots of children leftover. */
+ device_delete_children(dev);
+
+ return (0);
+}
+
+static int
+tegra_ehci_attach(device_t dev)
+{
+ struct tegra_ehci_softc *sc;
+ ehci_softc_t *esc;
+ int rv, rid;
+ uint64_t freq;
+ phandle_t node;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ node = ofw_bus_get_node(dev);
+ esc = &sc->ehci_softc;
+
+ /* Allocate resources. */
+ rid = 0;
+ sc->ehci_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (sc->ehci_mem_res == NULL) {
+ device_printf(dev, "Cannot allocate memory resources\n");
+ rv = ENXIO;
+ goto out;
+ }
+
+ rid = 0;
+ sc->ehci_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (sc->ehci_irq_res == NULL) {
+ device_printf(dev, "Cannot allocate IRQ resources\n");
+ rv = ENXIO;
+ goto out;
+ }
+
+ rv = hwreset_get_by_ofw_name(dev, "usb", &sc->reset);
+ if (rv != 0) {
+ device_printf(dev, "Cannot get reset\n");
+ rv = ENXIO;
+ goto out;
+ }
+
+ rv = phy_get_by_ofw_property(sc->dev, "nvidia,phy", &sc->phy);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'nvidia,phy' phy\n");
+ rv = ENXIO;
+ goto out;
+ }
+
+ rv = clk_get_by_ofw_index(sc->dev, 0, &sc->clk);
+ if (rv != 0) {
+ device_printf(dev, "Cannot get clock\n");
+ goto out;
+ }
+
+ rv = clk_enable(sc->clk);
+ if (rv != 0) {
+ device_printf(dev, "Cannot enable clock\n");
+ goto out;
+ }
+
+ freq = 0;
+ rv = clk_get_freq(sc->clk, &freq);
+ if (rv != 0) {
+ device_printf(dev, "Cannot get clock frequency\n");
+ goto out;
+ }
+
+ rv = hwreset_deassert(sc->reset);
+ if (rv != 0) {
+ device_printf(dev, "Cannot clear reset: %d\n", rv);
+ rv = ENXIO;
+ goto out;
+ }
+
+ rv = phy_enable(sc->dev, sc->phy);
+ if (rv != 0) {
+ device_printf(dev, "Cannot enable phy: %d\n", rv);
+ goto out;
+ }
+
+ /* Fill data for EHCI driver. */
+ esc->sc_vendor_get_port_speed = ehci_get_port_speed_hostc;
+ esc->sc_vendor_post_reset = tegra_ehci_post_reset;
+ esc->sc_io_tag = rman_get_bustag(sc->ehci_mem_res);
+ esc->sc_bus.parent = dev;
+ esc->sc_bus.devices = esc->sc_devices;
+ esc->sc_bus.devices_max = EHCI_MAX_DEVICES;
+ esc->sc_bus.dma_bits = 32;
+
+ /* Allocate all DMA memory. */
+ rv = usb_bus_mem_alloc_all(&esc->sc_bus, USB_GET_DMA_TAG(dev),
+ &ehci_iterate_hw_softc);
+ sc->usb_alloc_called = 1;
+ if (rv != 0) {
+ device_printf(dev, "usb_bus_mem_alloc_all() failed\n");
+ rv = ENOMEM;
+ goto out;
+ }
+
+ /*
+ * Set handle to USB related registers subregion used by
+ * generic EHCI driver.
+ */
+ rv = bus_space_subregion(esc->sc_io_tag,
+ rman_get_bushandle(sc->ehci_mem_res),
+ TEGRA_EHCI_REG_OFF, TEGRA_EHCI_REG_SIZE, &esc->sc_io_hdl);
+ if (rv != 0) {
+ device_printf(dev, "Could not create USB memory subregion\n");
+ rv = ENXIO;
+ goto out;
+ }
+
+ /* Setup interrupt handler. */
+ rv = bus_setup_intr(dev, sc->ehci_irq_res, INTR_TYPE_BIO, NULL,
+ (driver_intr_t *)ehci_interrupt, esc, &esc->sc_intr_hdl);
+ if (rv != 0) {
+ device_printf(dev, "Could not setup IRQ\n");
+ goto out;
+ }
+
+ /* Add USB bus device. */
+ esc->sc_bus.bdev = device_add_child(dev, "usbus", -1);
+ if (esc->sc_bus.bdev == NULL) {
+ device_printf(dev, "Could not add USB device\n");
+ goto out;
+ }
+ device_set_ivars(esc->sc_bus.bdev, &esc->sc_bus);
+
+ esc->sc_id_vendor = USB_VENDOR_FREESCALE;
+ strlcpy(esc->sc_vendor, "Nvidia", sizeof(esc->sc_vendor));
+
+ /* Set flags that affect ehci_init() behavior. */
+ esc->sc_flags |= EHCI_SCFLG_TT;
+ esc->sc_flags |= EHCI_SCFLG_NORESTERM;
+ rv = ehci_init(esc);
+ if (rv != 0) {
+ device_printf(dev, "USB init failed: %d\n",
+ rv);
+ goto out;
+ }
+ esc->sc_flags |= EHCI_SCFLG_DONEINIT;
+
+ /* Probe the bus. */
+ rv = device_probe_and_attach(esc->sc_bus.bdev);
+ if (rv != 0) {
+ device_printf(dev,
+ "device_probe_and_attach() failed\n");
+ goto out;
+ }
+ return (0);
+
+out:
+ tegra_ehci_detach(dev);
+ return (rv);
+}
+
+static device_method_t ehci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, tegra_ehci_probe),
+ DEVMETHOD(device_attach, tegra_ehci_attach),
+ DEVMETHOD(device_detach, tegra_ehci_detach),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+
+ DEVMETHOD_END
+};
+
+static driver_t ehci_driver = {
+ "ehci",
+ ehci_methods,
+ sizeof(struct tegra_ehci_softc)
+};
+
+static devclass_t ehci_devclass;
+DRIVER_MODULE(ehci, simplebus, ehci_driver, ehci_devclass, 0, 0);
+MODULE_DEPEND(ehci, usb, 1, 1, 1); \ No newline at end of file
diff --git a/sys/arm/nvidia/tegra_gpio.c b/sys/arm/nvidia/tegra_gpio.c
new file mode 100644
index 0000000..f9a1d4d
--- /dev/null
+++ b/sys/arm/nvidia/tegra_gpio.c
@@ -0,0 +1,480 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Tegra GPIO driver.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/gpio.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/gpio/gpiobusvar.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+
+#define GPIO_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define GPIO_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define GPIO_LOCK_INIT(_sc) mtx_init(&_sc->sc_mtx, \
+ device_get_nameunit(_sc->sc_dev), "tegra_gpio", MTX_DEF)
+#define GPIO_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
+#define GPIO_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
+#define GPIO_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
+
+#define WR4(_sc, _r, _v) bus_write_4((_sc)->mem_res, (_r), (_v))
+#define RD4(_sc, _r) bus_read_4((_sc)->mem_res, (_r))
+
+#define GPIO_BANK_OFFS 0x100 /* Bank offset */
+#define GPIO_NUM_BANKS 8 /* Total number per bank */
+#define GPIO_REGS_IN_BANK 4 /* Total registers in bank */
+#define GPIO_PINS_IN_REG 8 /* Total pin in register */
+
+#define GPIO_BANKNUM(n) ((n) / (GPIO_REGS_IN_BANK * GPIO_PINS_IN_REG))
+#define GPIO_PORTNUM(n) (((n) / GPIO_PINS_IN_REG) % GPIO_REGS_IN_BANK)
+#define GPIO_BIT(n) ((n) % GPIO_PINS_IN_REG)
+
+#define GPIO_REGNUM(n) (GPIO_BANKNUM(n) * GPIO_BANK_OFFS + \
+ GPIO_PORTNUM(n) * 4)
+
+#define NGPIO ((GPIO_NUM_BANKS * GPIO_REGS_IN_BANK * GPIO_PINS_IN_REG) - 8)
+
+/* Register offsets */
+#define GPIO_CNF 0x00
+#define GPIO_OE 0x10
+#define GPIO_OUT 0x20
+#define GPIO_IN 0x30
+#define GPIO_INT_STA 0x40
+#define GPIO_INT_ENB 0x50
+#define GPIO_INT_LVL 0x60
+#define GPIO_INT_CLR 0x70
+#define GPIO_MSK_CNF 0x80
+#define GPIO_MSK_OE 0x90
+#define GPIO_MSK_OUT 0xA0
+#define GPIO_MSK_INT_STA 0xC0
+#define GPIO_MSK_INT_ENB 0xD0
+#define GPIO_MSK_INT_LVL 0xE0
+
+char *tegra_gpio_port_names[] = {
+ "A", "B", "C", "D", /* Bank 0 */
+ "E", "F", "G", "H", /* Bank 1 */
+ "I", "J", "K", "L", /* Bank 2 */
+ "M", "N", "O", "P", /* Bank 3 */
+ "Q", "R", "S", "T", /* Bank 4 */
+ "U", "V", "W", "X", /* Bank 5 */
+ "Y", "Z", "AA", "BB", /* Bank 5 */
+ "CC", "DD", "EE" /* Bank 5 */
+};
+
+struct tegra_gpio_softc {
+ device_t dev;
+ device_t sc_busdev;
+ struct mtx sc_mtx;
+ struct resource *mem_res;
+ struct resource *irq_res;
+ void *gpio_ih;
+ int gpio_npins;
+ struct gpio_pin gpio_pins[NGPIO];
+};
+
+static struct ofw_compat_data compat_data[] = {
+ {"nvidia,tegra124-gpio", 1},
+ {NULL, 0}
+};
+
+static inline void
+gpio_write_masked(struct tegra_gpio_softc *sc, bus_size_t reg,
+ struct gpio_pin *pin, uint32_t val)
+{
+ uint32_t tmp;
+ int bit;
+
+ bit = GPIO_BIT(pin->gp_pin);
+ tmp = 0x100 << bit; /* mask */
+ tmp |= (val & 1) << bit; /* value */
+ bus_write_4(sc->mem_res, reg + GPIO_REGNUM(pin->gp_pin), tmp);
+}
+static inline uint32_t
+gpio_read(struct tegra_gpio_softc *sc, bus_size_t reg, struct gpio_pin *pin)
+{
+ int bit;
+ uint32_t val;
+
+ bit = GPIO_BIT(pin->gp_pin);
+ val = bus_read_4(sc->mem_res, reg + GPIO_REGNUM(pin->gp_pin));
+ return (val >> bit) & 1;
+}
+
+static void
+tegra_gpio_pin_configure(struct tegra_gpio_softc *sc, struct gpio_pin *pin,
+ unsigned int flags)
+{
+
+ if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) == 0)
+ return;
+
+ /* Manage input/output */
+ pin->gp_flags &= ~(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT);
+ if (flags & GPIO_PIN_OUTPUT) {
+ pin->gp_flags |= GPIO_PIN_OUTPUT;
+ gpio_write_masked(sc, GPIO_MSK_OE, pin, 1);
+ } else {
+ pin->gp_flags |= GPIO_PIN_INPUT;
+ gpio_write_masked(sc, GPIO_MSK_OE, pin, 0);
+ }
+}
+
+static device_t
+tegra_gpio_get_bus(device_t dev)
+{
+ struct tegra_gpio_softc *sc;
+
+ sc = device_get_softc(dev);
+ return (sc->sc_busdev);
+}
+
+static int
+tegra_gpio_pin_max(device_t dev, int *maxpin)
+{
+
+ *maxpin = NGPIO - 1;
+ return (0);
+}
+
+static int
+tegra_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
+{
+ struct tegra_gpio_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (pin >= sc->gpio_npins)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ *caps = sc->gpio_pins[pin].gp_caps;
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+tegra_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
+{
+ struct tegra_gpio_softc *sc;
+ int cnf;
+
+ sc = device_get_softc(dev);
+ if (pin >= sc->gpio_npins)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ cnf = gpio_read(sc, GPIO_CNF, &sc->gpio_pins[pin]);
+ if (cnf == 0) {
+ GPIO_UNLOCK(sc);
+ return (ENXIO);
+ }
+ *flags = sc->gpio_pins[pin].gp_flags;
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+tegra_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
+{
+ struct tegra_gpio_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (pin >= sc->gpio_npins)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ memcpy(name, sc->gpio_pins[pin].gp_name, GPIOMAXNAME);
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+tegra_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
+{
+ struct tegra_gpio_softc *sc;
+ int cnf;
+
+ sc = device_get_softc(dev);
+ if (pin >= sc->gpio_npins)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ cnf = gpio_read(sc, GPIO_CNF, &sc->gpio_pins[pin]);
+ if (cnf == 0) {
+ /* XXX - allow this for while ....
+ GPIO_UNLOCK(sc);
+ return (ENXIO);
+ */
+ gpio_write_masked(sc, GPIO_MSK_CNF, &sc->gpio_pins[pin], 1);
+ }
+ tegra_gpio_pin_configure(sc, &sc->gpio_pins[pin], flags);
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+tegra_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
+{
+ struct tegra_gpio_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (pin >= sc->gpio_npins)
+ return (EINVAL);
+ GPIO_LOCK(sc);
+ gpio_write_masked(sc, GPIO_MSK_OUT, &sc->gpio_pins[pin], value);
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+tegra_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
+{
+ struct tegra_gpio_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (pin >= sc->gpio_npins)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ *val = gpio_read(sc, GPIO_IN, &sc->gpio_pins[pin]);
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+tegra_gpio_pin_toggle(device_t dev, uint32_t pin)
+{
+ struct tegra_gpio_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (pin >= sc->gpio_npins)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ gpio_write_masked(sc, GPIO_MSK_OE, &sc->gpio_pins[pin],
+ gpio_read(sc, GPIO_IN, &sc->gpio_pins[pin]) ^ 1);
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+tegra_gpio_intr(void *arg)
+{
+ struct tegra_gpio_softc *sc;
+ uint32_t val;
+ int i;
+
+ sc = arg;
+ for (i = 0; i < NGPIO; i += GPIO_PINS_IN_REG) {
+ /* Clear interrupt */
+ val = bus_read_4(sc->mem_res, GPIO_INT_STA + GPIO_REGNUM(i));
+ val &= bus_read_4(sc->mem_res, GPIO_INT_ENB + GPIO_REGNUM(i));
+ bus_write_4(sc->mem_res, GPIO_INT_CLR + GPIO_REGNUM(i), val);
+ /* Interrupt handling */
+#ifdef not_yet
+ for (j = 0; j < GPIO_PINS_IN_REG; j++) {
+ if (val & (1 << j))
+ handle_irq(i + j);
+ }
+ */
+#endif
+ }
+ return (FILTER_HANDLED);
+}
+
+static int
+tegra_gpio_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) {
+ device_set_desc(dev, "Tegra GPIO Controller");
+ return (BUS_PROBE_DEFAULT);
+ }
+
+ return (ENXIO);
+}
+
+static int
+tegra_gpio_detach(device_t dev)
+{
+ struct tegra_gpio_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ KASSERT(mtx_initialized(&sc->sc_mtx), ("gpio mutex not initialized"));
+
+ gpiobus_detach_bus(dev);
+ if (sc->gpio_ih != NULL)
+ bus_teardown_intr(dev, sc->irq_res, sc->gpio_ih);
+ if (sc->irq_res != NULL)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
+ if (sc->mem_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
+ mtx_destroy(&sc->sc_mtx);
+
+ return(0);
+}
+
+static int
+tegra_gpio_attach(device_t dev)
+{
+ struct tegra_gpio_softc *sc;
+ int i, rid;
+
+ sc = device_get_softc(dev);
+ mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+
+ /* Allocate bus_space resources. */
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev, "Cannot allocate memory resources\n");
+ tegra_gpio_detach(dev);
+ return (ENXIO);
+ }
+
+ rid = 0;
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
+ if (sc->irq_res == NULL) {
+ device_printf(dev, "Cannot allocate IRQ resources\n");
+ tegra_gpio_detach(dev);
+ return (ENXIO);
+ }
+
+ sc->dev = dev;
+ sc->gpio_npins = NGPIO;
+
+ if ((bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC,
+ tegra_gpio_intr, NULL, sc, &sc->gpio_ih))) {
+ device_printf(dev,
+ "WARNING: unable to register interrupt handler\n");
+ tegra_gpio_detach(dev);
+ return (ENXIO);
+ }
+
+ for (i = 0; i < sc->gpio_npins; i++) {
+ sc->gpio_pins[i].gp_pin = i;
+ sc->gpio_pins[i].gp_caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
+ snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME, "gpio_%s.%d",
+ tegra_gpio_port_names[ i / GPIO_PINS_IN_REG],
+ i % GPIO_PINS_IN_REG);
+ sc->gpio_pins[i].gp_flags =
+ gpio_read(sc, GPIO_OE, &sc->gpio_pins[i]) != 0 ?
+ GPIO_PIN_OUTPUT : GPIO_PIN_INPUT;
+ }
+
+ sc->sc_busdev = gpiobus_attach_bus(dev);
+ if (sc->sc_busdev == NULL) {
+ tegra_gpio_detach(dev);
+ return (ENXIO);
+ }
+
+ return (bus_generic_attach(dev));
+}
+
+static int
+tegra_map_gpios(device_t dev, phandle_t pdev, phandle_t gparent,
+ int gcells, pcell_t *gpios, uint32_t *pin, uint32_t *flags)
+{
+
+ if (gcells != 2)
+ return (ERANGE);
+ *pin = gpios[0];
+ *flags= gpios[1];
+ return (0);
+}
+
+static phandle_t
+tegra_gpio_get_node(device_t bus, device_t dev)
+{
+
+ /* We only have one child, the GPIO bus, which needs our own node. */
+ return (ofw_bus_get_node(bus));
+}
+
+static device_method_t tegra_gpio_methods[] = {
+ DEVMETHOD(device_probe, tegra_gpio_probe),
+ DEVMETHOD(device_attach, tegra_gpio_attach),
+ DEVMETHOD(device_detach, tegra_gpio_detach),
+
+ /* GPIO protocol */
+ DEVMETHOD(gpio_get_bus, tegra_gpio_get_bus),
+ DEVMETHOD(gpio_pin_max, tegra_gpio_pin_max),
+ DEVMETHOD(gpio_pin_getname, tegra_gpio_pin_getname),
+ DEVMETHOD(gpio_pin_getflags, tegra_gpio_pin_getflags),
+ DEVMETHOD(gpio_pin_getcaps, tegra_gpio_pin_getcaps),
+ DEVMETHOD(gpio_pin_setflags, tegra_gpio_pin_setflags),
+ DEVMETHOD(gpio_pin_get, tegra_gpio_pin_get),
+ DEVMETHOD(gpio_pin_set, tegra_gpio_pin_set),
+ DEVMETHOD(gpio_pin_toggle, tegra_gpio_pin_toggle),
+ DEVMETHOD(gpio_map_gpios, tegra_map_gpios),
+
+ /* ofw_bus interface */
+ DEVMETHOD(ofw_bus_get_node, tegra_gpio_get_node),
+
+ DEVMETHOD_END
+};
+
+static driver_t tegra_gpio_driver = {
+ "gpio",
+ tegra_gpio_methods,
+ sizeof(struct tegra_gpio_softc),
+};
+static devclass_t tegra_gpio_devclass;
+
+EARLY_DRIVER_MODULE(tegra_gpio, simplebus, tegra_gpio_driver,
+ tegra_gpio_devclass, 0, 0, 70);
diff --git a/sys/arm/nvidia/tegra_i2c.c b/sys/arm/nvidia/tegra_i2c.c
new file mode 100644
index 0000000..65d8935
--- /dev/null
+++ b/sys/arm/nvidia/tegra_i2c.c
@@ -0,0 +1,804 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * I2C driver for Tegra SoCs.
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/limits.h>
+#include <sys/module.h>
+#include <sys/resource.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <dev/extres/clk/clk.h>
+#include <dev/extres/hwreset/hwreset.h>
+#include <dev/fdt/fdt_common.h>
+#include <dev/iicbus/iiconf.h>
+#include <dev/iicbus/iicbus.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "iicbus_if.h"
+
+#define I2C_CNFG 0x000
+#define I2C_CNFG_MSTR_CLR_BUS_ON_TIMEOUT (1 << 15)
+#define I2C_CNFG_DEBOUNCE_CNT(x) (((x) & 0x07) << 12)
+#define I2C_CNFG_NEW_MASTER_FSM (1 << 11)
+#define I2C_CNFG_PACKET_MODE_EN (1 << 10)
+#define I2C_CNFG_SEND (1 << 9)
+#define I2C_CNFG_NOACK (1 << 8)
+#define I2C_CNFG_CMD2 (1 << 7)
+#define I2C_CNFG_CMD1 (1 << 6)
+#define I2C_CNFG_START (1 << 5)
+#define I2C_CNFG_SLV2 (1 << 4)
+#define I2C_CNFG_LENGTH_SHIFT 1
+#define I2C_CNFG_LENGTH_MASK 0x7
+#define I2C_CNFG_A_MOD (1 << 0)
+
+#define I2C_CMD_ADDR0 0x004
+#define I2C_CMD_ADDR1 0x008
+#define I2C_CMD_DATA1 0x00c
+#define I2C_CMD_DATA2 0x010
+#define I2C_STATUS 0x01c
+#define I2C_SL_CNFG 0x020
+#define I2C_SL_RCVD 0x024
+#define I2C_SL_STATUS 0x028
+#define I2C_SL_ADDR1 0x02c
+#define I2C_SL_ADDR2 0x030
+#define I2C_TLOW_SEXT 0x034
+#define I2C_SL_DELAY_COUNT 0x03c
+#define I2C_SL_INT_MASK 0x040
+#define I2C_SL_INT_SOURCE 0x044
+#define I2C_SL_INT_SET 0x048
+#define I2C_TX_PACKET_FIFO 0x050
+#define I2C_RX_FIFO 0x054
+#define I2C_PACKET_TRANSFER_STATUS 0x058
+#define I2C_FIFO_CONTROL 0x05c
+#define I2C_FIFO_CONTROL_SLV_TX_FIFO_TRIG(x) (((x) & 0x07) << 13)
+#define I2C_FIFO_CONTROL_SLV_RX_FIFO_TRIG(x) (((x) & 0x07) << 10)
+#define I2C_FIFO_CONTROL_SLV_TX_FIFO_FLUSH (1 << 9)
+#define I2C_FIFO_CONTROL_SLV_RX_FIFO_FLUSH (1 << 8)
+#define I2C_FIFO_CONTROL_TX_FIFO_TRIG(x) (((x) & 0x07) << 5)
+#define I2C_FIFO_CONTROL_RX_FIFO_TRIG(x) (((x) & 0x07) << 2)
+#define I2C_FIFO_CONTROL_TX_FIFO_FLUSH (1 << 1)
+#define I2C_FIFO_CONTROL_RX_FIFO_FLUSH (1 << 0)
+
+#define I2C_FIFO_STATUS 0x060
+#define I2C_FIFO_STATUS_SLV_XFER_ERR_REASON (1 << 25)
+#define I2C_FIFO_STATUS_TX_FIFO_SLV_EMPTY_CNT(x) (((x) >> 20) & 0xF)
+#define I2C_FIFO_STATUS_RX_FIFO_SLV_FULL_CNT(x) (((x) >> 16) & 0xF)
+#define I2C_FIFO_STATUS_TX_FIFO_EMPTY_CNT(x) (((x) >> 4) & 0xF)
+#define I2C_FIFO_STATUS_RX_FIFO_FULL_CNT(x) (((x) >> 0) & 0xF)
+
+#define I2C_INTERRUPT_MASK_REGISTER 0x064
+#define I2C_INTERRUPT_STATUS_REGISTER 0x068
+#define I2C_INT_SLV_ACK_WITHHELD (1 << 28)
+#define I2C_INT_SLV_RD2WR (1 << 27)
+#define I2C_INT_SLV_WR2RD (1 << 26)
+#define I2C_INT_SLV_PKT_XFER_ERR (1 << 25)
+#define I2C_INT_SLV_TX_BUFFER_REQ (1 << 24)
+#define I2C_INT_SLV_RX_BUFFER_FILLED (1 << 23)
+#define I2C_INT_SLV_PACKET_XFER_COMPLETE (1 << 22)
+#define I2C_INT_SLV_TFIFO_OVF (1 << 21)
+#define I2C_INT_SLV_RFIFO_UNF (1 << 20)
+#define I2C_INT_SLV_TFIFO_DATA_REQ (1 << 17)
+#define I2C_INT_SLV_RFIFO_DATA_REQ (1 << 16)
+#define I2C_INT_BUS_CLEAR_DONE (1 << 11)
+#define I2C_INT_TLOW_MEXT_TIMEOUT (1 << 10)
+#define I2C_INT_TLOW_SEXT_TIMEOUT (1 << 9)
+#define I2C_INT_TIMEOUT (1 << 8)
+#define I2C_INT_PACKET_XFER_COMPLETE (1 << 7)
+#define I2C_INT_ALL_PACKETS_XFER_COMPLETE (1 << 6)
+#define I2C_INT_TFIFO_OVR (1 << 5)
+#define I2C_INT_RFIFO_UNF (1 << 4)
+#define I2C_INT_NOACK (1 << 3)
+#define I2C_INT_ARB_LOST (1 << 2)
+#define I2C_INT_TFIFO_DATA_REQ (1 << 1)
+#define I2C_INT_RFIFO_DATA_REQ (1 << 0)
+#define I2C_ERROR_MASK (I2C_INT_ARB_LOST | I2C_INT_NOACK | \
+ I2C_INT_RFIFO_UNF | I2C_INT_TFIFO_OVR)
+
+#define I2C_CLK_DIVISOR 0x06c
+#define I2C_CLK_DIVISOR_STD_FAST_MODE_SHIFT 16
+#define I2C_CLK_DIVISOR_STD_FAST_MODE_MASK 0xffff
+#define I2C_CLK_DIVISOR_HSMODE_SHIFT 0
+#define I2C_CLK_DIVISOR_HSMODE_MASK 0xffff
+#define I2C_INTERRUPT_SOURCE_REGISTER 0x070
+#define I2C_INTERRUPT_SET_REGISTER 0x074
+#define I2C_SLV_TX_PACKET_FIFO 0x07c
+#define I2C_SLV_PACKET_STATUS 0x080
+#define I2C_BUS_CLEAR_CONFIG 0x084
+#define I2C_BUS_CLEAR_CONFIG_BC_SCLK_THRESHOLD(x) (((x) & 0xFF) << 16)
+#define I2C_BUS_CLEAR_CONFIG_BC_STOP_COND (1 << 2)
+#define I2C_BUS_CLEAR_CONFIG_BC_TERMINATE (1 << 1)
+#define I2C_BUS_CLEAR_CONFIG_BC_ENABLE (1 << 0)
+
+#define I2C_BUS_CLEAR_STATUS 0x088
+#define I2C_BUS_CLEAR_STATUS_BC_STATUS (1 << 0)
+
+#define I2C_CONFIG_LOAD 0x08c
+#define I2C_CONFIG_LOAD_TIMEOUT_CONFIG_LOAD (1 << 2)
+#define I2C_CONFIG_LOAD_SLV_CONFIG_LOAD (1 << 1)
+#define I2C_CONFIG_LOAD_MSTR_CONFIG_LOAD (1 << 0)
+
+#define I2C_INTERFACE_TIMING_0 0x094
+#define I2C_INTERFACE_TIMING_1 0x098
+#define I2C_HS_INTERFACE_TIMING_0 0x09c
+#define I2C_HS_INTERFACE_TIMING_1 0x0a0
+
+/* Protocol header 0 */
+#define PACKET_HEADER0_HEADER_SIZE_SHIFT 28
+#define PACKET_HEADER0_HEADER_SIZE_MASK 0x3
+#define PACKET_HEADER0_PACKET_ID_SHIFT 16
+#define PACKET_HEADER0_PACKET_ID_MASK 0xff
+#define PACKET_HEADER0_CONT_ID_SHIFT 12
+#define PACKET_HEADER0_CONT_ID_MASK 0xf
+#define PACKET_HEADER0_PROTOCOL_I2C (1 << 4)
+#define PACKET_HEADER0_TYPE_SHIFT 0
+#define PACKET_HEADER0_TYPE_MASK 0x7
+
+/* I2C header */
+#define I2C_HEADER_HIGHSPEED_MODE (1 << 22)
+#define I2C_HEADER_CONT_ON_NAK (1 << 21)
+#define I2C_HEADER_SEND_START_BYTE (1 << 20)
+#define I2C_HEADER_READ (1 << 19)
+#define I2C_HEADER_10BIT_ADDR (1 << 18)
+#define I2C_HEADER_IE_ENABLE (1 << 17)
+#define I2C_HEADER_REPEAT_START (1 << 16)
+#define I2C_HEADER_CONTINUE_XFER (1 << 15)
+#define I2C_HEADER_MASTER_ADDR_SHIFT 12
+#define I2C_HEADER_MASTER_ADDR_MASK 0x7
+#define I2C_HEADER_SLAVE_ADDR_SHIFT 0
+#define I2C_HEADER_SLAVE_ADDR_MASK 0x3ff
+
+#define I2C_CLK_DIVISOR_STD_FAST_MODE 0x19
+#define I2C_CLK_MULTIPLIER_STD_FAST_MODE 8
+
+#define I2C_REQUEST_TIMEOUT (5 * hz)
+
+#define WR4(_sc, _r, _v) bus_write_4((_sc)->mem_res, (_r), (_v))
+#define RD4(_sc, _r) bus_read_4((_sc)->mem_res, (_r))
+
+#define LOCK(_sc) mtx_lock(&(_sc)->mtx)
+#define UNLOCK(_sc) mtx_unlock(&(_sc)->mtx)
+#define SLEEP(_sc, timeout) \
+ mtx_sleep(sc, &sc->mtx, 0, "i2cbuswait", timeout);
+#define LOCK_INIT(_sc) \
+ mtx_init(&_sc->mtx, device_get_nameunit(_sc->dev), "tegra_i2c", MTX_DEF)
+#define LOCK_DESTROY(_sc) mtx_destroy(&_sc->mtx)
+#define ASSERT_LOCKED(_sc) mtx_assert(&_sc->mtx, MA_OWNED)
+#define ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->mtx, MA_NOTOWNED)
+
+static struct ofw_compat_data compat_data[] = {
+ {"nvidia,tegra124-i2c", 1},
+ {NULL, 0}
+};
+enum tegra_i2c_xfer_type {
+ XFER_STOP, /* Send stop condition after xfer */
+ XFER_REPEAT_START, /* Send repeated start after xfer */
+ XFER_CONTINUE /* Don't send nothing */
+} ;
+
+struct tegra_i2c_softc {
+ device_t dev;
+ struct mtx mtx;
+
+ struct resource *mem_res;
+ struct resource *irq_res;
+ void *irq_h;
+
+ device_t iicbus;
+ clk_t clk;
+ hwreset_t reset;
+ uint32_t core_freq;
+ uint32_t bus_freq;
+ int bus_inuse;
+
+ struct iic_msg *msg;
+ int msg_idx;
+ uint32_t bus_err;
+ int done;
+};
+
+static int
+tegra_i2c_flush_fifo(struct tegra_i2c_softc *sc)
+{
+ int timeout;
+ uint32_t reg;
+
+ reg = RD4(sc, I2C_FIFO_CONTROL);
+ reg |= I2C_FIFO_CONTROL_TX_FIFO_FLUSH | I2C_FIFO_CONTROL_RX_FIFO_FLUSH;
+ WR4(sc, I2C_FIFO_CONTROL, reg);
+
+ timeout = 10;
+ while (timeout > 0) {
+ reg = RD4(sc, I2C_FIFO_CONTROL);
+ reg &= I2C_FIFO_CONTROL_TX_FIFO_FLUSH |
+ I2C_FIFO_CONTROL_RX_FIFO_FLUSH;
+ if (reg == 0)
+ break;
+ DELAY(10);
+ }
+ if (timeout <= 0) {
+ device_printf(sc->dev, "FIFO flush timedout\n");
+ return (ETIMEDOUT);
+ }
+ return (0);
+}
+
+static void
+tegra_i2c_setup_clk(struct tegra_i2c_softc *sc, int clk_freq)
+{
+ int div;
+
+ div = ((sc->core_freq / clk_freq) / 10) - 1;
+ if ((sc->core_freq / (10 * (div + 1))) > clk_freq)
+ div++;
+ if (div > 65535)
+ div = 65535;
+ WR4(sc, I2C_CLK_DIVISOR,
+ (1 << I2C_CLK_DIVISOR_HSMODE_SHIFT) |
+ (div << I2C_CLK_DIVISOR_STD_FAST_MODE_SHIFT));
+}
+
+static void
+tegra_i2c_bus_clear(struct tegra_i2c_softc *sc)
+{
+ int timeout;
+ uint32_t reg, status;
+
+ WR4(sc, I2C_BUS_CLEAR_CONFIG,
+ I2C_BUS_CLEAR_CONFIG_BC_SCLK_THRESHOLD(18) |
+ I2C_BUS_CLEAR_CONFIG_BC_STOP_COND |
+ I2C_BUS_CLEAR_CONFIG_BC_TERMINATE);
+
+ WR4(sc, I2C_CONFIG_LOAD, I2C_CONFIG_LOAD_MSTR_CONFIG_LOAD);
+ for (timeout = 1000; timeout > 0; timeout--) {
+ if (RD4(sc, I2C_CONFIG_LOAD) == 0)
+ break;
+ DELAY(10);
+ }
+ if (timeout <= 0)
+ device_printf(sc->dev, "config load timeouted\n");
+ reg = RD4(sc, I2C_BUS_CLEAR_CONFIG);
+ reg |= I2C_BUS_CLEAR_CONFIG_BC_ENABLE;
+ WR4(sc, I2C_BUS_CLEAR_CONFIG,reg);
+
+ for (timeout = 1000; timeout > 0; timeout--) {
+ if ((RD4(sc, I2C_BUS_CLEAR_CONFIG) &
+ I2C_BUS_CLEAR_CONFIG_BC_ENABLE) == 0)
+ break;
+ DELAY(10);
+ }
+ if (timeout <= 0)
+ device_printf(sc->dev, "bus clear timeouted\n");
+
+ status = RD4(sc, I2C_BUS_CLEAR_STATUS);
+ if ((status & I2C_BUS_CLEAR_STATUS_BC_STATUS) == 0)
+ device_printf(sc->dev, "bus clear failed\n");
+}
+
+static int
+tegra_i2c_hw_init(struct tegra_i2c_softc *sc)
+{
+ int rv, timeout;
+
+ /* Reset the core. */
+ rv = hwreset_assert(sc->reset);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot assert reset\n");
+ return (rv);
+ }
+ DELAY(10);
+ rv = hwreset_deassert(sc->reset);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot clear reset\n");
+ return (rv);
+ }
+
+ WR4(sc, I2C_INTERRUPT_MASK_REGISTER, 0);
+ WR4(sc, I2C_INTERRUPT_STATUS_REGISTER, 0xFFFFFFFF);
+ WR4(sc, I2C_CNFG, I2C_CNFG_NEW_MASTER_FSM | I2C_CNFG_PACKET_MODE_EN |
+ I2C_CNFG_DEBOUNCE_CNT(2));
+
+ tegra_i2c_setup_clk(sc, sc->bus_freq);
+
+ WR4(sc, I2C_FIFO_CONTROL, I2C_FIFO_CONTROL_TX_FIFO_TRIG(7) |
+ I2C_FIFO_CONTROL_RX_FIFO_TRIG(0));
+
+ WR4(sc, I2C_CONFIG_LOAD, I2C_CONFIG_LOAD_MSTR_CONFIG_LOAD);
+ for (timeout = 1000; timeout > 0; timeout--) {
+ if (RD4(sc, I2C_CONFIG_LOAD) == 0)
+ break;
+ DELAY(10);
+ }
+ if (timeout <= 0)
+ device_printf(sc->dev, "config load timeouted\n");
+
+ tegra_i2c_bus_clear(sc);
+ return (0);
+}
+
+static int
+tegra_i2c_tx(struct tegra_i2c_softc *sc)
+{
+ uint32_t reg;
+ int cnt, i;
+
+ if (sc->msg_idx >= sc->msg->len)
+ panic("Invalid call to tegra_i2c_tx\n");
+
+ while(sc->msg_idx < sc->msg->len) {
+ reg = RD4(sc, I2C_FIFO_STATUS);
+ if (I2C_FIFO_STATUS_TX_FIFO_EMPTY_CNT(reg) == 0)
+ break;
+ cnt = min(4, sc->msg->len - sc->msg_idx);
+ reg = 0;
+ for (i = 0; i < cnt; i++) {
+ reg |= sc->msg->buf[sc->msg_idx] << (i * 8);
+ sc->msg_idx++;
+ }
+ WR4(sc, I2C_TX_PACKET_FIFO, reg);
+ }
+ if (sc->msg_idx >= sc->msg->len)
+ return (0);
+ return (sc->msg->len - sc->msg_idx - 1);
+}
+
+static int
+tegra_i2c_rx(struct tegra_i2c_softc *sc)
+{
+ uint32_t reg;
+ int cnt, i;
+
+ if (sc->msg_idx >= sc->msg->len)
+ panic("Invalid call to tegra_i2c_rx\n");
+
+ while(sc->msg_idx < sc->msg->len) {
+ reg = RD4(sc, I2C_FIFO_STATUS);
+ if (I2C_FIFO_STATUS_RX_FIFO_FULL_CNT(reg) == 0)
+ break;
+ cnt = min(4, sc->msg->len - sc->msg_idx);
+ reg = RD4(sc, I2C_RX_FIFO);
+ for (i = 0; i < cnt; i++) {
+ sc->msg->buf[sc->msg_idx] = (reg >> (i * 8)) & 0xFF;
+ sc->msg_idx++;
+ }
+ }
+
+ if (sc->msg_idx >= sc->msg->len)
+ return (0);
+ return (sc->msg->len - sc->msg_idx - 1);
+}
+
+static void
+tegra_i2c_intr(void *arg)
+{
+ struct tegra_i2c_softc *sc;
+ uint32_t status, reg;
+ int rv;
+
+ sc = (struct tegra_i2c_softc *)arg;
+
+ LOCK(sc);
+ status = RD4(sc, I2C_INTERRUPT_SOURCE_REGISTER);
+ if (sc->msg == NULL) {
+ /* Unexpected interrupt - disable FIFOs, clear reset. */
+ reg = RD4(sc, I2C_INTERRUPT_MASK_REGISTER);
+ reg &= ~I2C_INT_TFIFO_DATA_REQ;
+ reg &= ~I2C_INT_RFIFO_DATA_REQ;
+ WR4(sc, I2C_INTERRUPT_MASK_REGISTER, 0);
+ WR4(sc, I2C_INTERRUPT_STATUS_REGISTER, status);
+ UNLOCK(sc);
+ return;
+ }
+
+ if ((status & I2C_ERROR_MASK) != 0) {
+ if (status & I2C_INT_NOACK)
+ sc->bus_err = IIC_ENOACK;
+ if (status & I2C_INT_ARB_LOST)
+ sc->bus_err = IIC_EBUSERR;
+ if ((status & I2C_INT_TFIFO_OVR) ||
+ (status & I2C_INT_RFIFO_UNF))
+ sc->bus_err = IIC_EBUSERR;
+ sc->done = 1;
+ } else if ((status & I2C_INT_RFIFO_DATA_REQ) &&
+ (sc->msg != NULL) && (sc->msg->flags & IIC_M_RD)) {
+ rv = tegra_i2c_rx(sc);
+ if (rv == 0) {
+ reg = RD4(sc, I2C_INTERRUPT_MASK_REGISTER);
+ reg &= ~I2C_INT_RFIFO_DATA_REQ;
+ WR4(sc, I2C_INTERRUPT_MASK_REGISTER, reg);
+ }
+ } else if ((status & I2C_INT_TFIFO_DATA_REQ) &&
+ (sc->msg != NULL) && !(sc->msg->flags & IIC_M_RD)) {
+ rv = tegra_i2c_tx(sc);
+ if (rv == 0) {
+ reg = RD4(sc, I2C_INTERRUPT_MASK_REGISTER);
+ reg &= ~I2C_INT_TFIFO_DATA_REQ;
+ WR4(sc, I2C_INTERRUPT_MASK_REGISTER, reg);
+ }
+ } else if ((status & I2C_INT_RFIFO_DATA_REQ) ||
+ (status & I2C_INT_TFIFO_DATA_REQ)) {
+ device_printf(sc->dev, "Unexpected data interrupt: 0x%08X\n",
+ status);
+ reg = RD4(sc, I2C_INTERRUPT_MASK_REGISTER);
+ reg &= ~I2C_INT_TFIFO_DATA_REQ;
+ reg &= ~I2C_INT_RFIFO_DATA_REQ;
+ WR4(sc, I2C_INTERRUPT_MASK_REGISTER, reg);
+ }
+ if (status & I2C_INT_PACKET_XFER_COMPLETE)
+ sc->done = 1;
+ WR4(sc, I2C_INTERRUPT_STATUS_REGISTER, status);
+ if (sc->done) {
+ WR4(sc, I2C_INTERRUPT_MASK_REGISTER, 0);
+ wakeup(&(sc->done));
+ }
+ UNLOCK(sc);
+}
+
+static void
+tegra_i2c_start_msg(struct tegra_i2c_softc *sc, struct iic_msg *msg,
+ enum tegra_i2c_xfer_type xtype)
+{
+ uint32_t tmp, mask;
+
+ /* Packet header. */
+ tmp = (0 << PACKET_HEADER0_HEADER_SIZE_SHIFT) |
+ PACKET_HEADER0_PROTOCOL_I2C |
+ (1 << PACKET_HEADER0_CONT_ID_SHIFT) |
+ (1 << PACKET_HEADER0_PACKET_ID_SHIFT);
+ WR4(sc, I2C_TX_PACKET_FIFO, tmp);
+
+
+ /* Packet size. */
+ WR4(sc, I2C_TX_PACKET_FIFO, msg->len - 1);
+
+ /* I2C header. */
+ tmp = I2C_HEADER_IE_ENABLE;
+ if (xtype == XFER_CONTINUE)
+ tmp |= I2C_HEADER_CONTINUE_XFER;
+ else if (xtype == XFER_REPEAT_START)
+ tmp |= I2C_HEADER_REPEAT_START;
+ tmp |= msg->slave << I2C_HEADER_SLAVE_ADDR_SHIFT;
+ if (msg->flags & IIC_M_RD) {
+ tmp |= I2C_HEADER_READ;
+ tmp |= 1 << I2C_HEADER_SLAVE_ADDR_SHIFT;
+ } else
+ tmp &= ~(1 << I2C_HEADER_SLAVE_ADDR_SHIFT);
+
+ WR4(sc, I2C_TX_PACKET_FIFO, tmp);
+
+ /* Interrupt mask. */
+ mask = I2C_INT_NOACK | I2C_INT_ARB_LOST | I2C_INT_PACKET_XFER_COMPLETE;
+ if (msg->flags & IIC_M_RD)
+ mask |= I2C_INT_RFIFO_DATA_REQ;
+ else
+ mask |= I2C_INT_TFIFO_DATA_REQ;
+ WR4(sc, I2C_INTERRUPT_MASK_REGISTER, mask);
+}
+
+static int
+tegra_i2c_poll(struct tegra_i2c_softc *sc)
+{
+ int timeout;
+
+ for(timeout = 10000; timeout > 0; timeout--) {
+ UNLOCK(sc);
+ tegra_i2c_intr(sc);
+ LOCK(sc);
+ if (sc->done != 0)
+ break;
+ DELAY(1);
+ }
+ if (timeout <= 0)
+ return (ETIMEDOUT);
+ return (0);
+}
+
+static int
+tegra_i2c_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
+{
+ int rv, i;
+ struct tegra_i2c_softc *sc;
+ enum tegra_i2c_xfer_type xtype;
+
+ sc = device_get_softc(dev);
+ LOCK(sc);
+
+ /* Get the bus. */
+ while (sc->bus_inuse == 1)
+ SLEEP(sc, 0);
+ sc->bus_inuse = 1;
+
+ rv = 0;
+ for (i = 0; i < nmsgs; i++) {
+ sc->msg = &msgs[i];
+ sc->msg_idx = 0;
+ sc->bus_err = 0;
+ sc->done = 0;
+ /* Check for valid parameters. */
+ if (sc->msg == NULL || sc->msg->buf == NULL ||
+ sc->msg->len == 0) {
+ rv = EINVAL;
+ break;
+ }
+
+ /* Get flags for next transfer. */
+ if (i == (nmsgs - 1)) {
+ if (msgs[i].flags & IIC_M_NOSTOP)
+ xtype = XFER_CONTINUE;
+ else
+ xtype = XFER_STOP;
+ } else {
+ if (msgs[i + 1].flags & IIC_M_NOSTART)
+ xtype = XFER_CONTINUE;
+ else
+ xtype = XFER_REPEAT_START;
+ }
+ tegra_i2c_start_msg(sc, sc->msg, xtype);
+ if (cold)
+ rv = tegra_i2c_poll(sc);
+ else
+ rv = msleep(&sc->done, &sc->mtx, PZERO, "iic",
+ I2C_REQUEST_TIMEOUT);
+
+ WR4(sc, I2C_INTERRUPT_MASK_REGISTER, 0);
+ WR4(sc, I2C_INTERRUPT_STATUS_REGISTER, 0xFFFFFFFF);
+ if (rv == 0)
+ rv = sc->bus_err;
+ if (rv != 0)
+ break;
+ }
+
+ if (rv != 0) {
+ tegra_i2c_hw_init(sc);
+ tegra_i2c_flush_fifo(sc);
+ }
+
+ sc->msg = NULL;
+ sc->msg_idx = 0;
+ sc->bus_err = 0;
+ sc->done = 0;
+
+ /* Wake up the processes that are waiting for the bus. */
+ sc->bus_inuse = 0;
+ wakeup(sc);
+ UNLOCK(sc);
+
+ return (rv);
+}
+
+static int
+tegra_i2c_iicbus_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
+{
+ struct tegra_i2c_softc *sc;
+ int busfreq;
+
+ sc = device_get_softc(dev);
+ busfreq = IICBUS_GET_FREQUENCY(sc->iicbus, speed);
+ sc = device_get_softc(dev);
+ LOCK(sc);
+ tegra_i2c_setup_clk(sc, busfreq);
+ UNLOCK(sc);
+ return (0);
+}
+
+static int
+tegra_i2c_probe(device_t dev)
+{
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+tegra_i2c_attach(device_t dev)
+{
+ int rv, rid;
+ phandle_t node;
+ struct tegra_i2c_softc *sc;
+ uint64_t freq;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ node = ofw_bus_get_node(dev);
+
+ LOCK_INIT(sc);
+
+ /* Get the memory resource for the register mapping. */
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev, "Cannot map registers.\n");
+ rv = ENXIO;
+ goto fail;
+ }
+
+ /* Allocate our IRQ resource. */
+ rid = 0;
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (sc->irq_res == NULL) {
+ device_printf(dev, "Cannot allocate interrupt.\n");
+ rv = ENXIO;
+ goto fail;
+ }
+
+ /* FDT resources. */
+ rv = clk_get_by_ofw_name(dev, "div-clk", &sc->clk);
+ if (rv != 0) {
+ device_printf(dev, "Cannot get i2c clock: %d\n", rv);
+ goto fail;
+ }
+ rv = hwreset_get_by_ofw_name(sc->dev, "i2c", &sc->reset);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get i2c reset\n");
+ return (ENXIO);
+ }
+ rv = OF_getencprop(node, "clock-frequency", &sc->bus_freq,
+ sizeof(sc->bus_freq));
+ if (rv != sizeof(sc->bus_freq)) {
+ sc->bus_freq = 100000;
+ goto fail;
+ }
+
+ /* Request maximum frequency for I2C block 136MHz (408MHz / 3). */
+ rv = clk_set_freq(sc->clk, 136000000, CLK_SET_ROUND_DOWN);
+ if (rv != 0) {
+ device_printf(dev, "Cannot set clock frequency\n");
+ goto fail;
+ }
+ rv = clk_get_freq(sc->clk, &freq);
+ if (rv != 0) {
+ device_printf(dev, "Cannot get clock frequency\n");
+ goto fail;
+ }
+ sc->core_freq = (uint32_t)freq;
+
+ rv = clk_enable(sc->clk);
+ if (rv != 0) {
+ device_printf(dev, "Cannot enable clock: %d\n", rv);
+ goto fail;
+ }
+
+ /* Init hardware. */
+ rv = tegra_i2c_hw_init(sc);
+ if (rv) {
+ device_printf(dev, "tegra_i2c_activate failed\n");
+ goto fail;
+ }
+
+ /* Setup interrupt. */
+ rv = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
+ NULL, tegra_i2c_intr, sc, &sc->irq_h);
+ if (rv) {
+ device_printf(dev, "Cannot setup interrupt.\n");
+ goto fail;
+ }
+
+ /* Attach the iicbus. */
+ sc->iicbus = device_add_child(dev, "iicbus", -1);
+ if (sc->iicbus == NULL) {
+ device_printf(dev, "Could not allocate iicbus instance.\n");
+ rv = ENXIO;
+ goto fail;
+ }
+
+ /* Probe and attach the iicbus. */
+ return (bus_generic_attach(dev));
+
+fail:
+ if (sc->irq_h != NULL)
+ bus_teardown_intr(dev, sc->irq_res, sc->irq_h);
+ if (sc->irq_res != NULL)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
+ if (sc->mem_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
+ LOCK_DESTROY(sc);
+
+ return (rv);
+}
+
+static int
+tegra_i2c_detach(device_t dev)
+{
+ struct tegra_i2c_softc *sc;
+ int rv;
+
+ sc = device_get_softc(dev);
+ tegra_i2c_hw_init(sc);
+ if (sc->irq_h != NULL)
+ bus_teardown_intr(dev, sc->irq_res, sc->irq_h);
+ if (sc->irq_res != NULL)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
+ if (sc->mem_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
+
+ LOCK_DESTROY(sc);
+ if (sc->iicbus)
+ rv = device_delete_child(dev, sc->iicbus);
+ return (bus_generic_detach(dev));
+}
+
+static phandle_t
+tegra_i2c_get_node(device_t bus, device_t dev)
+{
+
+ /* Share controller node with iibus device. */
+ return (ofw_bus_get_node(bus));
+}
+
+static device_method_t tegra_i2c_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, tegra_i2c_probe),
+ DEVMETHOD(device_attach, tegra_i2c_attach),
+ DEVMETHOD(device_detach, tegra_i2c_detach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+ DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
+ DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
+ DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
+
+ /* OFW methods */
+ DEVMETHOD(ofw_bus_get_node, tegra_i2c_get_node),
+
+ /* iicbus interface */
+ DEVMETHOD(iicbus_callback, iicbus_null_callback),
+ DEVMETHOD(iicbus_reset, tegra_i2c_iicbus_reset),
+ DEVMETHOD(iicbus_transfer, tegra_i2c_transfer),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(iichb, tegra_i2c_driver, tegra_i2c_methods,
+ sizeof(struct tegra_i2c_softc));
+static devclass_t tegra_i2c_devclass;
+EARLY_DRIVER_MODULE(iichb, simplebus, tegra_i2c_driver, tegra_i2c_devclass, 0,
+ 0, 73);
diff --git a/sys/arm/nvidia/tegra_lic.c b/sys/arm/nvidia/tegra_lic.c
new file mode 100644
index 0000000..6228c01
--- /dev/null
+++ b/sys/arm/nvidia/tegra_lic.c
@@ -0,0 +1,288 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Local interrupt controller driver for Tegra SoCs.
+ */
+#include <sys/param.h>
+#include <sys/module.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/rman.h>
+
+#include <machine/fdt.h>
+#include <machine/intr.h>
+#include <machine/resource.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "pic_if.h"
+
+#define LIC_VIRQ_CPU 0x00
+#define LIC_VIRQ_COP 0x04
+#define LIC_VFRQ_CPU 0x08
+#define LIC_VFRQ_COP 0x0c
+#define LIC_ISR 0x10
+#define LIC_FIR 0x14
+#define LIC_FIR_SET 0x18
+#define LIC_FIR_CLR 0x1c
+#define LIC_CPU_IER 0x20
+#define LIC_CPU_IER_SET 0x24
+#define LIC_CPU_IER_CLR 0x28
+#define LIC_CPU_IEP_CLASS 0x2C
+#define LIC_COP_IER 0x30
+#define LIC_COP_IER_SET 0x34
+#define LIC_COP_IER_CLR 0x38
+#define LIC_COP_IEP_CLASS 0x3c
+
+#define WR4(_sc, _b, _r, _v) bus_write_4((_sc)->mem_res[_b], (_r), (_v))
+#define RD4(_sc, _b, _r) bus_read_4((_sc)->mem_res[_b], (_r))
+
+static struct resource_spec lic_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { SYS_RES_MEMORY, 1, RF_ACTIVE },
+ { SYS_RES_MEMORY, 2, RF_ACTIVE },
+ { SYS_RES_MEMORY, 3, RF_ACTIVE },
+ { SYS_RES_MEMORY, 4, RF_ACTIVE },
+ { -1, 0 }
+};
+
+static struct ofw_compat_data compat_data[] = {
+ {"nvidia,tegra124-ictlr", 1},
+ {NULL, 0}
+};
+
+struct tegra_lic_sc {
+ device_t dev;
+ struct resource *mem_res[nitems(lic_spec)];
+ device_t parent;
+};
+
+static int
+tegra_lic_alloc_intr(device_t dev, struct intr_irqsrc *isrc,
+ struct resource *res, struct intr_map_data *data)
+{
+ struct tegra_lic_sc *sc = device_get_softc(dev);
+
+ return (PIC_ALLOC_INTR(sc->parent, isrc, res, data));
+}
+
+static void
+tegra_lic_disable_intr(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct tegra_lic_sc *sc = device_get_softc(dev);
+
+ PIC_DISABLE_INTR(sc->parent, isrc);
+}
+
+static void
+tegra_lic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct tegra_lic_sc *sc = device_get_softc(dev);
+
+ PIC_ENABLE_INTR(sc->parent, isrc);
+}
+
+static int
+tegra_lic_map_intr(device_t dev, struct intr_map_data *data,
+ struct intr_irqsrc **isrcp)
+{
+ struct tegra_lic_sc *sc = device_get_softc(dev);
+
+ return (PIC_MAP_INTR(sc->parent, data, isrcp));
+}
+
+static int
+tegra_lic_release_intr(device_t dev, struct intr_irqsrc *isrc,
+ struct resource *res, struct intr_map_data *data)
+{
+ struct tegra_lic_sc *sc = device_get_softc(dev);
+
+ return (PIC_RELEASE_INTR(sc->parent, isrc, res, data));
+}
+
+static int
+tegra_lic_setup_intr(device_t dev, struct intr_irqsrc *isrc,
+ struct resource *res, struct intr_map_data *data)
+{
+ struct tegra_lic_sc *sc = device_get_softc(dev);
+
+ return (PIC_SETUP_INTR(sc->parent, isrc, res, data));
+}
+
+static int
+tegra_lic_teardown_intr(device_t dev, struct intr_irqsrc *isrc,
+ struct resource *res, struct intr_map_data *data)
+{
+ struct tegra_lic_sc *sc = device_get_softc(dev);
+
+ return (PIC_TEARDOWN_INTR(sc->parent, isrc, res, data));
+}
+
+static void
+tegra_lic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct tegra_lic_sc *sc = device_get_softc(dev);
+
+ PIC_PRE_ITHREAD(sc->parent, isrc);
+}
+
+
+static void
+tegra_lic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct tegra_lic_sc *sc = device_get_softc(dev);
+
+ PIC_POST_ITHREAD(sc->parent, isrc);
+}
+
+static void
+tegra_lic_post_filter(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct tegra_lic_sc *sc = device_get_softc(dev);
+
+ PIC_POST_FILTER(sc->parent, isrc);
+}
+
+#ifdef SMP
+static int
+tegra_lic_bind_intr(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct tegra_lic_sc *sc = device_get_softc(dev);
+
+ return (PIC_BIND_INTR(sc->parent, isrc));
+}
+#endif
+
+static int
+tegra_lic_probe(device_t dev)
+{
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+tegra_lic_attach(device_t dev)
+{
+ struct tegra_lic_sc *sc;
+ phandle_t node;
+ phandle_t parent_xref;
+ int i, rv;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ node = ofw_bus_get_node(dev);
+
+ rv = OF_getencprop(node, "interrupt-parent", &parent_xref,
+ sizeof(parent_xref));
+ if (rv <= 0) {
+ device_printf(dev, "Cannot read parent node property\n");
+ goto fail;
+ }
+ sc->parent = OF_device_from_xref(parent_xref);
+ if (sc->parent == NULL) {
+ device_printf(dev, "Cannott find parent controller\n");
+ goto fail;
+ }
+
+ if (bus_alloc_resources(dev, lic_spec, sc->mem_res)) {
+ device_printf(dev, "Cannott allocate resources\n");
+ goto fail;
+ }
+
+ /* Disable all interrupts, route all to irq */
+ for (i = 0; i < nitems(lic_spec); i++) {
+ if (sc->mem_res[i] == NULL)
+ continue;
+ WR4(sc, i, LIC_CPU_IER_CLR, 0xFFFFFFFF);
+ WR4(sc, i, LIC_CPU_IEP_CLASS, 0);
+ }
+
+
+ if (intr_pic_register(dev, OF_xref_from_node(node)) != 0) {
+ device_printf(dev, "Cannot register PIC\n");
+ goto fail;
+ }
+ return (0);
+
+fail:
+ bus_release_resources(dev, lic_spec, sc->mem_res);
+ return (ENXIO);
+}
+
+static int
+tegra_lic_detach(device_t dev)
+{
+ struct tegra_lic_sc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+ for (i = 0; i < nitems(lic_spec); i++) {
+ if (sc->mem_res[i] == NULL)
+ continue;
+ bus_release_resource(dev, SYS_RES_MEMORY, i,
+ sc->mem_res[i]);
+ }
+ return (0);
+}
+
+static device_method_t tegra_lic_methods[] = {
+ DEVMETHOD(device_probe, tegra_lic_probe),
+ DEVMETHOD(device_attach, tegra_lic_attach),
+ DEVMETHOD(device_detach, tegra_lic_detach),
+
+ /* Interrupt controller interface */
+ DEVMETHOD(pic_alloc_intr, tegra_lic_alloc_intr),
+ DEVMETHOD(pic_disable_intr, tegra_lic_disable_intr),
+ DEVMETHOD(pic_enable_intr, tegra_lic_enable_intr),
+ DEVMETHOD(pic_map_intr, tegra_lic_map_intr),
+ DEVMETHOD(pic_release_intr, tegra_lic_release_intr),
+ DEVMETHOD(pic_setup_intr, tegra_lic_setup_intr),
+ DEVMETHOD(pic_teardown_intr, tegra_lic_teardown_intr),
+ DEVMETHOD(pic_pre_ithread, tegra_lic_pre_ithread),
+ DEVMETHOD(pic_post_ithread, tegra_lic_post_ithread),
+ DEVMETHOD(pic_post_filter, tegra_lic_post_filter),
+#ifdef SMP
+ DEVMETHOD(pic_bind_intr, tegra_lic_bind_intr),
+#endif
+ DEVMETHOD_END
+};
+devclass_t tegra_lic_devclass;
+DEFINE_CLASS_0(tegra_lic, tegra_lic_driver, tegra_lic_methods,
+ sizeof(struct tegra_lic_sc));
+EARLY_DRIVER_MODULE(tegra_lic, simplebus, tegra_lic_driver, tegra_lic_devclass,
+ NULL, NULL, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE + 1);
diff --git a/sys/arm/nvidia/tegra_pcie.c b/sys/arm/nvidia/tegra_pcie.c
new file mode 100644
index 0000000..e63ea47
--- /dev/null
+++ b/sys/arm/nvidia/tegra_pcie.c
@@ -0,0 +1,1691 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Nvidia Integrated PCI/PCI-Express controller driver.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/queue.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <sys/endian.h>
+
+#include <machine/intr.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <dev/extres/clk/clk.h>
+#include <dev/extres/hwreset/hwreset.h>
+#include <dev/extres/phy/phy.h>
+#include <dev/extres/regulator/regulator.h>
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/ofw_pci.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcib_private.h>
+
+#include <machine/devmap.h>
+#include <machine/resource.h>
+#include <machine/bus.h>
+
+#include "ofw_bus_if.h"
+#include "pcib_if.h"
+
+#include <arm/nvidia/tegra_pmc.h>
+
+/* --- Move to ofw_pci.c/.h ----------------------- */
+
+struct tegra_pci_range {
+ /* parsed phys.hi */
+ int nonrelocatable;
+ int prefetchable;
+ int aliased;
+ int space_code; /* In native format (not shifted)*/
+ int bus;
+ int device;
+ int function;
+ int reg;
+ pci_addr_t pci_addr; /* PCI Address */
+ bus_addr_t host_addr; /* Host bus address*/
+ bus_size_t size; /* Range size */
+};
+
+static int
+tegra_pci_get_ranges(phandle_t node, struct tegra_pci_range **ranges)
+{
+ int host_address_cells, pci_address_cells, size_cells;
+ cell_t *base_ranges;
+ ssize_t nbase_ranges;
+ int nranges;
+ int i, j, k;
+ uint32_t flags;
+ uint64_t tmp;
+
+ host_address_cells = 1;
+ pci_address_cells = 3;
+ size_cells = 2;
+ OF_getencprop(OF_parent(node), "#address-cells", &host_address_cells,
+ sizeof(host_address_cells));
+ OF_getencprop(node, "#address-cells", &pci_address_cells,
+ sizeof(pci_address_cells));
+ OF_getencprop(node, "#size-cells", &size_cells, sizeof(size_cells));
+
+ nbase_ranges = OF_getproplen(node, "ranges");
+ if (nbase_ranges <= 0)
+ return (-1);
+ nranges = nbase_ranges / sizeof(cell_t) /
+ (pci_address_cells + host_address_cells + size_cells);
+
+ *ranges = malloc(nranges * sizeof(struct tegra_pci_range),
+ M_DEVBUF, M_WAITOK);
+ base_ranges = malloc(nbase_ranges, M_DEVBUF, M_WAITOK);
+ OF_getencprop(node, "ranges", base_ranges, nbase_ranges);
+
+ for (i = 0, j = 0; i < nranges; i++) {
+ flags = base_ranges[j++];
+ (*ranges)[i].nonrelocatable =
+ flags & OFW_PCI_PHYS_HI_NONRELOCATABLE ? 1 : 0;
+ (*ranges)[i].prefetchable =
+ flags & OFW_PCI_PHYS_HI_PREFETCHABLE ? 1 : 0;
+ (*ranges)[i].aliased =
+ flags & OFW_PCI_PHYS_HI_ALIASED ? 1 : 0;
+ (*ranges)[i].space_code = flags & OFW_PCI_PHYS_HI_SPACEMASK;
+ (*ranges)[i].bus = OFW_PCI_PHYS_HI_BUS(flags);
+ (*ranges)[i].device = OFW_PCI_PHYS_HI_DEVICE(flags);
+ (*ranges)[i].function = OFW_PCI_PHYS_HI_FUNCTION(flags);
+ (*ranges)[i].reg = flags & OFW_PCI_PHYS_HI_REGISTERMASK;
+
+ tmp = 0;
+ for (k = 0; k < pci_address_cells - 1; k++) {
+ tmp <<= 32;
+ tmp |= base_ranges[j++];
+ }
+ (*ranges)[i].pci_addr = (pci_addr_t)tmp;
+
+ tmp = 0;
+ for (k = 0; k < host_address_cells; k++) {
+ tmp <<= 32;
+ tmp |= base_ranges[j++];
+ }
+ (*ranges)[i].host_addr = (bus_addr_t)tmp;
+ tmp = 0;
+
+ for (k = 0; k < size_cells; k++) {
+ tmp <<= 32;
+ tmp |= base_ranges[j++];
+ }
+ (*ranges)[i].size = (bus_size_t)tmp;
+ }
+
+ free(base_ranges, M_DEVBUF);
+ return (nranges);
+}
+
+/* -------------------------------------------------------------------------- */
+#define AFI_AXI_BAR0_SZ 0x000
+#define AFI_AXI_BAR1_SZ 0x004
+#define AFI_AXI_BAR2_SZ 0x008
+#define AFI_AXI_BAR3_SZ 0x00c
+#define AFI_AXI_BAR4_SZ 0x010
+#define AFI_AXI_BAR5_SZ 0x014
+#define AFI_AXI_BAR0_START 0x018
+#define AFI_AXI_BAR1_START 0x01c
+#define AFI_AXI_BAR2_START 0x020
+#define AFI_AXI_BAR3_START 0x024
+#define AFI_AXI_BAR4_START 0x028
+#define AFI_AXI_BAR5_START 0x02c
+#define AFI_FPCI_BAR0 0x030
+#define AFI_FPCI_BAR1 0x034
+#define AFI_FPCI_BAR2 0x038
+#define AFI_FPCI_BAR3 0x03c
+#define AFI_FPCI_BAR4 0x040
+#define AFI_FPCI_BAR5 0x044
+#define AFI_MSI_BAR_SZ 0x060
+#define AFI_MSI_FPCI_BAR_ST 0x064
+#define AFI_MSI_AXI_BAR_ST 0x068
+
+
+#define AFI_AXI_BAR6_SZ 0x134
+#define AFI_AXI_BAR7_SZ 0x138
+#define AFI_AXI_BAR8_SZ 0x13c
+#define AFI_AXI_BAR6_START 0x140
+#define AFI_AXI_BAR7_START 0x144
+#define AFI_AXI_BAR8_START 0x148
+#define AFI_FPCI_BAR6 0x14c
+#define AFI_FPCI_BAR7 0x150
+#define AFI_FPCI_BAR8 0x154
+
+#define AFI_CONFIGURATION 0x0ac
+#define AFI_CONFIGURATION_EN_FPCI (1 << 0)
+
+#define AFI_FPCI_ERROR_MASKS 0x0b0
+#define AFI_INTR_MASK 0x0b4
+#define AFI_INTR_MASK_MSI_MASK (1 << 8)
+#define AFI_INTR_MASK_INT_MASK (1 << 0)
+
+#define AFI_INTR_CODE 0x0b8
+#define AFI_INTR_CODE_MASK 0xf
+#define AFI_INTR_CODE_INT_CODE_INI_SLVERR 1
+#define AFI_INTR_CODE_INT_CODE_INI_DECERR 2
+#define AFI_INTR_CODE_INT_CODE_TGT_SLVERR 3
+#define AFI_INTR_CODE_INT_CODE_TGT_DECERR 4
+#define AFI_INTR_CODE_INT_CODE_TGT_WRERR 5
+#define AFI_INTR_CODE_INT_CODE_SM_MSG 6
+#define AFI_INTR_CODE_INT_CODE_DFPCI_DECERR 7
+#define AFI_INTR_CODE_INT_CODE_AXI_DECERR 8
+#define AFI_INTR_CODE_INT_CODE_FPCI_TIMEOUT 9
+#define AFI_INTR_CODE_INT_CODE_PE_PRSNT_SENSE 10
+#define AFI_INTR_CODE_INT_CODE_PE_CLKREQ_SENSE 11
+#define AFI_INTR_CODE_INT_CODE_CLKCLAMP_SENSE 12
+#define AFI_INTR_CODE_INT_CODE_RDY4PD_SENSE 13
+#define AFI_INTR_CODE_INT_CODE_P2P_ERROR 14
+
+
+#define AFI_INTR_SIGNATURE 0x0bc
+#define AFI_UPPER_FPCI_ADDRESS 0x0c0
+#define AFI_SM_INTR_ENABLE 0x0c4
+#define AFI_SM_INTR_RP_DEASSERT (1 << 14)
+#define AFI_SM_INTR_RP_ASSERT (1 << 13)
+#define AFI_SM_INTR_HOTPLUG (1 << 12)
+#define AFI_SM_INTR_PME (1 << 11)
+#define AFI_SM_INTR_FATAL_ERROR (1 << 10)
+#define AFI_SM_INTR_UNCORR_ERROR (1 << 9)
+#define AFI_SM_INTR_CORR_ERROR (1 << 8)
+#define AFI_SM_INTR_INTD_DEASSERT (1 << 7)
+#define AFI_SM_INTR_INTC_DEASSERT (1 << 6)
+#define AFI_SM_INTR_INTB_DEASSERT (1 << 5)
+#define AFI_SM_INTR_INTA_DEASSERT (1 << 4)
+#define AFI_SM_INTR_INTD_ASSERT (1 << 3)
+#define AFI_SM_INTR_INTC_ASSERT (1 << 2)
+#define AFI_SM_INTR_INTB_ASSERT (1 << 1)
+#define AFI_SM_INTR_INTA_ASSERT (1 << 0)
+
+#define AFI_AFI_INTR_ENABLE 0x0c8
+#define AFI_AFI_INTR_ENABLE_CODE(code) (1 << (code))
+
+#define AFI_PCIE_CONFIG 0x0f8
+#define AFI_PCIE_CONFIG_PCIE_DISABLE(x) (1 << ((x) + 1))
+#define AFI_PCIE_CONFIG_PCIE_DISABLE_ALL 0x6
+#define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_MASK (0xf << 20)
+#define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_XBAR2_1 (0x0 << 20)
+#define AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_XBAR4_1 (0x1 << 20)
+
+#define AFI_FUSE 0x104
+#define AFI_FUSE_PCIE_T0_GEN2_DIS (1 << 2)
+
+#define AFI_PEX0_CTRL 0x110
+#define AFI_PEX1_CTRL 0x118
+#define AFI_PEX2_CTRL 0x128
+#define AFI_PEX_CTRL_OVERRIDE_EN (1 << 4)
+#define AFI_PEX_CTRL_REFCLK_EN (1 << 3)
+#define AFI_PEX_CTRL_CLKREQ_EN (1 << 1)
+#define AFI_PEX_CTRL_RST_L (1 << 0)
+
+#define AFI_AXI_BAR6_SZ 0x134
+#define AFI_AXI_BAR7_SZ 0x138
+#define AFI_AXI_BAR8_SZ 0x13c
+#define AFI_AXI_BAR6_START 0x140
+#define AFI_AXI_BAR7_START 0x144
+#define AFI_AXI_BAR8_START 0x148
+#define AFI_FPCI_BAR6 0x14c
+#define AFI_FPCI_BAR7 0x150
+#define AFI_FPCI_BAR8 0x154
+#define AFI_PLLE_CONTROL 0x160
+#define AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL (1 << 9)
+#define AFI_PLLE_CONTROL_BYPASS_PCIE2PLLE_CONTROL (1 << 8)
+#define AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN (1 << 1)
+#define AFI_PLLE_CONTROL_PCIE2PLLE_CONTROL_EN (1 << 0)
+
+#define AFI_PEXBIAS_CTRL 0x168
+
+/* FPCI Address space */
+#define FPCI_MAP_IO 0xfdfc000000ULL
+#define FPCI_MAP_TYPE0_CONFIG 0xfdfc000000ULL
+#define FPCI_MAP_TYPE1_CONFIG 0xfdff000000ULL
+#define FPCI_MAP_EXT_TYPE0_CONFIG 0xfe00000000ULL
+#define FPCI_MAP_EXT_TYPE1_CONFIG 0xfe10000000ULL
+
+/* Configuration space */
+#define RP_VEND_XP 0x00000F00
+#define RP_VEND_XP_DL_UP (1 << 30)
+
+#define RP_PRIV_MISC 0x00000FE0
+#define RP_PRIV_MISC_PRSNT_MAP_EP_PRSNT (0xE << 0)
+#define RP_PRIV_MISC_PRSNT_MAP_EP_ABSNT (0xF << 0)
+
+#define RP_LINK_CONTROL_STATUS 0x00000090
+#define RP_LINK_CONTROL_STATUS_DL_LINK_ACTIVE 0x20000000
+#define RP_LINK_CONTROL_STATUS_LINKSTAT_MASK 0x3fff0000
+
+#define TEGRA_PCIE_LINKUP_TIMEOUT 200
+
+#define DEBUG
+#ifdef DEBUG
+#define debugf(fmt, args...) do { printf(fmt,##args); } while (0)
+#else
+#define debugf(fmt, args...)
+#endif
+
+/*
+ * Configuration space format:
+ * [27:24] extended register
+ * [23:16] bus
+ * [15:11] slot (device)
+ * [10: 8] function
+ * [ 7: 0] register
+ */
+#define PCI_CFG_EXT_REG(reg) ((((reg) >> 8) & 0x0f) << 24)
+#define PCI_CFG_BUS(bus) (((bus) & 0xff) << 16)
+#define PCI_CFG_DEV(dev) (((dev) & 0x1f) << 11)
+#define PCI_CFG_FUN(fun) (((fun) & 0x07) << 8)
+#define PCI_CFG_BASE_REG(reg) ((reg) & 0xff)
+
+#define PADS_WR4(_sc, _r, _v) bus_write_4((_sc)-pads_mem_res, (_r), (_v))
+#define PADS_RD4(_sc, _r) bus_read_4((_sc)->pads_mem_res, (_r))
+#define AFI_WR4(_sc, _r, _v) bus_write_4((_sc)->afi_mem_res, (_r), (_v))
+#define AFI_RD4(_sc, _r) bus_read_4((_sc)->afi_mem_res, (_r))
+
+static struct {
+ bus_size_t axi_start;
+ bus_size_t fpci_start;
+ bus_size_t size;
+} bars[] = {
+ {AFI_AXI_BAR0_START, AFI_FPCI_BAR0, AFI_AXI_BAR0_SZ}, /* BAR 0 */
+ {AFI_AXI_BAR1_START, AFI_FPCI_BAR1, AFI_AXI_BAR1_SZ}, /* BAR 1 */
+ {AFI_AXI_BAR2_START, AFI_FPCI_BAR2, AFI_AXI_BAR2_SZ}, /* BAR 2 */
+ {AFI_AXI_BAR3_START, AFI_FPCI_BAR3, AFI_AXI_BAR3_SZ}, /* BAR 3 */
+ {AFI_AXI_BAR4_START, AFI_FPCI_BAR4, AFI_AXI_BAR4_SZ}, /* BAR 4 */
+ {AFI_AXI_BAR5_START, AFI_FPCI_BAR5, AFI_AXI_BAR5_SZ}, /* BAR 5 */
+ {AFI_AXI_BAR6_START, AFI_FPCI_BAR6, AFI_AXI_BAR6_SZ}, /* BAR 6 */
+ {AFI_AXI_BAR7_START, AFI_FPCI_BAR7, AFI_AXI_BAR7_SZ}, /* BAR 7 */
+ {AFI_AXI_BAR8_START, AFI_FPCI_BAR8, AFI_AXI_BAR8_SZ}, /* BAR 8 */
+ {AFI_MSI_AXI_BAR_ST, AFI_MSI_FPCI_BAR_ST, AFI_MSI_BAR_SZ}, /* MSI 9 */
+};
+
+/* Compatible devices. */
+static struct ofw_compat_data compat_data[] = {
+ {"nvidia,tegra124-pcie", 1},
+ {NULL, 0},
+};
+
+struct tegra_pcib_port {
+ int enabled;
+ int port_idx; /* chip port index */
+ int num_lanes; /* number of lanes */
+ bus_size_t afi_pex_ctrl; /* offset of afi_pex_ctrl */
+
+ /* Config space properties. */
+ bus_addr_t rp_base_addr; /* PA of config window */
+ bus_size_t rp_size; /* size of config window */
+ bus_space_handle_t cfg_handle; /* handle of config window */
+};
+
+#define TEGRA_PCIB_MAX_PORTS 3
+struct tegra_pcib_softc {
+ device_t dev;
+ struct mtx mtx;
+ struct ofw_bus_iinfo pci_iinfo;
+ struct rman pref_mem_rman;
+ struct rman mem_rman;
+ struct rman io_rman;
+ struct resource *pads_mem_res;
+ struct resource *afi_mem_res;
+ struct resource *cfg_mem_res;
+ struct resource *irq_res;
+ struct resource *msi_irq_res;
+ void *intr_cookie;
+ void *msi_intr_cookie;
+
+ struct tegra_pci_range mem_range;
+ struct tegra_pci_range pref_mem_range;
+ struct tegra_pci_range io_range;
+
+ phy_t phy;
+ clk_t clk_pex;
+ clk_t clk_afi;
+ clk_t clk_pll_e;
+ clk_t clk_cml;
+ hwreset_t hwreset_pex;
+ hwreset_t hwreset_afi;
+ hwreset_t hwreset_pcie_x;
+ regulator_t supply_avddio_pex;
+ regulator_t supply_dvddio_pex;
+ regulator_t supply_avdd_pex_pll;
+ regulator_t supply_hvdd_pex;
+ regulator_t supply_hvdd_pex_pll_e;
+ regulator_t supply_vddio_pex_ctl;
+ regulator_t supply_avdd_pll_erefe;
+
+ int busnr; /* host bridge bus number */
+ uint32_t msi_bitmap;
+ bus_addr_t cfg_base_addr; /* base address of config */
+ bus_size_t cfg_cur_offs; /* currently mapped window */
+ bus_space_handle_t cfg_handle; /* handle of config window */
+ bus_space_tag_t bus_tag; /* tag of config window */
+ int lanes_cfg;
+ int num_ports;
+ struct tegra_pcib_port *ports[TEGRA_PCIB_MAX_PORTS];
+};
+
+/* ------------------------------------------------------------------------- */
+/*
+ * Resource manager
+ */
+static int
+tegra_pcib_rman_init(struct tegra_pcib_softc *sc)
+{
+ int err;
+ char buf[64];
+
+ /* Memory management. */
+ sc->pref_mem_rman.rm_type = RMAN_ARRAY;
+ snprintf(buf, sizeof(buf), "%s prefetchable memory space",
+ device_get_nameunit(sc->dev));
+ sc->pref_mem_rman.rm_descr = strdup(buf, M_DEVBUF);
+ err = rman_init(&sc->pref_mem_rman);
+ if (err)
+ return (err);
+
+ sc->mem_rman.rm_type = RMAN_ARRAY;
+ snprintf(buf, sizeof(buf), "%s non prefetchable memory space",
+ device_get_nameunit(sc->dev));
+ sc->mem_rman.rm_descr = strdup(buf, M_DEVBUF);
+ err = rman_init(&sc->mem_rman);
+ if (err)
+ return (err);
+
+ sc->io_rman.rm_type = RMAN_ARRAY;
+ snprintf(buf, sizeof(buf), "%s I/O space",
+ device_get_nameunit(sc->dev));
+ sc->io_rman.rm_descr = strdup(buf, M_DEVBUF);
+ err = rman_init(&sc->io_rman);
+ if (err) {
+ rman_fini(&sc->mem_rman);
+ return (err);
+ }
+
+ err = rman_manage_region(&sc->pref_mem_rman,
+ sc->pref_mem_range.host_addr,
+ sc->pref_mem_range.host_addr + sc->pref_mem_range.size - 1);
+ if (err)
+ goto error;
+ err = rman_manage_region(&sc->mem_rman,
+ sc->mem_range.host_addr,
+ sc->mem_range.host_addr + sc->mem_range.size - 1);
+ if (err)
+ goto error;
+ err = rman_manage_region(&sc->io_rman,
+ sc->io_range.pci_addr,
+ sc->io_range.pci_addr + sc->io_range.size - 1);
+ if (err)
+ goto error;
+ return (0);
+
+error:
+ rman_fini(&sc->pref_mem_rman);
+ rman_fini(&sc->mem_rman);
+ rman_fini(&sc->io_rman);
+ return (err);
+}
+
+static struct rman *
+tegra_pcib_rman(struct tegra_pcib_softc *sc, int type, u_int flags)
+{
+
+ switch (type) {
+ case SYS_RES_IOPORT:
+ return (&sc->io_rman);
+ case SYS_RES_MEMORY:
+ if (flags & RF_PREFETCHABLE)
+ return (&sc->pref_mem_rman);
+ else
+ return (&sc->mem_rman);
+ default:
+ break;
+ }
+
+ return (NULL);
+}
+
+static struct resource *
+tegra_pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
+ rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
+{
+ struct tegra_pcib_softc *sc;
+ struct rman *rm;
+ struct resource *res;
+
+ debugf("%s: enter %d start %#jx end %#jx count %#jx\n", __func__,
+ type, start, end, count);
+ sc = device_get_softc(dev);
+
+#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
+ if (type == PCI_RES_BUS) {
+ return (pci_domain_alloc_bus(0, child, rid, start, end, count,
+ flags));
+ }
+#endif
+
+ rm = tegra_pcib_rman(sc, type, flags);
+
+ if (rm == NULL) {
+ res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
+ type, rid, start, end, count, flags);
+
+ return (res);
+ }
+
+ if (bootverbose) {
+ device_printf(dev,
+ "rman_reserve_resource: start=%#jx, end=%#jx, count=%#jx\n",
+ start, end, count);
+ }
+
+ res = rman_reserve_resource(rm, start, end, count, flags, child);
+ if (res == NULL)
+ goto fail;
+ rman_set_rid(res, *rid);
+ if (flags & RF_ACTIVE) {
+ if (bus_activate_resource(child, type, *rid, res)) {
+ rman_release_resource(res);
+ goto fail;
+ }
+ }
+ return (res);
+
+fail:
+ if (bootverbose) {
+ device_printf(dev, "%s FAIL: type=%d, rid=%d, "
+ "start=%016jx, end=%016jx, count=%016jx, flags=%x\n",
+ __func__, type, *rid, start, end, count, flags);
+ }
+
+ return (NULL);
+}
+
+static int
+tegra_pcib_release_resource(device_t dev, device_t child, int type, int rid,
+ struct resource *res)
+{
+ struct tegra_pcib_softc *sc;
+ struct rman *rm;
+
+ sc = device_get_softc(dev);
+ debugf("%s: %d rid %x\n", __func__, type, rid);
+
+#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
+ if (type == PCI_RES_BUS)
+ return (pci_domain_release_bus(0, child, rid, res));
+#endif
+
+ rm = tegra_pcib_rman(sc, type, rman_get_flags(res));
+ if (rm != NULL) {
+ KASSERT(rman_is_region_manager(res, rm), ("rman mismatch"));
+ rman_release_resource(res);
+ }
+
+ return (bus_generic_release_resource(dev, child, type, rid, res));
+}
+
+static int
+tegra_pcib_adjust_resource(device_t dev, device_t child, int type,
+ struct resource *res, rman_res_t start, rman_res_t end)
+{
+ struct tegra_pcib_softc *sc;
+ struct rman *rm;
+
+ sc = device_get_softc(dev);
+ debugf("%s: %d start %jx end %jx \n", __func__, type, start, end);
+
+#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
+ if (type == PCI_RES_BUS)
+ return (pci_domain_adjust_bus(0, child, res, start, end));
+#endif
+
+ rm = tegra_pcib_rman(sc, type, rman_get_flags(res));
+ if (rm != NULL)
+ return (rman_adjust_resource(res, start, end));
+ return (bus_generic_adjust_resource(dev, child, type, res, start, end));
+}
+extern bus_space_tag_t fdtbus_bs_tag;
+static int
+tegra_pcib_pcie_activate_resource(device_t dev, device_t child, int type,
+ int rid, struct resource *r)
+{
+ struct tegra_pcib_softc *sc;
+ vm_offset_t start;
+ void *p;
+ int rv;
+
+ sc = device_get_softc(dev);
+ rv = rman_activate_resource(r);
+ if (rv != 0)
+ return (rv);
+ switch(type) {
+ case SYS_RES_IOPORT:
+ start = rman_get_start(r) + sc->io_range.host_addr;
+ break;
+ default:
+ start = rman_get_start(r);
+ rman_get_start(r);
+ break;
+ }
+
+ if (bootverbose)
+ printf("%s: start %zx, len %jd\n", __func__, start,
+ rman_get_size(r));
+
+ p = pmap_mapdev(start, (vm_size_t)rman_get_size(r));
+ rman_set_virtual(r, p);
+ rman_set_bustag(r, fdtbus_bs_tag);
+ rman_set_bushandle(r, (u_long)p);
+ return (0);
+}
+
+/* ------------------------------------------------------------------------- */
+/*
+ * IVARs
+ */
+static int
+tegra_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+ struct tegra_pcib_softc *sc = device_get_softc(dev);
+
+ switch (which) {
+ case PCIB_IVAR_BUS:
+ *result = sc->busnr;
+ return (0);
+ case PCIB_IVAR_DOMAIN:
+ *result = device_get_unit(dev);
+ return (0);
+ }
+
+ return (ENOENT);
+}
+
+static int
+tegra_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
+{
+ struct tegra_pcib_softc *sc = device_get_softc(dev);
+
+ switch (which) {
+ case PCIB_IVAR_BUS:
+ sc->busnr = value;
+ return (0);
+ }
+
+ return (ENOENT);
+}
+
+static int
+tegra_pcib_maxslots(device_t dev)
+{
+ return (16);
+}
+
+
+static int
+tegra_pcib_route_interrupt(device_t bus, device_t dev, int pin)
+{
+ struct tegra_pcib_softc *sc;
+
+ sc = device_get_softc(bus);
+ device_printf(bus, "route pin %d for device %d.%d to %ju\n",
+ pin, pci_get_slot(dev), pci_get_function(dev),
+ rman_get_start(sc->irq_res));
+
+ return (rman_get_start(sc->irq_res));
+}
+
+static int
+tegra_pcbib_map_cfg(struct tegra_pcib_softc *sc, u_int bus, u_int slot,
+ u_int func, u_int reg)
+{
+ bus_size_t offs;
+ int rv;
+
+ offs = sc->cfg_base_addr;
+ offs |= PCI_CFG_BUS(bus) | PCI_CFG_DEV(slot) | PCI_CFG_FUN(func) |
+ PCI_CFG_EXT_REG(reg);
+ if ((sc->cfg_handle != 0) && (sc->cfg_cur_offs == offs))
+ return (0);
+ if (sc->cfg_handle != 0)
+ bus_space_unmap(sc->bus_tag, sc->cfg_handle, 0x800);
+
+ rv = bus_space_map(sc->bus_tag, offs, 0x800, 0, &sc->cfg_handle);
+ if (rv != 0)
+ device_printf(sc->dev, "Cannot map config space\n");
+ else
+ sc->cfg_cur_offs = offs;
+ return (rv);
+}
+
+static uint32_t
+tegra_pcib_read_config(device_t dev, u_int bus, u_int slot, u_int func,
+ u_int reg, int bytes)
+{
+ struct tegra_pcib_softc *sc;
+ bus_space_handle_t hndl;
+ uint32_t off;
+ uint32_t val;
+ int rv, i;
+
+ sc = device_get_softc(dev);
+ if (bus == 0) {
+ if (func != 0)
+ return (0xFFFFFFFF);
+ for (i = 0; i < TEGRA_PCIB_MAX_PORTS; i++) {
+ if ((sc->ports[i] != NULL) &&
+ (sc->ports[i]->port_idx == slot)) {
+ hndl = sc->ports[i]->cfg_handle;
+ off = reg & 0xFFF;
+ break;
+ }
+ }
+ if (i >= TEGRA_PCIB_MAX_PORTS)
+ return (0xFFFFFFFF);
+ } else {
+ rv = tegra_pcbib_map_cfg(sc, bus, slot, func, reg);
+ if (rv != 0)
+ return (0xFFFFFFFF);
+ hndl = sc->cfg_handle;
+ off = PCI_CFG_BASE_REG(reg);
+ }
+
+ val = bus_space_read_4(sc->bus_tag, hndl, off & ~3);
+ switch (bytes) {
+ case 4:
+ break;
+ case 2:
+ if (off & 3)
+ val >>= 16;
+ val &= 0xffff;
+ break;
+ case 1:
+ val >>= ((off & 3) << 3);
+ val &= 0xff;
+ break;
+ }
+ return val;
+}
+
+static void
+tegra_pcib_write_config(device_t dev, u_int bus, u_int slot, u_int func,
+ u_int reg, uint32_t val, int bytes)
+{
+ struct tegra_pcib_softc *sc;
+ bus_space_handle_t hndl;
+ uint32_t off;
+ uint32_t val2;
+ int rv, i;
+
+ sc = device_get_softc(dev);
+ if (bus == 0) {
+ if (func != 0)
+ return;
+ for (i = 0; i < TEGRA_PCIB_MAX_PORTS; i++) {
+ if ((sc->ports[i] != NULL) &&
+ (sc->ports[i]->port_idx == slot)) {
+ hndl = sc->ports[i]->cfg_handle;
+ off = reg & 0xFFF;
+ break;
+ }
+ }
+ if (i >= TEGRA_PCIB_MAX_PORTS)
+ return;
+ } else {
+ rv = tegra_pcbib_map_cfg(sc, bus, slot, func, reg);
+ if (rv != 0)
+ return;
+ hndl = sc->cfg_handle;
+ off = PCI_CFG_BASE_REG(reg);
+ }
+
+ switch (bytes) {
+ case 4:
+ bus_space_write_4(sc->bus_tag, hndl, off, val);
+ break;
+ case 2:
+ val2 = bus_space_read_4(sc->bus_tag, hndl, off & ~3);
+ val2 &= ~(0xffff << ((off & 3) << 3));
+ val2 |= ((val & 0xffff) << ((off & 3) << 3));
+ bus_space_write_4(sc->bus_tag, hndl, off & ~3, val2);
+ break;
+ case 1:
+ val2 = bus_space_read_4(sc->bus_tag, hndl, off & ~3);
+ val2 &= ~(0xff << ((off & 3) << 3));
+ val2 |= ((val & 0xff) << ((off & 3) << 3));
+ bus_space_write_4(sc->bus_tag, hndl, off & ~3, val2);
+ break;
+ }
+}
+
+static int tegra_pci_intr(void *arg)
+{
+ struct tegra_pcib_softc *sc = arg;
+ uint32_t code, signature;
+
+ code = bus_read_4(sc->afi_mem_res, AFI_INTR_CODE) & AFI_INTR_CODE_MASK;
+ signature = bus_read_4(sc->afi_mem_res, AFI_INTR_SIGNATURE);
+ bus_write_4(sc->afi_mem_res, AFI_INTR_CODE, 0);
+ if (code == AFI_INTR_CODE_INT_CODE_SM_MSG)
+ return(FILTER_STRAY);
+
+ printf("tegra_pci_intr: code %x sig %x\n", code, signature);
+ return (FILTER_HANDLED);
+}
+
+#if defined(TEGRA_PCI_MSI)
+static int
+tegra_pcib_map_msi(device_t dev, device_t child, int irq, uint64_t *addr,
+ uint32_t *data)
+{
+ struct tegra_pcib_softc *sc;
+
+ sc = device_get_softc(dev);
+ irq = irq - MSI_IRQ;
+
+ /* validate parameters */
+ if (isclr(&sc->msi_bitmap, irq)) {
+ device_printf(dev, "invalid MSI 0x%x\n", irq);
+ return (EINVAL);
+ }
+
+ tegra_msi_data(irq, addr, data);
+
+ debugf("%s: irq: %d addr: %jx data: %x\n",
+ __func__, irq, *addr, *data);
+
+ return (0);
+}
+
+static int
+tegra_pcib_alloc_msi(device_t dev, device_t child, int count,
+ int maxcount __unused, int *irqs)
+{
+ struct tegra_pcib_softc *sc;
+ u_int start = 0, i;
+
+ if (powerof2(count) == 0 || count > MSI_IRQ_NUM)
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+ mtx_lock(&sc->mtx);
+
+ for (start = 0; (start + count) < MSI_IRQ_NUM; start++) {
+ for (i = start; i < start + count; i++) {
+ if (isset(&sc->msi_bitmap, i))
+ break;
+ }
+ if (i == start + count)
+ break;
+ }
+
+ if ((start + count) == MSI_IRQ_NUM) {
+ mtx_unlock(&sc->mtx);
+ return (ENXIO);
+ }
+
+ for (i = start; i < start + count; i++) {
+ setbit(&sc->msi_bitmap, i);
+ irqs[i] = MSI_IRQ + i;
+ }
+ debugf("%s: start: %x count: %x\n", __func__, start, count);
+
+ mtx_unlock(&sc->mtx);
+ return (0);
+}
+
+static int
+tegra_pcib_release_msi(device_t dev, device_t child, int count, int *irqs)
+{
+ struct tegra_pcib_softc *sc;
+ u_int i;
+
+ sc = device_get_softc(dev);
+ mtx_lock(&sc->mtx);
+
+ for (i = 0; i < count; i++)
+ clrbit(&sc->msi_bitmap, irqs[i] - MSI_IRQ);
+
+ mtx_unlock(&sc->mtx);
+ return (0);
+}
+#endif
+
+static bus_size_t
+tegra_pcib_pex_ctrl(struct tegra_pcib_softc *sc, int port)
+{
+ if (port >= TEGRA_PCIB_MAX_PORTS)
+ panic("invalid port number: %d\n", port);
+
+ if (port == 0)
+ return (AFI_PEX0_CTRL);
+ else if (port == 1)
+ return (AFI_PEX1_CTRL);
+ else if (port == 2)
+ return (AFI_PEX2_CTRL);
+ else
+ panic("invalid port number: %d\n", port);
+}
+
+static int
+tegra_pcib_enable_fdt_resources(struct tegra_pcib_softc *sc)
+{
+ int rv;
+
+ rv = hwreset_assert(sc->hwreset_pcie_x);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot assert 'pcie_x' reset\n");
+ return (rv);
+ }
+ rv = hwreset_assert(sc->hwreset_afi);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot assert 'afi' reset\n");
+ return (rv);
+ }
+ rv = hwreset_assert(sc->hwreset_pex);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot assert 'pex' reset\n");
+ return (rv);
+ }
+
+ tegra_powergate_power_off(TEGRA_POWERGATE_PCX);
+
+ /* Power supplies. */
+ rv = regulator_enable(sc->supply_avddio_pex);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot enable 'avddio_pex' regulator\n");
+ return (rv);
+ }
+ rv = regulator_enable(sc->supply_dvddio_pex);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot enable 'dvddio_pex' regulator\n");
+ return (rv);
+ }
+ rv = regulator_enable(sc->supply_avdd_pex_pll);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot enable 'avdd-pex-pll' regulator\n");
+ return (rv);
+ }
+
+ rv = regulator_enable(sc->supply_hvdd_pex);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot enable 'hvdd-pex-supply' regulator\n");
+ return (rv);
+ }
+ rv = regulator_enable(sc->supply_hvdd_pex_pll_e);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot enable 'hvdd-pex-pll-e-supply' regulator\n");
+ return (rv);
+ }
+ rv = regulator_enable(sc->supply_vddio_pex_ctl);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot enable 'vddio-pex-ctl' regulator\n");
+ return (rv);
+ }
+ rv = regulator_enable(sc->supply_avdd_pll_erefe);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot enable 'avdd-pll-erefe-supply' regulator\n");
+ return (rv);
+ }
+
+ rv = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCX,
+ sc->clk_pex, sc->hwreset_pex);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot enable 'PCX' powergate\n");
+ return (rv);
+ }
+
+ rv = hwreset_deassert(sc->hwreset_afi);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot unreset 'afi' reset\n");
+ return (rv);
+ }
+
+ rv = clk_enable(sc->clk_afi);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot enable 'afi' clock\n");
+ return (rv);
+ }
+
+ rv = clk_enable(sc->clk_cml);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot enable 'cml' clock\n");
+ return (rv);
+ }
+
+ rv = clk_enable(sc->clk_pll_e);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot enable 'pll_e' clock\n");
+ return (rv);
+ }
+ return (0);
+}
+
+static struct tegra_pcib_port *
+tegra_pcib_parse_port(struct tegra_pcib_softc *sc, phandle_t node)
+{
+ struct tegra_pcib_port *port;
+ uint32_t tmp[5];
+ char tmpstr[6];
+ int rv;
+
+ port = malloc(sizeof(struct tegra_pcib_port), M_DEVBUF, M_WAITOK);
+
+ rv = OF_getprop(node, "status", tmpstr, sizeof(tmpstr));
+ if (rv <= 0 || strcmp(tmpstr, "okay") == 0 ||
+ strcmp(tmpstr, "ok") == 0)
+ port->enabled = 1;
+ else
+ port->enabled = 0;
+
+ rv = OF_getencprop(node, "assigned-addresses", tmp, sizeof(tmp));
+ if (rv != sizeof(tmp)) {
+ device_printf(sc->dev, "Cannot parse assigned-address: %d\n",
+ rv);
+ goto fail;
+ }
+ port->rp_base_addr = tmp[2];
+ port->rp_size = tmp[4];
+ port->port_idx = OFW_PCI_PHYS_HI_DEVICE(tmp[0]) - 1;
+ if (port->port_idx >= TEGRA_PCIB_MAX_PORTS) {
+ device_printf(sc->dev, "Invalid port index: %d\n",
+ port->port_idx);
+ goto fail;
+ }
+ /* XXX - TODO:
+ * Implement proper function for parsing pci "reg" property:
+ * - it have PCI bus format
+ * - its relative to matching "assigned-addresses"
+ */
+ rv = OF_getencprop(node, "reg", tmp, sizeof(tmp));
+ if (rv != sizeof(tmp)) {
+ device_printf(sc->dev, "Cannot parse reg: %d\n", rv);
+ goto fail;
+ }
+ port->rp_base_addr += tmp[2];
+
+ rv = OF_getencprop(node, "nvidia,num-lanes", &port->num_lanes,
+ sizeof(port->num_lanes));
+ if (rv != sizeof(port->num_lanes)) {
+ device_printf(sc->dev, "Cannot parse nvidia,num-lanes: %d\n",
+ rv);
+ goto fail;
+ }
+ if (port->num_lanes > 4) {
+ device_printf(sc->dev, "Invalid nvidia,num-lanes: %d\n",
+ port->num_lanes);
+ goto fail;
+ }
+
+ port->afi_pex_ctrl = tegra_pcib_pex_ctrl(sc, port->port_idx);
+ sc->lanes_cfg |= port->num_lanes << (4 * port->port_idx);
+
+ return (port);
+fail:
+ free(port, M_DEVBUF);
+ return (NULL);
+}
+
+
+static int
+tegra_pcib_parse_fdt_resources(struct tegra_pcib_softc *sc, phandle_t node)
+{
+ phandle_t child;
+ struct tegra_pcib_port *port;
+ int rv;
+
+ /* Power supplies. */
+ rv = regulator_get_by_ofw_property(sc->dev, "avddio-pex-supply",
+ &sc->supply_avddio_pex);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot get 'avddio-pex' regulator\n");
+ return (ENXIO);
+ }
+ rv = regulator_get_by_ofw_property(sc->dev, "dvddio-pex-supply",
+ &sc->supply_dvddio_pex);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot get 'dvddio-pex' regulator\n");
+ return (ENXIO);
+ }
+ rv = regulator_get_by_ofw_property(sc->dev, "avdd-pex-pll-supply",
+ &sc->supply_avdd_pex_pll);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot get 'avdd-pex-pll' regulator\n");
+ return (ENXIO);
+ }
+ rv = regulator_get_by_ofw_property(sc->dev, "hvdd-pex-supply",
+ &sc->supply_hvdd_pex);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot get 'hvdd-pex' regulator\n");
+ return (ENXIO);
+ }
+ rv = regulator_get_by_ofw_property(sc->dev, "hvdd-pex-pll-e-supply",
+ &sc->supply_hvdd_pex_pll_e);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot get 'hvdd-pex-pll-e' regulator\n");
+ return (ENXIO);
+ }
+ rv = regulator_get_by_ofw_property(sc->dev, "vddio-pex-ctl-supply",
+ &sc->supply_vddio_pex_ctl);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot get 'vddio-pex-ctl' regulator\n");
+ return (ENXIO);
+ }
+ rv = regulator_get_by_ofw_property(sc->dev, "avdd-pll-erefe-supply",
+ &sc->supply_avdd_pll_erefe);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot get 'avdd-pll-erefe' regulator\n");
+ return (ENXIO);
+ }
+
+ /* Resets. */
+ rv = hwreset_get_by_ofw_name(sc->dev, "pex", &sc->hwreset_pex);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'pex' reset\n");
+ return (ENXIO);
+ }
+ rv = hwreset_get_by_ofw_name(sc->dev, "afi", &sc->hwreset_afi);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'afi' reset\n");
+ return (ENXIO);
+ }
+ rv = hwreset_get_by_ofw_name(sc->dev, "pcie_x", &sc->hwreset_pcie_x);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'pcie_x' reset\n");
+ return (ENXIO);
+ }
+
+ /* Clocks. */
+ rv = clk_get_by_ofw_name(sc->dev, "pex", &sc->clk_pex);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'pex' clock\n");
+ return (ENXIO);
+ }
+ rv = clk_get_by_ofw_name(sc->dev, "afi", &sc->clk_afi);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'afi' clock\n");
+ return (ENXIO);
+ }
+ rv = clk_get_by_ofw_name(sc->dev, "pll_e", &sc->clk_pll_e);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'pll_e' clock\n");
+ return (ENXIO);
+ }
+ rv = clk_get_by_ofw_name(sc->dev, "cml", &sc->clk_cml);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'cml' clock\n");
+ return (ENXIO);
+ }
+
+ /* Phy. */
+ rv = phy_get_by_ofw_name(sc->dev, "pcie", &sc->phy);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'pcie' phy\n");
+ return (ENXIO);
+ }
+
+ /* Ports */
+ sc->num_ports = 0;
+ for (child = OF_child(node); child != 0; child = OF_peer(child)) {
+ port = tegra_pcib_parse_port(sc, child);
+ if (port == NULL) {
+ device_printf(sc->dev, "Cannot parse PCIe port node\n");
+ return (ENXIO);
+ }
+ sc->ports[sc->num_ports++] = port;
+ }
+
+ return (0);
+}
+
+static int
+tegra_pcib_decode_ranges(struct tegra_pcib_softc *sc,
+ struct tegra_pci_range *ranges, int nranges)
+{
+ int i;
+
+ for (i = 2; i < nranges; i++) {
+ if (ranges[i].space_code == OFW_PCI_PHYS_HI_SPACE_IO) {
+ if (sc->io_range.size != 0) {
+ device_printf(sc->dev,
+ "Duplicated IO range found in DT\n");
+ return (ENXIO);
+ }
+ sc->io_range = ranges[i];
+ }
+ if ((ranges[i].space_code == OFW_PCI_PHYS_HI_SPACE_MEM32) &&
+ !ranges[i].prefetchable) {
+ if (sc->mem_range.size != 0) {
+ device_printf(sc->dev,
+ "Duplicated memory range found in DT\n");
+ return (ENXIO);
+ }
+ sc->mem_range = ranges[i];
+ }
+ if ((ranges[i].space_code == OFW_PCI_PHYS_HI_SPACE_MEM32) &&
+ ranges[i].prefetchable) {
+ if (sc->pref_mem_range.size != 0) {
+ device_printf(sc->dev,
+ "Duplicated memory range found in DT\n");
+ return (ENXIO);
+ }
+ sc->pref_mem_range = ranges[i];
+ }
+ }
+ if ((sc->io_range.size == 0) || (sc->mem_range.size == 0)
+ || (sc->pref_mem_range.size == 0)) {
+ device_printf(sc->dev,
+ " Not all required ranges are found in DT\n");
+ return (ENXIO);
+ }
+ return (0);
+}
+
+/*
+ * Hardware config.
+ */
+static int
+tegra_pcib_wait_for_link(struct tegra_pcib_softc *sc,
+ struct tegra_pcib_port *port)
+{
+ uint32_t reg;
+ int i;
+
+
+ /* Setup link detection. */
+ reg = tegra_pcib_read_config(sc->dev, 0, port->port_idx, 0,
+ RP_PRIV_MISC, 4);
+ reg &= ~RP_PRIV_MISC_PRSNT_MAP_EP_ABSNT;
+ reg |= RP_PRIV_MISC_PRSNT_MAP_EP_PRSNT;
+ tegra_pcib_write_config(sc->dev, 0, port->port_idx, 0,
+ RP_PRIV_MISC, reg, 4);
+
+ for (i = TEGRA_PCIE_LINKUP_TIMEOUT; i > 0; i--) {
+ reg = tegra_pcib_read_config(sc->dev, 0, port->port_idx, 0,
+ RP_VEND_XP, 4);
+ if (reg & RP_VEND_XP_DL_UP)
+ break;
+
+ }
+ if (i <= 0)
+ return (ETIMEDOUT);
+
+ for (i = TEGRA_PCIE_LINKUP_TIMEOUT; i > 0; i--) {
+ reg = tegra_pcib_read_config(sc->dev, 0, port->port_idx, 0,
+ RP_LINK_CONTROL_STATUS, 4);
+ if (reg & RP_LINK_CONTROL_STATUS_DL_LINK_ACTIVE)
+ break;
+
+ }
+ if (i <= 0)
+ return (ETIMEDOUT);
+ return (0);
+}
+
+static void
+tegra_pcib_port_enable(struct tegra_pcib_softc *sc, int port_num)
+{
+ struct tegra_pcib_port *port;
+ uint32_t reg;
+ int rv;
+
+ port = sc->ports[port_num];
+
+ /* Put port to reset. */
+ reg = AFI_RD4(sc, port->afi_pex_ctrl);
+ reg &= ~AFI_PEX_CTRL_RST_L;
+ AFI_WR4(sc, port->afi_pex_ctrl, reg);
+ AFI_RD4(sc, port->afi_pex_ctrl);
+ DELAY(10);
+
+ /* Enable clocks. */
+ reg |= AFI_PEX_CTRL_REFCLK_EN;
+ reg |= AFI_PEX_CTRL_CLKREQ_EN;
+ reg |= AFI_PEX_CTRL_OVERRIDE_EN;
+ AFI_WR4(sc, port->afi_pex_ctrl, reg);
+ AFI_RD4(sc, port->afi_pex_ctrl);
+ DELAY(100);
+
+ /* Release reset. */
+ reg |= AFI_PEX_CTRL_RST_L;
+ AFI_WR4(sc, port->afi_pex_ctrl, reg);
+
+ rv = tegra_pcib_wait_for_link(sc, port);
+ if (bootverbose)
+ device_printf(sc->dev, " port %d (%d lane%s): Link is %s\n",
+ port->port_idx, port->num_lanes,
+ port->num_lanes > 1 ? "s": "",
+ rv == 0 ? "up": "down");
+}
+
+
+static void
+tegra_pcib_port_disable(struct tegra_pcib_softc *sc, uint32_t port_num)
+{
+ struct tegra_pcib_port *port;
+ uint32_t reg;
+
+ port = sc->ports[port_num];
+
+ /* Put port to reset. */
+ reg = AFI_RD4(sc, port->afi_pex_ctrl);
+ reg &= ~AFI_PEX_CTRL_RST_L;
+ AFI_WR4(sc, port->afi_pex_ctrl, reg);
+ AFI_RD4(sc, port->afi_pex_ctrl);
+ DELAY(10);
+
+ /* Disable clocks. */
+ reg &= ~AFI_PEX_CTRL_CLKREQ_EN;
+ reg &= ~AFI_PEX_CTRL_REFCLK_EN;
+ AFI_WR4(sc, port->afi_pex_ctrl, reg);
+
+ if (bootverbose)
+ device_printf(sc->dev, " port %d (%d lane%s): Disabled\n",
+ port->port_idx, port->num_lanes,
+ port->num_lanes > 1 ? "s": "");
+}
+
+static void
+tegra_pcib_set_bar(struct tegra_pcib_softc *sc, int bar, uint32_t axi,
+ uint64_t fpci, uint32_t size, int is_memory)
+{
+ uint32_t fpci_reg;
+ uint32_t axi_reg;
+ uint32_t size_reg;
+
+ axi_reg = axi & ~0xFFF;
+ size_reg = size >> 12;
+ fpci_reg = (uint32_t)(fpci >> 8) & ~0xF;
+ fpci_reg |= is_memory ? 0x1 : 0x0;
+ AFI_WR4(sc, bars[bar].axi_start, axi_reg);
+ AFI_WR4(sc, bars[bar].size, size_reg);
+ AFI_WR4(sc, bars[bar].fpci_start, fpci_reg);
+}
+
+static int
+tegra_pcib_enable(struct tegra_pcib_softc *sc, uint32_t port)
+{
+ int rv;
+ int i;
+ uint32_t reg;
+
+ rv = tegra_pcib_enable_fdt_resources(sc);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot enable FDT resources\n");
+ return (rv);
+ }
+ /* Enable PLLE control. */
+ reg = AFI_RD4(sc, AFI_PLLE_CONTROL);
+ reg &= ~AFI_PLLE_CONTROL_BYPASS_PADS2PLLE_CONTROL;
+ reg |= AFI_PLLE_CONTROL_PADS2PLLE_CONTROL_EN;
+ AFI_WR4(sc, AFI_PLLE_CONTROL, reg);
+
+ /* Set bias pad. */
+ AFI_WR4(sc, AFI_PEXBIAS_CTRL, 0);
+
+ /* Configure mode and ports. */
+ reg = AFI_RD4(sc, AFI_PCIE_CONFIG);
+ reg &= ~AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_MASK;
+ if (sc->lanes_cfg == 0x14) {
+ if (bootverbose)
+ device_printf(sc->dev,
+ "Using x1,x4 configuration\n");
+ reg |= AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_XBAR4_1;
+ } else if (sc->lanes_cfg == 0x12) {
+ if (bootverbose)
+ device_printf(sc->dev,
+ "Using x1,x2 configuration\n");
+ reg |= AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_XBAR2_1;
+ } else {
+ device_printf(sc->dev,
+ "Unsupported lanes configuration: 0x%X\n", sc->lanes_cfg);
+ }
+ reg |= AFI_PCIE_CONFIG_PCIE_DISABLE_ALL;
+ for (i = 0; i < TEGRA_PCIB_MAX_PORTS; i++) {
+ if ((sc->ports[i] != NULL))
+ reg &=
+ ~AFI_PCIE_CONFIG_PCIE_DISABLE(sc->ports[i]->port_idx);
+ }
+ AFI_WR4(sc, AFI_PCIE_CONFIG, reg);
+
+ /* Enable Gen2 support. */
+ reg = AFI_RD4(sc, AFI_FUSE);
+ reg &= ~AFI_FUSE_PCIE_T0_GEN2_DIS;
+ AFI_WR4(sc, AFI_FUSE, reg);
+
+ /* Enable PCIe phy. */
+ rv = phy_enable(sc->dev, sc->phy);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot enable phy\n");
+ return (rv);
+ }
+
+ rv = hwreset_deassert(sc->hwreset_pcie_x);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot unreset 'pci_x' reset\n");
+ return (rv);
+ }
+
+ /* Enable config space. */
+ reg = AFI_RD4(sc, AFI_CONFIGURATION);
+ reg |= AFI_CONFIGURATION_EN_FPCI;
+ AFI_WR4(sc, AFI_CONFIGURATION, reg);
+
+ /* Enable AFI errors. */
+ reg = 0;
+ reg |= AFI_AFI_INTR_ENABLE_CODE(AFI_INTR_CODE_INT_CODE_INI_SLVERR);
+ reg |= AFI_AFI_INTR_ENABLE_CODE(AFI_INTR_CODE_INT_CODE_INI_DECERR);
+ reg |= AFI_AFI_INTR_ENABLE_CODE(AFI_INTR_CODE_INT_CODE_TGT_SLVERR);
+ reg |= AFI_AFI_INTR_ENABLE_CODE(AFI_INTR_CODE_INT_CODE_TGT_DECERR);
+ reg |= AFI_AFI_INTR_ENABLE_CODE(AFI_INTR_CODE_INT_CODE_TGT_WRERR);
+ reg |= AFI_AFI_INTR_ENABLE_CODE(AFI_INTR_CODE_INT_CODE_SM_MSG);
+ reg |= AFI_AFI_INTR_ENABLE_CODE(AFI_INTR_CODE_INT_CODE_DFPCI_DECERR);
+ reg |= AFI_AFI_INTR_ENABLE_CODE(AFI_INTR_CODE_INT_CODE_AXI_DECERR);
+ reg |= AFI_AFI_INTR_ENABLE_CODE(AFI_INTR_CODE_INT_CODE_FPCI_TIMEOUT);
+ reg |= AFI_AFI_INTR_ENABLE_CODE(AFI_INTR_CODE_INT_CODE_PE_PRSNT_SENSE);
+ reg |= AFI_AFI_INTR_ENABLE_CODE(AFI_INTR_CODE_INT_CODE_PE_CLKREQ_SENSE);
+ reg |= AFI_AFI_INTR_ENABLE_CODE(AFI_INTR_CODE_INT_CODE_CLKCLAMP_SENSE);
+ reg |= AFI_AFI_INTR_ENABLE_CODE(AFI_INTR_CODE_INT_CODE_RDY4PD_SENSE);
+ reg |= AFI_AFI_INTR_ENABLE_CODE(AFI_INTR_CODE_INT_CODE_P2P_ERROR);
+ AFI_WR4(sc, AFI_AFI_INTR_ENABLE, reg);
+ AFI_WR4(sc, AFI_SM_INTR_ENABLE, 0xffffffff);
+
+ /* Enable INT, disable MSI. */
+ AFI_WR4(sc, AFI_INTR_MASK, AFI_INTR_MASK_INT_MASK);
+
+ /* Mask all FPCI errors. */
+ AFI_WR4(sc, AFI_FPCI_ERROR_MASKS, 0);
+
+ /* Setup AFI translation windows. */
+ /* BAR 0 - type 1 extended configuration. */
+ tegra_pcib_set_bar(sc, 0, rman_get_start(sc->cfg_mem_res),
+ FPCI_MAP_EXT_TYPE1_CONFIG, rman_get_size(sc->cfg_mem_res), 0);
+
+ /* BAR 1 - downstream I/O. */
+ tegra_pcib_set_bar(sc, 1, sc->io_range.host_addr, FPCI_MAP_IO,
+ sc->io_range.size, 0);
+
+ /* BAR 2 - downstream prefetchable memory 1:1. */
+ tegra_pcib_set_bar(sc, 2, sc->pref_mem_range.host_addr,
+ sc->pref_mem_range.host_addr, sc->pref_mem_range.size, 1);
+
+ /* BAR 3 - downstream not prefetchable memory 1:1 .*/
+ tegra_pcib_set_bar(sc, 3, sc->mem_range.host_addr,
+ sc->mem_range.host_addr, sc->mem_range.size, 1);
+
+ /* BAR 3-8 clear. */
+ tegra_pcib_set_bar(sc, 4, 0, 0, 0, 0);
+ tegra_pcib_set_bar(sc, 5, 0, 0, 0, 0);
+ tegra_pcib_set_bar(sc, 6, 0, 0, 0, 0);
+ tegra_pcib_set_bar(sc, 7, 0, 0, 0, 0);
+ tegra_pcib_set_bar(sc, 8, 0, 0, 0, 0);
+
+ /* MSI BAR - clear. */
+ tegra_pcib_set_bar(sc, 9, 0, 0, 0, 0);
+ return(0);
+}
+
+static int
+tegra_pcib_probe(device_t dev)
+{
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) {
+ device_set_desc(dev, "Nvidia Integrated PCI/PCI-E Controller");
+ return (BUS_PROBE_DEFAULT);
+ }
+ return (ENXIO);
+}
+
+static int
+tegra_pcib_attach(device_t dev)
+{
+ struct tegra_pcib_softc *sc;
+ phandle_t node;
+ uint32_t unit;
+ int rv;
+ int rid;
+ int nranges;
+ struct tegra_pci_range *ranges;
+ struct tegra_pcib_port *port;
+ int i;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ unit = fdt_get_unit(dev);
+ mtx_init(&sc->mtx, "msi_mtx", NULL, MTX_DEF);
+
+
+ node = ofw_bus_get_node(dev);
+
+ rv = tegra_pcib_parse_fdt_resources(sc, node);
+ if (rv != 0) {
+ device_printf(dev, "Cannot get FDT resources\n");
+ return (rv);
+ }
+
+ nranges = tegra_pci_get_ranges(node, &ranges);
+ if (nranges != 5) {
+ device_printf(sc->dev, "Unexpected number of ranges: %d\n",
+ nranges);
+ rv = ENXIO;
+ goto out;
+ }
+
+ /* Allocate bus_space resources. */
+ rid = 0;
+ sc->pads_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->pads_mem_res == NULL) {
+ device_printf(dev, "Cannot allocate PADS register\n");
+ rv = ENXIO;
+ goto out;
+ }
+ /*
+ * XXX - FIXME
+ * tag for config space is not filled when RF_ALLOCATED flag is used.
+ */
+ sc->bus_tag = rman_get_bustag(sc->pads_mem_res);
+
+ rid = 1;
+ sc->afi_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->afi_mem_res == NULL) {
+ device_printf(dev, "Cannot allocate AFI register\n");
+ rv = ENXIO;
+ goto out;
+ }
+
+ rid = 2;
+ sc->cfg_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ALLOCATED);
+ if (sc->cfg_mem_res == NULL) {
+ device_printf(dev, "Cannot allocate config space memory\n");
+ rv = ENXIO;
+ goto out;
+ }
+ sc->cfg_base_addr = rman_get_start(sc->cfg_mem_res);
+
+
+ /* Map RP slots */
+ for (i = 0; i < TEGRA_PCIB_MAX_PORTS; i++) {
+ if (sc->ports[i] == NULL)
+ continue;
+ port = sc->ports[i];
+ rv = bus_space_map(sc->bus_tag, port->rp_base_addr,
+ port->rp_size, 0, &port->cfg_handle);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot allocate memory for "
+ "port: %d\n", i);
+ rv = ENXIO;
+ goto out;
+ }
+ }
+
+ /*
+ * Get PCI interrupt info.
+ */
+ ofw_bus_setup_iinfo(node, &sc->pci_iinfo, sizeof(pcell_t));
+ rid = 0;
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (sc->irq_res == NULL) {
+ device_printf(dev, "Cannot allocate IRQ resources\n");
+ rv = ENXIO;
+ goto out;
+ }
+
+ rid = 1;
+ sc->msi_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (sc->irq_res == NULL) {
+ device_printf(dev, "Cannot allocate MSI IRQ resources\n");
+ rv = ENXIO;
+ goto out;
+ }
+
+ if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
+ tegra_pci_intr, NULL, sc, &sc->intr_cookie)) {
+ device_printf(dev, "cannot setup interrupt handler\n");
+ rv = ENXIO;
+ goto out;
+ }
+
+ /* Memory management. */
+ rv = tegra_pcib_decode_ranges(sc, ranges, nranges);
+ if (rv != 0)
+ goto out;
+
+ rv = tegra_pcib_rman_init(sc);
+ if (rv != 0)
+ goto out;
+ free(ranges, M_DEVBUF);
+ ranges = NULL;
+
+ /*
+ * Enable PCIE device.
+ */
+ rv = tegra_pcib_enable(sc, unit);
+ if (rv != 0)
+ goto out;
+ for (i = 0; i < TEGRA_PCIB_MAX_PORTS; i++) {
+ if (sc->ports[i] == NULL)
+ continue;
+ if (sc->ports[i]->enabled)
+ tegra_pcib_port_enable(sc, i);
+ else
+ tegra_pcib_port_disable(sc, i);
+ }
+
+ device_add_child(dev, "pci", -1);
+
+ return (bus_generic_attach(dev));
+
+out:
+ if (ranges != NULL)
+ free(ranges, M_DEVBUF);
+
+ return (rv);
+}
+
+
+static device_method_t tegra_pcib_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, tegra_pcib_probe),
+ DEVMETHOD(device_attach, tegra_pcib_attach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_read_ivar, tegra_pcib_read_ivar),
+ DEVMETHOD(bus_write_ivar, tegra_pcib_write_ivar),
+ DEVMETHOD(bus_alloc_resource, tegra_pcib_alloc_resource),
+ DEVMETHOD(bus_adjust_resource, tegra_pcib_adjust_resource),
+ DEVMETHOD(bus_release_resource, tegra_pcib_release_resource),
+ DEVMETHOD(bus_activate_resource, tegra_pcib_pcie_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+
+ /* pcib interface */
+ DEVMETHOD(pcib_maxslots, tegra_pcib_maxslots),
+ DEVMETHOD(pcib_read_config, tegra_pcib_read_config),
+ DEVMETHOD(pcib_write_config, tegra_pcib_write_config),
+ DEVMETHOD(pcib_route_interrupt, tegra_pcib_route_interrupt),
+
+#if defined(TEGRA_PCI_MSI)
+ DEVMETHOD(pcib_alloc_msi, tegra_pcib_alloc_msi),
+ DEVMETHOD(pcib_release_msi, tegra_pcib_release_msi),
+ DEVMETHOD(pcib_map_msi, tegra_pcib_map_msi),
+#endif
+
+ /* OFW bus interface */
+ DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
+ DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
+ DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
+ DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
+ DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
+
+ DEVMETHOD_END
+};
+
+static driver_t tegra_pcib_driver = {
+ "pcib",
+ tegra_pcib_methods,
+ sizeof(struct tegra_pcib_softc),
+};
+
+devclass_t pcib_devclass;
+
+DRIVER_MODULE(pcib, simplebus, tegra_pcib_driver, pcib_devclass, 0, 0); \ No newline at end of file
diff --git a/sys/arm/nvidia/tegra_pinmux.c b/sys/arm/nvidia/tegra_pinmux.c
new file mode 100644
index 0000000..6123746
--- /dev/null
+++ b/sys/arm/nvidia/tegra_pinmux.c
@@ -0,0 +1,804 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Pin multiplexer driver for Tegra SoCs.
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/fdt/fdt_pinctrl.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+/* Pin multipexor register. */
+#define TEGRA_MUX_FUNCTION_MASK 0x03
+#define TEGRA_MUX_FUNCTION_SHIFT 0
+#define TEGRA_MUX_PUPD_MASK 0x03
+#define TEGRA_MUX_PUPD_SHIFT 2
+#define TEGRA_MUX_TRISTATE_SHIFT 4
+#define TEGRA_MUX_ENABLE_INPUT_SHIFT 5
+#define TEGRA_MUX_OPEN_DRAIN_SHIFT 6
+#define TEGRA_MUX_LOCK_SHIFT 7
+#define TEGRA_MUX_IORESET_SHIFT 8
+#define TEGRA_MUX_RCV_SEL_SHIFT 9
+
+
+/* Pin goup register. */
+#define TEGRA_GRP_HSM_SHIFT 2
+#define TEGRA_GRP_SCHMT_SHIFT 3
+#define TEGRA_GRP_DRV_TYPE_SHIFT 6
+#define TEGRA_GRP_DRV_TYPE_MASK 0x03
+#define TEGRA_GRP_DRV_DRVDN_SLWR_SHIFT 28
+#define TEGRA_GRP_DRV_DRVDN_SLWR_MASK 0x03
+#define TEGRA_GRP_DRV_DRVUP_SLWF_SHIFT 30
+#define TEGRA_GRP_DRV_DRVUP_SLWF_MASK 0x03
+
+struct pinmux_softc {
+ device_t dev;
+ struct resource *pad_mem_res;
+ struct resource *mux_mem_res;
+ struct resource *mipi_mem_res;
+};
+
+static struct ofw_compat_data compat_data[] = {
+ {"nvidia,tegra124-pinmux", 1},
+ {NULL, 0},
+};
+
+enum prop_id {
+ PROP_ID_PULL,
+ PROP_ID_TRISTATE,
+ PROP_ID_ENABLE_INPUT,
+ PROP_ID_OPEN_DRAIN,
+ PROP_ID_LOCK,
+ PROP_ID_IORESET,
+ PROP_ID_RCV_SEL,
+ PROP_ID_HIGH_SPEED_MODE,
+ PROP_ID_SCHMITT,
+ PROP_ID_LOW_POWER_MODE,
+ PROP_ID_DRIVE_DOWN_STRENGTH,
+ PROP_ID_DRIVE_UP_STRENGTH,
+ PROP_ID_SLEW_RATE_FALLING,
+ PROP_ID_SLEW_RATE_RISING,
+ PROP_ID_DRIVE_TYPE,
+
+ PROP_ID_MAX_ID
+};
+
+/* Numeric based parameters. */
+static const struct prop_name {
+ const char *name;
+ enum prop_id id;
+} prop_names[] = {
+ {"nvidia,pull", PROP_ID_PULL},
+ {"nvidia,tristate", PROP_ID_TRISTATE},
+ {"nvidia,enable-input", PROP_ID_ENABLE_INPUT},
+ {"nvidia,open-drain", PROP_ID_OPEN_DRAIN},
+ {"nvidia,lock", PROP_ID_LOCK},
+ {"nvidia,io-reset", PROP_ID_IORESET},
+ {"nvidia,rcv-sel", PROP_ID_RCV_SEL},
+ {"nvidia,high-speed-mode", PROP_ID_HIGH_SPEED_MODE},
+ {"nvidia,schmitt", PROP_ID_SCHMITT},
+ {"nvidia,low-power-mode", PROP_ID_LOW_POWER_MODE},
+ {"nvidia,pull-down-strength", PROP_ID_DRIVE_DOWN_STRENGTH},
+ {"nvidia,pull-up-strength", PROP_ID_DRIVE_UP_STRENGTH},
+ {"nvidia,slew-rate-falling", PROP_ID_SLEW_RATE_FALLING},
+ {"nvidia,slew-rate-rising", PROP_ID_SLEW_RATE_RISING},
+ {"nvidia,drive-type", PROP_ID_DRIVE_TYPE},
+};
+
+/*
+ * configuration for one pin group.
+ */
+struct pincfg {
+ char *function;
+ int params[PROP_ID_MAX_ID];
+};
+#define GPIO_BANK_A 0
+#define GPIO_BANK_B 1
+#define GPIO_BANK_C 2
+#define GPIO_BANK_D 3
+#define GPIO_BANK_E 4
+#define GPIO_BANK_F 5
+#define GPIO_BANK_G 6
+#define GPIO_BANK_H 7
+#define GPIO_BANK_I 8
+#define GPIO_BANK_J 9
+#define GPIO_BANK_K 10
+#define GPIO_BANK_L 11
+#define GPIO_BANK_M 12
+#define GPIO_BANK_N 13
+#define GPIO_BANK_O 14
+#define GPIO_BANK_P 15
+#define GPIO_BANK_Q 16
+#define GPIO_BANK_R 17
+#define GPIO_BANK_S 18
+#define GPIO_BANK_T 19
+#define GPIO_BANK_U 20
+#define GPIO_BANK_V 21
+#define GPIO_BANK_W 22
+#define GPIO_BANK_X 23
+#define GPIO_BANK_Y 24
+#define GPIO_BANK_Z 25
+#define GPIO_BANK_AA 26
+#define GPIO_BANK_BB 27
+#define GPIO_BANK_CC 28
+#define GPIO_BANK_DD 29
+#define GPIO_BANK_EE 30
+#define GPIO_BANK_FF 31
+#define GPIO_NUM(b, p) (8 * (b) + (p))
+
+struct tegra_mux {
+ char *name;
+ bus_size_t reg;
+ char *functions[4];
+ int gpio_num;
+};
+
+#define GMUX(r, gb, gi, nm, f1, f2, f3, f4) \
+{ \
+ .name = #nm, \
+ .reg = r, \
+ .gpio_num = GPIO_NUM(GPIO_BANK_##gb, gi), \
+ .functions = {#f1, #f2, #f3, #f4}, \
+}
+
+#define FMUX(r, nm, f1, f2, f3, f4) \
+{ \
+ .name = #nm, \
+ .reg = r, \
+ .gpio_num = -1, \
+ .functions = {#f1, #f2, #f3, #f4}, \
+}
+
+static const struct tegra_mux pin_mux_tbl[] = {
+ GMUX(0x000, O, 1, ulpi_data0_po1, spi3, hsi, uarta, ulpi),
+ GMUX(0x004, O, 2, ulpi_data1_po2, spi3, hsi, uarta, ulpi),
+ GMUX(0x008, O, 3, ulpi_data2_po3, spi3, hsi, uarta, ulpi),
+ GMUX(0x00C, O, 4, ulpi_data3_po4, spi3, hsi, uarta, ulpi),
+ GMUX(0x010, O, 5, ulpi_data4_po5, spi2, hsi, uarta, ulpi),
+ GMUX(0x014, O, 6, ulpi_data5_po6, spi2, hsi, uarta, ulpi),
+ GMUX(0x018, O, 7, ulpi_data6_po7, spi2, hsi, uarta, ulpi),
+ GMUX(0x01C, O, 0, ulpi_data7_po0, spi2, hsi, uarta, ulpi),
+ GMUX(0x020, P, 9, ulpi_clk_py0, spi1, spi5, uartd, ulpi),
+ GMUX(0x024, P, 1, ulpi_dir_py1, spi1, spi5, uartd, ulpi),
+ GMUX(0x028, P, 2, ulpi_nxt_py2, spi1, spi5, uartd, ulpi),
+ GMUX(0x02C, P, 3, ulpi_stp_py3, spi1, spi5, uartd, ulpi),
+ GMUX(0x030, P, 0, dap3_fs_pp0, i2s2, spi5, displaya, displayb),
+ GMUX(0x034, P, 1, dap3_din_pp1, i2s2, spi5, displaya, displayb),
+ GMUX(0x038, P, 2, dap3_dout_pp2, i2s2, spi5, displaya, rsvd4),
+ GMUX(0x03C, P, 3, dap3_sclk_pp3, i2s2, spi5, rsvd3, displayb),
+ GMUX(0x040, V, 0, pv0, rsvd1, rsvd2, rsvd3, rsvd4),
+ GMUX(0x044, V, 1, pv1, rsvd1, rsvd2, rsvd3, rsvd4),
+ GMUX(0x048, Z, 0, sdmmc1_clk_pz0, sdmmc1, clk12, rsvd3, rsvd4),
+ GMUX(0x04C, Z, 1, sdmmc1_cmd_pz1, sdmmc1, spdif, spi4, uarta),
+ GMUX(0x050, Y, 4, sdmmc1_dat3_py4, sdmmc1, spdif, spi4, uarta),
+ GMUX(0x054, Y, 5, sdmmc1_dat2_py5, sdmmc1, pwm0, spi4, uarta),
+ GMUX(0x058, Y, 6, sdmmc1_dat1_py6, sdmmc1, pwm1, spi4, uarta),
+ GMUX(0x05C, Y, 7, sdmmc1_dat0_py7, sdmmc1, rsvd2, spi4, uarta),
+ GMUX(0x068, W, 5, clk2_out_pw5, extperiph2, rsvd2, rsvd3, rsvd4),
+ GMUX(0x06C, CC, 5, clk2_req_pcc5, dap, rsvd2, rsvd3, rsvd4),
+ GMUX(0x110, N, 7, hdmi_int_pn7, rsvd1, rsvd2, rsvd3, rsvd4),
+ GMUX(0x114, V, 4, ddc_scl_pv4, i2c4, rsvd2, rsvd3, rsvd4),
+ GMUX(0x118, V, 5, ddc_sda_pv5, i2c4, rsvd2, rsvd3, rsvd4),
+ GMUX(0x164, V, 3, uart2_rxd_pc3, irda, spdif, uarta, spi4),
+ GMUX(0x168, C, 2, uart2_txd_pc2, irda, spdif, uarta, spi4),
+ GMUX(0x16C, J, 6, uart2_rts_n_pj6, uarta, uartb, gmi, spi4),
+ GMUX(0x170, J, 5, uart2_cts_n_pj5, uarta, uartb, gmi, spi4),
+ GMUX(0x174, W, 6, uart3_txd_pw6, uartc, rsvd2, gmi, spi4),
+ GMUX(0x178, W, 7, uart3_rxd_pw7, uartc, rsvd2, gmi, spi4),
+ GMUX(0x17C, S, 1, uart3_cts_n_pa1, uartc, sdmmc1, dtv, gmi),
+ GMUX(0x180, C, 0, uart3_rts_n_pc0, uartc, pwm0, dtv, gmi),
+ GMUX(0x184, U, 0, pu0, owr, uarta, gmi, rsvd4),
+ GMUX(0x188, U, 1, pu1, rsvd1, uarta, gmi, rsvd4),
+ GMUX(0x18C, U, 2, pu2, rsvd1, uarta, gmi, rsvd4),
+ GMUX(0x190, U, 3, pu3, pwm0, uarta, gmi, displayb),
+ GMUX(0x194, U, 4, pu4, pwm1, uarta, gmi, displayb),
+ GMUX(0x198, U, 5, pu5, pwm2, uarta, gmi, displayb),
+ GMUX(0x19C, U, 6, pu6, pwm3, uarta, rsvd3, gmi),
+ GMUX(0x1A0, C, 5, gen1_i2c_sda_pc5, i2c1, rsvd2, rsvd3, rsvd4),
+ GMUX(0x1A4, C, 4, gen1_i2c_scl_pc4, i2c1, rsvd2, rsvd3, rsvd4),
+ GMUX(0x1A8, P, 3, dap4_fs_pp4, i2s3, gmi, dtv, rsvd4),
+ GMUX(0x1AC, P, 4, dap4_din_pp5, i2s3, gmi, rsvd3, rsvd4),
+ GMUX(0x1B0, P, 5, dap4_dout_pp6, i2s3, gmi, dtv, rsvd4),
+ GMUX(0x1B4, P, 7, dap4_sclk_pp7, i2s3, gmi, rsvd3, rsvd4),
+ GMUX(0x1B8, P, 0, clk3_out_pee0, extperiph3, rsvd2, rsvd3, rsvd4),
+ GMUX(0x1BC, EE, 1, clk3_req_pee1, dev3, rsvd2, rsvd3, rsvd4),
+ GMUX(0x1C0, C, 7, pc7, rsvd1, rsvd2, gmi, gmi_alt),
+ GMUX(0x1C4, I, 5, pi5, sdmmc2, rsvd2, gmi, rsvd4),
+ GMUX(0x1C8, I, 7, pi7, rsvd1, trace, gmi, dtv),
+ GMUX(0x1CC, K, 0, pk0, rsvd1, sdmmc3, gmi, soc),
+ GMUX(0x1D0, K, 1, pk1, sdmmc2, trace, gmi, rsvd4),
+ GMUX(0x1D4, J, 0, pj0, rsvd1, rsvd2, gmi, usb),
+ GMUX(0x1D8, J, 2, pj2, rsvd1, rsvd2, gmi, soc),
+ GMUX(0x1DC, K, 3, pk3, sdmmc2, trace, gmi, ccla),
+ GMUX(0x1E0, K, 4, pk4, sdmmc2, rsvd2, gmi, gmi_alt),
+ GMUX(0x1E4, K, 2, pk2, rsvd1, rsvd2, gmi, rsvd4),
+ GMUX(0x1E8, I, 3, pi3, rsvd1, rsvd2, gmi, spi4),
+ GMUX(0x1EC, I, 6, pi6, rsvd1, rsvd2, gmi, sdmmc2),
+ GMUX(0x1F0, G, 0, pg0, rsvd1, rsvd2, gmi, rsvd4),
+ GMUX(0x1F4, G, 1, pg1, rsvd1, rsvd2, gmi, rsvd4),
+ GMUX(0x1F8, G, 2, pg2, rsvd1, trace, gmi, rsvd4),
+ GMUX(0x1FC, G, 3, pg3, rsvd1, trace, gmi, rsvd4),
+ GMUX(0x200, G, 4, pg4, rsvd1, tmds, gmi, spi4),
+ GMUX(0x204, G, 5, pg5, rsvd1, rsvd2, gmi, spi4),
+ GMUX(0x208, G, 6, pg6, rsvd1, rsvd2, gmi, spi4),
+ GMUX(0x20C, G, 7, pg7, rsvd1, rsvd2, gmi, spi4),
+ GMUX(0x210, H, 0, ph0, pwm0, trace, gmi, dtv),
+ GMUX(0x214, H, 1, ph1, pwm1, tmds, gmi, displaya),
+ GMUX(0x218, H, 2, ph2, pwm2, tmds, gmi, cldvfs),
+ GMUX(0x21C, H, 3, ph3, pwm3, spi4, gmi, cldvfs),
+ GMUX(0x220, H, 4, ph4, sdmmc2, rsvd2, gmi, rsvd4),
+ GMUX(0x224, H, 5, ph5, sdmmc2, rsvd2, gmi, rsvd4),
+ GMUX(0x228, H, 6, ph6, sdmmc2, trace, gmi, dtv),
+ GMUX(0x22C, H, 7, ph7, sdmmc2, trace, gmi, dtv),
+ GMUX(0x230, J, 7, pj7, uartd, rsvd2, gmi, gmi_alt),
+ GMUX(0x234, B, 0, pb0, uartd, rsvd2, gmi, rsvd4),
+ GMUX(0x238, B, 1, pb1, uartd, rsvd2, gmi, rsvd4),
+ GMUX(0x23C, K, 7, pk7, uartd, rsvd2, gmi, rsvd4),
+ GMUX(0x240, I, 0, pi0, rsvd1, rsvd2, gmi, rsvd4),
+ GMUX(0x244, I, 1, pi1, rsvd1, rsvd2, gmi, rsvd4),
+ GMUX(0x248, I, 2, pi2, sdmmc2, trace, gmi, rsvd4),
+ GMUX(0x24C, I, 4, pi4, spi4, trace, gmi, displaya),
+ GMUX(0x250, T, 5, gen2_i2c_scl_pt5, i2c2, rsvd2, gmi, rsvd4),
+ GMUX(0x254, T, 6, gen2_i2c_sda_pt6, i2c2, rsvd2, gmi, rsvd4),
+ GMUX(0x258, CC, 4, sdmmc4_clk_pcc4, sdmmc4, rsvd2, gmi, rsvd4),
+ GMUX(0x25C, T, 7, sdmmc4_cmd_pt7, sdmmc4, rsvd2, gmi, rsvd4),
+ GMUX(0x260, AA, 0, sdmmc4_dat0_paa0, sdmmc4, spi3, gmi, rsvd4),
+ GMUX(0x264, AA, 1, sdmmc4_dat1_paa1, sdmmc4, spi3, gmi, rsvd4),
+ GMUX(0x268, AA, 2, sdmmc4_dat2_paa2, sdmmc4, spi3, gmi, rsvd4),
+ GMUX(0x26C, AA, 3, sdmmc4_dat3_paa3, sdmmc4, spi3, gmi, rsvd4),
+ GMUX(0x270, AA, 4, sdmmc4_dat4_paa4, sdmmc4, spi3, gmi, rsvd4),
+ GMUX(0x274, AA, 5, sdmmc4_dat5_paa5, sdmmc4, spi3, rsvd3, rsvd4),
+ GMUX(0x278, AA, 6, sdmmc4_dat6_paa6, sdmmc4, spi3, gmi, rsvd4),
+ GMUX(0x27C, AA, 7, sdmmc4_dat7_paa7, sdmmc4, rsvd2, gmi, rsvd4),
+ GMUX(0x284, CC, 0, cam_mclk_pcc0, vi, vi_alt1, vi_alt3, sdmmc2),
+ GMUX(0x288, CC, 1, pcc1, i2s4, rsvd2, rsvd3, sdmmc2),
+ GMUX(0x28C, BB, 0, pbb0, vgp6, vimclk2, sdmmc2, vimclk2_alt),
+ GMUX(0x290, BB, 1, cam_i2c_scl_pbb1, vgp1, i2c3, rsvd3, sdmmc2),
+ GMUX(0x294, BB, 2, cam_i2c_sda_pbb2, vgp2, i2c3, rsvd3, sdmmc2),
+ GMUX(0x298, BB, 3, pbb3, vgp3, displaya, displayb, sdmmc2),
+ GMUX(0x29C, BB, 4, pbb4, vgp4, displaya, displayb, sdmmc2),
+ GMUX(0x2A0, BB, 5, pbb5, vgp5, displaya, rsvd3, sdmmc2),
+ GMUX(0x2A4, BB, 6, pbb6, i2s4, rsvd2, displayb, sdmmc2),
+ GMUX(0x2A8, BB, 7, pbb7, i2s4, rsvd2, rsvd3, sdmmc2),
+ GMUX(0x2AC, CC, 2, pcc2, i2s4, rsvd2, sdmmc3, sdmmc2),
+ FMUX(0x2B0, jtag_rtck, rtck, rsvd2, rsvd3, rsvd4),
+ GMUX(0x2B4, Z, 6, pwr_i2c_scl_pz6, i2cpwr, rsvd2, rsvd3, rsvd4),
+ GMUX(0x2B8, Z, 7, pwr_i2c_sda_pz7, i2cpwr, rsvd2, rsvd3, rsvd4),
+ GMUX(0x2BC, R, 0, kb_row0_pr0, kbc, rsvd2, rsvd3, rsvd4),
+ GMUX(0x2C0, R, 1, kb_row1_pr1, kbc, rsvd2, rsvd3, rsvd4),
+ GMUX(0x2C4, R, 2, kb_row2_pr2, kbc, rsvd2, rsvd3, rsvd4),
+ GMUX(0x2C8, R, 3, kb_row3_pr3, kbc, displaya, sys, displayb),
+ GMUX(0x2CC, R, 4, kb_row4_pr4, kbc, displaya, rsvd3, displayb),
+ GMUX(0x2D0, R, 5, kb_row5_pr5, kbc, displaya, rsvd3, displayb),
+ GMUX(0x2D4, R, 6, kb_row6_pr6, kbc, displaya, displaya_alt, displayb),
+ GMUX(0x2D8, R, 7, kb_row7_pr7, kbc, rsvd2, cldvfs, uarta),
+ GMUX(0x2DC, S, 0, kb_row8_ps0, kbc, rsvd2, cldvfs, uarta),
+ GMUX(0x2E0, S, 1, kb_row9_ps1, kbc, rsvd2, rsvd3, uarta),
+ GMUX(0x2E4, S, 2, kb_row10_ps2, kbc, rsvd2, rsvd3, uarta),
+ GMUX(0x2E8, S, 3, kb_row11_ps3, kbc, rsvd2, rsvd3, irda),
+ GMUX(0x2EC, S, 4, kb_row12_ps4, kbc, rsvd2, rsvd3, irda),
+ GMUX(0x2F0, S, 5, kb_row13_ps5, kbc, rsvd2, spi2, rsvd4),
+ GMUX(0x2F4, S, 6, kb_row14_ps6, kbc, rsvd2, spi2, rsvd4),
+ GMUX(0x2F8, S, 7, kb_row15_ps7, kbc, soc, rsvd3, rsvd4),
+ GMUX(0x2FC, Q, 0, kb_col0_pq0, kbc, rsvd2, spi2, rsvd4),
+ GMUX(0x300, Q, 1, kb_col1_pq1, kbc, rsvd2, spi2, rsvd4),
+ GMUX(0x304, Q, 2, kb_col2_pq2, kbc, rsvd2, spi2, rsvd4),
+ GMUX(0x308, Q, 3, kb_col3_pq3, kbc, displaya, pwm2, uarta),
+ GMUX(0x30C, Q, 4, kb_col4_pq4, kbc, owr, sdmmc3, uarta),
+ GMUX(0x310, Q, 5, kb_col5_pq5, kbc, rsvd2, sdmmc3, rsvd4),
+ GMUX(0x314, Q, 6, kb_col6_pq6, kbc, rsvd2, spi2, uartd),
+ GMUX(0x318, Q, 7, kb_col7_pq7, kbc, rsvd2, spi2, uartd),
+ GMUX(0x31C, A, 0, clk_32k_out_pa0, blink, soc, rsvd3, rsvd4),
+ FMUX(0x324, core_pwr_req, pwron, rsvd2, rsvd3, rsvd4),
+ FMUX(0x328, cpu_pwr_req, cpu, rsvd2, rsvd3, rsvd4),
+ FMUX(0x32C, pwr_int_n, pmi, rsvd2, rsvd3, rsvd4),
+ FMUX(0x330, clk_32k_in, clk, rsvd2, rsvd3, rsvd4),
+ FMUX(0x334, owr, owr, rsvd2, rsvd3, rsvd4),
+ GMUX(0x338, N, 0, dap1_fs_pn0, i2s0, hda, gmi, rsvd4),
+ GMUX(0x33C, N, 1, dap1_din_pn1, i2s0, hda, gmi, rsvd4),
+ GMUX(0x340, N, 2, dap1_dout_pn2, i2s0, hda, gmi, sata),
+ GMUX(0x344, N, 3, dap1_sclk_pn3, i2s0, hda, gmi, rsvd4),
+ GMUX(0x348, EE, 2, dap_mclk1_req_pee2, dap, dap1, sata, rsvd4),
+ GMUX(0x34C, W, 4, dap_mclk1_pw4, extperiph1, dap2, rsvd3, rsvd4),
+ GMUX(0x350, K, 6, spdif_in_pk6, spdif, rsvd2, rsvd3, i2c3),
+ GMUX(0x354, K, 5, spdif_out_pk5, spdif, rsvd2, rsvd3, i2c3),
+ GMUX(0x358, A, 2, dap2_fs_pa2, i2s1, hda, gmi, rsvd4),
+ GMUX(0x35C, A, 4, dap2_din_pa4, i2s1, hda, gmi, rsvd4),
+ GMUX(0x360, A, 5, dap2_dout_pa5, i2s1, hda, gmi, rsvd4),
+ GMUX(0x364, A, 3, dap2_sclk_pa3, i2s1, hda, gmi, rsvd4),
+ GMUX(0x368, X, 0, dvfs_pwm_px0, spi6, cldvfs, gmi, rsvd4),
+ GMUX(0x36C, X, 1, gpio_x1_aud_px1, spi6, rsvd2, gmi, rsvd4),
+ GMUX(0x370, X, 3, gpio_x3_aud_px3, spi6, spi1, gmi, rsvd4),
+ GMUX(0x374, X, 2, dvfs_clk_px2, spi6, cldvfs, gmi, rsvd4),
+ GMUX(0x378, X, 4, gpio_x4_aud_px4, gmi, spi1, spi2, dap2),
+ GMUX(0x37C, X, 5, gpio_x5_aud_px5, gmi, spi1, spi2, rsvd4),
+ GMUX(0x380, X, 6, gpio_x6_aud_px6, spi6, spi1, spi2, gmi),
+ GMUX(0x384, X, 7, gpio_x7_aud_px7, rsvd1, spi1, spi2, rsvd4),
+ GMUX(0x390, A, 6, sdmmc3_clk_pa6, sdmmc3, rsvd2, rsvd3, spi3),
+ GMUX(0x394, A, 7, sdmmc3_cmd_pa7, sdmmc3, pwm3, uarta, spi3),
+ GMUX(0x398, B, 7, sdmmc3_dat0_pb7, sdmmc3, rsvd2, rsvd3, spi3),
+ GMUX(0x39C, B, 6, sdmmc3_dat1_pb6, sdmmc3, pwm2, uarta, spi3),
+ GMUX(0x3A0, B, 5, sdmmc3_dat2_pb5, sdmmc3, pwm1, displaya, spi3),
+ GMUX(0x3A4, B, 4, sdmmc3_dat3_pb4, sdmmc3, pwm0, displayb, spi3),
+ GMUX(0x3BC, DD, 1, pex_l0_rst_n_pdd1, pe0, rsvd2, rsvd3, rsvd4),
+ GMUX(0x3C0, DD, 2, pex_l0_clkreq_n_pdd2, pe0, rsvd2, rsvd3, rsvd4),
+ GMUX(0x3C4, DD, 3, pex_wake_n_pdd3, pe, rsvd2, rsvd3, rsvd4),
+ GMUX(0x3CC, DD, 5, pex_l1_rst_n_pdd5, pe1, rsvd2, rsvd3, rsvd4),
+ GMUX(0x3D0, DD, 6, pex_l1_clkreq_n_pdd6, pe1, rsvd2, rsvd3, rsvd4),
+ GMUX(0x3E0, EE, 3, hdmi_cec_pee3, cec, rsvd2, rsvd3, rsvd4),
+ GMUX(0x3E4, V, 3, sdmmc1_wp_n_pv3, sdmmc1, clk12, spi4, uarta),
+ GMUX(0x3E8, V, 2, sdmmc3_cd_n_pv2, sdmmc3, owr, rsvd3, rsvd4),
+ GMUX(0x3EC, W, 2, gpio_w2_aud_pw2, spi6, rsvd2, spi2, i2c1),
+ GMUX(0x3F0, W, 3, gpio_w3_aud_pw3, spi6, spi1, spi2, i2c1),
+ GMUX(0x3F4, N, 4, usb_vbus_en0_pn4, usb, rsvd2, rsvd3, rsvd4),
+ GMUX(0x3F8, N, 5, usb_vbus_en1_pn5, usb, rsvd2, rsvd3, rsvd4),
+ GMUX(0x3FC, EE, 5, sdmmc3_clk_lb_in_pee5, sdmmc3, rsvd2, rsvd3, rsvd4),
+ GMUX(0x400, EE, 4, sdmmc3_clk_lb_out_pee4, sdmmc3, rsvd2, rsvd3, rsvd4),
+ FMUX(0x404, gmi_clk_lb, sdmmc2, rsvd2, gmi, rsvd4),
+ FMUX(0x408, reset_out_n, rsvd1, rsvd2, rsvd3, reset_out_n),
+ GMUX(0x40C, T, 0, kb_row16_pt0, kbc, rsvd2, rsvd3, uartc),
+ GMUX(0x410, T, 1, kb_row17_pt1, kbc, rsvd2, rsvd3, uartc),
+ GMUX(0x414, FF, 1, usb_vbus_en2_pff1, usb, rsvd2, rsvd3, rsvd4),
+ GMUX(0x418, FF, 2, pff2, sata, rsvd2, rsvd3, rsvd4),
+ GMUX(0x430, FF, 0, dp_hpd_pff0, dp, rsvd2, rsvd3, rsvd4),
+};
+
+struct tegra_grp {
+ char *name;
+ bus_size_t reg;
+ int drvdn_shift;
+ int drvdn_mask;
+ int drvup_shift;
+ int drvup_mask;
+};
+
+#define GRP(r, nm, dn_s, dn_w, up_s, up_w) \
+{ \
+ .name = #nm, \
+ .reg = r - 0x868, \
+ .drvdn_shift = dn_s, \
+ .drvdn_mask = (1 << dn_w) - 1, \
+ .drvup_shift = up_s, \
+ .drvup_mask = (1 << dn_w) - 1, \
+}
+
+/* Use register offsets from TRM */
+static const struct tegra_grp pin_grp_tbl[] = {
+ GRP(0x868, ao1, 12, 5, 20, 5),
+ GRP(0x86C, ao2, 12, 5, 20, 5),
+ GRP(0x870, at1, 12, 7, 20, 7),
+ GRP(0x874, at2, 12, 7, 20, 7),
+ GRP(0x878, at3, 12, 7, 20, 7),
+ GRP(0x87C, at4, 12, 7, 20, 7),
+ GRP(0x880, at5, 14, 5, 19, 5),
+ GRP(0x884, cdev1, 12, 5, 20, 5),
+ GRP(0x888, cdev2, 12, 5, 20, 5),
+ GRP(0x890, dap1, 12, 5, 20, 5),
+ GRP(0x894, dap2, 12, 5, 20, 5),
+ GRP(0x898, dap3, 12, 5, 20, 5),
+ GRP(0x89C, dap4, 12, 5, 20, 5),
+ GRP(0x8A0, dbg, 12, 5, 20, 5),
+ GRP(0x8B0, sdio3, 12, 7, 20, 7),
+ GRP(0x8B4, spi, 12, 5, 20, 5),
+ GRP(0x8B8, uaa, 12, 5, 20, 5),
+ GRP(0x8BC, uab, 12, 5, 20, 5),
+ GRP(0x8C0, uart2, 12, 5, 20, 5),
+ GRP(0x8C4, uart3, 12, 5, 20, 5),
+ GRP(0x8EC, sdio1, 12, 7, 20, 7),
+ GRP(0x8FC, ddc, 12, 5, 20, 5),
+ GRP(0x900, gma, 14, 5, 20, 5),
+ GRP(0x910, gme, 14, 5, 19, 5),
+ GRP(0x914, gmf, 14, 5, 19, 5),
+ GRP(0x918, gmg, 14, 5, 19, 5),
+ GRP(0x91C, gmh, 14, 5, 19, 5),
+ GRP(0x920, owr, 12, 5, 20, 5),
+ GRP(0x924, uda, 12, 5, 20, 5),
+ GRP(0x928, gpv, 12, 5, 20, 5),
+ GRP(0x92C, dev3, 12, 5, 20, 5),
+ GRP(0x938, cec, 12, 5, 20, 5),
+ GRP(0x994, at6, 12, 7, 20, 7),
+ GRP(0x998, dap5, 12, 5, 20, 5),
+ GRP(0x99C, usb_vbus_en, 12, 5, 20, 5),
+ GRP(0x9A8, ao3, 12, 5, -1, 0),
+ GRP(0x9B0, ao0, 12, 5, 20, 5),
+ GRP(0x9B4, hv0, 12, 5, -1, 0),
+ GRP(0x9C4, sdio4, 12, 5, 20, 5),
+ GRP(0x9C8, ao4, 12, 7, 20, 7),
+};
+
+static const struct tegra_grp *
+pinmux_search_grp(char *grp_name)
+{
+ int i;
+
+ for (i = 0; i < nitems(pin_grp_tbl); i++) {
+ if (strcmp(grp_name, pin_grp_tbl[i].name) == 0)
+ return (&pin_grp_tbl[i]);
+ }
+ return (NULL);
+}
+
+static const struct tegra_mux *
+pinmux_search_mux(char *pin_name)
+{
+ int i;
+
+ for (i = 0; i < nitems(pin_mux_tbl); i++) {
+ if (strcmp(pin_name, pin_mux_tbl[i].name) == 0)
+ return (&pin_mux_tbl[i]);
+ }
+ return (NULL);
+}
+
+static int
+pinmux_mux_function(const struct tegra_mux *mux, char *fnc_name)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ if (strcmp(fnc_name, mux->functions[i]) == 0)
+ return (i);
+ }
+ return (-1);
+}
+
+static int
+pinmux_config_mux(struct pinmux_softc *sc, char *pin_name,
+ const struct tegra_mux *mux, struct pincfg *cfg)
+{
+ int tmp;
+ uint32_t reg;
+
+ reg = bus_read_4(sc->mux_mem_res, mux->reg);
+
+ if (cfg->function != NULL) {
+ tmp = pinmux_mux_function(mux, cfg->function);
+ if (tmp == -1) {
+ device_printf(sc->dev,
+ "Unknown function %s for pin %s\n", cfg->function,
+ pin_name);
+ return (ENXIO);
+ }
+ reg &= ~(TEGRA_MUX_FUNCTION_MASK << TEGRA_MUX_FUNCTION_SHIFT);
+ reg |= (tmp & TEGRA_MUX_FUNCTION_MASK) <<
+ TEGRA_MUX_FUNCTION_SHIFT;
+ }
+ if (cfg->params[PROP_ID_PULL] != -1) {
+ reg &= ~(TEGRA_MUX_PUPD_MASK << TEGRA_MUX_PUPD_SHIFT);
+ reg |= (cfg->params[PROP_ID_PULL] & TEGRA_MUX_PUPD_MASK) <<
+ TEGRA_MUX_PUPD_SHIFT;
+ }
+ if (cfg->params[PROP_ID_TRISTATE] != -1) {
+ reg &= ~(1 << TEGRA_MUX_TRISTATE_SHIFT);
+ reg |= (cfg->params[PROP_ID_TRISTATE] & 1) <<
+ TEGRA_MUX_TRISTATE_SHIFT;
+ }
+ if (cfg->params[TEGRA_MUX_ENABLE_INPUT_SHIFT] != -1) {
+ reg &= ~(1 << TEGRA_MUX_ENABLE_INPUT_SHIFT);
+ reg |= (cfg->params[TEGRA_MUX_ENABLE_INPUT_SHIFT] & 1) <<
+ TEGRA_MUX_ENABLE_INPUT_SHIFT;
+ }
+ if (cfg->params[PROP_ID_ENABLE_INPUT] != -1) {
+ reg &= ~(1 << TEGRA_MUX_ENABLE_INPUT_SHIFT);
+ reg |= (cfg->params[PROP_ID_ENABLE_INPUT] & 1) <<
+ TEGRA_MUX_ENABLE_INPUT_SHIFT;
+ }
+ if (cfg->params[PROP_ID_ENABLE_INPUT] != -1) {
+ reg &= ~(1 << TEGRA_MUX_ENABLE_INPUT_SHIFT);
+ reg |= (cfg->params[PROP_ID_OPEN_DRAIN] & 1) <<
+ TEGRA_MUX_ENABLE_INPUT_SHIFT;
+ }
+ if (cfg->params[PROP_ID_LOCK] != -1) {
+ reg &= ~(1 << TEGRA_MUX_LOCK_SHIFT);
+ reg |= (cfg->params[PROP_ID_LOCK] & 1) <<
+ TEGRA_MUX_LOCK_SHIFT;
+ }
+ if (cfg->params[PROP_ID_IORESET] != -1) {
+ reg &= ~(1 << TEGRA_MUX_IORESET_SHIFT);
+ reg |= (cfg->params[PROP_ID_IORESET] & 1) <<
+ TEGRA_MUX_IORESET_SHIFT;
+ }
+ if (cfg->params[PROP_ID_RCV_SEL] != -1) {
+ reg &= ~(1 << TEGRA_MUX_RCV_SEL_SHIFT);
+ reg |= (cfg->params[PROP_ID_RCV_SEL] & 1) <<
+ TEGRA_MUX_RCV_SEL_SHIFT;
+ }
+ bus_write_4(sc->mux_mem_res, mux->reg, reg);
+ return (0);
+}
+
+static int
+pinmux_config_grp(struct pinmux_softc *sc, char *grp_name,
+ const struct tegra_grp *grp, struct pincfg *cfg)
+{
+ uint32_t reg;
+
+ reg = bus_read_4(sc->pad_mem_res, grp->reg);
+
+ if (cfg->params[PROP_ID_HIGH_SPEED_MODE] != -1) {
+ reg &= ~(1 << TEGRA_GRP_HSM_SHIFT);
+ reg |= (cfg->params[PROP_ID_HIGH_SPEED_MODE] & 1) <<
+ TEGRA_GRP_HSM_SHIFT;
+ }
+ if (cfg->params[PROP_ID_SCHMITT] != -1) {
+ reg &= ~(1 << TEGRA_GRP_SCHMT_SHIFT);
+ reg |= (cfg->params[PROP_ID_SCHMITT] & 1) <<
+ TEGRA_GRP_SCHMT_SHIFT;
+ }
+ if (cfg->params[PROP_ID_DRIVE_TYPE] != -1) {
+ reg &= ~(TEGRA_GRP_DRV_TYPE_MASK << TEGRA_GRP_DRV_TYPE_SHIFT);
+ reg |= (cfg->params[PROP_ID_DRIVE_TYPE] &
+ TEGRA_GRP_DRV_TYPE_MASK) << TEGRA_GRP_DRV_TYPE_SHIFT;
+ }
+ if (cfg->params[PROP_ID_SLEW_RATE_RISING] != -1) {
+ reg &= ~(TEGRA_GRP_DRV_DRVDN_SLWR_MASK <<
+ TEGRA_GRP_DRV_DRVDN_SLWR_SHIFT);
+ reg |= (cfg->params[PROP_ID_SLEW_RATE_RISING] &
+ TEGRA_GRP_DRV_DRVDN_SLWR_MASK) <<
+ TEGRA_GRP_DRV_DRVDN_SLWR_SHIFT;
+ }
+ if (cfg->params[PROP_ID_SLEW_RATE_FALLING] != -1) {
+ reg &= ~(TEGRA_GRP_DRV_DRVUP_SLWF_MASK <<
+ TEGRA_GRP_DRV_DRVUP_SLWF_SHIFT);
+ reg |= (cfg->params[PROP_ID_SLEW_RATE_FALLING] &
+ TEGRA_GRP_DRV_DRVUP_SLWF_MASK) <<
+ TEGRA_GRP_DRV_DRVUP_SLWF_SHIFT;
+ }
+ if ((cfg->params[PROP_ID_DRIVE_DOWN_STRENGTH] != -1) &&
+ (grp->drvdn_mask != -1)) {
+ reg &= ~(grp->drvdn_shift << grp->drvdn_mask);
+ reg |= (cfg->params[PROP_ID_DRIVE_DOWN_STRENGTH] &
+ grp->drvdn_mask) << grp->drvdn_shift;
+ }
+ if ((cfg->params[PROP_ID_DRIVE_UP_STRENGTH] != -1) &&
+ (grp->drvup_mask != -1)) {
+ reg &= ~(grp->drvup_shift << grp->drvup_mask);
+ reg |= (cfg->params[PROP_ID_DRIVE_UP_STRENGTH] &
+ grp->drvup_mask) << grp->drvup_shift;
+ }
+ bus_write_4(sc->pad_mem_res, grp->reg, reg);
+ return (0);
+}
+
+static int
+pinmux_config_node(struct pinmux_softc *sc, char *pin_name, struct pincfg *cfg)
+{
+ const struct tegra_mux *mux;
+ const struct tegra_grp *grp;
+ uint32_t reg;
+ int rv;
+
+ /* Handle MIPI special case first */
+ if (strcmp(pin_name, "dsi_b") == 0) {
+ if (cfg->function == NULL) {
+ /* nothing to set */
+ return (0);
+ }
+ reg = bus_read_4(sc->mipi_mem_res, 0); /* register 0x820 */
+ if (strcmp(cfg->function, "csi") == 0)
+ reg &= ~(1 << 1);
+ else if (strcmp(cfg->function, "dsi_b") == 0)
+ reg |= (1 << 1);
+ bus_write_4(sc->mipi_mem_res, 0, reg); /* register 0x820 */
+ }
+
+ /* Handle pin muxes */
+ mux = pinmux_search_mux(pin_name);
+ if (mux != NULL) {
+ if (mux->gpio_num != -1) {
+ /* XXXX TODO: Reserve gpio here */
+ }
+ rv = pinmux_config_mux(sc, pin_name, mux, cfg);
+ return (rv);
+ }
+
+ /* Handle pin groups */
+ grp = pinmux_search_grp(pin_name);
+ if (grp != NULL) {
+ rv = pinmux_config_grp(sc, pin_name, grp, cfg);
+ return (rv);
+ }
+
+ device_printf(sc->dev, "Unknown pin: %s\n", pin_name);
+ return (ENXIO);
+}
+
+static int
+pinmux_read_node(struct pinmux_softc *sc, phandle_t node, struct pincfg *cfg,
+ char **pins, int *lpins)
+{
+ int rv, i;
+
+ *lpins = OF_getprop_alloc(node, "nvidia,pins", 1, (void **)pins);
+ if (*lpins <= 0)
+ return (ENOENT);
+
+ /* Read function (mux) settings. */
+ rv = OF_getprop_alloc(node, "nvidia,function", 1,
+ (void **)&cfg->function);
+ if (rv <= 0)
+ cfg->function = NULL;
+
+ /* Read numeric properties. */
+ for (i = 0; i < PROP_ID_MAX_ID; i++) {
+ rv = OF_getencprop(node, prop_names[i].name, &cfg->params[i],
+ sizeof(cfg->params[i]));
+ if (rv <= 0)
+ cfg->params[i] = -1;
+ }
+ return (0);
+}
+
+static int
+pinmux_process_node(struct pinmux_softc *sc, phandle_t node)
+{
+ struct pincfg cfg;
+ char *pins, *pname;
+ int i, len, lpins, rv;
+
+ rv = pinmux_read_node(sc, node, &cfg, &pins, &lpins);
+ if (rv != 0)
+ return (rv);
+
+ len = 0;
+ pname = pins;
+ do {
+ i = strlen(pname) + 1;
+ rv = pinmux_config_node(sc, pname, &cfg);
+ if (rv != 0)
+ device_printf(sc->dev,
+ "Cannot configure pin: %s: %d\n", pname, rv);
+
+ len += i;
+ pname += i;
+ } while (len < lpins);
+
+ if (pins != NULL)
+ free(pins, M_OFWPROP);
+ if (cfg.function != NULL)
+ free(cfg.function, M_OFWPROP);
+ return (rv);
+}
+
+static int pinmux_configure(device_t dev, phandle_t cfgxref)
+{
+ struct pinmux_softc *sc;
+ phandle_t node, cfgnode;
+ int rv;
+
+ sc = device_get_softc(dev);
+ cfgnode = OF_node_from_xref(cfgxref);
+
+
+ for (node = OF_child(cfgnode); node != 0; node = OF_peer(node)) {
+ if (!fdt_is_enabled(node))
+ continue;
+ rv = pinmux_process_node(sc, node);
+ }
+ return (0);
+}
+
+static int
+pinmux_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
+ return (ENXIO);
+
+ device_set_desc(dev, "Tegra pin configuration");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+pinmux_detach(device_t dev)
+{
+
+ /* This device is always present. */
+ return (EBUSY);
+}
+
+static int
+pinmux_attach(device_t dev)
+{
+ struct pinmux_softc * sc;
+ int rid;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ rid = 0;
+ sc->pad_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->pad_mem_res == NULL) {
+ device_printf(dev, "Cannot allocate memory resources\n");
+ return (ENXIO);
+ }
+
+ rid = 1;
+ sc->mux_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mux_mem_res == NULL) {
+ device_printf(dev, "Cannot allocate memory resources\n");
+ return (ENXIO);
+ }
+
+ rid = 2;
+ sc->mipi_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mipi_mem_res == NULL) {
+ device_printf(dev, "Cannot allocate memory resources\n");
+ return (ENXIO);
+ }
+
+ /* Register as a pinctrl device and process default configuration */
+ fdt_pinctrl_register(dev, NULL);
+ fdt_pinctrl_configure_by_name(dev, "boot");
+
+ return (0);
+}
+
+
+static device_method_t tegra_pinmux_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, pinmux_probe),
+ DEVMETHOD(device_attach, pinmux_attach),
+ DEVMETHOD(device_detach, pinmux_detach),
+
+ /* fdt_pinctrl interface */
+ DEVMETHOD(fdt_pinctrl_configure,pinmux_configure),
+
+ DEVMETHOD_END
+};
+
+static driver_t tegra_pinmux_driver = {
+ "tegra_pinmux",
+ tegra_pinmux_methods,
+ sizeof(struct pinmux_softc),
+};
+
+static devclass_t tegra_pinmux_devclass;
+
+EARLY_DRIVER_MODULE(tegra_pinmux, simplebus, tegra_pinmux_driver,
+ tegra_pinmux_devclass, 0, 0, 71);
diff --git a/sys/arm/nvidia/tegra_pmc.h b/sys/arm/nvidia/tegra_pmc.h
new file mode 100644
index 0000000..933c408
--- /dev/null
+++ b/sys/arm/nvidia/tegra_pmc.h
@@ -0,0 +1,115 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _TEGRA_PMC_H_
+#define _TEGRA_PMC_H_
+
+enum tegra_suspend_mode {
+ TEGRA_SUSPEND_NONE = 0,
+ TEGRA_SUSPEND_LP2, /* CPU voltage off */
+ TEGRA_SUSPEND_LP1, /* CPU voltage off, DRAM self-refresh */
+ TEGRA_SUSPEND_LP0, /* CPU + core voltage off, DRAM self-refresh */
+};
+
+/* PARTIDs for powergate */
+enum tegra_powergate_id {
+ TEGRA_POWERGATE_CRAIL = 0,
+ TEGRA_POWERGATE_TD = 1,
+ TEGRA_POWERGATE_VE = 2,
+ TEGRA_POWERGATE_PCX = 3,
+ TEGRA_POWERGATE_VDE = 4,
+ TEGRA_POWERGATE_L2C = 5,
+ TEGRA_POWERGATE_MPE = 6,
+ TEGRA_POWERGATE_HEG = 7,
+ TEGRA_POWERGATE_SAX = 8,
+ TEGRA_POWERGATE_CE1 = 9,
+ TEGRA_POWERGATE_CE2 = 10,
+ TEGRA_POWERGATE_CE3 = 11,
+ TEGRA_POWERGATE_CELP = 12,
+ /* */
+ TEGRA_POWERGATE_CE0 = 14,
+ TEGRA_POWERGATE_C0NC = 15,
+ TEGRA_POWERGATE_C1NC = 16,
+ TEGRA_POWERGATE_SOR = 17,
+ TEGRA_POWERGATE_DIS = 18,
+ TEGRA_POWERGATE_DISB = 19,
+ TEGRA_POWERGATE_XUSBA = 20,
+ TEGRA_POWERGATE_XUSBB = 21,
+ TEGRA_POWERGATE_XUSBC = 22,
+ TEGRA_POWERGATE_VIC = 23,
+ TEGRA_POWERGATE_IRAM = 24,
+ /* */
+ TEGRA_POWERGATE_3D = 32
+
+};
+
+/* PARTIDs for power rails */
+enum tegra_powerrail_id {
+ TEGRA_IO_RAIL_CSIA = 0,
+ TEGRA_IO_RAIL_CSIB = 1,
+ TEGRA_IO_RAIL_DSI = 2,
+ TEGRA_IO_RAIL_MIPI_BIAS = 3,
+ TEGRA_IO_RAIL_PEX_BIAS = 4,
+ TEGRA_IO_RAIL_PEX_CLK1 = 5,
+ TEGRA_IO_RAIL_PEX_CLK2 = 6,
+ TEGRA_IO_RAIL_USB0 = 9,
+ TEGRA_IO_RAIL_USB1 = 10,
+ TEGRA_IO_RAIL_USB2 = 11,
+ TEGRA_IO_RAIL_USB_BIAS = 12,
+ TEGRA_IO_RAIL_NAND = 13,
+ TEGRA_IO_RAIL_UART = 14,
+ TEGRA_IO_RAIL_BB = 15,
+ TEGRA_IO_RAIL_AUDIO = 17,
+ TEGRA_IO_RAIL_HSIC = 19,
+ TEGRA_IO_RAIL_COMP = 22,
+ TEGRA_IO_RAIL_HDMI = 28,
+ TEGRA_IO_RAIL_PEX_CNTRL = 32,
+ TEGRA_IO_RAIL_SDMMC1 = 33,
+ TEGRA_IO_RAIL_SDMMC3 = 34,
+ TEGRA_IO_RAIL_SDMMC4 = 35,
+ TEGRA_IO_RAIL_CAM = 36,
+ TEGRA_IO_RAIL_RES = 37,
+ TEGRA_IO_RAIL_HV = 38,
+ TEGRA_IO_RAIL_DSIB = 39,
+ TEGRA_IO_RAIL_DSIC = 40,
+ TEGRA_IO_RAIL_DSID = 41,
+ TEGRA_IO_RAIL_CSIE = 44,
+ TEGRA_IO_RAIL_LVDS = 57,
+ TEGRA_IO_RAIL_SYS_DDC = 58,
+};
+
+int tegra_powergate_is_powered(enum tegra_powergate_id id);
+int tegra_powergate_power_on(enum tegra_powergate_id id);
+int tegra_powergate_power_off(enum tegra_powergate_id id);
+int tegra_powergate_remove_clamping(enum tegra_powergate_id id);
+int tegra_powergate_sequence_power_up(enum tegra_powergate_id id,
+ clk_t clk, hwreset_t rst);
+int tegra_io_rail_power_on(int tegra_powerrail_id);
+int tegra_io_rail_power_off(int tegra_powerrail_id);
+
+#endif /*_TEGRA_PMC_H_*/ \ No newline at end of file
diff --git a/sys/arm/nvidia/tegra_rtc.c b/sys/arm/nvidia/tegra_rtc.c
new file mode 100644
index 0000000..c15ded3
--- /dev/null
+++ b/sys/arm/nvidia/tegra_rtc.c
@@ -0,0 +1,303 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * RTC driver for Tegra SoCs.
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/clock.h>
+#include <sys/kernel.h>
+#include <sys/limits.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/module.h>
+#include <sys/resource.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <dev/extres/clk/clk.h>
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "clock_if.h"
+
+#define RTC_CONTROL 0x00
+#define RTC_BUSY 0x04
+#define RTC_BUSY_STATUS (1 << 0)
+#define RTC_SECONDS 0x08
+#define RTC_SHADOW_SECONDS 0x0c
+#define RTC_MILLI_SECONDS 0x10
+#define RTC_SECONDS_ALARM0 0x14
+#define RTC_SECONDS_ALARM1 0x18
+#define RTC_MILLI_SECONDS_ALARM 0x1c
+#define RTC_SECONDS_COUNTDOWN_ALARM 0x20
+#define RTC_MILLI_SECONDS_COUNTDOW_ALARM 0x24
+#define RTC_INTR_MASK 0x28
+#define RTC_INTR_MSEC_CDN_ALARM (1 << 4)
+#define RTC_INTR_SEC_CDN_ALARM (1 << 3)
+#define RTC_INTR_MSEC_ALARM (1 << 2)
+#define RTC_INTR_SEC_ALARM1 (1 << 1)
+#define RTC_INTR_SEC_ALARM0 (1 << 0)
+
+#define RTC_INTR_STATUS 0x2c
+#define RTC_INTR_SOURCE 0x30
+#define RTC_INTR_SET 0x34
+#define RTC_CORRECTION_FACTOR 0x38
+
+#define WR4(_sc, _r, _v) bus_write_4((_sc)->mem_res, (_r), (_v))
+#define RD4(_sc, _r) bus_read_4((_sc)->mem_res, (_r))
+
+#define LOCK(_sc) mtx_lock(&(_sc)->mtx)
+#define UNLOCK(_sc) mtx_unlock(&(_sc)->mtx)
+#define SLEEP(_sc, timeout) \
+ mtx_sleep(sc, &sc->mtx, 0, "rtcwait", timeout);
+#define LOCK_INIT(_sc) \
+ mtx_init(&_sc->mtx, device_get_nameunit(_sc->dev), "tegra_rtc", MTX_DEF)
+#define LOCK_DESTROY(_sc) mtx_destroy(&_sc->mtx)
+#define ASSERT_LOCKED(_sc) mtx_assert(&_sc->mtx, MA_OWNED)
+#define ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->mtx, MA_NOTOWNED)
+
+static struct ofw_compat_data compat_data[] = {
+ {"nvidia,tegra124-rtc", 1},
+ {NULL, 0}
+};
+
+struct tegra_rtc_softc {
+ device_t dev;
+ struct mtx mtx;
+
+ struct resource *mem_res;
+ struct resource *irq_res;
+ void *irq_h;
+
+ clk_t clk;
+ uint32_t core_freq;
+};
+
+static void
+tegra_rtc_wait(struct tegra_rtc_softc *sc)
+{
+ int timeout;
+
+ for (timeout = 500; timeout >0; timeout--) {
+ if ((RD4(sc, RTC_BUSY) & RTC_BUSY_STATUS) == 0)
+ break;
+ DELAY(1);
+ }
+ if (timeout <= 0)
+ device_printf(sc->dev, "Device busy timeouted\n");
+
+}
+
+/*
+ * Get the time of day clock and return it in ts.
+ * Return 0 on success, an error number otherwise.
+ */
+static int
+tegra_rtc_gettime(device_t dev, struct timespec *ts)
+{
+ struct tegra_rtc_softc *sc;
+ struct timeval tv;
+ uint32_t msec, sec;
+
+ sc = device_get_softc(dev);
+
+ LOCK(sc);
+ msec = RD4(sc, RTC_MILLI_SECONDS);
+ sec = RD4(sc, RTC_SHADOW_SECONDS);
+ UNLOCK(sc);
+ tv.tv_sec = sec;
+ tv.tv_usec = msec * 1000;
+ TIMEVAL_TO_TIMESPEC(&tv, ts);
+ return (0);
+}
+
+
+static int
+tegra_rtc_settime(device_t dev, struct timespec *ts)
+{
+ struct tegra_rtc_softc *sc;
+ struct timeval tv;
+
+ sc = device_get_softc(dev);
+
+ LOCK(sc);
+ TIMESPEC_TO_TIMEVAL(&tv, ts);
+ tegra_rtc_wait(sc);
+ WR4(sc, RTC_SECONDS, tv.tv_sec);
+ UNLOCK(sc);
+
+ return (0);
+}
+
+
+static void
+tegra_rtc_intr(void *arg)
+{
+ struct tegra_rtc_softc *sc;
+ uint32_t status;
+
+ sc = (struct tegra_rtc_softc *)arg;
+ LOCK(sc);
+ status = RD4(sc, RTC_INTR_STATUS);
+ WR4(sc, RTC_INTR_STATUS, status);
+ UNLOCK(sc);
+}
+
+static int
+tegra_rtc_probe(device_t dev)
+{
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+tegra_rtc_attach(device_t dev)
+{
+ int rv, rid;
+ struct tegra_rtc_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ LOCK_INIT(sc);
+
+ /* Get the memory resource for the register mapping. */
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev, "Cannot map registers.\n");
+ rv = ENXIO;
+ goto fail;
+ }
+
+ /* Allocate our IRQ resource. */
+ rid = 0;
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (sc->irq_res == NULL) {
+ device_printf(dev, "Cannot allocate interrupt.\n");
+ rv = ENXIO;
+ goto fail;
+ }
+
+ /* OFW resources. */
+ rv = clk_get_by_ofw_index(dev, 0, &sc->clk);
+ if (rv != 0) {
+ device_printf(dev, "Cannot get i2c clock: %d\n", rv);
+ goto fail;
+ }
+ rv = clk_enable(sc->clk);
+ if (rv != 0) {
+ device_printf(dev, "Cannot enable clock: %d\n", rv);
+ goto fail;
+ }
+
+ /* Init hardware. */
+ WR4(sc, RTC_SECONDS_ALARM0, 0);
+ WR4(sc, RTC_SECONDS_ALARM1, 0);
+ WR4(sc, RTC_INTR_STATUS, 0xFFFFFFFF);
+ WR4(sc, RTC_INTR_MASK, 0);
+
+ /* Setup interrupt */
+ rv = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
+ NULL, tegra_rtc_intr, sc, &sc->irq_h);
+ if (rv) {
+ device_printf(dev, "Cannot setup interrupt.\n");
+ goto fail;
+ }
+
+ /*
+ * Register as a time of day clock with 1-second resolution.
+ *
+ * XXXX Not yet, we don't have support for multiple RTCs
+ */
+ /* clock_register(dev, 1000000); */
+
+ return (bus_generic_attach(dev));
+
+fail:
+ if (sc->clk != NULL)
+ clk_release(sc->clk);
+ if (sc->irq_h != NULL)
+ bus_teardown_intr(dev, sc->irq_res, sc->irq_h);
+ if (sc->irq_res != NULL)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
+ if (sc->mem_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
+ LOCK_DESTROY(sc);
+
+ return (rv);
+}
+
+static int
+tegra_rtc_detach(device_t dev)
+{
+ struct tegra_rtc_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (sc->irq_h != NULL)
+ bus_teardown_intr(dev, sc->irq_res, sc->irq_h);
+ if (sc->irq_res != NULL)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
+ if (sc->mem_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
+
+ LOCK_DESTROY(sc);
+ return (bus_generic_detach(dev));
+}
+
+static device_method_t tegra_rtc_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, tegra_rtc_probe),
+ DEVMETHOD(device_attach, tegra_rtc_attach),
+ DEVMETHOD(device_detach, tegra_rtc_detach),
+
+ /* clock interface */
+ DEVMETHOD(clock_gettime, tegra_rtc_gettime),
+ DEVMETHOD(clock_settime, tegra_rtc_settime),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(tegra_rtc, tegra_rtc_driver, tegra_rtc_methods,
+ sizeof(struct tegra_rtc_softc));
+static devclass_t tegra_rtc_devclass;
+DRIVER_MODULE(tegra_rtc, simplebus, tegra_rtc_driver, tegra_rtc_devclass, 0, 0);
diff --git a/sys/arm/nvidia/tegra_sdhci.c b/sys/arm/nvidia/tegra_sdhci.c
new file mode 100644
index 0000000..e2ec063
--- /dev/null
+++ b/sys/arm/nvidia/tegra_sdhci.c
@@ -0,0 +1,465 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * SDHCI driver glue for NVIDIA Tegra family
+ *
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/types.h>
+#include <sys/bus.h>
+#include <sys/callout.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+#include <sys/taskqueue.h>
+#include <sys/time.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+
+#include <dev/extres/clk/clk.h>
+#include <dev/extres/hwreset/hwreset.h>
+#include <dev/gpio/gpiobusvar.h>
+#include <dev/mmc/bridge.h>
+#include <dev/mmc/mmcreg.h>
+#include <dev/mmc/mmcbrvar.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/sdhci/sdhci.h>
+
+#include "sdhci_if.h"
+
+/* Tegra SDHOST controller vendor register definitions */
+#define SDMMC_VENDOR_CLOCK_CNTRL 0x100
+#define VENDOR_CLOCK_CNTRL_CLK_SHIFT 8
+#define VENDOR_CLOCK_CNTRL_CLK_MASK 0xFF
+#define SDMMC_VENDOR_SYS_SW_CNTRL 0x104
+#define SDMMC_VENDOR_CAP_OVERRIDES 0x10C
+#define SDMMC_VENDOR_BOOT_CNTRL 0x110
+#define SDMMC_VENDOR_BOOT_ACK_TIMEOUT 0x114
+#define SDMMC_VENDOR_BOOT_DAT_TIMEOUT 0x118
+#define SDMMC_VENDOR_DEBOUNCE_COUNT 0x11C
+#define SDMMC_VENDOR_MISC_CNTRL 0x120
+#define VENDOR_MISC_CTRL_ENABLE_SDR104 0x8
+#define VENDOR_MISC_CTRL_ENABLE_SDR50 0x10
+#define VENDOR_MISC_CTRL_ENABLE_SDHCI_SPEC_300 0x20
+#define VENDOR_MISC_CTRL_ENABLE_DDR50 0x200
+#define SDMMC_MAX_CURRENT_OVERRIDE 0x124
+#define SDMMC_MAX_CURRENT_OVERRIDE_HI 0x128
+#define SDMMC_VENDOR_CLK_GATE_HYSTERESIS_COUNT 0x1D0
+#define SDMMC_VENDOR_PHWRESET_VAL0 0x1D4
+#define SDMMC_VENDOR_PHWRESET_VAL1 0x1D8
+#define SDMMC_VENDOR_PHWRESET_VAL2 0x1DC
+#define SDMMC_SDMEMCOMPPADCTRL_0 0x1E0
+#define SDMMC_AUTO_CAL_CONFIG 0x1E4
+#define SDMMC_AUTO_CAL_INTERVAL 0x1E8
+#define SDMMC_AUTO_CAL_STATUS 0x1EC
+#define SDMMC_SDMMC_MCCIF_FIFOCTRL 0x1F4
+#define SDMMC_TIMEOUT_WCOAL_SDMMC 0x1F8
+
+/* Compatible devices. */
+static struct ofw_compat_data compat_data[] = {
+ {"nvidia,tegra124-sdhci", 1},
+ {NULL, 0},
+};
+
+struct tegra_sdhci_softc {
+ device_t dev;
+ struct resource * mem_res;
+ struct resource * irq_res;
+ void * intr_cookie;
+ u_int quirks; /* Chip specific quirks */
+ u_int caps; /* If we override SDHCI_CAPABILITIES */
+ uint32_t max_clk; /* Max possible freq */
+ clk_t clk;
+ hwreset_t reset;
+ gpio_pin_t gpio_cd;
+ gpio_pin_t gpio_wp;
+ gpio_pin_t gpio_power;
+
+ int force_card_present;
+ struct sdhci_slot slot;
+
+};
+
+static inline uint32_t
+RD4(struct tegra_sdhci_softc *sc, bus_size_t off)
+{
+
+ return (bus_read_4(sc->mem_res, off));
+}
+
+static uint8_t
+tegra_sdhci_read_1(device_t dev, struct sdhci_slot *slot, bus_size_t off)
+{
+ struct tegra_sdhci_softc *sc;
+
+ sc = device_get_softc(dev);
+ return (bus_read_1(sc->mem_res, off));
+}
+
+static uint16_t
+tegra_sdhci_read_2(device_t dev, struct sdhci_slot *slot, bus_size_t off)
+{
+ struct tegra_sdhci_softc *sc;
+
+ sc = device_get_softc(dev);
+ return (bus_read_2(sc->mem_res, off));
+}
+
+static uint32_t
+tegra_sdhci_read_4(device_t dev, struct sdhci_slot *slot, bus_size_t off)
+{
+ struct tegra_sdhci_softc *sc;
+ uint32_t val32;
+
+ sc = device_get_softc(dev);
+ val32 = bus_read_4(sc->mem_res, off);
+ /* Force the card-present state if necessary. */
+ if (off == SDHCI_PRESENT_STATE && sc->force_card_present)
+ val32 |= SDHCI_CARD_PRESENT;
+ return (val32);
+}
+
+static void
+tegra_sdhci_read_multi_4(device_t dev, struct sdhci_slot *slot, bus_size_t off,
+ uint32_t *data, bus_size_t count)
+{
+ struct tegra_sdhci_softc *sc;
+
+ sc = device_get_softc(dev);
+ bus_read_multi_4(sc->mem_res, off, data, count);
+}
+
+static void
+tegra_sdhci_write_1(device_t dev, struct sdhci_slot *slot, bus_size_t off,
+ uint8_t val)
+{
+ struct tegra_sdhci_softc *sc;
+
+ sc = device_get_softc(dev);
+ bus_write_1(sc->mem_res, off, val);
+}
+
+static void
+tegra_sdhci_write_2(device_t dev, struct sdhci_slot *slot, bus_size_t off,
+ uint16_t val)
+{
+ struct tegra_sdhci_softc *sc;
+
+ sc = device_get_softc(dev);
+ bus_write_2(sc->mem_res, off, val);
+}
+
+static void
+tegra_sdhci_write_4(device_t dev, struct sdhci_slot *slot, bus_size_t off,
+ uint32_t val)
+{
+ struct tegra_sdhci_softc *sc;
+
+ sc = device_get_softc(dev);
+ bus_write_4(sc->mem_res, off, val);
+}
+
+static void
+tegra_sdhci_write_multi_4(device_t dev, struct sdhci_slot *slot, bus_size_t off,
+ uint32_t *data, bus_size_t count)
+{
+ struct tegra_sdhci_softc *sc;
+
+ sc = device_get_softc(dev);
+ bus_write_multi_4(sc->mem_res, off, data, count);
+}
+
+static void
+tegra_sdhci_intr(void *arg)
+{
+ struct tegra_sdhci_softc *sc = arg;
+
+ sdhci_generic_intr(&sc->slot);
+ RD4(sc, SDHCI_INT_STATUS);
+}
+
+static int
+tegra_generic_get_ro(device_t brdev, device_t reqdev)
+{
+
+ return (0);
+}
+
+static int
+tegra_sdhci_probe(device_t dev)
+{
+ struct tegra_sdhci_softc *sc;
+ phandle_t node;
+ pcell_t cid;
+ const struct ofw_compat_data *cd;
+
+ sc = device_get_softc(dev);
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_is_compatible(dev, "nvidia,tegra124-sdhci")) {
+ device_set_desc(dev, "Tegra SDHCI controller");
+ } else
+ return (ENXIO);
+ cd = ofw_bus_search_compatible(dev, compat_data);
+ if (cd->ocd_data == 0)
+ return (ENXIO);
+
+ node = ofw_bus_get_node(dev);
+
+ /* Allow dts to patch quirks, slots, and max-frequency. */
+ if ((OF_getencprop(node, "quirks", &cid, sizeof(cid))) > 0)
+ sc->quirks = cid;
+ if ((OF_getencprop(node, "max-frequency", &cid, sizeof(cid))) > 0)
+ sc->max_clk = cid;
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+tegra_sdhci_attach(device_t dev)
+{
+ struct tegra_sdhci_softc *sc;
+ int rid, rv;
+ uint64_t freq;
+ phandle_t node, prop;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ node = ofw_bus_get_node(dev);
+
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (!sc->mem_res) {
+ device_printf(dev, "cannot allocate memory window\n");
+ rv = ENXIO;
+ goto fail;
+ }
+
+ rid = 0;
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (!sc->irq_res) {
+ device_printf(dev, "cannot allocate interrupt\n");
+ rv = ENXIO;
+ goto fail;
+ }
+
+ if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
+ NULL, tegra_sdhci_intr, sc, &sc->intr_cookie)) {
+ device_printf(dev, "cannot setup interrupt handler\n");
+ rv = ENXIO;
+ goto fail;
+ }
+
+ rv = hwreset_get_by_ofw_name(sc->dev, "sdhci", &sc->reset);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'sdhci' reset\n");
+ goto fail;
+ }
+ rv = hwreset_deassert(sc->reset);
+ if (rv != 0) {
+ device_printf(dev, "Cannot unreset 'sdhci' reset\n");
+ goto fail;
+ }
+
+ gpio_pin_get_by_ofw_property(sc->dev, "cd-gpios", &sc->gpio_cd);
+ gpio_pin_get_by_ofw_property(sc->dev, "power-gpios", &sc->gpio_power);
+ gpio_pin_get_by_ofw_property(sc->dev, "wp-gpios", &sc->gpio_wp);
+
+ rv = clk_get_by_ofw_index(dev, 0, &sc->clk);
+ if (rv != 0) {
+
+ device_printf(dev, "Cannot get clock\n");
+ goto fail;
+ }
+
+ rv = clk_get_by_ofw_index(dev, 0, &sc->clk);
+ if (rv != 0) {
+ device_printf(dev, "Cannot get clock\n");
+ goto fail;
+ }
+ rv = clk_enable(sc->clk);
+ if (rv != 0) {
+ device_printf(dev, "Cannot enable clock\n");
+ goto fail;
+ }
+ rv = clk_set_freq(sc->clk, 48000000, CLK_SET_ROUND_DOWN);
+ if (rv != 0) {
+ device_printf(dev, "Cannot set clock\n");
+ }
+ rv = clk_get_freq(sc->clk, &freq);
+ if (rv != 0) {
+ device_printf(dev, "Cannot get clock frequency\n");
+ goto fail;
+ }
+ if (bootverbose)
+ device_printf(dev, " Base MMC clock: %lld\n", freq);
+
+ /* Fill slot information. */
+ sc->max_clk = (int)freq;
+ sc->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
+ SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
+ SDHCI_QUIRK_MISSING_CAPS;
+
+ /* Limit real slot capabilities. */
+ sc->caps = RD4(sc, SDHCI_CAPABILITIES);
+ if (OF_getencprop(node, "bus-width", &prop, sizeof(prop)) > 0) {
+ sc->caps &= ~(MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA);
+ switch (prop) {
+ case 8:
+ sc->caps |= MMC_CAP_8_BIT_DATA;
+ /* FALLTHROUGH */
+ case 4:
+ sc->caps |= MMC_CAP_4_BIT_DATA;
+ break;
+ case 1:
+ break;
+ default:
+ device_printf(dev, "Bad bus-width value %u\n", prop);
+ break;
+ }
+ }
+ if (OF_hasprop(node, "non-removable"))
+ sc->force_card_present = 1;
+ /*
+ * Clear clock field, so SDHCI driver uses supplied frequency.
+ * in sc->slot.max_clk
+ */
+ sc->caps &= ~SDHCI_CLOCK_V3_BASE_MASK;
+
+ sc->slot.quirks = sc->quirks;
+ sc->slot.max_clk = sc->max_clk;
+ sc->slot.caps = sc->caps;
+
+ rv = sdhci_init_slot(dev, &sc->slot, 0);
+ if (rv != 0) {
+ goto fail;
+ }
+
+ bus_generic_probe(dev);
+ bus_generic_attach(dev);
+
+ sdhci_start_slot(&sc->slot);
+
+ return (0);
+
+fail:
+ if (sc->gpio_cd != NULL)
+ gpio_pin_release(sc->gpio_cd);
+ if (sc->gpio_wp != NULL)
+ gpio_pin_release(sc->gpio_wp);
+ if (sc->gpio_power != NULL)
+ gpio_pin_release(sc->gpio_power);
+ if (sc->clk != NULL)
+ clk_release(sc->clk);
+ if (sc->reset != NULL)
+ hwreset_release(sc->reset);
+ if (sc->intr_cookie != NULL)
+ bus_teardown_intr(dev, sc->irq_res, sc->intr_cookie);
+ if (sc->irq_res != NULL)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
+ if (sc->mem_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
+
+ return (rv);
+}
+
+static int
+tegra_sdhci_detach(device_t dev)
+{
+ struct tegra_sdhci_softc *sc = device_get_softc(dev);
+ struct sdhci_slot *slot = &sc->slot;
+
+ bus_generic_detach(dev);
+ clk_release(sc->clk);
+ bus_teardown_intr(dev, sc->irq_res, sc->intr_cookie);
+ bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(sc->irq_res),
+ sc->irq_res);
+
+ sdhci_cleanup_slot(slot);
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ rman_get_rid(sc->mem_res),
+ sc->mem_res);
+ return (0);
+}
+
+static device_method_t tegra_sdhci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, tegra_sdhci_probe),
+ DEVMETHOD(device_attach, tegra_sdhci_attach),
+ DEVMETHOD(device_detach, tegra_sdhci_detach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_read_ivar, sdhci_generic_read_ivar),
+ DEVMETHOD(bus_write_ivar, sdhci_generic_write_ivar),
+
+ /* MMC bridge interface */
+ DEVMETHOD(mmcbr_update_ios, sdhci_generic_update_ios),
+ DEVMETHOD(mmcbr_request, sdhci_generic_request),
+ DEVMETHOD(mmcbr_get_ro, tegra_generic_get_ro),
+ DEVMETHOD(mmcbr_acquire_host, sdhci_generic_acquire_host),
+ DEVMETHOD(mmcbr_release_host, sdhci_generic_release_host),
+
+ /* SDHCI registers accessors */
+ DEVMETHOD(sdhci_read_1, tegra_sdhci_read_1),
+ DEVMETHOD(sdhci_read_2, tegra_sdhci_read_2),
+ DEVMETHOD(sdhci_read_4, tegra_sdhci_read_4),
+ DEVMETHOD(sdhci_read_multi_4, tegra_sdhci_read_multi_4),
+ DEVMETHOD(sdhci_write_1, tegra_sdhci_write_1),
+ DEVMETHOD(sdhci_write_2, tegra_sdhci_write_2),
+ DEVMETHOD(sdhci_write_4, tegra_sdhci_write_4),
+ DEVMETHOD(sdhci_write_multi_4, tegra_sdhci_write_multi_4),
+
+ { 0, 0 }
+};
+
+static devclass_t tegra_sdhci_devclass;
+
+static driver_t tegra_sdhci_driver = {
+ "sdhci_tegra",
+ tegra_sdhci_methods,
+ sizeof(struct tegra_sdhci_softc),
+};
+
+DRIVER_MODULE(sdhci_tegra, simplebus, tegra_sdhci_driver, tegra_sdhci_devclass,
+ 0, 0);
+MODULE_DEPEND(sdhci_tegra, sdhci, 1, 1, 1);
+DRIVER_MODULE(mmc, sdhci_tegra, mmc_driver, mmc_devclass, NULL, NULL);
diff --git a/sys/arm/nvidia/tegra_soctherm.c b/sys/arm/nvidia/tegra_soctherm.c
new file mode 100644
index 0000000..3102173
--- /dev/null
+++ b/sys/arm/nvidia/tegra_soctherm.c
@@ -0,0 +1,696 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Thermometer and thermal zones driver for Tegra SoCs.
+ * Calibration data and algo are taken from Linux, because this part of SoC
+ * is undocumented in TRM.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/gpio.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+
+#include <machine/bus.h>
+
+#include <dev/extres/clk/clk.h>
+#include <dev/extres/hwreset/hwreset.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <arm/nvidia/tegra_efuse.h>
+#include <gnu/dts/include/dt-bindings/thermal/tegra124-soctherm.h>
+#include "tegra_soctherm_if.h"
+
+/* Per sensors registers - base is 0x0c0*/
+#define TSENSOR_CONFIG0 0x000
+#define TSENSOR_CONFIG0_TALL(x) (((x) & 0xFFFFF) << 8)
+#define TSENSOR_CONFIG0_STATUS_CLR (1 << 5)
+#define TSENSOR_CONFIG0_TCALC_OVERFLOW (1 << 4)
+#define TSENSOR_CONFIG0_OVERFLOW (1 << 3)
+#define TSENSOR_CONFIG0_CPTR_OVERFLOW (1 << 2)
+#define TSENSOR_CONFIG0_RO_SEL (1 << 1)
+#define TSENSOR_CONFIG0_STOP (1 << 0)
+
+#define TSENSOR_CONFIG1 0x004
+#define TSENSOR_CONFIG1_TEMP_ENABLE (1U << 31)
+#define TSENSOR_CONFIG1_TEN_COUNT(x) (((x) & 0x3F) << 24)
+#define TSENSOR_CONFIG1_TIDDQ_EN(x) (((x) & 0x3F) << 15)
+#define TSENSOR_CONFIG1_TSAMPLE(x) (((x) & 0x3FF) << 0)
+
+#define TSENSOR_CONFIG2 0x008
+#define TSENSOR_CONFIG2_THERMA(x) (((x) & 0xFFFF) << 16)
+#define TSENSOR_CONFIG2_THERMB(x) (((x) & 0xFFFF) << 0)
+
+#define TSENSOR_STATUS0 0x00c
+#define TSENSOR_STATUS0_CAPTURE_VALID (1U << 31)
+#define TSENSOR_STATUS0_CAPTURE(x) (((x) >> 0) & 0xffff)
+
+#define TSENSOR_STATUS1 0x010
+#define TSENSOR_STATUS1_TEMP_VALID (1U << 31)
+#define TSENSOR_STATUS1_TEMP(x) (((x) >> 0) & 0xffff)
+
+#define TSENSOR_STATUS2 0x014
+#define TSENSOR_STATUS2_TEMP_MAX(x) (((x) >> 16) & 0xffff)
+#define TSENSOR_STATUS2_TEMP_MIN(x) (((x) >> 0) & 0xffff)
+
+/* Global registers */
+#define TSENSOR_PDIV 0x1c0
+#define TSENSOR_PDIV_T124 0x8888
+#define TSENSOR_HOTSPOT_OFF 0x1c4
+#define TSENSOR_HOTSPOT_OFF_T124 0x00060600
+#define TSENSOR_TEMP1 0x1c8
+#define TSENSOR_TEMP2 0x1cc
+
+/* Readbacks */
+#define READBACK_VALUE_MASK 0xff00
+#define READBACK_VALUE_SHIFT 8
+#define READBACK_ADD_HALF (1 << 7)
+#define READBACK_NEGATE (1 << 0)
+
+
+/* Fuses */
+#define FUSE_TSENSOR_CALIB_CP_TS_BASE_SHIFT 0
+#define FUSE_TSENSOR_CALIB_CP_TS_BASE_BITS 13
+#define FUSE_TSENSOR_CALIB_FT_TS_BASE_SHIFT 13
+#define FUSE_TSENSOR_CALIB_FT_TS_BASE_BITS 13
+
+#define FUSE_TSENSOR8_CALIB 0x180
+#define FUSE_TSENSOR8_CALIB_CP_TS_BASE(x) (((x) >> 0) & 0x3ff)
+#define FUSE_TSENSOR8_CALIB_FT_TS_BASE(x) (((x) >> 10) & 0x7ff)
+
+#define FUSE_SPARE_REALIGNMENT_REG 0x1fc
+#define FUSE_SPARE_REALIGNMENT_REG_SHIFT_CP_SHIFT 0
+#define FUSE_SPARE_REALIGNMENT_REG_SHIFT_CP_BITS 6
+#define FUSE_SPARE_REALIGNMENT_REG_SHIFT_FT_SHIFT 21
+#define FUSE_SPARE_REALIGNMENT_REG_SHIFT_FT_BITS 5
+#define FUSE_SPARE_REALIGNMENT_REG_SHIFT_CP(x) (((x) >> 0) & 0x3f)
+#define FUSE_SPARE_REALIGNMENT_REG_SHIFT_FT(x) (((x) >> 21) & 0x1f)
+
+
+#define NOMINAL_CALIB_FT_T124 105
+#define NOMINAL_CALIB_CP_T124 25
+
+#define WR4(_sc, _r, _v) bus_write_4((_sc)->mem_res, (_r), (_v))
+#define RD4(_sc, _r) bus_read_4((_sc)->mem_res, (_r))
+
+static struct sysctl_ctx_list soctherm_sysctl_ctx;
+
+struct soctherm_shared_cal {
+ uint32_t base_cp;
+ uint32_t base_ft;
+ int32_t actual_temp_cp;
+ int32_t actual_temp_ft;
+};
+struct tsensor_cfg {
+ uint32_t tall;
+ uint32_t tsample;
+ uint32_t tiddq_en;
+ uint32_t ten_count;
+ uint32_t pdiv;
+ uint32_t tsample_ate;
+ uint32_t pdiv_ate;
+};
+
+struct tsensor {
+ char *name;
+ int id;
+ struct tsensor_cfg *cfg;
+ bus_addr_t sensor_base;
+ bus_addr_t calib_fuse;
+ int fuse_corr_alpha;
+ int fuse_corr_beta;
+
+ int16_t therm_a;
+ int16_t therm_b;
+};
+
+struct soctherm_softc {
+ device_t dev;
+ struct resource *mem_res;
+ struct resource *irq_res;
+ void *irq_ih;
+
+ clk_t tsensor_clk;
+ clk_t soctherm_clk;
+ hwreset_t reset;
+
+ int ntsensors;
+ struct tsensor *tsensors;
+};
+
+static struct ofw_compat_data compat_data[] = {
+ {"nvidia,tegra124-soctherm", 1},
+ {NULL, 0},
+};
+
+static struct tsensor_cfg t124_tsensor_config = {
+ .tall = 16300,
+ .tsample = 120,
+ .tiddq_en = 1,
+ .ten_count = 1,
+ .pdiv = 8,
+ .tsample_ate = 480,
+ .pdiv_ate = 8
+};
+
+
+static struct tsensor t124_tsensors[] = {
+ {
+ .name = "cpu0",
+ .id = TEGRA124_SOCTHERM_SENSOR_CPU,
+ .cfg = &t124_tsensor_config,
+ .sensor_base = 0x0c0,
+ .calib_fuse = 0x098,
+ .fuse_corr_alpha = 1135400,
+ .fuse_corr_beta = -6266900,
+ },
+ {
+ .name = "cpu1",
+ .id = -1,
+ .cfg = &t124_tsensor_config,
+ .sensor_base = 0x0e0,
+ .calib_fuse = 0x084,
+ .fuse_corr_alpha = 1122220,
+ .fuse_corr_beta = -5700700,
+ },
+ {
+ .name = "cpu2",
+ .id = -1,
+ .cfg = &t124_tsensor_config,
+ .sensor_base = 0x100,
+ .calib_fuse = 0x088,
+ .fuse_corr_alpha = 1127000,
+ .fuse_corr_beta = -6768200,
+ },
+ {
+ .name = "cpu3",
+ .id = -1,
+ .cfg = &t124_tsensor_config,
+ .sensor_base = 0x120,
+ .calib_fuse = 0x12c,
+ .fuse_corr_alpha = 1110900,
+ .fuse_corr_beta = -6232000,
+ },
+ {
+ .name = "mem0",
+ .id = TEGRA124_SOCTHERM_SENSOR_MEM,
+ .cfg = &t124_tsensor_config,
+ .sensor_base = 0x140,
+ .calib_fuse = 0x158,
+ .fuse_corr_alpha = 1122300,
+ .fuse_corr_beta = -5936400,
+ },
+ {
+ .name = "mem1",
+ .id = -1,
+ .cfg = &t124_tsensor_config,
+ .sensor_base = 0x160,
+ .calib_fuse = 0x15c,
+ .fuse_corr_alpha = 1145700,
+ .fuse_corr_beta = -7124600,
+ },
+ {
+ .name = "gpu",
+ .id = TEGRA124_SOCTHERM_SENSOR_GPU,
+ .cfg = &t124_tsensor_config,
+ .sensor_base = 0x180,
+ .calib_fuse = 0x154,
+ .fuse_corr_alpha = 1120100,
+ .fuse_corr_beta = -6000500,
+ },
+ {
+ .name = "pllX",
+ .id = TEGRA124_SOCTHERM_SENSOR_PLLX,
+ .cfg = &t124_tsensor_config,
+ .sensor_base = 0x1a0,
+ .calib_fuse = 0x160,
+ .fuse_corr_alpha = 1106500,
+ .fuse_corr_beta = -6729300,
+ },
+};
+
+/* Extract signed integer bitfield from register */
+static int
+extract_signed(uint32_t reg, int shift, int bits)
+{
+ int32_t val;
+ uint32_t mask;
+
+ mask = (1 << bits) - 1;
+ val = ((reg >> shift) & mask) << (32 - bits);
+ val >>= 32 - bits;
+ return ((int32_t)val);
+}
+
+static inline int64_t div64_s64_precise(int64_t a, int64_t b)
+{
+ int64_t r, al;
+
+ al = a << 16;
+ r = (al * 2 + 1) / (2 * b);
+ return r >> 16;
+}
+
+static void
+get_shared_cal(struct soctherm_softc *sc, struct soctherm_shared_cal *cal)
+{
+ uint32_t val;
+ int calib_cp, calib_ft;
+
+ val = tegra_fuse_read_4(FUSE_TSENSOR8_CALIB);
+ cal->base_cp = FUSE_TSENSOR8_CALIB_CP_TS_BASE(val);
+ cal->base_ft = FUSE_TSENSOR8_CALIB_FT_TS_BASE(val);
+
+ val = tegra_fuse_read_4(FUSE_SPARE_REALIGNMENT_REG);
+ calib_ft = extract_signed(val,
+ FUSE_SPARE_REALIGNMENT_REG_SHIFT_FT_SHIFT,
+ FUSE_SPARE_REALIGNMENT_REG_SHIFT_FT_BITS);
+ calib_cp = extract_signed(val,
+ FUSE_SPARE_REALIGNMENT_REG_SHIFT_CP_SHIFT,
+ FUSE_SPARE_REALIGNMENT_REG_SHIFT_CP_BITS);
+
+ cal->actual_temp_cp = 2 * NOMINAL_CALIB_CP_T124 + calib_cp;
+ cal->actual_temp_ft = 2 * NOMINAL_CALIB_FT_T124 + calib_ft;
+#ifdef DEBUG
+ printf("%s: base_cp: %u, base_ft: %d,"
+ " actual_temp_cp: %d, actual_temp_ft: %d\n",
+ __func__, cal->base_cp, cal->base_ft,
+ cal->actual_temp_cp, cal->actual_temp_ft);
+#endif
+}
+
+
+static void
+tsensor_calibration(struct tsensor *sensor, struct soctherm_shared_cal *shared)
+{
+ uint32_t val;
+ int mult, div, calib_cp, calib_ft;
+ int actual_tsensor_ft, actual_tsensor_cp, delta_sens, delta_temp;
+ int temp_a, temp_b;
+ int64_t tmp;
+
+ val = tegra_fuse_read_4(sensor->calib_fuse);
+ calib_cp = extract_signed(val,
+ FUSE_TSENSOR_CALIB_CP_TS_BASE_SHIFT,
+ FUSE_TSENSOR_CALIB_CP_TS_BASE_BITS);
+ actual_tsensor_cp = shared->base_cp * 64 + calib_cp;
+
+ calib_ft = extract_signed(val,
+ FUSE_TSENSOR_CALIB_FT_TS_BASE_SHIFT,
+ FUSE_TSENSOR_CALIB_FT_TS_BASE_BITS);
+ actual_tsensor_ft = shared->base_ft * 32 + calib_ft;
+
+ delta_sens = actual_tsensor_ft - actual_tsensor_cp;
+ delta_temp = shared->actual_temp_ft - shared->actual_temp_cp;
+ mult = sensor->cfg->pdiv * sensor->cfg->tsample_ate;
+ div = sensor->cfg->tsample * sensor->cfg->pdiv_ate;
+
+
+ temp_a = div64_s64_precise((int64_t) delta_temp * (1LL << 13) * mult,
+ (int64_t) delta_sens * div);
+
+ tmp = (int64_t)actual_tsensor_ft * shared->actual_temp_cp -
+ (int64_t)actual_tsensor_cp * shared->actual_temp_ft;
+ temp_b = div64_s64_precise(tmp, (int64_t)delta_sens);
+
+ temp_a = div64_s64_precise((int64_t)temp_a * sensor->fuse_corr_alpha,
+ 1000000);
+ temp_b = div64_s64_precise((int64_t)temp_b * sensor->fuse_corr_alpha +
+ sensor->fuse_corr_beta, 1000000);
+ sensor->therm_a = (int16_t)temp_a;
+ sensor->therm_b = (int16_t)temp_b;
+#ifdef DEBUG
+ printf("%s: sensor %s fuse: 0x%08X (0x%04X, 0x%04X)"
+ " calib_cp: %d(0x%04X), calib_ft: %d(0x%04X)\n",
+ __func__, sensor->name, val, val & 0x1FFF, (val >> 13) & 0x1FFF,
+ calib_cp, calib_cp, calib_ft, calib_ft);
+ printf("therma: 0x%04X(%d), thermb: 0x%04X(%d)\n",
+ (uint16_t)sensor->therm_a, temp_a,
+ (uint16_t)sensor->therm_b, sensor->therm_b);
+#endif
+}
+
+static void
+soctherm_init_tsensor(struct soctherm_softc *sc, struct tsensor *sensor,
+ struct soctherm_shared_cal *shared_cal)
+{
+ uint32_t val;
+
+ tsensor_calibration(sensor, shared_cal);
+
+ val = RD4(sc, sensor->sensor_base + TSENSOR_CONFIG0);
+ val |= TSENSOR_CONFIG0_STOP;
+ val |= TSENSOR_CONFIG0_STATUS_CLR;
+ WR4(sc, sensor->sensor_base + TSENSOR_CONFIG0, val);
+
+ val = TSENSOR_CONFIG0_TALL(sensor->cfg->tall);
+ val |= TSENSOR_CONFIG0_STOP;
+ WR4(sc, sensor->sensor_base + TSENSOR_CONFIG0, val);
+
+ val = TSENSOR_CONFIG1_TSAMPLE(sensor->cfg->tsample - 1);
+ val |= TSENSOR_CONFIG1_TIDDQ_EN(sensor->cfg->tiddq_en);
+ val |= TSENSOR_CONFIG1_TEN_COUNT(sensor->cfg->ten_count);
+ val |= TSENSOR_CONFIG1_TEMP_ENABLE;
+ WR4(sc, sensor->sensor_base + TSENSOR_CONFIG1, val);
+
+ val = TSENSOR_CONFIG2_THERMA((uint16_t)sensor->therm_a) |
+ TSENSOR_CONFIG2_THERMB((uint16_t)sensor->therm_b);
+ WR4(sc, sensor->sensor_base + TSENSOR_CONFIG2, val);
+
+ val = RD4(sc, sensor->sensor_base + TSENSOR_CONFIG0);
+ val &= ~TSENSOR_CONFIG0_STOP;
+ WR4(sc, sensor->sensor_base + TSENSOR_CONFIG0, val);
+#ifdef DEBUG
+ printf(" Sensor: %s cfg:0x%08X, 0x%08X, 0x%08X,"
+ " sts:0x%08X, 0x%08X, 0x%08X\n", sensor->name,
+ RD4(sc, sensor->sensor_base + TSENSOR_CONFIG0),
+ RD4(sc, sensor->sensor_base + TSENSOR_CONFIG1),
+ RD4(sc, sensor->sensor_base + TSENSOR_CONFIG2),
+ RD4(sc, sensor->sensor_base + TSENSOR_STATUS0),
+ RD4(sc, sensor->sensor_base + TSENSOR_STATUS1),
+ RD4(sc, sensor->sensor_base + TSENSOR_STATUS2)
+ );
+#endif
+}
+
+static int
+soctherm_convert_raw(uint32_t val)
+{
+ int32_t t;
+
+ t = ((val & READBACK_VALUE_MASK) >> READBACK_VALUE_SHIFT) * 1000;
+ if (val & READBACK_ADD_HALF)
+ t += 500;
+ if (val & READBACK_NEGATE)
+ t *= -1;
+
+ return t;
+}
+
+static int
+soctherm_read_temp(struct soctherm_softc *sc, struct tsensor *sensor, int *temp)
+{
+ int timeout;
+ uint32_t val;
+
+
+ /* wait for valid sample */
+ for (timeout = 1000; timeout > 0; timeout--) {
+ val = RD4(sc, sensor->sensor_base + TSENSOR_STATUS1);
+ if ((val & TSENSOR_STATUS1_TEMP_VALID) != 0)
+ break;
+ DELAY(100);
+ }
+ if (timeout <= 0)
+ device_printf(sc->dev, "Sensor %s timeouted\n", sensor->name);
+ *temp = soctherm_convert_raw(val);
+#ifdef DEBUG
+ printf("%s: Raw: 0x%08X, temp: %d\n", __func__, val, *temp);
+ printf(" Sensor: %s cfg:0x%08X, 0x%08X, 0x%08X,"
+ " sts:0x%08X, 0x%08X, 0x%08X\n", sensor->name,
+ RD4(sc, sensor->sensor_base + TSENSOR_CONFIG0),
+ RD4(sc, sensor->sensor_base + TSENSOR_CONFIG1),
+ RD4(sc, sensor->sensor_base + TSENSOR_CONFIG2),
+ RD4(sc, sensor->sensor_base + TSENSOR_STATUS0),
+ RD4(sc, sensor->sensor_base + TSENSOR_STATUS1),
+ RD4(sc, sensor->sensor_base + TSENSOR_STATUS2)
+ );
+#endif
+ return 0;
+}
+
+static int
+soctherm_get_temp(device_t dev, device_t cdev, uintptr_t id, int *val)
+{
+ struct soctherm_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+ /* The direct sensor map starts at 0x100 */
+ if (id >= 0x100) {
+ id -= 0x100;
+ if (id >= sc->ntsensors)
+ return (ERANGE);
+ return(soctherm_read_temp(sc, sc->tsensors + id, val));
+ }
+ /* Linux (DT) compatible thermal zones */
+ for (i = 0; i < sc->ntsensors; i++) {
+ if (sc->tsensors->id == id)
+ return(soctherm_read_temp(sc, sc->tsensors + id, val));
+ }
+ return (ERANGE);
+}
+
+static int
+soctherm_sysctl_temperature(SYSCTL_HANDLER_ARGS)
+{
+ struct soctherm_softc *sc;
+ int val;
+ int rv;
+ int id;
+
+ /* Write request */
+ if (req->newptr != NULL)
+ return (EINVAL);
+
+ sc = arg1;
+ id = arg2;
+
+ if (id >= sc->ntsensors)
+ return (ERANGE);
+ rv = soctherm_read_temp(sc, sc->tsensors + id, &val);
+ if (rv != 0)
+ return (rv);
+
+ val = val / 100;
+ val += 2731;
+ rv = sysctl_handle_int(oidp, &val, 0, req);
+ return (rv);
+}
+
+static int
+soctherm_init_sysctl(struct soctherm_softc *sc)
+{
+ int i;
+ struct sysctl_oid *oid, *tmp;
+
+ sysctl_ctx_init(&soctherm_sysctl_ctx);
+ /* create node for hw.temp */
+ oid = SYSCTL_ADD_NODE(&soctherm_sysctl_ctx,
+ SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, "temperature",
+ CTLFLAG_RD, NULL, "");
+ if (oid == NULL)
+ return (ENXIO);
+
+ /* Add sensors */
+ for (i = sc->ntsensors - 1; i >= 0; i--) {
+ tmp = SYSCTL_ADD_PROC(&soctherm_sysctl_ctx,
+ SYSCTL_CHILDREN(oid), OID_AUTO, sc->tsensors[i].name,
+ CTLTYPE_INT | CTLFLAG_RD, sc, i,
+ soctherm_sysctl_temperature, "IK", "SoC Temperature");
+ if (tmp == NULL)
+ return (ENXIO);
+ }
+
+ return (0);
+}
+
+static int
+soctherm_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "Tegra temperature sensors");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+soctherm_attach(device_t dev)
+{
+ struct soctherm_softc *sc;
+ phandle_t node;
+ int i, rid, rv;
+ struct soctherm_shared_cal shared_calib;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ node = ofw_bus_get_node(sc->dev);
+
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev, "Cannot allocate memory resources\n");
+ goto fail;
+ }
+
+ rid = 0;
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
+ if (sc->irq_res == NULL) {
+ device_printf(dev, "Cannot allocate IRQ resources\n");
+ goto fail;
+ }
+
+/*
+ if ((bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC,
+ soctherm_intr, NULL, sc, &sc->irq_ih))) {
+ device_printf(dev,
+ "WARNING: unable to register interrupt handler\n");
+ goto fail;
+ }
+*/
+
+ /* OWF resources */
+ rv = hwreset_get_by_ofw_name(dev, "soctherm", &sc->reset);
+ if (rv != 0) {
+ device_printf(dev, "Cannot get fuse reset\n");
+ goto fail;
+ }
+ rv = clk_get_by_ofw_name(dev, "tsensor", &sc->tsensor_clk);
+ if (rv != 0) {
+ device_printf(dev, "Cannot get 'tsensor' clock: %d\n", rv);
+ goto fail;
+ }
+ rv = clk_get_by_ofw_name(dev, "soctherm", &sc->soctherm_clk);
+ if (rv != 0) {
+ device_printf(dev, "Cannot get 'soctherm' clock: %d\n", rv);
+ goto fail;
+ }
+
+ rv = hwreset_assert(sc->reset);
+ if (rv != 0) {
+ device_printf(dev, "Cannot assert reset\n");
+ goto fail;
+ }
+ rv = clk_enable(sc->tsensor_clk);
+ if (rv != 0) {
+ device_printf(dev, "Cannot enable 'tsensor' clock: %d\n", rv);
+ goto fail;
+ }
+ rv = clk_enable(sc->soctherm_clk);
+ if (rv != 0) {
+ device_printf(dev, "Cannot enable 'soctherm' clock: %d\n", rv);
+ goto fail;
+ }
+ rv = hwreset_deassert(sc->reset);
+ if (rv != 0) {
+ device_printf(dev, "Cannot clear reset\n");
+ goto fail;
+ }
+
+ /* Tegra 124 */
+ sc->tsensors = t124_tsensors;
+ sc->ntsensors = nitems(t124_tsensors);
+ get_shared_cal(sc, &shared_calib);
+
+ WR4(sc, TSENSOR_PDIV, TSENSOR_PDIV_T124);
+ WR4(sc, TSENSOR_HOTSPOT_OFF, TSENSOR_HOTSPOT_OFF_T124);
+
+ for (i = 0; i < sc->ntsensors; i++)
+ soctherm_init_tsensor(sc, sc->tsensors + i, &shared_calib);
+
+ rv = soctherm_init_sysctl(sc);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot initialize sysctls\n");
+ goto fail;
+ }
+
+ OF_device_register_xref(OF_xref_from_node(node), dev);
+ return (bus_generic_attach(dev));
+
+fail:
+ if (sc->irq_ih != NULL)
+ bus_teardown_intr(dev, sc->irq_res, sc->irq_ih);
+ sysctl_ctx_free(&soctherm_sysctl_ctx);
+ if (sc->tsensor_clk != NULL)
+ clk_release(sc->tsensor_clk);
+ if (sc->soctherm_clk != NULL)
+ clk_release(sc->soctherm_clk);
+ if (sc->reset != NULL)
+ hwreset_release(sc->reset);
+ if (sc->irq_res != NULL)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
+ if (sc->mem_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
+
+ return (ENXIO);
+}
+
+static int
+soctherm_detach(device_t dev)
+{
+ struct soctherm_softc *sc;
+ sc = device_get_softc(dev);
+
+ if (sc->irq_ih != NULL)
+ bus_teardown_intr(dev, sc->irq_res, sc->irq_ih);
+ sysctl_ctx_free(&soctherm_sysctl_ctx);
+ if (sc->tsensor_clk != NULL)
+ clk_release(sc->tsensor_clk);
+ if (sc->soctherm_clk != NULL)
+ clk_release(sc->soctherm_clk);
+ if (sc->reset != NULL)
+ hwreset_release(sc->reset);
+ if (sc->irq_res != NULL)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
+ if (sc->mem_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
+
+ return (ENXIO);
+}
+
+static device_method_t tegra_soctherm_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, soctherm_probe),
+ DEVMETHOD(device_attach, soctherm_attach),
+ DEVMETHOD(device_detach, soctherm_detach),
+
+ /* SOCTHERM interface */
+ DEVMETHOD(tegra_soctherm_get_temperature, soctherm_get_temp),
+
+ DEVMETHOD_END
+};
+
+static devclass_t tegra_soctherm_devclass;
+DEFINE_CLASS_0(tegra_soctherm, tegra_soctherm_driver, tegra_soctherm_methods,
+ sizeof(struct soctherm_softc));
+EARLY_DRIVER_MODULE(tegra_soctherm, simplebus, tegra_soctherm_driver,
+tegra_soctherm_devclass, 0, 0, 79);
diff --git a/sys/arm/nvidia/tegra_soctherm_if.m b/sys/arm/nvidia/tegra_soctherm_if.m
new file mode 100644
index 0000000..55ae044
--- /dev/null
+++ b/sys/arm/nvidia/tegra_soctherm_if.m
@@ -0,0 +1,42 @@
+#-
+# Copyright (c) 2016 Michal Meloun <mmel@FreeBSD.org>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+
+#include <machine/bus.h>
+
+INTERFACE tegra_soctherm;
+
+
+/**
+ * Read temperature
+ */
+METHOD int get_temperature{
+ device_t dev;
+ device_t consumer;
+ uintptr_t id;
+ int *val;
+};
diff --git a/sys/arm/nvidia/tegra_uart.c b/sys/arm/nvidia/tegra_uart.c
new file mode 100644
index 0000000..86972f0
--- /dev/null
+++ b/sys/arm/nvidia/tegra_uart.c
@@ -0,0 +1,251 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+
+/*
+ * UART driver for Tegra SoCs.
+ */
+#include "opt_platform.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/sysctl.h>
+#include <machine/bus.h>
+
+#include <dev/extres/clk/clk.h>
+#include <dev/extres/hwreset/hwreset.h>
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_cpu.h>
+#include <dev/uart/uart_cpu_fdt.h>
+#include <dev/uart/uart_bus.h>
+#include <dev/uart/uart_dev_ns8250.h>
+#include <dev/ic/ns16550.h>
+
+#include "uart_if.h"
+
+/*
+ * High-level UART interface.
+ */
+struct tegra_softc {
+ struct ns8250_softc ns8250_base;
+ clk_t clk;
+ hwreset_t reset;
+};
+
+/*
+ * UART class interface.
+ */
+static int
+tegra_uart_attach(struct uart_softc *sc)
+{
+ int rv;
+ struct ns8250_softc *ns8250 = (struct ns8250_softc*)sc;
+ struct uart_bas *bas = &sc->sc_bas;
+
+ rv = ns8250_bus_attach(sc);
+ if (rv != 0)
+ return (rv);
+
+ ns8250->ier_rxbits = 0x1d;
+ ns8250->ier_mask = 0xc0;
+ ns8250->ier = uart_getreg(bas, REG_IER) & ns8250->ier_mask;
+ ns8250->ier |= ns8250->ier_rxbits;
+ uart_setreg(bas, REG_IER, ns8250->ier);
+ uart_barrier(bas);
+ return (0);
+}
+
+static void
+tegra_uart_grab(struct uart_softc *sc)
+{
+ struct uart_bas *bas = &sc->sc_bas;
+ struct ns8250_softc *ns8250 = (struct ns8250_softc*)sc;
+ u_char ier;
+
+ /*
+ * turn off all interrupts to enter polling mode. Leave the
+ * saved mask alone. We'll restore whatever it was in ungrab.
+ * All pending interrupt signals are reset when IER is set to 0.
+ */
+ uart_lock(sc->sc_hwmtx);
+ ier = uart_getreg(bas, REG_IER);
+ uart_setreg(bas, REG_IER, ier & ns8250->ier_mask);
+ uart_setreg(bas, REG_FCR, 0);
+ uart_barrier(bas);
+ uart_unlock(sc->sc_hwmtx);
+}
+
+static void
+tegra_uart_ungrab(struct uart_softc *sc)
+{
+ struct ns8250_softc *ns8250 = (struct ns8250_softc*)sc;
+ struct uart_bas *bas = &sc->sc_bas;
+
+ /*
+ * Restore previous interrupt mask
+ */
+ uart_lock(sc->sc_hwmtx);
+ uart_setreg(bas, REG_FCR, ns8250->fcr);
+ uart_setreg(bas, REG_IER, ns8250->ier);
+ uart_barrier(bas);
+ uart_unlock(sc->sc_hwmtx);
+}
+
+static kobj_method_t tegra_methods[] = {
+ KOBJMETHOD(uart_probe, ns8250_bus_probe),
+ KOBJMETHOD(uart_attach, tegra_uart_attach),
+ KOBJMETHOD(uart_detach, ns8250_bus_detach),
+ KOBJMETHOD(uart_flush, ns8250_bus_flush),
+ KOBJMETHOD(uart_getsig, ns8250_bus_getsig),
+ KOBJMETHOD(uart_ioctl, ns8250_bus_ioctl),
+ KOBJMETHOD(uart_ipend, ns8250_bus_ipend),
+ KOBJMETHOD(uart_param, ns8250_bus_param),
+ KOBJMETHOD(uart_receive, ns8250_bus_receive),
+ KOBJMETHOD(uart_setsig, ns8250_bus_setsig),
+ KOBJMETHOD(uart_transmit, ns8250_bus_transmit),
+ KOBJMETHOD(uart_grab, tegra_uart_grab),
+ KOBJMETHOD(uart_ungrab, tegra_uart_ungrab),
+ KOBJMETHOD_END
+};
+
+static struct uart_class tegra_uart_class = {
+ "tegra class",
+ tegra_methods,
+ sizeof(struct tegra_softc),
+ .uc_ops = &uart_ns8250_ops,
+ .uc_range = 8,
+ .uc_rclk = 0,
+};
+
+/* Compatible devices. */
+static struct ofw_compat_data compat_data[] = {
+ {"nvidia,tegra124-uart", (uintptr_t)&tegra_uart_class},
+ {NULL, (uintptr_t)NULL},
+};
+
+UART_FDT_CLASS(compat_data);
+
+/*
+ * UART Driver interface.
+ */
+static int
+uart_fdt_get_shift1(phandle_t node)
+{
+ pcell_t shift;
+
+ if ((OF_getencprop(node, "reg-shift", &shift, sizeof(shift))) <= 0)
+ shift = 2;
+ return ((int)shift);
+}
+
+static int
+tegra_uart_probe(device_t dev)
+{
+ struct tegra_softc *sc;
+ phandle_t node;
+ uint64_t freq;
+ int shift;
+ int rv;
+ const struct ofw_compat_data *cd;
+
+ sc = device_get_softc(dev);
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+ cd = ofw_bus_search_compatible(dev, compat_data);
+ if (cd->ocd_data == 0)
+ return (ENXIO);
+ sc->ns8250_base.base.sc_class = (struct uart_class *)cd->ocd_data;
+
+ rv = hwreset_get_by_ofw_name(dev, "serial", &sc->reset);
+ if (rv != 0) {
+ device_printf(dev, "Cannot get 'serial' reset\n");
+ return (ENXIO);
+ }
+ rv = hwreset_deassert(sc->reset);
+ if (rv != 0) {
+ device_printf(dev, "Cannot unreset 'serial' reset\n");
+ return (ENXIO);
+ }
+
+ node = ofw_bus_get_node(dev);
+ shift = uart_fdt_get_shift1(node);
+ rv = clk_get_by_ofw_index(dev, 0, &sc->clk);
+ if (rv != 0) {
+ device_printf(dev, "Cannot get UART clock: %d\n", rv);
+ return (ENXIO);
+ }
+ rv = clk_enable(sc->clk);
+ if (rv != 0) {
+ device_printf(dev, "Cannot enable UART clock: %d\n", rv);
+ return (ENXIO);
+ }
+ rv = clk_get_freq(sc->clk, &freq);
+ if (rv != 0) {
+ device_printf(dev, "Cannot enable UART clock: %d\n", rv);
+ return (ENXIO);
+ }
+ return (uart_bus_probe(dev, shift, (int)freq, 0, 0));
+}
+
+static int
+tegra_uart_detach(device_t dev)
+{
+ struct tegra_softc *sc;
+
+ sc = device_get_softc(dev);
+ if (sc->clk != NULL) {
+ clk_release(sc->clk);
+ }
+
+ return (uart_bus_detach(dev));
+}
+
+static device_method_t tegra_uart_bus_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, tegra_uart_probe),
+ DEVMETHOD(device_attach, uart_bus_attach),
+ DEVMETHOD(device_detach, tegra_uart_detach),
+ { 0, 0 }
+};
+
+static driver_t tegra_uart_driver = {
+ uart_driver_name,
+ tegra_uart_bus_methods,
+ sizeof(struct tegra_softc),
+};
+
+DRIVER_MODULE(tegra_uart, simplebus, tegra_uart_driver, uart_devclass,
+ 0, 0); \ No newline at end of file
diff --git a/sys/arm/nvidia/tegra_usbphy.c b/sys/arm/nvidia/tegra_usbphy.c
new file mode 100644
index 0000000..40c0714
--- /dev/null
+++ b/sys/arm/nvidia/tegra_usbphy.c
@@ -0,0 +1,839 @@
+/*-
+ * Copyright (c) 2016 Michal Meloun <mmel@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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+
+/*
+ * USB phy driver for Tegra SoCs.
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <dev/extres/clk/clk.h>
+#include <dev/extres/hwreset/hwreset.h>
+#include <dev/extres/phy/phy.h>
+#include <dev/extres/regulator/regulator.h>
+#include <dev/fdt/fdt_common.h>
+#include <dev/fdt/fdt_pinctrl.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "phy_if.h"
+
+#define CTRL_ICUSB_CTRL 0x15c
+#define ICUSB_CTR_IC_ENB1 (1 << 3)
+
+#define CTRL_USB_USBMODE 0x1f8
+#define USB_USBMODE_MASK (3 << 0)
+#define USB_USBMODE_HOST (3 << 0)
+#define USB_USBMODE_DEVICE (2 << 0)
+
+#define CTRL_USB_HOSTPC1_DEVLC 0x1b4
+#define USB_HOSTPC1_DEVLC_PTS(x) (((x) & 0x7) << 29)
+#define USB_HOSTPC1_DEVLC_STS (1 << 28)
+#define USB_HOSTPC1_DEVLC_PHCD (1 << 22)
+
+
+#define IF_USB_SUSP_CTRL 0x400
+#define FAST_WAKEUP_RESP (1 << 26)
+#define UTMIP_SUSPL1_SET (1 << 25)
+#define USB_WAKEUP_DEBOUNCE_COUNT(x) (((x) & 0x7) << 16)
+#define USB_SUSP_SET (1 << 14)
+#define UTMIP_PHY_ENB (1 << 12)
+#define UTMIP_RESET (1 << 11)
+#define USB_SUSP_POL (1 << 10)
+#define USB_PHY_CLK_VALID_INT_ENB (1 << 9)
+#define USB_PHY_CLK_VALID_INT_STS (1 << 8)
+#define USB_PHY_CLK_VALID (1 << 7)
+#define USB_CLKEN (1 << 6)
+#define USB_SUSP_CLR (1 << 5)
+#define USB_WAKE_ON_DISCON_EN_DEV (1 << 4)
+#define USB_WAKE_ON_CNNT_EN_DEV (1 << 3)
+#define USB_WAKE_ON_RESUME_EN (1 << 2)
+#define USB_WAKEUP_INT_ENB (1 << 1)
+#define USB_WAKEUP_INT_STS (1 << 0)
+
+#define IF_USB_PHY_VBUS_SENSORS 0x404
+#define B_SESS_END_SW_VALUE (1 << 4)
+#define B_SESS_END_SW_EN (1 << 3)
+
+
+#define UTMIP_XCVR_CFG0 0x808
+#define UTMIP_XCVR_HSSLEW_MSB(x) ((((x) & 0x1fc) >> 2) << 25)
+#define UTMIP_XCVR_SETUP_MSB(x) ((((x) & 0x70) >> 4) << 22)
+#define UTMIP_XCVR_LSBIAS_SEL (1 << 21)
+#define UTMIP_XCVR_DISCON_METHOD (1 << 20)
+#define UTMIP_FORCE_PDZI_POWERUP (1 << 19)
+#define UTMIP_FORCE_PDZI_POWERDOWN (1 << 18)
+#define UTMIP_FORCE_PD2_POWERUP (1 << 17)
+#define UTMIP_FORCE_PD2_POWERDOWN (1 << 16)
+#define UTMIP_FORCE_PD_POWERUP (1 << 15)
+#define UTMIP_FORCE_PD_POWERDOWN (1 << 14)
+#define UTMIP_XCVR_TERMEN (1 << 13)
+#define UTMIP_XCVR_HSLOOPBACK (1 << 12)
+#define UTMIP_XCVR_LSFSLEW(x) (((x) & 0x3) << 10)
+#define UTMIP_XCVR_LSRSLEW(x) (((x) & 0x3) << 8)
+#define UTMIP_XCVR_FSSLEW(x) (((x) & 0x3) << 6)
+#define UTMIP_XCVR_HSSLEW(x) (((x) & 0x3) << 4)
+#define UTMIP_XCVR_SETUP(x) (((x) & 0xf) << 0)
+
+#define UTMIP_BIAS_CFG0 0x80C
+#define UTMIP_IDDIG_C_VAL (1 << 30)
+#define UTMIP_IDDIG_C_SEL (1 << 29)
+#define UTMIP_IDDIG_B_VAL (1 << 28)
+#define UTMIP_IDDIG_B_SEL (1 << 27)
+#define UTMIP_IDDIG_A_VAL (1 << 26)
+#define UTMIP_IDDIG_A_SEL (1 << 25)
+#define UTMIP_HSDISCON_LEVEL_MSB(x) ((((x) & 0x4) >> 2) << 24)
+#define UTMIP_IDPD_VAL (1 << 23)
+#define UTMIP_IDPD_SEL (1 << 22)
+#define UTMIP_IDDIG_VAL (1 << 21)
+#define UTMIP_IDDIG_SEL (1 << 20)
+#define UTMIP_GPI_VAL (1 << 19)
+#define UTMIP_GPI_SEL (1 << 18)
+#define UTMIP_ACTIVE_TERM_OFFSET(x) (((x) & 0x7) << 15)
+#define UTMIP_ACTIVE_PULLUP_OFFSET(x) (((x) & 0x7) << 12)
+#define UTMIP_OTGPD (1 << 11)
+#define UTMIP_BIASPD (1 << 10)
+#define UTMIP_VBUS_LEVEL_LEVEL(x) (((x) & 0x3) << 8)
+#define UTMIP_SESS_LEVEL_LEVEL(x) (((x) & 0x3) << 6)
+#define UTMIP_HSCHIRP_LEVEL(x) (((x) & 0x3) << 4)
+#define UTMIP_HSDISCON_LEVEL(x) (((x) & 0x3) << 2)
+#define UTMIP_HSSQUELCH_LEVEL(x) (((x) & 0x3) << 0)
+
+
+#define UTMIP_HSRX_CFG0 0x810
+#define UTMIP_KEEP_PATT_ON_ACTIVE(x) (((x) & 0x3) << 30)
+#define UTMIP_ALLOW_CONSEC_UPDN (1 << 29)
+#define UTMIP_REALIGN_ON_NEW_PKT (1 << 28)
+#define UTMIP_PCOUNT_UPDN_DIV(x) (((x) & 0xf) << 24)
+#define UTMIP_SQUELCH_EOP_DLY(x) (((x) & 0x7) << 21)
+#define UTMIP_NO_STRIPPING (1 << 20)
+#define UTMIP_IDLE_WAIT(x) (((x) & 0x1f) << 15)
+#define UTMIP_ELASTIC_LIMIT(x) (((x) & 0x1f) << 10)
+#define UTMIP_ELASTIC_OVERRUN_DISABLE (1 << 9)
+#define UTMIP_ELASTIC_UNDERRUN_DISABLE (1 << 8)
+#define UTMIP_PASS_CHIRP (1 << 7)
+#define UTMIP_PASS_FEEDBACK (1 << 6)
+#define UTMIP_PCOUNT_INERTIA(x) (((x) & 0x3) << 4)
+#define UTMIP_PHASE_ADJUST(x) (((x) & 0x3) << 2)
+#define UTMIP_THREE_SYNCBITS (1 << 1)
+#define UTMIP_USE4SYNC_TRAN (1 << 0)
+
+#define UTMIP_HSRX_CFG1 0x814
+#define UTMIP_HS_SYNC_START_DLY(x) (((x) & 0x1F) << 1)
+#define UTMIP_HS_ALLOW_KEEP_ALIVE (1 << 0)
+
+#define UTMIP_TX_CFG0 0x820
+#define UTMIP_FS_PREAMBLE_J (1 << 19)
+#define UTMIP_FS_POSTAMBLE_OUTPUT_ENABLE (1 << 18)
+#define UTMIP_FS_PREAMBLE_OUTPUT_ENABLE (1 << 17)
+#define UTMIP_FSLS_ALLOW_SOP_TX_STUFF_ERR (1 << 16)
+#define UTMIP_HS_READY_WAIT_FOR_VALID (1 << 15)
+#define UTMIP_HS_TX_IPG_DLY(x) (((x) & 0x1f) << 10)
+#define UTMIP_HS_DISCON_EOP_ONLY (1 << 9)
+#define UTMIP_HS_DISCON_DISABLE (1 << 8)
+#define UTMIP_HS_POSTAMBLE_OUTPUT_ENABLE (1 << 7)
+#define UTMIP_HS_PREAMBLE_OUTPUT_ENABLE (1 << 6)
+#define UTMIP_SIE_RESUME_ON_LINESTATE (1 << 5)
+#define UTMIP_SOF_ON_NO_STUFF (1 << 4)
+#define UTMIP_SOF_ON_NO_ENCODE (1 << 3)
+#define UTMIP_NO_STUFFING (1 << 2)
+#define UTMIP_NO_ENCODING (1 << 1)
+#define UTMIP_NO_SYNC_NO_EOP (1 << 0)
+
+#define UTMIP_MISC_CFG0 0x824
+#define UTMIP_DPDM_OBSERVE_SEL(x) (((x) & 0xf) << 27)
+#define UTMIP_DPDM_OBSERVE (1 << 26)
+#define UTMIP_KEEP_XCVR_PD_ON_SOFT_DISCON (1 << 25)
+#define UTMIP_ALLOW_LS_ON_SOFT_DISCON (1 << 24)
+#define UTMIP_FORCE_FS_DISABLE_ON_DEV_CHIRP (1 << 23)
+#define UTMIP_SUSPEND_EXIT_ON_EDGE (1 << 22)
+#define UTMIP_LS_TO_FS_SKIP_4MS (1 << 21)
+#define UTMIP_INJECT_ERROR_TYPE(x) (((x) & 0x3) << 19)
+#define UTMIP_FORCE_HS_CLOCK_ON (1 << 18)
+#define UTMIP_DISABLE_HS_TERM (1 << 17)
+#define UTMIP_FORCE_HS_TERM (1 << 16)
+#define UTMIP_DISABLE_PULLUP_DP (1 << 15)
+#define UTMIP_DISABLE_PULLUP_DM (1 << 14)
+#define UTMIP_DISABLE_PULLDN_DP (1 << 13)
+#define UTMIP_DISABLE_PULLDN_DM (1 << 12)
+#define UTMIP_FORCE_PULLUP_DP (1 << 11)
+#define UTMIP_FORCE_PULLUP_DM (1 << 10)
+#define UTMIP_FORCE_PULLDN_DP (1 << 9)
+#define UTMIP_FORCE_PULLDN_DM (1 << 8)
+#define UTMIP_STABLE_COUNT(x) (((x) & 0x7) << 5)
+#define UTMIP_STABLE_ALL (1 << 4)
+#define UTMIP_NO_FREE_ON_SUSPEND (1 << 3)
+#define UTMIP_NEVER_FREE_RUNNING_TERMS (1 << 2)
+#define UTMIP_ALWAYS_FREE_RUNNING_TERMS (1 << 1)
+#define UTMIP_COMB_TERMS (1 << 0)
+
+#define UTMIP_MISC_CFG1 0x828
+#define UTMIP_PHY_XTAL_CLOCKEN (1 << 30)
+
+#define UTMIP_DEBOUNCE_CFG0 0x82C
+#define UTMIP_BIAS_DEBOUNCE_B(x) (((x) & 0xffff) << 16)
+#define UTMIP_BIAS_DEBOUNCE_A(x) (((x) & 0xffff) << 0)
+
+#define UTMIP_BAT_CHRG_CFG0 0x830
+#define UTMIP_CHRG_DEBOUNCE_TIMESCALE(x) (((x) & 0x1f) << 8)
+#define UTMIP_OP_I_SRC_ENG (1 << 5)
+#define UTMIP_ON_SRC_ENG (1 << 4)
+#define UTMIP_OP_SRC_ENG (1 << 3)
+#define UTMIP_ON_SINK_ENG (1 << 2)
+#define UTMIP_OP_SINK_ENG (1 << 1)
+#define UTMIP_PD_CHRG (1 << 0)
+
+#define UTMIP_SPARE_CFG0 0x834
+#define FUSE_HS_IREF_CAP_CFG (1 << 7)
+#define FUSE_HS_SQUELCH_LEVEL (1 << 6)
+#define FUSE_SPARE (1 << 5)
+#define FUSE_TERM_RANGE_ADJ_SEL (1 << 4)
+#define FUSE_SETUP_SEL (1 << 3)
+#define HS_RX_LATE_SQUELCH (1 << 2)
+#define HS_RX_FLUSH_ALAP (1 << 1)
+#define HS_RX_IPG_ERROR_ENABLE (1 << 0)
+
+#define UTMIP_XCVR_CFG1 0x838
+#define UTMIP_XCVR_RPU_RANGE_ADJ(x) (((x) & 0x3) << 26)
+#define UTMIP_XCVR_HS_IREF_CAP(x) (((x) & 0x3) << 24)
+#define UTMIP_XCVR_SPARE(x) (((x) & 0x3) << 22)
+#define UTMIP_XCVR_TERM_RANGE_ADJ(x) (((x) & 0xf) << 18)
+#define UTMIP_RCTRL_SW_SET (1 << 17)
+#define UTMIP_RCTRL_SW_VAL(x) (((x) & 0x1f) << 12)
+#define UTMIP_TCTRL_SW_SET (1 << 11)
+#define UTMIP_TCTRL_SW_VAL(x) (((x) & 0x1f) << 6)
+#define UTMIP_FORCE_PDDR_POWERUP (1 << 5)
+#define UTMIP_FORCE_PDDR_POWERDOWN (1 << 4)
+#define UTMIP_FORCE_PDCHRP_POWERUP (1 << 3)
+#define UTMIP_FORCE_PDCHRP_POWERDOWN (1 << 2)
+#define UTMIP_FORCE_PDDISC_POWERUP (1 << 1)
+#define UTMIP_FORCE_PDDISC_POWERDOWN (1 << 0)
+
+#define UTMIP_BIAS_CFG1 0x83c
+#define UTMIP_BIAS_DEBOUNCE_TIMESCALE(x) (((x) & 0x3f) << 8)
+#define UTMIP_BIAS_PDTRK_COUNT(x) (((x) & 0x1f) << 3)
+#define UTMIP_VBUS_WAKEUP_POWERDOWN (1 << 2)
+#define UTMIP_FORCE_PDTRK_POWERUP (1 << 1)
+#define UTMIP_FORCE_PDTRK_POWERDOWN (1 << 0)
+
+static int usbpby_enable_cnt;
+
+enum usb_ifc_type {
+ USB_IFC_TYPE_UNKNOWN = 0,
+ USB_IFC_TYPE_UTMI,
+ USB_IFC_TYPE_ULPI
+};
+
+enum usb_dr_mode {
+ USB_DR_MODE_UNKNOWN = 0,
+ USB_DR_MODE_DEVICE,
+ USB_DR_MODE_HOST,
+ USB_DR_MODE_OTG
+};
+
+struct usbphy_softc {
+ device_t dev;
+ struct resource *mem_res;
+ struct resource *pads_res;
+ clk_t clk_reg;
+ clk_t clk_pads;
+ clk_t clk_pllu;
+ regulator_t supply_vbus;
+ hwreset_t reset_usb;
+ hwreset_t reset_pads;
+ enum usb_ifc_type ifc_type;
+ enum usb_dr_mode dr_mode;
+ bool have_utmi_regs;
+
+ /* UTMI params */
+ int hssync_start_delay;
+ int elastic_limit;
+ int idle_wait_delay;
+ int term_range_adj;
+ int xcvr_lsfslew;
+ int xcvr_lsrslew;
+ int xcvr_hsslew;
+ int hssquelch_level;
+ int hsdiscon_level;
+ int xcvr_setup;
+ int xcvr_setup_use_fuses;
+};
+
+static struct ofw_compat_data compat_data[] = {
+ {"nvidia,tegra30-usb-phy", 1},
+ {NULL, 0},
+};
+
+#define RD4(sc, offs) \
+ bus_read_4(sc->mem_res, offs)
+
+#define WR4(sc, offs, val) \
+ bus_write_4(sc->mem_res, offs, val)
+
+static int
+reg_wait(struct usbphy_softc *sc, uint32_t reg, uint32_t mask, uint32_t val)
+{
+ int i;
+
+ for (i = 0; i < 1000; i++) {
+ if ((RD4(sc, reg) & mask) == val)
+ return (0);
+ DELAY(10);
+ }
+ return (ETIMEDOUT);
+}
+
+static int
+usbphy_utmi_phy_clk(struct usbphy_softc *sc, bool enable)
+{
+ uint32_t val;
+ int rv;
+
+ val = RD4(sc, CTRL_USB_HOSTPC1_DEVLC);
+ if (enable)
+ val &= ~USB_HOSTPC1_DEVLC_PHCD;
+ else
+ val |= USB_HOSTPC1_DEVLC_PHCD;
+ WR4(sc, CTRL_USB_HOSTPC1_DEVLC, val);
+
+ rv = reg_wait(sc, IF_USB_SUSP_CTRL, USB_PHY_CLK_VALID,
+ enable ? USB_PHY_CLK_VALID: 0);
+ if (rv != 0) {
+ device_printf(sc->dev, "USB phy clock timeout.\n");
+ return (ETIMEDOUT);
+ }
+ return (0);
+}
+
+static int
+usbphy_utmi_enable(struct usbphy_softc *sc)
+{
+ int rv;
+ uint32_t val;
+
+ /* Reset phy */
+ val = RD4(sc, IF_USB_SUSP_CTRL);
+ val |= UTMIP_RESET;
+ WR4(sc, IF_USB_SUSP_CTRL, val);
+
+
+ val = RD4(sc, UTMIP_TX_CFG0);
+ val |= UTMIP_FS_PREAMBLE_J;
+ WR4(sc, UTMIP_TX_CFG0, val);
+
+ val = RD4(sc, UTMIP_HSRX_CFG0);
+ val &= ~UTMIP_IDLE_WAIT(~0);
+ val &= ~UTMIP_ELASTIC_LIMIT(~0);
+ val |= UTMIP_IDLE_WAIT(sc->idle_wait_delay);
+ val |= UTMIP_ELASTIC_LIMIT(sc->elastic_limit);
+ WR4(sc, UTMIP_HSRX_CFG0, val);
+
+ val = RD4(sc, UTMIP_HSRX_CFG1);
+ val &= ~UTMIP_HS_SYNC_START_DLY(~0);
+ val |= UTMIP_HS_SYNC_START_DLY(sc->hssync_start_delay);
+ WR4(sc, UTMIP_HSRX_CFG1, val);
+
+ val = RD4(sc, UTMIP_DEBOUNCE_CFG0);
+ val &= ~UTMIP_BIAS_DEBOUNCE_A(~0);
+ val |= UTMIP_BIAS_DEBOUNCE_A(0x7530); /* For 12MHz */
+ WR4(sc, UTMIP_DEBOUNCE_CFG0, val);
+
+ val = RD4(sc, UTMIP_MISC_CFG0);
+ val &= ~UTMIP_SUSPEND_EXIT_ON_EDGE;
+ WR4(sc, UTMIP_MISC_CFG0, val);
+
+ if (sc->dr_mode == USB_DR_MODE_DEVICE) {
+ val = RD4(sc,IF_USB_SUSP_CTRL);
+ val &= ~USB_WAKE_ON_CNNT_EN_DEV;
+ val &= ~USB_WAKE_ON_DISCON_EN_DEV;
+ WR4(sc, IF_USB_SUSP_CTRL, val);
+
+ val = RD4(sc, UTMIP_BAT_CHRG_CFG0);
+ val &= ~UTMIP_PD_CHRG;
+ WR4(sc, UTMIP_BAT_CHRG_CFG0, val);
+ } else {
+ val = RD4(sc, UTMIP_BAT_CHRG_CFG0);
+ val |= UTMIP_PD_CHRG;
+ WR4(sc, UTMIP_BAT_CHRG_CFG0, val);
+ }
+
+ usbpby_enable_cnt++;
+ if (usbpby_enable_cnt == 1) {
+ rv = hwreset_deassert(sc->reset_pads);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot unreset 'utmi-pads' reset\n");
+ return (rv);
+ }
+ rv = clk_enable(sc->clk_pads);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot enable 'utmi-pads' clock\n");
+ return (rv);
+ }
+
+ val = bus_read_4(sc->pads_res, UTMIP_BIAS_CFG0);
+ val &= ~UTMIP_OTGPD;
+ val &= ~UTMIP_BIASPD;
+ val &= ~UTMIP_HSSQUELCH_LEVEL(~0);
+ val &= ~UTMIP_HSDISCON_LEVEL(~0);
+ val &= ~UTMIP_HSDISCON_LEVEL_MSB(~0);
+ val |= UTMIP_HSSQUELCH_LEVEL(sc->hssquelch_level);
+ val |= UTMIP_HSDISCON_LEVEL(sc->hsdiscon_level);
+ val |= UTMIP_HSDISCON_LEVEL_MSB(sc->hsdiscon_level);
+ bus_write_4(sc->pads_res, UTMIP_BIAS_CFG0, val);
+
+ rv = clk_disable(sc->clk_pads);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot disable 'utmi-pads' clock\n");
+ return (rv);
+ }
+ }
+
+ val = RD4(sc, UTMIP_XCVR_CFG0);
+ val &= ~UTMIP_FORCE_PD_POWERDOWN;
+ val &= ~UTMIP_FORCE_PD2_POWERDOWN ;
+ val &= ~UTMIP_FORCE_PDZI_POWERDOWN;
+ val &= ~UTMIP_XCVR_LSBIAS_SEL;
+ val &= ~UTMIP_XCVR_LSFSLEW(~0);
+ val &= ~UTMIP_XCVR_LSRSLEW(~0);
+ val &= ~UTMIP_XCVR_HSSLEW(~0);
+ val &= ~UTMIP_XCVR_HSSLEW_MSB(~0);
+ val |= UTMIP_XCVR_LSFSLEW(sc->xcvr_lsfslew);
+ val |= UTMIP_XCVR_LSRSLEW(sc->xcvr_lsrslew);
+ val |= UTMIP_XCVR_HSSLEW(sc->xcvr_hsslew);
+ val |= UTMIP_XCVR_HSSLEW_MSB(sc->xcvr_hsslew);
+ if (!sc->xcvr_setup_use_fuses) {
+ val &= ~UTMIP_XCVR_SETUP(~0);
+ val &= ~UTMIP_XCVR_SETUP_MSB(~0);
+ val |= UTMIP_XCVR_SETUP(sc->xcvr_setup);
+ val |= UTMIP_XCVR_SETUP_MSB(sc->xcvr_setup);
+ }
+ WR4(sc, UTMIP_XCVR_CFG0, val);
+
+ val = RD4(sc, UTMIP_XCVR_CFG1);
+ val &= ~UTMIP_FORCE_PDDISC_POWERDOWN;
+ val &= ~UTMIP_FORCE_PDCHRP_POWERDOWN;
+ val &= ~UTMIP_FORCE_PDDR_POWERDOWN;
+ val &= ~UTMIP_XCVR_TERM_RANGE_ADJ(~0);
+ val |= UTMIP_XCVR_TERM_RANGE_ADJ(sc->term_range_adj);
+ WR4(sc, UTMIP_XCVR_CFG1, val);
+
+
+ val = RD4(sc, UTMIP_BIAS_CFG1);
+ val &= ~UTMIP_BIAS_PDTRK_COUNT(~0);
+ val |= UTMIP_BIAS_PDTRK_COUNT(0x5);
+ WR4(sc, UTMIP_BIAS_CFG1, val);
+
+ val = RD4(sc, UTMIP_SPARE_CFG0);
+ if (sc->xcvr_setup_use_fuses)
+ val |= FUSE_SETUP_SEL;
+ else
+ val &= ~FUSE_SETUP_SEL;
+ WR4(sc, UTMIP_SPARE_CFG0, val);
+
+ val = RD4(sc, IF_USB_SUSP_CTRL);
+ val |= UTMIP_PHY_ENB;
+ WR4(sc, IF_USB_SUSP_CTRL, val);
+
+ val = RD4(sc, IF_USB_SUSP_CTRL);
+ val &= ~UTMIP_RESET;
+ WR4(sc, IF_USB_SUSP_CTRL, val);
+
+ usbphy_utmi_phy_clk(sc, true);
+
+ val = RD4(sc, CTRL_USB_USBMODE);
+ val &= ~USB_USBMODE_MASK;
+ if (sc->dr_mode == USB_DR_MODE_HOST)
+ val |= USB_USBMODE_HOST;
+ else
+ val |= USB_USBMODE_DEVICE;
+ WR4(sc, CTRL_USB_USBMODE, val);
+
+ val = RD4(sc, CTRL_USB_HOSTPC1_DEVLC);
+ val &= ~USB_HOSTPC1_DEVLC_PTS(~0);
+ val |= USB_HOSTPC1_DEVLC_PTS(0);
+ WR4(sc, CTRL_USB_HOSTPC1_DEVLC, val);
+
+ return (0);
+}
+
+static int
+usbphy_utmi_disable(struct usbphy_softc *sc)
+{
+ int rv;
+ uint32_t val;
+
+ usbphy_utmi_phy_clk(sc, false);
+
+ if (sc->dr_mode == USB_DR_MODE_DEVICE) {
+ val = RD4(sc, IF_USB_SUSP_CTRL);
+ val &= ~USB_WAKEUP_DEBOUNCE_COUNT(~0);
+ val |= USB_WAKE_ON_CNNT_EN_DEV;
+ val |= USB_WAKEUP_DEBOUNCE_COUNT(5);
+ WR4(sc, IF_USB_SUSP_CTRL, val);
+ }
+
+ val = RD4(sc, IF_USB_SUSP_CTRL);
+ val |= UTMIP_RESET;
+ WR4(sc, IF_USB_SUSP_CTRL, val);
+
+ val = RD4(sc, UTMIP_BAT_CHRG_CFG0);
+ val |= UTMIP_PD_CHRG;
+ WR4(sc, UTMIP_BAT_CHRG_CFG0, val);
+
+ val = RD4(sc, UTMIP_XCVR_CFG0);
+ val |= UTMIP_FORCE_PD_POWERDOWN;
+ val |= UTMIP_FORCE_PD2_POWERDOWN;
+ val |= UTMIP_FORCE_PDZI_POWERDOWN;
+ WR4(sc, UTMIP_XCVR_CFG0, val);
+
+ val = RD4(sc, UTMIP_XCVR_CFG1);
+ val |= UTMIP_FORCE_PDDISC_POWERDOWN;
+ val |= UTMIP_FORCE_PDCHRP_POWERDOWN;
+ val |= UTMIP_FORCE_PDDR_POWERDOWN;
+ WR4(sc, UTMIP_XCVR_CFG1, val);
+
+ usbpby_enable_cnt--;
+ if (usbpby_enable_cnt <= 0) {
+ rv = clk_enable(sc->clk_pads);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot enable 'utmi-pads' clock\n");
+ return (rv);
+ }
+ val =bus_read_4(sc->pads_res, UTMIP_BIAS_CFG0);
+ val |= UTMIP_OTGPD;
+ val |= UTMIP_BIASPD;
+ bus_write_4(sc->pads_res, UTMIP_BIAS_CFG0, val);
+
+ rv = clk_disable(sc->clk_pads);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot disable 'utmi-pads' clock\n");
+ return (rv);
+ }
+ }
+ return (0);
+}
+
+static int
+usbphy_phy_enable(device_t dev, int id, bool enable)
+{
+ struct usbphy_softc *sc;
+ int rv = 0;
+
+ sc = device_get_softc(dev);
+
+ if (sc->ifc_type != USB_IFC_TYPE_UTMI) {
+ device_printf(sc->dev,
+ "Only UTMI interface is supported.\n");
+ return (ENXIO);
+ }
+ if (enable)
+ rv = usbphy_utmi_enable(sc);
+ else
+ rv = usbphy_utmi_disable(sc);
+
+ return (rv);
+}
+
+static enum usb_ifc_type
+usb_get_ifc_mode(device_t dev, phandle_t node, char *name)
+{
+ char *tmpstr;
+ int rv;
+ enum usb_ifc_type ret;
+
+ rv = OF_getprop_alloc(node, name, 1, (void **)&tmpstr);
+ if (rv <= 0)
+ return (USB_IFC_TYPE_UNKNOWN);
+
+ ret = USB_IFC_TYPE_UNKNOWN;
+ if (strcmp(tmpstr, "utmi") == 0)
+ ret = USB_IFC_TYPE_UTMI;
+ else if (strcmp(tmpstr, "ulpi") == 0)
+ ret = USB_IFC_TYPE_ULPI;
+ else
+ device_printf(dev, "Unsupported phy type: %s\n", tmpstr);
+ free(tmpstr, M_OFWPROP);
+ return (ret);
+}
+
+static enum usb_dr_mode
+usb_get_dr_mode(device_t dev, phandle_t node, char *name)
+{
+ char *tmpstr;
+ int rv;
+ enum usb_dr_mode ret;
+
+ rv = OF_getprop_alloc(node, name, 1, (void **)&tmpstr);
+ if (rv <= 0)
+ return (USB_DR_MODE_UNKNOWN);
+
+ ret = USB_DR_MODE_UNKNOWN;
+ if (strcmp(tmpstr, "device") == 0)
+ ret = USB_DR_MODE_DEVICE;
+ else if (strcmp(tmpstr, "host") == 0)
+ ret = USB_DR_MODE_HOST;
+ else if (strcmp(tmpstr, "otg") == 0)
+ ret = USB_DR_MODE_OTG;
+ else
+ device_printf(dev, "Unknown dr mode: %s\n", tmpstr);
+ free(tmpstr, M_OFWPROP);
+ return (ret);
+}
+
+static int
+usbphy_utmi_read_params(struct usbphy_softc *sc, phandle_t node)
+{
+ int rv;
+
+ rv = OF_getencprop(node, "nvidia,hssync-start-delay",
+ &sc->hssync_start_delay, sizeof (sc->hssync_start_delay));
+ if (rv <= 0)
+ return (ENXIO);
+
+ rv = OF_getencprop(node, "nvidia,elastic-limit",
+ &sc->elastic_limit, sizeof (sc->elastic_limit));
+ if (rv <= 0)
+ return (ENXIO);
+
+ rv = OF_getencprop(node, "nvidia,idle-wait-delay",
+ &sc->idle_wait_delay, sizeof (sc->idle_wait_delay));
+ if (rv <= 0)
+ return (ENXIO);
+
+ rv = OF_getencprop(node, "nvidia,term-range-adj",
+ &sc->term_range_adj, sizeof (sc->term_range_adj));
+ if (rv <= 0)
+ return (ENXIO);
+
+ rv = OF_getencprop(node, "nvidia,xcvr-lsfslew",
+ &sc->xcvr_lsfslew, sizeof (sc->xcvr_lsfslew));
+ if (rv <= 0)
+ return (ENXIO);
+
+ rv = OF_getencprop(node, "nvidia,xcvr-lsrslew",
+ &sc->xcvr_lsrslew, sizeof (sc->xcvr_lsrslew));
+ if (rv <= 0)
+ return (ENXIO);
+
+ rv = OF_getencprop(node, "nvidia,xcvr-hsslew",
+ &sc->xcvr_hsslew, sizeof (sc->xcvr_hsslew));
+ if (rv <= 0)
+ return (ENXIO);
+
+ rv = OF_getencprop(node, "nvidia,hssquelch-level",
+ &sc->hssquelch_level, sizeof (sc->hssquelch_level));
+ if (rv <= 0)
+ return (ENXIO);
+
+ rv = OF_getencprop(node, "nvidia,hsdiscon-level",
+ &sc->hsdiscon_level, sizeof (sc->hsdiscon_level));
+ if (rv <= 0)
+ return (ENXIO);
+
+ rv = OF_getproplen(node, "nvidia,xcvr-setup-use-fuses");
+ if (rv >= 1) {
+ sc->xcvr_setup_use_fuses = 1;
+ } else {
+ rv = OF_getencprop(node, "nvidia,xcvr-setup",
+ &sc->xcvr_setup, sizeof (sc->xcvr_setup));
+ if (rv <= 0)
+ return (ENXIO);
+ }
+
+ return (0);
+}
+
+static int
+usbphy_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
+ return (ENXIO);
+
+ device_set_desc(dev, "Tegra USB phy");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+usbphy_attach(device_t dev)
+{
+ struct usbphy_softc * sc;
+ int rid, rv;
+ phandle_t node;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev, "Cannot allocate memory resources\n");
+ return (ENXIO);
+ }
+
+ rid = 1;
+ sc->pads_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev, "Cannot allocate memory resources\n");
+ return (ENXIO);
+ }
+
+ node = ofw_bus_get_node(dev);
+
+ rv = hwreset_get_by_ofw_name(sc->dev, "usb", &sc->reset_usb);
+ if (rv != 0) {
+ device_printf(dev, "Cannot get 'usb' reset\n");
+ return (ENXIO);
+ }
+ rv = hwreset_get_by_ofw_name(sc->dev, "utmi-pads", &sc->reset_pads);
+ if (rv != 0) {
+ device_printf(dev, "Cannot get 'utmi-pads' reset\n");
+ return (ENXIO);
+ }
+
+ rv = clk_get_by_ofw_name(sc->dev, "reg", &sc->clk_reg);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'reg' clock\n");
+ return (ENXIO);
+ }
+ rv = clk_get_by_ofw_name(sc->dev, "pll_u", &sc->clk_pllu);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'pll_u' clock\n");
+ return (ENXIO);
+ }
+ rv = clk_get_by_ofw_name(sc->dev, "utmi-pads", &sc->clk_pads);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot get 'utmi-pads' clock\n");
+ return (ENXIO);
+ }
+
+ rv = hwreset_deassert(sc->reset_usb);
+ if (rv != 0) {
+ device_printf(dev, "Cannot unreset 'usb' reset\n");
+ return (ENXIO);
+ }
+
+ rv = clk_enable(sc->clk_pllu);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot enable 'pllu' clock\n");
+ return (ENXIO);
+ }
+ rv = clk_enable(sc->clk_reg);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot enable 'reg' clock\n");
+ return (ENXIO);
+ }
+ if (OF_hasprop(node, "nvidia,has-utmi-pad-registers"))
+ sc->have_utmi_regs = true;
+
+ sc->dr_mode = usb_get_dr_mode(dev, node, "dr_mode");
+ if (sc->dr_mode == USB_DR_MODE_UNKNOWN)
+ sc->dr_mode = USB_DR_MODE_HOST;
+
+ sc->ifc_type = usb_get_ifc_mode(dev, node, "phy_type");
+
+ /* We supports only utmi phy mode for now .... */
+ if (sc->ifc_type != USB_IFC_TYPE_UTMI) {
+ device_printf(dev, "Unsupported phy type\n");
+ return (ENXIO);
+ }
+ rv = usbphy_utmi_read_params(sc, node);
+ if (rv < 0)
+ return rv;
+
+ if (OF_hasprop(node, "vbus-supply")) {
+ rv = regulator_get_by_ofw_property(sc->dev, "vbus-supply",
+ &sc->supply_vbus);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot get \"vbus\" regulator\n");
+ return (ENXIO);
+ }
+ rv = regulator_enable(sc->supply_vbus);
+ if (rv != 0) {
+ device_printf(sc->dev,
+ "Cannot enable \"vbus\" regulator\n");
+ return (rv);
+ }
+ }
+
+ phy_register_provider(dev);
+ return (0);
+}
+
+static int
+usbphy_detach(device_t dev)
+{
+
+ /* This device is always present. */
+ return (EBUSY);
+}
+
+static device_method_t tegra_usbphy_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, usbphy_probe),
+ DEVMETHOD(device_attach, usbphy_attach),
+ DEVMETHOD(device_detach, usbphy_detach),
+
+ /* phy interface */
+ DEVMETHOD(phy_enable, usbphy_phy_enable),
+
+ DEVMETHOD_END
+};
+
+static driver_t tegra_usbphy_driver = {
+ "tegra_usbphy",
+ tegra_usbphy_methods,
+ sizeof(struct usbphy_softc),
+};
+
+static devclass_t tegra_usbphy_devclass;
+
+EARLY_DRIVER_MODULE(tegra_usbphy, simplebus, tegra_usbphy_driver,
+ tegra_usbphy_devclass, 0, 0, 79);
diff --git a/sys/arm/ti/aintc.c b/sys/arm/ti/aintc.c
index 19f4544..9a0a313 100644
--- a/sys/arm/ti/aintc.c
+++ b/sys/arm/ti/aintc.c
@@ -30,12 +30,15 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_platform.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/ktr.h>
#include <sys/module.h>
+#include <sys/proc.h>
#include <sys/rman.h>
#include <machine/bus.h>
#include <machine/intr.h>
@@ -45,6 +48,10 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
+#ifdef ARM_INTRNG
+#include "pic_if.h"
+#endif
+
#define INTC_REVISION 0x00
#define INTC_SYSCONFIG 0x10
#define INTC_SYSSTATUS 0x14
@@ -56,12 +63,27 @@ __FBSDID("$FreeBSD$");
#define INTC_ISR_SET(x) (0x90 + ((x) * 0x20))
#define INTC_ISR_CLEAR(x) (0x94 + ((x) * 0x20))
+#define INTC_SIR_SPURIOUS_MASK 0xffffff80
+#define INTS_SIR_ACTIVE_MASK 0x7f
+
+#define INTC_NIRQS 128
+
+#ifdef ARM_INTRNG
+struct ti_aintc_irqsrc {
+ struct intr_irqsrc tai_isrc;
+ u_int tai_irq;
+};
+#endif
+
struct ti_aintc_softc {
device_t sc_dev;
struct resource * aintc_res[3];
bus_space_tag_t aintc_bst;
bus_space_handle_t aintc_bsh;
uint8_t ver;
+#ifdef ARM_INTRNG
+ struct ti_aintc_irqsrc aintc_isrcs[INTC_NIRQS];
+#endif
};
static struct resource_spec ti_aintc_spec[] = {
@@ -83,6 +105,141 @@ static struct ofw_compat_data compat_data[] = {
{NULL, 0},
};
+#ifdef ARM_INTRNG
+static inline void
+ti_aintc_irq_eoi(struct ti_aintc_softc *sc)
+{
+
+ aintc_write_4(sc, INTC_CONTROL, 1);
+}
+
+static inline void
+ti_aintc_irq_mask(struct ti_aintc_softc *sc, u_int irq)
+{
+
+ aintc_write_4(sc, INTC_MIR_SET(irq >> 5), (1UL << (irq & 0x1F)));
+}
+
+static inline void
+ti_aintc_irq_unmask(struct ti_aintc_softc *sc, u_int irq)
+{
+
+ aintc_write_4(sc, INTC_MIR_CLEAR(irq >> 5), (1UL << (irq & 0x1F)));
+}
+
+static int
+ti_aintc_intr(void *arg)
+{
+ uint32_t irq;
+ struct ti_aintc_softc *sc = arg;
+
+ /* Get active interrupt */
+ irq = aintc_read_4(sc, INTC_SIR_IRQ);
+ if ((irq & INTC_SIR_SPURIOUS_MASK) != 0) {
+ device_printf(sc->sc_dev,
+ "Spurious interrupt detected (0x%08x)\n", irq);
+ ti_aintc_irq_eoi(sc);
+ return (FILTER_HANDLED);
+ }
+
+ /* Only level-sensitive interrupts detection is supported. */
+ irq &= INTS_SIR_ACTIVE_MASK;
+ if (intr_isrc_dispatch(&sc->aintc_isrcs[irq].tai_isrc,
+ curthread->td_intr_frame) != 0) {
+ ti_aintc_irq_mask(sc, irq);
+ ti_aintc_irq_eoi(sc);
+ device_printf(sc->sc_dev, "Stray irq %u disabled\n", irq);
+ }
+
+ arm_irq_memory_barrier(irq); /* XXX */
+ return (FILTER_HANDLED);
+}
+
+static void
+ti_aintc_enable_intr(device_t dev, struct intr_irqsrc *isrc)
+{
+ u_int irq = ((struct ti_aintc_irqsrc *)isrc)->tai_irq;
+ struct ti_aintc_softc *sc = device_get_softc(dev);
+
+ arm_irq_memory_barrier(irq);
+ ti_aintc_irq_unmask(sc, irq);
+}
+
+static void
+ti_aintc_disable_intr(device_t dev, struct intr_irqsrc *isrc)
+{
+ u_int irq = ((struct ti_aintc_irqsrc *)isrc)->tai_irq;
+ struct ti_aintc_softc *sc = device_get_softc(dev);
+
+ ti_aintc_irq_mask(sc, irq);
+}
+
+static int
+ti_aintc_map_intr(device_t dev, struct intr_map_data *data,
+ struct intr_irqsrc **isrcp)
+{
+ struct ti_aintc_softc *sc;
+
+ if (data->type != INTR_MAP_DATA_FDT || data->fdt.ncells != 1 ||
+ data->fdt.cells[0] >= INTC_NIRQS)
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+ *isrcp = &sc->aintc_isrcs[data->fdt.cells[0]].tai_isrc;
+ return (0);
+}
+
+static void
+ti_aintc_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
+{
+ u_int irq = ((struct ti_aintc_irqsrc *)isrc)->tai_irq;
+ struct ti_aintc_softc *sc = device_get_softc(dev);
+
+ ti_aintc_irq_mask(sc, irq);
+ ti_aintc_irq_eoi(sc);
+}
+
+static void
+ti_aintc_post_ithread(device_t dev, struct intr_irqsrc *isrc)
+{
+
+ ti_aintc_enable_intr(dev, isrc);
+}
+
+static void
+ti_aintc_post_filter(device_t dev, struct intr_irqsrc *isrc)
+{
+
+ ti_aintc_irq_eoi(device_get_softc(dev));
+}
+
+static int
+ti_aintc_pic_attach(struct ti_aintc_softc *sc)
+{
+ int error;
+ uint32_t irq;
+ const char *name;
+ intptr_t xref;
+
+ name = device_get_nameunit(sc->sc_dev);
+ for (irq = 0; irq < INTC_NIRQS; irq++) {
+ sc->aintc_isrcs[irq].tai_irq = irq;
+
+ error = intr_isrc_register(&sc->aintc_isrcs[irq].tai_isrc,
+ sc->sc_dev, 0, "%s,%u", name, irq);
+ if (error != 0)
+ return (error);
+ }
+
+ xref = OF_xref_from_node(ofw_bus_get_node(sc->sc_dev));
+ error = intr_pic_register(sc->sc_dev, xref);
+ if (error != 0)
+ return (error);
+
+ return (intr_pic_claim_root(sc->sc_dev, xref, ti_aintc_intr, sc, 0));
+}
+
+#else
static void
aintc_post_filter(void *arg)
{
@@ -90,6 +247,7 @@ aintc_post_filter(void *arg)
arm_irq_memory_barrier(0);
aintc_write_4(ti_aintc_sc, INTC_CONTROL, 1); /* EOI */
}
+#endif
static int
ti_aintc_probe(device_t dev)
@@ -137,14 +295,30 @@ ti_aintc_attach(device_t dev)
/*Set Priority Threshold */
aintc_write_4(sc, INTC_THRESHOLD, 0xFF);
+#ifndef ARM_INTRNG
arm_post_filter = aintc_post_filter;
-
+#else
+ if (ti_aintc_pic_attach(sc) != 0) {
+ device_printf(dev, "could not attach PIC\n");
+ return (ENXIO);
+ }
+#endif
return (0);
}
static device_method_t ti_aintc_methods[] = {
DEVMETHOD(device_probe, ti_aintc_probe),
DEVMETHOD(device_attach, ti_aintc_attach),
+
+#ifdef ARM_INTRNG
+ DEVMETHOD(pic_disable_intr, ti_aintc_disable_intr),
+ DEVMETHOD(pic_enable_intr, ti_aintc_enable_intr),
+ DEVMETHOD(pic_map_intr, ti_aintc_map_intr),
+ DEVMETHOD(pic_post_filter, ti_aintc_post_filter),
+ DEVMETHOD(pic_post_ithread, ti_aintc_post_ithread),
+ DEVMETHOD(pic_pre_ithread, ti_aintc_pre_ithread),
+#endif
+
{ 0, 0 }
};
@@ -160,6 +334,7 @@ EARLY_DRIVER_MODULE(aintc, simplebus, ti_aintc_driver, ti_aintc_devclass,
0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
SIMPLEBUS_PNP_INFO(compat_data);
+#ifndef ARM_INTRNG
int
arm_get_next_irq(int last_irq)
{
@@ -200,3 +375,4 @@ arm_unmask_irq(uintptr_t nb)
arm_irq_memory_barrier(nb);
aintc_write_4(sc, INTC_MIR_CLEAR(nb >> 5), (1UL << (nb & 0x1F)));
}
+#endif
diff --git a/sys/arm/ti/am335x/am335x_prcm.c b/sys/arm/ti/am335x/am335x_prcm.c
index 8a6476d..f72bb54 100644
--- a/sys/arm/ti/am335x/am335x_prcm.c
+++ b/sys/arm/ti/am335x/am335x_prcm.c
@@ -64,6 +64,8 @@ __FBSDID("$FreeBSD$");
#define CM_PER_MMC0_CLKCTRL (CM_PER + 0x03C)
#define CM_PER_I2C2_CLKCTRL (CM_PER + 0x044)
#define CM_PER_I2C1_CLKCTRL (CM_PER + 0x048)
+#define CM_PER_SPI0_CLKCTRL (CM_PER + 0x04C)
+#define CM_PER_SPI1_CLKCTRL (CM_PER + 0x050)
#define CM_PER_UART1_CLKCTRL (CM_PER + 0x06C)
#define CM_PER_UART2_CLKCTRL (CM_PER + 0x070)
#define CM_PER_UART3_CLKCTRL (CM_PER + 0x074)
@@ -274,6 +276,10 @@ struct ti_clock_dev ti_am335x_clk_devmap[] = {
AM335X_GENERIC_CLOCK_DEV(I2C2_CLK),
AM335X_GENERIC_CLOCK_DEV(I2C3_CLK),
+ /* McSPI we use hwmods as reference, not units in spec */
+ AM335X_GENERIC_CLOCK_DEV(SPI0_CLK),
+ AM335X_GENERIC_CLOCK_DEV(SPI1_CLK),
+
/* TSC_ADC */
AM335X_GENERIC_CLOCK_DEV(TSC_ADC_CLK),
@@ -356,6 +362,10 @@ static struct am335x_clk_details g_am335x_clk_details[] = {
_CLK_DETAIL(I2C2_CLK, CM_PER_I2C1_CLKCTRL, 0),
_CLK_DETAIL(I2C3_CLK, CM_PER_I2C2_CLKCTRL, 0),
+ /* McSPI modules, hwmods start with spi0 */
+ _CLK_DETAIL(SPI0_CLK, CM_PER_SPI0_CLKCTRL, 0),
+ _CLK_DETAIL(SPI1_CLK, CM_PER_SPI1_CLKCTRL, 0),
+
/* TSC_ADC module */
_CLK_DETAIL(TSC_ADC_CLK, CM_WKUP_ADC_TSC_CLKCTRL, 0),
diff --git a/sys/arm/ti/cpsw/if_cpsw.c b/sys/arm/ti/cpsw/if_cpsw.c
index a27393d..4486e0f 100644
--- a/sys/arm/ti/cpsw/if_cpsw.c
+++ b/sys/arm/ti/cpsw/if_cpsw.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2012 Damjan Marion <dmarion@Freebsd.org>
+ * Copyright (c) 2016 Rubicon Communications, LLC (Netgate)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -93,50 +94,55 @@ __FBSDID("$FreeBSD$");
/* Device probe/attach/detach. */
static int cpsw_probe(device_t);
-static void cpsw_init_slots(struct cpsw_softc *);
static int cpsw_attach(device_t);
-static void cpsw_free_slot(struct cpsw_softc *, struct cpsw_slot *);
static int cpsw_detach(device_t);
+static int cpswp_probe(device_t);
+static int cpswp_attach(device_t);
+static int cpswp_detach(device_t);
+
+static phandle_t cpsw_get_node(device_t, device_t);
/* Device Init/shutdown. */
-static void cpsw_init(void *);
-static void cpsw_init_locked(void *);
static int cpsw_shutdown(device_t);
-static void cpsw_shutdown_locked(struct cpsw_softc *);
+static void cpswp_init(void *);
+static void cpswp_init_locked(void *);
+static void cpswp_stop_locked(struct cpswp_softc *);
/* Device Suspend/Resume. */
static int cpsw_suspend(device_t);
static int cpsw_resume(device_t);
/* Ioctl. */
-static int cpsw_ioctl(struct ifnet *, u_long command, caddr_t data);
+static int cpswp_ioctl(struct ifnet *, u_long command, caddr_t data);
-static int cpsw_miibus_readreg(device_t, int phy, int reg);
-static int cpsw_miibus_writereg(device_t, int phy, int reg, int value);
-static void cpsw_miibus_statchg(device_t);
+static int cpswp_miibus_readreg(device_t, int phy, int reg);
+static int cpswp_miibus_writereg(device_t, int phy, int reg, int value);
+static void cpswp_miibus_statchg(device_t);
/* Send/Receive packets. */
static void cpsw_intr_rx(void *arg);
static struct mbuf *cpsw_rx_dequeue(struct cpsw_softc *);
static void cpsw_rx_enqueue(struct cpsw_softc *);
-static void cpsw_start(struct ifnet *);
-static void cpsw_tx_enqueue(struct cpsw_softc *);
+static void cpswp_start(struct ifnet *);
+static void cpswp_tx_enqueue(struct cpswp_softc *);
static int cpsw_tx_dequeue(struct cpsw_softc *);
/* Misc interrupts and watchdog. */
static void cpsw_intr_rx_thresh(void *);
static void cpsw_intr_misc(void *);
-static void cpsw_tick(void *);
-static void cpsw_ifmedia_sts(struct ifnet *, struct ifmediareq *);
-static int cpsw_ifmedia_upd(struct ifnet *);
-static void cpsw_tx_watchdog(struct cpsw_softc *);
+static void cpswp_tick(void *);
+static void cpswp_ifmedia_sts(struct ifnet *, struct ifmediareq *);
+static int cpswp_ifmedia_upd(struct ifnet *);
+static void cpsw_tx_watchdog(void *);
/* ALE support */
-static void cpsw_ale_read_entry(struct cpsw_softc *, uint16_t idx, uint32_t *ale_entry);
-static void cpsw_ale_write_entry(struct cpsw_softc *, uint16_t idx, uint32_t *ale_entry);
-static int cpsw_ale_mc_entry_set(struct cpsw_softc *, uint8_t portmap, uint8_t *mac);
-static int cpsw_ale_update_addresses(struct cpsw_softc *, int purge);
+static void cpsw_ale_read_entry(struct cpsw_softc *, uint16_t, uint32_t *);
+static void cpsw_ale_write_entry(struct cpsw_softc *, uint16_t, uint32_t *);
+static int cpsw_ale_mc_entry_set(struct cpsw_softc *, uint8_t, int, uint8_t *);
static void cpsw_ale_dump_table(struct cpsw_softc *);
+static int cpsw_ale_update_vlan_table(struct cpsw_softc *, int, int, int, int,
+ int);
+static int cpswp_ale_update_addresses(struct cpswp_softc *, int);
/* Statistics and sysctls. */
static void cpsw_add_sysctls(struct cpsw_softc *);
@@ -148,27 +154,9 @@ static int cpsw_stats_sysctl(SYSCTL_HANDLER_ARGS);
* Packets with more segments than this will be defragmented before
* they are queued.
*/
-#define CPSW_TXFRAGS 8
-
-
-/*
- * TODO: The CPSW subsystem (CPSW_SS) can drive two independent PHYs
- * as separate Ethernet ports. To properly support this, we should
- * break this into two separate devices: a CPSW_SS device that owns
- * the interrupts and actually talks to the CPSW hardware, and a
- * separate CPSW Ethernet child device for each Ethernet port. The RX
- * interrupt, for example, would be part of CPSW_SS; it would receive
- * a packet, note the input port, and then dispatch it to the child
- * device's interface queue. Similarly for transmit.
- *
- * It's not clear to me whether the device tree should be restructured
- * with a cpsw_ss node and two child nodes. That would allow specifying
- * MAC addresses for each port, for example, but might be overkill.
- *
- * Unfortunately, I don't have hardware right now that supports two
- * Ethernet ports via CPSW.
- */
+#define CPSW_TXFRAGS 16
+/* Shared resources. */
static device_method_t cpsw_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, cpsw_probe),
@@ -177,26 +165,49 @@ static device_method_t cpsw_methods[] = {
DEVMETHOD(device_shutdown, cpsw_shutdown),
DEVMETHOD(device_suspend, cpsw_suspend),
DEVMETHOD(device_resume, cpsw_resume),
- /* MII interface */
- DEVMETHOD(miibus_readreg, cpsw_miibus_readreg),
- DEVMETHOD(miibus_writereg, cpsw_miibus_writereg),
- DEVMETHOD(miibus_statchg, cpsw_miibus_statchg),
- { 0, 0 }
+ /* OFW methods */
+ DEVMETHOD(ofw_bus_get_node, cpsw_get_node),
+ DEVMETHOD_END
};
static driver_t cpsw_driver = {
- "cpsw",
+ "cpswss",
cpsw_methods,
sizeof(struct cpsw_softc),
};
static devclass_t cpsw_devclass;
-DRIVER_MODULE(cpsw, simplebus, cpsw_driver, cpsw_devclass, 0, 0);
+DRIVER_MODULE(cpswss, simplebus, cpsw_driver, cpsw_devclass, 0, 0);
+
+/* Port/Slave resources. */
+static device_method_t cpswp_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, cpswp_probe),
+ DEVMETHOD(device_attach, cpswp_attach),
+ DEVMETHOD(device_detach, cpswp_detach),
+ /* MII interface */
+ DEVMETHOD(miibus_readreg, cpswp_miibus_readreg),
+ DEVMETHOD(miibus_writereg, cpswp_miibus_writereg),
+ DEVMETHOD(miibus_statchg, cpswp_miibus_statchg),
+ DEVMETHOD_END
+};
+
+static driver_t cpswp_driver = {
+ "cpsw",
+ cpswp_methods,
+ sizeof(struct cpswp_softc),
+};
+
+static devclass_t cpswp_devclass;
+
+DRIVER_MODULE(cpsw, cpswss, cpswp_driver, cpswp_devclass, 0, 0);
DRIVER_MODULE(miibus, cpsw, miibus_driver, miibus_devclass, 0, 0);
MODULE_DEPEND(cpsw, ether, 1, 1, 1);
MODULE_DEPEND(cpsw, miibus, 1, 1, 1);
+static uint32_t slave_mdio_addr[] = { 0x4a100200, 0x4a100300 };
+
static struct resource_spec irq_res_spec[] = {
{ SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE },
{ SYS_RES_IRQ, 1, RF_ACTIVE | RF_SHAREABLE },
@@ -206,7 +217,7 @@ static struct resource_spec irq_res_spec[] = {
};
/* Number of entries here must match size of stats
- * array in struct cpsw_softc. */
+ * array in struct cpswp_softc. */
static struct cpsw_stat {
int reg;
char *oid;
@@ -251,7 +262,7 @@ static struct cpsw_stat {
* Basic debug support.
*/
-#define IF_DEBUG(sc) if (sc->cpsw_if_flags & IFF_DEBUG)
+#define IF_DEBUG(_sc) if ((_sc)->if_flags & IFF_DEBUG)
static void
cpsw_debugf_head(const char *funcname)
@@ -274,35 +285,42 @@ cpsw_debugf(const char *fmt, ...)
}
-#define CPSW_DEBUGF(a) do { \
- IF_DEBUG(sc) { \
- cpsw_debugf_head(__func__); \
- cpsw_debugf a; \
- } \
+#define CPSW_DEBUGF(_sc, a) do { \
+ if (sc->debug) { \
+ cpsw_debugf_head(__func__); \
+ cpsw_debugf a; \
+ } \
+} while (0)
+
+#define CPSWP_DEBUGF(_sc, a) do { \
+ IF_DEBUG((_sc)) { \
+ cpsw_debugf_head(__func__); \
+ cpsw_debugf a; \
+ } \
} while (0)
/*
* Locking macros
*/
-#define CPSW_TX_LOCK(sc) do { \
+#define CPSW_TX_LOCK(sc) do { \
mtx_assert(&(sc)->rx.lock, MA_NOTOWNED); \
mtx_lock(&(sc)->tx.lock); \
} while (0)
-#define CPSW_TX_UNLOCK(sc) mtx_unlock(&(sc)->tx.lock)
-#define CPSW_TX_LOCK_ASSERT(sc) mtx_assert(&(sc)->tx.lock, MA_OWNED)
+#define CPSW_TX_UNLOCK(sc) mtx_unlock(&(sc)->tx.lock)
+#define CPSW_TX_LOCK_ASSERT(sc) mtx_assert(&(sc)->tx.lock, MA_OWNED)
-#define CPSW_RX_LOCK(sc) do { \
+#define CPSW_RX_LOCK(sc) do { \
mtx_assert(&(sc)->tx.lock, MA_NOTOWNED); \
mtx_lock(&(sc)->rx.lock); \
} while (0)
-#define CPSW_RX_UNLOCK(sc) mtx_unlock(&(sc)->rx.lock)
-#define CPSW_RX_LOCK_ASSERT(sc) mtx_assert(&(sc)->rx.lock, MA_OWNED)
+#define CPSW_RX_UNLOCK(sc) mtx_unlock(&(sc)->rx.lock)
+#define CPSW_RX_LOCK_ASSERT(sc) mtx_assert(&(sc)->rx.lock, MA_OWNED)
-#define CPSW_GLOBAL_LOCK(sc) do { \
- if ((mtx_owned(&(sc)->tx.lock) ? 1 : 0) != \
+#define CPSW_GLOBAL_LOCK(sc) do { \
+ if ((mtx_owned(&(sc)->tx.lock) ? 1 : 0) != \
(mtx_owned(&(sc)->rx.lock) ? 1 : 0)) { \
panic("cpsw deadlock possibility detection!"); \
} \
@@ -310,25 +328,34 @@ cpsw_debugf(const char *fmt, ...)
mtx_lock(&(sc)->rx.lock); \
} while (0)
-#define CPSW_GLOBAL_UNLOCK(sc) do { \
- CPSW_RX_UNLOCK(sc); \
- CPSW_TX_UNLOCK(sc); \
+#define CPSW_GLOBAL_UNLOCK(sc) do { \
+ CPSW_RX_UNLOCK(sc); \
+ CPSW_TX_UNLOCK(sc); \
} while (0)
-#define CPSW_GLOBAL_LOCK_ASSERT(sc) do { \
+#define CPSW_GLOBAL_LOCK_ASSERT(sc) do { \
CPSW_TX_LOCK_ASSERT(sc); \
CPSW_RX_LOCK_ASSERT(sc); \
} while (0)
+#define CPSW_PORT_LOCK(_sc) do { \
+ mtx_assert(&(_sc)->lock, MA_NOTOWNED); \
+ mtx_lock(&(_sc)->lock); \
+} while (0)
+
+#define CPSW_PORT_UNLOCK(_sc) mtx_unlock(&(_sc)->lock)
+#define CPSW_PORT_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->lock, MA_OWNED)
+
/*
* Read/Write macros
*/
-#define cpsw_read_4(sc, reg) bus_read_4(sc->mem_res, reg)
-#define cpsw_write_4(sc, reg, val) bus_write_4(sc->mem_res, reg, val)
+#define cpsw_read_4(_sc, _reg) bus_read_4((_sc)->mem_res, (_reg))
+#define cpsw_write_4(_sc, _reg, _val) \
+ bus_write_4((_sc)->mem_res, (_reg), (_val))
#define cpsw_cpdma_bd_offset(i) (CPSW_CPPI_RAM_OFFSET + ((i)*16))
-#define cpsw_cpdma_bd_paddr(sc, slot) \
+#define cpsw_cpdma_bd_paddr(sc, slot) \
BUS_SPACE_PHYSADDR(sc->mem_res, slot->bd_offset)
#define cpsw_cpdma_read_bd(sc, slot, val) \
bus_read_region_4(sc->mem_res, slot->bd_offset, (uint32_t *) val, 4)
@@ -336,16 +363,16 @@ cpsw_debugf(const char *fmt, ...)
bus_write_region_4(sc->mem_res, slot->bd_offset, (uint32_t *) val, 4)
#define cpsw_cpdma_write_bd_next(sc, slot, next_slot) \
cpsw_write_4(sc, slot->bd_offset, cpsw_cpdma_bd_paddr(sc, next_slot))
-#define cpsw_cpdma_read_bd_flags(sc, slot) \
+#define cpsw_cpdma_read_bd_flags(sc, slot) \
bus_read_2(sc->mem_res, slot->bd_offset + 14)
#define cpsw_write_hdp_slot(sc, queue, slot) \
cpsw_write_4(sc, (queue)->hdp_offset, cpsw_cpdma_bd_paddr(sc, slot))
#define CP_OFFSET (CPSW_CPDMA_TX_CP(0) - CPSW_CPDMA_TX_HDP(0))
-#define cpsw_read_cp(sc, queue) \
+#define cpsw_read_cp(sc, queue) \
cpsw_read_4(sc, (queue)->hdp_offset + CP_OFFSET)
-#define cpsw_write_cp(sc, queue, val) \
+#define cpsw_write_cp(sc, queue, val) \
cpsw_write_4(sc, (queue)->hdp_offset + CP_OFFSET, (val))
-#define cpsw_write_cp_slot(sc, queue, slot) \
+#define cpsw_write_cp_slot(sc, queue, slot) \
cpsw_write_cp(sc, queue, cpsw_cpdma_bd_paddr(sc, slot))
#if 0
@@ -403,13 +430,12 @@ cpsw_dump_slot(struct cpsw_softc *sc, struct cpsw_slot *slot)
}
}
-#define CPSW_DUMP_SLOT(cs, slot) do { \
+#define CPSW_DUMP_SLOT(cs, slot) do { \
IF_DEBUG(sc) { \
cpsw_dump_slot(sc, slot); \
} \
} while (0)
-
static void
cpsw_dump_queue(struct cpsw_softc *sc, struct cpsw_slots *q)
{
@@ -435,28 +461,6 @@ cpsw_dump_queue(struct cpsw_softc *sc, struct cpsw_slots *q)
} \
} while (0)
-
-/*
- *
- * Device Probe, Attach, Detach.
- *
- */
-
-static int
-cpsw_probe(device_t dev)
-{
-
- if (!ofw_bus_status_okay(dev))
- return (ENXIO);
-
- if (!ofw_bus_is_compatible(dev, "ti,cpsw"))
- return (ENXIO);
-
- device_set_desc(dev, "3-port Switch Ethernet Subsystem");
- return (BUS_PROBE_DEFAULT);
-}
-
-
static void
cpsw_init_slots(struct cpsw_softc *sc)
{
@@ -473,50 +477,6 @@ cpsw_init_slots(struct cpsw_softc *sc)
}
}
-/*
- * bind an interrupt, add the relevant info to sc->interrupts
- */
-static int
-cpsw_attach_interrupt(struct cpsw_softc *sc, struct resource *res, driver_intr_t *handler, const char *description)
-{
- void **pcookie;
- int error;
-
- sc->interrupts[sc->interrupt_count].res = res;
- sc->interrupts[sc->interrupt_count].description = description;
- pcookie = &sc->interrupts[sc->interrupt_count].ih_cookie;
-
- error = bus_setup_intr(sc->dev, res, INTR_TYPE_NET | INTR_MPSAFE,
- NULL, *handler, sc, pcookie);
- if (error)
- device_printf(sc->dev,
- "could not setup %s\n", description);
- else
- ++sc->interrupt_count;
- return (error);
-}
-
-/*
- * teardown everything in sc->interrupts.
- */
-static void
-cpsw_detach_interrupts(struct cpsw_softc *sc)
-{
- int error;
- int i;
-
- for (i = 0; i < sizeof(sc->interrupts) / sizeof(sc->interrupts[0]); ++i) {
- if (!sc->interrupts[i].ih_cookie)
- continue;
- error = bus_teardown_intr(sc->dev,
- sc->interrupts[i].res, sc->interrupts[i].ih_cookie);
- if (error)
- device_printf(sc->dev, "could not release %s\n",
- sc->interrupts[i].description);
- sc->interrupts[i].ih_cookie = NULL;
- }
-}
-
static int
cpsw_add_slots(struct cpsw_softc *sc, struct cpsw_queue *queue, int requested)
{
@@ -532,7 +492,7 @@ cpsw_add_slots(struct cpsw_softc *sc, struct cpsw_queue *queue, int requested)
if (slot == NULL)
return (0);
if (bus_dmamap_create(sc->mbuf_dtag, 0, &slot->dmamap)) {
- if_printf(sc->ifp, "failed to create dmamap\n");
+ device_printf(sc->dev, "failed to create dmamap\n");
return (ENOMEM);
}
STAILQ_REMOVE_HEAD(&sc->avail, next);
@@ -543,56 +503,294 @@ cpsw_add_slots(struct cpsw_softc *sc, struct cpsw_queue *queue, int requested)
return (0);
}
-static int
-cpsw_attach(device_t dev)
+static void
+cpsw_free_slot(struct cpsw_softc *sc, struct cpsw_slot *slot)
{
- bus_dma_segment_t segs[1];
- struct cpsw_softc *sc = device_get_softc(dev);
- struct mii_softc *miisc;
- struct ifnet *ifp;
- int phy, nsegs, error;
+ int error;
+
+ if (slot->dmamap) {
+ if (slot->mbuf)
+ bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
+ error = bus_dmamap_destroy(sc->mbuf_dtag, slot->dmamap);
+ KASSERT(error == 0, ("Mapping still active"));
+ slot->dmamap = NULL;
+ }
+ if (slot->mbuf) {
+ m_freem(slot->mbuf);
+ slot->mbuf = NULL;
+ }
+}
+
+static void
+cpsw_reset(struct cpsw_softc *sc)
+{
+ int i;
+
+ callout_stop(&sc->watchdog.callout);
+
+ /* Reset RMII/RGMII wrapper. */
+ cpsw_write_4(sc, CPSW_WR_SOFT_RESET, 1);
+ while (cpsw_read_4(sc, CPSW_WR_SOFT_RESET) & 1)
+ ;
+
+ /* Disable TX and RX interrupts for all cores. */
+ for (i = 0; i < 3; ++i) {
+ cpsw_write_4(sc, CPSW_WR_C_RX_THRESH_EN(i), 0x00);
+ cpsw_write_4(sc, CPSW_WR_C_TX_EN(i), 0x00);
+ cpsw_write_4(sc, CPSW_WR_C_RX_EN(i), 0x00);
+ cpsw_write_4(sc, CPSW_WR_C_MISC_EN(i), 0x00);
+ }
+
+ /* Reset CPSW subsystem. */
+ cpsw_write_4(sc, CPSW_SS_SOFT_RESET, 1);
+ while (cpsw_read_4(sc, CPSW_SS_SOFT_RESET) & 1)
+ ;
+
+ /* Reset Sliver port 1 and 2 */
+ for (i = 0; i < 2; i++) {
+ /* Reset */
+ cpsw_write_4(sc, CPSW_SL_SOFT_RESET(i), 1);
+ while (cpsw_read_4(sc, CPSW_SL_SOFT_RESET(i)) & 1)
+ ;
+ }
+
+ /* Reset DMA controller. */
+ cpsw_write_4(sc, CPSW_CPDMA_SOFT_RESET, 1);
+ while (cpsw_read_4(sc, CPSW_CPDMA_SOFT_RESET) & 1)
+ ;
+
+ /* Disable TX & RX DMA */
+ cpsw_write_4(sc, CPSW_CPDMA_TX_CONTROL, 0);
+ cpsw_write_4(sc, CPSW_CPDMA_RX_CONTROL, 0);
+
+ /* Clear all queues. */
+ for (i = 0; i < 8; i++) {
+ cpsw_write_4(sc, CPSW_CPDMA_TX_HDP(i), 0);
+ cpsw_write_4(sc, CPSW_CPDMA_RX_HDP(i), 0);
+ cpsw_write_4(sc, CPSW_CPDMA_TX_CP(i), 0);
+ cpsw_write_4(sc, CPSW_CPDMA_RX_CP(i), 0);
+ }
+
+ /* Clear all interrupt Masks */
+ cpsw_write_4(sc, CPSW_CPDMA_RX_INTMASK_CLEAR, 0xFFFFFFFF);
+ cpsw_write_4(sc, CPSW_CPDMA_TX_INTMASK_CLEAR, 0xFFFFFFFF);
+}
+
+static void
+cpsw_init(struct cpsw_softc *sc)
+{
+ struct cpsw_slot *slot;
uint32_t reg;
- pcell_t phy_id[3];
- u_long mem_base, mem_size;
- phandle_t child;
- int len;
- CPSW_DEBUGF((""));
+ /* Clear ALE */
+ cpsw_write_4(sc, CPSW_ALE_CONTROL, CPSW_ALE_CTL_CLEAR_TBL);
- getbinuptime(&sc->attach_uptime);
- sc->dev = dev;
- sc->node = ofw_bus_get_node(dev);
+ /* Enable ALE */
+ reg = CPSW_ALE_CTL_ENABLE;
+ if (sc->dualemac)
+ reg |= CPSW_ALE_CTL_VLAN_AWARE;
+ cpsw_write_4(sc, CPSW_ALE_CONTROL, reg);
- /* TODO: handle multiple slaves */
- phy = -1;
+ /* Set Host Port Mapping. */
+ cpsw_write_4(sc, CPSW_PORT_P0_CPDMA_TX_PRI_MAP, 0x76543210);
+ cpsw_write_4(sc, CPSW_PORT_P0_CPDMA_RX_CH_MAP, 0);
+
+ /* Initialize ALE: set host port to forwarding(3). */
+ cpsw_write_4(sc, CPSW_ALE_PORTCTL(0), 3);
+
+ cpsw_write_4(sc, CPSW_SS_PTYPE, 0);
+
+ /* Enable statistics for ports 0, 1 and 2 */
+ cpsw_write_4(sc, CPSW_SS_STAT_PORT_EN, 7);
+
+ /* Experiment: Turn off flow control */
+ /* This seems to fix the watchdog resets that have plagued
+ earlier versions of this driver; I'm not yet sure if there
+ are negative effects yet. */
+ cpsw_write_4(sc, CPSW_SS_FLOW_CONTROL, 0);
+
+ /* Make IP hdr aligned with 4 */
+ cpsw_write_4(sc, CPSW_CPDMA_RX_BUFFER_OFFSET, 2);
+
+ /* Initialize RX Buffer Descriptors */
+ cpsw_write_4(sc, CPSW_CPDMA_RX_FREEBUFFER(0), 0);
+
+ /* Enable TX & RX DMA */
+ cpsw_write_4(sc, CPSW_CPDMA_TX_CONTROL, 1);
+ cpsw_write_4(sc, CPSW_CPDMA_RX_CONTROL, 1);
+
+ /* Enable Interrupts for core 0 */
+ cpsw_write_4(sc, CPSW_WR_C_RX_THRESH_EN(0), 0xFF);
+ cpsw_write_4(sc, CPSW_WR_C_RX_EN(0), 0xFF);
+ cpsw_write_4(sc, CPSW_WR_C_MISC_EN(0), 0x1F);
+
+ /* Enable host Error Interrupt */
+ cpsw_write_4(sc, CPSW_CPDMA_DMA_INTMASK_SET, 3);
+
+ /* Enable interrupts for RX Channel 0 */
+ cpsw_write_4(sc, CPSW_CPDMA_RX_INTMASK_SET, 1);
+
+ /* Initialze MDIO - ENABLE, PREAMBLE=0, FAULTENB, CLKDIV=0xFF */
+ /* TODO Calculate MDCLK=CLK/(CLKDIV+1) */
+ cpsw_write_4(sc, MDIOCONTROL, MDIOCTL_ENABLE | MDIOCTL_FAULTENB | 0xff);
+
+ /* Select MII in GMII_SEL, Internal Delay mode */
+ //ti_scm_reg_write_4(0x650, 0);
+
+ /* Initialize active queues. */
+ slot = STAILQ_FIRST(&sc->tx.active);
+ if (slot != NULL)
+ cpsw_write_hdp_slot(sc, &sc->tx, slot);
+ slot = STAILQ_FIRST(&sc->rx.active);
+ if (slot != NULL)
+ cpsw_write_hdp_slot(sc, &sc->rx, slot);
+ cpsw_rx_enqueue(sc);
+
+ /* Activate network interface. */
+ sc->rx.running = 1;
+ sc->tx.running = 1;
+ sc->watchdog.timer = 0;
+ callout_init(&sc->watchdog.callout, 0);
+ callout_reset(&sc->watchdog.callout, hz, cpsw_tx_watchdog, sc);
+}
+
+/*
+ *
+ * Device Probe, Attach, Detach.
+ *
+ */
+
+static int
+cpsw_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "ti,cpsw"))
+ return (ENXIO);
+
+ device_set_desc(dev, "3-port Switch Ethernet Subsystem");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+cpsw_intr_attach(struct cpsw_softc *sc)
+{
+
+ /* Note: We don't use sc->irq_res[2] (TX interrupt) */
+ if (bus_setup_intr(sc->dev, sc->irq_res[0],
+ INTR_TYPE_NET | INTR_MPSAFE, NULL, cpsw_intr_rx_thresh,
+ sc, &sc->ih_cookie[0]) != 0) {
+ return (-1);
+ }
+ if (bus_setup_intr(sc->dev, sc->irq_res[1],
+ INTR_TYPE_NET | INTR_MPSAFE, NULL, cpsw_intr_rx,
+ sc, &sc->ih_cookie[1]) != 0) {
+ return (-1);
+ }
+ if (bus_setup_intr(sc->dev, sc->irq_res[3],
+ INTR_TYPE_NET | INTR_MPSAFE, NULL, cpsw_intr_misc,
+ sc, &sc->ih_cookie[3]) != 0) {
+ return (-1);
+ }
+
+ return (0);
+}
+
+static void
+cpsw_intr_detach(struct cpsw_softc *sc)
+{
+ int i;
+
+ for (i = 0; i < CPSW_INTR_COUNT; i++) {
+ if (sc->ih_cookie[i]) {
+ bus_teardown_intr(sc->dev, sc->irq_res[i],
+ sc->ih_cookie[i]);
+ }
+ }
+}
+
+static int
+cpsw_get_fdt_data(struct cpsw_softc *sc, int port)
+{
+ char *name;
+ int len, phy, vlan;
+ pcell_t phy_id[3], vlan_id;
+ phandle_t child;
+ unsigned long mdio_child_addr;
/* Find any slave with phy_id */
+ phy = -1;
+ vlan = -1;
for (child = OF_child(sc->node); child != 0; child = OF_peer(child)) {
- len = OF_getproplen(child, "phy_id");
- if (len <= 0)
+ if (OF_getprop_alloc(child, "name", 1, (void **)&name) < 0)
continue;
-
- /* Get phy address from fdt */
- if (OF_getencprop(child, "phy_id", phy_id, len) <= 0)
+ if (sscanf(name, "slave@%x", &mdio_child_addr) != 1) {
+ free(name, M_OFWPROP);
continue;
+ }
+ free(name, M_OFWPROP);
+ if (mdio_child_addr != slave_mdio_addr[port])
+ continue;
+
+ len = OF_getproplen(child, "phy_id");
+ if (len / sizeof(pcell_t) == 2) {
+ /* Get phy address from fdt */
+ if (OF_getencprop(child, "phy_id", phy_id, len) > 0)
+ phy = phy_id[1];
+ }
- phy = phy_id[1];
- /* TODO: get memory window for MDIO */
+ len = OF_getproplen(child, "dual_emac_res_vlan");
+ if (len / sizeof(pcell_t) == 1) {
+ /* Get phy address from fdt */
+ if (OF_getencprop(child, "dual_emac_res_vlan",
+ &vlan_id, len) > 0) {
+ vlan = vlan_id;
+ }
+ }
break;
}
-
- if (phy == -1) {
- device_printf(dev, "failed to get PHY address from FDT\n");
+ if (phy == -1)
return (ENXIO);
+ sc->port[port].phy = phy;
+ sc->port[port].vlan = vlan;
+
+ return (0);
+}
+
+static int
+cpsw_attach(device_t dev)
+{
+ bus_dma_segment_t segs[1];
+ int error, i, nsegs;
+ struct cpsw_softc *sc;
+ uint32_t reg;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ sc->node = ofw_bus_get_node(dev);
+ getbinuptime(&sc->attach_uptime);
+
+ if (OF_getencprop(sc->node, "active_slave", &sc->active_slave,
+ sizeof(sc->active_slave)) <= 0) {
+ sc->active_slave = 0;
}
+ if (sc->active_slave > 1)
+ sc->active_slave = 1;
- mem_base = 0;
- mem_size = 0;
+ if (OF_hasprop(sc->node, "dual_emac"))
+ sc->dualemac = 1;
- if (fdt_regsize(sc->node, &mem_base, &mem_size) != 0) {
- device_printf(sc->dev, "no regs property in cpsw node\n");
- return (ENXIO);
+ for (i = 0; i < CPSW_PORTS; i++) {
+ if (!sc->dualemac && i != sc->active_slave)
+ continue;
+ if (cpsw_get_fdt_data(sc, i) != 0) {
+ device_printf(dev,
+ "failed to get PHY address from FDT\n");
+ return (ENXIO);
+ }
}
/* Initialize mutexes */
@@ -610,9 +808,8 @@ cpsw_attach(device_t dev)
}
sc->mem_rid = 0;
- sc->mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
- &sc->mem_rid, mem_base, mem_base + CPSW_MEMWINDOW_SIZE -1,
- CPSW_MEMWINDOW_SIZE, RF_ACTIVE);
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->mem_rid, RF_ACTIVE);
if (sc->mem_res == NULL) {
device_printf(sc->dev, "failed to allocate memory resource\n");
cpsw_detach(dev);
@@ -642,14 +839,6 @@ cpsw_attach(device_t dev)
return (error);
}
- /* Allocate network interface */
- ifp = sc->ifp = if_alloc(IFT_ETHER);
- if (ifp == NULL) {
- device_printf(dev, "if_alloc() failed\n");
- cpsw_detach(dev);
- return (ENOMEM);
- }
-
/* Allocate the null mbuf and pre-sync it. */
sc->null_mbuf = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
memset(sc->null_mbuf->m_data, 0, sc->null_mbuf->m_ext.ext_size);
@@ -660,16 +849,6 @@ cpsw_attach(device_t dev)
BUS_DMASYNC_PREWRITE);
sc->null_mbuf_paddr = segs[0].ds_addr;
- if_initname(ifp, device_get_name(dev), device_get_unit(dev));
- ifp->if_softc = sc;
- ifp->if_flags = IFF_SIMPLEX | IFF_MULTICAST | IFF_BROADCAST;
- ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_HWCSUM; //FIXME VLAN?
- ifp->if_capenable = ifp->if_capabilities;
-
- ifp->if_init = cpsw_init;
- ifp->if_start = cpsw_start;
- ifp->if_ioctl = cpsw_ioctl;
-
cpsw_init_slots(sc);
/* Allocate slots to TX and RX queues. */
@@ -679,7 +858,8 @@ cpsw_attach(device_t dev)
STAILQ_INIT(&sc->tx.active);
// For now: 128 slots to TX, rest to RX.
// XXX TODO: start with 32/64 and grow dynamically based on demand.
- if (cpsw_add_slots(sc, &sc->tx, 128) || cpsw_add_slots(sc, &sc->rx, -1)) {
+ if (cpsw_add_slots(sc, &sc->tx, 128) ||
+ cpsw_add_slots(sc, &sc->rx, -1)) {
device_printf(dev, "failed to allocate dmamaps\n");
cpsw_detach(dev);
return (ENOMEM);
@@ -687,127 +867,78 @@ cpsw_attach(device_t dev)
device_printf(dev, "Initial queue size TX=%d RX=%d\n",
sc->tx.queue_slots, sc->rx.queue_slots);
- ifp->if_snd.ifq_drv_maxlen = sc->tx.queue_slots;
- IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen);
- IFQ_SET_READY(&ifp->if_snd);
-
sc->tx.hdp_offset = CPSW_CPDMA_TX_HDP(0);
sc->rx.hdp_offset = CPSW_CPDMA_RX_HDP(0);
- /* Get high part of MAC address from control module (mac_id0_hi) */
- /* TODO: Get MAC ID1 as well as MAC ID0. */
- ti_scm_reg_read_4(0x634, &reg);
- sc->mac_addr[0] = reg & 0xFF;
- sc->mac_addr[1] = (reg >> 8) & 0xFF;
- sc->mac_addr[2] = (reg >> 16) & 0xFF;
- sc->mac_addr[3] = (reg >> 24) & 0xFF;
-
- /* Get low part of MAC address from control module (mac_id0_lo) */
- ti_scm_reg_read_4(0x630, &reg);
- sc->mac_addr[4] = reg & 0xFF;
- sc->mac_addr[5] = (reg >> 8) & 0xFF;
-
- /* Initialze MDIO - ENABLE, PREAMBLE=0, FAULTENB, CLKDIV=0xFF */
- /* TODO Calculate MDCLK=CLK/(CLKDIV+1) */
- cpsw_write_4(sc, MDIOCONTROL, 1 << 30 | 1 << 18 | 0xFF);
-
- /* Clear ALE */
- cpsw_write_4(sc, CPSW_ALE_CONTROL, 1 << 30);
-
- /* Attach PHY(s) */
- error = mii_attach(dev, &sc->miibus, ifp, cpsw_ifmedia_upd,
- cpsw_ifmedia_sts, BMSR_DEFCAPMASK, phy, MII_OFFSET_ANY, 0);
- if (error) {
- device_printf(dev, "attaching PHYs failed\n");
+ if (cpsw_intr_attach(sc) == -1) {
+ device_printf(dev, "failed to setup interrupts\n");
cpsw_detach(dev);
- return (error);
+ return (ENXIO);
}
- sc->mii = device_get_softc(sc->miibus);
- /* Tell the MAC where to find the PHY so autoneg works */
- miisc = LIST_FIRST(&sc->mii->mii_phys);
+ /* Reset the controller. */
+ cpsw_reset(sc);
+ cpsw_init(sc);
- /* Select PHY and enable interrupts */
- cpsw_write_4(sc, MDIOUSERPHYSEL0, 1 << 6 | (miisc->mii_phy & 0x1F));
-
- /* Note: We don't use sc->res[3] (TX interrupt) */
- if (cpsw_attach_interrupt(sc, sc->irq_res[0],
- cpsw_intr_rx_thresh, "CPSW RX threshold interrupt") ||
- cpsw_attach_interrupt(sc, sc->irq_res[1],
- cpsw_intr_rx, "CPSW RX interrupt") ||
- cpsw_attach_interrupt(sc, sc->irq_res[3],
- cpsw_intr_misc, "CPSW misc interrupt")) {
- cpsw_detach(dev);
- return (ENXIO);
+ for (i = 0; i < CPSW_PORTS; i++) {
+ if (!sc->dualemac && i != sc->active_slave)
+ continue;
+ sc->port[i].dev = device_add_child(dev, "cpsw", i);
+ if (sc->port[i].dev == NULL) {
+ cpsw_detach(dev);
+ return (ENXIO);
+ }
}
-
- ether_ifattach(ifp, sc->mac_addr);
- callout_init(&sc->watchdog.callout, 0);
+ bus_generic_attach(dev);
return (0);
}
-static void
-cpsw_free_slot(struct cpsw_softc *sc, struct cpsw_slot *slot)
-{
- int error;
-
- if (slot->dmamap) {
- error = bus_dmamap_destroy(sc->mbuf_dtag, slot->dmamap);
- KASSERT(error == 0, ("Mapping still active"));
- slot->dmamap = NULL;
- }
- if (slot->mbuf) {
- m_freem(slot->mbuf);
- slot->mbuf = NULL;
- }
-}
-
static int
cpsw_detach(device_t dev)
{
- struct cpsw_softc *sc = device_get_softc(dev);
+ struct cpsw_softc *sc;
int error, i;
- CPSW_DEBUGF((""));
+ bus_generic_detach(dev);
+ sc = device_get_softc(dev);
+
+ for (i = 0; i < CPSW_PORTS; i++) {
+ if (sc->port[i].dev)
+ device_delete_child(dev, sc->port[i].dev);
+ }
- /* Stop controller and free TX queue */
if (device_is_attached(dev)) {
- ether_ifdetach(sc->ifp);
- CPSW_GLOBAL_LOCK(sc);
- cpsw_shutdown_locked(sc);
- CPSW_GLOBAL_UNLOCK(sc);
+ callout_stop(&sc->watchdog.callout);
callout_drain(&sc->watchdog.callout);
}
- bus_generic_detach(dev);
- if (sc->miibus)
- device_delete_child(dev, sc->miibus);
-
/* Stop and release all interrupts */
- cpsw_detach_interrupts(sc);
+ cpsw_intr_detach(sc);
/* Free dmamaps and mbufs */
for (i = 0; i < sizeof(sc->_slots) / sizeof(sc->_slots[0]); ++i)
cpsw_free_slot(sc, &sc->_slots[i]);
+
+ /* Free null mbuf. */
if (sc->null_mbuf_dmamap) {
+ bus_dmamap_unload(sc->mbuf_dtag, sc->null_mbuf_dmamap);
error = bus_dmamap_destroy(sc->mbuf_dtag, sc->null_mbuf_dmamap);
KASSERT(error == 0, ("Mapping still active"));
- }
- if (sc->null_mbuf)
m_freem(sc->null_mbuf);
+ }
/* Free DMA tag */
- error = bus_dma_tag_destroy(sc->mbuf_dtag);
- KASSERT(error == 0, ("Unable to destroy DMA tag"));
+ if (sc->mbuf_dtag) {
+ error = bus_dma_tag_destroy(sc->mbuf_dtag);
+ KASSERT(error == 0, ("Unable to destroy DMA tag"));
+ }
/* Free IO memory handler */
- bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem_res);
+ if (sc->mem_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem_res);
bus_release_resources(dev, irq_res_spec, sc->irq_res);
- if (sc->ifp != NULL)
- if_free(sc->ifp);
-
/* Destroy mutexes */
mtx_destroy(&sc->rx.lock);
mtx_destroy(&sc->tx.lock);
@@ -815,196 +946,249 @@ cpsw_detach(device_t dev)
return (0);
}
-/*
- *
- * Init/Shutdown.
- *
- */
-
-static void
-cpsw_reset(struct cpsw_softc *sc)
+static phandle_t
+cpsw_get_node(device_t bus, device_t dev)
{
- int i;
-
- /* Reset RMII/RGMII wrapper. */
- cpsw_write_4(sc, CPSW_WR_SOFT_RESET, 1);
- while (cpsw_read_4(sc, CPSW_WR_SOFT_RESET) & 1)
- ;
- /* Disable TX and RX interrupts for all cores. */
- for (i = 0; i < 3; ++i) {
- cpsw_write_4(sc, CPSW_WR_C_RX_THRESH_EN(i), 0x00);
- cpsw_write_4(sc, CPSW_WR_C_TX_EN(i), 0x00);
- cpsw_write_4(sc, CPSW_WR_C_RX_EN(i), 0x00);
- cpsw_write_4(sc, CPSW_WR_C_MISC_EN(i), 0x00);
- }
+ /* Share controller node with port device. */
+ return (ofw_bus_get_node(bus));
+}
- /* Reset CPSW subsystem. */
- cpsw_write_4(sc, CPSW_SS_SOFT_RESET, 1);
- while (cpsw_read_4(sc, CPSW_SS_SOFT_RESET) & 1)
- ;
+static int
+cpswp_probe(device_t dev)
+{
- /* Reset Sliver port 1 and 2 */
- for (i = 0; i < 2; i++) {
- /* Reset */
- cpsw_write_4(sc, CPSW_SL_SOFT_RESET(i), 1);
- while (cpsw_read_4(sc, CPSW_SL_SOFT_RESET(i)) & 1)
- ;
+ if (device_get_unit(dev) > 1) {
+ device_printf(dev, "Only two ports are supported.\n");
+ return (ENXIO);
}
+ device_set_desc(dev, "Ethernet Switch Port");
- /* Reset DMA controller. */
- cpsw_write_4(sc, CPSW_CPDMA_SOFT_RESET, 1);
- while (cpsw_read_4(sc, CPSW_CPDMA_SOFT_RESET) & 1)
- ;
+ return (BUS_PROBE_DEFAULT);
+}
- /* Disable TX & RX DMA */
- cpsw_write_4(sc, CPSW_CPDMA_TX_CONTROL, 0);
- cpsw_write_4(sc, CPSW_CPDMA_RX_CONTROL, 0);
+static int
+cpswp_attach(device_t dev)
+{
+ int error;
+ struct ifnet *ifp;
+ struct cpswp_softc *sc;
+ uint32_t reg;
+ uint8_t mac_addr[ETHER_ADDR_LEN];
- /* Clear all queues. */
- for (i = 0; i < 8; i++) {
- cpsw_write_4(sc, CPSW_CPDMA_TX_HDP(i), 0);
- cpsw_write_4(sc, CPSW_CPDMA_RX_HDP(i), 0);
- cpsw_write_4(sc, CPSW_CPDMA_TX_CP(i), 0);
- cpsw_write_4(sc, CPSW_CPDMA_RX_CP(i), 0);
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ sc->pdev = device_get_parent(dev);
+ sc->swsc = device_get_softc(sc->pdev);
+ sc->unit = device_get_unit(dev);
+ sc->phy = sc->swsc->port[sc->unit].phy;
+ sc->vlan = sc->swsc->port[sc->unit].vlan;
+ if (sc->swsc->dualemac && sc->vlan == -1)
+ sc->vlan = sc->unit + 1;
+
+ if (sc->unit == 0) {
+ sc->physel = MDIOUSERPHYSEL0;
+ sc->phyaccess = MDIOUSERACCESS0;
+ } else {
+ sc->physel = MDIOUSERPHYSEL1;
+ sc->phyaccess = MDIOUSERACCESS1;
}
- /* Clear all interrupt Masks */
- cpsw_write_4(sc, CPSW_CPDMA_RX_INTMASK_CLEAR, 0xFFFFFFFF);
- cpsw_write_4(sc, CPSW_CPDMA_TX_INTMASK_CLEAR, 0xFFFFFFFF);
-}
+ mtx_init(&sc->lock, device_get_nameunit(dev), "cpsw port lock",
+ MTX_DEF);
-static void
-cpsw_init(void *arg)
-{
- struct cpsw_softc *sc = arg;
+ /* Allocate network interface */
+ ifp = sc->ifp = if_alloc(IFT_ETHER);
+ if (ifp == NULL) {
+ cpswp_detach(dev);
+ return (ENXIO);
+ }
- CPSW_DEBUGF((""));
- CPSW_GLOBAL_LOCK(sc);
- cpsw_init_locked(arg);
- CPSW_GLOBAL_UNLOCK(sc);
-}
+ if_initname(ifp, device_get_name(sc->dev), sc->unit);
+ ifp->if_softc = sc;
+ ifp->if_flags = IFF_SIMPLEX | IFF_MULTICAST | IFF_BROADCAST;
+ ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_HWCSUM; //FIXME VLAN?
+ ifp->if_capenable = ifp->if_capabilities;
-static void
-cpsw_init_locked(void *arg)
-{
- struct ifnet *ifp;
- struct cpsw_softc *sc = arg;
- struct cpsw_slot *slot;
- uint32_t i;
+ ifp->if_init = cpswp_init;
+ ifp->if_start = cpswp_start;
+ ifp->if_ioctl = cpswp_ioctl;
- CPSW_DEBUGF((""));
- ifp = sc->ifp;
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
- return;
+ ifp->if_snd.ifq_drv_maxlen = sc->swsc->tx.queue_slots;
+ IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen);
+ IFQ_SET_READY(&ifp->if_snd);
- getbinuptime(&sc->init_uptime);
+ /* Get high part of MAC address from control module (mac_id[0|1]_hi) */
+ ti_scm_reg_read_4(0x634 + sc->unit * 8, &reg);
+ mac_addr[0] = reg & 0xFF;
+ mac_addr[1] = (reg >> 8) & 0xFF;
+ mac_addr[2] = (reg >> 16) & 0xFF;
+ mac_addr[3] = (reg >> 24) & 0xFF;
- /* Reset the controller. */
- cpsw_reset(sc);
+ /* Get low part of MAC address from control module (mac_id[0|1]_lo) */
+ ti_scm_reg_read_4(0x630 + sc->unit * 8, &reg);
+ mac_addr[4] = reg & 0xFF;
+ mac_addr[5] = (reg >> 8) & 0xFF;
- /* Enable ALE */
- cpsw_write_4(sc, CPSW_ALE_CONTROL, 1 << 31 | 1 << 4);
+ error = mii_attach(dev, &sc->miibus, ifp, cpswp_ifmedia_upd,
+ cpswp_ifmedia_sts, BMSR_DEFCAPMASK, sc->phy, MII_OFFSET_ANY, 0);
+ if (error) {
+ device_printf(dev, "attaching PHYs failed\n");
+ cpswp_detach(dev);
+ return (error);
+ }
+ sc->mii = device_get_softc(sc->miibus);
- /* Init Sliver port 1 and 2 */
- for (i = 0; i < 2; i++) {
- /* Set Slave Mapping */
- cpsw_write_4(sc, CPSW_SL_RX_PRI_MAP(i), 0x76543210);
- cpsw_write_4(sc, CPSW_PORT_P_TX_PRI_MAP(i + 1), 0x33221100);
- cpsw_write_4(sc, CPSW_SL_RX_MAXLEN(i), 0x5f2);
- /* Set MACCONTROL for ports 0,1: IFCTL_B(16), IFCTL_A(15),
- GMII_EN(5), FULLDUPLEX(1) */
- /* TODO: Docs claim that IFCTL_B and IFCTL_A do the same thing? */
- /* Huh? Docs call bit 0 "Loopback" some places, "FullDuplex" others. */
- cpsw_write_4(sc, CPSW_SL_MACCONTROL(i), 1 << 15 | 1 << 5 | 1);
- }
-
- /* Set Host Port Mapping */
- cpsw_write_4(sc, CPSW_PORT_P0_CPDMA_TX_PRI_MAP, 0x76543210);
- cpsw_write_4(sc, CPSW_PORT_P0_CPDMA_RX_CH_MAP, 0);
+ /* Select PHY and enable interrupts */
+ cpsw_write_4(sc->swsc, sc->physel,
+ MDIO_PHYSEL_LINKINTENB | (sc->phy & 0x1F));
- /* Initialize ALE: all ports set to forwarding(3), initialize addrs */
- for (i = 0; i < 3; i++)
- cpsw_write_4(sc, CPSW_ALE_PORTCTL(i), 3);
- cpsw_ale_update_addresses(sc, 1);
+ ether_ifattach(sc->ifp, mac_addr);
+ callout_init(&sc->mii_callout, 0);
- cpsw_write_4(sc, CPSW_SS_PTYPE, 0);
+ return (0);
+}
- /* Enable statistics for ports 0, 1 and 2 */
- cpsw_write_4(sc, CPSW_SS_STAT_PORT_EN, 7);
+static int
+cpswp_detach(device_t dev)
+{
+ struct cpswp_softc *sc;
- /* Experiment: Turn off flow control */
- /* This seems to fix the watchdog resets that have plagued
- earlier versions of this driver; I'm not yet sure if there
- are negative effects yet. */
- cpsw_write_4(sc, CPSW_SS_FLOW_CONTROL, 0);
+ sc = device_get_softc(dev);
+ CPSWP_DEBUGF(sc, (""));
+ if (device_is_attached(dev)) {
+ ether_ifdetach(sc->ifp);
+ CPSW_PORT_LOCK(sc);
+ cpswp_stop_locked(sc);
+ CPSW_PORT_UNLOCK(sc);
+ callout_drain(&sc->mii_callout);
+ }
- /* Make IP hdr aligned with 4 */
- cpsw_write_4(sc, CPSW_CPDMA_RX_BUFFER_OFFSET, 2);
+ bus_generic_detach(dev);
- /* Initialize RX Buffer Descriptors */
- cpsw_write_4(sc, CPSW_CPDMA_RX_FREEBUFFER(0), 0);
+ if_free(sc->ifp);
+ mtx_destroy(&sc->lock);
- /* Enable TX & RX DMA */
- cpsw_write_4(sc, CPSW_CPDMA_TX_CONTROL, 1);
- cpsw_write_4(sc, CPSW_CPDMA_RX_CONTROL, 1);
+ return (0);
+}
- /* Enable Interrupts for core 0 */
- cpsw_write_4(sc, CPSW_WR_C_RX_THRESH_EN(0), 0xFF);
- cpsw_write_4(sc, CPSW_WR_C_RX_EN(0), 0xFF);
- cpsw_write_4(sc, CPSW_WR_C_MISC_EN(0), 0x3F);
+/*
+ *
+ * Init/Shutdown.
+ *
+ */
- /* Enable host Error Interrupt */
- cpsw_write_4(sc, CPSW_CPDMA_DMA_INTMASK_SET, 3);
+static int
+cpsw_ports_down(struct cpsw_softc *sc)
+{
+ struct cpswp_softc *psc;
+ struct ifnet *ifp1, *ifp2;
+
+ if (!sc->dualemac)
+ return (1);
+ psc = device_get_softc(sc->port[0].dev);
+ ifp1 = psc->ifp;
+ psc = device_get_softc(sc->port[1].dev);
+ ifp2 = psc->ifp;
+ if ((ifp1->if_flags & IFF_UP) == 0 && (ifp2->if_flags & IFF_UP) == 0)
+ return (1);
- /* Enable interrupts for RX Channel 0 */
- cpsw_write_4(sc, CPSW_CPDMA_RX_INTMASK_SET, 1);
+ return (0);
+}
- /* Initialze MDIO - ENABLE, PREAMBLE=0, FAULTENB, CLKDIV=0xFF */
- /* TODO Calculate MDCLK=CLK/(CLKDIV+1) */
- cpsw_write_4(sc, MDIOCONTROL, 1 << 30 | 1 << 18 | 0xFF);
+static void
+cpswp_init(void *arg)
+{
+ struct cpswp_softc *sc = arg;
- /* Select MII in GMII_SEL, Internal Delay mode */
- //ti_scm_reg_write_4(0x650, 0);
+ CPSWP_DEBUGF(sc, (""));
+ CPSW_PORT_LOCK(sc);
+ cpswp_init_locked(arg);
+ CPSW_PORT_UNLOCK(sc);
+}
- /* Initialize active queues. */
- slot = STAILQ_FIRST(&sc->tx.active);
- if (slot != NULL)
- cpsw_write_hdp_slot(sc, &sc->tx, slot);
- slot = STAILQ_FIRST(&sc->rx.active);
- if (slot != NULL)
- cpsw_write_hdp_slot(sc, &sc->rx, slot);
- cpsw_rx_enqueue(sc);
+static void
+cpswp_init_locked(void *arg)
+{
+ struct cpswp_softc *sc = arg;
+ struct ifnet *ifp;
+ uint32_t reg;
- /* Activate network interface */
- sc->rx.running = 1;
- sc->tx.running = 1;
- sc->watchdog.timer = 0;
- callout_reset(&sc->watchdog.callout, hz, cpsw_tick, sc);
- sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
- sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ CPSWP_DEBUGF(sc, (""));
+ CPSW_PORT_LOCK_ASSERT(sc);
+ ifp = sc->ifp;
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+ return;
+ getbinuptime(&sc->init_uptime);
+
+ if (!sc->swsc->rx.running && !sc->swsc->tx.running) {
+ /* Reset the controller. */
+ cpsw_reset(sc->swsc);
+ cpsw_init(sc->swsc);
+ }
+
+ /* Set Slave Mapping. */
+ cpsw_write_4(sc->swsc, CPSW_SL_RX_PRI_MAP(sc->unit), 0x76543210);
+ cpsw_write_4(sc->swsc, CPSW_PORT_P_TX_PRI_MAP(sc->unit + 1),
+ 0x33221100);
+ cpsw_write_4(sc->swsc, CPSW_SL_RX_MAXLEN(sc->unit), 0x5f2);
+ /* Enable MAC RX/TX modules. */
+ /* TODO: Docs claim that IFCTL_B and IFCTL_A do the same thing? */
+ /* Huh? Docs call bit 0 "Loopback" some places, "FullDuplex" others. */
+ reg = cpsw_read_4(sc->swsc, CPSW_SL_MACCONTROL(sc->unit));
+ reg |= CPSW_SL_MACTL_GMII_ENABLE;
+ cpsw_write_4(sc->swsc, CPSW_SL_MACCONTROL(sc->unit), reg);
+
+ /* Initialize ALE: set port to forwarding(3), initialize addrs */
+ cpsw_write_4(sc->swsc, CPSW_ALE_PORTCTL(sc->unit + 1), 3);
+ cpswp_ale_update_addresses(sc, 1);
+
+ if (sc->swsc->dualemac) {
+ /* Set Port VID. */
+ cpsw_write_4(sc->swsc, CPSW_PORT_P_VLAN(sc->unit + 1),
+ sc->vlan & 0xfff);
+ cpsw_ale_update_vlan_table(sc->swsc, sc->vlan,
+ (1 << (sc->unit + 1)) | (1 << 0), /* Member list */
+ (1 << (sc->unit + 1)) | (1 << 0), /* Untagged egress */
+ (1 << (sc->unit + 1)) | (1 << 0), 0); /* mcast reg flood */
+ }
+
+ mii_mediachg(sc->mii);
+ callout_reset(&sc->mii_callout, hz, cpswp_tick, sc);
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
}
static int
cpsw_shutdown(device_t dev)
{
- struct cpsw_softc *sc = device_get_softc(dev);
+ struct cpsw_softc *sc;
+ struct cpswp_softc *psc;
+ int i;
+
+ sc = device_get_softc(dev);
+ CPSW_DEBUGF(sc, (""));
+ for (i = 0; i < CPSW_PORTS; i++) {
+ if (!sc->dualemac && i != sc->active_slave)
+ continue;
+ psc = device_get_softc(sc->port[i].dev);
+ CPSW_PORT_LOCK(psc);
+ cpswp_stop_locked(psc);
+ CPSW_PORT_UNLOCK(psc);
+ }
- CPSW_DEBUGF((""));
- CPSW_GLOBAL_LOCK(sc);
- cpsw_shutdown_locked(sc);
- CPSW_GLOBAL_UNLOCK(sc);
return (0);
}
static void
cpsw_rx_teardown_locked(struct cpsw_softc *sc)
{
+ struct ifnet *ifp;
struct mbuf *received, *next;
int i = 0;
- CPSW_DEBUGF(("starting RX teardown"));
+ CPSW_DEBUGF(sc, ("starting RX teardown"));
cpsw_write_4(sc, CPSW_CPDMA_RX_TEARDOWN, 0);
for (;;) {
received = cpsw_rx_dequeue(sc);
@@ -1012,16 +1196,20 @@ cpsw_rx_teardown_locked(struct cpsw_softc *sc)
while (received != NULL) {
next = received->m_nextpkt;
received->m_nextpkt = NULL;
- (*sc->ifp->if_input)(sc->ifp, received);
+ ifp = received->m_pkthdr.rcvif;
+ (*ifp->if_input)(ifp, received);
+ if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
received = next;
}
CPSW_GLOBAL_LOCK(sc);
if (!sc->rx.running) {
- CPSW_DEBUGF(("finished RX teardown (%d retries)", i));
+ CPSW_DEBUGF(sc,
+ ("finished RX teardown (%d retries)", i));
return;
}
if (++i > 10) {
- if_printf(sc->ifp, "Unable to cleanly shutdown receiver\n");
+ device_printf(sc->dev,
+ "Unable to cleanly shutdown receiver\n");
return;
}
DELAY(10);
@@ -1033,27 +1221,30 @@ cpsw_tx_teardown_locked(struct cpsw_softc *sc)
{
int i = 0;
- CPSW_DEBUGF(("starting TX teardown"));
+ CPSW_DEBUGF(sc, ("starting TX teardown"));
cpsw_write_4(sc, CPSW_CPDMA_TX_TEARDOWN, 0);
cpsw_tx_dequeue(sc);
while (sc->tx.running && ++i < 10) {
DELAY(10);
cpsw_tx_dequeue(sc);
}
- if (sc->tx.running)
- if_printf(sc->ifp, "Unable to cleanly shutdown transmitter\n");
- CPSW_DEBUGF(("finished TX teardown (%d retries, %d idle buffers)",
+ if (sc->tx.running) {
+ device_printf(sc->dev,
+ "Unable to cleanly shutdown transmitter\n");
+ }
+ CPSW_DEBUGF(sc, ("finished TX teardown (%d retries, %d idle buffers)",
i, sc->tx.active_queue_len));
}
static void
-cpsw_shutdown_locked(struct cpsw_softc *sc)
+cpswp_stop_locked(struct cpswp_softc *sc)
{
struct ifnet *ifp;
+ uint32_t reg;
- CPSW_DEBUGF((""));
- CPSW_GLOBAL_LOCK_ASSERT(sc);
ifp = sc->ifp;
+ CPSWP_DEBUGF(sc, (""));
+ CPSW_PORT_LOCK_ASSERT(sc);
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
return;
@@ -1063,16 +1254,28 @@ cpsw_shutdown_locked(struct cpsw_softc *sc)
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
/* Stop ticker */
- callout_stop(&sc->watchdog.callout);
+ callout_stop(&sc->mii_callout);
/* Tear down the RX/TX queues. */
- cpsw_rx_teardown_locked(sc);
- cpsw_tx_teardown_locked(sc);
+ if (cpsw_ports_down(sc->swsc)) {
+ CPSW_GLOBAL_LOCK(sc->swsc);
+ cpsw_rx_teardown_locked(sc->swsc);
+ cpsw_tx_teardown_locked(sc->swsc);
+ CPSW_GLOBAL_UNLOCK(sc->swsc);
+ }
- /* Capture stats before we reset controller. */
- cpsw_stats_collect(sc);
+ /* Stop MAC RX/TX modules. */
+ reg = cpsw_read_4(sc->swsc, CPSW_SL_MACCONTROL(sc->unit));
+ reg &= ~CPSW_SL_MACTL_GMII_ENABLE;
+ cpsw_write_4(sc->swsc, CPSW_SL_MACCONTROL(sc->unit), reg);
- cpsw_reset(sc);
+ if (cpsw_ports_down(sc->swsc)) {
+ /* Capture stats before we reset controller. */
+ cpsw_stats_collect(sc->swsc);
+
+ cpsw_reset(sc->swsc);
+ cpsw_init(sc->swsc);
+ }
}
/*
@@ -1082,21 +1285,32 @@ cpsw_shutdown_locked(struct cpsw_softc *sc)
static int
cpsw_suspend(device_t dev)
{
- struct cpsw_softc *sc = device_get_softc(dev);
+ struct cpsw_softc *sc;
+ struct cpswp_softc *psc;
+ int i;
+
+ sc = device_get_softc(dev);
+ CPSW_DEBUGF(sc, (""));
+ for (i = 0; i < CPSW_PORTS; i++) {
+ if (!sc->dualemac && i != sc->active_slave)
+ continue;
+ psc = device_get_softc(sc->port[i].dev);
+ CPSW_PORT_LOCK(psc);
+ cpswp_stop_locked(psc);
+ CPSW_PORT_UNLOCK(psc);
+ }
- CPSW_DEBUGF((""));
- CPSW_GLOBAL_LOCK(sc);
- cpsw_shutdown_locked(sc);
- CPSW_GLOBAL_UNLOCK(sc);
return (0);
}
static int
cpsw_resume(device_t dev)
{
- struct cpsw_softc *sc = device_get_softc(dev);
+ struct cpsw_softc *sc;
+
+ sc = device_get_softc(dev);
+ CPSW_DEBUGF(sc, ("UNIMPLEMENTED"));
- CPSW_DEBUGF(("UNIMPLEMENTED"));
return (0);
}
@@ -1107,32 +1321,26 @@ cpsw_resume(device_t dev)
*/
static void
-cpsw_set_promisc(struct cpsw_softc *sc, int set)
+cpsw_set_promisc(struct cpswp_softc *sc, int set)
{
+ uint32_t reg;
+
/*
- * Enabling promiscuous mode requires two bits of work: First,
- * ALE_BYPASS needs to be enabled. That disables the ALE
- * forwarding logic and causes every packet to be sent to the
- * host port. That makes us promiscuous wrt received packets.
- *
- * With ALE forwarding disabled, the transmitter needs to set
- * an explicit output port on every packet to route it to the
- * correct egress. This should be doable for systems such as
- * BeagleBone where only one egress port is actually wired to
- * a PHY. If you have both egress ports wired up, life gets a
- * lot more interesting.
- *
- * Hmmm.... NetBSD driver uses ALE_BYPASS always and doesn't
- * seem to set explicit egress ports. Does that mean they
- * are always promiscuous?
+ * Enabling promiscuous mode requires ALE_BYPASS to be enabled.
+ * That disables the ALE forwarding logic and causes every
+ * packet to be sent only to the host port. In bypass mode,
+ * the ALE processes host port transmit packets the same as in
+ * normal mode.
*/
- if (set) {
- printf("Promiscuous mode unimplemented\n");
- }
+ reg = cpsw_read_4(sc->swsc, CPSW_ALE_CONTROL);
+ reg &= ~CPSW_ALE_CTL_BYPASS;
+ if (set)
+ reg |= CPSW_ALE_CTL_BYPASS;
+ cpsw_write_4(sc->swsc, CPSW_ALE_CONTROL, reg);
}
static void
-cpsw_set_allmulti(struct cpsw_softc *sc, int set)
+cpsw_set_allmulti(struct cpswp_softc *sc, int set)
{
if (set) {
printf("All-multicast mode unimplemented\n");
@@ -1140,22 +1348,26 @@ cpsw_set_allmulti(struct cpsw_softc *sc, int set)
}
static int
-cpsw_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
+cpswp_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
{
- struct cpsw_softc *sc = ifp->if_softc;
- struct ifreq *ifr = (struct ifreq *)data;
+ struct cpswp_softc *sc;
+ struct ifreq *ifr;
int error;
uint32_t changed;
error = 0;
+ sc = ifp->if_softc;
+ ifr = (struct ifreq *)data;
switch (command) {
case SIOCSIFFLAGS:
- CPSW_GLOBAL_LOCK(sc);
+ CPSW_PORT_LOCK(sc);
if (ifp->if_flags & IFF_UP) {
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- changed = ifp->if_flags ^ sc->cpsw_if_flags;
- CPSW_DEBUGF(("SIOCSIFFLAGS: UP & RUNNING (changed=0x%x)", changed));
+ changed = ifp->if_flags ^ sc->if_flags;
+ CPSWP_DEBUGF(sc,
+ ("SIOCSIFFLAGS: UP & RUNNING (changed=0x%x)",
+ changed));
if (changed & IFF_PROMISC)
cpsw_set_promisc(sc,
ifp->if_flags & IFF_PROMISC);
@@ -1163,25 +1375,27 @@ cpsw_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
cpsw_set_allmulti(sc,
ifp->if_flags & IFF_ALLMULTI);
} else {
- CPSW_DEBUGF(("SIOCSIFFLAGS: UP but not RUNNING; starting up"));
- cpsw_init_locked(sc);
+ CPSWP_DEBUGF(sc,
+ ("SIOCSIFFLAGS: UP but not RUNNING; starting up"));
+ cpswp_init_locked(sc);
}
} else if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- CPSW_DEBUGF(("SIOCSIFFLAGS: not UP but RUNNING; shutting down"));
- cpsw_shutdown_locked(sc);
+ CPSWP_DEBUGF(sc,
+ ("SIOCSIFFLAGS: not UP but RUNNING; shutting down"));
+ cpswp_stop_locked(sc);
}
- sc->cpsw_if_flags = ifp->if_flags;
- CPSW_GLOBAL_UNLOCK(sc);
+ sc->if_flags = ifp->if_flags;
+ CPSW_PORT_UNLOCK(sc);
break;
case SIOCADDMULTI:
- cpsw_ale_update_addresses(sc, 0);
+ cpswp_ale_update_addresses(sc, 0);
break;
case SIOCDELMULTI:
/* Ugh. DELMULTI doesn't provide the specific address
being removed, so the best we can do is remove
everything and rebuild it all. */
- cpsw_ale_update_addresses(sc, 1);
+ cpswp_ale_update_addresses(sc, 1);
break;
case SIOCGIFMEDIA:
case SIOCSIFMEDIA:
@@ -1199,41 +1413,43 @@ cpsw_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
*
*/
static int
-cpsw_miibus_ready(struct cpsw_softc *sc)
+cpswp_miibus_ready(struct cpsw_softc *sc, uint32_t reg)
{
uint32_t r, retries = CPSW_MIIBUS_RETRIES;
while (--retries) {
- r = cpsw_read_4(sc, MDIOUSERACCESS0);
- if ((r & 1 << 31) == 0)
- return 1;
+ r = cpsw_read_4(sc, reg);
+ if ((r & MDIO_PHYACCESS_GO) == 0)
+ return (1);
DELAY(CPSW_MIIBUS_DELAY);
}
- return 0;
+
+ return (0);
}
static int
-cpsw_miibus_readreg(device_t dev, int phy, int reg)
+cpswp_miibus_readreg(device_t dev, int phy, int reg)
{
- struct cpsw_softc *sc = device_get_softc(dev);
+ struct cpswp_softc *sc;
uint32_t cmd, r;
- if (!cpsw_miibus_ready(sc)) {
+ sc = device_get_softc(dev);
+ if (!cpswp_miibus_ready(sc->swsc, sc->phyaccess)) {
device_printf(dev, "MDIO not ready to read\n");
- return 0;
+ return (0);
}
/* Set GO, reg, phy */
- cmd = 1 << 31 | (reg & 0x1F) << 21 | (phy & 0x1F) << 16;
- cpsw_write_4(sc, MDIOUSERACCESS0, cmd);
+ cmd = MDIO_PHYACCESS_GO | (reg & 0x1F) << 21 | (phy & 0x1F) << 16;
+ cpsw_write_4(sc->swsc, sc->phyaccess, cmd);
- if (!cpsw_miibus_ready(sc)) {
+ if (!cpswp_miibus_ready(sc->swsc, sc->phyaccess)) {
device_printf(dev, "MDIO timed out during read\n");
- return 0;
+ return (0);
}
- r = cpsw_read_4(sc, MDIOUSERACCESS0);
- if((r & 1 << 29) == 0) {
+ r = cpsw_read_4(sc->swsc, sc->phyaccess);
+ if ((r & MDIO_PHYACCESS_ACK) == 0) {
device_printf(dev, "Failed to read from PHY.\n");
r = 0;
}
@@ -1241,60 +1457,63 @@ cpsw_miibus_readreg(device_t dev, int phy, int reg)
}
static int
-cpsw_miibus_writereg(device_t dev, int phy, int reg, int value)
+cpswp_miibus_writereg(device_t dev, int phy, int reg, int value)
{
- struct cpsw_softc *sc = device_get_softc(dev);
+ struct cpswp_softc *sc;
uint32_t cmd;
- if (!cpsw_miibus_ready(sc)) {
+ sc = device_get_softc(dev);
+ if (!cpswp_miibus_ready(sc->swsc, sc->phyaccess)) {
device_printf(dev, "MDIO not ready to write\n");
- return 0;
+ return (0);
}
/* Set GO, WRITE, reg, phy, and value */
- cmd = 3 << 30 | (reg & 0x1F) << 21 | (phy & 0x1F) << 16
- | (value & 0xFFFF);
- cpsw_write_4(sc, MDIOUSERACCESS0, cmd);
+ cmd = MDIO_PHYACCESS_GO | MDIO_PHYACCESS_WRITE |
+ (reg & 0x1F) << 21 | (phy & 0x1F) << 16 | (value & 0xFFFF);
+ cpsw_write_4(sc->swsc, sc->phyaccess, cmd);
- if (!cpsw_miibus_ready(sc)) {
+ if (!cpswp_miibus_ready(sc->swsc, sc->phyaccess)) {
device_printf(dev, "MDIO timed out during write\n");
- return 0;
+ return (0);
}
- if((cpsw_read_4(sc, MDIOUSERACCESS0) & (1 << 29)) == 0)
+ if ((cpsw_read_4(sc->swsc, sc->phyaccess) & MDIO_PHYACCESS_ACK) == 0)
device_printf(dev, "Failed to write to PHY.\n");
- return 0;
+ return (0);
}
static void
-cpsw_miibus_statchg(device_t dev)
+cpswp_miibus_statchg(device_t dev)
{
- struct cpsw_softc *sc = device_get_softc(dev);
- uint32_t mac_control;
- int i;
-
- CPSW_DEBUGF((""));
-
- for (i = 0; i < 2; i++) {
- mac_control = cpsw_read_4(sc, CPSW_SL_MACCONTROL(i));
- mac_control &= ~(1 << 15 | 1 << 7);
-
- switch(IFM_SUBTYPE(sc->mii->mii_media_active)) {
- case IFM_1000_SX:
- case IFM_1000_LX:
- case IFM_1000_CX:
- case IFM_1000_T:
- mac_control |= 1 << 7;
- break;
-
- default:
- mac_control |= 1 << 15;
- break;
- }
+ struct cpswp_softc *sc;
+ uint32_t mac_control, reg;
+
+ sc = device_get_softc(dev);
+ CPSWP_DEBUGF(sc, (""));
+
+ reg = CPSW_SL_MACCONTROL(sc->unit);
+ mac_control = cpsw_read_4(sc->swsc, reg);
+ mac_control &= ~(CPSW_SL_MACTL_GIG | CPSW_SL_MACTL_IFCTL_A |
+ CPSW_SL_MACTL_IFCTL_B | CPSW_SL_MACTL_FULLDUPLEX);
+
+ switch(IFM_SUBTYPE(sc->mii->mii_media_active)) {
+ case IFM_1000_SX:
+ case IFM_1000_LX:
+ case IFM_1000_CX:
+ case IFM_1000_T:
+ mac_control |= CPSW_SL_MACTL_GIG;
+ break;
- cpsw_write_4(sc, CPSW_SL_MACCONTROL(i), mac_control);
+ case IFM_100_TX:
+ mac_control |= CPSW_SL_MACTL_IFCTL_A;
+ break;
}
+ if (sc->mii->mii_media_active & IFM_FDX)
+ mac_control |= CPSW_SL_MACTL_FULLDUPLEX;
+
+ cpsw_write_4(sc->swsc, reg, mac_control);
}
/*
@@ -1302,12 +1521,11 @@ cpsw_miibus_statchg(device_t dev)
* Transmit/Receive Packets.
*
*/
-
-
static void
cpsw_intr_rx(void *arg)
{
struct cpsw_softc *sc = arg;
+ struct ifnet *ifp;
struct mbuf *received, *next;
CPSW_RX_LOCK(sc);
@@ -1319,7 +1537,9 @@ cpsw_intr_rx(void *arg)
while (received != NULL) {
next = received->m_nextpkt;
received->m_nextpkt = NULL;
- (*sc->ifp->if_input)(sc->ifp, received);
+ ifp = received->m_pkthdr.rcvif;
+ (*ifp->if_input)(ifp, received);
+ if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
received = next;
}
}
@@ -1329,11 +1549,10 @@ cpsw_rx_dequeue(struct cpsw_softc *sc)
{
struct cpsw_cpdma_bd bd;
struct cpsw_slot *slot;
- struct ifnet *ifp;
+ struct cpswp_softc *psc;
struct mbuf *mb_head, *mb_tail;
- int removed = 0;
+ int port, removed = 0;
- ifp = sc->ifp;
mb_head = mb_tail = NULL;
/* Pull completed packets off hardware RX queue. */
@@ -1342,7 +1561,7 @@ cpsw_rx_dequeue(struct cpsw_softc *sc)
if (bd.flags & CPDMA_BD_OWNER)
break; /* Still in use by hardware */
- CPSW_DEBUGF(("Removing received packet from RX queue"));
+ CPSW_DEBUGF(sc, ("Removing received packet from RX queue"));
++removed;
STAILQ_REMOVE_HEAD(&sc->rx.active, next);
STAILQ_INSERT_TAIL(&sc->rx.avail, slot, next);
@@ -1351,7 +1570,7 @@ cpsw_rx_dequeue(struct cpsw_softc *sc)
bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
if (bd.flags & CPDMA_BD_TDOWNCMPLT) {
- CPSW_DEBUGF(("RX teardown in progress"));
+ CPSW_DEBUGF(sc, ("RX teardown in progress"));
m_freem(slot->mbuf);
slot->mbuf = NULL;
cpsw_write_cp(sc, &sc->rx, 0xfffffffc);
@@ -1361,6 +1580,11 @@ cpsw_rx_dequeue(struct cpsw_softc *sc)
cpsw_write_cp_slot(sc, &sc->rx, slot);
+ port = (bd.flags & CPDMA_BD_PORT_MASK) - 1;
+ KASSERT(port >= 0 && port <= 1,
+ ("patcket received with invalid port: %d", port));
+ psc = device_get_softc(sc->port[port].dev);
+
/* Set up mbuf */
/* TODO: track SOP/EOP bits to assemble a full mbuf
out of received fragments. */
@@ -1368,10 +1592,10 @@ cpsw_rx_dequeue(struct cpsw_softc *sc)
slot->mbuf->m_len = bd.pktlen - 4;
slot->mbuf->m_pkthdr.len = bd.pktlen - 4;
slot->mbuf->m_flags |= M_PKTHDR;
- slot->mbuf->m_pkthdr.rcvif = ifp;
+ slot->mbuf->m_pkthdr.rcvif = psc->ifp;
slot->mbuf->m_nextpkt = NULL;
- if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) {
+ if ((psc->ifp->if_capenable & IFCAP_RXCSUM) != 0) {
/* check for valid CRC by looking into pkt_err[5:4] */
if ((bd.flags & CPDMA_BD_PKT_ERR_MASK) == 0) {
slot->mbuf->m_pkthdr.csum_flags |= CSUM_IP_CHECKED;
@@ -1405,7 +1629,6 @@ cpsw_rx_enqueue(struct cpsw_softc *sc)
{
bus_dma_segment_t seg[1];
struct cpsw_cpdma_bd bd;
- struct ifnet *ifp = sc->ifp;
struct cpsw_slots tmpqueue = STAILQ_HEAD_INITIALIZER(tmpqueue);
struct cpsw_slot *slot, *prev_slot = NULL;
struct cpsw_slot *last_old_slot, *first_new_slot;
@@ -1416,7 +1639,8 @@ cpsw_rx_enqueue(struct cpsw_softc *sc)
if (slot->mbuf == NULL) {
slot->mbuf = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (slot->mbuf == NULL) {
- if_printf(sc->ifp, "Unable to fill RX queue\n");
+ device_printf(sc->dev,
+ "Unable to fill RX queue\n");
break;
}
slot->mbuf->m_len =
@@ -1430,7 +1654,7 @@ cpsw_rx_enqueue(struct cpsw_softc *sc)
KASSERT(nsegs == 1, ("More than one segment (nsegs=%d)", nsegs));
KASSERT(error == 0, ("DMA error (error=%d)", error));
if (error != 0 || nsegs != 1) {
- if_printf(ifp,
+ device_printf(sc->dev,
"%s: Can't prep RX buf for DMA (nsegs=%d, error=%d)\n",
__func__, nsegs, error);
bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
@@ -1462,7 +1686,7 @@ cpsw_rx_enqueue(struct cpsw_softc *sc)
if (added == 0)
return;
- CPSW_DEBUGF(("Adding %d buffers to RX queue", added));
+ CPSW_DEBUGF(sc, ("Adding %d buffers to RX queue", added));
/* Link new entries to hardware RX queue. */
last_old_slot = STAILQ_LAST(&sc->rx.active, cpsw_slot, next);
@@ -1489,20 +1713,20 @@ cpsw_rx_enqueue(struct cpsw_softc *sc)
}
static void
-cpsw_start(struct ifnet *ifp)
+cpswp_start(struct ifnet *ifp)
{
- struct cpsw_softc *sc = ifp->if_softc;
+ struct cpswp_softc *sc = ifp->if_softc;
- CPSW_TX_LOCK(sc);
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) && sc->tx.running) {
- cpsw_tx_enqueue(sc);
- cpsw_tx_dequeue(sc);
+ CPSW_TX_LOCK(sc->swsc);
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) && sc->swsc->tx.running) {
+ cpswp_tx_enqueue(sc);
+ cpsw_tx_dequeue(sc->swsc);
}
- CPSW_TX_UNLOCK(sc);
+ CPSW_TX_UNLOCK(sc->swsc);
}
static void
-cpsw_tx_enqueue(struct cpsw_softc *sc)
+cpswp_tx_enqueue(struct cpswp_softc *sc)
{
bus_dma_segment_t segs[CPSW_TXFRAGS];
struct cpsw_cpdma_bd bd;
@@ -1510,10 +1734,15 @@ cpsw_tx_enqueue(struct cpsw_softc *sc)
struct cpsw_slot *slot, *prev_slot = NULL;
struct cpsw_slot *last_old_slot, *first_new_slot;
struct mbuf *m0;
- int error, nsegs, seg, added = 0, padlen;
+ int error, flags, nsegs, seg, added = 0, padlen;
+ flags = 0;
+ if (sc->swsc->dualemac) {
+ flags = CPDMA_BD_TO_PORT |
+ ((sc->unit + 1) & CPDMA_BD_PORT_MASK);
+ }
/* Pull pending packets from IF queue and prep them for DMA. */
- while ((slot = STAILQ_FIRST(&sc->tx.avail)) != NULL) {
+ while ((slot = STAILQ_FIRST(&sc->swsc->tx.avail)) != NULL) {
IF_DEQUEUE(&sc->ifp->if_snd, m0);
if (m0 == NULL)
break;
@@ -1524,45 +1753,47 @@ cpsw_tx_enqueue(struct cpsw_softc *sc)
padlen = 0;
/* Create mapping in DMA memory */
- error = bus_dmamap_load_mbuf_sg(sc->mbuf_dtag, slot->dmamap,
- slot->mbuf, segs, &nsegs, BUS_DMA_NOWAIT);
+ error = bus_dmamap_load_mbuf_sg(sc->swsc->mbuf_dtag,
+ slot->dmamap, slot->mbuf, segs, &nsegs, BUS_DMA_NOWAIT);
/* If the packet is too fragmented, try to simplify. */
if (error == EFBIG ||
(error == 0 &&
- nsegs + (padlen > 0 ? 1 : 0) > sc->tx.avail_queue_len)) {
- bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
+ nsegs + (padlen > 0 ? 1 : 0) > sc->swsc->tx.avail_queue_len)) {
+ bus_dmamap_unload(sc->swsc->mbuf_dtag, slot->dmamap);
if (padlen > 0) /* May as well add padding. */
m_append(slot->mbuf, padlen,
- sc->null_mbuf->m_data);
+ sc->swsc->null_mbuf->m_data);
m0 = m_defrag(slot->mbuf, M_NOWAIT);
if (m0 == NULL) {
- if_printf(sc->ifp,
+ device_printf(sc->dev,
"Can't defragment packet; dropping\n");
m_freem(slot->mbuf);
} else {
- CPSW_DEBUGF(("Requeueing defragmented packet"));
+ CPSWP_DEBUGF(sc,
+ ("Requeueing defragmented packet"));
IF_PREPEND(&sc->ifp->if_snd, m0);
}
slot->mbuf = NULL;
continue;
}
if (error != 0) {
- if_printf(sc->ifp,
+ device_printf(sc->dev,
"%s: Can't setup DMA (error=%d), dropping packet\n",
__func__, error);
- bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
+ bus_dmamap_unload(sc->swsc->mbuf_dtag, slot->dmamap);
m_freem(slot->mbuf);
slot->mbuf = NULL;
break;
}
- bus_dmamap_sync(sc->mbuf_dtag, slot->dmamap,
+ bus_dmamap_sync(sc->swsc->mbuf_dtag, slot->dmamap,
BUS_DMASYNC_PREWRITE);
+ CPSWP_DEBUGF(sc,
+ ("Queueing TX packet: %d segments + %d pad bytes",
+ nsegs, padlen));
- CPSW_DEBUGF(("Queueing TX packet: %d segments + %d pad bytes",
- nsegs, padlen));
-
+ slot->ifp = sc->ifp;
/* If there is only one segment, the for() loop
* gets skipped and the single buffer gets set up
* as both SOP and EOP. */
@@ -1572,18 +1803,20 @@ cpsw_tx_enqueue(struct cpsw_softc *sc)
bd.bufoff = 0;
bd.buflen = segs[0].ds_len;
bd.pktlen = m_length(slot->mbuf, NULL) + padlen;
- bd.flags = CPDMA_BD_SOP | CPDMA_BD_OWNER;
+ bd.flags = CPDMA_BD_SOP | CPDMA_BD_OWNER | flags;
for (seg = 1; seg < nsegs; ++seg) {
/* Save the previous buffer (which isn't EOP) */
- cpsw_cpdma_write_bd(sc, slot, &bd);
- if (prev_slot != NULL)
- cpsw_cpdma_write_bd_next(sc, prev_slot, slot);
+ cpsw_cpdma_write_bd(sc->swsc, slot, &bd);
+ if (prev_slot != NULL) {
+ cpsw_cpdma_write_bd_next(sc->swsc, prev_slot,
+ slot);
+ }
prev_slot = slot;
- STAILQ_REMOVE_HEAD(&sc->tx.avail, next);
- sc->tx.avail_queue_len--;
+ STAILQ_REMOVE_HEAD(&sc->swsc->tx.avail, next);
+ sc->swsc->tx.avail_queue_len--;
STAILQ_INSERT_TAIL(&tmpqueue, slot, next);
++added;
- slot = STAILQ_FIRST(&sc->tx.avail);
+ slot = STAILQ_FIRST(&sc->swsc->tx.avail);
/* Setup next buffer (which isn't SOP) */
bd.next = 0;
@@ -1591,42 +1824,42 @@ cpsw_tx_enqueue(struct cpsw_softc *sc)
bd.bufoff = 0;
bd.buflen = segs[seg].ds_len;
bd.pktlen = 0;
- bd.flags = CPDMA_BD_OWNER;
+ bd.flags = CPDMA_BD_OWNER | flags;
}
/* Save the final buffer. */
if (padlen <= 0)
bd.flags |= CPDMA_BD_EOP;
- cpsw_cpdma_write_bd(sc, slot, &bd);
+ cpsw_cpdma_write_bd(sc->swsc, slot, &bd);
if (prev_slot != NULL)
- cpsw_cpdma_write_bd_next(sc, prev_slot, slot);
+ cpsw_cpdma_write_bd_next(sc->swsc, prev_slot, slot);
prev_slot = slot;
- STAILQ_REMOVE_HEAD(&sc->tx.avail, next);
- sc->tx.avail_queue_len--;
+ STAILQ_REMOVE_HEAD(&sc->swsc->tx.avail, next);
+ sc->swsc->tx.avail_queue_len--;
STAILQ_INSERT_TAIL(&tmpqueue, slot, next);
++added;
if (padlen > 0) {
- slot = STAILQ_FIRST(&sc->tx.avail);
- STAILQ_REMOVE_HEAD(&sc->tx.avail, next);
- sc->tx.avail_queue_len--;
+ slot = STAILQ_FIRST(&sc->swsc->tx.avail);
+ STAILQ_REMOVE_HEAD(&sc->swsc->tx.avail, next);
+ sc->swsc->tx.avail_queue_len--;
STAILQ_INSERT_TAIL(&tmpqueue, slot, next);
++added;
/* Setup buffer of null pad bytes (definitely EOP) */
- cpsw_cpdma_write_bd_next(sc, prev_slot, slot);
+ cpsw_cpdma_write_bd_next(sc->swsc, prev_slot, slot);
prev_slot = slot;
bd.next = 0;
- bd.bufptr = sc->null_mbuf_paddr;
+ bd.bufptr = sc->swsc->null_mbuf_paddr;
bd.bufoff = 0;
bd.buflen = padlen;
bd.pktlen = 0;
- bd.flags = CPDMA_BD_EOP | CPDMA_BD_OWNER;
- cpsw_cpdma_write_bd(sc, slot, &bd);
+ bd.flags = CPDMA_BD_EOP | CPDMA_BD_OWNER | flags;
+ cpsw_cpdma_write_bd(sc->swsc, slot, &bd);
++nsegs;
}
- if (nsegs > sc->tx.longest_chain)
- sc->tx.longest_chain = nsegs;
+ if (nsegs > sc->swsc->tx.longest_chain)
+ sc->swsc->tx.longest_chain = nsegs;
// TODO: Should we defer the BPF tap until
// after all packets are queued?
@@ -1634,26 +1867,29 @@ cpsw_tx_enqueue(struct cpsw_softc *sc)
}
/* Attach the list of new buffers to the hardware TX queue. */
- last_old_slot = STAILQ_LAST(&sc->tx.active, cpsw_slot, next);
+ last_old_slot = STAILQ_LAST(&sc->swsc->tx.active, cpsw_slot, next);
first_new_slot = STAILQ_FIRST(&tmpqueue);
- STAILQ_CONCAT(&sc->tx.active, &tmpqueue);
+ STAILQ_CONCAT(&sc->swsc->tx.active, &tmpqueue);
if (first_new_slot == NULL) {
return;
} else if (last_old_slot == NULL) {
/* Start a fresh queue. */
- cpsw_write_hdp_slot(sc, &sc->tx, first_new_slot);
+ cpsw_write_hdp_slot(sc->swsc, &sc->swsc->tx, first_new_slot);
} else {
/* Add buffers to end of current queue. */
- cpsw_cpdma_write_bd_next(sc, last_old_slot, first_new_slot);
+ cpsw_cpdma_write_bd_next(sc->swsc, last_old_slot,
+ first_new_slot);
/* If underrun, restart queue. */
- if (cpsw_cpdma_read_bd_flags(sc, last_old_slot) & CPDMA_BD_EOQ) {
- cpsw_write_hdp_slot(sc, &sc->tx, first_new_slot);
+ if (cpsw_cpdma_read_bd_flags(sc->swsc, last_old_slot) &
+ CPDMA_BD_EOQ) {
+ cpsw_write_hdp_slot(sc->swsc, &sc->swsc->tx,
+ first_new_slot);
}
}
- sc->tx.queue_adds += added;
- sc->tx.active_queue_len += added;
- if (sc->tx.active_queue_len > sc->tx.max_active_queue_len) {
- sc->tx.max_active_queue_len = sc->tx.active_queue_len;
+ sc->swsc->tx.queue_adds += added;
+ sc->swsc->tx.active_queue_len += added;
+ if (sc->swsc->tx.active_queue_len > sc->swsc->tx.max_active_queue_len) {
+ sc->swsc->tx.max_active_queue_len = sc->swsc->tx.active_queue_len;
}
}
@@ -1665,7 +1901,7 @@ cpsw_tx_dequeue(struct cpsw_softc *sc)
slot = STAILQ_FIRST(&sc->tx.active);
if (slot == NULL && cpsw_read_cp(sc, &sc->tx) == 0xfffffffc) {
- CPSW_DEBUGF(("TX teardown of an empty queue"));
+ CPSW_DEBUGF(sc, ("TX teardown of an empty queue"));
cpsw_write_cp(sc, &sc->tx, 0xfffffffc);
sc->tx.running = 0;
return (0);
@@ -1677,11 +1913,13 @@ cpsw_tx_dequeue(struct cpsw_softc *sc)
if (flags & CPDMA_BD_OWNER)
break; /* Hardware is still using this packet. */
- CPSW_DEBUGF(("TX removing completed packet"));
+ CPSW_DEBUGF(sc, ("TX removing completed packet"));
bus_dmamap_sync(sc->mbuf_dtag, slot->dmamap, BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->mbuf_dtag, slot->dmamap);
m_freem(slot->mbuf);
slot->mbuf = NULL;
+ if (slot->ifp)
+ if_inc_counter(slot->ifp, IFCOUNTER_OPACKETS, 1);
/* Dequeue any additional buffers used by this packet. */
while (slot != NULL && slot->mbuf == NULL) {
@@ -1694,7 +1932,7 @@ cpsw_tx_dequeue(struct cpsw_softc *sc)
/* TearDown complete is only marked on the SOP for the packet. */
if (flags & CPDMA_BD_TDOWNCMPLT) {
- CPSW_DEBUGF(("TX teardown in progress"));
+ CPSW_DEBUGF(sc, ("TX teardown in progress"));
cpsw_write_cp(sc, &sc->tx, 0xfffffffc);
// TODO: Increment a count of dropped TX packets
sc->tx.running = 0;
@@ -1725,7 +1963,7 @@ cpsw_intr_rx_thresh(void *arg)
struct cpsw_softc *sc = arg;
uint32_t stat = cpsw_read_4(sc, CPSW_WR_C_RX_THRESH_STAT(0));
- CPSW_DEBUGF(("stat=%x", stat));
+ CPSW_DEBUGF(sc, ("stat=%x", stat));
cpsw_write_4(sc, CPSW_CPDMA_CPDMA_EOI_VECTOR, 0);
}
@@ -1817,16 +2055,20 @@ cpsw_intr_misc(void *arg)
struct cpsw_softc *sc = arg;
uint32_t stat = cpsw_read_4(sc, CPSW_WR_C_MISC_STAT(0));
- if (stat & 16)
- CPSW_DEBUGF(("Time sync event interrupt unimplemented"));
- if (stat & 8)
+ if (stat & CPSW_WR_C_MISC_EVNT_PEND)
+ CPSW_DEBUGF(sc, ("Time sync event interrupt unimplemented"));
+ if (stat & CPSW_WR_C_MISC_STAT_PEND)
cpsw_stats_collect(sc);
- if (stat & 4)
+ if (stat & CPSW_WR_C_MISC_HOST_PEND)
cpsw_intr_misc_host_error(sc);
- if (stat & 2)
- CPSW_DEBUGF(("MDIO link change interrupt unimplemented"));
- if (stat & 1)
- CPSW_DEBUGF(("MDIO operation completed interrupt unimplemented"));
+ if (stat & CPSW_WR_C_MISC_MDIOLINK) {
+ cpsw_write_4(sc, MDIOLINKINTMASKED,
+ cpsw_read_4(sc, MDIOLINKINTMASKED));
+ }
+ if (stat & CPSW_WR_C_MISC_MDIOUSER) {
+ CPSW_DEBUGF(sc,
+ ("MDIO operation completed interrupt unimplemented"));
+ }
cpsw_write_4(sc, CPSW_CPDMA_CPDMA_EOI_VECTOR, 3);
}
@@ -1837,56 +2079,51 @@ cpsw_intr_misc(void *arg)
*/
static void
-cpsw_tick(void *msc)
+cpswp_tick(void *msc)
{
- struct cpsw_softc *sc = msc;
-
- /* Check for TX timeout */
- cpsw_tx_watchdog(sc);
+ struct cpswp_softc *sc = msc;
/* Check for media type change */
mii_tick(sc->mii);
- if(sc->cpsw_media_status != sc->mii->mii_media.ifm_media) {
+ if (sc->media_status != sc->mii->mii_media.ifm_media) {
printf("%s: media type changed (ifm_media=%x)\n", __func__,
sc->mii->mii_media.ifm_media);
- cpsw_ifmedia_upd(sc->ifp);
+ cpswp_ifmedia_upd(sc->ifp);
}
/* Schedule another timeout one second from now */
- callout_reset(&sc->watchdog.callout, hz, cpsw_tick, sc);
+ callout_reset(&sc->mii_callout, hz, cpswp_tick, sc);
}
static void
-cpsw_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
+cpswp_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
{
- struct cpsw_softc *sc = ifp->if_softc;
+ struct cpswp_softc *sc;
struct mii_data *mii;
- CPSW_DEBUGF((""));
- CPSW_TX_LOCK(sc);
+ sc = ifp->if_softc;
+ CPSWP_DEBUGF(sc, (""));
+ CPSW_PORT_LOCK(sc);
mii = sc->mii;
mii_pollstat(mii);
ifmr->ifm_active = mii->mii_media_active;
ifmr->ifm_status = mii->mii_media_status;
-
- CPSW_TX_UNLOCK(sc);
+ CPSW_PORT_UNLOCK(sc);
}
static int
-cpsw_ifmedia_upd(struct ifnet *ifp)
+cpswp_ifmedia_upd(struct ifnet *ifp)
{
- struct cpsw_softc *sc = ifp->if_softc;
+ struct cpswp_softc *sc;
- CPSW_DEBUGF((""));
- if (ifp->if_flags & IFF_UP) {
- CPSW_GLOBAL_LOCK(sc);
- sc->cpsw_media_status = sc->mii->mii_media.ifm_media;
- mii_mediachg(sc->mii);
- cpsw_init_locked(sc);
- CPSW_GLOBAL_UNLOCK(sc);
- }
+ sc = ifp->if_softc;
+ CPSWP_DEBUGF(sc, (""));
+ CPSW_PORT_LOCK(sc);
+ mii_mediachg(sc->mii);
+ sc->media_status = sc->mii->mii_media.ifm_media;
+ CPSW_PORT_UNLOCK(sc);
return (0);
}
@@ -1894,20 +2131,29 @@ cpsw_ifmedia_upd(struct ifnet *ifp)
static void
cpsw_tx_watchdog_full_reset(struct cpsw_softc *sc)
{
+ struct cpswp_softc *psc;
+ int i;
+
cpsw_debugf_head("CPSW watchdog");
- if_printf(sc->ifp, "watchdog timeout\n");
- cpsw_shutdown_locked(sc);
- cpsw_init_locked(sc);
+ device_printf(sc->dev, "watchdog timeout\n");
+ for (i = 0; i < CPSW_PORTS; i++) {
+ if (!sc->dualemac && i != sc->active_slave)
+ continue;
+ psc = device_get_softc(sc->port[i].dev);
+ CPSW_PORT_LOCK(psc);
+ cpswp_stop_locked(psc);
+ CPSW_PORT_UNLOCK(psc);
+ }
}
static void
-cpsw_tx_watchdog(struct cpsw_softc *sc)
+cpsw_tx_watchdog(void *msc)
{
- struct ifnet *ifp = sc->ifp;
+ struct cpsw_softc *sc;
+ sc = msc;
CPSW_GLOBAL_LOCK(sc);
- if (sc->tx.active_queue_len == 0 || (ifp->if_flags & IFF_UP) == 0 ||
- (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || !sc->tx.running) {
+ if (sc->tx.active_queue_len == 0 || !sc->tx.running) {
sc->watchdog.timer = 0; /* Nothing to do. */
} else if (sc->tx.queue_removes > sc->tx.queue_removes_at_last_tick) {
sc->watchdog.timer = 0; /* Stuff done while we weren't looking. */
@@ -1916,15 +2162,17 @@ cpsw_tx_watchdog(struct cpsw_softc *sc)
} else {
/* There was something to do but it didn't get done. */
++sc->watchdog.timer;
- if (sc->watchdog.timer > 2) {
+ if (sc->watchdog.timer > 5) {
sc->watchdog.timer = 0;
- if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
++sc->watchdog.resets;
cpsw_tx_watchdog_full_reset(sc);
}
}
sc->tx.queue_removes_at_last_tick = sc->tx.queue_removes;
CPSW_GLOBAL_UNLOCK(sc);
+
+ /* Schedule another timeout one second from now */
+ callout_reset(&sc->watchdog.callout, hz, cpsw_tx_watchdog, sc);
}
/*
@@ -1951,38 +2199,38 @@ cpsw_ale_write_entry(struct cpsw_softc *sc, uint16_t idx, uint32_t *ale_entry)
cpsw_write_4(sc, CPSW_ALE_TBLCTL, 1 << 31 | (idx & 1023));
}
-static int
+static void
cpsw_ale_remove_all_mc_entries(struct cpsw_softc *sc)
{
int i;
uint32_t ale_entry[3];
- /* First two entries are link address and broadcast. */
- for (i = 2; i < CPSW_MAX_ALE_ENTRIES; i++) {
+ /* First four entries are link address and broadcast. */
+ for (i = 10; i < CPSW_MAX_ALE_ENTRIES; i++) {
cpsw_ale_read_entry(sc, i, ale_entry);
- if (((ale_entry[1] >> 28) & 3) == 1 && /* Address entry */
- ((ale_entry[1] >> 8) & 1) == 1) { /* MCast link addr */
+ if ((ALE_TYPE(ale_entry) == ALE_TYPE_ADDR ||
+ ALE_TYPE(ale_entry) == ALE_TYPE_VLAN_ADDR) &&
+ ALE_MCAST(ale_entry) == 1) { /* MCast link addr */
ale_entry[0] = ale_entry[1] = ale_entry[2] = 0;
cpsw_ale_write_entry(sc, i, ale_entry);
}
}
- return CPSW_MAX_ALE_ENTRIES;
}
static int
-cpsw_ale_mc_entry_set(struct cpsw_softc *sc, uint8_t portmap, uint8_t *mac)
+cpsw_ale_mc_entry_set(struct cpsw_softc *sc, uint8_t portmap, int vlan,
+ uint8_t *mac)
{
int free_index = -1, matching_index = -1, i;
- uint32_t ale_entry[3];
+ uint32_t ale_entry[3], ale_type;
/* Find a matching entry or a free entry. */
- for (i = 0; i < CPSW_MAX_ALE_ENTRIES; i++) {
+ for (i = 10; i < CPSW_MAX_ALE_ENTRIES; i++) {
cpsw_ale_read_entry(sc, i, ale_entry);
/* Entry Type[61:60] is 0 for free entry */
- if (free_index < 0 && ((ale_entry[1] >> 28) & 3) == 0) {
+ if (free_index < 0 && ALE_TYPE(ale_entry) == 0)
free_index = i;
- }
if ((((ale_entry[1] >> 8) & 0xFF) == mac[0]) &&
(((ale_entry[1] >> 0) & 0xFF) == mac[1]) &&
@@ -2001,12 +2249,17 @@ cpsw_ale_mc_entry_set(struct cpsw_softc *sc, uint8_t portmap, uint8_t *mac)
i = free_index;
}
+ if (vlan != -1)
+ ale_type = ALE_TYPE_VLAN_ADDR << 28 | vlan << 16;
+ else
+ ale_type = ALE_TYPE_ADDR << 28;
+
/* Set MAC address */
ale_entry[0] = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
ale_entry[1] = mac[0] << 8 | mac[1];
- /* Entry type[61:60] is addr entry(1), Mcast fwd state[63:62] is fw(3)*/
- ale_entry[1] |= 0xd0 << 24;
+ /* Entry type[61:60] and Mcast fwd state[63:62] is fw(3). */
+ ale_entry[1] |= ALE_MCAST_FWD | ale_type;
/* Set portmask [68:66] */
ale_entry[2] = (portmap & 7) << 2;
@@ -2022,9 +2275,23 @@ cpsw_ale_dump_table(struct cpsw_softc *sc) {
uint32_t ale_entry[3];
for (i = 0; i < CPSW_MAX_ALE_ENTRIES; i++) {
cpsw_ale_read_entry(sc, i, ale_entry);
- if (ale_entry[0] || ale_entry[1] || ale_entry[2]) {
- printf("ALE[%4u] %08x %08x %08x ", i, ale_entry[0],
- ale_entry[1], ale_entry[2]);
+ switch (ALE_TYPE(ale_entry)) {
+ case ALE_TYPE_VLAN:
+ printf("ALE[%4u] %08x %08x %08x ", i, ale_entry[2],
+ ale_entry[1], ale_entry[0]);
+ printf("type: %u ", ALE_TYPE(ale_entry));
+ printf("vlan: %u ", ALE_VLAN(ale_entry));
+ printf("untag: %u ", ALE_VLAN_UNTAG(ale_entry));
+ printf("reg flood: %u ", ALE_VLAN_REGFLOOD(ale_entry));
+ printf("unreg flood: %u ", ALE_VLAN_UNREGFLOOD(ale_entry));
+ printf("members: %u ", ALE_VLAN_MEMBERS(ale_entry));
+ printf("\n");
+ break;
+ case ALE_TYPE_ADDR:
+ case ALE_TYPE_VLAN_ADDR:
+ printf("ALE[%4u] %08x %08x %08x ", i, ale_entry[2],
+ ale_entry[1], ale_entry[0]);
+ printf("type: %u ", ALE_TYPE(ale_entry));
printf("mac: %02x:%02x:%02x:%02x:%02x:%02x ",
(ale_entry[1] >> 8) & 0xFF,
(ale_entry[1] >> 0) & 0xFF,
@@ -2032,62 +2299,109 @@ cpsw_ale_dump_table(struct cpsw_softc *sc) {
(ale_entry[0] >>16) & 0xFF,
(ale_entry[0] >> 8) & 0xFF,
(ale_entry[0] >> 0) & 0xFF);
- printf(((ale_entry[1] >> 8) & 1) ? "mcast " : "ucast ");
- printf("type: %u ", (ale_entry[1] >> 28) & 3);
- printf("port: %u ", (ale_entry[2] >> 2) & 7);
+ printf(ALE_MCAST(ale_entry) ? "mcast " : "ucast ");
+ if (ALE_TYPE(ale_entry) == ALE_TYPE_VLAN_ADDR)
+ printf("vlan: %u ", ALE_VLAN(ale_entry));
+ printf("port: %u ", ALE_PORTS(ale_entry));
printf("\n");
+ break;
}
}
printf("\n");
}
static int
-cpsw_ale_update_addresses(struct cpsw_softc *sc, int purge)
+cpswp_ale_update_addresses(struct cpswp_softc *sc, int purge)
{
uint8_t *mac;
- uint32_t ale_entry[3];
- struct ifnet *ifp = sc->ifp;
+ uint32_t ale_entry[3], ale_type, portmask;
struct ifmultiaddr *ifma;
- int i;
- /* Route incoming packets for our MAC address to Port 0 (host). */
- /* For simplicity, keep this entry at table index 0 in the ALE. */
- if_addr_rlock(ifp);
- mac = LLADDR((struct sockaddr_dl *)ifp->if_addr->ifa_addr);
+ if (sc->swsc->dualemac) {
+ ale_type = ALE_TYPE_VLAN_ADDR << 28 | sc->vlan << 16;
+ portmask = 1 << (sc->unit + 1) | 1 << 0;
+ } else {
+ ale_type = ALE_TYPE_ADDR << 28;
+ portmask = 7;
+ }
+
+ /*
+ * Route incoming packets for our MAC address to Port 0 (host).
+ * For simplicity, keep this entry at table index 0 for port 1 and
+ * at index 2 for port 2 in the ALE.
+ */
+ if_addr_rlock(sc->ifp);
+ mac = LLADDR((struct sockaddr_dl *)sc->ifp->if_addr->ifa_addr);
ale_entry[0] = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
- ale_entry[1] = 0x10 << 24 | mac[0] << 8 | mac[1]; /* addr entry + mac */
+ ale_entry[1] = ale_type | mac[0] << 8 | mac[1]; /* addr entry + mac */
ale_entry[2] = 0; /* port = 0 */
- cpsw_ale_write_entry(sc, 0, ale_entry);
+ cpsw_ale_write_entry(sc->swsc, 0 + 2 * sc->unit, ale_entry);
- /* Set outgoing MAC Address for Ports 1 and 2. */
- for (i = 1; i < 3; ++i) {
- cpsw_write_4(sc, CPSW_PORT_P_SA_HI(i),
- mac[3] << 24 | mac[2] << 16 | mac[1] << 8 | mac[0]);
- cpsw_write_4(sc, CPSW_PORT_P_SA_LO(i),
- mac[5] << 8 | mac[4]);
- }
- if_addr_runlock(ifp);
+ /* Set outgoing MAC Address for slave port. */
+ cpsw_write_4(sc->swsc, CPSW_PORT_P_SA_HI(sc->unit + 1),
+ mac[3] << 24 | mac[2] << 16 | mac[1] << 8 | mac[0]);
+ cpsw_write_4(sc->swsc, CPSW_PORT_P_SA_LO(sc->unit + 1),
+ mac[5] << 8 | mac[4]);
+ if_addr_runlock(sc->ifp);
- /* Keep the broadcast address at table entry 1. */
+ /* Keep the broadcast address at table entry 1 (or 3). */
ale_entry[0] = 0xffffffff; /* Lower 32 bits of MAC */
- ale_entry[1] = 0xd000ffff; /* FW (3 << 30), Addr entry (1 << 24), upper 16 bits of Mac */
- ale_entry[2] = 0x0000001c; /* Forward to all ports */
- cpsw_ale_write_entry(sc, 1, ale_entry);
+ /* ALE_MCAST_FWD, Addr type, upper 16 bits of Mac */
+ ale_entry[1] = ALE_MCAST_FWD | ale_type | 0xffff;
+ ale_entry[2] = portmask << 2;
+ cpsw_ale_write_entry(sc->swsc, 1 + 2 * sc->unit, ale_entry);
/* SIOCDELMULTI doesn't specify the particular address
being removed, so we have to remove all and rebuild. */
if (purge)
- cpsw_ale_remove_all_mc_entries(sc);
+ cpsw_ale_remove_all_mc_entries(sc->swsc);
/* Set other multicast addrs desired. */
- if_maddr_rlock(ifp);
- TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
+ if_maddr_rlock(sc->ifp);
+ TAILQ_FOREACH(ifma, &sc->ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK)
continue;
- cpsw_ale_mc_entry_set(sc, 7,
+ cpsw_ale_mc_entry_set(sc->swsc, portmask, sc->vlan,
LLADDR((struct sockaddr_dl *)ifma->ifma_addr));
}
- if_maddr_runlock(ifp);
+ if_maddr_runlock(sc->ifp);
+
+ return (0);
+}
+
+static int
+cpsw_ale_update_vlan_table(struct cpsw_softc *sc, int vlan, int ports,
+ int untag, int mcregflood, int mcunregflood)
+{
+ int free_index, i, matching_index;
+ uint32_t ale_entry[3];
+
+ free_index = matching_index = -1;
+ /* Find a matching entry or a free entry. */
+ for (i = 5; i < CPSW_MAX_ALE_ENTRIES; i++) {
+ cpsw_ale_read_entry(sc, i, ale_entry);
+
+ /* Entry Type[61:60] is 0 for free entry */
+ if (free_index < 0 && ALE_TYPE(ale_entry) == 0)
+ free_index = i;
+
+ if (ALE_VLAN(ale_entry) == vlan) {
+ matching_index = i;
+ break;
+ }
+ }
+
+ if (matching_index < 0) {
+ if (free_index < 0)
+ return (-1);
+ i = free_index;
+ }
+
+ ale_entry[0] = (untag & 7) << 24 | (mcregflood & 7) << 16 |
+ (mcunregflood & 7) << 8 | (ports & 7);
+ ale_entry[1] = ALE_TYPE_VLAN << 28 | vlan << 16;
+ ale_entry[2] = 0;
+ cpsw_ale_write_entry(sc, i, ale_entry);
return (0);
}
@@ -2108,9 +2422,9 @@ cpsw_stats_dump(struct cpsw_softc *sc)
for (i = 0; i < CPSW_SYSCTL_COUNT; ++i) {
r = cpsw_read_4(sc, CPSW_STATS_OFFSET +
cpsw_stat_sysctls[i].reg);
- CPSW_DEBUGF(("%s: %ju + %u = %ju", cpsw_stat_sysctls[i].oid,
- (intmax_t)sc->shadow_stats[i], r,
- (intmax_t)sc->shadow_stats[i] + r));
+ CPSW_DEBUGF(sc, ("%s: %ju + %u = %ju", cpsw_stat_sysctls[i].oid,
+ (intmax_t)sc->shadow_stats[i], r,
+ (intmax_t)sc->shadow_stats[i] + r));
}
}
#endif
@@ -2121,13 +2435,14 @@ cpsw_stats_collect(struct cpsw_softc *sc)
int i;
uint32_t r;
- CPSW_DEBUGF(("Controller shadow statistics updated."));
+ CPSW_DEBUGF(sc, ("Controller shadow statistics updated."));
for (i = 0; i < CPSW_SYSCTL_COUNT; ++i) {
r = cpsw_read_4(sc, CPSW_STATS_OFFSET +
cpsw_stat_sysctls[i].reg);
sc->shadow_stats[i] += r;
- cpsw_write_4(sc, CPSW_STATS_OFFSET + cpsw_stat_sysctls[i].reg, r);
+ cpsw_write_4(sc, CPSW_STATS_OFFSET + cpsw_stat_sysctls[i].reg,
+ r);
}
}
@@ -2162,11 +2477,13 @@ cpsw_stat_attached(SYSCTL_HANDLER_ARGS)
static int
cpsw_stat_uptime(SYSCTL_HANDLER_ARGS)
{
- struct cpsw_softc *sc;
+ struct cpsw_softc *swsc;
+ struct cpswp_softc *sc;
struct bintime t;
unsigned result;
- sc = (struct cpsw_softc *)arg1;
+ swsc = arg1;
+ sc = device_get_softc(swsc->port[arg2].dev);
if (sc->ifp->if_drv_flags & IFF_DRV_RUNNING) {
getbinuptime(&t);
bintime_sub(&t, &sc->init_uptime);
@@ -2177,7 +2494,8 @@ cpsw_stat_uptime(SYSCTL_HANDLER_ARGS)
}
static void
-cpsw_add_queue_sysctls(struct sysctl_ctx_list *ctx, struct sysctl_oid *node, struct cpsw_queue *queue)
+cpsw_add_queue_sysctls(struct sysctl_ctx_list *ctx, struct sysctl_oid *node,
+ struct cpsw_queue *queue)
{
struct sysctl_oid_list *parent;
@@ -2210,7 +2528,8 @@ cpsw_add_queue_sysctls(struct sysctl_ctx_list *ctx, struct sysctl_oid *node, str
}
static void
-cpsw_add_watchdog_sysctls(struct sysctl_ctx_list *ctx, struct sysctl_oid *node, struct cpsw_softc *sc)
+cpsw_add_watchdog_sysctls(struct sysctl_ctx_list *ctx, struct sysctl_oid *node,
+ struct cpsw_softc *sc)
{
struct sysctl_oid_list *parent;
@@ -2226,18 +2545,35 @@ cpsw_add_sysctls(struct cpsw_softc *sc)
struct sysctl_ctx_list *ctx;
struct sysctl_oid *stats_node, *queue_node, *node;
struct sysctl_oid_list *parent, *stats_parent, *queue_parent;
+ struct sysctl_oid_list *ports_parent, *port_parent;
+ char port[16];
int i;
ctx = device_get_sysctl_ctx(sc->dev);
parent = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev));
+ SYSCTL_ADD_INT(ctx, parent, OID_AUTO, "debug",
+ CTLFLAG_RW, &sc->debug, 0, "Enable switch debug messages");
+
SYSCTL_ADD_PROC(ctx, parent, OID_AUTO, "attachedSecs",
CTLTYPE_UINT | CTLFLAG_RD, sc, 0, cpsw_stat_attached, "IU",
"Time since driver attach");
- SYSCTL_ADD_PROC(ctx, parent, OID_AUTO, "uptime",
- CTLTYPE_UINT | CTLFLAG_RD, sc, 0, cpsw_stat_uptime, "IU",
- "Seconds since driver init");
+ node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "ports",
+ CTLFLAG_RD, NULL, "CPSW Ports Statistics");
+ ports_parent = SYSCTL_CHILDREN(node);
+ for (i = 0; i < CPSW_PORTS; i++) {
+ if (!sc->dualemac && i != sc->active_slave)
+ continue;
+ port[0] = '0' + i;
+ port[1] = '\0';
+ node = SYSCTL_ADD_NODE(ctx, ports_parent, OID_AUTO,
+ port, CTLFLAG_RD, NULL, "CPSW Port Statistics");
+ port_parent = SYSCTL_CHILDREN(node);
+ SYSCTL_ADD_PROC(ctx, port_parent, OID_AUTO, "uptime",
+ CTLTYPE_UINT | CTLFLAG_RD, sc, i,
+ cpsw_stat_uptime, "IU", "Seconds since driver init");
+ }
stats_node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "stats",
CTLFLAG_RD, NULL, "CPSW Statistics");
@@ -2266,4 +2602,3 @@ cpsw_add_sysctls(struct cpsw_softc *sc)
CTLFLAG_RD, NULL, "Watchdog Statistics");
cpsw_add_watchdog_sysctls(ctx, node, sc);
}
-
diff --git a/sys/arm/ti/cpsw/if_cpswreg.h b/sys/arm/ti/cpsw/if_cpswreg.h
index 98d6033..bea6f19 100644
--- a/sys/arm/ti/cpsw/if_cpswreg.h
+++ b/sys/arm/ti/cpsw/if_cpswreg.h
@@ -29,103 +29,142 @@
#ifndef _IF_CPSWREG_H
#define _IF_CPSWREG_H
-#define CPSW_SS_OFFSET 0x0000
-#define CPSW_SS_IDVER (CPSW_SS_OFFSET + 0x00)
-#define CPSW_SS_SOFT_RESET (CPSW_SS_OFFSET + 0x08)
-#define CPSW_SS_STAT_PORT_EN (CPSW_SS_OFFSET + 0x0C)
-#define CPSW_SS_PTYPE (CPSW_SS_OFFSET + 0x10)
+#define CPSW_SS_OFFSET 0x0000
+#define CPSW_SS_IDVER (CPSW_SS_OFFSET + 0x00)
+#define CPSW_SS_SOFT_RESET (CPSW_SS_OFFSET + 0x08)
+#define CPSW_SS_STAT_PORT_EN (CPSW_SS_OFFSET + 0x0C)
+#define CPSW_SS_PTYPE (CPSW_SS_OFFSET + 0x10)
#define CPSW_SS_FLOW_CONTROL (CPSW_SS_OFFSET + 0x24)
-#define CPSW_PORT_OFFSET 0x0100
+#define CPSW_PORT_OFFSET 0x0100
#define CPSW_PORT_P_MAX_BLKS(p) (CPSW_PORT_OFFSET + 0x08 + ((p) * 0x100))
#define CPSW_PORT_P_BLK_CNT(p) (CPSW_PORT_OFFSET + 0x0C + ((p) * 0x100))
-#define CPSW_PORT_P_TX_PRI_MAP(p) (CPSW_PORT_OFFSET + 0x118 + ((p-1) * 0x100))
-#define CPSW_PORT_P0_CPDMA_TX_PRI_MAP (CPSW_PORT_OFFSET + 0x01C)
-#define CPSW_PORT_P0_CPDMA_RX_CH_MAP (CPSW_PORT_OFFSET + 0x020)
-#define CPSW_PORT_P_SA_LO(p) (CPSW_PORT_OFFSET + 0x120 + ((p-1) * 0x100))
-#define CPSW_PORT_P_SA_HI(p) (CPSW_PORT_OFFSET + 0x124 + ((p-1) * 0x100))
-
-#define CPSW_CPDMA_OFFSET 0x0800
-#define CPSW_CPDMA_TX_CONTROL (CPSW_CPDMA_OFFSET + 0x04)
-#define CPSW_CPDMA_TX_TEARDOWN (CPSW_CPDMA_OFFSET + 0x08)
-#define CPSW_CPDMA_RX_CONTROL (CPSW_CPDMA_OFFSET + 0x14)
-#define CPSW_CPDMA_RX_TEARDOWN (CPSW_CPDMA_OFFSET + 0x18)
-#define CPSW_CPDMA_SOFT_RESET (CPSW_CPDMA_OFFSET + 0x1c)
-#define CPSW_CPDMA_DMACONTROL (CPSW_CPDMA_OFFSET + 0x20)
-#define CPSW_CPDMA_DMASTATUS (CPSW_CPDMA_OFFSET + 0x24)
-#define CPSW_CPDMA_RX_BUFFER_OFFSET (CPSW_CPDMA_OFFSET + 0x28)
-#define CPSW_CPDMA_TX_INTSTAT_RAW (CPSW_CPDMA_OFFSET + 0x80)
-#define CPSW_CPDMA_TX_INTSTAT_MASKED (CPSW_CPDMA_OFFSET + 0x84)
-#define CPSW_CPDMA_TX_INTMASK_SET (CPSW_CPDMA_OFFSET + 0x88)
-#define CPSW_CPDMA_TX_INTMASK_CLEAR (CPSW_CPDMA_OFFSET + 0x8C)
-#define CPSW_CPDMA_CPDMA_EOI_VECTOR (CPSW_CPDMA_OFFSET + 0x94)
-#define CPSW_CPDMA_RX_INTSTAT_RAW (CPSW_CPDMA_OFFSET + 0xA0)
-#define CPSW_CPDMA_RX_INTSTAT_MASKED (CPSW_CPDMA_OFFSET + 0xA4)
-#define CPSW_CPDMA_RX_INTMASK_SET (CPSW_CPDMA_OFFSET + 0xA8)
-#define CPSW_CPDMA_RX_INTMASK_CLEAR (CPSW_CPDMA_OFFSET + 0xAc)
-#define CPSW_CPDMA_DMA_INTSTAT_RAW (CPSW_CPDMA_OFFSET + 0xB0)
-#define CPSW_CPDMA_DMA_INTSTAT_MASKED (CPSW_CPDMA_OFFSET + 0xB4)
-#define CPSW_CPDMA_DMA_INTMASK_SET (CPSW_CPDMA_OFFSET + 0xB8)
-#define CPSW_CPDMA_DMA_INTMASK_CLEAR (CPSW_CPDMA_OFFSET + 0xBC)
-#define CPSW_CPDMA_RX_FREEBUFFER(p) (CPSW_CPDMA_OFFSET + 0x0e0 + ((p) * 0x04))
-
-#define CPSW_STATS_OFFSET 0x0900
-
-#define CPSW_STATERAM_OFFSET 0x0A00
-#define CPSW_CPDMA_TX_HDP(p) (CPSW_STATERAM_OFFSET + 0x00 + ((p) * 0x04))
-#define CPSW_CPDMA_RX_HDP(p) (CPSW_STATERAM_OFFSET + 0x20 + ((p) * 0x04))
-#define CPSW_CPDMA_TX_CP(p) (CPSW_STATERAM_OFFSET + 0x40 + ((p) * 0x04))
-#define CPSW_CPDMA_RX_CP(p) (CPSW_STATERAM_OFFSET + 0x60 + ((p) * 0x04))
-
-#define CPSW_CPTS_OFFSET 0x0C00
-
-#define CPSW_ALE_OFFSET 0x0D00
-#define CPSW_ALE_CONTROL (CPSW_ALE_OFFSET + 0x08)
-#define CPSW_ALE_TBLCTL (CPSW_ALE_OFFSET + 0x20)
-#define CPSW_ALE_TBLW2 (CPSW_ALE_OFFSET + 0x34)
-#define CPSW_ALE_TBLW1 (CPSW_ALE_OFFSET + 0x38)
-#define CPSW_ALE_TBLW0 (CPSW_ALE_OFFSET + 0x3C)
-#define CPSW_ALE_PORTCTL(p) (CPSW_ALE_OFFSET + 0x40 + ((p) * 0x04))
+#define CPSW_PORT_P_VLAN(p) (CPSW_PORT_OFFSET + 0x14 + ((p) * 0x100))
+#define CPSW_PORT_P_TX_PRI_MAP(p) (CPSW_PORT_OFFSET + 0x118 + ((p-1) * 0x100))
+#define CPSW_PORT_P0_CPDMA_TX_PRI_MAP (CPSW_PORT_OFFSET + 0x01C)
+#define CPSW_PORT_P0_CPDMA_RX_CH_MAP (CPSW_PORT_OFFSET + 0x020)
+#define CPSW_PORT_P_SA_LO(p) (CPSW_PORT_OFFSET + 0x120 + ((p-1) * 0x100))
+#define CPSW_PORT_P_SA_HI(p) (CPSW_PORT_OFFSET + 0x124 + ((p-1) * 0x100))
+
+#define CPSW_CPDMA_OFFSET 0x0800
+#define CPSW_CPDMA_TX_CONTROL (CPSW_CPDMA_OFFSET + 0x04)
+#define CPSW_CPDMA_TX_TEARDOWN (CPSW_CPDMA_OFFSET + 0x08)
+#define CPSW_CPDMA_RX_CONTROL (CPSW_CPDMA_OFFSET + 0x14)
+#define CPSW_CPDMA_RX_TEARDOWN (CPSW_CPDMA_OFFSET + 0x18)
+#define CPSW_CPDMA_SOFT_RESET (CPSW_CPDMA_OFFSET + 0x1c)
+#define CPSW_CPDMA_DMACONTROL (CPSW_CPDMA_OFFSET + 0x20)
+#define CPSW_CPDMA_DMASTATUS (CPSW_CPDMA_OFFSET + 0x24)
+#define CPSW_CPDMA_RX_BUFFER_OFFSET (CPSW_CPDMA_OFFSET + 0x28)
+#define CPSW_CPDMA_TX_INTSTAT_RAW (CPSW_CPDMA_OFFSET + 0x80)
+#define CPSW_CPDMA_TX_INTSTAT_MASKED (CPSW_CPDMA_OFFSET + 0x84)
+#define CPSW_CPDMA_TX_INTMASK_SET (CPSW_CPDMA_OFFSET + 0x88)
+#define CPSW_CPDMA_TX_INTMASK_CLEAR (CPSW_CPDMA_OFFSET + 0x8C)
+#define CPSW_CPDMA_CPDMA_EOI_VECTOR (CPSW_CPDMA_OFFSET + 0x94)
+#define CPSW_CPDMA_RX_INTSTAT_RAW (CPSW_CPDMA_OFFSET + 0xA0)
+#define CPSW_CPDMA_RX_INTSTAT_MASKED (CPSW_CPDMA_OFFSET + 0xA4)
+#define CPSW_CPDMA_RX_INTMASK_SET (CPSW_CPDMA_OFFSET + 0xA8)
+#define CPSW_CPDMA_RX_INTMASK_CLEAR (CPSW_CPDMA_OFFSET + 0xAc)
+#define CPSW_CPDMA_DMA_INTSTAT_RAW (CPSW_CPDMA_OFFSET + 0xB0)
+#define CPSW_CPDMA_DMA_INTSTAT_MASKED (CPSW_CPDMA_OFFSET + 0xB4)
+#define CPSW_CPDMA_DMA_INTMASK_SET (CPSW_CPDMA_OFFSET + 0xB8)
+#define CPSW_CPDMA_DMA_INTMASK_CLEAR (CPSW_CPDMA_OFFSET + 0xBC)
+#define CPSW_CPDMA_RX_FREEBUFFER(p) (CPSW_CPDMA_OFFSET + 0x0e0 + ((p) * 0x04))
+
+#define CPSW_STATS_OFFSET 0x0900
+
+#define CPSW_STATERAM_OFFSET 0x0A00
+#define CPSW_CPDMA_TX_HDP(p) (CPSW_STATERAM_OFFSET + 0x00 + ((p) * 0x04))
+#define CPSW_CPDMA_RX_HDP(p) (CPSW_STATERAM_OFFSET + 0x20 + ((p) * 0x04))
+#define CPSW_CPDMA_TX_CP(p) (CPSW_STATERAM_OFFSET + 0x40 + ((p) * 0x04))
+#define CPSW_CPDMA_RX_CP(p) (CPSW_STATERAM_OFFSET + 0x60 + ((p) * 0x04))
+
+#define CPSW_CPTS_OFFSET 0x0C00
+
+#define CPSW_ALE_OFFSET 0x0D00
+#define CPSW_ALE_CONTROL (CPSW_ALE_OFFSET + 0x08)
+#define CPSW_ALE_CTL_ENABLE (1U << 31)
+#define CPSW_ALE_CTL_CLEAR_TBL (1 << 30)
+#define CPSW_ALE_CTL_BYPASS (1 << 4)
+#define CPSW_ALE_CTL_VLAN_AWARE (1 << 2)
+#define CPSW_ALE_TBLCTL (CPSW_ALE_OFFSET + 0x20)
+#define CPSW_ALE_TBLW2 (CPSW_ALE_OFFSET + 0x34)
+#define CPSW_ALE_TBLW1 (CPSW_ALE_OFFSET + 0x38)
+#define CPSW_ALE_TBLW0 (CPSW_ALE_OFFSET + 0x3C)
+#define ALE_MCAST(_a) ((_a[1] >> 8) & 1)
+#define ALE_MCAST_FWD (3 << 30)
+#define ALE_PORTS(_a) ((_a[2] >> 2) & 7)
+#define ALE_TYPE(_a) ((_a[1] >> 28) & 3)
+#define ALE_TYPE_ADDR 1
+#define ALE_TYPE_VLAN 2
+#define ALE_TYPE_VLAN_ADDR 3
+#define ALE_VLAN(_a) ((_a[1] >> 16) & 0xfff)
+#define ALE_VLAN_UNREGFLOOD(_a) ((_a[0] >> 8) & 7)
+#define ALE_VLAN_REGFLOOD(_a) ((_a[0] >> 16) & 7)
+#define ALE_VLAN_UNTAG(_a) ((_a[0] >> 24) & 7)
+#define ALE_VLAN_MEMBERS(_a) (_a[0] & 7)
+#define CPSW_ALE_PORTCTL(p) (CPSW_ALE_OFFSET + 0x40 + ((p) * 0x04))
/* SL1 is at 0x0D80, SL2 is at 0x0DC0 */
-#define CPSW_SL_OFFSET 0x0D80
-#define CPSW_SL_MACCONTROL(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x04)
-#define CPSW_SL_MACSTATUS(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x08)
-#define CPSW_SL_SOFT_RESET(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x0C)
-#define CPSW_SL_RX_MAXLEN(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x10)
-#define CPSW_SL_RX_PAUSE(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x18)
-#define CPSW_SL_TX_PAUSE(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x1C)
-#define CPSW_SL_RX_PRI_MAP(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x24)
-
-#define MDIO_OFFSET 0x1000
-#define MDIOCONTROL (MDIO_OFFSET + 0x04)
-#define MDIOUSERACCESS0 (MDIO_OFFSET + 0x80)
-#define MDIOUSERPHYSEL0 (MDIO_OFFSET + 0x84)
-
-#define CPSW_WR_OFFSET 0x1200
-#define CPSW_WR_SOFT_RESET (CPSW_WR_OFFSET + 0x04)
-#define CPSW_WR_CONTROL (CPSW_WR_OFFSET + 0x08)
-#define CPSW_WR_INT_CONTROL (CPSW_WR_OFFSET + 0x0c)
-#define CPSW_WR_C_RX_THRESH_EN(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x10)
-#define CPSW_WR_C_RX_EN(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x14)
-#define CPSW_WR_C_TX_EN(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x18)
-#define CPSW_WR_C_MISC_EN(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x1C)
-#define CPSW_WR_C_RX_THRESH_STAT(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x40)
-#define CPSW_WR_C_RX_STAT(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x44)
-#define CPSW_WR_C_TX_STAT(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x48)
-#define CPSW_WR_C_MISC_STAT(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x4C)
-
-#define CPSW_CPPI_RAM_OFFSET 0x2000
+#define CPSW_SL_OFFSET 0x0D80
+#define CPSW_SL_MACCONTROL(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x04)
+#define CPSW_SL_MACTL_IFCTL_B (1 << 16)
+#define CPSW_SL_MACTL_IFCTL_A (1 << 15)
+#define CPSW_SL_MACTL_GIG (1 << 7)
+#define CPSW_SL_MACTL_GMII_ENABLE (1 << 5)
+#define CPSW_SL_MACTL_FULLDUPLEX (1 << 0)
+#define CPSW_SL_MACSTATUS(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x08)
+#define CPSW_SL_SOFT_RESET(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x0C)
+#define CPSW_SL_RX_MAXLEN(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x10)
+#define CPSW_SL_RX_PAUSE(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x18)
+#define CPSW_SL_TX_PAUSE(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x1C)
+#define CPSW_SL_RX_PRI_MAP(p) (CPSW_SL_OFFSET + (0x40 * (p)) + 0x24)
+
+#define MDIO_OFFSET 0x1000
+#define MDIOCONTROL (MDIO_OFFSET + 0x04)
+#define MDIOCTL_ENABLE (1 << 30)
+#define MDIOCTL_FAULTENB (1 << 18)
+#define MDIOLINKINTRAW (MDIO_OFFSET + 0x10)
+#define MDIOLINKINTMASKED (MDIO_OFFSET + 0x14)
+#define MDIOUSERACCESS0 (MDIO_OFFSET + 0x80)
+#define MDIOUSERPHYSEL0 (MDIO_OFFSET + 0x84)
+#define MDIOUSERACCESS1 (MDIO_OFFSET + 0x88)
+#define MDIOUSERPHYSEL1 (MDIO_OFFSET + 0x8C)
+#define MDIO_PHYSEL_LINKINTENB (1 << 6)
+#define MDIO_PHYACCESS_GO (1U << 31)
+#define MDIO_PHYACCESS_WRITE (1 << 30)
+#define MDIO_PHYACCESS_ACK (1 << 29)
+
+#define CPSW_WR_OFFSET 0x1200
+#define CPSW_WR_SOFT_RESET (CPSW_WR_OFFSET + 0x04)
+#define CPSW_WR_CONTROL (CPSW_WR_OFFSET + 0x08)
+#define CPSW_WR_INT_CONTROL (CPSW_WR_OFFSET + 0x0c)
+#define CPSW_WR_C_RX_THRESH_EN(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x10)
+#define CPSW_WR_C_RX_EN(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x14)
+#define CPSW_WR_C_TX_EN(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x18)
+#define CPSW_WR_C_MISC_EN(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x1C)
+#define CPSW_WR_C_RX_THRESH_STAT(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x40)
+#define CPSW_WR_C_RX_STAT(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x44)
+#define CPSW_WR_C_TX_STAT(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x48)
+#define CPSW_WR_C_MISC_STAT(p) (CPSW_WR_OFFSET + (0x10 * (p)) + 0x4C)
+#define CPSW_WR_C_MISC_EVNT_PEND (1 << 4)
+#define CPSW_WR_C_MISC_STAT_PEND (1 << 3)
+#define CPSW_WR_C_MISC_HOST_PEND (1 << 2)
+#define CPSW_WR_C_MISC_MDIOLINK (1 << 1)
+#define CPSW_WR_C_MISC_MDIOUSER (1 << 0)
+
+#define CPSW_CPPI_RAM_OFFSET 0x2000
#define CPSW_CPPI_RAM_SIZE 0x2000
#define CPSW_MEMWINDOW_SIZE 0x4000
-#define CPDMA_BD_SOP (1<<15)
-#define CPDMA_BD_EOP (1<<14)
-#define CPDMA_BD_OWNER (1<<13)
-#define CPDMA_BD_EOQ (1<<12)
-#define CPDMA_BD_TDOWNCMPLT (1<<11)
-#define CPDMA_BD_PKT_ERR_MASK (3<< 4)
+#define CPDMA_BD_SOP (1 << 15)
+#define CPDMA_BD_EOP (1 << 14)
+#define CPDMA_BD_OWNER (1 << 13)
+#define CPDMA_BD_EOQ (1 << 12)
+#define CPDMA_BD_TDOWNCMPLT (1 << 11)
+#define CPDMA_BD_PKT_ERR_MASK (3 << 4)
+#define CPDMA_BD_TO_PORT (1 << 4)
+#define CPDMA_BD_PORT_MASK 3
struct cpsw_cpdma_bd {
volatile uint32_t next;
diff --git a/sys/arm/ti/cpsw/if_cpswvar.h b/sys/arm/ti/cpsw/if_cpswvar.h
index fbd7de5..adf2a37 100644
--- a/sys/arm/ti/cpsw/if_cpswvar.h
+++ b/sys/arm/ti/cpsw/if_cpswvar.h
@@ -29,19 +29,21 @@
#ifndef _IF_CPSWVAR_H
#define _IF_CPSWVAR_H
-#define CPSW_INTR_COUNT 4
+#define CPSW_PORTS 2
+#define CPSW_INTR_COUNT 4
/* MII BUS */
-#define CPSW_MIIBUS_RETRIES 5
-#define CPSW_MIIBUS_DELAY 1000
+#define CPSW_MIIBUS_RETRIES 5
+#define CPSW_MIIBUS_DELAY 1000
-#define CPSW_MAX_ALE_ENTRIES 1024
+#define CPSW_MAX_ALE_ENTRIES 1024
-#define CPSW_SYSCTL_COUNT 34
+#define CPSW_SYSCTL_COUNT 34
struct cpsw_slot {
uint32_t bd_offset; /* Offset of corresponding BD within CPPI RAM. */
bus_dmamap_t dmamap;
+ struct ifnet *ifp;
struct mbuf *mbuf;
STAILQ_ENTRY(cpsw_slot) next;
};
@@ -64,52 +66,43 @@ struct cpsw_queue {
int hdp_offset;
};
+struct cpsw_port {
+ device_t dev;
+ int phy;
+ int vlan;
+};
+
struct cpsw_softc {
- struct ifnet *ifp;
- phandle_t node;
device_t dev;
+ int active_slave;
+ int debug;
+ int dualemac;
+ phandle_t node;
struct bintime attach_uptime; /* system uptime when attach happened. */
- struct bintime init_uptime; /* system uptime when init happened. */
+ struct cpsw_port port[2];
- /* TODO: We should set up a child structure for each port;
- store mac, phy information, etc, in that structure. */
- uint8_t mac_addr[ETHER_ADDR_LEN];
+ /* RX and TX buffer tracking */
+ struct cpsw_queue rx, tx;
- device_t miibus;
- struct mii_data *mii;
/* We expect 1 memory resource and 4 interrupts from the device tree. */
- struct resource *mem_res;
int mem_rid;
+ struct resource *mem_res;
struct resource *irq_res[CPSW_INTR_COUNT];
+ void *ih_cookie[CPSW_INTR_COUNT];
- /* Interrupts get recorded here as we initialize them. */
- /* Interrupt teardown just walks this list. */
- struct {
- struct resource *res;
- void *ih_cookie;
- const char *description;
- } interrupts[CPSW_INTR_COUNT];
- int interrupt_count;
+ /* An mbuf full of nulls for TX padding. */
+ bus_dmamap_t null_mbuf_dmamap;
+ struct mbuf *null_mbuf;
+ bus_addr_t null_mbuf_paddr;
- uint32_t cpsw_if_flags;
- int cpsw_media_status;
+ bus_dma_tag_t mbuf_dtag;
struct {
int resets;
int timer;
- struct callout callout;
+ struct callout callout;
} watchdog;
- bus_dma_tag_t mbuf_dtag;
-
- /* An mbuf full of nulls for TX padding. */
- bus_dmamap_t null_mbuf_dmamap;
- struct mbuf *null_mbuf;
- bus_addr_t null_mbuf_paddr;
-
- /* RX and TX buffer tracking */
- struct cpsw_queue rx, tx;
-
/* 64-bit versions of 32-bit hardware statistics counters */
uint64_t shadow_stats[CPSW_SYSCTL_COUNT];
@@ -123,4 +116,23 @@ struct cpsw_softc {
struct cpsw_slots avail;
};
+struct cpswp_softc {
+ device_t dev;
+ device_t miibus;
+ device_t pdev;
+ int media_status;
+ int unit;
+ int vlan;
+ struct bintime init_uptime; /* system uptime when init happened. */
+ struct callout mii_callout;
+ struct cpsw_softc *swsc;
+ struct ifnet *ifp;
+ struct mii_data *mii;
+ struct mtx lock;
+ uint32_t if_flags;
+ uint32_t phy;
+ uint32_t phyaccess;
+ uint32_t physel;
+};
+
#endif /*_IF_CPSWVAR_H */
diff --git a/sys/arm/ti/files.ti b/sys/arm/ti/files.ti
index d4daab1..6f571c6 100644
--- a/sys/arm/ti/files.ti
+++ b/sys/arm/ti/files.ti
@@ -18,6 +18,7 @@ arm/ti/ti_gpio.c optional gpio
arm/ti/ti_gpio_if.m optional gpio
arm/ti/ti_i2c.c optional ti_i2c
arm/ti/ti_sdhci.c optional sdhci
+arm/ti/ti_spi.c optional ti_spi
dev/uart/uart_dev_ti8250.c optional uart
dev/uart/uart_dev_ns8250.c optional uart
diff --git a/sys/arm/ti/omap4/omap4_gpio.c b/sys/arm/ti/omap4/omap4_gpio.c
index a261116..dd38f4a 100644
--- a/sys/arm/ti/omap4/omap4_gpio.c
+++ b/sys/arm/ti/omap4/omap4_gpio.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/gpio.h>
#include <machine/bus.h>
+#include <machine/intr.h>
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
diff --git a/sys/arm/ti/omap4/omap4_wugen.c b/sys/arm/ti/omap4/omap4_wugen.c
index 2b24eaf..f2bed61 100644
--- a/sys/arm/ti/omap4/omap4_wugen.c
+++ b/sys/arm/ti/omap4/omap4_wugen.c
@@ -57,44 +57,64 @@ struct omap4_wugen_sc {
};
static int
-omap4_wugen_register(device_t dev, struct intr_irqsrc *isrc,
- boolean_t *is_percpu)
+omap4_wugen_alloc_intr(device_t dev, struct intr_irqsrc *isrc,
+ struct resource *res, struct intr_map_data *data)
{
struct omap4_wugen_sc *sc = device_get_softc(dev);
- return (PIC_REGISTER(sc->sc_parent, isrc, is_percpu));
+ return (PIC_ALLOC_INTR(sc->sc_parent, isrc, res, data));
}
-static int
-omap4_wugen_unregister(device_t dev, struct intr_irqsrc *isrc)
+static void
+omap4_wugen_disable_intr(device_t dev, struct intr_irqsrc *isrc)
{
struct omap4_wugen_sc *sc = device_get_softc(dev);
- return (PIC_UNREGISTER(sc->sc_parent, isrc));
+ PIC_DISABLE_INTR(sc->sc_parent, isrc);
}
static void
-omap4_wugen_enable_source(device_t dev, struct intr_irqsrc *isrc)
+omap4_wugen_enable_intr(device_t dev, struct intr_irqsrc *isrc)
{
struct omap4_wugen_sc *sc = device_get_softc(dev);
- PIC_ENABLE_SOURCE(sc->sc_parent, isrc);
+ PIC_ENABLE_INTR(sc->sc_parent, isrc);
}
-static void
-omap4_wugen_disable_source(device_t dev, struct intr_irqsrc *isrc)
+static int
+omap4_wugen_map_intr(device_t dev, struct intr_map_data *data,
+ struct intr_irqsrc **isrcp)
{
struct omap4_wugen_sc *sc = device_get_softc(dev);
- PIC_DISABLE_SOURCE(sc->sc_parent, isrc);
+ return (PIC_MAP_INTR(sc->sc_parent, data, isrcp));
}
-static void
-omap4_wugen_enable_intr(device_t dev, struct intr_irqsrc *isrc)
+static int
+omap4_wugen_release_intr(device_t dev, struct intr_irqsrc *isrc,
+ struct resource *res, struct intr_map_data *data)
{
struct omap4_wugen_sc *sc = device_get_softc(dev);
- PIC_ENABLE_INTR(sc->sc_parent, isrc);
+ return (PIC_RELEASE_INTR(sc->sc_parent, isrc, res, data));
+}
+
+static int
+omap4_wugen_setup_intr(device_t dev, struct intr_irqsrc *isrc,
+ struct resource *res, struct intr_map_data *data)
+{
+ struct omap4_wugen_sc *sc = device_get_softc(dev);
+
+ return (PIC_SETUP_INTR(sc->sc_parent, isrc, res, data));
+}
+
+static int
+omap4_wugen_teardown_intr(device_t dev, struct intr_irqsrc *isrc,
+ struct resource *res, struct intr_map_data *data)
+{
+ struct omap4_wugen_sc *sc = device_get_softc(dev);
+
+ return (PIC_TEARDOWN_INTR(sc->sc_parent, isrc, res, data));
}
static void
@@ -124,11 +144,11 @@ omap4_wugen_post_filter(device_t dev, struct intr_irqsrc *isrc)
#ifdef SMP
static int
-omap4_wugen_bind(device_t dev, struct intr_irqsrc *isrc)
+omap4_wugen_bind_intr(device_t dev, struct intr_irqsrc *isrc)
{
struct omap4_wugen_sc *sc = device_get_softc(dev);
- return (PIC_BIND(sc->sc_parent, isrc));
+ return (PIC_BIND_INTR(sc->sc_parent, isrc));
}
#endif
@@ -207,16 +227,18 @@ static device_method_t omap4_wugen_methods[] = {
DEVMETHOD(device_detach, omap4_wugen_detach),
/* Interrupt controller interface */
- DEVMETHOD(pic_register, omap4_wugen_register),
- DEVMETHOD(pic_unregister, omap4_wugen_unregister),
- DEVMETHOD(pic_enable_source, omap4_wugen_enable_source),
- DEVMETHOD(pic_disable_source, omap4_wugen_disable_source),
+ DEVMETHOD(pic_alloc_intr, omap4_wugen_alloc_intr),
+ DEVMETHOD(pic_disable_intr, omap4_wugen_disable_intr),
DEVMETHOD(pic_enable_intr, omap4_wugen_enable_intr),
+ DEVMETHOD(pic_map_intr, omap4_wugen_map_intr),
+ DEVMETHOD(pic_release_intr, omap4_wugen_release_intr),
+ DEVMETHOD(pic_setup_intr, omap4_wugen_setup_intr),
+ DEVMETHOD(pic_teardown_intr, omap4_wugen_teardown_intr),
DEVMETHOD(pic_pre_ithread, omap4_wugen_pre_ithread),
DEVMETHOD(pic_post_ithread, omap4_wugen_post_ithread),
DEVMETHOD(pic_post_filter, omap4_wugen_post_filter),
#ifdef SMP
- DEVMETHOD(pic_bind, omap4_wugen_bind),
+ DEVMETHOD(pic_bind_intr, omap4_wugen_bind_intr),
#endif
DEVMETHOD_END
};
diff --git a/sys/arm/ti/ti_adc.c b/sys/arm/ti/ti_adc.c
index d65afc6..f11091f 100644
--- a/sys/arm/ti/ti_adc.c
+++ b/sys/arm/ti/ti_adc.c
@@ -161,11 +161,9 @@ ti_adc_input_setup(struct ti_adc_softc *sc, int32_t ain)
/* Set the negative voltage reference. */
val &= ~ADC_STEP_RFM_MSK;
- val |= ADC_STEP_RFM_VREFN << ADC_STEP_RFM_SHIFT;
/* Set the positive voltage reference. */
val &= ~ADC_STEP_RFP_MSK;
- val |= ADC_STEP_RFP_VREFP << ADC_STEP_RFP_SHIFT;
/* Set the samples average. */
val &= ~ADC_STEP_AVG_MSK;
@@ -450,11 +448,9 @@ ti_adc_idlestep_init(struct ti_adc_softc *sc)
/* Set the negative voltage reference. */
val &= ~ADC_STEP_RFM_MSK;
- val |= ADC_STEP_RFM_VREFN << ADC_STEP_RFM_SHIFT;
/* Set the positive voltage reference. */
val &= ~ADC_STEP_RFP_MSK;
- val |= ADC_STEP_RFP_VREFP << ADC_STEP_RFP_SHIFT;
/* Connect the input to VREFN. */
val &= ~ADC_STEP_INP_MSK;
@@ -484,6 +480,11 @@ ti_adc_attach(device_t dev)
sc = device_get_softc(dev);
sc->sc_dev = dev;
+ /* Activate the ADC_TSC module. */
+ err = ti_prcm_clk_enable(TSC_ADC_CLK);
+ if (err)
+ return (err);
+
rid = 0;
sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
RF_ACTIVE);
@@ -509,11 +510,6 @@ ti_adc_attach(device_t dev)
return (ENXIO);
}
- /* Activate the ADC_TSC module. */
- err = ti_prcm_clk_enable(TSC_ADC_CLK);
- if (err)
- return (err);
-
/* Check the ADC revision. */
rev = ADC_READ4(sc, ADC_REVISION);
device_printf(dev,
diff --git a/sys/arm/ti/ti_gpio.c b/sys/arm/ti/ti_gpio.c
index 2818bab..633fbf0 100644
--- a/sys/arm/ti/ti_gpio.c
+++ b/sys/arm/ti/ti_gpio.c
@@ -33,12 +33,15 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_platform.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
+#include <sys/proc.h>
#include <sys/rman.h>
#include <sys/lock.h>
#include <sys/mutex.h>
@@ -46,6 +49,7 @@ __FBSDID("$FreeBSD$");
#include <sys/interrupt.h>
#include <machine/bus.h>
+#include <machine/intr.h>
#include <machine/resource.h>
#include <arm/ti/ti_cpuid.h>
@@ -62,6 +66,9 @@ __FBSDID("$FreeBSD$");
#include "gpio_if.h"
#include "ti_gpio_if.h"
+#ifdef ARM_INTRNG
+#include "pic_if.h"
+#endif
#if !defined(SOC_OMAP4) && !defined(SOC_TI_AM335X)
#error "Unknown SoC"
@@ -72,12 +79,12 @@ __FBSDID("$FreeBSD$");
#define TI_GPIO_SYSCONFIG 0x0010
#define TI_GPIO_IRQSTATUS_RAW_0 0x0024
#define TI_GPIO_IRQSTATUS_RAW_1 0x0028
-#define TI_GPIO_IRQSTATUS_0 0x002C
-#define TI_GPIO_IRQSTATUS_1 0x0030
-#define TI_GPIO_IRQSTATUS_SET_0 0x0034
-#define TI_GPIO_IRQSTATUS_SET_1 0x0038
-#define TI_GPIO_IRQSTATUS_CLR_0 0x003C
-#define TI_GPIO_IRQSTATUS_CLR_1 0x0040
+#define TI_GPIO_IRQSTATUS_0 0x002C /* writing a 0 has no effect */
+#define TI_GPIO_IRQSTATUS_1 0x0030 /* writing a 0 has no effect */
+#define TI_GPIO_IRQSTATUS_SET_0 0x0034 /* writing a 0 has no effect */
+#define TI_GPIO_IRQSTATUS_SET_1 0x0038 /* writing a 0 has no effect */
+#define TI_GPIO_IRQSTATUS_CLR_0 0x003C /* writing a 0 has no effect */
+#define TI_GPIO_IRQSTATUS_CLR_1 0x0040 /* writing a 0 has no effect */
#define TI_GPIO_IRQWAKEN_0 0x0044
#define TI_GPIO_IRQWAKEN_1 0x0048
#define TI_GPIO_SYSSTATUS 0x0114
@@ -90,10 +97,10 @@ __FBSDID("$FreeBSD$");
#define TI_GPIO_OE 0x0134
#define TI_GPIO_DATAIN 0x0138
#define TI_GPIO_DATAOUT 0x013C
-#define TI_GPIO_LEVELDETECT0 0x0140
-#define TI_GPIO_LEVELDETECT1 0x0144
-#define TI_GPIO_RISINGDETECT 0x0148
-#define TI_GPIO_FALLINGDETECT 0x014C
+#define TI_GPIO_LEVELDETECT0 0x0140 /* RW register */
+#define TI_GPIO_LEVELDETECT1 0x0144 /* RW register */
+#define TI_GPIO_RISINGDETECT 0x0148 /* RW register */
+#define TI_GPIO_FALLINGDETECT 0x014C /* RW register */
#define TI_GPIO_DEBOUNCENABLE 0x0150
#define TI_GPIO_DEBOUNCINGTIME 0x0154
#define TI_GPIO_CLEARWKUPENA 0x0180
@@ -111,8 +118,14 @@ __FBSDID("$FreeBSD$");
#define PINS_PER_BANK 32
#define TI_GPIO_MASK(p) (1U << ((p) % PINS_PER_BANK))
+static int ti_gpio_intr(void *arg);
static int ti_gpio_detach(device_t);
+#ifdef ARM_INTRNG
+static int ti_gpio_pic_attach(struct ti_gpio_softc *sc);
+static int ti_gpio_pic_detach(struct ti_gpio_softc *sc);
+#endif
+
static u_int
ti_first_gpio_bank(void)
{
@@ -533,6 +546,7 @@ ti_gpio_pin_toggle(device_t dev, uint32_t pin)
return (0);
}
+#ifndef ARM_INTRNG
/**
* ti_gpio_intr - ISR for all GPIO modules
* @arg: the soft context pointer
@@ -567,6 +581,7 @@ ti_gpio_intr(void *arg)
return (FILTER_HANDLED);
}
+#endif
static int
ti_gpio_bank_init(device_t dev)
@@ -640,7 +655,9 @@ static int
ti_gpio_attach(device_t dev)
{
struct ti_gpio_softc *sc;
+#ifndef ARM_INTRNG
unsigned int i;
+#endif
int err;
sc = device_get_softc(dev);
@@ -679,6 +696,13 @@ ti_gpio_attach(device_t dev)
return (ENXIO);
}
+#ifdef ARM_INTRNG
+ if (ti_gpio_pic_attach(sc) != 0) {
+ device_printf(dev, "WARNING: unable to attach PIC\n");
+ ti_gpio_detach(dev);
+ return (ENXIO);
+ }
+#else
/*
* Initialize the interrupt settings. The default is active-low
* interrupts.
@@ -699,7 +723,7 @@ ti_gpio_attach(device_t dev)
sc->sc_mask_args = malloc(sizeof(struct ti_gpio_mask_arg) * sc->sc_maxpin,
M_DEVBUF, M_WAITOK | M_ZERO);
-
+#endif
/* We need to go through each block and ensure the clocks are running and
* the module is enabled. It might be better to do this only when the
* pins are configured which would result in less power used if the GPIO
@@ -747,6 +771,10 @@ ti_gpio_detach(device_t dev)
if (sc->sc_mem_res != NULL)
ti_gpio_intr_clr(sc, 0xffffffff);
gpiobus_detach_bus(dev);
+#ifdef ARM_INTRNG
+ if (sc->sc_isrcs != NULL)
+ ti_gpio_pic_detach(sc);
+#else
if (sc->sc_events)
free(sc->sc_events, M_DEVBUF);
if (sc->sc_mask_args)
@@ -755,6 +783,7 @@ ti_gpio_detach(device_t dev)
free(sc->sc_irq_polarity, M_DEVBUF);
if (sc->sc_irq_trigger)
free(sc->sc_irq_trigger, M_DEVBUF);
+#endif
/* Release the memory and IRQ resources. */
if (sc->sc_irq_hdl) {
bus_teardown_intr(dev, sc->sc_irq_res,
@@ -769,6 +798,282 @@ ti_gpio_detach(device_t dev)
return (0);
}
+#ifdef ARM_INTRNG
+static inline void
+ti_gpio_rwreg_set(struct ti_gpio_softc *sc, uint32_t reg, uint32_t mask)
+{
+
+ ti_gpio_write_4(sc, reg, ti_gpio_read_4(sc, reg) | mask);
+}
+
+static inline void
+ti_gpio_rwreg_clr(struct ti_gpio_softc *sc, uint32_t reg, uint32_t mask)
+{
+
+ ti_gpio_write_4(sc, reg, ti_gpio_read_4(sc, reg) & ~mask);
+}
+
+static inline void
+ti_gpio_isrc_mask(struct ti_gpio_softc *sc, struct ti_gpio_irqsrc *tgi)
+{
+
+ /* Writing a 0 has no effect. */
+ ti_gpio_intr_clr(sc, tgi->tgi_mask);
+}
+
+static inline void
+ti_gpio_isrc_unmask(struct ti_gpio_softc *sc, struct ti_gpio_irqsrc *tgi)
+{
+
+ /* Writing a 0 has no effect. */
+ ti_gpio_intr_set(sc, tgi->tgi_mask);
+}
+
+static inline void
+ti_gpio_isrc_eoi(struct ti_gpio_softc *sc, struct ti_gpio_irqsrc *tgi)
+{
+
+ /* Writing a 0 has no effect. */
+ ti_gpio_intr_ack(sc, tgi->tgi_mask);
+}
+
+static inline bool
+ti_gpio_isrc_is_level(struct ti_gpio_irqsrc *tgi)
+{
+
+ return (tgi->tgi_cfgreg == TI_GPIO_LEVELDETECT0 ||
+ tgi->tgi_cfgreg == TI_GPIO_LEVELDETECT1);
+}
+
+static int
+ti_gpio_intr(void *arg)
+{
+ u_int irq;
+ uint32_t reg;
+ struct ti_gpio_softc *sc;
+ struct trapframe *tf;
+ struct ti_gpio_irqsrc *tgi;
+
+ sc = (struct ti_gpio_softc *)arg;
+ tf = curthread->td_intr_frame;
+
+ reg = ti_gpio_intr_status(sc);
+ for (irq = 0; irq < sc->sc_maxpin; irq++) {
+ tgi = &sc->sc_isrcs[irq];
+ if ((reg & tgi->tgi_mask) == 0)
+ continue;
+ if (!ti_gpio_isrc_is_level(tgi))
+ ti_gpio_isrc_eoi(sc, tgi);
+ if (intr_isrc_dispatch(&tgi->tgi_isrc, tf) != 0) {
+ ti_gpio_isrc_mask(sc, tgi);
+ if (ti_gpio_isrc_is_level(tgi))
+ ti_gpio_isrc_eoi(sc, tgi);
+ device_printf(sc->sc_dev, "Stray irq %u disabled\n",
+ irq);
+ }
+ }
+ return (FILTER_HANDLED);
+}
+
+static int
+ti_gpio_pic_attach(struct ti_gpio_softc *sc)
+{
+ int error;
+ uint32_t irq;
+ const char *name;
+
+ sc->sc_isrcs = malloc(sizeof(*sc->sc_isrcs) * sc->sc_maxpin, M_DEVBUF,
+ M_WAITOK | M_ZERO);
+
+ name = device_get_nameunit(sc->sc_dev);
+ for (irq = 0; irq < sc->sc_maxpin; irq++) {
+ sc->sc_isrcs[irq].tgi_irq = irq;
+ sc->sc_isrcs[irq].tgi_mask = TI_GPIO_MASK(irq);
+ sc->sc_isrcs[irq].tgi_cfgreg = 0;
+
+ error = intr_isrc_register(&sc->sc_isrcs[irq].tgi_isrc,
+ sc->sc_dev, 0, "%s,%u", name, irq);
+ if (error != 0)
+ return (error); /* XXX deregister ISRCs */
+ }
+ return (intr_pic_register(sc->sc_dev,
+ OF_xref_from_node(ofw_bus_get_node(sc->sc_dev))));
+}
+
+static int
+ti_gpio_pic_detach(struct ti_gpio_softc *sc)
+{
+
+ /*
+ * There has not been established any procedure yet
+ * how to detach PIC from living system correctly.
+ */
+ device_printf(sc->sc_dev, "%s: not implemented yet\n", __func__);
+ return (EBUSY);
+}
+
+static void
+ti_gpio_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct ti_gpio_softc *sc = device_get_softc(dev);
+ struct ti_gpio_irqsrc *tgi = (struct ti_gpio_irqsrc *)isrc;
+
+ ti_gpio_isrc_mask(sc, tgi);
+}
+
+static void
+ti_gpio_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct ti_gpio_softc *sc = device_get_softc(dev);
+ struct ti_gpio_irqsrc *tgi = (struct ti_gpio_irqsrc *)isrc;
+
+ arm_irq_memory_barrier(tgi->tgi_irq);
+ ti_gpio_isrc_unmask(sc, tgi);
+}
+
+static int
+ti_gpio_pic_map_fdt(struct ti_gpio_softc *sc, u_int ncells, pcell_t *cells,
+ u_int *irqp, uint32_t *regp)
+{
+ uint32_t reg;
+
+ /*
+ * The first cell is the interrupt number.
+ * The second cell is used to specify flags:
+ * bits[3:0] trigger type and level flags:
+ * 1 = low-to-high edge triggered.
+ * 2 = high-to-low edge triggered.
+ * 4 = active high level-sensitive.
+ * 8 = active low level-sensitive.
+ */
+ if (ncells != 2 || cells[0] >= sc->sc_maxpin)
+ return (EINVAL);
+
+ /*
+ * All interrupt types could be set for an interrupt at one moment.
+ * At least, the combination of 'low-to-high' and 'high-to-low' edge
+ * triggered interrupt types can make a sense. However, no combo is
+ * supported now.
+ */
+ if (cells[1] == 1)
+ reg = TI_GPIO_RISINGDETECT;
+ else if (cells[1] == 2)
+ reg = TI_GPIO_FALLINGDETECT;
+ else if (cells[1] == 4)
+ reg = TI_GPIO_LEVELDETECT1;
+ else if (cells[1] == 8)
+ reg = TI_GPIO_LEVELDETECT0;
+ else
+ return (EINVAL);
+
+ *irqp = cells[0];
+ if (regp != NULL)
+ *regp = reg;
+ return (0);
+}
+
+static int
+ti_gpio_pic_map_intr(device_t dev, struct intr_map_data *data,
+ struct intr_irqsrc **isrcp)
+{
+ int error;
+ u_int irq;
+ struct ti_gpio_softc *sc;
+
+ if (data->type != INTR_MAP_DATA_FDT)
+ return (ENOTSUP);
+
+ sc = device_get_softc(dev);
+ error = ti_gpio_pic_map_fdt(sc, data->fdt.ncells, data->fdt.cells, &irq,
+ NULL);
+ if (error == 0)
+ *isrcp = &sc->sc_isrcs[irq].tgi_isrc;
+ return (error);
+}
+
+static void
+ti_gpio_pic_post_filter(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct ti_gpio_softc *sc = device_get_softc(dev);
+ struct ti_gpio_irqsrc *tgi = (struct ti_gpio_irqsrc *)isrc;
+
+ if (ti_gpio_isrc_is_level(tgi))
+ ti_gpio_isrc_eoi(sc, tgi);
+}
+
+static void
+ti_gpio_pic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
+{
+
+ ti_gpio_pic_enable_intr(dev, isrc);
+}
+
+static void
+ti_gpio_pic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct ti_gpio_softc *sc = device_get_softc(dev);
+ struct ti_gpio_irqsrc *tgi = (struct ti_gpio_irqsrc *)isrc;
+
+ ti_gpio_isrc_mask(sc, tgi);
+ if (ti_gpio_isrc_is_level(tgi))
+ ti_gpio_isrc_eoi(sc, tgi);
+}
+
+static int
+ti_gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc,
+ struct resource *res, struct intr_map_data *data)
+{
+ u_int irq;
+ uint32_t cfgreg;
+ struct ti_gpio_softc *sc;
+ struct ti_gpio_irqsrc *tgi;
+
+ if (data == NULL || data->type != INTR_MAP_DATA_FDT)
+ return (ENOTSUP);
+
+ sc = device_get_softc(dev);
+ tgi = (struct ti_gpio_irqsrc *)isrc;
+
+ /* Get and check config for an interrupt. */
+ if (ti_gpio_pic_map_fdt(sc, data->fdt.ncells, data->fdt.cells, &irq,
+ &cfgreg) != 0 || tgi->tgi_irq != irq)
+ return (EINVAL);
+
+ /*
+ * If this is a setup for another handler,
+ * only check that its configuration match.
+ */
+ if (isrc->isrc_handlers != 0)
+ return (tgi->tgi_cfgreg == cfgreg ? 0 : EINVAL);
+
+ TI_GPIO_LOCK(sc);
+ ti_gpio_rwreg_clr(sc, TI_GPIO_RISINGDETECT, tgi->tgi_mask);
+ ti_gpio_rwreg_clr(sc, TI_GPIO_FALLINGDETECT, tgi->tgi_mask);
+ ti_gpio_rwreg_clr(sc, TI_GPIO_LEVELDETECT1, tgi->tgi_mask);
+ ti_gpio_rwreg_clr(sc, TI_GPIO_LEVELDETECT0, tgi->tgi_mask);
+ tgi->tgi_cfgreg = cfgreg;
+ ti_gpio_rwreg_set(sc, cfgreg, tgi->tgi_mask);
+ TI_GPIO_UNLOCK(sc);
+ return (0);
+}
+
+static int
+ti_gpio_pic_teardown_intr(device_t dev, struct intr_irqsrc *isrc,
+ struct resource *res, struct intr_map_data *data)
+{
+ struct ti_gpio_softc *sc = device_get_softc(dev);
+ struct ti_gpio_irqsrc *tgi = (struct ti_gpio_irqsrc *)isrc;
+
+ if (isrc->isrc_handlers == 0) {
+ TI_GPIO_LOCK(sc);
+ ti_gpio_rwreg_clr(sc, tgi->tgi_cfgreg, tgi->tgi_mask);
+ tgi->tgi_cfgreg = 0;
+ TI_GPIO_UNLOCK(sc);
+ }
+ return (0);
+}
+
+#else
static uint32_t
ti_gpio_intr_reg(struct ti_gpio_softc *sc, int irq)
{
@@ -970,6 +1275,7 @@ ti_gpio_teardown_intr(device_t dev, device_t child, struct resource *ires,
return (err);
}
+#endif
static phandle_t
ti_gpio_get_node(device_t bus, device_t dev)
@@ -994,12 +1300,24 @@ static device_method_t ti_gpio_methods[] = {
DEVMETHOD(gpio_pin_set, ti_gpio_pin_set),
DEVMETHOD(gpio_pin_toggle, ti_gpio_pin_toggle),
+#ifdef ARM_INTRNG
+ /* Interrupt controller interface */
+ DEVMETHOD(pic_disable_intr, ti_gpio_pic_disable_intr),
+ DEVMETHOD(pic_enable_intr, ti_gpio_pic_enable_intr),
+ DEVMETHOD(pic_map_intr, ti_gpio_pic_map_intr),
+ DEVMETHOD(pic_setup_intr, ti_gpio_pic_setup_intr),
+ DEVMETHOD(pic_teardown_intr, ti_gpio_pic_teardown_intr),
+ DEVMETHOD(pic_post_filter, ti_gpio_pic_post_filter),
+ DEVMETHOD(pic_post_ithread, ti_gpio_pic_post_ithread),
+ DEVMETHOD(pic_pre_ithread, ti_gpio_pic_pre_ithread),
+#else
/* Bus interface */
DEVMETHOD(bus_activate_resource, ti_gpio_activate_resource),
DEVMETHOD(bus_deactivate_resource, ti_gpio_deactivate_resource),
DEVMETHOD(bus_config_intr, ti_gpio_config_intr),
DEVMETHOD(bus_setup_intr, ti_gpio_setup_intr),
DEVMETHOD(bus_teardown_intr, ti_gpio_teardown_intr),
+#endif
/* ofw_bus interface */
DEVMETHOD(ofw_bus_get_node, ti_gpio_get_node),
diff --git a/sys/arm/ti/ti_gpio.h b/sys/arm/ti/ti_gpio.h
index 6bd53c8..f16728b 100644
--- a/sys/arm/ti/ti_gpio.h
+++ b/sys/arm/ti/ti_gpio.h
@@ -39,10 +39,19 @@
*/
#define MAX_GPIO_INTRS 8
+#ifndef ARM_INTRNG
struct ti_gpio_mask_arg {
void *softc;
int pin;
};
+#else
+struct ti_gpio_irqsrc {
+ struct intr_irqsrc tgi_isrc;
+ u_int tgi_irq;
+ uint32_t tgi_mask;
+ uint32_t tgi_cfgreg;
+};
+#endif
/**
* Structure that stores the driver context.
@@ -52,11 +61,11 @@ struct ti_gpio_mask_arg {
struct ti_gpio_softc {
device_t sc_dev;
device_t sc_busdev;
-
+#ifndef ARM_INTRNG
/* Interrupt trigger type and level. */
enum intr_trigger *sc_irq_trigger;
enum intr_polarity *sc_irq_polarity;
-
+#endif
int sc_bank;
int sc_maxpin;
struct mtx sc_mtx;
@@ -65,11 +74,13 @@ struct ti_gpio_softc {
struct resource *sc_mem_res;
int sc_irq_rid;
struct resource *sc_irq_res;
-
+#ifndef ARM_INTRNG
/* Interrupt events. */
struct intr_event **sc_events;
struct ti_gpio_mask_arg *sc_mask_args;
-
+#else
+ struct ti_gpio_irqsrc *sc_isrcs;
+#endif
/* The handle for the register IRQ handlers. */
void *sc_irq_hdl;
};
diff --git a/sys/arm/ti/ti_hwmods.c b/sys/arm/ti/ti_hwmods.c
index 1488e55..db96235 100644
--- a/sys/arm/ti/ti_hwmods.c
+++ b/sys/arm/ti/ti_hwmods.c
@@ -76,6 +76,9 @@ struct hwmod ti_hwmods[] = {
{"epwmss1", PWMSS1_CLK},
{"epwmss2", PWMSS2_CLK},
+ {"spi0", SPI0_CLK},
+ {"spi1", SPI1_CLK},
+
{"timer1", TIMER1_CLK},
{"timer2", TIMER2_CLK},
{"timer3", TIMER3_CLK},
diff --git a/sys/arm/ti/ti_prcm.h b/sys/arm/ti/ti_prcm.h
index c40439a..61b6960 100644
--- a/sys/arm/ti/ti_prcm.h
+++ b/sys/arm/ti/ti_prcm.h
@@ -158,6 +158,10 @@ typedef enum {
/* RTC module */
RTC_CLK = 1900,
+
+ /* McSPI */
+ SPI0_CLK = 2000,
+ SPI1_CLK,
} clk_ident_t;
/*
diff --git a/sys/arm/ti/ti_sdhci.c b/sys/arm/ti/ti_sdhci.c
index 6c310b6..a24e693 100644
--- a/sys/arm/ti/ti_sdhci.c
+++ b/sys/arm/ti/ti_sdhci.c
@@ -722,3 +722,4 @@ static driver_t ti_sdhci_driver = {
DRIVER_MODULE(sdhci_ti, simplebus, ti_sdhci_driver, ti_sdhci_devclass, 0, 0);
MODULE_DEPEND(sdhci_ti, sdhci, 1, 1, 1);
DRIVER_MODULE(mmc, sdhci_ti, mmc_driver, mmc_devclass, NULL, NULL);
+MODULE_DEPEND(sdhci_ti, mmc, 1, 1, 1);
diff --git a/sys/arm/ti/ti_spi.c b/sys/arm/ti/ti_spi.c
new file mode 100644
index 0000000..e35f365
--- /dev/null
+++ b/sys/arm/ti/ti_spi.c
@@ -0,0 +1,582 @@
+/*-
+ * Copyright (c) 2016 Rubicon Communications, LLC (Netgate)
+ * 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/systm.h>
+#include <sys/bus.h>
+
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/sysctl.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/spibus/spi.h>
+#include <dev/spibus/spibusvar.h>
+
+#include <arm/ti/ti_prcm.h>
+#include <arm/ti/ti_hwmods.h>
+#include <arm/ti/ti_spireg.h>
+#include <arm/ti/ti_spivar.h>
+
+#include "spibus_if.h"
+
+static void ti_spi_intr(void *);
+static int ti_spi_detach(device_t);
+
+#undef TI_SPI_DEBUG
+#ifdef TI_SPI_DEBUG
+#define IRQSTATUSBITS \
+ "\020\1TX0_EMPTY\2TX0_UNDERFLOW\3RX0_FULL\4RX0_OVERFLOW" \
+ "\5TX1_EMPTY\6TX1_UNDERFLOW\7RX1_FULL\11TX2_EMPTY" \
+ "\12TX1_UNDERFLOW\13RX2_FULL\15TX3_EMPTY\16TX3_UNDERFLOW" \
+ "\17RX3_FULL\22EOW"
+#define CONFBITS \
+ "\020\1PHA\2POL\7EPOL\17DMAW\20DMAR\21DPE0\22DPE1\23IS" \
+ "\24TURBO\25FORCE\30SBE\31SBPOL\34FFEW\35FFER\36CLKG"
+#define STATBITS \
+ "\020\1RXS\2TXS\3EOT\4TXFFE\5TXFFF\6RXFFE\7RXFFFF"
+#define MODULCTRLBITS \
+ "\020\1SINGLE\2NOSPIEN\3SLAVE\4SYST\10MOA\11FDAA"
+#define CTRLBITS \
+ "\020\1ENABLED"
+
+static void
+ti_spi_printr(device_t dev)
+{
+ int clk, conf, ctrl, div, i, j, wl;
+ struct ti_spi_softc *sc;
+ uint32_t reg;
+
+ sc = device_get_softc(dev);
+ reg = TI_SPI_READ(sc, MCSPI_SYSCONFIG);
+ device_printf(dev, "SYSCONFIG: %#x\n", reg);
+ reg = TI_SPI_READ(sc, MCSPI_SYSSTATUS);
+ device_printf(dev, "SYSSTATUS: %#x\n", reg);
+ reg = TI_SPI_READ(sc, MCSPI_IRQSTATUS);
+ device_printf(dev, "IRQSTATUS: 0x%b\n", reg, IRQSTATUSBITS);
+ reg = TI_SPI_READ(sc, MCSPI_IRQENABLE);
+ device_printf(dev, "IRQENABLE: 0x%b\n", reg, IRQSTATUSBITS);
+ reg = TI_SPI_READ(sc, MCSPI_MODULCTRL);
+ device_printf(dev, "MODULCTRL: 0x%b\n", reg, MODULCTRLBITS);
+ for (i = 0; i < sc->sc_numcs; i++) {
+ ctrl = TI_SPI_READ(sc, MCSPI_CTRL_CH(i));
+ conf = TI_SPI_READ(sc, MCSPI_CONF_CH(i));
+ device_printf(dev, "CH%dCONF: 0x%b\n", i, conf, CONFBITS);
+ if (conf & MCSPI_CONF_CLKG) {
+ div = (conf >> MCSPI_CONF_CLK_SHIFT) & MCSPI_CONF_CLK_MSK;
+ div |= ((ctrl >> MCSPI_CTRL_EXTCLK_SHIFT) & MCSPI_CTRL_EXTCLK_MSK) << 4;
+ } else {
+ div = 1;
+ j = (conf >> MCSPI_CONF_CLK_SHIFT) & MCSPI_CONF_CLK_MSK;
+ while (j-- > 0)
+ div <<= 1;
+ }
+ clk = TI_SPI_GCLK / div;
+ wl = ((conf >> MCSPI_CONF_WL_SHIFT) & MCSPI_CONF_WL_MSK) + 1;
+ device_printf(dev, "wordlen: %-2d clock: %d\n", wl, clk);
+ reg = TI_SPI_READ(sc, MCSPI_STAT_CH(i));
+ device_printf(dev, "CH%dSTAT: 0x%b\n", i, reg, STATBITS);
+ device_printf(dev, "CH%dCTRL: 0x%b\n", i, ctrl, CTRLBITS);
+ }
+ reg = TI_SPI_READ(sc, MCSPI_XFERLEVEL);
+ device_printf(dev, "XFERLEVEL: %#x\n", reg);
+}
+#endif
+
+static void
+ti_spi_set_clock(struct ti_spi_softc *sc, int ch, int freq)
+{
+ uint32_t clkdiv, conf, div, extclk, reg;
+
+ clkdiv = TI_SPI_GCLK / freq;
+ if (clkdiv > MCSPI_EXTCLK_MSK) {
+ extclk = 0;
+ clkdiv = 0;
+ div = 1;
+ while (TI_SPI_GCLK / div > freq && clkdiv <= 0xf) {
+ clkdiv++;
+ div <<= 1;
+ }
+ conf = clkdiv << MCSPI_CONF_CLK_SHIFT;
+ } else {
+ extclk = clkdiv >> 4;
+ clkdiv &= MCSPI_CONF_CLK_MSK;
+ conf = MCSPI_CONF_CLKG | clkdiv << MCSPI_CONF_CLK_SHIFT;
+ }
+
+ reg = TI_SPI_READ(sc, MCSPI_CTRL_CH(ch));
+ reg &= ~(MCSPI_CTRL_EXTCLK_MSK << MCSPI_CTRL_EXTCLK_SHIFT);
+ reg |= extclk << MCSPI_CTRL_EXTCLK_SHIFT;
+ TI_SPI_WRITE(sc, MCSPI_CTRL_CH(ch), reg);
+
+ reg = TI_SPI_READ(sc, MCSPI_CONF_CH(ch));
+ reg &= ~(MCSPI_CONF_CLKG | MCSPI_CONF_CLK_MSK << MCSPI_CONF_CLK_SHIFT);
+ TI_SPI_WRITE(sc, MCSPI_CONF_CH(ch), reg | conf);
+}
+
+static int
+ti_spi_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+ if (!ofw_bus_is_compatible(dev, "ti,omap4-mcspi"))
+ return (ENXIO);
+
+ device_set_desc(dev, "TI McSPI controller");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+ti_spi_attach(device_t dev)
+{
+ int clk_id, err, i, rid, timeout;
+ struct ti_spi_softc *sc;
+ uint32_t rev;
+
+ sc = device_get_softc(dev);
+ sc->sc_dev = dev;
+
+ /*
+ * Get the MMCHS device id from FDT. If it's not there use the newbus
+ * unit number (which will work as long as the devices are in order and
+ * none are skipped in the fdt). Note that this is a property we made
+ * up and added in freebsd, it doesn't exist in the published bindings.
+ */
+ clk_id = ti_hwmods_get_clock(dev);
+ if (clk_id == INVALID_CLK_IDENT) {
+ device_printf(dev,
+ "failed to get clock based on hwmods property\n");
+ return (EINVAL);
+ }
+
+ /* Activate the McSPI module. */
+ err = ti_prcm_clk_enable(clk_id);
+ if (err) {
+ device_printf(dev, "Error: failed to activate source clock\n");
+ return (err);
+ }
+
+ /* Get the number of available channels. */
+ if ((OF_getencprop(ofw_bus_get_node(dev), "ti,spi-num-cs",
+ &sc->sc_numcs, sizeof(sc->sc_numcs))) <= 0) {
+ sc->sc_numcs = 2;
+ }
+
+ rid = 0;
+ sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (!sc->sc_mem_res) {
+ device_printf(dev, "cannot allocate memory window\n");
+ return (ENXIO);
+ }
+
+ sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
+ sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);
+
+ rid = 0;
+ sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE);
+ if (!sc->sc_irq_res) {
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+ device_printf(dev, "cannot allocate interrupt\n");
+ return (ENXIO);
+ }
+
+ /* Hook up our interrupt handler. */
+ if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
+ NULL, ti_spi_intr, sc, &sc->sc_intrhand)) {
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+ device_printf(dev, "cannot setup the interrupt handler\n");
+ return (ENXIO);
+ }
+
+ mtx_init(&sc->sc_mtx, "ti_spi", NULL, MTX_DEF);
+
+ /* Issue a softreset to the controller */
+ TI_SPI_WRITE(sc, MCSPI_SYSCONFIG, MCSPI_SYSCONFIG_SOFTRESET);
+ timeout = 1000;
+ while (!(TI_SPI_READ(sc, MCSPI_SYSSTATUS) &
+ MCSPI_SYSSTATUS_RESETDONE)) {
+ if (--timeout == 0) {
+ device_printf(dev,
+ "Error: Controller reset operation timed out\n");
+ ti_spi_detach(dev);
+ return (ENXIO);
+ }
+ DELAY(100);
+ }
+
+ /* Print the McSPI module revision. */
+ rev = TI_SPI_READ(sc, MCSPI_REVISION);
+ device_printf(dev,
+ "scheme: %#x func: %#x rtl: %d rev: %d.%d custom rev: %d\n",
+ (rev >> MCSPI_REVISION_SCHEME_SHIFT) & MCSPI_REVISION_SCHEME_MSK,
+ (rev >> MCSPI_REVISION_FUNC_SHIFT) & MCSPI_REVISION_FUNC_MSK,
+ (rev >> MCSPI_REVISION_RTL_SHIFT) & MCSPI_REVISION_RTL_MSK,
+ (rev >> MCSPI_REVISION_MAJOR_SHIFT) & MCSPI_REVISION_MAJOR_MSK,
+ (rev >> MCSPI_REVISION_MINOR_SHIFT) & MCSPI_REVISION_MINOR_MSK,
+ (rev >> MCSPI_REVISION_CUSTOM_SHIFT) & MCSPI_REVISION_CUSTOM_MSK);
+
+ /* Set Master mode, single channel. */
+ TI_SPI_WRITE(sc, MCSPI_MODULCTRL, MCSPI_MODULCTRL_SINGLE);
+
+ /* Clear pending interrupts and disable interrupts. */
+ TI_SPI_WRITE(sc, MCSPI_IRQENABLE, 0x0);
+ TI_SPI_WRITE(sc, MCSPI_IRQSTATUS, 0xffff);
+
+ for (i = 0; i < sc->sc_numcs; i++) {
+ /*
+ * Default to SPI mode 0, CS active low, 8 bits word length and
+ * 500kHz clock.
+ */
+ TI_SPI_WRITE(sc, MCSPI_CONF_CH(i),
+ MCSPI_CONF_DPE0 | MCSPI_CONF_EPOL |
+ (8 - 1) << MCSPI_CONF_WL_SHIFT);
+ /* Set initial clock - 500kHz. */
+ ti_spi_set_clock(sc, i, 500000);
+ }
+
+#ifdef TI_SPI_DEBUG
+ ti_spi_printr(dev);
+#endif
+
+ device_add_child(dev, "spibus", -1);
+
+ return (bus_generic_attach(dev));
+}
+
+static int
+ti_spi_detach(device_t dev)
+{
+ struct ti_spi_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ /* Clear pending interrupts and disable interrupts. */
+ TI_SPI_WRITE(sc, MCSPI_IRQENABLE, 0);
+ TI_SPI_WRITE(sc, MCSPI_IRQSTATUS, 0xffff);
+
+ /* Reset controller. */
+ TI_SPI_WRITE(sc, MCSPI_SYSCONFIG, MCSPI_SYSCONFIG_SOFTRESET);
+
+ bus_generic_detach(dev);
+
+ mtx_destroy(&sc->sc_mtx);
+ if (sc->sc_intrhand)
+ bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_intrhand);
+ if (sc->sc_irq_res)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
+ if (sc->sc_mem_res)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
+
+ return (0);
+}
+
+static int
+ti_spi_fill_fifo(struct ti_spi_softc *sc)
+{
+ int bytes, timeout;
+ struct spi_command *cmd;
+ uint32_t written;
+ uint8_t *data;
+
+ cmd = sc->sc_cmd;
+ bytes = min(sc->sc_len - sc->sc_written, sc->sc_fifolvl);
+ while (bytes-- > 0) {
+ data = (uint8_t *)cmd->tx_cmd;
+ written = sc->sc_written++;
+ if (written >= cmd->tx_cmd_sz) {
+ data = (uint8_t *)cmd->tx_data;
+ written -= cmd->tx_cmd_sz;
+ }
+ if (sc->sc_fifolvl == 1) {
+ /* FIFO disabled. */
+ timeout = 1000;
+ while (--timeout > 0 && (TI_SPI_READ(sc,
+ MCSPI_STAT_CH(sc->sc_cs)) & MCSPI_STAT_TXS) == 0) {
+ DELAY(100);
+ }
+ if (timeout == 0)
+ return (-1);
+ }
+ TI_SPI_WRITE(sc, MCSPI_TX_CH(sc->sc_cs), data[written]);
+ }
+
+ return (0);
+}
+
+static int
+ti_spi_drain_fifo(struct ti_spi_softc *sc)
+{
+ int bytes, timeout;
+ struct spi_command *cmd;
+ uint32_t read;
+ uint8_t *data;
+
+ cmd = sc->sc_cmd;
+ bytes = min(sc->sc_len - sc->sc_read, sc->sc_fifolvl);
+ while (bytes-- > 0) {
+ data = (uint8_t *)cmd->rx_cmd;
+ read = sc->sc_read++;
+ if (read >= cmd->rx_cmd_sz) {
+ data = (uint8_t *)cmd->rx_data;
+ read -= cmd->rx_cmd_sz;
+ }
+ if (sc->sc_fifolvl == 1) {
+ /* FIFO disabled. */
+ timeout = 1000;
+ while (--timeout > 0 && (TI_SPI_READ(sc,
+ MCSPI_STAT_CH(sc->sc_cs)) & MCSPI_STAT_RXS) == 0) {
+ DELAY(100);
+ }
+ if (timeout == 0)
+ return (-1);
+ }
+ data[read] = TI_SPI_READ(sc, MCSPI_RX_CH(sc->sc_cs));
+ }
+
+ return (0);
+}
+
+static void
+ti_spi_intr(void *arg)
+{
+ int eow;
+ struct ti_spi_softc *sc;
+ uint32_t status;
+
+ eow = 0;
+ sc = (struct ti_spi_softc *)arg;
+ TI_SPI_LOCK(sc);
+ status = TI_SPI_READ(sc, MCSPI_IRQSTATUS);
+
+ /*
+ * No new TX_empty or RX_full event will be asserted while the CPU has
+ * not performed the number of writes or reads defined by
+ * MCSPI_XFERLEVEL[AEL] and MCSPI_XFERLEVEL[AFL]. It is responsibility
+ * of CPU perform the right number of writes and reads.
+ */
+ if (status & MCSPI_IRQ_TX0_EMPTY)
+ ti_spi_fill_fifo(sc);
+ if (status & MCSPI_IRQ_RX0_FULL)
+ ti_spi_drain_fifo(sc);
+
+ if (status & MCSPI_IRQ_EOW)
+ eow = 1;
+
+ /* Clear interrupt status. */
+ TI_SPI_WRITE(sc, MCSPI_IRQSTATUS, status);
+
+ /* Check for end of transfer. */
+ if (sc->sc_written == sc->sc_len && sc->sc_read == sc->sc_len) {
+ sc->sc_flags |= TI_SPI_DONE;
+ wakeup(sc->sc_dev);
+ }
+
+ TI_SPI_UNLOCK(sc);
+}
+
+static int
+ti_spi_pio_transfer(struct ti_spi_softc *sc)
+{
+
+ while (sc->sc_len - sc->sc_written > 0) {
+ if (ti_spi_fill_fifo(sc) == -1)
+ return (EIO);
+ if (ti_spi_drain_fifo(sc) == -1)
+ return (EIO);
+ }
+
+ return (0);
+}
+
+static int
+ti_spi_gcd(int a, int b)
+{
+ int m;
+
+ while ((m = a % b) != 0) {
+ a = b;
+ b = m;
+ }
+
+ return (b);
+}
+
+static int
+ti_spi_transfer(device_t dev, device_t child, struct spi_command *cmd)
+{
+ int cs, err;
+ struct ti_spi_softc *sc;
+ uint32_t reg;
+
+ sc = device_get_softc(dev);
+
+ KASSERT(cmd->tx_cmd_sz == cmd->rx_cmd_sz,
+ ("TX/RX command sizes should be equal"));
+ KASSERT(cmd->tx_data_sz == cmd->rx_data_sz,
+ ("TX/RX data sizes should be equal"));
+
+ /* Get the proper chip select for this child. */
+ spibus_get_cs(child, &cs);
+ if (cs < 0 || cs > sc->sc_numcs) {
+ device_printf(dev, "Invalid chip select %d requested by %s\n",
+ cs, device_get_nameunit(child));
+ return (EINVAL);
+ }
+
+ TI_SPI_LOCK(sc);
+
+ /* If the controller is in use wait until it is available. */
+ while (sc->sc_flags & TI_SPI_BUSY)
+ mtx_sleep(dev, &sc->sc_mtx, 0, "ti_spi", 0);
+
+ /* Now we have control over SPI controller. */
+ sc->sc_flags = TI_SPI_BUSY;
+
+ /* Save the SPI command data. */
+ sc->sc_cs = cs;
+ sc->sc_cmd = cmd;
+ sc->sc_read = 0;
+ sc->sc_written = 0;
+ sc->sc_len = cmd->tx_cmd_sz + cmd->tx_data_sz;
+ sc->sc_fifolvl = ti_spi_gcd(sc->sc_len, TI_SPI_FIFOSZ);
+ if (sc->sc_fifolvl < 2 || sc->sc_len > 0xffff)
+ sc->sc_fifolvl = 1; /* FIFO disabled. */
+ /* Disable FIFO for now. */
+ sc->sc_fifolvl = 1;
+
+ /* Use a safe clock - 500kHz. */
+ ti_spi_set_clock(sc, sc->sc_cs, 500000);
+
+ /* Disable the FIFO. */
+ TI_SPI_WRITE(sc, MCSPI_XFERLEVEL, 0);
+
+ /* 8 bits word, d0 miso, d1 mosi, mode 0 and CS active low. */
+ reg = TI_SPI_READ(sc, MCSPI_CONF_CH(sc->sc_cs));
+ reg &= ~(MCSPI_CONF_FFER | MCSPI_CONF_FFEW | MCSPI_CONF_SBPOL |
+ MCSPI_CONF_SBE | MCSPI_CONF_TURBO | MCSPI_CONF_IS |
+ MCSPI_CONF_DPE1 | MCSPI_CONF_DPE0 | MCSPI_CONF_DMAR |
+ MCSPI_CONF_DMAW | MCSPI_CONF_EPOL);
+ reg |= MCSPI_CONF_DPE0 | MCSPI_CONF_EPOL | MCSPI_CONF_WL8BITS;
+ TI_SPI_WRITE(sc, MCSPI_CONF_CH(sc->sc_cs), reg);
+
+#if 0
+ /* Enable channel interrupts. */
+ reg = TI_SPI_READ(sc, MCSPI_IRQENABLE);
+ reg |= 0xf;
+ TI_SPI_WRITE(sc, MCSPI_IRQENABLE, reg);
+#endif
+
+ /* Start the transfer. */
+ reg = TI_SPI_READ(sc, MCSPI_CTRL_CH(sc->sc_cs));
+ TI_SPI_WRITE(sc, MCSPI_CTRL_CH(sc->sc_cs), reg | MCSPI_CTRL_ENABLE);
+
+ /* Force CS on. */
+ reg = TI_SPI_READ(sc, MCSPI_CONF_CH(sc->sc_cs));
+ TI_SPI_WRITE(sc, MCSPI_CONF_CH(sc->sc_cs), reg |= MCSPI_CONF_FORCE);
+
+ err = 0;
+ if (sc->sc_fifolvl == 1)
+ err = ti_spi_pio_transfer(sc);
+
+ /* Force CS off. */
+ reg = TI_SPI_READ(sc, MCSPI_CONF_CH(sc->sc_cs));
+ reg &= ~MCSPI_CONF_FORCE;
+ TI_SPI_WRITE(sc, MCSPI_CONF_CH(sc->sc_cs), reg);
+
+ /* Disable IRQs. */
+ reg = TI_SPI_READ(sc, MCSPI_IRQENABLE);
+ reg &= ~0xf;
+ TI_SPI_WRITE(sc, MCSPI_IRQENABLE, reg);
+ TI_SPI_WRITE(sc, MCSPI_IRQSTATUS, 0xf);
+
+ /* Disable the SPI channel. */
+ reg = TI_SPI_READ(sc, MCSPI_CTRL_CH(sc->sc_cs));
+ reg &= ~MCSPI_CTRL_ENABLE;
+ TI_SPI_WRITE(sc, MCSPI_CTRL_CH(sc->sc_cs), reg);
+
+ /* Disable FIFO. */
+ reg = TI_SPI_READ(sc, MCSPI_CONF_CH(sc->sc_cs));
+ reg &= ~(MCSPI_CONF_FFER | MCSPI_CONF_FFEW);
+ TI_SPI_WRITE(sc, MCSPI_CONF_CH(sc->sc_cs), reg);
+
+ /* Release the controller and wakeup the next thread waiting for it. */
+ sc->sc_flags = 0;
+ wakeup_one(dev);
+ TI_SPI_UNLOCK(sc);
+
+ return (err);
+}
+
+static phandle_t
+ti_spi_get_node(device_t bus, device_t dev)
+{
+
+ /* Share controller node with spibus. */
+ return (ofw_bus_get_node(bus));
+}
+
+static device_method_t ti_spi_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ti_spi_probe),
+ DEVMETHOD(device_attach, ti_spi_attach),
+ DEVMETHOD(device_detach, ti_spi_detach),
+
+ /* SPI interface */
+ DEVMETHOD(spibus_transfer, ti_spi_transfer),
+
+ /* ofw_bus interface */
+ DEVMETHOD(ofw_bus_get_node, ti_spi_get_node),
+
+ DEVMETHOD_END
+};
+
+static devclass_t ti_spi_devclass;
+
+static driver_t ti_spi_driver = {
+ "spi",
+ ti_spi_methods,
+ sizeof(struct ti_spi_softc),
+};
+
+DRIVER_MODULE(ti_spi, simplebus, ti_spi_driver, ti_spi_devclass, 0, 0);
diff --git a/sys/arm/ti/ti_spireg.h b/sys/arm/ti/ti_spireg.h
new file mode 100644
index 0000000..f31f55e
--- /dev/null
+++ b/sys/arm/ti/ti_spireg.h
@@ -0,0 +1,97 @@
+/*-
+ * Copyright (c) 2016 Rubicon Communications, LLC (Netgate)
+ * 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 _TI_SPIREG_H_
+#define _TI_SPIREG_H_
+
+#define TI_SPI_GCLK 48000000U
+#define TI_SPI_FIFOSZ 32
+#define MCSPI_REVISION 0x0
+#define MCSPI_REVISION_SCHEME_SHIFT 30
+#define MCSPI_REVISION_SCHEME_MSK 0x3
+#define MCSPI_REVISION_FUNC_SHIFT 16
+#define MCSPI_REVISION_FUNC_MSK 0xfff
+#define MCSPI_REVISION_RTL_SHIFT 11
+#define MCSPI_REVISION_RTL_MSK 0x1f
+#define MCSPI_REVISION_MAJOR_SHIFT 8
+#define MCSPI_REVISION_MAJOR_MSK 0x7
+#define MCSPI_REVISION_CUSTOM_SHIFT 6
+#define MCSPI_REVISION_CUSTOM_MSK 0x3
+#define MCSPI_REVISION_MINOR_SHIFT 0
+#define MCSPI_REVISION_MINOR_MSK 0x3f
+#define MCSPI_SYSCONFIG 0x110
+#define MCSPI_SYSCONFIG_SOFTRESET (1 << 1)
+#define MCSPI_SYSSTATUS 0x114
+#define MCSPI_SYSSTATUS_RESETDONE (1 << 0)
+#define MCSPI_MODULCTRL 0x128
+#define MCSPI_MODULCTRL_SLAVE (1 << 2)
+#define MCSPI_MODULCTRL_SINGLE (1 << 0)
+#define MCSPI_IRQSTATUS 0x118
+#define MCSPI_IRQENABLE 0x11c
+#define MCSPI_IRQ_EOW (1 << 17)
+#define MCSPI_IRQ_RX0_OVERFLOW (1 << 3)
+#define MCSPI_IRQ_RX0_FULL (1 << 2)
+#define MCSPI_IRQ_TX0_UNDERFLOW (1 << 1)
+#define MCSPI_IRQ_TX0_EMPTY (1 << 0)
+#define MCSPI_CONF_CH(_c) (0x12c + 0x14 * (_c))
+#define MCSPI_CONF_CLKG (1 << 29)
+#define MCSPI_CONF_FFER (1 << 28)
+#define MCSPI_CONF_FFEW (1 << 27)
+#define MCSPI_CONF_SBPOL (1 << 24)
+#define MCSPI_CONF_SBE (1 << 23)
+#define MCSPI_CONF_FORCE (1 << 20)
+#define MCSPI_CONF_TURBO (1 << 19)
+#define MCSPI_CONF_IS (1 << 18)
+#define MCSPI_CONF_DPE1 (1 << 17)
+#define MCSPI_CONF_DPE0 (1 << 16)
+#define MCSPI_CONF_DMAR (1 << 15)
+#define MCSPI_CONF_DMAW (1 << 14)
+#define MCSPI_CONF_WL_MSK 0x1f
+#define MCSPI_CONF_WL_SHIFT 7
+#define MCSPI_CONF_WL8BITS (7 << MCSPI_CONF_WL_SHIFT)
+#define MCSPI_CONF_EPOL (1 << 6)
+#define MCSPI_CONF_CLK_MSK 0xf
+#define MCSPI_CONF_CLK_SHIFT 2
+#define MCSPI_CONF_POL (1 << 1)
+#define MCSPI_CONF_PHA (1 << 0)
+#define MCSPI_STAT_CH(_c) (0x130 + 0x14 * (_c))
+#define MCSPI_STAT_TXFFF (1 << 4)
+#define MCSPI_STAT_TXS (1 << 1)
+#define MCSPI_STAT_RXS (1 << 0)
+#define MCSPI_CTRL_CH(_c) (0x134 + 0x14 * (_c))
+#define MCSPI_EXTCLK_MSK 0xfff
+#define MCSPI_CTRL_EXTCLK_MSK 0xff
+#define MCSPI_CTRL_EXTCLK_SHIFT 8
+#define MCSPI_CTRL_ENABLE (1 << 0)
+#define MCSPI_TX_CH(_c) (0x138 + 0x14 * (_c))
+#define MCSPI_RX_CH(_c) (0x13c + 0x14 * (_c))
+#define MCSPI_XFERLEVEL 0x17c
+#define MCSPI_XFERLEVEL_AFL(_a) (((_a) >> 8) & 0xff)
+#define MCSPI_XFERLEVEL_AEL(_a) (((_a) >> 0) & 0xff)
+
+#endif /* _TI_SPIREG_H_ */
diff --git a/sys/arm/ti/ti_spivar.h b/sys/arm/ti/ti_spivar.h
new file mode 100644
index 0000000..89731f3
--- /dev/null
+++ b/sys/arm/ti/ti_spivar.h
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (c) 2016 Rubicon Communications, LLC (Netgate)
+ * 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 _TI_SPIVAR_H_
+#define _TI_SPIVAR_H_
+
+struct ti_spi_softc {
+ bus_space_tag_t sc_bst;
+ bus_space_handle_t sc_bsh;
+ device_t sc_dev;
+ int sc_numcs;
+ struct mtx sc_mtx;
+ struct resource *sc_mem_res;
+ struct resource *sc_irq_res;
+ struct {
+ int cs;
+ int fifolvl;
+ struct spi_command *cmd;
+ uint32_t len;
+ uint32_t read;
+ uint32_t written;
+ } xfer;
+ uint32_t sc_flags;
+ void *sc_intrhand;
+#define sc_cs xfer.cs
+#define sc_fifolvl xfer.fifolvl
+#define sc_cmd xfer.cmd
+#define sc_len xfer.len
+#define sc_read xfer.read
+#define sc_written xfer.written
+};
+
+#define TI_SPI_BUSY 0x1
+#define TI_SPI_DONE 0x2
+
+#define TI_SPI_WRITE(_sc, _off, _val) \
+ bus_space_write_4((_sc)->sc_bst, (_sc)->sc_bsh, (_off), (_val))
+#define TI_SPI_READ(_sc, _off) \
+ bus_space_read_4((_sc)->sc_bst, (_sc)->sc_bsh, (_off))
+
+#define TI_SPI_LOCK(_sc) \
+ mtx_lock(&(_sc)->sc_mtx)
+#define TI_SPI_UNLOCK(_sc) \
+ mtx_unlock(&(_sc)->sc_mtx)
+
+#endif /* _TI_SPIVAR_H_ */
diff --git a/sys/arm/xscale/ixp425/avila_ata.c b/sys/arm/xscale/ixp425/avila_ata.c
index e3a9a52..f6dfaa6 100644
--- a/sys/arm/xscale/ixp425/avila_ata.c
+++ b/sys/arm/xscale/ixp425/avila_ata.c
@@ -287,7 +287,7 @@ ata_avila_alloc_resource(device_t dev, device_t child, int type, int *rid,
struct ata_avila_softc *sc = device_get_softc(dev);
KASSERT(type == SYS_RES_IRQ && *rid == ATA_IRQ_RID,
- ("type %u rid %u start %lu end %lu count %lu flags %u",
+ ("type %u rid %u start %ju end %ju count %ju flags %u",
type, *rid, start, end, count, flags));
/* doesn't matter what we return so reuse the real thing */
diff --git a/sys/arm/xscale/ixp425/ixp425.c b/sys/arm/xscale/ixp425/ixp425.c
index 017d567..20120e6 100644
--- a/sys/arm/xscale/ixp425/ixp425.c
+++ b/sys/arm/xscale/ixp425/ixp425.c
@@ -533,7 +533,7 @@ ixp425_alloc_resource(device_t dev, device_t child, int type, int *rid,
(start - vtrans->hwbase);
if (bootverbose)
device_printf(child,
- "%s: assign 0x%lx:0x%lx%s\n",
+ "%s: assign 0x%jx:0x%jx%s\n",
__func__, start, end - start,
vtrans->isa4x ? " A4X" :
vtrans->isslow ? " SLOW" : "");
@@ -542,14 +542,14 @@ ixp425_alloc_resource(device_t dev, device_t child, int type, int *rid,
vtrans = gethwvtrans(start, end - start);
if (vtrans == NULL) {
/* likely means above table needs to be updated */
- device_printf(child, "%s: no mapping for 0x%lx:0x%lx\n",
+ device_printf(child, "%s: no mapping for 0x%jx:0x%jx\n",
__func__, start, end - start);
return NULL;
}
rv = rman_reserve_resource(&sc->sc_mem_rman, start, end,
end - start, flags, child);
if (rv == NULL) {
- device_printf(child, "%s: cannot reserve 0x%lx:0x%lx\n",
+ device_printf(child, "%s: cannot reserve 0x%jx:0x%jx\n",
__func__, start, end - start);
return NULL;
}
@@ -586,7 +586,7 @@ ixp425_activate_resource(device_t dev, device_t child, int type, int rid,
if (type == SYS_RES_MEMORY) {
vtrans = gethwvtrans(rman_get_start(r), rman_get_size(r));
if (vtrans == NULL) { /* NB: should not happen */
- device_printf(child, "%s: no mapping for 0x%lx:0x%lx\n",
+ device_printf(child, "%s: no mapping for 0x%jx:0x%jx\n",
__func__, rman_get_start(r), rman_get_size(r));
return (ENOENT);
}
diff --git a/sys/arm/xscale/pxa/pxa_obio.c b/sys/arm/xscale/pxa/pxa_obio.c
index 6761ca3..6081588 100644
--- a/sys/arm/xscale/pxa/pxa_obio.c
+++ b/sys/arm/xscale/pxa/pxa_obio.c
@@ -159,9 +159,9 @@ pxa_print_child(device_t dev, device_t child)
retval += bus_print_child_header(dev, child);
retval += resource_list_print_type(&od->od_resources, "at mem",
- SYS_RES_MEMORY, "0x%08lx");
+ SYS_RES_MEMORY, "0x%08jx");
retval += resource_list_print_type(&od->od_resources, "irq",
- SYS_RES_IRQ, "%ld");
+ SYS_RES_IRQ, "%jd");
retval += bus_print_child_footer(dev, child);
@@ -390,7 +390,7 @@ pxa_alloc_gpio_irq(device_t dev, device_t child, int type, int *rid,
}
if (bootverbose)
- device_printf(dev, "lazy allocation of irq %ld for %s\n",
+ device_printf(dev, "lazy allocation of irq %jd for %s\n",
start, device_get_nameunit(child));
return (rv);
diff --git a/sys/arm/xscale/pxa/pxa_smi.c b/sys/arm/xscale/pxa/pxa_smi.c
index 4c49e75..b08a7c7 100644
--- a/sys/arm/xscale/pxa/pxa_smi.c
+++ b/sys/arm/xscale/pxa/pxa_smi.c
@@ -144,9 +144,9 @@ pxa_smi_print_child(device_t dev, device_t child)
retval += bus_print_child_header(dev, child);
retval += resource_list_print_type(&smid->smid_resources, "at mem",
- SYS_RES_MEMORY, "%#lx");
+ SYS_RES_MEMORY, "%#jx");
retval += resource_list_print_type(&smid->smid_resources, "irq",
- SYS_RES_IRQ, "%ld");
+ SYS_RES_IRQ, "%jd");
retval += bus_print_child_footer(dev, child);
diff --git a/sys/arm64/arm64/bzero.S b/sys/arm64/arm64/bzero.S
new file mode 100644
index 0000000..60ac97e
--- /dev/null
+++ b/sys/arm64/arm64/bzero.S
@@ -0,0 +1,206 @@
+/*-
+ * Copyright (C) 2016 Cavium Inc.
+ * All rights reserved.
+ *
+ * Developed by Semihalf.
+ *
+ * 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 <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+
+#include "assym.s"
+
+ /*
+ * void bzero(void *p, size_t size)
+ *
+ * x0 - p
+ * x1 - size
+ */
+ENTRY(bzero)
+ cbz x1, ending
+
+ /*
+ * x5 is number of cache lines to zero - calculated later and
+ * will become non-zero if buffer is long enough to zero by
+ * cache lines (and if it is allowed.)
+ * We need to zero it before proceeding with buffers of size
+ * smaller than 16 bytes - otherwise the x5 will not be
+ * calculated and will retain random value.
+ * "normal" is used for buffers <= 16 bytes and to align buffer
+ * to cache line for buffers bigger than cache line; non-0 x5
+ * after "normal" has completed indicates that it has been used
+ * to align buffer to cache line and now zero by cache lines will
+ * be performed, and x5 is amount of cache lines to loop through.
+ */
+ mov x5, xzr
+
+ /* No use of cache assisted zero for buffers with size <= 16 */
+ cmp x1, #0x10
+ b.le normal
+
+ /*
+ * Load size of line that will be cleaned by dc zva call.
+ * 0 means that the instruction is not allowed
+ */
+ ldr x7, =dczva_line_size
+ ldr x7, [x7]
+ cbz x7, normal
+
+ /*
+ * Buffer must be larger than cache line for using cache zeroing
+ * (and cache line aligned but this is checked after jump)
+ */
+ cmp x1, x7
+ b.lt normal
+
+ /*
+ * Calculate number of bytes to cache aligned address (x4) nad
+ * number of full cache lines (x5). x6 is final address to zero.
+ */
+ sub x2, x7, #0x01
+ mov x3, -1
+ eor x3, x3, x2
+ add x4, x0, x2
+ and x4, x4, x3
+ subs x4, x4, x0
+ b.eq normal
+
+ /* Calculate number of "lines" in buffer */
+ sub x5, x1, x4
+ rbit x2, x7
+ clz x2, x2
+ lsr x5, x5, x2
+
+ /*
+ * If number of cache lines is 0, we will not be able to zero
+ * by cache lines, so go normal way.
+ */
+ cbz x5, normal
+ /* x6 is final address to zero */
+ add x6, x0, x1
+
+ /*
+ * We are here because x5 is non-0 so normal will be used to
+ * align buffer before cache zeroing. x4 holds number of bytes
+ * needed for alignment.
+ */
+ mov x1, x4
+
+ /* When jumping here: x0 holds pointer, x1 holds size */
+normal:
+ /*
+ * Get buffer offset into 16 byte aligned address; 0 means pointer
+ * is aligned.
+ */
+ ands x2, x0, #0x0f
+ b.eq aligned_to_16
+ /* Calculate one-byte loop runs to 8 byte aligned address. */
+ ands x2, x2, #0x07
+ mov x3, #0x08
+ sub x2, x3, x2
+ /* x2 is number of bytes missing for alignment, x1 is buffer size */
+ cmp x1, x2
+ csel x2, x1, x2, le
+ sub x1, x1, x2
+
+ /*
+ * Byte by byte copy will copy at least enough bytes to align
+ * pointer and at most "size".
+ */
+align:
+ strb wzr, [x0], #0x01
+ subs x2, x2, #0x01
+ b.ne align
+
+ /* Now pointer is aligned to 8 bytes */
+ cmp x1, #0x10
+ b.lt lead_out
+ /*
+ * Check if copy of another 8 bytes is needed to align to 16 byte
+ * address and do it
+ */
+ tbz x0, #0x03, aligned_to_16
+ str xzr, [x0], #0x08
+ sub x1, x1, #0x08
+
+ /* While jumping here: x0 is 16 byte alligned address, x1 is size */
+aligned_to_16:
+ /* If size is less than 16 bytes, use lead_out to copy what remains */
+ cmp x1, #0x10
+ b.lt lead_out
+
+ lsr x2, x1, #0x04
+zero_by_16:
+ stp xzr, xzr, [x0], #0x10
+ subs x2, x2, #0x01
+ b.ne zero_by_16
+
+ /*
+ * Lead out requires addresses to be aligned to 8 bytes. It is used to
+ * zero buffers with sizes < 16 and what can not be zeroed by
+ * zero_by_16 loop.
+ */
+ ands x1, x1, #0x0f
+ b.eq lead_out_end
+lead_out:
+ tbz x1, #0x03, lead_out_dword
+ str xzr, [x0], #0x08
+lead_out_dword:
+ tbz x1, #0x02, lead_out_word
+ str wzr, [x0], #0x04
+lead_out_word:
+ tbz x1, #0x01, lead_out_byte
+ strh wzr, [x0], #0x02
+lead_out_byte:
+ tbz x1, #0x00, lead_out_end
+ strb wzr, [x0], #0x01
+
+lead_out_end:
+ /*
+ * If x5 is non-zero, this means that normal has been used as
+ * a lead in to align buffer address to cache size
+ */
+ cbz x5, ending
+
+ /*
+ * Here x5 holds number of lines to zero; x6 is final address of
+ * buffer. x0 is cache line aligned pointer. x7 is cache line size
+ * in bytes
+ */
+cache_line_zero:
+ dc zva, x0
+ add x0, x0, x7
+ subs x5, x5, #0x01
+ b.ne cache_line_zero
+
+ /* Need to zero remaining bytes? */
+ subs x1, x6, x0
+ b.ne normal
+
+ending:
+ ret
+
+END(bzero)
+
diff --git a/sys/arm64/arm64/copyinout.S b/sys/arm64/arm64/copyinout.S
index 1ba8106..b99dbc2 100644
--- a/sys/arm64/arm64/copyinout.S
+++ b/sys/arm64/arm64/copyinout.S
@@ -51,24 +51,18 @@ END(copyio_fault)
* int copyout(const void *kaddr, void *udaddr, size_t len)
*/
ENTRY(copyout)
- cbz x2, 2f /* If len == 0 then skip loop */
- add x3, x1, x2
+ cbz x2, 1f
+ adds x3, x1, x2
+ b.cs copyio_fault_nopcb
ldr x4, =VM_MAXUSER_ADDRESS
cmp x3, x4
b.hi copyio_fault_nopcb
- adr x6, copyio_fault /* Get the handler address */
- SET_FAULT_HANDLER(x6, x7) /* Set the handler */
-
-1: ldrb w4, [x0], #1 /* Load from kaddr */
- strb w4, [x1], #1 /* Store in uaddr */
- sub x2, x2, #1 /* len-- */
- cbnz x2, 1b
-
- SET_FAULT_HANDLER(xzr, x7) /* Clear the handler */
+ b copycommon
-2: mov x0, xzr /* return 0 */
+1: mov x0, xzr /* return 0 */
ret
+
END(copyout)
/*
@@ -77,24 +71,18 @@ END(copyout)
* int copyin(const void *uaddr, void *kdaddr, size_t len)
*/
ENTRY(copyin)
- cbz x2, 2f /* If len == 0 then skip loop */
- add x3, x0, x2
+ cbz x2, 1f
+ adds x3, x0, x2
+ b.cs copyio_fault_nopcb
ldr x4, =VM_MAXUSER_ADDRESS
cmp x3, x4
b.hi copyio_fault_nopcb
- adr x6, copyio_fault /* Get the handler address */
- SET_FAULT_HANDLER(x6, x7) /* Set the handler */
-
-1: ldrb w4, [x0], #1 /* Load from uaddr */
- strb w4, [x1], #1 /* Store in kaddr */
- sub x2, x2, #1 /* len-- */
- cbnz x2, 1b
-
- SET_FAULT_HANDLER(xzr, x7) /* Clear the handler */
+ b copycommon
-2: mov x0, xzr /* return 0 */
+1: mov x0, xzr /* return 0 */
ret
+
END(copyin)
/*
@@ -106,11 +94,11 @@ ENTRY(copyinstr)
mov x5, xzr /* count = 0 */
mov w4, #1 /* If zero return faulure */
cbz x2, 3f /* If len == 0 then skip loop */
- ldr x7, =VM_MAXUSER_ADDRESS
adr x6, copyio_fault /* Get the handler address */
SET_FAULT_HANDLER(x6, x7) /* Set the handler */
+ ldr x7, =VM_MAXUSER_ADDRESS
1: cmp x0, x7
b.cs copyio_fault
ldrb w4, [x0], #1 /* Load from uaddr */
@@ -130,3 +118,101 @@ ENTRY(copyinstr)
csel w0, wzr, w1, eq /* If so return success, else failure */
ret
END(copyinstr)
+
+/*
+ * Local helper
+ *
+ * x0 - src pointer
+ * x1 - dst pointer
+ * x2 - size
+ * lr - the return address, so jump here instead of calling
+ *
+ * This function is optimized to minimize concurrent memory accesses. In
+ * present form it is suited for cores with a single memory prefetching
+ * unit.
+ * ARM64TODO:
+ * Consider using separate functions for each ARM64 core. Adding memory
+ * access interleaving might increase a total throughput on A57 or A72.
+ */
+ .text
+ .align 4
+ .local copycommon
+ .type copycommon,@function
+
+copycommon:
+ adr x6, copyio_fault /* Get the handler address */
+ SET_FAULT_HANDLER(x6, x7) /* Set the handler */
+
+
+ /* Check alignment */
+ orr x3, x0, x1
+ ands x3, x3, 0x07
+ b.eq aligned
+
+ /* Unaligned is byte by byte copy */
+byte_by_byte:
+ ldrb w3, [x0], #0x01
+ strb w3, [x1], #0x01
+ subs x2, x2, #0x01
+ b.ne byte_by_byte
+ b ending
+
+aligned:
+ cmp x2, #0x10
+ b.lt lead_out
+ cmp x2, #0x40
+ b.lt by_dwords_start
+
+ /* Block copy */
+ lsr x15, x2, #0x06
+by_blocks:
+ ldp x3, x4, [x0], #0x10
+ ldp x5, x6, [x0], #0x10
+ ldp x7, x8, [x0], #0x10
+ ldp x9, x10, [x0], #0x10
+ stp x3, x4, [x1], #0x10
+ stp x5, x6, [x1], #0x10
+ stp x7, x8, [x1], #0x10
+ stp x9, x10, [x1], #0x10
+
+ subs x15, x15, #0x01
+ b.ne by_blocks
+
+ and x2, x2, #0x3f
+
+by_dwords_start:
+ lsr x15, x2, #0x04
+ cbz x15, lead_out
+by_dwords:
+ ldp x3, x4, [x0], #0x10
+ stp x3, x4, [x1], #0x10
+ subs x15, x15, #0x01
+ b.ne by_dwords
+
+ /* Less than 16 bytes to copy */
+lead_out:
+ tbz x2, #0x03, last_word
+ ldr x3, [x0], #0x08
+ str x3, [x1], #0x08
+
+last_word:
+ tbz x2, #0x02, last_hword
+ ldr w3, [x0], #0x04
+ str w3, [x1], #0x04
+
+last_hword:
+ tbz x2, #0x01, last_byte
+ ldrh w3, [x0], #0x02
+ strh w3, [x1], #0x02
+
+last_byte:
+ tbz x2, #0x00, ending
+ ldrb w3, [x0]
+ strb w3, [x1]
+
+ending:
+ SET_FAULT_HANDLER(xzr, x7) /* Clear the handler */
+
+ mov x0, xzr /* return 0 */
+ ret
+ .size copycommon, . - copycommon
diff --git a/sys/arm64/arm64/exception.S b/sys/arm64/arm64/exception.S
index c5a358b..63aa04c 100644
--- a/sys/arm64/arm64/exception.S
+++ b/sys/arm64/arm64/exception.S
@@ -150,7 +150,7 @@ END(handle_el1h_sync)
ENTRY(handle_el1h_irq)
save_registers 1
mov x0, sp
- bl arm_cpu_intr
+ bl intr_irq_handler
restore_registers 1
eret
END(handle_el1h_irq)
@@ -171,7 +171,7 @@ END(handle_el0_sync)
ENTRY(handle_el0_irq)
save_registers 0
mov x0, sp
- bl arm_cpu_intr
+ bl intr_irq_handler
do_ast
restore_registers 0
eret
diff --git a/sys/arm64/arm64/genassym.c b/sys/arm64/arm64/genassym.c
index 67c295f..26adc6d 100644
--- a/sys/arm64/arm64/genassym.c
+++ b/sys/arm64/arm64/genassym.c
@@ -52,7 +52,7 @@ ASSYM(PCB_SIZE, roundup2(sizeof(struct pcb), STACKALIGNBYTES + 1));
ASSYM(PCB_SINGLE_STEP_SHIFT, PCB_SINGLE_STEP_SHIFT);
ASSYM(PCB_REGS, offsetof(struct pcb, pcb_x));
ASSYM(PCB_SP, offsetof(struct pcb, pcb_sp));
-ASSYM(PCB_L1ADDR, offsetof(struct pcb, pcb_l1addr));
+ASSYM(PCB_L0ADDR, offsetof(struct pcb, pcb_l0addr));
ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault));
ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags));
diff --git a/sys/arm64/arm64/gic.c b/sys/arm64/arm64/gic.c
index 0a13b12..2140086 100644
--- a/sys/arm64/arm64/gic.c
+++ b/sys/arm64/arm64/gic.c
@@ -75,6 +75,7 @@ __FBSDID("$FreeBSD$");
#define GICD_ITARGETSR(n) (0x0800 + ((n) * 4)) /* v1 ICDIPTR */
#define GICD_ICFGR(n) (0x0C00 + ((n) * 4)) /* v1 ICDICFR */
#define GICD_SGIR(n) (0x0F00 + ((n) * 4)) /* v1 ICDSGIR */
+#define GICD_SGI_TARGET_SHIFT 16
/* CPU Registers */
#define GICC_CTLR 0x0000 /* v1 ICCICR */
@@ -108,6 +109,8 @@ static struct resource_spec arm_gic_spec[] = {
{ -1, 0 }
};
+static u_int arm_gic_map[MAXCPU];
+
static struct arm_gic_softc *arm_gic_sc = NULL;
#define gic_c_read_4(_sc, _reg) \
@@ -124,6 +127,29 @@ static pic_eoi_t gic_eoi;
static pic_mask_t gic_mask_irq;
static pic_unmask_t gic_unmask_irq;
+static uint8_t
+gic_cpu_mask(struct arm_gic_softc *sc)
+{
+ uint32_t mask;
+ int i;
+
+ /* Read the current cpuid mask by reading ITARGETSR{0..7} */
+ for (i = 0; i < 8; i++) {
+ mask = gic_d_read_4(sc, GICD_ITARGETSR(i));
+ if (mask != 0)
+ break;
+ }
+ /* No mask found, assume we are on CPU interface 0 */
+ if (mask == 0)
+ return (1);
+
+ /* Collect the mask in the lower byte */
+ mask |= mask >> 16;
+ mask |= mask >> 8;
+
+ return (mask);
+}
+
#ifdef SMP
static void
gic_init_secondary(device_t dev)
@@ -131,6 +157,9 @@ gic_init_secondary(device_t dev)
struct arm_gic_softc *sc = device_get_softc(dev);
int i;
+ /* Set the mask so we can find this CPU to send it IPIs */
+ arm_gic_map[PCPU_GET(cpuid)] = gic_cpu_mask(sc);
+
for (i = 0; i < sc->nirqs; i += 4)
gic_d_write_4(sc, GICD_IPRIORITYR(i >> 2), 0);
@@ -162,7 +191,7 @@ arm_gic_attach(device_t dev)
{
struct arm_gic_softc *sc;
int i;
- uint32_t icciidr;
+ uint32_t icciidr, mask;
if (arm_gic_sc)
return (ENXIO);
@@ -212,10 +241,19 @@ arm_gic_attach(device_t dev)
gic_d_write_4(sc, GICD_ICENABLER(i >> 5), 0xFFFFFFFF);
}
+ /* Find the current cpu mask */
+ mask = gic_cpu_mask(sc);
+ /* Set the mask so we can find this CPU to send it IPIs */
+ arm_gic_map[PCPU_GET(cpuid)] = mask;
+ /* Set all four targets to this cpu */
+ mask |= mask << 8;
+ mask |= mask << 16;
+
for (i = 0; i < sc->nirqs; i += 4) {
gic_d_write_4(sc, GICD_IPRIORITYR(i >> 2), 0);
- gic_d_write_4(sc, GICD_ITARGETSR(i >> 2),
- 1 << 0 | 1 << 8 | 1 << 16 | 1 << 24);
+ if (i > 32) {
+ gic_d_write_4(sc, GICD_ITARGETSR(i >> 2), mask);
+ }
}
/* Set all the interrupts to be in Group 0 (secure) */
@@ -299,7 +337,7 @@ gic_ipi_send(device_t dev, cpuset_t cpus, u_int ipi)
for (i = 0; i < MAXCPU; i++)
if (CPU_ISSET(i, &cpus))
- val |= 1 << (16 + i);
+ val |= arm_gic_map[i] << GICD_SGI_TARGET_SHIFT;
gic_d_write_4(sc, GICD_SGIR(0), val | ipi);
}
diff --git a/sys/arm64/arm64/intr_machdep.c b/sys/arm64/arm64/intr_machdep.c
index 5994279..d99303e 100644
--- a/sys/arm64/arm64/intr_machdep.c
+++ b/sys/arm64/arm64/intr_machdep.c
@@ -408,7 +408,7 @@ arm_setup_intr(const char *name, driver_filter_t *filt, driver_intr_t handler,
}
int
-arm_teardown_intr(void *cookie)
+intr_irq_remove_handler(device_t dev, u_int irq, void *cookie)
{
struct arm64_intr_entry *intr;
int error;
@@ -426,7 +426,7 @@ arm_teardown_intr(void *cookie)
}
int
-arm_config_intr(u_int hw_irq, enum intr_trigger trig, enum intr_polarity pol)
+intr_irq_config(u_int hw_irq, enum intr_trigger trig, enum intr_polarity pol)
{
struct arm64_intr_entry *intr;
@@ -476,7 +476,7 @@ stray:
}
void
-arm_cpu_intr(struct trapframe *tf)
+intr_irq_handler(struct trapframe *tf)
{
critical_enter();
@@ -512,7 +512,7 @@ SYSINIT(arm_intr_smp_init, SI_SUB_SMP, SI_ORDER_ANY, arm_intr_smp_init, NULL);
/* Attempt to bind the specified IRQ to the specified CPU. */
int
-arm_intr_bind(u_int hw_irq, int cpu)
+intr_irq_bind(u_int hw_irq, int cpu)
{
struct arm64_intr_entry *intr;
diff --git a/sys/arm64/arm64/locore.S b/sys/arm64/arm64/locore.S
index b1fd3ae..676c1d5 100644
--- a/sys/arm64/arm64/locore.S
+++ b/sys/arm64/arm64/locore.S
@@ -35,7 +35,7 @@
#include <machine/param.h>
#include <machine/pte.h>
-#define VIRT_BITS 39
+#define VIRT_BITS 48
.globl kernbase
.set kernbase, KERNBASE
@@ -89,7 +89,8 @@ _start:
/*
* At this point:
* x27 = TTBR0 table
- * x26 = TTBR1 table
+ * x26 = Kernel L1 table
+ * x24 = TTBR1 table
*/
/* Enable the mmu */
@@ -100,16 +101,6 @@ _start:
br x15
virtdone:
- /*
- * Now that we are in virtual address space,
- * we don't need the identity mapping in TTBR0 and
- * can set the TCR to a more useful value.
- */
- ldr x2, tcr
- mrs x3, id_aa64mmfr0_el1
- bfi x2, x3, #32, #3
- msr tcr_el1, x2
-
/* Set up the stack */
adr x25, initstack_end
mov sp, x25
@@ -128,6 +119,7 @@ virtdone:
/* Make the page table base a virtual address */
sub x26, x26, x29
+ sub x24, x24, x29
sub sp, sp, #(64 * 4)
mov x0, sp
@@ -139,6 +131,7 @@ virtdone:
str x26, [x0, 8] /* kern_l1pt */
str x29, [x0, 16] /* kern_delta */
str x25, [x0, 24] /* kern_stack */
+ str x24, [x0, 32] /* kern_l0pt */
/* trace back starts here */
mov fp, #0
@@ -175,7 +168,7 @@ ENTRY(mpentry)
msr contextidr_el1, x1
/* Load the kernel page table */
- adr x26, pagetable_l1_ttbr1
+ adr x24, pagetable_l0_ttbr1
/* Load the identity page table */
adr x27, pagetable_l0_ttbr0
@@ -187,16 +180,6 @@ ENTRY(mpentry)
br x15
mp_virtdone:
- /*
- * Now that we are in virtual address space,
- * we don't need the identity mapping in TTBR0 and
- * can set the TCR to a more useful value.
- */
- ldr x2, tcr
- mrs x3, id_aa64mmfr0_el1
- bfi x2, x3, #32, #3
- msr tcr_el1, x2
-
ldr x4, =secondary_stacks
mov x5, #(PAGE_SIZE * KSTACK_PAGES)
mul x5, x0, x5
@@ -388,11 +371,18 @@ create_pagetables:
mov x6, x26
bl link_l1_pagetable
+ /* Move to the l0 table */
+ add x24, x26, #PAGE_SIZE
+
+ /* Link the l0 -> l1 table */
+ mov x9, x6
+ mov x6, x24
+ bl link_l0_pagetable
/*
* Build the TTBR0 maps.
*/
- add x27, x26, #PAGE_SIZE
+ add x27, x24, #PAGE_SIZE
mov x6, x27 /* The initial page table */
#if defined(SOCDEV_PA) && defined(SOCDEV_VA)
@@ -440,7 +430,7 @@ link_l0_pagetable:
*/
/* Find the table index */
lsr x11, x8, #L0_SHIFT
- and x11, x11, #Ln_ADDR_MASK
+ and x11, x11, #L0_ADDR_MASK
/* Build the L0 block entry */
mov x12, #L0_TABLE
@@ -582,7 +572,7 @@ start_mmu:
/* Load ttbr0 and ttbr1 */
msr ttbr0_el1, x27
- msr ttbr1_el1, x26
+ msr ttbr1_el1, x24
isb
/* Clear the Monitor Debug System control register */
@@ -596,11 +586,8 @@ start_mmu:
/*
* Setup TCR according to PARange bits from ID_AA64MMFR0_EL1.
- * Some machines have physical memory mapped >512GiB, which can not
- * be identity-mapped using the default 39 VA bits. Thus, use
- * 48 VA bits for now and switch back to 39 after the VA jump.
*/
- ldr x2, tcr_early
+ ldr x2, tcr
mrs x3, id_aa64mmfr0_el1
bfi x2, x3, #32, #3
msr tcr_el1, x2
@@ -623,9 +610,6 @@ mair:
tcr:
.quad (TCR_TxSZ(64 - VIRT_BITS) | TCR_ASID_16 | TCR_TG1_4K | \
TCR_CACHE_ATTRS | TCR_SMP_ATTRS)
-tcr_early:
- .quad (TCR_T1SZ(64 - VIRT_BITS) | TCR_T0SZ(64 - 48) | \
- TCR_ASID_16 | TCR_TG1_4K | TCR_CACHE_ATTRS | TCR_SMP_ATTRS)
sctlr_set:
/* Bits to set */
.quad (SCTLR_UCI | SCTLR_nTWE | SCTLR_nTWI | SCTLR_UCT | SCTLR_DZE | \
@@ -651,6 +635,8 @@ pagetable:
.space PAGE_SIZE
pagetable_l1_ttbr1:
.space PAGE_SIZE
+pagetable_l0_ttbr1:
+ .space PAGE_SIZE
pagetable_l1_ttbr0:
.space PAGE_SIZE
pagetable_l0_ttbr0:
diff --git a/sys/arm64/arm64/machdep.c b/sys/arm64/arm64/machdep.c
index 49c9610..2bf108f 100644
--- a/sys/arm64/arm64/machdep.c
+++ b/sys/arm64/arm64/machdep.c
@@ -108,6 +108,14 @@ struct kva_md_info kmi;
int64_t dcache_line_size; /* The minimum D cache line size */
int64_t icache_line_size; /* The minimum I cache line size */
int64_t idcache_line_size; /* The minimum cache line size */
+int64_t dczva_line_size; /* The size of cache line the dc zva zeroes */
+
+/* pagezero_* implementations are provided in support.S */
+void pagezero_simple(void *);
+void pagezero_cache(void *);
+
+/* pagezero_simple is default pagezero */
+void (*pagezero)(void *p) = pagezero_simple;
static void
cpu_startup(void *dummy)
@@ -129,16 +137,6 @@ cpu_idle_wakeup(int cpu)
return (0);
}
-void
-bzero(void *buf, size_t len)
-{
- uint8_t *p;
-
- p = buf;
- while(len-- > 0)
- *p++ = 0;
-}
-
int
fill_regs(struct thread *td, struct reg *regs)
{
@@ -800,8 +798,9 @@ try_load_dtb(caddr_t kmdp)
static void
cache_setup(void)
{
- int dcache_line_shift, icache_line_shift;
+ int dcache_line_shift, icache_line_shift, dczva_line_shift;
uint32_t ctr_el0;
+ uint32_t dczid_el0;
ctr_el0 = READ_SPECIALREG(ctr_el0);
@@ -815,6 +814,20 @@ cache_setup(void)
icache_line_size = sizeof(int) << icache_line_shift;
idcache_line_size = MIN(dcache_line_size, icache_line_size);
+
+ dczid_el0 = READ_SPECIALREG(dczid_el0);
+
+ /* Check if dc zva is not prohibited */
+ if (dczid_el0 & DCZID_DZP)
+ dczva_line_size = 0;
+ else {
+ /* Same as with above calculations */
+ dczva_line_shift = DCZID_BS_SIZE(dczid_el0);
+ dczva_line_size = sizeof(int) << dczva_line_shift;
+
+ /* Change pagezero function */
+ pagezero = pagezero_cache;
+ }
}
void
@@ -896,8 +909,8 @@ initarm(struct arm64_bootparams *abp)
cache_setup();
/* Bootstrap enough of pmap to enter the kernel proper */
- pmap_bootstrap(abp->kern_l1pt, KERNBASE - abp->kern_delta,
- lastaddr - KERNBASE);
+ pmap_bootstrap(abp->kern_l0pt, abp->kern_l1pt,
+ KERNBASE - abp->kern_delta, lastaddr - KERNBASE);
arm_devmap_bootstrap(0, NULL);
diff --git a/sys/arm64/arm64/minidump_machdep.c b/sys/arm64/arm64/minidump_machdep.c
index 56d1713..27c2081 100644
--- a/sys/arm64/arm64/minidump_machdep.c
+++ b/sys/arm64/arm64/minidump_machdep.c
@@ -218,7 +218,7 @@ blk_write(struct dumperinfo *di, char *ptr, vm_paddr_t pa, size_t sz)
int
minidumpsys(struct dumperinfo *di)
{
- pd_entry_t *l1, *l2;
+ pd_entry_t *l0, *l1, *l2;
pt_entry_t *l3;
uint32_t pmapsize;
vm_offset_t va;
@@ -236,7 +236,7 @@ minidumpsys(struct dumperinfo *di)
pmapsize = 0;
for (va = VM_MIN_KERNEL_ADDRESS; va < kernel_vm_end; va += L2_SIZE) {
pmapsize += PAGE_SIZE;
- if (!pmap_get_tables(pmap_kernel(), va, &l1, &l2, &l3))
+ if (!pmap_get_tables(pmap_kernel(), va, &l0, &l1, &l2, &l3))
continue;
/* We should always be using the l2 table for kvm */
@@ -335,7 +335,7 @@ minidumpsys(struct dumperinfo *di)
/* Dump kernel page directory pages */
bzero(&tmpbuffer, sizeof(tmpbuffer));
for (va = VM_MIN_KERNEL_ADDRESS; va < kernel_vm_end; va += L2_SIZE) {
- if (!pmap_get_tables(pmap_kernel(), va, &l1, &l2, &l3)) {
+ if (!pmap_get_tables(pmap_kernel(), va, &l0, &l1, &l2, &l3)) {
/* We always write a page, even if it is zero */
error = blk_write(di, (char *)&tmpbuffer, 0, PAGE_SIZE);
if (error)
diff --git a/sys/arm64/arm64/mp_machdep.c b/sys/arm64/arm64/mp_machdep.c
index b89982d..22c99ba 100644
--- a/sys/arm64/arm64/mp_machdep.c
+++ b/sys/arm64/arm64/mp_machdep.c
@@ -80,6 +80,12 @@ static device_identify_t arm64_cpu_identify;
static device_probe_t arm64_cpu_probe;
static device_attach_t arm64_cpu_attach;
+static void ipi_ast(void *);
+static void ipi_hardclock(void *);
+static void ipi_preempt(void *);
+static void ipi_rendezvous(void *);
+static void ipi_stop(void *);
+
static int ipi_handler(void *arg);
struct mtx ap_boot_mtx;
@@ -179,7 +185,7 @@ release_aps(void *dummy __unused)
int cpu, i;
/* Setup the IPI handler */
- for (i = 0; i < COUNT_IPI; i++)
+ for (i = 0; i < INTR_IPI_COUNT; i++)
arm_setup_ipihandler(ipi_handler, i);
atomic_store_rel_int(&aps_ready, 1);
@@ -238,7 +244,7 @@ init_secondary(uint64_t cpu)
/* Configure the interrupt controller */
arm_init_secondary();
- for (i = 0; i < COUNT_IPI; i++)
+ for (i = 0; i < INTR_IPI_COUNT; i++)
arm_unmask_ipi(i);
/* Start per-CPU event timers. */
@@ -271,13 +277,65 @@ init_secondary(uint64_t cpu)
/* NOTREACHED */
}
+static void
+ipi_ast(void *dummy __unused)
+{
+
+ CTR0(KTR_SMP, "IPI_AST");
+}
+
+static void
+ipi_hardclock(void *dummy __unused)
+{
+
+ CTR1(KTR_SMP, "%s: IPI_HARDCLOCK", __func__);
+ hardclockintr();
+}
+
+static void
+ipi_preempt(void *dummy __unused)
+{
+ CTR1(KTR_SMP, "%s: IPI_PREEMPT", __func__);
+ sched_preempt(curthread);
+}
+
+static void
+ipi_rendezvous(void *dummy __unused)
+{
+
+ CTR0(KTR_SMP, "IPI_RENDEZVOUS");
+ smp_rendezvous_action();
+}
+
+static void
+ipi_stop(void *dummy __unused)
+{
+ u_int cpu;
+
+ CTR0(KTR_SMP, "IPI_STOP");
+
+ cpu = PCPU_GET(cpuid);
+ savectx(&stoppcbs[cpu]);
+
+ /* Indicate we are stopped */
+ CPU_SET_ATOMIC(cpu, &stopped_cpus);
+
+ /* Wait for restart */
+ while (!CPU_ISSET(cpu, &started_cpus))
+ cpu_spinwait();
+
+ CPU_CLR_ATOMIC(cpu, &started_cpus);
+ CPU_CLR_ATOMIC(cpu, &stopped_cpus);
+ CTR0(KTR_SMP, "IPI_STOP (restart)");
+}
+
static int
ipi_handler(void *arg)
{
u_int cpu, ipi;
arg = (void *)((uintptr_t)arg & ~(1 << 16));
- KASSERT((uintptr_t)arg < COUNT_IPI,
+ KASSERT((uintptr_t)arg < INTR_IPI_COUNT,
("Invalid IPI %ju", (uintptr_t)arg));
cpu = PCPU_GET(cpuid);
@@ -285,35 +343,20 @@ ipi_handler(void *arg)
switch(ipi) {
case IPI_AST:
- CTR0(KTR_SMP, "IPI_AST");
+ ipi_ast(NULL);
break;
case IPI_PREEMPT:
- CTR1(KTR_SMP, "%s: IPI_PREEMPT", __func__);
- sched_preempt(curthread);
+ ipi_preempt(NULL);
break;
case IPI_RENDEZVOUS:
- CTR0(KTR_SMP, "IPI_RENDEZVOUS");
- smp_rendezvous_action();
+ ipi_rendezvous(NULL);
break;
case IPI_STOP:
case IPI_STOP_HARD:
- CTR0(KTR_SMP, (ipi == IPI_STOP) ? "IPI_STOP" : "IPI_STOP_HARD");
- savectx(&stoppcbs[cpu]);
-
- /* Indicate we are stopped */
- CPU_SET_ATOMIC(cpu, &stopped_cpus);
-
- /* Wait for restart */
- while (!CPU_ISSET(cpu, &started_cpus))
- cpu_spinwait();
-
- CPU_CLR_ATOMIC(cpu, &started_cpus);
- CPU_CLR_ATOMIC(cpu, &stopped_cpus);
- CTR0(KTR_SMP, "IPI_STOP (restart)");
+ ipi_stop(NULL);
break;
case IPI_HARDCLOCK:
- CTR1(KTR_SMP, "%s: IPI_HARDCLOCK", __func__);
- hardclockintr();
+ ipi_hardclock(NULL);
break;
default:
panic("Unknown IPI %#0x on cpu %d", ipi, curcpu);
diff --git a/sys/arm64/arm64/nexus.c b/sys/arm64/arm64/nexus.c
index cdc5fc8..f48a7aa 100644
--- a/sys/arm64/arm64/nexus.c
+++ b/sys/arm64/arm64/nexus.c
@@ -39,6 +39,9 @@
* and I/O memory address space.
*/
+#include "opt_acpi.h"
+#include "opt_platform.h"
+
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -60,9 +63,6 @@ __FBSDID("$FreeBSD$");
#include <machine/resource.h>
#include <machine/intr.h>
-#include "opt_acpi.h"
-#include "opt_platform.h"
-
#ifdef FDT
#include <dev/ofw/openfirm.h>
#include "ofw_bus_if.h"
@@ -271,7 +271,7 @@ nexus_config_intr(device_t dev, int irq, enum intr_trigger trig,
enum intr_polarity pol)
{
- return (arm_config_intr(irq, trig, pol));
+ return (intr_irq_config(irq, trig, pol));
}
static int
@@ -298,7 +298,7 @@ static int
nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih)
{
- return (arm_teardown_intr(ih));
+ return (intr_irq_remove_handler(child, rman_get_start(r), ih));
}
#ifdef SMP
@@ -306,7 +306,7 @@ static int
nexus_bind_intr(device_t dev, device_t child, struct resource *irq, int cpu)
{
- return (arm_intr_bind(rman_get_start(irq), cpu));
+ return (intr_irq_bind(rman_get_start(irq), cpu));
}
#endif
diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c
index 5db731d..5eeccdd 100644
--- a/sys/arm64/arm64/pmap.c
+++ b/sys/arm64/arm64/pmap.c
@@ -11,7 +11,7 @@
* All rights reserved.
* Copyright (c) 2014 Andrew Turner
* All rights reserved.
- * Copyright (c) 2014 The FreeBSD Foundation
+ * Copyright (c) 2014-2016 The FreeBSD Foundation
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -142,9 +142,14 @@ __FBSDID("$FreeBSD$");
#include <machine/md_var.h>
#include <machine/pcb.h>
-#define NPDEPG (PAGE_SIZE/(sizeof (pd_entry_t)))
-#define NUPDE (NPDEPG * NPDEPG)
-#define NUSERPGTBLS (NUPDE + NPDEPG)
+#define NL0PG (PAGE_SIZE/(sizeof (pd_entry_t)))
+#define NL1PG (PAGE_SIZE/(sizeof (pd_entry_t)))
+#define NL2PG (PAGE_SIZE/(sizeof (pd_entry_t)))
+#define NL3PG (PAGE_SIZE/(sizeof (pt_entry_t)))
+
+#define NUL0E L0_ENTRIES
+#define NUL1E (NUL0E * NL1PG)
+#define NUL2E (NUL1E * NL2PG)
#if !defined(DIAGNOSTIC)
#ifdef __GNUC_GNU_INLINE__
@@ -266,22 +271,37 @@ pagecopy(void *s, void *d)
memcpy(d, s, PAGE_SIZE);
}
-static __inline void
-pagezero(void *p)
+#define pmap_l0_index(va) (((va) >> L0_SHIFT) & L0_ADDR_MASK)
+#define pmap_l1_index(va) (((va) >> L1_SHIFT) & Ln_ADDR_MASK)
+#define pmap_l2_index(va) (((va) >> L2_SHIFT) & Ln_ADDR_MASK)
+#define pmap_l3_index(va) (((va) >> L3_SHIFT) & Ln_ADDR_MASK)
+
+static __inline pd_entry_t *
+pmap_l0(pmap_t pmap, vm_offset_t va)
{
- bzero(p, PAGE_SIZE);
+ return (&pmap->pm_l0[pmap_l0_index(va)]);
}
-#define pmap_l1_index(va) (((va) >> L1_SHIFT) & Ln_ADDR_MASK)
-#define pmap_l2_index(va) (((va) >> L2_SHIFT) & Ln_ADDR_MASK)
-#define pmap_l3_index(va) (((va) >> L3_SHIFT) & Ln_ADDR_MASK)
+static __inline pd_entry_t *
+pmap_l0_to_l1(pd_entry_t *l0, vm_offset_t va)
+{
+ pd_entry_t *l1;
+
+ l1 = (pd_entry_t *)PHYS_TO_DMAP(pmap_load(l0) & ~ATTR_MASK);
+ return (&l1[pmap_l1_index(va)]);
+}
static __inline pd_entry_t *
pmap_l1(pmap_t pmap, vm_offset_t va)
{
+ pd_entry_t *l0;
- return (&pmap->pm_l1[pmap_l1_index(va)]);
+ l0 = pmap_l0(pmap, va);
+ if ((pmap_load(l0) & ATTR_DESCR_MASK) != L0_TABLE)
+ return (NULL);
+
+ return (pmap_l0_to_l1(l0, va));
}
static __inline pd_entry_t *
@@ -314,28 +334,103 @@ pmap_l2_to_l3(pd_entry_t *l2, vm_offset_t va)
return (&l3[pmap_l3_index(va)]);
}
+/*
+ * Returns the lowest valid pde for a given virtual address.
+ * The next level may or may not point to a valid page or block.
+ */
+static __inline pd_entry_t *
+pmap_pde(pmap_t pmap, vm_offset_t va, int *level)
+{
+ pd_entry_t *l0, *l1, *l2, desc;
+
+ l0 = pmap_l0(pmap, va);
+ desc = pmap_load(l0) & ATTR_DESCR_MASK;
+ if (desc != L0_TABLE) {
+ *level = -1;
+ return (NULL);
+ }
+
+ l1 = pmap_l0_to_l1(l0, va);
+ desc = pmap_load(l1) & ATTR_DESCR_MASK;
+ if (desc != L1_TABLE) {
+ *level = 0;
+ return (l0);
+ }
+
+ l2 = pmap_l1_to_l2(l1, va);
+ desc = pmap_load(l2) & ATTR_DESCR_MASK;
+ if (desc != L2_TABLE) {
+ *level = 1;
+ return (l1);
+ }
+
+ *level = 2;
+ return (l2);
+}
+
+/*
+ * Returns the lowest valid pte block or table entry for a given virtual
+ * address. If there are no valid entries return NULL and set the level to
+ * the first invalid level.
+ */
static __inline pt_entry_t *
-pmap_l3(pmap_t pmap, vm_offset_t va)
+pmap_pte(pmap_t pmap, vm_offset_t va, int *level)
{
- pd_entry_t *l2;
+ pd_entry_t *l1, *l2, desc;
+ pt_entry_t *l3;
- l2 = pmap_l2(pmap, va);
- if (l2 == NULL || (pmap_load(l2) & ATTR_DESCR_MASK) != L2_TABLE)
+ l1 = pmap_l1(pmap, va);
+ if (l1 == NULL) {
+ *level = 0;
return (NULL);
+ }
+ desc = pmap_load(l1) & ATTR_DESCR_MASK;
+ if (desc == L1_BLOCK) {
+ *level = 1;
+ return (l1);
+ }
+
+ if (desc != L1_TABLE) {
+ *level = 1;
+ return (NULL);
+ }
+
+ l2 = pmap_l1_to_l2(l1, va);
+ desc = pmap_load(l2) & ATTR_DESCR_MASK;
+ if (desc == L2_BLOCK) {
+ *level = 2;
+ return (l2);
+ }
- return (pmap_l2_to_l3(l2, va));
+ if (desc != L2_TABLE) {
+ *level = 2;
+ return (NULL);
+ }
+
+ *level = 3;
+ l3 = pmap_l2_to_l3(l2, va);
+ if ((pmap_load(l3) & ATTR_DESCR_MASK) != L3_PAGE)
+ return (NULL);
+
+ return (l3);
}
bool
-pmap_get_tables(pmap_t pmap, vm_offset_t va, pd_entry_t **l1, pd_entry_t **l2,
- pt_entry_t **l3)
+pmap_get_tables(pmap_t pmap, vm_offset_t va, pd_entry_t **l0, pd_entry_t **l1,
+ pd_entry_t **l2, pt_entry_t **l3)
{
- pd_entry_t *l1p, *l2p;
+ pd_entry_t *l0p, *l1p, *l2p;
- if (pmap->pm_l1 == NULL)
+ if (pmap->pm_l0 == NULL)
return (false);
- l1p = pmap_l1(pmap, va);
+ l0p = pmap_l0(pmap, va);
+ *l0 = l0p;
+
+ if ((pmap_load(l0p) & ATTR_DESCR_MASK) != L0_TABLE)
+ return (false);
+
+ l1p = pmap_l0_to_l1(l0p, va);
*l1 = l1p;
if ((pmap_load(l1p) & ATTR_DESCR_MASK) == L1_BLOCK) {
@@ -544,7 +639,8 @@ pmap_bootstrap_l3(vm_offset_t l1pt, vm_offset_t va, vm_offset_t l3_start)
* Bootstrap the system enough to run with virtual memory.
*/
void
-pmap_bootstrap(vm_offset_t l1pt, vm_paddr_t kernstart, vm_size_t kernlen)
+pmap_bootstrap(vm_offset_t l0pt, vm_offset_t l1pt, vm_paddr_t kernstart,
+ vm_size_t kernlen)
{
u_int l1_slot, l2_slot, avail_slot, map_slot, used_map_slot;
uint64_t kern_delta;
@@ -562,7 +658,7 @@ pmap_bootstrap(vm_offset_t l1pt, vm_paddr_t kernstart, vm_size_t kernlen)
printf("%lx\n", (KERNBASE >> L1_SHIFT) & Ln_ADDR_MASK);
/* Set this early so we can use the pagetable walking functions */
- kernel_pmap_store.pm_l1 = (pd_entry_t *)l1pt;
+ kernel_pmap_store.pm_l0 = (pd_entry_t *)l0pt;
PMAP_LOCK_INIT(kernel_pmap);
/*
@@ -805,30 +901,40 @@ pmap_invalidate_all(pmap_t pmap)
vm_paddr_t
pmap_extract(pmap_t pmap, vm_offset_t va)
{
- pd_entry_t *l2p, l2;
- pt_entry_t *l3p, l3;
+ pt_entry_t *pte, tpte;
vm_paddr_t pa;
+ int lvl;
pa = 0;
PMAP_LOCK(pmap);
/*
- * Start with the l2 tabel. We are unable to allocate
- * pages in the l1 table.
+ * Find the block or page map for this virtual address. pmap_pte
+ * will return either a valid block/page entry, or NULL.
*/
- l2p = pmap_l2(pmap, va);
- if (l2p != NULL) {
- l2 = pmap_load(l2p);
- if ((l2 & ATTR_DESCR_MASK) == L2_TABLE) {
- l3p = pmap_l2_to_l3(l2p, va);
- if (l3p != NULL) {
- l3 = pmap_load(l3p);
-
- if ((l3 & ATTR_DESCR_MASK) == L3_PAGE)
- pa = (l3 & ~ATTR_MASK) |
- (va & L3_OFFSET);
- }
- } else if ((l2 & ATTR_DESCR_MASK) == L2_BLOCK)
- pa = (l2 & ~ATTR_MASK) | (va & L2_OFFSET);
+ pte = pmap_pte(pmap, va, &lvl);
+ if (pte != NULL) {
+ tpte = pmap_load(pte);
+ pa = tpte & ~ATTR_MASK;
+ switch(lvl) {
+ case 1:
+ KASSERT((tpte & ATTR_DESCR_MASK) == L1_BLOCK,
+ ("pmap_extract: Invalid L1 pte found: %lx",
+ tpte & ATTR_DESCR_MASK));
+ pa |= (va & L1_OFFSET);
+ break;
+ case 2:
+ KASSERT((tpte & ATTR_DESCR_MASK) == L2_BLOCK,
+ ("pmap_extract: Invalid L2 pte found: %lx",
+ tpte & ATTR_DESCR_MASK));
+ pa |= (va & L2_OFFSET);
+ break;
+ case 3:
+ KASSERT((tpte & ATTR_DESCR_MASK) == L3_PAGE,
+ ("pmap_extract: Invalid L3 pte found: %lx",
+ tpte & ATTR_DESCR_MASK));
+ pa |= (va & L3_OFFSET);
+ break;
+ }
}
PMAP_UNLOCK(pmap);
return (pa);
@@ -844,21 +950,31 @@ pmap_extract(pmap_t pmap, vm_offset_t va)
vm_page_t
pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot)
{
- pt_entry_t *l3p, l3;
+ pt_entry_t *pte, tpte;
vm_paddr_t pa;
vm_page_t m;
+ int lvl;
pa = 0;
m = NULL;
PMAP_LOCK(pmap);
retry:
- l3p = pmap_l3(pmap, va);
- if (l3p != NULL && (l3 = pmap_load(l3p)) != 0) {
- if (((l3 & ATTR_AP_RW_BIT) == ATTR_AP(ATTR_AP_RW)) ||
+ pte = pmap_pte(pmap, va, &lvl);
+ if (pte != NULL) {
+ tpte = pmap_load(pte);
+
+ KASSERT(lvl > 0 && lvl <= 3,
+ ("pmap_extract_and_hold: Invalid level %d", lvl));
+ CTASSERT(L1_BLOCK == L2_BLOCK);
+ KASSERT((lvl == 3 && (tpte & ATTR_DESCR_MASK) == L3_PAGE) ||
+ (lvl < 3 && (tpte & ATTR_DESCR_MASK) == L1_BLOCK),
+ ("pmap_extract_and_hold: Invalid pte at L%d: %lx", lvl,
+ tpte & ATTR_DESCR_MASK));
+ if (((tpte & ATTR_AP_RW_BIT) == ATTR_AP(ATTR_AP_RW)) ||
((prot & VM_PROT_WRITE) == 0)) {
- if (vm_page_pa_tryrelock(pmap, l3 & ~ATTR_MASK, &pa))
+ if (vm_page_pa_tryrelock(pmap, tpte & ~ATTR_MASK, &pa))
goto retry;
- m = PHYS_TO_VM_PAGE(l3 & ~ATTR_MASK);
+ m = PHYS_TO_VM_PAGE(tpte & ~ATTR_MASK);
vm_page_hold(m);
}
}
@@ -870,25 +986,39 @@ retry:
vm_paddr_t
pmap_kextract(vm_offset_t va)
{
- pd_entry_t *l2p, l2;
- pt_entry_t *l3;
+ pt_entry_t *pte, tpte;
vm_paddr_t pa;
+ int lvl;
if (va >= DMAP_MIN_ADDRESS && va < DMAP_MAX_ADDRESS) {
pa = DMAP_TO_PHYS(va);
} else {
- l2p = pmap_l2(kernel_pmap, va);
- if (l2p == NULL)
- panic("pmap_kextract: No l2");
- l2 = pmap_load(l2p);
- if ((l2 & ATTR_DESCR_MASK) == L2_BLOCK)
- return ((l2 & ~ATTR_MASK) |
- (va & L2_OFFSET));
-
- l3 = pmap_l2_to_l3(l2p, va);
- if (l3 == NULL)
- panic("pmap_kextract: No l3...");
- pa = (pmap_load(l3) & ~ATTR_MASK) | (va & PAGE_MASK);
+ pa = 0;
+ pte = pmap_pte(kernel_pmap, va, &lvl);
+ if (pte != NULL) {
+ tpte = pmap_load(pte);
+ pa = tpte & ~ATTR_MASK;
+ switch(lvl) {
+ case 1:
+ KASSERT((tpte & ATTR_DESCR_MASK) == L1_BLOCK,
+ ("pmap_kextract: Invalid L1 pte found: %lx",
+ tpte & ATTR_DESCR_MASK));
+ pa |= (va & L1_OFFSET);
+ break;
+ case 2:
+ KASSERT((tpte & ATTR_DESCR_MASK) == L2_BLOCK,
+ ("pmap_kextract: Invalid L2 pte found: %lx",
+ tpte & ATTR_DESCR_MASK));
+ pa |= (va & L2_OFFSET);
+ break;
+ case 3:
+ KASSERT((tpte & ATTR_DESCR_MASK) == L3_PAGE,
+ ("pmap_kextract: Invalid L3 pte found: %lx",
+ tpte & ATTR_DESCR_MASK));
+ pa |= (va & L3_OFFSET);
+ break;
+ }
+ }
}
return (pa);
}
@@ -900,8 +1030,10 @@ pmap_kextract(vm_offset_t va)
void
pmap_kenter_device(vm_offset_t sva, vm_size_t size, vm_paddr_t pa)
{
- pt_entry_t *l3;
+ pd_entry_t *pde;
+ pt_entry_t *pte;
vm_offset_t va;
+ int lvl;
KASSERT((pa & L3_OFFSET) == 0,
("pmap_kenter_device: Invalid physical address"));
@@ -912,11 +1044,16 @@ pmap_kenter_device(vm_offset_t sva, vm_size_t size, vm_paddr_t pa)
va = sva;
while (size != 0) {
- l3 = pmap_l3(kernel_pmap, va);
- KASSERT(l3 != NULL, ("Invalid page table, va: 0x%lx", va));
- pmap_load_store(l3, (pa & ~L3_OFFSET) | ATTR_DEFAULT |
+ pde = pmap_pde(kernel_pmap, va, &lvl);
+ KASSERT(pde != NULL,
+ ("pmap_kenter_device: Invalid page entry, va: 0x%lx", va));
+ KASSERT(lvl == 2,
+ ("pmap_kenter_device: Invalid level %d", lvl));
+
+ pte = pmap_l2_to_l3(pde, va);
+ pmap_load_store(pte, (pa & ~L3_OFFSET) | ATTR_DEFAULT |
ATTR_IDX(DEVICE_MEMORY) | L3_PAGE);
- PTE_SYNC(l3);
+ PTE_SYNC(pte);
va += PAGE_SIZE;
pa += PAGE_SIZE;
@@ -927,28 +1064,30 @@ pmap_kenter_device(vm_offset_t sva, vm_size_t size, vm_paddr_t pa)
/*
* Remove a page from the kernel pagetables.
- * Note: not SMP coherent.
*/
PMAP_INLINE void
pmap_kremove(vm_offset_t va)
{
- pt_entry_t *l3;
+ pt_entry_t *pte;
+ int lvl;
- l3 = pmap_l3(kernel_pmap, va);
- KASSERT(l3 != NULL, ("pmap_kremove: Invalid address"));
+ pte = pmap_pte(kernel_pmap, va, &lvl);
+ KASSERT(pte != NULL, ("pmap_kremove: Invalid address"));
+ KASSERT(lvl == 3, ("pmap_kremove: Invalid pte level %d", lvl));
- if (pmap_l3_valid_cacheable(pmap_load(l3)))
+ if (pmap_l3_valid_cacheable(pmap_load(pte)))
cpu_dcache_wb_range(va, L3_SIZE);
- pmap_load_clear(l3);
- PTE_SYNC(l3);
+ pmap_load_clear(pte);
+ PTE_SYNC(pte);
pmap_invalidate_page(kernel_pmap, va);
}
void
pmap_kremove_device(vm_offset_t sva, vm_size_t size)
{
- pt_entry_t *l3;
+ pt_entry_t *pte;
vm_offset_t va;
+ int lvl;
KASSERT((sva & L3_OFFSET) == 0,
("pmap_kremove_device: Invalid virtual address"));
@@ -957,10 +1096,12 @@ pmap_kremove_device(vm_offset_t sva, vm_size_t size)
va = sva;
while (size != 0) {
- l3 = pmap_l3(kernel_pmap, va);
- KASSERT(l3 != NULL, ("Invalid page table, va: 0x%lx", va));
- pmap_load_clear(l3);
- PTE_SYNC(l3);
+ pte = pmap_pte(kernel_pmap, va, &lvl);
+ KASSERT(pte != NULL, ("Invalid page table, va: 0x%lx", va));
+ KASSERT(lvl == 3,
+ ("Invalid device pagetable level: %d != 3", lvl));
+ pmap_load_clear(pte);
+ PTE_SYNC(pte);
va += PAGE_SIZE;
size -= PAGE_SIZE;
@@ -999,19 +1140,26 @@ pmap_map(vm_offset_t *virt, vm_paddr_t start, vm_paddr_t end, int prot)
void
pmap_qenter(vm_offset_t sva, vm_page_t *ma, int count)
{
- pt_entry_t *l3, pa;
+ pd_entry_t *pde;
+ pt_entry_t *pte, pa;
vm_offset_t va;
vm_page_t m;
- int i;
+ int i, lvl;
va = sva;
for (i = 0; i < count; i++) {
+ pde = pmap_pde(kernel_pmap, va, &lvl);
+ KASSERT(pde != NULL,
+ ("pmap_qenter: Invalid page entry, va: 0x%lx", va));
+ KASSERT(lvl == 2,
+ ("pmap_qenter: Invalid level %d", lvl));
+
m = ma[i];
pa = VM_PAGE_TO_PHYS(m) | ATTR_DEFAULT | ATTR_AP(ATTR_AP_RW) |
ATTR_IDX(m->md.pv_memattr) | L3_PAGE;
- l3 = pmap_l3(kernel_pmap, va);
- pmap_load_store(l3, pa);
- PTE_SYNC(l3);
+ pte = pmap_l2_to_l3(pde, va);
+ pmap_load_store(pte, pa);
+ PTE_SYNC(pte);
va += L3_SIZE;
}
@@ -1021,25 +1169,27 @@ pmap_qenter(vm_offset_t sva, vm_page_t *ma, int count)
/*
* This routine tears out page mappings from the
* kernel -- it is meant only for temporary mappings.
- * Note: SMP coherent. Uses a ranged shootdown IPI.
*/
void
pmap_qremove(vm_offset_t sva, int count)
{
- pt_entry_t *l3;
+ pt_entry_t *pte;
vm_offset_t va;
+ int lvl;
KASSERT(sva >= VM_MIN_KERNEL_ADDRESS, ("usermode va %lx", sva));
va = sva;
while (count-- > 0) {
- l3 = pmap_l3(kernel_pmap, va);
- KASSERT(l3 != NULL, ("pmap_kremove: Invalid address"));
-
- if (pmap_l3_valid_cacheable(pmap_load(l3)))
- cpu_dcache_wb_range(va, L3_SIZE);
- pmap_load_clear(l3);
- PTE_SYNC(l3);
+ pte = pmap_pte(kernel_pmap, va, &lvl);
+ KASSERT(lvl == 3,
+ ("Invalid device pagetable level: %d != 3", lvl));
+ if (pte != NULL) {
+ if (pmap_l3_valid_cacheable(pmap_load(pte)))
+ cpu_dcache_wb_range(va, L3_SIZE);
+ pmap_load_clear(pte);
+ PTE_SYNC(pte);
+ }
va += PAGE_SIZE;
}
@@ -1104,26 +1254,47 @@ _pmap_unwire_l3(pmap_t pmap, vm_offset_t va, vm_page_t m, struct spglist *free)
/*
* unmap the page table page
*/
- if (m->pindex >= NUPDE) {
- /* PD page */
+ if (m->pindex >= (NUL2E + NUL1E)) {
+ /* l1 page */
+ pd_entry_t *l0;
+
+ l0 = pmap_l0(pmap, va);
+ pmap_load_clear(l0);
+ PTE_SYNC(l0);
+ } else if (m->pindex >= NUL2E) {
+ /* l2 page */
pd_entry_t *l1;
+
l1 = pmap_l1(pmap, va);
pmap_load_clear(l1);
PTE_SYNC(l1);
} else {
- /* PTE page */
+ /* l3 page */
pd_entry_t *l2;
+
l2 = pmap_l2(pmap, va);
pmap_load_clear(l2);
PTE_SYNC(l2);
}
pmap_resident_count_dec(pmap, 1);
- if (m->pindex < NUPDE) {
- /* We just released a PT, unhold the matching PD */
- vm_page_t pdpg;
+ if (m->pindex < NUL2E) {
+ /* We just released an l3, unhold the matching l2 */
+ pd_entry_t *l1, tl1;
+ vm_page_t l2pg;
- pdpg = PHYS_TO_VM_PAGE(*pmap_l1(pmap, va) & ~ATTR_MASK);
- pmap_unwire_l3(pmap, va, pdpg, free);
+ l1 = pmap_l1(pmap, va);
+ tl1 = pmap_load(l1);
+ l2pg = PHYS_TO_VM_PAGE(tl1 & ~ATTR_MASK);
+ pmap_unwire_l3(pmap, va, l2pg, free);
+ } else if (m->pindex < (NUL2E + NUL1E)) {
+ /* We just released an l2, unhold the matching l1 */
+ pd_entry_t *l0, tl0;
+ vm_page_t l1pg;
+
+ l0 = pmap_l0(pmap, va);
+ tl0 = pmap_load(l0);
+ l1pg = PHYS_TO_VM_PAGE(tl0 & ~ATTR_MASK);
+ pmap_unwire_l3(pmap, va, l1pg, free);
}
pmap_invalidate_page(pmap, va);
@@ -1164,27 +1335,27 @@ pmap_pinit0(pmap_t pmap)
PMAP_LOCK_INIT(pmap);
bzero(&pmap->pm_stats, sizeof(pmap->pm_stats));
- pmap->pm_l1 = kernel_pmap->pm_l1;
+ pmap->pm_l0 = kernel_pmap->pm_l0;
}
int
pmap_pinit(pmap_t pmap)
{
- vm_paddr_t l1phys;
- vm_page_t l1pt;
+ vm_paddr_t l0phys;
+ vm_page_t l0pt;
/*
- * allocate the l1 page
+ * allocate the l0 page
*/
- while ((l1pt = vm_page_alloc(NULL, 0xdeadbeef, VM_ALLOC_NORMAL |
+ while ((l0pt = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL |
VM_ALLOC_NOOBJ | VM_ALLOC_WIRED | VM_ALLOC_ZERO)) == NULL)
VM_WAIT;
- l1phys = VM_PAGE_TO_PHYS(l1pt);
- pmap->pm_l1 = (pd_entry_t *)PHYS_TO_DMAP(l1phys);
+ l0phys = VM_PAGE_TO_PHYS(l0pt);
+ pmap->pm_l0 = (pd_entry_t *)PHYS_TO_DMAP(l0phys);
- if ((l1pt->flags & PG_ZERO) == 0)
- pagezero(pmap->pm_l1);
+ if ((l0pt->flags & PG_ZERO) == 0)
+ pagezero(pmap->pm_l0);
bzero(&pmap->pm_stats, sizeof(pmap->pm_stats));
@@ -1205,7 +1376,7 @@ pmap_pinit(pmap_t pmap)
static vm_page_t
_pmap_alloc_l3(pmap_t pmap, vm_pindex_t ptepindex, struct rwlock **lockp)
{
- vm_page_t m, /*pdppg, */pdpg;
+ vm_page_t m, l1pg, l2pg;
PMAP_LOCK_ASSERT(pmap, MA_OWNED);
@@ -1237,33 +1408,84 @@ _pmap_alloc_l3(pmap_t pmap, vm_pindex_t ptepindex, struct rwlock **lockp)
* it isn't already there.
*/
- if (ptepindex >= NUPDE) {
- pd_entry_t *l1;
- vm_pindex_t l1index;
+ if (ptepindex >= (NUL2E + NUL1E)) {
+ pd_entry_t *l0;
+ vm_pindex_t l0index;
+
+ l0index = ptepindex - (NUL2E + NUL1E);
+ l0 = &pmap->pm_l0[l0index];
+ pmap_load_store(l0, VM_PAGE_TO_PHYS(m) | L0_TABLE);
+ PTE_SYNC(l0);
+ } else if (ptepindex >= NUL2E) {
+ vm_pindex_t l0index, l1index;
+ pd_entry_t *l0, *l1;
+ pd_entry_t tl0;
+
+ l1index = ptepindex - NUL2E;
+ l0index = l1index >> L0_ENTRIES_SHIFT;
+
+ l0 = &pmap->pm_l0[l0index];
+ tl0 = pmap_load(l0);
+ if (tl0 == 0) {
+ /* recurse for allocating page dir */
+ if (_pmap_alloc_l3(pmap, NUL2E + NUL1E + l0index,
+ lockp) == NULL) {
+ --m->wire_count;
+ /* XXX: release mem barrier? */
+ atomic_subtract_int(&vm_cnt.v_wire_count, 1);
+ vm_page_free_zero(m);
+ return (NULL);
+ }
+ } else {
+ l1pg = PHYS_TO_VM_PAGE(tl0 & ~ATTR_MASK);
+ l1pg->wire_count++;
+ }
- l1index = ptepindex - NUPDE;
- l1 = &pmap->pm_l1[l1index];
+ l1 = (pd_entry_t *)PHYS_TO_DMAP(pmap_load(l0) & ~ATTR_MASK);
+ l1 = &l1[ptepindex & Ln_ADDR_MASK];
pmap_load_store(l1, VM_PAGE_TO_PHYS(m) | L1_TABLE);
PTE_SYNC(l1);
-
} else {
- vm_pindex_t l1index;
- pd_entry_t *l1, *l2;
+ vm_pindex_t l0index, l1index;
+ pd_entry_t *l0, *l1, *l2;
+ pd_entry_t tl0, tl1;
- l1index = ptepindex >> (L1_SHIFT - L2_SHIFT);
- l1 = &pmap->pm_l1[l1index];
- if (pmap_load(l1) == 0) {
+ l1index = ptepindex >> Ln_ENTRIES_SHIFT;
+ l0index = l1index >> L0_ENTRIES_SHIFT;
+
+ l0 = &pmap->pm_l0[l0index];
+ tl0 = pmap_load(l0);
+ if (tl0 == 0) {
/* recurse for allocating page dir */
- if (_pmap_alloc_l3(pmap, NUPDE + l1index,
+ if (_pmap_alloc_l3(pmap, NUL2E + l1index,
lockp) == NULL) {
--m->wire_count;
atomic_subtract_int(&vm_cnt.v_wire_count, 1);
vm_page_free_zero(m);
return (NULL);
}
+ tl0 = pmap_load(l0);
+ l1 = (pd_entry_t *)PHYS_TO_DMAP(tl0 & ~ATTR_MASK);
+ l1 = &l1[l1index & Ln_ADDR_MASK];
} else {
- pdpg = PHYS_TO_VM_PAGE(pmap_load(l1) & ~ATTR_MASK);
- pdpg->wire_count++;
+ l1 = (pd_entry_t *)PHYS_TO_DMAP(tl0 & ~ATTR_MASK);
+ l1 = &l1[l1index & Ln_ADDR_MASK];
+ tl1 = pmap_load(l1);
+ if (tl1 == 0) {
+ /* recurse for allocating page dir */
+ if (_pmap_alloc_l3(pmap, NUL2E + l1index,
+ lockp) == NULL) {
+ --m->wire_count;
+ /* XXX: release mem barrier? */
+ atomic_subtract_int(
+ &vm_cnt.v_wire_count, 1);
+ vm_page_free_zero(m);
+ return (NULL);
+ }
+ } else {
+ l2pg = PHYS_TO_VM_PAGE(tl1 & ~ATTR_MASK);
+ l2pg->wire_count++;
+ }
}
l2 = (pd_entry_t *)PHYS_TO_DMAP(pmap_load(l1) & ~ATTR_MASK);
@@ -1281,8 +1503,9 @@ static vm_page_t
pmap_alloc_l3(pmap_t pmap, vm_offset_t va, struct rwlock **lockp)
{
vm_pindex_t ptepindex;
- pd_entry_t *l2;
+ pd_entry_t *pde, tpde;
vm_page_t m;
+ int lvl;
/*
* Calculate pagetable page index
@@ -1292,24 +1515,29 @@ retry:
/*
* Get the page directory entry
*/
- l2 = pmap_l2(pmap, va);
+ pde = pmap_pde(pmap, va, &lvl);
/*
- * If the page table page is mapped, we just increment the
- * hold count, and activate it.
+ * If the page table page is mapped, we just increment the hold count,
+ * and activate it. If we get a level 2 pde it will point to a level 3
+ * table.
*/
- if (l2 != NULL && pmap_load(l2) != 0) {
- m = PHYS_TO_VM_PAGE(pmap_load(l2) & ~ATTR_MASK);
- m->wire_count++;
- } else {
- /*
- * Here if the pte page isn't mapped, or if it has been
- * deallocated.
- */
- m = _pmap_alloc_l3(pmap, ptepindex, lockp);
- if (m == NULL && lockp != NULL)
- goto retry;
+ if (lvl == 2) {
+ tpde = pmap_load(pde);
+ if (tpde != 0) {
+ m = PHYS_TO_VM_PAGE(tpde & ~ATTR_MASK);
+ m->wire_count++;
+ return (m);
+ }
}
+
+ /*
+ * Here if the pte page isn't mapped, or if it has been deallocated.
+ */
+ m = _pmap_alloc_l3(pmap, ptepindex, lockp);
+ if (m == NULL && lockp != NULL)
+ goto retry;
+
return (m);
}
@@ -1332,7 +1560,7 @@ pmap_release(pmap_t pmap)
("pmap_release: pmap resident count %ld != 0",
pmap->pm_stats.resident_count));
- m = PHYS_TO_VM_PAGE(DMAP_TO_PHYS((vm_offset_t)pmap->pm_l1));
+ m = PHYS_TO_VM_PAGE(DMAP_TO_PHYS((vm_offset_t)pmap->pm_l0));
m->wire_count--;
atomic_subtract_int(&vm_cnt.v_wire_count, 1);
@@ -1369,7 +1597,7 @@ pmap_growkernel(vm_offset_t addr)
{
vm_paddr_t paddr;
vm_page_t nkpg;
- pd_entry_t *l1, *l2;
+ pd_entry_t *l0, *l1, *l2;
mtx_assert(&kernel_map->system_mtx, MA_OWNED);
@@ -1377,7 +1605,11 @@ pmap_growkernel(vm_offset_t addr)
if (addr - 1 >= kernel_map->max_offset)
addr = kernel_map->max_offset;
while (kernel_vm_end < addr) {
- l1 = pmap_l1(kernel_pmap, kernel_vm_end);
+ l0 = pmap_l0(kernel_pmap, kernel_vm_end);
+ KASSERT(pmap_load(l0) != 0,
+ ("pmap_growkernel: No level 0 kernel entry"));
+
+ l1 = pmap_l0_to_l1(l0, kernel_vm_end);
if (pmap_load(l1) == 0) {
/* We need a new PDP entry */
nkpg = vm_page_alloc(NULL, kernel_vm_end >> L1_SHIFT,
@@ -1716,7 +1948,7 @@ pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
{
struct rwlock *lock;
vm_offset_t va, va_next;
- pd_entry_t *l1, *l2;
+ pd_entry_t *l0, *l1, *l2;
pt_entry_t l3_paddr, *l3;
struct spglist free;
int anyvalid;
@@ -1739,7 +1971,15 @@ pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
if (pmap->pm_stats.resident_count == 0)
break;
- l1 = pmap_l1(pmap, sva);
+ l0 = pmap_l0(pmap, sva);
+ if (pmap_load(l0) == 0) {
+ va_next = (sva + L0_SIZE) & ~L0_OFFSET;
+ if (va_next < sva)
+ va_next = eva;
+ continue;
+ }
+
+ l1 = pmap_l0_to_l1(l0, sva);
if (pmap_load(l1) == 0) {
va_next = (sva + L1_SIZE) & ~L1_OFFSET;
if (va_next < sva)
@@ -1824,9 +2064,10 @@ pmap_remove_all(vm_page_t m)
{
pv_entry_t pv;
pmap_t pmap;
- pt_entry_t *l3, tl3;
- pd_entry_t *l2, tl2;
+ pd_entry_t *pde, tpde;
+ pt_entry_t *pte, tpte;
struct spglist free;
+ int lvl;
KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_remove_all: page %p is not managed", m));
@@ -1836,30 +2077,33 @@ pmap_remove_all(vm_page_t m)
pmap = PV_PMAP(pv);
PMAP_LOCK(pmap);
pmap_resident_count_dec(pmap, 1);
- l2 = pmap_l2(pmap, pv->pv_va);
- KASSERT(l2 != NULL, ("pmap_remove_all: no l2 table found"));
- tl2 = pmap_load(l2);
- KASSERT((tl2 & ATTR_DESCR_MASK) == L2_TABLE,
- ("pmap_remove_all: found a table when expecting "
- "a block in %p's pv list", m));
- l3 = pmap_l2_to_l3(l2, pv->pv_va);
+
+ pde = pmap_pde(pmap, pv->pv_va, &lvl);
+ KASSERT(pde != NULL,
+ ("pmap_remove_all: no page directory entry found"));
+ KASSERT(lvl == 2,
+ ("pmap_remove_all: invalid pde level %d", lvl));
+ tpde = pmap_load(pde);
+
+ pte = pmap_l2_to_l3(pde, pv->pv_va);
+ tpte = pmap_load(pte);
if (pmap_is_current(pmap) &&
- pmap_l3_valid_cacheable(pmap_load(l3)))
+ pmap_l3_valid_cacheable(tpte))
cpu_dcache_wb_range(pv->pv_va, L3_SIZE);
- tl3 = pmap_load_clear(l3);
- PTE_SYNC(l3);
+ pmap_load_clear(pte);
+ PTE_SYNC(pte);
pmap_invalidate_page(pmap, pv->pv_va);
- if (tl3 & ATTR_SW_WIRED)
+ if (tpte & ATTR_SW_WIRED)
pmap->pm_stats.wired_count--;
- if ((tl3 & ATTR_AF) != 0)
+ if ((tpte & ATTR_AF) != 0)
vm_page_aflag_set(m, PGA_REFERENCED);
/*
* Update the vm_page_t clean and reference bits.
*/
- if (pmap_page_dirty(tl3))
+ if (pmap_page_dirty(tpte))
vm_page_dirty(m);
- pmap_unuse_l3(pmap, pv->pv_va, tl2, &free);
+ pmap_unuse_l3(pmap, pv->pv_va, tpde, &free);
TAILQ_REMOVE(&m->md.pv_list, pv, pv_next);
m->md.pv_gen++;
free_pv_entry(pmap, pv);
@@ -1878,7 +2122,7 @@ void
pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
{
vm_offset_t va, va_next;
- pd_entry_t *l1, *l2;
+ pd_entry_t *l0, *l1, *l2;
pt_entry_t *l3p, l3;
if ((prot & VM_PROT_READ) == VM_PROT_NONE) {
@@ -1892,7 +2136,15 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
PMAP_LOCK(pmap);
for (; sva < eva; sva = va_next) {
- l1 = pmap_l1(pmap, sva);
+ l0 = pmap_l0(pmap, sva);
+ if (pmap_load(l0) == 0) {
+ va_next = (sva + L0_SIZE) & ~L0_OFFSET;
+ if (va_next < sva)
+ va_next = eva;
+ continue;
+ }
+
+ l1 = pmap_l0_to_l1(l0, sva);
if (pmap_load(l1) == 0) {
va_next = (sva + L1_SIZE) & ~L1_OFFSET;
if (va_next < sva)
@@ -1946,13 +2198,14 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
u_int flags, int8_t psind __unused)
{
struct rwlock *lock;
- pd_entry_t *l1, *l2;
+ pd_entry_t *pde;
pt_entry_t new_l3, orig_l3;
pt_entry_t *l3;
pv_entry_t pv;
- vm_paddr_t opa, pa, l2_pa, l3_pa;
- vm_page_t mpte, om, l2_m, l3_m;
+ vm_paddr_t opa, pa, l1_pa, l2_pa, l3_pa;
+ vm_page_t mpte, om, l1_m, l2_m, l3_m;
boolean_t nosleep;
+ int lvl;
va = trunc_page(va);
if ((m->oflags & VPO_UNMANAGED) == 0 && !vm_page_xbusied(m))
@@ -1986,14 +2239,44 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
PMAP_UNLOCK(pmap);
return (KERN_RESOURCE_SHORTAGE);
}
- l3 = pmap_l3(pmap, va);
+ pde = pmap_pde(pmap, va, &lvl);
+ KASSERT(pde != NULL,
+ ("pmap_enter: Invalid page entry, va: 0x%lx", va));
+ KASSERT(lvl == 2,
+ ("pmap_enter: Invalid level %d", lvl));
+
+ l3 = pmap_l2_to_l3(pde, va);
} else {
- l3 = pmap_l3(pmap, va);
- /* TODO: This is not optimal, but should mostly work */
- if (l3 == NULL) {
- l2 = pmap_l2(pmap, va);
+ pde = pmap_pde(pmap, va, &lvl);
+ /*
+ * If we get a level 2 pde it must point to a level 3 entry
+ * otherwise we will need to create the intermediate tables
+ */
+ if (lvl < 2) {
+ switch(lvl) {
+ default:
+ case -1:
+ /* Get the l0 pde to update */
+ pde = pmap_l0(pmap, va);
+ KASSERT(pde != NULL, ("..."));
+
+ l1_m = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL |
+ VM_ALLOC_NOOBJ | VM_ALLOC_WIRED |
+ VM_ALLOC_ZERO);
+ if (l1_m == NULL)
+ panic("pmap_enter: l1 pte_m == NULL");
+ if ((l1_m->flags & PG_ZERO) == 0)
+ pmap_zero_page(l1_m);
+
+ l1_pa = VM_PAGE_TO_PHYS(l1_m);
+ pmap_load_store(pde, l1_pa | L0_TABLE);
+ PTE_SYNC(pde);
+ /* FALLTHROUGH */
+ case 0:
+ /* Get the l1 pde to update */
+ pde = pmap_l1_to_l2(pde, va);
+ KASSERT(pde != NULL, ("..."));
- if (l2 == NULL) {
l2_m = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL |
VM_ALLOC_NOOBJ | VM_ALLOC_WIRED |
VM_ALLOC_ZERO);
@@ -2003,27 +2286,28 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
pmap_zero_page(l2_m);
l2_pa = VM_PAGE_TO_PHYS(l2_m);
- l1 = pmap_l1(pmap, va);
- pmap_load_store(l1, l2_pa | L1_TABLE);
- PTE_SYNC(l1);
- l2 = pmap_l1_to_l2(l1, va);
+ pmap_load_store(pde, l2_pa | L1_TABLE);
+ PTE_SYNC(pde);
+ /* FALLTHROUGH */
+ case 1:
+ /* Get the l2 pde to update */
+ pde = pmap_l1_to_l2(pde, va);
+
+ l3_m = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL |
+ VM_ALLOC_NOOBJ | VM_ALLOC_WIRED |
+ VM_ALLOC_ZERO);
+ if (l3_m == NULL)
+ panic("pmap_enter: l3 pte_m == NULL");
+ if ((l3_m->flags & PG_ZERO) == 0)
+ pmap_zero_page(l3_m);
+
+ l3_pa = VM_PAGE_TO_PHYS(l3_m);
+ pmap_load_store(pde, l3_pa | L2_TABLE);
+ PTE_SYNC(pde);
+ break;
}
-
- KASSERT(l2 != NULL,
- ("No l2 table after allocating one"));
-
- l3_m = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL |
- VM_ALLOC_NOOBJ | VM_ALLOC_WIRED | VM_ALLOC_ZERO);
- if (l3_m == NULL)
- panic("pmap_enter: l3 pte_m == NULL");
- if ((l3_m->flags & PG_ZERO) == 0)
- pmap_zero_page(l3_m);
-
- l3_pa = VM_PAGE_TO_PHYS(l3_m);
- pmap_load_store(l2, l3_pa | L2_TABLE);
- PTE_SYNC(l2);
- l3 = pmap_l2_to_l3(l2, va);
}
+ l3 = pmap_l2_to_l3(pde, va);
pmap_invalidate_page(pmap, va);
}
@@ -2207,9 +2491,10 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m,
vm_prot_t prot, vm_page_t mpte, struct rwlock **lockp)
{
struct spglist free;
- pd_entry_t *l2;
+ pd_entry_t *pde;
pt_entry_t *l3;
vm_paddr_t pa;
+ int lvl;
KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva ||
(m->oflags & VPO_UNMANAGED) != 0,
@@ -2235,7 +2520,7 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m,
/*
* Get the l2 entry
*/
- l2 = pmap_l2(pmap, va);
+ pde = pmap_pde(pmap, va, &lvl);
/*
* If the page table page is mapped, we just increment
@@ -2243,9 +2528,9 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m,
* attempt to allocate a page table page. If this
* attempt fails, we don't retry. Instead, we give up.
*/
- if (l2 != NULL && pmap_load(l2) != 0) {
+ if (lvl == 2 && pmap_load(pde) != 0) {
mpte =
- PHYS_TO_VM_PAGE(pmap_load(l2) & ~ATTR_MASK);
+ PHYS_TO_VM_PAGE(pmap_load(pde) & ~ATTR_MASK);
mpte->wire_count++;
} else {
/*
@@ -2261,10 +2546,15 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m,
l3 = &l3[pmap_l3_index(va)];
} else {
mpte = NULL;
- l3 = pmap_l3(kernel_pmap, va);
+ pde = pmap_pde(kernel_pmap, va, &lvl);
+ KASSERT(pde != NULL,
+ ("pmap_enter_quick_locked: Invalid page entry, va: 0x%lx",
+ va));
+ KASSERT(lvl == 2,
+ ("pmap_enter_quick_locked: Invalid level %d", lvl));
+ l3 = pmap_l2_to_l3(pde, va);
}
- if (l3 == NULL)
- panic("pmap_enter_quick_locked: No l3");
+
if (pmap_load(l3) != 0) {
if (mpte != NULL) {
mpte->wire_count--;
@@ -2336,14 +2626,22 @@ void
pmap_unwire(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
{
vm_offset_t va_next;
- pd_entry_t *l1, *l2;
+ pd_entry_t *l0, *l1, *l2;
pt_entry_t *l3;
boolean_t pv_lists_locked;
pv_lists_locked = FALSE;
PMAP_LOCK(pmap);
for (; sva < eva; sva = va_next) {
- l1 = pmap_l1(pmap, sva);
+ l0 = pmap_l0(pmap, sva);
+ if (pmap_load(l0) == 0) {
+ va_next = (sva + L0_SIZE) & ~L0_OFFSET;
+ if (va_next < sva)
+ va_next = eva;
+ continue;
+ }
+
+ l1 = pmap_l0_to_l1(l0, sva);
if (pmap_load(l1) == 0) {
va_next = (sva + L1_SIZE) & ~L1_OFFSET;
if (va_next < sva)
@@ -2551,9 +2849,9 @@ pmap_page_wired_mappings(vm_page_t m)
{
struct rwlock *lock;
pmap_t pmap;
- pt_entry_t *l3;
+ pt_entry_t *pte;
pv_entry_t pv;
- int count, md_gen;
+ int count, lvl, md_gen;
if ((m->oflags & VPO_UNMANAGED) != 0)
return (0);
@@ -2574,8 +2872,8 @@ restart:
goto restart;
}
}
- l3 = pmap_l3(pmap, pv->pv_va);
- if (l3 != NULL && (pmap_load(l3) & ATTR_SW_WIRED) != 0)
+ pte = pmap_pte(pmap, pv->pv_va, &lvl);
+ if (pte != NULL && (pmap_load(pte) & ATTR_SW_WIRED) != 0)
count++;
PMAP_UNLOCK(pmap);
}
@@ -2603,8 +2901,8 @@ restart:
void
pmap_remove_pages(pmap_t pmap)
{
- pd_entry_t ptepde, *l2;
- pt_entry_t *l3, tl3;
+ pd_entry_t *pde;
+ pt_entry_t *pte, tpte;
struct spglist free;
vm_page_t m;
pv_entry_t pv;
@@ -2612,7 +2910,7 @@ pmap_remove_pages(pmap_t pmap)
struct rwlock *lock;
int64_t bit;
uint64_t inuse, bitmask;
- int allfree, field, freed, idx;
+ int allfree, field, freed, idx, lvl;
vm_paddr_t pa;
lock = NULL;
@@ -2632,44 +2930,51 @@ pmap_remove_pages(pmap_t pmap)
pv = &pc->pc_pventry[idx];
inuse &= ~bitmask;
- l2 = pmap_l2(pmap, pv->pv_va);
- ptepde = pmap_load(l2);
- l3 = pmap_l2_to_l3(l2, pv->pv_va);
- tl3 = pmap_load(l3);
+ pde = pmap_pde(pmap, pv->pv_va, &lvl);
+ KASSERT(pde != NULL,
+ ("Attempting to remove an unmapped page"));
+ KASSERT(lvl == 2,
+ ("Invalid page directory level: %d", lvl));
+
+ pte = pmap_l2_to_l3(pde, pv->pv_va);
+ KASSERT(pte != NULL,
+ ("Attempting to remove an unmapped page"));
+
+ tpte = pmap_load(pte);
/*
* We cannot remove wired pages from a process' mapping at this time
*/
- if (tl3 & ATTR_SW_WIRED) {
+ if (tpte & ATTR_SW_WIRED) {
allfree = 0;
continue;
}
- pa = tl3 & ~ATTR_MASK;
+ pa = tpte & ~ATTR_MASK;
m = PHYS_TO_VM_PAGE(pa);
KASSERT(m->phys_addr == pa,
("vm_page_t %p phys_addr mismatch %016jx %016jx",
m, (uintmax_t)m->phys_addr,
- (uintmax_t)tl3));
+ (uintmax_t)tpte));
KASSERT((m->flags & PG_FICTITIOUS) != 0 ||
m < &vm_page_array[vm_page_array_size],
- ("pmap_remove_pages: bad l3 %#jx",
- (uintmax_t)tl3));
+ ("pmap_remove_pages: bad pte %#jx",
+ (uintmax_t)tpte));
+ /* XXX: assumes tpte is level 3 */
if (pmap_is_current(pmap) &&
- pmap_l3_valid_cacheable(pmap_load(l3)))
+ pmap_l3_valid_cacheable(tpte))
cpu_dcache_wb_range(pv->pv_va, L3_SIZE);
- pmap_load_clear(l3);
- PTE_SYNC(l3);
+ pmap_load_clear(pte);
+ PTE_SYNC(pte);
pmap_invalidate_page(pmap, pv->pv_va);
/*
* Update the vm_page_t clean/reference bits.
*/
- if ((tl3 & ATTR_AP_RW_BIT) ==
- ATTR_AP(ATTR_AP_RW))
+ if ((tpte & ATTR_AP_RW_BIT) == ATTR_AP(ATTR_AP_RW))
vm_page_dirty(m);
CHANGE_PV_LIST_LOCK_TO_VM_PAGE(&lock, m);
@@ -2681,7 +2986,8 @@ pmap_remove_pages(pmap_t pmap)
TAILQ_REMOVE(&m->md.pv_list, pv, pv_next);
m->md.pv_gen++;
- pmap_unuse_l3(pmap, pv->pv_va, ptepde, &free);
+ pmap_unuse_l3(pmap, pv->pv_va, pmap_load(pde),
+ &free);
freed++;
}
}
@@ -2711,9 +3017,9 @@ pmap_page_test_mappings(vm_page_t m, boolean_t accessed, boolean_t modified)
{
struct rwlock *lock;
pv_entry_t pv;
- pt_entry_t *l3, mask, value;
+ pt_entry_t *pte, mask, value;
pmap_t pmap;
- int md_gen;
+ int lvl, md_gen;
boolean_t rv;
rv = FALSE;
@@ -2733,7 +3039,9 @@ restart:
goto restart;
}
}
- l3 = pmap_l3(pmap, pv->pv_va);
+ pte = pmap_pte(pmap, pv->pv_va, &lvl);
+ KASSERT(lvl == 3,
+ ("pmap_page_test_mappings: Invalid level %d", lvl));
mask = 0;
value = 0;
if (modified) {
@@ -2744,7 +3052,7 @@ restart:
mask |= ATTR_AF | ATTR_DESCR_MASK;
value |= ATTR_AF | L3_PAGE;
}
- rv = (pmap_load(l3) & mask) == value;
+ rv = (pmap_load(pte) & mask) == value;
PMAP_UNLOCK(pmap);
if (rv)
goto out;
@@ -2788,13 +3096,14 @@ pmap_is_modified(vm_page_t m)
boolean_t
pmap_is_prefaultable(pmap_t pmap, vm_offset_t addr)
{
- pt_entry_t *l3;
+ pt_entry_t *pte;
boolean_t rv;
+ int lvl;
rv = FALSE;
PMAP_LOCK(pmap);
- l3 = pmap_l3(pmap, addr);
- if (l3 != NULL && pmap_load(l3) != 0) {
+ pte = pmap_pte(pmap, addr, &lvl);
+ if (pte != NULL && pmap_load(pte) != 0) {
rv = TRUE;
}
PMAP_UNLOCK(pmap);
@@ -2825,8 +3134,8 @@ pmap_remove_write(vm_page_t m)
pmap_t pmap;
struct rwlock *lock;
pv_entry_t pv;
- pt_entry_t *l3, oldl3;
- int md_gen;
+ pt_entry_t oldpte, *pte;
+ int lvl, md_gen;
KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_remove_write: page %p is not managed", m));
@@ -2856,14 +3165,14 @@ retry_pv_loop:
goto retry_pv_loop;
}
}
- l3 = pmap_l3(pmap, pv->pv_va);
+ pte = pmap_pte(pmap, pv->pv_va, &lvl);
retry:
- oldl3 = pmap_load(l3);
- if ((oldl3 & ATTR_AP_RW_BIT) == ATTR_AP(ATTR_AP_RW)) {
- if (!atomic_cmpset_long(l3, oldl3,
- oldl3 | ATTR_AP(ATTR_AP_RO)))
+ oldpte = pmap_load(pte);
+ if ((oldpte & ATTR_AP_RW_BIT) == ATTR_AP(ATTR_AP_RW)) {
+ if (!atomic_cmpset_long(pte, oldpte,
+ oldpte | ATTR_AP(ATTR_AP_RO)))
goto retry;
- if ((oldl3 & ATTR_AF) != 0)
+ if ((oldpte & ATTR_AF) != 0)
vm_page_dirty(m);
pmap_invalidate_page(pmap, pv->pv_va);
}
@@ -2901,10 +3210,10 @@ pmap_ts_referenced(vm_page_t m)
pv_entry_t pv, pvf;
pmap_t pmap;
struct rwlock *lock;
- pd_entry_t *l2p, l2;
- pt_entry_t *l3;
+ pd_entry_t *pde, tpde;
+ pt_entry_t *pte, tpte;
vm_paddr_t pa;
- int cleared, md_gen, not_cleared;
+ int cleared, md_gen, not_cleared, lvl;
struct spglist free;
KASSERT((m->oflags & VPO_UNMANAGED) == 0,
@@ -2934,28 +3243,31 @@ retry:
goto retry;
}
}
- l2p = pmap_l2(pmap, pv->pv_va);
- KASSERT(l2p != NULL, ("pmap_ts_referenced: no l2 table found"));
- l2 = pmap_load(l2p);
- KASSERT((l2 & ATTR_DESCR_MASK) == L2_TABLE,
+ pde = pmap_pde(pmap, pv->pv_va, &lvl);
+ KASSERT(pde != NULL, ("pmap_ts_referenced: no l2 table found"));
+ KASSERT(lvl == 2,
+ ("pmap_ts_referenced: invalid pde level %d", lvl));
+ tpde = pmap_load(pde);
+ KASSERT((tpde & ATTR_DESCR_MASK) == L2_TABLE,
("pmap_ts_referenced: found an invalid l2 table"));
- l3 = pmap_l2_to_l3(l2p, pv->pv_va);
- if ((pmap_load(l3) & ATTR_AF) != 0) {
- if (safe_to_clear_referenced(pmap, pmap_load(l3))) {
+ pte = pmap_l2_to_l3(pde, pv->pv_va);
+ tpte = pmap_load(pte);
+ if ((tpte & ATTR_AF) != 0) {
+ if (safe_to_clear_referenced(pmap, tpte)) {
/*
* TODO: We don't handle the access flag
* at all. We need to be able to set it in
* the exception handler.
*/
panic("ARM64TODO: safe_to_clear_referenced\n");
- } else if ((pmap_load(l3) & ATTR_SW_WIRED) == 0) {
+ } else if ((tpte & ATTR_SW_WIRED) == 0) {
/*
* Wired pages cannot be paged out so
* doing accessed bit emulation for
* them is wasted effort. We do the
* hard work for unwired pages only.
*/
- pmap_remove_l3(pmap, l3, pv->pv_va, l2,
+ pmap_remove_l3(pmap, pte, pv->pv_va, tpde,
&free, &lock);
pmap_invalidate_page(pmap, pv->pv_va);
cleared++;
@@ -3145,8 +3457,8 @@ pmap_activate(struct thread *td)
critical_enter();
pmap = vmspace_pmap(td->td_proc->p_vmspace);
- td->td_pcb->pcb_l1addr = vtophys(pmap->pm_l1);
- __asm __volatile("msr ttbr0_el1, %0" : : "r"(td->td_pcb->pcb_l1addr));
+ td->td_pcb->pcb_l0addr = vtophys(pmap->pm_l0);
+ __asm __volatile("msr ttbr0_el1, %0" : : "r"(td->td_pcb->pcb_l0addr));
pmap_invalidate_all(pmap);
critical_exit();
}
diff --git a/sys/arm64/arm64/support.S b/sys/arm64/arm64/support.S
index 2f42a84..4938240 100644
--- a/sys/arm64/arm64/support.S
+++ b/sys/arm64/arm64/support.S
@@ -33,6 +33,7 @@
__FBSDID("$FreeBSD$");
#include <machine/setjmp.h>
+#include <machine/param.h>
#include "assym.s"
@@ -290,3 +291,38 @@ ENTRY(longjmp)
mov x0, x1
ret
END(longjmp)
+
+/*
+ * pagezero, simple implementation
+ */
+ENTRY(pagezero_simple)
+ add x1, x0, #PAGE_SIZE
+
+1:
+ stp xzr, xzr, [x0], #0x10
+ stp xzr, xzr, [x0], #0x10
+ stp xzr, xzr, [x0], #0x10
+ stp xzr, xzr, [x0], #0x10
+ cmp x0, x1
+ b.ne 1b
+ ret
+
+END(pagezero_simple)
+
+/*
+ * pagezero, cache assisted
+ */
+ENTRY(pagezero_cache)
+ add x1, x0, #PAGE_SIZE
+
+ ldr x2, =dczva_line_size
+ ldr x2, [x2]
+
+1:
+ dc zva, x0
+ add x0, x0, x2
+ cmp x0, x1
+ b.ne 1b
+ ret
+
+END(pagezero_cache)
diff --git a/sys/arm64/arm64/swtch.S b/sys/arm64/arm64/swtch.S
index 35153c2..1b501a49 100644
--- a/sys/arm64/arm64/swtch.S
+++ b/sys/arm64/arm64/swtch.S
@@ -86,7 +86,7 @@ ENTRY(cpu_throw)
*/
/* Switch to the new pmap */
- ldr x5, [x4, #PCB_L1ADDR]
+ ldr x5, [x4, #PCB_L0ADDR]
msr ttbr0_el1, x5
isb
@@ -183,7 +183,7 @@ ENTRY(cpu_switch)
*/
/* Switch to the new pmap */
- ldr x5, [x4, #PCB_L1ADDR]
+ ldr x5, [x4, #PCB_L0ADDR]
msr ttbr0_el1, x5
isb
diff --git a/sys/arm64/arm64/vm_machdep.c b/sys/arm64/arm64/vm_machdep.c
index 6794b1b4..4950fe8 100644
--- a/sys/arm64/arm64/vm_machdep.c
+++ b/sys/arm64/arm64/vm_machdep.c
@@ -84,8 +84,8 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
td2->td_pcb = pcb2;
bcopy(td1->td_pcb, pcb2, sizeof(*pcb2));
- td2->td_pcb->pcb_l1addr =
- vtophys(vmspace_pmap(td2->td_proc->p_vmspace)->pm_l1);
+ td2->td_pcb->pcb_l0addr =
+ vtophys(vmspace_pmap(td2->td_proc->p_vmspace)->pm_l0);
tf = (struct trapframe *)STACKALIGN((struct trapframe *)pcb2 - 1);
bcopy(td1->td_frame, tf, sizeof(*tf));
diff --git a/sys/arm64/cloudabi64/cloudabi64_sysvec.c b/sys/arm64/cloudabi64/cloudabi64_sysvec.c
index cb569cd..a26007a 100644
--- a/sys/arm64/cloudabi64/cloudabi64_sysvec.c
+++ b/sys/arm64/cloudabi64/cloudabi64_sysvec.c
@@ -157,5 +157,6 @@ Elf64_Brandinfo cloudabi64_brand = {
.brand = ELFOSABI_CLOUDABI,
.machine = EM_AARCH64,
.sysvec = &cloudabi64_elf_sysvec,
+ .flags = BI_CAN_EXEC_DYN,
.compat_3_brand = "CloudABI",
};
diff --git a/sys/arm64/include/armreg.h b/sys/arm64/include/armreg.h
index 8b2bc92..40d07f0 100644
--- a/sys/arm64/include/armreg.h
+++ b/sys/arm64/include/armreg.h
@@ -66,6 +66,12 @@
#define CTR_ILINE_MASK (0xf << CTR_ILINE_SHIFT)
#define CTR_ILINE_SIZE(reg) (((reg) & CTR_ILINE_MASK) >> CTR_ILINE_SHIFT)
+/* DCZID_EL0 - Data Cache Zero ID register */
+#define DCZID_DZP (1 << 4) /* DC ZVA prohibited if non-0 */
+#define DCZID_BS_SHIFT 0
+#define DCZID_BS_MASK (0xf << DCZID_BS_SHIFT)
+#define DCZID_BS_SIZE(reg) (((reg) & DCZID_BS_MASK) >> DCZID_BS_SHIFT)
+
/* ESR_ELx */
#define ESR_ELx_ISS_MASK 0x00ffffff
#define ISS_INSN_FnV (0x01 << 10)
diff --git a/sys/arm64/include/cpu.h b/sys/arm64/include/cpu.h
index 8f14e82..520729c 100644
--- a/sys/arm64/include/cpu.h
+++ b/sys/arm64/include/cpu.h
@@ -1,6 +1,6 @@
/*-
* Copyright (c) 1990 The Regents of the University of California.
- * Copyright (c) 2014 The FreeBSD Foundation
+ * Copyright (c) 2014-2016 The FreeBSD Foundation
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -46,7 +46,7 @@
#include <machine/armreg.h>
#define TRAPF_PC(tfp) ((tfp)->tf_lr)
-#define TRAPF_USERMODE(tfp) (((tfp)->tf_elr & (1ul << 63)) == 0)
+#define TRAPF_USERMODE(tfp) (((tfp)->tf_spsr & PSR_M_MASK) == PSR_M_EL0t)
#define cpu_getstack(td) ((td)->td_frame->tf_sp)
#define cpu_setstack(td, sp) ((td)->td_frame->tf_sp = (sp))
diff --git a/sys/arm64/include/intr.h b/sys/arm64/include/intr.h
index 2d7da21..327b249 100644
--- a/sys/arm64/include/intr.h
+++ b/sys/arm64/include/intr.h
@@ -29,8 +29,10 @@
#ifndef _MACHINE_INTR_H_
#define _MACHINE_INTR_H_
-int arm_config_intr(u_int, enum intr_trigger, enum intr_polarity);
-void arm_cpu_intr(struct trapframe *);
+int intr_irq_config(u_int, enum intr_trigger, enum intr_polarity);
+void intr_irq_handler(struct trapframe *);
+int intr_irq_remove_handler(device_t, u_int, void *);
+
void arm_dispatch_intr(u_int, struct trapframe *);
int arm_enable_intr(void);
void arm_mask_irq(u_int);
@@ -44,12 +46,12 @@ int arm_map_msi(device_t, device_t, int, uint64_t *, uint32_t *);
int arm_map_msix(device_t, device_t, int, uint64_t *, uint32_t *);
int arm_setup_intr(const char *, driver_filter_t *, driver_intr_t,
void *, u_int, enum intr_type, void **);
-int arm_teardown_intr(void *);
void arm_unmask_irq(u_int);
#ifdef SMP
+int intr_irq_bind(u_int, int);
+
void arm_init_secondary(void);
-int arm_intr_bind(u_int, int);
void arm_setup_ipihandler(driver_filter_t *, u_int);
void arm_unmask_ipi(u_int);
#endif
diff --git a/sys/arm64/include/machdep.h b/sys/arm64/include/machdep.h
index 92c735b..0b1feae 100644
--- a/sys/arm64/include/machdep.h
+++ b/sys/arm64/include/machdep.h
@@ -34,11 +34,13 @@ struct arm64_bootparams {
vm_offset_t kern_l1pt; /* L1 page table for the kernel */
uint64_t kern_delta;
vm_offset_t kern_stack;
+ vm_offset_t kern_l0pt; /* L1 page table for the kernel */
};
extern vm_paddr_t physmap[];
extern u_int physmap_idx;
void initarm(struct arm64_bootparams *);
+extern void (*pagezero)(void *);
#endif /* _MACHINE_MACHDEP_H_ */
diff --git a/sys/arm64/include/pcb.h b/sys/arm64/include/pcb.h
index 55dd6e9..4426226 100644
--- a/sys/arm64/include/pcb.h
+++ b/sys/arm64/include/pcb.h
@@ -40,7 +40,7 @@ struct pcb {
/* These two need to be in order as we access them together */
uint64_t pcb_sp;
uint64_t pcb_tpidr_el0;
- vm_offset_t pcb_l1addr;
+ vm_offset_t pcb_l0addr;
/* Fault handler, the error value is passed in x0 */
vm_offset_t pcb_onfault;
diff --git a/sys/arm64/include/pmap.h b/sys/arm64/include/pmap.h
index 0faf2e8..578eb46 100644
--- a/sys/arm64/include/pmap.h
+++ b/sys/arm64/include/pmap.h
@@ -78,7 +78,7 @@ struct pv_addr {
struct pmap {
struct mtx pm_mtx;
struct pmap_statistics pm_stats; /* pmap statictics */
- pd_entry_t *pm_l1;
+ pd_entry_t *pm_l0;
TAILQ_HEAD(,pv_chunk) pm_pvchunk; /* list of mappings in pmap */
};
@@ -134,7 +134,7 @@ extern vm_offset_t virtual_end;
#define L1_MAPPABLE_P(va, pa, size) \
((((va) | (pa)) & L1_OFFSET) == 0 && (size) >= L1_SIZE)
-void pmap_bootstrap(vm_offset_t, vm_paddr_t, vm_size_t);
+void pmap_bootstrap(vm_offset_t, vm_offset_t, vm_paddr_t, vm_size_t);
void pmap_kenter_device(vm_offset_t, vm_size_t, vm_paddr_t);
vm_paddr_t pmap_kextract(vm_offset_t va);
void pmap_kremove(vm_offset_t);
@@ -149,7 +149,7 @@ boolean_t pmap_map_io_transient(vm_page_t *, vm_offset_t *, int, boolean_t);
void pmap_unmap_io_transient(vm_page_t *, vm_offset_t *, int, boolean_t);
bool pmap_get_tables(pmap_t, vm_offset_t, pd_entry_t **, pd_entry_t **,
- pt_entry_t **);
+ pd_entry_t **, pt_entry_t **);
#define pmap_page_is_mapped(m) (!TAILQ_EMPTY(&(m)->md.pv_list))
diff --git a/sys/arm64/include/pte.h b/sys/arm64/include/pte.h
index 645cf31..da70dc4 100644
--- a/sys/arm64/include/pte.h
+++ b/sys/arm64/include/pte.h
@@ -73,8 +73,10 @@ typedef uint64_t pt_entry_t; /* page table entry */
/* Level 0 table, 512GiB per entry */
#define L0_SHIFT 39
+#define L0_SIZE (1ul << L0_SHIFT)
+#define L0_OFFSET (L0_SIZE - 1ul)
#define L0_INVAL 0x0 /* An invalid address */
-#define L0_BLOCK 0x1 /* A block */
+ /* 0x1 Level 0 doesn't support block translation */
/* 0x2 also marks an invalid address */
#define L0_TABLE 0x3 /* A next-level table */
@@ -83,16 +85,16 @@ typedef uint64_t pt_entry_t; /* page table entry */
#define L1_SIZE (1 << L1_SHIFT)
#define L1_OFFSET (L1_SIZE - 1)
#define L1_INVAL L0_INVAL
-#define L1_BLOCK L0_BLOCK
+#define L1_BLOCK 0x1
#define L1_TABLE L0_TABLE
/* Level 2 table, 2MiB per entry */
#define L2_SHIFT 21
#define L2_SIZE (1 << L2_SHIFT)
#define L2_OFFSET (L2_SIZE - 1)
-#define L2_INVAL L0_INVAL
-#define L2_BLOCK L0_BLOCK
-#define L2_TABLE L0_TABLE
+#define L2_INVAL L1_INVAL
+#define L2_BLOCK L1_BLOCK
+#define L2_TABLE L1_TABLE
#define L2_BLOCK_MASK UINT64_C(0xffffffe00000)
@@ -106,7 +108,12 @@ typedef uint64_t pt_entry_t; /* page table entry */
/* 0x2 also marks an invalid address */
#define L3_PAGE 0x3
-#define Ln_ENTRIES (1 << 9)
+#define L0_ENTRIES_SHIFT 9
+#define L0_ENTRIES (1 << L0_ENTRIES_SHIFT)
+#define L0_ADDR_MASK (L0_ENTRIES - 1)
+
+#define Ln_ENTRIES_SHIFT 9
+#define Ln_ENTRIES (1 << Ln_ENTRIES_SHIFT)
#define Ln_ADDR_MASK (Ln_ENTRIES - 1)
#define Ln_TABLE_MASK ((1 << 12) - 1)
diff --git a/sys/arm64/include/smp.h b/sys/arm64/include/smp.h
index 0f56396..538981a 100644
--- a/sys/arm64/include/smp.h
+++ b/sys/arm64/include/smp.h
@@ -42,7 +42,7 @@ enum {
IPI_STOP,
IPI_STOP_HARD,
IPI_HARDCLOCK,
- COUNT_IPI,
+ INTR_IPI_COUNT,
};
void ipi_all_but_self(u_int ipi);
diff --git a/sys/arm64/include/vmparam.h b/sys/arm64/include/vmparam.h
index 2752ee1..cd9198e 100644
--- a/sys/arm64/include/vmparam.h
+++ b/sys/arm64/include/vmparam.h
@@ -188,7 +188,7 @@ extern vm_paddr_t dmap_phys_base;
})
#define VM_MIN_USER_ADDRESS (0x0000000000000000UL)
-#define VM_MAX_USER_ADDRESS (0x0000008000000000UL)
+#define VM_MAX_USER_ADDRESS (0x0001000000000000UL)
#define VM_MINUSER_ADDRESS (VM_MIN_USER_ADDRESS)
#define VM_MAXUSER_ADDRESS (VM_MAX_USER_ADDRESS)
diff --git a/sys/boot/Makefile.amd64 b/sys/boot/Makefile.amd64
index 384cf7a..f2ccbad 100644
--- a/sys/boot/Makefile.amd64
+++ b/sys/boot/Makefile.amd64
@@ -3,6 +3,7 @@
SUBDIR+= efi
SUBDIR+= libstand32
SUBDIR+= zfs
+SUBDIR+= geli
SUBDIR+= userboot
.if ${MK_FORTH} != "no"
diff --git a/sys/boot/Makefile.i386 b/sys/boot/Makefile.i386
index e7de353..8244da5 100644
--- a/sys/boot/Makefile.i386
+++ b/sys/boot/Makefile.i386
@@ -3,3 +3,4 @@
SUBDIR+= efi
SUBDIR+= libstand32
SUBDIR+= zfs
+SUBDIR+= geli
diff --git a/sys/boot/common/dev_net.c b/sys/boot/common/dev_net.c
index 873b28d..ed07a2c 100644
--- a/sys/boot/common/dev_net.c
+++ b/sys/boot/common/dev_net.c
@@ -169,6 +169,12 @@ net_open(struct open_file *f, ...)
setenv("boot.netif.gateway", inet_ntoa(gateip), 1);
setenv("boot.nfsroot.server", inet_ntoa(rootip), 1);
setenv("boot.nfsroot.path", rootpath, 1);
+ if (intf_mtu != 0) {
+ char mtu[16];
+ sprintf(mtu, "%u", intf_mtu);
+ setenv("boot.netif.mtu", mtu, 1);
+ }
+
}
netdev_opens++;
f->f_devdata = &netdev_sock;
diff --git a/sys/boot/common/disk.c b/sys/boot/common/disk.c
index a8801e1..c862d30 100644
--- a/sys/boot/common/disk.c
+++ b/sys/boot/common/disk.c
@@ -170,7 +170,7 @@ display_size(uint64_t size, u_int sectorsize)
return (buf);
}
-static int
+int
ptblread(void *d, void *buf, size_t blocks, off_t offset)
{
struct disk_devdesc *dev;
diff --git a/sys/boot/common/disk.h b/sys/boot/common/disk.h
index e95256d..d24fb1a 100644
--- a/sys/boot/common/disk.h
+++ b/sys/boot/common/disk.h
@@ -107,6 +107,7 @@ extern int disk_read(struct disk_devdesc *dev, void *buf, off_t offset,
u_int blocks);
extern int disk_write(struct disk_devdesc *dev, void *buf, off_t offset,
u_int blocks);
+extern int ptblread(void *d, void *buf, size_t blocks, off_t offset);
/*
* Print information about slices on a disk.
diff --git a/sys/boot/common/gpt.c b/sys/boot/common/gpt.c
index 8baa64c..7ab3fc6 100644
--- a/sys/boot/common/gpt.c
+++ b/sys/boot/common/gpt.c
@@ -39,8 +39,6 @@ __FBSDID("$FreeBSD$");
#include "util.h"
#include "gpt.h"
-#define MAXTBLENTS 128
-
static struct gpt_hdr hdr_primary, hdr_backup, *gpthdr;
static uint64_t hdr_primary_lba, hdr_backup_lba;
static struct gpt_ent table_primary[MAXTBLENTS], table_backup[MAXTBLENTS];
diff --git a/sys/boot/common/gpt.h b/sys/boot/common/gpt.h
index c42b40d..9d48564 100644
--- a/sys/boot/common/gpt.h
+++ b/sys/boot/common/gpt.h
@@ -32,6 +32,8 @@
#include <uuid.h>
#include <drv.h>
+#define MAXTBLENTS 128
+
int gptread(const uuid_t *uuid, struct dsk *dskp, char *buf);
int gptfind(const uuid_t *uuid, struct dsk *dskp, int part);
void gptbootfailed(struct dsk *dskp);
diff --git a/sys/boot/efi/Makefile b/sys/boot/efi/Makefile
index 94a975a..21da86f 100644
--- a/sys/boot/efi/Makefile
+++ b/sys/boot/efi/Makefile
@@ -2,8 +2,9 @@
.include <src.opts.mk>
-# In-tree GCC does not support __attribute__((ms_abi)).
-.if ${COMPILER_TYPE} != "gcc"
+# In-tree GCC does not support __attribute__((ms_abi)), but gcc newer
+# than 4.5 supports it.
+.if ${COMPILER_TYPE} != "gcc" || ${COMPILER_VERSION} >= 404500
.if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "arm"
.if ${MK_FDT} != "no"
@@ -17,7 +18,6 @@ SUBDIR+= fdt
SUBDIR+= libefi loader boot1
.endif
-.endif # ${COMPILER_TYPE} != "gcc"
+.endif # ${COMPILER_TYPE} != "gcc" || ${COMPILER_VERSION} >= 404500
.include <bsd.subdir.mk>
-
diff --git a/sys/boot/fdt/dts/arm/bcm2836.dtsi b/sys/boot/fdt/dts/arm/bcm2836.dtsi
index ce967df..5229d6a 100644
--- a/sys/boot/fdt/dts/arm/bcm2836.dtsi
+++ b/sys/boot/fdt/dts/arm/bcm2836.dtsi
@@ -32,8 +32,8 @@
timer {
compatible = "arm,armv7-timer";
clock-frequency = <19200000>;
- interrupts = <72 73 75 74>;
- interrupt-parent = <&intc>;
+ interrupts = <0 1 3 2>;
+ interrupt-parent = <&local_intc>;
};
SOC: axi {
@@ -41,12 +41,23 @@
#address-cells = <1>;
#size-cells = <1>;
reg = <0x3f000000 0x01000000>;
- ranges = <0 0x3f000000 0x01000000>;
+ ranges = <0 0x3f000000 0x01000000>,
+ <0x40000000 0x40000000 0x00001000>;
+
+ local_intc: local_intc {
+ compatible = "brcm,bcm2836-l1-intc";
+ reg = <0x40000000 0x100>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ interrupt-parent = <&local_intc>;
+ };
intc: interrupt-controller {
compatible = "broadcom,bcm2835-armctrl-ic",
"broadcom,bcm2708-armctrl-ic";
reg = <0xB200 0x200>;
+ interrupt-parent = <&local_intc>;
+ interrupts = <8>;
interrupt-controller;
#interrupt-cells = <1>;
diff --git a/sys/boot/fdt/dts/arm/beaglebone-black.dts b/sys/boot/fdt/dts/arm/beaglebone-black.dts
index d4f19b2..6605505 100644
--- a/sys/boot/fdt/dts/arm/beaglebone-black.dts
+++ b/sys/boot/fdt/dts/arm/beaglebone-black.dts
@@ -33,15 +33,18 @@
&am33xx_pinmux {
i2c1_pins: pinmux_i2c1_pins {
pinctrl-single,pins = <
- 0x158 (PIN_INPUT_PULLUP | MUX_MODE2) /* spi0_d1.i2c1_sda */
- 0x15c (PIN_INPUT_PULLUP | MUX_MODE2) /* spi0_cs0.i2c1_scl */
+ AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE2) /* spi0_d1.i2c1_sda */
+ AM33XX_IOPAD(0x95c, PIN_INPUT_PULLUP | MUX_MODE2) /* spi0_cs0.i2c1_scl */
>;
};
- i2c2_pins: pinmux_i2c2_pins {
+ spi1_pins: pinmux_spi1_pins {
pinctrl-single,pins = <
- 0x178 (PIN_INPUT_PULLUP | MUX_MODE3) /* uart1_ctsn.i2c2_sda */
- 0x17c (PIN_INPUT_PULLUP | MUX_MODE3) /* uart1_rtsn.i2c2_scl */
+ AM33XX_IOPAD(0x964, PIN_INPUT_PULLUP | MUX_MODE2) /* eCAP0_in_PWM0_out.spi1_cs1 */
+ AM33XX_IOPAD(0x990, PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcasp0_aclkx.spi1_sclk */
+ AM33XX_IOPAD(0x994, PIN_INPUT_PULLDOWN | MUX_MODE3) /* mcasp0_fsx.spi1_d0 - miso */
+ AM33XX_IOPAD(0x998, PIN_INPUT_PULLUP | MUX_MODE3) /* mcasp0_axr0.spi1_d1 - mosi */
+ AM33XX_IOPAD(0x99c, PIN_INPUT_PULLUP | MUX_MODE3) /* mcasp0_ahclkr.spi1_cs0 */
>;
};
};
@@ -72,6 +75,13 @@
status = "okay";
};
+&spi1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi1_pins>;
+
+ status = "okay";
+};
+
&lcdc {
hdmi = <&tda998x>;
};
diff --git a/sys/dev/filemon/filemon_lock.c b/sys/boot/fdt/dts/arm/tegra124-jetson-tk1-fbsd.dts
index 5cac47c..902616b 100644
--- a/sys/dev/filemon/filemon_lock.c
+++ b/sys/boot/fdt/dts/arm/tegra124-jetson-tk1-fbsd.dts
@@ -1,8 +1,11 @@
/*-
- * Copyright (c) 2009-2011, Juniper Networks, Inc.
- * Copyright (c) 2015, EMC Corp.
+ * Copyright (c) 2016 Michal Meloun <mmel@FreeBSD.org>
* All rights reserved.
*
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -12,10 +15,10 @@
* 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 JUNIPER NETWORKS AND CONTRIBUTORS ``AS IS'' AND
+ * 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 JUNIPER NETWORKS OR CONTRIBUTORS BE LIABLE
+ * 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)
@@ -23,35 +26,21 @@
* 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/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-static __inline void
-filemon_lock_read(void)
-{
-
- sx_slock(&access_lock);
-}
-
-static __inline void
-filemon_unlock_read(void)
-{
-
- sx_sunlock(&access_lock);
-}
-
-static __inline void
-filemon_lock_write(void)
-{
+#include "tegra124-jetson-tk1.dts"
- sx_xlock(&access_lock);
-}
+/ {
+ chosen {
+ stdin = &uartd;
+ stdout = &uartd;
+ };
-static __inline void
-filemon_unlock_write(void)
-{
+ memory {
+/* reg = <0x0 0x80000000 0x0 0x80000000>; */
+ reg = <0x0 0x80000000 0x0 0x70000000>;
+ };
- sx_xunlock(&access_lock);
-}
+};
diff --git a/sys/boot/geli/Makefile b/sys/boot/geli/Makefile
new file mode 100644
index 0000000..f5ab243
--- /dev/null
+++ b/sys/boot/geli/Makefile
@@ -0,0 +1,52 @@
+# $FreeBSD$
+# libgeliboot
+
+MAN=
+
+.include <src.opts.mk>
+MK_SSP= no
+
+LIB= geliboot
+INTERNALLIB=
+MK_PROFILE= no
+NO_PIC=
+
+.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
+CFLAGS+= -march=i386
+.endif
+.if ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "powerpc64"
+CFLAGS+= -m32
+.endif
+
+WARNS?= 0
+
+# string functions from libc
+.PATH: ${.CURDIR}/../../../lib/libc/string
+SRCS+= bcmp.c bcopy.c bzero.c
+
+# Our password input method
+SRCS+= pwgets.c
+
+# sha256 and sha512 from sys/crypto
+.PATH: ${.CURDIR}/../../crypto/sha2
+CFLAGS+= -DWEAK_REFS
+SRCS+= sha256c.c sha512c.c
+
+# md5 from libmd
+.PATH: ${.CURDIR}/../../../lib/libmd
+SRCS+= md5c.c
+
+# AES implementation from sys/crypto
+.PATH: ${.CURDIR}/../../crypto/rijndael
+CFLAGS+= -I${.CURDIR}/../../
+# Remove asserts
+CFLAGS+= -DNDEBUG
+SRCS+= rijndael-alg-fst.c rijndael-api-fst.c rijndael-api.c
+
+# local GELI Implementation
+.PATH: ${.CURDIR}/../../geom/eli
+CFLAGS+= -D_STAND
+SRCS+= geliboot_crypto.c g_eli_hmac.c g_eli_key.c g_eli_key_cache.c pkcs5v2.c
+
+.include <bsd.stand.mk>
+.include <bsd.lib.mk>
diff --git a/sbin/casperd/Makefile.depend b/sys/boot/geli/Makefile.depend
index aa79c09..7b57224 100644
--- a/sbin/casperd/Makefile.depend
+++ b/sys/boot/geli/Makefile.depend
@@ -2,18 +2,11 @@
# Autogenerated - do NOT edit!
DIRDEPS = \
- gnu/lib/csu \
- gnu/lib/libgcc \
include \
include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libcapsicum \
- lib/libcasper \
- lib/libcompiler_rt \
- lib/libnv \
- lib/libpjdlog \
- lib/libutil \
+ lib/libmd \
+ lib/libstand \
+ secure/lib/libcrypto \
.include <dirdeps.mk>
diff --git a/sys/boot/geli/geliboot.c b/sys/boot/geli/geliboot.c
new file mode 100644
index 0000000..becbc5f
--- /dev/null
+++ b/sys/boot/geli/geliboot.c
@@ -0,0 +1,292 @@
+/*-
+ * Copyright (c) 2015 Allan Jude <allanjude@FreeBSD.org>
+ * Copyright (c) 2005-2011 Pawel Jakub Dawidek <pawel@dawidek.net>
+ * 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 AUTHORS 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 AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include "geliboot.h"
+
+SLIST_HEAD(geli_list, geli_entry) geli_head = SLIST_HEAD_INITIALIZER(geli_head);
+struct geli_list *geli_headp;
+
+static int
+geli_same_device(struct geli_entry *ge, struct dsk *dskp)
+{
+
+ if (geli_e->dsk->drive == dskp->drive &&
+ dskp->part == 255 && geli_e->dsk->part == dskp->slice) {
+ /*
+ * Sometimes slice = slice, and sometimes part = slice
+ * If the incoming struct dsk has part=255, it means look at
+ * the slice instead of the part number
+ */
+ return (0);
+ }
+
+ /* Is this the same device? */
+ if (geli_e->dsk->drive != dskp->drive ||
+ geli_e->dsk->slice != dskp->slice ||
+ geli_e->dsk->part != dskp->part) {
+ return (1);
+ }
+
+ return (0);
+}
+
+void
+geli_init(void)
+{
+
+ geli_count = 0;
+ SLIST_INIT(&geli_head);
+}
+
+/*
+ * Read the last sector of the drive or partition pointed to by dsk and see
+ * if it is GELI encrypted
+ */
+int
+geli_taste(int read_func(void *vdev, void *priv, off_t off, void *buf,
+ size_t bytes), struct dsk *dskp, daddr_t lastsector)
+{
+ struct g_eli_metadata md;
+ u_char buf[DEV_BSIZE];
+ int error;
+
+ error = read_func(NULL, dskp, (off_t) lastsector * DEV_BSIZE, &buf,
+ (size_t) DEV_BSIZE);
+ if (error != 0) {
+ return (error);
+ }
+ error = eli_metadata_decode(buf, &md);
+ if (error != 0) {
+ return (error);
+ }
+
+ if ((md.md_flags & G_ELI_FLAG_ONETIME)) {
+ /* Swap device, skip it */
+ return (1);
+ }
+ if (!(md.md_flags & G_ELI_FLAG_BOOT)) {
+ /* Disk is not GELI boot device, skip it */
+ return (1);
+ }
+ if (md.md_iterations < 0) {
+ /* XXX TODO: Support loading key files */
+ /* Disk does not have a passphrase, skip it */
+ return (1);
+ }
+ geli_e = malloc(sizeof(struct geli_entry));
+ if (geli_e == NULL)
+ return (2);
+
+ geli_e->dsk = malloc(sizeof(struct dsk));
+ if (geli_e->dsk == NULL)
+ return (2);
+ memcpy(geli_e->dsk, dskp, sizeof(struct dsk));
+ geli_e->part_end = lastsector;
+ if (dskp->part == 255) {
+ geli_e->dsk->part = dskp->slice;
+ }
+
+ geli_e->md = md;
+ eli_metadata_softc(&geli_e->sc, &md, DEV_BSIZE,
+ (lastsector + DEV_BSIZE) * DEV_BSIZE);
+
+ SLIST_INSERT_HEAD(&geli_head, geli_e, entries);
+ geli_count++;
+
+ return (0);
+}
+
+/*
+ * Attempt to decrypt the device
+ */
+int
+geli_attach(struct dsk *dskp, const char *passphrase)
+{
+ u_char key[G_ELI_USERKEYLEN], mkey[G_ELI_DATAIVKEYLEN], *mkp;
+ u_int keynum;
+ struct hmac_ctx ctx;
+ int error;
+
+ SLIST_FOREACH_SAFE(geli_e, &geli_head, entries, geli_e_tmp) {
+ if (geli_same_device(geli_e, dskp) != 0) {
+ continue;
+ }
+
+ g_eli_crypto_hmac_init(&ctx, NULL, 0);
+ /*
+ * Prepare Derived-Key from the user passphrase.
+ */
+ if (geli_e->md.md_iterations < 0) {
+ /* XXX TODO: Support loading key files */
+ return (1);
+ } else if (geli_e->md.md_iterations == 0) {
+ g_eli_crypto_hmac_update(&ctx, geli_e->md.md_salt,
+ sizeof(geli_e->md.md_salt));
+ g_eli_crypto_hmac_update(&ctx, passphrase,
+ strlen(passphrase));
+ } else if (geli_e->md.md_iterations > 0) {
+ printf("Calculating GELI Decryption Key disk%dp%d @ %lu "
+ "iterations...\n", dskp->unit,
+ (dskp->slice > 0 ? dskp->slice : dskp->part),
+ geli_e->md.md_iterations);
+ u_char dkey[G_ELI_USERKEYLEN];
+
+ pkcs5v2_genkey(dkey, sizeof(dkey), geli_e->md.md_salt,
+ sizeof(geli_e->md.md_salt), passphrase,
+ geli_e->md.md_iterations);
+ g_eli_crypto_hmac_update(&ctx, dkey, sizeof(dkey));
+ bzero(&dkey, sizeof(dkey));
+ }
+
+ g_eli_crypto_hmac_final(&ctx, key, 0);
+
+ error = g_eli_mkey_decrypt(&geli_e->md, key, mkey, &keynum);
+ bzero(&key, sizeof(key));
+ if (error == -1) {
+ bzero(&mkey, sizeof(mkey));
+ printf("Bad GELI key: %d\n", error);
+ return (error);
+ } else if (error != 0) {
+ bzero(&mkey, sizeof(mkey));
+ printf("Failed to decrypt GELI master key: %d\n", error);
+ return (error);
+ }
+
+ /* Store the keys */
+ bcopy(mkey, geli_e->sc.sc_mkey, sizeof(geli_e->sc.sc_mkey));
+ bcopy(mkey, geli_e->sc.sc_ivkey, sizeof(geli_e->sc.sc_ivkey));
+ mkp = mkey + sizeof(geli_e->sc.sc_ivkey);
+ if ((geli_e->sc.sc_flags & G_ELI_FLAG_AUTH) == 0) {
+ bcopy(mkp, geli_e->sc.sc_ekey, G_ELI_DATAKEYLEN);
+ } else {
+ /*
+ * The encryption key is: ekey = HMAC_SHA512(Data-Key, 0x10)
+ */
+ g_eli_crypto_hmac(mkp, G_ELI_MAXKEYLEN, "\x10", 1,
+ geli_e->sc.sc_ekey, 0);
+ }
+ bzero(&mkey, sizeof(mkey));
+
+ /* Initialize the per-sector IV */
+ switch (geli_e->sc.sc_ealgo) {
+ case CRYPTO_AES_XTS:
+ break;
+ default:
+ SHA256_Init(&geli_e->sc.sc_ivctx);
+ SHA256_Update(&geli_e->sc.sc_ivctx, geli_e->sc.sc_ivkey,
+ sizeof(geli_e->sc.sc_ivkey));
+ break;
+ }
+
+ return (0);
+ }
+
+ /* Disk not found */
+ return (2);
+}
+
+int
+is_geli(struct dsk *dskp)
+{
+ SLIST_FOREACH_SAFE(geli_e, &geli_head, entries, geli_e_tmp) {
+ if (geli_same_device(geli_e, dskp) == 0) {
+ return (0);
+ }
+ }
+
+ return (1);
+}
+
+int
+geli_read(struct dsk *dskp, off_t offset, u_char *buf, size_t bytes)
+{
+ u_char iv[G_ELI_IVKEYLEN];
+ u_char *pbuf;
+ int error;
+ off_t os;
+ uint64_t keyno;
+ size_t n, nb;
+ struct g_eli_key gkey;
+
+ SLIST_FOREACH_SAFE(geli_e, &geli_head, entries, geli_e_tmp) {
+ if (geli_same_device(geli_e, dskp) != 0) {
+ continue;
+ }
+
+ nb = bytes / DEV_BSIZE;
+ for (n = 0; n < nb; n++) {
+ os = offset + (n * DEV_BSIZE);
+ pbuf = buf + (n * DEV_BSIZE);
+
+ g_eli_crypto_ivgen(&geli_e->sc, os, iv, G_ELI_IVKEYLEN);
+
+ /* Get the key that corresponds to this offset */
+ keyno = (os >> G_ELI_KEY_SHIFT) / DEV_BSIZE;
+ g_eli_key_fill(&geli_e->sc, &gkey, keyno);
+
+ error = geliboot_crypt(geli_e->sc.sc_ealgo, 0, pbuf,
+ DEV_BSIZE, gkey.gek_key, geli_e->sc.sc_ekeylen, iv);
+
+ if (error != 0) {
+ bzero(&gkey, sizeof(gkey));
+ printf("Failed to decrypt in geli_read()!");
+ return (error);
+ }
+ }
+ bzero(&gkey, sizeof(gkey));
+ return (0);
+ }
+
+ printf("GELI provider not found\n");
+ return (1);
+}
+
+int
+geli_passphrase(char *pw, int disk, int parttype, int part, struct dsk *dskp)
+{
+ int i;
+
+ /* TODO: Implement GELI keyfile(s) support */
+ for (i = 0; i < 3; i++) {
+ /* Try cached passphrase */
+ if (i == 0 && pw[0] != '\0') {
+ if (geli_attach(dskp, pw) == 0) {
+ return (0);
+ }
+ }
+ printf("GELI Passphrase for disk%d%c%d: ", disk, parttype, part);
+ pwgets(pw, GELI_PW_MAXLEN);
+ printf("\n");
+ if (geli_attach(dskp, pw) == 0) {
+ return (0);
+ }
+ }
+
+ return (1);
+}
diff --git a/sys/boot/geli/geliboot.h b/sys/boot/geli/geliboot.h
new file mode 100644
index 0000000..36bebcc
--- /dev/null
+++ b/sys/boot/geli/geliboot.h
@@ -0,0 +1,86 @@
+/*-
+ * Copyright (c) 2015 Allan Jude <allanjude@FreeBSD.org>
+ * Copyright (c) 2005-2011 Pawel Jakub Dawidek <pawel@dawidek.net>
+ * 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 AUTHORS 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 AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/endian.h>
+#include <sys/queue.h>
+
+#ifndef _GELIBOOT_H_
+#define _GELIBOOT_H_
+
+#define _STRING_H_
+#define _STRINGS_H_
+#define _STDIO_H_
+#include <geom/eli/g_eli.h>
+#include <geom/eli/pkcs5v2.h>
+
+/* Pull in the md5, sha256, and sha512 implementations */
+#include <md5.h>
+#include <crypto/sha2/sha256.h>
+#include <crypto/sha2/sha512.h>
+
+/* Pull in AES implementation */
+#include <crypto/rijndael/rijndael-api-fst.h>
+
+/* AES-XTS implementation */
+#define _STAND
+#define STAND_H /* We don't want stand.h in {gpt,zfs,gptzfs}boot */
+#include <opencrypto/xform_enc.h>
+
+#ifndef DEV_BSIZE
+#define DEV_BSIZE 512
+#endif
+
+#ifndef MIN
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#define GELI_PW_MAXLEN 256
+extern void pwgets(char *buf, int n);
+
+struct geli_entry {
+ struct dsk *dsk;
+ off_t part_end;
+ struct g_eli_softc sc;
+ struct g_eli_metadata md;
+ SLIST_ENTRY(geli_entry) entries;
+} *geli_e, *geli_e_tmp;
+
+int geli_count;
+
+void geli_init(void);
+int geli_taste(int read_func(void *vdev, void *priv, off_t off,
+ void *buf, size_t bytes), struct dsk *dsk, daddr_t lastsector);
+int geli_attach(struct dsk *dskp, const char *passphrase);
+int is_geli(struct dsk *dsk);
+int geli_read(struct dsk *dsk, off_t offset, u_char *buf, size_t bytes);
+int geli_decrypt(u_int algo, u_char *data, size_t datasize,
+ const u_char *key, size_t keysize, const uint8_t* iv);
+int geli_passphrase(char *pw, int disk, int parttype, int part, struct dsk *dskp);
+
+#endif /* _GELIBOOT_H_ */
diff --git a/sys/boot/geli/geliboot_crypto.c b/sys/boot/geli/geliboot_crypto.c
new file mode 100644
index 0000000..1596236
--- /dev/null
+++ b/sys/boot/geli/geliboot_crypto.c
@@ -0,0 +1,135 @@
+/*-
+ * Copyright (c) 2005-2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
+ * Copyright (c) 2015 Allan Jude <allanjude@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 AUTHORS 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 AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include "geliboot.h"
+
+int
+geliboot_crypt(u_int algo, int enc, u_char *data, size_t datasize,
+ const u_char *key, size_t keysize, u_char *iv)
+{
+ keyInstance aeskey;
+ cipherInstance cipher;
+ struct aes_xts_ctx xtsctx, *ctxp;
+ size_t xts_len;
+ int err, blks, i;
+
+ switch (algo) {
+ case CRYPTO_AES_CBC:
+ err = rijndael_makeKey(&aeskey, !enc, keysize,
+ (const char *)key);
+ if (err < 0) {
+ printf("Failed to setup decryption keys: %d\n", err);
+ return (err);
+ }
+
+ err = rijndael_cipherInit(&cipher, MODE_CBC, iv);
+ if (err < 0) {
+ printf("Failed to setup IV: %d\n", err);
+ return (err);
+ }
+
+ switch (enc) {
+ case 0: /* decrypt */
+ blks = rijndael_blockDecrypt(&cipher, &aeskey, data,
+ datasize * 8, data);
+ break;
+ case 1: /* encrypt */
+ blks = rijndael_blockEncrypt(&cipher, &aeskey, data,
+ datasize * 8, data);
+ break;
+ }
+ if (datasize != (blks / 8)) {
+ printf("Failed to decrypt the entire input: "
+ "%u != %u\n", blks, datasize);
+ return (1);
+ }
+ break;
+ case CRYPTO_AES_XTS:
+ xts_len = keysize << 1;
+ ctxp = &xtsctx;
+
+ rijndael_set_key(&ctxp->key1, key, xts_len / 2);
+ rijndael_set_key(&ctxp->key2, key + (xts_len / 16), xts_len / 2);
+
+ enc_xform_aes_xts.reinit(ctxp, iv);
+
+ switch (enc) {
+ case 0: /* decrypt */
+ for (i = 0; i < datasize; i += AES_XTS_BLOCKSIZE) {
+ enc_xform_aes_xts.decrypt(ctxp, data + i);
+ }
+ break;
+ case 1: /* encrypt */
+ for (i = 0; i < datasize; i += AES_XTS_BLOCKSIZE) {
+ enc_xform_aes_xts.encrypt(ctxp, data + i);
+ }
+ break;
+ }
+ break;
+ default:
+ printf("Unsupported crypto algorithm #%d\n", algo);
+ return (1);
+ }
+
+ return (0);
+}
+
+static int
+g_eli_crypto_cipher(u_int algo, int enc, u_char *data, size_t datasize,
+ const u_char *key, size_t keysize)
+{
+ u_char iv[keysize];
+
+ bzero(iv, sizeof(iv));
+ return (geliboot_crypt(algo, enc, data, datasize, key, keysize, iv));
+}
+
+int
+g_eli_crypto_encrypt(u_int algo, u_char *data, size_t datasize,
+ const u_char *key, size_t keysize)
+{
+
+ /* We prefer AES-CBC for metadata protection. */
+ if (algo == CRYPTO_AES_XTS)
+ algo = CRYPTO_AES_CBC;
+
+ return (g_eli_crypto_cipher(algo, 1, data, datasize, key, keysize));
+}
+
+int
+g_eli_crypto_decrypt(u_int algo, u_char *data, size_t datasize,
+ const u_char *key, size_t keysize)
+{
+
+ /* We prefer AES-CBC for metadata protection. */
+ if (algo == CRYPTO_AES_XTS)
+ algo = CRYPTO_AES_CBC;
+
+ return (g_eli_crypto_cipher(algo, 0, data, datasize, key, keysize));
+}
diff --git a/sys/boot/geli/pwgets.c b/sys/boot/geli/pwgets.c
new file mode 100644
index 0000000..aca6c3c
--- /dev/null
+++ b/sys/boot/geli/pwgets.c
@@ -0,0 +1,83 @@
+/* $NetBSD: gets.c,v 1.6 1995/10/11 21:16:57 pk Exp $ */
+
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. 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.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)gets.c 8.1 (Berkeley) 6/11/93
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "stand.h"
+
+/* gets() with constrained input length, for passwords */
+
+void
+pwgets(char *buf, int n)
+{
+ int c;
+ char *lp;
+
+ for (lp = buf;;)
+ switch (c = getchar() & 0177) {
+ case '\n':
+ case '\r':
+ *lp = '\0';
+ putchar('\n');
+ return;
+ case '\b':
+ case '\177':
+ if (lp > buf) {
+ lp--;
+ putchar('\b');
+ putchar(' ');
+ putchar('\b');
+ }
+ break;
+ case 'r'&037: {
+ char *p;
+
+ putchar('\n');
+ for (p = buf; p < lp; ++p)
+ putchar(*p);
+ break;
+ }
+ case 'u'&037:
+ case 'w'&037:
+ lp = buf;
+ putchar('\n');
+ break;
+ default:
+ if ((n < 1) || ((lp - buf) < n - 1)) {
+ *lp++ = c;
+ putchar('*');
+ }
+ }
+ /*NOTREACHED*/
+}
diff --git a/sys/boot/i386/boot0/Makefile b/sys/boot/i386/boot0/Makefile
index 733fc68..f5faef3 100644
--- a/sys/boot/i386/boot0/Makefile
+++ b/sys/boot/i386/boot0/Makefile
@@ -80,4 +80,3 @@ LDFLAGS=-e start -Ttext ${BOOT_BOOT0_ORG} -Wl,-N,-S,--oformat,binary
# XXX: clang integrated-as doesn't grok .codeNN directives yet
CFLAGS.boot0.S= ${CLANG_NO_IAS}
-CFLAGS+= ${CFLAGS.${.IMPSRC:T}}
diff --git a/sys/boot/i386/boot2/Makefile b/sys/boot/i386/boot2/Makefile
index 195206f..16ed404 100644
--- a/sys/boot/i386/boot2/Makefile
+++ b/sys/boot/i386/boot2/Makefile
@@ -115,4 +115,3 @@ machine: ${.CURDIR}/../../../i386/include .NOMETA
# XXX: clang integrated-as doesn't grok .codeNN directives yet
CFLAGS.boot1.S= ${CLANG_NO_IAS}
-CFLAGS+= ${CFLAGS.${.IMPSRC:T}}
diff --git a/sys/boot/i386/btx/btx/Makefile b/sys/boot/i386/btx/btx/Makefile
index 0f5a468..a07e000 100644
--- a/sys/boot/i386/btx/btx/Makefile
+++ b/sys/boot/i386/btx/btx/Makefile
@@ -31,4 +31,3 @@ LDFLAGS=-e start -Ttext ${ORG} -Wl,-N,-S,--oformat,binary
# XXX: clang integrated-as doesn't grok .codeNN directives yet
CFLAGS.btx.S= ${CLANG_NO_IAS}
-CFLAGS+= ${CFLAGS.${.IMPSRC:T}}
diff --git a/sys/boot/i386/btx/btxldr/Makefile b/sys/boot/i386/btx/btxldr/Makefile
index 7e57ca3..bf7833d 100644
--- a/sys/boot/i386/btx/btxldr/Makefile
+++ b/sys/boot/i386/btx/btxldr/Makefile
@@ -18,4 +18,3 @@ LDFLAGS=-e start -Ttext ${LOADER_ADDRESS} -Wl,-N,-S,--oformat,binary
# XXX: clang integrated-as doesn't grok .codeNN directives yet
CFLAGS.btxldr.S= ${CLANG_NO_IAS}
-CFLAGS+= ${CFLAGS.${.IMPSRC:T}}
diff --git a/sys/boot/i386/cdboot/Makefile b/sys/boot/i386/cdboot/Makefile
index a3dc251..e9e046b 100644
--- a/sys/boot/i386/cdboot/Makefile
+++ b/sys/boot/i386/cdboot/Makefile
@@ -16,4 +16,3 @@ LDFLAGS=-e start -Ttext ${ORG} -Wl,-N,-S,--oformat,binary
# XXX: clang integrated-as doesn't grok .codeNN directives yet
CFLAGS.cdboot.S= ${CLANG_NO_IAS}
-CFLAGS+= ${CFLAGS.${.IMPSRC:T}}
diff --git a/sys/boot/i386/common/bootargs.h b/sys/boot/i386/common/bootargs.h
index 4768d68..e6674e1 100644
--- a/sys/boot/i386/common/bootargs.h
+++ b/sys/boot/i386/common/bootargs.h
@@ -64,6 +64,12 @@ struct bootargs
*/
};
+struct geli_boot_args
+{
+ uint32_t size;
+ char gelipw[256];
+};
+
#endif /*__ASSEMBLER__*/
#endif /* !_BOOT_I386_ARGS_H_ */
diff --git a/sys/boot/i386/common/cons.c b/sys/boot/i386/common/cons.c
index 97019c6..b967d9b 100644
--- a/sys/boot/i386/common/cons.c
+++ b/sys/boot/i386/common/cons.c
@@ -97,6 +97,13 @@ xgetc(int fn)
}
int
+getchar(void)
+{
+
+ return (xgetc(0));
+}
+
+int
keyhit(unsigned int secs)
{
uint32_t t0, t1;
diff --git a/sys/boot/i386/common/drv.c b/sys/boot/i386/common/drv.c
index 52933d5..f5133de 100644
--- a/sys/boot/i386/common/drv.c
+++ b/sys/boot/i386/common/drv.c
@@ -29,7 +29,6 @@ __FBSDID("$FreeBSD$");
#include "xreadorg.h"
#endif
-#ifdef GPT
static struct edd_params params;
uint64_t
@@ -50,7 +49,6 @@ drvsize(struct dsk *dskp)
}
return (params.sectors);
}
-#endif /* GPT */
#ifndef USE_XREAD
static struct edd_packet packet;
diff --git a/sys/boot/i386/common/drv.h b/sys/boot/i386/common/drv.h
index 1ecfbc3..8ad3c9c 100644
--- a/sys/boot/i386/common/drv.h
+++ b/sys/boot/i386/common/drv.h
@@ -42,7 +42,7 @@ struct dsk {
int drvread(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk);
#ifdef GPT
int drvwrite(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk);
-uint64_t drvsize(struct dsk *dskp);
#endif /* GPT */
+uint64_t drvsize(struct dsk *dskp);
#endif /* !_DRV_H_ */
diff --git a/sys/boot/i386/gptboot/Makefile b/sys/boot/i386/gptboot/Makefile
index 1aafe0b..cc8251c 100644
--- a/sys/boot/i386/gptboot/Makefile
+++ b/sys/boot/i386/gptboot/Makefile
@@ -39,6 +39,14 @@ CFLAGS= -DBOOTPROG=\"gptboot\" \
CFLAGS.gcc+= --param max-inline-insns-single=100
+.if !defined(LOADER_NO_GELI_SUPPORT)
+CFLAGS+= -DLOADER_GELI_SUPPORT
+CFLAGS+= -I${.CURDIR}/../../geli
+LIBGELIBOOT= ${.OBJDIR}/../../geli/libgeliboot.a
+.PATH: ${.CURDIR}/../../../opencrypto
+OPENCRYPTO_XTS= xform_aes_xts.o
+.endif
+
LD_FLAGS=-static -N --gc-sections
LIBSTAND= ${.OBJDIR}/../../libstand32/libstand.a
@@ -60,14 +68,14 @@ gptldr.bin: gptldr.out
gptldr.out: gptldr.o
${LD} ${LD_FLAGS} -e start -Ttext ${ORG1} -o ${.TARGET} gptldr.o
-CLEANFILES+= gptboot.bin gptboot.out gptboot.o sio.o gpt.o crc32.o drv.o \
- cons.o util.o
+CLEANFILES+= gptboot.bin gptboot.out gptboot.o sio.o crc32.o drv.o \
+ cons.o util.o ${OPENCRYPTO_XTS}
gptboot.bin: gptboot.out
${OBJCOPY} -S -O binary gptboot.out ${.TARGET}
-gptboot.out: ${BTXCRT} gptboot.o sio.o gpt.o crc32.o drv.o cons.o util.o
- ${LD} ${LD_FLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC} ${LIBSTAND}
+gptboot.out: ${BTXCRT} gptboot.o sio.o crc32.o drv.o cons.o util.o ${OPENCRYPTO_XTS}
+ ${LD} ${LD_FLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC} ${LIBSTAND} ${LIBGELIBOOT}
gptboot.o: ${.CURDIR}/../../common/ufsread.c
@@ -82,4 +90,3 @@ machine: .NOMETA
# XXX: clang integrated-as doesn't grok .codeNN directives yet
CFLAGS.gptldr.S= ${CLANG_NO_IAS}
-CFLAGS+= ${CFLAGS.${.IMPSRC:T}}
diff --git a/sys/boot/i386/gptboot/Makefile.depend b/sys/boot/i386/gptboot/Makefile.depend
index c798603..295be1a 100644
--- a/sys/boot/i386/gptboot/Makefile.depend
+++ b/sys/boot/i386/gptboot/Makefile.depend
@@ -3,6 +3,10 @@
DIRDEPS = \
include \
+ include/xlocale \
+ lib/libmd \
+ lib/libstand \
+ sys/boot/geli \
sys/boot/i386/btx/btx \
sys/boot/i386/btx/lib \
sys/boot/libstand32 \
diff --git a/sys/boot/i386/gptboot/gptboot.c b/sys/boot/i386/gptboot/gptboot.c
index a1f46eb..14438e6 100644
--- a/sys/boot/i386/gptboot/gptboot.c
+++ b/sys/boot/i386/gptboot/gptboot.c
@@ -23,6 +23,7 @@ __FBSDID("$FreeBSD$");
#include <machine/bootinfo.h>
#include <machine/elf.h>
+#include <machine/pc/bios.h>
#include <machine/psl.h>
#include <stdarg.h>
@@ -31,6 +32,7 @@ __FBSDID("$FreeBSD$");
#include <btxv86.h>
+#include "bootargs.h"
#include "lib.h"
#include "rbx.h"
#include "drv.h"
@@ -82,14 +84,60 @@ static struct dsk dsk;
static char kname[1024];
static int comspeed = SIOSPD;
static struct bootinfo bootinfo;
+static struct geli_boot_args geliargs;
+
+static vm_offset_t high_heap_base;
+static uint32_t bios_basemem, bios_extmem, high_heap_size;
+
+static struct bios_smap smap;
+
+/*
+ * The minimum amount of memory to reserve in bios_extmem for the heap.
+ */
+#define HEAP_MIN (3 * 1024 * 1024)
+
+static char *heap_next;
+static char *heap_end;
void exit(int);
static void load(void);
static int parse(char *, int *);
static int dskread(void *, daddr_t, unsigned);
-static uint32_t memsize(void);
+void *malloc(size_t n);
+void free(void *ptr);
+#ifdef LOADER_GELI_SUPPORT
+static int vdev_read(void *vdev __unused, void *priv, off_t off, void *buf,
+ size_t bytes);
+#endif
+
+void *
+malloc(size_t n)
+{
+ char *p = heap_next;
+ if (p + n > heap_end) {
+ printf("malloc failure\n");
+ for (;;)
+ ;
+ /* NOTREACHED */
+ return (0);
+ }
+ heap_next += n;
+ return (p);
+}
+
+void
+free(void *ptr)
+{
+
+ return;
+}
#include "ufsread.c"
+#include "gpt.c"
+#ifdef LOADER_GELI_SUPPORT
+#include "geliboot.c"
+static char gelipw[GELI_PW_MAXLEN];
+#endif
static inline int
xfsread(ufs_ino_t inode, void *buf, size_t nbyte)
@@ -102,14 +150,90 @@ xfsread(ufs_ino_t inode, void *buf, size_t nbyte)
return (0);
}
-static inline uint32_t
-memsize(void)
+static void
+bios_getmem(void)
{
+ uint64_t size;
- v86.addr = MEM_EXT;
+ /* Parse system memory map */
+ v86.ebx = 0;
+ do {
+ v86.ctl = V86_FLAGS;
+ v86.addr = MEM_EXT; /* int 0x15 function 0xe820*/
+ v86.eax = 0xe820;
+ v86.ecx = sizeof(struct bios_smap);
+ v86.edx = SMAP_SIG;
+ v86.es = VTOPSEG(&smap);
+ v86.edi = VTOPOFF(&smap);
+ v86int();
+ if ((v86.efl & 1) || (v86.eax != SMAP_SIG))
+ break;
+ /* look for a low-memory segment that's large enough */
+ if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base == 0) &&
+ (smap.length >= (512 * 1024)))
+ bios_basemem = smap.length;
+ /* look for the first segment in 'extended' memory */
+ if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base == 0x100000)) {
+ bios_extmem = smap.length;
+ }
+
+ /*
+ * Look for the largest segment in 'extended' memory beyond
+ * 1MB but below 4GB.
+ */
+ if ((smap.type == SMAP_TYPE_MEMORY) && (smap.base > 0x100000) &&
+ (smap.base < 0x100000000ull)) {
+ size = smap.length;
+
+ /*
+ * If this segment crosses the 4GB boundary, truncate it.
+ */
+ if (smap.base + size > 0x100000000ull)
+ size = 0x100000000ull - smap.base;
+
+ if (size > high_heap_size) {
+ high_heap_size = size;
+ high_heap_base = smap.base;
+ }
+ }
+ } while (v86.ebx != 0);
+
+ /* Fall back to the old compatibility function for base memory */
+ if (bios_basemem == 0) {
+ v86.ctl = 0;
+ v86.addr = 0x12; /* int 0x12 */
+ v86int();
+
+ bios_basemem = (v86.eax & 0xffff) * 1024;
+ }
+
+ /* Fall back through several compatibility functions for extended memory */
+ if (bios_extmem == 0) {
+ v86.ctl = V86_FLAGS;
+ v86.addr = 0x15; /* int 0x15 function 0xe801*/
+ v86.eax = 0xe801;
+ v86int();
+ if (!(v86.efl & 1)) {
+ bios_extmem = ((v86.ecx & 0xffff) + ((v86.edx & 0xffff) * 64)) * 1024;
+ }
+ }
+ if (bios_extmem == 0) {
+ v86.ctl = 0;
+ v86.addr = 0x15; /* int 0x15 function 0x88*/
v86.eax = 0x8800;
v86int();
- return (v86.eax);
+ bios_extmem = (v86.eax & 0xffff) * 1024;
+ }
+
+ /*
+ * If we have extended memory and did not find a suitable heap
+ * region in the SMAP, use the last 3MB of 'extended' memory as a
+ * high heap candidate.
+ */
+ if (bios_extmem >= HEAP_MIN && high_heap_size < HEAP_MIN) {
+ high_heap_size = HEAP_MIN;
+ high_heap_base = bios_extmem + 0x100000 - HEAP_MIN;
+ }
}
static int
@@ -124,6 +248,16 @@ gptinit(void)
printf("%s: no UFS partition was found\n", BOOTPROG);
return (-1);
}
+#ifdef LOADER_GELI_SUPPORT
+ if (geli_taste(vdev_read, &dsk, (gpttable[curent].ent_lba_end -
+ gpttable[curent].ent_lba_start)) == 0) {
+ if (geli_passphrase(&gelipw, dsk.unit, 'p', curent + 1, &dsk) != 0) {
+ printf("%s: unable to decrypt GELI key\n", BOOTPROG);
+ return (-1);
+ }
+ }
+#endif
+
dsk_meta = 0;
return (0);
}
@@ -137,6 +271,17 @@ main(void)
ufs_ino_t ino;
dmadat = (void *)(roundup2(__base + (int32_t)&_end, 0x10000) - __base);
+
+ bios_getmem();
+
+ if (high_heap_size > 0) {
+ heap_end = PTOV(high_heap_base + high_heap_size);
+ heap_next = PTOV(high_heap_base);
+ } else {
+ heap_next = (char *)dmadat + sizeof(*dmadat);
+ heap_end = (char *)PTOV(bios_basemem);
+ }
+
v86.ctl = V86_FLAGS;
v86.efl = PSL_RESERVED_DEFAULT | PSL_I;
dsk.drive = *(uint8_t *)PTOV(ARGS);
@@ -146,10 +291,14 @@ main(void)
dsk.start = 0;
bootinfo.bi_version = BOOTINFO_VERSION;
bootinfo.bi_size = sizeof(bootinfo);
- bootinfo.bi_basemem = 0; /* XXX will be filled by loader or kernel */
- bootinfo.bi_extmem = memsize();
+ bootinfo.bi_basemem = bios_basemem / 1024;
+ bootinfo.bi_extmem = bios_extmem / 1024;
bootinfo.bi_memsizes_valid++;
+ bootinfo.bi_bios_dev = dsk.drive;
+#ifdef LOADER_GELI_SUPPORT
+ geli_init();
+#endif
/* Process configuration file */
if (gptinit() != 0)
@@ -327,9 +476,16 @@ load(void)
bootinfo.bi_esymtab = VTOP(p);
bootinfo.bi_kernelname = VTOP(kname);
bootinfo.bi_bios_dev = dsk.drive;
+ geliargs.size = sizeof(geliargs);
+#ifdef LOADER_GELI_SUPPORT
+ bcopy(gelipw, geliargs.gelipw, sizeof(geliargs.gelipw));
+ bzero(gelipw, sizeof(gelipw));
+#else
+ geliargs.gelipw[0] = '\0';
+#endif
__exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK),
MAKEBOOTDEV(dev_maj[dsk.type], dsk.part + 1, dsk.unit, 0xff),
- 0, 0, 0, VTOP(&bootinfo));
+ KARGS_FLAGS_EXTARG, 0, 0, VTOP(&bootinfo), geliargs);
}
static int
@@ -430,6 +586,53 @@ parse(char *cmdstr, int *dskupdated)
static int
dskread(void *buf, daddr_t lba, unsigned nblk)
{
+ int err;
+
+ err = drvread(&dsk, buf, lba + dsk.start, nblk);
- return drvread(&dsk, buf, lba + dsk.start, nblk);
+#ifdef LOADER_GELI_SUPPORT
+ if (err == 0 && is_geli(&dsk) == 0) {
+ /* Decrypt */
+ if (geli_read(&dsk, lba * DEV_BSIZE, buf, nblk * DEV_BSIZE))
+ return (err);
+ }
+#endif
+
+ return (err);
+}
+
+#ifdef LOADER_GELI_SUPPORT
+/*
+ * Read function compartible with the ZFS callback, required to keep the GELI
+ * Implementation the same for both UFS and ZFS
+ */
+static int
+vdev_read(void *vdev __unused, void *priv, off_t off, void *buf, size_t bytes)
+{
+ char *p;
+ daddr_t lba;
+ unsigned int nb;
+ struct dsk *dskp = (struct dsk *) priv;
+
+ if ((off & (DEV_BSIZE - 1)) || (bytes & (DEV_BSIZE - 1)))
+ return (-1);
+
+ p = buf;
+ lba = off / DEV_BSIZE;
+ lba += dskp->start;
+
+ while (bytes > 0) {
+ nb = bytes / DEV_BSIZE;
+ if (nb > VBLKSIZE / DEV_BSIZE)
+ nb = VBLKSIZE / DEV_BSIZE;
+ if (drvread(dskp, dmadat->blkbuf, lba, nb))
+ return (-1);
+ memcpy(p, dmadat->blkbuf, nb * DEV_BSIZE);
+ p += nb * DEV_BSIZE;
+ lba += nb;
+ bytes -= nb * DEV_BSIZE;
+ }
+
+ return (0);
}
+#endif /* LOADER_GELI_SUPPORT */
diff --git a/sys/boot/i386/gptzfsboot/Makefile b/sys/boot/i386/gptzfsboot/Makefile
index 1406333..97ddd39 100644
--- a/sys/boot/i386/gptzfsboot/Makefile
+++ b/sys/boot/i386/gptzfsboot/Makefile
@@ -35,6 +35,14 @@ CFLAGS= -DBOOTPROG=\"gptzfsboot\" \
-Wpointer-arith -Wshadow -Wstrict-prototypes -Wwrite-strings \
-Winline
+.if !defined(LOADER_NO_GELI_SUPPORT)
+CFLAGS+= -DLOADER_GELI_SUPPORT
+CFLAGS+= -I${.CURDIR}/../../geli
+LIBGELIBOOT= ${.OBJDIR}/../../geli/libgeliboot.a
+.PATH: ${.CURDIR}/../../../opencrypto
+OPENCRYPTO_XTS= xform_aes_xts.o
+.endif
+
CFLAGS.gcc+= --param max-inline-insns-single=100
LD_FLAGS=-static -N --gc-sections
@@ -59,13 +67,13 @@ gptldr.out: gptldr.o
${LD} ${LD_FLAGS} -e start -Ttext ${ORG1} -o ${.TARGET} gptldr.o
CLEANFILES+= gptzfsboot.bin gptzfsboot.out zfsboot.o sio.o cons.o \
- drv.o gpt.o util.o
+ drv.o gpt.o util.o ${OPENCRYPTO_XTS}
gptzfsboot.bin: gptzfsboot.out
${OBJCOPY} -S -O binary gptzfsboot.out ${.TARGET}
-gptzfsboot.out: ${BTXCRT} zfsboot.o sio.o gpt.o drv.o cons.o util.o
- ${LD} ${LD_FLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC} ${LIBSTAND}
+gptzfsboot.out: ${BTXCRT} zfsboot.o sio.o gpt.o drv.o cons.o util.o ${OPENCRYPTO_XTS}
+ ${LD} ${LD_FLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC} ${LIBSTAND} ${LIBGELIBOOT}
zfsboot.o: ${.CURDIR}/../../zfs/zfsimpl.c
@@ -80,4 +88,3 @@ machine: .NOMETA
# XXX: clang integrated-as doesn't grok .codeNN directives yet
CFLAGS.gptldr.S= ${CLANG_NO_IAS}
-CFLAGS+= ${CFLAGS.${.IMPSRC:T}}
diff --git a/sys/boot/i386/gptzfsboot/Makefile.depend b/sys/boot/i386/gptzfsboot/Makefile.depend
index 63a43d8..295be1a 100644
--- a/sys/boot/i386/gptzfsboot/Makefile.depend
+++ b/sys/boot/i386/gptzfsboot/Makefile.depend
@@ -4,6 +4,9 @@
DIRDEPS = \
include \
include/xlocale \
+ lib/libmd \
+ lib/libstand \
+ sys/boot/geli \
sys/boot/i386/btx/btx \
sys/boot/i386/btx/lib \
sys/boot/libstand32 \
diff --git a/sys/boot/i386/libi386/Makefile b/sys/boot/i386/libi386/Makefile
index f3c1d8d..f1c55f1 100644
--- a/sys/boot/i386/libi386/Makefile
+++ b/sys/boot/i386/libi386/Makefile
@@ -30,6 +30,12 @@ CFLAGS+= -DCOMSPEED=${BOOT_COMCONSOLE_SPEED}
CFLAGS+= -DDISK_DEBUG
.endif
+.if !defined(LOADER_NO_GELI_SUPPORT)
+# Decrypt encrypted drives
+CFLAGS+= -DLOADER_GELI_SUPPORT
+CFLAGS+= -I${.CURDIR}/../../geli
+.endif
+
.if !defined(BOOT_HIDE_SERIAL_NUMBERS)
# Export serial numbers, UUID, and asset tag from loader.
CFLAGS+= -DSMBIOS_SERIAL_NUMBERS
@@ -69,7 +75,6 @@ machine: .NOMETA
# XXX: clang integrated-as doesn't grok .codeNN directives yet
CFLAGS.amd64_tramp.S= ${CLANG_NO_IAS}
CFLAGS.multiboot_tramp.S= ${CLANG_NO_IAS}
-CFLAGS+= ${CFLAGS.${.IMPSRC:T}}
.if ${MACHINE_CPUARCH} == "amd64"
beforedepend ${OBJS}: machine
diff --git a/sys/boot/i386/libi386/Makefile.depend b/sys/boot/i386/libi386/Makefile.depend
index 18be76b..df20c96 100644
--- a/sys/boot/i386/libi386/Makefile.depend
+++ b/sys/boot/i386/libi386/Makefile.depend
@@ -4,6 +4,7 @@
DIRDEPS = \
include \
include/xlocale \
+ lib/libmd \
.include <dirdeps.mk>
diff --git a/sys/boot/i386/libi386/biosdisk.c b/sys/boot/i386/libi386/biosdisk.c
index 2a71d64..1c54769 100644
--- a/sys/boot/i386/libi386/biosdisk.c
+++ b/sys/boot/i386/libi386/biosdisk.c
@@ -49,6 +49,34 @@ __FBSDID("$FreeBSD$");
#include "disk.h"
#include "libi386.h"
+#ifdef LOADER_GELI_SUPPORT
+#include "cons.h"
+#include "drv.h"
+#include "gpt.h"
+#include "part.h"
+#include <uuid.h>
+struct pentry {
+ struct ptable_entry part;
+ uint64_t flags;
+ union {
+ uint8_t bsd;
+ uint8_t mbr;
+ uuid_t gpt;
+ uint16_t vtoc8;
+ } type;
+ STAILQ_ENTRY(pentry) entry;
+};
+struct ptable {
+ enum ptable_type type;
+ uint16_t sectorsize;
+ uint64_t sectors;
+
+ STAILQ_HEAD(, pentry) entries;
+};
+
+#include "geliboot.c"
+#endif /* LOADER_GELI_SUPPORT */
+
CTASSERT(sizeof(struct i386_devdesc) >= sizeof(struct disk_devdesc));
#define BIOS_NUMDRIVES 0x475
@@ -108,6 +136,18 @@ static int bd_ioctl(struct open_file *f, u_long cmd, void *data);
static void bd_print(int verbose);
static void bd_cleanup(void);
+#ifdef LOADER_GELI_SUPPORT
+static enum isgeli {
+ ISGELI_UNKNOWN,
+ ISGELI_NO,
+ ISGELI_YES
+};
+static enum isgeli geli_status[MAXBDDEV][MAXTBLENTS];
+
+int bios_read(void *vdev __unused, struct dsk *priv, off_t off, char *buf,
+ size_t bytes);
+#endif /* LOADER_GELI_SUPPORT */
+
struct devsw biosdisk = {
"disk",
DEVT_DISK,
@@ -154,6 +194,9 @@ bd_init(void)
{
int base, unit, nfd = 0;
+#ifdef LOADER_GELI_SUPPORT
+ geli_init();
+#endif
/* sequence 0, 0x80 */
for (base = 0; base <= 0x80; base += 0x80) {
for (unit = base; (nbdinfo < MAXBDDEV); unit++) {
@@ -299,7 +342,8 @@ bd_print(int verbose)
static int
bd_open(struct open_file *f, ...)
{
- struct disk_devdesc *dev;
+ struct disk_devdesc *dev, rdev;
+ int err, g_err;
va_list ap;
va_start(ap, f);
@@ -309,9 +353,83 @@ bd_open(struct open_file *f, ...)
if (dev->d_unit < 0 || dev->d_unit >= nbdinfo)
return (EIO);
- return (disk_open(dev, BD(dev).bd_sectors * BD(dev).bd_sectorsize,
+ err = disk_open(dev, BD(dev).bd_sectors * BD(dev).bd_sectorsize,
BD(dev).bd_sectorsize, (BD(dev).bd_flags & BD_FLOPPY) ?
- DISK_F_NOCACHE: 0));
+ DISK_F_NOCACHE: 0);
+
+#ifdef LOADER_GELI_SUPPORT
+ static char gelipw[GELI_PW_MAXLEN];
+ char *passphrase;
+
+ if (err)
+ return (err);
+
+ /* if we already know there is no GELI, skip the rest */
+ if (geli_status[dev->d_unit][dev->d_slice] != ISGELI_UNKNOWN)
+ return (err);
+
+ struct dsk dskp;
+ struct ptable *table = NULL;
+ struct ptable_entry part;
+ struct pentry *entry;
+ int geli_part = 0;
+
+ dskp.drive = bd_unit2bios(dev->d_unit);
+ dskp.type = dev->d_type;
+ dskp.unit = dev->d_unit;
+ dskp.slice = dev->d_slice;
+ dskp.part = dev->d_partition;
+ dskp.start = dev->d_offset;
+
+ memcpy(&rdev, dev, sizeof(rdev));
+ /* to read the GPT table, we need to read the first sector */
+ rdev.d_offset = 0;
+ /* We need the LBA of the end of the partition */
+ table = ptable_open(&rdev, BD(dev).bd_sectors,
+ BD(dev).bd_sectorsize, ptblread);
+ if (table == NULL) {
+ DEBUG("Can't read partition table");
+ /* soft failure, return the exit status of disk_open */
+ return (err);
+ }
+
+ if (table->type == PTABLE_GPT)
+ dskp.part = 255;
+
+ STAILQ_FOREACH(entry, &table->entries, entry) {
+ dskp.slice = entry->part.index;
+ dskp.start = entry->part.start;
+ if (is_geli(&dskp) == 0) {
+ geli_status[dev->d_unit][dskp.slice] = ISGELI_YES;
+ return (0);
+ }
+ if (geli_taste(bios_read, &dskp,
+ entry->part.end - entry->part.start) == 0) {
+ if ((passphrase = getenv("kern.geom.eli.passphrase"))
+ != NULL) {
+ /* Use the cached passphrase */
+ bcopy(passphrase, &gelipw, GELI_PW_MAXLEN);
+ }
+ if (geli_passphrase(&gelipw, dskp.unit, 'p',
+ (dskp.slice > 0 ? dskp.slice : dskp.part),
+ &dskp) == 0) {
+ setenv("kern.geom.eli.passphrase", &gelipw, 1);
+ bzero(gelipw, sizeof(gelipw));
+ geli_status[dev->d_unit][dskp.slice] = ISGELI_YES;
+ geli_part++;
+ }
+ } else
+ geli_status[dev->d_unit][dskp.slice] = ISGELI_NO;
+ }
+
+ /* none of the partitions on this disk have GELI */
+ if (geli_part == 0) {
+ /* found no GELI */
+ geli_status[dev->d_unit][dev->d_slice] = ISGELI_NO;
+ }
+#endif /* LOADER_GELI_SUPPORT */
+
+ return (err);
}
static int
@@ -586,6 +704,38 @@ bd_io(struct disk_devdesc *dev, daddr_t dblk, int blks, caddr_t dest, int write)
static int
bd_read(struct disk_devdesc *dev, daddr_t dblk, int blks, caddr_t dest)
{
+#ifdef LOADER_GELI_SUPPORT
+ struct dsk dskp;
+ off_t p_off;
+ int err, n;
+
+ /* if we already know there is no GELI, skip the rest */
+ if (geli_status[dev->d_unit][dev->d_slice] != ISGELI_YES)
+ return (bd_io(dev, dblk, blks, dest, 0));
+
+ if (geli_status[dev->d_unit][dev->d_slice] == ISGELI_YES) {
+ err = bd_io(dev, dblk, blks, dest, 0);
+ if (err)
+ return (err);
+
+ dskp.drive = bd_unit2bios(dev->d_unit);
+ dskp.type = dev->d_type;
+ dskp.unit = dev->d_unit;
+ dskp.slice = dev->d_slice;
+ dskp.part = dev->d_partition;
+ dskp.start = dev->d_offset;
+
+ /* GELI needs the offset relative to the partition start */
+ p_off = dblk - dskp.start;
+
+ err = geli_read(&dskp, p_off * BIOSDISK_SECSIZE, dest,
+ blks * BIOSDISK_SECSIZE);
+ if (err)
+ return (err);
+
+ return (0);
+ }
+#endif /* LOADER_GELI_SUPPORT */
return (bd_io(dev, dblk, blks, dest, 0));
}
@@ -682,3 +832,25 @@ bd_getdev(struct i386_devdesc *d)
DEBUG("dev is 0x%x\n", rootdev);
return(rootdev);
}
+
+#ifdef LOADER_GELI_SUPPORT
+int
+bios_read(void *vdev __unused, struct dsk *priv, off_t off, char *buf, size_t bytes)
+{
+ struct disk_devdesc dev;
+
+ dev.d_dev = &biosdisk;
+ dev.d_type = priv->type;
+ dev.d_unit = priv->unit;
+ dev.d_slice = priv->slice;
+ dev.d_partition = priv->part;
+ dev.d_offset = priv->start;
+
+ off = off / BIOSDISK_SECSIZE;
+ /* GELI gives us the offset relative to the partition start */
+ off += dev.d_offset;
+ bytes = bytes / BIOSDISK_SECSIZE;
+
+ return (bd_io(&dev, off, bytes, buf, 0));
+}
+#endif /* LOADER_GELI_SUPPORT */
diff --git a/sys/boot/i386/libi386/pxe.c b/sys/boot/i386/libi386/pxe.c
index efa04fc..d67665e 100644
--- a/sys/boot/i386/libi386/pxe.c
+++ b/sys/boot/i386/libi386/pxe.c
@@ -310,6 +310,11 @@ pxe_open(struct open_file *f, ...)
sprintf(temp, "%6D", bootplayer.CAddr, ":");
setenv("boot.netif.hwaddr", temp, 1);
}
+ if (intf_mtu != 0) {
+ char mtu[16];
+ sprintf(mtu, "%u", intf_mtu);
+ setenv("boot.netif.mtu", mtu, 1);
+ }
#ifdef LOADER_NFS_SUPPORT
printf("pxe_open: server addr: %s\n", inet_ntoa(rootip));
printf("pxe_open: server path: %s\n", rootpath);
diff --git a/sys/boot/i386/loader/Makefile b/sys/boot/i386/loader/Makefile
index 776ba92..233876a 100644
--- a/sys/boot/i386/loader/Makefile
+++ b/sys/boot/i386/loader/Makefile
@@ -58,6 +58,13 @@ CFLAGS+= -DLOADER_GZIP_SUPPORT
.if defined(LOADER_NANDFS_SUPPORT)
CFLAGS+= -DLOADER_NANDFS_SUPPORT
.endif
+.if !defined(LOADER_NO_GELI_SUPPORT)
+CFLAGS+= -DLOADER_GELI_SUPPORT
+LIBGELIBOOT= ${.OBJDIR}/../../geli/libgeliboot.a
+.PATH: ${.CURDIR}/../../../opencrypto
+SRCS+= xform_aes_xts.c
+CFLAGS+= -I${.CURDIR}/../../.. -D_STAND
+.endif
# Always add MI sources
.PATH: ${.CURDIR}/../../common
@@ -116,8 +123,8 @@ FILES+= loader.rc menu.rc
# XXX crt0.o needs to be first for pxeboot(8) to work
OBJS= ${BTXCRT}
-DPADD= ${LIBFICL} ${LIBFIREWIRE} ${LIBZFSBOOT} ${LIBI386} ${LIBSTAND}
-LDADD= ${LIBFICL} ${LIBFIREWIRE} ${LIBZFSBOOT} ${LIBI386} ${LIBSTAND}
+DPADD= ${LIBFICL} ${LIBFIREWIRE} ${LIBZFSBOOT} ${LIBI386} ${LIBSTAND} ${LIBGELIBOOT}
+LDADD= ${LIBFICL} ${LIBFIREWIRE} ${LIBZFSBOOT} ${LIBI386} ${LIBSTAND} ${LIBGELIBOOT}
.include <bsd.prog.mk>
diff --git a/sys/boot/i386/loader/Makefile.depend b/sys/boot/i386/loader/Makefile.depend
index 9650fc0..89d5422 100644
--- a/sys/boot/i386/loader/Makefile.depend
+++ b/sys/boot/i386/loader/Makefile.depend
@@ -6,6 +6,7 @@ DIRDEPS = \
include/xlocale \
lib/libstand \
sys/boot/ficl32 \
+ sys/boot/geli \
sys/boot/i386/btx/btx \
sys/boot/i386/btx/btxldr \
sys/boot/i386/btx/lib \
diff --git a/sys/boot/i386/loader/main.c b/sys/boot/i386/loader/main.c
index c0782fc..b3e7b41 100644
--- a/sys/boot/i386/loader/main.c
+++ b/sys/boot/i386/loader/main.c
@@ -68,7 +68,11 @@ static void extract_currdev(void);
static int isa_inb(int port);
static void isa_outb(int port, int value);
void exit(int code);
+#ifdef LOADER_GELI_SUPPORT
+struct geli_boot_args *gargs;
+#endif
#ifdef LOADER_ZFS_SUPPORT
+struct zfs_boot_args *zargs;
static void i386_zfs_probe(void);
#endif
@@ -164,7 +168,31 @@ main(void)
archsw.arch_isaoutb = isa_outb;
#ifdef LOADER_ZFS_SUPPORT
archsw.arch_zfs_probe = i386_zfs_probe;
-#endif
+
+#ifdef LOADER_GELI_SUPPORT
+ if ((kargs->bootflags & KARGS_FLAGS_EXTARG) != 0) {
+ zargs = (struct zfs_boot_args *)(kargs + 1);
+ if (zargs != NULL && zargs->size >= offsetof(struct zfs_boot_args, gelipw)) {
+ if (zargs->gelipw[0] != '\0') {
+ setenv("kern.geom.eli.passphrase", zargs->gelipw, 1);
+ bzero(zargs->gelipw, sizeof(zargs->gelipw));
+ }
+ }
+ }
+#endif /* LOADER_GELI_SUPPORT */
+#else /* !LOADER_ZFS_SUPPORT */
+#ifdef LOADER_GELI_SUPPORT
+ if ((kargs->bootflags & KARGS_FLAGS_EXTARG) != 0) {
+ gargs = (struct geli_boot_args *)(kargs + 1);
+ if (gargs != NULL && gargs->size >= offsetof(struct geli_boot_args, gelipw)) {
+ if (gargs->gelipw[0] != '\0') {
+ setenv("kern.geom.eli.passphrase", gargs->gelipw, 1);
+ bzero(gargs->gelipw, sizeof(gargs->gelipw));
+ }
+ }
+ }
+#endif /* LOADER_GELI_SUPPORT */
+#endif /* LOADER_ZFS_SUPPORT */
/*
* March through the device switch probing for things.
@@ -214,7 +242,6 @@ extract_currdev(void)
struct i386_devdesc new_currdev;
#ifdef LOADER_ZFS_SUPPORT
char buf[20];
- struct zfs_boot_args *zargs;
#endif
int biosdev = -1;
diff --git a/sys/boot/i386/pxeldr/Makefile b/sys/boot/i386/pxeldr/Makefile
index c4e008f..8de2139 100644
--- a/sys/boot/i386/pxeldr/Makefile
+++ b/sys/boot/i386/pxeldr/Makefile
@@ -46,4 +46,3 @@ ${LOADER}: ${LOADERBIN} ${BTXLDR} ${BTXKERN}
# XXX: clang integrated-as doesn't grok .codeNN directives yet
CFLAGS.pxeldr.S= ${CLANG_NO_IAS}
-CFLAGS+= ${CFLAGS.${.IMPSRC:T}}
diff --git a/sys/boot/i386/zfsboot/Makefile b/sys/boot/i386/zfsboot/Makefile
index f65e0ad..7f434a8 100644
--- a/sys/boot/i386/zfsboot/Makefile
+++ b/sys/boot/i386/zfsboot/Makefile
@@ -93,4 +93,3 @@ machine: .NOMETA
# XXX: clang integrated-as doesn't grok .codeNN directives yet
CFLAGS.zfsldr.S= ${CLANG_NO_IAS}
-CFLAGS+= ${CFLAGS.${.IMPSRC:T}}
diff --git a/sys/boot/i386/zfsboot/zfsboot.c b/sys/boot/i386/zfsboot/zfsboot.c
index 6fbbc6f..4b371dc 100644
--- a/sys/boot/i386/zfsboot/zfsboot.c
+++ b/sys/boot/i386/zfsboot/zfsboot.c
@@ -121,8 +121,10 @@ void exit(int);
static void load(void);
static int parse(void);
static void bios_getmem(void);
+void *malloc(size_t n);
+void free(void *ptr);
-static void *
+void *
malloc(size_t n)
{
char *p = heap_next;
@@ -130,10 +132,18 @@ malloc(size_t n)
printf("malloc failure\n");
for (;;)
;
- return 0;
+ /* NOTREACHED */
+ return (0);
}
heap_next += n;
- return p;
+ return (p);
+}
+
+void
+free(void *ptr)
+{
+
+ return;
}
static char *
@@ -141,9 +151,14 @@ strdup(const char *s)
{
char *p = malloc(strlen(s) + 1);
strcpy(p, s);
- return p;
+ return (p);
}
+#ifdef LOADER_GELI_SUPPORT
+#include "geliboot.c"
+static char gelipw[GELI_PW_MAXLEN];
+#endif
+
#include "zfsimpl.c"
/*
@@ -199,6 +214,14 @@ vdev_read(vdev_t *vdev, void *priv, off_t off, void *buf, size_t bytes)
nb = READ_BUF_SIZE / DEV_BSIZE;
if (drvread(dsk, dmadat->rdbuf, lba, nb))
return -1;
+#ifdef LOADER_GELI_SUPPORT
+ /* decrypt */
+ if (is_geli(dsk) == 0) {
+ if (geli_read(dsk, ((lba - dsk->start) * DEV_BSIZE),
+ dmadat->rdbuf, nb * DEV_BSIZE))
+ return (-1);
+ }
+#endif
memcpy(p, dmadat->rdbuf, nb * DEV_BSIZE);
p += nb * DEV_BSIZE;
lba += nb;
@@ -302,7 +325,7 @@ bios_getmem(void)
high_heap_size = HEAP_MIN;
high_heap_base = bios_extmem + 0x100000 - HEAP_MIN;
}
-}
+}
/*
* Try to detect a device supported by the legacy int13 BIOS
@@ -346,21 +369,39 @@ probe_drive(struct dsk *dsk)
#ifdef GPT
struct gpt_hdr hdr;
struct gpt_ent *ent;
- daddr_t slba, elba;
unsigned part, entries_per_sec;
#endif
+ daddr_t slba, elba;
struct dos_partition *dp;
char *sec;
unsigned i;
/*
- * If we find a vdev on the whole disk, stop here. Otherwise dig
- * out the partition table and probe each slice/partition
- * in turn for a vdev.
+ * If we find a vdev on the whole disk, stop here.
*/
if (vdev_probe(vdev_read, dsk, NULL) == 0)
return;
+#ifdef LOADER_GELI_SUPPORT
+ /*
+ * Taste the disk, if it is GELI encrypted, decrypt it and check to see if
+ * it is a usable vdev then. Otherwise dig
+ * out the partition table and probe each slice/partition
+ * in turn for a vdev or GELI encrypted vdev.
+ */
+ elba = drvsize(dsk);
+ if (elba > 0) {
+ elba--;
+ }
+ if (geli_taste(vdev_read, dsk, elba) == 0) {
+ if (geli_passphrase(&gelipw, dsk->unit, ':', 0, dsk) == 0) {
+ if (vdev_probe(vdev_read, dsk, NULL) == 0) {
+ return;
+ }
+ }
+ }
+#endif /* LOADER_GELI_SUPPORT */
+
sec = dmadat->secbuf;
dsk->start = 0;
@@ -383,6 +424,8 @@ probe_drive(struct dsk *dsk)
* return the spa_t for the first we find (if requested). This
* will have the effect of booting from the first pool on the
* disk.
+ *
+ * If no vdev is found, GELI decrypting the device and try again
*/
entries_per_sec = DEV_BSIZE / hdr.hdr_entsz;
slba = hdr.hdr_lba_table;
@@ -396,6 +439,8 @@ probe_drive(struct dsk *dsk)
if (memcmp(&ent->ent_type, &freebsd_zfs_uuid,
sizeof(uuid_t)) == 0) {
dsk->start = ent->ent_lba_start;
+ dsk->slice = part + 1;
+ dsk->part = 255;
if (vdev_probe(vdev_read, dsk, NULL) == 0) {
/*
* This slice had a vdev. We need a new dsk
@@ -403,13 +448,31 @@ probe_drive(struct dsk *dsk)
*/
dsk = copy_dsk(dsk);
}
+#ifdef LOADER_GELI_SUPPORT
+ else if (geli_taste(vdev_read, dsk, ent->ent_lba_end -
+ ent->ent_lba_start) == 0) {
+ if (geli_passphrase(&gelipw, dsk->unit, 'p', dsk->slice, dsk) == 0) {
+ /*
+ * This slice has GELI, check it for ZFS.
+ */
+ if (vdev_probe(vdev_read, dsk, NULL) == 0) {
+ /*
+ * This slice had a vdev. We need a new dsk
+ * structure now since the vdev now owns this one.
+ */
+ dsk = copy_dsk(dsk);
+ }
+ break;
+ }
+ }
+#endif /* LOADER_GELI_SUPPORT */
}
}
slba++;
}
return;
trymbr:
-#endif
+#endif /* GPT */
if (drvread(dsk, sec, DOSBBSECTOR, 1))
return;
@@ -419,13 +482,28 @@ trymbr:
if (!dp[i].dp_typ)
continue;
dsk->start = dp[i].dp_start;
+ dsk->slice = i + 1;
if (vdev_probe(vdev_read, dsk, NULL) == 0) {
- /*
- * This slice had a vdev. We need a new dsk structure now
- * since the vdev now owns this one.
- */
dsk = copy_dsk(dsk);
}
+#ifdef LOADER_GELI_SUPPORT
+ else if (geli_taste(vdev_read, dsk, dp[i].dp_size -
+ dp[i].dp_start) == 0) {
+ if (geli_passphrase(&gelipw, dsk->unit, 's', i, dsk) == 0) {
+ /*
+ * This slice has GELI, check it for ZFS.
+ */
+ if (vdev_probe(vdev_read, dsk, NULL) == 0) {
+ /*
+ * This slice had a vdev. We need a new dsk
+ * structure now since the vdev now owns this one.
+ */
+ dsk = copy_dsk(dsk);
+ }
+ break;
+ }
+ }
+#endif /* LOADER_GELI_SUPPORT */
}
}
@@ -445,8 +523,8 @@ main(void)
heap_end = PTOV(high_heap_base + high_heap_size);
heap_next = PTOV(high_heap_base);
} else {
- heap_next = (char *) dmadat + sizeof(*dmadat);
- heap_end = (char *) PTOV(bios_basemem);
+ heap_next = (char *)dmadat + sizeof(*dmadat);
+ heap_end = (char *)PTOV(bios_basemem);
}
dsk = malloc(sizeof(struct dsk));
@@ -472,6 +550,9 @@ main(void)
autoboot = 1;
+#ifdef LOADER_GELI_SUPPORT
+ geli_init();
+#endif
zfs_init();
/*
@@ -690,6 +771,12 @@ load(void)
zfsargs.pool = zfsmount.spa->spa_guid;
zfsargs.root = zfsmount.rootobj;
zfsargs.primary_pool = primary_spa->spa_guid;
+#ifdef LOADER_GELI_SUPPORT
+ bcopy(gelipw, zfsargs.gelipw, sizeof(zfsargs.gelipw));
+ bzero(gelipw, sizeof(gelipw));
+#else
+ zfsargs.gelipw[0] = '\0';
+#endif
if (primary_vdev != NULL)
zfsargs.primary_vdev = primary_vdev->v_guid;
else
diff --git a/sys/boot/i386/zfsloader/Makefile.depend b/sys/boot/i386/zfsloader/Makefile.depend
index b3810a2..15b0c98 100644
--- a/sys/boot/i386/zfsloader/Makefile.depend
+++ b/sys/boot/i386/zfsloader/Makefile.depend
@@ -6,6 +6,7 @@ DIRDEPS = \
include/xlocale \
lib/libstand \
sys/boot/ficl32 \
+ sys/boot/geli \
sys/boot/i386/btx/btx \
sys/boot/i386/btx/btxldr \
sys/boot/i386/btx/lib \
diff --git a/sys/boot/pc98/boot2/Makefile b/sys/boot/pc98/boot2/Makefile
index 6af4f90..8d5e791 100644
--- a/sys/boot/pc98/boot2/Makefile
+++ b/sys/boot/pc98/boot2/Makefile
@@ -114,4 +114,3 @@ boot2.h: boot1.out
# XXX: clang integrated-as doesn't grok .codeNN directives yet
CFLAGS.boot1.S= ${CLANG_NO_IAS}
-CFLAGS+= ${CFLAGS.${.IMPSRC:T}}
diff --git a/sys/boot/pc98/btx/btx/Makefile b/sys/boot/pc98/btx/btx/Makefile
index 905908f..9046d35 100644
--- a/sys/boot/pc98/btx/btx/Makefile
+++ b/sys/boot/pc98/btx/btx/Makefile
@@ -31,4 +31,3 @@ LDFLAGS=-e start -Ttext ${ORG} -Wl,-N,-S,--oformat,binary
# XXX: clang integrated-as doesn't grok .codeNN directives yet
CFLAGS.btx.S= ${CLANG_NO_IAS}
-CFLAGS+= ${CFLAGS.${.IMPSRC:T}}
diff --git a/sys/boot/pc98/btx/btxldr/Makefile b/sys/boot/pc98/btx/btxldr/Makefile
index 7d34e9e..b0c8996 100644
--- a/sys/boot/pc98/btx/btxldr/Makefile
+++ b/sys/boot/pc98/btx/btxldr/Makefile
@@ -18,4 +18,3 @@ LDFLAGS=-e start -Ttext ${LOADER_ADDRESS} -Wl,-N,-S,--oformat,binary
# XXX: clang integrated-as doesn't grok .codeNN directives yet
CFLAGS.btxldr.S= ${CLANG_NO_IAS}
-CFLAGS+= ${CFLAGS.${.IMPSRC:T}}
diff --git a/sys/boot/pc98/cdboot/Makefile b/sys/boot/pc98/cdboot/Makefile
index 23543d4..3b91c12 100644
--- a/sys/boot/pc98/cdboot/Makefile
+++ b/sys/boot/pc98/cdboot/Makefile
@@ -16,4 +16,3 @@ LDFLAGS=-e start -Ttext ${ORG} -Wl,-N,-S,--oformat,binary
# XXX: clang integrated-as doesn't grok .codeNN directives yet
CFLAGS.cdboot.S= ${CLANG_NO_IAS}
-CFLAGS+= ${CFLAGS.${.IMPSRC:T}}
diff --git a/sys/boot/zfs/libzfs.h b/sys/boot/zfs/libzfs.h
index ee64d1c..58bfd26 100644
--- a/sys/boot/zfs/libzfs.h
+++ b/sys/boot/zfs/libzfs.h
@@ -55,6 +55,7 @@ struct zfs_boot_args
uint64_t root;
uint64_t primary_pool;
uint64_t primary_vdev;
+ char gelipw[256];
};
int zfs_parsedev(struct zfs_devdesc *dev, const char *devspec,
diff --git a/sys/cam/ata/ata_da.c b/sys/cam/ata/ata_da.c
index 6ea25c2..38cf46e 100644
--- a/sys/cam/ata/ata_da.c
+++ b/sys/cam/ata/ata_da.c
@@ -466,14 +466,6 @@ static struct ada_quirk_entry ada_quirk_table[] =
},
{
/*
- * Samsung 843T Series SSDs
- * 4k optimised
- */
- { T_DIRECT, SIP_MEDIA_FIXED, "*", "SAMSUNG MZ7WD*", "*" },
- /*quirks*/ADA_Q_4K
- },
- {
- /*
* Samsung 850 SSDs
* 4k optimised
*/
@@ -482,10 +474,13 @@ static struct ada_quirk_entry ada_quirk_table[] =
},
{
/*
- * Samsung PM853T Series SSDs
+ * Samsung 843T Series SSDs (MZ7WD*)
+ * Samsung PM851 Series SSDs (MZ7TE*)
+ * Samsung PM853T Series SSDs (MZ7GE*)
+ * Samsung SM863 Series SSDs (MZ7KM*)
* 4k optimised
*/
- { T_DIRECT, SIP_MEDIA_FIXED, "*", "SAMSUNG MZ7GE*", "*" },
+ { T_DIRECT, SIP_MEDIA_FIXED, "*", "SAMSUNG MZ7*", "*" },
/*quirks*/ADA_Q_4K
},
{
diff --git a/sys/cam/cam_ccb.h b/sys/cam/cam_ccb.h
index 4e1e6a2..28415ed 100644
--- a/sys/cam/cam_ccb.h
+++ b/sys/cam/cam_ccb.h
@@ -725,6 +725,13 @@ struct ccb_scsiio {
u_int init_id; /* initiator id of who selected */
};
+static __inline uint8_t *
+scsiio_cdb_ptr(struct ccb_scsiio *ccb)
+{
+ return ((ccb->ccb_h.flags & CAM_CDB_POINTER) ?
+ ccb->cdb_io.cdb_ptr : ccb->cdb_io.cdb_bytes);
+}
+
/*
* ATA I/O Request CCB used for the XPT_ATA_IO function code.
*/
diff --git a/sys/cam/scsi/scsi_ch.c b/sys/cam/scsi/scsi_ch.c
index 137128d..8e069db 100644
--- a/sys/cam/scsi/scsi_ch.c
+++ b/sys/cam/scsi/scsi_ch.c
@@ -651,6 +651,7 @@ chdone(struct cam_periph *periph, union ccb *done_ccb)
} else {
int error;
+ announce_buf[0] = '\0';
error = cherror(done_ccb, CAM_RETRY_SELTO,
SF_RETRY_UA | SF_NO_PRINT);
/*
@@ -659,7 +660,7 @@ chdone(struct cam_periph *periph, union ccb *done_ccb)
*/
if (error == ERESTART) {
/*
- * A retry was scheuled, so
+ * A retry was scheduled, so
* just return.
*/
return;
diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
index 9d39182..07a6435 100644
--- a/sys/cam/scsi/scsi_da.c
+++ b/sys/cam/scsi/scsi_da.c
@@ -1138,14 +1138,6 @@ static struct da_quirk_entry da_quirk_table[] =
},
{
/*
- * Samsung 843T Series SSDs
- * 4k optimised
- */
- { T_DIRECT, SIP_MEDIA_FIXED, "ATA", "SAMSUNG MZ7WD*", "*" },
- /*quirks*/DA_Q_4K
- },
- {
- /*
* Samsung 850 SSDs
* 4k optimised & trim only works in 4k requests + 4k aligned
*/
@@ -1154,10 +1146,13 @@ static struct da_quirk_entry da_quirk_table[] =
},
{
/*
- * Samsung PM853T Series SSDs
+ * Samsung 843T Series SSDs (MZ7WD*)
+ * Samsung PM851 Series SSDs (MZ7TE*)
+ * Samsung PM853T Series SSDs (MZ7GE*)
+ * Samsung SM863 Series SSDs (MZ7KM*)
* 4k optimised
*/
- { T_DIRECT, SIP_MEDIA_FIXED, "ATA", "SAMSUNG MZ7GE*", "*" },
+ { T_DIRECT, SIP_MEDIA_FIXED, "ATA", "SAMSUNG MZ7*", "*" },
/*quirks*/DA_Q_4K
},
{
diff --git a/sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c b/sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c
index a2532f8..49becbc 100644
--- a/sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c
+++ b/sys/cddl/compat/opensolaris/kern/opensolaris_vfs.c
@@ -196,6 +196,7 @@ mount_snapshot(kthread_t *td, vnode_t **vpp, const char *fstype, char *fspath,
VI_UNLOCK(vp);
vrele(vp);
vfs_unbusy(mp);
+ vfs_freeopts(mp->mnt_optnew);
vfs_mount_destroy(mp);
*vpp = NULL;
return (error);
diff --git a/sys/cddl/compat/opensolaris/sys/vfs.h b/sys/cddl/compat/opensolaris/sys/vfs.h
index e1e49ed..c6e21cc 100644
--- a/sys/cddl/compat/opensolaris/sys/vfs.h
+++ b/sys/cddl/compat/opensolaris/sys/vfs.h
@@ -54,17 +54,6 @@ typedef struct mount vfs_t;
#define VFS_NOSETUID MNT_NOSUID
#define VFS_NOEXEC MNT_NOEXEC
-#define VFS_HOLD(vfsp) do { \
- MNT_ILOCK(vfsp); \
- MNT_REF(vfsp); \
- MNT_IUNLOCK(vfsp); \
-} while (0)
-#define VFS_RELE(vfsp) do { \
- MNT_ILOCK(vfsp); \
- MNT_REL(vfsp); \
- MNT_IUNLOCK(vfsp); \
-} while (0)
-
#define fs_vscan(vp, cr, async) (0)
#define VROOT VV_ROOT
diff --git a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
index d3bce0e..7ec7dfd 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
@@ -246,10 +246,6 @@ static int dtrace_dynvar_failclean; /* dynvars failed to clean */
#ifndef illumos
static struct mtx dtrace_unr_mtx;
MTX_SYSINIT(dtrace_unr_mtx, &dtrace_unr_mtx, "Unique resource identifier", MTX_DEF);
-int dtrace_in_probe; /* non-zero if executing a probe */
-#if defined(__i386__) || defined(__amd64__) || defined(__mips__) || defined(__powerpc__)
-uintptr_t dtrace_in_probe_addr; /* Address of invop when already in probe */
-#endif
static eventhandler_tag dtrace_kld_load_tag;
static eventhandler_tag dtrace_kld_unload_try_tag;
#endif
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/gfs.c b/sys/cddl/contrib/opensolaris/uts/common/fs/gfs.c
index 89882f4..c5c5c00 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/gfs.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/gfs.c
@@ -589,7 +589,9 @@ gfs_root_create(size_t size, vfs_t *vfsp, vnodeops_t *ops, ino64_t ino,
{
vnode_t *vp;
+#ifdef illumos
VFS_HOLD(vfsp);
+#endif
vp = gfs_dir_create(size, NULL, vfsp, ops, entries, inode_cb,
maxlen, readdir_cb, lookup_cb);
/* Manually set the inode */
@@ -700,7 +702,9 @@ found:
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
} else {
ASSERT(vp->v_vfsp != NULL);
+#ifdef illumos
VFS_RELE(vp->v_vfsp);
+#endif
}
#ifdef TODO
if (vp->v_flag & V_XATTRDIR)
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
index 188810b..9e8d86e 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c
@@ -107,6 +107,19 @@ dump_bytes(dmu_sendarg_t *dsp, void *buf, int len)
dsl_dataset_t *ds = dmu_objset_ds(dsp->dsa_os);
struct uio auio;
struct iovec aiov;
+
+ /*
+ * The code does not rely on this (len being a multiple of 8). We keep
+ * this assertion because of the corresponding assertion in
+ * receive_read(). Keeping this assertion ensures that we do not
+ * inadvertently break backwards compatibility (causing the assertion
+ * in receive_read() to trigger on old software).
+ *
+ * Removing the assertions could be rolled into a new feature that uses
+ * data that isn't 8-byte aligned; if the assertions were removed, a
+ * feature flag would have to be added.
+ */
+
ASSERT0(len % 8);
aiov.iov_base = buf;
@@ -1824,7 +1837,10 @@ receive_read(struct receive_arg *ra, int len, void *buf)
{
int done = 0;
- /* some things will require 8-byte alignment, so everything must */
+ /*
+ * The code doesn't rely on this (lengths being multiples of 8). See
+ * comment in dump_bytes.
+ */
ASSERT0(len % 8);
while (done < len) {
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_prop.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_prop.c
index 12e2771..8586cb6 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_prop.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_prop.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
+ * Copyright 2015, Joyent, Inc.
*/
#include <sys/zfs_context.h>
@@ -41,16 +42,14 @@
#define ZPROP_RECVD_SUFFIX "$recvd"
static int
-dodefault(const char *propname, int intsz, int numints, void *buf)
+dodefault(zfs_prop_t prop, int intsz, int numints, void *buf)
{
- zfs_prop_t prop;
-
/*
* The setonce properties are read-only, BUT they still
* have a default value that can be used as the initial
* value.
*/
- if ((prop = zfs_name_to_prop(propname)) == ZPROP_INVAL ||
+ if (prop == ZPROP_INVAL ||
(zfs_prop_readonly(prop) && !zfs_prop_setonce(prop)))
return (SET_ERROR(ENOENT));
@@ -148,7 +147,7 @@ dsl_prop_get_dd(dsl_dir_t *dd, const char *propname,
}
if (err == ENOENT)
- err = dodefault(propname, intsz, numints, buf);
+ err = dodefault(prop, intsz, numints, buf);
strfree(inheritstr);
strfree(recvdstr);
@@ -622,7 +621,7 @@ dsl_prop_set_sync_impl(dsl_dataset_t *ds, const char *propname,
int err;
uint64_t version = spa_version(ds->ds_dir->dd_pool->dp_spa);
- isint = (dodefault(propname, 8, 1, &intval) == 0);
+ isint = (dodefault(zfs_name_to_prop(propname), 8, 1, &intval) == 0);
if (ds->ds_is_snapshot) {
ASSERT(version >= SPA_VERSION_SNAP_PROPS);
@@ -1180,7 +1179,7 @@ dsl_prop_nvlist_add_uint64(nvlist_t *nv, zfs_prop_t prop, uint64_t value)
VERIFY(nvlist_alloc(&propval, NV_UNIQUE_NAME, KM_SLEEP) == 0);
VERIFY(nvlist_add_uint64(propval, ZPROP_VALUE, value) == 0);
/* Indicate the default source if we can. */
- if (dodefault(propname, 8, 1, &default_value) == 0 &&
+ if (dodefault(prop, 8, 1, &default_value) == 0 &&
value == default_value) {
VERIFY(nvlist_add_string(propval, ZPROP_SOURCE, "") == 0);
}
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
index c24836e..430ed34 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
@@ -1443,7 +1443,14 @@ getzfsvfs(const char *dsname, zfsvfs_t **zfvp)
mutex_enter(&os->os_user_ptr_lock);
*zfvp = dmu_objset_get_user(os);
if (*zfvp) {
+#ifdef illumos
VFS_HOLD((*zfvp)->z_vfs);
+#else
+ if (vfs_busy((*zfvp)->z_vfs, 0) != 0) {
+ *zfvp = NULL;
+ error = SET_ERROR(ESRCH);
+ }
+#endif
} else {
error = SET_ERROR(ESRCH);
}
@@ -1487,7 +1494,11 @@ zfsvfs_rele(zfsvfs_t *zfsvfs, void *tag)
rrm_exit(&zfsvfs->z_teardown_lock, tag);
if (zfsvfs->z_vfs) {
+#ifdef illumos
VFS_RELE(zfsvfs->z_vfs);
+#else
+ vfs_unbusy(zfsvfs->z_vfs);
+#endif
} else {
dmu_objset_disown(zfsvfs->z_os, zfsvfs);
zfsvfs_free(zfsvfs);
@@ -3018,11 +3029,13 @@ zfs_get_vfs(const char *resource)
mtx_lock(&mountlist_mtx);
TAILQ_FOREACH(vfsp, &mountlist, mnt_list) {
if (strcmp(refstr_value(vfsp->vfs_resource), resource) == 0) {
- VFS_HOLD(vfsp);
+ if (vfs_busy(vfsp, MBF_MNTLSTLOCK) != 0)
+ vfsp = NULL;
break;
}
}
- mtx_unlock(&mountlist_mtx);
+ if (vfsp == NULL)
+ mtx_unlock(&mountlist_mtx);
return (vfsp);
}
@@ -3475,7 +3488,11 @@ zfs_unmount_snap(const char *snapname)
ASSERT(!dsl_pool_config_held(dmu_objset_pool(zfsvfs->z_os)));
err = vn_vfswlock(vfsp->vfs_vnodecovered);
+#ifdef illumos
VFS_RELE(vfsp);
+#else
+ vfs_unbusy(vfsp);
+#endif
if (err != 0)
return (SET_ERROR(err));
@@ -3721,7 +3738,11 @@ zfs_ioc_rollback(const char *fsname, nvlist_t *args, nvlist_t *outnvl)
resume_err = zfs_resume_fs(zfsvfs, fsname);
error = error ? error : resume_err;
}
+#ifdef illumos
VFS_RELE(zfsvfs->z_vfs);
+#else
+ vfs_unbusy(zfsvfs->z_vfs);
+#endif
} else {
error = dsl_dataset_rollback(fsname, NULL, outnvl);
}
@@ -4376,7 +4397,11 @@ zfs_ioc_recv(zfs_cmd_t *zc)
if (error == 0)
error = zfs_resume_fs(zfsvfs, tofs);
error = error ? error : end_err;
+#ifdef illumos
VFS_RELE(zfsvfs->z_vfs);
+#else
+ vfs_unbusy(zfsvfs->z_vfs);
+#endif
} else {
error = dmu_recv_end(&drc, NULL);
}
@@ -4925,7 +4950,11 @@ zfs_ioc_userspace_upgrade(zfs_cmd_t *zc)
}
if (error == 0)
error = dmu_objset_userspace_upgrade(zfsvfs->z_os);
+#ifdef illumos
VFS_RELE(zfsvfs->z_vfs);
+#else
+ vfs_unbusy(zfsvfs->z_vfs);
+#endif
} else {
/* XXX kind of reading contents without owning */
error = dmu_objset_hold(zc->zc_name, FTAG, &os);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
index 5c2b66d..96b1cec 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
@@ -5773,7 +5773,7 @@ zfs_getpages(struct vnode *vp, vm_page_t *m, int count, int *rbehind,
off_t startoff, endoff;
int i, error;
vm_pindex_t reqstart, reqend;
- int lsize, reqsize, size;
+ int lsize, size;
object = m[0]->object;
error = 0;
@@ -5797,7 +5797,7 @@ zfs_getpages(struct vnode *vp, vm_page_t *m, int count, int *rbehind,
}
PCPU_INC(cnt.v_vnodein);
- PCPU_ADD(cnt.v_vnodepgsin, reqsize);
+ PCPU_ADD(cnt.v_vnodepgsin, count);
lsize = PAGE_SIZE;
if (IDX_TO_OFF(mlast->pindex) + lsize > object->un_pager.vnp.vnp_size)
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
index 04f0b6c..964b453 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c
@@ -743,7 +743,9 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
if (vp->v_type != VFIFO)
VN_LOCK_ASHARE(vp);
+#ifdef illumos
VFS_HOLD(zfsvfs->z_vfs);
+#endif
return (zp);
}
@@ -1428,7 +1430,9 @@ zfs_znode_free(znode_t *zp)
kmem_cache_free(znode_cache, zp);
+#ifdef illumos
VFS_RELE(zfsvfs->z_vfs);
+#endif
}
void
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c
index 25fba19..05e16ba 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c
@@ -2775,10 +2775,19 @@ zio_vdev_io_start(zio_t *zio)
(void) atomic_cas_64(&spa->spa_last_io, old, new);
}
+#ifdef illumos
align = 1ULL << vd->vdev_top->vdev_ashift;
if (!(zio->io_flags & ZIO_FLAG_PHYSICAL) &&
P2PHASE(zio->io_size, align) != 0) {
+#else
+ if (zio->io_flags & ZIO_FLAG_PHYSICAL)
+ align = 1ULL << vd->vdev_top->vdev_logical_ashift;
+ else
+ align = 1ULL << vd->vdev_top->vdev_ashift;
+
+ if (P2PHASE(zio->io_size, align) != 0) {
+#endif
/* Transform logical writes to be a full physical block size. */
uint64_t asize = P2ROUNDUP(zio->io_size, align);
char *abuf = NULL;
@@ -2794,6 +2803,7 @@ zio_vdev_io_start(zio_t *zio)
zio_subblock);
}
+#ifdef illumos
/*
* If this is not a physical io, make sure that it is properly aligned
* before proceeding.
@@ -2809,6 +2819,10 @@ zio_vdev_io_start(zio_t *zio)
ASSERT0(P2PHASE(zio->io_offset, SPA_MINBLOCKSIZE));
ASSERT0(P2PHASE(zio->io_size, SPA_MINBLOCKSIZE));
}
+#else
+ ASSERT0(P2PHASE(zio->io_offset, align));
+ ASSERT0(P2PHASE(zio->io_size, align));
+#endif
VERIFY(zio->io_type == ZIO_TYPE_READ || spa_writeable(spa));
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
index 0c3cfce..d0c7a74 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
@@ -589,7 +589,6 @@ zvol_create_minor(const char *name)
minor_t minor = 0;
char chrbuf[30], blkbuf[30];
#else
- struct cdev *dev;
struct g_provider *pp;
struct g_geom *gp;
uint64_t volsize, mode;
@@ -688,17 +687,25 @@ zvol_create_minor(const char *name)
bioq_init(&zv->zv_queue);
mtx_init(&zv->zv_queue_mtx, "zvol", NULL, MTX_DEF);
} else if (zv->zv_volmode == ZFS_VOLMODE_DEV) {
- if (make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK,
- &dev, &zvol_cdevsw, NULL, UID_ROOT, GID_OPERATOR,
- 0640, "%s/%s", ZVOL_DRIVER, name) != 0) {
+ struct make_dev_args args;
+
+ make_dev_args_init(&args);
+ args.mda_flags = MAKEDEV_CHECKNAME | MAKEDEV_WAITOK;
+ args.mda_devsw = &zvol_cdevsw;
+ args.mda_cr = NULL;
+ args.mda_uid = UID_ROOT;
+ args.mda_gid = GID_OPERATOR;
+ args.mda_mode = 0640;
+ args.mda_si_drv2 = zv;
+ error = make_dev_s(&args, &zv->zv_dev,
+ "%s/%s", ZVOL_DRIVER, name);
+ if (error != 0) {
kmem_free(zv, sizeof(*zv));
dmu_objset_disown(os, FTAG);
mutex_exit(&zfsdev_state_lock);
- return (SET_ERROR(ENXIO));
+ return (error);
}
- zv->zv_dev = dev;
- dev->si_iosize_max = MAXPHYS;
- dev->si_drv2 = zv;
+ zv->zv_dev->si_iosize_max = MAXPHYS;
}
LIST_INSERT_HEAD(&all_zvols, zv, zv_links);
#endif /* illumos */
@@ -2854,7 +2861,8 @@ zvol_create_snapshots(objset_t *os, const char *name)
break;
}
- if ((error = zvol_create_minor(sname)) != 0) {
+ error = zvol_create_minor(sname);
+ if (error != 0 && error != EEXIST) {
printf("ZFS WARNING: Unable to create ZVOL %s (error=%d).\n",
sname, error);
break;
@@ -2963,18 +2971,29 @@ zvol_rename_minor(zvol_state_t *zv, const char *newname)
g_error_provider(pp, 0);
g_topology_unlock();
} else if (zv->zv_volmode == ZFS_VOLMODE_DEV) {
+ struct make_dev_args args;
+
dev = zv->zv_dev;
ASSERT(dev != NULL);
zv->zv_dev = NULL;
destroy_dev(dev);
-
- if (make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK,
- &dev, &zvol_cdevsw, NULL, UID_ROOT, GID_OPERATOR,
- 0640, "%s/%s", ZVOL_DRIVER, newname) == 0) {
- zv->zv_dev = dev;
- dev->si_iosize_max = MAXPHYS;
- dev->si_drv2 = zv;
+ if (zv->zv_total_opens > 0) {
+ zv->zv_flags &= ~ZVOL_EXCL;
+ zv->zv_total_opens = 0;
+ zvol_last_close(zv);
}
+
+ make_dev_args_init(&args);
+ args.mda_flags = MAKEDEV_CHECKNAME | MAKEDEV_WAITOK;
+ args.mda_devsw = &zvol_cdevsw;
+ args.mda_cr = NULL;
+ args.mda_uid = UID_ROOT;
+ args.mda_gid = GID_OPERATOR;
+ args.mda_mode = 0640;
+ args.mda_si_drv2 = zv;
+ if (make_dev_s(&args, &zv->zv_dev,
+ "%s/%s", ZVOL_DRIVER, newname) == 0)
+ zv->zv_dev->si_iosize_max = MAXPHYS;
}
strlcpy(zv->zv_name, newname, sizeof(zv->zv_name));
}
@@ -3021,16 +3040,10 @@ zvol_rename_minors(const char *oldname, const char *newname)
static int
zvol_d_open(struct cdev *dev, int flags, int fmt, struct thread *td)
{
- zvol_state_t *zv;
+ zvol_state_t *zv = dev->si_drv2;
int err = 0;
mutex_enter(&zfsdev_state_lock);
- zv = dev->si_drv2;
- if (zv == NULL) {
- mutex_exit(&zfsdev_state_lock);
- return(ENXIO); /* zvol_create_minor() not done yet */
- }
-
if (zv->zv_total_opens == 0)
err = zvol_first_open(zv);
if (err) {
@@ -3068,16 +3081,9 @@ out:
static int
zvol_d_close(struct cdev *dev, int flags, int fmt, struct thread *td)
{
- zvol_state_t *zv;
- int err = 0;
+ zvol_state_t *zv = dev->si_drv2;
mutex_enter(&zfsdev_state_lock);
- zv = dev->si_drv2;
- if (zv == NULL) {
- mutex_exit(&zfsdev_state_lock);
- return(ENXIO);
- }
-
if (zv->zv_flags & ZVOL_EXCL) {
ASSERT(zv->zv_total_opens == 1);
zv->zv_flags &= ~ZVOL_EXCL;
diff --git a/sys/cddl/dev/dtrace/aarch64/dtrace_subr.c b/sys/cddl/dev/dtrace/aarch64/dtrace_subr.c
index 9cf5bc4..78b5637 100644
--- a/sys/cddl/dev/dtrace/aarch64/dtrace_subr.c
+++ b/sys/cddl/dev/dtrace/aarch64/dtrace_subr.c
@@ -45,8 +45,6 @@ __FBSDID("$FreeBSD$");
#include <machine/trap.h>
#include <vm/pmap.h>
-extern uintptr_t dtrace_in_probe_addr;
-extern int dtrace_in_probe;
extern dtrace_id_t dtrace_probeid_error;
extern int (*dtrace_invop_jump_addr)(struct trapframe *);
extern void dtrace_getnanotime(struct timespec *tsp);
diff --git a/sys/cddl/dev/dtrace/amd64/dtrace_subr.c b/sys/cddl/dev/dtrace/amd64/dtrace_subr.c
index 7f2ec7e..f6577d5 100644
--- a/sys/cddl/dev/dtrace/amd64/dtrace_subr.c
+++ b/sys/cddl/dev/dtrace/amd64/dtrace_subr.c
@@ -44,9 +44,6 @@
#include <machine/frame.h>
#include <vm/pmap.h>
-extern uintptr_t dtrace_in_probe_addr;
-extern int dtrace_in_probe;
-
extern void dtrace_getnanotime(struct timespec *tsp);
int dtrace_invop(uintptr_t, uintptr_t *, uintptr_t);
diff --git a/sys/cddl/dev/dtrace/arm/dtrace_subr.c b/sys/cddl/dev/dtrace/arm/dtrace_subr.c
index 2aea13e..44dde29 100644
--- a/sys/cddl/dev/dtrace/arm/dtrace_subr.c
+++ b/sys/cddl/dev/dtrace/arm/dtrace_subr.c
@@ -51,8 +51,6 @@ __FBSDID("$FreeBSD$");
#define BIT_LR 14
#define BIT_SP 13
-extern uintptr_t dtrace_in_probe_addr;
-extern int dtrace_in_probe;
extern dtrace_id_t dtrace_probeid_error;
extern int (*dtrace_invop_jump_addr)(struct trapframe *);
extern void dtrace_getnanotime(struct timespec *tsp);
diff --git a/sys/cddl/dev/dtrace/i386/dtrace_subr.c b/sys/cddl/dev/dtrace/i386/dtrace_subr.c
index 814019e..be5bd4b 100644
--- a/sys/cddl/dev/dtrace/i386/dtrace_subr.c
+++ b/sys/cddl/dev/dtrace/i386/dtrace_subr.c
@@ -46,8 +46,6 @@
#include <vm/pmap.h>
extern uintptr_t kernelbase;
-extern uintptr_t dtrace_in_probe_addr;
-extern int dtrace_in_probe;
extern void dtrace_getnanotime(struct timespec *tsp);
diff --git a/sys/cddl/dev/dtrace/mips/dtrace_subr.c b/sys/cddl/dev/dtrace/mips/dtrace_subr.c
index 4f13b98..a2aa8c7 100644
--- a/sys/cddl/dev/dtrace/mips/dtrace_subr.c
+++ b/sys/cddl/dev/dtrace/mips/dtrace_subr.c
@@ -46,8 +46,6 @@ __FBSDID("$FreeBSD$");
#define DELAYBRANCH(x) ((int)(x) < 0)
-extern uintptr_t dtrace_in_probe_addr;
-extern int dtrace_in_probe;
extern dtrace_id_t dtrace_probeid_error;
int dtrace_invop(uintptr_t, uintptr_t *, uintptr_t);
diff --git a/sys/cddl/dev/dtrace/powerpc/dtrace_subr.c b/sys/cddl/dev/dtrace/powerpc/dtrace_subr.c
index c0360fd..33b9e71 100644
--- a/sys/cddl/dev/dtrace/powerpc/dtrace_subr.c
+++ b/sys/cddl/dev/dtrace/powerpc/dtrace_subr.c
@@ -46,8 +46,6 @@ __FBSDID("$FreeBSD$");
#define DELAYBRANCH(x) ((int)(x) < 0)
-extern uintptr_t dtrace_in_probe_addr;
-extern int dtrace_in_probe;
extern dtrace_id_t dtrace_probeid_error;
extern int (*dtrace_invop_jump_addr)(struct trapframe *);
diff --git a/sys/compat/cloudabi/cloudabi_clock.c b/sys/compat/cloudabi/cloudabi_clock.c
index ed32cf6..b26d98e 100644
--- a/sys/compat/cloudabi/cloudabi_clock.c
+++ b/sys/compat/cloudabi/cloudabi_clock.c
@@ -31,8 +31,9 @@ __FBSDID("$FreeBSD$");
#include <sys/stdint.h>
#include <sys/syscallsubr.h>
+#include <contrib/cloudabi/cloudabi_types_common.h>
+
#include <compat/cloudabi/cloudabi_proto.h>
-#include <compat/cloudabi/cloudabi_syscalldefs.h>
#include <compat/cloudabi/cloudabi_util.h>
/* Converts a CloudABI clock ID to a FreeBSD clock ID. */
diff --git a/sys/compat/cloudabi/cloudabi_errno.c b/sys/compat/cloudabi/cloudabi_errno.c
index 5193cfc..38520b9 100644
--- a/sys/compat/cloudabi/cloudabi_errno.c
+++ b/sys/compat/cloudabi/cloudabi_errno.c
@@ -28,7 +28,8 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
-#include <compat/cloudabi/cloudabi_syscalldefs.h>
+#include <contrib/cloudabi/cloudabi_types_common.h>
+
#include <compat/cloudabi/cloudabi_util.h>
/* Converts a FreeBSD errno to a CloudABI errno. */
diff --git a/sys/compat/cloudabi/cloudabi_fd.c b/sys/compat/cloudabi/cloudabi_fd.c
index 17177d2..c044adc 100644
--- a/sys/compat/cloudabi/cloudabi_fd.c
+++ b/sys/compat/cloudabi/cloudabi_fd.c
@@ -38,8 +38,9 @@ __FBSDID("$FreeBSD$");
#include <sys/unistd.h>
#include <sys/vnode.h>
+#include <contrib/cloudabi/cloudabi_types_common.h>
+
#include <compat/cloudabi/cloudabi_proto.h>
-#include <compat/cloudabi/cloudabi_syscalldefs.h>
#include <compat/cloudabi/cloudabi_util.h>
/* Translation between CloudABI and Capsicum rights. */
diff --git a/sys/compat/cloudabi/cloudabi_file.c b/sys/compat/cloudabi/cloudabi_file.c
index cdf0585..f48b754 100644
--- a/sys/compat/cloudabi/cloudabi_file.c
+++ b/sys/compat/cloudabi/cloudabi_file.c
@@ -39,8 +39,9 @@ __FBSDID("$FreeBSD$");
#include <sys/uio.h>
#include <sys/vnode.h>
+#include <contrib/cloudabi/cloudabi_types_common.h>
+
#include <compat/cloudabi/cloudabi_proto.h>
-#include <compat/cloudabi/cloudabi_syscalldefs.h>
#include <compat/cloudabi/cloudabi_util.h>
#include <security/mac/mac_framework.h>
@@ -185,8 +186,8 @@ cloudabi_sys_file_link(struct thread *td,
return (error);
}
- error = kern_linkat(td, uap->fd1, uap->fd2, path1, path2,
- UIO_SYSSPACE, (uap->fd1 & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0 ?
+ error = kern_linkat(td, uap->fd1.fd, uap->fd2, path1, path2,
+ UIO_SYSSPACE, (uap->fd1.flags & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) ?
FOLLOW : NOFOLLOW);
cloudabi_freestr(path1);
cloudabi_freestr(path2);
@@ -248,7 +249,7 @@ cloudabi_sys_file_open(struct thread *td,
fflags |= O_SYNC;
cap_rights_set(&rights, CAP_FSYNC);
}
- if ((uap->fd & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) == 0)
+ if ((uap->dirfd.flags & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) == 0)
fflags |= O_NOFOLLOW;
if (write && (fflags & (O_APPEND | O_TRUNC)) == 0)
cap_rights_set(&rights, CAP_SEEK);
@@ -265,7 +266,7 @@ cloudabi_sys_file_open(struct thread *td,
fdrop(fp, td);
return (error);
}
- NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, uap->fd,
+ NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, uap->dirfd.fd,
&rights, td);
error = vn_open(&nd, &fflags, 0777 & ~td->td_proc->p_fd->fd_cmask, fp);
cloudabi_freestr(path);
@@ -657,8 +658,8 @@ cloudabi_sys_file_stat_get(struct thread *td,
return (error);
error = kern_statat(td,
- (uap->fd & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0 ? 0 :
- AT_SYMLINK_NOFOLLOW, uap->fd, path, UIO_SYSSPACE, &sb, NULL);
+ (uap->fd.flags & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0 ? 0 :
+ AT_SYMLINK_NOFOLLOW, uap->fd.fd, path, UIO_SYSSPACE, &sb, NULL);
cloudabi_freestr(path);
if (error != 0)
return (error);
@@ -711,8 +712,8 @@ cloudabi_sys_file_stat_put(struct thread *td,
return (error);
convert_utimens_arguments(&fs, uap->flags, ts);
- error = kern_utimensat(td, uap->fd, path, UIO_SYSSPACE, ts,
- UIO_SYSSPACE, (uap->fd & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) != 0 ?
+ error = kern_utimensat(td, uap->fd.fd, path, UIO_SYSSPACE, ts,
+ UIO_SYSSPACE, (uap->fd.flags & CLOUDABI_LOOKUP_SYMLINK_FOLLOW) ?
0 : AT_SYMLINK_NOFOLLOW);
cloudabi_freestr(path);
return (error);
@@ -751,7 +752,7 @@ cloudabi_sys_file_unlink(struct thread *td,
if (error != 0)
return (error);
- if (uap->flag & CLOUDABI_UNLINK_REMOVEDIR)
+ if (uap->flags & CLOUDABI_UNLINK_REMOVEDIR)
error = kern_rmdirat(td, uap->fd, path, UIO_SYSSPACE);
else
error = kern_unlinkat(td, uap->fd, path, UIO_SYSSPACE, 0);
diff --git a/sys/compat/cloudabi/cloudabi_futex.c b/sys/compat/cloudabi/cloudabi_futex.c
index aec2f33..d12b331 100644
--- a/sys/compat/cloudabi/cloudabi_futex.c
+++ b/sys/compat/cloudabi/cloudabi_futex.c
@@ -37,8 +37,9 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/umtx.h>
+#include <contrib/cloudabi/cloudabi_types_common.h>
+
#include <compat/cloudabi/cloudabi_proto.h>
-#include <compat/cloudabi/cloudabi_syscalldefs.h>
#include <compat/cloudabi/cloudabi_util.h>
/*
@@ -211,16 +212,16 @@ static int futex_user_cmpxchg(uint32_t *, uint32_t, uint32_t *, uint32_t);
static int
futex_address_create(struct futex_address *fa, struct thread *td,
- const void *object, cloudabi_mflags_t scope)
+ const void *object, cloudabi_scope_t scope)
{
KASSERT(td == curthread,
("Can only create umtx keys for the current thread"));
switch (scope) {
- case CLOUDABI_MAP_PRIVATE:
+ case CLOUDABI_SCOPE_PRIVATE:
return (umtx_key_get(object, TYPE_FUTEX, THREAD_SHARE,
&fa->fa_key));
- case CLOUDABI_MAP_SHARED:
+ case CLOUDABI_SCOPE_SHARED:
return (umtx_key_get(object, TYPE_FUTEX, AUTO_SHARE,
&fa->fa_key));
default:
@@ -258,7 +259,7 @@ futex_condvar_assert(const struct futex_condvar *fc)
static int
futex_condvar_lookup(struct thread *td, const cloudabi_condvar_t *address,
- cloudabi_mflags_t scope, struct futex_condvar **fcret)
+ cloudabi_scope_t scope, struct futex_condvar **fcret)
{
struct futex_address fa_condvar;
struct futex_condvar *fc;
@@ -285,8 +286,8 @@ futex_condvar_lookup(struct thread *td, const cloudabi_condvar_t *address,
static int
futex_condvar_lookup_or_create(struct thread *td,
- const cloudabi_condvar_t *condvar, cloudabi_mflags_t condvar_scope,
- const cloudabi_lock_t *lock, cloudabi_mflags_t lock_scope,
+ const cloudabi_condvar_t *condvar, cloudabi_scope_t condvar_scope,
+ const cloudabi_lock_t *lock, cloudabi_scope_t lock_scope,
struct futex_condvar **fcret)
{
struct futex_address fa_condvar, fa_lock;
@@ -384,7 +385,7 @@ futex_lock_assert(const struct futex_lock *fl)
static int
futex_lock_lookup(struct thread *td, const cloudabi_lock_t *address,
- cloudabi_mflags_t scope, struct futex_lock **flret)
+ cloudabi_scope_t scope, struct futex_lock **flret)
{
struct futex_address fa;
int error;
@@ -973,8 +974,8 @@ futex_user_cmpxchg(uint32_t *obj, uint32_t cmp, uint32_t *old, uint32_t new)
int
cloudabi_futex_condvar_wait(struct thread *td, cloudabi_condvar_t *condvar,
- cloudabi_mflags_t condvar_scope, cloudabi_lock_t *lock,
- cloudabi_mflags_t lock_scope, cloudabi_clockid_t clock_id,
+ cloudabi_scope_t condvar_scope, cloudabi_lock_t *lock,
+ cloudabi_scope_t lock_scope, cloudabi_clockid_t clock_id,
cloudabi_timestamp_t timeout, cloudabi_timestamp_t precision)
{
struct futex_condvar *fc;
@@ -1046,7 +1047,7 @@ cloudabi_futex_condvar_wait(struct thread *td, cloudabi_condvar_t *condvar,
int
cloudabi_futex_lock_rdlock(struct thread *td, cloudabi_lock_t *lock,
- cloudabi_mflags_t scope, cloudabi_clockid_t clock_id,
+ cloudabi_scope_t scope, cloudabi_clockid_t clock_id,
cloudabi_timestamp_t timeout, cloudabi_timestamp_t precision)
{
struct futex_lock *fl;
@@ -1065,7 +1066,7 @@ cloudabi_futex_lock_rdlock(struct thread *td, cloudabi_lock_t *lock,
int
cloudabi_futex_lock_wrlock(struct thread *td, cloudabi_lock_t *lock,
- cloudabi_mflags_t scope, cloudabi_clockid_t clock_id,
+ cloudabi_scope_t scope, cloudabi_clockid_t clock_id,
cloudabi_timestamp_t timeout, cloudabi_timestamp_t precision)
{
struct futex_lock *fl;
diff --git a/sys/compat/cloudabi/cloudabi_mem.c b/sys/compat/cloudabi/cloudabi_mem.c
index 9d82673..34ee14a 100644
--- a/sys/compat/cloudabi/cloudabi_mem.c
+++ b/sys/compat/cloudabi/cloudabi_mem.c
@@ -30,8 +30,9 @@ __FBSDID("$FreeBSD$");
#include <sys/mman.h>
#include <sys/sysproto.h>
+#include <contrib/cloudabi/cloudabi_types_common.h>
+
#include <compat/cloudabi/cloudabi_proto.h>
-#include <compat/cloudabi/cloudabi_syscalldefs.h>
/* Converts CloudABI's memory protection flags to FreeBSD's. */
static int
diff --git a/sys/compat/cloudabi/cloudabi_proc.c b/sys/compat/cloudabi/cloudabi_proc.c
index 8d0b6e7..139af2c 100644
--- a/sys/compat/cloudabi/cloudabi_proc.c
+++ b/sys/compat/cloudabi/cloudabi_proc.c
@@ -38,8 +38,9 @@ __FBSDID("$FreeBSD$");
#include <sys/syscallsubr.h>
#include <sys/unistd.h>
+#include <contrib/cloudabi/cloudabi_types_common.h>
+
#include <compat/cloudabi/cloudabi_proto.h>
-#include <compat/cloudabi/cloudabi_syscalldefs.h>
int
cloudabi_sys_proc_exec(struct thread *td,
diff --git a/sys/compat/cloudabi/cloudabi_proto.h b/sys/compat/cloudabi/cloudabi_proto.h
index e4baffd..95271fd 100644
--- a/sys/compat/cloudabi/cloudabi_proto.h
+++ b/sys/compat/cloudabi/cloudabi_proto.h
@@ -30,5 +30,7 @@
* calls. Unfortunately, we don't have a separate system call table for
* those, so rely on the system call table from COMPAT_CLOUDABI64.
*/
-#include <compat/cloudabi64/cloudabi64_syscalldefs.h>
+
+#include <contrib/cloudabi/cloudabi64_types.h>
+
#include <compat/cloudabi64/cloudabi64_proto.h>
diff --git a/sys/compat/cloudabi/cloudabi_sock.c b/sys/compat/cloudabi/cloudabi_sock.c
index cdccdff..b66f0ab 100644
--- a/sys/compat/cloudabi/cloudabi_sock.c
+++ b/sys/compat/cloudabi/cloudabi_sock.c
@@ -43,8 +43,9 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
+#include <contrib/cloudabi/cloudabi_types_common.h>
+
#include <compat/cloudabi/cloudabi_proto.h>
-#include <compat/cloudabi/cloudabi_syscalldefs.h>
#include <compat/cloudabi/cloudabi_util.h>
/* Converts FreeBSD's struct sockaddr to CloudABI's cloudabi_sockaddr_t. */
@@ -117,12 +118,12 @@ cloudabi_sys_sock_accept(struct thread *td,
if (uap->buf == NULL) {
/* Only return the new file descriptor number. */
- return (kern_accept(td, uap->s, NULL, NULL, NULL));
+ return (kern_accept(td, uap->sock, NULL, NULL, NULL));
} else {
/* Also return properties of the new socket descriptor. */
sal = MAX(sizeof(struct sockaddr_in),
sizeof(struct sockaddr_in6));
- error = kern_accept(td, uap->s, (void *)&sa, &sal, NULL);
+ error = kern_accept(td, uap->sock, (void *)&sa, &sal, NULL);
if (error != 0)
return (error);
@@ -143,7 +144,7 @@ cloudabi_sys_sock_bind(struct thread *td,
error = copyin_sockaddr_un(uap->path, uap->pathlen, &sun);
if (error != 0)
return (error);
- return (kern_bindat(td, uap->fd, uap->s, (struct sockaddr *)&sun));
+ return (kern_bindat(td, uap->fd, uap->sock, (struct sockaddr *)&sun));
}
int
@@ -156,7 +157,8 @@ cloudabi_sys_sock_connect(struct thread *td,
error = copyin_sockaddr_un(uap->path, uap->pathlen, &sun);
if (error != 0)
return (error);
- return (kern_connectat(td, uap->fd, uap->s, (struct sockaddr *)&sun));
+ return (kern_connectat(td, uap->fd, uap->sock,
+ (struct sockaddr *)&sun));
}
int
@@ -164,7 +166,7 @@ cloudabi_sys_sock_listen(struct thread *td,
struct cloudabi_sys_sock_listen_args *uap)
{
struct listen_args listen_args = {
- .s = uap->s,
+ .s = uap->sock,
.backlog = uap->backlog,
};
@@ -176,7 +178,7 @@ cloudabi_sys_sock_shutdown(struct thread *td,
struct cloudabi_sys_sock_shutdown_args *uap)
{
struct shutdown_args shutdown_args = {
- .s = uap->fd,
+ .s = uap->sock,
};
switch (uap->how) {
@@ -207,7 +209,7 @@ cloudabi_sys_sock_stat_get(struct thread *td,
struct socket *so;
int error;
- error = getsock_cap(td, uap->fd, cap_rights_init(&rights,
+ error = getsock_cap(td, uap->sock, cap_rights_init(&rights,
CAP_GETSOCKOPT, CAP_GETPEERNAME, CAP_GETSOCKNAME), &fp, NULL);
if (error != 0)
return (error);
@@ -243,7 +245,7 @@ cloudabi_sys_sock_stat_get(struct thread *td,
/* Set ss_state. */
if ((so->so_options & SO_ACCEPTCONN) != 0)
- ss.ss_state |= CLOUDABI_SOCKSTAT_ACCEPTCONN;
+ ss.ss_state |= CLOUDABI_SOCKSTATE_ACCEPTCONN;
fdrop(fp, td);
return (copyout(&ss, uap->buf, sizeof(ss)));
diff --git a/sys/compat/cloudabi/cloudabi_thread.c b/sys/compat/cloudabi/cloudabi_thread.c
index 8aee708..37dc794 100644
--- a/sys/compat/cloudabi/cloudabi_thread.c
+++ b/sys/compat/cloudabi/cloudabi_thread.c
@@ -31,8 +31,9 @@ __FBSDID("$FreeBSD$");
#include <sys/sched.h>
#include <sys/syscallsubr.h>
+#include <contrib/cloudabi/cloudabi_types_common.h>
+
#include <compat/cloudabi/cloudabi_proto.h>
-#include <compat/cloudabi/cloudabi_syscalldefs.h>
int
cloudabi_sys_thread_exit(struct thread *td,
diff --git a/sys/compat/cloudabi/cloudabi_util.h b/sys/compat/cloudabi/cloudabi_util.h
index 10da229..c0a02aa 100644
--- a/sys/compat/cloudabi/cloudabi_util.h
+++ b/sys/compat/cloudabi/cloudabi_util.h
@@ -30,7 +30,7 @@
#include <sys/socket.h>
-#include <compat/cloudabi/cloudabi_syscalldefs.h>
+#include <contrib/cloudabi/cloudabi_types_common.h>
struct file;
struct thread;
@@ -67,13 +67,13 @@ int cloudabi_convert_timespec(const struct timespec *, cloudabi_timestamp_t *);
* sleep on a lock or condition variable.
*/
int cloudabi_futex_condvar_wait(struct thread *, cloudabi_condvar_t *,
- cloudabi_mflags_t, cloudabi_lock_t *, cloudabi_mflags_t, cloudabi_clockid_t,
+ cloudabi_scope_t, cloudabi_lock_t *, cloudabi_scope_t, cloudabi_clockid_t,
cloudabi_timestamp_t, cloudabi_timestamp_t);
int cloudabi_futex_lock_rdlock(struct thread *, cloudabi_lock_t *,
- cloudabi_mflags_t, cloudabi_clockid_t, cloudabi_timestamp_t,
+ cloudabi_scope_t, cloudabi_clockid_t, cloudabi_timestamp_t,
cloudabi_timestamp_t);
int cloudabi_futex_lock_wrlock(struct thread *, cloudabi_lock_t *,
- cloudabi_mflags_t, cloudabi_clockid_t, cloudabi_timestamp_t,
+ cloudabi_scope_t, cloudabi_clockid_t, cloudabi_timestamp_t,
cloudabi_timestamp_t);
#endif
diff --git a/sys/compat/cloudabi64/Makefile b/sys/compat/cloudabi64/Makefile
index 3fbef57..83d27a3 100644
--- a/sys/compat/cloudabi64/Makefile
+++ b/sys/compat/cloudabi64/Makefile
@@ -8,5 +8,7 @@ sysent: cloudabi64_sysent.c cloudabi64_syscall.h cloudabi64_proto.h \
cloudabi64_sysent.c cloudabi64_syscall.h cloudabi64_proto.h \
cloudabi64_syscalls.c cloudabi64_systrace_args.c: \
- ../../kern/makesyscalls.sh syscalls.master syscalls.conf
- sh ../../kern/makesyscalls.sh syscalls.master syscalls.conf
+ ../../kern/makesyscalls.sh ../../contrib/cloudabi/syscalls.master \
+ syscalls.conf
+ sh ../../kern/makesyscalls.sh ../../contrib/cloudabi/syscalls.master \
+ syscalls.conf
diff --git a/sys/compat/cloudabi64/cloudabi64_fd.c b/sys/compat/cloudabi64/cloudabi64_fd.c
index b2fd67d..7d0c69a 100644
--- a/sys/compat/cloudabi64/cloudabi64_fd.c
+++ b/sys/compat/cloudabi64/cloudabi64_fd.c
@@ -34,7 +34,8 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/uio.h>
-#include <compat/cloudabi64/cloudabi64_syscalldefs.h>
+#include <contrib/cloudabi/cloudabi64_types.h>
+
#include <compat/cloudabi64/cloudabi64_proto.h>
/* Copies in 64-bit iovec structures from userspace. */
diff --git a/sys/compat/cloudabi64/cloudabi64_module.c b/sys/compat/cloudabi64/cloudabi64_module.c
index ca8ecf4..de890bc 100644
--- a/sys/compat/cloudabi64/cloudabi64_module.c
+++ b/sys/compat/cloudabi64/cloudabi64_module.c
@@ -36,7 +36,8 @@ __FBSDID("$FreeBSD$");
#include <sys/sysent.h>
#include <sys/systm.h>
-#include <compat/cloudabi64/cloudabi64_syscalldefs.h>
+#include <contrib/cloudabi/cloudabi64_types.h>
+
#include <compat/cloudabi64/cloudabi64_util.h>
register_t *
@@ -98,6 +99,7 @@ cloudabi64_fixup(register_t **stack_base, struct image_params *imgp)
#define PTR(type, ptr) { .a_type = (type), .a_ptr = (uintptr_t)(ptr) }
PTR(CLOUDABI_AT_ARGDATA, argdata),
VAL(CLOUDABI_AT_ARGDATALEN, argdatalen),
+ VAL(CLOUDABI_AT_BASE, args->base),
PTR(CLOUDABI_AT_CANARY, canary),
VAL(CLOUDABI_AT_CANARYLEN, sizeof(canarybuf)),
VAL(CLOUDABI_AT_NCPUS, mp_ncpus),
diff --git a/sys/compat/cloudabi64/cloudabi64_poll.c b/sys/compat/cloudabi64/cloudabi64_poll.c
index c8f1811..e44d69f 100644
--- a/sys/compat/cloudabi64/cloudabi64_poll.c
+++ b/sys/compat/cloudabi64/cloudabi64_poll.c
@@ -30,9 +30,10 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/syscallsubr.h>
+#include <contrib/cloudabi/cloudabi64_types.h>
+
#include <compat/cloudabi/cloudabi_util.h>
-#include <compat/cloudabi64/cloudabi64_syscalldefs.h>
#include <compat/cloudabi64/cloudabi64_proto.h>
/* Converts a FreeBSD signal number to a CloudABI signal number. */
@@ -248,7 +249,7 @@ cloudabi64_sys_poll(struct thread *td, struct cloudabi64_sys_poll_args *uap)
* Bandaid to support CloudABI futex constructs that are not
* implemented through FreeBSD's kqueue().
*/
- if (uap->nevents == 1) {
+ if (uap->nsubscriptions == 1) {
cloudabi64_subscription_t sub;
cloudabi64_event_t ev = {};
int error;
@@ -291,7 +292,7 @@ cloudabi64_sys_poll(struct thread *td, struct cloudabi64_sys_poll_args *uap)
td->td_retval[0] = 1;
return (copyout(&ev, uap->out, sizeof(ev)));
}
- } else if (uap->nevents == 2) {
+ } else if (uap->nsubscriptions == 2) {
cloudabi64_subscription_t sub[2];
cloudabi64_event_t ev[2] = {};
int error;
@@ -365,7 +366,7 @@ cloudabi64_sys_poll(struct thread *td, struct cloudabi64_sys_poll_args *uap)
}
}
- return (kern_kevent_anonymous(td, uap->nevents, &copyops));
+ return (kern_kevent_anonymous(td, uap->nsubscriptions, &copyops));
}
int
diff --git a/sys/compat/cloudabi64/cloudabi64_proto.h b/sys/compat/cloudabi64/cloudabi64_proto.h
index 8c65fe3..79a0f60 100644
--- a/sys/compat/cloudabi64/cloudabi64_proto.h
+++ b/sys/compat/cloudabi64/cloudabi64_proto.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/compat/cloudabi64/syscalls.master 286318 2015-08-05 13:09:46Z ed
+ * created from FreeBSD: head/sys/contrib/cloudabi/syscalls.master 297468 2016-03-31 18:50:06Z ed
*/
#ifndef _CLOUDABI64_SYSPROTO_H_
@@ -43,7 +43,7 @@ struct cloudabi_sys_clock_time_get_args {
};
struct cloudabi_sys_condvar_signal_args {
char condvar_l_[PADL_(cloudabi_condvar_t *)]; cloudabi_condvar_t * condvar; char condvar_r_[PADR_(cloudabi_condvar_t *)];
- char scope_l_[PADL_(cloudabi_mflags_t)]; cloudabi_mflags_t scope; char scope_r_[PADR_(cloudabi_mflags_t)];
+ char scope_l_[PADL_(cloudabi_scope_t)]; cloudabi_scope_t scope; char scope_r_[PADR_(cloudabi_scope_t)];
char nwaiters_l_[PADL_(cloudabi_nthreads_t)]; cloudabi_nthreads_t nwaiters; char nwaiters_r_[PADR_(cloudabi_nthreads_t)];
};
struct cloudabi_sys_fd_close_args {
@@ -64,19 +64,19 @@ struct cloudabi_sys_fd_dup_args {
struct cloudabi64_sys_fd_pread_args {
char fd_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t fd; char fd_r_[PADR_(cloudabi_fd_t)];
char iov_l_[PADL_(const cloudabi64_iovec_t *)]; const cloudabi64_iovec_t * iov; char iov_r_[PADR_(const cloudabi64_iovec_t *)];
- char iovcnt_l_[PADL_(cloudabi64_size_t)]; cloudabi64_size_t iovcnt; char iovcnt_r_[PADR_(cloudabi64_size_t)];
+ char iovcnt_l_[PADL_(size_t)]; size_t iovcnt; char iovcnt_r_[PADR_(size_t)];
char offset_l_[PADL_(cloudabi_filesize_t)]; cloudabi_filesize_t offset; char offset_r_[PADR_(cloudabi_filesize_t)];
};
struct cloudabi64_sys_fd_pwrite_args {
char fd_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t fd; char fd_r_[PADR_(cloudabi_fd_t)];
char iov_l_[PADL_(const cloudabi64_ciovec_t *)]; const cloudabi64_ciovec_t * iov; char iov_r_[PADR_(const cloudabi64_ciovec_t *)];
- char iovcnt_l_[PADL_(cloudabi64_size_t)]; cloudabi64_size_t iovcnt; char iovcnt_r_[PADR_(cloudabi64_size_t)];
+ char iovcnt_l_[PADL_(size_t)]; size_t iovcnt; char iovcnt_r_[PADR_(size_t)];
char offset_l_[PADL_(cloudabi_filesize_t)]; cloudabi_filesize_t offset; char offset_r_[PADR_(cloudabi_filesize_t)];
};
struct cloudabi64_sys_fd_read_args {
char fd_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t fd; char fd_r_[PADR_(cloudabi_fd_t)];
char iov_l_[PADL_(const cloudabi64_iovec_t *)]; const cloudabi64_iovec_t * iov; char iov_r_[PADR_(const cloudabi64_iovec_t *)];
- char iovcnt_l_[PADL_(cloudabi64_size_t)]; cloudabi64_size_t iovcnt; char iovcnt_r_[PADR_(cloudabi64_size_t)];
+ char iovcnt_l_[PADL_(size_t)]; size_t iovcnt; char iovcnt_r_[PADR_(size_t)];
};
struct cloudabi_sys_fd_replace_args {
char from_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t from; char from_r_[PADR_(cloudabi_fd_t)];
@@ -102,7 +102,7 @@ struct cloudabi_sys_fd_sync_args {
struct cloudabi64_sys_fd_write_args {
char fd_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t fd; char fd_r_[PADR_(cloudabi_fd_t)];
char iov_l_[PADL_(const cloudabi64_ciovec_t *)]; const cloudabi64_ciovec_t * iov; char iov_r_[PADR_(const cloudabi64_ciovec_t *)];
- char iovcnt_l_[PADL_(cloudabi64_size_t)]; cloudabi64_size_t iovcnt; char iovcnt_r_[PADR_(cloudabi64_size_t)];
+ char iovcnt_l_[PADL_(size_t)]; size_t iovcnt; char iovcnt_r_[PADR_(size_t)];
};
struct cloudabi_sys_file_advise_args {
char fd_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t fd; char fd_r_[PADR_(cloudabi_fd_t)];
@@ -130,7 +130,7 @@ struct cloudabi_sys_file_link_args {
char path2len_l_[PADL_(size_t)]; size_t path2len; char path2len_r_[PADR_(size_t)];
};
struct cloudabi_sys_file_open_args {
- char fd_l_[PADL_(cloudabi_lookup_t)]; cloudabi_lookup_t fd; char fd_r_[PADR_(cloudabi_lookup_t)];
+ char dirfd_l_[PADL_(cloudabi_lookup_t)]; cloudabi_lookup_t dirfd; char dirfd_r_[PADR_(cloudabi_lookup_t)];
char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)];
char pathlen_l_[PADL_(size_t)]; size_t pathlen; char pathlen_r_[PADR_(size_t)];
char oflags_l_[PADL_(cloudabi_oflags_t)]; cloudabi_oflags_t oflags; char oflags_r_[PADR_(cloudabi_oflags_t)];
@@ -146,7 +146,7 @@ struct cloudabi_sys_file_readlink_args {
char fd_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t fd; char fd_r_[PADR_(cloudabi_fd_t)];
char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)];
char pathlen_l_[PADL_(size_t)]; size_t pathlen; char pathlen_r_[PADR_(size_t)];
- char buf_l_[PADL_(void *)]; void * buf; char buf_r_[PADR_(void *)];
+ char buf_l_[PADL_(char *)]; char * buf; char buf_r_[PADR_(char *)];
char bufsize_l_[PADL_(size_t)]; size_t bufsize; char bufsize_r_[PADR_(size_t)];
};
struct cloudabi_sys_file_rename_args {
@@ -190,11 +190,11 @@ struct cloudabi_sys_file_unlink_args {
char fd_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t fd; char fd_r_[PADR_(cloudabi_fd_t)];
char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)];
char pathlen_l_[PADL_(size_t)]; size_t pathlen; char pathlen_r_[PADR_(size_t)];
- char flag_l_[PADL_(cloudabi_ulflags_t)]; cloudabi_ulflags_t flag; char flag_r_[PADR_(cloudabi_ulflags_t)];
+ char flags_l_[PADL_(cloudabi_ulflags_t)]; cloudabi_ulflags_t flags; char flags_r_[PADR_(cloudabi_ulflags_t)];
};
struct cloudabi_sys_lock_unlock_args {
char lock_l_[PADL_(cloudabi_lock_t *)]; cloudabi_lock_t * lock; char lock_r_[PADR_(cloudabi_lock_t *)];
- char scope_l_[PADL_(cloudabi_mflags_t)]; cloudabi_mflags_t scope; char scope_r_[PADR_(cloudabi_mflags_t)];
+ char scope_l_[PADL_(cloudabi_scope_t)]; cloudabi_scope_t scope; char scope_r_[PADR_(cloudabi_scope_t)];
};
struct cloudabi_sys_mem_advise_args {
char addr_l_[PADL_(void *)]; void * addr; char addr_r_[PADR_(void *)];
@@ -234,7 +234,7 @@ struct cloudabi_sys_mem_unmap_args {
struct cloudabi64_sys_poll_args {
char in_l_[PADL_(const cloudabi64_subscription_t *)]; const cloudabi64_subscription_t * in; char in_r_[PADR_(const cloudabi64_subscription_t *)];
char out_l_[PADL_(cloudabi64_event_t *)]; cloudabi64_event_t * out; char out_r_[PADR_(cloudabi64_event_t *)];
- char nevents_l_[PADL_(cloudabi64_size_t)]; cloudabi64_size_t nevents; char nevents_r_[PADR_(cloudabi64_size_t)];
+ char nsubscriptions_l_[PADL_(size_t)]; size_t nsubscriptions; char nsubscriptions_r_[PADR_(size_t)];
};
struct cloudabi_sys_proc_exec_args {
char fd_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t fd; char fd_r_[PADR_(cloudabi_fd_t)];
@@ -257,41 +257,41 @@ struct cloudabi_sys_random_get_args {
char nbyte_l_[PADL_(size_t)]; size_t nbyte; char nbyte_r_[PADR_(size_t)];
};
struct cloudabi_sys_sock_accept_args {
- char s_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t s; char s_r_[PADR_(cloudabi_fd_t)];
+ char sock_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t sock; char sock_r_[PADR_(cloudabi_fd_t)];
char buf_l_[PADL_(cloudabi_sockstat_t *)]; cloudabi_sockstat_t * buf; char buf_r_[PADR_(cloudabi_sockstat_t *)];
};
struct cloudabi_sys_sock_bind_args {
- char s_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t s; char s_r_[PADR_(cloudabi_fd_t)];
+ char sock_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t sock; char sock_r_[PADR_(cloudabi_fd_t)];
char fd_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t fd; char fd_r_[PADR_(cloudabi_fd_t)];
char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)];
char pathlen_l_[PADL_(size_t)]; size_t pathlen; char pathlen_r_[PADR_(size_t)];
};
struct cloudabi_sys_sock_connect_args {
- char s_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t s; char s_r_[PADR_(cloudabi_fd_t)];
+ char sock_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t sock; char sock_r_[PADR_(cloudabi_fd_t)];
char fd_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t fd; char fd_r_[PADR_(cloudabi_fd_t)];
char path_l_[PADL_(const char *)]; const char * path; char path_r_[PADR_(const char *)];
char pathlen_l_[PADL_(size_t)]; size_t pathlen; char pathlen_r_[PADR_(size_t)];
};
struct cloudabi_sys_sock_listen_args {
- char s_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t s; char s_r_[PADR_(cloudabi_fd_t)];
+ char sock_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t sock; char sock_r_[PADR_(cloudabi_fd_t)];
char backlog_l_[PADL_(cloudabi_backlog_t)]; cloudabi_backlog_t backlog; char backlog_r_[PADR_(cloudabi_backlog_t)];
};
struct cloudabi64_sys_sock_recv_args {
- char s_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t s; char s_r_[PADR_(cloudabi_fd_t)];
+ char sock_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t sock; char sock_r_[PADR_(cloudabi_fd_t)];
char in_l_[PADL_(const cloudabi64_recv_in_t *)]; const cloudabi64_recv_in_t * in; char in_r_[PADR_(const cloudabi64_recv_in_t *)];
char out_l_[PADL_(cloudabi64_recv_out_t *)]; cloudabi64_recv_out_t * out; char out_r_[PADR_(cloudabi64_recv_out_t *)];
};
struct cloudabi64_sys_sock_send_args {
- char s_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t s; char s_r_[PADR_(cloudabi_fd_t)];
+ char sock_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t sock; char sock_r_[PADR_(cloudabi_fd_t)];
char in_l_[PADL_(const cloudabi64_send_in_t *)]; const cloudabi64_send_in_t * in; char in_r_[PADR_(const cloudabi64_send_in_t *)];
char out_l_[PADL_(cloudabi64_send_out_t *)]; cloudabi64_send_out_t * out; char out_r_[PADR_(cloudabi64_send_out_t *)];
};
struct cloudabi_sys_sock_shutdown_args {
- char fd_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t fd; char fd_r_[PADR_(cloudabi_fd_t)];
+ char sock_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t sock; char sock_r_[PADR_(cloudabi_fd_t)];
char how_l_[PADL_(cloudabi_sdflags_t)]; cloudabi_sdflags_t how; char how_r_[PADR_(cloudabi_sdflags_t)];
};
struct cloudabi_sys_sock_stat_get_args {
- char fd_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t fd; char fd_r_[PADR_(cloudabi_fd_t)];
+ char sock_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t sock; char sock_r_[PADR_(cloudabi_fd_t)];
char buf_l_[PADL_(cloudabi_sockstat_t *)]; cloudabi_sockstat_t * buf; char buf_r_[PADR_(cloudabi_sockstat_t *)];
char flags_l_[PADL_(cloudabi_ssflags_t)]; cloudabi_ssflags_t flags; char flags_r_[PADR_(cloudabi_ssflags_t)];
};
@@ -300,7 +300,7 @@ struct cloudabi64_sys_thread_create_args {
};
struct cloudabi_sys_thread_exit_args {
char lock_l_[PADL_(cloudabi_lock_t *)]; cloudabi_lock_t * lock; char lock_r_[PADR_(cloudabi_lock_t *)];
- char scope_l_[PADL_(cloudabi_mflags_t)]; cloudabi_mflags_t scope; char scope_r_[PADR_(cloudabi_mflags_t)];
+ char scope_l_[PADL_(cloudabi_scope_t)]; cloudabi_scope_t scope; char scope_r_[PADR_(cloudabi_scope_t)];
};
struct cloudabi_sys_thread_tcb_set_args {
char tcb_l_[PADL_(void *)]; void * tcb; char tcb_r_[PADR_(void *)];
@@ -311,9 +311,9 @@ struct cloudabi_sys_thread_yield_args {
struct cloudabi64_sys_poll_fd_args {
char fd_l_[PADL_(cloudabi_fd_t)]; cloudabi_fd_t fd; char fd_r_[PADR_(cloudabi_fd_t)];
char in_l_[PADL_(const cloudabi64_subscription_t *)]; const cloudabi64_subscription_t * in; char in_r_[PADR_(const cloudabi64_subscription_t *)];
- char nin_l_[PADL_(cloudabi64_size_t)]; cloudabi64_size_t nin; char nin_r_[PADR_(cloudabi64_size_t)];
+ char nin_l_[PADL_(size_t)]; size_t nin; char nin_r_[PADR_(size_t)];
char out_l_[PADL_(cloudabi64_event_t *)]; cloudabi64_event_t * out; char out_r_[PADR_(cloudabi64_event_t *)];
- char nout_l_[PADL_(cloudabi64_size_t)]; cloudabi64_size_t nout; char nout_r_[PADR_(cloudabi64_size_t)];
+ char nout_l_[PADL_(size_t)]; size_t nout; char nout_r_[PADR_(size_t)];
char timeout_l_[PADL_(const cloudabi64_subscription_t *)]; const cloudabi64_subscription_t * timeout; char timeout_r_[PADR_(const cloudabi64_subscription_t *)];
};
int cloudabi_sys_clock_res_get(struct thread *, struct cloudabi_sys_clock_res_get_args *);
diff --git a/sys/compat/cloudabi64/cloudabi64_sock.c b/sys/compat/cloudabi64/cloudabi64_sock.c
index c612a32..e6b9c94 100644
--- a/sys/compat/cloudabi64/cloudabi64_sock.c
+++ b/sys/compat/cloudabi64/cloudabi64_sock.c
@@ -35,9 +35,10 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/uio.h>
+#include <contrib/cloudabi/cloudabi64_types.h>
+
#include <compat/cloudabi/cloudabi_util.h>
-#include <compat/cloudabi64/cloudabi64_syscalldefs.h>
#include <compat/cloudabi64/cloudabi64_proto.h>
static MALLOC_DEFINE(M_SOCKET, "socket", "CloudABI socket");
@@ -82,7 +83,7 @@ cloudabi64_sys_sock_recv(struct thread *td,
msghdr.msg_flags |= MSG_WAITALL;
/* TODO(ed): Add file descriptor passing. */
- error = kern_recvit(td, uap->s, &msghdr, UIO_SYSSPACE, NULL);
+ error = kern_recvit(td, uap->sock, &msghdr, UIO_SYSSPACE, NULL);
free(msghdr.msg_iov, M_SOCKET);
if (error != 0)
return (error);
@@ -132,7 +133,7 @@ cloudabi64_sys_sock_send(struct thread *td,
flags |= MSG_EOR;
/* TODO(ed): Add file descriptor passing. */
- error = kern_sendit(td, uap->s, &msghdr, flags, NULL, UIO_USERSPACE);
+ error = kern_sendit(td, uap->sock, &msghdr, flags, NULL, UIO_USERSPACE);
free(msghdr.msg_iov, M_SOCKET);
if (error != 0)
return (error);
diff --git a/sys/compat/cloudabi64/cloudabi64_syscall.h b/sys/compat/cloudabi64/cloudabi64_syscall.h
index 40c017a..b5694bf 100644
--- a/sys/compat/cloudabi64/cloudabi64_syscall.h
+++ b/sys/compat/cloudabi64/cloudabi64_syscall.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/compat/cloudabi64/syscalls.master 286318 2015-08-05 13:09:46Z ed
+ * created from FreeBSD: head/sys/contrib/cloudabi/syscalls.master 297468 2016-03-31 18:50:06Z ed
*/
#define CLOUDABI64_SYS_cloudabi_sys_clock_res_get 0
diff --git a/sys/compat/cloudabi64/cloudabi64_syscalls.c b/sys/compat/cloudabi64/cloudabi64_syscalls.c
index 5c0732b..03407ff 100644
--- a/sys/compat/cloudabi64/cloudabi64_syscalls.c
+++ b/sys/compat/cloudabi64/cloudabi64_syscalls.c
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/compat/cloudabi64/syscalls.master 286318 2015-08-05 13:09:46Z ed
+ * created from FreeBSD: head/sys/contrib/cloudabi/syscalls.master 297468 2016-03-31 18:50:06Z ed
*/
const char *cloudabi64_syscallnames[] = {
diff --git a/sys/compat/cloudabi64/cloudabi64_sysent.c b/sys/compat/cloudabi64/cloudabi64_sysent.c
index 2ed5042..50f4a65 100644
--- a/sys/compat/cloudabi64/cloudabi64_sysent.c
+++ b/sys/compat/cloudabi64/cloudabi64_sysent.c
@@ -3,12 +3,12 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/compat/cloudabi64/syscalls.master 286318 2015-08-05 13:09:46Z ed
+ * created from FreeBSD: head/sys/contrib/cloudabi/syscalls.master 297468 2016-03-31 18:50:06Z ed
*/
#include <sys/sysent.h>
#include <sys/sysproto.h>
-#include <compat/cloudabi64/cloudabi64_syscalldefs.h>
+#include <contrib/cloudabi/cloudabi64_types.h>
#include <compat/cloudabi64/cloudabi64_proto.h>
#define AS(name) (sizeof(struct name) / sizeof(register_t))
diff --git a/sys/compat/cloudabi64/cloudabi64_systrace_args.c b/sys/compat/cloudabi64/cloudabi64_systrace_args.c
index b3176aa..9429e8e 100644
--- a/sys/compat/cloudabi64/cloudabi64_systrace_args.c
+++ b/sys/compat/cloudabi64/cloudabi64_systrace_args.c
@@ -30,7 +30,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
case 2: {
struct cloudabi_sys_condvar_signal_args *p = params;
uarg[0] = (intptr_t) p->condvar; /* cloudabi_condvar_t * */
- iarg[1] = p->scope; /* cloudabi_mflags_t */
+ iarg[1] = p->scope; /* cloudabi_scope_t */
iarg[2] = p->nwaiters; /* cloudabi_nthreads_t */
*n_args = 3;
break;
@@ -75,7 +75,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
struct cloudabi64_sys_fd_pread_args *p = params;
iarg[0] = p->fd; /* cloudabi_fd_t */
uarg[1] = (intptr_t) p->iov; /* const cloudabi64_iovec_t * */
- iarg[2] = p->iovcnt; /* cloudabi64_size_t */
+ uarg[2] = p->iovcnt; /* size_t */
iarg[3] = p->offset; /* cloudabi_filesize_t */
*n_args = 4;
break;
@@ -85,7 +85,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
struct cloudabi64_sys_fd_pwrite_args *p = params;
iarg[0] = p->fd; /* cloudabi_fd_t */
uarg[1] = (intptr_t) p->iov; /* const cloudabi64_ciovec_t * */
- iarg[2] = p->iovcnt; /* cloudabi64_size_t */
+ uarg[2] = p->iovcnt; /* size_t */
iarg[3] = p->offset; /* cloudabi_filesize_t */
*n_args = 4;
break;
@@ -95,7 +95,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
struct cloudabi64_sys_fd_read_args *p = params;
iarg[0] = p->fd; /* cloudabi_fd_t */
uarg[1] = (intptr_t) p->iov; /* const cloudabi64_iovec_t * */
- iarg[2] = p->iovcnt; /* cloudabi64_size_t */
+ uarg[2] = p->iovcnt; /* size_t */
*n_args = 3;
break;
}
@@ -145,7 +145,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
struct cloudabi64_sys_fd_write_args *p = params;
iarg[0] = p->fd; /* cloudabi_fd_t */
uarg[1] = (intptr_t) p->iov; /* const cloudabi64_ciovec_t * */
- iarg[2] = p->iovcnt; /* cloudabi64_size_t */
+ uarg[2] = p->iovcnt; /* size_t */
*n_args = 3;
break;
}
@@ -193,7 +193,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
/* cloudabi_sys_file_open */
case 21: {
struct cloudabi_sys_file_open_args *p = params;
- iarg[0] = p->fd; /* cloudabi_lookup_t */
+ iarg[0] = p->dirfd; /* cloudabi_lookup_t */
uarg[1] = (intptr_t) p->path; /* const char * */
uarg[2] = p->pathlen; /* size_t */
iarg[3] = p->oflags; /* cloudabi_oflags_t */
@@ -217,7 +217,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
iarg[0] = p->fd; /* cloudabi_fd_t */
uarg[1] = (intptr_t) p->path; /* const char * */
uarg[2] = p->pathlen; /* size_t */
- uarg[3] = (intptr_t) p->buf; /* void * */
+ uarg[3] = (intptr_t) p->buf; /* char * */
uarg[4] = p->bufsize; /* size_t */
*n_args = 5;
break;
@@ -289,7 +289,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
iarg[0] = p->fd; /* cloudabi_fd_t */
uarg[1] = (intptr_t) p->path; /* const char * */
uarg[2] = p->pathlen; /* size_t */
- iarg[3] = p->flag; /* cloudabi_ulflags_t */
+ iarg[3] = p->flags; /* cloudabi_ulflags_t */
*n_args = 4;
break;
}
@@ -297,7 +297,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
case 31: {
struct cloudabi_sys_lock_unlock_args *p = params;
uarg[0] = (intptr_t) p->lock; /* cloudabi_lock_t * */
- iarg[1] = p->scope; /* cloudabi_mflags_t */
+ iarg[1] = p->scope; /* cloudabi_scope_t */
*n_args = 2;
break;
}
@@ -369,7 +369,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
struct cloudabi64_sys_poll_args *p = params;
uarg[0] = (intptr_t) p->in; /* const cloudabi64_subscription_t * */
uarg[1] = (intptr_t) p->out; /* cloudabi64_event_t * */
- iarg[2] = p->nevents; /* cloudabi64_size_t */
+ uarg[2] = p->nsubscriptions; /* size_t */
*n_args = 3;
break;
}
@@ -414,7 +414,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
/* cloudabi_sys_sock_accept */
case 45: {
struct cloudabi_sys_sock_accept_args *p = params;
- iarg[0] = p->s; /* cloudabi_fd_t */
+ iarg[0] = p->sock; /* cloudabi_fd_t */
uarg[1] = (intptr_t) p->buf; /* cloudabi_sockstat_t * */
*n_args = 2;
break;
@@ -422,7 +422,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
/* cloudabi_sys_sock_bind */
case 46: {
struct cloudabi_sys_sock_bind_args *p = params;
- iarg[0] = p->s; /* cloudabi_fd_t */
+ iarg[0] = p->sock; /* cloudabi_fd_t */
iarg[1] = p->fd; /* cloudabi_fd_t */
uarg[2] = (intptr_t) p->path; /* const char * */
uarg[3] = p->pathlen; /* size_t */
@@ -432,7 +432,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
/* cloudabi_sys_sock_connect */
case 47: {
struct cloudabi_sys_sock_connect_args *p = params;
- iarg[0] = p->s; /* cloudabi_fd_t */
+ iarg[0] = p->sock; /* cloudabi_fd_t */
iarg[1] = p->fd; /* cloudabi_fd_t */
uarg[2] = (intptr_t) p->path; /* const char * */
uarg[3] = p->pathlen; /* size_t */
@@ -442,7 +442,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
/* cloudabi_sys_sock_listen */
case 48: {
struct cloudabi_sys_sock_listen_args *p = params;
- iarg[0] = p->s; /* cloudabi_fd_t */
+ iarg[0] = p->sock; /* cloudabi_fd_t */
iarg[1] = p->backlog; /* cloudabi_backlog_t */
*n_args = 2;
break;
@@ -450,7 +450,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
/* cloudabi64_sys_sock_recv */
case 49: {
struct cloudabi64_sys_sock_recv_args *p = params;
- iarg[0] = p->s; /* cloudabi_fd_t */
+ iarg[0] = p->sock; /* cloudabi_fd_t */
uarg[1] = (intptr_t) p->in; /* const cloudabi64_recv_in_t * */
uarg[2] = (intptr_t) p->out; /* cloudabi64_recv_out_t * */
*n_args = 3;
@@ -459,7 +459,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
/* cloudabi64_sys_sock_send */
case 50: {
struct cloudabi64_sys_sock_send_args *p = params;
- iarg[0] = p->s; /* cloudabi_fd_t */
+ iarg[0] = p->sock; /* cloudabi_fd_t */
uarg[1] = (intptr_t) p->in; /* const cloudabi64_send_in_t * */
uarg[2] = (intptr_t) p->out; /* cloudabi64_send_out_t * */
*n_args = 3;
@@ -468,7 +468,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
/* cloudabi_sys_sock_shutdown */
case 51: {
struct cloudabi_sys_sock_shutdown_args *p = params;
- iarg[0] = p->fd; /* cloudabi_fd_t */
+ iarg[0] = p->sock; /* cloudabi_fd_t */
iarg[1] = p->how; /* cloudabi_sdflags_t */
*n_args = 2;
break;
@@ -476,7 +476,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
/* cloudabi_sys_sock_stat_get */
case 52: {
struct cloudabi_sys_sock_stat_get_args *p = params;
- iarg[0] = p->fd; /* cloudabi_fd_t */
+ iarg[0] = p->sock; /* cloudabi_fd_t */
uarg[1] = (intptr_t) p->buf; /* cloudabi_sockstat_t * */
iarg[2] = p->flags; /* cloudabi_ssflags_t */
*n_args = 3;
@@ -493,7 +493,7 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
case 54: {
struct cloudabi_sys_thread_exit_args *p = params;
uarg[0] = (intptr_t) p->lock; /* cloudabi_lock_t * */
- iarg[1] = p->scope; /* cloudabi_mflags_t */
+ iarg[1] = p->scope; /* cloudabi_scope_t */
*n_args = 2;
break;
}
@@ -514,9 +514,9 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
struct cloudabi64_sys_poll_fd_args *p = params;
iarg[0] = p->fd; /* cloudabi_fd_t */
uarg[1] = (intptr_t) p->in; /* const cloudabi64_subscription_t * */
- iarg[2] = p->nin; /* cloudabi64_size_t */
+ uarg[2] = p->nin; /* size_t */
uarg[3] = (intptr_t) p->out; /* cloudabi64_event_t * */
- iarg[4] = p->nout; /* cloudabi64_size_t */
+ uarg[4] = p->nout; /* size_t */
uarg[5] = (intptr_t) p->timeout; /* const cloudabi64_subscription_t * */
*n_args = 6;
break;
@@ -561,7 +561,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "cloudabi_condvar_t *";
break;
case 1:
- p = "cloudabi_mflags_t";
+ p = "cloudabi_scope_t";
break;
case 2:
p = "cloudabi_nthreads_t";
@@ -630,7 +630,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "const cloudabi64_iovec_t *";
break;
case 2:
- p = "cloudabi64_size_t";
+ p = "size_t";
break;
case 3:
p = "cloudabi_filesize_t";
@@ -649,7 +649,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "const cloudabi64_ciovec_t *";
break;
case 2:
- p = "cloudabi64_size_t";
+ p = "size_t";
break;
case 3:
p = "cloudabi_filesize_t";
@@ -668,7 +668,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "const cloudabi64_iovec_t *";
break;
case 2:
- p = "cloudabi64_size_t";
+ p = "size_t";
break;
default:
break;
@@ -752,7 +752,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "const cloudabi64_ciovec_t *";
break;
case 2:
- p = "cloudabi64_size_t";
+ p = "size_t";
break;
default:
break;
@@ -891,7 +891,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "size_t";
break;
case 3:
- p = "void *";
+ p = "char *";
break;
case 4:
p = "size_t";
@@ -1043,7 +1043,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "cloudabi_lock_t *";
break;
case 1:
- p = "cloudabi_mflags_t";
+ p = "cloudabi_scope_t";
break;
default:
break;
@@ -1171,7 +1171,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "cloudabi64_event_t *";
break;
case 2:
- p = "cloudabi64_size_t";
+ p = "size_t";
break;
default:
break;
@@ -1377,7 +1377,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "cloudabi_lock_t *";
break;
case 1:
- p = "cloudabi_mflags_t";
+ p = "cloudabi_scope_t";
break;
default:
break;
@@ -1406,13 +1406,13 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
p = "const cloudabi64_subscription_t *";
break;
case 2:
- p = "cloudabi64_size_t";
+ p = "size_t";
break;
case 3:
p = "cloudabi64_event_t *";
break;
case 4:
- p = "cloudabi64_size_t";
+ p = "size_t";
break;
case 5:
p = "const cloudabi64_subscription_t *";
@@ -1475,17 +1475,17 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
/* cloudabi64_sys_fd_pread */
case 8:
if (ndx == 0 || ndx == 1)
- p = "cloudabi64_size_t";
+ p = "size_t";
break;
/* cloudabi64_sys_fd_pwrite */
case 9:
if (ndx == 0 || ndx == 1)
- p = "cloudabi64_size_t";
+ p = "size_t";
break;
/* cloudabi64_sys_fd_read */
case 10:
if (ndx == 0 || ndx == 1)
- p = "cloudabi64_size_t";
+ p = "size_t";
break;
/* cloudabi_sys_fd_replace */
case 11:
@@ -1515,7 +1515,7 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
/* cloudabi64_sys_fd_write */
case 16:
if (ndx == 0 || ndx == 1)
- p = "cloudabi64_size_t";
+ p = "size_t";
break;
/* cloudabi_sys_file_advise */
case 17:
@@ -1630,7 +1630,7 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
/* cloudabi64_sys_poll */
case 39:
if (ndx == 0 || ndx == 1)
- p = "cloudabi64_size_t";
+ p = "size_t";
break;
/* cloudabi_sys_proc_exec */
case 40:
@@ -1677,12 +1677,12 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
/* cloudabi64_sys_sock_recv */
case 49:
if (ndx == 0 || ndx == 1)
- p = "cloudabi64_size_t";
+ p = "void";
break;
/* cloudabi64_sys_sock_send */
case 50:
if (ndx == 0 || ndx == 1)
- p = "cloudabi64_size_t";
+ p = "void";
break;
/* cloudabi_sys_sock_shutdown */
case 51:
@@ -1714,7 +1714,7 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
/* cloudabi64_sys_poll_fd */
case 57:
if (ndx == 0 || ndx == 1)
- p = "cloudabi64_size_t";
+ p = "size_t";
break;
default:
break;
diff --git a/sys/compat/cloudabi64/cloudabi64_thread.c b/sys/compat/cloudabi64/cloudabi64_thread.c
index 04b1782..51961f8 100644
--- a/sys/compat/cloudabi64/cloudabi64_thread.c
+++ b/sys/compat/cloudabi64/cloudabi64_thread.c
@@ -30,7 +30,8 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/systm.h>
-#include <compat/cloudabi64/cloudabi64_syscalldefs.h>
+#include <contrib/cloudabi/cloudabi64_types.h>
+
#include <compat/cloudabi64/cloudabi64_proto.h>
#include <compat/cloudabi64/cloudabi64_util.h>
diff --git a/sys/compat/cloudabi64/cloudabi64_util.h b/sys/compat/cloudabi64/cloudabi64_util.h
index 180a01e..dcec70e 100644
--- a/sys/compat/cloudabi64/cloudabi64_util.h
+++ b/sys/compat/cloudabi64/cloudabi64_util.h
@@ -31,7 +31,7 @@
#include <sys/types.h>
#include <sys/imgact_elf.h>
-#include <compat/cloudabi64/cloudabi64_syscalldefs.h>
+#include <contrib/cloudabi/cloudabi64_types.h>
struct image_params;
struct thread;
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
index bdcdf6f..598bdc5 100644
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -1653,6 +1653,19 @@ freebsd32_do_sendfile(struct thread *td,
hdtr32.hdr_cnt, &hdr_uio);
if (error)
goto out;
+#ifdef COMPAT_FREEBSD4
+ /*
+ * In FreeBSD < 5.0 the nbytes to send also included
+ * the header. If compat is specified subtract the
+ * header size from nbytes.
+ */
+ if (compat) {
+ if (uap->nbytes > hdr_uio->uio_resid)
+ uap->nbytes -= hdr_uio->uio_resid;
+ else
+ uap->nbytes = 0;
+ }
+#endif
}
if (hdtr.trailers != NULL) {
iov32 = PTRIN(hdtr32.trailers);
@@ -1670,7 +1683,7 @@ freebsd32_do_sendfile(struct thread *td,
goto out;
error = fo_sendfile(fp, uap->s, hdr_uio, trl_uio, offset,
- uap->nbytes, &sbytes, uap->flags, compat ? SFK_COMPAT : 0, td);
+ uap->nbytes, &sbytes, uap->flags, td);
fdrop(fp, td);
if (uap->sbytes != NULL)
diff --git a/sys/compat/linux/linux_event.c b/sys/compat/linux/linux_event.c
index b1ceadf..3e5a15c 100644
--- a/sys/compat/linux/linux_event.c
+++ b/sys/compat/linux/linux_event.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <sys/user.h>
#include <sys/file.h>
#include <sys/filedesc.h>
+#include <sys/filio.h>
#include <sys/errno.h>
#include <sys/event.h>
#include <sys/poll.h>
@@ -750,6 +751,8 @@ retry:
if (UINT64_MAX - efd->efd_count <= count) {
if ((efd->efd_flags & LINUX_O_NONBLOCK) != 0) {
mtx_unlock(&efd->efd_lock);
+ /* Do not not return the number of bytes written */
+ uio->uio_resid += sizeof(eventfd_t);
return (EAGAIN);
}
error = mtx_sleep(&efd->efd_count, &efd->efd_lock,
@@ -871,8 +874,24 @@ static int
eventfd_ioctl(struct file *fp, u_long cmd, void *data,
struct ucred *active_cred, struct thread *td)
{
+ struct eventfd *efd;
- return (ENXIO);
+ efd = fp->f_data;
+ if (fp->f_type != DTYPE_LINUXEFD || efd == NULL)
+ return (EINVAL);
+
+ switch (cmd)
+ {
+ case FIONBIO:
+ if (*(int *)data)
+ efd->efd_flags |= LINUX_O_NONBLOCK;
+ else
+ efd->efd_flags &= ~LINUX_O_NONBLOCK;
+ case FIOASYNC:
+ return (0);
+ default:
+ return (ENXIO);
+ }
}
/*ARGSUSED*/
diff --git a/sys/compat/linux/linux_mib.c b/sys/compat/linux/linux_mib.c
index 396344b..a66ed80 100644
--- a/sys/compat/linux/linux_mib.c
+++ b/sys/compat/linux/linux_mib.c
@@ -168,9 +168,6 @@ linux_find_prison(struct prison *spr, struct prison **prp)
struct prison *pr;
struct linux_prison *lpr;
- if (!linux_osd_jail_slot)
- /* In case osd_register failed. */
- spr = &prison0;
for (pr = spr;; pr = pr->pr_parent) {
mtx_lock(&pr->pr_mtx);
lpr = (pr == &prison0)
@@ -189,15 +186,14 @@ linux_find_prison(struct prison *spr, struct prison **prp)
* Ensure a prison has its own Linux info. If lprp is non-null, point it to
* the Linux info and lock the prison.
*/
-static int
+static void
linux_alloc_prison(struct prison *pr, struct linux_prison **lprp)
{
struct prison *ppr;
struct linux_prison *lpr, *nlpr;
- int error;
+ void *rsv;
/* If this prison already has Linux info, return that. */
- error = 0;
lpr = linux_find_prison(pr, &ppr);
if (ppr == pr)
goto done;
@@ -207,29 +203,24 @@ linux_alloc_prison(struct prison *pr, struct linux_prison **lprp)
*/
mtx_unlock(&ppr->pr_mtx);
nlpr = malloc(sizeof(struct linux_prison), M_PRISON, M_WAITOK);
+ rsv = osd_reserve(linux_osd_jail_slot);
lpr = linux_find_prison(pr, &ppr);
if (ppr == pr) {
free(nlpr, M_PRISON);
+ osd_free_reserved(rsv);
goto done;
}
/* Inherit the initial values from the ancestor. */
mtx_lock(&pr->pr_mtx);
- error = osd_jail_set(pr, linux_osd_jail_slot, nlpr);
- if (error == 0) {
- bcopy(lpr, nlpr, sizeof(*lpr));
- lpr = nlpr;
- } else {
- free(nlpr, M_PRISON);
- lpr = NULL;
- }
+ (void)osd_jail_set_reserved(pr, linux_osd_jail_slot, rsv, nlpr);
+ bcopy(lpr, nlpr, sizeof(*lpr));
+ lpr = nlpr;
mtx_unlock(&ppr->pr_mtx);
done:
if (lprp != NULL)
*lprp = lpr;
else
mtx_unlock(&pr->pr_mtx);
-
- return (error);
}
/*
@@ -249,7 +240,8 @@ linux_prison_create(void *obj, void *data)
* Inherit a prison's initial values from its parent
* (different from JAIL_SYS_INHERIT which also inherits changes).
*/
- return (linux_alloc_prison(pr, NULL));
+ linux_alloc_prison(pr, NULL);
+ return (0);
}
static int
@@ -345,11 +337,7 @@ linux_prison_set(void *obj, void *data)
* "linux=new" or "linux.*":
* the prison gets its own Linux info.
*/
- error = linux_alloc_prison(pr, &lpr);
- if (error) {
- mtx_unlock(&pr->pr_mtx);
- return (error);
- }
+ linux_alloc_prison(pr, &lpr);
if (osrelease) {
error = linux_map_osrel(osrelease, &lpr->pr_osrel);
if (error) {
@@ -449,21 +437,18 @@ linux_osd_jail_register(void)
linux_osd_jail_slot =
osd_jail_register(linux_prison_destructor, methods);
- if (linux_osd_jail_slot > 0) {
- /* Copy the system linux info to any current prisons. */
- sx_xlock(&allprison_lock);
- TAILQ_FOREACH(pr, &allprison, pr_list)
- (void)linux_alloc_prison(pr, NULL);
- sx_xunlock(&allprison_lock);
- }
+ /* Copy the system linux info to any current prisons. */
+ sx_slock(&allprison_lock);
+ TAILQ_FOREACH(pr, &allprison, pr_list)
+ linux_alloc_prison(pr, NULL);
+ sx_sunlock(&allprison_lock);
}
void
linux_osd_jail_deregister(void)
{
- if (linux_osd_jail_slot)
- osd_jail_deregister(linux_osd_jail_slot);
+ osd_jail_deregister(linux_osd_jail_slot);
}
void
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
index 7e9a0d5..98a842c 100644
--- a/sys/compat/linux/linux_misc.c
+++ b/sys/compat/linux/linux_misc.c
@@ -191,32 +191,33 @@ linux_alarm(struct thread *td, struct linux_alarm_args *args)
{
struct itimerval it, old_it;
u_int secs;
+ int error;
#ifdef DEBUG
if (ldebug(alarm))
printf(ARGS(alarm, "%u"), args->secs);
#endif
-
secs = args->secs;
-
- if (secs > INT_MAX)
- secs = INT_MAX;
-
- it.it_value.tv_sec = (long) secs;
- it.it_value.tv_usec = 0;
- it.it_interval.tv_sec = 0;
- it.it_interval.tv_usec = 0;
/*
- * According to POSIX and Linux implementation
- * the alarm() system call is always successfull.
- * Ignore errors and return 0 as a Linux does.
+ * Linux alarm() is always successfull. Limit secs to INT32_MAX / 2
+ * to match kern_setitimer()'s limit to avoid error from it.
+ *
+ * XXX. Linux limit secs to INT_MAX on 32 and does not limit on 64-bit
+ * platforms.
*/
- kern_setitimer(td, ITIMER_REAL, &it, &old_it);
- if (timevalisset(&old_it.it_value)) {
- if (old_it.it_value.tv_usec != 0)
- old_it.it_value.tv_sec++;
- td->td_retval[0] = old_it.it_value.tv_sec;
- }
+ if (secs > INT32_MAX / 2)
+ secs = INT32_MAX / 2;
+
+ it.it_value.tv_sec = secs;
+ it.it_value.tv_usec = 0;
+ timevalclear(&it.it_interval);
+ error = kern_setitimer(td, ITIMER_REAL, &it, &old_it);
+ KASSERT(error == 0, ("kern_setitimer returns %d", error));
+
+ if ((old_it.it_value.tv_sec == 0 && old_it.it_value.tv_usec > 0) ||
+ old_it.it_value.tv_usec >= 500000)
+ old_it.it_value.tv_sec++;
+ td->td_retval[0] = old_it.it_value.tv_sec;
return (0);
}
@@ -894,13 +895,14 @@ linux_utimensat(struct thread *td, struct linux_utimensat_args *args)
break;
}
timesp = times;
- }
- if (times[0].tv_nsec == UTIME_OMIT && times[1].tv_nsec == UTIME_OMIT)
/* This breaks POSIX, but is what the Linux kernel does
* _on purpose_ (documented in the man page for utimensat(2)),
* so we must follow that behaviour. */
- return (0);
+ if (times[0].tv_nsec == UTIME_OMIT &&
+ times[1].tv_nsec == UTIME_OMIT)
+ return (0);
+ }
if (args->pathname != NULL)
LCONVPATHEXIST_AT(td, args->pathname, &path, dfd);
diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c
index 01b007c..741a45b 100644
--- a/sys/compat/linux/linux_socket.c
+++ b/sys/compat/linux/linux_socket.c
@@ -448,7 +448,7 @@ linux_to_bsd_msg_flags(int flags)
if (flags & LINUX_MSG_ERRQUEUE)
;
#endif
- return ret_flags;
+ return (ret_flags);
}
/*
@@ -463,15 +463,12 @@ bsd_to_linux_sockaddr(struct sockaddr *arg)
struct sockaddr sa;
size_t sa_len = sizeof(struct sockaddr);
int error;
-
+
if ((error = copyin(arg, &sa, sa_len)))
return (error);
-
+
*(u_short *)&sa = sa.sa_family;
-
- error = copyout(&sa, arg, sa_len);
-
- return (error);
+ return (copyout(&sa, arg, sa_len));
}
static int
@@ -486,10 +483,7 @@ linux_to_bsd_sockaddr(struct sockaddr *arg, int len)
sa.sa_family = *(sa_family_t *)&sa;
sa.sa_len = len;
-
- error = copyout(&sa, arg, sa_len);
-
- return (error);
+ return (copyout(&sa, arg, sa_len));
}
static int
@@ -511,11 +505,7 @@ linux_sa_put(struct osockaddr *osa)
return (EINVAL);
sa.sa_family = bdom;
- error = copyout(&sa, osa, sizeof(sa.sa_family));
- if (error)
- return (error);
-
- return (0);
+ return (copyout(&sa, osa, sizeof(sa.sa_family)));
}
static int
@@ -912,10 +902,7 @@ linux_getsockname(struct thread *td, struct linux_getsockname_args *args)
bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.asa);
if (error)
return (error);
- error = linux_sa_put(PTRIN(args->addr));
- if (error)
- return (error);
- return (0);
+ return (linux_sa_put(PTRIN(args->addr)));
}
int
@@ -935,10 +922,7 @@ linux_getpeername(struct thread *td, struct linux_getpeername_args *args)
bsd_to_linux_sockaddr((struct sockaddr *)bsd_args.asa);
if (error)
return (error);
- error = linux_sa_put(PTRIN(args->addr));
- if (error)
- return (error);
- return (0);
+ return (linux_sa_put(PTRIN(args->addr)));
}
int
@@ -1003,7 +987,7 @@ linux_send(struct thread *td, struct linux_send_args *args)
bsd_args.flags = args->flags;
bsd_args.to = NULL;
bsd_args.tolen = 0;
- return sys_sendto(td, &bsd_args);
+ return (sys_sendto(td, &bsd_args));
}
struct linux_recv_args {
@@ -1040,7 +1024,6 @@ linux_sendto(struct thread *td, struct linux_sendto_args *args)
{
struct msghdr msg;
struct iovec aiov;
- int error;
if (linux_check_hdrincl(td, args->s) == 0)
/* IP_HDRINCL set, tweak the packet before sending */
@@ -1054,9 +1037,8 @@ linux_sendto(struct thread *td, struct linux_sendto_args *args)
msg.msg_flags = 0;
aiov.iov_base = PTRIN(args->msg);
aiov.iov_len = args->len;
- error = linux_sendit(td, args->s, &msg, args->flags, NULL,
- UIO_USERSPACE);
- return (error);
+ return (linux_sendit(td, args->s, &msg, args->flags, NULL,
+ UIO_USERSPACE));
}
int
diff --git a/sys/compat/linux/linux_stats.c b/sys/compat/linux/linux_stats.c
index 84ade7b..3638c6b 100644
--- a/sys/compat/linux/linux_stats.c
+++ b/sys/compat/linux/linux_stats.c
@@ -257,7 +257,7 @@ static int
stat_copyout(struct stat *buf, void *ubuf)
{
struct l_stat lbuf;
-
+
bzero(&lbuf, sizeof(lbuf));
lbuf.st_dev = buf->st_dev;
lbuf.st_ino = buf->st_ino;
@@ -303,7 +303,7 @@ linux_stat(struct thread *td, struct linux_stat_args *args)
return (error);
}
LFREEPATH(path);
- return(stat_copyout(&buf, args->up));
+ return (stat_copyout(&buf, args->up));
}
int
@@ -325,7 +325,7 @@ linux_lstat(struct thread *td, struct linux_lstat_args *args)
return (error);
}
LFREEPATH(path);
- return(stat_copyout(&buf, args->up));
+ return (stat_copyout(&buf, args->up));
}
#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
@@ -381,10 +381,22 @@ bsd_to_linux_ftype(const char *fstypename)
return (0L);
}
-static void
+static int
bsd_to_linux_statfs(struct statfs *bsd_statfs, struct l_statfs *linux_statfs)
{
+#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
+ uint64_t tmp;
+#define LINUX_HIBITS 0xffffffff00000000ULL
+
+ tmp = bsd_statfs->f_blocks | bsd_statfs->f_bfree | bsd_statfs->f_files |
+ bsd_statfs->f_bsize;
+ if ((bsd_statfs->f_bavail != -1 && (bsd_statfs->f_bavail & LINUX_HIBITS)) ||
+ (bsd_statfs->f_ffree != -1 && (bsd_statfs->f_ffree & LINUX_HIBITS)) ||
+ (tmp & LINUX_HIBITS))
+ return (EOVERFLOW);
+#undef LINUX_HIBITS
+#endif
linux_statfs->f_type = bsd_to_linux_ftype(bsd_statfs->f_fstypename);
linux_statfs->f_bsize = bsd_statfs->f_bsize;
linux_statfs->f_blocks = bsd_statfs->f_blocks;
@@ -395,6 +407,8 @@ bsd_to_linux_statfs(struct statfs *bsd_statfs, struct l_statfs *linux_statfs)
linux_statfs->f_fsid.val[0] = bsd_statfs->f_fsid.val[0];
linux_statfs->f_fsid.val[1] = bsd_statfs->f_fsid.val[1];
linux_statfs->f_namelen = MAXNAMLEN;
+
+ return (0);
}
int
@@ -415,8 +429,10 @@ linux_statfs(struct thread *td, struct linux_statfs_args *args)
LFREEPATH(path);
if (error)
return (error);
- bsd_to_linux_statfs(&bsd_statfs, &linux_statfs);
- return copyout(&linux_statfs, args->buf, sizeof(linux_statfs));
+ error = bsd_to_linux_statfs(&bsd_statfs, &linux_statfs);
+ if (error)
+ return (error);
+ return (copyout(&linux_statfs, args->buf, sizeof(linux_statfs)));
}
#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
@@ -458,7 +474,28 @@ linux_statfs64(struct thread *td, struct linux_statfs64_args *args)
if (error)
return (error);
bsd_to_linux_statfs64(&bsd_statfs, &linux_statfs);
- return copyout(&linux_statfs, args->buf, sizeof(linux_statfs));
+ return (copyout(&linux_statfs, args->buf, sizeof(linux_statfs)));
+}
+
+int
+linux_fstatfs64(struct thread *td, struct linux_fstatfs64_args *args)
+{
+ struct l_statfs64 linux_statfs;
+ struct statfs bsd_statfs;
+ int error;
+
+#ifdef DEBUG
+ if (ldebug(fstatfs64))
+ printf(ARGS(fstatfs64, "%d, *"), args->fd);
+#endif
+ if (args->bufsize != sizeof(struct l_statfs64))
+ return (EINVAL);
+
+ error = kern_fstatfs(td, args->fd, &bsd_statfs);
+ if (error)
+ return error;
+ bsd_to_linux_statfs64(&bsd_statfs, &linux_statfs);
+ return (copyout(&linux_statfs, args->buf, sizeof(linux_statfs)));
}
#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */
@@ -475,9 +512,11 @@ linux_fstatfs(struct thread *td, struct linux_fstatfs_args *args)
#endif
error = kern_fstatfs(td, args->fd, &bsd_statfs);
if (error)
- return error;
- bsd_to_linux_statfs(&bsd_statfs, &linux_statfs);
- return copyout(&linux_statfs, args->buf, sizeof(linux_statfs));
+ return (error);
+ error = bsd_to_linux_statfs(&bsd_statfs, &linux_statfs);
+ if (error)
+ return (error);
+ return (copyout(&linux_statfs, args->buf, sizeof(linux_statfs)));
}
struct l_ustat
diff --git a/sys/compat/linuxkpi/common/include/linux/bitops.h b/sys/compat/linuxkpi/common/include/linux/bitops.h
index 0dcdfe0..b12050a 100644
--- a/sys/compat/linuxkpi/common/include/linux/bitops.h
+++ b/sys/compat/linuxkpi/common/include/linux/bitops.h
@@ -147,11 +147,11 @@ find_last_bit(unsigned long *addr, unsigned long size)
if (mask)
return (bit + __flsl(mask));
}
- while (--pos) {
+ while (pos--) {
addr--;
bit -= BITS_PER_LONG;
if (*addr)
- return (bit + __flsl(mask));
+ return (bit + __flsl(*addr));
}
return (size);
}
diff --git a/sys/compat/linuxkpi/common/include/linux/jiffies.h b/sys/compat/linuxkpi/common/include/linux/jiffies.h
index f7bc529..33629ec 100644
--- a/sys/compat/linuxkpi/common/include/linux/jiffies.h
+++ b/sys/compat/linuxkpi/common/include/linux/jiffies.h
@@ -95,4 +95,14 @@ get_jiffies_64(void)
return ((u64)(unsigned)ticks);
}
+static inline int
+linux_timer_jiffies_until(unsigned long expires)
+{
+ int delta = expires - jiffies;
+ /* guard against already expired values */
+ if (delta < 1)
+ delta = 1;
+ return (delta);
+}
+
#endif /* _LINUX_JIFFIES_H_ */
diff --git a/sys/compat/linuxkpi/common/include/linux/list.h b/sys/compat/linuxkpi/common/include/linux/list.h
index 63e8af5..1357555 100644
--- a/sys/compat/linuxkpi/common/include/linux/list.h
+++ b/sys/compat/linuxkpi/common/include/linux/list.h
@@ -61,6 +61,7 @@
#include <netinet/in.h>
#include <netinet/in_pcb.h>
#include <netinet/in_var.h>
+#include <netinet/tcp_lro.h>
#include <netinet6/in6_var.h>
#include <netinet6/nd6.h>
diff --git a/sys/compat/linuxkpi/common/include/linux/wait.h b/sys/compat/linuxkpi/common/include/linux/wait.h
index c62f735..8afea08 100644
--- a/sys/compat/linuxkpi/common/include/linux/wait.h
+++ b/sys/compat/linuxkpi/common/include/linux/wait.h
@@ -34,6 +34,7 @@
#include <linux/spinlock.h>
#include <linux/sched.h>
#include <linux/list.h>
+#include <linux/jiffies.h>
#include <sys/param.h>
#include <sys/systm.h>
@@ -113,6 +114,52 @@ do { \
-_error; \
})
+#define wait_event_interruptible_timeout(q, cond, timeout) \
+({ \
+ void *c = &(q).wchan; \
+ long end = jiffies + timeout; \
+ int __ret = 0; \
+ int __rc = 0; \
+ \
+ if (!(cond)) { \
+ for (; __rc == 0;) { \
+ sleepq_lock(c); \
+ if (cond) { \
+ sleepq_release(c); \
+ __ret = 1; \
+ break; \
+ } \
+ sleepq_add(c, NULL, "completion", \
+ SLEEPQ_SLEEP | SLEEPQ_INTERRUPTIBLE, 0); \
+ sleepq_set_timeout(c, linux_timer_jiffies_until(end));\
+ __rc = sleepq_timedwait_sig (c, 0); \
+ if (__rc != 0) { \
+ /* check for timeout or signal. \
+ * 0 if the condition evaluated to false\
+ * after the timeout elapsed, 1 if the \
+ * condition evaluated to true after the\
+ * timeout elapsed. \
+ */ \
+ if (__rc == EWOULDBLOCK) \
+ __ret = (cond); \
+ else \
+ __ret = -ERESTARTSYS; \
+ } \
+ \
+ } \
+ } else { \
+ /* return remaining jiffies (at least 1) if the \
+ * condition evaluated to true before the timeout \
+ * elapsed. \
+ */ \
+ __ret = (end - jiffies); \
+ if( __ret < 1 ) \
+ __ret = 1; \
+ } \
+ __ret; \
+})
+
+
static inline int
waitqueue_active(wait_queue_head_t *q)
{
diff --git a/sys/compat/linuxkpi/common/src/linux_compat.c b/sys/compat/linuxkpi/common/src/linux_compat.c
index b8a0801..d85d4ad 100644
--- a/sys/compat/linuxkpi/common/src/linux_compat.c
+++ b/sys/compat/linuxkpi/common/src/linux_compat.c
@@ -894,16 +894,6 @@ kasprintf(gfp_t gfp, const char *fmt, ...)
return (p);
}
-static int
-linux_timer_jiffies_until(unsigned long expires)
-{
- int delta = expires - jiffies;
- /* guard against already expired values */
- if (delta < 1)
- delta = 1;
- return (delta);
-}
-
static void
linux_timer_callback_wrapper(void *context)
{
diff --git a/sys/compat/ndis/kern_ndis.c b/sys/compat/ndis/kern_ndis.c
index 2ad1683..90e79b0 100644
--- a/sys/compat/ndis/kern_ndis.c
+++ b/sys/compat/ndis/kern_ndis.c
@@ -348,13 +348,13 @@ ndis_create_sysctls(arg)
ndis_add_sysctl(sc, "BusType", "Bus Type", buf, NDIS_FLAG_RDONLY);
if (sc->ndis_res_io != NULL) {
- sprintf(buf, "0x%lx", rman_get_start(sc->ndis_res_io));
+ sprintf(buf, "0x%jx", rman_get_start(sc->ndis_res_io));
ndis_add_sysctl(sc, "IOBaseAddress",
"Base I/O Address", buf, NDIS_FLAG_RDONLY);
}
if (sc->ndis_irq != NULL) {
- sprintf(buf, "%lu", rman_get_start(sc->ndis_irq));
+ sprintf(buf, "%ju", rman_get_start(sc->ndis_irq));
ndis_add_sysctl(sc, "InterruptNumber",
"Interrupt Number", buf, NDIS_FLAG_RDONLY);
}
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index 5a8014c..c9fce2e 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -2792,9 +2792,6 @@ device urndis
# Realtek RTL8187B/L wireless driver
device urtw
#
-# Realtek RTL8188CU/RTL8192CU wireless driver
-device urtwn
-#
# ZyDas ZD1211/ZD1211B wireless driver
device zyd
#
diff --git a/sys/conf/files b/sys/conf/files
index 47b68b9..e2dbc67 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1413,12 +1413,20 @@ dev/exca/exca.c optional cbb
dev/extres/clk/clk.c optional ext_resources clk
dev/extres/clk/clkdev_if.m optional ext_resources clk
dev/extres/clk/clknode_if.m optional ext_resources clk
+dev/extres/clk/clk_bus.c optional ext_resources clk fdt
dev/extres/clk/clk_div.c optional ext_resources clk
dev/extres/clk/clk_fixed.c optional ext_resources clk
dev/extres/clk/clk_gate.c optional ext_resources clk
dev/extres/clk/clk_mux.c optional ext_resources clk
+dev/extres/phy/phy.c optional ext_resources phy
+dev/extres/phy/phy_if.m optional ext_resources phy
dev/extres/hwreset/hwreset.c optional ext_resources hwreset
dev/extres/hwreset/hwreset_if.m optional ext_resources hwreset
+dev/extres/regulator/regdev_if.m optional ext_resources regulator
+dev/extres/regulator/regnode_if.m optional ext_resources regulator
+dev/extres/regulator/regulator.c optional ext_resources regulator
+dev/extres/regulator/regulator_bus.c optional ext_resources regulator fdt
+dev/extres/regulator/regulator_fixed.c optional ext_resources regulator
dev/fatm/if_fatm.c optional fatm pci
dev/fb/fbd.c optional fbd | vt
dev/fb/fb_if.m standard
@@ -1560,10 +1568,10 @@ ipw_monitor.fw optional ipwmonitorfw | ipwfw \
compile-with "${NORMAL_FW}" \
no-obj no-implicit-rule \
clean "ipw_monitor.fw"
-dev/iscsi/icl.c optional iscsi | ctl
-dev/iscsi/icl_conn_if.m optional iscsi | ctl
+dev/iscsi/icl.c optional iscsi | ctl
+dev/iscsi/icl_conn_if.m optional iscsi | ctl
dev/iscsi/icl_proxy.c optional iscsi | ctl
-dev/iscsi/icl_soft.c optional iscsi | ctl
+dev/iscsi/icl_soft.c optional iscsi | ctl
dev/iscsi/iscsi.c optional iscsi scbus
dev/iscsi_initiator/iscsi.c optional iscsi_initiator scbus
dev/iscsi_initiator/iscsi_subr.c optional iscsi_initiator scbus
@@ -2547,11 +2555,12 @@ dev/uart/uart_bus_puc.c optional uart puc
dev/uart/uart_bus_scc.c optional uart scc
dev/uart/uart_core.c optional uart
dev/uart/uart_dbg.c optional uart gdb
-dev/uart/uart_dev_ns8250.c optional uart uart_ns8250
+dev/uart/uart_dev_ns8250.c optional uart uart_ns8250 | uart uart_snps
dev/uart/uart_dev_pl011.c optional uart pl011
dev/uart/uart_dev_quicc.c optional uart quicc
dev/uart/uart_dev_sab82532.c optional uart uart_sab82532
dev/uart/uart_dev_sab82532.c optional uart scc
+dev/uart/uart_dev_snps.c optional uart uart_snps
dev/uart/uart_dev_z8530.c optional uart uart_z8530
dev/uart/uart_dev_z8530.c optional uart scc
dev/uart/uart_if.m optional uart
@@ -2670,50 +2679,6 @@ dev/usb/wlan/if_uath.c optional uath
dev/usb/wlan/if_upgt.c optional upgt
dev/usb/wlan/if_ural.c optional ural
dev/usb/wlan/if_urtw.c optional urtw
-dev/usb/wlan/if_urtwn.c optional urtwn
-urtwn-rtl8188eufw.c optional urtwn-rtl8188eufw | urtwnfw \
- compile-with "${AWK} -f $S/tools/fw_stub.awk urtwn-rtl8188eufw.fw:urtwn-rtl8188eufw:111 -murtwn-rtl8188eufw -c${.TARGET}" \
- no-implicit-rule before-depend local \
- clean "urtwn-rtl8188eufw.c"
-urtwn-rtl8188eufw.fwo optional urtwn-rtl8188eufw | urtwnfw \
- dependency "urtwn-rtl8188eufw.fw" \
- compile-with "${NORMAL_FWO}" \
- no-implicit-rule \
- clean "urtwn-rtl8188eufw.fwo"
-urtwn-rtl8188eufw.fw optional urtwn-rtl8188eufw | urtwnfw \
- dependency "$S/contrib/dev/urtwn/urtwn-rtl8188eufw.fw.uu" \
- compile-with "${NORMAL_FW}" \
- no-obj no-implicit-rule \
- clean "urtwn-rtl8188eufw.fw"
-urtwn-rtl8192cfwT.c optional urtwn-rtl8192cfwT | urtwnfw \
- compile-with "${AWK} -f $S/tools/fw_stub.awk urtwn-rtl8192cfwT.fw:urtwn-rtl8192cfwT:111 -murtwn-rtl8192cfwT -c${.TARGET}" \
- no-implicit-rule before-depend local \
- clean "urtwn-rtl8192cfwT.c"
-urtwn-rtl8192cfwT.fwo optional urtwn-rtl8192cfwT | urtwnfw \
- dependency "urtwn-rtl8192cfwT.fw" \
- compile-with "${NORMAL_FWO}" \
- no-implicit-rule \
- clean "urtwn-rtl8192cfwT.fwo"
-urtwn-rtl8192cfwT.fw optional urtwn-rtl8192cfwT | urtwnfw \
- dependency "$S/contrib/dev/urtwn/urtwn-rtl8192cfwT.fw.uu" \
- compile-with "${NORMAL_FW}" \
- no-obj no-implicit-rule \
- clean "urtwn-rtl8192cfwT.fw"
-urtwn-rtl8192cfwU.c optional urtwn-rtl8192cfwU | urtwnfw \
- compile-with "${AWK} -f $S/tools/fw_stub.awk urtwn-rtl8192cfwU.fw:urtwn-rtl8192cfwU:111 -murtwn-rtl8192cfwU -c${.TARGET}" \
- no-implicit-rule before-depend local \
- clean "urtwn-rtl8192cfwU.c"
-urtwn-rtl8192cfwU.fwo optional urtwn-rtl8192cfwU | urtwnfw \
- dependency "urtwn-rtl8192cfwU.fw" \
- compile-with "${NORMAL_FWO}" \
- no-implicit-rule \
- clean "urtwn-rtl8192cfwU.fwo"
-urtwn-rtl8192cfwU.fw optional urtwn-rtl8192cfwU | urtwnfw \
- dependency "$S/contrib/dev/urtwn/urtwn-rtl8192cfwU.fw.uu" \
- compile-with "${NORMAL_FW}" \
- no-obj no-implicit-rule \
- clean "urtwn-rtl8192cfwU.fw"
-
dev/usb/wlan/if_zyd.c optional zyd
#
# USB serial and parallel port drivers
diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64
index 97f2e37..85366fa 100644
--- a/sys/conf/files.amd64
+++ b/sys/conf/files.amd64
@@ -50,12 +50,12 @@ font.h optional sc_dflt_font \
clean "font.h ${SC_DFLT_FONT}-8x14 ${SC_DFLT_FONT}-8x16 ${SC_DFLT_FONT}-8x8"
#
atkbdmap.h optional atkbd_dflt_keymap \
- compile-with "/usr/sbin/kbdcontrol -L ${ATKBD_DFLT_KEYMAP} | sed -e 's/^static keymap_t.* = /static keymap_t key_map = /' -e 's/^static accentmap_t.* = /static accentmap_t accent_map = /' > atkbdmap.h" \
+ compile-with "kbdcontrol -P ${S:S/sys$/share/}/vt/keymaps -P ${S:S/sys$/share/}/syscons/keymaps -L ${ATKBD_DFLT_KEYMAP} | sed -e 's/^static keymap_t.* = /static keymap_t key_map = /' -e 's/^static accentmap_t.* = /static accentmap_t accent_map = /' > atkbdmap.h" \
no-obj no-implicit-rule before-depend \
clean "atkbdmap.h"
#
ukbdmap.h optional ukbd_dflt_keymap \
- compile-with "/usr/sbin/kbdcontrol -L ${UKBD_DFLT_KEYMAP} | sed -e 's/^static keymap_t.* = /static keymap_t key_map = /' -e 's/^static accentmap_t.* = /static accentmap_t accent_map = /' > ukbdmap.h" \
+ compile-with "kbdcontrol -P ${S:S/sys$/share/}/vt/keymaps -P ${S:S/sys$/share/}/syscons/keymaps -L ${UKBD_DFLT_KEYMAP} | sed -e 's/^static keymap_t.* = /static keymap_t key_map = /' -e 's/^static accentmap_t.* = /static accentmap_t accent_map = /' > ukbdmap.h" \
no-obj no-implicit-rule before-depend \
clean "ukbdmap.h"
#
@@ -104,7 +104,6 @@ acpi_wakedata.h optional acpi \
amd64/amd64/amd64_mem.c optional mem
#amd64/amd64/apic_vector.S standard
amd64/amd64/atomic.c standard
-amd64/amd64/autoconf.c standard
amd64/amd64/bios.c standard
amd64/amd64/bpf_jit_machdep.c optional bpf_jitter
amd64/amd64/cpu_switch.S standard
@@ -596,6 +595,7 @@ x86/isa/nmi.c standard
x86/isa/orm.c optional isa
x86/pci/pci_bus.c optional pci
x86/pci/qpi.c optional pci
+x86/x86/autoconf.c standard
x86/x86/bus_machdep.c standard
x86/x86/busdma_bounce.c standard
x86/x86/busdma_machdep.c standard
diff --git a/sys/conf/files.arm b/sys/conf/files.arm
index 2407616..a9da11c 100644
--- a/sys/conf/files.arm
+++ b/sys/conf/files.arm
@@ -103,6 +103,8 @@ dev/hwpmc/hwpmc_arm.c optional hwpmc
dev/hwpmc/hwpmc_armv7.c optional hwpmc armv6
dev/iicbus/twsi/twsi.c optional twsi
dev/ofw/ofw_cpu.c optional fdt
+dev/ofw/ofwpci.c optional fdt pci
+dev/pci/pci_host_generic.c optional pci_host_generic pci fdt
dev/psci/psci.c optional psci
dev/psci/psci_arm.S optional psci
dev/syscons/scgfbrndr.c optional sc
diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64
index 8f5f10a..7bbe458 100644
--- a/sys/conf/files.arm64
+++ b/sys/conf/files.arm64
@@ -12,6 +12,7 @@ arm64/arm64/bus_machdep.c standard
arm64/arm64/bus_space_asm.S standard
arm64/arm64/busdma_bounce.c standard
arm64/arm64/busdma_machdep.c standard
+arm64/arm64/bzero.S standard
arm64/arm64/clock.c standard
arm64/arm64/copyinout.S standard
arm64/arm64/copystr.c standard
@@ -66,6 +67,7 @@ dev/hwpmc/hwpmc_arm64_md.c optional hwpmc
dev/mmc/host/dwmmc.c optional dwmmc
dev/mmc/host/dwmmc_hisi.c optional dwmmc soc_hisi_hi6220
dev/ofw/ofw_cpu.c optional fdt
+dev/ofw/ofwpci.c optional fdt pci
dev/pci/pci_host_generic.c optional pci fdt
dev/psci/psci.c optional psci
dev/psci/psci_arm64.S optional psci
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index b065165..4b6f158 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -49,12 +49,12 @@ font.h optional sc_dflt_font \
clean "font.h ${SC_DFLT_FONT}-8x14 ${SC_DFLT_FONT}-8x16 ${SC_DFLT_FONT}-8x8"
#
atkbdmap.h optional atkbd_dflt_keymap \
- compile-with "/usr/sbin/kbdcontrol -L ${ATKBD_DFLT_KEYMAP} | sed -e 's/^static keymap_t.* = /static keymap_t key_map = /' -e 's/^static accentmap_t.* = /static accentmap_t accent_map = /' > atkbdmap.h" \
+ compile-with "kbdcontrol -P ${S:S/sys$/share/}/vt/keymaps -P ${S:S/sys$/share/}/syscons/keymaps -L ${ATKBD_DFLT_KEYMAP} | sed -e 's/^static keymap_t.* = /static keymap_t key_map = /' -e 's/^static accentmap_t.* = /static accentmap_t accent_map = /' > atkbdmap.h" \
no-obj no-implicit-rule before-depend \
clean "atkbdmap.h"
#
ukbdmap.h optional ukbd_dflt_keymap \
- compile-with "/usr/sbin/kbdcontrol -L ${UKBD_DFLT_KEYMAP} | sed -e 's/^static keymap_t.* = /static keymap_t key_map = /' -e 's/^static accentmap_t.* = /static accentmap_t accent_map = /' > ukbdmap.h" \
+ compile-with "kbdcontrol -P ${S:S/sys$/share/}/vt/keymaps -P ${S:S/sys$/share/}/syscons/keymaps -L ${UKBD_DFLT_KEYMAP} | sed -e 's/^static keymap_t.* = /static keymap_t key_map = /' -e 's/^static accentmap_t.* = /static accentmap_t accent_map = /' > ukbdmap.h" \
no-obj no-implicit-rule before-depend \
clean "ukbdmap.h"
#
@@ -285,6 +285,7 @@ dev/nvme/nvme_sysctl.c optional nvme
dev/nvme/nvme_test.c optional nvme
dev/nvme/nvme_util.c optional nvme
dev/nvram/nvram.c optional nvram isa
+dev/ofw/ofwpci.c optional fdt pci
dev/pcf/pcf_isa.c optional pcf
dev/random/ivy.c optional rdrand_rng
dev/random/nehemiah.c optional padlock_rng
@@ -451,7 +452,6 @@ i386/bios/smapi_bios.S optional smapi
#i386/i386/apic_vector.s optional apic
i386/i386/atomic.c standard \
compile-with "${CC} -c ${CFLAGS} ${DEFINED_PROF:S/^$/-fomit-frame-pointer/} ${.IMPSRC}"
-i386/i386/autoconf.c standard
i386/i386/bios.c standard
i386/i386/bioscall.s standard
i386/i386/bpf_jit_machdep.c optional bpf_jitter
@@ -590,6 +590,7 @@ x86/isa/nmi.c standard
x86/isa/orm.c optional isa
x86/pci/pci_bus.c optional pci
x86/pci/qpi.c optional pci
+x86/x86/autoconf.c standard
x86/x86/bus_machdep.c standard
x86/x86/busdma_bounce.c standard
x86/x86/busdma_machdep.c standard
diff --git a/sys/conf/files.mips b/sys/conf/files.mips
index 91d53aa..4cacac4 100644
--- a/sys/conf/files.mips
+++ b/sys/conf/files.mips
@@ -92,3 +92,6 @@ dev/nvram2env/nvram2env.c optional nvram2env
dev/hwpmc/hwpmc_mips.c optional hwpmc
dev/hwpmc/hwpmc_mips24k.c optional hwpmc_mips24k
dev/hwpmc/hwpmc_mips74k.c optional hwpmc_mips74k
+
+# ofw support
+dev/ofw/ofwpci.c optional fdt pci
diff --git a/sys/conf/files.pc98 b/sys/conf/files.pc98
index 75269b4..9f0ef00 100644
--- a/sys/conf/files.pc98
+++ b/sys/conf/files.pc98
@@ -46,7 +46,7 @@ svr4_assym.h optional compat_svr4 \
clean "svr4_assym.h"
#
ukbdmap.h optional ukbd_dflt_keymap \
- compile-with "/usr/sbin/kbdcontrol -L ${UKBD_DFLT_KEYMAP} | sed -e 's/^static keymap_t.* = /static keymap_t key_map = /' -e 's/^static accentmap_t.* = /static accentmap_t accent_map = /' > ukbdmap.h" \
+ compile-with "kbdcontrol -P ${S:S/sys$/share/}/vt/keymaps -P ${S:S/sys$/share/}/syscons/keymaps -L ${UKBD_DFLT_KEYMAP} | sed -e 's/^static keymap_t.* = /static keymap_t key_map = /' -e 's/^static accentmap_t.* = /static accentmap_t accent_map = /' > ukbdmap.h" \
no-obj no-implicit-rule before-depend \
clean "ukbdmap.h"
#
@@ -147,7 +147,6 @@ i386/bios/apm.c optional apm
#i386/i386/apic_vector.s optional apic
i386/i386/atomic.c standard \
compile-with "${CC} -c ${CFLAGS} ${DEFINED_PROF:S/^$/-fomit-frame-pointer/} ${.IMPSRC}"
-i386/i386/autoconf.c standard
i386/i386/bios.c standard
i386/i386/bioscall.s standard
i386/i386/bpf_jit_machdep.c optional bpf_jitter
@@ -258,6 +257,7 @@ x86/isa/atpic.c optional atpic
x86/isa/clock.c standard
x86/isa/isa.c optional isa
x86/pci/pci_bus.c optional pci
+x86/x86/autoconf.c standard
x86/x86/busdma_bounce.c standard
x86/x86/busdma_machdep.c standard
x86/x86/cpu_machdep.c standard
diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc
index 0a1e7c1..d2e8e3b 100644
--- a/sys/conf/files.powerpc
+++ b/sys/conf/files.powerpc
@@ -57,6 +57,7 @@ dev/ofw/ofw_console.c optional aim
dev/ofw/ofw_disk.c optional ofwd aim
dev/ofw/ofw_iicbus.c optional iicbus aim
dev/ofw/ofwbus.c optional aim | fdt
+dev/ofw/ofwpci.c optional pci
dev/ofw/ofw_standard.c optional aim powerpc
dev/ofw/ofw_subr.c optional aim powerpc
dev/powermac_nvram/powermac_nvram.c optional powermac_nvram powermac
@@ -145,7 +146,6 @@ powerpc/mpc85xx/pci_mpc85xx.c optional pci mpc85xx | pci qoriq_dpaa
powerpc/mpc85xx/pci_mpc85xx_pcib.c optional pci mpc85xx | pci qoriq_dpaa
powerpc/mpc85xx/qoriq_gpio.c optional mpc85xx gpio | qoriq_dpaa gpio
powerpc/ofw/ofw_machdep.c standard
-powerpc/ofw/ofw_pci.c optional pci
powerpc/ofw/ofw_pcibus.c optional pci
powerpc/ofw/ofw_pcib_pci.c optional pci
powerpc/ofw/ofw_real.c optional aim
diff --git a/sys/conf/files.sparc64 b/sys/conf/files.sparc64
index 84f23ff..a9643bd 100644
--- a/sys/conf/files.sparc64
+++ b/sys/conf/files.sparc64
@@ -8,17 +8,17 @@
# dependency lines other than the first are silently ignored.
#
atkbdmap.h optional atkbd_dflt_keymap \
- compile-with "/usr/sbin/kbdcontrol -L ${ATKBD_DFLT_KEYMAP} | sed -e 's/^static keymap_t.* = /static keymap_t key_map = /' -e 's/^static accentmap_t.* = /static accentmap_t accent_map = /' > atkbdmap.h" \
+ compile-with "kbdcontrol -P ${S:S/sys$/share/}/vt/keymaps -P ${S:S/sys$/share/}/syscons/keymaps -L ${ATKBD_DFLT_KEYMAP} | sed -e 's/^static keymap_t.* = /static keymap_t key_map = /' -e 's/^static accentmap_t.* = /static accentmap_t accent_map = /' > atkbdmap.h" \
no-obj no-implicit-rule before-depend \
clean "atkbdmap.h"
#
sunkbdmap.h optional sunkbd_dflt_keymap \
- compile-with "/usr/sbin/kbdcontrol -L ${SUNKBD_DFLT_KEYMAP} | sed -e 's/^static keymap_t.* = /static keymap_t key_map = /' -e 's/^static accentmap_t.* = /static accentmap_t accent_map = /' > sunkbdmap.h" \
+ compile-with "kbdcontrol -P ${S:S/sys$/share/}/vt/keymaps -P ${S:S/sys$/share/}/syscons/keymaps -L ${SUNKBD_DFLT_KEYMAP} | sed -e 's/^static keymap_t.* = /static keymap_t key_map = /' -e 's/^static accentmap_t.* = /static accentmap_t accent_map = /' > sunkbdmap.h" \
no-obj no-implicit-rule before-depend \
clean "sunkbdmap.h"
#
ukbdmap.h optional ukbd_dflt_keymap \
- compile-with "/usr/sbin/kbdcontrol -L ${UKBD_DFLT_KEYMAP} | sed -e 's/^static keymap_t.* = /static keymap_t key_map = /' -e 's/^static accentmap_t.* = /static accentmap_t accent_map = /' > ukbdmap.h" \
+ compile-with "kbdcontrol -P ${S:S/sys$/share/}/vt/keymaps -P ${S:S/sys$/share/}/syscons/keymaps -L ${UKBD_DFLT_KEYMAP} | sed -e 's/^static keymap_t.* = /static keymap_t key_map = /' -e 's/^static accentmap_t.* = /static accentmap_t accent_map = /' > ukbdmap.h" \
no-obj no-implicit-rule before-depend \
clean "ukbdmap.h"
#
diff --git a/sys/conf/kern.opts.mk b/sys/conf/kern.opts.mk
index d1d2d04..ad6ee72 100644
--- a/sys/conf/kern.opts.mk
+++ b/sys/conf/kern.opts.mk
@@ -30,7 +30,6 @@ __DEFAULT_YES_OPTIONS = \
CDDL \
CRYPT \
CUSE \
- FAST_DEPEND \
FORMAT_EXTENSIONS \
INET \
INET6 \
@@ -49,12 +48,6 @@ __DEFAULT_NO_OPTIONS = \
NAND \
OFED
-# Enable FAST_DEPEND by default for the meta build.
-.if !empty(.MAKE.MODE:Unormal:Mmeta)
-__DEFAULT_YES_OPTIONS+= FAST_DEPEND
-__DEFAULT_NO_OPTIONS:= ${__DEFAULT_NO_OPTIONS:NFAST_DEPEND}
-.endif
-
# Some options are totally broken on some architectures. We disable
# them. If you need to enable them on an experimental basis, you
# must change this code.
@@ -65,9 +58,8 @@ __DEFAULT_NO_OPTIONS:= ${__DEFAULT_NO_OPTIONS:NFAST_DEPEND}
# Things that don't work based on the CPU
.if ${MACHINE_CPUARCH} == "arm"
-BROKEN_OPTIONS+= ZFS
. if ${MACHINE_ARCH:Marmv6*} == ""
-BROKEN_OPTIONS+= CDDL
+BROKEN_OPTIONS+= CDDL ZFS
. endif
.endif
diff --git a/sys/conf/kern.post.mk b/sys/conf/kern.post.mk
index d5047a8..d28e87b 100644
--- a/sys/conf/kern.post.mk
+++ b/sys/conf/kern.post.mk
@@ -145,10 +145,6 @@ ${FULLKERNEL}: ${SYSTEM_DEP} vers.o
OBJS_DEPEND_GUESS+= assym.s vnode_if.h ${BEFORE_DEPEND:M*.h} \
${MFILES:T:S/.m$/.h/}
-.if ${MK_FAST_DEPEND} == "no" && !exists(${.OBJDIR}/.depend)
-${SYSTEM_OBJS}: ${OBJS_DEPEND_GUESS}
-.endif
-
LNFILES= ${CFILES:T:S/.c$/.ln/}
.for mfile in ${MFILES}
@@ -189,23 +185,6 @@ genassym.o: $S/$M/$M/genassym.c
${SYSTEM_OBJS} genassym.o vers.o: opt_global.h
-# Normal files first
-CFILES_NORMAL= ${CFILES:N*/cddl/*:N*fs/nfsclient/nfs_clkdtrace*:N*/compat/linuxkpi/common/*:N*/ofed/*:N*/dev/mlx5/*}
-SFILES_NORMAL= ${SFILES:N*/cddl/*}
-
-# We have "special" -I include paths for zfs/dtrace files in 'depend'.
-CFILES_CDDL= ${CFILES:M*/cddl/*}
-SFILES_CDDL= ${SFILES:M*/cddl/*}
-
-# We have "special" -I include paths for LinuxKPI.
-CFILES_LINUXKPI=${CFILES:M*/compat/linuxkpi/common/*}
-
-# We have "special" -I include paths for OFED.
-CFILES_OFED=${CFILES:M*/ofed/*}
-
-# We have "special" -I include paths for MLX5.
-CFILES_MLX5=${CFILES:M*/dev/mlx5/*}
-
# Skip reading .depend when not needed to speed up tree-walks
# and simple lookups.
.if !empty(.MAKEFLAGS:M-V${_V_READ_DEPEND}) || make(obj) || make(clean*) || \
@@ -216,9 +195,6 @@ _SKIP_READ_DEPEND= 1
.endif
kernel-depend: .depend
-# The argument list can be very long, so use make -V and xargs to
-# pass it to mkdep.
-_MKDEPCC:= ${CC:N${CCACHE_BIN}}
SRCS= assym.s vnode_if.h ${BEFORE_DEPEND} ${CFILES} \
${SYSTEM_CFILES} ${GEN_CFILES} ${SFILES} \
${MFILES:T:S/.m$/.h/}
@@ -228,7 +204,6 @@ DEPENDFILES= .depend .depend.*
.if !empty(.MAKE.MODE:Unormal:Mmeta) && empty(.MAKE.MODE:Unormal:Mnofilemon)
_meta_filemon= 1
.endif
-.if ${MK_FAST_DEPEND} == "yes"
DEPENDOBJS+= ${SYSTEM_OBJS} genassym.o
DEPENDFILES_OBJS= ${DEPENDOBJS:O:u:C/^/.depend./}
.if ${MAKE_VERSION} < 20160220
@@ -261,12 +236,10 @@ CFLAGS+= ${DEPEND_CFLAGS}
# all dependencies are correctly added or accounted for. This is mostly to
# ensure downstream uses of kernel-depend are handled.
beforebuild: kernel-depend
-.endif # ${MK_FAST_DEPEND} == "yes"
# Guess some dependencies for when no ${DEPENDFILE}.OBJ is generated yet.
# For meta+filemon the .meta file is checked for since it is the dependency
# file used.
-.if ${MK_FAST_DEPEND} == "yes"
.for __obj in ${DEPENDOBJS:O:u}
.if (defined(_meta_filemon) && !exists(${.OBJDIR}/${__obj}.meta)) || \
(!defined(_meta_filemon) && !exists(${.OBJDIR}/.depend.${__obj}))
@@ -276,32 +249,10 @@ ${__obj}: ${OBJS_DEPEND_GUESS}
${__obj}: ${OBJS_DEPEND_GUESS.${__obj}}
.endif
.endfor
-.endif
.NOPATH: .depend ${DEPENDFILES_OBJS}
.depend: .PRECIOUS ${SRCS}
-.if ${MK_FAST_DEPEND} == "no"
- rm -f ${.TARGET}.tmp
-# C files
- ${MAKE} -V CFILES_NORMAL -V SYSTEM_CFILES -V GEN_CFILES | \
- CC="${_MKDEPCC}" xargs mkdep -a -f ${.TARGET}.tmp ${CFLAGS}
- ${MAKE} -V CFILES_CDDL | \
- CC="${_MKDEPCC}" xargs mkdep -a -f ${.TARGET}.tmp ${ZFS_CFLAGS} \
- ${FBT_CFLAGS} ${DTRACE_CFLAGS}
- ${MAKE} -V CFILES_LINUXKPI | \
- CC="${_MKDEPCC}" xargs mkdep -a -f ${.TARGET}.tmp \
- ${CFLAGS} ${LINUXKPI_INCLUDES}
- ${MAKE} -V CFILES_OFED -V CFILES_MLX5 | \
- CC="${_MKDEPCC}" xargs mkdep -a -f ${.TARGET}.tmp \
- ${CFLAGS} ${OFEDINCLUDES}
-# Assembly files
- ${MAKE} -V SFILES_NORMAL | \
- CC="${_MKDEPCC}" xargs mkdep -a -f ${.TARGET}.tmp ${ASM_CFLAGS}
- ${MAKE} -V SFILES_CDDL | \
- CC="${_MKDEPCC}" xargs mkdep -a -f ${.TARGET}.tmp ${ZFS_ASM_CFLAGS}
- mv ${.TARGET}.tmp ${.TARGET}
-.endif
_ILINKS= machine
.if ${MACHINE} != ${MACHINE_CPUARCH} && ${MACHINE} != "arm64"
diff --git a/sys/conf/kern.pre.mk b/sys/conf/kern.pre.mk
index cf6ec10..591c988 100644
--- a/sys/conf/kern.pre.mk
+++ b/sys/conf/kern.pre.mk
@@ -64,29 +64,6 @@ NOSTDINC= -nostdinc
INCLUDES= ${NOSTDINC} ${INCLMAGIC} -I. -I$S
-.if ${MK_FAST_DEPEND} == "no" && (make(depend) || make(kernel-depend))
-
-# This hack lets us use the ipfilter code without spamming a new
-# include path into contrib'ed source files.
-INCLUDES+= -I$S/contrib/ipfilter
-
-# ... and the same for ath
-INCLUDES+= -I$S/dev/ath -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal
-
-# ... and the same for the NgATM stuff
-INCLUDES+= -I$S/contrib/ngatm
-
-# ... and the same for vchiq
-INCLUDES+= -I$S/contrib/vchiq
-
-# ... and the same for twa
-INCLUDES+= -I$S/dev/twa
-
-# ... and the same for cxgb and cxgbe
-INCLUDES+= -I$S/dev/cxgb -I$S/dev/cxgbe
-
-.endif
-
CFLAGS= ${COPTFLAGS} ${DEBUG}
CFLAGS+= ${INCLUDES} -D_KERNEL -DHAVE_KERNEL_OPTION_HEADERS -include opt_global.h
CFLAGS_PARAM_INLINE_UNIT_GROWTH?=100
diff --git a/sys/conf/kmod.mk b/sys/conf/kmod.mk
index 6a3e1eb..9e6b06c 100644
--- a/sys/conf/kmod.mk
+++ b/sys/conf/kmod.mk
@@ -458,11 +458,6 @@ cleanilinks:
OBJS_DEPEND_GUESS+= ${SRCS:M*.h}
.include <bsd.dep.mk>
-
-.if ${MK_FAST_DEPEND} == "no" && !exists(${.OBJDIR}/${DEPENDFILE})
-${OBJS}: ${OBJS_DEPEND_GUESS}
-.endif
-
.include <bsd.clang-analyze.mk>
.include <bsd.obj.mk>
.include "kern.mk"
diff --git a/sys/contrib/cloudabi/cloudabi64_types.h b/sys/contrib/cloudabi/cloudabi64_types.h
new file mode 100644
index 0000000..88babaa
--- /dev/null
+++ b/sys/contrib/cloudabi/cloudabi64_types.h
@@ -0,0 +1,225 @@
+// Copyright (c) 2016 Nuxi (https://nuxi.nl/) and contributors.
+//
+// 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 file is automatically generated. Do not edit.
+//
+// Source: https://github.com/NuxiNL/cloudabi
+
+#ifndef CLOUDABI64_TYPES_H
+#define CLOUDABI64_TYPES_H
+
+#include "cloudabi_types_common.h"
+
+typedef struct {
+ _Alignas(4) cloudabi_auxtype_t a_type;
+ union {
+ _Alignas(8) uint64_t a_val;
+ _Alignas(8) uint64_t a_ptr;
+ };
+} cloudabi64_auxv_t;
+_Static_assert(offsetof(cloudabi64_auxv_t, a_type) == 0, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_auxv_t, a_val) == 8, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_auxv_t, a_ptr) == 8, "Incorrect layout");
+_Static_assert(sizeof(cloudabi64_auxv_t) == 16, "Incorrect layout");
+_Static_assert(_Alignof(cloudabi64_auxv_t) == 8, "Incorrect layout");
+
+typedef struct {
+ _Alignas(8) uint64_t iov_base;
+ _Alignas(8) uint64_t iov_len;
+} cloudabi64_ciovec_t;
+_Static_assert(offsetof(cloudabi64_ciovec_t, iov_base) == 0, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_ciovec_t, iov_len) == 8, "Incorrect layout");
+_Static_assert(sizeof(cloudabi64_ciovec_t) == 16, "Incorrect layout");
+_Static_assert(_Alignof(cloudabi64_ciovec_t) == 8, "Incorrect layout");
+
+typedef struct {
+ _Alignas(8) cloudabi_userdata_t userdata;
+ _Alignas(2) cloudabi_errno_t error;
+ _Alignas(1) cloudabi_eventtype_t type;
+ union {
+ struct {
+ _Alignas(8) cloudabi_userdata_t identifier;
+ } clock;
+ struct {
+ _Alignas(8) uint64_t condvar;
+ } condvar;
+ struct {
+ _Alignas(8) cloudabi_filesize_t nbytes;
+ _Alignas(4) cloudabi_fd_t fd;
+ _Alignas(2) cloudabi_eventrwflags_t flags;
+ } fd_readwrite;
+ struct {
+ _Alignas(8) uint64_t lock;
+ } lock;
+ struct {
+ _Alignas(4) cloudabi_fd_t fd;
+ _Alignas(1) cloudabi_signal_t signal;
+ _Alignas(4) cloudabi_exitcode_t exitcode;
+ } proc_terminate;
+ };
+} cloudabi64_event_t;
+_Static_assert(offsetof(cloudabi64_event_t, userdata) == 0, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_event_t, error) == 8, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_event_t, type) == 10, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_event_t, clock.identifier) == 16, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_event_t, condvar.condvar) == 16, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_event_t, fd_readwrite.nbytes) == 16, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_event_t, fd_readwrite.fd) == 24, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_event_t, fd_readwrite.flags) == 28, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_event_t, lock.lock) == 16, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_event_t, proc_terminate.fd) == 16, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_event_t, proc_terminate.signal) == 20, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_event_t, proc_terminate.exitcode) == 24, "Incorrect layout");
+_Static_assert(sizeof(cloudabi64_event_t) == 32, "Incorrect layout");
+_Static_assert(_Alignof(cloudabi64_event_t) == 8, "Incorrect layout");
+
+typedef struct {
+ _Alignas(8) uint64_t iov_base;
+ _Alignas(8) uint64_t iov_len;
+} cloudabi64_iovec_t;
+_Static_assert(offsetof(cloudabi64_iovec_t, iov_base) == 0, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_iovec_t, iov_len) == 8, "Incorrect layout");
+_Static_assert(sizeof(cloudabi64_iovec_t) == 16, "Incorrect layout");
+_Static_assert(_Alignof(cloudabi64_iovec_t) == 8, "Incorrect layout");
+
+typedef void cloudabi64_processentry_t(uint64_t auxv);
+
+typedef struct {
+ _Alignas(8) uint64_t ri_data;
+ _Alignas(8) uint64_t ri_datalen;
+ _Alignas(8) uint64_t ri_fds;
+ _Alignas(8) uint64_t ri_fdslen;
+ _Alignas(2) cloudabi_msgflags_t ri_flags;
+} cloudabi64_recv_in_t;
+_Static_assert(offsetof(cloudabi64_recv_in_t, ri_data) == 0, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_recv_in_t, ri_datalen) == 8, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_recv_in_t, ri_fds) == 16, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_recv_in_t, ri_fdslen) == 24, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_recv_in_t, ri_flags) == 32, "Incorrect layout");
+_Static_assert(sizeof(cloudabi64_recv_in_t) == 40, "Incorrect layout");
+_Static_assert(_Alignof(cloudabi64_recv_in_t) == 8, "Incorrect layout");
+
+typedef struct {
+ _Alignas(8) uint64_t si_data;
+ _Alignas(8) uint64_t si_datalen;
+ _Alignas(8) uint64_t si_fds;
+ _Alignas(8) uint64_t si_fdslen;
+ _Alignas(2) cloudabi_msgflags_t si_flags;
+} cloudabi64_send_in_t;
+_Static_assert(offsetof(cloudabi64_send_in_t, si_data) == 0, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_send_in_t, si_datalen) == 8, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_send_in_t, si_fds) == 16, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_send_in_t, si_fdslen) == 24, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_send_in_t, si_flags) == 32, "Incorrect layout");
+_Static_assert(sizeof(cloudabi64_send_in_t) == 40, "Incorrect layout");
+_Static_assert(_Alignof(cloudabi64_send_in_t) == 8, "Incorrect layout");
+
+typedef struct {
+ _Alignas(8) uint64_t so_datalen;
+} cloudabi64_send_out_t;
+_Static_assert(offsetof(cloudabi64_send_out_t, so_datalen) == 0, "Incorrect layout");
+_Static_assert(sizeof(cloudabi64_send_out_t) == 8, "Incorrect layout");
+_Static_assert(_Alignof(cloudabi64_send_out_t) == 8, "Incorrect layout");
+
+typedef struct {
+ _Alignas(8) cloudabi_userdata_t userdata;
+ _Alignas(2) cloudabi_subflags_t flags;
+ _Alignas(1) cloudabi_eventtype_t type;
+ union {
+ struct {
+ _Alignas(8) cloudabi_userdata_t identifier;
+ _Alignas(4) cloudabi_clockid_t clock_id;
+ _Alignas(8) cloudabi_timestamp_t timeout;
+ _Alignas(8) cloudabi_timestamp_t precision;
+ _Alignas(2) cloudabi_subclockflags_t flags;
+ } clock;
+ struct {
+ _Alignas(8) uint64_t condvar;
+ _Alignas(8) uint64_t lock;
+ _Alignas(1) cloudabi_scope_t condvar_scope;
+ _Alignas(1) cloudabi_scope_t lock_scope;
+ } condvar;
+ struct {
+ _Alignas(4) cloudabi_fd_t fd;
+ _Alignas(2) cloudabi_subrwflags_t flags;
+ } fd_readwrite;
+ struct {
+ _Alignas(8) uint64_t lock;
+ _Alignas(1) cloudabi_scope_t lock_scope;
+ } lock;
+ struct {
+ _Alignas(4) cloudabi_fd_t fd;
+ } proc_terminate;
+ };
+} cloudabi64_subscription_t;
+_Static_assert(offsetof(cloudabi64_subscription_t, userdata) == 0, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_subscription_t, flags) == 8, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_subscription_t, type) == 10, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_subscription_t, clock.identifier) == 16, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_subscription_t, clock.clock_id) == 24, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_subscription_t, clock.timeout) == 32, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_subscription_t, clock.precision) == 40, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_subscription_t, clock.flags) == 48, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_subscription_t, condvar.condvar) == 16, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_subscription_t, condvar.lock) == 24, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_subscription_t, condvar.condvar_scope) == 32, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_subscription_t, condvar.lock_scope) == 33, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_subscription_t, fd_readwrite.fd) == 16, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_subscription_t, fd_readwrite.flags) == 20, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_subscription_t, lock.lock) == 16, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_subscription_t, lock.lock_scope) == 24, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_subscription_t, proc_terminate.fd) == 16, "Incorrect layout");
+_Static_assert(sizeof(cloudabi64_subscription_t) == 56, "Incorrect layout");
+_Static_assert(_Alignof(cloudabi64_subscription_t) == 8, "Incorrect layout");
+
+typedef void cloudabi64_threadentry_t(cloudabi_tid_t tid, uint64_t aux);
+
+typedef struct {
+ _Alignas(8) uint64_t ro_datalen;
+ _Alignas(8) uint64_t ro_fdslen;
+ _Alignas(2) cloudabi_sockaddr_t ro_sockname;
+ _Alignas(2) cloudabi_sockaddr_t ro_peername;
+ _Alignas(2) cloudabi_msgflags_t ro_flags;
+} cloudabi64_recv_out_t;
+_Static_assert(offsetof(cloudabi64_recv_out_t, ro_datalen) == 0, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_recv_out_t, ro_fdslen) == 8, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_recv_out_t, ro_sockname) == 16, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_recv_out_t, ro_peername) == 36, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_recv_out_t, ro_flags) == 56, "Incorrect layout");
+_Static_assert(sizeof(cloudabi64_recv_out_t) == 64, "Incorrect layout");
+_Static_assert(_Alignof(cloudabi64_recv_out_t) == 8, "Incorrect layout");
+
+typedef struct {
+ _Alignas(8) uint64_t entry_point;
+ _Alignas(8) uint64_t stack;
+ _Alignas(8) uint64_t stack_size;
+ _Alignas(8) uint64_t argument;
+} cloudabi64_threadattr_t;
+_Static_assert(offsetof(cloudabi64_threadattr_t, entry_point) == 0, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_threadattr_t, stack) == 8, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_threadattr_t, stack_size) == 16, "Incorrect layout");
+_Static_assert(offsetof(cloudabi64_threadattr_t, argument) == 24, "Incorrect layout");
+_Static_assert(sizeof(cloudabi64_threadattr_t) == 32, "Incorrect layout");
+_Static_assert(_Alignof(cloudabi64_threadattr_t) == 8, "Incorrect layout");
+
+#endif
diff --git a/sys/contrib/cloudabi/cloudabi_types_common.h b/sys/contrib/cloudabi/cloudabi_types_common.h
new file mode 100644
index 0000000..83c61b9
--- /dev/null
+++ b/sys/contrib/cloudabi/cloudabi_types_common.h
@@ -0,0 +1,463 @@
+// Copyright (c) 2016 Nuxi (https://nuxi.nl/) and contributors.
+//
+// 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 file is automatically generated. Do not edit.
+//
+// Source: https://github.com/NuxiNL/cloudabi
+
+#ifndef CLOUDABI_TYPES_COMMON_H
+#define CLOUDABI_TYPES_COMMON_H
+
+#if defined(__FreeBSD__) && defined(_KERNEL)
+#include <sys/stdint.h>
+#elif defined(__linux__) && defined(__KERNEL__)
+#include <linux/types.h>
+#else
+#include <stddef.h>
+#include <stdint.h>
+#endif
+
+typedef uint8_t cloudabi_advice_t;
+#define CLOUDABI_ADVICE_DONTNEED 1
+#define CLOUDABI_ADVICE_NOREUSE 2
+#define CLOUDABI_ADVICE_NORMAL 3
+#define CLOUDABI_ADVICE_RANDOM 4
+#define CLOUDABI_ADVICE_SEQUENTIAL 5
+#define CLOUDABI_ADVICE_WILLNEED 6
+
+typedef uint32_t cloudabi_auxtype_t;
+#define CLOUDABI_AT_ARGDATA 256
+#define CLOUDABI_AT_ARGDATALEN 257
+#define CLOUDABI_AT_BASE 7
+#define CLOUDABI_AT_CANARY 258
+#define CLOUDABI_AT_CANARYLEN 259
+#define CLOUDABI_AT_NCPUS 260
+#define CLOUDABI_AT_NULL 0
+#define CLOUDABI_AT_PAGESZ 6
+#define CLOUDABI_AT_PHDR 3
+#define CLOUDABI_AT_PHNUM 4
+#define CLOUDABI_AT_TID 261
+
+typedef uint32_t cloudabi_backlog_t;
+
+typedef uint32_t cloudabi_clockid_t;
+#define CLOUDABI_CLOCK_MONOTONIC 1
+#define CLOUDABI_CLOCK_PROCESS_CPUTIME_ID 2
+#define CLOUDABI_CLOCK_REALTIME 3
+#define CLOUDABI_CLOCK_THREAD_CPUTIME_ID 4
+
+typedef uint32_t cloudabi_condvar_t;
+#define CLOUDABI_CONDVAR_HAS_NO_WAITERS 0
+
+typedef uint64_t cloudabi_device_t;
+
+typedef uint64_t cloudabi_dircookie_t;
+#define CLOUDABI_DIRCOOKIE_START 0
+
+typedef uint16_t cloudabi_errno_t;
+#define CLOUDABI_E2BIG 1
+#define CLOUDABI_EACCES 2
+#define CLOUDABI_EADDRINUSE 3
+#define CLOUDABI_EADDRNOTAVAIL 4
+#define CLOUDABI_EAFNOSUPPORT 5
+#define CLOUDABI_EAGAIN 6
+#define CLOUDABI_EALREADY 7
+#define CLOUDABI_EBADF 8
+#define CLOUDABI_EBADMSG 9
+#define CLOUDABI_EBUSY 10
+#define CLOUDABI_ECANCELED 11
+#define CLOUDABI_ECHILD 12
+#define CLOUDABI_ECONNABORTED 13
+#define CLOUDABI_ECONNREFUSED 14
+#define CLOUDABI_ECONNRESET 15
+#define CLOUDABI_EDEADLK 16
+#define CLOUDABI_EDESTADDRREQ 17
+#define CLOUDABI_EDOM 18
+#define CLOUDABI_EDQUOT 19
+#define CLOUDABI_EEXIST 20
+#define CLOUDABI_EFAULT 21
+#define CLOUDABI_EFBIG 22
+#define CLOUDABI_EHOSTUNREACH 23
+#define CLOUDABI_EIDRM 24
+#define CLOUDABI_EILSEQ 25
+#define CLOUDABI_EINPROGRESS 26
+#define CLOUDABI_EINTR 27
+#define CLOUDABI_EINVAL 28
+#define CLOUDABI_EIO 29
+#define CLOUDABI_EISCONN 30
+#define CLOUDABI_EISDIR 31
+#define CLOUDABI_ELOOP 32
+#define CLOUDABI_EMFILE 33
+#define CLOUDABI_EMLINK 34
+#define CLOUDABI_EMSGSIZE 35
+#define CLOUDABI_EMULTIHOP 36
+#define CLOUDABI_ENAMETOOLONG 37
+#define CLOUDABI_ENETDOWN 38
+#define CLOUDABI_ENETRESET 39
+#define CLOUDABI_ENETUNREACH 40
+#define CLOUDABI_ENFILE 41
+#define CLOUDABI_ENOBUFS 42
+#define CLOUDABI_ENODEV 43
+#define CLOUDABI_ENOENT 44
+#define CLOUDABI_ENOEXEC 45
+#define CLOUDABI_ENOLCK 46
+#define CLOUDABI_ENOLINK 47
+#define CLOUDABI_ENOMEM 48
+#define CLOUDABI_ENOMSG 49
+#define CLOUDABI_ENOPROTOOPT 50
+#define CLOUDABI_ENOSPC 51
+#define CLOUDABI_ENOSYS 52
+#define CLOUDABI_ENOTCONN 53
+#define CLOUDABI_ENOTDIR 54
+#define CLOUDABI_ENOTEMPTY 55
+#define CLOUDABI_ENOTRECOVERABLE 56
+#define CLOUDABI_ENOTSOCK 57
+#define CLOUDABI_ENOTSUP 58
+#define CLOUDABI_ENOTTY 59
+#define CLOUDABI_ENXIO 60
+#define CLOUDABI_EOVERFLOW 61
+#define CLOUDABI_EOWNERDEAD 62
+#define CLOUDABI_EPERM 63
+#define CLOUDABI_EPIPE 64
+#define CLOUDABI_EPROTO 65
+#define CLOUDABI_EPROTONOSUPPORT 66
+#define CLOUDABI_EPROTOTYPE 67
+#define CLOUDABI_ERANGE 68
+#define CLOUDABI_EROFS 69
+#define CLOUDABI_ESPIPE 70
+#define CLOUDABI_ESRCH 71
+#define CLOUDABI_ESTALE 72
+#define CLOUDABI_ETIMEDOUT 73
+#define CLOUDABI_ETXTBSY 74
+#define CLOUDABI_EXDEV 75
+#define CLOUDABI_ENOTCAPABLE 76
+
+typedef uint16_t cloudabi_eventrwflags_t;
+#define CLOUDABI_EVENT_FD_READWRITE_HANGUP 0x0001
+
+typedef uint8_t cloudabi_eventtype_t;
+#define CLOUDABI_EVENTTYPE_CLOCK 1
+#define CLOUDABI_EVENTTYPE_CONDVAR 2
+#define CLOUDABI_EVENTTYPE_FD_READ 3
+#define CLOUDABI_EVENTTYPE_FD_WRITE 4
+#define CLOUDABI_EVENTTYPE_LOCK_RDLOCK 5
+#define CLOUDABI_EVENTTYPE_LOCK_WRLOCK 6
+#define CLOUDABI_EVENTTYPE_PROC_TERMINATE 7
+
+typedef uint32_t cloudabi_exitcode_t;
+
+typedef uint32_t cloudabi_fd_t;
+#define CLOUDABI_PROCESS_CHILD 0xffffffff
+#define CLOUDABI_MAP_ANON_FD 0xffffffff
+
+typedef uint16_t cloudabi_fdflags_t;
+#define CLOUDABI_FDFLAG_APPEND 0x0001
+#define CLOUDABI_FDFLAG_DSYNC 0x0002
+#define CLOUDABI_FDFLAG_NONBLOCK 0x0004
+#define CLOUDABI_FDFLAG_RSYNC 0x0008
+#define CLOUDABI_FDFLAG_SYNC 0x0010
+
+typedef uint16_t cloudabi_fdsflags_t;
+#define CLOUDABI_FDSTAT_FLAGS 0x0001
+#define CLOUDABI_FDSTAT_RIGHTS 0x0002
+
+typedef int64_t cloudabi_filedelta_t;
+
+typedef uint64_t cloudabi_filesize_t;
+
+typedef uint8_t cloudabi_filetype_t;
+#define CLOUDABI_FILETYPE_UNKNOWN 0
+#define CLOUDABI_FILETYPE_BLOCK_DEVICE 16
+#define CLOUDABI_FILETYPE_CHARACTER_DEVICE 17
+#define CLOUDABI_FILETYPE_DIRECTORY 32
+#define CLOUDABI_FILETYPE_FIFO 48
+#define CLOUDABI_FILETYPE_POLL 64
+#define CLOUDABI_FILETYPE_PROCESS 80
+#define CLOUDABI_FILETYPE_REGULAR_FILE 96
+#define CLOUDABI_FILETYPE_SHARED_MEMORY 112
+#define CLOUDABI_FILETYPE_SOCKET_DGRAM 128
+#define CLOUDABI_FILETYPE_SOCKET_SEQPACKET 129
+#define CLOUDABI_FILETYPE_SOCKET_STREAM 130
+#define CLOUDABI_FILETYPE_SYMBOLIC_LINK 144
+
+typedef uint16_t cloudabi_fsflags_t;
+#define CLOUDABI_FILESTAT_ATIM 0x0001
+#define CLOUDABI_FILESTAT_ATIM_NOW 0x0002
+#define CLOUDABI_FILESTAT_MTIM 0x0004
+#define CLOUDABI_FILESTAT_MTIM_NOW 0x0008
+#define CLOUDABI_FILESTAT_SIZE 0x0010
+
+typedef uint64_t cloudabi_inode_t;
+
+typedef uint32_t cloudabi_linkcount_t;
+
+typedef uint32_t cloudabi_lock_t;
+#define CLOUDABI_LOCK_UNLOCKED 0x00000000
+#define CLOUDABI_LOCK_WRLOCKED 0x40000000
+#define CLOUDABI_LOCK_KERNEL_MANAGED 0x80000000
+#define CLOUDABI_LOCK_BOGUS 0x80000000
+
+typedef uint32_t cloudabi_lookupflags_t;
+#define CLOUDABI_LOOKUP_SYMLINK_FOLLOW 0x00000001
+
+typedef uint8_t cloudabi_mflags_t;
+#define CLOUDABI_MAP_ANON 0x01
+#define CLOUDABI_MAP_FIXED 0x02
+#define CLOUDABI_MAP_PRIVATE 0x04
+#define CLOUDABI_MAP_SHARED 0x08
+
+typedef uint8_t cloudabi_mprot_t;
+#define CLOUDABI_PROT_EXEC 0x01
+#define CLOUDABI_PROT_WRITE 0x02
+#define CLOUDABI_PROT_READ 0x04
+
+typedef uint8_t cloudabi_msflags_t;
+#define CLOUDABI_MS_ASYNC 0x01
+#define CLOUDABI_MS_INVALIDATE 0x02
+#define CLOUDABI_MS_SYNC 0x04
+
+typedef uint16_t cloudabi_msgflags_t;
+#define CLOUDABI_MSG_CTRUNC 0x0001
+#define CLOUDABI_MSG_EOR 0x0002
+#define CLOUDABI_MSG_PEEK 0x0004
+#define CLOUDABI_MSG_TRUNC 0x0008
+#define CLOUDABI_MSG_WAITALL 0x0010
+
+typedef uint32_t cloudabi_nthreads_t;
+
+typedef uint16_t cloudabi_oflags_t;
+#define CLOUDABI_O_CREAT 0x0001
+#define CLOUDABI_O_DIRECTORY 0x0002
+#define CLOUDABI_O_EXCL 0x0004
+#define CLOUDABI_O_TRUNC 0x0008
+
+typedef uint64_t cloudabi_rights_t;
+#define CLOUDABI_RIGHT_FD_DATASYNC 0x0000000000000001
+#define CLOUDABI_RIGHT_FD_READ 0x0000000000000002
+#define CLOUDABI_RIGHT_FD_SEEK 0x0000000000000004
+#define CLOUDABI_RIGHT_FD_STAT_PUT_FLAGS 0x0000000000000008
+#define CLOUDABI_RIGHT_FD_SYNC 0x0000000000000010
+#define CLOUDABI_RIGHT_FD_TELL 0x0000000000000020
+#define CLOUDABI_RIGHT_FD_WRITE 0x0000000000000040
+#define CLOUDABI_RIGHT_FILE_ADVISE 0x0000000000000080
+#define CLOUDABI_RIGHT_FILE_ALLOCATE 0x0000000000000100
+#define CLOUDABI_RIGHT_FILE_CREATE_DIRECTORY 0x0000000000000200
+#define CLOUDABI_RIGHT_FILE_CREATE_FILE 0x0000000000000400
+#define CLOUDABI_RIGHT_FILE_CREATE_FIFO 0x0000000000000800
+#define CLOUDABI_RIGHT_FILE_LINK_SOURCE 0x0000000000001000
+#define CLOUDABI_RIGHT_FILE_LINK_TARGET 0x0000000000002000
+#define CLOUDABI_RIGHT_FILE_OPEN 0x0000000000004000
+#define CLOUDABI_RIGHT_FILE_READDIR 0x0000000000008000
+#define CLOUDABI_RIGHT_FILE_READLINK 0x0000000000010000
+#define CLOUDABI_RIGHT_FILE_RENAME_SOURCE 0x0000000000020000
+#define CLOUDABI_RIGHT_FILE_RENAME_TARGET 0x0000000000040000
+#define CLOUDABI_RIGHT_FILE_STAT_FGET 0x0000000000080000
+#define CLOUDABI_RIGHT_FILE_STAT_FPUT_SIZE 0x0000000000100000
+#define CLOUDABI_RIGHT_FILE_STAT_FPUT_TIMES 0x0000000000200000
+#define CLOUDABI_RIGHT_FILE_STAT_GET 0x0000000000400000
+#define CLOUDABI_RIGHT_FILE_STAT_PUT_TIMES 0x0000000000800000
+#define CLOUDABI_RIGHT_FILE_SYMLINK 0x0000000001000000
+#define CLOUDABI_RIGHT_FILE_UNLINK 0x0000000002000000
+#define CLOUDABI_RIGHT_MEM_MAP 0x0000000004000000
+#define CLOUDABI_RIGHT_MEM_MAP_EXEC 0x0000000008000000
+#define CLOUDABI_RIGHT_POLL_FD_READWRITE 0x0000000010000000
+#define CLOUDABI_RIGHT_POLL_MODIFY 0x0000000020000000
+#define CLOUDABI_RIGHT_POLL_PROC_TERMINATE 0x0000000040000000
+#define CLOUDABI_RIGHT_POLL_WAIT 0x0000000080000000
+#define CLOUDABI_RIGHT_PROC_EXEC 0x0000000100000000
+#define CLOUDABI_RIGHT_SOCK_ACCEPT 0x0000000200000000
+#define CLOUDABI_RIGHT_SOCK_BIND_DIRECTORY 0x0000000400000000
+#define CLOUDABI_RIGHT_SOCK_BIND_SOCKET 0x0000000800000000
+#define CLOUDABI_RIGHT_SOCK_CONNECT_DIRECTORY 0x0000001000000000
+#define CLOUDABI_RIGHT_SOCK_CONNECT_SOCKET 0x0000002000000000
+#define CLOUDABI_RIGHT_SOCK_LISTEN 0x0000004000000000
+#define CLOUDABI_RIGHT_SOCK_SHUTDOWN 0x0000008000000000
+#define CLOUDABI_RIGHT_SOCK_STAT_GET 0x0000010000000000
+
+typedef uint8_t cloudabi_sa_family_t;
+#define CLOUDABI_AF_UNSPEC 0
+#define CLOUDABI_AF_INET 1
+#define CLOUDABI_AF_INET6 2
+#define CLOUDABI_AF_UNIX 3
+
+typedef uint8_t cloudabi_scope_t;
+#define CLOUDABI_SCOPE_PRIVATE 4
+#define CLOUDABI_SCOPE_SHARED 8
+
+typedef uint8_t cloudabi_sdflags_t;
+#define CLOUDABI_SHUT_RD 0x01
+#define CLOUDABI_SHUT_WR 0x02
+
+typedef uint8_t cloudabi_signal_t;
+#define CLOUDABI_SIGABRT 1
+#define CLOUDABI_SIGALRM 2
+#define CLOUDABI_SIGBUS 3
+#define CLOUDABI_SIGCHLD 4
+#define CLOUDABI_SIGCONT 5
+#define CLOUDABI_SIGFPE 6
+#define CLOUDABI_SIGHUP 7
+#define CLOUDABI_SIGILL 8
+#define CLOUDABI_SIGINT 9
+#define CLOUDABI_SIGKILL 10
+#define CLOUDABI_SIGPIPE 11
+#define CLOUDABI_SIGQUIT 12
+#define CLOUDABI_SIGSEGV 13
+#define CLOUDABI_SIGSTOP 14
+#define CLOUDABI_SIGSYS 15
+#define CLOUDABI_SIGTERM 16
+#define CLOUDABI_SIGTRAP 17
+#define CLOUDABI_SIGTSTP 18
+#define CLOUDABI_SIGTTIN 19
+#define CLOUDABI_SIGTTOU 20
+#define CLOUDABI_SIGURG 21
+#define CLOUDABI_SIGUSR1 22
+#define CLOUDABI_SIGUSR2 23
+#define CLOUDABI_SIGVTALRM 24
+#define CLOUDABI_SIGXCPU 25
+#define CLOUDABI_SIGXFSZ 26
+
+typedef uint8_t cloudabi_ssflags_t;
+#define CLOUDABI_SOCKSTAT_CLEAR_ERROR 0x01
+
+typedef uint32_t cloudabi_sstate_t;
+#define CLOUDABI_SOCKSTATE_ACCEPTCONN 0x00000001
+
+typedef uint16_t cloudabi_subclockflags_t;
+#define CLOUDABI_SUBSCRIPTION_CLOCK_ABSTIME 0x0001
+
+typedef uint16_t cloudabi_subflags_t;
+#define CLOUDABI_SUBSCRIPTION_ADD 0x0001
+#define CLOUDABI_SUBSCRIPTION_CLEAR 0x0002
+#define CLOUDABI_SUBSCRIPTION_DELETE 0x0004
+#define CLOUDABI_SUBSCRIPTION_DISABLE 0x0008
+#define CLOUDABI_SUBSCRIPTION_ENABLE 0x0010
+#define CLOUDABI_SUBSCRIPTION_ONESHOT 0x0020
+
+typedef uint16_t cloudabi_subrwflags_t;
+#define CLOUDABI_SUBSCRIPTION_FD_READWRITE_POLL 0x0001
+
+typedef uint32_t cloudabi_tid_t;
+
+typedef uint64_t cloudabi_timestamp_t;
+
+typedef uint8_t cloudabi_ulflags_t;
+#define CLOUDABI_UNLINK_REMOVEDIR 0x01
+
+typedef uint64_t cloudabi_userdata_t;
+
+typedef uint8_t cloudabi_whence_t;
+#define CLOUDABI_WHENCE_CUR 1
+#define CLOUDABI_WHENCE_END 2
+#define CLOUDABI_WHENCE_SET 3
+
+typedef struct {
+ _Alignas(8) cloudabi_dircookie_t d_next;
+ _Alignas(8) cloudabi_inode_t d_ino;
+ _Alignas(4) uint32_t d_namlen;
+ _Alignas(1) cloudabi_filetype_t d_type;
+} cloudabi_dirent_t;
+_Static_assert(offsetof(cloudabi_dirent_t, d_next) == 0, "Incorrect layout");
+_Static_assert(offsetof(cloudabi_dirent_t, d_ino) == 8, "Incorrect layout");
+_Static_assert(offsetof(cloudabi_dirent_t, d_namlen) == 16, "Incorrect layout");
+_Static_assert(offsetof(cloudabi_dirent_t, d_type) == 20, "Incorrect layout");
+_Static_assert(sizeof(cloudabi_dirent_t) == 24, "Incorrect layout");
+_Static_assert(_Alignof(cloudabi_dirent_t) == 8, "Incorrect layout");
+
+typedef struct {
+ _Alignas(1) cloudabi_filetype_t fs_filetype;
+ _Alignas(2) cloudabi_fdflags_t fs_flags;
+ _Alignas(8) cloudabi_rights_t fs_rights_base;
+ _Alignas(8) cloudabi_rights_t fs_rights_inheriting;
+} cloudabi_fdstat_t;
+_Static_assert(offsetof(cloudabi_fdstat_t, fs_filetype) == 0, "Incorrect layout");
+_Static_assert(offsetof(cloudabi_fdstat_t, fs_flags) == 2, "Incorrect layout");
+_Static_assert(offsetof(cloudabi_fdstat_t, fs_rights_base) == 8, "Incorrect layout");
+_Static_assert(offsetof(cloudabi_fdstat_t, fs_rights_inheriting) == 16, "Incorrect layout");
+_Static_assert(sizeof(cloudabi_fdstat_t) == 24, "Incorrect layout");
+_Static_assert(_Alignof(cloudabi_fdstat_t) == 8, "Incorrect layout");
+
+typedef struct {
+ _Alignas(8) cloudabi_device_t st_dev;
+ _Alignas(8) cloudabi_inode_t st_ino;
+ _Alignas(1) cloudabi_filetype_t st_filetype;
+ _Alignas(4) cloudabi_linkcount_t st_nlink;
+ _Alignas(8) cloudabi_filesize_t st_size;
+ _Alignas(8) cloudabi_timestamp_t st_atim;
+ _Alignas(8) cloudabi_timestamp_t st_mtim;
+ _Alignas(8) cloudabi_timestamp_t st_ctim;
+} cloudabi_filestat_t;
+_Static_assert(offsetof(cloudabi_filestat_t, st_dev) == 0, "Incorrect layout");
+_Static_assert(offsetof(cloudabi_filestat_t, st_ino) == 8, "Incorrect layout");
+_Static_assert(offsetof(cloudabi_filestat_t, st_filetype) == 16, "Incorrect layout");
+_Static_assert(offsetof(cloudabi_filestat_t, st_nlink) == 20, "Incorrect layout");
+_Static_assert(offsetof(cloudabi_filestat_t, st_size) == 24, "Incorrect layout");
+_Static_assert(offsetof(cloudabi_filestat_t, st_atim) == 32, "Incorrect layout");
+_Static_assert(offsetof(cloudabi_filestat_t, st_mtim) == 40, "Incorrect layout");
+_Static_assert(offsetof(cloudabi_filestat_t, st_ctim) == 48, "Incorrect layout");
+_Static_assert(sizeof(cloudabi_filestat_t) == 56, "Incorrect layout");
+_Static_assert(_Alignof(cloudabi_filestat_t) == 8, "Incorrect layout");
+
+typedef struct {
+ _Alignas(4) cloudabi_fd_t fd;
+ _Alignas(4) cloudabi_lookupflags_t flags;
+} cloudabi_lookup_t;
+_Static_assert(offsetof(cloudabi_lookup_t, fd) == 0, "Incorrect layout");
+_Static_assert(offsetof(cloudabi_lookup_t, flags) == 4, "Incorrect layout");
+_Static_assert(sizeof(cloudabi_lookup_t) == 8, "Incorrect layout");
+_Static_assert(_Alignof(cloudabi_lookup_t) == 4, "Incorrect layout");
+
+typedef struct {
+ _Alignas(1) cloudabi_sa_family_t sa_family;
+ union {
+ struct {
+ _Alignas(1) uint8_t addr[4];
+ _Alignas(2) uint16_t port;
+ } sa_inet;
+ struct {
+ _Alignas(1) uint8_t addr[16];
+ _Alignas(2) uint16_t port;
+ } sa_inet6;
+ };
+} cloudabi_sockaddr_t;
+_Static_assert(offsetof(cloudabi_sockaddr_t, sa_family) == 0, "Incorrect layout");
+_Static_assert(offsetof(cloudabi_sockaddr_t, sa_inet.addr) == 2, "Incorrect layout");
+_Static_assert(offsetof(cloudabi_sockaddr_t, sa_inet.port) == 6, "Incorrect layout");
+_Static_assert(offsetof(cloudabi_sockaddr_t, sa_inet6.addr) == 2, "Incorrect layout");
+_Static_assert(offsetof(cloudabi_sockaddr_t, sa_inet6.port) == 18, "Incorrect layout");
+_Static_assert(sizeof(cloudabi_sockaddr_t) == 20, "Incorrect layout");
+_Static_assert(_Alignof(cloudabi_sockaddr_t) == 2, "Incorrect layout");
+
+typedef struct {
+ _Alignas(2) cloudabi_sockaddr_t ss_sockname;
+ _Alignas(2) cloudabi_sockaddr_t ss_peername;
+ _Alignas(2) cloudabi_errno_t ss_error;
+ _Alignas(4) cloudabi_sstate_t ss_state;
+} cloudabi_sockstat_t;
+_Static_assert(offsetof(cloudabi_sockstat_t, ss_sockname) == 0, "Incorrect layout");
+_Static_assert(offsetof(cloudabi_sockstat_t, ss_peername) == 20, "Incorrect layout");
+_Static_assert(offsetof(cloudabi_sockstat_t, ss_error) == 40, "Incorrect layout");
+_Static_assert(offsetof(cloudabi_sockstat_t, ss_state) == 44, "Incorrect layout");
+_Static_assert(sizeof(cloudabi_sockstat_t) == 48, "Incorrect layout");
+_Static_assert(_Alignof(cloudabi_sockstat_t) == 4, "Incorrect layout");
+
+#endif
diff --git a/sys/contrib/cloudabi/syscalldefs_md.h b/sys/contrib/cloudabi/syscalldefs_md.h
deleted file mode 100644
index f2e3705..0000000
--- a/sys/contrib/cloudabi/syscalldefs_md.h
+++ /dev/null
@@ -1,255 +0,0 @@
-// Copyright (c) 2015 Nuxi, https://nuxi.nl/
-//
-// 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.
-
-// Machine dependent definitions.
-
-// Macro to force sane alignment rules.
-//
-// On x86-32 it is the case that 64-bit integers are 4-byte aligned when
-// embedded in structs, even though they are 8-byte aligned when not
-// embedded. Force 8-byte alignment explicitly.
-#define MEMBER(type) alignas(alignof(type)) type
-#define ASSERT_OFFSET(type, field, offset32, offset64) \
- static_assert((sizeof(PTR(void)) == 4 && \
- offsetof(IDENT(type), field) == (offset32)) || \
- (sizeof(PTR(void)) == 8 && \
- offsetof(IDENT(type), field) == (offset64)), \
- "Offset incorrect")
-#define ASSERT_SIZE(type, size32, size64) \
- static_assert( \
- (sizeof(PTR(void)) == 4 && sizeof(IDENT(type)) == (size32)) || \
- (sizeof(PTR(void)) == 8 && sizeof(IDENT(type)) == (size64)), \
- "Size incorrect")
-
-typedef void IDENT(threadentry_t)(cloudabi_tid_t, PTR(void));
-
-// Auxiliary vector entry, used to provide paramters on startup.
-typedef struct {
- uint32_t a_type;
- union {
- MEMBER(IDENT(size_t)) a_val;
- MEMBER(PTR(void)) a_ptr;
- };
-} IDENT(auxv_t);
-ASSERT_OFFSET(auxv_t, a_type, 0, 0);
-ASSERT_OFFSET(auxv_t, a_val, 4, 8);
-ASSERT_OFFSET(auxv_t, a_ptr, 4, 8);
-ASSERT_SIZE(auxv_t, 8, 16);
-
-typedef struct {
- MEMBER(PTR(const void)) iov_base;
- MEMBER(IDENT(size_t)) iov_len;
-} IDENT(ciovec_t);
-ASSERT_OFFSET(ciovec_t, iov_base, 0, 0);
-ASSERT_OFFSET(ciovec_t, iov_len, 4, 8);
-ASSERT_SIZE(ciovec_t, 8, 16);
-
-typedef struct {
- MEMBER(cloudabi_userdata_t) userdata;
- MEMBER(cloudabi_errno_t) error;
- MEMBER(cloudabi_eventtype_t) type;
- union {
- // CLOUDABI_EVENTTYPE_CLOCK: Wait until the value of a clock
- // exceeds a value.
- struct {
- MEMBER(cloudabi_userdata_t) identifier;
- } clock;
-
- // CLOUDABI_EVENTTYPE_CONDVAR: Release a lock and wait on a
- // condition variable.
- struct {
- MEMBER(PTR(_Atomic(cloudabi_condvar_t))) condvar;
- } condvar;
-
- // CLOUDABI_EVENTTYPE_FD_READ and CLOUDABI_EVENTTYPE_FD_WRITE:
- // Wait for a file descriptor to allow read() and write() to be
- // called without blocking.
- struct {
- MEMBER(cloudabi_filesize_t) nbytes;
- MEMBER(cloudabi_fd_t) fd;
- MEMBER(uint16_t) flags;
- } fd_readwrite;
-
- // CLOUDABI_EVENT_LOCK_RDLOCK and CLOUDABI_EVENT_LOCK_WRLOCK: Wait
- // and acquire a read or write lock.
- struct {
- MEMBER(PTR(_Atomic(cloudabi_lock_t))) lock;
- } lock;
-
- // CLOUDABI_EVENTTYPE_PROC_TERMINATE: Wait for a process to terminate.
- struct {
- MEMBER(cloudabi_fd_t) fd;
- MEMBER(cloudabi_signal_t) signal; // Non-zero if process got killed.
- MEMBER(cloudabi_exitcode_t) exitcode; // Exit code.
- } proc_terminate;
- };
-} IDENT(event_t);
-ASSERT_OFFSET(event_t, userdata, 0, 0);
-ASSERT_OFFSET(event_t, error, 8, 8);
-ASSERT_OFFSET(event_t, type, 10, 10);
-ASSERT_OFFSET(event_t, clock.identifier, 16, 16);
-ASSERT_OFFSET(event_t, condvar.condvar, 16, 16);
-ASSERT_OFFSET(event_t, fd_readwrite.nbytes, 16, 16);
-ASSERT_OFFSET(event_t, fd_readwrite.fd, 24, 24);
-ASSERT_OFFSET(event_t, fd_readwrite.flags, 28, 28);
-ASSERT_OFFSET(event_t, lock.lock, 16, 16);
-ASSERT_OFFSET(event_t, proc_terminate.fd, 16, 16);
-ASSERT_OFFSET(event_t, proc_terminate.signal, 20, 20);
-ASSERT_OFFSET(event_t, proc_terminate.exitcode, 24, 24);
-ASSERT_SIZE(event_t, 32, 32);
-
-typedef struct {
- MEMBER(PTR(void)) iov_base;
- MEMBER(IDENT(size_t)) iov_len;
-} IDENT(iovec_t);
-ASSERT_OFFSET(iovec_t, iov_base, 0, 0);
-ASSERT_OFFSET(iovec_t, iov_len, 4, 8);
-ASSERT_SIZE(iovec_t, 8, 16);
-
-typedef struct {
- MEMBER(PTR(const IDENT(iovec_t))) ri_data; // Data I/O vectors.
- MEMBER(IDENT(size_t)) ri_datalen; // Number of data I/O vectors.
- MEMBER(PTR(cloudabi_fd_t)) ri_fds; // File descriptors.
- MEMBER(IDENT(size_t)) ri_fdslen; // Number of file descriptors.
- MEMBER(cloudabi_msgflags_t) ri_flags; // Input flags.
-} IDENT(recv_in_t);
-ASSERT_OFFSET(recv_in_t, ri_data, 0, 0);
-ASSERT_OFFSET(recv_in_t, ri_datalen, 4, 8);
-ASSERT_OFFSET(recv_in_t, ri_fds, 8, 16);
-ASSERT_OFFSET(recv_in_t, ri_fdslen, 12, 24);
-ASSERT_OFFSET(recv_in_t, ri_flags, 16, 32);
-ASSERT_SIZE(recv_in_t, 20, 40);
-
-typedef struct {
- MEMBER(IDENT(size_t)) ro_datalen; // Bytes of data received.
- MEMBER(IDENT(size_t)) ro_fdslen; // Number of file descriptors received.
- MEMBER(cloudabi_sockaddr_t) ro_sockname; // Address of receiver.
- MEMBER(cloudabi_sockaddr_t) ro_peername; // Address of sender.
- MEMBER(cloudabi_msgflags_t) ro_flags; // Output flags.
-} IDENT(recv_out_t);
-ASSERT_OFFSET(recv_out_t, ro_datalen, 0, 0);
-ASSERT_OFFSET(recv_out_t, ro_fdslen, 4, 8);
-ASSERT_OFFSET(recv_out_t, ro_sockname, 8, 16);
-ASSERT_OFFSET(recv_out_t, ro_peername, 28, 36);
-ASSERT_OFFSET(recv_out_t, ro_flags, 48, 56);
-ASSERT_SIZE(recv_out_t, 52, 64);
-
-typedef struct {
- MEMBER(PTR(const IDENT(ciovec_t))) si_data; // Data I/O vectors.
- MEMBER(IDENT(size_t)) si_datalen; // Number of data I/O vectors.
- MEMBER(PTR(const cloudabi_fd_t)) si_fds; // File descriptors.
- MEMBER(IDENT(size_t)) si_fdslen; // Number of file descriptors.
- MEMBER(cloudabi_msgflags_t) si_flags; // Input flags.
-} IDENT(send_in_t);
-ASSERT_OFFSET(send_in_t, si_data, 0, 0);
-ASSERT_OFFSET(send_in_t, si_datalen, 4, 8);
-ASSERT_OFFSET(send_in_t, si_fds, 8, 16);
-ASSERT_OFFSET(send_in_t, si_fdslen, 12, 24);
-ASSERT_OFFSET(send_in_t, si_flags, 16, 32);
-ASSERT_SIZE(send_in_t, 20, 40);
-
-typedef struct {
- MEMBER(IDENT(size_t)) so_datalen; // Bytes of data sent.
-} IDENT(send_out_t);
-ASSERT_OFFSET(send_out_t, so_datalen, 0, 0);
-ASSERT_SIZE(send_out_t, 4, 8);
-
-typedef struct {
- MEMBER(cloudabi_userdata_t) userdata;
- MEMBER(uint16_t) flags;
- MEMBER(cloudabi_eventtype_t) type;
- union {
- // CLOUDABI_EVENTTYPE_CLOCK: Wait until the value of a clock
- // exceeds a value.
- struct {
- MEMBER(cloudabi_userdata_t) identifier;
- MEMBER(cloudabi_clockid_t) clock_id;
- MEMBER(cloudabi_timestamp_t) timeout;
- MEMBER(cloudabi_timestamp_t) precision;
- MEMBER(uint16_t) flags;
- } clock;
-
- // CLOUDABI_EVENTTYPE_CONDVAR: Release a lock and wait on a
- // condition variable.
- struct {
- MEMBER(PTR(_Atomic(cloudabi_condvar_t))) condvar;
- MEMBER(PTR(_Atomic(cloudabi_lock_t))) lock;
- MEMBER(cloudabi_mflags_t) condvar_scope;
- MEMBER(cloudabi_mflags_t) lock_scope;
- } condvar;
-
- // CLOUDABI_EVENTTYPE_FD_READ and CLOUDABI_EVENTTYPE_FD_WRITE:
- // Wait for a file descriptor to allow read() and write() to be
- // called without blocking.
- struct {
- MEMBER(cloudabi_fd_t) fd;
- MEMBER(uint16_t) flags;
- } fd_readwrite;
-
- // CLOUDABI_EVENT_LOCK_RDLOCK and CLOUDABI_EVENT_LOCK_WRLOCK: Wait
- // and acquire a read or write lock.
- struct {
- MEMBER(PTR(_Atomic(cloudabi_lock_t))) lock;
- MEMBER(cloudabi_mflags_t) lock_scope;
- } lock;
-
- // CLOUDABI_EVENTTYPE_PROC_TERMINATE: Wait for a process to terminate.
- struct {
- MEMBER(cloudabi_fd_t) fd;
- } proc_terminate;
- };
-} IDENT(subscription_t);
-ASSERT_OFFSET(subscription_t, userdata, 0, 0);
-ASSERT_OFFSET(subscription_t, flags, 8, 8);
-ASSERT_OFFSET(subscription_t, type, 10, 10);
-ASSERT_OFFSET(subscription_t, clock.identifier, 16, 16);
-ASSERT_OFFSET(subscription_t, clock.clock_id, 24, 24);
-ASSERT_OFFSET(subscription_t, clock.timeout, 32, 32);
-ASSERT_OFFSET(subscription_t, clock.precision, 40, 40);
-ASSERT_OFFSET(subscription_t, clock.flags, 48, 48);
-ASSERT_OFFSET(subscription_t, condvar.condvar, 16, 16);
-ASSERT_OFFSET(subscription_t, condvar.lock, 20, 24);
-ASSERT_OFFSET(subscription_t, condvar.condvar_scope, 24, 32);
-ASSERT_OFFSET(subscription_t, condvar.lock_scope, 25, 33);
-ASSERT_OFFSET(subscription_t, fd_readwrite.fd, 16, 16);
-ASSERT_OFFSET(subscription_t, fd_readwrite.flags, 20, 20);
-ASSERT_OFFSET(subscription_t, lock.lock, 16, 16);
-ASSERT_OFFSET(subscription_t, lock.lock_scope, 20, 24);
-ASSERT_OFFSET(subscription_t, proc_terminate.fd, 16, 16);
-ASSERT_SIZE(subscription_t, 56, 56);
-
-typedef struct {
- MEMBER(PTR(IDENT(threadentry_t))) entry_point; // Entry point.
- MEMBER(PTR(void)) stack; // Pointer to stack buffer.
- MEMBER(IDENT(size_t)) stack_size; // Size of stack buffer.
- MEMBER(PTR(void)) argument; // Argument to be passed to entry point.
-} IDENT(threadattr_t);
-ASSERT_OFFSET(threadattr_t, entry_point, 0, 0);
-ASSERT_OFFSET(threadattr_t, stack, 4, 8);
-ASSERT_OFFSET(threadattr_t, stack_size, 8, 16);
-ASSERT_OFFSET(threadattr_t, argument, 12, 24);
-ASSERT_SIZE(threadattr_t, 16, 32);
-
-#undef MEMBER
-#undef ASSERT_OFFSET
-#undef ASSERT_SIZE
diff --git a/sys/contrib/cloudabi/syscalldefs_mi.h b/sys/contrib/cloudabi/syscalldefs_mi.h
deleted file mode 100644
index adce208..0000000
--- a/sys/contrib/cloudabi/syscalldefs_mi.h
+++ /dev/null
@@ -1,476 +0,0 @@
-// Copyright (c) 2015 Nuxi, https://nuxi.nl/
-//
-// 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 COMMON_SYSCALLDEFS_MI_H
-#define COMMON_SYSCALLDEFS_MI_H
-
-// Machine independent definitions.
-
-// Socket address families.
-#define CLOUDABI_AF_UNSPEC 0
-#define CLOUDABI_AF_INET 1
-#define CLOUDABI_AF_INET6 2
-#define CLOUDABI_AF_UNIX 3
-
-// File and memory I/O advice.
-#define CLOUDABI_ADVICE_DONTNEED 1
-#define CLOUDABI_ADVICE_NOREUSE 2
-#define CLOUDABI_ADVICE_NORMAL 3
-#define CLOUDABI_ADVICE_RANDOM 4
-#define CLOUDABI_ADVICE_SEQUENTIAL 5
-#define CLOUDABI_ADVICE_WILLNEED 6
-
-// Auxiliary vector entries. All entries that are also part of the
-// x86-64 ABI use the same number. All extensions start at 256.
-#define CLOUDABI_AT_ARGDATA 256
-#define CLOUDABI_AT_ARGDATALEN 257
-#define CLOUDABI_AT_CANARY 258
-#define CLOUDABI_AT_CANARYLEN 259
-#define CLOUDABI_AT_NCPUS 260
-#define CLOUDABI_AT_NULL 0
-#define CLOUDABI_AT_PAGESZ 6
-#define CLOUDABI_AT_PHDR 3
-#define CLOUDABI_AT_PHNUM 4
-#define CLOUDABI_AT_TID 261
-
-// Clocks.
-#define CLOUDABI_CLOCK_MONOTONIC 1
-#define CLOUDABI_CLOCK_PROCESS_CPUTIME_ID 2
-#define CLOUDABI_CLOCK_REALTIME 3
-#define CLOUDABI_CLOCK_THREAD_CPUTIME_ID 4
-
-// Condition variables.
-#define CLOUDABI_CONDVAR_HAS_NO_WAITERS 0
-
-// The start of a directory, to be passed to readdir().
-#define CLOUDABI_DIRCOOKIE_START 0
-
-// POSIX standard error numbers.
-#define CLOUDABI_E2BIG 1
-#define CLOUDABI_EACCES 2
-#define CLOUDABI_EADDRINUSE 3
-#define CLOUDABI_EADDRNOTAVAIL 4
-#define CLOUDABI_EAFNOSUPPORT 5
-#define CLOUDABI_EAGAIN 6
-#define CLOUDABI_EALREADY 7
-#define CLOUDABI_EBADF 8
-#define CLOUDABI_EBADMSG 9
-#define CLOUDABI_EBUSY 10
-#define CLOUDABI_ECANCELED 11
-#define CLOUDABI_ECHILD 12
-#define CLOUDABI_ECONNABORTED 13
-#define CLOUDABI_ECONNREFUSED 14
-#define CLOUDABI_ECONNRESET 15
-#define CLOUDABI_EDEADLK 16
-#define CLOUDABI_EDESTADDRREQ 17
-#define CLOUDABI_EDOM 18
-#define CLOUDABI_EDQUOT 19
-#define CLOUDABI_EEXIST 20
-#define CLOUDABI_EFAULT 21
-#define CLOUDABI_EFBIG 22
-#define CLOUDABI_EHOSTUNREACH 23
-#define CLOUDABI_EIDRM 24
-#define CLOUDABI_EILSEQ 25
-#define CLOUDABI_EINPROGRESS 26
-#define CLOUDABI_EINTR 27
-#define CLOUDABI_EINVAL 28
-#define CLOUDABI_EIO 29
-#define CLOUDABI_EISCONN 30
-#define CLOUDABI_EISDIR 31
-#define CLOUDABI_ELOOP 32
-#define CLOUDABI_EMFILE 33
-#define CLOUDABI_EMLINK 34
-#define CLOUDABI_EMSGSIZE 35
-#define CLOUDABI_EMULTIHOP 36
-#define CLOUDABI_ENAMETOOLONG 37
-#define CLOUDABI_ENETDOWN 38
-#define CLOUDABI_ENETRESET 39
-#define CLOUDABI_ENETUNREACH 40
-#define CLOUDABI_ENFILE 41
-#define CLOUDABI_ENOBUFS 42
-#define CLOUDABI_ENODEV 43
-#define CLOUDABI_ENOENT 44
-#define CLOUDABI_ENOEXEC 45
-#define CLOUDABI_ENOLCK 46
-#define CLOUDABI_ENOLINK 47
-#define CLOUDABI_ENOMEM 48
-#define CLOUDABI_ENOMSG 49
-#define CLOUDABI_ENOPROTOOPT 50
-#define CLOUDABI_ENOSPC 51
-#define CLOUDABI_ENOSYS 52
-#define CLOUDABI_ENOTCONN 53
-#define CLOUDABI_ENOTDIR 54
-#define CLOUDABI_ENOTEMPTY 55
-#define CLOUDABI_ENOTRECOVERABLE 56
-#define CLOUDABI_ENOTSOCK 57
-#define CLOUDABI_ENOTSUP 58
-#define CLOUDABI_ENOTTY 59
-#define CLOUDABI_ENXIO 60
-#define CLOUDABI_EOVERFLOW 61
-#define CLOUDABI_EOWNERDEAD 62
-#define CLOUDABI_EPERM 63
-#define CLOUDABI_EPIPE 64
-#define CLOUDABI_EPROTO 65
-#define CLOUDABI_EPROTONOSUPPORT 66
-#define CLOUDABI_EPROTOTYPE 67
-#define CLOUDABI_ERANGE 68
-#define CLOUDABI_EROFS 69
-#define CLOUDABI_ESPIPE 70
-#define CLOUDABI_ESRCH 71
-#define CLOUDABI_ESTALE 72
-#define CLOUDABI_ETIMEDOUT 73
-#define CLOUDABI_ETXTBSY 74
-#define CLOUDABI_EXDEV 75
-
-// Non-standard error numbers.
-#define CLOUDABI_ENOTCAPABLE 76
-
-#define CLOUDABI_EVENT_FD_READWRITE_HANGUP 0x1
-
-// Filter types for cloudabi_eventtype_t.
-#define CLOUDABI_EVENTTYPE_CLOCK 1
-#define CLOUDABI_EVENTTYPE_CONDVAR 2
-#define CLOUDABI_EVENTTYPE_FD_READ 3
-#define CLOUDABI_EVENTTYPE_FD_WRITE 4
-#define CLOUDABI_EVENTTYPE_LOCK_RDLOCK 5
-#define CLOUDABI_EVENTTYPE_LOCK_WRLOCK 6
-#define CLOUDABI_EVENTTYPE_PROC_TERMINATE 7
-
-// File descriptor behavior flags.
-#define CLOUDABI_FDFLAG_APPEND 0x1
-#define CLOUDABI_FDFLAG_DSYNC 0x2
-#define CLOUDABI_FDFLAG_NONBLOCK 0x4
-#define CLOUDABI_FDFLAG_RSYNC 0x8
-#define CLOUDABI_FDFLAG_SYNC 0x10
-
-// fdstat_put() flags.
-#define CLOUDABI_FDSTAT_FLAGS 0x1
-#define CLOUDABI_FDSTAT_RIGHTS 0x2
-
-// filestat_put() flags.
-#define CLOUDABI_FILESTAT_ATIM 0x1
-#define CLOUDABI_FILESTAT_ATIM_NOW 0x2
-#define CLOUDABI_FILESTAT_MTIM 0x4
-#define CLOUDABI_FILESTAT_MTIM_NOW 0x8
-#define CLOUDABI_FILESTAT_SIZE 0x10
-
-// File types returned through struct stat::st_mode.
-#define CLOUDABI_FILETYPE_UNKNOWN 0
-#define CLOUDABI_FILETYPE_BLOCK_DEVICE 0x10
-#define CLOUDABI_FILETYPE_CHARACTER_DEVICE 0x11
-#define CLOUDABI_FILETYPE_DIRECTORY 0x20
-#define CLOUDABI_FILETYPE_FIFO 0x30
-#define CLOUDABI_FILETYPE_POLL 0x40
-#define CLOUDABI_FILETYPE_PROCESS 0x50
-#define CLOUDABI_FILETYPE_REGULAR_FILE 0x60
-#define CLOUDABI_FILETYPE_SHARED_MEMORY 0x70
-#define CLOUDABI_FILETYPE_SOCKET_DGRAM 0x80
-#define CLOUDABI_FILETYPE_SOCKET_SEQPACKET 0x81
-#define CLOUDABI_FILETYPE_SOCKET_STREAM 0x82
-#define CLOUDABI_FILETYPE_SYMBOLIC_LINK 0x90
-
-// Read-write lock related constants.
-#define CLOUDABI_LOCK_UNLOCKED 0 // Lock is unlocked.
-#define CLOUDABI_LOCK_WRLOCKED 0x40000000 // Lock is write locked.
-#define CLOUDABI_LOCK_KERNEL_MANAGED 0x80000000 // Lock has waiters.
-#define CLOUDABI_LOCK_BOGUS 0x80000000 // Lock is broken.
-
-// Lookup properties for *at() functions.
-#define CLOUDABI_LOOKUP_SYMLINK_FOLLOW (UINT64_C(0x1) << 32)
-
-// Open flags for openat(), etc.
-#define CLOUDABI_O_CREAT 0x1
-#define CLOUDABI_O_DIRECTORY 0x2
-#define CLOUDABI_O_EXCL 0x4
-#define CLOUDABI_O_TRUNC 0x8
-
-// File descriptor returned to pdfork()'s child process.
-#define CLOUDABI_PROCESS_CHILD 0xffffffff
-
-// mmap() map flags.
-#define CLOUDABI_MAP_ANON 0x1
-#define CLOUDABI_MAP_FIXED 0x2
-#define CLOUDABI_MAP_PRIVATE 0x4
-#define CLOUDABI_MAP_SHARED 0x8
-
-// File descriptor that must be passed in when using CLOUDABI_MAP_ANON.
-#define CLOUDABI_MAP_ANON_FD 0xffffffff
-
-// msync() flags.
-#define CLOUDABI_MS_ASYNC 0x1
-#define CLOUDABI_MS_INVALIDATE 0x2
-#define CLOUDABI_MS_SYNC 0x4
-
-// send() and recv() flags.
-#define CLOUDABI_MSG_CTRUNC 0x1 // Control data truncated.
-#define CLOUDABI_MSG_EOR 0x2 // Terminates a record.
-#define CLOUDABI_MSG_PEEK 0x4 // Leave received data in queue.
-#define CLOUDABI_MSG_TRUNC 0x8 // Normal data truncated.
-#define CLOUDABI_MSG_WAITALL 0x10 // Attempt to fill the read buffer.
-
-// mmap()/mprotect() protection flags.
-#define CLOUDABI_PROT_EXEC 0x1
-#define CLOUDABI_PROT_WRITE 0x2
-#define CLOUDABI_PROT_READ 0x4
-
-// File descriptor capabilities/rights.
-#define CLOUDABI_RIGHT_BIT(bit) (UINT64_C(1) << (bit))
-#define CLOUDABI_RIGHT_FD_DATASYNC CLOUDABI_RIGHT_BIT(0)
-#define CLOUDABI_RIGHT_FD_READ CLOUDABI_RIGHT_BIT(1)
-#define CLOUDABI_RIGHT_FD_SEEK CLOUDABI_RIGHT_BIT(2)
-#define CLOUDABI_RIGHT_FD_STAT_PUT_FLAGS CLOUDABI_RIGHT_BIT(3)
-#define CLOUDABI_RIGHT_FD_SYNC CLOUDABI_RIGHT_BIT(4)
-#define CLOUDABI_RIGHT_FD_TELL CLOUDABI_RIGHT_BIT(5)
-#define CLOUDABI_RIGHT_FD_WRITE CLOUDABI_RIGHT_BIT(6)
-#define CLOUDABI_RIGHT_FILE_ADVISE CLOUDABI_RIGHT_BIT(7)
-#define CLOUDABI_RIGHT_FILE_ALLOCATE CLOUDABI_RIGHT_BIT(8)
-#define CLOUDABI_RIGHT_FILE_CREATE_DIRECTORY CLOUDABI_RIGHT_BIT(9)
-#define CLOUDABI_RIGHT_FILE_CREATE_FILE CLOUDABI_RIGHT_BIT(10)
-#define CLOUDABI_RIGHT_FILE_CREATE_FIFO CLOUDABI_RIGHT_BIT(11)
-#define CLOUDABI_RIGHT_FILE_LINK_SOURCE CLOUDABI_RIGHT_BIT(12)
-#define CLOUDABI_RIGHT_FILE_LINK_TARGET CLOUDABI_RIGHT_BIT(13)
-#define CLOUDABI_RIGHT_FILE_OPEN CLOUDABI_RIGHT_BIT(14)
-#define CLOUDABI_RIGHT_FILE_READDIR CLOUDABI_RIGHT_BIT(15)
-#define CLOUDABI_RIGHT_FILE_READLINK CLOUDABI_RIGHT_BIT(16)
-#define CLOUDABI_RIGHT_FILE_RENAME_SOURCE CLOUDABI_RIGHT_BIT(17)
-#define CLOUDABI_RIGHT_FILE_RENAME_TARGET CLOUDABI_RIGHT_BIT(18)
-#define CLOUDABI_RIGHT_FILE_STAT_FGET CLOUDABI_RIGHT_BIT(19)
-#define CLOUDABI_RIGHT_FILE_STAT_FPUT_SIZE CLOUDABI_RIGHT_BIT(20)
-#define CLOUDABI_RIGHT_FILE_STAT_FPUT_TIMES CLOUDABI_RIGHT_BIT(21)
-#define CLOUDABI_RIGHT_FILE_STAT_GET CLOUDABI_RIGHT_BIT(22)
-#define CLOUDABI_RIGHT_FILE_STAT_PUT_TIMES CLOUDABI_RIGHT_BIT(23)
-#define CLOUDABI_RIGHT_FILE_SYMLINK CLOUDABI_RIGHT_BIT(24)
-#define CLOUDABI_RIGHT_FILE_UNLINK CLOUDABI_RIGHT_BIT(25)
-#define CLOUDABI_RIGHT_MEM_MAP CLOUDABI_RIGHT_BIT(26)
-#define CLOUDABI_RIGHT_MEM_MAP_EXEC CLOUDABI_RIGHT_BIT(27)
-#define CLOUDABI_RIGHT_POLL_FD_READWRITE CLOUDABI_RIGHT_BIT(28)
-#define CLOUDABI_RIGHT_POLL_MODIFY CLOUDABI_RIGHT_BIT(29)
-#define CLOUDABI_RIGHT_POLL_PROC_TERMINATE CLOUDABI_RIGHT_BIT(30)
-#define CLOUDABI_RIGHT_POLL_WAIT CLOUDABI_RIGHT_BIT(31)
-#define CLOUDABI_RIGHT_PROC_EXEC CLOUDABI_RIGHT_BIT(32)
-#define CLOUDABI_RIGHT_SOCK_ACCEPT CLOUDABI_RIGHT_BIT(33)
-#define CLOUDABI_RIGHT_SOCK_BIND_DIRECTORY CLOUDABI_RIGHT_BIT(34)
-#define CLOUDABI_RIGHT_SOCK_BIND_SOCKET CLOUDABI_RIGHT_BIT(35)
-#define CLOUDABI_RIGHT_SOCK_CONNECT_DIRECTORY CLOUDABI_RIGHT_BIT(36)
-#define CLOUDABI_RIGHT_SOCK_CONNECT_SOCKET CLOUDABI_RIGHT_BIT(37)
-#define CLOUDABI_RIGHT_SOCK_LISTEN CLOUDABI_RIGHT_BIT(38)
-#define CLOUDABI_RIGHT_SOCK_SHUTDOWN CLOUDABI_RIGHT_BIT(39)
-#define CLOUDABI_RIGHT_SOCK_STAT_GET CLOUDABI_RIGHT_BIT(40)
-
-// Socket shutdown flags.
-#define CLOUDABI_SHUT_RD 0x1
-#define CLOUDABI_SHUT_WR 0x2
-
-// Signals.
-#define CLOUDABI_SIGABRT 1
-#define CLOUDABI_SIGALRM 2
-#define CLOUDABI_SIGBUS 3
-#define CLOUDABI_SIGCHLD 4
-#define CLOUDABI_SIGCONT 5
-#define CLOUDABI_SIGFPE 6
-#define CLOUDABI_SIGHUP 7
-#define CLOUDABI_SIGILL 8
-#define CLOUDABI_SIGINT 9
-#define CLOUDABI_SIGKILL 10
-#define CLOUDABI_SIGPIPE 11
-#define CLOUDABI_SIGQUIT 12
-#define CLOUDABI_SIGSEGV 13
-#define CLOUDABI_SIGSTOP 14
-#define CLOUDABI_SIGSYS 15
-#define CLOUDABI_SIGTERM 16
-#define CLOUDABI_SIGTRAP 17
-#define CLOUDABI_SIGTSTP 18
-#define CLOUDABI_SIGTTIN 19
-#define CLOUDABI_SIGTTOU 20
-#define CLOUDABI_SIGURG 21
-#define CLOUDABI_SIGUSR1 22
-#define CLOUDABI_SIGUSR2 23
-#define CLOUDABI_SIGVTALRM 24
-#define CLOUDABI_SIGXCPU 25
-#define CLOUDABI_SIGXFSZ 26
-
-// sockstat() flags.
-#define CLOUDABI_SOCKSTAT_CLEAR_ERROR 0x1
-
-// sockstat() state.
-#define CLOUDABI_SOCKSTAT_ACCEPTCONN 0x1
-
-// cloudabi_subscription_t flags.
-#define CLOUDABI_SUBSCRIPTION_ADD 0x1
-#define CLOUDABI_SUBSCRIPTION_CLEAR 0x2
-#define CLOUDABI_SUBSCRIPTION_DELETE 0x4
-#define CLOUDABI_SUBSCRIPTION_DISABLE 0x8
-#define CLOUDABI_SUBSCRIPTION_ENABLE 0x10
-#define CLOUDABI_SUBSCRIPTION_ONESHOT 0x20
-
-// cloudabi_subscription_t::clock.flags.
-#define CLOUDABI_SUBSCRIPTION_CLOCK_ABSTIME 0x1
-
-// cloudabi_subscription_t::fd_readwrite.flags.
-#define CLOUDABI_SUBSCRIPTION_FD_READWRITE_POLL 0x1
-
-// unlinkat().
-#define CLOUDABI_UNLINK_REMOVEDIR 0x1
-
-// Seeking.
-#define CLOUDABI_WHENCE_CUR 1
-#define CLOUDABI_WHENCE_END 2
-#define CLOUDABI_WHENCE_SET 3
-
-typedef uint8_t cloudabi_advice_t; // posix_fadvise() and posix_madvise().
-typedef uint32_t cloudabi_backlog_t; // listen().
-typedef uint32_t cloudabi_clockid_t; // clock_*().
-typedef uint32_t cloudabi_condvar_t; // pthread_cond_*().
-typedef uint64_t cloudabi_device_t; // struct stat::st_dev.
-typedef uint64_t cloudabi_dircookie_t; // readdir().
-typedef uint16_t cloudabi_errno_t; // errno.
-typedef uint8_t cloudabi_eventtype_t; // poll().
-typedef uint32_t cloudabi_exitcode_t; // _exit() and _Exit().
-typedef uint32_t cloudabi_fd_t; // File descriptors.
-typedef uint16_t cloudabi_fdflags_t; // cloudabi_fdstat_t.
-typedef uint16_t cloudabi_fdsflags_t; // fd_stat_put().
-typedef int64_t cloudabi_filedelta_t; // lseek().
-typedef uint64_t cloudabi_filesize_t; // ftruncate(), struct stat::st_size.
-typedef uint8_t cloudabi_filetype_t; // struct stat::st_mode.
-typedef uint16_t cloudabi_fsflags_t; // file_stat_put().
-typedef uint64_t cloudabi_inode_t; // struct stat::st_ino.
-typedef uint32_t cloudabi_linkcount_t; // struct stat::st_nlink.
-typedef uint32_t cloudabi_lock_t; // pthread_{mutex,rwlock}_*().
-typedef uint64_t cloudabi_lookup_t; // openat(), linkat(), etc.
-typedef uint8_t cloudabi_mflags_t; // mmap().
-typedef uint8_t cloudabi_mprot_t; // mmap().
-typedef uint8_t cloudabi_msflags_t; // msync().
-typedef uint16_t cloudabi_msgflags_t; // send() and recv().
-typedef uint32_t cloudabi_nthreads_t; // pthread_cond_*().
-typedef uint16_t cloudabi_oflags_t; // openat(), etc.
-typedef uint64_t cloudabi_rights_t; // File descriptor rights.
-typedef uint8_t cloudabi_sa_family_t; // Socket address family.
-typedef uint8_t cloudabi_sdflags_t; // shutdown().
-typedef uint8_t cloudabi_ssflags_t; // sockstat().
-typedef uint8_t cloudabi_signal_t; // raise().
-typedef uint32_t cloudabi_tid_t; // Thread ID.
-typedef uint64_t cloudabi_timestamp_t; // clock_*(), struct stat::st_*tim.
-typedef uint8_t cloudabi_ulflags_t; // unlinkat().
-typedef uint64_t cloudabi_userdata_t; // User-supplied data for callbacks.
-typedef uint8_t cloudabi_whence_t; // lseek().
-
-// Macro to force sane alignment rules.
-//
-// On x86-32 it is the case that 64-bit integers are 4-byte aligned when
-// embedded in structs, even though they are 8-byte aligned when not
-// embedded. Force 8-byte alignment explicitly.
-#define MEMBER(type) alignas(alignof(type)) type
-#define ASSERT_OFFSET(type, field, offset) \
- static_assert(offsetof(cloudabi_##type, field) == (offset), \
- "Offset incorrect")
-#define ASSERT_SIZE(type, size) \
- static_assert(sizeof(cloudabi_##type) == (size), "Size incorrect")
-
-// Directory entries.
-typedef struct {
- MEMBER(cloudabi_dircookie_t) d_next; // Cookie of the next entry.
- MEMBER(cloudabi_inode_t) d_ino; // Inode number of the current entry.
- MEMBER(uint32_t) d_namlen; // Length of the name of the current entry.
- MEMBER(cloudabi_filetype_t) d_type; // File type of the current entry.
-} cloudabi_dirent_t;
-ASSERT_OFFSET(dirent_t, d_next, 0);
-ASSERT_OFFSET(dirent_t, d_ino, 8);
-ASSERT_OFFSET(dirent_t, d_namlen, 16);
-ASSERT_OFFSET(dirent_t, d_type, 20);
-ASSERT_SIZE(dirent_t, 24);
-
-// File descriptor status.
-typedef struct {
- MEMBER(cloudabi_filetype_t) fs_filetype; // File descriptor type.
- MEMBER(cloudabi_fdflags_t) fs_flags; // Non-blocking mode, etc.
- MEMBER(cloudabi_rights_t) fs_rights_base; // Base rights.
- MEMBER(cloudabi_rights_t) fs_rights_inheriting; // Inheriting rights.
-} cloudabi_fdstat_t;
-ASSERT_OFFSET(fdstat_t, fs_filetype, 0);
-ASSERT_OFFSET(fdstat_t, fs_flags, 2);
-ASSERT_OFFSET(fdstat_t, fs_rights_base, 8);
-ASSERT_OFFSET(fdstat_t, fs_rights_inheriting, 16);
-ASSERT_SIZE(fdstat_t, 24);
-
-// File status.
-typedef struct {
- MEMBER(cloudabi_device_t) st_dev; // Device storing the file.
- MEMBER(cloudabi_inode_t) st_ino; // Inode of the file.
- MEMBER(cloudabi_filetype_t) st_filetype; // File type.
- MEMBER(cloudabi_linkcount_t) st_nlink; // Number of hardlinks.
- MEMBER(cloudabi_filesize_t) st_size; // Size of the file.
- MEMBER(cloudabi_timestamp_t) st_atim; // Access time.
- MEMBER(cloudabi_timestamp_t) st_mtim; // Modification time.
- MEMBER(cloudabi_timestamp_t) st_ctim; // Change time.
-} cloudabi_filestat_t;
-ASSERT_OFFSET(filestat_t, st_dev, 0);
-ASSERT_OFFSET(filestat_t, st_ino, 8);
-ASSERT_OFFSET(filestat_t, st_filetype, 16);
-ASSERT_OFFSET(filestat_t, st_nlink, 20);
-ASSERT_OFFSET(filestat_t, st_size, 24);
-ASSERT_OFFSET(filestat_t, st_atim, 32);
-ASSERT_OFFSET(filestat_t, st_mtim, 40);
-ASSERT_OFFSET(filestat_t, st_ctim, 48);
-ASSERT_SIZE(filestat_t, 56);
-
-typedef struct {
- MEMBER(cloudabi_sa_family_t) sa_family;
- union {
- struct {
- // IPv4 address and port number.
- MEMBER(uint8_t) addr[4];
- MEMBER(uint16_t) port;
- } sa_inet;
- struct {
- // IPv6 address and port number.
- // TODO(ed): What about the flow info and scope ID?
- MEMBER(uint8_t) addr[16];
- MEMBER(uint16_t) port;
- } sa_inet6;
- };
-} cloudabi_sockaddr_t;
-ASSERT_OFFSET(sockaddr_t, sa_family, 0);
-ASSERT_OFFSET(sockaddr_t, sa_inet.addr, 2);
-ASSERT_OFFSET(sockaddr_t, sa_inet.port, 6);
-ASSERT_OFFSET(sockaddr_t, sa_inet6.addr, 2);
-ASSERT_OFFSET(sockaddr_t, sa_inet6.port, 18);
-ASSERT_SIZE(sockaddr_t, 20);
-
-// Socket status.
-typedef struct {
- MEMBER(cloudabi_sockaddr_t) ss_sockname; // Socket address.
- MEMBER(cloudabi_sockaddr_t) ss_peername; // Peer address.
- MEMBER(cloudabi_errno_t) ss_error; // Current error state.
- MEMBER(uint32_t) ss_state; // State flags.
-} cloudabi_sockstat_t;
-ASSERT_OFFSET(sockstat_t, ss_sockname, 0);
-ASSERT_OFFSET(sockstat_t, ss_peername, 20);
-ASSERT_OFFSET(sockstat_t, ss_error, 40);
-ASSERT_OFFSET(sockstat_t, ss_state, 44);
-ASSERT_SIZE(sockstat_t, 48);
-
-#undef MEMBER
-#undef ASSERT_OFFSET
-#undef ASSERT_SIZE
-
-#endif
diff --git a/sys/compat/cloudabi64/syscalls.master b/sys/contrib/cloudabi/syscalls.master
index 5fd6f7e..7da55c5 100644
--- a/sys/compat/cloudabi64/syscalls.master
+++ b/sys/contrib/cloudabi/syscalls.master
@@ -1,19 +1,43 @@
$FreeBSD$
-; System call table for CloudABI.
+; Copyright (c) 2016 Nuxi (https://nuxi.nl/) and contributors.
;
-; All system calls that do not use any machine-dependent data types are
-; prefixed with cloudabi_sys_. The others are called cloudabi64_sys_.
+; 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 file is automatically generated. Do not edit.
+;
+; Source: https://github.com/NuxiNL/cloudabi
#include <sys/sysent.h>
#include <sys/sysproto.h>
-#include <compat/cloudabi64/cloudabi64_syscalldefs.h>
+#include <contrib/cloudabi/cloudabi64_types.h>
+
#include <compat/cloudabi64/cloudabi64_proto.h>
0 AUE_NULL STD { cloudabi_timestamp_t \
cloudabi_sys_clock_res_get( \
cloudabi_clockid_t clock_id); }
+
1 AUE_NULL STD { cloudabi_timestamp_t \
cloudabi_sys_clock_time_get( \
cloudabi_clockid_t clock_id, \
@@ -21,200 +45,274 @@
2 AUE_NULL STD { void cloudabi_sys_condvar_signal( \
cloudabi_condvar_t *condvar, \
- cloudabi_mflags_t scope, \
+ cloudabi_scope_t scope, \
cloudabi_nthreads_t nwaiters); }
3 AUE_NULL STD { void cloudabi_sys_fd_close( \
cloudabi_fd_t fd); }
+
4 AUE_NULL STD { cloudabi_fd_t cloudabi_sys_fd_create1( \
cloudabi_filetype_t type); }
+
5 AUE_NULL STD { void cloudabi_sys_fd_create2( \
cloudabi_filetype_t type); }
+
6 AUE_NULL STD { void cloudabi_sys_fd_datasync( \
cloudabi_fd_t fd); }
+
7 AUE_NULL STD { cloudabi_fd_t cloudabi_sys_fd_dup( \
cloudabi_fd_t from); }
-8 AUE_NULL STD { cloudabi64_size_t cloudabi64_sys_fd_pread( \
+
+8 AUE_NULL STD { size_t cloudabi64_sys_fd_pread( \
cloudabi_fd_t fd, \
const cloudabi64_iovec_t *iov, \
- cloudabi64_size_t iovcnt, \
+ size_t iovcnt, \
cloudabi_filesize_t offset); }
-9 AUE_NULL STD { cloudabi64_size_t cloudabi64_sys_fd_pwrite( \
+
+9 AUE_NULL STD { size_t cloudabi64_sys_fd_pwrite( \
cloudabi_fd_t fd, \
const cloudabi64_ciovec_t *iov, \
- cloudabi64_size_t iovcnt, \
+ size_t iovcnt, \
cloudabi_filesize_t offset); }
-10 AUE_NULL STD { cloudabi64_size_t cloudabi64_sys_fd_read( \
+
+10 AUE_NULL STD { size_t cloudabi64_sys_fd_read( \
cloudabi_fd_t fd, \
const cloudabi64_iovec_t *iov, \
- cloudabi64_size_t iovcnt); }
+ size_t iovcnt); }
+
11 AUE_NULL STD { void cloudabi_sys_fd_replace( \
cloudabi_fd_t from, \
cloudabi_fd_t to); }
-12 AUE_NULL STD { cloudabi_filesize_t cloudabi_sys_fd_seek( \
+
+12 AUE_NULL STD { cloudabi_filesize_t \
+ cloudabi_sys_fd_seek( \
cloudabi_fd_t fd, \
cloudabi_filedelta_t offset, \
cloudabi_whence_t whence); }
+
13 AUE_NULL STD { void cloudabi_sys_fd_stat_get( \
cloudabi_fd_t fd, \
cloudabi_fdstat_t *buf); }
+
14 AUE_NULL STD { void cloudabi_sys_fd_stat_put( \
cloudabi_fd_t fd, \
const cloudabi_fdstat_t *buf, \
cloudabi_fdsflags_t flags); }
+
15 AUE_NULL STD { void cloudabi_sys_fd_sync( \
cloudabi_fd_t fd); }
-16 AUE_NULL STD { cloudabi64_size_t cloudabi64_sys_fd_write( \
+
+16 AUE_NULL STD { size_t cloudabi64_sys_fd_write( \
cloudabi_fd_t fd, \
const cloudabi64_ciovec_t *iov, \
- cloudabi64_size_t iovcnt); }
+ size_t iovcnt); }
17 AUE_NULL STD { void cloudabi_sys_file_advise( \
cloudabi_fd_t fd, \
cloudabi_filesize_t offset, \
cloudabi_filesize_t len, \
cloudabi_advice_t advice); }
+
18 AUE_NULL STD { void cloudabi_sys_file_allocate( \
cloudabi_fd_t fd, \
cloudabi_filesize_t offset, \
cloudabi_filesize_t len); }
+
19 AUE_NULL STD { void cloudabi_sys_file_create( \
cloudabi_fd_t fd, \
- const char *path, size_t pathlen, \
+ const char *path, \
+ size_t pathlen, \
cloudabi_filetype_t type); }
+
20 AUE_NULL STD { void cloudabi_sys_file_link( \
cloudabi_lookup_t fd1, \
- const char *path1, size_t path1len, \
+ const char *path1, \
+ size_t path1len, \
cloudabi_fd_t fd2, \
- const char *path2, size_t path2len); }
+ const char *path2, \
+ size_t path2len); }
+
21 AUE_NULL STD { cloudabi_fd_t cloudabi_sys_file_open( \
- cloudabi_lookup_t fd, \
- const char *path, size_t pathlen, \
+ cloudabi_lookup_t dirfd, \
+ const char *path, \
+ size_t pathlen, \
cloudabi_oflags_t oflags, \
const cloudabi_fdstat_t *fds); }
+
22 AUE_NULL STD { size_t cloudabi_sys_file_readdir( \
cloudabi_fd_t fd, \
- void *buf, size_t nbyte, \
+ void *buf, \
+ size_t nbyte, \
cloudabi_dircookie_t cookie); }
+
23 AUE_NULL STD { size_t cloudabi_sys_file_readlink( \
cloudabi_fd_t fd, \
- const char *path, size_t pathlen, \
- void *buf, size_t bufsize); }
+ const char *path, \
+ size_t pathlen, \
+ char *buf, \
+ size_t bufsize); }
+
24 AUE_NULL STD { void cloudabi_sys_file_rename( \
cloudabi_fd_t oldfd, \
- const char *old, size_t oldlen, \
+ const char *old, \
+ size_t oldlen, \
cloudabi_fd_t newfd, \
- const char *new, size_t newlen); }
+ const char *new, \
+ size_t newlen); }
+
25 AUE_NULL STD { void cloudabi_sys_file_stat_fget( \
cloudabi_fd_t fd, \
cloudabi_filestat_t *buf); }
+
26 AUE_NULL STD { void cloudabi_sys_file_stat_fput( \
cloudabi_fd_t fd, \
const cloudabi_filestat_t *buf, \
cloudabi_fsflags_t flags); }
+
27 AUE_NULL STD { void cloudabi_sys_file_stat_get( \
cloudabi_lookup_t fd, \
- const char *path, size_t pathlen, \
+ const char *path, \
+ size_t pathlen, \
cloudabi_filestat_t *buf); }
+
28 AUE_NULL STD { void cloudabi_sys_file_stat_put( \
cloudabi_lookup_t fd, \
- const char *path, size_t pathlen, \
+ const char *path, \
+ size_t pathlen, \
const cloudabi_filestat_t *buf, \
cloudabi_fsflags_t flags); }
+
29 AUE_NULL STD { void cloudabi_sys_file_symlink( \
- const char *path1, size_t path1len, \
+ const char *path1, \
+ size_t path1len, \
cloudabi_fd_t fd, \
- const char *path2, size_t path2len); }
+ const char *path2, \
+ size_t path2len); }
+
30 AUE_NULL STD { void cloudabi_sys_file_unlink( \
cloudabi_fd_t fd, \
- const char *path, size_t pathlen, \
- cloudabi_ulflags_t flag); }
+ const char *path, \
+ size_t pathlen, \
+ cloudabi_ulflags_t flags); }
31 AUE_NULL STD { void cloudabi_sys_lock_unlock( \
cloudabi_lock_t *lock, \
- cloudabi_mflags_t scope); }
+ cloudabi_scope_t scope); }
32 AUE_NULL STD { void cloudabi_sys_mem_advise( \
- void *addr, size_t len, \
+ void *addr, \
+ size_t len, \
cloudabi_advice_t advice); }
+
33 AUE_NULL STD { void cloudabi_sys_mem_lock( \
- const void *addr, size_t len); }
+ const void *addr, \
+ size_t len); }
+
34 AUE_NULL STD { void cloudabi_sys_mem_map( \
- void *addr, size_t len, \
+ void *addr, \
+ size_t len, \
cloudabi_mprot_t prot, \
cloudabi_mflags_t flags, \
cloudabi_fd_t fd, \
cloudabi_filesize_t off); }
+
35 AUE_NULL STD { void cloudabi_sys_mem_protect( \
- void *addr, size_t len, \
+ void *addr, \
+ size_t len, \
cloudabi_mprot_t prot); }
+
36 AUE_NULL STD { void cloudabi_sys_mem_sync( \
- void *addr, size_t len, \
+ void *addr, \
+ size_t len, \
cloudabi_msflags_t flags); }
+
37 AUE_NULL STD { void cloudabi_sys_mem_unlock( \
- const void *addr, size_t len); }
+ const void *addr, \
+ size_t len); }
+
38 AUE_NULL STD { void cloudabi_sys_mem_unmap( \
- void * addr, size_t len); }
+ void *addr, \
+ size_t len); }
-39 AUE_NULL STD { cloudabi64_size_t cloudabi64_sys_poll( \
+39 AUE_NULL STD { size_t cloudabi64_sys_poll( \
const cloudabi64_subscription_t *in, \
cloudabi64_event_t *out, \
- cloudabi64_size_t nevents); }
+ size_t nsubscriptions); }
40 AUE_NULL STD { void cloudabi_sys_proc_exec( \
- cloudabi_fd_t fd, const void *data, \
+ cloudabi_fd_t fd, \
+ const void *data, \
size_t datalen, \
const cloudabi_fd_t *fds, \
size_t fdslen); }
+
41 AUE_NULL STD { void cloudabi_sys_proc_exit( \
cloudabi_exitcode_t rval); }
-42 AUE_NULL STD { cloudabi_fd_t cloudabi_sys_proc_fork(); }
+
+42 AUE_NULL STD { void cloudabi_sys_proc_fork(); }
+
43 AUE_NULL STD { void cloudabi_sys_proc_raise( \
cloudabi_signal_t sig); }
44 AUE_NULL STD { void cloudabi_sys_random_get( \
- void *buf, size_t nbyte); }
+ void *buf, \
+ size_t nbyte); }
45 AUE_NULL STD { cloudabi_fd_t cloudabi_sys_sock_accept( \
- cloudabi_fd_t s, \
+ cloudabi_fd_t sock, \
cloudabi_sockstat_t *buf); }
+
46 AUE_NULL STD { void cloudabi_sys_sock_bind( \
- cloudabi_fd_t s, cloudabi_fd_t fd, \
- const char *path, size_t pathlen); }
+ cloudabi_fd_t sock, \
+ cloudabi_fd_t fd, \
+ const char *path, \
+ size_t pathlen); }
+
47 AUE_NULL STD { void cloudabi_sys_sock_connect( \
- cloudabi_fd_t s, cloudabi_fd_t fd, \
- const char *path, size_t pathlen); }
+ cloudabi_fd_t sock, \
+ cloudabi_fd_t fd, \
+ const char *path, \
+ size_t pathlen); }
+
48 AUE_NULL STD { void cloudabi_sys_sock_listen( \
- cloudabi_fd_t s, \
+ cloudabi_fd_t sock, \
cloudabi_backlog_t backlog); }
-49 AUE_NULL STD { cloudabi64_size_t cloudabi64_sys_sock_recv( \
- cloudabi_fd_t s, \
+
+49 AUE_NULL STD { void cloudabi64_sys_sock_recv( \
+ cloudabi_fd_t sock, \
const cloudabi64_recv_in_t *in, \
cloudabi64_recv_out_t *out); }
-50 AUE_NULL STD { cloudabi64_size_t cloudabi64_sys_sock_send( \
- cloudabi_fd_t s, \
+
+50 AUE_NULL STD { void cloudabi64_sys_sock_send( \
+ cloudabi_fd_t sock, \
const cloudabi64_send_in_t *in, \
cloudabi64_send_out_t *out); }
+
51 AUE_NULL STD { void cloudabi_sys_sock_shutdown( \
- cloudabi_fd_t fd, \
+ cloudabi_fd_t sock, \
cloudabi_sdflags_t how); }
+
52 AUE_NULL STD { void cloudabi_sys_sock_stat_get( \
- cloudabi_fd_t fd, \
+ cloudabi_fd_t sock, \
cloudabi_sockstat_t *buf, \
cloudabi_ssflags_t flags); }
53 AUE_NULL STD { cloudabi_tid_t cloudabi64_sys_thread_create( \
cloudabi64_threadattr_t *attr); }
+
54 AUE_NULL STD { void cloudabi_sys_thread_exit( \
cloudabi_lock_t *lock, \
- cloudabi_mflags_t scope); }
-55 AUE_NULL STD { void cloudabi_sys_thread_tcb_set(void *tcb); }
+ cloudabi_scope_t scope); }
+
+55 AUE_NULL STD { void cloudabi_sys_thread_tcb_set( \
+ void *tcb); }
+
56 AUE_NULL STD { void cloudabi_sys_thread_yield(); }
-57 AUE_NULL STD { cloudabi64_size_t cloudabi64_sys_poll_fd( \
+57 AUE_NULL STD { size_t cloudabi64_sys_poll_fd( \
cloudabi_fd_t fd, \
const cloudabi64_subscription_t *in, \
- cloudabi64_size_t nin, \
+ size_t nin, \
cloudabi64_event_t *out, \
- cloudabi64_size_t nout, \
+ size_t nout, \
const cloudabi64_subscription_t *timeout); }
diff --git a/sys/contrib/rdma/krping/krping.c b/sys/contrib/rdma/krping/krping.c
index 667af40..3ad881e 100644
--- a/sys/contrib/rdma/krping/krping.c
+++ b/sys/contrib/rdma/krping/krping.c
@@ -261,12 +261,18 @@ static int krping_cma_event_handler(struct rdma_cm_id *cma_id,
case RDMA_CM_EVENT_ROUTE_RESOLVED:
cb->state = ROUTE_RESOLVED;
+ cb->child_cm_id = cma_id;
wake_up_interruptible(&cb->sem);
break;
case RDMA_CM_EVENT_CONNECT_REQUEST:
- cb->state = CONNECT_REQUEST;
- cb->child_cm_id = cma_id;
+ if (cb->state == IDLE) {
+ cb->state = CONNECT_REQUEST;
+ cb->child_cm_id = cma_id;
+ } else {
+ PRINTF(cb, "Received connection request in wrong state"
+ " (%d)\n", cb->state);
+ }
DEBUG_LOG(cb, "child cma %p\n", cb->child_cm_id);
wake_up_interruptible(&cb->sem);
break;
diff --git a/sys/ddb/db_ps.c b/sys/ddb/db_ps.c
index f38c89f..76ab2c5 100644
--- a/sys/ddb/db_ps.c
+++ b/sys/ddb/db_ps.c
@@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
#include <sys/cons.h>
#include <sys/jail.h>
#include <sys/kdb.h>
+#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/sysent.h>
#include <sys/systm.h>
@@ -302,6 +303,7 @@ DB_SHOW_COMMAND(thread, db_show_thread)
struct thread *td;
struct lock_object *lock;
bool comma;
+ int delta;
/* Determine which thread to examine. */
if (have_addr)
@@ -376,6 +378,16 @@ DB_SHOW_COMMAND(thread, db_show_thread)
td->td_wchan);
db_printf(" priority: %d\n", td->td_priority);
db_printf(" container lock: %s (%p)\n", lock->lo_name, lock);
+ if (td->td_swvoltick != 0) {
+ delta = (u_int)ticks - (u_int)td->td_swvoltick;
+ db_printf(" last voluntary switch: %d ms ago\n",
+ 1000 * delta / hz);
+ }
+ if (td->td_swinvoltick != 0) {
+ delta = (u_int)ticks - (u_int)td->td_swinvoltick;
+ db_printf(" last involuntary switch: %d ms ago\n",
+ 1000 * delta / hz);
+ }
}
DB_SHOW_COMMAND(proc, db_show_proc)
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index 70d4bce..6f5a11f 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -795,10 +795,10 @@ acpi_print_child(device_t bus, device_t child)
int retval = 0;
retval += bus_print_child_header(bus, child);
- retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx");
- retval += resource_list_print_type(rl, "iomem", SYS_RES_MEMORY, "%#lx");
- retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
- retval += resource_list_print_type(rl, "drq", SYS_RES_DRQ, "%ld");
+ retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#jx");
+ retval += resource_list_print_type(rl, "iomem", SYS_RES_MEMORY, "%#jx");
+ retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
+ retval += resource_list_print_type(rl, "drq", SYS_RES_DRQ, "%jd");
if (device_get_flags(child))
retval += printf(" flags %#x", device_get_flags(child));
retval += bus_print_child_domain(bus, child);
@@ -1156,7 +1156,7 @@ acpi_sysres_alloc(device_t dev)
rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev);
STAILQ_FOREACH(rle, rl, link) {
if (rle->res != NULL) {
- device_printf(dev, "duplicate resource for %lx\n", rle->start);
+ device_printf(dev, "duplicate resource for %jx\n", rle->start);
continue;
}
@@ -1179,7 +1179,7 @@ acpi_sysres_alloc(device_t dev)
rman_manage_region(rm, rman_get_start(res), rman_get_end(res));
rle->res = res;
} else if (bootverbose)
- device_printf(dev, "reservation of %lx, %lx (%d) failed\n",
+ device_printf(dev, "reservation of %jx, %jx (%d) failed\n",
rle->start, rle->count, rle->type);
}
return (0);
diff --git a/sys/dev/acpica/acpi_hpet.c b/sys/dev/acpica/acpi_hpet.c
index 76fbd5a..da1e160e 100644
--- a/sys/dev/acpica/acpi_hpet.c
+++ b/sys/dev/acpica/acpi_hpet.c
@@ -453,7 +453,7 @@ hpet_attach(device_t dev)
/* Validate that we can access the whole region. */
if (rman_get_size(sc->mem_res) < HPET_MEM_WIDTH) {
- device_printf(dev, "memory region width %ld too small\n",
+ device_printf(dev, "memory region width %jd too small\n",
rman_get_size(sc->mem_res));
bus_free_resource(dev, SYS_RES_MEMORY, sc->mem_res);
return (ENXIO);
diff --git a/sys/dev/acpica/acpi_timer.c b/sys/dev/acpica/acpi_timer.c
index 2cdf908..34a8320 100644
--- a/sys/dev/acpica/acpi_timer.c
+++ b/sys/dev/acpica/acpi_timer.c
@@ -152,7 +152,7 @@ acpi_timer_identify(driver_t *driver, device_t parent)
rlen = AcpiGbl_FADT.PmTimerLength;
rstart = AcpiGbl_FADT.XPmTimerBlock.Address;
if (bus_set_resource(dev, rtype, rid, rstart, rlen))
- device_printf(dev, "couldn't set resource (%s 0x%lx+0x%lx)\n",
+ device_printf(dev, "couldn't set resource (%s 0x%jx+0x%jx)\n",
(rtype == SYS_RES_IOPORT) ? "port" : "mem", rstart, rlen);
return_VOID;
}
diff --git a/sys/dev/advansys/adv_isa.c b/sys/dev/advansys/adv_isa.c
index 00381a3..3b3a45b 100644
--- a/sys/dev/advansys/adv_isa.c
+++ b/sys/dev/advansys/adv_isa.c
@@ -136,7 +136,7 @@ adv_isa_probe(device_t dev)
|| (iobase != adv_isa_ioports[port_index])) {
if (bootverbose)
device_printf(dev,
- "Invalid baseport of 0x%lx specified. "
+ "Invalid baseport of 0x%jx specified. "
"Nearest valid baseport is 0x%x. Failing "
"probe.\n", iobase,
(port_index <= max_port_index) ?
diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c
index 25ebbf7..8341f66 100644
--- a/sys/dev/ahci/ahci.c
+++ b/sys/dev/ahci/ahci.c
@@ -527,7 +527,7 @@ ahci_alloc_resource(device_t dev, device_t child, int type, int *rid,
{
struct ahci_controller *ctlr = device_get_softc(dev);
struct resource *res;
- long st;
+ rman_res_t st;
int offset, size, unit;
unit = (intptr_t)device_get_ivars(child);
diff --git a/sys/dev/ahci/ahci.h b/sys/dev/ahci/ahci.h
index 86bdf2b..868a376 100644
--- a/sys/dev/ahci/ahci.h
+++ b/sys/dev/ahci/ahci.h
@@ -597,6 +597,7 @@ enum ahci_err_type {
#define AHCI_Q_1MSI 0x00020000
#define AHCI_Q_FORCE_PI 0x00040000
#define AHCI_Q_RESTORE_CAP 0x00080000
+#define AHCI_Q_NOMSIX 0x00100000
#define AHCI_Q_BIT_STRING \
"\020" \
@@ -619,7 +620,8 @@ enum ahci_err_type {
"\021ABAR0" \
"\0221MSI" \
"\023FORCE_PI" \
- "\024RESTORE_CAP"
+ "\024RESTORE_CAP" \
+ "\025NOMSIX"
int ahci_attach(device_t dev);
int ahci_detach(device_t dev);
diff --git a/sys/dev/ahci/ahci_pci.c b/sys/dev/ahci/ahci_pci.c
index 5c236ce..57f7ea9 100644
--- a/sys/dev/ahci/ahci_pci.c
+++ b/sys/dev/ahci/ahci_pci.c
@@ -293,7 +293,7 @@ static const struct {
{0x11851039, 0x00, "SiS 968", 0},
{0x01861039, 0x00, "SiS 968", 0},
{0xa01c177d, 0x00, "ThunderX", AHCI_Q_ABAR0|AHCI_Q_1MSI},
- {0x00311c36, 0x00, "Annapurna", AHCI_Q_FORCE_PI|AHCI_Q_RESTORE_CAP},
+ {0x00311c36, 0x00, "Annapurna", AHCI_Q_FORCE_PI|AHCI_Q_RESTORE_CAP|AHCI_Q_NOMSIX},
{0x00000000, 0x00, NULL, 0}
};
@@ -437,6 +437,9 @@ ahci_pci_attach(device_t dev)
&ctlr->r_rid, RF_ACTIVE)))
return ENXIO;
+ if (ctlr->quirks & AHCI_Q_NOMSIX)
+ msix_count = 0;
+
/* Read MSI-x BAR IDs if supported */
if (msix_count > 0) {
error = ahci_pci_read_msix_bars(dev, &table_bar, &pba_bar);
diff --git a/sys/dev/amdsbwd/amdsbwd.c b/sys/dev/amdsbwd/amdsbwd.c
index 7221db4..207d0b9 100644
--- a/sys/dev/amdsbwd/amdsbwd.c
+++ b/sys/dev/amdsbwd/amdsbwd.c
@@ -106,6 +106,8 @@ __FBSDID("$FreeBSD$");
/* SB7xx RRG 2.3.1.1, SB600 RRG 2.3.1.1, SB8xx RRG 2.3.1. */
#define AMDSB_SMBUS_DEVID 0x43851002
#define AMDSB8_SMBUS_REVID 0x40
+#define AMDHUDSON_SMBUS_DEVID 0x780b1022
+#define AMDKERNCZ_SMBUS_DEVID 0x790b1022
#define amdsbwd_verbose_printf(dev, ...) \
do { \
@@ -279,7 +281,9 @@ amdsbwd_identify(driver_t *driver, device_t parent)
smb_dev = pci_find_bsf(0, 20, 0);
if (smb_dev == NULL)
return;
- if (pci_get_devid(smb_dev) != AMDSB_SMBUS_DEVID)
+ if (pci_get_devid(smb_dev) != AMDSB_SMBUS_DEVID &&
+ pci_get_devid(smb_dev) != AMDHUDSON_SMBUS_DEVID &&
+ pci_get_devid(smb_dev) != AMDKERNCZ_SMBUS_DEVID)
return;
child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "amdsbwd", -1);
@@ -309,10 +313,12 @@ amdsbwd_probe_sb7xx(device_t dev, struct resource *pmres, uint32_t *addr)
*addr <<= 8;
*addr |= pmio_read(pmres, AMDSB_PM_WDT_BASE_MSB - i);
}
+ *addr &= ~0x07u;
+
/* Set watchdog timer tick to 1s. */
val = pmio_read(pmres, AMDSB_PM_WDT_CTRL);
val &= ~AMDSB_WDT_RES_MASK;
- val |= AMDSB_WDT_RES_10MS;
+ val |= AMDSB_WDT_RES_1S;
pmio_write(pmres, AMDSB_PM_WDT_CTRL, val);
/* Enable watchdog device (in stopped state). */
@@ -372,7 +378,7 @@ amdsbwd_probe_sb8xx(device_t dev, struct resource *pmres, uint32_t *addr)
val = pmio_read(pmres, AMDSB8_PM_WDT_EN);
device_printf(dev, "AMDSB8_PM_WDT_EN value = %#02x\n", val);
#endif
- device_set_desc(dev, "AMD SB8xx Watchdog Timer");
+ device_set_desc(dev, "AMD SB8xx/SB9xx/Axx Watchdog Timer");
}
static int
@@ -404,7 +410,8 @@ amdsbwd_probe(device_t dev)
smb_dev = pci_find_bsf(0, 20, 0);
KASSERT(smb_dev != NULL, ("can't find SMBus PCI device\n"));
- if (pci_get_revid(smb_dev) < AMDSB8_SMBUS_REVID)
+ if (pci_get_devid(smb_dev) == AMDSB_SMBUS_DEVID &&
+ pci_get_revid(smb_dev) < AMDSB8_SMBUS_REVID)
amdsbwd_probe_sb7xx(dev, res, &addr);
else
amdsbwd_probe_sb8xx(dev, res, &addr);
@@ -440,10 +447,7 @@ amdsbwd_attach_sb(device_t dev, struct amdsbwd_softc *sc)
smb_dev = pci_find_bsf(0, 20, 0);
KASSERT(smb_dev != NULL, ("can't find SMBus PCI device\n"));
- if (pci_get_revid(smb_dev) < AMDSB8_SMBUS_REVID)
- sc->ms_per_tick = 10;
- else
- sc->ms_per_tick = 1000;
+ sc->ms_per_tick = 1000;
sc->res_ctrl = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
&sc->rid_ctrl, RF_ACTIVE);
diff --git a/sys/dev/arcmsr/arcmsr.c b/sys/dev/arcmsr/arcmsr.c
index 3cf7fce..cabb99a 100644
--- a/sys/dev/arcmsr/arcmsr.c
+++ b/sys/dev/arcmsr/arcmsr.c
@@ -872,7 +872,7 @@ static void arcmsr_srb_timeout(void *arg)
ARCMSR_LOCK_ACQUIRE(&acb->isr_lock);
if(srb->srb_state == ARCMSR_SRB_START)
{
- cmd = srb->pccb->csio.cdb_io.cdb_bytes[0];
+ cmd = scsiio_cdb_ptr(&srb->pccb->csio)[0];
srb->srb_state = ARCMSR_SRB_TIMEOUT;
srb->pccb->ccb_h.status |= CAM_CMD_TIMEOUT;
arcmsr_srb_complete(srb, 1);
@@ -997,7 +997,7 @@ static void arcmsr_build_srb(struct CommandControlBlock *srb,
arcmsr_cdb->LUN = pccb->ccb_h.target_lun;
arcmsr_cdb->Function = 1;
arcmsr_cdb->CdbLength = (u_int8_t)pcsio->cdb_len;
- bcopy(pcsio->cdb_io.cdb_bytes, arcmsr_cdb->Cdb, pcsio->cdb_len);
+ bcopy(scsiio_cdb_ptr(pcsio), arcmsr_cdb->Cdb, pcsio->cdb_len);
if(nseg != 0) {
struct AdapterControlBlock *acb = srb->acb;
bus_dmasync_op_t op;
@@ -2453,10 +2453,11 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *p
struct CMD_MESSAGE_FIELD *pcmdmessagefld;
int retvalue = 0, transfer_len = 0;
char *buffer;
- u_int32_t controlcode = (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[5] << 24 |
- (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[6] << 16 |
- (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[7] << 8 |
- (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[8];
+ uint8_t *ptr = scsiio_cdb_ptr(&pccb->csio);
+ u_int32_t controlcode = (u_int32_t ) ptr[5] << 24 |
+ (u_int32_t ) ptr[6] << 16 |
+ (u_int32_t ) ptr[7] << 8 |
+ (u_int32_t ) ptr[8];
/* 4 bytes: Areca io control code */
if ((pccb->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR) {
buffer = pccb->csio.data_ptr;
@@ -2683,7 +2684,7 @@ static void arcmsr_execute_srb(void *arg, bus_dma_segment_t *dm_segs, int nseg,
if(acb->devstate[target][lun] == ARECA_RAID_GONE) {
u_int8_t block_cmd, cmd;
- cmd = pccb->csio.cdb_io.cdb_bytes[0];
+ cmd = scsiio_cdb_ptr(&pccb->csio)[0];
block_cmd = cmd & 0x0f;
if(block_cmd == 0x08 || block_cmd == 0x0a) {
printf("arcmsr%d:block 'read/write' command "
@@ -2800,7 +2801,7 @@ static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb,
return;
}
pccb->ccb_h.status |= CAM_REQ_CMP;
- switch (pccb->csio.cdb_io.cdb_bytes[0]) {
+ switch (scsiio_cdb_ptr(&pccb->csio)[0]) {
case INQUIRY: {
unsigned char inqdata[36];
char *buffer = pccb->csio.data_ptr;
@@ -2853,6 +2854,12 @@ static void arcmsr_action(struct cam_sim *psim, union ccb *pccb)
int target = pccb->ccb_h.target_id;
int error;
+ if (pccb->ccb_h.flags & CAM_CDB_PHYS) {
+ pccb->ccb_h.status = CAM_REQ_INVALID;
+ xpt_done(pccb);
+ return;
+ }
+
if(target == 16) {
/* virtual device for iop message transfer */
arcmsr_handle_virtual_command(acb, pccb);
diff --git a/sys/dev/ata/ata-lowlevel.c b/sys/dev/ata/ata-lowlevel.c
index 6b825c0..1c81c6f 100644
--- a/sys/dev/ata/ata-lowlevel.c
+++ b/sys/dev/ata/ata-lowlevel.c
@@ -851,7 +851,7 @@ ata_pio_read(struct ata_request *request, int length)
panic("ata_pio_read: Unsupported CAM data type %x\n",
(request->ccb->ccb_h.flags & CAM_DATA_MASK));
- /* We may have extra byte already red but not stored. */
+ /* We may have extra byte already read but not stored. */
if (resid) {
addr[0] = buf[1];
addr++;
diff --git a/sys/dev/ath/if_ath_lna_div.c b/sys/dev/ath/if_ath_lna_div.c
index f0a33a5..5c770c0 100644
--- a/sys/dev/ath/if_ath_lna_div.c
+++ b/sys/dev/ath/if_ath_lna_div.c
@@ -766,7 +766,7 @@ ath_lna_rx_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs,
/* Short scan check */
if (antcomb->scan && antcomb->alt_good) {
- if (time_after(ticks, antcomb->scan_start_time +
+ if (ieee80211_time_after(ticks, antcomb->scan_start_time +
msecs_to_jiffies(ATH_ANT_DIV_COMB_SHORT_SCAN_INTR)))
short_scan = AH_TRUE;
else
diff --git a/sys/dev/atkbdc/atkbdc_subr.c b/sys/dev/atkbdc/atkbdc_subr.c
index 28730c6..436d97a 100644
--- a/sys/dev/atkbdc/atkbdc_subr.c
+++ b/sys/dev/atkbdc/atkbdc_subr.c
@@ -63,7 +63,7 @@ atkbdc_print_child(device_t bus, device_t dev)
retval += printf(" flags 0x%x", flags);
irq = bus_get_resource_start(dev, SYS_RES_IRQ, kbdcdev->rid);
if (irq != 0)
- retval += printf(" irq %ld", irq);
+ retval += printf(" irq %jd", irq);
retval += bus_print_child_footer(bus, dev);
return (retval);
diff --git a/sys/dev/bhnd/bhnd.c b/sys/dev/bhnd/bhnd.c
index 674094a..860d58d 100644
--- a/sys/dev/bhnd/bhnd.c
+++ b/sys/dev/bhnd/bhnd.c
@@ -451,7 +451,7 @@ bhnd_generic_print_child(device_t dev, device_t child)
rl = BUS_GET_RESOURCE_LIST(dev, child);
if (rl != NULL) {
retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY,
- "%#lx");
+ "%#jx");
}
retval += printf(" at core %u", bhnd_get_core_index(child));
@@ -499,7 +499,7 @@ bhnd_generic_probe_nomatch(device_t dev, device_t child)
rl = BUS_GET_RESOURCE_LIST(dev, child);
if (rl != NULL)
- resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
+ resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
printf(" at core %u (no driver attached)\n",
bhnd_get_core_index(child));
diff --git a/sys/dev/bhnd/bhndb/bhndb.c b/sys/dev/bhnd/bhndb/bhndb.c
index 238d4ee..43580b7 100644
--- a/sys/dev/bhnd/bhndb/bhndb.c
+++ b/sys/dev/bhnd/bhndb/bhndb.c
@@ -143,9 +143,9 @@ bhndb_print_child(device_t dev, device_t child)
rl = BUS_GET_RESOURCE_LIST(dev, child);
if (rl != NULL) {
retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY,
- "%#lx");
+ "%#jx");
retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ,
- "%ld");
+ "%jd");
}
retval += bus_print_child_domain(dev, child);
diff --git a/sys/dev/bwn/if_bwn.c b/sys/dev/bwn/if_bwn.c
index 2f474d1..decef5f 100644
--- a/sys/dev/bwn/if_bwn.c
+++ b/sys/dev/bwn/if_bwn.c
@@ -2612,7 +2612,7 @@ bwn_phy_g_task_15s(struct bwn_mac *mac)
BWN_GETTIME(now);
if (bwn_has_hwpctl(mac)) {
expire = now - BWN_LO_PWRVEC_EXPIRE;
- if (time_before(lo->pwr_vec_read_time, expire)) {
+ if (ieee80211_time_before(lo->pwr_vec_read_time, expire)) {
bwn_lo_get_powervector(mac);
bwn_phy_g_dc_lookup_init(mac, 0);
}
@@ -2621,7 +2621,7 @@ bwn_phy_g_task_15s(struct bwn_mac *mac)
expire = now - BWN_LO_CALIB_EXPIRE;
TAILQ_FOREACH_SAFE(cal, &lo->calib_list, list, tmp) {
- if (!time_before(cal->calib_time, expire))
+ if (!ieee80211_time_before(cal->calib_time, expire))
continue;
if (BWN_BBATTCMP(&cal->bbatt, &pg->pg_bbatt) &&
BWN_RFATTCMP(&cal->rfatt, &pg->pg_rfatt)) {
@@ -6149,7 +6149,7 @@ bwn_lo_save(struct bwn_mac *mac, struct bwn_lo_g_value *sav)
BWN_PHY_WRITE(mac, BWN_PHY_CCK(0x2f), 0);
nanouptime(&ts);
- if (time_before(lo->txctl_measured_time,
+ if (ieee80211_time_before(lo->txctl_measured_time,
(ts.tv_nsec / 1000000 + ts.tv_sec * 1000) - BWN_LO_TXCTL_EXPIRE))
bwn_lo_measure_txctl_values(mac);
@@ -9365,7 +9365,7 @@ bwn_phy_txpower_check(struct bwn_mac *mac, uint32_t flags)
BWN_GETTIME(now);
- if (!(flags & BWN_TXPWR_IGNORE_TIME) && time_before(now, phy->nexttime))
+ if (!(flags & BWN_TXPWR_IGNORE_TIME) && ieee80211_time_before(now, phy->nexttime))
return;
phy->nexttime = now + 2 * 1000;
diff --git a/sys/dev/bxe/bxe.c b/sys/dev/bxe/bxe.c
index d944395..53d8e97 100644
--- a/sys/dev/bxe/bxe.c
+++ b/sys/dev/bxe/bxe.c
@@ -3063,7 +3063,7 @@ bxe_tpa_stop(struct bxe_softc *sc,
#if __FreeBSD_version >= 800000
/* specify what RSS queue was used for this flow */
m->m_pkthdr.flowid = fp->index;
- M_HASHTYPE_SET(m, M_HASHTYPE_OPAQUE);
+ BXE_SET_FLOWID(m);
#endif
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
@@ -3352,7 +3352,7 @@ bxe_rxeof(struct bxe_softc *sc,
#if __FreeBSD_version >= 800000
/* specify what RSS queue was used for this flow */
m->m_pkthdr.flowid = fp->index;
- M_HASHTYPE_SET(m, M_HASHTYPE_OPAQUE);
+ BXE_SET_FLOWID(m);
#endif
next_rx:
@@ -4829,6 +4829,8 @@ bxe_dump_mbuf(struct bxe_softc *sc,
}
while (m) {
+
+#if __FreeBSD_version >= 1000000
BLOGD(sc, DBG_MBUF,
"%02d: mbuf=%p m_len=%d m_flags=0x%b m_data=%p\n",
i, m, m->m_len, m->m_flags, M_FLAG_BITS, m->m_data);
@@ -4839,6 +4841,26 @@ bxe_dump_mbuf(struct bxe_softc *sc,
i, m->m_pkthdr.len, m->m_flags, M_FLAG_BITS,
(int)m->m_pkthdr.csum_flags, CSUM_BITS);
}
+#else
+ BLOGD(sc, DBG_MBUF,
+ "%02d: mbuf=%p m_len=%d m_flags=0x%b m_data=%p\n",
+ i, m, m->m_len, m->m_flags,
+ "\20\1M_EXT\2M_PKTHDR\3M_EOR\4M_RDONLY", m->m_data);
+
+ if (m->m_flags & M_PKTHDR) {
+ BLOGD(sc, DBG_MBUF,
+ "%02d: - m_pkthdr: tot_len=%d flags=0x%b csum_flags=%b\n",
+ i, m->m_pkthdr.len, m->m_flags,
+ "\20\12M_BCAST\13M_MCAST\14M_FRAG"
+ "\15M_FIRSTFRAG\16M_LASTFRAG\21M_VLANTAG"
+ "\22M_PROMISC\23M_NOFREE",
+ (int)m->m_pkthdr.csum_flags,
+ "\20\1CSUM_IP\2CSUM_TCP\3CSUM_UDP\4CSUM_IP_FRAGS"
+ "\5CSUM_FRAGMENT\6CSUM_TSO\11CSUM_IP_CHECKED"
+ "\12CSUM_IP_VALID\13CSUM_DATA_VALID"
+ "\14CSUM_PSEUDO_HDR");
+ }
+#endif /* #if __FreeBSD_version >= 1000000 */
if (m->m_flags & M_EXT) {
switch (m->m_ext.ext_type) {
@@ -5222,7 +5244,9 @@ bxe_tx_encap(struct bxe_fastpath *fp, struct mbuf **m_head)
sc = fp->sc;
+#if __FreeBSD_version >= 800000
M_ASSERTPKTHDR(*m_head);
+#endif /* #if __FreeBSD_version >= 800000 */
m0 = *m_head;
rc = defragged = nbds = ovlan = vlan_off = total_pkt_size = 0;
@@ -5741,7 +5765,7 @@ bxe_tx_mq_start_locked(struct bxe_softc *sc,
if (!sc->link_vars.link_up ||
(if_getdrvflags(ifp) &
(IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != IFF_DRV_RUNNING) {
- rc = drbr_enqueue_drv(ifp, tx_br, m);
+ rc = drbr_enqueue(ifp, tx_br, m);
goto bxe_tx_mq_start_locked_exit;
}
@@ -5756,7 +5780,7 @@ bxe_tx_mq_start_locked(struct bxe_softc *sc,
next = drbr_dequeue_drv(ifp, tx_br);
} else if (drbr_needs_enqueue_drv(ifp, tx_br)) {
/* have both new and pending work, maintain packet order */
- rc = drbr_enqueue_drv(ifp, tx_br, m);
+ rc = drbr_enqueue(ifp, tx_br, m);
if (rc != 0) {
fp->eth_q_stats.tx_soft_errors++;
goto bxe_tx_mq_start_locked_exit;
@@ -5785,7 +5809,7 @@ bxe_tx_mq_start_locked(struct bxe_softc *sc,
/* mark the TX queue as full and save the frame */
if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0);
/* XXX this may reorder the frame */
- rc = drbr_enqueue_drv(ifp, tx_br, next);
+ rc = drbr_enqueue(ifp, tx_br, next);
fp->eth_q_stats.mbuf_alloc_tx--;
fp->eth_q_stats.tx_frames_deferred++;
}
@@ -5837,7 +5861,8 @@ bxe_tx_mq_start(struct ifnet *ifp,
fp_index = 0; /* default is the first queue */
/* check if flowid is set */
- if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE)
+
+ if (BXE_VALID_FLOWID(m))
fp_index = (m->m_pkthdr.flowid % sc->num_queues);
fp = &sc->fp[fp_index];
@@ -5846,7 +5871,7 @@ bxe_tx_mq_start(struct ifnet *ifp,
rc = bxe_tx_mq_start_locked(sc, ifp, fp, m);
BXE_FP_TX_UNLOCK(fp);
} else
- rc = drbr_enqueue_drv(ifp, fp->tx_br, m);
+ rc = drbr_enqueue(ifp, fp->tx_br, m);
return (rc);
}
@@ -12845,7 +12870,7 @@ bxe_allocate_bars(struct bxe_softc *sc)
sc->bar[i].handle = rman_get_bushandle(sc->bar[i].resource);
sc->bar[i].kva = (vm_offset_t)rman_get_virtual(sc->bar[i].resource);
- BLOGI(sc, "PCI BAR%d [%02x] memory allocated: %p-%p (%ld) -> %p\n",
+ BLOGI(sc, "PCI BAR%d [%02x] memory allocated: %p-%p (%jd) -> %p\n",
i, PCIR_BAR(i),
(void *)rman_get_start(sc->bar[i].resource),
(void *)rman_get_end(sc->bar[i].resource),
@@ -15677,18 +15702,11 @@ bxe_add_sysctls(struct bxe_softc *sc)
CTLFLAG_RD, BXE_DRIVER_VERSION, 0,
"version");
- SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "bc_version",
- CTLFLAG_RD, sc->devinfo.bc_ver_str, 0,
- "bootcode version");
-
snprintf(sc->fw_ver_str, sizeof(sc->fw_ver_str), "%d.%d.%d.%d",
BCM_5710_FW_MAJOR_VERSION,
BCM_5710_FW_MINOR_VERSION,
BCM_5710_FW_REVISION_VERSION,
BCM_5710_FW_ENGINEERING_VERSION);
- SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "fw_version",
- CTLFLAG_RD, sc->fw_ver_str, 0,
- "firmware version");
snprintf(sc->mf_mode_str, sizeof(sc->mf_mode_str), "%s",
((sc->devinfo.mf_info.mf_mode == SINGLE_FUNCTION) ? "Single" :
@@ -15696,32 +15714,58 @@ bxe_add_sysctls(struct bxe_softc *sc)
(sc->devinfo.mf_info.mf_mode == MULTI_FUNCTION_SI) ? "MF-SI" :
(sc->devinfo.mf_info.mf_mode == MULTI_FUNCTION_AFEX) ? "MF-AFEX" :
"Unknown"));
- SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "mf_mode",
- CTLFLAG_RD, sc->mf_mode_str, 0,
- "multifunction mode");
-
SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "mf_vnics",
CTLFLAG_RD, &sc->devinfo.mf_info.vnics_per_port, 0,
"multifunction vnics per port");
- SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "mac_addr",
- CTLFLAG_RD, sc->mac_addr_str, 0,
- "mac address");
-
snprintf(sc->pci_link_str, sizeof(sc->pci_link_str), "%s x%d",
((sc->devinfo.pcie_link_speed == 1) ? "2.5GT/s" :
(sc->devinfo.pcie_link_speed == 2) ? "5.0GT/s" :
(sc->devinfo.pcie_link_speed == 4) ? "8.0GT/s" :
"???GT/s"),
sc->devinfo.pcie_link_width);
+
+ sc->debug = bxe_debug;
+
+#if __FreeBSD_version >= 900000
+ SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "bc_version",
+ CTLFLAG_RD, sc->devinfo.bc_ver_str, 0,
+ "bootcode version");
+ SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "fw_version",
+ CTLFLAG_RD, sc->fw_ver_str, 0,
+ "firmware version");
+ SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "mf_mode",
+ CTLFLAG_RD, sc->mf_mode_str, 0,
+ "multifunction mode");
+ SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "mac_addr",
+ CTLFLAG_RD, sc->mac_addr_str, 0,
+ "mac address");
SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "pci_link",
CTLFLAG_RD, sc->pci_link_str, 0,
"pci link status");
-
- sc->debug = bxe_debug;
SYSCTL_ADD_ULONG(ctx, children, OID_AUTO, "debug",
CTLFLAG_RW, &sc->debug,
"debug logging mode");
+#else
+ SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "bc_version",
+ CTLFLAG_RD, &sc->devinfo.bc_ver_str, 0,
+ "bootcode version");
+ SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "fw_version",
+ CTLFLAG_RD, &sc->fw_ver_str, 0,
+ "firmware version");
+ SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "mf_mode",
+ CTLFLAG_RD, &sc->mf_mode_str, 0,
+ "multifunction mode");
+ SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "mac_addr",
+ CTLFLAG_RD, &sc->mac_addr_str, 0,
+ "mac address");
+ SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "pci_link",
+ CTLFLAG_RD, &sc->pci_link_str, 0,
+ "pci link status");
+ SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "debug",
+ CTLFLAG_RW, &sc->debug, 0,
+ "debug logging mode");
+#endif /* #if __FreeBSD_version >= 900000 */
SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "trigger_grcdump",
CTLTYPE_UINT | CTLFLAG_RW, sc, 0,
diff --git a/sys/dev/bxe/bxe.h b/sys/dev/bxe/bxe.h
index e87c65b..73f72ce 100644
--- a/sys/dev/bxe/bxe.h
+++ b/sys/dev/bxe/bxe.h
@@ -2271,6 +2271,17 @@ void bxe_dump_mem(struct bxe_softc *sc, char *tag,
void bxe_dump_mbuf_data(struct bxe_softc *sc, char *pTag,
struct mbuf *m, uint8_t contents);
+
+#if __FreeBSD_version >= 800000
+#if __FreeBSD_version >= 1000000
+#define BXE_SET_FLOWID(m) M_HASHTYPE_SET(m, M_HASHTYPE_OPAQUE)
+#define BXE_VALID_FLOWID(m) (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE)
+#else
+#define BXE_VALID_FLOWID(m) ((m->m_flags & M_FLOWID) != 0)
+#define BXE_SET_FLOWID(m) m->m_flags |= M_FLOWID
+#endif
+#endif /* #if __FreeBSD_version >= 800000 */
+
/***********/
/* INLINES */
/***********/
diff --git a/sys/dev/cardbus/cardbus_cis.c b/sys/dev/cardbus/cardbus_cis.c
index 5d7704a..f9f7816 100644
--- a/sys/dev/cardbus/cardbus_cis.c
+++ b/sys/dev/cardbus/cardbus_cis.c
@@ -485,7 +485,8 @@ cardbus_read_tuple_init(device_t cbdev, device_t child, uint32_t *start,
"to read CIS.\n");
return (NULL);
}
- DEVPRINTF((cbdev, "CIS Mapped to %#lx\n", rman_get_start(res)));
+ DEVPRINTF((cbdev, "CIS Mapped to %#jx\n",
+ rman_get_start(res)));
/* Flip to the right ROM image if CIS is in ROM */
if (space == PCIM_CIS_ASI_ROM) {
diff --git a/sys/dev/ctau/if_ct.c b/sys/dev/ctau/if_ct.c
index da8d32c..a3df2a8 100644
--- a/sys/dev/ctau/if_ct.c
+++ b/sys/dev/ctau/if_ct.c
@@ -459,7 +459,7 @@ static int ct_probe (device_t dev)
}
if (!ct_probe_board (iobase, -1, -1)) {
- printf ("ct%d: probing for Tau-ISA at %lx faild\n", unit, iobase);
+ printf ("ct%d: probing for Tau-ISA at %jx faild\n", unit, iobase);
return ENXIO;
}
@@ -632,7 +632,7 @@ static int ct_attach (device_t dev)
ct_ln[2] = '0' + unit;
mtx_init (&bd->ct_mtx, ct_ln, MTX_NETWORK_LOCK, MTX_DEF|MTX_RECURSE);
if (! probe_irq (b, irq)) {
- printf ("ct%d: irq %ld not functional\n", unit, irq);
+ printf ("ct%d: irq %jd not functional\n", unit, irq);
bd->board = 0;
adapter [unit] = 0;
free (b, M_DEVBUF);
@@ -651,7 +651,7 @@ static int ct_attach (device_t dev)
if (bus_setup_intr (dev, bd->irq_res,
INTR_TYPE_NET|INTR_MPSAFE,
NULL, ct_intr, bd, &bd->intrhand)) {
- printf ("ct%d: Can't setup irq %ld\n", unit, irq);
+ printf ("ct%d: Can't setup irq %jd\n", unit, irq);
bd->board = 0;
adapter [unit] = 0;
free (b, M_DEVBUF);
diff --git a/sys/dev/cxgb/cxgb_sge.c b/sys/dev/cxgb/cxgb_sge.c
index a622fcf..c83bd66 100644
--- a/sys/dev/cxgb/cxgb_sge.c
+++ b/sys/dev/cxgb/cxgb_sge.c
@@ -2976,11 +2976,7 @@ process_responses(adapter_t *adap, struct sge_qset *qs, int budget)
#if defined(INET6) || defined(INET)
/* Flush LRO */
- while (!SLIST_EMPTY(&lro_ctrl->lro_active)) {
- struct lro_entry *queued = SLIST_FIRST(&lro_ctrl->lro_active);
- SLIST_REMOVE_HEAD(&lro_ctrl->lro_active, next);
- tcp_lro_flush(lro_ctrl, queued);
- }
+ tcp_lro_flush_all(lro_ctrl);
#endif
if (sleeping)
diff --git a/sys/dev/cxgbe/adapter.h b/sys/dev/cxgbe/adapter.h
index ee14712..2193142 100644
--- a/sys/dev/cxgbe/adapter.h
+++ b/sys/dev/cxgbe/adapter.h
@@ -246,12 +246,10 @@ struct vi_info {
int rsrv_noflowq; /* Reserve queue 0 for non-flowid packets */
int nrxq; /* # of rx queues */
int first_rxq; /* index of first rx queue */
-#ifdef TCP_OFFLOAD
int nofldtxq; /* # of offload tx queues */
int first_ofld_txq; /* index of first offload tx queue */
int nofldrxq; /* # of offload rx queues */
int first_ofld_rxq; /* index of first offload rx queue */
-#endif
int tmr_idx;
int pktc_idx;
int qsize_rxq;
@@ -311,9 +309,7 @@ struct cluster_layout {
struct cluster_metadata {
u_int refcount;
-#ifdef INVARIANTS
struct fl_sdesc *sd; /* For debug only. Could easily be stale */
-#endif
};
struct fl_sdesc {
@@ -571,7 +567,6 @@ iq_to_rxq(struct sge_iq *iq)
}
-#ifdef TCP_OFFLOAD
/* ofld_rxq: SGE ingress queue + SGE free list + miscellaneous items */
struct sge_ofld_rxq {
struct sge_iq iq; /* MUST be first */
@@ -584,7 +579,6 @@ iq_to_ofld_rxq(struct sge_iq *iq)
return (__containerof(iq, struct sge_ofld_rxq, iq));
}
-#endif
struct wrqe {
STAILQ_ENTRY(wrqe) link;
@@ -636,7 +630,6 @@ struct sge_wrq {
} __aligned(CACHE_LINE_SIZE);
-#ifdef DEV_NETMAP
struct sge_nm_rxq {
struct vi_info *vi;
@@ -691,19 +684,14 @@ struct sge_nm_txq {
bus_addr_t ba;
int iqidx;
} __aligned(CACHE_LINE_SIZE);
-#endif
struct sge {
int nrxq; /* total # of Ethernet rx queues */
int ntxq; /* total # of Ethernet tx tx queues */
-#ifdef TCP_OFFLOAD
int nofldrxq; /* total # of TOE rx queues */
int nofldtxq; /* total # of TOE tx queues */
-#endif
-#ifdef DEV_NETMAP
int nnmrxq; /* total # of netmap rx queues */
int nnmtxq; /* total # of netmap tx queues */
-#endif
int niq; /* total # of ingress queues */
int neq; /* total # of egress queues */
@@ -712,14 +700,10 @@ struct sge {
struct sge_wrq *ctrlq; /* Control queues */
struct sge_txq *txq; /* NIC tx queues */
struct sge_rxq *rxq; /* NIC rx queues */
-#ifdef TCP_OFFLOAD
struct sge_wrq *ofld_txq; /* TOE tx queues */
struct sge_ofld_rxq *ofld_rxq; /* TOE rx queues */
-#endif
-#ifdef DEV_NETMAP
struct sge_nm_txq *nm_txq; /* netmap tx queues */
struct sge_nm_rxq *nm_rxq; /* netmap rx queues */
-#endif
uint16_t iq_start;
int eq_start;
@@ -778,20 +762,16 @@ struct adapter {
struct port_info *port[MAX_NPORTS];
uint8_t chan_map[MAX_NCHAN];
-#ifdef TCP_OFFLOAD
void *tom_softc; /* (struct tom_data *) */
struct tom_tunables tt;
void *iwarp_softc; /* (struct c4iw_dev *) */
void *iscsi_ulp_softc; /* (struct cxgbei_data *) */
-#endif
struct l2t_data *l2t; /* L2 table */
struct tid_info tids;
uint16_t doorbells;
-#ifdef TCP_OFFLOAD
int offload_map; /* ports with IFCAP_TOE enabled */
int active_ulds; /* ULDs activated on this adapter */
-#endif
int flags;
int debug_flags;
@@ -840,11 +820,9 @@ struct adapter {
fw_msg_handler_t fw_msg_handler[7]; /* NUM_FW6_TYPES */
cpl_handler_t cpl_handler[0xef]; /* NUM_CPL_CMDS */
-#ifdef INVARIANTS
const char *last_op;
const void *last_op_thr;
int last_op_flags;
-#endif
int sc_do_rxcopy;
};
diff --git a/sys/dev/cxgbe/common/t4_hw.c b/sys/dev/cxgbe/common/t4_hw.c
index 92104c8..588f6fd 100644
--- a/sys/dev/cxgbe/common/t4_hw.c
+++ b/sys/dev/cxgbe/common/t4_hw.c
@@ -5615,6 +5615,7 @@ void t4_get_port_stats_offset(struct adapter *adap, int idx,
void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p)
{
u32 bgmap = t4_get_mps_bg_map(adap, idx);
+ u32 stat_ctl;
#define GET_STAT(name) \
t4_read_reg64(adap, \
@@ -5622,6 +5623,8 @@ void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p)
T5_PORT_REG(idx, A_MPS_PORT_STAT_##name##_L)))
#define GET_STAT_COM(name) t4_read_reg64(adap, A_MPS_STAT_##name##_L)
+ stat_ctl = t4_read_reg(adap, A_MPS_STAT_CTL);
+
p->tx_pause = GET_STAT(TX_PORT_PAUSE);
p->tx_octets = GET_STAT(TX_PORT_BYTES);
p->tx_frames = GET_STAT(TX_PORT_FRAMES);
@@ -5646,6 +5649,12 @@ void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p)
p->tx_ppp6 = GET_STAT(TX_PORT_PPP6);
p->tx_ppp7 = GET_STAT(TX_PORT_PPP7);
+ if (stat_ctl & F_COUNTPAUSESTATTX) {
+ p->tx_frames -= p->tx_pause;
+ p->tx_octets -= p->tx_pause * 64;
+ p->tx_mcast_frames -= p->tx_pause;
+ }
+
p->rx_pause = GET_STAT(RX_PORT_PAUSE);
p->rx_octets = GET_STAT(RX_PORT_BYTES);
p->rx_frames = GET_STAT(RX_PORT_FRAMES);
@@ -5674,6 +5683,12 @@ void t4_get_port_stats(struct adapter *adap, int idx, struct port_stats *p)
p->rx_ppp6 = GET_STAT(RX_PORT_PPP6);
p->rx_ppp7 = GET_STAT(RX_PORT_PPP7);
+ if (stat_ctl & F_COUNTPAUSESTATRX) {
+ p->rx_frames -= p->rx_pause;
+ p->rx_octets -= p->rx_pause * 64;
+ p->rx_mcast_frames -= p->rx_pause;
+ }
+
p->rx_ovflow0 = (bgmap & 1) ? GET_STAT_COM(RX_BG_0_MAC_DROP_FRAME) : 0;
p->rx_ovflow1 = (bgmap & 2) ? GET_STAT_COM(RX_BG_1_MAC_DROP_FRAME) : 0;
p->rx_ovflow2 = (bgmap & 4) ? GET_STAT_COM(RX_BG_2_MAC_DROP_FRAME) : 0;
diff --git a/sys/dev/cxgbe/firmware/t4fw_cfg.txt b/sys/dev/cxgbe/firmware/t4fw_cfg.txt
index 0e13122..43820a0 100644
--- a/sys/dev/cxgbe/firmware/t4fw_cfg.txt
+++ b/sys/dev/cxgbe/firmware/t4fw_cfg.txt
@@ -10,7 +10,7 @@
[global]
rss_glb_config_mode = basicvirtual
- rss_glb_config_options = tnlmapen, hashtoeplitz, tnlalllkp
+ rss_glb_config_options = tnlmapen,hashtoeplitz,tnlalllkp
sge_timer_value = 1, 5, 10, 50, 100, 200 # usecs
@@ -20,61 +20,82 @@
# disable TP_PARA_REG3.RxFragEn
reg[0x7d6c] = 0x00000000/0x00007000
- # TP_SHIFT_CNT
- reg[0x7dc0] = 0x62f8849
+ reg[0x7dc0] = 0x0e2f8849 # TP_SHIFT_CNT
filterMode = fragmentation, mpshittype, protocol, vlan, port, fcoe
filterMask = protocol, fcoe
- # TP rx and tx channels (0 = auto).
+ tp_pmrx = 36, 512
+ tp_pmrx_pagesize = 64K
+
+ # TP number of RX channels (0 = auto)
tp_nrxch = 0
- tp_ntxch = 0
- # TP rx and tx payload memory (% of the total EDRAM + DDR3).
- tp_pmrx = 38, 512
- tp_pmtx = 60, 512
- tp_pmrx_pagesize = 64K
+ tp_pmtx = 46, 512
tp_pmtx_pagesize = 64K
- # cluster, lan, or wan.
- tp_tcptuning = lan
+ # TP number of TX channels (0 = auto)
+ tp_ntxch = 0
# TP OFLD MTUs
tp_mtus = 88, 256, 512, 576, 808, 1024, 1280, 1488, 1500, 2002, 2048, 4096, 4352, 8192, 9000, 9600
+ # cluster, lan, or wan.
+ tp_tcptuning = lan
+
# PFs 0-3. These get 8 MSI/8 MSI-X vectors each. VFs are supported by
-# these 4 PFs only. Not used here at all.
+# these 4 PFs only.
[function "0"]
- nvf = 16
- nvi = 1
- rssnvi = 0
-[function "0/*"]
- nvi = 1
- rssnvi = 0
+ nvf = 4
+ wx_caps = all
+ r_caps = all
+ nvi = 2
+ rssnvi = 2
+ niqflint = 4
+ nethctrl = 4
+ neq = 8
+ nexactf = 4
+ cmask = all
+ pmask = 0x1
[function "1"]
- nvf = 16
- nvi = 1
- rssnvi = 0
-[function "1/*"]
- nvi = 1
- rssnvi = 0
+ nvf = 4
+ wx_caps = all
+ r_caps = all
+ nvi = 2
+ rssnvi = 2
+ niqflint = 4
+ nethctrl = 4
+ neq = 8
+ nexactf = 4
+ cmask = all
+ pmask = 0x2
[function "2"]
- nvf = 16
- nvi = 1
- rssnvi = 0
-[function "2/*"]
- nvi = 1
- rssnvi = 0
+ nvf = 4
+ wx_caps = all
+ r_caps = all
+ nvi = 2
+ rssnvi = 2
+ niqflint = 4
+ nethctrl = 4
+ neq = 8
+ nexactf = 4
+ cmask = all
+ pmask = 0x4
[function "3"]
- nvf = 16
- nvi = 1
- rssnvi = 0
-[function "3/*"]
- nvi = 1
- rssnvi = 0
+ nvf = 4
+ wx_caps = all
+ r_caps = all
+ nvi = 2
+ rssnvi = 2
+ niqflint = 4
+ nethctrl = 4
+ neq = 8
+ nexactf = 4
+ cmask = all
+ pmask = 0x8
# PF4 is the resource-rich PF that the bus/nexus driver attaches to.
# It gets 32 MSI/128 MSI-X vectors.
@@ -86,15 +107,19 @@
niqflint = 512
nethctrl = 1024
neq = 2048
- nexactf = 328
+ nexactf = 280
cmask = all
pmask = all
# driver will mask off features it won't use
- protocol = ofld
+ protocol = ofld, rddp, rdmac, iscsi_initiator_pdu, iscsi_target_pdu
tp_l2t = 4096
tp_ddp = 2
+ tp_ddp_iscsi = 2
+ tp_stag = 2
+ tp_pbl = 5
+ tp_rq = 7
# TCAM has 8K cells; each region must start at a multiple of 128 cell.
# Each entry in these categories takes 4 cells each. nhash will use the
@@ -130,6 +155,60 @@
nexactf = 8
nfilter = 16
+# For Virtual functions, we only allow NIC functionality and we only allow
+# access to one port (1 << PF). Note that because of limitations in the
+# Scatter Gather Engine (SGE) hardware which checks writes to VF KDOORBELL
+# and GTS registers, the number of Ingress and Egress Queues must be a power
+# of 2.
+#
+[function "0/*"]
+ wx_caps = 0x82
+ r_caps = 0x86
+ nvi = 1
+ rssnvi = 1
+ niqflint = 2
+ nethctrl = 2
+ neq = 4
+ nexactf = 2
+ cmask = all
+ pmask = 0x1
+
+[function "1/*"]
+ wx_caps = 0x82
+ r_caps = 0x86
+ nvi = 1
+ rssnvi = 1
+ niqflint = 2
+ nethctrl = 2
+ neq = 4
+ nexactf = 2
+ cmask = all
+ pmask = 0x2
+
+[function "2/*"]
+ wx_caps = 0x82
+ r_caps = 0x86
+ nvi = 1
+ rssnvi = 1
+ niqflint = 2
+ nethctrl = 2
+ neq = 4
+ nexactf = 2
+ cmask = all
+ pmask = 0x4
+
+[function "3/*"]
+ wx_caps = 0x82
+ r_caps = 0x86
+ nvi = 1
+ rssnvi = 1
+ niqflint = 2
+ nethctrl = 2
+ neq = 4
+ nexactf = 2
+ cmask = all
+ pmask = 0x8
+
# MPS has 192K buffer space for ingress packets from the wire as well as
# loopback path of the L2 switch.
[port "0"]
@@ -166,7 +245,7 @@
[fini]
version = 0x1
- checksum = 0x98210e18
+ checksum = 0xbec0621
#
# $FreeBSD$
#
diff --git a/sys/dev/cxgbe/firmware/t5fw_cfg.txt b/sys/dev/cxgbe/firmware/t5fw_cfg.txt
index 4ae6c99..9e16da5 100644
--- a/sys/dev/cxgbe/firmware/t5fw_cfg.txt
+++ b/sys/dev/cxgbe/firmware/t5fw_cfg.txt
@@ -10,12 +10,33 @@
[global]
rss_glb_config_mode = basicvirtual
- rss_glb_config_options = tnlmapen, hashtoeplitz, tnlalllkp
+ rss_glb_config_options = tnlmapen,hashtoeplitz,tnlalllkp
# PL_TIMEOUT register
- pl_timeout_value = 200 # the timeout value in units of us
+ pl_timeout_value = 10000 # the timeout value in units of us
- sge_timer_value = 1, 5, 10, 50, 100, 200 # usecs
+ # SGE_THROTTLE_CONTROL
+ bar2throttlecount = 500 # bar2throttlecount in us
+
+ sge_timer_value = 1, 5, 10, 50, 100, 200 # SGE_TIMER_VALUE* in usecs
+
+ reg[0x1124] = 0x00000400/0x00000400 # SGE_CONTROL2, enable VFIFO; if
+ # SGE_VFIFO_SIZE is not set, then
+ # firmware will set it up in function
+ # of number of egress queues used
+
+ reg[0x1130] = 0x00d5ffeb # SGE_DBP_FETCH_THRESHOLD, fetch
+ # threshold set to queue depth
+ # minus 128-entries for FL and HP
+ # queues, and 0xfff for LP which
+ # prompts the firmware to set it up
+ # in function of egress queues
+ # used
+
+ reg[0x113c] = 0x0002ffc0 # SGE_VFIFO_SIZE, set to 0x2ffc0 which
+ # prompts the firmware to set it up in
+ # function of number of egress queues
+ # used
# enable TP_OUT_CONFIG.IPIDSPLITMODE
reg[0x7d04] = 0x00010000/0x00010000
@@ -26,34 +47,38 @@
# enable TP_PARA_REG6.EnableCSnd
reg[0x7d78] = 0x00000400/0x00000000
- # TP_SHIFT_CNT
- reg[0x7dc0] = 0x62f8849
-
- # TP_GLOBAL_CONFIG
- reg[0x7d08] = 0x00000800/0x00000800 # set IssFromCplEnable
-
- # TP_PARA_REG0
- reg[0x7d60] = 0x06000000/0x07000000 # set InitCWND to 6
+ reg[0x7dc0] = 0x0e2f8849 # TP_SHIFT_CNT
filterMode = fragmentation, mpshittype, protocol, vlan, port, fcoe
filterMask = protocol, fcoe
- # TP rx and tx channels (0 = auto).
+ tp_pmrx = 36, 512
+ tp_pmrx_pagesize = 64K
+
+ # TP number of RX channels (0 = auto)
tp_nrxch = 0
- tp_ntxch = 0
- # TP rx and tx payload memory (% of the total EDRAM + DDR3).
- tp_pmrx = 38, 512
- tp_pmtx = 60, 512
- tp_pmrx_pagesize = 64K
+ tp_pmtx = 46, 512
tp_pmtx_pagesize = 64K
- # cluster, lan, or wan.
- tp_tcptuning = lan
+ # TP number of TX channels (0 = auto)
+ tp_ntxch = 0
# TP OFLD MTUs
tp_mtus = 88, 256, 512, 576, 808, 1024, 1280, 1488, 1500, 2002, 2048, 4096, 4352, 8192, 9000, 9600
+ # TP_GLOBAL_CONFIG
+ reg[0x7d08] = 0x00000800/0x00000800 # set IssFromCplEnable
+
+ # TP_PC_CONFIG
+ reg[0x7d48] = 0x00000000/0x00000400 # clear EnableFLMError
+
+ # TP_PARA_REG0
+ reg[0x7d60] = 0x06000000/0x07000000 # set InitCWND to 6
+
+ # cluster, lan, or wan.
+ tp_tcptuning = lan
+
# MC configuration
mc_mode_brc[0] = 1 # mc0 - 1: enable BRC, 0: enable RBC
mc_mode_brc[1] = 1 # mc1 - 1: enable BRC, 0: enable RBC
@@ -63,38 +88,58 @@
# TPT error.
# PFs 0-3. These get 8 MSI/8 MSI-X vectors each. VFs are supported by
-# these 4 PFs only. Not used here at all.
+# these 4 PFs only.
[function "0"]
- nvf = 16
- nvi = 1
- rssnvi = 0
-[function "0/*"]
- nvi = 1
- rssnvi = 0
+ nvf = 4
+ wx_caps = all
+ r_caps = all
+ nvi = 2
+ rssnvi = 2
+ niqflint = 4
+ nethctrl = 4
+ neq = 8
+ nexactf = 4
+ cmask = all
+ pmask = 0x1
[function "1"]
- nvf = 16
- nvi = 1
- rssnvi = 0
-[function "1/*"]
- nvi = 1
- rssnvi = 0
+ nvf = 4
+ wx_caps = all
+ r_caps = all
+ nvi = 2
+ rssnvi = 2
+ niqflint = 4
+ nethctrl = 4
+ neq = 8
+ nexactf = 4
+ cmask = all
+ pmask = 0x2
[function "2"]
- nvf = 16
- nvi = 1
- rssnvi = 0
-[function "2/*"]
- nvi = 1
- rssnvi = 0
+ nvf = 4
+ wx_caps = all
+ r_caps = all
+ nvi = 2
+ rssnvi = 2
+ niqflint = 4
+ nethctrl = 4
+ neq = 8
+ nexactf = 4
+ cmask = all
+ pmask = 0x4
[function "3"]
- nvf = 16
- nvi = 1
- rssnvi = 0
-[function "3/*"]
- nvi = 1
- rssnvi = 0
+ nvf = 4
+ wx_caps = all
+ r_caps = all
+ nvi = 2
+ rssnvi = 2
+ niqflint = 4
+ nethctrl = 4
+ neq = 8
+ nexactf = 4
+ cmask = all
+ pmask = 0x8
# PF4 is the resource-rich PF that the bus/nexus driver attaches to.
# It gets 32 MSI/128 MSI-X vectors.
@@ -106,15 +151,19 @@
niqflint = 512
nethctrl = 1024
neq = 2048
- nexactf = 328
+ nexactf = 456
cmask = all
pmask = all
# driver will mask off features it won't use
- protocol = ofld
+ protocol = ofld, rddp, rdmac, iscsi_initiator_pdu, iscsi_target_pdu, iscsi_t10dif
tp_l2t = 4096
tp_ddp = 2
+ tp_ddp_iscsi = 2
+ tp_stag = 2
+ tp_pbl = 5
+ tp_rq = 7
# TCAM has 8K cells; each region must start at a multiple of 128 cell.
# Each entry in these categories takes 4 cells each. nhash will use the
@@ -150,6 +199,60 @@
nexactf = 8
nfilter = 16
+# For Virtual functions, we only allow NIC functionality and we only allow
+# access to one port (1 << PF). Note that because of limitations in the
+# Scatter Gather Engine (SGE) hardware which checks writes to VF KDOORBELL
+# and GTS registers, the number of Ingress and Egress Queues must be a power
+# of 2.
+#
+[function "0/*"]
+ wx_caps = 0x82
+ r_caps = 0x86
+ nvi = 1
+ rssnvi = 1
+ niqflint = 2
+ nethctrl = 2
+ neq = 4
+ nexactf = 2
+ cmask = all
+ pmask = 0x1
+
+[function "1/*"]
+ wx_caps = 0x82
+ r_caps = 0x86
+ nvi = 1
+ rssnvi = 1
+ niqflint = 2
+ nethctrl = 2
+ neq = 4
+ nexactf = 2
+ cmask = all
+ pmask = 0x2
+
+[function "2/*"]
+ wx_caps = 0x82
+ r_caps = 0x86
+ nvi = 1
+ rssnvi = 1
+ niqflint = 2
+ nethctrl = 2
+ neq = 4
+ nexactf = 2
+ cmask = all
+ pmask = 0x4
+
+[function "3/*"]
+ wx_caps = 0x82
+ r_caps = 0x86
+ nvi = 1
+ rssnvi = 1
+ niqflint = 2
+ nethctrl = 2
+ neq = 4
+ nexactf = 2
+ cmask = all
+ pmask = 0x8
+
# MPS has 192K buffer space for ingress packets from the wire as well as
# loopback path of the L2 switch.
[port "0"]
@@ -186,7 +289,7 @@
[fini]
version = 0x1
- checksum = 0x7044b7fd
+ checksum = 0x2d7417e5
#
# $FreeBSD$
#
diff --git a/sys/dev/cxgbe/iw_cxgbe/cm.c b/sys/dev/cxgbe/iw_cxgbe/cm.c
index c884f5a..c2b72fa 100644
--- a/sys/dev/cxgbe/iw_cxgbe/cm.c
+++ b/sys/dev/cxgbe/iw_cxgbe/cm.c
@@ -80,7 +80,7 @@ static spinlock_t timeout_lock;
static void process_req(struct work_struct *ctx);
static void start_ep_timer(struct c4iw_ep *ep);
-static void stop_ep_timer(struct c4iw_ep *ep);
+static int stop_ep_timer(struct c4iw_ep *ep);
static int set_tcpinfo(struct c4iw_ep *ep);
static enum c4iw_ep_state state_read(struct c4iw_ep_common *epc);
static void __state_set(struct c4iw_ep_common *epc, enum c4iw_ep_state tostate);
@@ -96,14 +96,14 @@ static void send_mpa_req(struct c4iw_ep *ep);
static int send_mpa_reject(struct c4iw_ep *ep, const void *pdata, u8 plen);
static int send_mpa_reply(struct c4iw_ep *ep, const void *pdata, u8 plen);
static void close_complete_upcall(struct c4iw_ep *ep, int status);
-static int abort_connection(struct c4iw_ep *ep);
+static int send_abort(struct c4iw_ep *ep);
static void peer_close_upcall(struct c4iw_ep *ep);
static void peer_abort_upcall(struct c4iw_ep *ep);
static void connect_reply_upcall(struct c4iw_ep *ep, int status);
static int connect_request_upcall(struct c4iw_ep *ep);
static void established_upcall(struct c4iw_ep *ep);
-static void process_mpa_reply(struct c4iw_ep *ep);
-static void process_mpa_request(struct c4iw_ep *ep);
+static int process_mpa_reply(struct c4iw_ep *ep);
+static int process_mpa_request(struct c4iw_ep *ep);
static void process_peer_close(struct c4iw_ep *ep);
static void process_conn_error(struct c4iw_ep *ep);
static void process_close_complete(struct c4iw_ep *ep);
@@ -123,11 +123,11 @@ static void release_ep_resources(struct c4iw_ep *ep);
} while (0)
#define STOP_EP_TIMER(ep) \
- do { \
+ ({ \
CTR3(KTR_IW_CXGBE, "stop_ep_timer (%s:%d) ep %p", \
__func__, __LINE__, (ep)); \
stop_ep_timer(ep); \
- } while (0)
+ })
#ifdef KTR
static char *states[] = {
@@ -147,6 +147,34 @@ static char *states[] = {
};
#endif
+
+static void deref_cm_id(struct c4iw_ep_common *epc)
+{
+ epc->cm_id->rem_ref(epc->cm_id);
+ epc->cm_id = NULL;
+ set_bit(CM_ID_DEREFED, &epc->history);
+}
+
+static void ref_cm_id(struct c4iw_ep_common *epc)
+{
+ set_bit(CM_ID_REFED, &epc->history);
+ epc->cm_id->add_ref(epc->cm_id);
+}
+
+static void deref_qp(struct c4iw_ep *ep)
+{
+ c4iw_qp_rem_ref(&ep->com.qp->ibqp);
+ clear_bit(QP_REFERENCED, &ep->com.flags);
+ set_bit(QP_DEREFED, &ep->com.history);
+}
+
+static void ref_qp(struct c4iw_ep *ep)
+{
+ set_bit(QP_REFERENCED, &ep->com.flags);
+ set_bit(QP_REFED, &ep->com.history);
+ c4iw_qp_add_ref(&ep->com.qp->ibqp);
+}
+
static void
process_req(struct work_struct *ctx)
{
@@ -304,9 +332,7 @@ process_peer_close(struct c4iw_ep *ep)
disconnect = 0;
STOP_EP_TIMER(ep);
close_socket(&ep->com, 0);
- ep->com.cm_id->rem_ref(ep->com.cm_id);
- ep->com.cm_id = NULL;
- ep->com.qp = NULL;
+ deref_cm_id(&ep->com);
release = 1;
break;
@@ -490,6 +516,7 @@ process_close_complete(struct c4iw_ep *ep)
/* The cm_id may be null if we failed to connect */
mutex_lock(&ep->com.mutex);
+ set_bit(CLOSE_CON_RPL, &ep->com.history);
switch (ep->com.state) {
@@ -580,13 +607,14 @@ static void
process_data(struct c4iw_ep *ep)
{
struct sockaddr_in *local, *remote;
+ int disconnect = 0;
CTR5(KTR_IW_CXGBE, "%s: so %p, ep %p, state %s, sbused %d", __func__,
ep->com.so, ep, states[ep->com.state], sbused(&ep->com.so->so_rcv));
switch (state_read(&ep->com)) {
case MPA_REQ_SENT:
- process_mpa_reply(ep);
+ disconnect = process_mpa_reply(ep);
break;
case MPA_REQ_WAIT:
in_getsockaddr(ep->com.so, (struct sockaddr **)&local);
@@ -595,7 +623,7 @@ process_data(struct c4iw_ep *ep)
ep->com.remote_addr = *remote;
free(local, M_SONAME);
free(remote, M_SONAME);
- process_mpa_request(ep);
+ disconnect = process_mpa_request(ep);
break;
default:
if (sbused(&ep->com.so->so_rcv))
@@ -605,6 +633,9 @@ process_data(struct c4iw_ep *ep)
ep->com.so->so_state, sbused(&ep->com.so->so_rcv));
break;
}
+ if (disconnect)
+ c4iw_ep_disconnect(ep, disconnect == 2, GFP_KERNEL);
+
}
static void
@@ -749,9 +780,9 @@ int db_delay_usecs = 1;
SYSCTL_INT(_hw_iw_cxgbe, OID_AUTO, db_delay_usecs, CTLFLAG_RWTUN, &db_delay_usecs, 0,
"Usecs to delay awaiting db fifo to drain");
-static int dack_mode = 1;
+static int dack_mode = 0;
SYSCTL_INT(_hw_iw_cxgbe, OID_AUTO, dack_mode, CTLFLAG_RWTUN, &dack_mode, 0,
- "Delayed ack mode (default = 1)");
+ "Delayed ack mode (default = 0)");
int c4iw_max_read_depth = 8;
SYSCTL_INT(_hw_iw_cxgbe, OID_AUTO, c4iw_max_read_depth, CTLFLAG_RWTUN, &c4iw_max_read_depth, 0,
@@ -773,9 +804,9 @@ int c4iw_debug = 1;
SYSCTL_INT(_hw_iw_cxgbe, OID_AUTO, c4iw_debug, CTLFLAG_RWTUN, &c4iw_debug, 0,
"Enable debug logging (default = 0)");
-static int peer2peer;
+static int peer2peer = 1;
SYSCTL_INT(_hw_iw_cxgbe, OID_AUTO, peer2peer, CTLFLAG_RWTUN, &peer2peer, 0,
- "Support peer2peer ULPs (default = 0)");
+ "Support peer2peer ULPs (default = 1)");
static int p2p_type = FW_RI_INIT_P2PTYPE_READ_REQ;
SYSCTL_INT(_hw_iw_cxgbe, OID_AUTO, p2p_type, CTLFLAG_RWTUN, &p2p_type, 0,
@@ -827,14 +858,16 @@ start_ep_timer(struct c4iw_ep *ep)
add_timer(&ep->timer);
}
-static void
+static int
stop_ep_timer(struct c4iw_ep *ep)
{
del_timer_sync(&ep->timer);
if (!test_and_set_bit(TIMEOUT, &ep->com.flags)) {
c4iw_put_ep(&ep->com);
+ return 0;
}
+ return 1;
}
static enum
@@ -900,6 +933,8 @@ void _c4iw_free_ep(struct kref *kref)
epc = &ep->com;
KASSERT(!epc->entry.tqe_prev, ("%s epc %p still on req list",
__func__, epc));
+ if (test_bit(QP_REFERENCED, &ep->com.flags))
+ deref_qp(ep);
kfree(ep);
}
@@ -1175,20 +1210,17 @@ static void close_complete_upcall(struct c4iw_ep *ep, int status)
CTR2(KTR_IW_CXGBE, "%s:ccu1 %1", __func__, ep);
ep->com.cm_id->event_handler(ep->com.cm_id, &event);
- ep->com.cm_id->rem_ref(ep->com.cm_id);
- ep->com.cm_id = NULL;
- ep->com.qp = NULL;
+ deref_cm_id(&ep->com);
set_bit(CLOSE_UPCALL, &ep->com.history);
}
CTR2(KTR_IW_CXGBE, "%s:ccuE %p", __func__, ep);
}
-static int abort_connection(struct c4iw_ep *ep)
+static int send_abort(struct c4iw_ep *ep)
{
int err;
CTR2(KTR_IW_CXGBE, "%s:abB %p", __func__, ep);
- state_set(&ep->com, ABORTING);
abort_socket(ep);
err = close_socket(&ep->com, 0);
set_bit(ABORT_CONN, &ep->com.history);
@@ -1226,9 +1258,7 @@ static void peer_abort_upcall(struct c4iw_ep *ep)
CTR2(KTR_IW_CXGBE, "%s:pau1 %p", __func__, ep);
ep->com.cm_id->event_handler(ep->com.cm_id, &event);
- ep->com.cm_id->rem_ref(ep->com.cm_id);
- ep->com.cm_id = NULL;
- ep->com.qp = NULL;
+ deref_cm_id(&ep->com);
set_bit(ABORT_UPCALL, &ep->com.history);
}
CTR2(KTR_IW_CXGBE, "%s:pauE %p", __func__, ep);
@@ -1282,9 +1312,7 @@ static void connect_reply_upcall(struct c4iw_ep *ep, int status)
if (status < 0) {
CTR3(KTR_IW_CXGBE, "%s:cru4 %p %d", __func__, ep, status);
- ep->com.cm_id->rem_ref(ep->com.cm_id);
- ep->com.cm_id = NULL;
- ep->com.qp = NULL;
+ deref_cm_id(&ep->com);
}
CTR2(KTR_IW_CXGBE, "%s:cruE %p", __func__, ep);
@@ -1353,8 +1381,19 @@ static void established_upcall(struct c4iw_ep *ep)
}
-
-static void process_mpa_reply(struct c4iw_ep *ep)
+/*
+ * process_mpa_reply - process streaming mode MPA reply
+ *
+ * Returns:
+ *
+ * 0 upon success indicating a connect request was delivered to the ULP
+ * or the mpa request is incomplete but valid so far.
+ *
+ * 1 if a failure requires the caller to close the connection.
+ *
+ * 2 if a failure requires the caller to abort the connection.
+ */
+static int process_mpa_reply(struct c4iw_ep *ep)
{
struct mpa_message *mpa;
struct mpa_v2_conn_params *mpa_v2_params;
@@ -1367,17 +1406,17 @@ static void process_mpa_reply(struct c4iw_ep *ep)
struct mbuf *top, *m;
int flags = MSG_DONTWAIT;
struct uio uio;
+ int disconnect = 0;
CTR2(KTR_IW_CXGBE, "%s:pmrB %p", __func__, ep);
/*
- * Stop mpa timer. If it expired, then the state has
- * changed and we bail since ep_timeout already aborted
- * the connection.
+ * Stop mpa timer. If it expired, then
+ * we ignore the MPA reply. process_timeout()
+ * will abort the connection.
*/
- STOP_EP_TIMER(ep);
- if (state_read(&ep->com) != MPA_REQ_SENT)
- return;
+ if (STOP_EP_TIMER(ep))
+ return 0;
uio.uio_resid = 1000000;
uio.uio_td = ep->com.thread;
@@ -1389,7 +1428,7 @@ static void process_mpa_reply(struct c4iw_ep *ep)
CTR2(KTR_IW_CXGBE, "%s:pmr1 %p", __func__, ep);
START_EP_TIMER(ep);
- return;
+ return 0;
}
err = -err;
CTR2(KTR_IW_CXGBE, "%s:pmr2 %p", __func__, ep);
@@ -1417,7 +1456,7 @@ static void process_mpa_reply(struct c4iw_ep *ep)
CTR3(KTR_IW_CXGBE, "%s:pmr5 %p %d", __func__, ep,
ep->mpa_pkt_len + m->m_len);
err = (-EINVAL);
- goto err;
+ goto err_stop_timer;
}
/*
@@ -1435,8 +1474,9 @@ static void process_mpa_reply(struct c4iw_ep *ep)
/*
* if we don't even have the mpa message, then bail.
*/
- if (ep->mpa_pkt_len < sizeof(*mpa))
- return;
+ if (ep->mpa_pkt_len < sizeof(*mpa)) {
+ return 0;
+ }
mpa = (struct mpa_message *) ep->mpa_pkt;
/* Validate MPA header. */
@@ -1447,14 +1487,14 @@ static void process_mpa_reply(struct c4iw_ep *ep)
printk(KERN_ERR MOD "%s MPA version mismatch. Local = %d, "
" Received = %d\n", __func__, mpa_rev, mpa->revision);
err = -EPROTO;
- goto err;
+ goto err_stop_timer;
}
if (memcmp(mpa->key, MPA_KEY_REP, sizeof(mpa->key))) {
CTR2(KTR_IW_CXGBE, "%s:pmr7 %p", __func__, ep);
err = -EPROTO;
- goto err;
+ goto err_stop_timer;
}
plen = ntohs(mpa->private_data_size);
@@ -1466,7 +1506,7 @@ static void process_mpa_reply(struct c4iw_ep *ep)
CTR2(KTR_IW_CXGBE, "%s:pmr8 %p", __func__, ep);
err = -EPROTO;
- goto err;
+ goto err_stop_timer;
}
/*
@@ -1475,8 +1515,9 @@ static void process_mpa_reply(struct c4iw_ep *ep)
if (ep->mpa_pkt_len > (sizeof(*mpa) + plen)) {
CTR2(KTR_IW_CXGBE, "%s:pmr9 %p", __func__, ep);
+ STOP_EP_TIMER(ep);
err = -EPROTO;
- goto err;
+ goto err_stop_timer;
}
ep->plen = (u8) plen;
@@ -1488,14 +1529,14 @@ static void process_mpa_reply(struct c4iw_ep *ep)
if (ep->mpa_pkt_len < (sizeof(*mpa) + plen)) {
CTR2(KTR_IW_CXGBE, "%s:pmra %p", __func__, ep);
- return;
+ return 0;
}
if (mpa->flags & MPA_REJECT) {
CTR2(KTR_IW_CXGBE, "%s:pmrb %p", __func__, ep);
err = -ECONNREFUSED;
- goto err;
+ goto err_stop_timer;
}
/*
@@ -1638,6 +1679,7 @@ static void process_mpa_reply(struct c4iw_ep *ep)
err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
err = -ENOMEM;
+ disconnect = 1;
goto out;
}
@@ -1658,19 +1700,33 @@ static void process_mpa_reply(struct c4iw_ep *ep)
err = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
C4IW_QP_ATTR_NEXT_STATE, &attrs, 0);
err = -ENOMEM;
+ disconnect = 1;
goto out;
}
goto out;
+err_stop_timer:
+ STOP_EP_TIMER(ep);
err:
- state_set(&ep->com, ABORTING);
- abort_connection(ep);
+ disconnect = 2;
out:
connect_reply_upcall(ep, err);
CTR2(KTR_IW_CXGBE, "%s:pmrE %p", __func__, ep);
- return;
+ return disconnect;
}
-static void
+/*
+ * process_mpa_request - process streaming mode MPA request
+ *
+ * Returns:
+ *
+ * 0 upon success indicating a connect request was delivered to the ULP
+ * or the mpa request is incomplete but valid so far.
+ *
+ * 1 if a failure requires the caller to close the connection.
+ *
+ * 2 if a failure requires the caller to abort the connection.
+ */
+static int
process_mpa_request(struct c4iw_ep *ep)
{
struct mpa_message *mpa;
@@ -1684,7 +1740,7 @@ process_mpa_request(struct c4iw_ep *ep)
CTR3(KTR_IW_CXGBE, "%s: ep %p, state %s", __func__, ep, states[state]);
if (state != MPA_REQ_WAIT)
- return;
+ return 0;
iov.iov_base = &ep->mpa_pkt[ep->mpa_pkt_len];
iov.iov_len = sizeof(ep->mpa_pkt) - ep->mpa_pkt_len;
@@ -1698,13 +1754,10 @@ process_mpa_request(struct c4iw_ep *ep)
rc = soreceive(ep->com.so, NULL, &uio, NULL, NULL, &flags);
if (rc == EAGAIN)
- return;
- else if (rc) {
-abort:
- STOP_EP_TIMER(ep);
- abort_connection(ep);
- return;
- }
+ return 0;
+ else if (rc)
+ goto err_stop_timer;
+
KASSERT(uio.uio_offset > 0, ("%s: sorecieve on so %p read no data",
__func__, ep->com.so));
ep->mpa_pkt_len += uio.uio_offset;
@@ -1718,7 +1771,7 @@ abort:
/* Don't even have the MPA message. Wait for more data to arrive. */
if (ep->mpa_pkt_len < sizeof(*mpa))
- return;
+ return 0;
mpa = (struct mpa_message *) ep->mpa_pkt;
/*
@@ -1727,24 +1780,24 @@ abort:
if (mpa->revision > mpa_rev) {
log(LOG_ERR, "%s: MPA version mismatch. Local = %d,"
" Received = %d\n", __func__, mpa_rev, mpa->revision);
- goto abort;
+ goto err_stop_timer;
}
if (memcmp(mpa->key, MPA_KEY_REQ, sizeof(mpa->key)))
- goto abort;
+ goto err_stop_timer;
/*
* Fail if there's too much private data.
*/
plen = ntohs(mpa->private_data_size);
if (plen > MPA_MAX_PRIVATE_DATA)
- goto abort;
+ goto err_stop_timer;
/*
* If plen does not account for pkt size
*/
if (ep->mpa_pkt_len > (sizeof(*mpa) + plen))
- goto abort;
+ goto err_stop_timer;
ep->plen = (u8) plen;
@@ -1752,7 +1805,7 @@ abort:
* If we don't have all the pdata yet, then bail.
*/
if (ep->mpa_pkt_len < (sizeof(*mpa) + plen))
- return;
+ return 0;
/*
* If we get here we have accumulated the entire mpa
@@ -1794,7 +1847,7 @@ abort:
ep->mpa_attr.p2p_type = p2p_type;
if (set_tcpinfo(ep))
- goto abort;
+ goto err_stop_timer;
CTR5(KTR_IW_CXGBE, "%s: crc_enabled = %d, recv_marker_enabled = %d, "
"xmit_marker_enabled = %d, version = %d", __func__,
@@ -1807,12 +1860,18 @@ abort:
/* drive upcall */
mutex_lock(&ep->parent_ep->com.mutex);
if (ep->parent_ep->com.state != DEAD) {
- if(connect_request_upcall(ep)) {
- abort_connection(ep);
- }
- }else
- abort_connection(ep);
+ if(connect_request_upcall(ep))
+ goto err_out;
+ }else {
+ goto err_out;
+ }
mutex_unlock(&ep->parent_ep->com.mutex);
+ return 0;
+
+err_stop_timer:
+ STOP_EP_TIMER(ep);
+err_out:
+ return 2;
}
/*
@@ -1825,6 +1884,7 @@ int c4iw_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
int err;
struct c4iw_ep *ep = to_ep(cm_id);
CTR2(KTR_IW_CXGBE, "%s:crcB %p", __func__, ep);
+ int disconnect = 0;
if (state_read(&ep->com) == DEAD) {
@@ -1838,7 +1898,7 @@ int c4iw_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
if (mpa_rev == 0) {
CTR2(KTR_IW_CXGBE, "%s:crc2 %p", __func__, ep);
- abort_connection(ep);
+ disconnect = 2;
}
else {
@@ -1847,6 +1907,8 @@ int c4iw_reject_cr(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
err = soshutdown(ep->com.so, 3);
}
c4iw_put_ep(&ep->com);
+ if (disconnect)
+ err = c4iw_ep_disconnect(ep, disconnect == 2, GFP_KERNEL);
CTR2(KTR_IW_CXGBE, "%s:crc4 %p", __func__, ep);
return 0;
}
@@ -1859,6 +1921,7 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
struct c4iw_ep *ep = to_ep(cm_id);
struct c4iw_dev *h = to_c4iw_dev(cm_id->device);
struct c4iw_qp *qp = get_qhp(h, conn_param->qpn);
+ int abort = 0;
CTR2(KTR_IW_CXGBE, "%s:cacB %p", __func__, ep);
@@ -1866,7 +1929,7 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
CTR2(KTR_IW_CXGBE, "%s:cac1 %p", __func__, ep);
err = -ECONNRESET;
- goto err;
+ goto err_out;
}
BUG_ON(state_read(&ep->com) != MPA_REQ_RCVD);
@@ -1878,9 +1941,8 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
(conn_param->ird > c4iw_max_read_depth)) {
CTR2(KTR_IW_CXGBE, "%s:cac2 %p", __func__, ep);
- abort_connection(ep);
err = -EINVAL;
- goto err;
+ goto err_abort;
}
if (ep->mpa_attr.version == 2 && ep->mpa_attr.enhanced_rdma_conn) {
@@ -1894,9 +1956,8 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
ep->ord = conn_param->ord;
send_mpa_reject(ep, conn_param->private_data,
conn_param->private_data_len);
- abort_connection(ep);
err = -ENOMEM;
- goto err;
+ goto err_abort;
}
if (conn_param->ird > ep->ord) {
@@ -1910,9 +1971,8 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
}
else {
CTR2(KTR_IW_CXGBE, "%s:cac7 %p", __func__, ep);
- abort_connection(ep);
err = -ENOMEM;
- goto err;
+ goto err_abort;
}
}
@@ -1932,9 +1992,10 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
}
- cm_id->add_ref(cm_id);
ep->com.cm_id = cm_id;
+ ref_cm_id(&ep->com);
ep->com.qp = qp;
+ ref_qp(ep);
//ep->ofld_txq = TOEPCB(ep->com.so)->ofld_txq;
/* bind QP to EP and move to RTS */
@@ -1956,7 +2017,7 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
if (err) {
CTR2(KTR_IW_CXGBE, "%s:caca %p", __func__, ep);
- goto err1;
+ goto err_defef_cm_id;
}
err = send_mpa_reply(ep, conn_param->private_data,
conn_param->private_data_len);
@@ -1964,7 +2025,7 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
if (err) {
CTR2(KTR_IW_CXGBE, "%s:caca %p", __func__, ep);
- goto err1;
+ goto err_defef_cm_id;
}
state_set(&ep->com, FPDU_MODE);
@@ -1972,11 +2033,13 @@ int c4iw_accept_cr(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
c4iw_put_ep(&ep->com);
CTR2(KTR_IW_CXGBE, "%s:cacE %p", __func__, ep);
return 0;
-err1:
- ep->com.cm_id = NULL;
- ep->com.qp = NULL;
- cm_id->rem_ref(cm_id);
-err:
+err_defef_cm_id:
+ deref_cm_id(&ep->com);
+err_abort:
+ abort = 1;
+err_out:
+ if (abort)
+ c4iw_ep_disconnect(ep, 1, GFP_KERNEL);
c4iw_put_ep(&ep->com);
CTR2(KTR_IW_CXGBE, "%s:cacE err %p", __func__, ep);
return err;
@@ -2028,9 +2091,9 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
ep->ord = 1;
}
- cm_id->add_ref(cm_id);
ep->com.dev = dev;
ep->com.cm_id = cm_id;
+ ref_cm_id(&ep->com);
ep->com.qp = get_qhp(dev, conn_param->qpn);
if (!ep->com.qp) {
@@ -2039,6 +2102,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
err = -EINVAL;
goto fail2;
}
+ ref_qp(ep);
ep->com.thread = curthread;
ep->com.so = cm_id->so;
@@ -2096,7 +2160,7 @@ fail3:
CTR2(KTR_IW_CXGBE, "%s:ccb %p", __func__, ep);
fib4_free_nh_ext(RT_DEFAULT_FIB, &nh4);
fail2:
- cm_id->rem_ref(cm_id);
+ deref_cm_id(&ep->com);
c4iw_put_ep(&ep->com);
out:
CTR2(KTR_IW_CXGBE, "%s:ccE %p", __func__, ep);
@@ -2124,8 +2188,8 @@ c4iw_create_listen_ep(struct iw_cm_id *cm_id, int backlog)
goto failed;
}
- cm_id->add_ref(cm_id);
ep->com.cm_id = cm_id;
+ ref_cm_id(&ep->com);
ep->com.dev = dev;
ep->backlog = backlog;
ep->com.local_addr = cm_id->local_addr;
@@ -2150,7 +2214,7 @@ c4iw_destroy_listen_ep(struct iw_cm_id *cm_id)
cm_id->so, states[ep->com.state]);
state_set(&ep->com, DEAD);
- cm_id->rem_ref(cm_id);
+ deref_cm_id(&ep->com);
c4iw_put_ep(&ep->com);
return;
@@ -2232,7 +2296,8 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
CTR2(KTR_IW_CXGBE, "%s:ced4 %p", __func__, ep);
set_bit(EP_DISC_ABORT, &ep->com.history);
- ret = abort_connection(ep);
+ close_complete_upcall(ep, -ECONNRESET);
+ ret = send_abort(ep);
} else {
CTR2(KTR_IW_CXGBE, "%s:ced5 %p", __func__, ep);
@@ -2250,8 +2315,25 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
}
if (fatal) {
+ set_bit(EP_DISC_FAIL, &ep->com.history);
+ if (!abrupt) {
+ STOP_EP_TIMER(ep);
+ close_complete_upcall(ep, -EIO);
+ }
+ if (ep->com.qp) {
+ struct c4iw_qp_attributes attrs;
+ attrs.next_state = C4IW_QP_STATE_ERROR;
+ ret = c4iw_modify_qp(ep->com.dev, ep->com.qp,
+ C4IW_QP_ATTR_NEXT_STATE,
+ &attrs, 1);
+ if (ret) {
+ CTR2(KTR_IW_CXGBE, "%s:ced7 %p", __func__, ep);
+ printf("%s - qp <- error failed!\n", __func__);
+ }
+ }
release_ep_resources(ep);
+ ep->com.state = DEAD;
CTR2(KTR_IW_CXGBE, "%s:ced6 %p", __func__, ep);
}
CTR2(KTR_IW_CXGBE, "%s:cedE %p", __func__, ep);
@@ -2290,8 +2372,13 @@ static void ep_timeout(unsigned long arg)
if (!test_and_set_bit(TIMEOUT, &ep->com.flags)) {
- list_add_tail(&ep->entry, &timeout_list);
- kickit = 1;
+ /*
+ * Only insert if it is not already on the list.
+ */
+ if (!ep->entry.next) {
+ list_add_tail(&ep->entry, &timeout_list);
+ kickit = 1;
+ }
}
spin_unlock(&timeout_lock);
diff --git a/sys/dev/cxgbe/iw_cxgbe/cq.c b/sys/dev/cxgbe/iw_cxgbe/cq.c
index 8710e03..b40ffc7 100644
--- a/sys/dev/cxgbe/iw_cxgbe/cq.c
+++ b/sys/dev/cxgbe/iw_cxgbe/cq.c
@@ -724,7 +724,7 @@ static int c4iw_poll_cq_one(struct c4iw_cq *chp, struct ib_wc *wc)
default:
printf("Unexpected cqe_status 0x%x for QPID = 0x%0x\n",
CQE_STATUS(&cqe), CQE_QPID(&cqe));
- ret = -EINVAL;
+ wc->status = IB_WC_FATAL_ERR;
}
}
out:
@@ -861,6 +861,7 @@ c4iw_create_cq(struct ib_device *ibdev, struct ib_cq_init_attr *attr,
if (!mm2)
goto err4;
+ memset(&uresp, 0, sizeof(uresp));
uresp.qid_mask = rhp->rdev.cqmask;
uresp.cqid = chp->cq.cqid;
uresp.size = chp->cq.size;
@@ -871,7 +872,8 @@ c4iw_create_cq(struct ib_device *ibdev, struct ib_cq_init_attr *attr,
uresp.gts_key = ucontext->key;
ucontext->key += PAGE_SIZE;
spin_unlock(&ucontext->mmap_lock);
- ret = ib_copy_to_udata(udata, &uresp, sizeof uresp);
+ ret = ib_copy_to_udata(udata, &uresp,
+ sizeof(uresp) - sizeof(uresp.reserved));
if (ret)
goto err5;
diff --git a/sys/dev/cxgbe/iw_cxgbe/iw_cxgbe.h b/sys/dev/cxgbe/iw_cxgbe/iw_cxgbe.h
index c232f70..38a8af6 100644
--- a/sys/dev/cxgbe/iw_cxgbe/iw_cxgbe.h
+++ b/sys/dev/cxgbe/iw_cxgbe/iw_cxgbe.h
@@ -157,7 +157,7 @@ static inline int c4iw_fatal_error(struct c4iw_rdev *rdev)
static inline int c4iw_num_stags(struct c4iw_rdev *rdev)
{
- return min((int)T4_MAX_NUM_STAG, (int)(rdev->adap->vres.stag.size >> 5));
+ return (int)(rdev->adap->vres.stag.size >> 5);
}
#define C4IW_WR_TO (10*HZ)
@@ -435,6 +435,7 @@ struct c4iw_qp {
atomic_t refcnt;
wait_queue_head_t wait;
struct timer_list timer;
+ int sq_sig_all;
};
static inline struct c4iw_qp *to_c4iw_qp(struct ib_qp *ibqp)
@@ -712,7 +713,8 @@ enum c4iw_ep_flags {
ABORT_REQ_IN_PROGRESS = 1,
RELEASE_RESOURCES = 2,
CLOSE_SENT = 3,
- TIMEOUT = 4
+ TIMEOUT = 4,
+ QP_REFERENCED = 5
};
enum c4iw_ep_history {
@@ -737,7 +739,13 @@ enum c4iw_ep_history {
EP_DISC_ABORT = 18,
CONN_RPL_UPCALL = 19,
ACT_RETRY_NOMEM = 20,
- ACT_RETRY_INUSE = 21
+ ACT_RETRY_INUSE = 21,
+ CLOSE_CON_RPL = 22,
+ EP_DISC_FAIL = 24,
+ QP_REFED = 25,
+ QP_DEREFED = 26,
+ CM_ID_REFED = 27,
+ CM_ID_DEREFED = 28
};
struct c4iw_ep_common {
diff --git a/sys/dev/cxgbe/iw_cxgbe/mem.c b/sys/dev/cxgbe/iw_cxgbe/mem.c
index f7c460a..e42aa1a 100644
--- a/sys/dev/cxgbe/iw_cxgbe/mem.c
+++ b/sys/dev/cxgbe/iw_cxgbe/mem.c
@@ -46,6 +46,12 @@ __FBSDID("$FreeBSD$");
#define T4_ULPTX_MIN_IO 32
#define C4IW_MAX_INLINE_SIZE 96
+static int mr_exceeds_hw_limits(struct c4iw_dev *dev, u64 length)
+{
+ return (is_t4(dev->rdev.adap) ||
+ is_t5(dev->rdev.adap)) &&
+ length >= 8*1024*1024*1024ULL;
+}
static int
write_adapter_mem(struct c4iw_rdev *rdev, u32 addr, u32 len, void *data)
{
@@ -144,8 +150,12 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry,
if ((!reset_tpt_entry) && (*stag == T4_STAG_UNSET)) {
stag_idx = c4iw_get_resource(&rdev->resource.tpt_table);
- if (!stag_idx)
+ if (!stag_idx) {
+ mutex_lock(&rdev->stats.lock);
+ rdev->stats.stag.fail++;
+ mutex_unlock(&rdev->stats.lock);
return -ENOMEM;
+ }
mutex_lock(&rdev->stats.lock);
rdev->stats.stag.cur += 32;
if (rdev->stats.stag.cur > rdev->stats.stag.max)
@@ -250,9 +260,9 @@ static int register_mem(struct c4iw_dev *rhp, struct c4iw_pd *php,
int ret;
ret = write_tpt_entry(&rhp->rdev, 0, &stag, 1, mhp->attr.pdid,
- FW_RI_STAG_NSMR, mhp->attr.perms,
+ FW_RI_STAG_NSMR, mhp->attr.len ? mhp->attr.perms : 0,
mhp->attr.mw_bind_enable, mhp->attr.zbva,
- mhp->attr.va_fbo, mhp->attr.len, shift - 12,
+ mhp->attr.va_fbo, mhp->attr.len ? mhp->attr.len : -1, shift - 12,
mhp->attr.pbl_size, mhp->attr.pbl_addr);
if (ret)
return ret;
@@ -381,7 +391,7 @@ int c4iw_reregister_phys_mem(struct ib_mr *mr, int mr_rereg_mask,
struct c4iw_dev *rhp;
__be64 *page_list = NULL;
int shift = 0;
- u64 total_size;
+ u64 total_size = 0;
int npages = 0;
int ret;
@@ -416,7 +426,10 @@ int c4iw_reregister_phys_mem(struct ib_mr *mr, int mr_rereg_mask,
if (ret)
return ret;
}
-
+ if (mr_exceeds_hw_limits(rhp, total_size)) {
+ kfree(page_list);
+ return -EINVAL;
+ }
ret = reregister_mem(rhp, php, &mh, shift, npages);
kfree(page_list);
if (ret)
@@ -477,10 +490,15 @@ struct ib_mr *c4iw_register_phys_mem(struct ib_pd *pd,
if (ret)
goto err;
+ if (mr_exceeds_hw_limits(rhp, total_size)) {
+ kfree(page_list);
+ ret = -EINVAL;
+ goto err;
+ }
ret = alloc_pbl(mhp, npages);
if (ret) {
kfree(page_list);
- goto err_pbl;
+ goto err;
}
ret = write_pbl(&mhp->rhp->rdev, page_list, mhp->attr.pbl_addr,
@@ -580,6 +598,10 @@ struct ib_mr *c4iw_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
php = to_c4iw_pd(pd);
rhp = php->rhp;
+
+ if (mr_exceeds_hw_limits(rhp, length))
+ return ERR_PTR(-EINVAL);
+
mhp = kzalloc(sizeof(*mhp), GFP_KERNEL);
if (!mhp)
return ERR_PTR(-ENOMEM);
diff --git a/sys/dev/cxgbe/iw_cxgbe/qp.c b/sys/dev/cxgbe/iw_cxgbe/qp.c
index 1c0381c..3ee16b1 100644
--- a/sys/dev/cxgbe/iw_cxgbe/qp.c
+++ b/sys/dev/cxgbe/iw_cxgbe/qp.c
@@ -615,7 +615,7 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
fw_flags = 0;
if (wr->send_flags & IB_SEND_SOLICITED)
fw_flags |= FW_RI_SOLICITED_EVENT_FLAG;
- if (wr->send_flags & IB_SEND_SIGNALED)
+ if (wr->send_flags & IB_SEND_SIGNALED || qhp->sq_sig_all)
fw_flags |= FW_RI_COMPLETION_FLAG;
swsqe = &qhp->wq.sq.sw_sq[qhp->wq.sq.pidx];
switch (wr->opcode) {
@@ -673,7 +673,8 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
}
swsqe->idx = qhp->wq.sq.pidx;
swsqe->complete = 0;
- swsqe->signaled = (wr->send_flags & IB_SEND_SIGNALED);
+ swsqe->signaled = (wr->send_flags & IB_SEND_SIGNALED) ||
+ qhp->sq_sig_all;
swsqe->wr_id = wr->wr_id;
init_wr_hdr(wqe, qhp->wq.sq.pidx, fw_opcode, fw_flags, len16);
@@ -952,7 +953,7 @@ static void __flush_qp(struct c4iw_qp *qhp, struct c4iw_cq *rchp,
flushed = c4iw_flush_rq(&qhp->wq, &rchp->cq, count);
spin_unlock(&qhp->lock);
spin_unlock_irqrestore(&rchp->lock, flag);
- if (flushed) {
+ if (flushed && rchp->ibcq.comp_handler) {
spin_lock_irqsave(&rchp->comp_handler_lock, flag);
(*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
spin_unlock_irqrestore(&rchp->comp_handler_lock, flag);
@@ -966,7 +967,7 @@ static void __flush_qp(struct c4iw_qp *qhp, struct c4iw_cq *rchp,
flushed = c4iw_flush_sq(&qhp->wq, &schp->cq, count);
spin_unlock(&qhp->lock);
spin_unlock_irqrestore(&schp->lock, flag);
- if (flushed) {
+ if (flushed && schp->ibcq.comp_handler) {
spin_lock_irqsave(&schp->comp_handler_lock, flag);
(*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context);
spin_unlock_irqrestore(&schp->comp_handler_lock, flag);
@@ -1530,6 +1531,7 @@ c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
qhp->attr.enable_bind = 1;
qhp->attr.max_ord = 1;
qhp->attr.max_ird = 1;
+ qhp->sq_sig_all = attrs->sq_sig_type == IB_SIGNAL_ALL_WR;
spin_lock_init(&qhp->lock);
mutex_init(&qhp->mutex);
init_waitqueue_head(&qhp->wait);
@@ -1702,6 +1704,12 @@ int c4iw_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
memset(attr, 0, sizeof *attr);
memset(init_attr, 0, sizeof *init_attr);
attr->qp_state = to_ib_qp_state(qhp->attr.state);
+ init_attr->cap.max_send_wr = qhp->attr.sq_num_entries;
+ init_attr->cap.max_recv_wr = qhp->attr.rq_num_entries;
+ init_attr->cap.max_send_sge = qhp->attr.sq_max_sges;
+ init_attr->cap.max_recv_sge = qhp->attr.sq_max_sges;
+ init_attr->cap.max_inline_data = T4_MAX_SEND_INLINE;
+ init_attr->sq_sig_type = qhp->sq_sig_all ? IB_SIGNAL_ALL_WR : 0;
return 0;
}
#endif
diff --git a/sys/dev/cxgbe/iw_cxgbe/t4.h b/sys/dev/cxgbe/iw_cxgbe/t4.h
index 023c607..b0118f9 100644
--- a/sys/dev/cxgbe/iw_cxgbe/t4.h
+++ b/sys/dev/cxgbe/iw_cxgbe/t4.h
@@ -69,7 +69,6 @@
#define T4_MAX_SQ_SIZE (T4_MAX_EQ_SIZE - 1)
#define T4_MAX_QP_DEPTH (T4_MAX_RQ_SIZE - 1)
#define T4_MAX_CQ_DEPTH (T4_MAX_IQ_SIZE - 1)
-#define T4_MAX_NUM_STAG (1<<15)
#define T4_MAX_MR_SIZE (~0ULL - 1)
#define T4_PAGESIZE_MASK 0xffff000 /* 4KB-128MB */
#define T4_STAG_UNSET 0xffffffff
@@ -524,7 +523,7 @@ static inline void t4_swcq_consume(struct t4_cq *cq)
static inline void t4_hwcq_consume(struct t4_cq *cq)
{
cq->bits_type_ts = cq->queue[cq->cidx].bits_type_ts;
- if (++cq->cidx_inc == (cq->size >> 4)) {
+ if (++cq->cidx_inc == (cq->size >> 4) || cq->cidx_inc == M_CIDXINC) {
u32 val;
val = SEINTARM(0) | CIDXINC(cq->cidx_inc) | TIMERREG(7) |
diff --git a/sys/dev/cxgbe/iw_cxgbe/user.h b/sys/dev/cxgbe/iw_cxgbe/user.h
index 59a1f43..d42f659 100644
--- a/sys/dev/cxgbe/iw_cxgbe/user.h
+++ b/sys/dev/cxgbe/iw_cxgbe/user.h
@@ -50,6 +50,7 @@ struct c4iw_create_cq_resp {
__u32 cqid;
__u32 size;
__u32 qid_mask;
+ __u32 reserved; /* explicit padding (optional for i386) */
};
struct c4iw_create_qp_resp {
diff --git a/sys/dev/cxgbe/offload.h b/sys/dev/cxgbe/offload.h
index 2b5e4dc..992b4cd 100644
--- a/sys/dev/cxgbe/offload.h
+++ b/sys/dev/cxgbe/offload.h
@@ -125,7 +125,6 @@ struct t4_virt_res { /* virtualized HW resources */
struct t4_range l2t;
};
-#ifdef TCP_OFFLOAD
enum {
ULD_TOM = 0,
ULD_IWARP,
@@ -152,6 +151,7 @@ struct tom_tunables {
int tx_align;
};
+#ifdef TCP_OFFLOAD
int t4_register_uld(struct uld_info *);
int t4_unregister_uld(struct uld_info *);
int t4_activate_uld(struct adapter *, int);
diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c
index 77777f8..11d4253 100644
--- a/sys/dev/cxgbe/t4_main.c
+++ b/sys/dev/cxgbe/t4_main.c
@@ -334,7 +334,8 @@ TUNABLE_INT("hw.cxgbe.nbmcaps_allowed", &t4_nbmcaps_allowed);
static int t4_linkcaps_allowed = 0; /* No DCBX, PPP, etc. by default */
TUNABLE_INT("hw.cxgbe.linkcaps_allowed", &t4_linkcaps_allowed);
-static int t4_switchcaps_allowed = 0;
+static int t4_switchcaps_allowed = FW_CAPS_CONFIG_SWITCH_INGRESS |
+ FW_CAPS_CONFIG_SWITCH_EGRESS;
TUNABLE_INT("hw.cxgbe.switchcaps_allowed", &t4_switchcaps_allowed);
static int t4_niccaps_allowed = FW_CAPS_CONFIG_NIC;
@@ -343,13 +344,13 @@ TUNABLE_INT("hw.cxgbe.niccaps_allowed", &t4_niccaps_allowed);
static int t4_toecaps_allowed = -1;
TUNABLE_INT("hw.cxgbe.toecaps_allowed", &t4_toecaps_allowed);
-static int t4_rdmacaps_allowed = 0;
+static int t4_rdmacaps_allowed = -1;
TUNABLE_INT("hw.cxgbe.rdmacaps_allowed", &t4_rdmacaps_allowed);
static int t4_tlscaps_allowed = 0;
TUNABLE_INT("hw.cxgbe.tlscaps_allowed", &t4_tlscaps_allowed);
-static int t4_iscsicaps_allowed = 0;
+static int t4_iscsicaps_allowed = -1;
TUNABLE_INT("hw.cxgbe.iscsicaps_allowed", &t4_iscsicaps_allowed);
static int t4_fcoecaps_allowed = 0;
@@ -1731,29 +1732,29 @@ cxgbe_get_counter(struct ifnet *ifp, ift_counter c)
switch (c) {
case IFCOUNTER_IPACKETS:
- return (s->rx_frames - s->rx_pause);
+ return (s->rx_frames);
case IFCOUNTER_IERRORS:
return (s->rx_jabber + s->rx_runt + s->rx_too_long +
s->rx_fcs_err + s->rx_len_err);
case IFCOUNTER_OPACKETS:
- return (s->tx_frames - s->tx_pause);
+ return (s->tx_frames);
case IFCOUNTER_OERRORS:
return (s->tx_error_frames);
case IFCOUNTER_IBYTES:
- return (s->rx_octets - s->rx_pause * 64);
+ return (s->rx_octets);
case IFCOUNTER_OBYTES:
- return (s->tx_octets - s->tx_pause * 64);
+ return (s->tx_octets);
case IFCOUNTER_IMCASTS:
- return (s->rx_mcast_frames - s->rx_pause);
+ return (s->rx_mcast_frames);
case IFCOUNTER_OMCASTS:
- return (s->tx_mcast_frames - s->tx_pause);
+ return (s->tx_mcast_frames);
case IFCOUNTER_IQDROPS:
return (s->rx_ovflow0 + s->rx_ovflow1 + s->rx_ovflow2 +
@@ -6287,6 +6288,9 @@ mem_region_show(struct sbuf *sb, const char *name, unsigned int from,
{
unsigned int size;
+ if (from == to)
+ return;
+
size = to - from + 1;
if (size == 0)
return;
@@ -6390,13 +6394,10 @@ sysctl_meminfo(SYSCTL_HANDLER_ARGS)
md++;
if (t4_read_reg(sc, A_LE_DB_CONFIG) & F_HASHEN) {
- if (chip_id(sc) <= CHELSIO_T5) {
- hi = t4_read_reg(sc, A_LE_DB_TID_HASHBASE) / 4;
+ if (chip_id(sc) <= CHELSIO_T5)
md->base = t4_read_reg(sc, A_LE_DB_HASH_TID_BASE);
- } else {
- hi = t4_read_reg(sc, A_LE_DB_HASH_TID_BASE);
+ else
md->base = t4_read_reg(sc, A_LE_DB_HASH_TBL_BASE_ADDR);
- }
md->limit = 0;
} else {
md->base = 0;
@@ -9103,9 +9104,26 @@ tweak_tunables(void)
if (t4_toecaps_allowed == -1)
t4_toecaps_allowed = FW_CAPS_CONFIG_TOE;
+
+ if (t4_rdmacaps_allowed == -1) {
+ t4_rdmacaps_allowed = FW_CAPS_CONFIG_RDMA_RDDP |
+ FW_CAPS_CONFIG_RDMA_RDMAC;
+ }
+
+ if (t4_iscsicaps_allowed == -1) {
+ t4_iscsicaps_allowed = FW_CAPS_CONFIG_ISCSI_INITIATOR_PDU |
+ FW_CAPS_CONFIG_ISCSI_TARGET_PDU |
+ FW_CAPS_CONFIG_ISCSI_T10DIF;
+ }
#else
if (t4_toecaps_allowed == -1)
t4_toecaps_allowed = 0;
+
+ if (t4_rdmacaps_allowed == -1)
+ t4_rdmacaps_allowed = 0;
+
+ if (t4_iscsicaps_allowed == -1)
+ t4_iscsicaps_allowed = 0;
#endif
#ifdef DEV_NETMAP
diff --git a/sys/dev/cxgbe/t4_sge.c b/sys/dev/cxgbe/t4_sge.c
index 33d8d48..daf3b8a 100644
--- a/sys/dev/cxgbe/t4_sge.c
+++ b/sys/dev/cxgbe/t4_sge.c
@@ -1397,13 +1397,8 @@ process_iql:
#if defined(INET) || defined(INET6)
if (iq->flags & IQ_LRO_ENABLED) {
struct lro_ctrl *lro = &rxq->lro;
- struct lro_entry *l;
- while (!SLIST_EMPTY(&lro->lro_active)) {
- l = SLIST_FIRST(&lro->lro_active);
- SLIST_REMOVE_HEAD(&lro->lro_active, next);
- tcp_lro_flush(lro, l);
- }
+ tcp_lro_flush_all(lro);
}
#endif
@@ -2343,8 +2338,8 @@ eth_tx(struct mp_ring *r, u_int cidx, u_int pidx)
} else {
total++;
remaining--;
- n = write_txpkt_wr(txq, (void *)wr, m0, available);
ETHER_BPF_MTAP(ifp, m0);
+ n = write_txpkt_wr(txq, (void *)wr, m0, available);
}
MPASS(n >= 1 && n <= available && n <= SGE_MAX_WR_NDESC);
diff --git a/sys/dev/drm2/i915/i915_gem.c b/sys/dev/drm2/i915/i915_gem.c
index 7789e36..41ce74c 100644
--- a/sys/dev/drm2/i915/i915_gem.c
+++ b/sys/dev/drm2/i915/i915_gem.c
@@ -1481,7 +1481,7 @@ i915_gem_pager_fault(vm_object_t vm_obj, vm_ooffset_t offset, int prot,
struct drm_i915_gem_object *obj = to_intel_bo(gem_obj);
struct drm_device *dev = obj->base.dev;
drm_i915_private_t *dev_priv = dev->dev_private;
- vm_page_t page, oldpage;
+ vm_page_t page;
int ret = 0;
#ifdef FREEBSD_WIP
bool write = (prot & VM_PROT_WRITE) != 0;
@@ -1504,13 +1504,10 @@ i915_gem_pager_fault(vm_object_t vm_obj, vm_ooffset_t offset, int prot,
* progress.
*/
if (*mres != NULL) {
- oldpage = *mres;
- vm_page_lock(oldpage);
- vm_page_remove(oldpage);
- vm_page_unlock(oldpage);
- *mres = NULL;
- } else
- oldpage = NULL;
+ vm_page_lock(*mres);
+ vm_page_remove(*mres);
+ vm_page_unlock(*mres);
+ }
VM_OBJECT_WUNLOCK(vm_obj);
retry:
ret = 0;
@@ -1590,7 +1587,6 @@ retry:
}
page->valid = VM_PAGE_BITS_ALL;
have_page:
- *mres = page;
vm_page_xbusy(page);
CTR4(KTR_DRM, "fault %p %jx %x phys %x", gem_obj, offset, prot,
@@ -1603,11 +1599,13 @@ have_page:
i915_gem_object_unpin(obj);
}
DRM_UNLOCK(dev);
- if (oldpage != NULL) {
- vm_page_lock(oldpage);
- vm_page_free(oldpage);
- vm_page_unlock(oldpage);
+ if (*mres != NULL) {
+ KASSERT(*mres != page, ("loosing %p %p", *mres, page));
+ vm_page_lock(*mres);
+ vm_page_free(*mres);
+ vm_page_unlock(*mres);
}
+ *mres = page;
vm_object_pip_wakeup(vm_obj);
return (VM_PAGER_OK);
diff --git a/sys/dev/drm2/i915/intel_pm.c b/sys/dev/drm2/i915/intel_pm.c
index ab9eee4..ddab457 100644
--- a/sys/dev/drm2/i915/intel_pm.c
+++ b/sys/dev/drm2/i915/intel_pm.c
@@ -3672,9 +3672,39 @@ static void gen6_init_clock_gating(struct drm_device *dev)
ILK_DPARBUNIT_CLOCK_GATE_ENABLE |
ILK_DPFDUNIT_CLOCK_GATE_ENABLE);
+
+#ifdef FREEBSD_WIP
+ /* NOTE Linux<->FreeBSD: Disable GEN6_MBCTL write.
+ *
+ * This arrived in Linux 3.6 in commit
+ * b4ae3f22d238617ca11610b29fde16cf8c0bc6e0 and causes significantly
+ * increased power consumption after kldloading i915kms.ko on FreeBSD
+ * on (some) Sandy Bridge laptops. A Thinkpad X220 reported about 11W
+ * after booting while idle at the vt(4) console and about double that
+ * after loading the driver.
+ *
+ * There were reports in Linux of increased consumption after a suspend
+ * and resume cycle due to that change.
+ *
+ * Linux bug reports:
+ * https://bugs.freedesktop.org/show_bug.cgi?id=54089
+ * https://bugzilla.kernel.org/show_bug.cgi?id=58971
+ *
+ * This suspend and resume issue is reportedly fixed in Linux with
+ * commits 7dcd2677ea912573d9ed4bcd629b0023b2d11505 and
+ * 7dcd2677ea912573d9ed4bcd629b0023b2d11505 (Linux 3.11). However, I
+ * found that those changes did not help on FreeBSD, where increased
+ * power consumption is observed after loading i915kms.ko without
+ * suspending and resuming.
+ *
+ * This workaround should be removed after updating to a future Linux
+ * i915 version and verifying normal power consumption on Sandy Bridge.
+ */
+
/* WaMbcDriverBootEnable */
I915_WRITE(GEN6_MBCTL, I915_READ(GEN6_MBCTL) |
GEN6_MBCTL_ENABLE_BOOT_FETCH);
+#endif /* FREEBSD_WIP */
for_each_pipe(pipe) {
I915_WRITE(DSPCNTR(pipe),
diff --git a/sys/dev/drm2/ttm/ttm_bo_vm.c b/sys/dev/drm2/ttm/ttm_bo_vm.c
index 5d72d97..96ebeca 100644
--- a/sys/dev/drm2/ttm/ttm_bo_vm.c
+++ b/sys/dev/drm2/ttm/ttm_bo_vm.c
@@ -106,21 +106,18 @@ ttm_bo_vm_fault(vm_object_t vm_obj, vm_ooffset_t offset,
struct ttm_buffer_object *bo = vm_obj->handle;
struct ttm_bo_device *bdev = bo->bdev;
struct ttm_tt *ttm = NULL;
- vm_page_t m, m1, oldm;
+ vm_page_t m, m1;
int ret;
int retval = VM_PAGER_OK;
struct ttm_mem_type_manager *man =
&bdev->man[bo->mem.mem_type];
vm_object_pip_add(vm_obj, 1);
- oldm = *mres;
- if (oldm != NULL) {
- vm_page_lock(oldm);
- vm_page_remove(oldm);
- vm_page_unlock(oldm);
- *mres = NULL;
- } else
- oldm = NULL;
+ if (*mres != NULL) {
+ vm_page_lock(*mres);
+ vm_page_remove(*mres);
+ vm_page_unlock(*mres);
+ }
retry:
VM_OBJECT_WUNLOCK(vm_obj);
m = NULL;
@@ -261,14 +258,14 @@ reserve:
bo, m, m1, (uintmax_t)offset));
}
m->valid = VM_PAGE_BITS_ALL;
- *mres = m;
vm_page_xbusy(m);
-
- if (oldm != NULL) {
- vm_page_lock(oldm);
- vm_page_free(oldm);
- vm_page_unlock(oldm);
+ if (*mres != NULL) {
+ KASSERT(*mres != m, ("loosing %p %p", *mres, m));
+ vm_page_lock(*mres);
+ vm_page_free(*mres);
+ vm_page_unlock(*mres);
}
+ *mres = m;
out_io_unlock1:
ttm_mem_io_unlock(man);
diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c
index b1b2c4a..93b33ad 100644
--- a/sys/dev/e1000/if_igb.c
+++ b/sys/dev/e1000/if_igb.c
@@ -1184,10 +1184,27 @@ igb_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
}
}
#endif
+#if __FreeBSD_version >= 1000000
+ /* HW cannot turn these on/off separately */
+ if (mask & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) {
+ ifp->if_capenable ^= IFCAP_RXCSUM;
+ ifp->if_capenable ^= IFCAP_RXCSUM_IPV6;
+ reinit = 1;
+ }
+ if (mask & IFCAP_TXCSUM) {
+ ifp->if_capenable ^= IFCAP_TXCSUM;
+ reinit = 1;
+ }
+ if (mask & IFCAP_TXCSUM_IPV6) {
+ ifp->if_capenable ^= IFCAP_TXCSUM_IPV6;
+ reinit = 1;
+ }
+#else
if (mask & IFCAP_HWCSUM) {
ifp->if_capenable ^= IFCAP_HWCSUM;
reinit = 1;
}
+#endif
if (mask & IFCAP_TSO4) {
ifp->if_capenable ^= IFCAP_TSO4;
reinit = 1;
@@ -1266,14 +1283,26 @@ igb_init_locked(struct adapter *adapter)
/* Set hardware offload abilities */
ifp->if_hwassist = 0;
if (ifp->if_capenable & IFCAP_TXCSUM) {
+#if __FreeBSD_version >= 1000000
+ ifp->if_hwassist |= (CSUM_IP_TCP | CSUM_IP_UDP);
+ if (adapter->hw.mac.type != e1000_82575)
+ ifp->if_hwassist |= CSUM_IP_SCTP;
+#else
ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP);
#if __FreeBSD_version >= 800000
- if ((adapter->hw.mac.type == e1000_82576) ||
- (adapter->hw.mac.type == e1000_82580))
+ if (adapter->hw.mac.type != e1000_82575)
ifp->if_hwassist |= CSUM_SCTP;
#endif
+#endif
}
+#if __FreeBSD_version >= 1000000
+ if (ifp->if_capenable & IFCAP_TXCSUM_IPV6) {
+ ifp->if_hwassist |= (CSUM_IP6_TCP | CSUM_IP6_UDP);
+ if (adapter->hw.mac.type != e1000_82575)
+ ifp->if_hwassist |= CSUM_IP6_SCTP;
+ }
+#endif
if (ifp->if_capenable & IFCAP_TSO)
ifp->if_hwassist |= CSUM_TSO;
@@ -3160,6 +3189,9 @@ igb_setup_interface(device_t dev, struct adapter *adapter)
ifp->if_capabilities = ifp->if_capenable = 0;
ifp->if_capabilities = IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM;
+#if __FreeBSD_version >= 1000000
+ ifp->if_capabilities |= IFCAP_HWCSUM_IPV6;
+#endif
ifp->if_capabilities |= IFCAP_TSO;
ifp->if_capabilities |= IFCAP_JUMBO_MTU;
ifp->if_capenable = ifp->if_capabilities;
@@ -3933,17 +3965,29 @@ igb_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp,
switch (ipproto) {
case IPPROTO_TCP:
+#if __FreeBSD_version >= 1000000
+ if (mp->m_pkthdr.csum_flags & (CSUM_IP_TCP | CSUM_IP6_TCP))
+#else
if (mp->m_pkthdr.csum_flags & CSUM_TCP)
+#endif
type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_L4T_TCP;
break;
case IPPROTO_UDP:
+#if __FreeBSD_version >= 1000000
+ if (mp->m_pkthdr.csum_flags & (CSUM_IP_UDP | CSUM_IP6_UDP))
+#else
if (mp->m_pkthdr.csum_flags & CSUM_UDP)
+#endif
type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_L4T_UDP;
break;
#if __FreeBSD_version >= 800000
case IPPROTO_SCTP:
+#if __FreeBSD_version >= 1000000
+ if (mp->m_pkthdr.csum_flags & (CSUM_IP_SCTP | CSUM_IP6_SCTP))
+#else
if (mp->m_pkthdr.csum_flags & CSUM_SCTP)
+#endif
type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_L4T_SCTP;
break;
#endif
@@ -4701,8 +4745,7 @@ igb_initialize_receive_units(struct adapter *adapter)
rxcsum |= E1000_RXCSUM_PCSD;
#if __FreeBSD_version >= 800000
/* For SCTP Offload */
- if (((hw->mac.type == e1000_82576) ||
- (hw->mac.type == e1000_82580)) &&
+ if ((hw->mac.type != e1000_82575) &&
(ifp->if_capenable & IFCAP_RXCSUM))
rxcsum |= E1000_RXCSUM_CRCOFL;
#endif
@@ -4711,8 +4754,7 @@ igb_initialize_receive_units(struct adapter *adapter)
if (ifp->if_capenable & IFCAP_RXCSUM) {
rxcsum |= E1000_RXCSUM_IPPCSE;
#if __FreeBSD_version >= 800000
- if ((adapter->hw.mac.type == e1000_82576) ||
- (adapter->hw.mac.type == e1000_82580))
+ if (adapter->hw.mac.type != e1000_82575)
rxcsum |= E1000_RXCSUM_CRCOFL;
#endif
} else
@@ -4932,7 +4974,6 @@ igb_rxeof(struct igb_queue *que, int count, int *done)
struct rx_ring *rxr = que->rxr;
struct ifnet *ifp = adapter->ifp;
struct lro_ctrl *lro = &rxr->lro;
- struct lro_entry *queued;
int i, processed = 0, rxdone = 0;
u32 ptype, staterr = 0;
union e1000_adv_rx_desc *cur;
@@ -5160,10 +5201,7 @@ next_desc:
/*
* Flush any outstanding LRO work
*/
- while ((queued = SLIST_FIRST(&lro->lro_active)) != NULL) {
- SLIST_REMOVE_HEAD(&lro->lro_active, next);
- tcp_lro_flush(lro, queued);
- }
+ tcp_lro_flush_all(lro);
if (done != NULL)
*done += rxdone;
diff --git a/sys/dev/e1000/if_igb.h b/sys/dev/e1000/if_igb.h
index 98df1ec..a0c35be 100644
--- a/sys/dev/e1000/if_igb.h
+++ b/sys/dev/e1000/if_igb.h
@@ -291,7 +291,11 @@
#define ETH_ADDR_LEN 6
/* Offload bits in mbuf flag */
-#if __FreeBSD_version >= 800000
+#if __FreeBSD_version >= 1000000
+#define CSUM_OFFLOAD_IPV4 (CSUM_IP|CSUM_IP_TCP|CSUM_IP_UDP|CSUM_IP_SCTP)
+#define CSUM_OFFLOAD_IPV6 (CSUM_IP6_TCP|CSUM_IP6_UDP|CSUM_IP6_SCTP)
+#define CSUM_OFFLOAD (CSUM_OFFLOAD_IPV4|CSUM_OFFLOAD_IPV6)
+#elif __FreeBSD_version >= 800000
#define CSUM_OFFLOAD (CSUM_IP|CSUM_TCP|CSUM_UDP|CSUM_SCTP)
#else
#define CSUM_OFFLOAD (CSUM_IP|CSUM_TCP|CSUM_UDP)
diff --git a/sys/dev/ed/if_ed_3c503.c b/sys/dev/ed/if_ed_3c503.c
index 353fbbf..bcb9e44 100644
--- a/sys/dev/ed/if_ed_3c503.c
+++ b/sys/dev/ed/if_ed_3c503.c
@@ -324,7 +324,7 @@ ed_probe_3Com(device_t dev, int port_rid, int flags)
ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ5);
break;
default:
- device_printf(dev, "Invalid irq configuration (%ld) must be 3-5,9 for 3c503\n",
+ device_printf(dev, "Invalid irq configuration (%jd) must be 3-5,9 for 3c503\n",
irq);
return (ENXIO);
}
diff --git a/sys/dev/ed/if_ed_cbus.c b/sys/dev/ed/if_ed_cbus.c
index f9672ac..7926fa8 100644
--- a/sys/dev/ed/if_ed_cbus.c
+++ b/sys/dev/ed/if_ed_cbus.c
@@ -1021,7 +1021,7 @@ ed_probe_CNET98(device_t dev, int port_rid, int flags)
if (((rman_get_start(sc->port_res) & 0x0fff) != 0x03d0)
|| ((rman_get_start(sc->port_res) & 0xf000) < (u_short) 0xa000)) {
#ifdef DIAGNOSTIC
- device_printf(dev, "Invalid i/o port configuration (0x%lx) "
+ device_printf(dev, "Invalid i/o port configuration (0x%jx) "
"must be %s for %s\n", rman_get_start(sc->port_res),
"0x[a-f]3d0", "CNET98");
#endif
@@ -1032,7 +1032,7 @@ ed_probe_CNET98(device_t dev, int port_rid, int flags)
/* Check window area address */
tmp_s = rman_get_start(sc->mem_res) >> 12;
if (tmp_s < 0x80) {
- device_printf(dev, "Please change window address(0x%lx)\n",
+ device_printf(dev, "Please change window address(0x%jx)\n",
rman_get_start(sc->mem_res));
return (ENXIO);
}
@@ -1040,8 +1040,8 @@ ed_probe_CNET98(device_t dev, int port_rid, int flags)
tmp_s &= 0x0f;
tmp = rman_get_start(sc->port_res) >> 12;
if ((tmp_s <= tmp) && (tmp < (tmp_s + 4))) {
- device_printf(dev, "Please change iobase address(0x%lx) "
- "or window address(0x%lx)\n",
+ device_printf(dev, "Please change iobase address(0x%jx) "
+ "or window address(0x%jx)\n",
rman_get_start(sc->port_res),
rman_get_start(sc->mem_res));
return (ENXIO);
@@ -1128,7 +1128,7 @@ ed_probe_CNET98(device_t dev, int port_rid, int flags)
tmp = ED_CNET98_INT_IRQ13;
break;
default:
- device_printf(dev, "Invalid irq configuration (%ld) must be "
+ device_printf(dev, "Invalid irq configuration (%jd) must be "
"%s for %s\n", conf_irq, "3,5,6,9,12,13", "CNET98");
return (ENXIO);
}
@@ -1169,7 +1169,7 @@ ed_probe_CNET98EL(device_t dev, int port_rid, int flags)
/* Check I/O address. 0x[0-f]3d0 are allowed. */
if ((rman_get_start(sc->port_res) & 0x0fff) != 0x03d0) {
#ifdef DIAGNOSTIC
- device_printf(dev, "Invalid i/o port configuration (0x%lx) "
+ device_printf(dev, "Invalid i/o port configuration (0x%jx) "
"must be %s for %s\n", rman_get_start(sc->port_res),
"0x?3d0", "CNET98E/L");
#endif
@@ -1223,7 +1223,7 @@ ed_probe_CNET98EL(device_t dev, int port_rid, int flags)
break;
#endif
default:
- device_printf(dev, "Invalid irq configuration (%ld) must be "
+ device_printf(dev, "Invalid irq configuration (%jd) must be "
"%s for %s\n", conf_irq, "3,5,6", "CNET98E/L");
return (ENXIO);
}
@@ -1285,7 +1285,7 @@ ed_probe_NEC77(device_t dev, int port_rid, int flags)
tmp = ED_NEC77_IRQ13;
break;
default:
- device_printf(dev, "Invalid irq configuration (%ld) must be "
+ device_printf(dev, "Invalid irq configuration (%jd) must be "
"%s for %s\n", conf_irq, "3,5,6,12,13", "PC-9801-77");
return (ENXIO);
}
@@ -1337,7 +1337,7 @@ ed_probe_NW98X(device_t dev, int port_rid, int flags)
tmp = ED_NW98X_IRQ13;
break;
default:
- device_printf(dev, "Invalid irq configuration (%ld) must be "
+ device_printf(dev, "Invalid irq configuration (%jd) must be "
"%s for %s\n", conf_irq, "3,5,6,12,13", "EC/EP-98X");
return (ENXIO);
}
@@ -1439,7 +1439,7 @@ ed_probe_SB98(device_t dev, int port_rid, int flags)
/* Check I/O address. 00d[02468ace] are allowed. */
if ((rman_get_start(sc->port_res) & ~0x000e) != 0x00d0) {
#ifdef DIAGNOSTIC
- device_printf(dev, "Invalid i/o port configuration (0x%lx) "
+ device_printf(dev, "Invalid i/o port configuration (0x%jx) "
"must be %s for %s\n", rman_get_start(sc->port_res),
"0xd?", "SB9801");
#endif
@@ -1475,7 +1475,7 @@ ed_probe_SB98(device_t dev, int port_rid, int flags)
tmp = ED_SB98_CFG_IRQ12;
break;
default:
- device_printf(dev, "Invalid irq configuration (%ld) must be "
+ device_printf(dev, "Invalid irq configuration (%jd) must be "
"%s for %s\n", conf_irq, "3,5,6,12", "SB9801");
return (ENXIO);
}
diff --git a/sys/dev/extres/clk/clk.c b/sys/dev/extres/clk/clk.c
index f1ed098..07cbd6b 100644
--- a/sys/dev/extres/clk/clk.c
+++ b/sys/dev/extres/clk/clk.c
@@ -487,10 +487,10 @@ clkdom_dump(struct clkdom * clkdom)
CLK_TOPO_SLOCK();
TAILQ_FOREACH(clknode, &clkdom->clknode_list, clkdom_link) {
rv = clknode_get_freq(clknode, &freq);
- printf("Clock: %s, parent: %s(%d), freq: %llu\n", clknode->name,
+ printf("Clock: %s, parent: %s(%d), freq: %ju\n", clknode->name,
clknode->parent == NULL ? "(NULL)" : clknode->parent->name,
clknode->parent_idx,
- ((rv == 0) ? freq: rv));
+ (uintmax_t)((rv == 0) ? freq: rv));
}
CLK_TOPO_UNLOCK();
}
@@ -818,6 +818,10 @@ clknode_set_freq(struct clknode *clknode, uint64_t freq, int flags,
/* We have exclusive topology lock, node lock is not needed. */
CLK_TOPO_XASSERT();
+ /* Check for no change */
+ if (clknode->freq == freq)
+ return (0);
+
parent_freq = 0;
/*
@@ -1258,4 +1262,75 @@ clk_get_by_ofw_name(device_t dev, const char *name, clk_t *clk)
return (rv);
return (clk_get_by_ofw_index(dev, idx, clk));
}
+
+/* --------------------------------------------------------------------------
+ *
+ * Support functions for parsing various clock related OFW things.
+ */
+
+/*
+ * Get "clock-output-names" and (optional) "clock-indices" lists.
+ * Both lists are alocated using M_OFWPROP specifier.
+ *
+ * Returns number of items or 0.
+ */
+int
+clk_parse_ofw_out_names(device_t dev, phandle_t node, const char ***out_names,
+ uint32_t **indices)
+{
+ int name_items, rv;
+
+ *out_names = NULL;
+ *indices = NULL;
+ if (!OF_hasprop(node, "clock-output-names"))
+ return (0);
+ rv = ofw_bus_string_list_to_array(node, "clock-output-names",
+ out_names);
+ if (rv <= 0)
+ return (0);
+ name_items = rv;
+
+ if (!OF_hasprop(node, "clock-indices"))
+ return (name_items);
+ rv = OF_getencprop_alloc(node, "clock-indices", sizeof (uint32_t),
+ (void **)indices);
+ if (rv != name_items) {
+ device_printf(dev, " Size of 'clock-output-names' and "
+ "'clock-indices' differs\n");
+ free(*out_names, M_OFWPROP);
+ free(*indices, M_OFWPROP);
+ return (0);
+ }
+ return (name_items);
+}
+
+/*
+ * Get output clock name for single output clock node.
+ */
+int
+clk_parse_ofw_clk_name(device_t dev, phandle_t node, const char **name)
+{
+ const char **out_names;
+ const char *tmp_name;
+ int rv;
+
+ *name = NULL;
+ if (!OF_hasprop(node, "clock-output-names")) {
+ tmp_name = ofw_bus_get_name(dev);
+ if (tmp_name == NULL)
+ return (ENXIO);
+ *name = strdup(tmp_name, M_OFWPROP);
+ return (0);
+ }
+ rv = ofw_bus_string_list_to_array(node, "clock-output-names",
+ &out_names);
+ if (rv != 1) {
+ free(out_names, M_OFWPROP);
+ device_printf(dev, "Malformed 'clock-output-names' property\n");
+ return (ENXIO);
+ }
+ *name = strdup(out_names[0], M_OFWPROP);
+ free(out_names, M_OFWPROP);
+ return (0);
+}
#endif
diff --git a/sys/dev/extres/clk/clk.h b/sys/dev/extres/clk/clk.h
index 8547bae..510f0ce 100644
--- a/sys/dev/extres/clk/clk.h
+++ b/sys/dev/extres/clk/clk.h
@@ -131,6 +131,9 @@ const char *clk_get_name(clk_t clk);
#ifdef FDT
int clk_get_by_ofw_index(device_t dev, int idx, clk_t *clk);
int clk_get_by_ofw_name(device_t dev, const char *name, clk_t *clk);
+int clk_parse_ofw_out_names(device_t dev, phandle_t node,
+ const char ***out_names, uint32_t **indices);
+int clk_parse_ofw_clk_name(device_t dev, phandle_t node, const char **name);
#endif
#endif /* _DEV_EXTRES_CLK_H_ */
diff --git a/sys/dev/extres/clk/clk_bus.c b/sys/dev/extres/clk/clk_bus.c
new file mode 100644
index 0000000..e475736
--- /dev/null
+++ b/sys/dev/extres/clk/clk_bus.c
@@ -0,0 +1,93 @@
+/*-
+ * Copyright 2016 Michal Meloun <mmel@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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+
+#include <dev/fdt/simplebus.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+struct ofw_clkbus_softc {
+ struct simplebus_softc simplebus_sc;
+};
+
+static int
+ofw_clkbus_probe(device_t dev)
+{
+ const char *name;
+
+ name = ofw_bus_get_name(dev);
+
+ if (name == NULL || strcmp(name, "clocks") != 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "OFW clocks bus");
+
+ return (BUS_PROBE_GENERIC);
+}
+
+static int
+ofw_clkbus_attach(device_t dev)
+{
+ struct ofw_clkbus_softc *sc;
+ phandle_t node, child;
+ device_t cdev;
+
+ sc = device_get_softc(dev);
+ node = ofw_bus_get_node(dev);
+ simplebus_init(dev, node);
+
+ for (child = OF_child(node); child > 0; child = OF_peer(child)) {
+ cdev = simplebus_add_device(dev, child, 0, NULL, -1, NULL);
+ if (cdev != NULL)
+ device_probe_and_attach(cdev);
+ }
+
+ return (bus_generic_attach(dev));
+}
+
+static device_method_t ofw_clkbus_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ofw_clkbus_probe),
+ DEVMETHOD(device_attach, ofw_clkbus_attach),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_1(ofw_clkbus, ofw_clkbus_driver, ofw_clkbus_methods,
+ sizeof(struct ofw_clkbus_softc), simplebus_driver);
+static devclass_t ofw_clkbus_devclass;
+EARLY_DRIVER_MODULE(ofw_clkbus, simplebus, ofw_clkbus_driver,
+ ofw_clkbus_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
+MODULE_VERSION(ofw_clkbus, 1);
diff --git a/sys/dev/extres/clk/clk_div.c b/sys/dev/extres/clk/clk_div.c
index fcb0a57..51cc838 100644
--- a/sys/dev/extres/clk/clk_div.c
+++ b/sys/dev/extres/clk/clk_div.c
@@ -46,6 +46,10 @@ __FBSDID("$FreeBSD$");
CLKDEV_READ_4(clknode_get_device(_clk), off, val)
#define MD4(_clk, off, clr, set ) \
CLKDEV_MODIFY_4(clknode_get_device(_clk), off, clr, set)
+#define DEVICE_LOCK(_clk) \
+ CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
+#define DEVICE_UNLOCK(_clk) \
+ CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
static int clknode_div_init(struct clknode *clk, device_t dev);
static int clknode_div_recalc(struct clknode *clk, uint64_t *req);
@@ -86,7 +90,9 @@ clknode_div_init(struct clknode *clk, device_t dev)
sc = clknode_get_softc(clk);
+ DEVICE_LOCK(clk);
rv = RD4(clk, sc->offset, &reg);
+ DEVICE_UNLOCK(clk);
if (rv != 0)
return (rv);
@@ -171,12 +177,17 @@ clknode_div_set_freq(struct clknode *clk, uint64_t fin, uint64_t *fout,
(*fout != (_fin / divider)))
return (ERANGE);
+ DEVICE_LOCK(clk);
rv = MD4(clk, sc->offset,
(sc->i_mask << sc->i_shift) | (sc->f_mask << sc->f_shift),
(i_div << sc->i_shift) | (f_div << sc->f_shift));
- if (rv != 0)
+ if (rv != 0) {
+ DEVICE_UNLOCK(clk);
return (rv);
+ }
RD4(clk, sc->offset, &reg);
+ DEVICE_UNLOCK(clk);
+
sc->divider = divider;
}
diff --git a/sys/dev/extres/clk/clk_fixed.c b/sys/dev/extres/clk/clk_fixed.c
index 4ddceae..02721ae 100644
--- a/sys/dev/extres/clk/clk_fixed.c
+++ b/sys/dev/extres/clk/clk_fixed.c
@@ -27,7 +27,6 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/bus.h>
@@ -35,20 +34,25 @@ __FBSDID("$FreeBSD$");
#include <sys/kobj.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
+#include <sys/module.h>
#include <sys/rman.h>
#include <sys/systm.h>
#include <machine/bus.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
#include <dev/extres/clk/clk_fixed.h>
-#define DEVICE_LOCK(_sc) mtx_lock((_sc)->mtx)
-#define DEVICE_UNLOCK(_sc) mtx_unlock((_sc)->mtx)
+#define CLK_TYPE_FIXED 1
+#define CLK_TYPE_FIXED_FACTOR 2
static int clknode_fixed_init(struct clknode *clk, device_t dev);
static int clknode_fixed_recalc(struct clknode *clk, uint64_t *freq);
+static int clknode_fixed_set_freq(struct clknode *clk, uint64_t fin,
+ uint64_t *fout, int flags, int *stop);
+
struct clknode_fixed_sc {
- struct mtx *mtx;
int fixed_flags;
uint64_t freq;
uint32_t mult;
@@ -59,6 +63,7 @@ static clknode_method_t clknode_fixed_methods[] = {
/* Device interface */
CLKNODEMETHOD(clknode_init, clknode_fixed_init),
CLKNODEMETHOD(clknode_recalc_freq, clknode_fixed_recalc),
+ CLKNODEMETHOD(clknode_set_freq, clknode_fixed_set_freq),
CLKNODEMETHOD_END
};
DEFINE_CLASS_1(clknode_fixed, clknode_fixed_class, clknode_fixed_methods,
@@ -74,36 +79,52 @@ clknode_fixed_init(struct clknode *clk, device_t dev)
clknode_init_parent_idx(clk, 0);
return(0);
}
+
static int
clknode_fixed_recalc(struct clknode *clk, uint64_t *freq)
{
struct clknode_fixed_sc *sc;
sc = clknode_get_softc(clk);
- if (sc->freq != 0)
- *freq = sc->freq;
- else if ((sc->mult != 0) && (sc->div != 0))
+
+ if ((sc->mult != 0) && (sc->div != 0))
*freq = (*freq / sc->div) * sc->mult;
else
- *freq = 0;
+ *freq = sc->freq;
+ return (0);
+}
+
+static int
+clknode_fixed_set_freq(struct clknode *clk, uint64_t fin, uint64_t *fout,
+ int flags, int *stop)
+{
+ struct clknode_fixed_sc *sc;
+
+ sc = clknode_get_softc(clk);
+ if (sc->mult == 0 || sc->div == 0) {
+ /* Fixed frequency clock. */
+ *stop = 1;
+ if (*fout != sc->freq)
+ return (ERANGE);
+ return (0);
+ }
+ /* Fixed factor clock. */
+ *stop = 0;
+ *fout = (*fout / sc->mult) * sc->div;
return (0);
}
int
-clknode_fixed_register(struct clkdom *clkdom, struct clk_fixed_def *clkdef,
- struct mtx *dev_mtx)
+clknode_fixed_register(struct clkdom *clkdom, struct clk_fixed_def *clkdef)
{
struct clknode *clk;
struct clknode_fixed_sc *sc;
- if ((clkdef->freq == 0) && (clkdef->clkdef.parent_cnt == 0))
- panic("fixed clk: Frequency is not defined for clock source");
clk = clknode_create(clkdom, &clknode_fixed_class, &clkdef->clkdef);
if (clk == NULL)
return (1);
sc = clknode_get_softc(clk);
- sc->mtx = dev_mtx;
sc->fixed_flags = clkdef->fixed_flags;
sc->freq = clkdef->freq;
sc->mult = clkdef->mult;
@@ -112,3 +133,150 @@ clknode_fixed_register(struct clkdom *clkdom, struct clk_fixed_def *clkdef,
clknode_register(clkdom, clk);
return (0);
}
+
+#ifdef FDT
+
+static struct ofw_compat_data compat_data[] = {
+ {"fixed-clock", CLK_TYPE_FIXED},
+ {"fixed-factor-clock", CLK_TYPE_FIXED_FACTOR},
+ {NULL, 0},
+};
+
+struct clk_fixed_softc {
+ device_t dev;
+ struct clkdom *clkdom;
+};
+
+static int
+clk_fixed_probe(device_t dev)
+{
+ intptr_t clk_type;
+
+ clk_type = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
+ switch (clk_type) {
+ case CLK_TYPE_FIXED:
+ device_set_desc(dev, "Fixed clock");
+ return (BUS_PROBE_DEFAULT);
+ case CLK_TYPE_FIXED_FACTOR:
+ device_set_desc(dev, "Fixed factor clock");
+ return (BUS_PROBE_DEFAULT);
+ default:
+ return (ENXIO);
+ }
+}
+
+static int
+clk_fixed_init_fixed(struct clk_fixed_softc *sc, phandle_t node,
+ struct clk_fixed_def *def)
+{
+ uint32_t freq;
+ int rv;
+
+ def->clkdef.id = 1;
+ rv = OF_getencprop(node, "clock-frequency", &freq, sizeof(freq));
+ if (rv <= 0)
+ return (ENXIO);
+ def->freq = freq;
+ return (0);
+}
+
+static int
+clk_fixed_init_fixed_factor(struct clk_fixed_softc *sc, phandle_t node,
+ struct clk_fixed_def *def)
+{
+ int rv;
+ clk_t parent;
+
+ def->clkdef.id = 1;
+ rv = OF_getencprop(node, "clock-mult", &def->mult, sizeof(def->mult));
+ if (rv <= 0)
+ return (ENXIO);
+ rv = OF_getencprop(node, "clock-div", &def->div, sizeof(def->div));
+ if (rv <= 0)
+ return (ENXIO);
+ /* Get name of parent clock */
+ rv = clk_get_by_ofw_index(sc->dev, 0, &parent);
+ if (rv != 0)
+ return (ENXIO);
+ def->clkdef.parent_names = malloc(sizeof(char *), M_OFWPROP, M_WAITOK);
+ def->clkdef.parent_names[0] = clk_get_name(parent);
+ def->clkdef.parent_cnt = 1;
+ clk_release(parent);
+ return (0);
+}
+
+static int
+clk_fixed_attach(device_t dev)
+{
+ struct clk_fixed_softc *sc;
+ intptr_t clk_type;
+ phandle_t node;
+ struct clk_fixed_def def;
+ int rv;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ node = ofw_bus_get_node(dev);
+ clk_type = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
+
+ bzero(&def, sizeof(def));
+ if (clk_type == CLK_TYPE_FIXED)
+ rv = clk_fixed_init_fixed(sc, node, &def);
+ else if (clk_type == CLK_TYPE_FIXED_FACTOR)
+ rv = clk_fixed_init_fixed_factor(sc, node, &def);
+ else
+ rv = ENXIO;
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot FDT parameters.\n");
+ goto fail;
+ }
+ rv = clk_parse_ofw_clk_name(dev, node, &def.clkdef.name);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot parse clock name.\n");
+ goto fail;
+ }
+ sc->clkdom = clkdom_create(dev);
+ KASSERT(sc->clkdom != NULL, ("Clock domain is NULL"));
+
+ rv = clknode_fixed_register(sc->clkdom, &def);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot register fixed clock.\n");
+ rv = ENXIO;
+ goto fail;
+ }
+
+ rv = clkdom_finit(sc->clkdom);
+ if (rv != 0) {
+ device_printf(sc->dev, "Clk domain finit fails.\n");
+ rv = ENXIO;
+ goto fail;
+ }
+#ifdef CLK_DEBUG
+ clkdom_dump(sc->clkdom);
+#endif
+ free(__DECONST(char *, def.clkdef.name), M_OFWPROP);
+ free(def.clkdef.parent_names, M_OFWPROP);
+ return (bus_generic_attach(dev));
+
+fail:
+ free(__DECONST(char *, def.clkdef.name), M_OFWPROP);
+ free(def.clkdef.parent_names, M_OFWPROP);
+ return (rv);
+}
+
+static device_method_t clk_fixed_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, clk_fixed_probe),
+ DEVMETHOD(device_attach, clk_fixed_attach),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(clk_fixed, clk_fixed_driver, clk_fixed_methods,
+ sizeof(struct clk_fixed_softc));
+static devclass_t clk_fixed_devclass;
+EARLY_DRIVER_MODULE(clk_fixed, simplebus, clk_fixed_driver,
+ clk_fixed_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
+MODULE_VERSION(clk_fixed, 1);
+
+#endif
diff --git a/sys/dev/extres/clk/clk_fixed.h b/sys/dev/extres/clk/clk_fixed.h
index f57ee96..e2643ff 100644
--- a/sys/dev/extres/clk/clk_fixed.h
+++ b/sys/dev/extres/clk/clk_fixed.h
@@ -47,7 +47,6 @@ struct clk_fixed_def {
int fixed_flags;
};
-int clknode_fixed_register(struct clkdom *clkdom, struct clk_fixed_def *clkdef,
- struct mtx *dev_mtx);
+int clknode_fixed_register(struct clkdom *clkdom, struct clk_fixed_def *clkdef);
#endif /*_DEV_EXTRES_CLK_FIXED_H_*/
diff --git a/sys/dev/extres/clk/clk_gate.c b/sys/dev/extres/clk/clk_gate.c
index 2107450..e0673fd 100644
--- a/sys/dev/extres/clk/clk_gate.c
+++ b/sys/dev/extres/clk/clk_gate.c
@@ -46,7 +46,10 @@ __FBSDID("$FreeBSD$");
CLKDEV_READ_4(clknode_get_device(_clk), off, val)
#define MD4(_clk, off, clr, set ) \
CLKDEV_MODIFY_4(clknode_get_device(_clk), off, clr, set)
-
+#define DEVICE_LOCK(_clk) \
+ CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
+#define DEVICE_UNLOCK(_clk) \
+ CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
static int clknode_gate_init(struct clknode *clk, device_t dev);
static int clknode_gate_set_gate(struct clknode *clk, bool enable);
@@ -77,7 +80,9 @@ clknode_gate_init(struct clknode *clk, device_t dev)
int rv;
sc = clknode_get_softc(clk);
+ DEVICE_LOCK(clk);
rv = RD4(clk, sc->offset, &reg);
+ DEVICE_UNLOCK(clk);
if (rv != 0)
return (rv);
reg = (reg >> sc->shift) & sc->mask;
@@ -95,11 +100,15 @@ clknode_gate_set_gate(struct clknode *clk, bool enable)
sc = clknode_get_softc(clk);
sc->ungated = enable;
+ DEVICE_LOCK(clk);
rv = MD4(clk, sc->offset, sc->mask << sc->shift,
(sc->ungated ? sc->on_value : sc->off_value) << sc->shift);
- if (rv != 0)
+ if (rv != 0) {
+ DEVICE_UNLOCK(clk);
return (rv);
+ }
RD4(clk, sc->offset, &reg);
+ DEVICE_UNLOCK(clk);
return(0);
}
diff --git a/sys/dev/extres/clk/clk_mux.c b/sys/dev/extres/clk/clk_mux.c
index 54e0653..624f587 100644
--- a/sys/dev/extres/clk/clk_mux.c
+++ b/sys/dev/extres/clk/clk_mux.c
@@ -46,6 +46,10 @@ __FBSDID("$FreeBSD$");
CLKDEV_READ_4(clknode_get_device(_clk), off, val)
#define MD4(_clk, off, clr, set ) \
CLKDEV_MODIFY_4(clknode_get_device(_clk), off, clr, set)
+#define DEVICE_LOCK(_clk) \
+ CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
+#define DEVICE_UNLOCK(_clk) \
+ CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
static int clknode_mux_init(struct clknode *clk, device_t dev);
static int clknode_mux_set_mux(struct clknode *clk, int idx);
@@ -76,9 +80,12 @@ clknode_mux_init(struct clknode *clk, device_t dev)
sc = clknode_get_softc(clk);
+ DEVICE_LOCK(clk);
rv = RD4(clk, sc->offset, &reg);
- if (rv != 0)
+ DEVICE_UNLOCK(clk);
+ if (rv != 0) {
return (rv);
+ }
reg = (reg >> sc->shift) & sc->mask;
clknode_init_parent_idx(clk, reg);
return(0);
@@ -93,11 +100,16 @@ clknode_mux_set_mux(struct clknode *clk, int idx)
sc = clknode_get_softc(clk);
+ DEVICE_LOCK(clk);
rv = MD4(clk, sc->offset, sc->mask << sc->shift,
(idx & sc->mask) << sc->shift);
- if (rv != 0)
+ if (rv != 0) {
+ DEVICE_UNLOCK(clk);
return (rv);
+ }
RD4(clk, sc->offset, &reg);
+ DEVICE_UNLOCK(clk);
+
return(0);
}
diff --git a/sys/dev/extres/clk/clkdev_if.m b/sys/dev/extres/clk/clkdev_if.m
index b43d205..f9f5084 100644
--- a/sys/dev/extres/clk/clkdev_if.m
+++ b/sys/dev/extres/clk/clkdev_if.m
@@ -30,6 +30,71 @@
INTERFACE clkdev;
+CODE {
+ #include <sys/systm.h>
+ #include <sys/bus.h>
+ static int
+ clkdev_default_write_4(device_t dev, bus_addr_t addr, uint32_t val)
+ {
+ device_t pdev;
+
+ pdev = device_get_parent(dev);
+ if (pdev == NULL)
+ return (ENXIO);
+
+ return (CLKDEV_WRITE_4(pdev, addr, val));
+ }
+
+ static int
+ clkdev_default_read_4(device_t dev, bus_addr_t addr, uint32_t *val)
+ {
+ device_t pdev;
+
+ pdev = device_get_parent(dev);
+ if (pdev == NULL)
+ return (ENXIO);
+
+ return (CLKDEV_READ_4(pdev, addr, val));
+ }
+
+ static int
+ clkdev_default_modify_4(device_t dev, bus_addr_t addr,
+ uint32_t clear_mask, uint32_t set_mask)
+ {
+ device_t pdev;
+
+ pdev = device_get_parent(dev);
+ if (pdev == NULL)
+ return (ENXIO);
+
+ return (CLKDEV_MODIFY_4(pdev, addr, clear_mask, set_mask));
+ }
+
+ static void
+ clkdev_default_device_lock(device_t dev)
+ {
+ device_t pdev;
+
+ pdev = device_get_parent(dev);
+ if (pdev == NULL)
+ panic("clkdev_device_lock not implemented");
+
+ CLKDEV_DEVICE_LOCK(pdev);
+ }
+
+ static void
+ clkdev_default_device_unlock(device_t dev)
+ {
+ device_t pdev;
+
+ pdev = device_get_parent(dev);
+ if (pdev == NULL)
+ panic("clkdev_device_unlock not implemented");
+
+ CLKDEV_DEVICE_UNLOCK(pdev);
+ }
+}
+
#
# Write single register
#
@@ -37,7 +102,7 @@ METHOD int write_4 {
device_t dev;
bus_addr_t addr;
uint32_t val;
-};
+} DEFAULT clkdev_default_write_4;
#
# Read single register
@@ -46,7 +111,7 @@ METHOD int read_4 {
device_t dev;
bus_addr_t addr;
uint32_t *val;
-};
+} DEFAULT clkdev_default_read_4;
#
# Modify single register
@@ -56,4 +121,18 @@ METHOD int modify_4 {
bus_addr_t addr;
uint32_t clear_mask;
uint32_t set_mask;
-};
+} DEFAULT clkdev_default_modify_4;
+
+#
+# Get exclusive access to underlying device
+#
+METHOD void device_lock {
+ device_t dev;
+} DEFAULT clkdev_default_device_lock;
+
+#
+# Release exclusive access to underlying device
+#
+METHOD void device_unlock {
+ device_t dev;
+} DEFAULT clkdev_default_device_unlock;
diff --git a/sys/dev/extres/phy/phy.c b/sys/dev/extres/phy/phy.c
new file mode 100644
index 0000000..0e2c7e1
--- /dev/null
+++ b/sys/dev/extres/phy/phy.c
@@ -0,0 +1,235 @@
+/*-
+ * Copyright 2016 Michal Meloun <mmel@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#include "opt_platform.h"
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/systm.h>
+
+#ifdef FDT
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#endif
+
+#include <dev/extres/phy/phy.h>
+
+#include "phy_if.h"
+
+struct phy {
+ device_t consumer_dev; /* consumer device*/
+ device_t provider_dev; /* provider device*/
+ uintptr_t phy_id; /* phy id */
+};
+
+MALLOC_DEFINE(M_PHY, "phy", "Phy framework");
+
+int
+phy_init(device_t consumer, phy_t phy)
+{
+
+ return (PHY_INIT(phy->provider_dev, phy->phy_id, true));
+}
+
+int
+phy_deinit(device_t consumer, phy_t phy)
+{
+
+ return (PHY_INIT(phy->provider_dev, phy->phy_id, false));
+}
+
+
+int
+phy_enable(device_t consumer, phy_t phy)
+{
+
+ return (PHY_ENABLE(phy->provider_dev, phy->phy_id, true));
+}
+
+int
+phy_disable(device_t consumer, phy_t phy)
+{
+
+ return (PHY_ENABLE(phy->provider_dev, phy->phy_id, false));
+}
+
+int
+phy_status(device_t consumer, phy_t phy, int *value)
+{
+
+ return (PHY_STATUS(phy->provider_dev, phy->phy_id, value));
+}
+
+int
+phy_get_by_id(device_t consumer_dev, device_t provider_dev, intptr_t id,
+ phy_t *phy_out)
+{
+ phy_t phy;
+
+ /* Create handle */
+ phy = malloc(sizeof(struct phy), M_PHY,
+ M_WAITOK | M_ZERO);
+ phy->consumer_dev = consumer_dev;
+ phy->provider_dev = provider_dev;
+ phy->phy_id = id;
+ *phy_out = phy;
+ return (0);
+}
+
+void
+phy_release(phy_t phy)
+{
+ free(phy, M_PHY);
+}
+
+
+#ifdef FDT
+int phy_default_map(device_t provider, phandle_t xref, int ncells,
+ pcell_t *cells, intptr_t *id)
+{
+
+ if (ncells == 0)
+ *id = 1;
+ else if (ncells == 1)
+ *id = cells[0];
+ else
+ return (ERANGE);
+
+ return (0);
+}
+
+int
+phy_get_by_ofw_idx(device_t consumer_dev, int idx, phy_t *phy)
+{
+ phandle_t cnode, xnode;
+ pcell_t *cells;
+ device_t phydev;
+ int ncells, rv;
+ intptr_t id;
+
+ cnode = ofw_bus_get_node(consumer_dev);
+ if (cnode <= 0) {
+ device_printf(consumer_dev,
+ "%s called on not ofw based device\n", __func__);
+ return (ENXIO);
+ }
+ rv = ofw_bus_parse_xref_list_alloc(cnode, "phys", "#phy-cells", idx,
+ &xnode, &ncells, &cells);
+ if (rv != 0)
+ return (rv);
+
+ /* Tranlate provider to device. */
+ phydev = OF_device_from_xref(xnode);
+ if (phydev == NULL) {
+ free(cells, M_OFWPROP);
+ return (ENODEV);
+ }
+ /* Map phy to number. */
+ rv = PHY_MAP(phydev, xnode, ncells, cells, &id);
+ free(cells, M_OFWPROP);
+ if (rv != 0)
+ return (rv);
+
+ return (phy_get_by_id(consumer_dev, phydev, id, phy));
+}
+
+int
+phy_get_by_ofw_name(device_t consumer_dev, char *name, phy_t *phy)
+{
+ int rv, idx;
+ phandle_t cnode;
+
+ cnode = ofw_bus_get_node(consumer_dev);
+ if (cnode <= 0) {
+ device_printf(consumer_dev,
+ "%s called on not ofw based device\n", __func__);
+ return (ENXIO);
+ }
+ rv = ofw_bus_find_string_index(cnode, "phy-names", name, &idx);
+ if (rv != 0)
+ return (rv);
+ return (phy_get_by_ofw_idx(consumer_dev, idx, phy));
+}
+
+int
+phy_get_by_ofw_property(device_t consumer_dev, char *name, phy_t *phy)
+{
+ phandle_t cnode;
+ pcell_t *cells;
+ device_t phydev;
+ int ncells, rv;
+ intptr_t id;
+
+ cnode = ofw_bus_get_node(consumer_dev);
+ if (cnode <= 0) {
+ device_printf(consumer_dev,
+ "%s called on not ofw based device\n", __func__);
+ return (ENXIO);
+ }
+ ncells = OF_getencprop_alloc(cnode, name, sizeof(pcell_t),
+ (void **)&cells);
+ if (ncells < 1)
+ return (ENXIO);
+
+ /* Tranlate provider to device. */
+ phydev = OF_device_from_xref(cells[0]);
+ if (phydev == NULL) {
+ free(cells, M_OFWPROP);
+ return (ENODEV);
+ }
+ /* Map phy to number. */
+ rv = PHY_MAP(phydev, cells[0], ncells - 1 , cells + 1, &id);
+ free(cells, M_OFWPROP);
+ if (rv != 0)
+ return (rv);
+
+ return (phy_get_by_id(consumer_dev, phydev, id, phy));
+}
+
+void
+phy_register_provider(device_t provider_dev)
+{
+ phandle_t xref, node;
+
+ node = ofw_bus_get_node(provider_dev);
+ if (node <= 0)
+ panic("%s called on not ofw based device.\n", __func__);
+
+ xref = OF_xref_from_node(node);
+ OF_device_register_xref(xref, provider_dev);
+}
+
+void
+phy_unregister_provider(device_t provider_dev)
+{
+ phandle_t xref;
+
+ xref = OF_xref_from_device(provider_dev);
+ OF_device_register_xref(xref, NULL);
+}
+#endif
diff --git a/sys/dev/extres/phy/phy.h b/sys/dev/extres/phy/phy.h
new file mode 100644
index 0000000..93b4fe4
--- /dev/null
+++ b/sys/dev/extres/phy/phy.h
@@ -0,0 +1,63 @@
+/*-
+ * Copyright 2016 Michal Meloun <mmel@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef DEV_EXTRES_PHY_H
+#define DEV_EXTRES_PHY_H
+
+#include "opt_platform.h"
+#include <sys/types.h>
+#ifdef FDT
+#include <dev/ofw/ofw_bus.h>
+#endif
+
+typedef struct phy *phy_t;
+
+/*
+ * Provider interface
+ */
+#ifdef FDT
+void phy_register_provider(device_t provider);
+void phy_unregister_provider(device_t provider);
+#endif
+
+/*
+ * Consumer interface
+ */
+int phy_get_by_id(device_t consumer_dev, device_t provider_dev, intptr_t id,
+ phy_t *phy);
+void phy_release(phy_t phy);
+int phy_get_by_ofw_name(device_t consumer, char *name, phy_t *phy);
+int phy_get_by_ofw_idx(device_t consumer, int idx, phy_t *phy);
+int phy_get_by_ofw_property(device_t consumer, char *name, phy_t *phy);
+
+int phy_init(device_t consumer, phy_t phy);
+int phy_deinit(device_t consumer, phy_t phy);
+int phy_enable(device_t consumer, phy_t phy);
+int phy_disable(device_t consumer, phy_t phy);
+int phy_status(device_t consumer, phy_t phy, int *value);
+
+#endif /* DEV_EXTRES_PHY_H */
diff --git a/sys/dev/extres/phy/phy_if.m b/sys/dev/extres/phy/phy_if.m
new file mode 100644
index 0000000..e3b4e33
--- /dev/null
+++ b/sys/dev/extres/phy/phy_if.m
@@ -0,0 +1,84 @@
+#-
+# Copyright 2016 Michal Meloun <mmel@FreeBSD.org>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+
+#ifdef FDT
+#include <sys/types.h>
+#include <dev/ofw/ofw_bus.h>
+#endif
+
+INTERFACE phy;
+
+#ifdef FDT
+HEADER {
+int phy_default_map(device_t , phandle_t, int, pcell_t *, intptr_t *);
+}
+
+#
+# map fdt property cells to phy number
+# Returns 0 on success or a standard errno value.
+#
+METHOD int map {
+ device_t provider_dev;
+ phandle_t xref;
+ int ncells;
+ pcell_t *cells;
+ intptr_t *id;
+} DEFAULT phy_default_map;
+#endif
+
+#
+# Init/deinit phy
+# Returns 0 on success or a standard errno value.
+#
+METHOD int init {
+ device_t provider_dev;
+ intptr_t id;
+ bool inti;
+};
+
+#
+# Enable/disable phy
+# Returns 0 on success or a standard errno value.
+#
+METHOD int enable {
+ device_t provider_dev;
+ intptr_t id;
+ bool enable;
+};
+
+#
+# Get phy status
+# Returns 0 on success or a standard errno value.
+#
+METHOD int status {
+ device_t provider_dev;
+ intptr_t id;
+ int *status; /* PHY_STATUS_* */
+};
+
+
diff --git a/sys/dev/extres/regulator/regdev_if.m b/sys/dev/extres/regulator/regdev_if.m
new file mode 100644
index 0000000..eecbf8b
--- /dev/null
+++ b/sys/dev/extres/regulator/regdev_if.m
@@ -0,0 +1,56 @@
+#-
+# Copyright 2016 Michal Meloun <mmel@FreeBSD.org>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+
+#ifdef FDT
+#include <sys/types.h>
+#include <dev/ofw/ofw_bus.h>
+#endif
+
+#include <machine/bus.h>
+
+INTERFACE regdev;
+
+#ifdef FDT
+
+HEADER {
+int regdev_default_ofw_map(device_t , phandle_t, int, pcell_t *, intptr_t *);
+}
+
+#
+# map fdt property cells to regulator number
+# Returns 0 on success or a standard errno value.
+#
+METHOD int map {
+ device_t provider_dev;
+ phandle_t xref;
+ int ncells;
+ pcell_t *cells;
+ intptr_t *id;
+} DEFAULT regdev_default_ofw_map;
+
+#endif
diff --git a/sys/dev/extres/regulator/regnode_if.m b/sys/dev/extres/regulator/regnode_if.m
new file mode 100644
index 0000000..d92f26f
--- /dev/null
+++ b/sys/dev/extres/regulator/regnode_if.m
@@ -0,0 +1,82 @@
+#-
+# Copyright (c) 2016 Michal Meloun <mmel@FreeBSD.org>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+
+INTERFACE regnode;
+HEADER {
+ struct regnode;
+}
+
+#
+# Initialize regulator
+# Returns 0 on success or a standard errno value.
+#
+METHOD int init {
+ struct regnode *regnode;
+};
+
+#
+# Enable/disable regulator
+# Returns 0 on success or a standard errno value.
+# - enable - input.
+# - delay - output, delay needed to stabilize voltage (in us)
+#
+METHOD int enable {
+ struct regnode *regnode;
+ bool enable;
+ int *udelay;
+};
+
+#
+# Get regulator status
+# Returns 0 on success or a standard errno value.
+#
+METHOD int status {
+ struct regnode *regnode;
+ int *status; /* REGULATOR_STATUS_* */
+};
+
+#
+# Set regulator voltage
+# Returns 0 on success or a standard errno value.
+# - min_uvolt, max_uvolt - input, requested voltage range (in uV)
+# - delay - output, delay needed to stabilize voltage (in us)
+METHOD int set_voltage {
+ struct regnode *regnode;
+ int min_uvolt;
+ int max_uvolt;
+ int *udelay;
+};
+
+#
+# Get regulator voltage
+# Returns 0 on success or a standard errno value.
+#
+METHOD int get_voltage {
+ struct regnode *regnode;
+ int *uvolt;
+};
diff --git a/sys/dev/extres/regulator/regulator.c b/sys/dev/extres/regulator/regulator.c
new file mode 100644
index 0000000..b941aa1
--- /dev/null
+++ b/sys/dev/extres/regulator/regulator.c
@@ -0,0 +1,984 @@
+/*-
+ * Copyright 2016 Michal Meloun <mmel@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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_platform.h"
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/queue.h>
+#include <sys/kobj.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/limits.h>
+#include <sys/lock.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+#include <sys/sx.h>
+
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#endif
+#include <dev/extres/regulator/regulator.h>
+
+#include "regdev_if.h"
+
+MALLOC_DEFINE(M_REGULATOR, "regulator", "Regulator framework");
+
+/* Forward declarations. */
+struct regulator;
+struct regnode;
+
+typedef TAILQ_HEAD(regnode_list, regnode) regnode_list_t;
+typedef TAILQ_HEAD(regulator_list, regulator) regulator_list_t;
+
+/* Default regulator methods. */
+static int regnode_method_enable(struct regnode *regnode, bool enable,
+ int *udelay);
+static int regnode_method_status(struct regnode *regnode, int *status);
+static int regnode_method_set_voltage(struct regnode *regnode, int min_uvolt,
+ int max_uvolt, int *udelay);
+static int regnode_method_get_voltage(struct regnode *regnode, int *uvolt);
+
+/*
+ * Regulator controller methods.
+ */
+static regnode_method_t regnode_methods[] = {
+ REGNODEMETHOD(regnode_enable, regnode_method_enable),
+ REGNODEMETHOD(regnode_status, regnode_method_status),
+ REGNODEMETHOD(regnode_set_voltage, regnode_method_set_voltage),
+ REGNODEMETHOD(regnode_get_voltage, regnode_method_get_voltage),
+
+ REGNODEMETHOD_END
+};
+DEFINE_CLASS_0(regnode, regnode_class, regnode_methods, 0);
+
+/*
+ * Regulator node - basic element for modelling SOC and bard power supply
+ * chains. Its contains producer data.
+ */
+struct regnode {
+ KOBJ_FIELDS;
+
+ TAILQ_ENTRY(regnode) reglist_link; /* Global list entry */
+ regulator_list_t consumers_list; /* Consumers list */
+
+ /* Cache for already resolved names */
+ struct regnode *parent; /* Resolved parent */
+
+ /* Details of this device. */
+ const char *name; /* Globally unique name */
+ const char *parent_name; /* Parent name */
+
+ device_t pdev; /* Producer device_t */
+ void *softc; /* Producer softc */
+ intptr_t id; /* Per producer unique id */
+#ifdef FDT
+ phandle_t ofw_node; /* OFW node of regulator */
+#endif
+ int flags; /* REGULATOR_FLAGS_ */
+ struct sx lock; /* Lock for this regulator */
+ int ref_cnt; /* Reference counter */
+ int enable_cnt; /* Enabled counter */
+
+ struct regnode_std_param std_param; /* Standard parameters */
+};
+
+/*
+ * Per consumer data, information about how a consumer is using a regulator
+ * node.
+ * A pointer to this structure is used as a handle in the consumer interface.
+ */
+struct regulator {
+ device_t cdev; /* Consumer device */
+ struct regnode *regnode;
+ TAILQ_ENTRY(regulator) link; /* Consumers list entry */
+
+ int enable_cnt;
+ int min_uvolt; /* Requested uvolt range */
+ int max_uvolt;
+};
+
+/*
+ * Regulator names must be system wide unique.
+ */
+static regnode_list_t regnode_list = TAILQ_HEAD_INITIALIZER(regnode_list);
+
+static struct sx regnode_topo_lock;
+SX_SYSINIT(regulator_topology, &regnode_topo_lock, "Regulator topology lock");
+
+#define REG_TOPO_SLOCK() sx_slock(&regnode_topo_lock)
+#define REG_TOPO_XLOCK() sx_xlock(&regnode_topo_lock)
+#define REG_TOPO_UNLOCK() sx_unlock(&regnode_topo_lock)
+#define REG_TOPO_ASSERT() sx_assert(&regnode_topo_lock, SA_LOCKED)
+#define REG_TOPO_XASSERT() sx_assert(&regnode_topo_lock, SA_XLOCKED)
+
+#define REGNODE_SLOCK(_sc) sx_slock(&((_sc)->lock))
+#define REGNODE_XLOCK(_sc) sx_xlock(&((_sc)->lock))
+#define REGNODE_UNLOCK(_sc) sx_unlock(&((_sc)->lock))
+
+/* ----------------------------------------------------------------------------
+ *
+ * Default regulator methods for base class.
+ *
+ */
+static int
+regnode_method_enable(struct regnode *regnode, bool enable, int *udelay)
+{
+
+ if (!enable)
+ return (ENXIO);
+
+ *udelay = 0;
+ return (0);
+}
+
+static int
+regnode_method_status(struct regnode *regnode, int *status)
+{
+ *status = REGULATOR_STATUS_ENABLED;
+ return (0);
+}
+
+static int
+regnode_method_set_voltage(struct regnode *regnode, int min_uvolt, int max_uvolt,
+ int *udelay)
+{
+
+ if ((min_uvolt > regnode->std_param.max_uvolt) ||
+ (max_uvolt < regnode->std_param.min_uvolt))
+ return (ERANGE);
+ *udelay = 0;
+ return (0);
+}
+
+static int
+regnode_method_get_voltage(struct regnode *regnode, int *uvolt)
+{
+
+ return (regnode->std_param.min_uvolt +
+ (regnode->std_param.max_uvolt - regnode->std_param.min_uvolt) / 2);
+}
+
+/* ----------------------------------------------------------------------------
+ *
+ * Internal functions.
+ *
+ */
+
+static struct regnode *
+regnode_find_by_name(const char *name)
+{
+ struct regnode *entry;
+
+ REG_TOPO_ASSERT();
+
+ TAILQ_FOREACH(entry, &regnode_list, reglist_link) {
+ if (strcmp(entry->name, name) == 0)
+ return (entry);
+ }
+ return (NULL);
+}
+
+static struct regnode *
+regnode_find_by_id(device_t dev, intptr_t id)
+{
+ struct regnode *entry;
+
+ REG_TOPO_ASSERT();
+
+ TAILQ_FOREACH(entry, &regnode_list, reglist_link) {
+ if ((entry->pdev == dev) && (entry->id == id))
+ return (entry);
+ }
+
+ return (NULL);
+}
+
+/*
+ * Create and initialize regulator object, but do not register it.
+ */
+struct regnode *
+regnode_create(device_t pdev, regnode_class_t regnode_class,
+ struct regnode_init_def *def)
+{
+ struct regnode *regnode;
+
+ KASSERT(def->name != NULL, ("regulator name is NULL"));
+ KASSERT(def->name[0] != '\0', ("regulator name is empty"));
+
+ REG_TOPO_SLOCK();
+ if (regnode_find_by_name(def->name) != NULL)
+ panic("Duplicated regulator registration: %s\n", def->name);
+ REG_TOPO_UNLOCK();
+
+ /* Create object and initialize it. */
+ regnode = malloc(sizeof(struct regnode), M_REGULATOR,
+ M_WAITOK | M_ZERO);
+ kobj_init((kobj_t)regnode, (kobj_class_t)regnode_class);
+ sx_init(&regnode->lock, "Regulator node lock");
+
+ /* Allocate softc if required. */
+ if (regnode_class->size > 0) {
+ regnode->softc = malloc(regnode_class->size, M_REGULATOR,
+ M_WAITOK | M_ZERO);
+ }
+
+
+ /* Copy all strings unless they're flagged as static. */
+ if (def->flags & REGULATOR_FLAGS_STATIC) {
+ regnode->name = def->name;
+ regnode->parent_name = def->parent_name;
+ } else {
+ regnode->name = strdup(def->name, M_REGULATOR);
+ if (def->parent_name != NULL)
+ regnode->parent_name = strdup(def->parent_name,
+ M_REGULATOR);
+ }
+
+ /* Rest of init. */
+ TAILQ_INIT(&regnode->consumers_list);
+ regnode->id = def->id;
+ regnode->pdev = pdev;
+ regnode->flags = def->flags;
+ regnode->parent = NULL;
+ regnode->std_param = def->std_param;
+#ifdef FDT
+ regnode->ofw_node = def->ofw_node;
+#endif
+
+ return (regnode);
+}
+
+/* Register regulator object. */
+struct regnode *
+regnode_register(struct regnode *regnode)
+{
+ int rv;
+
+#ifdef FDT
+ if (regnode->ofw_node <= 0)
+ regnode->ofw_node = ofw_bus_get_node(regnode->pdev);
+ if (regnode->ofw_node <= 0)
+ return (NULL);
+#endif
+
+ rv = REGNODE_INIT(regnode);
+ if (rv != 0) {
+ printf("REGNODE_INIT failed: %d\n", rv);
+ return (NULL);
+ }
+
+ REG_TOPO_XLOCK();
+ TAILQ_INSERT_TAIL(&regnode_list, regnode, reglist_link);
+ REG_TOPO_UNLOCK();
+#ifdef FDT
+ OF_device_register_xref(OF_xref_from_node(regnode->ofw_node),
+ regnode->pdev);
+#endif
+ return (regnode);
+}
+
+static int
+regnode_resolve_parent(struct regnode *regnode)
+{
+
+ /* All ready resolved or no parent? */
+ if ((regnode->parent != NULL) ||
+ (regnode->parent_name == NULL))
+ return (0);
+
+ regnode->parent = regnode_find_by_name(regnode->parent_name);
+ if (regnode->parent == NULL)
+ return (ENODEV);
+ return (0);
+}
+
+static void
+regnode_delay(int usec)
+{
+ int ticks;
+
+ if (usec == 0)
+ return;
+ ticks = (usec * hz + 999999) / 1000000;
+
+ if (cold || ticks < 2)
+ DELAY(usec);
+ else
+ pause("REGULATOR", ticks);
+}
+
+/* --------------------------------------------------------------------------
+ *
+ * Regulator providers interface
+ *
+ */
+
+const char *
+regnode_get_name(struct regnode *regnode)
+{
+
+ return (regnode->name);
+}
+
+const char *
+regnode_get_parent_name(struct regnode *regnode)
+{
+
+ return (regnode->parent_name);
+}
+
+int
+regnode_get_flags(struct regnode *regnode)
+{
+
+ return (regnode->flags);
+}
+
+void *
+regnode_get_softc(struct regnode *regnode)
+{
+
+ return (regnode->softc);
+}
+
+device_t
+regnode_get_device(struct regnode *regnode)
+{
+
+ return (regnode->pdev);
+}
+
+struct regnode_std_param *regnode_get_stdparam(struct regnode *regnode)
+{
+
+ return (&regnode->std_param);
+}
+
+void regnode_topo_unlock(void)
+{
+
+ REG_TOPO_UNLOCK();
+}
+
+void regnode_topo_xlock(void)
+{
+
+ REG_TOPO_XLOCK();
+}
+
+void regnode_topo_slock(void)
+{
+
+ REG_TOPO_SLOCK();
+}
+
+
+/* --------------------------------------------------------------------------
+ *
+ * Real consumers executive
+ *
+ */
+struct regnode *
+regnode_get_parent(struct regnode *regnode)
+{
+ int rv;
+
+ REG_TOPO_ASSERT();
+
+ rv = regnode_resolve_parent(regnode);
+ if (rv != 0)
+ return (NULL);
+
+ return (regnode->parent);
+}
+
+/*
+ * Enable regulator.
+ */
+int
+regnode_enable(struct regnode *regnode)
+{
+ int udelay;
+ int rv;
+
+ REG_TOPO_ASSERT();
+
+ /* Enable regulator for each node in chain, starting from source. */
+ rv = regnode_resolve_parent(regnode);
+ if (rv != 0)
+ return (rv);
+ if (regnode->parent != NULL) {
+ rv = regnode_enable(regnode->parent);
+ if (rv != 0)
+ return (rv);
+ }
+
+ /* Handle this node. */
+ REGNODE_XLOCK(regnode);
+ if (regnode->enable_cnt == 0) {
+ rv = REGNODE_ENABLE(regnode, true, &udelay);
+ if (rv != 0) {
+ REGNODE_UNLOCK(regnode);
+ return (rv);
+ }
+ regnode_delay(udelay);
+ }
+ regnode->enable_cnt++;
+ REGNODE_UNLOCK(regnode);
+ return (0);
+}
+
+/*
+ * Disable regulator.
+ */
+int
+regnode_disable(struct regnode *regnode)
+{
+ int udelay;
+ int rv;
+
+ REG_TOPO_ASSERT();
+ rv = 0;
+
+ REGNODE_XLOCK(regnode);
+ /* Disable regulator for each node in chain, starting from consumer. */
+ if ((regnode->enable_cnt == 1) &&
+ ((regnode->flags & REGULATOR_FLAGS_NOT_DISABLE) == 0)) {
+ rv = REGNODE_ENABLE(regnode, false, &udelay);
+ if (rv != 0) {
+ REGNODE_UNLOCK(regnode);
+ return (rv);
+ }
+ regnode_delay(udelay);
+ }
+ regnode->enable_cnt--;
+ REGNODE_UNLOCK(regnode);
+
+ rv = regnode_resolve_parent(regnode);
+ if (rv != 0)
+ return (rv);
+ if (regnode->parent != NULL)
+ rv = regnode_disable(regnode->parent);
+ return (rv);
+}
+
+/*
+ * Stop regulator.
+ */
+int
+regnode_stop(struct regnode *regnode, int depth)
+{
+ int udelay;
+ int rv;
+
+ REG_TOPO_ASSERT();
+ rv = 0;
+
+ REGNODE_XLOCK(regnode);
+ /* The first node must not be enabled. */
+ if ((regnode->enable_cnt != 0) && (depth == 0)) {
+ REGNODE_UNLOCK(regnode);
+ return (EBUSY);
+ }
+ /* Disable regulator for each node in chain, starting from consumer */
+ if ((regnode->enable_cnt == 0) &&
+ ((regnode->flags & REGULATOR_FLAGS_NOT_DISABLE) == 0)) {
+ rv = REGNODE_ENABLE(regnode, false, &udelay);
+ if (rv != 0) {
+ REGNODE_UNLOCK(regnode);
+ return (rv);
+ }
+ regnode_delay(udelay);
+ }
+ REGNODE_UNLOCK(regnode);
+
+ rv = regnode_resolve_parent(regnode);
+ if (rv != 0)
+ return (rv);
+ if (regnode->parent != NULL)
+ rv = regnode_stop(regnode->parent, depth + 1);
+ return (rv);
+}
+
+/*
+ * Get regulator status. (REGULATOR_STATUS_*)
+ */
+int
+regnode_status(struct regnode *regnode, int *status)
+{
+ int rv;
+
+ REG_TOPO_ASSERT();
+
+ REGNODE_XLOCK(regnode);
+ rv = REGNODE_STATUS(regnode, status);
+ REGNODE_UNLOCK(regnode);
+ return (rv);
+}
+
+/*
+ * Get actual regulator voltage.
+ */
+int
+regnode_get_voltage(struct regnode *regnode, int *uvolt)
+{
+ int rv;
+
+ REG_TOPO_ASSERT();
+
+ REGNODE_XLOCK(regnode);
+ rv = REGNODE_GET_VOLTAGE(regnode, uvolt);
+ REGNODE_UNLOCK(regnode);
+
+ /* Pass call into parent, if regulator is in bypass mode. */
+ if (rv == ENOENT) {
+ rv = regnode_resolve_parent(regnode);
+ if (rv != 0)
+ return (rv);
+ if (regnode->parent != NULL)
+ rv = regnode_get_voltage(regnode->parent, uvolt);
+
+ }
+ return (rv);
+}
+
+/*
+ * Set regulator voltage.
+ */
+int
+regnode_set_voltage(struct regnode *regnode, int min_uvolt, int max_uvolt)
+{
+ int udelay;
+ int rv;
+
+ REG_TOPO_ASSERT();
+
+ REGNODE_XLOCK(regnode);
+
+ rv = REGNODE_SET_VOLTAGE(regnode, min_uvolt, max_uvolt, &udelay);
+ if (rv == 0)
+ regnode_delay(udelay);
+ REGNODE_UNLOCK(regnode);
+ return (rv);
+}
+
+/*
+ * Consumer variant of regnode_set_voltage().
+ */
+static int
+regnode_set_voltage_checked(struct regnode *regnode, struct regulator *reg,
+ int min_uvolt, int max_uvolt)
+{
+ int udelay;
+ int all_max_uvolt;
+ int all_min_uvolt;
+ struct regulator *tmp;
+ int rv;
+
+ REG_TOPO_ASSERT();
+
+ REGNODE_XLOCK(regnode);
+ /* Return error if requested range is outside of regulator range. */
+ if ((min_uvolt > regnode->std_param.max_uvolt) ||
+ (max_uvolt < regnode->std_param.min_uvolt)) {
+ REGNODE_UNLOCK(regnode);
+ return (ERANGE);
+ }
+
+ /* Get actual voltage range for all consumers. */
+ all_min_uvolt = regnode->std_param.min_uvolt;
+ all_max_uvolt = regnode->std_param.max_uvolt;
+ TAILQ_FOREACH(tmp, &regnode->consumers_list, link) {
+ /* Don't take requestor in account. */
+ if (tmp == reg)
+ continue;
+ if (all_min_uvolt < tmp->min_uvolt)
+ all_min_uvolt = tmp->min_uvolt;
+ if (all_max_uvolt > tmp->max_uvolt)
+ all_max_uvolt = tmp->max_uvolt;
+ }
+
+ /* Test if request fits to actual contract. */
+ if ((min_uvolt > all_max_uvolt) ||
+ (max_uvolt < all_min_uvolt)) {
+ REGNODE_UNLOCK(regnode);
+ return (ERANGE);
+ }
+
+ /* Adjust new range.*/
+ if (min_uvolt < all_min_uvolt)
+ min_uvolt = all_min_uvolt;
+ if (max_uvolt > all_max_uvolt)
+ max_uvolt = all_max_uvolt;
+
+ rv = REGNODE_SET_VOLTAGE(regnode, min_uvolt, max_uvolt, &udelay);
+ regnode_delay(udelay);
+ REGNODE_UNLOCK(regnode);
+ return (rv);
+}
+
+#ifdef FDT
+phandle_t
+regnode_get_ofw_node(struct regnode *regnode)
+{
+
+ return (regnode->ofw_node);
+}
+#endif
+
+/* --------------------------------------------------------------------------
+ *
+ * Regulator consumers interface.
+ *
+ */
+/* Helper function for regulator_get*() */
+static regulator_t
+regulator_create(struct regnode *regnode, device_t cdev)
+{
+ struct regulator *reg;
+
+ REG_TOPO_ASSERT();
+
+ reg = malloc(sizeof(struct regulator), M_REGULATOR,
+ M_WAITOK | M_ZERO);
+ reg->cdev = cdev;
+ reg->regnode = regnode;
+ reg->enable_cnt = 0;
+
+ REGNODE_XLOCK(regnode);
+ regnode->ref_cnt++;
+ TAILQ_INSERT_TAIL(&regnode->consumers_list, reg, link);
+ reg ->min_uvolt = regnode->std_param.min_uvolt;
+ reg ->max_uvolt = regnode->std_param.max_uvolt;
+ REGNODE_UNLOCK(regnode);
+
+ return (reg);
+}
+
+int
+regulator_enable(regulator_t reg)
+{
+ int rv;
+ struct regnode *regnode;
+
+ regnode = reg->regnode;
+ KASSERT(regnode->ref_cnt > 0,
+ ("Attempt to access unreferenced regulator: %s\n", regnode->name));
+ REG_TOPO_SLOCK();
+ rv = regnode_enable(regnode);
+ if (rv == 0)
+ reg->enable_cnt++;
+ REG_TOPO_UNLOCK();
+ return (rv);
+}
+
+int
+regulator_disable(regulator_t reg)
+{
+ int rv;
+ struct regnode *regnode;
+
+ regnode = reg->regnode;
+ KASSERT(regnode->ref_cnt > 0,
+ ("Attempt to access unreferenced regulator: %s\n", regnode->name));
+ KASSERT(reg->enable_cnt > 0,
+ ("Attempt to disable already disabled regulator: %s\n",
+ regnode->name));
+ REG_TOPO_SLOCK();
+ rv = regnode_disable(regnode);
+ if (rv == 0)
+ reg->enable_cnt--;
+ REG_TOPO_UNLOCK();
+ return (rv);
+}
+
+int
+regulator_stop(regulator_t reg)
+{
+ int rv;
+ struct regnode *regnode;
+
+ regnode = reg->regnode;
+ KASSERT(regnode->ref_cnt > 0,
+ ("Attempt to access unreferenced regulator: %s\n", regnode->name));
+ KASSERT(reg->enable_cnt == 0,
+ ("Attempt to stop already enabled regulator: %s\n", regnode->name));
+
+ REG_TOPO_SLOCK();
+ rv = regnode_stop(regnode, 0);
+ REG_TOPO_UNLOCK();
+ return (rv);
+}
+
+int
+regulator_status(regulator_t reg, int *status)
+{
+ int rv;
+ struct regnode *regnode;
+
+ regnode = reg->regnode;
+ KASSERT(regnode->ref_cnt > 0,
+ ("Attempt to access unreferenced regulator: %s\n", regnode->name));
+
+ REG_TOPO_SLOCK();
+ rv = regnode_status(regnode, status);
+ REG_TOPO_UNLOCK();
+ return (rv);
+}
+
+int
+regulator_get_voltage(regulator_t reg, int *uvolt)
+{
+ int rv;
+ struct regnode *regnode;
+
+ regnode = reg->regnode;
+ KASSERT(regnode->ref_cnt > 0,
+ ("Attempt to access unreferenced regulator: %s\n", regnode->name));
+
+ REG_TOPO_SLOCK();
+ rv = regnode_get_voltage(regnode, uvolt);
+ REG_TOPO_UNLOCK();
+ return (rv);
+}
+
+int
+regulator_set_voltage(regulator_t reg, int min_uvolt, int max_uvolt)
+{
+ struct regnode *regnode;
+ int rv;
+
+ regnode = reg->regnode;
+ KASSERT(regnode->ref_cnt > 0,
+ ("Attempt to access unreferenced regulator: %s\n", regnode->name));
+
+ REG_TOPO_SLOCK();
+
+ rv = regnode_set_voltage_checked(regnode, reg, min_uvolt, max_uvolt);
+ if (rv == 0) {
+ reg->min_uvolt = min_uvolt;
+ reg->max_uvolt = max_uvolt;
+ }
+ REG_TOPO_UNLOCK();
+ return (rv);
+}
+
+const char *
+regulator_get_name(regulator_t reg)
+{
+ struct regnode *regnode;
+
+ regnode = reg->regnode;
+ KASSERT(regnode->ref_cnt > 0,
+ ("Attempt to access unreferenced regulator: %s\n", regnode->name));
+ return (regnode->name);
+}
+
+int
+regulator_get_by_name(device_t cdev, const char *name, regulator_t *reg)
+{
+ struct regnode *regnode;
+
+ REG_TOPO_SLOCK();
+ regnode = regnode_find_by_name(name);
+ if (regnode == NULL) {
+ REG_TOPO_UNLOCK();
+ return (ENODEV);
+ }
+ *reg = regulator_create(regnode, cdev);
+ REG_TOPO_UNLOCK();
+ return (0);
+}
+
+int
+regulator_get_by_id(device_t cdev, device_t pdev, intptr_t id, regulator_t *reg)
+{
+ struct regnode *regnode;
+
+ REG_TOPO_SLOCK();
+
+ regnode = regnode_find_by_id(pdev, id);
+ if (regnode == NULL) {
+ REG_TOPO_UNLOCK();
+ return (ENODEV);
+ }
+ *reg = regulator_create(regnode, cdev);
+ REG_TOPO_UNLOCK();
+
+ return (0);
+}
+
+int
+regulator_release(regulator_t reg)
+{
+ struct regnode *regnode;
+
+ regnode = reg->regnode;
+ KASSERT(regnode->ref_cnt > 0,
+ ("Attempt to access unreferenced regulator: %s\n", regnode->name));
+ REG_TOPO_SLOCK();
+ while (reg->enable_cnt > 0) {
+ regnode_disable(regnode);
+ reg->enable_cnt--;
+ }
+ REGNODE_XLOCK(regnode);
+ TAILQ_REMOVE(&regnode->consumers_list, reg, link);
+ regnode->ref_cnt--;
+ REGNODE_UNLOCK(regnode);
+ REG_TOPO_UNLOCK();
+
+ free(reg, M_REGULATOR);
+ return (0);
+}
+
+#ifdef FDT
+/* Default DT mapper. */
+int
+regdev_default_ofw_map(device_t dev, phandle_t xref, int ncells,
+ pcell_t *cells, intptr_t *id)
+{
+ if (ncells == 0)
+ *id = 1;
+ else if (ncells == 1)
+ *id = cells[0];
+ else
+ return (ERANGE);
+
+ return (0);
+}
+
+int
+regulator_parse_ofw_stdparam(device_t pdev, phandle_t node,
+ struct regnode_init_def *def)
+{
+ phandle_t supply_xref;
+ struct regnode_std_param *par;
+ int rv;
+
+ par = &def->std_param;
+ rv = OF_getprop_alloc(node, "regulator-name", 1,
+ (void **)&def->name);
+ if (rv <= 0) {
+ device_printf(pdev, "%s: Missing regulator name\n",
+ __func__);
+ return (ENXIO);
+ }
+
+ rv = OF_getencprop(node, "regulator-min-microvolt", &par->min_uvolt,
+ sizeof(par->min_uvolt));
+ if (rv <= 0)
+ par->min_uvolt = 0;
+
+ rv = OF_getencprop(node, "regulator-max-microvolt", &par->max_uvolt,
+ sizeof(par->max_uvolt));
+ if (rv <= 0)
+ par->max_uvolt = 0;
+
+ rv = OF_getencprop(node, "regulator-min-microamp", &par->min_uamp,
+ sizeof(par->min_uamp));
+ if (rv <= 0)
+ par->min_uamp = 0;
+
+ rv = OF_getencprop(node, "regulator-max-microamp", &par->max_uamp,
+ sizeof(par->max_uamp));
+ if (rv <= 0)
+ par->max_uamp = 0;
+
+ rv = OF_getencprop(node, "regulator-ramp-delay", &par->ramp_delay,
+ sizeof(par->ramp_delay));
+ if (rv <= 0)
+ par->ramp_delay = 0;
+
+ rv = OF_getencprop(node, "regulator-enable-ramp-delay",
+ &par->enable_delay, sizeof(par->enable_delay));
+ if (rv <= 0)
+ par->enable_delay = 0;
+
+ if (OF_hasprop(node, "regulator-boot-on"))
+ par->boot_on = 1;
+
+ if (OF_hasprop(node, "regulator-always-on"))
+ par->always_on = 1;
+
+ if (OF_hasprop(node, "enable-active-high"))
+ par->enable_active_high = 1;
+
+ rv = OF_getencprop(node, "vin-supply", &supply_xref,
+ sizeof(supply_xref));
+ if (rv >= 0) {
+ rv = OF_getprop_alloc(supply_xref, "regulator-name", 1,
+ (void **)&def->parent_name);
+ if (rv <= 0)
+ def->parent_name = NULL;
+ }
+ return (0);
+}
+
+int
+regulator_get_by_ofw_property(device_t cdev, char *name, regulator_t *reg)
+{
+ phandle_t cnode, *cells;
+ device_t regdev;
+ int ncells, rv;
+ intptr_t id;
+
+ *reg = NULL;
+
+ cnode = ofw_bus_get_node(cdev);
+ if (cnode <= 0) {
+ device_printf(cdev, "%s called on not ofw based device\n",
+ __func__);
+ return (ENXIO);
+ }
+
+ cells = NULL;
+ ncells = OF_getencprop_alloc(cnode, name, sizeof(*cells),
+ (void **)&cells);
+ if (ncells <= 0)
+ return (ENXIO);
+
+ /* Translate xref to device */
+ regdev = OF_device_from_xref(cells[0]);
+ if (regdev == NULL) {
+ free(cells, M_OFWPROP);
+ return (ENODEV);
+ }
+
+ /* Map regulator to number */
+ rv = REGDEV_MAP(regdev, cells[0], ncells - 1, cells + 1, &id);
+ free(cells, M_OFWPROP);
+ if (rv != 0)
+ return (rv);
+ return (regulator_get_by_id(cdev, regdev, id, reg));
+}
+#endif
diff --git a/sys/dev/extres/regulator/regulator.h b/sys/dev/extres/regulator/regulator.h
new file mode 100644
index 0000000..380bad6
--- /dev/null
+++ b/sys/dev/extres/regulator/regulator.h
@@ -0,0 +1,127 @@
+/*-
+ * Copyright 2016 Michal Meloun <mmel@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _DEV_EXTRES_REGULATOR_H_
+#define _DEV_EXTRES_REGULATOR_H_
+#include "opt_platform.h"
+
+#include <sys/kobj.h>
+#ifdef FDT
+#include <dev/ofw/ofw_bus.h>
+#endif
+#include "regnode_if.h"
+
+#define REGULATOR_FLAGS_STATIC 0x00000001 /* Static strings */
+#define REGULATOR_FLAGS_NOT_DISABLE 0x00000002 /* Cannot be disabled */
+
+#define REGULATOR_STATUS_ENABLED 0x00000001
+#define REGULATOR_STATUS_OVERCURRENT 0x00000002
+
+typedef struct regulator *regulator_t;
+
+/* Standard regulator parameters. */
+struct regnode_std_param {
+ int min_uvolt; /* In uV */
+ int max_uvolt; /* In uV */
+ int min_uamp; /* In uA */
+ int max_uamp; /* In uA */
+ int ramp_delay; /* In uV/usec */
+ int enable_delay; /* In usec */
+ bool boot_on; /* Is enabled on boot */
+ bool always_on; /* Must be enabled */
+ int enable_active_high;
+};
+
+/* Initialization parameters. */
+struct regnode_init_def {
+ char *name; /* Regulator name */
+ char *parent_name; /* Name of parent regulator */
+ struct regnode_std_param std_param; /* Standard parameters */
+ intptr_t id; /* Regulator ID */
+ int flags; /* Flags */
+#ifdef FDT
+ phandle_t ofw_node; /* OFW node of regulator */
+#endif
+
+};
+
+/*
+ * Shorthands for constructing method tables.
+ */
+#define REGNODEMETHOD KOBJMETHOD
+#define REGNODEMETHOD_END KOBJMETHOD_END
+#define regnode_method_t kobj_method_t
+#define regnode_class_t kobj_class_t
+DECLARE_CLASS(regnode_class);
+
+/* Providers interface. */
+struct regnode *regnode_create(device_t pdev, regnode_class_t regnode_class,
+ struct regnode_init_def *def);
+struct regnode *regnode_register(struct regnode *regnode);
+const char *regnode_get_name(struct regnode *regnode);
+const char *regnode_get_parent_name(struct regnode *regnode);
+struct regnode *regnode_get_parent(struct regnode *regnode);
+int regnode_get_flags(struct regnode *regnode);
+void *regnode_get_softc(struct regnode *regnode);
+device_t regnode_get_device(struct regnode *regnode);
+struct regnode_std_param *regnode_get_stdparam(struct regnode *regnode);
+void regnode_topo_unlock(void);
+void regnode_topo_xlock(void);
+void regnode_topo_slock(void);
+
+int regnode_enable(struct regnode *regnode);
+int regnode_disable(struct regnode *regnode);
+int regnode_stop(struct regnode *regnode, int depth);
+int regnode_status(struct regnode *regnode, int *status);
+int regnode_get_voltage(struct regnode *regnode, int *uvolt);
+int regnode_set_voltage(struct regnode *regnode, int min_uvolt, int max_uvolt);
+#ifdef FDT
+phandle_t regnode_get_ofw_node(struct regnode *regnode);
+#endif
+
+/* Consumers interface. */
+int regulator_get_by_name(device_t cdev, const char *name,
+ regulator_t *regulator);
+int regulator_get_by_id(device_t cdev, device_t pdev, intptr_t id,
+ regulator_t *regulator);
+int regulator_release(regulator_t regulator);
+const char *regulator_get_name(regulator_t regulator);
+int regulator_enable(regulator_t reg);
+int regulator_disable(regulator_t reg);
+int regulator_stop(regulator_t reg);
+int regulator_status(regulator_t reg, int *status);
+int regulator_get_voltage(regulator_t reg, int *uvolt);
+int regulator_set_voltage(regulator_t reg, int min_uvolt, int max_uvolt);
+
+#ifdef FDT
+int regulator_get_by_ofw_property(device_t dev, char *name, regulator_t *reg);
+int regulator_parse_ofw_stdparam(device_t dev, phandle_t node,
+ struct regnode_init_def *def);
+#endif
+
+#endif /* _DEV_EXTRES_REGULATOR_H_ */
diff --git a/sys/dev/extres/regulator/regulator_bus.c b/sys/dev/extres/regulator/regulator_bus.c
new file mode 100644
index 0000000..5e7f4c9
--- /dev/null
+++ b/sys/dev/extres/regulator/regulator_bus.c
@@ -0,0 +1,89 @@
+/*-
+ * Copyright 2016 Michal Meloun <mmel@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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+
+#include <dev/fdt/simplebus.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+struct ofw_regulator_bus_softc {
+ struct simplebus_softc simplebus_sc;
+};
+
+static int
+ofw_regulator_bus_probe(device_t dev)
+{
+ const char *name;
+
+ name = ofw_bus_get_name(dev);
+ if (name == NULL || strcmp(name, "regulators") != 0)
+ return (ENXIO);
+ device_set_desc(dev, "OFW regulators bus");
+
+ return (0);
+}
+
+static int
+ofw_regulator_bus_attach(device_t dev)
+{
+ struct ofw_regulator_bus_softc *sc;
+ phandle_t node, child;
+
+ sc = device_get_softc(dev);
+ node = ofw_bus_get_node(dev);
+ simplebus_init(dev, node);
+
+ for (child = OF_child(node); child > 0; child = OF_peer(child)) {
+ simplebus_add_device(dev, child, 0, NULL, -1, NULL);
+ }
+
+ return (bus_generic_attach(dev));
+}
+
+static device_method_t ofw_regulator_bus_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ofw_regulator_bus_probe),
+ DEVMETHOD(device_attach, ofw_regulator_bus_attach),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_1(ofw_regulator_bus, ofw_regulator_bus_driver,
+ ofw_regulator_bus_methods, sizeof(struct ofw_regulator_bus_softc),
+ simplebus_driver);
+static devclass_t ofw_regulator_bus_devclass;
+EARLY_DRIVER_MODULE(ofw_regulator_bus, simplebus, ofw_regulator_bus_driver,
+ ofw_regulator_bus_devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
+MODULE_VERSION(ofw_regulator_bus, 1);
diff --git a/sys/dev/extres/regulator/regulator_fixed.c b/sys/dev/extres/regulator/regulator_fixed.c
new file mode 100644
index 0000000..5a44a72
--- /dev/null
+++ b/sys/dev/extres/regulator/regulator_fixed.c
@@ -0,0 +1,456 @@
+/*-
+ * Copyright 2016 Michal Meloun <mmel@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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_platform.h"
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/gpio.h>
+#include <sys/kernel.h>
+#include <sys/kobj.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#endif
+#include <dev/gpio/gpiobusvar.h>
+#include <dev/extres/regulator/regulator_fixed.h>
+
+#include "regdev_if.h"
+
+MALLOC_DEFINE(M_FIXEDREGULATOR, "fixedregulator", "Fixed regulator");
+
+/* GPIO list for shared pins. */
+typedef TAILQ_HEAD(gpio_list, gpio_entry) gpio_list_t;
+struct gpio_entry {
+ TAILQ_ENTRY(gpio_entry) link;
+ struct gpiobus_pin gpio_pin;
+ int use_cnt;
+ int enable_cnt;
+};
+static gpio_list_t gpio_list = TAILQ_HEAD_INITIALIZER(gpio_list);
+static struct mtx gpio_list_mtx;
+MTX_SYSINIT(gpio_list_lock, &gpio_list_mtx, "Regulator GPIO lock", MTX_DEF);
+
+struct regnode_fixed_sc {
+ struct regnode_std_param *param;
+ bool gpio_open_drain;
+ struct gpio_entry *gpio_entry;
+};
+
+static int regnode_fixed_init(struct regnode *regnode);
+static int regnode_fixed_enable(struct regnode *regnode, bool enable,
+ int *udelay);
+static int regnode_fixed_status(struct regnode *regnode, int *status);
+
+static regnode_method_t regnode_fixed_methods[] = {
+ /* Regulator interface */
+ REGNODEMETHOD(regnode_init, regnode_fixed_init),
+ REGNODEMETHOD(regnode_enable, regnode_fixed_enable),
+ REGNODEMETHOD(regnode_status, regnode_fixed_status),
+ REGNODEMETHOD_END
+};
+DEFINE_CLASS_1(regnode_fixed, regnode_fixed_class, regnode_fixed_methods,
+ sizeof(struct regnode_fixed_sc), regnode_class);
+
+/*
+ * GPIO list functions.
+ * Two or more regulators can share single GPIO pins, so we must track all
+ * GPIOs in gpio_list.
+ * The GPIO pin is registerd and reseved for first consumer, all others share
+ * gpio_entry with it.
+ */
+static struct gpio_entry *
+regnode_get_gpio_entry(struct gpiobus_pin *gpio_pin)
+{
+ struct gpio_entry *entry, *tmp;
+ device_t busdev;
+ int rv;
+
+ busdev = GPIO_GET_BUS(gpio_pin->dev);
+ if (busdev == NULL)
+ return (NULL);
+ entry = malloc(sizeof(struct gpio_entry), M_FIXEDREGULATOR,
+ M_WAITOK | M_ZERO);
+
+ mtx_lock(&gpio_list_mtx);
+
+ TAILQ_FOREACH(tmp, &gpio_list, link) {
+ if (tmp->gpio_pin.dev == gpio_pin->dev &&
+ tmp->gpio_pin.pin == gpio_pin->pin) {
+ tmp->use_cnt++;
+ mtx_unlock(&gpio_list_mtx);
+ free(entry, M_FIXEDREGULATOR);
+ return (tmp);
+ }
+ }
+
+ /* Reserve pin. */
+ /* XXX Can we call gpiobus_map_pin() with gpio_list_mtx mutex held? */
+ rv = gpiobus_map_pin(busdev, gpio_pin->pin);
+ if (rv != 0) {
+ mtx_unlock(&gpio_list_mtx);
+ free(entry, M_FIXEDREGULATOR);
+ return (NULL);
+ }
+ /* Everything is OK, build new entry and insert it to list. */
+ entry->gpio_pin = *gpio_pin;
+ entry->use_cnt = 1;
+ TAILQ_INSERT_TAIL(&gpio_list, entry, link);
+
+ mtx_unlock(&gpio_list_mtx);
+ return (entry);
+}
+
+
+/*
+ * Regulator class implementation.
+ */
+static int
+regnode_fixed_init(struct regnode *regnode)
+{
+ device_t dev;
+ struct regnode_fixed_sc *sc;
+ struct gpiobus_pin *pin;
+ uint32_t flags;
+ bool enable;
+ int rv;
+
+ sc = regnode_get_softc(regnode);
+ dev = regnode_get_device(regnode);
+ sc->param = regnode_get_stdparam(regnode);
+ if (sc->gpio_entry == NULL)
+ return (0);
+ pin = &sc->gpio_entry->gpio_pin;
+
+ flags = GPIO_PIN_OUTPUT;
+ if (sc->gpio_open_drain)
+ flags |= GPIO_PIN_OPENDRAIN;
+ enable = sc->param->boot_on || sc->param->always_on;
+ if (!sc->param->enable_active_high)
+ enable = !enable;
+ rv = GPIO_PIN_SET(pin->dev, pin->pin, enable);
+ if (rv != 0) {
+ device_printf(dev, "Cannot set GPIO pin: %d\n", pin->pin);
+ return (rv);
+ }
+ rv = GPIO_PIN_SETFLAGS(pin->dev, pin->pin, flags);
+ if (rv != 0) {
+ device_printf(dev, "Cannot configure GPIO pin: %d\n", pin->pin);
+ return (rv);
+ }
+
+ return (0);
+}
+
+/*
+ * Enable/disable regulator.
+ * Take shared GPIO pins in account
+ */
+static int
+regnode_fixed_enable(struct regnode *regnode, bool enable, int *udelay)
+{
+ device_t dev;
+ struct regnode_fixed_sc *sc;
+ struct gpiobus_pin *pin;
+ int rv;
+
+ sc = regnode_get_softc(regnode);
+ dev = regnode_get_device(regnode);
+
+ *udelay = 0;
+ if (sc->param->always_on && !enable)
+ return (0);
+ if (sc->gpio_entry == NULL)
+ return (0);
+ pin = &sc->gpio_entry->gpio_pin;
+ if (enable) {
+ sc->gpio_entry->enable_cnt++;
+ if (sc->gpio_entry->enable_cnt > 1)
+ return (0);
+ } else {
+ KASSERT(sc->gpio_entry->enable_cnt > 0,
+ ("Invalid enable count"));
+ sc->gpio_entry->enable_cnt--;
+ if (sc->gpio_entry->enable_cnt >= 1)
+ return (0);
+ }
+ if (!sc->param->enable_active_high)
+ enable = !enable;
+ rv = GPIO_PIN_SET(pin->dev, pin->pin, enable);
+ if (rv != 0) {
+ device_printf(dev, "Cannot set GPIO pin: %d\n", pin->pin);
+ return (rv);
+ }
+ *udelay = sc->param->enable_delay;
+ return (0);
+}
+
+static int
+regnode_fixed_status(struct regnode *regnode, int *status)
+{
+ struct regnode_fixed_sc *sc;
+ struct gpiobus_pin *pin;
+ uint32_t val;
+ int rv;
+
+ sc = regnode_get_softc(regnode);
+
+ *status = 0;
+ if (sc->gpio_entry == NULL) {
+ *status = REGULATOR_STATUS_ENABLED;
+ return (0);
+ }
+ pin = &sc->gpio_entry->gpio_pin;
+
+ rv = GPIO_PIN_GET(pin->dev, pin->pin, &val);
+ if (rv == 0) {
+ if (!sc->param->enable_active_high ^ (val != 0))
+ *status = REGULATOR_STATUS_ENABLED;
+ }
+ return (rv);
+}
+
+int
+regnode_fixed_register(device_t dev, struct regnode_fixed_init_def *init_def)
+{
+ struct regnode *regnode;
+ struct regnode_fixed_sc *sc;
+
+ regnode = regnode_create(dev, &regnode_fixed_class,
+ &init_def->reg_init_def);
+ if (regnode == NULL) {
+ device_printf(dev, "Cannot create regulator.\n");
+ return(ENXIO);
+ }
+ sc = regnode_get_softc(regnode);
+ sc->gpio_open_drain = init_def->gpio_open_drain;
+ if (init_def->gpio_pin != NULL) {
+ sc->gpio_entry = regnode_get_gpio_entry(init_def->gpio_pin);
+ if (sc->gpio_entry == NULL)
+ return(ENXIO);
+ }
+ regnode = regnode_register(regnode);
+ if (regnode == NULL) {
+ device_printf(dev, "Cannot register regulator.\n");
+ return(ENXIO);
+ }
+ return (0);
+}
+
+/*
+ * OFW Driver implementation.
+ */
+#ifdef FDT
+
+struct regfix_softc
+{
+ device_t dev;
+ bool attach_done;
+ struct regnode_fixed_init_def init_def;
+ phandle_t gpio_prodxref;
+ pcell_t *gpio_cells;
+ int gpio_ncells;
+ struct gpiobus_pin gpio_pin;
+};
+
+static struct ofw_compat_data compat_data[] = {
+ {"regulator-fixed", 1},
+ {NULL, 0},
+};
+
+static int
+regfix_get_gpio(struct regfix_softc * sc)
+{
+ device_t busdev;
+ phandle_t node;
+
+ int rv;
+
+ if (sc->gpio_prodxref == 0)
+ return (0);
+
+ node = ofw_bus_get_node(sc->dev);
+
+ /* Test if controller exist. */
+ sc->gpio_pin.dev = OF_device_from_xref(sc->gpio_prodxref);
+ if (sc->gpio_pin.dev == NULL)
+ return (ENODEV);
+
+ /* Test if GPIO bus already exist. */
+ busdev = GPIO_GET_BUS(sc->gpio_pin.dev);
+ if (busdev == NULL)
+ return (ENODEV);
+
+ rv = gpio_map_gpios(sc->gpio_pin.dev, node,
+ OF_node_from_xref(sc->gpio_prodxref), sc->gpio_ncells,
+ sc->gpio_cells, &(sc->gpio_pin.pin), &(sc->gpio_pin.flags));
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot map the gpio property.\n");
+ return (ENXIO);
+ }
+ sc->init_def.gpio_pin = &sc->gpio_pin;
+ return (0);
+}
+
+static int
+regfix_parse_fdt(struct regfix_softc * sc)
+{
+ phandle_t node;
+ int rv;
+ struct regnode_init_def *init_def;
+
+ node = ofw_bus_get_node(sc->dev);
+ init_def = &sc->init_def.reg_init_def;
+
+ rv = regulator_parse_ofw_stdparam(sc->dev, node, init_def);
+ if (rv != 0) {
+ device_printf(sc->dev, "Cannot parse standard parameters.\n");
+ return(rv);
+ }
+
+ /* Fixed regulator uses 'startup-delay-us' property for enable_delay */
+ rv = OF_getencprop(node, "startup-delay-us",
+ &init_def->std_param.enable_delay,
+ sizeof(init_def->std_param.enable_delay));
+ if (rv <= 0)
+ init_def->std_param.enable_delay = 0;
+ /* GPIO pin */
+ if (OF_hasprop(node, "gpio-open-drain"))
+ sc->init_def.gpio_open_drain = true;
+
+ if (!OF_hasprop(node, "gpio"))
+ return (0);
+ rv = ofw_bus_parse_xref_list_alloc(node, "gpio", "#gpio-cells", 0,
+ &sc->gpio_prodxref, &sc->gpio_ncells, &sc->gpio_cells);
+ if (rv != 0) {
+ sc->gpio_prodxref = 0;
+ device_printf(sc->dev, "Malformed gpio property\n");
+ return (ENXIO);
+ }
+ return (0);
+}
+
+static void
+regfix_new_pass(device_t dev)
+{
+ struct regfix_softc * sc;
+ int rv;
+
+ sc = device_get_softc(dev);
+ bus_generic_new_pass(dev);
+
+ if (sc->attach_done)
+ return;
+
+ /* Try to get and configure GPIO. */
+ rv = regfix_get_gpio(sc);
+ if (rv != 0)
+ return;
+
+ /* Register regulator. */
+ regnode_fixed_register(sc->dev, &sc->init_def);
+ sc->attach_done = true;
+}
+
+static int
+regfix_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data)
+ return (ENXIO);
+
+ device_set_desc(dev, "Fixed Regulator");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+regfix_detach(device_t dev)
+{
+
+ /* This device is always present. */
+ return (EBUSY);
+}
+
+static int
+regfix_attach(device_t dev)
+{
+ struct regfix_softc * sc;
+ int rv;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ /* Parse FDT data. */
+ rv = regfix_parse_fdt(sc);
+ if (rv != 0)
+ return(ENXIO);
+
+ /* Fill reset of init. */
+ sc->init_def.reg_init_def.id = 1;
+ sc->init_def.reg_init_def.flags = REGULATOR_FLAGS_STATIC;
+
+ /* Try to get and configure GPIO. */
+ rv = regfix_get_gpio(sc);
+ if (rv != 0)
+ return (bus_generic_attach(dev));
+
+ /* Register regulator. */
+ regnode_fixed_register(sc->dev, &sc->init_def);
+ sc->attach_done = true;
+
+ return (bus_generic_attach(dev));
+}
+
+static device_method_t regfix_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, regfix_probe),
+ DEVMETHOD(device_attach, regfix_attach),
+ DEVMETHOD(device_detach, regfix_detach),
+ /* Bus interface */
+ DEVMETHOD(bus_new_pass, regfix_new_pass),
+ /* Regdev interface */
+ DEVMETHOD(regdev_map, regdev_default_ofw_map),
+
+ DEVMETHOD_END
+};
+
+static devclass_t regfix_devclass;
+DEFINE_CLASS_0(regfix, regfix_driver, regfix_methods,
+ sizeof(struct regfix_softc));
+EARLY_DRIVER_MODULE(regfix, simplebus, regfix_driver,
+ regfix_devclass, 0, 0, BUS_PASS_BUS);
+
+#endif /* FDT */
diff --git a/sys/compat/cloudabi64/cloudabi64_syscalldefs.h b/sys/dev/extres/regulator/regulator_fixed.h
index d57f5f4..5cc0751 100644
--- a/sys/compat/cloudabi64/cloudabi64_syscalldefs.h
+++ b/sys/dev/extres/regulator/regulator_fixed.h
@@ -1,5 +1,6 @@
/*-
- * Copyright (c) 2015 Nuxi, https://nuxi.nl/
+ * Copyright 2016 Michal Meloun <mmel@FreeBSD.org>
+ * All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -25,21 +26,19 @@
* $FreeBSD$
*/
-#ifndef _CLOUDABI64_SYSCALLDEFS_H_
-#define _CLOUDABI64_SYSCALLDEFS_H_
+#ifndef _DEV_EXTRES_REGULATOR_FIXED_H_
+#define _DEV_EXTRES_REGULATOR_FIXED_H_
-#include <sys/types.h>
+#include <dev/gpio/gpiobusvar.h>
+#include <dev/extres/regulator/regulator.h>
-#include <compat/cloudabi/cloudabi_syscalldefs.h>
+struct regnode_fixed_init_def {
+ struct regnode_init_def reg_init_def;
+ bool gpio_open_drain;
+ struct gpiobus_pin *gpio_pin;
+};
-typedef uint64_t cloudabi64_size_t;
-typedef uint64_t cloudabi64_uintptr_t;
+int regnode_fixed_register(device_t dev,
+ struct regnode_fixed_init_def *init_def);
-/* Import machine-dependent CloudABI definitions for 64-bit systems. */
-#define IDENT(ident) cloudabi64_##ident
-#define PTR(type) cloudabi64_uintptr_t
-#include <contrib/cloudabi/syscalldefs_md.h>
-#undef IDENT
-#undef PTR
-
-#endif
+#endif /*_DEV_EXTRES_REGULATOR_FIXED_H_*/
diff --git a/sys/dev/fdt/fdt_common.c b/sys/dev/fdt/fdt_common.c
index 6211aca..73f7ada 100644
--- a/sys/dev/fdt/fdt_common.c
+++ b/sys/dev/fdt/fdt_common.c
@@ -722,3 +722,16 @@ fdt_get_unit(device_t dev)
return (strtol(name,NULL,0));
}
+
+int
+fdt_get_chosen_bootargs(char *bootargs, size_t max_size)
+{
+ phandle_t chosen;
+
+ chosen = OF_finddevice("/chosen");
+ if (chosen == -1)
+ return (ENXIO);
+ if (OF_getprop(chosen, "bootargs", bootargs, max_size) == -1)
+ return (ENXIO);
+ return (0);
+} \ No newline at end of file
diff --git a/sys/dev/fdt/fdt_common.h b/sys/dev/fdt/fdt_common.h
index db27b43..17af344 100644
--- a/sys/dev/fdt/fdt_common.h
+++ b/sys/dev/fdt/fdt_common.h
@@ -100,5 +100,6 @@ int fdt_parent_addr_cells(phandle_t);
int fdt_reg_to_rl(phandle_t, struct resource_list *);
int fdt_pm(phandle_t);
int fdt_get_unit(device_t);
+int fdt_get_chosen_bootargs(char *bootargs, size_t max_size);
#endif /* _FDT_COMMON_H_ */
diff --git a/sys/dev/fdt/simplebus.c b/sys/dev/fdt/simplebus.c
index 36c278f..8d43a70 100644
--- a/sys/dev/fdt/simplebus.c
+++ b/sys/dev/fdt/simplebus.c
@@ -369,7 +369,7 @@ simplebus_alloc_resource(device_t bus, device_t child, int type, int *rid,
if (j == sc->nranges && sc->nranges != 0) {
if (bootverbose)
device_printf(bus, "Could not map resource "
- "%#lx-%#lx\n", start, end);
+ "%#jx-%#jx\n", start, end);
return (NULL);
}
@@ -387,8 +387,8 @@ simplebus_print_res(struct simplebus_devinfo *di)
if (di == NULL)
return (0);
rv = 0;
- rv += resource_list_print_type(&di->rl, "mem", SYS_RES_MEMORY, "%#lx");
- rv += resource_list_print_type(&di->rl, "irq", SYS_RES_IRQ, "%ld");
+ rv += resource_list_print_type(&di->rl, "mem", SYS_RES_MEMORY, "%#jx");
+ rv += resource_list_print_type(&di->rl, "irq", SYS_RES_IRQ, "%jd");
return (rv);
}
diff --git a/sys/dev/filemon/filemon.c b/sys/dev/filemon/filemon.c
index cd40c5a..10f27ad 100644
--- a/sys/dev/filemon/filemon.c
+++ b/sys/dev/filemon/filemon.c
@@ -1,7 +1,7 @@
/*-
* Copyright (c) 2011, David E. O'Brien.
* Copyright (c) 2009-2011, Juniper Networks, Inc.
- * Copyright (c) 2015, EMC Corp.
+ * Copyright (c) 2015-2016, EMC Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -46,7 +46,6 @@ __FBSDID("$FreeBSD$");
#include <sys/module.h>
#include <sys/poll.h>
#include <sys/proc.h>
-#include <sys/queue.h>
#include <sys/sx.h>
#include <sys/syscall.h>
#include <sys/sysent.h>
@@ -80,23 +79,112 @@ static struct cdevsw filemon_cdevsw = {
MALLOC_DECLARE(M_FILEMON);
MALLOC_DEFINE(M_FILEMON, "filemon", "File access monitor");
+/*
+ * The filemon->lock protects several things currently:
+ * - fname1/fname2/msgbufr are pre-allocated and used per syscall
+ * for logging and copyins rather than stack variables.
+ * - Serializing the filemon's log output.
+ * - Preventing inheritance or removal of the filemon into proc.p_filemon.
+ */
struct filemon {
- TAILQ_ENTRY(filemon) link; /* Link into the in-use list. */
- struct sx lock; /* Lock mutex for this filemon. */
+ struct sx lock; /* Lock for this filemon. */
struct file *fp; /* Output file pointer. */
- struct proc *p; /* The process being monitored. */
char fname1[MAXPATHLEN]; /* Temporary filename buffer. */
char fname2[MAXPATHLEN]; /* Temporary filename buffer. */
char msgbufr[1024]; /* Output message buffer. */
+ int error; /* Log write error, returned on close(2). */
+ u_int refcnt; /* Pointer reference count. */
+ u_int proccnt; /* Process count. */
};
-static TAILQ_HEAD(, filemon) filemons_inuse = TAILQ_HEAD_INITIALIZER(filemons_inuse);
-static TAILQ_HEAD(, filemon) filemons_free = TAILQ_HEAD_INITIALIZER(filemons_free);
-static struct sx access_lock;
-
static struct cdev *filemon_dev;
+static void filemon_output(struct filemon *filemon, char *msg, size_t len);
+
+static __inline struct filemon *
+filemon_acquire(struct filemon *filemon)
+{
+
+ if (filemon != NULL)
+ refcount_acquire(&filemon->refcnt);
+ return (filemon);
+}
+
+/*
+ * Release a reference and free on the last one.
+ */
+static void
+filemon_release(struct filemon *filemon)
+{
+
+ if (refcount_release(&filemon->refcnt) == 0)
+ return;
+ /*
+ * There are valid cases of releasing while locked, such as in
+ * filemon_untrack_processes, but none which are done where there
+ * is not at least 1 reference remaining.
+ */
+ sx_assert(&filemon->lock, SA_UNLOCKED);
+
+ sx_destroy(&filemon->lock);
+ free(filemon, M_FILEMON);
+}
+
+/*
+ * Acquire the proc's p_filemon reference and lock the filemon.
+ * The proc's p_filemon may not match this filemon on return.
+ */
+static struct filemon *
+filemon_proc_get(struct proc *p)
+{
+ struct filemon *filemon;
+
+ PROC_LOCK(p);
+ filemon = filemon_acquire(p->p_filemon);
+ PROC_UNLOCK(p);
+
+ if (filemon == NULL)
+ return (NULL);
+ /*
+ * The p->p_filemon may have changed by now. That case is handled
+ * by the exit and fork hooks and filemon_attach_proc specially.
+ */
+ sx_xlock(&filemon->lock);
+ return (filemon);
+}
+
+/* Remove and release the filemon on the given process. */
+static void
+filemon_proc_drop(struct proc *p)
+{
+ struct filemon *filemon;
+
+ KASSERT(p->p_filemon != NULL, ("%s: proc %p NULL p_filemon",
+ __func__, p));
+ sx_assert(&p->p_filemon->lock, SA_XLOCKED);
+ PROC_LOCK(p);
+ filemon = p->p_filemon;
+ p->p_filemon = NULL;
+ --filemon->proccnt;
+ PROC_UNLOCK(p);
+ /*
+ * This should not be the last reference yet. filemon_release()
+ * cannot be called with filemon locked, which the caller expects
+ * will stay locked.
+ */
+ KASSERT(filemon->refcnt > 1, ("%s: proc %p dropping filemon %p "
+ "with last reference", __func__, p, filemon));
+ filemon_release(filemon);
+}
+
+/* Unlock and release the filemon. */
+static __inline void
+filemon_drop(struct filemon *filemon)
+{
+
+ sx_xunlock(&filemon->lock);
+ filemon_release(filemon);
+}
-#include "filemon_lock.c"
#include "filemon_wrapper.c"
static void
@@ -115,35 +203,151 @@ filemon_comment(struct filemon *filemon)
filemon_output(filemon, filemon->msgbufr, len);
}
+/*
+ * Invalidate the passed filemon in all processes.
+ */
static void
-filemon_dtr(void *data)
+filemon_untrack_processes(struct filemon *filemon)
{
- struct filemon *filemon = data;
+ struct proc *p;
- if (filemon != NULL) {
- struct file *fp;
+ sx_assert(&filemon->lock, SA_XLOCKED);
- /* Follow same locking order as filemon_pid_check. */
- filemon_lock_write();
- sx_xlock(&filemon->lock);
+ /* Avoid allproc loop if there is no need. */
+ if (filemon->proccnt == 0)
+ return;
+
+ /*
+ * Processes in this list won't go away while here since
+ * filemon_event_process_exit() will lock on filemon->lock
+ * which we hold.
+ */
+ sx_slock(&allproc_lock);
+ FOREACH_PROC_IN_SYSTEM(p) {
+ /*
+ * No PROC_LOCK is needed to compare here since it is
+ * guaranteed to not change since we have its filemon
+ * locked. Everything that changes this p_filemon will
+ * be locked on it.
+ */
+ if (p->p_filemon == filemon)
+ filemon_proc_drop(p);
+ }
+ sx_sunlock(&allproc_lock);
+
+ /*
+ * It's possible some references were acquired but will be
+ * dropped shortly as they are restricted from being
+ * inherited. There is at least the reference in cdevpriv remaining.
+ */
+ KASSERT(filemon->refcnt > 0, ("%s: filemon %p should have "
+ "references still.", __func__, filemon));
+ KASSERT(filemon->proccnt == 0, ("%s: filemon %p should not have "
+ "attached procs still.", __func__, filemon));
+}
- /* Remove from the in-use list. */
- TAILQ_REMOVE(&filemons_inuse, filemon, link);
+/*
+ * Close out the log.
+ */
+static void
+filemon_close_log(struct filemon *filemon)
+{
+ struct file *fp;
+ struct timeval now;
+ size_t len;
- fp = filemon->fp;
- filemon->fp = NULL;
- filemon->p = NULL;
+ sx_assert(&filemon->lock, SA_XLOCKED);
+ if (filemon->fp == NULL)
+ return;
- /* Add to the free list. */
- TAILQ_INSERT_TAIL(&filemons_free, filemon, link);
+ getmicrotime(&now);
- /* Give up write access. */
- sx_xunlock(&filemon->lock);
- filemon_unlock_write();
+ len = snprintf(filemon->msgbufr,
+ sizeof(filemon->msgbufr),
+ "# Stop %ju.%06ju\n# Bye bye\n",
+ (uintmax_t)now.tv_sec, (uintmax_t)now.tv_usec);
+
+ filemon_output(filemon, filemon->msgbufr, len);
+ fp = filemon->fp;
+ filemon->fp = NULL;
+
+ sx_xunlock(&filemon->lock);
+ fdrop(fp, curthread);
+ sx_xlock(&filemon->lock);
+}
+
+/*
+ * The devfs file is being closed. Untrace all processes. It is possible
+ * filemon_close/close(2) was not called.
+ */
+static void
+filemon_dtr(void *data)
+{
+ struct filemon *filemon = data;
- if (fp != NULL)
- fdrop(fp, curthread);
+ if (filemon == NULL)
+ return;
+
+ sx_xlock(&filemon->lock);
+ /*
+ * Detach the filemon. It cannot be inherited after this.
+ */
+ filemon_untrack_processes(filemon);
+ filemon_close_log(filemon);
+ filemon_drop(filemon);
+}
+
+/* Attach the filemon to the process. */
+static int
+filemon_attach_proc(struct filemon *filemon, struct proc *p)
+{
+ struct filemon *filemon2;
+
+ sx_assert(&filemon->lock, SA_XLOCKED);
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+ KASSERT((p->p_flag & P_WEXIT) == 0,
+ ("%s: filemon %p attaching to exiting process %p",
+ __func__, filemon, p));
+
+ if (p->p_filemon == filemon)
+ return (0);
+ /*
+ * Don't allow truncating other process traces. It is
+ * not really intended to trace procs other than curproc
+ * anyhow.
+ */
+ if (p->p_filemon != NULL && p != curproc)
+ return (EBUSY);
+ /*
+ * Historic behavior of filemon has been to let a child initiate
+ * tracing on itself and cease existing tracing. Bmake
+ * .META + .MAKE relies on this. It is only relevant for attaching to
+ * curproc.
+ */
+ while (p->p_filemon != NULL) {
+ PROC_UNLOCK(p);
+ sx_xunlock(&filemon->lock);
+ while ((filemon2 = filemon_proc_get(p)) != NULL) {
+ /* It may have changed. */
+ if (p->p_filemon == filemon2)
+ filemon_proc_drop(p);
+ filemon_drop(filemon2);
+ }
+ sx_xlock(&filemon->lock);
+ PROC_LOCK(p);
+ /*
+ * It may have been attached to, though unlikely.
+ * Try again if needed.
+ */
}
+
+ KASSERT(p->p_filemon == NULL,
+ ("%s: proc %p didn't detach filemon %p", __func__, p,
+ p->p_filemon));
+ p->p_filemon = filemon_acquire(filemon);
+ ++filemon->proccnt;
+
+ return (0);
}
static int
@@ -178,10 +382,16 @@ filemon_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag __unused,
/* Set the monitored process ID. */
case FILEMON_SET_PID:
+ /* Invalidate any existing processes already set. */
+ filemon_untrack_processes(filemon);
+
error = pget(*((pid_t *)data), PGET_CANDEBUG | PGET_NOTWEXIT,
&p);
if (error == 0) {
- filemon->p = p;
+ KASSERT(p->p_filemon != filemon,
+ ("%s: proc %p didn't untrack filemon %p",
+ __func__, p, filemon));
+ error = filemon_attach_proc(filemon, p);
PROC_UNLOCK(p);
}
break;
@@ -199,49 +409,48 @@ static int
filemon_open(struct cdev *dev, int oflags __unused, int devtype __unused,
struct thread *td __unused)
{
+ int error;
struct filemon *filemon;
- /* Get exclusive write access. */
- filemon_lock_write();
-
- if ((filemon = TAILQ_FIRST(&filemons_free)) != NULL)
- TAILQ_REMOVE(&filemons_free, filemon, link);
-
- /* Give up write access. */
- filemon_unlock_write();
-
- if (filemon == NULL) {
- filemon = malloc(sizeof(struct filemon), M_FILEMON,
- M_WAITOK | M_ZERO);
- sx_init(&filemon->lock, "filemon");
- }
-
- devfs_set_cdevpriv(filemon, filemon_dtr);
-
- /* Get exclusive write access. */
- filemon_lock_write();
+ filemon = malloc(sizeof(*filemon), M_FILEMON,
+ M_WAITOK | M_ZERO);
+ sx_init(&filemon->lock, "filemon");
+ refcount_init(&filemon->refcnt, 1);
- /* Add to the in-use list. */
- TAILQ_INSERT_TAIL(&filemons_inuse, filemon, link);
+ error = devfs_set_cdevpriv(filemon, filemon_dtr);
+ if (error != 0)
+ filemon_release(filemon);
- /* Give up write access. */
- filemon_unlock_write();
-
- return (0);
+ return (error);
}
+/* Called on close of last devfs file handle, before filemon_dtr(). */
static int
filemon_close(struct cdev *dev __unused, int flag __unused, int fmt __unused,
struct thread *td __unused)
{
+ struct filemon *filemon;
+ int error;
- return (0);
+ if ((error = devfs_get_cdevpriv((void **) &filemon)) != 0)
+ return (error);
+
+ sx_xlock(&filemon->lock);
+ filemon_close_log(filemon);
+ error = filemon->error;
+ sx_xunlock(&filemon->lock);
+ /*
+ * Processes are still being traced but won't log anything
+ * now. After this call returns filemon_dtr() is called which
+ * will detach processes.
+ */
+
+ return (error);
}
static void
filemon_load(void *dummy __unused)
{
- sx_init(&access_lock, "filemons_inuse");
/* Install the syscall wrappers. */
filemon_wrapper_install();
@@ -253,38 +462,11 @@ filemon_load(void *dummy __unused)
static int
filemon_unload(void)
{
- struct filemon *filemon;
- int error = 0;
-
- /* Get exclusive write access. */
- filemon_lock_write();
-
- if (TAILQ_FIRST(&filemons_inuse) != NULL)
- error = EBUSY;
- else {
- destroy_dev(filemon_dev);
-
- /* Deinstall the syscall wrappers. */
- filemon_wrapper_deinstall();
- }
- /* Give up write access. */
- filemon_unlock_write();
+ destroy_dev(filemon_dev);
+ filemon_wrapper_deinstall();
- if (error == 0) {
- /* free() filemon structs free list. */
- filemon_lock_write();
- while ((filemon = TAILQ_FIRST(&filemons_free)) != NULL) {
- TAILQ_REMOVE(&filemons_free, filemon, link);
- sx_destroy(&filemon->lock);
- free(filemon, M_FILEMON);
- }
- filemon_unlock_write();
-
- sx_destroy(&access_lock);
- }
-
- return (error);
+ return (0);
}
static int
diff --git a/sys/dev/filemon/filemon_wrapper.c b/sys/dev/filemon/filemon_wrapper.c
index 6911dc5..87c9392 100644
--- a/sys/dev/filemon/filemon_wrapper.c
+++ b/sys/dev/filemon/filemon_wrapper.c
@@ -1,7 +1,7 @@
/*-
* Copyright (c) 2011, David E. O'Brien.
* Copyright (c) 2009-2011, Juniper Networks, Inc.
- * Copyright (c) 2015, EMC Corp.
+ * Copyright (c) 2015-2016, EMC Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,8 +29,9 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <sys/imgact.h>
#include <sys/eventhandler.h>
+#include <sys/filedesc.h>
+#include <sys/imgact.h>
#include <sys/sx.h>
#include <sys/vnode.h>
@@ -45,6 +46,7 @@ filemon_output(struct filemon *filemon, char *msg, size_t len)
{
struct uio auio;
struct iovec aiov;
+ int error;
if (filemon->fp == NULL)
return;
@@ -62,56 +64,33 @@ filemon_output(struct filemon *filemon, char *msg, size_t len)
if (filemon->fp->f_type == DTYPE_VNODE)
bwillwrite();
- fo_write(filemon->fp, &auio, curthread->td_ucred, 0, curthread);
-}
-
-static struct filemon *
-filemon_pid_check(struct proc *p)
-{
- struct filemon *filemon;
-
- filemon_lock_read();
- if (TAILQ_EMPTY(&filemons_inuse)) {
- filemon_unlock_read();
- return (NULL);
- }
- sx_slock(&proctree_lock);
- while (p->p_pid != 0) {
- TAILQ_FOREACH(filemon, &filemons_inuse, link) {
- if (p == filemon->p) {
- sx_sunlock(&proctree_lock);
- sx_xlock(&filemon->lock);
- filemon_unlock_read();
- return (filemon);
- }
- }
- p = proc_realparent(p);
- }
- sx_sunlock(&proctree_lock);
- filemon_unlock_read();
- return (NULL);
+ error = fo_write(filemon->fp, &auio, curthread->td_ucred, 0, curthread);
+ if (error != 0)
+ filemon->error = error;
}
static int
filemon_wrapper_chdir(struct thread *td, struct chdir_args *uap)
{
- int ret;
- size_t done;
+ int error, ret;
size_t len;
struct filemon *filemon;
if ((ret = sys_chdir(td, uap)) == 0) {
- if ((filemon = filemon_pid_check(curproc)) != NULL) {
- copyinstr(uap->path, filemon->fname1,
- sizeof(filemon->fname1), &done);
+ if ((filemon = filemon_proc_get(curproc)) != NULL) {
+ if ((error = copyinstr(uap->path, filemon->fname1,
+ sizeof(filemon->fname1), NULL)) != 0) {
+ filemon->error = error;
+ goto copyfail;
+ }
len = snprintf(filemon->msgbufr,
sizeof(filemon->msgbufr), "C %d %s\n",
curproc->p_pid, filemon->fname1);
filemon_output(filemon, filemon->msgbufr, len);
-
- sx_xunlock(&filemon->lock);
+copyfail:
+ filemon_drop(filemon);
}
}
@@ -126,12 +105,11 @@ filemon_event_process_exec(void *arg __unused, struct proc *p,
char *fullpath, *freepath;
size_t len;
- if ((filemon = filemon_pid_check(p)) != NULL) {
+ if ((filemon = filemon_proc_get(p)) != NULL) {
fullpath = "<unknown>";
freepath = NULL;
- vn_fullpath(FIRST_THREAD_IN_PROC(p), imgp->vp, &fullpath,
- &freepath);
+ vn_fullpath(curthread, imgp->vp, &fullpath, &freepath);
len = snprintf(filemon->msgbufr,
sizeof(filemon->msgbufr), "E %d %s\n",
@@ -139,321 +117,244 @@ filemon_event_process_exec(void *arg __unused, struct proc *p,
filemon_output(filemon, filemon->msgbufr, len);
- sx_xunlock(&filemon->lock);
+ filemon_drop(filemon);
free(freepath, M_TEMP);
}
}
-static int
-filemon_wrapper_open(struct thread *td, struct open_args *uap)
+static void
+_filemon_wrapper_openat(struct thread *td, char *upath, int flags, int fd)
{
- int ret;
- size_t done;
+ int error;
size_t len;
+ struct file *fp;
struct filemon *filemon;
+ char *atpath, *freepath;
+ cap_rights_t rights;
- if ((ret = sys_open(td, uap)) == 0) {
- if ((filemon = filemon_pid_check(curproc)) != NULL) {
- copyinstr(uap->path, filemon->fname1,
- sizeof(filemon->fname1), &done);
-
- if (uap->flags & O_RDWR) {
- /*
- * We'll get the W record below, but need
- * to also output an R to distingish from
- * O_WRONLY.
- */
- len = snprintf(filemon->msgbufr,
- sizeof(filemon->msgbufr), "R %d %s\n",
- curproc->p_pid, filemon->fname1);
- filemon_output(filemon, filemon->msgbufr, len);
- }
+ if ((filemon = filemon_proc_get(curproc)) != NULL) {
+ atpath = "";
+ freepath = NULL;
+ fp = NULL;
+ if ((error = copyinstr(upath, filemon->fname1,
+ sizeof(filemon->fname1), NULL)) != 0) {
+ filemon->error = error;
+ goto copyfail;
+ }
+ if (filemon->fname1[0] != '/' && fd != AT_FDCWD) {
+ /*
+ * rats - we cannot do too much about this.
+ * the trace should show a dir we read
+ * recently.. output an A record as a clue
+ * until we can do better.
+ * XXX: This may be able to come out with
+ * the namecache lookup now.
+ */
len = snprintf(filemon->msgbufr,
- sizeof(filemon->msgbufr), "%c %d %s\n",
- (uap->flags & O_ACCMODE) ? 'W':'R',
+ sizeof(filemon->msgbufr), "A %d %s\n",
curproc->p_pid, filemon->fname1);
filemon_output(filemon, filemon->msgbufr, len);
-
- sx_xunlock(&filemon->lock);
+ /*
+ * Try to resolve the path from the vnode using the
+ * namecache. It may be inaccurate, but better
+ * than nothing.
+ */
+ if (getvnode(td, fd,
+ cap_rights_init(&rights, CAP_LOOKUP), &fp) == 0) {
+ vn_fullpath(td, fp->f_vnode, &atpath,
+ &freepath);
+ }
+ }
+ if (flags & O_RDWR) {
+ /*
+ * We'll get the W record below, but need
+ * to also output an R to distinguish from
+ * O_WRONLY.
+ */
+ len = snprintf(filemon->msgbufr,
+ sizeof(filemon->msgbufr), "R %d %s%s%s\n",
+ curproc->p_pid, atpath,
+ atpath[0] != '\0' ? "/" : "", filemon->fname1);
+ filemon_output(filemon, filemon->msgbufr, len);
}
- }
- return (ret);
+ len = snprintf(filemon->msgbufr,
+ sizeof(filemon->msgbufr), "%c %d %s%s%s\n",
+ (flags & O_ACCMODE) ? 'W':'R',
+ curproc->p_pid, atpath,
+ atpath[0] != '\0' ? "/" : "", filemon->fname1);
+ filemon_output(filemon, filemon->msgbufr, len);
+copyfail:
+ filemon_drop(filemon);
+ if (fp != NULL)
+ fdrop(fp, td);
+ free(freepath, M_TEMP);
+ }
}
static int
-filemon_wrapper_openat(struct thread *td, struct openat_args *uap)
+filemon_wrapper_open(struct thread *td, struct open_args *uap)
{
int ret;
- size_t done;
- size_t len;
- struct filemon *filemon;
- if ((ret = sys_openat(td, uap)) == 0) {
- if ((filemon = filemon_pid_check(curproc)) != NULL) {
- copyinstr(uap->path, filemon->fname1,
- sizeof(filemon->fname1), &done);
-
- filemon->fname2[0] = '\0';
- if (filemon->fname1[0] != '/' && uap->fd != AT_FDCWD) {
- /*
- * rats - we cannot do too much about this.
- * the trace should show a dir we read
- * recently.. output an A record as a clue
- * until we can do better.
- */
- len = snprintf(filemon->msgbufr,
- sizeof(filemon->msgbufr), "A %d %s\n",
- curproc->p_pid, filemon->fname1);
- filemon_output(filemon, filemon->msgbufr, len);
- }
- if (uap->flag & O_RDWR) {
- /*
- * We'll get the W record below, but need
- * to also output an R to distingish from
- * O_WRONLY.
- */
- len = snprintf(filemon->msgbufr,
- sizeof(filemon->msgbufr), "R %d %s%s\n",
- curproc->p_pid, filemon->fname2, filemon->fname1);
- filemon_output(filemon, filemon->msgbufr, len);
- }
-
-
- len = snprintf(filemon->msgbufr,
- sizeof(filemon->msgbufr), "%c %d %s%s\n",
- (uap->flag & O_ACCMODE) ? 'W':'R',
- curproc->p_pid, filemon->fname2, filemon->fname1);
- filemon_output(filemon, filemon->msgbufr, len);
-
- sx_xunlock(&filemon->lock);
- }
- }
+ if ((ret = sys_open(td, uap)) == 0)
+ _filemon_wrapper_openat(td, uap->path, uap->flags, AT_FDCWD);
return (ret);
}
static int
-filemon_wrapper_rename(struct thread *td, struct rename_args *uap)
+filemon_wrapper_openat(struct thread *td, struct openat_args *uap)
{
int ret;
- size_t done;
- size_t len;
- struct filemon *filemon;
- if ((ret = sys_rename(td, uap)) == 0) {
- if ((filemon = filemon_pid_check(curproc)) != NULL) {
- copyinstr(uap->from, filemon->fname1,
- sizeof(filemon->fname1), &done);
- copyinstr(uap->to, filemon->fname2,
- sizeof(filemon->fname2), &done);
-
- len = snprintf(filemon->msgbufr,
- sizeof(filemon->msgbufr), "M %d '%s' '%s'\n",
- curproc->p_pid, filemon->fname1, filemon->fname2);
-
- filemon_output(filemon, filemon->msgbufr, len);
-
- sx_xunlock(&filemon->lock);
- }
- }
+ if ((ret = sys_openat(td, uap)) == 0)
+ _filemon_wrapper_openat(td, uap->path, uap->flag, uap->fd);
return (ret);
}
static int
-filemon_wrapper_link(struct thread *td, struct link_args *uap)
+filemon_wrapper_rename(struct thread *td, struct rename_args *uap)
{
- int ret;
- size_t done;
+ int error, ret;
size_t len;
struct filemon *filemon;
- if ((ret = sys_link(td, uap)) == 0) {
- if ((filemon = filemon_pid_check(curproc)) != NULL) {
- copyinstr(uap->path, filemon->fname1,
- sizeof(filemon->fname1), &done);
- copyinstr(uap->link, filemon->fname2,
- sizeof(filemon->fname2), &done);
+ if ((ret = sys_rename(td, uap)) == 0) {
+ if ((filemon = filemon_proc_get(curproc)) != NULL) {
+ if (((error = copyinstr(uap->from, filemon->fname1,
+ sizeof(filemon->fname1), NULL)) != 0) ||
+ ((error = copyinstr(uap->to, filemon->fname2,
+ sizeof(filemon->fname2), NULL)) != 0)) {
+ filemon->error = error;
+ goto copyfail;
+ }
len = snprintf(filemon->msgbufr,
- sizeof(filemon->msgbufr), "L %d '%s' '%s'\n",
+ sizeof(filemon->msgbufr), "M %d '%s' '%s'\n",
curproc->p_pid, filemon->fname1, filemon->fname2);
filemon_output(filemon, filemon->msgbufr, len);
-
- sx_xunlock(&filemon->lock);
+copyfail:
+ filemon_drop(filemon);
}
}
return (ret);
}
-static int
-filemon_wrapper_symlink(struct thread *td, struct symlink_args *uap)
+static void
+_filemon_wrapper_link(struct thread *td, char *upath1, char *upath2)
{
- int ret;
- size_t done;
- size_t len;
struct filemon *filemon;
+ size_t len;
+ int error;
+
+ if ((filemon = filemon_proc_get(curproc)) != NULL) {
+ if (((error = copyinstr(upath1, filemon->fname1,
+ sizeof(filemon->fname1), NULL)) != 0) ||
+ ((error = copyinstr(upath2, filemon->fname2,
+ sizeof(filemon->fname2), NULL)) != 0)) {
+ filemon->error = error;
+ goto copyfail;
+ }
- if ((ret = sys_symlink(td, uap)) == 0) {
- if ((filemon = filemon_pid_check(curproc)) != NULL) {
- copyinstr(uap->path, filemon->fname1,
- sizeof(filemon->fname1), &done);
- copyinstr(uap->link, filemon->fname2,
- sizeof(filemon->fname2), &done);
-
- len = snprintf(filemon->msgbufr,
- sizeof(filemon->msgbufr), "L %d '%s' '%s'\n",
- curproc->p_pid, filemon->fname1, filemon->fname2);
-
- filemon_output(filemon, filemon->msgbufr, len);
+ len = snprintf(filemon->msgbufr,
+ sizeof(filemon->msgbufr), "L %d '%s' '%s'\n",
+ curproc->p_pid, filemon->fname1, filemon->fname2);
- sx_xunlock(&filemon->lock);
- }
+ filemon_output(filemon, filemon->msgbufr, len);
+copyfail:
+ filemon_drop(filemon);
}
-
- return (ret);
}
static int
-filemon_wrapper_linkat(struct thread *td, struct linkat_args *uap)
+filemon_wrapper_link(struct thread *td, struct link_args *uap)
{
int ret;
- size_t done;
- size_t len;
- struct filemon *filemon;
-
- if ((ret = sys_linkat(td, uap)) == 0) {
- if ((filemon = filemon_pid_check(curproc)) != NULL) {
- copyinstr(uap->path1, filemon->fname1,
- sizeof(filemon->fname1), &done);
- copyinstr(uap->path2, filemon->fname2,
- sizeof(filemon->fname2), &done);
-
- len = snprintf(filemon->msgbufr,
- sizeof(filemon->msgbufr), "L %d '%s' '%s'\n",
- curproc->p_pid, filemon->fname1, filemon->fname2);
- filemon_output(filemon, filemon->msgbufr, len);
-
- sx_xunlock(&filemon->lock);
- }
- }
+ if ((ret = sys_link(td, uap)) == 0)
+ _filemon_wrapper_link(td, uap->path, uap->link);
return (ret);
}
static int
-filemon_wrapper_stat(struct thread *td, struct stat_args *uap)
+filemon_wrapper_symlink(struct thread *td, struct symlink_args *uap)
{
int ret;
- size_t done;
- size_t len;
- struct filemon *filemon;
- if ((ret = sys_stat(td, uap)) == 0) {
- if ((filemon = filemon_pid_check(curproc)) != NULL) {
- copyinstr(uap->path, filemon->fname1,
- sizeof(filemon->fname1), &done);
-
- len = snprintf(filemon->msgbufr,
- sizeof(filemon->msgbufr), "S %d %s\n",
- curproc->p_pid, filemon->fname1);
-
- filemon_output(filemon, filemon->msgbufr, len);
-
- sx_xunlock(&filemon->lock);
- }
- }
+ if ((ret = sys_symlink(td, uap)) == 0)
+ _filemon_wrapper_link(td, uap->path, uap->link);
return (ret);
}
-#if defined(COMPAT_IA32) || defined(COMPAT_FREEBSD32) || defined(COMPAT_ARCH32)
static int
-filemon_wrapper_freebsd32_stat(struct thread *td,
- struct freebsd32_stat_args *uap)
+filemon_wrapper_linkat(struct thread *td, struct linkat_args *uap)
{
int ret;
- size_t done;
- size_t len;
- struct filemon *filemon;
-
- if ((ret = freebsd32_stat(td, uap)) == 0) {
- if ((filemon = filemon_pid_check(curproc)) != NULL) {
- copyinstr(uap->path, filemon->fname1,
- sizeof(filemon->fname1), &done);
-
- len = snprintf(filemon->msgbufr,
- sizeof(filemon->msgbufr), "S %d %s\n",
- curproc->p_pid, filemon->fname1);
-
- filemon_output(filemon, filemon->msgbufr, len);
- sx_xunlock(&filemon->lock);
- }
- }
+ if ((ret = sys_linkat(td, uap)) == 0)
+ _filemon_wrapper_link(td, uap->path1, uap->path2);
return (ret);
}
-#endif
static void
filemon_event_process_exit(void *arg __unused, struct proc *p)
{
size_t len;
struct filemon *filemon;
- struct timeval now;
- /* Get timestamp before locking. */
- getmicrotime(&now);
-
- if ((filemon = filemon_pid_check(p)) != NULL) {
+ if ((filemon = filemon_proc_get(p)) != NULL) {
len = snprintf(filemon->msgbufr, sizeof(filemon->msgbufr),
"X %d %d %d\n", p->p_pid, p->p_xexit, p->p_xsig);
filemon_output(filemon, filemon->msgbufr, len);
- /* Check if the monitored process is about to exit. */
- if (filemon->p == p) {
- len = snprintf(filemon->msgbufr,
- sizeof(filemon->msgbufr),
- "# Stop %ju.%06ju\n# Bye bye\n",
- (uintmax_t)now.tv_sec, (uintmax_t)now.tv_usec);
-
- filemon_output(filemon, filemon->msgbufr, len);
- filemon->p = NULL;
- }
-
- sx_xunlock(&filemon->lock);
+ /*
+ * filemon_untrack_processes() may have dropped this p_filemon
+ * already while in filemon_proc_get() before acquiring the
+ * filemon lock.
+ */
+ KASSERT(p->p_filemon == NULL || p->p_filemon == filemon,
+ ("%s: p %p was attached while exiting, expected "
+ "filemon %p or NULL", __func__, p, filemon));
+ if (p->p_filemon == filemon)
+ filemon_proc_drop(p);
+
+ filemon_drop(filemon);
}
}
static int
filemon_wrapper_unlink(struct thread *td, struct unlink_args *uap)
{
- int ret;
- size_t done;
+ int error, ret;
size_t len;
struct filemon *filemon;
if ((ret = sys_unlink(td, uap)) == 0) {
- if ((filemon = filemon_pid_check(curproc)) != NULL) {
- copyinstr(uap->path, filemon->fname1,
- sizeof(filemon->fname1), &done);
+ if ((filemon = filemon_proc_get(curproc)) != NULL) {
+ if ((error = copyinstr(uap->path, filemon->fname1,
+ sizeof(filemon->fname1), NULL)) != 0) {
+ filemon->error = error;
+ goto copyfail;
+ }
len = snprintf(filemon->msgbufr,
sizeof(filemon->msgbufr), "D %d %s\n",
curproc->p_pid, filemon->fname1);
filemon_output(filemon, filemon->msgbufr, len);
-
- sx_xunlock(&filemon->lock);
+copyfail:
+ filemon_drop(filemon);
}
}
@@ -467,14 +368,34 @@ filemon_event_process_fork(void *arg __unused, struct proc *p1,
size_t len;
struct filemon *filemon;
- if ((filemon = filemon_pid_check(p1)) != NULL) {
+ if ((filemon = filemon_proc_get(p1)) != NULL) {
len = snprintf(filemon->msgbufr,
sizeof(filemon->msgbufr), "F %d %d\n",
p1->p_pid, p2->p_pid);
filemon_output(filemon, filemon->msgbufr, len);
- sx_xunlock(&filemon->lock);
+ /*
+ * filemon_untrack_processes() or
+ * filemon_ioctl(FILEMON_SET_PID) may have changed the parent's
+ * p_filemon while in filemon_proc_get() before acquiring the
+ * filemon lock. Only inherit if the parent is still traced by
+ * this filemon.
+ */
+ if (p1->p_filemon == filemon) {
+ PROC_LOCK(p2);
+ /*
+ * It may have been attached to already by a new
+ * filemon.
+ */
+ if (p2->p_filemon == NULL) {
+ p2->p_filemon = filemon_acquire(filemon);
+ ++filemon->proccnt;
+ }
+ PROC_UNLOCK(p2);
+ }
+
+ filemon_drop(filemon);
}
}
@@ -491,7 +412,6 @@ filemon_wrapper_install(void)
sv_table[SYS_open].sy_call = (sy_call_t *) filemon_wrapper_open;
sv_table[SYS_openat].sy_call = (sy_call_t *) filemon_wrapper_openat;
sv_table[SYS_rename].sy_call = (sy_call_t *) filemon_wrapper_rename;
- sv_table[SYS_stat].sy_call = (sy_call_t *) filemon_wrapper_stat;
sv_table[SYS_unlink].sy_call = (sy_call_t *) filemon_wrapper_unlink;
sv_table[SYS_link].sy_call = (sy_call_t *) filemon_wrapper_link;
sv_table[SYS_symlink].sy_call = (sy_call_t *) filemon_wrapper_symlink;
@@ -504,7 +424,6 @@ filemon_wrapper_install(void)
sv_table[FREEBSD32_SYS_open].sy_call = (sy_call_t *) filemon_wrapper_open;
sv_table[FREEBSD32_SYS_openat].sy_call = (sy_call_t *) filemon_wrapper_openat;
sv_table[FREEBSD32_SYS_rename].sy_call = (sy_call_t *) filemon_wrapper_rename;
- sv_table[FREEBSD32_SYS_freebsd32_stat].sy_call = (sy_call_t *) filemon_wrapper_freebsd32_stat;
sv_table[FREEBSD32_SYS_unlink].sy_call = (sy_call_t *) filemon_wrapper_unlink;
sv_table[FREEBSD32_SYS_link].sy_call = (sy_call_t *) filemon_wrapper_link;
sv_table[FREEBSD32_SYS_symlink].sy_call = (sy_call_t *) filemon_wrapper_symlink;
@@ -532,7 +451,6 @@ filemon_wrapper_deinstall(void)
sv_table[SYS_open].sy_call = (sy_call_t *)sys_open;
sv_table[SYS_openat].sy_call = (sy_call_t *)sys_openat;
sv_table[SYS_rename].sy_call = (sy_call_t *)sys_rename;
- sv_table[SYS_stat].sy_call = (sy_call_t *)sys_stat;
sv_table[SYS_unlink].sy_call = (sy_call_t *)sys_unlink;
sv_table[SYS_link].sy_call = (sy_call_t *)sys_link;
sv_table[SYS_symlink].sy_call = (sy_call_t *)sys_symlink;
@@ -545,7 +463,6 @@ filemon_wrapper_deinstall(void)
sv_table[FREEBSD32_SYS_open].sy_call = (sy_call_t *)sys_open;
sv_table[FREEBSD32_SYS_openat].sy_call = (sy_call_t *)sys_openat;
sv_table[FREEBSD32_SYS_rename].sy_call = (sy_call_t *)sys_rename;
- sv_table[FREEBSD32_SYS_freebsd32_stat].sy_call = (sy_call_t *)freebsd32_stat;
sv_table[FREEBSD32_SYS_unlink].sy_call = (sy_call_t *)sys_unlink;
sv_table[FREEBSD32_SYS_link].sy_call = (sy_call_t *)sys_link;
sv_table[FREEBSD32_SYS_symlink].sy_call = (sy_call_t *)sys_symlink;
diff --git a/sys/dev/flash/mx25l.c b/sys/dev/flash/mx25l.c
index c4dad4b..6b71340 100644
--- a/sys/dev/flash/mx25l.c
+++ b/sys/dev/flash/mx25l.c
@@ -26,6 +26,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_platform.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bio.h>
@@ -40,6 +42,12 @@ __FBSDID("$FreeBSD$");
#include <sys/mutex.h>
#include <geom/geom_disk.h>
+#ifdef FDT
+#include <dev/fdt/fdt_common.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/openfirm.h>
+#endif
+
#include <dev/spibus/spi.h>
#include "spibus_if.h"
@@ -48,6 +56,8 @@ __FBSDID("$FreeBSD$");
#define FL_NONE 0x00
#define FL_ERASE_4K 0x01
#define FL_ERASE_32K 0x02
+#define FL_ENABLE_4B_ADDR 0x04
+#define FL_DISABLE_4B_ADDR 0x08
/*
* Define the sectorsize to be a smaller size rather than the flash
@@ -105,6 +115,7 @@ struct mx25l_flash_ident flash_devices[] = {
{ "mx25ll32", 0xc2, 0x2016, 64 * 1024, 64, FL_NONE },
{ "mx25ll64", 0xc2, 0x2017, 64 * 1024, 128, FL_NONE },
{ "mx25ll128", 0xc2, 0x2018, 64 * 1024, 256, FL_ERASE_4K | FL_ERASE_32K },
+ { "mx25ll256", 0xc2, 0x2019, 64 * 1024, 512, FL_ERASE_4K | FL_ERASE_32K | FL_ENABLE_4B_ADDR },
{ "s25fl032", 0x01, 0x0215, 64 * 1024, 64, FL_NONE },
{ "s25fl064", 0x01, 0x0216, 64 * 1024, 128, FL_NONE },
{ "s25fl128", 0x01, 0x2018, 64 * 1024, 256, FL_NONE },
@@ -211,10 +222,13 @@ mx25l_set_writable(device_t dev, int writable)
static void
mx25l_erase_cmd(device_t dev, off_t sector, uint8_t ecmd)
{
- uint8_t txBuf[4], rxBuf[4];
+ struct mx25l_softc *sc;
+ uint8_t txBuf[5], rxBuf[5];
struct spi_command cmd;
int err;
+ sc = device_get_softc(dev);
+
mx25l_wait_for_device_ready(dev);
mx25l_set_writable(dev, 1);
@@ -225,11 +239,20 @@ mx25l_erase_cmd(device_t dev, off_t sector, uint8_t ecmd)
txBuf[0] = ecmd;
cmd.tx_cmd = txBuf;
cmd.rx_cmd = rxBuf;
- cmd.rx_cmd_sz = 4;
- cmd.tx_cmd_sz = 4;
- txBuf[1] = ((sector >> 16) & 0xff);
- txBuf[2] = ((sector >> 8) & 0xff);
- txBuf[3] = (sector & 0xff);
+ if (sc->sc_flags & FL_ENABLE_4B_ADDR) {
+ cmd.rx_cmd_sz = 5;
+ cmd.tx_cmd_sz = 5;
+ txBuf[1] = ((sector >> 24) & 0xff);
+ txBuf[2] = ((sector >> 16) & 0xff);
+ txBuf[3] = ((sector >> 8) & 0xff);
+ txBuf[4] = (sector & 0xff);
+ } else {
+ cmd.rx_cmd_sz = 4;
+ cmd.tx_cmd_sz = 4;
+ txBuf[1] = ((sector >> 16) & 0xff);
+ txBuf[2] = ((sector >> 8) & 0xff);
+ txBuf[3] = (sector & 0xff);
+ }
err = SPIBUS_TRANSFER(device_get_parent(dev), dev, &cmd);
}
@@ -247,8 +270,13 @@ mx25l_write(device_t dev, off_t offset, caddr_t data, off_t count)
pdev = device_get_parent(dev);
sc = device_get_softc(dev);
- cmd.tx_cmd_sz = 4;
- cmd.rx_cmd_sz = 4;
+ if (sc->sc_flags & FL_ENABLE_4B_ADDR) {
+ cmd.tx_cmd_sz = 5;
+ cmd.rx_cmd_sz = 5;
+ } else {
+ cmd.tx_cmd_sz = 4;
+ cmd.rx_cmd_sz = 4;
+ }
bytes_writen = 0;
write_offset = offset;
@@ -282,9 +310,16 @@ mx25l_write(device_t dev, off_t offset, caddr_t data, off_t count)
mx25l_erase_cmd(dev, offset + bytes_writen, CMD_SECTOR_ERASE);
txBuf[0] = CMD_PAGE_PROGRAM;
- txBuf[1] = ((write_offset >> 16) & 0xff);
- txBuf[2] = ((write_offset >> 8) & 0xff);
- txBuf[3] = (write_offset & 0xff);
+ if (sc->sc_flags & FL_ENABLE_4B_ADDR) {
+ txBuf[1] = ((write_offset >> 24) & 0xff);
+ txBuf[2] = ((write_offset >> 16) & 0xff);
+ txBuf[3] = ((write_offset >> 8) & 0xff);
+ txBuf[4] = (write_offset & 0xff);
+ } else {
+ txBuf[1] = ((write_offset >> 16) & 0xff);
+ txBuf[2] = ((write_offset >> 8) & 0xff);
+ txBuf[3] = (write_offset & 0xff);
+ }
bytes_to_write = MIN(FLASH_PAGE_SIZE,
count - bytes_writen);
@@ -336,14 +371,26 @@ mx25l_read(device_t dev, off_t offset, caddr_t data, off_t count)
return (EIO);
txBuf[0] = CMD_FAST_READ;
- cmd.tx_cmd_sz = 5;
- cmd.rx_cmd_sz = 5;
-
- txBuf[1] = ((offset >> 16) & 0xff);
- txBuf[2] = ((offset >> 8) & 0xff);
- txBuf[3] = (offset & 0xff);
- /* Dummy byte */
- txBuf[4] = 0;
+ if (sc->sc_flags & FL_ENABLE_4B_ADDR) {
+ cmd.tx_cmd_sz = 6;
+ cmd.rx_cmd_sz = 6;
+
+ txBuf[1] = ((offset >> 24) & 0xff);
+ txBuf[2] = ((offset >> 16) & 0xff);
+ txBuf[3] = ((offset >> 8) & 0xff);
+ txBuf[4] = (offset & 0xff);
+ /* Dummy byte */
+ txBuf[5] = 0;
+ } else {
+ cmd.tx_cmd_sz = 5;
+ cmd.rx_cmd_sz = 5;
+
+ txBuf[1] = ((offset >> 16) & 0xff);
+ txBuf[2] = ((offset >> 8) & 0xff);
+ txBuf[3] = (offset & 0xff);
+ /* Dummy byte */
+ txBuf[4] = 0;
+ }
cmd.tx_cmd = txBuf;
cmd.rx_cmd = rxBuf;
@@ -358,9 +405,45 @@ mx25l_read(device_t dev, off_t offset, caddr_t data, off_t count)
}
static int
+mx25l_set_4b_mode(device_t dev, uint8_t command)
+{
+ uint8_t txBuf[1], rxBuf[1];
+ struct spi_command cmd;
+ device_t pdev;
+ int err;
+
+ memset(&cmd, 0, sizeof(cmd));
+ memset(txBuf, 0, sizeof(txBuf));
+ memset(rxBuf, 0, sizeof(rxBuf));
+
+ pdev = device_get_parent(dev);
+
+ cmd.tx_cmd_sz = cmd.rx_cmd_sz = 1;
+
+ cmd.tx_cmd = txBuf;
+ cmd.rx_cmd = rxBuf;
+
+ txBuf[0] = command;
+
+ err = SPIBUS_TRANSFER(pdev, dev, &cmd);
+
+ mx25l_wait_for_device_ready(dev);
+
+ return (err);
+}
+
+static int
mx25l_probe(device_t dev)
{
+
+#ifdef FDT
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+ if (!ofw_bus_is_compatible(dev, "st,m25p"))
+ return (ENXIO);
+#endif
device_set_desc(dev, "M25Pxx Flash Family");
+
return (0);
}
@@ -397,6 +480,12 @@ mx25l_attach(device_t dev)
sc->sc_sectorsize = ident->sectorsize;
sc->sc_flags = ident->flags;
+ if (sc->sc_flags & FL_ENABLE_4B_ADDR)
+ mx25l_set_4b_mode(dev, CMD_ENTER_4B_MODE);
+
+ if (sc->sc_flags & FL_DISABLE_4B_ADDR)
+ mx25l_set_4b_mode(dev, CMD_EXIT_4B_MODE);
+
/* NB: use stripesize to hold the erase/region size for RedBoot */
sc->sc_disk->d_stripesize = ident->sectorsize;
diff --git a/sys/dev/flash/mx25lreg.h b/sys/dev/flash/mx25lreg.h
index 7253dba..5e303e1 100644
--- a/sys/dev/flash/mx25lreg.h
+++ b/sys/dev/flash/mx25lreg.h
@@ -45,6 +45,8 @@
#define CMD_BULK_ERASE 0xC7
#define CMD_BLOCK_4K_ERASE 0x20
#define CMD_BLOCK_32K_ERASE 0x52
+#define CMD_ENTER_4B_MODE 0xB7
+#define CMD_EXIT_4B_MODE 0xE9
/*
* Status register flags
diff --git a/sys/dev/gpio/gpiobus.c b/sys/dev/gpio/gpiobus.c
index 44ab581..553d574 100644
--- a/sys/dev/gpio/gpiobus.c
+++ b/sys/dev/gpio/gpiobus.c
@@ -390,7 +390,7 @@ gpiobus_probe_nomatch(device_t dev, device_t child)
device_printf(dev, "<unknown device> at pins %s", pins);
else
device_printf(dev, "<unknown device> at pin %s", pins);
- resource_list_print_type(&devi->rl, "irq", SYS_RES_IRQ, "%ld");
+ resource_list_print_type(&devi->rl, "irq", SYS_RES_IRQ, "%jd");
printf("\n");
}
@@ -412,7 +412,7 @@ gpiobus_print_child(device_t dev, device_t child)
gpiobus_print_pins(devi, pins, sizeof(pins));
retval += printf("%s", pins);
}
- resource_list_print_type(&devi->rl, "irq", SYS_RES_IRQ, "%ld");
+ resource_list_print_type(&devi->rl, "irq", SYS_RES_IRQ, "%jd");
retval += bus_print_child_footer(dev, child);
return (retval);
diff --git a/sys/dev/gpio/ofw_gpiobus.c b/sys/dev/gpio/ofw_gpiobus.c
index be5a747..f6d2115 100644
--- a/sys/dev/gpio/ofw_gpiobus.c
+++ b/sys/dev/gpio/ofw_gpiobus.c
@@ -575,6 +575,7 @@ static devclass_t ofwgpiobus_devclass;
DEFINE_CLASS_1(gpiobus, ofw_gpiobus_driver, ofw_gpiobus_methods,
sizeof(struct gpiobus_softc), gpiobus_driver);
-DRIVER_MODULE(ofw_gpiobus, gpio, ofw_gpiobus_driver, ofwgpiobus_devclass, 0, 0);
+EARLY_DRIVER_MODULE(ofw_gpiobus, gpio, ofw_gpiobus_driver, ofwgpiobus_devclass,
+ 0, 0, BUS_PASS_BUS);
MODULE_VERSION(ofw_gpiobus, 1);
MODULE_DEPEND(ofw_gpiobus, gpiobus, 1, 1, 1);
diff --git a/sys/dev/hyperv/include/hyperv.h b/sys/dev/hyperv/include/hyperv.h
index 0a057c8..26a2bfc 100644
--- a/sys/dev/hyperv/include/hyperv.h
+++ b/sys/dev/hyperv/include/hyperv.h
@@ -124,6 +124,8 @@ typedef struct hv_guid {
unsigned char data[16];
} __packed hv_guid;
+int snprintf_hv_guid(char *, size_t, const hv_guid *);
+
#define HV_NIC_GUID \
.data = {0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, \
0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E}
diff --git a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
index 0cec9a7..acc49b4 100644
--- a/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
+++ b/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
@@ -181,6 +181,7 @@ struct hn_txdesc {
#define HN_CSUM_ASSIST_WIN8 (CSUM_IP | CSUM_TCP)
#define HN_CSUM_ASSIST (CSUM_IP | CSUM_UDP | CSUM_TCP)
+#define HN_LRO_LENLIM_MULTIRX_DEF (12 * ETHERMTU)
#define HN_LRO_LENLIM_DEF (25 * ETHERMTU)
/* YYY 2*MTU is a bit rough, but should be good enough. */
#define HN_LRO_LENLIM_MIN(ifp) (2 * (ifp)->if_mtu)
@@ -333,6 +334,17 @@ static void hn_xmit_txeof(struct hn_tx_ring *);
static void hn_xmit_taskfunc(void *, int);
static void hn_xmit_txeof_taskfunc(void *, int);
+#if __FreeBSD_version >= 1100099
+static void
+hn_set_lro_lenlim(struct hn_softc *sc, int lenlim)
+{
+ int i;
+
+ for (i = 0; i < sc->hn_rx_ring_inuse; ++i)
+ sc->hn_rx_ring[i].hn_lro.lro_length_lim = lenlim;
+}
+#endif
+
static int
hn_ifmedia_upd(struct ifnet *ifp __unused)
{
@@ -530,6 +542,16 @@ netvsc_attach(device_t dev)
device_printf(dev, "%d TX ring, %d RX ring\n",
sc->hn_tx_ring_inuse, sc->hn_rx_ring_inuse);
+#if __FreeBSD_version >= 1100099
+ if (sc->hn_rx_ring_inuse > 1) {
+ /*
+ * Reduce TCP segment aggregation limit for multiple
+ * RX rings to increase ACK timeliness.
+ */
+ hn_set_lro_lenlim(sc, HN_LRO_LENLIM_MULTIRX_DEF);
+ }
+#endif
+
if (device_info.link_state == 0) {
sc->hn_carrier = 1;
}
@@ -756,13 +778,8 @@ netvsc_channel_rollup(struct hv_vmbus_channel *chan)
struct hn_tx_ring *txr = chan->hv_chan_txr;
#if defined(INET) || defined(INET6)
struct hn_rx_ring *rxr = chan->hv_chan_rxr;
- struct lro_ctrl *lro = &rxr->hn_lro;
- struct lro_entry *queued;
- while ((queued = SLIST_FIRST(&lro->lro_active)) != NULL) {
- SLIST_REMOVE_HEAD(&lro->lro_active, next);
- tcp_lro_flush(lro, queued);
- }
+ tcp_lro_flush_all(&rxr->hn_lro);
#endif
/*
@@ -1238,8 +1255,10 @@ netvsc_recv(struct hv_vmbus_channel *chan, netvsc_packet *packet,
return (0);
} else if (packet->tot_data_buf_len <= MHLEN) {
m_new = m_gethdr(M_NOWAIT, MT_DATA);
- if (m_new == NULL)
+ if (m_new == NULL) {
+ if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
return (0);
+ }
memcpy(mtod(m_new, void *), packet->data,
packet->tot_data_buf_len);
m_new->m_pkthdr.len = m_new->m_len = packet->tot_data_buf_len;
@@ -1259,7 +1278,7 @@ netvsc_recv(struct hv_vmbus_channel *chan, netvsc_packet *packet,
m_new = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, size);
if (m_new == NULL) {
- if_printf(ifp, "alloc mbuf failed.\n");
+ if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
return (0);
}
@@ -1449,14 +1468,8 @@ hn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
*/
NV_LOCK(sc);
if (sc->hn_rx_ring[0].hn_lro.lro_length_lim <
- HN_LRO_LENLIM_MIN(ifp)) {
- int i;
-
- for (i = 0; i < sc->hn_rx_ring_inuse; ++i) {
- sc->hn_rx_ring[i].hn_lro.lro_length_lim =
- HN_LRO_LENLIM_MIN(ifp);
- }
- }
+ HN_LRO_LENLIM_MIN(ifp))
+ hn_set_lro_lenlim(sc, HN_LRO_LENLIM_MIN(ifp));
NV_UNLOCK(sc);
#endif
@@ -1789,7 +1802,7 @@ hn_lro_lenlim_sysctl(SYSCTL_HANDLER_ARGS)
{
struct hn_softc *sc = arg1;
unsigned int lenlim;
- int error, i;
+ int error;
lenlim = sc->hn_rx_ring[0].hn_lro.lro_length_lim;
error = sysctl_handle_int(oidp, &lenlim, 0, req);
@@ -1801,8 +1814,7 @@ hn_lro_lenlim_sysctl(SYSCTL_HANDLER_ARGS)
return EINVAL;
NV_LOCK(sc);
- for (i = 0; i < sc->hn_rx_ring_inuse; ++i)
- sc->hn_rx_ring[i].hn_lro.lro_length_lim = lenlim;
+ hn_set_lro_lenlim(sc, lenlim);
NV_UNLOCK(sc);
return 0;
}
diff --git a/sys/dev/hyperv/utilities/hv_heartbeat.c b/sys/dev/hyperv/utilities/hv_heartbeat.c
index c1b6da5..09bd28b 100644
--- a/sys/dev/hyperv/utilities/hv_heartbeat.c
+++ b/sys/dev/hyperv/utilities/hv_heartbeat.c
@@ -94,6 +94,10 @@ static int
hv_heartbeat_probe(device_t dev)
{
const char *p = vmbus_get_type(dev);
+
+ if (resource_disabled("hvheartbeat", 0))
+ return ENXIO;
+
if (!memcmp(p, &service_guid, sizeof(hv_guid))) {
device_set_desc(dev, "Hyper-V Heartbeat Service");
return BUS_PROBE_DEFAULT;
diff --git a/sys/dev/hyperv/utilities/hv_kvp.c b/sys/dev/hyperv/utilities/hv_kvp.c
index 8517918..d71310b 100644
--- a/sys/dev/hyperv/utilities/hv_kvp.c
+++ b/sys/dev/hyperv/utilities/hv_kvp.c
@@ -304,28 +304,11 @@ hv_kvp_convert_utf16_ipinfo_to_utf8(struct hv_kvp_ip_msg *host_ip_msg,
{
int err_ip, err_subnet, err_gway, err_dns, err_adap;
int UNUSED_FLAG = 1;
- int guid_index;
struct hv_device *hv_dev; /* GUID Data Structure */
hn_softc_t *sc; /* hn softc structure */
char if_name[4];
- unsigned char guid_instance[40];
- char *guid_data = NULL;
char buf[39];
- struct guid_extract {
- char a1[2];
- char a2[2];
- char a3[2];
- char a4[2];
- char b1[2];
- char b2[2];
- char c1[2];
- char c2[2];
- char d[4];
- char e[12];
- };
-
- struct guid_extract *id;
device_t *devs;
int devcnt;
@@ -352,17 +335,7 @@ hv_kvp_convert_utf16_ipinfo_to_utf8(struct hv_kvp_ip_msg *host_ip_msg,
/* Trying to find GUID of Network Device */
hv_dev = sc->hn_dev_obj;
- for (guid_index = 0; guid_index < 16; guid_index++) {
- sprintf(&guid_instance[guid_index * 2], "%02x",
- hv_dev->device_id.data[guid_index]);
- }
-
- guid_data = (char *)guid_instance;
- id = (struct guid_extract *)guid_data;
- snprintf(buf, sizeof(buf), "{%.2s%.2s%.2s%.2s-%.2s%.2s-%.2s%.2s-%.4s-%s}",
- id->a4, id->a3, id->a2, id->a1,
- id->b2, id->b1, id->c2, id->c1, id->d, id->e);
- guid_data = NULL;
+ snprintf_hv_guid(buf, sizeof(buf), &hv_dev->device_id);
sprintf(if_name, "%s%d", "hn", device_get_unit(devs[devcnt]));
if (strncmp(buf, (char *)umsg->body.kvp_ip_val.adapter_id, 39) == 0) {
@@ -890,6 +863,10 @@ static int
hv_kvp_probe(device_t dev)
{
const char *p = vmbus_get_type(dev);
+
+ if (resource_disabled("hvkvp", 0))
+ return ENXIO;
+
if (!memcmp(p, &service_guid, sizeof(hv_guid))) {
device_set_desc(dev, "Hyper-V KVP Service");
return BUS_PROBE_DEFAULT;
diff --git a/sys/dev/hyperv/utilities/hv_shutdown.c b/sys/dev/hyperv/utilities/hv_shutdown.c
index 20bc65e..0beed5a 100644
--- a/sys/dev/hyperv/utilities/hv_shutdown.c
+++ b/sys/dev/hyperv/utilities/hv_shutdown.c
@@ -116,6 +116,10 @@ static int
hv_shutdown_probe(device_t dev)
{
const char *p = vmbus_get_type(dev);
+
+ if (resource_disabled("hvshutdown", 0))
+ return ENXIO;
+
if (!memcmp(p, &service_guid, sizeof(hv_guid))) {
device_set_desc(dev, "Hyper-V Shutdown Service");
return BUS_PROBE_DEFAULT;
diff --git a/sys/dev/hyperv/utilities/hv_timesync.c b/sys/dev/hyperv/utilities/hv_timesync.c
index d1ea904..06580d7 100644
--- a/sys/dev/hyperv/utilities/hv_timesync.c
+++ b/sys/dev/hyperv/utilities/hv_timesync.c
@@ -171,6 +171,10 @@ static int
hv_timesync_probe(device_t dev)
{
const char *p = vmbus_get_type(dev);
+
+ if (resource_disabled("hvtimesync", 0))
+ return ENXIO;
+
if (!memcmp(p, &service_guid, sizeof(hv_guid))) {
device_set_desc(dev, "Hyper-V Time Synch Service");
return BUS_PROBE_DEFAULT;
diff --git a/sys/dev/hyperv/vmbus/hv_connection.c b/sys/dev/hyperv/vmbus/hv_connection.c
index aa1e59e..e170298 100644
--- a/sys/dev/hyperv/vmbus/hv_connection.c
+++ b/sys/dev/hyperv/vmbus/hv_connection.c
@@ -364,31 +364,35 @@ hv_vmbus_on_events(int cpu)
/**
* Send a msg on the vmbus's message connection
*/
-int hv_vmbus_post_message(void *buffer, size_t bufferLen) {
- int ret = 0;
+int hv_vmbus_post_message(void *buffer, size_t bufferLen)
+{
hv_vmbus_connection_id connId;
- unsigned retries = 0;
+ sbintime_t time = SBT_1MS;
+ int retries;
+ int ret;
- /* NetScaler delays from previous code were consolidated here */
- static int delayAmount[] = {100, 100, 100, 500, 500, 5000, 5000, 5000};
+ connId.as_uint32_t = 0;
+ connId.u.id = HV_VMBUS_MESSAGE_CONNECTION_ID;
- /* for(each entry in delayAmount) try to post message,
- * delay a little bit before retrying
+ /*
+ * We retry to cope with transient failures caused by host side's
+ * insufficient resources. 20 times should suffice in practice.
*/
- for (retries = 0;
- retries < sizeof(delayAmount)/sizeof(delayAmount[0]); retries++) {
- connId.as_uint32_t = 0;
- connId.u.id = HV_VMBUS_MESSAGE_CONNECTION_ID;
- ret = hv_vmbus_post_msg_via_msg_ipc(connId, 1, buffer, bufferLen);
- if (ret != HV_STATUS_INSUFFICIENT_BUFFERS)
- break;
- /* TODO: KYS We should use a blocking wait call */
- DELAY(delayAmount[retries]);
+ for (retries = 0; retries < 20; retries++) {
+ ret = hv_vmbus_post_msg_via_msg_ipc(connId, 1, buffer,
+ bufferLen);
+ if (ret == HV_STATUS_SUCCESS)
+ return (0);
+
+ pause_sbt("pstmsg", time, 0, C_HARDCLOCK);
+ if (time < SBT_1S * 2)
+ time *= 2;
}
- KASSERT(ret == 0, ("Error VMBUS: Message Post Failed\n"));
+ KASSERT(ret == HV_STATUS_SUCCESS,
+ ("Error VMBUS: Message Post Failed, ret=%d\n", ret));
- return (ret);
+ return (EAGAIN);
}
/**
diff --git a/sys/dev/hyperv/vmbus/hv_et.c b/sys/dev/hyperv/vmbus/hv_et.c
index d961486..9fb6e23 100644
--- a/sys/dev/hyperv/vmbus/hv_et.c
+++ b/sys/dev/hyperv/vmbus/hv_et.c
@@ -60,7 +60,7 @@ hv_et_start(struct eventtimer *et, sbintime_t firsttime, sbintime_t periodtime)
timer_cfg.as_uint64 = 0;
timer_cfg.auto_enable = 1;
- timer_cfg.sintx = HV_VMBUS_MESSAGE_SINT;
+ timer_cfg.sintx = HV_VMBUS_TIMER_SINT;
periodticks[curcpu] = sbintime2tick(periodtime);
if (firsttime == 0)
diff --git a/sys/dev/hyperv/vmbus/hv_hv.c b/sys/dev/hyperv/vmbus/hv_hv.c
index 6afc2b8..a87b5ce 100644
--- a/sys/dev/hyperv/vmbus/hv_hv.c
+++ b/sys/dev/hyperv/vmbus/hv_hv.c
@@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/pcpu.h>
#include <sys/timetc.h>
+#include <sys/kernel.h>
#include <machine/bus.h>
#include <machine/md_var.h>
#include <vm/vm.h>
@@ -207,8 +208,6 @@ hv_vmbus_init(void)
hv_vmbus_g_context.hypercall_page = virt_addr;
- tc_init(&hv_timecounter); /* register virtual timecount */
-
hv_et_init();
return (0);
@@ -368,6 +367,9 @@ hv_vmbus_synic_init(void *arg)
wrmsr(HV_X64_MSR_SINT0 + HV_VMBUS_MESSAGE_SINT,
shared_sint.as_uint64_t);
+ wrmsr(HV_X64_MSR_SINT0 + HV_VMBUS_TIMER_SINT,
+ shared_sint.as_uint64_t);
+
/* Enable the global synic bit */
sctrl.as_uint64_t = rdmsr(HV_X64_MSR_SCONTROL);
sctrl.u.enable = 1;
@@ -404,12 +406,23 @@ void hv_vmbus_synic_cleanup(void *arg)
shared_sint.u.masked = 1;
/*
- * Disable the interrupt
+ * Disable the interrupt 0
*/
wrmsr(
HV_X64_MSR_SINT0 + HV_VMBUS_MESSAGE_SINT,
shared_sint.as_uint64_t);
+ shared_sint.as_uint64_t = rdmsr(
+ HV_X64_MSR_SINT0 + HV_VMBUS_TIMER_SINT);
+
+ shared_sint.u.masked = 1;
+
+ /*
+ * Disable the interrupt 1
+ */
+ wrmsr(
+ HV_X64_MSR_SINT0 + HV_VMBUS_TIMER_SINT,
+ shared_sint.as_uint64_t);
simp.as_uint64_t = rdmsr(HV_X64_MSR_SIMP);
simp.u.simp_enabled = 0;
simp.u.base_simp_gpa = 0;
@@ -423,3 +436,14 @@ void hv_vmbus_synic_cleanup(void *arg)
wrmsr(HV_X64_MSR_SIEFP, siefp.as_uint64_t);
}
+static void
+hv_tc_init(void)
+{
+ if (vm_guest != VM_GUEST_HV)
+ return;
+
+ /* register virtual timecounter */
+ tc_init(&hv_timecounter);
+}
+
+SYSINIT(hv_tc_init, SI_SUB_HYPERVISOR, SI_ORDER_FIRST, hv_tc_init, NULL);
diff --git a/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c b/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
index 4895f71..669a532 100644
--- a/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
+++ b/sys/dev/hyperv/vmbus/hv_vmbus_drv_freebsd.c
@@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
#include <sys/pcpu.h>
#include <x86/apicvar.h>
+#include <dev/hyperv/include/hyperv.h>
#include "hv_vmbus_priv.h"
#include <contrib/dev/acpica/include/acpi.h>
@@ -75,7 +76,7 @@ static char *vmbus_ids[] = { "VMBUS", NULL };
* the hypervisor.
*/
static void
-vmbus_msg_swintr(void *arg)
+vmbus_msg_swintr(void *arg, int pending __unused)
{
int cpu;
void* page_addr;
@@ -174,12 +175,15 @@ hv_vmbus_isr(struct trapframe *frame)
/* Check if there are actual msgs to be process */
page_addr = hv_vmbus_g_context.syn_ic_msg_page[cpu];
- msg = (hv_vmbus_message*) page_addr + HV_VMBUS_MESSAGE_SINT;
+ msg = (hv_vmbus_message*) page_addr + HV_VMBUS_TIMER_SINT;
/* we call eventtimer process the message */
if (msg->header.message_type == HV_MESSAGE_TIMER_EXPIRED) {
msg->header.message_type = HV_MESSAGE_TYPE_NONE;
+ /* call intrrupt handler of event timer */
+ hv_et_intr(frame);
+
/*
* Make sure the write to message_type (ie set to
* HV_MESSAGE_TYPE_NONE) happens before we read the
@@ -196,12 +200,12 @@ hv_vmbus_isr(struct trapframe *frame)
*/
wrmsr(HV_X64_MSR_EOM, 0);
}
- hv_et_intr(frame);
- return (FILTER_HANDLED);
}
+ msg = (hv_vmbus_message*) page_addr + HV_VMBUS_MESSAGE_SINT;
if (msg->header.message_type != HV_MESSAGE_TYPE_NONE) {
- swi_sched(hv_vmbus_g_context.msg_swintr[cpu], 0);
+ taskqueue_enqueue(hv_vmbus_g_context.hv_msg_tq[cpu],
+ &hv_vmbus_g_context.hv_msg_task[cpu]);
}
return (FILTER_HANDLED);
@@ -279,6 +283,23 @@ vmbus_write_ivar(
return (ENOENT);
}
+static int
+vmbus_child_pnpinfo_str(device_t dev, device_t child, char *buf, size_t buflen)
+{
+ char guidbuf[40];
+ struct hv_device *dev_ctx = device_get_ivars(child);
+
+ strlcat(buf, "classid=", buflen);
+ snprintf_hv_guid(guidbuf, sizeof(guidbuf), &dev_ctx->class_id);
+ strlcat(buf, guidbuf, buflen);
+
+ strlcat(buf, " deviceid=", buflen);
+ snprintf_hv_guid(guidbuf, sizeof(guidbuf), &dev_ctx->device_id);
+ strlcat(buf, guidbuf, buflen);
+
+ return (0);
+}
+
struct hv_device*
hv_vmbus_child_device_create(
hv_guid type,
@@ -300,15 +321,17 @@ hv_vmbus_child_device_create(
return (child_dev);
}
-static void
-print_dev_guid(struct hv_device *dev)
+int
+snprintf_hv_guid(char *buf, size_t sz, const hv_guid *guid)
{
- int i;
- unsigned char guid_name[100];
- for (i = 0; i < 32; i += 2)
- sprintf(&guid_name[i], "%02x", dev->class_id.data[i / 2]);
- if(bootverbose)
- printf("VMBUS: Class ID: %s\n", guid_name);
+ int cnt;
+ const unsigned char *d = guid->data;
+
+ cnt = snprintf(buf, sz,
+ "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ d[3], d[2], d[1], d[0], d[5], d[4], d[7], d[6],
+ d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
+ return (cnt);
}
int
@@ -317,8 +340,11 @@ hv_vmbus_child_device_register(struct hv_device *child_dev)
device_t child;
int ret = 0;
- print_dev_guid(child_dev);
-
+ if (bootverbose) {
+ char name[40];
+ snprintf_hv_guid(name, sizeof(name), &child_dev->class_id);
+ printf("VMBUS: Class ID: %s\n", name);
+ }
child = device_add_child(vmbus_devp, NULL, -1);
child_dev->device = child;
@@ -485,9 +511,6 @@ vmbus_bus_init(void)
setup_args.vector = hv_vmbus_g_context.hv_cb_vector;
CPU_FOREACH(j) {
- hv_vmbus_g_context.hv_msg_intr_event[j] = NULL;
- hv_vmbus_g_context.msg_swintr[j] = NULL;
-
snprintf(buf, sizeof(buf), "cpu%d:hyperv", j);
intrcnt_add(buf, &hv_vmbus_intr_cpu[j]);
@@ -504,39 +527,21 @@ vmbus_bus_init(void)
*/
hv_vmbus_g_context.hv_event_queue[j] = taskqueue_create_fast("hyperv event", M_WAITOK,
taskqueue_thread_enqueue, &hv_vmbus_g_context.hv_event_queue[j]);
- if (hv_vmbus_g_context.hv_event_queue[j] == NULL) {
- if (bootverbose)
- printf("VMBUS: failed to setup taskqueue\n");
- goto cleanup1;
- }
CPU_SETOF(j, &cpu_mask);
taskqueue_start_threads_cpuset(&hv_vmbus_g_context.hv_event_queue[j], 1, PI_NET, &cpu_mask,
"hvevent%d", j);
/*
- * Setup software interrupt thread and handler for msg handling.
- */
- ret = swi_add(&hv_vmbus_g_context.hv_msg_intr_event[j],
- "hv_msg", vmbus_msg_swintr, (void *)(long)j, SWI_CLOCK, 0,
- &hv_vmbus_g_context.msg_swintr[j]);
- if (ret) {
- if(bootverbose)
- printf("VMBUS: failed to setup msg swi for "
- "cpu %d\n", j);
- goto cleanup1;
- }
-
- /*
- * Bind the swi thread to the cpu.
+ * Setup per-cpu tasks and taskqueues to handle msg.
*/
- ret = intr_event_bind(hv_vmbus_g_context.hv_msg_intr_event[j],
- j);
- if (ret) {
- if(bootverbose)
- printf("VMBUS: failed to bind msg swi thread "
- "to cpu %d\n", j);
- goto cleanup1;
- }
+ hv_vmbus_g_context.hv_msg_tq[j] = taskqueue_create_fast(
+ "hyperv msg", M_WAITOK, taskqueue_thread_enqueue,
+ &hv_vmbus_g_context.hv_msg_tq[j]);
+ CPU_SETOF(j, &cpu_mask);
+ taskqueue_start_threads_cpuset(&hv_vmbus_g_context.hv_msg_tq[j],
+ 1, PI_NET, &cpu_mask, "hvmsg%d", j);
+ TASK_INIT(&hv_vmbus_g_context.hv_msg_task[j], 0,
+ vmbus_msg_swintr, (void *)(long)j);
/*
* Prepare the per cpu msg and event pages to be called on each cpu.
@@ -576,11 +581,10 @@ vmbus_bus_init(void)
* remove swi and vmbus callback vector;
*/
CPU_FOREACH(j) {
- if (hv_vmbus_g_context.hv_event_queue[j] != NULL)
+ if (hv_vmbus_g_context.hv_event_queue[j] != NULL) {
taskqueue_free(hv_vmbus_g_context.hv_event_queue[j]);
- if (hv_vmbus_g_context.msg_swintr[j] != NULL)
- swi_remove(hv_vmbus_g_context.msg_swintr[j]);
- hv_vmbus_g_context.hv_msg_intr_event[j] = NULL;
+ hv_vmbus_g_context.hv_event_queue[j] = NULL;
+ }
}
vmbus_vector_free(hv_vmbus_g_context.hv_cb_vector);
@@ -645,11 +649,10 @@ vmbus_bus_exit(void)
/* remove swi */
CPU_FOREACH(i) {
- if (hv_vmbus_g_context.hv_event_queue[i] != NULL)
+ if (hv_vmbus_g_context.hv_event_queue[i] != NULL) {
taskqueue_free(hv_vmbus_g_context.hv_event_queue[i]);
- if (hv_vmbus_g_context.msg_swintr[i] != NULL)
- swi_remove(hv_vmbus_g_context.msg_swintr[i]);
- hv_vmbus_g_context.hv_msg_intr_event[i] = NULL;
+ hv_vmbus_g_context.hv_event_queue[i] = NULL;
+ }
}
vmbus_vector_free(hv_vmbus_g_context.hv_cb_vector);
@@ -714,6 +717,7 @@ static device_method_t vmbus_methods[] = {
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, vmbus_read_ivar),
DEVMETHOD(bus_write_ivar, vmbus_write_ivar),
+ DEVMETHOD(bus_child_pnpinfo_str, vmbus_child_pnpinfo_str),
{ 0, 0 } };
diff --git a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
index 62fa22a..1a0ed04 100644
--- a/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
+++ b/sys/dev/hyperv/vmbus/hv_vmbus_priv.h
@@ -70,6 +70,7 @@ typedef uint16_t hv_vmbus_status;
* You did not supply enough message buffers to send a message.
*/
+#define HV_STATUS_SUCCESS ((uint16_t)0)
#define HV_STATUS_INSUFFICIENT_BUFFERS ((uint16_t)0x0013)
typedef void (*hv_vmbus_channel_callback)(void *context);
@@ -180,7 +181,8 @@ enum {
HV_VMBUS_EVENT_PORT_ID = 2,
HV_VMBUS_MONITOR_CONNECTION_ID = 3,
HV_VMBUS_MONITOR_PORT_ID = 3,
- HV_VMBUS_MESSAGE_SINT = 2
+ HV_VMBUS_MESSAGE_SINT = 2,
+ HV_VMBUS_TIMER_SINT = 4,
};
#define HV_PRESENT_BIT 0x80000000
@@ -203,8 +205,8 @@ typedef struct {
* event and msg handling.
*/
struct taskqueue *hv_event_queue[MAXCPU];
- struct intr_event *hv_msg_intr_event[MAXCPU];
- void *msg_swintr[MAXCPU];
+ struct taskqueue *hv_msg_tq[MAXCPU];
+ struct task hv_msg_task[MAXCPU];
/*
* Host use this vector to intrrupt guest for vmbus channel
* event and msg.
diff --git a/sys/dev/ichwd/ichwd.c b/sys/dev/ichwd/ichwd.c
index ec84f8f..75c41b7 100644
--- a/sys/dev/ichwd/ichwd.c
+++ b/sys/dev/ichwd/ichwd.c
@@ -540,9 +540,6 @@ ichwd_find_ich_lpc_bridge(struct ichwd_device **id_p)
if (ich == NULL)
return (NULL);
- ichwd_verbose_printf(ich, "found ICH%d or equivalent chipset: %s\n",
- id->ich_version, id->desc);
-
if (id_p)
*id_p = id;
@@ -573,8 +570,6 @@ ichwd_identify(driver_t *driver, device_t parent)
if (dev == NULL)
return;
- device_set_desc_copy(dev, id_p->desc);
-
switch (id_p->tco_version) {
case 1:
break;
@@ -611,10 +606,16 @@ ichwd_identify(driver_t *driver, device_t parent)
static int
ichwd_probe(device_t dev)
{
+ struct ichwd_device *id_p;
/* Do not claim some ISA PnP device by accident. */
if (isa_get_logicalid(dev) != 0)
return (ENXIO);
+
+ if (ichwd_find_ich_lpc_bridge(&id_p) == NULL)
+ return (ENXIO);
+
+ device_set_desc_copy(dev, id_p->desc);
return (0);
}
@@ -677,9 +678,6 @@ ichwd_attach(device_t dev)
if (ichwd_clear_noreboot(sc) != 0)
goto fail;
- ichwd_verbose_printf(dev, "%s (ICH%d or equivalent)\n",
- id_p->desc, sc->ich_version);
-
/*
* Determine if we are coming up after a watchdog-induced reset. Some
* BIOSes may clear this bit at bootup, preventing us from reporting
diff --git a/sys/dev/iicbus/iicbus.c b/sys/dev/iicbus/iicbus.c
index df29b09..a090bb9 100644
--- a/sys/dev/iicbus/iicbus.c
+++ b/sys/dev/iicbus/iicbus.c
@@ -149,7 +149,7 @@ iicbus_print_child(device_t dev, device_t child)
retval += bus_print_child_header(dev, child);
if (devi->addr != 0)
retval += printf(" at addr %#x", devi->addr);
- resource_list_print_type(&devi->rl, "irq", SYS_RES_IRQ, "%ld");
+ resource_list_print_type(&devi->rl, "irq", SYS_RES_IRQ, "%jd");
retval += bus_print_child_footer(dev, child);
return (retval);
diff --git a/sys/dev/iir/iir.c b/sys/dev/iir/iir.c
index bf5cec5..e74698e 100644
--- a/sys/dev/iir/iir.c
+++ b/sys/dev/iir/iir.c
@@ -744,9 +744,9 @@ gdt_next(struct gdt_softc *gdt)
ccb->ccb_h.flags));
csio = &ccb->csio;
ccbh = &ccb->ccb_h;
- cmd = csio->cdb_io.cdb_bytes[0];
- /* Max CDB length is 12 bytes */
- if (csio->cdb_len > 12) {
+ cmd = scsiio_cdb_ptr(csio)[0];
+ /* Max CDB length is 12 bytes, can't be phys addr */
+ if (csio->cdb_len > 12 || (ccbh->flags & CAM_CDB_PHYS)) {
ccbh->status = CAM_REQ_INVALID;
--gdt_stat.io_count_act;
xpt_done(ccb);
diff --git a/sys/dev/iir/iir_pci.c b/sys/dev/iir/iir_pci.c
index 261f5a6..5db66b1 100644
--- a/sys/dev/iir/iir_pci.c
+++ b/sys/dev/iir/iir_pci.c
@@ -228,7 +228,7 @@ iir_pci_attach(device_t dev)
/* check and reset interface area */
bus_write_4(gdt->sc_dpmem, GDT_MPR_IC, htole32(GDT_MPR_MAGIC));
if (bus_read_4(gdt->sc_dpmem, GDT_MPR_IC) != htole32(GDT_MPR_MAGIC)) {
- device_printf(dev, "cannot access DPMEM at 0x%lx (shadowed?)\n",
+ device_printf(dev, "cannot access DPMEM at 0x%jx (shadowed?)\n",
rman_get_start(gdt->sc_dpmem));
error = ENXIO;
goto err;
diff --git a/sys/dev/ipmi/ipmi.c b/sys/dev/ipmi/ipmi.c
index 8101717..314d4d6 100644
--- a/sys/dev/ipmi/ipmi.c
+++ b/sys/dev/ipmi/ipmi.c
@@ -603,6 +603,20 @@ ipmi_polled_enqueue_request(struct ipmi_softc *sc, struct ipmi_request *req)
*/
static int
+ipmi_reset_watchdog(struct ipmi_softc *sc)
+{
+ struct ipmi_request *req;
+ int error;
+
+ IPMI_ALLOC_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0),
+ IPMI_RESET_WDOG, 0, 0);
+ error = ipmi_submit_driver_request(sc, req, 0);
+ if (error)
+ device_printf(sc->ipmi_dev, "Failed to reset watchdog\n");
+ return (error);
+}
+
+static int
ipmi_set_watchdog(struct ipmi_softc *sc, unsigned int sec)
{
struct ipmi_request *req;
@@ -613,7 +627,6 @@ ipmi_set_watchdog(struct ipmi_softc *sc, unsigned int sec)
IPMI_ALLOC_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0),
IPMI_SET_WDOG, 6, 0);
-
if (sec) {
req->ir_request[0] = IPMI_SET_WD_TIMER_DONT_STOP
| IPMI_SET_WD_TIMER_SMS_OS;
@@ -630,24 +643,10 @@ ipmi_set_watchdog(struct ipmi_softc *sc, unsigned int sec)
req->ir_request[4] = 0;
req->ir_request[5] = 0;
}
-
error = ipmi_submit_driver_request(sc, req, 0);
if (error)
device_printf(sc->ipmi_dev, "Failed to set watchdog\n");
- else if (sec) {
- IPMI_INIT_DRIVER_REQUEST(req, IPMI_ADDR(IPMI_APP_REQUEST, 0),
- IPMI_RESET_WDOG, 0, 0);
-
- error = ipmi_submit_driver_request(sc, req, 0);
- if (error)
- device_printf(sc->ipmi_dev,
- "Failed to reset watchdog\n");
- }
-
return (error);
- /*
- dump_watchdog(sc);
- */
}
static void
@@ -665,12 +664,24 @@ ipmi_wd_event(void *arg, unsigned int cmd, int *error)
timeout = ((uint64_t)1 << cmd) / 1000000000;
if (timeout == 0)
timeout = 1;
- e = ipmi_set_watchdog(sc, timeout);
- if (e == 0) {
- *error = 0;
- sc->ipmi_watchdog_active = 1;
- } else
- (void)ipmi_set_watchdog(sc, 0);
+ if (timeout != sc->ipmi_watchdog_active) {
+ e = ipmi_set_watchdog(sc, timeout);
+ if (e == 0) {
+ sc->ipmi_watchdog_active = timeout;
+ } else {
+ (void)ipmi_set_watchdog(sc, 0);
+ sc->ipmi_watchdog_active = 0;
+ }
+ }
+ if (sc->ipmi_watchdog_active != 0) {
+ e = ipmi_reset_watchdog(sc);
+ if (e == 0) {
+ *error = 0;
+ } else {
+ (void)ipmi_set_watchdog(sc, 0);
+ sc->ipmi_watchdog_active = 0;
+ }
+ }
} else if (atomic_readandclear_int(&sc->ipmi_watchdog_active) != 0) {
e = ipmi_set_watchdog(sc, 0);
if (e != 0 && cmd == 0)
diff --git a/sys/dev/isci/isci_controller.c b/sys/dev/isci/isci_controller.c
index b0f4285..d3ec045 100644
--- a/sys/dev/isci/isci_controller.c
+++ b/sys/dev/isci/isci_controller.c
@@ -740,6 +740,11 @@ void isci_action(struct cam_sim *sim, union ccb *ccb)
}
break;
case XPT_SCSI_IO:
+ if (ccb->ccb_h.flags & CAM_CDB_PHYS) {
+ ccb->ccb_h.status = CAM_REQ_INVALID;
+ xpt_done(ccb);
+ break;
+ }
isci_io_request_execute_scsi_io(ccb, controller);
break;
#if __FreeBSD_version >= 900026
@@ -802,6 +807,7 @@ isci_controller_release_queued_ccbs(struct ISCI_CONTROLLER *controller)
{
struct ISCI_REMOTE_DEVICE *dev;
struct ccb_hdr *ccb_h;
+ uint8_t *ptr;
int dev_idx;
KASSERT(mtx_owned(&controller->lock), ("controller lock not owned"));
@@ -821,8 +827,8 @@ isci_controller_release_queued_ccbs(struct ISCI_CONTROLLER *controller)
if (ccb_h == NULL)
continue;
- isci_log_message(1, "ISCI", "release %p %x\n", ccb_h,
- ((union ccb *)ccb_h)->csio.cdb_io.cdb_bytes[0]);
+ ptr = scsiio_cdb_ptr(&((union ccb *)ccb_h)->csio);
+ isci_log_message(1, "ISCI", "release %p %x\n", ccb_h, *ptr);
dev->queued_ccb_in_progress = (union ccb *)ccb_h;
isci_io_request_execute_scsi_io(
diff --git a/sys/dev/isci/isci_io_request.c b/sys/dev/isci/isci_io_request.c
index e6b68fd..f86c126 100644
--- a/sys/dev/isci/isci_io_request.c
+++ b/sys/dev/isci/isci_io_request.c
@@ -86,6 +86,7 @@ isci_io_request_complete(SCI_CONTROLLER_HANDLE_T scif_controller,
struct ISCI_REMOTE_DEVICE *isci_remote_device;
union ccb *ccb;
BOOL complete_ccb;
+ struct ccb_scsiio *csio;
complete_ccb = TRUE;
isci_controller = (struct ISCI_CONTROLLER *) sci_object_get_association(scif_controller);
@@ -93,7 +94,7 @@ isci_io_request_complete(SCI_CONTROLLER_HANDLE_T scif_controller,
(struct ISCI_REMOTE_DEVICE *) sci_object_get_association(remote_device);
ccb = isci_request->ccb;
-
+ csio = &ccb->csio;
ccb->ccb_h.status &= ~CAM_STATUS_MASK;
switch (completion_status) {
@@ -124,7 +125,6 @@ isci_io_request_complete(SCI_CONTROLLER_HANDLE_T scif_controller,
SCI_SSP_RESPONSE_IU_T * response_buffer;
uint32_t sense_length;
int error_code, sense_key, asc, ascq;
- struct ccb_scsiio *csio = &ccb->csio;
response_buffer = (SCI_SSP_RESPONSE_IU_T *)
scif_io_request_get_response_iu_address(
@@ -146,7 +146,7 @@ isci_io_request_complete(SCI_CONTROLLER_HANDLE_T scif_controller,
isci_log_message(1, "ISCI",
"isci: bus=%x target=%x lun=%x cdb[0]=%x status=%x key=%x asc=%x ascq=%x\n",
ccb->ccb_h.path_id, ccb->ccb_h.target_id,
- ccb->ccb_h.target_lun, csio->cdb_io.cdb_bytes[0],
+ ccb->ccb_h.target_lun, scsiio_cdb_ptr(csio),
csio->scsi_status, sense_key, asc, ascq);
break;
}
@@ -157,7 +157,7 @@ isci_io_request_complete(SCI_CONTROLLER_HANDLE_T scif_controller,
isci_log_message(0, "ISCI",
"isci: bus=%x target=%x lun=%x cdb[0]=%x remote device reset required\n",
ccb->ccb_h.path_id, ccb->ccb_h.target_id,
- ccb->ccb_h.target_lun, ccb->csio.cdb_io.cdb_bytes[0]);
+ ccb->ccb_h.target_lun, scsiio_cdb_ptr(csio));
break;
case SCI_IO_FAILURE_TERMINATED:
@@ -165,7 +165,7 @@ isci_io_request_complete(SCI_CONTROLLER_HANDLE_T scif_controller,
isci_log_message(0, "ISCI",
"isci: bus=%x target=%x lun=%x cdb[0]=%x terminated\n",
ccb->ccb_h.path_id, ccb->ccb_h.target_id,
- ccb->ccb_h.target_lun, ccb->csio.cdb_io.cdb_bytes[0]);
+ ccb->ccb_h.target_lun, scsiio_cdb_ptr(csio));
break;
case SCI_IO_FAILURE_INVALID_STATE:
@@ -208,7 +208,7 @@ isci_io_request_complete(SCI_CONTROLLER_HANDLE_T scif_controller,
isci_log_message(1, "ISCI",
"isci: bus=%x target=%x lun=%x cdb[0]=%x completion status=%x\n",
ccb->ccb_h.path_id, ccb->ccb_h.target_id,
- ccb->ccb_h.target_lun, ccb->csio.cdb_io.cdb_bytes[0],
+ ccb->ccb_h.target_lun, scsiio_cdb_ptr(csio),
completion_status);
ccb->ccb_h.status |= CAM_REQ_CMP_ERR;
break;
@@ -285,13 +285,13 @@ isci_io_request_complete(SCI_CONTROLLER_HANDLE_T scif_controller,
* get a ready notification for this device.
*/
isci_log_message(1, "ISCI", "already queued %p %x\n",
- ccb, ccb->csio.cdb_io.cdb_bytes[0]);
+ ccb, scsiio_cdb_ptr(csio));
isci_remote_device->queued_ccb_in_progress = NULL;
} else {
isci_log_message(1, "ISCI", "queue %p %x\n", ccb,
- ccb->csio.cdb_io.cdb_bytes[0]);
+ scsiio_cdb_ptr(csio));
ccb->ccb_h.status |= CAM_SIM_QUEUED;
TAILQ_INSERT_TAIL(&isci_remote_device->queued_ccbs,
@@ -373,7 +373,7 @@ scif_cb_io_request_get_cdb_address(void * scif_user_io_request)
struct ISCI_IO_REQUEST *isci_request =
(struct ISCI_IO_REQUEST *)scif_user_io_request;
- return (isci_request->ccb->csio.cdb_io.cdb_bytes);
+ return (scsiio_cdb_ptr(&isci_request->ccb->csio));
}
/**
diff --git a/sys/dev/iscsi/iscsi.c b/sys/dev/iscsi/iscsi.c
index a9bdaf7..7172ec0 100644
--- a/sys/dev/iscsi/iscsi.c
+++ b/sys/dev/iscsi/iscsi.c
@@ -288,6 +288,8 @@ iscsi_session_terminate_task(struct iscsi_session *is,
struct iscsi_outstanding *io, bool requeue)
{
+ ISCSI_SESSION_LOCK_ASSERT(is);
+
if (io->io_ccb != NULL) {
io->io_ccb->ccb_h.status &= ~(CAM_SIM_QUEUED | CAM_STATUS_MASK);
if (requeue)
@@ -2220,6 +2222,7 @@ iscsi_action_scsiio(struct iscsi_session *is, union ccb *ccb)
error = icl_pdu_append_data(request, csio->data_ptr, len, M_NOWAIT);
if (error != 0) {
+ iscsi_outstanding_remove(is, io);
icl_pdu_free(request);
if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
xpt_freeze_devq(ccb->ccb_h.path, 1);
diff --git a/sys/dev/iwn/if_iwn.c b/sys/dev/iwn/if_iwn.c
index 28b7b7f..bffa8de 100644
--- a/sys/dev/iwn/if_iwn.c
+++ b/sys/dev/iwn/if_iwn.c
@@ -2554,7 +2554,8 @@ iwn_find_eeprom_channel(struct iwn_softc *sc, struct ieee80211_channel *c)
} else {
for (j = 0; j < 5; j++) {
for (i = 0; i < iwn_bands[j].nchan; i++) {
- if (iwn_bands[j].chan[i] == c->ic_ieee)
+ if (iwn_bands[j].chan[i] == c->ic_ieee &&
+ ((j == 0) ^ IEEE80211_IS_CHAN_A(c)) == 1)
return &sc->eeprom_channels[j][i];
}
}
@@ -8700,7 +8701,9 @@ iwn_panicked(void *arg0, int pending)
struct iwn_softc *sc = arg0;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+#if 0
int error;
+#endif
if (vap == NULL) {
printf("%s: null vap\n", __func__);
@@ -8708,8 +8711,18 @@ iwn_panicked(void *arg0, int pending)
}
device_printf(sc->sc_dev, "%s: controller panicked, iv_state = %d; "
- "resetting...\n", __func__, vap->iv_state);
+ "restarting\n", __func__, vap->iv_state);
+ /*
+ * This is not enough work. We need to also reinitialise
+ * the correct transmit state for aggregation enabled queues,
+ * which has a very specific requirement of
+ * ring index = 802.11 seqno % 256. If we don't do this (which
+ * we definitely don't!) then the firmware will just panic again.
+ */
+#if 1
+ ieee80211_restart_all(ic);
+#else
IWN_LOCK(sc);
iwn_stop_locked(sc);
@@ -8726,6 +8739,7 @@ iwn_panicked(void *arg0, int pending)
}
IWN_UNLOCK(sc);
+#endif
}
static void
diff --git a/sys/dev/ixgbe/if_ix.c b/sys/dev/ixgbe/if_ix.c
index f0e218f..5e16fbd 100644
--- a/sys/dev/ixgbe/if_ix.c
+++ b/sys/dev/ixgbe/if_ix.c
@@ -4749,10 +4749,6 @@ ixgbe_sysctl_advertise(SYSCTL_HANDLER_ARGS)
if ((error) || (req->newptr == NULL))
return (error);
- /* Checks to validate new value */
- if (adapter->advertise == advertise) /* no change */
- return (0);
-
return ixgbe_set_advertise(adapter, advertise);
}
@@ -4763,6 +4759,10 @@ ixgbe_set_advertise(struct adapter *adapter, int advertise)
struct ixgbe_hw *hw;
ixgbe_link_speed speed;
+ /* Checks to validate new value */
+ if (adapter->advertise == advertise) /* no change */
+ return (0);
+
hw = &adapter->hw;
dev = adapter->dev;
diff --git a/sys/dev/ixgbe/ix_txrx.c b/sys/dev/ixgbe/ix_txrx.c
index 00e5dc8..66bcb25 100644
--- a/sys/dev/ixgbe/ix_txrx.c
+++ b/sys/dev/ixgbe/ix_txrx.c
@@ -1753,7 +1753,6 @@ ixgbe_rxeof(struct ix_queue *que)
struct rx_ring *rxr = que->rxr;
struct ifnet *ifp = adapter->ifp;
struct lro_ctrl *lro = &rxr->lro;
- struct lro_entry *queued;
int i, nextp, processed = 0;
u32 staterr = 0;
u32 count = adapter->rx_process_limit;
@@ -2003,10 +2002,7 @@ next_desc:
/*
* Flush any outstanding LRO work
*/
- while ((queued = SLIST_FIRST(&lro->lro_active)) != NULL) {
- SLIST_REMOVE_HEAD(&lro->lro_active, next);
- tcp_lro_flush(lro, queued);
- }
+ tcp_lro_flush_all(lro);
IXGBE_RX_UNLOCK(rxr);
diff --git a/sys/dev/ixl/ixl_txrx.c b/sys/dev/ixl/ixl_txrx.c
index 0ae7433..ca6e252 100644
--- a/sys/dev/ixl/ixl_txrx.c
+++ b/sys/dev/ixl/ixl_txrx.c
@@ -1511,7 +1511,6 @@ ixl_rxeof(struct ixl_queue *que, int count)
struct ifnet *ifp = vsi->ifp;
#if defined(INET6) || defined(INET)
struct lro_ctrl *lro = &rxr->lro;
- struct lro_entry *queued;
#endif
int i, nextp, processed = 0;
union i40e_rx_desc *cur;
@@ -1735,10 +1734,7 @@ next_desc:
/*
* Flush any outstanding LRO work
*/
- while ((queued = SLIST_FIRST(&lro->lro_active)) != NULL) {
- SLIST_REMOVE_HEAD(&lro->lro_active, next);
- tcp_lro_flush(lro, queued);
- }
+ tcp_lro_flush_all(lro);
#endif
IXL_RX_UNLOCK(rxr);
diff --git a/sys/dev/le/lebuffer_sbus.c b/sys/dev/le/lebuffer_sbus.c
index 1254fc3..f2c7c5f 100644
--- a/sys/dev/le/lebuffer_sbus.c
+++ b/sys/dev/le/lebuffer_sbus.c
@@ -297,7 +297,7 @@ lebuffer_print_res(struct lebuffer_devinfo *ldi)
rv = 0;
rv += resource_list_print_type(&ldi->ldi_rl, "mem", SYS_RES_MEMORY,
- "%#lx");
- rv += resource_list_print_type(&ldi->ldi_rl, "irq", SYS_RES_IRQ, "%ld");
+ "%#jx");
+ rv += resource_list_print_type(&ldi->ldi_rl, "irq", SYS_RES_IRQ, "%jd");
return (rv);
}
diff --git a/sys/dev/mca/mca_bus.c b/sys/dev/mca/mca_bus.c
index 55ac9ed..2de61da 100644
--- a/sys/dev/mca/mca_bus.c
+++ b/sys/dev/mca/mca_bus.c
@@ -365,11 +365,11 @@ mca_print_child (device_t dev, device_t child)
rid = 0;
while ((rle = resource_list_find(&(m_dev->rl), SYS_RES_IOPORT, rid++))) {
if (rle->count == 1) {
- snprintf(buf, sizeof(buf), "%s%lx",
+ snprintf(buf, sizeof(buf), "%s%jx",
((rid == 1) ? "io 0x" : "0x"),
rle->start);
} else {
- snprintf(buf, sizeof(buf), "%s%lx-0x%lx",
+ snprintf(buf, sizeof(buf), "%s%jx-0x%jx",
((rid == 1) ? "io 0x" : "0x"),
rle->start,
(rle->start + rle->count));
@@ -381,11 +381,11 @@ mca_print_child (device_t dev, device_t child)
rid = 0;
while ((rle = resource_list_find(&(m_dev->rl), SYS_RES_MEMORY, rid++))) {
if (rle->count == 1) {
- snprintf(buf, sizeof(buf), "%s%lx",
+ snprintf(buf, sizeof(buf), "%s%jx",
((rid == 1) ? "mem 0x" : "0x"),
rle->start);
} else {
- snprintf(buf, sizeof(buf), "%s%lx-0x%lx",
+ snprintf(buf, sizeof(buf), "%s%jx-0x%jx",
((rid == 1) ? "mem 0x" : "0x"),
rle->start,
(rle->start + rle->count));
@@ -396,14 +396,14 @@ mca_print_child (device_t dev, device_t child)
rid = 0;
while ((rle = resource_list_find(&(m_dev->rl), SYS_RES_IRQ, rid++))) {
- snprintf(buf, sizeof(buf), "irq %ld", rle->start);
+ snprintf(buf, sizeof(buf), "irq %jd", rle->start);
mca_reg_print(child, buf,
((rid == 1) ? &separator : NULL), &column);
}
rid = 0;
while ((rle = resource_list_find(&(m_dev->rl), SYS_RES_DRQ, rid++))) {
- snprintf(buf, sizeof(buf), "drq %lx", rle->start);
+ snprintf(buf, sizeof(buf), "drq %jx", rle->start);
mca_reg_print(child, buf,
((rid == 1) ? &separator : NULL), &column);
}
diff --git a/sys/dev/mfi/mfi.c b/sys/dev/mfi/mfi.c
index ddcc853..c224186 100644
--- a/sys/dev/mfi/mfi.c
+++ b/sys/dev/mfi/mfi.c
@@ -2141,7 +2141,7 @@ mfi_build_syspdio(struct mfi_softc *sc, struct bio *bio)
pass = &cm->cm_frame->pass;
bzero(pass->cdb, 16);
pass->header.cmd = MFI_CMD_PD_SCSI_IO;
- switch (bio->bio_cmd & 0x03) {
+ switch (bio->bio_cmd) {
case BIO_READ:
flags = MFI_CMD_DATAIN | MFI_CMD_BIO;
readop = 1;
@@ -2200,7 +2200,7 @@ mfi_build_ldio(struct mfi_softc *sc, struct bio *bio)
bzero(cm->cm_frame, sizeof(union mfi_frame));
cm->cm_frame->header.context = context;
io = &cm->cm_frame->io;
- switch (bio->bio_cmd & 0x03) {
+ switch (bio->bio_cmd) {
case BIO_READ:
io->header.cmd = MFI_CMD_LD_READ;
flags = MFI_CMD_DATAIN | MFI_CMD_BIO;
diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_rx.c b/sys/dev/mlx5/mlx5_en/mlx5_en_rx.c
index 48339be..230dfcc 100644
--- a/sys/dev/mlx5/mlx5_en/mlx5_en_rx.c
+++ b/sys/dev/mlx5/mlx5_en/mlx5_en_rx.c
@@ -322,9 +322,6 @@ mlx5e_decompress_cqes(struct mlx5e_cq *cq)
static int
mlx5e_poll_rx_cq(struct mlx5e_rq *rq, int budget)
{
-#ifndef HAVE_TURBO_LRO
- struct lro_entry *queued;
-#endif
int i;
for (i = 0; i < budget; i++) {
@@ -399,10 +396,7 @@ wq_ll_pop:
/* ensure cq space is freed before enabling more cqes */
wmb();
#ifndef HAVE_TURBO_LRO
- while ((queued = SLIST_FIRST(&rq->lro.lro_active)) != NULL) {
- SLIST_REMOVE_HEAD(&rq->lro.lro_active, next);
- tcp_lro_flush(&rq->lro, queued);
- }
+ tcp_lro_flush_all(&rq->lro);
#endif
return (i);
}
diff --git a/sys/dev/mmc/host/dwmmc.c b/sys/dev/mmc/host/dwmmc.c
index 5dc0626..5b24a6d 100644
--- a/sys/dev/mmc/host/dwmmc.c
+++ b/sys/dev/mmc/host/dwmmc.c
@@ -1178,3 +1178,4 @@ static devclass_t dwmmc_devclass;
DRIVER_MODULE(dwmmc, simplebus, dwmmc_driver, dwmmc_devclass, 0, 0);
DRIVER_MODULE(dwmmc, ofwbus, dwmmc_driver, dwmmc_devclass, 0, 0);
DRIVER_MODULE(mmc, dwmmc, mmc_driver, mmc_devclass, NULL, NULL);
+MODULE_DEPEND(dwmmc, mmc, 1, 1, 1);
diff --git a/sys/dev/mmc/mmc.c b/sys/dev/mmc/mmc.c
index a65ff41..9f88079 100644
--- a/sys/dev/mmc/mmc.c
+++ b/sys/dev/mmc/mmc.c
@@ -1811,3 +1811,5 @@ driver_t mmc_driver = {
sizeof(struct mmc_softc),
};
devclass_t mmc_devclass;
+
+MODULE_VERSION(mmc, 1);
diff --git a/sys/dev/mmc/mmcreg.h b/sys/dev/mmc/mmcreg.h
index f454ddb..b169d26 100644
--- a/sys/dev/mmc/mmcreg.h
+++ b/sys/dev/mmc/mmcreg.h
@@ -85,8 +85,11 @@ struct mmc_command {
#define MMC_RSP_R1B (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE | MMC_RSP_BUSY)
#define MMC_RSP_R2 (MMC_RSP_PRESENT | MMC_RSP_136 | MMC_RSP_CRC)
#define MMC_RSP_R3 (MMC_RSP_PRESENT)
-#define MMC_RSP_R6 (MMC_RSP_PRESENT | MMC_RSP_CRC)
-#define MMC_RSP_R7 (MMC_RSP_PRESENT | MMC_RSP_CRC)
+#define MMC_RSP_R4 (MMC_RSP_PRESENT)
+#define MMC_RSP_R5 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
+#define MMC_RSP_R5B (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE | MMC_RSP_BUSY)
+#define MMC_RSP_R6 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
+#define MMC_RSP_R7 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
#define MMC_RSP(x) ((x) & MMC_RSP_MASK)
uint32_t retries;
uint32_t error;
diff --git a/sys/dev/mvs/mvs_pci.c b/sys/dev/mvs/mvs_pci.c
index 316ac00..b3262f8 100644
--- a/sys/dev/mvs/mvs_pci.c
+++ b/sys/dev/mvs/mvs_pci.c
@@ -396,7 +396,7 @@ mvs_alloc_resource(device_t dev, device_t child, int type, int *rid,
int unit = ((struct mvs_channel *)device_get_softc(child))->unit;
struct resource *res = NULL;
int offset = HC_BASE(unit >> 2) + PORT_BASE(unit & 0x03);
- long st;
+ rman_res_t st;
switch (type) {
case SYS_RES_MEMORY:
diff --git a/sys/dev/mvs/mvs_soc.c b/sys/dev/mvs/mvs_soc.c
index d4ecd8f..b34df30 100644
--- a/sys/dev/mvs/mvs_soc.c
+++ b/sys/dev/mvs/mvs_soc.c
@@ -342,7 +342,7 @@ mvs_alloc_resource(device_t dev, device_t child, int type, int *rid,
int unit = ((struct mvs_channel *)device_get_softc(child))->unit;
struct resource *res = NULL;
int offset = PORT_BASE(unit & 0x03);
- long st;
+ rman_res_t st;
switch (type) {
case SYS_RES_MEMORY:
diff --git a/sys/dev/mxge/if_mxge.c b/sys/dev/mxge/if_mxge.c
index 928917f..f78b34b 100644
--- a/sys/dev/mxge/if_mxge.c
+++ b/sys/dev/mxge/if_mxge.c
@@ -2819,11 +2819,7 @@ mxge_clean_rx_done(struct mxge_slice_state *ss)
break;
}
#if defined(INET) || defined (INET6)
- while (!SLIST_EMPTY(&ss->lc.lro_active)) {
- struct lro_entry *lro = SLIST_FIRST(&ss->lc.lro_active);
- SLIST_REMOVE_HEAD(&ss->lc.lro_active, next);
- tcp_lro_flush(&ss->lc, lro);
- }
+ tcp_lro_flush_all(&ss->lc);
#endif
}
@@ -4612,7 +4608,7 @@ mxge_add_msix_irqs(mxge_softc_t *sc)
device_printf(sc->dev, "using %d msix IRQs:",
sc->num_slices);
for (i = 0; i < sc->num_slices; i++)
- printf(" %ld", rman_get_start(sc->msix_irq_res[i]));
+ printf(" %jd", rman_get_start(sc->msix_irq_res[i]));
printf("\n");
}
return (0);
@@ -4668,7 +4664,7 @@ mxge_add_single_irq(mxge_softc_t *sc)
return ENXIO;
}
if (mxge_verbose)
- device_printf(sc->dev, "using %s irq %ld\n",
+ device_printf(sc->dev, "using %s irq %jd\n",
sc->legacy_irq ? "INTx" : "MSI",
rman_get_start(sc->irq_res));
err = bus_setup_intr(sc->dev, sc->irq_res,
@@ -4823,7 +4819,7 @@ mxge_attach(device_t dev)
sc->sram = rman_get_virtual(sc->mem_res);
sc->sram_size = 2*1024*1024 - (2*(48*1024)+(32*1024)) - 0x100;
if (sc->sram_size > rman_get_size(sc->mem_res)) {
- device_printf(dev, "impossible memory region size %ld\n",
+ device_printf(dev, "impossible memory region size %jd\n",
rman_get_size(sc->mem_res));
err = ENXIO;
goto abort_with_mem_res;
diff --git a/sys/dev/ncr/ncr.c b/sys/dev/ncr/ncr.c
index 6c941e1..111cd69 100644
--- a/sys/dev/ncr/ncr.c
+++ b/sys/dev/ncr/ncr.c
@@ -3860,6 +3860,16 @@ ncr_action (struct cam_sim *sim, union ccb *ccb)
csio = &ccb->csio;
/*
+ * Make sure we support this request. We can't do
+ * PHYS pointers.
+ */
+ if (ccb->ccb_h.flags & CAM_CDB_PHYS) {
+ ccb->ccb_h.status = CAM_REQ_INVALID;
+ xpt_done(ccb);
+ return;
+ }
+
+ /*
* Last time we need to check if this CCB needs to
* be aborted.
*/
@@ -4070,8 +4080,7 @@ ncr_action (struct cam_sim *sim, union ccb *ccb)
/*
** command
*/
- /* XXX JGibbs - Support other command types */
- cp->phys.cmd.addr = vtophys (csio->cdb_io.cdb_bytes);
+ cp->phys.cmd.addr = vtophys (scsiio_cdb_ptr(csio));
cp->phys.cmd.size = csio->cdb_len;
/*
** sense command
@@ -4083,7 +4092,6 @@ ncr_action (struct cam_sim *sim, union ccb *ccb)
*/
cp->sensecmd[0] = 0x03;
cp->sensecmd[1] = ccb->ccb_h.target_lun << 5;
- cp->sensecmd[4] = sizeof(struct scsi_sense_data);
cp->sensecmd[4] = csio->sense_len;
/*
** sense data
diff --git a/sys/dev/nctgpio/nctgpio.c b/sys/dev/nctgpio/nctgpio.c
new file mode 100644
index 0000000..ab547c0
--- /dev/null
+++ b/sys/dev/nctgpio/nctgpio.c
@@ -0,0 +1,802 @@
+/*-
+ * Copyright (c) 2016 Daniel Wyatt <Daniel.Wyatt@gmail.com>
+ * 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$
+ *
+ */
+
+/*
+ * Nuvoton GPIO driver.
+ *
+ */
+
+#include <sys/cdefs.h>
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/eventhandler.h>
+#include <sys/lock.h>
+
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/gpio.h>
+
+#include <isa/isavar.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <dev/gpio/gpiobusvar.h>
+
+#include "gpio_if.h"
+
+/*
+ * Global configuration registers (CR).
+ */
+#define NCT_CR_LDN 0x07 /* Logical Device Number */
+#define NCT_CR_CHIP_ID 0x20 /* Chip ID */
+#define NCT_CR_CHIP_ID_H 0x20 /* Chip ID (high byte) */
+#define NCT_CR_CHIP_ID_L 0x21 /* Chip ID (low byte) */
+#define NCT_CR_OPT_1 0x26 /* Global Options (1) */
+
+/* Logical Device Numbers. */
+#define NCT_LDN_GPIO 0x07
+#define NCT_LDN_GPIO_CFG 0x08
+#define NCT_LDN_GPIO_MODE 0x0f
+
+/* Logical Device 7 */
+#define NCT_LD7_GPIO_ENABLE 0x30
+#define NCT_LD7_GPIO0_IOR 0xe0
+#define NCT_LD7_GPIO0_DAT 0xe1
+#define NCT_LD7_GPIO0_INV 0xe2
+#define NCT_LD7_GPIO0_DST 0xe3
+#define NCT_LD7_GPIO1_IOR 0xe4
+#define NCT_LD7_GPIO1_DAT 0xe5
+#define NCT_LD7_GPIO1_INV 0xe6
+#define NCT_LD7_GPIO1_DST 0xe7
+
+/* Logical Device F */
+#define NCT_LDF_GPIO0_OUTCFG 0xe0
+#define NCT_LDF_GPIO1_OUTCFG 0xe1
+
+#define NCT_EXTFUNC_ENTER 0x87
+#define NCT_EXTFUNC_EXIT 0xaa
+
+#define NCT_MAX_PIN 15
+#define NCT_IS_VALID_PIN(_p) ((_p) >= 0 && (_p) <= NCT_MAX_PIN)
+
+#define NCT_PIN_BIT(_p) (1 << ((_p) % 8))
+
+#define NCT_GPIO_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \
+ GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL | \
+ GPIO_PIN_INVIN | GPIO_PIN_INVOUT)
+
+struct nct_softc {
+ device_t dev;
+ device_t busdev;
+ struct mtx mtx;
+ struct resource *portres;
+ int rid;
+ struct gpio_pin pins[NCT_MAX_PIN];
+};
+
+#define GPIO_LOCK_INIT(_sc) mtx_init(&(_sc)->mtx, \
+ device_get_nameunit(dev), NULL, MTX_DEF)
+#define GPIO_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->mtx)
+#define GPIO_LOCK(_sc) mtx_lock(&(_sc)->mtx)
+#define GPIO_UNLOCK(_sc) mtx_unlock(&(_sc)->mtx)
+#define GPIO_ASSERT_LOCKED(_sc) mtx_assert(&(_sc)->mtx, MA_OWNED)
+#define GPIO_ASSERT_UNLOCKED(_sc) mtx_assert(&(_sc)->mtx, MA_NOTOWNED)
+
+#define NCT_BARRIER_WRITE(_sc) \
+ bus_barrier((_sc)->portres, 0, 2, BUS_SPACE_BARRIER_WRITE)
+
+#define NCT_BARRIER_READ_WRITE(_sc) \
+ bus_barrier((_sc)->portres, 0, 2, \
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)
+
+static void ext_cfg_enter(struct nct_softc *);
+static void ext_cfg_exit(struct nct_softc *);
+
+/*
+ * Potential Extended Function Enable Register addresses.
+ * Same address as EFIR.
+ */
+uint8_t probe_addrs[] = {0x2e, 0x4e};
+
+struct nuvoton_vendor_device_id {
+ uint16_t chip_id;
+ const char * descr;
+} nct_devs[] = {
+ {
+ .chip_id = 0x1061,
+ .descr = "Nuvoton NCT5104D",
+ },
+ {
+ .chip_id = 0xc452,
+ .descr = "Nuvoton NCT5104D (PC-Engines APU)",
+ },
+};
+
+static void
+write_cfg_reg_1(struct nct_softc *sc, uint8_t reg, uint8_t value)
+{
+ GPIO_ASSERT_LOCKED(sc);
+ bus_write_1(sc->portres, 0, reg);
+ NCT_BARRIER_WRITE(sc);
+ bus_write_1(sc->portres, 1, value);
+ NCT_BARRIER_WRITE(sc);
+}
+
+static uint8_t
+read_cfg_reg_1(struct nct_softc *sc, uint8_t reg)
+{
+ uint8_t value;
+
+ GPIO_ASSERT_LOCKED(sc);
+ bus_write_1(sc->portres, 0, reg);
+ NCT_BARRIER_READ_WRITE(sc);
+ value = bus_read_1(sc->portres, 1);
+ NCT_BARRIER_READ_WRITE(sc);
+
+ return (value);
+}
+
+static uint16_t
+read_cfg_reg_2(struct nct_softc *sc, uint8_t reg)
+{
+ uint16_t value;
+
+ value = read_cfg_reg_1(sc, reg) << 8;
+ value |= read_cfg_reg_1(sc, reg + 1);
+
+ return (value);
+}
+
+/*
+ * Enable extended function mode.
+ *
+ */
+static void
+ext_cfg_enter(struct nct_softc *sc)
+{
+ GPIO_ASSERT_LOCKED(sc);
+ bus_write_1(sc->portres, 0, NCT_EXTFUNC_ENTER);
+ NCT_BARRIER_WRITE(sc);
+ bus_write_1(sc->portres, 0, NCT_EXTFUNC_ENTER);
+ NCT_BARRIER_WRITE(sc);
+}
+
+/*
+ * Disable extended function mode.
+ *
+ */
+static void
+ext_cfg_exit(struct nct_softc *sc)
+{
+ GPIO_ASSERT_LOCKED(sc);
+ bus_write_1(sc->portres, 0, NCT_EXTFUNC_EXIT);
+ NCT_BARRIER_WRITE(sc);
+}
+
+/*
+ * Select a Logical Device.
+ */
+static void
+select_ldn(struct nct_softc *sc, uint8_t ldn)
+{
+ write_cfg_reg_1(sc, NCT_CR_LDN, ldn);
+}
+
+/*
+ * Get the GPIO Input/Output register address
+ * for a pin.
+ */
+static uint8_t
+nct_ior_addr(uint32_t pin_num)
+{
+ uint8_t addr;
+
+ addr = NCT_LD7_GPIO0_IOR;
+ if (pin_num > 7)
+ addr = NCT_LD7_GPIO1_IOR;
+
+ return (addr);
+}
+
+/*
+ * Get the GPIO Data register address for a pin.
+ */
+static uint8_t
+nct_dat_addr(uint32_t pin_num)
+{
+ uint8_t addr;
+
+ addr = NCT_LD7_GPIO0_DAT;
+ if (pin_num > 7)
+ addr = NCT_LD7_GPIO1_DAT;
+
+ return (addr);
+}
+
+/*
+ * Get the GPIO Inversion register address
+ * for a pin.
+ */
+static uint8_t
+nct_inv_addr(uint32_t pin_num)
+{
+ uint8_t addr;
+
+ addr = NCT_LD7_GPIO0_INV;
+ if (pin_num > 7)
+ addr = NCT_LD7_GPIO1_INV;
+
+ return (addr);
+}
+
+/*
+ * Get the GPIO Output Configuration/Mode
+ * register address for a pin.
+ */
+static uint8_t
+nct_outcfg_addr(uint32_t pin_num)
+{
+ uint8_t addr;
+
+ addr = NCT_LDF_GPIO0_OUTCFG;
+ if (pin_num > 7)
+ addr = NCT_LDF_GPIO1_OUTCFG;
+
+ return (addr);
+}
+
+/*
+ * Set a pin to output mode.
+ */
+static void
+nct_set_pin_is_output(struct nct_softc *sc, uint32_t pin_num)
+{
+ uint8_t reg;
+ uint8_t ior;
+
+ reg = nct_ior_addr(pin_num);
+ select_ldn(sc, NCT_LDN_GPIO);
+ ior = read_cfg_reg_1(sc, reg);
+ ior &= ~(NCT_PIN_BIT(pin_num));
+ write_cfg_reg_1(sc, reg, ior);
+}
+
+/*
+ * Set a pin to input mode.
+ */
+static void
+nct_set_pin_is_input(struct nct_softc *sc, uint32_t pin_num)
+{
+ uint8_t reg;
+ uint8_t ior;
+
+ reg = nct_ior_addr(pin_num);
+ select_ldn(sc, NCT_LDN_GPIO);
+ ior = read_cfg_reg_1(sc, reg);
+ ior |= NCT_PIN_BIT(pin_num);
+ write_cfg_reg_1(sc, reg, ior);
+}
+
+/*
+ * Check whether a pin is configured as an input.
+ */
+static bool
+nct_pin_is_input(struct nct_softc *sc, uint32_t pin_num)
+{
+ uint8_t reg;
+ uint8_t ior;
+
+ reg = nct_ior_addr(pin_num);
+ select_ldn(sc, NCT_LDN_GPIO);
+ ior = read_cfg_reg_1(sc, reg);
+
+ return (ior & NCT_PIN_BIT(pin_num));
+}
+
+/*
+ * Write a value to an output pin.
+ */
+static void
+nct_write_pin(struct nct_softc *sc, uint32_t pin_num, uint8_t data)
+{
+ uint8_t reg;
+ uint8_t value;
+
+ reg = nct_dat_addr(pin_num);
+ select_ldn(sc, NCT_LDN_GPIO);
+ value = read_cfg_reg_1(sc, reg);
+ if (data)
+ value |= NCT_PIN_BIT(pin_num);
+ else
+ value &= ~(NCT_PIN_BIT(pin_num));
+
+ write_cfg_reg_1(sc, reg, value);
+}
+
+static bool
+nct_read_pin(struct nct_softc *sc, uint32_t pin_num)
+{
+ uint8_t reg;
+
+ reg = nct_dat_addr(pin_num);
+ select_ldn(sc, NCT_LDN_GPIO);
+
+ return (read_cfg_reg_1(sc, reg) & NCT_PIN_BIT(pin_num));
+}
+
+static void
+nct_set_pin_is_inverted(struct nct_softc *sc, uint32_t pin_num)
+{
+ uint8_t reg;
+ uint8_t inv;
+
+ reg = nct_inv_addr(pin_num);
+ select_ldn(sc, NCT_LDN_GPIO);
+ inv = read_cfg_reg_1(sc, reg);
+ inv |= (NCT_PIN_BIT(pin_num));
+ write_cfg_reg_1(sc, reg, inv);
+}
+
+static void
+nct_set_pin_not_inverted(struct nct_softc *sc, uint32_t pin_num)
+{
+ uint8_t reg;
+ uint8_t inv;
+
+ reg = nct_inv_addr(pin_num);
+ select_ldn(sc, NCT_LDN_GPIO);
+ inv = read_cfg_reg_1(sc, reg);
+ inv &= ~(NCT_PIN_BIT(pin_num));
+ write_cfg_reg_1(sc, reg, inv);
+}
+
+static bool
+nct_pin_is_inverted(struct nct_softc *sc, uint32_t pin_num)
+{
+ uint8_t reg;
+ uint8_t inv;
+
+ reg = nct_inv_addr(pin_num);
+ select_ldn(sc, NCT_LDN_GPIO);
+ inv = read_cfg_reg_1(sc, reg);
+
+ return (inv & NCT_PIN_BIT(pin_num));
+}
+
+static void
+nct_set_pin_opendrain(struct nct_softc *sc, uint32_t pin_num)
+{
+ uint8_t reg;
+ uint8_t outcfg;
+
+ reg = nct_outcfg_addr(pin_num);
+ select_ldn(sc, NCT_LDN_GPIO_MODE);
+ outcfg = read_cfg_reg_1(sc, reg);
+ outcfg |= (NCT_PIN_BIT(pin_num));
+ write_cfg_reg_1(sc, reg, outcfg);
+}
+
+static void
+nct_set_pin_pushpull(struct nct_softc *sc, uint32_t pin_num)
+{
+ uint8_t reg;
+ uint8_t outcfg;
+
+ reg = nct_outcfg_addr(pin_num);
+ select_ldn(sc, NCT_LDN_GPIO_MODE);
+ outcfg = read_cfg_reg_1(sc, reg);
+ outcfg &= ~(NCT_PIN_BIT(pin_num));
+ write_cfg_reg_1(sc, reg, outcfg);
+}
+
+static bool
+nct_pin_is_opendrain(struct nct_softc *sc, uint32_t pin_num)
+{
+ uint8_t reg;
+ uint8_t outcfg;
+
+ reg = nct_outcfg_addr(pin_num);
+ select_ldn(sc, NCT_LDN_GPIO_MODE);
+ outcfg = read_cfg_reg_1(sc, reg);
+
+ return (outcfg & NCT_PIN_BIT(pin_num));
+}
+
+static void
+nct_identify(driver_t *driver, device_t parent)
+{
+ if (device_find_child(parent, driver->name, 0) != NULL)
+ return;
+
+ BUS_ADD_CHILD(parent, 0, driver->name, 0);
+}
+
+static int
+nct_probe(device_t dev)
+{
+ int i, j;
+ int rc;
+ struct nct_softc *sc;
+ uint16_t chipid;
+
+ /* Make sure we do not claim some ISA PNP device. */
+ if (isa_get_logicalid(dev) != 0)
+ return (ENXIO);
+
+ sc = device_get_softc(dev);
+
+ for (i = 0; i < sizeof(probe_addrs) / sizeof(*probe_addrs); i++) {
+ sc->rid = 0;
+ sc->portres = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->rid,
+ probe_addrs[i], probe_addrs[i] + 1, 2, RF_ACTIVE);
+ if (sc->portres == NULL)
+ continue;
+
+ GPIO_LOCK_INIT(sc);
+
+ GPIO_ASSERT_UNLOCKED(sc);
+ GPIO_LOCK(sc);
+ ext_cfg_enter(sc);
+ chipid = read_cfg_reg_2(sc, NCT_CR_CHIP_ID);
+ ext_cfg_exit(sc);
+ GPIO_UNLOCK(sc);
+
+ GPIO_LOCK_DESTROY(sc);
+
+ bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, sc->portres);
+ bus_delete_resource(dev, SYS_RES_IOPORT, sc->rid);
+
+ for (j = 0; j < sizeof(nct_devs) / sizeof(*nct_devs); j++) {
+ if (chipid == nct_devs[j].chip_id) {
+ rc = bus_set_resource(dev, SYS_RES_IOPORT, 0, probe_addrs[i], 2);
+ if (rc != 0) {
+ device_printf(dev, "bus_set_resource failed for address 0x%02X\n", probe_addrs[i]);
+ continue;
+ }
+ device_set_desc(dev, nct_devs[j].descr);
+ return (BUS_PROBE_DEFAULT);
+ }
+ }
+ }
+ return (ENXIO);
+}
+
+static int
+nct_attach(device_t dev)
+{
+ struct nct_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+
+ sc->rid = 0;
+ sc->portres = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->rid,
+ 0ul, ~0ul, 2, RF_ACTIVE);
+ if (sc->portres == NULL) {
+ device_printf(dev, "cannot allocate ioport\n");
+ return (ENXIO);
+ }
+
+ GPIO_LOCK_INIT(sc);
+
+ GPIO_ASSERT_UNLOCKED(sc);
+ GPIO_LOCK(sc);
+ ext_cfg_enter(sc);
+ select_ldn(sc, NCT_LDN_GPIO);
+ /* Enable gpio0 and gpio1. */
+ write_cfg_reg_1(sc, NCT_LD7_GPIO_ENABLE,
+ read_cfg_reg_1(sc, NCT_LD7_GPIO_ENABLE) | 0x03);
+
+ for (i = 0; i <= NCT_MAX_PIN; i++) {
+ struct gpio_pin *pin;
+
+ pin = &sc->pins[i];
+ pin->gp_pin = i;
+ pin->gp_caps = NCT_GPIO_CAPS;
+ pin->gp_flags = 0;
+
+ snprintf(pin->gp_name, GPIOMAXNAME, "GPIO%02u", i);
+ pin->gp_name[GPIOMAXNAME - 1] = '\0';
+
+ if (nct_pin_is_input(sc, i))
+ pin->gp_flags |= GPIO_PIN_INPUT;
+ else
+ pin->gp_flags |= GPIO_PIN_OUTPUT;
+
+ if (nct_pin_is_opendrain(sc, i))
+ pin->gp_flags |= GPIO_PIN_OPENDRAIN;
+ else
+ pin->gp_flags |= GPIO_PIN_PUSHPULL;
+
+ if (nct_pin_is_inverted(sc, i))
+ pin->gp_flags |= (GPIO_PIN_INVIN | GPIO_PIN_INVOUT);
+ }
+ GPIO_UNLOCK(sc);
+
+ sc->busdev = gpiobus_attach_bus(dev);
+ if (sc->busdev == NULL) {
+ GPIO_ASSERT_UNLOCKED(sc);
+ GPIO_LOCK(sc);
+ ext_cfg_exit(sc);
+ GPIO_UNLOCK(sc);
+ bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, sc->portres);
+ GPIO_LOCK_DESTROY(sc);
+
+ return (ENXIO);
+ }
+
+ return (0);
+}
+
+static int
+nct_detach(device_t dev)
+{
+ struct nct_softc *sc;
+
+ sc = device_get_softc(dev);
+ gpiobus_detach_bus(dev);
+
+ GPIO_ASSERT_UNLOCKED(sc);
+ GPIO_LOCK(sc);
+ ext_cfg_exit(sc);
+ GPIO_UNLOCK(sc);
+
+ /* Cleanup resources. */
+ bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, sc->portres);
+
+ GPIO_LOCK_DESTROY(sc);
+
+ return (0);
+}
+
+static device_t
+nct_gpio_get_bus(device_t dev)
+{
+ struct nct_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ return (sc->busdev);
+}
+
+static int
+nct_gpio_pin_max(device_t dev, int *npins)
+{
+ *npins = NCT_MAX_PIN;
+
+ return (0);
+}
+
+static int
+nct_gpio_pin_set(device_t dev, uint32_t pin_num, uint32_t pin_value)
+{
+ struct nct_softc *sc;
+
+ if (!NCT_IS_VALID_PIN(pin_num))
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+ GPIO_ASSERT_UNLOCKED(sc);
+ GPIO_LOCK(sc);
+ nct_write_pin(sc, pin_num, pin_value);
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+nct_gpio_pin_get(device_t dev, uint32_t pin_num, uint32_t *pin_value)
+{
+ struct nct_softc *sc;
+
+ if (!NCT_IS_VALID_PIN(pin_num))
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+ GPIO_ASSERT_UNLOCKED(sc);
+ GPIO_LOCK(sc);
+ *pin_value = nct_read_pin(sc, pin_num);
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+nct_gpio_pin_toggle(device_t dev, uint32_t pin_num)
+{
+ struct nct_softc *sc;
+
+ if (!NCT_IS_VALID_PIN(pin_num))
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+ GPIO_ASSERT_UNLOCKED(sc);
+ GPIO_LOCK(sc);
+ if (nct_read_pin(sc, pin_num))
+ nct_write_pin(sc, pin_num, 0);
+ else
+ nct_write_pin(sc, pin_num, 1);
+
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+nct_gpio_pin_getcaps(device_t dev, uint32_t pin_num, uint32_t *caps)
+{
+ struct nct_softc *sc;
+
+ if (!NCT_IS_VALID_PIN(pin_num))
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+ GPIO_ASSERT_UNLOCKED(sc);
+ GPIO_LOCK(sc);
+ *caps = sc->pins[pin_num].gp_caps;
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+nct_gpio_pin_getflags(device_t dev, uint32_t pin_num, uint32_t *flags)
+{
+ struct nct_softc *sc;
+
+ if (!NCT_IS_VALID_PIN(pin_num))
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+ GPIO_ASSERT_UNLOCKED(sc);
+ GPIO_LOCK(sc);
+ *flags = sc->pins[pin_num].gp_flags;
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+nct_gpio_pin_getname(device_t dev, uint32_t pin_num, char *name)
+{
+ struct nct_softc *sc;
+
+ if (!NCT_IS_VALID_PIN(pin_num))
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+ GPIO_ASSERT_UNLOCKED(sc);
+ GPIO_LOCK(sc);
+ memcpy(name, sc->pins[pin_num].gp_name, GPIOMAXNAME);
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+nct_gpio_pin_setflags(device_t dev, uint32_t pin_num, uint32_t flags)
+{
+ struct nct_softc *sc;
+ struct gpio_pin *pin;
+
+ if (!NCT_IS_VALID_PIN(pin_num))
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+ pin = &sc->pins[pin_num];
+ if ((flags & pin->gp_caps) != flags)
+ return (EINVAL);
+
+ GPIO_ASSERT_UNLOCKED(sc);
+ GPIO_LOCK(sc);
+ if (flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) {
+ if ((flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) ==
+ (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) {
+ GPIO_UNLOCK(sc);
+ return (EINVAL);
+ }
+
+ if (flags & GPIO_PIN_INPUT)
+ nct_set_pin_is_input(sc, pin_num);
+ else
+ nct_set_pin_is_output(sc, pin_num);
+ }
+
+ if (flags & (GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)) {
+ if (flags & GPIO_PIN_INPUT) {
+ GPIO_UNLOCK(sc);
+ return (EINVAL);
+ }
+
+ if ((flags & (GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)) ==
+ (GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)) {
+ GPIO_UNLOCK(sc);
+ return (EINVAL);
+ }
+
+ if (flags & GPIO_PIN_OPENDRAIN)
+ nct_set_pin_opendrain(sc, pin_num);
+ else
+ nct_set_pin_pushpull(sc, pin_num);
+ }
+
+ if (flags & (GPIO_PIN_INVIN | GPIO_PIN_INVOUT)) {
+ if ((flags & (GPIO_PIN_INVIN | GPIO_PIN_INVOUT)) !=
+ (GPIO_PIN_INVIN | GPIO_PIN_INVOUT)) {
+ GPIO_UNLOCK(sc);
+ return (EINVAL);
+ }
+
+ if (flags & GPIO_PIN_INVIN)
+ nct_set_pin_is_inverted(sc, pin_num);
+ else
+ nct_set_pin_not_inverted(sc, pin_num);
+ }
+
+ pin->gp_flags = flags;
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static device_method_t nct_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_identify, nct_identify),
+ DEVMETHOD(device_probe, nct_probe),
+ DEVMETHOD(device_attach, nct_attach),
+ DEVMETHOD(device_detach, nct_detach),
+
+ /* GPIO */
+ DEVMETHOD(gpio_get_bus, nct_gpio_get_bus),
+ DEVMETHOD(gpio_pin_max, nct_gpio_pin_max),
+ DEVMETHOD(gpio_pin_get, nct_gpio_pin_get),
+ DEVMETHOD(gpio_pin_set, nct_gpio_pin_set),
+ DEVMETHOD(gpio_pin_toggle, nct_gpio_pin_toggle),
+ DEVMETHOD(gpio_pin_getname, nct_gpio_pin_getname),
+ DEVMETHOD(gpio_pin_getcaps, nct_gpio_pin_getcaps),
+ DEVMETHOD(gpio_pin_getflags, nct_gpio_pin_getflags),
+ DEVMETHOD(gpio_pin_setflags, nct_gpio_pin_setflags),
+
+ DEVMETHOD_END
+};
+
+static driver_t nct_isa_driver = {
+ "gpio",
+ nct_methods,
+ sizeof(struct nct_softc)
+};
+
+static devclass_t nct_devclass;
+
+DRIVER_MODULE(nctgpio, isa, nct_isa_driver, nct_devclass, NULL, NULL);
+MODULE_DEPEND(nctgpio, gpiobus, 1, 1, 1);
diff --git a/sys/dev/netmap/netmap_generic.c b/sys/dev/netmap/netmap_generic.c
index bc5b452..9129960 100644
--- a/sys/dev/netmap/netmap_generic.c
+++ b/sys/dev/netmap/netmap_generic.c
@@ -129,8 +129,9 @@ static inline struct mbuf *
netmap_get_mbuf(int len)
{
struct mbuf *m;
- m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR | M_NOFREE);
+ m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (m) {
+ m->m_flags |= M_NOFREE; /* XXXNP: Almost certainly incorrect. */
m->m_ext.ext_arg1 = m->m_ext.ext_buf; // XXX save
m->m_ext.ext_free = (void *)netmap_default_mbuf_destructor;
m->m_ext.ext_type = EXT_EXTREF;
diff --git a/sys/dev/oce/oce_if.c b/sys/dev/oce/oce_if.c
index f0cce5f..3704612 100644
--- a/sys/dev/oce/oce_if.c
+++ b/sys/dev/oce/oce_if.c
@@ -1497,16 +1497,12 @@ static void
oce_rx_flush_lro(struct oce_rq *rq)
{
struct lro_ctrl *lro = &rq->lro;
- struct lro_entry *queued;
POCE_SOFTC sc = (POCE_SOFTC) rq->parent;
if (!IF_LRO_ENABLED(sc))
return;
- while ((queued = SLIST_FIRST(&lro->lro_active)) != NULL) {
- SLIST_REMOVE_HEAD(&lro->lro_active, next);
- tcp_lro_flush(lro, queued);
- }
+ tcp_lro_flush_all(lro);
rq->lro_pkts_queued = 0;
return;
diff --git a/sys/dev/ofw/ofw_iicbus.c b/sys/dev/ofw/ofw_iicbus.c
index c0fa054..73cad7c 100644
--- a/sys/dev/ofw/ofw_iicbus.c
+++ b/sys/dev/ofw/ofw_iicbus.c
@@ -80,8 +80,10 @@ static devclass_t ofwiicbus_devclass;
DEFINE_CLASS_1(iicbus, ofw_iicbus_driver, ofw_iicbus_methods,
sizeof(struct iicbus_softc), iicbus_driver);
-DRIVER_MODULE(ofw_iicbus, iicbb, ofw_iicbus_driver, ofwiicbus_devclass, 0, 0);
-DRIVER_MODULE(ofw_iicbus, iichb, ofw_iicbus_driver, ofwiicbus_devclass, 0, 0);
+EARLY_DRIVER_MODULE(ofw_iicbus, iicbb, ofw_iicbus_driver, ofwiicbus_devclass,
+ 0, 0, BUS_PASS_BUS);
+EARLY_DRIVER_MODULE(ofw_iicbus, iichb, ofw_iicbus_driver, ofwiicbus_devclass,
+ 0, 0, BUS_PASS_BUS);
MODULE_VERSION(ofw_iicbus, 1);
MODULE_DEPEND(ofw_iicbus, iicbus, 1, 1, 1);
diff --git a/sys/dev/ofw/ofwbus.c b/sys/dev/ofw/ofwbus.c
index 8eb5dd5..fc43410 100644
--- a/sys/dev/ofw/ofwbus.c
+++ b/sys/dev/ofw/ofwbus.c
@@ -200,8 +200,8 @@ ofwbus_alloc_resource(device_t bus, device_t child, int type, int *rid,
return (NULL);
}
start = rle->start;
- count = ulmax(count, rle->count);
- end = ulmax(rle->end, start + count - 1);
+ count = ummax(count, rle->count);
+ end = ummax(rle->end, start + count - 1);
}
switch (type) {
diff --git a/sys/dev/ofw/ofwpci.c b/sys/dev/ofw/ofwpci.c
new file mode 100644
index 0000000..2872fe1
--- /dev/null
+++ b/sys/dev/ofw/ofwpci.c
@@ -0,0 +1,628 @@
+/*-
+ * 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/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/rman.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_pci.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/ofwpci.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+#include <machine/bus.h>
+#include <machine/md_var.h>
+#include <machine/resource.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include "pcib_if.h"
+
+/*
+ * If it is necessary to set another value of this for
+ * some platforms it should be set at fdt.h file
+ */
+#ifndef PCI_MAP_INTR
+#define PCI_MAP_INTR 4
+#endif
+
+#define PCI_INTR_PINS 4
+
+/*
+ * bus interface.
+ */
+static struct resource * ofw_pci_alloc_resource(device_t, device_t,
+ int, int *, rman_res_t, rman_res_t, rman_res_t, u_int);
+static int ofw_pci_release_resource(device_t, device_t, int, int,
+ struct resource *);
+static int ofw_pci_activate_resource(device_t, device_t, int, int,
+ struct resource *);
+static int ofw_pci_deactivate_resource(device_t, device_t, int, int,
+ struct resource *);
+static int ofw_pci_adjust_resource(device_t, device_t, int,
+ struct resource *, rman_res_t, rman_res_t);
+
+#ifdef __powerpc__
+static bus_space_tag_t ofw_pci_bus_get_bus_tag(device_t, device_t);
+#endif
+
+/*
+ * pcib interface
+ */
+static int ofw_pci_maxslots(device_t);
+
+/*
+ * ofw_bus interface
+ */
+static phandle_t ofw_pci_get_node(device_t, device_t);
+
+/*
+ * local methods
+ */
+static int ofw_pci_fill_ranges(phandle_t, struct ofw_pci_range *);
+
+/*
+ * Driver methods.
+ */
+static device_method_t ofw_pci_methods[] = {
+
+ /* Device interface */
+ DEVMETHOD(device_attach, ofw_pci_attach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_read_ivar, ofw_pci_read_ivar),
+ DEVMETHOD(bus_write_ivar, ofw_pci_write_ivar),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+ DEVMETHOD(bus_alloc_resource, ofw_pci_alloc_resource),
+ DEVMETHOD(bus_release_resource, ofw_pci_release_resource),
+ DEVMETHOD(bus_activate_resource, ofw_pci_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, ofw_pci_deactivate_resource),
+ DEVMETHOD(bus_adjust_resource, ofw_pci_adjust_resource),
+#ifdef __powerpc__
+ DEVMETHOD(bus_get_bus_tag, ofw_pci_bus_get_bus_tag),
+#endif
+
+ /* pcib interface */
+ DEVMETHOD(pcib_maxslots, ofw_pci_maxslots),
+ DEVMETHOD(pcib_route_interrupt, ofw_pci_route_interrupt),
+
+ /* ofw_bus interface */
+ DEVMETHOD(ofw_bus_get_node, ofw_pci_get_node),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(ofw_pci, ofw_pci_driver, ofw_pci_methods, 0);
+
+int
+ofw_pci_init(device_t dev)
+{
+ struct ofw_pci_softc *sc;
+ phandle_t node;
+ u_int32_t busrange[2];
+ struct ofw_pci_range *rp;
+ int error;
+ struct ofw_pci_cell_info *cell_info;
+
+ node = ofw_bus_get_node(dev);
+ sc = device_get_softc(dev);
+ sc->sc_initialized = 1;
+ sc->sc_range = NULL;
+
+ cell_info = (struct ofw_pci_cell_info *)malloc(sizeof(*cell_info),
+ M_DEVBUF, M_WAITOK | M_ZERO);
+
+ sc->sc_cell_info = cell_info;
+
+ if (OF_getencprop(node, "bus-range", busrange, sizeof(busrange)) != 8)
+ busrange[0] = 0;
+
+ sc->sc_dev = dev;
+ sc->sc_node = node;
+ sc->sc_bus = busrange[0];
+
+ if (sc->sc_quirks & OFW_PCI_QUIRK_RANGES_ON_CHILDREN) {
+ phandle_t c;
+ int n, i;
+
+ sc->sc_nrange = 0;
+ for (c = OF_child(node); c != 0; c = OF_peer(c)) {
+ n = ofw_pci_nranges(c, cell_info);
+ if (n > 0)
+ sc->sc_nrange += n;
+ }
+ if (sc->sc_nrange == 0) {
+ error = ENXIO;
+ goto out;
+ }
+ sc->sc_range = malloc(sc->sc_nrange * sizeof(sc->sc_range[0]),
+ M_DEVBUF, M_WAITOK);
+ i = 0;
+ for (c = OF_child(node); c != 0; c = OF_peer(c)) {
+ n = ofw_pci_fill_ranges(c, &sc->sc_range[i]);
+ if (n > 0)
+ i += n;
+ }
+ KASSERT(i == sc->sc_nrange, ("range count mismatch"));
+ } else {
+ sc->sc_nrange = ofw_pci_nranges(node, cell_info);
+ if (sc->sc_nrange <= 0) {
+ device_printf(dev, "could not getranges\n");
+ error = ENXIO;
+ goto out;
+ }
+ sc->sc_range = malloc(sc->sc_nrange * sizeof(sc->sc_range[0]),
+ M_DEVBUF, M_WAITOK);
+ ofw_pci_fill_ranges(node, sc->sc_range);
+ }
+
+ sc->sc_io_rman.rm_type = RMAN_ARRAY;
+ sc->sc_io_rman.rm_descr = "PCI I/O Ports";
+ error = rman_init(&sc->sc_io_rman);
+ if (error) {
+ device_printf(dev, "rman_init() failed. error = %d\n", error);
+ goto out;
+ }
+
+ sc->sc_mem_rman.rm_type = RMAN_ARRAY;
+ sc->sc_mem_rman.rm_descr = "PCI Memory";
+ error = rman_init(&sc->sc_mem_rman);
+ if (error) {
+ device_printf(dev, "rman_init() failed. error = %d\n", error);
+ goto out;
+ }
+
+ for (rp = sc->sc_range; rp < sc->sc_range + sc->sc_nrange &&
+ rp->pci_hi != 0; rp++) {
+ error = 0;
+
+ switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
+ case OFW_PCI_PHYS_HI_SPACE_CONFIG:
+ break;
+ case OFW_PCI_PHYS_HI_SPACE_IO:
+ error = rman_manage_region(&sc->sc_io_rman, rp->pci,
+ rp->pci + rp->size - 1);
+ break;
+ case OFW_PCI_PHYS_HI_SPACE_MEM32:
+ case OFW_PCI_PHYS_HI_SPACE_MEM64:
+ error = rman_manage_region(&sc->sc_mem_rman, rp->pci,
+ rp->pci + rp->size - 1);
+ break;
+ }
+
+ if (error) {
+ device_printf(dev,
+ "rman_manage_region(%x, %#jx, %#jx) failed. "
+ "error = %d\n", rp->pci_hi &
+ OFW_PCI_PHYS_HI_SPACEMASK, rp->pci,
+ rp->pci + rp->size - 1, error);
+ goto out;
+ }
+ }
+
+ ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(cell_t));
+ return (0);
+
+out:
+ free(cell_info, M_DEVBUF);
+ free(sc->sc_range, M_DEVBUF);
+ rman_fini(&sc->sc_io_rman);
+ rman_fini(&sc->sc_mem_rman);
+
+ return (error);
+}
+
+int
+ofw_pci_attach(device_t dev)
+{
+ struct ofw_pci_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+ if (!sc->sc_initialized) {
+ error = ofw_pci_init(dev);
+ if (error)
+ return (error);
+ }
+
+ device_add_child(dev, "pci", -1);
+ return (bus_generic_attach(dev));
+}
+
+static int
+ofw_pci_maxslots(device_t dev)
+{
+
+ return (PCI_SLOTMAX);
+}
+
+int
+ofw_pci_route_interrupt(device_t bus, device_t dev, int pin)
+{
+ struct ofw_pci_softc *sc;
+ struct ofw_pci_register reg;
+ uint32_t pintr, mintr[PCI_MAP_INTR];
+ int intrcells;
+ phandle_t iparent;
+
+ sc = device_get_softc(bus);
+ pintr = pin;
+
+ /* Fabricate imap information in case this isn't an OFW device */
+ bzero(&reg, sizeof(reg));
+ reg.phys_hi = (pci_get_bus(dev) << OFW_PCI_PHYS_HI_BUSSHIFT) |
+ (pci_get_slot(dev) << OFW_PCI_PHYS_HI_DEVICESHIFT) |
+ (pci_get_function(dev) << OFW_PCI_PHYS_HI_FUNCTIONSHIFT);
+
+ intrcells = ofw_bus_lookup_imap(ofw_bus_get_node(dev),
+ &sc->sc_pci_iinfo, &reg, sizeof(reg), &pintr, sizeof(pintr),
+ mintr, sizeof(mintr), &iparent);
+ if (intrcells != 0) {
+ pintr = ofw_bus_map_intr(dev, iparent, intrcells, mintr);
+ return (pintr);
+ }
+
+ /*
+ * Maybe it's a real interrupt, not an intpin
+ */
+ if (pin > PCI_INTR_PINS)
+ return (pin);
+
+ device_printf(bus, "could not route pin %d for device %d.%d\n",
+ pin, pci_get_slot(dev), pci_get_function(dev));
+ return (PCI_INVALID_IRQ);
+}
+
+int
+ofw_pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+ struct ofw_pci_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ switch (which) {
+ case PCIB_IVAR_DOMAIN:
+ *result = device_get_unit(dev);
+ return (0);
+ case PCIB_IVAR_BUS:
+ *result = sc->sc_bus;
+ return (0);
+ default:
+ break;
+ }
+
+ return (ENOENT);
+}
+
+int
+ofw_pci_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
+{
+ struct ofw_pci_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ switch (which) {
+ case PCIB_IVAR_BUS:
+ sc->sc_bus = value;
+ return (0);
+ default:
+ break;
+ }
+
+ return (ENOENT);
+}
+
+int
+ofw_pci_nranges(phandle_t node, struct ofw_pci_cell_info *info)
+{
+ ssize_t nbase_ranges;
+
+ if (info == NULL)
+ return (-1);
+
+ info->host_address_cells = 1;
+ info->size_cells = 2;
+ info->pci_address_cell = 3;
+
+ OF_getencprop(OF_parent(node), "#address-cells",
+ &(info->host_address_cells), sizeof(info->host_address_cells));
+ OF_getencprop(node, "#address-cells",
+ &(info->pci_address_cell), sizeof(info->pci_address_cell));
+ OF_getencprop(node, "#size-cells", &(info->size_cells),
+ sizeof(info->size_cells));
+
+ nbase_ranges = OF_getproplen(node, "ranges");
+ if (nbase_ranges <= 0)
+ return (-1);
+
+ return (nbase_ranges / sizeof(cell_t) /
+ (info->pci_address_cell + info->host_address_cells +
+ info->size_cells));
+}
+
+static struct resource *
+ofw_pci_alloc_resource(device_t bus, device_t child, int type, int *rid,
+ rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
+{
+ struct ofw_pci_softc *sc;
+ struct resource *rv;
+ struct rman *rm;
+ int needactivate;
+
+ needactivate = flags & RF_ACTIVE;
+ flags &= ~RF_ACTIVE;
+
+ sc = device_get_softc(bus);
+
+ switch (type) {
+ case SYS_RES_MEMORY:
+ rm = &sc->sc_mem_rman;
+ break;
+
+ case SYS_RES_IOPORT:
+ rm = &sc->sc_io_rman;
+ break;
+
+ case SYS_RES_IRQ:
+ return (bus_alloc_resource(bus, type, rid, start, end, count,
+ flags));
+
+ default:
+ device_printf(bus, "unknown resource request from %s\n",
+ device_get_nameunit(child));
+ return (NULL);
+ }
+
+ rv = rman_reserve_resource(rm, start, end, count, flags, child);
+ if (rv == NULL) {
+ device_printf(bus, "failed to reserve resource for %s\n",
+ device_get_nameunit(child));
+ return (NULL);
+ }
+
+ rman_set_rid(rv, *rid);
+
+ if (needactivate) {
+ if (bus_activate_resource(child, type, *rid, rv) != 0) {
+ device_printf(bus,
+ "failed to activate resource for %s\n",
+ device_get_nameunit(child));
+ rman_release_resource(rv);
+ return (NULL);
+ }
+ }
+
+ return (rv);
+}
+
+static int
+ofw_pci_release_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *res)
+{
+
+ if (rman_get_flags(res) & RF_ACTIVE) {
+ int error = bus_deactivate_resource(child, type, rid, res);
+ if (error)
+ return error;
+ }
+
+ return (rman_release_resource(res));
+}
+
+static int
+ofw_pci_activate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *res)
+{
+ struct ofw_pci_softc *sc;
+ bus_space_handle_t handle;
+ bus_space_tag_t tag;
+ int rv;
+
+ sc = device_get_softc(bus);
+
+ if (type == SYS_RES_IRQ) {
+ return (bus_activate_resource(bus, type, rid, res));
+ }
+ if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
+ struct ofw_pci_range *rp;
+ vm_paddr_t start;
+ int space;
+
+ start = (vm_paddr_t)rman_get_start(res);
+
+ /*
+ * Map this through the ranges list
+ */
+ for (rp = sc->sc_range; rp < sc->sc_range + sc->sc_nrange &&
+ rp->pci_hi != 0; rp++) {
+ if (start < rp->pci || start >= rp->pci + rp->size)
+ continue;
+
+ switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
+ case OFW_PCI_PHYS_HI_SPACE_IO:
+ space = SYS_RES_IOPORT;
+ break;
+ case OFW_PCI_PHYS_HI_SPACE_MEM32:
+ case OFW_PCI_PHYS_HI_SPACE_MEM64:
+ space = SYS_RES_MEMORY;
+ break;
+ default:
+ space = -1;
+ }
+
+ if (type == space) {
+ start += (rp->host - rp->pci);
+ break;
+ }
+ }
+
+ if (bootverbose)
+ printf("ofw_pci mapdev: start %jx, len %jd\n",
+ (rman_res_t)start, rman_get_size(res));
+
+ tag = BUS_GET_BUS_TAG(child, child);
+ if (tag == NULL)
+ return (ENOMEM);
+
+ rman_set_bustag(res, tag);
+ rv = bus_space_map(tag, start,
+ rman_get_size(res), 0, &handle);
+ if (rv != 0)
+ return (ENOMEM);
+
+ rman_set_bushandle(res, handle);
+ rman_set_virtual(res, (void *)handle); /* XXX for powerpc only ? */
+ }
+
+ return (rman_activate_resource(res));
+}
+
+#ifdef __powerpc__
+static bus_space_tag_t
+ofw_pci_bus_get_bus_tag(device_t bus, device_t child)
+{
+
+ return (&bs_le_tag);
+}
+#endif
+
+static int
+ofw_pci_deactivate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *res)
+{
+
+ /*
+ * If this is a memory resource, unmap it.
+ */
+ if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) {
+ u_int32_t psize;
+
+ psize = rman_get_size(res);
+ pmap_unmapdev((vm_offset_t)rman_get_virtual(res), psize);
+ }
+
+ return (rman_deactivate_resource(res));
+}
+
+static int
+ofw_pci_adjust_resource(device_t bus, device_t child, int type,
+ struct resource *res, rman_res_t start, rman_res_t end)
+{
+ struct rman *rm = NULL;
+ struct ofw_pci_softc *sc = device_get_softc(bus);
+
+ KASSERT(!(rman_get_flags(res) & RF_ACTIVE),
+ ("active resources cannot be adjusted"));
+ if (rman_get_flags(res) & RF_ACTIVE)
+ return (EINVAL);
+
+ switch (type) {
+ case SYS_RES_MEMORY:
+ rm = &sc->sc_mem_rman;
+ break;
+ case SYS_RES_IOPORT:
+ rm = &sc->sc_io_rman;
+ break;
+ default:
+ return (ENXIO);
+ }
+
+ if (!rman_is_region_manager(res, rm))
+ return (EINVAL);
+
+ return (rman_adjust_resource(res, start, end));
+}
+
+static phandle_t
+ofw_pci_get_node(device_t bus, device_t dev)
+{
+ struct ofw_pci_softc *sc;
+
+ sc = device_get_softc(bus);
+ /* We only have one child, the PCI bus, which needs our own node. */
+
+ return (sc->sc_node);
+}
+
+static int
+ofw_pci_fill_ranges(phandle_t node, struct ofw_pci_range *ranges)
+{
+ int host_address_cells = 1, pci_address_cells = 3, size_cells = 2;
+ cell_t *base_ranges;
+ ssize_t nbase_ranges;
+ int nranges;
+ int i, j, k;
+
+ OF_getencprop(OF_parent(node), "#address-cells", &host_address_cells,
+ sizeof(host_address_cells));
+ OF_getencprop(node, "#address-cells", &pci_address_cells,
+ sizeof(pci_address_cells));
+ OF_getencprop(node, "#size-cells", &size_cells, sizeof(size_cells));
+
+ nbase_ranges = OF_getproplen(node, "ranges");
+ if (nbase_ranges <= 0)
+ return (-1);
+ nranges = nbase_ranges / sizeof(cell_t) /
+ (pci_address_cells + host_address_cells + size_cells);
+
+ base_ranges = malloc(nbase_ranges, M_DEVBUF, M_WAITOK);
+ OF_getencprop(node, "ranges", base_ranges, nbase_ranges);
+
+ for (i = 0, j = 0; i < nranges; i++) {
+ ranges[i].pci_hi = base_ranges[j++];
+ ranges[i].pci = 0;
+ for (k = 0; k < pci_address_cells - 1; k++) {
+ ranges[i].pci <<= 32;
+ ranges[i].pci |= base_ranges[j++];
+ }
+ ranges[i].host = 0;
+ for (k = 0; k < host_address_cells; k++) {
+ ranges[i].host <<= 32;
+ ranges[i].host |= base_ranges[j++];
+ }
+ ranges[i].size = 0;
+ for (k = 0; k < size_cells; k++) {
+ ranges[i].size <<= 32;
+ ranges[i].size |= base_ranges[j++];
+ }
+ }
+
+ free(base_ranges, M_DEVBUF);
+ return (nranges);
+}
diff --git a/sys/dev/ofw/ofwpci.h b/sys/dev/ofw/ofwpci.h
new file mode 100644
index 0000000..e9825ad
--- /dev/null
+++ b/sys/dev/ofw/ofwpci.h
@@ -0,0 +1,83 @@
+/*-
+ * 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 _DEV_OFW_OFWPCI_H_
+#define _DEV_OFW_OFWPCI_H_
+
+/*
+ * Export class definition for inheritance purposes
+ */
+DECLARE_CLASS(ofw_pci_driver);
+
+struct ofw_pci_cell_info {
+ pcell_t host_address_cells;
+ pcell_t pci_address_cell;
+ pcell_t size_cells;
+ };
+
+struct ofw_pci_range {
+ uint32_t pci_hi;
+ uint64_t pci;
+ uint64_t host;
+ uint64_t size;
+};
+
+/*
+ * Quirks for some adapters
+ */
+enum {
+ OFW_PCI_QUIRK_RANGES_ON_CHILDREN = 1,
+};
+
+struct ofw_pci_softc {
+ device_t sc_dev;
+ phandle_t sc_node;
+ int sc_bus;
+ int sc_initialized;
+ int sc_quirks;
+
+ struct ofw_pci_range *sc_range;
+ int sc_nrange;
+ struct ofw_pci_cell_info *sc_cell_info;
+
+ struct rman sc_io_rman;
+ struct rman sc_mem_rman;
+ bus_space_tag_t sc_memt;
+ bus_dma_tag_t sc_dmat;
+
+ struct ofw_bus_iinfo sc_pci_iinfo;
+};
+
+int ofw_pci_init(device_t);
+int ofw_pci_attach(device_t);
+int ofw_pci_read_ivar(device_t, device_t, int, uintptr_t *);
+int ofw_pci_write_ivar(device_t, device_t, int, uintptr_t);
+int ofw_pci_route_interrupt(device_t, device_t, int);
+int ofw_pci_nranges(phandle_t, struct ofw_pci_cell_info *);
+
+#endif /* _DEV_OFW_OFWPCI_H_ */
diff --git a/sys/dev/pccard/pccard.c b/sys/dev/pccard/pccard.c
index 0681242..04dcc44 100644
--- a/sys/dev/pccard/pccard.c
+++ b/sys/dev/pccard/pccard.c
@@ -507,7 +507,7 @@ pccard_function_init(struct pccard_function *pf, int entry)
end = start + ios->length - 1;
else
end = ~0;
- DEVPRINTF((bus, "I/O rid %d start %#lx end %#lx\n",
+ DEVPRINTF((bus, "I/O rid %d start %#jx end %#jx\n",
i, start, end));
rid = i;
len = ios->length;
@@ -531,7 +531,7 @@ pccard_function_init(struct pccard_function *pf, int entry)
end = start + mems->length - 1;
else
end = ~0;
- DEVPRINTF((bus, "Memory rid %d start %#lx end %#lx\ncardaddr %#lx hostaddr %#lx length %#lx\n",
+ DEVPRINTF((bus, "Memory rid %d start %#jx end %#jx\ncardaddr %#jx hostaddr %#jx length %#jx\n",
i, start, end, mems->cardaddr, mems->hostaddr,
mems->length));
rid = i;
@@ -602,7 +602,7 @@ pccard_function_free(struct pccard_function *pf)
device_printf(pf->sc->dev,
"function_free: Resource still owned by "
"child, oops. "
- "(type=%d, rid=%d, addr=%#lx)\n",
+ "(type=%d, rid=%d, addr=%#jx)\n",
rle->type, rle->rid,
rman_get_start(rle->res));
BUS_RELEASE_RESOURCE(device_get_parent(pf->sc->dev),
@@ -697,7 +697,7 @@ pccard_function_enable(struct pccard_function *pf)
&pf->ccr_rid, PCCARD_MEM_PAGE_SIZE, RF_ACTIVE);
if (!pf->ccr_res)
goto bad;
- DEVPRINTF((dev, "ccr_res == %#lx-%#lx, base=%#x\n",
+ DEVPRINTF((dev, "ccr_res == %#jx-%#jx, base=%#x\n",
rman_get_start(pf->ccr_res), rman_get_end(pf->ccr_res),
pf->ccr_base));
CARD_SET_RES_FLAGS(device_get_parent(dev), dev, SYS_RES_MEMORY,
@@ -1025,26 +1025,6 @@ pccard_child_location_str(device_t bus, device_t child, char *buf,
return (0);
}
-/* XXX Maybe this should be in subr_bus? */
-static void
-pccard_safe_quote(char *dst, const char *src, size_t len)
-{
- char *walker = dst, *ep = dst + len - 1;
-
- if (len == 0)
- return;
- while (src != NULL && walker < ep)
- {
- if (*src == '"') {
- if (ep - walker < 2)
- break;
- *walker++ = '\\';
- }
- *walker++ = *src++;
- }
- *walker = '\0';
-}
-
static int
pccard_child_pnpinfo_str(device_t bus, device_t child, char *buf,
size_t buflen)
@@ -1054,8 +1034,8 @@ pccard_child_pnpinfo_str(device_t bus, device_t child, char *buf,
struct pccard_softc *sc = PCCARD_SOFTC(bus);
char cis0[128], cis1[128];
- pccard_safe_quote(cis0, sc->card.cis1_info[0], sizeof(cis0));
- pccard_safe_quote(cis1, sc->card.cis1_info[1], sizeof(cis1));
+ devctl_safe_quote(cis0, sc->card.cis1_info[0], sizeof(cis0));
+ devctl_safe_quote(cis1, sc->card.cis1_info[1], sizeof(cis1));
snprintf(buf, buflen, "manufacturer=0x%04x product=0x%04x "
"cisvendor=\"%s\" cisproduct=\"%s\" function_type=%d",
sc->card.manufacturer, sc->card.product, cis0, cis1, pf->function);
@@ -1197,7 +1177,7 @@ pccard_release_resource(device_t dev, device_t child, int type, int rid,
if (!rle) {
device_printf(dev, "Allocated resource not found, "
- "%d %#x %#lx %#lx\n",
+ "%d %#x %#jx %#jx\n",
type, rid, rman_get_start(r), rman_get_size(r));
return ENOENT;
}
diff --git a/sys/dev/pccard/pccard_cis.c b/sys/dev/pccard/pccard_cis.c
index 4bd06b5..4bd5e77 100644
--- a/sys/dev/pccard/pccard_cis.c
+++ b/sys/dev/pccard/pccard_cis.c
@@ -151,7 +151,7 @@ pccard_scan_cis(device_t bus, device_t dev, pccard_scan_t fct, void *arg)
tuple.memh = rman_get_bushandle(res);
tuple.ptr = 0;
- DPRINTF(("cis mem map %#x (resource: %#lx)\n",
+ DPRINTF(("cis mem map %#x (resource: %#jx)\n",
(unsigned int) tuple.memh, rman_get_start(res)));
tuple.mult = 2;
@@ -576,9 +576,9 @@ pccard_print_cis(device_t dev)
printf("; iomask %#lx, iospace", cfe->iomask);
for (i = 0; i < cfe->num_iospace; i++) {
- printf(" %#lx", cfe->iospace[i].start);
+ printf(" %#jx", cfe->iospace[i].start);
if (cfe->iospace[i].length)
- printf("-%#lx",
+ printf("-%#jx",
cfe->iospace[i].start +
cfe->iospace[i].length - 1);
}
@@ -587,14 +587,14 @@ pccard_print_cis(device_t dev)
printf("; memspace");
for (i = 0; i < cfe->num_memspace; i++) {
- printf(" %#lx",
+ printf(" %#jx",
cfe->memspace[i].cardaddr);
if (cfe->memspace[i].length)
- printf("-%#lx",
+ printf("-%#jx",
cfe->memspace[i].cardaddr +
cfe->memspace[i].length - 1);
if (cfe->memspace[i].hostaddr)
- printf("@%#lx",
+ printf("@%#jx",
cfe->memspace[i].hostaddr);
}
}
diff --git a/sys/dev/pccbb/pccbb.c b/sys/dev/pccbb/pccbb.c
index 9398771..067aa5a 100644
--- a/sys/dev/pccbb/pccbb.c
+++ b/sys/dev/pccbb/pccbb.c
@@ -229,7 +229,7 @@ cbb_destroy_res(struct cbb_softc *sc)
while ((rle = SLIST_FIRST(&sc->rl)) != NULL) {
device_printf(sc->dev, "Danger Will Robinson: Resource "
"left allocated! This is a bug... "
- "(rid=%x, type=%d, addr=%lx)\n", rle->rid, rle->type,
+ "(rid=%x, type=%d, addr=%jx)\n", rle->rid, rle->type,
rman_get_start(rle->res));
SLIST_REMOVE_HEAD(&sc->rl, link);
free(rle, M_DEVBUF);
@@ -1241,8 +1241,8 @@ cbb_cardbus_alloc_resource(device_t brdev, device_t child, int type,
case SYS_RES_IRQ:
tmp = rman_get_start(sc->irq_res);
if (start > tmp || end < tmp || count != 1) {
- device_printf(child, "requested interrupt %ld-%ld,"
- "count = %ld not supported by cbb\n",
+ device_printf(child, "requested interrupt %jd-%jd,"
+ "count = %jd not supported by cbb\n",
start, end, count);
return (NULL);
}
@@ -1425,8 +1425,8 @@ cbb_pcic_alloc_resource(device_t brdev, device_t child, int type, int *rid,
case SYS_RES_IRQ:
tmp = rman_get_start(sc->irq_res);
if (start > tmp || end < tmp || count != 1) {
- device_printf(child, "requested interrupt %ld-%ld,"
- "count = %ld not supported by cbb\n",
+ device_printf(child, "requested interrupt %jd-%jd,"
+ "count = %jd not supported by cbb\n",
start, end, count);
return (NULL);
}
diff --git a/sys/dev/pccbb/pccbb_pci.c b/sys/dev/pccbb/pccbb_pci.c
index e739027..4ec8d9b 100644
--- a/sys/dev/pccbb/pccbb_pci.c
+++ b/sys/dev/pccbb/pccbb_pci.c
@@ -313,7 +313,7 @@ cbb_pci_attach(device_t brdev)
mtx_destroy(&sc->mtx);
return (ENOMEM);
} else {
- DEVPRINTF((brdev, "Found memory at %08lx\n",
+ DEVPRINTF((brdev, "Found memory at %jx\n",
rman_get_start(sc->base_res)));
}
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index 492efe0..8343181 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -1643,7 +1643,7 @@ pci_alloc_msix_method(device_t dev, device_t child, int *count)
if (bootverbose) {
rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, 1);
if (actual == 1)
- device_printf(child, "using IRQ %lu for MSI-X\n",
+ device_printf(child, "using IRQ %ju for MSI-X\n",
rle->start);
else {
int run;
@@ -1653,7 +1653,7 @@ pci_alloc_msix_method(device_t dev, device_t child, int *count)
* IRQ values as ranges. 'irq' is the previous IRQ.
* 'run' is true if we are in a range.
*/
- device_printf(child, "using IRQs %lu", rle->start);
+ device_printf(child, "using IRQs %ju", rle->start);
irq = rle->start;
run = 0;
for (i = 1; i < actual; i++) {
@@ -1674,7 +1674,7 @@ pci_alloc_msix_method(device_t dev, device_t child, int *count)
}
/* Start new range. */
- printf(",%lu", rle->start);
+ printf(",%ju", rle->start);
irq = rle->start;
}
@@ -3572,13 +3572,13 @@ pci_alloc_secbus(device_t dev, device_t child, int *rid, rman_res_t start,
start, end, count, flags & ~RF_ACTIVE);
if (res == NULL) {
resource_list_delete(rl, PCI_RES_BUS, *rid);
- device_printf(child, "allocating %lu bus%s failed\n",
+ device_printf(child, "allocating %ju bus%s failed\n",
count, count == 1 ? "" : "es");
return (NULL);
}
if (bootverbose)
device_printf(child,
- "Lazy allocation of %lu bus%s at %lu\n", count,
+ "Lazy allocation of %ju bus%s at %ju\n", count,
count == 1 ? "" : "es", rman_get_start(res));
PCI_WRITE_CONFIG(dev, child, sec_reg, rman_get_start(res), 1);
PCI_WRITE_CONFIG(dev, child, sub_reg, rman_get_end(res), 1);
@@ -4391,9 +4391,9 @@ pci_print_child(device_t dev, device_t child)
retval += bus_print_child_header(dev, child);
- retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx");
- retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
- retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+ retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#jx");
+ retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
+ retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
if (device_get_flags(dev))
retval += printf(" flags %#x", device_get_flags(dev));
@@ -4971,13 +4971,13 @@ pci_reserve_map(device_t dev, device_t child, int type, int *rid,
if (res == NULL) {
resource_list_delete(rl, type, *rid);
device_printf(child,
- "%#lx bytes of rid %#x res %d failed (%#lx, %#lx).\n",
+ "%#jx bytes of rid %#x res %d failed (%#jx, %#jx).\n",
count, *rid, type, start, end);
goto out;
}
if (bootverbose)
device_printf(child,
- "Lazy allocation of %#lx bytes rid %#x type %d at %#lx\n",
+ "Lazy allocation of %#jx bytes rid %#x type %d at %#jx\n",
count, *rid, type, rman_get_start(res));
map = rman_get_start(res);
pci_write_bar(child, pm, map);
@@ -5254,7 +5254,7 @@ pci_delete_resource(device_t dev, device_t child, int type, int rid)
resource_list_busy(rl, type, rid)) {
device_printf(dev, "delete_resource: "
"Resource still owned by child, oops. "
- "(type=%d, rid=%d, addr=%lx)\n",
+ "(type=%d, rid=%d, addr=%jx)\n",
type, rid, rman_get_start(rle->res));
return;
}
diff --git a/sys/dev/pci/pci_host_generic.c b/sys/dev/pci/pci_host_generic.c
index f0c8d45..110ee68 100644
--- a/sys/dev/pci/pci_host_generic.c
+++ b/sys/dev/pci/pci_host_generic.c
@@ -540,7 +540,7 @@ generic_pcie_alloc_resource_pcie(device_t dev, device_t child, int type, int *ri
if (bootverbose) {
device_printf(dev,
- "rman_reserve_resource: start=%#lx, end=%#lx, count=%#lx\n",
+ "rman_reserve_resource: start=%#jx, end=%#jx, count=%#jx\n",
start, end, count);
}
@@ -560,7 +560,7 @@ generic_pcie_alloc_resource_pcie(device_t dev, device_t child, int type, int *ri
fail:
device_printf(dev, "%s FAIL: type=%d, rid=%d, "
- "start=%016lx, end=%016lx, count=%016lx, flags=%x\n",
+ "start=%016jx, end=%016jx, count=%016jx, flags=%x\n",
__func__, type, *rid, start, end, count, flags);
return (NULL);
@@ -744,7 +744,7 @@ generic_pcie_alloc_resource_ofw(device_t bus, device_t child, int type, int *rid
if (i == MAX_RANGES_TUPLES) {
device_printf(bus, "Could not map resource "
- "%#lx-%#lx\n", start, end);
+ "%#jx-%#jx\n", start, end);
return (NULL);
}
}
diff --git a/sys/dev/pci/pci_pci.c b/sys/dev/pci/pci_pci.c
index 24f9b3a..112b198 100644
--- a/sys/dev/pci/pci_pci.c
+++ b/sys/dev/pci/pci_pci.c
@@ -247,7 +247,7 @@ pcib_is_isa_range(struct pcib_softc *sc, rman_res_t start, rman_res_t end,
alias:
if (bootverbose)
device_printf(sc->dev,
- "I/O range %#lx-%#lx overlaps with an ISA alias\n", start,
+ "I/O range %#jx-%#jx overlaps with an ISA alias\n", start,
end);
return (1);
}
@@ -339,7 +339,7 @@ alloc_ranges(rman_res_t start, rman_res_t end, void *arg)
rid = w->reg;
if (bootverbose)
device_printf(as->sc->dev,
- "allocating non-ISA range %#lx-%#lx\n", start, end);
+ "allocating non-ISA range %#jx-%#jx\n", start, end);
as->res[as->count] = bus_alloc_resource(as->sc->dev, SYS_RES_IOPORT,
&rid, start, end, end - start + 1, 0);
if (as->res[as->count] == NULL)
@@ -621,7 +621,7 @@ pcib_suballoc_bus(struct pcib_secbus *bus, device_t child, int *rid,
if (bootverbose)
device_printf(bus->dev,
- "allocated bus range (%lu-%lu) for rid %d of %s\n",
+ "allocated bus range (%ju-%ju) for rid %d of %s\n",
rman_get_start(res), rman_get_end(res), *rid,
pcib_child_name(child));
rman_set_rid(res, *rid);
@@ -646,7 +646,7 @@ pcib_grow_subbus(struct pcib_secbus *bus, rman_res_t new_end)
if (error)
return (error);
if (bootverbose)
- device_printf(bus->dev, "grew bus range to %lu-%lu\n",
+ device_printf(bus->dev, "grew bus range to %ju-%ju\n",
rman_get_start(bus->res), rman_get_end(bus->res));
error = rman_manage_region(&bus->rman, old_end + 1,
rman_get_end(bus->res));
@@ -694,8 +694,8 @@ pcib_alloc_subbus(struct pcib_secbus *bus, device_t child, int *rid,
/* Finally, attempt to grow the existing resource. */
if (bootverbose) {
device_printf(bus->dev,
- "attempting to grow bus range for %lu buses\n", count);
- printf("\tback candidate range: %lu-%lu\n", start_free,
+ "attempting to grow bus range for %ju buses\n", count);
+ printf("\tback candidate range: %ju-%ju\n", start_free,
new_end);
}
if (pcib_grow_subbus(bus, new_end) == 0)
@@ -1174,7 +1174,7 @@ pcib_suballoc_resource(struct pcib_softc *sc, struct pcib_window *w,
if (bootverbose)
device_printf(sc->dev,
- "allocated %s range (%#lx-%#lx) for rid %x of %s\n",
+ "allocated %s range (%#jx-%#jx) for rid %x of %s\n",
w->name, rman_get_start(res), rman_get_end(res), *rid,
pcib_child_name(child));
rman_set_rid(res, *rid);
@@ -1401,7 +1401,7 @@ pcib_grow_window(struct pcib_softc *sc, struct pcib_window *w, int type,
if (error) {
if (bootverbose)
device_printf(sc->dev,
- "failed to allocate initial %s window (%#lx-%#lx,%#lx)\n",
+ "failed to allocate initial %s window (%#jx-%#jx,%#jx)\n",
w->name, start, end, count);
return (error);
}
@@ -1433,7 +1433,7 @@ pcib_grow_window(struct pcib_softc *sc, struct pcib_window *w, int type,
*/
if (bootverbose)
device_printf(sc->dev,
- "attempting to grow %s window for (%#lx-%#lx,%#lx)\n",
+ "attempting to grow %s window for (%#jx-%#jx,%#jx)\n",
w->name, start, end, count);
align = (rman_res_t)1 << RF_ALIGNMENT(flags);
if (start < w->base) {
@@ -1457,7 +1457,7 @@ pcib_grow_window(struct pcib_softc *sc, struct pcib_window *w, int type,
*/
if (front >= start && front <= end_free) {
if (bootverbose)
- printf("\tfront candidate range: %#lx-%#lx\n",
+ printf("\tfront candidate range: %#jx-%#jx\n",
front, end_free);
front &= ~wmask;
front = w->base - front;
@@ -1485,7 +1485,7 @@ pcib_grow_window(struct pcib_softc *sc, struct pcib_window *w, int type,
*/
if (back <= end && start_free <= back) {
if (bootverbose)
- printf("\tback candidate range: %#lx-%#lx\n",
+ printf("\tback candidate range: %#jx-%#jx\n",
start_free, back);
back |= wmask;
back -= w->limit;
@@ -1709,7 +1709,7 @@ pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
#endif
}
if (end < start) {
- device_printf(dev, "ioport: end (%lx) < start (%lx)\n",
+ device_printf(dev, "ioport: end (%jx) < start (%jx)\n",
end, start);
start = 0;
end = 0;
@@ -1717,13 +1717,13 @@ pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
}
if (!ok) {
device_printf(dev, "%s%srequested unsupported I/O "
- "range 0x%lx-0x%lx (decoding 0x%x-0x%x)\n",
+ "range 0x%jx-0x%jx (decoding 0x%x-0x%x)\n",
name, suffix, start, end, sc->iobase, sc->iolimit);
return (NULL);
}
if (bootverbose)
device_printf(dev,
- "%s%srequested I/O range 0x%lx-0x%lx: in range\n",
+ "%s%srequested I/O range 0x%jx-0x%jx: in range\n",
name, suffix, start, end);
break;
@@ -1778,7 +1778,7 @@ pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
#endif
}
if (end < start) {
- device_printf(dev, "memory: end (%lx) < start (%lx)\n",
+ device_printf(dev, "memory: end (%jx) < start (%jx)\n",
end, start);
start = 0;
end = 0;
@@ -1786,7 +1786,7 @@ pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
}
if (!ok && bootverbose)
device_printf(dev,
- "%s%srequested unsupported memory range %#lx-%#lx "
+ "%s%srequested unsupported memory range %#jx-%#jx "
"(decoding %#jx-%#jx, %#jx-%#jx)\n",
name, suffix, start, end,
(uintmax_t)sc->membase, (uintmax_t)sc->memlimit,
@@ -1795,7 +1795,7 @@ pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
return (NULL);
if (bootverbose)
device_printf(dev,"%s%srequested memory range "
- "0x%lx-0x%lx: good\n",
+ "0x%jx-0x%jx: good\n",
name, suffix, start, end);
break;
diff --git a/sys/dev/pci/pci_subr.c b/sys/dev/pci/pci_subr.c
index 77c60c3..f281117 100644
--- a/sys/dev/pci/pci_subr.c
+++ b/sys/dev/pci/pci_subr.c
@@ -185,7 +185,7 @@ pcib_host_res_decodes(struct pcib_host_resources *hr, int type, rman_res_t start
int rid;
if (bootverbose)
- device_printf(hr->hr_pcib, "decoding %d %srange %#lx-%#lx\n",
+ device_printf(hr->hr_pcib, "decoding %d %srange %#jx-%#jx\n",
type, flags & RF_PREFETCHABLE ? "prefetchable ": "", start,
end);
rid = resource_list_add_next(&hr->hr_rl, type, start, end,
@@ -229,8 +229,8 @@ restart:
if (((flags & RF_PREFETCHABLE) != 0) !=
((rle->flags & RLE_PREFETCH) != 0))
continue;
- new_start = ulmax(start, rle->start);
- new_end = ulmin(end, rle->end);
+ new_start = ummax(start, rle->start);
+ new_end = ummin(end, rle->end);
if (new_start > new_end ||
new_start + count - 1 > new_end ||
new_start + count < new_start)
@@ -240,7 +240,7 @@ restart:
if (r != NULL) {
if (bootverbose)
device_printf(hr->hr_pcib,
- "allocated type %d (%#lx-%#lx) for rid %x of %s\n",
+ "allocated type %d (%#jx-%#jx) for rid %x of %s\n",
type, rman_get_start(r), rman_get_end(r),
*rid, pcib_child_name(dev));
return (r);
diff --git a/sys/dev/ppbus/vpo.c b/sys/dev/ppbus/vpo.c
index 9c9054f..f508275 100644
--- a/sys/dev/ppbus/vpo.c
+++ b/sys/dev/ppbus/vpo.c
@@ -187,17 +187,19 @@ vpo_intr(struct vpo_data *vpo, struct ccb_scsiio *csio)
#ifdef VP0_DEBUG
int i;
#endif
+ uint8_t *ptr;
+ ptr = scsiio_cdb_ptr(csio);
if (vpo->vpo_isplus) {
errno = imm_do_scsi(&vpo->vpo_io, VP0_INITIATOR,
csio->ccb_h.target_id,
- (char *)&csio->cdb_io.cdb_bytes, csio->cdb_len,
+ ptr, csio->cdb_len,
(char *)csio->data_ptr, csio->dxfer_len,
&vpo->vpo_stat, &vpo->vpo_count, &vpo->vpo_error);
} else {
errno = vpoio_do_scsi(&vpo->vpo_io, VP0_INITIATOR,
csio->ccb_h.target_id,
- (char *)&csio->cdb_io.cdb_bytes, csio->cdb_len,
+ ptr, csio->cdb_len,
(char *)csio->data_ptr, csio->dxfer_len,
&vpo->vpo_stat, &vpo->vpo_count, &vpo->vpo_error);
}
@@ -208,7 +210,7 @@ vpo_intr(struct vpo_data *vpo, struct ccb_scsiio *csio)
/* dump of command */
for (i=0; i<csio->cdb_len; i++)
- printf("%x ", ((char *)&csio->cdb_io.cdb_bytes)[i]);
+ printf("%x ", ((char *)ptr)[i]);
printf("\n");
#endif
@@ -307,11 +309,15 @@ vpo_action(struct cam_sim *sim, union ccb *ccb)
csio = &ccb->csio;
+ if (ccb->ccb_h.flags & CAM_CDB_PHYS) {
+ ccb->ccb_h.status = CAM_REQ_INVALID;
+ xpt_done(ccb);
+ break;
+ }
#ifdef VP0_DEBUG
device_printf(vpo->vpo_dev, "XPT_SCSI_IO (0x%x) request\n",
- csio->cdb_io.cdb_bytes[0]);
+ *scsiio_cdb_ptr(csio));
#endif
-
vpo_intr(vpo, csio);
xpt_done(ccb);
diff --git a/sys/dev/ppc/ppc.c b/sys/dev/ppc/ppc.c
index a23f06c..4c6761f 100644
--- a/sys/dev/ppc/ppc.c
+++ b/sys/dev/ppc/ppc.c
@@ -1699,7 +1699,7 @@ ppc_probe(device_t dev, int rid)
next_bios_ppc += 1;
if (bootverbose)
device_printf(dev,
- "parallel port found at 0x%lx\n", port);
+ "parallel port found at 0x%jx\n", port);
}
#else
if ((next_bios_ppc < BIOS_MAX_PPC) &&
@@ -1707,7 +1707,7 @@ ppc_probe(device_t dev, int rid)
port = *(BIOS_PORTS + next_bios_ppc++);
if (bootverbose)
device_printf(dev,
- "parallel port found at 0x%lx\n", port);
+ "parallel port found at 0x%jx\n", port);
} else {
device_printf(dev, "parallel port not found.\n");
return (ENXIO);
diff --git a/sys/dev/proto/proto_bus_isa.c b/sys/dev/proto/proto_bus_isa.c
index e7438bf..4dad91c 100644
--- a/sys/dev/proto/proto_bus_isa.c
+++ b/sys/dev/proto/proto_bus_isa.c
@@ -80,7 +80,7 @@ proto_isa_probe(device_t dev)
return (ENODEV);
sb = sbuf_new_auto();
- sbuf_printf(sb, "%s:%#lx", proto_isa_prefix, rman_get_start(res));
+ sbuf_printf(sb, "%s:%#jx", proto_isa_prefix, rman_get_start(res));
sbuf_finish(sb);
device_set_desc_copy(dev, sbuf_data(sb));
sbuf_delete(sb);
diff --git a/sys/dev/qlxgb/qla_isr.c b/sys/dev/qlxgb/qla_isr.c
index 3169fd1..983fc12 100644
--- a/sys/dev/qlxgb/qla_isr.c
+++ b/sys/dev/qlxgb/qla_isr.c
@@ -267,7 +267,6 @@ qla_rcv_isr(qla_host_t *ha, uint32_t sds_idx, uint32_t count)
uint32_t comp_idx, desc_count;
q80_stat_desc_t *sdesc;
struct lro_ctrl *lro;
- struct lro_entry *queued;
uint32_t ret = 0;
dev = ha->pci_dev;
@@ -324,11 +323,7 @@ qla_rcv_isr(qla_host_t *ha, uint32_t sds_idx, uint32_t count)
}
}
- while((!SLIST_EMPTY(&lro->lro_active))) {
- queued = SLIST_FIRST(&lro->lro_active);
- SLIST_REMOVE_HEAD(&lro->lro_active, next);
- tcp_lro_flush(lro, queued);
- }
+ tcp_lro_flush_all(lro);
if (hw->sds[sds_idx].sdsr_next != comp_idx) {
QL_UPDATE_SDS_CONSUMER_INDEX(ha, sds_idx, comp_idx);
diff --git a/sys/dev/qlxge/qls_isr.c b/sys/dev/qlxge/qls_isr.c
index 03b3a3c..4cca895 100644
--- a/sys/dev/qlxge/qls_isr.c
+++ b/sys/dev/qlxge/qls_isr.c
@@ -232,7 +232,6 @@ qls_cq_isr(qla_host_t *ha, uint32_t cq_idx)
uint32_t i, cq_comp_idx;
int ret = 0, tx_comp_done = 0;
struct lro_ctrl *lro;
- struct lro_entry *queued;
cq_b = ha->rx_ring[cq_idx].cq_base_vaddr;
lro = &ha->rx_ring[cq_idx].lro;
@@ -287,11 +286,7 @@ qls_cq_isr(qla_host_t *ha, uint32_t cq_idx)
}
}
- while((!SLIST_EMPTY(&lro->lro_active))) {
- queued = SLIST_FIRST(&lro->lro_active);
- SLIST_REMOVE_HEAD(&lro->lro_active, next);
- tcp_lro_flush(lro, queued);
- }
+ tcp_lro_flush_all(lro);
ha->rx_ring[cq_idx].cq_next = cq_comp_idx;
diff --git a/sys/dev/random/random_harvestq.c b/sys/dev/random/random_harvestq.c
index c56d1ec..081ba83 100644
--- a/sys/dev/random/random_harvestq.c
+++ b/sys/dev/random/random_harvestq.c
@@ -183,7 +183,8 @@ random_kthread(void)
/* NOTREACHED */
}
/* This happens well after SI_SUB_RANDOM */
-SYSINIT(random_device_h_proc, SI_SUB_CREATE_INIT, SI_ORDER_ANY, kproc_start, &random_proc_kp);
+SYSINIT(random_device_h_proc, SI_SUB_KICK_SCHEDULER, SI_ORDER_ANY, kproc_start,
+ &random_proc_kp);
/*
* Run through all fast sources reading entropy for the given
diff --git a/sys/dev/sdhci/sdhci_fdt.c b/sys/dev/sdhci/sdhci_fdt.c
index e49eda8..27709d0 100644
--- a/sys/dev/sdhci/sdhci_fdt.c
+++ b/sys/dev/sdhci/sdhci_fdt.c
@@ -308,3 +308,4 @@ DRIVER_MODULE(sdhci_fdt, simplebus, sdhci_fdt_driver, sdhci_fdt_devclass,
NULL, NULL);
MODULE_DEPEND(sdhci_fdt, sdhci, 1, 1, 1);
DRIVER_MODULE(mmc, sdhci_fdt, mmc_driver, mmc_devclass, NULL, NULL);
+MODULE_DEPEND(sdhci_fdt, mmc, 1, 1, 1);
diff --git a/sys/dev/sdhci/sdhci_pci.c b/sys/dev/sdhci/sdhci_pci.c
index e0fd29c..3ed43ab 100644
--- a/sys/dev/sdhci/sdhci_pci.c
+++ b/sys/dev/sdhci/sdhci_pci.c
@@ -475,3 +475,4 @@ DRIVER_MODULE(sdhci_pci, pci, sdhci_pci_driver, sdhci_pci_devclass, NULL,
NULL);
MODULE_DEPEND(sdhci_pci, sdhci, 1, 1, 1);
DRIVER_MODULE(mmc, sdhci_pci, mmc_driver, mmc_devclass, NULL, NULL);
+MODULE_DEPEND(sdhci_pci, mmc, 1, 1, 1);
diff --git a/sys/dev/sfxge/sfxge_mcdi.c b/sys/dev/sfxge/sfxge_mcdi.c
index 3a85c28..85d7997 100644
--- a/sys/dev/sfxge/sfxge_mcdi.c
+++ b/sys/dev/sfxge/sfxge_mcdi.c
@@ -250,10 +250,6 @@ sfxge_mcdi_ioctl(struct sfxge_softc *sc, sfxge_ioc_t *ip)
}
mcdibuf = malloc(SFXGE_MCDI_MAX_PAYLOAD, M_TEMP, M_WAITOK | M_ZERO);
- if (mcdibuf == NULL) {
- rc = ENOMEM;
- goto fail4;
- }
if ((rc = copyin(ip->u.mcdi.payload, mcdibuf, ip->u.mcdi.len)) != 0) {
goto fail5;
}
@@ -292,7 +288,6 @@ sfxge_mcdi_ioctl(struct sfxge_softc *sc, sfxge_ioc_t *ip)
fail6:
fail5:
free(mcdibuf, M_TEMP);
-fail4:
fail3:
fail2:
fail1:
diff --git a/sys/dev/sfxge/sfxge_nvram.c b/sys/dev/sfxge/sfxge_nvram.c
index c4fa224..9113a89 100644
--- a/sys/dev/sfxge/sfxge_nvram.c
+++ b/sys/dev/sfxge/sfxge_nvram.c
@@ -75,10 +75,6 @@ sfxge_nvram_rw(struct sfxge_softc *sc, sfxge_ioc_t *ip, efx_nvram_type_t type,
goto fail1;
buf = malloc(chunk_size, M_TEMP, M_WAITOK);
- if (buf == NULL) {
- rc = ENOMEM;
- goto fail2;
- }
off = 0;
while (total_size) {
@@ -108,7 +104,6 @@ sfxge_nvram_rw(struct sfxge_softc *sc, sfxge_ioc_t *ip, efx_nvram_type_t type,
fail3:
free(buf, M_TEMP);
-fail2:
efx_nvram_rw_finish(enp, type);
fail1:
return (rc);
diff --git a/sys/dev/siba/siba.c b/sys/dev/siba/siba.c
index 3489ddc..f0bcd9f 100644
--- a/sys/dev/siba/siba.c
+++ b/sys/dev/siba/siba.c
@@ -597,8 +597,8 @@ siba_print_all_resources(device_t dev)
if (STAILQ_FIRST(rl))
retval += printf(" at");
- retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
- retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+ retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
+ retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
return (retval);
}
diff --git a/sys/dev/siis/siis.c b/sys/dev/siis/siis.c
index 9ceb444..cb9d800 100644
--- a/sys/dev/siis/siis.c
+++ b/sys/dev/siis/siis.c
@@ -320,7 +320,7 @@ siis_alloc_resource(device_t dev, device_t child, int type, int *rid,
int unit = ((struct siis_channel *)device_get_softc(child))->unit;
struct resource *res = NULL;
int offset = unit << 13;
- long st;
+ rman_res_t st;
switch (type) {
case SYS_RES_MEMORY:
diff --git a/sys/dev/sound/isa/ad1816.c b/sys/dev/sound/isa/ad1816.c
index f3bb89a..2ae39cf 100644
--- a/sys/dev/sound/isa/ad1816.c
+++ b/sys/dev/sound/isa/ad1816.c
@@ -624,11 +624,11 @@ ad1816_attach(device_t dev)
goto no;
}
if (ad1816->drq2)
- snprintf(status2, SND_STATUSLEN, ":%ld", rman_get_start(ad1816->drq2));
+ snprintf(status2, SND_STATUSLEN, ":%jd", rman_get_start(ad1816->drq2));
else
status2[0] = '\0';
- snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %ld%s bufsz %u %s",
+ snprintf(status, SND_STATUSLEN, "at io 0x%jx irq %jd drq %jd%s bufsz %u %s",
rman_get_start(ad1816->io_base),
rman_get_start(ad1816->irq),
rman_get_start(ad1816->drq1),
diff --git a/sys/dev/sound/isa/ess.c b/sys/dev/sound/isa/ess.c
index 5fd9529..e4032de 100644
--- a/sys/dev/sound/isa/ess.c
+++ b/sys/dev/sound/isa/ess.c
@@ -867,12 +867,12 @@ ess_attach(device_t dev)
}
if (sc->drq2)
- snprintf(buf, SND_STATUSLEN, ":%ld", rman_get_start(sc->drq2));
+ snprintf(buf, SND_STATUSLEN, ":%jd", rman_get_start(sc->drq2));
else
buf[0] = '\0';
- snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %ld%s bufsz %u %s",
- rman_get_start(sc->io_base), rman_get_start(sc->irq),
+ snprintf(status, SND_STATUSLEN, "at io 0x%jx irq %jd drq %jd%s bufsz %u %s",
+ rman_get_start(sc->io_base), rman_get_start(sc->irq),
rman_get_start(sc->drq1), buf, sc->bufsize,
PCM_KLDSTRING(snd_ess));
diff --git a/sys/dev/sound/isa/mss.c b/sys/dev/sound/isa/mss.c
index 7aaef06..62f6617 100644
--- a/sys/dev/sound/isa/mss.c
+++ b/sys/dev/sound/isa/mss.c
@@ -1326,7 +1326,7 @@ mss_probe(device_t dev)
}
tmp &= 0x3f;
if (!(tmp == 0x04 || tmp == 0x0f || tmp == 0x00 || tmp == 0x05)) {
- BVDDB(printf("No MSS signature detected on port 0x%lx (0x%x)\n",
+ BVDDB(printf("No MSS signature detected on port 0x%jx (0x%x)\n",
rman_get_start(mss->io_base), tmpx));
goto no;
}
@@ -1767,7 +1767,7 @@ mss_doattach(device_t dev, struct mss_info *mss)
else
status2[0] = '\0';
- snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %d%s bufsz %u",
+ snprintf(status, SND_STATUSLEN, "at io 0x%jx irq %jd drq %d%s bufsz %u",
rman_get_start(mss->io_base), rman_get_start(mss->irq), pdma, status2, mss->bufsize);
if (pcm_register(dev, mss, 1, 1)) goto no;
diff --git a/sys/dev/sound/isa/sb16.c b/sys/dev/sound/isa/sb16.c
index 536de77..946c6bf 100644
--- a/sys/dev/sound/isa/sb16.c
+++ b/sys/dev/sound/isa/sb16.c
@@ -854,11 +854,11 @@ sb16_attach(device_t dev)
}
if (!(pcm_getflags(dev) & SD_F_SIMPLEX))
- snprintf(status2, SND_STATUSLEN, ":%ld", rman_get_start(sb->drq2));
+ snprintf(status2, SND_STATUSLEN, ":%jd", rman_get_start(sb->drq2));
else
status2[0] = '\0';
- snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %ld%s bufsz %u %s",
+ snprintf(status, SND_STATUSLEN, "at io 0x%jx irq %jd drq %jd%s bufsz %u %s",
rman_get_start(sb->io_base), rman_get_start(sb->irq),
rman_get_start(sb->drq1), status2, sb->bufsize,
PCM_KLDSTRING(snd_sb16));
diff --git a/sys/dev/sound/isa/sb8.c b/sys/dev/sound/isa/sb8.c
index 7c39515..c9ed746 100644
--- a/sys/dev/sound/isa/sb8.c
+++ b/sys/dev/sound/isa/sb8.c
@@ -749,7 +749,7 @@ sb_attach(device_t dev)
goto no;
}
- snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld drq %ld bufsz %u %s",
+ snprintf(status, SND_STATUSLEN, "at io 0x%jx irq %jd drq %jd bufsz %u %s",
rman_get_start(sb->io_base), rman_get_start(sb->irq),
rman_get_start(sb->drq), sb->bufsize, PCM_KLDSTRING(snd_sb8));
diff --git a/sys/dev/sound/pci/als4000.c b/sys/dev/sound/pci/als4000.c
index b214333..bb38749 100644
--- a/sys/dev/sound/pci/als4000.c
+++ b/sys/dev/sound/pci/als4000.c
@@ -848,7 +848,7 @@ als_pci_attach(device_t dev)
pcm_addchan(dev, PCMDIR_PLAY, &alspchan_class, sc);
pcm_addchan(dev, PCMDIR_REC, &alsrchan_class, sc);
- snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld %s",
+ snprintf(status, SND_STATUSLEN, "at io 0x%jx irq %jd %s",
rman_get_start(sc->reg), rman_get_start(sc->irq),PCM_KLDSTRING(snd_als4000));
pcm_setstatus(dev, status);
return 0;
diff --git a/sys/dev/sound/pci/atiixp.c b/sys/dev/sound/pci/atiixp.c
index 8df67aa..ca9a539 100644
--- a/sys/dev/sound/pci/atiixp.c
+++ b/sys/dev/sound/pci/atiixp.c
@@ -1097,7 +1097,7 @@ atiixp_chip_post_init(void *arg)
"polling", CTLTYPE_INT | CTLFLAG_RW, sc->dev, sizeof(sc->dev),
sysctl_atiixp_polling, "I", "Enable polling mode");
- snprintf(status, SND_STATUSLEN, "at memory 0x%lx irq %ld %s",
+ snprintf(status, SND_STATUSLEN, "at memory 0x%jx irq %jd %s",
rman_get_start(sc->reg), rman_get_start(sc->irq),
PCM_KLDSTRING(snd_atiixp));
diff --git a/sys/dev/sound/pci/aureal.c b/sys/dev/sound/pci/aureal.c
index 67af075..f990f43 100644
--- a/sys/dev/sound/pci/aureal.c
+++ b/sys/dev/sound/pci/aureal.c
@@ -645,7 +645,7 @@ au_pci_attach(device_t dev)
goto bad;
}
- snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld %s",
+ snprintf(status, SND_STATUSLEN, "at %s 0x%jx irq %jd %s",
(type[0] == SYS_RES_IOPORT)? "io" : "memory",
rman_get_start(reg[0]), rman_get_start(irq),PCM_KLDSTRING(snd_aureal));
diff --git a/sys/dev/sound/pci/cmi.c b/sys/dev/sound/pci/cmi.c
index 6075a92..9e62659 100644
--- a/sys/dev/sound/pci/cmi.c
+++ b/sys/dev/sound/pci/cmi.c
@@ -995,7 +995,7 @@ cmi_attach(device_t dev)
pcm_addchan(dev, PCMDIR_PLAY, &cmichan_class, sc);
pcm_addchan(dev, PCMDIR_REC, &cmichan_class, sc);
- snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld %s",
+ snprintf(status, SND_STATUSLEN, "at io 0x%jx irq %jd %s",
rman_get_start(sc->reg), rman_get_start(sc->irq),PCM_KLDSTRING(snd_cmi));
pcm_setstatus(dev, status);
diff --git a/sys/dev/sound/pci/cs4281.c b/sys/dev/sound/pci/cs4281.c
index 929b9d7..4750daf 100644
--- a/sys/dev/sound/pci/cs4281.c
+++ b/sys/dev/sound/pci/cs4281.c
@@ -849,7 +849,7 @@ cs4281_pci_attach(device_t dev)
pcm_addchan(dev, PCMDIR_PLAY, &cs4281chan_class, sc);
pcm_addchan(dev, PCMDIR_REC, &cs4281chan_class, sc);
- snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld %s",
+ snprintf(status, SND_STATUSLEN, "at %s 0x%jx irq %jd %s",
(sc->regtype == SYS_RES_IOPORT)? "io" : "memory",
rman_get_start(sc->reg), rman_get_start(sc->irq),PCM_KLDSTRING(snd_cs4281));
pcm_setstatus(dev, status);
diff --git a/sys/dev/sound/pci/csapcm.c b/sys/dev/sound/pci/csapcm.c
index 89ffd2b..5a1544d 100644
--- a/sys/dev/sound/pci/csapcm.c
+++ b/sys/dev/sound/pci/csapcm.c
@@ -821,7 +821,7 @@ pcmcsa_attach(device_t dev)
return (ENXIO);
}
- snprintf(status, SND_STATUSLEN, "at irq %ld %s",
+ snprintf(status, SND_STATUSLEN, "at irq %jd %s",
rman_get_start(resp->irq),PCM_KLDSTRING(snd_csa));
/* Enable interrupt. */
diff --git a/sys/dev/sound/pci/ds1.c b/sys/dev/sound/pci/ds1.c
index 302271a..23f3d5c 100644
--- a/sys/dev/sound/pci/ds1.c
+++ b/sys/dev/sound/pci/ds1.c
@@ -1010,7 +1010,7 @@ ds_pci_attach(device_t dev)
goto bad;
}
- snprintf(status, SND_STATUSLEN, "at memory 0x%lx irq %ld %s",
+ snprintf(status, SND_STATUSLEN, "at memory 0x%jx irq %jd %s",
rman_get_start(sc->reg), rman_get_start(sc->irq),PCM_KLDSTRING(snd_ds1));
if (pcm_register(dev, sc, DS1_CHANS, 2))
diff --git a/sys/dev/sound/pci/emu10k1.c b/sys/dev/sound/pci/emu10k1.c
index c4a13f3..f1d77ee 100644
--- a/sys/dev/sound/pci/emu10k1.c
+++ b/sys/dev/sound/pci/emu10k1.c
@@ -2132,7 +2132,7 @@ emu_pci_attach(device_t dev)
goto bad;
}
- snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld %s",
+ snprintf(status, SND_STATUSLEN, "at io 0x%jx irq %jd %s",
rman_get_start(sc->reg), rman_get_start(sc->irq),
PCM_KLDSTRING(snd_emu10k1));
diff --git a/sys/dev/sound/pci/emu10kx.c b/sys/dev/sound/pci/emu10kx.c
index b2eaf2c..bd97ab8 100644
--- a/sys/dev/sound/pci/emu10kx.c
+++ b/sys/dev/sound/pci/emu10kx.c
@@ -3225,7 +3225,7 @@ emu_pci_attach(device_t dev)
device_printf(dev, "unable to create control device\n");
goto bad;
}
- snprintf(status, 255, "rev %d at io 0x%lx irq %ld", sc->rev, rman_get_start(sc->reg), rman_get_start(sc->irq));
+ snprintf(status, 255, "rev %d at io 0x%jx irq %jd", sc->rev, rman_get_start(sc->reg), rman_get_start(sc->irq));
/* Voices */
for (i = 0; i < NUM_G; i++) {
diff --git a/sys/dev/sound/pci/envy24.c b/sys/dev/sound/pci/envy24.c
index c4eaa10..9272a95 100644
--- a/sys/dev/sound/pci/envy24.c
+++ b/sys/dev/sound/pci/envy24.c
@@ -2599,7 +2599,7 @@ envy24_pci_attach(device_t dev)
/* set status iformation */
snprintf(status, SND_STATUSLEN,
- "at io 0x%lx:%ld,0x%lx:%ld,0x%lx:%ld,0x%lx:%ld irq %ld",
+ "at io 0x%jx:%jd,0x%jx:%jd,0x%jx:%jd,0x%jx:%jd irq %jd",
rman_get_start(sc->cs),
rman_get_end(sc->cs) - rman_get_start(sc->cs) + 1,
rman_get_start(sc->ddma),
diff --git a/sys/dev/sound/pci/envy24ht.c b/sys/dev/sound/pci/envy24ht.c
index 85a36c2..fe1fb19 100644
--- a/sys/dev/sound/pci/envy24ht.c
+++ b/sys/dev/sound/pci/envy24ht.c
@@ -2507,7 +2507,7 @@ envy24ht_pci_attach(device_t dev)
/* set status iformation */
snprintf(status, SND_STATUSLEN,
- "at io 0x%lx:%ld,0x%lx:%ld irq %ld",
+ "at io 0x%jx:%jd,0x%jx:%jd irq %jd",
rman_get_start(sc->cs),
rman_get_end(sc->cs) - rman_get_start(sc->cs) + 1,
rman_get_start(sc->mt),
diff --git a/sys/dev/sound/pci/es137x.c b/sys/dev/sound/pci/es137x.c
index 0dd88a8..7032c84 100644
--- a/sys/dev/sound/pci/es137x.c
+++ b/sys/dev/sound/pci/es137x.c
@@ -1856,7 +1856,7 @@ es_pci_attach(device_t dev)
goto bad;
}
- snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld %s",
+ snprintf(status, SND_STATUSLEN, "at %s 0x%jx irq %jd %s",
(es->regtype == SYS_RES_IOPORT)? "io" : "memory",
rman_get_start(es->reg), rman_get_start(es->irq),
PCM_KLDSTRING(snd_es137x));
diff --git a/sys/dev/sound/pci/fm801.c b/sys/dev/sound/pci/fm801.c
index 82b1d77..252e714 100644
--- a/sys/dev/sound/pci/fm801.c
+++ b/sys/dev/sound/pci/fm801.c
@@ -639,7 +639,7 @@ fm801_pci_attach(device_t dev)
goto oops;
}
- snprintf(status, 64, "at %s 0x%lx irq %ld %s",
+ snprintf(status, 64, "at %s 0x%jx irq %jd %s",
(fm801->regtype == SYS_RES_IOPORT)? "io" : "memory",
rman_get_start(fm801->reg), rman_get_start(fm801->irq),PCM_KLDSTRING(snd_fm801));
diff --git a/sys/dev/sound/pci/hda/hdac.c b/sys/dev/sound/pci/hda/hdac.c
index b0f250c..c761acb 100644
--- a/sys/dev/sound/pci/hda/hdac.c
+++ b/sys/dev/sound/pci/hda/hdac.c
@@ -159,6 +159,7 @@ static const struct {
{ HDA_ATI_RV940, "ATI RV940", 0, 0 },
{ HDA_ATI_RV970, "ATI RV970", 0, 0 },
{ HDA_ATI_R1000, "ATI R1000", 0, 0 },
+ { HDA_AMD_HUDSON2, "AMD Hudson-2", 0, 0 },
{ HDA_RDC_M3010, "RDC M3010", 0, 0 },
{ HDA_VIA_VT82XX, "VIA VT8251/8237A",0, 0 },
{ HDA_SIS_966, "SiS 966", 0, 0 },
@@ -167,6 +168,7 @@ static const struct {
{ HDA_INTEL_ALL, "Intel", 0, 0 },
{ HDA_NVIDIA_ALL, "NVIDIA", 0, 0 },
{ HDA_ATI_ALL, "ATI", 0, 0 },
+ { HDA_AMD_ALL, "AMD", 0, 0 },
{ HDA_VIA_ALL, "VIA", 0, 0 },
{ HDA_SIS_ALL, "SiS", 0, 0 },
{ HDA_ULI_ALL, "ULI", 0, 0 },
diff --git a/sys/dev/sound/pci/hda/hdac.h b/sys/dev/sound/pci/hda/hdac.h
index 9538b307..1fc265a 100644
--- a/sys/dev/sound/pci/hda/hdac.h
+++ b/sys/dev/sound/pci/hda/hdac.h
@@ -136,6 +136,10 @@
#define HDA_ATI_R1000 HDA_MODEL_CONSTRUCT(ATI, 0xaaa0)
#define HDA_ATI_ALL HDA_MODEL_CONSTRUCT(ATI, 0xffff)
+#define AMD_VENDORID 0x1022
+#define HDA_AMD_HUDSON2 HDA_MODEL_CONSTRUCT(AMD, 0x780d)
+#define HDA_AMD_ALL HDA_MODEL_CONSTRUCT(AMD, 0xffff)
+
/* RDC */
#define RDC_VENDORID 0x17f3
#define HDA_RDC_M3010 HDA_MODEL_CONSTRUCT(RDC, 0x3010)
diff --git a/sys/dev/sound/pci/hdspe-pcm.c b/sys/dev/sound/pci/hdspe-pcm.c
index dc62377..d84712d 100644
--- a/sys/dev/sound/pci/hdspe-pcm.c
+++ b/sys/dev/sound/pci/hdspe-pcm.c
@@ -668,7 +668,7 @@ hdspe_pcm_attach(device_t dev)
scp->chnum++;
}
- snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld %s",
+ snprintf(status, SND_STATUSLEN, "at io 0x%jx irq %jd %s",
rman_get_start(scp->sc->cs),
rman_get_start(scp->sc->irq),
PCM_KLDSTRING(snd_hdspe));
diff --git a/sys/dev/sound/pci/ich.c b/sys/dev/sound/pci/ich.c
index 4895ad6..61b6781 100644
--- a/sys/dev/sound/pci/ich.c
+++ b/sys/dev/sound/pci/ich.c
@@ -687,7 +687,7 @@ ich_setstatus(struct sc_info *sc)
char status[SND_STATUSLEN];
snprintf(status, SND_STATUSLEN,
- "at io 0x%lx, 0x%lx irq %ld bufsz %u %s",
+ "at io 0x%jx, 0x%jx irq %jd bufsz %u %s",
rman_get_start(sc->nambar), rman_get_start(sc->nabmbar),
rman_get_start(sc->irq), sc->bufsz,PCM_KLDSTRING(snd_ich));
diff --git a/sys/dev/sound/pci/maestro.c b/sys/dev/sound/pci/maestro.c
index c7cbb35..fbadf3b 100644
--- a/sys/dev/sound/pci/maestro.c
+++ b/sys/dev/sound/pci/maestro.c
@@ -1917,7 +1917,7 @@ agg_attach(device_t dev)
adjust_pchbase(ess->pch, ess->playchns, ess->bufsz);
snprintf(status, SND_STATUSLEN,
- "port 0x%lx-0x%lx irq %ld at device %d.%d on pci%d",
+ "port 0x%jx-0x%jx irq %jd at device %d.%d on pci%d",
rman_get_start(reg), rman_get_end(reg), rman_get_start(irq),
pci_get_slot(dev), pci_get_function(dev), pci_get_bus(dev));
pcm_setstatus(dev, status);
diff --git a/sys/dev/sound/pci/maestro3.c b/sys/dev/sound/pci/maestro3.c
index 20a9bda..5bab021 100644
--- a/sys/dev/sound/pci/maestro3.c
+++ b/sys/dev/sound/pci/maestro3.c
@@ -1440,7 +1440,7 @@ m3_pci_attach(device_t dev)
goto bad;
}
}
- snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld %s",
+ snprintf(status, SND_STATUSLEN, "at %s 0x%jx irq %jd %s",
(sc->regtype == SYS_RES_IOPORT)? "io" : "memory",
rman_get_start(sc->reg), rman_get_start(sc->irq),
PCM_KLDSTRING(snd_maestro3));
diff --git a/sys/dev/sound/pci/neomagic.c b/sys/dev/sound/pci/neomagic.c
index 71c1bf1..8a78bf7 100644
--- a/sys/dev/sound/pci/neomagic.c
+++ b/sys/dev/sound/pci/neomagic.c
@@ -702,7 +702,7 @@ nm_pci_attach(device_t dev)
goto bad;
}
- snprintf(status, SND_STATUSLEN, "at memory 0x%lx, 0x%lx irq %ld %s",
+ snprintf(status, SND_STATUSLEN, "at memory 0x%jx, 0x%jx irq %jd %s",
rman_get_start(sc->buf), rman_get_start(sc->reg),
rman_get_start(sc->irq),PCM_KLDSTRING(snd_neomagic));
diff --git a/sys/dev/sound/pci/solo.c b/sys/dev/sound/pci/solo.c
index 534d810..dc46ac8 100644
--- a/sys/dev/sound/pci/solo.c
+++ b/sys/dev/sound/pci/solo.c
@@ -1051,7 +1051,7 @@ ess_attach(device_t dev)
if (mixer_init(dev, &solomixer_class, sc))
goto no;
- snprintf(status, SND_STATUSLEN, "at io 0x%lx,0x%lx,0x%lx irq %ld %s",
+ snprintf(status, SND_STATUSLEN, "at io 0x%jx,0x%jx,0x%jx irq %jd %s",
rman_get_start(sc->io), rman_get_start(sc->sb), rman_get_start(sc->vc),
rman_get_start(sc->irq),PCM_KLDSTRING(snd_solo));
diff --git a/sys/dev/sound/pci/t4dwave.c b/sys/dev/sound/pci/t4dwave.c
index ef48890..32ddd00 100644
--- a/sys/dev/sound/pci/t4dwave.c
+++ b/sys/dev/sound/pci/t4dwave.c
@@ -948,7 +948,7 @@ tr_pci_attach(device_t dev)
goto bad;
}
- snprintf(status, 64, "at io 0x%lx irq %ld %s",
+ snprintf(status, 64, "at io 0x%jx irq %jd %s",
rman_get_start(tr->reg), rman_get_start(tr->irq),PCM_KLDSTRING(snd_t4dwave));
if (pcm_register(dev, tr, dacn, 1))
diff --git a/sys/dev/sound/pci/via8233.c b/sys/dev/sound/pci/via8233.c
index 0694cef..45fe175 100644
--- a/sys/dev/sound/pci/via8233.c
+++ b/sys/dev/sound/pci/via8233.c
@@ -1348,7 +1348,7 @@ via_attach(device_t dev)
ac97_setextmode(via->codec, ext);
}
- snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld %s",
+ snprintf(status, SND_STATUSLEN, "at io 0x%jx irq %jd %s",
rman_get_start(via->reg), rman_get_start(via->irq),
PCM_KLDSTRING(snd_via8233));
diff --git a/sys/dev/sound/pci/via82c686.c b/sys/dev/sound/pci/via82c686.c
index 6b615e8..4484d6e 100644
--- a/sys/dev/sound/pci/via82c686.c
+++ b/sys/dev/sound/pci/via82c686.c
@@ -590,7 +590,7 @@ via_attach(device_t dev)
NSEGS * sizeof(struct via_dma_op), dma_cb, via, 0) != 0)
goto bad;
- snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld %s",
+ snprintf(status, SND_STATUSLEN, "at io 0x%jx irq %jd %s",
rman_get_start(via->reg), rman_get_start(via->irq),
PCM_KLDSTRING(snd_via82c686));
diff --git a/sys/dev/sound/pci/vibes.c b/sys/dev/sound/pci/vibes.c
index f16e3ef..22c84c8 100644
--- a/sys/dev/sound/pci/vibes.c
+++ b/sys/dev/sound/pci/vibes.c
@@ -815,7 +815,7 @@ sv_attach(device_t dev) {
((mu - ml) % 0x200)) {
device_printf(dev, "sv_attach: resource assumptions not met "
"(midi 0x%08lx, games 0x%08lx)\n",
- midi_start, games_start);
+ (u_long)midi_start, (u_long)games_start);
goto fail;
}
@@ -874,7 +874,7 @@ sv_attach(device_t dev) {
pcm_addchan(dev, PCMDIR_PLAY, &svpchan_class, sc);
pcm_addchan(dev, PCMDIR_REC, &svrchan_class, sc);
- snprintf(status, SND_STATUSLEN, "at io 0x%lx irq %ld %s",
+ snprintf(status, SND_STATUSLEN, "at io 0x%jx irq %jd %s",
rman_get_start(sc->enh_reg), rman_get_start(sc->irq),PCM_KLDSTRING(snd_vibes));
pcm_setstatus(dev, status);
diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c
index cb52ce7..a36afef 100644
--- a/sys/dev/uart/uart_dev_ns8250.c
+++ b/sys/dev/uart/uart_dev_ns8250.c
@@ -398,7 +398,6 @@ struct uart_class uart_ns8250_class = {
static struct ofw_compat_data compat_data[] = {
{"ns16550", (uintptr_t)&uart_ns8250_class},
{"ns16550a", (uintptr_t)&uart_ns8250_class},
- {"snps,dw-apb-uart", (uintptr_t)&uart_ns8250_class},
{NULL, (uintptr_t)NULL},
};
UART_FDT_CLASS_AND_DEVICE(compat_data);
@@ -451,19 +450,9 @@ ns8250_bus_attach(struct uart_softc *sc)
pcell_t cell;
#endif
- ns8250->busy_detect = 0;
-
#ifdef FDT
- /*
- * Check whether uart requires to read USR reg when IIR_BUSY and
- * has broken txfifo.
- */
- ns8250->busy_detect = ofw_bus_is_compatible(sc->sc_dev, "snps,dw-apb-uart");
+ /* Check whether uart has a broken txfifo. */
node = ofw_bus_get_node(sc->sc_dev);
- /* XXX: This is kept for a short time for compatibility with older device trees */
- if ((OF_getencprop(node, "busy-detect", &cell, sizeof(cell))) > 0
- && cell != 0)
- ns8250->busy_detect = 1;
if ((OF_getencprop(node, "broken-txfifo", &cell, sizeof(cell))) > 0)
broken_txfifo = cell ? 1 : 0;
#endif
diff --git a/sys/dev/uart/uart_dev_snps.c b/sys/dev/uart/uart_dev_snps.c
new file mode 100644
index 0000000..af4000f
--- /dev/null
+++ b/sys/dev/uart/uart_dev_snps.c
@@ -0,0 +1,283 @@
+/*-
+ * Copyright (c) 2016 Jared McNeill <jmcneill@invisible.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_bus.h>
+#include <dev/uart/uart_cpu_fdt.h>
+#include <dev/uart/uart_dev_ns8250.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#ifdef EXT_RESOURCES
+#include <dev/extres/clk/clk.h>
+#include <dev/extres/hwreset/hwreset.h>
+#endif
+
+#include "uart_if.h"
+
+struct snps_softc {
+ struct ns8250_softc ns8250;
+
+#ifdef EXT_RESOURCES
+ clk_t baudclk;
+ clk_t apb_pclk;
+ hwreset_t reset;
+#endif
+};
+
+static int
+snps_uart_attach(struct uart_softc *uart_sc)
+{
+ struct snps_softc *sc;
+
+ sc = (struct snps_softc *)uart_sc;
+
+ /* UART requires to read USR reg when IIR_BUSY */
+ sc->ns8250.busy_detect = 1;
+
+ return (ns8250_bus_attach(uart_sc));
+}
+
+static kobj_method_t snps_methods[] = {
+ KOBJMETHOD(uart_probe, ns8250_bus_probe),
+ KOBJMETHOD(uart_attach, snps_uart_attach),
+ KOBJMETHOD(uart_detach, ns8250_bus_detach),
+ KOBJMETHOD(uart_flush, ns8250_bus_flush),
+ KOBJMETHOD(uart_getsig, ns8250_bus_getsig),
+ KOBJMETHOD(uart_ioctl, ns8250_bus_ioctl),
+ KOBJMETHOD(uart_ipend, ns8250_bus_ipend),
+ KOBJMETHOD(uart_param, ns8250_bus_param),
+ KOBJMETHOD(uart_receive, ns8250_bus_receive),
+ KOBJMETHOD(uart_setsig, ns8250_bus_setsig),
+ KOBJMETHOD(uart_transmit, ns8250_bus_transmit),
+ KOBJMETHOD(uart_grab, ns8250_bus_grab),
+ KOBJMETHOD(uart_ungrab, ns8250_bus_ungrab),
+ KOBJMETHOD_END
+};
+
+struct uart_class uart_snps_class = {
+ "snps",
+ snps_methods,
+ sizeof(struct snps_softc),
+ .uc_ops = &uart_ns8250_ops,
+ .uc_range = 8,
+ .uc_rclk = 0,
+};
+
+static struct ofw_compat_data compat_data[] = {
+ { "snps,dw-apb-uart", (uintptr_t)&uart_snps_class },
+ { NULL, (uintptr_t)NULL }
+};
+UART_FDT_CLASS(compat_data);
+
+#ifdef EXT_RESOURCES
+static int
+snps_get_clocks(device_t dev, clk_t *baudclk, clk_t *apb_pclk)
+{
+ struct snps_softc *sc;
+
+ sc = device_get_softc(dev);
+ *baudclk = NULL;
+ *apb_pclk = NULL;
+
+ /* Baud clock is either named "baudclk", or there is a single
+ * unnamed clock.
+ */
+ if (clk_get_by_ofw_name(dev, "baudclk", baudclk) != 0 &&
+ clk_get_by_ofw_index(dev, 0, baudclk) != 0)
+ return (ENOENT);
+
+ /* APB peripheral clock is optional */
+ (void)clk_get_by_ofw_name(dev, "apb_pclk", apb_pclk);
+
+ return (0);
+}
+#endif
+
+static int
+snps_probe(device_t dev)
+{
+ struct snps_softc *sc;
+ struct uart_class *uart_class;
+ phandle_t node;
+ uint32_t shift, clock;
+ uint64_t freq;
+ int error;
+#ifdef EXT_RESOURCES
+ clk_t baudclk, apb_pclk;
+ hwreset_t reset;
+#endif
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ uart_class = (struct uart_class *)ofw_bus_search_compatible(dev,
+ compat_data)->ocd_data;
+ if (uart_class == NULL)
+ return (ENXIO);
+
+ freq = 0;
+ sc = device_get_softc(dev);
+ sc->ns8250.base.sc_class = uart_class;
+
+ node = ofw_bus_get_node(dev);
+ if (OF_getencprop(node, "reg-shift", &shift, sizeof(shift)) <= 0)
+ shift = 0;
+ if (OF_getencprop(node, "clock-frequency", &clock, sizeof(clock)) <= 0)
+ clock = 0;
+
+#ifdef EXT_RESOURCES
+ if (hwreset_get_by_ofw_idx(dev, 0, &reset) == 0) {
+ error = hwreset_deassert(reset);
+ if (error != 0) {
+ device_printf(dev, "cannot de-assert reset\n");
+ return (error);
+ }
+ }
+
+ if (snps_get_clocks(dev, &baudclk, &apb_pclk) == 0) {
+ error = clk_enable(baudclk);
+ if (error != 0) {
+ device_printf(dev, "cannot enable baud clock\n");
+ return (error);
+ }
+ if (apb_pclk != NULL) {
+ error = clk_enable(apb_pclk);
+ if (error != 0) {
+ device_printf(dev,
+ "cannot enable peripheral clock\n");
+ return (error);
+ }
+ }
+
+ if (clock == 0) {
+ error = clk_get_freq(baudclk, &freq);
+ if (error != 0) {
+ device_printf(dev, "cannot get frequency\n");
+ return (error);
+ }
+ clock = (uint32_t)freq;
+ }
+ }
+#endif
+
+ if (bootverbose && clock == 0)
+ device_printf(dev, "could not determine frequency\n");
+
+ error = uart_bus_probe(dev, (int)shift, (int)clock, 0, 0);
+ if (error != 0)
+ return (error);
+
+#ifdef EXT_RESOURCES
+ /* XXX uart_bus_probe has changed the softc, so refresh it */
+ sc = device_get_softc(dev);
+
+ /* Store clock and reset handles for detach */
+ sc->baudclk = baudclk;
+ sc->apb_pclk = apb_pclk;
+ sc->reset = reset;
+#endif
+
+ return (0);
+}
+
+static int
+snps_detach(device_t dev)
+{
+#ifdef EXT_RESOURCES
+ struct snps_softc *sc;
+ clk_t baudclk, apb_pclk;
+ hwreset_t reset;
+#endif
+ int error;
+
+#ifdef EXT_RESOURCES
+ sc = device_get_softc(dev);
+ baudclk = sc->baudclk;
+ apb_pclk = sc->apb_pclk;
+ reset = sc->reset;
+#endif
+
+ error = uart_bus_detach(dev);
+ if (error != 0)
+ return (error);
+
+#ifdef EXT_RESOURCES
+ if (reset != NULL) {
+ error = hwreset_assert(reset);
+ if (error != 0) {
+ device_printf(dev, "cannot assert reset\n");
+ return (error);
+ }
+ hwreset_release(reset);
+ }
+ if (apb_pclk != NULL) {
+ error = clk_release(apb_pclk);
+ if (error != 0) {
+ device_printf(dev, "cannot release peripheral clock\n");
+ return (error);
+ }
+ }
+ if (baudclk != NULL) {
+ error = clk_release(baudclk);
+ if (error != 0) {
+ device_printf(dev, "cannot release baud clock\n");
+ return (error);
+ }
+ }
+#endif
+
+ return (0);
+}
+
+static device_method_t snps_bus_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, snps_probe),
+ DEVMETHOD(device_attach, uart_bus_attach),
+ DEVMETHOD(device_detach, snps_detach),
+ DEVMETHOD_END
+};
+
+static driver_t snps_uart_driver = {
+ uart_driver_name,
+ snps_bus_methods,
+ sizeof(struct snps_softc)
+};
+
+DRIVER_MODULE(uart_snps, simplebus, snps_uart_driver, uart_devclass, 0, 0);
diff --git a/sys/dev/usb/wlan/if_urtwn.c b/sys/dev/urtwn/if_urtwn.c
index 8b56847..95de7ce 100644
--- a/sys/dev/usb/wlan/if_urtwn.c
+++ b/sys/dev/urtwn/if_urtwn.c
@@ -78,8 +78,8 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_debug.h>
-#include <dev/usb/wlan/if_urtwnreg.h>
-#include <dev/usb/wlan/if_urtwnvar.h>
+#include <dev/urtwn/if_urtwnreg.h>
+#include <dev/urtwn/if_urtwnvar.h>
#ifdef USB_DEBUG
enum {
@@ -95,6 +95,7 @@ enum {
URTWN_DEBUG_ROM = 0x00000200, /* various ROM info */
URTWN_DEBUG_KEY = 0x00000400, /* crypto keys management */
URTWN_DEBUG_TXPWR = 0x00000800, /* dump Tx power values */
+ URTWN_DEBUG_RSSI = 0x00001000, /* dump RSSI lookups */
URTWN_DEBUG_ANY = 0xffffffff
};
@@ -109,6 +110,9 @@ enum {
#define IEEE80211_HAS_ADDR4(wh) IEEE80211_IS_DSTODS(wh)
+static int urtwn_enable_11n = 1;
+TUNABLE_INT("hw.usb.urtwn.enable_11n", &urtwn_enable_11n);
+
/* various supported device vendors/products */
static const STRUCT_USB_HOST_ID urtwn_devs[] = {
#define URTWN_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) }
@@ -465,6 +469,19 @@ urtwn_match(device_t self)
return (usbd_lookup_id_by_uaa(urtwn_devs, sizeof(urtwn_devs), uaa));
}
+static void
+urtwn_update_chw(struct ieee80211com *ic)
+{
+}
+
+static int
+urtwn_ampdu_enable(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap)
+{
+
+ /* We're driving this ourselves (eventually); don't involve net80211 */
+ return (0);
+}
+
static int
urtwn_attach(device_t self)
{
@@ -555,7 +572,9 @@ urtwn_attach(device_t self)
| IEEE80211_C_HOSTAP /* hostap mode */
| IEEE80211_C_SHPREAMBLE /* short preamble supported */
| IEEE80211_C_SHSLOT /* short slot time supported */
+#if 0
| IEEE80211_C_BGSCAN /* capable of bg scanning */
+#endif
| IEEE80211_C_WPA /* 802.11i */
| IEEE80211_C_WME /* 802.11e */
;
@@ -565,9 +584,27 @@ urtwn_attach(device_t self)
IEEE80211_CRYPTO_TKIP |
IEEE80211_CRYPTO_AES_CCM;
+ /* Assume they're all 11n capable for now */
+ if (urtwn_enable_11n) {
+ device_printf(self, "enabling 11n\n");
+ ic->ic_htcaps = IEEE80211_HTC_HT |
+ IEEE80211_HTC_AMPDU |
+ IEEE80211_HTC_AMSDU |
+ IEEE80211_HTCAP_MAXAMSDU_3839 |
+ IEEE80211_HTCAP_SMPS_OFF;
+ /* no HT40 just yet */
+ // ic->ic_htcaps |= IEEE80211_HTCAP_CHWIDTH40;
+
+ /* XXX TODO: verify chains versus streams for urtwn */
+ ic->ic_txstream = sc->ntxchains;
+ ic->ic_rxstream = sc->nrxchains;
+ }
+
memset(bands, 0, sizeof(bands));
setbit(bands, IEEE80211_MODE_11B);
setbit(bands, IEEE80211_MODE_11G);
+ if (urtwn_enable_11n)
+ setbit(bands, IEEE80211_MODE_11NG);
ieee80211_init_channels(ic, NULL, bands);
ieee80211_ifattach(ic);
@@ -589,6 +626,8 @@ urtwn_attach(device_t self)
sc->sc_node_free = ic->ic_node_free;
ic->ic_node_free = urtwn_r88e_node_free;
}
+ ic->ic_update_chw = urtwn_update_chw;
+ ic->ic_ampdu_enable = urtwn_ampdu_enable;
ieee80211_radiotap_attach(ic, &sc->sc_txtap.wt_ihdr,
sizeof(sc->sc_txtap), URTWN_TX_RADIOTAP_PRESENT,
@@ -1005,6 +1044,9 @@ urtwn_rx_frame(struct urtwn_softc *sc, struct mbuf *m, int8_t *rssi_p)
tap->wr_tsft &= 0xffffffff00000000;
tap->wr_tsft += stat->rxdw5;
+ /* XXX 20/40? */
+ /* XXX shortgi? */
+
/* Map HW rate index to 802.11 rate. */
if (!(rxdw3 & R92C_RXDW3_HT)) {
tap->wr_rate = ridx2rate[rate];
@@ -1081,6 +1123,8 @@ tr_setup:
nf = URTWN_NOISE_FLOOR;
if (ni != NULL) {
+ if (ni->ni_flags & IEEE80211_NODE_HT)
+ m->m_flags |= M_AMPDU;
(void)ieee80211_input(ni, m, rssi - nf, nf);
ieee80211_free_node(ni);
} else {
@@ -1827,7 +1871,7 @@ urtwn_ra_init(struct urtwn_softc *sc)
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ieee80211_node *ni;
- struct ieee80211_rateset *rs;
+ struct ieee80211_rateset *rs, *rs_ht;
struct r92c_fw_cmd_macid_cfg cmd;
uint32_t rates, basicrates;
uint8_t mode;
@@ -1835,10 +1879,13 @@ urtwn_ra_init(struct urtwn_softc *sc)
ni = ieee80211_ref_node(vap->iv_bss);
rs = &ni->ni_rates;
+ rs_ht = (struct ieee80211_rateset *) &ni->ni_htrates;
/* Get normal and basic rates mask. */
rates = basicrates = 0;
maxrate = maxbasicrate = 0;
+
+ /* This is for 11bg */
for (i = 0; i < rs->rs_nrates; i++) {
/* Convert 802.11 rate to HW rate index. */
for (j = 0; j < nitems(ridx2rate); j++)
@@ -1856,10 +1903,32 @@ urtwn_ra_init(struct urtwn_softc *sc)
maxbasicrate = j;
}
}
+
+ /* If we're doing 11n, enable 11n rates */
+ if (ni->ni_flags & IEEE80211_NODE_HT) {
+ for (i = 0; i < rs_ht->rs_nrates; i++) {
+ if ((rs_ht->rs_rates[i] & 0x7f) > 0xf)
+ continue;
+ /* 11n rates start at index 12 */
+ j = ((rs_ht->rs_rates[i]) & 0xf) + 12;
+ rates |= (1 << j);
+
+ /* Guard against the rate table being oddly ordered */
+ if (j > maxrate)
+ maxrate = j;
+ }
+ }
+
+#if 0
+ if (ic->ic_curmode == IEEE80211_MODE_11NG)
+ raid = R92C_RAID_11GN;
+#endif
+ /* NB: group addressed frames are done at 11bg rates for now */
if (ic->ic_curmode == IEEE80211_MODE_11B)
mode = R92C_RAID_11B;
else
mode = R92C_RAID_11BG;
+ /* XXX misleading 'mode' value here for unicast frames */
URTWN_DPRINTF(sc, URTWN_DEBUG_RA,
"%s: mode 0x%x, rates 0x%08x, basicrates 0x%08x\n", __func__,
mode, rates, basicrates);
@@ -1874,6 +1943,7 @@ urtwn_ra_init(struct urtwn_softc *sc)
"could not add broadcast station\n");
return (error);
}
+
/* Set initial MRR rate. */
URTWN_DPRINTF(sc, URTWN_DEBUG_RA, "%s: maxbasicrate %d\n", __func__,
maxbasicrate);
@@ -1881,6 +1951,12 @@ urtwn_ra_init(struct urtwn_softc *sc)
maxbasicrate);
/* Set rates mask for unicast frames. */
+ if (ni->ni_flags & IEEE80211_NODE_HT)
+ mode = R92C_RAID_11GN;
+ else if (ic->ic_curmode == IEEE80211_MODE_11B)
+ mode = R92C_RAID_11B;
+ else
+ mode = R92C_RAID_11BG;
cmd.macid = URTWN_MACID_BSS | URTWN_MACID_VALID;
cmd.mask = htole32(mode << 28 | rates);
error = urtwn_fw_cmd(sc, R92C_CMD_MACID_CONFIG, &cmd, sizeof(cmd));
@@ -1896,7 +1972,11 @@ urtwn_ra_init(struct urtwn_softc *sc)
maxrate);
/* Indicate highest supported rate. */
- ni->ni_txrate = rs->rs_rates[rs->rs_nrates - 1];
+ if (ni->ni_flags & IEEE80211_NODE_HT)
+ ni->ni_txrate = rs_ht->rs_rates[rs_ht->rs_nrates - 1]
+ | IEEE80211_RATE_MCS;
+ else
+ ni->ni_txrate = rs->rs_rates[rs->rs_nrates - 1];
ieee80211_free_node(ni);
return (0);
@@ -2559,7 +2639,7 @@ urtwn_update_avgrssi(struct urtwn_softc *sc, int rate, int8_t rssi)
sc->avg_pwdb = ((sc->avg_pwdb * 19 + pwdb) / 20) + 1;
else
sc->avg_pwdb = ((sc->avg_pwdb * 19 + pwdb) / 20);
- URTWN_DPRINTF(sc, URTWN_DEBUG_RA, "%s: PWDB %d, EMA %d\n", __func__,
+ URTWN_DPRINTF(sc, URTWN_DEBUG_RSSI, "%s: PWDB %d, EMA %d\n", __func__,
pwdb, sc->avg_pwdb);
}
@@ -2643,7 +2723,12 @@ urtwn_r88e_get_rssi(struct urtwn_softc *sc, int rate, void *physt)
static __inline uint8_t
rate2ridx(uint8_t rate)
{
+ if (rate & IEEE80211_RATE_MCS) {
+ /* 11n rates start at idx 12 */
+ return ((rate & 0xf) + 12);
+ }
switch (rate) {
+ /* 11g */
case 12: return 4;
case 18: return 5;
case 24: return 6;
@@ -2652,6 +2737,7 @@ rate2ridx(uint8_t rate)
case 72: return 9;
case 96: return 10;
case 108: return 11;
+ /* 11b */
case 2: return 0;
case 4: return 1;
case 11: return 2;
@@ -2711,15 +2797,24 @@ urtwn_tx_data(struct urtwn_softc *sc, struct ieee80211_node *ni,
(void) ieee80211_ratectl_rate(ni, NULL, 0);
rate = ni->ni_txrate;
} else {
- if (ic->ic_curmode != IEEE80211_MODE_11B)
+ /* XXX TODO: drop the default rate for 11b/11g? */
+ if (ni->ni_flags & IEEE80211_NODE_HT)
+ rate = IEEE80211_RATE_MCS | 0x4; /* MCS4 */
+ else if (ic->ic_curmode != IEEE80211_MODE_11B)
rate = 108;
else
rate = 22;
}
}
+ /*
+ * XXX TODO: this should be per-node, for 11b versus 11bg
+ * nodes in hostap mode
+ */
ridx = rate2ridx(rate);
- if (ic->ic_curmode != IEEE80211_MODE_11B)
+ if (ni->ni_flags & IEEE80211_NODE_HT)
+ raid = R92C_RAID_11GN;
+ else if (ic->ic_curmode != IEEE80211_MODE_11B)
raid = R92C_RAID_11BG;
else
raid = R92C_RAID_11B;
@@ -2763,7 +2858,10 @@ urtwn_tx_data(struct urtwn_softc *sc, struct ieee80211_node *ni,
} else
txd->txdw1 |= htole32(R92C_TXDW1_AGGBK);
- if (ic->ic_flags & IEEE80211_F_USEPROT) {
+ /* protmode, non-HT */
+ /* XXX TODO: noack frames? */
+ if ((rate & 0x80) == 0 &&
+ (ic->ic_flags & IEEE80211_F_USEPROT)) {
switch (ic->ic_protmode) {
case IEEE80211_PROT_CTSONLY:
txd->txdw4 |= htole32(
@@ -2779,8 +2877,21 @@ urtwn_tx_data(struct urtwn_softc *sc, struct ieee80211_node *ni,
break;
}
}
+
+ /* protmode, HT */
+ /* XXX TODO: noack frames? */
+ if ((rate & 0x80) &&
+ (ic->ic_htprotmode == IEEE80211_PROT_RTSCTS)) {
+ txd->txdw4 |= htole32(
+ R92C_TXDW4_RTSEN |
+ R92C_TXDW4_HWRTSEN);
+ }
+
+ /* XXX TODO: rtsrate is configurable? 24mbit may
+ * be a bit high for RTS rate? */
txd->txdw4 |= htole32(SM(R92C_TXDW4_RTSRATE,
URTWN_RIDX_OFDM24));
+
txd->txdw5 |= htole32(0x0001ff00);
} else /* IEEE80211_FC0_TYPE_MGT */
qsel = R92C_TXDW1_QSEL_MGNT;
@@ -2793,14 +2904,21 @@ urtwn_tx_data(struct urtwn_softc *sc, struct ieee80211_node *ni,
SM(R92C_TXDW1_QSEL, qsel) |
SM(R92C_TXDW1_RAID, raid));
+ /* XXX TODO: 40MHZ flag? */
+ /* XXX TODO: AMPDU flag? (AGG_ENABLE or AGG_BREAK?) Density shift? */
+ /* XXX Short preamble? */
+ /* XXX Short-GI? */
+
if (sc->chip & URTWN_CHIP_88E)
txd->txdw1 |= htole32(SM(R88E_TXDW1_MACID, macid));
else
txd->txdw1 |= htole32(SM(R92C_TXDW1_MACID, macid));
txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, ridx));
+
/* Force this rate if needed. */
if (URTWN_CHIP_HAS_RATECTL(sc) || ismcast ||
+ (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) ||
(m->m_flags & M_EAPOL) || type != IEEE80211_FC0_TYPE_DATA)
txd->txdw4 |= htole32(R92C_TXDW4_DRVRATE);
@@ -2888,6 +3006,8 @@ urtwn_tx_raw(struct urtwn_softc *sc, struct ieee80211_node *ni,
}
}
+ /* XXX TODO: 11n checks, matching urtwn_tx_data() */
+
wh = mtod(m, struct ieee80211_frame *);
type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
@@ -2916,6 +3036,7 @@ urtwn_tx_raw(struct urtwn_softc *sc, struct ieee80211_node *ni,
else
txd->txdw1 |= htole32(SM(R92C_TXDW1_MACID, URTWN_MACID_BC));
+ /* XXX TODO: rate index/config (RAID) for 11n? */
txd->txdw1 |= htole32(SM(R92C_TXDW1_QSEL, R92C_TXDW1_QSEL_MGNT));
txd->txdw1 |= htole32(SM(R92C_TXDW1_CIPHER, cipher));
diff --git a/sys/dev/usb/wlan/if_urtwnreg.h b/sys/dev/urtwn/if_urtwnreg.h
index 72835f3..72835f3 100644
--- a/sys/dev/usb/wlan/if_urtwnreg.h
+++ b/sys/dev/urtwn/if_urtwnreg.h
diff --git a/sys/dev/usb/wlan/if_urtwnvar.h b/sys/dev/urtwn/if_urtwnvar.h
index ba8ca81..ba8ca81 100644
--- a/sys/dev/usb/wlan/if_urtwnvar.h
+++ b/sys/dev/urtwn/if_urtwnvar.h
diff --git a/sys/dev/usb/controller/ehci_pci.c b/sys/dev/usb/controller/ehci_pci.c
index 3a6f725..cad351c 100644
--- a/sys/dev/usb/controller/ehci_pci.c
+++ b/sys/dev/usb/controller/ehci_pci.c
@@ -112,6 +112,8 @@ ehci_pci_match(device_t self)
case 0x20951022:
return ("AMD CS5536 (Geode) USB 2.0 controller");
+ case 0x78081022:
+ return ("AMD FCH USB 2.0 controller");
case 0x43451002:
return "ATI SB200 USB 2.0 controller";
@@ -168,6 +170,10 @@ ehci_pci_match(device_t self)
return ("Intel Wildcat Point USB 2.0 controller USB-A");
case 0x8cad8086:
return ("Intel Wildcat Point USB 2.0 controller USB-B");
+ case 0x8d268086:
+ return ("Intel Wellsburg USB 2.0 controller");
+ case 0x8d2d8086:
+ return ("Intel Wellsburg USB 2.0 controller");
case 0x9c268086:
return ("Intel Lynx Point LP USB 2.0 controller USB");
diff --git a/sys/dev/usb/controller/ohci_pci.c b/sys/dev/usb/controller/ohci_pci.c
index c50de54..96950a7 100644
--- a/sys/dev/usb/controller/ohci_pci.c
+++ b/sys/dev/usb/controller/ohci_pci.c
@@ -124,9 +124,10 @@ ohci_pci_match(device_t self)
case 0x740c1022:
return ("AMD-756 USB Controller");
-
case 0x74141022:
return ("AMD-766 USB Controller");
+ case 0x78071022:
+ return ("AMD FCH USB Controller");
case 0x43741002:
return "ATI SB400 USB Controller";
diff --git a/sys/dev/usb/controller/uhci_pci.c b/sys/dev/usb/controller/uhci_pci.c
index e7e4412..5916996 100644
--- a/sys/dev/usb/controller/uhci_pci.c
+++ b/sys/dev/usb/controller/uhci_pci.c
@@ -161,6 +161,12 @@ uhci_pci_match(device_t self)
case 0x24de8086:
return ("Intel 82801EB (ICH5) USB controller USB-D");
+ case 0x25a98086:
+ return ("Intel 6300ESB USB controller USB-A");
+
+ case 0x25aa8086:
+ return ("Intel 6300ESB USB controller USB-B");
+
case 0x26588086:
return ("Intel 82801FB/FR/FW/FRW (ICH6) USB controller USB-A");
diff --git a/sys/dev/usb/controller/xhci_pci.c b/sys/dev/usb/controller/xhci_pci.c
index 0a8a95b..d4355e9 100644
--- a/sys/dev/usb/controller/xhci_pci.c
+++ b/sys/dev/usb/controller/xhci_pci.c
@@ -95,6 +95,9 @@ xhci_pci_match(device_t self)
uint32_t device_id = pci_get_devid(self);
switch (device_id) {
+ case 0x78141022:
+ return ("AMD FCH USB 3.0 controller");
+
case 0x01941033:
return ("NEC uPD720200 USB 3.0 controller");
@@ -115,6 +118,8 @@ xhci_pci_match(device_t self)
return ("Intel Lynx Point USB 3.0 controller");
case 0x8cb18086:
return ("Intel Wildcat Point USB 3.0 controller");
+ case 0x8d318086:
+ return ("Intel Wellsburg USB 3.0 controller");
case 0x9cb18086:
return ("Broadwell Integrated PCH-LP chipset USB 3.0 controller");
diff --git a/sys/dev/usb/usb_busdma.c b/sys/dev/usb/usb_busdma.c
index 821e0fb..75378a2 100644
--- a/sys/dev/usb/usb_busdma.c
+++ b/sys/dev/usb/usb_busdma.c
@@ -472,17 +472,22 @@ usb_pc_common_mem_cb(void *arg, bus_dma_segment_t *segs,
pc->page_offset_buf = rem;
pc->page_offset_end += rem;
#ifdef USB_DEBUG
- if (nseg > 1 &&
- ((segs->ds_addr + segs->ds_len) & (USB_PAGE_SIZE - 1)) !=
- ((segs + 1)->ds_addr & (USB_PAGE_SIZE - 1))) {
- /*
- * This check verifies there is no page offset hole
- * between the first and second segment. See the
- * BUS_DMA_KEEP_PG_OFFSET flag.
- */
- DPRINTFN(0, "Page offset was not preserved\n");
- error = 1;
- goto done;
+ if (nseg > 1) {
+ int x;
+
+ for (x = 0; x != nseg - 1; x++) {
+ if (((segs[x].ds_addr + segs[x].ds_len) & (USB_PAGE_SIZE - 1)) ==
+ ((segs[x + 1].ds_addr & (USB_PAGE_SIZE - 1))))
+ continue;
+ /*
+ * This check verifies there is no page offset
+ * hole between any of the segments. See the
+ * BUS_DMA_KEEP_PG_OFFSET flag.
+ */
+ DPRINTFN(0, "Page offset was not preserved\n");
+ error = 1;
+ goto done;
+ }
}
#endif
while (pc->ismultiseg) {
diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs
index 07b3f73..7f75d5a 100644
--- a/sys/dev/usb/usbdevs
+++ b/sys/dev/usb/usbdevs
@@ -1700,6 +1700,7 @@ product DISPLAYLINK UM7X0 0x401a nanovision MiMo
product DISPLAYLINK LT1421 0x03e0 Lenovo ThinkVision LT1421
product DISPLAYLINK POLARIS2 0x0117 Polaris2 USB dock
product DISPLAYLINK PLUGABLE 0x0377 Plugable docking station
+product DISPLAYLINK ITEC 0x02e9 i-tec USB 2.0 Docking Station
/* DMI products */
product DMI CFSM_RW 0xa109 CF/SM Reader/Writer
diff --git a/sys/dev/usb/video/udl.c b/sys/dev/usb/video/udl.c
index 0d7c504..1096ed3 100644
--- a/sys/dev/usb/video/udl.c
+++ b/sys/dev/usb/video/udl.c
@@ -177,7 +177,8 @@ static const STRUCT_USB_HOST_ID udl_devs[] = {
{USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_PLUGABLE, DL160)},
{USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_LUM70, DL125)},
{USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_POLARIS2, DLUNK)},
- {USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_LT1421, DLUNK)}
+ {USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_LT1421, DLUNK)},
+ {USB_VPI(USB_VENDOR_DISPLAYLINK, USB_PRODUCT_DISPLAYLINK_ITEC, DL165)},
};
static void
diff --git a/sys/dev/usb/wlan/if_rum.c b/sys/dev/usb/wlan/if_rum.c
index e428a8f..08be717 100644
--- a/sys/dev/usb/wlan/if_rum.c
+++ b/sys/dev/usb/wlan/if_rum.c
@@ -154,6 +154,7 @@ static usb_callback_t rum_bulk_write_callback;
static usb_error_t rum_do_request(struct rum_softc *sc,
struct usb_device_request *req, void *data);
+static usb_error_t rum_do_mcu_request(struct rum_softc *sc, int);
static struct ieee80211vap *rum_vap_create(struct ieee80211com *,
const char [IFNAMSIZ], int, enum ieee80211_opmode,
int, const uint8_t [IEEE80211_ADDR_LEN],
@@ -165,6 +166,11 @@ static int rum_cmd_sleepable(struct rum_softc *, const void *,
static void rum_tx_free(struct rum_tx_data *, int);
static void rum_setup_tx_list(struct rum_softc *);
static void rum_unsetup_tx_list(struct rum_softc *);
+static void rum_beacon_miss(struct ieee80211vap *);
+static void rum_sta_recv_mgmt(struct ieee80211_node *,
+ struct mbuf *, int,
+ const struct ieee80211_rx_stats *, int, int);
+static int rum_set_power_state(struct rum_softc *, int);
static int rum_newstate(struct ieee80211vap *,
enum ieee80211_state, int);
static uint8_t rum_crypto_mode(struct rum_softc *, u_int, int);
@@ -232,6 +238,8 @@ static int rum_init(struct rum_softc *);
static void rum_stop(struct rum_softc *);
static void rum_load_microcode(struct rum_softc *, const uint8_t *,
size_t);
+static int rum_set_sleep_time(struct rum_softc *, uint16_t);
+static int rum_reset(struct ieee80211vap *, u_long);
static int rum_set_beacon(struct rum_softc *,
struct ieee80211vap *);
static int rum_alloc_beacon(struct rum_softc *,
@@ -530,6 +538,8 @@ rum_attach(device_t self)
| IEEE80211_C_BGSCAN /* bg scanning supported */
| IEEE80211_C_WPA /* 802.11i */
| IEEE80211_C_WME /* 802.11e */
+ | IEEE80211_C_PMGT /* Station-side power mgmt */
+ | IEEE80211_C_SWSLEEP /* net80211 managed power mgmt */
;
ic->ic_cryptocaps =
@@ -629,6 +639,20 @@ rum_do_request(struct rum_softc *sc,
return (err);
}
+static usb_error_t
+rum_do_mcu_request(struct rum_softc *sc, int request)
+{
+ struct usb_device_request req;
+
+ req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+ req.bRequest = RT2573_MCU_CNTL;
+ USETW(req.wValue, request);
+ USETW(req.wIndex, 0);
+ USETW(req.wLength, 0);
+
+ return (rum_do_request(sc, &req, NULL));
+}
+
static struct ieee80211vap *
rum_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
enum ieee80211_opmode opmode, int flags,
@@ -659,8 +683,24 @@ rum_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
vap->iv_key_set = rum_key_set;
vap->iv_key_delete = rum_key_delete;
vap->iv_update_beacon = rum_update_beacon;
+ vap->iv_reset = rum_reset;
vap->iv_max_aid = RT2573_ADDR_MAX;
+ if (opmode == IEEE80211_M_STA) {
+ /*
+ * Move device to the sleep state when
+ * beacon is received and there is no data for us.
+ *
+ * Used only for IEEE80211_S_SLEEP state.
+ */
+ rvp->recv_mgmt = vap->iv_recv_mgmt;
+ vap->iv_recv_mgmt = rum_sta_recv_mgmt;
+
+ /* Ignored while sleeping. */
+ rvp->bmiss = vap->iv_bmiss;
+ vap->iv_bmiss = rum_beacon_miss;
+ }
+
usb_callout_init_mtx(&rvp->ratectl_ch, &sc->sc_mtx, 0);
TASK_INIT(&rvp->ratectl_task, 0, rum_ratectl_task, rvp);
ieee80211_ratectl_init(vap);
@@ -795,6 +835,89 @@ rum_unsetup_tx_list(struct rum_softc *sc)
}
}
+static void
+rum_beacon_miss(struct ieee80211vap *vap)
+{
+ struct ieee80211com *ic = vap->iv_ic;
+ struct rum_softc *sc = ic->ic_softc;
+ struct rum_vap *rvp = RUM_VAP(vap);
+ int sleep;
+
+ RUM_LOCK(sc);
+ if (sc->sc_sleeping && sc->sc_sleep_end < ticks) {
+ DPRINTFN(12, "dropping 'sleeping' bit, "
+ "device must be awake now\n");
+
+ sc->sc_sleeping = 0;
+ }
+
+ sleep = sc->sc_sleeping;
+ RUM_UNLOCK(sc);
+
+ if (!sleep)
+ rvp->bmiss(vap);
+#ifdef USB_DEBUG
+ else
+ DPRINTFN(13, "bmiss event is ignored whilst sleeping\n");
+#endif
+}
+
+static void
+rum_sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m, int subtype,
+ const struct ieee80211_rx_stats *rxs,
+ int rssi, int nf)
+{
+ struct ieee80211vap *vap = ni->ni_vap;
+ struct rum_softc *sc = vap->iv_ic->ic_softc;
+ struct rum_vap *rvp = RUM_VAP(vap);
+
+ if (vap->iv_state == IEEE80211_S_SLEEP &&
+ subtype == IEEE80211_FC0_SUBTYPE_BEACON) {
+ RUM_LOCK(sc);
+ DPRINTFN(12, "beacon, mybss %d (flags %02X)\n",
+ !!(sc->last_rx_flags & RT2573_RX_MYBSS),
+ sc->last_rx_flags);
+
+ if ((sc->last_rx_flags & (RT2573_RX_MYBSS | RT2573_RX_BC)) ==
+ (RT2573_RX_MYBSS | RT2573_RX_BC)) {
+ /*
+ * Put it to sleep here; in case if there is a data
+ * for us, iv_recv_mgmt() will wakeup the device via
+ * SLEEP -> RUN state transition.
+ */
+ rum_set_power_state(sc, 1);
+ }
+ RUM_UNLOCK(sc);
+ }
+
+ rvp->recv_mgmt(ni, m, subtype, rxs, rssi, nf);
+}
+
+static int
+rum_set_power_state(struct rum_softc *sc, int sleep)
+{
+ usb_error_t uerror;
+
+ RUM_LOCK_ASSERT(sc);
+
+ DPRINTFN(12, "moving to %s state (sleep time %u)\n",
+ sleep ? "sleep" : "awake", sc->sc_sleep_time);
+
+ uerror = rum_do_mcu_request(sc,
+ sleep ? RT2573_MCU_SLEEP : RT2573_MCU_WAKEUP);
+ if (uerror != USB_ERR_NORMAL_COMPLETION) {
+ device_printf(sc->sc_dev,
+ "%s: could not change power state: %s\n",
+ __func__, usbd_errstr(uerror));
+ return (EIO);
+ }
+
+ sc->sc_sleeping = !!sleep;
+ sc->sc_sleep_end = sleep ? ticks + sc->sc_sleep_time : 0;
+
+ return (0);
+}
+
static int
rum_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
@@ -804,7 +927,8 @@ rum_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
const struct ieee80211_txparam *tp;
enum ieee80211_state ostate;
struct ieee80211_node *ni;
- int ret;
+ usb_error_t uerror;
+ int ret = 0;
ostate = vap->iv_state;
DPRINTF("%s -> %s\n",
@@ -815,6 +939,17 @@ rum_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
RUM_LOCK(sc);
usb_callout_stop(&rvp->ratectl_ch);
+ if (ostate == IEEE80211_S_SLEEP && vap->iv_opmode == IEEE80211_M_STA) {
+ rum_clrbits(sc, RT2573_TXRX_CSR4, RT2573_ACKCTS_PWRMGT);
+ rum_clrbits(sc, RT2573_MAC_CSR11, RT2573_AUTO_WAKEUP);
+
+ /*
+ * Ignore any errors;
+ * any subsequent TX will wakeup it anyway
+ */
+ (void) rum_set_power_state(sc, 0);
+ }
+
switch (nstate) {
case IEEE80211_S_INIT:
if (ostate == IEEE80211_S_RUN)
@@ -823,6 +958,9 @@ rum_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
break;
case IEEE80211_S_RUN:
+ if (ostate == IEEE80211_S_SLEEP)
+ break; /* already handled */
+
ni = ieee80211_ref_node(vap->iv_bss);
if (vap->iv_opmode != IEEE80211_M_MONITOR) {
@@ -857,20 +995,39 @@ rum_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_curchan)];
if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE)
rum_ratectl_start(sc, ni);
+run_fail:
ieee80211_free_node(ni);
break;
+ case IEEE80211_S_SLEEP:
+ /* Implemented for STA mode only. */
+ if (vap->iv_opmode != IEEE80211_M_STA)
+ break;
+
+ uerror = rum_setbits(sc, RT2573_MAC_CSR11, RT2573_AUTO_WAKEUP);
+ if (uerror != USB_ERR_NORMAL_COMPLETION) {
+ ret = EIO;
+ break;
+ }
+
+ uerror = rum_setbits(sc, RT2573_TXRX_CSR4, RT2573_ACKCTS_PWRMGT);
+ if (uerror != USB_ERR_NORMAL_COMPLETION) {
+ ret = EIO;
+ break;
+ }
+
+ ret = rum_set_power_state(sc, 1);
+ if (ret != 0) {
+ device_printf(sc->sc_dev,
+ "%s: could not move to the SLEEP state: %s\n",
+ __func__, usbd_errstr(uerror));
+ }
+ break;
default:
break;
}
RUM_UNLOCK(sc);
IEEE80211_LOCK(ic);
- return (rvp->newstate(vap, nstate, arg));
-
-run_fail:
- RUM_UNLOCK(sc);
- IEEE80211_LOCK(ic);
- ieee80211_free_node(ni);
- return ret;
+ return (ret == 0 ? rvp->newstate(vap, nstate, arg) : ret);
}
static void
@@ -1001,6 +1158,7 @@ rum_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
rssi = rum_get_rssi(sc, sc->sc_rx_desc.rssi);
flags = le32toh(sc->sc_rx_desc.flags);
+ sc->last_rx_flags = flags;
if (flags & RT2573_RX_CRC_ERROR) {
/*
* This should not happen since we did not
@@ -1995,6 +2153,7 @@ rum_enable_tsf_sync(struct rum_softc *sc)
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint32_t tmp;
+ uint16_t bintval;
if (vap->iv_opmode != IEEE80211_M_STA) {
/*
@@ -2008,7 +2167,8 @@ rum_enable_tsf_sync(struct rum_softc *sc)
tmp = rum_read(sc, RT2573_TXRX_CSR9) & 0xff000000;
/* set beacon interval (in 1/16ms unit) */
- tmp |= vap->iv_bss->ni_intval * 16;
+ bintval = vap->iv_bss->ni_intval;
+ tmp |= bintval * 16;
tmp |= RT2573_TSF_TIMER_EN | RT2573_TBTT_TIMER_EN;
switch (vap->iv_opmode) {
@@ -2042,7 +2202,8 @@ rum_enable_tsf_sync(struct rum_softc *sc)
if (rum_write(sc, RT2573_TXRX_CSR9, tmp) != 0)
return EIO;
- return 0;
+ /* refresh current sleep time */
+ return (rum_set_sleep_time(sc, bintval));
}
static void
@@ -2460,7 +2621,6 @@ rum_stop(struct rum_softc *sc)
static void
rum_load_microcode(struct rum_softc *sc, const uint8_t *ucode, size_t size)
{
- struct usb_device_request req;
uint16_t reg = RT2573_MCU_CODE_BASE;
usb_error_t err;
@@ -2475,14 +2635,8 @@ rum_load_microcode(struct rum_softc *sc, const uint8_t *ucode, size_t size)
}
}
- req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
- req.bRequest = RT2573_MCU_CNTL;
- USETW(req.wValue, RT2573_MCU_RUN);
- USETW(req.wIndex, 0);
- USETW(req.wLength, 0);
-
- err = rum_do_request(sc, &req, NULL);
- if (err != 0) {
+ err = rum_do_mcu_request(sc, RT2573_MCU_RUN);
+ if (err != USB_ERR_NORMAL_COMPLETION) {
device_printf(sc->sc_dev, "could not run firmware: %s\n",
usbd_errstr(err));
}
@@ -2492,6 +2646,72 @@ rum_load_microcode(struct rum_softc *sc, const uint8_t *ucode, size_t size)
}
static int
+rum_set_sleep_time(struct rum_softc *sc, uint16_t bintval)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ usb_error_t uerror;
+ int exp, delay;
+
+ RUM_LOCK_ASSERT(sc);
+
+ exp = ic->ic_lintval / bintval;
+ delay = ic->ic_lintval % bintval;
+
+ if (exp > RT2573_TBCN_EXP_MAX)
+ exp = RT2573_TBCN_EXP_MAX;
+ if (delay > RT2573_TBCN_DELAY_MAX)
+ delay = RT2573_TBCN_DELAY_MAX;
+
+ uerror = rum_modbits(sc, RT2573_MAC_CSR11,
+ RT2573_TBCN_EXP(exp) |
+ RT2573_TBCN_DELAY(delay),
+ RT2573_TBCN_EXP(RT2573_TBCN_EXP_MAX) |
+ RT2573_TBCN_DELAY(RT2573_TBCN_DELAY_MAX));
+
+ if (uerror != USB_ERR_NORMAL_COMPLETION)
+ return (EIO);
+
+ sc->sc_sleep_time = IEEE80211_TU_TO_TICKS(exp * bintval + delay);
+
+ return (0);
+}
+
+static int
+rum_reset(struct ieee80211vap *vap, u_long cmd)
+{
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_node *ni;
+ struct rum_softc *sc = ic->ic_softc;
+ int error;
+
+ switch (cmd) {
+ case IEEE80211_IOC_POWERSAVE:
+ error = 0;
+ break;
+ case IEEE80211_IOC_POWERSAVESLEEP:
+ ni = ieee80211_ref_node(vap->iv_bss);
+
+ RUM_LOCK(sc);
+ error = rum_set_sleep_time(sc, ni->ni_intval);
+ if (vap->iv_state == IEEE80211_S_SLEEP) {
+ /* Use new values for wakeup timer. */
+ rum_clrbits(sc, RT2573_MAC_CSR11, RT2573_AUTO_WAKEUP);
+ rum_setbits(sc, RT2573_MAC_CSR11, RT2573_AUTO_WAKEUP);
+ }
+ /* XXX send reassoc */
+ RUM_UNLOCK(sc);
+
+ ieee80211_free_node(ni);
+ break;
+ default:
+ error = ENETRESET;
+ break;
+ }
+
+ return (error);
+}
+
+static int
rum_set_beacon(struct rum_softc *sc, struct ieee80211vap *vap)
{
struct ieee80211com *ic = vap->iv_ic;
@@ -2924,14 +3144,15 @@ rum_scan_end(struct ieee80211com *ic)
{
struct rum_softc *sc = ic->ic_softc;
- RUM_LOCK(sc);
- if (ic->ic_opmode != IEEE80211_M_AHDEMO)
- rum_enable_tsf_sync(sc);
- else
- rum_enable_tsf(sc);
- rum_set_bssid(sc, sc->sc_bssid);
- RUM_UNLOCK(sc);
-
+ if (ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN) {
+ RUM_LOCK(sc);
+ if (ic->ic_opmode != IEEE80211_M_AHDEMO)
+ rum_enable_tsf_sync(sc);
+ else
+ rum_enable_tsf(sc);
+ rum_set_bssid(sc, sc->sc_bssid);
+ RUM_UNLOCK(sc);
+ }
}
static void
diff --git a/sys/dev/usb/wlan/if_rumreg.h b/sys/dev/usb/wlan/if_rumreg.h
index 06c0a81..96726b1 100644
--- a/sys/dev/usb/wlan/if_rumreg.h
+++ b/sys/dev/usb/wlan/if_rumreg.h
@@ -136,6 +136,13 @@
/* possible flags for register MAC_CSR5 */
#define RT2573_NUM_BSSID_MSK(n) (((n * 3) & 3) << 16)
+/* possible flags for register MAC_CSR11 */
+#define RT2573_AUTO_WAKEUP (1 << 15)
+#define RT2573_TBCN_EXP(n) ((n) << 8)
+#define RT2573_TBCN_EXP_MAX 0x7f
+#define RT2573_TBCN_DELAY(t) (t)
+#define RT2573_TBCN_DELAY_MAX 0xff
+
/* possible flags for register TXRX_CSR0 */
/* Tx filter flags are in the low 16 bits */
#define RT2573_AUTO_TX_SEQ (1 << 15)
@@ -152,6 +159,7 @@
#define RT2573_DROP_ACKCTS (1 << 25)
/* possible flags for register TXRX_CSR4 */
+#define RT2573_ACKCTS_PWRMGT (1 << 16)
#define RT2573_SHORT_PREAMBLE (1 << 18)
#define RT2573_MRR_ENABLED (1 << 19)
#define RT2573_MRR_CCK_FALLBACK (1 << 22)
@@ -188,7 +196,10 @@
#define RT2573_LED_ON 0x1e1e
#define RT2573_LED_OFF 0x0
-#define RT2573_MCU_RUN (1 << 3)
+/* USB vendor requests */
+#define RT2573_MCU_SLEEP 7
+#define RT2573_MCU_RUN 8
+#define RT2573_MCU_WAKEUP 9
#define RT2573_SMART_MODE (1 << 0)
diff --git a/sys/dev/usb/wlan/if_rumvar.h b/sys/dev/usb/wlan/if_rumvar.h
index d494468..6c42569 100644
--- a/sys/dev/usb/wlan/if_rumvar.h
+++ b/sys/dev/usb/wlan/if_rumvar.h
@@ -96,6 +96,11 @@ struct rum_vap {
int (*newstate)(struct ieee80211vap *,
enum ieee80211_state, int);
+ void (*bmiss)(struct ieee80211vap *);
+ void (*recv_mgmt)(struct ieee80211_node *,
+ struct mbuf *, int,
+ const struct ieee80211_rx_stats *,
+ int, int);
};
#define RUM_VAP(vap) ((struct rum_vap *)(vap))
@@ -124,6 +129,10 @@ struct rum_softc {
struct mtx sc_mtx;
+ int sc_sleep_end;
+ int sc_sleep_time;
+ uint8_t last_rx_flags;
+
struct rum_cmdq cmdq[RUM_CMDQ_SIZE];
struct mtx cmdq_mtx;
struct task cmdq_task;
@@ -135,6 +144,7 @@ struct rum_softc {
uint8_t txpow[44];
u_int sc_detached:1,
sc_running:1,
+ sc_sleeping:1,
sc_clr_shkeys:1;
uint8_t sc_bssid[IEEE80211_ADDR_LEN];
diff --git a/sys/dev/vnic/nic_main.c b/sys/dev/vnic/nic_main.c
index 0b21952..ae04326 100644
--- a/sys/dev/vnic/nic_main.c
+++ b/sys/dev/vnic/nic_main.c
@@ -119,7 +119,7 @@ static int nicpf_detach(device_t);
#ifdef PCI_IOV
static int nicpf_iov_init(device_t, uint16_t, const nvlist_t *);
static void nicpf_iov_uninit(device_t);
-static int nicpf_iov_addr_vf(device_t, uint16_t, const nvlist_t *);
+static int nicpf_iov_add_vf(device_t, uint16_t, const nvlist_t *);
#endif
static device_method_t nicpf_methods[] = {
@@ -131,7 +131,7 @@ static device_method_t nicpf_methods[] = {
#ifdef PCI_IOV
DEVMETHOD(pci_iov_init, nicpf_iov_init),
DEVMETHOD(pci_iov_uninit, nicpf_iov_uninit),
- DEVMETHOD(pci_iov_add_vf, nicpf_iov_addr_vf),
+ DEVMETHOD(pci_iov_add_vf, nicpf_iov_add_vf),
#endif
DEVMETHOD_END,
};
@@ -269,18 +269,9 @@ nicpf_iov_init(device_t dev, uint16_t num_vfs, const nvlist_t *params)
nic = device_get_softc(dev);
- nic->num_vf_en = 0;
if (num_vfs == 0)
return (ENXIO);
- if (num_vfs > MAX_NUM_VFS_SUPPORTED)
- return (EINVAL);
- /*
- * Just set variables here.
- * The number of VFs will be written to configuration
- * space later in PCI_ADD_VF().
- */
- nic->num_vf_en = num_vfs;
nic->flags |= NIC_SRIOV_ENABLED;
return (0);
@@ -294,7 +285,7 @@ nicpf_iov_uninit(device_t dev)
}
static int
-nicpf_iov_addr_vf(device_t dev, uint16_t vfnum, const nvlist_t *params)
+nicpf_iov_add_vf(device_t dev, uint16_t vfnum, const nvlist_t *params)
{
const void *mac;
struct nicpf *nic;
@@ -306,6 +297,9 @@ nicpf_iov_addr_vf(device_t dev, uint16_t vfnum, const nvlist_t *params)
if ((nic->flags & NIC_SRIOV_ENABLED) == 0)
return (ENXIO);
+ if (vfnum > (nic->num_vf_en - 1))
+ return (EINVAL);
+
if (nvlist_exists_binary(params, "mac-addr") != 0) {
mac = nvlist_get_binary(params, "mac-addr", &size);
bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vfnum]);
@@ -1094,11 +1088,8 @@ static int nic_sriov_init(device_t dev, struct nicpf *nic)
}
/* Fix-up the number of enabled VFs */
total_vf_cnt = pci_read_config(dev, iov_pos + PCIR_SRIOV_TOTAL_VFS, 2);
- if (total_vf_cnt < nic->num_vf_en)
- nic->num_vf_en = total_vf_cnt;
-
if (total_vf_cnt == 0)
- return (0);
+ return (ENXIO);
/* Attach SR-IOV */
pf_schema = pci_iov_schema_alloc_node();
@@ -1116,7 +1107,6 @@ static int nic_sriov_init(device_t dev, struct nicpf *nic)
device_printf(dev,
"Failed to initialize SR-IOV (error=%d)\n",
err);
- nic->num_vf_en = 0;
return (err);
}
#endif
diff --git a/sys/dev/vnic/nicvf_main.c b/sys/dev/vnic/nicvf_main.c
index 4625846..5b74ac9 100644
--- a/sys/dev/vnic/nicvf_main.c
+++ b/sys/dev/vnic/nicvf_main.c
@@ -661,12 +661,6 @@ nicvf_if_transmit(struct ifnet *ifp, struct mbuf *mbuf)
sq = &qs->sq[qidx];
- if ((if_getdrvflags(ifp) & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
- IFF_DRV_RUNNING) {
- err = drbr_enqueue(ifp, sq->br, mbuf);
- return (err);
- }
-
if (mbuf->m_next != NULL &&
(mbuf->m_pkthdr.csum_flags &
(CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_SCTP)) != 0) {
@@ -679,17 +673,23 @@ nicvf_if_transmit(struct ifnet *ifp, struct mbuf *mbuf)
}
}
+ err = drbr_enqueue(ifp, sq->br, mbuf);
+ if (((if_getdrvflags(ifp) & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
+ IFF_DRV_RUNNING) || !nic->link_up || (err != 0)) {
+ /*
+ * Try to enqueue packet to the ring buffer.
+ * If the driver is not active, link down or enqueue operation
+ * failed, return with the appropriate error code.
+ */
+ return (err);
+ }
+
if (NICVF_TX_TRYLOCK(sq) != 0) {
- err = nicvf_tx_mbuf_locked(sq, mbuf);
+ err = nicvf_xmit_locked(sq);
NICVF_TX_UNLOCK(sq);
return (err);
- } else {
- err = drbr_enqueue(ifp, sq->br, mbuf);
- if (err != 0)
- return (err);
-
+ } else
taskqueue_enqueue(sq->snd_taskq, &sq->snd_task);
- }
return (0);
}
diff --git a/sys/dev/vnic/nicvf_queues.c b/sys/dev/vnic/nicvf_queues.c
index 13ea636..9b46d7c 100644
--- a/sys/dev/vnic/nicvf_queues.c
+++ b/sys/dev/vnic/nicvf_queues.c
@@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/sockio.h>
#include <sys/socket.h>
-#include <sys/stdatomic.h>
#include <sys/cpuset.h>
#include <sys/lock.h>
#include <sys/mutex.h>
@@ -61,11 +60,12 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/vmparam.h>
-#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_media.h>
#include <net/ifq.h>
+#include <net/bpf.h>
+#include <net/ethernet.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
@@ -106,6 +106,8 @@ static void nicvf_cmp_queue_config(struct nicvf *, struct queue_set *, int,
boolean_t);
static void nicvf_sq_free_used_descs(struct nicvf *, struct snd_queue *, int);
+static int nicvf_tx_mbuf_locked(struct snd_queue *, struct mbuf **);
+
static void nicvf_rbdr_task(void *, int);
static void nicvf_rbdr_task_nowait(void *, int);
@@ -740,10 +742,10 @@ nicvf_cq_intr_handler(struct nicvf *nic, uint8_t cq_idx)
int cqe_count, cqe_head;
struct queue_set *qs = nic->qs;
struct cmp_queue *cq = &qs->cq[cq_idx];
+ struct snd_queue *sq = &qs->sq[cq_idx];
struct rcv_queue *rq;
struct cqe_rx_t *cq_desc;
struct lro_ctrl *lro;
- struct lro_entry *queued;
int rq_idx;
int cmp_err;
@@ -819,6 +821,7 @@ done:
((if_getdrvflags(nic->ifp) & IFF_DRV_RUNNING) != 0)) {
/* Reenable TXQ if its stopped earlier due to SQ full */
if_setdrvflagbits(nic->ifp, IFF_DRV_RUNNING, IFF_DRV_OACTIVE);
+ taskqueue_enqueue(sq->snd_taskq, &sq->snd_task);
}
out:
/*
@@ -827,10 +830,7 @@ out:
rq_idx = cq_idx;
rq = &nic->qs->rq[rq_idx];
lro = &rq->lro;
- while ((queued = SLIST_FIRST(&lro->lro_active)) != NULL) {
- SLIST_REMOVE_HEAD(&lro->lro_active, next);
- tcp_lro_flush(lro, queued);
- }
+ tcp_lro_flush_all(lro);
NICVF_CMP_UNLOCK(cq);
@@ -992,25 +992,62 @@ nicvf_free_cmp_queue(struct nicvf *nic, struct cmp_queue *cq)
memset(cq->mtx_name, 0, sizeof(cq->mtx_name));
}
-static void
-nicvf_snd_task(void *arg, int pending)
+int
+nicvf_xmit_locked(struct snd_queue *sq)
{
- struct snd_queue *sq = (struct snd_queue *)arg;
- struct mbuf *mbuf;
+ struct nicvf *nic;
+ struct ifnet *ifp;
+ struct mbuf *next;
+ int err;
- NICVF_TX_LOCK(sq);
- while (1) {
- mbuf = drbr_dequeue(NULL, sq->br);
- if (mbuf == NULL)
- break;
+ NICVF_TX_LOCK_ASSERT(sq);
+
+ nic = sq->nic;
+ ifp = nic->ifp;
+ err = 0;
+
+ while ((next = drbr_peek(ifp, sq->br)) != NULL) {
+ err = nicvf_tx_mbuf_locked(sq, &next);
+ if (err != 0) {
+ if (next == NULL)
+ drbr_advance(ifp, sq->br);
+ else
+ drbr_putback(ifp, sq->br, next);
- if (nicvf_tx_mbuf_locked(sq, mbuf) != 0) {
- /* XXX ARM64TODO: Increase Tx drop counter */
- m_freem(mbuf);
break;
}
+ drbr_advance(ifp, sq->br);
+ /* Send a copy of the frame to the BPF listener */
+ ETHER_BPF_MTAP(ifp, next);
}
+ return (err);
+}
+
+static void
+nicvf_snd_task(void *arg, int pending)
+{
+ struct snd_queue *sq = (struct snd_queue *)arg;
+ struct nicvf *nic;
+ struct ifnet *ifp;
+ int err;
+
+ nic = sq->nic;
+ ifp = nic->ifp;
+
+ /*
+ * Skip sending anything if the driver is not running,
+ * SQ full or link is down.
+ */
+ if (((if_getdrvflags(ifp) & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
+ IFF_DRV_RUNNING) || !nic->link_up)
+ return;
+
+ NICVF_TX_LOCK(sq);
+ err = nicvf_xmit_locked(sq);
NICVF_TX_UNLOCK(sq);
+ /* Try again */
+ if (err != 0)
+ taskqueue_enqueue(sq->snd_taskq, &sq->snd_task);
}
/* Initialize transmit queue */
@@ -1048,7 +1085,7 @@ nicvf_init_snd_queue(struct nicvf *nic, struct snd_queue *sq, int q_len,
sq->desc = sq->dmem.base;
sq->head = sq->tail = 0;
- atomic_store_rel_int(&sq->free_cnt, q_len - 1);
+ sq->free_cnt = q_len - 1;
sq->thresh = SND_QUEUE_THRESH;
sq->idx = qidx;
sq->nic = nic;
@@ -1640,7 +1677,7 @@ nicvf_get_sq_desc(struct snd_queue *sq, int desc_cnt)
int qentry;
qentry = sq->tail;
- atomic_subtract_int(&sq->free_cnt, desc_cnt);
+ sq->free_cnt -= desc_cnt;
sq->tail += desc_cnt;
sq->tail &= (sq->dmem.q_len - 1);
@@ -1652,7 +1689,7 @@ static void
nicvf_put_sq_desc(struct snd_queue *sq, int desc_cnt)
{
- atomic_add_int(&sq->free_cnt, desc_cnt);
+ sq->free_cnt += desc_cnt;
sq->head += desc_cnt;
sq->head &= (sq->dmem.q_len - 1);
}
@@ -1772,7 +1809,6 @@ nicvf_sq_add_hdr_subdesc(struct snd_queue *sq, int qentry,
}
ip = (struct ip *)(mbuf->m_data + ehdrlen);
- ip->ip_sum = 0;
iphlen = ip->ip_hl << 2;
poff = ehdrlen + iphlen;
@@ -1864,8 +1900,8 @@ static inline void nicvf_sq_add_gather_subdesc(struct snd_queue *sq, int qentry,
}
/* Put an mbuf to a SQ for packet transfer. */
-int
-nicvf_tx_mbuf_locked(struct snd_queue *sq, struct mbuf *mbuf)
+static int
+nicvf_tx_mbuf_locked(struct snd_queue *sq, struct mbuf **mbufp)
{
bus_dma_segment_t segs[256];
struct nicvf *nic;
@@ -1883,15 +1919,17 @@ nicvf_tx_mbuf_locked(struct snd_queue *sq, struct mbuf *mbuf)
snd_buff = &sq->snd_buff[sq->tail];
err = bus_dmamap_load_mbuf_sg(sq->snd_buff_dmat, snd_buff->dmap,
- mbuf, segs, &nsegs, BUS_DMA_NOWAIT);
- if (err != 0) {
+ *mbufp, segs, &nsegs, BUS_DMA_NOWAIT);
+ if (__predict_false(err != 0)) {
/* ARM64TODO: Add mbuf defragmenting if we lack maps */
+ m_freem(*mbufp);
+ *mbufp = NULL;
return (err);
}
/* Set how many subdescriptors is required */
nic = sq->nic;
- if (mbuf->m_pkthdr.tso_segsz != 0 && nic->hw_tso)
+ if ((*mbufp)->m_pkthdr.tso_segsz != 0 && nic->hw_tso)
subdesc_cnt = MIN_SQ_DESC_PER_PKT_XMIT;
else
subdesc_cnt = MIN_SQ_DESC_PER_PKT_XMIT + nsegs - 1;
@@ -1905,10 +1943,15 @@ nicvf_tx_mbuf_locked(struct snd_queue *sq, struct mbuf *mbuf)
qentry = nicvf_get_sq_desc(sq, subdesc_cnt);
/* Add SQ header subdesc */
- err = nicvf_sq_add_hdr_subdesc(sq, qentry, subdesc_cnt - 1, mbuf,
- mbuf->m_pkthdr.len);
+ err = nicvf_sq_add_hdr_subdesc(sq, qentry, subdesc_cnt - 1, *mbufp,
+ (*mbufp)->m_pkthdr.len);
if (err != 0) {
+ nicvf_put_sq_desc(sq, subdesc_cnt);
bus_dmamap_unload(sq->snd_buff_dmat, snd_buff->dmap);
+ if (err == ENOBUFS) {
+ m_freem(*mbufp);
+ *mbufp = NULL;
+ }
return (err);
}
@@ -1985,19 +2028,23 @@ nicvf_get_rcv_mbuf(struct nicvf *nic, struct cqe_rx_t *cqe_rx)
/*
* HW by default verifies IP & TCP/UDP/SCTP checksums
*/
-
- /* XXX: Do we need to include IP with options too? */
- if (__predict_true(cqe_rx->l3_type == L3TYPE_IPV4 ||
- cqe_rx->l3_type == L3TYPE_IPV6)) {
+ if (__predict_true(cqe_rx->l3_type == L3TYPE_IPV4)) {
mbuf->m_pkthdr.csum_flags =
(CSUM_IP_CHECKED | CSUM_IP_VALID);
}
- if (cqe_rx->l4_type == L4TYPE_TCP ||
- cqe_rx->l4_type == L4TYPE_UDP ||
- cqe_rx->l4_type == L4TYPE_SCTP) {
+
+ switch (cqe_rx->l4_type) {
+ case L4TYPE_UDP:
+ case L4TYPE_TCP: /* fall through */
mbuf->m_pkthdr.csum_flags |=
(CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
- mbuf->m_pkthdr.csum_data = htons(0xffff);
+ mbuf->m_pkthdr.csum_data = 0xffff;
+ break;
+ case L4TYPE_SCTP:
+ mbuf->m_pkthdr.csum_flags |= CSUM_SCTP_VALID;
+ break;
+ default:
+ break;
}
}
}
diff --git a/sys/dev/vnic/nicvf_queues.h b/sys/dev/vnic/nicvf_queues.h
index 8a27880..0fe8e3b 100644
--- a/sys/dev/vnic/nicvf_queues.h
+++ b/sys/dev/vnic/nicvf_queues.h
@@ -388,7 +388,7 @@ void nicvf_disable_intr(struct nicvf *, int, int);
void nicvf_clear_intr(struct nicvf *, int, int);
int nicvf_is_intr_enabled(struct nicvf *, int, int);
-int nicvf_tx_mbuf_locked(struct snd_queue *, struct mbuf *);
+int nicvf_xmit_locked(struct snd_queue *sq);
/* Register access APIs */
void nicvf_reg_write(struct nicvf *, uint64_t, uint64_t);
diff --git a/sys/dev/vnic/thunder_bgx_fdt.c b/sys/dev/vnic/thunder_bgx_fdt.c
index ec6e68f..b4d77cf 100644
--- a/sys/dev/vnic/thunder_bgx_fdt.c
+++ b/sys/dev/vnic/thunder_bgx_fdt.c
@@ -285,18 +285,9 @@ bgx_fdt_init_phy(struct bgx *bgx)
continue;
}
- if (OF_getencprop(child, "phy-handle", &phy,
- sizeof(phy)) <= 0) {
- if (bootverbose) {
- device_printf(bgx->dev,
- "No phy-handle in PHY node. Skipping...\n");
- }
- continue;
- }
/* Acquire PHY address */
- phy = OF_node_from_xref(phy);
- if (OF_getencprop(phy, "reg", &bgx->lmac[lmac].phyaddr,
+ if (OF_getencprop(child, "reg", &bgx->lmac[lmac].phyaddr,
sizeof(bgx->lmac[lmac].phyaddr)) <= 0) {
if (bootverbose) {
device_printf(bgx->dev,
@@ -305,6 +296,15 @@ bgx_fdt_init_phy(struct bgx *bgx)
bgx->lmac[lmac].phyaddr = MII_PHY_ANY;
}
+ if (OF_getencprop(child, "phy-handle", &phy,
+ sizeof(phy)) <= 0) {
+ if (bootverbose) {
+ device_printf(bgx->dev,
+ "No phy-handle in PHY node. Skipping...\n");
+ }
+ continue;
+ }
+ phy = OF_instance_to_package(phy);
/*
* Get PHY interface (MDIO bus) device.
* Driver must be already attached.
@@ -321,7 +321,7 @@ bgx_fdt_init_phy(struct bgx *bgx)
}
/* Get mac address from FDT */
- bgx_fdt_get_macaddr(phy, bgx->lmac[lmac].mac);
+ bgx_fdt_get_macaddr(child, bgx->lmac[lmac].mac);
bgx->lmac[lmac].lmacid = lmac;
lmac++;
diff --git a/sys/dev/vt/hw/vga/vt_vga.c b/sys/dev/vt/hw/vga/vt_vga.c
index 4661f35..62c9bf3 100644
--- a/sys/dev/vt/hw/vga/vt_vga.c
+++ b/sys/dev/vt/hw/vga/vt_vga.c
@@ -1214,7 +1214,6 @@ vga_init(struct vt_device *vd)
if (vd->vd_softc == NULL)
vd->vd_softc = (void *)&vga_conssoftc;
sc = vd->vd_softc;
- textmode = 0;
if (vd->vd_flags & VDF_DOWNGRADE && vd->vd_video_dev != NULL)
vga_pci_repost(vd->vd_video_dev);
@@ -1229,6 +1228,13 @@ vga_init(struct vt_device *vd)
bus_space_map(sc->vga_reg_tag, VGA_REG_BASE, VGA_REG_SIZE, 0,
&sc->vga_reg_handle);
+ /*
+ * If "hw.vga.textmode" is not set and we're running on hypervisor,
+ * we use text mode by default, this is because when we're on
+ * hypervisor, vt(4) is usually much slower in graphics mode than
+ * in text mode, especially when we're on Hyper-V.
+ */
+ textmode = vm_guest != VM_GUEST_NO;
TUNABLE_INT_FETCH("hw.vga.textmode", &textmode);
if (textmode) {
vd->vd_flags |= VDF_TEXTMODE;
diff --git a/sys/dev/vxge/vxge.c b/sys/dev/vxge/vxge.c
index 9a3cab6..84320f6 100644
--- a/sys/dev/vxge/vxge.c
+++ b/sys/dev/vxge/vxge.c
@@ -996,7 +996,6 @@ vxge_rx_compl(vxge_hal_vpath_h vpath_handle, vxge_hal_rxd_h rxdh,
vxge_vpath_t *vpath = (vxge_vpath_t *) userdata;
vxge_dev_t *vdev = vpath->vdev;
- struct lro_entry *queued = NULL;
struct lro_ctrl *lro = &vpath->lro;
/* get the interface pointer */
@@ -1083,12 +1082,8 @@ vxge_rx_compl(vxge_hal_vpath_h vpath_handle, vxge_hal_rxd_h rxdh,
&dtr_priv, &t_code) == VXGE_HAL_OK);
/* Flush any outstanding LRO work */
- if (vpath->lro_enable && vpath->lro.lro_cnt) {
- while ((queued = SLIST_FIRST(&lro->lro_active)) != NULL) {
- SLIST_REMOVE_HEAD(&lro->lro_active, next);
- tcp_lro_flush(lro, queued);
- }
- }
+ if (vpath->lro_enable && vpath->lro.lro_cnt)
+ tcp_lro_flush_all(lro);
return (status);
}
diff --git a/sys/dev/wbwd/wbwd.c b/sys/dev/wbwd/wbwd.c
index 484b5bf..53e9084 100644
--- a/sys/dev/wbwd/wbwd.c
+++ b/sys/dev/wbwd/wbwd.c
@@ -91,8 +91,11 @@ __FBSDID("$FreeBSD$");
#define WB_LDN8_CRF7_FORCE 0x20 /* 1: force timeout (self-clear) */
#define WB_LDN8_CRF7_TS 0x10 /* 0: counting, 1: fired */
#define WB_LDN8_CRF7_IRQS 0x0f /* irq source for watchdog, 2 == SMI */
-#define WB_LDN8_CRF7_CLEAR_MASK \
- (WB_LDN8_CRF7_MOUSE|WB_LDN8_CRF7_KEYB|WB_LDN8_CRF7_TS|WB_LDN8_CRF7_IRQS)
+
+enum chips { w83627hf, w83627s, w83697hf, w83697ug, w83637hf, w83627thf,
+ w83687thf, w83627ehf, w83627dhg, w83627uhg, w83667hg,
+ w83627dhg_p, w83667hg_b, nct6775, nct6776, nct6779, nct6791,
+ nct6792, nct6102 };
struct wb_softc {
device_t dev;
@@ -103,6 +106,10 @@ struct wb_softc {
eventhandler_tag ev_tag;
int (*ext_cfg_enter_f)(struct wb_softc *, u_short);
void (*ext_cfg_exit_f)(struct wb_softc *, u_short);
+ enum chips chip;
+ uint8_t ctl_reg;
+ uint8_t time_reg;
+ uint8_t csr_reg;
int debug_verbose;
/*
@@ -144,46 +151,104 @@ struct winbond_superio_cfg {
};
struct winbond_vendor_device_id {
- uint16_t vendor_id;
uint8_t device_id;
- uint8_t device_rev;
+ enum chips chip;
const char * descr;
} wb_devs[] = {
{
- .vendor_id = 0x5ca3,
.device_id = 0x52,
- .device_rev = 0x17,
- .descr = "Winbond 83627HF/F/HG/G Rev. G",
+ .chip = w83627hf,
+ .descr = "Winbond 83627HF/F/HG/G",
},
{
- .vendor_id = 0x5ca3,
- .device_id = 0x52,
- .device_rev = 0x3a,
- .descr = "Winbond 83627HF/F/HG/G Rev. J",
+ .device_id = 0x59,
+ .chip = w83627s,
+ .descr = "Winbond 83627S",
},
{
- .vendor_id = 0x5ca3,
- .device_id = 0x52,
- .device_rev = 0x41,
- .descr = "Winbond 83627HF/F/HG/G Rev. UD-A",
+ .device_id = 0x60,
+ .chip = w83697hf,
+ .descr = "Winbond 83697HF",
+ },
+ {
+ .device_id = 0x68,
+ .chip = w83697ug,
+ .descr = "Winbond 83697UG",
+ },
+ {
+ .device_id = 0x70,
+ .chip = w83637hf,
+ .descr = "Winbond 83637HF",
+ },
+ {
+ .device_id = 0x82,
+ .chip = w83627thf,
+ .descr = "Winbond 83627THF",
+ },
+ {
+ .device_id = 0x85,
+ .chip = w83687thf,
+ .descr = "Winbond 83687THF",
+ },
+ {
+ .device_id = 0x88,
+ .chip = w83627ehf,
+ .descr = "Winbond 83627EHF",
},
{
- .vendor_id = 0x5ca3,
.device_id = 0xa0,
- .device_rev = 0x25,
- .descr = "Winbond 83627DHG IC ver. 5",
+ .chip = w83627dhg,
+ .descr = "Winbond 83627DHG",
+ },
+ {
+ .device_id = 0xa2,
+ .chip = w83627uhg,
+ .descr = "Winbond 83627UHG",
+ },
+ {
+ .device_id = 0xa5,
+ .chip = w83667hg,
+ .descr = "Winbond 83667HG",
},
{
- .vendor_id = 0x5ca3,
.device_id = 0xb0,
- .device_rev = 0x73,
- .descr = "Winbond 83627DHG-P",
+ .chip = w83627dhg_p,
+ .descr = "Winbond 83627DHG-P",
+ },
+ {
+ .device_id = 0xb3,
+ .chip = w83667hg_b,
+ .descr = "Winbond 83667HG-B",
+ },
+ {
+ .device_id = 0xb4,
+ .chip = nct6775,
+ .descr = "Nuvoton NCT6775",
},
{
- .vendor_id = 0x5ca3,
.device_id = 0xc3,
- .device_rev = 0x33,
- .descr = "Nuvoton WPCM450RA0BX",
+ .chip = nct6776,
+ .descr = "Nuvoton NCT6776",
+ },
+ {
+ .device_id = 0xc4,
+ .chip = nct6102,
+ .descr = "Nuvoton NCT6102",
+ },
+ {
+ .device_id = 0xc5,
+ .chip = nct6779,
+ .descr = "Nuvoton NCT6779",
+ },
+ {
+ .device_id = 0xc8,
+ .chip = nct6791,
+ .descr = "Nuvoton NCT6791",
+ },
+ {
+ .device_id = 0xc9,
+ .chip = nct6792,
+ .descr = "Nuvoton NCT6792",
},
};
@@ -231,6 +296,22 @@ read_efdr_1(struct wb_softc *sc, u_short baseport)
return (inb(baseport + 1));
}
+static void
+write_reg(struct wb_softc *sc, uint8_t reg, uint8_t value)
+{
+
+ write_efir_1(sc, 0, reg);
+ write_efdr_1(sc, 0, value);
+}
+
+static uint8_t
+read_reg(struct wb_softc *sc, uint8_t reg)
+{
+
+ write_efir_1(sc, 0, reg);
+ return (read_efdr_1(sc, 0));
+}
+
/*
* Return the watchdog related registers as we last read them. This will
* usually not give the current timeout or state on whether the watchdog
@@ -248,9 +329,9 @@ sysctl_wb_debug(SYSCTL_HANDLER_ARGS)
sbuf_new_for_sysctl(&sb, NULL, 64, req);
sbuf_printf(&sb, "LDN8 (GPIO2, Watchdog): ");
- sbuf_printf(&sb, "CRF5 0x%02x ", sc->reg_1);
- sbuf_printf(&sb, "CRF6 0x%02x ", sc->reg_timeout);
- sbuf_printf(&sb, "CRF7 0x%02x", sc->reg_2);
+ sbuf_printf(&sb, "CR%02X 0x%02x ", sc->ctl_reg, sc->reg_1);
+ sbuf_printf(&sb, "CR%02X 0x%02x ", sc->time_reg, sc->reg_timeout);
+ sbuf_printf(&sb, "CR%02X 0x%02x", sc->csr_reg, sc->reg_2);
error = sbuf_finish(&sb);
sbuf_delete(&sb);
@@ -269,23 +350,17 @@ sysctl_wb_debug_current(SYSCTL_HANDLER_ARGS)
sc = arg1;
- /*
- * Enter extended function mode in case someone else has been
- * poking on the registers. We will not leave it though.
- */
if ((*sc->ext_cfg_enter_f)(sc, 0) != 0)
return (ENXIO);
/* Watchdog is configured as part of LDN 8 (GPIO Port2, Watchdog). */
- write_efir_1(sc, 0, WB_LDN_REG);
- write_efdr_1(sc, 0, WB_LDN_REG_LDN8);
+ write_reg(sc, WB_LDN_REG, WB_LDN_REG_LDN8);
+
+ sc->reg_1 = read_reg(sc, sc->ctl_reg);
+ sc->reg_timeout = read_reg(sc, sc->time_reg);
+ sc->reg_2 = read_reg(sc, sc->csr_reg);
- write_efir_1(sc, 0, WB_LDN8_CRF5);
- sc->reg_1 = read_efdr_1(sc, 0);
- write_efir_1(sc, 0, WB_LDN8_CRF6);
- sc->reg_timeout = read_efdr_1(sc, 0);
- write_efir_1(sc, 0, WB_LDN8_CRF7);
- sc->reg_2 = read_efdr_1(sc, 0);
+ (*sc->ext_cfg_exit_f)(sc, 0);
return (sysctl_wb_debug(oidp, arg1, arg2, req));
}
@@ -326,10 +401,6 @@ sysctl_wb_force_test_nmi(SYSCTL_HANDLER_ARGS)
}
#endif
- /*
- * Enter extended function mode in case someone else has been
- * poking on the registers. We will not leave it though.
- */
if ((*sc->ext_cfg_enter_f)(sc, 0) != 0)
return (ENXIO);
@@ -343,16 +414,14 @@ sysctl_wb_force_test_nmi(SYSCTL_HANDLER_ARGS)
#endif
/* Watchdog is configured as part of LDN 8 (GPIO Port2, Watchdog). */
- write_efir_1(sc, 0, WB_LDN_REG);
- write_efdr_1(sc, 0, WB_LDN_REG_LDN8);
+ write_reg(sc, WB_LDN_REG, WB_LDN_REG_LDN8);
/* Force watchdog to fire. */
- write_efir_1(sc, 0, WB_LDN8_CRF7);
- sc->reg_2 = read_efdr_1(sc, 0);
+ sc->reg_2 = read_reg(sc, sc->csr_reg);
sc->reg_2 |= WB_LDN8_CRF7_FORCE;
+ write_reg(sc, sc->csr_reg, sc->reg_2);
- write_efir_1(sc, 0, WB_LDN8_CRF7);
- write_efdr_1(sc, 0, sc->reg_2);
+ (*sc->ext_cfg_exit_f)(sc, 0);
return (0);
}
@@ -414,30 +483,36 @@ static int
wb_set_watchdog(struct wb_softc *sc, unsigned int timeout)
{
+ if (timeout != 0) {
+ /*
+ * In case an override is set, let it override. It may lead
+ * to strange results as we do not check the input of the sysctl.
+ */
+ if (sc->timeout_override > 0)
+ timeout = sc->timeout_override;
+
+ /* Make sure we support the requested timeout. */
+ if (timeout > 255 * 60)
+ return (EINVAL);
+ }
+
if (sc->debug_verbose)
wb_print_state(sc, "Before watchdog counter (re)load");
- /*
- * Enter extended function mode in case someone else has been
- * poking on the registers. We will not leave it though.
- */
if ((*sc->ext_cfg_enter_f)(sc, 0) != 0)
return (ENXIO);
/* Watchdog is configured as part of LDN 8 (GPIO Port2, Watchdog) */
- write_efir_1(sc, 0, WB_LDN_REG);
- write_efdr_1(sc, 0, WB_LDN_REG_LDN8);
+ write_reg(sc, WB_LDN_REG, WB_LDN_REG_LDN8);
/* Disable and validate or arm/reset watchdog. */
if (timeout == 0) {
/* Disable watchdog. */
- write_efir_1(sc, 0, WB_LDN8_CRF6);
- write_efdr_1(sc, 0, 0x00);
+ write_reg(sc, sc->time_reg, 0x00);
+ sc->reg_timeout = read_reg(sc, sc->time_reg);
+ (*sc->ext_cfg_exit_f)(sc, 0);
/* Re-check. */
- write_efir_1(sc, 0, WB_LDN8_CRF6);
- sc->reg_timeout = read_efdr_1(sc, 0);
-
if (sc->reg_timeout != 0x00) {
device_printf(sc->dev, "Failed to disable watchdog: "
"0x%02x.\n", sc->reg_timeout);
@@ -445,20 +520,8 @@ wb_set_watchdog(struct wb_softc *sc, unsigned int timeout)
}
} else {
- /*
- * In case an override is set, let it override. It may lead
- * to strange results as we do not check the input of the sysctl.
- */
- if (sc->timeout_override > 0)
- timeout = sc->timeout_override;
-
- /* Make sure we support the requested timeout. */
- if (timeout > 255 * 60)
- return (EINVAL);
-
/* Read current scaling factor. */
- write_efir_1(sc, 0, WB_LDN8_CRF5);
- sc->reg_1 = read_efdr_1(sc, 0);
+ sc->reg_1 = read_reg(sc, sc->ctl_reg);
if (timeout > 255) {
/* Set scaling factor to 60s. */
@@ -473,21 +536,18 @@ wb_set_watchdog(struct wb_softc *sc, unsigned int timeout)
}
/* In case we fired before we need to clear to fire again. */
- write_efir_1(sc, 0, WB_LDN8_CRF7);
- sc->reg_2 = read_efdr_1(sc, 0);
+ sc->reg_2 = read_reg(sc, sc->csr_reg);
if (sc->reg_2 & WB_LDN8_CRF7_TS) {
sc->reg_2 &= ~WB_LDN8_CRF7_TS;
- write_efir_1(sc, 0, WB_LDN8_CRF7);
- write_efdr_1(sc, 0, sc->reg_2);
+ write_reg(sc, sc->csr_reg, sc->reg_2);
}
/* Write back scaling factor. */
- write_efir_1(sc, 0, WB_LDN8_CRF5);
- write_efdr_1(sc, 0, sc->reg_1);
+ write_reg(sc, sc->ctl_reg, sc->reg_1);
/* Set timer and arm/reset the watchdog. */
- write_efir_1(sc, 0, WB_LDN8_CRF6);
- write_efdr_1(sc, 0, sc->reg_timeout);
+ write_reg(sc, sc->time_reg, sc->reg_timeout);
+ (*sc->ext_cfg_exit_f)(sc, 0);
}
if (sc->debug_verbose)
@@ -556,6 +616,7 @@ wb_probe_enable(device_t dev, int probe)
struct wb_softc *sc;
int error, found, i, j;
uint8_t dev_id, dev_rev, cr26;
+ char buf[128];
if (dev == NULL)
sc = NULL;
@@ -566,6 +627,7 @@ wb_probe_enable(device_t dev, int probe)
}
error = ENXIO;
+ found = 0;
for (i = 0; i < sizeof(probe_addrs) / sizeof(*probe_addrs); i++) {
if (sc != NULL) {
@@ -578,7 +640,6 @@ wb_probe_enable(device_t dev, int probe)
sc->bsh = rman_get_bushandle(sc->portres);
}
- found = 0;
error = (*probe_addrs[i].ext_cfg_enter_f)(sc, probe_addrs[i].efer);
if (error != 0)
goto cleanup;
@@ -591,6 +652,9 @@ wb_probe_enable(device_t dev, int probe)
write_efir_1(sc, probe_addrs[i].efer, WB_CR26);
cr26 = read_efdr_1(sc, probe_addrs[i].efer);
+ if (dev_id == 0xff && dev_rev == 0xff)
+ goto cleanup;
+
/* HEFRAS of 0 means EFER at 0x2e, 1 means EFER at 0x4e. */
if (((cr26 & 0x40) == 0x00 && probe_addrs[i].efer != 0x2e) ||
((cr26 & 0x40) == 0x40 && probe_addrs[i].efer != 0x4e)) {
@@ -602,36 +666,30 @@ wb_probe_enable(device_t dev, int probe)
goto cleanup;
}
- if (dev_id == 0xff && dev_rev == 0xff)
- goto cleanup;
-
for (j = 0; j < sizeof(wb_devs) / sizeof(*wb_devs); j++) {
- if (wb_devs[j].device_id == dev_id &&
- wb_devs[j].device_rev == dev_rev) {
- if (probe && dev != NULL)
- device_set_desc(dev, wb_devs[j].descr);
- found++;
+ if (wb_devs[j].device_id == dev_id) {
+ found = 1;
break;
}
}
- if (!found) {
- if (probe && dev != NULL) {
- device_set_desc(dev, "Unknown Winbond/Nuvoton model");
- device_printf(dev, "DevID 0x%02x DevRev 0x%02x, "
- "please report this.\n", dev_id, dev_rev);
- }
- found++;
+ if (probe && dev != NULL) {
+ snprintf(buf, sizeof(buf),
+ "%s (0x%02x/0x%02x) Watchdog Timer",
+ found ? wb_devs[j].descr :
+ "Unknown Winbond/Nuvoton", dev_id, dev_rev);
+ device_set_desc_copy(dev, buf);
+ }
+
+ /* If this is hinted attach, try to guess the model. */
+ if (dev != NULL && !found) {
+ found = 1;
+ j = 0;
}
- if (probe && found && bootverbose && dev != NULL)
- device_printf(dev, "%s EFER 0x%02x ID 0x%02x Rev 0x%02x"
- " CR26 0x%02x (probing)\n", device_get_desc(dev),
- probe_addrs[i].efer, dev_id, dev_rev, cr26);
cleanup:
if (probe || !found) {
(*probe_addrs[i].ext_cfg_exit_f)(sc, probe_addrs[i].efer);
-
if (sc != NULL)
(void) bus_release_resource(dev, SYS_RES_IOPORT,
sc->rid, sc->portres);
@@ -646,9 +704,21 @@ cleanup:
if (sc != NULL) {
sc->ext_cfg_enter_f = probe_addrs[i].ext_cfg_enter_f;
sc->ext_cfg_exit_f = probe_addrs[i].ext_cfg_exit_f;
+ sc->chip = wb_devs[j].chip;
+ sc->ctl_reg = 0xf5;
+ sc->time_reg = 0xf6;
+ sc->csr_reg = 0xf7;
+ if (sc->chip == w83697hf ||
+ sc->chip == w83697ug) {
+ sc->ctl_reg = 0xf3;
+ sc->time_reg = 0xf4;
+ } else if (sc->chip == nct6102) {
+ sc->ctl_reg = 0xf0;
+ sc->time_reg = 0xf1;
+ sc->csr_reg = 0xf2;
+ }
}
- error = BUS_PROBE_DEFAULT;
- break;
+ return (BUS_PROBE_SPECIFIC);
} else
error = ENXIO;
}
@@ -659,15 +729,10 @@ cleanup:
static void
wb_identify(driver_t *driver, device_t parent)
{
- device_t dev;
- if ((dev = device_find_child(parent, driver->name, 0)) == NULL) {
- if (wb_probe_enable(dev, 1) != BUS_PROBE_DEFAULT) {
- if (bootverbose)
- device_printf(dev, "can not find compatible Winbond chip.\n");
- } else
- dev = BUS_ADD_CHILD(parent, 0, driver->name, 0);
- return;
+ if (device_find_child(parent, driver->name, 0) == NULL) {
+ if (wb_probe_enable(NULL, 1) <= 0)
+ BUS_ADD_CHILD(parent, 0, driver->name, 0);
}
}
@@ -690,6 +755,7 @@ wb_attach(device_t dev)
struct sysctl_oid *soid;
unsigned long timeout;
int error;
+ uint8_t t;
error = wb_probe_enable(dev, 0);
if (error > 0)
@@ -700,37 +766,95 @@ wb_attach(device_t dev)
("%s: successfull probe result but not setup correctly", __func__));
/* Watchdog is configured as part of LDN 8 (GPIO Port2, Watchdog). */
- write_efir_1(sc, 0, WB_LDN_REG);
- write_efdr_1(sc, 0, WB_LDN_REG_LDN8);
-
- /* Make sure LDN8 is enabled (Do we need to? Also affects GPIO). */
- write_efir_1(sc, 0, WB_LDN8_CR30);
- write_efdr_1(sc, 0, WB_LDN8_CR30_ACTIVE);
+ write_reg(sc, WB_LDN_REG, WB_LDN_REG_LDN8);
+
+ /* Make sure WDT is enabled. */
+ write_reg(sc, WB_LDN8_CR30,
+ read_reg(sc, WB_LDN8_CR30) | WB_LDN8_CR30_ACTIVE);
+
+ switch (sc->chip) {
+ case w83627hf:
+ case w83627s:
+ t = read_reg(sc, 0x2B) & ~0x10;
+ write_reg(sc, 0x2B, t); /* set GPIO24 to WDT0 */
+ break;
+ case w83697hf:
+ /* Set pin 119 to WDTO# mode (= CR29, WDT0) */
+ t = read_reg(sc, 0x29) & ~0x60;
+ t |= 0x20;
+ write_reg(sc, 0x29, t);
+ break;
+ case w83697ug:
+ /* Set pin 118 to WDTO# mode */
+ t = read_reg(sc, 0x2b) & ~0x04;
+ write_reg(sc, 0x2b, t);
+ break;
+ case w83627thf:
+ t = (read_reg(sc, 0x2B) & ~0x08) | 0x04;
+ write_reg(sc, 0x2B, t); /* set GPIO3 to WDT0 */
+ break;
+ case w83627dhg:
+ case w83627dhg_p:
+ t = read_reg(sc, 0x2D) & ~0x01; /* PIN77 -> WDT0# */
+ write_reg(sc, 0x2D, t); /* set GPIO5 to WDT0 */
+ t = read_reg(sc, sc->ctl_reg);
+ t |= 0x02; /* enable the WDTO# output low pulse
+ * to the KBRST# pin */
+ write_reg(sc, sc->ctl_reg, t);
+ break;
+ case w83637hf:
+ break;
+ case w83687thf:
+ t = read_reg(sc, 0x2C) & ~0x80; /* PIN47 -> WDT0# */
+ write_reg(sc, 0x2C, t);
+ break;
+ case w83627ehf:
+ case w83627uhg:
+ case w83667hg:
+ case w83667hg_b:
+ case nct6775:
+ case nct6776:
+ case nct6779:
+ case nct6791:
+ case nct6792:
+ case nct6102:
+ /*
+ * These chips have a fixed WDTO# output pin (W83627UHG),
+ * or support more than one WDTO# output pin.
+ * Don't touch its configuration, and hope the BIOS
+ * does the right thing.
+ */
+ t = read_reg(sc, sc->ctl_reg);
+ t |= 0x02; /* enable the WDTO# output low pulse
+ * to the KBRST# pin */
+ write_reg(sc, sc->ctl_reg, t);
+ break;
+ default:
+ break;
+ }
/* Read the current watchdog configuration. */
- write_efir_1(sc, 0, WB_LDN8_CRF5);
- sc->reg_1 = read_efdr_1(sc, 0);
- write_efir_1(sc, 0, WB_LDN8_CRF6);
- sc->reg_timeout = read_efdr_1(sc, 0);
- write_efir_1(sc, 0, WB_LDN8_CRF7);
- sc->reg_2 = read_efdr_1(sc, 0);
+ sc->reg_1 = read_reg(sc, sc->ctl_reg);
+ sc->reg_timeout = read_reg(sc, sc->time_reg);
+ sc->reg_2 = read_reg(sc, sc->csr_reg);
/* Print current state if bootverbose or watchdog already enabled. */
if (bootverbose || (sc->reg_timeout > 0x00))
wb_print_state(sc, "Before watchdog attach");
+ sc->reg_1 &= ~WB_LDN8_CRF5_KEYB_P20;
+ sc->reg_1 |= WB_LDN8_CRF5_KBRST;
+ write_reg(sc, sc->ctl_reg, sc->reg_1);
+
/*
- * Clear a previous watchdog timeout event (if (still) set).
- * Disable all all interrupt reset sources (defaults).
+ * Clear a previous watchdog timeout event (if still set).
+ * Disable timer reset on mouse interrupts. Leave reset on keyboard,
+ * since one of my boards is getting stuck in reboot without it.
*/
- sc->reg_1 &= ~(WB_LDN8_CRF5_KEYB_P20);
- sc->reg_1 |= WB_LDN8_CRF5_KBRST;
- write_efir_1(sc, 0, WB_LDN8_CRF5);
- write_efdr_1(sc, 0, sc->reg_1);
+ sc->reg_2 &= ~(WB_LDN8_CRF7_MOUSE|WB_LDN8_CRF7_TS);
+ write_reg(sc, sc->csr_reg, sc->reg_2);
- sc->reg_2 &= ~WB_LDN8_CRF7_CLEAR_MASK;
- write_efir_1(sc, 0, WB_LDN8_CRF7);
- write_efdr_1(sc, 0, sc->reg_2);
+ (*sc->ext_cfg_exit_f)(sc, 0);
/* Read global timeout override tunable, Add per device sysctls. */
if (TUNABLE_ULONG_FETCH("hw.wbwd.timeout_override", &timeout)) {
diff --git a/sys/dev/wl/if_wl.c b/sys/dev/wl/if_wl.c
index 7146a25..6414d33 100644
--- a/sys/dev/wl/if_wl.c
+++ b/sys/dev/wl/if_wl.c
@@ -495,7 +495,7 @@ wlattach(device_t device)
}
#ifdef WLDEBUG
- printf("wlattach: base %lx, unit %d\n", rman_get_start(sc->res_ioport),
+ printf("wlattach: base %jx, unit %d\n", rman_get_start(sc->res_ioport),
device_get_unit(device));
#endif
diff --git a/sys/dev/wpi/if_wpi.c b/sys/dev/wpi/if_wpi.c
index 824f75b..e435096 100644
--- a/sys/dev/wpi/if_wpi.c
+++ b/sys/dev/wpi/if_wpi.c
@@ -284,7 +284,6 @@ static void wpi_scan_end(struct ieee80211com *);
static void wpi_set_channel(struct ieee80211com *);
static void wpi_scan_curchan(struct ieee80211_scan_state *, unsigned long);
static void wpi_scan_mindwell(struct ieee80211_scan_state *);
-static void wpi_hw_reset(void *, int);
static device_method_t wpi_methods[] = {
/* Device interface */
@@ -531,18 +530,9 @@ wpi_attach(device_t dev)
callout_init_mtx(&sc->scan_timeout, &sc->rxon_mtx, 0);
callout_init_mtx(&sc->tx_timeout, &sc->txq_state_mtx, 0);
callout_init_mtx(&sc->watchdog_rfkill, &sc->sc_mtx, 0);
- TASK_INIT(&sc->sc_reinittask, 0, wpi_hw_reset, sc);
TASK_INIT(&sc->sc_radiooff_task, 0, wpi_radio_off, sc);
TASK_INIT(&sc->sc_radioon_task, 0, wpi_radio_on, sc);
- sc->sc_tq = taskqueue_create("wpi_taskq", M_WAITOK,
- taskqueue_thread_enqueue, &sc->sc_tq);
- error = taskqueue_start_threads(&sc->sc_tq, 1, 0, "wpi_taskq");
- if (error != 0) {
- device_printf(dev, "can't start threads, error %d\n", error);
- goto fail;
- }
-
wpi_sysctlattach(sc);
/*
@@ -695,14 +685,10 @@ wpi_detach(device_t dev)
if (ic->ic_vap_create == wpi_vap_create) {
ieee80211_draintask(ic, &sc->sc_radioon_task);
+ ieee80211_draintask(ic, &sc->sc_radiooff_task);
wpi_stop(sc);
- if (sc->sc_tq != NULL) {
- taskqueue_drain_all(sc->sc_tq);
- taskqueue_free(sc->sc_tq);
- }
-
callout_drain(&sc->watchdog_rfkill);
callout_drain(&sc->tx_timeout);
callout_drain(&sc->scan_timeout);
@@ -1517,7 +1503,8 @@ wpi_find_eeprom_channel(struct wpi_softc *sc, struct ieee80211_channel *c)
for (j = 0; j < WPI_CHAN_BANDS_COUNT; j++)
for (i = 0; i < wpi_bands[j].nchan; i++)
- if (wpi_bands[j].chan[i] == c->ic_ieee)
+ if (wpi_bands[j].chan[i] == c->ic_ieee &&
+ ((j == 0) ^ IEEE80211_IS_CHAN_A(c)) == 1)
return &sc->eeprom_channels[j][i];
return NULL;
@@ -2332,7 +2319,7 @@ wpi_notif_intr(struct wpi_softc *sc)
WPI_NT_LOCK(sc);
wpi_clear_node_table(sc);
WPI_NT_UNLOCK(sc);
- taskqueue_enqueue(sc->sc_tq,
+ ieee80211_runtask(ic,
&sc->sc_radiooff_task);
return;
}
@@ -2569,6 +2556,8 @@ wpi_intr(void *arg)
WPI_WRITE(sc, WPI_FH_INT, r2);
if (__predict_false(r1 & (WPI_INT_SW_ERR | WPI_INT_HW_ERR))) {
+ struct ieee80211com *ic = &sc->sc_ic;
+
device_printf(sc->sc_dev, "fatal firmware error\n");
#ifdef WPI_DEBUG
wpi_debug_registers(sc);
@@ -2577,7 +2566,7 @@ wpi_intr(void *arg)
DPRINTF(sc, WPI_DEBUG_HW,
"(%s)\n", (r1 & WPI_INT_SW_ERR) ? "(Software Error)" :
"(Hardware Error)");
- taskqueue_enqueue(sc->sc_tq, &sc->sc_reinittask);
+ ieee80211_restart_all(ic);
goto end;
}
@@ -3200,7 +3189,7 @@ wpi_scan_timeout(void *arg)
struct ieee80211com *ic = &sc->sc_ic;
ic_printf(ic, "scan timeout\n");
- taskqueue_enqueue(sc->sc_tq, &sc->sc_reinittask);
+ ieee80211_restart_all(ic);
}
static void
@@ -3210,7 +3199,7 @@ wpi_tx_timeout(void *arg)
struct ieee80211com *ic = &sc->sc_ic;
ic_printf(ic, "device timeout\n");
- taskqueue_enqueue(sc->sc_tq, &sc->sc_reinittask);
+ ieee80211_restart_all(ic);
}
static void
@@ -3227,8 +3216,10 @@ wpi_parent(struct ieee80211com *ic)
ieee80211_notify_radio(ic, 0);
ieee80211_stop(vap);
}
- } else
+ } else {
+ ieee80211_notify_radio(ic, 0);
wpi_stop(sc);
+ }
}
/*
@@ -5654,23 +5645,3 @@ wpi_scan_mindwell(struct ieee80211_scan_state *ss)
{
/* NB: don't try to abort scan; wait for firmware to finish */
}
-
-static void
-wpi_hw_reset(void *arg, int pending)
-{
- struct wpi_softc *sc = arg;
- struct ieee80211com *ic = &sc->sc_ic;
- struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
-
- DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_DOING, __func__);
-
- ieee80211_notify_radio(ic, 0);
- if (vap != NULL && (ic->ic_flags & IEEE80211_F_SCAN))
- ieee80211_cancel_scan(vap);
-
- wpi_stop(sc);
- if (vap != NULL) {
- ieee80211_stop(vap);
- ieee80211_init(vap);
- }
-}
diff --git a/sys/dev/wpi/if_wpivar.h b/sys/dev/wpi/if_wpivar.h
index 1957740..437f1d8 100644
--- a/sys/dev/wpi/if_wpivar.h
+++ b/sys/dev/wpi/if_wpivar.h
@@ -228,13 +228,9 @@ struct wpi_softc {
struct wpi_dma_info fw_dma;
/* Tasks used by the driver. */
- struct task sc_reinittask;
struct task sc_radiooff_task;
struct task sc_radioon_task;
- /* Taskqueue */
- struct taskqueue *sc_tq;
-
/* Eeprom info. */
uint8_t cap;
uint16_t rev;
diff --git a/sys/dev/xe/if_xe.c b/sys/dev/xe/if_xe.c
index d6ccae9..e18af8c 100644
--- a/sys/dev/xe/if_xe.c
+++ b/sys/dev/xe/if_xe.c
@@ -1984,7 +1984,7 @@ xe_activate(device_t dev)
sc->port_res);
start = (rman_get_start(sc->port_res) + 15) & ~0xf;
} while (1);
- DEVPRINTF(1, (dev, "RealPort port 0x%0lx, size 0x%0lx\n",
+ DEVPRINTF(1, (dev, "RealPort port 0x%0jx, size 0x%0jx\n",
bus_get_resource_start(dev, SYS_RES_IOPORT, sc->port_rid),
bus_get_resource_count(dev, SYS_RES_IOPORT, sc->port_rid)));
} else if (sc->ce2) {
@@ -2024,7 +2024,7 @@ xe_activate(device_t dev)
sc->port_res);
sc->port_res = NULL;
}
- DEVPRINTF(1, (dev, "CEM2/CEM3 port 0x%0lx, size 0x%0lx\n",
+ DEVPRINTF(1, (dev, "CEM2/CEM3 port 0x%0jx, size 0x%0jx\n",
bus_get_resource_start(dev, SYS_RES_IOPORT, sc->port_rid),
bus_get_resource_count(dev, SYS_RES_IOPORT, sc->port_rid)));
}
diff --git a/sys/dev/xe/if_xe_pccard.c b/sys/dev/xe/if_xe_pccard.c
index bbe6253..fb2cff6 100644
--- a/sys/dev/xe/if_xe_pccard.c
+++ b/sys/dev/xe/if_xe_pccard.c
@@ -140,7 +140,7 @@ xe_cemfix(device_t dev)
DEVPRINTF(2, (dev, "cemfix\n"));
- DEVPRINTF(1, (dev, "CEM I/O port 0x%0lx, size 0x%0lx\n",
+ DEVPRINTF(1, (dev, "CEM I/O port 0x%0jx, size 0x%0jx\n",
bus_get_resource_start(dev, SYS_RES_IOPORT, sc->port_rid),
bus_get_resource_count(dev, SYS_RES_IOPORT, sc->port_rid)));
diff --git a/sys/dev/xen/blkfront/blkfront.c b/sys/dev/xen/blkfront/blkfront.c
index d35e04a..ef36b94 100644
--- a/sys/dev/xen/blkfront/blkfront.c
+++ b/sys/dev/xen/blkfront/blkfront.c
@@ -855,6 +855,20 @@ xbd_feature_string(struct xbd_softc *sc, char *features, size_t len)
feature_cnt++;
}
+ if ((sc->xbd_flags & XBDF_DISCARD) != 0) {
+ if (feature_cnt != 0)
+ sbuf_printf(&sb, ", ");
+ sbuf_printf(&sb, "discard");
+ feature_cnt++;
+ }
+
+ if ((sc->xbd_flags & XBDF_PERSISTENT) != 0) {
+ if (feature_cnt != 0)
+ sbuf_printf(&sb, ", ");
+ sbuf_printf(&sb, "persistent_grants");
+ feature_cnt++;
+ }
+
(void) sbuf_finish(&sb);
return (sbuf_len(&sb));
}
@@ -985,7 +999,8 @@ xbd_vdevice_to_unit(uint32_t vdevice, int *unit, const char **name)
int
xbd_instance_create(struct xbd_softc *sc, blkif_sector_t sectors,
- int vdevice, uint16_t vdisk_info, unsigned long sector_size)
+ int vdevice, uint16_t vdisk_info, unsigned long sector_size,
+ unsigned long phys_sector_size)
{
char features[80];
int unit, error = 0;
@@ -1013,6 +1028,8 @@ xbd_instance_create(struct xbd_softc *sc, blkif_sector_t sectors,
sc->xbd_disk->d_name = name;
sc->xbd_disk->d_drv1 = sc;
sc->xbd_disk->d_sectorsize = sector_size;
+ sc->xbd_disk->d_stripesize = phys_sector_size;
+ sc->xbd_disk->d_stripeoffset = 0;
sc->xbd_disk->d_mediasize = sectors * sector_size;
sc->xbd_disk->d_maxsize = sc->xbd_max_request_size;
@@ -1206,7 +1223,7 @@ static void
xbd_connect(struct xbd_softc *sc)
{
device_t dev = sc->xbd_dev;
- unsigned long sectors, sector_size;
+ unsigned long sectors, sector_size, phys_sector_size;
unsigned int binfo;
int err, feature_barrier, feature_flush;
int i, j;
@@ -1229,6 +1246,11 @@ xbd_connect(struct xbd_softc *sc)
return;
}
err = xs_gather(XST_NIL, xenbus_get_otherend_path(dev),
+ "physical-sector-size", "%lu", &phys_sector_size,
+ NULL);
+ if (err || phys_sector_size <= sector_size)
+ phys_sector_size = 0;
+ err = xs_gather(XST_NIL, xenbus_get_otherend_path(dev),
"feature-barrier", "%lu", &feature_barrier,
NULL);
if (err == 0 && feature_barrier != 0)
@@ -1330,7 +1352,7 @@ xbd_connect(struct xbd_softc *sc)
bus_print_child_footer(device_get_parent(dev), dev);
xbd_instance_create(sc, sectors, sc->xbd_vdevice, binfo,
- sector_size);
+ sector_size, phys_sector_size);
}
(void)xenbus_set_state(dev, XenbusStateConnected);
diff --git a/sys/dev/xen/blkfront/block.h b/sys/dev/xen/blkfront/block.h
index 28c6ff2..ddb4088 100644
--- a/sys/dev/xen/blkfront/block.h
+++ b/sys/dev/xen/blkfront/block.h
@@ -159,10 +159,12 @@ typedef enum {
XBDF_READY = 1 << 3, /* Is ready */
XBDF_CM_SHORTAGE = 1 << 4, /* Free cm resource shortage active. */
XBDF_GNT_SHORTAGE = 1 << 5, /* Grant ref resource shortage active */
- XBDF_WAIT_IDLE = 1 << 6 /*
+ XBDF_WAIT_IDLE = 1 << 6, /*
* No new work until oustanding work
* completes.
*/
+ XBDF_DISCARD = 1 << 7, /* backend supports discard */
+ XBDF_PERSISTENT = 1 << 8 /* backend supports persistent grants */
} xbd_flag_t;
/*
@@ -200,7 +202,8 @@ struct xbd_softc {
};
int xbd_instance_create(struct xbd_softc *, blkif_sector_t sectors, int device,
- uint16_t vdisk_info, unsigned long sector_size);
+ uint16_t vdisk_info, unsigned long sector_size,
+ unsigned long phys_sector_size);
static inline void
xbd_added_qentry(struct xbd_softc *sc, xbd_q_index_t index)
diff --git a/sys/dev/xen/netfront/netfront.c b/sys/dev/xen/netfront/netfront.c
index 22ca81c..7add70a 100644
--- a/sys/dev/xen/netfront/netfront.c
+++ b/sys/dev/xen/netfront/netfront.c
@@ -1202,7 +1202,6 @@ xn_rxeof(struct netfront_rxq *rxq)
struct netfront_info *np = rxq->info;
#if (defined(INET) || defined(INET6))
struct lro_ctrl *lro = &rxq->lro;
- struct lro_entry *queued;
#endif
struct netfront_rx_info rinfo;
struct netif_rx_response *rx = &rinfo.rx;
@@ -1296,11 +1295,7 @@ xn_rxeof(struct netfront_rxq *rxq)
/*
* Flush any outstanding LRO work
*/
- while (!SLIST_EMPTY(&lro->lro_active)) {
- queued = SLIST_FIRST(&lro->lro_active);
- SLIST_REMOVE_HEAD(&lro->lro_active, next);
- tcp_lro_flush(lro, queued);
- }
+ tcp_lro_flush_all(lro);
#endif
xn_alloc_rx_buffers(rxq);
diff --git a/sys/fs/autofs/autofs.c b/sys/fs/autofs/autofs.c
index c4b1ec3..eee74ea 100644
--- a/sys/fs/autofs/autofs.c
+++ b/sys/fs/autofs/autofs.c
@@ -77,6 +77,7 @@
#include <sys/sysctl.h>
#include <sys/syscallsubr.h>
#include <sys/taskqueue.h>
+#include <sys/tree.h>
#include <sys/vnode.h>
#include <machine/atomic.h>
#include <vm/uma.h>
@@ -149,6 +150,15 @@ TUNABLE_INT("vfs.autofs.interruptible", &autofs_interruptible);
SYSCTL_INT(_vfs_autofs, OID_AUTO, interruptible, CTLFLAG_RWTUN,
&autofs_interruptible, 1, "Allow requests to be interrupted by signal");
+static int
+autofs_node_cmp(const struct autofs_node *a, const struct autofs_node *b)
+{
+
+ return (strcmp(a->an_name, b->an_name));
+}
+
+RB_GENERATE(autofs_node_tree, autofs_node, an_link, autofs_node_cmp);
+
int
autofs_init(struct vfsconf *vfsp)
{
diff --git a/sys/fs/autofs/autofs.h b/sys/fs/autofs/autofs.h
index 27e380b..bab2282 100644
--- a/sys/fs/autofs/autofs.h
+++ b/sys/fs/autofs/autofs.h
@@ -65,11 +65,12 @@ extern int autofs_mount_on_stat;
#define AUTOFS_ASSERT_UNLOCKED(X) sx_assert(&X->am_lock, SA_UNLOCKED)
struct autofs_node {
- TAILQ_ENTRY(autofs_node) an_next;
+ RB_ENTRY(autofs_node) an_link;
char *an_name;
int an_fileno;
struct autofs_node *an_parent;
- TAILQ_HEAD(, autofs_node) an_children;
+ RB_HEAD(autofs_node_tree,
+ autofs_node) an_children;
struct autofs_mount *an_mount;
struct vnode *an_vnode;
struct sx an_vnode_lock;
@@ -136,4 +137,6 @@ void autofs_node_delete(struct autofs_node *anp);
int autofs_node_vn(struct autofs_node *anp, struct mount *mp,
int flags, struct vnode **vpp);
+RB_PROTOTYPE(autofs_node_tree, autofs_node, an_link, autofs_node_cmp);
+
#endif /* !AUTOFS_H */
diff --git a/sys/fs/autofs/autofs_vfsops.c b/sys/fs/autofs/autofs_vfsops.c
index 722ff24..b427a7f 100644
--- a/sys/fs/autofs/autofs_vfsops.c
+++ b/sys/fs/autofs/autofs_vfsops.c
@@ -42,6 +42,7 @@
#include <sys/stat.h>
#include <sys/sx.h>
#include <sys/taskqueue.h>
+#include <sys/tree.h>
#include <sys/vnode.h>
#include <fs/autofs/autofs.h>
@@ -158,10 +159,10 @@ autofs_unmount(struct mount *mp, int mntflags)
/*
* Not terribly efficient, but at least not recursive.
*/
- while (!TAILQ_EMPTY(&amp->am_root->an_children)) {
- anp = TAILQ_FIRST(&amp->am_root->an_children);
- while (!TAILQ_EMPTY(&anp->an_children))
- anp = TAILQ_FIRST(&anp->an_children);
+ while (!RB_EMPTY(&amp->am_root->an_children)) {
+ anp = RB_MIN(autofs_node_tree, &amp->am_root->an_children);
+ while (!RB_EMPTY(&anp->an_children))
+ anp = RB_MIN(autofs_node_tree, &anp->an_children);
autofs_node_delete(anp);
}
autofs_node_delete(amp->am_root);
diff --git a/sys/fs/autofs/autofs_vnops.c b/sys/fs/autofs/autofs_vnops.c
index 515d228..0ab6ec1 100644
--- a/sys/fs/autofs/autofs_vnops.c
+++ b/sys/fs/autofs/autofs_vnops.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <sys/stat.h>
#include <sys/systm.h>
#include <sys/taskqueue.h>
+#include <sys/tree.h>
#include <sys/vnode.h>
#include <machine/atomic.h>
#include <vm/uma.h>
@@ -371,7 +372,7 @@ autofs_dirent_reclen(const char *name)
{
size_t reclen;
- autofs_readdir_one(NULL, name, -1, &reclen);
+ (void)autofs_readdir_one(NULL, name, -1, &reclen);
return (reclen);
}
@@ -450,7 +451,7 @@ autofs_readdir(struct vop_readdir_args *ap)
* Write out the directory entries for subdirectories.
*/
AUTOFS_SLOCK(amp);
- TAILQ_FOREACH(child, &anp->an_children, an_next) {
+ RB_FOREACH(child, autofs_node_tree, &anp->an_children) {
/*
* Check the offset to skip entries returned by previous
* calls to getdents().
@@ -575,8 +576,8 @@ autofs_node_new(struct autofs_node *parent, struct autofs_mount *amp,
anp->an_parent = parent;
anp->an_mount = amp;
if (parent != NULL)
- TAILQ_INSERT_TAIL(&parent->an_children, anp, an_next);
- TAILQ_INIT(&anp->an_children);
+ RB_INSERT(autofs_node_tree, &parent->an_children, anp);
+ RB_INIT(&anp->an_children);
*anpp = anp;
return (0);
@@ -586,27 +587,28 @@ int
autofs_node_find(struct autofs_node *parent, const char *name,
int namelen, struct autofs_node **anpp)
{
- struct autofs_node *anp;
+ struct autofs_node *anp, find;
+ int error;
AUTOFS_ASSERT_LOCKED(parent->an_mount);
- TAILQ_FOREACH(anp, &parent->an_children, an_next) {
- if (namelen >= 0) {
- if (strlen(anp->an_name) != namelen)
- continue;
- if (strncmp(anp->an_name, name, namelen) != 0)
- continue;
- } else {
- if (strcmp(anp->an_name, name) != 0)
- continue;
- }
+ if (namelen >= 0)
+ find.an_name = strndup(name, namelen, M_AUTOFS);
+ else
+ find.an_name = strdup(name, M_AUTOFS);
+ anp = RB_FIND(autofs_node_tree, &parent->an_children, &find);
+ if (anp != NULL) {
+ error = 0;
if (anpp != NULL)
*anpp = anp;
- return (0);
+ } else {
+ error = ENOENT;
}
- return (ENOENT);
+ free(find.an_name, M_AUTOFS);
+
+ return (error);
}
void
@@ -615,13 +617,13 @@ autofs_node_delete(struct autofs_node *anp)
struct autofs_node *parent;
AUTOFS_ASSERT_XLOCKED(anp->an_mount);
- KASSERT(TAILQ_EMPTY(&anp->an_children), ("have children"));
+ KASSERT(RB_EMPTY(&anp->an_children), ("have children"));
callout_drain(&anp->an_callout);
parent = anp->an_parent;
if (parent != NULL)
- TAILQ_REMOVE(&parent->an_children, anp, an_next);
+ RB_REMOVE(autofs_node_tree, &parent->an_children, anp);
sx_destroy(&anp->an_vnode_lock);
free(anp->an_name, M_AUTOFS);
uma_zfree(autofs_node_zone, anp);
diff --git a/sys/fs/cd9660/cd9660_vnops.c b/sys/fs/cd9660/cd9660_vnops.c
index 47d4f75..cab8db7 100644
--- a/sys/fs/cd9660/cd9660_vnops.c
+++ b/sys/fs/cd9660/cd9660_vnops.c
@@ -341,11 +341,9 @@ cd9660_read(ap)
} else
error = bread(vp, lbn, size, NOCRED, &bp);
}
- n = MIN(n, size - bp->b_resid);
- if (error) {
- brelse(bp);
+ if (error != 0)
return (error);
- }
+ n = MIN(n, size - bp->b_resid);
error = uiomove(bp->b_data + on, (int)n, uio);
brelse(bp);
diff --git a/sys/fs/ext2fs/ext2_alloc.c b/sys/fs/ext2fs/ext2_alloc.c
index 12067d2..9d5417c 100644
--- a/sys/fs/ext2fs/ext2_alloc.c
+++ b/sys/fs/ext2fs/ext2_alloc.c
@@ -406,10 +406,8 @@ ext2_valloc(struct vnode *pvp, int mode, struct ucred *cred, struct vnode **vpp)
/*
* Set up a new generation number for this inode.
- * XXX check if this makes sense in ext2
*/
- if (ip->i_gen == 0 || ++ip->i_gen == 0)
- ip->i_gen = random() / 2 + 1;
+ ip->i_gen = arc4random();
vfs_timestamp(&ts);
ip->i_birthtime = ts.tv_sec;
diff --git a/sys/fs/ext2fs/ext2_dinode.h b/sys/fs/ext2fs/ext2_dinode.h
index 3f5ddef..a172a5b 100644
--- a/sys/fs/ext2fs/ext2_dinode.h
+++ b/sys/fs/ext2fs/ext2_dinode.h
@@ -131,6 +131,7 @@ struct ext2fs_dinode {
uint32_t e2di_crtime; /* 144: Creation (birth)time */
uint32_t e2di_crtime_extra; /* 148: Extra creation (birth)time */
uint32_t e2di_version_hi; /* 152: High bits of inode version */
+ uint32_t e2di_projid; /* 156: Project ID */
};
#endif /* !_FS_EXT2FS_EXT2_DINODE_H_ */
diff --git a/sys/fs/ext2fs/ext2fs.h b/sys/fs/ext2fs/ext2fs.h
index b8c4701..c23f2a2 100644
--- a/sys/fs/ext2fs/ext2fs.h
+++ b/sys/fs/ext2fs/ext2fs.h
@@ -72,7 +72,7 @@ struct ext2fs {
uint32_t e2fs_first_ino; /* first non-reserved inode */
uint16_t e2fs_inode_size; /* size of inode structure */
uint16_t e2fs_block_group_nr; /* block grp number of this sblk*/
- uint32_t e2fs_features_compat; /* compatible feature set */
+ uint32_t e2fs_features_compat; /* compatible feature set */
uint32_t e2fs_features_incompat; /* incompatible feature set */
uint32_t e2fs_features_rocompat; /* RO-compatible feature set */
uint8_t e2fs_uuid[16]; /* 128-bit uuid for volume */
@@ -88,25 +88,54 @@ struct ext2fs {
uint32_t e3fs_last_orphan; /* start of list of inodes to delete */
uint32_t e3fs_hash_seed[4]; /* HTREE hash seed */
char e3fs_def_hash_version; /* Default hash version to use */
- char e3fs_reserved_char_pad;
+ char e3fs_jnl_backup_type;
+ uint16_t e3fs_desc_size; /* size of group descriptor */
uint32_t e3fs_default_mount_opts;
uint32_t e3fs_first_meta_bg; /* First metablock block group */
- uint32_t e3fs_mkfs_time; /* when the fs was created */
- uint32_t e3fs_jnl_blks[17]; /* backup of the journal inode */
- uint32_t e4fs_bcount_hi; /* block count */
- uint32_t e4fs_rbcount_hi; /* reserved blocks count */
- uint32_t e4fs_fbcount_hi; /* free blocks count */
- uint16_t e4fs_min_extra_isize;/* all inodes have at least some bytes */
+ uint32_t e3fs_mkfs_time; /* when the fs was created */
+ uint32_t e3fs_jnl_blks[17]; /* backup of the journal inode */
+ uint32_t e4fs_bcount_hi; /* high bits of blocks count */
+ uint32_t e4fs_rbcount_hi; /* high bits of reserved blocks count */
+ uint32_t e4fs_fbcount_hi; /* high bits of free blocks count */
+ uint16_t e4fs_min_extra_isize; /* all inodes have at least some bytes */
uint16_t e4fs_want_extra_isize; /* inodes must reserve some bytes */
- uint32_t e4fs_flags; /* miscellaneous flags */
- uint16_t e4fs_raid_stride; /* RAID stride */
- uint16_t e4fs_mmpintv; /* number of seconds to wait in MMP checking */
- uint64_t e4fs_mmpblk; /* block for multi-mount protection */
- uint32_t e4fs_raid_stripe_wid;/* blocks on all data disks (N * stride) */
- uint8_t e4fs_log_gpf; /* FLEX_BG group size */
- uint8_t e4fs_char_pad2;
- uint16_t e4fs_pad;
- uint32_t reserved2[162]; /* Padding to the end of the block */
+ uint32_t e4fs_flags; /* miscellaneous flags */
+ uint16_t e4fs_raid_stride; /* RAID stride */
+ uint16_t e4fs_mmpintv; /* number of seconds to wait in MMP checking */
+ uint64_t e4fs_mmpblk; /* block for multi-mount protection */
+ uint32_t e4fs_raid_stripe_wid; /* blocks on all data disks (N * stride) */
+ uint8_t e4fs_log_gpf; /* FLEX_BG group size */
+ uint8_t e4fs_chksum_type; /* metadata checksum algorithm used */
+ uint8_t e4fs_encrypt; /* versioning level for encryption */
+ uint8_t e4fs_reserved_pad;
+ uint64_t e4fs_kbytes_written; /* number of lifetime kilobytes */
+ uint32_t e4fs_snapinum; /* inode number of active snapshot */
+ uint32_t e4fs_snapid; /* sequential ID of active snapshot */
+ uint64_t e4fs_snaprbcount; /* reserved blocks for active snapshot */
+ uint32_t e4fs_snaplist; /* inode number for on-disk snapshot */
+ uint32_t e4fs_errcount; /* number of file system errors */
+ uint32_t e4fs_first_errtime; /* first time an error happened */
+ uint32_t e4fs_first_errino; /* inode involved in first error */
+ uint64_t e4fs_first_errblk; /* block involved of first error */
+ uint8_t e4fs_first_errfunc[32]; /* function where error happened */
+ uint32_t e4fs_first_errline; /* line number where error happened */
+ uint32_t e4fs_last_errtime; /* most recent time of an error */
+ uint32_t e4fs_last_errino; /* inode involved in last error */
+ uint32_t e4fs_last_errline; /* line number where error happened */
+ uint64_t e4fs_last_errblk; /* block involved of last error */
+ uint8_t e4fs_last_errfunc[32]; /* function where error happened */
+ uint8_t e4fs_mount_opts[64];
+ uint32_t e4fs_usrquota_inum; /* inode for tracking user quota */
+ uint32_t e4fs_grpquota_inum; /* inode for tracking group quota */
+ uint32_t e4fs_overhead_clusters; /* overhead blocks/clusters */
+ uint32_t e4fs_backup_bgs[2]; /* groups with sparse_super2 SBs */
+ uint8_t e4fs_encrypt_algos[4]; /* encryption algorithms in use */
+ uint8_t e4fs_encrypt_pw_salt[16]; /* salt used for string2key */
+ uint32_t e4fs_lpf_ino; /* location of the lost+found inode */
+ uint32_t e4fs_proj_quota_inum; /* inode for tracking project quota */
+ uint32_t e4fs_chksum_seed; /* checksum seed */
+ uint32_t e4fs_reserved[98]; /* padding to the end of the block */
+ uint32_t e4fs_sbchksum; /* superblock checksum */
};
/*
diff --git a/sys/geom/sched/g_sched.c b/sys/geom/sched/g_sched.c
index ea1fd41..d4e3ca0 100644
--- a/sys/geom/sched/g_sched.c
+++ b/sys/geom/sched/g_sched.c
@@ -1316,7 +1316,8 @@ g_sched_destroy(struct g_geom *gp, boolean_t force)
gsp->gs_fini(sc->sc_data);
g_gsched_unref(gsp);
sc->sc_gsched = NULL;
- }
+ } else
+ error = 0;
if ((sc->sc_flags & G_SCHED_PROXYING) && oldpp) {
error = g_destroy_proxy(gp, oldpp);
diff --git a/sys/i386/conf/GENERIC.hints b/sys/i386/conf/GENERIC.hints
index fb30240..ffd10a6 100644
--- a/sys/i386/conf/GENERIC.hints
+++ b/sys/i386/conf/GENERIC.hints
@@ -38,6 +38,5 @@ hint.atrtc.0.irq="8"
hint.attimer.0.at="isa"
hint.attimer.0.port="0x40"
hint.attimer.0.irq="0"
-hint.wbwd.0.at="isa"
hint.acpi_throttle.0.disabled="1"
hint.p4tcc.0.disabled="1"
diff --git a/sys/i386/i386/vm_machdep.c b/sys/i386/i386/vm_machdep.c
index 62e99aa..fe6297a 100644
--- a/sys/i386/i386/vm_machdep.c
+++ b/sys/i386/i386/vm_machdep.c
@@ -127,8 +127,8 @@ get_pcb_user_save_td(struct thread *td)
vm_offset_t p;
p = td->td_kstack + td->td_kstack_pages * PAGE_SIZE -
- cpu_max_ext_state_size;
- KASSERT((p % 64) == 0, ("Unaligned pcb_user_save area"));
+ roundup2(cpu_max_ext_state_size, XSAVE_AREA_ALIGN);
+ KASSERT((p % XSAVE_AREA_ALIGN) == 0, ("Unaligned pcb_user_save area"));
return ((union savefpu *)p);
}
@@ -147,7 +147,8 @@ get_pcb_td(struct thread *td)
vm_offset_t p;
p = td->td_kstack + td->td_kstack_pages * PAGE_SIZE -
- cpu_max_ext_state_size - sizeof(struct pcb);
+ roundup2(cpu_max_ext_state_size, XSAVE_AREA_ALIGN) -
+ sizeof(struct pcb);
return ((struct pcb *)p);
}
diff --git a/sys/i386/include/intr_machdep.h b/sys/i386/include/intr_machdep.h
index 0a2a6d5..d1be076 100644
--- a/sys/i386/include/intr_machdep.h
+++ b/sys/i386/include/intr_machdep.h
@@ -83,7 +83,7 @@
#ifndef LOCORE
-typedef void inthand_t(u_int cs, u_int ef, u_int esp, u_int ss);
+typedef void inthand_t(void);
#define IDTVEC(name) __CONCAT(X,name)
diff --git a/sys/i386/include/md_var.h b/sys/i386/include/md_var.h
index f854373..c4c9ca9 100644
--- a/sys/i386/include/md_var.h
+++ b/sys/i386/include/md_var.h
@@ -46,7 +46,6 @@ extern int szosigcode;
#endif
extern uint32_t *vm_page_dump;
-typedef void alias_for_inthand_t(u_int cs, u_int ef, u_int esp, u_int ss);
struct segment_descriptor;
union savefpu;
diff --git a/sys/i386/linux/linux_dummy.c b/sys/i386/linux/linux_dummy.c
index 4c0cad0..fd73c9d 100644
--- a/sys/i386/linux/linux_dummy.c
+++ b/sys/i386/linux/linux_dummy.c
@@ -71,7 +71,6 @@ DUMMY(pivot_root);
DUMMY(mincore);
DUMMY(lookup_dcookie);
DUMMY(remap_file_pages);
-DUMMY(fstatfs64);
DUMMY(mbind);
DUMMY(get_mempolicy);
DUMMY(set_mempolicy);
diff --git a/sys/i386/linux/linux_proto.h b/sys/i386/linux/linux_proto.h
index 884292f..7e260d8 100644
--- a/sys/i386/linux/linux_proto.h
+++ b/sys/i386/linux/linux_proto.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/i386/linux/syscalls.master 293907 2016-01-14 10:13:58Z glebius
+ * created from FreeBSD: head/sys/i386/linux/syscalls.master 297061 2016-03-20 13:21:20Z dchagin
*/
#ifndef _LINUX_SYSPROTO_H_
@@ -848,7 +848,9 @@ struct linux_statfs64_args {
char buf_l_[PADL_(struct l_statfs64_buf *)]; struct l_statfs64_buf * buf; char buf_r_[PADR_(struct l_statfs64_buf *)];
};
struct linux_fstatfs64_args {
- register_t dummy;
+ char fd_l_[PADL_(l_uint)]; l_uint fd; char fd_r_[PADR_(l_uint)];
+ char bufsize_l_[PADL_(size_t)]; size_t bufsize; char bufsize_r_[PADR_(size_t)];
+ char buf_l_[PADL_(struct l_statfs64_buf *)]; struct l_statfs64_buf * buf; char buf_r_[PADR_(struct l_statfs64_buf *)];
};
struct linux_tgkill_args {
char tgid_l_[PADL_(int)]; int tgid; char tgid_r_[PADR_(int)];
diff --git a/sys/i386/linux/linux_syscall.h b/sys/i386/linux/linux_syscall.h
index 1be670a..918f838 100644
--- a/sys/i386/linux/linux_syscall.h
+++ b/sys/i386/linux/linux_syscall.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/i386/linux/syscalls.master 293907 2016-01-14 10:13:58Z glebius
+ * created from FreeBSD: head/sys/i386/linux/syscalls.master 297061 2016-03-20 13:21:20Z dchagin
*/
#define LINUX_SYS_linux_exit 1
diff --git a/sys/i386/linux/linux_syscalls.c b/sys/i386/linux/linux_syscalls.c
index 68a81ef..4a5cd4c 100644
--- a/sys/i386/linux/linux_syscalls.c
+++ b/sys/i386/linux/linux_syscalls.c
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/i386/linux/syscalls.master 293907 2016-01-14 10:13:58Z glebius
+ * created from FreeBSD: head/sys/i386/linux/syscalls.master 297061 2016-03-20 13:21:20Z dchagin
*/
const char *linux_syscallnames[] = {
diff --git a/sys/i386/linux/linux_sysent.c b/sys/i386/linux/linux_sysent.c
index d853d1d..181141d 100644
--- a/sys/i386/linux/linux_sysent.c
+++ b/sys/i386/linux/linux_sysent.c
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/i386/linux/syscalls.master 293907 2016-01-14 10:13:58Z glebius
+ * created from FreeBSD: head/sys/i386/linux/syscalls.master 297061 2016-03-20 13:21:20Z dchagin
*/
#include <sys/param.h>
@@ -287,7 +287,7 @@ struct sysent linux_sysent[] = {
{ AS(linux_clock_getres_args), (sy_call_t *)linux_clock_getres, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 266 = linux_clock_getres */
{ AS(linux_clock_nanosleep_args), (sy_call_t *)linux_clock_nanosleep, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 267 = linux_clock_nanosleep */
{ AS(linux_statfs64_args), (sy_call_t *)linux_statfs64, AUE_STATFS, NULL, 0, 0, 0, SY_THR_STATIC }, /* 268 = linux_statfs64 */
- { 0, (sy_call_t *)linux_fstatfs64, AUE_FSTATFS, NULL, 0, 0, 0, SY_THR_STATIC }, /* 269 = linux_fstatfs64 */
+ { AS(linux_fstatfs64_args), (sy_call_t *)linux_fstatfs64, AUE_FSTATFS, NULL, 0, 0, 0, SY_THR_STATIC }, /* 269 = linux_fstatfs64 */
{ AS(linux_tgkill_args), (sy_call_t *)linux_tgkill, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 270 = linux_tgkill */
{ AS(linux_utimes_args), (sy_call_t *)linux_utimes, AUE_UTIMES, NULL, 0, 0, 0, SY_THR_STATIC }, /* 271 = linux_utimes */
{ AS(linux_fadvise64_64_args), (sy_call_t *)linux_fadvise64_64, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 272 = linux_fadvise64_64 */
diff --git a/sys/i386/linux/linux_systrace_args.c b/sys/i386/linux/linux_systrace_args.c
index 85fc9ca..7feba47 100644
--- a/sys/i386/linux/linux_systrace_args.c
+++ b/sys/i386/linux/linux_systrace_args.c
@@ -1870,7 +1870,11 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
}
/* linux_fstatfs64 */
case 269: {
- *n_args = 0;
+ struct linux_fstatfs64_args *p = params;
+ iarg[0] = p->fd; /* l_uint */
+ uarg[1] = p->bufsize; /* size_t */
+ uarg[2] = (intptr_t) p->buf; /* struct l_statfs64_buf * */
+ *n_args = 3;
break;
}
/* linux_tgkill */
@@ -5265,6 +5269,19 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
break;
/* linux_fstatfs64 */
case 269:
+ switch(ndx) {
+ case 0:
+ p = "l_uint";
+ break;
+ case 1:
+ p = "size_t";
+ break;
+ case 2:
+ p = "struct l_statfs64_buf *";
+ break;
+ default:
+ break;
+ };
break;
/* linux_tgkill */
case 270:
@@ -7138,6 +7155,9 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
break;
/* linux_fstatfs64 */
case 269:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
/* linux_tgkill */
case 270:
if (ndx == 0 || ndx == 1)
diff --git a/sys/i386/linux/syscalls.master b/sys/i386/linux/syscalls.master
index 248770c..1032ef0 100644
--- a/sys/i386/linux/syscalls.master
+++ b/sys/i386/linux/syscalls.master
@@ -452,7 +452,7 @@
267 AUE_NULL STD { int linux_clock_nanosleep(clockid_t which, int flags, \
struct l_timespec *rqtp, struct l_timespec *rmtp); }
268 AUE_STATFS STD { int linux_statfs64(char *path, size_t bufsize, struct l_statfs64_buf *buf); }
-269 AUE_FSTATFS STD { int linux_fstatfs64(void); }
+269 AUE_FSTATFS STD { int linux_fstatfs64(l_uint fd, size_t bufsize, struct l_statfs64_buf *buf); }
270 AUE_NULL STD { int linux_tgkill(int tgid, int pid, int sig); }
271 AUE_UTIMES STD { int linux_utimes(char *fname, \
struct l_timeval *tptr); }
diff --git a/sys/isa/isa_common.c b/sys/isa/isa_common.c
index d2c8113..83e988c 100644
--- a/sys/isa/isa_common.c
+++ b/sys/isa/isa_common.c
@@ -629,10 +629,10 @@ isa_print_all_resources(device_t dev)
if (STAILQ_FIRST(rl) || device_get_flags(dev))
retval += printf(" at");
- retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx");
- retval += resource_list_print_type(rl, "iomem", SYS_RES_MEMORY, "%#lx");
- retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
- retval += resource_list_print_type(rl, "drq", SYS_RES_DRQ, "%ld");
+ retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#jx");
+ retval += resource_list_print_type(rl, "iomem", SYS_RES_MEMORY, "%#jx");
+ retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
+ retval += resource_list_print_type(rl, "drq", SYS_RES_DRQ, "%jd");
if (device_get_flags(dev))
retval += printf(" flags %#x", device_get_flags(dev));
#ifdef ISAPNP
diff --git a/sys/kern/imgact_binmisc.c b/sys/kern/imgact_binmisc.c
index dd57717..39ca156 100644
--- a/sys/kern/imgact_binmisc.c
+++ b/sys/kern/imgact_binmisc.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2013-15, Stacey D. Son
+ * Copyright (c) 2013-16, Stacey D. Son
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -220,16 +220,17 @@ imgact_binmisc_add_entry(ximgact_binmisc_entry_t *xbe)
{
imgact_binmisc_entry_t *ibe;
char *p;
+ int cnt;
if (xbe->xbe_msize > IBE_MAGIC_MAX)
return (EINVAL);
- for(p = xbe->xbe_name; *p != 0; p++)
- if (!isascii((int)*p))
+ for(cnt = 0, p = xbe->xbe_name; *p != 0; cnt++, p++)
+ if (cnt >= IBE_NAME_MAX || !isascii((int)*p))
return (EINVAL);
- for(p = xbe->xbe_interpreter; *p != 0; p++)
- if (!isascii((int)*p))
+ for(cnt = 0, p = xbe->xbe_interpreter; *p != 0; cnt++, p++)
+ if (cnt >= IBE_INTERP_LEN_MAX || !isascii((int)*p))
return (EINVAL);
/* Make sure we don't have any invalid #'s. */
@@ -266,8 +267,6 @@ imgact_binmisc_add_entry(ximgact_binmisc_entry_t *xbe)
/* Preallocate a new entry. */
ibe = imgact_binmisc_new_entry(xbe);
- if (!ibe)
- return (ENOMEM);
SLIST_INSERT_HEAD(&interpreter_list, ibe, link);
interp_list_entry_count++;
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index 43d4800..0bed714 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -1370,10 +1370,6 @@ __elfN(coredump)(struct thread *td, struct vnode *vp, off_t limit, int flags)
* and write it out following the notes.
*/
hdr = malloc(hdrsize, M_TEMP, M_WAITOK);
- if (hdr == NULL) {
- error = EINVAL;
- goto done;
- }
error = __elfN(corehdr)(&params, seginfo.count, hdr, hdrsize, &notelst,
notesz);
diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c
index 96c5229..47f2f90 100644
--- a/sys/kern/init_sysent.c
+++ b/sys/kern/init_sysent.c
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/kern/syscalls.master 296572 2016-03-09 19:05:11Z jhb
+ * created from FreeBSD: head/sys/kern/syscalls.master 297167 2016-03-21 21:37:33Z jhb
*/
#include "opt_compat.h"
diff --git a/sys/kern/kern_condvar.c b/sys/kern/kern_condvar.c
index 8061829..6f891e0 100644
--- a/sys/kern/kern_condvar.c
+++ b/sys/kern/kern_condvar.c
@@ -122,15 +122,8 @@ _cv_wait(struct cv *cvp, struct lock_object *lock)
"Waiting on \"%s\"", cvp->cv_description);
class = LOCK_CLASS(lock);
- if (cold || SCHEDULER_STOPPED()) {
- /*
- * During autoconfiguration, just give interrupts
- * a chance, then just return. Don't run any other
- * thread or panic below, in case this is the idle
- * process and already asleep.
- */
+ if (SCHEDULER_STOPPED())
return;
- }
sleepq_lock(cvp);
@@ -183,13 +176,7 @@ _cv_wait_unlock(struct cv *cvp, struct lock_object *lock)
("cv_wait_unlock cannot be used with Giant"));
class = LOCK_CLASS(lock);
- if (cold || SCHEDULER_STOPPED()) {
- /*
- * During autoconfiguration, just give interrupts
- * a chance, then just return. Don't run any other
- * thread or panic below, in case this is the idle
- * process and already asleep.
- */
+ if (SCHEDULER_STOPPED()) {
class->lc_unlock(lock);
return;
}
@@ -240,15 +227,8 @@ _cv_wait_sig(struct cv *cvp, struct lock_object *lock)
"Waiting on \"%s\"", cvp->cv_description);
class = LOCK_CLASS(lock);
- if (cold || SCHEDULER_STOPPED()) {
- /*
- * After a panic, or during autoconfiguration, just give
- * interrupts a chance, then just return; don't run any other
- * procs or panic below, in case this is the idle process and
- * already asleep.
- */
+ if (SCHEDULER_STOPPED())
return (0);
- }
sleepq_lock(cvp);
@@ -307,15 +287,8 @@ _cv_timedwait_sbt(struct cv *cvp, struct lock_object *lock, sbintime_t sbt,
"Waiting on \"%s\"", cvp->cv_description);
class = LOCK_CLASS(lock);
- if (cold || SCHEDULER_STOPPED()) {
- /*
- * After a panic, or during autoconfiguration, just give
- * interrupts a chance, then just return; don't run any other
- * thread or panic below, in case this is the idle process and
- * already asleep.
- */
- return 0;
- }
+ if (SCHEDULER_STOPPED())
+ return (0);
sleepq_lock(cvp);
@@ -376,15 +349,8 @@ _cv_timedwait_sig_sbt(struct cv *cvp, struct lock_object *lock,
"Waiting on \"%s\"", cvp->cv_description);
class = LOCK_CLASS(lock);
- if (cold || SCHEDULER_STOPPED()) {
- /*
- * After a panic, or during autoconfiguration, just give
- * interrupts a chance, then just return; don't run any other
- * thread or panic below, in case this is the idle process and
- * already asleep.
- */
- return 0;
- }
+ if (SCHEDULER_STOPPED())
+ return (0);
sleepq_lock(cvp);
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 00bd54b..b37adcc 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -3958,7 +3958,7 @@ badfo_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred,
static int
badfo_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio,
struct uio *trl_uio, off_t offset, size_t nbytes, off_t *sent, int flags,
- int kflags, struct thread *td)
+ struct thread *td)
{
return (EBADF);
@@ -4044,7 +4044,7 @@ invfo_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred,
int
invfo_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio,
struct uio *trl_uio, off_t offset, size_t nbytes, off_t *sent, int flags,
- int kflags, struct thread *td)
+ struct thread *td)
{
return (EINVAL);
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 69f0774..7c88fe0 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -1570,8 +1570,6 @@ exec_register(execsw_arg)
for (es = execsw; *es; es++)
count++;
newexecsw = malloc(count * sizeof(*es), M_TEMP, M_WAITOK);
- if (newexecsw == NULL)
- return (ENOMEM);
xs = newexecsw;
if (execsw)
for (es = execsw; *es; es++)
@@ -1604,8 +1602,6 @@ exec_unregister(execsw_arg)
if (*es != execsw_arg)
count++;
newexecsw = malloc(count * sizeof(*es), M_TEMP, M_WAITOK);
- if (newexecsw == NULL)
- return (ENOMEM);
xs = newexecsw;
for (es = execsw; *es; es++)
if (*es != execsw_arg)
diff --git a/sys/kern/kern_fail.c b/sys/kern/kern_fail.c
index 3737aa3..ec466dd 100644
--- a/sys/kern/kern_fail.c
+++ b/sys/kern/kern_fail.c
@@ -52,17 +52,25 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_stack.h"
+
#include <sys/ctype.h>
#include <sys/errno.h>
#include <sys/fail.h>
#include <sys/kernel.h>
#include <sys/libkern.h>
+#include <sys/limits.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/sbuf.h>
+#include <sys/sleepqueue.h>
+#include <sys/sx.h>
+#include <sys/sysctl.h>
+#include <sys/types.h>
+#include <machine/atomic.h>
#include <machine/stdarg.h>
#ifdef ILOG_DEFINE_FOR_FILE
@@ -72,11 +80,45 @@ ILOG_DEFINE_FOR_FILE(L_ISI_FAIL_POINT, L_ILOG, fail_point);
static MALLOC_DEFINE(M_FAIL_POINT, "Fail Points", "fail points system");
#define fp_free(ptr) free(ptr, M_FAIL_POINT)
#define fp_malloc(size, flags) malloc((size), M_FAIL_POINT, (flags))
+#define fs_free(ptr) fp_free(ptr)
+#define fs_malloc() fp_malloc(sizeof(struct fail_point_setting), \
+ M_WAITOK | M_ZERO)
+
+ /**
+ * These define the wchans that are used for sleeping, pausing respectively.
+ * They are chosen arbitrarily but need to be distinct to the failpoint and
+ * the sleep/pause distinction.
+ */
+#define FP_SLEEP_CHANNEL(fp) (void*)(fp)
+#define FP_PAUSE_CHANNEL(fp) __DEVOLATILE(void*, &fp->fp_setting)
+
+/**
+ * Don't allow more than this many entries in a fail point set by sysctl.
+ * The 99.99...% case is to have 1 entry. I can't imagine having this many
+ * entries, so it should not limit us. Saves on re-mallocs while holding
+ * a non-sleepable lock.
+ */
+#define FP_MAX_ENTRY_COUNT 20
+
+/* Used to drain sbufs to the sysctl output */
+int fail_sysctl_drain_func(void *, const char *, int);
+
+/* Head of tailq of struct fail_point_entry */
+TAILQ_HEAD(fail_point_entry_queue, fail_point_entry);
+
+/**
+ * fp entries garbage list; outstanding entries are cleaned up in the
+ * garbage collector
+ */
+STAILQ_HEAD(fail_point_setting_garbage, fail_point_setting);
+static struct fail_point_setting_garbage fp_setting_garbage =
+ STAILQ_HEAD_INITIALIZER(fp_setting_garbage);
+static struct mtx mtx_garbage_list;
+MTX_SYSINIT(mtx_garbage_list, &mtx_garbage_list, "fail point garbage mtx",
+ MTX_SPIN);
-static struct mtx g_fp_mtx;
-MTX_SYSINIT(g_fp_mtx, &g_fp_mtx, "fail point mtx", MTX_DEF);
-#define FP_LOCK() mtx_lock(&g_fp_mtx)
-#define FP_UNLOCK() mtx_unlock(&g_fp_mtx)
+static struct sx sx_fp_set;
+SX_SYSINIT(sx_fp_set, &sx_fp_set, "fail point set sx");
/**
* Failpoint types.
@@ -90,7 +132,11 @@ enum fail_point_t {
FAIL_POINT_BREAK, /**< break into the debugger */
FAIL_POINT_PRINT, /**< print a message */
FAIL_POINT_SLEEP, /**< sleep for some msecs */
- FAIL_POINT_NUMTYPES
+ FAIL_POINT_PAUSE, /**< sleep until failpoint is set to off */
+ FAIL_POINT_YIELD, /**< yield the cpu */
+ FAIL_POINT_DELAY, /**< busy wait the cpu */
+ FAIL_POINT_NUMTYPES,
+ FAIL_POINT_INVALID = -1
};
static struct {
@@ -104,53 +150,307 @@ static struct {
[FAIL_POINT_BREAK] = FP_TYPE_NM_LEN("break"),
[FAIL_POINT_PRINT] = FP_TYPE_NM_LEN("print"),
[FAIL_POINT_SLEEP] = FP_TYPE_NM_LEN("sleep"),
+ [FAIL_POINT_PAUSE] = FP_TYPE_NM_LEN("pause"),
+ [FAIL_POINT_YIELD] = FP_TYPE_NM_LEN("yield"),
+ [FAIL_POINT_DELAY] = FP_TYPE_NM_LEN("delay"),
};
+#define FE_COUNT_UNTRACKED (INT_MIN)
+
/**
* Internal structure tracking a single term of a complete failpoint.
* @ingroup failpoint_private
*/
struct fail_point_entry {
- enum fail_point_t fe_type; /**< type of entry */
+ volatile bool fe_stale;
+ enum fail_point_t fe_type; /**< type of entry */
int fe_arg; /**< argument to type (e.g. return value) */
int fe_prob; /**< likelihood of firing in millionths */
- int fe_count; /**< number of times to fire, 0 means always */
+ int fe_count; /**< number of times to fire, -1 means infinite */
pid_t fe_pid; /**< only fail for this process */
- TAILQ_ENTRY(fail_point_entry) fe_entries; /**< next entry in fail point */
+ struct fail_point *fe_parent; /**< backpointer to fp */
+ TAILQ_ENTRY(fail_point_entry) fe_entries; /**< next entry ptr */
};
+struct fail_point_setting {
+ STAILQ_ENTRY(fail_point_setting) fs_garbage_link;
+ struct fail_point_entry_queue fp_entry_queue;
+ struct fail_point * fs_parent;
+ struct mtx feq_mtx; /* Gives fail_point_pause something to do. */
+};
+
+/**
+ * Defines stating the equivalent of probablilty one (100%)
+ */
+enum {
+ PROB_MAX = 1000000, /* probability between zero and this number */
+ PROB_DIGITS = 6 /* number of zero's in above number */
+};
+
+/* Get a ref on an fp's fp_setting */
+static inline struct fail_point_setting *fail_point_setting_get_ref(
+ struct fail_point *fp);
+/* Release a ref on an fp_setting */
+static inline void fail_point_setting_release_ref(struct fail_point *fp);
+/* Allocate and initialize a struct fail_point_setting */
+static struct fail_point_setting *fail_point_setting_new(struct
+ fail_point *);
+/* Free a struct fail_point_setting */
+static void fail_point_setting_destroy(struct fail_point_setting *fp_setting);
+/* Allocate and initialize a struct fail_point_entry */
+static struct fail_point_entry *fail_point_entry_new(struct
+ fail_point_setting *);
+/* Free a struct fail_point_entry */
+static void fail_point_entry_destroy(struct fail_point_entry *fp_entry);
+/* Append fp setting to garbage list */
+static inline void fail_point_setting_garbage_append(
+ struct fail_point_setting *fp_setting);
+/* Swap fp's setting with fp_setting_new */
+static inline struct fail_point_setting *
+ fail_point_swap_settings(struct fail_point *fp,
+ struct fail_point_setting *fp_setting_new);
+/* Free up any zero-ref setting in the garbage queue */
+static void fail_point_garbage_collect(void);
+/* If this fail point's setting are empty, then swap it out to NULL. */
+static inline void fail_point_eval_swap_out(struct fail_point *fp,
+ struct fail_point_setting *fp_setting);
+
+bool
+fail_point_is_off(struct fail_point *fp)
+{
+ bool return_val;
+ struct fail_point_setting *fp_setting;
+ struct fail_point_entry *ent;
+
+ return_val = true;
+
+ fp_setting = fail_point_setting_get_ref(fp);
+ if (fp_setting != NULL) {
+ TAILQ_FOREACH(ent, &fp_setting->fp_entry_queue,
+ fe_entries) {
+ if (!ent->fe_stale) {
+ return_val = false;
+ break;
+ }
+ }
+ }
+ fail_point_setting_release_ref(fp);
+
+ return (return_val);
+}
+
+/* Allocate and initialize a struct fail_point_setting */
+static struct fail_point_setting *
+fail_point_setting_new(struct fail_point *fp)
+{
+ struct fail_point_setting *fs_new;
+
+ fs_new = fs_malloc();
+ fs_new->fs_parent = fp;
+ TAILQ_INIT(&fs_new->fp_entry_queue);
+ mtx_init(&fs_new->feq_mtx, "fail point entries", NULL, MTX_SPIN);
+
+ fail_point_setting_garbage_append(fs_new);
+
+ return (fs_new);
+}
+
+/* Free a struct fail_point_setting */
+static void
+fail_point_setting_destroy(struct fail_point_setting *fp_setting)
+{
+ struct fail_point_entry *ent;
+
+ while (!TAILQ_EMPTY(&fp_setting->fp_entry_queue)) {
+ ent = TAILQ_FIRST(&fp_setting->fp_entry_queue);
+ TAILQ_REMOVE(&fp_setting->fp_entry_queue, ent, fe_entries);
+ fail_point_entry_destroy(ent);
+ }
+
+ fs_free(fp_setting);
+}
+
+/* Allocate and initialize a struct fail_point_entry */
+static struct fail_point_entry *
+fail_point_entry_new(struct fail_point_setting *fp_setting)
+{
+ struct fail_point_entry *fp_entry;
+
+ fp_entry = fp_malloc(sizeof(struct fail_point_entry),
+ M_WAITOK | M_ZERO);
+ fp_entry->fe_parent = fp_setting->fs_parent;
+ fp_entry->fe_prob = PROB_MAX;
+ fp_entry->fe_pid = NO_PID;
+ fp_entry->fe_count = FE_COUNT_UNTRACKED;
+ TAILQ_INSERT_TAIL(&fp_setting->fp_entry_queue, fp_entry,
+ fe_entries);
+
+ return (fp_entry);
+}
+
+/* Free a struct fail_point_entry */
+static void
+fail_point_entry_destroy(struct fail_point_entry *fp_entry)
+{
+
+ fp_free(fp_entry);
+}
+
+/* Get a ref on an fp's fp_setting */
+static inline struct fail_point_setting *
+fail_point_setting_get_ref(struct fail_point *fp)
+{
+ struct fail_point_setting *fp_setting;
+
+ /* Invariant: if we have a ref, our pointer to fp_setting is safe */
+ atomic_add_acq_32(&fp->fp_ref_cnt, 1);
+ fp_setting = fp->fp_setting;
+
+ return (fp_setting);
+}
+
+/* Release a ref on an fp_setting */
+static inline void
+fail_point_setting_release_ref(struct fail_point *fp)
+{
+
+ KASSERT(&fp->fp_ref_cnt > 0, ("Attempting to deref w/no refs"));
+ atomic_subtract_rel_32(&fp->fp_ref_cnt, 1);
+}
+
+/* Append fp entries to fp garbage list */
+static inline void
+fail_point_setting_garbage_append(struct fail_point_setting *fp_setting)
+{
+
+ mtx_lock_spin(&mtx_garbage_list);
+ STAILQ_INSERT_TAIL(&fp_setting_garbage, fp_setting,
+ fs_garbage_link);
+ mtx_unlock_spin(&mtx_garbage_list);
+}
+
+/* Swap fp's entries with fp_setting_new */
+static struct fail_point_setting *
+fail_point_swap_settings(struct fail_point *fp,
+ struct fail_point_setting *fp_setting_new)
+{
+ struct fail_point_setting *fp_setting_old;
+
+ fp_setting_old = fp->fp_setting;
+ fp->fp_setting = fp_setting_new;
+
+ return (fp_setting_old);
+}
+
+static inline void
+fail_point_eval_swap_out(struct fail_point *fp,
+ struct fail_point_setting *fp_setting)
+{
+
+ /* We may have already been swapped out and replaced; ignore. */
+ if (fp->fp_setting == fp_setting)
+ fail_point_swap_settings(fp, NULL);
+}
+
+/* Free up any zero-ref entries in the garbage queue */
+static void
+fail_point_garbage_collect()
+{
+ struct fail_point_setting *fs_current, *fs_next;
+ struct fail_point_setting_garbage fp_ents_free_list;
+
+ /**
+ * We will transfer the entries to free to fp_ents_free_list while holding
+ * the spin mutex, then free it after we drop the lock. This avoids
+ * triggering witness due to sleepable mutexes in the memory
+ * allocator.
+ */
+ STAILQ_INIT(&fp_ents_free_list);
+
+ mtx_lock_spin(&mtx_garbage_list);
+ STAILQ_FOREACH_SAFE(fs_current, &fp_setting_garbage, fs_garbage_link,
+ fs_next) {
+ if (fs_current->fs_parent->fp_setting != fs_current &&
+ fs_current->fs_parent->fp_ref_cnt == 0) {
+ STAILQ_REMOVE(&fp_setting_garbage, fs_current,
+ fail_point_setting, fs_garbage_link);
+ STAILQ_INSERT_HEAD(&fp_ents_free_list, fs_current,
+ fs_garbage_link);
+ }
+ }
+ mtx_unlock_spin(&mtx_garbage_list);
+
+ STAILQ_FOREACH_SAFE(fs_current, &fp_ents_free_list, fs_garbage_link,
+ fs_next)
+ fail_point_setting_destroy(fs_current);
+}
+
+/* Drain out all refs from this fail point */
+static inline void
+fail_point_drain(struct fail_point *fp, int expected_ref)
+{
+ struct fail_point_setting *entries;
+
+ entries = fail_point_swap_settings(fp, NULL);
+ /**
+ * We have unpaused all threads; so we will wait no longer
+ * than the time taken for the longest remaining sleep, or
+ * the length of time of a long-running code block.
+ */
+ while (fp->fp_ref_cnt > expected_ref) {
+ wakeup(FP_PAUSE_CHANNEL(fp));
+ tsleep(&fp, PWAIT, "fail_point_drain", hz / 100);
+ }
+ fail_point_swap_settings(fp, entries);
+}
+
static inline void
-fail_point_sleep(struct fail_point *fp, struct fail_point_entry *ent,
- int msecs, enum fail_point_return_code *pret)
+fail_point_pause(struct fail_point *fp, enum fail_point_return_code *pret,
+ struct mtx *mtx_sleep)
{
- /* convert from millisecs to ticks, rounding up */
- int timo = ((msecs * hz) + 999) / 1000;
+
+ if (fp->fp_pre_sleep_fn)
+ fp->fp_pre_sleep_fn(fp->fp_pre_sleep_arg);
+
+ msleep_spin(FP_PAUSE_CHANNEL(fp), mtx_sleep, "failpt", 0);
+
+ if (fp->fp_post_sleep_fn)
+ fp->fp_post_sleep_fn(fp->fp_post_sleep_arg);
+}
+
+static inline void
+fail_point_sleep(struct fail_point *fp, int msecs,
+ enum fail_point_return_code *pret)
+{
+ int timo;
+
+ /* Convert from millisecs to ticks, rounding up */
+ timo = howmany(msecs * hz, 1000);
if (timo > 0) {
- if (fp->fp_sleep_fn == NULL) {
- msleep(fp, &g_fp_mtx, PWAIT, "failpt", timo);
+ if (!(fp->fp_flags & FAIL_POINT_USE_TIMEOUT_PATH)) {
+ if (fp->fp_pre_sleep_fn)
+ fp->fp_pre_sleep_fn(fp->fp_pre_sleep_arg);
+
+ tsleep(FP_SLEEP_CHANNEL(fp), PWAIT, "failpt", timo);
+
+ if (fp->fp_post_sleep_fn)
+ fp->fp_post_sleep_fn(fp->fp_post_sleep_arg);
} else {
- timeout(fp->fp_sleep_fn, fp->fp_sleep_arg, timo);
+ if (fp->fp_pre_sleep_fn)
+ fp->fp_pre_sleep_fn(fp->fp_pre_sleep_arg);
+
+ timeout(fp->fp_post_sleep_fn, fp->fp_post_sleep_arg,
+ timo);
*pret = FAIL_POINT_RC_QUEUED;
}
}
}
-
-/**
- * Defines stating the equivalent of probablilty one (100%)
- */
-enum {
- PROB_MAX = 1000000, /* probability between zero and this number */
- PROB_DIGITS = 6, /* number of zero's in above number */
-};
-
-static char *parse_fail_point(struct fail_point_entries *, char *);
-static char *parse_term(struct fail_point_entries *, char *);
+static char *parse_fail_point(struct fail_point_setting *, char *);
+static char *parse_term(struct fail_point_setting *, char *);
static char *parse_number(int *out_units, int *out_decimal, char *);
static char *parse_type(struct fail_point_entry *, char *);
-static void free_entry(struct fail_point_entries *, struct fail_point_entry *);
-static void clear_entries(struct fail_point_entries *);
/**
* Initialize a fail_point. The name is formed in a printf-like fashion
@@ -167,7 +467,7 @@ fail_point_init(struct fail_point *fp, const char *fmt, ...)
char *name;
int n;
- TAILQ_INIT(&fp->fp_entries);
+ fp->fp_setting = NULL;
fp->fp_flags = 0;
/* Figure out the size of the name. */
@@ -185,25 +485,33 @@ fail_point_init(struct fail_point *fp, const char *fmt, ...)
fp->fp_name = name;
fp->fp_location = "";
fp->fp_flags |= FAIL_POINT_DYNAMIC_NAME;
- fp->fp_sleep_fn = NULL;
- fp->fp_sleep_arg = NULL;
+ fp->fp_pre_sleep_fn = NULL;
+ fp->fp_pre_sleep_arg = NULL;
+ fp->fp_post_sleep_fn = NULL;
+ fp->fp_post_sleep_arg = NULL;
}
/**
- * Free the resources held by a fail_point.
- *
+ * Free the resources held by a fail_point, and wake any paused threads.
+ * Thou shalt not allow threads to hit this fail point after you enter this
+ * function, nor shall you call this multiple times for a given fp.
* @ingroup failpoint
*/
void
fail_point_destroy(struct fail_point *fp)
{
+ fail_point_drain(fp, 0);
+
if ((fp->fp_flags & FAIL_POINT_DYNAMIC_NAME) != 0) {
fp_free(__DECONST(void *, fp->fp_name));
fp->fp_name = NULL;
}
fp->fp_flags = 0;
- clear_entries(&fp->fp_entries);
+
+ sx_xlock(&sx_fp_set);
+ fail_point_garbage_collect();
+ sx_xunlock(&sx_fp_set);
}
/**
@@ -216,21 +524,51 @@ fail_point_destroy(struct fail_point *fp)
enum fail_point_return_code
fail_point_eval_nontrivial(struct fail_point *fp, int *return_value)
{
- enum fail_point_return_code ret = FAIL_POINT_RC_CONTINUE;
- struct fail_point_entry *ent, *next;
+ bool execute = false;
+ struct fail_point_entry *ent;
+ struct fail_point_setting *fp_setting;
+ enum fail_point_return_code ret;
+ int cont;
+ int count;
int msecs;
+ int usecs;
+
+ ret = FAIL_POINT_RC_CONTINUE;
+ cont = 0; /* don't continue by default */
+
+ fp_setting = fail_point_setting_get_ref(fp);
+ if (fp_setting == NULL)
+ goto abort;
- FP_LOCK();
+ TAILQ_FOREACH(ent, &fp_setting->fp_entry_queue, fe_entries) {
- TAILQ_FOREACH_SAFE(ent, &fp->fp_entries, fe_entries, next) {
- int cont = 0; /* don't continue by default */
+ if (ent->fe_stale)
+ continue;
if (ent->fe_prob < PROB_MAX &&
ent->fe_prob < random() % PROB_MAX)
continue;
+
if (ent->fe_pid != NO_PID && ent->fe_pid != curproc->p_pid)
continue;
+ if (ent->fe_count != FE_COUNT_UNTRACKED) {
+ count = ent->fe_count;
+ while (count > 0) {
+ if (atomic_cmpset_32(&ent->fe_count, count, count - 1)) {
+ count--;
+ execute = true;
+ break;
+ }
+ count = ent->fe_count;
+ }
+ if (execute == false)
+ /* We lost the race; consider the entry stale and bail now */
+ continue;
+ if (count == 0)
+ ent->fe_stale = true;
+ }
+
switch (ent->fe_type) {
case FAIL_POINT_PANIC:
panic("fail point %s panicking", fp->fp_name);
@@ -244,7 +582,7 @@ fail_point_eval_nontrivial(struct fail_point *fp, int *return_value)
case FAIL_POINT_BREAK:
printf("fail point %s breaking to debugger\n",
- fp->fp_name);
+ fp->fp_name);
breakpoint();
break;
@@ -254,51 +592,95 @@ fail_point_eval_nontrivial(struct fail_point *fp, int *return_value)
break;
case FAIL_POINT_SLEEP:
- /*
- * Free the entry now if necessary, since
- * we're about to drop the mutex and sleep.
- */
msecs = ent->fe_arg;
- if (ent->fe_count > 0 && --ent->fe_count == 0) {
- free_entry(&fp->fp_entries, ent);
- ent = NULL;
- }
-
if (msecs)
- fail_point_sleep(fp, ent, msecs, &ret);
+ fail_point_sleep(fp, msecs, &ret);
+ break;
+
+ case FAIL_POINT_PAUSE:
+ /**
+ * Pausing is inherently strange with multiple
+ * entries given our design. That is because some
+ * entries could be unreachable, for instance in cases like:
+ * pause->return. We can never reach the return entry.
+ * The sysctl layer actually truncates all entries after
+ * a pause for this reason.
+ */
+ mtx_lock_spin(&fp_setting->feq_mtx);
+ fail_point_pause(fp, &ret, &fp_setting->feq_mtx);
+ mtx_unlock_spin(&fp_setting->feq_mtx);
+ break;
+
+ case FAIL_POINT_YIELD:
+ kern_yield(-1);
+ break;
+
+ case FAIL_POINT_DELAY:
+ usecs = ent->fe_arg;
+ DELAY(usecs);
break;
default:
break;
}
- if (ent != NULL && ent->fe_count > 0 && --ent->fe_count == 0)
- free_entry(&fp->fp_entries, ent);
if (cont == 0)
break;
}
- /* Get rid of "off"s at the end. */
- while ((ent = TAILQ_LAST(&fp->fp_entries, fail_point_entries)) &&
- ent->fe_type == FAIL_POINT_OFF)
- free_entry(&fp->fp_entries, ent);
+ if (fail_point_is_off(fp))
+ fail_point_eval_swap_out(fp, fp_setting);
- FP_UNLOCK();
+abort:
+ fail_point_setting_release_ref(fp);
return (ret);
+
}
/**
* Translate internal fail_point structure into human-readable text.
*/
static void
-fail_point_get(struct fail_point *fp, struct sbuf *sb)
+fail_point_get(struct fail_point *fp, struct sbuf *sb,
+ bool verbose)
{
struct fail_point_entry *ent;
+ struct fail_point_setting *fp_setting;
+ struct fail_point_entry *fp_entry_cpy;
+ int cnt_sleeping;
+ int idx;
+ int printed_entry_count;
+
+ cnt_sleeping = 0;
+ idx = 0;
+ printed_entry_count = 0;
+
+ fp_entry_cpy = fp_malloc(sizeof(struct fail_point_entry) *
+ (FP_MAX_ENTRY_COUNT + 1), M_WAITOK);
+
+ fp_setting = fail_point_setting_get_ref(fp);
- FP_LOCK();
+ if (fp_setting != NULL) {
+ TAILQ_FOREACH(ent, &fp_setting->fp_entry_queue, fe_entries) {
+ if (ent->fe_stale)
+ continue;
- TAILQ_FOREACH(ent, &fp->fp_entries, fe_entries) {
+ KASSERT(printed_entry_count < FP_MAX_ENTRY_COUNT,
+ ("FP entry list larger than allowed"));
+
+ fp_entry_cpy[printed_entry_count] = *ent;
+ ++printed_entry_count;
+ }
+ }
+ fail_point_setting_release_ref(fp);
+
+ /* This is our equivalent of a NULL terminator */
+ fp_entry_cpy[printed_entry_count].fe_type = FAIL_POINT_INVALID;
+
+ while (idx < printed_entry_count) {
+ ent = &fp_entry_cpy[idx];
+ ++idx;
if (ent->fe_prob < PROB_MAX) {
int decimal = ent->fe_prob % (PROB_MAX / 100);
int units = ent->fe_prob / (PROB_MAX / 100);
@@ -313,7 +695,7 @@ fail_point_get(struct fail_point *fp, struct sbuf *sb)
}
sbuf_printf(sb, "%%");
}
- if (ent->fe_count > 0)
+ if (ent->fe_count >= 0)
sbuf_printf(sb, "%d*", ent->fe_count);
sbuf_printf(sb, "%s", fail_type_strings[ent->fe_type].name);
if (ent->fe_arg)
@@ -323,10 +705,33 @@ fail_point_get(struct fail_point *fp, struct sbuf *sb)
if (TAILQ_NEXT(ent, fe_entries))
sbuf_printf(sb, "->");
}
- if (TAILQ_EMPTY(&fp->fp_entries))
+ if (!printed_entry_count)
sbuf_printf(sb, "off");
- FP_UNLOCK();
+ fp_free(fp_entry_cpy);
+ if (verbose) {
+#ifdef STACK
+ /* Print number of sleeping threads. queue=0 is the argument
+ * used by msleep when sending our threads to sleep. */
+ sbuf_printf(sb, "\nsleeping_thread_stacks = {\n");
+ sleepq_sbuf_print_stacks(sb, FP_SLEEP_CHANNEL(fp), 0,
+ &cnt_sleeping);
+
+ sbuf_printf(sb, "},\n");
+#endif
+ sbuf_printf(sb, "sleeping_thread_count = %d,\n",
+ cnt_sleeping);
+
+#ifdef STACK
+ sbuf_printf(sb, "paused_thread_stacks = {\n");
+ sleepq_sbuf_print_stacks(sb, FP_PAUSE_CHANNEL(fp), 0,
+ &cnt_sleeping);
+
+ sbuf_printf(sb, "},\n");
+#endif
+ sbuf_printf(sb, "paused_thread_count = %d\n",
+ cnt_sleeping);
+ }
}
/**
@@ -336,38 +741,91 @@ fail_point_get(struct fail_point *fp, struct sbuf *sb)
static int
fail_point_set(struct fail_point *fp, char *buf)
{
- int error = 0;
struct fail_point_entry *ent, *ent_next;
- struct fail_point_entries new_entries;
+ struct fail_point_setting *entries;
+ bool should_wake_paused;
+ bool should_truncate;
+ int error;
+
+ error = 0;
+ should_wake_paused = false;
+ should_truncate = false;
/* Parse new entries. */
- TAILQ_INIT(&new_entries);
- if (!parse_fail_point(&new_entries, buf)) {
- clear_entries(&new_entries);
+ /**
+ * ref protects our new malloc'd stuff from being garbage collected
+ * before we link it.
+ */
+ fail_point_setting_get_ref(fp);
+ entries = fail_point_setting_new(fp);
+ if (parse_fail_point(entries, buf) == NULL) {
+ STAILQ_REMOVE(&fp_setting_garbage, entries,
+ fail_point_setting, fs_garbage_link);
+ fail_point_setting_destroy(entries);
error = EINVAL;
goto end;
}
- FP_LOCK();
-
- /* Move new entries in. */
- TAILQ_SWAP(&fp->fp_entries, &new_entries, fail_point_entry, fe_entries);
- clear_entries(&new_entries);
+ /**
+ * Transfer the entries we are going to keep to a new list.
+ * Get rid of useless zero probability entries, and entries with hit
+ * count 0.
+ * If 'off' is present, and it has no hit count set, then all entries
+ * after it are discarded since they are unreachable.
+ */
+ TAILQ_FOREACH_SAFE(ent, &entries->fp_entry_queue, fe_entries, ent_next) {
+ if (ent->fe_prob == 0 || ent->fe_count == 0) {
+ printf("Discarding entry which cannot execute %s\n",
+ fail_type_strings[ent->fe_type].name);
+ TAILQ_REMOVE(&entries->fp_entry_queue, ent,
+ fe_entries);
+ fp_free(ent);
+ continue;
+ } else if (should_truncate) {
+ printf("Discarding unreachable entry %s\n",
+ fail_type_strings[ent->fe_type].name);
+ TAILQ_REMOVE(&entries->fp_entry_queue, ent,
+ fe_entries);
+ fp_free(ent);
+ continue;
+ }
- /* Get rid of useless zero probability entries. */
- TAILQ_FOREACH_SAFE(ent, &fp->fp_entries, fe_entries, ent_next) {
- if (ent->fe_prob == 0)
- free_entry(&fp->fp_entries, ent);
+ if (ent->fe_type == FAIL_POINT_OFF) {
+ should_wake_paused = true;
+ if (ent->fe_count == FE_COUNT_UNTRACKED) {
+ should_truncate = true;
+ TAILQ_REMOVE(&entries->fp_entry_queue, ent,
+ fe_entries);
+ fp_free(ent);
+ }
+ } else if (ent->fe_type == FAIL_POINT_PAUSE) {
+ should_truncate = true;
+ } else if (ent->fe_type == FAIL_POINT_SLEEP && (fp->fp_flags &
+ FAIL_POINT_NONSLEEPABLE)) {
+ /**
+ * If this fail point is annotated as being in a
+ * non-sleepable ctx, convert sleep to delay and
+ * convert the msec argument to usecs.
+ */
+ printf("Sleep call request on fail point in "
+ "non-sleepable context; using delay instead "
+ "of sleep\n");
+ ent->fe_type = FAIL_POINT_DELAY;
+ ent->fe_arg *= 1000;
+ }
}
- /* Get rid of "off"s at the end. */
- while ((ent = TAILQ_LAST(&fp->fp_entries, fail_point_entries)) &&
- ent->fe_type == FAIL_POINT_OFF)
- free_entry(&fp->fp_entries, ent);
-
- FP_UNLOCK();
+ if (TAILQ_EMPTY(&entries->fp_entry_queue)) {
+ entries = fail_point_swap_settings(fp, NULL);
+ if (entries != NULL)
+ wakeup(FP_PAUSE_CHANNEL(fp));
+ } else {
+ if (should_wake_paused)
+ wakeup(FP_PAUSE_CHANNEL(fp));
+ fail_point_swap_settings(fp, entries);
+ }
- end:
+end:
#ifdef IWARNING
if (error)
IWARNING("Failed to set %s %s to %s",
@@ -377,6 +835,7 @@ fail_point_set(struct fail_point *fp, char *buf)
fp->fp_name, fp->fp_location, buf);
#endif /* IWARNING */
+ fail_point_setting_release_ref(fp);
return (error);
}
@@ -385,25 +844,33 @@ fail_point_set(struct fail_point *fp, char *buf)
/**
* Handle kernel failpoint set/get.
*/
+
int
fail_point_sysctl(SYSCTL_HANDLER_ARGS)
{
- struct fail_point *fp = arg1;
- char *buf = NULL;
+ struct fail_point *fp;
+ char *buf;
+ struct sbuf *sb_check;
struct sbuf sb;
int error;
- /* Retrieving */
- sbuf_new(&sb, NULL, 128, SBUF_AUTOEXTEND | SBUF_INCLUDENUL);
- fail_point_get(fp, &sb);
- sbuf_trim(&sb);
- error = sbuf_finish(&sb);
- if (error == 0)
- error = SYSCTL_OUT(req, sbuf_data(&sb), sbuf_len(&sb));
- sbuf_delete(&sb);
+ error = 0;
+ fp = arg1;
+ buf = NULL;
+
+ sb_check = sbuf_new(&sb, NULL, 1024, SBUF_AUTOEXTEND);
+ if (sb_check != &sb)
+ return (ENOMEM);
+
+ sbuf_set_drain(&sb, (sbuf_drain_func *)fail_sysctl_drain_func, req);
/* Setting */
- if (!error && req->newptr) {
+ /**
+ * Lock protects any new entries from being garbage collected before we
+ * can link them to the fail point.
+ */
+ sx_xlock(&sx_fp_set);
+ if (req->newptr) {
if (req->newlen > MAX_FAIL_POINT_BUF) {
error = EINVAL;
goto out;
@@ -417,31 +884,95 @@ fail_point_sysctl(SYSCTL_HANDLER_ARGS)
buf[req->newlen] = '\0';
error = fail_point_set(fp, buf);
- }
+ }
+
+ fail_point_garbage_collect();
+ sx_xunlock(&sx_fp_set);
+
+ /* Retrieving. */
+ fail_point_get(fp, &sb, false);
out:
- fp_free(buf);
+ sbuf_finish(&sb);
+ sbuf_delete(&sb);
+
+ if (buf)
+ fp_free(buf);
+
return (error);
}
+int
+fail_point_sysctl_status(SYSCTL_HANDLER_ARGS)
+{
+ struct fail_point *fp;
+ struct sbuf sb, *sb_check;
+
+ fp = arg1;
+
+ sb_check = sbuf_new(&sb, NULL, 1024, SBUF_AUTOEXTEND);
+ if (sb_check != &sb)
+ return (ENOMEM);
+
+ sbuf_set_drain(&sb, (sbuf_drain_func *)fail_sysctl_drain_func, req);
+
+ /* Retrieving. */
+ fail_point_get(fp, &sb, true);
+
+ sbuf_finish(&sb);
+ sbuf_delete(&sb);
+
+ /**
+ * Lock protects any new entries from being garbage collected before we
+ * can link them to the fail point.
+ */
+ sx_xlock(&sx_fp_set);
+ fail_point_garbage_collect();
+ sx_xunlock(&sx_fp_set);
+
+ return (0);
+}
+
+int
+fail_sysctl_drain_func(void *sysctl_args, const char *buf, int len)
+{
+ struct sysctl_req *sa;
+ int error;
+
+ sa = sysctl_args;
+
+ error = SYSCTL_OUT(sa, buf, len);
+
+ if (error == ENOMEM)
+ return (-1);
+ else
+ return (len);
+}
+
+
/**
* Internal helper function to translate a human-readable failpoint string
* into a internally-parsable fail_point structure.
*/
static char *
-parse_fail_point(struct fail_point_entries *ents, char *p)
+parse_fail_point(struct fail_point_setting *ents, char *p)
{
/* <fail_point> ::
* <term> ( "->" <term> )*
*/
+ uint8_t term_count;
+
+ term_count = 1;
+
p = parse_term(ents, p);
if (p == NULL)
return (NULL);
+
while (*p != '\0') {
- if (p[0] != '-' || p[1] != '>')
- return (NULL);
- p = parse_term(ents, p + 2);
- if (p == NULL)
+ term_count++;
+ if (p[0] != '-' || p[1] != '>' ||
+ (p = parse_term(ents, p+2)) == NULL ||
+ term_count > FP_MAX_ENTRY_COUNT)
return (NULL);
}
return (p);
@@ -451,14 +982,11 @@ parse_fail_point(struct fail_point_entries *ents, char *p)
* Internal helper function to parse an individual term from a failpoint.
*/
static char *
-parse_term(struct fail_point_entries *ents, char *p)
+parse_term(struct fail_point_setting *ents, char *p)
{
struct fail_point_entry *ent;
- ent = fp_malloc(sizeof *ent, M_WAITOK | M_ZERO);
- ent->fe_prob = PROB_MAX;
- ent->fe_pid = NO_PID;
- TAILQ_INSERT_TAIL(ents, ent, fe_entries);
+ ent = fail_point_entry_new(ents);
/*
* <term> ::
@@ -483,7 +1011,7 @@ parse_term(struct fail_point_entries *ents, char *p)
if (ent->fe_prob > PROB_MAX)
ent->fe_prob = PROB_MAX;
} else if (*p == '*') {
- if (!units || decimal)
+ if (!units || units < 0 || decimal)
return (NULL);
ent->fe_count = units;
} else
@@ -500,7 +1028,7 @@ parse_term(struct fail_point_entries *ents, char *p)
/* [ "(" <integer> ")" ] */
if (*p != '(')
- return p;
+ return (p);
p++;
if (!isdigit(*p) && *p != '-')
return (NULL);
@@ -509,7 +1037,7 @@ parse_term(struct fail_point_entries *ents, char *p)
return (NULL);
/* [ "[pid " <integer> "]" ] */
-#define PID_STRING "[pid "
+#define PID_STRING "[pid "
if (strncmp(p, PID_STRING, sizeof(PID_STRING) - 1) != 0)
return (p);
p += sizeof(PID_STRING) - 1;
@@ -530,7 +1058,7 @@ parse_number(int *out_units, int *out_decimal, char *p)
{
char *old_p;
- /*
+ /**
* <number> ::
* <integer> [ "." <integer> ] |
* "." <integer>
@@ -584,29 +1112,17 @@ parse_type(struct fail_point_entry *ent, char *beg)
return (NULL);
}
-/**
- * Internal helper function to free an individual failpoint term.
- */
-static void
-free_entry(struct fail_point_entries *ents, struct fail_point_entry *ent)
-{
- TAILQ_REMOVE(ents, ent, fe_entries);
- fp_free(ent);
-}
+/* The fail point sysctl tree. */
+SYSCTL_NODE(_debug, OID_AUTO, fail_point, CTLFLAG_RW, 0, "fail points");
-/**
- * Internal helper function to clear out all failpoint terms for a single
- * failpoint.
- */
-static void
-clear_entries(struct fail_point_entries *ents)
+/* Debugging/testing stuff for fail point */
+static int
+sysctl_test_fail_point(SYSCTL_HANDLER_ARGS)
{
- struct fail_point_entry *ent, *ent_next;
- TAILQ_FOREACH_SAFE(ent, ents, fe_entries, ent_next)
- fp_free(ent);
- TAILQ_INIT(ents);
+ KFAIL_POINT_RETURN(DEBUG_FP, test_fail_point);
+ return (0);
}
-
-/* The fail point sysctl tree. */
-SYSCTL_NODE(_debug, OID_AUTO, fail_point, CTLFLAG_RW, 0, "fail points");
+SYSCTL_OID(_debug_fail_point, OID_AUTO, test_trigger_fail_point,
+ CTLTYPE_STRING | CTLFLAG_RD, NULL, 0, sysctl_test_fail_point, "A",
+ "Trigger test fail points");
diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c
index 7454d79..e204291 100644
--- a/sys/kern/kern_linker.c
+++ b/sys/kern/kern_linker.c
@@ -1763,8 +1763,6 @@ linker_hints_lookup(const char *path, int pathlen, const char *modname,
goto bad;
}
hints = malloc(vattr.va_size, M_TEMP, M_WAITOK);
- if (hints == NULL)
- goto bad;
error = vn_rdwr(UIO_READ, nd.ni_vp, (caddr_t)hints, vattr.va_size, 0,
UIO_SYSSPACE, IO_NODELOCKED, cred, NOCRED, &reclen, td);
if (error)
diff --git a/sys/kern/kern_mbuf.c b/sys/kern/kern_mbuf.c
index 3074589..5e634d7 100644
--- a/sys/kern/kern_mbuf.c
+++ b/sys/kern/kern_mbuf.c
@@ -424,6 +424,7 @@ mb_ctor_mbuf(void *mem, int size, void *arg, int how)
m = (struct mbuf *)mem;
flags = args->flags;
+ MPASS((flags & M_NOFREE) == 0);
error = m_init(m, how, type, flags);
@@ -572,6 +573,7 @@ mb_ctor_pack(void *mem, int size, void *arg, int how)
args = (struct mb_args *)arg;
flags = args->flags;
type = args->type;
+ MPASS((flags & M_NOFREE) == 0);
#ifdef INVARIANTS
trash_ctor(m->m_ext.ext_buf, MCLBYTES, arg, how);
@@ -731,6 +733,7 @@ m_clget(struct mbuf *m, int how)
zone_drain(zone_pack);
uma_zalloc_arg(zone_clust, m, how);
}
+ MBUF_PROBE2(m__clget, m, how);
return (m->m_flags & M_EXT);
}
@@ -745,6 +748,7 @@ void *
m_cljget(struct mbuf *m, int how, int size)
{
uma_zone_t zone;
+ void *retval;
if (m != NULL) {
KASSERT((m->m_flags & M_EXT) == 0, ("%s: mbuf %p has M_EXT",
@@ -753,7 +757,11 @@ m_cljget(struct mbuf *m, int how, int size)
}
zone = m_getzone(size);
- return (uma_zalloc_arg(zone, m, how));
+ retval = uma_zalloc_arg(zone, m, how);
+
+ MBUF_PROBE4(m__cljget, m, how, size, retval);
+
+ return (retval);
}
/*
@@ -934,6 +942,7 @@ void
m_freem(struct mbuf *mb)
{
+ MBUF_PROBE1(m__freem, mb);
while (mb != NULL)
mb = m_free(mb);
}
diff --git a/sys/kern/kern_osd.c b/sys/kern/kern_osd.c
index cc9bed1..41d518f 100644
--- a/sys/kern/kern_osd.c
+++ b/sys/kern/kern_osd.c
@@ -44,6 +44,23 @@ __FBSDID("$FreeBSD$");
/* OSD (Object Specific Data) */
+/*
+ * Lock key:
+ * (m) osd_module_lock
+ * (o) osd_object_lock
+ * (l) osd_list_lock
+ */
+struct osd_master {
+ struct sx osd_module_lock;
+ struct rmlock osd_object_lock;
+ struct mtx osd_list_lock;
+ LIST_HEAD(, osd) osd_list; /* (l) */
+ osd_destructor_t *osd_destructors; /* (o) */
+ osd_method_t *osd_methods; /* (m) */
+ u_int osd_ntslots; /* (m) */
+ const u_int osd_nmethods;
+};
+
static MALLOC_DEFINE(M_OSD, "osd", "Object Specific Data");
static int osd_debug = 0;
@@ -61,25 +78,12 @@ static void do_osd_del(u_int type, struct osd *osd, u_int slot,
int list_locked);
/*
- * Lists of objects with OSD.
- *
- * Lock key:
- * (m) osd_module_lock
- * (o) osd_object_lock
- * (l) osd_list_lock
+ * List of objects with OSD.
*/
-static LIST_HEAD(, osd) osd_list[OSD_LAST + 1]; /* (m) */
-static osd_method_t *osd_methods[OSD_LAST + 1]; /* (m) */
-static u_int osd_nslots[OSD_LAST + 1]; /* (m) */
-static osd_destructor_t *osd_destructors[OSD_LAST + 1]; /* (o) */
-static const u_int osd_nmethods[OSD_LAST + 1] = {
- [OSD_JAIL] = PR_MAXMETHOD,
+struct osd_master osdm[OSD_LAST + 1] = {
+ [OSD_JAIL] = { .osd_nmethods = PR_MAXMETHOD },
};
-static struct sx osd_module_lock[OSD_LAST + 1];
-static struct rmlock osd_object_lock[OSD_LAST + 1];
-static struct mtx osd_list_lock[OSD_LAST + 1];
-
static void
osd_default_destructor(void *value __unused)
{
@@ -101,12 +105,12 @@ osd_register(u_int type, osd_destructor_t destructor, osd_method_t *methods)
if (destructor == NULL)
destructor = osd_default_destructor;
- sx_xlock(&osd_module_lock[type]);
+ sx_xlock(&osdm[type].osd_module_lock);
/*
* First, we try to find unused slot.
*/
- for (i = 0; i < osd_nslots[type]; i++) {
- if (osd_destructors[type][i] == NULL) {
+ for (i = 0; i < osdm[type].osd_ntslots; i++) {
+ if (osdm[type].osd_destructors[i] == NULL) {
OSD_DEBUG("Unused slot found (type=%u, slot=%u).",
type, i);
break;
@@ -115,31 +119,31 @@ osd_register(u_int type, osd_destructor_t destructor, osd_method_t *methods)
/*
* If no unused slot was found, allocate one.
*/
- if (i == osd_nslots[type]) {
- osd_nslots[type]++;
- if (osd_nmethods[type] != 0)
- osd_methods[type] = realloc(osd_methods[type],
- sizeof(osd_method_t) * osd_nslots[type] *
- osd_nmethods[type], M_OSD, M_WAITOK);
- newptr = malloc(sizeof(osd_destructor_t) * osd_nslots[type],
- M_OSD, M_WAITOK);
- rm_wlock(&osd_object_lock[type]);
- bcopy(osd_destructors[type], newptr,
+ if (i == osdm[type].osd_ntslots) {
+ osdm[type].osd_ntslots++;
+ if (osdm[type].osd_nmethods != 0)
+ osdm[type].osd_methods = realloc(osdm[type].osd_methods,
+ sizeof(osd_method_t) * osdm[type].osd_ntslots *
+ osdm[type].osd_nmethods, M_OSD, M_WAITOK);
+ newptr = malloc(sizeof(osd_destructor_t) *
+ osdm[type].osd_ntslots, M_OSD, M_WAITOK);
+ rm_wlock(&osdm[type].osd_object_lock);
+ bcopy(osdm[type].osd_destructors, newptr,
sizeof(osd_destructor_t) * i);
- free(osd_destructors[type], M_OSD);
- osd_destructors[type] = newptr;
- rm_wunlock(&osd_object_lock[type]);
+ free(osdm[type].osd_destructors, M_OSD);
+ osdm[type].osd_destructors = newptr;
+ rm_wunlock(&osdm[type].osd_object_lock);
OSD_DEBUG("New slot allocated (type=%u, slot=%u).",
type, i + 1);
}
- osd_destructors[type][i] = destructor;
- if (osd_nmethods[type] != 0) {
- for (m = 0; m < osd_nmethods[type]; m++)
- osd_methods[type][i * osd_nmethods[type] + m] =
- methods != NULL ? methods[m] : NULL;
+ osdm[type].osd_destructors[i] = destructor;
+ if (osdm[type].osd_nmethods != 0) {
+ for (m = 0; m < osdm[type].osd_nmethods; m++)
+ osdm[type].osd_methods[i * osdm[type].osd_nmethods + m]
+ = methods != NULL ? methods[m] : NULL;
}
- sx_xunlock(&osd_module_lock[type]);
+ sx_xunlock(&osdm[type].osd_module_lock);
return (i + 1);
}
@@ -150,105 +154,142 @@ osd_deregister(u_int type, u_int slot)
KASSERT(type >= OSD_FIRST && type <= OSD_LAST, ("Invalid type."));
KASSERT(slot > 0, ("Invalid slot."));
- KASSERT(osd_destructors[type][slot - 1] != NULL, ("Unused slot."));
+ KASSERT(osdm[type].osd_destructors[slot - 1] != NULL, ("Unused slot."));
- sx_xlock(&osd_module_lock[type]);
- rm_wlock(&osd_object_lock[type]);
+ sx_xlock(&osdm[type].osd_module_lock);
+ rm_wlock(&osdm[type].osd_object_lock);
/*
* Free all OSD for the given slot.
*/
- mtx_lock(&osd_list_lock[type]);
- LIST_FOREACH_SAFE(osd, &osd_list[type], osd_next, tosd)
+ mtx_lock(&osdm[type].osd_list_lock);
+ LIST_FOREACH_SAFE(osd, &osdm[type].osd_list, osd_next, tosd)
do_osd_del(type, osd, slot, 1);
- mtx_unlock(&osd_list_lock[type]);
+ mtx_unlock(&osdm[type].osd_list_lock);
/*
* Set destructor to NULL to free the slot.
*/
- osd_destructors[type][slot - 1] = NULL;
- if (slot == osd_nslots[type]) {
- osd_nslots[type]--;
- osd_destructors[type] = realloc(osd_destructors[type],
- sizeof(osd_destructor_t) * osd_nslots[type], M_OSD,
+ osdm[type].osd_destructors[slot - 1] = NULL;
+ if (slot == osdm[type].osd_ntslots) {
+ osdm[type].osd_ntslots--;
+ osdm[type].osd_destructors = realloc(osdm[type].osd_destructors,
+ sizeof(osd_destructor_t) * osdm[type].osd_ntslots, M_OSD,
M_NOWAIT | M_ZERO);
- if (osd_nmethods[type] != 0)
- osd_methods[type] = realloc(osd_methods[type],
- sizeof(osd_method_t) * osd_nslots[type] *
- osd_nmethods[type], M_OSD, M_NOWAIT | M_ZERO);
+ if (osdm[type].osd_nmethods != 0)
+ osdm[type].osd_methods = realloc(osdm[type].osd_methods,
+ sizeof(osd_method_t) * osdm[type].osd_ntslots *
+ osdm[type].osd_nmethods, M_OSD, M_NOWAIT | M_ZERO);
/*
* We always reallocate to smaller size, so we assume it will
* always succeed.
*/
- KASSERT(osd_destructors[type] != NULL &&
- (osd_nmethods[type] == 0 || osd_methods[type] != NULL),
- ("realloc() failed"));
+ KASSERT(osdm[type].osd_destructors != NULL &&
+ (osdm[type].osd_nmethods == 0 ||
+ osdm[type].osd_methods != NULL), ("realloc() failed"));
OSD_DEBUG("Deregistration of the last slot (type=%u, slot=%u).",
type, slot);
} else {
OSD_DEBUG("Slot deregistration (type=%u, slot=%u).",
type, slot);
}
- rm_wunlock(&osd_object_lock[type]);
- sx_xunlock(&osd_module_lock[type]);
+ rm_wunlock(&osdm[type].osd_object_lock);
+ sx_xunlock(&osdm[type].osd_module_lock);
}
int
osd_set(u_int type, struct osd *osd, u_int slot, void *value)
{
+
+ return (osd_set_reserved(type, osd, slot, NULL, value));
+}
+
+void *
+osd_reserve(u_int slot)
+{
+
+ KASSERT(slot > 0, ("Invalid slot."));
+
+ OSD_DEBUG("Reserving slot array (slot=%u).", slot);
+ return (malloc(sizeof(void *) * slot, M_OSD, M_WAITOK | M_ZERO));
+}
+
+int
+osd_set_reserved(u_int type, struct osd *osd, u_int slot, void *rsv,
+ void *value)
+{
struct rm_priotracker tracker;
KASSERT(type >= OSD_FIRST && type <= OSD_LAST, ("Invalid type."));
KASSERT(slot > 0, ("Invalid slot."));
- KASSERT(osd_destructors[type][slot - 1] != NULL, ("Unused slot."));
+ KASSERT(osdm[type].osd_destructors[slot - 1] != NULL, ("Unused slot."));
- rm_rlock(&osd_object_lock[type], &tracker);
+ rm_rlock(&osdm[type].osd_object_lock, &tracker);
if (slot > osd->osd_nslots) {
+ void *newptr;
+
if (value == NULL) {
OSD_DEBUG(
"Not allocating null slot (type=%u, slot=%u).",
type, slot);
- rm_runlock(&osd_object_lock[type], &tracker);
+ rm_runlock(&osdm[type].osd_object_lock, &tracker);
+ if (rsv)
+ osd_free_reserved(rsv);
return (0);
- } else if (osd->osd_nslots == 0) {
+ }
+
+ /*
+ * Too few slots allocated here, so we need to extend or create
+ * the array.
+ */
+ if (rsv) {
/*
- * First OSD for this object, so we need to allocate
- * space and put it onto the list.
+ * Use the reserve passed in (assumed to be
+ * the right size).
*/
- osd->osd_slots = malloc(sizeof(void *) * slot, M_OSD,
- M_NOWAIT | M_ZERO);
- if (osd->osd_slots == NULL) {
- rm_runlock(&osd_object_lock[type], &tracker);
- return (ENOMEM);
+ newptr = rsv;
+ if (osd->osd_nslots != 0) {
+ memcpy(newptr, osd->osd_slots,
+ sizeof(void *) * osd->osd_nslots);
+ free(osd->osd_slots, M_OSD);
}
- osd->osd_nslots = slot;
- mtx_lock(&osd_list_lock[type]);
- LIST_INSERT_HEAD(&osd_list[type], osd, osd_next);
- mtx_unlock(&osd_list_lock[type]);
- OSD_DEBUG("Setting first slot (type=%u).", type);
} else {
- void *newptr;
-
- /*
- * Too few slots allocated here, needs to extend
- * the array.
- */
newptr = realloc(osd->osd_slots, sizeof(void *) * slot,
M_OSD, M_NOWAIT | M_ZERO);
if (newptr == NULL) {
- rm_runlock(&osd_object_lock[type], &tracker);
+ rm_runlock(&osdm[type].osd_object_lock,
+ &tracker);
return (ENOMEM);
}
- osd->osd_slots = newptr;
- osd->osd_nslots = slot;
- OSD_DEBUG("Growing slots array (type=%u).", type);
}
- }
+ if (osd->osd_nslots == 0) {
+ /*
+ * First OSD for this object, so we need to put it
+ * onto the list.
+ */
+ mtx_lock(&osdm[type].osd_list_lock);
+ LIST_INSERT_HEAD(&osdm[type].osd_list, osd, osd_next);
+ mtx_unlock(&osdm[type].osd_list_lock);
+ OSD_DEBUG("Setting first slot (type=%u).", type);
+ } else
+ OSD_DEBUG("Growing slots array (type=%u).", type);
+ osd->osd_slots = newptr;
+ osd->osd_nslots = slot;
+ } else if (rsv)
+ osd_free_reserved(rsv);
OSD_DEBUG("Setting slot value (type=%u, slot=%u, value=%p).", type,
slot, value);
osd->osd_slots[slot - 1] = value;
- rm_runlock(&osd_object_lock[type], &tracker);
+ rm_runlock(&osdm[type].osd_object_lock, &tracker);
return (0);
}
+void
+osd_free_reserved(void *rsv)
+{
+
+ OSD_DEBUG("Discarding reserved slot array.");
+ free(rsv, M_OSD);
+}
+
void *
osd_get(u_int type, struct osd *osd, u_int slot)
{
@@ -257,9 +298,9 @@ osd_get(u_int type, struct osd *osd, u_int slot)
KASSERT(type >= OSD_FIRST && type <= OSD_LAST, ("Invalid type."));
KASSERT(slot > 0, ("Invalid slot."));
- KASSERT(osd_destructors[type][slot - 1] != NULL, ("Unused slot."));
+ KASSERT(osdm[type].osd_destructors[slot - 1] != NULL, ("Unused slot."));
- rm_rlock(&osd_object_lock[type], &tracker);
+ rm_rlock(&osdm[type].osd_object_lock, &tracker);
if (slot > osd->osd_nslots) {
value = NULL;
OSD_DEBUG("Slot doesn't exist (type=%u, slot=%u).", type, slot);
@@ -268,7 +309,7 @@ osd_get(u_int type, struct osd *osd, u_int slot)
OSD_DEBUG("Returning slot value (type=%u, slot=%u, value=%p).",
type, slot, value);
}
- rm_runlock(&osd_object_lock[type], &tracker);
+ rm_runlock(&osdm[type].osd_object_lock, &tracker);
return (value);
}
@@ -277,9 +318,9 @@ osd_del(u_int type, struct osd *osd, u_int slot)
{
struct rm_priotracker tracker;
- rm_rlock(&osd_object_lock[type], &tracker);
+ rm_rlock(&osdm[type].osd_object_lock, &tracker);
do_osd_del(type, osd, slot, 0);
- rm_runlock(&osd_object_lock[type], &tracker);
+ rm_runlock(&osdm[type].osd_object_lock, &tracker);
}
static void
@@ -289,7 +330,7 @@ do_osd_del(u_int type, struct osd *osd, u_int slot, int list_locked)
KASSERT(type >= OSD_FIRST && type <= OSD_LAST, ("Invalid type."));
KASSERT(slot > 0, ("Invalid slot."));
- KASSERT(osd_destructors[type][slot - 1] != NULL, ("Unused slot."));
+ KASSERT(osdm[type].osd_destructors[slot - 1] != NULL, ("Unused slot."));
OSD_DEBUG("Deleting slot (type=%u, slot=%u).", type, slot);
@@ -298,7 +339,7 @@ do_osd_del(u_int type, struct osd *osd, u_int slot, int list_locked)
return;
}
if (osd->osd_slots[slot - 1] != NULL) {
- osd_destructors[type][slot - 1](osd->osd_slots[slot - 1]);
+ osdm[type].osd_destructors[slot - 1](osd->osd_slots[slot - 1]);
osd->osd_slots[slot - 1] = NULL;
}
for (i = osd->osd_nslots - 1; i >= 0; i--) {
@@ -312,10 +353,10 @@ do_osd_del(u_int type, struct osd *osd, u_int slot, int list_locked)
/* No values left for this object. */
OSD_DEBUG("No more slots left (type=%u).", type);
if (!list_locked)
- mtx_lock(&osd_list_lock[type]);
+ mtx_lock(&osdm[type].osd_list_lock);
LIST_REMOVE(osd, osd_next);
if (!list_locked)
- mtx_unlock(&osd_list_lock[type]);
+ mtx_unlock(&osdm[type].osd_list_lock);
free(osd->osd_slots, M_OSD);
osd->osd_slots = NULL;
osd->osd_nslots = 0;
@@ -341,21 +382,21 @@ osd_call(u_int type, u_int method, void *obj, void *data)
int error, i;
KASSERT(type >= OSD_FIRST && type <= OSD_LAST, ("Invalid type."));
- KASSERT(method < osd_nmethods[type], ("Invalid method."));
+ KASSERT(method < osdm[type].osd_nmethods, ("Invalid method."));
/*
* Call this method for every slot that defines it, stopping if an
* error is encountered.
*/
error = 0;
- sx_slock(&osd_module_lock[type]);
- for (i = 0; i < osd_nslots[type]; i++) {
- methodfun =
- osd_methods[type][i * osd_nmethods[type] + method];
+ sx_slock(&osdm[type].osd_module_lock);
+ for (i = 0; i < osdm[type].osd_ntslots; i++) {
+ methodfun = osdm[type].osd_methods[i * osdm[type].osd_nmethods +
+ method];
if (methodfun != NULL && (error = methodfun(obj, data)) != 0)
break;
}
- sx_sunlock(&osd_module_lock[type]);
+ sx_sunlock(&osdm[type].osd_module_lock);
return (error);
}
@@ -373,14 +414,14 @@ osd_exit(u_int type, struct osd *osd)
return;
}
- rm_rlock(&osd_object_lock[type], &tracker);
+ rm_rlock(&osdm[type].osd_object_lock, &tracker);
for (i = 1; i <= osd->osd_nslots; i++) {
- if (osd_destructors[type][i - 1] != NULL)
+ if (osdm[type].osd_destructors[i - 1] != NULL)
do_osd_del(type, osd, i, 0);
else
OSD_DEBUG("Unused slot (type=%u, slot=%u).", type, i);
}
- rm_runlock(&osd_object_lock[type], &tracker);
+ rm_runlock(&osdm[type].osd_object_lock, &tracker);
OSD_DEBUG("Object exit (type=%u).", type);
}
@@ -390,13 +431,13 @@ osd_init(void *arg __unused)
u_int i;
for (i = OSD_FIRST; i <= OSD_LAST; i++) {
- osd_nslots[i] = 0;
- LIST_INIT(&osd_list[i]);
- sx_init(&osd_module_lock[i], "osd_module");
- rm_init(&osd_object_lock[i], "osd_object");
- mtx_init(&osd_list_lock[i], "osd_list", NULL, MTX_DEF);
- osd_destructors[i] = NULL;
- osd_methods[i] = NULL;
+ sx_init(&osdm[i].osd_module_lock, "osd_module");
+ rm_init(&osdm[i].osd_object_lock, "osd_object");
+ mtx_init(&osdm[i].osd_list_lock, "osd_list", NULL, MTX_DEF);
+ LIST_INIT(&osdm[i].osd_list);
+ osdm[i].osd_destructors = NULL;
+ osdm[i].osd_ntslots = 0;
+ osdm[i].osd_methods = NULL;
}
}
SYSINIT(osd, SI_SUB_LOCK, SI_ORDER_ANY, osd_init, NULL);
diff --git a/sys/kern/kern_racct.c b/sys/kern/kern_racct.c
index 1c3c9d7..419c69e 100644
--- a/sys/kern/kern_racct.c
+++ b/sys/kern/kern_racct.c
@@ -114,6 +114,8 @@ SDT_PROBE_DEFINE3(racct, , rusage, set,
"struct proc *", "int", "uint64_t");
SDT_PROBE_DEFINE3(racct, , rusage, set__failure,
"struct proc *", "int", "uint64_t");
+SDT_PROBE_DEFINE3(racct, , rusage, set__force,
+ "struct proc *", "int", "uint64_t");
SDT_PROBE_DEFINE3(racct, , rusage, sub,
"struct proc *", "int", "uint64_t");
SDT_PROBE_DEFINE3(racct, , rusage, sub__cred,
@@ -532,7 +534,7 @@ racct_adjust_resource(struct racct *racct, int resource,
}
static int
-racct_add_locked(struct proc *p, int resource, uint64_t amount)
+racct_add_locked(struct proc *p, int resource, uint64_t amount, int force)
{
#ifdef RCTL
int error;
@@ -540,8 +542,6 @@ racct_add_locked(struct proc *p, int resource, uint64_t amount)
ASSERT_RACCT_ENABLED();
- SDT_PROBE3(racct, , rusage, add, p, resource, amount);
-
/*
* We need proc lock to dereference p->p_ucred.
*/
@@ -549,7 +549,7 @@ racct_add_locked(struct proc *p, int resource, uint64_t amount)
#ifdef RCTL
error = rctl_enforce(p, resource, amount);
- if (error && RACCT_IS_DENIABLE(resource)) {
+ if (error && !force && RACCT_IS_DENIABLE(resource)) {
SDT_PROBE3(racct, , rusage, add__failure, p, resource, amount);
return (error);
}
@@ -572,12 +572,32 @@ racct_add(struct proc *p, int resource, uint64_t amount)
if (!racct_enable)
return (0);
+ SDT_PROBE3(racct, , rusage, add, p, resource, amount);
+
mtx_lock(&racct_lock);
- error = racct_add_locked(p, resource, amount);
+ error = racct_add_locked(p, resource, amount, 0);
mtx_unlock(&racct_lock);
return (error);
}
+/*
+ * Increase allocation of 'resource' by 'amount' for process 'p'.
+ * Doesn't check for limits and never fails.
+ */
+void
+racct_add_force(struct proc *p, int resource, uint64_t amount)
+{
+
+ if (!racct_enable)
+ return;
+
+ SDT_PROBE3(racct, , rusage, add__force, p, resource, amount);
+
+ mtx_lock(&racct_lock);
+ racct_add_locked(p, resource, amount, 1);
+ mtx_unlock(&racct_lock);
+}
+
static void
racct_add_cred_locked(struct ucred *cred, int resource, uint64_t amount)
{
@@ -597,8 +617,6 @@ racct_add_cred_locked(struct ucred *cred, int resource, uint64_t amount)
/*
* Increase allocation of 'resource' by 'amount' for credential 'cred'.
* Doesn't check for limits and never fails.
- *
- * XXX: Shouldn't this ever return an error?
*/
void
racct_add_cred(struct ucred *cred, int resource, uint64_t amount)
@@ -612,32 +630,8 @@ racct_add_cred(struct ucred *cred, int resource, uint64_t amount)
mtx_unlock(&racct_lock);
}
-/*
- * Increase allocation of 'resource' by 'amount' for process 'p'.
- * Doesn't check for limits and never fails.
- */
-void
-racct_add_force(struct proc *p, int resource, uint64_t amount)
-{
-
- if (!racct_enable)
- return;
-
- SDT_PROBE3(racct, , rusage, add__force, p, resource, amount);
-
- /*
- * We need proc lock to dereference p->p_ucred.
- */
- PROC_LOCK_ASSERT(p, MA_OWNED);
-
- mtx_lock(&racct_lock);
- racct_adjust_resource(p->p_racct, resource, amount);
- racct_add_cred_locked(p->p_ucred, resource, amount);
- mtx_unlock(&racct_lock);
-}
-
static int
-racct_set_locked(struct proc *p, int resource, uint64_t amount)
+racct_set_locked(struct proc *p, int resource, uint64_t amount, int force)
{
int64_t old_amount, decayed_amount;
int64_t diff_proc, diff_cred;
@@ -647,8 +641,6 @@ racct_set_locked(struct proc *p, int resource, uint64_t amount)
ASSERT_RACCT_ENABLED();
- SDT_PROBE3(racct, , rusage, set, p, resource, amount);
-
/*
* We need proc lock to dereference p->p_ucred.
*/
@@ -678,7 +670,7 @@ racct_set_locked(struct proc *p, int resource, uint64_t amount)
#ifdef RCTL
if (diff_proc > 0) {
error = rctl_enforce(p, resource, diff_proc);
- if (error && RACCT_IS_DENIABLE(resource)) {
+ if (error && !force && RACCT_IS_DENIABLE(resource)) {
SDT_PROBE3(racct, , rusage, set__failure, p, resource,
amount);
return (error);
@@ -709,51 +701,14 @@ racct_set(struct proc *p, int resource, uint64_t amount)
if (!racct_enable)
return (0);
+ SDT_PROBE3(racct, , rusage, set__force, p, resource, amount);
+
mtx_lock(&racct_lock);
- error = racct_set_locked(p, resource, amount);
+ error = racct_set_locked(p, resource, amount, 0);
mtx_unlock(&racct_lock);
return (error);
}
-static void
-racct_set_force_locked(struct proc *p, int resource, uint64_t amount)
-{
- int64_t old_amount, decayed_amount;
- int64_t diff_proc, diff_cred;
-
- ASSERT_RACCT_ENABLED();
-
- SDT_PROBE3(racct, , rusage, set, p, resource, amount);
-
- /*
- * We need proc lock to dereference p->p_ucred.
- */
- PROC_LOCK_ASSERT(p, MA_OWNED);
-
- old_amount = p->p_racct->r_resources[resource];
- /*
- * The diffs may be negative.
- */
- diff_proc = amount - old_amount;
- if (RACCT_IS_DECAYING(resource)) {
- /*
- * Resources in per-credential racct containers may decay.
- * If this is the case, we need to calculate the difference
- * between the new amount and the proportional value of the
- * old amount that has decayed in the ucred racct containers.
- */
- decayed_amount = old_amount * RACCT_DECAY_FACTOR / FSCALE;
- diff_cred = amount - decayed_amount;
- } else
- diff_cred = diff_proc;
-
- racct_adjust_resource(p->p_racct, resource, diff_proc);
- if (diff_cred > 0)
- racct_add_cred_locked(p->p_ucred, resource, diff_cred);
- else if (diff_cred < 0)
- racct_sub_cred_locked(p->p_ucred, resource, -diff_cred);
-}
-
void
racct_set_force(struct proc *p, int resource, uint64_t amount)
{
@@ -761,8 +716,10 @@ racct_set_force(struct proc *p, int resource, uint64_t amount)
if (!racct_enable)
return;
+ SDT_PROBE3(racct, , rusage, set, p, resource, amount);
+
mtx_lock(&racct_lock);
- racct_set_force_locked(p, resource, amount);
+ racct_set_locked(p, resource, amount, 1);
mtx_unlock(&racct_lock);
}
@@ -930,13 +887,13 @@ racct_proc_fork(struct proc *parent, struct proc *child)
continue;
error = racct_set_locked(child, i,
- parent->p_racct->r_resources[i]);
+ parent->p_racct->r_resources[i], 0);
if (error != 0)
goto out;
}
- error = racct_add_locked(child, RACCT_NPROC, 1);
- error += racct_add_locked(child, RACCT_NTHR, 1);
+ error = racct_add_locked(child, RACCT_NPROC, 1, 0);
+ error += racct_add_locked(child, RACCT_NTHR, 1, 0);
out:
mtx_unlock(&racct_lock);
@@ -1002,7 +959,7 @@ racct_proc_exit(struct proc *p)
pct = racct_getpcpu(p, pct_estimate);
mtx_lock(&racct_lock);
- racct_set_locked(p, RACCT_CPU, runtime);
+ racct_set_locked(p, RACCT_CPU, runtime, 0);
racct_add_cred_locked(p->p_ucred, RACCT_PCTCPU, pct);
for (i = 0; i <= RACCT_MAX; i++) {
@@ -1010,7 +967,7 @@ racct_proc_exit(struct proc *p)
continue;
if (!RACCT_IS_RECLAIMABLE(i))
continue;
- racct_set_locked(p, i, 0);
+ racct_set_locked(p, i, 0, 0);
}
mtx_unlock(&racct_lock);
@@ -1150,23 +1107,21 @@ racct_proc_wakeup(struct proc *p)
}
static void
-racct_decay_resource(struct racct *racct, void * res, void* dummy)
+racct_decay_callback(struct racct *racct, void *dummy1, void *dummy2)
{
- int resource;
int64_t r_old, r_new;
ASSERT_RACCT_ENABLED();
mtx_assert(&racct_lock, MA_OWNED);
- resource = *(int *)res;
- r_old = racct->r_resources[resource];
+ r_old = racct->r_resources[RACCT_PCTCPU];
/* If there is nothing to decay, just exit. */
if (r_old <= 0)
return;
r_new = r_old * RACCT_DECAY_FACTOR / FSCALE;
- racct->r_resources[resource] = r_new;
+ racct->r_resources[RACCT_PCTCPU] = r_new;
}
static void
@@ -1184,17 +1139,17 @@ racct_decay_post(void)
}
static void
-racct_decay(int resource)
+racct_decay(void)
{
ASSERT_RACCT_ENABLED();
- ui_racct_foreach(racct_decay_resource, racct_decay_pre,
- racct_decay_post, &resource, NULL);
- loginclass_racct_foreach(racct_decay_resource, racct_decay_pre,
- racct_decay_post, &resource, NULL);
- prison_racct_foreach(racct_decay_resource, racct_decay_pre,
- racct_decay_post, &resource, NULL);
+ ui_racct_foreach(racct_decay_callback, racct_decay_pre,
+ racct_decay_post, NULL, NULL);
+ loginclass_racct_foreach(racct_decay_callback, racct_decay_pre,
+ racct_decay_post, NULL, NULL);
+ prison_racct_foreach(racct_decay_callback, racct_decay_pre,
+ racct_decay_post, NULL, NULL);
}
static void
@@ -1209,7 +1164,7 @@ racctd(void)
ASSERT_RACCT_ENABLED();
for (;;) {
- racct_decay(RACCT_PCTCPU);
+ racct_decay();
sx_slock(&allproc_lock);
@@ -1249,11 +1204,11 @@ racctd(void)
pct_estimate = 0;
pct = racct_getpcpu(p, pct_estimate);
mtx_lock(&racct_lock);
- racct_set_force_locked(p, RACCT_PCTCPU, pct);
- racct_set_locked(p, RACCT_CPU, runtime);
+ racct_set_locked(p, RACCT_PCTCPU, pct, 1);
+ racct_set_locked(p, RACCT_CPU, runtime, 0);
racct_set_locked(p, RACCT_WALLCLOCK,
(uint64_t)wallclock.tv_sec * 1000000 +
- wallclock.tv_usec);
+ wallclock.tv_usec, 0);
mtx_unlock(&racct_lock);
PROC_UNLOCK(p);
}
diff --git a/sys/kern/kern_rctl.c b/sys/kern/kern_rctl.c
index b0d3fd6..1970ed8 100644
--- a/sys/kern/kern_rctl.c
+++ b/sys/kern/kern_rctl.c
@@ -78,10 +78,16 @@ FEATURE(rctl, "Resource Limits");
#define RCTL_PCPU_SHIFT (10 * 1000000)
unsigned int rctl_maxbufsize = RCTL_MAX_OUTBUFSIZE;
+static int rctl_log_rate_limit = 10;
+static int rctl_devctl_rate_limit = 10;
SYSCTL_NODE(_kern_racct, OID_AUTO, rctl, CTLFLAG_RW, 0, "Resource Limits");
SYSCTL_UINT(_kern_racct_rctl, OID_AUTO, maxbufsize, CTLFLAG_RWTUN,
&rctl_maxbufsize, 0, "Maximum output buffer size");
+SYSCTL_UINT(_kern_racct_rctl, OID_AUTO, log_rate_limit, CTLFLAG_RW,
+ &rctl_log_rate_limit, 0, "Maximum number of log messages per second");
+SYSCTL_UINT(_kern_racct_rctl, OID_AUTO, devctl_rate_limit, CTLFLAG_RW,
+ &rctl_devctl_rate_limit, 0, "Maximum number of devctl messages per second");
/*
* 'rctl_rule_link' connects a rule with every racct it's related to.
@@ -219,43 +225,43 @@ rctl_resource_name(int resource)
panic("rctl_resource_name: unknown resource %d", resource);
}
-/*
- * Return the amount of resource that can be allocated by 'p' before
- * hitting 'rule'.
- */
-static int64_t
-rctl_available_resource(const struct proc *p, const struct rctl_rule *rule)
+static struct racct *
+rctl_proc_rule_to_racct(const struct proc *p, const struct rctl_rule *rule)
{
- int resource;
- int64_t available = INT64_MAX;
struct ucred *cred = p->p_ucred;
ASSERT_RACCT_ENABLED();
rw_assert(&rctl_lock, RA_LOCKED);
- resource = rule->rr_resource;
switch (rule->rr_per) {
case RCTL_SUBJECT_TYPE_PROCESS:
- available = rule->rr_amount -
- p->p_racct->r_resources[resource];
- break;
+ return (p->p_racct);
case RCTL_SUBJECT_TYPE_USER:
- available = rule->rr_amount -
- cred->cr_ruidinfo->ui_racct->r_resources[resource];
- break;
+ return (cred->cr_ruidinfo->ui_racct);
case RCTL_SUBJECT_TYPE_LOGINCLASS:
- available = rule->rr_amount -
- cred->cr_loginclass->lc_racct->r_resources[resource];
- break;
+ return (cred->cr_loginclass->lc_racct);
case RCTL_SUBJECT_TYPE_JAIL:
- available = rule->rr_amount -
- cred->cr_prison->pr_prison_racct->prr_racct->
- r_resources[resource];
- break;
+ return (cred->cr_prison->pr_prison_racct->prr_racct);
default:
- panic("rctl_compute_available: unknown per %d",
- rule->rr_per);
+ panic("%s: unknown per %d", __func__, rule->rr_per);
}
+}
+
+/*
+ * Return the amount of resource that can be allocated by 'p' before
+ * hitting 'rule'.
+ */
+static int64_t
+rctl_available_resource(const struct proc *p, const struct rctl_rule *rule)
+{
+ int64_t available;
+ const struct racct *racct;
+
+ ASSERT_RACCT_ENABLED();
+ rw_assert(&rctl_lock, RA_LOCKED);
+
+ racct = rctl_proc_rule_to_racct(p, rule);
+ available = rule->rr_amount - racct->r_resources[rule->rr_resource];
return (available);
}
@@ -336,13 +342,13 @@ rctl_pcpu_available(const struct proc *p) {
int
rctl_enforce(struct proc *p, int resource, uint64_t amount)
{
+ static struct timeval log_lasttime, devctl_lasttime;
+ static int log_curtime = 0, devctl_curtime = 0;
struct rctl_rule *rule;
struct rctl_rule_link *link;
struct sbuf sb;
int should_deny = 0;
char *buf;
- static int curtime = 0;
- static struct timeval lasttime;
ASSERT_RACCT_ENABLED();
@@ -383,7 +389,8 @@ rctl_enforce(struct proc *p, int resource, uint64_t amount)
if (p->p_state != PRS_NORMAL)
continue;
- if (!ppsratecheck(&lasttime, &curtime, 10))
+ if (!ppsratecheck(&log_lasttime, &log_curtime,
+ rctl_log_rate_limit))
continue;
buf = malloc(RCTL_LOG_BUFSIZE, M_RCTL, M_NOWAIT);
@@ -409,6 +416,10 @@ rctl_enforce(struct proc *p, int resource, uint64_t amount)
if (p->p_state != PRS_NORMAL)
continue;
+ if (!ppsratecheck(&devctl_lasttime, &devctl_curtime,
+ rctl_devctl_rate_limit))
+ continue;
+
buf = malloc(RCTL_LOG_BUFSIZE, M_RCTL, M_NOWAIT);
if (buf == NULL) {
printf("rctl_enforce: out of memory\n");
@@ -642,6 +653,9 @@ str2int64(const char *str, int64_t *value)
if ((size_t)(end - str) != strlen(str))
return (EINVAL);
+ if (*value < 0)
+ return (ERANGE);
+
return (0);
}
@@ -1008,8 +1022,13 @@ rctl_string_to_rule(char *rulestr, struct rctl_rule **rulep)
error = str2int64(amountstr, &rule->rr_amount);
if (error != 0)
goto out;
- if (RACCT_IS_IN_MILLIONS(rule->rr_resource))
+ if (RACCT_IS_IN_MILLIONS(rule->rr_resource)) {
+ if (rule->rr_amount > INT64_MAX / 1000000) {
+ error = ERANGE;
+ goto out;
+ }
rule->rr_amount *= 1000000;
+ }
}
if (perstr == NULL || perstr[0] == '\0')
diff --git a/sys/kern/kern_sendfile.c b/sys/kern/kern_sendfile.c
index a2e1311..7ee7780 100644
--- a/sys/kern/kern_sendfile.c
+++ b/sys/kern/kern_sendfile.c
@@ -516,7 +516,7 @@ sendfile_getsock(struct thread *td, int s, struct file **sock_fp,
int
vn_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio,
struct uio *trl_uio, off_t offset, size_t nbytes, off_t *sent, int flags,
- int kflags, struct thread *td)
+ struct thread *td)
{
struct file *sock_fp;
struct vnode *vp;
@@ -534,7 +534,7 @@ vn_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio,
so = NULL;
m = mh = NULL;
sfs = NULL;
- sbytes = 0;
+ hdrlen = sbytes = 0;
softerr = 0;
error = sendfile_getobj(td, fp, &obj, &vp, &shmfd, &obj_size, &bsize);
@@ -560,26 +560,6 @@ vn_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio,
cv_init(&sfs->cv, "sendfile");
}
- /* If headers are specified copy them into mbufs. */
- if (hdr_uio != NULL && hdr_uio->uio_resid > 0) {
- hdr_uio->uio_td = td;
- hdr_uio->uio_rw = UIO_WRITE;
- /*
- * In FBSD < 5.0 the nbytes to send also included
- * the header. If compat is specified subtract the
- * header size from nbytes.
- */
- if (kflags & SFK_COMPAT) {
- if (nbytes > hdr_uio->uio_resid)
- nbytes -= hdr_uio->uio_resid;
- else
- nbytes = 0;
- }
- mh = m_uiotombuf(hdr_uio, M_WAITOK, 0, 0, 0);
- hdrlen = m_length(mh, &mhtail);
- } else
- hdrlen = 0;
-
rem = nbytes ? omin(nbytes, obj_size - offset) : obj_size - offset;
/*
@@ -668,11 +648,20 @@ retry_space:
SOCKBUF_UNLOCK(&so->so_snd);
/*
- * Reduce space in the socket buffer by the size of
- * the header mbuf chain.
- * hdrlen is set to 0 after the first loop.
+ * At the beginning of the first loop check if any headers
+ * are specified and copy them into mbufs. Reduce space in
+ * the socket buffer by the size of the header mbuf chain.
+ * Clear hdr_uio here and hdrlen at the end of the first loop.
*/
- space -= hdrlen;
+ if (hdr_uio != NULL && hdr_uio->uio_resid > 0) {
+ hdr_uio->uio_td = td;
+ hdr_uio->uio_rw = UIO_WRITE;
+ hdr_uio->uio_resid = min(hdr_uio->uio_resid, space);
+ mh = m_uiotombuf(hdr_uio, M_WAITOK, 0, 0, 0);
+ hdrlen = m_length(mh, &mhtail);
+ space -= hdrlen;
+ hdr_uio = NULL;
+ }
if (vp != NULL) {
error = vn_lock(vp, LK_SHARED);
@@ -944,6 +933,19 @@ sendfile(struct thread *td, struct sendfile_args *uap, int compat)
&hdr_uio);
if (error != 0)
goto out;
+#ifdef COMPAT_FREEBSD4
+ /*
+ * In FreeBSD < 5.0 the nbytes to send also included
+ * the header. If compat is specified subtract the
+ * header size from nbytes.
+ */
+ if (compat) {
+ if (uap->nbytes > hdr_uio->uio_resid)
+ uap->nbytes -= hdr_uio->uio_resid;
+ else
+ uap->nbytes = 0;
+ }
+#endif
}
if (hdtr.trailers != NULL) {
error = copyinuio(hdtr.trailers, hdtr.trl_cnt,
@@ -965,7 +967,7 @@ sendfile(struct thread *td, struct sendfile_args *uap, int compat)
}
error = fo_sendfile(fp, uap->s, hdr_uio, trl_uio, uap->offset,
- uap->nbytes, &sbytes, uap->flags, compat ? SFK_COMPAT : 0, td);
+ uap->nbytes, &sbytes, uap->flags, td);
fdrop(fp, td);
if (uap->sbytes != NULL)
diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c
index 8c84773..c9932f56 100644
--- a/sys/kern/kern_synch.c
+++ b/sys/kern/kern_synch.c
@@ -162,15 +162,7 @@ _sleep(void *ident, struct lock_object *lock, int priority,
else
class = NULL;
- if (cold || SCHEDULER_STOPPED()) {
- /*
- * During autoconfiguration, just return;
- * don't run any other threads or panic below,
- * in case this is the idle thread and already asleep.
- * XXX: this used to do "s = splhigh(); splx(safepri);
- * splx(s);" to give interrupts a chance, but there is
- * no way to give interrupts a chance now.
- */
+ if (SCHEDULER_STOPPED()) {
if (lock != NULL && priority & PDROP)
class->lc_unlock(lock);
return (0);
@@ -264,17 +256,8 @@ msleep_spin_sbt(void *ident, struct mtx *mtx, const char *wmesg,
KASSERT(p != NULL, ("msleep1"));
KASSERT(ident != NULL && TD_IS_RUNNING(td), ("msleep"));
- if (cold || SCHEDULER_STOPPED()) {
- /*
- * During autoconfiguration, just return;
- * don't run any other threads or panic below,
- * in case this is the idle thread and already asleep.
- * XXX: this used to do "s = splhigh(); splx(safepri);
- * splx(s);" to give interrupts a chance, but there is
- * no way to give interrupts a chance now.
- */
+ if (SCHEDULER_STOPPED())
return (0);
- }
sleepq_lock(ident);
CTR5(KTR_PROC, "msleep_spin: thread %ld (pid %ld, %s) on %s (%p)",
@@ -438,8 +421,10 @@ mi_switch(int flags, struct thread *newtd)
if (flags & SW_VOL) {
td->td_ru.ru_nvcsw++;
td->td_swvoltick = ticks;
- } else
+ } else {
td->td_ru.ru_nivcsw++;
+ td->td_swinvoltick = ticks;
+ }
#ifdef SCHED_STATS
SCHED_STAT_INC(sched_switch_stats[flags & SW_TYPE_MASK]);
#endif
diff --git a/sys/kern/pic_if.m b/sys/kern/pic_if.m
index 2309f0c..3003c35 100644
--- a/sys/kern/pic_if.m
+++ b/sys/kern/pic_if.m
@@ -1,7 +1,6 @@
#-
-# Copyright (c) 2012 Jakub Wojciech Klama <jceel@FreeBSD.org>
-# Copyright (c) 2015 Svatopluk Kraus
-# Copyright (c) 2015 Michal Meloun
+# Copyright (c) 2015-2016 Svatopluk Kraus
+# Copyright (c) 2015-2016 Michal Meloun
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -30,88 +29,132 @@
#include <sys/bus.h>
#include <sys/cpuset.h>
-#include <machine/frame.h>
-#include <machine/intr.h>
+#include <sys/resource.h>
+#include <sys/intr.h>
INTERFACE pic;
CODE {
- static int null_pic_bind(device_t dev, struct intr_irqsrc *isrc)
+ static int
+ dflt_pic_bind_intr(device_t dev, struct intr_irqsrc *isrc)
{
+
return (EOPNOTSUPP);
}
- static void null_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc)
+ static int
+ null_pic_alloc_intr(device_t dev, struct intr_irqsrc *isrc,
+ struct resource *res, struct intr_map_data *data)
+ {
+
+ return (0);
+ }
+
+ static int
+ null_pic_release_intr(device_t dev, struct intr_irqsrc *isrc,
+ struct resource *res, struct intr_map_data *data)
+ {
+
+ return (0);
+ }
+
+ static int
+ null_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc,
+ struct resource *res, struct intr_map_data *data)
{
- return;
+
+ return (0);
}
- static void null_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
+ static int
+ null_pic_teardown_intr(device_t dev, struct intr_irqsrc *isrc,
+ struct resource *res, struct intr_map_data *data)
{
- return;
+
+ return (0);
}
- static void null_pic_init_secondary(device_t dev)
+ static void
+ null_pic_init_secondary(device_t dev)
{
- return;
}
- static void null_pic_ipi_send(device_t dev, cpuset_t cpus, u_int ipi)
+ static void
+ null_pic_ipi_send(device_t dev, cpuset_t cpus, u_int ipi)
{
- return;
+ }
+
+ static int
+ dflt_pic_ipi_setup(device_t dev, u_int ipi, struct intr_irqsrc *isrc)
+ {
+
+ return (EOPNOTSUPP);
}
};
-METHOD int register {
+METHOD int alloc_intr {
device_t dev;
struct intr_irqsrc *isrc;
- boolean_t *is_percpu;
-};
+ struct resource *res;
+ struct intr_map_data *data;
+} DEFAULT null_pic_alloc_intr;
-METHOD int unregister {
+METHOD int bind_intr {
device_t dev;
struct intr_irqsrc *isrc;
-};
+} DEFAULT dflt_pic_bind_intr;
METHOD void disable_intr {
device_t dev;
struct intr_irqsrc *isrc;
-} DEFAULT null_pic_disable_intr;
+};
-METHOD void disable_source {
+METHOD void enable_intr {
device_t dev;
struct intr_irqsrc *isrc;
};
-METHOD void enable_source {
+METHOD int map_intr {
device_t dev;
- struct intr_irqsrc *isrc;
+ struct intr_map_data *data;
+ struct intr_irqsrc **isrcp;
};
-METHOD void enable_intr {
+METHOD int release_intr {
device_t dev;
struct intr_irqsrc *isrc;
-} DEFAULT null_pic_enable_intr;
+ struct resource *res;
+ struct intr_map_data *data;
+} DEFAULT null_pic_release_intr;
-METHOD void pre_ithread {
+METHOD int setup_intr {
device_t dev;
struct intr_irqsrc *isrc;
-};
+ struct resource *res;
+ struct intr_map_data *data;
+} DEFAULT null_pic_setup_intr;
-METHOD void post_ithread {
+METHOD int teardown_intr {
device_t dev;
struct intr_irqsrc *isrc;
-};
+ struct resource *res;
+ struct intr_map_data *data;
+} DEFAULT null_pic_teardown_intr;
METHOD void post_filter {
device_t dev;
struct intr_irqsrc *isrc;
};
-METHOD int bind {
+METHOD void post_ithread {
device_t dev;
struct intr_irqsrc *isrc;
-} DEFAULT null_pic_bind;
+};
+
+METHOD void pre_ithread {
+ device_t dev;
+ struct intr_irqsrc *isrc;
+};
METHOD void init_secondary {
device_t dev;
@@ -121,4 +164,11 @@ METHOD void ipi_send {
device_t dev;
struct intr_irqsrc *isrc;
cpuset_t cpus;
+ u_int ipi;
} DEFAULT null_pic_ipi_send;
+
+METHOD int ipi_setup {
+ device_t dev;
+ u_int ipi;
+ struct intr_irqsrc **isrcp;
+} DEFAULT dflt_pic_ipi_setup;
diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c
index 8daa9f2..caf9202 100644
--- a/sys/kern/subr_bus.c
+++ b/sys/kern/subr_bus.c
@@ -839,6 +839,38 @@ sysctl_devctl_queue(SYSCTL_HANDLER_ARGS)
return (0);
}
+/**
+ * @brief safely quotes strings that might have double quotes in them.
+ *
+ * The devctl protocol relies on quoted strings having matching quotes.
+ * This routine quotes any internal quotes so the resulting string
+ * is safe to pass to snprintf to construct, for example pnp info strings.
+ * Strings are always terminated with a NUL, but may be truncated if longer
+ * than @p len bytes after quotes.
+ *
+ * @param dst Buffer to hold the string. Must be at least @p len bytes long
+ * @param src Original buffer.
+ * @param len Length of buffer pointed to by @dst, including trailing NUL
+ */
+void
+devctl_safe_quote(char *dst, const char *src, size_t len)
+{
+ char *walker = dst, *ep = dst + len - 1;
+
+ if (len == 0)
+ return;
+ while (src != NULL && walker < ep)
+ {
+ if (*src == '"') {
+ if (ep - walker < 2)
+ break;
+ *walker++ = '\\';
+ }
+ *walker++ = *src++;
+ }
+ *walker = '\0';
+}
+
/* End of /dev/devctl code */
static TAILQ_HEAD(,device) bus_data_devices;
diff --git a/sys/kern/subr_counter.c b/sys/kern/subr_counter.c
index ea2759c..5149f2d 100644
--- a/sys/kern/subr_counter.c
+++ b/sys/kern/subr_counter.c
@@ -94,3 +94,28 @@ sysctl_handle_counter_u64(SYSCTL_HANDLER_ARGS)
return (0);
}
+
+int
+sysctl_handle_counter_u64_array(SYSCTL_HANDLER_ARGS)
+{
+ uint64_t *out;
+ int error;
+
+ out = malloc(arg2 * sizeof(uint64_t), M_TEMP, M_WAITOK);
+ for (int i = 0; i < arg2; i++)
+ out[i] = counter_u64_fetch(((counter_u64_t *)arg1)[i]);
+
+ error = SYSCTL_OUT(req, out, arg2 * sizeof(uint64_t));
+ free(out, M_TEMP);
+
+ if (error || !req->newptr)
+ return (error);
+
+ /*
+ * Any write attempt to a counter zeroes it.
+ */
+ for (int i = 0; i < arg2; i++)
+ counter_u64_zero(((counter_u64_t *)arg1)[i]);
+
+ return (0);
+}
diff --git a/sys/kern/subr_intr.c b/sys/kern/subr_intr.c
index 1c97fd4..96319ad 100644
--- a/sys/kern/subr_intr.c
+++ b/sys/kern/subr_intr.c
@@ -1,7 +1,6 @@
/*-
- * Copyright (c) 2012-2014 Jakub Wojciech Klama <jceel@FreeBSD.org>.
- * Copyright (c) 2015 Svatopluk Kraus
- * Copyright (c) 2015 Michal Meloun
+ * Copyright (c) 2015-2016 Svatopluk Kraus
+ * Copyright (c) 2015-2016 Michal Meloun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -24,8 +23,6 @@
* 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/cdefs.h>
@@ -38,6 +35,7 @@ __FBSDID("$FreeBSD$");
* - to complete things for removable PICs
*/
+#include "opt_acpi.h"
#include "opt_ddb.h"
#include "opt_platform.h"
@@ -52,6 +50,7 @@ __FBSDID("$FreeBSD$");
#include <sys/interrupt.h>
#include <sys/conf.h>
#include <sys/cpuset.h>
+#include <sys/rman.h>
#include <sys/sched.h>
#include <sys/smp.h>
#include <machine/atomic.h>
@@ -112,6 +111,35 @@ u_int irq_next_free;
#define IRQ_INVALID nitems(irq_sources)
+/*
+ * XXX - All stuff around struct intr_dev_data is considered as temporary
+ * until better place for storing struct intr_map_data will be find.
+ *
+ * For now, there are two global interrupt numbers spaces:
+ * <0, NIRQ) ... interrupts without config data
+ * managed in irq_sources[]
+ * IRQ_DDATA_BASE + <0, 2 * NIRQ) ... interrupts with config data
+ * managed in intr_ddata_tab[]
+ *
+ * Read intr_ddata_lookup() to see how these spaces are worked with.
+ * Note that each interrupt number from second space duplicates some number
+ * from first space at this moment. An interrupt number from first space can
+ * be duplicated even multiple times in second space.
+ */
+struct intr_dev_data {
+ device_t idd_dev;
+ intptr_t idd_xref;
+ u_int idd_irq;
+ struct intr_map_data idd_data;
+ struct intr_irqsrc * idd_isrc;
+};
+
+static struct intr_dev_data *intr_ddata_tab[2 * NIRQ];
+static u_int intr_ddata_first_unused;
+
+#define IRQ_DDATA_BASE 10000
+CTASSERT(IRQ_DDATA_BASE > IRQ_INVALID);
+
#ifdef SMP
static boolean_t irq_assign_cpu = FALSE;
#endif
@@ -173,12 +201,10 @@ static inline void
isrc_increment_count(struct intr_irqsrc *isrc)
{
- /*
- * XXX - It should be atomic for PPI interrupts. It was proven that
- * the lost is measurable easily for timer PPI interrupts.
- */
- isrc->isrc_count[0]++;
- /*atomic_add_long(&isrc->isrc_count[0], 1);*/
+ if (isrc->isrc_flags & INTR_ISRCF_PPI)
+ atomic_add_long(&isrc->isrc_count[0], 1);
+ else
+ isrc->isrc_count[0]++;
}
/*
@@ -233,6 +259,16 @@ isrc_setup_counters(struct intr_irqsrc *isrc)
isrc_update_name(isrc, NULL);
}
+/*
+ * Virtualization for interrupt source interrupt counters release.
+ */
+static void
+isrc_release_counters(struct intr_irqsrc *isrc)
+{
+
+ panic("%s: not implemented", __func__);
+}
+
#ifdef SMP
/*
* Virtualization for interrupt source IPI counters setup.
@@ -279,8 +315,8 @@ intr_irq_handler(struct trapframe *tf)
* be called straight from the interrupt controller, when associated interrupt
* source is learned.
*/
-void
-intr_irq_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf)
+int
+intr_isrc_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf)
{
KASSERT(isrc != NULL, ("%s: no source", __func__));
@@ -293,57 +329,16 @@ intr_irq_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf)
error = isrc->isrc_filter(isrc->isrc_arg, tf);
PIC_POST_FILTER(isrc->isrc_dev, isrc);
if (error == FILTER_HANDLED)
- return;
- } else
+ return (0);
+ } else
#endif
if (isrc->isrc_event != NULL) {
if (intr_event_handle(isrc->isrc_event, tf) == 0)
- return;
+ return (0);
}
isrc_increment_straycount(isrc);
- PIC_DISABLE_SOURCE(isrc->isrc_dev, isrc);
-
- device_printf(isrc->isrc_dev, "stray irq <%s> disabled",
- isrc->isrc_name);
-}
-
-/*
- * Allocate interrupt source.
- */
-static struct intr_irqsrc *
-isrc_alloc(u_int type, u_int extsize)
-{
- struct intr_irqsrc *isrc;
-
- isrc = malloc(sizeof(*isrc) + extsize, M_INTRNG, M_WAITOK | M_ZERO);
- isrc->isrc_irq = IRQ_INVALID; /* just to be safe */
- isrc->isrc_type = type;
- isrc->isrc_nspc_type = INTR_IRQ_NSPC_NONE;
- isrc->isrc_trig = INTR_TRIGGER_CONFORM;
- isrc->isrc_pol = INTR_POLARITY_CONFORM;
- CPU_ZERO(&isrc->isrc_cpu);
- return (isrc);
-}
-
-/*
- * Free interrupt source.
- */
-static void
-isrc_free(struct intr_irqsrc *isrc)
-{
-
- free(isrc, M_INTRNG);
-}
-
-void
-intr_irq_set_name(struct intr_irqsrc *isrc, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- vsnprintf(isrc->isrc_name, INTR_ISRC_NAMELEN, fmt, ap);
- va_end(ap);
+ return (EINVAL);
}
/*
@@ -356,8 +351,8 @@ intr_irq_set_name(struct intr_irqsrc *isrc, const char *fmt, ...)
* immediately. However, if only one free handle left which is reused
* constantly...
*/
-static int
-isrc_alloc_irq_locked(struct intr_irqsrc *isrc)
+static inline int
+isrc_alloc_irq(struct intr_irqsrc *isrc)
{
u_int maxirqs, irq;
@@ -383,46 +378,35 @@ found:
isrc->isrc_irq = irq;
irq_sources[irq] = isrc;
- intr_irq_set_name(isrc, "irq%u", irq);
- isrc_setup_counters(isrc);
-
irq_next_free = irq + 1;
if (irq_next_free >= maxirqs)
irq_next_free = 0;
return (0);
}
-#ifdef notyet
+
/*
* Free unique interrupt number (resource handle) from interrupt source.
*/
-static int
+static inline int
isrc_free_irq(struct intr_irqsrc *isrc)
{
- u_int maxirqs;
- mtx_assert(&isrc_table_lock, MA_NOTOWNED);
+ mtx_assert(&isrc_table_lock, MA_OWNED);
- maxirqs = nitems(irq_sources);
- if (isrc->isrc_irq >= maxirqs)
+ if (isrc->isrc_irq >= nitems(irq_sources))
return (EINVAL);
-
- mtx_lock(&isrc_table_lock);
- if (irq_sources[isrc->isrc_irq] != isrc) {
- mtx_unlock(&isrc_table_lock);
+ if (irq_sources[isrc->isrc_irq] != isrc)
return (EINVAL);
- }
irq_sources[isrc->isrc_irq] = NULL;
isrc->isrc_irq = IRQ_INVALID; /* just to be safe */
- mtx_unlock(&isrc_table_lock);
-
return (0);
}
-#endif
+
/*
* Lookup interrupt source by interrupt number (resource handle).
*/
-static struct intr_irqsrc *
+static inline struct intr_irqsrc *
isrc_lookup(u_int irq)
{
@@ -432,158 +416,159 @@ isrc_lookup(u_int irq)
}
/*
- * Lookup interrupt source by namespace description.
+ * Initialize interrupt source and register it into global interrupt table.
*/
-static struct intr_irqsrc *
-isrc_namespace_lookup(device_t dev, uint16_t type, uint16_t num)
+int
+intr_isrc_register(struct intr_irqsrc *isrc, device_t dev, u_int flags,
+ const char *fmt, ...)
{
- u_int irq;
- struct intr_irqsrc *isrc;
+ int error;
+ va_list ap;
- mtx_assert(&isrc_table_lock, MA_OWNED);
+ bzero(isrc, sizeof(struct intr_irqsrc));
+ isrc->isrc_dev = dev;
+ isrc->isrc_irq = IRQ_INVALID; /* just to be safe */
+ isrc->isrc_flags = flags;
+
+ va_start(ap, fmt);
+ vsnprintf(isrc->isrc_name, INTR_ISRC_NAMELEN, fmt, ap);
+ va_end(ap);
- for (irq = 0; irq < nitems(irq_sources); irq++) {
- isrc = irq_sources[irq];
- if (isrc != NULL && isrc->isrc_dev == dev &&
- isrc->isrc_nspc_type == type && isrc->isrc_nspc_num == num)
- return (isrc);
+ mtx_lock(&isrc_table_lock);
+ error = isrc_alloc_irq(isrc);
+ if (error != 0) {
+ mtx_unlock(&isrc_table_lock);
+ return (error);
}
- return (NULL);
+ /*
+ * Setup interrupt counters, but not for IPI sources. Those are setup
+ * later and only for used ones (up to INTR_IPI_COUNT) to not exhaust
+ * our counter pool.
+ */
+ if ((isrc->isrc_flags & INTR_ISRCF_IPI) == 0)
+ isrc_setup_counters(isrc);
+ mtx_unlock(&isrc_table_lock);
+ return (0);
}
/*
- * Map interrupt source according to namespace into framework. If such mapping
- * does not exist, create it. Return unique interrupt number (resource handle)
- * associated with mapped interrupt source.
+ * Deregister interrupt source from global interrupt table.
*/
-u_int
-intr_namespace_map_irq(device_t dev, uint16_t type, uint16_t num)
+int
+intr_isrc_deregister(struct intr_irqsrc *isrc)
{
- struct intr_irqsrc *isrc, *new_isrc;
int error;
- new_isrc = isrc_alloc(INTR_ISRCT_NAMESPACE, 0);
-
mtx_lock(&isrc_table_lock);
- isrc = isrc_namespace_lookup(dev, type, num);
- if (isrc != NULL) {
- mtx_unlock(&isrc_table_lock);
- isrc_free(new_isrc);
- return (isrc->isrc_irq); /* already mapped */
- }
+ if ((isrc->isrc_flags & INTR_ISRCF_IPI) == 0)
+ isrc_release_counters(isrc);
+ error = isrc_free_irq(isrc);
+ mtx_unlock(&isrc_table_lock);
+ return (error);
+}
- error = isrc_alloc_irq_locked(new_isrc);
- if (error != 0) {
+static struct intr_dev_data *
+intr_ddata_alloc(u_int extsize)
+{
+ struct intr_dev_data *ddata;
+
+ ddata = malloc(sizeof(*ddata) + extsize, M_INTRNG, M_WAITOK | M_ZERO);
+
+ mtx_lock(&isrc_table_lock);
+ if (intr_ddata_first_unused >= nitems(intr_ddata_tab)) {
mtx_unlock(&isrc_table_lock);
- isrc_free(new_isrc);
- return (IRQ_INVALID); /* no space left */
+ free(ddata, M_INTRNG);
+ return (NULL);
}
-
- new_isrc->isrc_dev = dev;
- new_isrc->isrc_nspc_type = type;
- new_isrc->isrc_nspc_num = num;
+ intr_ddata_tab[intr_ddata_first_unused] = ddata;
+ ddata->idd_irq = IRQ_DDATA_BASE + intr_ddata_first_unused++;
mtx_unlock(&isrc_table_lock);
-
- return (new_isrc->isrc_irq);
+ return (ddata);
}
-#ifdef FDT
-/*
- * Lookup interrupt source by FDT description.
- */
static struct intr_irqsrc *
-isrc_fdt_lookup(intptr_t xref, pcell_t *cells, u_int ncells)
+intr_ddata_lookup(u_int irq, struct intr_map_data **datap)
{
- u_int irq, cellsize;
+ int error;
struct intr_irqsrc *isrc;
+ struct intr_dev_data *ddata;
- mtx_assert(&isrc_table_lock, MA_OWNED);
+ isrc = isrc_lookup(irq);
+ if (isrc != NULL) {
+ if (datap != NULL)
+ *datap = NULL;
+ return (isrc);
+ }
- cellsize = ncells * sizeof(*cells);
- for (irq = 0; irq < nitems(irq_sources); irq++) {
- isrc = irq_sources[irq];
- if (isrc != NULL && isrc->isrc_type == INTR_ISRCT_FDT &&
- isrc->isrc_xref == xref && isrc->isrc_ncells == ncells &&
- memcmp(isrc->isrc_cells, cells, cellsize) == 0)
- return (isrc);
+ if (irq < IRQ_DDATA_BASE)
+ return (NULL);
+
+ irq -= IRQ_DDATA_BASE;
+ if (irq >= nitems(intr_ddata_tab))
+ return (NULL);
+
+ ddata = intr_ddata_tab[irq];
+ if (ddata->idd_isrc == NULL) {
+ error = intr_map_irq(ddata->idd_dev, ddata->idd_xref,
+ &ddata->idd_data, &irq);
+ if (error != 0)
+ return (NULL);
+ ddata->idd_isrc = isrc_lookup(irq);
}
- return (NULL);
+ if (datap != NULL)
+ *datap = &ddata->idd_data;
+ return (ddata->idd_isrc);
}
+#ifdef DEV_ACPI
/*
- * Map interrupt source according to FDT data into framework. If such mapping
+ * Map interrupt source according to ACPI info into framework. If such mapping
* does not exist, create it. Return unique interrupt number (resource handle)
* associated with mapped interrupt source.
*/
u_int
-intr_fdt_map_irq(phandle_t node, pcell_t *cells, u_int ncells)
+intr_acpi_map_irq(device_t dev, u_int irq, enum intr_polarity pol,
+ enum intr_trigger trig)
{
- struct intr_irqsrc *isrc, *new_isrc;
- u_int cellsize;
- intptr_t xref;
- int error;
-
- xref = (intptr_t)node; /* It's so simple for now. */
-
- cellsize = ncells * sizeof(*cells);
- new_isrc = isrc_alloc(INTR_ISRCT_FDT, cellsize);
-
- mtx_lock(&isrc_table_lock);
- isrc = isrc_fdt_lookup(xref, cells, ncells);
- if (isrc != NULL) {
- mtx_unlock(&isrc_table_lock);
- isrc_free(new_isrc);
- return (isrc->isrc_irq); /* already mapped */
- }
-
- error = isrc_alloc_irq_locked(new_isrc);
- if (error != 0) {
- mtx_unlock(&isrc_table_lock);
- isrc_free(new_isrc);
- return (IRQ_INVALID); /* no space left */
- }
-
- new_isrc->isrc_xref = xref;
- new_isrc->isrc_ncells = ncells;
- memcpy(new_isrc->isrc_cells, cells, cellsize);
- mtx_unlock(&isrc_table_lock);
-
- return (new_isrc->isrc_irq);
+ struct intr_dev_data *ddata;
+
+ ddata = intr_ddata_alloc(0);
+ if (ddata == NULL)
+ return (0xFFFFFFFF); /* no space left */
+
+ ddata->idd_dev = dev;
+ ddata->idd_data.type = INTR_MAP_DATA_ACPI;
+ ddata->idd_data.acpi.irq = irq;
+ ddata->idd_data.acpi.pol = pol;
+ ddata->idd_data.acpi.trig = trig;
+ return (ddata->idd_irq);
}
#endif
-
+#ifdef FDT
/*
- * Register interrupt source into interrupt controller.
+ * Map interrupt source according to FDT data into framework. If such mapping
+ * does not exist, create it. Return unique interrupt number (resource handle)
+ * associated with mapped interrupt source.
*/
-static int
-isrc_register(struct intr_irqsrc *isrc)
+u_int
+intr_fdt_map_irq(phandle_t node, pcell_t *cells, u_int ncells)
{
- struct intr_pic *pic;
- boolean_t is_percpu;
- int error;
-
- if (isrc->isrc_flags & INTR_ISRCF_REGISTERED)
- return (0);
-
- if (isrc->isrc_dev == NULL) {
- pic = pic_lookup(NULL, isrc->isrc_xref);
- if (pic == NULL || pic->pic_dev == NULL)
- return (ESRCH);
- isrc->isrc_dev = pic->pic_dev;
- }
-
- error = PIC_REGISTER(isrc->isrc_dev, isrc, &is_percpu);
- if (error != 0)
- return (error);
+ struct intr_dev_data *ddata;
+ u_int cellsize;
- mtx_lock(&isrc_table_lock);
- isrc->isrc_flags |= INTR_ISRCF_REGISTERED;
- if (is_percpu)
- isrc->isrc_flags |= INTR_ISRCF_PERCPU;
- isrc_update_name(isrc, NULL);
- mtx_unlock(&isrc_table_lock);
- return (0);
+ cellsize = ncells * sizeof(*cells);
+ ddata = intr_ddata_alloc(cellsize);
+ if (ddata == NULL)
+ return (0xFFFFFFFF); /* no space left */
+
+ ddata->idd_xref = (intptr_t)node;
+ ddata->idd_data.type = INTR_MAP_DATA_FDT;
+ ddata->idd_data.fdt.ncells = ncells;
+ ddata->idd_data.fdt.cells = (pcell_t *)(ddata + 1);
+ memcpy(ddata->idd_data.fdt.cells, cells, cellsize);
+ return (ddata->idd_irq);
}
+#endif
#ifdef INTR_SOLO
/*
@@ -678,7 +663,7 @@ intr_isrc_assign_cpu(void *arg, int cpu)
* informed if the call is successfull.
*/
if (irq_assign_cpu) {
- error = PIC_BIND(isrc->isrc_dev, isrc);
+ error = PIC_BIND_INTR(isrc->isrc_dev, isrc);
if (error) {
CPU_ZERO(&isrc->isrc_cpu);
mtx_unlock(&isrc_table_lock);
@@ -774,7 +759,7 @@ isrc_add_handler(struct intr_irqsrc *isrc, const char *name,
/*
* Lookup interrupt controller locked.
*/
-static struct intr_pic *
+static inline struct intr_pic *
pic_lookup_locked(device_t dev, intptr_t xref)
{
struct intr_pic *pic;
@@ -801,7 +786,6 @@ pic_lookup(device_t dev, intptr_t xref)
mtx_lock(&pic_list_lock);
pic = pic_lookup_locked(dev, xref);
mtx_unlock(&pic_list_lock);
-
return (pic);
}
@@ -871,7 +855,7 @@ intr_pic_register(device_t dev, intptr_t xref)
* Unregister interrupt controller.
*/
int
-intr_pic_unregister(device_t dev, intptr_t xref)
+intr_pic_deregister(device_t dev, intptr_t xref)
{
panic("%s: not implemented", __func__);
@@ -923,12 +907,73 @@ intr_pic_claim_root(device_t dev, intptr_t xref, intr_irq_filter_t *filter,
}
int
-intr_irq_add_handler(device_t dev, driver_filter_t filt, driver_intr_t hand,
- void *arg, u_int irq, int flags, void **cookiep)
+intr_map_irq(device_t dev, intptr_t xref, struct intr_map_data *data,
+ u_int *irqp)
{
- const char *name;
+ int error;
+ struct intr_irqsrc *isrc;
+ struct intr_pic *pic;
+
+ if (data == NULL)
+ return (EINVAL);
+
+ pic = pic_lookup(dev, xref);
+ if (pic == NULL || pic->pic_dev == NULL)
+ return (ESRCH);
+
+ error = PIC_MAP_INTR(pic->pic_dev, data, &isrc);
+ if (error == 0)
+ *irqp = isrc->isrc_irq;
+ return (error);
+}
+
+int
+intr_alloc_irq(device_t dev, struct resource *res)
+{
+ struct intr_map_data *data;
+ struct intr_irqsrc *isrc;
+
+ KASSERT(rman_get_start(res) == rman_get_end(res),
+ ("%s: more interrupts in resource", __func__));
+
+ isrc = intr_ddata_lookup(rman_get_start(res), &data);
+ if (isrc == NULL)
+ return (EINVAL);
+
+ return (PIC_ALLOC_INTR(isrc->isrc_dev, isrc, res, data));
+}
+
+int
+intr_release_irq(device_t dev, struct resource *res)
+{
+ struct intr_map_data *data;
struct intr_irqsrc *isrc;
+
+ KASSERT(rman_get_start(res) == rman_get_end(res),
+ ("%s: more interrupts in resource", __func__));
+
+ isrc = intr_ddata_lookup(rman_get_start(res), &data);
+ if (isrc == NULL)
+ return (EINVAL);
+
+ return (PIC_RELEASE_INTR(isrc->isrc_dev, isrc, res, data));
+}
+
+int
+intr_setup_irq(device_t dev, struct resource *res, driver_filter_t filt,
+ driver_intr_t hand, void *arg, int flags, void **cookiep)
+{
int error;
+ struct intr_map_data *data;
+ struct intr_irqsrc *isrc;
+ const char *name;
+
+ KASSERT(rman_get_start(res) == rman_get_end(res),
+ ("%s: more interrupts in resource", __func__));
+
+ isrc = intr_ddata_lookup(rman_get_start(res), &data);
+ if (isrc == NULL)
+ return (EINVAL);
name = device_get_nameunit(dev);
@@ -947,21 +992,7 @@ intr_irq_add_handler(device_t dev, driver_filter_t filt, driver_intr_t hand,
debugf("irq %u cannot solo on %s\n", irq, name);
return (EINVAL);
}
-#endif
- isrc = isrc_lookup(irq);
- if (isrc == NULL) {
- debugf("irq %u without source on %s\n", irq, name);
- return (EINVAL);
- }
-
- error = isrc_register(isrc);
- if (error != 0) {
- debugf("irq %u map error %d on %s\n", irq, error, name);
- return (error);
- }
-
-#ifdef INTR_SOLO
if (flags & INTR_SOLO) {
error = iscr_setup_filter(isrc, name, (intr_irq_filter_t *)filt,
arg, cookiep);
@@ -978,24 +1009,32 @@ intr_irq_add_handler(device_t dev, driver_filter_t filt, driver_intr_t hand,
return (error);
mtx_lock(&isrc_table_lock);
- isrc->isrc_handlers++;
- if (isrc->isrc_handlers == 1) {
- PIC_ENABLE_INTR(isrc->isrc_dev, isrc);
- PIC_ENABLE_SOURCE(isrc->isrc_dev, isrc);
+ error = PIC_SETUP_INTR(isrc->isrc_dev, isrc, res, data);
+ if (error == 0) {
+ isrc->isrc_handlers++;
+ if (isrc->isrc_handlers == 1)
+ PIC_ENABLE_INTR(isrc->isrc_dev, isrc);
}
mtx_unlock(&isrc_table_lock);
- return (0);
+ if (error != 0)
+ intr_event_remove_handler(*cookiep);
+ return (error);
}
int
-intr_irq_remove_handler(device_t dev, u_int irq, void *cookie)
+intr_teardown_irq(device_t dev, struct resource *res, void *cookie)
{
- struct intr_irqsrc *isrc;
int error;
+ struct intr_map_data *data;
+ struct intr_irqsrc *isrc;
- isrc = isrc_lookup(irq);
+ KASSERT(rman_get_start(res) == rman_get_end(res),
+ ("%s: more interrupts in resource", __func__));
+
+ isrc = intr_ddata_lookup(rman_get_start(res), &data);
if (isrc == NULL || isrc->isrc_handlers == 0)
return (EINVAL);
+
#ifdef INTR_SOLO
if (isrc->isrc_filter != NULL) {
if (isrc != cookie)
@@ -1005,8 +1044,8 @@ intr_irq_remove_handler(device_t dev, u_int irq, void *cookie)
isrc->isrc_filter = NULL;
isrc->isrc_arg = NULL;
isrc->isrc_handlers = 0;
- PIC_DISABLE_SOURCE(isrc->isrc_dev, isrc);
PIC_DISABLE_INTR(isrc->isrc_dev, isrc);
+ PIC_TEARDOWN_INTR(isrc->isrc_dev, isrc, res, data);
isrc_update_name(isrc, NULL);
mtx_unlock(&isrc_table_lock);
return (0);
@@ -1019,10 +1058,9 @@ intr_irq_remove_handler(device_t dev, u_int irq, void *cookie)
if (error == 0) {
mtx_lock(&isrc_table_lock);
isrc->isrc_handlers--;
- if (isrc->isrc_handlers == 0) {
- PIC_DISABLE_SOURCE(isrc->isrc_dev, isrc);
+ if (isrc->isrc_handlers == 0)
PIC_DISABLE_INTR(isrc->isrc_dev, isrc);
- }
+ PIC_TEARDOWN_INTR(isrc->isrc_dev, isrc, res, data);
intrcnt_updatename(isrc);
mtx_unlock(&isrc_table_lock);
}
@@ -1030,36 +1068,16 @@ intr_irq_remove_handler(device_t dev, u_int irq, void *cookie)
}
int
-intr_irq_config(u_int irq, enum intr_trigger trig, enum intr_polarity pol)
+intr_describe_irq(device_t dev, struct resource *res, void *cookie,
+ const char *descr)
{
+ int error;
struct intr_irqsrc *isrc;
- isrc = isrc_lookup(irq);
- if (isrc == NULL)
- return (EINVAL);
-
- if (isrc->isrc_handlers != 0)
- return (EBUSY); /* interrrupt is enabled (active) */
+ KASSERT(rman_get_start(res) == rman_get_end(res),
+ ("%s: more interrupts in resource", __func__));
- /*
- * Once an interrupt is enabled, we do not change its configuration.
- * A controller PIC_ENABLE_INTR() method is called when an interrupt
- * is going to be enabled. In this method, a controller should setup
- * the interrupt according to saved configuration parameters.
- */
- isrc->isrc_trig = trig;
- isrc->isrc_pol = pol;
-
- return (0);
-}
-
-int
-intr_irq_describe(u_int irq, void *cookie, const char *descr)
-{
- struct intr_irqsrc *isrc;
- int error;
-
- isrc = isrc_lookup(irq);
+ isrc = intr_ddata_lookup(rman_get_start(res), NULL);
if (isrc == NULL || isrc->isrc_handlers == 0)
return (EINVAL);
#ifdef INTR_SOLO
@@ -1084,11 +1102,14 @@ intr_irq_describe(u_int irq, void *cookie, const char *descr)
#ifdef SMP
int
-intr_irq_bind(u_int irq, int cpu)
+intr_bind_irq(device_t dev, struct resource *res, int cpu)
{
struct intr_irqsrc *isrc;
- isrc = isrc_lookup(irq);
+ KASSERT(rman_get_start(res) == rman_get_end(res),
+ ("%s: more interrupts in resource", __func__));
+
+ isrc = intr_ddata_lookup(rman_get_start(res), NULL);
if (isrc == NULL || isrc->isrc_handlers == 0)
return (EINVAL);
#ifdef INTR_SOLO
@@ -1135,7 +1156,7 @@ intr_irq_shuffle(void *arg __unused)
for (i = 0; i < NIRQ; i++) {
isrc = irq_sources[i];
if (isrc == NULL || isrc->isrc_handlers == 0 ||
- isrc->isrc_flags & INTR_ISRCF_PERCPU)
+ isrc->isrc_flags & INTR_ISRCF_PPI)
continue;
if (isrc->isrc_event != NULL &&
@@ -1151,7 +1172,7 @@ intr_irq_shuffle(void *arg __unused)
* for bound ISRC. The best thing we can do is to clear
* isrc_cpu so inconsistency with ie_cpu will be detectable.
*/
- if (PIC_BIND(isrc->isrc_dev, isrc) != 0)
+ if (PIC_BIND_INTR(isrc->isrc_dev, isrc) != 0)
CPU_ZERO(&isrc->isrc_cpu);
}
mtx_unlock(&isrc_table_lock);
@@ -1196,6 +1217,7 @@ intr_pic_init_secondary(void)
DB_SHOW_COMMAND(irqs, db_show_irqs)
{
u_int i, irqsum;
+ u_long num;
struct intr_irqsrc *isrc;
for (irqsum = 0, i = 0; i < NIRQ; i++) {
@@ -1203,11 +1225,11 @@ DB_SHOW_COMMAND(irqs, db_show_irqs)
if (isrc == NULL)
continue;
+ num = isrc->isrc_count != NULL ? isrc->isrc_count[0] : 0;
db_printf("irq%-3u <%s>: cpu %02lx%s cnt %lu\n", i,
isrc->isrc_name, isrc->isrc_cpu.__bits[0],
- isrc->isrc_flags & INTR_ISRCF_BOUND ? " (bound)" : "",
- isrc->isrc_count[0]);
- irqsum += isrc->isrc_count[0];
+ isrc->isrc_flags & INTR_ISRCF_BOUND ? " (bound)" : "", num);
+ irqsum += num;
}
db_printf("irq total %u\n", irqsum);
}
diff --git a/sys/kern/subr_rman.c b/sys/kern/subr_rman.c
index 41f1f34..9bbec64 100644
--- a/sys/kern/subr_rman.c
+++ b/sys/kern/subr_rman.c
@@ -159,7 +159,7 @@ rman_manage_region(struct rman *rm, rman_res_t start, rman_res_t end)
struct resource_i *r, *s, *t;
int rv = 0;
- DPRINTF(("rman_manage_region: <%s> request: start %#lx, end %#lx\n",
+ DPRINTF(("rman_manage_region: <%s> request: start %#jx, end %#jx\n",
rm->rm_descr, start, end));
if (start < rm->rm_start || end > rm->rm_end)
return EINVAL;
@@ -174,7 +174,7 @@ rman_manage_region(struct rman *rm, rman_res_t start, rman_res_t end)
/* Skip entries before us. */
TAILQ_FOREACH(s, &rm->rm_list, r_link) {
- if (s->r_end == ULONG_MAX)
+ if (s->r_end == ~0)
break;
if (s->r_end + 1 >= r->r_start)
break;
@@ -444,8 +444,8 @@ rman_reserve_resource_bound(struct rman *rm, rman_res_t start, rman_res_t end,
rv = NULL;
- DPRINTF(("rman_reserve_resource_bound: <%s> request: [%#lx, %#lx], "
- "length %#lx, flags %u, device %s\n", rm->rm_descr, start, end,
+ DPRINTF(("rman_reserve_resource_bound: <%s> request: [%#jx, %#jx], "
+ "length %#jx, flags %x, device %s\n", rm->rm_descr, start, end,
count, flags,
dev == NULL ? "<null>" : device_get_nameunit(dev)));
KASSERT((flags & RF_FIRSTSHARE) == 0,
@@ -454,19 +454,29 @@ rman_reserve_resource_bound(struct rman *rm, rman_res_t start, rman_res_t end,
mtx_lock(rm->rm_mtx);
+ r = TAILQ_FIRST(&rm->rm_list);
+ if (r == NULL) {
+ DPRINTF(("NULL list head\n"));
+ } else {
+ DPRINTF(("rman_reserve_resource_bound: trying %#jx <%#jx,%#jx>\n",
+ r->r_end, start, count-1));
+ }
for (r = TAILQ_FIRST(&rm->rm_list);
r && r->r_end < start + count - 1;
- r = TAILQ_NEXT(r, r_link))
+ r = TAILQ_NEXT(r, r_link)) {
;
+ DPRINTF(("rman_reserve_resource_bound: tried %#jx <%#jx,%#jx>\n",
+ r->r_end, start, count-1));
+ }
if (r == NULL) {
DPRINTF(("could not find a region\n"));
goto out;
}
- amask = (1ul << RF_ALIGNMENT(flags)) - 1;
- KASSERT(start <= ULONG_MAX - amask,
- ("start (%#lx) + amask (%#lx) would wrap around", start, amask));
+ amask = (1ull << RF_ALIGNMENT(flags)) - 1;
+ KASSERT(start <= RM_MAX_END - amask,
+ ("start (%#jx) + amask (%#jx) would wrap around", start, amask));
/* If bound is 0, bmask will also be 0 */
bmask = ~(bound - 1);
@@ -474,18 +484,18 @@ rman_reserve_resource_bound(struct rman *rm, rman_res_t start, rman_res_t end,
* First try to find an acceptable totally-unshared region.
*/
for (s = r; s; s = TAILQ_NEXT(s, r_link)) {
- DPRINTF(("considering [%#lx, %#lx]\n", s->r_start, s->r_end));
+ DPRINTF(("considering [%#jx, %#jx]\n", s->r_start, s->r_end));
/*
* The resource list is sorted, so there is no point in
* searching further once r_start is too large.
*/
if (s->r_start > end - (count - 1)) {
- DPRINTF(("s->r_start (%#lx) + count - 1> end (%#lx)\n",
+ DPRINTF(("s->r_start (%#jx) + count - 1> end (%#jx)\n",
s->r_start, end));
break;
}
- if (s->r_start > ULONG_MAX - amask) {
- DPRINTF(("s->r_start (%#lx) + amask (%#lx) too large\n",
+ if (s->r_start > RM_MAX_END - amask) {
+ DPRINTF(("s->r_start (%#jx) + amask (%#jx) too large\n",
s->r_start, amask));
break;
}
@@ -493,7 +503,7 @@ rman_reserve_resource_bound(struct rman *rm, rman_res_t start, rman_res_t end,
DPRINTF(("region is allocated\n"));
continue;
}
- rstart = ulmax(s->r_start, start);
+ rstart = ummax(s->r_start, start);
/*
* Try to find a region by adjusting to boundary and alignment
* until both conditions are satisfied. This is not an optimal
@@ -505,16 +515,16 @@ rman_reserve_resource_bound(struct rman *rm, rman_res_t start, rman_res_t end,
rstart += bound - (rstart & ~bmask);
} while ((rstart & amask) != 0 && rstart < end &&
rstart < s->r_end);
- rend = ulmin(s->r_end, ulmax(rstart + count - 1, end));
+ rend = ummin(s->r_end, ummax(rstart + count - 1, end));
if (rstart > rend) {
DPRINTF(("adjusted start exceeds end\n"));
continue;
}
- DPRINTF(("truncated region: [%#lx, %#lx]; size %#lx (requested %#lx)\n",
+ DPRINTF(("truncated region: [%#jx, %#jx]; size %#jx (requested %#jx)\n",
rstart, rend, (rend - rstart + 1), count));
if ((rend - rstart + 1) >= count) {
- DPRINTF(("candidate region: [%#lx, %#lx], size %#lx\n",
+ DPRINTF(("candidate region: [%#jx, %#jx], size %#jx\n",
rstart, rend, (rend - rstart + 1)));
if ((s->r_end - s->r_start + 1) == count) {
DPRINTF(("candidate region is entire chunk\n"));
@@ -545,7 +555,7 @@ rman_reserve_resource_bound(struct rman *rm, rman_res_t start, rman_res_t end,
if (s->r_start < rv->r_start && s->r_end > rv->r_end) {
DPRINTF(("splitting region in three parts: "
- "[%#lx, %#lx]; [%#lx, %#lx]; [%#lx, %#lx]\n",
+ "[%#jx, %#jx]; [%#jx, %#jx]; [%#jx, %#jx]\n",
s->r_start, rv->r_start - 1,
rv->r_start, rv->r_end,
rv->r_end + 1, s->r_end));
@@ -1032,8 +1042,8 @@ dump_rman_header(struct rman *rm)
if (db_pager_quit)
return;
- db_printf("rman %p: %s (0x%lx-0x%lx full range)\n",
- rm, rm->rm_descr, rm->rm_start, rm->rm_end);
+ db_printf("rman %p: %s (0x%jx-0x%jx full range)\n",
+ rm, rm->rm_descr, (rman_res_t)rm->rm_start, (rman_res_t)rm->rm_end);
}
static void
@@ -1051,7 +1061,7 @@ dump_rman(struct rman *rm)
devname = "nomatch";
} else
devname = NULL;
- db_printf(" 0x%lx-0x%lx (RID=%d) ",
+ db_printf(" 0x%jx-0x%jx (RID=%d) ",
r->r_start, r->r_end, r->r_rid);
if (devname != NULL)
db_printf("(%s)\n", devname);
diff --git a/sys/kern/subr_sleepqueue.c b/sys/kern/subr_sleepqueue.c
index 12908f6..ef06c48 100644
--- a/sys/kern/subr_sleepqueue.c
+++ b/sys/kern/subr_sleepqueue.c
@@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
#include "opt_sleepqueue_profiling.h"
#include "opt_ddb.h"
#include "opt_sched.h"
+#include "opt_stack.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -75,6 +76,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sdt.h>
#include <sys/signalvar.h>
#include <sys/sleepqueue.h>
+#include <sys/stack.h>
#include <sys/sysctl.h>
#include <vm/uma.h>
@@ -83,6 +85,7 @@ __FBSDID("$FreeBSD$");
#include <ddb/ddb.h>
#endif
+
/*
* Constants for the hash table of sleep queue chains.
* SC_TABLESIZE must be a power of two for SC_MASK to work properly.
@@ -382,6 +385,8 @@ sleepq_set_timeout_sbt(void *wchan, sbintime_t sbt, sbintime_t pr,
MPASS(TD_ON_SLEEPQ(td));
MPASS(td->td_sleepqueue == NULL);
MPASS(wchan != NULL);
+ if (cold)
+ panic("timed sleep before timers are working");
callout_reset_sbt_on(&td->td_slpcallout, sbt, pr,
sleepq_timeout, td, PCPU_GET(cpuid), flags | C_DIRECT_EXEC);
}
@@ -1034,6 +1039,122 @@ sleepq_abort(struct thread *td, int intrval)
return (sleepq_resume_thread(sq, td, 0));
}
+/*
+ * Prints the stacks of all threads presently sleeping on wchan/queue to
+ * the sbuf sb. Sets count_stacks_printed to the number of stacks actually
+ * printed. Typically, this will equal the number of threads sleeping on the
+ * queue, but may be less if sb overflowed before all stacks were printed.
+ */
+#ifdef STACK
+int
+sleepq_sbuf_print_stacks(struct sbuf *sb, void *wchan, int queue,
+ int *count_stacks_printed)
+{
+ struct thread *td, *td_next;
+ struct sleepqueue *sq;
+ struct stack **st;
+ struct sbuf **td_infos;
+ int i, stack_idx, error, stacks_to_allocate;
+ bool finished, partial_print;
+
+ error = 0;
+ finished = false;
+ partial_print = false;
+
+ KASSERT(wchan != NULL, ("%s: invalid NULL wait channel", __func__));
+ MPASS((queue >= 0) && (queue < NR_SLEEPQS));
+
+ stacks_to_allocate = 10;
+ for (i = 0; i < 3 && !finished ; i++) {
+ /* We cannot malloc while holding the queue's spinlock, so
+ * we do our mallocs now, and hope it is enough. If it
+ * isn't, we will free these, drop the lock, malloc more,
+ * and try again, up to a point. After that point we will
+ * give up and report ENOMEM. We also cannot write to sb
+ * during this time since the client may have set the
+ * SBUF_AUTOEXTEND flag on their sbuf, which could cause a
+ * malloc as we print to it. So we defer actually printing
+ * to sb until after we drop the spinlock.
+ */
+
+ /* Where we will store the stacks. */
+ st = malloc(sizeof(struct stack *) * stacks_to_allocate,
+ M_TEMP, M_WAITOK);
+ for (stack_idx = 0; stack_idx < stacks_to_allocate;
+ stack_idx++)
+ st[stack_idx] = stack_create();
+
+ /* Where we will store the td name, tid, etc. */
+ td_infos = malloc(sizeof(struct sbuf *) * stacks_to_allocate,
+ M_TEMP, M_WAITOK);
+ for (stack_idx = 0; stack_idx < stacks_to_allocate;
+ stack_idx++)
+ td_infos[stack_idx] = sbuf_new(NULL, NULL,
+ MAXCOMLEN + sizeof(struct thread *) * 2 + 40,
+ SBUF_FIXEDLEN);
+
+ sleepq_lock(wchan);
+ sq = sleepq_lookup(wchan);
+ if (sq == NULL) {
+ /* This sleepq does not exist; exit and return ENOENT. */
+ error = ENOENT;
+ finished = true;
+ sleepq_release(wchan);
+ goto loop_end;
+ }
+
+ stack_idx = 0;
+ /* Save thread info */
+ TAILQ_FOREACH_SAFE(td, &sq->sq_blocked[queue], td_slpq,
+ td_next) {
+ if (stack_idx >= stacks_to_allocate)
+ goto loop_end;
+
+ /* Note the td_lock is equal to the sleepq_lock here. */
+ stack_save_td(st[stack_idx], td);
+
+ sbuf_printf(td_infos[stack_idx], "%d: %s %p",
+ td->td_tid, td->td_name, td);
+
+ ++stack_idx;
+ }
+
+ finished = true;
+ sleepq_release(wchan);
+
+ /* Print the stacks */
+ for (i = 0; i < stack_idx; i++) {
+ sbuf_finish(td_infos[i]);
+ sbuf_printf(sb, "--- thread %s: ---\n", sbuf_data(td_infos[i]));
+ stack_sbuf_print(sb, st[i]);
+ sbuf_printf(sb, "\n");
+
+ error = sbuf_error(sb);
+ if (error == 0)
+ *count_stacks_printed = stack_idx;
+ }
+
+loop_end:
+ if (!finished)
+ sleepq_release(wchan);
+ for (stack_idx = 0; stack_idx < stacks_to_allocate;
+ stack_idx++)
+ stack_destroy(st[stack_idx]);
+ for (stack_idx = 0; stack_idx < stacks_to_allocate;
+ stack_idx++)
+ sbuf_delete(td_infos[stack_idx]);
+ free(st, M_TEMP);
+ free(td_infos, M_TEMP);
+ stacks_to_allocate *= 10;
+ }
+
+ if (!finished && error == 0)
+ error = ENOMEM;
+
+ return (error);
+}
+#endif
+
#ifdef SLEEPQUEUE_PROFILING
#define SLEEPQ_PROF_LOCATIONS 1024
#define SLEEPQ_SBUFSIZE 512
diff --git a/sys/kern/subr_smp.c b/sys/kern/subr_smp.c
index 82349f8..9848136 100644
--- a/sys/kern/subr_smp.c
+++ b/sys/kern/subr_smp.c
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/bus.h>
#include <sys/lock.h>
+#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/pcpu.h>
#include <sys/sched.h>
@@ -51,6 +52,10 @@ __FBSDID("$FreeBSD$");
#include "opt_sched.h"
#ifdef SMP
+MALLOC_DEFINE(M_TOPO, "toponodes", "SMP topology data");
+#endif
+
+#ifdef SMP
volatile cpuset_t stopped_cpus;
volatile cpuset_t started_cpus;
volatile cpuset_t suspended_cpus;
@@ -556,7 +561,7 @@ smp_rendezvous(void (* setup_func)(void *),
smp_rendezvous_cpus(all_cpus, setup_func, action_func, teardown_func, arg);
}
-static struct cpu_group group[MAXCPU];
+static struct cpu_group group[MAXCPU * MAX_CACHE_LEVELS + 1];
struct cpu_group *
smp_topo(void)
@@ -616,6 +621,17 @@ smp_topo(void)
}
struct cpu_group *
+smp_topo_alloc(u_int count)
+{
+ static u_int index;
+ u_int curr;
+
+ curr = index;
+ index += count;
+ return (&group[curr]);
+}
+
+struct cpu_group *
smp_topo_none(void)
{
struct cpu_group *top;
@@ -861,3 +877,233 @@ sysctl_kern_smp_active(SYSCTL_HANDLER_ARGS)
return (error);
}
+
+#ifdef SMP
+void
+topo_init_node(struct topo_node *node)
+{
+
+ bzero(node, sizeof(*node));
+ TAILQ_INIT(&node->children);
+}
+
+void
+topo_init_root(struct topo_node *root)
+{
+
+ topo_init_node(root);
+ root->type = TOPO_TYPE_SYSTEM;
+}
+
+struct topo_node *
+topo_add_node_by_hwid(struct topo_node *parent, int hwid,
+ topo_node_type type, uintptr_t subtype)
+{
+ struct topo_node *node;
+
+ TAILQ_FOREACH_REVERSE(node, &parent->children,
+ topo_children, siblings) {
+ if (node->hwid == hwid
+ && node->type == type && node->subtype == subtype) {
+ return (node);
+ }
+ }
+
+ node = malloc(sizeof(*node), M_TOPO, M_WAITOK);
+ topo_init_node(node);
+ node->parent = parent;
+ node->hwid = hwid;
+ node->type = type;
+ node->subtype = subtype;
+ TAILQ_INSERT_TAIL(&parent->children, node, siblings);
+ parent->nchildren++;
+
+ return (node);
+}
+
+struct topo_node *
+topo_find_node_by_hwid(struct topo_node *parent, int hwid,
+ topo_node_type type, uintptr_t subtype)
+{
+
+ struct topo_node *node;
+
+ TAILQ_FOREACH(node, &parent->children, siblings) {
+ if (node->hwid == hwid
+ && node->type == type && node->subtype == subtype) {
+ return (node);
+ }
+ }
+
+ return (NULL);
+}
+
+void
+topo_promote_child(struct topo_node *child)
+{
+ struct topo_node *next;
+ struct topo_node *node;
+ struct topo_node *parent;
+
+ parent = child->parent;
+ next = TAILQ_NEXT(child, siblings);
+ TAILQ_REMOVE(&parent->children, child, siblings);
+ TAILQ_INSERT_HEAD(&parent->children, child, siblings);
+
+ while (next != NULL) {
+ node = next;
+ next = TAILQ_NEXT(node, siblings);
+ TAILQ_REMOVE(&parent->children, node, siblings);
+ TAILQ_INSERT_AFTER(&parent->children, child, node, siblings);
+ child = node;
+ }
+}
+
+struct topo_node *
+topo_next_node(struct topo_node *top, struct topo_node *node)
+{
+ struct topo_node *next;
+
+ if ((next = TAILQ_FIRST(&node->children)) != NULL)
+ return (next);
+
+ if ((next = TAILQ_NEXT(node, siblings)) != NULL)
+ return (next);
+
+ while ((node = node->parent) != top)
+ if ((next = TAILQ_NEXT(node, siblings)) != NULL)
+ return (next);
+
+ return (NULL);
+}
+
+struct topo_node *
+topo_next_nonchild_node(struct topo_node *top, struct topo_node *node)
+{
+ struct topo_node *next;
+
+ if ((next = TAILQ_NEXT(node, siblings)) != NULL)
+ return (next);
+
+ while ((node = node->parent) != top)
+ if ((next = TAILQ_NEXT(node, siblings)) != NULL)
+ return (next);
+
+ return (NULL);
+}
+
+void
+topo_set_pu_id(struct topo_node *node, cpuid_t id)
+{
+
+ KASSERT(node->type == TOPO_TYPE_PU,
+ ("topo_set_pu_id: wrong node type: %u", node->type));
+ KASSERT(CPU_EMPTY(&node->cpuset) && node->cpu_count == 0,
+ ("topo_set_pu_id: cpuset already not empty"));
+ node->id = id;
+ CPU_SET(id, &node->cpuset);
+ node->cpu_count = 1;
+ node->subtype = 1;
+
+ while ((node = node->parent) != NULL) {
+ if (CPU_ISSET(id, &node->cpuset))
+ break;
+ CPU_SET(id, &node->cpuset);
+ node->cpu_count++;
+ }
+}
+
+int
+topo_analyze(struct topo_node *topo_root, int all,
+ int *pkg_count, int *cores_per_pkg, int *thrs_per_core)
+{
+ struct topo_node *pkg_node;
+ struct topo_node *core_node;
+ struct topo_node *pu_node;
+ int thrs_per_pkg;
+ int cpp_counter;
+ int tpc_counter;
+ int tpp_counter;
+
+ *pkg_count = 0;
+ *cores_per_pkg = -1;
+ *thrs_per_core = -1;
+ thrs_per_pkg = -1;
+ pkg_node = topo_root;
+ while (pkg_node != NULL) {
+ if (pkg_node->type != TOPO_TYPE_PKG) {
+ pkg_node = topo_next_node(topo_root, pkg_node);
+ continue;
+ }
+ if (!all && CPU_EMPTY(&pkg_node->cpuset)) {
+ pkg_node = topo_next_nonchild_node(topo_root, pkg_node);
+ continue;
+ }
+
+ (*pkg_count)++;
+
+ cpp_counter = 0;
+ tpp_counter = 0;
+ core_node = pkg_node;
+ while (core_node != NULL) {
+ if (core_node->type == TOPO_TYPE_CORE) {
+ if (!all && CPU_EMPTY(&core_node->cpuset)) {
+ core_node =
+ topo_next_nonchild_node(pkg_node,
+ core_node);
+ continue;
+ }
+
+ cpp_counter++;
+
+ tpc_counter = 0;
+ pu_node = core_node;
+ while (pu_node != NULL) {
+ if (pu_node->type == TOPO_TYPE_PU &&
+ (all || !CPU_EMPTY(&pu_node->cpuset)))
+ tpc_counter++;
+ pu_node = topo_next_node(core_node,
+ pu_node);
+ }
+
+ if (*thrs_per_core == -1)
+ *thrs_per_core = tpc_counter;
+ else if (*thrs_per_core != tpc_counter)
+ return (0);
+
+ core_node = topo_next_nonchild_node(pkg_node,
+ core_node);
+ } else {
+ /* PU node directly under PKG. */
+ if (core_node->type == TOPO_TYPE_PU &&
+ (all || !CPU_EMPTY(&core_node->cpuset)))
+ tpp_counter++;
+ core_node = topo_next_node(pkg_node,
+ core_node);
+ }
+ }
+
+ if (*cores_per_pkg == -1)
+ *cores_per_pkg = cpp_counter;
+ else if (*cores_per_pkg != cpp_counter)
+ return (0);
+ if (thrs_per_pkg == -1)
+ thrs_per_pkg = tpp_counter;
+ else if (thrs_per_pkg != tpp_counter)
+ return (0);
+
+ pkg_node = topo_next_nonchild_node(topo_root, pkg_node);
+ }
+
+ KASSERT(*pkg_count > 0,
+ ("bug in topology or analysis"));
+ if (*cores_per_pkg == 0) {
+ KASSERT(*thrs_per_core == -1 && thrs_per_pkg > 0,
+ ("bug in topology or analysis"));
+ *thrs_per_core = thrs_per_pkg;
+ }
+
+ return (1);
+}
+#endif /* SMP */
+
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c
index fe79f52..75fb66e 100644
--- a/sys/kern/sys_generic.c
+++ b/sys/kern/sys_generic.c
@@ -89,12 +89,14 @@ __FBSDID("$FreeBSD$");
#define SYS_IOCTL_SMALL_SIZE 128 /* bytes */
#define SYS_IOCTL_SMALL_ALIGN 8 /* bytes */
-int iosize_max_clamp = 0;
+#ifdef __LP64__
+static int iosize_max_clamp = 0;
SYSCTL_INT(_debug, OID_AUTO, iosize_max_clamp, CTLFLAG_RW,
&iosize_max_clamp, 0, "Clamp max i/o size to INT_MAX");
-int devfs_iosize_max_clamp = 1;
+static int devfs_iosize_max_clamp = 1;
SYSCTL_INT(_debug, OID_AUTO, devfs_iosize_max_clamp, CTLFLAG_RW,
&devfs_iosize_max_clamp, 0, "Clamp max i/o size to INT_MAX for devices");
+#endif
/*
* Assert that the return value of read(2) and write(2) syscalls fits
@@ -159,6 +161,24 @@ struct selfd {
static uma_zone_t selfd_zone;
static struct mtx_pool *mtxpool_select;
+#ifdef __LP64__
+size_t
+devfs_iosize_max(void)
+{
+
+ return (devfs_iosize_max_clamp || SV_CURPROC_FLAG(SV_ILP32) ?
+ INT_MAX : SSIZE_MAX);
+}
+
+size_t
+iosize_max(void)
+{
+
+ return (iosize_max_clamp || SV_CURPROC_FLAG(SV_ILP32) ?
+ INT_MAX : SSIZE_MAX);
+}
+#endif
+
#ifndef _SYS_SYSPROTO_H_
struct read_args {
int fd;
diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c
index 44ddd81..3575028 100644
--- a/sys/kern/syscalls.c
+++ b/sys/kern/syscalls.c
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/kern/syscalls.master 296572 2016-03-09 19:05:11Z jhb
+ * created from FreeBSD: head/sys/kern/syscalls.master 297167 2016-03-21 21:37:33Z jhb
*/
const char *syscallnames[] = {
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index f08f5e3..5675425 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -554,7 +554,7 @@
312 AUE_SETRESGID STD { int setresgid(gid_t rgid, gid_t egid, \
gid_t sgid); }
313 AUE_NULL OBSOL signanosleep
-314 AUE_NULL STD { int aio_return(struct aiocb *aiocbp); }
+314 AUE_NULL STD { ssize_t aio_return(struct aiocb *aiocbp); }
315 AUE_NULL STD { int aio_suspend( \
struct aiocb * const * aiocbp, int nent, \
const struct timespec *timeout); }
@@ -643,7 +643,7 @@
358 AUE_EXTATTR_DELETE_FILE STD { int extattr_delete_file(const char *path, \
int attrnamespace, \
const char *attrname); }
-359 AUE_NULL STD { int aio_waitcomplete( \
+359 AUE_NULL STD { ssize_t aio_waitcomplete( \
struct aiocb **aiocbp, \
struct timespec *timeout); }
360 AUE_GETRESUID STD { int getresuid(uid_t *ruid, uid_t *euid, \
diff --git a/sys/kern/systrace_args.c b/sys/kern/systrace_args.c
index 6fd03f1..c2ea2b4 100644
--- a/sys/kern/systrace_args.c
+++ b/sys/kern/systrace_args.c
@@ -9796,7 +9796,7 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
/* aio_return */
case 314:
if (ndx == 0 || ndx == 1)
- p = "int";
+ p = "ssize_t";
break;
/* aio_suspend */
case 315:
@@ -9972,7 +9972,7 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
/* aio_waitcomplete */
case 359:
if (ndx == 0 || ndx == 1)
- p = "int";
+ p = "ssize_t";
break;
/* getresuid */
case 360:
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c
index 23bfbff..62dfda6 100644
--- a/sys/kern/uipc_mbuf.c
+++ b/sys/kern/uipc_mbuf.c
@@ -47,6 +47,49 @@ __FBSDID("$FreeBSD$");
#include <sys/domain.h>
#include <sys/protosw.h>
#include <sys/uio.h>
+#include <sys/sdt.h>
+
+SDT_PROBE_DEFINE5_XLATE(sdt, , , m__init,
+ "struct mbuf *", "mbufinfo_t *",
+ "uint32_t", "uint32_t",
+ "uint16_t", "uint16_t",
+ "uint32_t", "uint32_t",
+ "uint32_t", "uint32_t");
+
+SDT_PROBE_DEFINE3_XLATE(sdt, , , m__gethdr,
+ "uint32_t", "uint32_t",
+ "uint16_t", "uint16_t",
+ "struct mbuf *", "mbufinfo_t *");
+
+SDT_PROBE_DEFINE3_XLATE(sdt, , , m__get,
+ "uint32_t", "uint32_t",
+ "uint16_t", "uint16_t",
+ "struct mbuf *", "mbufinfo_t *");
+
+SDT_PROBE_DEFINE4_XLATE(sdt, , , m__getcl,
+ "uint32_t", "uint32_t",
+ "uint16_t", "uint16_t",
+ "uint32_t", "uint32_t",
+ "struct mbuf *", "mbufinfo_t *");
+
+SDT_PROBE_DEFINE3_XLATE(sdt, , , m__clget,
+ "struct mbuf *", "mbufinfo_t *",
+ "uint32_t", "uint32_t",
+ "uint32_t", "uint32_t");
+
+SDT_PROBE_DEFINE4_XLATE(sdt, , , m__cljget,
+ "struct mbuf *", "mbufinfo_t *",
+ "uint32_t", "uint32_t",
+ "uint32_t", "uint32_t",
+ "void*", "void*");
+
+SDT_PROBE_DEFINE(sdt, , , m__cljset);
+
+SDT_PROBE_DEFINE1_XLATE(sdt, , , m__free,
+ "struct mbuf *", "mbufinfo_t *");
+
+SDT_PROBE_DEFINE1_XLATE(sdt, , , m__freem,
+ "struct mbuf *", "mbufinfo_t *");
#include <security/mac/mac_framework.h>
@@ -1627,7 +1670,7 @@ m_unshare(struct mbuf *m0, int how)
* don't know how to break up the non-contiguous memory when
* doing DMA.
*/
- n = m_getcl(how, m->m_type, m->m_flags);
+ n = m_getcl(how, m->m_type, m->m_flags & M_COPYFLAGS);
if (n == NULL) {
m_freem(m0);
return (NULL);
@@ -1657,7 +1700,7 @@ m_unshare(struct mbuf *m0, int how)
break;
off += cc;
- n = m_getcl(how, m->m_type, m->m_flags);
+ n = m_getcl(how, m->m_type, m->m_flags & M_COPYFLAGS);
if (n == NULL) {
m_freem(mfirst);
m_freem(m0);
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index 35d17b1..d873217 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -358,7 +358,7 @@ sysctl_maxsockets(SYSCTL_HANDLER_ARGS)
}
SYSCTL_PROC(_kern_ipc, OID_AUTO, maxsockets, CTLTYPE_INT|CTLFLAG_RW,
&maxsockets, 0, sysctl_maxsockets, "IU",
- "Maximum number of sockets avaliable");
+ "Maximum number of sockets available");
/*
* Socket operation routines. These routines are called by the routines in
diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c
index 27fa239..20df141 100644
--- a/sys/kern/vfs_aio.c
+++ b/sys/kern/vfs_aio.c
@@ -743,7 +743,7 @@ aio_process_rw(struct kaiocb *job)
struct file *fp;
struct uio auio;
struct iovec aiov;
- int cnt;
+ ssize_t cnt;
int error;
int oublock_st, oublock_end;
int inblock_st, inblock_end;
@@ -1173,7 +1173,7 @@ aio_qphysio(struct proc *p, struct kaiocb *job)
struct cdevsw *csw;
struct cdev *dev;
struct kaioinfo *ki;
- int error, ref, unmap, poff;
+ int error, ref, poff;
vm_prot_t prot;
cb = &job->uaiocb;
@@ -1206,12 +1206,13 @@ aio_qphysio(struct proc *p, struct kaiocb *job)
ki = p->p_aioinfo;
poff = (vm_offset_t)cb->aio_buf & PAGE_MASK;
- unmap = ((dev->si_flags & SI_UNMAPPED) && unmapped_buf_allowed);
- if (unmap) {
+ if ((dev->si_flags & SI_UNMAPPED) && unmapped_buf_allowed) {
if (cb->aio_nbytes > MAXPHYS) {
error = -1;
goto unref;
}
+
+ pbuf = NULL;
} else {
if (cb->aio_nbytes > MAXPHYS - poff) {
error = -1;
@@ -1221,17 +1222,14 @@ aio_qphysio(struct proc *p, struct kaiocb *job)
error = -1;
goto unref;
}
- }
- job->bp = bp = g_alloc_bio();
- if (!unmap) {
+
job->pbuf = pbuf = (struct buf *)getpbuf(NULL);
BUF_KERNPROC(pbuf);
- }
-
- AIO_LOCK(ki);
- if (!unmap)
+ AIO_LOCK(ki);
ki->kaio_buffer_count++;
- AIO_UNLOCK(ki);
+ AIO_UNLOCK(ki);
+ }
+ job->bp = bp = g_alloc_bio();
bp->bio_length = cb->aio_nbytes;
bp->bio_bcount = cb->aio_nbytes;
@@ -1245,17 +1243,18 @@ aio_qphysio(struct proc *p, struct kaiocb *job)
prot = VM_PROT_READ;
if (cb->aio_lio_opcode == LIO_READ)
prot |= VM_PROT_WRITE; /* Less backwards than it looks */
- if ((job->npages = vm_fault_quick_hold_pages(
- &curproc->p_vmspace->vm_map,
+ job->npages = vm_fault_quick_hold_pages(&curproc->p_vmspace->vm_map,
(vm_offset_t)bp->bio_data, bp->bio_length, prot, job->pages,
- sizeof(job->pages)/sizeof(job->pages[0]))) < 0) {
+ nitems(job->pages));
+ if (job->npages < 0) {
error = EFAULT;
goto doerror;
}
- if (!unmap) {
+ if (pbuf != NULL) {
pmap_qenter((vm_offset_t)pbuf->b_data,
job->pages, job->npages);
bp->bio_data = pbuf->b_data + poff;
+ atomic_add_int(&num_buf_aio, 1);
} else {
bp->bio_ma = job->pages;
bp->bio_ma_n = job->npages;
@@ -1264,20 +1263,16 @@ aio_qphysio(struct proc *p, struct kaiocb *job)
bp->bio_flags |= BIO_UNMAPPED;
}
- if (!unmap)
- atomic_add_int(&num_buf_aio, 1);
-
/* Perform transfer. */
csw->d_strategy(bp);
dev_relthread(dev, ref);
return (0);
doerror:
- AIO_LOCK(ki);
- if (!unmap)
+ if (pbuf != NULL) {
+ AIO_LOCK(ki);
ki->kaio_buffer_count--;
- AIO_UNLOCK(ki);
- if (pbuf) {
+ AIO_UNLOCK(ki);
relpbuf(pbuf, NULL);
job->pbuf = NULL;
}
@@ -1446,8 +1441,7 @@ aio_aqueue(struct thread *td, struct aiocb *ujob, struct aioliojob *lj,
return (error);
}
- /* XXX: aio_nbytes is later casted to signed types. */
- if (job->uaiocb.aio_nbytes > INT_MAX) {
+ if (job->uaiocb.aio_nbytes > IOSIZE_MAX) {
uma_zfree(aiocb_zone, job);
return (EINVAL);
}
@@ -1788,7 +1782,7 @@ kern_aio_return(struct thread *td, struct aiocb *ujob, struct aiocb_ops *ops)
struct proc *p = td->td_proc;
struct kaiocb *job;
struct kaioinfo *ki;
- int status, error;
+ long status, error;
ki = p->p_aioinfo;
if (ki == NULL)
@@ -2344,7 +2338,8 @@ kern_aio_waitcomplete(struct thread *td, struct aiocb **ujobp,
struct kaioinfo *ki;
struct kaiocb *job;
struct aiocb *ujob;
- int error, status, timo;
+ long error, status;
+ int timo;
ops->store_aiocb(ujobp, NULL);
diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c
index 9be0ece..9eb523c 100644
--- a/sys/kern/vfs_export.c
+++ b/sys/kern/vfs_export.c
@@ -256,10 +256,10 @@ vfs_free_addrlist_af(struct radix_node_head **prnh)
rnh = *prnh;
RADIX_NODE_HEAD_LOCK(rnh);
- (*rnh->rnh_walktree)(&rnh->rh, vfs_free_netcred, &rnh->rh);
+ (*rnh->rnh_walktree)(&rnh->rh, vfs_free_netcred, rnh);
RADIX_NODE_HEAD_UNLOCK(rnh);
RADIX_NODE_HEAD_DESTROY(rnh);
- free(rnh, M_RTABLE);
+ rn_detachhead((void **)prnh);
prnh = NULL;
}
diff --git a/sys/kern/vfs_mountroot.c b/sys/kern/vfs_mountroot.c
index cf24253..a33e376 100644
--- a/sys/kern/vfs_mountroot.c
+++ b/sys/kern/vfs_mountroot.c
@@ -89,6 +89,7 @@ __FBSDID("$FreeBSD$");
static int parse_mount(char **);
static struct mntarg *parse_mountroot_options(struct mntarg *, const char *);
static int sysctl_vfs_root_mount_hold(SYSCTL_HANDLER_ARGS);
+static void vfs_mountroot_wait(void);
static int vfs_mountroot_wait_if_neccessary(const char *fs, const char *dev);
/*
@@ -488,6 +489,8 @@ parse_dir_ask(char **conf)
char *mnt;
int error;
+ vfs_mountroot_wait();
+
printf("\nLoader variables:\n");
parse_dir_ask_printenv("vfs.root.mountfrom");
parse_dir_ask_printenv("vfs.root.mountfrom.options");
diff --git a/sys/mips/atheros/apb.c b/sys/mips/atheros/apb.c
index 8d230a7..abae9c2 100644
--- a/sys/mips/atheros/apb.c
+++ b/sys/mips/atheros/apb.c
@@ -178,7 +178,7 @@ apb_alloc_resource(device_t bus, device_t child, int type, int *rid,
passthrough = (device_get_parent(child) != bus);
rle = NULL;
- dprintf("%s: entry (%p, %p, %d, %d, %p, %p, %ld, %d)\n",
+ dprintf("%s: entry (%p, %p, %d, %d, %p, %p, %jd, %d)\n",
__func__, bus, child, type, *rid, (void *)(intptr_t)start,
(void *)(intptr_t)end, count, flags);
@@ -491,8 +491,8 @@ apb_print_all_resources(device_t dev)
if (STAILQ_FIRST(rl))
retval += printf(" at");
- retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
- retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+ retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
+ retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
return (retval);
}
diff --git a/sys/mips/beri/beri_simplebus.c b/sys/mips/beri/beri_simplebus.c
index dd219a5..79302f6 100644
--- a/sys/mips/beri/beri_simplebus.c
+++ b/sys/mips/beri/beri_simplebus.c
@@ -239,8 +239,8 @@ simplebus_print_child(device_t dev, device_t child)
rv = 0;
rv += bus_print_child_header(dev, child);
- rv += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
- rv += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+ rv += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
+ rv += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
if ((ip = simplebus_get_interrupt_parent(child)) != NULL)
rv += printf(" (%s)", device_get_nameunit(ip));
rv += bus_print_child_footer(dev, child);
diff --git a/sys/mips/mips/mips_pic.c b/sys/mips/mips/mips_pic.c
index 250f8cf..4e97c41 100644
--- a/sys/mips/mips/mips_pic.c
+++ b/sys/mips/mips/mips_pic.c
@@ -48,6 +48,8 @@ __FBSDID("$FreeBSD$");
#include <sys/mutex.h>
#include <sys/smp.h>
#include <sys/sched.h>
+#include <sys/pmc.h>
+#include <sys/pmckern.h>
#include <machine/bus.h>
#include <machine/hwfunc.h>
@@ -217,8 +219,11 @@ mips_pic_intr(void *arg)
KASSERT(i == 0, ("all interrupts handled"));
#ifdef HWPMC_HOOKS
- if (pmc_hook && (PCPU_GET(curthread)->td_pflags & TDP_CALLCHAIN))
+ if (pmc_hook && (PCPU_GET(curthread)->td_pflags & TDP_CALLCHAIN)) {
+ struct trapframe *tf = PCPU_GET(curthread)->td_intr_frame;
+
pmc_hook(PCPU_GET(curthread), PMC_FN_USER_CALLCHAIN, tf);
+ }
#endif
return (FILTER_HANDLED);
}
diff --git a/sys/mips/mips/nexus.c b/sys/mips/mips/nexus.c
index 617d842..89049f0 100644
--- a/sys/mips/mips/nexus.c
+++ b/sys/mips/mips/nexus.c
@@ -231,8 +231,8 @@ nexus_print_all_resources(device_t dev)
if (STAILQ_FIRST(rl))
retval += printf(" at");
- retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
- retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+ retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
+ retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
return (retval);
}
@@ -275,7 +275,7 @@ nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
struct rman *rm;
int isdefault, needactivate, passthrough;
- dprintf("%s: entry (%p, %p, %d, %p, %p, %p, %ld, %d)\n",
+ dprintf("%s: entry (%p, %p, %d, %p, %p, %p, %jd, %d)\n",
__func__, bus, child, type, rid, (void *)(intptr_t)start,
(void *)(intptr_t)end, count, flags);
dprintf("%s: requested rid is %d\n", __func__, *rid);
@@ -350,7 +350,7 @@ nexus_set_resource(device_t dev, device_t child, int type, int rid,
struct resource_list *rl = &ndev->nx_resources;
struct resource_list_entry *rle;
- dprintf("%s: entry (%p, %p, %d, %d, %p, %ld)\n",
+ dprintf("%s: entry (%p, %p, %d, %d, %p, %jd)\n",
__func__, dev, child, type, rid, (void *)(intptr_t)start, count);
rle = resource_list_add(rl, type, rid, start, start + count - 1,
diff --git a/sys/mips/nlm/xlp_pci.c b/sys/mips/nlm/xlp_pci.c
index fee23cd..863c6aa 100644
--- a/sys/mips/nlm/xlp_pci.c
+++ b/sys/mips/nlm/xlp_pci.c
@@ -433,7 +433,7 @@ mips_platform_pcib_setup_intr(device_t dev, device_t child,
if (error)
return error;
if (rman_get_start(irq) != rman_get_end(irq)) {
- device_printf(dev, "Interrupt allocation %lu != %lu\n",
+ device_printf(dev, "Interrupt allocation %ju != %ju\n",
rman_get_start(irq), rman_get_end(irq));
return (EINVAL);
}
diff --git a/sys/mips/nlm/xlp_simplebus.c b/sys/mips/nlm/xlp_simplebus.c
index 3ffb19a..413775b 100644
--- a/sys/mips/nlm/xlp_simplebus.c
+++ b/sys/mips/nlm/xlp_simplebus.c
@@ -209,7 +209,7 @@ xlp_simplebus_alloc_resource(device_t bus, device_t child, int type, int *rid,
if (j == sc->nranges && sc->nranges != 0) {
if (bootverbose)
device_printf(bus, "Could not map resource "
- "%#lx-%#lx\n", start, end);
+ "%#jx-%#jx\n", start, end);
return (NULL);
}
}
@@ -235,7 +235,7 @@ xlp_simplebus_alloc_resource(device_t bus, device_t child, int type, int *rid,
} else {
if (bootverbose)
device_printf(bus, "Invalid MEM range"
- "%#lx-%#lx\n", start, end);
+ "%#jx-%#jx\n", start, end);
return (NULL);
}
break;
diff --git a/sys/mips/rmi/iodi.c b/sys/mips/rmi/iodi.c
index da0405d..d1f74e1 100644
--- a/sys/mips/rmi/iodi.c
+++ b/sys/mips/rmi/iodi.c
@@ -134,17 +134,17 @@ iodi_alloc_resource(device_t bus, device_t child, int type, int *rid,
#ifdef DEBUG
switch (type) {
case SYS_RES_IRQ:
- device_printf(bus, "IRQ resource - for %s %lx-%lx\n",
+ device_printf(bus, "IRQ resource - for %s %jx-%jx\n",
device_get_nameunit(child), start, end);
break;
case SYS_RES_IOPORT:
- device_printf(bus, "IOPORT resource - for %s %lx-%lx\n",
+ device_printf(bus, "IOPORT resource - for %s %jx-%jx\n",
device_get_nameunit(child), start, end);
break;
case SYS_RES_MEMORY:
- device_printf(bus, "MEMORY resource - for %s %lx-%lx\n",
+ device_printf(bus, "MEMORY resource - for %s %jx-%jx\n",
device_get_nameunit(child), start, end);
break;
}
diff --git a/sys/mips/rmi/xlr_pci.c b/sys/mips/rmi/xlr_pci.c
index 194213b..53581a6 100644
--- a/sys/mips/rmi/xlr_pci.c
+++ b/sys/mips/rmi/xlr_pci.c
@@ -464,7 +464,7 @@ mips_platform_pci_setup_intr(device_t dev, device_t child,
if (error)
return error;
if (rman_get_start(irq) != rman_get_end(irq)) {
- device_printf(dev, "Interrupt allocation %lu != %lu\n",
+ device_printf(dev, "Interrupt allocation %ju != %ju\n",
rman_get_start(irq), rman_get_end(irq));
return (EINVAL);
}
diff --git a/sys/mips/rt305x/obio.c b/sys/mips/rt305x/obio.c
index ff7ba03..ac27230 100644
--- a/sys/mips/rt305x/obio.c
+++ b/sys/mips/rt305x/obio.c
@@ -587,8 +587,8 @@ obio_print_all_resources(device_t dev)
if (STAILQ_FIRST(rl))
retval += printf(" at");
- retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
- retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+ retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
+ retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
return (retval);
}
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index 8d9e499..e2c2205 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -250,6 +250,7 @@ SUBDIR= \
${_nandfs} \
${_nandsim} \
${_ncr} \
+ ${_nctgpio} \
${_ncv} \
${_ndis} \
netfpga10g \
@@ -367,6 +368,8 @@ SUBDIR= \
udf_iconv \
ufs \
unionfs \
+ urtwn \
+ ${_urtwnfw} \
usb \
utopia \
${_vesa} \
@@ -484,6 +487,7 @@ _ispfw= ispfw
_mwlfw= mwlfw
_ralfw= ralfw
_rtwnfw= rtwnfw
+_urtwnfw= urtwnfw
_sf= sf
_ti= ti
_txp= txp
@@ -555,6 +559,7 @@ _ixv= ixv
_linprocfs= linprocfs
_linsysfs= linsysfs
_linux= linux
+_nctgpio= nctgpio
_ndis= ndis
_pccard= pccard
.if ${MK_OFED} != "no" || defined(ALL_MODULES)
diff --git a/sys/modules/nctgpio/Makefile b/sys/modules/nctgpio/Makefile
new file mode 100644
index 0000000..88e133d
--- /dev/null
+++ b/sys/modules/nctgpio/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../dev/nctgpio
+KMOD= nctgpio
+SRCS= nctgpio.c
+SRCS+= device_if.h bus_if.h isa_if.h gpio_if.h opt_platform.h
+
+.include <bsd.kmod.mk>
diff --git a/sys/modules/pflog/Makefile b/sys/modules/pflog/Makefile
index 1889681..36656dc 100644
--- a/sys/modules/pflog/Makefile
+++ b/sys/modules/pflog/Makefile
@@ -7,14 +7,11 @@ SRCS= if_pflog.c \
opt_pf.h opt_inet.h opt_inet6.h opt_bpf.h
SRCS+= bus_if.h device_if.h
-.if defined(KERNBUILDDIR)
-MKDEP+= -include ${KERNBUILDDIR}/opt_global.h
-.else
+.if !defined(KERNBUILDDIR)
.if defined(VIMAGE)
opt_global.h:
echo "#define VIMAGE 1" >> ${.TARGET}
CFLAGS+= -include opt_global.h
-MKDEP+= -include opt_global.h
.endif
.endif
diff --git a/sys/modules/pfsync/Makefile b/sys/modules/pfsync/Makefile
index d38bde7..89af6f9 100644
--- a/sys/modules/pfsync/Makefile
+++ b/sys/modules/pfsync/Makefile
@@ -7,14 +7,11 @@ SRCS= if_pfsync.c \
opt_pf.h opt_inet.h opt_inet6.h
SRCS+= bus_if.h device_if.h
-.if defined(KERNBUILDDIR)
-MKDEP+= -include ${KERNBUILDDIR}/opt_global.h
-.else
+.if !defined(KERNBUILDDIR)
.if defined(VIMAGE)
opt_global.h:
echo "#define VIMAGE 1" >> ${.TARGET}
CFLAGS+= -include opt_global.h
-MKDEP+= -include opt_global.h
.endif
.endif
diff --git a/sys/modules/usb/urtwn/Makefile b/sys/modules/urtwn/Makefile
index 59fa910..a4fdc25 100644
--- a/sys/modules/usb/urtwn/Makefile
+++ b/sys/modules/urtwn/Makefile
@@ -1,8 +1,9 @@
# $FreeBSD$
-.PATH: ${.CURDIR}/../../../dev/usb/wlan
+.PATH: ${.CURDIR}/../../dev/urtwn
-.include <src.opts.mk>
+SYSDIR?=${.CURDIR}/../..
+.include "${SYSDIR}/conf/kern.opts.mk"
KMOD = if_urtwn
SRCS = if_urtwn.c if_urtwnreg.h if_urtwnvar.h \
diff --git a/sys/modules/usb/urtwnfw/Makefile b/sys/modules/urtwnfw/Makefile
index 611b411..611b411 100644
--- a/sys/modules/usb/urtwnfw/Makefile
+++ b/sys/modules/urtwnfw/Makefile
diff --git a/sys/modules/usb/urtwnfw/Makefile.inc b/sys/modules/urtwnfw/Makefile.inc
index 17c78be..2a97a09 100644
--- a/sys/modules/usb/urtwnfw/Makefile.inc
+++ b/sys/modules/urtwnfw/Makefile.inc
@@ -11,5 +11,5 @@ FIRMWS= ${_FIRM}:${KMOD}:111
# FIRMWARE_LICENSE= realtek
-${_FIRM}: ${.CURDIR}/../../../../contrib/dev/urtwn/${_FIRM}.uu
+${_FIRM}: ${.CURDIR}/../../../contrib/dev/urtwn/${_FIRM}.uu
uudecode -p $? > ${.TARGET}
diff --git a/sys/modules/usb/urtwnfw/urtwnrtl8188eu/Makefile b/sys/modules/urtwnfw/urtwnrtl8188eu/Makefile
index d3c974e..d3c974e 100644
--- a/sys/modules/usb/urtwnfw/urtwnrtl8188eu/Makefile
+++ b/sys/modules/urtwnfw/urtwnrtl8188eu/Makefile
diff --git a/sys/modules/usb/urtwnfw/urtwnrtl8192cT/Makefile b/sys/modules/urtwnfw/urtwnrtl8192cT/Makefile
index ef49984..ef49984 100644
--- a/sys/modules/usb/urtwnfw/urtwnrtl8192cT/Makefile
+++ b/sys/modules/urtwnfw/urtwnrtl8192cT/Makefile
diff --git a/sys/modules/usb/urtwnfw/urtwnrtl8192cU/Makefile b/sys/modules/urtwnfw/urtwnrtl8192cU/Makefile
index e9a932c..e9a932c 100644
--- a/sys/modules/usb/urtwnfw/urtwnrtl8192cU/Makefile
+++ b/sys/modules/urtwnfw/urtwnrtl8192cU/Makefile
diff --git a/sys/modules/usb/Makefile b/sys/modules/usb/Makefile
index b236d04..72b123e 100644
--- a/sys/modules/usb/Makefile
+++ b/sys/modules/usb/Makefile
@@ -47,7 +47,6 @@ SUBDIR = usb
SUBDIR += ${_dwc_otg} ehci ${_musb} ohci uhci xhci ${_uss820dci} ${_at91dci} \
${_atmegadci} ${_avr32dci} ${_rsu} ${_rsufw} ${_saf1761otg}
SUBDIR += ${_rum} ${_run} ${_runfw} ${_uath} upgt usie ural ${_zyd} ${_urtw}
-SUBDIR += urtwn ${_urtwnfw}
SUBDIR += atp uhid ukbd ums udbp ufm uep wsp ugold uled
SUBDIR += ucom u3g uark ubsa ubser uchcom ucycom ufoma uftdi ugensa uipaq ulpt \
umct umcs umodem umoscom uplcom uslcom uvisor uvscom
@@ -70,7 +69,6 @@ _rum= rum
_uath= uath
_zyd= zyd
_kue= kue
-_urtwnfw= urtwnfw
_run= run
_runfw= runfw
_rsu= rsu
diff --git a/sys/modules/wtap/Makefile b/sys/modules/wtap/Makefile
index 68b905f..58f60fb 100644
--- a/sys/modules/wtap/Makefile
+++ b/sys/modules/wtap/Makefile
@@ -16,11 +16,8 @@ SRCS += visibility.c
SRCS += opt_global.h
-.if defined(KERNBUILDDIR)
-MKDEP= -include ${KERNBUILDDIR}/opt_global.h
-.else
+.if !defined(KERNBUILDDIR)
CFLAGS+= -include opt_global.h
-MKDEP= -include opt_global.h
opt_global.h:
echo "#define VIMAGE 1" > ${.TARGET}
diff --git a/sys/net/ethernet.h b/sys/net/ethernet.h
index 438028d..52d8f61 100644
--- a/sys/net/ethernet.h
+++ b/sys/net/ethernet.h
@@ -333,6 +333,7 @@ struct ether_vlan_header {
#define ETHERTYPE_SLOW 0x8809 /* 802.3ad link aggregation (LACP) */
#define ETHERTYPE_PPP 0x880B /* PPP (obsolete by PPPoE) */
#define ETHERTYPE_HITACHI 0x8820 /* Hitachi Cable (Optoelectronic Systems Laboratory) */
+#define ETHERTYPE_TEST 0x8822 /* Network Conformance Testing */
#define ETHERTYPE_MPLS 0x8847 /* MPLS Unicast */
#define ETHERTYPE_MPLS_MCAST 0x8848 /* MPLS Multicast */
#define ETHERTYPE_AXIS 0x8856 /* Axis Communications AB proprietary bootstrap/config */
diff --git a/sys/net/if_debug.c b/sys/net/if_debug.c
index 1d198eb..fbcc2b0 100644
--- a/sys/net/if_debug.c
+++ b/sys/net/if_debug.c
@@ -67,6 +67,8 @@ if_show_ifnet(struct ifnet *ifp)
IF_DB_PRINTF("%p", if_l2com);
IF_DB_PRINTF("%p", if_vnet);
IF_DB_PRINTF("%p", if_home_vnet);
+ IF_DB_PRINTF("%p", if_vlantrunk);
+ IF_DB_PRINTF("%p", if_bpf);
IF_DB_PRINTF("%p", if_addr);
IF_DB_PRINTF("%p", if_llsoftc);
IF_DB_PRINTF("%p", if_label);
diff --git a/sys/net/route.c b/sys/net/route.c
index 45f479c..4b191d0 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -201,6 +201,16 @@ rt_tables_get_rnh(int table, int fam)
return (*rt_tables_get_rnh_ptr(table, fam));
}
+u_int
+rt_tables_get_gen(int table, int fam)
+{
+ struct rib_head *rnh;
+
+ rnh = *rt_tables_get_rnh_ptr(table, fam);
+ return (rnh->rnh_gen);
+}
+
+
/*
* route initialization must occur before ip6_init2(), which happenas at
* SI_ORDER_MIDDLE.
@@ -1754,6 +1764,7 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt,
*ret_nrt = rt;
RT_ADDREF(rt);
}
+ rnh->rnh_gen++; /* Routing table updated */
RT_UNLOCK(rt);
break;
case RTM_CHANGE:
diff --git a/sys/net/route.h b/sys/net/route.h
index 6cc1e1c..e0ff6b4 100644
--- a/sys/net/route.h
+++ b/sys/net/route.h
@@ -98,6 +98,14 @@ struct rt_metrics {
/* lle state is exported in rmx_state rt_metrics field */
#define rmx_state rmx_weight
+/*
+ * Keep a generation count of routing table, incremented on route addition,
+ * so we can invalidate caches. This is accessed without a lock, as precision
+ * is not required.
+ */
+typedef volatile u_int rt_gen_t; /* tree generation (for adds) */
+#define RT_GEN(fibnum, af) rt_tables_get_gen(fibnum, af)
+
#define RT_DEFAULT_FIB 0 /* Explicitly mark fib=0 restricted cases */
#define RT_ALL_FIBS -1 /* Announce event for every fib */
#ifdef _KERNEL
@@ -398,6 +406,20 @@ struct rt_addrinfo {
} \
} while (0)
+/*
+ * Validate a cached route based on a supplied cookie. If there is an
+ * out-of-date cache, simply free it. Update the generation number
+ * for the new allocation
+ */
+#define RT_VALIDATE(ro, cookiep, fibnum) do { \
+ rt_gen_t cookie = RT_GEN(fibnum, (ro)->ro_dst.sa_family); \
+ if (*(cookiep) != cookie && (ro)->ro_rt != NULL) { \
+ RTFREE((ro)->ro_rt); \
+ (ro)->ro_rt = NULL; \
+ *(cookiep) = cookie; \
+ } \
+} while (0)
+
struct ifmultiaddr;
struct rib_head;
@@ -415,6 +437,7 @@ int rt_setgate(struct rtentry *, struct sockaddr *, struct sockaddr *);
void rt_maskedcopy(struct sockaddr *, struct sockaddr *, struct sockaddr *);
struct rib_head *rt_table_init(int);
void rt_table_destroy(struct rib_head *);
+u_int rt_tables_get_gen(int table, int fam);
int rtsock_addrmsg(int, struct ifaddr *, int);
int rtsock_routemsg(int, struct ifnet *ifp, int, struct rtentry *, int);
diff --git a/sys/net/route_var.h b/sys/net/route_var.h
index 86fc8a9..a8ef56a 100644
--- a/sys/net/route_var.h
+++ b/sys/net/route_var.h
@@ -41,7 +41,7 @@ struct rib_head {
rn_walktree_t *rnh_walktree; /* traverse tree */
rn_walktree_from_t *rnh_walktree_from; /* traverse tree below a */
rn_close_t *rnh_close; /*do something when the last ref drops*/
- u_int rnh_gen; /* generation counter */
+ rt_gen_t rnh_gen; /* generation counter */
int rnh_multipath; /* multipath capable ? */
struct radix_node rnh_nodes[3]; /* empty tree for common case */
struct rwlock rib_lock; /* config/data path lock */
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index d59ef70..810da1b 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -275,8 +275,6 @@ rts_attach(struct socket *so, int proto, struct thread *td)
/* XXX */
rp = malloc(sizeof *rp, M_PCB, M_WAITOK | M_ZERO);
- if (rp == NULL)
- return ENOBUFS;
so->so_pcb = (caddr_t)rp;
so->so_fibnum = td->td_proc->p_fibnum;
diff --git a/sys/net80211/ieee80211.h b/sys/net80211/ieee80211.h
index 0a25392..f5fdd5a 100644
--- a/sys/net80211/ieee80211.h
+++ b/sys/net80211/ieee80211.h
@@ -317,6 +317,27 @@ struct ieee80211_wme_param {
} __packed;
/*
+ * WME U-APSD qos info field defines
+ */
+#define WME_CAPINFO_UAPSD_EN 0x00000080
+#define WME_CAPINFO_UAPSD_VO 0x00000001
+#define WME_CAPINFO_UAPSD_VI 0x00000002
+#define WME_CAPINFO_UAPSD_BK 0x00000004
+#define WME_CAPINFO_UAPSD_BE 0x00000008
+#define WME_CAPINFO_UAPSD_ACFLAGS_SHIFT 0
+#define WME_CAPINFO_UAPSD_ACFLAGS_MASK 0xF
+#define WME_CAPINFO_UAPSD_MAXSP_SHIFT 5
+#define WME_CAPINFO_UAPSD_MAXSP_MASK 0x3
+#define WME_CAPINFO_IE_OFFSET 8
+#define WME_UAPSD_MAXSP(_qosinfo) \
+ (((_qosinfo) >> WME_CAPINFO_UAPSD_MAXSP_SHIFT) & \
+ WME_CAPINFO_UAPSD_MAXSP_MASK)
+#define WME_UAPSD_AC_ENABLED(_ac, _qosinfo) \
+ ((1 << (3 - (_ac))) & ( \
+ ((_qosinfo) >> WME_CAPINFO_UAPSD_ACFLAGS_SHIFT) & \
+ WME_CAPINFO_UAPSD_ACFLAGS_MASK))
+
+/*
* Management Notification Frame
*/
struct ieee80211_mnf {
@@ -346,6 +367,7 @@ struct ieee80211_action {
#define IEEE80211_ACTION_CAT_MESH 13 /* Mesh */
#define IEEE80211_ACTION_CAT_SELF_PROT 15 /* Self-protected */
/* 16 - 125 reserved */
+#define IEEE80211_ACTION_VHT 21
#define IEEE80211_ACTION_CAT_VENDOR 127 /* Vendor Specific */
#define IEEE80211_ACTION_HT_TXCHWIDTH 0 /* recommended xmit chan width*/
@@ -695,6 +717,151 @@ struct ieee80211_ie_htinfo {
#define IEEE80211_HTINFO_BASIC_STBCMCS_S 0
#define IEEE80211_HTINFO_DUALPROTECTED 0x80
+
+/*
+ * 802.11ac definitions - 802.11ac-2013 .
+ */
+
+/* VHT opmode bits */
+#define IEEE80211_VHT_OPMODE_CHANWIDTH_MASK 3
+#define IEEE80211_VHT_OPMODE_CHANWIDTH_20MHZ 0
+#define IEEE80211_VHT_OPMODE_CHANWIDTH_40MHZ 1
+#define IEEE80211_VHT_OPMODE_CHANWIDTH_80MHZ 2
+#define IEEE80211_VHT_OPMODE_CHANWIDTH_160MHZ 3
+#define IEEE80211_VHT_OPMODE_RX_NSS_MASK 0x70
+#define IEEE80211_VHT_OPMODE_RX_NSS_SHIFT 4
+#define IEEE80211_VHT_OPMODE_RX_NSS_TYPE_BF 0x80
+
+/*
+ * Maximum length of A-MPDU that the STA can RX in VHT.
+ * Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets)
+ */
+#define IEEE80211_VHTCAP_MAX_AMPDU_8K 0
+#define IEEE80211_VHTCAP_MAX_AMPDU_16K 1
+#define IEEE80211_VHTCAP_MAX_AMPDU_32K 2
+#define IEEE80211_VHTCAP_MAX_AMPDU_64K 3
+#define IEEE80211_VHTCAP_MAX_AMPDU_128K 4
+#define IEEE80211_VHTCAP_MAX_AMPDU_256K 5
+#define IEEE80211_VHTCAP_MAX_AMPDU_512K 6
+#define IEEE80211_VHTCAP_MAX_AMPDU_1024K 7
+
+/*
+ * VHT MCS information.
+ * + rx_highest/tx_highest: optional; maximum long GI VHT PPDU
+ * data rate. 1Mbit/sec units.
+ * + rx_mcs_map/tx_mcs_map: bitmap of per-stream supported MCS;
+ * 2 bits each.
+ */
+#define IEEE80211_VHT_MCS_SUPPORT_0_7 0 /* MCS0-7 */
+#define IEEE80211_VHT_MCS_SUPPORT_0_8 1 /* MCS0-8 */
+#define IEEE80211_VHT_MCS_SUPPORT_0_9 2 /* MCS0-9 */
+#define IEEE80211_VHT_MCS_NOT_SUPPORTED 3 /* not supported */
+
+struct ieee80211_vht_mcs_info {
+ uint16_t rx_mcs_map;
+ uint16_t rx_highest;
+ uint16_t tx_mcs_map;
+ uint16_t tx_highest;
+} __packed;
+
+/* VHT capabilities element: 802.11ac-2013 8.4.2.160 */
+struct ieee80211_ie_vhtcap {
+ uint8_t ie;
+ uint8_t len;
+ uint32_t vht_cap_info;
+ struct ieee80211_vht_mcs_info supp_mcs;
+} __packed;
+
+#define IEEE80211_VHT_CHANWIDTH_USE_HT 0 /* Use HT IE for chw */
+#define IEEE80211_VHT_CHANWIDTH_80MHZ 1 /* 80MHz */
+#define IEEE80211_VHT_CHANWIDTH_160MHZ 2 /* 160MHz */
+#define IEEE80211_VHT_CHANWIDTH_80P80MHZ 3 /* 80+80MHz */
+
+/* VHT operation IE - 802.11ac-2013 8.4.2.161 */
+struct ieee80211_ie_vht_operation {
+ uint8_t ie;
+ uint8_t len;
+ uint8_t chan_width;
+ uint8_t center_freq_seg1_idx;
+ uint8_t center_freq_seg2_idx;
+ uint16_t basic_mcs_set;
+} __packed;
+
+/* 802.11ac VHT Capabilities */
+#define IEEE80211_VHTCAP_MAX_MPDU_LENGTH_3895 0x00000000
+#define IEEE80211_VHTCAP_MAX_MPDU_LENGTH_7991 0x00000001
+#define IEEE80211_VHTCAP_MAX_MPDU_LENGTH_11454 0x00000002
+#define IEEE80211_VHTCAP_MAX_MPDU_MASK 0x00000003
+#define IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_160MHZ 0x00000004
+#define IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ 0x00000008
+#define IEEE80211_VHTCAP_SUPP_CHAN_WIDTH_MASK 0x0000000C
+#define IEEE80211_VHTCAP_RXLDPC 0x00000010
+#define IEEE80211_VHTCAP_SHORT_GI_80 0x00000020
+#define IEEE80211_VHTCAP_SHORT_GI_160 0x00000040
+#define IEEE80211_VHTCAP_TXSTBC 0x00000080
+#define IEEE80211_VHTCAP_RXSTBC_1 0x00000100
+#define IEEE80211_VHTCAP_RXSTBC_2 0x00000200
+#define IEEE80211_VHTCAP_RXSTBC_3 0x00000300
+#define IEEE80211_VHTCAP_RXSTBC_4 0x00000400
+#define IEEE80211_VHTCAP_RXSTBC_MASK 0x00000700
+#define IEEE80211_VHTCAP_SU_BEAMFORMER_CAPABLE 0x00000800
+#define IEEE80211_VHTCAP_SU_BEAMFORMEE_CAPABLE 0x00001000
+#define IEEE80211_VHTCAP_BEAMFORMEE_STS_SHIFT 13
+#define IEEE80211_VHTCAP_BEAMFORMEE_STS_MASK \
+ (7 << IEEE80211_VHTCAP_BEAMFORMEE_STS_SHIFT)
+#define IEEE80211_VHTCAP_SOUNDING_DIMENSIONS_SHIFT 16
+#define IEEE80211_VHTCAP_SOUNDING_DIMENSIONS_MASK \
+ (7 << IEEE80211_VHTCAP_SOUNDING_DIMENSIONS_SHIFT)
+#define IEEE80211_VHTCAP_MU_BEAMFORMER_CAPABLE 0x00080000
+#define IEEE80211_VHTCAP_MU_BEAMFORMEE_CAPABLE 0x00100000
+#define IEEE80211_VHTCAP_VHT_TXOP_PS 0x00200000
+#define IEEE80211_VHTCAP_HTC_VHT 0x00400000
+#define IEEE80211_VHTCAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT 23
+#define IEEE80211_VHTCAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK \
+ (7 << IEEE80211_VHTCAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT)
+#define IEEE80211_VHTCAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB 0x08000000
+#define IEEE80211_VHTCAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB 0x0c000000
+#define IEEE80211_VHTCAP_RX_ANTENNA_PATTERN 0x10000000
+#define IEEE80211_VHTCAP_TX_ANTENNA_PATTERN 0x20000000
+
+/*
+ * VHT Transmit Power Envelope element - 802.11ac-2013 8.4.2.164
+ *
+ * This defines the maximum transmit power for various bandwidths.
+ */
+/*
+ * Count is how many elements follow and what they're for:
+ *
+ * 0 - 20 MHz
+ * 1 - 20+40 MHz
+ * 2 - 20+40+80 MHz
+ * 3 - 20+40+80+(160, 80+80) MHz
+ */
+#define IEEE80211_VHT_TXPWRENV_INFO_COUNT_SHIFT 0
+#define IEEE80211_VHT_TXPWRENV_INFO_COUNT_MASK 0x07
+
+/*
+ * Unit is the tx power representation. It should be EIRP for now;
+ * other values are reserved.
+ */
+#define IEEE80211_VHT_TXPWRENV_UNIT_MASK 0x38
+#define IEEE80211_VHT_TXPWRENV_UNIT_SHIFT 3
+
+/* This value is within the unit mask/shift above */
+#define IEEE80211_VHT_TXPWRENV_UNIT_EIRP 0
+
+struct ieee80211_ie_vht_txpwrenv {
+ uint8_t ie;
+ uint8_t len;
+ uint8_t tx_info;
+ int8_t tx_elem[0]; /* TX power elements, 1/2 dB, signed */
+};
+
+/* VHT action codes */
+#define WLAN_ACTION_VHT_COMPRESSED_BF 0
+#define WLAN_ACTION_VHT_GROUPID_MGMT 1
+#define WLAN_ACTION_VHT_OPMODE_NOTIF 2
+
/*
* Management information element payloads.
*/
@@ -709,6 +876,8 @@ enum {
IEEE80211_ELEMID_IBSSPARMS = 6,
IEEE80211_ELEMID_COUNTRY = 7,
IEEE80211_ELEMID_BSSLOAD = 11,
+ IEEE80211_ELEMID_TSPEC = 13,
+ IEEE80211_ELEMID_TCLAS = 14,
IEEE80211_ELEMID_CHALLENGE = 16,
/* 17-31 reserved for challenge text extension */
IEEE80211_ELEMID_PWRCNSTR = 32,
@@ -728,6 +897,17 @@ enum {
IEEE80211_ELEMID_XRATES = 50,
IEEE80211_ELEMID_APCHANREP = 51,
IEEE80211_ELEMID_HTINFO = 61,
+ IEEE80211_ELEMID_SECCHAN_OFFSET = 62,
+ IEEE80211_ELEMID_RRM_ENACAPS = 70,
+ IEEE80211_ELEMID_MULTIBSSID = 71,
+ IEEE80211_ELEMID_COEX_2040 = 72,
+ IEEE80211_ELEMID_INTOL_CHN_REPORT = 73,
+ IEEE80211_ELEMID_OVERLAP_BSS_SCAN_PARAM = 74,
+ IEEE80211_ELEMID_TSF_REQ = 91,
+ IEEE80211_ELEMID_TSF_RESP = 92,
+ IEEE80211_ELEMID_WNM_SLEEP_MODE = 93,
+ IEEE80211_ELEMID_TIM_BCAST_REQ = 94,
+ IEEE80211_ELEMID_TIM_BCAST_RESP = 95,
IEEE80211_ELEMID_TPC = 150,
IEEE80211_ELEMID_CCKM = 156,
IEEE80211_ELEMID_VENDOR = 221, /* vendor private */
@@ -751,7 +931,7 @@ enum {
IEEE80211_ELEMID_MESHGANN = 125,
IEEE80211_ELEMID_MESHRANN = 126,
/* 127 Extended Capabilities */
- IEEE80211_ELEMID_MESHEXTCAP = 127,
+ IEEE80211_ELEMID_EXTCAP = 127,
/* 128-129 reserved */
IEEE80211_ELEMID_MESHPREQ = 130,
IEEE80211_ELEMID_MESHPREP = 131,
@@ -760,6 +940,11 @@ enum {
IEEE80211_ELEMID_MESHPXU = 137,
IEEE80211_ELEMID_MESHPXUC = 138,
IEEE80211_ELEMID_MESHAH = 60, /* XXX: remove */
+
+ /* 802.11ac */
+ IEEE80211_ELEMID_VHT_CAP = 191,
+ IEEE80211_ELEMID_VHT_OPMODE = 192,
+ IEEE80211_ELEMID_VHT_PWR_ENV = 195,
};
struct ieee80211_tim_ie {
diff --git a/sys/net80211/ieee80211_amrr.c b/sys/net80211/ieee80211_amrr.c
index f50334e..7460223 100644
--- a/sys/net80211/ieee80211_amrr.c
+++ b/sys/net80211/ieee80211_amrr.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
+#include <sys/sbuf.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
@@ -75,6 +76,7 @@ static void amrr_tx_update(const struct ieee80211vap *vap,
const struct ieee80211_node *, void *, void *, void *);
static void amrr_sysctlattach(struct ieee80211vap *,
struct sysctl_ctx_list *, struct sysctl_oid *);
+static void amrr_node_stats(struct ieee80211_node *ni, struct sbuf *s);
/* number of references from net80211 layer */
static int nrefs = 0;
@@ -91,6 +93,7 @@ static const struct ieee80211_ratectl amrr = {
.ir_tx_complete = amrr_tx_complete,
.ir_tx_update = amrr_tx_update,
.ir_setinterval = amrr_setinterval,
+ .ir_node_stats = amrr_node_stats,
};
IEEE80211_RATECTL_MODULE(amrr, 1);
IEEE80211_RATECTL_ALG(amrr, IEEE80211_RATECTL_AMRR, amrr);
@@ -410,3 +413,31 @@ amrr_sysctlattach(struct ieee80211vap *vap,
"amrr_min_sucess_threshold", CTLFLAG_RW,
&amrr->amrr_min_success_threshold, 0, "");
}
+
+static void
+amrr_node_stats(struct ieee80211_node *ni, struct sbuf *s)
+{
+ int rate;
+ struct ieee80211_amrr_node *amn = ni->ni_rctls;
+ struct ieee80211_rateset *rs;
+
+ /* XXX TODO: check locking? */
+
+ /* XXX TODO: this should be a method */
+ if (amrr_node_is_11n(ni)) {
+ rs = (struct ieee80211_rateset *) &ni->ni_htrates;
+ rate = rs->rs_rates[amn->amn_rix] & IEEE80211_RATE_VAL;
+ sbuf_printf(s, "rate: MCS %d\n", rate);
+ } else {
+ rs = &ni->ni_rates;
+ rate = rs->rs_rates[amn->amn_rix] & IEEE80211_RATE_VAL;
+ sbuf_printf(s, "rate: %d Mbit\n", rate / 2);
+ }
+
+ sbuf_printf(s, "ticks: %d\n", amn->amn_ticks);
+ sbuf_printf(s, "txcnt: %u\n", amn->amn_txcnt);
+ sbuf_printf(s, "success: %u\n", amn->amn_success);
+ sbuf_printf(s, "success_threshold: %u\n", amn->amn_success_threshold);
+ sbuf_printf(s, "recovery: %u\n", amn->amn_recovery);
+ sbuf_printf(s, "retry_cnt: %u\n", amn->amn_retrycnt);
+}
diff --git a/sys/net80211/ieee80211_dfs.c b/sys/net80211/ieee80211_dfs.c
index 232ceb7..4478d9e 100644
--- a/sys/net80211/ieee80211_dfs.c
+++ b/sys/net80211/ieee80211_dfs.c
@@ -245,7 +245,7 @@ dfs_timeout(void *arg)
for (i = 0; i < ic->ic_nchans; i++) {
c = &ic->ic_channels[i];
if (IEEE80211_IS_CHAN_RADAR(c)) {
- if (time_after_eq(now, dfs->nol_event[i]+NOL_TIMEOUT)) {
+ if (ieee80211_time_after_eq(now, dfs->nol_event[i]+NOL_TIMEOUT)) {
c->ic_state &= ~IEEE80211_CHANSTATE_RADAR;
if (c->ic_state & IEEE80211_CHANSTATE_NORADAR) {
/*
diff --git a/sys/net80211/ieee80211_freebsd.h b/sys/net80211/ieee80211_freebsd.h
index 0566da7..62f3335 100644
--- a/sys/net80211/ieee80211_freebsd.h
+++ b/sys/net80211/ieee80211_freebsd.h
@@ -251,10 +251,10 @@ void ieee80211_vap_destroy(struct ieee80211vap *);
#define ticks_to_msecs(t) (1000*(t) / hz)
#define ticks_to_secs(t) ((t) / hz)
-#define time_after(a,b) ((long)(b) - (long)(a) < 0)
-#define time_before(a,b) time_after(b,a)
-#define time_after_eq(a,b) ((long)(a) - (long)(b) >= 0)
-#define time_before_eq(a,b) time_after_eq(b,a)
+#define ieee80211_time_after(a,b) ((long)(b) - (long)(a) < 0)
+#define ieee80211_time_before(a,b) ieee80211_time_after(b,a)
+#define ieee80211_time_after_eq(a,b) ((long)(a) - (long)(b) >= 0)
+#define ieee80211_time_before_eq(a,b) ieee80211_time_after_eq(b,a)
struct mbuf *ieee80211_getmgtframe(uint8_t **frm, int headroom, int pktlen);
diff --git a/sys/net80211/ieee80211_ht.c b/sys/net80211/ieee80211_ht.c
index 1a21734..be380e9 100644
--- a/sys/net80211/ieee80211_ht.c
+++ b/sys/net80211/ieee80211_ht.c
@@ -1406,7 +1406,7 @@ ieee80211_ht_timeout(struct ieee80211com *ic)
IEEE80211_LOCK_ASSERT(ic);
if ((ic->ic_flags_ht & IEEE80211_FHT_NONHT_PR) &&
- time_after(ticks, ic->ic_lastnonht + IEEE80211_NONHT_PRESENT_AGE)) {
+ ieee80211_time_after(ticks, ic->ic_lastnonht + IEEE80211_NONHT_PRESENT_AGE)) {
#if 0
IEEE80211_NOTE(vap, IEEE80211_MSG_11N, ni,
"%s", "time out non-HT STA present on channel");
diff --git a/sys/net80211/ieee80211_hwmp.c b/sys/net80211/ieee80211_hwmp.c
index 6bbc32c..0c920d8 100644
--- a/sys/net80211/ieee80211_hwmp.c
+++ b/sys/net80211/ieee80211_hwmp.c
@@ -260,7 +260,7 @@ ieee80211_hwmp_init(void)
}
SYSINIT(wlan_hwmp, SI_SUB_DRIVERS, SI_ORDER_SECOND, ieee80211_hwmp_init, NULL);
-void
+static void
hwmp_vattach(struct ieee80211vap *vap)
{
struct ieee80211_hwmp_state *hs;
@@ -279,7 +279,7 @@ hwmp_vattach(struct ieee80211vap *vap)
vap->iv_hwmp = hs;
}
-void
+static void
hwmp_vdetach(struct ieee80211vap *vap)
{
struct ieee80211_hwmp_state *hs = vap->iv_hwmp;
@@ -289,7 +289,7 @@ hwmp_vdetach(struct ieee80211vap *vap)
vap->iv_hwmp = NULL;
}
-int
+static int
hwmp_newstate(struct ieee80211vap *vap, enum ieee80211_state ostate, int arg)
{
enum ieee80211_state nstate = vap->iv_state;
diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c
index 3b4379f..5c2f9e5 100644
--- a/sys/net80211/ieee80211_input.c
+++ b/sys/net80211/ieee80211_input.c
@@ -603,9 +603,10 @@ ieee80211_parse_beacon(struct ieee80211_node *ni, struct mbuf *m,
case IEEE80211_ELEMID_MESHCONF:
scan->meshconf = frm;
break;
- case IEEE80211_ELEMID_MESHEXTCAP:
- break;
#endif
+ /* Extended capabilities; nothing handles it for now */
+ case IEEE80211_ELEMID_EXTCAP:
+ break;
case IEEE80211_ELEMID_VENDOR:
if (iswpaoui(frm))
scan->wpa = frm;
diff --git a/sys/net80211/ieee80211_ioctl.h b/sys/net80211/ieee80211_ioctl.h
index ee98026..8c606c1 100644
--- a/sys/net80211/ieee80211_ioctl.h
+++ b/sys/net80211/ieee80211_ioctl.h
@@ -246,7 +246,10 @@ struct ieee80211_stats {
uint32_t is_ampdu_bar_tx_retry; /* A-MPDU BAR frames TX rtry */
uint32_t is_ampdu_bar_tx_fail; /* A-MPDU BAR frames TX fail */
- uint32_t is_spare[7];
+ uint32_t is_ff_encapfail; /* failed FF encap */
+ uint32_t is_amsdu_encapfail; /* failed A-MSDU encap */
+
+ uint32_t is_spare[5];
};
/*
diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c
index 6ac3655..520687b 100644
--- a/sys/net80211/ieee80211_node.c
+++ b/sys/net80211/ieee80211_node.c
@@ -2638,7 +2638,7 @@ ieee80211_erp_timeout(struct ieee80211com *ic)
IEEE80211_LOCK_ASSERT(ic);
if ((ic->ic_flags_ext & IEEE80211_FEXT_NONERP_PR) &&
- time_after(ticks, ic->ic_lastnonerp + IEEE80211_NONERP_PRESENT_AGE)) {
+ ieee80211_time_after(ticks, ic->ic_lastnonerp + IEEE80211_NONERP_PRESENT_AGE)) {
#if 0
IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC, ni,
"%s", "age out non-ERP sta present on channel");
diff --git a/sys/net80211/ieee80211_power.c b/sys/net80211/ieee80211_power.c
index 587e48f..4493ed6 100644
--- a/sys/net80211/ieee80211_power.c
+++ b/sys/net80211/ieee80211_power.c
@@ -623,7 +623,7 @@ ieee80211_sta_ps_timer_check(struct ieee80211vap *vap)
/* If we've done any data within our idle interval, bail */
/* XXX hard-coded to one second for now, ew! */
- if (time_after(ic->ic_lastdata + 500, ticks))
+ if (ieee80211_time_after(ic->ic_lastdata + 500, ticks))
goto out;
/*
diff --git a/sys/net80211/ieee80211_proto.c b/sys/net80211/ieee80211_proto.c
index 3bc3141..2feb59a 100644
--- a/sys/net80211/ieee80211_proto.c
+++ b/sys/net80211/ieee80211_proto.c
@@ -1531,7 +1531,7 @@ beacon_miss(void *arg, int npending)
IEEE80211_LOCK(ic);
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
/*
- * We only pass events through for sta vap's in RUN state;
+ * We only pass events through for sta vap's in RUN+ state;
* may be too restrictive but for now this saves all the
* handlers duplicating these checks.
*/
@@ -1550,7 +1550,7 @@ beacon_swmiss(void *arg, int npending)
struct ieee80211com *ic = vap->iv_ic;
IEEE80211_LOCK(ic);
- if (vap->iv_state == IEEE80211_S_RUN) {
+ if (vap->iv_state >= IEEE80211_S_RUN) {
/* XXX Call multiple times if npending > zero? */
vap->iv_bmiss(vap);
}
@@ -1570,8 +1570,7 @@ ieee80211_swbmiss(void *arg)
IEEE80211_LOCK_ASSERT(ic);
- /* XXX sleep state? */
- KASSERT(vap->iv_state == IEEE80211_S_RUN,
+ KASSERT(vap->iv_state >= IEEE80211_S_RUN,
("wrong state %d", vap->iv_state));
if (ic->ic_flags & IEEE80211_F_SCAN) {
diff --git a/sys/net80211/ieee80211_ratectl.c b/sys/net80211/ieee80211_ratectl.c
index 3eff898..e9a0e2f 100644
--- a/sys/net80211/ieee80211_ratectl.c
+++ b/sys/net80211/ieee80211_ratectl.c
@@ -28,6 +28,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
+#include <sys/sbuf.h>
#include <sys/systm.h>
#include <sys/socket.h>
#include <sys/malloc.h>
@@ -68,12 +69,52 @@ ieee80211_ratectl_unregister(int type)
ratectls[type] = NULL;
}
+static void
+ieee80211_ratectl_sysctl_stats_node_iter(void *arg, struct ieee80211_node *ni)
+{
+
+ struct sbuf *sb = (struct sbuf *) arg;
+ sbuf_printf(sb, "MAC: %6D\n", ni->ni_macaddr, ":");
+ ieee80211_ratectl_node_stats(ni, sb);
+ sbuf_printf(sb, "\n");
+}
+
+static int
+ieee80211_ratectl_sysctl_stats(SYSCTL_HANDLER_ARGS)
+{
+ struct ieee80211vap *vap = arg1;
+ struct ieee80211com *ic = vap->iv_ic;
+ struct sbuf sb;
+ int error;
+
+ error = sysctl_wire_old_buffer(req, 0);
+ if (error)
+ return (error);
+ sbuf_new_for_sysctl(&sb, NULL, 8, req);
+ sbuf_clear_flags(&sb, SBUF_INCLUDENUL);
+
+ IEEE80211_LOCK(ic);
+ ieee80211_iterate_nodes(&ic->ic_sta,
+ ieee80211_ratectl_sysctl_stats_node_iter,
+ &sb);
+ IEEE80211_UNLOCK(ic);
+
+ error = sbuf_finish(&sb);
+ sbuf_delete(&sb);
+ return (error);
+}
+
void
ieee80211_ratectl_init(struct ieee80211vap *vap)
{
if (vap->iv_rate == ratectls[IEEE80211_RATECTL_NONE])
ieee80211_ratectl_set(vap, IEEE80211_RATECTL_AMRR);
vap->iv_rate->ir_init(vap);
+
+ /* Attach generic stats sysctl */
+ SYSCTL_ADD_PROC(vap->iv_sysctl, SYSCTL_CHILDREN(vap->iv_oid), OID_AUTO,
+ "rate_stats", CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, vap,
+ 0, ieee80211_ratectl_sysctl_stats, "A", "ratectl node stats");
}
void
diff --git a/sys/net80211/ieee80211_ratectl.h b/sys/net80211/ieee80211_ratectl.h
index 5603509..9765fe7 100644
--- a/sys/net80211/ieee80211_ratectl.h
+++ b/sys/net80211/ieee80211_ratectl.h
@@ -53,6 +53,7 @@ struct ieee80211_ratectl {
const struct ieee80211_node *,
void *, void *, void *);
void (*ir_setinterval)(const struct ieee80211vap *, int);
+ void (*ir_node_stats)(struct ieee80211_node *ni, struct sbuf *s);
};
void ieee80211_ratectl_register(int, const struct ieee80211_ratectl *);
@@ -115,3 +116,13 @@ ieee80211_ratectl_setinterval(const struct ieee80211vap *vap, int msecs)
return;
vap->iv_rate->ir_setinterval(vap, msecs);
}
+
+static __inline void
+ieee80211_ratectl_node_stats(struct ieee80211_node *ni, struct sbuf *s)
+{
+ const struct ieee80211vap *vap = ni->ni_vap;
+
+ if (vap->iv_rate->ir_node_stats == NULL)
+ return;
+ vap->iv_rate->ir_node_stats(ni, s);
+}
diff --git a/sys/net80211/ieee80211_scan_sta.c b/sys/net80211/ieee80211_scan_sta.c
index 07df92f..233c436 100644
--- a/sys/net80211/ieee80211_scan_sta.c
+++ b/sys/net80211/ieee80211_scan_sta.c
@@ -1323,7 +1323,7 @@ sta_roam_check(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
* XXX deauth current ap
*/
if (curRate < roamRate || curRssi < roamRssi) {
- if (time_after(ticks, ic->ic_lastscan + vap->iv_scanvalid)) {
+ if (ieee80211_time_after(ticks, ic->ic_lastscan + vap->iv_scanvalid)) {
/*
* Scan cache contents are too old; force a scan now
* if possible so we have current state to make a
@@ -1333,7 +1333,7 @@ sta_roam_check(struct ieee80211_scan_state *ss, struct ieee80211vap *vap)
* XXX force immediate switch on scan complete
*/
if (!IEEE80211_IS_CHAN_DTURBO(ic->ic_curchan) &&
- time_after(ticks, ic->ic_lastdata + vap->iv_bgscanidle))
+ ieee80211_time_after(ticks, ic->ic_lastdata + vap->iv_bgscanidle))
ieee80211_bg_scan(vap, 0);
return;
}
diff --git a/sys/net80211/ieee80211_scan_sw.c b/sys/net80211/ieee80211_scan_sw.c
index fc62f24..5875980 100644
--- a/sys/net80211/ieee80211_scan_sw.c
+++ b/sys/net80211/ieee80211_scan_sw.c
@@ -304,7 +304,7 @@ ieee80211_swscan_check_scan(const struct ieee80211_scanner *scan,
}
if ((ic->ic_flags & IEEE80211_F_SCAN) == 0 &&
(flags & IEEE80211_SCAN_FLUSH) == 0 &&
- time_before(ticks, ic->ic_lastscan + vap->iv_scanvalid)) {
+ ieee80211_time_before(ticks, ic->ic_lastscan + vap->iv_scanvalid)) {
/*
* We're not currently scanning and the cache is
* deemed hot enough to consult. Lock out others
@@ -674,7 +674,7 @@ end:
if (scandone || (ss->ss_flags & IEEE80211_SCAN_GOTPICK) ||
(ss_priv->ss_iflags & ISCAN_ABORT) ||
- time_after(ticks + ss->ss_mindwell, ss_priv->ss_scanend)) {
+ ieee80211_time_after(ticks + ss->ss_mindwell, ss_priv->ss_scanend)) {
ss_priv->ss_iflags &= ~ISCAN_RUNNING;
scan_end(ss, scandone);
return;
@@ -686,7 +686,7 @@ end:
/*
* Watch for truncation due to the scan end time.
*/
- if (time_after(ticks + ss->ss_maxdwell, ss_priv->ss_scanend))
+ if (ieee80211_time_after(ticks + ss->ss_maxdwell, ss_priv->ss_scanend))
maxdwell = ss_priv->ss_scanend - ticks;
else
maxdwell = ss->ss_maxdwell;
@@ -807,7 +807,7 @@ scan_end(struct ieee80211_scan_state *ss, int scandone)
if ((ss_priv->ss_iflags & ISCAN_CANCEL) == 0 &&
!ss->ss_ops->scan_end(ss, vap) &&
(ss->ss_flags & IEEE80211_SCAN_ONCE) == 0 &&
- time_before(ticks + ss->ss_mindwell, ss_priv->ss_scanend)) {
+ ieee80211_time_before(ticks + ss->ss_mindwell, ss_priv->ss_scanend)) {
IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
"%s: done, restart "
"[ticks %u, dwell min %lu scanend %lu]\n",
@@ -923,7 +923,7 @@ ieee80211_swscan_add_scan(struct ieee80211vap *vap,
* the timer so we'll switch to the next channel.
*/
if ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_MINDWELL) == 0 &&
- time_after_eq(ticks, SCAN_PRIVATE(ss)->ss_chanmindwell)) {
+ ieee80211_time_after_eq(ticks, SCAN_PRIVATE(ss)->ss_chanmindwell)) {
IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
"%s: chan %3d%c min dwell met (%u > %lu)\n",
__func__,
diff --git a/sys/net80211/ieee80211_sta.c b/sys/net80211/ieee80211_sta.c
index ee14ffd..16d801c 100644
--- a/sys/net80211/ieee80211_sta.c
+++ b/sys/net80211/ieee80211_sta.c
@@ -206,6 +206,24 @@ sta_authretry(struct ieee80211vap *vap, struct ieee80211_node *ni, int reason)
}
}
+static void
+sta_swbmiss_start(struct ieee80211vap *vap)
+{
+
+ if (vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS) {
+ /*
+ * Start s/w beacon miss timer for devices w/o
+ * hardware support. We fudge a bit here since
+ * we're doing this in software.
+ */
+ vap->iv_swbmiss_period = IEEE80211_TU_TO_TICKS(
+ 2 * vap->iv_bmissthreshold * vap->iv_bss->ni_intval);
+ vap->iv_swbmiss_count = 0;
+ callout_reset(&vap->iv_swbmiss, vap->iv_swbmiss_period,
+ ieee80211_swbmiss, vap);
+ }
+}
+
/*
* IEEE80211_M_STA vap state machine handler.
* This routine handles the main states in the 802.11 protocol.
@@ -341,12 +359,13 @@ sta_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
break;
}
break;
+ case IEEE80211_S_SLEEP:
case IEEE80211_S_RUN:
switch (arg & 0xff) {
case IEEE80211_FC0_SUBTYPE_AUTH:
IEEE80211_SEND_MGMT(ni,
IEEE80211_FC0_SUBTYPE_AUTH, 2);
- vap->iv_state = ostate; /* stay RUN */
+ vap->iv_state = IEEE80211_S_RUN; /* stay RUN */
break;
case IEEE80211_FC0_SUBTYPE_DEAUTH:
ieee80211_sta_leave(ni);
@@ -418,19 +437,8 @@ sta_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
goto invalid;
}
ieee80211_sync_curchan(ic);
- if (ostate != IEEE80211_S_RUN &&
- (vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS)) {
- /*
- * Start s/w beacon miss timer for devices w/o
- * hardware support. We fudge a bit here since
- * we're doing this in software.
- */
- vap->iv_swbmiss_period = IEEE80211_TU_TO_TICKS(
- 2 * vap->iv_bmissthreshold * ni->ni_intval);
- vap->iv_swbmiss_count = 0;
- callout_reset(&vap->iv_swbmiss, vap->iv_swbmiss_period,
- ieee80211_swbmiss, vap);
- }
+ if (ostate != IEEE80211_S_RUN)
+ sta_swbmiss_start(vap);
/*
* When 802.1x is not in use mark the port authorized
* at this point so traffic can flow.
@@ -450,6 +458,7 @@ sta_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
goto invalid;
break;
case IEEE80211_S_SLEEP:
+ sta_swbmiss_start(vap);
vap->iv_sta_ps(vap, 1);
break;
default:
@@ -1244,7 +1253,7 @@ contbgscan(struct ieee80211vap *vap)
return ((ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN) &&
(ic->ic_flags & IEEE80211_F_CSAPENDING) == 0 &&
vap->iv_state == IEEE80211_S_RUN && /* XXX? */
- time_after(ticks, ic->ic_lastdata + vap->iv_bgscanidle));
+ ieee80211_time_after(ticks, ic->ic_lastdata + vap->iv_bgscanidle));
}
/*
@@ -1265,8 +1274,8 @@ startbgscan(struct ieee80211vap *vap)
#ifdef IEEE80211_SUPPORT_SUPERG
!IEEE80211_IS_CHAN_DTURBO(ic->ic_curchan) &&
#endif
- time_after(ticks, ic->ic_lastscan + vap->iv_bgscanintvl) &&
- time_after(ticks, ic->ic_lastdata + vap->iv_bgscanidle));
+ ieee80211_time_after(ticks, ic->ic_lastscan + vap->iv_bgscanintvl) &&
+ ieee80211_time_after(ticks, ic->ic_lastdata + vap->iv_bgscanidle));
}
static void
diff --git a/sys/net80211/ieee80211_wds.c b/sys/net80211/ieee80211_wds.c
index 03d9c60..7fe91cc 100644
--- a/sys/net80211/ieee80211_wds.c
+++ b/sys/net80211/ieee80211_wds.c
@@ -288,9 +288,11 @@ ieee80211_dwds_mcast(struct ieee80211vap *vap0, struct mbuf *m)
/*
* Encapsulate the packet in prep for transmission.
*/
+ IEEE80211_TX_LOCK(ic);
mcopy = ieee80211_encap(vap, ni, mcopy);
if (mcopy == NULL) {
/* NB: stat+msg handled in ieee80211_encap */
+ IEEE80211_TX_UNLOCK(ic);
ieee80211_free_node(ni);
continue;
}
@@ -298,6 +300,7 @@ ieee80211_dwds_mcast(struct ieee80211vap *vap0, struct mbuf *m)
mcopy->m_pkthdr.rcvif = (void *) ni;
err = ieee80211_parent_xmitpkt(ic, mcopy);
+ IEEE80211_TX_UNLOCK(ic);
if (!err) {
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
if_inc_counter(ifp, IFCOUNTER_OMCASTS, 1);
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index ec42e67..50e5d6e 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -1298,6 +1298,11 @@ in_pcbfree(struct inpcb *inp)
if (inp->inp_moptions != NULL)
inp_freemoptions(inp->inp_moptions);
#endif
+ if (inp->inp_route.ro_rt) {
+ RTFREE(inp->inp_route.ro_rt);
+ inp->inp_route.ro_rt = (struct rtentry *)NULL;
+ }
+
inp->inp_vflag = 0;
inp->inp_flags2 |= INP_FREED;
crfree(inp->inp_cred);
@@ -2225,6 +2230,23 @@ in_pcbremlists(struct inpcb *inp)
}
/*
+ * Check for alternatives when higher level complains
+ * about service problems. For now, invalidate cached
+ * routing information. If the route was created dynamically
+ * (by a redirect), time to try a default gateway again.
+ */
+void
+in_losing(struct inpcb *inp)
+{
+
+ if (inp->inp_route.ro_rt) {
+ RTFREE(inp->inp_route.ro_rt);
+ inp->inp_route.ro_rt = (struct rtentry *)NULL;
+ }
+ return;
+}
+
+/*
* A set label operation has occurred at the socket layer, propagate the
* label change into the in_pcb for the socket.
*/
diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h
index 54eab88..9c77a51 100644
--- a/sys/netinet/in_pcb.h
+++ b/sys/netinet/in_pcb.h
@@ -42,6 +42,7 @@
#include <sys/_lock.h>
#include <sys/_mutex.h>
#include <sys/_rwlock.h>
+#include <net/route.h>
#ifdef _KERNEL
#include <sys/lock.h>
@@ -238,8 +239,14 @@ struct inpcb {
#define inp_zero_size offsetof(struct inpcb, inp_gencnt)
inp_gen_t inp_gencnt; /* (c) generation count */
struct llentry *inp_lle; /* cached L2 information */
- struct rtentry *inp_rt; /* cached L3 information */
struct rwlock inp_lock;
+ rt_gen_t inp_rt_cookie; /* generation for route entry */
+ union { /* cached L3 information */
+ struct route inpu_route;
+ struct route_in6 inpu_route6;
+ } inp_rtu;
+#define inp_route inp_rtu.inpu_route
+#define inp_route6 inp_rtu.inpu_route6
};
#define inp_fport inp_inc.inc_fport
#define inp_lport inp_inc.inc_lport
@@ -722,6 +729,7 @@ 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 *);
+void in_losing(struct inpcb *);
void in_pcbsetsolabel(struct socket *so);
int in_getpeeraddr(struct socket *so, struct sockaddr **nam);
int in_getsockaddr(struct socket *so, struct sockaddr **nam);
diff --git a/sys/netinet/in_pcbgroup.c b/sys/netinet/in_pcbgroup.c
index 2d3c136..04a7699 100644
--- a/sys/netinet/in_pcbgroup.c
+++ b/sys/netinet/in_pcbgroup.c
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mbuf.h>
#include <sys/mutex.h>
#include <sys/smp.h>
+#include <sys/socket.h>
#include <sys/socketvar.h>
#include <net/rss_config.h>
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index fa225fc..afdf1a7 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -282,17 +282,36 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
gw = dst = (struct sockaddr_in *)&ro->ro_dst;
fibnum = (inp != NULL) ? inp->inp_inc.inc_fibnum : M_GETFIB(m);
rte = ro->ro_rt;
- /*
- * The address family should also be checked in case of sharing
- * the cache with IPv6.
- */
- if (rte == NULL || dst->sin_family != AF_INET) {
+ if (rte == NULL) {
bzero(dst, sizeof(*dst));
dst->sin_family = AF_INET;
dst->sin_len = sizeof(*dst);
dst->sin_addr = ip->ip_dst;
}
again:
+ /*
+ * Validate route against routing table additions;
+ * a better/more specific route might have been added.
+ */
+ if (inp)
+ RT_VALIDATE(ro, &inp->inp_rt_cookie, fibnum);
+ /*
+ * If there is a cached route,
+ * check that it is to the same destination
+ * and is still up. If not, free it and try again.
+ * The address family should also be checked in case of sharing the
+ * cache with IPv6.
+ * Also check whether routing cache needs invalidation.
+ */
+ rte = ro->ro_rt;
+ if (rte && ((rte->rt_flags & RTF_UP) == 0 ||
+ rte->rt_ifp == NULL ||
+ !RT_LINK_IS_UP(rte->rt_ifp) ||
+ dst->sin_family != AF_INET ||
+ dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
+ RTFREE(rte);
+ rte = ro->ro_rt = (struct rtentry *)NULL;
+ }
ia = NULL;
have_ia_ref = 0;
/*
diff --git a/sys/netinet/sctp_cc_functions.c b/sys/netinet/sctp_cc_functions.c
index 0bddcfd..0ad3e33 100644
--- a/sys/netinet/sctp_cc_functions.c
+++ b/sys/netinet/sctp_cc_functions.c
@@ -1526,13 +1526,13 @@ sctp_rtt_rtcc_calculated(struct sctp_tcb *stcb SCTP_UNUSED,
struct sctp_hs_raise_drop {
int32_t cwnd;
- int32_t increase;
- int32_t drop_percent;
+ int8_t increase;
+ int8_t drop_percent;
};
#define SCTP_HS_TABLE_SIZE 73
-struct sctp_hs_raise_drop sctp_cwnd_adjust[SCTP_HS_TABLE_SIZE] = {
+static const struct sctp_hs_raise_drop sctp_cwnd_adjust[SCTP_HS_TABLE_SIZE] = {
{38, 1, 50}, /* 0 */
{118, 2, 44}, /* 1 */
{221, 3, 41}, /* 2 */
@@ -1632,7 +1632,7 @@ sctp_hs_cwnd_increase(struct sctp_tcb *stcb, struct sctp_nets *net)
}
}
net->last_hs_used = indx;
- incr = ((sctp_cwnd_adjust[indx].increase) << 10);
+ incr = (((int32_t) sctp_cwnd_adjust[indx].increase) << 10);
net->cwnd += incr;
}
sctp_enforce_cwnd_limit(&stcb->asoc, net);
@@ -1658,7 +1658,7 @@ sctp_hs_cwnd_decrease(struct sctp_tcb *stcb, struct sctp_nets *net)
} else {
/* drop by the proper amount */
net->ssthresh = net->cwnd - (int)((net->cwnd / 100) *
- sctp_cwnd_adjust[net->last_hs_used].drop_percent);
+ (int32_t) sctp_cwnd_adjust[net->last_hs_used].drop_percent);
net->cwnd = net->ssthresh;
/* now where are we */
indx = net->last_hs_used;
@@ -2323,7 +2323,7 @@ sctp_htcp_cwnd_update_after_ecn_echo(struct sctp_tcb *stcb,
}
}
-struct sctp_cc_functions sctp_cc_functions[] = {
+const struct sctp_cc_functions sctp_cc_functions[] = {
{
.sctp_set_initial_cc_param = sctp_set_initial_cc_param,
.sctp_cwnd_update_after_sack = sctp_cwnd_update_after_sack,
diff --git a/sys/netinet/sctp_constants.h b/sys/netinet/sctp_constants.h
index 5837f6f..497dde6 100644
--- a/sys/netinet/sctp_constants.h
+++ b/sys/netinet/sctp_constants.h
@@ -68,6 +68,8 @@ __FBSDID("$FreeBSD$");
/* Largest length of a chunk */
#define SCTP_MAX_CHUNK_LENGTH 0xffff
+/* Largest length of an error cause */
+#define SCTP_MAX_CAUSE_LENGTH 0xffff
/* Number of addresses where we just skip the counting */
#define SCTP_COUNT_LIMIT 40
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c
index 75c1ac5..cbc7fb5 100644
--- a/sys/netinet/sctp_indata.c
+++ b/sys/netinet/sctp_indata.c
@@ -1948,7 +1948,7 @@ finish_express_del:
return (1);
}
-int8_t sctp_map_lookup_tab[256] = {
+static const int8_t sctp_map_lookup_tab[256] = {
0, 1, 0, 2, 0, 1, 0, 3,
0, 1, 0, 2, 0, 1, 0, 4,
0, 1, 0, 2, 0, 1, 0, 3,
@@ -2495,7 +2495,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
if (op_err != NULL) {
cause = mtod(op_err, struct sctp_gen_error_cause *);
cause->code = htons(SCTP_CAUSE_UNRECOG_CHUNK);
- cause->length = htons(chk_length + sizeof(struct sctp_gen_error_cause));
+ cause->length = htons((uint16_t) (chk_length + sizeof(struct sctp_gen_error_cause)));
SCTP_BUF_LEN(op_err) = sizeof(struct sctp_gen_error_cause);
SCTP_BUF_NEXT(op_err) = SCTP_M_COPYM(m, *offset, chk_length, M_NOWAIT);
if (SCTP_BUF_NEXT(op_err) != NULL) {
@@ -2688,7 +2688,7 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_GAP,
tp1->whoTo->flight_size,
tp1->book_size,
- (uintptr_t) tp1->whoTo,
+ (uint32_t) (uintptr_t) tp1->whoTo,
tp1->rec.data.TSN_seq);
}
sctp_flight_size_decrease(tp1);
@@ -2897,7 +2897,7 @@ sctp_check_for_revoked(struct sctp_tcb *stcb,
sctp_misc_ints(SCTP_FLIGHT_LOG_UP_REVOKE,
tp1->whoTo->flight_size,
tp1->book_size,
- (uintptr_t) tp1->whoTo,
+ (uint32_t) (uintptr_t) tp1->whoTo,
tp1->rec.data.TSN_seq);
}
sctp_flight_size_increase(tp1);
@@ -3211,7 +3211,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_RSND,
(tp1->whoTo ? (tp1->whoTo->flight_size) : 0),
tp1->book_size,
- (uintptr_t) tp1->whoTo,
+ (uint32_t) (uintptr_t) tp1->whoTo,
tp1->rec.data.TSN_seq);
}
if (tp1->whoTo) {
@@ -3523,7 +3523,7 @@ sctp_window_probe_recovery(struct sctp_tcb *stcb,
sctp_misc_ints(SCTP_FLIGHT_LOG_DWN_WP_FWD,
tp1->whoTo ? tp1->whoTo->flight_size : 0,
tp1->book_size,
- (uintptr_t) tp1->whoTo,
+ (uint32_t) (uintptr_t) tp1->whoTo,
tp1->rec.data.TSN_seq);
return;
}
@@ -3542,7 +3542,7 @@ sctp_window_probe_recovery(struct sctp_tcb *stcb,
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_WP,
tp1->whoTo->flight_size,
tp1->book_size,
- (uintptr_t) tp1->whoTo,
+ (uint32_t) (uintptr_t) tp1->whoTo,
tp1->rec.data.TSN_seq);
}
}
@@ -3661,7 +3661,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_CA,
tp1->whoTo->flight_size,
tp1->book_size,
- (uintptr_t) tp1->whoTo,
+ (uint32_t) (uintptr_t) tp1->whoTo,
tp1->rec.data.TSN_seq);
}
sctp_flight_size_decrease(tp1);
@@ -4302,7 +4302,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_CA,
tp1->whoTo->flight_size,
tp1->book_size,
- (uintptr_t) tp1->whoTo,
+ (uint32_t) (uintptr_t) tp1->whoTo,
tp1->rec.data.TSN_seq);
}
sctp_flight_size_decrease(tp1);
@@ -4575,7 +4575,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
sctp_misc_ints(SCTP_FLIGHT_LOG_UP_REVOKE,
tp1->whoTo->flight_size,
tp1->book_size,
- (uintptr_t) tp1->whoTo,
+ (uint32_t) (uintptr_t) tp1->whoTo,
tp1->rec.data.TSN_seq);
}
sctp_flight_size_increase(tp1);
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index a205f2f..c555be2 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -2358,7 +2358,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
SCTP_RTT_FROM_NON_DATA);
#if defined(INET) || defined(INET6)
if (((*netp)->port == 0) && (port != 0)) {
- sctp_pathmtu_adjustment(stcb, (*netp)->mtu - sizeof(struct udphdr));
+ sctp_pathmtu_adjustment(stcb, (uint16_t) ((*netp)->mtu - sizeof(struct udphdr)));
}
(*netp)->port = port;
#endif
@@ -3339,7 +3339,7 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc,
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PDRP,
tp1->whoTo->flight_size,
tp1->book_size,
- (uintptr_t) stcb,
+ (uint32_t) (uintptr_t) stcb,
tp1->rec.data.TSN_seq);
}
if (tp1->sent < SCTP_DATAGRAM_RESEND) {
@@ -5596,7 +5596,7 @@ process_control_chunks:
len = min(SCTP_SIZE32(chk_length), (uint32_t) (length - *offset));
cause = mtod(op_err, struct sctp_gen_error_cause *);
cause->code = htons(SCTP_CAUSE_UNRECOG_CHUNK);
- cause->length = htons(len + sizeof(struct sctp_gen_error_cause));
+ cause->length = htons((uint16_t) (len + sizeof(struct sctp_gen_error_cause)));
SCTP_BUF_LEN(op_err) = sizeof(struct sctp_gen_error_cause);
SCTP_BUF_NEXT(op_err) = SCTP_M_COPYM(m, *offset, len, M_NOWAIT);
if (SCTP_BUF_NEXT(op_err) != NULL) {
@@ -6033,7 +6033,9 @@ trigger_send:
if (!TAILQ_EMPTY(&stcb->asoc.control_send_queue)) {
cnt_ctrl_ready = stcb->asoc.ctrl_queue_cnt - stcb->asoc.ecn_echo_cnt_onq;
}
- if (cnt_ctrl_ready || stcb->asoc.trigger_reset ||
+ if (!TAILQ_EMPTY(&stcb->asoc.asconf_send_queue) ||
+ cnt_ctrl_ready ||
+ stcb->asoc.trigger_reset ||
((un_sent) &&
(stcb->asoc.peers_rwnd > 0 ||
(stcb->asoc.peers_rwnd <= 0 && stcb->asoc.total_flight == 0)))) {
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index a900106..8eda473 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -67,7 +67,7 @@ struct sack_track {
struct sctp_gap_ack_block gaps[SCTP_MAX_GAPS_INARRAY];
};
-struct sack_track sack_array[256] = {
+const struct sack_track sack_array[256] = {
{0, 0, 0, 0, /* 0x00 */
{{0, 0},
{0, 0},
@@ -3508,7 +3508,7 @@ sctp_find_cmsg(int c_type, void *data, struct mbuf *control, size_t cpsize)
return (found);
}
/* It is exactly what we want. Copy it out. */
- m_copydata(control, at + CMSG_ALIGN(sizeof(cmh)), cpsize, (caddr_t)data);
+ m_copydata(control, at + CMSG_ALIGN(sizeof(cmh)), (int)cpsize, (caddr_t)data);
return (1);
} else {
struct sctp_sndrcvinfo *sndrcvinfo;
@@ -4186,7 +4186,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
udp = (struct udphdr *)((caddr_t)ip + sizeof(struct ip));
udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
udp->uh_dport = port;
- udp->uh_ulen = htons(packet_length - sizeof(struct ip));
+ udp->uh_ulen = htons((uint16_t) (packet_length - sizeof(struct ip)));
if (V_udp_cksum) {
udp->uh_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, udp->uh_ulen + htons(IPPROTO_UDP));
} else {
@@ -4414,7 +4414,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
} else {
ip6h->ip6_nxt = IPPROTO_SCTP;
}
- ip6h->ip6_plen = (packet_length - sizeof(struct ip6_hdr));
+ ip6h->ip6_plen = (uint16_t) (packet_length - sizeof(struct ip6_hdr));
ip6h->ip6_dst = sin6->sin6_addr;
/*
@@ -4533,7 +4533,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
udp = (struct udphdr *)((caddr_t)ip6h + sizeof(struct ip6_hdr));
udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
udp->uh_dport = port;
- udp->uh_ulen = htons(packet_length - sizeof(struct ip6_hdr));
+ udp->uh_ulen = htons((uint16_t) (packet_length - sizeof(struct ip6_hdr)));
udp->uh_sum = 0;
sctphdr = (struct sctphdr *)((caddr_t)udp + sizeof(struct udphdr));
} else {
@@ -6479,10 +6479,10 @@ error_out:
}
}
/* get the new end of length */
- len = M_TRAILINGSPACE(*endofchain);
+ len = (int)M_TRAILINGSPACE(*endofchain);
} else {
/* how much is left at the end? */
- len = M_TRAILINGSPACE(*endofchain);
+ len = (int)M_TRAILINGSPACE(*endofchain);
}
/* Find the end of the data, for appending */
cp = (mtod((*endofchain), caddr_t)+SCTP_BUF_LEN((*endofchain)));
@@ -6636,7 +6636,7 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
ph = mtod(m, struct sctp_paramhdr *);
ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
- ph->param_length = htons(sizeof(struct sctp_paramhdr) + ca->sndlen);
+ ph->param_length = htons((uint16_t) (sizeof(struct sctp_paramhdr) + ca->sndlen));
}
/*
* We add one here to keep the assoc from dis-appearing on
@@ -6814,7 +6814,7 @@ sctp_copy_out_all(struct uio *uio, int len)
left = len;
SCTP_BUF_LEN(ret) = 0;
/* save space for the data chunk header */
- cancpy = M_TRAILINGSPACE(ret);
+ cancpy = (int)M_TRAILINGSPACE(ret);
willcpy = min(cancpy, left);
at = ret;
while (left > 0) {
@@ -6835,7 +6835,7 @@ sctp_copy_out_all(struct uio *uio, int len)
}
at = SCTP_BUF_NEXT(at);
SCTP_BUF_LEN(at) = 0;
- cancpy = M_TRAILINGSPACE(at);
+ cancpy = (int)M_TRAILINGSPACE(at);
willcpy = min(cancpy, left);
}
}
@@ -6869,7 +6869,7 @@ sctp_sendall(struct sctp_inpcb *inp, struct uio *uio, struct mbuf *m,
ca->sndrcv.sinfo_flags &= ~SCTP_SENDALL;
/* get length and mbuf chain */
if (uio) {
- ca->sndlen = uio->uio_resid;
+ ca->sndlen = (int)uio->uio_resid;
ca->m = sctp_copy_out_all(uio, ca->sndlen);
if (ca->m == NULL) {
SCTP_FREE(ca, SCTP_M_COPYAL);
@@ -7019,7 +7019,7 @@ all_done:
sctp_misc_ints(SCTP_FLIGHT_LOG_UP,
data_list[i]->whoTo->flight_size,
data_list[i]->book_size,
- (uintptr_t) data_list[i]->whoTo,
+ (uint32_t) (uintptr_t) data_list[i]->whoTo,
data_list[i]->rec.data.TSN_seq);
}
sctp_flight_size_increase(data_list[i]);
@@ -7516,7 +7516,7 @@ dont_do_it:
goto out_of;
}
sctp_snd_sb_alloc(stcb, sizeof(struct sctp_data_chunk));
- chk->book_size = chk->send_size = (to_move + sizeof(struct sctp_data_chunk));
+ chk->book_size = chk->send_size = (uint16_t) (to_move + sizeof(struct sctp_data_chunk));
chk->book_size_scale = 0;
chk->sent = SCTP_DATAGRAM_UNSENT;
@@ -7551,7 +7551,7 @@ dont_do_it:
chk->rec.data.TSN_seq = atomic_fetchadd_int(&asoc->sending_seq, 1);
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_AT_SEND_2_OUTQ) {
sctp_misc_ints(SCTP_STRMOUT_LOG_SEND,
- (uintptr_t) stcb, sp->length,
+ (uint32_t) (uintptr_t) stcb, sp->length,
(uint32_t) ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq),
chk->rec.data.TSN_seq);
}
@@ -8943,6 +8943,8 @@ sctp_queue_op_err(struct sctp_tcb *stcb, struct mbuf *op_err)
chk->asoc = &stcb->asoc;
chk->data = op_err;
chk->whoTo = NULL;
+ chk->rec.chunk_id.id = SCTP_OPERATION_ERROR;
+ chk->rec.chunk_id.can_take_data = 0;
hdr = mtod(op_err, struct sctp_chunkhdr *);
hdr->chunk_type = SCTP_OPERATION_ERROR;
hdr->chunk_flags = 0;
@@ -9827,7 +9829,7 @@ one_chunk_around:
sctp_misc_ints(SCTP_FLIGHT_LOG_UP_RSND,
data_list[i]->whoTo->flight_size,
data_list[i]->book_size,
- (uintptr_t) data_list[i]->whoTo,
+ (uint32_t) (uintptr_t) data_list[i]->whoTo,
data_list[i]->rec.data.TSN_seq);
}
sctp_flight_size_increase(data_list[i]);
@@ -10288,7 +10290,7 @@ sctp_fill_in_rest:
space_needed = (sizeof(struct sctp_forward_tsn_chunk) +
(cnt_of_skipped * sizeof(struct sctp_strseq)));
- cnt_of_space = M_TRAILINGSPACE(chk->data);
+ cnt_of_space = (unsigned int)M_TRAILINGSPACE(chk->data);
if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
ovh = SCTP_MIN_OVERHEAD;
@@ -10414,7 +10416,7 @@ sctp_send_sack(struct sctp_tcb *stcb, int so_locked
struct sctp_sack_chunk *sack;
struct sctp_nr_sack_chunk *nr_sack;
struct sctp_gap_ack_block *gap_descriptor;
- struct sack_track *selector;
+ const struct sack_track *selector;
int mergeable = 0;
int offset;
caddr_t limit;
@@ -10546,7 +10548,7 @@ sctp_send_sack(struct sctp_tcb *stcb, int so_locked
}
/* ok, lets go through and fill it in */
SCTP_BUF_RESV_UF(a_chk->data, SCTP_MIN_OVERHEAD);
- space = M_TRAILINGSPACE(a_chk->data);
+ space = (unsigned int)M_TRAILINGSPACE(a_chk->data);
if (space > (a_chk->whoTo->mtu - SCTP_MIN_OVERHEAD)) {
space = (a_chk->whoTo->mtu - SCTP_MIN_OVERHEAD);
}
@@ -10760,9 +10762,9 @@ sctp_send_sack(struct sctp_tcb *stcb, int so_locked
* queue.
*/
if (type == SCTP_SELECTIVE_ACK) {
- a_chk->send_size = sizeof(struct sctp_sack_chunk) +
+ a_chk->send_size = (uint16_t) (sizeof(struct sctp_sack_chunk) +
(num_gap_blocks + num_nr_gap_blocks) * sizeof(struct sctp_gap_ack_block) +
- num_dups * sizeof(int32_t);
+ num_dups * sizeof(int32_t));
SCTP_BUF_LEN(a_chk->data) = a_chk->send_size;
sack->sack.cum_tsn_ack = htonl(asoc->cumulative_tsn);
sack->sack.a_rwnd = htonl(asoc->my_rwnd);
@@ -10772,9 +10774,9 @@ sctp_send_sack(struct sctp_tcb *stcb, int so_locked
sack->ch.chunk_flags = flags;
sack->ch.chunk_length = htons(a_chk->send_size);
} else {
- a_chk->send_size = sizeof(struct sctp_nr_sack_chunk) +
+ a_chk->send_size = (uint16_t) (sizeof(struct sctp_nr_sack_chunk) +
(num_gap_blocks + num_nr_gap_blocks) * sizeof(struct sctp_gap_ack_block) +
- num_dups * sizeof(int32_t);
+ num_dups * sizeof(int32_t));
SCTP_BUF_LEN(a_chk->data) = a_chk->send_size;
nr_sack->nr_sack.cum_tsn_ack = htonl(asoc->cumulative_tsn);
nr_sack->nr_sack.a_rwnd = htonl(asoc->my_rwnd);
@@ -11082,10 +11084,10 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst,
udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
udp->uh_dport = port;
udp->uh_sum = 0;
- udp->uh_ulen = htons(sizeof(struct udphdr) +
+ udp->uh_ulen = htons((uint16_t) (sizeof(struct udphdr) +
sizeof(struct sctphdr) +
sizeof(struct sctp_chunkhdr) +
- cause_len + padding_len);
+ cause_len + padding_len));
len += sizeof(struct udphdr);
shout = (struct sctphdr *)((caddr_t)shout + sizeof(struct udphdr));
} else {
@@ -11108,7 +11110,7 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst,
} else {
ch->chunk_flags = SCTP_HAD_NO_TCB;
}
- ch->chunk_length = htons(sizeof(struct sctp_chunkhdr) + cause_len);
+ ch->chunk_length = htons((uint16_t) (sizeof(struct sctp_chunkhdr) + cause_len));
len += sizeof(struct sctp_chunkhdr);
len += cause_len + padding_len;
@@ -11157,7 +11159,7 @@ sctp_send_resp_msg(struct sockaddr *src, struct sockaddr *dst,
#endif
#ifdef INET6
case AF_INET6:
- ip6->ip6_plen = len - sizeof(struct ip6_hdr);
+ ip6->ip6_plen = (uint16_t) (len - sizeof(struct ip6_hdr));
if (port) {
#if defined(SCTP_WITH_NO_CSUM)
SCTP_STAT_INCR(sctps_sendnocrc);
@@ -11484,7 +11486,7 @@ jump_out:
* Len is already adjusted to size minus overhead above take
* out the pkt_drop chunk itself from it.
*/
- chk->send_size = len - sizeof(struct sctp_pktdrop_chunk);
+ chk->send_size = (uint16_t) (len - sizeof(struct sctp_pktdrop_chunk));
len = chk->send_size;
} else {
/* no truncation needed */
@@ -11624,7 +11626,7 @@ sctp_add_stream_reset_out(struct sctp_tcb *stcb, struct sctp_tmit_chunk *chk,
if (number_entries > SCTP_MAX_STREAMS_AT_ONCE_RESET) {
number_entries = SCTP_MAX_STREAMS_AT_ONCE_RESET;
}
- len = (sizeof(struct sctp_stream_reset_out_request) + (sizeof(uint16_t) * number_entries));
+ len = (uint16_t) (sizeof(struct sctp_stream_reset_out_request) + (sizeof(uint16_t) * number_entries));
req_out->ph.param_type = htons(SCTP_STR_RESET_OUT_REQUEST);
req_out->ph.param_length = htons(len);
req_out->request_seq = htonl(seq);
@@ -11681,7 +11683,7 @@ sctp_add_stream_reset_in(struct sctp_tmit_chunk *chk,
/* get to new offset for the param. */
req_in = (struct sctp_stream_reset_in_request *)((caddr_t)ch + len);
/* now how long will this param be? */
- len = (sizeof(struct sctp_stream_reset_in_request) + (sizeof(uint16_t) * number_entries));
+ len = (uint16_t) (sizeof(struct sctp_stream_reset_in_request) + (sizeof(uint16_t) * number_entries));
req_in->ph.param_type = htons(SCTP_STR_RESET_IN_REQUEST);
req_in->ph.param_length = htons(len);
req_in->request_seq = htonl(seq);
@@ -12313,7 +12315,7 @@ sctp_copy_it_in(struct sctp_tcb *stcb,
(void)SCTP_GETTIME_TIMEVAL(&sp->ts);
sp->stream = srcv->sinfo_stream;
- sp->length = min(uio->uio_resid, max_send_len);
+ sp->length = (uint32_t) min(uio->uio_resid, max_send_len);
if ((sp->length == (uint32_t) uio->uio_resid) &&
((user_marks_eor == 0) ||
(srcv->sinfo_flags & SCTP_EOF) ||
@@ -12472,7 +12474,7 @@ sctp_lower_sosend(struct socket *so,
SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
return (EINVAL);
}
- sndlen = uio->uio_resid;
+ sndlen = (unsigned int)uio->uio_resid;
} else {
top = SCTP_HEADER_TO_CHAIN(i_pak);
sndlen = SCTP_HEADER_LEN(i_pak);
@@ -12871,7 +12873,7 @@ sctp_lower_sosend(struct socket *so,
/* now move forward the data pointer */
ph = mtod(mm, struct sctp_paramhdr *);
ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
- ph->param_length = htons(sizeof(struct sctp_paramhdr) + tot_out);
+ ph->param_length = htons((uint16_t) (sizeof(struct sctp_paramhdr) + tot_out));
ph++;
SCTP_BUF_LEN(mm) = tot_out + sizeof(struct sctp_paramhdr);
if (top == NULL) {
@@ -13291,7 +13293,7 @@ skip_preblock:
min(SCTP_BASE_SYSCTL(sctp_add_more_threshold), SCTP_SB_LIMIT_SND(so)))) {
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_BLK_LOGGING_ENABLE) {
sctp_log_block(SCTP_BLOCK_LOG_INTO_BLK,
- asoc, uio->uio_resid);
+ asoc, (size_t)uio->uio_resid);
}
be.error = 0;
stcb->block_entry = &be;
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index 7e3218d..12aa145 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -5357,6 +5357,7 @@ void
sctp_add_local_addr_ep(struct sctp_inpcb *inp, struct sctp_ifa *ifa, uint32_t action)
{
struct sctp_laddr *laddr;
+ struct sctp_tcb *stcb;
int fnd, error = 0;
fnd = 0;
@@ -5402,6 +5403,9 @@ sctp_add_local_addr_ep(struct sctp_inpcb *inp, struct sctp_ifa *ifa, uint32_t ac
default:
break;
}
+ LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
+ sctp_add_local_addr_restricted(stcb, ifa);
+ }
}
return;
}
diff --git a/sys/netinet/sctp_ss_functions.c b/sys/netinet/sctp_ss_functions.c
index a2568ad..c4cbb05 100644
--- a/sys/netinet/sctp_ss_functions.c
+++ b/sys/netinet/sctp_ss_functions.c
@@ -822,7 +822,7 @@ default_again:
return (strq);
}
-struct sctp_ss_functions sctp_ss_functions[] = {
+const struct sctp_ss_functions sctp_ss_functions[] = {
/* SCTP_SS_DEFAULT */
{
.sctp_ss_init = sctp_ss_default_init,
diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c
index dec02de..9fa37e7 100644
--- a/sys/netinet/sctp_timer.c
+++ b/sys/netinet/sctp_timer.c
@@ -662,7 +662,7 @@ start_again:
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_RSND_TO,
chk->whoTo->flight_size,
chk->book_size,
- (uintptr_t) chk->whoTo,
+ (uint32_t) (uintptr_t) chk->whoTo,
chk->rec.data.TSN_seq);
}
sctp_flight_size_decrease(chk);
@@ -790,7 +790,7 @@ start_again:
sctp_misc_ints(SCTP_FLIGHT_LOG_UP,
chk->whoTo->flight_size,
chk->book_size,
- (uintptr_t) chk->whoTo,
+ (uint32_t) (uintptr_t) chk->whoTo,
chk->rec.data.TSN_seq);
}
sctp_flight_size_increase(chk);
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
index d11bf20..a75f025 100644
--- a/sys/netinet/sctp_usrreq.c
+++ b/sys/netinet/sctp_usrreq.c
@@ -54,8 +54,8 @@ __FBSDID("$FreeBSD$");
-extern struct sctp_cc_functions sctp_cc_functions[];
-extern struct sctp_ss_functions sctp_ss_functions[];
+extern const struct sctp_cc_functions sctp_cc_functions[];
+extern const struct sctp_ss_functions sctp_ss_functions[];
void
sctp_init(void)
@@ -132,7 +132,7 @@ sctp_pathmtu_adjustment(struct sctp_tcb *stcb, uint16_t nxtsz)
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PMTU,
chk->whoTo->flight_size,
chk->book_size,
- (uintptr_t) chk->whoTo,
+ (uint32_t) (uintptr_t) chk->whoTo,
chk->rec.data.TSN_seq);
}
/* Clear any time so NO RTT is being done */
@@ -1413,7 +1413,7 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
int creat_lock_on = 0;
struct sctp_tcb *stcb = NULL;
struct sockaddr *sa;
- int num_v6 = 0, num_v4 = 0, *totaddrp, totaddr;
+ unsigned int num_v6 = 0, num_v4 = 0, *totaddrp, totaddr;
uint32_t vrf_id;
int bad_addresses = 0;
sctp_assoc_t *a_id;
@@ -1449,10 +1449,10 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
error = EFAULT;
goto out_now;
}
- totaddrp = (int *)optval;
+ totaddrp = (unsigned int *)optval;
totaddr = *totaddrp;
sa = (struct sockaddr *)(totaddrp + 1);
- stcb = sctp_connectx_helper_find(inp, sa, &totaddr, &num_v4, &num_v6, &error, (optsize - sizeof(int)), &bad_addresses);
+ stcb = sctp_connectx_helper_find(inp, sa, &totaddr, &num_v4, &num_v6, &error, (unsigned int)(optsize - sizeof(int)), &bad_addresses);
if ((stcb != NULL) || bad_addresses) {
/* Already have or am bring up an association */
SCTP_ASOC_CREATE_UNLOCK(inp);
@@ -1903,7 +1903,8 @@ flags_out:
case SCTP_GET_ASSOC_ID_LIST:
{
struct sctp_assoc_ids *ids;
- unsigned int at, limit;
+ uint32_t at;
+ size_t limit;
SCTP_CHECK_AND_CAST(ids, optval, struct sctp_assoc_ids, *optsize);
SCTP_INP_RLOCK(inp);
@@ -1919,6 +1920,11 @@ flags_out:
LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
if (at < limit) {
ids->gaids_assoc_id[at++] = sctp_get_associd(stcb);
+ if (at == 0) {
+ error = EINVAL;
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
+ break;
+ }
} else {
error = EINVAL;
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
@@ -5810,6 +5816,10 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
__func__);
continue;
}
+ if ((sctp_is_addr_restricted(stcb, laddr->ifa)) &&
+ (!sctp_is_addr_pending(stcb, laddr->ifa))) {
+ continue;
+ }
if (laddr->ifa == ifa) {
found = 1;
break;
@@ -5862,7 +5872,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
}
- sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED);
+ sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED);
out_of_it:
SCTP_TCB_UNLOCK(stcb);
} else {
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index 4115256..9434f06 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -58,8 +58,8 @@ __FBSDID("$FreeBSD$");
#define KTR_SCTP KTR_SUBSYS
#endif
-extern struct sctp_cc_functions sctp_cc_functions[];
-extern struct sctp_ss_functions sctp_ss_functions[];
+extern const struct sctp_cc_functions sctp_cc_functions[];
+extern const struct sctp_ss_functions sctp_ss_functions[];
void
sctp_sblog(struct sockbuf *sb, struct sctp_tcb *stcb, int from, int incr)
@@ -503,7 +503,7 @@ sctp_wakeup_log(struct sctp_tcb *stcb, uint32_t wake_cnt, int from)
}
void
-sctp_log_block(uint8_t from, struct sctp_association *asoc, int sendlen)
+sctp_log_block(uint8_t from, struct sctp_association *asoc, size_t sendlen)
{
struct sctp_cwnd_log sctp_clog;
@@ -513,7 +513,7 @@ sctp_log_block(uint8_t from, struct sctp_association *asoc, int sendlen)
sctp_clog.x.blk.stream_qcnt = (uint16_t) asoc->stream_queue_cnt;
sctp_clog.x.blk.chunks_on_oque = (uint16_t) asoc->chunks_on_out_queue;
sctp_clog.x.blk.flight_size = (uint16_t) (asoc->total_flight / 1024);
- sctp_clog.x.blk.sndlen = sendlen;
+ sctp_clog.x.blk.sndlen = (uint32_t) sendlen;
SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
SCTP_LOG_EVENT_BLOCK,
from,
@@ -2679,7 +2679,8 @@ sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb,
struct mbuf *m_notify;
struct sctp_assoc_change *sac;
struct sctp_queued_to_read *control;
- size_t notif_len, abort_len;
+ unsigned int notif_len;
+ uint16_t abort_len;
unsigned int i;
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
@@ -2691,7 +2692,7 @@ sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb,
return;
}
if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT)) {
- notif_len = sizeof(struct sctp_assoc_change);
+ notif_len = (unsigned int)sizeof(struct sctp_assoc_change);
if (abort != NULL) {
abort_len = ntohs(abort->ch.chunk_length);
} else {
@@ -2705,7 +2706,7 @@ sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb,
m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_NOWAIT, 1, MT_DATA);
if (m_notify == NULL) {
/* Retry with smaller value. */
- notif_len = sizeof(struct sctp_assoc_change);
+ notif_len = (unsigned int)sizeof(struct sctp_assoc_change);
m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_NOWAIT, 1, MT_DATA);
if (m_notify == NULL) {
goto set_error;
@@ -3570,7 +3571,8 @@ sctp_notify_remote_error(struct sctp_tcb *stcb, uint16_t error, struct sctp_erro
struct mbuf *m_notify;
struct sctp_remote_error *sre;
struct sctp_queued_to_read *control;
- size_t notif_len, chunk_len;
+ unsigned int notif_len;
+ uint16_t chunk_len;
if ((stcb == NULL) ||
sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVPEERERR)) {
@@ -3581,11 +3583,11 @@ sctp_notify_remote_error(struct sctp_tcb *stcb, uint16_t error, struct sctp_erro
} else {
chunk_len = 0;
}
- notif_len = sizeof(struct sctp_remote_error) + chunk_len;
+ notif_len = (unsigned int)(sizeof(struct sctp_remote_error) + chunk_len);
m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_NOWAIT, 1, MT_DATA);
if (m_notify == NULL) {
/* Retry with smaller value. */
- notif_len = sizeof(struct sctp_remote_error);
+ notif_len = (unsigned int)sizeof(struct sctp_remote_error);
m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_NOWAIT, 1, MT_DATA);
if (m_notify == NULL) {
return;
@@ -4739,19 +4741,23 @@ sctp_generate_cause(uint16_t code, char *info)
{
struct mbuf *m;
struct sctp_gen_error_cause *cause;
- size_t info_len, len;
+ size_t info_len;
+ uint16_t len;
if ((code == 0) || (info == NULL)) {
return (NULL);
}
info_len = strlen(info);
- len = sizeof(struct sctp_paramhdr) + info_len;
+ if (info_len > (SCTP_MAX_CAUSE_LENGTH - sizeof(struct sctp_paramhdr))) {
+ return (NULL);
+ }
+ len = (uint16_t) (sizeof(struct sctp_paramhdr) + info_len);
m = sctp_get_mbuf_for_msg(len, 0, M_NOWAIT, 1, MT_DATA);
if (m != NULL) {
SCTP_BUF_LEN(m) = len;
cause = mtod(m, struct sctp_gen_error_cause *);
cause->code = htons(code);
- cause->length = htons((uint16_t) len);
+ cause->length = htons(len);
memcpy(cause->info, info, info_len);
}
return (m);
@@ -4762,15 +4768,15 @@ sctp_generate_no_user_data_cause(uint32_t tsn)
{
struct mbuf *m;
struct sctp_error_no_user_data *no_user_data_cause;
- size_t len;
+ uint16_t len;
- len = sizeof(struct sctp_error_no_user_data);
+ len = (uint16_t) sizeof(struct sctp_error_no_user_data);
m = sctp_get_mbuf_for_msg(len, 0, M_NOWAIT, 1, MT_DATA);
if (m != NULL) {
SCTP_BUF_LEN(m) = len;
no_user_data_cause = mtod(m, struct sctp_error_no_user_data *);
no_user_data_cause->cause.code = htons(SCTP_CAUSE_NO_USER_DATA);
- no_user_data_cause->cause.length = htons((uint16_t) len);
+ no_user_data_cause->cause.length = htons(len);
no_user_data_cause->tsn = tsn; /* tsn is passed in as NBO */
}
return (m);
@@ -5295,7 +5301,7 @@ sctp_sorecvmsg(struct socket *so,
uint32_t rwnd_req = 0;
int hold_sblock = 0;
int hold_rlock = 0;
- int slen = 0;
+ ssize_t slen = 0;
uint32_t held_length = 0;
int sockbuf_lock = 0;
@@ -5340,11 +5346,11 @@ sctp_sorecvmsg(struct socket *so,
in_eeor_mode = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR);
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RECV_RWND_LOGGING_ENABLE) {
sctp_misc_ints(SCTP_SORECV_ENTER,
- rwnd_req, in_eeor_mode, so->so_rcv.sb_cc, uio->uio_resid);
+ rwnd_req, in_eeor_mode, so->so_rcv.sb_cc, (uint32_t) uio->uio_resid);
}
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RECV_RWND_LOGGING_ENABLE) {
sctp_misc_ints(SCTP_SORECV_ENTERPL,
- rwnd_req, block_allowed, so->so_rcv.sb_cc, uio->uio_resid);
+ rwnd_req, block_allowed, so->so_rcv.sb_cc, (uint32_t) uio->uio_resid);
}
error = sblock(&so->so_rcv, (block_allowed ? SBL_WAIT : 0));
if (error) {
@@ -6219,13 +6225,13 @@ out:
if (stcb) {
sctp_misc_ints(SCTP_SORECV_DONE,
freed_so_far,
- ((uio) ? (slen - uio->uio_resid) : slen),
+ (uint32_t) ((uio) ? (slen - uio->uio_resid) : slen),
stcb->asoc.my_rwnd,
so->so_rcv.sb_cc);
} else {
sctp_misc_ints(SCTP_SORECV_DONE,
freed_so_far,
- ((uio) ? (slen - uio->uio_resid) : slen),
+ (uint32_t) ((uio) ? (slen - uio->uio_resid) : slen),
0,
so->so_rcv.sb_cc);
}
@@ -6452,30 +6458,30 @@ out_now:
struct sctp_tcb *
sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr,
- int *totaddr, int *num_v4, int *num_v6, int *error,
- int limit, int *bad_addr)
+ unsigned int *totaddr,
+ unsigned int *num_v4, unsigned int *num_v6, int *error,
+ unsigned int limit, int *bad_addr)
{
struct sockaddr *sa;
struct sctp_tcb *stcb = NULL;
- size_t incr, at, i;
+ unsigned int incr, at, i;
at = incr = 0;
sa = addr;
-
*error = *num_v6 = *num_v4 = 0;
/* account and validate addresses */
- for (i = 0; i < (size_t)*totaddr; i++) {
+ for (i = 0; i < *totaddr; i++) {
switch (sa->sa_family) {
#ifdef INET
case AF_INET:
- (*num_v4) += 1;
- incr = sizeof(struct sockaddr_in);
if (sa->sa_len != incr) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
*error = EINVAL;
*bad_addr = 1;
return (NULL);
}
+ (*num_v4) += 1;
+ incr = (unsigned int)sizeof(struct sockaddr_in);
break;
#endif
#ifdef INET6
@@ -6491,14 +6497,14 @@ sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr,
*bad_addr = 1;
return (NULL);
}
- (*num_v6) += 1;
- incr = sizeof(struct sockaddr_in6);
if (sa->sa_len != incr) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
*error = EINVAL;
*bad_addr = 1;
return (NULL);
}
+ (*num_v6) += 1;
+ incr = (unsigned int)sizeof(struct sockaddr_in6);
break;
}
#endif
@@ -6507,7 +6513,7 @@ sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr,
/* we are done */
break;
}
- if (i == (size_t)*totaddr) {
+ if (i == *totaddr) {
break;
}
SCTP_INP_INCR_REF(inp);
@@ -6518,7 +6524,7 @@ sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr,
} else {
SCTP_INP_DECR_REF(inp);
}
- if ((at + incr) > (size_t)limit) {
+ if ((at + incr) > limit) {
*totaddr = i;
break;
}
diff --git a/sys/netinet/sctputil.h b/sys/netinet/sctputil.h
index 354d40e..2d32792 100644
--- a/sys/netinet/sctputil.h
+++ b/sys/netinet/sctputil.h
@@ -220,7 +220,8 @@ sctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr,
struct sctp_tcb *
sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr,
- int *totaddr, int *num_v4, int *num_v6, int *error, int limit, int *bad_addr);
+ unsigned int *totaddr, unsigned int *num_v4, unsigned int *num_v6,
+ int *error, unsigned int limit, int *bad_addr);
int sctp_is_there_an_abort_here(struct mbuf *, int, uint32_t *);
@@ -376,7 +377,7 @@ void sctp_log_closing(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int16_t loc
void sctp_log_lock(struct sctp_inpcb *inp, struct sctp_tcb *stcb, uint8_t from);
void sctp_log_maxburst(struct sctp_tcb *stcb, struct sctp_nets *, int, int, uint8_t);
-void sctp_log_block(uint8_t, struct sctp_association *, int);
+void sctp_log_block(uint8_t, struct sctp_association *, size_t);
void sctp_log_rwnd(uint8_t, uint32_t, uint32_t, uint32_t);
void sctp_log_rwnd_set(uint8_t, uint32_t, uint32_t, uint32_t, uint32_t);
int sctp_fill_stat_log(void *, size_t *);
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 102430d..7134ce4 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -235,16 +235,39 @@ VNET_DEFINE(struct inpcbhead, tcb);
VNET_DEFINE(struct inpcbinfo, tcbinfo);
/*
- * TCP statistics are stored in an "array" of counter(9)s.
+ * TCP statistics are stored in an array of counter(9)s, which size matches
+ * size of struct tcpstat. TCP running connection count is a regular array.
*/
VNET_PCPUSTAT_DEFINE(struct tcpstat, tcpstat);
-VNET_PCPUSTAT_SYSINIT(tcpstat);
SYSCTL_VNET_PCPUSTAT(_net_inet_tcp, TCPCTL_STATS, stats, struct tcpstat,
tcpstat, "TCP statistics (struct tcpstat, netinet/tcp_var.h)");
+VNET_DEFINE(counter_u64_t, tcps_states[TCP_NSTATES]);
+SYSCTL_COUNTER_U64_ARRAY(_net_inet_tcp, TCPCTL_STATES, states, CTLFLAG_RD |
+ CTLFLAG_VNET, &VNET_NAME(tcps_states)[0], TCP_NSTATES,
+ "TCP connection counts by TCP state");
+
+static void
+tcp_vnet_init(const void *unused)
+{
+
+ COUNTER_ARRAY_ALLOC(VNET(tcps_states), TCP_NSTATES, M_WAITOK);
+ VNET_PCPUSTAT_ALLOC(tcpstat, M_WAITOK);
+}
+VNET_SYSINIT(tcp_vnet_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
+ tcp_vnet_init, NULL);
#ifdef VIMAGE
-VNET_PCPUSTAT_SYSUNINIT(tcpstat);
+static void
+tcp_vnet_uninit(const void *unused)
+{
+
+ COUNTER_ARRAY_FREE(VNET(tcps_states), TCP_NSTATES);
+ VNET_PCPUSTAT_FREE(tcpstat);
+}
+VNET_SYSUNINIT(tcp_vnet_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
+ tcp_vnet_uninit, NULL);
#endif /* VIMAGE */
+
/*
* Kernel module interface for updating tcpstat. The argument is an index
* into tcpstat treated as an array.
diff --git a/sys/netinet/tcp_lro.c b/sys/netinet/tcp_lro.c
index 7067abe..bd323bf 100644
--- a/sys/netinet/tcp_lro.c
+++ b/sys/netinet/tcp_lro.c
@@ -67,6 +67,8 @@ static MALLOC_DEFINE(M_LRO, "LRO", "LRO control structures");
#define TCP_LRO_INVALID_CSUM 0x0000
#endif
+static void tcp_lro_rx_done(struct lro_ctrl *lc);
+
int
tcp_lro_init(struct lro_ctrl *lc)
{
@@ -91,8 +93,8 @@ tcp_lro_init_args(struct lro_ctrl *lc, struct ifnet *ifp,
lc->lro_ackcnt_lim = TCP_LRO_ACKCNT_MAX;
lc->lro_length_lim = TCP_LRO_LENGTH_MAX;
lc->ifp = ifp;
- SLIST_INIT(&lc->lro_free);
- SLIST_INIT(&lc->lro_active);
+ LIST_INIT(&lc->lro_free);
+ LIST_INIT(&lc->lro_active);
/* compute size to allocate */
size = (lro_mbufs * sizeof(struct mbuf *)) +
@@ -111,7 +113,7 @@ tcp_lro_init_args(struct lro_ctrl *lc, struct ifnet *ifp,
/* setup linked list */
for (i = 0; i != lro_entries; i++)
- SLIST_INSERT_HEAD(&lc->lro_free, le + i, next);
+ LIST_INSERT_HEAD(&lc->lro_free, le + i, next);
return (0);
}
@@ -123,11 +125,11 @@ tcp_lro_free(struct lro_ctrl *lc)
unsigned x;
/* reset LRO free list */
- SLIST_INIT(&lc->lro_free);
+ LIST_INIT(&lc->lro_free);
/* free active mbufs, if any */
- while ((le = SLIST_FIRST(&lc->lro_active)) != NULL) {
- SLIST_REMOVE_HEAD(&lc->lro_active, next);
+ while ((le = LIST_FIRST(&lc->lro_active)) != NULL) {
+ LIST_REMOVE(le, next);
m_freem(le->m_head);
}
@@ -226,20 +228,31 @@ tcp_lro_rx_csum_fixup(struct lro_entry *le, void *l3hdr, struct tcphdr *th,
}
#endif
+static void
+tcp_lro_rx_done(struct lro_ctrl *lc)
+{
+ struct lro_entry *le;
+
+ while ((le = LIST_FIRST(&lc->lro_active)) != NULL) {
+ LIST_REMOVE(le, next);
+ tcp_lro_flush(lc, le);
+ }
+}
+
void
tcp_lro_flush_inactive(struct lro_ctrl *lc, const struct timeval *timeout)
{
struct lro_entry *le, *le_tmp;
struct timeval tv;
- if (SLIST_EMPTY(&lc->lro_active))
+ if (LIST_EMPTY(&lc->lro_active))
return;
getmicrotime(&tv);
timevalsub(&tv, timeout);
- SLIST_FOREACH_SAFE(le, &lc->lro_active, next, le_tmp) {
+ LIST_FOREACH_SAFE(le, &lc->lro_active, next, le_tmp) {
if (timevalcmp(&tv, &le->mtime, >=)) {
- SLIST_REMOVE(&lc->lro_active, le, lro_entry, next);
+ LIST_REMOVE(le, next);
tcp_lro_flush(lc, le);
}
}
@@ -335,7 +348,7 @@ tcp_lro_flush(struct lro_ctrl *lc, struct lro_entry *le)
lc->lro_queued += le->append_cnt + 1;
lc->lro_flushed++;
bzero(le, sizeof(*le));
- SLIST_INSERT_HEAD(&lc->lro_free, le, next);
+ LIST_INSERT_HEAD(&lc->lro_free, le, next);
}
static int
@@ -362,13 +375,12 @@ done:
void
tcp_lro_flush_all(struct lro_ctrl *lc)
{
- struct lro_entry *le;
uint32_t hashtype;
uint32_t flowid;
unsigned x;
/* check if no mbufs to flush */
- if (__predict_false(lc->lro_mbuf_count == 0))
+ if (lc->lro_mbuf_count == 0)
goto done;
/* sort all mbufs according to stream */
@@ -390,10 +402,7 @@ tcp_lro_flush_all(struct lro_ctrl *lc)
hashtype = M_HASHTYPE_GET(mb);
/* flush active streams */
- while ((le = SLIST_FIRST(&lc->lro_active)) != NULL) {
- SLIST_REMOVE_HEAD(&lc->lro_active, next);
- tcp_lro_flush(lc, le);
- }
+ tcp_lro_rx_done(lc);
}
#ifdef TCP_LRO_RESET_SEQUENCE
/* reset sequence number */
@@ -409,10 +418,8 @@ tcp_lro_flush_all(struct lro_ctrl *lc)
}
done:
/* flush active streams */
- while ((le = SLIST_FIRST(&lc->lro_active)) != NULL) {
- SLIST_REMOVE_HEAD(&lc->lro_active, next);
- tcp_lro_flush(lc, le);
- }
+ tcp_lro_rx_done(lc);
+
lc->lro_mbuf_count = 0;
}
@@ -586,7 +593,7 @@ tcp_lro_rx(struct lro_ctrl *lc, struct mbuf *m, uint32_t csum)
seq = ntohl(th->th_seq);
/* Try to find a matching previous segment. */
- SLIST_FOREACH(le, &lc->lro_active, next) {
+ LIST_FOREACH(le, &lc->lro_active, next) {
if (le->eh_type != eh_type)
continue;
if (le->source_port != th->th_sport ||
@@ -613,7 +620,7 @@ tcp_lro_rx(struct lro_ctrl *lc, struct mbuf *m, uint32_t csum)
/* Flush now if appending will result in overflow. */
if (le->p_len > (lc->lro_length_lim - tcp_data_len)) {
- SLIST_REMOVE(&lc->lro_active, le, lro_entry, next);
+ LIST_REMOVE(le, next);
tcp_lro_flush(lc, le);
break;
}
@@ -622,7 +629,7 @@ tcp_lro_rx(struct lro_ctrl *lc, struct mbuf *m, uint32_t csum)
if (__predict_false(seq != le->next_seq ||
(tcp_data_len == 0 && le->ack_seq == th->th_ack))) {
/* Out of order packet or duplicate ACK. */
- SLIST_REMOVE(&lc->lro_active, le, lro_entry, next);
+ LIST_REMOVE(le, next);
tcp_lro_flush(lc, le);
return (TCP_LRO_CANNOT);
}
@@ -655,8 +662,7 @@ tcp_lro_rx(struct lro_ctrl *lc, struct mbuf *m, uint32_t csum)
* be further delayed.
*/
if (le->append_cnt >= lc->lro_ackcnt_lim) {
- SLIST_REMOVE(&lc->lro_active, le, lro_entry,
- next);
+ LIST_REMOVE(le, next);
tcp_lro_flush(lc, le);
}
return (0);
@@ -680,7 +686,7 @@ tcp_lro_rx(struct lro_ctrl *lc, struct mbuf *m, uint32_t csum)
* overflow, pro-actively flush now.
*/
if (le->p_len > (lc->lro_length_lim - lc->ifp->if_mtu)) {
- SLIST_REMOVE(&lc->lro_active, le, lro_entry, next);
+ LIST_REMOVE(le, next);
tcp_lro_flush(lc, le);
} else
getmicrotime(&le->mtime);
@@ -689,13 +695,13 @@ tcp_lro_rx(struct lro_ctrl *lc, struct mbuf *m, uint32_t csum)
}
/* Try to find an empty slot. */
- if (SLIST_EMPTY(&lc->lro_free))
- return (TCP_LRO_CANNOT);
+ if (LIST_EMPTY(&lc->lro_free))
+ return (TCP_LRO_NO_ENTRIES);
/* Start a new segment chain. */
- le = SLIST_FIRST(&lc->lro_free);
- SLIST_REMOVE_HEAD(&lc->lro_free, next);
- SLIST_INSERT_HEAD(&lc->lro_active, le, next);
+ le = LIST_FIRST(&lc->lro_free);
+ LIST_REMOVE(le, next);
+ LIST_INSERT_HEAD(&lc->lro_active, le, next);
getmicrotime(&le->mtime);
/* Start filling in details. */
diff --git a/sys/netinet/tcp_lro.h b/sys/netinet/tcp_lro.h
index 3fc627c..b81a950 100644
--- a/sys/netinet/tcp_lro.h
+++ b/sys/netinet/tcp_lro.h
@@ -41,9 +41,8 @@
#define TCP_LRO_SEQUENCE(mb) \
(mb)->m_pkthdr.PH_loc.thirtytwo[0]
-struct lro_entry
-{
- SLIST_ENTRY(lro_entry) next;
+struct lro_entry {
+ LIST_ENTRY(lro_entry) next;
struct mbuf *m_head;
struct mbuf *m_tail;
union {
@@ -72,7 +71,7 @@ struct lro_entry
uint16_t timestamp; /* flag, not a TCP hdr field. */
struct timeval mtime;
};
-SLIST_HEAD(lro_head, lro_entry);
+LIST_HEAD(lro_head, lro_entry);
#define le_ip4 leip.ip4
#define le_ip6 leip.ip6
@@ -110,6 +109,7 @@ void tcp_lro_flush_all(struct lro_ctrl *);
int tcp_lro_rx(struct lro_ctrl *, struct mbuf *, uint32_t);
void tcp_lro_queue_mbuf(struct lro_ctrl *, struct mbuf *);
+#define TCP_LRO_NO_ENTRIES -2
#define TCP_LRO_CANNOT -1
#define TCP_LRO_NOT_SUPPORTED 1
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index 96a8700..2043fc9 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -1379,9 +1379,6 @@ send:
#endif
#ifdef INET
{
- struct route ro;
-
- bzero(&ro, sizeof(ro));
ip->ip_len = htons(m->m_pkthdr.len);
#ifdef INET6
if (tp->t_inpcb->inp_vflag & INP_IPV6PROTO)
@@ -1412,13 +1409,12 @@ send:
tcp_pcap_add(th, m, &(tp->t_outpkts));
#endif
- error = ip_output(m, tp->t_inpcb->inp_options, &ro,
+ error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route,
((so->so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0), 0,
tp->t_inpcb);
- if (error == EMSGSIZE && ro.ro_rt != NULL)
- mtu = ro.ro_rt->rt_mtu;
- RO_RTFREE(&ro);
+ if (error == EMSGSIZE && tp->t_inpcb->inp_route.ro_rt != NULL)
+ mtu = tp->t_inpcb->inp_route.ro_rt->rt_mtu;
}
#endif /* INET */
@@ -1652,7 +1648,7 @@ tcp_setpersist(struct tcpcb *tp)
int
tcp_addoptions(struct tcpopt *to, u_char *optp)
{
- u_int mask, optlen = 0;
+ u_int32_t mask, optlen = 0;
for (mask = 1; mask < TOF_MAXOPT; mask <<= 1) {
if ((to->to_flags & mask) != mask)
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index ff218dd..33b16ad 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -1542,7 +1542,7 @@ tcp_close(struct tcpcb *tp)
#endif
in_pcbdrop(inp);
TCPSTAT_INC(tcps_closed);
- TCPSTAT_DEC(tcps_states[tp->t_state]);
+ TCPSTATES_DEC(tp->t_state);
KASSERT(inp->inp_socket != NULL, ("tcp_close: inp_socket NULL"));
so = inp->inp_socket;
soisdisconnected(so);
@@ -1632,6 +1632,10 @@ tcp_notify(struct inpcb *inp, int error)
if (tp->t_state == TCPS_ESTABLISHED &&
(error == EHOSTUNREACH || error == ENETUNREACH ||
error == EHOSTDOWN)) {
+ if (inp->inp_route.ro_rt) {
+ RTFREE(inp->inp_route.ro_rt);
+ inp->inp_route.ro_rt = (struct rtentry *)NULL;
+ }
return (inp);
} else if (tp->t_state < TCPS_ESTABLISHED && tp->t_rxtshift > 3 &&
tp->t_softerror) {
@@ -1665,7 +1669,7 @@ tcp_pcblist(SYSCTL_HANDLER_ARGS)
*/
if (req->oldptr == NULL) {
n = V_tcbinfo.ipi_count +
- TCPSTAT_FETCH(tcps_states[TCPS_SYN_RECEIVED]);
+ counter_u64_fetch(VNET(tcps_states)[TCPS_SYN_RECEIVED]);
n += imax(n / 8, 10);
req->oldidx = 2 * (sizeof xig) + n * sizeof(struct xtcpcb);
return (0);
@@ -1682,7 +1686,7 @@ tcp_pcblist(SYSCTL_HANDLER_ARGS)
n = V_tcbinfo.ipi_count;
INP_LIST_RUNLOCK(&V_tcbinfo);
- m = TCPSTAT_FETCH(tcps_states[TCPS_SYN_RECEIVED]);
+ m = counter_u64_fetch(VNET(tcps_states)[TCPS_SYN_RECEIVED]);
error = sysctl_wire_old_buffer(req, 2 * (sizeof xig)
+ (n + m) * sizeof(struct xtcpcb));
@@ -1702,8 +1706,6 @@ tcp_pcblist(SYSCTL_HANDLER_ARGS)
return (error);
inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK);
- if (inp_list == NULL)
- return (ENOMEM);
INP_INFO_WLOCK(&V_tcbinfo);
for (inp = LIST_FIRST(V_tcbinfo.ipi_listhead), i = 0;
@@ -1926,11 +1928,11 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
else if (V_icmp_may_rst && (cmd == PRC_UNREACH_ADMIN_PROHIB ||
cmd == PRC_UNREACH_PORT || cmd == PRC_TIMXCEED_INTRANS) && ip)
notify = tcp_drop_syn_sent;
- /*
- * Redirects don't need to be handled up here.
- */
- else if (PRC_IS_REDIRECT(cmd))
+ else if (PRC_IS_REDIRECT(cmd)) {
+ /* signal EHOSTDOWN, as it flushes the cached route */
+ in_pcbnotifyall(&V_tcbinfo, faddr, EHOSTDOWN, notify);
return;
+ }
/*
* Hostdead is ugly because it goes linearly through all PCBs.
* XXX: We never get this from ICMP, otherwise it makes an
@@ -2986,8 +2988,8 @@ tcp_state_change(struct tcpcb *tp, int newstate)
int pstate = tp->t_state;
#endif
- TCPSTAT_DEC(tcps_states[tp->t_state]);
- TCPSTAT_INC(tcps_states[newstate]);
+ TCPSTATES_DEC(tp->t_state);
+ TCPSTATES_INC(newstate);
tp->t_state = newstate;
TCP_PROBE6(state__change, NULL, tp, NULL, tp, NULL, pstate);
}
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index 0ff7318..b898c49 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -351,7 +351,7 @@ syncache_insert(struct syncache *sc, struct syncache_head *sch)
SCH_UNLOCK(sch);
- TCPSTAT_INC(tcps_states[TCPS_SYN_RECEIVED]);
+ TCPSTATES_INC(TCPS_SYN_RECEIVED);
TCPSTAT_INC(tcps_sc_added);
}
@@ -365,7 +365,7 @@ syncache_drop(struct syncache *sc, struct syncache_head *sch)
SCH_LOCK_ASSERT(sch);
- TCPSTAT_DEC(tcps_states[TCPS_SYN_RECEIVED]);
+ TCPSTATES_DEC(TCPS_SYN_RECEIVED);
TAILQ_REMOVE(&sch->sch_bucket, sc, sc_hash);
sch->sch_length--;
@@ -1003,7 +1003,7 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
* sonewconn->tcp_usr_attach in TCPS_CLOSED state, then
* syncache_socket() will change it to TCPS_SYN_RECEIVED.
*/
- TCPSTAT_DEC(tcps_states[TCPS_SYN_RECEIVED]);
+ TCPSTATES_DEC(TCPS_SYN_RECEIVED);
TAILQ_REMOVE(&sch->sch_bucket, sc, sc_hash);
sch->sch_length--;
#ifdef TCP_OFFLOAD
diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c
index 046feba..172c394 100644
--- a/sys/netinet/tcp_timer.c
+++ b/sys/netinet/tcp_timer.c
@@ -786,7 +786,9 @@ tcp_timer_rexmt(void * xtp)
#ifdef INET6
if ((tp->t_inpcb->inp_vflag & INP_IPV6) != 0)
in6_losing(tp->t_inpcb);
+ else
#endif
+ in_losing(tp->t_inpcb);
tp->t_rttvar += (tp->t_srtt >> TCP_RTT_SHIFT);
tp->t_srtt = 0;
}
diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c
index c98de24..ff36ce7 100644
--- a/sys/netinet/tcp_timewait.c
+++ b/sys/netinet/tcp_timewait.c
@@ -660,7 +660,7 @@ tcp_tw_2msl_stop(struct tcptw *tw, int reuse)
if (!reuse)
uma_zfree(V_tcptw_zone, tw);
- TCPSTAT_DEC(tcps_states[TCPS_TIME_WAIT]);
+ TCPSTATES_DEC(TCPS_TIME_WAIT);
}
struct tcptw *
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index 09493f0..6a3cde6 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -1883,7 +1883,7 @@ tcp_attach(struct socket *so)
tp->t_state = TCPS_CLOSED;
INP_WUNLOCK(inp);
INP_INFO_RUNLOCK(&V_tcbinfo);
- TCPSTAT_INC(tcps_states[TCPS_CLOSED]);
+ TCPSTATES_INC(TCPS_CLOSED);
return (0);
}
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index 2f23881..d60ad9f 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -364,7 +364,7 @@ struct tcpcb {
* options in tcp_addoptions.
*/
struct tcpopt {
- u_int64_t to_flags; /* which options are present */
+ u_int32_t to_flags; /* which options are present */
#define TOF_MSS 0x0001 /* maximum segment size */
#define TOF_SCALE 0x0002 /* window scaling */
#define TOF_SACKPERM 0x0004 /* SACK permitted */
@@ -588,9 +588,6 @@ struct tcpstat {
uint64_t tcps_sig_err_sigopt; /* No signature expected by socket */
uint64_t tcps_sig_err_nosigopt; /* No signature provided by segment */
- /* Running connection count. */
- uint64_t tcps_states[TCP_NSTATES];
-
uint64_t _pad[12]; /* 6 UTO, 6 TBD */
};
@@ -609,9 +606,6 @@ VNET_PCPUSTAT_DECLARE(struct tcpstat, tcpstat); /* tcp statistics */
#define TCPSTAT_ADD(name, val) \
VNET_PCPUSTAT_ADD(struct tcpstat, tcpstat, name, (val))
#define TCPSTAT_INC(name) TCPSTAT_ADD(name, 1)
-#define TCPSTAT_DEC(name) TCPSTAT_ADD(name, -1)
-#define TCPSTAT_FETCH(name) VNET_PCPUSTAT_FETCH(struct tcpstat, tcpstat, \
- name)
/*
* Kernel module consumers must use this accessor macro.
@@ -621,6 +615,13 @@ void kmod_tcpstat_inc(int statnum);
kmod_tcpstat_inc(offsetof(struct tcpstat, name) / sizeof(uint64_t))
/*
+ * Running TCP connection count by state.
+ */
+VNET_DECLARE(counter_u64_t, tcps_states[TCP_NSTATES]);
+#define TCPSTATES_INC(state) counter_u64_add(VNET(tcps_states)[state], 1)
+#define TCPSTATES_DEC(state) counter_u64_add(VNET(tcps_states)[state], -1)
+
+/*
* TCP specific helper hook point identifiers.
*/
#define HHOOK_TCP_EST_IN 0
@@ -678,6 +679,7 @@ struct xtcpcb {
#define TCPCTL_V6MSSDFLT 13 /* MSS default for IPv6 */
#define TCPCTL_SACK 14 /* Selective Acknowledgement,rfc 2018 */
#define TCPCTL_DROP 15 /* drop tcp connection */
+#define TCPCTL_STATES 16 /* connection counts by TCP state */
#ifdef _KERNEL
#ifdef SYSCTL_DECL
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index f474a54..56aa56f 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -740,6 +740,11 @@ udp_notify(struct inpcb *inp, int errno)
* or a write lock, but a read lock is sufficient.
*/
INP_LOCK_ASSERT(inp);
+ if ((errno == EHOSTUNREACH || errno == ENETUNREACH ||
+ errno == EHOSTDOWN) && inp->inp_route.ro_rt) {
+ RTFREE(inp->inp_route.ro_rt);
+ inp->inp_route.ro_rt = (struct rtentry *)NULL;
+ }
inp->inp_socket->so_error = errno;
sorwakeup(inp->inp_socket);
@@ -761,11 +766,11 @@ udp_common_ctlinput(int cmd, struct sockaddr *sa, void *vip,
if (sa->sa_family != AF_INET || faddr.s_addr == INADDR_ANY)
return;
- /*
- * Redirects don't need to be handled up here.
- */
- if (PRC_IS_REDIRECT(cmd))
+ if (PRC_IS_REDIRECT(cmd)) {
+ /* signal EHOSTDOWN, as it flushes the cached route */
+ in_pcbnotifyall(&V_udbinfo, faddr, EHOSTDOWN, udp_notify);
return;
+ }
/*
* Hostdead is ugly because it goes linearly through all PCBs.
@@ -1116,7 +1121,7 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
int error = 0;
int ipflags;
u_short fport, lport;
- int unlock_udbinfo;
+ int unlock_udbinfo, unlock_inp;
u_char tos;
uint8_t pr;
uint16_t cscov = 0;
@@ -1137,7 +1142,15 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
}
src.sin_family = 0;
- INP_RLOCK(inp);
+ sin = (struct sockaddr_in *)addr;
+ if (sin == NULL ||
+ (inp->inp_laddr.s_addr == INADDR_ANY && inp->inp_lport == 0)) {
+ INP_WLOCK(inp);
+ unlock_inp = UH_WLOCKED;
+ } else {
+ INP_RLOCK(inp);
+ unlock_inp = UH_RLOCKED;
+ }
tos = inp->inp_ip_tos;
if (control != NULL) {
/*
@@ -1145,7 +1158,10 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
* stored in a single mbuf.
*/
if (control->m_next) {
- INP_RUNLOCK(inp);
+ if (unlock_inp == UH_WLOCKED)
+ INP_WUNLOCK(inp);
+ else
+ INP_RUNLOCK(inp);
m_freem(control);
m_freem(m);
return (EINVAL);
@@ -1220,7 +1236,10 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
m_freem(control);
}
if (error) {
- INP_RUNLOCK(inp);
+ if (unlock_inp == UH_WLOCKED)
+ INP_WUNLOCK(inp);
+ else
+ INP_RUNLOCK(inp);
m_freem(m);
return (error);
}
@@ -1246,8 +1265,6 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
sin = (struct sockaddr_in *)addr;
if (sin != NULL &&
(inp->inp_laddr.s_addr == INADDR_ANY && inp->inp_lport == 0)) {
- INP_RUNLOCK(inp);
- INP_WLOCK(inp);
INP_HASH_WLOCK(pcbinfo);
unlock_udbinfo = UH_WLOCKED;
} else if ((sin != NULL && (
@@ -1514,9 +1531,10 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
else if (unlock_udbinfo == UH_RLOCKED)
INP_HASH_RUNLOCK(pcbinfo);
UDP_PROBE(send, NULL, inp, &ui->ui_i, inp, &ui->ui_u);
- error = ip_output(m, inp->inp_options, NULL, ipflags,
+ error = ip_output(m, inp->inp_options,
+ (unlock_inp == UH_WLOCKED ? &inp->inp_route : NULL), ipflags,
inp->inp_moptions, inp);
- if (unlock_udbinfo == UH_WLOCKED)
+ if (unlock_inp == UH_WLOCKED)
INP_WUNLOCK(inp);
else
INP_RUNLOCK(inp);
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index 393bb7e..797093a 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -2367,7 +2367,7 @@ in6_lltable_dump_entry(struct lltable *llt, struct llentry *lle,
sdl->sdl_alen = ifp->if_addrlen;
sdl->sdl_index = ifp->if_index;
sdl->sdl_type = ifp->if_type;
- bcopy(&lle->ll_addr, LLADDR(sdl), ifp->if_addrlen);
+ bcopy(lle->ll_addr, LLADDR(sdl), ifp->if_addrlen);
if (lle->la_expire != 0)
ndpc.rtm.rtm_rmx.rmx_expire = lle->la_expire +
lle->lle_remtime / hz +
diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c
index 64981b3..471dd82 100644
--- a/sys/netinet6/in6_ifattach.c
+++ b/sys/netinet6/in6_ifattach.c
@@ -890,3 +890,29 @@ in6_purgemaddrs(struct ifnet *ifp)
IN6_MULTI_UNLOCK();
}
+
+void
+in6_ifattach_destroy(void)
+{
+
+ callout_drain(&V_in6_tmpaddrtimer_ch);
+}
+
+static void
+in6_ifattach_init(void *dummy)
+{
+
+ /* Timer for regeneranation of temporary addresses randomize ID. */
+ callout_init(&V_in6_tmpaddrtimer_ch, 0);
+ callout_reset(&V_in6_tmpaddrtimer_ch,
+ (V_ip6_temp_preferred_lifetime - V_ip6_desync_factor -
+ V_ip6_temp_regen_advance) * hz,
+ in6_tmpaddrtimer, curvnet);
+}
+
+/*
+ * Cheat.
+ * This must be after route_init(), which is now SI_ORDER_THIRD.
+ */
+SYSINIT(in6_ifattach_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE,
+ in6_ifattach_init, NULL);
diff --git a/sys/netinet6/in6_ifattach.h b/sys/netinet6/in6_ifattach.h
index af62731..a5a82c0 100644
--- a/sys/netinet6/in6_ifattach.h
+++ b/sys/netinet6/in6_ifattach.h
@@ -35,6 +35,7 @@
#ifdef _KERNEL
void in6_ifattach(struct ifnet *, struct ifnet *);
+void in6_ifattach_destroy(void);
void in6_ifdetach(struct ifnet *);
int in6_get_tmpifid(struct ifnet *, u_int8_t *, const u_int8_t *, int);
void in6_tmpaddrtimer(void *);
diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c
index a779b8d..98f4cd3 100644
--- a/sys/netinet6/in6_pcb.c
+++ b/sys/netinet6/in6_pcb.c
@@ -827,9 +827,10 @@ void
in6_losing(struct inpcb *in6p)
{
- /*
- * We don't store route pointers in the routing table anymore
- */
+ if (in6p->inp_route6.ro_rt) {
+ RTFREE(in6p->inp_route6.ro_rt);
+ in6p->inp_route6.ro_rt = (struct rtentry *)NULL;
+ }
return;
}
@@ -840,9 +841,11 @@ in6_losing(struct inpcb *in6p)
struct inpcb *
in6_rtchange(struct inpcb *inp, int errno)
{
- /*
- * We don't store route pointers in the routing table anymore
- */
+
+ if (inp->inp_route6.ro_rt) {
+ RTFREE(inp->inp_route6.ro_rt);
+ inp->inp_route6.ro_rt = (struct rtentry *)NULL;
+ }
return inp;
}
diff --git a/sys/netinet6/in6_pcbgroup.c b/sys/netinet6/in6_pcbgroup.c
index 694de99..4a68432 100644
--- a/sys/netinet6/in6_pcbgroup.c
+++ b/sys/netinet6/in6_pcbgroup.c
@@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/mbuf.h>
+#include <sys/socket.h>
#include <net/rss_config.h>
diff --git a/sys/netinet6/in6_src.c b/sys/netinet6/in6_src.c
index 4029402..40b4723 100644
--- a/sys/netinet6/in6_src.c
+++ b/sys/netinet6/in6_src.c
@@ -226,9 +226,6 @@ in6_selectsrc(uint32_t fibnum, struct sockaddr_in6 *dstsock,
*/
if (opts && (pi = opts->ip6po_pktinfo) &&
!IN6_IS_ADDR_UNSPECIFIED(&pi->ipi6_addr)) {
- struct sockaddr_in6 srcsock;
- struct in6_ifaddr *ia6;
-
/* get the outgoing interface */
if ((error = in6_selectif(dstsock, opts, mopts, &ifp, oifp,
fibnum))
@@ -242,33 +239,36 @@ in6_selectsrc(uint32_t fibnum, struct sockaddr_in6 *dstsock,
* the interface must be specified; otherwise, ifa_ifwithaddr()
* will fail matching the address.
*/
- bzero(&srcsock, sizeof(srcsock));
- srcsock.sin6_family = AF_INET6;
- srcsock.sin6_len = sizeof(srcsock);
- srcsock.sin6_addr = pi->ipi6_addr;
+ tmp = pi->ipi6_addr;
if (ifp) {
- error = in6_setscope(&srcsock.sin6_addr, ifp, NULL);
+ error = in6_setscope(&tmp, ifp, &odstzone);
if (error)
return (error);
}
if (cred != NULL && (error = prison_local_ip6(cred,
- &srcsock.sin6_addr, (inp != NULL &&
- (inp->inp_flags & IN6P_IPV6_V6ONLY) != 0))) != 0)
+ &tmp, (inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)) != 0)
return (error);
- ia6 = (struct in6_ifaddr *)ifa_ifwithaddr(
- (struct sockaddr *)&srcsock);
- if (ia6 == NULL ||
- (ia6->ia6_flags & (IN6_IFF_ANYCAST | IN6_IFF_NOTREADY))) {
- if (ia6 != NULL)
- ifa_free(&ia6->ia_ifa);
- return (EADDRNOTAVAIL);
- }
- pi->ipi6_addr = srcsock.sin6_addr; /* XXX: this overrides pi */
+ /*
+ * If IPV6_BINDANY socket option is set, we allow to specify
+ * non local addresses as source address in IPV6_PKTINFO
+ * ancillary data.
+ */
+ if ((inp->inp_flags & INP_BINDANY) == 0) {
+ ia = in6ifa_ifwithaddr(&tmp, odstzone);
+ if (ia == NULL || (ia->ia6_flags & (IN6_IFF_ANYCAST |
+ IN6_IFF_NOTREADY))) {
+ if (ia != NULL)
+ ifa_free(&ia->ia_ifa);
+ return (EADDRNOTAVAIL);
+ }
+ bcopy(&ia->ia_addr.sin6_addr, srcp, sizeof(*srcp));
+ ifa_free(&ia->ia_ifa);
+ } else
+ bcopy(&tmp, srcp, sizeof(*srcp));
+ pi->ipi6_addr = tmp; /* XXX: this overrides pi */
if (ifpp)
*ifpp = ifp;
- bcopy(&ia6->ia_addr.sin6_addr, srcp, sizeof(*srcp));
- ifa_free(&ia6->ia_ifa);
return (0);
}
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index e6c16a9..6b49b26 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -156,9 +156,6 @@ static struct netisr_handler ip6_direct_nh = {
};
#endif
-VNET_DECLARE(struct callout, in6_tmpaddrtimer_ch);
-#define V_in6_tmpaddrtimer_ch VNET(in6_tmpaddrtimer_ch)
-
VNET_DEFINE(struct pfil_head, inet6_pfil_hook);
VNET_PCPUSTAT_DEFINE(struct ip6stat, ip6stat);
@@ -170,7 +167,6 @@ VNET_PCPUSTAT_SYSUNINIT(ip6stat);
struct rmlock in6_ifaddr_lock;
RM_SYSINIT(in6_ifaddr_lock, &in6_ifaddr_lock, "in6_ifaddr_lock");
-static void ip6_init2(void *);
static int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *);
#ifdef PULLDOWN_TEST
static struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int);
@@ -331,40 +327,11 @@ ip6_destroy()
}
hashdestroy(V_in6_ifaddrhashtbl, M_IFADDR, V_in6_ifaddrhmask);
nd6_destroy();
- callout_drain(&V_in6_tmpaddrtimer_ch);
+ in6_ifattach_destroy();
}
#endif
static int
-ip6_init2_vnet(const void *unused __unused)
-{
-
- /* nd6_timer_init */
- callout_init(&V_nd6_timer_ch, 0);
- callout_reset(&V_nd6_timer_ch, hz, nd6_timer, curvnet);
-
- /* timer for regeneranation of temporary addresses randomize ID */
- callout_init(&V_in6_tmpaddrtimer_ch, 0);
- callout_reset(&V_in6_tmpaddrtimer_ch,
- (V_ip6_temp_preferred_lifetime - V_ip6_desync_factor -
- V_ip6_temp_regen_advance) * hz,
- in6_tmpaddrtimer, curvnet);
-
- return (0);
-}
-
-static void
-ip6_init2(void *dummy)
-{
-
- ip6_init2_vnet(NULL);
-}
-
-/* cheat */
-/* This must be after route_init(), which is now SI_ORDER_THIRD */
-SYSINIT(netinet6init2, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ip6_init2, NULL);
-
-static int
ip6_input_hbh(struct mbuf *m, uint32_t *plen, uint32_t *rtalert, int *off,
int *nxt, int *ours)
{
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c
index 3a47285..7895139 100644
--- a/sys/netinet6/ip6_output.c
+++ b/sys/netinet6/ip6_output.c
@@ -546,7 +546,18 @@ again:
/* adjust pointer */
ip6 = mtod(m, struct ip6_hdr *);
- if (ro->ro_rt && fwd_tag == NULL) {
+ /*
+ * Validate route against routing table additions;
+ * a better/more specific route might have been added.
+ * Make sure address family is set in route.
+ */
+ if (inp) {
+ ro->ro_dst.sin6_family = AF_INET6;
+ RT_VALIDATE((struct route *)ro, &inp->inp_rt_cookie, fibnum);
+ }
+ if (ro->ro_rt && fwd_tag == NULL && (ro->ro_rt->rt_flags & RTF_UP) &&
+ ro->ro_dst.sin6_family == AF_INET6 &&
+ IN6_ARE_ADDR_EQUAL(&ro->ro_dst.sin6_addr, &ip6->ip6_dst)) {
rt = ro->ro_rt;
ifp = ro->ro_rt->rt_ifp;
} else {
@@ -939,7 +950,8 @@ passout:
m->m_pkthdr.len);
ifa_free(&ia6->ia_ifa);
}
- error = nd6_output_ifp(ifp, origifp, m, dst, NULL);
+ error = nd6_output_ifp(ifp, origifp, m, dst,
+ (struct route *)ro);
goto done;
}
@@ -1038,7 +1050,8 @@ sendorfree:
counter_u64_add(ia->ia_ifa.ifa_obytes,
m->m_pkthdr.len);
}
- error = nd6_output_ifp(ifp, origifp, m, dst, NULL);
+ error = nd6_output_ifp(ifp, origifp, m, dst,
+ (struct route *)ro);
} else
m_freem(m);
}
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index 60693e1..8b1da24 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -127,7 +127,7 @@ static int nd6_is_new_addr_neighbor(const struct sockaddr_in6 *,
static void nd6_setmtu0(struct ifnet *, struct nd_ifinfo *);
static void nd6_slowtimo(void *);
static int regen_tmpaddr(struct in6_ifaddr *);
-static void nd6_free(struct llentry *, int);
+static void nd6_free(struct llentry **, int);
static void nd6_free_redirect(const struct llentry *);
static void nd6_llinfo_timer(void *);
static void nd6_llinfo_settimer_locked(struct llentry *, long);
@@ -142,6 +142,7 @@ static VNET_DEFINE(struct callout, nd6_slowtimo_ch);
#define V_nd6_slowtimo_ch VNET(nd6_slowtimo_ch)
VNET_DEFINE(struct callout, nd6_timer_ch);
+#define V_nd6_timer_ch VNET(nd6_timer_ch)
static void
nd6_lle_event(void *arg __unused, struct llentry *lle, int evt)
@@ -213,11 +214,14 @@ nd6_init(void)
/* initialization of the default router list */
TAILQ_INIT(&V_nd_defrouter);
- /* start timer */
+ /* Start timers. */
callout_init(&V_nd6_slowtimo_ch, 0);
callout_reset(&V_nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz,
nd6_slowtimo, curvnet);
+ callout_init(&V_nd6_timer_ch, 0);
+ callout_reset(&V_nd6_timer_ch, hz, nd6_timer, curvnet);
+
nd6_dad_init();
if (IS_DEFAULT_VNET(curvnet)) {
lle_event_eh = EVENTHANDLER_REGISTER(lle_event, nd6_lle_event,
@@ -723,12 +727,16 @@ nd6_llinfo_timer(void *arg)
struct llentry *ln;
struct in6_addr *dst, *pdst, *psrc, src;
struct ifnet *ifp;
- struct nd_ifinfo *ndi = NULL;
+ struct nd_ifinfo *ndi;
int do_switch, send_ns;
long delay;
KASSERT(arg != NULL, ("%s: arg NULL", __func__));
ln = (struct llentry *)arg;
+ ifp = lltable_get_ifp(ln->lle_tbl);
+ CURVNET_SET(ifp->if_vnet);
+
+ ND6_RLOCK();
LLE_WLOCK(ln);
if (callout_pending(&ln->lle_timer)) {
/*
@@ -748,10 +756,10 @@ nd6_llinfo_timer(void *arg)
* would have been 1.
*/
LLE_WUNLOCK(ln);
+ ND6_RUNLOCK();
+ CURVNET_RESTORE();
return;
}
- ifp = ln->lle_tbl->llt_ifp;
- CURVNET_SET(ifp->if_vnet);
ndi = ND_IFINFO(ifp);
send_ns = 0;
dst = &ln->r_l3addr.addr6;
@@ -773,8 +781,7 @@ nd6_llinfo_timer(void *arg)
}
if (ln->la_flags & LLE_DELETED) {
- nd6_free(ln, 0);
- ln = NULL;
+ nd6_free(&ln, 0);
goto done;
}
@@ -799,9 +806,7 @@ nd6_llinfo_timer(void *arg)
ln->la_hold = m0;
clear_llinfo_pqueue(ln);
}
- EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_TIMEDOUT);
- nd6_free(ln, 0);
- ln = NULL;
+ nd6_free(&ln, 0);
if (m != NULL)
icmp6_error2(m, ICMP6_DST_UNREACH,
ICMP6_DST_UNREACH_ADDR, 0, ifp);
@@ -830,12 +835,8 @@ nd6_llinfo_timer(void *arg)
* GC timer has ended and entry hasn't been used.
* Run Garbage collector (RFC 4861, 5.3)
*/
- if (!ND6_LLINFO_PERMANENT(ln)) {
- EVENTHANDLER_INVOKE(lle_event, ln,
- LLENTRY_EXPIRED);
- nd6_free(ln, 1);
- ln = NULL;
- }
+ if (!ND6_LLINFO_PERMANENT(ln))
+ nd6_free(&ln, 1);
break;
}
@@ -857,9 +858,7 @@ nd6_llinfo_timer(void *arg)
ln->la_asked++;
send_ns = 1;
} else {
- EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_EXPIRED);
- nd6_free(ln, 0);
- ln = NULL;
+ nd6_free(&ln, 0);
}
break;
default:
@@ -867,6 +866,8 @@ nd6_llinfo_timer(void *arg)
__func__, ln->ln_state);
}
done:
+ if (ln != NULL)
+ ND6_RUNLOCK();
if (send_ns != 0) {
nd6_llinfo_settimer_locked(ln, (long)ndi->retrans * hz / 1000);
psrc = nd6_llinfo_get_holdsrc(ln, &src);
@@ -1363,12 +1364,27 @@ nd6_is_addr_neighbor(const struct sockaddr_in6 *addr, struct ifnet *ifp)
* Set noinline to be dtrace-friendly
*/
static __noinline void
-nd6_free(struct llentry *ln, int gc)
+nd6_free(struct llentry **lnp, int gc)
{
- struct nd_defrouter *dr;
struct ifnet *ifp;
+ struct llentry *ln;
+ struct nd_defrouter *dr;
+
+ ln = *lnp;
+ *lnp = NULL;
LLE_WLOCK_ASSERT(ln);
+ ND6_RLOCK_ASSERT();
+
+ ifp = lltable_get_ifp(ln->lle_tbl);
+ if ((ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV) != 0)
+ dr = defrouter_lookup_locked(&ln->r_l3addr.addr6, ifp);
+ else
+ dr = NULL;
+ ND6_RUNLOCK();
+
+ if ((ln->la_flags & LLE_DELETED) == 0)
+ EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_EXPIRED);
/*
* we used to have pfctlinput(PRC_HOSTDEAD) here.
@@ -1378,11 +1394,7 @@ nd6_free(struct llentry *ln, int gc)
/* cancel timer */
nd6_llinfo_settimer_locked(ln, -1);
- dr = NULL;
- ifp = ln->lle_tbl->llt_ifp;
if (ND_IFINFO(ifp)->flags & ND6_IFF_ACCEPT_RTADV) {
- dr = defrouter_lookup(&ln->r_l3addr.addr6, ifp);
-
if (dr != NULL && dr->expire &&
ln->ln_state == ND6_LLINFO_STALE && gc) {
/*
diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h
index 4c83467..3b1aa96 100644
--- a/sys/netinet6/nd6.h
+++ b/sys/netinet6/nd6.h
@@ -355,9 +355,6 @@ VNET_DECLARE(struct rwlock, nd6_lock);
#define nd6log(x) do { if (V_nd6_debug) log x; } while (/*CONSTCOND*/ 0)
-VNET_DECLARE(struct callout, nd6_timer_ch);
-#define V_nd6_timer_ch VNET(nd6_timer_ch)
-
/* nd6_rtr.c */
VNET_DECLARE(int, nd6_defifindex);
VNET_DECLARE(int, ip6_desync_factor); /* seconds */
@@ -459,7 +456,7 @@ void defrouter_reset(void);
void defrouter_select(void);
void defrouter_ref(struct nd_defrouter *);
void defrouter_rele(struct nd_defrouter *);
-void defrouter_remove(struct nd_defrouter *);
+bool defrouter_remove(struct in6_addr *, struct ifnet *);
void defrouter_unlink(struct nd_defrouter *, struct nd_drhead *);
void defrouter_del(struct nd_defrouter *);
void prelist_remove(struct nd_prefix *);
diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c
index d528575..d621b52 100644
--- a/sys/netinet6/nd6_nbr.c
+++ b/sys/netinet6/nd6_nbr.c
@@ -857,30 +857,19 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
* Remove the sender from the Default Router List and
* update the Destination Cache entries.
*/
- struct nd_defrouter *dr;
struct ifnet *nd6_ifp;
nd6_ifp = lltable_get_ifp(ln->lle_tbl);
- ND6_WLOCK();
- dr = defrouter_lookup_locked(&ln->r_l3addr.addr6,
- nd6_ifp);
- if (dr != NULL) {
- /* releases the ND lock */
- defrouter_remove(dr);
- dr = NULL;
- } else {
- ND6_WUNLOCK();
- if ((ND_IFINFO(nd6_ifp)->flags & ND6_IFF_ACCEPT_RTADV) != 0) {
- /*
- * Even if the neighbor is not in the default
- * router list, the neighbor may be used
- * as a next hop for some destinations
- * (e.g. redirect case). So we must
- * call rt6_flush explicitly.
- */
- rt6_flush(&ip6->ip6_src, ifp);
- }
- }
+ if (!defrouter_remove(&ln->r_l3addr.addr6, nd6_ifp) &&
+ (ND_IFINFO(nd6_ifp)->flags &
+ ND6_IFF_ACCEPT_RTADV) != 0)
+ /*
+ * Even if the neighbor is not in the default
+ * router list, the neighbor may be used as a
+ * next hop for some destinations (e.g. redirect
+ * case). So we must call rt6_flush explicitly.
+ */
+ rt6_flush(&ip6->ip6_src, ifp);
}
ln->ln_router = is_router;
}
diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c
index 294c90a..6fee830 100644
--- a/sys/netinet6/nd6_rtr.c
+++ b/sys/netinet6/nd6_rtr.c
@@ -627,22 +627,26 @@ defrouter_reset(void)
}
/*
- * Remove a router from the global list and free it.
- *
- * The ND lock must be held and is released before returning. The caller must
- * hold a reference on the router object.
+ * Look up a matching default router list entry and remove it. Returns true if a
+ * matching entry was found, false otherwise.
*/
-void
-defrouter_remove(struct nd_defrouter *dr)
+bool
+defrouter_remove(struct in6_addr *addr, struct ifnet *ifp)
{
+ struct nd_defrouter *dr;
- ND6_WLOCK_ASSERT();
- KASSERT(dr->refcnt >= 2, ("unexpected refcount 0x%x", dr->refcnt));
+ ND6_WLOCK();
+ dr = defrouter_lookup_locked(addr, ifp);
+ if (dr == NULL) {
+ ND6_WUNLOCK();
+ return (false);
+ }
defrouter_unlink(dr, NULL);
ND6_WUNLOCK();
defrouter_del(dr);
defrouter_rele(dr);
+ return (true);
}
/*
@@ -850,14 +854,14 @@ defrtrlist_update(struct nd_defrouter *new)
struct nd_defrouter *dr, *n;
int oldpref;
- ND6_WLOCK();
- if ((dr = defrouter_lookup_locked(&new->rtaddr, new->ifp)) != NULL) {
- if (new->rtlifetime == 0) {
- /* releases the ND lock */
- defrouter_remove(dr);
- return (NULL);
- }
+ if (new->rtlifetime == 0) {
+ defrouter_remove(&new->rtaddr, new->ifp);
+ return (NULL);
+ }
+ ND6_WLOCK();
+ dr = defrouter_lookup_locked(&new->rtaddr, new->ifp);
+ if (dr != NULL) {
oldpref = rtpref(dr);
/* override */
@@ -881,25 +885,17 @@ defrtrlist_update(struct nd_defrouter *new)
*/
TAILQ_REMOVE(&V_nd_defrouter, dr, dr_entry);
n = dr;
- goto insert;
- }
-
- /* entry does not exist */
- if (new->rtlifetime == 0) {
- ND6_WUNLOCK();
- return (NULL);
- }
-
- n = malloc(sizeof(*n), M_IP6NDP, M_NOWAIT | M_ZERO);
- if (n == NULL) {
- ND6_WUNLOCK();
- return (NULL);
+ } else {
+ n = malloc(sizeof(*n), M_IP6NDP, M_NOWAIT | M_ZERO);
+ if (n == NULL) {
+ ND6_WUNLOCK();
+ return (NULL);
+ }
+ memcpy(n, new, sizeof(*n));
+ /* Initialize with an extra reference for the caller. */
+ refcount_init(&n->refcnt, 2);
}
- memcpy(n, new, sizeof(*n));
- /* Initialize with an extra reference for the caller. */
- refcount_init(&n->refcnt, 2);
-insert:
/*
* Insert the new router in the Default Router List;
* The Default Router List should be in the descending order
diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c
index 9768df5..ebcf6d6 100644
--- a/sys/netinet6/udp6_usrreq.c
+++ b/sys/netinet6/udp6_usrreq.c
@@ -876,8 +876,8 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
UDP_PROBE(send, NULL, inp, ip6, inp, udp6);
UDPSTAT_INC(udps_opackets);
- error = ip6_output(m, optp, NULL, flags, inp->in6p_moptions,
- NULL, inp);
+ error = ip6_output(m, optp, &inp->inp_route6, flags,
+ inp->in6p_moptions, NULL, inp);
break;
case AF_INET:
error = EAFNOSUPPORT;
diff --git a/sys/netipsec/ipsec_output.c b/sys/netipsec/ipsec_output.c
index 1523e0b..e0523d4 100644
--- a/sys/netipsec/ipsec_output.c
+++ b/sys/netipsec/ipsec_output.c
@@ -441,7 +441,7 @@ ipsec_encap(struct mbuf **mp, struct secasindex *saidx)
setdf = V_ip4_ipsec_dfbit;
break;
default:/* propagate to outer header */
- setdf = (ip->ip_off & ntohs(IP_DF)) != 0;
+ setdf = (ip->ip_off & htons(IP_DF)) != 0;
}
itos = ip->ip_tos;
break;
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index 283dddc9..0220286 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -6192,11 +6192,13 @@ pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0, struct inpcb *inp)
* We do need to be careful about bridges. If the
* net.link.bridge.pfil_bridge sysctl is set we can be filtering on a
* bridge, so if the input interface is a bridge member and the output
- * interface is its bridge we're not actually forwarding but bridging.
+ * interface is its bridge or a member of the same bridge we're not
+ * actually forwarding but bridging.
*/
- if (dir == PF_OUT && m->m_pkthdr.rcvif && ifp != m->m_pkthdr.rcvif
- && (m->m_pkthdr.rcvif->if_bridge == NULL
- || m->m_pkthdr.rcvif->if_bridge != ifp->if_softc))
+ if (dir == PF_OUT && m->m_pkthdr.rcvif && ifp != m->m_pkthdr.rcvif &&
+ (m->m_pkthdr.rcvif->if_bridge == NULL ||
+ (m->m_pkthdr.rcvif->if_bridge != ifp->if_softc &&
+ m->m_pkthdr.rcvif->if_bridge != ifp->if_bridge)))
fwdir = PF_FWD;
if (!V_pf_status.running)
diff --git a/sys/nfs/bootp_subr.c b/sys/nfs/bootp_subr.c
index dd76d7e..51c76e7 100644
--- a/sys/nfs/bootp_subr.c
+++ b/sys/nfs/bootp_subr.c
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/endian.h>
#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/sockio.h>
@@ -158,6 +159,7 @@ struct bootpc_ifcontext {
int dhcpquerytype; /* dhcp type sent */
struct in_addr dhcpserver;
int gotdhcpserver;
+ uint16_t mtu;
};
#define TAG_MAXLEN 1024
@@ -199,6 +201,7 @@ struct bootpc_globalcontext {
#define TAG_ROUTERS 3 /* Routers (in order of preference) */
#define TAG_HOSTNAME 12 /* Client host name */
#define TAG_ROOT 17 /* Root path */
+#define TAG_INTF_MTU 26 /* Interface MTU Size (RFC2132) */
/* DHCP specific tags */
#define TAG_OVERLOAD 52 /* Option Overload */
@@ -273,7 +276,7 @@ static int bootpc_call(struct bootpc_globalcontext *gctx,
static void bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx,
struct thread *td);
-static int bootpc_adjust_interface(struct bootpc_ifcontext *ifctx,
+static void bootpc_adjust_interface(struct bootpc_ifcontext *ifctx,
struct bootpc_globalcontext *gctx, struct thread *td);
static void bootpc_decode_reply(struct nfsv3_diskless *nd,
@@ -1008,33 +1011,41 @@ bootpc_shutdown_interface(struct bootpc_ifcontext *ifctx, struct thread *td)
panic("%s: SIOCDIFADDR, error=%d", __func__, error);
}
-static int
+static void
bootpc_adjust_interface(struct bootpc_ifcontext *ifctx,
struct bootpc_globalcontext *gctx, struct thread *td)
{
int error;
- struct sockaddr_in defdst;
- struct sockaddr_in defmask;
struct sockaddr_in *sin;
struct ifreq *ifr;
struct in_aliasreq *ifra;
struct sockaddr_in *myaddr;
struct sockaddr_in *netmask;
- struct sockaddr_in *gw;
ifr = &ifctx->ireq;
ifra = &ifctx->iareq;
myaddr = &ifctx->myaddr;
netmask = &ifctx->netmask;
- gw = &ifctx->gw;
if (bootpc_ifctx_isresolved(ifctx) == 0) {
/* Shutdown interfaces where BOOTP failed */
bootpc_shutdown_interface(ifctx, td);
- return (0);
+ return;
}
- printf("Adjusted interface %s\n", ifctx->ireq.ifr_name);
+ printf("Adjusted interface %s", ifctx->ireq.ifr_name);
+
+ /* Do BOOTP interface options */
+ if (ifctx->mtu != 0) {
+ printf(" (MTU=%d%s)", ifctx->mtu,
+ (ifctx->mtu > 1514) ? "/JUMBO" : "");
+ ifr->ifr_mtu = ifctx->mtu;
+ error = ifioctl(bootp_so, SIOCSIFMTU, (caddr_t) ifr, td);
+ if (error != 0)
+ panic("%s: SIOCSIFMTU, error=%d", __func__, error);
+ }
+ printf("\n");
+
/*
* Do enough of ifconfig(8) so that the chosen interface
* can talk to the servers. (just set the address)
@@ -1054,24 +1065,48 @@ bootpc_adjust_interface(struct bootpc_ifcontext *ifctx,
error = ifioctl(bootp_so, SIOCAIFADDR, (caddr_t)ifra, td);
if (error != 0)
panic("%s: SIOCAIFADDR, error=%d", __func__, error);
+}
+
+static void
+bootpc_add_default_route(struct bootpc_ifcontext *ifctx)
+{
+ int error;
+ struct sockaddr_in defdst;
+ struct sockaddr_in defmask;
- /* Add new default route */
+ if (ifctx->gw.sin_addr.s_addr == htonl(INADDR_ANY))
+ return;
- if (ifctx->gotgw != 0 || gctx->gotgw == 0) {
- clear_sinaddr(&defdst);
- clear_sinaddr(&defmask);
- /* XXX MRT just table 0 */
- error = rtrequest_fib(RTM_ADD,
- (struct sockaddr *) &defdst, (struct sockaddr *) gw,
- (struct sockaddr *) &defmask,
- (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL, RT_DEFAULT_FIB);
- if (error != 0) {
- printf("%s: RTM_ADD, error=%d\n", __func__, error);
- return (error);
- }
+ clear_sinaddr(&defdst);
+ clear_sinaddr(&defmask);
+
+ error = rtrequest_fib(RTM_ADD, (struct sockaddr *)&defdst,
+ (struct sockaddr *) &ifctx->gw, (struct sockaddr *)&defmask,
+ (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL, RT_DEFAULT_FIB);
+ if (error != 0) {
+ printf("%s: RTM_ADD, error=%d\n", __func__, error);
}
+}
+
+static void
+bootpc_remove_default_route(struct bootpc_ifcontext *ifctx)
+{
+ int error;
+ struct sockaddr_in defdst;
+ struct sockaddr_in defmask;
+
+ if (ifctx->gw.sin_addr.s_addr == htonl(INADDR_ANY))
+ return;
+
+ clear_sinaddr(&defdst);
+ clear_sinaddr(&defmask);
- return (0);
+ error = rtrequest_fib(RTM_DELETE, (struct sockaddr *)&defdst,
+ (struct sockaddr *) &ifctx->gw, (struct sockaddr *)&defmask,
+ (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL, RT_DEFAULT_FIB);
+ if (error != 0) {
+ printf("%s: RTM_DELETE, error=%d\n", __func__, error);
+ }
}
static int
@@ -1463,6 +1498,8 @@ bootpc_decode_reply(struct nfsv3_diskless *nd, struct bootpc_ifcontext *ifctx,
if (p == NULL) {
p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen,
TAG_ROOT);
+ if (p != NULL)
+ ifctx->gotrootpath = 1;
}
#ifdef ROOTDEVNAME
if ((p == NULL || (boothowto & RB_DFLTROOT) != 0) &&
@@ -1482,7 +1519,6 @@ bootpc_decode_reply(struct nfsv3_diskless *nd, struct bootpc_ifcontext *ifctx,
}
printf("rootfs %s ", p);
gctx->gotrootpath = 1;
- ifctx->gotrootpath = 1;
gctx->setrootfs = ifctx;
p = bootpc_tag(&gctx->tag, &ifctx->reply,
@@ -1522,6 +1558,11 @@ bootpc_decode_reply(struct nfsv3_diskless *nd, struct bootpc_ifcontext *ifctx,
p[i] = '\0';
}
+ p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen,
+ TAG_INTF_MTU);
+ if (p != NULL) {
+ ifctx->mtu = be16dec(p);
+ }
printf("\n");
@@ -1533,10 +1574,6 @@ bootpc_decode_reply(struct nfsv3_diskless *nd, struct bootpc_ifcontext *ifctx,
else
ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSC_NET);
}
- if (ifctx->gotgw == 0) {
- /* Use proxyarp */
- ifctx->gw.sin_addr.s_addr = ifctx->myaddr.sin_addr.s_addr;
- }
}
void
@@ -1728,9 +1765,11 @@ retry:
kern_setenv("boot.netif.name", ifctx->ifp->if_xname);
+ bootpc_add_default_route(ifctx);
error = md_mount(&nd->root_saddr, nd->root_hostnam,
nd->root_fh, &nd->root_fhsize,
&nd->root_args, td);
+ bootpc_remove_default_route(ifctx);
if (error != 0) {
if (gctx->any_root_overrides == 0)
panic("nfs_boot: mount root, error=%d", error);
@@ -1748,6 +1787,7 @@ retry:
ifctx->myaddr.sin_addr.s_addr |
~ ifctx->netmask.sin_addr.s_addr;
bcopy(&ifctx->netmask, &nd->myif.ifra_mask, sizeof(ifctx->netmask));
+ bcopy(&ifctx->gw, &nd->mygateway, sizeof(ifctx->gw));
out:
while((ifctx = STAILQ_FIRST(&gctx->interfaces)) != NULL) {
diff --git a/sys/nfs/nfs_diskless.c b/sys/nfs/nfs_diskless.c
index 864aae0..e765c2e 100644
--- a/sys/nfs/nfs_diskless.c
+++ b/sys/nfs/nfs_diskless.c
@@ -154,6 +154,7 @@ nfs_parse_options(const char *envopts, struct nfs_args *nd)
* boot.netif.netmask netmask on boot interface
* boot.netif.gateway default gateway (optional)
* boot.netif.hwaddr hardware address of boot interface
+ * boot.netif.mtu interface mtu from bootp/dhcp (optional)
* boot.nfsroot.server IP address of root filesystem server
* boot.nfsroot.path path of the root filesystem on server
* boot.nfsroot.nfshandle NFS handle for root filesystem on server
diff --git a/sys/ofed/drivers/infiniband/core/iwcm.c b/sys/ofed/drivers/infiniband/core/iwcm.c
index a90f907..7e27584 100644
--- a/sys/ofed/drivers/infiniband/core/iwcm.c
+++ b/sys/ofed/drivers/infiniband/core/iwcm.c
@@ -79,7 +79,6 @@ struct iwcm_listen_work {
static LIST_HEAD(listen_port_list);
static DEFINE_MUTEX(listen_port_mutex);
-static DEFINE_MUTEX(dequeue_mutex);
struct listen_port_info {
struct list_head list;
@@ -455,7 +454,6 @@ iw_so_event_handler(struct work_struct *_work)
kfree(work);
return;
}
- mutex_lock(&dequeue_mutex);
/* Dequeue & process all new 'so' connection requests for this cmid */
while ((so = dequeue_socket(work->cm_id->so)) != NULL) {
@@ -475,7 +473,6 @@ iw_so_event_handler(struct work_struct *_work)
}
}
err:
- mutex_unlock(&dequeue_mutex);
kfree(work);
#endif
return;
@@ -487,7 +484,6 @@ iw_so_upcall(struct socket *parent_so, void *arg, int waitflag)
struct socket *so;
struct iw_cm_id *cm_id = arg;
- mutex_lock(&dequeue_mutex);
/* check whether iw_so_event_handler() already dequeued this 'so' */
so = TAILQ_FIRST(&parent_so->so_comp);
if (!so)
@@ -500,7 +496,6 @@ iw_so_upcall(struct socket *parent_so, void *arg, int waitflag)
INIT_WORK(&work->work, iw_so_event_handler);
queue_work(iwcm_wq, &work->work);
- mutex_unlock(&dequeue_mutex);
return SU_OK;
}
diff --git a/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib.h b/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib.h
index eb269a4..acf3d54 100644
--- a/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -322,6 +322,8 @@ struct ipoib_dev_priv {
unsigned long flags;
+ int gone;
+
struct mutex vlan_mutex;
struct rb_root path_tree;
diff --git a/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c b/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 5e69a52..9a68b23 100644
--- a/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -258,6 +258,10 @@ ipoib_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
struct ifreq *ifr = (struct ifreq *) data;
int error = 0;
+ /* check if detaching */
+ if (priv == NULL || priv->gone != 0)
+ return (ENXIO);
+
switch (command) {
case SIOCSIFFLAGS:
if (ifp->if_flags & IFF_UP) {
@@ -794,6 +798,7 @@ ipoib_detach(struct ipoib_dev_priv *priv)
dev = priv->dev;
if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) {
+ priv->gone = 1;
bpfdetach(dev);
if_detach(dev);
if_free(dev);
diff --git a/sys/ofed/drivers/net/mlx4/en_port.c b/sys/ofed/drivers/net/mlx4/en_port.c
index e4dab0a..2a1c4ba 100644
--- a/sys/ofed/drivers/net/mlx4/en_port.c
+++ b/sys/ofed/drivers/net/mlx4/en_port.c
@@ -60,10 +60,11 @@ int mlx4_SET_VLAN_FLTR(struct mlx4_dev *dev, struct mlx4_en_priv *priv)
memset(filter, 0, sizeof(*filter));
for (i = VLAN_FLTR_SIZE - 1; i >= 0; i--) {
entry = 0;
- for (j = 0; j < 32; j++)
+ for (j = 0; j < 32; j++) {
if (test_bit(index, priv->active_vlans))
entry |= 1 << j;
- index++;
+ index++;
+ }
filter->entry[i] = cpu_to_be32(entry);
}
err = mlx4_cmd(dev, mailbox->dma, priv->port, 0, MLX4_CMD_SET_VLAN_FLTR,
diff --git a/sys/ofed/drivers/net/mlx4/en_rx.c b/sys/ofed/drivers/net/mlx4/en_rx.c
index 7c5b759..b29096d 100644
--- a/sys/ofed/drivers/net/mlx4/en_rx.c
+++ b/sys/ofed/drivers/net/mlx4/en_rx.c
@@ -561,9 +561,6 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
struct mbuf *mb;
struct mlx4_cq *mcq = &cq->mcq;
struct mlx4_cqe *buf = cq->buf;
-#ifdef INET
- struct lro_entry *queued;
-#endif
int index;
unsigned int length;
int polled = 0;
@@ -616,7 +613,8 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
goto next;
}
- mb->m_pkthdr.flowid = cq->ring;
+ /* forward Toeplitz compatible hash value */
+ mb->m_pkthdr.flowid = be32_to_cpu(cqe->immed_rss_invalid);
M_HASHTYPE_SET(mb, M_HASHTYPE_OPAQUE);
mb->m_pkthdr.rcvif = dev;
if (be32_to_cpu(cqe->vlan_my_qpn) &
@@ -668,10 +666,7 @@ next:
/* Flush all pending IP reassembly sessions */
out:
#ifdef INET
- while ((queued = SLIST_FIRST(&ring->lro.lro_active)) != NULL) {
- SLIST_REMOVE_HEAD(&ring->lro.lro_active, next);
- tcp_lro_flush(&ring->lro, queued);
- }
+ tcp_lro_flush_all(&ring->lro);
#endif
AVG_PERF_COUNTER(priv->pstats.rx_coal_avg, polled);
mcq->cons_index = cons_index;
diff --git a/sys/ofed/drivers/net/mlx4/en_tx.c b/sys/ofed/drivers/net/mlx4/en_tx.c
index 56bb5b2..4358aa6 100644
--- a/sys/ofed/drivers/net/mlx4/en_tx.c
+++ b/sys/ofed/drivers/net/mlx4/en_tx.c
@@ -1060,7 +1060,7 @@ mlx4_en_transmit(struct ifnet *dev, struct mbuf *m)
/* Compute which queue to use */
if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) {
- i = m->m_pkthdr.flowid % priv->tx_ring_num;
+ i = (m->m_pkthdr.flowid % 128) % priv->tx_ring_num;
}
else {
i = mlx4_en_select_queue(dev, m);
diff --git a/sys/pc98/pc98/canbus.c b/sys/pc98/pc98/canbus.c
index 8c3ee4e..0c54ceb 100644
--- a/sys/pc98/pc98/canbus.c
+++ b/sys/pc98/pc98/canbus.c
@@ -433,9 +433,9 @@ print_all_resources(device_t dev)
if (STAILQ_FIRST(rl))
retval += printf(" at");
- retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx");
- retval += resource_list_print_type(rl, "iomem", SYS_RES_MEMORY, "%#lx");
- retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+ retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#jx");
+ retval += resource_list_print_type(rl, "iomem", SYS_RES_MEMORY, "%#jx");
+ retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
return retval;
}
diff --git a/sys/powerpc/include/bus.h b/sys/powerpc/include/bus.h
index 658c4eb..cb6dc77 100644
--- a/sys/powerpc/include/bus.h
+++ b/sys/powerpc/include/bus.h
@@ -79,9 +79,14 @@
#define BUS_SPACE_MAXADDR 0xFFFFFFFFFFFFFFFFUL
#define BUS_SPACE_MAXSIZE 0xFFFFFFFFFFFFFFFFUL
#else
+#ifdef BOOKE
+#define BUS_SPACE_MAXADDR 0xFFFFFFFFFULL
+#define BUS_SPACE_MAXSIZE 0xFFFFFFFFUL
+#else
#define BUS_SPACE_MAXADDR 0xFFFFFFFFUL
#define BUS_SPACE_MAXSIZE 0xFFFFFFFFUL
#endif
+#endif
#define BUS_SPACE_MAP_CACHEABLE 0x01
#define BUS_SPACE_MAP_LINEAR 0x02
diff --git a/sys/powerpc/mpc85xx/fsl_sdhc.c b/sys/powerpc/mpc85xx/fsl_sdhc.c
index 174a8e6..29bedd8 100644
--- a/sys/powerpc/mpc85xx/fsl_sdhc.c
+++ b/sys/powerpc/mpc85xx/fsl_sdhc.c
@@ -126,7 +126,7 @@ static devclass_t fsl_sdhc_devclass;
DRIVER_MODULE(sdhci_fsl, simplebus, fsl_sdhc_driver, fsl_sdhc_devclass, 0, 0);
DRIVER_MODULE(mmc, sdhci_fsl, mmc_driver, mmc_devclass, NULL, NULL);
-
+MODULE_DEPEND(sdhci_fsl, mmc, 1, 1, 1);
/*****************************************************************************
* Private methods
diff --git a/sys/powerpc/mpc85xx/lbc.c b/sys/powerpc/mpc85xx/lbc.c
index a94a841..37e3ed0 100644
--- a/sys/powerpc/mpc85xx/lbc.c
+++ b/sys/powerpc/mpc85xx/lbc.c
@@ -718,8 +718,8 @@ lbc_alloc_resource(device_t bus, device_t child, int type, int *rid,
res = rman_reserve_resource(rm, start, end, count, flags, child);
if (res == NULL) {
- device_printf(bus, "failed to reserve resource %#lx - %#lx "
- "(%#lx)\n", start, end, count);
+ device_printf(bus, "failed to reserve resource %#jx - %#jx "
+ "(%#jx)\n", start, end, count);
return (NULL);
}
@@ -749,8 +749,8 @@ lbc_print_child(device_t dev, device_t child)
rv = 0;
rv += bus_print_child_header(dev, child);
- rv += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
- rv += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+ rv += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
+ rv += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
rv += bus_print_child_footer(dev, child);
return (rv);
diff --git a/sys/powerpc/mpc85xx/pci_mpc85xx.c b/sys/powerpc/mpc85xx/pci_mpc85xx.c
index 4397ac0..5a141b6 100644
--- a/sys/powerpc/mpc85xx/pci_mpc85xx.c
+++ b/sys/powerpc/mpc85xx/pci_mpc85xx.c
@@ -58,12 +58,11 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/ofw_pci.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/ofwpci.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcib_private.h>
-#include <powerpc/ofw/ofw_pci.h>
-
#include "ofw_bus_if.h"
#include "pcib_if.h"
diff --git a/sys/powerpc/ofw/ofw_pci.c b/sys/powerpc/ofw/ofw_pci.c
index 0ca5bc0..20aa81f 100644
--- a/sys/powerpc/ofw/ofw_pci.c
+++ b/sys/powerpc/ofw/ofw_pci.c
@@ -384,10 +384,10 @@ ofw_pci_activate_resource(device_t bus, device_t child, int type, int rid,
}
if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
struct ofw_pci_range *rp;
- vm_offset_t start;
+ vm_paddr_t start;
int space;
- start = (vm_offset_t)rman_get_start(res);
+ start = (vm_paddr_t)rman_get_start(res);
/*
* Map this through the ranges list
@@ -416,8 +416,8 @@ ofw_pci_activate_resource(device_t bus, device_t child, int type, int rid,
}
if (bootverbose)
- printf("ofw_pci mapdev: start %zx, len %ld\n", start,
- rman_get_size(res));
+ printf("ofw_pci mapdev: start %jx, len %jd\n",
+ (rman_res_t)start, rman_get_size(res));
p = pmap_mapdev(start, (vm_size_t)rman_get_size(res));
if (p == NULL)
diff --git a/sys/powerpc/powermac/cpcht.c b/sys/powerpc/powermac/cpcht.c
index 765d946..3145689 100644
--- a/sys/powerpc/powermac/cpcht.c
+++ b/sys/powerpc/powermac/cpcht.c
@@ -51,7 +51,7 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
-#include <powerpc/ofw/ofw_pci.h>
+#include <dev/ofw/ofwpci.h>
#include <vm/vm.h>
#include <vm/pmap.h>
diff --git a/sys/powerpc/powermac/grackle.c b/sys/powerpc/powermac/grackle.c
index 95d59a1..3d35fea 100644
--- a/sys/powerpc/powermac/grackle.c
+++ b/sys/powerpc/powermac/grackle.c
@@ -35,11 +35,13 @@ __FBSDID("$FreeBSD$");
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/proc.h>
+#include <sys/rman.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_pci.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/ofwpci.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
@@ -50,9 +52,6 @@ __FBSDID("$FreeBSD$");
#include <machine/pio.h>
#include <machine/resource.h>
-#include <sys/rman.h>
-
-#include <powerpc/ofw/ofw_pci.h>
#include <powerpc/powermac/gracklevar.h>
#include <vm/vm.h>
diff --git a/sys/powerpc/powermac/macgpio.c b/sys/powerpc/powermac/macgpio.c
index 6b67514..c72f8d7 100644
--- a/sys/powerpc/powermac/macgpio.c
+++ b/sys/powerpc/powermac/macgpio.c
@@ -236,7 +236,7 @@ macgpio_print_child(device_t dev, device_t child)
printf(" addr 0x%02x", dinfo->gpio_num); /* should not happen */
resource_list_print_type(&dinfo->mdi_resources, "irq", SYS_RES_IRQ,
- "%ld");
+ "%jd");
retval += bus_print_child_footer(dev, child);
return (retval);
@@ -258,7 +258,7 @@ macgpio_probe_nomatch(device_t dev, device_t child)
if (dinfo->gpio_num >= 0)
printf(" gpio %d",dinfo->gpio_num);
resource_list_print_type(&dinfo->mdi_resources, "irq",
- SYS_RES_IRQ, "%ld");
+ SYS_RES_IRQ, "%jd");
printf(" (no driver attached)\n");
}
}
diff --git a/sys/powerpc/powermac/macio.c b/sys/powerpc/powermac/macio.c
index 285d627..7a15b85 100644
--- a/sys/powerpc/powermac/macio.c
+++ b/sys/powerpc/powermac/macio.c
@@ -447,8 +447,8 @@ macio_print_child(device_t dev, device_t child)
retval += bus_print_child_header(dev, child);
- retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
- retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+ retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
+ retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
retval += bus_print_child_footer(dev, child);
@@ -470,8 +470,8 @@ macio_probe_nomatch(device_t dev, device_t child)
if ((type = ofw_bus_get_type(child)) == NULL)
type = "(unknown)";
device_printf(dev, "<%s, %s>", type, ofw_bus_get_name(child));
- resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
- resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+ resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
+ resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
printf(" (no driver attached)\n");
}
}
diff --git a/sys/powerpc/powermac/uninorth.c b/sys/powerpc/powermac/uninorth.c
index e34c9d8..2d32a49 100644
--- a/sys/powerpc/powermac/uninorth.c
+++ b/sys/powerpc/powermac/uninorth.c
@@ -425,8 +425,8 @@ unin_chip_print_child(device_t dev, device_t child)
retval += bus_print_child_header(dev, child);
- retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
- retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+ retval += resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
+ retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
retval += bus_print_child_footer(dev, child);
@@ -447,8 +447,8 @@ unin_chip_probe_nomatch(device_t dev, device_t child)
if ((type = ofw_bus_get_type(child)) == NULL)
type = "(unknown)";
device_printf(dev, "<%s, %s>", type, ofw_bus_get_name(child));
- resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#lx");
- resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+ resource_list_print_type(rl, "mem", SYS_RES_MEMORY, "%#jx");
+ resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
printf(" (no driver attached)\n");
}
}
@@ -591,7 +591,7 @@ unin_chip_activate_resource(device_t bus, device_t child, int type, int rid,
start = (vm_offset_t) rman_get_start(res);
if (bootverbose)
- printf("unin mapdev: start %zx, len %ld\n", start,
+ printf("unin mapdev: start %zx, len %jd\n", start,
rman_get_size(res));
p = pmap_mapdev(start, (vm_size_t) rman_get_size(res));
diff --git a/sys/powerpc/powermac/uninorthpci.c b/sys/powerpc/powermac/uninorthpci.c
index 9da06ff..6149af5 100644
--- a/sys/powerpc/powermac/uninorthpci.c
+++ b/sys/powerpc/powermac/uninorthpci.c
@@ -32,11 +32,13 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/kernel.h>
+#include <sys/rman.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_pci.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/ofwpci.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
@@ -47,9 +49,6 @@ __FBSDID("$FreeBSD$");
#include <machine/pio.h>
#include <machine/resource.h>
-#include <sys/rman.h>
-
-#include <powerpc/ofw/ofw_pci.h>
#include <powerpc/powermac/uninorthvar.h>
#include <vm/vm.h>
diff --git a/sys/powerpc/powermac/uninorthvar.h b/sys/powerpc/powermac/uninorthvar.h
index e08478d..e570da0 100644
--- a/sys/powerpc/powermac/uninorthvar.h
+++ b/sys/powerpc/powermac/uninorthvar.h
@@ -30,7 +30,7 @@
#include <dev/ofw/ofw_bus_subr.h>
#include <dev/ofw/ofw_pci.h>
-#include <powerpc/ofw/ofw_pci.h>
+#include <dev/ofw/ofwpci.h>
struct uninorth_softc {
struct ofw_pci_softc pci_sc;
diff --git a/sys/powerpc/powerpc/nexus.c b/sys/powerpc/powerpc/nexus.c
index 1ad118c..f5a3da8 100644
--- a/sys/powerpc/powerpc/nexus.c
+++ b/sys/powerpc/powerpc/nexus.c
@@ -203,7 +203,7 @@ nexus_activate_resource(device_t bus __unused, device_t child __unused,
start = (vm_paddr_t) rman_get_start(r);
if (bootverbose)
- printf("nexus mapdev: start %jx, len %ld\n",
+ printf("nexus mapdev: start %jx, len %jd\n",
(uintmax_t)start, rman_get_size(r));
p = pmap_mapdev(start, (vm_size_t) rman_get_size(r));
diff --git a/sys/powerpc/ps3/ps3bus.c b/sys/powerpc/ps3/ps3bus.c
index bbb40c8..37ea0b7 100644
--- a/sys/powerpc/ps3/ps3bus.c
+++ b/sys/powerpc/ps3/ps3bus.c
@@ -480,9 +480,9 @@ ps3bus_print_child(device_t dev, device_t child)
retval += bus_print_child_header(dev, child);
retval += resource_list_print_type(&dinfo->resources, "mem",
- SYS_RES_MEMORY, "%#lx");
+ SYS_RES_MEMORY, "%#jx");
retval += resource_list_print_type(&dinfo->resources, "irq",
- SYS_RES_IRQ, "%ld");
+ SYS_RES_IRQ, "%jd");
retval += bus_print_child_footer(dev, child);
diff --git a/sys/powerpc/pseries/rtas_pci.c b/sys/powerpc/pseries/rtas_pci.c
index bb72b71..873168e 100644
--- a/sys/powerpc/pseries/rtas_pci.c
+++ b/sys/powerpc/pseries/rtas_pci.c
@@ -32,11 +32,13 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/kernel.h>
+#include <sys/rman.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_pci.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/ofwpci.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
@@ -48,12 +50,9 @@ __FBSDID("$FreeBSD$");
#include <machine/resource.h>
#include <machine/rtas.h>
-#include <sys/rman.h>
-
#include <vm/vm.h>
#include <vm/pmap.h>
-#include <powerpc/ofw/ofw_pci.h>
#include <powerpc/pseries/plpar_iommu.h>
#include "pcib_if.h"
diff --git a/sys/powerpc/pseries/vdevice.c b/sys/powerpc/pseries/vdevice.c
index 2323bc7..72b76c7 100644
--- a/sys/powerpc/pseries/vdevice.c
+++ b/sys/powerpc/pseries/vdevice.c
@@ -180,7 +180,7 @@ vdevice_print_child(device_t dev, device_t child)
retval += bus_print_child_header(dev, child);
- retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+ retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
retval += bus_print_child_footer(dev, child);
diff --git a/sys/powerpc/psim/iobus.c b/sys/powerpc/psim/iobus.c
index 741b62a..ce4a93a 100644
--- a/sys/powerpc/psim/iobus.c
+++ b/sys/powerpc/psim/iobus.c
@@ -253,7 +253,7 @@ iobus_print_child(device_t dev, device_t child)
retval += bus_print_child_header(dev, child);
retval += printf(" offset 0x%x", dinfo->id_reg[1]);
- retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+ retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
retval += bus_print_child_footer(dev, child);
diff --git a/sys/rpc/rpc_generic.c b/sys/rpc/rpc_generic.c
index 28aa849..80d658d 100644
--- a/sys/rpc/rpc_generic.c
+++ b/sys/rpc/rpc_generic.c
@@ -390,15 +390,11 @@ __rpc_uaddr2taddr_af(int af, const char *uaddr)
}
ret = (struct netbuf *)malloc(sizeof *ret, M_RPC, M_WAITOK);
- if (ret == NULL)
- goto out;
switch (af) {
case AF_INET:
sin = (struct sockaddr_in *)malloc(sizeof *sin, M_RPC,
M_WAITOK);
- if (sin == NULL)
- goto out;
memset(sin, 0, sizeof *sin);
sin->sin_family = AF_INET;
sin->sin_port = htons(port);
@@ -415,8 +411,6 @@ __rpc_uaddr2taddr_af(int af, const char *uaddr)
case AF_INET6:
sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6, M_RPC,
M_WAITOK);
- if (sin6 == NULL)
- goto out;
memset(sin6, 0, sizeof *sin6);
sin6->sin6_family = AF_INET6;
sin6->sin6_port = htons(port);
@@ -433,8 +427,6 @@ __rpc_uaddr2taddr_af(int af, const char *uaddr)
case AF_LOCAL:
sun = (struct sockaddr_un *)malloc(sizeof *sun, M_RPC,
M_WAITOK);
- if (sun == NULL)
- goto out;
memset(sun, 0, sizeof *sun);
sun->sun_family = AF_LOCAL;
strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1);
diff --git a/sys/rpc/svc.c b/sys/rpc/svc.c
index f725d53..b436c18 100644
--- a/sys/rpc/svc.c
+++ b/sys/rpc/svc.c
@@ -560,7 +560,7 @@ svc_loss_reg(SVCXPRT *xprt, void (*dispatch)(SVCXPRT *))
mtx_unlock(&pool->sp_lock);
return (TRUE);
}
- s = malloc(sizeof (struct svc_callout), M_RPC, M_NOWAIT);
+ s = malloc(sizeof(struct svc_loss_callout), M_RPC, M_NOWAIT);
if (s == NULL) {
mtx_unlock(&pool->sp_lock);
return (FALSE);
diff --git a/sys/sparc64/central/central.c b/sys/sparc64/central/central.c
index 15876f0..9b16364 100644
--- a/sys/sparc64/central/central.c
+++ b/sys/sparc64/central/central.c
@@ -295,5 +295,5 @@ central_print_res(struct central_devinfo *cdi)
{
return (resource_list_print_type(&cdi->cdi_rl, "mem", SYS_RES_MEMORY,
- "%#lx"));
+ "%#jx"));
}
diff --git a/sys/sparc64/ebus/ebus.c b/sys/sparc64/ebus/ebus.c
index a53b20b..49abe18 100644
--- a/sys/sparc64/ebus/ebus.c
+++ b/sys/sparc64/ebus/ebus.c
@@ -721,8 +721,8 @@ ebus_print_res(struct ebus_devinfo *edi)
retval = 0;
retval += resource_list_print_type(&edi->edi_rl, "addr", SYS_RES_MEMORY,
- "%#lx");
+ "%#jx");
retval += resource_list_print_type(&edi->edi_rl, "irq", SYS_RES_IRQ,
- "%ld");
+ "%jd");
return (retval);
}
diff --git a/sys/sparc64/fhc/fhc.c b/sys/sparc64/fhc/fhc.c
index b9d8bc6..85aa67d 100644
--- a/sys/sparc64/fhc/fhc.c
+++ b/sys/sparc64/fhc/fhc.c
@@ -529,7 +529,7 @@ fhc_print_res(struct fhc_devinfo *fdi)
rv = 0;
rv += resource_list_print_type(&fdi->fdi_rl, "mem", SYS_RES_MEMORY,
- "%#lx");
- rv += resource_list_print_type(&fdi->fdi_rl, "irq", SYS_RES_IRQ, "%ld");
+ "%#jx");
+ rv += resource_list_print_type(&fdi->fdi_rl, "irq", SYS_RES_IRQ, "%jd");
return (rv);
}
diff --git a/sys/sparc64/pci/apb.c b/sys/sparc64/pci/apb.c
index ba3643c..55f1313 100644
--- a/sys/sparc64/pci/apb.c
+++ b/sys/sparc64/pci/apb.c
@@ -136,7 +136,7 @@ apb_map_print(uint8_t map, rman_res_t scale)
for (first = 1, i = 0; i < 8; i++) {
if ((map & (1 << i)) != 0) {
- printf("%s0x%lx-0x%lx", first ? "" : ", ",
+ printf("%s0x%jx-0x%jx", first ? "" : ", ",
i * scale, (i + 1) * scale - 1);
first = 0;
}
@@ -253,26 +253,26 @@ apb_alloc_resource(device_t dev, device_t child, int type, int *rid,
case SYS_RES_IOPORT:
if (!apb_checkrange(sc->sc_iomap, APB_IO_SCALE, start, end)) {
device_printf(dev, "device %s requested unsupported "
- "I/O range 0x%lx-0x%lx\n",
+ "I/O range 0x%jx-0x%jx\n",
device_get_nameunit(child), start, end);
return (NULL);
}
if (bootverbose)
device_printf(sc->sc_bsc.ops_pcib_sc.dev, "device "
- "%s requested decoded I/O range 0x%lx-0x%lx\n",
+ "%s requested decoded I/O range 0x%jx-0x%jx\n",
device_get_nameunit(child), start, end);
break;
case SYS_RES_MEMORY:
if (!apb_checkrange(sc->sc_memmap, APB_MEM_SCALE, start,
end)) {
device_printf(dev, "device %s requested unsupported "
- "memory range 0x%lx-0x%lx\n",
+ "memory range 0x%jx-0x%jx\n",
device_get_nameunit(child), start, end);
return (NULL);
}
if (bootverbose)
device_printf(sc->sc_bsc.ops_pcib_sc.dev, "device "
- "%s requested decoded memory range 0x%lx-0x%lx\n",
+ "%s requested decoded memory range 0x%jx-0x%jx\n",
device_get_nameunit(child), start, end);
break;
}
diff --git a/sys/sparc64/sbus/dma_sbus.c b/sys/sparc64/sbus/dma_sbus.c
index cf22569..4a83c92 100644
--- a/sys/sparc64/sbus/dma_sbus.c
+++ b/sys/sparc64/sbus/dma_sbus.c
@@ -409,7 +409,7 @@ dma_print_res(struct dma_devinfo *ddi)
rv = 0;
rv += resource_list_print_type(&ddi->ddi_rl, "mem", SYS_RES_MEMORY,
- "%#lx");
- rv += resource_list_print_type(&ddi->ddi_rl, "irq", SYS_RES_IRQ, "%ld");
+ "%#jx");
+ rv += resource_list_print_type(&ddi->ddi_rl, "irq", SYS_RES_IRQ, "%jd");
return (rv);
}
diff --git a/sys/sparc64/sbus/sbus.c b/sys/sparc64/sbus/sbus.c
index af46c77..65e44ff 100644
--- a/sys/sparc64/sbus/sbus.c
+++ b/sys/sparc64/sbus/sbus.c
@@ -929,8 +929,8 @@ sbus_print_res(struct sbus_devinfo *sdi)
rv = 0;
rv += resource_list_print_type(&sdi->sdi_rl, "mem", SYS_RES_MEMORY,
- "%#lx");
+ "%#jx");
rv += resource_list_print_type(&sdi->sdi_rl, "irq", SYS_RES_IRQ,
- "%ld");
+ "%jd");
return (rv);
}
diff --git a/sys/sparc64/sparc64/nexus.c b/sys/sparc64/sparc64/nexus.c
index 3e099bd..3e72b6c 100644
--- a/sys/sparc64/sparc64/nexus.c
+++ b/sys/sparc64/sparc64/nexus.c
@@ -605,8 +605,8 @@ nexus_print_res(struct nexus_devinfo *ndi)
rv = 0;
rv += resource_list_print_type(&ndi->ndi_rl, "mem", SYS_RES_MEMORY,
- "%#lx");
+ "%#jx");
rv += resource_list_print_type(&ndi->ndi_rl, "irq", SYS_RES_IRQ,
- "%ld");
+ "%jd");
return (rv);
}
diff --git a/sys/sparc64/sparc64/upa.c b/sys/sparc64/sparc64/upa.c
index 504d001..34bc50f 100644
--- a/sys/sparc64/sparc64/upa.c
+++ b/sys/sparc64/sparc64/upa.c
@@ -588,8 +588,8 @@ upa_print_res(struct upa_devinfo *udi)
rv = 0;
rv += resource_list_print_type(&udi->udi_rl, "mem", SYS_RES_MEMORY,
- "%#lx");
+ "%#jx");
rv += resource_list_print_type(&udi->udi_rl, "irq", SYS_RES_IRQ,
- "%ld");
+ "%jd");
return (rv);
}
diff --git a/sys/sys/_types.h b/sys/sys/_types.h
index 3b3c16d..16039a6 100644
--- a/sys/sys/_types.h
+++ b/sys/sys/_types.h
@@ -112,6 +112,6 @@ typedef union {
__int64_t _mbstateL; /* for alignment */
} __mbstate_t;
-typedef unsigned long __rman_res_t;
+typedef __uintmax_t __rman_res_t;
#endif /* !_SYS__TYPES_H_ */
diff --git a/sys/sys/aio.h b/sys/sys/aio.h
index 25ffb28..0abee2d 100644
--- a/sys/sys/aio.h
+++ b/sys/sys/aio.h
@@ -238,7 +238,7 @@ int aio_suspend(const struct aiocb * const[], int, const struct timespec *);
int aio_mlock(struct aiocb *);
#ifdef __BSD_VISIBLE
-int aio_waitcomplete(struct aiocb **, struct timespec *);
+ssize_t aio_waitcomplete(struct aiocb **, struct timespec *);
#endif
int aio_fsync(int op, struct aiocb *aiocbp);
diff --git a/sys/sys/bus.h b/sys/sys/bus.h
index 5f0df65..e0297cc 100644
--- a/sys/sys/bus.h
+++ b/sys/sys/bus.h
@@ -141,6 +141,7 @@ void devctl_notify(const char *__system, const char *__subsystem,
const char *__type, const char *__data);
void devctl_queue_data_f(char *__data, int __flags);
void devctl_queue_data(char *__data);
+void devctl_safe_quote(char *__dst, const char *__src, size_t len);
/**
* Device name parsers. Hook to allow device enumerators to map
diff --git a/sys/sys/fail.h b/sys/sys/fail.h
index e011459..bd2eab1 100644
--- a/sys/sys/fail.h
+++ b/sys/sys/fail.h
@@ -37,6 +37,11 @@
#include <sys/linker_set.h>
#include <sys/queue.h>
#include <sys/sysctl.h>
+#include <sys/condvar.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/systm.h>
/**
* Failpoint return codes, used internally.
@@ -49,7 +54,8 @@ enum fail_point_return_code {
};
struct fail_point_entry;
-TAILQ_HEAD(fail_point_entries, fail_point_entry);
+struct fail_point_setting;
+
/**
* Internal failpoint structure, tracking all the current details of the
* failpoint. This structure is the core component shared between the
@@ -57,22 +63,42 @@ TAILQ_HEAD(fail_point_entries, fail_point_entry);
* @ingroup failpoint_private
*/
struct fail_point {
- const char *fp_name; /**< name of fail point */
- const char *fp_location; /**< file:line of fail point */
- struct fail_point_entries fp_entries; /**< list of entries */
+ const char *fp_name; /* name of fail point */
+ const char *fp_location; /* file:line of fail point */
+ volatile int fp_ref_cnt; /**
+ * protects fp_setting: while holding
+ * a ref, fp_setting points to an
+ * unfreed fail_point_setting
+ */
+ struct fail_point_setting * volatile fp_setting;
int fp_flags;
- void (*fp_sleep_fn)(void *); /**< Function to call at end of
- * sleep for sleep failpoints */
- void *fp_sleep_arg; /**< Arg for sleep_fn */
+
+ /**< Function to call before sleep or pause */
+ void (*fp_pre_sleep_fn)(void *);
+ /**< Arg for fp_pre_sleep_fn */
+ void *fp_pre_sleep_arg;
+
+ /**< Function to call after waking from sleep or pause */
+ void (*fp_post_sleep_fn)(void *);
+ /**< Arg for fp_post_sleep_fn */
+ void *fp_post_sleep_arg;
};
#define FAIL_POINT_DYNAMIC_NAME 0x01 /**< Must free name on destroy */
+/**< Use timeout path for sleep instead of msleep */
+#define FAIL_POINT_USE_TIMEOUT_PATH 0x02
+/**< If fail point is set to sleep, replace the sleep call with delay */
+#define FAIL_POINT_NONSLEEPABLE 0x04
+
+#define FAIL_POINT_CV_DESC "fp cv no iterators"
+#define FAIL_POINT_IS_OFF(fp) (__predict_true((fp)->fp_setting == NULL) || \
+ __predict_true(fail_point_is_off(fp)))
__BEGIN_DECLS
/* Private failpoint eval function -- use fail_point_eval() instead. */
enum fail_point_return_code fail_point_eval_nontrivial(struct fail_point *,
- int *ret);
+ int *ret);
/**
* @addtogroup failpoint
@@ -86,26 +112,62 @@ enum fail_point_return_code fail_point_eval_nontrivial(struct fail_point *,
void fail_point_init(struct fail_point *, const char *fmt, ...)
__printflike(2, 3);
+/* Return true iff this fail point is set to off, false otherwise */
+bool fail_point_is_off(struct fail_point *fp);
+
+/**
+ * Set the pre-sleep function for a fail point
+ * If fp_post_sleep_fn is specified, then FAIL_POINT_SLEEP will result in a
+ * (*fp->fp_pre_sleep_fn)(fp->fp_pre_sleep_arg) call by the thread.
+ */
+static inline void
+fail_point_sleep_set_pre_func(struct fail_point *fp, void (*sleep_fn)(void *))
+{
+ fp->fp_pre_sleep_fn = sleep_fn;
+}
+
+static inline void
+fail_point_sleep_set_pre_arg(struct fail_point *fp, void *sleep_arg)
+{
+ fp->fp_pre_sleep_arg = sleep_arg;
+}
+
/**
- * Set the sleep function for a fail point
- * If sleep_fn is specified, then FAIL_POINT_SLEEP will result in a
- * (*fp->sleep_fn)(fp->sleep_arg) call by the timer thread. Otherwise,
- * if sleep_fn is NULL (default), then FAIL_POINT_SLEEP will result in the
- * fail_point_eval() call sleeping.
+ * Set the post-sleep function. This will be passed to timeout if we take
+ * the timeout path. This must be set if you sleep using the timeout path.
*/
-static __inline void
-fail_point_sleep_set_func(struct fail_point *fp, void (*sleep_fn)(void *))
+static inline void
+fail_point_sleep_set_post_func(struct fail_point *fp, void (*sleep_fn)(void *))
{
- fp->fp_sleep_fn = sleep_fn;
+ fp->fp_post_sleep_fn = sleep_fn;
}
+static inline void
+fail_point_sleep_set_post_arg(struct fail_point *fp, void *sleep_arg)
+{
+ fp->fp_post_sleep_arg = sleep_arg;
+}
/**
- * Set the argument for the sleep function for a fail point
+ * If the FAIL_POINT_USE_TIMEOUT flag is set on a failpoint, then
+ * FAIL_POINT_SLEEP will result in a call to timeout instead of
+ * msleep. Note that if you sleep while this flag is set, you must
+ * set fp_post_sleep_fn or an error will occur upon waking.
*/
-static __inline void
-fail_point_sleep_set_arg(struct fail_point *fp, void *sleep_arg)
+static inline void
+fail_point_use_timeout_path(struct fail_point *fp, bool use_timeout,
+ void (*post_sleep_fn)(void *))
{
- fp->fp_sleep_arg = sleep_arg;
+ KASSERT(!use_timeout || post_sleep_fn != NULL ||
+ (post_sleep_fn == NULL && fp->fp_post_sleep_fn != NULL),
+ ("Setting fp to use timeout, but not setting post_sleep_fn\n"));
+
+ if (use_timeout)
+ fp->fp_flags |= FAIL_POINT_USE_TIMEOUT_PATH;
+ else
+ fp->fp_flags &= ~FAIL_POINT_USE_TIMEOUT_PATH;
+
+ if (post_sleep_fn != NULL)
+ fp->fp_post_sleep_fn = post_sleep_fn;
}
/**
@@ -116,33 +178,64 @@ void fail_point_destroy(struct fail_point *);
/**
* Evaluate a failpoint.
*/
-static __inline enum fail_point_return_code
+static inline enum fail_point_return_code
fail_point_eval(struct fail_point *fp, int *ret)
{
- if (TAILQ_EMPTY(&fp->fp_entries)) {
+ if (__predict_true(fp->fp_setting == NULL))
return (FAIL_POINT_RC_CONTINUE);
- }
return (fail_point_eval_nontrivial(fp, ret));
}
__END_DECLS
/* Declare a fail_point and its sysctl in a function. */
-#define _FAIL_POINT_NAME(name) _fail_point_##name
-#define _FAIL_POINT_LOCATION() "(" __FILE__ ":" __XSTRING(__LINE__) ")"
+#define _FAIL_POINT_NAME(name) _fail_point_##name
+#define _FAIL_POINT_LOCATION() "(" __FILE__ ":" __XSTRING(__LINE__) ")"
+#define _FAIL_POINT_INIT(parent, name, flags) \
+ static struct fail_point _FAIL_POINT_NAME(name) = { \
+ .fp_name = #name, \
+ .fp_location = _FAIL_POINT_LOCATION(), \
+ .fp_ref_cnt = 0, \
+ .fp_setting = NULL, \
+ .fp_flags = (flags), \
+ .fp_pre_sleep_fn = NULL, \
+ .fp_pre_sleep_arg = NULL, \
+ .fp_post_sleep_fn = NULL, \
+ .fp_post_sleep_arg = NULL, \
+ }; \
+ SYSCTL_OID(parent, OID_AUTO, name, \
+ CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, \
+ &_FAIL_POINT_NAME(name), 0, fail_point_sysctl, \
+ "A", ""); \
+ SYSCTL_OID(parent, OID_AUTO, status_##name, \
+ CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, \
+ &_FAIL_POINT_NAME(name), 0, \
+ fail_point_sysctl_status, "A", "");
+#define _FAIL_POINT_EVAL(name, cond, code...) \
+ int RETURN_VALUE; \
+ \
+ if (__predict_false(cond && \
+ fail_point_eval(&_FAIL_POINT_NAME(name), &RETURN_VALUE))) { \
+ \
+ code; \
+ \
+ }
+
/**
- * Instantiate a failpoint which returns "value" from the function when triggered.
- * @param parent The parent sysctl under which to locate the sysctl
+ * Instantiate a failpoint which returns "RETURN_VALUE" from the function
+ * when triggered.
+ * @param parent The parent sysctl under which to locate the fp's sysctl
* @param name The name of the failpoint in the sysctl tree (and printouts)
- * @return Instantly returns the return("value") specified in the
+ * @return Instantly returns the RETURN_VALUE specified in the
* failpoint, if triggered.
*/
#define KFAIL_POINT_RETURN(parent, name) \
KFAIL_POINT_CODE(parent, name, return RETURN_VALUE)
/**
- * Instantiate a failpoint which returns (void) from the function when triggered.
+ * Instantiate a failpoint which returns (void) from the function when
+ * triggered.
* @param parent The parent sysctl under which to locate the sysctl
* @param name The name of the failpoint in the sysctl tree (and printouts)
* @return Instantly returns void, if triggered in the failpoint.
@@ -153,7 +246,8 @@ __END_DECLS
/**
* Instantiate a failpoint which sets an error when triggered.
* @param parent The parent sysctl under which to locate the sysctl
- * @param name The name of the failpoint in the sysctl tree (and printouts)
+ * @param name The name of the failpoint in the sysctl tree (and
+ * printouts)
* @param error_var A variable to set to the failpoint's specified
* return-value when triggered
*/
@@ -164,7 +258,8 @@ __END_DECLS
* Instantiate a failpoint which sets an error and then goes to a
* specified label in the function when triggered.
* @param parent The parent sysctl under which to locate the sysctl
- * @param name The name of the failpoint in the sysctl tree (and printouts)
+ * @param name The name of the failpoint in the sysctl tree (and
+ * printouts)
* @param error_var A variable to set to the failpoint's specified
* return-value when triggered
* @param label The location to goto when triggered.
@@ -173,39 +268,81 @@ __END_DECLS
KFAIL_POINT_CODE(parent, name, (error_var) = RETURN_VALUE; goto label)
/**
+ * Instantiate a failpoint which sets its pre- and post-sleep callback
+ * mechanisms.
+ * @param parent The parent sysctl under which to locate the sysctl
+ * @param name The name of the failpoint in the sysctl tree (and
+ * printouts)
+ * @param pre_func Function pointer to the pre-sleep function, which will be
+ * called directly before going to sleep.
+ * @param pre_arg Argument to the pre-sleep function
+ * @param post_func Function pointer to the pot-sleep function, which will be
+ * called directly before going to sleep.
+ * @param post_arg Argument to the post-sleep function
+ */
+#define KFAIL_POINT_SLEEP_CALLBACKS(parent, name, pre_func, pre_arg, \
+ post_func, post_arg) \
+ KFAIL_POINT_CODE_SLEEP_CALLBACKS(parent, name, pre_func, \
+ pre_arg, post_func, post_arg, return RETURN_VALUE)
+
+/**
+ * Instantiate a failpoint which runs arbitrary code when triggered, and sets
+ * its pre- and post-sleep callback mechanisms
+ * @param parent The parent sysctl under which to locate the sysctl
+ * @param name The name of the failpoint in the sysctl tree (and
+ * printouts)
+ * @param pre_func Function pointer to the pre-sleep function, which will be
+ * called directly before going to sleep.
+ * @param pre_arg Argument to the pre-sleep function
+ * @param post_func Function pointer to the pot-sleep function, which will be
+ * called directly before going to sleep.
+ * @param post_arg Argument to the post-sleep function
+ * @param code The arbitrary code to run when triggered. Can reference
+ * "RETURN_VALUE" if desired to extract the specified
+ * user return-value when triggered. Note that this is
+ * implemented with a do-while loop so be careful of
+ * break and continue statements.
+ */
+#define KFAIL_POINT_CODE_SLEEP_CALLBACKS(parent, name, pre_func, pre_arg, \
+ post_func, post_arg, code...) \
+ do { \
+ _FAIL_POINT_INIT(parent, name) \
+ _FAIL_POINT_NAME(name).fp_pre_sleep_fn = pre_func; \
+ _FAIL_POINT_NAME(name).fp_pre_sleep_arg = pre_arg; \
+ _FAIL_POINT_NAME(name).fp_post_sleep_fn = post_func; \
+ _FAIL_POINT_NAME(name).fp_post_sleep_arg = post_arg; \
+ _FAIL_POINT_EVAL(name, true, code) \
+ } while (0)
+
+
+/**
* Instantiate a failpoint which runs arbitrary code when triggered.
* @param parent The parent sysctl under which to locate the sysctl
* @param name The name of the failpoint in the sysctl tree
- * (and printouts)
+ * (and printouts)
* @param code The arbitrary code to run when triggered. Can reference
* "RETURN_VALUE" if desired to extract the specified
* user return-value when triggered. Note that this is
* implemented with a do-while loop so be careful of
* break and continue statements.
*/
-#define KFAIL_POINT_CODE(parent, name, code) \
-do { \
- int RETURN_VALUE; \
- static struct fail_point _FAIL_POINT_NAME(name) = { \
- #name, \
- _FAIL_POINT_LOCATION(), \
- TAILQ_HEAD_INITIALIZER(_FAIL_POINT_NAME(name).fp_entries), \
- 0, \
- NULL, NULL, \
- }; \
- SYSCTL_OID(parent, OID_AUTO, name, \
- CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, \
- &_FAIL_POINT_NAME(name), 0, fail_point_sysctl, \
- "A", ""); \
- \
- if (__predict_false( \
- fail_point_eval(&_FAIL_POINT_NAME(name), &RETURN_VALUE))) { \
- \
- code; \
- \
- } \
-} while (0)
+#define KFAIL_POINT_CODE(parent, name, code...) \
+ do { \
+ _FAIL_POINT_INIT(parent, name, 0) \
+ _FAIL_POINT_EVAL(name, true, code) \
+ } while (0)
+
+#define KFAIL_POINT_CODE_FLAGS(parent, name, flags, code...) \
+ do { \
+ _FAIL_POINT_INIT(parent, name, flags) \
+ _FAIL_POINT_EVAL(name, true, code) \
+ } while (0)
+#define KFAIL_POINT_CODE_COND(parent, name, cond, flags, code...) \
+ do { \
+ _FAIL_POINT_INIT(parent, name, flags) \
+ _FAIL_POINT_EVAL(name, cond, code) \
+ } while (0)
/**
* @}
@@ -214,6 +351,7 @@ do { \
#ifdef _KERNEL
int fail_point_sysctl(SYSCTL_HANDLER_ARGS);
+int fail_point_sysctl_status(SYSCTL_HANDLER_ARGS);
/* The fail point sysctl tree. */
SYSCTL_DECL(_debug_fail_point);
diff --git a/sys/sys/file.h b/sys/sys/file.h
index 524c1ce..c30eb05 100644
--- a/sys/sys/file.h
+++ b/sys/sys/file.h
@@ -112,7 +112,7 @@ typedef int fo_chown_t(struct file *fp, uid_t uid, gid_t gid,
struct ucred *active_cred, struct thread *td);
typedef int fo_sendfile_t(struct file *fp, int sockfd, struct uio *hdr_uio,
struct uio *trl_uio, off_t offset, size_t nbytes,
- off_t *sent, int flags, int kflags, struct thread *td);
+ off_t *sent, int flags, struct thread *td);
typedef int fo_seek_t(struct file *fp, off_t offset, int whence,
struct thread *td);
typedef int fo_fill_kinfo_t(struct file *fp, struct kinfo_file *kif,
@@ -376,11 +376,11 @@ fo_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred,
static __inline int
fo_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio,
struct uio *trl_uio, off_t offset, size_t nbytes, off_t *sent, int flags,
- int kflags, struct thread *td)
+ struct thread *td)
{
return ((*fp->f_ops->fo_sendfile)(fp, sockfd, hdr_uio, trl_uio, offset,
- nbytes, sent, flags, kflags, td));
+ nbytes, sent, flags, td));
}
static __inline int
diff --git a/sys/sys/intr.h b/sys/sys/intr.h
index 5ef2379..04325c1 100644
--- a/sys/sys/intr.h
+++ b/sys/sys/intr.h
@@ -1,7 +1,6 @@
-/* $NetBSD: intr.h,v 1.7 2003/06/16 20:01:00 thorpej Exp $ */
-
/*-
- * Copyright (c) 1997 Mark Brinicombe.
+ * Copyright (c) 2015-2016 Svatopluk Kraus
+ * Copyright (c) 2015-2016 Michal Meloun
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -12,28 +11,20 @@
* 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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Mark Brinicombe
- * for the NetBSD Project.
- * 4. The name of the company nor the name of the author may be used to
- * endorse or promote products derived from this software without specific
- * prior written permission.
*
- * 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 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)
+ * 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 _SYS_INTR_H_
@@ -41,6 +32,37 @@
#include <sys/systm.h>
+enum intr_map_data_type {
+ INTR_MAP_DATA_ACPI,
+ INTR_MAP_DATA_FDT,
+};
+
+#ifdef DEV_ACPI
+struct intr_map_data_acpi {
+ u_int irq;
+ enum intr_polarity pol;
+ enum intr_trigger trig;
+};
+#endif
+#ifdef FDT
+struct intr_map_data_fdt {
+ u_int ncells;
+ pcell_t *cells;
+};
+#endif
+
+struct intr_map_data {
+ enum intr_map_data_type type;
+ union {
+#ifdef DEV_ACPI
+ struct intr_map_data_acpi acpi;
+#endif
+#ifdef FDT
+ struct intr_map_data_fdt fdt;
+#endif
+ };
+};
+
#ifdef notyet
#define INTR_SOLO INTR_MD1
typedef int intr_irq_filter_t(void *arg, struct trapframe *tf);
@@ -50,30 +72,16 @@ typedef int intr_irq_filter_t(void *arg);
#define INTR_ISRC_NAMELEN (MAXCOMLEN + 1)
-typedef void intr_ipi_filter_t(void *arg);
-
-enum intr_isrc_type {
- INTR_ISRCT_NAMESPACE,
- INTR_ISRCT_FDT
-};
-
-#define INTR_ISRCF_REGISTERED 0x01 /* registered in a controller */
-#define INTR_ISRCF_PERCPU 0x02 /* per CPU interrupt */
+#define INTR_ISRCF_IPI 0x01 /* IPI interrupt */
+#define INTR_ISRCF_PPI 0x02 /* PPI interrupt */
#define INTR_ISRCF_BOUND 0x04 /* bound to a CPU */
/* Interrupt source definition. */
struct intr_irqsrc {
device_t isrc_dev; /* where isrc is mapped */
- intptr_t isrc_xref; /* device reference key */
- uintptr_t isrc_data; /* device data for isrc */
u_int isrc_irq; /* unique identificator */
- enum intr_isrc_type isrc_type; /* how is isrc decribed */
u_int isrc_flags;
char isrc_name[INTR_ISRC_NAMELEN];
- uint16_t isrc_nspc_type;
- uint16_t isrc_nspc_num;
- enum intr_trigger isrc_trig;
- enum intr_polarity isrc_pol;
cpuset_t isrc_cpu; /* on which CPUs is enabled */
u_int isrc_index;
u_long * isrc_count;
@@ -81,47 +89,46 @@ struct intr_irqsrc {
struct intr_event * isrc_event;
#ifdef INTR_SOLO
intr_irq_filter_t * isrc_filter;
-#endif
- intr_ipi_filter_t * isrc_ipifilter;
void * isrc_arg;
-#ifdef FDT
- u_int isrc_ncells;
- pcell_t isrc_cells[]; /* leave it last */
#endif
};
-void intr_irq_set_name(struct intr_irqsrc *isrc, const char *fmt, ...)
- __printflike(2, 3);
+/* Intr interface for PIC. */
+int intr_isrc_deregister(struct intr_irqsrc *);
+int intr_isrc_register(struct intr_irqsrc *, device_t, u_int, const char *, ...)
+ __printflike(4, 5);
-void intr_irq_dispatch(struct intr_irqsrc *isrc, struct trapframe *tf);
-
-#define INTR_IRQ_NSPC_NONE 0
-#define INTR_IRQ_NSPC_PLAIN 1
-#define INTR_IRQ_NSPC_IRQ 2
-#define INTR_IRQ_NSPC_IPI 3
+int intr_isrc_dispatch(struct intr_irqsrc *, struct trapframe *);
+u_int intr_irq_next_cpu(u_int current_cpu, cpuset_t *cpumask);
-u_int intr_namespace_map_irq(device_t dev, uint16_t type, uint16_t num);
-#ifdef FDT
-u_int intr_fdt_map_irq(phandle_t, pcell_t *, u_int);
-#endif
+int intr_pic_register(device_t, intptr_t);
+int intr_pic_deregister(device_t, intptr_t);
+int intr_pic_claim_root(device_t, intptr_t, intr_irq_filter_t *, void *, u_int);
extern device_t intr_irq_root_dev;
-int intr_pic_register(device_t dev, intptr_t xref);
-int intr_pic_unregister(device_t dev, intptr_t xref);
-int intr_pic_claim_root(device_t dev, intptr_t xref, intr_irq_filter_t *filter,
- void *arg, u_int ipicount);
+/* Intr interface for BUS. */
+int intr_map_irq(device_t, intptr_t, struct intr_map_data *, u_int *);
-int intr_irq_add_handler(device_t dev, driver_filter_t, driver_intr_t, void *,
- u_int, int, void **);
-int intr_irq_remove_handler(device_t dev, u_int, void *);
-int intr_irq_config(u_int, enum intr_trigger, enum intr_polarity);
-int intr_irq_describe(u_int, void *, const char *);
+int intr_alloc_irq(device_t, struct resource *);
+int intr_release_irq(device_t, struct resource *);
-u_int intr_irq_next_cpu(u_int current_cpu, cpuset_t *cpumask);
+int intr_setup_irq(device_t, struct resource *, driver_filter_t, driver_intr_t,
+ void *, int, void **);
+int intr_teardown_irq(device_t, struct resource *, void *);
+
+int intr_describe_irq(device_t, struct resource *, void *, const char *);
+
+#ifdef DEV_ACPI
+u_int intr_acpi_map_irq(device_t, u_int, enum intr_polarity,
+ enum intr_trigger);
+#endif
+#ifdef FDT
+u_int intr_fdt_map_irq(phandle_t, pcell_t *, u_int);
+#endif
#ifdef SMP
-int intr_irq_bind(u_int, int);
+int intr_bind_irq(device_t, struct resource *, int);
void intr_pic_init_secondary(void);
diff --git a/sys/sys/libkern.h b/sys/sys/libkern.h
index efbaa4a..b1b7257 100644
--- a/sys/sys/libkern.h
+++ b/sys/sys/libkern.h
@@ -65,6 +65,16 @@ static __inline u_quad_t uqmax(u_quad_t a, u_quad_t b) { return (a > b ? a : b);
static __inline u_quad_t uqmin(u_quad_t a, u_quad_t b) { return (a < b ? a : b); }
static __inline u_long ulmax(u_long a, u_long b) { return (a > b ? a : b); }
static __inline u_long ulmin(u_long a, u_long b) { return (a < b ? a : b); }
+static __inline __uintmax_t ummax(__uintmax_t a, __uintmax_t b)
+{
+
+ return (a > b ? a : b);
+}
+static __inline __uintmax_t ummin(__uintmax_t a, __uintmax_t b)
+{
+
+ return (a < b ? a : b);
+}
static __inline off_t omax(off_t a, off_t b) { return (a > b ? a : b); }
static __inline off_t omin(off_t a, off_t b) { return (a < b ? a : b); }
diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h
index 0b9fb2b..4a48d47 100644
--- a/sys/sys/mbuf.h
+++ b/sys/sys/mbuf.h
@@ -44,6 +44,32 @@
#endif
#endif
+#ifdef _KERNEL
+#include <sys/sdt.h>
+
+#define MBUF_PROBE1(probe, arg0) \
+ SDT_PROBE1(sdt, , , probe, arg0)
+#define MBUF_PROBE2(probe, arg0, arg1) \
+ SDT_PROBE2(sdt, , , probe, arg0, arg1)
+#define MBUF_PROBE3(probe, arg0, arg1, arg2) \
+ SDT_PROBE3(sdt, , , probe, arg0, arg1, arg2)
+#define MBUF_PROBE4(probe, arg0, arg1, arg2, arg3) \
+ SDT_PROBE4(sdt, , , probe, arg0, arg1, arg2, arg3)
+#define MBUF_PROBE5(probe, arg0, arg1, arg2, arg3, arg4) \
+ SDT_PROBE5(sdt, , , probe, arg0, arg1, arg2, arg3, arg4)
+
+SDT_PROBE_DECLARE(sdt, , , m__init);
+SDT_PROBE_DECLARE(sdt, , , m__gethdr);
+SDT_PROBE_DECLARE(sdt, , , m__get);
+SDT_PROBE_DECLARE(sdt, , , m__getcl);
+SDT_PROBE_DECLARE(sdt, , , m__clget);
+SDT_PROBE_DECLARE(sdt, , , m__cljget);
+SDT_PROBE_DECLARE(sdt, , , m__cljset);
+SDT_PROBE_DECLARE(sdt, , , m__free);
+SDT_PROBE_DECLARE(sdt, , , m__freem);
+
+#endif /* _KERNEL */
+
/*
* Mbufs are of a single size, MSIZE (sys/param.h), which includes overhead.
* An mbuf may add a single "mbuf cluster" of size MCLBYTES (also in
@@ -672,42 +698,52 @@ m_init(struct mbuf *m, int how, short type, int flags)
m->m_len = 0;
m->m_flags = flags;
m->m_type = type;
- if (flags & M_PKTHDR) {
- if ((error = m_pkthdr_init(m, how)) != 0)
- return (error);
- }
+ if (flags & M_PKTHDR)
+ error = m_pkthdr_init(m, how);
+ else
+ error = 0;
- return (0);
+ MBUF_PROBE5(m__init, m, how, type, flags, error);
+ return (error);
}
static __inline struct mbuf *
m_get(int how, short type)
{
+ struct mbuf *m;
struct mb_args args;
args.flags = 0;
args.type = type;
- return (uma_zalloc_arg(zone_mbuf, &args, how));
+ m = uma_zalloc_arg(zone_mbuf, &args, how);
+ MBUF_PROBE3(m__get, how, type, m);
+ return (m);
}
static __inline struct mbuf *
m_gethdr(int how, short type)
{
+ struct mbuf *m;
struct mb_args args;
args.flags = M_PKTHDR;
args.type = type;
- return (uma_zalloc_arg(zone_mbuf, &args, how));
+ m = uma_zalloc_arg(zone_mbuf, &args, how);
+ MBUF_PROBE3(m__gethdr, how, type, m);
+ return (m);
}
static __inline struct mbuf *
m_getcl(int how, short type, int flags)
{
+ struct mbuf *m;
struct mb_args args;
args.flags = flags;
args.type = type;
- return (uma_zalloc_arg(zone_pack, &args, how));
+ m = uma_zalloc_arg(zone_pack, &args, how);
+ MBUF_PROBE4(m__getcl, how, type, flags, m);
+ return (m);
}
/*
@@ -747,6 +783,7 @@ m_cljset(struct mbuf *m, void *cl, int type)
m->m_ext.ext_flags = EXT_FLAG_EMBREF;
m->m_ext.ext_count = 1;
m->m_flags |= M_EXT;
+ MBUF_PROBE3(m__cljset, m, cl, type);
}
static __inline void
@@ -1122,6 +1159,7 @@ m_free(struct mbuf *m)
{
struct mbuf *n = m->m_next;
+ MBUF_PROBE1(m__free, m);
if ((m->m_flags & (M_PKTHDR|M_NOFREE)) == (M_PKTHDR|M_NOFREE))
m_tag_delete_chain(m, NULL);
if (m->m_flags & M_EXT)
diff --git a/sys/sys/osd.h b/sys/sys/osd.h
index 14316ae..820e0f4 100644
--- a/sys/sys/osd.h
+++ b/sys/sys/osd.h
@@ -59,6 +59,10 @@ int osd_register(u_int type, osd_destructor_t destructor,
void osd_deregister(u_int type, u_int slot);
int osd_set(u_int type, struct osd *osd, u_int slot, void *value);
+void *osd_reserve(u_int slot);
+int osd_set_reserved(u_int type, struct osd *osd, u_int slot, void *rsv,
+ void *value);
+void osd_free_reserved(void *rsv);
void *osd_get(u_int type, struct osd *osd, u_int slot);
void osd_del(u_int type, struct osd *osd, u_int slot);
int osd_call(u_int type, u_int method, void *obj, void *data);
@@ -71,6 +75,8 @@ void osd_exit(u_int type, struct osd *osd);
osd_deregister(OSD_THREAD, (slot))
#define osd_thread_set(td, slot, value) \
osd_set(OSD_THREAD, &(td)->td_osd, (slot), (value))
+#define osd_thread_set_reserved(td, slot, rsv, value) \
+ osd_set_reserved(OSD_THREAD, &(td)->td_osd, (slot), (rsv), (value))
#define osd_thread_get(td, slot) \
osd_get(OSD_THREAD, &(td)->td_osd, (slot))
#define osd_thread_del(td, slot) do { \
@@ -88,6 +94,8 @@ void osd_exit(u_int type, struct osd *osd);
osd_deregister(OSD_JAIL, (slot))
#define osd_jail_set(pr, slot, value) \
osd_set(OSD_JAIL, &(pr)->pr_osd, (slot), (value))
+#define osd_jail_set_reserved(pr, slot, rsv, value) \
+ osd_set_reserved(OSD_JAIL, &(pr)->pr_osd, (slot), (rsv), (value))
#define osd_jail_get(pr, slot) \
osd_get(OSD_JAIL, &(pr)->pr_osd, (slot))
#define osd_jail_del(pr, slot) \
diff --git a/sys/sys/param.h b/sys/sys/param.h
index 9108576..987453c 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -58,7 +58,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 1100102 /* Master, propagated to newvers */
+#define __FreeBSD_version 1100104 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index f9ca6d9..2d1769e 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -162,6 +162,7 @@ struct pargs {
*/
struct cpuset;
struct filecaps;
+struct filemon;
struct kaioinfo;
struct kaudit_record;
struct kdtrace_proc;
@@ -253,6 +254,7 @@ struct thread {
int td_slptick; /* (t) Time at sleep. */
int td_blktick; /* (t) Time spent blocked. */
int td_swvoltick; /* (t) Time at last SW_VOL switch. */
+ int td_swinvoltick; /* (t) Time at last SW_INVOL switch. */
u_int td_cow; /* (*) Number of copy-on-write faults */
struct rusage td_ru; /* (t) rusage information. */
struct rusage_ext td_rux; /* (t) Internal rusage information. */
@@ -580,6 +582,7 @@ struct proc {
struct procdesc *p_procdesc; /* (e) Process descriptor, if any. */
u_int p_treeflag; /* (e) P_TREE flags */
int p_pendingexits; /* (c) Count of pending thread exits. */
+ struct filemon *p_filemon; /* (c) filemon-specific data. */
/* End area that is zeroed on creation. */
#define p_endzero p_magic
diff --git a/sys/sys/racct.h b/sys/sys/racct.h
index 3075856..8d1f2fa 100644
--- a/sys/sys/racct.h
+++ b/sys/sys/racct.h
@@ -98,7 +98,7 @@ extern int racct_enable;
/*
* Resource usage can drop, as opposed to only grow. When the process
- * terminates, its resource usage is freed from the respective
+ * terminates, its resource usage is subtracted from the respective
* per-credential racct containers.
*/
#define RACCT_IS_RECLAIMABLE(X) (racct_types[X] & RACCT_RECLAIMABLE)
@@ -126,8 +126,7 @@ extern int racct_enable;
* When a process terminates, its resource usage is not automatically
* subtracted from per-credential racct containers. Instead, the resource
* usage of per-credential racct containers decays in time.
- * Resource usage can olso drop for such resource.
- * So far, the only such resource is RACCT_PCTCPU.
+ * Resource usage can also drop for such resource.
*/
#define RACCT_IS_DECAYING(X) (racct_types[X] & RACCT_DECAYING)
diff --git a/sys/sys/sleepqueue.h b/sys/sys/sleepqueue.h
index cdb7a39..d59dc7e 100644
--- a/sys/sys/sleepqueue.h
+++ b/sys/sys/sleepqueue.h
@@ -107,5 +107,11 @@ int sleepq_type(void *wchan);
void sleepq_wait(void *wchan, int pri);
int sleepq_wait_sig(void *wchan, int pri);
+#ifdef STACK
+struct sbuf;
+int sleepq_sbuf_print_stacks(struct sbuf *sb, void *wchan, int queue,
+ int *count_stacks_printed);
+#endif
+
#endif /* _KERNEL */
#endif /* !_SYS_SLEEPQUEUE_H_ */
diff --git a/sys/sys/smp.h b/sys/sys/smp.h
index 58b1754..904b9f7 100644
--- a/sys/sys/smp.h
+++ b/sys/sys/smp.h
@@ -17,9 +17,52 @@
#ifndef LOCORE
#include <sys/cpuset.h>
+#include <sys/queue.h>
/*
- * Topology of a NUMA or HTT system.
+ * Types of nodes in the topological tree.
+ */
+typedef enum {
+ /* No node has this type; can be used in topo API calls. */
+ TOPO_TYPE_DUMMY,
+ /* Processing unit aka computing unit aka logical CPU. */
+ TOPO_TYPE_PU,
+ /* Physical subdivision of a package. */
+ TOPO_TYPE_CORE,
+ /* CPU L1/L2/L3 cache. */
+ TOPO_TYPE_CACHE,
+ /* Package aka chip, equivalent to socket. */
+ TOPO_TYPE_PKG,
+ /* NUMA node. */
+ TOPO_TYPE_NODE,
+ /* Other logical or physical grouping of PUs. */
+ /* E.g. PUs on the same dye, or PUs sharing an FPU. */
+ TOPO_TYPE_GROUP,
+ /* The whole system. */
+ TOPO_TYPE_SYSTEM
+} topo_node_type;
+
+/* Hardware indenitifier of a topology component. */
+typedef unsigned int hwid_t;
+/* Logical CPU idenitifier. */
+typedef int cpuid_t;
+
+/* A node in the topology. */
+struct topo_node {
+ struct topo_node *parent;
+ TAILQ_HEAD(topo_children, topo_node) children;
+ TAILQ_ENTRY(topo_node) siblings;
+ cpuset_t cpuset;
+ topo_node_type type;
+ uintptr_t subtype;
+ hwid_t hwid;
+ cpuid_t id;
+ int nchildren;
+ int cpu_count;
+};
+
+/*
+ * Scheduling topology of a NUMA or SMP system.
*
* The top level topology is an array of pointers to groups. Each group
* contains a bitmask of cpus in its group or subgroups. It may also
@@ -52,6 +95,8 @@ typedef struct cpu_group *cpu_group_t;
#define CG_SHARE_L2 2
#define CG_SHARE_L3 3
+#define MAX_CACHE_LEVELS CG_SHARE_L3
+
/*
* Behavior modifiers for load balancing and affinity.
*/
@@ -60,10 +105,29 @@ typedef struct cpu_group *cpu_group_t;
#define CG_FLAG_THREAD (CG_FLAG_HTT | CG_FLAG_SMT) /* Any threading. */
/*
- * Convenience routines for building topologies.
+ * Convenience routines for building and traversing topologies.
*/
#ifdef SMP
+void topo_init_node(struct topo_node *node);
+void topo_init_root(struct topo_node *root);
+struct topo_node * topo_add_node_by_hwid(struct topo_node *parent, int hwid,
+ topo_node_type type, uintptr_t subtype);
+struct topo_node * topo_find_node_by_hwid(struct topo_node *parent, int hwid,
+ topo_node_type type, uintptr_t subtype);
+void topo_promote_child(struct topo_node *child);
+struct topo_node * topo_next_node(struct topo_node *top,
+ struct topo_node *node);
+struct topo_node * topo_next_nonchild_node(struct topo_node *top,
+ struct topo_node *node);
+void topo_set_pu_id(struct topo_node *node, cpuid_t id);
+int topo_analyze(struct topo_node *topo_root, int all, int *pkg_count,
+ int *cores_per_pkg, int *thrs_per_core);
+
+#define TOPO_FOREACH(i, root) \
+ for (i = root; i != NULL; i = topo_next_node(root, i))
+
struct cpu_group *smp_topo(void);
+struct cpu_group *smp_topo_alloc(u_int count);
struct cpu_group *smp_topo_none(void);
struct cpu_group *smp_topo_1level(int l1share, int l1count, int l1flags);
struct cpu_group *smp_topo_2level(int l2share, int l2count, int l1share,
diff --git a/sys/sys/socket.h b/sys/sys/socket.h
index c20b075..649ba00 100644
--- a/sys/sys/socket.h
+++ b/sys/sys/socket.h
@@ -594,7 +594,6 @@ struct sf_hdtr {
#define SF_FLAGS(rh, flags) (((rh) << 16) | (flags))
#ifdef _KERNEL
-#define SFK_COMPAT 0x00000001
#define SF_READAHEAD(flags) ((flags) >> 16)
#endif /* _KERNEL */
diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h
index fef33b8..8a32a64 100644
--- a/sys/sys/syscall.h
+++ b/sys/sys/syscall.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/kern/syscalls.master 296572 2016-03-09 19:05:11Z jhb
+ * created from FreeBSD: head/sys/kern/syscalls.master 297167 2016-03-21 21:37:33Z jhb
*/
#define SYS_syscall 0
diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk
index 3f62141..a264838 100644
--- a/sys/sys/syscall.mk
+++ b/sys/sys/syscall.mk
@@ -1,7 +1,7 @@
# FreeBSD system call object files.
# DO NOT EDIT-- this file is automatically generated.
# $FreeBSD$
-# created from FreeBSD: head/sys/kern/syscalls.master 296572 2016-03-09 19:05:11Z jhb
+# created from FreeBSD: head/sys/kern/syscalls.master 297167 2016-03-21 21:37:33Z jhb
MIASM = \
syscall.o \
exit.o \
diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h
index 7c1e79c..eb5eef0 100644
--- a/sys/sys/sysctl.h
+++ b/sys/sys/sysctl.h
@@ -204,6 +204,7 @@ int sysctl_handle_long(SYSCTL_HANDLER_ARGS);
int sysctl_handle_string(SYSCTL_HANDLER_ARGS);
int sysctl_handle_opaque(SYSCTL_HANDLER_ARGS);
int sysctl_handle_counter_u64(SYSCTL_HANDLER_ARGS);
+int sysctl_handle_counter_u64_array(SYSCTL_HANDLER_ARGS);
int sysctl_handle_uma_zone_max(SYSCTL_HANDLER_ARGS);
int sysctl_handle_uma_zone_cur(SYSCTL_HANDLER_ARGS);
@@ -640,11 +641,34 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry);
#define SYSCTL_ADD_COUNTER_U64(ctx, parent, nbr, name, access, ptr, descr) \
({ \
+ counter_u64_t *__ptr = (ptr); \
CTASSERT(((access) & CTLTYPE) == 0 || \
((access) & SYSCTL_CT_ASSERT_MASK) == CTLTYPE_U64); \
sysctl_add_oid(ctx, parent, nbr, name, \
CTLTYPE_U64 | CTLFLAG_MPSAFE | (access), \
- ptr, 0, sysctl_handle_counter_u64, "QU", __DESCR(descr)); \
+ __ptr, 0, sysctl_handle_counter_u64, "QU", __DESCR(descr)); \
+})
+
+/* Oid for an array of counter(9)s. The pointer and length must be non zero. */
+#define SYSCTL_COUNTER_U64_ARRAY(parent, nbr, name, access, ptr, len, descr) \
+ SYSCTL_OID(parent, nbr, name, \
+ CTLTYPE_OPAQUE | CTLFLAG_MPSAFE | (access), \
+ (ptr), (len), sysctl_handle_counter_u64_array, "S", descr); \
+ CTASSERT((((access) & CTLTYPE) == 0 || \
+ ((access) & SYSCTL_CT_ASSERT_MASK) == CTLTYPE_OPAQUE) && \
+ sizeof(counter_u64_t) == sizeof(*(ptr)) && \
+ sizeof(uint64_t) == sizeof(**(ptr)))
+
+#define SYSCTL_ADD_COUNTER_U64_ARRAY(ctx, parent, nbr, name, access, \
+ ptr, len, descr) \
+({ \
+ counter_u64_t *__ptr = (ptr); \
+ CTASSERT(((access) & CTLTYPE) == 0 || \
+ ((access) & SYSCTL_CT_ASSERT_MASK) == CTLTYPE_OPAQUE); \
+ sysctl_add_oid(ctx, parent, nbr, name, \
+ CTLTYPE_OPAQUE | CTLFLAG_MPSAFE | (access), \
+ __ptr, len, sysctl_handle_counter_u64_array, "S", \
+ __DESCR(descr)); \
})
/* Oid for an opaque object. Specified by a pointer and a length. */
diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h
index e3151f6..6d2357a 100644
--- a/sys/sys/sysproto.h
+++ b/sys/sys/sysproto.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/kern/syscalls.master 296572 2016-03-09 19:05:11Z jhb
+ * created from FreeBSD: head/sys/kern/syscalls.master 297167 2016-03-21 21:37:33Z jhb
*/
#ifndef _SYS_SYSPROTO_H_
diff --git a/sys/sys/systm.h b/sys/sys/systm.h
index 026a03c..9c6e450 100644
--- a/sys/sys/systm.h
+++ b/sys/sys/systm.h
@@ -148,10 +148,14 @@ extern char **kenvp;
extern const void *zero_region; /* address space maps to a zeroed page */
extern int unmapped_buf_allowed;
-extern int iosize_max_clamp;
-extern int devfs_iosize_max_clamp;
-#define IOSIZE_MAX (iosize_max_clamp ? INT_MAX : SSIZE_MAX)
-#define DEVFS_IOSIZE_MAX (devfs_iosize_max_clamp ? INT_MAX : SSIZE_MAX)
+
+#ifdef __LP64__
+#define IOSIZE_MAX iosize_max()
+#define DEVFS_IOSIZE_MAX devfs_iosize_max()
+#else
+#define IOSIZE_MAX SSIZE_MAX
+#define DEVFS_IOSIZE_MAX SSIZE_MAX
+#endif
/*
* General function declarations.
@@ -403,6 +407,11 @@ struct cdev;
dev_t dev2udev(struct cdev *x);
const char *devtoname(struct cdev *cdev);
+#ifdef __LP64__
+size_t devfs_iosize_max(void);
+size_t iosize_max(void);
+#endif
+
int poll_no_poll(int events);
/* XXX: Should be void nanodelay(u_int nsec); */
diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c
index 19c00de..799efe3 100644
--- a/sys/ufs/ffs/ffs_alloc.c
+++ b/sys/ufs/ffs/ffs_alloc.c
@@ -2270,8 +2270,6 @@ ffs_blkfree_cg(ump, fs, devvp, bno, size, inum, dephd)
bdwrite(bp);
}
-TASKQUEUE_DEFINE_THREAD(ffs_trim);
-
struct ffs_blkfree_trim_params {
struct task task;
struct ufsmount *ump;
@@ -2294,6 +2292,7 @@ ffs_blkfree_trim_task(ctx, pending)
ffs_blkfree_cg(tp->ump, tp->ump->um_fs, tp->devvp, tp->bno, tp->size,
tp->inum, tp->pdephd);
vn_finished_secondary_write(UFSTOVFS(tp->ump));
+ atomic_add_int(&tp->ump->um_trim_inflight, -1);
free(tp, M_TEMP);
}
@@ -2306,7 +2305,7 @@ ffs_blkfree_trim_completed(bip)
tp = bip->bio_caller2;
g_destroy_bio(bip);
TASK_INIT(&tp->task, 0, ffs_blkfree_trim_task, tp);
- taskqueue_enqueue(taskqueue_ffs_trim, &tp->task);
+ taskqueue_enqueue(tp->ump->um_trim_tq, &tp->task);
}
void
@@ -2350,6 +2349,7 @@ ffs_blkfree(ump, fs, devvp, bno, size, inum, vtype, dephd)
* reordering, TRIM might be issued after we reuse the block
* and write some new data into it.
*/
+ atomic_add_int(&ump->um_trim_inflight, 1);
tp = malloc(sizeof(struct ffs_blkfree_trim_params), M_TEMP, M_WAITOK);
tp->ump = ump;
tp->devvp = devvp;
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index 04ea39c..bedc8e1 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -1937,9 +1937,9 @@ softdep_waitidle(struct mount *mp, int flags __unused)
vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
error = VOP_FSYNC(devvp, MNT_WAIT, td);
VOP_UNLOCK(devvp, 0);
+ ACQUIRE_LOCK(ump);
if (error != 0)
break;
- ACQUIRE_LOCK(ump);
}
ump->softdep_req = 0;
if (i == SU_WAITIDLE_RETRIES && error == 0 && ump->softdep_deps != 0) {
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index a82ef61..b89dc33 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <sys/namei.h>
#include <sys/priv.h>
#include <sys/proc.h>
+#include <sys/taskqueue.h>
#include <sys/kernel.h>
#include <sys/vnode.h>
#include <sys/mount.h>
@@ -1005,6 +1006,12 @@ ffs_mountfs(devvp, mp, td)
mp->mnt_stat.f_mntonname);
ump->um_candelete = 0;
}
+ if (ump->um_candelete) {
+ ump->um_trim_tq = taskqueue_create("trim", M_WAITOK,
+ taskqueue_thread_enqueue, &ump->um_trim_tq);
+ taskqueue_start_threads(&ump->um_trim_tq, 1, PVFS,
+ "%s trim", mp->mnt_stat.f_mntonname);
+ }
}
ump->um_mountp = mp;
@@ -1260,6 +1267,12 @@ ffs_unmount(mp, mntflags)
}
if (susp)
vfs_write_resume(mp, VR_START_WRITE);
+ if (ump->um_trim_tq != NULL) {
+ while (ump->um_trim_inflight != 0)
+ pause("ufsutr", hz);
+ taskqueue_drain_all(ump->um_trim_tq);
+ taskqueue_free(ump->um_trim_tq);
+ }
DROP_GIANT();
g_topology_lock();
if (ump->um_fsckpid > 0) {
diff --git a/sys/ufs/ufs/ufs_extattr.c b/sys/ufs/ufs/ufs_extattr.c
index 209d93e..b521a42 100644
--- a/sys/ufs/ufs/ufs_extattr.c
+++ b/sys/ufs/ufs/ufs_extattr.c
@@ -597,8 +597,6 @@ ufs_extattr_enable(struct ufsmount *ump, int attrnamespace,
attribute = malloc(sizeof(struct ufs_extattr_list_entry),
M_UFS_EXTATTR, M_WAITOK);
- if (attribute == NULL)
- return (ENOMEM);
if (!(ump->um_extattr.uepm_flags & UFS_EXTATTR_UEPM_STARTED)) {
error = EOPNOTSUPP;
diff --git a/sys/ufs/ufs/ufsmount.h b/sys/ufs/ufs/ufsmount.h
index 7148b76..838c1e3 100644
--- a/sys/ufs/ufs/ufsmount.h
+++ b/sys/ufs/ufs/ufsmount.h
@@ -50,6 +50,7 @@ MALLOC_DECLARE(M_UFSMNT);
struct buf;
struct inode;
struct nameidata;
+struct taskqueue;
struct timeval;
struct ucred;
struct uio;
@@ -85,11 +86,15 @@ struct ufsmount {
int64_t um_savedmaxfilesize; /* XXX - limit maxfilesize */
int um_candelete; /* devvp supports TRIM */
int um_writesuspended; /* suspension in progress */
- int (*um_balloc)(struct vnode *, off_t, int, struct ucred *, int, struct buf **);
+ u_int um_trim_inflight;
+ struct taskqueue *um_trim_tq;
+ int (*um_balloc)(struct vnode *, off_t, int, struct ucred *,
+ int, struct buf **);
int (*um_blkatoff)(struct vnode *, off_t, char **, struct buf **);
int (*um_truncate)(struct vnode *, off_t, int, struct ucred *);
int (*um_update)(struct vnode *, int);
- int (*um_valloc)(struct vnode *, int, struct ucred *, struct vnode **);
+ int (*um_valloc)(struct vnode *, int, struct ucred *,
+ struct vnode **);
int (*um_vfree)(struct vnode *, ino_t, int);
void (*um_ifree)(struct ufsmount *, struct inode *);
int (*um_rdonly)(struct inode *);
diff --git a/sys/x86/include/apicreg.h b/sys/x86/include/apicreg.h
index 35630c7..d3cfaaf 100644
--- a/sys/x86/include/apicreg.h
+++ b/sys/x86/include/apicreg.h
@@ -399,10 +399,11 @@ typedef struct IOAPIC ioapic_t;
#define APIC_LVTT_VECTOR 0x000000ff
#define APIC_LVTT_DS 0x00001000
#define APIC_LVTT_M 0x00010000
-#define APIC_LVTT_TM 0x00020000
+#define APIC_LVTT_TM 0x00060000
# define APIC_LVTT_TM_ONE_SHOT 0x00000000
# define APIC_LVTT_TM_PERIODIC 0x00020000
-
+# define APIC_LVTT_TM_TSCDLT 0x00040000
+# define APIC_LVTT_TM_RSRV 0x00060000
/* APIC timer current count */
#define APIC_TIMER_MAX_COUNT 0xffffffff
diff --git a/sys/x86/include/specialreg.h b/sys/x86/include/specialreg.h
index 5f2c010..c2d2c59 100644
--- a/sys/x86/include/specialreg.h
+++ b/sys/x86/include/specialreg.h
@@ -457,6 +457,7 @@
#define MSR_DRAM_ENERGY_STATUS 0x619
#define MSR_PP0_ENERGY_STATUS 0x639
#define MSR_PP1_ENERGY_STATUS 0x641
+#define MSR_TSC_DEADLINE 0x6e0 /* Writes are not serializing */
/*
* VMX MSRs
@@ -478,7 +479,8 @@
#define MSR_VMX_TRUE_ENTRY_CTLS 0x490
/*
- * X2APIC MSRs
+ * X2APIC MSRs.
+ * Writes are not serializing.
*/
#define MSR_APIC_000 0x800
#define MSR_APIC_ID 0x802
diff --git a/sys/x86/include/x86_var.h b/sys/x86/include/x86_var.h
index c349913..46ce1a0 100644
--- a/sys/x86/include/x86_var.h
+++ b/sys/x86/include/x86_var.h
@@ -86,6 +86,13 @@ struct fpreg;
struct dbreg;
struct dumperinfo;
+/*
+ * The interface type of the interrupt handler entry point cannot be
+ * expressed in C. Use simplest non-variadic function type as an
+ * approximation.
+ */
+typedef void alias_for_inthand_t(void);
+
void *alloc_fpusave(int flags);
void busdma_swi(void);
bool cpu_mwait_usable(void);
diff --git a/sys/i386/i386/autoconf.c b/sys/x86/x86/autoconf.c
index 029ed2e..813fe4c 100644
--- a/sys/i386/i386/autoconf.c
+++ b/sys/x86/x86/autoconf.c
@@ -65,7 +65,9 @@ __FBSDID("$FreeBSD$");
#include <net/ethernet.h>
#include <netinet/in.h>
+#ifdef PC98
#include <machine/bootinfo.h>
+#endif
#include <machine/md_var.h>
#ifdef DEV_ISA
@@ -92,7 +94,7 @@ configure_first(dummy)
void *dummy;
{
- /* nexus0 is the top of the i386 device tree */
+ /* nexus0 is the top of the x86 device tree */
device_add_child(root_bus, "nexus", 0);
}
@@ -101,13 +103,6 @@ configure(dummy)
void *dummy;
{
- /*
- * Enable interrupts on the processor. The interrupts are still
- * disabled in the interrupt controllers until interrupt handlers
- * are registered.
- */
- enable_intr();
-
/* initialize new bus architecture */
root_bus_configure();
diff --git a/sys/x86/x86/intr_machdep.c b/sys/x86/x86/intr_machdep.c
index 35ec992..6678887 100644
--- a/sys/x86/x86/intr_machdep.c
+++ b/sys/x86/x86/intr_machdep.c
@@ -393,6 +393,21 @@ intr_init(void *dummy __unused)
}
SYSINIT(intr_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_init, NULL);
+static void
+intr_init_final(void *dummy __unused)
+{
+
+ /*
+ * Enable interrupts on the BSP after all of the interrupt
+ * controllers are initialized. Device interrupts are still
+ * disabled in the interrupt controllers until interrupt
+ * handlers are registered. Interrupts are enabled on each AP
+ * after their first context switch.
+ */
+ enable_intr();
+}
+SYSINIT(intr_init_final, SI_SUB_INTR, SI_ORDER_ANY, intr_init_final, NULL);
+
#ifndef DEV_ATPIC
/* Initialize the two 8259A's to a known-good shutdown state. */
void
diff --git a/sys/x86/x86/io_apic.c b/sys/x86/x86/io_apic.c
index 44609e6..1a2cc3c 100644
--- a/sys/x86/x86/io_apic.c
+++ b/sys/x86/x86/io_apic.c
@@ -987,14 +987,6 @@ apic_add_resource(device_t dev, int rid, vm_paddr_t base, size_t length)
{
int error;
-#ifdef PAE
- /*
- * Resources use long's to track resources, so we can't
- * include memory regions above 4GB.
- */
- if (base >= ~0ul)
- return;
-#endif
error = bus_set_resource(dev, SYS_RES_MEMORY, rid, base, length);
if (error)
panic("apic_add_resource: resource %d failed set with %d", rid,
diff --git a/sys/x86/x86/local_apic.c b/sys/x86/x86/local_apic.c
index 7fc6278..82efae3 100644
--- a/sys/x86/x86/local_apic.c
+++ b/sys/x86/x86/local_apic.c
@@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$");
#include <vm/pmap.h>
#include <x86/apicreg.h>
+#include <machine/clock.h>
#include <machine/cpufunc.h>
#include <machine/cputypes.h>
#include <machine/frame.h>
@@ -94,6 +95,13 @@ CTASSERT(IPI_STOP < APIC_SPURIOUS_INT);
#define IRQ_DTRACE_RET (NUM_IO_INTS + 3)
#define IRQ_EVTCHN (NUM_IO_INTS + 4)
+enum lat_timer_mode {
+ LAT_MODE_UNDEF = 0,
+ LAT_MODE_PERIODIC = 1,
+ LAT_MODE_ONESHOT = 2,
+ LAT_MODE_DEADLINE = 3,
+};
+
/*
* Support for local APICs. Local APICs manage interrupts on each
* individual processor as opposed to I/O APICs which receive interrupts
@@ -119,9 +127,10 @@ struct lapic {
u_int la_cluster_id:2;
u_int la_present:1;
u_long *la_timer_count;
- u_long la_timer_period;
- u_int la_timer_mode;
- uint32_t lvt_timer_cache;
+ uint64_t la_timer_period;
+ enum lat_timer_mode la_timer_mode;
+ uint32_t lvt_timer_base;
+ uint32_t lvt_timer_last;
/* Include IDT_SYSCALL to make indexing easier. */
int la_ioint_irqs[APIC_NUM_IOINTS + 1];
} static lapics[MAX_APIC_ID + 1];
@@ -160,13 +169,19 @@ volatile char *lapic_map;
vm_paddr_t lapic_paddr;
int x2apic_mode;
int lapic_eoi_suppression;
+static int lapic_timer_tsc_deadline;
static u_long lapic_timer_divisor;
static struct eventtimer lapic_et;
+#ifdef SMP
+static uint64_t lapic_ipi_wait_mult;
+#endif
SYSCTL_NODE(_hw, OID_AUTO, apic, CTLFLAG_RD, 0, "APIC options");
SYSCTL_INT(_hw_apic, OID_AUTO, x2apic_mode, CTLFLAG_RD, &x2apic_mode, 0, "");
SYSCTL_INT(_hw_apic, OID_AUTO, eoi_suppression, CTLFLAG_RD,
&lapic_eoi_suppression, 0, "");
+SYSCTL_INT(_hw_apic, OID_AUTO, timer_tsc_deadline, CTLFLAG_RD,
+ &lapic_timer_tsc_deadline, 0, "");
static uint32_t
lapic_read32(enum LAPIC_REGISTERS reg)
@@ -256,10 +271,10 @@ native_lapic_enable_x2apic(void)
static void lapic_enable(void);
static void lapic_resume(struct pic *pic, bool suspend_cancelled);
-static void lapic_timer_oneshot(struct lapic *,
- u_int count, int enable_int);
-static void lapic_timer_periodic(struct lapic *,
- u_int count, int enable_int);
+static void lapic_timer_oneshot(struct lapic *);
+static void lapic_timer_oneshot_nointr(struct lapic *, uint32_t);
+static void lapic_timer_periodic(struct lapic *);
+static void lapic_timer_deadline(struct lapic *);
static void lapic_timer_stop(struct lapic *);
static void lapic_timer_set_divisor(u_int divisor);
static uint32_t lvt_mode(struct lapic *la, u_int pin, uint32_t value);
@@ -391,6 +406,9 @@ lvt_mode(struct lapic *la, u_int pin, uint32_t value)
static void
native_lapic_init(vm_paddr_t addr)
{
+#ifdef SMP
+ uint64_t r, r1, r2, rx;
+#endif
uint32_t ver;
u_int regs[4];
int i, arat;
@@ -450,7 +468,14 @@ native_lapic_init(vm_paddr_t addr)
if (!arat) {
lapic_et.et_flags |= ET_FLAGS_C3STOP;
lapic_et.et_quality -= 200;
+ } else if ((cpu_feature & CPUID_TSC) != 0 &&
+ (cpu_feature2 & CPUID2_TSCDLT) != 0 &&
+ tsc_is_invariant && tsc_freq != 0) {
+ lapic_timer_tsc_deadline = 1;
+ TUNABLE_INT_FETCH("hw.lapic_tsc_deadline",
+ &lapic_timer_tsc_deadline);
}
+
lapic_et.et_frequency = 0;
/* We don't know frequency yet, so trying to guess. */
lapic_et.et_min_period = 0x00001000LL;
@@ -484,6 +509,38 @@ native_lapic_init(vm_paddr_t addr)
TUNABLE_INT_FETCH("hw.lapic_eoi_suppression",
&lapic_eoi_suppression);
}
+
+#ifdef SMP
+#define LOOPS 1000000
+ /*
+ * Calibrate the busy loop waiting for IPI ack in xAPIC mode.
+ * lapic_ipi_wait_mult contains the number of iterations which
+ * approximately delay execution for 1 microsecond (the
+ * argument to native_lapic_ipi_wait() is in microseconds).
+ *
+ * We assume that TSC is present and already measured.
+ * Possible TSC frequency jumps are irrelevant to the
+ * calibration loop below, the CPU clock management code is
+ * not yet started, and we do not enter sleep states.
+ */
+ KASSERT((cpu_feature & CPUID_TSC) != 0 && tsc_freq != 0,
+ ("TSC not initialized"));
+ r = rdtsc();
+ for (rx = 0; rx < LOOPS; rx++) {
+ (void)lapic_read_icr_lo();
+ ia32_pause();
+ }
+ r = rdtsc() - r;
+ r1 = tsc_freq * LOOPS;
+ r2 = r * 1000000;
+ lapic_ipi_wait_mult = r1 >= r2 ? r1 / r2 : 1;
+ if (bootverbose) {
+ printf("LAPIC: ipi_wait() us multiplier %ju (r %ju tsc %ju)\n",
+ (uintmax_t)lapic_ipi_wait_mult, (uintmax_t)r,
+ (uintmax_t)tsc_freq);
+ }
+#undef LOOPS
+#endif /* SMP */
}
/*
@@ -604,23 +661,35 @@ native_lapic_setup(int boot)
}
/* Program timer LVT and setup handler. */
- la->lvt_timer_cache = lvt_mode(la, APIC_LVT_TIMER,
+ la->lvt_timer_base = lvt_mode(la, APIC_LVT_TIMER,
lapic_read32(LAPIC_LVT_TIMER));
- lapic_write32(LAPIC_LVT_TIMER, la->lvt_timer_cache);
+ la->lvt_timer_last = la->lvt_timer_base;
+ lapic_write32(LAPIC_LVT_TIMER, la->lvt_timer_base);
if (boot) {
snprintf(buf, sizeof(buf), "cpu%d:timer", PCPU_GET(cpuid));
intrcnt_add(buf, &la->la_timer_count);
}
/* Setup the timer if configured. */
- if (la->la_timer_mode != 0) {
+ if (la->la_timer_mode != LAT_MODE_UNDEF) {
KASSERT(la->la_timer_period != 0, ("lapic%u: zero divisor",
lapic_id()));
- lapic_timer_set_divisor(lapic_timer_divisor);
- if (la->la_timer_mode == 1)
- lapic_timer_periodic(la, la->la_timer_period, 1);
- else
- lapic_timer_oneshot(la, la->la_timer_period, 1);
+ switch (la->la_timer_mode) {
+ case LAT_MODE_PERIODIC:
+ lapic_timer_set_divisor(lapic_timer_divisor);
+ lapic_timer_periodic(la);
+ break;
+ case LAT_MODE_ONESHOT:
+ lapic_timer_set_divisor(lapic_timer_divisor);
+ lapic_timer_oneshot(la);
+ break;
+ case LAT_MODE_DEADLINE:
+ lapic_timer_deadline(la);
+ break;
+ default:
+ panic("corrupted la_timer_mode %p %d", la,
+ la->la_timer_mode);
+ }
}
/* Program error LVT and clear any existing errors. */
@@ -722,46 +791,75 @@ native_lapic_disable_pmc(void)
#endif
}
+static void
+lapic_calibrate_initcount(struct eventtimer *et, struct lapic *la)
+{
+ u_long value;
+
+ /* Start off with a divisor of 2 (power on reset default). */
+ lapic_timer_divisor = 2;
+ /* Try to calibrate the local APIC timer. */
+ do {
+ lapic_timer_set_divisor(lapic_timer_divisor);
+ lapic_timer_oneshot_nointr(la, APIC_TIMER_MAX_COUNT);
+ DELAY(1000000);
+ value = APIC_TIMER_MAX_COUNT - lapic_read32(LAPIC_CCR_TIMER);
+ if (value != APIC_TIMER_MAX_COUNT)
+ break;
+ lapic_timer_divisor <<= 1;
+ } while (lapic_timer_divisor <= 128);
+ if (lapic_timer_divisor > 128)
+ panic("lapic: Divisor too big");
+ if (bootverbose) {
+ printf("lapic: Divisor %lu, Frequency %lu Hz\n",
+ lapic_timer_divisor, value);
+ }
+ et->et_frequency = value;
+}
+
+static void
+lapic_calibrate_deadline(struct eventtimer *et, struct lapic *la __unused)
+{
+
+ et->et_frequency = tsc_freq;
+ if (bootverbose) {
+ printf("lapic: deadline tsc mode, Frequency %ju Hz\n",
+ (uintmax_t)et->et_frequency);
+ }
+}
+
static int
lapic_et_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
{
struct lapic *la;
- u_long value;
la = &lapics[PCPU_GET(apic_id)];
if (et->et_frequency == 0) {
- /* Start off with a divisor of 2 (power on reset default). */
- lapic_timer_divisor = 2;
- /* Try to calibrate the local APIC timer. */
- do {
- lapic_timer_set_divisor(lapic_timer_divisor);
- lapic_timer_oneshot(la, APIC_TIMER_MAX_COUNT, 0);
- DELAY(1000000);
- value = APIC_TIMER_MAX_COUNT -
- lapic_read32(LAPIC_CCR_TIMER);
- if (value != APIC_TIMER_MAX_COUNT)
- break;
- lapic_timer_divisor <<= 1;
- } while (lapic_timer_divisor <= 128);
- if (lapic_timer_divisor > 128)
- panic("lapic: Divisor too big");
- if (bootverbose)
- printf("lapic: Divisor %lu, Frequency %lu Hz\n",
- lapic_timer_divisor, value);
- et->et_frequency = value;
+ if (lapic_timer_tsc_deadline)
+ lapic_calibrate_deadline(et, la);
+ else
+ lapic_calibrate_initcount(et, la);
et->et_min_period = (0x00000002LLU << 32) / et->et_frequency;
et->et_max_period = (0xfffffffeLLU << 32) / et->et_frequency;
}
- if (la->la_timer_mode == 0)
- lapic_timer_set_divisor(lapic_timer_divisor);
if (period != 0) {
- la->la_timer_mode = 1;
- la->la_timer_period = ((uint32_t)et->et_frequency * period) >> 32;
- lapic_timer_periodic(la, la->la_timer_period, 1);
+ if (la->la_timer_mode == LAT_MODE_UNDEF)
+ lapic_timer_set_divisor(lapic_timer_divisor);
+ la->la_timer_mode = LAT_MODE_PERIODIC;
+ la->la_timer_period = ((uint32_t)et->et_frequency * period) >>
+ 32;
+ lapic_timer_periodic(la);
+ } else if (lapic_timer_tsc_deadline) {
+ la->la_timer_mode = LAT_MODE_DEADLINE;
+ la->la_timer_period = (et->et_frequency * first) >> 32;
+ lapic_timer_deadline(la);
} else {
- la->la_timer_mode = 2;
- la->la_timer_period = ((uint32_t)et->et_frequency * first) >> 32;
- lapic_timer_oneshot(la, la->la_timer_period, 1);
+ if (la->la_timer_mode == LAT_MODE_UNDEF)
+ lapic_timer_set_divisor(lapic_timer_divisor);
+ la->la_timer_mode = LAT_MODE_ONESHOT;
+ la->la_timer_period = ((uint32_t)et->et_frequency * first) >>
+ 32;
+ lapic_timer_oneshot(la);
}
return (0);
}
@@ -769,10 +867,11 @@ lapic_et_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
static int
lapic_et_stop(struct eventtimer *et)
{
- struct lapic *la = &lapics[PCPU_GET(apic_id)];
+ struct lapic *la;
- la->la_timer_mode = 0;
+ la = &lapics[PCPU_GET(apic_id)];
lapic_timer_stop(la);
+ la->la_timer_mode = LAT_MODE_UNDEF;
return (0);
}
@@ -1071,42 +1170,76 @@ lapic_timer_set_divisor(u_int divisor)
}
static void
-lapic_timer_oneshot(struct lapic *la, u_int count, int enable_int)
+lapic_timer_oneshot(struct lapic *la)
{
uint32_t value;
- value = la->lvt_timer_cache;
- value &= ~APIC_LVTT_TM;
+ value = la->lvt_timer_base;
+ value &= ~(APIC_LVTT_TM | APIC_LVT_M);
value |= APIC_LVTT_TM_ONE_SHOT;
- if (enable_int)
- value &= ~APIC_LVT_M;
+ la->lvt_timer_last = value;
lapic_write32(LAPIC_LVT_TIMER, value);
- lapic_write32(LAPIC_ICR_TIMER, count);
+ lapic_write32(LAPIC_ICR_TIMER, la->la_timer_period);
}
static void
-lapic_timer_periodic(struct lapic *la, u_int count, int enable_int)
+lapic_timer_oneshot_nointr(struct lapic *la, uint32_t count)
{
uint32_t value;
- value = la->lvt_timer_cache;
+ value = la->lvt_timer_base;
value &= ~APIC_LVTT_TM;
- value |= APIC_LVTT_TM_PERIODIC;
- if (enable_int)
- value &= ~APIC_LVT_M;
+ value |= APIC_LVTT_TM_ONE_SHOT | APIC_LVT_M;
+ la->lvt_timer_last = value;
lapic_write32(LAPIC_LVT_TIMER, value);
lapic_write32(LAPIC_ICR_TIMER, count);
}
static void
-lapic_timer_stop(struct lapic *la)
+lapic_timer_periodic(struct lapic *la)
{
uint32_t value;
- value = la->lvt_timer_cache;
- value &= ~APIC_LVTT_TM;
- value |= APIC_LVT_M;
+ value = la->lvt_timer_base;
+ value &= ~(APIC_LVTT_TM | APIC_LVT_M);
+ value |= APIC_LVTT_TM_PERIODIC;
+ la->lvt_timer_last = value;
lapic_write32(LAPIC_LVT_TIMER, value);
+ lapic_write32(LAPIC_ICR_TIMER, la->la_timer_period);
+}
+
+static void
+lapic_timer_deadline(struct lapic *la)
+{
+ uint32_t value;
+
+ value = la->lvt_timer_base;
+ value &= ~(APIC_LVTT_TM | APIC_LVT_M);
+ value |= APIC_LVTT_TM_TSCDLT;
+ if (value != la->lvt_timer_last) {
+ la->lvt_timer_last = value;
+ lapic_write32_nofence(LAPIC_LVT_TIMER, value);
+ if (!x2apic_mode)
+ mfence();
+ }
+ wrmsr(MSR_TSC_DEADLINE, la->la_timer_period + rdtsc());
+}
+
+static void
+lapic_timer_stop(struct lapic *la)
+{
+ uint32_t value;
+
+ if (la->la_timer_mode == LAT_MODE_DEADLINE) {
+ wrmsr(MSR_TSC_DEADLINE, 0);
+ mfence();
+ } else {
+ value = la->lvt_timer_base;
+ value &= ~APIC_LVTT_TM;
+ value |= APIC_LVT_M;
+ la->lvt_timer_last = value;
+ lapic_write32(LAPIC_LVT_TIMER, value);
+ }
}
void
@@ -1621,31 +1754,25 @@ SYSINIT(apic_setup_io, SI_SUB_INTR, SI_ORDER_THIRD, apic_setup_io, NULL);
* private to the MD code. The public interface for the rest of the
* kernel is defined in mp_machdep.c.
*/
+
+/*
+ * Wait delay microseconds for IPI to be sent. If delay is -1, we
+ * wait forever.
+ */
static int
native_lapic_ipi_wait(int delay)
{
- int x;
+ uint64_t rx;
/* LAPIC_ICR.APIC_DELSTAT_MASK is undefined in x2APIC mode */
if (x2apic_mode)
return (1);
- /*
- * Wait delay microseconds for IPI to be sent. If delay is
- * -1, we wait forever.
- */
- if (delay == -1) {
- while ((lapic_read_icr_lo() & APIC_DELSTAT_MASK) !=
- APIC_DELSTAT_IDLE)
- ia32_pause();
- return (1);
- }
-
- for (x = 0; x < delay; x += 5) {
+ for (rx = 0; delay == -1 || rx < lapic_ipi_wait_mult * delay; rx++) {
if ((lapic_read_icr_lo() & APIC_DELSTAT_MASK) ==
APIC_DELSTAT_IDLE)
return (1);
- DELAY(5);
+ ia32_pause();
}
return (0);
}
diff --git a/sys/x86/x86/mp_x86.c b/sys/x86/x86/mp_x86.c
index 9594ff3..90051c8 100644
--- a/sys/x86/x86/mp_x86.c
+++ b/sys/x86/x86/mp_x86.c
@@ -133,19 +133,28 @@ volatile int aps_ready = 0;
* the APs.
*/
struct cpu_info cpu_info[MAX_APIC_ID + 1];
-int cpu_apic_ids[MAXCPU];
int apic_cpuids[MAX_APIC_ID + 1];
+int cpu_apic_ids[MAXCPU];
/* Holds pending bitmap based IPIs per CPU */
volatile u_int cpu_ipi_pending[MAXCPU];
-int cpu_logical; /* logical cpus per core */
-int cpu_cores; /* cores per package */
-
static void release_aps(void *dummy);
-static u_int hyperthreading_cpus; /* logical cpus sharing L1 cache */
static int hyperthreading_allowed = 1;
+SYSCTL_INT(_machdep, OID_AUTO, hyperthreading_allowed, CTLFLAG_RDTUN,
+ &hyperthreading_allowed, 0, "Use Intel HTT logical CPUs");
+
+static struct topo_node topo_root;
+
+static int pkg_id_shift;
+static int core_id_shift;
+static int disabled_cpus;
+
+struct cache_info {
+ int id_shift;
+ int present;
+} static caches[MAX_CACHE_LEVELS];
void
mem_range_AP_init(void)
@@ -155,60 +164,125 @@ mem_range_AP_init(void)
mem_range_softc.mr_op->initAP(&mem_range_softc);
}
-static void
-topo_probe_amd(void)
+/*
+ * Round up to the next power of two, if necessary, and then
+ * take log2.
+ * Returns -1 if argument is zero.
+ */
+static __inline int
+mask_width(u_int x)
{
- int core_id_bits;
- int id;
- /* AMD processors do not support HTT. */
- cpu_logical = 1;
+ return (fls(x << (1 - powerof2(x))) - 1);
+}
- if ((amd_feature2 & AMDID2_CMP) == 0) {
- cpu_cores = 1;
- return;
- }
+static int
+add_deterministic_cache(int type, int level, int share_count)
+{
- core_id_bits = (cpu_procinfo2 & AMDID_COREID_SIZE) >>
- AMDID_COREID_SIZE_SHIFT;
- if (core_id_bits == 0) {
- cpu_cores = (cpu_procinfo2 & AMDID_CMP_CORES) + 1;
- return;
+ if (type == 0)
+ return (0);
+ if (type > 3) {
+ printf("unexpected cache type %d\n", type);
+ return (1);
+ }
+ if (type == 2) /* ignore instruction cache */
+ return (1);
+ if (level == 0 || level > MAX_CACHE_LEVELS) {
+ printf("unexpected cache level %d\n", type);
+ return (1);
}
- /* Fam 10h and newer should get here. */
- for (id = 0; id <= MAX_APIC_ID; id++) {
- /* Check logical CPU availability. */
- if (!cpu_info[id].cpu_present || cpu_info[id].cpu_disabled)
- continue;
- /* Check if logical CPU has the same package ID. */
- if ((id >> core_id_bits) != (boot_cpu_id >> core_id_bits))
- continue;
- cpu_cores++;
+ if (caches[level - 1].present) {
+ printf("WARNING: multiple entries for L%u data cache\n", level);
+ printf("%u => %u\n", caches[level - 1].id_shift,
+ mask_width(share_count));
+ }
+ caches[level - 1].id_shift = mask_width(share_count);
+ caches[level - 1].present = 1;
+
+ if (caches[level - 1].id_shift > pkg_id_shift) {
+ printf("WARNING: L%u data cache covers more "
+ "APIC IDs than a package\n", level);
+ printf("%u > %u\n", caches[level - 1].id_shift, pkg_id_shift);
+ caches[level - 1].id_shift = pkg_id_shift;
}
+ if (caches[level - 1].id_shift < core_id_shift) {
+ printf("WARNING: L%u data cache covers less "
+ "APIC IDs than a core\n", level);
+ printf("%u < %u\n", caches[level - 1].id_shift, core_id_shift);
+ caches[level - 1].id_shift = core_id_shift;
+ }
+
+ return (1);
}
-/*
- * Round up to the next power of two, if necessary, and then
- * take log2.
- * Returns -1 if argument is zero.
- */
-static __inline int
-mask_width(u_int x)
+static void
+topo_probe_amd(void)
{
+ u_int p[4];
+ int level;
+ int share_count;
+ int type;
+ int i;
- return (fls(x << (1 - powerof2(x))) - 1);
+ /* No multi-core capability. */
+ if ((amd_feature2 & AMDID2_CMP) == 0)
+ return;
+
+ /* For families 10h and newer. */
+ pkg_id_shift = (cpu_procinfo2 & AMDID_COREID_SIZE) >>
+ AMDID_COREID_SIZE_SHIFT;
+
+ /* For 0Fh family. */
+ if (pkg_id_shift == 0)
+ pkg_id_shift =
+ mask_width((cpu_procinfo2 & AMDID_CMP_CORES) + 1);
+
+ if ((amd_feature2 & AMDID2_TOPOLOGY) != 0) {
+ for (i = 0; ; i++) {
+ cpuid_count(0x8000001d, i, p);
+ type = p[0] & 0x1f;
+ level = (p[0] >> 5) & 0x7;
+ share_count = 1 + ((p[0] >> 14) & 0xfff);
+
+ if (!add_deterministic_cache(type, level, share_count))
+ break;
+ }
+ } else {
+ if (cpu_exthigh >= 0x80000005) {
+ cpuid_count(0x80000005, 0, p);
+ if (((p[2] >> 24) & 0xff) != 0) {
+ caches[0].id_shift = 0;
+ caches[0].present = 1;
+ }
+ }
+ if (cpu_exthigh >= 0x80000006) {
+ cpuid_count(0x80000006, 0, p);
+ if (((p[2] >> 16) & 0xffff) != 0) {
+ caches[1].id_shift = 0;
+ caches[1].present = 1;
+ }
+ if (((p[3] >> 18) & 0x3fff) != 0) {
+
+ /*
+ * TODO: Account for dual-node processors
+ * where each node within a package has its own
+ * L3 cache.
+ */
+ caches[2].id_shift = pkg_id_shift;
+ caches[2].present = 1;
+ }
+ }
+ }
}
static void
-topo_probe_0x4(void)
+topo_probe_intel_0x4(void)
{
u_int p[4];
- int pkg_id_bits;
- int core_id_bits;
int max_cores;
int max_logical;
- int id;
/* Both zero and one here mean one logical processor per package. */
max_logical = (cpu_feature & CPUID_HTT) != 0 ?
@@ -216,180 +290,432 @@ topo_probe_0x4(void)
if (max_logical <= 1)
return;
- /*
- * Because of uniformity assumption we examine only
- * those logical processors that belong to the same
- * package as BSP. Further, we count number of
- * logical processors that belong to the same core
- * as BSP thus deducing number of threads per core.
- */
if (cpu_high >= 0x4) {
cpuid_count(0x04, 0, p);
max_cores = ((p[0] >> 26) & 0x3f) + 1;
} else
max_cores = 1;
- core_id_bits = mask_width(max_logical/max_cores);
- if (core_id_bits < 0)
- return;
- pkg_id_bits = core_id_bits + mask_width(max_cores);
-
- for (id = 0; id <= MAX_APIC_ID; id++) {
- /* Check logical CPU availability. */
- if (!cpu_info[id].cpu_present || cpu_info[id].cpu_disabled)
- continue;
- /* Check if logical CPU has the same package ID. */
- if ((id >> pkg_id_bits) != (boot_cpu_id >> pkg_id_bits))
- continue;
- cpu_cores++;
- /* Check if logical CPU has the same package and core IDs. */
- if ((id >> core_id_bits) == (boot_cpu_id >> core_id_bits))
- cpu_logical++;
- }
-
- KASSERT(cpu_cores >= 1 && cpu_logical >= 1,
- ("topo_probe_0x4 couldn't find BSP"));
- cpu_cores /= cpu_logical;
- hyperthreading_cpus = cpu_logical;
+ core_id_shift = mask_width(max_logical/max_cores);
+ KASSERT(core_id_shift >= 0,
+ ("intel topo: max_cores > max_logical\n"));
+ pkg_id_shift = core_id_shift + mask_width(max_cores);
}
static void
-topo_probe_0xb(void)
+topo_probe_intel_0xb(void)
{
u_int p[4];
int bits;
- int cnt;
- int i;
- int logical;
int type;
- int x;
+ int i;
+
+ /* Fall back if CPU leaf 11 doesn't really exist. */
+ cpuid_count(0x0b, 0, p);
+ if (p[1] == 0) {
+ topo_probe_intel_0x4();
+ return;
+ }
/* We only support three levels for now. */
- for (i = 0; i < 3; i++) {
+ for (i = 0; ; i++) {
cpuid_count(0x0b, i, p);
- /* Fall back if CPU leaf 11 doesn't really exist. */
- if (i == 0 && p[1] == 0) {
- topo_probe_0x4();
- return;
- }
-
bits = p[0] & 0x1f;
- logical = p[1] &= 0xffff;
type = (p[2] >> 8) & 0xff;
- if (type == 0 || logical == 0)
+
+ if (type == 0)
break;
- /*
- * Because of uniformity assumption we examine only
- * those logical processors that belong to the same
- * package as BSP.
- */
- for (cnt = 0, x = 0; x <= MAX_APIC_ID; x++) {
- if (!cpu_info[x].cpu_present ||
- cpu_info[x].cpu_disabled)
- continue;
- if (x >> bits == boot_cpu_id >> bits)
- cnt++;
- }
+
+ /* TODO: check for duplicate (re-)assignment */
if (type == CPUID_TYPE_SMT)
- cpu_logical = cnt;
+ core_id_shift = bits;
else if (type == CPUID_TYPE_CORE)
- cpu_cores = cnt;
+ pkg_id_shift = bits;
+ else
+ printf("unknown CPU level type %d\n", type);
+ }
+
+ if (pkg_id_shift < core_id_shift) {
+ printf("WARNING: core covers more APIC IDs than a package\n");
+ core_id_shift = pkg_id_shift;
}
- if (cpu_logical == 0)
- cpu_logical = 1;
- cpu_cores /= cpu_logical;
+}
+
+static void
+topo_probe_intel_caches(void)
+{
+ u_int p[4];
+ int level;
+ int share_count;
+ int type;
+ int i;
+
+ if (cpu_high < 0x4) {
+ /*
+ * Available cache level and sizes can be determined
+ * via CPUID leaf 2, but that requires a huge table of hardcoded
+ * values, so for now just assume L1 and L2 caches potentially
+ * shared only by HTT processing units, if HTT is present.
+ */
+ caches[0].id_shift = pkg_id_shift;
+ caches[0].present = 1;
+ caches[1].id_shift = pkg_id_shift;
+ caches[1].present = 1;
+ return;
+ }
+
+ for (i = 0; ; i++) {
+ cpuid_count(0x4, i, p);
+ type = p[0] & 0x1f;
+ level = (p[0] >> 5) & 0x7;
+ share_count = 1 + ((p[0] >> 14) & 0xfff);
+
+ if (!add_deterministic_cache(type, level, share_count))
+ break;
+ }
+}
+
+static void
+topo_probe_intel(void)
+{
+
+ /*
+ * See Intel(R) 64 Architecture Processor
+ * Topology Enumeration article for details.
+ *
+ * Note that 0x1 <= cpu_high < 4 case should be
+ * compatible with topo_probe_intel_0x4() logic when
+ * CPUID.1:EBX[23:16] > 0 (cpu_cores will be 1)
+ * or it should trigger the fallback otherwise.
+ */
+ if (cpu_high >= 0xb)
+ topo_probe_intel_0xb();
+ else if (cpu_high >= 0x1)
+ topo_probe_intel_0x4();
+
+ topo_probe_intel_caches();
}
/*
- * Both topology discovery code and code that consumes topology
- * information assume top-down uniformity of the topology.
- * That is, all physical packages must be identical and each
- * core in a package must have the same number of threads.
* Topology information is queried only on BSP, on which this
* code runs and for which it can query CPUID information.
- * Then topology is extrapolated on all packages using the
- * uniformity assumption.
+ * Then topology is extrapolated on all packages using an
+ * assumption that APIC ID to hardware component ID mapping is
+ * homogenious.
+ * That doesn't necesserily imply that the topology is uniform.
*/
void
topo_probe(void)
{
static int cpu_topo_probed = 0;
+ struct x86_topo_layer {
+ int type;
+ int subtype;
+ int id_shift;
+ } topo_layers[MAX_CACHE_LEVELS + 3];
+ struct topo_node *parent;
+ struct topo_node *node;
+ int layer;
+ int nlayers;
+ int node_id;
+ int i;
if (cpu_topo_probed)
return;
CPU_ZERO(&logical_cpus_mask);
+
if (mp_ncpus <= 1)
- cpu_cores = cpu_logical = 1;
+ ; /* nothing */
else if (cpu_vendor_id == CPU_VENDOR_AMD)
topo_probe_amd();
- else if (cpu_vendor_id == CPU_VENDOR_INTEL) {
- /*
- * See Intel(R) 64 Architecture Processor
- * Topology Enumeration article for details.
- *
- * Note that 0x1 <= cpu_high < 4 case should be
- * compatible with topo_probe_0x4() logic when
- * CPUID.1:EBX[23:16] > 0 (cpu_cores will be 1)
- * or it should trigger the fallback otherwise.
- */
- if (cpu_high >= 0xb)
- topo_probe_0xb();
- else if (cpu_high >= 0x1)
- topo_probe_0x4();
- }
+ else if (cpu_vendor_id == CPU_VENDOR_INTEL)
+ topo_probe_intel();
+
+ KASSERT(pkg_id_shift >= core_id_shift,
+ ("bug in APIC topology discovery"));
+
+ nlayers = 0;
+ bzero(topo_layers, sizeof(topo_layers));
+
+ topo_layers[nlayers].type = TOPO_TYPE_PKG;
+ topo_layers[nlayers].id_shift = pkg_id_shift;
+ if (bootverbose)
+ printf("Package ID shift: %u\n", topo_layers[nlayers].id_shift);
+ nlayers++;
/*
- * Fallback: assume each logical CPU is in separate
- * physical package. That is, no multi-core, no SMT.
+ * Consider all caches to be within a package/chip
+ * and "in front" of all sub-components like
+ * cores and hardware threads.
*/
- if (cpu_cores == 0 || cpu_logical == 0)
- cpu_cores = cpu_logical = 1;
+ for (i = MAX_CACHE_LEVELS - 1; i >= 0; --i) {
+ if (caches[i].present) {
+ KASSERT(caches[i].id_shift <= pkg_id_shift,
+ ("bug in APIC topology discovery"));
+ KASSERT(caches[i].id_shift >= core_id_shift,
+ ("bug in APIC topology discovery"));
+
+ topo_layers[nlayers].type = TOPO_TYPE_CACHE;
+ topo_layers[nlayers].subtype = i + 1;
+ topo_layers[nlayers].id_shift = caches[i].id_shift;
+ if (bootverbose)
+ printf("L%u cache ID shift: %u\n",
+ topo_layers[nlayers].subtype,
+ topo_layers[nlayers].id_shift);
+ nlayers++;
+ }
+ }
+
+ if (pkg_id_shift > core_id_shift) {
+ topo_layers[nlayers].type = TOPO_TYPE_CORE;
+ topo_layers[nlayers].id_shift = core_id_shift;
+ if (bootverbose)
+ printf("Core ID shift: %u\n",
+ topo_layers[nlayers].id_shift);
+ nlayers++;
+ }
+
+ topo_layers[nlayers].type = TOPO_TYPE_PU;
+ topo_layers[nlayers].id_shift = 0;
+ nlayers++;
+
+ topo_init_root(&topo_root);
+ for (i = 0; i <= MAX_APIC_ID; ++i) {
+ if (!cpu_info[i].cpu_present)
+ continue;
+
+ parent = &topo_root;
+ for (layer = 0; layer < nlayers; ++layer) {
+ node_id = i >> topo_layers[layer].id_shift;
+ parent = topo_add_node_by_hwid(parent, node_id,
+ topo_layers[layer].type,
+ topo_layers[layer].subtype);
+ }
+ }
+
+ parent = &topo_root;
+ for (layer = 0; layer < nlayers; ++layer) {
+ node_id = boot_cpu_id >> topo_layers[layer].id_shift;
+ node = topo_find_node_by_hwid(parent, node_id,
+ topo_layers[layer].type,
+ topo_layers[layer].subtype);
+ topo_promote_child(node);
+ parent = node;
+ }
+
cpu_topo_probed = 1;
}
-struct cpu_group *
-cpu_topo(void)
+/*
+ * Assign logical CPU IDs to local APICs.
+ */
+void
+assign_cpu_ids(void)
{
- int cg_flags;
+ struct topo_node *node;
+ u_int smt_mask;
+
+ smt_mask = (1u << core_id_shift) - 1;
/*
- * Determine whether any threading flags are
- * necessry.
+ * Assign CPU IDs to local APIC IDs and disable any CPUs
+ * beyond MAXCPU. CPU 0 is always assigned to the BSP.
*/
- topo_probe();
- if (cpu_logical > 1 && hyperthreading_cpus)
- cg_flags = CG_FLAG_HTT;
- else if (cpu_logical > 1)
- cg_flags = CG_FLAG_SMT;
+ mp_ncpus = 0;
+ TOPO_FOREACH(node, &topo_root) {
+ if (node->type != TOPO_TYPE_PU)
+ continue;
+
+ if ((node->hwid & smt_mask) != (boot_cpu_id & smt_mask))
+ cpu_info[node->hwid].cpu_hyperthread = 1;
+
+ if (resource_disabled("lapic", node->hwid)) {
+ if (node->hwid != boot_cpu_id)
+ cpu_info[node->hwid].cpu_disabled = 1;
+ else
+ printf("Cannot disable BSP, APIC ID = %d\n",
+ node->hwid);
+ }
+
+ if (!hyperthreading_allowed &&
+ cpu_info[node->hwid].cpu_hyperthread)
+ cpu_info[node->hwid].cpu_disabled = 1;
+
+ if (mp_ncpus >= MAXCPU)
+ cpu_info[node->hwid].cpu_disabled = 1;
+
+ if (cpu_info[node->hwid].cpu_disabled) {
+ disabled_cpus++;
+ continue;
+ }
+
+ cpu_apic_ids[mp_ncpus] = node->hwid;
+ apic_cpuids[node->hwid] = mp_ncpus;
+ topo_set_pu_id(node, mp_ncpus);
+ mp_ncpus++;
+ }
+
+ KASSERT(mp_maxid >= mp_ncpus - 1,
+ ("%s: counters out of sync: max %d, count %d", __func__, mp_maxid,
+ mp_ncpus));
+}
+
+/*
+ * Print various information about the SMP system hardware and setup.
+ */
+void
+cpu_mp_announce(void)
+{
+ struct topo_node *node;
+ const char *hyperthread;
+ int pkg_count;
+ int cores_per_pkg;
+ int thrs_per_core;
+
+ printf("FreeBSD/SMP: ");
+ if (topo_analyze(&topo_root, 1, &pkg_count,
+ &cores_per_pkg, &thrs_per_core)) {
+ printf("%d package(s)", pkg_count);
+ if (cores_per_pkg > 0)
+ printf(" x %d core(s)", cores_per_pkg);
+ if (thrs_per_core > 1)
+ printf(" x %d hardware threads", thrs_per_core);
+ } else {
+ printf("Non-uniform topology");
+ }
+ printf("\n");
+
+ if (disabled_cpus) {
+ printf("FreeBSD/SMP Online: ");
+ if (topo_analyze(&topo_root, 0, &pkg_count,
+ &cores_per_pkg, &thrs_per_core)) {
+ printf("%d package(s)", pkg_count);
+ if (cores_per_pkg > 0)
+ printf(" x %d core(s)", cores_per_pkg);
+ if (thrs_per_core > 1)
+ printf(" x %d hardware threads", thrs_per_core);
+ } else {
+ printf("Non-uniform topology");
+ }
+ printf("\n");
+ }
+
+ if (!bootverbose)
+ return;
+
+ TOPO_FOREACH(node, &topo_root) {
+ switch (node->type) {
+ case TOPO_TYPE_PKG:
+ printf("Package HW ID = %u (%#x)\n",
+ node->hwid, node->hwid);
+ break;
+ case TOPO_TYPE_CORE:
+ printf("\tCore HW ID = %u (%#x)\n",
+ node->hwid, node->hwid);
+ break;
+ case TOPO_TYPE_PU:
+ if (cpu_info[node->hwid].cpu_hyperthread)
+ hyperthread = "/HT";
+ else
+ hyperthread = "";
+
+ if (node->subtype == 0)
+ printf("\t\tCPU (AP%s): APIC ID: %u (%#x)"
+ "(disabled)\n", hyperthread, node->hwid,
+ node->hwid);
+ else if (node->id == 0)
+ printf("\t\tCPU0 (BSP): APIC ID: %u (%#x)\n",
+ node->hwid, node->hwid);
+ else
+ printf("\t\tCPU%u (AP%s): APIC ID: %u (%#x)\n",
+ node->id, hyperthread, node->hwid,
+ node->hwid);
+ break;
+ default:
+ /* ignored */
+ break;
+ }
+ }
+}
+
+static void
+x86topo_add_sched_group(struct topo_node *root, struct cpu_group *cg_root)
+{
+ struct topo_node *node;
+ int nchildren;
+ int ncores;
+ int i;
+
+ KASSERT(root->type == TOPO_TYPE_SYSTEM || root->type == TOPO_TYPE_CACHE,
+ ("x86topo_add_sched_group: bad type: %u", root->type));
+ CPU_COPY(&root->cpuset, &cg_root->cg_mask);
+ cg_root->cg_count = root->cpu_count;
+ if (root->type == TOPO_TYPE_SYSTEM)
+ cg_root->cg_level = CG_SHARE_NONE;
else
- cg_flags = 0;
- if (mp_ncpus % (cpu_cores * cpu_logical) != 0) {
- printf("WARNING: Non-uniform processors.\n");
- printf("WARNING: Using suboptimal topology.\n");
- return (smp_topo_none());
+ cg_root->cg_level = root->subtype;
+
+ ncores = 0;
+ node = root;
+ while (node != NULL) {
+ if (node->type != TOPO_TYPE_CORE) {
+ node = topo_next_node(root, node);
+ continue;
+ }
+
+ ncores++;
+ node = topo_next_nonchild_node(root, node);
}
- /*
- * No multi-core or hyper-threaded.
- */
- if (cpu_logical * cpu_cores == 1)
+
+ if (cg_root->cg_level != CG_SHARE_NONE &&
+ root->cpu_count > 1 && ncores < 2)
+ cg_root->cg_flags = CG_FLAG_SMT;
+
+ nchildren = 0;
+ node = root;
+ while (node != NULL) {
+ if (node->type != TOPO_TYPE_CACHE ||
+ (root->type != TOPO_TYPE_SYSTEM &&
+ CPU_CMP(&node->cpuset, &root->cpuset) == 0)) {
+ node = topo_next_node(root, node);
+ continue;
+ }
+ nchildren++;
+ node = topo_next_nonchild_node(root, node);
+ }
+
+ cg_root->cg_child = smp_topo_alloc(nchildren);
+ cg_root->cg_children = nchildren;
+
+ node = root;
+ i = 0;
+ while (node != NULL) {
+ if (node->type != TOPO_TYPE_CACHE ||
+ (root->type != TOPO_TYPE_SYSTEM &&
+ CPU_CMP(&node->cpuset, &root->cpuset) == 0)) {
+ node = topo_next_node(root, node);
+ continue;
+ }
+ cg_root->cg_child[i].cg_parent = cg_root;
+ x86topo_add_sched_group(node, &cg_root->cg_child[i]);
+ i++;
+ node = topo_next_nonchild_node(root, node);
+ }
+}
+
+struct cpu_group *
+cpu_topo(void)
+{
+ struct cpu_group *cg_root;
+
+ if (mp_ncpus <= 1)
return (smp_topo_none());
- /*
- * Only HTT no multi-core.
- */
- if (cpu_logical > 1 && cpu_cores == 1)
- return (smp_topo_1level(CG_SHARE_L1, cpu_logical, cg_flags));
- /*
- * Only multi-core no HTT.
- */
- if (cpu_cores > 1 && cpu_logical == 1)
- return (smp_topo_1level(CG_SHARE_L2, cpu_cores, cg_flags));
- /*
- * Both HTT and multi-core.
- */
- return (smp_topo_2level(CG_SHARE_L2, cpu_cores,
- CG_SHARE_L1, cpu_logical, cg_flags));
+
+ cg_root = smp_topo_alloc(1);
+ x86topo_add_sched_group(&topo_root, cg_root);
+ return (cg_root);
}
@@ -445,47 +771,9 @@ cpu_mp_probe(void)
}
/*
- * Print various information about the SMP system hardware and setup.
+ * AP CPU's call this to initialize themselves.
*/
void
-cpu_mp_announce(void)
-{
- const char *hyperthread;
- int i;
-
- printf("FreeBSD/SMP: %d package(s) x %d core(s)",
- mp_ncpus / (cpu_cores * cpu_logical), cpu_cores);
- if (hyperthreading_cpus > 1)
- printf(" x %d HTT threads", cpu_logical);
- else if (cpu_logical > 1)
- printf(" x %d SMT threads", cpu_logical);
- printf("\n");
-
- /* List active CPUs first. */
- printf(" cpu0 (BSP): APIC ID: %2d\n", boot_cpu_id);
- for (i = 1; i < mp_ncpus; i++) {
- if (cpu_info[cpu_apic_ids[i]].cpu_hyperthread)
- hyperthread = "/HT";
- else
- hyperthread = "";
- printf(" cpu%d (AP%s): APIC ID: %2d\n", i, hyperthread,
- cpu_apic_ids[i]);
- }
-
- /* List disabled CPUs last. */
- for (i = 0; i <= MAX_APIC_ID; i++) {
- if (!cpu_info[i].cpu_present || !cpu_info[i].cpu_disabled)
- continue;
- if (cpu_info[i].cpu_hyperthread)
- hyperthread = "/HT";
- else
- hyperthread = "";
- printf(" cpu (AP%s): APIC ID: %2d (disabled)\n", hyperthread,
- i);
- }
-}
-
-void
init_secondary_tail(void)
{
u_int cpuid;
@@ -546,8 +834,7 @@ init_secondary_tail(void)
printf("SMP: AP CPU #%d Launched!\n", cpuid);
/* Determine if we are a logical CPU. */
- /* XXX Calculation depends on cpu_logical being a power of 2, e.g. 2 */
- if (cpu_logical > 1 && PCPU_GET(apic_id) % cpu_logical != 0)
+ if (cpu_info[PCPU_GET(apic_id)].cpu_hyperthread)
CPU_SET(cpuid, &logical_cpus_mask);
if (bootverbose)
@@ -612,85 +899,13 @@ set_interrupt_apic_ids(void)
continue;
/* Don't let hyperthreads service interrupts. */
- if (cpu_logical > 1 &&
- apic_id % cpu_logical != 0)
+ if (cpu_info[apic_id].cpu_hyperthread)
continue;
intr_add_cpu(i);
}
}
-/*
- * Assign logical CPU IDs to local APICs.
- */
-void
-assign_cpu_ids(void)
-{
- u_int i;
-
- TUNABLE_INT_FETCH("machdep.hyperthreading_allowed",
- &hyperthreading_allowed);
-
- /* Check for explicitly disabled CPUs. */
- for (i = 0; i <= MAX_APIC_ID; i++) {
- if (!cpu_info[i].cpu_present || cpu_info[i].cpu_bsp)
- continue;
-
- if (hyperthreading_cpus > 1 && i % hyperthreading_cpus != 0) {
- cpu_info[i].cpu_hyperthread = 1;
-
- /*
- * Don't use HT CPU if it has been disabled by a
- * tunable.
- */
- if (hyperthreading_allowed == 0) {
- cpu_info[i].cpu_disabled = 1;
- continue;
- }
- }
-
- /* Don't use this CPU if it has been disabled by a tunable. */
- if (resource_disabled("lapic", i)) {
- cpu_info[i].cpu_disabled = 1;
- continue;
- }
- }
-
- if (hyperthreading_allowed == 0 && hyperthreading_cpus > 1) {
- hyperthreading_cpus = 0;
- cpu_logical = 1;
- }
-
- /*
- * Assign CPU IDs to local APIC IDs and disable any CPUs
- * beyond MAXCPU. CPU 0 is always assigned to the BSP.
- *
- * To minimize confusion for userland, we attempt to number
- * CPUs such that all threads and cores in a package are
- * grouped together. For now we assume that the BSP is always
- * the first thread in a package and just start adding APs
- * starting with the BSP's APIC ID.
- */
- mp_ncpus = 1;
- cpu_apic_ids[0] = boot_cpu_id;
- apic_cpuids[boot_cpu_id] = 0;
- for (i = boot_cpu_id + 1; i != boot_cpu_id;
- i == MAX_APIC_ID ? i = 0 : i++) {
- if (!cpu_info[i].cpu_present || cpu_info[i].cpu_bsp ||
- cpu_info[i].cpu_disabled)
- continue;
-
- if (mp_ncpus < MAXCPU) {
- cpu_apic_ids[mp_ncpus] = i;
- apic_cpuids[i] = mp_ncpus;
- mp_ncpus++;
- } else
- cpu_info[i].cpu_disabled = 1;
- }
- KASSERT(mp_maxid >= mp_ncpus - 1,
- ("%s: counters out of sync: max %d, count %d", __func__, mp_maxid,
- mp_ncpus));
-}
#ifdef COUNT_XINVLTLB_HITS
u_int xhits_gbl[MAXCPU];
@@ -910,7 +1125,7 @@ ipi_all_but_self(u_int ipi)
}
int
-ipi_nmi_handler()
+ipi_nmi_handler(void)
{
u_int cpuid;
diff --git a/sys/x86/x86/nexus.c b/sys/x86/x86/nexus.c
index 39eeb82..8b49d41 100644
--- a/sys/x86/x86/nexus.c
+++ b/sys/x86/x86/nexus.c
@@ -301,9 +301,9 @@ nexus_print_all_resources(device_t dev)
if (STAILQ_FIRST(rl))
retval += printf(" at");
- retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx");
- retval += resource_list_print_type(rl, "iomem", SYS_RES_MEMORY, "%#lx");
- retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+ retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#jx");
+ retval += resource_list_print_type(rl, "iomem", SYS_RES_MEMORY, "%#jx");
+ retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
return retval;
}
diff --git a/targets/Makefile.xtras b/targets/Makefile.xtras
index 807cb9a..124bddc 100644
--- a/targets/Makefile.xtras
+++ b/targets/Makefile.xtras
@@ -33,14 +33,27 @@ OTHER_TARGETS = \
destroy-host \
destroy-stage \
-BUILD_TARGETS != cd ${_here} && \
+BUILD_TARGETS_${MACHINE:tu} != cd ${_here} && \
find . \( -name Makefile.depend -o -name ${.MAKE.DEPENDFILE:T} \) | \
sed 's,/Makefile.*,,;s,^./,,' | sort -u
+.for _machine in ${all_machine_list}
+_targets_${_machine} != cd ${_here} && \
+ find . \( -name Makefile.depend.${_machine} -o \
+ -name ${.MAKE.DEPENDFILE:T}.${_machine} \) | \
+ sed 's,/Makefile.*,,;s,^./,,' | sort -u
+BUILD_TARGETS_${_machine:tu} += ${_targets_${_machine}}
+.endfor
+
show-valid-targets:
- @echo "Build targets for ${MACHINE} (leave out the ${target_dirs:S,${_here:T},,:S,^/,,:S,$,/,}):"
- @echo "${BUILD_TARGETS:ts\n}"
- @echo; echo "Other targets:"; echo "${OTHER_TARGETS:ts\n}"
+.for _machine in ${all_machine_list:O}
+.if !empty(BUILD_TARGETS_${_machine:tu})
+ @echo "Build targets for ${_machine} (leave out the ${target_dirs:S,${_here:T},,:S,^/,,:S,$,/,}):"
+ @echo -e "${BUILD_TARGETS_${_machine:tu}:O:ts\n}" | sed -e 's,^, ,'
+ @echo
+.endif
+.endfor
+ @echo "Other targets:"; echo "${OTHER_TARGETS:O:ts\n}" | sed -e 's,^, ,'
.endif
help: show-help
diff --git a/targets/pseudo/hosttools/Makefile.depend b/targets/pseudo/hosttools/Makefile.depend
deleted file mode 100644
index d39e91e..0000000
--- a/targets/pseudo/hosttools/Makefile.depend
+++ /dev/null
@@ -1,36 +0,0 @@
-# $FreeBSD$
-
-# This file is not autogenerated - take care!
-
-.if !defined(MK_KERBEROS)
-.include <src.opts.mk>
-.endif
-
-DIRDEPS = \
- lib/clang/include.host \
- lib/libc++.host \
- lib/libcxxrt.host \
- share/doc/llvm/clang.host \
- usr.bin/clang/clang-tblgen.host \
- usr.bin/clang/clang.host \
- usr.bin/clang/llvm-tblgen.host \
- usr.bin/lex/lib.host \
- usr.bin/localedef.host \
- usr.bin/mkcsmapper_static.host \
- usr.bin/mkesdb_static.host \
- usr.bin/mkuzip.host \
- usr.bin/yacc.host \
- usr.bin/xinstall.host \
- usr.bin/xlint/xlint.host \
- usr.sbin/config.host \
-
-.if ${MK_KERBEROS} != "no"
-DIRDEPS+= \
- kerberos5/tools/asn1_compile.host \
- kerberos5/tools/make-roken.host \
- usr.bin/compile_et.host \
-
-.endif
-
-
-.include <dirdeps.mk>
diff --git a/targets/pseudo/hosttools/Makefile.depend.host b/targets/pseudo/hosttools/Makefile.depend.host
new file mode 100644
index 0000000..89d87f4
--- /dev/null
+++ b/targets/pseudo/hosttools/Makefile.depend.host
@@ -0,0 +1,31 @@
+# $FreeBSD$
+
+# This file is not autogenerated - take care!
+
+.if !defined(MK_KERBEROS)
+.include <src.opts.mk>
+.endif
+
+# These are all .host dependencies
+
+DIRDEPS = \
+ usr.bin/clang/clang-tblgen \
+ usr.bin/clang/llvm-tblgen \
+ usr.bin/localedef \
+ usr.bin/mkcsmapper_static \
+ usr.bin/mkesdb_static \
+ usr.bin/xinstall \
+ usr.bin/xlint/xlint \
+ usr.bin/yacc \
+ usr.sbin/config \
+
+.if ${MK_KERBEROS} != "no"
+DIRDEPS+= \
+ kerberos5/tools/asn1_compile \
+ kerberos5/tools/make-roken \
+ usr.bin/compile_et \
+
+.endif
+
+
+.include <dirdeps.mk>
diff --git a/targets/pseudo/userland/misc/Makefile.depend b/targets/pseudo/userland/misc/Makefile.depend
index c186f6d..b0423a5 100644
--- a/targets/pseudo/userland/misc/Makefile.depend
+++ b/targets/pseudo/userland/misc/Makefile.depend
@@ -32,6 +32,7 @@ DIRDEPS+= \
DIRDEPS.x86sys= \
sys/boot/efi/libefi \
+ sys/boot/geli \
sys/boot/i386/boot0 \
sys/boot/i386/boot0sio \
sys/boot/i386/boot2 \
diff --git a/tests/sys/aio/aio_test.c b/tests/sys/aio/aio_test.c
index 607f46d..5515161 100644
--- a/tests/sys/aio/aio_test.c
+++ b/tests/sys/aio/aio_test.c
@@ -649,6 +649,79 @@ ATF_TC_BODY(aio_md_test, tc)
aio_md_cleanup(&arg);
}
+ATF_TC_WITHOUT_HEAD(aio_large_read_test);
+ATF_TC_BODY(aio_large_read_test, tc)
+{
+ char pathname[PATH_MAX];
+ struct aiocb cb, *cbp;
+ ssize_t nread;
+ size_t len;
+ int fd;
+#ifdef __LP64__
+ int clamped;
+#endif
+
+ ATF_REQUIRE_KERNEL_MODULE("aio");
+ ATF_REQUIRE_UNSAFE_AIO();
+
+#ifdef __LP64__
+ len = sizeof(clamped);
+ if (sysctlbyname("debug.iosize_max_clamp", &clamped, &len, NULL, 0) ==
+ -1)
+ atf_libc_error(errno, "Failed to read debug.iosize_max_clamp");
+#endif
+
+ /* Determine the maximum supported read(2) size. */
+ len = SSIZE_MAX;
+#ifdef __LP64__
+ if (clamped)
+ len = INT_MAX;
+#endif
+
+ strcpy(pathname, PATH_TEMPLATE);
+ fd = mkstemp(pathname);
+ ATF_REQUIRE_MSG(fd != -1, "mkstemp failed: %s", strerror(errno));
+
+ unlink(pathname);
+
+ memset(&cb, 0, sizeof(cb));
+ cb.aio_nbytes = len;
+ cb.aio_fildes = fd;
+ cb.aio_buf = NULL;
+ if (aio_read(&cb) == -1)
+ atf_tc_fail("aio_read() of maximum read size failed: %s",
+ strerror(errno));
+
+ nread = aio_waitcomplete(&cbp, NULL);
+ if (nread == -1)
+ atf_tc_fail("aio_waitcomplete() failed: %s", strerror(errno));
+ if (nread != 0)
+ atf_tc_fail("aio_read() from empty file returned data: %zd",
+ nread);
+
+ memset(&cb, 0, sizeof(cb));
+ cb.aio_nbytes = len + 1;
+ cb.aio_fildes = fd;
+ cb.aio_buf = NULL;
+ if (aio_read(&cb) == -1) {
+ if (errno == EINVAL)
+ goto finished;
+ atf_tc_fail("aio_read() of too large read size failed: %s",
+ strerror(errno));
+ }
+
+ nread = aio_waitcomplete(&cbp, NULL);
+ if (nread == -1) {
+ if (errno == EINVAL)
+ goto finished;
+ atf_tc_fail("aio_waitcomplete() failed: %s", strerror(errno));
+ }
+ atf_tc_fail("aio_read() of too large read size returned: %zd", nread);
+
+finished:
+ close(fd);
+}
+
ATF_TP_ADD_TCS(tp)
{
@@ -658,6 +731,7 @@ ATF_TP_ADD_TCS(tp)
ATF_TP_ADD_TC(tp, aio_pty_test);
ATF_TP_ADD_TC(tp, aio_pipe_test);
ATF_TP_ADD_TC(tp, aio_md_test);
+ ATF_TP_ADD_TC(tp, aio_large_read_test);
return (atf_no_error());
}
diff --git a/tests/sys/geom/class/geom_subr.sh b/tests/sys/geom/class/geom_subr.sh
index b437183..b03ee43 100644
--- a/tests/sys/geom/class/geom_subr.sh
+++ b/tests/sys/geom/class/geom_subr.sh
@@ -35,16 +35,14 @@ geom_test_cleanup()
}
if [ $(id -u) -ne 0 ]; then
- echo 'Tests must be run as root'
- echo 'Bail out!'
- exit 1
+ echo '1..0 # SKIP tests must be run as root'
+ exit 0
fi
# If the geom class isn't already loaded, try loading it.
if ! kldstat -q -m g_${class}; then
if ! geom ${class} load; then
- echo "Could not load module for geom class=${class}"
- echo 'Bail out!'
- exit 1
+ echo "1..0 # SKIP could not load module for geom class=${class}"
+ exit 0
fi
fi
diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc
index eb9060d..326e543 100644
--- a/tools/build/mk/OptionalObsoleteFiles.inc
+++ b/tools/build/mk/OptionalObsoleteFiles.inc
@@ -8024,6 +8024,7 @@ OLD_FILES+=usr/share/examples/libusb20/control.c
OLD_FILES+=usr/share/examples/libusb20/util.c
OLD_FILES+=usr/share/examples/libusb20/util.h
OLD_DIRS+=usr/share/examples/libusb20
+OLD_FILES+=usr/share/firmware/ar5523.bin
OLD_FILES+=usr/share/man/man1/uhsoctl.1.gz
OLD_FILES+=usr/share/man/man1/usbhidaction.1.gz
OLD_FILES+=usr/share/man/man1/usbhidctl.1.gz
diff --git a/tools/build/options/WITHOUT_FAST_DEPEND b/tools/build/options/WITHOUT_FAST_DEPEND
deleted file mode 100644
index 2e6ca44..0000000
--- a/tools/build/options/WITHOUT_FAST_DEPEND
+++ /dev/null
@@ -1,5 +0,0 @@
-.\" $FreeBSD$
-Set to use the historical
-.Xr mkdep 1
-for the "make depend" phase of the build.
-This option is deprecated and will be removed soon.
diff --git a/tools/build/options/WITH_CCACHE_BUILD b/tools/build/options/WITH_CCACHE_BUILD
index 4e29c9a..86b7f1a 100644
--- a/tools/build/options/WITH_CCACHE_BUILD
+++ b/tools/build/options/WITH_CCACHE_BUILD
@@ -24,9 +24,6 @@ when using an external compiler.
The
.Sy CCACHE_CPP2
option is used for Clang but not GCC.
-ccache works best when combined with the
-.Sy WITH_FAST_DEPEND
-option.
.Pp
Sharing a cache between multiple work directories requires using a layout
similar to
diff --git a/tools/build/options/WITH_FAST_DEPEND b/tools/build/options/WITH_FAST_DEPEND
deleted file mode 100644
index 2597a36..0000000
--- a/tools/build/options/WITH_FAST_DEPEND
+++ /dev/null
@@ -1,7 +0,0 @@
-.\" $FreeBSD$
-Set to generate
-.Sy .depend
-files in the build during compilation instead of the
-historial
-.Xr mkdep 1
-call during the "make depend" phase.
diff --git a/tools/tinder.sh b/tools/tinder.sh
index 4291e88..aaca7c8 100755
--- a/tools/tinder.sh
+++ b/tools/tinder.sh
@@ -58,4 +58,4 @@ for i in "$@"; do
;;
esac
done
-make tinderbox UNIVERSE_TARGET="_cleanobj _obj _depend everything" $MAKE_ARGS SUBDIR_OVERRIDE="$SUBDIR"
+make tinderbox UNIVERSE_TARGET="_cleanobj _obj everything" $MAKE_ARGS SUBDIR_OVERRIDE="$SUBDIR"
diff --git a/tools/tools/nanobsd/defaults.sh b/tools/tools/nanobsd/defaults.sh
index 9a5c5cb..cb7a2d1 100755
--- a/tools/tools/nanobsd/defaults.sh
+++ b/tools/tools/nanobsd/defaults.sh
@@ -83,6 +83,9 @@ NANO_KERNEL=GENERIC
# Use "default" to install all built modules.
NANO_MODULES=
+# Early customize commands.
+NANO_EARLY_CUSTOMIZE=""
+
# Customize commands.
NANO_CUSTOMIZE=""
@@ -450,6 +453,22 @@ native_xtools ( ) (
)
#
+# Run the requested set of early customization scripts, run before
+# buildworld.
+#
+run_early_customize() {
+
+ pprint 2 "run early customize scripts"
+ for c in $NANO_EARLY_CUSTOMIZE
+ do
+ pprint 2 "early customize \"$c\""
+ pprint 3 "log: ${NANO_LOG}/_.early_cust.$c"
+ pprint 4 "`type $c`"
+ { set -x ; $c ; set +x ; } >${NANO_LOG}/_.early_cust.$c 2>&1
+ done
+}
+
+#
# Run the requested set of customization scripts, run after we've
# done an installworld, installed the etc files, installed the kernel
# and tweaked them in the standard way.
@@ -916,7 +935,7 @@ cust_pkgng ( ) (
mkdir -p ${NANO_WORLDDIR}/Pkg
(
cd "${NANO_PACKAGE_DIR}"
- find "${NANO_PACKAGE_LIST}" -print |
+ find ${NANO_PACKAGE_LIST} -print |
cpio -Ldumpv ${NANO_WORLDDIR}/Pkg
)
@@ -961,6 +980,15 @@ cust_pkgng ( ) (
#######################################################################
# Convenience function:
+# Register all args as early customize function to run just before
+# build commences.
+
+early_customize_cmd () {
+ NANO_EARLY_CUSTOMIZE="$NANO_EARLY_CUSTOMIZE $*"
+}
+
+#######################################################################
+# Convenience function:
# Register all args as customize function.
customize_cmd ( ) {
diff --git a/tools/tools/nanobsd/nanobsd.sh b/tools/tools/nanobsd/nanobsd.sh
index a17db7a..f140a76 100755
--- a/tools/tools/nanobsd/nanobsd.sh
+++ b/tools/tools/nanobsd/nanobsd.sh
@@ -139,6 +139,8 @@ fi
pprint 1 "NanoBSD image ${NANO_NAME} build starting"
+run_early_customize
+
if $do_world ; then
if $do_clean ; then
clean_build
diff --git a/tools/tools/net80211/wlanstats/main.c b/tools/tools/net80211/wlanstats/main.c
index 34d939f..5716d4b 100644
--- a/tools/tools/net80211/wlanstats/main.c
+++ b/tools/tools/net80211/wlanstats/main.c
@@ -61,6 +61,10 @@ static struct {
"ampdu_drop,ampdu_bar,ampdu_baroow,ampdu_barmove,ampdu_bartx,"
"ampdu_bartxfail,ampdu_bartxretry,rssi,rate"
},
+ {
+ "amsdu",
+ "input,output,amsdu_tooshort,amsdu_split,amsdu_decap,amsdu_encap,rssi,rate"
+ },
};
static const char *
diff --git a/tools/tools/net80211/wlanstats/wlanstats.c b/tools/tools/net80211/wlanstats/wlanstats.c
index ef83470..50c86fc 100644
--- a/tools/tools/net80211/wlanstats/wlanstats.c
+++ b/tools/tools/net80211/wlanstats/wlanstats.c
@@ -767,6 +767,7 @@ wlan_get_curstat(struct bsdstat *sf, int s, char b[], size_t bs)
case S_FF_SPLIT: STAT(ff_split);
case S_FF_DECAP: STAT(ff_decap);
case S_FF_ENCAP: STAT(ff_encap);
+ case S_FF_ENCAPFAIL: STAT(ff_encapfail);
case S_RX_BADBINTVAL: STAT(rx_badbintval);
case S_RX_MGMT: STAT(rx_mgmt);
case S_RX_DEMICFAIL: STAT(rx_demicfail);
@@ -929,6 +930,7 @@ wlan_get_totstat(struct bsdstat *sf, int s, char b[], size_t bs)
case S_FF_SPLIT: STAT(ff_split);
case S_FF_DECAP: STAT(ff_decap);
case S_FF_ENCAP: STAT(ff_encap);
+ case S_FF_ENCAPFAIL: STAT(ff_encapfail);
case S_RX_BADBINTVAL: STAT(rx_badbintval);
case S_RX_MGMT: STAT(rx_mgmt);
case S_RX_DEMICFAIL: STAT(rx_demicfail);
diff --git a/tools/tools/vt/setfont/Makefile b/tools/tools/vt/setfont/Makefile
deleted file mode 100644
index a242d51..0000000
--- a/tools/tools/vt/setfont/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-PROG= setfont
-MAN1=
-
-WARNS?= 6
-
-.include <bsd.prog.mk>
diff --git a/tools/tools/vt/setfont/setfont.c b/tools/tools/vt/setfont/setfont.c
deleted file mode 100644
index 127fad3..0000000
--- a/tools/tools/vt/setfont/setfont.c
+++ /dev/null
@@ -1,89 +0,0 @@
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/consio.h>
-#include <sys/endian.h>
-#include <sys/ioctl.h>
-#include <sys/param.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-struct file_header {
- uint8_t magic[8];
- uint8_t width;
- uint8_t height;
- uint16_t pad;
- uint32_t glyph_count;
- uint32_t map_count[4];
-} __packed;
-
-static vfnt_map_t *
-load_mappingtable(unsigned int nmappings)
-{
- vfnt_map_t *t;
- unsigned int i;
-
- if (nmappings == 0)
- return (NULL);
-
- t = malloc(sizeof *t * nmappings);
-
- if (fread(t, sizeof *t * nmappings, 1, stdin) != 1) {
- perror("mappings");
- exit(1);
- }
-
- for (i = 0; i < nmappings; i++) {
- t[i].src = be32toh(t[i].src);
- t[i].dst = be16toh(t[i].dst);
- t[i].len = be16toh(t[i].len);
- }
-
- return (t);
-}
-
-int
-main(int argc __unused, char *argv[] __unused)
-{
- struct file_header fh;
- static vfnt_t vfnt;
- size_t glyphsize;
- unsigned int i;
-
- if (fread(&fh, sizeof fh, 1, stdin) != 1) {
- perror("file_header");
- return (1);
- }
-
- if (memcmp(fh.magic, "VFNT0002", 8) != 0) {
- fprintf(stderr, "Bad magic\n");
- return (1);
- }
-
- for (i = 0; i < VFNT_MAPS; i++)
- vfnt.map_count[i] = be32toh(fh.map_count[i]);
- vfnt.glyph_count = be32toh(fh.glyph_count);
- vfnt.width = fh.width;
- vfnt.height = fh.height;
-
- glyphsize = howmany(vfnt.width, 8) * vfnt.height * vfnt.glyph_count;
- vfnt.glyphs = malloc(glyphsize);
-
- if (fread(vfnt.glyphs, glyphsize, 1, stdin) != 1) {
- perror("glyphs");
- return (1);
- }
-
- for (i = 0; i < VFNT_MAPS; i++)
- vfnt.map[i] = load_mappingtable(vfnt.map_count[i]);
-
- if (ioctl(STDOUT_FILENO, PIO_VFONT, &vfnt) == -1) {
- perror("PIO_VFONT");
- return (1);
- }
-
- return (0);
-}
diff --git a/usr.bin/bmake/Makefile b/usr.bin/bmake/Makefile
index b3291ed..8e1afa2 100644
--- a/usr.bin/bmake/Makefile
+++ b/usr.bin/bmake/Makefile
@@ -14,10 +14,10 @@ CFLAGS+= -I${.CURDIR}
CLEANDIRS+= FreeBSD
CLEANFILES+= bootstrap
-# $Id: Makefile,v 1.55 2016/03/07 22:02:47 sjg Exp $
+# $Id: Makefile,v 1.58 2016/03/15 23:39:12 sjg Exp $
# Base version on src date
-_MAKE_VERSION= 20160307
+_MAKE_VERSION= 20160315
PROG?= ${.CURDIR:T}
diff --git a/usr.bin/fetch/fetch.1 b/usr.bin/fetch/fetch.1
index 58b59ad..999fb2e 100644
--- a/usr.bin/fetch/fetch.1
+++ b/usr.bin/fetch/fetch.1
@@ -1,6 +1,6 @@
.\"-
.\" Copyright (c) 2000-2014 Dag-Erling Smørgrav
-.\" Copyright (c) 2013 Michael Gmelin <freebsd@grem.de>
+.\" Copyright (c) 2013-2016 Michael Gmelin <freebsd@grem.de>
.\" All rights reserved.
.\" Portions Copyright (c) 1999 Massachusetts Institute of Technology; used
.\" by permission.
@@ -30,7 +30,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 25, 2015
+.Dd March 18, 2016
.Dt FETCH 1
.Os
.Sh NAME
@@ -134,11 +134,17 @@ only.
[SSL]
Path to certificate bundle containing trusted CA certificates.
If not specified,
-.Pa /etc/ssl/cert.pem
+.Pa /usr/local/etc/ssl/cert.pem
is used.
-The file may contain multiple CA certificates. The port
+If this file does not exist,
+.Pa /etc/ssl/cert.pem
+is used instead.
+If neither file exists and no CA path has been configured,
+OpenSSL's default CA cert and path settings apply.
+The certificate bundle can contain multiple CA certificates.
+The
.Pa security/ca_root_nss
-is a common source of a current CA bundle.
+port is a common source of a current CA bundle.
.It Fl -ca-path= Ns Ar dir
[SSL]
The directory
@@ -218,10 +224,16 @@ altogether, or a comma- or whitespace-separated list of hosts for
which proxies should not be used.
.It Fl -no-sslv3
[SSL]
-Don't allow SSL version 3 when negotiating the connection.
+Do not allow SSL version 3 when negotiating the connection.
+This option is deprecated and is provided for backward compatibility
+only.
+SSLv3 is disabled by default.
+Set
+.Ev SSL_ALLOW_SSL3
+to change this behavior.
.It Fl -no-tlsv1
[SSL]
-Don't allow TLS version 1 when negotiating the connection.
+Do not allow TLS version 1 when negotiating the connection.
.It Fl -no-verify-hostname
[SSL]
Do not verify that the hostname matches the subject of the
@@ -351,8 +363,10 @@ for a description of additional environment variables, including
.Ev SSL_CLIENT_CERT_FILE ,
.Ev SSL_CLIENT_KEY_FILE ,
.Ev SSL_CRL_FILE ,
-.Ev SSL_NO_SSL3 ,
+.Ev SSL_ALLOW_SSL3 ,
.Ev SSL_NO_TLS1 ,
+.Ev SSL_NO_TLS1_1 ,
+.Ev SSL_NO_TLS1_2 ,
.Ev SSL_NO_VERIFY_HOSTNAME
and
.Ev SSL_NO_VERIFY_PEER .
@@ -371,7 +385,8 @@ argument is used and the remote file is not newer than the
specified file then the command will still return success,
although no file is transferred.
.Sh SEE ALSO
-.Xr fetch 3
+.Xr fetch 3 ,
+.Xr phttpget 8
.Sh HISTORY
The
.Nm
diff --git a/usr.bin/finger/sprint.c b/usr.bin/finger/sprint.c
index d9a6cef..afbab4e 100644
--- a/usr.bin/finger/sprint.c
+++ b/usr.bin/finger/sprint.c
@@ -149,7 +149,7 @@ office:
else if (pn->officephone)
(void)printf(" %-7.7s", " ");
if (pn->officephone)
- (void)printf(" %-.9s",
+ (void)printf(" %-.15s",
prphone(pn->officephone));
} else
(void)printf(" %.*s", MAXHOSTNAME, w->host);
diff --git a/usr.bin/ktrace/ktrace.1 b/usr.bin/ktrace/ktrace.1
index a5e930a..4a46052 100644
--- a/usr.bin/ktrace/ktrace.1
+++ b/usr.bin/ktrace/ktrace.1
@@ -28,7 +28,7 @@
.\" @(#)ktrace.1 8.1 (Berkeley) 6/6/93
.\" $FreeBSD$
.\"
-.Dd August 26, 2014
+.Dd March 31, 2016
.Dt KTRACE 1
.Os
.Sh NAME
@@ -175,7 +175,8 @@ on process 67
# disable tracing of all user-owned processes
.Dl $ ktrace -C
.Sh SEE ALSO
-.Xr kdump 1
+.Xr kdump 1 ,
+.Xr ktrace 2
.Sh HISTORY
The
.Nm
diff --git a/usr.bin/localedef/ctype.c b/usr.bin/localedef/ctype.c
index d610833..e737ed5 100644
--- a/usr.bin/localedef/ctype.c
+++ b/usr.bin/localedef/ctype.c
@@ -332,14 +332,14 @@ dump_ctype(void)
ctn->ctype |= _ISLOWER;
if ((wc >= '0') && (wc <= '9'))
ctn->ctype |= _ISDIGIT;
+ if (wc == ' ')
+ ctn->ctype |= _ISPRINT;
if (strchr(" \f\n\r\t\v", (char)wc) != NULL)
ctn->ctype |= _ISSPACE;
if (strchr("0123456789ABCDEFabcdef", (char)wc) != NULL)
ctn->ctype |= _ISXDIGIT;
if (strchr(" \t", (char)wc))
ctn->ctype |= _ISBLANK;
- if (wc == ' ')
- ctn->ctype |= _ISPRINT;
/*
* Technically these settings are only
diff --git a/usr.bin/netstat/inet.c b/usr.bin/netstat/inet.c
index b0a0a7f..4793229 100644
--- a/usr.bin/netstat/inet.c
+++ b/usr.bin/netstat/inet.c
@@ -82,6 +82,7 @@ __FBSDID("$FreeBSD$");
#include <unistd.h>
#include <libxo/xo.h>
#include "netstat.h"
+#include "nl_defs.h"
char *inetname(struct in_addr *);
void inetprint(const char *, struct in_addr *, int, const char *, int,
@@ -638,6 +639,7 @@ void
tcp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
{
struct tcpstat tcpstat;
+ uint64_t tcps_states[TCP_NSTATES];
#ifdef INET6
if (tcp_done != 0)
@@ -650,6 +652,10 @@ tcp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
sizeof(tcpstat), kread_counters) != 0)
return;
+ if (fetch_stats_ro("net.inet.tcp.states", nl[N_TCPS_STATES].n_value,
+ &tcps_states, sizeof(tcps_states), kread_counters) != 0)
+ return;
+
xo_open_container("tcp");
xo_emit("{T:/%s}:\n", name);
@@ -853,6 +859,28 @@ tcp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
#undef p2a
#undef p3
xo_close_container("ecn");
+
+ xo_open_container("TCP connection count by state");
+ xo_emit("{T:/TCP connection count by state}:\n");
+ for (int i = 0; i < TCP_NSTATES; i++) {
+ /*
+ * XXXGL: is there a way in libxo to use %s
+ * in the "content string" of a format
+ * string? I failed to do that, that's why
+ * a temporary buffer is used to construct
+ * format string for xo_emit().
+ */
+ char fmtbuf[80];
+
+ if (sflag > 1 && tcps_states[i] == 0)
+ continue;
+ snprintf(fmtbuf, sizeof(fmtbuf), "\t{:%s/%%ju} "
+ "{Np:/connection ,connections} in %s state\n",
+ tcpstates[i], tcpstates[i]);
+ xo_emit(fmtbuf, (uintmax_t )tcps_states[i]);
+ }
+ xo_close_container("TCP connection count by state");
+
xo_close_container("tcp");
}
diff --git a/usr.bin/netstat/main.c b/usr.bin/netstat/main.c
index e8cf914..4e4428d 100644
--- a/usr.bin/netstat/main.c
+++ b/usr.bin/netstat/main.c
@@ -551,15 +551,15 @@ main(int argc, char *argv[])
exit(0);
}
-int
-fetch_stats(const char *sysctlname, u_long off, void *stats, size_t len,
- int (*kreadfn)(u_long, void *, size_t))
+static int
+fetch_stats_internal(const char *sysctlname, u_long off, void *stats,
+ size_t len, kreadfn_t kreadfn, int zero)
{
int error;
if (live) {
memset(stats, 0, len);
- if (zflag)
+ if (zero)
error = sysctlbyname(sysctlname, NULL, NULL, stats,
len);
else
@@ -574,6 +574,23 @@ fetch_stats(const char *sysctlname, u_long off, void *stats, size_t len,
return (error);
}
+int
+fetch_stats(const char *sysctlname, u_long off, void *stats,
+ size_t len, kreadfn_t kreadfn)
+{
+
+ return (fetch_stats_internal(sysctlname, off, stats, len, kreadfn,
+ zflag));
+}
+
+int
+fetch_stats_ro(const char *sysctlname, u_long off, void *stats,
+ size_t len, kreadfn_t kreadfn)
+{
+
+ return (fetch_stats_internal(sysctlname, off, stats, len, kreadfn, 0));
+}
+
/*
* Print out protocol statistics or control blocks (per sflag).
* If the interface was not specifically requested, and the symbol
diff --git a/usr.bin/netstat/netstat.h b/usr.bin/netstat/netstat.h
index 776c4d4..4db2844 100644
--- a/usr.bin/netstat/netstat.h
+++ b/usr.bin/netstat/netstat.h
@@ -63,8 +63,10 @@ extern int unit; /* unit number for above */
extern int live; /* true if we are examining a live system */
-int fetch_stats(const char *sysctlname, u_long addr, void *stats,
- size_t len, int (*kreadfn)(u_long, void *, size_t));
+typedef int kreadfn_t(u_long, void *, size_t);
+int fetch_stats(const char *, u_long, void *, size_t, kreadfn_t);
+int fetch_stats_ro(const char *, u_long, void *, size_t, kreadfn_t);
+
int kread(u_long addr, void *buf, size_t size);
uint64_t kread_counter(u_long addr);
int kread_counters(u_long addr, void *buf, size_t size);
diff --git a/usr.bin/netstat/nlist_symbols b/usr.bin/netstat/nlist_symbols
index e2b7e2f..afad45d 100644
--- a/usr.bin/netstat/nlist_symbols
+++ b/usr.bin/netstat/nlist_symbols
@@ -44,6 +44,7 @@ all _sctpstat
all _sfstat
all _tcbinfo
all _tcpstat
+all _tcps_states
all _udbinfo
all _udpstat
all _unp_count
diff --git a/usr.bin/netstat/route.c b/usr.bin/netstat/route.c
index 77487df..1cd831b 100644
--- a/usr.bin/netstat/route.c
+++ b/usr.bin/netstat/route.c
@@ -417,6 +417,7 @@ p_sockaddr(const char *name, struct sockaddr *sa, struct sockaddr *mask,
if (width < 0) {
snprintf(buf, sizeof(buf), "{:%s/%%s} ", name);
xo_emit(buf, cp);
+ protrusion = 0;
} else {
if (Wflag != 0 || numeric_addr) {
snprintf(buf, sizeof(buf), "{[:%d}{:%s/%%s}{]:} ",
diff --git a/usr.bin/showmount/showmount.8 b/usr.bin/showmount/showmount.8
index 2831593..692c6d6 100644
--- a/usr.bin/showmount/showmount.8
+++ b/usr.bin/showmount/showmount.8
@@ -31,7 +31,7 @@
.\" @(#)showmount.8 8.3 (Berkeley) 3/29/95
.\" $FreeBSD$
.\"
-.Dd August 16, 2014
+.Dd March 20, 2016
.Dt SHOWMOUNT 8
.Os
.Sh NAME
@@ -40,6 +40,7 @@
.Sh SYNOPSIS
.Nm
.Op Fl a | d
+.Op Fl E
.Op Fl e
.Op Fl 1
.Op Fl 3
@@ -73,6 +74,12 @@ List all mount points in the form:
.Ed
.It Fl d
List directory paths of mount points instead of hosts.
+.It Fl E
+Show the
+.Ar host Ns 's
+exports list in a script-friendly format.
+Client addresses and the header are not shown, and special
+characters are escaped.
.It Fl e
Show the
.Ar host Ns 's
diff --git a/usr.bin/showmount/showmount.c b/usr.bin/showmount/showmount.c
index d0da570..46e58e4 100644
--- a/usr.bin/showmount/showmount.c
+++ b/usr.bin/showmount/showmount.c
@@ -61,13 +61,15 @@ static const char rcsid[] =
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <vis.h>
/* Constant defs */
#define ALL 1
#define DIRS 2
-#define DODUMP 0x1
-#define DOEXPORTS 0x2
+#define DODUMP 0x1
+#define DOEXPORTS 0x2
+#define DOPARSABLEEXPORTS 0x4
struct mountlist {
struct mountlist *ml_left;
@@ -108,13 +110,14 @@ int tcp_callrpc(const char *host, int prognum, int versnum, int procnum,
int
main(int argc, char **argv)
{
+ char strvised[MNTPATHLEN * 4 + 1];
register struct exportslist *exp;
register struct grouplist *grp;
register int rpcs = 0, mntvers = 3;
const char *host;
- int ch, estat;
+ int ch, estat, nbytes;
- while ((ch = getopt(argc, argv, "ade13")) != -1)
+ while ((ch = getopt(argc, argv, "adEe13")) != -1)
switch (ch) {
case 'a':
if (type == 0) {
@@ -130,6 +133,9 @@ main(int argc, char **argv)
} else
usage();
break;
+ case 'E':
+ rpcs |= DOPARSABLEEXPORTS;
+ break;
case 'e':
rpcs |= DOEXPORTS;
break;
@@ -146,6 +152,13 @@ main(int argc, char **argv)
argc -= optind;
argv += optind;
+ if ((rpcs & DOPARSABLEEXPORTS) != 0) {
+ if ((rpcs & DOEXPORTS) != 0)
+ errx(1, "-E cannot be used with -e");
+ if ((rpcs & DODUMP) != 0)
+ errx(1, "-E cannot be used with -a or -d");
+ }
+
if (argc > 0)
host = *argv;
else
@@ -161,7 +174,7 @@ main(int argc, char **argv)
clnt_perrno(estat);
errx(1, "can't do mountdump rpc");
}
- if (rpcs & DOEXPORTS)
+ if (rpcs & (DOEXPORTS | DOPARSABLEEXPORTS))
if ((estat = tcp_callrpc(host, MOUNTPROG, mntvers,
MOUNTPROC_EXPORT, (xdrproc_t)xdr_void, (char *)0,
(xdrproc_t)xdr_exportslist, (char *)&exportslist)) != 0) {
@@ -202,6 +215,17 @@ main(int argc, char **argv)
exp = exp->ex_next;
}
}
+ if (rpcs & DOPARSABLEEXPORTS) {
+ exp = exportslist;
+ while (exp) {
+ nbytes = strsnvis(strvised, sizeof(strvised),
+ exp->ex_dirp, VIS_GLOB | VIS_NL, "\"'$");
+ if (nbytes == -1)
+ err(1, "strsnvis");
+ printf("%s\n", strvised);
+ exp = exp->ex_next;
+ }
+ }
exit(0);
}
diff --git a/usr.bin/truss/syscalls.c b/usr.bin/truss/syscalls.c
index f5a28ae..9f291f0 100644
--- a/usr.bin/truss/syscalls.c
+++ b/usr.bin/truss/syscalls.c
@@ -70,7 +70,7 @@ __FBSDID("$FreeBSD$");
#include <unistd.h>
#include <vis.h>
-#include <compat/cloudabi/cloudabi_syscalldefs.h>
+#include <contrib/cloudabi/cloudabi_types_common.h>
#include "truss.h"
#include "extern.h"
@@ -818,7 +818,7 @@ static struct xlat cloudabi_ssflags[] = {
};
static struct xlat cloudabi_ssstate[] = {
- X(SOCKSTAT_ACCEPTCONN)
+ X(SOCKSTATE_ACCEPTCONN)
XEND
};
diff --git a/usr.bin/vtfontcvt/vtfontcvt.c b/usr.bin/vtfontcvt/vtfontcvt.c
index 4dadee7..ffe43b5 100644
--- a/usr.bin/vtfontcvt/vtfontcvt.c
+++ b/usr.bin/vtfontcvt/vtfontcvt.c
@@ -315,12 +315,13 @@ parse_hex(FILE *fp, unsigned int map_idx)
if (bytes != NULL)
errx(1, "malformed input: Width tag after font data");
set_width(atoi(ln + 9));
- } else if (sscanf(ln, "%4x:", &curchar)) {
+ } else if (sscanf(ln, "%6x:", &curchar)) {
if (bytes == NULL) {
bytes = xmalloc(wbytes * height);
bytes_r = xmalloc(wbytes * height);
}
- p = ln + 5;
+ /* ln is guaranteed to have a colon here. */
+ p = strchr(ln, ':') + 1;
chars_per_row = strlen(p) / height;
dwidth = width;
if (chars_per_row / 2 > (width + 7) / 8)
diff --git a/usr.bin/whois/whois.c b/usr.bin/whois/whois.c
index 1630067..49b2005 100644
--- a/usr.bin/whois/whois.c
+++ b/usr.bin/whois/whois.c
@@ -431,9 +431,13 @@ done:
else if ((flags & WHOIS_SPAM_ME) ||
strchr(query, ' ') != NULL)
fprintf(fp, "%s\r\n", query);
- else if (strcasecmp(hostname, ANICHOST) == 0)
- fprintf(fp, "+ %s\r\n", query);
- else if (strcasecmp(hostres->ai_canonname, VNICHOST) == 0)
+ else if (strcasecmp(hostname, ANICHOST) == 0) {
+ if (strncasecmp(query, "AS", 2) == 0 &&
+ strspn(query+2, "0123456789") == strlen(query+2))
+ fprintf(fp, "+ a %s\r\n", query+2);
+ else
+ fprintf(fp, "+ %s\r\n", query);
+ } else if (strcasecmp(hostres->ai_canonname, VNICHOST) == 0)
fprintf(fp, "domain %s\r\n", query);
else
fprintf(fp, "%s\r\n", query);
diff --git a/usr.bin/xo/Makefile b/usr.bin/xo/Makefile
index 0773987..6159169 100644
--- a/usr.bin/xo/Makefile
+++ b/usr.bin/xo/Makefile
@@ -12,7 +12,10 @@ MAN= xo.1
# XXX For xoversion.h
CFLAGS+=-I${LIBXOSRC}/libxo
-LIBADD= xo
+# XXX For xo_config.h
+CFLAGS+=-I${SRCTOP}/lib/libxo
+
+LIBADD= xo util
.if ${MK_TESTS} != "no"
SUBDIR+= tests
diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile
index 86b5247..16feb68 100644
--- a/usr.sbin/Makefile
+++ b/usr.sbin/Makefile
@@ -194,9 +194,7 @@ SUBDIR.${MK_TIMED}+= timed
SUBDIR.${MK_TOOLCHAIN}+= config
SUBDIR.${MK_TOOLCHAIN}+= crunch
SUBDIR.${MK_UNBOUND}+= unbound
-.if !(${COMPILER_TYPE} == "gcc" && ${COMPILER_VERSION} >= 50200)
SUBDIR.${MK_USB}+= uathload
-.endif
SUBDIR.${MK_USB}+= uhsoctl
SUBDIR.${MK_USB}+= usbconfig
SUBDIR.${MK_USB}+= usbdump
diff --git a/usr.sbin/autofs/log.c b/usr.sbin/autofs/log.c
index d5682cc..b3935dc 100644
--- a/usr.sbin/autofs/log.c
+++ b/usr.sbin/autofs/log.c
@@ -88,6 +88,7 @@ log_common(int priority, int log_errno, const char *fmt, va_list ap)
{
static char msgbuf[MSGBUF_LEN];
static char msgbuf_strvised[MSGBUF_LEN * 4 + 1];
+ char *errstr;
int ret;
ret = vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
@@ -121,21 +122,23 @@ log_common(int priority, int log_errno, const char *fmt, va_list ap)
}
} else {
+ errstr = strerror(log_errno);
+
if (peer_name != NULL) {
fprintf(stderr, "%s: %s (%s): %s: %s\n", getprogname(),
- peer_addr, peer_name, msgbuf_strvised, strerror(errno));
+ peer_addr, peer_name, msgbuf_strvised, errstr);
syslog(priority, "%s (%s): %s: %s",
- peer_addr, peer_name, msgbuf_strvised, strerror(errno));
+ peer_addr, peer_name, msgbuf_strvised, errstr);
} else if (peer_addr != NULL) {
fprintf(stderr, "%s: %s: %s: %s\n", getprogname(),
- peer_addr, msgbuf_strvised, strerror(errno));
+ peer_addr, msgbuf_strvised, errstr);
syslog(priority, "%s: %s: %s",
- peer_addr, msgbuf_strvised, strerror(errno));
+ peer_addr, msgbuf_strvised, errstr);
} else {
fprintf(stderr, "%s: %s: %s\n", getprogname(),
- msgbuf_strvised, strerror(errno));
+ msgbuf_strvised, errstr);
syslog(priority, "%s: %s",
- msgbuf_strvised, strerror(errno));
+ msgbuf_strvised, errstr);
}
}
}
diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c
index c6763c9..1e45bad 100644
--- a/usr.sbin/bhyve/pci_emul.c
+++ b/usr.sbin/bhyve/pci_emul.c
@@ -2054,6 +2054,7 @@ pci_emul_dior(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx,
return (0);
}
+ value = 0;
if (size == 1) {
value = sc->ioregs[offset];
} else if (size == 2) {
diff --git a/usr.sbin/bluetooth/bthidd/kbd.c b/usr.sbin/bluetooth/bthidd/kbd.c
index cd9f70b..a92a63a 100644
--- a/usr.sbin/bluetooth/bthidd/kbd.c
+++ b/usr.sbin/bluetooth/bthidd/kbd.c
@@ -514,7 +514,7 @@ int32_t
kbd_status_changed(bthid_session_p s, uint8_t *data, int32_t len)
{
vkbd_status_t st;
- uint8_t leds, report_id;
+ uint8_t found, report_id;
hid_device_p hid_device;
hid_data_t d;
hid_item_t h;
@@ -523,15 +523,21 @@ kbd_status_changed(bthid_session_p s, uint8_t *data, int32_t len)
assert(len == sizeof(vkbd_status_t));
memcpy(&st, data, sizeof(st));
- leds = 0;
+ found = 0;
report_id = NO_REPORT_ID;
hid_device = get_hid_device(&s->bdaddr);
assert(hid_device != NULL);
+ data[0] = 0xa2; /* DATA output (HID output report) */
+ data[1] = 0x00;
+ data[2] = 0x00;
+
for (d = hid_start_parse(hid_device->desc, 1 << hid_output, -1);
hid_get_item(d, &h) > 0; ) {
if (HID_PAGE(h.usage) == HUP_LEDS) {
+ found++;
+
if (report_id == NO_REPORT_ID)
report_id = h.report_ID;
else if (h.report_ID != report_id)
@@ -544,17 +550,17 @@ kbd_status_changed(bthid_session_p s, uint8_t *data, int32_t len)
switch(HID_USAGE(h.usage)) {
case 0x01: /* Num Lock LED */
if (st.leds & LED_NUM)
- hid_set_data(&leds, &h, 1);
+ hid_set_data(&data[1], &h, 1);
break;
case 0x02: /* Caps Lock LED */
if (st.leds & LED_CAP)
- hid_set_data(&leds, &h, 1);
+ hid_set_data(&data[1], &h, 1);
break;
case 0x03: /* Scroll Lock LED */
if (st.leds & LED_SCR)
- hid_set_data(&leds, &h, 1);
+ hid_set_data(&data[1], &h, 1);
break;
/* XXX add other LEDs ? */
@@ -563,18 +569,8 @@ kbd_status_changed(bthid_session_p s, uint8_t *data, int32_t len)
}
hid_end_parse(d);
- data[0] = 0xa2; /* DATA output (HID output report) */
-
- if (report_id != NO_REPORT_ID) {
- data[1] = report_id;
- data[2] = leds;
- len = 3;
- } else {
- data[1] = leds;
- len = 2;
- }
-
- write(s->intr, data, len);
+ if (found)
+ write(s->intr, data, (report_id != NO_REPORT_ID) ? 3 : 2);
return (0);
}
diff --git a/usr.sbin/bsdinstall/scripts/zfsboot b/usr.sbin/bsdinstall/scripts/zfsboot
index ed93c37..4dedbf0 100755
--- a/usr.sbin/bsdinstall/scripts/zfsboot
+++ b/usr.sbin/bsdinstall/scripts/zfsboot
@@ -302,7 +302,7 @@ msg_swap_mirror_help="Mirror swap partitions for redundancy, breaks crash dumps"
msg_swap_size="Swap Size"
msg_swap_size_help="Customize how much swap space is allocated to each selected disk"
msg_swap_toosmall="The selected swap size (%s) is to small. Please enter a value greater than 100MB or enter 0 for no swap"
-msg_these_disks_are_too_small="These disks are too small given the amount of requested\nswap (%s) and/or geli(8) (%s) partitions, which would\ntake 50%% or more of each of the following selected disk\ndevices (not recommended):\n\n %s\n\nRecommend changing partition size(s) and/or selecting a\ndifferent set of devices."
+msg_these_disks_are_too_small="These disks are smaller than the amount of requested\nswap (%s) and/or geli(8) (%s) partitions, which would\ntake 100%% or more of each of the following selected disks:\n\n %s\n\nRecommend changing partition size(s) and/or selecting a\ndifferent set of disks."
msg_unable_to_get_disk_capacity="Unable to get disk capacity of \`%s'"
msg_unsupported_partition_scheme="%s is an unsupported partition scheme"
msg_user_cancelled="User Cancelled."
@@ -1483,11 +1483,12 @@ while :; do
# NB: dialog_menu_layout supports running non-interactively
dialog_menu_layout || continue
- # Make sure each disk will be at least 50% ZFS
+ # Make sure each disk will have room for ZFS
if f_expand_number "$ZFSBOOT_SWAP_SIZE" swapsize &&
- f_expand_number "$ZFSBOOT_BOOT_POOL_SIZE" bootsize
+ f_expand_number "$ZFSBOOT_BOOT_POOL_SIZE" bootsize &&
+ f_expand_number "1g" zpoolmin
then
- minsize=$swapsize teeny_disks=
+ minsize=$(( $swapsize + $zpoolmin )) teeny_disks=
[ "$ZFSBOOT_BOOT_POOL" ] &&
minsize=$(( $minsize + $bootsize ))
for disk in $ZFSBOOT_DISKS; do
@@ -1495,7 +1496,6 @@ while :; do
$disk $DEVICE_TYPE_DISK device
$device get capacity disksize || continue
[ ${disksize:-0} -ge 0 ] || disksize=0
- disksize=$(( $disksize - $minsize ))
[ $disksize -lt $minsize ] &&
teeny_disks="$teeny_disks $disk"
done
diff --git a/usr.sbin/ctld/log.c b/usr.sbin/ctld/log.c
index ac838f3..ed66c31 100644
--- a/usr.sbin/ctld/log.c
+++ b/usr.sbin/ctld/log.c
@@ -88,6 +88,7 @@ log_common(int priority, int log_errno, const char *fmt, va_list ap)
{
static char msgbuf[MSGBUF_LEN];
static char msgbuf_strvised[MSGBUF_LEN * 4 + 1];
+ char *errstr;
int ret;
ret = vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
@@ -121,21 +122,23 @@ log_common(int priority, int log_errno, const char *fmt, va_list ap)
}
} else {
+ errstr = strerror(log_errno);
+
if (peer_name != NULL) {
fprintf(stderr, "%s: %s (%s): %s: %s\n", getprogname(),
- peer_addr, peer_name, msgbuf_strvised, strerror(errno));
+ peer_addr, peer_name, msgbuf_strvised, errstr);
syslog(priority, "%s (%s): %s: %s",
- peer_addr, peer_name, msgbuf_strvised, strerror(errno));
+ peer_addr, peer_name, msgbuf_strvised, errstr);
} else if (peer_addr != NULL) {
fprintf(stderr, "%s: %s: %s: %s\n", getprogname(),
- peer_addr, msgbuf_strvised, strerror(errno));
+ peer_addr, msgbuf_strvised, errstr);
syslog(priority, "%s: %s: %s",
- peer_addr, msgbuf_strvised, strerror(errno));
+ peer_addr, msgbuf_strvised, errstr);
} else {
fprintf(stderr, "%s: %s: %s\n", getprogname(),
- msgbuf_strvised, strerror(errno));
+ msgbuf_strvised, errstr);
syslog(priority, "%s: %s",
- msgbuf_strvised, strerror(errno));
+ msgbuf_strvised, errstr);
}
}
}
diff --git a/usr.sbin/devinfo/devinfo.c b/usr.sbin/devinfo/devinfo.c
index 40f2b0b..734d563 100644
--- a/usr.sbin/devinfo/devinfo.c
+++ b/usr.sbin/devinfo/devinfo.c
@@ -66,9 +66,9 @@ print_resource(struct devinfo_res *res)
rman = devinfo_handle_to_rman(res->dr_rman);
hexmode = (rman->dm_size > 1000) || (rman->dm_size == 0);
- printf(hexmode ? "0x%lx" : "%lu", res->dr_start);
+ printf(hexmode ? "0x%jx" : "%ju", res->dr_start);
if (res->dr_size > 1)
- printf(hexmode ? "-0x%lx" : "-%lu",
+ printf(hexmode ? "-0x%jx" : "-%ju",
res->dr_start + res->dr_size - 1);
}
diff --git a/usr.sbin/iscsid/iscsid.c b/usr.sbin/iscsid/iscsid.c
index 72828ef..5be7a44 100644
--- a/usr.sbin/iscsid/iscsid.c
+++ b/usr.sbin/iscsid/iscsid.c
@@ -290,7 +290,9 @@ void
fail(const struct connection *conn, const char *reason)
{
struct iscsi_daemon_fail idf;
- int error;
+ int error, saved_errno;
+
+ saved_errno = errno;
memset(&idf, 0, sizeof(idf));
idf.idf_session_id = conn->conn_session_id;
@@ -299,6 +301,8 @@ fail(const struct connection *conn, const char *reason)
error = ioctl(conn->conn_iscsi_fd, ISCSIDFAIL, &idf);
if (error != 0)
log_err(1, "ISCSIDFAIL");
+
+ errno = saved_errno;
}
/*
diff --git a/usr.sbin/iscsid/log.c b/usr.sbin/iscsid/log.c
index ea7755f..920c081 100644
--- a/usr.sbin/iscsid/log.c
+++ b/usr.sbin/iscsid/log.c
@@ -88,6 +88,7 @@ log_common(int priority, int log_errno, const char *fmt, va_list ap)
{
static char msgbuf[MSGBUF_LEN];
static char msgbuf_strvised[MSGBUF_LEN * 4 + 1];
+ char *errstr;
int ret;
ret = vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
@@ -121,21 +122,23 @@ log_common(int priority, int log_errno, const char *fmt, va_list ap)
}
} else {
+ errstr = strerror(log_errno);
+
if (peer_name != NULL) {
fprintf(stderr, "%s: %s (%s): %s: %s\n", getprogname(),
- peer_addr, peer_name, msgbuf_strvised, strerror(errno));
+ peer_addr, peer_name, msgbuf_strvised, errstr);
syslog(priority, "%s (%s): %s: %s",
- peer_addr, peer_name, msgbuf_strvised, strerror(errno));
+ peer_addr, peer_name, msgbuf_strvised, errstr);
} else if (peer_addr != NULL) {
fprintf(stderr, "%s: %s: %s: %s\n", getprogname(),
- peer_addr, msgbuf_strvised, strerror(errno));
+ peer_addr, msgbuf_strvised, errstr);
syslog(priority, "%s: %s: %s",
- peer_addr, msgbuf_strvised, strerror(errno));
+ peer_addr, msgbuf_strvised, errstr);
} else {
fprintf(stderr, "%s: %s: %s\n", getprogname(),
- msgbuf_strvised, strerror(errno));
+ msgbuf_strvised, errstr);
syslog(priority, "%s: %s",
- msgbuf_strvised, strerror(errno));
+ msgbuf_strvised, errstr);
}
}
}
diff --git a/usr.sbin/kbdcontrol/kbdcontrol.1 b/usr.sbin/kbdcontrol/kbdcontrol.1
index ea76b53..17e9d11 100644
--- a/usr.sbin/kbdcontrol/kbdcontrol.1
+++ b/usr.sbin/kbdcontrol/kbdcontrol.1
@@ -13,7 +13,7 @@
.\" @(#)kbdcontrol.1
.\" $FreeBSD$
.\"
-.Dd January 29, 2008
+.Dd March 16, 2016
.Dt KBDCONTROL 1
.Os
.Sh NAME
@@ -36,6 +36,7 @@
.Op Fl f Ar # Ar string
.Op Fl k Ar keyboard_device
.Op Fl L Ar keymap_file
+.Op Fl P Ar path
.Sh DESCRIPTION
The
.Nm
@@ -171,6 +172,12 @@ and write the
compiled from it to stdout.
This option is primarily intended for programmers and is probably
of little use under normal circumstances.
+.It Fl P Ar path
+Search for the keymap file in
+.Ar path .
+The
+.Fl P
+option may be specified multiple times.
.El
.Sh ENVIRONMENT
The environment variable
diff --git a/usr.sbin/kbdcontrol/kbdcontrol.c b/usr.sbin/kbdcontrol/kbdcontrol.c
index 0f927ef..f381bd7 100644
--- a/usr.sbin/kbdcontrol/kbdcontrol.c
+++ b/usr.sbin/kbdcontrol/kbdcontrol.c
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include <fcntl.h>
#include <sys/kbio.h>
#include <sys/consio.h>
+#include <sys/queue.h>
#include <sys/sysctl.h>
#include "path.h"
#include "lex.h"
@@ -112,11 +113,13 @@ static const int repeats[] = { 34, 38, 42, 46, 50, 55, 59, 63,
static const int ndelays = (sizeof(delays) / sizeof(int));
static const int nrepeats = (sizeof(repeats) / sizeof(int));
static int hex = 0;
+static int paths_configured = 0;
static int token;
int number;
char letter;
+static void add_keymap_path(const char *path);
static void dump_accent_definition(char *name, accentmap_t *accentmap);
static void dump_entry(int value);
static void dump_key_definition(char *name, keymap_t *keymap);
@@ -142,6 +145,12 @@ static void set_keyrates(char *opt);
static void show_kbd_info(void);
static void usage(void) __dead2;
+struct pathent {
+ STAILQ_ENTRY(pathent) next;
+ char *path;
+};
+static STAILQ_HEAD(, pathent) pathlist = STAILQ_HEAD_INITIALIZER(pathlist);
+
/* Detect presence of vt(4). */
static int
is_vt4(void)
@@ -279,11 +288,11 @@ get_entry(void)
}
static int
-get_definition_line(FILE *fd, keymap_t *keymap, accentmap_t *accentmap)
+get_definition_line(FILE *file, keymap_t *keymap, accentmap_t *accentmap)
{
int c;
- yyin = fd;
+ yyin = file;
if (token < 0)
token = yylex();
@@ -791,32 +800,57 @@ dump_accent_definition(char *name, accentmap_t *accentmap)
}
static void
+add_keymap_path(const char *path)
+{
+ struct pathent* pe;
+ size_t len;
+
+ len = strlen(path);
+ if ((pe = malloc(sizeof(*pe))) == NULL ||
+ (pe->path = malloc(len + 2)) == NULL)
+ err(1, "malloc");
+ memcpy(pe->path, path, len);
+ if (len > 0 && path[len - 1] != '/')
+ pe->path[len++] = '/';
+ pe->path[len] = '\0';
+ STAILQ_INSERT_TAIL(&pathlist, pe, next);
+}
+
+static void
load_keymap(char *opt, int dumponly)
{
keymap_t keymap;
accentmap_t accentmap;
- FILE *fd;
- int i, j;
+ struct pathent *pe;
+ FILE *file;
+ int j;
char *name, *cp;
char blank[] = "", keymap_path[] = KEYMAP_PATH;
char vt_keymap_path[] = VT_KEYMAP_PATH, dotkbd[] = ".kbd";
- char *prefix[] = {blank, blank, keymap_path, NULL};
char *postfix[] = {blank, dotkbd, NULL};
- if (is_vt4())
- prefix[2] = vt_keymap_path;
- cp = getenv("KEYMAP_PATH");
- if (cp != NULL)
- asprintf(&(prefix[0]), "%s/", cp);
-
- fd = NULL;
- for (i=0; prefix[i] && fd == NULL; i++) {
- for (j=0; postfix[j] && fd == NULL; j++) {
- name = mkfullname(prefix[i], opt, postfix[j]);
- fd = fopen(name, "r");
+ if (!paths_configured) {
+ cp = getenv("KEYMAP_PATH");
+ if (cp != NULL)
+ add_keymap_path(cp);
+ add_keymap_path("");
+ if (is_vt4())
+ add_keymap_path(vt_keymap_path);
+ else
+ add_keymap_path(keymap_path);
+ paths_configured = 1;
+ }
+
+ file = NULL;
+ STAILQ_FOREACH(pe, &pathlist, next) {
+ for (j=0; postfix[j] && file == NULL; j++) {
+ name = mkfullname(pe->path, opt, postfix[j]);
+ file = fopen(name, "r");
+ if (file != NULL)
+ break;
}
}
- if (fd == NULL) {
+ if (file == NULL) {
warn("keymap file \"%s\" not found", opt);
return;
}
@@ -824,7 +858,7 @@ load_keymap(char *opt, int dumponly)
memset(&accentmap, 0, sizeof(accentmap));
token = -1;
while (1) {
- if (get_definition_line(fd, &keymap, &accentmap) < 0)
+ if (get_definition_line(file, &keymap, &accentmap) < 0)
break;
}
if (dumponly) {
@@ -841,13 +875,13 @@ load_keymap(char *opt, int dumponly)
}
if ((keymap.n_keys > 0) && (ioctl(0, PIO_KEYMAP, &keymap) < 0)) {
warn("setting keymap");
- fclose(fd);
+ fclose(file);
return;
}
if ((accentmap.n_accs > 0)
&& (ioctl(0, PIO_DEADKEYMAP, &accentmap) < 0)) {
warn("setting accentmap");
- fclose(fd);
+ fclose(file);
return;
}
}
@@ -1170,7 +1204,7 @@ usage(void)
fprintf(stderr, "%s\n%s\n%s\n",
"usage: kbdcontrol [-dFKix] [-A name] [-a name] [-b duration.pitch | [quiet.]belltype]",
" [-r delay.repeat | speed] [-l mapfile] [-f # string]",
-" [-k device] [-L mapfile]");
+" [-k device] [-L mapfile] [-P path]");
exit(1);
}
@@ -1178,9 +1212,16 @@ usage(void)
int
main(int argc, char **argv)
{
+ const char *optstring = "A:a:b:df:iKk:Fl:L:P:r:x";
int opt;
- while((opt = getopt(argc, argv, "A:a:b:df:iKk:Fl:L:r:x")) != -1)
+ /* Collect any -P arguments, regardless of where they appear. */
+ while ((opt = getopt(argc, argv, optstring)) != -1)
+ if (opt == 'P')
+ add_keymap_path(optarg);
+
+ optind = optreset = 1;
+ while ((opt = getopt(argc, argv, optstring)) != -1)
switch(opt) {
case 'A':
case 'a':
@@ -1198,6 +1239,8 @@ main(int argc, char **argv)
case 'L':
load_keymap(optarg, 1);
break;
+ case 'P':
+ break;
case 'f':
set_functionkey(optarg,
nextarg(argc, argv, &optind, 'f'));
diff --git a/usr.sbin/mtest/mtest.c b/usr.sbin/mtest/mtest.c
index a28fab7..af522e2 100644
--- a/usr.sbin/mtest/mtest.c
+++ b/usr.sbin/mtest/mtest.c
@@ -396,6 +396,7 @@ process_cmd(char *cmd, int s, int s6, FILE *fp __unused)
while (isblank(*++line))
; /* Skip whitespace. */
+ n = 0;
switch (*cmd) {
case '?':
usage();
@@ -611,7 +612,6 @@ process_cmd(char *cmd, int s, int s6, FILE *fp __unused)
}
/* First determine our current filter mode. */
- n = 0;
if (getsourcefilter(af2sock(af, s, s6), ifindex,
&su.sa, su.sa.sa_len, &fmode, &n, NULL) != 0) {
warn("getsourcefilter");
diff --git a/usr.sbin/ndiscvt/ndisgen.sh b/usr.sbin/ndiscvt/ndisgen.sh
index 97e8364..1674ea1 100644
--- a/usr.sbin/ndiscvt/ndisgen.sh
+++ b/usr.sbin/ndiscvt/ndisgen.sh
@@ -432,11 +432,6 @@ fi
echo -n " Building kernel module... "
echo "" > bus_if.h
echo "" > device_if.h
-if ! ${MAKE} -f ${MAKEFILE} depend > /dev/null; then
- echo "build failed. Exiting."
- echo ""
- exit
-fi
if ! ${MAKE} -f ${MAKEFILE} all > /dev/null; then
echo "build failed. Exiting."
echo ""
diff --git a/usr.sbin/pciconf/cap.c b/usr.sbin/pciconf/cap.c
index 980e2c7..cd5ae26 100644
--- a/usr.sbin/pciconf/cap.c
+++ b/usr.sbin/pciconf/cap.c
@@ -410,14 +410,38 @@ aspm_string(uint8_t aspm)
}
}
+static int
+slot_power(uint32_t cap)
+{
+ int mwatts;
+
+ mwatts = (cap & PCIEM_SLOT_CAP_SPLV) >> 7;
+ switch (cap & PCIEM_SLOT_CAP_SPLS) {
+ case 0x0:
+ mwatts *= 1000;
+ break;
+ case 0x1:
+ mwatts *= 100;
+ break;
+ case 0x2:
+ mwatts *= 10;
+ break;
+ default:
+ break;
+ }
+ return (mwatts);
+}
+
static void
cap_express(int fd, struct pci_conf *p, uint8_t ptr)
{
- uint32_t cap, cap2;
+ uint32_t cap;
uint16_t ctl, flags, sta;
+ unsigned int version;
flags = read_config(fd, &p->pc_sel, ptr + PCIER_FLAGS, 2);
- printf("PCI-Express %d ", flags & PCIEM_FLAGS_VERSION);
+ version = flags & PCIEM_FLAGS_VERSION;
+ printf("PCI-Express %u ", version);
switch (flags & PCIEM_FLAGS_TYPE) {
case PCIEM_TYPE_ENDPOINT:
printf("endpoint");
@@ -450,12 +474,9 @@ cap_express(int fd, struct pci_conf *p, uint8_t ptr)
printf("type %d", (flags & PCIEM_FLAGS_TYPE) >> 4);
break;
}
- if (flags & PCIEM_FLAGS_SLOT)
- printf(" slot");
if (flags & PCIEM_FLAGS_IRQ)
- printf(" IRQ %d", (flags & PCIEM_FLAGS_IRQ) >> 9);
+ printf(" MSI %d", (flags & PCIEM_FLAGS_IRQ) >> 9);
cap = read_config(fd, &p->pc_sel, ptr + PCIER_DEVICE_CAP, 4);
- cap2 = read_config(fd, &p->pc_sel, ptr + PCIER_DEVICE_CAP2, 4);
ctl = read_config(fd, &p->pc_sel, ptr + PCIER_DEVICE_CTL, 2);
printf(" max data %d(%d)",
MAX_PAYLOAD((ctl & PCIEM_CTL_MAX_PAYLOAD) >> 5),
@@ -466,12 +487,22 @@ cap_express(int fd, struct pci_conf *p, uint8_t ptr)
printf(" RO");
if (ctl & PCIEM_CTL_NOSNOOP_ENABLE)
printf(" NS");
+ if (version >= 2) {
+ cap = read_config(fd, &p->pc_sel, ptr + PCIER_DEVICE_CAP2, 4);
+ if ((cap & PCIEM_CAP2_ARI) != 0) {
+ ctl = read_config(fd, &p->pc_sel,
+ ptr + PCIER_DEVICE_CTL2, 4);
+ printf(" ARI %s",
+ (ctl & PCIEM_CTL2_ARI) ? "enabled" : "disabled");
+ }
+ }
cap = read_config(fd, &p->pc_sel, ptr + PCIER_LINK_CAP, 4);
sta = read_config(fd, &p->pc_sel, ptr + PCIER_LINK_STA, 2);
+ if (cap == 0 && sta == 0)
+ return;
+ printf("\n ");
printf(" link x%d(x%d)", (sta & PCIEM_LINK_STA_WIDTH) >> 4,
(cap & PCIEM_LINK_CAP_MAX_WIDTH) >> 4);
- if ((cap & (PCIEM_LINK_CAP_MAX_WIDTH | PCIEM_LINK_CAP_ASPM)) != 0)
- printf("\n ");
if ((cap & PCIEM_LINK_CAP_MAX_WIDTH) != 0) {
printf(" speed %s(%s)", (sta & PCIEM_LINK_STA_WIDTH) == 0 ?
"0.0" : link_speed_string(sta & PCIEM_LINK_STA_SPEED),
@@ -482,11 +513,26 @@ cap_express(int fd, struct pci_conf *p, uint8_t ptr)
printf(" ASPM %s(%s)", aspm_string(ctl & PCIEM_LINK_CTL_ASPMC),
aspm_string((cap & PCIEM_LINK_CAP_ASPM) >> 10));
}
- if ((cap2 & PCIEM_CAP2_ARI) != 0) {
- ctl = read_config(fd, &p->pc_sel, ptr + PCIER_DEVICE_CTL2, 4);
- printf(" ARI %s",
- (ctl & PCIEM_CTL2_ARI) ? "enabled" : "disabled");
- }
+ if (!(flags & PCIEM_FLAGS_SLOT))
+ return;
+ cap = read_config(fd, &p->pc_sel, ptr + PCIER_SLOT_CAP, 4);
+ sta = read_config(fd, &p->pc_sel, ptr + PCIER_SLOT_STA, 2);
+ ctl = read_config(fd, &p->pc_sel, ptr + PCIER_SLOT_CTL, 2);
+ printf("\n ");
+ printf(" slot %d", (cap & PCIEM_SLOT_CAP_PSN) >> 19);
+ printf(" power limit %d mW", slot_power(cap));
+ if (cap & PCIEM_SLOT_CAP_HPC)
+ printf(" HotPlug(%s)", sta & PCIEM_SLOT_STA_PDS ? "present" :
+ "empty");
+ if (cap & PCIEM_SLOT_CAP_HPS)
+ printf(" surprise");
+ if (cap & PCIEM_SLOT_CAP_APB)
+ printf(" Attn Button");
+ if (cap & PCIEM_SLOT_CAP_PCP)
+ printf(" PC(%s)", ctl & PCIEM_SLOT_CTL_PCC ? "on" : "off");
+ if (cap & PCIEM_SLOT_CAP_MRLSP)
+ printf(" MRL(%s)", sta & PCIEM_SLOT_STA_MRLSS ? "open" :
+ "closed");
}
static void
diff --git a/usr.sbin/pw/cpdir.c b/usr.sbin/pw/cpdir.c
index 334f789..679758b 100644
--- a/usr.sbin/pw/cpdir.c
+++ b/usr.sbin/pw/cpdir.c
@@ -37,7 +37,6 @@ static const char rcsid[] =
#include <unistd.h>
#include "pw.h"
-#include "pwupd.h"
void
copymkdir(int rootfd, char const * dir, int skelfd, mode_t mode, uid_t uid,
diff --git a/usr.sbin/pw/pw.8 b/usr.sbin/pw/pw.8
index 3a9c0b0..84ceda3 100644
--- a/usr.sbin/pw/pw.8
+++ b/usr.sbin/pw/pw.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd June 14, 2015
+.Dd March 27, 2016
.Dt PW 8
.Os
.Sh NAME
@@ -420,18 +420,16 @@ Set the account's primary group to the given group.
.Ar group
may be defined by either its name or group number.
.It Fl G Ar grouplist
-Set additional group memberships for an account.
+Set secondary group memberships for an account.
.Ar grouplist
-is a comma, space or tab-separated list of group names or group numbers.
-The user's name is added to the group lists in
-.Pa /etc/group ,
-and
-removed from any groups not specified in
-.Ar grouplist .
-Note: a user should not be added to their primary group with
+is a comma, space, or tab-separated list of group names or group numbers.
+The user is added to the groups specified in
+.Ar grouplist ,
+and removed from all groups not specified.
+The current login session is not affected by group membership changes,
+which only take effect when the user reconnects.
+Note: do not add a user to their primary group with
.Ar grouplist .
-Also, group membership changes do not take effect for current user login
-sessions, requiring the user to reconnect to be affected by the changes.
.It Fl L Ar class
This option sets the login class for the user being created.
See
diff --git a/usr.sbin/pw/pw_user.c b/usr.sbin/pw/pw_user.c
index 2f87b56..5ad1409 100644
--- a/usr.sbin/pw/pw_user.c
+++ b/usr.sbin/pw/pw_user.c
@@ -31,8 +31,6 @@ static const char rcsid[] =
#endif /* not lint */
#include <sys/param.h>
-#include <sys/resource.h>
-#include <sys/time.h>
#include <sys/types.h>
#include <ctype.h>
diff --git a/usr.sbin/pw/pw_utils.c b/usr.sbin/pw/pw_utils.c
index 1a4f812..e483977 100644
--- a/usr.sbin/pw/pw_utils.c
+++ b/usr.sbin/pw/pw_utils.c
@@ -27,13 +27,10 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <sys/types.h>
#include <sys/wait.h>
#include <err.h>
-#include <inttypes.h>
#include <sysexits.h>
-#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
diff --git a/usr.sbin/pw/pw_vpw.c b/usr.sbin/pw/pw_vpw.c
index 2d1c75b..08c8bd5 100644
--- a/usr.sbin/pw/pw_vpw.c
+++ b/usr.sbin/pw/pw_vpw.c
@@ -37,7 +37,6 @@ static const char rcsid[] =
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
-#include <sys/param.h>
#include <err.h>
#include "pwupd.h"
diff --git a/usr.sbin/sesutil/eltsub.c b/usr.sbin/sesutil/eltsub.c
index 287530d..f7c4b9d 100644
--- a/usr.sbin/sesutil/eltsub.c
+++ b/usr.sbin/sesutil/eltsub.c
@@ -37,13 +37,9 @@
#include <sys/sbuf.h>
#include <err.h>
-#include <unistd.h>
#include <stddef.h>
-#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
-#include <sys/ioctl.h>
-#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_enc.h>
#include "eltsub.h"
diff --git a/usr.sbin/sesutil/sesutil.c b/usr.sbin/sesutil/sesutil.c
index 0f04c07..0bf82f4 100644
--- a/usr.sbin/sesutil/sesutil.c
+++ b/usr.sbin/sesutil/sesutil.c
@@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <unistd.h>
-#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_enc.h>
#include "eltsub.h"
diff --git a/usr.sbin/uathload/Makefile b/usr.sbin/uathload/Makefile
index 949f800..f8b26a4 100644
--- a/usr.sbin/uathload/Makefile
+++ b/usr.sbin/uathload/Makefile
@@ -3,28 +3,14 @@
PROG= uathload
MAN= uathload.8
-SRCS= uathload.c ar5523.bin
+SRCS= uathload.c
+FILES= ar5523.bin
+FILESDIR= ${SHAREDIR}/firmware
+FILESMODE= 444
CLEANFILES= ar5523.bin
-# It's hard to tag ar5523.o with the proper gnu note saying that it has a
-# non-executable stack, so ld doesn't properly mark his executable as
-# not having an executable stack. Mark it explicitly, but only for those
-# platforms that support his feature (otherwise signals don't work).
-# Note: Newer versions of ld than is in the tree ignore -z.
-.if ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "powerpc" || ${MACHINE_ARCH} == "powerpc64"
-LDFLAGS+= -Wl,-z,noexecstack
-.endif
-
-# The conversion from .bin to .o doesn't always produce a pedantically correct
-# .o's. And it doesn't matter, so turn off the mismatch warnings since it is
-# pure data. On mips64 here's no easy way to produce a proper .o.
-LDFLAGS+= -Wl,--no-warn-mismatch
-
ar5523.bin: ${.CURDIR}/../../sys/contrib/dev/uath/ar5523.bin.uu
uudecode -p ${.CURDIR}/../../sys/contrib/dev/uath/ar5523.bin.uu > ${.TARGET}
-ar5523.o: ar5523.bin
- ${LD} -b binary -d -warn-common -r -d -o ${.TARGET} ar5523.bin
-
.include <bsd.prog.mk>
diff --git a/usr.sbin/uathload/uathload.c b/usr.sbin/uathload/uathload.c
index 64ae661..50e9eb6 100644
--- a/usr.sbin/uathload/uathload.c
+++ b/usr.sbin/uathload/uathload.c
@@ -140,23 +140,19 @@ main(int argc, char *argv[])
if (argc > 1)
usage();
- if (argc == 1) {
+ if (argc == 1)
fwname = argv[0];
- fw = open(fwname, O_RDONLY, 0);
- if (fw < 0)
- err(-1, "open(%s)", fwname);
- if (fstat(fw, &sb) < 0)
- err(-1, "fstat(%s)", fwname);
- txdata = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fw, 0);
- if (txdata == MAP_FAILED)
- err(-1, "mmap(%s)", fwname);
- len = sb.st_size;
- } else {
- fwname = "ar5523.bin (builtin)";
- fw = -1;
- txdata = &_binary_ar5523_bin_start;
- len = &_binary_ar5523_bin_end - &_binary_ar5523_bin_start;
- }
+ else
+ fwname = _PATH_FIRMWARE "/ar5523.bin";
+ fw = open(fwname, O_RDONLY, 0);
+ if (fw < 0)
+ err(-1, "open(%s)", fwname);
+ if (fstat(fw, &sb) < 0)
+ err(-1, "fstat(%s)", fwname);
+ txdata = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fw, 0);
+ if (txdata == MAP_FAILED)
+ err(-1, "mmap(%s)", fwname);
+ len = sb.st_size;
/* XXX verify device is an AR5005 part */
if (getdevname(devname, msgdev, datadev))
err(-1, "getdevname error");
OpenPOWER on IntegriCloud