aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorPeter Grehan <grehan@FreeBSD.org>2011-09-15 22:14:35 +0000
committerPeter Grehan <grehan@FreeBSD.org>2011-09-15 22:14:35 +0000
commitfab4c373af4f465f03ae217f491d8cf3a3eeb26d (patch)
tree42ba64b8c25f527cf3d9b56c4ce4c51c11d445d1 /sys
parentbd2228ab3ee0cde6831fe446d793fffda2f48503 (diff)
parent3fb4fa3574e36c997c2cdcaa6f6e39a37e89f572 (diff)
Notes
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/amd64/exception.S31
-rw-r--r--sys/amd64/amd64/genassym.c1
-rw-r--r--sys/amd64/amd64/machdep.c12
-rw-r--r--sys/amd64/amd64/pmap.c82
-rw-r--r--sys/amd64/amd64/trap.c18
-rw-r--r--sys/amd64/conf/GENERIC9
-rw-r--r--sys/amd64/conf/NOTES8
-rw-r--r--sys/amd64/ia32/ia32_syscall.c2
-rw-r--r--sys/amd64/include/md_var.h1
-rw-r--r--sys/amd64/include/param.h4
-rw-r--r--sys/amd64/linux32/linux32_machdep.c3
-rw-r--r--sys/arm/arm/irq_dispatch.S4
-rw-r--r--sys/arm/arm/pmap.c86
-rw-r--r--sys/arm/at91/uart_dev_at91usart.c23
-rw-r--r--sys/arm/conf/AVILA4
-rw-r--r--sys/arm/conf/BWCT6
-rw-r--r--sys/arm/conf/CAMBRIA4
-rw-r--r--sys/arm/conf/CNS11XXNAS6
-rw-r--r--sys/arm/conf/CRB6
-rw-r--r--sys/arm/conf/DB-78XXX4
-rw-r--r--sys/arm/conf/DB-88F5XXX4
-rw-r--r--sys/arm/conf/DB-88F6XXX4
-rw-r--r--sys/arm/conf/DOCKSTAR4
-rw-r--r--sys/arm/conf/EP802196
-rw-r--r--sys/arm/conf/GUMSTIX6
-rw-r--r--sys/arm/conf/HL2008
-rw-r--r--sys/arm/conf/HL2018
-rw-r--r--sys/arm/conf/IQ312446
-rw-r--r--sys/arm/conf/KB920X8
-rw-r--r--sys/arm/conf/LN2410SBC2
-rw-r--r--sys/arm/conf/NSLU6
-rw-r--r--sys/arm/conf/QILA9G208
-rw-r--r--sys/arm/conf/SAM9G20EK8
-rw-r--r--sys/arm/conf/SHEEVAPLUG4
-rw-r--r--sys/arm/conf/SIMICS6
-rw-r--r--sys/arm/conf/TS78004
-rw-r--r--sys/arm/include/param.h2
-rw-r--r--sys/arm/sa11x0/sa11x0_irq.S2
-rw-r--r--sys/boot/common/util.c2
-rw-r--r--sys/boot/forth/loader.conf7
-rw-r--r--sys/boot/forth/loader.conf.57
-rw-r--r--sys/boot/forth/menu.4th7
-rw-r--r--sys/boot/forth/menu.4th.810
-rw-r--r--sys/boot/i386/gptboot/Makefile7
-rw-r--r--sys/boot/i386/gptzfsboot/Makefile7
-rw-r--r--sys/boot/i386/zfsboot/Makefile19
-rw-r--r--sys/boot/powerpc/ps3/Makefile3
-rw-r--r--sys/boot/powerpc/ps3/conf.c6
-rw-r--r--sys/boot/powerpc/ps3/devicename.c2
-rw-r--r--sys/boot/powerpc/ps3/lv1call.S10
-rw-r--r--sys/boot/powerpc/ps3/lv1call.h10
-rw-r--r--sys/boot/powerpc/ps3/main.c12
-rw-r--r--sys/boot/powerpc/ps3/ps3cdrom.c154
-rw-r--r--sys/boot/powerpc/ps3/ps3stor.c47
-rw-r--r--sys/boot/zfs/zfstest.c56
-rw-r--r--sys/cam/ata/ata_da.c131
-rw-r--r--sys/cam/cam_periph.c27
-rw-r--r--sys/cam/cam_xpt.c71
-rw-r--r--sys/cam/cam_xpt.h4
-rw-r--r--sys/cddl/boot/zfs/zfssubr.c2
-rw-r--r--sys/cddl/compat/opensolaris/sys/file.h11
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h1
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c2
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c14
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c22
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c29
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c51
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c41
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c103
-rw-r--r--sys/compat/freebsd32/freebsd32.h2
-rw-r--r--sys/compat/freebsd32/freebsd32_ioctl.c3
-rw-r--r--sys/compat/linprocfs/linprocfs.c29
-rw-r--r--sys/compat/linux/linux_file.c9
-rw-r--r--sys/compat/linux/linux_fork.c8
-rw-r--r--sys/compat/linux/linux_ioctl.c41
-rw-r--r--sys/compat/linux/linux_socket.c3
-rw-r--r--sys/compat/linux/linux_stats.c5
-rw-r--r--sys/compat/svr4/svr4_fcntl.c17
-rw-r--r--sys/compat/svr4/svr4_filio.c3
-rw-r--r--sys/compat/svr4/svr4_ioctl.c3
-rw-r--r--sys/compat/svr4/svr4_misc.c10
-rw-r--r--sys/compat/svr4/svr4_stream.c5
-rw-r--r--sys/conf/NOTES18
-rw-r--r--sys/conf/files1
-rw-r--r--sys/conf/files.powerpc2
-rw-r--r--sys/conf/kern.pre.mk4
-rw-r--r--sys/conf/newvers.sh2
-rw-r--r--sys/conf/options9
-rw-r--r--sys/contrib/pf/net/if_pfsync.c2
-rw-r--r--sys/contrib/pf/net/pf.c3
-rw-r--r--sys/ddb/db_break.c2
-rw-r--r--sys/dev/aac/aac_linux.c3
-rw-r--r--sys/dev/acpica/acpi.c2
-rw-r--r--sys/dev/acpica/acpi_hpet.c14
-rw-r--r--sys/dev/acpica/acpi_hpet.h2
-rw-r--r--sys/dev/acpica/acpi_pcib_acpi.c8
-rw-r--r--sys/dev/ahci/ahci.c23
-rw-r--r--sys/dev/ahci/ahci.h1
-rw-r--r--sys/dev/alc/if_alc.c26
-rw-r--r--sys/dev/amr/amr_linux.c3
-rw-r--r--sys/dev/arcmsr/arcmsr.c19
-rw-r--r--sys/dev/ata/ata-pci.c6
-rw-r--r--sys/dev/ata/ata-pci.h3
-rw-r--r--sys/dev/ata/chipsets/ata-acard.c19
-rw-r--r--sys/dev/ata/chipsets/ata-acerlabs.c25
-rw-r--r--sys/dev/ata/chipsets/ata-intel.c52
-rw-r--r--sys/dev/ata/chipsets/ata-nvidia.c24
-rw-r--r--sys/dev/ata/chipsets/ata-promise.c2
-rw-r--r--sys/dev/ath/ath_dfs/null/dfs_null.c74
-rw-r--r--sys/dev/ath/ath_hal/ah.c39
-rw-r--r--sys/dev/ath/ath_hal/ah.h46
-rw-r--r--sys/dev/ath/ath_hal/ah_desc.h6
-rw-r--r--sys/dev/ath/ath_hal/ah_eeprom.h1
-rw-r--r--sys/dev/ath/ath_hal/ah_eeprom_9287.c23
-rw-r--r--sys/dev/ath/ath_hal/ah_eeprom_v14.c6
-rw-r--r--sys/dev/ath/ath_hal/ah_eeprom_v14.h5
-rw-r--r--sys/dev/ath/ath_hal/ah_eeprom_v4k.c25
-rw-r--r--sys/dev/ath/ath_hal/ah_internal.h4
-rw-r--r--sys/dev/ath/ath_hal/ah_regdomain.c40
-rw-r--r--sys/dev/ath/ath_hal/ah_regdomain/ah_rd_ctry.h4
-rw-r--r--sys/dev/ath/ath_hal/ah_regdomain/ah_rd_regenum.h100
-rw-r--r--sys/dev/ath/ath_hal/ar5210/ar5210.h1
-rw-r--r--sys/dev/ath/ath_hal/ar5210/ar5210_attach.c1
-rw-r--r--sys/dev/ath/ath_hal/ar5210/ar5210_beacon.c11
-rw-r--r--sys/dev/ath/ath_hal/ar5211/ar5211.h1
-rw-r--r--sys/dev/ath/ath_hal/ar5211/ar5211_attach.c1
-rw-r--r--sys/dev/ath/ath_hal/ar5211/ar5211_beacon.c11
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212.h2
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212_ani.c40
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212_attach.c2
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212_beacon.c11
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212_misc.c10
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416.h6
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416.ini2
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_ani.c83
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_attach.c7
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c30
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_cal.c53
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_misc.c82
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_recv.c40
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_reset.c77
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416reg.h9
-rw-r--r--sys/dev/ath/ath_hal/ar9001/ar9160_attach.c23
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9280.c20
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9280.h3
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9280_attach.c39
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9285_attach.c2
-rw-r--r--sys/dev/ath/ath_hal/ar9002/ar9287_attach.c2
-rw-r--r--sys/dev/ath/ath_rate/sample/sample.h9
-rw-r--r--sys/dev/ath/if_ath.c179
-rw-r--r--sys/dev/ath/if_ath_sysctl.c16
-rw-r--r--sys/dev/ath/if_athdfs.h3
-rw-r--r--sys/dev/ath/if_athioctl.h31
-rw-r--r--sys/dev/ath/if_athvar.h12
-rw-r--r--sys/dev/bvm/bvm_console.c24
-rw-r--r--sys/dev/bxe/if_bxe.c2
-rw-r--r--sys/dev/cardbus/cardbus_cis.c1
-rw-r--r--sys/dev/cfe/cfe_console.c24
-rw-r--r--sys/dev/coretemp/coretemp.c221
-rw-r--r--sys/dev/dcons/dcons_os.c30
-rw-r--r--sys/dev/gem/if_gem.c2
-rw-r--r--sys/dev/hptiop/hptiop.c2
-rw-r--r--sys/dev/hwpmc/hwpmc_logging.c3
-rw-r--r--sys/dev/ichwd/ichwd.c7
-rw-r--r--sys/dev/ipmi/ipmi_linux.c3
-rw-r--r--sys/dev/iscsi/initiator/iscsi.c5
-rw-r--r--sys/dev/isp/isp.c3
-rw-r--r--sys/dev/isp/isp_freebsd.c186
-rw-r--r--sys/dev/isp/isp_freebsd.h16
-rw-r--r--sys/dev/isp/isp_pci.c80
-rw-r--r--sys/dev/isp/ispvar.h5
-rw-r--r--sys/dev/ixgbe/ixgbe.c9
-rw-r--r--sys/dev/mfi/mfi.c3
-rw-r--r--sys/dev/mfi/mfi_linux.c3
-rw-r--r--sys/dev/mii/brgphy.c18
-rw-r--r--sys/dev/mii/mii_physubr.c4
-rw-r--r--sys/dev/mmc/mmcsd.c2
-rw-r--r--sys/dev/mps/mps_sas.c2
-rw-r--r--sys/dev/mpt/mpilib/mpi_ioc.h20
-rw-r--r--sys/dev/mpt/mpt.c66
-rw-r--r--sys/dev/mpt/mpt.h16
-rw-r--r--sys/dev/mpt/mpt_cam.c105
-rw-r--r--sys/dev/mpt/mpt_debug.c43
-rw-r--r--sys/dev/mpt/mpt_pci.c10
-rw-r--r--sys/dev/mpt/mpt_raid.c72
-rw-r--r--sys/dev/mpt/mpt_raid.h21
-rw-r--r--sys/dev/mpt/mpt_user.c16
-rw-r--r--sys/dev/ofw/ofw_console.c23
-rw-r--r--sys/dev/pci/pci.c67
-rw-r--r--sys/dev/puc/pucdata.c6
-rw-r--r--sys/dev/re/if_re.c2
-rw-r--r--sys/dev/sio/sio.c37
-rw-r--r--sys/dev/smc/if_smc.c5
-rw-r--r--sys/dev/snp/snp.c3
-rw-r--r--sys/dev/sound/pci/hda/hdac.c8
-rw-r--r--sys/dev/sound/pcm/dsp.c3
-rw-r--r--sys/dev/sound/usb/uaudio.c4
-rw-r--r--sys/dev/streams/streams.c4
-rw-r--r--sys/dev/syscons/syscons.c6
-rw-r--r--sys/dev/syscons/syscons.h3
-rw-r--r--sys/dev/tdfx/tdfx_linux.c3
-rw-r--r--sys/dev/uart/uart_core.c30
-rw-r--r--sys/dev/usb/input/ums.c48
-rw-r--r--sys/dev/usb/net/uhso.c2
-rw-r--r--sys/dev/usb/quirk/usb_quirk.c25
-rw-r--r--sys/dev/usb/serial/u3g.c3
-rw-r--r--sys/dev/usb/storage/umass.c6
-rw-r--r--sys/dev/usb/usb_dev.c59
-rw-r--r--sys/dev/usb/usb_device.c123
-rw-r--r--sys/dev/usb/usb_device.h9
-rw-r--r--sys/dev/usb/usb_freebsd.h2
-rw-r--r--sys/dev/usb/usb_msctest.c135
-rw-r--r--sys/dev/usb/usb_msctest.h2
-rw-r--r--sys/dev/usb/usb_request.c16
-rw-r--r--sys/dev/usb/usbdevs4
-rw-r--r--sys/dev/usb/usbdi.h5
-rw-r--r--sys/dev/vge/if_vge.c18
-rw-r--r--sys/dev/vge/if_vgereg.h2
-rw-r--r--sys/dev/xen/console/console.c10
-rw-r--r--sys/fs/cd9660/iso.h2
-rw-r--r--sys/fs/coda/coda_psdev.c3
-rw-r--r--sys/fs/devfs/devfs_devs.c6
-rw-r--r--sys/fs/devfs/devfs_vnops.c2
-rw-r--r--sys/fs/fdescfs/fdesc_vnops.c8
-rw-r--r--sys/fs/fifofs/fifo_vnops.c2
-rw-r--r--sys/fs/msdosfs/msdosfsmount.h2
-rw-r--r--sys/fs/nfsclient/nfs_clnode.c21
-rw-r--r--sys/fs/nfsclient/nfs_clport.c10
-rw-r--r--sys/fs/nfsclient/nfs_clvnops.c2
-rw-r--r--sys/fs/nfsclient/nfsnode.h3
-rw-r--r--sys/fs/nfsserver/nfs_nfsdport.c10
-rw-r--r--sys/fs/nfsserver/nfs_nfsdserv.c43
-rw-r--r--sys/fs/ntfs/ntfs.h2
-rw-r--r--sys/fs/portalfs/portal_vfsops.c8
-rw-r--r--sys/fs/portalfs/portal_vnops.c14
-rw-r--r--sys/fs/procfs/procfs.c15
-rw-r--r--sys/fs/smbfs/smbfs.h2
-rw-r--r--sys/fs/tmpfs/tmpfs_vnops.c9
-rw-r--r--sys/gnu/fs/xfs/xfs_dfrag.c6
-rw-r--r--sys/i386/conf/GENERIC9
-rw-r--r--sys/i386/conf/XBOX6
-rw-r--r--sys/i386/conf/XEN6
-rw-r--r--sys/i386/i386/machdep.c12
-rw-r--r--sys/i386/i386/pmap.c82
-rw-r--r--sys/i386/i386/trap.c2
-rw-r--r--sys/i386/ibcs2/ibcs2_fcntl.c3
-rw-r--r--sys/i386/ibcs2/ibcs2_ioctl.c3
-rw-r--r--sys/i386/ibcs2/ibcs2_misc.c7
-rw-r--r--sys/i386/ibcs2/imgact_coff.c64
-rw-r--r--sys/i386/include/param.h2
-rw-r--r--sys/i386/linux/linux_machdep.c6
-rw-r--r--sys/i386/xen/pmap.c73
-rw-r--r--sys/ia64/ia32/ia32_trap.c2
-rw-r--r--sys/ia64/ia64/dump_machdep.c5
-rw-r--r--sys/ia64/ia64/locore.S4
-rw-r--r--sys/ia64/ia64/pmap.c106
-rw-r--r--sys/ia64/ia64/trap.c2
-rw-r--r--sys/ia64/include/param.h4
-rw-r--r--sys/kern/capabilities.conf53
-rw-r--r--sys/kern/init_main.c3
-rw-r--r--sys/kern/init_sysent.c32
-rw-r--r--sys/kern/kern_conf.c3
-rw-r--r--sys/kern/kern_descrip.c210
-rw-r--r--sys/kern/kern_event.c10
-rw-r--r--sys/kern/kern_exec.c6
-rw-r--r--sys/kern/kern_exit.c82
-rw-r--r--sys/kern/kern_fork.c96
-rw-r--r--sys/kern/kern_jail.c38
-rw-r--r--sys/kern/kern_kthread.c2
-rw-r--r--sys/kern/kern_linker.c3
-rw-r--r--sys/kern/kern_lock.c14
-rw-r--r--sys/kern/kern_proc.c11
-rw-r--r--sys/kern/kern_racct.c19
-rw-r--r--sys/kern/kern_rctl.c15
-rw-r--r--sys/kern/kern_resource.c40
-rw-r--r--sys/kern/kern_shutdown.c44
-rw-r--r--sys/kern/kern_sig.c31
-rw-r--r--sys/kern/kern_timeout.c7
-rw-r--r--sys/kern/sched_4bsd.c4
-rw-r--r--sys/kern/sched_ule.c6
-rw-r--r--sys/kern/subr_kdb.c97
-rw-r--r--sys/kern/subr_pcpu.c3
-rw-r--r--sys/kern/subr_sbuf.c2
-rw-r--r--sys/kern/subr_smp.c54
-rw-r--r--sys/kern/subr_syscall.c213
-rw-r--r--sys/kern/subr_taskqueue.c4
-rw-r--r--sys/kern/subr_trap.c162
-rw-r--r--sys/kern/sys_capability.c68
-rw-r--r--sys/kern/sys_generic.c85
-rw-r--r--sys/kern/sys_pipe.c3
-rw-r--r--sys/kern/sys_procdesc.c524
-rw-r--r--sys/kern/sys_socket.c2
-rw-r--r--sys/kern/syscalls.c10
-rw-r--r--sys/kern/syscalls.master8
-rw-r--r--sys/kern/systrace_args.c63
-rw-r--r--sys/kern/tty.c17
-rw-r--r--sys/kern/tty_pts.c4
-rw-r--r--sys/kern/uipc_mqueue.c79
-rw-r--r--sys/kern/uipc_sem.c85
-rw-r--r--sys/kern/uipc_shm.c106
-rw-r--r--sys/kern/uipc_sockbuf.c2
-rw-r--r--sys/kern/uipc_socket.c2
-rw-r--r--sys/kern/uipc_syscalls.c96
-rw-r--r--sys/kern/uipc_usrreq.c7
-rw-r--r--sys/kern/vfs_acl.c11
-rw-r--r--sys/kern/vfs_aio.c29
-rw-r--r--sys/kern/vfs_bio.c2
-rw-r--r--sys/kern/vfs_extattr.c10
-rw-r--r--sys/kern/vfs_init.c45
-rw-r--r--sys/kern/vfs_lookup.c40
-rw-r--r--sys/kern/vfs_mount.c3
-rw-r--r--sys/kern/vfs_subr.c4
-rw-r--r--sys/kern/vfs_syscalls.c279
-rw-r--r--sys/kern/vfs_vnops.c56
-rw-r--r--sys/mips/cavium/asm_octeon.S4
-rw-r--r--sys/mips/cavium/octeon_mp.c34
-rw-r--r--sys/mips/conf/OCTEON12
-rw-r--r--sys/mips/conf/XLP2
-rw-r--r--sys/mips/conf/XLP644
-rw-r--r--sys/mips/conf/XLPN322
-rw-r--r--sys/mips/include/param.h2
-rw-r--r--sys/mips/mips/dump_machdep.c2
-rw-r--r--sys/mips/mips/exception.S12
-rw-r--r--sys/mips/mips/pmap.c79
-rw-r--r--sys/mips/nlm/board.c3
-rw-r--r--sys/mips/nlm/board.h3
-rw-r--r--sys/mips/nlm/bus_space_rmi.c8
-rw-r--r--sys/mips/nlm/bus_space_rmi_pci.c768
-rw-r--r--sys/mips/nlm/clock.h3
-rw-r--r--sys/mips/nlm/cms.c166
-rw-r--r--sys/mips/nlm/files.xlp11
-rw-r--r--sys/mips/nlm/hal/bridge.h271
-rw-r--r--sys/mips/nlm/hal/cop0.h280
-rw-r--r--sys/mips/nlm/hal/cop2.h236
-rw-r--r--sys/mips/nlm/hal/cpucontrol.h186
-rw-r--r--sys/mips/nlm/hal/fmn.c336
-rw-r--r--sys/mips/nlm/hal/fmn.h233
-rw-r--r--sys/mips/nlm/hal/haldefs.h437
-rw-r--r--sys/mips/nlm/hal/iomap.h239
-rw-r--r--sys/mips/nlm/hal/mips-extns.h242
-rw-r--r--sys/mips/nlm/hal/mmio.h338
-rw-r--r--sys/mips/nlm/hal/mmu.h147
-rw-r--r--sys/mips/nlm/hal/pcibus.h89
-rw-r--r--sys/mips/nlm/hal/pic.h609
-rw-r--r--sys/mips/nlm/hal/sys.h168
-rw-r--r--sys/mips/nlm/hal/uart.h166
-rw-r--r--sys/mips/nlm/hal/usb.h59
-rw-r--r--sys/mips/nlm/intern_dev.c86
-rw-r--r--sys/mips/nlm/interrupt.h3
-rw-r--r--sys/mips/nlm/intr_machdep.c4
-rw-r--r--sys/mips/nlm/iodi.c233
-rw-r--r--sys/mips/nlm/mpreset.S9
-rw-r--r--sys/mips/nlm/msgring.h5
-rw-r--r--sys/mips/nlm/uart_bus_xlp_iodi.c6
-rw-r--r--sys/mips/nlm/uart_cpu_xlp.c (renamed from sys/mips/nlm/uart_cpu_mips_xlp.c)34
-rw-r--r--sys/mips/nlm/uart_pci_xlp.c85
-rw-r--r--sys/mips/nlm/usb_init.c92
-rw-r--r--sys/mips/nlm/xlp.h114
-rw-r--r--sys/mips/nlm/xlp_machdep.c59
-rw-r--r--sys/mips/nlm/xlp_pci.c666
-rw-r--r--sys/modules/Makefile3
-rw-r--r--sys/modules/dcons/Makefile5
-rw-r--r--sys/modules/ipfw/Makefile2
-rw-r--r--sys/modules/netgraph/ipfw/Makefile16
-rw-r--r--sys/modules/portalfs/Makefile3
-rw-r--r--sys/modules/sio/Makefile2
-rw-r--r--sys/net/bpf.c2
-rw-r--r--sys/net/if_bridge.c28
-rw-r--r--sys/net/if_ethersubr.c1
-rw-r--r--sys/net/if_lagg.c1
-rw-r--r--sys/net/if_tap.c1
-rw-r--r--sys/net/if_tun.c1
-rw-r--r--sys/net/radix_mpath.c5
-rw-r--r--sys/net/route.c2
-rw-r--r--sys/net80211/ieee80211_ht.c10
-rw-r--r--sys/net80211/ieee80211_output.c8
-rw-r--r--sys/net80211/ieee80211_proto.c17
-rw-r--r--sys/net80211/ieee80211_scan_sta.c10
-rw-r--r--sys/netgraph/ng_ether.c3
-rw-r--r--sys/netgraph/ng_ipfw.c54
-rw-r--r--sys/netgraph/ng_mppc.c3
-rw-r--r--sys/netgraph/ng_parse.c12
-rw-r--r--sys/netgraph/ng_socket.c2
-rw-r--r--sys/netinet/in.c5
-rw-r--r--sys/netinet/ip_divert.c1
-rw-r--r--sys/netinet/ip_fw.h10
-rw-r--r--sys/netinet/ipfw/ip_fw2.c67
-rw-r--r--sys/netinet/ipfw/ip_fw_dynamic.c2
-rw-r--r--sys/netinet/ipfw/ip_fw_log.c26
-rw-r--r--sys/netinet/ipfw/ip_fw_pfil.c39
-rw-r--r--sys/netinet/ipfw/ip_fw_private.h1
-rw-r--r--sys/netinet/ipfw/ip_fw_sockopt.c13
-rw-r--r--sys/netinet/ipfw/ip_fw_table.c2
-rw-r--r--sys/netinet/sctp.h22
-rw-r--r--sys/netinet/sctp_asconf.c63
-rw-r--r--sys/netinet/sctp_cc_functions.c361
-rw-r--r--sys/netinet/sctp_constants.h30
-rw-r--r--sys/netinet/sctp_header.h3
-rw-r--r--sys/netinet/sctp_indata.c175
-rw-r--r--sys/netinet/sctp_input.c96
-rw-r--r--sys/netinet/sctp_output.c593
-rw-r--r--sys/netinet/sctp_output.h2
-rw-r--r--sys/netinet/sctp_pcb.c123
-rw-r--r--sys/netinet/sctp_pcb.h8
-rw-r--r--sys/netinet/sctp_structs.h30
-rw-r--r--sys/netinet/sctp_sysctl.c37
-rw-r--r--sys/netinet/sctp_sysctl.h28
-rw-r--r--sys/netinet/sctp_timer.c386
-rw-r--r--sys/netinet/sctp_timer.h6
-rw-r--r--sys/netinet/sctp_uio.h35
-rw-r--r--sys/netinet/sctp_usrreq.c742
-rw-r--r--sys/netinet/sctp_var.h5
-rw-r--r--sys/netinet/sctputil.c265
-rw-r--r--sys/netinet/tcp_input.c78
-rw-r--r--sys/netinet/tcp_output.c2
-rw-r--r--sys/netinet/udp_usrreq.c60
-rw-r--r--sys/netinet6/in6.c21
-rw-r--r--sys/netinet6/in6.h5
-rw-r--r--sys/netinet6/in6_proto.c5
-rw-r--r--sys/netinet6/ip6_forward.c70
-rw-r--r--sys/netinet6/ip6_input.c31
-rw-r--r--sys/netinet6/ip6_output.c36
-rw-r--r--sys/netinet6/ip6_var.h3
-rw-r--r--sys/netinet6/mld6.c11
-rw-r--r--sys/netinet6/nd6_rtr.c10
-rw-r--r--sys/netinet6/sctp6_usrreq.c27
-rw-r--r--sys/netinet6/udp6_usrreq.c44
-rw-r--r--sys/nfsclient/nfs_bio.c8
-rw-r--r--sys/nfsclient/nfs_node.c21
-rw-r--r--sys/nfsclient/nfs_vfsops.c5
-rw-r--r--sys/nfsclient/nfs_vnops.c8
-rw-r--r--sys/nfsclient/nfsnode.h2
-rw-r--r--sys/nfsserver/nfs_serv.c1
-rw-r--r--sys/nfsserver/nfs_srvkrpc.c3
-rw-r--r--sys/ofed/include/linux/linux_compat.c4
-rw-r--r--sys/opencrypto/cryptodev.c4
-rw-r--r--sys/pc98/cbus/sio.c29
-rw-r--r--sys/pc98/conf/GENERIC4
-rw-r--r--sys/pc98/pc98/machdep.c12
-rw-r--r--sys/pci/if_rlreg.h1
-rw-r--r--sys/powerpc/aim/locore32.S4
-rw-r--r--sys/powerpc/aim/locore64.S4
-rw-r--r--sys/powerpc/aim/mmu_oea.c61
-rw-r--r--sys/powerpc/aim/mmu_oea64.c59
-rw-r--r--sys/powerpc/aim/trap.c2
-rw-r--r--sys/powerpc/booke/locore.S32
-rw-r--r--sys/powerpc/booke/platform_bare.c13
-rw-r--r--sys/powerpc/booke/pmap.c266
-rw-r--r--sys/powerpc/booke/trap.c2
-rw-r--r--sys/powerpc/conf/MPC85XX2
-rw-r--r--sys/powerpc/include/param.h2
-rw-r--r--sys/powerpc/include/pmap.h2
-rw-r--r--sys/powerpc/mambo/mambo_console.c24
-rw-r--r--sys/powerpc/mpc85xx/atpic.c4
-rw-r--r--sys/powerpc/powermac/fcu.c12
-rw-r--r--sys/powerpc/powerpc/mmu_if.m2
-rw-r--r--sys/powerpc/ps3/ps3cdrom.c703
-rw-r--r--sys/rpc/clnt_dg.c7
-rw-r--r--sys/security/audit/audit_arg.c2
-rw-r--r--sys/security/audit/audit_pipe.c1
-rw-r--r--sys/security/mac/mac_framework.h14
-rw-r--r--sys/security/mac/mac_policy.h24
-rw-r--r--sys/security/mac/mac_posix_sem.c32
-rw-r--r--sys/security/mac/mac_posix_shm.c59
-rw-r--r--sys/security/mac/mac_syscalls.c5
-rw-r--r--sys/security/mac_biba/mac_biba.c204
-rw-r--r--sys/security/mac_mls/mac_mls.c207
-rw-r--r--sys/security/mac_stub/mac_stub.c48
-rw-r--r--sys/security/mac_test/mac_test.c66
-rw-r--r--sys/sparc64/conf/GENERIC4
-rw-r--r--sys/sparc64/include/param.h4
-rw-r--r--sys/sparc64/sbus/sbus.c4
-rw-r--r--sys/sparc64/sparc64/dump_machdep.c9
-rw-r--r--sys/sparc64/sparc64/exception.S4
-rw-r--r--sys/sparc64/sparc64/mp_machdep.c8
-rw-r--r--sys/sparc64/sparc64/pmap.c71
-rw-r--r--sys/sparc64/sparc64/trap.c2
-rw-r--r--sys/sparc64/sparc64/tsb.c2
-rw-r--r--sys/sys/buf.h6
-rw-r--r--sys/sys/bus.h14
-rw-r--r--sys/sys/capability.h84
-rw-r--r--sys/sys/file.h51
-rw-r--r--sys/sys/filedesc.h3
-rw-r--r--sys/sys/kdb.h2
-rw-r--r--sys/sys/mount.h76
-rw-r--r--sys/sys/namei.h18
-rw-r--r--sys/sys/param.h2
-rw-r--r--sys/sys/pcpu.h7
-rw-r--r--sys/sys/proc.h9
-rw-r--r--sys/sys/procdesc.h119
-rw-r--r--sys/sys/resourcevar.h1
-rw-r--r--sys/sys/selinfo.h1
-rw-r--r--sys/sys/sockbuf.h2
-rw-r--r--sys/sys/syscall.h5
-rw-r--r--sys/sys/syscall.mk5
-rw-r--r--sys/sys/sysproto.h20
-rw-r--r--sys/sys/systm.h4
-rw-r--r--sys/sys/unistd.h5
-rw-r--r--sys/sys/user.h19
-rw-r--r--sys/sys/vnode.h11
-rw-r--r--sys/ufs/ffs/ffs_alloc.c19
-rw-r--r--sys/ufs/ffs/ffs_extern.h1
-rw-r--r--sys/ufs/ffs/ffs_inode.c14
-rw-r--r--sys/ufs/ffs/ffs_softdep.c47
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c12
-rw-r--r--sys/ufs/ffs/ffs_vnops.c3
-rw-r--r--sys/ufs/ufs/inode.h8
-rw-r--r--sys/ufs/ufs/ufs_extattr.c4
-rw-r--r--sys/vm/device_pager.c11
-rw-r--r--sys/vm/swap_pager.c129
-rw-r--r--sys/vm/swap_pager.h3
-rw-r--r--sys/vm/vm_contig.c1
-rw-r--r--sys/vm/vm_fault.c4
-rw-r--r--sys/vm/vm_kern.c4
-rw-r--r--sys/vm/vm_mmap.c34
-rw-r--r--sys/vm/vm_object.c8
-rw-r--r--sys/vm/vm_page.c148
-rw-r--r--sys/vm/vm_page.h55
-rw-r--r--sys/vm/vm_pageout.c28
-rw-r--r--sys/vm/vnode_pager.c2
-rw-r--r--sys/x86/acpica/acpi_apm.c1
-rw-r--r--sys/x86/x86/tsc.c11
522 files changed, 14263 insertions, 7187 deletions
diff --git a/sys/amd64/amd64/exception.S b/sys/amd64/amd64/exception.S
index c537a4f45c832..89ad638c7e3fc 100644
--- a/sys/amd64/amd64/exception.S
+++ b/sys/amd64/amd64/exception.S
@@ -380,8 +380,11 @@ IDTVEC(fast_syscall)
movl $TF_HASSEGS,TF_FLAGS(%rsp)
cld
FAKE_MCOUNT(TF_RIP(%rsp))
- movq %rsp,%rdi
- call syscall
+ movq PCPU(CURTHREAD),%rdi
+ movq %rsp,TD_FRAME(%rdi)
+ movl TF_RFLAGS(%rsp),%esi
+ andl $PSL_T,%esi
+ call amd64_syscall
1: movq PCPU(CURPCB),%rax
/* Disable interrupts before testing PCB_FULL_IRET. */
cli
@@ -390,29 +393,25 @@ IDTVEC(fast_syscall)
/* Check for and handle AST's on return to userland. */
movq PCPU(CURTHREAD),%rax
testl $TDF_ASTPENDING | TDF_NEEDRESCHED,TD_FLAGS(%rax)
- je 2f
- sti
- movq %rsp, %rdi
- call ast
- jmp 1b
-2: /* Restore preserved registers. */
+ jne 2f
+ /* Restore preserved registers. */
MEXITCOUNT
movq TF_RDI(%rsp),%rdi /* bonus; preserve arg 1 */
movq TF_RSI(%rsp),%rsi /* bonus: preserve arg 2 */
movq TF_RDX(%rsp),%rdx /* return value 2 */
movq TF_RAX(%rsp),%rax /* return value 1 */
- movq TF_RBX(%rsp),%rbx /* C preserved */
- movq TF_RBP(%rsp),%rbp /* C preserved */
- movq TF_R12(%rsp),%r12 /* C preserved */
- movq TF_R13(%rsp),%r13 /* C preserved */
- movq TF_R14(%rsp),%r14 /* C preserved */
- movq TF_R15(%rsp),%r15 /* C preserved */
movq TF_RFLAGS(%rsp),%r11 /* original %rflags */
movq TF_RIP(%rsp),%rcx /* original %rip */
- movq TF_RSP(%rsp),%r9 /* user stack pointer */
- movq %r9,%rsp /* original %rsp */
+ movq TF_RSP(%rsp),%rsp /* user stack pointer */
swapgs
sysretq
+
+2: /* AST scheduled. */
+ sti
+ movq %rsp,%rdi
+ call ast
+ jmp 1b
+
3: /* Requested full context restore, use doreti for that. */
MEXITCOUNT
jmp doreti
diff --git a/sys/amd64/amd64/genassym.c b/sys/amd64/amd64/genassym.c
index 1c9abd5ab1b1d..d133223ffb237 100644
--- a/sys/amd64/amd64/genassym.c
+++ b/sys/amd64/amd64/genassym.c
@@ -87,6 +87,7 @@ ASSYM(TD_PCB, offsetof(struct thread, td_pcb));
ASSYM(TD_PFLAGS, offsetof(struct thread, td_pflags));
ASSYM(TD_PROC, offsetof(struct thread, td_proc));
ASSYM(TD_TID, offsetof(struct thread, td_tid));
+ASSYM(TD_FRAME, offsetof(struct thread, td_frame));
ASSYM(TDF_ASTPENDING, TDF_ASTPENDING);
ASSYM(TDF_NEEDRESCHED, TDF_NEEDRESCHED);
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index f90ad03a59170..1e7b26c081f43 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -1309,7 +1309,7 @@ getmemsize(caddr_t kmdp, u_int64_t first)
{
int i, physmap_idx, pa_indx, da_indx;
vm_paddr_t pa, physmap[PHYSMAP_SIZE];
- u_long physmem_tunable;
+ u_long physmem_tunable, memtest;
pt_entry_t *pte;
struct bios_smap *smapbase, *smap, *smapend;
u_int32_t smapsize;
@@ -1372,6 +1372,13 @@ getmemsize(caddr_t kmdp, u_int64_t first)
Maxmem = atop(physmem_tunable);
/*
+ * By default keep the memtest enabled. Use a general name so that
+ * one could eventually do more with the code than just disable it.
+ */
+ memtest = 1;
+ TUNABLE_ULONG_FETCH("hw.memtest.tests", &memtest);
+
+ /*
* Don't allow MAXMEM or hw.physmem to extend the amount of memory
* in the system.
*/
@@ -1433,6 +1440,8 @@ getmemsize(caddr_t kmdp, u_int64_t first)
goto do_dump_avail;
page_bad = FALSE;
+ if (memtest == 0)
+ goto skip_memtest;
/*
* map page into kernel: valid, read/write,non-cacheable
@@ -1470,6 +1479,7 @@ getmemsize(caddr_t kmdp, u_int64_t first)
*/
*(int *)ptr = tmp;
+skip_memtest:
/*
* Adjust array of valid/good pages.
*/
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index bed795b974762..43df8ee15baa9 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -2123,7 +2123,7 @@ pmap_collect(pmap_t locked_pmap, struct vpgqueues *vpq)
KASSERT((tpte & PG_W) == 0,
("pmap_collect: wired pte %#lx", tpte));
if (tpte & PG_A)
- vm_page_flag_set(m, PG_REFERENCED);
+ vm_page_aflag_set(m, PGA_REFERENCED);
if ((tpte & (PG_M | PG_RW)) == (PG_M | PG_RW))
vm_page_dirty(m);
free = NULL;
@@ -2137,7 +2137,7 @@ pmap_collect(pmap_t locked_pmap, struct vpgqueues *vpq)
}
if (TAILQ_EMPTY(&m->md.pv_list) &&
TAILQ_EMPTY(&pa_to_pvh(VM_PAGE_TO_PHYS(m))->pv_list))
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
}
}
@@ -2320,7 +2320,7 @@ pmap_pv_demote_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa)
va_last = va + NBPDR - PAGE_SIZE;
do {
m++;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_pv_demote_pde: page %p is not managed", m));
va += PAGE_SIZE;
pmap_insert_entry(pmap, va, m);
@@ -2391,7 +2391,7 @@ pmap_remove_entry(pmap_t pmap, vm_page_t m, vm_offset_t va)
if (TAILQ_EMPTY(&m->md.pv_list)) {
pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
if (TAILQ_EMPTY(&pvh->pv_list))
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
}
}
@@ -2615,10 +2615,10 @@ pmap_remove_pde(pmap_t pmap, pd_entry_t *pdq, vm_offset_t sva,
if ((oldpde & (PG_M | PG_RW)) == (PG_M | PG_RW))
vm_page_dirty(m);
if (oldpde & PG_A)
- vm_page_flag_set(m, PG_REFERENCED);
+ vm_page_aflag_set(m, PGA_REFERENCED);
if (TAILQ_EMPTY(&m->md.pv_list) &&
TAILQ_EMPTY(&pvh->pv_list))
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
}
}
if (pmap == kernel_pmap) {
@@ -2659,7 +2659,7 @@ pmap_remove_pte(pmap_t pmap, pt_entry_t *ptq, vm_offset_t va,
if ((oldpte & (PG_M | PG_RW)) == (PG_M | PG_RW))
vm_page_dirty(m);
if (oldpte & PG_A)
- vm_page_flag_set(m, PG_REFERENCED);
+ vm_page_aflag_set(m, PGA_REFERENCED);
pmap_remove_entry(pmap, m, va);
}
return (pmap_unuse_pt(pmap, va, ptepde, free));
@@ -2847,7 +2847,7 @@ pmap_remove_all(vm_page_t m)
vm_offset_t va;
vm_page_t free;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_remove_all: page %p is not managed", m));
free = NULL;
vm_page_lock_queues();
@@ -2872,7 +2872,7 @@ pmap_remove_all(vm_page_t m)
if (tpte & PG_W)
pmap->pm_stats.wired_count--;
if (tpte & PG_A)
- vm_page_flag_set(m, PG_REFERENCED);
+ vm_page_aflag_set(m, PGA_REFERENCED);
/*
* Update the vm_page_t clean and reference bits.
@@ -2885,7 +2885,7 @@ pmap_remove_all(vm_page_t m)
free_pv_entry(pmap, pv);
PMAP_UNLOCK(pmap);
}
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
vm_page_unlock_queues();
pmap_free_zero_pages(free);
}
@@ -3194,8 +3194,8 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_prot_t access, vm_page_t m,
KASSERT(va < UPT_MIN_ADDRESS || va >= UPT_MAX_ADDRESS,
("pmap_enter: invalid to pmap_enter page table pages (va: 0x%lx)",
va));
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0 ||
- (m->oflags & VPO_BUSY) != 0,
+ KASSERT((m->oflags & (VPO_UNMANAGED | VPO_BUSY)) != 0 ||
+ VM_OBJECT_LOCKED(m->object),
("pmap_enter: page %p is not busy", m));
mpte = NULL;
@@ -3276,7 +3276,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_prot_t access, vm_page_t m,
/*
* Enter on the PV list if part of our managed memory.
*/
- if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0) {
+ if ((m->oflags & VPO_UNMANAGED) == 0) {
KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva,
("pmap_enter: managed mapping within the clean submap"));
if (pv == NULL)
@@ -3301,7 +3301,7 @@ validate:
if ((prot & VM_PROT_WRITE) != 0) {
newpte |= PG_RW;
if ((newpte & PG_MANAGED) != 0)
- vm_page_flag_set(m, PG_WRITEABLE);
+ vm_page_aflag_set(m, PGA_WRITEABLE);
}
if ((prot & VM_PROT_EXECUTE) == 0)
newpte |= pg_nx;
@@ -3325,7 +3325,7 @@ validate:
origpte = pte_load_store(pte, newpte);
if (origpte & PG_A) {
if (origpte & PG_MANAGED)
- vm_page_flag_set(om, PG_REFERENCED);
+ vm_page_aflag_set(om, PGA_REFERENCED);
if (opa != VM_PAGE_TO_PHYS(m) || ((origpte &
PG_NX) == 0 && (newpte & PG_NX)))
invlva = TRUE;
@@ -3339,7 +3339,7 @@ validate:
if ((origpte & PG_MANAGED) != 0 &&
TAILQ_EMPTY(&om->md.pv_list) &&
TAILQ_EMPTY(&pa_to_pvh(opa)->pv_list))
- vm_page_flag_clear(om, PG_WRITEABLE);
+ vm_page_aflag_clear(om, PGA_WRITEABLE);
if (invlva)
pmap_invalidate_page(pmap, va);
} else
@@ -3389,7 +3389,7 @@ pmap_enter_pde(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot)
}
newpde = VM_PAGE_TO_PHYS(m) | pmap_cache_bits(m->md.pat_mode, 1) |
PG_PS | PG_V;
- if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0) {
+ if ((m->oflags & VPO_UNMANAGED) == 0) {
newpde |= PG_MANAGED;
/*
@@ -3498,7 +3498,7 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m,
vm_paddr_t pa;
KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva ||
- (m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0,
+ (m->oflags & VPO_UNMANAGED) != 0,
("pmap_enter_quick_locked: managed mapping within the clean submap"));
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
PMAP_LOCK_ASSERT(pmap, MA_OWNED);
@@ -3556,7 +3556,7 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m,
/*
* Enter on the PV list if part of our managed memory.
*/
- if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0 &&
+ if ((m->oflags & VPO_UNMANAGED) == 0 &&
!pmap_try_insert_pv_entry(pmap, va, m)) {
if (mpte != NULL) {
free = NULL;
@@ -3581,7 +3581,7 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m,
/*
* Now validate mapping with RO protection
*/
- if (m->flags & (PG_FICTITIOUS|PG_UNMANAGED))
+ if ((m->oflags & VPO_UNMANAGED) != 0)
pte_store(pte, pa | PG_V | PG_U);
else
pte_store(pte, pa | PG_V | PG_U | PG_MANAGED);
@@ -3958,7 +3958,7 @@ pmap_page_exists_quick(pmap_t pmap, vm_page_t m)
int loops = 0;
boolean_t rv;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_page_exists_quick: page %p is not managed", m));
rv = FALSE;
vm_page_lock_queues();
@@ -3999,7 +3999,7 @@ pmap_page_wired_mappings(vm_page_t m)
int count;
count = 0;
- if ((m->flags & PG_FICTITIOUS) != 0)
+ if ((m->oflags & VPO_UNMANAGED) != 0)
return (count);
vm_page_lock_queues();
count = pmap_pvh_wired_mappings(&m->md, count);
@@ -4041,7 +4041,7 @@ pmap_page_is_mapped(vm_page_t m)
{
boolean_t rv;
- if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0)
+ if ((m->oflags & VPO_UNMANAGED) != 0)
return (FALSE);
vm_page_lock_queues();
rv = !TAILQ_EMPTY(&m->md.pv_list) ||
@@ -4147,7 +4147,7 @@ pmap_remove_pages(pmap_t pmap)
if (TAILQ_EMPTY(&pvh->pv_list)) {
for (mt = m; mt < &m[NBPDR / PAGE_SIZE]; mt++)
if (TAILQ_EMPTY(&mt->md.pv_list))
- vm_page_flag_clear(mt, PG_WRITEABLE);
+ vm_page_aflag_clear(mt, PGA_WRITEABLE);
}
mpte = pmap_lookup_pt_page(pmap, pv->pv_va);
if (mpte != NULL) {
@@ -4165,7 +4165,7 @@ pmap_remove_pages(pmap_t pmap)
if (TAILQ_EMPTY(&m->md.pv_list)) {
pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
if (TAILQ_EMPTY(&pvh->pv_list))
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
}
}
pmap_unuse_pt(pmap, pv->pv_va, ptepde, &free);
@@ -4199,17 +4199,17 @@ pmap_is_modified(vm_page_t m)
{
boolean_t rv;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_is_modified: page %p is not managed", m));
/*
- * If the page is not VPO_BUSY, then PG_WRITEABLE cannot be
- * concurrently set while the object is locked. Thus, if PG_WRITEABLE
+ * If the page is not VPO_BUSY, then PGA_WRITEABLE cannot be
+ * concurrently set while the object is locked. Thus, if PGA_WRITEABLE
* is clear, no PTEs can have PG_M set.
*/
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
if ((m->oflags & VPO_BUSY) == 0 &&
- (m->flags & PG_WRITEABLE) == 0)
+ (m->aflags & PGA_WRITEABLE) == 0)
return (FALSE);
vm_page_lock_queues();
rv = pmap_is_modified_pvh(&m->md) ||
@@ -4280,7 +4280,7 @@ pmap_is_referenced(vm_page_t m)
{
boolean_t rv;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_is_referenced: page %p is not managed", m));
vm_page_lock_queues();
rv = pmap_is_referenced_pvh(&m->md) ||
@@ -4328,17 +4328,17 @@ pmap_remove_write(vm_page_t m)
pt_entry_t oldpte, *pte;
vm_offset_t va;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_remove_write: page %p is not managed", m));
/*
- * If the page is not VPO_BUSY, then PG_WRITEABLE cannot be set by
- * another thread while the object is locked. Thus, if PG_WRITEABLE
+ * If the page is not VPO_BUSY, then PGA_WRITEABLE cannot be set by
+ * another thread while the object is locked. Thus, if PGA_WRITEABLE
* is clear, no page table entries need updating.
*/
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
if ((m->oflags & VPO_BUSY) == 0 &&
- (m->flags & PG_WRITEABLE) == 0)
+ (m->aflags & PGA_WRITEABLE) == 0)
return;
vm_page_lock_queues();
pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
@@ -4370,7 +4370,7 @@ retry:
}
PMAP_UNLOCK(pmap);
}
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
vm_page_unlock_queues();
}
@@ -4397,7 +4397,7 @@ pmap_ts_referenced(vm_page_t m)
vm_offset_t va;
int rtval = 0;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_ts_referenced: page %p is not managed", m));
pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
vm_page_lock_queues();
@@ -4471,18 +4471,18 @@ pmap_clear_modify(vm_page_t m)
pt_entry_t oldpte, *pte;
vm_offset_t va;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_clear_modify: page %p is not managed", m));
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
KASSERT((m->oflags & VPO_BUSY) == 0,
("pmap_clear_modify: page %p is busy", m));
/*
- * If the page is not PG_WRITEABLE, then no PTEs can have PG_M set.
+ * If the page is not PGA_WRITEABLE, then no PTEs can have PG_M set.
* If the object containing the page is locked and the page is not
- * VPO_BUSY, then PG_WRITEABLE cannot be concurrently set.
+ * VPO_BUSY, then PGA_WRITEABLE cannot be concurrently set.
*/
- if ((m->flags & PG_WRITEABLE) == 0)
+ if ((m->aflags & PGA_WRITEABLE) == 0)
return;
vm_page_lock_queues();
pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
@@ -4548,7 +4548,7 @@ pmap_clear_reference(vm_page_t m)
pt_entry_t *pte;
vm_offset_t va;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_clear_reference: page %p is not managed", m));
vm_page_lock_queues();
pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
index 4e5f8b8aa9f50..16f151fce3ef1 100644
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -883,41 +883,37 @@ cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
return (error);
}
+#include "../../kern/subr_syscall.c"
+
/*
* syscall - system call request C handler
*
* A system call is essentially treated as a trap.
*/
void
-syscall(struct trapframe *frame)
+amd64_syscall(struct thread *td, int traced)
{
- struct thread *td;
struct syscall_args sa;
- register_t orig_tf_rflags;
int error;
ksiginfo_t ksi;
#ifdef DIAGNOSTIC
- if (ISPL(frame->tf_cs) != SEL_UPL) {
+ if (ISPL(td->td_frame->tf_cs) != SEL_UPL) {
panic("syscall");
/* NOT REACHED */
}
#endif
- orig_tf_rflags = frame->tf_rflags;
- td = curthread;
- td->td_frame = frame;
-
error = syscallenter(td, &sa);
/*
* Traced syscall.
*/
- if (orig_tf_rflags & PSL_T) {
- frame->tf_rflags &= ~PSL_T;
+ if (__predict_false(traced)) {
+ td->td_frame->tf_rflags &= ~PSL_T;
ksiginfo_init_trap(&ksi);
ksi.ksi_signo = SIGTRAP;
ksi.ksi_code = TRAP_TRACE;
- ksi.ksi_addr = (void *)frame->tf_rip;
+ ksi.ksi_addr = (void *)td->td_frame->tf_rip;
trapsignal(td, &ksi);
}
diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC
index 7c42038ed056f..036c1b2812308 100644
--- a/sys/amd64/conf/GENERIC
+++ b/sys/amd64/conf/GENERIC
@@ -37,7 +37,7 @@ options MD_ROOT # MD is a potential root device
options NFSCL # New Network Filesystem Client
options NFSD # New Network Filesystem Server
options NFSLOCKD # Network Lock Manager
-options NFS_ROOT # NFS usable as /, requires NFSCLIENT
+options NFS_ROOT # NFS usable as /, requires NFSCL
options MSDOSFS # MSDOS Filesystem
options CD9660 # ISO 9660 Filesystem
options PROCFS # Process filesystem (requires PSEUDOFS)
@@ -187,10 +187,7 @@ device plip # TCP/IP over parallel
device ppi # Parallel port interface device
#device vpo # Requires scbus and da
-# If you've got a "dumb" serial or parallel PCI card that is
-# supported by the puc(4) glue driver, uncomment the following
-# line to enable it (connects to sio, uart and/or ppc drivers):
-#device puc
+device puc # Multi I/O cards and multi-channel UARTs
# PCI Ethernet NICs.
device bxe # Broadcom BCM57710/BCM57711/BCM57711E 10Gb Ethernet
@@ -330,7 +327,7 @@ device uath # Atheros AR5523 wireless NICs
device upgt # Conexant/Intersil PrismGT wireless NICs.
device ural # Ralink Technology RT2500USB wireless NICs
device urtw # Realtek RTL8187B/L wireless NICs
-device zyd # ZyDAS zb1211/zb1211b wireless NICs
+device zyd # ZyDAS zd1211/zd1211b wireless NICs
# FireWire support
device firewire # FireWire bus code
diff --git a/sys/amd64/conf/NOTES b/sys/amd64/conf/NOTES
index 4a47aceda0b10..07ea7b3135869 100644
--- a/sys/amd64/conf/NOTES
+++ b/sys/amd64/conf/NOTES
@@ -490,6 +490,14 @@ options ENABLE_ALART # Control alarm on Intel intpm driver
#
options PMAP_SHPGPERPROC=201
+#
+# Number of initial kernel page table pages used for early bootstrap.
+# This number should include enough pages to map the kernel and any
+# modules or other data loaded with the kernel by the loader. Each
+# page table page maps 2MB.
+#
+options NKPT=31
+
#####################################################################
# ABI Emulation
diff --git a/sys/amd64/ia32/ia32_syscall.c b/sys/amd64/ia32/ia32_syscall.c
index 0b46dae7a5e35..d79272a01dcfb 100644
--- a/sys/amd64/ia32/ia32_syscall.c
+++ b/sys/amd64/ia32/ia32_syscall.c
@@ -163,6 +163,8 @@ ia32_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
return (error);
}
+#include "../../kern/subr_syscall.c"
+
void
ia32_syscall(struct trapframe *frame)
{
diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h
index 88f3e1dbaed8f..479c84e85f1e2 100644
--- a/sys/amd64/include/md_var.h
+++ b/sys/amd64/include/md_var.h
@@ -75,6 +75,7 @@ struct fpreg;
struct dbreg;
struct dumperinfo;
+void amd64_syscall(struct thread *td, int traced);
void busdma_swi(void);
void cpu_setregs(void);
void doreti_iret(void) __asm(__STRING(doreti_iret));
diff --git a/sys/amd64/include/param.h b/sys/amd64/include/param.h
index 9a742f94e9b95..6dbeb4035925e 100644
--- a/sys/amd64/include/param.h
+++ b/sys/amd64/include/param.h
@@ -64,7 +64,9 @@
#endif
#if defined(SMP) || defined(KLD_MODULE)
-#define MAXCPU 32
+#ifndef MAXCPU
+#define MAXCPU 64
+#endif
#else
#define MAXCPU 1
#endif
diff --git a/sys/amd64/linux32/linux32_machdep.c b/sys/amd64/linux32/linux32_machdep.c
index 26041a3099353..a8ebe7ef1629c 100644
--- a/sys/amd64/linux32/linux32_machdep.c
+++ b/sys/amd64/linux32/linux32_machdep.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
+#include <sys/capability.h>
#include <sys/file.h>
#include <sys/fcntl.h>
#include <sys/clock.h>
@@ -566,7 +567,7 @@ linux_mmap_common(struct thread *td, l_uintptr_t addr, l_size_t len, l_int prot,
* protection options specified.
*/
- if ((error = fget(td, bsd_args.fd, &fp)) != 0)
+ if ((error = fget(td, bsd_args.fd, CAP_MMAP, &fp)) != 0)
return (error);
if (fp->f_type != DTYPE_VNODE) {
fdrop(fp, td);
diff --git a/sys/arm/arm/irq_dispatch.S b/sys/arm/arm/irq_dispatch.S
index e3577565ed32a..c919de006bff7 100644
--- a/sys/arm/arm/irq_dispatch.S
+++ b/sys/arm/arm/irq_dispatch.S
@@ -109,9 +109,9 @@ _C_LABEL(intrnames):
_C_LABEL(intrcnt):
.space NIRQ * 4
_C_LABEL(sintrnames):
- .word NIRQ * (MAXCOMLEN + 1)
+ .int NIRQ * (MAXCOMLEN + 1)
_C_LABEL(sintrcnt):
- .word NIRQ * 4
+ .int NIRQ * 4
.global _C_LABEL(current_intr_depth)
_C_LABEL(current_intr_depth):
diff --git a/sys/arm/arm/pmap.c b/sys/arm/arm/pmap.c
index d24a4229611a8..28835ec9362d2 100644
--- a/sys/arm/arm/pmap.c
+++ b/sys/arm/arm/pmap.c
@@ -1402,7 +1402,7 @@ pmap_fix_cache(struct vm_page *pg, pmap_t pm, vm_offset_t va)
if ((kwritable == 0) && (writable == 0)) {
pg->md.pvh_attrs &= ~PVF_MOD;
- vm_page_flag_clear(pg, PG_WRITEABLE);
+ vm_page_aflag_clear(pg, PGA_WRITEABLE);
return;
}
}
@@ -1568,7 +1568,7 @@ pmap_clearbit(struct vm_page *pg, u_int maskbits)
}
if (maskbits & PVF_WRITE)
- vm_page_flag_clear(pg, PG_WRITEABLE);
+ vm_page_aflag_clear(pg, PGA_WRITEABLE);
vm_page_unlock_queues();
return (count);
}
@@ -1630,7 +1630,7 @@ pmap_enter_pv(struct vm_page *pg, struct pv_entry *pve, pmap_t pm,
pg->md.pvh_attrs |= flags & (PVF_REF | PVF_MOD);
if (pve->pv_flags & PVF_WIRED)
++pm->pm_stats.wired_count;
- vm_page_flag_set(pg, PG_REFERENCED);
+ vm_page_aflag_set(pg, PGA_REFERENCED);
}
/*
@@ -1699,7 +1699,7 @@ pmap_nuke_pv(struct vm_page *pg, pmap_t pm, struct pv_entry *pve)
if (TAILQ_FIRST(&pg->md.pv_list) == NULL)
pg->md.pvh_attrs &= ~PVF_REF;
else
- vm_page_flag_set(pg, PG_REFERENCED);
+ vm_page_aflag_set(pg, PGA_REFERENCED);
if ((pve->pv_flags & PVF_NC) && ((pm == pmap_kernel()) ||
(pve->pv_flags & PVF_WRITE) || !(pve->pv_flags & PVF_MWC)))
pmap_fix_cache(pg, pm, 0);
@@ -1709,7 +1709,7 @@ pmap_nuke_pv(struct vm_page *pg, pmap_t pm, struct pv_entry *pve)
break;
if (!pve) {
pg->md.pvh_attrs &= ~PVF_MOD;
- vm_page_flag_clear(pg, PG_WRITEABLE);
+ vm_page_aflag_clear(pg, PGA_WRITEABLE);
}
}
pv = TAILQ_FIRST(&pg->md.pv_list);
@@ -1724,7 +1724,7 @@ pmap_nuke_pv(struct vm_page *pg, pmap_t pm, struct pv_entry *pve)
--pm->pm_stats.wired_count;
pg->md.pvh_attrs &= ~PVF_REF;
pg->md.pvh_attrs &= ~PVF_MOD;
- vm_page_flag_clear(pg, PG_WRITEABLE);
+ vm_page_aflag_clear(pg, PGA_WRITEABLE);
pmap_free_pv_entry(pv);
}
}
@@ -2695,7 +2695,7 @@ pmap_remove_pages(pmap_t pmap)
npv = TAILQ_NEXT(pv, pv_plist);
pmap_nuke_pv(m, pmap, pv);
if (TAILQ_EMPTY(&m->md.pv_list))
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
pmap_free_pv_entry(pv);
pmap_free_l2_bucket(pmap, l2b, 1);
}
@@ -3120,7 +3120,7 @@ pmap_remove_all(vm_page_t m)
pmap_t curpm;
int flags = 0;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_remove_all: page %p is not managed", m));
if (TAILQ_EMPTY(&m->md.pv_list))
return;
@@ -3172,7 +3172,7 @@ pmap_remove_all(vm_page_t m)
else
pmap_tlb_flushD(curpm);
}
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
vm_page_unlock_queues();
}
@@ -3242,7 +3242,7 @@ pmap_protect(pmap_t pm, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot)
PTE_SYNC(ptep);
if (pg != NULL) {
- if (!(pg->flags & PG_UNMANAGED)) {
+ if (!(pg->oflags & VPO_UNMANAGED)) {
f = pmap_modify_pv(pg, pm, sva,
PVF_WRITE, 0);
vm_page_dirty(pg);
@@ -3327,8 +3327,8 @@ pmap_enter_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
pa = systempage.pv_pa;
m = NULL;
} else {
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0 ||
- (m->oflags & VPO_BUSY) != 0 || (flags & M_NOWAIT) != 0,
+ KASSERT((m->oflags & (VPO_UNMANAGED | VPO_BUSY)) != 0 ||
+ (flags & M_NOWAIT) != 0,
("pmap_enter_locked: page %p is not busy", m));
pa = VM_PAGE_TO_PHYS(m);
}
@@ -3406,7 +3406,7 @@ do_l2b_alloc:
vm_page_dirty(m);
}
if (m && opte)
- vm_page_flag_set(m, PG_REFERENCED);
+ vm_page_aflag_set(m, PGA_REFERENCED);
} else {
/*
* Need to do page referenced emulation.
@@ -3417,8 +3417,8 @@ do_l2b_alloc:
if (prot & VM_PROT_WRITE) {
npte |= L2_S_PROT_W;
if (m != NULL &&
- (m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0)
- vm_page_flag_set(m, PG_WRITEABLE);
+ (m->oflags & VPO_UNMANAGED) == 0)
+ vm_page_aflag_set(m, PGA_WRITEABLE);
}
npte |= pte_l2_s_cache_mode;
if (m && m == opg) {
@@ -3480,36 +3480,36 @@ do_l2b_alloc:
* this physical page is not/is already mapped.
*/
- if (m && ((m->flags & PG_FICTITIOUS) ||
- ((m->flags & PG_UNMANAGED) &&
+ if (m && (m->oflags & VPO_UNMANAGED) &&
!m->md.pv_kva &&
- TAILQ_EMPTY(&m->md.pv_list)))) {
+ TAILQ_EMPTY(&m->md.pv_list)) {
pmap_free_pv_entry(pve);
pve = NULL;
}
- } else if (m && !(m->flags & PG_FICTITIOUS) &&
- (!(m->flags & PG_UNMANAGED) || m->md.pv_kva ||
+ } else if (m &&
+ (!(m->oflags & VPO_UNMANAGED) || m->md.pv_kva ||
!TAILQ_EMPTY(&m->md.pv_list)))
pve = pmap_get_pv_entry();
- } else if (m && !(m->flags & PG_FICTITIOUS) &&
- (!(m->flags & PG_UNMANAGED) || m->md.pv_kva ||
+ } else if (m &&
+ (!(m->oflags & VPO_UNMANAGED) || m->md.pv_kva ||
!TAILQ_EMPTY(&m->md.pv_list)))
pve = pmap_get_pv_entry();
- if (m && !(m->flags & PG_FICTITIOUS)) {
- KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva,
- ("pmap_enter: managed mapping within the clean submap"));
- if (m->flags & PG_UNMANAGED) {
+ if (m) {
+ if ((m->oflags & VPO_UNMANAGED)) {
if (!TAILQ_EMPTY(&m->md.pv_list) ||
- m->md.pv_kva) {
+ m->md.pv_kva) {
KASSERT(pve != NULL, ("No pv"));
nflags |= PVF_UNMAN;
pmap_enter_pv(m, pve, pmap, va, nflags);
} else
m->md.pv_kva = va;
} else {
- KASSERT(pve != NULL, ("No pv"));
- pmap_enter_pv(m, pve, pmap, va, nflags);
+ KASSERT(va < kmi.clean_sva ||
+ va >= kmi.clean_eva,
+ ("pmap_enter: managed mapping within the clean submap"));
+ KASSERT(pve != NULL, ("No pv"));
+ pmap_enter_pv(m, pve, pmap, va, nflags);
}
}
}
@@ -4423,7 +4423,7 @@ pmap_page_exists_quick(pmap_t pmap, vm_page_t m)
int loops = 0;
boolean_t rv;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_page_exists_quick: page %p is not managed", m));
rv = FALSE;
vm_page_lock_queues();
@@ -4453,7 +4453,7 @@ pmap_page_wired_mappings(vm_page_t m)
int count;
count = 0;
- if ((m->flags & PG_FICTITIOUS) != 0)
+ if ((m->oflags & VPO_UNMANAGED) != 0)
return (count);
vm_page_lock_queues();
TAILQ_FOREACH(pv, &m->md.pv_list, pv_list)
@@ -4472,7 +4472,7 @@ int
pmap_ts_referenced(vm_page_t m)
{
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_ts_referenced: page %p is not managed", m));
return (pmap_clearbit(m, PVF_REF));
}
@@ -4482,7 +4482,7 @@ boolean_t
pmap_is_modified(vm_page_t m)
{
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_is_modified: page %p is not managed", m));
if (m->md.pvh_attrs & PVF_MOD)
return (TRUE);
@@ -4498,18 +4498,18 @@ void
pmap_clear_modify(vm_page_t m)
{
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_clear_modify: page %p is not managed", m));
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
KASSERT((m->oflags & VPO_BUSY) == 0,
("pmap_clear_modify: page %p is busy", m));
/*
- * If the page is not PG_WRITEABLE, then no mappings can be modified.
+ * If the page is not PGA_WRITEABLE, then no mappings can be modified.
* If the object containing the page is locked and the page is not
- * VPO_BUSY, then PG_WRITEABLE cannot be concurrently set.
+ * VPO_BUSY, then PGA_WRITEABLE cannot be concurrently set.
*/
- if ((m->flags & PG_WRITEABLE) == 0)
+ if ((m->aflags & PGA_WRITEABLE) == 0)
return;
if (m->md.pvh_attrs & PVF_MOD)
pmap_clearbit(m, PVF_MOD);
@@ -4526,7 +4526,7 @@ boolean_t
pmap_is_referenced(vm_page_t m)
{
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_is_referenced: page %p is not managed", m));
return ((m->md.pvh_attrs & PVF_REF) != 0);
}
@@ -4540,7 +4540,7 @@ void
pmap_clear_reference(vm_page_t m)
{
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_clear_reference: page %p is not managed", m));
if (m->md.pvh_attrs & PVF_REF)
pmap_clearbit(m, PVF_REF);
@@ -4554,17 +4554,17 @@ void
pmap_remove_write(vm_page_t m)
{
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_remove_write: page %p is not managed", m));
/*
- * If the page is not VPO_BUSY, then PG_WRITEABLE cannot be set by
- * another thread while the object is locked. Thus, if PG_WRITEABLE
+ * If the page is not VPO_BUSY, then PGA_WRITEABLE cannot be set by
+ * another thread while the object is locked. Thus, if PGA_WRITEABLE
* is clear, no page table entries need updating.
*/
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
if ((m->oflags & VPO_BUSY) != 0 ||
- (m->flags & PG_WRITEABLE) != 0)
+ (m->aflags & PGA_WRITEABLE) != 0)
pmap_clearbit(m, PVF_WRITE);
}
diff --git a/sys/arm/at91/uart_dev_at91usart.c b/sys/arm/at91/uart_dev_at91usart.c
index 94ea9de1d2751..f3d21aae5a0f6 100644
--- a/sys/arm/at91/uart_dev_at91usart.c
+++ b/sys/arm/at91/uart_dev_at91usart.c
@@ -29,8 +29,6 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include "opt_comconsole.h"
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
@@ -485,25 +483,10 @@ at91_usart_bus_param(struct uart_softc *sc, int baudrate, int databits,
static __inline void
at91_rx_put(struct uart_softc *sc, int key)
{
-#if defined(KDB) && defined(ALT_BREAK_TO_DEBUGGER)
- int kdb_brk;
- if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) {
- if ((kdb_brk = kdb_alt_break(key, &sc->sc_altbrk)) != 0) {
- switch (kdb_brk) {
- case KDB_REQ_DEBUGGER:
- kdb_enter(KDB_WHY_BREAK,
- "Break sequence on console");
- break;
- case KDB_REQ_PANIC:
- kdb_panic("Panic sequence on console");
- break;
- case KDB_REQ_REBOOT:
- kdb_reboot();
- break;
- }
- }
- }
+#if defined(KDB)
+ if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE)
+ kdb_alt_break(key, &sc->sc_altbrk);
#endif
uart_rx_put(sc, key);
}
diff --git a/sys/arm/conf/AVILA b/sys/arm/conf/AVILA
index 0140eb0f57a77..7916b2cc68fe9 100644
--- a/sys/arm/conf/AVILA
+++ b/sys/arm/conf/AVILA
@@ -50,8 +50,8 @@ options SCHED_4BSD #4BSD scheduler
options INET #InterNETworking
options FFS #Berkeley Fast Filesystem
options SOFTUPDATES #Enable FFS soft updates support
-options NFSCLIENT #Network Filesystem Client
-options NFS_ROOT #NFS usable as /, requires NFSCLIENT
+options NFSCL #New Network Filesystem Client
+options NFS_ROOT #NFS usable as /, requires NFSCL
options BOOTP
options BOOTP_NFSROOT
options BOOTP_NFSV3
diff --git a/sys/arm/conf/BWCT b/sys/arm/conf/BWCT
index 0fb3b872cba6d..3a28e487d7b28 100644
--- a/sys/arm/conf/BWCT
+++ b/sys/arm/conf/BWCT
@@ -46,10 +46,10 @@ options SOFTUPDATES #Enable FFS soft updates support
#options MD_ROOT_SIZE=4096 # 3MB ram disk
#options ROOTDEVNAME=\"ufs:md0\"
#options ROOTDEVNAME=\"ufs:/dev/mmcsd0s1a\"
-options NFSCLIENT #Network Filesystem Client
-#options NFSSERVER #Network Filesystem Server
+options NFSCL #New Network Filesystem Client
+#options NFSD #New Network Filesystem Server
#options NFSLOCKD #Network Lock Manager
-options NFS_ROOT #NFS usable as /, requires NFSCLIENT
+options NFS_ROOT #NFS usable as /, requires NFSCL
options BOOTP_NFSROOT
options BOOTP
diff --git a/sys/arm/conf/CAMBRIA b/sys/arm/conf/CAMBRIA
index befe28af72355..19a8daa5572c5 100644
--- a/sys/arm/conf/CAMBRIA
+++ b/sys/arm/conf/CAMBRIA
@@ -51,8 +51,8 @@ options SCHED_4BSD #4BSD scheduler
options INET #InterNETworking
options FFS #Berkeley Fast Filesystem
options SOFTUPDATES #Enable FFS soft updates support
-options NFSCLIENT #Network Filesystem Client
-options NFS_ROOT #NFS usable as /, requires NFSCLIENT
+options NFSCL #New Network Filesystem Client
+options NFS_ROOT #NFS usable as /, requires NFSCL
options BOOTP
options BOOTP_NFSROOT
options BOOTP_NFSV3
diff --git a/sys/arm/conf/CNS11XXNAS b/sys/arm/conf/CNS11XXNAS
index 76db42b4e3630..2832779a5ad5b 100644
--- a/sys/arm/conf/CNS11XXNAS
+++ b/sys/arm/conf/CNS11XXNAS
@@ -66,10 +66,10 @@ options FFS #Berkeley Fast Filesystem
options SOFTUPDATES #Enable FFS soft updates support
options UFS_ACL #Support for access control lists
options UFS_DIRHASH #Improve performance on big directories
-options NFSCLIENT #Network Filesystem Client
-#options NFSSERVER #Network Filesystem Server
+options NFSCL #New Network Filesystem Client
+#options NFSD #New Network Filesystem Server
#options NFSLOCKD #Network Lock Manager
-options NFS_ROOT #NFS usable as /, requires NFSCLIENT
+options NFS_ROOT #NFS usable as /, requires NFSCL
options MSDOSFS #MSDOS Filesystem
#options CD9660 #ISO 9660 Filesystem
#options PROCFS #Process filesystem (requires PSEUDOFS)
diff --git a/sys/arm/conf/CRB b/sys/arm/conf/CRB
index 45f19e03202df..bf12e0b819e0c 100644
--- a/sys/arm/conf/CRB
+++ b/sys/arm/conf/CRB
@@ -41,10 +41,10 @@ options FFS #Berkeley Fast Filesystem
options SOFTUPDATES #Enable FFS soft updates support
options UFS_ACL #Support for access control lists
options UFS_DIRHASH #Improve performance on big directories
-options NFSCLIENT #Network Filesystem Client
-options NFSSERVER #Network Filesystem Server
+options NFSCL #New Network Filesystem Client
+options NFSD #New Network Filesystem Server
options NFSLOCKD #Network Lock Manager
-options NFS_ROOT #NFS usable as /, requires NFSCLIENT
+options NFS_ROOT #NFS usable as /, requires NFSCL
#options MSDOSFS #MSDOS Filesystem
options CD9660 #ISO 9660 Filesystem
#options PROCFS #Process filesystem (requires PSEUDOFS)
diff --git a/sys/arm/conf/DB-78XXX b/sys/arm/conf/DB-78XXX
index 7b58adaa9370a..d38ae55aade3c 100644
--- a/sys/arm/conf/DB-78XXX
+++ b/sys/arm/conf/DB-78XXX
@@ -17,9 +17,9 @@ options SCHED_4BSD #4BSD scheduler
options INET #InterNETworking
options INET6 #IPv6 communications protocols
options FFS #Berkeley Fast Filesystem
-options NFSCLIENT #Network Filesystem Client
+options NFSCL #New Network Filesystem Client
options NFSLOCKD #Network Lock Manager
-options NFS_ROOT #NFS usable as /, requires NFSCLIENT
+options NFS_ROOT #NFS usable as /, requires NFSCL
options BOOTP
options BOOTP_NFSROOT
options BOOTP_NFSV3
diff --git a/sys/arm/conf/DB-88F5XXX b/sys/arm/conf/DB-88F5XXX
index 655d4a736afaa..d5df863c0158c 100644
--- a/sys/arm/conf/DB-88F5XXX
+++ b/sys/arm/conf/DB-88F5XXX
@@ -17,9 +17,9 @@ options SCHED_4BSD #4BSD scheduler
options INET #InterNETworking
options INET6 #IPv6 communications protocols
options FFS #Berkeley Fast Filesystem
-options NFSCLIENT #Network Filesystem Client
+options NFSCL #New Network Filesystem Client
options NFSLOCKD #Network Lock Manager
-options NFS_ROOT #NFS usable as /, requires NFSCLIENT
+options NFS_ROOT #NFS usable as /, requires NFSCL
options BOOTP
options BOOTP_NFSROOT
options BOOTP_NFSV3
diff --git a/sys/arm/conf/DB-88F6XXX b/sys/arm/conf/DB-88F6XXX
index ff9f28940bfb5..fec1c4e7f20c0 100644
--- a/sys/arm/conf/DB-88F6XXX
+++ b/sys/arm/conf/DB-88F6XXX
@@ -17,9 +17,9 @@ options SCHED_4BSD #4BSD scheduler
options INET #InterNETworking
options INET6 #IPv6 communications protocols
options FFS #Berkeley Fast Filesystem
-options NFSCLIENT #Network Filesystem Client
+options NFSCL #New Network Filesystem Client
options NFSLOCKD #Network Lock Manager
-options NFS_ROOT #NFS usable as /, requires NFSCLIENT
+options NFS_ROOT #NFS usable as /, requires NFSCL
options BOOTP
options BOOTP_NFSROOT
options BOOTP_NFSV3
diff --git a/sys/arm/conf/DOCKSTAR b/sys/arm/conf/DOCKSTAR
index 780cb78d4d683..4e5b596394292 100644
--- a/sys/arm/conf/DOCKSTAR
+++ b/sys/arm/conf/DOCKSTAR
@@ -17,9 +17,9 @@ options SCHED_4BSD #4BSD scheduler
options INET #InterNETworking
options INET6 #IPv6 communications protocols
options FFS #Berkeley Fast Filesystem
-options NFSCLIENT #Network Filesystem Client
+options NFSCL #New Network Filesystem Client
options NFSLOCKD #Network Lock Manager
-options NFS_ROOT #NFS usable as /, requires NFSCLIENT
+options NFS_ROOT #NFS usable as /, requires NFSCL
options BOOTP
options BOOTP_NFSROOT
options BOOTP_NFSV3
diff --git a/sys/arm/conf/EP80219 b/sys/arm/conf/EP80219
index 23717dfa96335..38b0c2f448899 100644
--- a/sys/arm/conf/EP80219
+++ b/sys/arm/conf/EP80219
@@ -40,10 +40,10 @@ options FFS #Berkeley Fast Filesystem
options SOFTUPDATES #Enable FFS soft updates support
options UFS_ACL #Support for access control lists
options UFS_DIRHASH #Improve performance on big directories
-options NFSCLIENT #Network Filesystem Client
-options NFSSERVER #Network Filesystem Server
+options NFSCL #New Network Filesystem Client
+options NFSD #New Network Filesystem Server
options NFSLOCKD #Network Lock Manager
-options NFS_ROOT #NFS usable as /, requires NFSCLIENT
+options NFS_ROOT #NFS usable as /, requires NFSCL
#options MSDOSFS #MSDOS Filesystem
options CD9660 #ISO 9660 Filesystem
#options PROCFS #Process filesystem (requires PSEUDOFS)
diff --git a/sys/arm/conf/GUMSTIX b/sys/arm/conf/GUMSTIX
index e7900f5660c9e..8017a7ae3fde6 100644
--- a/sys/arm/conf/GUMSTIX
+++ b/sys/arm/conf/GUMSTIX
@@ -45,9 +45,9 @@ options FFS #Berkeley Fast Filesystem
options SOFTUPDATES #Enable FFS soft updates support
options UFS_ACL #Support for access control lists
options UFS_DIRHASH #Improve performance on big directories
-options NFSCLIENT #Network Filesystem Client
-#options NFSSERVER #Network Filesystem Server
-options NFS_ROOT #NFS usable as /, requires NFSCLIENT
+options NFSCL #New Network Filesystem Client
+#options NFSD #New Network Filesystem Server
+options NFS_ROOT #NFS usable as /, requires NFSCL
#options MSDOSFS #MSDOS Filesystem
#options CD9660 #ISO 9660 Filesystem
#options PROCFS #Process filesystem (requires PSEUDOFS)
diff --git a/sys/arm/conf/HL200 b/sys/arm/conf/HL200
index dd46a61c2fde9..ffd306ab0ba3a 100644
--- a/sys/arm/conf/HL200
+++ b/sys/arm/conf/HL200
@@ -39,10 +39,10 @@ options FFS #Berkeley Fast Filesystem
#options MD_ROOT #MD is a potential root device
#options MD_ROOT_SIZE=4096 # 3MB ram disk
#options ROOTDEVNAME=\"ufs:/dev/mmcsd0s1a\"
-options NFSCLIENT #Network Filesystem Client
-#options NFSSERVER #Network Filesystem Server
+options NFSCL #New Network Filesystem Client
+#options NFSD #New Network Filesystem Server
#options NFSLOCKD #Network Lock Manager
-options NFS_ROOT #NFS usable as /, requires NFSCLIENT
+options NFS_ROOT #NFS usable as /, requires NFSCL
options BOOTP_NFSROOT
options BOOTP
options BOOTP_NFSV3
@@ -126,7 +126,7 @@ device udav # Davicom DM9601E USB
device rum # Ralink Technology RT2501USB wireless NICs
device uath # Atheros AR5523 wireless NICs
device ural # Ralink Technology RT2500USB wireless NICs
-device zyd # ZyDAS zb1211/zb1211b wireless NICs
+device zyd # ZyDAS zd1211/zd1211b wireless NICs
# SCSI peripherals
device scbus # SCSI bus (required for SCSI)
device da # Direct Access (disks)
diff --git a/sys/arm/conf/HL201 b/sys/arm/conf/HL201
index 6524cc648e869..157ac21a3ca72 100644
--- a/sys/arm/conf/HL201
+++ b/sys/arm/conf/HL201
@@ -39,10 +39,10 @@ options FFS #Berkeley Fast Filesystem
#options MD_ROOT #MD is a potential root device
#options MD_ROOT_SIZE=4096 # 3MB ram disk
#options ROOTDEVNAME=\"ufs:/dev/mmcsd0s1a\"
-options NFSCLIENT #Network Filesystem Client
-#options NFSSERVER #Network Filesystem Server
+options NFSCL #New Network Filesystem Client
+#options NFSD #New Network Filesystem Server
#options NFSLOCKD #Network Lock Manager
-options NFS_ROOT #NFS usable as /, requires NFSCLIENT
+options NFS_ROOT #NFS usable as /, requires NFSCL
options BOOTP_NFSROOT
options BOOTP
options BOOTP_NFSV3
@@ -117,7 +117,7 @@ device udav # Davicom DM9601E USB
#device rum # Ralink Technology RT2501USB wireless NICs
#device uath # Atheros AR5523 wireless NICs
#device ural # Ralink Technology RT2500USB wireless NICs
-#device zyd # ZyDAS zb1211/zb1211b wireless NICs
+#device zyd # ZyDAS zd1211/zd1211b wireless NICs
# SCSI peripherals
device scbus # SCSI bus (required for SCSI)
device da # Direct Access (disks)
diff --git a/sys/arm/conf/IQ31244 b/sys/arm/conf/IQ31244
index 56798116c4348..e35427c679da5 100644
--- a/sys/arm/conf/IQ31244
+++ b/sys/arm/conf/IQ31244
@@ -41,10 +41,10 @@ options FFS #Berkeley Fast Filesystem
options SOFTUPDATES #Enable FFS soft updates support
options UFS_ACL #Support for access control lists
options UFS_DIRHASH #Improve performance on big directories
-options NFSCLIENT #Network Filesystem Client
-options NFSSERVER #Network Filesystem Server
+options NFSCL #New Network Filesystem Client
+options NFSD #New Network Filesystem Server
options NFSLOCKD #Network Lock Manager
-options NFS_ROOT #NFS usable as /, requires NFSCLIENT
+options NFS_ROOT #NFS usable as /, requires NFSCL
#options MSDOSFS #MSDOS Filesystem
options CD9660 #ISO 9660 Filesystem
#options PROCFS #Process filesystem (requires PSEUDOFS)
diff --git a/sys/arm/conf/KB920X b/sys/arm/conf/KB920X
index f47e9acf09b28..524e38705389c 100644
--- a/sys/arm/conf/KB920X
+++ b/sys/arm/conf/KB920X
@@ -40,10 +40,10 @@ options FFS #Berkeley Fast Filesystem
#options MD_ROOT #MD is a potential root device
#options MD_ROOT_SIZE=4096 # 4MB ram disk
options ROOTDEVNAME=\"ufs:/dev/mmcsd0s1a\"
-options NFSCLIENT #Network Filesystem Client
-#options NFSSERVER #Network Filesystem Server
+options NFSCL #New Network Filesystem Client
+#options NFSD #New Network Filesystem Server
#options NFSLOCKD #Network Lock Manager
-#options NFS_ROOT #NFS usable as /, requires NFSCLIENT
+#options NFS_ROOT #NFS usable as /, requires NFSCL
#options BOOTP_NFSROOT
#options BOOTP
@@ -126,7 +126,7 @@ device udav # Davicom DM9601E USB
device rum # Ralink Technology RT2501USB wireless NICs
device uath # Atheros AR5523 wireless NICs
device ural # Ralink Technology RT2500USB wireless NICs
-device zyd # ZyDAS zb1211/zb1211b wireless NICs
+device zyd # ZyDAS zd1211/zd1211b wireless NICs
# SCSI peripherals
device scbus # SCSI bus (required for SCSI)
device da # Direct Access (disks)
diff --git a/sys/arm/conf/LN2410SBC b/sys/arm/conf/LN2410SBC
index e4f3a5445c607..4598aef57ff8a 100644
--- a/sys/arm/conf/LN2410SBC
+++ b/sys/arm/conf/LN2410SBC
@@ -45,7 +45,7 @@ options ROOTDEVNAME=\"ufs:da0s1\"
#options BOOTP
#options BOOTP_NFSROOT # NFS mount root filesystem using BOOTP info
-#options NFSCLIENT #Network File System client
+#options NFSCL #New Network Filesystem Client
#options NFS_ROOT #NFS usable as root device
options PSEUDOFS #Pseudo-filesystem framework
diff --git a/sys/arm/conf/NSLU b/sys/arm/conf/NSLU
index d921e34902440..2e4f4b1cc5a27 100644
--- a/sys/arm/conf/NSLU
+++ b/sys/arm/conf/NSLU
@@ -58,10 +58,10 @@ options FFS #Berkeley Fast Filesystem
options SOFTUPDATES #Enable FFS soft updates support
options UFS_ACL #Support for access control lists
options UFS_DIRHASH #Improve performance on big directories
-options NFSCLIENT #Network Filesystem Client
-options NFSSERVER #Network Filesystem Server
+options NFSCL #New Network Filesystem Client
+options NFSD #New Network Filesystem Server
options NFSLOCKD #Network Lock Manager
-options NFS_ROOT #NFS usable as /, requires NFSCLIENT
+options NFS_ROOT #NFS usable as /, requires NFSCL
#options MSDOSFS #MSDOS Filesystem
options CD9660 #ISO 9660 Filesystem
#options PROCFS #Process filesystem (requires PSEUDOFS)
diff --git a/sys/arm/conf/QILA9G20 b/sys/arm/conf/QILA9G20
index 55839cee1ad11..6318a574df0f6 100644
--- a/sys/arm/conf/QILA9G20
+++ b/sys/arm/conf/QILA9G20
@@ -39,10 +39,10 @@ options FFS #Berkeley Fast Filesystem
#options UFS_DIRHASH #Improve performance on big directories
#options MD_ROOT #MD is a potential root device
#options MD_ROOT_SIZE=4096 # 3MB ram disk
-options NFSCLIENT #Network Filesystem Client
-#options NFSSERVER #Network Filesystem Server
+options NFSCL #New Network Filesystem Client
+#options NFSD #New Network Filesystem Server
#options NFSLOCKD #Network Lock Manager
-#options NFS_ROOT #NFS usable as /, requires NFSCLIENT
+#options NFS_ROOT #NFS usable as /, requires NFSCL
#options BOOTP_NFSROOT
#options BOOTP
#options BOOTP_NFSV3
@@ -142,7 +142,7 @@ device udav # Davicom DM9601E USB
#device rum # Ralink Technology RT2501USB wireless NICs
#device uath # Atheros AR5523 wireless NICs
#device ural # Ralink Technology RT2500USB wireless NICs
-#device zyd # ZyDAS zb1211/zb1211b wireless NICs
+#device zyd # ZyDAS zd1211/zd1211b wireless NICs
# Wireless NIC cards
#device wlan # 802.11 support
diff --git a/sys/arm/conf/SAM9G20EK b/sys/arm/conf/SAM9G20EK
index 6c2e94ef1cdcb..e304e9d84b4b0 100644
--- a/sys/arm/conf/SAM9G20EK
+++ b/sys/arm/conf/SAM9G20EK
@@ -38,10 +38,10 @@ options FFS #Berkeley Fast Filesystem
#options UFS_DIRHASH #Improve performance on big directories
#options MD_ROOT #MD is a potential root device
#options MD_ROOT_SIZE=4096 # 3MB ram disk
-options NFSCLIENT #Network Filesystem Client
-#options NFSSERVER #Network Filesystem Server
+options NFSCL #New Network Filesystem Client
+#options NFSD #New Network Filesystem Server
#options NFSLOCKD #Network Lock Manager
-#options NFS_ROOT #NFS usable as /, requires NFSCLIENT
+#options NFS_ROOT #NFS usable as /, requires NFSCL
#options BOOTP_NFSROOT
#options BOOTP
#options BOOTP_NFSV3
@@ -142,7 +142,7 @@ device udav # Davicom DM9601E USB
#device rum # Ralink Technology RT2501USB wireless NICs
#device uath # Atheros AR5523 wireless NICs
#device ural # Ralink Technology RT2500USB wireless NICs
-#device zyd # ZyDAS zb1211/zb1211b wireless NICs
+#device zyd # ZyDAS zd1211/zd1211b wireless NICs
# Wireless NIC cards
#device wlan # 802.11 support
diff --git a/sys/arm/conf/SHEEVAPLUG b/sys/arm/conf/SHEEVAPLUG
index 75a5474517e66..5392c95093ef1 100644
--- a/sys/arm/conf/SHEEVAPLUG
+++ b/sys/arm/conf/SHEEVAPLUG
@@ -17,9 +17,9 @@ options SCHED_4BSD #4BSD scheduler
options INET #InterNETworking
options INET6 #IPv6 communications protocols
options FFS #Berkeley Fast Filesystem
-options NFSCLIENT #Network Filesystem Client
+options NFSCL #New Network Filesystem Client
options NFSLOCKD #Network Lock Manager
-options NFS_ROOT #NFS usable as /, requires NFSCLIENT
+options NFS_ROOT #NFS usable as /, requires NFSCL
options BOOTP
options BOOTP_NFSROOT
options BOOTP_NFSV3
diff --git a/sys/arm/conf/SIMICS b/sys/arm/conf/SIMICS
index 229c60f9cdeaf..84ff983cde002 100644
--- a/sys/arm/conf/SIMICS
+++ b/sys/arm/conf/SIMICS
@@ -39,10 +39,10 @@ options UFS_ACL #Support for access control lists
options UFS_DIRHASH #Improve performance on big directories
options MD_ROOT #MD is a potential root device
options ROOTDEVNAME=\"ufs:md0\"
-options NFSCLIENT #Network Filesystem Client
-options NFSSERVER #Network Filesystem Server
+options NFSCL #New Network Filesystem Client
+options NFSD #New Network Filesystem Server
options NFSLOCKD #Network Lock Manager
-options NFS_ROOT #NFS usable as /, requires NFSCLIENT
+options NFS_ROOT #NFS usable as /, requires NFSCL
#options MSDOSFS #MSDOS Filesystem
options CD9660 #ISO 9660 Filesystem
#options PROCFS #Process filesystem (requires PSEUDOFS)
diff --git a/sys/arm/conf/TS7800 b/sys/arm/conf/TS7800
index c72661af00144..5300ccab92f44 100644
--- a/sys/arm/conf/TS7800
+++ b/sys/arm/conf/TS7800
@@ -18,9 +18,9 @@ options INET #InterNETworking
options INET6 #IPv6 communications protocols
options FFS #Berkeley Fast Filesystem
options SOFTUPDATES # Enable FFS soft updates support
-options NFSCLIENT #Network Filesystem Client
+options NFSCL #New Network Filesystem Client
options NFSLOCKD #Network Lock Manager
-options NFS_ROOT #NFS usable as /, requires NFSCLIENT
+options NFS_ROOT #NFS usable as /, requires NFSCL
options BOOTP
options BOOTP_NFSROOT
options BOOTP_NFSV3
diff --git a/sys/arm/include/param.h b/sys/arm/include/param.h
index 1694bc43c5ed9..96a70388f1f51 100644
--- a/sys/arm/include/param.h
+++ b/sys/arm/include/param.h
@@ -61,7 +61,9 @@
#define MID_MACHINE MID_ARM6
#if defined(SMP) || defined(KLD_MODULE)
+#ifndef MAXCPU
#define MAXCPU 2
+#endif
#else
#define MAXCPU 1
#endif /* SMP || KLD_MODULE */
diff --git a/sys/arm/sa11x0/sa11x0_irq.S b/sys/arm/sa11x0/sa11x0_irq.S
index 3cc3d14f7c3bc..1cacc2ddf8468 100644
--- a/sys/arm/sa11x0/sa11x0_irq.S
+++ b/sys/arm/sa11x0/sa11x0_irq.S
@@ -122,7 +122,7 @@ ENTRY(sa11x0_activateirqs)
.global _C_LABEL(intrnames), _C_LABEL(sintrnames)
_C_LABEL(intrnames):
_C_LABEL(sintrnames):
- .word 0
+ .int 0
.globl _C_LABEL(intrcnt), _C_LABEL(sintrcnt)
diff --git a/sys/boot/common/util.c b/sys/boot/common/util.c
index 012106aef8acd..07f69a3b2f91c 100644
--- a/sys/boot/common/util.c
+++ b/sys/boot/common/util.c
@@ -119,7 +119,7 @@ printf(const char *fmt, ...)
{
va_list ap;
const char *hex = "0123456789abcdef";
- char buf[10], *s;
+ char buf[32], *s;
unsigned long long u;
int c, l;
diff --git a/sys/boot/forth/loader.conf b/sys/boot/forth/loader.conf
index 759d62cf3fd24..c8abe58018e9c 100644
--- a/sys/boot/forth/loader.conf
+++ b/sys/boot/forth/loader.conf
@@ -55,6 +55,11 @@ module_path="/boot/modules" # Set the module search path
#prompt="\\${interpret}" # Set the command prompt
#root_disk_unit="0" # Force the root disk unit number
#rootdev="disk1s1a" # Set the root filesystem
+#tftp.blksize="1428" # Set the RFC 2348 TFTP block size.
+ # If the TFTP server does not support RFC 2348,
+ # the block size is set to 512. If the value
+ # is out of range ( < 8 || > 9008 ) an error is
+ # returned.
##############################################################
@@ -104,6 +109,8 @@ module_path="/boot/modules" # Set the module search path
#kern.ncallout="" # Set the maximum # of timer events
#kern.ngroups="1023" # Set the maximum # of supplemental groups
#kern.sgrowsiz="" # Set the amount to grow stack
+#kern.cam.boot_delay="10000" # Delay (in ms) of root mount for CAM bus
+ # registration, useful for USB sticks as root
#kern.cam.scsi_delay="2000" # Delay (in ms) before probing SCSI
#kern.ipc.maxsockets="" # Set the maximum number of sockets avaliable
#kern.ipc.nmbclusters="" # Set the number of mbuf clusters
diff --git a/sys/boot/forth/loader.conf.5 b/sys/boot/forth/loader.conf.5
index c8c61c6dd0756..fa83c8f48a6c9 100644
--- a/sys/boot/forth/loader.conf.5
+++ b/sys/boot/forth/loader.conf.5
@@ -23,7 +23,7 @@
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
-.Dd January 16, 2008
+.Dd July 20, 2011
.Dt LOADER.CONF 5
.Os
.Sh NAME
@@ -107,6 +107,9 @@ present file.
Name of the kernel to be loaded.
If no kernel name is set, no additional
modules will be loaded.
+The name must be a subdirectory of
+.Pa /boot
+that contains a kernel.
.It Ar kernel_options
Flags to be passed to the kernel.
.It Ar password
@@ -190,7 +193,7 @@ replacing it with
.Dq spinning
character (useful for embedded products and such).
.It Va kernel
-.Pq Dq Pa /boot/kernel/kernel
+.Pq Dq kernel
.It Va loader_conf_files
.Pq Dq Pa /boot/loader.conf /boot/loader.conf.local
.It Va splash_bmp_load
diff --git a/sys/boot/forth/menu.4th b/sys/boot/forth/menu.4th
index 110ec1c9253eb..fbb6c16b5c04c 100644
--- a/sys/boot/forth/menu.4th
+++ b/sys/boot/forth/menu.4th
@@ -742,11 +742,12 @@ create init_text8 255 allot
else
-rot 2drop
- \ disable timeout if less than zero
+ \ boot immediately if less than zero
dup 0< if
drop
- 0 menu_timeout_enabled !
- 0 ( assigned to menu_timeout below )
+ menu-create
+ 0 25 at-xy
+ 0 boot
then
then
then
diff --git a/sys/boot/forth/menu.4th.8 b/sys/boot/forth/menu.4th.8
index 45388f5418521..55cbfd1e109bc 100644
--- a/sys/boot/forth/menu.4th.8
+++ b/sys/boot/forth/menu.4th.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 18, 2011
+.Dd Aug 29, 2011
.Dt MENU.4TH 8
.Os
.Sh NAME
@@ -96,11 +96,15 @@ will wait before executing
by default) unless a key is pressed.
If set to
.Dq Li NO
-(case-insensitive) or
-.Dq Li -1 ,
+(case-insensitive)
.Ic menu-display
will wait for user input and never execute
.Ic menu_timeout_command .
+If set to
+.Dq Li -1 ,
+.Ic menu-display
+will boot immediately, preventing both interruption of the autoboot process and
+escaping to the loader prompt.
Default is
.Dq Li 10 .
See
diff --git a/sys/boot/i386/gptboot/Makefile b/sys/boot/i386/gptboot/Makefile
index 5642220a34082..48a6d590c8c88 100644
--- a/sys/boot/i386/gptboot/Makefile
+++ b/sys/boot/i386/gptboot/Makefile
@@ -20,12 +20,7 @@ GPTBOOT_UFS?= UFS1_AND_UFS2
#GPTBOOT_UFS?= UFS1_ONLY
CFLAGS= -DBOOTPROG=\"gptboot\" \
- -Os \
- -fno-guess-branch-probability \
- -fomit-frame-pointer \
- -fno-unit-at-a-time \
- -mno-align-long-strings \
- -mrtd \
+ -O1 \
-DGPT \
-D${GPTBOOT_UFS} \
-DSIOPRT=${BOOT_COMCONSOLE_PORT} \
diff --git a/sys/boot/i386/gptzfsboot/Makefile b/sys/boot/i386/gptzfsboot/Makefile
index f0ee578ce38ca..2067162a8cd3d 100644
--- a/sys/boot/i386/gptzfsboot/Makefile
+++ b/sys/boot/i386/gptzfsboot/Makefile
@@ -17,12 +17,7 @@ ORG1= 0x7c00
ORG2= 0x0
CFLAGS= -DBOOTPROG=\"gptzfsboot\" \
- -Os \
- -fno-guess-branch-probability \
- -fomit-frame-pointer \
- -fno-unit-at-a-time \
- -mno-align-long-strings \
- -mrtd \
+ -O1 \
-DGPT -DBOOT2 \
-DSIOPRT=${BOOT_COMCONSOLE_PORT} \
-DSIOFMT=${B2SIOFMT} \
diff --git a/sys/boot/i386/zfsboot/Makefile b/sys/boot/i386/zfsboot/Makefile
index 8caff2790a663..024fa258583a5 100644
--- a/sys/boot/i386/zfsboot/Makefile
+++ b/sys/boot/i386/zfsboot/Makefile
@@ -15,12 +15,7 @@ ORG1= 0x7c00
ORG2= 0x2000
CFLAGS= -DBOOTPROG=\"zfsboot\" \
- -Os \
- -fno-guess-branch-probability \
- -fomit-frame-pointer \
- -fno-unit-at-a-time \
- -mno-align-long-strings \
- -mrtd \
+ -O1 \
-DBOOT2 \
-DSIOPRT=${BOOT_COMCONSOLE_PORT} \
-DSIOFMT=${B2SIOFMT} \
@@ -85,20 +80,10 @@ zfsboot.bin: zfsboot.out
zfsboot.out: ${BTXCRT} zfsboot.o sio.o drv.o cons.o util.o
${LD} ${LDFLAGS} -Ttext ${ORG2} -o ${.TARGET} ${.ALLSRC} ${LIBSTAND}
-zfsboot.o: zfsboot.s
-.if ${CC:T:Mclang} == "clang"
- ${CC} ${ACFLAGS} -c zfsboot.s
-.endif
-
SRCS= zfsboot.c
-zfsboot.s: zfsboot.c ${.CURDIR}/../../zfs/zfsimpl.c
- ${CC} ${CFLAGS} -S -o zfsboot.s.tmp ${.CURDIR}/zfsboot.c
- sed -e '/align/d' -e '/nop/d' < zfsboot.s.tmp > zfsboot.s
- rm -f zfsboot.s.tmp
-
.if ${MACHINE_CPUARCH} == "amd64"
-beforedepend zfsboot.s: machine
+beforedepend zfsboot.o: machine
CLEANFILES+= machine
machine:
ln -sf ${.CURDIR}/../../../i386/include machine
diff --git a/sys/boot/powerpc/ps3/Makefile b/sys/boot/powerpc/ps3/Makefile
index 0f0b7829a709f..0dee5f4c7a8db 100644
--- a/sys/boot/powerpc/ps3/Makefile
+++ b/sys/boot/powerpc/ps3/Makefile
@@ -10,7 +10,8 @@ INSTALLFLAGS= -b
# Architecture-specific loader code
SRCS= start.S conf.c metadata.c vers.c main.c devicename.c ppc64_elf_freebsd.c
-SRCS+= lv1call.S ps3cons.c font.h ps3mmu.c ps3net.c ps3repo.c ps3stor.c ps3disk.c
+SRCS+= lv1call.S ps3cons.c font.h ps3mmu.c ps3net.c ps3repo.c \
+ ps3stor.c ps3disk.c ps3cdrom.c
SRCS+= ucmpdi2.c
LOADER_DISK_SUPPORT?= yes
diff --git a/sys/boot/powerpc/ps3/conf.c b/sys/boot/powerpc/ps3/conf.c
index 200fc7f29c696..3a5ae4c41f028 100644
--- a/sys/boot/powerpc/ps3/conf.c
+++ b/sys/boot/powerpc/ps3/conf.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#endif
extern struct devsw ps3disk;
+extern struct devsw ps3cdrom;
/*
* We could use linker sets for some or all of these, but
@@ -47,7 +48,10 @@ extern struct devsw ps3disk;
/* Exported for libstand */
struct devsw *devsw[] = {
-#if defined(LOADER_DISK_SUPPORT) || defined(LOADER_CD9660_SUPPORT)
+#if defined(LOADER_CD9660_SUPPORT)
+ &ps3cdrom,
+#endif
+#if defined(LOADER_DISK_SUPPORT)
&ps3disk,
#endif
#if defined(LOADER_NET_SUPPORT)
diff --git a/sys/boot/powerpc/ps3/devicename.c b/sys/boot/powerpc/ps3/devicename.c
index c46bc8928047a..041f853986d58 100644
--- a/sys/boot/powerpc/ps3/devicename.c
+++ b/sys/boot/powerpc/ps3/devicename.c
@@ -157,6 +157,7 @@ ps3_parsedev(struct ps3_devdesc **dev, const char *devspec, const char **path)
break;
case DEVT_NET:
+ case DEVT_CD:
/*
* PS3 only has one network interface (well, two, but
* netbooting over wireless is not something I'm going
@@ -213,6 +214,7 @@ ps3_fmtdev(void *vdev)
break;
case DEVT_NET:
+ case DEVT_CD:
sprintf(buf, "%s%d:", dev->d_dev->dv_name, dev->d_unit);
break;
}
diff --git a/sys/boot/powerpc/ps3/lv1call.S b/sys/boot/powerpc/ps3/lv1call.S
index 1c1e28ee0bde7..a399a9c3bbf62 100644
--- a/sys/boot/powerpc/ps3/lv1call.S
+++ b/sys/boot/powerpc/ps3/lv1call.S
@@ -307,14 +307,8 @@ lv1_storage_read:
sldi %r6,%r9,32
clrldi %r7,%r10,32
or %r6,%r6,%r7
- lwz %r7,8(%r1)
- lwz %r8,12(%r1)
- sldi %r7,%r7,32
- or %r7,%r7,%r8
- lwz %r8,16(%r1)
- lwz %r9,20(%r1)
- sldi %r8,%r8,32
- or %r8,%r8,%r9
+ ld %r7,8(%r1)
+ ld %r8,16(%r1)
li %r11,245
hc
diff --git a/sys/boot/powerpc/ps3/lv1call.h b/sys/boot/powerpc/ps3/lv1call.h
index da47afb4dad86..fb8044825bd08 100644
--- a/sys/boot/powerpc/ps3/lv1call.h
+++ b/sys/boot/powerpc/ps3/lv1call.h
@@ -69,12 +69,12 @@ int lv1_net_stop_tx_dma(int bus, int dev, int);
int lv1_net_stop_rx_dma(int bus, int dev, int);
int lv1_get_repository_node_value(uint64_t lpar_id, uint64_t n1, uint64_t n2,
- uint64_t n3, uint64_t n4, uint64_t *v1, uint64_t *v2);
+ uint64_t n3, uint64_t n4, uint64_t *v1, uint64_t *v2);
-int lv1_storage_read(uint64_t dev_id, uint64_t region_id,
- uint64_t start_sector, uint64_t sector_count,
- uint64_t flags, uint64_t buf, uint64_t *tag);
-int lv1_storage_check_async_status(uint64_t dev_id, uint64_t tag, uint64_t *status);
+int lv1_storage_read(uint64_t dev_id, uint64_t region_id, uint64_t start_sector,
+ uint64_t sector_count, uint64_t flags, uint64_t buf, uint64_t *tag);
+int lv1_storage_check_async_status(uint64_t dev_id, uint64_t tag,
+ uint64_t *status);
#endif
diff --git a/sys/boot/powerpc/ps3/main.c b/sys/boot/powerpc/ps3/main.c
index db808adba289b..64bd7e9f9a245 100644
--- a/sys/boot/powerpc/ps3/main.c
+++ b/sys/boot/powerpc/ps3/main.c
@@ -92,11 +92,17 @@ main(void)
}
}
- printf("\nDevice: %s\n", devsw[i]->dv_name);
-
currdev.d_dev = devsw[i];
currdev.d_type = currdev.d_dev->dv_type;
+ if (strcmp(devsw[i]->dv_name, "cd") == 0) {
+ f.f_devdata = &currdev;
+ currdev.d_unit = 0;
+
+ if (devsw[i]->dv_open(&f, &currdev) == 0)
+ break;
+ }
+
if (strcmp(devsw[i]->dv_name, "disk") == 0) {
f.f_devdata = &currdev;
currdev.d_unit = 3;
@@ -113,6 +119,8 @@ main(void)
if (devsw[i] == NULL)
panic("No boot device found!");
+ else
+ printf("Boot device: %s\n", devsw[i]->dv_name);
/*
* Get timebase at boot.
diff --git a/sys/boot/powerpc/ps3/ps3cdrom.c b/sys/boot/powerpc/ps3/ps3cdrom.c
new file mode 100644
index 0000000000000..843ecd56052f3
--- /dev/null
+++ b/sys/boot/powerpc/ps3/ps3cdrom.c
@@ -0,0 +1,154 @@
+/*-
+ * Copyright (C) 2011 glevand <geoffrey.levand@mail.ru>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/endian.h>
+#include <machine/stdarg.h>
+#include <stand.h>
+
+#include "bootstrap.h"
+#include "ps3bus.h"
+#include "ps3devdesc.h"
+#include "ps3stor.h"
+
+#define dev_printf(dev, fmt, args...) \
+ printf("%s%d: " fmt "\n", dev->d_dev->dv_name, dev->d_unit, ##args)
+
+#ifdef CD_DEBUG
+#define DEBUG(fmt, args...) printf("%s:%d: " fmt "\n", __func__, __LINE__, ##args)
+#else
+#define DEBUG(fmt, args...)
+#endif
+
+static int ps3cdrom_init(void);
+static int ps3cdrom_strategy(void *devdata, int flag, daddr_t dblk,
+ size_t size, char *buf, size_t *rsize);
+static int ps3cdrom_open(struct open_file *f, ...);
+static int ps3cdrom_close(struct open_file *f);
+static void ps3cdrom_print(int verbose);
+
+struct devsw ps3cdrom = {
+ "cd",
+ DEVT_CD,
+ ps3cdrom_init,
+ ps3cdrom_strategy,
+ ps3cdrom_open,
+ ps3cdrom_close,
+ noioctl,
+ ps3cdrom_print,
+};
+
+static struct ps3_stordev stor_dev;
+
+static int ps3cdrom_init(void)
+{
+ int err;
+
+ err = ps3stor_setup(&stor_dev, PS3_DEV_TYPE_STOR_CDROM);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+static int ps3cdrom_strategy(void *devdata, int flag, daddr_t dblk,
+ size_t size, char *buf, size_t *rsize)
+{
+ struct ps3_devdesc *dev = (struct ps3_devdesc *) devdata;
+ int err;
+
+ DEBUG("d_unit=%u dblk=%llu size=%u", dev->d_unit, dblk, size);
+
+ if (flag != F_READ) {
+ dev_printf(dev, "write operation is not supported!");
+ return EROFS;
+ }
+
+ if (dblk % (stor_dev.sd_blksize / DEV_BSIZE) != 0)
+ return EINVAL;
+
+ dblk /= (stor_dev.sd_blksize / DEV_BSIZE);
+
+ if (size % stor_dev.sd_blksize) {
+ dev_printf(dev,
+ "size=%u is not multiple of device block size=%llu", size,
+ stor_dev.sd_blksize);
+ return EINVAL;
+ }
+
+ if (rsize)
+ *rsize = 0;
+
+ err = ps3stor_read_sectors(&stor_dev, dev->d_unit, dblk,
+ size / stor_dev.sd_blksize, 0, buf);
+
+ if (!err && rsize)
+ *rsize = size;
+
+ if (err)
+ dev_printf(dev,
+ "read operation failed dblk=%llu size=%d err=%d", dblk,
+ size, err);
+
+ return err;
+}
+
+static int ps3cdrom_open(struct open_file *f, ...)
+{
+ char buf[2048];
+ va_list ap;
+ struct ps3_devdesc *dev;
+ int err;
+
+ va_start(ap, f);
+ dev = va_arg(ap, struct ps3_devdesc *);
+ va_end(ap);
+
+ if (dev->d_unit > 0) {
+ dev_printf(dev, "attempt to open nonexistent disk");
+ return ENXIO;
+ }
+
+ err = ps3stor_read_sectors(&stor_dev, dev->d_unit, 16, 1, 0, buf);
+ if (err)
+ return EIO;
+
+ /* Do not attach if not ISO9660 (workaround for buggy firmware) */
+ if (memcmp(buf, "\001CD001", 6) != 0)
+ return EIO;
+
+ return 0;
+}
+
+static int ps3cdrom_close(struct open_file *f)
+{
+ return 0;
+}
+
+static void ps3cdrom_print(int verbose)
+{
+}
diff --git a/sys/boot/powerpc/ps3/ps3stor.c b/sys/boot/powerpc/ps3/ps3stor.c
index 667b39ca5e988..bbfc56a7ae2ac 100644
--- a/sys/boot/powerpc/ps3/ps3stor.c
+++ b/sys/boot/powerpc/ps3/ps3stor.c
@@ -52,35 +52,39 @@ int ps3stor_setup(struct ps3_stordev *sd, int type)
if (err)
goto out;
- err = ps3repo_read_bus_dev_id(sd->sd_busidx, sd->sd_devidx, &sd->sd_devid);
+ err = ps3repo_read_bus_dev_id(sd->sd_busidx, sd->sd_devidx,
+ &sd->sd_devid);
if (err)
goto out;
- err = ps3repo_read_bus_dev_blk_size(sd->sd_busidx, sd->sd_devidx, &sd->sd_blksize);
+ err = ps3repo_read_bus_dev_blk_size(sd->sd_busidx, sd->sd_devidx,
+ &sd->sd_blksize);
if (err)
goto out;
- err = ps3repo_read_bus_dev_nblocks(sd->sd_busidx, sd->sd_devidx, &sd->sd_nblocks);
+ err = ps3repo_read_bus_dev_nblocks(sd->sd_busidx, sd->sd_devidx,
+ &sd->sd_nblocks);
if (err)
goto out;
- err = ps3repo_read_bus_dev_nregs(sd->sd_busidx, sd->sd_devidx, &sd->sd_nregs);
+ err = ps3repo_read_bus_dev_nregs(sd->sd_busidx, sd->sd_devidx,
+ &sd->sd_nregs);
if (err)
goto out;
for (i = 0; i < sd->sd_nregs; i++) {
- err = ps3repo_read_bus_dev_reg_id(sd->sd_busidx, sd->sd_devidx, i,
- &sd->sd_regs[i].sr_id);
+ err = ps3repo_read_bus_dev_reg_id(sd->sd_busidx, sd->sd_devidx,
+ i, &sd->sd_regs[i].sr_id);
if (err)
goto out;
- err = ps3repo_read_bus_dev_reg_start(sd->sd_busidx, sd->sd_devidx, i,
- &sd->sd_regs[i].sr_start);
+ err = ps3repo_read_bus_dev_reg_start(sd->sd_busidx,
+ sd->sd_devidx, i, &sd->sd_regs[i].sr_start);
if (err)
goto out;
- err = ps3repo_read_bus_dev_reg_size(sd->sd_busidx, sd->sd_devidx, i,
- &sd->sd_regs[i].sr_size);
+ err = ps3repo_read_bus_dev_reg_size(sd->sd_busidx,
+ sd->sd_devidx, i, &sd->sd_regs[i].sr_size);
if (err)
goto out;
}
@@ -109,19 +113,20 @@ out:
return err;
}
+static char dma_buf[2048] __aligned(2048);
+
int ps3stor_read_sectors(struct ps3_stordev *sd, int regidx,
uint64_t start_sector, uint64_t sector_count, uint64_t flags, char *buf)
{
#define MIN(a, b) ((a) <= (b) ? (a) : (b))
-#define BOUNCE_SECTORS 4
+#define BOUNCE_SECTORS (sizeof(dma_buf) / sd->sd_blksize)
#define ASYNC_STATUS_POLL_PERIOD 100 /* microseconds */
struct ps3_storreg *reg = &sd->sd_regs[regidx];
- char dma_buf[sd->sd_blksize * BOUNCE_SECTORS];
uint64_t nleft, nread, nsectors;
uint64_t tag, status;
unsigned int timeout;
- int err;
+ int err = 0;
nleft = sector_count;
nread = 0;
@@ -129,8 +134,9 @@ int ps3stor_read_sectors(struct ps3_stordev *sd, int regidx,
while (nleft) {
nsectors = MIN(nleft, BOUNCE_SECTORS);
- err = lv1_storage_read(sd->sd_devid, reg->sr_id, start_sector + nread, nsectors,
- flags, (uint32_t) dma_buf, &tag);
+ err = lv1_storage_read(sd->sd_devid, reg->sr_id,
+ start_sector + nread, nsectors, flags, (uint32_t)dma_buf,
+ &tag);
if (err)
return err;
@@ -140,7 +146,8 @@ int ps3stor_read_sectors(struct ps3_stordev *sd, int regidx,
if (timeout < ASYNC_STATUS_POLL_PERIOD)
return ETIMEDOUT;
- err = lv1_storage_check_async_status(sd->sd_devid, tag, &status);
+ err = lv1_storage_check_async_status(sd->sd_devid, tag,
+ &status);
if (!err && !status)
break;
@@ -148,12 +155,16 @@ int ps3stor_read_sectors(struct ps3_stordev *sd, int regidx,
timeout -= ASYNC_STATUS_POLL_PERIOD;
}
- memcpy(buf + nread * sd->sd_blksize, (u_char *) dma_buf, nsectors * sd->sd_blksize);
+ if (status != 0)
+ return EIO;
+
+ memcpy(buf + nread * sd->sd_blksize, (u_char *)dma_buf,
+ nsectors * sd->sd_blksize);
nread += nsectors;
nleft -= nsectors;
}
- return 0;
+ return err;
#undef MIN
#undef BOUNCE_SECTORS
diff --git a/sys/boot/zfs/zfstest.c b/sys/boot/zfs/zfstest.c
index 303ef5f08efed..3e32da57781ee 100644
--- a/sys/boot/zfs/zfstest.c
+++ b/sys/boot/zfs/zfstest.c
@@ -30,6 +30,7 @@
#include <sys/param.h>
#include <sys/queue.h>
+#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
@@ -37,14 +38,14 @@
#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>
-#include <errno.h>
+#include <unistd.h>
#define NBBY 8
void
pager_output(const char *line)
{
- printf("%s", line);
+ fprintf(stderr, "%s", line);
}
#include "zfsimpl.c"
@@ -55,8 +56,8 @@ vdev_read(vdev_t *vdev, void *priv, off_t off, void *buf, size_t bytes)
int fd = *(int *) priv;
if (pread(fd, buf, bytes, off) != bytes)
- return -1;
- return 0;
+ return (-1);
+ return (0);
}
static int
@@ -69,10 +70,10 @@ zfs_read(spa_t *spa, dnode_phys_t *dn, void *buf, size_t size, off_t off)
n = size;
if (off + n > zp->zp_size)
n = zp->zp_size - off;
-
+
rc = dnode_read(spa, dn, off, buf, n);
if (rc)
- return (rc);
+ return (-rc);
return (n);
}
@@ -80,22 +81,24 @@ zfs_read(spa_t *spa, dnode_phys_t *dn, void *buf, size_t size, off_t off)
int
main(int argc, char** argv)
{
- int i, n, off;
- int fd[99];
- spa_t *spa;
- dnode_phys_t dn;
char buf[512];
+ int fd[100];
+ struct stat sb;
+ dnode_phys_t dn;
+ spa_t *spa;
+ int i, n, off;
zfs_init();
if (argc == 1) {
static char *av[] = {
- "zfstest", "/dev/da0p2", "/dev/da1p2", "/dev/da2p2",
+ "zfstest", "COPYRIGHT",
+ "/dev/da0p2", "/dev/da1p2", "/dev/da2p2",
NULL,
};
- argc = 4;
+ argc = 5;
argv = av;
}
- for (i = 1; i < argc; i++) {
+ for (i = 2; i < argc; i++) {
fd[i] = open(argv[i], O_RDONLY);
if (fd[i] < 0)
continue;
@@ -105,16 +108,37 @@ main(int argc, char** argv)
spa_all_status();
spa = STAILQ_FIRST(&zfs_pools);
- if (!spa || zfs_mount_pool(spa))
+ if (spa == NULL) {
+ fprintf(stderr, "no pools\n");
exit(1);
+ }
- if (zfs_lookup(spa, "zfs.c", &dn))
+ if (zfs_mount_pool(spa)) {
+ fprintf(stderr, "can't mount pool\n");
exit(1);
+ }
+
+ if (zfs_lookup(spa, argv[1], &dn)) {
+ fprintf(stderr, "can't lookup\n");
+ exit(1);
+ }
+
+ if (zfs_dnode_stat(spa, &dn, &sb)) {
+ fprintf(stderr, "can't stat\n");
+ exit(1);
+ }
+
off = 0;
do {
n = zfs_read(spa, &dn, buf, 512, off);
+ if (n < 0) {
+ fprintf(stderr, "zfs_read failed\n");
+ exit(1);
+ }
write(1, buf, n);
off += n;
- } while (n == 512);
+ } while (off < sb.st_size);
+
+ return (0);
}
diff --git a/sys/cam/ata/ata_da.c b/sys/cam/ata/ata_da.c
index ed0dbef444d74..b1d5ea83eb571 100644
--- a/sys/cam/ata/ata_da.c
+++ b/sys/cam/ata/ata_da.c
@@ -69,6 +69,7 @@ __FBSDID("$FreeBSD$");
#define ATA_MAX_28BIT_LBA 268435455UL
typedef enum {
+ ADA_STATE_RAHEAD,
ADA_STATE_WCACHE,
ADA_STATE_NORMAL
} ada_state;
@@ -94,7 +95,8 @@ typedef enum {
} ada_quirks;
typedef enum {
- ADA_CCB_WCACHE = 0x01,
+ ADA_CCB_RAHEAD = 0x01,
+ ADA_CCB_WCACHE = 0x02,
ADA_CCB_BUFFER_IO = 0x03,
ADA_CCB_WAITING = 0x04,
ADA_CCB_DUMP = 0x05,
@@ -132,6 +134,7 @@ struct ada_softc {
int outstanding_cmds;
int trim_max_ranges;
int trim_running;
+ int read_ahead;
int write_cache;
#ifdef ADA_TEST_FAILURE
int force_read_error;
@@ -294,10 +297,19 @@ static void adaresume(void *arg);
#define ADA_DEFAULT_SPINDOWN_SUSPEND 1
#endif
+#ifndef ADA_DEFAULT_READ_AHEAD
+#define ADA_DEFAULT_READ_AHEAD 1
+#endif
+
#ifndef ADA_DEFAULT_WRITE_CACHE
#define ADA_DEFAULT_WRITE_CACHE 1
#endif
+#define ADA_RA (softc->read_ahead >= 0 ? \
+ softc->read_ahead : ada_read_ahead)
+#define ADA_WC (softc->write_cache >= 0 ? \
+ softc->write_cache : ada_write_cache)
+
/*
* Most platforms map firmware geometry to actual, but some don't. If
* not overridden, default to nothing.
@@ -312,6 +324,7 @@ static int ada_default_timeout = ADA_DEFAULT_TIMEOUT;
static int ada_send_ordered = ADA_DEFAULT_SEND_ORDERED;
static int ada_spindown_shutdown = ADA_DEFAULT_SPINDOWN_SHUTDOWN;
static int ada_spindown_suspend = ADA_DEFAULT_SPINDOWN_SUSPEND;
+static int ada_read_ahead = ADA_DEFAULT_READ_AHEAD;
static int ada_write_cache = ADA_DEFAULT_WRITE_CACHE;
SYSCTL_NODE(_kern_cam, OID_AUTO, ada, CTLFLAG_RD, 0,
@@ -334,6 +347,9 @@ TUNABLE_INT("kern.cam.ada.spindown_shutdown", &ada_spindown_shutdown);
SYSCTL_INT(_kern_cam_ada, OID_AUTO, spindown_suspend, CTLFLAG_RW,
&ada_spindown_suspend, 0, "Spin down upon suspend");
TUNABLE_INT("kern.cam.ada.spindown_suspend", &ada_spindown_suspend);
+SYSCTL_INT(_kern_cam_ada, OID_AUTO, read_ahead, CTLFLAG_RW,
+ &ada_read_ahead, 0, "Enable disk read-ahead");
+TUNABLE_INT("kern.cam.ada.read_ahead", &ada_read_ahead);
SYSCTL_INT(_kern_cam_ada, OID_AUTO, write_cache, CTLFLAG_RW,
&ada_write_cache, 0, "Enable disk write cache");
TUNABLE_INT("kern.cam.ada.write_cache", &ada_write_cache);
@@ -425,7 +441,8 @@ adaclose(struct disk *dp)
softc = (struct ada_softc *)periph->softc;
/* We only sync the cache if the drive is capable of it. */
- if (softc->flags & ADA_FLAG_CAN_FLUSHCACHE) {
+ if ((softc->flags & ADA_FLAG_CAN_FLUSHCACHE) != 0 &&
+ (softc->flags & ADA_FLAG_PACK_INVALID) == 0) {
ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
cam_fill_ataio(&ccb->ataio,
@@ -467,12 +484,20 @@ static void
adaschedule(struct cam_periph *periph)
{
struct ada_softc *softc = (struct ada_softc *)periph->softc;
+ uint32_t prio;
+ /* Check if cam_periph_getccb() was called. */
+ prio = periph->immediate_priority;
+
+ /* Check if we have more work to do. */
if (bioq_first(&softc->bio_queue) ||
(!softc->trim_running && bioq_first(&softc->trim_queue))) {
- /* Have more work to do, so ensure we stay scheduled */
- xpt_schedule(periph, CAM_PRIORITY_NORMAL);
+ prio = CAM_PRIORITY_NORMAL;
}
+
+ /* Schedule CCB if any of above is true. */
+ if (prio != CAM_PRIORITY_NONE)
+ xpt_schedule(periph, prio);
}
/*
@@ -736,16 +761,19 @@ adaasync(void *callback_arg, u_int32_t code,
softc = (struct ada_softc *)periph->softc;
cam_periph_async(periph, code, path, arg);
- if (ada_write_cache < 0 && softc->write_cache < 0)
- break;
if (softc->state != ADA_STATE_NORMAL)
break;
xpt_setup_ccb(&cgd.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
cgd.ccb_h.func_code = XPT_GDEV_TYPE;
xpt_action((union ccb *)&cgd);
- if ((cgd.ident_data.support.command1 & ATA_SUPPORT_WRITECACHE) == 0)
- break;
- softc->state = ADA_STATE_WCACHE;
+ if (ADA_RA >= 0 &&
+ cgd.ident_data.support.command1 & ATA_SUPPORT_LOOKAHEAD)
+ softc->state = ADA_STATE_RAHEAD;
+ else if (ADA_WC >= 0 &&
+ cgd.ident_data.support.command1 & ATA_SUPPORT_WRITECACHE)
+ softc->state = ADA_STATE_WCACHE;
+ else
+ break;
cam_periph_acquire(periph);
cam_freeze_devq_arg(periph->path,
RELSIM_RELEASE_RUNLEVEL, CAM_RL_DEV + 1);
@@ -788,6 +816,9 @@ adasysctlinit(void *context, int pending)
}
SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
+ OID_AUTO, "read_ahead", CTLFLAG_RW | CTLFLAG_MPSAFE,
+ &softc->read_ahead, 0, "Enable disk read ahead.");
+ SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
OID_AUTO, "write_cache", CTLFLAG_RW | CTLFLAG_MPSAFE,
&softc->write_cache, 0, "Enable disk write cache.");
#ifdef ADA_TEST_FAILURE
@@ -921,6 +952,10 @@ adaregister(struct cam_periph *periph, void *arg)
quirks = softc->quirks;
TUNABLE_INT_FETCH(announce_buf, &quirks);
softc->quirks = quirks;
+ softc->read_ahead = -1;
+ snprintf(announce_buf, sizeof(announce_buf),
+ "kern.cam.ada.%d.read_ahead", periph->unit_number);
+ TUNABLE_INT_FETCH(announce_buf, &softc->read_ahead);
softc->write_cache = -1;
snprintf(announce_buf, sizeof(announce_buf),
"kern.cam.ada.%d.write_cache", periph->unit_number);
@@ -1043,7 +1078,14 @@ adaregister(struct cam_periph *periph, void *arg)
(ADA_DEFAULT_TIMEOUT * hz) / ADA_ORDEREDTAG_INTERVAL,
adasendorderedtag, softc);
- if ((ada_write_cache >= 0 || softc->write_cache >= 0) &&
+ if (ADA_RA >= 0 &&
+ cgd->ident_data.support.command1 & ATA_SUPPORT_LOOKAHEAD) {
+ softc->state = ADA_STATE_RAHEAD;
+ cam_periph_acquire(periph);
+ cam_freeze_devq_arg(periph->path,
+ RELSIM_RELEASE_RUNLEVEL, CAM_RL_DEV + 1);
+ xpt_schedule(periph, CAM_PRIORITY_DEV);
+ } else if (ADA_WC >= 0 &&
cgd->ident_data.support.command1 & ATA_SUPPORT_WRITECACHE) {
softc->state = ADA_STATE_WCACHE;
cam_periph_acquire(periph);
@@ -1316,8 +1358,19 @@ out:
adaschedule(periph);
break;
}
+ case ADA_STATE_RAHEAD:
case ADA_STATE_WCACHE:
{
+ if (softc->flags & ADA_FLAG_PACK_INVALID) {
+ softc->state = ADA_STATE_NORMAL;
+ xpt_release_ccb(start_ccb);
+ cam_release_devq(periph->path,
+ RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_DEV + 1, FALSE);
+ adaschedule(periph);
+ cam_periph_release_locked(periph);
+ return;
+ }
+
cam_fill_ataio(ataio,
1,
adadone,
@@ -1327,10 +1380,15 @@ out:
0,
ada_default_timeout*1000);
- ata_28bit_cmd(ataio, ATA_SETFEATURES, (softc->write_cache > 0 ||
- (softc->write_cache < 0 && ada_write_cache)) ?
- ATA_SF_ENAB_WCACHE : ATA_SF_DIS_WCACHE, 0, 0);
- start_ccb->ccb_h.ccb_state = ADA_CCB_WCACHE;
+ if (softc->state == ADA_STATE_RAHEAD) {
+ ata_28bit_cmd(ataio, ATA_SETFEATURES, ADA_RA ?
+ ATA_SF_ENAB_RCACHE : ATA_SF_DIS_RCACHE, 0, 0);
+ start_ccb->ccb_h.ccb_state = ADA_CCB_RAHEAD;
+ } else {
+ ata_28bit_cmd(ataio, ATA_SETFEATURES, ADA_WC ?
+ ATA_SF_ENAB_WCACHE : ATA_SF_DIS_WCACHE, 0, 0);
+ start_ccb->ccb_h.ccb_state = ADA_CCB_WCACHE;
+ }
xpt_action(start_ccb);
break;
}
@@ -1342,6 +1400,7 @@ adadone(struct cam_periph *periph, union ccb *done_ccb)
{
struct ada_softc *softc;
struct ccb_ataio *ataio;
+ struct ccb_getdev *cgd;
softc = (struct ada_softc *)periph->softc;
ataio = &done_ccb->ataio;
@@ -1361,7 +1420,8 @@ adadone(struct cam_periph *periph, union ccb *done_ccb)
return;
}
if (error != 0) {
- if (error == ENXIO) {
+ if (error == ENXIO &&
+ (softc->flags & ADA_FLAG_PACK_INVALID) == 0) {
/*
* Catastrophic error. Mark our pack as
* invalid.
@@ -1421,6 +1481,47 @@ adadone(struct cam_periph *periph, union ccb *done_ccb)
biodone(bp);
break;
}
+ case ADA_CCB_RAHEAD:
+ {
+ if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ if (adaerror(done_ccb, 0, 0) == ERESTART) {
+ return;
+ } else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
+ cam_release_devq(done_ccb->ccb_h.path,
+ /*relsim_flags*/0,
+ /*reduction*/0,
+ /*timeout*/0,
+ /*getcount_only*/0);
+ }
+ }
+
+ /*
+ * Since our peripheral may be invalidated by an error
+ * above or an external event, we must release our CCB
+ * before releasing the reference on the peripheral.
+ * The peripheral will only go away once the last reference
+ * is removed, and we need it around for the CCB release
+ * operation.
+ */
+ cgd = (struct ccb_getdev *)done_ccb;
+ xpt_setup_ccb(&cgd->ccb_h, periph->path, CAM_PRIORITY_NORMAL);
+ cgd->ccb_h.func_code = XPT_GDEV_TYPE;
+ xpt_action((union ccb *)cgd);
+ if (ADA_WC >= 0 &&
+ cgd->ident_data.support.command1 & ATA_SUPPORT_WRITECACHE) {
+ softc->state = ADA_STATE_WCACHE;
+ xpt_release_ccb(done_ccb);
+ xpt_schedule(periph, CAM_PRIORITY_DEV);
+ return;
+ }
+ softc->state = ADA_STATE_NORMAL;
+ xpt_release_ccb(done_ccb);
+ cam_release_devq(periph->path,
+ RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_DEV + 1, FALSE);
+ adaschedule(periph);
+ cam_periph_release_locked(periph);
+ return;
+ }
case ADA_CCB_WCACHE:
{
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c
index f63077220e66f..67c2d01125d67 100644
--- a/sys/cam/cam_periph.c
+++ b/sys/cam/cam_periph.c
@@ -1550,7 +1550,8 @@ camperiphscsisenseerror(union ccb *ccb, cam_flags camflags,
* make sure we actually have retries available.
*/
if ((err_action & SSQ_DECREMENT_COUNT) != 0) {
- if (ccb->ccb_h.retry_count > 0)
+ if (ccb->ccb_h.retry_count > 0 &&
+ (periph->flags & CAM_PERIPH_INVALID) == 0)
ccb->ccb_h.retry_count--;
else {
*action_string = "Retries exhausted";
@@ -1718,6 +1719,7 @@ int
cam_periph_error(union ccb *ccb, cam_flags camflags,
u_int32_t sense_flags, union ccb *save_ccb)
{
+ struct cam_periph *periph;
const char *action_string;
cam_status status;
int frozen;
@@ -1725,7 +1727,8 @@ cam_periph_error(union ccb *ccb, cam_flags camflags,
int openings;
u_int32_t relsim_flags;
u_int32_t timeout = 0;
-
+
+ periph = xpt_path_periph(ccb->ccb_h.path);
action_string = NULL;
status = ccb->ccb_h.status;
frozen = (status & CAM_DEV_QFRZN) != 0;
@@ -1787,9 +1790,9 @@ cam_periph_error(union ccb *ccb, cam_flags camflags,
xpt_print(ccb->ccb_h.path, "Data overrun\n");
printed++;
}
- error = EIO; /* we have to kill the command */
/* decrement the number of retries */
- if (ccb->ccb_h.retry_count > 0) {
+ if (ccb->ccb_h.retry_count > 0 &&
+ (periph->flags & CAM_PERIPH_INVALID) == 0) {
ccb->ccb_h.retry_count--;
error = ERESTART;
} else {
@@ -1808,7 +1811,8 @@ cam_periph_error(union ccb *ccb, cam_flags camflags,
struct cam_path *newpath;
if ((camflags & CAM_RETRY_SELTO) != 0) {
- if (ccb->ccb_h.retry_count > 0) {
+ if (ccb->ccb_h.retry_count > 0 &&
+ (periph->flags & CAM_PERIPH_INVALID) == 0) {
ccb->ccb_h.retry_count--;
error = ERESTART;
@@ -1826,10 +1830,11 @@ cam_periph_error(union ccb *ccb, cam_flags camflags,
timeout = periph_selto_delay;
break;
}
+ action_string = "Retries exhausted";
}
error = ENXIO;
/* Should we do more if we can't create the path?? */
- if (xpt_create_path(&newpath, xpt_path_periph(ccb->ccb_h.path),
+ if (xpt_create_path(&newpath, periph,
xpt_path_path_id(ccb->ccb_h.path),
xpt_path_target_id(ccb->ccb_h.path),
CAM_LUN_WILDCARD) != CAM_REQ_CMP)
@@ -1874,11 +1879,16 @@ cam_periph_error(union ccb *ccb, cam_flags camflags,
/* FALLTHROUGH */
case CAM_REQUEUE_REQ:
/* Unconditional requeue */
- error = ERESTART;
if (bootverbose && printed == 0) {
xpt_print(ccb->ccb_h.path, "Request requeued\n");
printed++;
}
+ if ((periph->flags & CAM_PERIPH_INVALID) == 0)
+ error = ERESTART;
+ else {
+ action_string = "Retries exhausted";
+ error = EIO;
+ }
break;
case CAM_RESRC_UNAVAIL:
/* Wait a bit for the resource shortage to abate. */
@@ -1893,7 +1903,8 @@ cam_periph_error(union ccb *ccb, cam_flags camflags,
/* FALLTHROUGH */
default:
/* decrement the number of retries */
- if (ccb->ccb_h.retry_count > 0) {
+ if (ccb->ccb_h.retry_count > 0 &&
+ (periph->flags & CAM_PERIPH_INVALID) == 0) {
ccb->ccb_h.retry_count--;
error = ERESTART;
if (bootverbose && printed == 0) {
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
index 013c415d7c7d8..10b89c77b9bec 100644
--- a/sys/cam/cam_xpt.c
+++ b/sys/cam/cam_xpt.c
@@ -3336,8 +3336,10 @@ xpt_create_path_unlocked(struct cam_path **new_path_ptr,
}
}
status = xpt_compile_path(path, periph, path_id, target_id, lun_id);
- if (need_unlock)
+ if (need_unlock) {
CAM_SIM_UNLOCK(bus->sim);
+ xpt_release_bus(bus);
+ }
if (status != CAM_REQ_CMP) {
free(path, M_CAMXPT);
path = NULL;
@@ -3445,6 +3447,38 @@ xpt_free_path(struct cam_path *path)
free(path, M_CAMXPT);
}
+void
+xpt_path_counts(struct cam_path *path, uint32_t *bus_ref,
+ uint32_t *periph_ref, uint32_t *target_ref, uint32_t *device_ref)
+{
+
+ mtx_lock(&xsoftc.xpt_topo_lock);
+ if (bus_ref) {
+ if (path->bus)
+ *bus_ref = path->bus->refcount;
+ else
+ *bus_ref = 0;
+ }
+ mtx_unlock(&xsoftc.xpt_topo_lock);
+ if (periph_ref) {
+ if (path->periph)
+ *periph_ref = path->periph->refcount;
+ else
+ *periph_ref = 0;
+ }
+ if (target_ref) {
+ if (path->target)
+ *target_ref = path->target->refcount;
+ else
+ *target_ref = 0;
+ }
+ if (device_ref) {
+ if (path->device)
+ *device_ref = path->device->refcount;
+ else
+ *device_ref = 0;
+ }
+}
/*
* Return -1 for failure, 0 for exact match, 1 for match with wildcards
@@ -4264,15 +4298,17 @@ static void
xpt_release_bus(struct cam_eb *bus)
{
+ mtx_lock(&xsoftc.xpt_topo_lock);
+ KASSERT(bus->refcount >= 1, ("bus->refcount >= 1"));
if ((--bus->refcount == 0)
&& (TAILQ_FIRST(&bus->et_entries) == NULL)) {
- mtx_lock(&xsoftc.xpt_topo_lock);
TAILQ_REMOVE(&xsoftc.xpt_busses, bus, links);
xsoftc.bus_generation++;
mtx_unlock(&xsoftc.xpt_topo_lock);
cam_sim_release(bus->sim);
free(bus, M_CAMXPT);
- }
+ } else
+ mtx_unlock(&xsoftc.xpt_topo_lock);
}
static struct cam_et *
@@ -4296,7 +4332,9 @@ xpt_alloc_target(struct cam_eb *bus, target_id_t target_id)
* Hold a reference to our parent bus so it
* will not go away before we do.
*/
+ mtx_lock(&xsoftc.xpt_topo_lock);
bus->refcount++;
+ mtx_unlock(&xsoftc.xpt_topo_lock);
/* Insertion sort into our bus's target list */
cur_target = TAILQ_FIRST(&bus->et_entries);
@@ -4317,15 +4355,17 @@ static void
xpt_release_target(struct cam_et *target)
{
- if ((--target->refcount == 0)
- && (TAILQ_FIRST(&target->ed_entries) == NULL)) {
- TAILQ_REMOVE(&target->bus->et_entries, target, links);
- target->bus->generation++;
- xpt_release_bus(target->bus);
- if (target->luns)
- free(target->luns, M_CAMXPT);
- free(target, M_CAMXPT);
- }
+ if (target->refcount == 1) {
+ if (TAILQ_FIRST(&target->ed_entries) == NULL) {
+ TAILQ_REMOVE(&target->bus->et_entries, target, links);
+ target->bus->generation++;
+ xpt_release_bus(target->bus);
+ if (target->luns)
+ free(target->luns, M_CAMXPT);
+ free(target, M_CAMXPT);
+ }
+ } else
+ target->refcount--;
}
static struct cam_ed *
@@ -4422,7 +4462,7 @@ void
xpt_release_device(struct cam_ed *device)
{
- if (--device->refcount == 0) {
+ if (device->refcount == 1) {
struct cam_devq *devq;
if (device->alloc_ccb_entry.pinfo.index != CAM_UNQUEUED_INDEX
@@ -4430,7 +4470,7 @@ xpt_release_device(struct cam_ed *device)
panic("Removing device while still queued for ccbs");
if ((device->flags & CAM_DEV_REL_TIMEOUT_PENDING) != 0)
- callout_stop(&device->callout);
+ callout_stop(&device->callout);
TAILQ_REMOVE(&device->target->ed_entries, device,links);
device->target->generation++;
@@ -4442,7 +4482,8 @@ xpt_release_device(struct cam_ed *device)
cam_ccbq_fini(&device->ccbq);
xpt_release_target(device->target);
free(device, M_CAMXPT);
- }
+ } else
+ device->refcount--;
}
u_int32_t
diff --git a/sys/cam/cam_xpt.h b/sys/cam/cam_xpt.h
index f7d9b428cb70e..1d0e7f7d23817 100644
--- a/sys/cam/cam_xpt.h
+++ b/sys/cam/cam_xpt.h
@@ -106,6 +106,9 @@ cam_status xpt_create_path_unlocked(struct cam_path **new_path_ptr,
int xpt_getattr(char *buf, size_t len, const char *attr,
struct cam_path *path);
void xpt_free_path(struct cam_path *path);
+void xpt_path_counts(struct cam_path *path, uint32_t *bus_ref,
+ uint32_t *periph_ref, uint32_t *target_ref,
+ uint32_t *device_ref);
int xpt_path_comp(struct cam_path *path1,
struct cam_path *path2);
void xpt_print_path(struct cam_path *path);
@@ -138,4 +141,3 @@ void xpt_release_path(struct cam_path *path);
#endif /* _KERNEL */
#endif /* _CAM_CAM_XPT_H */
-
diff --git a/sys/cddl/boot/zfs/zfssubr.c b/sys/cddl/boot/zfs/zfssubr.c
index 5022292b995d6..e76c2738939e8 100644
--- a/sys/cddl/boot/zfs/zfssubr.c
+++ b/sys/cddl/boot/zfs/zfssubr.c
@@ -328,7 +328,7 @@ typedef struct raidz_map {
(mask) = (x) & 0x8080808080808080ULL; \
(mask) = ((mask) << 1) - ((mask) >> 7); \
(x) = (((x) << 1) & 0xfefefefefefefefeULL) ^ \
- ((mask) & 0x1d1d1d1d1d1d1d1d); \
+ ((mask) & 0x1d1d1d1d1d1d1d1dULL); \
}
#define VDEV_RAIDZ_64MUL_4(x, mask) \
diff --git a/sys/cddl/compat/opensolaris/sys/file.h b/sys/cddl/compat/opensolaris/sys/file.h
index 811b78cf87a62..7a3df369603a9 100644
--- a/sys/cddl/compat/opensolaris/sys/file.h
+++ b/sys/cddl/compat/opensolaris/sys/file.h
@@ -36,12 +36,18 @@
#ifdef _KERNEL
typedef struct file file_t;
+#include <sys/capability.h>
+
static __inline file_t *
getf(int fd)
{
struct file *fp;
- if (fget(curthread, fd, &fp) == 0)
+ /*
+ * We wouldn't need all of these rights on every invocation
+ * if we had more information about intent.
+ */
+ if (fget(curthread, fd, CAP_READ | CAP_WRITE | CAP_SEEK, &fp) == 0)
return (fp);
return (NULL);
}
@@ -51,7 +57,8 @@ releasef(int fd)
{
struct file *fp;
- if (fget(curthread, fd, &fp) == 0) {
+ /* No CAP_ rights required, as we're only releasing. */
+ if (fget(curthread, fd, 0, &fp) == 0) {
fdrop(fp, curthread);
fdrop(fp, curthread);
}
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h
index f7e44aadffe3f..5692dc6f44927 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h
@@ -353,7 +353,6 @@ extern void *zfsdev_get_soft_state(minor_t minor,
extern minor_t zfsdev_minor_alloc(void);
extern void *zfsdev_state;
-extern kmutex_t zfsdev_state_lock;
#endif /* _KERNEL */
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c
index 0885f27116d4d..7f9b933e7d1d7 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c
@@ -488,7 +488,7 @@ void
txg_delay(dsl_pool_t *dp, uint64_t txg, int ticks)
{
tx_state_t *tx = &dp->dp_tx;
- int timeout = ddi_get_lbolt() + ticks;
+ clock_t timeout = ddi_get_lbolt() + ticks;
/* don't delay if this txg could transition to quiesing immediately */
if (tx->tx_open_txg > txg ||
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
index 4d4b63cb2a074..47c7b4af00965 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c
@@ -410,7 +410,7 @@ vdev_geom_open(vdev_t *vd, uint64_t *psize, uint64_t *ashift)
struct g_provider *pp;
struct g_consumer *cp;
size_t bufsize;
- int error, lock;
+ int error;
/*
* We must have a pathname, and it must be absolute.
@@ -422,12 +422,6 @@ vdev_geom_open(vdev_t *vd, uint64_t *psize, uint64_t *ashift)
vd->vdev_tsd = NULL;
- if (mutex_owned(&spa_namespace_lock)) {
- mutex_exit(&spa_namespace_lock);
- lock = 1;
- } else {
- lock = 0;
- }
DROP_GIANT();
g_topology_lock();
error = 0;
@@ -459,11 +453,7 @@ vdev_geom_open(vdev_t *vd, uint64_t *psize, uint64_t *ashift)
!ISP2(cp->provider->sectorsize)) {
ZFS_LOG(1, "Provider %s has unsupported sectorsize.",
vd->vdev_path);
-
- g_topology_lock();
vdev_geom_detach(cp, 0);
- g_topology_unlock();
-
error = EINVAL;
cp = NULL;
} else if (cp->acw == 0 && (spa_mode(vd->vdev_spa) & FWRITE) != 0) {
@@ -486,8 +476,6 @@ vdev_geom_open(vdev_t *vd, uint64_t *psize, uint64_t *ashift)
}
g_topology_unlock();
PICKUP_GIANT();
- if (lock)
- mutex_enter(&spa_namespace_lock);
if (cp == NULL) {
vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED;
return (error);
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 ba13747ddb384..17174b29ed9ee 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
@@ -1963,8 +1963,10 @@ top:
uint64_t cookie = 0;
int len = sizeof (zc->zc_name) - (p - zc->zc_name);
- while (dmu_dir_list_next(os, len, p, NULL, &cookie) == 0)
- (void) dmu_objset_prefetch(zc->zc_name, NULL);
+ while (dmu_dir_list_next(os, len, p, NULL, &cookie) == 0) {
+ if (!dataset_name_hidden(zc->zc_name))
+ (void) dmu_objset_prefetch(zc->zc_name, NULL);
+ }
}
do {
@@ -4813,7 +4815,7 @@ zfsdev_minor_alloc(void)
static minor_t last_minor;
minor_t m;
- ASSERT(MUTEX_HELD(&zfsdev_state_lock));
+ ASSERT(MUTEX_HELD(&spa_namespace_lock));
for (m = last_minor + 1; m != last_minor; m++) {
if (m > ZFSDEV_MAX_MINOR)
@@ -4833,7 +4835,7 @@ zfs_ctldev_init(struct cdev *devp)
minor_t minor;
zfs_soft_state_t *zs;
- ASSERT(MUTEX_HELD(&zfsdev_state_lock));
+ ASSERT(MUTEX_HELD(&spa_namespace_lock));
minor = zfsdev_minor_alloc();
if (minor == 0)
@@ -4854,7 +4856,7 @@ zfs_ctldev_init(struct cdev *devp)
static void
zfs_ctldev_destroy(zfs_onexit_t *zo, minor_t minor)
{
- ASSERT(MUTEX_HELD(&zfsdev_state_lock));
+ ASSERT(MUTEX_HELD(&spa_namespace_lock));
zfs_onexit_destroy(zo);
ddi_soft_state_free(zfsdev_state, minor);
@@ -4884,9 +4886,9 @@ zfsdev_open(struct cdev *devp, int flag, int mode, struct thread *td)
/* This is the control device. Allocate a new minor if requested. */
if (flag & FEXCL) {
- mutex_enter(&zfsdev_state_lock);
+ mutex_enter(&spa_namespace_lock);
error = zfs_ctldev_init(devp);
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
}
return (error);
@@ -4901,14 +4903,14 @@ zfsdev_close(void *data)
if (minor == 0)
return;
- mutex_enter(&zfsdev_state_lock);
+ mutex_enter(&spa_namespace_lock);
zo = zfsdev_get_soft_state(minor, ZSST_CTLDEV);
if (zo == NULL) {
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
return;
}
zfs_ctldev_destroy(zo, minor);
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
}
static int
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 588ea85593652..8d8ddfcb22de8 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
@@ -331,8 +331,7 @@ page_lookup(vnode_t *vp, int64_t start, int64_t off, int64_t nbytes)
* sleeping so that the page daemon is less
* likely to reclaim it.
*/
- vm_page_lock_queues();
- vm_page_flag_set(pp, PG_REFERENCED);
+ vm_page_reference(pp);
vm_page_sleep(pp, "zfsmwb");
continue;
}
@@ -612,7 +611,8 @@ zfs_read(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cr, caller_context_t *ct)
/*
* If we're in FRSYNC mode, sync out this znode before reading it.
*/
- if (ioflag & FRSYNC || zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
+ if (zfsvfs->z_log &&
+ (ioflag & FRSYNC || zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS))
zil_commit(zfsvfs->z_log, zp->z_id);
/*
@@ -2642,11 +2642,11 @@ zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
uint32_t blksize;
u_longlong_t nblocks;
uint64_t links;
- uint64_t mtime[2], ctime[2], crtime[2];
+ uint64_t mtime[2], ctime[2], crtime[2], rdev;
xvattr_t *xvap = (xvattr_t *)vap; /* vap may be an xvattr_t * */
xoptattr_t *xoap = NULL;
boolean_t skipaclchk = (flags & ATTR_NOACLCHECK) ? B_TRUE : B_FALSE;
- sa_bulk_attr_t bulk[3];
+ sa_bulk_attr_t bulk[4];
int count = 0;
ZFS_ENTER(zfsvfs);
@@ -2657,6 +2657,9 @@ zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_MTIME(zfsvfs), NULL, &mtime, 16);
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL, &ctime, 16);
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_CTIME(zfsvfs), NULL, &crtime, 16);
+ if (vp->v_type == VBLK || vp->v_type == VCHR)
+ SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_RDEV(zfsvfs), NULL,
+ &rdev, 8);
if ((error = sa_bulk_lookup(zp->z_sa_hdl, bulk, count)) != 0) {
ZFS_EXIT(zfsvfs);
@@ -2685,7 +2688,11 @@ zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
mutex_enter(&zp->z_lock);
vap->va_type = IFTOVT(zp->z_mode);
vap->va_mode = zp->z_mode & ~S_IFMT;
-// vap->va_fsid = zp->z_zfsvfs->z_vfs->vfs_dev;
+#ifdef sun
+ vap->va_fsid = zp->z_zfsvfs->z_vfs->vfs_dev;
+#else
+ vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
+#endif
vap->va_nodeid = zp->z_id;
if ((vp->v_flag & VROOT) && zfs_show_ctldir(zp))
links = zp->z_links + 1;
@@ -2693,8 +2700,12 @@ zfs_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr,
links = zp->z_links;
vap->va_nlink = MIN(links, UINT32_MAX); /* nlink_t limit! */
vap->va_size = zp->z_size;
- vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
-// vap->va_rdev = zfs_cmpldev(pzp->zp_rdev);
+#ifdef sun
+ vap->va_rdev = vp->v_rdev;
+#else
+ if (vp->v_type == VBLK || vp->v_type == VCHR)
+ vap->va_rdev = zfs_cmpldev(rdev);
+#endif
vap->va_seq = zp->z_seq;
vap->va_flags = 0; /* FreeBSD: Reset chflags(2) flags. */
@@ -6329,7 +6340,7 @@ vop_getextattr {
if (error == 0)
*ap->a_size = (size_t)va.va_size;
} else if (ap->a_uio != NULL)
- error = VOP_READ(vp, ap->a_uio, IO_UNIT | IO_SYNC, ap->a_cred);
+ error = VOP_READ(vp, ap->a_uio, IO_UNIT, ap->a_cred);
VOP_UNLOCK(vp, 0);
vn_close(vp, flags, ap->a_cred, td);
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 1f3d0b2a31f00..285881297f6bf 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
@@ -627,6 +627,18 @@ zfs_znode_dmu_fini(znode_t *zp)
zp->z_sa_hdl = NULL;
}
+static void
+zfs_vnode_forget(vnode_t *vp)
+{
+
+ VOP_UNLOCK(vp, 0);
+ VI_LOCK(vp);
+ vp->v_usecount--;
+ vp->v_iflag |= VI_DOOMED;
+ vp->v_data = NULL;
+ vdropl(vp);
+}
+
/*
* Construct a new znode/vnode and intialize.
*
@@ -688,6 +700,8 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
if (sa_bulk_lookup(zp->z_sa_hdl, bulk, count) != 0 || zp->z_gen == 0) {
if (hdl == NULL)
sa_handle_destroy(zp->z_sa_hdl);
+ zfs_vnode_forget(vp);
+ zp->z_vnode = NULL;
kmem_cache_free(znode_cache, zp);
return (NULL);
}
@@ -700,7 +714,23 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
case VDIR:
zp->z_zn_prefetch = B_TRUE; /* z_prefetch default is enabled */
break;
+#ifdef sun
+ case VBLK:
+ case VCHR:
+ {
+ uint64_t rdev;
+ VERIFY(sa_lookup(zp->z_sa_hdl, SA_ZPL_RDEV(zfsvfs),
+ &rdev, sizeof (rdev)) == 0);
+
+ vp->v_rdev = zfs_cmpldev(rdev);
+ }
+ break;
+#endif /* sun */
case VFIFO:
+#ifdef sun
+ case VSOCK:
+ case VDOOR:
+#endif /* sun */
vp->v_op = &zfs_fifoops;
break;
case VREG:
@@ -709,6 +739,14 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
vp->v_op = &zfs_shareops;
}
break;
+#ifdef sun
+ case VLNK:
+ vn_setops(vp, zfs_symvnodeops);
+ break;
+ default:
+ vn_setops(vp, zfs_evnodeops);
+ break;
+#endif /* sun */
}
if (vp->v_type != VFIFO)
VN_LOCK_ASHARE(vp);
@@ -1235,6 +1273,7 @@ zfs_rezget(znode_t *zp)
zfsvfs_t *zfsvfs = zp->z_zfsvfs;
dmu_object_info_t doi;
dmu_buf_t *db;
+ vnode_t *vp;
uint64_t obj_num = zp->z_id;
uint64_t mode, size;
sa_bulk_attr_t bulk[8];
@@ -1310,8 +1349,9 @@ zfs_rezget(znode_t *zp)
* that for example regular file was replaced with directory
* which has the same object number.
*/
- if (ZTOV(zp) != NULL &&
- ZTOV(zp)->v_type != IFTOVT((mode_t)zp->z_mode)) {
+ vp = ZTOV(zp);
+ if (vp != NULL &&
+ vp->v_type != IFTOVT((mode_t)zp->z_mode)) {
zfs_znode_dmu_fini(zp);
ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
return (EIO);
@@ -1319,8 +1359,11 @@ zfs_rezget(znode_t *zp)
zp->z_unlinked = (zp->z_links == 0);
zp->z_blksz = doi.doi_data_block_size;
- if (zp->z_size != size && ZTOV(zp) != NULL)
- vnode_pager_setsize(ZTOV(zp), zp->z_size);
+ if (vp != NULL) {
+ vn_pages_remove(vp, 0, 0);
+ if (zp->z_size != size)
+ vnode_pager_setsize(vp, zp->z_size);
+ }
ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c
index 5c7b22e2a3f32..515e613c27b76 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011 by Delphix. All rights reserved.
*/
/* Portions Copyright 2010 Robert Milkowski */
@@ -567,7 +568,7 @@ zil_destroy(zilog_t *zilog, boolean_t keep_first)
if (!list_is_empty(&zilog->zl_lwb_list)) {
ASSERT(zh->zh_claim_txg == 0);
- ASSERT(!keep_first);
+ VERIFY(!keep_first);
while ((lwb = list_head(&zilog->zl_lwb_list)) != NULL) {
list_remove(&zilog->zl_lwb_list, lwb);
if (lwb->lwb_buf != NULL)
@@ -1668,20 +1669,9 @@ zil_alloc(objset_t *os, zil_header_t *zh_phys)
void
zil_free(zilog_t *zilog)
{
- lwb_t *head_lwb;
-
zilog->zl_stop_sync = 1;
- /*
- * After zil_close() there should only be one lwb with a buffer.
- */
- head_lwb = list_head(&zilog->zl_lwb_list);
- if (head_lwb) {
- ASSERT(head_lwb == list_tail(&zilog->zl_lwb_list));
- list_remove(&zilog->zl_lwb_list, head_lwb);
- zio_buf_free(head_lwb->lwb_buf, head_lwb->lwb_sz);
- kmem_cache_free(zil_lwb_cache, head_lwb);
- }
+ ASSERT(list_is_empty(&zilog->zl_lwb_list));
list_destroy(&zilog->zl_lwb_list);
avl_destroy(&zilog->zl_vdev_tree);
@@ -1721,6 +1711,10 @@ zil_open(objset_t *os, zil_get_data_t *get_data)
{
zilog_t *zilog = dmu_objset_zil(os);
+ ASSERT(zilog->zl_clean_taskq == NULL);
+ ASSERT(zilog->zl_get_data == NULL);
+ ASSERT(list_is_empty(&zilog->zl_lwb_list));
+
zilog->zl_get_data = get_data;
zilog->zl_clean_taskq = taskq_create("zil_clean", 1, minclsyspri,
2, 2, TASKQ_PREPOPULATE);
@@ -1734,7 +1728,7 @@ zil_open(objset_t *os, zil_get_data_t *get_data)
void
zil_close(zilog_t *zilog)
{
- lwb_t *tail_lwb;
+ lwb_t *lwb;
uint64_t txg = 0;
zil_commit(zilog, 0); /* commit all itx */
@@ -1746,9 +1740,9 @@ zil_close(zilog_t *zilog)
* destroy the zl_clean_taskq.
*/
mutex_enter(&zilog->zl_lock);
- tail_lwb = list_tail(&zilog->zl_lwb_list);
- if (tail_lwb != NULL)
- txg = tail_lwb->lwb_max_txg;
+ lwb = list_tail(&zilog->zl_lwb_list);
+ if (lwb != NULL)
+ txg = lwb->lwb_max_txg;
mutex_exit(&zilog->zl_lock);
if (txg)
txg_wait_synced(zilog->zl_dmu_pool, txg);
@@ -1756,6 +1750,19 @@ zil_close(zilog_t *zilog)
taskq_destroy(zilog->zl_clean_taskq);
zilog->zl_clean_taskq = NULL;
zilog->zl_get_data = NULL;
+
+ /*
+ * We should have only one LWB left on the list; remove it now.
+ */
+ mutex_enter(&zilog->zl_lock);
+ lwb = list_head(&zilog->zl_lwb_list);
+ if (lwb != NULL) {
+ ASSERT(lwb == list_tail(&zilog->zl_lwb_list));
+ list_remove(&zilog->zl_lwb_list, lwb);
+ zio_buf_free(lwb->lwb_buf, lwb->lwb_sz);
+ kmem_cache_free(zil_lwb_cache, lwb);
+ }
+ mutex_exit(&zilog->zl_lock);
}
/*
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 a514247321ac8..61c96becdea3e 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c
@@ -94,12 +94,11 @@ static char *zvol_tag = "zvol_tag";
#define ZVOL_DUMPSIZE "dumpsize"
/*
- * This lock protects the zfsdev_state structure from being modified
- * while it's being used, e.g. an open that comes in before a create
- * finishes. It also protects temporary opens of the dataset so that,
+ * The spa_namespace_lock protects the zfsdev_state structure from being
+ * modified while it's being used, e.g. an open that comes in before a
+ * create finishes. It also protects temporary opens of the dataset so that,
* e.g., an open doesn't get a spurious EBUSY.
*/
-kmutex_t zfsdev_state_lock;
static uint32_t zvol_minors;
typedef struct zvol_extent {
@@ -246,7 +245,7 @@ zvol_minor_lookup(const char *name)
struct g_geom *gp;
zvol_state_t *zv = NULL;
- ASSERT(MUTEX_HELD(&zfsdev_state_lock));
+ ASSERT(MUTEX_HELD(&spa_namespace_lock));
g_topology_lock();
LIST_FOREACH(gp, &zfs_zvol_class.geom, geom) {
@@ -462,11 +461,11 @@ zvol_name2minor(const char *name, minor_t *minor)
{
zvol_state_t *zv;
- mutex_enter(&zfsdev_state_lock);
+ mutex_enter(&spa_namespace_lock);
zv = zvol_minor_lookup(name);
if (minor && zv)
*minor = zv->zv_minor;
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
return (zv ? 0 : -1);
}
#endif /* sun */
@@ -485,10 +484,10 @@ zvol_create_minor(const char *name)
ZFS_LOG(1, "Creating ZVOL %s...", name);
- mutex_enter(&zfsdev_state_lock);
+ mutex_enter(&spa_namespace_lock);
if (zvol_minor_lookup(name) != NULL) {
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
return (EEXIST);
}
@@ -496,20 +495,20 @@ zvol_create_minor(const char *name)
error = dmu_objset_own(name, DMU_OST_ZVOL, B_TRUE, FTAG, &os);
if (error) {
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
return (error);
}
#ifdef sun
if ((minor = zfsdev_minor_alloc()) == 0) {
dmu_objset_disown(os, FTAG);
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
return (ENXIO);
}
if (ddi_soft_state_zalloc(zfsdev_state, minor) != DDI_SUCCESS) {
dmu_objset_disown(os, FTAG);
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
return (EAGAIN);
}
(void) ddi_prop_update_string(minor, zfs_dip, ZVOL_PROP_NAME,
@@ -521,7 +520,7 @@ zvol_create_minor(const char *name)
minor, DDI_PSEUDO, 0) == DDI_FAILURE) {
ddi_soft_state_free(zfsdev_state, minor);
dmu_objset_disown(os, FTAG);
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
return (EAGAIN);
}
@@ -532,7 +531,7 @@ zvol_create_minor(const char *name)
ddi_remove_minor_node(zfs_dip, chrbuf);
ddi_soft_state_free(zfsdev_state, minor);
dmu_objset_disown(os, FTAG);
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
return (EAGAIN);
}
@@ -572,7 +571,7 @@ zvol_create_minor(const char *name)
zvol_minors++;
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
zvol_geom_run(zv);
@@ -594,7 +593,7 @@ zvol_remove_zv(zvol_state_t *zv)
minor_t minor = zv->zv_minor;
#endif
- ASSERT(MUTEX_HELD(&zfsdev_state_lock));
+ ASSERT(MUTEX_HELD(&spa_namespace_lock));
if (zv->zv_total_opens != 0)
return (EBUSY);
@@ -620,15 +619,15 @@ zvol_remove_minor(const char *name)
zvol_state_t *zv;
int rc;
- mutex_enter(&zfsdev_state_lock);
+ mutex_enter(&spa_namespace_lock);
if ((zv = zvol_minor_lookup(name)) == NULL) {
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
return (ENXIO);
}
g_topology_lock();
rc = zvol_remove_zv(zv);
g_topology_unlock();
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
return (rc);
}
@@ -730,7 +729,7 @@ zvol_update_volsize(objset_t *os, uint64_t volsize)
dmu_tx_t *tx;
int error;
- ASSERT(MUTEX_HELD(&zfsdev_state_lock));
+ ASSERT(MUTEX_HELD(&spa_namespace_lock));
tx = dmu_tx_create(os);
dmu_tx_hold_zap(tx, ZVOL_ZAP_OBJ, TRUE, NULL);
@@ -761,7 +760,7 @@ zvol_remove_minors(const char *name)
namelen = strlen(name);
DROP_GIANT();
- mutex_enter(&zfsdev_state_lock);
+ mutex_enter(&spa_namespace_lock);
g_topology_lock();
LIST_FOREACH_SAFE(gp, &zfs_zvol_class.geom, geom, gptmp) {
@@ -779,7 +778,7 @@ zvol_remove_minors(const char *name)
}
g_topology_unlock();
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
PICKUP_GIANT();
}
@@ -793,10 +792,10 @@ zvol_set_volsize(const char *name, major_t maj, uint64_t volsize)
uint64_t old_volsize = 0ULL;
uint64_t readonly;
- mutex_enter(&zfsdev_state_lock);
+ mutex_enter(&spa_namespace_lock);
zv = zvol_minor_lookup(name);
if ((error = dmu_objset_hold(name, FTAG, &os)) != 0) {
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
return (error);
}
@@ -863,7 +862,7 @@ zvol_set_volsize(const char *name, major_t maj, uint64_t volsize)
out:
dmu_objset_rele(os, FTAG);
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
return (error);
}
@@ -875,18 +874,18 @@ zvol_open(struct g_provider *pp, int flag, int count)
zvol_state_t *zv;
int err = 0;
- mutex_enter(&zfsdev_state_lock);
+ mutex_enter(&spa_namespace_lock);
zv = pp->private;
if (zv == NULL) {
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
return (ENXIO);
}
if (zv->zv_total_opens == 0)
err = zvol_first_open(zv);
if (err) {
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
return (err);
}
if ((flag & FWRITE) && (zv->zv_flags & ZVOL_RDONLY)) {
@@ -908,13 +907,13 @@ zvol_open(struct g_provider *pp, int flag, int count)
#endif
zv->zv_total_opens += count;
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
return (err);
out:
if (zv->zv_total_opens == 0)
zvol_last_close(zv);
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
return (err);
}
@@ -925,11 +924,11 @@ zvol_close(struct g_provider *pp, int flag, int count)
zvol_state_t *zv;
int error = 0;
- mutex_enter(&zfsdev_state_lock);
+ mutex_enter(&spa_namespace_lock);
zv = pp->private;
if (zv == NULL) {
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
return (ENXIO);
}
@@ -952,7 +951,7 @@ zvol_close(struct g_provider *pp, int flag, int count)
if (zv->zv_total_opens == 0)
zvol_last_close(zv);
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
return (error);
}
@@ -1571,12 +1570,12 @@ zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
int error = 0;
rl_t *rl;
- mutex_enter(&zfsdev_state_lock);
+ mutex_enter(&spa_namespace_lock);
zv = zfsdev_get_soft_state(getminor(dev), ZSST_ZVOL);
if (zv == NULL) {
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
return (ENXIO);
}
ASSERT(zv->zv_total_opens > 0);
@@ -1590,7 +1589,7 @@ zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
dki.dki_ctype = DKC_UNKNOWN;
dki.dki_unit = getminor(dev);
dki.dki_maxtransfer = 1 << (SPA_MAXBLOCKSHIFT - zv->zv_min_bs);
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
if (ddi_copyout(&dki, (void *)arg, sizeof (dki), flag))
error = EFAULT;
return (error);
@@ -1600,7 +1599,7 @@ zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
dkm.dki_lbsize = 1U << zv->zv_min_bs;
dkm.dki_capacity = zv->zv_volsize >> zv->zv_min_bs;
dkm.dki_media_type = DK_UNKNOWN;
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
if (ddi_copyout(&dkm, (void *)arg, sizeof (dkm), flag))
error = EFAULT;
return (error);
@@ -1610,14 +1609,14 @@ zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
uint64_t vs = zv->zv_volsize;
uint8_t bs = zv->zv_min_bs;
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
error = zvol_getefi((void *)arg, flag, vs, bs);
return (error);
}
case DKIOCFLUSHWRITECACHE:
dkc = (struct dk_callback *)arg;
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
zil_commit(zv->zv_zilog, ZVOL_OBJ);
if ((flag & FKIOCTL) && dkc != NULL && dkc->dkc_callback) {
(*dkc->dkc_callback)(dkc->dkc_cookie, error);
@@ -1643,10 +1642,10 @@ zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
}
if (wce) {
zv->zv_flags |= ZVOL_WCE;
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
} else {
zv->zv_flags &= ~ZVOL_WCE;
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
zil_commit(zv->zv_zilog, ZVOL_OBJ);
}
return (0);
@@ -1682,7 +1681,7 @@ zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
break;
}
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
return (error);
}
#endif /* sun */
@@ -1698,14 +1697,12 @@ zvol_init(void)
{
VERIFY(ddi_soft_state_init(&zfsdev_state, sizeof (zfs_soft_state_t),
1) == 0);
- mutex_init(&zfsdev_state_lock, NULL, MUTEX_DEFAULT, NULL);
ZFS_LOG(1, "ZVOL Initialized.");
}
void
zvol_fini(void)
{
- mutex_destroy(&zfsdev_state_lock);
ddi_soft_state_fini(&zfsdev_state);
ZFS_LOG(1, "ZVOL Deinitialized.");
}
@@ -1720,7 +1717,7 @@ zvol_dump_init(zvol_state_t *zv, boolean_t resize)
nvlist_t *nv = NULL;
uint64_t version = spa_version(dmu_objset_spa(zv->zv_objset));
- ASSERT(MUTEX_HELD(&zfsdev_state_lock));
+ ASSERT(MUTEX_HELD(&spa_namespace_lock));
error = dmu_free_long_range(zv->zv_objset, ZVOL_OBJ, 0,
DMU_OBJECT_END);
/* wait for dmu_free_long_range to actually free the blocks */
@@ -2200,11 +2197,11 @@ zvol_create_minors(const char *name)
p = osname + strlen(osname);
len = MAXPATHLEN - (p - osname);
- if (strchr(name, '/') == NULL) {
- /* Prefetch only for pool name. */
- cookie = 0;
- while (dmu_dir_list_next(os, len, p, NULL, &cookie) == 0)
- (void) dmu_objset_prefetch(p, NULL);
+ /* Prefetch the datasets. */
+ cookie = 0;
+ while (dmu_dir_list_next(os, len, p, NULL, &cookie) == 0) {
+ if (!dataset_name_hidden(osname))
+ (void) dmu_objset_prefetch(osname, NULL);
}
cookie = 0;
@@ -2230,7 +2227,7 @@ zvol_rename_minor(struct g_geom *gp, const char *newname)
struct g_provider *pp;
zvol_state_t *zv;
- ASSERT(MUTEX_HELD(&zfsdev_state_lock));
+ ASSERT(MUTEX_HELD(&spa_namespace_lock));
g_topology_assert();
pp = LIST_FIRST(&gp->provider);
@@ -2264,7 +2261,7 @@ zvol_rename_minors(const char *oldname, const char *newname)
newnamelen = strlen(newname);
DROP_GIANT();
- mutex_enter(&zfsdev_state_lock);
+ mutex_enter(&spa_namespace_lock);
g_topology_lock();
LIST_FOREACH(gp, &zfs_zvol_class.geom, geom) {
@@ -2287,6 +2284,6 @@ zvol_rename_minors(const char *oldname, const char *newname)
}
g_topology_unlock();
- mutex_exit(&zfsdev_state_lock);
+ mutex_exit(&spa_namespace_lock);
PICKUP_GIANT();
}
diff --git a/sys/compat/freebsd32/freebsd32.h b/sys/compat/freebsd32/freebsd32.h
index 82bdc53c049f9..5d1a269df4e79 100644
--- a/sys/compat/freebsd32/freebsd32.h
+++ b/sys/compat/freebsd32/freebsd32.h
@@ -310,7 +310,7 @@ struct kinfo_proc32 {
char ki_rqindex;
u_char ki_oncpu;
u_char ki_lastcpu;
- char ki_ocomm[OCOMMLEN+1];
+ char ki_tdname[TDNAMLEN+1];
char ki_wmesg[WMESGLEN+1];
char ki_login[LOGNAMELEN+1];
char ki_lockname[LOCKNAMELEN+1];
diff --git a/sys/compat/freebsd32/freebsd32_ioctl.c b/sys/compat/freebsd32/freebsd32_ioctl.c
index e662a5d25ed9e..1d773caab3bcb 100644
--- a/sys/compat/freebsd32/freebsd32_ioctl.c
+++ b/sys/compat/freebsd32/freebsd32_ioctl.c
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include "opt_compat.h"
#include <sys/param.h>
+#include <sys/capability.h>
#include <sys/cdio.h>
#include <sys/fcntl.h>
#include <sys/filio.h>
@@ -354,7 +355,7 @@ freebsd32_ioctl(struct thread *td, struct freebsd32_ioctl_args *uap)
struct file *fp;
int error;
- if ((error = fget(td, uap->fd, &fp)) != 0)
+ if ((error = fget(td, uap->fd, CAP_IOCTL, &fp)) != 0)
return (error);
if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
fdrop(fp, td);
diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c
index 692c5a38af50c..8832d3d793702 100644
--- a/sys/compat/linprocfs/linprocfs.c
+++ b/sys/compat/linprocfs/linprocfs.c
@@ -502,6 +502,33 @@ linprocfs_dostat(PFS_FILL_ARGS)
return (0);
}
+static int
+linprocfs_doswaps(PFS_FILL_ARGS)
+{
+ struct xswdev xsw;
+ uintmax_t total, used;
+ int n;
+ char devname[SPECNAMELEN + 1];
+
+ sbuf_printf(sb, "Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n");
+ mtx_lock(&Giant);
+ for (n = 0; ; n++) {
+ if (swap_dev_info(n, &xsw, devname, sizeof(devname)) != 0)
+ break;
+ total = (uintmax_t)xsw.xsw_nblks * PAGE_SIZE / 1024;
+ used = (uintmax_t)xsw.xsw_used * PAGE_SIZE / 1024;
+
+ /*
+ * The space and not tab after the device name is on
+ * purpose. Linux does so.
+ */
+ sbuf_printf(sb, "/dev/%-34s unknown\t\t%jd\t%jd\t-1\n",
+ devname, total, used);
+ }
+ mtx_unlock(&Giant);
+ return (0);
+}
+
/*
* Filler function for proc/uptime
*/
@@ -1490,6 +1517,8 @@ linprocfs_init(PFS_INIT_ARGS)
NULL, NULL, NULL, 0);
pfs_create_file(root, "stat", &linprocfs_dostat,
NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(root, "swaps", &linprocfs_doswaps,
+ NULL, NULL, NULL, PFS_RD);
pfs_create_file(root, "uptime", &linprocfs_douptime,
NULL, NULL, NULL, PFS_RD);
pfs_create_file(root, "version", &linprocfs_doversion,
diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c
index 44ad193c8b706..e923032878031 100644
--- a/sys/compat/linux/linux_file.c
+++ b/sys/compat/linux/linux_file.c
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/capability.h>
#include <sys/conf.h>
#include <sys/dirent.h>
#include <sys/fcntl.h>
@@ -141,7 +142,7 @@ linux_common_open(struct thread *td, int dirfd, char *path, int l_flags, int mod
* having the same filedesc could use that fd without
* checking below.
*/
- error = fget(td, fd, &fp);
+ error = fget(td, fd, CAP_IOCTL, &fp);
if (!error) {
sx_slock(&proctree_lock);
PROC_LOCK(p);
@@ -345,7 +346,7 @@ getdents_common(struct thread *td, struct linux_getdents64_args *args,
} else
justone = 0;
- if ((error = getvnode(td->td_proc->p_fd, args->fd, &fp)) != 0)
+ if ((error = getvnode(td->td_proc->p_fd, args->fd, CAP_READ, &fp)) != 0)
return (error);
if ((fp->f_flag & FREAD) == 0) {
@@ -1041,7 +1042,7 @@ linux_pread(td, uap)
if (error == 0) {
/* This seems to violate POSIX but linux does it */
- if ((error = fgetvp(td, uap->fd, &vp)) != 0)
+ if ((error = fgetvp(td, uap->fd, CAP_READ, &vp)) != 0)
return (error);
if (vp->v_type == VDIR) {
vrele(vp);
@@ -1390,7 +1391,7 @@ fcntl_common(struct thread *td, struct linux_fcntl64_args *args)
* significant effect for pipes (SIGIO is not delivered for
* pipes under Linux-2.2.35 at least).
*/
- error = fget(td, args->fd, &fp);
+ error = fget(td, args->fd, CAP_FCNTL, &fp);
if (error)
return (error);
if (fp->f_type == DTYPE_PIPE) {
diff --git a/sys/compat/linux/linux_fork.c b/sys/compat/linux/linux_fork.c
index bf1d45c9ea343..5d2ce5bdb0cb2 100644
--- a/sys/compat/linux/linux_fork.c
+++ b/sys/compat/linux/linux_fork.c
@@ -64,7 +64,8 @@ linux_fork(struct thread *td, struct linux_fork_args *args)
printf(ARGS(fork, ""));
#endif
- if ((error = fork1(td, RFFDG | RFPROC | RFSTOPPED, 0, &p2)) != 0)
+ if ((error = fork1(td, RFFDG | RFPROC | RFSTOPPED, 0, &p2, NULL, 0))
+ != 0)
return (error);
td->td_retval[0] = p2->p_pid;
@@ -100,7 +101,8 @@ linux_vfork(struct thread *td, struct linux_vfork_args *args)
#endif
/* Exclude RFPPWAIT */
- if ((error = fork1(td, RFFDG | RFPROC | RFMEM | RFSTOPPED, 0, &p2)) != 0)
+ if ((error = fork1(td, RFFDG | RFPROC | RFMEM | RFSTOPPED, 0, &p2,
+ NULL, 0)) != 0)
return (error);
td->td_retval[0] = p2->p_pid;
@@ -190,7 +192,7 @@ linux_clone(struct thread *td, struct linux_clone_args *args)
if (args->parent_tidptr == NULL)
return (EINVAL);
- error = fork1(td, ff, 0, &p2);
+ error = fork1(td, ff, 0, &p2, NULL, 0);
if (error)
return (error);
diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c
index 5532c931fb396..d021fbada6509 100644
--- a/sys/compat/linux/linux_ioctl.c
+++ b/sys/compat/linux/linux_ioctl.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sysproto.h>
+#include <sys/capability.h>
#include <sys/cdio.h>
#include <sys/dvdio.h>
#include <sys/conf.h>
@@ -193,7 +194,7 @@ linux_ioctl_hdio(struct thread *td, struct linux_ioctl_args *args)
u_int sectorsize, fwcylinders, fwheads, fwsectors;
off_t mediasize, bytespercyl;
- if ((error = fget(td, args->fd, &fp)) != 0)
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
return (error);
switch (args->cmd & 0xffff) {
case LINUX_HDIO_GET_GEO:
@@ -274,7 +275,7 @@ linux_ioctl_disk(struct thread *td, struct linux_ioctl_args *args)
u_int sectorsize;
off_t mediasize;
- if ((error = fget(td, args->fd, &fp)) != 0)
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
return (error);
switch (args->cmd & 0xffff) {
case LINUX_BLKGETSIZE:
@@ -700,7 +701,7 @@ linux_ioctl_termio(struct thread *td, struct linux_ioctl_args *args)
struct file *fp;
int error;
- if ((error = fget(td, args->fd, &fp)) != 0)
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
return (error);
switch (args->cmd & 0xffff) {
@@ -1440,7 +1441,7 @@ linux_ioctl_cdrom(struct thread *td, struct linux_ioctl_args *args)
struct file *fp;
int error;
- if ((error = fget(td, args->fd, &fp)) != 0)
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
return (error);
switch (args->cmd & 0xffff) {
@@ -1965,7 +1966,7 @@ linux_ioctl_console(struct thread *td, struct linux_ioctl_args *args)
struct file *fp;
int error;
- if ((error = fget(td, args->fd, &fp)) != 0)
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
return (error);
switch (args->cmd & 0xffff) {
@@ -2356,7 +2357,7 @@ linux_ioctl_socket(struct thread *td, struct linux_ioctl_args *args)
ifp = NULL;
error = 0;
- if ((error = fget(td, args->fd, &fp)) != 0)
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
return (error);
type = fp->f_type;
fdrop(fp, td);
@@ -2582,7 +2583,7 @@ linux_ioctl_private(struct thread *td, struct linux_ioctl_args *args)
struct file *fp;
int error, type;
- if ((error = fget(td, args->fd, &fp)) != 0)
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
return (error);
type = fp->f_type;
fdrop(fp, td);
@@ -2608,7 +2609,7 @@ linux_ioctl_sg(struct thread *td, struct linux_ioctl_args *args)
u_long cmd;
int error;
- if ((error = fget(td, args->fd, &fp)) != 0) {
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0) {
printf("sg_linux_ioctl: fget returned %d\n", error);
return (error);
}
@@ -2843,7 +2844,7 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args)
case LINUX_VIDIOCSCHAN: args->cmd = VIDIOCSCHAN; break;
case LINUX_VIDIOCGTUNER:
- if ((error = fget(td, args->fd, &fp)) != 0)
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
return (error);
error = copyin((void *) args->arg, &l_vtun, sizeof(l_vtun));
if (error) {
@@ -2861,7 +2862,7 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args)
return (error);
case LINUX_VIDIOCSTUNER:
- if ((error = fget(td, args->fd, &fp)) != 0)
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
return (error);
error = copyin((void *) args->arg, &l_vtun, sizeof(l_vtun));
if (error) {
@@ -2878,7 +2879,7 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args)
case LINUX_VIDIOCCAPTURE: args->cmd = VIDIOCCAPTURE; break;
case LINUX_VIDIOCGWIN:
- if ((error = fget(td, args->fd, &fp)) != 0)
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
return (error);
error = fo_ioctl(fp, VIDIOCGWIN, &vwin, td->td_ucred, td);
if (!error) {
@@ -2890,7 +2891,7 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args)
return (error);
case LINUX_VIDIOCSWIN:
- if ((error = fget(td, args->fd, &fp)) != 0)
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
return (error);
error = copyin((void *) args->arg, &l_vwin, sizeof(l_vwin));
if (error) {
@@ -2913,7 +2914,7 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args)
return (error);
case LINUX_VIDIOCGFBUF:
- if ((error = fget(td, args->fd, &fp)) != 0)
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
return (error);
error = fo_ioctl(fp, VIDIOCGFBUF, &vbuf, td->td_ucred, td);
if (!error) {
@@ -2925,7 +2926,7 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args)
return (error);
case LINUX_VIDIOCSFBUF:
- if ((error = fget(td, args->fd, &fp)) != 0)
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
return (error);
error = copyin((void *) args->arg, &l_vbuf, sizeof(l_vbuf));
if (error) {
@@ -2953,7 +2954,7 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args)
case LINUX_VIDIOCGPLAYINFO: args->cmd = VIDIOCGPLAYINFO; break;
case LINUX_VIDIOCSMICROCODE:
- if ((error = fget(td, args->fd, &fp)) != 0)
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
return (error);
error = copyin((void *) args->arg, &l_vcode, sizeof(l_vcode));
if (error) {
@@ -3197,7 +3198,7 @@ linux_ioctl_v4l2(struct thread *td, struct linux_ioctl_args *args)
error = copyin((void *)args->arg, &l_vformat, sizeof(l_vformat));
if (error)
return (error);
- if ((error = fget(td, args->fd, &fp)) != 0)
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
return (error);
if (linux_to_bsd_v4l2_format(&l_vformat, &vformat) != 0)
error = EINVAL;
@@ -3220,7 +3221,7 @@ linux_ioctl_v4l2(struct thread *td, struct linux_ioctl_args *args)
if (error)
return (error);
linux_to_bsd_v4l2_standard(&l_vstd, &vstd);
- if ((error = fget(td, args->fd, &fp)) != 0)
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
return (error);
error = fo_ioctl(fp, VIDIOC_ENUMSTD, (caddr_t)&vstd,
td->td_ucred, td);
@@ -3242,7 +3243,7 @@ linux_ioctl_v4l2(struct thread *td, struct linux_ioctl_args *args)
sizeof(struct l_v4l2_input));
if (error != 0)
return (error);
- if ((error = fget(td, args->fd, &fp)) != 0)
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
return (error);
error = fo_ioctl(fp, VIDIOC_ENUMINPUT, (caddr_t)&vinp,
td->td_ucred, td);
@@ -3261,7 +3262,7 @@ linux_ioctl_v4l2(struct thread *td, struct linux_ioctl_args *args)
error = copyin((void *)args->arg, &l_vbuf, sizeof(l_vbuf));
if (error)
return (error);
- if ((error = fget(td, args->fd, &fp)) != 0)
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
return (error);
linux_to_bsd_v4l2_buffer(&l_vbuf, &vbuf);
if ((args->cmd & 0xffff) == LINUX_VIDIOC_QUERYBUF)
@@ -3431,7 +3432,7 @@ linux_ioctl(struct thread *td, struct linux_ioctl_args *args)
(unsigned long)args->cmd);
#endif
- if ((error = fget(td, args->fd, &fp)) != 0)
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
return (error);
if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
fdrop(fp, td);
diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c
index 6940e45be0bd2..08728a13db19e 100644
--- a/sys/compat/linux/linux_socket.c
+++ b/sys/compat/linux/linux_socket.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/sysproto.h>
+#include <sys/capability.h>
#include <sys/fcntl.h>
#include <sys/file.h>
#include <sys/limits.h>
@@ -743,7 +744,7 @@ linux_connect(struct thread *td, struct linux_connect_args *args)
* socket and use the file descriptor reference instead of
* creating a new one.
*/
- error = fgetsock(td, args->s, &so, &fflag);
+ error = fgetsock(td, args->s, CAP_CONNECT, &so, &fflag);
if (error == 0) {
error = EISCONN;
if (fflag & FNONBLOCK) {
diff --git a/sys/compat/linux/linux_stats.c b/sys/compat/linux/linux_stats.c
index 8fa08b690f9ca..90f860d447766 100644
--- a/sys/compat/linux/linux_stats.c
+++ b/sys/compat/linux/linux_stats.c
@@ -141,8 +141,11 @@ translate_fd_major_minor(struct thread *td, int fd, struct stat *buf)
struct vnode *vp;
int major, minor;
+ /*
+ * No capability rights required here.
+ */
if ((!S_ISCHR(buf->st_mode) && !S_ISBLK(buf->st_mode)) ||
- fget(td, fd, &fp) != 0)
+ fget(td, fd, 0, &fp) != 0)
return;
vp = fp->f_vnode;
if (vp != NULL && vp->v_rdev != NULL &&
diff --git a/sys/compat/svr4/svr4_fcntl.c b/sys/compat/svr4/svr4_fcntl.c
index 88e4fc2bc12df..ce1452a3043bc 100644
--- a/sys/compat/svr4/svr4_fcntl.c
+++ b/sys/compat/svr4/svr4_fcntl.c
@@ -33,6 +33,7 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/capability.h>
#include <sys/systm.h>
#include <sys/file.h>
#include <sys/filedesc.h>
@@ -261,7 +262,17 @@ fd_revoke(td, fd)
int error, *retval;
retval = td->td_retval;
- if ((error = fgetvp(td, fd, &vp)) != 0)
+ /*
+ * If we ever want to support Capsicum on SVR4 processes (unlikely)
+ * or FreeBSD grows a native frevoke() (more likely), we will need a
+ * CAP_REVOKE here.
+ *
+ * In the meantime, use CAP_MASK_VALID: if a SVR4 process wants to
+ * do an frevoke(), it needs to do it on either a regular file
+ * descriptor or a fully-privileged capability (which is effectively
+ * the same as a non-capability-restricted file descriptor).
+ */
+ if ((error = fgetvp(td, fd, CAP_MASK_VALID, &vp)) != 0)
return (error);
if (vp->v_type != VCHR && vp->v_type != VBLK) {
@@ -313,7 +324,7 @@ fd_truncate(td, fd, flp)
/*
* We only support truncating the file.
*/
- if ((error = fget(td, fd, &fp)) != 0)
+ if ((error = fget(td, fd, CAP_FTRUNCATE, &fp)) != 0)
return (error);
vp = fp->f_vnode;
@@ -392,7 +403,7 @@ svr4_sys_open(td, uap)
#if defined(NOTYET)
struct file *fp;
- error = fget(td, retval, &fp);
+ error = fget(td, retval, CAP_IOCTL, &fp);
PROC_UNLOCK(p);
/*
* we may have lost a race the above open() and
diff --git a/sys/compat/svr4/svr4_filio.c b/sys/compat/svr4/svr4_filio.c
index ca85653823ab4..cb7cadae9c4f2 100644
--- a/sys/compat/svr4/svr4_filio.c
+++ b/sys/compat/svr4/svr4_filio.c
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/systm.h>
+#include <sys/capability.h>
#include <sys/file.h>
#include <sys/filio.h>
#include <sys/lock.h>
@@ -113,7 +114,7 @@ svr4_sys_read(td, uap)
ra.buf = uap->buf;
ra.nbyte = uap->nbyte;
- if (fget(td, uap->fd, &fp) != 0) {
+ if (fget(td, uap->fd, CAP_READ, &fp) != 0) {
DPRINTF(("Something fishy with the user-supplied file descriptor...\n"));
return EBADF;
}
diff --git a/sys/compat/svr4/svr4_ioctl.c b/sys/compat/svr4/svr4_ioctl.c
index 1cea41af856b5..36b05803821f6 100644
--- a/sys/compat/svr4/svr4_ioctl.c
+++ b/sys/compat/svr4/svr4_ioctl.c
@@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/proc.h>
+#include <sys/capability.h>
#include <sys/file.h>
#include <sys/filedesc.h>
#include <sys/fcntl.h>
@@ -102,7 +103,7 @@ svr4_sys_ioctl(td, uap)
retval = td->td_retval;
cmd = uap->com;
- if ((error = fget(td, uap->fd, &fp)) != 0)
+ if ((error = fget(td, uap->fd, CAP_IOCTL, &fp)) != 0)
return (error);
if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
diff --git a/sys/compat/svr4/svr4_misc.c b/sys/compat/svr4/svr4_misc.c
index 6f80fe64e6671..c0a74780ee484 100644
--- a/sys/compat/svr4/svr4_misc.c
+++ b/sys/compat/svr4/svr4_misc.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/capability.h>
#include <sys/dirent.h>
#include <sys/fcntl.h>
#include <sys/filedesc.h>
@@ -246,7 +247,8 @@ svr4_sys_getdents64(td, uap)
DPRINTF(("svr4_sys_getdents64(%d, *, %d)\n",
uap->fd, uap->nbytes));
- if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) {
+ if ((error = getvnode(td->td_proc->p_fd, uap->fd,
+ CAP_READ | CAP_SEEK, &fp)) != 0) {
return (error);
}
@@ -427,7 +429,8 @@ svr4_sys_getdents(td, uap)
if (uap->nbytes < 0)
return (EINVAL);
- if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
+ if ((error = getvnode(td->td_proc->p_fd, uap->fd,
+ CAP_READ | CAP_SEEK, &fp)) != 0)
return (error);
if ((fp->f_flag & FREAD) == 0) {
@@ -615,7 +618,8 @@ svr4_sys_fchroot(td, uap)
if ((error = priv_check(td, PRIV_VFS_FCHROOT)) != 0)
return error;
- if ((error = getvnode(fdp, uap->fd, &fp)) != 0)
+ /* XXX: we have the chroot priv... what cap might we need? all? */
+ if ((error = getvnode(fdp, uap->fd, 0, &fp)) != 0)
return error;
vp = fp->f_vnode;
VREF(vp);
diff --git a/sys/compat/svr4/svr4_stream.c b/sys/compat/svr4/svr4_stream.c
index ec95eece0e5b7..a1a42c030116b 100644
--- a/sys/compat/svr4/svr4_stream.c
+++ b/sys/compat/svr4/svr4_stream.c
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/capability.h>
#include <sys/fcntl.h>
#include <sys/filedesc.h>
#include <sys/filio.h>
@@ -1448,7 +1449,7 @@ svr4_sys_putmsg(td, uap)
struct file *fp;
int error;
- if ((error = fget(td, uap->fd, &fp)) != 0) {
+ if ((error = fget(td, uap->fd, CAP_WRITE, &fp)) != 0) {
#ifdef DEBUG_SVR4
uprintf("putmsg: bad fp\n");
#endif
@@ -1620,7 +1621,7 @@ svr4_sys_getmsg(td, uap)
struct file *fp;
int error;
- if ((error = fget(td, uap->fd, &fp)) != 0) {
+ if ((error = fget(td, uap->fd, CAP_READ, &fp)) != 0) {
#ifdef DEBUG_SVR4
uprintf("getmsg: bad fp\n");
#endif
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index d3951e34fc2cc..fd76593362c0a 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -213,6 +213,10 @@ options SCHED_STATS
# Mandatory:
options SMP # Symmetric MultiProcessor Kernel
+# MAXCPU defines the maximum number of CPUs that can boot in the system.
+# A default value should be already present, for every architecture.
+options MAXCPU=32
+
# ADAPTIVE_MUTEXES changes the behavior of blocking mutexes to spin
# if the thread that currently owns the mutex is executing on another
# CPU. This behaviour is enabled by default, so this option can be used
@@ -495,16 +499,6 @@ options DIAGNOSTIC
options REGRESSION
#
-# RESTARTABLE_PANICS allows one to continue from a panic as if it were
-# a call to the debugger to continue from a panic as instead. It is only
-# useful if a kernel debugger is present. To restart from a panic, reset
-# the panicstr variable to NULL and continue execution. This option is
-# for development use only and should NOT be used in production systems
-# to "workaround" a panic.
-#
-#options RESTARTABLE_PANICS
-
-#
# This option lets some drivers co-exist that can't co-exist in a running
# system. This is used to be able to compile all kernel code in one go for
# quality assurance purposes (like this file, which the option takes it name
@@ -1165,6 +1159,9 @@ options MAC_TEST
options CAPABILITIES # fine-grained rights on file descriptors
options CAPABILITY_MODE # sandboxes with no global namespace access
+# Support for process descriptors
+options PROCDESC
+
#####################################################################
# CLOCK OPTIONS
@@ -2932,7 +2929,6 @@ options SCSI_NCR_MYADDR=7
options SC_DEBUG_LEVEL=5 # Syscons debug level
options SC_RENDER_DEBUG # syscons rendering debugging
-options SHOW_BUSYBUFS # List buffers that prevent root unmount
options VFS_BIO_DEBUG # VFS buffer I/O debugging
options KSTACK_MAX_PAGES=32 # Maximum pages to give the kernel stack
diff --git a/sys/conf/files b/sys/conf/files
index 0dc814e0934aa..5c5d92d6b163f 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -2412,6 +2412,7 @@ kern/subr_witness.c optional witness
kern/sys_capability.c standard
kern/sys_generic.c standard
kern/sys_pipe.c standard
+kern/sys_procdesc.c standard
kern/sys_process.c standard
kern/sys_socket.c standard
kern/syscalls.c standard
diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc
index 9f5a35701fe07..031a1848f800d 100644
--- a/sys/conf/files.powerpc
+++ b/sys/conf/files.powerpc
@@ -207,8 +207,8 @@ powerpc/ps3/ohci_ps3.c optional ps3 ohci
powerpc/ps3/if_glc.c optional ps3 glc
powerpc/ps3/mmu_ps3.c optional ps3
powerpc/ps3/platform_ps3.c optional ps3
-powerpc/ps3/ps3ata.c optional ps3 ps3ata
powerpc/ps3/ps3bus.c optional ps3
+powerpc/ps3/ps3cdrom.c optional ps3 scbus
powerpc/ps3/ps3disk.c optional ps3
powerpc/ps3/ps3pic.c optional ps3
powerpc/ps3/ps3_syscons.c optional ps3 sc
diff --git a/sys/conf/kern.pre.mk b/sys/conf/kern.pre.mk
index e9aa6e23d7980..2320b89fa8b57 100644
--- a/sys/conf/kern.pre.mk
+++ b/sys/conf/kern.pre.mk
@@ -27,8 +27,12 @@ SIZE?= size
_MINUS_O= -O
CTFFLAGS+= -g
.else
+.if ${MACHINE_CPUARCH} == "powerpc"
+_MINUS_O= -O # gcc miscompiles some code at -O2
+.else
_MINUS_O= -O2
.endif
+.endif
.if ${MACHINE_CPUARCH} == "amd64"
COPTFLAGS?=-O2 -frename-registers -pipe
.else
diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh
index 9681c7904d434..b7d02e7a780a5 100644
--- a/sys/conf/newvers.sh
+++ b/sys/conf/newvers.sh
@@ -32,7 +32,7 @@
TYPE="FreeBSD"
REVISION="9.0"
-BRANCH="CURRENT"
+BRANCH="BETA2"
if [ "X${BRANCH_OVERRIDE}" != "X" ]; then
BRANCH=${BRANCH_OVERRIDE}
fi
diff --git a/sys/conf/options b/sys/conf/options
index 9f1ac80dbb96e..a7f12124d9cdc 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -47,6 +47,8 @@ TWA_DEBUG opt_twa.h
TWA_FLASH_FIRMWARE opt_twa.h
# Debugging options.
+ALT_BREAK_TO_DEBUGGER opt_kdb.h
+BREAK_TO_DEBUGGER opt_kdb.h
DDB
DDB_BUFR_SIZE opt_ddb.h
DDB_CAPTURE_DEFAULTBUFSIZE opt_ddb.h
@@ -149,11 +151,11 @@ PPC_DEBUG opt_ppc.h
PPC_PROBE_CHIPSET opt_ppc.h
PPS_SYNC opt_ntp.h
PREEMPTION opt_sched.h
+PROCDESC opt_procdesc.h
QUOTA
SCHED_4BSD opt_sched.h
SCHED_STATS opt_sched.h
SCHED_ULE opt_sched.h
-SHOW_BUSYBUFS
SLEEPQUEUE_PROFILING
SLHCI_DEBUG opt_slhci.h
SPX_HACK
@@ -570,6 +572,7 @@ DFLTPHYS opt_global.h
DIAGNOSTIC opt_global.h
INVARIANT_SUPPORT opt_global.h
INVARIANTS opt_global.h
+MAXCPU opt_global.h
MAXPHYS opt_global.h
MCLSHIFT opt_global.h
MUTEX_DEBUG opt_global.h
@@ -578,7 +581,6 @@ LOCK_PROFILING opt_global.h
LOCK_PROFILING_FAST opt_global.h
MSIZE opt_global.h
REGRESSION opt_global.h
-RESTARTABLE_PANICS opt_global.h
RWLOCK_NOINLINE opt_global.h
SX_NOINLINE opt_global.h
VFS_BIO_DEBUG opt_global.h
@@ -636,9 +638,6 @@ BKTR_SIS_VIA_MODE opt_bktr.h
BKTR_USE_FREEBSD_SMBUS opt_bktr.h
BKTR_NEW_MSP34XX_DRIVER opt_bktr.h
-BREAK_TO_DEBUGGER opt_comconsole.h
-ALT_BREAK_TO_DEBUGGER opt_comconsole.h
-
# Options to support PPS
UART_PPS_ON_CTS opt_uart.h
diff --git a/sys/contrib/pf/net/if_pfsync.c b/sys/contrib/pf/net/if_pfsync.c
index ba8a348812ac3..0a093fcf23039 100644
--- a/sys/contrib/pf/net/if_pfsync.c
+++ b/sys/contrib/pf/net/if_pfsync.c
@@ -2126,8 +2126,8 @@ pfsync_sendout(void)
#else
struct ifnet *ifp = &sc->sc_if;
#endif
- struct mbuf *m;
#endif
+ struct mbuf *m;
struct ip *ip;
struct pfsync_header *ph;
struct pfsync_subheader *subh;
diff --git a/sys/contrib/pf/net/pf.c b/sys/contrib/pf/net/pf.c
index 5efd651f4dbb7..9d40371476632 100644
--- a/sys/contrib/pf/net/pf.c
+++ b/sys/contrib/pf/net/pf.c
@@ -6967,7 +6967,8 @@ done:
ipfwtag = m_tag_alloc(MTAG_IPFW_RULE, 0,
sizeof(struct ipfw_rule_ref), M_NOWAIT | M_ZERO);
if (ipfwtag != NULL) {
- ((struct ipfw_rule_ref *)(ipfwtag+1))->info = r->divert.port;
+ ((struct ipfw_rule_ref *)(ipfwtag+1))->info =
+ ntohs(r->divert.port);
((struct ipfw_rule_ref *)(ipfwtag+1))->rulenum = dir;
m_tag_prepend(m, ipfwtag);
diff --git a/sys/ddb/db_break.c b/sys/ddb/db_break.c
index ac0c874184875..02833ec0a8289 100644
--- a/sys/ddb/db_break.c
+++ b/sys/ddb/db_break.c
@@ -35,8 +35,6 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include "opt_comconsole.h"
-
#include <sys/param.h>
#include <vm/vm.h>
diff --git a/sys/dev/aac/aac_linux.c b/sys/dev/aac/aac_linux.c
index f8852358adec9..049e2be78e5be 100644
--- a/sys/dev/aac/aac_linux.c
+++ b/sys/dev/aac/aac_linux.c
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/capability.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/module.h>
@@ -78,7 +79,7 @@ aac_linux_ioctl(struct thread *td, struct linux_ioctl_args *args)
u_long cmd;
int error;
- if ((error = fget(td, args->fd, &fp)) != 0)
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
return (error);
cmd = args->cmd;
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index 9352be9c3377c..1d0cc2388cdde 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -574,7 +574,7 @@ acpi_attach(device_t dev)
&sc->acpi_suspend_sx, 0, acpi_sleep_state_sysctl, "A", "");
SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
OID_AUTO, "sleep_delay", CTLFLAG_RW, &sc->acpi_sleep_delay, 0,
- "sleep delay");
+ "sleep delay in seconds");
SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
OID_AUTO, "s4bios", CTLFLAG_RW, &sc->acpi_s4bios, 0, "S4BIOS mode");
SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
diff --git a/sys/dev/acpica/acpi_hpet.c b/sys/dev/acpica/acpi_hpet.c
index 40e8676fceb3f..134a86afe73ae 100644
--- a/sys/dev/acpica/acpi_hpet.c
+++ b/sys/dev/acpica/acpi_hpet.c
@@ -190,13 +190,10 @@ restart:
bus_write_4(sc->mem_res, HPET_TIMER_COMPARATOR(t->num),
t->next);
}
- if (fdiv < 5000) {
- bus_read_4(sc->mem_res, HPET_TIMER_COMPARATOR(t->num));
- now = bus_read_4(sc->mem_res, HPET_MAIN_COUNTER);
- if ((int32_t)(now - t->next) >= 0) {
- fdiv *= 2;
- goto restart;
- }
+ now = bus_read_4(sc->mem_res, HPET_MAIN_COUNTER);
+ if ((int32_t)(now - t->next + HPET_MIN_CYCLES) >= 0) {
+ fdiv *= 2;
+ goto restart;
}
return (0);
}
@@ -679,7 +676,8 @@ hpet_attach(device_t dev)
t->et.et_quality -= 10;
t->et.et_frequency = sc->freq;
t->et.et_min_period.sec = 0;
- t->et.et_min_period.frac = 0x00008000LLU << 32;
+ t->et.et_min_period.frac =
+ (((uint64_t)(HPET_MIN_CYCLES * 2) << 32) / sc->freq) << 32;
t->et.et_max_period.sec = 0xfffffffeLLU / sc->freq;
t->et.et_max_period.frac =
((0xfffffffeLLU << 32) / sc->freq) << 32;
diff --git a/sys/dev/acpica/acpi_hpet.h b/sys/dev/acpica/acpi_hpet.h
index 8ca40cdfb3c01..fd495d5267f14 100644
--- a/sys/dev/acpica/acpi_hpet.h
+++ b/sys/dev/acpica/acpi_hpet.h
@@ -62,4 +62,6 @@
#define HPET_TIMER_FSB_VAL(x) ((x) * 0x20 + 0x110)
#define HPET_TIMER_FSB_ADDR(x) ((x) * 0x20 + 0x114)
+#define HPET_MIN_CYCLES 128 /* Period considered reliable. */
+
#endif /* !__ACPI_HPET_H__ */
diff --git a/sys/dev/acpica/acpi_pcib_acpi.c b/sys/dev/acpica/acpi_pcib_acpi.c
index 99e3f1f75cbe8..b96ced52f901f 100644
--- a/sys/dev/acpica/acpi_pcib_acpi.c
+++ b/sys/dev/acpica/acpi_pcib_acpi.c
@@ -207,9 +207,11 @@ acpi_pcib_producer_handler(ACPI_RESOURCE *res, void *context)
length = res->Data.ExtAddress64.AddressLength;
break;
}
- if (length == 0 ||
- res->Data.Address.MinAddressFixed != ACPI_ADDRESS_FIXED ||
- res->Data.Address.MaxAddressFixed != ACPI_ADDRESS_FIXED)
+ if (length == 0)
+ break;
+ if (min + length - 1 != max &&
+ (res->Data.Address.MinAddressFixed != ACPI_ADDRESS_FIXED ||
+ res->Data.Address.MaxAddressFixed != ACPI_ADDRESS_FIXED))
break;
flags = 0;
switch (res->Data.Address.ResourceType) {
diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c
index 0bc094edccea0..7be4cdb1f2837 100644
--- a/sys/dev/ahci/ahci.c
+++ b/sys/dev/ahci/ahci.c
@@ -128,6 +128,7 @@ static struct {
{0x43931002, 0x00, "ATI IXP700", 0},
{0x43941002, 0x00, "ATI IXP800", 0},
{0x43951002, 0x00, "ATI IXP800", 0},
+ {0x06121b21, 0x00, "ASMedia ASM1061", 0},
{0x26528086, 0x00, "Intel ICH6", AHCI_Q_NOFORCE},
{0x26538086, 0x00, "Intel ICH6M", AHCI_Q_NOFORCE},
{0x26818086, 0x00, "Intel ESB2", 0},
@@ -264,7 +265,7 @@ static struct {
{0x0abe10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
{0x0abf10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA},
{0x0d8410de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
- {0x0d8510de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
+ {0x0d8510de, 0x00, "NVIDIA MCP89", AHCI_Q_NOFORCE|AHCI_Q_NOAA},
{0x0d8610de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
{0x0d8710de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
{0x0d8810de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA},
@@ -1879,12 +1880,13 @@ ahci_execute_transaction(struct ahci_slot *slot)
device_printf(dev, "Poll timeout on slot %d port %d\n",
slot->slot, port);
device_printf(dev, "is %08x cs %08x ss %08x "
- "rs %08x tfd %02x serr %08x\n",
+ "rs %08x tfd %02x serr %08x cmd %08x\n",
ATA_INL(ch->r_mem, AHCI_P_IS),
ATA_INL(ch->r_mem, AHCI_P_CI),
ATA_INL(ch->r_mem, AHCI_P_SACT), ch->rslots,
ATA_INL(ch->r_mem, AHCI_P_TFD),
- ATA_INL(ch->r_mem, AHCI_P_SERR));
+ ATA_INL(ch->r_mem, AHCI_P_SERR),
+ ATA_INL(ch->r_mem, AHCI_P_CMD));
et = AHCI_ERR_TIMEOUT;
}
@@ -1960,8 +1962,12 @@ ahci_timeout(struct ahci_slot *slot)
ccs = (ATA_INL(ch->r_mem, AHCI_P_CMD) & AHCI_P_CMD_CCS_MASK)
>> AHCI_P_CMD_CCS_SHIFT;
if ((sstatus & (1 << slot->slot)) != 0 || ccs == slot->slot ||
- ch->fbs_enabled)
+ ch->fbs_enabled || ch->wrongccs)
slot->state = AHCI_SLOT_EXECUTING;
+ else if ((ch->rslots & (1 << ccs)) == 0) {
+ ch->wrongccs = 1;
+ slot->state = AHCI_SLOT_EXECUTING;
+ }
callout_reset(&slot->timeout,
(int)slot->ccb->ccb_h.timeout * hz / 2000,
@@ -1971,10 +1977,12 @@ ahci_timeout(struct ahci_slot *slot)
device_printf(dev, "Timeout on slot %d port %d\n",
slot->slot, slot->ccb->ccb_h.target_id & 0x0f);
- device_printf(dev, "is %08x cs %08x ss %08x rs %08x tfd %02x serr %08x\n",
+ device_printf(dev, "is %08x cs %08x ss %08x rs %08x tfd %02x "
+ "serr %08x cmd %08x\n",
ATA_INL(ch->r_mem, AHCI_P_IS), ATA_INL(ch->r_mem, AHCI_P_CI),
ATA_INL(ch->r_mem, AHCI_P_SACT), ch->rslots,
- ATA_INL(ch->r_mem, AHCI_P_TFD), ATA_INL(ch->r_mem, AHCI_P_SERR));
+ ATA_INL(ch->r_mem, AHCI_P_TFD), ATA_INL(ch->r_mem, AHCI_P_SERR),
+ ATA_INL(ch->r_mem, AHCI_P_CMD));
/* Handle frozen command. */
if (ch->frozen) {
@@ -1987,7 +1995,7 @@ ahci_timeout(struct ahci_slot *slot)
}
xpt_done(fccb);
}
- if (!ch->fbs_enabled) {
+ if (!ch->fbs_enabled && !ch->wrongccs) {
/* Without FBS we know real timeout source. */
ch->fatalerr = 1;
/* Handle command with timeout. */
@@ -2585,6 +2593,7 @@ ahci_reset(device_t dev)
xpt_release_simq(ch->sim, TRUE);
ch->eslots = 0;
ch->toslots = 0;
+ ch->wrongccs = 0;
ch->fatalerr = 0;
/* Tell the XPT about the event */
xpt_async(AC_BUS_RESET, ch->path, NULL);
diff --git a/sys/dev/ahci/ahci.h b/sys/dev/ahci/ahci.h
index 3ace69fff9259..559c67ab0e4ad 100644
--- a/sys/dev/ahci/ahci.h
+++ b/sys/dev/ahci/ahci.h
@@ -426,6 +426,7 @@ struct ahci_channel {
int resetting; /* Hard-reset in progress. */
int resetpolldiv; /* Hard-reset poll divider. */
int listening; /* SUD bit is cleared. */
+ int wrongccs; /* CCS field in CMD was wrong */
union ccb *frozen; /* Frozen command */
struct callout pm_timer; /* Power management events */
struct callout reset_timer; /* Hard-reset timeout */
diff --git a/sys/dev/alc/if_alc.c b/sys/dev/alc/if_alc.c
index ff0424ecf8d42..c13cb188dc179 100644
--- a/sys/dev/alc/if_alc.c
+++ b/sys/dev/alc/if_alc.c
@@ -532,13 +532,11 @@ alc_phy_reset(struct alc_softc *sc)
uint16_t data;
/* Reset magic from Linux. */
- CSR_WRITE_2(sc, ALC_GPHY_CFG,
- GPHY_CFG_HIB_EN | GPHY_CFG_HIB_PULSE | GPHY_CFG_SEL_ANA_RESET);
+ CSR_WRITE_2(sc, ALC_GPHY_CFG, GPHY_CFG_SEL_ANA_RESET);
CSR_READ_2(sc, ALC_GPHY_CFG);
DELAY(10 * 1000);
- CSR_WRITE_2(sc, ALC_GPHY_CFG,
- GPHY_CFG_EXT_RESET | GPHY_CFG_HIB_EN | GPHY_CFG_HIB_PULSE |
+ CSR_WRITE_2(sc, ALC_GPHY_CFG, GPHY_CFG_EXT_RESET |
GPHY_CFG_SEL_ANA_RESET);
CSR_READ_2(sc, ALC_GPHY_CFG);
DELAY(10 * 1000);
@@ -623,6 +621,23 @@ alc_phy_reset(struct alc_softc *sc)
alc_miibus_writereg(sc->alc_dev, sc->alc_phyaddr,
ALC_MII_DBG_DATA, data);
DELAY(1000);
+
+ /* Disable hibernation. */
+ alc_miibus_writereg(sc->alc_dev, sc->alc_phyaddr, ALC_MII_DBG_ADDR,
+ 0x0029);
+ data = alc_miibus_readreg(sc->alc_dev, sc->alc_phyaddr,
+ ALC_MII_DBG_DATA);
+ data &= ~0x8000;
+ alc_miibus_writereg(sc->alc_dev, sc->alc_phyaddr, ALC_MII_DBG_DATA,
+ data);
+
+ alc_miibus_writereg(sc->alc_dev, sc->alc_phyaddr, ALC_MII_DBG_ADDR,
+ 0x000B);
+ data = alc_miibus_readreg(sc->alc_dev, sc->alc_phyaddr,
+ ALC_MII_DBG_DATA);
+ data &= ~0x8000;
+ alc_miibus_writereg(sc->alc_dev, sc->alc_phyaddr, ALC_MII_DBG_DATA,
+ data);
}
static void
@@ -648,8 +663,7 @@ alc_phy_down(struct alc_softc *sc)
break;
default:
/* Force PHY down. */
- CSR_WRITE_2(sc, ALC_GPHY_CFG,
- GPHY_CFG_EXT_RESET | GPHY_CFG_HIB_EN | GPHY_CFG_HIB_PULSE |
+ CSR_WRITE_2(sc, ALC_GPHY_CFG, GPHY_CFG_EXT_RESET |
GPHY_CFG_SEL_ANA_RESET | GPHY_CFG_PHY_IDDQ |
GPHY_CFG_PWDOWN_HW);
DELAY(1000);
diff --git a/sys/dev/amr/amr_linux.c b/sys/dev/amr/amr_linux.c
index cb8c4573ef6bc..44e858ba804e4 100644
--- a/sys/dev/amr/amr_linux.c
+++ b/sys/dev/amr/amr_linux.c
@@ -30,6 +30,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/capability.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/module.h>
@@ -74,7 +75,7 @@ amr_linux_ioctl(struct thread *p, struct linux_ioctl_args *args)
struct file *fp;
int error;
- if ((error = fget(p, args->fd, &fp)) != 0)
+ if ((error = fget(p, args->fd, CAP_IOCTL, &fp)) != 0)
return (error);
error = fo_ioctl(fp, args->cmd, (caddr_t)args->arg, p->td_ucred, p);
fdrop(fp, p);
diff --git a/sys/dev/arcmsr/arcmsr.c b/sys/dev/arcmsr/arcmsr.c
index 962f6b87397d9..10bb5042891cc 100644
--- a/sys/dev/arcmsr/arcmsr.c
+++ b/sys/dev/arcmsr/arcmsr.c
@@ -68,6 +68,7 @@
** 1.20.00.21 02/08/2011 Ching Huang Implement I/O request timeout
** 02/14/2011 Ching Huang Modified pktRequestCount
** 1.20.00.21 03/03/2011 Ching Huang if a command timeout, then wait its ccb back before free it
+** 1.20.00.22 07/04/2011 Ching Huang Fixed multiple MTX panic
******************************************************************************************
* $FreeBSD$
*/
@@ -150,7 +151,7 @@
#define arcmsr_callout_init(a) callout_init(a);
#endif
-#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.21 2010-03-03"
+#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.22 2011-07-04"
#include <dev/arcmsr/arcmsr.h>
#define SRB_SIZE ((sizeof(struct CommandControlBlock)+0x1f) & 0xffe0)
#define ARCMSR_SRBS_POOL_SIZE (SRB_SIZE * ARCMSR_MAX_FREESRB_NUM)
@@ -1293,11 +1294,15 @@ static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb)
static void arcmsr_poll(struct cam_sim * psim)
{
struct AdapterControlBlock *acb;
+ int mutex;
acb = (struct AdapterControlBlock *)cam_sim_softc(psim);
- ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
+ mutex = mtx_owned(&acb->qbuffer_lock);
+ if( mutex == 0 )
+ ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
arcmsr_interrupt(acb);
- ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
+ if( mutex == 0 )
+ ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
return;
}
/*
@@ -2089,8 +2094,11 @@ struct CommandControlBlock * arcmsr_get_freesrb(struct AdapterControlBlock *acb)
{
struct CommandControlBlock *srb=NULL;
u_int32_t workingsrb_startindex, workingsrb_doneindex;
+ int mutex;
- ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
+ mutex = mtx_owned(&acb->qbuffer_lock);
+ if( mutex == 0 )
+ ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
workingsrb_doneindex=acb->workingsrb_doneindex;
workingsrb_startindex=acb->workingsrb_startindex;
srb=acb->srbworkingQ[workingsrb_startindex];
@@ -2101,7 +2109,8 @@ struct CommandControlBlock * arcmsr_get_freesrb(struct AdapterControlBlock *acb)
} else {
srb=NULL;
}
- ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
+ if( mutex == 0 )
+ ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
return(srb);
}
/*
diff --git a/sys/dev/ata/ata-pci.c b/sys/dev/ata/ata-pci.c
index cf579f80f2de7..374612ec88b48 100644
--- a/sys/dev/ata/ata-pci.c
+++ b/sys/dev/ata/ata-pci.c
@@ -49,8 +49,7 @@ __FBSDID("$FreeBSD$");
#include <dev/ata/ata-pci.h>
#include <ata_if.h>
-/* local vars */
-static MALLOC_DEFINE(M_ATAPCI, "ata_pci", "ATA driver PCI");
+MALLOC_DEFINE(M_ATAPCI, "ata_pci", "ATA driver PCI");
/* misc defines */
#define IOMASK 0xfffffffc
@@ -146,13 +145,14 @@ ata_pci_detach(device_t dev)
device_delete_child(dev, children[i]);
free(children, M_TEMP);
}
-
if (ctlr->r_irq) {
bus_teardown_intr(dev, ctlr->r_irq, ctlr->handle);
bus_release_resource(dev, SYS_RES_IRQ, ctlr->r_irq_rid, ctlr->r_irq);
if (ctlr->r_irq_rid != ATA_IRQ_RID)
pci_release_msi(dev);
}
+ if (ctlr->chipdeinit != NULL)
+ ctlr->chipdeinit(dev);
if (ctlr->r_res2)
bus_release_resource(dev, ctlr->r_type2, ctlr->r_rid2, ctlr->r_res2);
if (ctlr->r_res1)
diff --git a/sys/dev/ata/ata-pci.h b/sys/dev/ata/ata-pci.h
index 51064f6d7d5ab..3b90498e96171 100644
--- a/sys/dev/ata/ata-pci.h
+++ b/sys/dev/ata/ata-pci.h
@@ -55,6 +55,7 @@ struct ata_pci_controller {
int channels;
int ichannels;
int (*chipinit)(device_t);
+ int (*chipdeinit)(device_t);
int (*suspend)(device_t);
int (*resume)(device_t);
int (*ch_attach)(device_t);
@@ -579,6 +580,8 @@ int ata_sii_chipinit(device_t);
/* externs */
extern devclass_t ata_pci_devclass;
+MALLOC_DECLARE(M_ATAPCI);
+
/* macro for easy definition of all driver module stuff */
#define ATA_DECLARE_DRIVER(dname) \
static device_method_t __CONCAT(dname,_methods)[] = { \
diff --git a/sys/dev/ata/chipsets/ata-acard.c b/sys/dev/ata/chipsets/ata-acard.c
index bb81c48dc4cf2..761ec546efb33 100644
--- a/sys/dev/ata/chipsets/ata-acard.c
+++ b/sys/dev/ata/chipsets/ata-acard.c
@@ -59,6 +59,7 @@ struct ata_serialize {
/* local prototypes */
static int ata_acard_chipinit(device_t dev);
+static int ata_acard_chipdeinit(device_t dev);
static int ata_acard_ch_attach(device_t dev);
static int ata_acard_status(device_t dev);
static int ata_acard_850_setmode(device_t dev, int target, int mode);
@@ -93,6 +94,7 @@ ata_acard_probe(device_t dev)
ata_set_desc(dev);
ctlr->chipinit = ata_acard_chipinit;
+ ctlr->chipdeinit = ata_acard_chipdeinit;
return (BUS_PROBE_DEFAULT);
}
@@ -111,7 +113,7 @@ ata_acard_chipinit(device_t dev)
ctlr->setmode = ata_acard_850_setmode;
ctlr->locking = ata_serialize;
serial = malloc(sizeof(struct ata_serialize),
- M_TEMP, M_WAITOK | M_ZERO);
+ M_ATAPCI, M_WAITOK | M_ZERO);
ata_serialize_init(serial);
ctlr->chipset_data = serial;
}
@@ -121,6 +123,21 @@ ata_acard_chipinit(device_t dev)
}
static int
+ata_acard_chipdeinit(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+ struct ata_serialize *serial;
+
+ if (ctlr->chip->cfg1 == ATP_OLD) {
+ serial = ctlr->chipset_data;
+ mtx_destroy(&serial->locked_mtx);
+ free(serial, M_ATAPCI);
+ ctlr->chipset_data = NULL;
+ }
+ return (0);
+}
+
+static int
ata_acard_ch_attach(device_t dev)
{
struct ata_channel *ch = device_get_softc(dev);
diff --git a/sys/dev/ata/chipsets/ata-acerlabs.c b/sys/dev/ata/chipsets/ata-acerlabs.c
index 79e9d1192b16a..9d528daa999dd 100644
--- a/sys/dev/ata/chipsets/ata-acerlabs.c
+++ b/sys/dev/ata/chipsets/ata-acerlabs.c
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
/* local prototypes */
static int ata_ali_chipinit(device_t dev);
+static int ata_ali_chipdeinit(device_t dev);
static int ata_ali_ch_attach(device_t dev);
static int ata_ali_sata_ch_attach(device_t dev);
static void ata_ali_reset(device_t dev);
@@ -95,6 +96,7 @@ ata_ali_probe(device_t dev)
ata_set_desc(dev);
ctlr->chipinit = ata_ali_chipinit;
+ ctlr->chipdeinit = ata_ali_chipdeinit;
return (BUS_PROBE_DEFAULT);
}
@@ -122,7 +124,7 @@ ata_ali_chipinit(device_t dev)
return 0;
/* Allocate resources for later use by channel attach routines. */
- res = malloc(sizeof(struct ali_sata_resources), M_TEMP, M_WAITOK);
+ res = malloc(sizeof(struct ali_sata_resources), M_ATAPCI, M_WAITOK);
for (i = 0; i < 4; i++) {
rid = PCIR_BAR(i);
res->bars[i] = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
@@ -173,6 +175,27 @@ ata_ali_chipinit(device_t dev)
}
static int
+ata_ali_chipdeinit(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+ struct ali_sata_resources *res;
+ int i;
+
+ if (ctlr->chip->cfg2 == ALI_SATA) {
+ res = ctlr->chipset_data;
+ for (i = 0; i < 4; i++) {
+ if (res->bars[i] != NULL) {
+ bus_release_resource(dev, SYS_RES_IOPORT,
+ PCIR_BAR(i), res->bars[i]);
+ }
+ }
+ free(res, M_ATAPCI);
+ ctlr->chipset_data = NULL;
+ }
+ return (0);
+}
+
+static int
ata_ali_ch_attach(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
diff --git a/sys/dev/ata/chipsets/ata-intel.c b/sys/dev/ata/chipsets/ata-intel.c
index e128051b5023a..c5c22cb9e8b96 100644
--- a/sys/dev/ata/chipsets/ata-intel.c
+++ b/sys/dev/ata/chipsets/ata-intel.c
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
/* local prototypes */
static int ata_intel_chipinit(device_t dev);
+static int ata_intel_chipdeinit(device_t dev);
static int ata_intel_ch_attach(device_t dev);
static void ata_intel_reset(device_t dev);
static int ata_intel_old_setmode(device_t dev, int target, int mode);
@@ -85,6 +86,18 @@ static void ata_intel_31244_reset(device_t dev);
#define INTEL_6CH2 8
#define INTEL_ICH7 16
+struct ata_intel_data {
+ struct mtx lock;
+ u_char smap[4];
+};
+
+#define ATA_INTEL_SMAP(ctlr, ch) \
+ &((struct ata_intel_data *)((ctlr)->chipset_data))->smap[(ch)->unit * 2]
+#define ATA_INTEL_LOCK(ctlr) \
+ mtx_lock(&((struct ata_intel_data *)((ctlr)->chipset_data))->lock)
+#define ATA_INTEL_UNLOCK(ctlr) \
+ mtx_unlock(&((struct ata_intel_data *)((ctlr)->chipset_data))->lock)
+
/*
* Intel chipset support functions
*/
@@ -206,6 +219,7 @@ ata_intel_probe(device_t dev)
ata_set_desc(dev);
ctlr->chipinit = ata_intel_chipinit;
+ ctlr->chipdeinit = ata_intel_chipdeinit;
return (BUS_PROBE_DEFAULT);
}
@@ -213,11 +227,14 @@ static int
ata_intel_chipinit(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(dev);
+ struct ata_intel_data *data;
if (ata_setup_interrupt(dev, ata_generic_intr))
return ENXIO;
- ctlr->chipset_data = NULL;
+ data = malloc(sizeof(struct ata_intel_data), M_ATAPCI, M_WAITOK | M_ZERO);
+ mtx_init(&data->lock, "Intel SATA lock", NULL, MTX_DEF);
+ ctlr->chipset_data = (void *)data;
/* good old PIIX needs special treatment (not implemented) */
if (ctlr->chip->chipid == ATA_I82371FB) {
@@ -305,6 +322,19 @@ ata_intel_chipinit(device_t dev)
}
static int
+ata_intel_chipdeinit(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(dev);
+ struct ata_intel_data *data;
+
+ data = ctlr->chipset_data;
+ mtx_destroy(&data->lock);
+ free(data, M_ATAPCI);
+ ctlr->chipset_data = NULL;
+ return (0);
+}
+
+static int
ata_intel_ch_attach(device_t dev)
{
struct ata_pci_controller *ctlr;
@@ -329,7 +359,7 @@ ata_intel_ch_attach(device_t dev)
ch->flags |= ATA_ALWAYS_DMASTAT;
if (ctlr->chip->max_dma >= ATA_SA150) {
- smap = (u_char *)&ctlr->chipset_data + ch->unit * 2;
+ smap = ATA_INTEL_SMAP(ctlr, ch);
map = pci_read_config(device_get_parent(dev), 0x90, 1);
if (ctlr->chip->cfg1 & INTEL_ICH5) {
map &= 0x07;
@@ -415,7 +445,7 @@ ata_intel_reset(device_t dev)
return (ata_generic_reset(dev));
/* Do hard-reset on respective SATA ports. */
- smap = (u_char *)&ctlr->chipset_data + ch->unit * 2;
+ smap = ATA_INTEL_SMAP(ctlr, ch);
mask = 1 << smap[0];
if ((ch->flags & ATA_NO_SLAVE) == 0)
mask |= (1 << smap[1]);
@@ -605,7 +635,7 @@ ata_intel_sata_ahci_read(device_t dev, int port, int reg, u_int32_t *result)
ctlr = device_get_softc(parent);
ch = device_get_softc(dev);
port = (port == 1) ? 1 : 0;
- smap = (u_char *)&ctlr->chipset_data + ch->unit * 2;
+ smap = ATA_INTEL_SMAP(ctlr, ch);
offset = 0x100 + smap[port] * 0x80;
switch (reg) {
case ATA_SSTATUS:
@@ -635,7 +665,7 @@ ata_intel_sata_cscr_read(device_t dev, int port, int reg, u_int32_t *result)
parent = device_get_parent(dev);
ctlr = device_get_softc(parent);
ch = device_get_softc(dev);
- smap = (u_char *)&ctlr->chipset_data + ch->unit * 2;
+ smap = ATA_INTEL_SMAP(ctlr, ch);
port = (port == 1) ? 1 : 0;
switch (reg) {
case ATA_SSTATUS:
@@ -650,9 +680,11 @@ ata_intel_sata_cscr_read(device_t dev, int port, int reg, u_int32_t *result)
default:
return (EINVAL);
}
+ ATA_INTEL_LOCK(ctlr);
pci_write_config(parent, 0xa0,
0x50 + smap[port] * 0x10 + reg * 4, 4);
*result = pci_read_config(parent, 0xa4, 4);
+ ATA_INTEL_UNLOCK(ctlr);
return (0);
}
@@ -680,8 +712,10 @@ ata_intel_sata_sidpr_read(device_t dev, int port, int reg, u_int32_t *result)
default:
return (EINVAL);
}
+ ATA_INTEL_LOCK(ctlr);
ATA_IDX_OUTL(ch, ATA_IDX_ADDR, ((ch->unit * 2 + port) << 8) + reg);
*result = ATA_IDX_INL(ch, ATA_IDX_DATA);
+ ATA_INTEL_UNLOCK(ctlr);
return (0);
}
@@ -698,7 +732,7 @@ ata_intel_sata_ahci_write(device_t dev, int port, int reg, u_int32_t value)
ctlr = device_get_softc(parent);
ch = device_get_softc(dev);
port = (port == 1) ? 1 : 0;
- smap = (u_char *)&ctlr->chipset_data + ch->unit * 2;
+ smap = ATA_INTEL_SMAP(ctlr, ch);
offset = 0x100 + smap[port] * 0x80;
switch (reg) {
case ATA_SSTATUS:
@@ -728,7 +762,7 @@ ata_intel_sata_cscr_write(device_t dev, int port, int reg, u_int32_t value)
parent = device_get_parent(dev);
ctlr = device_get_softc(parent);
ch = device_get_softc(dev);
- smap = (u_char *)&ctlr->chipset_data + ch->unit * 2;
+ smap = ATA_INTEL_SMAP(ctlr, ch);
port = (port == 1) ? 1 : 0;
switch (reg) {
case ATA_SSTATUS:
@@ -743,9 +777,11 @@ ata_intel_sata_cscr_write(device_t dev, int port, int reg, u_int32_t value)
default:
return (EINVAL);
}
+ ATA_INTEL_LOCK(ctlr);
pci_write_config(parent, 0xa0,
0x50 + smap[port] * 0x10 + reg * 4, 4);
pci_write_config(parent, 0xa4, value, 4);
+ ATA_INTEL_UNLOCK(ctlr);
return (0);
}
@@ -773,8 +809,10 @@ ata_intel_sata_sidpr_write(device_t dev, int port, int reg, u_int32_t value)
default:
return (EINVAL);
}
+ ATA_INTEL_LOCK(ctlr);
ATA_IDX_OUTL(ch, ATA_IDX_ADDR, ((ch->unit * 2 + port) << 8) + reg);
ATA_IDX_OUTL(ch, ATA_IDX_DATA, value);
+ ATA_INTEL_UNLOCK(ctlr);
return (0);
}
diff --git a/sys/dev/ata/chipsets/ata-nvidia.c b/sys/dev/ata/chipsets/ata-nvidia.c
index b1da6f0ecccc3..2edc0f1471df1 100644
--- a/sys/dev/ata/chipsets/ata-nvidia.c
+++ b/sys/dev/ata/chipsets/ata-nvidia.c
@@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
/* local prototypes */
static int ata_nvidia_chipinit(device_t dev);
static int ata_nvidia_ch_attach(device_t dev);
+static int ata_nvidia_ch_attach_dumb(device_t dev);
static int ata_nvidia_status(device_t dev);
static void ata_nvidia_reset(device_t dev);
static int ata_nvidia_setmode(device_t dev, int target, int mode);
@@ -62,6 +63,7 @@ static int ata_nvidia_setmode(device_t dev, int target, int mode);
#define NV4 0x01
#define NVQ 0x02
#define NVAHCI 0x04
+#define NVNOFORCE 0x08
/*
@@ -158,7 +160,7 @@ ata_nvidia_probe(device_t dev)
{ ATA_NFORCE_MCP79_AA, 0, NVAHCI, 0, ATA_SA300, "nForce MCP79" },
{ ATA_NFORCE_MCP79_AB, 0, NVAHCI, 0, ATA_SA300, "nForce MCP79" },
{ ATA_NFORCE_MCP89_A0, 0, NVAHCI, 0, ATA_SA300, "nForce MCP89" },
- { ATA_NFORCE_MCP89_A1, 0, NVAHCI, 0, ATA_SA300, "nForce MCP89" },
+ { ATA_NFORCE_MCP89_A1, 0, NVAHCI|NVNOFORCE, 0, ATA_SA300, "nForce MCP89" },
{ ATA_NFORCE_MCP89_A2, 0, NVAHCI, 0, ATA_SA300, "nForce MCP89" },
{ ATA_NFORCE_MCP89_A3, 0, NVAHCI, 0, ATA_SA300, "nForce MCP89" },
{ ATA_NFORCE_MCP89_A4, 0, NVAHCI, 0, ATA_SA300, "nForce MCP89" },
@@ -178,7 +180,9 @@ ata_nvidia_probe(device_t dev)
return ENXIO;
ata_set_desc(dev);
- if (ctlr->chip->cfg1 & NVAHCI)
+ if ((ctlr->chip->cfg1 & NVAHCI) &&
+ ((ctlr->chip->cfg1 & NVNOFORCE) == 0 ||
+ pci_get_subclass(dev) != PCIS_STORAGE_IDE))
ctlr->chipinit = ata_ahci_chipinit;
else
ctlr->chipinit = ata_nvidia_chipinit;
@@ -193,7 +197,10 @@ ata_nvidia_chipinit(device_t dev)
if (ata_setup_interrupt(dev, ata_generic_intr))
return ENXIO;
- if (ctlr->chip->max_dma >= ATA_SA150) {
+ if (ctlr->chip->cfg1 & NVAHCI) {
+ ctlr->ch_attach = ata_nvidia_ch_attach_dumb;
+ ctlr->setmode = ata_sata_setmode;
+ } else if (ctlr->chip->max_dma >= ATA_SA150) {
if (pci_read_config(dev, PCIR_BAR(5), 1) & 1)
ctlr->r_type2 = SYS_RES_IOPORT;
else
@@ -264,6 +271,17 @@ ata_nvidia_ch_attach(device_t dev)
return 0;
}
+static int
+ata_nvidia_ch_attach_dumb(device_t dev)
+{
+ struct ata_channel *ch = device_get_softc(dev);
+
+ if (ata_pci_ch_attach(dev))
+ return ENXIO;
+ ch->flags |= ATA_SATA;
+ return 0;
+}
+
static int
ata_nvidia_status(device_t dev)
{
diff --git a/sys/dev/ata/chipsets/ata-promise.c b/sys/dev/ata/chipsets/ata-promise.c
index bee7bbad89e02..2f8b2a5ec131a 100644
--- a/sys/dev/ata/chipsets/ata-promise.c
+++ b/sys/dev/ata/chipsets/ata-promise.c
@@ -280,7 +280,7 @@ ata_promise_chipinit(device_t dev)
/* setup host packet controls */
hpkt = malloc(sizeof(struct ata_promise_sx4),
- M_TEMP, M_NOWAIT | M_ZERO);
+ M_ATAPCI, M_NOWAIT | M_ZERO);
mtx_init(&hpkt->mtx, "ATA promise HPKT lock", NULL, MTX_DEF);
TAILQ_INIT(&hpkt->queue);
hpkt->busy = 0;
diff --git a/sys/dev/ath/ath_dfs/null/dfs_null.c b/sys/dev/ath/ath_dfs/null/dfs_null.c
index 2f050a40d1cfa..a3bae91458568 100644
--- a/sys/dev/ath/ath_dfs/null/dfs_null.c
+++ b/sys/dev/ath/ath_dfs/null/dfs_null.c
@@ -61,7 +61,7 @@ __FBSDID("$FreeBSD$");
#include <net/bpf.h>
#ifdef INET
-#include <netinet/in.h>
+#include <netinet/in.h>
#include <netinet/if_ether.h>
#endif
@@ -141,12 +141,80 @@ ath_dfs_tasklet_needed(struct ath_softc *sc, struct ieee80211_channel *chan)
}
/*
- * Handle ioctl requests from the diagnostic interface
+ * Handle ioctl requests from the diagnostic interface.
+ *
+ * The initial part of this code resembles ath_ioctl_diag();
+ * it's likely a good idea to reduce duplication between
+ * these two routines.
*/
int
ath_ioctl_phyerr(struct ath_softc *sc, struct ath_diag *ad)
{
- return 1;
+ unsigned int id = ad->ad_id & ATH_DIAG_ID;
+ void *indata = NULL;
+ void *outdata = NULL;
+ u_int32_t insize = ad->ad_in_size;
+ u_int32_t outsize = ad->ad_out_size;
+ int error = 0;
+ HAL_PHYERR_PARAM peout;
+ HAL_PHYERR_PARAM *pe;
+
+ if (ad->ad_id & ATH_DIAG_IN) {
+ /*
+ * Copy in data.
+ */
+ indata = malloc(insize, M_TEMP, M_NOWAIT);
+ if (indata == NULL) {
+ error = ENOMEM;
+ goto bad;
+ }
+ error = copyin(ad->ad_in_data, indata, insize);
+ if (error)
+ goto bad;
+ }
+ if (ad->ad_id & ATH_DIAG_DYN) {
+ /*
+ * Allocate a buffer for the results (otherwise the HAL
+ * returns a pointer to a buffer where we can read the
+ * results). Note that we depend on the HAL leaving this
+ * pointer for us to use below in reclaiming the buffer;
+ * may want to be more defensive.
+ */
+ outdata = malloc(outsize, M_TEMP, M_NOWAIT);
+ if (outdata == NULL) {
+ error = ENOMEM;
+ goto bad;
+ }
+ }
+ switch (id) {
+ case DFS_SET_THRESH:
+ if (insize < sizeof(HAL_PHYERR_PARAM)) {
+ error = EINVAL;
+ break;
+ }
+ pe = (HAL_PHYERR_PARAM *) indata;
+ ath_hal_enabledfs(sc->sc_ah, pe);
+ break;
+ case DFS_GET_THRESH:
+ memset(&peout, 0, sizeof(peout));
+ outsize = sizeof(HAL_PHYERR_PARAM);
+ ath_hal_getdfsthresh(sc->sc_ah, &peout);
+ pe = (HAL_PHYERR_PARAM *) outdata;
+ memcpy(pe, &peout, sizeof(*pe));
+ break;
+ default:
+ error = EINVAL;
+ }
+ if (outsize < ad->ad_out_size)
+ ad->ad_out_size = outsize;
+ if (outdata && copyout(outdata, ad->ad_out_data, ad->ad_out_size))
+ error = EFAULT;
+bad:
+ if ((ad->ad_id & ATH_DIAG_IN) && indata != NULL)
+ free(indata, M_TEMP);
+ if ((ad->ad_id & ATH_DIAG_DYN) && outdata != NULL)
+ free(outdata, M_TEMP);
+ return error;
}
/*
diff --git a/sys/dev/ath/ath_hal/ah.c b/sys/dev/ath/ath_hal/ah.c
index 647f32205bd38..4055079dc71ca 100644
--- a/sys/dev/ath/ath_hal/ah.c
+++ b/sys/dev/ath/ath_hal/ah.c
@@ -522,6 +522,9 @@ ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
case HAL_CAP_REG_DMN: /* regulatory domain */
*result = AH_PRIVATE(ah)->ah_currentRD;
return HAL_OK;
+ case HAL_CAP_DFS_DMN: /* DFS Domain */
+ *result = AH_PRIVATE(ah)->ah_dfsDomain;
+ return HAL_OK;
case HAL_CAP_CIPHER: /* cipher handled in hardware */
case HAL_CAP_TKIP_MIC: /* handle TKIP MIC in hardware */
return HAL_ENOTSUPP;
@@ -654,6 +657,8 @@ ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
}
case HAL_CAP_RXDESC_SELFLINK: /* hardware supports self-linked final RX descriptors correctly */
return pCap->halHasRxSelfLinkedTail ? HAL_OK : HAL_ENOTSUPP;
+ case HAL_CAP_LONG_RXDESC_TSF: /* 32 bit TSF in RX descriptor? */
+ return pCap->halHasLongRxDescTsf ? HAL_OK : HAL_ENOTSUPP;
default:
return HAL_EINVAL;
}
@@ -1219,3 +1224,37 @@ ath_ee_interpolate(uint16_t target, uint16_t srcLeft, uint16_t srcRight,
}
return rv;
}
+
+/*
+ * Adjust the TSF.
+ */
+void
+ath_hal_adjusttsf(struct ath_hal *ah, int32_t tsfdelta)
+{
+ /* XXX handle wrap/overflow */
+ OS_REG_WRITE(ah, AR_TSF_L32, OS_REG_READ(ah, AR_TSF_L32) + tsfdelta);
+}
+
+/*
+ * Enable or disable CCA.
+ */
+void
+ath_hal_setcca(struct ath_hal *ah, int ena)
+{
+ /*
+ * NB: fill me in; this is not provided by default because disabling
+ * CCA in most locales violates regulatory.
+ */
+}
+
+/*
+ * Get CCA setting.
+ */
+int
+ath_hal_getcca(struct ath_hal *ah)
+{
+ u_int32_t diag;
+ if (ath_hal_getcapability(ah, HAL_CAP_DIAG, 0, &diag) != HAL_OK)
+ return 1;
+ return ((diag & 0x500000) == 0);
+}
diff --git a/sys/dev/ath/ath_hal/ah.h b/sys/dev/ath/ath_hal/ah.h
index f81e6aab27365..f4254c14fa878 100644
--- a/sys/dev/ath/ath_hal/ah.h
+++ b/sys/dev/ath/ath_hal/ah.h
@@ -148,6 +148,7 @@ typedef enum {
HAL_CAP_BSSIDMATCH = 238, /* hardware has disable bssid match */
HAL_CAP_STREAMS = 239, /* how many 802.11n spatial streams are available */
HAL_CAP_RXDESC_SELFLINK = 242, /* support a self-linked tail RX descriptor */
+ HAL_CAP_LONG_RXDESC_TSF = 243, /* hardware supports 32bit TSF in RX descriptor */
} HAL_CAPABILITY_TYPE;
/*
@@ -718,22 +719,32 @@ typedef struct {
u_int32_t pe_relpwr; /* Relative power threshold in 0.5dB steps */
u_int32_t pe_relstep; /* Pulse Relative step threshold in 0.5dB steps */
u_int32_t pe_maxlen; /* Max length of radar sign in 0.8us units */
- HAL_BOOL pe_usefir128; /* Use the average in-band power measured over 128 cycles */
- HAL_BOOL pe_blockradar; /*
+ int32_t pe_usefir128; /* Use the average in-band power measured over 128 cycles */
+ int32_t pe_blockradar; /*
* Enable to block radar check if pkt detect is done via OFDM
* weak signal detect or pkt is detected immediately after tx
* to rx transition
*/
- HAL_BOOL pe_enmaxrssi; /*
+ int32_t pe_enmaxrssi; /*
* Enable to use the max rssi instead of the last rssi during
* fine gain changes for radar detection
*/
- HAL_BOOL pe_extchannel; /* Enable DFS on ext channel */
+ int32_t pe_extchannel; /* Enable DFS on ext channel */
+ int32_t pe_enabled; /* Whether radar detection is enabled */
} HAL_PHYERR_PARAM;
#define HAL_PHYERR_PARAM_NOVAL 65535
#define HAL_PHYERR_PARAM_ENABLE 0x8000 /* Enable/Disable if applicable */
+/*
+ * DFS operating mode flags.
+ */
+typedef enum {
+ HAL_DFS_UNINIT_DOMAIN = 0, /* Uninitialized dfs domain */
+ HAL_DFS_FCC_DOMAIN = 1, /* FCC3 dfs domain */
+ HAL_DFS_ETSI_DOMAIN = 2, /* ETSI dfs domain */
+ HAL_DFS_MKK4_DOMAIN = 3, /* Japan dfs domain */
+} HAL_DFS_DOMAIN;
/*
* Flag for setting QUIET period
@@ -746,15 +757,18 @@ typedef enum {
} HAL_QUIET_FLAG;
#define HAL_DFS_EVENT_PRICH 0x0000001
+#define HAL_DFS_EVENT_EXTCH 0x0000002
+#define HAL_DFS_EVENT_EXTEARLY 0x0000004
+#define HAL_DFS_EVENT_ISDC 0x0000008
-struct dfs_event {
+struct hal_dfs_event {
uint64_t re_full_ts; /* 64-bit full timestamp from interrupt time */
uint32_t re_ts; /* Original 15 bit recv timestamp */
uint8_t re_rssi; /* rssi of radar event */
uint8_t re_dur; /* duration of radar pulse */
uint32_t re_flags; /* Flags (see above) */
};
-typedef struct dfs_event HAL_DFS_EVENT;
+typedef struct hal_dfs_event HAL_DFS_EVENT;
typedef struct
{
@@ -765,7 +779,7 @@ typedef struct
int ah_dma_beacon_response_time;/* in TU's */
int ah_sw_beacon_response_time; /* in TU's */
int ah_additional_swba_backoff; /* in TU's */
-}HAL_OPS_CONFIG;
+} HAL_OPS_CONFIG;
/*
* Hardware Access Layer (HAL) API.
@@ -954,6 +968,7 @@ struct ath_hal {
HAL_BOOL __ahdecl(*ah_procRadarEvent)(struct ath_hal *ah,
struct ath_rx_status *rxs, uint64_t fulltsf,
const char *buf, HAL_DFS_EVENT *event);
+ HAL_BOOL __ahdecl(*ah_isFastClockEnabled)(struct ath_hal *ah);
/* Key Cache Functions */
uint32_t __ahdecl(*ah_getKeyCacheSize)(struct ath_hal*);
@@ -982,6 +997,7 @@ struct ath_hal {
void __ahdecl(*ah_setStationBeaconTimers)(struct ath_hal*,
const HAL_BEACON_STATE *);
void __ahdecl(*ah_resetStationBeaconTimers)(struct ath_hal*);
+ uint64_t __ahdecl(*ah_getNextTBTT)(struct ath_hal *);
/* 802.11n Functions */
HAL_BOOL __ahdecl(*ah_chainTxDesc)(struct ath_hal *,
@@ -1124,4 +1140,20 @@ extern uint32_t __ahdecl ath_computedur_ht(uint32_t frameLen, uint16_t rate,
extern uint16_t __ahdecl ath_hal_computetxtime(struct ath_hal *,
const HAL_RATE_TABLE *rates, uint32_t frameLen,
uint16_t rateix, HAL_BOOL shortPreamble);
+
+/*
+ * Adjust the TSF.
+ */
+extern void __ahdecl ath_hal_adjusttsf(struct ath_hal *ah, int32_t tsfdelta);
+
+/*
+ * Enable or disable CCA.
+ */
+void __ahdecl ath_hal_setcca(struct ath_hal *ah, int ena);
+
+/*
+ * Get CCA setting.
+ */
+int __ahdecl ath_hal_getcca(struct ath_hal *ah);
+
#endif /* _ATH_AH_H_ */
diff --git a/sys/dev/ath/ath_hal/ah_desc.h b/sys/dev/ath/ath_hal/ah_desc.h
index bd3e6a821e9ed..4651fc2d7cc09 100644
--- a/sys/dev/ath/ath_hal/ah_desc.h
+++ b/sys/dev/ath/ath_hal/ah_desc.h
@@ -158,6 +158,12 @@ enum {
HAL_PHYERR_CCK_RATE_ILLEGAL = 27, /* */
HAL_PHYERR_CCK_SERVICE = 30, /* */
HAL_PHYERR_CCK_RESTART = 31, /* */
+ HAL_PHYERR_CCK_LENGTH_ILLEGAL = 32, /* */
+ HAL_PHYERR_CCK_POWER_DROP = 33, /* */
+ /* AR5416 and later */
+ HAL_PHYERR_HT_CRC_ERROR = 34, /* */
+ HAL_PHYERR_HT_LENGTH_ILLEGAL = 35, /* */
+ HAL_PHYERR_HT_RATE_ILLEGAL = 36, /* */
};
/* value found in rs_keyix to mark invalid entries */
diff --git a/sys/dev/ath/ath_hal/ah_eeprom.h b/sys/dev/ath/ath_hal/ah_eeprom.h
index 2ca058982f306..b77fb6427c021 100644
--- a/sys/dev/ath/ath_hal/ah_eeprom.h
+++ b/sys/dev/ath/ath_hal/ah_eeprom.h
@@ -104,6 +104,7 @@ enum {
AR_EEP_PWDCLKIND, /* uint8_t* */
AR_EEP_TEMPSENSE_SLOPE, /* int8_t* */
AR_EEP_TEMPSENSE_SLOPE_PAL_ON, /* int8_t* */
+ AR_EEP_FRAC_N_5G, /* uint8_t* */
};
typedef struct {
diff --git a/sys/dev/ath/ath_hal/ah_eeprom_9287.c b/sys/dev/ath/ath_hal/ah_eeprom_9287.c
index 40550939bb6a1..099fe34b2b10d 100644
--- a/sys/dev/ath/ath_hal/ah_eeprom_9287.c
+++ b/sys/dev/ath/ath_hal/ah_eeprom_9287.c
@@ -298,11 +298,18 @@ ath_hal_9287EepromAttach(struct ath_hal *ah)
uint32_t sum;
HALASSERT(ee == AH_NULL);
-
- if (!ath_hal_eepromRead(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
- HALDEBUG(ah, HAL_DEBUG_ANY,
- "%s Error reading Eeprom MAGIC\n", __func__);
- return HAL_EEREAD;
+
+ /*
+ * Don't check magic if we're supplied with an EEPROM block,
+ * typically this is from Howl but it may also be from later
+ * boards w/ an embedded WMAC.
+ */
+ if (ah->ah_eepromdata == NULL) {
+ if (!ath_hal_eepromRead(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
+ HALDEBUG(ah, HAL_DEBUG_ANY,
+ "%s Error reading Eeprom MAGIC\n", __func__);
+ return HAL_EEREAD;
+ }
}
HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s Eeprom Magic = 0x%x\n",
__func__, magic);
@@ -328,7 +335,11 @@ ath_hal_9287EepromAttach(struct ath_hal *ah)
}
}
/* Convert to eeprom native eeprom endian format */
- if (isBigEndian()) {
+ /*
+ * XXX this is likely incorrect but will do for now
+ * XXX to get embedded boards working.
+ */
+ if (ah->ah_eepromdata == NULL && isBigEndian()) {
for (w = 0; w < NW(HAL_EEPROM_9287); w++)
eep_data[w] = __bswap16(eep_data[w]);
}
diff --git a/sys/dev/ath/ath_hal/ah_eeprom_v14.c b/sys/dev/ath/ath_hal/ah_eeprom_v14.c
index fdddea10605b9..37e973c16921a 100644
--- a/sys/dev/ath/ath_hal/ah_eeprom_v14.c
+++ b/sys/dev/ath/ath_hal/ah_eeprom_v14.c
@@ -97,6 +97,12 @@ v14EepromGet(struct ath_hal *ah, int param, void *val)
return HAL_OK;
} else
return HAL_EIO;
+ case AR_EEP_FRAC_N_5G:
+ if (IS_VERS(>=, AR5416_EEP_MINOR_VER_22)) {
+ *(uint8_t *) val = pBase->frac_n_5g;
+ } else
+ *(uint8_t *) val = 0;
+ return HAL_OK;
case AR_EEP_AMODE:
HALASSERT(val == AH_NULL);
return pBase->opCapFlags & AR5416_OPFLAGS_11A ?
diff --git a/sys/dev/ath/ath_hal/ah_eeprom_v14.h b/sys/dev/ath/ath_hal/ah_eeprom_v14.h
index 6061b2f85d313..7b2c898ce6ee2 100644
--- a/sys/dev/ath/ath_hal/ah_eeprom_v14.h
+++ b/sys/dev/ath/ath_hal/ah_eeprom_v14.h
@@ -187,7 +187,10 @@ typedef struct BaseEepHeader {
uint8_t rcChainMask; /* "1" if the card is an HB93 1x2 */
uint8_t desiredScaleCCK;
uint8_t pwr_table_offset;
- uint8_t frac_n_5g;
+ uint8_t frac_n_5g; /*
+ * bit 0: indicates that fracN synth
+ * mode applies to all 5G channels
+ */
uint8_t futureBase[21];
} __packed BASE_EEP_HEADER; // 64 B
diff --git a/sys/dev/ath/ath_hal/ah_eeprom_v4k.c b/sys/dev/ath/ath_hal/ah_eeprom_v4k.c
index 36a6e736f219f..927f08e394da6 100644
--- a/sys/dev/ath/ath_hal/ah_eeprom_v4k.c
+++ b/sys/dev/ath/ath_hal/ah_eeprom_v4k.c
@@ -75,8 +75,7 @@ v4kEepromGet(struct ath_hal *ah, int param, void *val)
case AR_EEP_RXGAIN_TYPE:
return AR5416_EEP_RXGAIN_ORIG;
case AR_EEP_TXGAIN_TYPE:
- return IS_VERS(>=, AR5416_EEP_MINOR_VER_19) ?
- pBase->txGainType : AR5416_EEP_TXGAIN_ORIG;
+ return pBase->txGainType;
case AR_EEP_OL_PWRCTRL:
HALASSERT(val == AH_NULL);
return HAL_EIO;
@@ -288,11 +287,17 @@ ath_hal_v4kEepromAttach(struct ath_hal *ah)
uint32_t sum;
HALASSERT(ee == AH_NULL);
-
- if (!ath_hal_eepromRead(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
- HALDEBUG(ah, HAL_DEBUG_ANY,
- "%s Error reading Eeprom MAGIC\n", __func__);
- return HAL_EEREAD;
+ /*
+ * Don't check magic if we're supplied with an EEPROM block,
+ * typically this is from Howl but it may also be from later
+ * boards w/ an embedded WMAC.
+ */
+ if (ah->ah_eepromdata == NULL) {
+ if (!ath_hal_eepromRead(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
+ HALDEBUG(ah, HAL_DEBUG_ANY,
+ "%s Error reading Eeprom MAGIC\n", __func__);
+ return HAL_EEREAD;
+ }
}
HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s Eeprom Magic = 0x%x\n",
__func__, magic);
@@ -318,7 +323,11 @@ ath_hal_v4kEepromAttach(struct ath_hal *ah)
}
}
/* Convert to eeprom native eeprom endian format */
- if (isBigEndian()) {
+ /*
+ * XXX this is likely incorrect but will do for now
+ * XXX to get embedded boards working.
+ */
+ if (ah->ah_eepromdata == NULL && isBigEndian()) {
for (w = 0; w < NW(struct ar5416eeprom_4k); w++)
eep_data[w] = __bswap16(eep_data[w]);
}
diff --git a/sys/dev/ath/ath_hal/ah_internal.h b/sys/dev/ath/ath_hal/ah_internal.h
index 120620c8751c3..79184bd236508 100644
--- a/sys/dev/ath/ath_hal/ah_internal.h
+++ b/sys/dev/ath/ath_hal/ah_internal.h
@@ -208,7 +208,8 @@ typedef struct {
halBssidMatchSupport : 1,
hal4kbSplitTransSupport : 1,
halHasRxSelfLinkedTail : 1,
- halSupportsFastClock5GHz : 1; /* Hardware supports 5ghz fast clock; check eeprom/channel before using */
+ halSupportsFastClock5GHz : 1, /* Hardware supports 5ghz fast clock; check eeprom/channel before using */
+ halHasLongRxDescTsf : 1;
uint32_t halWirelessModes;
uint16_t halTotalQueues;
uint16_t halKeyCacheSize;
@@ -303,6 +304,7 @@ struct ath_hal_private {
*/
HAL_REG_DOMAIN ah_currentRD; /* EEPROM regulatory domain */
HAL_REG_DOMAIN ah_currentRDext; /* EEPROM extended regdomain flags */
+ HAL_DFS_DOMAIN ah_dfsDomain; /* current DFS domain */
HAL_CHANNEL_INTERNAL ah_channels[AH_MAXCHAN]; /* private chan state */
u_int ah_nchan; /* valid items in ah_channels */
const struct regDomain *ah_rd2GHz; /* reg state for 2G band */
diff --git a/sys/dev/ath/ath_hal/ah_regdomain.c b/sys/dev/ath/ath_hal/ah_regdomain.c
index 9aae3324a00da..7298c6bee8af9 100644
--- a/sys/dev/ath/ath_hal/ah_regdomain.c
+++ b/sys/dev/ath/ath_hal/ah_regdomain.c
@@ -125,6 +125,8 @@ static const struct cmode modes[] = {
IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D },
};
+static void ath_hal_update_dfsdomain(struct ath_hal *ah);
+
static OS_INLINE uint16_t
getEepromRD(struct ath_hal *ah)
{
@@ -526,6 +528,7 @@ getchannels(struct ath_hal *ah,
"skip ecm channel\n");
continue;
}
+#if 0
if ((fband->useDfs & dfsMask) &&
(cm->flags & IEEE80211_CHAN_HT40)) {
/* NB: DFS and HT40 don't mix */
@@ -533,6 +536,7 @@ getchannels(struct ath_hal *ah,
"skip HT40 chan, DFS required\n");
continue;
}
+#endif
/*
* Make sure that channel separation
* meets the requirement.
@@ -698,8 +702,12 @@ ath_hal_init_channels(struct ath_hal *ah,
ah->ah_countryCode = country->countryCode;
HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s: cc %u\n",
__func__, ah->ah_countryCode);
+
+ /* Update current DFS domain */
+ ath_hal_update_dfsdomain(ah);
} else
status = HAL_EINVAL;
+
return status;
}
@@ -744,6 +752,11 @@ ath_hal_set_channels(struct ath_hal *ah,
__func__, ah->ah_countryCode);
} else
status = HAL_EINVAL;
+
+ if (status == HAL_OK) {
+ /* Update current DFS domain */
+ (void) ath_hal_update_dfsdomain(ah);
+ }
return status;
}
@@ -809,6 +822,33 @@ ath_hal_getctl(struct ath_hal *ah, const struct ieee80211_channel *c)
return ctl;
}
+
+/*
+ * Update the current dfsDomain setting based on the given
+ * country code.
+ *
+ * Since FreeBSD/net80211 allows the channel set to change
+ * after the card has been setup (via ath_hal_init_channels())
+ * this function method is needed to update ah_dfsDomain.
+ */
+void
+ath_hal_update_dfsdomain(struct ath_hal *ah)
+{
+ const REG_DOMAIN *rd5GHz = AH_PRIVATE(ah)->ah_rd5GHz;
+ HAL_DFS_DOMAIN dfsDomain = HAL_DFS_UNINIT_DOMAIN;
+
+ if (rd5GHz->dfsMask & DFS_FCC3)
+ dfsDomain = HAL_DFS_FCC_DOMAIN;
+ if (rd5GHz->dfsMask & DFS_ETSI)
+ dfsDomain = HAL_DFS_ETSI_DOMAIN;
+ if (rd5GHz->dfsMask & DFS_MKK4)
+ dfsDomain = HAL_DFS_MKK4_DOMAIN;
+ AH_PRIVATE(ah)->ah_dfsDomain = dfsDomain;
+ HALDEBUG(ah, HAL_DEBUG_REGDOMAIN, "%s ah_dfsDomain: %d\n",
+ __func__, AH_PRIVATE(ah)->ah_dfsDomain);
+}
+
+
/*
* Return the max allowed antenna gain and apply any regulatory
* domain specific changes.
diff --git a/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_ctry.h b/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_ctry.h
index a85bd92d41f89..af4824c3b5a03 100644
--- a/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_ctry.h
+++ b/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_ctry.h
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
- * Copyright (c) 2005-2006 Atheros Communications, Inc.
+ * Copyright (c) 2005-2011 Atheros Communications, Inc.
* All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -34,7 +34,7 @@ static COUNTRY_CODE_TO_ENUM_RD allCountries[] = {
{ CTRY_ALGERIA, NULL1_WORLD },
{ CTRY_ARGENTINA, APL3_WORLD },
{ CTRY_ARMENIA, ETSI4_WORLD },
- { CTRY_AUSTRALIA, FCC2_WORLD },
+ { CTRY_AUSTRALIA, FCC3_WORLD },
{ CTRY_AUSTRIA, ETSI1_WORLD },
{ CTRY_AZERBAIJAN, ETSI4_WORLD },
{ CTRY_BAHRAIN, APL6_WORLD },
diff --git a/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_regenum.h b/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_regenum.h
index f68743b078bf7..bc569cb00a3ed 100644
--- a/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_regenum.h
+++ b/sys/dev/ath/ath_hal/ah_regdomain/ah_rd_regenum.h
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
- * Copyright (c) 2005-2006 Atheros Communications, Inc.
+ * Copyright (c) 2005-2011 Atheros Communications, Inc.
* All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -46,6 +46,7 @@ enum {
FCC1_WORLD = 0x11, /* Hong Kong */
FCC4_FCCA = 0x12, /* USA - Public Safety */
FCC5_FCCB = 0x13, /* USA w/ 1/2 and 1/4 width channels */
+ FCC6_FCCA = 0x14, /* Canada for AP only */
FCC2_FCCA = 0x20, /* Canada */
FCC2_WORLD = 0x21, /* Australia & HK */
@@ -62,6 +63,8 @@ enum {
ETSI4_ETSIC = 0x38,
ETSI5_WORLD = 0x39,
ETSI6_WORLD = 0x34, /* Bulgaria */
+ ETSI8_WORLD = 0x3D, /* Russia */
+ ETSI9_WORLD = 0x3E, /* Ukraine */
ETSI_RESERVED = 0x33, /* Reserved (Do not used) */
MKK1_MKKA = 0x40, /* Japan (JP1) */
@@ -77,8 +80,9 @@ enum {
MKK1_MKKA1 = 0x4A, /* Japan (JE1) */
MKK1_MKKA2 = 0x4B, /* Japan (JE2) */
MKK1_MKKC = 0x4C, /* Japan (MKK1_MKKA,except Ch14) */
+ APL2_FCCA = 0x4D, /* Mobile customer */
- APL3_FCCA = 0x50,
+ APL3_FCCA = 0x50,
APL1_WORLD = 0x52, /* Latin America */
APL1_FCCA = 0x53,
APL1_APLA = 0x54,
@@ -86,9 +90,10 @@ enum {
APL2_ETSIC = 0x56, /* Venezuela */
APL5_WORLD = 0x58, /* Chile */
APL6_WORLD = 0x5B, /* Singapore */
- APL7_FCCA = 0x5C, /* Taiwan 5.47 Band */
- APL8_WORLD = 0x5D, /* Malaysia 5GHz */
- APL9_WORLD = 0x5E, /* Korea 5GHz */
+ APL7_FCCA = 0x5C, /* Taiwan 5.47 Band */
+ APL8_WORLD = 0x5D, /* Malaysia 5GHz */
+ APL9_WORLD = 0x5E, /* Korea 5GHz; before 11/2007; now APs only */
+ APL10_WORLD = 0x5F, /* Korea 5GHz; After 11/2007; STAs only */
/*
* World mode SKUs
@@ -97,16 +102,17 @@ enum {
WOR1_WORLD = 0x61, /* World1 (WO1 SKU) */
WOR2_WORLD = 0x62, /* World2 (WO2 SKU) */
WOR3_WORLD = 0x63, /* World3 (WO3 SKU) */
- WOR4_WORLD = 0x64, /* World4 (WO4 SKU) */
- WOR5_ETSIC = 0x65, /* World5 (WO5 SKU) */
+ WOR4_WORLD = 0x64, /* World4 (WO4 SKU) */
+ WOR5_ETSIC = 0x65, /* World5 (WO5 SKU) */
WOR01_WORLD = 0x66, /* World0-1 (WW0-1 SKU) */
WOR02_WORLD = 0x67, /* World0-2 (WW0-2 SKU) */
EU1_WORLD = 0x68, /* Same as World0-2 (WW0-2 SKU), except active scan ch1-13. No ch14 */
- WOR9_WORLD = 0x69, /* World9 (WO9 SKU) */
- WORA_WORLD = 0x6A, /* WorldA (WOA SKU) */
+ WOR9_WORLD = 0x69, /* World9 (WO9 SKU) */
+ WORA_WORLD = 0x6A, /* WorldA (WOA SKU) */
WORB_WORLD = 0x6B, /* WorldB (WOB SKU) */
+ WORC_WORLD = 0x6C, /* WorldC (WOC SKU) */
MKK3_MKKB = 0x80, /* Japan UNI-1 even + MKKB */
MKK3_MKKA2 = 0x81, /* Japan UNI-1 even + MKKA2 */
@@ -132,17 +138,48 @@ enum {
MKK8_MKKA2 = 0x90, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKA2 */
MKK8_MKKC = 0x91, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKC */
- /* Following definitions are used only by s/w to map old
- * Japan SKUs.
+ MKK14_MKKA1 = 0x92, /* Japan UNI-1 even + UNI-1 odd + 4.9GHz + MKKA1 */
+ MKK15_MKKA1 = 0x93, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + 4.9GHz + MKKA1 */
+
+ MKK10_FCCA = 0xD0, /* Japan UNI-1 even + UNI-2 + 4.9GHz + FCCA */
+ MKK10_MKKA1 = 0xD1, /* Japan UNI-1 even + UNI-2 + 4.9GHz + MKKA1 */
+ MKK10_MKKC = 0xD2, /* Japan UNI-1 even + UNI-2 + 4.9GHz + MKKC */
+ MKK10_MKKA2 = 0xD3, /* Japan UNI-1 even + UNI-2 + 4.9GHz + MKKA2 */
+
+ MKK11_MKKA = 0xD4, /* Japan UNI-1 even + UNI-2 + mid-band + 4.9GHz + MKKA */
+ MKK11_FCCA = 0xD5, /* Japan UNI-1 even + UNI-2 + mid-band + 4.9GHz + FCCA */
+ MKK11_MKKA1 = 0xD6, /* Japan UNI-1 even + UNI-2 + mid-band + 4.9GHz + MKKA1 */
+ MKK11_MKKC = 0xD7, /* Japan UNI-1 even + UNI-2 + mid-band + 4.9GHz + MKKC */
+ MKK11_MKKA2 = 0xD8, /* Japan UNI-1 even + UNI-2 + mid-band + 4.9GHz + MKKA2 */
+
+ MKK12_MKKA = 0xD9, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + 4.9GHz + MKKA */
+ MKK12_FCCA = 0xDA, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + 4.9GHz + FCCA */
+ MKK12_MKKA1 = 0xDB, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + 4.9GHz + MKKA1 */
+ MKK12_MKKC = 0xDC, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + 4.9GHz + MKKC */
+ MKK12_MKKA2 = 0xDD, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + 4.9GHz + MKKA2 */
+
+ MKK13_MKKB = 0xDE, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + mid-band + MKKB + All passive + no adhoc */
+
+ /*
+ * Following definitions are used only by s/w to map old
+ * Japan SKUs.
*/
- MKK3_MKKA = 0xF0, /* Japan UNI-1 even + MKKA */
- MKK3_MKKA1 = 0xF1, /* Japan UNI-1 even + MKKA1 */
- MKK3_FCCA = 0xF2, /* Japan UNI-1 even + FCCA */
- MKK4_MKKA = 0xF3, /* Japan UNI-1 even + UNI-2 + MKKA */
- MKK4_MKKA1 = 0xF4, /* Japan UNI-1 even + UNI-2 + MKKA1 */
- MKK4_FCCA = 0xF5, /* Japan UNI-1 even + UNI-2 + FCCA */
- MKK9_MKKA = 0xF6, /* Japan UNI-1 even + 4.9GHz */
- MKK10_MKKA = 0xF7, /* Japan UNI-1 even + UNI-2 + 4.9GHz */
+ MKK3_MKKA = 0xF0, /* Japan UNI-1 even + MKKA */
+ MKK3_MKKA1 = 0xF1, /* Japan UNI-1 even + MKKA1 */
+ MKK3_FCCA = 0xF2, /* Japan UNI-1 even + FCCA */
+ MKK4_MKKA = 0xF3, /* Japan UNI-1 even + UNI-2 + MKKA */
+ MKK4_MKKA1 = 0xF4, /* Japan UNI-1 even + UNI-2 + MKKA1 */
+ MKK4_FCCA = 0xF5, /* Japan UNI-1 even + UNI-2 + FCCA */
+ MKK9_MKKA = 0xF6, /* Japan UNI-1 even + 4.9GHz */
+ MKK10_MKKA = 0xF7, /* Japan UNI-1 even + UNI-2 + 4.9GHz */
+ MKK6_MKKA1 = 0xF8, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKA1 */
+ MKK6_FCCA = 0xF9, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + FCCA */
+ MKK7_MKKA1 = 0xFA, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + MKKA1 */
+ MKK7_FCCA = 0xFB, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + FCCA */
+ MKK9_FCCA = 0xFC, /* Japan UNI-1 even + 4.9GHz + FCCA */
+ MKK9_MKKA1 = 0xFD, /* Japan UNI-1 even + 4.9GHz + MKKA1 */
+ MKK9_MKKC = 0xFE, /* Japan UNI-1 even + 4.9GHz + MKKC */
+ MKK9_MKKA2 = 0xFF, /* Japan UNI-1 even + 4.9GHz + MKKA2 */
/*
* Regulator domains ending in a number (e.g. APL1,
@@ -157,8 +194,10 @@ enum {
APL4 = 0x0450, /* Jordan */
APL5 = 0x0550, /* Chile */
APL6 = 0x0650, /* Singapore */
+ APL7 = 0x0750, /* Taiwan, disable ch52 */
APL8 = 0x0850, /* Malaysia */
- APL9 = 0x0950, /* Korea (South) ROC 3 */
+ APL9 = 0x0950, /* Korea. Before 11/2007. Now used only by APs */
+ APL10 = 0x1050, /* Korea. After 11/2007. For STAs only */
ETSI1 = 0x0130, /* Europe & others */
ETSI2 = 0x0230, /* Europe & others */
@@ -166,16 +205,19 @@ enum {
ETSI4 = 0x0430, /* Europe & others */
ETSI5 = 0x0530, /* Europe & others */
ETSI6 = 0x0630, /* Europe & others */
+ ETSI8 = 0x0830, /* Russia */
+ ETSI9 = 0x0930, /* Ukraine */
ETSIA = 0x0A30, /* France */
ETSIB = 0x0B30, /* Israel */
ETSIC = 0x0C30, /* Latin America */
FCC1 = 0x0110, /* US & others */
FCC2 = 0x0120, /* Canada, Australia & New Zealand */
- FCC3 = 0x0160, /* US w/new middle band & DFS */
- FCC4 = 0x0165, /* US Public Safety */
- FCC5 = 0x0166, /* US w/ 1/2 and 1/4 width channels */
- FCCA = 0x0A10,
+ FCC3 = 0x0160, /* US w/new middle band & DFS */
+ FCC4 = 0x0165, /* US Public Safety */
+ FCC5 = 0x0166, /* US w/ 1/2 and 1/4 width channels */
+ FCC6 = 0x0610, /* Canada and Australia */
+ FCCA = 0x0A10,
FCCB = 0x0A11, /* US w/ 1/2 and 1/4 width channels */
APLD = 0x0D50, /* South Korea */
@@ -188,8 +230,14 @@ enum {
MKK6 = 0x0640, /* Japan (UNI-1 odd + UNI-1 even) */
MKK7 = 0x0740, /* Japan (UNI-1 odd + UNI-1 even + UNI-2 */
MKK8 = 0x0840, /* Japan (UNI-1 odd + UNI-1 even + UNI-2 + mid-band) */
- MKK9 = 0x0940, /* Japan (UNI-1 even + 4.9 GHZ) */
- MKK10 = 0x0B40, /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */
+ MKK9 = 0x0940, /* Japan (UNI-1 even + 4.9 GHZ) */
+ MKK10 = 0x0B40, /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */
+ MKK11 = 0x1140, /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */
+ MKK12 = 0x1240, /* Japan (UNI-1 even + UNI-2 + 4.9 GHZ) */
+ MKK13 = 0x0C40, /* Same as MKK8 but all passive and no adhoc 11a */
+ MKK14 = 0x1440, /* Japan UNI-1 even + UNI-1 odd + 4.9GHz */
+ MKK15 = 0x1540, /* Japan UNI-1 even + UNI-1 odd + UNI-2 + 4.9GHz */
+
MKKA = 0x0A40, /* Japan */
MKKC = 0x0A50,
diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210.h b/sys/dev/ath/ath_hal/ar5210/ar5210.h
index a8776726a3ba9..24718531566f3 100644
--- a/sys/dev/ath/ath_hal/ar5210/ar5210.h
+++ b/sys/dev/ath/ath_hal/ar5210/ar5210.h
@@ -268,6 +268,7 @@ extern void ar5210BeaconInit(struct ath_hal *, uint32_t, uint32_t);
extern void ar5210SetStaBeaconTimers(struct ath_hal *,
const HAL_BEACON_STATE *);
extern void ar5210ResetStaBeaconTimers(struct ath_hal *);
+extern uint64_t ar5210GetNextTBTT(struct ath_hal *);
extern HAL_BOOL ar5210IsInterruptPending(struct ath_hal *);
extern HAL_BOOL ar5210GetPendingInterrupts(struct ath_hal *, HAL_INT *);
diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c b/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c
index 41d957a614c6f..79c305511e6fd 100644
--- a/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c
+++ b/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c
@@ -148,6 +148,7 @@ static const struct ath_hal_private ar5210hal = {{
.ah_beaconInit = ar5210BeaconInit,
.ah_setStationBeaconTimers = ar5210SetStaBeaconTimers,
.ah_resetStationBeaconTimers = ar5210ResetStaBeaconTimers,
+ .ah_getNextTBTT = ar5210GetNextTBTT,
/* Interrupt Functions */
.ah_isInterruptPending = ar5210IsInterruptPending,
diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_beacon.c b/sys/dev/ath/ath_hal/ar5210/ar5210_beacon.c
index a613c9ca7d16a..e12b039723e5d 100644
--- a/sys/dev/ath/ath_hal/ar5210/ar5210_beacon.c
+++ b/sys/dev/ath/ath_hal/ar5210/ar5210_beacon.c
@@ -27,6 +27,17 @@
#include "ar5210/ar5210desc.h"
/*
+ * Return the hardware NextTBTT in TSF
+ */
+uint64_t
+ar5210GetNextTBTT(struct ath_hal *ah)
+{
+#define TU_TO_TSF(_tu) (((uint64_t)(_tu)) << 10)
+ return TU_TO_TSF(OS_REG_READ(ah, AR_TIMER0));
+#undef TU_TO_TSF
+}
+
+/*
* Initialize all of the hardware registers used to send beacons.
*/
void
diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211.h b/sys/dev/ath/ath_hal/ar5211/ar5211.h
index 0057ba425f98d..51acd38862c54 100644
--- a/sys/dev/ath/ath_hal/ar5211/ar5211.h
+++ b/sys/dev/ath/ath_hal/ar5211/ar5211.h
@@ -296,6 +296,7 @@ extern void ar5211BeaconInit(struct ath_hal *, uint32_t, uint32_t);
extern void ar5211SetStaBeaconTimers(struct ath_hal *,
const HAL_BEACON_STATE *);
extern void ar5211ResetStaBeaconTimers(struct ath_hal *);
+extern uint64_t ar5211GetNextTBTT(struct ath_hal *);
extern HAL_BOOL ar5211IsInterruptPending(struct ath_hal *);
extern HAL_BOOL ar5211GetPendingInterrupts(struct ath_hal *, HAL_INT *);
diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c b/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c
index 14daa0bffedc5..a0c42b2bf7c41 100644
--- a/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c
+++ b/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c
@@ -148,6 +148,7 @@ static const struct ath_hal_private ar5211hal = {{
.ah_beaconInit = ar5211BeaconInit,
.ah_setStationBeaconTimers = ar5211SetStaBeaconTimers,
.ah_resetStationBeaconTimers = ar5211ResetStaBeaconTimers,
+ .ah_getNextTBTT = ar5211GetNextTBTT,
/* Interrupt Functions */
.ah_isInterruptPending = ar5211IsInterruptPending,
diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211_beacon.c b/sys/dev/ath/ath_hal/ar5211/ar5211_beacon.c
index 31e9c5df8a936..b2775d0376f5a 100644
--- a/sys/dev/ath/ath_hal/ar5211/ar5211_beacon.c
+++ b/sys/dev/ath/ath_hal/ar5211/ar5211_beacon.c
@@ -30,6 +30,17 @@
*/
/*
+ * Return the hardware NextTBTT in TSF
+ */
+uint64_t
+ar5211GetNextTBTT(struct ath_hal *ah)
+{
+#define TU_TO_TSF(_tu) (((uint64_t)(_tu)) << 10)
+ return TU_TO_TSF(OS_REG_READ(ah, AR_TIMER0));
+#undef TU_TO_TSF
+}
+
+/*
* Initialize all of the hardware registers used to send beacons.
*/
void
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212.h b/sys/dev/ath/ath_hal/ar5212/ar5212.h
index 8503a629aa367..40e718e46736b 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212.h
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212.h
@@ -430,6 +430,7 @@ extern void ar5212BeaconInit(struct ath_hal *ah,
extern void ar5212ResetStaBeaconTimers(struct ath_hal *ah);
extern void ar5212SetStaBeaconTimers(struct ath_hal *ah,
const HAL_BEACON_STATE *);
+extern uint64_t ar5212GetNextTBTT(struct ath_hal *);
extern HAL_BOOL ar5212IsInterruptPending(struct ath_hal *ah);
extern HAL_BOOL ar5212GetPendingInterrupts(struct ath_hal *ah, HAL_INT *);
@@ -625,5 +626,6 @@ extern void ar5212GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe);
extern HAL_BOOL ar5212ProcessRadarEvent(struct ath_hal *ah,
struct ath_rx_status *rxs, uint64_t fulltsf, const char *buf,
HAL_DFS_EVENT *event);
+extern HAL_BOOL ar5212IsFastClockEnabled(struct ath_hal *ah);
#endif /* _ATH_AR5212_H_ */
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c b/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c
index c0ebd952c219b..b101306a6354c 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212_ani.c
@@ -222,7 +222,14 @@ ar5212AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
typedef int TABLE[];
struct ath_hal_5212 *ahp = AH5212(ah);
struct ar5212AniState *aniState = ahp->ah_curani;
- const struct ar5212AniParams *params = aniState->params;
+ const struct ar5212AniParams *params = AH_NULL;
+
+ /*
+ * This function may be called before there's a current
+ * channel (eg to disable ANI.)
+ */
+ if (aniState != AH_NULL)
+ params = aniState->params;
OS_MARK(ah, AH_MARK_ANI_CONTROL, cmd);
@@ -343,8 +350,8 @@ ar5212AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
ahp->ah_procPhyErr &= ~HAL_ANI_ENA;
/* Turn off HW counters if we have them */
ar5212AniDetach(ah);
- ar5212SetRxFilter(ah,
- ar5212GetRxFilter(ah) &~ HAL_RX_FILTER_PHYERR);
+ ah->ah_setRxFilter(ah,
+ ah->ah_getRxFilter(ah) &~ HAL_RX_FILTER_PHYERR);
} else { /* normal/auto mode */
/* don't mess with state if already enabled */
if (ahp->ah_procPhyErr & HAL_ANI_ENA)
@@ -358,8 +365,8 @@ ar5212AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
ahp->ah_curani->params:
&ahp->ah_aniParams24 /*XXX*/);
} else {
- ar5212SetRxFilter(ah,
- ar5212GetRxFilter(ah) | HAL_RX_FILTER_PHYERR);
+ ah->ah_setRxFilter(ah,
+ ah->ah_getRxFilter(ah) | HAL_RX_FILTER_PHYERR);
}
ahp->ah_procPhyErr |= HAL_ANI_ENA;
}
@@ -609,8 +616,20 @@ ar5212AniReset(struct ath_hal *ah, const struct ieee80211_channel *chan,
/*
* Turn off PHY error frame delivery while we futz with settings.
*/
- rxfilter = ar5212GetRxFilter(ah);
- ar5212SetRxFilter(ah, rxfilter &~ HAL_RX_FILTER_PHYERR);
+ rxfilter = ah->ah_getRxFilter(ah);
+ ah->ah_setRxFilter(ah, rxfilter &~ HAL_RX_FILTER_PHYERR);
+
+ /*
+ * If ANI is disabled at this point, don't set the default
+ * ANI parameter settings - leave the HAL settings there.
+ * This is (currently) needed for reliable radar detection.
+ */
+ if (! ANI_ENA(ah)) {
+ HALDEBUG(ah, HAL_DEBUG_ANI, "%s: ANI disabled\n",
+ __func__);
+ goto finish;
+ }
+
/*
* Automatic processing is done only in station mode right now.
*/
@@ -644,10 +663,15 @@ ar5212AniReset(struct ath_hal *ah, const struct ieee80211_channel *chan,
ar5212AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 0);
ichan->privFlags |= CHANNEL_ANI_SETUP;
}
+ /*
+ * In case the counters haven't yet been setup; set them up.
+ */
+ enableAniMIBCounters(ah, ahp->ah_curani->params);
ar5212AniRestart(ah, aniState);
+finish:
/* restore RX filter mask */
- ar5212SetRxFilter(ah, rxfilter);
+ ah->ah_setRxFilter(ah, rxfilter);
}
/*
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c b/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c
index 01c0e2c8ad076..eaceaba766e32 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c
@@ -133,6 +133,7 @@ static const struct ath_hal_private ar5212hal = {{
.ah_enableDfs = ar5212EnableDfs,
.ah_getDfsThresh = ar5212GetDfsThresh,
.ah_procRadarEvent = ar5212ProcessRadarEvent,
+ .ah_isFastClockEnabled = ar5212IsFastClockEnabled,
/* Key Cache Functions */
.ah_getKeyCacheSize = ar5212GetKeyCacheSize,
@@ -150,6 +151,7 @@ static const struct ath_hal_private ar5212hal = {{
.ah_beaconInit = ar5212BeaconInit,
.ah_setStationBeaconTimers = ar5212SetStaBeaconTimers,
.ah_resetStationBeaconTimers = ar5212ResetStaBeaconTimers,
+ .ah_getNextTBTT = ar5212GetNextTBTT,
/* Interrupt Functions */
.ah_isInterruptPending = ar5212IsInterruptPending,
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_beacon.c b/sys/dev/ath/ath_hal/ar5212/ar5212_beacon.c
index bf0b38a56db7e..1b4b342bc4ae2 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212_beacon.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212_beacon.c
@@ -26,6 +26,17 @@
#include "ar5212/ar5212desc.h"
/*
+ * Return the hardware NextTBTT in TSF
+ */
+uint64_t
+ar5212GetNextTBTT(struct ath_hal *ah)
+{
+#define TU_TO_TSF(_tu) (((uint64_t)(_tu)) << 10)
+ return TU_TO_TSF(OS_REG_READ(ah, AR_TIMER0));
+#undef TU_TO_TSF
+}
+
+/*
* Initialize all of the hardware registers used to
* send beacons. Note that for station operation the
* driver calls ar5212SetStaBeaconTimers instead.
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c b/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c
index 3a6019d993fd2..5bcde762a5d46 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212_misc.c
@@ -1222,3 +1222,13 @@ ar5212ProcessRadarEvent(struct ath_hal *ah, struct ath_rx_status *rxs,
return AH_TRUE;
}
+
+/*
+ * Return whether 5GHz fast-clock (44MHz) is enabled.
+ * It's always disabled for AR5212 series NICs.
+ */
+HAL_BOOL
+ar5212IsFastClockEnabled(struct ath_hal *ah)
+{
+ return AH_FALSE;
+}
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416.h b/sys/dev/ath/ath_hal/ar5416/ar5416.h
index e5294b0634bb6..a0f5deead8bb2 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416.h
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416.h
@@ -169,6 +169,7 @@ extern void ar5416BeaconInit(struct ath_hal *ah,
extern void ar5416ResetStaBeaconTimers(struct ath_hal *ah);
extern void ar5416SetStaBeaconTimers(struct ath_hal *ah,
const HAL_BEACON_STATE *);
+extern uint64_t ar5416GetNextTBTT(struct ath_hal *);
extern HAL_BOOL ar5416EepromRead(struct ath_hal *, u_int off, uint16_t *data);
extern HAL_BOOL ar5416EepromWrite(struct ath_hal *, u_int off, uint16_t data);
@@ -186,6 +187,8 @@ extern void ar5416GpioSetIntr(struct ath_hal *ah, u_int, uint32_t ilevel);
extern u_int ar5416GetWirelessModes(struct ath_hal *ah);
extern void ar5416SetLedState(struct ath_hal *ah, HAL_LED_STATE state);
+extern uint64_t ar5416GetTsf64(struct ath_hal *ah);
+extern void ar5416SetTsf64(struct ath_hal *ah, uint64_t tsf64);
extern void ar5416ResetTsf(struct ath_hal *ah);
extern HAL_BOOL ar5416SetAntennaSwitch(struct ath_hal *, HAL_ANT_SETTING);
extern HAL_BOOL ar5416SetDecompMask(struct ath_hal *, uint16_t, int);
@@ -208,6 +211,7 @@ extern void ar5416GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe);
extern HAL_BOOL ar5416ProcessRadarEvent(struct ath_hal *ah,
struct ath_rx_status *rxs, uint64_t fulltsf, const char *buf,
HAL_DFS_EVENT *event);
+extern HAL_BOOL ar5416IsFastClockEnabled(struct ath_hal *ah);
extern HAL_BOOL ar5416SetPowerMode(struct ath_hal *ah, HAL_POWER_MODE mode,
int setChip);
@@ -218,6 +222,8 @@ extern HAL_BOOL ar5416ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry);
extern HAL_BOOL ar5416SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry,
const HAL_KEYVAL *k, const uint8_t *mac, int xorKey);
+extern uint32_t ar5416GetRxFilter(struct ath_hal *ah);
+extern void ar5416SetRxFilter(struct ath_hal *ah, uint32_t bits);
extern void ar5416StartPcuReceive(struct ath_hal *ah);
extern void ar5416StopPcuReceive(struct ath_hal *ah);
extern HAL_BOOL ar5416SetupRxDesc(struct ath_hal *,
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416.ini b/sys/dev/ath/ath_hal/ar5416/ar5416.ini
index a1d39f9f4346c..7f8c7934c0d02 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416.ini
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416.ini
@@ -687,7 +687,7 @@ static const uint32_t ar5416Addac[][2] = {
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000000 },
- {0x000098cc, 0x00000000 },
+ {0x000098c4, 0x00000000 },
};
/* hand-crafted from code that does explicit register writes */
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_ani.c b/sys/dev/ath/ath_hal/ar5416/ar5416_ani.c
index e2c8592a13b43..5af6b240b6cc5 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_ani.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_ani.c
@@ -156,6 +156,8 @@ ar5416AniAttach(struct ath_hal *ah, const struct ar5212AniParams *params24,
/*
* Cleanup any ANI state setup.
+ *
+ * This doesn't restore registers to their default settings!
*/
void
ar5416AniDetach(struct ath_hal *ah)
@@ -173,7 +175,43 @@ ar5416AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
typedef int TABLE[];
struct ath_hal_5212 *ahp = AH5212(ah);
struct ar5212AniState *aniState = ahp->ah_curani;
- const struct ar5212AniParams *params = aniState->params;
+ const struct ar5212AniParams *params = AH_NULL;
+
+ /*
+ * This function may be called before there's a current
+ * channel (eg to disable ANI.)
+ */
+ if (aniState != AH_NULL)
+ params = aniState->params;
+
+ OS_MARK(ah, AH_MARK_ANI_CONTROL, cmd);
+
+ /* These commands can't be disabled */
+ if (cmd == HAL_ANI_PRESENT)
+ return AH_TRUE;
+
+ if (cmd == HAL_ANI_MODE) {
+ if (param == 0) {
+ ahp->ah_procPhyErr &= ~HAL_ANI_ENA;
+ /* Turn off HW counters if we have them */
+ ar5416AniDetach(ah);
+ } else { /* normal/auto mode */
+ /* don't mess with state if already enabled */
+ if (! (ahp->ah_procPhyErr & HAL_ANI_ENA)) {
+ /* Enable MIB Counters */
+ /*
+ * XXX use 2.4ghz params if no channel is
+ * available
+ */
+ enableAniMIBCounters(ah,
+ ahp->ah_curani != AH_NULL ?
+ ahp->ah_curani->params:
+ &ahp->ah_aniParams24);
+ ahp->ah_procPhyErr |= HAL_ANI_ENA;
+ }
+ }
+ return AH_TRUE;
+ }
/* Check whether the particular function is enabled */
if (((1 << cmd) & AH5416(ah)->ah_ani_function) == 0) {
@@ -183,7 +221,6 @@ ar5416AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
return AH_FALSE;
}
- OS_MARK(ah, AH_MARK_ANI_CONTROL, cmd);
switch (cmd) {
case HAL_ANI_NOISE_IMMUNITY_LEVEL: {
@@ -317,23 +354,6 @@ ar5416AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param)
aniState->spurImmunityLevel = level;
break;
}
- case HAL_ANI_PRESENT:
- break;
- case HAL_ANI_MODE:
- if (param == 0) {
- ahp->ah_procPhyErr &= ~HAL_ANI_ENA;
- /* Turn off HW counters if we have them */
- ar5416AniDetach(ah);
- } else { /* normal/auto mode */
- /* don't mess with state if already enabled */
- if (ahp->ah_procPhyErr & HAL_ANI_ENA)
- break;
- /* Enable MIB Counters */
- enableAniMIBCounters(ah, ahp->ah_curani != AH_NULL ?
- ahp->ah_curani->params: &ahp->ah_aniParams24 /*XXX*/);
- ahp->ah_procPhyErr |= HAL_ANI_ENA;
- }
- break;
#ifdef AH_PRIVATE_DIAG
case HAL_ANI_PHYERR_RESET:
ahp->ah_stats.ast_ani_ofdmerrs = 0;
@@ -548,8 +568,21 @@ ar5416AniReset(struct ath_hal *ah, const struct ieee80211_channel *chan,
/*
* Turn off PHY error frame delivery while we futz with settings.
*/
- rxfilter = ar5212GetRxFilter(ah);
- ar5212SetRxFilter(ah, rxfilter &~ HAL_RX_FILTER_PHYERR);
+ rxfilter = ah->ah_getRxFilter(ah);
+ ah->ah_setRxFilter(ah, rxfilter &~ HAL_RX_FILTER_PHYERR);
+
+ /*
+ * If ANI is disabled at this point, don't set the default
+ * ANI parameter settings - leave the HAL settings there.
+ * This is (currently) needed for reliable radar detection.
+ */
+ if (! ANI_ENA(ah)) {
+ HALDEBUG(ah, HAL_DEBUG_ANI, "%s: ANI disabled\n",
+ __func__);
+ goto finish;
+ }
+
+
/*
* Automatic processing is done only in station mode right now.
*/
@@ -583,10 +616,16 @@ ar5416AniReset(struct ath_hal *ah, const struct ieee80211_channel *chan,
ar5416AniControl(ah, HAL_ANI_FIRSTEP_LEVEL, 0);
ichan->privFlags |= CHANNEL_ANI_SETUP;
}
+
+ /*
+ * In case the counters haven't yet been setup; set them up.
+ */
+ enableAniMIBCounters(ah, aniState->params);
ar5416AniRestart(ah, aniState);
+finish:
/* restore RX filter mask */
- ar5212SetRxFilter(ah, rxfilter);
+ ah->ah_setRxFilter(ah, rxfilter);
}
/*
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c
index 607f97ab481d6..12589f28fff2e 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c
@@ -117,6 +117,8 @@ ar5416InitState(struct ath_hal_5416 *ahp5416, uint16_t devid, HAL_SOFTC sc,
ah->ah_resetTxQueue = ar5416ResetTxQueue;
/* Receive Functions */
+ ah->ah_getRxFilter = ar5416GetRxFilter;
+ ah->ah_setRxFilter = ar5416SetRxFilter;
ah->ah_startPcuReceive = ar5416StartPcuReceive;
ah->ah_stopPcuReceive = ar5416StopPcuReceive;
ah->ah_setupRxDesc = ar5416SetupRxDesc;
@@ -134,6 +136,7 @@ ar5416InitState(struct ath_hal_5416 *ahp5416, uint16_t devid, HAL_SOFTC sc,
ah->ah_gpioGet = ar5416GpioGet;
ah->ah_gpioSet = ar5416GpioSet;
ah->ah_gpioSetIntr = ar5416GpioSetIntr;
+ ah->ah_getTsf64 = ar5416GetTsf64;
ah->ah_resetTsf = ar5416ResetTsf;
ah->ah_getRfGain = ar5416GetRfgain;
ah->ah_setAntennaSwitch = ar5416SetAntennaSwitch;
@@ -148,6 +151,7 @@ ar5416InitState(struct ath_hal_5416 *ahp5416, uint16_t devid, HAL_SOFTC sc,
ah->ah_enableDfs = ar5416EnableDfs;
ah->ah_getDfsThresh = ar5416GetDfsThresh;
ah->ah_procRadarEvent = ar5416ProcessRadarEvent;
+ ah->ah_isFastClockEnabled = ar5416IsFastClockEnabled;
/* Power Management Functions */
ah->ah_setPowerMode = ar5416SetPowerMode;
@@ -157,6 +161,7 @@ ar5416InitState(struct ath_hal_5416 *ahp5416, uint16_t devid, HAL_SOFTC sc,
ah->ah_beaconInit = ar5416BeaconInit;
ah->ah_setStationBeaconTimers = ar5416SetStaBeaconTimers;
ah->ah_resetStationBeaconTimers = ar5416ResetStaBeaconTimers;
+ ah->ah_getNextTBTT = ar5416GetNextTBTT;
/* 802.11n Functions */
ah->ah_chainTxDesc = ar5416ChainTxDesc;
@@ -885,6 +890,8 @@ ar5416FillCapabilityInfo(struct ath_hal *ah)
pCap->halGTTSupport = AH_TRUE;
pCap->halCSTSupport = AH_TRUE;
pCap->halEnhancedDfsSupport = AH_FALSE;
+ /* Hardware supports 32 bit TSF values in the RX descriptor */
+ pCap->halHasLongRxDescTsf = AH_TRUE;
if (ath_hal_eepromGetFlag(ah, AR_EEP_RFKILL) &&
ath_hal_eepromGet(ah, AR_EEP_RFSILENT, &ahpriv->ah_rfsilent) == HAL_OK) {
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c b/sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c
index 66b50537de966..8b61e14658ae8 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_beacon.c
@@ -26,6 +26,16 @@
#include "ar5416/ar5416phy.h"
#define TU_TO_USEC(_tu) ((_tu) << 10)
+#define ONE_EIGHTH_TU_TO_USEC(_tu8) ((_tu8) << 7)
+
+/*
+ * Return the hardware NextTBTT in TSF
+ */
+uint64_t
+ar5416GetNextTBTT(struct ath_hal *ah)
+{
+ return OS_REG_READ(ah, AR_NEXT_TBTT);
+}
/*
* Initialize all of the hardware registers used to
@@ -38,8 +48,8 @@ ar5416SetBeaconTimers(struct ath_hal *ah, const HAL_BEACON_TIMERS *bt)
uint32_t bperiod;
OS_REG_WRITE(ah, AR_NEXT_TBTT, TU_TO_USEC(bt->bt_nexttbtt));
- OS_REG_WRITE(ah, AR_NEXT_DBA, TU_TO_USEC(bt->bt_nextdba) >> 3);
- OS_REG_WRITE(ah, AR_NEXT_SWBA, TU_TO_USEC(bt->bt_nextswba) >> 3);
+ OS_REG_WRITE(ah, AR_NEXT_DBA, ONE_EIGHTH_TU_TO_USEC(bt->bt_nextdba));
+ OS_REG_WRITE(ah, AR_NEXT_SWBA, ONE_EIGHTH_TU_TO_USEC(bt->bt_nextswba));
OS_REG_WRITE(ah, AR_NEXT_NDP, TU_TO_USEC(bt->bt_nextatim));
bperiod = TU_TO_USEC(bt->bt_intval & HAL_BEACON_PERIOD);
@@ -144,7 +154,7 @@ ar5416SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *bs)
/* NB: no cfp setting since h/w automatically takes care */
- OS_REG_WRITE(ah, AR_NEXT_TBTT, bs->bs_nexttbtt);
+ OS_REG_WRITE(ah, AR_NEXT_TBTT, TU_TO_USEC(bs->bs_nexttbtt));
/*
* Start the beacon timers by setting the BEACON register
@@ -221,15 +231,19 @@ ar5416SetStaBeaconTimers(struct ath_hal *ah, const HAL_BEACON_STATE *bs)
OS_REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(nextTbtt - SLEEP_SLOP));
/* cab timeout is now in 1/8 TU */
- OS_REG_WRITE(ah, AR_SLEEP1,
+ OS_REG_WRITE(ah, AR5416_SLEEP1,
SM((CAB_TIMEOUT_VAL << 3), AR5416_SLEEP1_CAB_TIMEOUT)
- | AR_SLEEP1_ASSUME_DTIM);
+ | AR5416_SLEEP1_ASSUME_DTIM);
+
+ /* XXX autosleep? Use min beacon timeout; check ath9k -adrian */
/* beacon timeout is now in 1/8 TU */
- OS_REG_WRITE(ah, AR_SLEEP2,
+ OS_REG_WRITE(ah, AR5416_SLEEP2,
SM((BEACON_TIMEOUT_VAL << 3), AR5416_SLEEP2_BEACON_TIMEOUT));
- OS_REG_WRITE(ah, AR_TIM_PERIOD, beaconintval);
- OS_REG_WRITE(ah, AR_DTIM_PERIOD, dtimperiod);
+ /* TIM_PERIOD and DTIM_PERIOD are now in uS. */
+ OS_REG_WRITE(ah, AR_TIM_PERIOD, TU_TO_USEC(beaconintval));
+ OS_REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod));
+
OS_REG_SET_BIT(ah, AR_TIMER_MODE,
AR_TIMER_MODE_TBTT | AR_TIMER_MODE_TIM | AR_TIMER_MODE_DTIM);
HALDEBUG(ah, HAL_DEBUG_BEACON, "%s: next DTIM %d\n",
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c b/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c
index 1356c7d1081b9..d51417f4992a3 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_cal.c
@@ -72,7 +72,15 @@ ar5416IsCalSupp(struct ath_hal *ah, const struct ieee80211_channel *chan,
return !IEEE80211_IS_CHAN_B(chan);
case ADC_GAIN_CAL:
case ADC_DC_CAL:
- /* Run ADC Gain Cal for either 5ghz any or 2ghz HT40 */
+ /*
+ * Run ADC Gain Cal for either 5ghz any or 2ghz HT40.
+ *
+ * Don't run ADC calibrations for 5ghz fast clock mode
+ * in HT20 - only one ADC is used.
+ */
+ if (IEEE80211_IS_CHAN_HT20(chan) &&
+ (IS_5GHZ_FAST_CLOCK_EN(ah, chan)))
+ return AH_FALSE;
if (IEEE80211_IS_CHAN_5GHZ(chan))
return AH_TRUE;
if (IEEE80211_IS_CHAN_HT40(chan))
@@ -186,36 +194,22 @@ ar5416RunInitCals(struct ath_hal *ah, int init_cal_count)
}
#endif
+
+/*
+ * AGC calibration for the AR5416, AR9130, AR9160, AR9280.
+ */
HAL_BOOL
ar5416InitCalHardware(struct ath_hal *ah, const struct ieee80211_channel *chan)
{
- if (AR_SREV_MERLIN_10_OR_LATER(ah)) {
- /* Enable Rx Filter Cal */
- OS_REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
- OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
- AR_PHY_AGC_CONTROL_FLTR_CAL);
-
- /* Clear the carrier leak cal bit */
- OS_REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
-
- /* kick off the cal */
- OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
- /* Poll for offset calibration complete */
- if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {
- HALDEBUG(ah, HAL_DEBUG_ANY,
- "%s: offset calibration failed to complete in 1ms; "
- "noisy environment?\n", __func__);
- return AH_FALSE;
- }
+ if (AR_SREV_MERLIN_10_OR_LATER(ah)) {
+ /* Disable ADC */
+ OS_REG_CLR_BIT(ah, AR_PHY_ADC_CTL,
+ AR_PHY_ADC_CTL_OFF_PWDADC);
- /* Set the cl cal bit and rerun the cal a 2nd time */
/* Enable Rx Filter Cal */
- OS_REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
AR_PHY_AGC_CONTROL_FLTR_CAL);
-
- OS_REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
}
/* Calibrate the AGC */
@@ -229,6 +223,16 @@ ar5416InitCalHardware(struct ath_hal *ah, const struct ieee80211_channel *chan)
return AH_FALSE;
}
+ if (AR_SREV_MERLIN_10_OR_LATER(ah)) {
+ /* Enable ADC */
+ OS_REG_SET_BIT(ah, AR_PHY_ADC_CTL,
+ AR_PHY_ADC_CTL_OFF_PWDADC);
+
+ /* Disable Rx Filter Cal */
+ OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
+ AR_PHY_AGC_CONTROL_FLTR_CAL);
+ }
+
return AH_TRUE;
}
@@ -247,7 +251,8 @@ ar5416InitCal(struct ath_hal *ah, const struct ieee80211_channel *chan)
/* Do initial chipset-specific calibration */
if (! AH5416(ah)->ah_cal_initcal(ah, chan)) {
- HALDEBUG(ah, HAL_DEBUG_ANY, "%s: initial chipset calibration did "
+ HALDEBUG(ah, HAL_DEBUG_ANY,
+ "%s: initial chipset calibration did "
"not complete in time; noisy environment?\n", __func__);
return AH_FALSE;
}
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c b/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c
index 6266b5813532b..7e61c84930d96 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_misc.c
@@ -93,6 +93,41 @@ ar5416SetLedState(struct ath_hal *ah, HAL_LED_STATE state)
}
/*
+ * Get the current hardware tsf for stamlme
+ */
+uint64_t
+ar5416GetTsf64(struct ath_hal *ah)
+{
+ uint32_t low1, low2, u32;
+
+ /* sync multi-word read */
+ low1 = OS_REG_READ(ah, AR_TSF_L32);
+ u32 = OS_REG_READ(ah, AR_TSF_U32);
+ low2 = OS_REG_READ(ah, AR_TSF_L32);
+ if (low2 < low1) { /* roll over */
+ /*
+ * If we are not preempted this will work. If we are
+ * then we re-reading AR_TSF_U32 does no good as the
+ * low bits will be meaningless. Likewise reading
+ * L32, U32, U32, then comparing the last two reads
+ * to check for rollover doesn't help if preempted--so
+ * we take this approach as it costs one less PCI read
+ * which can be noticeable when doing things like
+ * timestamping packets in monitor mode.
+ */
+ u32++;
+ }
+ return (((uint64_t) u32) << 32) | ((uint64_t) low2);
+}
+
+void
+ar5416SetTsf64(struct ath_hal *ah, uint64_t tsf64)
+{
+ OS_REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff);
+ OS_REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff);
+}
+
+/*
* Reset the current hardware tsf for stamlme.
*/
void
@@ -617,10 +652,20 @@ ar5416GetDfsThresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
temp = val & AR_PHY_RADAR_1_RELSTEP_CHECK;
pe->pe_relstep = MS(val, AR_PHY_RADAR_1_RELSTEP_THRESH);
if (temp)
- pe->pe_relstep |= HAL_PHYERR_PARAM_ENABLE;
+ pe->pe_enabled = 1;
+ else
+ pe->pe_enabled = 0;
+
pe->pe_maxlen = MS(val, AR_PHY_RADAR_1_MAXLEN);
pe->pe_extchannel = !! (OS_REG_READ(ah, AR_PHY_RADAR_EXT) &
AR_PHY_RADAR_EXT_ENA);
+
+ pe->pe_usefir128 = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
+ AR_PHY_RADAR_1_USE_FIR128);
+ pe->pe_blockradar = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
+ AR_PHY_RADAR_1_BLOCK_CHECK);
+ pe->pe_enmaxrssi = !! (OS_REG_READ(ah, AR_PHY_RADAR_1) &
+ AR_PHY_RADAR_1_MAX_RRSSI);
}
/*
@@ -660,23 +705,36 @@ ar5416EnableDfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
OS_REG_WRITE(ah, AR_PHY_RADAR_0, val | AR_PHY_RADAR_0_ENA);
- val = OS_REG_READ(ah, AR_PHY_RADAR_1);
- val |= (AR_PHY_RADAR_1_MAX_RRSSI | AR_PHY_RADAR_1_BLOCK_CHECK);
+ if (pe->pe_usefir128 == 1)
+ OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_USE_FIR128);
+ else if (pe->pe_usefir128 == 0)
+ OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_USE_FIR128);
+
+ if (pe->pe_enmaxrssi == 1)
+ OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_MAX_RRSSI);
+ else if (pe->pe_enmaxrssi == 0)
+ OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_MAX_RRSSI);
+
+ if (pe->pe_blockradar == 1)
+ OS_REG_SET_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_BLOCK_CHECK);
+ else if (pe->pe_blockradar == 0)
+ OS_REG_CLR_BIT(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_BLOCK_CHECK);
if (pe->pe_maxlen != HAL_PHYERR_PARAM_NOVAL) {
+ val = OS_REG_READ(ah, AR_PHY_RADAR_1);
val &= ~AR_PHY_RADAR_1_MAXLEN;
val |= SM(pe->pe_maxlen, AR_PHY_RADAR_1_MAXLEN);
+ OS_REG_WRITE(ah, AR_PHY_RADAR_1, val);
}
- OS_REG_WRITE(ah, AR_PHY_RADAR_1, val);
/*
* Enable HT/40 if the upper layer asks;
* it should check the channel is HT/40 and HAL_CAP_EXT_CHAN_DFS
* is available.
*/
- if (pe->pe_extchannel)
+ if (pe->pe_extchannel == 1)
OS_REG_SET_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
- else
+ else if (pe->pe_extchannel == 0)
OS_REG_CLR_BIT(ah, AR_PHY_RADAR_EXT, AR_PHY_RADAR_EXT_ENA);
if (pe->pe_relstep != HAL_PHYERR_PARAM_NOVAL) {
@@ -708,3 +766,15 @@ ar5416ProcessRadarEvent(struct ath_hal *ah, struct ath_rx_status *rxs,
*/
return AH_FALSE;
}
+
+/*
+ * Return whether fast-clock is currently enabled for this
+ * channel.
+ */
+HAL_BOOL
+ar5416IsFastClockEnabled(struct ath_hal *ah)
+{
+ struct ath_hal_private *ahp = AH_PRIVATE(ah);
+
+ return IS_5GHZ_FAST_CLOCK_EN(ah, ahp->ah_curchan);
+}
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_recv.c b/sys/dev/ath/ath_hal/ar5416/ar5416_recv.c
index 8a7f3bae3db3f..289da427eb4b1 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_recv.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_recv.c
@@ -27,6 +27,46 @@
#include "ar5416/ar5416desc.h"
/*
+ * Get the receive filter.
+ */
+uint32_t
+ar5416GetRxFilter(struct ath_hal *ah)
+{
+ uint32_t bits = OS_REG_READ(ah, AR_RX_FILTER);
+ uint32_t phybits = OS_REG_READ(ah, AR_PHY_ERR);
+
+ if (phybits & AR_PHY_ERR_RADAR)
+ bits |= HAL_RX_FILTER_PHYRADAR;
+ if (phybits & (AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING))
+ bits |= HAL_RX_FILTER_PHYERR;
+ return bits;
+}
+
+/*
+ * Set the receive filter.
+ */
+void
+ar5416SetRxFilter(struct ath_hal *ah, u_int32_t bits)
+{
+ uint32_t phybits;
+
+ OS_REG_WRITE(ah, AR_RX_FILTER, (bits & 0xffff));
+ phybits = 0;
+ if (bits & HAL_RX_FILTER_PHYRADAR)
+ phybits |= AR_PHY_ERR_RADAR;
+ if (bits & HAL_RX_FILTER_PHYERR)
+ phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING;
+ OS_REG_WRITE(ah, AR_PHY_ERR, phybits);
+ if (phybits) {
+ OS_REG_WRITE(ah, AR_RXCFG,
+ OS_REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA);
+ } else {
+ OS_REG_WRITE(ah, AR_RXCFG,
+ OS_REG_READ(ah, AR_RXCFG) &~ AR_RXCFG_ZLFDMA);
+ }
+}
+
+/*
* Start receive at the PCU engine
*/
void
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c b/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c
index 1da686a3df086..112d9669540fe 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c
@@ -147,7 +147,7 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode,
/* For chips on which the RTC reset is done, save TSF before it gets cleared */
if (AR_SREV_HOWL(ah) ||
(AR_SREV_MERLIN(ah) && ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)))
- tsf = ar5212GetTsf64(ah);
+ tsf = ar5416GetTsf64(ah);
/* Mark PHY as inactive; marked active in ar5416InitBB() */
ar5416MarkPhyInactive(ah);
@@ -159,7 +159,7 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode,
/* Restore TSF */
if (tsf)
- ar5212SetTsf64(ah, tsf);
+ ar5416SetTsf64(ah, tsf);
OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
if (AR_SREV_MERLIN_10_OR_LATER(ah))
@@ -192,9 +192,9 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode,
* value after the initvals have been applied, with an offset
* based on measured time difference
*/
- if (AR_SREV_HOWL(ah) && (ar5212GetTsf64(ah) < tsf)) {
+ if (AR_SREV_HOWL(ah) && (ar5416GetTsf64(ah) < tsf)) {
tsf += 1500;
- ar5212SetTsf64(ah, tsf);
+ ar5416SetTsf64(ah, tsf);
}
HALDEBUG(ah, HAL_DEBUG_RESET, ">>>2 %s: AR_PHY_DAG_CTRLCCK=0x%x\n",
@@ -364,8 +364,7 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode,
OS_REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000);
OS_REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_LAST, 300);
OS_REG_RMW_FIELD(ah, AR_TIMT, AR_TIMT_FIRST, 750);
-#endif
-
+#endif
ar5416InitBB(ah, chan);
/* Setup compression registers */
@@ -503,7 +502,7 @@ ar5416ChannelChange(struct ath_hal *ah, const structu ieee80211_channel *chan)
chan->ic_state &= ~IEEE80211_CHANSTATE_CWINT;
ichan->channel_time = 0;
- ichan->tsf_last = ar5212GetTsf64(ah);
+ ichan->tsf_last = ar5416GetTsf64(ah);
ar5212TxEnable(ah, AH_TRUE);
return AH_TRUE;
}
@@ -1423,60 +1422,20 @@ ar5416UpdateChainMasks(struct ath_hal *ah, HAL_BOOL is_ht)
void
ar5416InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan)
{
- uint32_t pll;
-
- if (AR_SREV_MERLIN_20(ah) &&
- chan != AH_NULL && IEEE80211_IS_CHAN_5GHZ(chan)) {
- /*
- * PLL WAR for Merlin 2.0/2.1
- * When doing fast clock, set PLL to 0x142c
- * Else, set PLL to 0x2850 to prevent reset-to-reset variation
- */
- pll = IS_5GHZ_FAST_CLOCK_EN(ah, chan) ? 0x142c : 0x2850;
- } else if (AR_SREV_MERLIN_10_OR_LATER(ah)) {
- pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV);
- if (chan != AH_NULL) {
- if (IEEE80211_IS_CHAN_HALF(chan))
- pll |= SM(0x1, AR_RTC_SOWL_PLL_CLKSEL);
- else if (IEEE80211_IS_CHAN_QUARTER(chan))
- pll |= SM(0x2, AR_RTC_SOWL_PLL_CLKSEL);
-
- if (IEEE80211_IS_CHAN_5GHZ(chan))
- pll |= SM(0x28, AR_RTC_SOWL_PLL_DIV);
- else
- pll |= SM(0x2c, AR_RTC_SOWL_PLL_DIV);
-
- } else
- pll |= SM(0x2c, AR_RTC_SOWL_PLL_DIV);
- } else if (AR_SREV_SOWL_10_OR_LATER(ah)) {
- pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV);
- if (chan != AH_NULL) {
- if (IEEE80211_IS_CHAN_HALF(chan))
- pll |= SM(0x1, AR_RTC_SOWL_PLL_CLKSEL);
- else if (IEEE80211_IS_CHAN_QUARTER(chan))
- pll |= SM(0x2, AR_RTC_SOWL_PLL_CLKSEL);
+ uint32_t pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2;
+ if (chan != AH_NULL) {
+ if (IEEE80211_IS_CHAN_HALF(chan))
+ pll |= SM(0x1, AR_RTC_PLL_CLKSEL);
+ else if (IEEE80211_IS_CHAN_QUARTER(chan))
+ pll |= SM(0x2, AR_RTC_PLL_CLKSEL);
- if (IEEE80211_IS_CHAN_5GHZ(chan))
- pll |= SM(0x50, AR_RTC_SOWL_PLL_DIV);
- else
- pll |= SM(0x58, AR_RTC_SOWL_PLL_DIV);
- } else
- pll |= SM(0x58, AR_RTC_SOWL_PLL_DIV);
- } else {
- pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2;
- if (chan != AH_NULL) {
- if (IEEE80211_IS_CHAN_HALF(chan))
- pll |= SM(0x1, AR_RTC_PLL_CLKSEL);
- else if (IEEE80211_IS_CHAN_QUARTER(chan))
- pll |= SM(0x2, AR_RTC_PLL_CLKSEL);
-
- if (IEEE80211_IS_CHAN_5GHZ(chan))
- pll |= SM(0xa, AR_RTC_PLL_DIV);
- else
- pll |= SM(0xb, AR_RTC_PLL_DIV);
- } else
+ if (IEEE80211_IS_CHAN_5GHZ(chan))
+ pll |= SM(0xa, AR_RTC_PLL_DIV);
+ else
pll |= SM(0xb, AR_RTC_PLL_DIV);
- }
+ } else
+ pll |= SM(0xb, AR_RTC_PLL_DIV);
+
OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
/* TODO:
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416reg.h b/sys/dev/ath/ath_hal/ar5416/ar5416reg.h
index 561c5b41b385d..c18c26f90fafe 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416reg.h
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416reg.h
@@ -40,6 +40,7 @@
#define AR_INTR_ASYNC_MASK 0x4030 /* asynchronous interrupt mask */
#define AR_INTR_SYNC_MASK 0x4034 /* synchronous interrupt mask */
#define AR_INTR_ASYNC_CAUSE 0x4038 /* check pending interrupts */
+#define AR_INTR_ASYNC_CAUSE_CLR 0x4038 /* clear pending interrupts */
#define AR_INTR_ASYNC_ENABLE 0x403c /* enable interrupts */
#define AR5416_PCIE_SERDES 0x4040
#define AR5416_PCIE_SERDES2 0x4044
@@ -79,6 +80,13 @@
#endif /* AH_SUPPORT_AR9130 */
#define AR_RESET_TSF 0x8020
+
+/*
+ * AR_SLEEP1 / AR_SLEEP2 are in the same place as in
+ * AR5212, however the fields have changed.
+ */
+#define AR5416_SLEEP1 0x80d4
+#define AR5416_SLEEP2 0x80d8
#define AR_RXFIFO_CFG 0x8114
#define AR_PHY_ERR_1 0x812c
#define AR_PHY_ERR_MASK_1 0x8130 /* mask for AR_PHY_ERR_1 */
@@ -402,6 +410,7 @@
#define AR9271_AN_RF2G6_OFFS_S 20
/* Sleep control */
+#define AR5416_SLEEP1_ASSUME_DTIM 0x00080000
#define AR5416_SLEEP1_CAB_TIMEOUT 0xFFE00000 /* Cab timeout (TU) */
#define AR5416_SLEEP1_CAB_TIMEOUT_S 22
diff --git a/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c b/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c
index a87d1adc0e716..2234eb35bfb65 100644
--- a/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c
+++ b/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c
@@ -86,6 +86,28 @@ ar9160AniSetup(struct ath_hal *ah)
ar5416AniAttach(ah, &aniparams, &aniparams, AH_TRUE);
}
+static void
+ar9160InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan)
+{
+ uint32_t pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV);
+ if (chan != AH_NULL) {
+ if (IEEE80211_IS_CHAN_HALF(chan))
+ pll |= SM(0x1, AR_RTC_SOWL_PLL_CLKSEL);
+ else if (IEEE80211_IS_CHAN_QUARTER(chan))
+ pll |= SM(0x2, AR_RTC_SOWL_PLL_CLKSEL);
+
+ if (IEEE80211_IS_CHAN_5GHZ(chan))
+ pll |= SM(0x50, AR_RTC_SOWL_PLL_DIV);
+ else
+ pll |= SM(0x58, AR_RTC_SOWL_PLL_DIV);
+ } else
+ pll |= SM(0x58, AR_RTC_SOWL_PLL_DIV);
+
+ OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
+ OS_DELAY(RTC_PLL_SETTLE_DELAY);
+ OS_REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_SLEEP_DERIVED_CLK);
+}
+
/*
* Attach for an AR9160 part.
*/
@@ -118,6 +140,7 @@ ar9160Attach(uint16_t devid, HAL_SOFTC sc,
/* XXX override with 9160 specific state */
/* override 5416 methods for our needs */
+ AH5416(ah)->ah_initPLL = ar9160InitPLL;
AH5416(ah)->ah_cal.iqCalData.calData = &ar9160_iq_cal;
AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9160_adc_gain_cal;
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9280.c b/sys/dev/ath/ath_hal/ar9002/ar9280.c
index f1bb4fe3f6bd0..99fd1d790d2e9 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9280.c
+++ b/sys/dev/ath/ath_hal/ar9002/ar9280.c
@@ -76,6 +76,7 @@ ar9280SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan)
uint32_t freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0;
CHAN_CENTERS centers;
uint32_t refDivA = 24;
+ uint8_t frac_n_5g;
OS_MARK(ah, AH_MARK_SETCHANNEL, chan->ic_freq);
@@ -85,6 +86,9 @@ ar9280SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan)
reg32 = OS_REG_READ(ah, AR_PHY_SYNTH_CONTROL);
reg32 &= 0xc0000000;
+ if (ath_hal_eepromGet(ah, AR_EEP_FRAC_N_5G, &frac_n_5g) != HAL_OK)
+ frac_n_5g = 0;
+
if (freq < 4800) { /* 2 GHz, fractional mode */
uint32_t txctl;
@@ -106,11 +110,16 @@ ar9280SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan)
bMode = 0;
fracMode = 0;
- if ((freq % 20) == 0) {
- aModeRefSel = 3;
- } else if ((freq % 10) == 0) {
- aModeRefSel = 2;
- } else {
+ switch (frac_n_5g) {
+ case 0:
+ if ((freq % 20) == 0) {
+ aModeRefSel = 3;
+ } else if ((freq % 10) == 0) {
+ aModeRefSel = 2;
+ }
+ if (aModeRefSel) break;
+ case 1:
+ default:
aModeRefSel = 0;
/* Enable 2G (fractional) mode for channels which are 5MHz spaced */
fracMode = 1;
@@ -121,6 +130,7 @@ ar9280SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan)
OS_A_REG_RMW_FIELD(ah, AR_AN_SYNTH9,
AR_AN_SYNTH9_REFDIVA, refDivA);
}
+
if (!fracMode) {
ndiv = (freq * (refDivA >> aModeRefSel))/60;
channelSel = ndiv & 0x1ff;
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9280.h b/sys/dev/ath/ath_hal/ar9002/ar9280.h
index 3ac8fd5c23bbe..e383918abbfa0 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9280.h
+++ b/sys/dev/ath/ath_hal/ar9002/ar9280.h
@@ -59,5 +59,6 @@ struct ath_hal;
HAL_BOOL ar9280SetAntennaSwitch(struct ath_hal *, HAL_ANT_SETTING);
void ar9280SpurMitigate(struct ath_hal *,
const struct ieee80211_channel *);
-
+void ar9280InitPLL(struct ath_hal *ah,
+ const struct ieee80211_channel *chan);
#endif /* _ATH_AR9280_H_ */
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c b/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c
index 3743c2195111d..4f4b8baf2b428 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c
+++ b/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c
@@ -42,14 +42,14 @@ static const HAL_PERCAL_DATA ar9280_iq_cal = { /* single sample */
static const HAL_PERCAL_DATA ar9280_adc_gain_cal = { /* single sample */
.calName = "ADC Gain", .calType = ADC_GAIN_CAL,
.calNumSamples = MIN_CAL_SAMPLES,
- .calCountMax = PER_MIN_LOG_COUNT,
+ .calCountMax = PER_MAX_LOG_COUNT,
.calCollect = ar5416AdcGainCalCollect,
.calPostProc = ar5416AdcGainCalibration
};
static const HAL_PERCAL_DATA ar9280_adc_dc_cal = { /* single sample */
.calName = "ADC DC", .calType = ADC_DC_CAL,
.calNumSamples = MIN_CAL_SAMPLES,
- .calCountMax = PER_MIN_LOG_COUNT,
+ .calCountMax = PER_MAX_LOG_COUNT,
.calCollect = ar5416AdcDcCalCollect,
.calPostProc = ar5416AdcDcCalibration
};
@@ -99,6 +99,39 @@ ar9280AniSetup(struct ath_hal *ah)
ar5416AniAttach(ah, &aniparams, &aniparams, AH_TRUE);
}
+void
+ar9280InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan)
+{
+ uint32_t pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV);
+
+ if (AR_SREV_MERLIN_20(ah) &&
+ chan != AH_NULL && IEEE80211_IS_CHAN_5GHZ(chan)) {
+ /*
+ * PLL WAR for Merlin 2.0/2.1
+ * When doing fast clock, set PLL to 0x142c
+ * Else, set PLL to 0x2850 to prevent reset-to-reset variation
+ */
+ pll = IS_5GHZ_FAST_CLOCK_EN(ah, chan) ? 0x142c : 0x2850;
+ } else if (AR_SREV_MERLIN_10_OR_LATER(ah)) {
+ pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV);
+ if (chan != AH_NULL) {
+ if (IEEE80211_IS_CHAN_HALF(chan))
+ pll |= SM(0x1, AR_RTC_SOWL_PLL_CLKSEL);
+ else if (IEEE80211_IS_CHAN_QUARTER(chan))
+ pll |= SM(0x2, AR_RTC_SOWL_PLL_CLKSEL);
+ if (IEEE80211_IS_CHAN_5GHZ(chan))
+ pll |= SM(0x28, AR_RTC_SOWL_PLL_DIV);
+ else
+ pll |= SM(0x2c, AR_RTC_SOWL_PLL_DIV);
+ } else
+ pll |= SM(0x2c, AR_RTC_SOWL_PLL_DIV);
+ }
+
+ OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
+ OS_DELAY(RTC_PLL_SETTLE_DELAY);
+ OS_REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_SLEEP_DERIVED_CLK);
+}
+
/* XXX shouldn't be here! */
#define EEP_MINOR(_ah) \
(AH_PRIVATE(_ah)->ah_eeversion & AR5416_EEP_VER_MINOR_MASK)
@@ -138,6 +171,8 @@ ar9280Attach(uint16_t devid, HAL_SOFTC sc,
/* XXX override with 9280 specific state */
/* override 5416 methods for our needs */
+ AH5416(ah)->ah_initPLL = ar9280InitPLL;
+
ah->ah_setAntennaSwitch = ar9280SetAntennaSwitch;
ah->ah_configPCIE = ar9280ConfigPCIE;
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c b/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c
index 2547148f838c1..02c7b9892aa83 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c
+++ b/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c
@@ -136,6 +136,8 @@ ar9285Attach(uint16_t devid, HAL_SOFTC sc,
/* XXX override with 9285 specific state */
/* override 5416 methods for our needs */
+ AH5416(ah)->ah_initPLL = ar9280InitPLL;
+
ah->ah_setAntennaSwitch = ar9285SetAntennaSwitch;
ah->ah_configPCIE = ar9285ConfigPCIE;
ah->ah_setTxPower = ar9285SetTransmitPower;
diff --git a/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c b/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c
index ed9feb8fe754f..78400f52f95fd 100644
--- a/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c
+++ b/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c
@@ -137,6 +137,8 @@ ar9287Attach(uint16_t devid, HAL_SOFTC sc,
/* XXX override with 9280 specific state */
/* override 5416 methods for our needs */
+ AH5416(ah)->ah_initPLL = ar9280InitPLL;
+
ah->ah_setAntennaSwitch = ar9287SetAntennaSwitch;
ah->ah_configPCIE = ar9287ConfigPCIE;
diff --git a/sys/dev/ath/ath_rate/sample/sample.h b/sys/dev/ath/ath_rate/sample/sample.h
index d61868d942767..b39e0be716464 100644
--- a/sys/dev/ath/ath_rate/sample/sample.h
+++ b/sys/dev/ath/ath_rate/sample/sample.h
@@ -199,8 +199,8 @@ static unsigned calc_usecs_unicast_packet(struct ath_softc *sc,
ctsduration += rt->info[cix].spAckDuration;
/* XXX assumes short preamble */
- /* XXX assumes HT/20; the node info isn't yet available here */
- ctsduration += ath_hal_pkt_txtime(sc->sc_ah, rt, length, rix, 0, is_ht40);
+ ctsduration += ath_hal_pkt_txtime(sc->sc_ah, rt, length, rix,
+ is_ht40, 0);
if (cts) /* SIFS + ACK */
ctsduration += rt->info[cix].spAckDuration;
@@ -210,8 +210,9 @@ static unsigned calc_usecs_unicast_packet(struct ath_softc *sc,
tt += t_difs;
/* XXX assumes short preamble */
- /* XXX assumes HT/20; the node info isn't yet available here */
- tt += (long_retries+1)*ath_hal_pkt_txtime(sc->sc_ah, rt, length, rix, 0, is_ht40);
+ tt += (long_retries+1)*ath_hal_pkt_txtime(sc->sc_ah, rt, length, rix,
+ is_ht40, 0);
+
tt += (long_retries+1)*(t_sifs + rt->info[rix].spAckDuration);
for (x = 0; x <= short_retries + long_retries; x++) {
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c
index 35592d9b47ad8..af612748f8c29 100644
--- a/sys/dev/ath/if_ath.c
+++ b/sys/dev/ath/if_ath.c
@@ -214,24 +214,6 @@ static void ath_tdma_update(struct ieee80211_node *ni,
static void ath_tdma_beacon_send(struct ath_softc *sc,
struct ieee80211vap *vap);
-static __inline void
-ath_hal_setcca(struct ath_hal *ah, int ena)
-{
- /*
- * NB: fill me in; this is not provided by default because disabling
- * CCA in most locales violates regulatory.
- */
-}
-
-static __inline int
-ath_hal_getcca(struct ath_hal *ah)
-{
- u_int32_t diag;
- if (ath_hal_getcapability(ah, HAL_CAP_DIAG, 0, &diag) != HAL_OK)
- return 1;
- return ((diag & 0x500000) == 0);
-}
-
#define TDMA_EP_MULTIPLIER (1<<10) /* pow2 to optimize out * and / */
#define TDMA_LPF_LEN 6
#define TDMA_DUMMY_MARKER 0x127
@@ -613,6 +595,7 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
sc->sc_hasbmatch = ath_hal_hasbssidmatch(ah);
sc->sc_hastsfadd = ath_hal_hastsfadjust(ah);
sc->sc_rxslink = ath_hal_self_linked_final_rxdesc(ah);
+ sc->sc_rxtsf32 = ath_hal_has_long_rxdesc_tsf(ah);
if (ath_hal_hasfastframes(ah))
ic->ic_caps |= IEEE80211_C_FF;
wmodes = ath_hal_getwirelessmodes(ah);
@@ -1389,13 +1372,32 @@ ath_intr(void *arg)
}
}
if (status & HAL_INT_RXEOL) {
+ int imask = sc->sc_imask;
/*
* NB: the hardware should re-read the link when
* RXE bit is written, but it doesn't work at
* least on older hardware revs.
*/
sc->sc_stats.ast_rxeol++;
+ /*
+ * Disable RXEOL/RXORN - prevent an interrupt
+ * storm until the PCU logic can be reset.
+ * In case the interface is reset some other
+ * way before "sc_kickpcu" is called, don't
+ * modify sc_imask - that way if it is reset
+ * by a call to ath_reset() somehow, the
+ * interrupt mask will be correctly reprogrammed.
+ */
+ imask &= ~(HAL_INT_RXEOL | HAL_INT_RXORN);
+ ath_hal_intrset(ah, imask);
+ /*
+ * Enqueue an RX proc, to handled whatever
+ * is in the RX queue.
+ * This will then kick the PCU.
+ */
+ taskqueue_enqueue(sc->sc_tq, &sc->sc_rxtask);
sc->sc_rxlink = NULL;
+ sc->sc_kickpcu = 1;
}
if (status & HAL_INT_TXURN) {
sc->sc_stats.ast_txurn++;
@@ -2937,16 +2939,31 @@ ath_descdma_setup(struct ath_softc *sc,
{
#define DS2PHYS(_dd, _ds) \
((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
+#define ATH_DESC_4KB_BOUND_CHECK(_daddr, _len) \
+ ((((u_int32_t)(_daddr) & 0xFFF) > (0x1000 - (_len))) ? 1 : 0)
struct ifnet *ifp = sc->sc_ifp;
- struct ath_desc *ds;
+ uint8_t *ds;
struct ath_buf *bf;
int i, bsize, error;
+ int desc_len;
+
+ desc_len = sizeof(struct ath_desc);
DPRINTF(sc, ATH_DEBUG_RESET, "%s: %s DMA: %u buffers %u desc/buf\n",
__func__, name, nbuf, ndesc);
dd->dd_name = name;
- dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc;
+ dd->dd_desc_len = desc_len * nbuf * ndesc;
+
+ /*
+ * Merlin work-around:
+ * Descriptors that cross the 4KB boundary can't be used.
+ * Assume one skipped descriptor per 4KB page.
+ */
+ if (! ath_hal_split4ktrans(sc->sc_ah)) {
+ int numdescpage = 4096 / (desc_len * ndesc);
+ dd->dd_desc_len = (nbuf / numdescpage + 1) * 4096;
+ }
/*
* Setup DMA descriptor area.
@@ -2995,7 +3012,7 @@ ath_descdma_setup(struct ath_softc *sc,
goto fail2;
}
- ds = dd->dd_desc;
+ ds = (uint8_t *) dd->dd_desc;
DPRINTF(sc, ATH_DEBUG_RESET, "%s: %s DMA map: %p (%lu) -> %p (%lu)\n",
__func__, dd->dd_name, ds, (u_long) dd->dd_desc_len,
(caddr_t) dd->dd_desc_paddr, /*XXX*/ (u_long) dd->dd_desc_len);
@@ -3011,9 +3028,23 @@ ath_descdma_setup(struct ath_softc *sc,
dd->dd_bufptr = bf;
STAILQ_INIT(head);
- for (i = 0; i < nbuf; i++, bf++, ds += ndesc) {
- bf->bf_desc = ds;
+ for (i = 0; i < nbuf; i++, bf++, ds += (ndesc * desc_len)) {
+ bf->bf_desc = (struct ath_desc *) ds;
bf->bf_daddr = DS2PHYS(dd, ds);
+ if (! ath_hal_split4ktrans(sc->sc_ah)) {
+ /*
+ * Merlin WAR: Skip descriptor addresses which
+ * cause 4KB boundary crossing along any point
+ * in the descriptor.
+ */
+ if (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr,
+ desc_len * ndesc)) {
+ /* Start at the next page */
+ ds += 0x1000 - (bf->bf_daddr & 0xFFF);
+ bf->bf_desc = (struct ath_desc *) ds;
+ bf->bf_daddr = DS2PHYS(dd, ds);
+ }
+ }
error = bus_dmamap_create(sc->sc_dmat, BUS_DMA_NOWAIT,
&bf->bf_dmamap);
if (error != 0) {
@@ -3036,6 +3067,7 @@ fail0:
memset(dd, 0, sizeof(*dd));
return error;
#undef DS2PHYS
+#undef ATH_DESC_4KB_BOUND_CHECK
}
static void
@@ -3245,14 +3277,49 @@ ath_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf)
* a full 64-bit TSF using the specified TSF.
*/
static __inline u_int64_t
-ath_extend_tsf(u_int32_t rstamp, u_int64_t tsf)
+ath_extend_tsf15(u_int32_t rstamp, u_int64_t tsf)
{
if ((tsf & 0x7fff) < rstamp)
tsf -= 0x8000;
+
return ((tsf &~ 0x7fff) | rstamp);
}
/*
+ * Extend 32-bit time stamp from rx descriptor to
+ * a full 64-bit TSF using the specified TSF.
+ */
+static __inline u_int64_t
+ath_extend_tsf32(u_int32_t rstamp, u_int64_t tsf)
+{
+ u_int32_t tsf_low = tsf & 0xffffffff;
+ u_int64_t tsf64 = (tsf & ~0xffffffffULL) | rstamp;
+
+ if (rstamp > tsf_low && (rstamp - tsf_low > 0x10000000))
+ tsf64 -= 0x100000000ULL;
+
+ if (rstamp < tsf_low && (tsf_low - rstamp > 0x10000000))
+ tsf64 += 0x100000000ULL;
+
+ return tsf64;
+}
+
+/*
+ * Extend the TSF from the RX descriptor to a full 64 bit TSF.
+ * Earlier hardware versions only wrote the low 15 bits of the
+ * TSF into the RX descriptor; later versions (AR5416 and up)
+ * include the 32 bit TSF value.
+ */
+static __inline u_int64_t
+ath_extend_tsf(struct ath_softc *sc, u_int32_t rstamp, u_int64_t tsf)
+{
+ if (sc->sc_rxtsf32)
+ return ath_extend_tsf32(rstamp, tsf);
+ else
+ return ath_extend_tsf15(rstamp, tsf);
+}
+
+/*
* Intercept management frames to collect beacon rssi data
* and to do ibss merges.
*/
@@ -3285,7 +3352,7 @@ ath_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m,
if (vap->iv_opmode == IEEE80211_M_IBSS &&
vap->iv_state == IEEE80211_S_RUN) {
uint32_t rstamp = sc->sc_lastrs->rs_tstamp;
- uint64_t tsf = ath_extend_tsf(rstamp,
+ uint64_t tsf = ath_extend_tsf(sc, rstamp,
ath_hal_gettsf64(sc->sc_ah));
/*
* Handle ibss merge as needed; check the tsf on the
@@ -3357,7 +3424,7 @@ ath_rx_tap(struct ifnet *ifp, struct mbuf *m,
sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_SHORTGI;
}
#endif
- sc->sc_rx_th.wr_tsf = htole64(ath_extend_tsf(rs->rs_tstamp, tsf));
+ sc->sc_rx_th.wr_tsf = htole64(ath_extend_tsf(sc, rs->rs_tstamp, tsf));
if (rs->rs_status & HAL_RXERR_CRC)
sc->sc_rx_th.wr_flags |= IEEE80211_RADIOTAP_F_BADFCS;
/* XXX propagate other error flags from descriptor */
@@ -3740,6 +3807,25 @@ rx_next:
if (ath_dfs_tasklet_needed(sc, sc->sc_curchan))
taskqueue_enqueue(sc->sc_tq, &sc->sc_dfstask);
+ /*
+ * Now that all the RX frames were handled that
+ * need to be handled, kick the PCU if there's
+ * been an RXEOL condition.
+ */
+ if (sc->sc_kickpcu) {
+ sc->sc_kickpcu = 0;
+ ath_stoprecv(sc);
+ sc->sc_imask |= (HAL_INT_RXEOL | HAL_INT_RXORN);
+ if (ath_startrecv(sc) != 0) {
+ if_printf(ifp,
+ "%s: couldn't restart RX after RXEOL; resetting\n",
+ __func__);
+ ath_reset(ifp);
+ return;
+ }
+ ath_hal_intrset(ah, sc->sc_imask);
+ }
+
if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
#ifdef IEEE80211_SUPPORT_SUPERG
ieee80211_ff_age_all(ic, 100);
@@ -4963,6 +5049,7 @@ ath_setregdomain(struct ieee80211com *ic, struct ieee80211_regdomain *reg,
__func__, status);
return EINVAL; /* XXX */
}
+
return 0;
}
@@ -5344,6 +5431,9 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
case SIOCGATHDIAG:
error = ath_ioctl_diag(sc, (struct ath_diag *) ifr);
break;
+ case SIOCGATHPHYERR:
+ error = ath_ioctl_phyerr(sc,(struct ath_diag*) ifr);
+ break;
#endif
case SIOCGIFADDR:
error = ether_ioctl(ifp, cmd, data);
@@ -5388,20 +5478,6 @@ ath_announce(struct ath_softc *sc)
}
#ifdef IEEE80211_SUPPORT_TDMA
-static __inline uint32_t
-ath_hal_getnexttbtt(struct ath_hal *ah)
-{
-#define AR_TIMER0 0x8028
- return OS_REG_READ(ah, AR_TIMER0);
-}
-
-static __inline void
-ath_hal_adjusttsf(struct ath_hal *ah, int32_t tsfdelta)
-{
- /* XXX handle wrap/overflow */
- OS_REG_WRITE(ah, AR_TSF_L32, OS_REG_READ(ah, AR_TSF_L32) + tsfdelta);
-}
-
static void
ath_tdma_settimers(struct ath_softc *sc, u_int32_t nexttbtt, u_int32_t bintval)
{
@@ -5413,6 +5489,8 @@ ath_tdma_settimers(struct ath_softc *sc, u_int32_t nexttbtt, u_int32_t bintval)
bt.bt_nextdba = (nexttbtt<<3) - sc->sc_tdmadbaprep;
bt.bt_nextswba = (nexttbtt<<3) - sc->sc_tdmaswbaprep;
bt.bt_nextatim = nexttbtt+1;
+ /* Enables TBTT, DBA, SWBA timers by default */
+ bt.bt_flags = 0;
ath_hal_beaconsettimers(ah, &bt);
}
@@ -5555,8 +5633,8 @@ ath_tdma_update(struct ieee80211_node *ni,
struct ath_softc *sc = ic->ic_ifp->if_softc;
struct ath_hal *ah = sc->sc_ah;
const HAL_RATE_TABLE *rt = sc->sc_currates;
- u_int64_t tsf, rstamp, nextslot;
- u_int32_t txtime, nextslottu, timer0;
+ u_int64_t tsf, rstamp, nextslot, nexttbtt;
+ u_int32_t txtime, nextslottu;
int32_t tudelta, tsfdelta;
const struct ath_rx_status *rs;
int rix;
@@ -5587,7 +5665,7 @@ ath_tdma_update(struct ieee80211_node *ni,
/* extend rx timestamp to 64 bits */
rs = sc->sc_lastrs;
tsf = ath_hal_gettsf64(ah);
- rstamp = ath_extend_tsf(rs->rs_tstamp, tsf);
+ rstamp = ath_extend_tsf(sc, rs->rs_tstamp, tsf);
/*
* The rx timestamp is set by the hardware on completing
* reception (at the point where the rx descriptor is DMA'd
@@ -5603,15 +5681,15 @@ ath_tdma_update(struct ieee80211_node *ni,
nextslottu = TSF_TO_TU(nextslot>>32, nextslot) & HAL_BEACON_PERIOD;
/*
- * TIMER0 is the h/w's idea of NextTBTT (in TU's). Convert
- * to usecs and calculate the difference between what the
+ * Retrieve the hardware NextTBTT in usecs
+ * and calculate the difference between what the
* other station thinks and what we have programmed. This
* lets us figure how to adjust our timers to match. The
* adjustments are done by pulling the TSF forward and possibly
* rewriting the beacon timers.
*/
- timer0 = ath_hal_getnexttbtt(ah);
- tsfdelta = (int32_t)((nextslot % TU_TO_TSF(HAL_BEACON_PERIOD+1)) - TU_TO_TSF(timer0));
+ nexttbtt = ath_hal_getnexttbtt(ah);
+ tsfdelta = (int32_t)((nextslot % TU_TO_TSF(HAL_BEACON_PERIOD + 1)) - nexttbtt);
DPRINTF(sc, ATH_DEBUG_TDMA_TIMER,
"tsfdelta %d avg +%d/-%d\n", tsfdelta,
@@ -5631,7 +5709,7 @@ ath_tdma_update(struct ieee80211_node *ni,
TDMA_SAMPLE(sc->sc_avgtsfdeltap, 0);
TDMA_SAMPLE(sc->sc_avgtsfdeltam, 0);
}
- tudelta = nextslottu - timer0;
+ tudelta = nextslottu - TSF_TO_TU(nexttbtt >> 32, nexttbtt);
/*
* Copy sender's timetstamp into tdma ie so they can
@@ -5650,10 +5728,9 @@ ath_tdma_update(struct ieee80211_node *ni,
&ni->ni_tstamp.data, 8);
#if 0
DPRINTF(sc, ATH_DEBUG_TDMA_TIMER,
- "tsf %llu nextslot %llu (%d, %d) nextslottu %u timer0 %u (%d)\n",
+ "tsf %llu nextslot %llu (%d, %d) nextslottu %u nexttbtt %llu (%d)\n",
(unsigned long long) tsf, (unsigned long long) nextslot,
- (int)(nextslot - tsf), tsfdelta,
- nextslottu, timer0, tudelta);
+ (int)(nextslot - tsf), tsfdelta, nextslottu, nexttbtt, tudelta);
#endif
/*
* Adjust the beacon timers only when pulling them forward
diff --git a/sys/dev/ath/if_ath_sysctl.c b/sys/dev/ath/if_ath_sysctl.c
index e3c9966b8f55d..ea6f949bdbe40 100644
--- a/sys/dev/ath/if_ath_sysctl.c
+++ b/sys/dev/ath/if_ath_sysctl.c
@@ -354,7 +354,21 @@ ath_sysctl_intmit(SYSCTL_HANDLER_ARGS)
error = sysctl_handle_int(oidp, &intmit, 0, req);
if (error || !req->newptr)
return error;
- return !ath_hal_setintmit(sc->sc_ah, intmit) ? EINVAL : 0;
+
+ /* reusing error; 1 here means "good"; 0 means "fail" */
+ error = ath_hal_setintmit(sc->sc_ah, intmit);
+ if (! error)
+ return EINVAL;
+
+ /*
+ * Reset the hardware here - disabling ANI in the HAL
+ * doesn't reset ANI related registers, so it'll leave
+ * things in an inconsistent state.
+ */
+ if (sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING)
+ ath_reset(sc->sc_ifp);
+
+ return 0;
}
#ifdef IEEE80211_SUPPORT_TDMA
diff --git a/sys/dev/ath/if_athdfs.h b/sys/dev/ath/if_athdfs.h
index 88ee7fc7af8ce..a3f27f90e94ef 100644
--- a/sys/dev/ath/if_athdfs.h
+++ b/sys/dev/ath/if_athdfs.h
@@ -42,6 +42,7 @@ extern int ath_dfs_process_radar_event(struct ath_softc *sc,
extern int ath_dfs_tasklet_needed(struct ath_softc *sc,
struct ieee80211_channel *chan);
extern int ath_ioctl_phyerr(struct ath_softc *sc, struct ath_diag *ad);
-extern int ath_dfs_get_thresholds(struct ath_softc *sc, HAL_PHYERR_PARAM *param);
+extern int ath_dfs_get_thresholds(struct ath_softc *sc,
+ HAL_PHYERR_PARAM *param);
#endif /* __IF_ATHDFS_H__ */
diff --git a/sys/dev/ath/if_athioctl.h b/sys/dev/ath/if_athioctl.h
index 98dd03791d990..4b50d0d8265f7 100644
--- a/sys/dev/ath/if_athioctl.h
+++ b/sys/dev/ath/if_athioctl.h
@@ -154,6 +154,7 @@ struct ath_diag {
};
#define SIOCGATHDIAG _IOWR('i', 138, struct ath_diag)
+#define SIOCGATHPHYERR _IOWR('i', 140, struct ath_diag)
/*
* Radio capture format.
@@ -205,4 +206,34 @@ struct ath_tx_radiotap_header {
int8_t wt_chan_maxpow;
} __packed;
+/*
+ * DFS ioctl commands
+ */
+
+#define DFS_SET_THRESH 2
+#define DFS_GET_THRESH 3
+#define DFS_RADARDETECTS 6
+
+/*
+ * DFS ioctl parameter types
+ */
+#define DFS_PARAM_FIRPWR 1
+#define DFS_PARAM_RRSSI 2
+#define DFS_PARAM_HEIGHT 3
+#define DFS_PARAM_PRSSI 4
+#define DFS_PARAM_INBAND 5
+#define DFS_PARAM_NOL 6 /* XXX not used in FreeBSD */
+#define DFS_PARAM_RELSTEP_EN 7
+#define DFS_PARAM_RELSTEP 8
+#define DFS_PARAM_RELPWR_EN 9
+#define DFS_PARAM_RELPWR 10
+#define DFS_PARAM_MAXLEN 11
+#define DFS_PARAM_USEFIR128 12
+#define DFS_PARAM_BLOCKRADAR 13
+#define DFS_PARAM_MAXRSSI_EN 14
+
+/* FreeBSD-specific start at 32 */
+#define DFS_PARAM_ENABLE 32
+#define DFS_PARAM_EN_EXTCH 33
+
#endif /* _DEV_ATH_ATHIOCTL_H */
diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h
index 3bc8522660192..5c468e7f76469 100644
--- a/sys/dev/ath/if_athvar.h
+++ b/sys/dev/ath/if_athvar.h
@@ -254,7 +254,9 @@ struct ath_softc {
sc_tdma : 1,/* TDMA in use */
sc_setcca : 1,/* set/clr CCA with TDMA */
sc_resetcal : 1,/* reset cal state next trip */
- sc_rxslink : 1;/* do self-linked final descriptor */
+ sc_rxslink : 1,/* do self-linked final descriptor */
+ sc_kickpcu : 1,/* kick PCU RX on next RX proc */
+ sc_rxtsf32 : 1;/* RX dec TSF is 32 bits */
uint32_t sc_eerd; /* regdomain from EEPROM */
uint32_t sc_eecc; /* country code from EEPROM */
/* rate tables */
@@ -481,6 +483,8 @@ void ath_intr(void *);
((*(_ah)->ah_setBeaconTimers)((_ah), (_bt)))
#define ath_hal_beacontimers(_ah, _bs) \
((*(_ah)->ah_setStationBeaconTimers)((_ah), (_bs)))
+#define ath_hal_getnexttbtt(_ah) \
+ ((*(_ah)->ah_getNextTBTT)((_ah)))
#define ath_hal_setassocid(_ah, _bss, _associd) \
((*(_ah)->ah_writeAssocid)((_ah), (_bss), (_associd)))
#define ath_hal_phydisable(_ah) \
@@ -651,11 +655,13 @@ void ath_intr(void *);
#define ath_hal_gettxchainmask(_ah, _ptxchainmask) \
(ath_hal_getcapability(_ah, HAL_CAP_TX_CHAINMASK, 0, _ptxchainmask))
#define ath_hal_split4ktrans(_ah) \
- (ath_hal_getcapability(_ah, HAP_CAP_SPLIT_4KB_TRANS, 0, NULL) == HAL_OK)
+ (ath_hal_getcapability(_ah, HAL_CAP_SPLIT_4KB_TRANS, 0, NULL) == HAL_OK)
#define ath_hal_self_linked_final_rxdesc(_ah) \
(ath_hal_getcapability(_ah, HAL_CAP_RXDESC_SELFLINK, 0, NULL) == HAL_OK)
#define ath_hal_gtxto_supported(_ah) \
(ath_hal_getcapability(_ah, HAL_CAP_GTXTO, 0, NULL) == HAL_OK)
+#define ath_hal_has_long_rxdesc_tsf(_ah) \
+ (ath_hal_getcapability(_ah, HAL_CAP_LONG_RXDESC_TSF, 0, NULL) == HAL_OK)
#define ath_hal_setuprxdesc(_ah, _ds, _size, _intreq) \
((*(_ah)->ah_setupRxDesc)((_ah), (_ds), (_size), (_intreq)))
@@ -711,6 +717,8 @@ void ath_intr(void *);
((*(_ah)->ah_getDfsThresh)((_ah), (_param)))
#define ath_hal_procradarevent(_ah, _rxs, _fulltsf, _buf, _event) \
((*(_ah)->ah_procRadarEvent)((_ah), (_rxs), (_fulltsf), (_buf), (_event)))
+#define ath_hal_is_fast_clock_enabled(_ah) \
+ ((*(_ah)->ah_isFastClockEnabled)((_ah)))
#define ath_hal_gpioCfgOutput(_ah, _gpio, _type) \
((*(_ah)->ah_gpioCfgOutput)((_ah), (_gpio), (_type)))
diff --git a/sys/dev/bvm/bvm_console.c b/sys/dev/bvm/bvm_console.c
index 392346ee3eae9..291910076f926 100644
--- a/sys/dev/bvm/bvm_console.c
+++ b/sys/dev/bvm/bvm_console.c
@@ -29,8 +29,6 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include "opt_comconsole.h"
-
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
@@ -63,7 +61,7 @@ static int polltime;
static struct callout_handle bvm_timeouthandle
= CALLOUT_HANDLE_INITIALIZER(&bvm_timeouthandle);
-#if defined(KDB) && defined(ALT_BREAK_TO_DEBUGGER)
+#if defined(KDB)
static int alt_break_state;
#endif
@@ -211,24 +209,8 @@ bvm_cngetc(struct consdev *cp)
unsigned char ch;
if (bvm_rcons(&ch) == 0) {
-#if defined(KDB) && defined(ALT_BREAK_TO_DEBUGGER)
- int kdb_brk;
-
- if ((kdb_brk = kdb_alt_break(ch, &alt_break_state)) != 0) {
- switch (kdb_brk) {
- case KDB_REQ_DEBUGGER:
- kdb_enter(KDB_WHY_BREAK,
- "Break sequence on console");
- break;
- case KDB_REQ_PANIC:
- kdb_panic("Panic sequence on console");
- break;
- case KDB_REQ_REBOOT:
- kdb_reboot();
- break;
-
- }
- }
+#if defined(KDB)
+ kdb_alt_break(ch, &alt_break_state);
#endif
return (ch);
}
diff --git a/sys/dev/bxe/if_bxe.c b/sys/dev/bxe/if_bxe.c
index e7534f4bb48c1..930a4f03d50e7 100644
--- a/sys/dev/bxe/if_bxe.c
+++ b/sys/dev/bxe/if_bxe.c
@@ -7188,7 +7188,7 @@ bxe_attn_int(struct bxe_softc* sc)
/* sum[hi:lo] += add[hi:lo] */
#define ADD_64(s_hi, a_hi, s_lo, a_lo) do { \
s_lo += a_lo; \
- s_hi += a_hi + (s_lo < a_lo) ? 1 : 0; \
+ s_hi += a_hi + ((s_lo < a_lo) ? 1 : 0); \
} while (0)
/* Subtraction = minuend -= subtrahend */
diff --git a/sys/dev/cardbus/cardbus_cis.c b/sys/dev/cardbus/cardbus_cis.c
index ca1ef4b6ed765..5d7704a53f59e 100644
--- a/sys/dev/cardbus/cardbus_cis.c
+++ b/sys/dev/cardbus/cardbus_cis.c
@@ -441,6 +441,7 @@ cardbus_read_tuple_finish(device_t cbdev, device_t child, int rid,
{
if (res != CIS_CONFIG_SPACE) {
bus_release_resource(child, SYS_RES_MEMORY, rid, res);
+ bus_delete_resource(child, SYS_RES_MEMORY, rid);
}
}
diff --git a/sys/dev/cfe/cfe_console.c b/sys/dev/cfe/cfe_console.c
index 1461ef21119f1..5a6b0a2bf9ba1 100644
--- a/sys/dev/cfe/cfe_console.c
+++ b/sys/dev/cfe/cfe_console.c
@@ -27,8 +27,6 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include "opt_comconsole.h"
-
#include <sys/param.h>
#include <sys/kdb.h>
#include <sys/kernel.h>
@@ -67,7 +65,7 @@ static int polltime;
static struct callout_handle cfe_timeouthandle
= CALLOUT_HANDLE_INITIALIZER(&cfe_timeouthandle);
-#if defined(KDB) && defined(ALT_BREAK_TO_DEBUGGER)
+#if defined(KDB)
static int alt_break_state;
#endif
@@ -191,24 +189,8 @@ cfe_cngetc(struct consdev *cp)
unsigned char ch;
if (cfe_read(conhandle, &ch, 1) == 1) {
-#if defined(KDB) && defined(ALT_BREAK_TO_DEBUGGER)
- int kdb_brk;
-
- if ((kdb_brk = kdb_alt_break(ch, &alt_break_state)) != 0) {
- switch (kdb_brk) {
- case KDB_REQ_DEBUGGER:
- kdb_enter(KDB_WHY_BREAK,
- "Break sequence on console");
- break;
- case KDB_REQ_PANIC:
- kdb_panic("Panic sequence on console");
- break;
- case KDB_REQ_REBOOT:
- kdb_reboot();
- break;
-
- }
- }
+#if defined(KDB)
+ kdb_alt_break(ch, &alt_break_state);
#endif
return (ch);
}
diff --git a/sys/dev/coretemp/coretemp.c b/sys/dev/coretemp/coretemp.c
index 411b9eecf167b..cb1cbff3100e9 100644
--- a/sys/dev/coretemp/coretemp.c
+++ b/sys/dev/coretemp/coretemp.c
@@ -48,12 +48,21 @@ __FBSDID("$FreeBSD$");
#include <machine/cputypes.h>
#include <machine/md_var.h>
-#define TZ_ZEROC 2732
+#define TZ_ZEROC 2732
+
+#define THERM_STATUS_LOG 0x02
+#define THERM_STATUS 0x01
+#define THERM_STATUS_TEMP_SHIFT 16
+#define THERM_STATUS_TEMP_MASK 0x7f
+#define THERM_STATUS_RES_SHIFT 27
+#define THERM_STATUS_RES_MASK 0x0f
+#define THERM_STATUS_VALID_SHIFT 31
+#define THERM_STATUS_VALID_MASK 0x01
struct coretemp_softc {
device_t sc_dev;
int sc_tjmax;
- struct sysctl_oid *sc_oid;
+ unsigned int sc_throttle_log;
};
/*
@@ -64,8 +73,10 @@ static int coretemp_probe(device_t dev);
static int coretemp_attach(device_t dev);
static int coretemp_detach(device_t dev);
-static int coretemp_get_temp(device_t dev);
-static int coretemp_get_temp_sysctl(SYSCTL_HANDLER_ARGS);
+static uint64_t coretemp_get_thermal_msr(int cpu);
+static void coretemp_clear_thermal_msr(int cpu);
+static int coretemp_get_val_sysctl(SYSCTL_HANDLER_ARGS);
+static int coretemp_throttle_log_sysctl(SYSCTL_HANDLER_ARGS);
static device_method_t coretemp_methods[] = {
/* Device interface */
@@ -83,8 +94,16 @@ static driver_t coretemp_driver = {
sizeof(struct coretemp_softc),
};
+enum therm_info {
+ CORETEMP_TEMP,
+ CORETEMP_DELTA,
+ CORETEMP_RESOLUTION,
+ CORETEMP_TJMAX,
+};
+
static devclass_t coretemp_devclass;
-DRIVER_MODULE(coretemp, cpu, coretemp_driver, coretemp_devclass, NULL, NULL);
+DRIVER_MODULE(coretemp, cpu, coretemp_driver, coretemp_devclass, NULL,
+ NULL);
static void
coretemp_identify(driver_t *driver, device_t parent)
@@ -135,6 +154,8 @@ coretemp_attach(device_t dev)
uint64_t msr;
int cpu_model, cpu_stepping;
int ret, tjtarget;
+ struct sysctl_oid *oid;
+ struct sysctl_ctx_list *ctx;
sc->sc_dev = dev;
pdev = device_get_parent(dev);
@@ -149,7 +170,7 @@ coretemp_attach(device_t dev)
*/
if (cpu_model < 0xe)
return (ENXIO);
-
+
#if 0 /*
* XXXrpaulo: I have this CPU model and when it returns from C3
* coretemp continues to function properly.
@@ -216,7 +237,7 @@ coretemp_attach(device_t dev)
ret = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &msr);
if (ret == 0) {
tjtarget = (msr >> 16) & 0xff;
-
+
/*
* On earlier generation of processors, the value
* obtained from IA32_TEMPERATURE_TARGET register is
@@ -225,12 +246,12 @@ coretemp_attach(device_t dev)
* these numbers are, with the publicly available
* documents from Intel.
*
- * For now, we consider [70, 100]C range, as
+ * For now, we consider [70, 110]C range, as
* described in #322683, as "reasonable" and accept
* these values whenever the MSR is available for
* read, regardless the CPU model.
*/
- if (tjtarget >= 70 && tjtarget <= 100)
+ if (tjtarget >= 70 && tjtarget <= 110)
sc->sc_tjmax = tjtarget;
else
device_printf(dev, "Tj(target) value %d "
@@ -243,15 +264,35 @@ coretemp_attach(device_t dev)
if (bootverbose)
device_printf(dev, "Setting TjMax=%d\n", sc->sc_tjmax);
+ 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 "temperature" MIB to dev.cpu.N.
+ * Add the MIBs to dev.cpu.N and dev.cpu.N.coretemp.
*/
- sc->sc_oid = SYSCTL_ADD_PROC(device_get_sysctl_ctx(pdev),
- SYSCTL_CHILDREN(device_get_sysctl_tree(pdev)),
- OID_AUTO, "temperature",
- CTLTYPE_INT | CTLFLAG_RD,
- dev, 0, coretemp_get_temp_sysctl, "IK",
+ SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(device_get_sysctl_tree(pdev)),
+ OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD, dev,
+ CORETEMP_TEMP, coretemp_get_val_sysctl, "IK",
"Current temperature");
+ SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "delta",
+ CTLTYPE_INT | CTLFLAG_RD, 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, 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, dev, CORETEMP_TJMAX,
+ coretemp_get_val_sysctl, "IK",
+ "TCC activation temperature");
+ SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO,
+ "throttle_log", CTLTYPE_INT | CTLFLAG_RW, dev, 0,
+ coretemp_throttle_log_sysctl, "I",
+ "Set to 1 if the thermal sensor has tripped");
return (0);
}
@@ -259,22 +300,13 @@ coretemp_attach(device_t dev)
static int
coretemp_detach(device_t dev)
{
- struct coretemp_softc *sc = device_get_softc(dev);
-
- sysctl_remove_oid(sc->sc_oid, 1, 0);
-
return (0);
}
-
-static int
-coretemp_get_temp(device_t dev)
+static uint64_t
+coretemp_get_thermal_msr(int cpu)
{
uint64_t msr;
- int temp;
- int cpu = device_get_unit(dev);
- struct coretemp_softc *sc = device_get_softc(dev);
- char stemp[16];
thread_lock(curthread);
sched_bind(curthread, cpu);
@@ -296,51 +328,116 @@ coretemp_get_temp(device_t dev)
sched_unbind(curthread);
thread_unlock(curthread);
- /*
- * Check for Thermal Status and Thermal Status Log.
- */
- if ((msr & 0x3) == 0x3)
- device_printf(dev, "PROCHOT asserted\n");
+ return (msr);
+}
+
+static void
+coretemp_clear_thermal_msr(int cpu)
+{
+ thread_lock(curthread);
+ sched_bind(curthread, cpu);
+ thread_unlock(curthread);
+
+ wrmsr(MSR_THERM_STATUS, 0);
+
+ thread_lock(curthread);
+ sched_unbind(curthread);
+ thread_unlock(curthread);
+}
+
+static int
+coretemp_get_val_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ device_t dev;
+ uint64_t msr;
+ int val, tmp;
+ struct coretemp_softc *sc;
+ enum therm_info type;
+ char stemp[16];
+
+ dev = (device_t) arg1;
+ msr = coretemp_get_thermal_msr(device_get_unit(dev));
+ sc = device_get_softc(dev);
+ type = arg2;
+
+ if (((msr >> THERM_STATUS_VALID_SHIFT) & THERM_STATUS_VALID_MASK) != 1) {
+ val = -1;
+ } else {
+ switch (type) {
+ case CORETEMP_TEMP:
+ tmp = (msr >> THERM_STATUS_TEMP_SHIFT) &
+ THERM_STATUS_TEMP_MASK;
+ val = (sc->sc_tjmax - tmp) * 10 + TZ_ZEROC;
+ break;
+ case CORETEMP_DELTA:
+ val = (msr >> THERM_STATUS_TEMP_SHIFT) &
+ THERM_STATUS_TEMP_MASK;
+ break;
+ case CORETEMP_RESOLUTION:
+ val = (msr >> THERM_STATUS_RES_SHIFT) &
+ THERM_STATUS_RES_MASK;
+ break;
+ case CORETEMP_TJMAX:
+ val = sc->sc_tjmax * 10 + TZ_ZEROC;
+ break;
+ }
+ }
+
+ if (msr & THERM_STATUS_LOG) {
+ sc->sc_throttle_log = 1;
- /*
- * Bit 31 contains "Reading valid"
- */
- if (((msr >> 31) & 0x1) == 1) {
/*
- * Starting on bit 16 and ending on bit 22.
+ * 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.
*/
- temp = sc->sc_tjmax - ((msr >> 16) & 0x7f);
- } else
- temp = -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.
- */
- if (((msr >> 4) & 0x3) == 0x3) {
- device_printf(dev, "critical temperature detected, "
- "suggest system shutdown\n");
- snprintf(stemp, sizeof(stemp), "%d", temp);
- devctl_notify("coretemp", "Thermal", stemp, "notify=0xcc");
+ if (msr & THERM_STATUS) {
+ tmp = (msr >> THERM_STATUS_TEMP_SHIFT) &
+ THERM_STATUS_TEMP_MASK;
+ tmp = (sc->sc_tjmax - tmp) * 10 + TZ_ZEROC;
+ device_printf(dev, "critical temperature detected, "
+ "suggest system shutdown\n");
+ snprintf(stemp, sizeof(stemp), "%d", tmp);
+ devctl_notify("coretemp", "Thermal", stemp,
+ "notify=0xcc");
+ }
}
- return (temp);
+ return (sysctl_handle_int(oidp, &val, 0, req));
}
static int
-coretemp_get_temp_sysctl(SYSCTL_HANDLER_ARGS)
+coretemp_throttle_log_sysctl(SYSCTL_HANDLER_ARGS)
{
- device_t dev = (device_t) arg1;
- int temp;
+ device_t dev;
+ uint64_t msr;
+ int error, val;
+ struct coretemp_softc *sc;
+
+ dev = (device_t) arg1;
+ msr = coretemp_get_thermal_msr(device_get_unit(dev));
+ sc = device_get_softc(dev);
+
+ if (msr & THERM_STATUS_LOG)
+ sc->sc_throttle_log = 1;
+
+ val = sc->sc_throttle_log;
- temp = coretemp_get_temp(dev) * 10 + TZ_ZEROC;
+ error = sysctl_handle_int(oidp, &val, 0, req);
- return (sysctl_handle_int(oidp, &temp, 0, req));
+ if (error || !req->newptr)
+ return (error);
+ else if (val != 0)
+ return (EINVAL);
+
+ coretemp_clear_thermal_msr(device_get_unit(dev));
+ sc->sc_throttle_log = 0;
+
+ return (0);
}
diff --git a/sys/dev/dcons/dcons_os.c b/sys/dev/dcons/dcons_os.c
index 3b98cdd255f70..b7de4148ef740 100644
--- a/sys/dev/dcons/dcons_os.c
+++ b/sys/dev/dcons/dcons_os.c
@@ -64,7 +64,6 @@
#include <vm/vm_param.h>
#include <vm/pmap.h>
-#include "opt_comconsole.h"
#include "opt_dcons.h"
#include "opt_kdb.h"
#include "opt_gdb.h"
@@ -133,38 +132,21 @@ static struct ttydevsw dcons_ttydevsw = {
.tsw_outwakeup = dcons_outwakeup,
};
-#if (defined(GDB) || defined(DDB)) && defined(ALT_BREAK_TO_DEBUGGER)
+#if (defined(GDB) || defined(DDB))
static int
dcons_check_break(struct dcons_softc *dc, int c)
{
- int kdb_brk;
if (c < 0)
return (c);
- if ((kdb_brk = kdb_alt_break(c, &dc->brk_state)) != 0) {
- switch (kdb_brk) {
- case KDB_REQ_DEBUGGER:
- if ((dc->flags & DC_GDB) != 0) {
#ifdef GDB
- if (gdb_cur == &dcons_gdb_dbgport) {
- kdb_dbbe_select("gdb");
- kdb_enter(KDB_WHY_BREAK,
- "Break sequence on dcons gdb port");
- }
+ if ((dc->flags & DC_GDB) != 0 && gdb_cur == &dcons_gdb_dbgport)
+ kdb_alt_break_gdb(c, &dc->brk_state);
+ else
#endif
- } else
- kdb_enter(KDB_WHY_BREAK,
- "Break sequence on dcons console port");
- break;
- case KDB_REQ_PANIC:
- kdb_panic("Panic sequence on dcons console port");
- break;
- case KDB_REQ_REBOOT:
- kdb_reboot();
- break;
- }
- }
+ kdb_alt_break(c, &dc->brk_state);
+
return (c);
}
#else
diff --git a/sys/dev/gem/if_gem.c b/sys/dev/gem/if_gem.c
index 6f53eaea1c8b1..d75e1ab8dc61e 100644
--- a/sys/dev/gem/if_gem.c
+++ b/sys/dev/gem/if_gem.c
@@ -947,10 +947,8 @@ gem_init_locked(struct gem_softc *sc)
GEM_LOCK_ASSERT(sc, MA_OWNED);
-#ifdef notyet
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
return;
-#endif
#ifdef GEM_DEBUG
CTR2(KTR_GEM, "%s: %s: calling stop", device_get_name(sc->sc_dev),
diff --git a/sys/dev/hptiop/hptiop.c b/sys/dev/hptiop/hptiop.c
index 77a4ccd5b4c3d..49ffcefe6c578 100644
--- a/sys/dev/hptiop/hptiop.c
+++ b/sys/dev/hptiop/hptiop.c
@@ -1269,6 +1269,8 @@ static int hptiop_probe(device_t dev)
id = pci_get_device(dev);
switch (id) {
+ case 0x4322:
+ case 0x4321:
case 0x4320:
sas = 1;
case 0x3220:
diff --git a/sys/dev/hwpmc/hwpmc_logging.c b/sys/dev/hwpmc/hwpmc_logging.c
index 633c6f953b6e9..b85572a3c86fb 100644
--- a/sys/dev/hwpmc/hwpmc_logging.c
+++ b/sys/dev/hwpmc/hwpmc_logging.c
@@ -37,6 +37,7 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/capability.h>
#include <sys/file.h>
#include <sys/kernel.h>
#include <sys/kthread.h>
@@ -589,7 +590,7 @@ pmclog_configure_log(struct pmc_mdep *md, struct pmc_owner *po, int logfd)
po->po_file));
/* get a reference to the file state */
- error = fget_write(curthread, logfd, &po->po_file);
+ error = fget_write(curthread, logfd, CAP_WRITE, &po->po_file);
if (error)
goto error;
diff --git a/sys/dev/ichwd/ichwd.c b/sys/dev/ichwd/ichwd.c
index a66826e4c6e42..5d800c963e863 100644
--- a/sys/dev/ichwd/ichwd.c
+++ b/sys/dev/ichwd/ichwd.c
@@ -402,11 +402,10 @@ ichwd_event(void *arg, unsigned int cmd, int *error)
cmd &= WD_INTERVAL;
timeout = ((uint64_t)1 << cmd) / ICHWD_TICK;
if (cmd) {
- if (timeout != sc->timeout) {
- if (!sc->active)
- ichwd_tmr_enable(sc);
+ if (!sc->active)
+ ichwd_tmr_enable(sc);
+ if (timeout != sc->timeout)
ichwd_tmr_set(sc, timeout);
- }
ichwd_tmr_reload(sc);
*error = 0;
} else {
diff --git a/sys/dev/ipmi/ipmi_linux.c b/sys/dev/ipmi/ipmi_linux.c
index fcf2bd50322d6..430bd08589485 100644
--- a/sys/dev/ipmi/ipmi_linux.c
+++ b/sys/dev/ipmi/ipmi_linux.c
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/capability.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/module.h>
@@ -92,7 +93,7 @@ ipmi_linux_ioctl(struct thread *td, struct linux_ioctl_args *args)
u_long cmd;
int error;
- if ((error = fget(td, args->fd, &fp)) != 0)
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
return (error);
cmd = args->cmd;
diff --git a/sys/dev/iscsi/initiator/iscsi.c b/sys/dev/iscsi/initiator/iscsi.c
index d35f6310747a1..292ce8f21fa08 100644
--- a/sys/dev/iscsi/initiator/iscsi.c
+++ b/sys/dev/iscsi/initiator/iscsi.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include "opt_iscsi_initiator.h"
#include <sys/param.h>
+#include <sys/capability.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/conf.h>
@@ -387,11 +388,11 @@ i_setsoc(isc_session_t *sp, int fd, struct thread *td)
if(sp->soc != NULL)
isc_stop_receiver(sp);
- error = fget(td, fd, &sp->fp);
+ error = fget(td, fd, CAP_SOCK_ALL, &sp->fp);
if(error)
return error;
- if((error = fgetsock(td, fd, &sp->soc, 0)) == 0) {
+ if((error = fgetsock(td, fd, CAP_SOCK_ALL, &sp->soc, 0)) == 0) {
sp->td = td;
isc_start_receiver(sp);
}
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c
index 95f2add24743c..dfba62e6e0416 100644
--- a/sys/dev/isp/isp.c
+++ b/sys/dev/isp/isp.c
@@ -102,7 +102,6 @@ static const uint8_t alpa_map[] = {
/*
* Local function prototypes.
*/
-static void isp_prt_endcmd(ispsoftc_t *, XS_T *);
static int isp_parse_async(ispsoftc_t *, uint16_t);
static int isp_parse_async_fc(ispsoftc_t *, uint16_t);
static int isp_handle_other_response(ispsoftc_t *, int, isphdr_t *, uint32_t *);
@@ -5391,7 +5390,7 @@ out:
* Support routines.
*/
-static void
+void
isp_prt_endcmd(ispsoftc_t *isp, XS_T *xs)
{
char cdbstr[16 * 5 + 1];
diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c
index 4a664bfb9a339..8d62f5ebdece4 100644
--- a/sys/dev/isp/isp_freebsd.c
+++ b/sys/dev/isp/isp_freebsd.c
@@ -67,7 +67,10 @@ static void isp_intr_enable(void *);
static void isp_cam_async(void *, uint32_t, struct cam_path *, void *);
static void isp_poll(struct cam_sim *);
static timeout_t isp_watchdog;
+static timeout_t isp_gdt;
+static task_fn_t isp_gdt_task;
static timeout_t isp_ldt;
+static task_fn_t isp_ldt_task;
static void isp_kthread(void *);
static void isp_action(struct cam_sim *, union ccb *);
#ifdef ISP_INTERNAL_TARGET
@@ -105,15 +108,13 @@ isp_attach_chan(ispsoftc_t *isp, struct cam_devq *devq, int chan)
return (EIO);
}
ISP_UNLOCK(isp);
-
- if (xpt_create_path(&path, NULL, cam_sim_path(sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+ if (xpt_create_path_unlocked(&path, NULL, cam_sim_path(sim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
ISP_LOCK(isp);
xpt_bus_deregister(cam_sim_path(sim));
ISP_UNLOCK(isp);
cam_sim_free(sim, FALSE);
return (ENXIO);
}
-
xpt_setup_ccb(&csa.ccb_h, path, 5);
csa.ccb_h.func_code = XPT_SASYNC_CB;
csa.event_enable = AC_LOST_DEVICE;
@@ -141,8 +142,11 @@ isp_attach_chan(ispsoftc_t *isp, struct cam_devq *devq, int chan)
fc->path = path;
fc->isp = isp;
fc->ready = 1;
+
callout_init_mtx(&fc->ldt, &isp->isp_osinfo.lock, 0);
callout_init_mtx(&fc->gdt, &isp->isp_osinfo.lock, 0);
+ TASK_INIT(&fc->ltask, 1, isp_ldt_task, fc);
+ TASK_INIT(&fc->gtask, 1, isp_gdt_task, fc);
/*
* We start by being "loop down" if we have an initiator role
@@ -184,12 +188,16 @@ isp_attach(ispsoftc_t *isp)
isp->isp_osinfo.ehook.ich_func = isp_intr_enable;
isp->isp_osinfo.ehook.ich_arg = isp;
+ /*
+ * Haha. Set this first, because if we're loaded as a module isp_intr_enable
+ * will be called right awawy, which will clear isp_osinfo.ehook_active,
+ * which would be unwise to then set again later.
+ */
+ isp->isp_osinfo.ehook_active = 1;
if (config_intrhook_establish(&isp->isp_osinfo.ehook) != 0) {
isp_prt(isp, ISP_LOGERR, "could not establish interrupt enable hook");
return (-EIO);
}
- isp->isp_osinfo.ehook_active = 1;
-
/*
* Create the device queue for our SIM(s).
@@ -246,20 +254,33 @@ unwind:
return (-1);
}
-void
+int
isp_detach(ispsoftc_t *isp)
{
+ struct cam_sim *sim;
+ struct cam_path *path;
+ struct ccb_setasync csa;
int chan;
ISP_LOCK(isp);
+ for (chan = isp->isp_nchan - 1; chan >= 0; chan -= 1) {
+ if (IS_FC(isp)) {
+ sim = ISP_FC_PC(isp, chan)->sim;
+ path = ISP_FC_PC(isp, chan)->path;
+ } else {
+ sim = ISP_SPI_PC(isp, chan)->sim;
+ path = ISP_SPI_PC(isp, chan)->path;
+ }
+ if (sim->refcount > 2) {
+ ISP_UNLOCK(isp);
+ return (EBUSY);
+ }
+ }
if (isp->isp_osinfo.timer_active) {
callout_stop(&isp->isp_osinfo.tmo);
isp->isp_osinfo.timer_active = 0;
}
- ISP_UNLOCK(isp);
for (chan = isp->isp_nchan - 1; chan >= 0; chan -= 1) {
- struct cam_sim *sim;
- struct cam_path *path;
if (IS_FC(isp)) {
sim = ISP_FC_PC(isp, chan)->sim;
path = ISP_FC_PC(isp, chan)->path;
@@ -267,12 +288,17 @@ isp_detach(ispsoftc_t *isp)
sim = ISP_SPI_PC(isp, chan)->sim;
path = ISP_SPI_PC(isp, chan)->path;
}
+ xpt_setup_ccb(&csa.ccb_h, path, 5);
+ csa.ccb_h.func_code = XPT_SASYNC_CB;
+ csa.event_enable = 0;
+ csa.callback = isp_cam_async;
+ csa.callback_arg = sim;
+ xpt_action((union ccb *)&csa);
xpt_free_path(path);
- ISP_LOCK(isp);
xpt_bus_deregister(cam_sim_path(sim));
- ISP_UNLOCK(isp);
cam_sim_free(sim, FALSE);
}
+ ISP_UNLOCK(isp);
if (isp->isp_osinfo.cdev) {
destroy_dev(isp->isp_osinfo.cdev);
isp->isp_osinfo.cdev = NULL;
@@ -285,6 +311,7 @@ isp_detach(ispsoftc_t *isp)
cam_simq_free(isp->isp_osinfo.devq);
isp->isp_osinfo.devq = NULL;
}
+ return (0);
}
static void
@@ -303,6 +330,20 @@ isp_freeze_loopdown(ispsoftc_t *isp, int chan, char *msg)
}
}
+static void
+isp_unfreeze_loopdown(ispsoftc_t *isp, int chan)
+{
+ if (IS_FC(isp)) {
+ struct isp_fc *fc = ISP_FC_PC(isp, chan);
+ int wasfrozen = fc->simqfrozen & SIMQFRZ_LOOPDOWN;
+ fc->simqfrozen &= ~SIMQFRZ_LOOPDOWN;
+ if (wasfrozen && fc->simqfrozen == 0) {
+ isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "%s: Chan %d releasing simq", __func__, chan);
+ xpt_release_simq(fc->sim, 1);
+ }
+ }
+}
+
static int
ispioctl(struct cdev *dev, u_long c, caddr_t addr, int flags, struct thread *td)
@@ -696,6 +737,7 @@ isp_intr_enable(void *arg)
}
}
}
+ isp->isp_osinfo.ehook_active = 0;
ISP_UNLOCK(isp);
/* Release our hook so that the boot can continue. */
config_intrhook_disestablish(&isp->isp_osinfo.ehook);
@@ -1302,7 +1344,7 @@ done:
xpt_print(ccb->ccb_h.path, "now disabled for target mode\n");
}
if (tptr) {
- rls_lun_statep(isp, tptr);
+ destroy_lun_state(isp, tptr);
}
isp->isp_osinfo.rptr = NULL;
isp->isp_osinfo.tmbusy = 0;
@@ -3781,19 +3823,20 @@ static void
isp_cam_async(void *cbarg, uint32_t code, struct cam_path *path, void *arg)
{
struct cam_sim *sim;
+ int bus, tgt;
ispsoftc_t *isp;
sim = (struct cam_sim *)cbarg;
isp = (ispsoftc_t *) cam_sim_softc(sim);
+ bus = cam_sim_bus(sim);
+ tgt = xpt_path_target_id(path);
+
switch (code) {
case AC_LOST_DEVICE:
if (IS_SCSI(isp)) {
uint16_t oflags, nflags;
- int bus = cam_sim_bus(sim);
sdparam *sdp = SDPARAM(isp, bus);
- int tgt;
- tgt = xpt_path_target_id(path);
if (tgt >= 0) {
nflags = sdp->isp_devparam[tgt].nvrm_flags;
#ifndef ISP_TARGET_MODE
@@ -3837,11 +3880,32 @@ isp_watchdog(void *arg)
{
struct ccb_scsiio *xs = arg;
ispsoftc_t *isp;
- uint32_t handle;
+ uint32_t ohandle = ISP_HANDLE_FREE, handle;
isp = XS_ISP(xs);
handle = isp_find_handle(isp, xs);
+
+ if (handle != ISP_HANDLE_FREE && !XS_CMD_WPEND_P(xs)) {
+ isp_xs_prt(isp, xs, ISP_LOGWARN, "first watchdog (handle 0x%x) timed out- deferring for grace period", handle);
+ callout_reset(&PISP_PCMD(xs)->wdog, 2 * hz, isp_watchdog, xs);
+ XS_CMD_S_WPEND(xs);
+ return;
+ }
+ XS_C_TACTIVE(xs);
+
+ /*
+ * Hand crank the interrupt code just to be sure the command isn't stuck somewhere.
+ */
+ if (handle != ISP_HANDLE_FREE) {
+ uint32_t isr;
+ uint16_t sema, mbox;
+ if (ISP_READ_ISR(isp, &isr, &sema, &mbox) != 0) {
+ isp_intr(isp, isr, sema, mbox);
+ }
+ ohandle = handle;
+ handle = isp_find_handle(isp, xs);
+ }
if (handle != ISP_HANDLE_FREE) {
/*
* Try and make sure the command is really dead before
@@ -3878,7 +3942,14 @@ isp_watchdog(void *arg)
isp_destroy_handle(isp, handle);
isp_prt(isp, ISP_LOGERR, "%s: timeout for handle 0x%x", __func__, handle);
XS_SETERR(xs, CAM_CMD_TIMEOUT);
+ isp_prt_endcmd(isp, xs);
isp_done(xs);
+ } else {
+ if (ohandle != ISP_HANDLE_FREE) {
+ isp_prt(isp, ISP_LOGWARN, "%s: timeout for handle 0x%x, recovered during interrupt", __func__, ohandle);
+ } else {
+ isp_prt(isp, ISP_LOGWARN, "%s: timeout for handle already free", __func__);
+ }
}
}
@@ -3937,12 +4008,20 @@ static void
isp_gdt(void *arg)
{
struct isp_fc *fc = arg;
+ taskqueue_enqueue(taskqueue_thread, &fc->gtask);
+}
+
+static void
+isp_gdt_task(void *arg, int pending)
+{
+ struct isp_fc *fc = arg;
ispsoftc_t *isp = fc->isp;
int chan = fc - isp->isp_osinfo.pc.fc;
fcportdb_t *lp;
int dbidx, tgt, more_to_do = 0;
- isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Chan %d GDT timer expired @ %lu", chan, (unsigned long) time_uptime);
+ ISP_LOCK(isp);
+ isp_prt(isp, ISP_LOGDEBUG0, "Chan %d GDT timer expired", chan);
for (dbidx = 0; dbidx < MAX_FC_TARG; dbidx++) {
lp = &FCPARAM(isp, chan)->portdb[dbidx];
@@ -3953,6 +4032,7 @@ isp_gdt(void *arg)
continue;
}
if (lp->gone_timer != 0) {
+ isp_prt(isp, ISP_LOGSANCFG, "%s: Chan %d more to do for target %u (timer=%u)", __func__, chan, lp->dev_map_idx - 1, lp->gone_timer);
lp->gone_timer -= 1;
more_to_do++;
continue;
@@ -3968,9 +4048,11 @@ isp_gdt(void *arg)
if (more_to_do) {
callout_reset(&fc->gdt, hz, isp_gdt, fc);
} else {
- isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Chan %d Stopping Gone Device Timer", chan);
+ callout_deactivate(&fc->gdt);
+ isp_prt(isp, ISP_LOGSANCFG, "Chan %d Stopping Gone Device Timer @ %lu", chan, (unsigned long) time_uptime);
}
}
+ ISP_UNLOCK(isp);
}
/*
@@ -3986,12 +4068,21 @@ static void
isp_ldt(void *arg)
{
struct isp_fc *fc = arg;
+ taskqueue_enqueue(taskqueue_thread, &fc->ltask);
+}
+
+static void
+isp_ldt_task(void *arg, int pending)
+{
+ struct isp_fc *fc = arg;
ispsoftc_t *isp = fc->isp;
int chan = fc - isp->isp_osinfo.pc.fc;
fcportdb_t *lp;
- int dbidx, tgt;
+ int dbidx, tgt, i;
+ ISP_LOCK(isp);
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "Chan %d Loop Down Timer expired @ %lu", chan, (unsigned long) time_uptime);
+ callout_deactivate(&fc->ldt);
/*
* Notify to the OS all targets who we now consider have departed.
@@ -4009,6 +4100,23 @@ isp_ldt(void *arg)
/*
* XXX: CLEAN UP AND COMPLETE ANY PENDING COMMANDS FIRST!
*/
+
+
+ for (i = 0; i < isp->isp_maxcmds; i++) {
+ struct ccb_scsiio *xs;
+
+ if (!ISP_VALID_HANDLE(isp, isp->isp_xflist[i].handle)) {
+ continue;
+ }
+ if ((xs = isp->isp_xflist[i].cmd) == NULL) {
+ continue;
+ }
+ if (dbidx != (FCPARAM(isp, chan)->isp_dev_map[XS_TGT(xs)] - 1)) {
+ continue;
+ }
+ isp_prt(isp, ISP_LOGWARN, "command handle 0x%08x for %d.%d.%d orphaned by loop down timeout",
+ isp->isp_xflist[i].handle, chan, XS_TGT(xs), XS_LUN(xs));
+ }
/*
* Mark that we've announced that this device is gone....
@@ -4030,6 +4138,9 @@ isp_ldt(void *arg)
isp_make_gone(isp, chan, tgt);
}
+ if (FCPARAM(isp, chan)->role & ISP_ROLE_INITIATOR) {
+ isp_unfreeze_loopdown(isp, chan);
+ }
/*
* The loop down timer has expired. Wake up the kthread
* to notice that fact (or make it false).
@@ -4037,6 +4148,7 @@ isp_ldt(void *arg)
fc->loop_dead = 1;
fc->loop_down_time = fc->loop_down_limit+1;
wakeup(fc);
+ ISP_UNLOCK(isp);
}
static void
@@ -4050,7 +4162,7 @@ isp_kthread(void *arg)
mtx_lock(&isp->isp_osinfo.lock);
for (;;) {
- int wasfrozen, lb, lim;
+ int lb, lim;
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "%s: Chan %d checking FC state", __func__, chan);
lb = isp_fc_runstate(isp, chan, 250000);
@@ -4121,12 +4233,7 @@ isp_kthread(void *arg)
*/
if (FCPARAM(isp, chan)->loop_seen_once || fc->loop_dead) {
- wasfrozen = fc->simqfrozen & SIMQFRZ_LOOPDOWN;
- fc->simqfrozen &= ~SIMQFRZ_LOOPDOWN;
- if (wasfrozen && fc->simqfrozen == 0) {
- isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "%s: Chan %d releasing simq", __func__, chan);
- xpt_release_simq(fc->sim, 1);
- }
+ isp_unfreeze_loopdown(isp, chan);
}
isp_prt(isp, ISP_LOGSANCFG|ISP_LOGDEBUG0, "%s: Chan %d sleep time %d", __func__, chan, slp);
@@ -4225,6 +4332,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
ts = 60*1000;
}
ts = isp_mstohz(ts);
+ XS_S_TACTIVE(ccb);
callout_reset(&PISP_PCMD(ccb)->wdog, ts, isp_watchdog, ccb);
break;
case CMD_RQLATER:
@@ -4631,7 +4739,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
if (kp->xport_specific.fc.valid & KNOB_VALID_ADDRESS) {
fcp->isp_wwnn = ISP_FC_PC(isp, bus)->def_wwnn = kp->xport_specific.fc.wwnn;
fcp->isp_wwpn = ISP_FC_PC(isp, bus)->def_wwpn = kp->xport_specific.fc.wwpn;
-isp_prt(isp, ISP_LOGALL, "Setting Channel %d wwns to 0x%jx 0x%jx", bus, fcp->isp_wwnn, fcp->isp_wwpn);
+ isp_prt(isp, ISP_LOGALL, "Setting Channel %d wwns to 0x%jx 0x%jx", bus, fcp->isp_wwnn, fcp->isp_wwpn);
}
ccb->ccb_h.status = CAM_REQ_CMP;
if (kp->xport_specific.fc.valid & KNOB_VALID_ROLE) {
@@ -4751,7 +4859,9 @@ isp_prt(isp, ISP_LOGALL, "Setting Channel %d wwns to 0x%jx 0x%jx", bus, fcp->isp
/*
* Set base transfer capabilities for Fibre Channel, for this HBA.
*/
- if (IS_24XX(isp)) {
+ if (IS_25XX(isp)) {
+ cpi->base_transfer_speed = 8000000;
+ } else if (IS_24XX(isp)) {
cpi->base_transfer_speed = 4000000;
} else if (IS_23XX(isp)) {
cpi->base_transfer_speed = 2000000;
@@ -4797,6 +4907,7 @@ void
isp_done(XS_T *sccb)
{
ispsoftc_t *isp = XS_ISP(sccb);
+ uint32_t status;
if (XS_NOERR(sccb))
XS_SETERR(sccb, CAM_REQ_CMP);
@@ -4811,8 +4922,10 @@ isp_done(XS_T *sccb)
}
sccb->ccb_h.status &= ~CAM_SIM_QUEUED;
- if ((sccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
- isp_prt(isp, ISP_LOGDEBUG0, "target %d lun %d CAM status 0x%x SCSI status 0x%x", XS_TGT(sccb), XS_LUN(sccb), sccb->ccb_h.status, sccb->scsi_status);
+ status = sccb->ccb_h.status & CAM_STATUS_MASK;
+ if (status != CAM_REQ_CMP) {
+ if (status != CAM_SEL_TIMEOUT)
+ isp_prt(isp, ISP_LOGDEBUG0, "target %d lun %d CAM status 0x%x SCSI status 0x%x", XS_TGT(sccb), XS_LUN(sccb), sccb->ccb_h.status, sccb->scsi_status);
if ((sccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
sccb->ccb_h.status |= CAM_DEV_QFRZN;
xpt_freeze_devq(sccb->ccb_h.path, 1);
@@ -4824,7 +4937,8 @@ isp_done(XS_T *sccb)
}
XS_CMD_S_DONE(sccb);
- callout_stop(&PISP_PCMD(sccb)->wdog);
+ if (XS_TACTIVE_P(sccb))
+ callout_stop(&PISP_PCMD(sccb)->wdog);
XS_CMD_S_CLEAR(sccb);
isp_free_pcmd(isp, (union ccb *) sccb);
xpt_done((union ccb *) sccb);
@@ -5423,15 +5537,19 @@ isp_default_wwn(ispsoftc_t * isp, int chan, int isactive, int iswwnn)
void
isp_prt(ispsoftc_t *isp, int level, const char *fmt, ...)
{
+ int loc;
+ char lbuf[128];
va_list ap;
+
if (level != ISP_LOGALL && (level & isp->isp_dblev) == 0) {
return;
}
- printf("%s: ", device_get_nameunit(isp->isp_dev));
+ sprintf(lbuf, "%s: ", device_get_nameunit(isp->isp_dev));
+ loc = strlen(lbuf);
va_start(ap, fmt);
- vprintf(fmt, ap);
+ vsnprintf(&lbuf[loc], sizeof (lbuf) - loc - 1, fmt, ap);
va_end(ap);
- printf("\n");
+ printf("%s\n", lbuf);
}
void
diff --git a/sys/dev/isp/isp_freebsd.h b/sys/dev/isp/isp_freebsd.h
index 0d67630ec3566..1fb5fc56a89fe 100644
--- a/sys/dev/isp/isp_freebsd.h
+++ b/sys/dev/isp/isp_freebsd.h
@@ -41,6 +41,7 @@
#include <sys/proc.h>
#include <sys/bus.h>
+#include <sys/taskqueue.h>
#include <machine/bus.h>
#include <machine/cpu.h>
@@ -182,6 +183,8 @@ struct isp_fc {
ready : 1;
struct callout ldt; /* loop down timer */
struct callout gdt; /* gone device timer */
+ struct task ltask;
+ struct task gtask;
#ifdef ISP_TARGET_MODE
struct tslist lun_hash[LUN_HASH_SIZE];
#ifdef ISP_INTERNAL_TARGET
@@ -579,7 +582,7 @@ default: \
* prototypes for isp_pci && isp_freebsd to share
*/
extern int isp_attach(ispsoftc_t *);
-extern void isp_detach(ispsoftc_t *);
+extern int isp_detach(ispsoftc_t *);
extern void isp_uninit(ispsoftc_t *);
extern uint64_t isp_default_wwn(ispsoftc_t *, int, int, int);
@@ -597,12 +600,23 @@ extern int isp_autoconfig;
* Platform private flags
*/
#define ISP_SPRIV_ERRSET 0x1
+#define ISP_SPRIV_TACTIVE 0x2
#define ISP_SPRIV_DONE 0x8
+#define ISP_SPRIV_WPEND 0x10
+
+#define XS_S_TACTIVE(sccb) (sccb)->ccb_h.spriv_field0 |= ISP_SPRIV_TACTIVE
+#define XS_C_TACTIVE(sccb) (sccb)->ccb_h.spriv_field0 &= ~ISP_SPRIV_TACTIVE
+#define XS_TACTIVE_P(sccb) ((sccb)->ccb_h.spriv_field0 & ISP_SPRIV_TACTIVE)
#define XS_CMD_S_DONE(sccb) (sccb)->ccb_h.spriv_field0 |= ISP_SPRIV_DONE
#define XS_CMD_C_DONE(sccb) (sccb)->ccb_h.spriv_field0 &= ~ISP_SPRIV_DONE
#define XS_CMD_DONE_P(sccb) ((sccb)->ccb_h.spriv_field0 & ISP_SPRIV_DONE)
+#define XS_CMD_S_WPEND(sccb) (sccb)->ccb_h.spriv_field0 |= ISP_SPRIV_WPEND
+#define XS_CMD_C_WPEND(sccb) (sccb)->ccb_h.spriv_field0 &= ~ISP_SPRIV_WPEND
+#define XS_CMD_WPEND_P(sccb) ((sccb)->ccb_h.spriv_field0 & ISP_SPRIV_WPEND)
+
+
#define XS_CMD_S_CLEAR(sccb) (sccb)->ccb_h.spriv_field0 = 0
/*
diff --git a/sys/dev/isp/isp_pci.c b/sys/dev/isp/isp_pci.c
index 5eb073957bc1a..b6b23fafa59d1 100644
--- a/sys/dev/isp/isp_pci.c
+++ b/sys/dev/isp/isp_pci.c
@@ -347,7 +347,11 @@ static int isp_pci_detach (device_t);
struct isp_pcisoftc {
ispsoftc_t pci_isp;
device_t pci_dev;
- struct resource * pci_reg;
+ struct resource * regs;
+ void * irq;
+ int iqd;
+ int rtp;
+ int rgd;
void * ih;
int16_t pci_poff[_NREG_BLKS];
bus_dma_tag_t dmat;
@@ -645,8 +649,7 @@ isp_get_specific_options(device_t dev, int chan, ispsoftc_t *isp)
static int
isp_pci_attach(device_t dev)
{
- struct resource *regs, *irq;
- int rtp, rgd, iqd, i, m1, m2, locksetup = 0;
+ int i, m1, m2, locksetup = 0;
int isp_nvports = 0;
uint32_t data, cmd, linesz, did;
struct isp_pcisoftc *pcs;
@@ -687,32 +690,31 @@ isp_pci_attach(device_t dev)
isp_get_pci_options(dev, &m1, &m2);
linesz = PCI_DFLT_LNSZ;
- irq = regs = NULL;
- rgd = rtp = iqd = 0;
+ pcs->irq = pcs->regs = NULL;
+ pcs->rgd = pcs->rtp = pcs->iqd = 0;
cmd = pci_read_config(dev, PCIR_COMMAND, 2);
if (cmd & m1) {
- rtp = (m1 == PCIM_CMD_MEMEN)? SYS_RES_MEMORY : SYS_RES_IOPORT;
- rgd = (m1 == PCIM_CMD_MEMEN)? MEM_MAP_REG : IO_MAP_REG;
- regs = bus_alloc_resource_any(dev, rtp, &rgd, RF_ACTIVE);
+ pcs->rtp = (m1 == PCIM_CMD_MEMEN)? SYS_RES_MEMORY : SYS_RES_IOPORT;
+ pcs->rgd = (m1 == PCIM_CMD_MEMEN)? MEM_MAP_REG : IO_MAP_REG;
+ pcs->regs = bus_alloc_resource_any(dev, pcs->rtp, &pcs->rgd, RF_ACTIVE);
}
- if (regs == NULL && (cmd & m2)) {
- rtp = (m2 == PCIM_CMD_MEMEN)? SYS_RES_MEMORY : SYS_RES_IOPORT;
- rgd = (m2 == PCIM_CMD_MEMEN)? MEM_MAP_REG : IO_MAP_REG;
- regs = bus_alloc_resource_any(dev, rtp, &rgd, RF_ACTIVE);
+ if (pcs->regs == NULL && (cmd & m2)) {
+ pcs->rtp = (m2 == PCIM_CMD_MEMEN)? SYS_RES_MEMORY : SYS_RES_IOPORT;
+ pcs->rgd = (m2 == PCIM_CMD_MEMEN)? MEM_MAP_REG : IO_MAP_REG;
+ pcs->regs = bus_alloc_resource_any(dev, pcs->rtp, &pcs->rgd, RF_ACTIVE);
}
- if (regs == NULL) {
+ if (pcs->regs == NULL) {
device_printf(dev, "unable to map any ports\n");
goto bad;
}
if (bootverbose) {
- device_printf(dev, "using %s space register mapping\n", (rgd == IO_MAP_REG)? "I/O" : "Memory");
+ device_printf(dev, "using %s space register mapping\n", (pcs->rgd == IO_MAP_REG)? "I/O" : "Memory");
}
- isp->isp_bus_tag = rman_get_bustag(regs);
- isp->isp_bus_handle = rman_get_bushandle(regs);
+ isp->isp_bus_tag = rman_get_bustag(pcs->regs);
+ isp->isp_bus_handle = rman_get_bushandle(pcs->regs);
pcs->pci_dev = dev;
- pcs->pci_reg = regs;
pcs->pci_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF;
pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = PCI_MBOX_REGS_OFF;
pcs->pci_poff[SXP_BLOCK >> _BLK_REG_SHFT] = PCI_SXP_REGS_OFF;
@@ -931,13 +933,13 @@ isp_pci_attach(device_t dev)
pcs->msicount = 1;
}
if (pci_alloc_msi(dev, &pcs->msicount) == 0) {
- iqd = 1;
+ pcs->iqd = 1;
} else {
- iqd = 0;
+ pcs->iqd = 0;
}
}
- irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &iqd, RF_ACTIVE | RF_SHAREABLE);
- if (irq == NULL) {
+ pcs->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &pcs->iqd, RF_ACTIVE | RF_SHAREABLE);
+ if (pcs->irq == NULL) {
device_printf(dev, "could not allocate interrupt\n");
goto bad;
}
@@ -946,7 +948,7 @@ isp_pci_attach(device_t dev)
mtx_init(&isp->isp_osinfo.lock, "isp", NULL, MTX_DEF);
locksetup++;
- if (isp_setup_intr(dev, irq, ISP_IFLAGS, NULL, isp_platform_intr, isp, &pcs->ih)) {
+ if (isp_setup_intr(dev, pcs->irq, ISP_IFLAGS, NULL, isp_platform_intr, isp, &pcs->ih)) {
device_printf(dev, "could not setup interrupt\n");
goto bad;
}
@@ -982,19 +984,19 @@ isp_pci_attach(device_t dev)
bad:
if (pcs->ih) {
- (void) bus_teardown_intr(dev, irq, pcs->ih);
+ (void) bus_teardown_intr(dev, pcs->irq, pcs->ih);
}
if (locksetup) {
mtx_destroy(&isp->isp_osinfo.lock);
}
- if (irq) {
- (void) bus_release_resource(dev, SYS_RES_IRQ, iqd, irq);
+ if (pcs->irq) {
+ (void) bus_release_resource(dev, SYS_RES_IRQ, pcs->iqd, pcs->irq);
}
if (pcs->msicount) {
pci_release_msi(dev);
}
- if (regs) {
- (void) bus_release_resource(dev, rtp, rgd, regs);
+ if (pcs->regs) {
+ (void) bus_release_resource(dev, pcs->rtp, pcs->rgd, pcs->regs);
}
if (pcs->pci_isp.isp_param) {
free(pcs->pci_isp.isp_param, M_DEVBUF);
@@ -1012,14 +1014,36 @@ isp_pci_detach(device_t dev)
{
struct isp_pcisoftc *pcs;
ispsoftc_t *isp;
+ int status;
pcs = device_get_softc(dev);
if (pcs == NULL) {
return (ENXIO);
}
isp = (ispsoftc_t *) pcs;
- ISP_DISABLE_INTS(isp);
+ status = isp_detach(isp);
+ if (status)
+ return (status);
+ ISP_LOCK(isp);
+ isp_uninit(isp);
+ if (pcs->ih) {
+ (void) bus_teardown_intr(dev, pcs->irq, pcs->ih);
+ }
+ ISP_UNLOCK(isp);
mtx_destroy(&isp->isp_osinfo.lock);
+ (void) bus_release_resource(dev, SYS_RES_IRQ, pcs->iqd, pcs->irq);
+ if (pcs->msicount) {
+ pci_release_msi(dev);
+ }
+ (void) bus_release_resource(dev, pcs->rtp, pcs->rgd, pcs->regs);
+ if (pcs->pci_isp.isp_param) {
+ free(pcs->pci_isp.isp_param, M_DEVBUF);
+ pcs->pci_isp.isp_param = NULL;
+ }
+ if (pcs->pci_isp.isp_osinfo.pc.ptr) {
+ free(pcs->pci_isp.isp_osinfo.pc.ptr, M_DEVBUF);
+ pcs->pci_isp.isp_osinfo.pc.ptr = NULL;
+ }
return (0);
}
diff --git a/sys/dev/isp/ispvar.h b/sys/dev/isp/ispvar.h
index d7937949c4885..55edc17228cff 100644
--- a/sys/dev/isp/ispvar.h
+++ b/sys/dev/isp/ispvar.h
@@ -953,6 +953,11 @@ void isp_async(ispsoftc_t *, ispasync_t, ...);
#define ISPASYNC_CHANGE_OTHER 2
/*
+ * Platform Independent Error Prinout
+ */
+void isp_prt_endcmd(ispsoftc_t *, XS_T *);
+
+/*
* Platform Dependent Error and Debug Printout
*
* Two required functions for each platform must be provided:
diff --git a/sys/dev/ixgbe/ixgbe.c b/sys/dev/ixgbe/ixgbe.c
index a382a5356c4ef..9a709afcc01a7 100644
--- a/sys/dev/ixgbe/ixgbe.c
+++ b/sys/dev/ixgbe/ixgbe.c
@@ -3849,6 +3849,8 @@ fail:
**********************************************************************/
#define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2
+#define BSIZEPKT_ROUNDUP ((1<<IXGBE_SRRCTL_BSIZEPKT_SHIFT)-1)
+
static void
ixgbe_initialize_receive_units(struct adapter *adapter)
{
@@ -3882,7 +3884,7 @@ ixgbe_initialize_receive_units(struct adapter *adapter)
hlreg &= ~IXGBE_HLREG0_JUMBOEN;
IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg);
- bufsz = adapter->rx_mbuf_sz >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;
+ bufsz = (adapter->rx_mbuf_sz + BSIZEPKT_ROUNDUP) >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;
for (int i = 0; i < adapter->num_queues; i++, rxr++) {
u64 rdba = rxr->rxdma.dma_paddr;
@@ -4300,9 +4302,10 @@ ixgbe_rxeof(struct ix_queue *que, int count)
sendmp = rbuf->fmp;
rbuf->m_pack = rbuf->fmp = NULL;
- if (sendmp != NULL) /* secondary frag */
+ if (sendmp != NULL) { /* secondary frag */
+ mp->m_flags &= ~M_PKTHDR;
sendmp->m_pkthdr.len += mp->m_len;
- else {
+ } else {
/* first desc of a non-ps chain */
sendmp = mp;
sendmp->m_flags |= M_PKTHDR;
diff --git a/sys/dev/mfi/mfi.c b/sys/dev/mfi/mfi.c
index f9bfffe8786dd..470362d5baa3a 100644
--- a/sys/dev/mfi/mfi.c
+++ b/sys/dev/mfi/mfi.c
@@ -2132,8 +2132,7 @@ mfi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td
if (ioc->mfi_sense_len) {
/* get user-space sense ptr then copy out sense */
- bcopy(&((struct mfi_ioc_packet*)arg)
- ->mfi_frame.raw[ioc->mfi_sense_off],
+ bcopy(&ioc->mfi_frame.raw[ioc->mfi_sense_off],
&sense_ptr.sense_ptr_data[0],
sizeof(sense_ptr.sense_ptr_data));
#ifdef __amd64__
diff --git a/sys/dev/mfi/mfi_linux.c b/sys/dev/mfi/mfi_linux.c
index 44edf49109db1..12135ff2470bc 100644
--- a/sys/dev/mfi/mfi_linux.c
+++ b/sys/dev/mfi/mfi_linux.c
@@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/capability.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/module.h>
@@ -95,7 +96,7 @@ mfi_linux_ioctl(struct thread *p, struct linux_ioctl_args *args)
break;
}
- if ((error = fget(p, args->fd, &fp)) != 0)
+ if ((error = fget(p, args->fd, CAP_IOCTL, &fp)) != 0)
return (error);
error = fo_ioctl(fp, cmd, (caddr_t)args->arg, p->td_ucred, p);
fdrop(fp, p);
diff --git a/sys/dev/mii/brgphy.c b/sys/dev/mii/brgphy.c
index 8e3986a80be1c..88090b7607a47 100644
--- a/sys/dev/mii/brgphy.c
+++ b/sys/dev/mii/brgphy.c
@@ -876,10 +876,22 @@ brgphy_reset(struct mii_softc *sc)
struct bge_softc *bge_sc = NULL;
struct bce_softc *bce_sc = NULL;
struct ifnet *ifp;
- int val;
+ int i, val;
+
+ /*
+ * Perform a reset. Note that at least some Broadcom PHYs default to
+ * being powered down as well as isolated after a reset but don't work
+ * if one or both of these bits are cleared. However, they just work
+ * fine if both bits remain set, so we don't use mii_phy_reset() here.
+ */
+ PHY_WRITE(sc, BRGPHY_MII_BMCR, BRGPHY_BMCR_RESET);
- /* Perform a standard PHY reset. */
- mii_phy_reset(sc);
+ /* Wait 100ms for it to complete. */
+ for (i = 0; i < 100; i++) {
+ if ((PHY_READ(sc, BRGPHY_MII_BMCR) & BRGPHY_BMCR_RESET) == 0)
+ break;
+ DELAY(1000);
+ }
/* Handle any PHY specific procedures following the reset. */
switch (sc->mii_mpd_oui) {
diff --git a/sys/dev/mii/mii_physubr.c b/sys/dev/mii/mii_physubr.c
index be6650595cf2a..8e1476a7df45e 100644
--- a/sys/dev/mii/mii_physubr.c
+++ b/sys/dev/mii/mii_physubr.c
@@ -273,8 +273,8 @@ mii_phy_reset(struct mii_softc *sc)
DELAY(1000);
}
- /* NB: a PHY may default to isolation. */
- reg &= ~BMCR_ISO;
+ /* NB: a PHY may default to being powered down and/or isolated. */
+ reg &= ~(BMCR_PDOWN | BMCR_ISO);
if ((sc->mii_flags & MIIF_NOISOLATE) == 0 &&
((ife == NULL && sc->mii_inst != 0) ||
(ife != NULL && IFM_INST(ife->ifm_media) != sc->mii_inst)))
diff --git a/sys/dev/mmc/mmcsd.c b/sys/dev/mmc/mmcsd.c
index cbb64e4409dd7..6dd007c441d3b 100644
--- a/sys/dev/mmc/mmcsd.c
+++ b/sys/dev/mmc/mmcsd.c
@@ -137,7 +137,7 @@ mmcsd_attach(device_t dev)
d->d_drv1 = sc;
d->d_maxsize = 4*1024*1024; /* Maximum defined SD card AU size. */
d->d_sectorsize = mmc_get_sector_size(dev);
- d->d_mediasize = mmc_get_media_size(dev) * d->d_sectorsize;
+ d->d_mediasize = (off_t)mmc_get_media_size(dev) * d->d_sectorsize;
d->d_stripeoffset = 0;
d->d_stripesize = mmc_get_erase_sector(dev) * d->d_sectorsize;
d->d_unit = device_get_unit(dev);
diff --git a/sys/dev/mps/mps_sas.c b/sys/dev/mps/mps_sas.c
index 6fbda923bc445..2aa4773eef915 100644
--- a/sys/dev/mps/mps_sas.c
+++ b/sys/dev/mps/mps_sas.c
@@ -925,7 +925,7 @@ mpssas_action(struct cam_sim *sim, union ccb *ccb)
cpi->hba_misc = PIM_NOBUSRESET;
cpi->hba_eng_cnt = 0;
cpi->max_target = sassc->sc->facts->MaxTargets - 1;
- cpi->max_lun = 0;
+ cpi->max_lun = 8;
cpi->initiator_id = 255;
strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
strncpy(cpi->hba_vid, "LSILogic", HBA_IDLEN);
diff --git a/sys/dev/mpt/mpilib/mpi_ioc.h b/sys/dev/mpt/mpilib/mpi_ioc.h
index 107c561aeee72..c0c73d29f81c2 100644
--- a/sys/dev/mpt/mpilib/mpi_ioc.h
+++ b/sys/dev/mpt/mpilib/mpi_ioc.h
@@ -33,7 +33,7 @@
* Title: MPI IOC, Port, Event, FW Download, and FW Upload messages
* Creation Date: August 11, 2000
*
- * mpi_ioc.h Version: 01.05.14
+ * mpi_ioc.h Version: 01.05.16
*
* Version History
* ---------------
@@ -140,6 +140,16 @@
* added _MULTI_PORT_DOMAIN.
* 05-24-07 01.05.14 Added Common Boot Block type to FWDownload Request.
* Added Common Boot Block type to FWUpload Request.
+ * 08-07-07 01.05.15 Added MPI_EVENT_SAS_INIT_RC_REMOVED define.
+ * Added MPI_EVENT_IR2_RC_DUAL_PORT_ADDED and
+ * MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED for IR2 event data.
+ * Added SASAddress field to SAS Initiator Device Table
+ * Overflow event data structure.
+ * 03-28-08 01.05.16 Added two new ReasonCode values to SAS Device Status
+ * Change Event data to indicate completion of internally
+ * generated task management.
+ * Added MPI_EVENT_DSCVRY_ERR_DS_SATA_INIT_FAILURE define.
+ * Added MPI_EVENT_SAS_INIT_RC_INACCESSIBLE define.
* --------------------------------------------------------------------------
*/
@@ -639,6 +649,8 @@ typedef struct _EVENT_DATA_SAS_DEVICE_STATUS_CHANGE
#define MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL (0x0B)
#define MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL (0x0C)
#define MPI_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION (0x0D)
+#define MPI_EVENT_SAS_DEV_STAT_RC_CMPL_INTERNAL_DEV_RESET (0x0E)
+#define MPI_EVENT_SAS_DEV_STAT_RC_CMPL_TASK_ABORT_INTERNAL (0x0F)
/* SCSI Event data for Queue Full event */
@@ -735,6 +747,8 @@ typedef struct _MPI_EVENT_DATA_IR2
#define MPI_EVENT_IR2_RC_PD_REMOVED (0x05)
#define MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED (0x06)
#define MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR (0x07)
+#define MPI_EVENT_IR2_RC_DUAL_PORT_ADDED (0x08)
+#define MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED (0x09)
/* defines for logical disk states */
#define MPI_LD_STATE_OPTIMAL (0x00)
@@ -894,6 +908,7 @@ typedef struct _EVENT_DATA_DISCOVERY_ERROR
#define MPI_EVENT_DSCVRY_ERR_DS_UNSUPPORTED_DEVICE (0x00000800)
#define MPI_EVENT_DSCVRY_ERR_DS_MAX_SATA_TARGETS (0x00001000)
#define MPI_EVENT_DSCVRY_ERR_DS_MULTI_PORT_DOMAIN (0x00002000)
+#define MPI_EVENT_DSCVRY_ERR_DS_SATA_INIT_FAILURE (0x00004000)
/* SAS SMP Error Event data */
@@ -929,6 +944,8 @@ typedef struct _EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE
/* defines for the ReasonCode field of the SAS Initiator Device Status Change event */
#define MPI_EVENT_SAS_INIT_RC_ADDED (0x01)
+#define MPI_EVENT_SAS_INIT_RC_REMOVED (0x02)
+#define MPI_EVENT_SAS_INIT_RC_INACCESSIBLE (0x03)
/* SAS Initiator Device Table Overflow Event data */
@@ -937,6 +954,7 @@ typedef struct _EVENT_DATA_SAS_INIT_TABLE_OVERFLOW
U8 MaxInit; /* 00h */
U8 CurrentInit; /* 01h */
U16 Reserved1; /* 02h */
+ U64 SASAddress; /* 04h */
} EVENT_DATA_SAS_INIT_TABLE_OVERFLOW,
MPI_POINTER PTR_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW,
MpiEventDataSasInitTableOverflow_t,
diff --git a/sys/dev/mpt/mpt.c b/sys/dev/mpt/mpt.c
index fb24025ecffe8..9dfd73b2b3b58 100644
--- a/sys/dev/mpt/mpt.c
+++ b/sys/dev/mpt/mpt.c
@@ -301,66 +301,75 @@ mpt_modevent(module_t mod, int type, void *data)
return (error);
}
-int
+static int
mpt_stdload(struct mpt_personality *pers)
{
+
/* Load is always successful. */
return (0);
}
-int
+static int
mpt_stdprobe(struct mpt_softc *mpt)
{
+
/* Probe is always successful. */
return (0);
}
-int
+static int
mpt_stdattach(struct mpt_softc *mpt)
{
+
/* Attach is always successful. */
return (0);
}
-int
+static int
mpt_stdenable(struct mpt_softc *mpt)
{
+
/* Enable is always successful. */
return (0);
}
-void
+static void
mpt_stdready(struct mpt_softc *mpt)
{
-}
+}
-int
+static int
mpt_stdevent(struct mpt_softc *mpt, request_t *req, MSG_EVENT_NOTIFY_REPLY *msg)
{
+
mpt_lprt(mpt, MPT_PRT_DEBUG, "mpt_stdevent: 0x%x\n", msg->Event & 0xFF);
/* Event was not for us. */
return (0);
}
-void
+static void
mpt_stdreset(struct mpt_softc *mpt, int type)
{
+
}
-void
+static void
mpt_stdshutdown(struct mpt_softc *mpt)
{
+
}
-void
+static void
mpt_stddetach(struct mpt_softc *mpt)
{
+
}
-int
+static int
mpt_stdunload(struct mpt_personality *pers)
{
+
/* Unload is always successful. */
return (0);
}
@@ -383,7 +392,6 @@ mpt_postattach(void *unused)
}
SYSINIT(mptdev, SI_SUB_CONFIGURE, SI_ORDER_MIDDLE, mpt_postattach, NULL);
-
/******************************* Bus DMA Support ******************************/
void
mpt_map_rquest(void *arg, bus_dma_segment_t *segs, int nseg, int error)
@@ -478,6 +486,7 @@ static int
mpt_default_reply_handler(struct mpt_softc *mpt, request_t *req,
uint32_t reply_desc, MSG_DEFAULT_REPLY *reply_frame)
{
+
mpt_prt(mpt,
"Default Handler Called: req=%p:%u reply_descriptor=%x frame=%p\n",
req, req->serno, reply_desc, reply_frame);
@@ -494,8 +503,8 @@ static int
mpt_config_reply_handler(struct mpt_softc *mpt, request_t *req,
uint32_t reply_desc, MSG_DEFAULT_REPLY *reply_frame)
{
- if (req != NULL) {
+ if (req != NULL) {
if (reply_frame != NULL) {
MSG_CONFIG *cfgp;
MSG_CONFIG_REPLY *reply;
@@ -528,6 +537,7 @@ static int
mpt_handshake_reply_handler(struct mpt_softc *mpt, request_t *req,
uint32_t reply_desc, MSG_DEFAULT_REPLY *reply_frame)
{
+
/* Nothing to be done. */
return (TRUE);
}
@@ -650,6 +660,7 @@ static int
mpt_core_event(struct mpt_softc *mpt, request_t *req,
MSG_EVENT_NOTIFY_REPLY *msg)
{
+
mpt_lprt(mpt, MPT_PRT_DEBUG, "mpt_core_event: 0x%x\n",
msg->Event & 0xFF);
switch(msg->Event & 0xFF) {
@@ -870,6 +881,7 @@ mpt_complete_request_chain(struct mpt_softc *mpt, struct req_queue *chain,
void
mpt_dump_reply_frame(struct mpt_softc *mpt, MSG_DEFAULT_REPLY *reply_frame)
{
+
mpt_prt(mpt, "Address Reply:\n");
mpt_print_reply(reply_frame);
}
@@ -881,12 +893,14 @@ static __inline uint32_t mpt_rd_intr(struct mpt_softc *mpt);
static __inline uint32_t
mpt_rd_db(struct mpt_softc *mpt)
{
+
return mpt_read(mpt, MPT_OFFSET_DOORBELL);
}
static __inline uint32_t
mpt_rd_intr(struct mpt_softc *mpt)
{
+
return mpt_read(mpt, MPT_OFFSET_INTR_STATUS);
}
@@ -895,6 +909,7 @@ static int
mpt_wait_db_ack(struct mpt_softc *mpt)
{
int i;
+
for (i=0; i < MPT_MAX_WAIT; i++) {
if (!MPT_DB_IS_BUSY(mpt_rd_intr(mpt))) {
maxwait_ack = i > maxwait_ack ? i : maxwait_ack;
@@ -910,6 +925,7 @@ static int
mpt_wait_db_int(struct mpt_softc *mpt)
{
int i;
+
for (i = 0; i < MPT_MAX_WAIT; i++) {
if (MPT_DB_INTR(mpt_rd_intr(mpt))) {
maxwait_int = i > maxwait_int ? i : maxwait_int;
@@ -925,6 +941,7 @@ void
mpt_check_doorbell(struct mpt_softc *mpt)
{
uint32_t db = mpt_rd_db(mpt);
+
if (MPT_STATE(db) != MPT_DB_STATE_RUNNING) {
mpt_prt(mpt, "Device not running\n");
mpt_print_db(db);
@@ -956,6 +973,7 @@ static int mpt_download_fw(struct mpt_softc *mpt);
static int
mpt_soft_reset(struct mpt_softc *mpt)
{
+
mpt_lprt(mpt, MPT_PRT_DEBUG, "soft reset\n");
/* Have to use hard reset if we are not in Running state */
@@ -1019,6 +1037,7 @@ mpt_enable_diag_mode(struct mpt_softc *mpt)
static void
mpt_disable_diag_mode(struct mpt_softc *mpt)
{
+
mpt_write(mpt, MPT_OFFSET_SEQUENCE, 0xFFFFFFFF);
}
@@ -1094,6 +1113,7 @@ mpt_hard_reset(struct mpt_softc *mpt)
static void
mpt_core_ioc_reset(struct mpt_softc *mpt, int type)
{
+
/*
* Complete all pending requests with a status
* appropriate for an IOC reset.
@@ -1102,7 +1122,6 @@ mpt_core_ioc_reset(struct mpt_softc *mpt, int type)
MPI_IOCSTATUS_INVALID_STATE);
}
-
/*
* Reset the IOC when needed. Try software command first then if needed
* poke at the magic diagnostic reset. Note that a hard reset resets
@@ -1263,6 +1282,7 @@ retry:
void
mpt_send_cmd(struct mpt_softc *mpt, request_t *req)
{
+
if (mpt->verbose > MPT_PRT_DEBUG2) {
mpt_dump_request(mpt, req);
}
@@ -2110,6 +2130,7 @@ mpt_send_event_request(struct mpt_softc *mpt, int onoff)
void
mpt_enable_ints(struct mpt_softc *mpt)
{
+
/* Unmask every thing except door bell int */
mpt_write(mpt, MPT_OFFSET_INTR_MASK, MPT_INTR_DB_MASK);
}
@@ -2120,6 +2141,7 @@ mpt_enable_ints(struct mpt_softc *mpt)
void
mpt_disable_ints(struct mpt_softc *mpt)
{
+
/* Mask all interrupts */
mpt_write(mpt, MPT_OFFSET_INTR_MASK,
MPT_INTR_REPLY_MASK | MPT_INTR_DB_MASK);
@@ -2219,7 +2241,7 @@ mpt_detach(struct mpt_softc *mpt)
return (0);
}
-int
+static int
mpt_core_load(struct mpt_personality *pers)
{
int i;
@@ -2245,7 +2267,7 @@ mpt_core_load(struct mpt_personality *pers)
* Initialize per-instance driver data and perform
* initial controller configuration.
*/
-int
+static int
mpt_core_attach(struct mpt_softc *mpt)
{
int val, error;
@@ -2276,9 +2298,10 @@ mpt_core_attach(struct mpt_softc *mpt)
return (error);
}
-int
+static int
mpt_core_enable(struct mpt_softc *mpt)
{
+
/*
* We enter with the IOC enabled, but async events
* not enabled, ports not enabled and interrupts
@@ -2326,13 +2349,14 @@ mpt_core_enable(struct mpt_softc *mpt)
return (0);
}
-void
+static void
mpt_core_shutdown(struct mpt_softc *mpt)
{
+
mpt_disable_ints(mpt);
}
-void
+static void
mpt_core_detach(struct mpt_softc *mpt)
{
int val;
@@ -2351,9 +2375,10 @@ mpt_core_detach(struct mpt_softc *mpt)
mpt_dma_buf_free(mpt);
}
-int
+static int
mpt_core_unload(struct mpt_personality *pers)
{
+
/* Unload is always successful. */
return (0);
}
@@ -2575,6 +2600,7 @@ static void
mpt_dma_buf_free(struct mpt_softc *mpt)
{
int i;
+
if (mpt->request_dmat == 0) {
mpt_lprt(mpt, MPT_PRT_DEBUG, "already released dma memory\n");
return;
diff --git a/sys/dev/mpt/mpt.h b/sys/dev/mpt/mpt.h
index d12c307c80311..8a20e82b92d5a 100644
--- a/sys/dev/mpt/mpt.h
+++ b/sys/dev/mpt/mpt.h
@@ -1075,16 +1075,6 @@ mpt_complete_request_chain(struct mpt_softc *, struct req_queue *, u_int);
int mpt_reset(struct mpt_softc *, int /*reinit*/);
/****************************** Debugging ************************************/
-typedef struct mpt_decode_entry {
- char *name;
- u_int value;
- u_int mask;
-} mpt_decode_entry_t;
-
-int mpt_decode_value(mpt_decode_entry_t *table, u_int num_entries,
- const char *name, u_int value, u_int *cur_column,
- u_int wrap_point);
-
void mpt_dump_data(struct mpt_softc *, const char *, void *, int);
void mpt_dump_request(struct mpt_softc *, request_t *);
@@ -1110,17 +1100,21 @@ do { \
mpt_prt(mpt, __VA_ARGS__); \
} while (0)
+#if 0
#define mpt_lprtc(mpt, level, ...) \
do { \
if (level <= (mpt)->verbose) \
mpt_prtc(mpt, __VA_ARGS__); \
} while (0)
+#endif
#else
void mpt_lprt(struct mpt_softc *, int, const char *, ...)
__printflike(3, 4);
+#if 0
void mpt_lprtc(struct mpt_softc *, int, const char *, ...)
__printflike(3, 4);
#endif
+#endif
void mpt_prt(struct mpt_softc *, const char *, ...)
__printflike(2, 3);
void mpt_prtc(struct mpt_softc *, const char *, ...)
@@ -1277,7 +1271,6 @@ void mpt_check_doorbell(struct mpt_softc *mpt);
void mpt_dump_reply_frame(struct mpt_softc *mpt,
MSG_DEFAULT_REPLY *reply_frame);
-void mpt_set_config_regs(struct mpt_softc *);
int mpt_issue_cfg_req(struct mpt_softc */*mpt*/, request_t */*req*/,
cfgparms_t *params,
bus_addr_t /*addr*/, bus_size_t/*len*/,
@@ -1331,6 +1324,5 @@ char *mpt_ioc_diag(uint32_t diag);
void mpt_req_state(mpt_req_state_t state);
void mpt_print_config_request(void *vmsg);
void mpt_print_request(void *vmsg);
-void mpt_print_scsi_io_request(MSG_SCSI_IO_REQUEST *msg);
void mpt_dump_sgl(SGE_IO_UNION *se, int offset);
#endif /* _MPT_H_ */
diff --git a/sys/dev/mpt/mpt_cam.c b/sys/dev/mpt/mpt_cam.c
index 1b997d155a2d9..d512458c7582b 100644
--- a/sys/dev/mpt/mpt_cam.c
+++ b/sys/dev/mpt/mpt_cam.c
@@ -193,7 +193,7 @@ MODULE_DEPEND(mpt_cam, cam, 1, 1, 1);
int mpt_enable_sata_wc = -1;
TUNABLE_INT("hw.mpt.enable_sata_wc", &mpt_enable_sata_wc);
-int
+static int
mpt_cam_probe(struct mpt_softc *mpt)
{
int role;
@@ -215,7 +215,7 @@ mpt_cam_probe(struct mpt_softc *mpt)
return (ENODEV);
}
-int
+static int
mpt_cam_attach(struct mpt_softc *mpt)
{
struct cam_devq *devq;
@@ -509,7 +509,6 @@ mpt_read_config_info_fc(struct mpt_softc *mpt)
static int
mpt_set_initial_config_fc(struct mpt_softc *mpt)
{
-
CONFIG_PAGE_FC_PORT_1 fc;
U32 fl;
int r, doit = 0;
@@ -881,8 +880,8 @@ static int
mpt_sata_pass_reply_handler(struct mpt_softc *mpt, request_t *req,
uint32_t reply_desc, MSG_DEFAULT_REPLY *reply_frame)
{
- if (req != NULL) {
+ if (req != NULL) {
if (reply_frame != NULL) {
req->IOCStatus = le16toh(reply_frame->IOCStatus);
}
@@ -1114,7 +1113,7 @@ mpt_set_initial_config_spi(struct mpt_softc *mpt)
return (0);
}
-int
+static int
mpt_cam_enable(struct mpt_softc *mpt)
{
int error;
@@ -1151,9 +1150,10 @@ out:
return (error);
}
-void
+static void
mpt_cam_ready(struct mpt_softc *mpt)
{
+
/*
* If we're in target mode, hang out resources now
* so we don't cause the world to hang talking to us.
@@ -1171,7 +1171,7 @@ mpt_cam_ready(struct mpt_softc *mpt)
mpt->ready = 1;
}
-void
+static void
mpt_cam_detach(struct mpt_softc *mpt)
{
mpt_handler_t handler;
@@ -1842,8 +1842,6 @@ bad:
memset(se, 0,sizeof (*se));
se->Address = htole32(dm_segs->ds_addr);
-
-
MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len);
tf = flags;
if (seg == first_lim - 1) {
@@ -1958,9 +1956,6 @@ bad:
memset(se, 0, sizeof (*se));
se->Address = htole32(dm_segs->ds_addr);
-
-
-
MPI_pSGE_SET_LENGTH(se, dm_segs->ds_len);
tf = flags;
if (seg == this_seg_lim - 1) {
@@ -2543,7 +2538,8 @@ mpt_cam_event(struct mpt_softc *mpt, request_t *req,
pqf->CurrentDepth = le16toh(pqf->CurrentDepth);
mpt_prt(mpt, "QUEUE FULL EVENT: Bus 0x%02x Target 0x%02x Depth "
"%d\n", pqf->Bus, pqf->TargetID, pqf->CurrentDepth);
- if (mpt->phydisk_sim) {
+ if (mpt->phydisk_sim && mpt_is_raid_member(mpt,
+ pqf->TargetID) != 0) {
sim = mpt->phydisk_sim;
} else {
sim = mpt->sim;
@@ -2575,9 +2571,85 @@ mpt_cam_event(struct mpt_softc *mpt, request_t *req,
mpt_prt(mpt, "IR resync update %d completed\n",
(data0 >> 16) & 0xff);
break;
+ case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
+ {
+ union ccb *ccb;
+ struct cam_sim *sim;
+ struct cam_path *tmppath;
+ PTR_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE psdsc;
+
+ psdsc = (PTR_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE)msg->Data;
+ if (mpt->phydisk_sim && mpt_is_raid_member(mpt,
+ psdsc->TargetID) != 0)
+ sim = mpt->phydisk_sim;
+ else
+ sim = mpt->sim;
+ switch(psdsc->ReasonCode) {
+ case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
+ MPTLOCK_2_CAMLOCK(mpt);
+ ccb = xpt_alloc_ccb_nowait();
+ if (ccb == NULL) {
+ mpt_prt(mpt,
+ "unable to alloc CCB for rescan\n");
+ CAMLOCK_2_MPTLOCK(mpt);
+ break;
+ }
+ if (xpt_create_path(&ccb->ccb_h.path, xpt_periph,
+ cam_sim_path(sim), psdsc->TargetID,
+ CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+ CAMLOCK_2_MPTLOCK(mpt);
+ mpt_prt(mpt,
+ "unable to create path for rescan\n");
+ xpt_free_ccb(ccb);
+ break;
+ }
+ xpt_rescan(ccb);
+ CAMLOCK_2_MPTLOCK(mpt);
+ break;
+ case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
+ MPTLOCK_2_CAMLOCK(mpt);
+ if (xpt_create_path(&tmppath, NULL, cam_sim_path(sim),
+ psdsc->TargetID, CAM_LUN_WILDCARD) !=
+ CAM_REQ_CMP) {
+ mpt_prt(mpt,
+ "unable to create path for async event");
+ CAMLOCK_2_MPTLOCK(mpt);
+ break;
+ }
+ xpt_async(AC_LOST_DEVICE, tmppath, NULL);
+ xpt_free_path(tmppath);
+ CAMLOCK_2_MPTLOCK(mpt);
+ break;
+ case MPI_EVENT_SAS_DEV_STAT_RC_CMPL_INTERNAL_DEV_RESET:
+ case MPI_EVENT_SAS_DEV_STAT_RC_CMPL_TASK_ABORT_INTERNAL:
+ case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
+ break;
+ default:
+ mpt_lprt(mpt, MPT_PRT_WARN,
+ "SAS device status change: Bus: 0x%02x TargetID: "
+ "0x%02x ReasonCode: 0x%02x\n", psdsc->Bus,
+ psdsc->TargetID, psdsc->ReasonCode);
+ break;
+ }
+ break;
+ }
+ case MPI_EVENT_SAS_DISCOVERY_ERROR:
+ {
+ PTR_EVENT_DATA_DISCOVERY_ERROR pde;
+
+ pde = (PTR_EVENT_DATA_DISCOVERY_ERROR)msg->Data;
+ pde->DiscoveryStatus = le32toh(pde->DiscoveryStatus);
+ mpt_lprt(mpt, MPT_PRT_WARN,
+ "SAS discovery error: Port: 0x%02x Status: 0x%08x\n",
+ pde->Port, pde->DiscoveryStatus);
+ break;
+ }
case MPI_EVENT_EVENT_CHANGE:
case MPI_EVENT_INTEGRATED_RAID:
- case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
+ case MPI_EVENT_IR2:
+ case MPI_EVENT_LOG_ENTRY_ADDED:
+ case MPI_EVENT_SAS_DISCOVERY:
+ case MPI_EVENT_SAS_PHY_LINK_STATUS:
case MPI_EVENT_SAS_SES:
break;
default:
@@ -3045,6 +3117,7 @@ mpt_fc_els_reply_handler(struct mpt_softc *mpt, request_t *req,
static void
mpt_cam_ioc_reset(struct mpt_softc *mpt, int type)
{
+
/*
* The pending list is already run down by
* the generic handler. Perform the same
@@ -3974,6 +4047,7 @@ mpt_spawn_recovery_thread(struct mpt_softc *mpt)
static void
mpt_terminate_recovery_thread(struct mpt_softc *mpt)
{
+
if (mpt->recovery_thread == NULL) {
return;
}
@@ -4377,6 +4451,7 @@ mpt_add_target_commands(struct mpt_softc *mpt)
static int
mpt_enable_lun(struct mpt_softc *mpt, target_id_t tgt, lun_id_t lun)
{
+
if (tgt == CAM_TARGET_WILDCARD && lun == CAM_LUN_WILDCARD) {
mpt->twildcard = 1;
} else if (lun >= MPT_MAX_LUNS) {
@@ -4402,6 +4477,7 @@ static int
mpt_disable_lun(struct mpt_softc *mpt, target_id_t tgt, lun_id_t lun)
{
int i;
+
if (tgt == CAM_TARGET_WILDCARD && lun == CAM_LUN_WILDCARD) {
mpt->twildcard = 0;
} else if (lun >= MPT_MAX_LUNS) {
@@ -5286,6 +5362,7 @@ mpt_tgt_dump_tgt_state(struct mpt_softc *mpt, request_t *req)
static void
mpt_tgt_dump_req_state(struct mpt_softc *mpt, request_t *req)
{
+
mpt_prt(mpt, "req %p:%u index %u (%x) state %x\n", req, req->serno,
req->index, req->index, req->state);
mpt_tgt_dump_tgt_state(mpt, req);
diff --git a/sys/dev/mpt/mpt_debug.c b/sys/dev/mpt/mpt_debug.c
index e7f75faa5b456..dd70dc9d8160a 100644
--- a/sys/dev/mpt/mpt_debug.c
+++ b/sys/dev/mpt/mpt_debug.c
@@ -285,6 +285,7 @@ mpt_scsi_state(int code)
}
return buf;
}
+
static char *
mpt_scsi_status(int code)
{
@@ -298,10 +299,11 @@ mpt_scsi_status(int code)
snprintf(buf, sizeof buf, "Unknown (0x%08x)", code);
return buf;
}
-static char *
+
+static const char *
mpt_who(int who_init)
{
- char *who;
+ const char *who;
switch (who_init) {
case MPT_DB_INIT_NOONE: who = "No One"; break;
@@ -315,10 +317,10 @@ mpt_who(int who_init)
return who;
}
-static char *
+static const char *
mpt_state(u_int32_t mb)
{
- char *text;
+ const char *text;
switch (MPT_STATE(mb)) {
case MPT_DB_STATE_RESET: text = "Reset"; break;
@@ -347,6 +349,7 @@ mpt_scsi_tm_type(int code)
void
mpt_print_db(u_int32_t mb)
{
+
printf("mpt mailbox: (0x%x) State %s WhoInit %s\n",
mb, mpt_state(mb), mpt_who(MPT_WHO(mb)));
}
@@ -357,6 +360,7 @@ mpt_print_db(u_int32_t mb)
static void
mpt_print_reply_hdr(MSG_DEFAULT_REPLY *msg)
{
+
printf("%s Reply @ %p\n", mpt_ioc_function(msg->Function), msg);
printf("\tIOC Status %s\n", mpt_ioc_status(msg->IOCStatus));
printf("\tIOCLogInfo 0x%08x\n", msg->IOCLogInfo);
@@ -368,6 +372,7 @@ mpt_print_reply_hdr(MSG_DEFAULT_REPLY *msg)
static void
mpt_print_init_reply(MSG_IOC_INIT_REPLY *msg)
{
+
mpt_print_reply_hdr((MSG_DEFAULT_REPLY *)msg);
printf("\tWhoInit %s\n", mpt_who(msg->WhoInit));
printf("\tMaxDevices 0x%02x\n", msg->MaxDevices);
@@ -377,6 +382,7 @@ mpt_print_init_reply(MSG_IOC_INIT_REPLY *msg)
static void
mpt_print_ioc_facts(MSG_IOC_FACTS_REPLY *msg)
{
+
mpt_print_reply_hdr((MSG_DEFAULT_REPLY *)msg);
printf("\tIOCNumber %d\n", msg->IOCNumber);
printf("\tMaxChainDepth %d\n", msg->MaxChainDepth);
@@ -402,6 +408,7 @@ mpt_print_ioc_facts(MSG_IOC_FACTS_REPLY *msg)
static void
mpt_print_enable_reply(MSG_PORT_ENABLE_REPLY *msg)
{
+
mpt_print_reply_hdr((MSG_DEFAULT_REPLY *)msg);
printf("\tPort: %d\n", msg->PortNumber);
}
@@ -409,6 +416,7 @@ mpt_print_enable_reply(MSG_PORT_ENABLE_REPLY *msg)
static void
mpt_print_scsi_io_reply(MSG_SCSI_IO_REPLY *msg)
{
+
mpt_print_reply_hdr((MSG_DEFAULT_REPLY *)msg);
printf("\tBus: %d\n", msg->Bus);
printf("\tTargetID %d\n", msg->TargetID);
@@ -420,11 +428,10 @@ mpt_print_scsi_io_reply(MSG_SCSI_IO_REPLY *msg)
printf("\tResponseInfo 0x%08x\n", msg->ResponseInfo);
}
-
-
static void
mpt_print_event_notice(MSG_EVENT_NOTIFY_REPLY *msg)
{
+
mpt_print_reply_hdr((MSG_DEFAULT_REPLY *)msg);
printf("\tEvent: %s\n", mpt_ioc_event(msg->Event));
printf("\tEventContext 0x%04x\n", msg->EventContext);
@@ -517,7 +524,7 @@ mpt_print_request_hdr(MSG_REQUEST_HEADER *req)
printf("\tMsgContext 0x%08x\n", req->MsgContext);
}
-void
+static void
mpt_print_scsi_io_request(MSG_SCSI_IO_REQUEST *orig_msg)
{
MSG_SCSI_IO_REQUEST local, *msg = &local;
@@ -575,6 +582,7 @@ mpt_print_scsi_io_request(MSG_SCSI_IO_REQUEST *orig_msg)
static void
mpt_print_scsi_tmf_request(MSG_SCSI_TASK_MGMT *msg)
{
+
mpt_print_request_hdr((MSG_REQUEST_HEADER *)msg);
printf("\tLun 0x%02x\n", msg->LUN[1]);
printf("\tTaskType %s\n", mpt_scsi_tm_type(msg->TaskType));
@@ -585,6 +593,7 @@ mpt_print_scsi_tmf_request(MSG_SCSI_TASK_MGMT *msg)
static void
mpt_print_scsi_target_assist_request(PTR_MSG_TARGET_ASSIST_REQUEST msg)
{
+
mpt_print_request_hdr((MSG_REQUEST_HEADER *)msg);
printf("\tStatusCode 0x%02x\n", msg->StatusCode);
printf("\tTargetAssist 0x%02x\n", msg->TargetAssistFlags);
@@ -600,6 +609,7 @@ static void
mpt_print_scsi_target_status_send_request(MSG_TARGET_STATUS_SEND_REQUEST *msg)
{
SGE_IO_UNION x;
+
mpt_print_request_hdr((MSG_REQUEST_HEADER *)msg);
printf("\tStatusCode 0x%02x\n", msg->StatusCode);
printf("\tStatusFlags 0x%02x\n", msg->StatusFlags);
@@ -637,7 +647,14 @@ mpt_print_request(void *vreq)
}
}
-int
+#if 0
+typedef struct mpt_decode_entry {
+ char *name;
+ u_int value;
+ u_int mask;
+} mpt_decode_entry_t;
+
+static int
mpt_decode_value(mpt_decode_entry_t *table, u_int num_entries,
const char *name, u_int value, u_int *cur_column,
u_int wrap_point)
@@ -689,7 +706,7 @@ mpt_decode_value(mpt_decode_entry_t *table, u_int num_entries,
return (printed);
}
-static mpt_decode_entry_t req_state_parse_table[] = {
+static const mpt_decode_entry_t req_state_parse_table[] = {
{ "REQ_FREE", 0x00, 0xff },
{ "REQ_ALLOCATED", 0x01, 0x01 },
{ "REQ_QUEUED", 0x02, 0x02 },
@@ -698,13 +715,15 @@ static mpt_decode_entry_t req_state_parse_table[] = {
{ "REQ_NEED_WAKEUP", 0x10, 0x10 }
};
-void
+static void
mpt_req_state(mpt_req_state_t state)
{
+
mpt_decode_value(req_state_parse_table,
NUM_ELEMENTS(req_state_parse_table),
"REQ_STATE", state, NULL, 80);
}
+#endif
#define LAST_SGE ( \
MPI_SGE_FLAGS_END_OF_LIST | \
@@ -805,6 +824,7 @@ mpt_dump_data(struct mpt_softc *mpt, const char *msg, void *addr, int len)
{
int offset;
uint8_t *cp = addr;
+
mpt_prt(mpt, "%s:", msg);
for (offset = 0; offset < len; offset++) {
if ((offset & 0xf) == 0) {
@@ -820,6 +840,7 @@ mpt_dump_request(struct mpt_softc *mpt, request_t *req)
{
uint32_t *pReq = req->req_vbuf;
int o;
+
#if __FreeBSD_version >= 500000
mpt_prt(mpt, "Send Request %d (%jx):",
req->index, (uintmax_t) req->req_pbuf);
@@ -850,6 +871,7 @@ mpt_lprt(struct mpt_softc *mpt, int level, const char *fmt, ...)
}
}
+#if 0
void
mpt_lprtc(struct mpt_softc *mpt, int level, const char *fmt, ...)
{
@@ -861,6 +883,7 @@ mpt_lprtc(struct mpt_softc *mpt, int level, const char *fmt, ...)
}
}
#endif
+#endif
void
mpt_prt(struct mpt_softc *mpt, const char *fmt, ...)
diff --git a/sys/dev/mpt/mpt_pci.c b/sys/dev/mpt/mpt_pci.c
index f7201b613e6af..7e3211b4722e7 100644
--- a/sys/dev/mpt/mpt_pci.c
+++ b/sys/dev/mpt/mpt_pci.c
@@ -201,6 +201,9 @@ static int mpt_pci_shutdown(device_t);
static int mpt_dma_mem_alloc(struct mpt_softc *mpt);
static void mpt_dma_mem_free(struct mpt_softc *mpt);
static void mpt_read_config_regs(struct mpt_softc *mpt);
+#if 0
+static void mpt_set_config_regs(struct mpt_softc *mpt);
+#endif
static void mpt_pci_intr(void *);
static device_method_t mpt_methods[] = {
@@ -404,6 +407,7 @@ mpt_link_peer(struct mpt_softc *mpt)
static void
mpt_unlink_peer(struct mpt_softc *mpt)
{
+
if (mpt->mpt2) {
mpt->mpt2->mpt2 = NULL;
}
@@ -654,6 +658,7 @@ bad:
static void
mpt_free_bus_resources(struct mpt_softc *mpt)
{
+
if (mpt->ih) {
bus_teardown_intr(mpt->dev, mpt->pci_irq, mpt->ih);
mpt->ih = NULL;
@@ -827,6 +832,7 @@ mpt_dma_mem_free(struct mpt_softc *mpt)
static void
mpt_read_config_regs(struct mpt_softc *mpt)
{
+
mpt->pci_cfg.Command = pci_read_config(mpt->dev, PCIR_COMMAND, 2);
mpt->pci_cfg.LatencyTimer_LineSize =
pci_read_config(mpt->dev, PCIR_CACHELNSZ, 2);
@@ -840,8 +846,9 @@ mpt_read_config_regs(struct mpt_softc *mpt)
mpt->pci_cfg.PMCSR = pci_read_config(mpt->dev, 0x44, 4);
}
+#if 0
/* Sets modifiable config registers */
-void
+static void
mpt_set_config_regs(struct mpt_softc *mpt)
{
uint32_t val;
@@ -880,6 +887,7 @@ mpt_set_config_regs(struct mpt_softc *mpt)
pci_write_config(mpt->dev, PCIR_INTLINE, mpt->pci_cfg.IntLine, 1);
pci_write_config(mpt->dev, 0x44, mpt->pci_cfg.PMCSR, 4);
}
+#endif
static void
mpt_pci_intr(void *arg)
diff --git a/sys/dev/mpt/mpt_raid.c b/sys/dev/mpt/mpt_raid.c
index 11650ed7f7c5a..8000a0103ed1d 100644
--- a/sys/dev/mpt/mpt_raid.c
+++ b/sys/dev/mpt/mpt_raid.c
@@ -81,7 +81,6 @@ struct mpt_raid_action_result
#define REQ_IOCSTATUS(req) ((req)->IOCStatus & MPI_IOCSTATUS_MASK)
-
static mpt_probe_handler_t mpt_raid_probe;
static mpt_attach_handler_t mpt_raid_attach;
static mpt_enable_handler_t mpt_raid_enable;
@@ -125,9 +124,25 @@ static void mpt_adjust_queue_depth(struct mpt_softc *, struct mpt_raid_volume *,
static void mpt_raid_sysctl_attach(struct mpt_softc *);
#endif
+static const char *mpt_vol_type(struct mpt_raid_volume *vol);
+static const char *mpt_vol_state(struct mpt_raid_volume *vol);
+static const char *mpt_disk_state(struct mpt_raid_disk *disk);
+static void mpt_vol_prt(struct mpt_softc *mpt, struct mpt_raid_volume *vol,
+ const char *fmt, ...);
+static void mpt_disk_prt(struct mpt_softc *mpt, struct mpt_raid_disk *disk,
+ const char *fmt, ...);
+
+static int mpt_issue_raid_req(struct mpt_softc *mpt,
+ struct mpt_raid_volume *vol, struct mpt_raid_disk *disk, request_t *req,
+ u_int Action, uint32_t ActionDataWord, bus_addr_t addr, bus_size_t len,
+ int write, int wait);
+
+static int mpt_refresh_raid_data(struct mpt_softc *mpt);
+static void mpt_schedule_raid_refresh(struct mpt_softc *mpt);
+
static uint32_t raid_handler_id = MPT_HANDLER_ID_NONE;
-const char *
+static const char *
mpt_vol_type(struct mpt_raid_volume *vol)
{
switch (vol->config_page->VolumeType) {
@@ -142,7 +157,7 @@ mpt_vol_type(struct mpt_raid_volume *vol)
}
}
-const char *
+static const char *
mpt_vol_state(struct mpt_raid_volume *vol)
{
switch (vol->config_page->VolumeStatus.State) {
@@ -157,7 +172,7 @@ mpt_vol_state(struct mpt_raid_volume *vol)
}
}
-const char *
+static const char *
mpt_disk_state(struct mpt_raid_disk *disk)
{
switch (disk->config_page.PhysDiskStatus.State) {
@@ -182,7 +197,7 @@ mpt_disk_state(struct mpt_raid_disk *disk)
}
}
-void
+static void
mpt_vol_prt(struct mpt_softc *mpt, struct mpt_raid_volume *vol,
const char *fmt, ...)
{
@@ -196,7 +211,7 @@ mpt_vol_prt(struct mpt_softc *mpt, struct mpt_raid_volume *vol,
va_end(ap);
}
-void
+static void
mpt_disk_prt(struct mpt_softc *mpt, struct mpt_raid_disk *disk,
const char *fmt, ...)
{
@@ -254,16 +269,17 @@ mpt_raid_async(void *callback_arg, u_int32_t code,
}
}
-int
+static int
mpt_raid_probe(struct mpt_softc *mpt)
{
+
if (mpt->ioc_page2 == NULL || mpt->ioc_page2->MaxPhysDisks == 0) {
return (ENODEV);
}
return (0);
}
-int
+static int
mpt_raid_attach(struct mpt_softc *mpt)
{
struct ccb_setasync csa;
@@ -307,13 +323,14 @@ cleanup:
return (error);
}
-int
+static int
mpt_raid_enable(struct mpt_softc *mpt)
{
+
return (0);
}
-void
+static void
mpt_raid_detach(struct mpt_softc *mpt)
{
struct ccb_setasync csa;
@@ -338,6 +355,7 @@ mpt_raid_detach(struct mpt_softc *mpt)
static void
mpt_raid_ioc_reset(struct mpt_softc *mpt, int type)
{
+
/* Nothing to do yet. */
}
@@ -570,7 +588,7 @@ mpt_raid_reply_frame_handler(struct mpt_softc *mpt, request_t *req,
/*
* Utiltity routine to perform a RAID action command;
*/
-int
+static int
mpt_issue_raid_req(struct mpt_softc *mpt, struct mpt_raid_volume *vol,
struct mpt_raid_disk *disk, request_t *req, u_int Action,
uint32_t ActionDataWord, bus_addr_t addr, bus_size_t len,
@@ -719,6 +737,7 @@ mpt_raid_thread(void *arg)
static void
mpt_raid_quiesce_timeout(void *arg)
{
+
/* Complete the CCB with error */
/* COWWWW */
}
@@ -776,7 +795,7 @@ mpt_raid_quiesce_disk(struct mpt_softc *mpt, struct mpt_raid_disk *mpt_disk,
/* XXX Ignores that there may be multiple busses/IOCs involved. */
cam_status
-mpt_map_physdisk(struct mpt_softc *mpt, union ccb *ccb, u_int *tgt)
+mpt_map_physdisk(struct mpt_softc *mpt, union ccb *ccb, target_id_t *tgt)
{
struct mpt_raid_disk *mpt_disk;
@@ -793,7 +812,26 @@ mpt_map_physdisk(struct mpt_softc *mpt, union ccb *ccb, u_int *tgt)
/* XXX Ignores that there may be multiple busses/IOCs involved. */
int
-mpt_is_raid_volume(struct mpt_softc *mpt, int tgt)
+mpt_is_raid_member(struct mpt_softc *mpt, target_id_t tgt)
+{
+ struct mpt_raid_disk *mpt_disk;
+ int i;
+
+ if (mpt->ioc_page2 == NULL || mpt->ioc_page2->MaxPhysDisks == 0)
+ return (0);
+ for (i = 0; i < mpt->ioc_page2->MaxPhysDisks; i++) {
+ mpt_disk = &mpt->raid_disks[i];
+ if ((mpt_disk->flags & MPT_RDF_ACTIVE) != 0 &&
+ mpt_disk->config_page.PhysDiskID == tgt)
+ return (1);
+ }
+ return (0);
+
+}
+
+/* XXX Ignores that there may be multiple busses/IOCs involved. */
+int
+mpt_is_raid_volume(struct mpt_softc *mpt, target_id_t tgt)
{
CONFIG_PAGE_IOC_2_RAID_VOL *ioc_vol;
CONFIG_PAGE_IOC_2_RAID_VOL *ioc_last_vol;
@@ -1305,7 +1343,7 @@ mpt_refresh_raid_vol(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol,
* be updated by our event handler. Interesting changes are displayed
* to the console.
*/
-int
+static int
mpt_refresh_raid_data(struct mpt_softc *mpt)
{
CONFIG_PAGE_IOC_2_RAID_VOL *ioc_vol;
@@ -1565,9 +1603,10 @@ mpt_raid_timer(void *arg)
#endif
}
-void
+static void
mpt_schedule_raid_refresh(struct mpt_softc *mpt)
{
+
callout_reset(&mpt->raid_timer, MPT_RAID_SYNC_REPORT_INTERVAL,
mpt_raid_timer, mpt);
}
@@ -1719,7 +1758,8 @@ mpt_raid_set_vol_mwce(struct mpt_softc *mpt, mpt_raid_mwce_t mwce)
MPT_UNLOCK(mpt);
return (0);
}
-const char *mpt_vol_mwce_strs[] =
+
+static const char *mpt_vol_mwce_strs[] =
{
"On",
"Off",
diff --git a/sys/dev/mpt/mpt_raid.h b/sys/dev/mpt/mpt_raid.h
index bc5aa7dd9fe2c..2047707b155ca 100644
--- a/sys/dev/mpt/mpt_raid.h
+++ b/sys/dev/mpt/mpt_raid.h
@@ -53,29 +53,14 @@ typedef enum {
MPT_RAID_MWCE_NC
} mpt_raid_mwce_t;
-const char *mpt_vol_type(struct mpt_raid_volume *);
-const char *mpt_vol_state(struct mpt_raid_volume *);
-const char *mpt_disk_state(struct mpt_raid_disk *);
-void
-mpt_vol_prt(struct mpt_softc *, struct mpt_raid_volume *, const char *fmt, ...);
-void
-mpt_disk_prt(struct mpt_softc *, struct mpt_raid_disk *, const char *, ...);
-
-int
-mpt_issue_raid_req(struct mpt_softc *, struct mpt_raid_volume *,
- struct mpt_raid_disk *, request_t *, u_int, uint32_t, bus_addr_t,
- bus_size_t, int, int);
-
-cam_status
-mpt_map_physdisk(struct mpt_softc *, union ccb *, target_id_t *);
-int mpt_is_raid_volume(struct mpt_softc *, int);
+cam_status mpt_map_physdisk(struct mpt_softc *, union ccb *, target_id_t *);
+int mpt_is_raid_member(struct mpt_softc *, target_id_t);
+int mpt_is_raid_volume(struct mpt_softc *, target_id_t);
#if 0
cam_status
mpt_raid_quiesce_disk(struct mpt_softc *, struct mpt_raid_disk *, request_t *);
#endif
-int mpt_refresh_raid_data(struct mpt_softc *);
-void mpt_schedule_raid_refresh(struct mpt_softc *);
void mpt_raid_free_mem(struct mpt_softc *);
static __inline void
diff --git a/sys/dev/mpt/mpt_user.c b/sys/dev/mpt/mpt_user.c
index e6a9d1f5e6058..78762c7511848 100644
--- a/sys/dev/mpt/mpt_user.c
+++ b/sys/dev/mpt/mpt_user.c
@@ -94,7 +94,7 @@ static MALLOC_DEFINE(M_MPTUSER, "mpt_user", "Buffers for mpt(4) ioctls");
static uint32_t user_handler_id = MPT_HANDLER_ID_NONE;
-int
+static int
mpt_user_probe(struct mpt_softc *mpt)
{
@@ -102,7 +102,7 @@ mpt_user_probe(struct mpt_softc *mpt)
return (0);
}
-int
+static int
mpt_user_attach(struct mpt_softc *mpt)
{
mpt_handler_t handler;
@@ -131,19 +131,20 @@ mpt_user_attach(struct mpt_softc *mpt)
return (0);
}
-int
+static int
mpt_user_enable(struct mpt_softc *mpt)
{
return (0);
}
-void
+static void
mpt_user_ready(struct mpt_softc *mpt)
{
+
}
-int
+static int
mpt_user_event(struct mpt_softc *mpt, request_t *req,
MSG_EVENT_NOTIFY_REPLY *msg)
{
@@ -152,12 +153,13 @@ mpt_user_event(struct mpt_softc *mpt, request_t *req,
return (0);
}
-void
+static void
mpt_user_reset(struct mpt_softc *mpt, int type)
{
+
}
-void
+static void
mpt_user_detach(struct mpt_softc *mpt)
{
mpt_handler_t handler;
diff --git a/sys/dev/ofw/ofw_console.c b/sys/dev/ofw/ofw_console.c
index fd280c97fc894..62dbe51e87e00 100644
--- a/sys/dev/ofw/ofw_console.c
+++ b/sys/dev/ofw/ofw_console.c
@@ -26,7 +26,6 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include "opt_comconsole.h"
#include "opt_ofw.h"
#include <sys/param.h>
@@ -64,7 +63,7 @@ static int polltime;
static struct callout_handle ofw_timeouthandle
= CALLOUT_HANDLE_INITIALIZER(&ofw_timeouthandle);
-#if defined(KDB) && defined(ALT_BREAK_TO_DEBUGGER)
+#if defined(KDB)
static int alt_break_state;
#endif
@@ -199,24 +198,8 @@ ofw_cngetc(struct consdev *cp)
unsigned char ch;
if (OF_read(stdin, &ch, 1) > 0) {
-#if defined(KDB) && defined(ALT_BREAK_TO_DEBUGGER)
- int kdb_brk;
-
- if ((kdb_brk = kdb_alt_break(ch, &alt_break_state)) != 0) {
- switch (kdb_brk) {
- case KDB_REQ_DEBUGGER:
- kdb_enter(KDB_WHY_BREAK,
- "Break sequence on console");
- break;
- case KDB_REQ_PANIC:
- kdb_panic("Panic sequence on console");
- break;
- case KDB_REQ_REBOOT:
- kdb_reboot();
- break;
-
- }
- }
+#if defined(KDB)
+ kdb_alt_break(ch, &alt_break_state);
#endif
return (ch);
}
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index 7eb84e6e5ee39..9ebb8486913cf 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcivar.h>
#include <dev/pci/pci_private.h>
+#include <dev/usb/controller/xhcireg.h>
#include <dev/usb/controller/ehcireg.h>
#include <dev/usb/controller/ohcireg.h>
#include <dev/usb/controller/uhcireg.h>
@@ -2956,6 +2957,68 @@ ehci_early_takeover(device_t self)
bus_release_resource(self, SYS_RES_MEMORY, rid, res);
}
+/* Perform early XHCI takeover from SMM. */
+static void
+xhci_early_takeover(device_t self)
+{
+ struct resource *res;
+ uint32_t cparams;
+ uint32_t eec;
+ uint8_t eecp;
+ uint8_t bios_sem;
+ uint8_t offs;
+ int rid;
+ int i;
+
+ rid = PCIR_BAR(0);
+ res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+ if (res == NULL)
+ return;
+
+ cparams = bus_read_4(res, XHCI_HCSPARAMS0);
+
+ eec = -1;
+
+ /* Synchronise with the BIOS if it owns the controller. */
+ for (eecp = XHCI_HCS0_XECP(cparams) << 2; eecp != 0 && XHCI_XECP_NEXT(eec);
+ eecp += XHCI_XECP_NEXT(eec) << 2) {
+ eec = bus_read_4(res, eecp);
+
+ if (XHCI_XECP_ID(eec) != XHCI_ID_USB_LEGACY)
+ continue;
+
+ bios_sem = bus_read_1(res, eecp + XHCI_XECP_BIOS_SEM);
+ if (bios_sem == 0)
+ continue;
+
+ if (bootverbose)
+ printf("xhci early: "
+ "SMM active, request owner change\n");
+
+ bus_write_1(res, eecp + XHCI_XECP_OS_SEM, 1);
+
+ /* wait a maximum of 5 second */
+
+ for (i = 0; (i < 5000) && (bios_sem != 0); i++) {
+ DELAY(1000);
+ bios_sem = bus_read_1(res, eecp +
+ XHCI_XECP_BIOS_SEM);
+ }
+
+ if (bios_sem != 0) {
+ if (bootverbose)
+ printf("xhci early: "
+ "SMM does not respond\n");
+ }
+
+ /* Disable interrupts */
+ offs = bus_read_1(res, XHCI_CAPLENGTH);
+ bus_write_4(res, offs + XHCI_USBCMD, 0);
+ bus_read_4(res, offs + XHCI_USBSTS);
+ }
+ bus_release_resource(self, SYS_RES_MEMORY, rid, res);
+}
+
void
pci_add_resources(device_t bus, device_t dev, int force, uint32_t prefetchmask)
{
@@ -3002,7 +3065,9 @@ pci_add_resources(device_t bus, device_t dev, int force, uint32_t prefetchmask)
if (pci_usb_takeover && pci_get_class(dev) == PCIC_SERIALBUS &&
pci_get_subclass(dev) == PCIS_SERIALBUS_USB) {
- if (pci_get_progif(dev) == PCIP_SERIALBUS_USB_EHCI)
+ if (pci_get_progif(dev) == PCIP_SERIALBUS_USB_XHCI)
+ xhci_early_takeover(dev);
+ else if (pci_get_progif(dev) == PCIP_SERIALBUS_USB_EHCI)
ehci_early_takeover(dev);
else if (pci_get_progif(dev) == PCIP_SERIALBUS_USB_OHCI)
ohci_early_takeover(dev);
diff --git a/sys/dev/puc/pucdata.c b/sys/dev/puc/pucdata.c
index 2b38d9b171efe..f675b69b661ae 100644
--- a/sys/dev/puc/pucdata.c
+++ b/sys/dev/puc/pucdata.c
@@ -524,6 +524,12 @@ const struct puc_cfg puc_pci_devices[] = {
PUC_PORT_4S, 0x18, 0, 8,
},
+ { 0x1393, 0x1120, 0xffff, 0,
+ "Moxa Technologies, CP-112UL",
+ DEFAULT_RCLK * 8,
+ PUC_PORT_2S, 0x18, 0, 8,
+ },
+
{ 0x1393, 0x1141, 0xffff, 0,
"Moxa Technologies, Industio CP-114",
DEFAULT_RCLK * 8,
diff --git a/sys/dev/re/if_re.c b/sys/dev/re/if_re.c
index 37dd62fa61778..3c45cc97d9c6e 100644
--- a/sys/dev/re/if_re.c
+++ b/sys/dev/re/if_re.c
@@ -174,6 +174,8 @@ TUNABLE_INT("hw.re.prefer_iomap", &prefer_iomap);
static struct rl_type re_devs[] = {
{ DLINK_VENDORID, DLINK_DEVICEID_528T, 0,
"D-Link DGE-528(T) Gigabit Ethernet Adapter" },
+ { DLINK_VENDORID, DLINK_DEVICEID_530T_REVC, 0,
+ "D-Link DGE-530(T) Gigabit Ethernet Adapter" },
{ RT_VENDORID, RT_DEVICEID_8139, 0,
"RealTek 8139C+ 10/100BaseTX" },
{ RT_VENDORID, RT_DEVICEID_8101E, 0,
diff --git a/sys/dev/sio/sio.c b/sys/dev/sio/sio.c
index f1348c4c35760..7e2054e2070c6 100644
--- a/sys/dev/sio/sio.c
+++ b/sys/dev/sio/sio.c
@@ -33,7 +33,6 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include "opt_comconsole.h"
#include "opt_compat.h"
#include "opt_gdb.h"
#include "opt_kdb.h"
@@ -228,7 +227,7 @@ struct com_s {
struct pps_state pps;
int pps_bit;
-#ifdef ALT_BREAK_TO_DEBUGGER
+#ifdef KDB
int alt_brk_state;
#endif
@@ -1102,8 +1101,7 @@ determined_type: ;
}
if (ret)
device_printf(dev, "could not activate interrupt\n");
-#if defined(KDB) && (defined(BREAK_TO_DEBUGGER) || \
- defined(ALT_BREAK_TO_DEBUGGER))
+#if defined(KDB)
/*
* Enable interrupts for early break-to-debugger support
* on the console.
@@ -1196,8 +1194,7 @@ comclose(tp)
com->poll_output = FALSE;
sio_setreg(com, com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
-#if defined(KDB) && (defined(BREAK_TO_DEBUGGER) || \
- defined(ALT_BREAK_TO_DEBUGGER))
+#if defined(KDB)
/*
* Leave interrupts enabled and don't clear DTR if this is the
* console. This allows us to detect break-to-debugger events
@@ -1483,9 +1480,8 @@ siointr1(com)
u_char modem_status;
u_char *ioptr;
u_char recv_data;
-#if defined(KDB) && defined(ALT_BREAK_TO_DEBUGGER)
- int kdb_brk;
+#ifdef KDB
again:
#endif
@@ -1518,27 +1514,9 @@ again:
else
recv_data = inb(com->data_port);
#ifdef KDB
-#ifdef ALT_BREAK_TO_DEBUGGER
if (com->unit == comconsole &&
- (kdb_brk = kdb_alt_break(recv_data,
- &com->alt_brk_state)) != 0) {
- mtx_unlock_spin(&sio_lock);
- switch (kdb_brk) {
- case KDB_REQ_DEBUGGER:
- kdb_enter(KDB_WHY_BREAK,
- "Break sequence on console");
- break;
- case KDB_REQ_PANIC:
- kdb_panic("panic on console");
- break;
- case KDB_REQ_REBOOT:
- kdb_reboot();
- break;
- }
- mtx_lock_spin(&sio_lock);
+ kdb_alt_break(recv_data, &com->alt_brk_state) != 0)
goto again;
- }
-#endif /* ALT_BREAK_TO_DEBUGGER */
#endif /* KDB */
if (line_status & (LSR_BI | LSR_FE | LSR_PE)) {
/*
@@ -1554,10 +1532,9 @@ again:
* Note: BI together with FE/PE means just BI.
*/
if (line_status & LSR_BI) {
-#if defined(KDB) && defined(BREAK_TO_DEBUGGER)
+#if defined(KDB)
if (com->unit == comconsole) {
- kdb_enter(KDB_WHY_BREAK,
- "Line break on console");
+ kdb_break();
goto cont;
}
#endif
diff --git a/sys/dev/smc/if_smc.c b/sys/dev/smc/if_smc.c
index 22f8bab9e822b..4aa0396fbe88c 100644
--- a/sys/dev/smc/if_smc.c
+++ b/sys/dev/smc/if_smc.c
@@ -538,6 +538,7 @@ smc_task_tx(void *context, int pending)
struct smc_softc *sc;
struct mbuf *m, *m0;
u_int packet, len;
+ int last_len;
uint8_t *data;
(void)pending;
@@ -590,16 +591,18 @@ smc_task_tx(void *context, int pending)
* Push the data out to the device.
*/
data = NULL;
+ last_len = 0;
for (; m != NULL; m = m->m_next) {
data = mtod(m, uint8_t *);
smc_write_multi_2(sc, DATA0, (uint16_t *)data, m->m_len / 2);
+ last_len = m->m_len;
}
/*
* Push out the control byte and and the odd byte if needed.
*/
if ((len & 1) != 0 && data != NULL)
- smc_write_2(sc, DATA0, (CTRL_ODD << 8) | data[m->m_len - 1]);
+ smc_write_2(sc, DATA0, (CTRL_ODD << 8) | data[last_len - 1]);
else
smc_write_2(sc, DATA0, 0);
diff --git a/sys/dev/snp/snp.c b/sys/dev/snp/snp.c
index b05ad2a81b968..1c02660bec1db 100644
--- a/sys/dev/snp/snp.c
+++ b/sys/dev/snp/snp.c
@@ -252,6 +252,9 @@ snp_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags,
SNP_UNLOCK();
return (EBUSY);
}
+ /*
+ * XXXRW / XXXJA: no capability check here.
+ */
error = ttyhook_register(&ss->snp_tty, td->td_proc,
*(int *)data, &snp_hook, ss);
SNP_UNLOCK();
diff --git a/sys/dev/sound/pci/hda/hdac.c b/sys/dev/sound/pci/hda/hdac.c
index bb0f3851437ab..66aa162dc3920 100644
--- a/sys/dev/sound/pci/hda/hdac.c
+++ b/sys/dev/sound/pci/hda/hdac.c
@@ -295,6 +295,7 @@ SND_DECLARE_FILE("$FreeBSD$");
#define LENOVO_VENDORID 0x17aa
#define LENOVO_3KN100_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x2066)
#define LENOVO_3KN200_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x384e)
+#define LENOVO_B450_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x3a0d)
#define LENOVO_TCA55_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0x1015)
#define LENOVO_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(LENOVO, 0xffff)
@@ -2582,6 +2583,13 @@ hdac_widget_pin_getconfig(struct hdac_widget *w)
break;
}
}
+ } else if (id == HDA_CODEC_CX20561 &&
+ sc->pci_subvendor == LENOVO_B450_SUBVENDOR) {
+ switch (nid) {
+ case 22:
+ patch = "as=1 seq=15";
+ break;
+ }
}
if (patch != NULL)
diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c
index 1d52cbe3c7d11..2cfc1701d3502 100644
--- a/sys/dev/sound/pcm/dsp.c
+++ b/sys/dev/sound/pcm/dsp.c
@@ -1062,7 +1062,8 @@ dsp_ioctl(struct cdev *i_dev, u_long cmd, caddr_t arg, int mode,
{
struct pcm_channel *chn, *rdch, *wrch;
struct snddev_info *d;
- int *arg_i, ret, tmp, xcmd;
+ u_long xcmd;
+ int *arg_i, ret, tmp;
d = dsp_get_info(i_dev);
if (!DSP_REGISTERED(d, i_dev))
diff --git a/sys/dev/sound/usb/uaudio.c b/sys/dev/sound/usb/uaudio.c
index 565022c228be8..955b4c5c3e9a9 100644
--- a/sys/dev/sound/usb/uaudio.c
+++ b/sys/dev/sound/usb/uaudio.c
@@ -927,8 +927,8 @@ uaudio_chan_fill_info_sub(struct uaudio_softc *sc, struct usb_device *udev,
continue;
}
if (asf1d->bLength < (sizeof(*asf1d) +
- (asf1d->bSamFreqType == 0) ? 6 :
- (asf1d->bSamFreqType * 3))) {
+ ((asf1d->bSamFreqType == 0) ? 6 :
+ (asf1d->bSamFreqType * 3)))) {
DPRINTFN(11, "'asf1d' descriptor is too short\n");
asf1d = NULL;
continue;
diff --git a/sys/dev/streams/streams.c b/sys/dev/streams/streams.c
index 00f65a3907c27..ad2817f5ca669 100644
--- a/sys/dev/streams/streams.c
+++ b/sys/dev/streams/streams.c
@@ -95,7 +95,9 @@ static struct fileops svr4_netops = {
.fo_poll = soo_poll,
.fo_kqfilter = soo_kqfilter,
.fo_stat = soo_stat,
- .fo_close = svr4_soo_close
+ .fo_close = svr4_soo_close,
+ .fo_chmod = invfo_chmod,
+ .fo_chown = invfo_chown,
};
static struct cdevsw streams_cdevsw = {
diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c
index 69d628e877459..b8f328ee34c3c 100644
--- a/sys/dev/syscons/syscons.c
+++ b/sys/dev/syscons/syscons.c
@@ -3514,7 +3514,7 @@ next_code:
case DBG:
#ifndef SC_DISABLE_KDBKEY
if (enable_kdbkey)
- kdb_enter(KDB_WHY_BREAK, "manual escape to debugger");
+ kdb_break();
#endif
break;
@@ -3562,6 +3562,10 @@ next_code:
/* goto next_code */
} else {
/* regular keys (maybe MKEY is set) */
+#if !defined(SC_DISABLE_KDBKEY) && defined(KDB)
+ if (enable_kdbkey)
+ kdb_alt_break(c, &sc->sc_altbrk);
+#endif
if (!(sc->flags & SC_SCRN_BLANKED))
return c;
}
diff --git a/sys/dev/syscons/syscons.h b/sys/dev/syscons/syscons.h
index a23f88474a30d..79f531bd47a12 100644
--- a/sys/dev/syscons/syscons.h
+++ b/sys/dev/syscons/syscons.h
@@ -266,6 +266,9 @@ typedef struct sc_softc {
u_char cursor_char;
u_char mouse_char;
+#ifdef KDB
+ int sc_altbrk;
+#endif
} sc_softc_t;
/* virtual screen */
diff --git a/sys/dev/tdfx/tdfx_linux.c b/sys/dev/tdfx/tdfx_linux.c
index 2e877f6d0173d..0b769f01a2412 100644
--- a/sys/dev/tdfx/tdfx_linux.c
+++ b/sys/dev/tdfx/tdfx_linux.c
@@ -28,6 +28,7 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/capability.h>
#include <sys/file.h>
#include <sys/kernel.h>
#include <sys/module.h>
@@ -53,7 +54,7 @@ linux_ioctl_tdfx(struct thread *td, struct linux_ioctl_args* args)
struct file *fp;
- if ((error = fget(td, args->fd, &fp)) != 0)
+ if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
return (error);
/* We simply copy the data and send it right to ioctl */
copyin((caddr_t)args->arg, &d_pio, sizeof(d_pio));
diff --git a/sys/dev/uart/uart_core.c b/sys/dev/uart/uart_core.c
index 38d2a8f737734..9260d063b9903 100644
--- a/sys/dev/uart/uart_core.c
+++ b/sys/dev/uart/uart_core.c
@@ -27,10 +27,6 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#ifndef KLD_MODULE
-#include "opt_comconsole.h"
-#endif
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
@@ -118,10 +114,10 @@ uart_intr_break(void *arg)
{
struct uart_softc *sc = arg;
-#if defined(KDB) && defined(BREAK_TO_DEBUGGER)
+#if defined(KDB)
if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) {
- kdb_enter(KDB_WHY_BREAK, "Line break on console");
- return (0);
+ if (kdb_break())
+ return (0);
}
#endif
if (sc->sc_opened)
@@ -170,26 +166,10 @@ uart_intr_rxready(void *arg)
rxp = sc->sc_rxput;
UART_RECEIVE(sc);
-#if defined(KDB) && defined(ALT_BREAK_TO_DEBUGGER)
+#if defined(KDB)
if (sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE) {
while (rxp != sc->sc_rxput) {
- int kdb_brk;
-
- if ((kdb_brk = kdb_alt_break(sc->sc_rxbuf[rxp++],
- &sc->sc_altbrk)) != 0) {
- switch (kdb_brk) {
- case KDB_REQ_DEBUGGER:
- kdb_enter(KDB_WHY_BREAK,
- "Break sequence on console");
- break;
- case KDB_REQ_PANIC:
- kdb_panic("Panic sequence on console");
- break;
- case KDB_REQ_REBOOT:
- kdb_reboot();
- break;
- }
- }
+ kdb_alt_break(sc->sc_rxbuf[rxp++], &sc->sc_altbrk);
if (rxp == sc->sc_rxbufsz)
rxp = 0;
}
diff --git a/sys/dev/usb/input/ums.c b/sys/dev/usb/input/ums.c
index 3c4f36e21ab0e..12d9e89a2eb20 100644
--- a/sys/dev/usb/input/ums.c
+++ b/sys/dev/usb/input/ums.c
@@ -367,7 +367,9 @@ ums_probe(device_t dev)
{
struct usb_attach_arg *uaa = device_get_ivars(dev);
void *d_ptr;
- int error;
+ struct hid_data *hd;
+ struct hid_item hi;
+ int error, mdepth, found;
uint16_t d_len;
DPRINTFN(11, "\n");
@@ -388,14 +390,44 @@ ums_probe(device_t dev)
if (error)
return (ENXIO);
- if (hid_is_collection(d_ptr, d_len,
- HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE)))
- error = BUS_PROBE_DEFAULT;
- else
- error = ENXIO;
-
+ hd = hid_start_parse(d_ptr, d_len, 1 << hid_input);
+ if (hd == NULL)
+ return (0);
+ mdepth = 0;
+ found = 0;
+ while (hid_get_item(hd, &hi)) {
+ switch (hi.kind) {
+ case hid_collection:
+ if (mdepth != 0)
+ mdepth++;
+ else if (hi.collection == 1 &&
+ hi.usage ==
+ HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))
+ mdepth++;
+ break;
+ case hid_endcollection:
+ if (mdepth != 0)
+ mdepth--;
+ break;
+ case hid_input:
+ if (mdepth == 0)
+ break;
+ if (hi.usage ==
+ HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X) &&
+ (hi.flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS)
+ found++;
+ if (hi.usage ==
+ HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y) &&
+ (hi.flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS)
+ found++;
+ break;
+ default:
+ break;
+ }
+ }
+ hid_end_parse(hd);
free(d_ptr, M_TEMP);
- return (error);
+ return (found ? BUS_PROBE_DEFAULT : ENXIO);
}
static void
diff --git a/sys/dev/usb/net/uhso.c b/sys/dev/usb/net/uhso.c
index cbb0b087b1430..6b42de80a8d3b 100644
--- a/sys/dev/usb/net/uhso.c
+++ b/sys/dev/usb/net/uhso.c
@@ -249,6 +249,8 @@ static struct unrhdr *uhso_ifnet_unit = NULL;
static const STRUCT_USB_HOST_ID uhso_devs[] = {
#define UHSO_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) }
+ /* Option GlobeTrotter MAX 7.2 with upgraded firmware */
+ UHSO_DEV(OPTION, GTMAX72, UHSO_STATIC_IFACE),
/* Option GlobeSurfer iCON 7.2 */
UHSO_DEV(OPTION, GSICON72, UHSO_STATIC_IFACE),
/* Option iCON 225 */
diff --git a/sys/dev/usb/quirk/usb_quirk.c b/sys/dev/usb/quirk/usb_quirk.c
index e54b9084c2e86..d3093f7ec1fdb 100644
--- a/sys/dev/usb/quirk/usb_quirk.c
+++ b/sys/dev/usb/quirk/usb_quirk.c
@@ -148,12 +148,10 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
UQ_MSC_FORCE_PROTO_SCSI),
USB_QUIRK(AIPTEK, POCKETCAM3M, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI),
- USB_QUIRK(AIPTEK2, SUNPLUS_TECH, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(ALCOR, SDCR_6335, 0x0000, 0xffff, UQ_MSC_NO_TEST_UNIT_READY,
UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(ALCOR, SDCR_6362, 0x0000, 0xffff, UQ_MSC_NO_TEST_UNIT_READY,
UQ_MSC_NO_SYNC_CACHE),
- USB_QUIRK(ALCOR, AU6390, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(ALCOR, UMCR_9361, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_GETMAXLUN),
USB_QUIRK(ALCOR, TRANSCEND, 0x0000, 0xffff, UQ_MSC_NO_GETMAXLUN,
@@ -173,14 +171,12 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(CENTURY, EX35QUAT, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_FORCE_SHORT_INQ,
UQ_MSC_NO_START_STOP, UQ_MSC_IGNORE_RESIDUE),
- USB_QUIRK(CENTURY, EX35SW4_SB4, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(CYPRESS, XX6830XX, 0x0000, 0xffff, UQ_MSC_NO_GETMAXLUN,
UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(DESKNOTE, UCR_61S2B, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI),
USB_QUIRK(DMI, CFSM_RW, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI,
UQ_MSC_NO_GETMAXLUN),
- USB_QUIRK(DMI, DISK, 0x000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(EPSON, STYLUS_875DC, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
USB_QUIRK(EPSON, STYLUS_895, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
@@ -188,7 +184,6 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(FEIYA, 5IN1, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI),
USB_QUIRK(FREECOM, DVD, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_SCSI),
- USB_QUIRK(FREECOM, HDD, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(FUJIPHOTO, MASS0100, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI_I,
UQ_MSC_FORCE_PROTO_ATAPI, UQ_MSC_NO_RS_CLEAR_UA, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(GENESYS, GL641USB2IDE, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
@@ -232,7 +227,6 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(IOMEGA, ZIP100, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI,
UQ_MSC_NO_TEST_UNIT_READY), /* XXX ZIP drives can also use ATAPI */
- USB_QUIRK(JMICRON, JM20336, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(JMICRON, JM20337, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI,
UQ_MSC_NO_SYNC_CACHE),
@@ -279,8 +273,6 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
UQ_MSC_FORCE_PROTO_ATAPI),
USB_QUIRK(MYSON, HEDEN, 0x0000, 0xffff, UQ_MSC_IGNORE_RESIDUE,
UQ_MSC_NO_SYNC_CACHE),
- USB_QUIRK(MYSON, HEDEN_8813, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
- USB_QUIRK(MYSON, STARREADER, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(NEODIO, ND3260, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_FORCE_SHORT_INQ),
USB_QUIRK(NETAC, CF_CARD, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
@@ -317,7 +309,6 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK(PANASONIC, KXLCB35AN, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI),
USB_QUIRK(PANASONIC, LS120CAM, 0x0000, 0xffff, UQ_MSC_FORCE_PROTO_UFI),
- USB_QUIRK(PHILIPS, SPE3030CC, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(PLEXTOR, 40_12_40U, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_TEST_UNIT_READY),
USB_QUIRK(PNY, ATTACHE2, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
@@ -328,7 +319,6 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
USB_QUIRK_VP(USB_VENDOR_SAMSUNG_TECHWIN,
USB_PRODUCT_SAMSUNG_TECHWIN_DIGIMAX_410, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY),
- USB_QUIRK(SAMSUNG, YP_U4, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
USB_QUIRK(SANDISK, SDDR05A, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_CBI,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_READ_CAP_OFFBY1,
UQ_MSC_NO_GETMAXLUN),
@@ -448,12 +438,6 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = {
UQ_MSC_FORCE_PROTO_ATAPI),
USB_QUIRK(MEIZU, M6_SL, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_INQUIRY, UQ_MSC_NO_SYNC_CACHE),
- USB_QUIRK(ACTIONS, MP4, 0x0000, 0xffff, UQ_MSC_FORCE_WIRE_BBB,
- UQ_MSC_FORCE_PROTO_SCSI, UQ_MSC_NO_SYNC_CACHE),
- USB_QUIRK(ASUS, GMSC, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
- USB_QUIRK(CHIPSBANK, USBMEMSTICK, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
- USB_QUIRK(CHIPSBANK, USBMEMSTICK1, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
- USB_QUIRK(NEWLINK, USB2IDEBRIDGE, 0x0000, 0xffff, UQ_MSC_NO_SYNC_CACHE),
/* Non-standard USB MIDI devices */
USB_QUIRK(ROLAND, UM1, 0x0000, 0xffff, UQ_AU_VENDOR_CLASS),
@@ -567,9 +551,9 @@ usb_test_quirk_by_info(const struct usbd_lookup_info *info, uint16_t quirk)
uint16_t x;
uint16_t y;
- if (quirk == UQ_NONE) {
- return (0);
- }
+ if (quirk == UQ_NONE)
+ goto done;
+
mtx_lock(&usb_quirk_mtx);
for (x = 0; x != USB_DEV_QUIRKS_MAX; x++) {
@@ -603,7 +587,8 @@ usb_test_quirk_by_info(const struct usbd_lookup_info *info, uint16_t quirk)
break;
}
mtx_unlock(&usb_quirk_mtx);
- return (0);
+done:
+ return (0); /* no quirk match */
}
static struct usb_quirk_entry *
diff --git a/sys/dev/usb/serial/u3g.c b/sys/dev/usb/serial/u3g.c
index 31e8e112e1903..46a153f4cb8b0 100644
--- a/sys/dev/usb/serial/u3g.c
+++ b/sys/dev/usb/serial/u3g.c
@@ -280,6 +280,8 @@ static const STRUCT_USB_HOST_ID u3g_devs[] = {
U3G_DEV(HUAWEI, E143D, U3GINIT_HUAWEI),
U3G_DEV(HUAWEI, E143E, U3GINIT_HUAWEI),
U3G_DEV(HUAWEI, E143F, U3GINIT_HUAWEI),
+ U3G_DEV(HUAWEI, E173, 0),
+ U3G_DEV(HUAWEI, E173_INIT, U3GINIT_HUAWEISCSI),
U3G_DEV(HUAWEI, E180V, U3GINIT_HUAWEI),
U3G_DEV(HUAWEI, E220, U3GINIT_HUAWEI),
U3G_DEV(HUAWEI, E220BIS, U3GINIT_HUAWEI),
@@ -293,6 +295,7 @@ static const STRUCT_USB_HOST_ID u3g_devs[] = {
U3G_DEV(LONGCHEER, WM66, U3GINIT_HUAWEI),
U3G_DEV(LONGCHEER, DISK, U3GINIT_TCT),
U3G_DEV(LONGCHEER, W14, 0),
+ U3G_DEV(LONGCHEER, XSSTICK, 0),
U3G_DEV(MERLIN, V620, 0),
U3G_DEV(NEOTEL, PRIME, 0),
U3G_DEV(NOVATEL, E725, 0),
diff --git a/sys/dev/usb/storage/umass.c b/sys/dev/usb/storage/umass.c
index 9292c842bcb77..41e98d50c8561 100644
--- a/sys/dev/usb/storage/umass.c
+++ b/sys/dev/usb/storage/umass.c
@@ -1025,12 +1025,6 @@ umass_attach(device_t dev)
sc->cam_scsi_sense.opcode = REQUEST_SENSE;
sc->cam_scsi_test_unit_ready.opcode = TEST_UNIT_READY;
- /*
- * some devices need a delay after that the configuration value is
- * set to function properly:
- */
- usb_pause_mtx(NULL, hz);
-
/* register the SIM */
err = umass_cam_attach_sim(sc);
if (err) {
diff --git a/sys/dev/usb/usb_dev.c b/sys/dev/usb/usb_dev.c
index dbba08eba496e..990bda22e4c69 100644
--- a/sys/dev/usb/usb_dev.c
+++ b/sys/dev/usb/usb_dev.c
@@ -911,10 +911,23 @@ usb_close(void *arg)
DPRINTFN(2, "cpd=%p\n", cpd);
- err = usb_ref_device(cpd, &refs, 1);
- if (err) {
- free(cpd, M_USBDEV);
- return;
+ err = usb_ref_device(cpd, &refs, 0);
+ if (err)
+ goto done;
+
+ /*
+ * If this function is not called directly from the root HUB
+ * thread, there is usually a need to lock the enumeration
+ * lock. Check this.
+ */
+ if (!usbd_enum_is_locked(cpd->udev)) {
+
+ DPRINTFN(2, "Locking enumeration\n");
+
+ /* reference device */
+ err = usb_usb_ref_device(cpd, &refs);
+ if (err)
+ goto done;
}
if (cpd->fflags & FREAD) {
usb_fifo_close(refs.rxfifo, cpd->fflags);
@@ -922,10 +935,9 @@ usb_close(void *arg)
if (cpd->fflags & FWRITE) {
usb_fifo_close(refs.txfifo, cpd->fflags);
}
-
usb_unref_device(cpd, &refs);
+done:
free(cpd, M_USBDEV);
- return;
}
static void
@@ -1648,7 +1660,6 @@ usb_fifo_attach(struct usb_device *udev, void *priv_sc,
struct usb_fifo *f_rx;
char devname[32];
uint8_t n;
- struct usb_fs_privdata* pd;
f_sc->fp[USB_FIFO_TX] = NULL;
f_sc->fp[USB_FIFO_RX] = NULL;
@@ -1746,22 +1757,10 @@ usb_fifo_attach(struct usb_device *udev, void *priv_sc,
usb_alloc_symlink(devname);
}
- /*
- * Initialize device private data - this is used to find the
- * actual USB device itself.
- */
- pd = malloc(sizeof(struct usb_fs_privdata), M_USBDEV, M_WAITOK | M_ZERO);
- pd->bus_index = device_get_unit(udev->bus->bdev);
- pd->dev_index = udev->device_index;
- pd->ep_addr = -1; /* not an endpoint */
- pd->fifo_index = f_tx->fifo_index & f_rx->fifo_index;
- pd->mode = FREAD|FWRITE;
-
- /* Now, create the device itself */
- f_sc->dev = make_dev(&usb_devsw, 0, uid, gid, mode,
- "%s", devname);
- /* XXX setting si_drv1 and creating the device is not atomic! */
- f_sc->dev->si_drv1 = pd;
+ /* Create the device */
+ f_sc->dev = usb_make_dev(udev, devname, -1,
+ f_tx->fifo_index & f_rx->fifo_index,
+ FREAD|FWRITE, uid, gid, mode);
}
DPRINTFN(2, "attached %p/%p\n", f_tx, f_rx);
@@ -1814,12 +1813,6 @@ usb_fifo_free_buffer(struct usb_fifo *f)
bzero(&f->used_q, sizeof(f->used_q));
}
-static void
-usb_fifo_cleanup(void* ptr)
-{
- free(ptr, M_USBDEV);
-}
-
void
usb_fifo_detach(struct usb_fifo_sc *f_sc)
{
@@ -1832,11 +1825,9 @@ usb_fifo_detach(struct usb_fifo_sc *f_sc)
f_sc->fp[USB_FIFO_TX] = NULL;
f_sc->fp[USB_FIFO_RX] = NULL;
- if (f_sc->dev != NULL) {
- destroy_dev_sched_cb(f_sc->dev,
- usb_fifo_cleanup, f_sc->dev->si_drv1);
- f_sc->dev = NULL;
- }
+ usb_destroy_dev(f_sc->dev);
+
+ f_sc->dev = NULL;
DPRINTFN(2, "detached %p\n", f_sc);
}
diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c
index 932c0222272b2..7e0de330ed7c3 100644
--- a/sys/dev/usb/usb_device.c
+++ b/sys/dev/usb/usb_device.c
@@ -102,10 +102,8 @@ static void usb_notify_addq(const char *type, struct usb_device *);
#endif
#if USB_HAVE_UGEN
static void usb_fifo_free_wrap(struct usb_device *, uint8_t, uint8_t);
-static struct cdev *usb_make_dev(struct usb_device *, int, int);
static void usb_cdev_create(struct usb_device *);
static void usb_cdev_free(struct usb_device *);
-static void usb_cdev_cleanup(void *);
#endif
/* This variable is global to allow easy access to it: */
@@ -1241,7 +1239,7 @@ static void
usb_init_attach_arg(struct usb_device *udev,
struct usb_attach_arg *uaa)
{
- bzero(uaa, sizeof(*uaa));
+ memset(uaa, 0, sizeof(*uaa));
uaa->device = udev;
uaa->usb_mode = udev->flags.usb_mode;
@@ -1626,10 +1624,12 @@ usb_alloc_device(device_t parent_dev, struct usb_bus *bus,
LIST_INIT(&udev->pd_list);
/* Create the control endpoint device */
- udev->ctrl_dev = usb_make_dev(udev, 0, FREAD|FWRITE);
+ udev->ctrl_dev = usb_make_dev(udev, NULL, 0, 0,
+ FREAD|FWRITE, UID_ROOT, GID_OPERATOR, 0600);
/* Create a link from /dev/ugenX.X to the default endpoint */
- make_dev_alias(udev->ctrl_dev, "%s", udev->ugen_name);
+ if (udev->ctrl_dev != NULL)
+ make_dev_alias(udev->ctrl_dev->cdev, "%s", udev->ugen_name);
#endif
/* Initialise device */
if (bus->methods->device_init != NULL) {
@@ -1850,6 +1850,20 @@ repeat_set_config:
}
}
}
+ if (set_config_failed == 0 && config_index == 0 &&
+ usb_test_quirk(&uaa, UQ_MSC_NO_SYNC_CACHE) == 0) {
+
+ /*
+ * Try to figure out if there are any MSC quirks we
+ * should apply automatically:
+ */
+ err = usb_msc_auto_quirk(udev, 0);
+
+ if (err != 0) {
+ set_config_failed = 1;
+ goto repeat_set_config;
+ }
+ }
config_done:
DPRINTF("new dev (addr %d), udev=%p, parent_hub=%p\n",
@@ -1884,11 +1898,12 @@ done:
}
#if USB_HAVE_UGEN
-static struct cdev *
-usb_make_dev(struct usb_device *udev, int ep, int mode)
+struct usb_fs_privdata *
+usb_make_dev(struct usb_device *udev, const char *devname, int ep,
+ int fi, int rwmode, uid_t uid, gid_t gid, int mode)
{
struct usb_fs_privdata* pd;
- char devname[20];
+ char buffer[32];
/* Store information to locate ourselves again later */
pd = malloc(sizeof(struct usb_fs_privdata), M_USBDEV,
@@ -1896,16 +1911,39 @@ usb_make_dev(struct usb_device *udev, int ep, int mode)
pd->bus_index = device_get_unit(udev->bus->bdev);
pd->dev_index = udev->device_index;
pd->ep_addr = ep;
- pd->mode = mode;
+ pd->fifo_index = fi;
+ pd->mode = rwmode;
/* Now, create the device itself */
- snprintf(devname, sizeof(devname), "%u.%u.%u",
- pd->bus_index, pd->dev_index, pd->ep_addr);
- pd->cdev = make_dev(&usb_devsw, 0, UID_ROOT,
- GID_OPERATOR, 0600, USB_DEVICE_DIR "/%s", devname);
+ if (devname == NULL) {
+ devname = buffer;
+ snprintf(buffer, sizeof(buffer), USB_DEVICE_DIR "/%u.%u.%u",
+ pd->bus_index, pd->dev_index, pd->ep_addr);
+ }
+
+ pd->cdev = make_dev(&usb_devsw, 0, uid, gid, mode, "%s", devname);
+
+ if (pd->cdev == NULL) {
+ DPRINTFN(0, "Failed to create device %s\n", devname);
+ free(pd, M_USBDEV);
+ return (NULL);
+ }
+
+ /* XXX setting si_drv1 and creating the device is not atomic! */
pd->cdev->si_drv1 = pd;
- return (pd->cdev);
+ return (pd);
+}
+
+void
+usb_destroy_dev(struct usb_fs_privdata *pd)
+{
+ if (pd == NULL)
+ return;
+
+ destroy_dev(pd->cdev);
+
+ free(pd, M_USBDEV);
}
static void
@@ -1915,7 +1953,6 @@ usb_cdev_create(struct usb_device *udev)
struct usb_endpoint_descriptor *ed;
struct usb_descriptor *desc;
struct usb_fs_privdata* pd;
- struct cdev *dev;
int inmode, outmode, inmask, outmask, mode;
uint8_t ep;
@@ -1957,14 +1994,16 @@ usb_cdev_create(struct usb_device *udev)
/* Create all available endpoints except EP0 */
for (ep = 1; ep < 16; ep++) {
- mode = inmask & (1 << ep) ? inmode : 0;
- mode |= outmask & (1 << ep) ? outmode : 0;
+ mode = (inmask & (1 << ep)) ? inmode : 0;
+ mode |= (outmask & (1 << ep)) ? outmode : 0;
if (mode == 0)
continue; /* no IN or OUT endpoint */
- dev = usb_make_dev(udev, ep, mode);
- pd = dev->si_drv1;
- LIST_INSERT_HEAD(&udev->pd_list, pd, pd_next);
+ pd = usb_make_dev(udev, NULL, ep, 0,
+ mode, UID_ROOT, GID_OPERATOR, 0600);
+
+ if (pd != NULL)
+ LIST_INSERT_HEAD(&udev->pd_list, pd, pd_next);
}
}
@@ -1972,25 +2011,16 @@ static void
usb_cdev_free(struct usb_device *udev)
{
struct usb_fs_privdata* pd;
- struct cdev* pcdev;
DPRINTFN(2, "Freeing device nodes\n");
while ((pd = LIST_FIRST(&udev->pd_list)) != NULL) {
KASSERT(pd->cdev->si_drv1 == pd, ("privdata corrupt"));
- pcdev = pd->cdev;
- pd->cdev = NULL;
LIST_REMOVE(pd, pd_next);
- if (pcdev != NULL)
- destroy_dev_sched_cb(pcdev, usb_cdev_cleanup, pd);
- }
-}
-static void
-usb_cdev_cleanup(void* arg)
-{
- free(arg, M_USBDEV);
+ usb_destroy_dev(pd);
+ }
}
#endif
@@ -2046,8 +2076,7 @@ usb_free_device(struct usb_device *udev, uint8_t flag)
}
mtx_unlock(&usb_ref_lock);
- destroy_dev_sched_cb(udev->ctrl_dev, usb_cdev_cleanup,
- udev->ctrl_dev->si_drv1);
+ usb_destroy_dev(udev->ctrl_dev);
#endif
if (udev->flags.usb_mode == USB_MODE_DEVICE) {
@@ -2355,8 +2384,22 @@ uint8_t
usb_test_quirk(const struct usb_attach_arg *uaa, uint16_t quirk)
{
uint8_t found;
+ uint8_t x;
+
+ if (quirk == UQ_NONE)
+ return (0);
+
+ /* search the automatic per device quirks first */
+
+ for (x = 0; x != USB_MAX_AUTO_QUIRK; x++) {
+ if (uaa->device->autoQuirk[x] == quirk)
+ return (1);
+ }
+
+ /* search global quirk table, if any */
found = (usb_test_quirk_p) (&uaa->info, quirk);
+
return (found);
}
@@ -2683,3 +2726,17 @@ usbd_set_pnpinfo(struct usb_device *udev, uint8_t iface_index, const char *pnpin
return (0); /* success */
}
+usb_error_t
+usbd_add_dynamic_quirk(struct usb_device *udev, uint16_t quirk)
+{
+ uint8_t x;
+
+ for (x = 0; x != USB_MAX_AUTO_QUIRK; x++) {
+ if (udev->autoQuirk[x] == 0 ||
+ udev->autoQuirk[x] == quirk) {
+ udev->autoQuirk[x] = quirk;
+ return (0); /* success */
+ }
+ }
+ return (USB_ERR_NOMEM);
+}
diff --git a/sys/dev/usb/usb_device.h b/sys/dev/usb/usb_device.h
index bf412214dd4f6..bde20b0790e73 100644
--- a/sys/dev/usb/usb_device.h
+++ b/sys/dev/usb/usb_device.h
@@ -29,6 +29,7 @@
struct usb_symlink; /* UGEN */
struct usb_device; /* linux compat */
+struct usb_fs_privdata;
#define USB_CTRL_XFER_MAX 2
@@ -135,7 +136,7 @@ struct usb_device {
#if USB_HAVE_UGEN
struct usb_fifo *fifo[USB_FIFO_MAX];
struct usb_symlink *ugen_symlink; /* our generic symlink */
- struct cdev *ctrl_dev; /* Control Endpoint 0 device node */
+ struct usb_fs_privdata *ctrl_dev; /* Control Endpoint 0 device node */
LIST_HEAD(,usb_fs_privdata) pd_list;
char ugen_name[20]; /* name of ugenX.X device */
#endif
@@ -148,6 +149,7 @@ struct usb_device {
uint16_t power; /* mA the device uses */
uint16_t langid; /* language for strings */
+ uint16_t autoQuirk[USB_MAX_AUTO_QUIRK]; /* dynamic quirks */
uint8_t address; /* device addess */
uint8_t device_index; /* device index in "bus->devices" */
@@ -202,6 +204,11 @@ struct usb_device *usb_alloc_device(device_t parent_dev, struct usb_bus *bus,
struct usb_device *parent_hub, uint8_t depth,
uint8_t port_index, uint8_t port_no,
enum usb_dev_speed speed, enum usb_hc_mode mode);
+#if USB_HAVE_UGEN
+struct usb_fs_privdata *usb_make_dev(struct usb_device *, const char *,
+ int, int, int, uid_t, gid_t, int);
+void usb_destroy_dev(struct usb_fs_privdata *);
+#endif
usb_error_t usb_probe_and_attach(struct usb_device *udev,
uint8_t iface_index);
void usb_detach_device(struct usb_device *, uint8_t, uint8_t);
diff --git a/sys/dev/usb/usb_freebsd.h b/sys/dev/usb/usb_freebsd.h
index ae69cdb8926e3..349e13e8477d7 100644
--- a/sys/dev/usb/usb_freebsd.h
+++ b/sys/dev/usb/usb_freebsd.h
@@ -68,6 +68,8 @@
#define USB_EP0_BUFSIZE 1024 /* bytes */
#define USB_CS_RESET_LIMIT 20 /* failures = 20 * 50 ms = 1sec */
+#define USB_MAX_AUTO_QUIRK 4 /* maximum number of dynamic quirks */
+
typedef uint32_t usb_timeout_t; /* milliseconds */
typedef uint32_t usb_frlength_t; /* bytes */
typedef uint32_t usb_frcount_t; /* units */
diff --git a/sys/dev/usb/usb_msctest.c b/sys/dev/usb/usb_msctest.c
index 0b6024b3d76ce..0355653fbd039 100644
--- a/sys/dev/usb/usb_msctest.c
+++ b/sys/dev/usb/usb_msctest.c
@@ -1,6 +1,6 @@
/* $FreeBSD$ */
/*-
- * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
+ * Copyright (c) 2008,2011 Hans Petter Selasky. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -83,7 +83,10 @@ enum {
DIR_NONE,
};
+#define SCSI_MAX_LEN 0x100
#define SCSI_INQ_LEN 0x24
+#define SCSI_SENSE_LEN 0xFF
+
static uint8_t scsi_test_unit_ready[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static uint8_t scsi_inquiry[] = { 0x12, 0x00, 0x00, 0x00, SCSI_INQ_LEN, 0x00 };
static uint8_t scsi_rezero_init[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 };
@@ -96,6 +99,10 @@ static uint8_t scsi_huawei_eject[] = { 0x11, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00 };
static uint8_t scsi_tct_eject[] = { 0x06, 0xf5, 0x04, 0x02, 0x52, 0x70 };
+static uint8_t scsi_sync_cache[] = { 0x35, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 };
+static uint8_t scsi_request_sense[] = { 0x03, 0x00, 0x00, 0x00, 0x12, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
#define BULK_SIZE 64 /* dummy */
#define ERR_CSW_FAILED -1
@@ -149,7 +156,7 @@ struct bbb_transfer {
uint8_t status_try;
int error;
- uint8_t buffer[256];
+ uint8_t buffer[SCSI_MAX_LEN] __aligned(4);
};
static usb_callback_t bbb_command_callback;
@@ -163,7 +170,7 @@ static void bbb_done(struct bbb_transfer *, int);
static void bbb_transfer_start(struct bbb_transfer *, uint8_t);
static void bbb_data_clear_stall_callback(struct usb_xfer *, uint8_t,
uint8_t);
-static uint8_t bbb_command_start(struct bbb_transfer *, uint8_t, uint8_t,
+static int bbb_command_start(struct bbb_transfer *, uint8_t, uint8_t,
void *, size_t, void *, size_t, usb_timeout_t);
static struct bbb_transfer *bbb_attach(struct usb_device *, uint8_t);
static void bbb_detach(struct bbb_transfer *);
@@ -175,6 +182,7 @@ static const struct usb_config bbb_config[ST_MAX] = {
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
.bufsize = sizeof(struct bbb_cbw),
+ .flags = {.ext_buffer = 1,},
.callback = &bbb_command_callback,
.timeout = 4 * USB_MS_HZ, /* 4 seconds */
},
@@ -184,7 +192,7 @@ static const struct usb_config bbb_config[ST_MAX] = {
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
.bufsize = BULK_SIZE,
- .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,},
+ .flags = {.ext_buffer = 1,.proxy_buffer = 1,.short_xfer_ok = 1,},
.callback = &bbb_data_read_callback,
.timeout = 4 * USB_MS_HZ, /* 4 seconds */
},
@@ -203,7 +211,7 @@ static const struct usb_config bbb_config[ST_MAX] = {
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
.bufsize = BULK_SIZE,
- .flags = {.proxy_buffer = 1,},
+ .flags = {.ext_buffer = 1,.proxy_buffer = 1,},
.callback = &bbb_data_write_callback,
.timeout = 4 * USB_MS_HZ, /* 4 seconds */
},
@@ -222,7 +230,7 @@ static const struct usb_config bbb_config[ST_MAX] = {
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
.bufsize = sizeof(struct bbb_csw),
- .flags = {.short_xfer_ok = 1,},
+ .flags = {.ext_buffer = 1,.short_xfer_ok = 1,},
.callback = &bbb_status_callback,
.timeout = 1 * USB_MS_HZ, /* 1 second */
},
@@ -454,7 +462,7 @@ bbb_status_callback(struct usb_xfer *xfer, usb_error_t error)
* 0: Success
* Else: Failure
*------------------------------------------------------------------------*/
-static uint8_t
+static int
bbb_command_start(struct bbb_transfer *sc, uint8_t dir, uint8_t lun,
void *data_ptr, size_t data_len, void *cmd_ptr, size_t cmd_len,
usb_timeout_t data_timeout)
@@ -566,9 +574,10 @@ int
usb_iface_is_cdrom(struct usb_device *udev, uint8_t iface_index)
{
struct bbb_transfer *sc;
- usb_error_t err;
- uint8_t timeout, is_cdrom;
+ uint8_t timeout;
+ uint8_t is_cdrom;
uint8_t sid_type;
+ int err;
sc = bbb_attach(udev, iface_index);
if (sc == NULL)
@@ -595,6 +604,114 @@ usb_iface_is_cdrom(struct usb_device *udev, uint8_t iface_index)
}
usb_error_t
+usb_msc_auto_quirk(struct usb_device *udev, uint8_t iface_index)
+{
+ struct bbb_transfer *sc;
+ uint8_t timeout;
+ uint8_t is_no_direct;
+ uint8_t sid_type;
+ int err;
+
+ sc = bbb_attach(udev, iface_index);
+ if (sc == NULL)
+ return (0);
+
+ /*
+ * Some devices need a delay after that the configuration
+ * value is set to function properly:
+ */
+ usb_pause_mtx(NULL, hz);
+
+ is_no_direct = 1;
+ for (timeout = 4; timeout; timeout--) {
+ err = bbb_command_start(sc, DIR_IN, 0, sc->buffer,
+ SCSI_INQ_LEN, &scsi_inquiry, sizeof(scsi_inquiry),
+ USB_MS_HZ);
+
+ if (err == 0 && sc->actlen > 0) {
+ sid_type = sc->buffer[0] & 0x1F;
+ if (sid_type == 0x00)
+ is_no_direct = 0;
+ break;
+ } else if (err != ERR_CSW_FAILED)
+ break; /* non retryable error */
+ usb_pause_mtx(NULL, hz);
+ }
+
+ if (is_no_direct) {
+ DPRINTF("Device is not direct access.\n");
+ goto done;
+ }
+
+ err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
+ &scsi_test_unit_ready, sizeof(scsi_test_unit_ready),
+ USB_MS_HZ);
+
+ if (err != 0) {
+
+ if (err != ERR_CSW_FAILED)
+ goto error;
+ }
+
+ err = bbb_command_start(sc, DIR_IN, 0, NULL, 0,
+ &scsi_sync_cache, sizeof(scsi_sync_cache),
+ USB_MS_HZ);
+
+ if (err != 0) {
+
+ if (err != ERR_CSW_FAILED)
+ goto error;
+
+ DPRINTF("Device doesn't handle synchronize cache\n");
+
+ usbd_add_dynamic_quirk(udev, UQ_MSC_NO_SYNC_CACHE);
+ }
+
+ /* clear sense status of any failed commands on the device */
+
+ err = bbb_command_start(sc, DIR_IN, 0, sc->buffer,
+ SCSI_INQ_LEN, &scsi_inquiry, sizeof(scsi_inquiry),
+ USB_MS_HZ);
+
+ DPRINTF("Inquiry = %d\n", err);
+
+ if (err != 0) {
+
+ if (err != ERR_CSW_FAILED)
+ goto error;
+ }
+
+ err = bbb_command_start(sc, DIR_IN, 0, sc->buffer,
+ SCSI_SENSE_LEN, &scsi_request_sense,
+ sizeof(scsi_request_sense), USB_MS_HZ);
+
+ DPRINTF("Request sense = %d\n", err);
+
+ if (err != 0) {
+
+ if (err != ERR_CSW_FAILED)
+ goto error;
+ }
+
+done:
+ bbb_detach(sc);
+ return (0);
+
+error:
+ bbb_detach(sc);
+
+ DPRINTF("Device did not respond, enabling all quirks\n");
+
+ usbd_add_dynamic_quirk(udev, UQ_MSC_NO_SYNC_CACHE);
+ usbd_add_dynamic_quirk(udev, UQ_MSC_NO_TEST_UNIT_READY);
+
+ /* Need to re-enumerate the device */
+ usbd_req_re_enumerate(udev, NULL);
+
+ return (USB_ERR_STALLED);
+}
+
+usb_error_t
usb_msc_eject(struct usb_device *udev, uint8_t iface_index, int method)
{
struct bbb_transfer *sc;
diff --git a/sys/dev/usb/usb_msctest.h b/sys/dev/usb/usb_msctest.h
index 807d5f5d5d5b9..e4a717feb31e0 100644
--- a/sys/dev/usb/usb_msctest.h
+++ b/sys/dev/usb/usb_msctest.h
@@ -40,5 +40,7 @@ int usb_iface_is_cdrom(struct usb_device *udev,
uint8_t iface_index);
usb_error_t usb_msc_eject(struct usb_device *udev,
uint8_t iface_index, int method);
+usb_error_t usb_msc_auto_quirk(struct usb_device *udev,
+ uint8_t iface_index);
#endif /* _USB_MSCTEST_H_ */
diff --git a/sys/dev/usb/usb_request.c b/sys/dev/usb/usb_request.c
index bb5e0daa8591d..347f9464a6f47 100644
--- a/sys/dev/usb/usb_request.c
+++ b/sys/dev/usb/usb_request.c
@@ -67,6 +67,11 @@
#include <dev/usb/usb_bus.h>
#include <sys/ctype.h>
+static int usb_no_cs_fail;
+
+SYSCTL_INT(_hw_usb, OID_AUTO, no_cs_fail, CTLFLAG_RW,
+ &usb_no_cs_fail, 0, "USB clear stall failures are ignored, if set");
+
#ifdef USB_DEBUG
static int usb_pr_poll_delay = USB_PORT_RESET_DELAY;
static int usb_pr_recovery_delay = USB_PORT_RESET_RECOVERY;
@@ -238,7 +243,7 @@ usb_do_clear_stall_callback(struct usb_xfer *xfer, usb_error_t error)
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
-
+tr_transferred:
/* reset error counter */
udev->clear_stall_errors = 0;
@@ -297,6 +302,13 @@ tr_setup:
break;
DPRINTF("Clear stall failed.\n");
+
+ /*
+ * Some VMs like VirtualBox always return failure on
+ * clear-stall which we sometimes should just ignore.
+ */
+ if (usb_no_cs_fail)
+ goto tr_transferred;
if (udev->clear_stall_errors == USB_CS_RESET_LIMIT)
goto tr_setup;
@@ -1769,7 +1781,7 @@ usbd_req_get_report(struct usb_device *udev, struct mtx *mtx, void *data,
struct usb_interface *iface = usbd_get_iface(udev, iface_index);
struct usb_device_request req;
- if ((iface == NULL) || (iface->idesc == NULL) || (id == 0)) {
+ if ((iface == NULL) || (iface->idesc == NULL)) {
return (USB_ERR_INVAL);
}
DPRINTFN(5, "len=%d\n", len);
diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs
index 386e5461daa04..6a729a2ef61ba 100644
--- a/sys/dev/usb/usbdevs
+++ b/sys/dev/usb/usbdevs
@@ -1874,6 +1874,8 @@ product HUAWEI E1752 0x1446 3G modem
product HUAWEI K3765 0x1465 3G modem
product HUAWEI E1820 0x14ac E1820 HSPA+ USB Slider
product HUAWEI K3765_INIT 0x1520 K3765 Initial
+product HUAWEI E173 0x1c05 3G modem
+product HUAWEI E173_INIT 0x1c0b 3G modem initial
/* HUAWEI 3com products */
product HUAWEI3COM WUB320G 0x0009 Aolynk WUB320g
@@ -2110,6 +2112,7 @@ product LOGITEC RT2870_3 0x0164 RT2870
product LONGCHEER WM66 0x6061 Longcheer WM66 HSDPA
product LONGCHEER W14 0x9603 Mobilcom W14
product LONGCHEER DISK 0xf000 Driver disk
+product LONGCHEER XSSTICK 0x9605 4G Systems XSStick P14
/* Lucent products */
@@ -2447,6 +2450,7 @@ product OPTION GT3GQUAD 0x6300 GlobeTrotter 3G QUAD datacard
product OPTION GT3GPLUS 0x6600 GlobeTrotter 3G+ datacard
product OPTION GTICON322 0xd033 GlobeTrotter Icon322 storage
product OPTION GTMAX36 0x6701 GlobeTrotter Max 3.6 Modem
+product OPTION GTMAX72 0x6711 GlobeTrotter Max 7.2 HSDPA
product OPTION GTHSDPA 0x6971 GlobeTrotter HSDPA
product OPTION GTMAXHSUPA 0x7001 GlobeTrotter HSUPA
product OPTION GTMAXHSUPAE 0x6901 GlobeTrotter HSUPA PCIe
diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h
index d832c327db13b..6446720e86110 100644
--- a/sys/dev/usb/usbdi.h
+++ b/sys/dev/usb/usbdi.h
@@ -37,6 +37,7 @@ struct usb_page_search;
struct usb_process;
struct usb_proc_msg;
struct usb_mbuf;
+struct usb_fs_privdata;
struct mbuf;
typedef enum { /* keep in sync with usb_errstr_table */
@@ -449,7 +450,7 @@ struct usb_fifo_methods {
struct usb_fifo_sc {
struct usb_fifo *fp[2];
- struct cdev* dev;
+ struct usb_fs_privdata *dev;
};
const char *usbd_errstr(usb_error_t error);
@@ -474,6 +475,8 @@ void device_set_usb_desc(device_t dev);
void usb_pause_mtx(struct mtx *mtx, int _ticks);
usb_error_t usbd_set_pnpinfo(struct usb_device *udev,
uint8_t iface_index, const char *pnpinfo);
+usb_error_t usbd_add_dynamic_quirk(struct usb_device *udev,
+ uint16_t quirk);
const struct usb_device_id *usbd_lookup_id_by_info(
const struct usb_device_id *id, usb_size_t sizeof_id,
diff --git a/sys/dev/vge/if_vge.c b/sys/dev/vge/if_vge.c
index d9a58cce5b820..952970219603e 100644
--- a/sys/dev/vge/if_vge.c
+++ b/sys/dev/vge/if_vge.c
@@ -1752,6 +1752,10 @@ vge_intr(void *arg)
#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING) {
+ status = CSR_READ_4(sc, VGE_ISR);
+ CSR_WRITE_4(sc, VGE_ISR, status);
+ if (status != 0xFFFFFFFF && (status & VGE_ISR_LINKSTS) != 0)
+ vge_link_statchg(sc);
VGE_UNLOCK(sc);
return;
}
@@ -2109,11 +2113,10 @@ vge_init_locked(struct vge_softc *sc)
#ifdef DEVICE_POLLING
/*
- * Disable interrupts if we are polling.
+ * Disable interrupts except link state change if we are polling.
*/
if (ifp->if_capenable & IFCAP_POLLING) {
- CSR_WRITE_4(sc, VGE_IMR, 0);
- CSR_WRITE_1(sc, VGE_CRC3, VGE_CR3_INT_GMSK);
+ CSR_WRITE_4(sc, VGE_IMR, VGE_INTRS_POLLING);
} else /* otherwise ... */
#endif
{
@@ -2121,9 +2124,9 @@ vge_init_locked(struct vge_softc *sc)
* Enable interrupts.
*/
CSR_WRITE_4(sc, VGE_IMR, VGE_INTRS);
- CSR_WRITE_4(sc, VGE_ISR, 0xFFFFFFFF);
- CSR_WRITE_1(sc, VGE_CRS3, VGE_CR3_INT_GMSK);
}
+ CSR_WRITE_4(sc, VGE_ISR, 0xFFFFFFFF);
+ CSR_WRITE_1(sc, VGE_CRS3, VGE_CR3_INT_GMSK);
sc->vge_flags &= ~VGE_FLAG_LINK;
mii_mediachg(mii);
@@ -2280,8 +2283,9 @@ vge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
return (error);
VGE_LOCK(sc);
/* Disable interrupts */
- CSR_WRITE_4(sc, VGE_IMR, 0);
- CSR_WRITE_1(sc, VGE_CRC3, VGE_CR3_INT_GMSK);
+ CSR_WRITE_4(sc, VGE_IMR, VGE_INTRS_POLLING);
+ CSR_WRITE_4(sc, VGE_ISR, 0xFFFFFFFF);
+ CSR_WRITE_1(sc, VGE_CRS3, VGE_CR3_INT_GMSK);
ifp->if_capenable |= IFCAP_POLLING;
VGE_UNLOCK(sc);
} else {
diff --git a/sys/dev/vge/if_vgereg.h b/sys/dev/vge/if_vgereg.h
index 77cd61eb6baf0..c8b3f1bb459b3 100644
--- a/sys/dev/vge/if_vgereg.h
+++ b/sys/dev/vge/if_vgereg.h
@@ -302,6 +302,8 @@
VGE_ISR_LINKSTS|VGE_ISR_RXNODESC| \
VGE_ISR_RXDMA_STALL|VGE_ISR_TXDMA_STALL)
+#define VGE_INTRS_POLLING (VGE_ISR_PHYINT|VGE_ISR_LINKSTS)
+
/* Interrupt mask register */
#define VGE_IMR_RXOK_HIPRIO 0x00000001 /* hi prio RX int */
diff --git a/sys/dev/xen/console/console.c b/sys/dev/xen/console/console.c
index d614082848005..5a14623d1c306 100644
--- a/sys/dev/xen/console/console.c
+++ b/sys/dev/xen/console/console.c
@@ -70,6 +70,10 @@ static int rc, rp;
static unsigned int cnsl_evt_reg;
static unsigned int wc, wp; /* write_cons, write_prod */
+#ifdef KDB
+static int xc_altbrk;
+#endif
+
#define CDEV_MAJOR 12
#define XCUNIT(x) (dev2unit(x))
#define ISTTYOPEN(tp) ((tp) && ((tp)->t_state & TS_ISOPEN))
@@ -268,8 +272,12 @@ xencons_rx(char *buf, unsigned len)
#endif
) {
tty_lock(tp);
- for (i = 0; i < len; i++)
+ for (i = 0; i < len; i++) {
+#ifdef KDB
+ kdb_alt_break(buf[i], &xc_altbrk);
+#endif
ttydisc_rint(tp, buf[i], 0);
+ }
ttydisc_rint_done(tp);
tty_unlock(tp);
} else {
diff --git a/sys/fs/cd9660/iso.h b/sys/fs/cd9660/iso.h
index 0988bf6b4066f..89322e74dab69 100644
--- a/sys/fs/cd9660/iso.h
+++ b/sys/fs/cd9660/iso.h
@@ -220,7 +220,7 @@ enum ISO_FTYPE { ISO_FTYPE_DEFAULT, ISO_FTYPE_9660, ISO_FTYPE_RRIP,
#endif
struct iso_mnt {
- int im_flags;
+ uint64_t im_flags;
struct mount *im_mountp;
struct cdev *im_dev;
diff --git a/sys/fs/coda/coda_psdev.c b/sys/fs/coda/coda_psdev.c
index 494f30bff513a..e982a2c467e76 100644
--- a/sys/fs/coda/coda_psdev.c
+++ b/sys/fs/coda/coda_psdev.c
@@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/capability.h>
#include <sys/conf.h>
#include <sys/ioccom.h>
#include <sys/kernel.h>
@@ -371,7 +372,7 @@ vc_write(struct cdev *dev, struct uio *uiop, int flag)
struct vnode *vp = NULL;
if (tmp->oh.result == 0) {
- error = getvnode(uiop->uio_td->td_proc->p_fd,
+ error = getvnode(uiop->uio_td->td_proc->p_fd, CAP_WRITE,
tmp->fd, &fp);
if (!error) {
/*
diff --git a/sys/fs/devfs/devfs_devs.c b/sys/fs/devfs/devfs_devs.c
index d72ada03672d3..a2d3222dda933 100644
--- a/sys/fs/devfs/devfs_devs.c
+++ b/sys/fs/devfs/devfs_devs.c
@@ -630,13 +630,15 @@ devfs_populate_loop(struct devfs_mount *dm, int cleanup)
void
devfs_populate(struct devfs_mount *dm)
{
+ unsigned gen;
sx_assert(&dm->dm_lock, SX_XLOCKED);
- if (dm->dm_generation == devfs_generation)
+ gen = devfs_generation;
+ if (dm->dm_generation == gen)
return;
while (devfs_populate_loop(dm, 0))
continue;
- dm->dm_generation = devfs_generation;
+ dm->dm_generation = gen;
}
/*
diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c
index 955bd8b0f22f8..68ab7ce9d94b8 100644
--- a/sys/fs/devfs/devfs_vnops.c
+++ b/sys/fs/devfs/devfs_vnops.c
@@ -1665,6 +1665,8 @@ static struct fileops devfs_ops_f = {
.fo_kqfilter = devfs_kqfilter_f,
.fo_stat = devfs_stat_f,
.fo_close = devfs_close_f,
+ .fo_chmod = vn_chmod,
+ .fo_chown = vn_chown,
.fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE
};
diff --git a/sys/fs/fdescfs/fdesc_vnops.c b/sys/fs/fdescfs/fdesc_vnops.c
index e11b59ca67169..3c4f44d17c969 100644
--- a/sys/fs/fdescfs/fdesc_vnops.c
+++ b/sys/fs/fdescfs/fdesc_vnops.c
@@ -40,6 +40,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/capability.h>
#include <sys/conf.h>
#include <sys/dirent.h>
#include <sys/filedesc.h>
@@ -305,7 +306,10 @@ fdesc_lookup(ap)
fd = fd1;
}
- if ((error = fget(td, fd, &fp)) != 0)
+ /*
+ * No rights to check since 'fp' isn't actually used.
+ */
+ if ((error = fget(td, fd, 0, &fp)) != 0)
goto bad;
/* Check if we're looking up ourselves. */
@@ -455,7 +459,7 @@ fdesc_setattr(ap)
/*
* Allow setattr where there is an underlying vnode.
*/
- error = getvnode(td->td_proc->p_fd, fd, &fp);
+ error = getvnode(td->td_proc->p_fd, fd, CAP_EXTATTR_SET, &fp);
if (error) {
/*
* getvnode() returns EINVAL if the file descriptor is not
diff --git a/sys/fs/fifofs/fifo_vnops.c b/sys/fs/fifofs/fifo_vnops.c
index e339a8ac8535f..b8d4a400660e0 100644
--- a/sys/fs/fifofs/fifo_vnops.c
+++ b/sys/fs/fifofs/fifo_vnops.c
@@ -72,6 +72,8 @@ struct fileops fifo_ops_f = {
.fo_kqfilter = fifo_kqfilter_f,
.fo_stat = fifo_stat_f,
.fo_close = fifo_close_f,
+ .fo_chmod = vn_chmod,
+ .fo_chown = vn_chown,
.fo_flags = DFLAG_PASSABLE
};
diff --git a/sys/fs/msdosfs/msdosfsmount.h b/sys/fs/msdosfs/msdosfsmount.h
index 417923fa80597..673095ed69f5d 100644
--- a/sys/fs/msdosfs/msdosfsmount.h
+++ b/sys/fs/msdosfs/msdosfsmount.h
@@ -103,7 +103,7 @@ struct msdosfsmount {
u_int pm_fatdiv; /* offset computation */
u_int pm_curfat; /* current fat for FAT32 (0 otherwise) */
u_int *pm_inusemap; /* ptr to bitmap of in-use clusters */
- u_int pm_flags; /* see below */
+ uint64_t pm_flags; /* see below */
void *pm_u2w; /* Local->Unicode iconv handle */
void *pm_w2u; /* Unicode->Local iconv handle */
void *pm_u2d; /* Unicode->DOS iconv handle */
diff --git a/sys/fs/nfsclient/nfs_clnode.c b/sys/fs/nfsclient/nfs_clnode.c
index d15de6e9c7b0c..5e7185df2125b 100644
--- a/sys/fs/nfsclient/nfs_clnode.c
+++ b/sys/fs/nfsclient/nfs_clnode.c
@@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
+#include <sys/taskqueue.h>
#include <sys/vnode.h>
#include <vm/uma.h>
@@ -65,6 +66,8 @@ MALLOC_DECLARE(M_NEWNFSREQ);
uma_zone_t newnfsnode_zone;
+static void nfs_freesillyrename(void *arg, __unused int pending);
+
void
ncl_nhinit(void)
{
@@ -186,6 +189,20 @@ ncl_nget(struct mount *mntp, u_int8_t *fhp, int fhsize, struct nfsnode **npp,
return (0);
}
+/*
+ * Do the vrele(sp->s_dvp) as a separate task in order to avoid a
+ * deadlock because of a LOR when vrele() locks the directory vnode.
+ */
+static void
+nfs_freesillyrename(void *arg, __unused int pending)
+{
+ struct sillyrename *sp;
+
+ sp = arg;
+ vrele(sp->s_dvp);
+ free(sp, M_NEWNFSREQ);
+}
+
int
ncl_inactive(struct vop_inactive_args *ap)
{
@@ -220,8 +237,8 @@ ncl_inactive(struct vop_inactive_args *ap)
*/
ncl_removeit(sp, vp);
crfree(sp->s_cred);
- vrele(sp->s_dvp);
- FREE((caddr_t)sp, M_NEWNFSREQ);
+ TASK_INIT(&sp->s_task, 0, nfs_freesillyrename, sp);
+ taskqueue_enqueue(taskqueue_thread, &sp->s_task);
mtx_lock(&np->n_mtx);
}
np->n_flag &= NMODIFIED;
diff --git a/sys/fs/nfsclient/nfs_clport.c b/sys/fs/nfsclient/nfs_clport.c
index 44d3c7421c482..acbfa6ceda8f3 100644
--- a/sys/fs/nfsclient/nfs_clport.c
+++ b/sys/fs/nfsclient/nfs_clport.c
@@ -36,6 +36,8 @@ __FBSDID("$FreeBSD$");
#include "opt_kdtrace.h"
+#include <sys/capability.h>
+
/*
* generally, I don't like #includes inside .h files, but it seems to
* be the easiest way to handle the port.
@@ -1231,7 +1233,13 @@ nfssvc_nfscl(struct thread *td, struct nfssvc_args *uap)
error = copyin(uap->argp, (caddr_t)&nfscbdarg, sizeof(nfscbdarg));
if (error)
return (error);
- if ((error = fget(td, nfscbdarg.sock, &fp)) != 0) {
+ /*
+ * Since we don't know what rights might be required,
+ * pretend that we need them all. It is better to be too
+ * careful than too reckless.
+ */
+ if ((error = fget(td, nfscbdarg.sock, CAP_SOCK_ALL, &fp))
+ != 0) {
return (error);
}
if (fp->f_type != DTYPE_SOCKET) {
diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c
index a69c76e8e30f8..7e87b6e71a101 100644
--- a/sys/fs/nfsclient/nfs_clvnops.c
+++ b/sys/fs/nfsclient/nfs_clvnops.c
@@ -1596,6 +1596,8 @@ again:
if (attrflag)
(void) nfscl_loadattrcache(&newvp, &nfsva, NULL,
NULL, 0, 1);
+ if (error != 0)
+ vput(newvp);
}
}
if (!error) {
diff --git a/sys/fs/nfsclient/nfsnode.h b/sys/fs/nfsclient/nfsnode.h
index 1d1c89c7d4b7b..c29805d5efea6 100644
--- a/sys/fs/nfsclient/nfsnode.h
+++ b/sys/fs/nfsclient/nfsnode.h
@@ -35,11 +35,14 @@
#ifndef _NFSCLIENT_NFSNODE_H_
#define _NFSCLIENT_NFSNODE_H_
+#include <sys/_task.h>
+
/*
* Silly rename structure that hangs off the nfsnode until the name
* can be removed by nfs_inactive()
*/
struct sillyrename {
+ struct task s_task;
struct ucred *s_cred;
struct vnode *s_dvp;
long s_namlen;
diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c
index 56c563ae1f33a..42ace8204f22f 100644
--- a/sys/fs/nfsserver/nfs_nfsdport.c
+++ b/sys/fs/nfsserver/nfs_nfsdport.c
@@ -34,6 +34,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <sys/capability.h>
+
/*
* Functions that perform the vfs operations required by the routines in
* nfsd_serv.c. It is hoped that this change will make the server more
@@ -280,6 +282,7 @@ nfsvno_namei(struct nfsrv_descript *nd, struct nameidata *ndp,
*retdirp = NULL;
cnp->cn_nameptr = cnp->cn_pnbuf;
+ ndp->ni_strictrelative = 0;
/*
* Extract and set starting directory.
*/
@@ -3027,7 +3030,12 @@ nfssvc_nfsd(struct thread *td, struct nfssvc_args *uap)
error = copyin(uap->argp, (caddr_t)&sockarg, sizeof (sockarg));
if (error)
goto out;
- if ((error = fget(td, sockarg.sock, &fp)) != 0)
+ /*
+ * Since we don't know what rights might be required,
+ * pretend that we need them all. It is better to be too
+ * careful than too reckless.
+ */
+ if ((error = fget(td, sockarg.sock, CAP_SOCK_ALL, &fp)) != 0)
goto out;
if (fp->f_type != DTYPE_SOCKET) {
fdrop(fp, td);
diff --git a/sys/fs/nfsserver/nfs_nfsdserv.c b/sys/fs/nfsserver/nfs_nfsdserv.c
index b6a365d612780..85fbbd24dcd76 100644
--- a/sys/fs/nfsserver/nfs_nfsdserv.c
+++ b/sys/fs/nfsserver/nfs_nfsdserv.c
@@ -620,7 +620,7 @@ nfsrvd_read(struct nfsrv_descript *nd, __unused int isdgram,
vnode_t vp, NFSPROC_T *p, struct nfsexstuff *exp)
{
u_int32_t *tl;
- int error = 0, cnt, len, getret = 1, reqlen, eof = 0;
+ int error = 0, cnt, getret = 1, reqlen, eof = 0;
mbuf_t m2, m3;
struct nfsvattr nva;
off_t off = 0x0;
@@ -714,11 +714,11 @@ nfsrvd_read(struct nfsrv_descript *nd, __unused int isdgram,
eof = 1;
} else if (reqlen == 0)
cnt = 0;
- else if ((off + reqlen) > nva.na_size)
+ else if ((off + reqlen) >= nva.na_size) {
cnt = nva.na_size - off;
- else
+ eof = 1;
+ } else
cnt = reqlen;
- len = NFSM_RNDUP(cnt);
m3 = NULL;
if (cnt > 0) {
nd->nd_repstat = nfsvno_read(vp, off, cnt, nd->nd_cred, p,
@@ -748,7 +748,7 @@ nfsrvd_read(struct nfsrv_descript *nd, __unused int isdgram,
*tl++ = txdr_unsigned(cnt);
} else
NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- if (len < reqlen || eof)
+ if (eof)
*tl++ = newnfs_true;
else
*tl++ = newnfs_false;
@@ -1425,6 +1425,7 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgram,
struct nfsrvfh tfh;
char *bufp, *tbufp = NULL;
u_long *hashp;
+ fhandle_t fh;
if (nd->nd_repstat) {
nfsrv_wcc(nd, fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
@@ -1450,19 +1451,34 @@ nfsrvd_rename(struct nfsrv_descript *nd, int isdgram,
tnes = *toexp;
tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd->nd_cred, p, 0);
} else {
+ tfh.nfsrvfh_len = 0;
error = nfsrv_mtofh(nd, &tfh);
+ if (error == 0)
+ error = nfsvno_getfh(dp, &fh, p);
if (error) {
vput(dp);
/* todp is always NULL except NFSv4 */
nfsvno_relpathbuf(&fromnd);
goto out;
}
- nd->nd_cred->cr_uid = nd->nd_saveduid;
- nfsd_fhtovp(nd, &tfh, LK_EXCLUSIVE, &tdp, &tnes, NULL, 0, p);
- if (tdp) {
+
+ /* If this is the same file handle, just VREF() the vnode. */
+ if (tfh.nfsrvfh_len == NFSX_MYFH &&
+ !NFSBCMP(tfh.nfsrvfh_data, &fh, NFSX_MYFH)) {
+ VREF(dp);
+ tdp = dp;
+ tnes = *exp;
tdirfor_ret = nfsvno_getattr(tdp, &tdirfor, nd->nd_cred,
p, 1);
- NFSVOPUNLOCK(tdp, 0);
+ } else {
+ nd->nd_cred->cr_uid = nd->nd_saveduid;
+ nfsd_fhtovp(nd, &tfh, LK_EXCLUSIVE, &tdp, &tnes, NULL,
+ 0, p);
+ if (tdp) {
+ tdirfor_ret = nfsvno_getattr(tdp, &tdirfor,
+ nd->nd_cred, p, 1);
+ NFSVOPUNLOCK(tdp, 0);
+ }
}
}
NFSNAMEICNDSET(&tond.ni_cnd, nd->nd_cred, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART);
@@ -2725,12 +2741,11 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram,
* Do basic access checking.
*/
if (!nd->nd_repstat && vnode_vtype(vp) != VREG) {
- if (vnode_vtype(vp) == VDIR)
- nd->nd_repstat = NFSERR_ISDIR;
- else if (vnode_vtype(vp) == VLNK)
+ /*
+ * The IETF working group decided that this is the correct
+ * error return for all non-regular files.
+ */
nd->nd_repstat = NFSERR_SYMLINK;
- else
- nd->nd_repstat = NFSERR_INVAL;
}
if (!nd->nd_repstat && (stp->ls_flags & NFSLCK_WRITEACCESS))
nd->nd_repstat = nfsvno_accchk(vp, VWRITE, nd->nd_cred,
diff --git a/sys/fs/ntfs/ntfs.h b/sys/fs/ntfs/ntfs.h
index 4f6431f371526..8415222297be5 100644
--- a/sys/fs/ntfs/ntfs.h
+++ b/sys/fs/ntfs/ntfs.h
@@ -250,7 +250,7 @@ struct ntfsmount {
uid_t ntm_uid;
gid_t ntm_gid;
mode_t ntm_mode;
- u_int ntm_flag;
+ uint64_t ntm_flag;
cn_t ntm_cfree;
struct ntvattrdef *ntm_ad;
int ntm_adnum;
diff --git a/sys/fs/portalfs/portal_vfsops.c b/sys/fs/portalfs/portal_vfsops.c
index a8c16c4b17fa4..04e7a3d225003 100644
--- a/sys/fs/portalfs/portal_vfsops.c
+++ b/sys/fs/portalfs/portal_vfsops.c
@@ -40,6 +40,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/capability.h>
#include <sys/domain.h>
#include <sys/filedesc.h>
#include <sys/kernel.h>
@@ -112,7 +113,12 @@ portal_mount(struct mount *mp)
if (error)
return (error);
- if ((error = fget(td, v, &fp)) != 0)
+ /*
+ * Capsicum is not incompatible with portalfs, but we don't really
+ * know what rights are required. In the spirit of "better safe than
+ * sorry", pretend that all rights are required for now.
+ */
+ if ((error = fget(td, v, CAP_MASK_VALID, &fp)) != 0)
return (error);
if (fp->f_type != DTYPE_SOCKET) {
fdrop(fp, td);
diff --git a/sys/fs/portalfs/portal_vnops.c b/sys/fs/portalfs/portal_vnops.c
index 6fcc1ce642193..7cd5267698b74 100644
--- a/sys/fs/portalfs/portal_vnops.c
+++ b/sys/fs/portalfs/portal_vnops.c
@@ -38,7 +38,10 @@
* Portal Filesystem
*/
+#include "opt_capsicum.h"
+
#include <sys/param.h>
+#include <sys/capability.h>
#include <sys/fcntl.h>
#include <sys/file.h>
#include <sys/kernel.h>
@@ -232,6 +235,15 @@ portal_open(ap)
struct file *fp;
struct portal_cred pcred;
+#ifdef CAPABILITY_MODE
+ /*
+ * This may require access to a global namespace (e.g. an IP address);
+ * disallow it entirely, as we do open(2).
+ */
+ if (IN_CAPABILITY_MODE(td))
+ return (ECAPMODE);
+#endif
+
/*
* Nothing to do when opening the root node.
*/
@@ -414,7 +426,7 @@ portal_open(ap)
* Check that the mode the file is being opened for is a subset
* of the mode of the existing descriptor.
*/
- if ((error = fget(td, fd, &fp)) != 0)
+ if ((error = fget(td, fd, 0, &fp)) != 0)
goto bad;
if (((ap->a_mode & (FREAD|FWRITE)) | fp->f_flag) != fp->f_flag) {
fdrop(fp, td);
diff --git a/sys/fs/procfs/procfs.c b/sys/fs/procfs/procfs.c
index 8b69eb1a0b3c7..514e279396fec 100644
--- a/sys/fs/procfs/procfs.c
+++ b/sys/fs/procfs/procfs.c
@@ -67,20 +67,23 @@
int
procfs_doprocfile(PFS_FILL_ARGS)
{
- char *fullpath = "unknown";
- char *freepath = NULL;
+ char *fullpath;
+ char *freepath;
struct vnode *textvp;
+ int error;
+ freepath = NULL;
PROC_LOCK(p);
textvp = p->p_textvp;
vhold(textvp);
PROC_UNLOCK(p);
- vn_fullpath(td, textvp, &fullpath, &freepath);
+ error = vn_fullpath(td, textvp, &fullpath, &freepath);
vdrop(textvp);
- sbuf_printf(sb, "%s", fullpath);
- if (freepath)
+ if (error == 0)
+ sbuf_printf(sb, "%s", fullpath);
+ if (freepath != NULL)
free(freepath, M_TEMP);
- return (0);
+ return (error);
}
/*
diff --git a/sys/fs/smbfs/smbfs.h b/sys/fs/smbfs/smbfs.h
index 4be0a55c76b38..84c79a12f8925 100644
--- a/sys/fs/smbfs/smbfs.h
+++ b/sys/fs/smbfs/smbfs.h
@@ -80,7 +80,7 @@ struct smbmount {
struct mount * sm_mp;
struct smbnode * sm_root;
struct ucred * sm_owner;
- u_int sm_flags;
+ uint64_t sm_flags;
long sm_nextino;
struct smb_share * sm_share;
/* struct simplelock sm_npslock;*/
diff --git a/sys/fs/tmpfs/tmpfs_vnops.c b/sys/fs/tmpfs/tmpfs_vnops.c
index 0568e93cd4144..74aba047edcd4 100644
--- a/sys/fs/tmpfs/tmpfs_vnops.c
+++ b/sys/fs/tmpfs/tmpfs_vnops.c
@@ -518,8 +518,7 @@ lookupvpg:
* Reference the page before unlocking and sleeping so
* that the page daemon is less likely to reclaim it.
*/
- vm_page_lock_queues();
- vm_page_flag_set(m, PG_REFERENCED);
+ vm_page_reference(m);
vm_page_sleep(m, "tmfsmr");
goto lookupvpg;
}
@@ -538,8 +537,7 @@ lookupvpg:
* Reference the page before unlocking and sleeping so
* that the page daemon is less likely to reclaim it.
*/
- vm_page_lock_queues();
- vm_page_flag_set(m, PG_REFERENCED);
+ vm_page_reference(m);
vm_page_sleep(m, "tmfsmr");
goto lookupvpg;
}
@@ -650,8 +648,7 @@ lookupvpg:
* Reference the page before unlocking and sleeping so
* that the page daemon is less likely to reclaim it.
*/
- vm_page_lock_queues();
- vm_page_flag_set(vpg, PG_REFERENCED);
+ vm_page_reference(vpg);
vm_page_sleep(vpg, "tmfsmw");
goto lookupvpg;
}
diff --git a/sys/gnu/fs/xfs/xfs_dfrag.c b/sys/gnu/fs/xfs/xfs_dfrag.c
index 77a71dfe143c5..7b6b04ebcda70 100644
--- a/sys/gnu/fs/xfs/xfs_dfrag.c
+++ b/sys/gnu/fs/xfs/xfs_dfrag.c
@@ -46,6 +46,7 @@
#include "xfs_mac.h"
#include "xfs_rw.h"
+#include <sys/capability.h>
#include <sys/file.h>
/*
@@ -79,7 +80,8 @@ xfs_swapext(
}
/* Pull information for the target fd */
- if (fgetvp(td, (int)sxp->sx_fdtarget, &bvp) != 0) {
+ if (fgetvp(td, (int)sxp->sx_fdtarget, CAP_READ | CAP_WRITE, &bvp)
+ != 0) {
error = XFS_ERROR(EINVAL);
goto error0;
}
@@ -91,7 +93,7 @@ xfs_swapext(
goto error0;
}
- if (fgetvp(td, (int)sxp->sx_fdtmp, &btvp) != 0) {
+ if (fgetvp(td, (int)sxp->sx_fdtmp, CAP_READ | CAP_WRITE, &btvp) != 0) {
error = XFS_ERROR(EINVAL);
goto error0;
}
diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC
index c4548c6bce1ce..69e8d9b042921 100644
--- a/sys/i386/conf/GENERIC
+++ b/sys/i386/conf/GENERIC
@@ -39,7 +39,7 @@ options MD_ROOT # MD is a potential root device
options NFSCL # New Network Filesystem Client
options NFSD # New Network Filesystem Server
options NFSLOCKD # Network Lock Manager
-options NFS_ROOT # NFS usable as /, requires NFSCLIENT
+options NFS_ROOT # NFS usable as /, requires NFSCL
options MSDOSFS # MSDOS Filesystem
options CD9660 # ISO 9660 Filesystem
options PROCFS # Process filesystem (requires PSEUDOFS)
@@ -196,10 +196,7 @@ device plip # TCP/IP over parallel
device ppi # Parallel port interface device
#device vpo # Requires scbus and da
-# If you've got a "dumb" serial or parallel PCI card that is
-# supported by the puc(4) glue driver, uncomment the following
-# line to enable it (connects to sio, uart and/or ppc drivers):
-#device puc
+device puc # Multi I/O cards and multi-channel UARTs
# PCI Ethernet NICs.
device bxe # Broadcom BCM57710/BCM57711/BCM57711E 10Gb Ethernet
@@ -342,7 +339,7 @@ device uath # Atheros AR5523 wireless NICs
device upgt # Conexant/Intersil PrismGT wireless NICs.
device ural # Ralink Technology RT2500USB wireless NICs
device urtw # Realtek RTL8187B/L wireless NICs
-device zyd # ZyDAS zb1211/zb1211b wireless NICs
+device zyd # ZyDAS zd1211/zd1211b wireless NICs
# FireWire support
device firewire # FireWire bus code
diff --git a/sys/i386/conf/XBOX b/sys/i386/conf/XBOX
index a3e8a6bbbc2f4..9ee270b8ae4ee 100644
--- a/sys/i386/conf/XBOX
+++ b/sys/i386/conf/XBOX
@@ -27,10 +27,10 @@ options SOFTUPDATES # Enable FFS soft updates support
#options UFS_ACL # Support for access control lists
#options UFS_DIRHASH # Improve performance on big directories
#options MD_ROOT # MD is a potential root device
-options NFSCLIENT # Network Filesystem Client
-#options NFSSERVER # Network Filesystem Server
+options NFSCL # New Network Filesystem Client
+#options NFSD # New Network Filesystem Server
#options NFSLOCKD # Network Lock Manager
-#options NFS_ROOT # NFS usable as /, requires NFSCLIENT
+#options NFS_ROOT # NFS usable as /, requires NFSCL
#options MSDOSFS # MSDOS Filesystem
options CD9660 # ISO 9660 Filesystem
#options PROCFS # Process filesystem (requires PSEUDOFS)
diff --git a/sys/i386/conf/XEN b/sys/i386/conf/XEN
index f1fb99bab82ae..ad453bf80a1a4 100644
--- a/sys/i386/conf/XEN
+++ b/sys/i386/conf/XEN
@@ -21,10 +21,10 @@ options SOFTUPDATES # Enable FFS soft updates support
options UFS_ACL # Support for access control lists
options UFS_DIRHASH # Improve performance on big directories
options UFS_GJOURNAL # Enable gjournal-based UFS journaling
-options NFSCLIENT # Network Filesystem Client
-options NFSSERVER # Network Filesystem Server
+options NFSCL # New Network Filesystem Client
+options NFSD # New Network Filesystem Server
options NFSLOCKD # Network Lock Manager
-options NFS_ROOT # NFS usable as /, requires NFSCLIENT
+options NFS_ROOT # NFS usable as /, requires NFSCL
options MSDOSFS # MSDOS Filesystem
options CD9660 # ISO 9660 Filesystem
options PROCFS # Process filesystem (requires PSEUDOFS)
diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
index 91050c43bee3d..e596b964d992b 100644
--- a/sys/i386/i386/machdep.c
+++ b/sys/i386/i386/machdep.c
@@ -2132,7 +2132,7 @@ static void
getmemsize(int first)
{
int has_smap, off, physmap_idx, pa_indx, da_indx;
- u_long physmem_tunable;
+ u_long physmem_tunable, memtest;
vm_paddr_t physmap[PHYSMAP_SIZE];
pt_entry_t *pte;
quad_t dcons_addr, dcons_size;
@@ -2339,6 +2339,13 @@ physmap_done:
if (has_smap && Maxmem > atop(physmap[physmap_idx + 1]))
Maxmem = atop(physmap[physmap_idx + 1]);
+ /*
+ * By default keep the memtest enabled. Use a general name so that
+ * one could eventually do more with the code than just disable it.
+ */
+ memtest = 1;
+ TUNABLE_ULONG_FETCH("hw.memtest.tests", &memtest);
+
if (atop(physmap[physmap_idx + 1]) != Maxmem &&
(boothowto & RB_VERBOSE))
printf("Physical memory use set to %ldK\n", Maxmem * 4);
@@ -2402,6 +2409,8 @@ physmap_done:
goto do_dump_avail;
page_bad = FALSE;
+ if (memtest == 0)
+ goto skip_memtest;
/*
* map page into kernel: valid, read/write,non-cacheable
@@ -2439,6 +2448,7 @@ physmap_done:
*/
*(int *)ptr = tmp;
+skip_memtest:
/*
* Adjust array of valid/good pages.
*/
diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
index 002e52948eb0c..db5f99566f79b 100644
--- a/sys/i386/i386/pmap.c
+++ b/sys/i386/i386/pmap.c
@@ -2207,7 +2207,7 @@ pmap_collect(pmap_t locked_pmap, struct vpgqueues *vpq)
KASSERT((tpte & PG_W) == 0,
("pmap_collect: wired pte %#jx", (uintmax_t)tpte));
if (tpte & PG_A)
- vm_page_flag_set(m, PG_REFERENCED);
+ vm_page_aflag_set(m, PGA_REFERENCED);
if ((tpte & (PG_M | PG_RW)) == (PG_M | PG_RW))
vm_page_dirty(m);
free = NULL;
@@ -2221,7 +2221,7 @@ pmap_collect(pmap_t locked_pmap, struct vpgqueues *vpq)
}
if (TAILQ_EMPTY(&m->md.pv_list) &&
TAILQ_EMPTY(&pa_to_pvh(VM_PAGE_TO_PHYS(m))->pv_list))
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
}
sched_unpin();
}
@@ -2400,7 +2400,7 @@ pmap_pv_demote_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa)
va_last = va + NBPDR - PAGE_SIZE;
do {
m++;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_pv_demote_pde: page %p is not managed", m));
va += PAGE_SIZE;
pmap_insert_entry(pmap, va, m);
@@ -2461,7 +2461,7 @@ pmap_remove_entry(pmap_t pmap, vm_page_t m, vm_offset_t va)
if (TAILQ_EMPTY(&m->md.pv_list)) {
pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
if (TAILQ_EMPTY(&pvh->pv_list))
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
}
}
@@ -2714,10 +2714,10 @@ pmap_remove_pde(pmap_t pmap, pd_entry_t *pdq, vm_offset_t sva,
if ((oldpde & (PG_M | PG_RW)) == (PG_M | PG_RW))
vm_page_dirty(m);
if (oldpde & PG_A)
- vm_page_flag_set(m, PG_REFERENCED);
+ vm_page_aflag_set(m, PGA_REFERENCED);
if (TAILQ_EMPTY(&m->md.pv_list) &&
TAILQ_EMPTY(&pvh->pv_list))
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
}
}
if (pmap == kernel_pmap) {
@@ -2763,7 +2763,7 @@ pmap_remove_pte(pmap_t pmap, pt_entry_t *ptq, vm_offset_t va, vm_page_t *free)
if ((oldpte & (PG_M | PG_RW)) == (PG_M | PG_RW))
vm_page_dirty(m);
if (oldpte & PG_A)
- vm_page_flag_set(m, PG_REFERENCED);
+ vm_page_aflag_set(m, PGA_REFERENCED);
pmap_remove_entry(pmap, m, va);
}
return (pmap_unuse_pt(pmap, va, free));
@@ -2927,7 +2927,7 @@ pmap_remove_all(vm_page_t m)
vm_offset_t va;
vm_page_t free;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_remove_all: page %p is not managed", m));
free = NULL;
vm_page_lock_queues();
@@ -2953,7 +2953,7 @@ pmap_remove_all(vm_page_t m)
if (tpte & PG_W)
pmap->pm_stats.wired_count--;
if (tpte & PG_A)
- vm_page_flag_set(m, PG_REFERENCED);
+ vm_page_aflag_set(m, PGA_REFERENCED);
/*
* Update the vm_page_t clean and reference bits.
@@ -2966,7 +2966,7 @@ pmap_remove_all(vm_page_t m)
free_pv_entry(pmap, pv);
PMAP_UNLOCK(pmap);
}
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
sched_unpin();
vm_page_unlock_queues();
pmap_free_zero_pages(free);
@@ -3299,8 +3299,8 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_prot_t access, vm_page_t m,
KASSERT(va < UPT_MIN_ADDRESS || va >= UPT_MAX_ADDRESS,
("pmap_enter: invalid to pmap_enter page table pages (va: 0x%x)",
va));
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0 ||
- (m->oflags & VPO_BUSY) != 0,
+ KASSERT((m->oflags & (VPO_UNMANAGED | VPO_BUSY)) != 0 ||
+ VM_OBJECT_LOCKED(m->object),
("pmap_enter: page %p is not busy", m));
mpte = NULL;
@@ -3388,7 +3388,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_prot_t access, vm_page_t m,
/*
* Enter on the PV list if part of our managed memory.
*/
- if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0) {
+ if ((m->oflags & VPO_UNMANAGED) == 0) {
KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva,
("pmap_enter: managed mapping within the clean submap"));
if (pv == NULL)
@@ -3413,7 +3413,7 @@ validate:
if ((prot & VM_PROT_WRITE) != 0) {
newpte |= PG_RW;
if ((newpte & PG_MANAGED) != 0)
- vm_page_flag_set(m, PG_WRITEABLE);
+ vm_page_aflag_set(m, PGA_WRITEABLE);
}
#ifdef PAE
if ((prot & VM_PROT_EXECUTE) == 0)
@@ -3439,7 +3439,7 @@ validate:
origpte = pte_load_store(pte, newpte);
if (origpte & PG_A) {
if (origpte & PG_MANAGED)
- vm_page_flag_set(om, PG_REFERENCED);
+ vm_page_aflag_set(om, PGA_REFERENCED);
if (opa != VM_PAGE_TO_PHYS(m))
invlva = TRUE;
#ifdef PAE
@@ -3457,7 +3457,7 @@ validate:
if ((origpte & PG_MANAGED) != 0 &&
TAILQ_EMPTY(&om->md.pv_list) &&
TAILQ_EMPTY(&pa_to_pvh(opa)->pv_list))
- vm_page_flag_clear(om, PG_WRITEABLE);
+ vm_page_aflag_clear(om, PGA_WRITEABLE);
if (invlva)
pmap_invalidate_page(pmap, va);
} else
@@ -3498,7 +3498,7 @@ pmap_enter_pde(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot)
}
newpde = VM_PAGE_TO_PHYS(m) | pmap_cache_bits(m->md.pat_mode, 1) |
PG_PS | PG_V;
- if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0) {
+ if ((m->oflags & VPO_UNMANAGED) == 0) {
newpde |= PG_MANAGED;
/*
@@ -3604,7 +3604,7 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m,
vm_page_t free;
KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva ||
- (m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0,
+ (m->oflags & VPO_UNMANAGED) != 0,
("pmap_enter_quick_locked: managed mapping within the clean submap"));
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
PMAP_LOCK_ASSERT(pmap, MA_OWNED);
@@ -3667,7 +3667,7 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m,
/*
* Enter on the PV list if part of our managed memory.
*/
- if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0 &&
+ if ((m->oflags & VPO_UNMANAGED) == 0 &&
!pmap_try_insert_pv_entry(pmap, va, m)) {
if (mpte != NULL) {
free = NULL;
@@ -3695,7 +3695,7 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m,
/*
* Now validate mapping with RO protection
*/
- if (m->flags & (PG_FICTITIOUS|PG_UNMANAGED))
+ if ((m->oflags & VPO_UNMANAGED) != 0)
pte_store(pte, pa | PG_V | PG_U);
else
pte_store(pte, pa | PG_V | PG_U | PG_MANAGED);
@@ -4096,7 +4096,7 @@ pmap_page_exists_quick(pmap_t pmap, vm_page_t m)
int loops = 0;
boolean_t rv;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_page_exists_quick: page %p is not managed", m));
rv = FALSE;
vm_page_lock_queues();
@@ -4137,7 +4137,7 @@ pmap_page_wired_mappings(vm_page_t m)
int count;
count = 0;
- if ((m->flags & PG_FICTITIOUS) != 0)
+ if ((m->oflags & VPO_UNMANAGED) != 0)
return (count);
vm_page_lock_queues();
count = pmap_pvh_wired_mappings(&m->md, count);
@@ -4181,7 +4181,7 @@ pmap_page_is_mapped(vm_page_t m)
{
boolean_t rv;
- if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0)
+ if ((m->oflags & VPO_UNMANAGED) != 0)
return (FALSE);
vm_page_lock_queues();
rv = !TAILQ_EMPTY(&m->md.pv_list) ||
@@ -4287,7 +4287,7 @@ pmap_remove_pages(pmap_t pmap)
if (TAILQ_EMPTY(&pvh->pv_list)) {
for (mt = m; mt < &m[NBPDR / PAGE_SIZE]; mt++)
if (TAILQ_EMPTY(&mt->md.pv_list))
- vm_page_flag_clear(mt, PG_WRITEABLE);
+ vm_page_aflag_clear(mt, PGA_WRITEABLE);
}
mpte = pmap_lookup_pt_page(pmap, pv->pv_va);
if (mpte != NULL) {
@@ -4305,7 +4305,7 @@ pmap_remove_pages(pmap_t pmap)
if (TAILQ_EMPTY(&m->md.pv_list)) {
pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
if (TAILQ_EMPTY(&pvh->pv_list))
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
}
pmap_unuse_pt(pmap, pv->pv_va, &free);
}
@@ -4341,17 +4341,17 @@ pmap_is_modified(vm_page_t m)
{
boolean_t rv;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_is_modified: page %p is not managed", m));
/*
- * If the page is not VPO_BUSY, then PG_WRITEABLE cannot be
- * concurrently set while the object is locked. Thus, if PG_WRITEABLE
+ * If the page is not VPO_BUSY, then PGA_WRITEABLE cannot be
+ * concurrently set while the object is locked. Thus, if PGA_WRITEABLE
* is clear, no PTEs can have PG_M set.
*/
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
if ((m->oflags & VPO_BUSY) == 0 &&
- (m->flags & PG_WRITEABLE) == 0)
+ (m->aflags & PGA_WRITEABLE) == 0)
return (FALSE);
vm_page_lock_queues();
rv = pmap_is_modified_pvh(&m->md) ||
@@ -4424,7 +4424,7 @@ pmap_is_referenced(vm_page_t m)
{
boolean_t rv;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_is_referenced: page %p is not managed", m));
vm_page_lock_queues();
rv = pmap_is_referenced_pvh(&m->md) ||
@@ -4474,17 +4474,17 @@ pmap_remove_write(vm_page_t m)
pt_entry_t oldpte, *pte;
vm_offset_t va;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_remove_write: page %p is not managed", m));
/*
- * If the page is not VPO_BUSY, then PG_WRITEABLE cannot be set by
- * another thread while the object is locked. Thus, if PG_WRITEABLE
+ * If the page is not VPO_BUSY, then PGA_WRITEABLE cannot be set by
+ * another thread while the object is locked. Thus, if PGA_WRITEABLE
* is clear, no page table entries need updating.
*/
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
if ((m->oflags & VPO_BUSY) == 0 &&
- (m->flags & PG_WRITEABLE) == 0)
+ (m->aflags & PGA_WRITEABLE) == 0)
return;
vm_page_lock_queues();
sched_pin();
@@ -4522,7 +4522,7 @@ retry:
}
PMAP_UNLOCK(pmap);
}
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
sched_unpin();
vm_page_unlock_queues();
}
@@ -4550,7 +4550,7 @@ pmap_ts_referenced(vm_page_t m)
vm_offset_t va;
int rtval = 0;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_ts_referenced: page %p is not managed", m));
pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
vm_page_lock_queues();
@@ -4626,18 +4626,18 @@ pmap_clear_modify(vm_page_t m)
pt_entry_t oldpte, *pte;
vm_offset_t va;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_clear_modify: page %p is not managed", m));
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
KASSERT((m->oflags & VPO_BUSY) == 0,
("pmap_clear_modify: page %p is busy", m));
/*
- * If the page is not PG_WRITEABLE, then no PTEs can have PG_M set.
+ * If the page is not PGA_WRITEABLE, then no PTEs can have PG_M set.
* If the object containing the page is locked and the page is not
- * VPO_BUSY, then PG_WRITEABLE cannot be concurrently set.
+ * VPO_BUSY, then PGA_WRITEABLE cannot be concurrently set.
*/
- if ((m->flags & PG_WRITEABLE) == 0)
+ if ((m->aflags & PGA_WRITEABLE) == 0)
return;
vm_page_lock_queues();
sched_pin();
@@ -4715,7 +4715,7 @@ pmap_clear_reference(vm_page_t m)
pt_entry_t *pte;
vm_offset_t va;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_clear_reference: page %p is not managed", m));
vm_page_lock_queues();
sched_pin();
diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c
index 5a8016c9c69da..dddecaa807ff1 100644
--- a/sys/i386/i386/trap.c
+++ b/sys/i386/i386/trap.c
@@ -1054,6 +1054,8 @@ cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
return (error);
}
+#include "../../kern/subr_syscall.c"
+
/*
* syscall - system call request C handler
*
diff --git a/sys/i386/ibcs2/ibcs2_fcntl.c b/sys/i386/ibcs2/ibcs2_fcntl.c
index 6875aef71fdcd..fddfcb59321b6 100644
--- a/sys/i386/ibcs2/ibcs2_fcntl.c
+++ b/sys/i386/ibcs2/ibcs2_fcntl.c
@@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/capability.h>
#include <sys/fcntl.h>
#include <sys/file.h>
#include <sys/filedesc.h>
@@ -203,7 +204,7 @@ ibcs2_open(td, uap)
struct file *fp;
int error;
- error = fget(td, td->td_retval[0], &fp);
+ error = fget(td, td->td_retval[0], CAP_IOCTL, &fp);
PROC_UNLOCK(p);
if (error)
return (EBADF);
diff --git a/sys/i386/ibcs2/ibcs2_ioctl.c b/sys/i386/ibcs2/ibcs2_ioctl.c
index 90184e3cb6286..3a582ce2f3376 100644
--- a/sys/i386/ibcs2/ibcs2_ioctl.c
+++ b/sys/i386/ibcs2/ibcs2_ioctl.c
@@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/capability.h>
#include <sys/consio.h>
#include <sys/fcntl.h>
#include <sys/file.h>
@@ -333,7 +334,7 @@ ibcs2_ioctl(td, uap)
struct file *fp;
int error;
- if ((error = fget(td, uap->fd, &fp)) != 0) {
+ if ((error = fget(td, uap->fd, CAP_IOCTL, &fp)) != 0) {
DPRINTF(("ibcs2_ioctl(%d): bad fd %d ", p->p_pid,
uap->fd));
return EBADF;
diff --git a/sys/i386/ibcs2/ibcs2_misc.c b/sys/i386/ibcs2/ibcs2_misc.c
index c537100ba177d..a08fdf3914d1a 100644
--- a/sys/i386/ibcs2/ibcs2_misc.c
+++ b/sys/i386/ibcs2/ibcs2_misc.c
@@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$");
*/
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/capability.h>
#include <sys/dirent.h>
#include <sys/fcntl.h>
#include <sys/filedesc.h>
@@ -336,7 +337,8 @@ ibcs2_getdents(td, uap)
#define BSD_DIRENT(cp) ((struct dirent *)(cp))
#define IBCS2_RECLEN(reclen) (reclen + sizeof(u_short))
- if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
+ if ((error = getvnode(td->td_proc->p_fd, uap->fd,
+ CAP_READ | CAP_SEEK, &fp)) != 0)
return (error);
if ((fp->f_flag & FREAD) == 0) {
fdrop(fp, td);
@@ -492,7 +494,8 @@ ibcs2_read(td, uap)
u_long *cookies = NULL, *cookiep;
int ncookies;
- if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) {
+ if ((error = getvnode(td->td_proc->p_fd, uap->fd,
+ CAP_READ | CAP_SEEK, &fp)) != 0) {
if (error == EINVAL)
return read(td, (struct read_args *)uap);
else
diff --git a/sys/i386/ibcs2/imgact_coff.c b/sys/i386/ibcs2/imgact_coff.c
index 4a3cb95f8d4ba..44a243cac8354 100644
--- a/sys/i386/ibcs2/imgact_coff.c
+++ b/sys/i386/ibcs2/imgact_coff.c
@@ -91,9 +91,10 @@ load_coff_section(struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset,
map_len = round_page(offset + filsz) - trunc_page(map_offset);
}
- DPRINTF(("%s(%d): vm_mmap(&vmspace->vm_map, &0x%08lx, 0x%x, 0x%x, "
+ DPRINTF(("%s(%d): vm_mmap(&vmspace->vm_map, &0x%08jx, 0x%x, 0x%x, "
"VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED, OBJT_VNODE, vp, 0x%x)\n",
- __FILE__, __LINE__, map_addr, map_len, prot, map_offset));
+ __FILE__, __LINE__, (uintmax_t)map_addr, map_len, prot,
+ map_offset));
if ((error = vm_mmap(&vmspace->vm_map,
&map_addr,
@@ -123,16 +124,16 @@ load_coff_section(struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset,
map_addr = trunc_page((vm_offset_t)vmaddr + filsz);
map_len = round_page((vm_offset_t)vmaddr + memsz) - map_addr;
- DPRINTF(("%s(%d): vm_map_find(&vmspace->vm_map, NULL, 0, &0x%08lx,0x%x, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0)\n", __FILE__, __LINE__, map_addr, map_len));
+ DPRINTF(("%s(%d): vm_map_find(&vmspace->vm_map, NULL, 0, &0x%08jx,0x%x, VMFS_NO_SPACE, VM_PROT_ALL, VM_PROT_ALL, 0)\n", __FILE__, __LINE__, (uintmax_t)map_addr, map_len));
if (map_len != 0) {
error = vm_map_find(&vmspace->vm_map, NULL, 0, &map_addr,
- map_len, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0);
+ map_len, VMFS_NO_SPACE, VM_PROT_ALL, VM_PROT_ALL, 0);
if (error)
- return error;
+ return (vm_mmap_to_errno(error));
}
- if ((error = vm_mmap(kernel_map,
+ if ((error = vm_mmap(exec_map,
(vm_offset_t *) &data_buf,
PAGE_SIZE,
VM_PROT_READ,
@@ -145,7 +146,7 @@ load_coff_section(struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset,
error = copyout(data_buf, (caddr_t) map_addr, copy_len);
- if (vm_map_remove(kernel_map,
+ if (vm_map_remove(exec_map,
(vm_offset_t) data_buf,
(vm_offset_t) data_buf + PAGE_SIZE))
panic("load_coff_section vm_map_remove failed");
@@ -213,7 +214,7 @@ coff_load_file(struct thread *td, char *name)
*/
VOP_UNLOCK(vp, 0);
- if ((error = vm_mmap(kernel_map,
+ if ((error = vm_mmap(exec_map,
(vm_offset_t *) &ptr,
PAGE_SIZE,
VM_PROT_READ,
@@ -279,7 +280,7 @@ coff_load_file(struct thread *td, char *name)
error = 0;
dealloc_and_fail:
- if (vm_map_remove(kernel_map,
+ if (vm_map_remove(exec_map,
(vm_offset_t) ptr,
(vm_offset_t) ptr + PAGE_SIZE))
panic("%s vm_map_remove failed", __func__);
@@ -306,7 +307,7 @@ exec_coff_imgact(imgp)
unsigned long text_offset = 0, text_address = 0, text_size = 0;
unsigned long data_offset = 0, data_address = 0, data_size = 0;
unsigned long bss_size = 0;
- caddr_t hole;
+ vm_offset_t hole;
if (fhdr->f_magic != I386_COFF ||
!(fhdr->f_flags & F_EXEC)) {
@@ -343,9 +344,9 @@ exec_coff_imgact(imgp)
for (i = 0; i < nscns; i++) {
- DPRINTF(("i = %d, scns[i].s_name = %s, scns[i].s_vaddr = %08lx, "
- "scns[i].s_scnptr = %d\n", i, scns[i].s_name,
- scns[i].s_vaddr, scns[i].s_scnptr));
+ DPRINTF(("i = %d, s_name = %s, s_vaddr = %08lx, "
+ "s_scnptr = %ld s_size = %lx\n", i, scns[i].s_name,
+ scns[i].s_vaddr, scns[i].s_scnptr, scns[i].s_size));
if (scns[i].s_flags & STYP_NOLOAD) {
/*
* A section that is not loaded, for whatever
@@ -372,12 +373,12 @@ exec_coff_imgact(imgp)
int len = round_page(scns[i].s_size + PAGE_SIZE);
int j;
- if ((error = vm_mmap(kernel_map,
+ if ((error = vm_mmap(exec_map,
(vm_offset_t *) &buf,
len,
VM_PROT_READ,
VM_PROT_READ,
- 0,
+ MAP_SHARED,
OBJT_VNODE,
imgp->vp,
foff)) != 0) {
@@ -411,12 +412,16 @@ exec_coff_imgact(imgp)
error = coff_load_file(
FIRST_THREAD_IN_PROC(imgp->proc),
libname);
- if (error)
+ if (error) {
+ printf(
+ "error %d loading coff shared library %s\n",
+ error, libname);
break;
+ }
}
free(libbuf, M_TEMP);
}
- if (vm_map_remove(kernel_map,
+ if (vm_map_remove(exec_map,
(vm_offset_t) buf,
(vm_offset_t) buf + len))
panic("exec_coff_imgact vm_map_remove failed");
@@ -429,7 +434,7 @@ exec_coff_imgact(imgp)
*/
DPRINTF(("%s(%d): load_coff_section(vmspace, "
- "imgp->vp, %08lx, %08lx, 0x%x, 0x%x, 0x%x)\n",
+ "imgp->vp, %08lx, %08lx, 0x%lx, 0x%lx, 0x%x)\n",
__FILE__, __LINE__, text_offset, text_address,
text_size, text_size, VM_PROT_READ | VM_PROT_EXECUTE));
if ((error = load_coff_section(vmspace, imgp->vp,
@@ -446,7 +451,7 @@ exec_coff_imgact(imgp)
DPRINTF(("%s(%d): load_coff_section(vmspace, "
- "imgp->vp, 0x%08lx, 0x%08lx, 0x%x, 0x%x, 0x%x)\n",
+ "imgp->vp, 0x%08lx, 0x%08lx, 0x%lx, 0x%lx, 0x%x)\n",
__FILE__, __LINE__, data_offset, data_address,
data_size + bss_size, data_size, VM_PROT_ALL));
if ((error = load_coff_section(vmspace, imgp->vp,
@@ -467,26 +472,25 @@ exec_coff_imgact(imgp)
vmspace->vm_taddr = (caddr_t)(void *)(uintptr_t)text_address;
vmspace->vm_daddr = (caddr_t)(void *)(uintptr_t)data_address;
- hole = (caddr_t)trunc_page((vm_offset_t)vmspace->vm_daddr) + ctob(vmspace->vm_dsize);
-
+ hole = trunc_page((vm_offset_t)vmspace->vm_daddr +
+ ctob(vmspace->vm_dsize));
- DPRINTF(("%s(%d): vm_map_find(&vmspace->vm_map, NULL, 0, &0x%08lx, PAGE_SIZE, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0)\n",
- __FILE__, __LINE__, hole));
+ DPRINTF(("%s(%d): vm_map_find(&vmspace->vm_map, NULL, 0, &0x%jx, PAGE_SIZE, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0)\n",
+ __FILE__, __LINE__, (uintmax_t)hole));
DPRINTF(("imgact: error = %d\n", error));
- error = vm_map_find(&vmspace->vm_map, NULL, 0,
- (vm_offset_t *) &hole, PAGE_SIZE, FALSE,
- VM_PROT_ALL, VM_PROT_ALL, 0);
-
- DPRINTF(("IBCS2: start vm_dsize = 0x%x, vm_daddr = 0x%x end = 0x%x\n",
+ vm_map_find(&vmspace->vm_map, NULL, 0,
+ (vm_offset_t *)&hole, PAGE_SIZE, VMFS_NO_SPACE,
+ VM_PROT_ALL, VM_PROT_ALL, 0);
+ DPRINTF(("IBCS2: start vm_dsize = 0x%x, vm_daddr = 0x%p end = 0x%p\n",
ctob(vmspace->vm_dsize), vmspace->vm_daddr,
ctob(vmspace->vm_dsize) + vmspace->vm_daddr ));
- DPRINTF(("%s(%d): returning successfully!\n", __FILE__, __LINE__));
+ DPRINTF(("%s(%d): returning %d!\n", __FILE__, __LINE__, error));
fail:
vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY);
- return error;
+ return (error);
}
/*
diff --git a/sys/i386/include/param.h b/sys/i386/include/param.h
index d95fcf3fd087d..6a0495c4c9529 100644
--- a/sys/i386/include/param.h
+++ b/sys/i386/include/param.h
@@ -68,7 +68,9 @@
#define MID_MACHINE MID_I386
#if defined(SMP) || defined(KLD_MODULE)
+#ifndef MAXCPU
#define MAXCPU 32
+#endif
#else
#define MAXCPU 1
#endif /* SMP || KLD_MODULE */
diff --git a/sys/i386/linux/linux_machdep.c b/sys/i386/linux/linux_machdep.c
index d1f6ab99780c3..57756c4d3e83d 100644
--- a/sys/i386/linux/linux_machdep.c
+++ b/sys/i386/linux/linux_machdep.c
@@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/capability.h>
#include <sys/file.h>
#include <sys/fcntl.h>
#include <sys/imgact.h>
@@ -467,9 +468,12 @@ linux_mmap_common(struct thread *td, l_uintptr_t addr, l_size_t len, l_int prot,
* The file descriptor fildes is opened with
* read permission, regardless of the
* protection options specified.
+ *
+ * Checking just CAP_MMAP is fine here, since the real work
+ * is done in the FreeBSD mmap().
*/
- if ((error = fget(td, bsd_args.fd, &fp)) != 0)
+ if ((error = fget(td, bsd_args.fd, CAP_MMAP, &fp)) != 0)
return (error);
if (fp->f_type != DTYPE_VNODE) {
fdrop(fp, td);
diff --git a/sys/i386/xen/pmap.c b/sys/i386/xen/pmap.c
index b5e71da2cd818..b19f75c61b8ef 100644
--- a/sys/i386/xen/pmap.c
+++ b/sys/i386/xen/pmap.c
@@ -2037,7 +2037,7 @@ pmap_collect(pmap_t locked_pmap, struct vpgqueues *vpq)
KASSERT((tpte & PG_W) == 0,
("pmap_collect: wired pte %#jx", (uintmax_t)tpte));
if (tpte & PG_A)
- vm_page_flag_set(m, PG_REFERENCED);
+ vm_page_aflag_set(m, PGA_REFERENCED);
if ((tpte & (PG_M | PG_RW)) == (PG_M | PG_RW))
vm_page_dirty(m);
free = NULL;
@@ -2050,7 +2050,7 @@ pmap_collect(pmap_t locked_pmap, struct vpgqueues *vpq)
PMAP_UNLOCK(pmap);
}
if (TAILQ_EMPTY(&m->md.pv_list))
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
}
sched_unpin();
}
@@ -2222,7 +2222,7 @@ pmap_remove_entry(pmap_t pmap, vm_page_t m, vm_offset_t va)
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
pmap_pvh_free(&m->md, pmap, va);
if (TAILQ_EMPTY(&m->md.pv_list))
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
}
/*
@@ -2274,7 +2274,7 @@ pmap_remove_pte(pmap_t pmap, pt_entry_t *ptq, vm_offset_t va, vm_page_t *free)
if ((oldpte & (PG_M | PG_RW)) == (PG_M | PG_RW))
vm_page_dirty(m);
if (oldpte & PG_A)
- vm_page_flag_set(m, PG_REFERENCED);
+ vm_page_aflag_set(m, PGA_REFERENCED);
pmap_remove_entry(pmap, m, va);
}
return (pmap_unuse_pt(pmap, va, free));
@@ -2430,7 +2430,7 @@ pmap_remove_all(vm_page_t m)
pt_entry_t *pte, tpte;
vm_page_t free;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_remove_all: page %p is not managed", m));
free = NULL;
vm_page_lock_queues();
@@ -2446,7 +2446,7 @@ pmap_remove_all(vm_page_t m)
if (tpte & PG_W)
pmap->pm_stats.wired_count--;
if (tpte & PG_A)
- vm_page_flag_set(m, PG_REFERENCED);
+ vm_page_aflag_set(m, PGA_REFERENCED);
/*
* Update the vm_page_t clean and reference bits.
@@ -2459,7 +2459,7 @@ pmap_remove_all(vm_page_t m)
free_pv_entry(pmap, pv);
PMAP_UNLOCK(pmap);
}
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
PT_UPDATES_FLUSH();
if (*PMAP1)
PT_SET_MA(PADDR1, 0);
@@ -2616,8 +2616,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_prot_t access, vm_page_t m,
KASSERT(va < UPT_MIN_ADDRESS || va >= UPT_MAX_ADDRESS,
("pmap_enter: invalid to pmap_enter page table pages (va: 0x%x)",
va));
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0 ||
- (m->oflags & VPO_BUSY) != 0,
+ KASSERT((m->oflags & (VPO_UNMANAGED | VPO_BUSY)) != 0,
("pmap_enter: page %p is not busy", m));
mpte = NULL;
@@ -2715,7 +2714,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_prot_t access, vm_page_t m,
/*
* Enter on the PV list if part of our managed memory.
*/
- if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0) {
+ if ((m->oflags & VPO_UNMANAGED) == 0) {
KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva,
("pmap_enter: managed mapping within the clean submap"));
if (pv == NULL)
@@ -2740,7 +2739,7 @@ validate:
if ((prot & VM_PROT_WRITE) != 0) {
newpte |= PG_RW;
if ((newpte & PG_MANAGED) != 0)
- vm_page_flag_set(m, PG_WRITEABLE);
+ vm_page_aflag_set(m, PGA_WRITEABLE);
}
#ifdef PAE
if ((prot & VM_PROT_EXECUTE) == 0)
@@ -2765,7 +2764,7 @@ validate:
PT_SET_VA(pte, newpte | PG_A, FALSE);
if (origpte & PG_A) {
if (origpte & PG_MANAGED)
- vm_page_flag_set(om, PG_REFERENCED);
+ vm_page_aflag_set(om, PGA_REFERENCED);
if (opa != VM_PAGE_TO_PHYS(m))
invlva = TRUE;
#ifdef PAE
@@ -2782,7 +2781,7 @@ validate:
}
if ((origpte & PG_MANAGED) != 0 &&
TAILQ_EMPTY(&om->md.pv_list))
- vm_page_flag_clear(om, PG_WRITEABLE);
+ vm_page_aflag_clear(om, PGA_WRITEABLE);
if (invlva)
pmap_invalidate_page(pmap, va);
} else{
@@ -2915,7 +2914,7 @@ pmap_enter_quick_locked(multicall_entry_t **mclpp, int *count, pmap_t pmap, vm_o
multicall_entry_t *mcl = *mclpp;
KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva ||
- (m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0,
+ (m->oflags & VPO_UNMANAGED) != 0,
("pmap_enter_quick_locked: managed mapping within the clean submap"));
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
PMAP_LOCK_ASSERT(pmap, MA_OWNED);
@@ -2979,7 +2978,7 @@ pmap_enter_quick_locked(multicall_entry_t **mclpp, int *count, pmap_t pmap, vm_o
/*
* Enter on the PV list if part of our managed memory.
*/
- if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0 &&
+ if ((m->oflags & VPO_UNMANAGED) == 0 &&
!pmap_try_insert_pv_entry(pmap, va, m)) {
if (mpte != NULL) {
free = NULL;
@@ -3008,7 +3007,7 @@ pmap_enter_quick_locked(multicall_entry_t **mclpp, int *count, pmap_t pmap, vm_o
/*
* Now validate mapping with RO protection
*/
- if (m->flags & (PG_FICTITIOUS|PG_UNMANAGED))
+ if ((m->oflags & VPO_UNMANAGED) != 0)
pte_store(pte, pa | PG_V | PG_U);
else
pte_store(pte, pa | PG_V | PG_U | PG_MANAGED);
@@ -3016,7 +3015,7 @@ pmap_enter_quick_locked(multicall_entry_t **mclpp, int *count, pmap_t pmap, vm_o
/*
* Now validate mapping with RO protection
*/
- if (m->flags & (PG_FICTITIOUS|PG_UNMANAGED))
+ if ((m->oflags & VPO_UNMANAGED) != 0)
pa = xpmap_ptom(pa | PG_V | PG_U);
else
pa = xpmap_ptom(pa | PG_V | PG_U | PG_MANAGED);
@@ -3403,7 +3402,7 @@ pmap_page_exists_quick(pmap_t pmap, vm_page_t m)
int loops = 0;
boolean_t rv;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_page_exists_quick: page %p is not managed", m));
rv = FALSE;
vm_page_lock_queues();
@@ -3435,7 +3434,7 @@ pmap_page_wired_mappings(vm_page_t m)
int count;
count = 0;
- if ((m->flags & PG_FICTITIOUS) != 0)
+ if ((m->oflags & VPO_UNMANAGED) != 0)
return (count);
vm_page_lock_queues();
sched_pin();
@@ -3461,7 +3460,7 @@ pmap_page_is_mapped(vm_page_t m)
{
boolean_t rv;
- if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0)
+ if ((m->oflags & VPO_UNMANAGED) != 0)
return (FALSE);
vm_page_lock_queues();
rv = !TAILQ_EMPTY(&m->md.pv_list) ||
@@ -3550,7 +3549,7 @@ pmap_remove_pages(pmap_t pmap)
TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
if (TAILQ_EMPTY(&m->md.pv_list))
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
pmap_unuse_pt(pmap, pv->pv_va, &free);
@@ -3600,18 +3599,18 @@ pmap_is_modified(vm_page_t m)
pmap_t pmap;
boolean_t rv;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_is_modified: page %p is not managed", m));
rv = FALSE;
/*
- * If the page is not VPO_BUSY, then PG_WRITEABLE cannot be
- * concurrently set while the object is locked. Thus, if PG_WRITEABLE
+ * If the page is not VPO_BUSY, then PGA_WRITEABLE cannot be
+ * concurrently set while the object is locked. Thus, if PGA_WRITEABLE
* is clear, no PTEs can have PG_M set.
*/
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
if ((m->oflags & VPO_BUSY) == 0 &&
- (m->flags & PG_WRITEABLE) == 0)
+ (m->aflags & PGA_WRITEABLE) == 0)
return (rv);
vm_page_lock_queues();
sched_pin();
@@ -3671,7 +3670,7 @@ pmap_is_referenced(vm_page_t m)
pmap_t pmap;
boolean_t rv;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_is_referenced: page %p is not managed", m));
rv = FALSE;
vm_page_lock_queues();
@@ -3732,17 +3731,17 @@ pmap_remove_write(vm_page_t m)
pmap_t pmap;
pt_entry_t oldpte, *pte;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_remove_write: page %p is not managed", m));
/*
- * If the page is not VPO_BUSY, then PG_WRITEABLE cannot be set by
- * another thread while the object is locked. Thus, if PG_WRITEABLE
+ * If the page is not VPO_BUSY, then PGA_WRITEABLE cannot be set by
+ * another thread while the object is locked. Thus, if PGA_WRITEABLE
* is clear, no page table entries need updating.
*/
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
if ((m->oflags & VPO_BUSY) == 0 &&
- (m->flags & PG_WRITEABLE) == 0)
+ (m->aflags & PGA_WRITEABLE) == 0)
return;
vm_page_lock_queues();
sched_pin();
@@ -3770,7 +3769,7 @@ retry:
}
PMAP_UNLOCK(pmap);
}
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
PT_UPDATES_FLUSH();
if (*PMAP1)
PT_SET_MA(PADDR1, 0);
@@ -3798,7 +3797,7 @@ pmap_ts_referenced(vm_page_t m)
pt_entry_t *pte;
int rtval = 0;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_ts_referenced: page %p is not managed", m));
vm_page_lock_queues();
sched_pin();
@@ -3840,18 +3839,18 @@ pmap_clear_modify(vm_page_t m)
pmap_t pmap;
pt_entry_t *pte;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_clear_modify: page %p is not managed", m));
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
KASSERT((m->oflags & VPO_BUSY) == 0,
("pmap_clear_modify: page %p is busy", m));
/*
- * If the page is not PG_WRITEABLE, then no PTEs can have PG_M set.
+ * If the page is not PGA_WRITEABLE, then no PTEs can have PG_M set.
* If the object containing the page is locked and the page is not
- * VPO_BUSY, then PG_WRITEABLE cannot be concurrently set.
+ * VPO_BUSY, then PGA_WRITEABLE cannot be concurrently set.
*/
- if ((m->flags & PG_WRITEABLE) == 0)
+ if ((m->aflags & PGA_WRITEABLE) == 0)
return;
vm_page_lock_queues();
sched_pin();
@@ -3886,7 +3885,7 @@ pmap_clear_reference(vm_page_t m)
pmap_t pmap;
pt_entry_t *pte;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_clear_reference: page %p is not managed", m));
vm_page_lock_queues();
sched_pin();
diff --git a/sys/ia64/ia32/ia32_trap.c b/sys/ia64/ia32/ia32_trap.c
index 57f4791695609..6755358189a16 100644
--- a/sys/ia64/ia32/ia32_trap.c
+++ b/sys/ia64/ia32/ia32_trap.c
@@ -144,6 +144,8 @@ ia32_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
return (error);
}
+#include "../../kern/subr_syscall.c"
+
static void
ia32_syscall(struct trapframe *tf)
{
diff --git a/sys/ia64/ia64/dump_machdep.c b/sys/ia64/ia64/dump_machdep.c
index ae82c360c582c..734acc76e43be 100644
--- a/sys/ia64/ia64/dump_machdep.c
+++ b/sys/ia64/ia64/dump_machdep.c
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#endif
#include <vm/vm.h>
#include <vm/pmap.h>
+#include <machine/bootinfo.h>
#include <machine/efi.h>
#include <machine/elf.h>
#include <machine/md_var.h>
@@ -191,7 +192,8 @@ foreach_chunk(callback_t cb, void *arg)
seqnr = 0;
mdp = efi_md_first();
while (mdp != NULL) {
- if (mdp->md_type == EFI_MD_TYPE_FREE) {
+ if (mdp->md_type == EFI_MD_TYPE_FREE ||
+ mdp->md_type == EFI_MD_TYPE_DATA) {
error = (*cb)(mdp, seqnr++, arg);
if (error)
return (-error);
@@ -225,6 +227,7 @@ dumpsys(struct dumperinfo *di)
ehdr.e_ident[EI_OSABI] = ELFOSABI_STANDALONE; /* XXX big picture? */
ehdr.e_type = ET_CORE;
ehdr.e_machine = EM_IA_64;
+ ehdr.e_entry = ia64_tpa((uintptr_t)bootinfo);
ehdr.e_phoff = sizeof(ehdr);
ehdr.e_flags = EF_IA_64_ABSOLUTE; /* XXX misuse? */
ehdr.e_ehsize = sizeof(ehdr);
diff --git a/sys/ia64/ia64/locore.S b/sys/ia64/ia64/locore.S
index d4c1190f5d837..f79ca68f37ca1 100644
--- a/sys/ia64/ia64/locore.S
+++ b/sys/ia64/ia64/locore.S
@@ -207,13 +207,13 @@ intr_n = 1
intr_n = intr_n + 1
.endr
EXPORT(sintrnames)
- .word INTRCNT_COUNT * INTRNAME_LEN
+ data8 INTRCNT_COUNT * INTRNAME_LEN
.align 8
EXPORT(intrcnt)
.fill INTRCNT_COUNT, 8, 0
EXPORT(sintrcnt)
- .word INTRCNT_COUNT
+ data8 INTRCNT_COUNT * 8
.text
// in0: image base
diff --git a/sys/ia64/ia64/pmap.c b/sys/ia64/ia64/pmap.c
index 0e34f36ccaca3..37116f5af198f 100644
--- a/sys/ia64/ia64/pmap.c
+++ b/sys/ia64/ia64/pmap.c
@@ -804,7 +804,7 @@ retry:
pmap_invalidate_page(va);
pmap_switch(oldpmap);
if (pmap_accessed(pte))
- vm_page_flag_set(m, PG_REFERENCED);
+ vm_page_aflag_set(m, PGA_REFERENCED);
if (pmap_dirty(pte))
vm_page_dirty(m);
pmap_free_pte(pte, va);
@@ -819,7 +819,7 @@ retry:
free_pv_entry(pv);
}
if (TAILQ_EMPTY(&m->md.pv_list))
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
}
if (allocated_pv == NULL) {
if (vpq == &vm_page_queues[PQ_INACTIVE]) {
@@ -972,7 +972,7 @@ pmap_remove_entry(pmap_t pmap, vm_page_t m, vm_offset_t va, pv_entry_t pv)
TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
m->md.pv_list_count--;
if (TAILQ_FIRST(&m->md.pv_list) == NULL)
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
TAILQ_REMOVE(&pmap->pm_pvlist, pv, pv_plist);
free_pv_entry(pv);
@@ -1198,7 +1198,7 @@ pmap_remove_pte(pmap_t pmap, struct ia64_lpte *pte, vm_offset_t va,
if (pmap_dirty(pte))
vm_page_dirty(m);
if (pmap_accessed(pte))
- vm_page_flag_set(m, PG_REFERENCED);
+ vm_page_aflag_set(m, PGA_REFERENCED);
error = pmap_remove_entry(pmap, m, va, pv);
}
@@ -1217,43 +1217,54 @@ pmap_kextract(vm_offset_t va)
{
struct ia64_lpte *pte;
uint64_t *pbvm_pgtbl;
+ vm_paddr_t pa;
u_int idx;
KASSERT(va >= VM_MAXUSER_ADDRESS, ("Must be kernel VA"));
/* Regions 6 and 7 are direct mapped. */
- if (va >= IA64_RR_BASE(6))
- return (IA64_RR_MASK(va));
+ if (va >= IA64_RR_BASE(6)) {
+ pa = IA64_RR_MASK(va);
+ goto out;
+ }
- /* Bail out if the virtual address is beyond our limits. */
+ /* Region 5 is our KVA. Bail out if the VA is beyond our limits. */
if (va >= kernel_vm_end)
- return (0);
-
+ goto err_out;
if (va >= VM_MIN_KERNEL_ADDRESS) {
pte = pmap_find_kpte(va);
- return (pmap_present(pte) ? pmap_ppn(pte)|(va&PAGE_MASK) : 0);
+ pa = pmap_present(pte) ? pmap_ppn(pte) | (va & PAGE_MASK) : 0;
+ goto out;
}
- /* PBVM page table. */
- if (va >= IA64_PBVM_PGTBL + bootinfo->bi_pbvm_pgtblsz);
- return (0);
- if (va >= IA64_PBVM_PGTBL)
- return (va - IA64_PBVM_PGTBL) + bootinfo->bi_pbvm_pgtbl;
+ /* The PBVM page table. */
+ if (va >= IA64_PBVM_PGTBL + bootinfo->bi_pbvm_pgtblsz)
+ goto err_out;
+ if (va >= IA64_PBVM_PGTBL) {
+ pa = (va - IA64_PBVM_PGTBL) + bootinfo->bi_pbvm_pgtbl;
+ goto out;
+ }
- /* PBVM. */
+ /* The PBVM itself. */
if (va >= IA64_PBVM_BASE) {
pbvm_pgtbl = (void *)IA64_PBVM_PGTBL;
idx = (va - IA64_PBVM_BASE) >> IA64_PBVM_PAGE_SHIFT;
if (idx >= (bootinfo->bi_pbvm_pgtblsz >> 3))
- return (0);
+ goto err_out;
if ((pbvm_pgtbl[idx] & PTE_PRESENT) == 0)
- return (0);
- return ((pbvm_pgtbl[idx] & PTE_PPN_MASK) +
- (va & IA64_PBVM_PAGE_MASK));
+ goto err_out;
+ pa = (pbvm_pgtbl[idx] & PTE_PPN_MASK) +
+ (va & IA64_PBVM_PAGE_MASK);
+ goto out;
}
- printf("XXX: %s: va=%#lx\n", __func__, va);
- return (0);
+ err_out:
+ printf("XXX: %s: va=%#lx is invalid\n", __func__, va);
+ pa = 0;
+ /* FALLTHROUGH */
+
+ out:
+ return (pa);
}
/*
@@ -1431,7 +1442,7 @@ pmap_remove_all(vm_page_t m)
pmap_t oldpmap;
pv_entry_t pv;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_remove_all: page %p is not managed", m));
vm_page_lock_queues();
while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) {
@@ -1449,7 +1460,7 @@ pmap_remove_all(vm_page_t m)
pmap_switch(oldpmap);
PMAP_UNLOCK(pmap);
}
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
vm_page_unlock_queues();
}
@@ -1537,8 +1548,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_prot_t access, vm_page_t m,
va &= ~PAGE_MASK;
KASSERT(va <= VM_MAX_KERNEL_ADDRESS, ("pmap_enter: toobig"));
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0 ||
- (m->oflags & VPO_BUSY) != 0,
+ KASSERT((m->oflags & (VPO_UNMANAGED | VPO_BUSY)) != 0,
("pmap_enter: page %p is not busy", m));
/*
@@ -1608,7 +1618,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_prot_t access, vm_page_t m,
/*
* Enter on the PV list if part of our managed memory.
*/
- if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0) {
+ if ((m->oflags & VPO_UNMANAGED) == 0) {
KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva,
("pmap_enter: managed mapping within the clean submap"));
pmap_insert_entry(pmap, va, m);
@@ -1637,7 +1647,7 @@ validate:
ia64_sync_icache(va, PAGE_SIZE);
if ((prot & VM_PROT_WRITE) != 0 && managed)
- vm_page_flag_set(m, PG_WRITEABLE);
+ vm_page_aflag_set(m, PGA_WRITEABLE);
vm_page_unlock_queues();
pmap_switch(oldpmap);
PMAP_UNLOCK(pmap);
@@ -1709,7 +1719,7 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m,
boolean_t managed;
KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva ||
- (m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0,
+ (m->oflags & VPO_UNMANAGED) != 0,
("pmap_enter_quick_locked: managed mapping within the clean submap"));
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
PMAP_LOCK_ASSERT(pmap, MA_OWNED);
@@ -1719,7 +1729,7 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m,
if (!pmap_present(pte)) {
/* Enter on the PV list if the page is managed. */
- if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0) {
+ if ((m->oflags & VPO_UNMANAGED) == 0) {
if (!pmap_try_insert_pv_entry(pmap, va, m)) {
pmap_free_pte(pte, va);
return;
@@ -1889,7 +1899,7 @@ pmap_page_exists_quick(pmap_t pmap, vm_page_t m)
int loops = 0;
boolean_t rv;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_page_exists_quick: page %p is not managed", m));
rv = FALSE;
vm_page_lock_queues();
@@ -1921,7 +1931,7 @@ pmap_page_wired_mappings(vm_page_t m)
int count;
count = 0;
- if ((m->flags & PG_FICTITIOUS) != 0)
+ if ((m->oflags & VPO_UNMANAGED) != 0)
return (count);
vm_page_lock_queues();
TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
@@ -1999,7 +2009,7 @@ pmap_ts_referenced(vm_page_t m)
pv_entry_t pv;
int count = 0;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_ts_referenced: page %p is not managed", m));
vm_page_lock_queues();
TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
@@ -2033,18 +2043,18 @@ pmap_is_modified(vm_page_t m)
pv_entry_t pv;
boolean_t rv;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_is_modified: page %p is not managed", m));
rv = FALSE;
/*
- * If the page is not VPO_BUSY, then PG_WRITEABLE cannot be
- * concurrently set while the object is locked. Thus, if PG_WRITEABLE
+ * If the page is not VPO_BUSY, then PGA_WRITEABLE cannot be
+ * concurrently set while the object is locked. Thus, if PGA_WRITEABLE
* is clear, no PTEs can be dirty.
*/
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
if ((m->oflags & VPO_BUSY) == 0 &&
- (m->flags & PG_WRITEABLE) == 0)
+ (m->aflags & PGA_WRITEABLE) == 0)
return (rv);
vm_page_lock_queues();
TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
@@ -2093,7 +2103,7 @@ pmap_is_referenced(vm_page_t m)
pv_entry_t pv;
boolean_t rv;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_is_referenced: page %p is not managed", m));
rv = FALSE;
vm_page_lock_queues();
@@ -2122,18 +2132,18 @@ pmap_clear_modify(vm_page_t m)
pmap_t oldpmap;
pv_entry_t pv;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_clear_modify: page %p is not managed", m));
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
KASSERT((m->oflags & VPO_BUSY) == 0,
("pmap_clear_modify: page %p is busy", m));
/*
- * If the page is not PG_WRITEABLE, then no PTEs can be modified.
+ * If the page is not PGA_WRITEABLE, then no PTEs can be modified.
* If the object containing the page is locked and the page is not
- * VPO_BUSY, then PG_WRITEABLE cannot be concurrently set.
+ * VPO_BUSY, then PGA_WRITEABLE cannot be concurrently set.
*/
- if ((m->flags & PG_WRITEABLE) == 0)
+ if ((m->aflags & PGA_WRITEABLE) == 0)
return;
vm_page_lock_queues();
TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
@@ -2163,7 +2173,7 @@ pmap_clear_reference(vm_page_t m)
pmap_t oldpmap;
pv_entry_t pv;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_clear_reference: page %p is not managed", m));
vm_page_lock_queues();
TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
@@ -2192,17 +2202,17 @@ pmap_remove_write(vm_page_t m)
pv_entry_t pv;
vm_prot_t prot;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_remove_write: page %p is not managed", m));
/*
- * If the page is not VPO_BUSY, then PG_WRITEABLE cannot be set by
- * another thread while the object is locked. Thus, if PG_WRITEABLE
+ * If the page is not VPO_BUSY, then PGA_WRITEABLE cannot be set by
+ * another thread while the object is locked. Thus, if PGA_WRITEABLE
* is clear, no page table entries need updating.
*/
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
if ((m->oflags & VPO_BUSY) == 0 &&
- (m->flags & PG_WRITEABLE) == 0)
+ (m->aflags & PGA_WRITEABLE) == 0)
return;
vm_page_lock_queues();
TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
@@ -2225,7 +2235,7 @@ pmap_remove_write(vm_page_t m)
pmap_switch(oldpmap);
PMAP_UNLOCK(pmap);
}
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
vm_page_unlock_queues();
}
diff --git a/sys/ia64/ia64/trap.c b/sys/ia64/ia64/trap.c
index 4b84f769340e0..d587b05868fd6 100644
--- a/sys/ia64/ia64/trap.c
+++ b/sys/ia64/ia64/trap.c
@@ -929,6 +929,8 @@ cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
return (0);
}
+#include "../../kern/subr_syscall.c"
+
/*
* Process a system call.
*
diff --git a/sys/ia64/include/param.h b/sys/ia64/include/param.h
index 36b27e048903d..d996441f6246f 100644
--- a/sys/ia64/include/param.h
+++ b/sys/ia64/include/param.h
@@ -62,7 +62,9 @@
#endif
#if defined(SMP) || defined(KLD_MODULE)
-#define MAXCPU 32
+#ifndef MAXCPU
+#define MAXCPU 64
+#endif
#else
#define MAXCPU 1
#endif
diff --git a/sys/kern/capabilities.conf b/sys/kern/capabilities.conf
index f9a6b242d99b0..4a62643623eb7 100644
--- a/sys/kern/capabilities.conf
+++ b/sys/kern/capabilities.conf
@@ -196,7 +196,7 @@ fpathconf
##
## Allow various file descriptor-based I/O operations, subject to capability
-## rights. mmap(2) requires further attention.
+## rights.
##
freebsd6_ftruncate
freebsd6_lseek
@@ -239,9 +239,7 @@ getcontext
## Allow directory I/O on a file descriptor, subject to capability rights.
## Originally we had separate capabilities for directory-specific read
## operations, but on BSD we allow reading the raw directory data, so we just
-## rely on CAP_READ (etc) now.
-##
-## XXXRW: Possibly these should also use CAP_SEEK.
+## rely on CAP_READ and CAP_SEEK now.
##
getdents
getdirentries
@@ -336,8 +334,6 @@ issetugid
## Allow kevent(2), as we will authorize based on capability rights on the
## target descriptor.
##
-## XXXRW: Do we do this?
-##
kevent
##
@@ -406,9 +402,6 @@ mlockall
## Allow memory mapping a file descriptor, and updating protections, subject
## to capability rights.
##
-## XXXRW: We currently don't properly mask VM protections using capability
-## rights.
-##
mmap
mprotect
@@ -447,28 +440,26 @@ obreak
olio_listio
##
-## Once Capsicum is fully merged, some of the *at(2) calls which can be
-## semantically constrained will be permitted in capability mode. For now,
-## we will simply not allow them to be called.
+## Operations relative to directory capabilities.
##
-#faccessat
-#fstatat
-#fchmodat
-#futimesat
-#mkdirat
-#rmdirat
-#mkfifoat
-#mknodat
-#openat
-#renameat
+faccessat
+fstatat
+fchmodat
+futimesat
+mkdirat
+rmdirat
+mkfifoat
+mknodat
+openat
+renameat
##
-## ONCE CAPSICUM IS FULLY MERGED:
-## Allow entry into open(2). This system call will fail, since access to the global
-## file namespace has been disallowed, but allowing entry into the syscall means
-## that an audit trail will be generated (which is also very useful for debugging),
+## Allow entry into open(2). This system call will fail, since access to the
+## global file namespace has been disallowed, but allowing entry into the
+## syscall means that an audit trail will be generated (which is also very
+## useful for debugging).
##
-#open
+open
##
## Allow poll(2), which will be scoped by capability rights.
@@ -484,7 +475,7 @@ openbsd_poll
pdfork
pdgetpid
pdkill
-pdwait4
+#pdwait4 # not yet implemented
##
## Allow pipe(2).
@@ -648,11 +639,9 @@ setsockopt
setuid
##
-## ONCE CAPSICUM IS FULLY MERGED:
-## Allow shm_open(2), which is scoped so as to allow only access to new
-## anonymous objects.
+## shm_open(2) is scoped so as to allow only access to new anonymous objects.
##
-#shm_open
+shm_open
##
## Allow I/O-related file descriptors, subject to capability rights.
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index be5c26fec029b..fc072457c1916 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -790,7 +790,8 @@ create_init(const void *udata __unused)
struct ucred *newcred, *oldcred;
int error;
- error = fork1(&thread0, RFFDG | RFPROC | RFSTOPPED, 0, &initproc);
+ error = fork1(&thread0, RFFDG | RFPROC | RFSTOPPED, 0, &initproc,
+ NULL, 0);
if (error)
panic("cannot fork init: %d\n", error);
KASSERT(initproc->p_pid == 1, ("create_init: initproc->p_pid != 1"));
diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c
index 004516b6e8ded..d1063f4e83e15 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
+ * created from FreeBSD: head/sys/kern/syscalls.master 224987 2011-08-18 22:51:30Z jonathan
*/
#include "opt_compat.h"
@@ -39,7 +39,7 @@ struct sysent sysent[] = {
{ 0, (sy_call_t *)fork, AUE_FORK, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 2 = fork */
{ AS(read_args), (sy_call_t *)read, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 3 = read */
{ AS(write_args), (sy_call_t *)write, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 4 = write */
- { AS(open_args), (sy_call_t *)open, AUE_OPEN_RWTC, NULL, 0, 0, 0, SY_THR_STATIC }, /* 5 = open */
+ { AS(open_args), (sy_call_t *)open, AUE_OPEN_RWTC, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 5 = open */
{ AS(close_args), (sy_call_t *)close, AUE_CLOSE, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 6 = close */
{ AS(wait_args), (sy_call_t *)wait4, AUE_WAIT4, NULL, 0, 0, 0, SY_THR_STATIC }, /* 7 = wait4 */
{ compat(AS(ocreat_args),creat), AUE_CREAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 8 = old creat */
@@ -516,26 +516,26 @@ struct sysent sysent[] = {
{ AS(truncate_args), (sy_call_t *)truncate, AUE_TRUNCATE, NULL, 0, 0, 0, SY_THR_STATIC }, /* 479 = truncate */
{ AS(ftruncate_args), (sy_call_t *)ftruncate, AUE_FTRUNCATE, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 480 = ftruncate */
{ AS(thr_kill2_args), (sy_call_t *)thr_kill2, AUE_KILL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 481 = thr_kill2 */
- { AS(shm_open_args), (sy_call_t *)shm_open, AUE_SHMOPEN, NULL, 0, 0, 0, SY_THR_STATIC }, /* 482 = shm_open */
+ { AS(shm_open_args), (sy_call_t *)shm_open, AUE_SHMOPEN, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 482 = shm_open */
{ AS(shm_unlink_args), (sy_call_t *)shm_unlink, AUE_SHMUNLINK, NULL, 0, 0, 0, SY_THR_STATIC }, /* 483 = shm_unlink */
{ AS(cpuset_args), (sy_call_t *)cpuset, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 484 = cpuset */
{ AS(cpuset_setid_args), (sy_call_t *)cpuset_setid, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 485 = cpuset_setid */
{ AS(cpuset_getid_args), (sy_call_t *)cpuset_getid, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 486 = cpuset_getid */
{ AS(cpuset_getaffinity_args), (sy_call_t *)cpuset_getaffinity, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 487 = cpuset_getaffinity */
{ AS(cpuset_setaffinity_args), (sy_call_t *)cpuset_setaffinity, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 488 = cpuset_setaffinity */
- { AS(faccessat_args), (sy_call_t *)faccessat, AUE_FACCESSAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 489 = faccessat */
- { AS(fchmodat_args), (sy_call_t *)fchmodat, AUE_FCHMODAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 490 = fchmodat */
+ { AS(faccessat_args), (sy_call_t *)faccessat, AUE_FACCESSAT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 489 = faccessat */
+ { AS(fchmodat_args), (sy_call_t *)fchmodat, AUE_FCHMODAT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 490 = fchmodat */
{ AS(fchownat_args), (sy_call_t *)fchownat, AUE_FCHOWNAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 491 = fchownat */
{ AS(fexecve_args), (sy_call_t *)fexecve, AUE_FEXECVE, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 492 = fexecve */
- { AS(fstatat_args), (sy_call_t *)fstatat, AUE_FSTATAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 493 = fstatat */
- { AS(futimesat_args), (sy_call_t *)futimesat, AUE_FUTIMESAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 494 = futimesat */
+ { AS(fstatat_args), (sy_call_t *)fstatat, AUE_FSTATAT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 493 = fstatat */
+ { AS(futimesat_args), (sy_call_t *)futimesat, AUE_FUTIMESAT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 494 = futimesat */
{ AS(linkat_args), (sy_call_t *)linkat, AUE_LINKAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 495 = linkat */
- { AS(mkdirat_args), (sy_call_t *)mkdirat, AUE_MKDIRAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 496 = mkdirat */
- { AS(mkfifoat_args), (sy_call_t *)mkfifoat, AUE_MKFIFOAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 497 = mkfifoat */
- { AS(mknodat_args), (sy_call_t *)mknodat, AUE_MKNODAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 498 = mknodat */
- { AS(openat_args), (sy_call_t *)openat, AUE_OPENAT_RWTC, NULL, 0, 0, 0, SY_THR_STATIC }, /* 499 = openat */
+ { AS(mkdirat_args), (sy_call_t *)mkdirat, AUE_MKDIRAT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 496 = mkdirat */
+ { AS(mkfifoat_args), (sy_call_t *)mkfifoat, AUE_MKFIFOAT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 497 = mkfifoat */
+ { AS(mknodat_args), (sy_call_t *)mknodat, AUE_MKNODAT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 498 = mknodat */
+ { AS(openat_args), (sy_call_t *)openat, AUE_OPENAT_RWTC, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 499 = openat */
{ AS(readlinkat_args), (sy_call_t *)readlinkat, AUE_READLINKAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 500 = readlinkat */
- { AS(renameat_args), (sy_call_t *)renameat, AUE_RENAMEAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 501 = renameat */
+ { AS(renameat_args), (sy_call_t *)renameat, AUE_RENAMEAT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 501 = renameat */
{ AS(symlinkat_args), (sy_call_t *)symlinkat, AUE_SYMLINKAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 502 = symlinkat */
{ AS(unlinkat_args), (sy_call_t *)unlinkat, AUE_UNLINKAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 503 = unlinkat */
{ AS(posix_openpt_args), (sy_call_t *)posix_openpt, AUE_POSIX_OPENPT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 504 = posix_openpt */
@@ -552,10 +552,10 @@ struct sysent sysent[] = {
{ AS(cap_getrights_args), (sy_call_t *)cap_getrights, AUE_CAP_GETRIGHTS, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 515 = cap_getrights */
{ 0, (sy_call_t *)cap_enter, AUE_CAP_ENTER, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 516 = cap_enter */
{ AS(cap_getmode_args), (sy_call_t *)cap_getmode, AUE_CAP_GETMODE, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 517 = cap_getmode */
- { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 518 = pdfork */
- { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 519 = pdkill */
- { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 520 = pdgetpid */
- { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 521 = pdwait */
+ { AS(pdfork_args), (sy_call_t *)pdfork, AUE_PDFORK, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 518 = pdfork */
+ { AS(pdkill_args), (sy_call_t *)pdkill, AUE_PDKILL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 519 = pdkill */
+ { AS(pdgetpid_args), (sy_call_t *)pdgetpid, AUE_PDGETPID, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 520 = pdgetpid */
+ { 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 521 = pdwait4 */
{ AS(pselect_args), (sy_call_t *)pselect, AUE_SELECT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 522 = pselect */
{ AS(getloginclass_args), (sy_call_t *)getloginclass, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 523 = getloginclass */
{ AS(setloginclass_args), (sy_call_t *)setloginclass, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 524 = setloginclass */
diff --git a/sys/kern/kern_conf.c b/sys/kern/kern_conf.c
index a4d90c78218e4..8da16d288b3eb 100644
--- a/sys/kern/kern_conf.c
+++ b/sys/kern/kern_conf.c
@@ -764,7 +764,8 @@ make_dev_credv(int flags, struct cdev **dres, struct cdevsw *devsw, int unit,
LIST_REMOVE(dev, si_list);
dev_unlock();
devfs_free(dev);
- }
+ } else
+ dev_unlock();
return (res);
}
}
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 829ece218b099..4aaed1f040e8d 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
#include "opt_compat.h"
#include "opt_ddb.h"
#include "opt_ktrace.h"
+#include "opt_procdesc.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -65,6 +66,7 @@ __FBSDID("$FreeBSD$");
#include <sys/pipe.h>
#include <sys/priv.h>
#include <sys/proc.h>
+#include <sys/procdesc.h>
#include <sys/protosw.h>
#include <sys/racct.h>
#include <sys/resourcevar.h>
@@ -120,6 +122,8 @@ static int fill_vnode_info(struct vnode *vp, struct kinfo_file *kif);
static int fill_socket_info(struct socket *so, struct kinfo_file *kif);
static int fill_pts_info(struct tty *tp, struct kinfo_file *kif);
static int fill_pipe_info(struct pipe *pi, struct kinfo_file *kif);
+static int fill_procdesc_info(struct procdesc *pdp,
+ struct kinfo_file *kif);
/*
* A process is initially started out with NDFILE descriptors stored within
@@ -431,6 +435,26 @@ fdtofp(int fd, struct filedesc *fdp)
return (fp);
}
+static inline int
+fdunwrap(int fd, cap_rights_t rights, struct filedesc *fdp, struct file **fpp)
+{
+
+ *fpp = fdtofp(fd, fdp);
+ if (*fpp == NULL)
+ return (EBADF);
+
+#ifdef CAPABILITIES
+ if ((*fpp)->f_type == DTYPE_CAPABILITY) {
+ int err = cap_funwrap(*fpp, rights, fpp);
+ if (err != 0) {
+ *fpp = NULL;
+ return (err);
+ }
+ }
+#endif /* CAPABILITIES */
+ return (0);
+}
+
int
kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
{
@@ -489,9 +513,9 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
case F_GETFL:
FILEDESC_SLOCK(fdp);
- if ((fp = fdtofp(fd, fdp)) == NULL) {
+ error = fdunwrap(fd, CAP_FCNTL, fdp, &fp);
+ if (error != 0) {
FILEDESC_SUNLOCK(fdp);
- error = EBADF;
break;
}
td->td_retval[0] = OFLAGS(fp->f_flag);
@@ -500,9 +524,9 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
case F_SETFL:
FILEDESC_SLOCK(fdp);
- if ((fp = fdtofp(fd, fdp)) == NULL) {
+ error = fdunwrap(fd, CAP_FCNTL, fdp, &fp);
+ if (error != 0) {
FILEDESC_SUNLOCK(fdp);
- error = EBADF;
break;
}
fhold(fp);
@@ -532,9 +556,9 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
case F_GETOWN:
FILEDESC_SLOCK(fdp);
- if ((fp = fdtofp(fd, fdp)) == NULL) {
+ error = fdunwrap(fd, CAP_FCNTL, fdp, &fp);
+ if (error != 0) {
FILEDESC_SUNLOCK(fdp);
- error = EBADF;
break;
}
fhold(fp);
@@ -547,9 +571,9 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
case F_SETOWN:
FILEDESC_SLOCK(fdp);
- if ((fp = fdtofp(fd, fdp)) == NULL) {
+ error = fdunwrap(fd, CAP_FCNTL, fdp, &fp);
+ if (error != 0) {
FILEDESC_SUNLOCK(fdp);
- error = EBADF;
break;
}
fhold(fp);
@@ -573,9 +597,9 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
case F_SETLK:
do_setlk:
FILEDESC_SLOCK(fdp);
- if ((fp = fdtofp(fd, fdp)) == NULL) {
+ error = fdunwrap(fd, CAP_FLOCK, fdp, &fp);
+ if (error != 0) {
FILEDESC_SUNLOCK(fdp);
- error = EBADF;
break;
}
if (fp->f_type != DTYPE_VNODE) {
@@ -668,9 +692,9 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
case F_GETLK:
FILEDESC_SLOCK(fdp);
- if ((fp = fdtofp(fd, fdp)) == NULL) {
+ error = fdunwrap(fd, CAP_FLOCK, fdp, &fp);
+ if (error != 0) {
FILEDESC_SUNLOCK(fdp);
- error = EBADF;
break;
}
if (fp->f_type != DTYPE_VNODE) {
@@ -1312,7 +1336,7 @@ kern_fstat(struct thread *td, int fd, struct stat *sbp)
AUDIT_ARG_FD(fd);
- if ((error = fget(td, fd, &fp)) != 0)
+ if ((error = fget(td, fd, CAP_FSTAT, &fp)) != 0)
return (error);
AUDIT_ARG_FILE(td->td_proc, fp);
@@ -1368,7 +1392,7 @@ fpathconf(struct thread *td, struct fpathconf_args *uap)
struct vnode *vp;
int error;
- if ((error = fget(td, uap->fd, &fp)) != 0)
+ if ((error = fget(td, uap->fd, CAP_FPATHCONF, &fp)) != 0)
return (error);
/* If asynchronous I/O is available, it works for all descriptors. */
@@ -2294,7 +2318,7 @@ fget_unlocked(struct filedesc *fdp, int fd)
#define FGET_GETCAP 0x00000001
static __inline int
_fget(struct thread *td, int fd, struct file **fpp, int flags,
- cap_rights_t needrights, cap_rights_t *haverights, u_char *maxprotp,
+ cap_rights_t needrights, cap_rights_t *haverightsp, u_char *maxprotp,
int fget_flags)
{
struct filedesc *fdp;
@@ -2316,6 +2340,16 @@ _fget(struct thread *td, int fd, struct file **fpp, int flags,
#ifdef CAPABILITIES
/*
+ * If this is a capability, what rights does it have?
+ */
+ if (haverightsp != NULL) {
+ if (fp->f_type == DTYPE_CAPABILITY)
+ *haverightsp = cap_rights(fp);
+ else
+ *haverightsp = CAP_MASK_VALID;
+ }
+
+ /*
* If a capability has been requested, return the capability directly.
* Otherwise, check capability rights, extract the underlying object,
* and check its access flags.
@@ -2369,28 +2403,36 @@ _fget(struct thread *td, int fd, struct file **fpp, int flags,
}
int
-fget(struct thread *td, int fd, struct file **fpp)
+fget(struct thread *td, int fd, cap_rights_t rights, struct file **fpp)
+{
+
+ return(_fget(td, fd, fpp, 0, rights, NULL, NULL, 0));
+}
+
+int
+fget_mmap(struct thread *td, int fd, cap_rights_t rights, u_char *maxprotp,
+ struct file **fpp)
{
- return(_fget(td, fd, fpp, 0, 0, NULL, NULL, 0));
+ return (_fget(td, fd, fpp, 0, rights, NULL, maxprotp, 0));
}
int
-fget_read(struct thread *td, int fd, struct file **fpp)
+fget_read(struct thread *td, int fd, cap_rights_t rights, struct file **fpp)
{
- return(_fget(td, fd, fpp, FREAD, 0, NULL, NULL, 0));
+ return(_fget(td, fd, fpp, FREAD, rights, NULL, NULL, 0));
}
int
-fget_write(struct thread *td, int fd, struct file **fpp)
+fget_write(struct thread *td, int fd, cap_rights_t rights, struct file **fpp)
{
- return(_fget(td, fd, fpp, FWRITE, 0, NULL, NULL, 0));
+ return (_fget(td, fd, fpp, FWRITE, rights, NULL, NULL, 0));
}
/*
- * Unlike the other fget() calls, which will accept and check capability rights
+ * Unlike the other fget() calls, which accept and check capability rights
* but never return capabilities, fgetcap() returns the capability but doesn't
* check capability rights.
*/
@@ -2410,13 +2452,15 @@ fgetcap(struct thread *td, int fd, struct file **fpp)
* XXX: what about the unused flags ?
*/
static __inline int
-_fgetvp(struct thread *td, int fd, struct vnode **vpp, int flags)
+_fgetvp(struct thread *td, int fd, int flags, cap_rights_t needrights,
+ cap_rights_t *haverightsp, struct vnode **vpp)
{
struct file *fp;
int error;
*vpp = NULL;
- if ((error = _fget(td, fd, &fp, flags, 0, NULL, NULL, 0)) != 0)
+ if ((error = _fget(td, fd, &fp, flags, needrights, haverightsp,
+ NULL, 0)) != 0)
return (error);
if (fp->f_vnode == NULL) {
error = EINVAL;
@@ -2430,25 +2474,33 @@ _fgetvp(struct thread *td, int fd, struct vnode **vpp, int flags)
}
int
-fgetvp(struct thread *td, int fd, struct vnode **vpp)
+fgetvp(struct thread *td, int fd, cap_rights_t rights, struct vnode **vpp)
{
- return (_fgetvp(td, fd, vpp, 0));
+ return (_fgetvp(td, fd, 0, rights, NULL, vpp));
}
int
-fgetvp_read(struct thread *td, int fd, struct vnode **vpp)
+fgetvp_rights(struct thread *td, int fd, cap_rights_t need, cap_rights_t *have,
+ struct vnode **vpp)
+{
+ return (_fgetvp(td, fd, 0, need, have, vpp));
+}
+
+int
+fgetvp_read(struct thread *td, int fd, cap_rights_t rights, struct vnode **vpp)
{
- return (_fgetvp(td, fd, vpp, FREAD));
+ return (_fgetvp(td, fd, FREAD, rights, NULL, vpp));
}
#ifdef notyet
int
-fgetvp_write(struct thread *td, int fd, struct vnode **vpp)
+fgetvp_write(struct thread *td, int fd, cap_rights_t rights,
+ struct vnode **vpp)
{
- return (_fgetvp(td, fd, vpp, FWRITE));
+ return (_fgetvp(td, fd, FWRITE, rights, NULL, vpp));
}
#endif
@@ -2464,7 +2516,8 @@ fgetvp_write(struct thread *td, int fd, struct vnode **vpp)
* during use.
*/
int
-fgetsock(struct thread *td, int fd, struct socket **spp, u_int *fflagp)
+fgetsock(struct thread *td, int fd, cap_rights_t rights, struct socket **spp,
+ u_int *fflagp)
{
struct file *fp;
int error;
@@ -2472,7 +2525,7 @@ fgetsock(struct thread *td, int fd, struct socket **spp, u_int *fflagp)
*spp = NULL;
if (fflagp != NULL)
*fflagp = 0;
- if ((error = _fget(td, fd, &fp, 0, 0, NULL, NULL, 0)) != 0)
+ if ((error = _fget(td, fd, &fp, 0, rights, NULL, NULL, 0)) != 0)
return (error);
if (fp->f_type != DTYPE_SOCKET) {
error = ENOTSOCK;
@@ -2557,7 +2610,7 @@ flock(struct thread *td, struct flock_args *uap)
int vfslocked;
int error;
- if ((error = fget(td, uap->fd, &fp)) != 0)
+ if ((error = fget(td, uap->fd, CAP_FLOCK, &fp)) != 0)
return (error);
if (fp->f_type != DTYPE_VNODE) {
fdrop(fp, td);
@@ -2946,6 +2999,22 @@ sysctl_kern_proc_ofiledesc(SYSCTL_HANDLER_ARGS)
so = NULL;
tp = NULL;
kif->kf_fd = i;
+
+#ifdef CAPABILITIES
+ /*
+ * When reporting a capability, most fields will be from the
+ * underlying object, but do mark as a capability. With
+ * ofiledesc, we don't have a field to export the cap_rights_t,
+ * but we do with the new filedesc.
+ */
+ if (fp->f_type == DTYPE_CAPABILITY) {
+ kif->kf_flags |= KF_FLAG_CAPABILITY;
+ (void)cap_funwrap(fp, 0, &fp);
+ }
+#else
+ KASSERT(fp->f_type != DTYPE_CAPABILITY,
+ ("sysctl_kern_proc_ofiledesc: saw capability"));
+#endif
switch (fp->f_type) {
case DTYPE_VNODE:
kif->kf_type = KF_TYPE_VNODE;
@@ -2991,6 +3060,12 @@ sysctl_kern_proc_ofiledesc(SYSCTL_HANDLER_ARGS)
tp = fp->f_data;
break;
+#ifdef PROCDESC
+ case DTYPE_PROCDESC:
+ kif->kf_type = KF_TYPE_PROCDESC;
+ break;
+#endif
+
default:
kif->kf_type = KF_TYPE_UNKNOWN;
break;
@@ -3153,6 +3228,9 @@ export_fd_for_sysctl(void *data, int type, int fd, int fflags, int refcnt,
case KF_TYPE_PTS:
error = fill_pts_info((struct tty *)data, kif);
break;
+ case KF_TYPE_PROCDESC:
+ error = fill_procdesc_info((struct procdesc *)data, kif);
+ break;
default:
error = 0;
}
@@ -3262,6 +3340,22 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS)
if ((fp = fdp->fd_ofiles[i]) == NULL)
continue;
data = NULL;
+
+#ifdef CAPABILITIES
+ /*
+ * When reporting a capability, most fields will be from the
+ * underlying object, but do mark as a capability and export
+ * the capability rights mask.
+ */
+ if (fp->f_type == DTYPE_CAPABILITY) {
+ kif->kf_flags |= KF_FLAG_CAPABILITY;
+ kif->kf_cap_rights = cap_rights(fp);
+ (void)cap_funwrap(fp, 0, &fp);
+ }
+#else /* !CAPABILITIES */
+ KASSERT(fp->f_type != DTYPE_CAPABILITY,
+ ("sysctl_kern_proc_filedesc: saw capability"));
+#endif
switch (fp->f_type) {
case DTYPE_VNODE:
type = KF_TYPE_VNODE;
@@ -3310,6 +3404,13 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS)
data = fp->f_data;
break;
+#ifdef PROCDESC
+ case DTYPE_PROCDESC:
+ type = KF_TYPE_PROCDESC;
+ data = fp->f_data;
+ break;
+#endif
+
default:
type = KF_TYPE_UNKNOWN;
break;
@@ -3505,6 +3606,16 @@ fill_pipe_info(struct pipe *pi, struct kinfo_file *kif)
return (0);
}
+static int
+fill_procdesc_info(struct procdesc *pdp, struct kinfo_file *kif)
+{
+
+ if (pdp == NULL)
+ return (1);
+ kif->kf_un.kf_proc.kf_pid = pdp->pd_pid;
+ return (0);
+}
+
static SYSCTL_NODE(_kern_proc, KERN_PROC_FILEDESC, filedesc, CTLFLAG_RD,
sysctl_kern_proc_filedesc, "Process filedesc entries");
@@ -3693,6 +3804,22 @@ badfo_close(struct file *fp, struct thread *td)
return (EBADF);
}
+static int
+badfo_chmod(struct file *fp, mode_t mode, struct ucred *active_cred,
+ struct thread *td)
+{
+
+ return (EBADF);
+}
+
+static int
+badfo_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred,
+ struct thread *td)
+{
+
+ return (EBADF);
+}
+
struct fileops badfileops = {
.fo_read = badfo_readwrite,
.fo_write = badfo_readwrite,
@@ -3702,8 +3829,25 @@ struct fileops badfileops = {
.fo_kqfilter = badfo_kqfilter,
.fo_stat = badfo_stat,
.fo_close = badfo_close,
+ .fo_chmod = badfo_chmod,
+ .fo_chown = badfo_chown,
};
+int
+invfo_chmod(struct file *fp, mode_t mode, struct ucred *active_cred,
+ struct thread *td)
+{
+
+ return (EINVAL);
+}
+
+int
+invfo_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred,
+ struct thread *td)
+{
+
+ return (EINVAL);
+}
/*-------------------------------------------------------------------*/
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index e14ae0211bc6c..dc11411fd5df2 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/capability.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/mutex.h>
@@ -122,6 +123,8 @@ static struct fileops kqueueops = {
.fo_kqfilter = kqueue_kqfilter,
.fo_stat = kqueue_stat,
.fo_close = kqueue_close,
+ .fo_chmod = invfo_chmod,
+ .fo_chown = invfo_chown,
};
static int knote_attach(struct knote *kn, struct kqueue *kq);
@@ -816,7 +819,7 @@ kern_kevent(struct thread *td, int fd, int nchanges, int nevents,
struct file *fp;
int i, n, nerrors, error;
- if ((error = fget(td, fd, &fp)) != 0)
+ if ((error = fget(td, fd, CAP_POST_EVENT, &fp)) != 0)
return (error);
if ((error = kqueue_acquire(fp, &kq)) != 0)
goto done_norel;
@@ -972,7 +975,7 @@ kqueue_register(struct kqueue *kq, struct kevent *kev, struct thread *td, int wa
findkn:
if (fops->f_isfd) {
KASSERT(td != NULL, ("td is NULL"));
- error = fget(td, kev->ident, &fp);
+ error = fget(td, kev->ident, CAP_POLL_EVENT, &fp);
if (error)
goto done;
@@ -1701,6 +1704,7 @@ kqueue_close(struct file *fp, struct thread *td)
SLIST_REMOVE(&fdp->fd_kqlist, kq, kqueue, kq_list);
FILEDESC_XUNLOCK(fdp);
+ seldrain(&kq->kq_sel);
knlist_destroy(&kq->kq_sel.si_note);
mtx_destroy(&kq->kq_lock);
kq->kq_fdp = NULL;
@@ -2181,7 +2185,7 @@ kqfd_register(int fd, struct kevent *kev, struct thread *td, int waitok)
struct file *fp;
int error;
- if ((error = fget(td, fd, &fp)) != 0)
+ if ((error = fget(td, fd, CAP_POST_EVENT, &fp)) != 0)
return (error);
if ((error = kqueue_acquire(fp, &kq)) != 0)
goto noacquire;
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index f7f80af68c25a..1c424204800f2 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -439,7 +439,11 @@ interpret:
imgp->vp = binvp;
} else {
AUDIT_ARG_FD(args->fd);
- error = fgetvp(td, args->fd, &binvp);
+ /*
+ * Some might argue that CAP_READ and/or CAP_MMAP should also
+ * be required here; such arguments will be entertained.
+ */
+ error = fgetvp_read(td, args->fd, CAP_FEXECVE, &binvp);
if (error)
goto exec_fail;
vfslocked = VFS_LOCK_GIANT(binvp->v_mount);
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 30b94b6a28a40..e5d60942f7c07 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -40,16 +40,19 @@ __FBSDID("$FreeBSD$");
#include "opt_compat.h"
#include "opt_kdtrace.h"
#include "opt_ktrace.h"
+#include "opt_procdesc.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sysproto.h>
+#include <sys/capability.h>
#include <sys/eventhandler.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/proc.h>
+#include <sys/procdesc.h>
#include <sys/pioctl.h>
#include <sys/jail.h>
#include <sys/tty.h>
@@ -461,39 +464,54 @@ exit1(struct thread *td, int rv)
knlist_clear(&p->p_klist, 1);
/*
- * Notify parent that we're gone. If parent has the PS_NOCLDWAIT
- * flag set, or if the handler is set to SIG_IGN, notify process
- * 1 instead (and hope it will handle this situation).
+ * If this is a process with a descriptor, we may not need to deliver
+ * a signal to the parent. proctree_lock is held over
+ * procdesc_exit() to serialize concurrent calls to close() and
+ * exit().
*/
- PROC_LOCK(p->p_pptr);
- mtx_lock(&p->p_pptr->p_sigacts->ps_mtx);
- if (p->p_pptr->p_sigacts->ps_flag & (PS_NOCLDWAIT | PS_CLDSIGIGN)) {
- struct proc *pp;
-
- mtx_unlock(&p->p_pptr->p_sigacts->ps_mtx);
- pp = p->p_pptr;
- PROC_UNLOCK(pp);
- proc_reparent(p, initproc);
- p->p_sigparent = SIGCHLD;
- PROC_LOCK(p->p_pptr);
-
+#ifdef PROCDESC
+ if (p->p_procdesc == NULL || procdesc_exit(p)) {
+#endif
/*
- * Notify parent, so in case he was wait(2)ing or
- * executing waitpid(2) with our pid, he will
- * continue.
+ * Notify parent that we're gone. If parent has the
+ * PS_NOCLDWAIT flag set, or if the handler is set to SIG_IGN,
+ * notify process 1 instead (and hope it will handle this
+ * situation).
*/
- wakeup(pp);
- } else
- mtx_unlock(&p->p_pptr->p_sigacts->ps_mtx);
+ PROC_LOCK(p->p_pptr);
+ mtx_lock(&p->p_pptr->p_sigacts->ps_mtx);
+ if (p->p_pptr->p_sigacts->ps_flag &
+ (PS_NOCLDWAIT | PS_CLDSIGIGN)) {
+ struct proc *pp;
- if (p->p_pptr == initproc)
- psignal(p->p_pptr, SIGCHLD);
- else if (p->p_sigparent != 0) {
- if (p->p_sigparent == SIGCHLD)
- childproc_exited(p);
- else /* LINUX thread */
- psignal(p->p_pptr, p->p_sigparent);
- }
+ mtx_unlock(&p->p_pptr->p_sigacts->ps_mtx);
+ pp = p->p_pptr;
+ PROC_UNLOCK(pp);
+ proc_reparent(p, initproc);
+ p->p_sigparent = SIGCHLD;
+ PROC_LOCK(p->p_pptr);
+
+ /*
+ * Notify parent, so in case he was wait(2)ing or
+ * executing waitpid(2) with our pid, he will
+ * continue.
+ */
+ wakeup(pp);
+ } else
+ mtx_unlock(&p->p_pptr->p_sigacts->ps_mtx);
+
+ if (p->p_pptr == initproc)
+ psignal(p->p_pptr, SIGCHLD);
+ else if (p->p_sigparent != 0) {
+ if (p->p_sigparent == SIGCHLD)
+ childproc_exited(p);
+ else /* LINUX thread */
+ psignal(p->p_pptr, p->p_sigparent);
+ }
+#ifdef PROCDESC
+ } else
+ PROC_LOCK(p->p_pptr);
+#endif
sx_xunlock(&proctree_lock);
/*
@@ -660,7 +678,7 @@ wait4(struct thread *td, struct wait_args *uap)
* rusage. Asserts and will release both the proctree_lock and the process
* lock as part of its work.
*/
-static void
+void
proc_reap(struct thread *td, struct proc *p, int *status, int options,
struct rusage *rusage)
{
@@ -722,6 +740,10 @@ proc_reap(struct thread *td, struct proc *p, int *status, int options,
sx_xunlock(&allproc_lock);
LIST_REMOVE(p, p_sibling);
leavepgrp(p);
+#ifdef PROCDESC
+ if (p->p_procdesc != NULL)
+ procdesc_reap(p);
+#endif
sx_xunlock(&proctree_lock);
/*
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index 9d3e22d224cf7..32d00550a8157 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -40,11 +40,13 @@ __FBSDID("$FreeBSD$");
#include "opt_kdtrace.h"
#include "opt_ktrace.h"
#include "opt_kstack_pages.h"
+#include "opt_procdesc.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sysproto.h>
#include <sys/eventhandler.h>
+#include <sys/fcntl.h>
#include <sys/filedesc.h>
#include <sys/jail.h>
#include <sys/kernel.h>
@@ -55,6 +57,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mutex.h>
#include <sys/priv.h>
#include <sys/proc.h>
+#include <sys/procdesc.h>
#include <sys/pioctl.h>
#include <sys/racct.h>
#include <sys/resourcevar.h>
@@ -104,7 +107,7 @@ fork(struct thread *td, struct fork_args *uap)
int error;
struct proc *p2;
- error = fork1(td, RFFDG | RFPROC, 0, &p2);
+ error = fork1(td, RFFDG | RFPROC, 0, &p2, NULL, 0);
if (error == 0) {
td->td_retval[0] = p2->p_pid;
td->td_retval[1] = 0;
@@ -112,6 +115,34 @@ fork(struct thread *td, struct fork_args *uap)
return (error);
}
+/* ARGUSED */
+int
+pdfork(td, uap)
+ struct thread *td;
+ struct pdfork_args *uap;
+{
+#ifdef PROCDESC
+ int error, fd;
+ struct proc *p2;
+
+ /*
+ * It is necessary to return fd by reference because 0 is a valid file
+ * descriptor number, and the child needs to be able to distinguish
+ * itself from the parent using the return value.
+ */
+ error = fork1(td, RFFDG | RFPROC | RFPROCDESC, 0, &p2,
+ &fd, uap->flags);
+ if (error == 0) {
+ td->td_retval[0] = p2->p_pid;
+ td->td_retval[1] = 0;
+ error = copyout(&fd, uap->fdp, sizeof(fd));
+ }
+ return (error);
+#else
+ return (ENOSYS);
+#endif
+}
+
/* ARGSUSED */
int
vfork(struct thread *td, struct vfork_args *uap)
@@ -124,7 +155,7 @@ vfork(struct thread *td, struct vfork_args *uap)
#else
flags = RFFDG | RFPROC | RFPPWAIT | RFMEM;
#endif
- error = fork1(td, flags, 0, &p2);
+ error = fork1(td, flags, 0, &p2, NULL, 0);
if (error == 0) {
td->td_retval[0] = p2->p_pid;
td->td_retval[1] = 0;
@@ -143,7 +174,7 @@ rfork(struct thread *td, struct rfork_args *uap)
return (EINVAL);
AUDIT_ARG_FFLAGS(uap->flags);
- error = fork1(td, uap->flags, 0, &p2);
+ error = fork1(td, uap->flags, 0, &p2, NULL, 0);
if (error == 0) {
td->td_retval[0] = p2 ? p2->p_pid : 0;
td->td_retval[1] = 0;
@@ -337,7 +368,7 @@ fail:
static void
do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2,
- struct vmspace *vm2)
+ struct vmspace *vm2, int pdflags)
{
struct proc *p1, *pptr;
int p2_held, trypid;
@@ -625,6 +656,16 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2,
p2->p_vmspace->vm_ssize);
}
+#ifdef PROCDESC
+ /*
+ * Associate the process descriptor with the process before anything
+ * can happen that might cause that process to need the descriptor.
+ * However, don't do this until after fork(2) can no longer fail.
+ */
+ if (flags & RFPROCDESC)
+ procdesc_new(p2, pdflags);
+#endif
+
/*
* Both processes are set up, now check if any loadable modules want
* to adjust anything.
@@ -710,7 +751,8 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2,
}
int
-fork1(struct thread *td, int flags, int pages, struct proc **procp)
+fork1(struct thread *td, int flags, int pages, struct proc **procp,
+ int *procdescp, int pdflags)
{
struct proc *p1;
struct proc *newproc;
@@ -721,6 +763,9 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp)
int error;
static int curfail;
static struct timeval lastfail;
+#ifdef PROCDESC
+ struct file *fp_procdesc = NULL;
+#endif
/* Check for the undefined or unimplemented flags. */
if ((flags & ~(RFFLAGS | RFTSIGFLAGS(RFTSIGMASK))) != 0)
@@ -738,6 +783,18 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp)
if ((flags & RFTSIGZMB) != 0 && (u_int)RFTSIGNUM(flags) > _SIG_MAXSIG)
return (EINVAL);
+#ifdef PROCDESC
+ if ((flags & RFPROCDESC) != 0) {
+ /* Can't not create a process yet get a process descriptor. */
+ if ((flags & RFPROC) == 0)
+ return (EINVAL);
+
+ /* Must provide a place to put a procdesc if creating one. */
+ if (procdescp == NULL)
+ return (EINVAL);
+ }
+#endif
+
p1 = td->td_proc;
/*
@@ -757,6 +814,25 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp)
return (EAGAIN);
#endif
+#ifdef PROCDESC
+ /*
+ * If required, create a process descriptor in the parent first; we
+ * will abandon it if something goes wrong. We don't finit() until
+ * later.
+ */
+ if (flags & RFPROCDESC) {
+ error = falloc(td, &fp_procdesc, procdescp, 0);
+ if (error != 0) {
+#ifdef RACCT
+ PROC_LOCK(p1);
+ racct_sub(p1, RACCT_NPROC, 1);
+ PROC_UNLOCK(p1);
+#endif
+ return (error);
+ }
+ }
+#endif
+
mem_charged = 0;
vm2 = NULL;
if (pages == 0)
@@ -868,12 +944,16 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp)
PROC_UNLOCK(p1);
}
if (ok) {
- do_fork(td, flags, newproc, td2, vm2);
+ do_fork(td, flags, newproc, td2, vm2, pdflags);
/*
* Return child proc pointer to parent.
*/
*procp = newproc;
+#ifdef PROCDESC
+ if (flags & RFPROCDESC)
+ procdesc_finit(newproc->p_procdesc, fp_procdesc);
+#endif
return (0);
}
@@ -892,6 +972,10 @@ fail1:
if (vm2 != NULL)
vmspace_free(vm2);
uma_zfree(proc_zone, newproc);
+#ifdef PROCDESC
+ if (((flags & RFPROCDESC) != 0) && (fp_procdesc != NULL))
+ fdrop(fp_procdesc, td);
+#endif
pause("fork", hz / 2);
#ifdef RACCT
PROC_LOCK(p1);
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
index 358d67394e4e9..8ce8327bde154 100644
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -540,8 +540,8 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
#ifdef INET6
int ip6s, redo_ip6;
#endif
- unsigned pr_flags, ch_flags;
- unsigned pr_allow, ch_allow, tallow;
+ uint64_t pr_allow, ch_allow, pr_flags, ch_flags;
+ unsigned tallow;
char numbuf[12];
error = priv_check(td, PRIV_JAIL_SET);
@@ -2470,32 +2470,11 @@ prison_deref(struct prison *pr, int flags)
if (!(flags & PD_LOCKED))
mtx_lock(&pr->pr_mtx);
- /* Decrement the user references in a separate loop. */
- if (flags & PD_DEUREF) {
- for (tpr = pr;; tpr = tpr->pr_parent) {
- if (tpr != pr)
- mtx_lock(&tpr->pr_mtx);
- if (--tpr->pr_uref > 0)
- break;
- KASSERT(tpr != &prison0, ("prison0 pr_uref=0"));
- mtx_unlock(&tpr->pr_mtx);
- }
- /* Done if there were only user references to remove. */
- if (!(flags & PD_DEREF)) {
- mtx_unlock(&tpr->pr_mtx);
- if (flags & PD_LIST_SLOCKED)
- sx_sunlock(&allprison_lock);
- else if (flags & PD_LIST_XLOCKED)
- sx_xunlock(&allprison_lock);
- return;
- }
- if (tpr != pr) {
- mtx_unlock(&tpr->pr_mtx);
- mtx_lock(&pr->pr_mtx);
- }
- }
-
for (;;) {
+ if (flags & PD_DEUREF) {
+ pr->pr_uref--;
+ KASSERT(prison0.pr_uref != 0, ("prison0 pr_uref=0"));
+ }
if (flags & PD_DEREF)
pr->pr_ref--;
/* If the prison still has references, nothing else to do. */
@@ -2551,7 +2530,7 @@ prison_deref(struct prison *pr, int flags)
/* Removing a prison frees a reference on its parent. */
pr = ppr;
mtx_lock(&pr->pr_mtx);
- flags = PD_DEREF;
+ flags = PD_DEREF | PD_DEUREF;
}
}
@@ -3858,7 +3837,8 @@ prison_priv_check(struct ucred *cred, int priv)
case PRIV_VFS_UNMOUNT:
case PRIV_VFS_MOUNT_NONUSER:
case PRIV_VFS_MOUNT_OWNER:
- if (cred->cr_prison->pr_allow & PR_ALLOW_MOUNT)
+ if (cred->cr_prison->pr_allow & PR_ALLOW_MOUNT &&
+ cred->cr_prison->pr_enforce_statfs < 2)
return (0);
else
return (EPERM);
diff --git a/sys/kern/kern_kthread.c b/sys/kern/kern_kthread.c
index 95f896fa5aa68..bb1246980d5b3 100644
--- a/sys/kern/kern_kthread.c
+++ b/sys/kern/kern_kthread.c
@@ -88,7 +88,7 @@ kproc_create(void (*func)(void *), void *arg,
panic("kproc_create called too soon");
error = fork1(&thread0, RFMEM | RFFDG | RFPROC | RFSTOPPED | flags,
- pages, &p2);
+ pages, &p2, NULL, 0);
if (error)
return error;
diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c
index f91925475b295..4337c953713e9 100644
--- a/sys/kern/kern_linker.c
+++ b/sys/kern/kern_linker.c
@@ -1116,8 +1116,9 @@ kern_kldunload(struct thread *td, int fileid, int flags)
PMC_CALL_HOOK(td, PMC_FN_KLD_UNLOAD, (void *) &pkm);
KLD_UNLOCK_READ();
} else
-#else
KLD_UNLOCK();
+#else
+ KLD_UNLOCK();
#endif
CURVNET_RESTORE();
return (error);
diff --git a/sys/kern/kern_lock.c b/sys/kern/kern_lock.c
index 8e5546ee30717..73118726e3ab8 100644
--- a/sys/kern/kern_lock.c
+++ b/sys/kern/kern_lock.c
@@ -477,8 +477,18 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk,
return (0);
}
- if (op == LK_SHARED && (lk->lock_object.lo_flags & LK_NOSHARE))
- op = LK_EXCLUSIVE;
+ if (lk->lock_object.lo_flags & LK_NOSHARE) {
+ switch (op) {
+ case LK_SHARED:
+ op = LK_EXCLUSIVE;
+ break;
+ case LK_UPGRADE:
+ case LK_DOWNGRADE:
+ _lockmgr_assert(lk, KA_XLOCKED | KA_NOTRECURSED,
+ file, line);
+ return (0);
+ }
+ }
wakeup_swapper = 0;
switch (op) {
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index 4f1dc4567f181..c84c5ae776dbf 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -848,12 +848,14 @@ fill_kinfo_thread(struct thread *td, struct kinfo_proc *kp, int preferthread)
kp->ki_tdaddr = td;
PROC_LOCK_ASSERT(p, MA_OWNED);
+ if (preferthread)
+ PROC_SLOCK(p);
thread_lock(td);
if (td->td_wmesg != NULL)
strlcpy(kp->ki_wmesg, td->td_wmesg, sizeof(kp->ki_wmesg));
else
bzero(kp->ki_wmesg, sizeof(kp->ki_wmesg));
- strlcpy(kp->ki_ocomm, td->td_name, sizeof(kp->ki_ocomm));
+ strlcpy(kp->ki_tdname, td->td_name, sizeof(kp->ki_tdname));
if (TD_ON_LOCK(td)) {
kp->ki_kiflag |= KI_LOCKBLOCK;
strlcpy(kp->ki_lockname, td->td_lockname,
@@ -899,6 +901,7 @@ fill_kinfo_thread(struct thread *td, struct kinfo_proc *kp, int preferthread)
kp->ki_pri.pri_user = td->td_user_pri;
if (preferthread) {
+ rufetchtd(td, &kp->ki_rusage);
kp->ki_runtime = cputick2usec(td->td_rux.rux_runtime);
kp->ki_pctcpu = sched_pctcpu(td);
kp->ki_estcpu = td->td_estcpu;
@@ -911,6 +914,8 @@ fill_kinfo_thread(struct thread *td, struct kinfo_proc *kp, int preferthread)
kp->ki_siglist = td->td_siglist;
kp->ki_sigmask = td->td_sigmask;
thread_unlock(td);
+ if (preferthread)
+ PROC_SUNLOCK(p);
}
/*
@@ -1054,7 +1059,7 @@ freebsd32_kinfo_proc_out(const struct kinfo_proc *ki, struct kinfo_proc32 *ki32)
CP(*ki, *ki32, ki_rqindex);
CP(*ki, *ki32, ki_oncpu);
CP(*ki, *ki32, ki_lastcpu);
- bcopy(ki->ki_ocomm, ki32->ki_ocomm, OCOMMLEN + 1);
+ bcopy(ki->ki_tdname, ki32->ki_tdname, TDNAMLEN + 1);
bcopy(ki->ki_wmesg, ki32->ki_wmesg, WMESGLEN + 1);
bcopy(ki->ki_login, ki32->ki_login, LOGNAMELEN + 1);
bcopy(ki->ki_lockname, ki32->ki_lockname, LOCKNAMELEN + 1);
@@ -1386,7 +1391,7 @@ sysctl_kern_proc_args(SYSCTL_HANDLER_ARGS)
pa = p->p_args;
pargs_hold(pa);
PROC_UNLOCK(p);
- if (req->oldptr != NULL && pa != NULL)
+ if (pa != NULL)
error = SYSCTL_OUT(req, pa->ar_args, pa->ar_length);
pargs_drop(pa);
if (error != 0 || req->newptr == NULL)
diff --git a/sys/kern/kern_racct.c b/sys/kern/kern_racct.c
index 401ce1dce9d5f..b12b7c776ab88 100644
--- a/sys/kern/kern_racct.c
+++ b/sys/kern/kern_racct.c
@@ -605,6 +605,7 @@ out:
void
racct_proc_exit(struct proc *p)
{
+ int i;
uint64_t runtime;
PROC_LOCK(p);
@@ -618,14 +619,18 @@ racct_proc_exit(struct proc *p)
if (runtime < p->p_prev_runtime)
runtime = p->p_prev_runtime;
#endif
- racct_set(p, RACCT_CPU, runtime);
+ mtx_lock(&racct_lock);
+ racct_set_locked(p, RACCT_CPU, runtime);
- /*
- * XXX: Free this some other way.
- */
- racct_set(p, RACCT_NPTS, 0);
- racct_set(p, RACCT_NTHR, 0);
- racct_set(p, RACCT_RSS, 0);
+ for (i = 0; i <= RACCT_MAX; i++) {
+ if (p->p_racct->r_resources[i] == 0)
+ continue;
+ if (!RACCT_IS_RECLAIMABLE(i))
+ continue;
+ racct_set_locked(p, i, 0);
+ }
+
+ mtx_unlock(&racct_lock);
PROC_UNLOCK(p);
#ifdef RCTL
diff --git a/sys/kern/kern_rctl.c b/sys/kern/kern_rctl.c
index a939758bc18d4..d60cae44205d5 100644
--- a/sys/kern/kern_rctl.c
+++ b/sys/kern/kern_rctl.c
@@ -363,6 +363,17 @@ rctl_enforce(struct proc *p, int resource, uint64_t amount)
rule->rr_action));
/*
+ * We're supposed to send a signal, but the process
+ * is not fully initialized yet, probably because we
+ * got called from fork1(). For now just deny the
+ * allocation instead.
+ */
+ if (p->p_state != PRS_NORMAL) {
+ should_deny = 1;
+ continue;
+ }
+
+ /*
* We're using the fact that RCTL_ACTION_SIG* values
* are equal to their counterparts from sys/signal.h.
*/
@@ -908,7 +919,7 @@ rctl_string_to_rule(char *rulestr, struct rctl_rule **rulep)
if (error != 0)
goto out;
if (RACCT_IS_IN_MILLIONS(rule->rr_resource))
- rule->rr_amount *= 1000;
+ rule->rr_amount *= 1000000;
}
if (perstr == NULL || perstr[0] == '\0')
@@ -1223,7 +1234,7 @@ rctl_racct_to_sbuf(struct racct *racct, int sloppy)
continue;
amount = racct->r_resources[i];
if (RACCT_IS_IN_MILLIONS(i))
- amount /= 1000;
+ amount /= 1000000;
sbuf_printf(sb, "%s=%jd,", rctl_resource_name(i), amount);
}
sbuf_setpos(sb, sbuf_len(sb) - 1);
diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c
index 1062703b682b2..78a25ebaad99d 100644
--- a/sys/kern/kern_resource.c
+++ b/sys/kern/kern_resource.c
@@ -813,7 +813,7 @@ void
calcru(struct proc *p, struct timeval *up, struct timeval *sp)
{
struct thread *td;
- uint64_t u;
+ uint64_t runtime, u;
PROC_LOCK_ASSERT(p, MA_OWNED);
PROC_SLOCK_ASSERT(p, MA_OWNED);
@@ -826,7 +826,9 @@ calcru(struct proc *p, struct timeval *up, struct timeval *sp)
td = curthread;
if (td->td_proc == p) {
u = cpu_ticks();
- p->p_rux.rux_runtime += u - PCPU_GET(switchtime);
+ runtime = u - PCPU_GET(switchtime);
+ td->td_runtime += runtime;
+ td->td_incruntime += runtime;
PCPU_SET(switchtime, u);
}
/* Make sure the per-thread stats are current. */
@@ -838,6 +840,34 @@ calcru(struct proc *p, struct timeval *up, struct timeval *sp)
calcru1(p, &p->p_rux, up, sp);
}
+/* Collect resource usage for a single thread. */
+void
+rufetchtd(struct thread *td, struct rusage *ru)
+{
+ struct proc *p;
+ uint64_t runtime, u;
+
+ p = td->td_proc;
+ PROC_SLOCK_ASSERT(p, MA_OWNED);
+ THREAD_LOCK_ASSERT(td, MA_OWNED);
+ /*
+ * If we are getting stats for the current thread, then add in the
+ * stats that this thread has accumulated in its current time slice.
+ * We reset the thread and CPU state as if we had performed a context
+ * switch right here.
+ */
+ if (td == curthread) {
+ u = cpu_ticks();
+ runtime = u - PCPU_GET(switchtime);
+ td->td_runtime += runtime;
+ td->td_incruntime += runtime;
+ PCPU_SET(switchtime, u);
+ }
+ ruxagg(p, td);
+ *ru = td->td_ru;
+ calcru1(p, &td->td_rux, &ru->ru_utime, &ru->ru_stime);
+}
+
static void
calcru1(struct proc *p, struct rusage_ext *ruxp, struct timeval *up,
struct timeval *sp)
@@ -955,12 +985,10 @@ kern_getrusage(struct thread *td, int who, struct rusage *rup)
case RUSAGE_THREAD:
PROC_SLOCK(p);
- ruxagg(p, td);
- PROC_SUNLOCK(p);
thread_lock(td);
- *rup = td->td_ru;
- calcru1(p, &td->td_rux, &rup->ru_utime, &rup->ru_stime);
+ rufetchtd(td, rup);
thread_unlock(td);
+ PROC_SUNLOCK(p);
break;
default:
diff --git a/sys/kern/kern_shutdown.c b/sys/kern/kern_shutdown.c
index 60e854fe340c0..c1e3dda4fb19c 100644
--- a/sys/kern/kern_shutdown.c
+++ b/sys/kern/kern_shutdown.c
@@ -40,7 +40,6 @@ __FBSDID("$FreeBSD$");
#include "opt_ddb.h"
#include "opt_kdb.h"
#include "opt_panic.h"
-#include "opt_show_busybufs.h"
#include "opt_sched.h"
#include "opt_watchdog.h"
@@ -66,6 +65,7 @@ __FBSDID("$FreeBSD$");
#include <sys/smp.h>
#include <sys/sysctl.h>
#include <sys/sysproto.h>
+#include <sys/vnode.h>
#ifdef SW_WATCHDOG
#include <sys/watchdog.h>
#endif
@@ -123,6 +123,14 @@ TUNABLE_INT("kern.sync_on_panic", &sync_on_panic);
SYSCTL_NODE(_kern, OID_AUTO, shutdown, CTLFLAG_RW, 0, "Shutdown environment");
+#ifndef DIAGNOSTIC
+static int show_busybufs;
+#else
+static int show_busybufs = 1;
+#endif
+SYSCTL_INT(_kern_shutdown, OID_AUTO, show_busybufs, CTLFLAG_RW,
+ &show_busybufs, 0, "");
+
/*
* Variable panicstr contains argument to first call to panic; used as flag
* to indicate that the kernel has already called panic.
@@ -389,13 +397,17 @@ kern_reboot(int howto)
}
#endif
nbusy++;
-#if defined(SHOW_BUSYBUFS) || defined(DIAGNOSTIC)
- printf(
- "%d: bufobj:%p, flags:%0x, blkno:%ld, lblkno:%ld\n",
- nbusy, bp->b_bufobj,
- bp->b_flags, (long)bp->b_blkno,
- (long)bp->b_lblkno);
-#endif
+ if (show_busybufs > 0) {
+ printf(
+ "%d: buf:%p, vnode:%p, flags:%0x, blkno:%jd, lblkno:%jd, buflock:",
+ nbusy, bp, bp->b_vp, bp->b_flags,
+ (intmax_t)bp->b_blkno,
+ (intmax_t)bp->b_lblkno);
+ BUF_LOCKPRINTINFO(bp);
+ if (show_busybufs > 1)
+ vn_printf(bp->b_vp,
+ "vnode content: ");
+ }
}
}
if (nbusy) {
@@ -585,15 +597,6 @@ panic(const char *fmt, ...)
kdb_backtrace();
if (debugger_on_panic)
kdb_enter(KDB_WHY_PANIC, "panic");
-#ifdef RESTARTABLE_PANICS
- /* See if the user aborted the panic, in which case we continue. */
- if (panicstr == NULL) {
-#ifdef SMP
- atomic_store_rel_int(&panic_cpu, NOCPU);
-#endif
- return;
- }
-#endif
#endif
/*thread_lock(td); */
td->td_flags |= TDF_INPANIC;
@@ -702,8 +705,11 @@ dump_write(struct dumperinfo *di, void *virtual, vm_offset_t physical,
if (length != 0 && (offset < di->mediaoffset ||
offset - di->mediaoffset + length > di->mediasize)) {
- printf("Attempt to write outside dump device boundaries.\n");
- return (ENXIO);
+ printf("Attempt to write outside dump device boundaries.\n"
+ "offset(%jd), mediaoffset(%jd), length(%ju), mediasize(%jd).\n",
+ (intmax_t)offset, (intmax_t)di->mediaoffset,
+ (uintmax_t)length, (intmax_t)di->mediasize);
+ return (ENOSPC);
}
return (di->dumper(di->priv, virtual, physical, offset, length));
}
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index e1861eb1e81d4..26ef0d7f31d47 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -41,12 +41,14 @@ __FBSDID("$FreeBSD$");
#include "opt_kdtrace.h"
#include "opt_ktrace.h"
#include "opt_core.h"
+#include "opt_procdesc.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/signalvar.h>
#include <sys/vnode.h>
#include <sys/acct.h>
+#include <sys/capability.h>
#include <sys/condvar.h>
#include <sys/event.h>
#include <sys/fcntl.h>
@@ -59,6 +61,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mutex.h>
#include <sys/namei.h>
#include <sys/proc.h>
+#include <sys/procdesc.h>
#include <sys/posix4.h>
#include <sys/pioctl.h>
#include <sys/racct.h>
@@ -1698,6 +1701,34 @@ kill(struct thread *td, struct kill_args *uap)
/* NOTREACHED */
}
+int
+pdkill(td, uap)
+ struct thread *td;
+ struct pdkill_args *uap;
+{
+#ifdef PROCDESC
+ struct proc *p;
+ int error;
+
+ AUDIT_ARG_SIGNUM(uap->signum);
+ AUDIT_ARG_FD(uap->fd);
+ if ((u_int)uap->signum > _SIG_MAXSIG)
+ return (EINVAL);
+
+ error = procdesc_find(td, uap->fd, CAP_PDKILL, &p);
+ if (error)
+ return (error);
+ AUDIT_ARG_PROCESS(p);
+ error = p_cansignal(td, p, uap->signum);
+ if (error == 0 && uap->signum)
+ psignal(p, uap->signum);
+ PROC_UNLOCK(p);
+ return (error);
+#else
+ return (ENOSYS);
+#endif
+}
+
#if defined(COMPAT_43)
#ifndef _SYS_SYSPROTO_H_
struct okillpg_args {
diff --git a/sys/kern/kern_timeout.c b/sys/kern/kern_timeout.c
index 6a6f46b2c72bc..b820bd913ead1 100644
--- a/sys/kern/kern_timeout.c
+++ b/sys/kern/kern_timeout.c
@@ -269,10 +269,17 @@ callout_cpu_switch(struct callout *c, struct callout_cpu *cc, int new_cpu)
MPASS(c != NULL && cc != NULL);
CC_LOCK_ASSERT(cc);
+ /*
+ * Avoid interrupts and preemption firing after the callout cpu
+ * is blocked in order to avoid deadlocks as the new thread
+ * may be willing to acquire the callout cpu lock.
+ */
c->c_cpu = CPUBLOCK;
+ spinlock_enter();
CC_UNLOCK(cc);
new_cc = CC_CPU(new_cpu);
CC_LOCK(new_cc);
+ spinlock_exit();
c->c_cpu = new_cpu;
return (new_cc);
}
diff --git a/sys/kern/sched_4bsd.c b/sys/kern/sched_4bsd.c
index 574755f02ee24..136080caf55a5 100644
--- a/sys/kern/sched_4bsd.c
+++ b/sys/kern/sched_4bsd.c
@@ -720,7 +720,7 @@ sched_exit(struct proc *p, struct thread *td)
{
KTR_STATE1(KTR_SCHED, "thread", sched_tdname(td), "proc exit",
- "prio:td", td->td_priority);
+ "prio:%d", td->td_priority);
PROC_LOCK_ASSERT(p, MA_OWNED);
sched_exit_thread(FIRST_THREAD_IN_PROC(p), td);
@@ -731,7 +731,7 @@ sched_exit_thread(struct thread *td, struct thread *child)
{
KTR_STATE1(KTR_SCHED, "thread", sched_tdname(child), "exit",
- "prio:td", child->td_priority);
+ "prio:%d", child->td_priority);
thread_lock(td);
td->td_estcpu = ESTCPULIM(td->td_estcpu + child->td_estcpu);
thread_unlock(td);
diff --git a/sys/kern/sched_ule.c b/sys/kern/sched_ule.c
index 05267f3d6adb3..f505676933aac 100644
--- a/sys/kern/sched_ule.c
+++ b/sys/kern/sched_ule.c
@@ -84,7 +84,7 @@ dtrace_vtime_switch_func_t dtrace_vtime_switch_func;
#define TS_NAME_LEN (MAXCOMLEN + sizeof(" td ") + sizeof(__XSTRING(UINT_MAX)))
#define TDQ_NAME_LEN (sizeof("sched lock ") + sizeof(__XSTRING(MAXCPU)))
-#define TDQ_LOADNAME_LEN (PCPU_NAME_LEN + sizeof(" load"))
+#define TDQ_LOADNAME_LEN (sizeof("CPU ") + sizeof(__XSTRING(MAXCPU)) - 1 + sizeof(" load"))
/*
* Thread scheduler specific section. All fields are protected
@@ -2022,7 +2022,7 @@ sched_exit(struct proc *p, struct thread *child)
struct thread *td;
KTR_STATE1(KTR_SCHED, "thread", sched_tdname(child), "proc exit",
- "prio:td", child->td_priority);
+ "prio:%d", child->td_priority);
PROC_LOCK_ASSERT(p, MA_OWNED);
td = FIRST_THREAD_IN_PROC(p);
sched_exit_thread(td, child);
@@ -2039,7 +2039,7 @@ sched_exit_thread(struct thread *td, struct thread *child)
{
KTR_STATE1(KTR_SCHED, "thread", sched_tdname(child), "thread exit",
- "prio:td", child->td_priority);
+ "prio:%d", child->td_priority);
/*
* Give the child's runtime to the parent without returning the
* sleep time as a penalty to the parent. This causes shells that
diff --git a/sys/kern/subr_kdb.c b/sys/kern/subr_kdb.c
index f5cb31e71dd6c..2ee7dc674dfa4 100644
--- a/sys/kern/subr_kdb.c
+++ b/sys/kern/subr_kdb.c
@@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$");
#include "opt_kdb.h"
#include "opt_stack.h"
+#include "opt_watchdog.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -41,6 +42,9 @@ __FBSDID("$FreeBSD$");
#include <sys/smp.h>
#include <sys/stack.h>
#include <sys/sysctl.h>
+#ifdef SW_WATCHDOG
+#include <sys/watchdog.h>
+#endif
#include <machine/kdb.h>
#include <machine/pcb.h>
@@ -57,6 +61,21 @@ struct pcb *kdb_thrctx = NULL;
struct thread *kdb_thread = NULL;
struct trapframe *kdb_frame = NULL;
+#ifdef BREAK_TO_DEBUGGER
+#define KDB_BREAK_TO_DEBUGGER 1
+#else
+#define KDB_BREAK_TO_DEBUGGER 0
+#endif
+
+#ifdef ALT_BREAK_TO_DEBUGGER
+#define KDB_ALT_BREAK_TO_DEBUGGER 1
+#else
+#define KDB_ALT_BREAK_TO_DEBUGGER 0
+#endif
+
+static int kdb_break_to_debugger = KDB_BREAK_TO_DEBUGGER;
+static int kdb_alt_break_to_debugger = KDB_ALT_BREAK_TO_DEBUGGER;
+
KDB_BACKEND(null, NULL, NULL, NULL);
SET_DECLARE(kdb_dbbe_set, struct kdb_dbbe);
@@ -87,6 +106,15 @@ SYSCTL_PROC(_debug_kdb, OID_AUTO, trap, CTLTYPE_INT | CTLFLAG_RW, NULL, 0,
SYSCTL_PROC(_debug_kdb, OID_AUTO, trap_code, CTLTYPE_INT | CTLFLAG_RW, NULL, 0,
kdb_sysctl_trap_code, "I", "set to cause a page fault via code access");
+SYSCTL_INT(_debug_kdb, OID_AUTO, break_to_debugger, CTLTYPE_INT | CTLFLAG_RW |
+ CTLFLAG_TUN, &kdb_break_to_debugger, 0, "Enable break to debugger");
+TUNABLE_INT("debug.kdb.break_to_debugger", &kdb_break_to_debugger);
+
+SYSCTL_INT(_debug_kdb, OID_AUTO, alt_break_to_debugger, CTLTYPE_INT |
+ CTLFLAG_RW | CTLFLAG_TUN, &kdb_alt_break_to_debugger, 0,
+ "Enable alternative break to debugger");
+TUNABLE_INT("debug.kdb.alt_break_to_debugger", &kdb_alt_break_to_debugger);
+
/*
* Flag to indicate to debuggers why the debugger was entered.
*/
@@ -241,7 +269,17 @@ enum {
};
int
-kdb_alt_break(int key, int *state)
+kdb_break(void)
+{
+
+ if (!kdb_break_to_debugger)
+ return (0);
+ kdb_enter(KDB_WHY_BREAK, "Break to debugger");
+ return (KDB_REQ_DEBUGGER);
+}
+
+static int
+kdb_alt_break_state(int key, int *state)
{
int brk;
@@ -275,6 +313,53 @@ kdb_alt_break(int key, int *state)
return (brk);
}
+static int
+kdb_alt_break_internal(int key, int *state, int force_gdb)
+{
+ int brk;
+
+ if (!kdb_alt_break_to_debugger)
+ return (0);
+ brk = kdb_alt_break_state(key, state);
+ switch (brk) {
+ case KDB_REQ_DEBUGGER:
+ if (force_gdb)
+ kdb_dbbe_select("gdb");
+ kdb_enter(KDB_WHY_BREAK, "Break to debugger");
+ break;
+
+ case KDB_REQ_PANIC:
+ if (force_gdb)
+ kdb_dbbe_select("gdb");
+ kdb_panic("Panic sequence on console");
+ break;
+
+ case KDB_REQ_REBOOT:
+ kdb_reboot();
+ break;
+ }
+ return (0);
+}
+
+int
+kdb_alt_break(int key, int *state)
+{
+
+ return (kdb_alt_break_internal(key, state, 0));
+}
+
+/*
+ * This variation on kdb_alt_break() is used only by dcons, which has its own
+ * configuration flag to force GDB use regardless of the global KDB
+ * configuration.
+ */
+int
+kdb_alt_break_gdb(int key, int *state)
+{
+
+ return (kdb_alt_break_internal(key, state, 1));
+}
+
/*
* Print a backtrace of the calling thread. The backtrace is generated by
* the selected debugger, provided it supports backtraces. If no debugger
@@ -506,6 +591,9 @@ kdb_trap(int type, int code, struct trapframe *tf)
cpuset_t other_cpus;
#endif
struct kdb_dbbe *be;
+#ifdef SW_WATCHDOG
+ u_int wdoglvt;
+#endif
register_t intr;
int handled;
@@ -519,6 +607,10 @@ kdb_trap(int type, int code, struct trapframe *tf)
intr = intr_disable();
+#ifdef SW_WATCHDOG
+ wdoglvt = wdog_kern_last_timeout();
+ wdog_kern_pat(WD_TO_NEVER);
+#endif
#ifdef SMP
other_cpus = all_cpus;
CPU_CLR(PCPU_GET(cpuid), &other_cpus);
@@ -550,6 +642,9 @@ kdb_trap(int type, int code, struct trapframe *tf)
#ifdef SMP
restart_cpus(stopped_cpus);
#endif
+#ifdef SW_WATCHDOG
+ wdog_kern_pat(wdoglvt);
+#endif
intr_restore(intr);
diff --git a/sys/kern/subr_pcpu.c b/sys/kern/subr_pcpu.c
index ec6b590d25d8f..ba76bb249ecb5 100644
--- a/sys/kern/subr_pcpu.c
+++ b/sys/kern/subr_pcpu.c
@@ -92,9 +92,6 @@ pcpu_init(struct pcpu *pcpu, int cpuid, size_t size)
cpu_pcpu_init(pcpu, cpuid, size);
pcpu->pc_rm_queue.rmq_next = &pcpu->pc_rm_queue;
pcpu->pc_rm_queue.rmq_prev = &pcpu->pc_rm_queue;
-#ifdef KTR
- snprintf(pcpu->pc_name, sizeof(pcpu->pc_name), "CPU %d", cpuid);
-#endif
}
void
diff --git a/sys/kern/subr_sbuf.c b/sys/kern/subr_sbuf.c
index e931e65503300..c0d7ea0a1ba99 100644
--- a/sys/kern/subr_sbuf.c
+++ b/sys/kern/subr_sbuf.c
@@ -184,7 +184,7 @@ sbuf_newbuf(struct sbuf *s, char *buf, int length, int flags)
s->s_buf = buf;
if ((s->s_flags & SBUF_AUTOEXTEND) == 0) {
- KASSERT(s->s_size > 1,
+ KASSERT(s->s_size >= 0,
("attempt to create a too small sbuf"));
}
diff --git a/sys/kern/subr_smp.c b/sys/kern/subr_smp.c
index d0c5deff04ec8..87d536c4e56d9 100644
--- a/sys/kern/subr_smp.c
+++ b/sys/kern/subr_smp.c
@@ -109,8 +109,7 @@ static void (*volatile smp_rv_setup_func)(void *arg);
static void (*volatile smp_rv_action_func)(void *arg);
static void (*volatile smp_rv_teardown_func)(void *arg);
static void *volatile smp_rv_func_arg;
-static volatile int smp_rv_waiters[3];
-static volatile int smp_rv_generation;
+static volatile int smp_rv_waiters[4];
/*
* Shared mutex to restrict busywaits between smp_rendezvous() and
@@ -321,7 +320,6 @@ smp_rendezvous_action(void)
void (*local_setup_func)(void*);
void (*local_action_func)(void*);
void (*local_teardown_func)(void*);
- int generation;
#ifdef INVARIANTS
int owepreempt;
#endif
@@ -336,7 +334,6 @@ smp_rendezvous_action(void)
local_setup_func = smp_rv_setup_func;
local_action_func = smp_rv_action_func;
local_teardown_func = smp_rv_teardown_func;
- generation = smp_rv_generation;
/*
* Use a nested critical section to prevent any preemptions
@@ -382,32 +379,28 @@ smp_rendezvous_action(void)
if (local_action_func != NULL)
local_action_func(local_func_arg);
- /*
- * Signal that the main action has been completed. If a
- * full exit rendezvous is requested, then all CPUs will
- * wait here until all CPUs have finished the main action.
- *
- * Note that the write by the last CPU to finish the action
- * may become visible to different CPUs at different times.
- * As a result, the CPU that initiated the rendezvous may
- * exit the rendezvous and drop the lock allowing another
- * rendezvous to be initiated on the same CPU or a different
- * CPU. In that case the exit sentinel may be cleared before
- * all CPUs have noticed causing those CPUs to hang forever.
- * Workaround this by using a generation count to notice when
- * this race occurs and to exit the rendezvous in that case.
- */
- MPASS(generation == smp_rv_generation);
- atomic_add_int(&smp_rv_waiters[2], 1);
if (local_teardown_func != smp_no_rendevous_barrier) {
- while (smp_rv_waiters[2] < smp_rv_ncpus &&
- generation == smp_rv_generation)
+ /*
+ * Signal that the main action has been completed. If a
+ * full exit rendezvous is requested, then all CPUs will
+ * wait here until all CPUs have finished the main action.
+ */
+ atomic_add_int(&smp_rv_waiters[2], 1);
+ while (smp_rv_waiters[2] < smp_rv_ncpus)
cpu_spinwait();
if (local_teardown_func != NULL)
local_teardown_func(local_func_arg);
}
+ /*
+ * Signal that the rendezvous is fully completed by this CPU.
+ * This means that no member of smp_rv_* pseudo-structure will be
+ * accessed by this target CPU after this point; in particular,
+ * memory pointed by smp_rv_func_arg.
+ */
+ atomic_add_int(&smp_rv_waiters[3], 1);
+
td->td_critnest--;
KASSERT(owepreempt == td->td_owepreempt,
("rendezvous action changed td_owepreempt"));
@@ -441,8 +434,6 @@ smp_rendezvous_cpus(cpuset_t map,
mtx_lock_spin(&smp_ipi_mtx);
- atomic_add_acq_int(&smp_rv_generation, 1);
-
/* Pass rendezvous parameters via global variables. */
smp_rv_ncpus = ncpus;
smp_rv_setup_func = setup_func;
@@ -451,6 +442,7 @@ smp_rendezvous_cpus(cpuset_t map,
smp_rv_func_arg = arg;
smp_rv_waiters[1] = 0;
smp_rv_waiters[2] = 0;
+ smp_rv_waiters[3] = 0;
atomic_store_rel_int(&smp_rv_waiters[0], 0);
/*
@@ -466,13 +458,13 @@ smp_rendezvous_cpus(cpuset_t map,
smp_rendezvous_action();
/*
- * If the caller did not request an exit barrier to be enforced
- * on each CPU, ensure that this CPU waits for all the other
- * CPUs to finish the rendezvous.
+ * Ensure that the master CPU waits for all the other
+ * CPUs to finish the rendezvous, so that smp_rv_*
+ * pseudo-structure and the arg are guaranteed to not
+ * be in use.
*/
- if (teardown_func == smp_no_rendevous_barrier)
- while (atomic_load_acq_int(&smp_rv_waiters[2]) < ncpus)
- cpu_spinwait();
+ while (atomic_load_acq_int(&smp_rv_waiters[3]) < ncpus)
+ cpu_spinwait();
mtx_unlock_spin(&smp_ipi_mtx);
}
diff --git a/sys/kern/subr_syscall.c b/sys/kern/subr_syscall.c
new file mode 100644
index 0000000000000..cb0d9295ed2bd
--- /dev/null
+++ b/sys/kern/subr_syscall.c
@@ -0,0 +1,213 @@
+/*-
+ * Copyright (C) 1994, David Greenman
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (C) 2010 Konstantin Belousov <kib@freebsd.org>
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the University of Utah, and 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 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: @(#)trap.c 7.4 (Berkeley) 5/13/91
+ */
+
+#include "opt_capsicum.h"
+#include "opt_ktrace.h"
+#include "opt_kdtrace.h"
+
+__FBSDID("$FreeBSD$");
+
+#include <sys/capability.h>
+#include <sys/ktr.h>
+#ifdef KTRACE
+#include <sys/uio.h>
+#include <sys/ktrace.h>
+#endif
+#include <security/audit/audit.h>
+
+static inline int
+syscallenter(struct thread *td, struct syscall_args *sa)
+{
+ struct proc *p;
+ int error, traced;
+
+ PCPU_INC(cnt.v_syscall);
+ p = td->td_proc;
+
+ td->td_pticks = 0;
+ if (td->td_ucred != p->p_ucred)
+ cred_update_thread(td);
+ if (p->p_flag & P_TRACED) {
+ traced = 1;
+ PROC_LOCK(p);
+ td->td_dbgflags &= ~TDB_USERWR;
+ td->td_dbgflags |= TDB_SCE;
+ PROC_UNLOCK(p);
+ } else
+ traced = 0;
+ error = (p->p_sysent->sv_fetch_syscall_args)(td, sa);
+#ifdef KTRACE
+ if (KTRPOINT(td, KTR_SYSCALL))
+ ktrsyscall(sa->code, sa->narg, sa->args);
+#endif
+
+ CTR6(KTR_SYSC,
+"syscall: td=%p pid %d %s (%#lx, %#lx, %#lx)",
+ td, td->td_proc->p_pid, syscallname(p, sa->code),
+ sa->args[0], sa->args[1], sa->args[2]);
+
+ if (error == 0) {
+ STOPEVENT(p, S_SCE, sa->narg);
+ PTRACESTOP_SC(p, td, S_PT_SCE);
+ if (td->td_dbgflags & TDB_USERWR) {
+ /*
+ * Reread syscall number and arguments if
+ * debugger modified registers or memory.
+ */
+ error = (p->p_sysent->sv_fetch_syscall_args)(td, sa);
+#ifdef KTRACE
+ if (KTRPOINT(td, KTR_SYSCALL))
+ ktrsyscall(sa->code, sa->narg, sa->args);
+#endif
+ if (error != 0)
+ goto retval;
+ }
+
+#ifdef CAPABILITY_MODE
+ /*
+ * In capability mode, we only allow access to system calls
+ * flagged with SYF_CAPENABLED.
+ */
+ if (IN_CAPABILITY_MODE(td) &&
+ !(sa->callp->sy_flags & SYF_CAPENABLED)) {
+ error = ECAPMODE;
+ goto retval;
+ }
+#endif
+
+ error = syscall_thread_enter(td, sa->callp);
+ if (error != 0)
+ goto retval;
+
+#ifdef KDTRACE_HOOKS
+ /*
+ * If the systrace module has registered it's probe
+ * callback and if there is a probe active for the
+ * syscall 'entry', process the probe.
+ */
+ if (systrace_probe_func != NULL && sa->callp->sy_entry != 0)
+ (*systrace_probe_func)(sa->callp->sy_entry, sa->code,
+ sa->callp, sa->args, 0);
+#endif
+
+ AUDIT_SYSCALL_ENTER(sa->code, td);
+ error = (sa->callp->sy_call)(td, sa->args);
+ AUDIT_SYSCALL_EXIT(error, td);
+
+ /* Save the latest error return value. */
+ td->td_errno = error;
+
+#ifdef KDTRACE_HOOKS
+ /*
+ * If the systrace module has registered it's probe
+ * callback and if there is a probe active for the
+ * syscall 'return', process the probe.
+ */
+ if (systrace_probe_func != NULL && sa->callp->sy_return != 0)
+ (*systrace_probe_func)(sa->callp->sy_return, sa->code,
+ sa->callp, NULL, (error) ? -1 : td->td_retval[0]);
+#endif
+ syscall_thread_exit(td, sa->callp);
+ CTR4(KTR_SYSC, "syscall: p=%p error=%d return %#lx %#lx",
+ p, error, td->td_retval[0], td->td_retval[1]);
+ }
+ retval:
+ if (traced) {
+ PROC_LOCK(p);
+ td->td_dbgflags &= ~TDB_SCE;
+ PROC_UNLOCK(p);
+ }
+ (p->p_sysent->sv_set_syscall_retval)(td, error);
+ return (error);
+}
+
+static inline void
+syscallret(struct thread *td, int error, struct syscall_args *sa __unused)
+{
+ struct proc *p;
+ int traced;
+
+ p = td->td_proc;
+
+ /*
+ * Check for misbehavior.
+ */
+ WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
+ syscallname(p, sa->code));
+ KASSERT(td->td_critnest == 0,
+ ("System call %s returning in a critical section",
+ syscallname(p, sa->code)));
+ KASSERT(td->td_locks == 0,
+ ("System call %s returning with %d locks held",
+ syscallname(p, sa->code), td->td_locks));
+
+ /*
+ * Handle reschedule and other end-of-syscall issues
+ */
+ userret(td, td->td_frame);
+
+ CTR4(KTR_SYSC, "syscall %s exit thread %p pid %d proc %s",
+ syscallname(p, sa->code), td, td->td_proc->p_pid, td->td_name);
+
+#ifdef KTRACE
+ if (KTRPOINT(td, KTR_SYSRET))
+ ktrsysret(sa->code, error, td->td_retval[0]);
+#endif
+
+ if (p->p_flag & P_TRACED) {
+ traced = 1;
+ PROC_LOCK(p);
+ td->td_dbgflags |= TDB_SCX;
+ PROC_UNLOCK(p);
+ } else
+ traced = 0;
+ /*
+ * This works because errno is findable through the
+ * register set. If we ever support an emulation where this
+ * is not the case, this code will need to be revisited.
+ */
+ STOPEVENT(p, S_SCX, sa->code);
+ PTRACESTOP_SC(p, td, S_PT_SCX);
+ if (traced || (td->td_dbgflags & (TDB_EXEC | TDB_FORK)) != 0) {
+ PROC_LOCK(p);
+ td->td_dbgflags &= ~(TDB_SCX | TDB_EXEC | TDB_FORK);
+ PROC_UNLOCK(p);
+ }
+}
diff --git a/sys/kern/subr_taskqueue.c b/sys/kern/subr_taskqueue.c
index 4c4589901557d..31ea52d1d8761 100644
--- a/sys/kern/subr_taskqueue.c
+++ b/sys/kern/subr_taskqueue.c
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include <sys/interrupt.h>
#include <sys/kernel.h>
#include <sys/kthread.h>
+#include <sys/limits.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
@@ -173,7 +174,8 @@ taskqueue_enqueue_locked(struct taskqueue *queue, struct task *task)
* Count multiple enqueues.
*/
if (task->ta_pending) {
- task->ta_pending++;
+ if (task->ta_pending < USHRT_MAX)
+ task->ta_pending++;
return (0);
}
diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c
index 3527ed1fbedfc..42adf80f04fee 100644
--- a/sys/kern/subr_trap.c
+++ b/sys/kern/subr_trap.c
@@ -252,7 +252,6 @@ ast(struct trapframe *framep)
mtx_assert(&Giant, MA_NOTOWNED);
}
-#ifdef HAVE_SYSCALL_ARGS_DEF
const char *
syscallname(struct proc *p, u_int code)
{
@@ -264,164 +263,3 @@ syscallname(struct proc *p, u_int code)
return (unknown);
return (sv->sv_syscallnames[code]);
}
-
-int
-syscallenter(struct thread *td, struct syscall_args *sa)
-{
- struct proc *p;
- int error, traced;
-
- PCPU_INC(cnt.v_syscall);
- p = td->td_proc;
-
- td->td_pticks = 0;
- if (td->td_ucred != p->p_ucred)
- cred_update_thread(td);
- if (p->p_flag & P_TRACED) {
- traced = 1;
- PROC_LOCK(p);
- td->td_dbgflags &= ~TDB_USERWR;
- td->td_dbgflags |= TDB_SCE;
- PROC_UNLOCK(p);
- } else
- traced = 0;
- error = (p->p_sysent->sv_fetch_syscall_args)(td, sa);
-#ifdef KTRACE
- if (KTRPOINT(td, KTR_SYSCALL))
- ktrsyscall(sa->code, sa->narg, sa->args);
-#endif
-
- CTR6(KTR_SYSC,
-"syscall: td=%p pid %d %s (%#lx, %#lx, %#lx)",
- td, td->td_proc->p_pid, syscallname(p, sa->code),
- sa->args[0], sa->args[1], sa->args[2]);
-
- if (error == 0) {
- STOPEVENT(p, S_SCE, sa->narg);
- PTRACESTOP_SC(p, td, S_PT_SCE);
- if (td->td_dbgflags & TDB_USERWR) {
- /*
- * Reread syscall number and arguments if
- * debugger modified registers or memory.
- */
- error = (p->p_sysent->sv_fetch_syscall_args)(td, sa);
-#ifdef KTRACE
- if (KTRPOINT(td, KTR_SYSCALL))
- ktrsyscall(sa->code, sa->narg, sa->args);
-#endif
- if (error != 0)
- goto retval;
- }
-
-#ifdef CAPABILITY_MODE
- /*
- * In capability mode, we only allow access to system calls
- * flagged with SYF_CAPENABLED.
- */
- if (IN_CAPABILITY_MODE(td) &&
- !(sa->callp->sy_flags & SYF_CAPENABLED)) {
- error = ECAPMODE;
- goto retval;
- }
-#endif
-
- error = syscall_thread_enter(td, sa->callp);
- if (error != 0)
- goto retval;
-
-#ifdef KDTRACE_HOOKS
- /*
- * If the systrace module has registered it's probe
- * callback and if there is a probe active for the
- * syscall 'entry', process the probe.
- */
- if (systrace_probe_func != NULL && sa->callp->sy_entry != 0)
- (*systrace_probe_func)(sa->callp->sy_entry, sa->code,
- sa->callp, sa->args, 0);
-#endif
-
- AUDIT_SYSCALL_ENTER(sa->code, td);
- error = (sa->callp->sy_call)(td, sa->args);
- AUDIT_SYSCALL_EXIT(error, td);
-
- /* Save the latest error return value. */
- td->td_errno = error;
-
-#ifdef KDTRACE_HOOKS
- /*
- * If the systrace module has registered it's probe
- * callback and if there is a probe active for the
- * syscall 'return', process the probe.
- */
- if (systrace_probe_func != NULL && sa->callp->sy_return != 0)
- (*systrace_probe_func)(sa->callp->sy_return, sa->code,
- sa->callp, NULL, (error) ? -1 : td->td_retval[0]);
-#endif
- syscall_thread_exit(td, sa->callp);
- CTR4(KTR_SYSC, "syscall: p=%p error=%d return %#lx %#lx",
- p, error, td->td_retval[0], td->td_retval[1]);
- }
- retval:
- if (traced) {
- PROC_LOCK(p);
- td->td_dbgflags &= ~TDB_SCE;
- PROC_UNLOCK(p);
- }
- (p->p_sysent->sv_set_syscall_retval)(td, error);
- return (error);
-}
-
-void
-syscallret(struct thread *td, int error, struct syscall_args *sa __unused)
-{
- struct proc *p;
- int traced;
-
- p = td->td_proc;
-
- /*
- * Check for misbehavior.
- */
- WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
- syscallname(p, sa->code));
- KASSERT(td->td_critnest == 0,
- ("System call %s returning in a critical section",
- syscallname(p, sa->code)));
- KASSERT(td->td_locks == 0,
- ("System call %s returning with %d locks held",
- syscallname(p, sa->code), td->td_locks));
-
- /*
- * Handle reschedule and other end-of-syscall issues
- */
- userret(td, td->td_frame);
-
- CTR4(KTR_SYSC, "syscall %s exit thread %p pid %d proc %s",
- syscallname(p, sa->code), td, td->td_proc->p_pid, td->td_name);
-
-#ifdef KTRACE
- if (KTRPOINT(td, KTR_SYSRET))
- ktrsysret(sa->code, error, td->td_retval[0]);
-#endif
-
- if (p->p_flag & P_TRACED) {
- traced = 1;
- PROC_LOCK(p);
- td->td_dbgflags |= TDB_SCX;
- PROC_UNLOCK(p);
- } else
- traced = 0;
- /*
- * This works because errno is findable through the
- * register set. If we ever support an emulation where this
- * is not the case, this code will need to be revisited.
- */
- STOPEVENT(p, S_SCX, sa->code);
- PTRACESTOP_SC(p, td, S_PT_SCX);
- if (traced || (td->td_dbgflags & (TDB_EXEC | TDB_FORK)) != 0) {
- PROC_LOCK(p);
- td->td_dbgflags &= ~(TDB_SCX | TDB_EXEC | TDB_FORK);
- PROC_UNLOCK(p);
- }
-}
-#endif /* HAVE_SYSCALL_ARGS_DEF */
diff --git a/sys/kern/sys_capability.c b/sys/kern/sys_capability.c
index 04f98d8290c7a..318ffe4e04d2f 100644
--- a/sys/kern/sys_capability.c
+++ b/sys/kern/sys_capability.c
@@ -31,9 +31,24 @@
/*
* FreeBSD kernel capability facility.
*
- * Currently, this file implements only capability mode; capabilities
- * (rights-refined file descriptors) will follow.
+ * Two kernel features are implemented here: capability mode, a sandboxed mode
+ * of execution for processes, and capabilities, a refinement on file
+ * descriptors that allows fine-grained control over operations on the file
+ * descriptor. Collectively, these allow processes to run in the style of a
+ * historic "capability system" in which they can use only resources
+ * explicitly delegated to them. This model is enforced by restricting access
+ * to global namespaces in capability mode.
*
+ * Capabilities wrap other file descriptor types, binding them to a constant
+ * rights mask set when the capability is created. New capabilities may be
+ * derived from existing capabilities, but only if they have the same or a
+ * strict subset of the rights on the original capability.
+ *
+ * System calls permitted in capability mode are defined in capabilities.conf;
+ * calls must be carefully audited for safety to ensure that they don't allow
+ * escape from a sandbox. Some calls permit only a subset of operations in
+ * capability mode -- for example, shm_open(2) is limited to creating
+ * anonymous, rather than named, POSIX shared memory objects.
*/
#include "opt_capsicum.h"
@@ -61,7 +76,7 @@ __FBSDID("$FreeBSD$");
#ifdef CAPABILITY_MODE
-FEATURE(security_capabilities, "Capsicum Capability Mode");
+FEATURE(security_capability_mode, "Capsicum Capability Mode");
/*
* System call to enter capability mode for the process.
@@ -119,6 +134,8 @@ cap_getmode(struct thread *td, struct cap_getmode_args *uap)
#ifdef CAPABILITIES
+FEATURE(security_capabilities, "Capsicum Capabilities");
+
/*
* struct capability describes a capability, and is hung off of its struct
* file f_data field. cap_file and cap_rightss are static once hooked up, as
@@ -144,6 +161,8 @@ static fo_poll_t capability_poll;
static fo_kqfilter_t capability_kqfilter;
static fo_stat_t capability_stat;
static fo_close_t capability_close;
+static fo_chmod_t capability_chmod;
+static fo_chown_t capability_chown;
static struct fileops capability_ops = {
.fo_read = capability_read,
@@ -154,6 +173,8 @@ static struct fileops capability_ops = {
.fo_kqfilter = capability_kqfilter,
.fo_stat = capability_stat,
.fo_close = capability_close,
+ .fo_chmod = capability_chmod,
+ .fo_chown = capability_chown,
.fo_flags = DFLAG_PASSABLE,
};
@@ -166,6 +187,8 @@ static struct fileops capability_ops_unpassable = {
.fo_kqfilter = capability_kqfilter,
.fo_stat = capability_stat,
.fo_close = capability_close,
+ .fo_chmod = capability_chmod,
+ .fo_chown = capability_chown,
.fo_flags = 0,
};
@@ -220,18 +243,16 @@ cap_new(struct thread *td, struct cap_new_args *uap)
{
int error, capfd;
int fd = uap->fd;
- struct file *fp, *fcapp;
+ struct file *fp;
cap_rights_t rights = uap->rights;
AUDIT_ARG_FD(fd);
-#ifdef notyet /* capability auditing will follow in a few commits */
AUDIT_ARG_RIGHTS(rights);
-#endif
- error = fget(td, fd, &fp);
+ error = fget(td, fd, rights, &fp);
if (error)
return (error);
AUDIT_ARG_FILE(td->td_proc, fp);
- error = kern_capwrap(td, fp, rights, &fcapp, &capfd);
+ error = kern_capwrap(td, fp, rights, &capfd);
if (error)
return (error);
@@ -269,10 +290,10 @@ cap_getrights(struct thread *td, struct cap_getrights_args *uap)
*/
int
kern_capwrap(struct thread *td, struct file *fp, cap_rights_t rights,
- struct file **fcappp, int *capfdp)
+ int *capfdp)
{
struct capability *cp, *cp_old;
- struct file *fp_object;
+ struct file *fp_object, *fcapp;
int error;
if ((rights | CAP_MASK_VALID) != CAP_MASK_VALID)
@@ -292,7 +313,7 @@ kern_capwrap(struct thread *td, struct file *fp, cap_rights_t rights,
/*
* Allocate a new file descriptor to hang the capability off of.
*/
- error = falloc(td, fcappp, capfdp, fp->f_flag);
+ error = falloc(td, &fcapp, capfdp, fp->f_flag);
if (error)
return (error);
@@ -311,18 +332,18 @@ kern_capwrap(struct thread *td, struct file *fp, cap_rights_t rights,
cp = uma_zalloc(capability_zone, M_WAITOK | M_ZERO);
cp->cap_rights = rights;
cp->cap_object = fp_object;
- cp->cap_file = *fcappp;
+ cp->cap_file = fcapp;
if (fp->f_flag & DFLAG_PASSABLE)
- finit(*fcappp, fp->f_flag, DTYPE_CAPABILITY, cp,
+ finit(fcapp, fp->f_flag, DTYPE_CAPABILITY, cp,
&capability_ops);
else
- finit(*fcappp, fp->f_flag, DTYPE_CAPABILITY, cp,
+ finit(fcapp, fp->f_flag, DTYPE_CAPABILITY, cp,
&capability_ops_unpassable);
/*
* Release our private reference (the proc filedesc still has one).
*/
- fdrop(*fcappp, td);
+ fdrop(fcapp, td);
return (0);
}
@@ -469,6 +490,22 @@ capability_stat(struct file *fp, struct stat *sb, struct ucred *active_cred,
panic("capability_stat");
}
+int
+capability_chmod(struct file *fp, mode_t mode, struct ucred *active_cred,
+ struct thread *td)
+{
+
+ panic("capability_chmod");
+}
+
+int
+capability_chown(struct file *fp, uid_t uid, gid_t gid,
+ struct ucred *active_cred, struct thread *td)
+{
+
+ panic("capability_chown");
+}
+
#else /* !CAPABILITIES */
/*
@@ -514,4 +551,3 @@ cap_funwrap_mmap(struct file *fp_cap, cap_rights_t rights, u_char *maxprotp,
}
#endif /* CAPABILITIES */
-
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c
index 1a2685cc1f012..7b45efa2ff51d 100644
--- a/sys/kern/sys_generic.c
+++ b/sys/kern/sys_generic.c
@@ -37,12 +37,14 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_capsicum.h"
#include "opt_compat.h"
#include "opt_ktrace.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sysproto.h>
+#include <sys/capability.h>
#include <sys/filedesc.h>
#include <sys/filio.h>
#include <sys/fcntl.h>
@@ -232,7 +234,7 @@ kern_readv(struct thread *td, int fd, struct uio *auio)
struct file *fp;
int error;
- error = fget_read(td, fd, &fp);
+ error = fget_read(td, fd, CAP_READ | CAP_SEEK, &fp);
if (error)
return (error);
error = dofileread(td, fd, fp, auio, (off_t)-1, 0);
@@ -275,7 +277,7 @@ kern_preadv(td, fd, auio, offset)
struct file *fp;
int error;
- error = fget_read(td, fd, &fp);
+ error = fget_read(td, fd, CAP_READ, &fp);
if (error)
return (error);
if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE))
@@ -441,7 +443,7 @@ kern_writev(struct thread *td, int fd, struct uio *auio)
struct file *fp;
int error;
- error = fget_write(td, fd, &fp);
+ error = fget_write(td, fd, CAP_WRITE | CAP_SEEK, &fp);
if (error)
return (error);
error = dofilewrite(td, fd, fp, auio, (off_t)-1, 0);
@@ -484,7 +486,7 @@ kern_pwritev(td, fd, auio, offset)
struct file *fp;
int error;
- error = fget_write(td, fd, &fp);
+ error = fget_write(td, fd, CAP_WRITE, &fp);
if (error)
return (error);
if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE))
@@ -566,7 +568,7 @@ kern_ftruncate(td, fd, length)
AUDIT_ARG_FD(fd);
if (length < 0)
return (EINVAL);
- error = fget(td, fd, &fp);
+ error = fget(td, fd, CAP_FTRUNCATE, &fp);
if (error)
return (error);
AUDIT_ARG_FILE(td->td_proc, fp);
@@ -696,7 +698,7 @@ kern_ioctl(struct thread *td, int fd, u_long com, caddr_t data)
AUDIT_ARG_FD(fd);
AUDIT_ARG_CMD(com);
- if ((error = fget(td, fd, &fp)) != 0)
+ if ((error = fget(td, fd, CAP_IOCTL, &fp)) != 0)
return (error);
if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
fdrop(fp, td);
@@ -1054,6 +1056,37 @@ selsetbits(fd_mask **ibits, fd_mask **obits, int idx, fd_mask bit, int events)
return (n);
}
+static __inline int
+getselfd_cap(struct filedesc *fdp, int fd, struct file **fpp)
+{
+ struct file *fp;
+#ifdef CAPABILITIES
+ struct file *fp_fromcap;
+ int error;
+#endif
+
+ if ((fp = fget_unlocked(fdp, fd)) == NULL)
+ return (EBADF);
+#ifdef CAPABILITIES
+ /*
+ * If the file descriptor is for a capability, test rights and use
+ * the file descriptor references by the capability.
+ */
+ error = cap_funwrap(fp, CAP_POLL_EVENT, &fp_fromcap);
+ if (error) {
+ fdrop(fp, curthread);
+ return (error);
+ }
+ if (fp != fp_fromcap) {
+ fhold(fp_fromcap);
+ fdrop(fp, curthread);
+ fp = fp_fromcap;
+ }
+#endif /* CAPABILITIES */
+ *fpp = fp;
+ return (0);
+}
+
/*
* Traverse the list of fds attached to this thread's seltd and check for
* completion.
@@ -1069,6 +1102,7 @@ selrescan(struct thread *td, fd_mask **ibits, fd_mask **obits)
struct file *fp;
fd_mask bit;
int fd, ev, n, idx;
+ int error;
fdp = td->td_proc->p_fd;
stp = td->td_sel;
@@ -1080,8 +1114,9 @@ selrescan(struct thread *td, fd_mask **ibits, fd_mask **obits)
/* If the selinfo wasn't cleared the event didn't fire. */
if (si != NULL)
continue;
- if ((fp = fget_unlocked(fdp, fd)) == NULL)
- return (EBADF);
+ error = getselfd_cap(fdp, fd, &fp);
+ if (error)
+ return (error);
idx = fd / NFDBITS;
bit = (fd_mask)1 << (fd % NFDBITS);
ev = fo_poll(fp, selflags(ibits, idx, bit), td->td_ucred, td);
@@ -1109,6 +1144,7 @@ selscan(td, ibits, obits, nfd)
fd_mask bit;
int ev, flags, end, fd;
int n, idx;
+ int error;
fdp = td->td_proc->p_fd;
n = 0;
@@ -1119,8 +1155,9 @@ selscan(td, ibits, obits, nfd)
flags = selflags(ibits, idx, bit);
if (flags == 0)
continue;
- if ((fp = fget_unlocked(fdp, fd)) == NULL)
- return (EBADF);
+ error = getselfd_cap(fdp, fd, &fp);
+ if (error)
+ return (error);
selfdalloc(td, (void *)(uintptr_t)fd);
ev = fo_poll(fp, flags, td->td_ucred, td);
fdrop(fp, td);
@@ -1242,11 +1279,17 @@ pollrescan(struct thread *td)
if (si != NULL)
continue;
fp = fdp->fd_ofiles[fd->fd];
+#ifdef CAPABILITIES
+ if ((fp == NULL)
+ || (cap_funwrap(fp, CAP_POLL_EVENT, &fp) != 0)) {
+#else
if (fp == NULL) {
+#endif
fd->revents = POLLNVAL;
n++;
continue;
}
+
/*
* Note: backend also returns POLLHUP and
* POLLERR if appropriate.
@@ -1307,7 +1350,12 @@ pollscan(td, fds, nfd)
fds->revents = 0;
} else {
fp = fdp->fd_ofiles[fds->fd];
+#ifdef CAPABILITIES
+ if ((fp == NULL)
+ || (cap_funwrap(fp, CAP_POLL_EVENT, &fp) != 0)) {
+#else
if (fp == NULL) {
+#endif
fds->revents = POLLNVAL;
n++;
} else {
@@ -1442,6 +1490,23 @@ selfdfree(struct seltd *stp, struct selfd *sfp)
uma_zfree(selfd_zone, sfp);
}
+/* Drain the waiters tied to all the selfd belonging the specified selinfo. */
+void
+seldrain(sip)
+ struct selinfo *sip;
+{
+
+ /*
+ * This feature is already provided by doselwakeup(), thus it is
+ * enough to go for it.
+ * Eventually, the context, should take care to avoid races
+ * between thread calling select()/poll() and file descriptor
+ * detaching, but, again, the races are just the same as
+ * selwakeup().
+ */
+ doselwakeup(sip, -1);
+}
+
/*
* Record a select request.
*/
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
index 50b03897e2773..c44a2c964e499 100644
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -155,6 +155,8 @@ static struct fileops pipeops = {
.fo_kqfilter = pipe_kqfilter,
.fo_stat = pipe_stat,
.fo_close = pipe_close,
+ .fo_chmod = invfo_chmod,
+ .fo_chown = invfo_chown,
.fo_flags = DFLAG_PASSABLE
};
@@ -1515,6 +1517,7 @@ pipeclose(cpipe)
*/
knlist_clear(&cpipe->pipe_sel.si_note, 1);
cpipe->pipe_present = PIPE_FINALIZED;
+ seldrain(&cpipe->pipe_sel);
knlist_destroy(&cpipe->pipe_sel.si_note);
/*
diff --git a/sys/kern/sys_procdesc.c b/sys/kern/sys_procdesc.c
new file mode 100644
index 0000000000000..9993732527cdb
--- /dev/null
+++ b/sys/kern/sys_procdesc.c
@@ -0,0 +1,524 @@
+/*-
+ * Copyright (c) 2009 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed at the University of Cambridge Computer
+ * Laboratory with support from a grant from Google, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*-
+ * FreeBSD process descriptor facility.
+ *
+ * Some processes are represented by a file descriptor, which will be used in
+ * preference to signaling and pids for the purposes of process management,
+ * and is, in effect, a form of capability. When a process descriptor is
+ * used with a process, it ceases to be visible to certain traditional UNIX
+ * process facilities, such as waitpid(2).
+ *
+ * Some semantics:
+ *
+ * - At most one process descriptor will exist for any process, although
+ * references to that descriptor may be held from many processes (or even
+ * be in flight between processes over a local domain socket).
+ * - Last close on the process descriptor will terminate the process using
+ * SIGKILL and reparent it to init so that there's a process to reap it
+ * when it's done exiting.
+ * - If the process exits before the descriptor is closed, it will not
+ * generate SIGCHLD on termination, or be picked up by waitpid().
+ * - The pdkill(2) system call may be used to deliver a signal to the process
+ * using its process descriptor.
+ * - The pdwait4(2) system call may be used to block (or not) on a process
+ * descriptor to collect termination information.
+ *
+ * Open questions:
+ *
+ * - How to handle ptrace(2)?
+ * - Will we want to add a pidtoprocdesc(2) system call to allow process
+ * descriptors to be created for processes without pfork(2)?
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_procdesc.h"
+
+#include <sys/param.h>
+#include <sys/capability.h>
+#include <sys/fcntl.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/poll.h>
+#include <sys/proc.h>
+#include <sys/procdesc.h>
+#include <sys/resourcevar.h>
+#include <sys/stat.h>
+#include <sys/sysproto.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+#include <sys/ucred.h>
+
+#include <security/audit/audit.h>
+
+#include <vm/uma.h>
+
+#ifdef PROCDESC
+
+FEATURE(process_descriptors, "Process Descriptors");
+
+static uma_zone_t procdesc_zone;
+
+static fo_rdwr_t procdesc_read;
+static fo_rdwr_t procdesc_write;
+static fo_truncate_t procdesc_truncate;
+static fo_ioctl_t procdesc_ioctl;
+static fo_poll_t procdesc_poll;
+static fo_kqfilter_t procdesc_kqfilter;
+static fo_stat_t procdesc_stat;
+static fo_close_t procdesc_close;
+static fo_chmod_t procdesc_chmod;
+static fo_chown_t procdesc_chown;
+
+static struct fileops procdesc_ops = {
+ .fo_read = procdesc_read,
+ .fo_write = procdesc_write,
+ .fo_truncate = procdesc_truncate,
+ .fo_ioctl = procdesc_ioctl,
+ .fo_poll = procdesc_poll,
+ .fo_kqfilter = procdesc_kqfilter,
+ .fo_stat = procdesc_stat,
+ .fo_close = procdesc_close,
+ .fo_chmod = procdesc_chmod,
+ .fo_chown = procdesc_chown,
+ .fo_flags = DFLAG_PASSABLE,
+};
+
+/*
+ * Initialize with VFS so that process descriptors are available along with
+ * other file descriptor types. As long as it runs before init(8) starts,
+ * there shouldn't be a problem.
+ */
+static void
+procdesc_init(void *dummy __unused)
+{
+
+ procdesc_zone = uma_zcreate("procdesc", sizeof(struct procdesc),
+ NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
+ if (procdesc_zone == NULL)
+ panic("procdesc_init: procdesc_zone not initialized");
+}
+SYSINIT(vfs, SI_SUB_VFS, SI_ORDER_ANY, procdesc_init, NULL);
+
+/*
+ * Return a locked process given a process descriptor, or ESRCH if it has
+ * died.
+ */
+int
+procdesc_find(struct thread *td, int fd, cap_rights_t rights,
+ struct proc **p)
+{
+ struct procdesc *pd;
+ struct file *fp;
+ int error;
+
+ error = fget(td, fd, rights, &fp);
+ if (error)
+ return (error);
+ if (fp->f_type != DTYPE_PROCDESC) {
+ error = EBADF;
+ goto out;
+ }
+ pd = fp->f_data;
+ sx_slock(&proctree_lock);
+ if (pd->pd_proc != NULL) {
+ *p = pd->pd_proc;
+ PROC_LOCK(*p);
+ } else
+ error = ESRCH;
+ sx_sunlock(&proctree_lock);
+out:
+ fdrop(fp, td);
+ return (error);
+}
+
+/*
+ * Function to be used by procstat(1) sysctls when returning procdesc
+ * information.
+ */
+pid_t
+procdesc_pid(struct file *fp_procdesc)
+{
+ struct procdesc *pd;
+
+ KASSERT(fp_procdesc->f_type == DTYPE_PROCDESC,
+ ("procdesc_pid: !procdesc"));
+
+ pd = fp_procdesc->f_data;
+ return (pd->pd_pid);
+}
+
+/*
+ * Retrieve the PID associated with a process descriptor.
+ */
+int
+kern_pdgetpid(struct thread *td, int fd, cap_rights_t rights, pid_t *pidp)
+{
+ struct file *fp;
+ int error;
+
+ error = fget(td, fd, rights, &fp);
+ if (error)
+ return (error);
+ if (fp->f_type != DTYPE_PROCDESC) {
+ error = EBADF;
+ goto out;
+ }
+ *pidp = procdesc_pid(fp);
+out:
+ fdrop(fp, td);
+ return (error);
+}
+
+/*
+ * System call to return the pid of a process given its process descriptor.
+ */
+int
+pdgetpid(struct thread *td, struct pdgetpid_args *uap)
+{
+ pid_t pid;
+ int error;
+
+ AUDIT_ARG_FD(uap->fd);
+ error = kern_pdgetpid(td, uap->fd, CAP_PDGETPID, &pid);
+ if (error == 0)
+ error = copyout(&pid, uap->pidp, sizeof(pid));
+ return (error);
+}
+
+/*
+ * When a new process is forked by pdfork(), a file descriptor is allocated
+ * by the fork code first, then the process is forked, and then we get a
+ * chance to set up the process descriptor. Failure is not permitted at this
+ * point, so procdesc_new() must succeed.
+ */
+void
+procdesc_new(struct proc *p, int flags)
+{
+ struct procdesc *pd;
+
+ pd = uma_zalloc(procdesc_zone, M_WAITOK | M_ZERO);
+ pd->pd_proc = p;
+ pd->pd_pid = p->p_pid;
+ p->p_procdesc = pd;
+ pd->pd_flags = 0;
+ if (flags & PD_DAEMON)
+ pd->pd_flags |= PDF_DAEMON;
+ PROCDESC_LOCK_INIT(pd);
+
+ /*
+ * Process descriptors start out with two references: one from their
+ * struct file, and the other from their struct proc.
+ */
+ refcount_init(&pd->pd_refcount, 2);
+}
+
+/*
+ * Initialize a file with a process descriptor.
+ */
+void
+procdesc_finit(struct procdesc *pdp, struct file *fp)
+{
+
+ finit(fp, FREAD | FWRITE, DTYPE_PROCDESC, pdp, &procdesc_ops);
+}
+
+static void
+procdesc_free(struct procdesc *pd)
+{
+
+ /*
+ * When the last reference is released, we assert that the descriptor
+ * has been closed, but not that the process has exited, as we will
+ * detach the descriptor before the process dies if the descript is
+ * closed, as we can't wait synchronously.
+ */
+ if (refcount_release(&pd->pd_refcount)) {
+ KASSERT(pd->pd_proc == NULL,
+ ("procdesc_free: pd_proc != NULL"));
+ KASSERT((pd->pd_flags & PDF_CLOSED),
+ ("procdesc_free: !PDF_CLOSED"));
+
+ PROCDESC_LOCK_DESTROY(pd);
+ uma_zfree(procdesc_zone, pd);
+ }
+}
+
+/*
+ * procdesc_exit() - notify a process descriptor that its process is exiting.
+ * We use the proctree_lock to ensure that process exit either happens
+ * strictly before or strictly after a concurrent call to procdesc_close().
+ */
+int
+procdesc_exit(struct proc *p)
+{
+ struct procdesc *pd;
+
+ sx_assert(&proctree_lock, SA_XLOCKED);
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+ KASSERT(p->p_procdesc != NULL, ("procdesc_exit: p_procdesc NULL"));
+
+ pd = p->p_procdesc;
+
+ PROCDESC_LOCK(pd);
+ KASSERT((pd->pd_flags & PDF_CLOSED) == 0 || p->p_pptr == initproc,
+ ("procdesc_exit: closed && parent not init"));
+
+ pd->pd_flags |= PDF_EXITED;
+
+ /*
+ * If the process descriptor has been closed, then we have nothing
+ * to do; return 1 so that init will get SIGCHLD and do the reaping.
+ * Clean up the procdesc now rather than letting it happen during
+ * that reap.
+ */
+ if (pd->pd_flags & PDF_CLOSED) {
+ PROCDESC_UNLOCK(pd);
+ pd->pd_proc = NULL;
+ p->p_procdesc = NULL;
+ procdesc_free(pd);
+ return (1);
+ }
+ if (pd->pd_flags & PDF_SELECTED) {
+ pd->pd_flags &= ~PDF_SELECTED;
+ selwakeup(&pd->pd_selinfo);
+ }
+ PROCDESC_UNLOCK(pd);
+ return (0);
+}
+
+/*
+ * When a process descriptor is reaped, perhaps as a result of close() or
+ * pdwait4(), release the process's reference on the process descriptor.
+ */
+void
+procdesc_reap(struct proc *p)
+{
+ struct procdesc *pd;
+
+ sx_assert(&proctree_lock, SA_XLOCKED);
+ KASSERT(p->p_procdesc != NULL, ("procdesc_reap: p_procdesc == NULL"));
+
+ pd = p->p_procdesc;
+ pd->pd_proc = NULL;
+ procdesc_free(pd);
+}
+
+/*
+ * procdesc_close() - last close on a process descriptor. If the process is
+ * still running, terminate with SIGKILL (unless PD_DAEMON is set) and let
+ * init(8) clean up the mess; if not, we have to clean up the zombie ourselves.
+ */
+static int
+procdesc_close(struct file *fp, struct thread *td)
+{
+ struct procdesc *pd;
+ struct proc *p;
+
+ KASSERT(fp->f_type == DTYPE_PROCDESC, ("procdesc_close: !procdesc"));
+
+ pd = fp->f_data;
+ fp->f_ops = &badfileops;
+ fp->f_data = NULL;
+
+ sx_xlock(&proctree_lock);
+ PROCDESC_LOCK(pd);
+ pd->pd_flags |= PDF_CLOSED;
+ PROCDESC_UNLOCK(pd);
+ p = pd->pd_proc;
+ PROC_LOCK(p);
+ if (p->p_state == PRS_ZOMBIE) {
+ /*
+ * If the process is already dead and just awaiting reaping,
+ * do that now. This will release the process's reference to
+ * the process descriptor when it calls back into
+ * procdesc_reap().
+ */
+ PROC_SLOCK(p);
+ proc_reap(curthread, p, NULL, 0, NULL);
+ } else {
+ /*
+ * If the process is not yet dead, we need to kill it, but we
+ * can't wait around synchronously for it to go away, as that
+ * path leads to madness (and deadlocks). First, detach the
+ * process from its descriptor so that its exit status will
+ * be reported normally.
+ */
+ pd->pd_proc = NULL;
+ p->p_procdesc = NULL;
+ procdesc_free(pd);
+
+ /*
+ * Next, reparent it to init(8) so that there's someone to
+ * pick up the pieces; finally, terminate with prejudice.
+ */
+ p->p_sigparent = SIGCHLD;
+ proc_reparent(p, initproc);
+ if ((pd->pd_flags & PD_DAEMON) == 0)
+ psignal(p, SIGKILL);
+ PROC_UNLOCK(p);
+ sx_xunlock(&proctree_lock);
+ }
+
+ /*
+ * Release the file descriptor's reference on the process descriptor.
+ */
+ procdesc_free(pd);
+ return (0);
+}
+
+static int
+procdesc_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
+ int flags, struct thread *td)
+{
+
+ return (EOPNOTSUPP);
+}
+
+static int
+procdesc_write(struct file *fp, struct uio *uio, struct ucred *active_cred,
+ int flags, struct thread *td)
+{
+
+ return (EOPNOTSUPP);
+}
+
+static int
+procdesc_truncate(struct file *fp, off_t length, struct ucred *active_cred,
+ struct thread *td)
+{
+
+ return (EOPNOTSUPP);
+}
+
+static int
+procdesc_ioctl(struct file *fp, u_long com, void *data,
+ struct ucred *active_cred, struct thread *td)
+{
+
+ return (EOPNOTSUPP);
+}
+
+static int
+procdesc_poll(struct file *fp, int events, struct ucred *active_cred,
+ struct thread *td)
+{
+ struct procdesc *pd;
+ int revents;
+
+ revents = 0;
+ pd = fp->f_data;
+ PROCDESC_LOCK(pd);
+ if (pd->pd_flags & PDF_EXITED)
+ revents |= POLLHUP;
+ if (revents == 0) {
+ selrecord(td, &pd->pd_selinfo);
+ pd->pd_flags |= PDF_SELECTED;
+ }
+ PROCDESC_UNLOCK(pd);
+ return (revents);
+}
+
+static int
+procdesc_kqfilter(struct file *fp, struct knote *kn)
+{
+
+ return (EOPNOTSUPP);
+}
+
+static int
+procdesc_stat(struct file *fp, struct stat *sb, struct ucred *active_cred,
+ struct thread *td)
+{
+ struct procdesc *pd;
+ struct timeval pstart;
+
+ /*
+ * XXXRW: Perhaps we should cache some more information from the
+ * process so that we can return it reliably here even after it has
+ * died. For example, caching its credential data.
+ */
+ bzero(sb, sizeof(*sb));
+ pd = fp->f_data;
+ sx_slock(&proctree_lock);
+ if (pd->pd_proc != NULL) {
+ PROC_LOCK(pd->pd_proc);
+
+ /* Set birth and [acm] times to process start time. */
+ pstart = pd->pd_proc->p_stats->p_start;
+ timevaladd(&pstart, &boottime);
+ TIMEVAL_TO_TIMESPEC(&pstart, &sb->st_birthtim);
+ sb->st_atim = sb->st_birthtim;
+ sb->st_ctim = sb->st_birthtim;
+ sb->st_mtim = sb->st_birthtim;
+ if (pd->pd_proc->p_state != PRS_ZOMBIE)
+ sb->st_mode = S_IFREG | S_IRWXU;
+ else
+ sb->st_mode = S_IFREG;
+ sb->st_uid = pd->pd_proc->p_ucred->cr_ruid;
+ sb->st_gid = pd->pd_proc->p_ucred->cr_rgid;
+ PROC_UNLOCK(pd->pd_proc);
+ } else
+ sb->st_mode = S_IFREG;
+ sx_sunlock(&proctree_lock);
+ return (0);
+}
+
+static int
+procdesc_chmod(struct file *fp, mode_t mode, struct ucred *active_cred,
+ struct thread *td)
+{
+
+ return (EOPNOTSUPP);
+}
+
+static int
+procdesc_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred,
+ struct thread *td)
+{
+
+ return (EOPNOTSUPP);
+}
+
+#else /* !PROCDESC */
+
+int
+pdgetpid(struct thread *td, struct pdgetpid_args *uap)
+{
+
+ return (ENOSYS);
+}
+
+#endif /* PROCDESC */
diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c
index c9b053443f454..cd6f655cc65cb 100644
--- a/sys/kern/sys_socket.c
+++ b/sys/kern/sys_socket.c
@@ -64,6 +64,8 @@ struct fileops socketops = {
.fo_kqfilter = soo_kqfilter,
.fo_stat = soo_stat,
.fo_close = soo_close,
+ .fo_chmod = invfo_chmod,
+ .fo_chown = invfo_chown,
.fo_flags = DFLAG_PASSABLE
};
diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c
index abd94842c184c..e3531880cba6b 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
+ * created from FreeBSD: head/sys/kern/syscalls.master 224987 2011-08-18 22:51:30Z jonathan
*/
const char *syscallnames[] = {
@@ -525,10 +525,10 @@ const char *syscallnames[] = {
"cap_getrights", /* 515 = cap_getrights */
"cap_enter", /* 516 = cap_enter */
"cap_getmode", /* 517 = cap_getmode */
- "#518", /* 518 = pdfork */
- "#519", /* 519 = pdkill */
- "#520", /* 520 = pdgetpid */
- "#521", /* 521 = pdwait */
+ "pdfork", /* 518 = pdfork */
+ "pdkill", /* 519 = pdkill */
+ "pdgetpid", /* 520 = pdgetpid */
+ "#521", /* 521 = pdwait4 */
"pselect", /* 522 = pselect */
"getloginclass", /* 523 = getloginclass */
"setloginclass", /* 524 = setloginclass */
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index 0b249a5b55ad7..b79c6c7109cc2 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -919,10 +919,10 @@
u_int64_t *rightsp); }
516 AUE_CAP_ENTER STD { int cap_enter(void); }
517 AUE_CAP_GETMODE STD { int cap_getmode(u_int *modep); }
-518 AUE_PDFORK UNIMPL pdfork
-519 AUE_PDKILL UNIMPL pdkill
-520 AUE_PDGETPID UNIMPL pdgetpid
-521 AUE_PDWAIT UNIMPL pdwait
+518 AUE_PDFORK STD { int pdfork(int *fdp, int flags); }
+519 AUE_PDKILL STD { int pdkill(int fd, int signum); }
+520 AUE_PDGETPID STD { int pdgetpid(int fd, pid_t *pidp); }
+521 AUE_PDWAIT UNIMPL pdwait4
522 AUE_SELECT STD { int pselect(int nd, fd_set *in, \
fd_set *ou, fd_set *ex, \
const struct timespec *ts, \
diff --git a/sys/kern/systrace_args.c b/sys/kern/systrace_args.c
index f57777f8c898b..9343613d9be61 100644
--- a/sys/kern/systrace_args.c
+++ b/sys/kern/systrace_args.c
@@ -3124,6 +3124,30 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
*n_args = 1;
break;
}
+ /* pdfork */
+ case 518: {
+ struct pdfork_args *p = params;
+ uarg[0] = (intptr_t) p->fdp; /* int * */
+ iarg[1] = p->flags; /* int */
+ *n_args = 2;
+ break;
+ }
+ /* pdkill */
+ case 519: {
+ struct pdkill_args *p = params;
+ iarg[0] = p->fd; /* int */
+ iarg[1] = p->signum; /* int */
+ *n_args = 2;
+ break;
+ }
+ /* pdgetpid */
+ case 520: {
+ struct pdgetpid_args *p = params;
+ iarg[0] = p->fd; /* int */
+ uarg[1] = (intptr_t) p->pidp; /* pid_t * */
+ *n_args = 2;
+ break;
+ }
/* pselect */
case 522: {
struct pselect_args *p = params;
@@ -8381,6 +8405,45 @@ systrace_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
break;
};
break;
+ /* pdfork */
+ case 518:
+ switch(ndx) {
+ case 0:
+ p = "int *";
+ break;
+ case 1:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* pdkill */
+ case 519:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "int";
+ break;
+ default:
+ break;
+ };
+ break;
+ /* pdgetpid */
+ case 520:
+ switch(ndx) {
+ case 0:
+ p = "int";
+ break;
+ case 1:
+ p = "pid_t *";
+ break;
+ default:
+ break;
+ };
+ break;
/* pselect */
case 522:
switch(ndx) {
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index 187e6358f7514..b5fcba91b4a50 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -30,9 +30,11 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_capsicum.h"
#include "opt_compat.h"
#include <sys/param.h>
+#include <sys/capability.h>
#include <sys/conf.h>
#include <sys/cons.h>
#include <sys/fcntl.h>
@@ -764,7 +766,7 @@ ttyil_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
struct thread *td)
{
struct tty *tp = dev->si_drv1;
- int error = 0;
+ int error;
tty_lock(tp);
if (tty_gone(tp)) {
@@ -775,6 +777,7 @@ ttyil_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
error = ttydevsw_cioctl(tp, dev2unit(dev), cmd, data, td);
if (error != ENOIOCTL)
goto done;
+ error = 0;
switch (cmd) {
case TIOCGETA:
@@ -1020,6 +1023,8 @@ tty_dealloc(void *arg)
MPASS(ttyinq_getsize(&tp->t_inq) == 0);
MPASS(ttyoutq_getsize(&tp->t_outq) == 0);
+ seldrain(&tp->t_inpoll);
+ seldrain(&tp->t_outpoll);
knlist_destroy(&tp->t_inpoll.si_note);
knlist_destroy(&tp->t_outpoll.si_note);
@@ -1810,6 +1815,9 @@ ttyhook_register(struct tty **rtp, struct proc *p, int fd,
{
struct tty *tp;
struct file *fp;
+#ifdef CAPABILITIES
+ struct file *fp_cap;
+#endif
struct cdev *dev;
struct cdevsw *cdp;
struct filedesc *fdp;
@@ -1827,6 +1835,13 @@ ttyhook_register(struct tty **rtp, struct proc *p, int fd,
goto done1;
}
+#ifdef CAPABILITIES
+ fp_cap = fp;
+ error = cap_funwrap(fp_cap, CAP_TTYHOOK, &fp);
+ if (error)
+ return (error);
+#endif
+
/*
* Make sure the vnode is bound to a character device.
* Unlocked check for the vnode type is ok there, because we
diff --git a/sys/kern/tty_pts.c b/sys/kern/tty_pts.c
index a3db59bfc5a43..f2f5c4e71bd8f 100644
--- a/sys/kern/tty_pts.c
+++ b/sys/kern/tty_pts.c
@@ -597,6 +597,8 @@ static struct fileops ptsdev_ops = {
.fo_kqfilter = ptsdev_kqfilter,
.fo_stat = ptsdev_stat,
.fo_close = ptsdev_close,
+ .fo_chmod = invfo_chmod,
+ .fo_chown = invfo_chown,
.fo_flags = DFLAG_PASSABLE,
};
@@ -686,6 +688,8 @@ ptsdrv_free(void *softc)
racct_sub_cred(psc->pts_cred, RACCT_NPTS, 1);
crfree(psc->pts_cred);
+ seldrain(&psc->pts_inpoll);
+ seldrain(&psc->pts_outpoll);
knlist_destroy(&psc->pts_inpoll.si_note);
knlist_destroy(&psc->pts_outpoll.si_note);
diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c
index 9b334acb3fe3d..b91b890e8a273 100644
--- a/sys/kern/uipc_mqueue.c
+++ b/sys/kern/uipc_mqueue.c
@@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/limits.h>
#include <sys/buf.h>
+#include <sys/capability.h>
#include <sys/dirent.h>
#include <sys/event.h>
#include <sys/eventhandler.h>
@@ -1561,6 +1562,8 @@ mqueue_free(struct mqueue *mq)
}
mtx_destroy(&mq->mq_mutex);
+ seldrain(&mq->mq_rsel);
+ seldrain(&mq->mq_wsel);
knlist_destroy(&mq->mq_rsel.si_note);
knlist_destroy(&mq->mq_wsel.si_note);
uma_zfree(mqueue_zone, mq);
@@ -2087,19 +2090,19 @@ kmq_unlink(struct thread *td, struct kmq_unlink_args *uap)
return (error);
}
-typedef int (*_fgetf)(struct thread *, int, struct file **);
+typedef int (*_fgetf)(struct thread *, int, cap_rights_t, struct file **);
/*
* Get message queue by giving file slot
*/
static int
-_getmq(struct thread *td, int fd, _fgetf func,
+_getmq(struct thread *td, int fd, cap_rights_t rights, _fgetf func,
struct file **fpp, struct mqfs_node **ppn, struct mqueue **pmq)
{
struct mqfs_node *pn;
int error;
- error = func(td, fd, fpp);
+ error = func(td, fd, rights, fpp);
if (error)
return (error);
if (&mqueueops != (*fpp)->f_ops) {
@@ -2118,21 +2121,21 @@ static __inline int
getmq(struct thread *td, int fd, struct file **fpp, struct mqfs_node **ppn,
struct mqueue **pmq)
{
- return _getmq(td, fd, fget, fpp, ppn, pmq);
+ return _getmq(td, fd, CAP_POLL_EVENT, fget, fpp, ppn, pmq);
}
static __inline int
getmq_read(struct thread *td, int fd, struct file **fpp,
struct mqfs_node **ppn, struct mqueue **pmq)
{
- return _getmq(td, fd, fget_read, fpp, ppn, pmq);
+ return _getmq(td, fd, CAP_READ, fget_read, fpp, ppn, pmq);
}
static __inline int
getmq_write(struct thread *td, int fd, struct file **fpp,
struct mqfs_node **ppn, struct mqueue **pmq)
{
- return _getmq(td, fd, fget_write, fpp, ppn, pmq);
+ return _getmq(td, fd, CAP_WRITE, fget_write, fpp, ppn, pmq);
}
static int
@@ -2243,7 +2246,7 @@ kmq_notify(struct thread *td, struct kmq_notify_args *uap)
struct filedesc *fdp;
struct proc *p;
struct mqueue *mq;
- struct file *fp;
+ struct file *fp, *fp2;
struct mqueue_notifier *nt, *newnt = NULL;
int error;
@@ -2267,7 +2270,18 @@ kmq_notify(struct thread *td, struct kmq_notify_args *uap)
return (error);
again:
FILEDESC_SLOCK(fdp);
- if (fget_locked(fdp, uap->mqd) != fp) {
+ fp2 = fget_locked(fdp, uap->mqd);
+ if (fp2 == NULL) {
+ FILEDESC_SUNLOCK(fdp);
+ error = EBADF;
+ goto out;
+ }
+ error = cap_funwrap(fp2, CAP_POLL_EVENT, &fp2);
+ if (error) {
+ FILEDESC_SUNLOCK(fdp);
+ goto out;
+ }
+ if (fp2 != fp) {
FILEDESC_SUNLOCK(fdp);
error = EBADF;
goto out;
@@ -2457,6 +2471,7 @@ mqf_stat(struct file *fp, struct stat *st, struct ucred *active_cred,
struct mqfs_node *pn = fp->f_data;
bzero(st, sizeof *st);
+ sx_xlock(&mqfs_data.mi_lock);
st->st_atim = pn->mn_atime;
st->st_mtim = pn->mn_mtime;
st->st_ctim = pn->mn_ctime;
@@ -2464,10 +2479,56 @@ mqf_stat(struct file *fp, struct stat *st, struct ucred *active_cred,
st->st_uid = pn->mn_uid;
st->st_gid = pn->mn_gid;
st->st_mode = S_IFIFO | pn->mn_mode;
+ sx_xunlock(&mqfs_data.mi_lock);
return (0);
}
static int
+mqf_chmod(struct file *fp, mode_t mode, struct ucred *active_cred,
+ struct thread *td)
+{
+ struct mqfs_node *pn;
+ int error;
+
+ error = 0;
+ pn = fp->f_data;
+ sx_xlock(&mqfs_data.mi_lock);
+ error = vaccess(VREG, pn->mn_mode, pn->mn_uid, pn->mn_gid, VADMIN,
+ active_cred, NULL);
+ if (error != 0)
+ goto out;
+ pn->mn_mode = mode & ACCESSPERMS;
+out:
+ sx_xunlock(&mqfs_data.mi_lock);
+ return (error);
+}
+
+static int
+mqf_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred,
+ struct thread *td)
+{
+ struct mqfs_node *pn;
+ int error;
+
+ error = 0;
+ pn = fp->f_data;
+ sx_xlock(&mqfs_data.mi_lock);
+ if (uid == (uid_t)-1)
+ uid = pn->mn_uid;
+ if (gid == (gid_t)-1)
+ gid = pn->mn_gid;
+ if (((uid != pn->mn_uid && uid != active_cred->cr_uid) ||
+ (gid != pn->mn_gid && !groupmember(gid, active_cred))) &&
+ (error = priv_check_cred(active_cred, PRIV_VFS_CHOWN, 0)))
+ goto out;
+ pn->mn_uid = uid;
+ pn->mn_gid = gid;
+out:
+ sx_xunlock(&mqfs_data.mi_lock);
+ return (error);
+}
+
+static int
mqf_kqfilter(struct file *fp, struct knote *kn)
{
struct mqueue *mq = FPTOMQ(fp);
@@ -2523,6 +2584,8 @@ static struct fileops mqueueops = {
.fo_poll = mqf_poll,
.fo_kqfilter = mqf_kqfilter,
.fo_stat = mqf_stat,
+ .fo_chmod = mqf_chmod,
+ .fo_chown = mqf_chown,
.fo_close = mqf_close
};
diff --git a/sys/kern/uipc_sem.c b/sys/kern/uipc_sem.c
index 917c343ed3a42..f77bf3b9d5a33 100644
--- a/sys/kern/uipc_sem.c
+++ b/sys/kern/uipc_sem.c
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include "opt_posix.h"
#include <sys/param.h>
+#include <sys/capability.h>
#include <sys/condvar.h>
#include <sys/fcntl.h>
#include <sys/file.h>
@@ -116,7 +117,8 @@ static int ksem_create(struct thread *td, const char *path,
semid_t *semidp, mode_t mode, unsigned int value,
int flags, int compat32);
static void ksem_drop(struct ksem *ks);
-static int ksem_get(struct thread *td, semid_t id, struct file **fpp);
+static int ksem_get(struct thread *td, semid_t id, cap_rights_t rights,
+ struct file **fpp);
static struct ksem *ksem_hold(struct ksem *ks);
static void ksem_insert(char *path, Fnv32_t fnv, struct ksem *ks);
static struct ksem *ksem_lookup(char *path, Fnv32_t fnv);
@@ -133,6 +135,8 @@ static fo_poll_t ksem_poll;
static fo_kqfilter_t ksem_kqfilter;
static fo_stat_t ksem_stat;
static fo_close_t ksem_closef;
+static fo_chmod_t ksem_chmod;
+static fo_chown_t ksem_chown;
/* File descriptor operations. */
static struct fileops ksem_ops = {
@@ -144,6 +148,8 @@ static struct fileops ksem_ops = {
.fo_kqfilter = ksem_kqfilter,
.fo_stat = ksem_stat,
.fo_close = ksem_closef,
+ .fo_chmod = ksem_chmod,
+ .fo_chown = ksem_chown,
.fo_flags = DFLAG_PASSABLE
};
@@ -218,19 +224,76 @@ ksem_stat(struct file *fp, struct stat *sb, struct ucred *active_cred,
* file descriptor.
*/
bzero(sb, sizeof(*sb));
- sb->st_mode = S_IFREG | ks->ks_mode; /* XXX */
+ mtx_lock(&sem_lock);
sb->st_atim = ks->ks_atime;
sb->st_ctim = ks->ks_ctime;
sb->st_mtim = ks->ks_mtime;
- sb->st_birthtim = ks->ks_birthtime;
+ sb->st_birthtim = ks->ks_birthtime;
sb->st_uid = ks->ks_uid;
sb->st_gid = ks->ks_gid;
+ sb->st_mode = S_IFREG | ks->ks_mode; /* XXX */
+ mtx_unlock(&sem_lock);
return (0);
}
static int
+ksem_chmod(struct file *fp, mode_t mode, struct ucred *active_cred,
+ struct thread *td)
+{
+ struct ksem *ks;
+ int error;
+
+ error = 0;
+ ks = fp->f_data;
+ mtx_lock(&sem_lock);
+#ifdef MAC
+ error = mac_posixsem_check_setmode(active_cred, ks, mode);
+ if (error != 0)
+ goto out;
+#endif
+ error = vaccess(VREG, ks->ks_mode, ks->ks_uid, ks->ks_gid, VADMIN,
+ active_cred, NULL);
+ if (error != 0)
+ goto out;
+ ks->ks_mode = mode & ACCESSPERMS;
+out:
+ mtx_unlock(&sem_lock);
+ return (error);
+}
+
+static int
+ksem_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred,
+ struct thread *td)
+{
+ struct ksem *ks;
+ int error;
+
+ error = 0;
+ ks = fp->f_data;
+ mtx_lock(&sem_lock);
+#ifdef MAC
+ error = mac_posixsem_check_setowner(active_cred, ks, uid, gid);
+ if (error != 0)
+ goto out;
+#endif
+ if (uid == (uid_t)-1)
+ uid = ks->ks_uid;
+ if (gid == (gid_t)-1)
+ gid = ks->ks_gid;
+ if (((uid != ks->ks_uid && uid != active_cred->cr_uid) ||
+ (gid != ks->ks_gid && !groupmember(gid, active_cred))) &&
+ (error = priv_check_cred(active_cred, PRIV_VFS_CHOWN, 0)))
+ goto out;
+ ks->ks_uid = uid;
+ ks->ks_gid = gid;
+out:
+ mtx_unlock(&sem_lock);
+ return (error);
+}
+
+static int
ksem_closef(struct file *fp, struct thread *td)
{
struct ksem *ks;
@@ -525,13 +588,13 @@ ksem_create(struct thread *td, const char *name, semid_t *semidp, mode_t mode,
}
static int
-ksem_get(struct thread *td, semid_t id, struct file **fpp)
+ksem_get(struct thread *td, semid_t id, cap_rights_t rights, struct file **fpp)
{
struct ksem *ks;
struct file *fp;
int error;
- error = fget(td, id, &fp);
+ error = fget(td, id, rights, &fp);
if (error)
return (EINVAL);
if (fp->f_type != DTYPE_SEM) {
@@ -623,7 +686,8 @@ ksem_close(struct thread *td, struct ksem_close_args *uap)
struct file *fp;
int error;
- error = ksem_get(td, uap->id, &fp);
+ /* No capability rights required to close a semaphore. */
+ error = ksem_get(td, uap->id, 0, &fp);
if (error)
return (error);
ks = fp->f_data;
@@ -648,7 +712,7 @@ ksem_post(struct thread *td, struct ksem_post_args *uap)
struct ksem *ks;
int error;
- error = ksem_get(td, uap->id, &fp);
+ error = ksem_get(td, uap->id, CAP_SEM_POST, &fp);
if (error)
return (error);
ks = fp->f_data;
@@ -738,7 +802,7 @@ kern_sem_wait(struct thread *td, semid_t id, int tryflag,
int error;
DP((">>> kern_sem_wait entered! pid=%d\n", (int)td->td_proc->p_pid));
- error = ksem_get(td, id, &fp);
+ error = ksem_get(td, id, CAP_SEM_WAIT, &fp);
if (error)
return (error);
ks = fp->f_data;
@@ -804,7 +868,7 @@ ksem_getvalue(struct thread *td, struct ksem_getvalue_args *uap)
struct ksem *ks;
int error, val;
- error = ksem_get(td, uap->id, &fp);
+ error = ksem_get(td, uap->id, CAP_SEM_GETVALUE, &fp);
if (error)
return (error);
ks = fp->f_data;
@@ -838,7 +902,8 @@ ksem_destroy(struct thread *td, struct ksem_destroy_args *uap)
struct ksem *ks;
int error;
- error = ksem_get(td, uap->id, &fp);
+ /* No capability rights required to close a semaphore. */
+ error = ksem_get(td, uap->id, 0, &fp);
if (error)
return (error);
ks = fp->f_data;
diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c
index 0414f1283e769..f9fc3ca8bf30e 100644
--- a/sys/kern/uipc_shm.c
+++ b/sys/kern/uipc_shm.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2006 Robert N. M. Watson
+ * Copyright (c) 2006, 2011 Robert N. M. Watson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,25 +31,21 @@
*
* TODO:
*
- * (2) Need to export data to a userland tool via a sysctl. Should ipcs(1)
+ * (1) Need to export data to a userland tool via a sysctl. Should ipcs(1)
* and ipcrm(1) be expanded or should new tools to manage both POSIX
* kernel semaphores and POSIX shared memory be written?
*
- * (3) Add support for this file type to fstat(1).
+ * (2) Add support for this file type to fstat(1).
*
- * (4) Resource limits? Does this need its own resource limits or are the
+ * (3) Resource limits? Does this need its own resource limits or are the
* existing limits in mmap(2) sufficient?
*
- * (5) Partial page truncation. vnode_pager_setsize() will zero any parts
+ * (4) Partial page truncation. vnode_pager_setsize() will zero any parts
* of a partially mapped page as a result of ftruncate(2)/truncate(2).
* We can do the same (with the same pmap evil), but do we need to
* worry about the bits on disk if the page is swapped out or will the
* swapper zero the parts of a page that are invalid if the page is
* swapped back in for us?
- *
- * (6) Add MAC support in mac_biba(4) and mac_mls(4).
- *
- * (7) Add a MAC check_create() hook for creating new named objects.
*/
#include <sys/cdefs.h>
@@ -68,6 +64,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/mman.h>
#include <sys/mutex.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/refcount.h>
#include <sys/resourcevar.h>
@@ -123,6 +120,8 @@ static fo_poll_t shm_poll;
static fo_kqfilter_t shm_kqfilter;
static fo_stat_t shm_stat;
static fo_close_t shm_close;
+static fo_chmod_t shm_chmod;
+static fo_chown_t shm_chown;
/* File descriptor operations. */
static struct fileops shm_ops = {
@@ -134,6 +133,8 @@ static struct fileops shm_ops = {
.fo_kqfilter = shm_kqfilter,
.fo_stat = shm_stat,
.fo_close = shm_close,
+ .fo_chmod = shm_chmod,
+ .fo_chown = shm_chown,
.fo_flags = DFLAG_PASSABLE
};
@@ -218,16 +219,18 @@ shm_stat(struct file *fp, struct stat *sb, struct ucred *active_cred,
* descriptor.
*/
bzero(sb, sizeof(*sb));
- sb->st_mode = S_IFREG | shmfd->shm_mode; /* XXX */
sb->st_blksize = PAGE_SIZE;
sb->st_size = shmfd->shm_size;
sb->st_blocks = (sb->st_size + sb->st_blksize - 1) / sb->st_blksize;
+ mtx_lock(&shm_timestamp_lock);
sb->st_atim = shmfd->shm_atime;
sb->st_ctim = shmfd->shm_ctime;
sb->st_mtim = shmfd->shm_mtime;
- sb->st_birthtim = shmfd->shm_birthtime;
+ sb->st_birthtim = shmfd->shm_birthtime;
+ sb->st_mode = S_IFREG | shmfd->shm_mode; /* XXX */
sb->st_uid = shmfd->shm_uid;
sb->st_gid = shmfd->shm_gid;
+ mtx_unlock(&shm_timestamp_lock);
return (0);
}
@@ -395,14 +398,18 @@ static int
shm_access(struct shmfd *shmfd, struct ucred *ucred, int flags)
{
accmode_t accmode;
+ int error;
accmode = 0;
if (flags & FREAD)
accmode |= VREAD;
if (flags & FWRITE)
accmode |= VWRITE;
- return (vaccess(VREG, shmfd->shm_mode, shmfd->shm_uid, shmfd->shm_gid,
- accmode, ucred, NULL));
+ mtx_lock(&shm_timestamp_lock);
+ error = vaccess(VREG, shmfd->shm_mode, shmfd->shm_uid, shmfd->shm_gid,
+ accmode, ucred, NULL);
+ mtx_unlock(&shm_timestamp_lock);
+ return (error);
}
/*
@@ -540,8 +547,16 @@ shm_open(struct thread *td, struct shm_open_args *uap)
if (shmfd == NULL) {
/* Object does not yet exist, create it if requested. */
if (uap->flags & O_CREAT) {
- shmfd = shm_alloc(td->td_ucred, cmode);
- shm_insert(path, fnv, shmfd);
+#ifdef MAC
+ error = mac_posixshm_check_create(td->td_ucred,
+ path);
+ if (error == 0) {
+#endif
+ shmfd = shm_alloc(td->td_ucred, cmode);
+ shm_insert(path, fnv, shmfd);
+#ifdef MAC
+ }
+#endif
} else {
free(path, M_SHMFD);
error = ENOENT;
@@ -558,7 +573,7 @@ shm_open(struct thread *td, struct shm_open_args *uap)
else {
#ifdef MAC
error = mac_posixshm_check_open(td->td_ucred,
- shmfd);
+ shmfd, FFLAGS(uap->flags & O_ACCMODE));
if (error == 0)
#endif
error = shm_access(shmfd, td->td_ucred,
@@ -651,3 +666,62 @@ shm_mmap(struct shmfd *shmfd, vm_size_t objsize, vm_ooffset_t foff,
*obj = shmfd->shm_object;
return (0);
}
+
+static int
+shm_chmod(struct file *fp, mode_t mode, struct ucred *active_cred,
+ struct thread *td)
+{
+ struct shmfd *shmfd;
+ int error;
+
+ error = 0;
+ shmfd = fp->f_data;
+ mtx_lock(&shm_timestamp_lock);
+ /*
+ * SUSv4 says that x bits of permission need not be affected.
+ * Be consistent with our shm_open there.
+ */
+#ifdef MAC
+ error = mac_posixshm_check_setmode(active_cred, shmfd, mode);
+ if (error != 0)
+ goto out;
+#endif
+ error = vaccess(VREG, shmfd->shm_mode, shmfd->shm_uid,
+ shmfd->shm_gid, VADMIN, active_cred, NULL);
+ if (error != 0)
+ goto out;
+ shmfd->shm_mode = mode & ACCESSPERMS;
+out:
+ mtx_unlock(&shm_timestamp_lock);
+ return (error);
+}
+
+static int
+shm_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred,
+ struct thread *td)
+{
+ struct shmfd *shmfd;
+ int error;
+
+ error = 0;
+ shmfd = fp->f_data;
+ mtx_lock(&shm_timestamp_lock);
+#ifdef MAC
+ error = mac_posixshm_check_setowner(active_cred, shmfd, uid, gid);
+ if (error != 0)
+ goto out;
+#endif
+ if (uid == (uid_t)-1)
+ uid = shmfd->shm_uid;
+ if (gid == (gid_t)-1)
+ gid = shmfd->shm_gid;
+ if (((uid != shmfd->shm_uid && uid != active_cred->cr_uid) ||
+ (gid != shmfd->shm_gid && !groupmember(gid, active_cred))) &&
+ (error = priv_check_cred(active_cred, PRIV_VFS_CHOWN, 0)))
+ goto out;
+ shmfd->shm_uid = uid;
+ shmfd->shm_gid = gid;
+out:
+ mtx_unlock(&shm_timestamp_lock);
+ return (error);
+}
diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c
index 2d86d740996c0..551afac00138e 100644
--- a/sys/kern/uipc_sockbuf.c
+++ b/sys/kern/uipc_sockbuf.c
@@ -61,7 +61,7 @@ void (*aio_swake)(struct socket *, struct sockbuf *);
u_long sb_max = SB_MAX;
u_long sb_max_adj =
- SB_MAX * MCLBYTES / (MSIZE + MCLBYTES); /* adjusted sb_max */
+ (quad_t)SB_MAX * MCLBYTES / (MSIZE + MCLBYTES); /* adjusted sb_max */
static u_long sb_efficiency = 8; /* parameter for sbreserve() */
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index 990c6bad11f89..bbd4fad38749b 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -661,6 +661,8 @@ sofree(struct socket *so)
*/
sbdestroy(&so->so_snd, so);
sbdestroy(&so->so_rcv, so);
+ seldrain(&so->so_snd.sb_sel);
+ seldrain(&so->so_rcv.sb_sel);
knlist_destroy(&so->so_rcv.sb_sel.si_note);
knlist_destroy(&so->so_snd.sb_sel.si_note);
sodealloc(so);
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
index c434973a1b675..0e5efe6f3a9be 100644
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -120,33 +120,47 @@ SYSCTL_INT(_kern_ipc, OID_AUTO, nsfbufsused, CTLFLAG_RD, &nsfbufsused, 0,
"Number of sendfile(2) sf_bufs in use");
/*
- * Convert a user file descriptor to a kernel file entry. A reference on the
- * file entry is held upon returning. This is lighter weight than
- * fgetsock(), which bumps the socket reference drops the file reference
- * count instead, as this approach avoids several additional mutex operations
- * associated with the additional reference count. If requested, return the
- * open file flags.
+ * Convert a user file descriptor to a kernel file entry and check that, if
+ * it is a capability, the right rights are present. A reference on the file
+ * entry is held upon returning.
*/
static int
-getsock(struct filedesc *fdp, int fd, struct file **fpp, u_int *fflagp)
+getsock_cap(struct filedesc *fdp, int fd, cap_rights_t rights,
+ struct file **fpp, u_int *fflagp)
{
struct file *fp;
+#ifdef CAPABILITIES
+ struct file *fp_fromcap;
int error;
+#endif
fp = NULL;
- if (fdp == NULL || (fp = fget_unlocked(fdp, fd)) == NULL) {
- error = EBADF;
- } else if (fp->f_type != DTYPE_SOCKET) {
+ if ((fdp == NULL) || ((fp = fget_unlocked(fdp, fd)) == NULL))
+ return (EBADF);
+#ifdef CAPABILITIES
+ /*
+ * If the file descriptor is for a capability, test rights and use
+ * the file descriptor referenced by the capability.
+ */
+ error = cap_funwrap(fp, rights, &fp_fromcap);
+ if (error) {
fdrop(fp, curthread);
- fp = NULL;
- error = ENOTSOCK;
- } else {
- if (fflagp != NULL)
- *fflagp = fp->f_flag;
- error = 0;
+ return (error);
}
+ if (fp != fp_fromcap) {
+ fhold(fp_fromcap);
+ fdrop(fp, curthread);
+ fp = fp_fromcap;
+ }
+#endif /* CAPABILITIES */
+ if (fp->f_type != DTYPE_SOCKET) {
+ fdrop(fp, curthread);
+ return (ENOTSOCK);
+ }
+ if (fflagp != NULL)
+ *fflagp = fp->f_flag;
*fpp = fp;
- return (error);
+ return (0);
}
/*
@@ -226,7 +240,7 @@ kern_bind(td, fd, sa)
int error;
AUDIT_ARG_FD(fd);
- error = getsock(td->td_proc->p_fd, fd, &fp, NULL);
+ error = getsock_cap(td->td_proc->p_fd, fd, CAP_BIND, &fp, NULL);
if (error)
return (error);
so = fp->f_data;
@@ -257,7 +271,7 @@ listen(td, uap)
int error;
AUDIT_ARG_FD(uap->s);
- error = getsock(td->td_proc->p_fd, uap->s, &fp, NULL);
+ error = getsock_cap(td->td_proc->p_fd, uap->s, CAP_LISTEN, &fp, NULL);
if (error == 0) {
so = fp->f_data;
#ifdef MAC
@@ -347,7 +361,7 @@ kern_accept(struct thread *td, int s, struct sockaddr **name,
AUDIT_ARG_FD(s);
fdp = td->td_proc->p_fd;
- error = getsock(fdp, s, &headfp, &fflag);
+ error = getsock_cap(fdp, s, CAP_ACCEPT, &headfp, &fflag);
if (error)
return (error);
head = headfp->f_data;
@@ -535,7 +549,7 @@ kern_connect(td, fd, sa)
int interrupted = 0;
AUDIT_ARG_FD(fd);
- error = getsock(td->td_proc->p_fd, fd, &fp, NULL);
+ error = getsock_cap(td->td_proc->p_fd, fd, CAP_CONNECT, &fp, NULL);
if (error)
return (error);
so = fp->f_data;
@@ -744,12 +758,16 @@ kern_sendit(td, s, mp, flags, control, segflg)
struct socket *so;
int i;
int len, error;
+ cap_rights_t rights;
#ifdef KTRACE
struct uio *ktruio = NULL;
#endif
AUDIT_ARG_FD(s);
- error = getsock(td->td_proc->p_fd, s, &fp, NULL);
+ rights = CAP_WRITE;
+ if (mp->msg_name != NULL)
+ rights |= CAP_CONNECT;
+ error = getsock_cap(td->td_proc->p_fd, s, rights, &fp, NULL);
if (error)
return (error);
so = (struct socket *)fp->f_data;
@@ -953,7 +971,7 @@ kern_recvit(td, s, mp, fromseg, controlp)
*controlp = NULL;
AUDIT_ARG_FD(s);
- error = getsock(td->td_proc->p_fd, s, &fp, NULL);
+ error = getsock_cap(td->td_proc->p_fd, s, CAP_READ, &fp, NULL);
if (error)
return (error);
so = fp->f_data;
@@ -1267,7 +1285,8 @@ shutdown(td, uap)
int error;
AUDIT_ARG_FD(uap->s);
- error = getsock(td->td_proc->p_fd, uap->s, &fp, NULL);
+ error = getsock_cap(td->td_proc->p_fd, uap->s, CAP_SHUTDOWN, &fp,
+ NULL);
if (error == 0) {
so = fp->f_data;
error = soshutdown(so, uap->how);
@@ -1330,7 +1349,7 @@ kern_setsockopt(td, s, level, name, val, valseg, valsize)
}
AUDIT_ARG_FD(s);
- error = getsock(td->td_proc->p_fd, s, &fp, NULL);
+ error = getsock_cap(td->td_proc->p_fd, s, CAP_SETSOCKOPT, &fp, NULL);
if (error == 0) {
so = fp->f_data;
error = sosetopt(so, &sopt);
@@ -1409,7 +1428,7 @@ kern_getsockopt(td, s, level, name, val, valseg, valsize)
}
AUDIT_ARG_FD(s);
- error = getsock(td->td_proc->p_fd, s, &fp, NULL);
+ error = getsock_cap(td->td_proc->p_fd, s, CAP_GETSOCKOPT, &fp, NULL);
if (error == 0) {
so = fp->f_data;
error = sogetopt(so, &sopt);
@@ -1471,7 +1490,7 @@ kern_getsockname(struct thread *td, int fd, struct sockaddr **sa,
return (EINVAL);
AUDIT_ARG_FD(fd);
- error = getsock(td->td_proc->p_fd, fd, &fp, NULL);
+ error = getsock_cap(td->td_proc->p_fd, fd, CAP_GETSOCKNAME, &fp, NULL);
if (error)
return (error);
so = fp->f_data;
@@ -1571,7 +1590,7 @@ kern_getpeername(struct thread *td, int fd, struct sockaddr **sa,
return (EINVAL);
AUDIT_ARG_FD(fd);
- error = getsock(td->td_proc->p_fd, fd, &fp, NULL);
+ error = getsock_cap(td->td_proc->p_fd, fd, CAP_GETPEERNAME, &fp, NULL);
if (error)
return (error);
so = fp->f_data;
@@ -1827,7 +1846,7 @@ kern_sendfile(struct thread *td, struct sendfile_args *uap,
* we send only the header/trailer and no payload data.
*/
AUDIT_ARG_FD(uap->fd);
- if ((error = fgetvp_read(td, uap->fd, &vp)) != 0)
+ if ((error = fgetvp_read(td, uap->fd, CAP_READ, &vp)) != 0)
goto out;
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
vn_lock(vp, LK_SHARED | LK_RETRY);
@@ -1865,8 +1884,8 @@ kern_sendfile(struct thread *td, struct sendfile_args *uap,
* The socket must be a stream socket and connected.
* Remember if it a blocking or non-blocking socket.
*/
- if ((error = getsock(td->td_proc->p_fd, uap->s, &sock_fp,
- NULL)) != 0)
+ if ((error = getsock_cap(td->td_proc->p_fd, uap->s, CAP_WRITE,
+ &sock_fp, NULL)) != 0)
goto out;
so = sock_fp->f_data;
if (so->so_type != SOCK_STREAM) {
@@ -2298,7 +2317,7 @@ sctp_peeloff(td, uap)
fdp = td->td_proc->p_fd;
AUDIT_ARG_FD(uap->sd);
- error = fgetsock(td, uap->sd, &head, &fflag);
+ error = fgetsock(td, uap->sd, CAP_PEELOFF, &head, &fflag);
if (error)
goto done2;
error = sctp_can_peel_off(head, (sctp_assoc_t)uap->name);
@@ -2391,6 +2410,7 @@ sctp_generic_sendmsg (td, uap)
#endif
struct uio auio;
struct iovec iov[1];
+ cap_rights_t rights;
if (uap->sinfo) {
error = copyin(uap->sinfo, &sinfo, sizeof (sinfo));
@@ -2398,16 +2418,19 @@ sctp_generic_sendmsg (td, uap)
return (error);
u_sinfo = &sinfo;
}
+
+ rights = CAP_WRITE;
if (uap->tolen) {
error = getsockaddr(&to, uap->to, uap->tolen);
if (error) {
to = NULL;
goto sctp_bad2;
}
+ rights |= CAP_CONNECT;
}
AUDIT_ARG_FD(uap->sd);
- error = getsock(td->td_proc->p_fd, uap->sd, &fp, NULL);
+ error = getsock_cap(td->td_proc->p_fd, uap->sd, rights, &fp, NULL);
if (error)
goto sctp_bad;
#ifdef KTRACE
@@ -2494,6 +2517,7 @@ sctp_generic_sendmsg_iov(td, uap)
#endif
struct uio auio;
struct iovec *iov, *tiov;
+ cap_rights_t rights;
if (uap->sinfo) {
error = copyin(uap->sinfo, &sinfo, sizeof (sinfo));
@@ -2501,16 +2525,18 @@ sctp_generic_sendmsg_iov(td, uap)
return (error);
u_sinfo = &sinfo;
}
+ rights = CAP_WRITE;
if (uap->tolen) {
error = getsockaddr(&to, uap->to, uap->tolen);
if (error) {
to = NULL;
goto sctp_bad2;
}
+ rights |= CAP_CONNECT;
}
AUDIT_ARG_FD(uap->sd);
- error = getsock(td->td_proc->p_fd, uap->sd, &fp, NULL);
+ error = getsock_cap(td->td_proc->p_fd, uap->sd, rights, &fp, NULL);
if (error)
goto sctp_bad1;
@@ -2618,7 +2644,7 @@ sctp_generic_recvmsg(td, uap)
#endif
AUDIT_ARG_FD(uap->sd);
- error = getsock(td->td_proc->p_fd, uap->sd, &fp, NULL);
+ error = getsock_cap(td->td_proc->p_fd, uap->sd, CAP_READ, &fp, NULL);
if (error) {
return (error);
}
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index 4bad3869fe852..3a34f58605b5e 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -816,7 +816,7 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
struct unpcb *unp, *unp2;
struct socket *so2;
u_int mbcnt_delta, sbcc;
- u_long newhiwat;
+ u_int newhiwat;
int error = 0;
unp = sotounpcb(so);
@@ -974,7 +974,10 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
sorwakeup_locked(so2);
SOCKBUF_LOCK(&so->so_snd);
- newhiwat = so->so_snd.sb_hiwat - (sbcc - unp2->unp_cc);
+ if ((int)so->so_snd.sb_hiwat >= (int)(sbcc - unp2->unp_cc))
+ newhiwat = so->so_snd.sb_hiwat - (sbcc - unp2->unp_cc);
+ else
+ newhiwat = 0;
(void)chgsbsize(so->so_cred->cr_uidinfo, &so->so_snd.sb_hiwat,
newhiwat, RLIM_INFINITY);
so->so_snd.sb_mbmax -= mbcnt_delta;
diff --git a/sys/kern/vfs_acl.c b/sys/kern/vfs_acl.c
index b1cda38419e51..9010a5068bfb9 100644
--- a/sys/kern/vfs_acl.c
+++ b/sys/kern/vfs_acl.c
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sysproto.h>
+#include <sys/capability.h>
#include <sys/fcntl.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
@@ -408,7 +409,7 @@ __acl_get_fd(struct thread *td, struct __acl_get_fd_args *uap)
struct file *fp;
int vfslocked, error;
- error = getvnode(td->td_proc->p_fd, uap->filedes, &fp);
+ error = getvnode(td->td_proc->p_fd, uap->filedes, CAP_ACL_GET, &fp);
if (error == 0) {
vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
error = vacl_get_acl(td, fp->f_vnode, uap->type, uap->aclp);
@@ -427,7 +428,7 @@ __acl_set_fd(struct thread *td, struct __acl_set_fd_args *uap)
struct file *fp;
int vfslocked, error;
- error = getvnode(td->td_proc->p_fd, uap->filedes, &fp);
+ error = getvnode(td->td_proc->p_fd, uap->filedes, CAP_ACL_SET, &fp);
if (error == 0) {
vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
error = vacl_set_acl(td, fp->f_vnode, uap->type, uap->aclp);
@@ -486,7 +487,8 @@ __acl_delete_fd(struct thread *td, struct __acl_delete_fd_args *uap)
struct file *fp;
int vfslocked, error;
- error = getvnode(td->td_proc->p_fd, uap->filedes, &fp);
+ error = getvnode(td->td_proc->p_fd, uap->filedes, CAP_ACL_DELETE,
+ &fp);
if (error == 0) {
vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
error = vacl_delete(td, fp->f_vnode, uap->type);
@@ -545,7 +547,8 @@ __acl_aclcheck_fd(struct thread *td, struct __acl_aclcheck_fd_args *uap)
struct file *fp;
int vfslocked, error;
- error = getvnode(td->td_proc->p_fd, uap->filedes, &fp);
+ error = getvnode(td->td_proc->p_fd, uap->filedes, CAP_ACL_CHECK,
+ &fp);
if (error == 0) {
vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
error = vacl_aclcheck(td, fp->f_vnode, uap->type, uap->aclp);
diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c
index 69b4e0a00c70e..aedbdd05385aa 100644
--- a/sys/kern/vfs_aio.c
+++ b/sys/kern/vfs_aio.c
@@ -28,6 +28,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/bio.h>
#include <sys/buf.h>
+#include <sys/capability.h>
#include <sys/eventhandler.h>
#include <sys/sysproto.h>
#include <sys/filedesc.h>
@@ -1577,17 +1578,30 @@ aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj,
aiocbe->uaiocb.aio_lio_opcode = type;
opcode = aiocbe->uaiocb.aio_lio_opcode;
- /* Fetch the file object for the specified file descriptor. */
+ /*
+ * Validate the opcode and fetch the file object for the specified
+ * file descriptor.
+ *
+ * XXXRW: Moved the opcode validation up here so that we don't
+ * retrieve a file descriptor without knowing what the capabiltity
+ * should be.
+ */
fd = aiocbe->uaiocb.aio_fildes;
switch (opcode) {
case LIO_WRITE:
- error = fget_write(td, fd, &fp);
+ error = fget_write(td, fd, CAP_WRITE | CAP_SEEK, &fp);
break;
case LIO_READ:
- error = fget_read(td, fd, &fp);
+ error = fget_read(td, fd, CAP_READ | CAP_SEEK, &fp);
+ break;
+ case LIO_SYNC:
+ error = fget(td, fd, CAP_FSYNC, &fp);
+ break;
+ case LIO_NOP:
+ error = fget(td, fd, 0, &fp);
break;
default:
- error = fget(td, fd, &fp);
+ error = EINVAL;
}
if (error) {
uma_zfree(aiocb_zone, aiocbe);
@@ -1623,11 +1637,6 @@ aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj,
uma_zfree(aiocb_zone, aiocbe);
return (0);
}
- if ((opcode != LIO_READ) && (opcode != LIO_WRITE) &&
- (opcode != LIO_SYNC)) {
- error = EINVAL;
- goto aqueue_fail;
- }
if (aiocbe->uaiocb.aio_sigevent.sigev_notify != SIGEV_KEVENT)
goto no_kqueue;
@@ -1971,7 +1980,7 @@ aio_cancel(struct thread *td, struct aio_cancel_args *uap)
struct vnode *vp;
/* Lookup file object. */
- error = fget(td, uap->fd, &fp);
+ error = fget(td, uap->fd, 0, &fp);
if (error)
return (error);
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index a6ad81e9e03bc..7b5b0154c6b69 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -4020,7 +4020,7 @@ DB_SHOW_COMMAND(buffer, db_show_buffer)
db_printf("\n");
}
db_printf(" ");
- lockmgr_printinfo(&bp->b_lock);
+ BUF_LOCKPRINTINFO(bp);
}
DB_SHOW_COMMAND(lockedbufs, lockedbufs)
diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c
index e7bf2d19d7d39..b8b9cdf058bdf 100644
--- a/sys/kern/vfs_extattr.c
+++ b/sys/kern/vfs_extattr.c
@@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/capability.h>
#include <sys/lock.h>
#include <sys/mount.h>
#include <sys/mutex.h>
@@ -230,7 +231,7 @@ extattr_set_fd(td, uap)
return (error);
AUDIT_ARG_TEXT(attrname);
- error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
+ error = getvnode(td->td_proc->p_fd, uap->fd, CAP_EXTATTR_SET, &fp);
if (error)
return (error);
@@ -410,7 +411,7 @@ extattr_get_fd(td, uap)
return (error);
AUDIT_ARG_TEXT(attrname);
- error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
+ error = getvnode(td->td_proc->p_fd, uap->fd, CAP_EXTATTR_GET, &fp);
if (error)
return (error);
@@ -560,7 +561,8 @@ extattr_delete_fd(td, uap)
return (error);
AUDIT_ARG_TEXT(attrname);
- error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
+ error = getvnode(td->td_proc->p_fd, uap->fd, CAP_EXTATTR_DELETE,
+ &fp);
if (error)
return (error);
@@ -719,7 +721,7 @@ extattr_list_fd(td, uap)
AUDIT_ARG_FD(uap->fd);
AUDIT_ARG_VALUE(uap->attrnamespace);
- error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
+ error = getvnode(td->td_proc->p_fd, uap->fd, CAP_EXTATTR_LIST, &fp);
if (error)
return (error);
diff --git a/sys/kern/vfs_init.c b/sys/kern/vfs_init.c
index 4367b8c8096ba..0165b38c3cd55 100644
--- a/sys/kern/vfs_init.c
+++ b/sys/kern/vfs_init.c
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/fnv_hash.h>
#include <sys/kernel.h>
#include <sys/linker.h>
#include <sys/mount.h>
@@ -65,6 +66,18 @@ int maxvfsconf = VFS_GENERIC + 1;
struct vfsconfhead vfsconf = TAILQ_HEAD_INITIALIZER(vfsconf);
/*
+ * Loader.conf variable vfs.typenumhash enables setting vfc_typenum using a hash
+ * calculation on vfc_name, so that it doesn't change when file systems are
+ * loaded in a different order. This will avoid the NFS server file handles from
+ * changing for file systems that use vfc_typenum in their fsid.
+ */
+static int vfs_typenumhash = 1;
+TUNABLE_INT("vfs.typenumhash", &vfs_typenumhash);
+SYSCTL_INT(_vfs, OID_AUTO, typenumhash, CTLFLAG_RDTUN, &vfs_typenumhash, 0,
+ "Set vfc_typenum using a hash calculation on vfc_name, so that it does not"
+ "change when file systems are loaded in a different order.");
+
+/*
* A Zen vnode attribute structure.
*
* Initialized when the first filesystem registers by vfs_register().
@@ -138,6 +151,9 @@ vfs_register(struct vfsconf *vfc)
struct sysctl_oid *oidp;
struct vfsops *vfsops;
static int once;
+ struct vfsconf *tvfc;
+ uint32_t hashval;
+ int secondpass;
if (!once) {
vattr_null(&va_null);
@@ -152,7 +168,34 @@ vfs_register(struct vfsconf *vfc)
if (vfs_byname(vfc->vfc_name) != NULL)
return EEXIST;
- vfc->vfc_typenum = maxvfsconf++;
+ if (vfs_typenumhash != 0) {
+ /*
+ * Calculate a hash on vfc_name to use for vfc_typenum. Unless
+ * all of 1<->255 are assigned, it is limited to 8bits since
+ * that is what ZFS uses from vfc_typenum and is also the
+ * preferred range for vfs_getnewfsid().
+ */
+ hashval = fnv_32_str(vfc->vfc_name, FNV1_32_INIT);
+ hashval &= 0xff;
+ secondpass = 0;
+ do {
+ /* Look for and fix any collision. */
+ TAILQ_FOREACH(tvfc, &vfsconf, vfc_list) {
+ if (hashval == tvfc->vfc_typenum) {
+ if (hashval == 255 && secondpass == 0) {
+ hashval = 1;
+ secondpass = 1;
+ } else
+ hashval++;
+ break;
+ }
+ }
+ } while (tvfc != NULL);
+ vfc->vfc_typenum = hashval;
+ if (vfc->vfc_typenum >= maxvfsconf)
+ maxvfsconf = vfc->vfc_typenum + 1;
+ } else
+ vfc->vfc_typenum = maxvfsconf++;
TAILQ_INSERT_TAIL(&vfsconf, vfc, vfc_list);
/*
diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
index 50a2570254f46..a14501704fa97 100644
--- a/sys/kern/vfs_lookup.c
+++ b/sys/kern/vfs_lookup.c
@@ -37,12 +37,14 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_capsicum.h"
#include "opt_kdtrace.h"
#include "opt_ktrace.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/capability.h>
#include <sys/fcntl.h>
#include <sys/jail.h>
#include <sys/lock.h>
@@ -178,6 +180,18 @@ namei(struct nameidata *ndp)
if (!error && *cnp->cn_pnbuf == '\0')
error = ENOENT;
+#ifdef CAPABILITY_MODE
+ /*
+ * In capability mode, lookups must be "strictly relative" (i.e.
+ * not an absolute path, and not containing '..' components) to
+ * a real file descriptor, not the pseudo-descriptor AT_FDCWD.
+ */
+ if (IN_CAPABILITY_MODE(td)) {
+ ndp->ni_strictrelative = 1;
+ if (ndp->ni_dirfd == AT_FDCWD)
+ error = ECAPMODE;
+ }
+#endif
if (error) {
uma_zfree(namei_zone, cnp->cn_pnbuf);
#ifdef DIAGNOSTIC
@@ -212,7 +226,20 @@ namei(struct nameidata *ndp)
AUDIT_ARG_ATFD1(ndp->ni_dirfd);
if (cnp->cn_flags & AUDITVNODE2)
AUDIT_ARG_ATFD2(ndp->ni_dirfd);
- error = fgetvp(td, ndp->ni_dirfd, &dp);
+ error = fgetvp_rights(td, ndp->ni_dirfd,
+ ndp->ni_rightsneeded | CAP_LOOKUP,
+ &(ndp->ni_baserights), &dp);
+#ifdef CAPABILITIES
+ /*
+ * Lookups relative to a capability must also be
+ * strictly relative.
+ *
+ * Note that a capability with rights CAP_MASK_VALID
+ * is treated exactly like a regular file descriptor.
+ */
+ if (ndp->ni_baserights != CAP_MASK_VALID)
+ ndp->ni_strictrelative = 1;
+#endif
}
if (error != 0 || dp != NULL) {
FILEDESC_SUNLOCK(fdp);
@@ -254,6 +281,8 @@ namei(struct nameidata *ndp)
if (*(cnp->cn_nameptr) == '/') {
vrele(dp);
VFS_UNLOCK_GIANT(vfslocked);
+ if (ndp->ni_strictrelative != 0)
+ return (ENOTCAPABLE);
while (*(cnp->cn_nameptr) == '/') {
cnp->cn_nameptr++;
ndp->ni_pathlen--;
@@ -597,7 +626,10 @@ dirloop:
}
/*
- * Handle "..": four special cases.
+ * Handle "..": five special cases.
+ * 0. If doing a capability lookup, return ENOTCAPABLE (this is a
+ * fairly conservative design choice, but it's the only one that we
+ * are satisfied guarantees the property we're looking for).
* 1. Return an error if this is the last component of
* the name and the operation is DELETE or RENAME.
* 2. If at root directory (e.g. after chroot)
@@ -611,6 +643,10 @@ dirloop:
* the jail or chroot, don't let them out.
*/
if (cnp->cn_flags & ISDOTDOT) {
+ if (ndp->ni_strictrelative != 0) {
+ error = ENOTCAPABLE;
+ goto bad;
+ }
if ((cnp->cn_flags & ISLASTCN) != 0 &&
(cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) {
error = EINVAL;
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index 5edf0f52acbb7..5d6892c5e9b73 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -1496,7 +1496,8 @@ vfs_getopts(struct vfsoptlist *opts, const char *name, int *error)
}
int
-vfs_flagopt(struct vfsoptlist *opts, const char *name, u_int *w, u_int val)
+vfs_flagopt(struct vfsoptlist *opts, const char *name, uint64_t *w,
+ uint64_t val)
{
struct vfsopt *opt;
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 934745b433b64..325ca99deb32a 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -2841,6 +2841,7 @@ DB_SHOW_COMMAND(mount, db_show_mount)
MNT_FLAG(MNT_ASYNC);
MNT_FLAG(MNT_SUIDDIR);
MNT_FLAG(MNT_SOFTDEP);
+ MNT_FLAG(MNT_SUJ);
MNT_FLAG(MNT_NOSYMFOLLOW);
MNT_FLAG(MNT_GJOURNAL);
MNT_FLAG(MNT_MULTILABEL);
@@ -2866,7 +2867,6 @@ DB_SHOW_COMMAND(mount, db_show_mount)
MNT_FLAG(MNT_FORCE);
MNT_FLAG(MNT_SNAPSHOT);
MNT_FLAG(MNT_BYFSID);
- MNT_FLAG(MNT_SOFTDEP);
#undef MNT_FLAG
if (flags != 0) {
if (buf[0] != '\0')
@@ -2894,7 +2894,6 @@ DB_SHOW_COMMAND(mount, db_show_mount)
MNT_KERN_FLAG(MNTK_REFEXPIRE);
MNT_KERN_FLAG(MNTK_EXTENDED_SHARED);
MNT_KERN_FLAG(MNTK_SHARED_WRITES);
- MNT_KERN_FLAG(MNTK_SUJ);
MNT_KERN_FLAG(MNTK_UNMOUNT);
MNT_KERN_FLAG(MNTK_MWAIT);
MNT_KERN_FLAG(MNTK_SUSPEND);
@@ -3313,6 +3312,7 @@ vbusy(struct vnode *vp)
static void
destroy_vpollinfo(struct vpollinfo *vi)
{
+ seldrain(&vi->vpi_selinfo);
knlist_destroy(&vi->vpi_selinfo.si_note);
mtx_destroy(&vi->vpi_lock);
uma_zfree(vnodepoll_zone, vi);
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index b48c6e7969585..c0ae0a7476495 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -37,6 +37,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_capsicum.h"
#include "opt_compat.h"
#include "opt_kdtrace.h"
#include "opt_ktrace.h"
@@ -45,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/bio.h>
#include <sys/buf.h>
+#include <sys/capability.h>
#include <sys/disk.h>
#include <sys/sysent.h>
#include <sys/malloc.h>
@@ -94,8 +96,6 @@ SDT_PROBE_ARGTYPE(vfs, , stat, reg, 1, "int");
static int chroot_refuse_vdir_fds(struct filedesc *fdp);
static int getutimes(const struct timeval *, enum uio_seg, struct timespec *);
-static int setfown(struct thread *td, struct vnode *, uid_t, gid_t);
-static int setfmode(struct thread *td, struct vnode *, int);
static int setfflags(struct thread *td, struct vnode *, int);
static int setutimes(struct thread *td, struct vnode *,
const struct timespec *, int, int);
@@ -373,7 +373,7 @@ kern_fstatfs(struct thread *td, int fd, struct statfs *buf)
int error;
AUDIT_ARG_FD(fd);
- error = getvnode(td->td_proc->p_fd, fd, &fp);
+ error = getvnode(td->td_proc->p_fd, fd, CAP_FSTATFS, &fp);
if (error)
return (error);
vp = fp->f_vnode;
@@ -746,7 +746,7 @@ fchdir(td, uap)
int error;
AUDIT_ARG_FD(uap->fd);
- if ((error = getvnode(fdp, uap->fd, &fp)) != 0)
+ if ((error = getvnode(fdp, uap->fd, CAP_FCHDIR, &fp)) != 0)
return (error);
vp = fp->f_vnode;
VREF(vp);
@@ -991,6 +991,41 @@ change_root(vp, td)
return (0);
}
+static __inline cap_rights_t
+flags_to_rights(int flags)
+{
+ cap_rights_t rights = 0;
+
+ switch ((flags & O_ACCMODE)) {
+ case O_RDONLY:
+ rights |= CAP_READ;
+ break;
+
+ case O_RDWR:
+ rights |= CAP_READ;
+ /* fall through */
+
+ case O_WRONLY:
+ rights |= CAP_WRITE;
+ break;
+
+ case O_EXEC:
+ rights |= CAP_FEXECVE;
+ break;
+ }
+
+ if (flags & O_CREAT)
+ rights |= CAP_CREATE;
+
+ if (flags & O_TRUNC)
+ rights |= CAP_FTRUNCATE;
+
+ if ((flags & O_EXLOCK) || (flags & O_SHLOCK))
+ rights |= CAP_FLOCK;
+
+ return (rights);
+}
+
/*
* Check permissions, allocate an open file structure, and call the device
* open routine if any.
@@ -1049,14 +1084,16 @@ kern_openat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
struct vnode *vp;
int cmode;
struct file *nfp;
- int type, indx, error;
+ int type, indx = -1, error, error_open;
struct flock lf;
struct nameidata nd;
int vfslocked;
+ cap_rights_t rights_needed = CAP_LOOKUP;
AUDIT_ARG_FFLAGS(flags);
AUDIT_ARG_MODE(mode);
/* XXX: audit dirfd */
+ rights_needed |= flags_to_rights(flags);
/*
* Only one of the O_EXEC, O_RDONLY, O_WRONLY and O_RDWR flags
* may be specified.
@@ -1069,16 +1106,19 @@ kern_openat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
else
flags = FFLAGS(flags);
- error = falloc(td, &nfp, &indx, flags);
+ /*
+ * allocate the file descriptor, but don't install a descriptor yet
+ */
+ error = falloc_noinstall(td, &nfp);
if (error)
return (error);
- /* An extra reference on `nfp' has been held for us by falloc(). */
+ /* An extra reference on `nfp' has been held for us by falloc_noinstall(). */
fp = nfp;
/* Set the flags early so the finit in devfs can pick them up. */
fp->f_flag = flags & FMASK;
cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
- NDINIT_AT(&nd, LOOKUP, FOLLOW | AUDITVNODE1 | MPSAFE, pathseg, path, fd,
- td);
+ NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | AUDITVNODE1 | MPSAFE, pathseg,
+ path, fd, rights_needed, td);
td->td_dupfd = -1; /* XXX check for fdopen */
error = vn_open(&nd, &flags, cmode, fp);
if (error) {
@@ -1087,30 +1127,35 @@ kern_openat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
* wonderous happened deep below and we just pass it up
* pretending we know what we do.
*/
- if (error == ENXIO && fp->f_ops != &badfileops) {
- fdrop(fp, td);
- td->td_retval[0] = indx;
- return (0);
- }
+ if (error == ENXIO && fp->f_ops != &badfileops)
+ goto success;
/*
* handle special fdopen() case. bleh. dupfdopen() is
* responsible for dropping the old contents of ofiles[indx]
* if it succeeds.
+ *
+ * Don't do this for relative (capability) lookups; we don't
+ * understand exactly what would happen, and we don't think
+ * that it ever should.
*/
- if ((error == ENODEV || error == ENXIO) &&
- td->td_dupfd >= 0 && /* XXX from fdopen */
- (error =
- dupfdopen(td, fdp, indx, td->td_dupfd, flags, error)) == 0) {
- td->td_retval[0] = indx;
- fdrop(fp, td);
- return (0);
+ if ((nd.ni_strictrelative == 0) &&
+ (error == ENODEV || error == ENXIO) &&
+ (td->td_dupfd >= 0)) {
+ /* XXX from fdopen */
+ error_open = error;
+ if ((error = finstall(td, fp, &indx, flags)) != 0)
+ goto bad_unlocked;
+ if ((error = dupfdopen(td, fdp, indx, td->td_dupfd,
+ flags, error_open)) == 0)
+ goto success;
}
/*
* Clean up the descriptor, but only if another thread hadn't
* replaced or closed it.
*/
- fdclose(fdp, fp, indx, td);
+ if (indx != -1)
+ fdclose(fdp, fp, indx, td);
fdrop(fp, td);
if (error == ERESTART)
@@ -1161,6 +1206,27 @@ kern_openat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
goto bad;
}
VFS_UNLOCK_GIANT(vfslocked);
+success:
+ /*
+ * If we haven't already installed the FD (for dupfdopen), do so now.
+ */
+ if (indx == -1) {
+#ifdef CAPABILITIES
+ if (nd.ni_strictrelative == 1) {
+ /*
+ * We are doing a strict relative lookup; wrap the
+ * result in a capability.
+ */
+ if ((error = kern_capwrap(td, fp, nd.ni_baserights,
+ &indx)) != 0)
+ goto bad_unlocked;
+ } else
+#endif
+ if ((error = finstall(td, fp, &indx, flags)) != 0)
+ goto bad_unlocked;
+
+ }
+
/*
* Release our private reference, leaving the one associated with
* the descriptor table intact.
@@ -1170,8 +1236,11 @@ kern_openat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
return (0);
bad:
VFS_UNLOCK_GIANT(vfslocked);
- fdclose(fdp, fp, indx, td);
+bad_unlocked:
+ if (indx != -1)
+ fdclose(fdp, fp, indx, td);
fdrop(fp, td);
+ td->td_retval[0] = -1;
return (error);
}
@@ -1283,8 +1352,9 @@ kern_mknodat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
return (error);
restart:
bwillwrite();
- NDINIT_AT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1,
- pathseg, path, fd, td);
+ NDINIT_ATRIGHTS(&nd, CREATE,
+ LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1, pathseg, path, fd,
+ CAP_MKFIFO, td);
if ((error = namei(&nd)) != 0)
return (error);
vfslocked = NDHASGIANT(&nd);
@@ -1918,7 +1988,7 @@ lseek(td, uap)
int vfslocked;
AUDIT_ARG_FD(uap->fd);
- if ((error = fget(td, uap->fd, &fp)) != 0)
+ if ((error = fget(td, uap->fd, CAP_SEEK, &fp)) != 0)
return (error);
if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE)) {
fdrop(fp, td);
@@ -2135,8 +2205,8 @@ kern_accessat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
} else
cred = tmpcred = td->td_ucred;
AUDIT_ARG_VALUE(mode);
- NDINIT_AT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | MPSAFE |
- AUDITVNODE1, pathseg, path, fd, td);
+ NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | MPSAFE |
+ AUDITVNODE1, pathseg, path, fd, CAP_FSTAT, td);
if ((error = namei(&nd)) != 0)
goto out1;
vfslocked = NDHASGIANT(&nd);
@@ -2345,9 +2415,9 @@ kern_statat_vnhook(struct thread *td, int flag, int fd, char *path,
if (flag & ~AT_SYMLINK_NOFOLLOW)
return (EINVAL);
- NDINIT_AT(&nd, LOOKUP, ((flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW :
+ NDINIT_ATRIGHTS(&nd, LOOKUP, ((flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW :
FOLLOW) | LOCKSHARED | LOCKLEAF | AUDITVNODE1 | MPSAFE, pathseg,
- path, fd, td);
+ path, fd, CAP_FSTAT, td);
if ((error = namei(&nd)) != 0)
return (error);
@@ -2775,7 +2845,8 @@ fchflags(td, uap)
AUDIT_ARG_FD(uap->fd);
AUDIT_ARG_FFLAGS(uap->flags);
- if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
+ if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_FCHFLAGS,
+ &fp)) != 0)
return (error);
vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
#ifdef AUDIT
@@ -2792,9 +2863,10 @@ fchflags(td, uap)
/*
* Common implementation code for chmod(), lchmod() and fchmod().
*/
-static int
-setfmode(td, vp, mode)
+int
+setfmode(td, cred, vp, mode)
struct thread *td;
+ struct ucred *cred;
struct vnode *vp;
int mode;
{
@@ -2808,10 +2880,10 @@ setfmode(td, vp, mode)
VATTR_NULL(&vattr);
vattr.va_mode = mode & ALLPERMS;
#ifdef MAC
- error = mac_vnode_check_setmode(td->td_ucred, vp, vattr.va_mode);
+ error = mac_vnode_check_setmode(cred, vp, vattr.va_mode);
if (error == 0)
#endif
- error = VOP_SETATTR(vp, &vattr, td->td_ucred);
+ error = VOP_SETATTR(vp, &vattr, cred);
VOP_UNLOCK(vp, 0);
vn_finished_write(mp);
return (error);
@@ -2901,13 +2973,13 @@ kern_fchmodat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
AUDIT_ARG_MODE(mode);
follow = (flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW;
- NDINIT_AT(&nd, LOOKUP, follow | MPSAFE | AUDITVNODE1, pathseg, path,
- fd, td);
+ NDINIT_ATRIGHTS(&nd, LOOKUP, follow | MPSAFE | AUDITVNODE1, pathseg,
+ path, fd, CAP_FCHMOD, td);
if ((error = namei(&nd)) != 0)
return (error);
vfslocked = NDHASGIANT(&nd);
NDFREE(&nd, NDF_ONLY_PNBUF);
- error = setfmode(td, nd.ni_vp, mode);
+ error = setfmode(td, td->td_ucred, nd.ni_vp, mode);
vrele(nd.ni_vp);
VFS_UNLOCK_GIANT(vfslocked);
return (error);
@@ -2923,29 +2995,18 @@ struct fchmod_args {
};
#endif
int
-fchmod(td, uap)
- struct thread *td;
- register struct fchmod_args /* {
- int fd;
- int mode;
- } */ *uap;
+fchmod(struct thread *td, struct fchmod_args *uap)
{
struct file *fp;
- int vfslocked;
int error;
AUDIT_ARG_FD(uap->fd);
AUDIT_ARG_MODE(uap->mode);
- if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
+
+ error = fget(td, uap->fd, CAP_FCHMOD, &fp);
+ if (error != 0)
return (error);
- vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
-#ifdef AUDIT
- vn_lock(fp->f_vnode, LK_SHARED | LK_RETRY);
- AUDIT_ARG_VNODE1(fp->f_vnode);
- VOP_UNLOCK(fp->f_vnode, 0);
-#endif
- error = setfmode(td, fp->f_vnode, uap->mode);
- VFS_UNLOCK_GIANT(vfslocked);
+ error = fo_chmod(fp, uap->mode, td->td_ucred, td);
fdrop(fp, td);
return (error);
}
@@ -2953,9 +3014,10 @@ fchmod(td, uap)
/*
* Common implementation for chown(), lchown(), and fchown()
*/
-static int
-setfown(td, vp, uid, gid)
+int
+setfown(td, cred, vp, uid, gid)
struct thread *td;
+ struct ucred *cred;
struct vnode *vp;
uid_t uid;
gid_t gid;
@@ -2971,11 +3033,11 @@ setfown(td, vp, uid, gid)
vattr.va_uid = uid;
vattr.va_gid = gid;
#ifdef MAC
- error = mac_vnode_check_setowner(td->td_ucred, vp, vattr.va_uid,
+ error = mac_vnode_check_setowner(cred, vp, vattr.va_uid,
vattr.va_gid);
if (error == 0)
#endif
- error = VOP_SETATTR(vp, &vattr, td->td_ucred);
+ error = VOP_SETATTR(vp, &vattr, cred);
VOP_UNLOCK(vp, 0);
vn_finished_write(mp);
return (error);
@@ -3043,14 +3105,14 @@ kern_fchownat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
AUDIT_ARG_OWNER(uid, gid);
follow = (flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW;
- NDINIT_AT(&nd, LOOKUP, follow | MPSAFE | AUDITVNODE1, pathseg, path,
- fd, td);
+ NDINIT_ATRIGHTS(&nd, LOOKUP, follow | MPSAFE | AUDITVNODE1, pathseg,
+ path, fd, CAP_FCHOWN, td);
if ((error = namei(&nd)) != 0)
return (error);
vfslocked = NDHASGIANT(&nd);
NDFREE(&nd, NDF_ONLY_PNBUF);
- error = setfown(td, nd.ni_vp, uid, gid);
+ error = setfown(td, td->td_ucred, nd.ni_vp, uid, gid);
vrele(nd.ni_vp);
VFS_UNLOCK_GIANT(vfslocked);
return (error);
@@ -3108,21 +3170,14 @@ fchown(td, uap)
} */ *uap;
{
struct file *fp;
- int vfslocked;
int error;
AUDIT_ARG_FD(uap->fd);
AUDIT_ARG_OWNER(uap->uid, uap->gid);
- if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
+ error = fget(td, uap->fd, CAP_FCHOWN, &fp);
+ if (error != 0)
return (error);
- vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
-#ifdef AUDIT
- vn_lock(fp->f_vnode, LK_SHARED | LK_RETRY);
- AUDIT_ARG_VNODE1(fp->f_vnode);
- VOP_UNLOCK(fp->f_vnode, 0);
-#endif
- error = setfown(td, fp->f_vnode, uap->uid, uap->gid);
- VFS_UNLOCK_GIANT(vfslocked);
+ error = fo_chown(fp, uap->uid, uap->gid, td->td_ucred, td);
fdrop(fp, td);
return (error);
}
@@ -3258,8 +3313,8 @@ kern_utimesat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
if ((error = getutimes(tptr, tptrseg, ts)) != 0)
return (error);
- NDINIT_AT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg, path,
- fd, td);
+ NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, pathseg,
+ path, fd, CAP_FUTIMES, td);
if ((error = namei(&nd)) != 0)
return (error);
@@ -3348,7 +3403,8 @@ kern_futimes(struct thread *td, int fd, struct timeval *tptr,
AUDIT_ARG_FD(fd);
if ((error = getutimes(tptr, tptrseg, ts)) != 0)
return (error);
- if ((error = getvnode(td->td_proc->p_fd, fd, &fp)) != 0)
+ if ((error = getvnode(td->td_proc->p_fd, fd, CAP_FUTIMES, &fp))
+ != 0)
return (error);
vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
#ifdef AUDIT
@@ -3500,7 +3556,8 @@ fsync(td, uap)
int error, lock_flags;
AUDIT_ARG_FD(uap->fd);
- if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
+ if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_FSYNC,
+ &fp)) != 0)
return (error);
vp = fp->f_vnode;
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
@@ -3587,11 +3644,11 @@ kern_renameat(struct thread *td, int oldfd, char *old, int newfd, char *new,
bwillwrite();
#ifdef MAC
- NDINIT_AT(&fromnd, DELETE, LOCKPARENT | LOCKLEAF | SAVESTART | MPSAFE |
- AUDITVNODE1, pathseg, old, oldfd, td);
+ NDINIT_ATRIGHTS(&fromnd, DELETE, LOCKPARENT | LOCKLEAF | SAVESTART |
+ MPSAFE | AUDITVNODE1, pathseg, old, oldfd, CAP_DELETE, td);
#else
- NDINIT_AT(&fromnd, DELETE, WANTPARENT | SAVESTART | MPSAFE |
- AUDITVNODE1, pathseg, old, oldfd, td);
+ NDINIT_ATRIGHTS(&fromnd, DELETE, WANTPARENT | SAVESTART | MPSAFE |
+ AUDITVNODE1, pathseg, old, oldfd, CAP_DELETE, td);
#endif
if ((error = namei(&fromnd)) != 0)
@@ -3614,8 +3671,9 @@ kern_renameat(struct thread *td, int oldfd, char *old, int newfd, char *new,
vrele(fvp);
goto out1;
}
- NDINIT_AT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART |
- MPSAFE | AUDITVNODE2, pathseg, new, newfd, td);
+ NDINIT_ATRIGHTS(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE |
+ SAVESTART | MPSAFE | AUDITVNODE2, pathseg, new, newfd, CAP_CREATE,
+ td);
if (fromnd.ni_vp->v_type == VDIR)
tond.ni_cnd.cn_flags |= WILLBEDIR;
if ((error = namei(&tond)) != 0) {
@@ -3741,8 +3799,8 @@ kern_mkdirat(struct thread *td, int fd, char *path, enum uio_seg segflg,
AUDIT_ARG_MODE(mode);
restart:
bwillwrite();
- NDINIT_AT(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE | AUDITVNODE1,
- segflg, path, fd, td);
+ NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | MPSAFE |
+ AUDITVNODE1, segflg, path, fd, CAP_MKDIR, td);
nd.ni_cnd.cn_flags |= WILLBEDIR;
if ((error = namei(&nd)) != 0)
return (error);
@@ -3830,8 +3888,8 @@ kern_rmdirat(struct thread *td, int fd, char *path, enum uio_seg pathseg)
restart:
bwillwrite();
- NDINIT_AT(&nd, DELETE, LOCKPARENT | LOCKLEAF | MPSAFE | AUDITVNODE1,
- pathseg, path, fd, td);
+ NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF | MPSAFE |
+ AUDITVNODE1, pathseg, path, fd, CAP_RMDIR, td);
if ((error = namei(&nd)) != 0)
return (error);
vfslocked = NDHASGIANT(&nd);
@@ -3925,7 +3983,8 @@ kern_ogetdirentries(struct thread *td, struct ogetdirentries_args *uap,
/* XXX arbitrary sanity limit on `count'. */
if (uap->count > 64 * 1024)
return (EINVAL);
- if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
+ if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_READ,
+ &fp)) != 0)
return (error);
if ((fp->f_flag & FREAD) == 0) {
fdrop(fp, td);
@@ -4085,7 +4144,8 @@ kern_getdirentries(struct thread *td, int fd, char *buf, u_int count,
AUDIT_ARG_FD(fd);
if (count > INT_MAX)
return (EINVAL);
- if ((error = getvnode(td->td_proc->p_fd, fd, &fp)) != 0)
+ if ((error = getvnode(td->td_proc->p_fd, fd, CAP_READ | CAP_SEEK,
+ &fp)) != 0)
return (error);
if ((fp->f_flag & FREAD) == 0) {
fdrop(fp, td);
@@ -4248,30 +4308,49 @@ out:
}
/*
- * Convert a user file descriptor to a kernel file entry.
- * A reference on the file entry is held upon returning.
+ * Convert a user file descriptor to a kernel file entry and check that, if it
+ * is a capability, the correct rights are present. A reference on the file
+ * entry is held upon returning.
*/
int
-getvnode(fdp, fd, fpp)
- struct filedesc *fdp;
- int fd;
- struct file **fpp;
+getvnode(struct filedesc *fdp, int fd, cap_rights_t rights,
+ struct file **fpp)
{
- int error;
struct file *fp;
+#ifdef CAPABILITIES
+ struct file *fp_fromcap;
+#endif
+ int error;
error = 0;
fp = NULL;
- if (fdp == NULL || (fp = fget_unlocked(fdp, fd)) == NULL)
- error = EBADF;
- else if (fp->f_vnode == NULL) {
- error = EINVAL;
+ if ((fdp == NULL) || (fp = fget_unlocked(fdp, fd)) == NULL)
+ return (EBADF);
+#ifdef CAPABILITIES
+ /*
+ * If the file descriptor is for a capability, test rights and use the
+ * file descriptor referenced by the capability.
+ */
+ error = cap_funwrap(fp, rights, &fp_fromcap);
+ if (error) {
+ fdrop(fp, curthread);
+ return (error);
+ }
+ if (fp != fp_fromcap) {
+ fhold(fp_fromcap);
fdrop(fp, curthread);
+ fp = fp_fromcap;
+ }
+#endif /* CAPABILITIES */
+ if (fp->f_vnode == NULL) {
+ fdrop(fp, curthread);
+ return (EINVAL);
}
*fpp = fp;
- return (error);
+ return (0);
}
+
/*
* Get an (NFS) file handle.
*/
@@ -4683,7 +4762,7 @@ kern_posix_fallocate(struct thread *td, int fd, off_t offset, off_t len)
fp = NULL;
vfslocked = 0;
- error = fget(td, fd, &fp);
+ error = fget(td, fd, CAP_WRITE, &fp);
if (error != 0)
goto out;
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index e8bcc91cb9696..92fb0d9335f7e 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -61,8 +61,12 @@ __FBSDID("$FreeBSD$");
#include <sys/syslog.h>
#include <sys/unistd.h>
+#include <security/audit/audit.h>
#include <security/mac/mac_framework.h>
+#include <vm/vm.h>
+#include <vm/vm_object.h>
+
static fo_rdwr_t vn_read;
static fo_rdwr_t vn_write;
static fo_truncate_t vn_truncate;
@@ -81,6 +85,8 @@ struct fileops vnops = {
.fo_kqfilter = vn_kqfilter,
.fo_stat = vn_statfile,
.fo_close = vn_closefile,
+ .fo_chmod = vn_chmod,
+ .fo_chown = vn_chown,
.fo_flags = DFLAG_PASSABLE | DFLAG_SEEKABLE
};
@@ -1357,3 +1363,53 @@ vn_rlimit_fsize(const struct vnode *vp, const struct uio *uio,
PROC_UNLOCK(td->td_proc);
return (0);
}
+
+int
+vn_chmod(struct file *fp, mode_t mode, struct ucred *active_cred,
+ struct thread *td)
+{
+ struct vnode *vp;
+ int error, vfslocked;
+
+ vp = fp->f_vnode;
+ vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+#ifdef AUDIT
+ vn_lock(vp, LK_SHARED | LK_RETRY);
+ AUDIT_ARG_VNODE1(vp);
+ VOP_UNLOCK(vp, 0);
+#endif
+ error = setfmode(td, active_cred, vp, mode);
+ VFS_UNLOCK_GIANT(vfslocked);
+ return (error);
+}
+
+int
+vn_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred,
+ struct thread *td)
+{
+ struct vnode *vp;
+ int error, vfslocked;
+
+ vp = fp->f_vnode;
+ vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+#ifdef AUDIT
+ vn_lock(vp, LK_SHARED | LK_RETRY);
+ AUDIT_ARG_VNODE1(vp);
+ VOP_UNLOCK(vp, 0);
+#endif
+ error = setfown(td, active_cred, vp, uid, gid);
+ VFS_UNLOCK_GIANT(vfslocked);
+ return (error);
+}
+
+void
+vn_pages_remove(struct vnode *vp, vm_pindex_t start, vm_pindex_t end)
+{
+ vm_object_t object;
+
+ if ((object = vp->v_object) == NULL)
+ return;
+ VM_OBJECT_LOCK(object);
+ vm_object_page_remove(object, start, end, 0);
+ VM_OBJECT_UNLOCK(object);
+}
diff --git a/sys/mips/cavium/asm_octeon.S b/sys/mips/cavium/asm_octeon.S
index 94ac875a19962..1ef5083348979 100644
--- a/sys/mips/cavium/asm_octeon.S
+++ b/sys/mips/cavium/asm_octeon.S
@@ -50,12 +50,12 @@ LEAF(octeon_ap_wait)
jal platform_processor_id
nop
-1: ll t0, octeon_ap_boot
+1: lld t0, octeon_ap_boot
bne v0, t0, 1b
nop
move t0, zero
- sc t0, octeon_ap_boot
+ scd t0, octeon_ap_boot
beqz t0, 1b
nop
diff --git a/sys/mips/cavium/octeon_mp.c b/sys/mips/cavium/octeon_mp.c
index efddee86ae0fd..2bc268e95064b 100644
--- a/sys/mips/cavium/octeon_mp.c
+++ b/sys/mips/cavium/octeon_mp.c
@@ -46,7 +46,8 @@ __FBSDID("$FreeBSD$");
/* XXX */
extern cvmx_bootinfo_t *octeon_bootinfo;
-unsigned octeon_ap_boot = ~0;
+/* NOTE: this 64-bit mask (and many others) limits MAXCPU to 64 */
+uint64_t octeon_ap_boot = ~0ULL;
void
platform_ipi_send(int cpuid)
@@ -105,15 +106,13 @@ platform_init_ap(int cpuid)
void
platform_cpu_mask(cpuset_t *mask)
{
+ uint64_t core_mask = octeon_bootinfo->core_mask;
+ uint64_t i, m;
CPU_ZERO(mask);
-
- /*
- * XXX: hack in order to simplify CPU set building, assuming that
- * core_mask is 32-bits.
- */
- memcpy(mask, &octeon_bootinfo->core_mask,
- sizeof(octeon_bootinfo->core_mask));
+ for (i = 0, m = 1 ; i < MAXCPU; i++, m <<= 1)
+ if (core_mask & m)
+ CPU_SET(i, mask);
}
struct cpu_group *
@@ -125,11 +124,26 @@ platform_smp_topo(void)
int
platform_start_ap(int cpuid)
{
- if (atomic_cmpset_32(&octeon_ap_boot, ~0, cpuid) == 0)
+ uint64_t cores_in_reset;
+
+ /*
+ * Release the core if it is in reset, and let it rev up a bit.
+ * The real synchronization happens below via octeon_ap_boot.
+ */
+ cores_in_reset = cvmx_read_csr(CVMX_CIU_PP_RST);
+ if (cores_in_reset & (1ULL << cpuid)) {
+ if (bootverbose)
+ printf ("AP #%d still in reset\n", cpuid);
+ cores_in_reset &= ~(1ULL << cpuid);
+ cvmx_write_csr(CVMX_CIU_PP_RST, (uint64_t)(cores_in_reset));
+ DELAY(2000); /* Give it a moment to start */
+ }
+
+ if (atomic_cmpset_64(&octeon_ap_boot, ~0, cpuid) == 0)
return (-1);
for (;;) {
DELAY(1000);
- if (atomic_cmpset_32(&octeon_ap_boot, 0, ~0) != 0)
+ if (atomic_cmpset_64(&octeon_ap_boot, 0, ~0) != 0)
return (0);
printf("Waiting for cpu%d to start\n", cpuid);
}
diff --git a/sys/mips/conf/OCTEON1 b/sys/mips/conf/OCTEON1
index 2a0abcf42249d..60b2b01f77e50 100644
--- a/sys/mips/conf/OCTEON1
+++ b/sys/mips/conf/OCTEON1
@@ -295,4 +295,4 @@ device udav # Davicom DM9601E USB
device rum # Ralink Technology RT2501USB wireless NICs
device uath # Atheros AR5523 wireless NICs
device ural # Ralink Technology RT2500USB wireless NICs
-device zyd # ZyDAS zb1211/zb1211b wireless NICs
+device zyd # ZyDAS zd1211/zd1211b wireless NICs
diff --git a/sys/mips/conf/XLP b/sys/mips/conf/XLP
index 6843534b72fe8..ff40239a30415 100644
--- a/sys/mips/conf/XLP
+++ b/sys/mips/conf/XLP
@@ -36,6 +36,7 @@ options SCHED_ULE # ULE scheduler
options SMP
options PREEMPTION # Enable kernel thread preemption
#options FULL_PREEMPTION # Enable kernel thread preemption
+#options MAXCPU=128 # XLP can probe 128 CPUs
options INET # InterNETworking
options INET6 # IPv6 communications protocols
options FFS # Berkeley Fast Filesystem
@@ -88,6 +89,7 @@ device bpf
# UART
device uart
+device pci
# Network
device ether
diff --git a/sys/mips/conf/XLP64 b/sys/mips/conf/XLP64
index 997a1f61c7fcd..1d4b575f3a45d 100644
--- a/sys/mips/conf/XLP64
+++ b/sys/mips/conf/XLP64
@@ -21,7 +21,7 @@ machine mips mips64eb
ident XLP64
options ISA_MIPS64
-makeoptions ARCH_FLAGS="-march=mips64 -mabi=64"
+makeoptions ARCH_FLAGS="-march=mips64r2 -mabi=64"
makeoptions KERNLOADADDR=0xffffffff80100000
include "../nlm/std.xlp"
@@ -38,6 +38,7 @@ options SCHED_ULE # ULE scheduler
options SMP
options PREEMPTION # Enable kernel thread preemption
#options FULL_PREEMPTION # Enable kernel thread preemption
+#options MAXCPU=128 # XLP can probe 128 CPUs
options INET # InterNETworking
options INET6 # IPv6 communications protocols
options FFS # Berkeley Fast Filesystem
@@ -90,6 +91,7 @@ device bpf
# UART
device uart
+device pci
# Network
device ether
diff --git a/sys/mips/conf/XLPN32 b/sys/mips/conf/XLPN32
index 97c73a80d6952..02119a85435ce 100644
--- a/sys/mips/conf/XLPN32
+++ b/sys/mips/conf/XLPN32
@@ -37,6 +37,7 @@ options SCHED_ULE # ULE scheduler
options SMP
options PREEMPTION # Enable kernel thread preemption
#options FULL_PREEMPTION # Enable kernel thread preemption
+#options MAXCPU=128 # XLP can probe 128 CPUs
options INET # InterNETworking
options INET6 # IPv6 communications protocols
options FFS # Berkeley Fast Filesystem
@@ -89,6 +90,7 @@ device bpf
# UART
device uart
+device pci
# Network
device ether
diff --git a/sys/mips/include/param.h b/sys/mips/include/param.h
index 0b1ea9837afa8..5f25c81c98f95 100644
--- a/sys/mips/include/param.h
+++ b/sys/mips/include/param.h
@@ -87,7 +87,9 @@
#ifdef SMP
#define MAXSMPCPU 32
+#ifndef MAXCPU
#define MAXCPU MAXSMPCPU
+#endif
#else
#define MAXSMPCPU 1
#define MAXCPU 1
diff --git a/sys/mips/mips/dump_machdep.c b/sys/mips/mips/dump_machdep.c
index 1dd69f759c253..bf8c4a3152f3d 100644
--- a/sys/mips/mips/dump_machdep.c
+++ b/sys/mips/mips/dump_machdep.c
@@ -188,7 +188,7 @@ cb_dumpdata(struct md_pa *mdp, int seqnr, void *arg)
}
#ifdef SW_WATCHDOG
- wdog_kern_path(WD_LASTVAL);
+ wdog_kern_pat(WD_LASTVAL);
#endif
error = dump_write(di, (void *)(intptr_t)(pa),0, dumplo, sz); /* XXX fix PA */
if (error)
diff --git a/sys/mips/mips/exception.S b/sys/mips/mips/exception.S
index ed7554bc7c03f..729391e1efcf0 100644
--- a/sys/mips/mips/exception.S
+++ b/sys/mips/mips/exception.S
@@ -1140,13 +1140,21 @@ END(MipsFPTrap)
intrnames:
.space INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
sintrnames:
- .word INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
+#ifdef __mips_n64
+ .quad INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
+#else
+ .int INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
+#endif
.align 4
intrcnt:
.space INTRCNT_COUNT * 4 * 2
sintrcnt:
- .word INTRCNT_COUNT * 4 * 2
+#ifdef __mips_n64
+ .quad INTRCNT_COUNT * 4 * 2
+#else
+ .int INTRCNT_COUNT * 4 * 2
+#endif
/*
diff --git a/sys/mips/mips/pmap.c b/sys/mips/mips/pmap.c
index 4d4609907169d..7da76be6236d4 100644
--- a/sys/mips/mips/pmap.c
+++ b/sys/mips/mips/pmap.c
@@ -1432,7 +1432,7 @@ retry:
KASSERT(!pte_test(&oldpte, PTE_W),
("wired pte for unwired page"));
if (m->md.pv_flags & PV_TABLE_REF)
- vm_page_flag_set(m, PG_REFERENCED);
+ vm_page_aflag_set(m, PGA_REFERENCED);
if (pte_test(&oldpte, PTE_D))
vm_page_dirty(m);
pmap_invalidate_page(pmap, va);
@@ -1448,7 +1448,7 @@ retry:
free_pv_entry(pv);
}
if (TAILQ_EMPTY(&m->md.pv_list)) {
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
m->md.pv_flags &= ~(PV_TABLE_REF | PV_TABLE_MOD);
}
}
@@ -1527,7 +1527,7 @@ pmap_remove_entry(pmap_t pmap, vm_page_t m, vm_offset_t va)
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
pmap_pvh_free(&m->md, pmap, va);
if (TAILQ_EMPTY(&m->md.pv_list))
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
}
/*
@@ -1589,7 +1589,7 @@ pmap_remove_pte(struct pmap *pmap, pt_entry_t *ptq, vm_offset_t va)
vm_page_dirty(m);
}
if (m->md.pv_flags & PV_TABLE_REF)
- vm_page_flag_set(m, PG_REFERENCED);
+ vm_page_aflag_set(m, PGA_REFERENCED);
m->md.pv_flags &= ~(PV_TABLE_REF | PV_TABLE_MOD);
pmap_remove_entry(pmap, m, va);
@@ -1708,12 +1708,12 @@ pmap_remove_all(vm_page_t m)
pv_entry_t pv;
pt_entry_t *pte, tpte;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_remove_all: page %p is not managed", m));
vm_page_lock_queues();
if (m->md.pv_flags & PV_TABLE_REF)
- vm_page_flag_set(m, PG_REFERENCED);
+ vm_page_aflag_set(m, PGA_REFERENCED);
while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) {
PMAP_LOCK(pv->pv_pmap);
@@ -1757,7 +1757,7 @@ pmap_remove_all(vm_page_t m)
free_pv_entry(pv);
}
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
m->md.pv_flags &= ~(PV_TABLE_REF | PV_TABLE_MOD);
vm_page_unlock_queues();
}
@@ -1863,8 +1863,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_prot_t access, vm_page_t m,
va &= ~PAGE_MASK;
KASSERT(va <= VM_MAX_KERNEL_ADDRESS, ("pmap_enter: toobig"));
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0 ||
- (m->oflags & VPO_BUSY) != 0,
+ KASSERT((m->oflags & (VPO_UNMANAGED | VPO_BUSY)) != 0,
("pmap_enter: page %p is not busy", m));
mpte = NULL;
@@ -1952,7 +1951,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_prot_t access, vm_page_t m,
* raise IPL while manipulating pv_table since pmap_enter can be
* called at interrupt time.
*/
- if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0) {
+ if ((m->oflags & VPO_UNMANAGED) == 0) {
KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva,
("pmap_enter: managed mapping within the clean submap"));
if (pv == NULL)
@@ -2005,7 +2004,7 @@ validate:
*pte = newpte;
if (page_is_managed(opa) && (opa != pa)) {
if (om->md.pv_flags & PV_TABLE_REF)
- vm_page_flag_set(om, PG_REFERENCED);
+ vm_page_aflag_set(om, PGA_REFERENCED);
om->md.pv_flags &=
~(PV_TABLE_REF | PV_TABLE_MOD);
}
@@ -2018,7 +2017,7 @@ validate:
}
if (page_is_managed(opa) &&
TAILQ_EMPTY(&om->md.pv_list))
- vm_page_flag_clear(om, PG_WRITEABLE);
+ vm_page_aflag_clear(om, PGA_WRITEABLE);
} else {
*pte = newpte;
}
@@ -2067,7 +2066,7 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m,
vm_paddr_t pa;
KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva ||
- (m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0,
+ (m->oflags & VPO_UNMANAGED) != 0,
("pmap_enter_quick_locked: managed mapping within the clean submap"));
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
PMAP_LOCK_ASSERT(pmap, MA_OWNED);
@@ -2129,7 +2128,7 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m,
/*
* Enter on the PV list if part of our managed memory.
*/
- if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0 &&
+ if ((m->oflags & VPO_UNMANAGED) == 0 &&
!pmap_try_insert_pv_entry(pmap, mpte, va, m)) {
if (mpte != NULL) {
pmap_unwire_pte_hold(pmap, va, mpte);
@@ -2464,7 +2463,7 @@ pmap_page_exists_quick(pmap_t pmap, vm_page_t m)
int loops = 0;
boolean_t rv;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_page_exists_quick: page %p is not managed", m));
rv = FALSE;
vm_page_lock_queues();
@@ -2536,7 +2535,7 @@ pmap_remove_pages(pmap_t pmap)
m->md.pv_list_count--;
TAILQ_REMOVE(&m->md.pv_list, pv, pv_list);
if (TAILQ_FIRST(&m->md.pv_list) == NULL) {
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
}
pmap_unuse_pt(pv->pv_pmap, pv->pv_va, pv->pv_ptem);
free_pv_entry(pv);
@@ -2558,7 +2557,7 @@ pmap_testbit(vm_page_t m, int bit)
pt_entry_t *pte;
boolean_t rv = FALSE;
- if (m->flags & PG_FICTITIOUS)
+ if (m->oflags & VPO_UNMANAGED)
return (rv);
if (TAILQ_FIRST(&m->md.pv_list) == NULL)
@@ -2585,7 +2584,7 @@ pmap_changebit(vm_page_t m, int bit, boolean_t setem)
pv_entry_t pv;
pt_entry_t *pte;
- if (m->flags & PG_FICTITIOUS)
+ if (m->oflags & VPO_UNMANAGED)
return;
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
@@ -2616,7 +2615,7 @@ pmap_changebit(vm_page_t m, int bit, boolean_t setem)
PMAP_UNLOCK(pv->pv_pmap);
}
if (!setem && bit == PTE_D)
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
}
/*
@@ -2634,7 +2633,7 @@ pmap_page_wired_mappings(vm_page_t m)
int count;
count = 0;
- if ((m->flags & PG_FICTITIOUS) != 0)
+ if ((m->oflags & VPO_UNMANAGED) != 0)
return (count);
vm_page_lock_queues();
TAILQ_FOREACH(pv, &m->md.pv_list, pv_list) {
@@ -2659,17 +2658,17 @@ pmap_remove_write(vm_page_t m)
vm_offset_t va;
pt_entry_t *pte;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_remove_write: page %p is not managed", m));
/*
- * If the page is not VPO_BUSY, then PG_WRITEABLE cannot be set by
- * another thread while the object is locked. Thus, if PG_WRITEABLE
+ * If the page is not VPO_BUSY, then PGA_WRITEABLE cannot be set by
+ * another thread while the object is locked. Thus, if PGA_WRITEABLE
* is clear, no page table entries need updating.
*/
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
if ((m->oflags & VPO_BUSY) == 0 &&
- (m->flags & PG_WRITEABLE) == 0)
+ (m->aflags & PGA_WRITEABLE) == 0)
return;
/*
@@ -2686,7 +2685,7 @@ pmap_remove_write(vm_page_t m)
pmap_protect(pv->pv_pmap, va, va + PAGE_SIZE,
VM_PROT_READ | VM_PROT_EXECUTE);
}
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
vm_page_unlock_queues();
}
@@ -2699,7 +2698,7 @@ int
pmap_ts_referenced(vm_page_t m)
{
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_ts_referenced: page %p is not managed", m));
if (m->md.pv_flags & PV_TABLE_REF) {
vm_page_lock_queues();
@@ -2721,17 +2720,17 @@ pmap_is_modified(vm_page_t m)
{
boolean_t rv;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_is_modified: page %p is not managed", m));
/*
- * If the page is not VPO_BUSY, then PG_WRITEABLE cannot be
- * concurrently set while the object is locked. Thus, if PG_WRITEABLE
+ * If the page is not VPO_BUSY, then PGA_WRITEABLE cannot be
+ * concurrently set while the object is locked. Thus, if PGA_WRITEABLE
* is clear, no PTEs can have PTE_D set.
*/
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
if ((m->oflags & VPO_BUSY) == 0 &&
- (m->flags & PG_WRITEABLE) == 0)
+ (m->aflags & PGA_WRITEABLE) == 0)
return (FALSE);
vm_page_lock_queues();
if (m->md.pv_flags & PV_TABLE_MOD)
@@ -2775,18 +2774,18 @@ void
pmap_clear_modify(vm_page_t m)
{
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_clear_modify: page %p is not managed", m));
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
KASSERT((m->oflags & VPO_BUSY) == 0,
("pmap_clear_modify: page %p is busy", m));
/*
- * If the page is not PG_WRITEABLE, then no PTEs can have PTE_D set.
+ * If the page is not PGA_WRITEABLE, then no PTEs can have PTE_D set.
* If the object containing the page is locked and the page is not
- * VPO_BUSY, then PG_WRITEABLE cannot be concurrently set.
+ * VPO_BUSY, then PGA_WRITEABLE cannot be concurrently set.
*/
- if ((m->flags & PG_WRITEABLE) == 0)
+ if ((m->aflags & PGA_WRITEABLE) == 0)
return;
vm_page_lock_queues();
if (m->md.pv_flags & PV_TABLE_MOD) {
@@ -2806,7 +2805,7 @@ boolean_t
pmap_is_referenced(vm_page_t m)
{
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_is_referenced: page %p is not managed", m));
return ((m->md.pv_flags & PV_TABLE_REF) != 0);
}
@@ -2820,7 +2819,7 @@ void
pmap_clear_reference(vm_page_t m)
{
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_clear_reference: page %p is not managed", m));
vm_page_lock_queues();
if (m->md.pv_flags & PV_TABLE_REF) {
@@ -2930,7 +2929,7 @@ retry:
* determine if the address is MINCORE_REFERENCED.
*/
m = PHYS_TO_VM_PAGE(pa);
- if ((m->flags & PG_REFERENCED) != 0)
+ if ((m->aflags & PGA_REFERENCED) != 0)
val |= MINCORE_REFERENCED | MINCORE_REFERENCED_OTHER;
}
if ((val & (MINCORE_MODIFIED_OTHER | MINCORE_REFERENCED_OTHER)) !=
@@ -3168,7 +3167,7 @@ page_is_managed(vm_paddr_t pa)
m = PHYS_TO_VM_PAGE(pa);
if (m == NULL)
return (0);
- if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0)
+ if ((m->oflags & VPO_UNMANAGED) == 0)
return (1);
}
return (0);
@@ -3181,12 +3180,12 @@ init_pte_prot(vm_offset_t va, vm_page_t m, vm_prot_t prot)
if (!(prot & VM_PROT_WRITE))
rw = PTE_V | PTE_RO | PTE_C_CACHE;
- else if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0) {
+ else if ((m->oflags & VPO_UNMANAGED) == 0) {
if ((m->md.pv_flags & PV_TABLE_MOD) != 0)
rw = PTE_V | PTE_D | PTE_C_CACHE;
else
rw = PTE_V | PTE_C_CACHE;
- vm_page_flag_set(m, PG_WRITEABLE);
+ vm_page_aflag_set(m, PGA_WRITEABLE);
} else
/* Needn't emulate a modified bit for unmanaged pages. */
rw = PTE_V | PTE_D | PTE_C_CACHE;
diff --git a/sys/mips/nlm/board.c b/sys/mips/nlm/board.c
index d75059e21caec..5fd771d8d2cb4 100644
--- a/sys/mips/nlm/board.c
+++ b/sys/mips/nlm/board.c
@@ -29,7 +29,6 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
@@ -38,7 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mutex.h>
#include <mips/nlm/hal/mips-extns.h>
-#include <mips/nlm/hal/mmio.h>
+#include <mips/nlm/hal/haldefs.h>
#include <mips/nlm/hal/iomap.h>
#include <mips/nlm/hal/fmn.h>
#include <mips/nlm/hal/pic.h>
diff --git a/sys/mips/nlm/board.h b/sys/mips/nlm/board.h
index 742ebbab2a4ba..5a0c868c5105a 100644
--- a/sys/mips/nlm/board.h
+++ b/sys/mips/nlm/board.h
@@ -25,8 +25,9 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
+ * NETLOGIC_BSD
* $FreeBSD$
- * NETLOGIC_BSD */
+ */
#ifndef __NLM_BOARD_H__
#define __NLM_BOARD_H__
diff --git a/sys/mips/nlm/bus_space_rmi.c b/sys/mips/nlm/bus_space_rmi.c
index 8653cdfaaf421..6bb3fff7f8fb6 100644
--- a/sys/mips/nlm/bus_space_rmi.c
+++ b/sys/mips/nlm/bus_space_rmi.c
@@ -401,14 +401,14 @@ static u_int8_t
rmi_bus_space_read_1(void *tag, bus_space_handle_t handle,
bus_size_t offset)
{
- return (u_int8_t) (*(volatile u_int32_t *)(handle + offset));
+ return (u_int8_t) (*(volatile u_int8_t *)(handle + offset));
}
static u_int16_t
rmi_bus_space_read_2(void *tag, bus_space_handle_t handle,
bus_size_t offset)
{
- return (u_int16_t)(*(volatile u_int32_t *)(handle + offset));
+ return (u_int16_t)(*(volatile u_int16_t *)(handle + offset));
}
static u_int32_t
@@ -453,14 +453,14 @@ static void
rmi_bus_space_write_1(void *tag, bus_space_handle_t handle,
bus_size_t offset, u_int8_t value)
{
- *(volatile u_int32_t *)(handle + offset) = (u_int32_t)value;
+ *(volatile u_int8_t *)(handle + offset) = value;
}
static void
rmi_bus_space_write_2(void *tag, bus_space_handle_t handle,
bus_size_t offset, u_int16_t value)
{
- *(volatile u_int32_t *)(handle + offset) = (u_int32_t)value;
+ *(volatile u_int16_t *)(handle + offset) = value;
}
static void
diff --git a/sys/mips/nlm/bus_space_rmi_pci.c b/sys/mips/nlm/bus_space_rmi_pci.c
new file mode 100644
index 0000000000000..8e757ef02070a
--- /dev/null
+++ b/sys/mips/nlm/bus_space_rmi_pci.c
@@ -0,0 +1,768 @@
+/*-
+ * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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.
+ *
+ * NETLOGIC_BSD */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/endian.h>
+#include <sys/malloc.h>
+#include <sys/ktr.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_extern.h>
+
+#include <machine/bus.h>
+#include <machine/cache.h>
+
+static int
+rmi_pci_bus_space_map(void *t, bus_addr_t addr,
+ bus_size_t size, int flags,
+ bus_space_handle_t * bshp);
+
+static void
+rmi_pci_bus_space_unmap(void *t, bus_space_handle_t bsh,
+ bus_size_t size);
+
+static int
+rmi_pci_bus_space_subregion(void *t,
+ bus_space_handle_t bsh,
+ bus_size_t offset, bus_size_t size,
+ bus_space_handle_t * nbshp);
+
+static u_int8_t
+rmi_pci_bus_space_read_1(void *t,
+ bus_space_handle_t handle,
+ bus_size_t offset);
+
+static u_int16_t
+rmi_pci_bus_space_read_2(void *t,
+ bus_space_handle_t handle,
+ bus_size_t offset);
+
+static u_int32_t
+rmi_pci_bus_space_read_4(void *t,
+ bus_space_handle_t handle,
+ bus_size_t offset);
+
+static void
+rmi_pci_bus_space_read_multi_1(void *t,
+ bus_space_handle_t handle,
+ bus_size_t offset, u_int8_t * addr,
+ size_t count);
+
+static void
+rmi_pci_bus_space_read_multi_2(void *t,
+ bus_space_handle_t handle,
+ bus_size_t offset, u_int16_t * addr,
+ size_t count);
+
+static void
+rmi_pci_bus_space_read_multi_4(void *t,
+ bus_space_handle_t handle,
+ bus_size_t offset, u_int32_t * addr,
+ size_t count);
+
+static void
+rmi_pci_bus_space_read_region_1(void *t,
+ bus_space_handle_t bsh,
+ bus_size_t offset, u_int8_t * addr,
+ size_t count);
+
+static void
+rmi_pci_bus_space_read_region_2(void *t,
+ bus_space_handle_t bsh,
+ bus_size_t offset, u_int16_t * addr,
+ size_t count);
+
+static void
+rmi_pci_bus_space_read_region_4(void *t,
+ bus_space_handle_t bsh,
+ bus_size_t offset, u_int32_t * addr,
+ size_t count);
+
+static void
+rmi_pci_bus_space_write_1(void *t,
+ bus_space_handle_t handle,
+ bus_size_t offset, u_int8_t value);
+
+static void
+rmi_pci_bus_space_write_2(void *t,
+ bus_space_handle_t handle,
+ bus_size_t offset, u_int16_t value);
+
+static void
+rmi_pci_bus_space_write_4(void *t,
+ bus_space_handle_t handle,
+ bus_size_t offset, u_int32_t value);
+
+static void
+rmi_pci_bus_space_write_multi_1(void *t,
+ bus_space_handle_t handle,
+ bus_size_t offset,
+ const u_int8_t * addr,
+ size_t count);
+
+static void
+rmi_pci_bus_space_write_multi_2(void *t,
+ bus_space_handle_t handle,
+ bus_size_t offset,
+ const u_int16_t * addr,
+ size_t count);
+
+static void
+rmi_pci_bus_space_write_multi_4(void *t,
+ bus_space_handle_t handle,
+ bus_size_t offset,
+ const u_int32_t * addr,
+ size_t count);
+
+static void
+rmi_pci_bus_space_write_region_2(void *t,
+ bus_space_handle_t bsh,
+ bus_size_t offset,
+ const u_int16_t * addr,
+ size_t count);
+
+static void
+rmi_pci_bus_space_write_region_4(void *t,
+ bus_space_handle_t bsh,
+ bus_size_t offset,
+ const u_int32_t * addr,
+ size_t count);
+
+
+static void
+rmi_pci_bus_space_set_region_2(void *t,
+ bus_space_handle_t bsh,
+ bus_size_t offset, u_int16_t value,
+ size_t count);
+static void
+rmi_pci_bus_space_set_region_4(void *t,
+ bus_space_handle_t bsh,
+ bus_size_t offset, u_int32_t value,
+ size_t count);
+
+static void
+rmi_pci_bus_space_barrier(void *tag __unused, bus_space_handle_t bsh __unused,
+ bus_size_t offset __unused, bus_size_t len __unused, int flags);
+
+static void
+rmi_pci_bus_space_copy_region_2(void *t,
+ bus_space_handle_t bsh1,
+ bus_size_t off1,
+ bus_space_handle_t bsh2,
+ bus_size_t off2, size_t count);
+
+u_int8_t
+rmi_pci_bus_space_read_stream_1(void *t, bus_space_handle_t handle,
+ bus_size_t offset);
+
+static u_int16_t
+rmi_pci_bus_space_read_stream_2(void *t, bus_space_handle_t handle,
+ bus_size_t offset);
+
+static u_int32_t
+rmi_pci_bus_space_read_stream_4(void *t, bus_space_handle_t handle,
+ bus_size_t offset);
+static void
+rmi_pci_bus_space_read_multi_stream_1(void *t,
+ bus_space_handle_t handle,
+ bus_size_t offset, u_int8_t * addr,
+ size_t count);
+
+static void
+rmi_pci_bus_space_read_multi_stream_2(void *t,
+ bus_space_handle_t handle,
+ bus_size_t offset, u_int16_t * addr,
+ size_t count);
+
+static void
+rmi_pci_bus_space_read_multi_stream_4(void *t,
+ bus_space_handle_t handle,
+ bus_size_t offset, u_int32_t * addr,
+ size_t count);
+
+void
+rmi_pci_bus_space_write_stream_1(void *t, bus_space_handle_t bsh,
+ bus_size_t offset, u_int8_t value);
+static void
+rmi_pci_bus_space_write_stream_2(void *t, bus_space_handle_t handle,
+ bus_size_t offset, u_int16_t value);
+
+static void
+rmi_pci_bus_space_write_stream_4(void *t, bus_space_handle_t handle,
+ bus_size_t offset, u_int32_t value);
+
+static void
+rmi_pci_bus_space_write_multi_stream_1(void *t,
+ bus_space_handle_t handle,
+ bus_size_t offset,
+ const u_int8_t * addr,
+ size_t count);
+static void
+rmi_pci_bus_space_write_multi_stream_2(void *t,
+ bus_space_handle_t handle,
+ bus_size_t offset,
+ const u_int16_t * addr,
+ size_t count);
+
+static void
+rmi_pci_bus_space_write_multi_stream_4(void *t,
+ bus_space_handle_t handle,
+ bus_size_t offset,
+ const u_int32_t * addr,
+ size_t count);
+
+#define TODO() printf("XLR memory bus space function '%s' unimplemented\n", __func__)
+
+static struct bus_space local_rmi_pci_bus_space = {
+ /* cookie */
+ (void *)0,
+
+ /* mapping/unmapping */
+ rmi_pci_bus_space_map,
+ rmi_pci_bus_space_unmap,
+ rmi_pci_bus_space_subregion,
+
+ /* allocation/deallocation */
+ NULL,
+ NULL,
+
+ /* barrier */
+ rmi_pci_bus_space_barrier,
+
+ /* read (single) */
+ rmi_pci_bus_space_read_1,
+ rmi_pci_bus_space_read_2,
+ rmi_pci_bus_space_read_4,
+ NULL,
+
+ /* read multiple */
+ rmi_pci_bus_space_read_multi_1,
+ rmi_pci_bus_space_read_multi_2,
+ rmi_pci_bus_space_read_multi_4,
+ NULL,
+
+ /* read region */
+ rmi_pci_bus_space_read_region_1,
+ rmi_pci_bus_space_read_region_2,
+ rmi_pci_bus_space_read_region_4,
+ NULL,
+
+ /* write (single) */
+ rmi_pci_bus_space_write_1,
+ rmi_pci_bus_space_write_2,
+ rmi_pci_bus_space_write_4,
+ NULL,
+
+ /* write multiple */
+ rmi_pci_bus_space_write_multi_1,
+ rmi_pci_bus_space_write_multi_2,
+ rmi_pci_bus_space_write_multi_4,
+ NULL,
+
+ /* write region */
+ NULL,
+ rmi_pci_bus_space_write_region_2,
+ rmi_pci_bus_space_write_region_4,
+ NULL,
+
+ /* set multiple */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+
+ /* set region */
+ NULL,
+ rmi_pci_bus_space_set_region_2,
+ rmi_pci_bus_space_set_region_4,
+ NULL,
+
+ /* copy */
+ NULL,
+ rmi_pci_bus_space_copy_region_2,
+ NULL,
+ NULL,
+
+ /* read (single) stream */
+ rmi_pci_bus_space_read_stream_1,
+ rmi_pci_bus_space_read_stream_2,
+ rmi_pci_bus_space_read_stream_4,
+ NULL,
+
+ /* read multiple stream */
+ rmi_pci_bus_space_read_multi_stream_1,
+ rmi_pci_bus_space_read_multi_stream_2,
+ rmi_pci_bus_space_read_multi_stream_4,
+ NULL,
+
+ /* read region stream */
+ rmi_pci_bus_space_read_region_1,
+ rmi_pci_bus_space_read_region_2,
+ rmi_pci_bus_space_read_region_4,
+ NULL,
+
+ /* write (single) stream */
+ rmi_pci_bus_space_write_stream_1,
+ rmi_pci_bus_space_write_stream_2,
+ rmi_pci_bus_space_write_stream_4,
+ NULL,
+
+ /* write multiple stream */
+ rmi_pci_bus_space_write_multi_stream_1,
+ rmi_pci_bus_space_write_multi_stream_2,
+ rmi_pci_bus_space_write_multi_stream_4,
+ NULL,
+
+ /* write region stream */
+ NULL,
+ rmi_pci_bus_space_write_region_2,
+ rmi_pci_bus_space_write_region_4,
+ NULL,
+};
+
+/* generic bus_space tag */
+bus_space_tag_t rmi_pci_bus_space = &local_rmi_pci_bus_space;
+
+/*
+ * Map a region of device bus space into CPU virtual address space.
+ */
+static int
+rmi_pci_bus_space_map(void *t __unused, bus_addr_t addr,
+ bus_size_t size __unused, int flags __unused,
+ bus_space_handle_t * bshp)
+{
+ *bshp = addr;
+ return (0);
+}
+
+/*
+ * Unmap a region of device bus space.
+ */
+static void
+rmi_pci_bus_space_unmap(void *t __unused, bus_space_handle_t bsh __unused,
+ bus_size_t size __unused)
+{
+}
+
+/*
+ * Get a new handle for a subregion of an already-mapped area of bus space.
+ */
+
+static int
+rmi_pci_bus_space_subregion(void *t __unused, bus_space_handle_t bsh,
+ bus_size_t offset, bus_size_t size __unused,
+ bus_space_handle_t * nbshp)
+{
+ *nbshp = bsh + offset;
+ return (0);
+}
+
+/*
+ * Read a 1, 2, 4, or 8 byte quantity from bus space
+ * described by tag/handle/offset.
+ */
+
+static u_int8_t
+rmi_pci_bus_space_read_1(void *tag, bus_space_handle_t handle,
+ bus_size_t offset)
+{
+ return (u_int8_t) (*(volatile u_int8_t *)(handle + offset));
+}
+
+static u_int16_t
+rmi_pci_bus_space_read_2(void *tag, bus_space_handle_t handle,
+ bus_size_t offset)
+{
+ u_int16_t value;
+
+ value = *(volatile u_int16_t *)(handle + offset);
+ return bswap16(value);
+}
+
+static u_int32_t
+rmi_pci_bus_space_read_4(void *tag, bus_space_handle_t handle,
+ bus_size_t offset)
+{
+ uint32_t value;
+
+ value = *(volatile u_int32_t *)(handle + offset);
+ return bswap32(value);
+}
+
+/*
+ * Read `count' 1, 2, 4, or 8 byte quantities from bus space
+ * described by tag/handle/offset and copy into buffer provided.
+ */
+static void
+rmi_pci_bus_space_read_multi_1(void *tag, bus_space_handle_t handle,
+ bus_size_t offset, u_int8_t * addr, size_t count)
+{
+ while (count--) {
+ *addr = *(volatile u_int8_t *)(handle + offset);
+ addr++;
+ }
+}
+
+static void
+rmi_pci_bus_space_read_multi_2(void *tag, bus_space_handle_t handle,
+ bus_size_t offset, u_int16_t * addr, size_t count)
+{
+
+ while (count--) {
+ *addr = *(volatile u_int16_t *)(handle + offset);
+ *addr = bswap16(*addr);
+ addr++;
+ }
+}
+
+static void
+rmi_pci_bus_space_read_multi_4(void *tag, bus_space_handle_t handle,
+ bus_size_t offset, u_int32_t * addr, size_t count)
+{
+
+ while (count--) {
+ *addr = *(volatile u_int32_t *)(handle + offset);
+ *addr = bswap32(*addr);
+ addr++;
+ }
+}
+
+/*
+ * Write the 1, 2, 4, or 8 byte value `value' to bus space
+ * described by tag/handle/offset.
+ */
+
+static void
+rmi_pci_bus_space_write_1(void *tag, bus_space_handle_t handle,
+ bus_size_t offset, u_int8_t value)
+{
+ mips_sync();
+ *(volatile u_int8_t *)(handle + offset) = value;
+}
+
+static void
+rmi_pci_bus_space_write_2(void *tag, bus_space_handle_t handle,
+ bus_size_t offset, u_int16_t value)
+{
+ mips_sync();
+ *(volatile u_int16_t *)(handle + offset) = bswap16(value);
+}
+
+
+static void
+rmi_pci_bus_space_write_4(void *tag, bus_space_handle_t handle,
+ bus_size_t offset, u_int32_t value)
+{
+ mips_sync();
+ *(volatile u_int32_t *)(handle + offset) = bswap32(value);
+}
+
+/*
+ * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
+ * provided to bus space described by tag/handle/offset.
+ */
+
+
+static void
+rmi_pci_bus_space_write_multi_1(void *tag, bus_space_handle_t handle,
+ bus_size_t offset, const u_int8_t * addr, size_t count)
+{
+ mips_sync();
+ while (count--) {
+ (*(volatile u_int8_t *)(handle + offset)) = *addr;
+ addr++;
+ }
+}
+
+static void
+rmi_pci_bus_space_write_multi_2(void *tag, bus_space_handle_t handle,
+ bus_size_t offset, const u_int16_t * addr, size_t count)
+{
+ mips_sync();
+ while (count--) {
+ (*(volatile u_int16_t *)(handle + offset)) = bswap16(*addr);
+ addr++;
+ }
+}
+
+static void
+rmi_pci_bus_space_write_multi_4(void *tag, bus_space_handle_t handle,
+ bus_size_t offset, const u_int32_t * addr, size_t count)
+{
+ mips_sync();
+ while (count--) {
+ (*(volatile u_int32_t *)(handle + offset)) = bswap32(*addr);
+ addr++;
+ }
+}
+
+/*
+ * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
+ * by tag/handle starting at `offset'.
+ */
+
+static void
+rmi_pci_bus_space_set_region_2(void *t, bus_space_handle_t bsh,
+ bus_size_t offset, u_int16_t value, size_t count)
+{
+ bus_addr_t addr = bsh + offset;
+
+ for (; count != 0; count--, addr += 2)
+ (*(volatile u_int16_t *)(addr)) = value;
+}
+
+static void
+rmi_pci_bus_space_set_region_4(void *t, bus_space_handle_t bsh,
+ bus_size_t offset, u_int32_t value, size_t count)
+{
+ bus_addr_t addr = bsh + offset;
+
+ for (; count != 0; count--, addr += 4)
+ (*(volatile u_int32_t *)(addr)) = value;
+}
+
+
+/*
+ * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
+ * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
+ */
+static void
+rmi_pci_bus_space_copy_region_2(void *t, bus_space_handle_t bsh1,
+ bus_size_t off1, bus_space_handle_t bsh2,
+ bus_size_t off2, size_t count)
+{
+ TODO();
+}
+
+/*
+ * Read `count' 1, 2, 4, or 8 byte quantities from bus space
+ * described by tag/handle/offset and copy into buffer provided.
+ */
+
+u_int8_t
+rmi_pci_bus_space_read_stream_1(void *t, bus_space_handle_t handle,
+ bus_size_t offset)
+{
+
+ return *((volatile u_int8_t *)(handle + offset));
+}
+
+
+static u_int16_t
+rmi_pci_bus_space_read_stream_2(void *t, bus_space_handle_t handle,
+ bus_size_t offset)
+{
+ return *(volatile u_int16_t *)(handle + offset);
+}
+
+
+static u_int32_t
+rmi_pci_bus_space_read_stream_4(void *t, bus_space_handle_t handle,
+ bus_size_t offset)
+{
+ return (*(volatile u_int32_t *)(handle + offset));
+}
+
+
+static void
+rmi_pci_bus_space_read_multi_stream_1(void *tag, bus_space_handle_t handle,
+ bus_size_t offset, u_int8_t * addr, size_t count)
+{
+ while (count--) {
+ *addr = (*(volatile u_int8_t *)(handle + offset));
+ addr++;
+ }
+}
+
+static void
+rmi_pci_bus_space_read_multi_stream_2(void *tag, bus_space_handle_t handle,
+ bus_size_t offset, u_int16_t * addr, size_t count)
+{
+ while (count--) {
+ *addr = (*(volatile u_int16_t *)(handle + offset));
+ addr++;
+ }
+}
+
+static void
+rmi_pci_bus_space_read_multi_stream_4(void *tag, bus_space_handle_t handle,
+ bus_size_t offset, u_int32_t * addr, size_t count)
+{
+ while (count--) {
+ *addr = (*(volatile u_int32_t *)(handle + offset));
+ addr++;
+ }
+}
+
+
+
+/*
+ * Read `count' 1, 2, 4, or 8 byte quantities from bus space
+ * described by tag/handle and starting at `offset' and copy into
+ * buffer provided.
+ */
+void
+rmi_pci_bus_space_read_region_1(void *t, bus_space_handle_t bsh,
+ bus_size_t offset, u_int8_t * addr, size_t count)
+{
+ bus_addr_t baddr = bsh + offset;
+
+ while (count--) {
+ *addr++ = (*(volatile u_int8_t *)(baddr));
+ baddr += 1;
+ }
+}
+
+void
+rmi_pci_bus_space_read_region_2(void *t, bus_space_handle_t bsh,
+ bus_size_t offset, u_int16_t * addr, size_t count)
+{
+ bus_addr_t baddr = bsh + offset;
+
+ while (count--) {
+ *addr++ = (*(volatile u_int16_t *)(baddr));
+ baddr += 2;
+ }
+}
+
+void
+rmi_pci_bus_space_read_region_4(void *t, bus_space_handle_t bsh,
+ bus_size_t offset, u_int32_t * addr, size_t count)
+{
+ bus_addr_t baddr = bsh + offset;
+
+ while (count--) {
+ *addr++ = (*(volatile u_int32_t *)(baddr));
+ baddr += 4;
+ }
+}
+
+
+void
+rmi_pci_bus_space_write_stream_1(void *t, bus_space_handle_t handle,
+ bus_size_t offset, u_int8_t value)
+{
+ mips_sync();
+ *(volatile u_int8_t *)(handle + offset) = value;
+}
+
+static void
+rmi_pci_bus_space_write_stream_2(void *t, bus_space_handle_t handle,
+ bus_size_t offset, u_int16_t value)
+{
+ mips_sync();
+ *(volatile u_int16_t *)(handle + offset) = value;
+}
+
+
+static void
+rmi_pci_bus_space_write_stream_4(void *t, bus_space_handle_t handle,
+ bus_size_t offset, u_int32_t value)
+{
+ mips_sync();
+ *(volatile u_int32_t *)(handle + offset) = value;
+}
+
+
+static void
+rmi_pci_bus_space_write_multi_stream_1(void *tag, bus_space_handle_t handle,
+ bus_size_t offset, const u_int8_t * addr, size_t count)
+{
+ mips_sync();
+ while (count--) {
+ (*(volatile u_int8_t *)(handle + offset)) = *addr;
+ addr++;
+ }
+}
+
+static void
+rmi_pci_bus_space_write_multi_stream_2(void *tag, bus_space_handle_t handle,
+ bus_size_t offset, const u_int16_t * addr, size_t count)
+{
+ mips_sync();
+ while (count--) {
+ (*(volatile u_int16_t *)(handle + offset)) = *addr;
+ addr++;
+ }
+}
+
+static void
+rmi_pci_bus_space_write_multi_stream_4(void *tag, bus_space_handle_t handle,
+ bus_size_t offset, const u_int32_t * addr, size_t count)
+{
+ mips_sync();
+ while (count--) {
+ (*(volatile u_int32_t *)(handle + offset)) = *addr;
+ addr++;
+ }
+}
+
+void
+rmi_pci_bus_space_write_region_2(void *t,
+ bus_space_handle_t bsh,
+ bus_size_t offset,
+ const u_int16_t * addr,
+ size_t count)
+{
+ bus_addr_t baddr = (bus_addr_t) bsh + offset;
+
+ while (count--) {
+ (*(volatile u_int16_t *)(baddr)) = *addr;
+ addr++;
+ baddr += 2;
+ }
+}
+
+void
+rmi_pci_bus_space_write_region_4(void *t, bus_space_handle_t bsh,
+ bus_size_t offset, const u_int32_t * addr, size_t count)
+{
+ bus_addr_t baddr = bsh + offset;
+
+ while (count--) {
+ (*(volatile u_int32_t *)(baddr)) = *addr;
+ addr++;
+ baddr += 4;
+ }
+}
+
+static void
+rmi_pci_bus_space_barrier(void *tag __unused, bus_space_handle_t bsh __unused,
+ bus_size_t offset __unused, bus_size_t len __unused, int flags)
+{
+
+}
diff --git a/sys/mips/nlm/clock.h b/sys/mips/nlm/clock.h
index 2135dbf5ee0d3..7a2be07004527 100644
--- a/sys/mips/nlm/clock.h
+++ b/sys/mips/nlm/clock.h
@@ -25,8 +25,9 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
+ * NETLOGIC_BSD
* $FreeBSD$
- * NETLOGIC_BSD */
+ */
#ifndef _RMI_CLOCK_H_
#define _RMI_CLOCK_H_
diff --git a/sys/mips/nlm/cms.c b/sys/mips/nlm/cms.c
index fb03d8030f0eb..043d5884e0720 100644
--- a/sys/mips/nlm/cms.c
+++ b/sys/mips/nlm/cms.c
@@ -56,9 +56,8 @@ __FBSDID("$FreeBSD$");
#include <machine/intr_machdep.h>
#include <mips/nlm/hal/mips-extns.h>
-#include <mips/nlm/hal/mmio.h>
+#include <mips/nlm/hal/haldefs.h>
#include <mips/nlm/hal/iomap.h>
-#include <mips/nlm/hal/cop0.h>
#include <mips/nlm/hal/cop2.h>
#include <mips/nlm/hal/fmn.h>
#include <mips/nlm/hal/pic.h>
@@ -108,7 +107,7 @@ xlp_msgring_config(void)
int i;
/* TODO: Add other nodes */
- xlp_cms_base = nlm_regbase_cms(0);
+ xlp_cms_base = nlm_get_cms_regbase(0);
mtx_init(&msgmap_lock, "msgring", NULL, MTX_SPIN);
if (xlp_threads_per_core < xlp_msg_threads_per_core)
@@ -147,62 +146,58 @@ xlp_msgring_iodi_config(void)
void
nlm_cms_credit_setup(int credit)
{
- int src, qid, i;
+ int src, qid, i;
#if 0
- /* there are a total of 18 src stations on XLP. */
+ /* there are a total of 18 src stations on XLP. */
printf("Setting up CMS credits!\n");
- for(src=0; src<18; src++) {
- for(qid=0; qid<1024; qid++) {
- nlm_cms_setup_credits(xlp_cms_base, qid, src, credit);
- }
- }
+ for (src=0; src<18; src++) {
+ for(qid=0; qid<1024; qid++) {
+ nlm_cms_setup_credits(xlp_cms_base, qid, src, credit);
+ }
+ }
#endif
printf("Setting up CMS credits!\n");
/* CPU Credits */
- for(i = 1; i < 8; i++) {
+ for (i = 1; i < 8; i++) {
src = (i << 4);
- for(qid = 0; qid < 1024; qid++) {
- nlm_cms_setup_credits(xlp_cms_base, qid, src, credit);
- }
- }
+ for (qid = 0; qid < 1024; qid++)
+ nlm_cms_setup_credits(xlp_cms_base, qid, src, credit);
+ }
/* PCIE Credits */
- for(i = 0; i < 4; i++) {
+ for(i = 0; i < 4; i++) {
src = (256 + (i * 2));
- for(qid = 0; qid < 1024; qid++) {
- nlm_cms_setup_credits(xlp_cms_base, qid, src, credit);
- }
- }
+ for(qid = 0; qid < 1024; qid++)
+ nlm_cms_setup_credits(xlp_cms_base, qid, src, credit);
+ }
/* DTE Credits */
src = 264;
- for(qid = 0; qid < 1024; qid++) {
- nlm_cms_setup_credits(xlp_cms_base, qid, src, credit);
- }
+ for (qid = 0; qid < 1024; qid++)
+ nlm_cms_setup_credits(xlp_cms_base, qid, src, credit);
/* RSA Credits */
src = 272;
- for(qid = 0; qid < 1024; qid++) {
- nlm_cms_setup_credits(xlp_cms_base, qid, src, credit);
- }
+ for (qid = 0; qid < 1024; qid++)
+ nlm_cms_setup_credits(xlp_cms_base, qid, src, credit);
+
/* Crypto Credits */
src = 281;
- for(qid = 0; qid < 1024; qid++) {
- nlm_cms_setup_credits(xlp_cms_base, qid, src, credit);
- }
+ for (qid = 0; qid < 1024; qid++)
+ nlm_cms_setup_credits(xlp_cms_base, qid, src, credit);
+
/* CMP Credits */
src = 298;
- for(qid = 0; qid < 1024; qid++) {
- nlm_cms_setup_credits(xlp_cms_base, qid, src, credit);
- }
+ for (qid = 0; qid < 1024; qid++)
+ nlm_cms_setup_credits(xlp_cms_base, qid, src, credit);
+
/* POE Credits */
src = 384;
- for(qid = 0; qid < 1024; qid++) {
- nlm_cms_setup_credits(xlp_cms_base, qid, src, credit);
- }
+ for(qid = 0; qid < 1024; qid++)
+ nlm_cms_setup_credits(xlp_cms_base, qid, src, credit);
+
/* NAE Credits */
src = 476;
- for(qid = 0; qid < 1024; qid++) {
- nlm_cms_setup_credits(xlp_cms_base, qid, src, credit);
- }
+ for(qid = 0; qid < 1024; qid++)
+ nlm_cms_setup_credits(xlp_cms_base, qid, src, credit);
}
void
@@ -210,7 +205,7 @@ xlp_msgring_cpu_init(uint32_t cpuid)
{
int queue,i;
- queue = XLP_CMS_CPU_PUSHQ(0, ((cpuid >> 2) & 0x7), (cpuid & 0x3), 0);
+ queue = CMS_CPU_PUSHQ(0, ((cpuid >> 2) & 0x7), (cpuid & 0x3), 0);
/* temp allocate 4 segments to each output queue */
nlm_cms_alloc_onchip_q(xlp_cms_base, queue, 4);
/* Enable high watermark and non empty interrupt */
@@ -247,9 +242,9 @@ xlp_handle_msg_vc(int vc, int max_msgs)
uint32_t mflags, status;
for (i = 0; i < max_msgs; i++) {
- mflags = nlm_fmn_saveflags();
+ mflags = nlm_save_flags_cop2();
status = nlm_fmn_msgrcv(vc, &srcid, &size, &code, &msg);
- nlm_fmn_restoreflags(mflags);
+ nlm_restore_flags(mflags);
if (status != 0) /* If there is no msg or error */
break;
if (srcid < 0 && srcid >= 1024) {
@@ -273,27 +268,27 @@ xlp_handle_msg_vc(int vc, int max_msgs)
static int
msgring_process_fast_intr(void *arg)
{
- struct msgring_thread *mthd;
- struct thread *td;
- int cpu;
+ struct msgring_thread *mthd;
+ struct thread *td;
+ int cpu;
cpu = nlm_cpuid();
- mthd = &msgring_threads[cpu];
- td = mthd->thread;
+ mthd = &msgring_threads[cpu];
+ td = mthd->thread;
- /* clear pending interrupts */
- nlm_write_c0_eirr(1ULL << IRQ_MSGRING);
+ /* clear pending interrupts */
+ nlm_write_c0_eirr(1ULL << IRQ_MSGRING);
- /* wake up the target thread */
- mthd->needed = 1;
- thread_lock(td);
- if (TD_AWAITING_INTR(td)) {
- TD_CLR_IWAIT(td);
- sched_add(td, SRQ_INTR);
- }
+ /* wake up the target thread */
+ mthd->needed = 1;
+ thread_lock(td);
+ if (TD_AWAITING_INTR(td)) {
+ TD_CLR_IWAIT(td);
+ sched_add(td, SRQ_INTR);
+ }
- thread_unlock(td);
- return (FILTER_HANDLED);
+ thread_unlock(td);
+ return (FILTER_HANDLED);
}
u_int fmn_msgcount[32][4];
@@ -302,31 +297,31 @@ u_int fmn_loops[32];
static void
msgring_process(void * arg)
{
- volatile struct msgring_thread *mthd;
- struct thread *td;
- uint32_t mflags;
+ volatile struct msgring_thread *mthd;
+ struct thread *td;
+ uint32_t mflags;
int hwtid, vc, handled, nmsgs;
hwtid = (intptr_t)arg;
- mthd = &msgring_threads[hwtid];
- td = mthd->thread;
- KASSERT(curthread == td,
- ("%s:msg_ithread and proc linkage out of sync", __func__));
+ mthd = &msgring_threads[hwtid];
+ td = mthd->thread;
+ KASSERT(curthread == td,
+ ("%s:msg_ithread and proc linkage out of sync", __func__));
- /* First bind this thread to the right CPU */
- thread_lock(td);
- sched_bind(td, xlp_hwtid_to_cpuid[hwtid]);
- thread_unlock(td);
+ /* First bind this thread to the right CPU */
+ thread_lock(td);
+ sched_bind(td, xlp_hwtid_to_cpuid[hwtid]);
+ thread_unlock(td);
if (hwtid != nlm_cpuid())
printf("Misscheduled hwtid %d != cpuid %d\n", hwtid, nlm_cpuid());
- mflags = nlm_fmn_saveflags();
- nlm_fmn_cpu_init(IRQ_MSGRING, 0, 0, 0, 0, 0);
- nlm_fmn_restoreflags(mflags);
+ mflags = nlm_save_flags_cop2();
+ nlm_fmn_cpu_init(IRQ_MSGRING, 0, 0, 0, 0, 0);
+ nlm_restore_flags(mflags);
- /* start processing messages */
- for( ; ; ) {
- /*atomic_store_rel_int(&mthd->needed, 0);*/
+ /* start processing messages */
+ for( ; ; ) {
+ /*atomic_store_rel_int(&mthd->needed, 0);*/
/* enable cop2 access */
do {
@@ -338,22 +333,22 @@ msgring_process(void * arg)
}
} while (handled);
- /* sleep */
+ /* sleep */
#if 0
- thread_lock(td);
- if (mthd->needed) {
- thread_unlock(td);
- continue;
- }
- sched_class(td, PRI_ITHD);
- TD_SET_IWAIT(td);
- mi_switch(SW_VOL, NULL);
- thread_unlock(td);
+ thread_lock(td);
+ if (mthd->needed) {
+ thread_unlock(td);
+ continue;
+ }
+ sched_class(td, PRI_ITHD);
+ TD_SET_IWAIT(td);
+ mi_switch(SW_VOL, NULL);
+ thread_unlock(td);
#else
pause("wmsg", 1);
#endif
fmn_loops[hwtid]++;
- }
+ }
}
static void
@@ -396,7 +391,6 @@ register_msgring_handler(int startb, int endb, msgring_handler action,
msgmap[i].arg = arg;
}
mtx_unlock_spin(&msgmap_lock);
-
return (0);
}
diff --git a/sys/mips/nlm/files.xlp b/sys/mips/nlm/files.xlp
index ac138454896f1..f9b2b719d3a5a 100644
--- a/sys/mips/nlm/files.xlp
+++ b/sys/mips/nlm/files.xlp
@@ -3,10 +3,13 @@ mips/nlm/hal/fmn.c standard
mips/nlm/xlp_machdep.c standard
mips/nlm/intr_machdep.c standard
mips/nlm/tick.c standard
-mips/nlm/iodi.c standard
mips/nlm/board.c standard
mips/nlm/cms.c standard
-mips/nlm/bus_space_rmi.c standard
+mips/nlm/bus_space_rmi.c standard
+mips/nlm/bus_space_rmi_pci.c standard
mips/nlm/mpreset.S standard
-mips/nlm/uart_bus_xlp_iodi.c optional uart
-mips/nlm/uart_cpu_mips_xlp.c optional uart
+mips/nlm/xlp_pci.c optional pci
+mips/nlm/intern_dev.c optional pci
+mips/nlm/uart_pci_xlp.c optional uart
+mips/nlm/uart_cpu_xlp.c optional uart
+mips/nlm/usb_init.c optional usb
diff --git a/sys/mips/nlm/hal/bridge.h b/sys/mips/nlm/hal/bridge.h
index d91ccd6488624..543c3659421db 100644
--- a/sys/mips/nlm/hal/bridge.h
+++ b/sys/mips/nlm/hal/bridge.h
@@ -25,11 +25,12 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
+ * NETLOGIC_BSD
* $FreeBSD$
- * NETLOGIC_BSD */
+ */
-#ifndef __NLM_BRIDGE_H__
-#define __NLM_BRIDGE_H__
+#ifndef __NLM_HAL_BRIDGE_H__
+#define __NLM_HAL_BRIDGE_H__
/**
* @file_name mio.h
@@ -37,141 +38,147 @@
* @brief Basic definitions of XLP memory and io subsystem
*/
-/* BRIDGE specific registers */
-#define XLP_BRIDGE_MODE_REG 0x40
-#define XLP_BRIDGE_PCI_CFG_BASE_REG 0x41
-#define XLP_BRIDGE_PCI_CFG_LIMIT_REG 0x42
-#define XLP_BRIDGE_PCIE_CFG_BASE_REG 0x43
-#define XLP_BRIDGE_PCIE_CFG_LIMIT_REG 0x44
-#define XLP_BRIDGE_BUSNUM_BAR0_REG 0x45
-#define XLP_BRIDGE_BUSNUM_BAR1_REG 0x46
-#define XLP_BRIDGE_BUSNUM_BAR2_REG 0x47
-#define XLP_BRIDGE_BUSNUM_BAR3_REG 0x48
-#define XLP_BRIDGE_BUSNUM_BAR4_REG 0x49
-#define XLP_BRIDGE_BUSNUM_BAR5_REG 0x4a
-#define XLP_BRIDGE_BUSNUM_BAR6_REG 0x4b
-#define XLP_BRIDGE_FLASH_BAR0_REG 0x4c
-#define XLP_BRIDGE_FLASH_BAR1_REG 0x4d
-#define XLP_BRIDGE_FLASH_BAR2_REG 0x4e
-#define XLP_BRIDGE_FLASH_BAR3_REG 0x4f
-#define XLP_BRIDGE_FLASH_LIMIT0_REG 0x50
-#define XLP_BRIDGE_FLASH_LIMIT1_REG 0x51
-#define XLP_BRIDGE_FLASH_LIMIT2_REG 0x52
-#define XLP_BRIDGE_FLASH_LIMIT3_REG 0x53
+/*
+ * BRIDGE specific registers
+ *
+ * These registers start after the PCIe header, which has 0x40
+ * standard entries
+ */
+#define BRIDGE_MODE 0x00
+#define BRIDGE_PCI_CFG_BASE 0x01
+#define BRIDGE_PCI_CFG_LIMIT 0x02
+#define BRIDGE_PCIE_CFG_BASE 0x03
+#define BRIDGE_PCIE_CFG_LIMIT 0x04
+#define BRIDGE_BUSNUM_BAR0 0x05
+#define BRIDGE_BUSNUM_BAR1 0x06
+#define BRIDGE_BUSNUM_BAR2 0x07
+#define BRIDGE_BUSNUM_BAR3 0x08
+#define BRIDGE_BUSNUM_BAR4 0x09
+#define BRIDGE_BUSNUM_BAR5 0x0a
+#define BRIDGE_BUSNUM_BAR6 0x0b
+#define BRIDGE_FLASH_BAR0 0x0c
+#define BRIDGE_FLASH_BAR1 0x0d
+#define BRIDGE_FLASH_BAR2 0x0e
+#define BRIDGE_FLASH_BAR3 0x0f
+#define BRIDGE_FLASH_LIMIT0 0x10
+#define BRIDGE_FLASH_LIMIT1 0x11
+#define BRIDGE_FLASH_LIMIT2 0x12
+#define BRIDGE_FLASH_LIMIT3 0x13
-#define XLP_BRIDGE_DRAM_BAR_REG(i) (0x54 + (i))
-#define XLP_BRIDGE_DRAM_BAR0_REG 0x54
-#define XLP_BRIDGE_DRAM_BAR1_REG 0x55
-#define XLP_BRIDGE_DRAM_BAR2_REG 0x56
-#define XLP_BRIDGE_DRAM_BAR3_REG 0x57
-#define XLP_BRIDGE_DRAM_BAR4_REG 0x58
-#define XLP_BRIDGE_DRAM_BAR5_REG 0x59
-#define XLP_BRIDGE_DRAM_BAR6_REG 0x5a
-#define XLP_BRIDGE_DRAM_BAR7_REG 0x5b
+#define BRIDGE_DRAM_BAR(i) (0x14 + (i))
+#define BRIDGE_DRAM_BAR0 0x14
+#define BRIDGE_DRAM_BAR1 0x15
+#define BRIDGE_DRAM_BAR2 0x16
+#define BRIDGE_DRAM_BAR3 0x17
+#define BRIDGE_DRAM_BAR4 0x18
+#define BRIDGE_DRAM_BAR5 0x19
+#define BRIDGE_DRAM_BAR6 0x1a
+#define BRIDGE_DRAM_BAR7 0x1b
-#define XLP_BRIDGE_DRAM_LIMIT_REG(i) (0x5c + (i))
-#define XLP_BRIDGE_DRAM_LIMIT0_REG 0x5c
-#define XLP_BRIDGE_DRAM_LIMIT1_REG 0x5d
-#define XLP_BRIDGE_DRAM_LIMIT2_REG 0x5e
-#define XLP_BRIDGE_DRAM_LIMIT3_REG 0x5f
-#define XLP_BRIDGE_DRAM_LIMIT4_REG 0x60
-#define XLP_BRIDGE_DRAM_LIMIT5_REG 0x61
-#define XLP_BRIDGE_DRAM_LIMIT6_REG 0x62
-#define XLP_BRIDGE_DRAM_LIMIT7_REG 0x63
+#define BRIDGE_DRAM_LIMIT(i) (0x1c + (i))
+#define BRIDGE_DRAM_LIMIT0 0x1c
+#define BRIDGE_DRAM_LIMIT1 0x1d
+#define BRIDGE_DRAM_LIMIT2 0x1e
+#define BRIDGE_DRAM_LIMIT3 0x1f
+#define BRIDGE_DRAM_LIMIT4 0x20
+#define BRIDGE_DRAM_LIMIT5 0x21
+#define BRIDGE_DRAM_LIMIT6 0x22
+#define BRIDGE_DRAM_LIMIT7 0x23
-#define XLP_BRIDGE_DRAM_NODE_TRANSLN0_REG 0x64
-#define XLP_BRIDGE_DRAM_NODE_TRANSLN1_REG 0x65
-#define XLP_BRIDGE_DRAM_NODE_TRANSLN2_REG 0x66
-#define XLP_BRIDGE_DRAM_NODE_TRANSLN3_REG 0x67
-#define XLP_BRIDGE_DRAM_NODE_TRANSLN4_REG 0x68
-#define XLP_BRIDGE_DRAM_NODE_TRANSLN5_REG 0x69
-#define XLP_BRIDGE_DRAM_NODE_TRANSLN6_REG 0x6a
-#define XLP_BRIDGE_DRAM_NODE_TRANSLN7_REG 0x6b
-#define XLP_BRIDGE_DRAM_CHNL_TRANSLN0_REG 0x6c
-#define XLP_BRIDGE_DRAM_CHNL_TRANSLN1_REG 0x6d
-#define XLP_BRIDGE_DRAM_CHNL_TRANSLN2_REG 0x6e
-#define XLP_BRIDGE_DRAM_CHNL_TRANSLN3_REG 0x6f
-#define XLP_BRIDGE_DRAM_CHNL_TRANSLN4_REG 0x70
-#define XLP_BRIDGE_DRAM_CHNL_TRANSLN5_REG 0x71
-#define XLP_BRIDGE_DRAM_CHNL_TRANSLN6_REG 0x72
-#define XLP_BRIDGE_DRAM_CHNL_TRANSLN7_REG 0x73
-#define XLP_BRIDGE_PCIEMEM_BASE0_REG 0x74
-#define XLP_BRIDGE_PCIEMEM_BASE1_REG 0x75
-#define XLP_BRIDGE_PCIEMEM_BASE2_REG 0x76
-#define XLP_BRIDGE_PCIEMEM_BASE3_REG 0x77
-#define XLP_BRIDGE_PCIEMEM_LIMIT0_REG 0x78
-#define XLP_BRIDGE_PCIEMEM_LIMIT1_REG 0x79
-#define XLP_BRIDGE_PCIEMEM_LIMIT2_REG 0x7a
-#define XLP_BRIDGE_PCIEMEM_LIMIT3_REG 0x7b
-#define XLP_BRIDGE_PCIEIO_BASE0_REG 0x7c
-#define XLP_BRIDGE_PCIEIO_BASE1_REG 0x7d
-#define XLP_BRIDGE_PCIEIO_BASE2_REG 0x7e
-#define XLP_BRIDGE_PCIEIO_BASE3_REG 0x7f
-#define XLP_BRIDGE_PCIEIO_LIMIT0_REG 0x80
-#define XLP_BRIDGE_PCIEIO_LIMIT1_REG 0x81
-#define XLP_BRIDGE_PCIEIO_LIMIT2_REG 0x82
-#define XLP_BRIDGE_PCIEIO_LIMIT3_REG 0x83
-#define XLP_BRIDGE_PCIEMEM_BASE4_REG 0x84
-#define XLP_BRIDGE_PCIEMEM_BASE5_REG 0x85
-#define XLP_BRIDGE_PCIEMEM_BASE6_REG 0x86
-#define XLP_BRIDGE_PCIEMEM_LIMIT4_REG 0x87
-#define XLP_BRIDGE_PCIEMEM_LIMIT5_REG 0x88
-#define XLP_BRIDGE_PCIEMEM_LIMIT6_REG 0x89
-#define XLP_BRIDGE_PCIEIO_BASE4_REG 0x8a
-#define XLP_BRIDGE_PCIEIO_BASE5_REG 0x8b
-#define XLP_BRIDGE_PCIEIO_BASE6_REG 0x8c
-#define XLP_BRIDGE_PCIEIO_LIMIT4_REG 0x8d
-#define XLP_BRIDGE_PCIEIO_LIMIT5_REG 0x8e
-#define XLP_BRIDGE_PCIEIO_LIMIT6_REG 0x8f
-#define XLP_BRIDGE_NBU_EVENT_CNT_CTL_REG 0x90
-#define XLP_BRIDGE_EVNTCTR1_LOW_REG 0x91
-#define XLP_BRIDGE_EVNTCTR1_HI_REG 0x92
-#define XLP_BRIDGE_EVNT_CNT_CTL2_REG 0x93
-#define XLP_BRIDGE_EVNTCTR2_LOW_REG 0x94
-#define XLP_BRIDGE_EVNTCTR2_HI_REG 0x95
-#define XLP_BRIDGE_TRACEBUF_MATCH_REG0 0x96
-#define XLP_BRIDGE_TRACEBUF_MATCH_REG1 0x97
-#define XLP_BRIDGE_TRACEBUF_MATCH_LOW_REG 0x98
-#define XLP_BRIDGE_TRACEBUF_MATCH_HI_REG 0x99
-#define XLP_BRIDGE_TRACEBUF_CTRL_REG 0x9a
-#define XLP_BRIDGE_TRACEBUF_INIT_REG 0x9b
-#define XLP_BRIDGE_TRACEBUF_ACCESS_REG 0x9c
-#define XLP_BRIDGE_TRACEBUF_READ_DATA_REG0 0x9d
-#define XLP_BRIDGE_TRACEBUF_READ_DATA_REG1 0x9d
-#define XLP_BRIDGE_TRACEBUF_READ_DATA_REG2 0x9f
-#define XLP_BRIDGE_TRACEBUF_READ_DATA_REG3 0xa0
-#define XLP_BRIDGE_TRACEBUF_STATUS_REG 0xa1
-#define XLP_BRIDGE_ADDRESS_ERROR0_REG 0xa2
-#define XLP_BRIDGE_ADDRESS_ERROR1_REG 0xa3
-#define XLP_BRIDGE_ADDRESS_ERROR2_REG 0xa4
-#define XLP_BRIDGE_TAG_ECC_ADDR_ERROR0_REG 0xa5
-#define XLP_BRIDGE_TAG_ECC_ADDR_ERROR1_REG 0xa6
-#define XLP_BRIDGE_TAG_ECC_ADDR_ERROR2_REG 0xa7
-#define XLP_BRIDGE_LINE_FLUSH_REG0 0xa8
-#define XLP_BRIDGE_LINE_FLUSH_REG1 0xa9
-#define XLP_BRIDGE_NODE_ID_REG 0xaa
-#define XLP_BRIDGE_ERROR_INTERRUPT_EN_REG 0xab
-#define XLP_BRIDGE_PCIE0_WEIGHT_REG 0x300
-#define XLP_BRIDGE_PCIE1_WEIGHT_REG 0x301
-#define XLP_BRIDGE_PCIE2_WEIGHT_REG 0x302
-#define XLP_BRIDGE_PCIE3_WEIGHT_REG 0x303
-#define XLP_BRIDGE_USB_WEIGHT_REG 0x304
-#define XLP_BRIDGE_NET_WEIGHT_REG 0x305
-#define XLP_BRIDGE_POE_WEIGHT_REG 0x306
-#define XLP_BRIDGE_CMS_WEIGHT_REG 0x307
-#define XLP_BRIDGE_DMAENG_WEIGHT_REG 0x308
-#define XLP_BRIDGE_SEC_WEIGHT_REG 0x309
-#define XLP_BRIDGE_COMP_WEIGHT_REG 0x30a
-#define XLP_BRIDGE_GIO_WEIGHT_REG 0x30b
-#define XLP_BRIDGE_FLASH_WEIGHT_REG 0x30c
+#define BRIDGE_DRAM_NODE_TRANSLN0 0x24
+#define BRIDGE_DRAM_NODE_TRANSLN1 0x25
+#define BRIDGE_DRAM_NODE_TRANSLN2 0x26
+#define BRIDGE_DRAM_NODE_TRANSLN3 0x27
+#define BRIDGE_DRAM_NODE_TRANSLN4 0x28
+#define BRIDGE_DRAM_NODE_TRANSLN5 0x29
+#define BRIDGE_DRAM_NODE_TRANSLN6 0x2a
+#define BRIDGE_DRAM_NODE_TRANSLN7 0x2b
+#define BRIDGE_DRAM_CHNL_TRANSLN0 0x2c
+#define BRIDGE_DRAM_CHNL_TRANSLN1 0x2d
+#define BRIDGE_DRAM_CHNL_TRANSLN2 0x2e
+#define BRIDGE_DRAM_CHNL_TRANSLN3 0x2f
+#define BRIDGE_DRAM_CHNL_TRANSLN4 0x30
+#define BRIDGE_DRAM_CHNL_TRANSLN5 0x31
+#define BRIDGE_DRAM_CHNL_TRANSLN6 0x32
+#define BRIDGE_DRAM_CHNL_TRANSLN7 0x33
+#define BRIDGE_PCIEMEM_BASE0 0x34
+#define BRIDGE_PCIEMEM_BASE1 0x35
+#define BRIDGE_PCIEMEM_BASE2 0x36
+#define BRIDGE_PCIEMEM_BASE3 0x37
+#define BRIDGE_PCIEMEM_LIMIT0 0x38
+#define BRIDGE_PCIEMEM_LIMIT1 0x39
+#define BRIDGE_PCIEMEM_LIMIT2 0x3a
+#define BRIDGE_PCIEMEM_LIMIT3 0x3b
+#define BRIDGE_PCIEIO_BASE0 0x3c
+#define BRIDGE_PCIEIO_BASE1 0x3d
+#define BRIDGE_PCIEIO_BASE2 0x3e
+#define BRIDGE_PCIEIO_BASE3 0x3f
+#define BRIDGE_PCIEIO_LIMIT0 0x40
+#define BRIDGE_PCIEIO_LIMIT1 0x41
+#define BRIDGE_PCIEIO_LIMIT2 0x42
+#define BRIDGE_PCIEIO_LIMIT3 0x43
+#define BRIDGE_PCIEMEM_BASE4 0x44
+#define BRIDGE_PCIEMEM_BASE5 0x45
+#define BRIDGE_PCIEMEM_BASE6 0x46
+#define BRIDGE_PCIEMEM_LIMIT4 0x47
+#define BRIDGE_PCIEMEM_LIMIT5 0x48
+#define BRIDGE_PCIEMEM_LIMIT6 0x49
+#define BRIDGE_PCIEIO_BASE4 0x4a
+#define BRIDGE_PCIEIO_BASE5 0x4b
+#define BRIDGE_PCIEIO_BASE6 0x4c
+#define BRIDGE_PCIEIO_LIMIT4 0x4d
+#define BRIDGE_PCIEIO_LIMIT5 0x4e
+#define BRIDGE_PCIEIO_LIMIT6 0x4f
+#define BRIDGE_NBU_EVENT_CNT_CTL 0x50
+#define BRIDGE_EVNTCTR1_LOW 0x51
+#define BRIDGE_EVNTCTR1_HI 0x52
+#define BRIDGE_EVNT_CNT_CTL2 0x53
+#define BRIDGE_EVNTCTR2_LOW 0x54
+#define BRIDGE_EVNTCTR2_HI 0x55
+#define BRIDGE_TRACEBUF_MATCH0 0x56
+#define BRIDGE_TRACEBUF_MATCH1 0x57
+#define BRIDGE_TRACEBUF_MATCH_LOW 0x58
+#define BRIDGE_TRACEBUF_MATCH_HI 0x59
+#define BRIDGE_TRACEBUF_CTRL 0x5a
+#define BRIDGE_TRACEBUF_INIT 0x5b
+#define BRIDGE_TRACEBUF_ACCESS 0x5c
+#define BRIDGE_TRACEBUF_READ_DATA0 0x5d
+#define BRIDGE_TRACEBUF_READ_DATA1 0x5d
+#define BRIDGE_TRACEBUF_READ_DATA2 0x5f
+#define BRIDGE_TRACEBUF_READ_DATA3 0x60
+#define BRIDGE_TRACEBUF_STATUS 0x61
+#define BRIDGE_ADDRESS_ERROR0 0x62
+#define BRIDGE_ADDRESS_ERROR1 0x63
+#define BRIDGE_ADDRESS_ERROR2 0x64
+#define BRIDGE_TAG_ECC_ADDR_ERROR0 0x65
+#define BRIDGE_TAG_ECC_ADDR_ERROR1 0x66
+#define BRIDGE_TAG_ECC_ADDR_ERROR2 0x67
+#define BRIDGE_LINE_FLUSH0 0x68
+#define BRIDGE_LINE_FLUSH1 0x69
+#define BRIDGE_NODE_ID 0x6a
+#define BRIDGE_ERROR_INTERRUPT_EN 0x6b
+#define BRIDGE_PCIE0_WEIGHT 0x2c0
+#define BRIDGE_PCIE1_WEIGHT 0x2c1
+#define BRIDGE_PCIE2_WEIGHT 0x2c2
+#define BRIDGE_PCIE3_WEIGHT 0x2c3
+#define BRIDGE_USB_WEIGHT 0x2c4
+#define BRIDGE_NET_WEIGHT 0x2c5
+#define BRIDGE_POE_WEIGHT 0x2c6
+#define BRIDGE_CMS_WEIGHT 0x2c7
+#define BRIDGE_DMAENG_WEIGHT 0x2c8
+#define BRIDGE_SEC_WEIGHT 0x2c9
+#define BRIDGE_COMP_WEIGHT 0x2ca
+#define BRIDGE_GIO_WEIGHT 0x2cb
+#define BRIDGE_FLASH_WEIGHT 0x2cc
#if !defined(LOCORE) && !defined(__ASSEMBLY__)
-#define nlm_rdreg_bridge(b, r) nlm_read_reg_kseg(b, r)
-#define nlm_wreg_bridge(b, r, v) nlm_write_reg_kseg(b, r, v)
-#define nlm_pcibase_bridge(node) nlm_pcicfg_base(XLP_IO_BRIDGE_OFFSET(node))
-#define nlm_regbase_bridge(node) nlm_pcibase_bridge(node)
+#define nlm_read_bridge_reg(b, r) nlm_read_reg(b, r)
+#define nlm_write_bridge_reg(b, r, v) nlm_write_reg(b, r, v)
+#define nlm_get_bridge_pcibase(node) \
+ nlm_pcicfg_base(XLP_IO_BRIDGE_OFFSET(node))
+#define nlm_get_bridge_regbase(node) \
+ (nlm_get_bridge_pcibase(node) + XLP_IO_PCI_HDRSZ)
#endif
-
#endif
diff --git a/sys/mips/nlm/hal/cop0.h b/sys/mips/nlm/hal/cop0.h
deleted file mode 100644
index 18ecc97dfe90b..0000000000000
--- a/sys/mips/nlm/hal/cop0.h
+++ /dev/null
@@ -1,280 +0,0 @@
-/*-
- * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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$
- * NETLOGIC_BSD */
-
-#ifndef __NLM_COP0_H__
-#define __NLM_COP0_H__
-
-#define NLM_C0_INDEX 0
-#define NLM_C0_RANDOM 1
-#define NLM_C0_ENTRYLO0 2
-#define NLM_C0_ENTRYLO1 3
-#define NLM_C0_CONTEXT 4
-#define NLM_C0_USERLOCAL 4
-#define NLM_C0_PAGEMASK 5
-#define NLM_C0_WIRED 6
-#define NLM_C0_BADVADDR 8
-#define NLM_C0_COUNT 9
-#define NLM_C0_EIRR 9
-#define NLM_C0_EIMR 9
-#define NLM_C0_ENTRYHI 10
-#define NLM_C0_COMPARE 11
-#define NLM_C0_STATUS 12
-#define NLM_C0_INTCTL 12
-#define NLM_C0_SRSCTL 12
-#define NLM_C0_CAUSE 13
-#define NLM_C0_EPC 14
-#define NLM_C0_PRID 15
-#define NLM_C0_EBASE 15
-#define NLM_C0_CONFIG 16
-#define NLM_C0_CONFIG0 16
-#define NLM_C0_CONFIG1 16
-#define NLM_C0_CONFIG2 16
-#define NLM_C0_CONFIG3 16
-#define NLM_C0_CONFIG4 16
-#define NLM_C0_CONFIG5 16
-#define NLM_C0_CONFIG6 16
-#define NLM_C0_CONFIG7 16
-#define NLM_C0_WATCHLO 18
-#define NLM_C0_WATCHHI 19
-#define NLM_C0_XCONTEXT 20
-#define NLM_C0_SCRATCH 22
-#define NLM_C0_SCRATCH0 22
-#define NLM_C0_SCRATCH1 22
-#define NLM_C0_SCRATCH2 22
-#define NLM_C0_SCRATCH3 22
-#define NLM_C0_SCRATCH4 22
-#define NLM_C0_SCRATCH5 22
-#define NLM_C0_SCRATCH6 22
-#define NLM_C0_SCRATCH7 22
-#define NLM_C0_DEBUG 23
-#define NLM_C0_DEPC 24
-#define NLM_C0_PERFCNT 25
-#define NLM_C0_PERFCNT0 25
-#define NLM_C0_PERFCNT1 25
-#define NLM_C0_TAGLO 28
-#define NLM_C0_DATALO 28
-#define NLM_C0_TAGHI 29
-#define NLM_C0_DATAHI 29
-#define NLM_C0_ERROREPC 30
-#define NLM_C0_DESAVE 31
-
-/* cop0 status bits */
-#define NLM_STATUS_CP0_EN (1<<28)
-#define NLM_STATUS_CP1_EN (1<<29)
-#define NLM_STATUS_CP2_EN (1<<30)
-#define NLM_STATUS_KX_EN (1<<7)
-#define NLM_STATUS_UX_EN (1<<5)
-
-#ifndef LOCORE
-
-#define nlm_memory_barrier() \
- __asm__ __volatile__( \
- ".set push\n\t" \
- ".set noreorder\n\t" \
- " sync\n\t" \
- ".set pop" \
- ::: "memory")
-
-#define NLM_DEFINE_ACCESSORS32(name, reg, sel) \
-static __inline__ uint32_t nlm_read_c0_##name(void) \
-{ \
- uint32_t __rv; \
- __asm__ __volatile__ ( \
- ".set push\n" \
- ".set noreorder\n" \
- ".set mips64\n" \
- "mfc0 %0, $%1, %2\n" \
- ".set pop\n" \
- : "=r" (__rv) \
- : "i" (reg), "i" (sel) \
- ); \
- return __rv; \
-} \
- \
-static __inline__ void nlm_write_c0_##name(uint32_t val) \
-{ \
- __asm__ __volatile__( \
- ".set push\n" \
- ".set noreorder\n" \
- ".set mips64\n" \
- "mtc0 %0, $%1, %2\n" \
- ".set pop\n" \
- :: "r" (val), "i" (reg), "i" (sel) \
- ); \
-} struct __hack
-
-/* struct __hack above swallows a semicolon - otherwise the macro
- * usage below cannot have the terminating semicolon */
-#if (__mips == 64)
-#define NLM_DEFINE_ACCESSORS64(name, reg, sel) \
-static __inline__ uint64_t nlm_read_c0_##name(void) \
-{ \
- uint64_t __rv; \
- __asm__ __volatile__ ( \
- ".set push\n" \
- ".set noreorder\n" \
- ".set mips64\n" \
- "dmfc0 %0,$%1,%2\n" \
- ".set pop\n" \
- : "=r" (__rv) \
- : "i" (reg), "i" (sel) ); \
- return __rv; \
-} \
- \
-static __inline__ void nlm_write_c0_##name(uint64_t val) \
-{ \
- __asm__ __volatile__ ( \
- ".set push\n" \
- ".set noreorder\n" \
- ".set mips64\n" \
- "dmtc0 %0,$%1,%2\n" \
- ".set pop\n" \
- :: "r" (val), "i" (reg), "i" (sel) ); \
-} struct __hack
-
-#else
-
-#define NLM_DEFINE_ACCESSORS64(name, reg, sel) \
-static __inline__ uint64_t nlm_read_c0_##name(void) \
-{ \
- uint32_t __high, __low; \
- __asm__ __volatile__ ( \
- ".set push\n" \
- ".set noreorder\n" \
- ".set mips64\n" \
- "dmfc0 $8, $%2, %3\n" \
- "dsra32 %0, $8, 0\n" \
- "sll %1, $8, 0\n" \
- ".set pop\n" \
- : "=r"(__high), "=r"(__low) \
- : "i"(reg), "i"(sel) \
- : "$8" ); \
- \
- return (((uint64_t)__high << 32) | __low); \
-} \
- \
-static __inline__ void nlm_write_c0_##name(uint64_t val) \
-{ \
- uint32_t __high = val >> 32; \
- uint32_t __low = val & 0xffffffff; \
- __asm__ __volatile__ ( \
- ".set push\n" \
- ".set noreorder\n" \
- ".set mips64\n" \
- "dsll32 $8, %1, 0\n" \
- "dsll32 $9, %0, 0\n" \
- "dsrl32 $8, $8, 0\n" \
- "or $8, $8, $9\n" \
- "dmtc0 $8, $%2, %3\n" \
- ".set pop\n" \
- :: "r"(__high), "r"(__low), "i"(reg), "i"(sel) \
- : "$8", "$9"); \
-} struct __hack
-
-#endif
-
-NLM_DEFINE_ACCESSORS32(index, 0, 0);
-NLM_DEFINE_ACCESSORS32(random, 1, 0);
-NLM_DEFINE_ACCESSORS64(entrylo0, 2, 0);
-NLM_DEFINE_ACCESSORS64(entrylo1, 3, 0);
-NLM_DEFINE_ACCESSORS64(context, 4, 0);
-NLM_DEFINE_ACCESSORS64(userlocal, 4, 0);
-NLM_DEFINE_ACCESSORS32(pagemask, 5, 0);
-NLM_DEFINE_ACCESSORS32(wired, 6, 0);
-NLM_DEFINE_ACCESSORS64(badvaddr, 8, 0);
-NLM_DEFINE_ACCESSORS32(count, 9, 0);
-NLM_DEFINE_ACCESSORS64(eirr, 9, 6);
-NLM_DEFINE_ACCESSORS64(eimr, 9, 7);
-NLM_DEFINE_ACCESSORS64(entryhi, 10, 0);
-NLM_DEFINE_ACCESSORS32(compare, 11, 0);
-NLM_DEFINE_ACCESSORS32(status, 12, 0);
-NLM_DEFINE_ACCESSORS32(intctl, 12, 1);
-NLM_DEFINE_ACCESSORS32(srsctl, 12, 2);
-NLM_DEFINE_ACCESSORS32(cause, 13, 0);
-NLM_DEFINE_ACCESSORS64(epc, 14, 0);
-NLM_DEFINE_ACCESSORS32(prid, 15, 0);
-NLM_DEFINE_ACCESSORS32(ebase, 15, 1);
-NLM_DEFINE_ACCESSORS32(config0, 16, 0);
-NLM_DEFINE_ACCESSORS32(config1, 16, 1);
-NLM_DEFINE_ACCESSORS32(config2, 16, 2);
-NLM_DEFINE_ACCESSORS32(config3, 16, 3);
-NLM_DEFINE_ACCESSORS32(config6, 16, 6);
-NLM_DEFINE_ACCESSORS32(config7, 16, 7);
-NLM_DEFINE_ACCESSORS64(watchlo0, 18, 0);
-NLM_DEFINE_ACCESSORS32(watchhi0, 19, 0);
-NLM_DEFINE_ACCESSORS64(xcontext, 20, 0);
-NLM_DEFINE_ACCESSORS64(scratch0, 22, 0);
-NLM_DEFINE_ACCESSORS64(scratch1, 22, 1);
-NLM_DEFINE_ACCESSORS64(scratch2, 22, 2);
-NLM_DEFINE_ACCESSORS64(scratch3, 22, 3);
-NLM_DEFINE_ACCESSORS64(scratch4, 22, 4);
-NLM_DEFINE_ACCESSORS64(scratch5, 22, 5);
-NLM_DEFINE_ACCESSORS64(scratch6, 22, 6);
-NLM_DEFINE_ACCESSORS64(scratch7, 22, 7);
-NLM_DEFINE_ACCESSORS32(debug, 23, 0);
-NLM_DEFINE_ACCESSORS32(depc, 24, 0);
-NLM_DEFINE_ACCESSORS32(perfctrl0, 25, 0);
-NLM_DEFINE_ACCESSORS64(perfcntr0, 25, 1);
-NLM_DEFINE_ACCESSORS32(perfctrl1, 25, 2);
-NLM_DEFINE_ACCESSORS64(perfcntr1, 25, 3);
-NLM_DEFINE_ACCESSORS32(perfctrl2, 25, 4);
-NLM_DEFINE_ACCESSORS64(perfcntr2, 25, 5);
-NLM_DEFINE_ACCESSORS32(perfctrl3, 25, 6);
-NLM_DEFINE_ACCESSORS64(perfcntr3, 25, 7);
-NLM_DEFINE_ACCESSORS64(taglo0, 28, 0);
-NLM_DEFINE_ACCESSORS64(taglo2, 28, 2);
-NLM_DEFINE_ACCESSORS64(taghi0, 29, 0);
-NLM_DEFINE_ACCESSORS64(taghi2, 29, 2);
-NLM_DEFINE_ACCESSORS64(errorepc, 30, 0);
-NLM_DEFINE_ACCESSORS64(desave, 31, 0);
-
-static __inline__ int nlm_nodeid(void)
-{
- return (nlm_read_c0_ebase() >> 5) & 0x3;
-}
-
-static __inline__ int nlm_cpuid(void)
-{
- return nlm_read_c0_ebase() & 0x1f;
-}
-
-static __inline__ int nlm_threadid(void)
-{
- return nlm_read_c0_ebase() & 0x3;
-}
-
-static __inline__ int nlm_coreid(void)
-{
- return (nlm_read_c0_ebase() >> 2) & 0x7;
-}
-
-#endif
-
-#endif
diff --git a/sys/mips/nlm/hal/cop2.h b/sys/mips/nlm/hal/cop2.h
index 062cd9df44ab5..6b79d3fd68f5c 100644
--- a/sys/mips/nlm/hal/cop2.h
+++ b/sys/mips/nlm/hal/cop2.h
@@ -25,27 +25,28 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
+ * NETLOGIC_BSD
* $FreeBSD$
- * NETLOGIC_BSD */
+ */
-#ifndef __NLM_COP2_H__
-#define __NLM_COP2_H__
+#ifndef __NLM_HAL_COP2_H__
+#define __NLM_HAL_COP2_H__
-#define XLP_COP2_TX_BUF_REG 0
-#define XLP_COP2_RX_BUF_REG 1
-#define XLP_COP2_TXMSGSTATUS_REG 2
-#define XLP_COP2_RXMSGSTATUS_REG 3
-#define XLP_COP2_MSGSTATUS1_REG 4
-#define XLP_COP2_MSGCONFIG_REG 5
-#define XLP_COP2_MSGCONFIG1_REG 6
+#define COP2_TX_BUF 0
+#define COP2_RX_BUF 1
+#define COP2_TXMSGSTATUS 2
+#define COP2_RXMSGSTATUS 3
+#define COP2_MSGSTATUS1 4
+#define COP2_MSGCONFIG 5
+#define COP2_MSGCONFIG1 6
-#define CROSSTHR_POPQ_EN 0x01
-#define VC0_POPQ_EN 0x02
-#define VC1_POPQ_EN 0x04
-#define VC2_POPQ_EN 0x08
-#define VC3_POPQ_EN 0x10
-#define ALL_VC_POPQ_EN 0x1E
-#define ALL_VC_CT_POPQ_EN 0x1F
+#define CROSSTHR_POPQ_EN 0x01
+#define VC0_POPQ_EN 0x02
+#define VC1_POPQ_EN 0x04
+#define VC2_POPQ_EN 0x08
+#define VC3_POPQ_EN 0x10
+#define ALL_VC_POPQ_EN 0x1E
+#define ALL_VC_CT_POPQ_EN 0x1F
struct nlm_fmn_msg {
uint64_t msg[4];
@@ -62,8 +63,7 @@ static inline uint32_t nlm_read_c2_##name(void) \
"mfc2 %0, $%1, %2\n" \
".set pop\n" \
: "=r" (__rv) \
- : "i" (reg), "i" (sel) \
- ); \
+ : "i" (reg), "i" (sel)); \
return __rv; \
} \
\
@@ -75,8 +75,7 @@ static inline void nlm_write_c2_##name(uint32_t val) \
".set mips64\n" \
"mtc2 %0, $%1, %2\n" \
".set pop\n" \
- :: "r" (val), "i" (reg), "i" (sel) \
- ); \
+ : : "r" (val), "i" (reg), "i" (sel)); \
} struct __hack
#if (__mips == 64)
@@ -91,7 +90,7 @@ static inline uint64_t nlm_read_c2_##name(void) \
"dmfc2 %0, $%1, %2\n" \
".set pop\n" \
: "=r" (__rv) \
- : "i" (reg), "i" (sel) ); \
+ : "i" (reg), "i" (sel)); \
return __rv; \
} \
\
@@ -103,7 +102,7 @@ static inline void nlm_write_c2_##name(uint64_t val) \
".set mips64\n" \
"dmtc2 %0, $%1, %2\n" \
".set pop\n" \
- :: "r" (val), "i" (reg), "i" (sel) ); \
+ : : "r" (val), "i" (reg), "i" (sel)); \
} struct __hack
#else
@@ -122,15 +121,15 @@ static inline uint64_t nlm_read_c2_##name(void) \
".set pop\n" \
: "=r"(__high), "=r"(__low) \
: "i"(reg), "i"(sel) \
- : "$8" ); \
+ : "$8"); \
\
- return (((uint64_t)__high << 32) | __low); \
+ return ((uint64_t)__high << 32) | __low; \
} \
\
static inline void nlm_write_c2_##name(uint64_t val) \
{ \
- uint32_t __high = val >> 32; \
- uint32_t __low = val & 0xffffffff; \
+ uint32_t __high = val >> 32; \
+ uint32_t __low = val & 0xffffffff; \
__asm__ __volatile__ ( \
".set push\n" \
".set noreorder\n" \
@@ -141,113 +140,100 @@ static inline void nlm_write_c2_##name(uint64_t val) \
"or $8, $8, $9\n" \
"dmtc2 $8, $%2, %3\n" \
".set pop\n" \
- :: "r"(__high), "r"(__low), "i"(reg), "i"(sel) \
- :"$8", "$9"); \
+ : : "r"(__high), "r"(__low), "i"(reg), "i"(sel) \
+ : "$8", "$9"); \
} struct __hack
#endif
-NLM_DEFINE_COP2_ACCESSORS64(txbuf0, XLP_COP2_TX_BUF_REG, 0);
-NLM_DEFINE_COP2_ACCESSORS64(txbuf1, XLP_COP2_TX_BUF_REG, 1);
-NLM_DEFINE_COP2_ACCESSORS64(txbuf2, XLP_COP2_TX_BUF_REG, 2);
-NLM_DEFINE_COP2_ACCESSORS64(txbuf3, XLP_COP2_TX_BUF_REG, 3);
+NLM_DEFINE_COP2_ACCESSORS64(txbuf0, COP2_TX_BUF, 0);
+NLM_DEFINE_COP2_ACCESSORS64(txbuf1, COP2_TX_BUF, 1);
+NLM_DEFINE_COP2_ACCESSORS64(txbuf2, COP2_TX_BUF, 2);
+NLM_DEFINE_COP2_ACCESSORS64(txbuf3, COP2_TX_BUF, 3);
-NLM_DEFINE_COP2_ACCESSORS64(rxbuf0, XLP_COP2_RX_BUF_REG, 0);
-NLM_DEFINE_COP2_ACCESSORS64(rxbuf1, XLP_COP2_RX_BUF_REG, 1);
-NLM_DEFINE_COP2_ACCESSORS64(rxbuf2, XLP_COP2_RX_BUF_REG, 2);
-NLM_DEFINE_COP2_ACCESSORS64(rxbuf3, XLP_COP2_RX_BUF_REG, 3);
+NLM_DEFINE_COP2_ACCESSORS64(rxbuf0, COP2_RX_BUF, 0);
+NLM_DEFINE_COP2_ACCESSORS64(rxbuf1, COP2_RX_BUF, 1);
+NLM_DEFINE_COP2_ACCESSORS64(rxbuf2, COP2_RX_BUF, 2);
+NLM_DEFINE_COP2_ACCESSORS64(rxbuf3, COP2_RX_BUF, 3);
-NLM_DEFINE_COP2_ACCESSORS32(txmsgstatus, XLP_COP2_TXMSGSTATUS_REG, 0);
-NLM_DEFINE_COP2_ACCESSORS32(rxmsgstatus, XLP_COP2_RXMSGSTATUS_REG, 0);
-NLM_DEFINE_COP2_ACCESSORS32(msgstatus1, XLP_COP2_MSGSTATUS1_REG, 0);
-NLM_DEFINE_COP2_ACCESSORS32(msgconfig, XLP_COP2_MSGCONFIG_REG, 0);
-NLM_DEFINE_COP2_ACCESSORS32(msgconfig1, XLP_COP2_MSGCONFIG1_REG, 0);
+NLM_DEFINE_COP2_ACCESSORS32(txmsgstatus, COP2_TXMSGSTATUS, 0);
+NLM_DEFINE_COP2_ACCESSORS32(rxmsgstatus, COP2_RXMSGSTATUS, 0);
+NLM_DEFINE_COP2_ACCESSORS32(msgstatus1, COP2_MSGSTATUS1, 0);
+NLM_DEFINE_COP2_ACCESSORS32(msgconfig, COP2_MSGCONFIG, 0);
+NLM_DEFINE_COP2_ACCESSORS32(msgconfig1, COP2_MSGCONFIG1, 0);
/* successful completion returns 1, else 0 */
-static __inline__ int nlm_msgsend(int val)
+static inline int
+nlm_msgsend(int val)
{
int result;
__asm__ volatile (
- ".set push \n"
- ".set noreorder \n"
- ".set mips64 \n"
- "move $8, %1 \n"
- "sync \n"
- "/* msgsnds $9, $8 */ \n"
- ".word 0x4a084801 \n"
- "move %0, $9 \n"
- ".set pop \n"
+ ".set push\n"
+ ".set noreorder\n"
+ ".set mips64\n"
+ "move $8, %1\n"
+ "sync\n"
+ "/* msgsnds $9, $8 */\n"
+ ".word 0x4a084801\n"
+ "move %0, $9\n"
+ ".set pop\n"
: "=r" (result)
: "r" (val)
- : "$8", "$9"
- );
+ : "$8", "$9");
return result;
}
-static __inline__ int nlm_msgld(int vc)
+static inline int
+nlm_msgld(int vc)
{
int val;
__asm__ volatile (
- ".set push \n"
- ".set noreorder \n"
- ".set mips64 \n"
- "move $8, %1 \n"
- "/* msgld $9, $8 */ \n"
- ".word 0x4a084802 \n"
- "move %0, $9 \n"
- ".set pop \n"
+ ".set push\n"
+ ".set noreorder\n"
+ ".set mips64\n"
+ "move $8, %1\n"
+ "/* msgld $9, $8 */\n"
+ ".word 0x4a084802\n"
+ "move %0, $9\n"
+ ".set pop\n"
: "=r" (val)
: "r" (vc)
- : "$8", "$9"
- );
+ : "$8", "$9");
return val;
}
-static __inline__ void nlm_msgwait(int vc)
+static inline void
+nlm_msgwait(int vc)
{
__asm__ volatile (
- ".set push \n"
- ".set noreorder \n"
- ".set mips64 \n"
- "move $8, %0 \n"
- "/* msgwait $8 */ \n"
- ".word 0x4a080003 \n"
- ".set pop \n"
- :: "r" (vc)
- : "$8"
- );
-}
-
-/* TODO this is not needed in n32 and n64 */
-static __inline uint32_t
-nlm_fmn_saveflags(void)
-{
- uint32_t sr = mips_rd_status();
-
- mips_wr_status((sr & ~MIPS_SR_INT_IE) | MIPS_SR_COP_2_BIT);
- return (sr);
-}
-
-static __inline void
-nlm_fmn_restoreflags(uint32_t sr)
-{
-
- mips_wr_status(sr);
+ ".set push\n"
+ ".set noreorder\n"
+ ".set mips64\n"
+ "move $8, %0\n"
+ "/* msgwait $8 */\n"
+ ".word 0x4a080003\n"
+ ".set pop\n"
+ : : "r" (vc)
+ : "$8");
}
-static __inline__ int nlm_fmn_msgsend(int dstid, int size, int swcode,
- struct nlm_fmn_msg *m)
+static inline int
+nlm_fmn_msgsend(int dstid, int size, int swcode, struct nlm_fmn_msg *m)
{
uint32_t flags, status;
int rv;
size -= 1;
- flags = nlm_fmn_saveflags();
- switch(size) {
- case 3: nlm_write_c2_txbuf3(m->msg[3]);
- case 2: nlm_write_c2_txbuf2(m->msg[2]);
- case 1: nlm_write_c2_txbuf1(m->msg[1]);
- case 0: nlm_write_c2_txbuf0(m->msg[0]);
+ flags = nlm_save_flags_cop2();
+ switch (size) {
+ case 3:
+ nlm_write_c2_txbuf3(m->msg[3]);
+ case 2:
+ nlm_write_c2_txbuf2(m->msg[2]);
+ case 1:
+ nlm_write_c2_txbuf1(m->msg[1]);
+ case 0:
+ nlm_write_c2_txbuf0(m->msg[0]);
}
dstid |= ((swcode << 24) | (size << 16));
@@ -255,19 +241,19 @@ static __inline__ int nlm_fmn_msgsend(int dstid, int size, int swcode,
rv = !status;
if (rv != 0)
rv = nlm_read_c2_txmsgstatus();
- nlm_fmn_restoreflags(flags);
+ nlm_restore_flags(flags);
- return (rv);
+ return rv;
}
-static __inline__ int nlm_fmn_msgrcv(int vc, int *srcid, int *size, int *code,
- struct nlm_fmn_msg *m)
+static inline int
+nlm_fmn_msgrcv(int vc, int *srcid, int *size, int *code, struct nlm_fmn_msg *m)
{
uint32_t status;
uint32_t msg_status, flags;
int tmp_sz, rv;
- flags = nlm_fmn_saveflags();
+ flags = nlm_save_flags_cop2();
status = nlm_msgld(vc); /* will return 0, if error */
rv = !status;
if (rv == 0) {
@@ -276,38 +262,24 @@ static __inline__ int nlm_fmn_msgrcv(int vc, int *srcid, int *size, int *code,
*code = (msg_status >> 18) & 0xff;
*srcid = (msg_status >> 4) & 0xfff;
tmp_sz = *size - 1;
- switch(tmp_sz) {
- case 3: m->msg[3] = nlm_read_c2_rxbuf3();
- case 2: m->msg[2] = nlm_read_c2_rxbuf2();
- case 1: m->msg[1] = nlm_read_c2_rxbuf1();
- case 0: m->msg[0] = nlm_read_c2_rxbuf0();
+ switch (tmp_sz) {
+ case 3:
+ m->msg[3] = nlm_read_c2_rxbuf3();
+ case 2:
+ m->msg[2] = nlm_read_c2_rxbuf2();
+ case 1:
+ m->msg[1] = nlm_read_c2_rxbuf1();
+ case 0:
+ m->msg[0] = nlm_read_c2_rxbuf0();
}
}
- nlm_fmn_restoreflags(flags);
+ nlm_restore_flags(flags);
return rv;
}
-/**
- * nlm_fmn_cpu_init() initializes the per-h/w thread cop2 w.r.t the following
- * configuration parameters. It needs to be individually setup on each
- * hardware thread.
- *
- * int_vec - interrupt vector getting placed into msgconfig reg
- * ctpe - cross thread message pop enable. When set to 1, the thread (h/w cpu)
- * associated where this cop2 register is setup, can pop messages
- * intended for any other thread in the same core.
- * v0pe - VC0 pop message request mode enable. When set to 1, the thread
- * can send pop requests to vc0.
- * v1pe - VC1 pop message request mode enable. When set to 1, the thread
- * can send pop requests to vc1.
- * v2pe - VC2 pop message request mode enable. When set to 1, the thread
- * can send pop requests to vc2.
- * v3pe - VC3 pop message request mode enable. When set to 1, the thread
- * can send pop requests to vc3.
- */
-static __inline__ void nlm_fmn_cpu_init(int int_vec, int ctpe, int v0pe,
- int v1pe, int v2pe, int v3pe)
+static inline void
+nlm_fmn_cpu_init(int int_vec, int ctpe, int v0pe, int v1pe, int v2pe, int v3pe)
{
uint32_t val = nlm_read_c2_msgconfig();
diff --git a/sys/mips/nlm/hal/cpucontrol.h b/sys/mips/nlm/hal/cpucontrol.h
index 0bc0f5be7bbb2..715cd535f5d6e 100644
--- a/sys/mips/nlm/hal/cpucontrol.h
+++ b/sys/mips/nlm/hal/cpucontrol.h
@@ -25,46 +25,168 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
+ * NETLOGIC_BSD
* $FreeBSD$
- * NETLOGIC_BSD */
+ */
-#ifndef __NLM_CPUCONTROL_H__
-#define __NLM_CPUCONTROL_H__
+#ifndef __NLM_HAL_CPUCONTROL_H__
+#define __NLM_HAL_CPUCONTROL_H__
-#define XLP_CPU_BLOCKID_IFU 0
-#define XLP_CPU_BLOCKID_ICU 1
+#define CPU_BLOCKID_IFU 0
+#define CPU_BLOCKID_ICU 1
+#define CPU_BLOCKID_IEU 2
+#define CPU_BLOCKID_LSU 3
+#define CPU_BLOCKID_MMU 4
+#define CPU_BLOCKID_PRF 5
+#define CPU_BLOCKID_SCH 7
+#define CPU_BLOCKID_SCU 8
+#define CPU_BLOCKID_FPU 9
+#define CPU_BLOCKID_MAP 10
-#define XLP_CPU_BLOCKID_IEU 2
-#define XLP_CPU_BLOCKID_LSU 3
-#define XLP_LSU_DEFEATURE 0x304
-#define XLP_LSU_CERRLOG_REGID 0x09
+#define LSU_DEFEATURE 0x304
+#define LSU_CERRLOG_REGID 0x09
+#define SCHED_DEFEATURE 0x700
-#define XLP_CPU_BLOCKID_MMU 4
-#define XLP_CPU_BLOCKID_PRF 5
+/* Offsets of interest from the 'MAP' Block */
+#define MAP_THREADMODE 0x00
+#define MAP_EXT_EBASE_ENABLE 0x04
+#define MAP_CCDI_CONFIG 0x08
+#define MAP_THRD0_CCDI_STATUS 0x0c
+#define MAP_THRD1_CCDI_STATUS 0x10
+#define MAP_THRD2_CCDI_STATUS 0x14
+#define MAP_THRD3_CCDI_STATUS 0x18
+#define MAP_THRD0_DEBUG_MODE 0x1c
+#define MAP_THRD1_DEBUG_MODE 0x20
+#define MAP_THRD2_DEBUG_MODE 0x24
+#define MAP_THRD3_DEBUG_MODE 0x28
+#define MAP_MISC_STATE 0x60
+#define MAP_DEBUG_READ_CTL 0x64
+#define MAP_DEBUG_READ_REG0 0x68
+#define MAP_DEBUG_READ_REG1 0x6c
-#define XLP_CPU_BLOCKID_SCH 7
-#define XLP_SCHED_DEFEATURE 0x700
+#define MMU_SETUP 0x400
+#define MMU_LFSRSEED 0x401
+#define MMU_HPW_NUM_PAGE_LVL 0x410
+#define MMU_PGWKR_PGDBASE 0x411
+#define MMU_PGWKR_PGDSHFT 0x412
+#define MMU_PGWKR_PGDMASK 0x413
+#define MMU_PGWKR_PUDSHFT 0x414
+#define MMU_PGWKR_PUDMASK 0x415
+#define MMU_PGWKR_PMDSHFT 0x416
+#define MMU_PGWKR_PMDMASK 0x417
+#define MMU_PGWKR_PTESHFT 0x418
+#define MMU_PGWKR_PTEMASK 0x419
-#define XLP_CPU_BLOCKID_SCU 8
-#define XLP_CPU_BLOCKID_FPU 9
-#define XLP_CPU_BLOCKID_MAP 10
+#if !defined(LOCORE) && !defined(__ASSEMBLY__)
+#if defined(__mips_n64) || defined(__mips_n32)
+static __inline uint64_t
+nlm_mfcr(uint32_t reg)
+{
+ uint64_t res;
-/* Offsets of interest from the 'MAP' Block */
-#define XLP_BLKID_MAP_THREADMODE 0x00
-#define XLP_BLKID_MAP_EXT_EBASE_ENABLE 0x04
-#define XLP_BLKID_MAP_CCDI_CONFIG 0x08
-#define XLP_BLKID_MAP_THRD0_CCDI_STATUS 0x0c
-#define XLP_BLKID_MAP_THRD1_CCDI_STATUS 0x10
-#define XLP_BLKID_MAP_THRD2_CCDI_STATUS 0x14
-#define XLP_BLKID_MAP_THRD3_CCDI_STATUS 0x18
-#define XLP_BLKID_MAP_THRD0_DEBUG_MODE 0x1c
-#define XLP_BLKID_MAP_THRD1_DEBUG_MODE 0x20
-#define XLP_BLKID_MAP_THRD2_DEBUG_MODE 0x24
-#define XLP_BLKID_MAP_THRD3_DEBUG_MODE 0x28
-#define XLP_BLKID_MAP_MISC_STATE 0x60
-#define XLP_BLKID_MAP_DEBUG_READ_CTL 0x64
-#define XLP_BLKID_MAP_DEBUG_READ_REG0 0x68
-#define XLP_BLKID_MAP_DEBUG_READ_REG1 0x6c
+ __asm__ __volatile__(
+ ".set push\n\t"
+ ".set noreorder\n\t"
+ "move $9, %1\n\t"
+ ".word 0x71280018\n\t" /* mfcr $8, $9 */
+ "move %0, $8\n\t"
+ ".set pop\n"
+ : "=r" (res) : "r"(reg)
+ : "$8", "$9"
+ );
+ return (res);
+}
+
+static __inline void
+nlm_mtcr(uint32_t reg, uint64_t value)
+{
+ __asm__ __volatile__(
+ ".set push\n\t"
+ ".set noreorder\n\t"
+ "move $8, %0\n"
+ "move $9, %1\n"
+ ".word 0x71280019\n" /* mtcr $8, $9 */
+ ".set pop\n"
+ :
+ : "r" (value), "r" (reg)
+ : "$8", "$9"
+ );
+}
+
+#else /* !(defined(__mips_n64) || defined(__mips_n32)) */
+
+static __inline__ uint64_t
+nlm_mfcr(uint32_t reg)
+{
+ uint32_t hi, lo;
+
+ __asm__ __volatile__ (
+ ".set push\n"
+ ".set mips64\n"
+ "move $8, %2\n"
+ ".word 0x71090018\n"
+ "nop \n"
+ "dsra32 %0, $9, 0\n"
+ "sll %1, $9, 0\n"
+ ".set pop\n"
+ : "=r"(hi), "=r"(lo)
+ : "r"(reg) : "$8", "$9");
+
+ return (((uint64_t)hi) << 32) | lo;
+}
+
+static __inline__ void
+nlm_mtcr(uint32_t reg, uint64_t val)
+{
+ uint32_t hi, lo;
+
+ hi = val >> 32;
+ lo = val & 0xffffffff;
+
+ __asm__ __volatile__ (
+ ".set push\n"
+ ".set mips64\n"
+ "move $9, %0\n"
+ "dsll32 $9, %1, 0\n"
+ "dsll32 $8, %0, 0\n"
+ "dsrl32 $9, $9, 0\n"
+ "or $9, $9, $8\n"
+ "move $8, %2\n"
+ ".word 0x71090019\n"
+ "nop \n"
+ ".set pop\n"
+ : :"r"(hi), "r"(lo), "r"(reg)
+ : "$8", "$9");
+}
+#endif /* (defined(__mips_n64) || defined(__mips_n32)) */
+
+/* hashindex_en = 1 to enable hash mode, hashindex_en=0 to disable
+ * global_mode = 1 to enable global mode, global_mode=0 to disable
+ * clk_gating = 0 to enable clock gating, clk_gating=1 to disable
+ */
+static __inline__ void nlm_mmu_setup(int hashindex_en, int global_mode,
+ int clk_gating)
+{
+ uint32_t mmusetup = 0;
+
+ mmusetup |= (hashindex_en << 13);
+ mmusetup |= (clk_gating << 3);
+ mmusetup |= (global_mode << 0);
+ nlm_mtcr(MMU_SETUP, mmusetup);
+}
+
+static __inline__ void nlm_mmu_lfsr_seed (int thr0_seed, int thr1_seed,
+ int thr2_seed, int thr3_seed)
+{
+ uint32_t seed = nlm_mfcr(MMU_LFSRSEED);
+
+ seed |= ((thr3_seed & 0x7f) << 23);
+ seed |= ((thr2_seed & 0x7f) << 16);
+ seed |= ((thr1_seed & 0x7f) << 7);
+ seed |= ((thr0_seed & 0x7f) << 0);
+ nlm_mtcr(MMU_LFSRSEED, seed);
+}
+#endif /* __ASSEMBLY__ */
#endif /* __NLM_CPUCONTROL_H__ */
diff --git a/sys/mips/nlm/hal/fmn.c b/sys/mips/nlm/hal/fmn.c
index fd4f7c80a7df8..e58a2a5590361 100644
--- a/sys/mips/nlm/hal/fmn.c
+++ b/sys/mips/nlm/hal/fmn.c
@@ -25,20 +25,19 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
- * $FreeBSD$
* NETLOGIC_BSD */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-
#include <sys/types.h>
+#include <sys/systm.h>
+
+#include <machine/cpufunc.h>
#include <mips/nlm/hal/mips-extns.h>
-#include <mips/nlm/hal/mmio.h>
+#include <mips/nlm/hal/haldefs.h>
#include <mips/nlm/hal/iomap.h>
#include <mips/nlm/hal/fmn.h>
-#include <sys/systm.h>
-uint32_t bad_xlp_num_nodes = 4;
/* XLP can take upto 16K of FMN messages per hardware queue, as spill.
* But, configuring all 16K causes the total spill memory to required
* to blow upto 192MB for single chip configuration, and 768MB in four
@@ -68,27 +67,7 @@ uint64_t nlm_cms_spill_total_messages = 1 * 1024;
* For all 4 nodes, there are 18*4 = 72 FMN stations
*/
uint32_t nlm_cms_total_stations = 18 * 4 /*xlp_num_nodes*/;
-uint32_t cms_onchip_seg_availability[XLP_CMS_ON_CHIP_PER_QUEUE_SPACE];
-
-int nlm_cms_verify_credit_config (int spill_en, int tot_credit)
-{
- /* Note: In XLP there seem to be no mechanism to read back
- * the credit count that has been programmed into a sid / did pair;
- * since we have only one register 0x2000 to read.
- * Hence it looks like all credit mgmt/verification needs to
- * be done by software. Software could keep track of total credits
- * getting programmed and verify it from this function.
- */
-
- if (spill_en) {
- /* TODO */
- }
-
- if (tot_credit > (XLP_CMS_ON_CHIP_MESG_SPACE*bad_xlp_num_nodes))
- return 1; /* credits overflowed - should not happen */
-
- return 0;
-}
+uint32_t cms_onchip_seg_availability[CMS_ON_CHIP_PER_QUEUE_SPACE];
/**
* Takes inputs as node, queue_size and maximum number of queues.
@@ -163,7 +142,7 @@ void nlm_cms_setup_credits(uint64_t base, int destid, int srcid, int credit)
uint32_t val;
val = ((credit << 24) | (destid << 12) | (srcid << 0));
- nlm_wreg_cms(base, XLP_CMS_OUTPUTQ_CREDIT_CFG_REG, val);
+ nlm_write_cms_reg(base, CMS_OUTPUTQ_CREDIT_CFG, val);
}
@@ -182,93 +161,93 @@ int nlm_cms_config_onchip_queue (uint64_t base, uint64_t spill_base,
#if 0
/* configure credits for src cpu0, on this queue */
- nlm_cms_setup_credits(base, qid, XLP_CMS_CPU0_SRC_STID,
- XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
+ nlm_cms_setup_credits(base, qid, CMS_CPU0_SRC_STID,
+ CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
nlm_cms_spill_total_messages));
/* configure credits for src cpu1, on this queue */
- nlm_cms_setup_credits(base, qid, XLP_CMS_CPU1_SRC_STID,
- XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
+ nlm_cms_setup_credits(base, qid, CMS_CPU1_SRC_STID,
+ CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
nlm_cms_spill_total_messages));
/* configure credits for src cpu2, on this queue */
- nlm_cms_setup_credits(base, qid, XLP_CMS_CPU2_SRC_STID,
- XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
+ nlm_cms_setup_credits(base, qid, CMS_CPU2_SRC_STID,
+ CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
nlm_cms_spill_total_messages));
/* configure credits for src cpu3, on this queue */
- nlm_cms_setup_credits(base, qid, XLP_CMS_CPU3_SRC_STID,
- XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
+ nlm_cms_setup_credits(base, qid, CMS_CPU3_SRC_STID,
+ CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
nlm_cms_spill_total_messages));
/* configure credits for src cpu4, on this queue */
- nlm_cms_setup_credits(base, qid, XLP_CMS_CPU4_SRC_STID,
- XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
+ nlm_cms_setup_credits(base, qid, CMS_CPU4_SRC_STID,
+ CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
nlm_cms_spill_total_messages));
/* configure credits for src cpu5, on this queue */
- nlm_cms_setup_credits(base, qid, XLP_CMS_CPU5_SRC_STID,
- XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
+ nlm_cms_setup_credits(base, qid, CMS_CPU5_SRC_STID,
+ CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
nlm_cms_spill_total_messages));
/* configure credits for src cpu6, on this queue */
- nlm_cms_setup_credits(base, qid, XLP_CMS_CPU6_SRC_STID,
- XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
+ nlm_cms_setup_credits(base, qid, CMS_CPU6_SRC_STID,
+ CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
nlm_cms_spill_total_messages));
/* configure credits for src cpu7, on this queue */
- nlm_cms_setup_credits(base, qid, XLP_CMS_CPU7_SRC_STID,
- XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
+ nlm_cms_setup_credits(base, qid, CMS_CPU7_SRC_STID,
+ CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
nlm_cms_spill_total_messages));
/* configure credits for src pcie0, on this queue */
- nlm_cms_setup_credits(base, qid, XLP_CMS_PCIE0_SRC_STID,
- XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
+ nlm_cms_setup_credits(base, qid, CMS_PCIE0_SRC_STID,
+ CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
nlm_cms_spill_total_messages));
/* configure credits for src pcie1, on this queue */
- nlm_cms_setup_credits(base, qid, XLP_CMS_PCIE1_SRC_STID,
- XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
+ nlm_cms_setup_credits(base, qid, CMS_PCIE1_SRC_STID,
+ CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
nlm_cms_spill_total_messages));
/* configure credits for src pcie2, on this queue */
- nlm_cms_setup_credits(base, qid, XLP_CMS_PCIE2_SRC_STID,
- XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
+ nlm_cms_setup_credits(base, qid, CMS_PCIE2_SRC_STID,
+ CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
nlm_cms_spill_total_messages));
/* configure credits for src pcie3, on this queue */
- nlm_cms_setup_credits(base, qid, XLP_CMS_PCIE3_SRC_STID,
- XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
+ nlm_cms_setup_credits(base, qid, CMS_PCIE3_SRC_STID,
+ CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
nlm_cms_spill_total_messages));
/* configure credits for src dte, on this queue */
- nlm_cms_setup_credits(base, qid, XLP_CMS_DTE_SRC_STID,
- XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
+ nlm_cms_setup_credits(base, qid, CMS_DTE_SRC_STID,
+ CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
nlm_cms_spill_total_messages));
/* configure credits for src rsa_ecc, on this queue */
- nlm_cms_setup_credits(base, qid, XLP_CMS_RSA_ECC_SRC_STID,
- XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
+ nlm_cms_setup_credits(base, qid, CMS_RSA_ECC_SRC_STID,
+ CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
nlm_cms_spill_total_messages));
/* configure credits for src crypto, on this queue */
- nlm_cms_setup_credits(base, qid, XLP_CMS_CRYPTO_SRC_STID,
- XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
+ nlm_cms_setup_credits(base, qid, CMS_CRYPTO_SRC_STID,
+ CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
nlm_cms_spill_total_messages));
/* configure credits for src cmp, on this queue */
- nlm_cms_setup_credits(base, qid, XLP_CMS_CMP_SRC_STID,
- XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
+ nlm_cms_setup_credits(base, qid, CMS_CMP_SRC_STID,
+ CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
nlm_cms_spill_total_messages));
/* configure credits for src poe, on this queue */
- nlm_cms_setup_credits(base, qid, XLP_CMS_POE_SRC_STID,
- XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
+ nlm_cms_setup_credits(base, qid, CMS_POE_SRC_STID,
+ CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
nlm_cms_spill_total_messages));
/* configure credits for src nae, on this queue */
- nlm_cms_setup_credits(base, qid, XLP_CMS_NAE_SRC_STID,
- XLP_CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
+ nlm_cms_setup_credits(base, qid, CMS_NAE_SRC_STID,
+ CMS_DEFAULT_CREDIT(nlm_cms_total_stations,
nlm_cms_spill_total_messages));
#endif
@@ -289,20 +268,20 @@ int nlm_cms_alloc_spill_q(uint64_t base, int qid, uint64_t spill_base,
uint64_t queue_config;
uint32_t spill_start;
- if(nsegs > XLP_CMS_MAX_SPILL_SEGMENTS_PER_QUEUE) {
+ if(nsegs > CMS_MAX_SPILL_SEGMENTS_PER_QUEUE) {
return 1;
}
- queue_config = nlm_rdreg_cms(base,(XLP_CMS_OUTPUTQ_CONFIG_REG(qid)));
+ queue_config = nlm_read_cms_reg(base,(CMS_OUTPUTQ_CONFIG(qid)));
spill_start = ((spill_base >> 12) & 0x3F);
/* Spill configuration */
- queue_config = (((uint64_t)XLP_CMS_SPILL_ENA << 62) |
+ queue_config = (((uint64_t)CMS_SPILL_ENA << 62) |
(((spill_base >> 18) & 0x3FFFFF) << 27) |
(spill_start + nsegs - 1) << 21 |
(spill_start << 15));
- nlm_wreg_cms(base,(XLP_CMS_OUTPUTQ_CONFIG_REG(qid)),queue_config);
+ nlm_write_cms_reg(base,(CMS_OUTPUTQ_CONFIG(qid)),queue_config);
return 0;
}
@@ -320,8 +299,8 @@ int nlm_cms_alloc_onchip_q(uint64_t base, int qid, int nsegs)
int onchipbase, start, last;
uint8_t i;
- if( ((curr_end + nsegs) > XLP_CMS_MAX_ONCHIP_SEGMENTS) ||
- (nsegs > XLP_CMS_ON_CHIP_PER_QUEUE_SPACE) ) {
+ if( ((curr_end + nsegs) > CMS_MAX_ONCHIP_SEGMENTS) ||
+ (nsegs > CMS_ON_CHIP_PER_QUEUE_SPACE) ) {
/* Invalid configuration */
return 1;
}
@@ -347,15 +326,15 @@ int nlm_cms_alloc_onchip_q(uint64_t base, int qid, int nsegs)
cms_onchip_seg_availability[onchipbase] |= (1 << i);
}
- queue_config = nlm_rdreg_cms(base,(XLP_CMS_OUTPUTQ_CONFIG_REG(qid)));
+ queue_config = nlm_read_cms_reg(base,(CMS_OUTPUTQ_CONFIG(qid)));
/* On chip configuration */
- queue_config = (((uint64_t)XLP_CMS_QUEUE_ENA << 63) |
+ queue_config = (((uint64_t)CMS_QUEUE_ENA << 63) |
((onchipbase & 0x1f) << 10) |
((last & 0x1f) << 5) |
(start & 0x1f));
- nlm_wreg_cms(base,(XLP_CMS_OUTPUTQ_CONFIG_REG(qid)),queue_config);
+ nlm_write_cms_reg(base,(CMS_OUTPUTQ_CONFIG(qid)),queue_config);
return 0;
}
@@ -367,85 +346,86 @@ void nlm_cms_default_setup(int node, uint64_t spill_base, int spill_en,
int queue;
uint64_t base;
- base = nlm_regbase_cms(node);
+ base = nlm_get_cms_regbase(node);
for(j=0; j<1024; j++) {
- printf("Qid:0x%04d Val:0x%016jx\n",j, (uintmax_t)nlm_cms_get_onchip_queue (base, j));
+ printf("Qid:0x%04d Val:0x%016jx\n",j,
+ (uintmax_t)nlm_cms_get_onchip_queue (base, j));
}
/* Enable all cpu push queues */
for (j=0; j<XLP_MAX_CORES; j++)
for (k=0; k<XLP_MAX_THREADS; k++)
- for (vc=0; vc<XLP_CMS_MAX_VCPU_VC; vc++) {
+ for (vc=0; vc<CMS_MAX_VCPU_VC; vc++) {
/* TODO : remove this once SMP works */
if( (j == 0) && (k == 0) )
continue;
- queue = XLP_CMS_CPU_PUSHQ(node, j, k, vc);
+ queue = CMS_CPU_PUSHQ(node, j, k, vc);
nlm_cms_config_onchip_queue(base, spill_base, queue, spill_en);
}
/* Enable pcie 0 push queue */
- for (j=XLP_CMS_PCIE0_QID(0); j<XLP_CMS_PCIE0_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_PCIE0_QID(0); j<CMS_PCIE0_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_config_onchip_queue(base, spill_base, queue, spill_en);
}
/* Enable pcie 1 push queue */
- for (j=XLP_CMS_PCIE1_QID(0); j<XLP_CMS_PCIE1_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_PCIE1_QID(0); j<CMS_PCIE1_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_config_onchip_queue(base, spill_base, queue, spill_en);
}
/* Enable pcie 2 push queue */
- for (j=XLP_CMS_PCIE2_QID(0); j<XLP_CMS_PCIE2_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_PCIE2_QID(0); j<CMS_PCIE2_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_config_onchip_queue(base, spill_base, queue, spill_en);
}
/* Enable pcie 3 push queue */
- for (j=XLP_CMS_PCIE3_QID(0); j<XLP_CMS_PCIE3_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_PCIE3_QID(0); j<CMS_PCIE3_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_config_onchip_queue(base, spill_base, queue, spill_en);
}
/* Enable DTE push queue */
- for (j=XLP_CMS_DTE_QID(0); j<XLP_CMS_DTE_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_DTE_QID(0); j<CMS_DTE_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_config_onchip_queue(base, spill_base, queue, spill_en);
}
/* Enable RSA/ECC push queue */
- for (j=XLP_CMS_RSA_ECC_QID(0); j<XLP_CMS_RSA_ECC_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_RSA_ECC_QID(0); j<CMS_RSA_ECC_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_config_onchip_queue(base, spill_base, queue, spill_en);
}
/* Enable crypto push queue */
- for (j=XLP_CMS_CRYPTO_QID(0); j<XLP_CMS_CRYPTO_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_CRYPTO_QID(0); j<CMS_CRYPTO_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_config_onchip_queue(base, spill_base, queue, spill_en);
}
/* Enable CMP push queue */
- for (j=XLP_CMS_CMP_QID(0); j<XLP_CMS_CMP_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_CMP_QID(0); j<CMS_CMP_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_config_onchip_queue(base, spill_base, queue, spill_en);
}
/* Enable POE push queue */
- for (j=XLP_CMS_POE_QID(0); j<XLP_CMS_POE_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_POE_QID(0); j<CMS_POE_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_config_onchip_queue(base, spill_base, queue, spill_en);
}
/* Enable NAE push queue */
- for (j=XLP_CMS_NAE_QID(0); j<XLP_CMS_NAE_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_NAE_QID(0); j<CMS_NAE_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_config_onchip_queue(base, spill_base, queue, spill_en);
}
/* Enable all pop queues */
if (popq_en) {
- for (j=XLP_CMS_POPQ_QID(0); j<XLP_CMS_POPQ_MAXQID; j++) {
- queue = XLP_CMS_POPQ(node, j);
+ for (j=CMS_POPQ_QID(0); j<CMS_POPQ_MAXQID; j++) {
+ queue = CMS_POPQ(node, j);
nlm_cms_config_onchip_queue(base, spill_base, queue,
spill_en);
}
@@ -454,16 +434,16 @@ void nlm_cms_default_setup(int node, uint64_t spill_base, int spill_en,
uint64_t nlm_cms_get_onchip_queue (uint64_t base, int qid)
{
- return nlm_rdreg_cms(base, XLP_CMS_OUTPUTQ_CONFIG_REG(qid));
+ return nlm_read_cms_reg(base, CMS_OUTPUTQ_CONFIG(qid));
}
void nlm_cms_set_onchip_queue (uint64_t base, int qid, uint64_t val)
{
uint64_t rdval;
- rdval = nlm_rdreg_cms(base, XLP_CMS_OUTPUTQ_CONFIG_REG(qid));
+ rdval = nlm_read_cms_reg(base, CMS_OUTPUTQ_CONFIG(qid));
rdval |= val;
- nlm_wreg_cms(base, XLP_CMS_OUTPUTQ_CONFIG_REG(qid), rdval);
+ nlm_write_cms_reg(base, CMS_OUTPUTQ_CONFIG(qid), rdval);
}
void nlm_cms_per_queue_level_intr(uint64_t base, int qid, int sub_type,
@@ -471,12 +451,12 @@ void nlm_cms_per_queue_level_intr(uint64_t base, int qid, int sub_type,
{
uint64_t val;
- val = nlm_rdreg_cms(base, XLP_CMS_OUTPUTQ_CONFIG_REG(qid));
+ val = nlm_read_cms_reg(base, CMS_OUTPUTQ_CONFIG(qid));
val |= (((uint64_t)sub_type<<54) |
((uint64_t)intr_val<<56));
- nlm_wreg_cms(base, XLP_CMS_OUTPUTQ_CONFIG_REG(qid), val);
+ nlm_write_cms_reg(base, CMS_OUTPUTQ_CONFIG(qid), val);
}
void nlm_cms_level_intr(int node, int sub_type, int intr_val)
@@ -485,78 +465,78 @@ void nlm_cms_level_intr(int node, int sub_type, int intr_val)
int queue;
uint64_t base;
- base = nlm_regbase_cms(node);
+ base = nlm_get_cms_regbase(node);
/* setup level intr config on all cpu push queues */
for (j=0; j<XLP_MAX_CORES; j++)
for (k=0; k<XLP_MAX_THREADS; k++)
- for (vc=0; vc<XLP_CMS_MAX_VCPU_VC; vc++) {
- queue = XLP_CMS_CPU_PUSHQ(node, j, k, vc);
+ for (vc=0; vc<CMS_MAX_VCPU_VC; vc++) {
+ queue = CMS_CPU_PUSHQ(node, j, k, vc);
nlm_cms_per_queue_level_intr(base, queue, sub_type, intr_val);
}
/* setup level intr config on all pcie 0 push queue */
- for (j=XLP_CMS_PCIE0_QID(0); j<XLP_CMS_PCIE0_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_PCIE0_QID(0); j<CMS_PCIE0_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_per_queue_level_intr(base, queue, sub_type, intr_val);
}
/* setup level intr config on all pcie 1 push queue */
- for (j=XLP_CMS_PCIE1_QID(0); j<XLP_CMS_PCIE1_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_PCIE1_QID(0); j<CMS_PCIE1_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_per_queue_level_intr(base, queue, sub_type, intr_val);
}
/* setup level intr config on all pcie 2 push queue */
- for (j=XLP_CMS_PCIE2_QID(0); j<XLP_CMS_PCIE2_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_PCIE2_QID(0); j<CMS_PCIE2_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_per_queue_level_intr(base, queue, sub_type, intr_val);
}
/* setup level intr config on all pcie 3 push queue */
- for (j=XLP_CMS_PCIE3_QID(0); j<XLP_CMS_PCIE3_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_PCIE3_QID(0); j<CMS_PCIE3_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_per_queue_level_intr(base, queue, sub_type, intr_val);
}
/* setup level intr config on all DTE push queue */
- for (j=XLP_CMS_DTE_QID(0); j<XLP_CMS_DTE_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_DTE_QID(0); j<CMS_DTE_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_per_queue_level_intr(base, queue, sub_type, intr_val);
}
/* setup level intr config on all RSA/ECC push queue */
- for (j=XLP_CMS_RSA_ECC_QID(0); j<XLP_CMS_RSA_ECC_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_RSA_ECC_QID(0); j<CMS_RSA_ECC_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_per_queue_level_intr(base, queue, sub_type, intr_val);
}
/* setup level intr config on all crypto push queue */
- for (j=XLP_CMS_CRYPTO_QID(0); j<XLP_CMS_CRYPTO_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_CRYPTO_QID(0); j<CMS_CRYPTO_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_per_queue_level_intr(base, queue, sub_type, intr_val);
}
/* setup level intr config on all CMP push queue */
- for (j=XLP_CMS_CMP_QID(0); j<XLP_CMS_CMP_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_CMP_QID(0); j<CMS_CMP_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_per_queue_level_intr(base, queue, sub_type, intr_val);
}
/* setup level intr config on all POE push queue */
- for (j=XLP_CMS_POE_QID(0); j<XLP_CMS_POE_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_POE_QID(0); j<CMS_POE_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_per_queue_level_intr(base, queue, sub_type, intr_val);
}
/* setup level intr config on all NAE push queue */
- for (j=XLP_CMS_NAE_QID(0); j<XLP_CMS_NAE_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_NAE_QID(0); j<CMS_NAE_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_per_queue_level_intr(base, queue, sub_type, intr_val);
}
/* setup level intr config on all pop queues */
- for (j=XLP_CMS_POPQ_QID(0); j<XLP_CMS_POPQ_MAXQID; j++) {
- queue = XLP_CMS_POPQ(node, j);
+ for (j=CMS_POPQ_QID(0); j<CMS_POPQ_MAXQID; j++) {
+ queue = CMS_POPQ(node, j);
nlm_cms_per_queue_level_intr(base, queue, sub_type, intr_val);
}
}
@@ -566,12 +546,12 @@ void nlm_cms_per_queue_timer_intr(uint64_t base, int qid, int sub_type,
{
uint64_t val;
- val = nlm_rdreg_cms(base, XLP_CMS_OUTPUTQ_CONFIG_REG(qid));
+ val = nlm_read_cms_reg(base, CMS_OUTPUTQ_CONFIG(qid));
val |= (((uint64_t)sub_type<<49) |
((uint64_t)intr_val<<51));
- nlm_wreg_cms(base, XLP_CMS_OUTPUTQ_CONFIG_REG(qid), val);
+ nlm_write_cms_reg(base, CMS_OUTPUTQ_CONFIG(qid), val);
}
void nlm_cms_timer_intr(int node, int en, int sub_type, int intr_val)
@@ -580,78 +560,78 @@ void nlm_cms_timer_intr(int node, int en, int sub_type, int intr_val)
int queue;
uint64_t base;
- base = nlm_regbase_cms(node);
+ base = nlm_get_cms_regbase(node);
/* setup timer intr config on all cpu push queues */
for (j=0; j<XLP_MAX_CORES; j++)
for (k=0; k<XLP_MAX_THREADS; k++)
- for (vc=0; vc<XLP_CMS_MAX_VCPU_VC; vc++) {
- queue = XLP_CMS_CPU_PUSHQ(node, j, k, vc);
+ for (vc=0; vc<CMS_MAX_VCPU_VC; vc++) {
+ queue = CMS_CPU_PUSHQ(node, j, k, vc);
nlm_cms_per_queue_timer_intr(base, queue, sub_type, intr_val);
}
/* setup timer intr config on all pcie 0 push queue */
- for (j=XLP_CMS_PCIE0_QID(0); j<XLP_CMS_PCIE0_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_PCIE0_QID(0); j<CMS_PCIE0_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_per_queue_timer_intr(base, queue, sub_type, intr_val);
}
/* setup timer intr config on all pcie 1 push queue */
- for (j=XLP_CMS_PCIE1_QID(0); j<XLP_CMS_PCIE1_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_PCIE1_QID(0); j<CMS_PCIE1_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_per_queue_timer_intr(base, queue, sub_type, intr_val);
}
/* setup timer intr config on all pcie 2 push queue */
- for (j=XLP_CMS_PCIE2_QID(0); j<XLP_CMS_PCIE2_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_PCIE2_QID(0); j<CMS_PCIE2_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_per_queue_timer_intr(base, queue, sub_type, intr_val);
}
/* setup timer intr config on all pcie 3 push queue */
- for (j=XLP_CMS_PCIE3_QID(0); j<XLP_CMS_PCIE3_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_PCIE3_QID(0); j<CMS_PCIE3_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_per_queue_timer_intr(base, queue, sub_type, intr_val);
}
/* setup timer intr config on all DTE push queue */
- for (j=XLP_CMS_DTE_QID(0); j<XLP_CMS_DTE_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_DTE_QID(0); j<CMS_DTE_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_per_queue_timer_intr(base, queue, sub_type, intr_val);
}
/* setup timer intr config on all RSA/ECC push queue */
- for (j=XLP_CMS_RSA_ECC_QID(0); j<XLP_CMS_RSA_ECC_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_RSA_ECC_QID(0); j<CMS_RSA_ECC_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_per_queue_timer_intr(base, queue, sub_type, intr_val);
}
/* setup timer intr config on all crypto push queue */
- for (j=XLP_CMS_CRYPTO_QID(0); j<XLP_CMS_CRYPTO_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_CRYPTO_QID(0); j<CMS_CRYPTO_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_per_queue_timer_intr(base, queue, sub_type, intr_val);
}
/* setup timer intr config on all CMP push queue */
- for (j=XLP_CMS_CMP_QID(0); j<XLP_CMS_CMP_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_CMP_QID(0); j<CMS_CMP_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_per_queue_timer_intr(base, queue, sub_type, intr_val);
}
/* setup timer intr config on all POE push queue */
- for (j=XLP_CMS_POE_QID(0); j<XLP_CMS_POE_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_POE_QID(0); j<CMS_POE_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_per_queue_timer_intr(base, queue, sub_type, intr_val);
}
/* setup timer intr config on all NAE push queue */
- for (j=XLP_CMS_NAE_QID(0); j<XLP_CMS_NAE_MAXQID; j++) {
- queue = XLP_CMS_IO_PUSHQ(node, j);
+ for (j=CMS_NAE_QID(0); j<CMS_NAE_MAXQID; j++) {
+ queue = CMS_IO_PUSHQ(node, j);
nlm_cms_per_queue_timer_intr(base, queue, sub_type, intr_val);
}
/* setup timer intr config on all pop queues */
- for (j=XLP_CMS_POPQ_QID(0); j<XLP_CMS_POPQ_MAXQID; j++) {
- queue = XLP_CMS_POPQ(node, j);
+ for (j=CMS_POPQ_QID(0); j<CMS_POPQ_MAXQID; j++) {
+ queue = CMS_POPQ(node, j);
nlm_cms_per_queue_timer_intr(base, queue, sub_type, intr_val);
}
}
@@ -660,7 +640,7 @@ void nlm_cms_timer_intr(int node, int en, int sub_type, int intr_val)
int nlm_cms_outputq_intr_check(uint64_t base, int qid)
{
uint64_t val;
- val = nlm_rdreg_cms(base, XLP_CMS_OUTPUTQ_CONFIG_REG(qid));
+ val = nlm_read_cms_reg(base, CMS_OUTPUTQ_CONFIG(qid));
return ((val >> 59) & 0x1);
}
@@ -668,77 +648,77 @@ int nlm_cms_outputq_intr_check(uint64_t base, int qid)
void nlm_cms_outputq_clr_intr(uint64_t base, int qid)
{
uint64_t val;
- val = nlm_rdreg_cms(base, XLP_CMS_OUTPUTQ_CONFIG_REG(qid));
+ val = nlm_read_cms_reg(base, CMS_OUTPUTQ_CONFIG(qid));
val |= (1ULL<<59);
- nlm_wreg_cms(base, XLP_CMS_OUTPUTQ_CONFIG_REG(qid), val);
+ nlm_write_cms_reg(base, CMS_OUTPUTQ_CONFIG(qid), val);
}
void nlm_cms_illegal_dst_error_intr(uint64_t base, int en)
{
uint64_t val;
- val = nlm_rdreg_cms(base, XLP_CMS_MSG_CONFIG_REG);
+ val = nlm_read_cms_reg(base, CMS_MSG_CONFIG);
val |= (en<<8);
- nlm_wreg_cms(base, XLP_CMS_MSG_CONFIG_REG, val);
+ nlm_write_cms_reg(base, CMS_MSG_CONFIG, val);
}
void nlm_cms_timeout_error_intr(uint64_t base, int en)
{
uint64_t val;
- val = nlm_rdreg_cms(base, XLP_CMS_MSG_CONFIG_REG);
+ val = nlm_read_cms_reg(base, CMS_MSG_CONFIG);
val |= (en<<7);
- nlm_wreg_cms(base, XLP_CMS_MSG_CONFIG_REG, val);
+ nlm_write_cms_reg(base, CMS_MSG_CONFIG, val);
}
void nlm_cms_biu_error_resp_intr(uint64_t base, int en)
{
uint64_t val;
- val = nlm_rdreg_cms(base, XLP_CMS_MSG_CONFIG_REG);
+ val = nlm_read_cms_reg(base, CMS_MSG_CONFIG);
val |= (en<<6);
- nlm_wreg_cms(base, XLP_CMS_MSG_CONFIG_REG, val);
+ nlm_write_cms_reg(base, CMS_MSG_CONFIG, val);
}
void nlm_cms_spill_uncorrectable_ecc_error_intr(uint64_t base, int en)
{
uint64_t val;
- val = nlm_rdreg_cms(base, XLP_CMS_MSG_CONFIG_REG);
+ val = nlm_read_cms_reg(base, CMS_MSG_CONFIG);
val |= (en<<5) | (en<<3);
- nlm_wreg_cms(base, XLP_CMS_MSG_CONFIG_REG, val);
+ nlm_write_cms_reg(base, CMS_MSG_CONFIG, val);
}
void nlm_cms_spill_correctable_ecc_error_intr(uint64_t base, int en)
{
uint64_t val;
- val = nlm_rdreg_cms(base, XLP_CMS_MSG_CONFIG_REG);
+ val = nlm_read_cms_reg(base, CMS_MSG_CONFIG);
val |= (en<<4) | (en<<2);
- nlm_wreg_cms(base, XLP_CMS_MSG_CONFIG_REG, val);
+ nlm_write_cms_reg(base, CMS_MSG_CONFIG, val);
}
void nlm_cms_outputq_uncorrectable_ecc_error_intr(uint64_t base, int en)
{
uint64_t val;
- val = nlm_rdreg_cms(base, XLP_CMS_MSG_CONFIG_REG);
+ val = nlm_read_cms_reg(base, CMS_MSG_CONFIG);
val |= (en<<1);
- nlm_wreg_cms(base, XLP_CMS_MSG_CONFIG_REG, val);
+ nlm_write_cms_reg(base, CMS_MSG_CONFIG, val);
}
void nlm_cms_outputq_correctable_ecc_error_intr(uint64_t base, int en)
{
uint64_t val;
- val = nlm_rdreg_cms(base, XLP_CMS_MSG_CONFIG_REG);
+ val = nlm_read_cms_reg(base, CMS_MSG_CONFIG);
val |= (en<<0);
- nlm_wreg_cms(base, XLP_CMS_MSG_CONFIG_REG, val);
+ nlm_write_cms_reg(base, CMS_MSG_CONFIG, val);
}
uint64_t nlm_cms_network_error_status(uint64_t base)
{
- return nlm_rdreg_cms(base, XLP_CMS_MSG_ERR_REG);
+ return nlm_read_cms_reg(base, CMS_MSG_ERR);
}
int nlm_cms_get_net_error_code(uint64_t err)
@@ -770,20 +750,20 @@ void nlm_cms_trace_setup(uint64_t base, int en, uint64_t trace_base,
{
uint64_t val;
- nlm_wreg_cms(base, XLP_CMS_TRACE_BASE_ADDR_REG, trace_base);
- nlm_wreg_cms(base, XLP_CMS_TRACE_LIMIT_ADDR_REG, trace_limit);
+ nlm_write_cms_reg(base, CMS_TRACE_BASE_ADDR, trace_base);
+ nlm_write_cms_reg(base, CMS_TRACE_LIMIT_ADDR, trace_limit);
- val = nlm_rdreg_cms(base, XLP_CMS_TRACE_CONFIG_REG);
+ val = nlm_read_cms_reg(base, CMS_TRACE_CONFIG);
val |= (((uint64_t)match_dstid_en << 39) |
((dst_id & 0xfff) << 24) |
(match_srcid_en << 23) |
((src_id & 0xfff) << 8) |
(wrap << 1) |
(en << 0));
- nlm_wreg_cms(base, XLP_CMS_MSG_CONFIG_REG, val);
+ nlm_write_cms_reg(base, CMS_MSG_CONFIG, val);
}
void nlm_cms_endian_byte_swap (uint64_t base, int en)
{
- nlm_wreg_cms(base, XLP_CMS_MSG_ENDIAN_SWAP_REG, en);
+ nlm_write_cms_reg(base, CMS_MSG_ENDIAN_SWAP, en);
}
diff --git a/sys/mips/nlm/hal/fmn.h b/sys/mips/nlm/hal/fmn.h
index 75fc77403166c..88ba113ec473d 100644
--- a/sys/mips/nlm/hal/fmn.h
+++ b/sys/mips/nlm/hal/fmn.h
@@ -25,8 +25,9 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
+ * NETLOGIC_BSD
* $FreeBSD$
- * NETLOGIC_BSD */
+ */
#ifndef __NLM_FMNV2_H__
#define __NLM_FMNV2_H__
@@ -38,156 +39,156 @@
*/
/* FMN configuration registers */
-#define XLP_CMS_OUTPUTQ_CONFIG_REG(i) ((i)*2)
-#define XLP_CMS_MAX_OUTPUTQ 1024
-#define XLP_CMS_OUTPUTQ_CREDIT_CFG_REG (0x2000/4)
-#define XLP_CMS_MSG_CONFIG_REG (0x2008/4)
-#define XLP_CMS_MSG_ERR_REG (0x2010/4)
-#define XLP_CMS_TRACE_CONFIG_REG (0x2018/4)
-#define XLP_CMS_TRACE_BASE_ADDR_REG (0x2020/4)
-#define XLP_CMS_TRACE_LIMIT_ADDR_REG (0x2028/4)
-#define XLP_CMS_TRACE_CURRENT_ADDR_REG (0x2030/4)
-#define XLP_CMS_MSG_ENDIAN_SWAP_REG (0x2038/4)
+#define CMS_OUTPUTQ_CONFIG(i) ((i)*2)
+#define CMS_MAX_OUTPUTQ 1024
+#define CMS_OUTPUTQ_CREDIT_CFG (0x2000/4)
+#define CMS_MSG_CONFIG (0x2008/4)
+#define CMS_MSG_ERR (0x2010/4)
+#define CMS_TRACE_CONFIG (0x2018/4)
+#define CMS_TRACE_BASE_ADDR (0x2020/4)
+#define CMS_TRACE_LIMIT_ADDR (0x2028/4)
+#define CMS_TRACE_CURRENT_ADDR (0x2030/4)
+#define CMS_MSG_ENDIAN_SWAP (0x2038/4)
-#define XLP_CMS_CPU_PUSHQ(node, core, thread, vc) \
+#define CMS_CPU_PUSHQ(node, core, thread, vc) \
(((node)<<10) | ((core)<<4) | ((thread)<<2) | ((vc)<<0))
-#define XLP_CMS_POPQ(node, queue) (((node)<<10) | (queue))
-#define XLP_CMS_IO_PUSHQ(node, queue) (((node)<<10) | (queue))
+#define CMS_POPQ(node, queue) (((node)<<10) | (queue))
+#define CMS_IO_PUSHQ(node, queue) (((node)<<10) | (queue))
-#define XLP_CMS_POPQ_QID(i) (128+(i))
-#define XLP_CMS_POPQ_MAXQID 255
-#define XLP_CMS_PCIE0_QID(i) (256+(i))
-#define XLP_CMS_PCIE0_MAXQID 257
-#define XLP_CMS_PCIE1_QID(i) (258+(i))
-#define XLP_CMS_PCIE1_MAXQID 259
-#define XLP_CMS_PCIE2_QID(i) (260+(i))
-#define XLP_CMS_PCIE2_MAXQID 261
-#define XLP_CMS_PCIE3_QID(i) (262+(i))
-#define XLP_CMS_PCIE3_MAXQID 263
-#define XLP_CMS_DTE_QID(i) (264+(i))
-#define XLP_CMS_DTE_MAXQID 267
-#define XLP_CMS_RSA_ECC_QID(i) (272+(i))
-#define XLP_CMS_RSA_ECC_MAXQID 280
-#define XLP_CMS_CRYPTO_QID(i) (281+(i))
-#define XLP_CMS_CRYPTO_MAXQID 296
+#define CMS_POPQ_QID(i) (128+(i))
+#define CMS_POPQ_MAXQID 255
+#define CMS_PCIE0_QID(i) (256+(i))
+#define CMS_PCIE0_MAXQID 257
+#define CMS_PCIE1_QID(i) (258+(i))
+#define CMS_PCIE1_MAXQID 259
+#define CMS_PCIE2_QID(i) (260+(i))
+#define CMS_PCIE2_MAXQID 261
+#define CMS_PCIE3_QID(i) (262+(i))
+#define CMS_PCIE3_MAXQID 263
+#define CMS_DTE_QID(i) (264+(i))
+#define CMS_DTE_MAXQID 267
+#define CMS_RSA_ECC_QID(i) (272+(i))
+#define CMS_RSA_ECC_MAXQID 280
+#define CMS_CRYPTO_QID(i) (281+(i))
+#define CMS_CRYPTO_MAXQID 296
/* TODO PCI header register 0x3C says CMP starts at 297(0x129) VERIFY */
-#define XLP_CMS_CMP_QID(i) (298+(i))
-#define XLP_CMS_CMP_MAXQID 305
-#define XLP_CMS_POE_QID(i) (384+(i))
-#define XLP_CMS_POE_MAXQID 391
-#define XLP_CMS_NAE_QID(i) (476+(i))
-#define XLP_CMS_NAE_MAXQID 1023
+#define CMS_CMP_QID(i) (298+(i))
+#define CMS_CMP_MAXQID 305
+#define CMS_POE_QID(i) (384+(i))
+#define CMS_POE_MAXQID 391
+#define CMS_NAE_QID(i) (476+(i))
+#define CMS_NAE_MAXQID 1023
-#define XLP_CMS_NAE_TX_VC_BASE 476
-#define XLP_CMS_NAE_TX_VC_LIMIT 999
-#define XLP_CMS_NAE_RX_VC_BASE 1000
-#define XLP_CMS_NAE_RX_VC_LIMIT 1019
+#define CMS_NAE_TX_VC_BASE 476
+#define CMS_NAE_TX_VC_LIMIT 999
+#define CMS_NAE_RX_VC_BASE 1000
+#define CMS_NAE_RX_VC_LIMIT 1019
-#define XLP_MAX_CMS_QUEUES 1024
+#define MAX_CMS_QUEUES 1024
/* FMN Level Interrupt Type */
-#define XLP_CMS_LVL_INTR_DISABLE 0
-#define XLP_CMS_LVL_LOW_WATERMARK 1
-#define XLP_CMS_LVL_HI_WATERMARK 2
+#define CMS_LVL_INTR_DISABLE 0
+#define CMS_LVL_LOW_WATERMARK 1
+#define CMS_LVL_HI_WATERMARK 2
/* FMN Level interrupt trigger values */
-#define XLP_CMS_QUEUE_NON_EMPTY 0
-#define XLP_CMS_QUEUE_QUARTER_FULL 1
-#define XLP_CMS_QUEUE_HALF_FULL 2
-#define XLP_CMS_QUEUE_THREE_QUARTER_FULL 3
-#define XLP_CMS_QUEUE_FULL 4
+#define CMS_QUEUE_NON_EMPTY 0
+#define CMS_QUEUE_QUARTER_FULL 1
+#define CMS_QUEUE_HALF_FULL 2
+#define CMS_QUEUE_THREE_QUARTER_FULL 3
+#define CMS_QUEUE_FULL 4
/* FMN Timer Interrupt Type */
-#define XLP_CMS_TIMER_INTR_DISABLE 0
-#define XLP_CMS_TIMER_CONSUMER 1
-#define XLP_CMS_TIMER_PRODUCER 1
+#define CMS_TIMER_INTR_DISABLE 0
+#define CMS_TIMER_CONSUMER 1
+#define CMS_TIMER_PRODUCER 1
/* FMN timer interrupt trigger values */
-#define XLP_CMS_TWO_POW_EIGHT_CYCLES 0
-#define XLP_CMS_TWO_POW_TEN_CYCLES 1
-#define XLP_CMS_TWO_POW_TWELVE_CYCLES 2
-#define XLP_CMS_TWO_POW_FOURTEEN_CYCLES 3
-#define XLP_CMS_TWO_POW_SIXTEEN_CYCLES 4
-#define XLP_CMS_TWO_POW_EIGHTTEEN_CYCLES 5
-#define XLP_CMS_TWO_POW_TWENTY_CYCLES 6
-#define XLP_CMS_TWO_POW_TWENTYTWO_CYCLES 7
+#define CMS_TWO_POW_EIGHT_CYCLES 0
+#define CMS_TWO_POW_TEN_CYCLES 1
+#define CMS_TWO_POW_TWELVE_CYCLES 2
+#define CMS_TWO_POW_FOURTEEN_CYCLES 3
+#define CMS_TWO_POW_SIXTEEN_CYCLES 4
+#define CMS_TWO_POW_EIGHTTEEN_CYCLES 5
+#define CMS_TWO_POW_TWENTY_CYCLES 6
+#define CMS_TWO_POW_TWENTYTWO_CYCLES 7
-#define XLP_CMS_QUEUE_ENA 1ULL
-#define XLP_CMS_QUEUE_DIS 0
-#define XLP_CMS_SPILL_ENA 1ULL
-#define XLP_CMS_SPILL_DIS 0
+#define CMS_QUEUE_ENA 1ULL
+#define CMS_QUEUE_DIS 0
+#define CMS_SPILL_ENA 1ULL
+#define CMS_SPILL_DIS 0
-#define XLP_CMS_MAX_VCPU_VC 4
+#define CMS_MAX_VCPU_VC 4
/* Each XLP chip can hold upto 32K messages on the chip itself */
-#define XLP_CMS_ON_CHIP_MESG_SPACE (32*1024)
-#define XLP_CMS_ON_CHIP_PER_QUEUE_SPACE \
- ((XLP_CMS_ON_CHIP_MESG_SPACE)/(XLP_MAX_CMS_QUEUES))
-#define XLP_CMS_MAX_ONCHIP_SEGMENTS 1024
-#define XLP_CMS_MAX_SPILL_SEGMENTS_PER_QUEUE 64
+#define CMS_ON_CHIP_MESG_SPACE (32*1024)
+#define CMS_ON_CHIP_PER_QUEUE_SPACE \
+ ((CMS_ON_CHIP_MESG_SPACE)/(MAX_CMS_QUEUES))
+#define CMS_MAX_ONCHIP_SEGMENTS 1024
+#define CMS_MAX_SPILL_SEGMENTS_PER_QUEUE 64
/* FMN Network error */
-#define XLP_CMS_ILLEGAL_DST_ERROR 0x100
-#define XLP_CMS_BIU_TIMEOUT_ERROR 0x080
-#define XLP_CMS_BIU_ERROR 0x040
-#define XLP_CMS_SPILL_FILL_UNCORRECT_ECC_ERROR 0x020
-#define XLP_CMS_SPILL_FILL_CORRECT_ECC_ERROR 0x010
-#define XLP_CMS_SPILL_UNCORRECT_ECC_ERROR 0x008
-#define XLP_CMS_SPILL_CORRECT_ECC_ERROR 0x004
-#define XLP_CMS_OUTPUTQ_UNCORRECT_ECC_ERROR 0x002
-#define XLP_CMS_OUTPUTQ_CORRECT_ECC_ERROR 0x001
+#define CMS_ILLEGAL_DST_ERROR 0x100
+#define CMS_BIU_TIMEOUT_ERROR 0x080
+#define CMS_BIU_ERROR 0x040
+#define CMS_SPILL_FILL_UNCORRECT_ECC_ERROR 0x020
+#define CMS_SPILL_FILL_CORRECT_ECC_ERROR 0x010
+#define CMS_SPILL_UNCORRECT_ECC_ERROR 0x008
+#define CMS_SPILL_CORRECT_ECC_ERROR 0x004
+#define CMS_OUTPUTQ_UNCORRECT_ECC_ERROR 0x002
+#define CMS_OUTPUTQ_CORRECT_ECC_ERROR 0x001
/* worst case, a single entry message consists of a 4 byte header
* and an 8-byte entry = 12 bytes in total
*/
-#define XLP_CMS_SINGLE_ENTRY_MSG_SIZE 12
+#define CMS_SINGLE_ENTRY_MSG_SIZE 12
/* total spill memory needed for one FMN queue */
-#define XLP_CMS_PER_QUEUE_SPILL_MEM(spilltotmsgs) \
- ((spilltotmsgs) * (XLP_CMS_SINGLE_ENTRY_MSG_SIZE))
+#define CMS_PER_QUEUE_SPILL_MEM(spilltotmsgs) \
+ ((spilltotmsgs) * (CMS_SINGLE_ENTRY_MSG_SIZE))
/* total spill memory needed */
-#define XLP_CMS_TOTAL_SPILL_MEM(spilltotmsgs) \
- ((XLP_CMS_PER_QUEUE_SPILL_MEM(spilltotmsgs)) * \
- (XLP_MAX_CMS_QUEUES))
+#define CMS_TOTAL_SPILL_MEM(spilltotmsgs) \
+ ((CMS_PER_QUEUE_SPILL_MEM(spilltotmsgs)) * \
+ (MAX_CMS_QUEUES))
/* total number of FMN messages possible in a queue */
-#define XLP_CMS_TOTAL_QUEUE_SIZE(spilltotmsgs) \
- ((spilltotmsgs) + (XLP_CMS_ON_CHIP_PER_QUEUE_SPACE))
+#define CMS_TOTAL_QUEUE_SIZE(spilltotmsgs) \
+ ((spilltotmsgs) + (CMS_ON_CHIP_PER_QUEUE_SPACE))
/* FMN Src station id's */
-#define XLP_CMS_CPU0_SRC_STID (0 << 4)
-#define XLP_CMS_CPU1_SRC_STID (1 << 4)
-#define XLP_CMS_CPU2_SRC_STID (2 << 4)
-#define XLP_CMS_CPU3_SRC_STID (3 << 4)
-#define XLP_CMS_CPU4_SRC_STID (4 << 4)
-#define XLP_CMS_CPU5_SRC_STID (5 << 4)
-#define XLP_CMS_CPU6_SRC_STID (6 << 4)
-#define XLP_CMS_CPU7_SRC_STID (7 << 4)
-#define XLP_CMS_PCIE0_SRC_STID 256
-#define XLP_CMS_PCIE1_SRC_STID 258
-#define XLP_CMS_PCIE2_SRC_STID 260
-#define XLP_CMS_PCIE3_SRC_STID 262
-#define XLP_CMS_DTE_SRC_STID 264
-#define XLP_CMS_RSA_ECC_SRC_STID 272
-#define XLP_CMS_CRYPTO_SRC_STID 281
-#define XLP_CMS_CMP_SRC_STID 298
-#define XLP_CMS_POE_SRC_STID 384
-#define XLP_CMS_NAE_SRC_STID 476
+#define CMS_CPU0_SRC_STID (0 << 4)
+#define CMS_CPU1_SRC_STID (1 << 4)
+#define CMS_CPU2_SRC_STID (2 << 4)
+#define CMS_CPU3_SRC_STID (3 << 4)
+#define CMS_CPU4_SRC_STID (4 << 4)
+#define CMS_CPU5_SRC_STID (5 << 4)
+#define CMS_CPU6_SRC_STID (6 << 4)
+#define CMS_CPU7_SRC_STID (7 << 4)
+#define CMS_PCIE0_SRC_STID 256
+#define CMS_PCIE1_SRC_STID 258
+#define CMS_PCIE2_SRC_STID 260
+#define CMS_PCIE3_SRC_STID 262
+#define CMS_DTE_SRC_STID 264
+#define CMS_RSA_ECC_SRC_STID 272
+#define CMS_CRYPTO_SRC_STID 281
+#define CMS_CMP_SRC_STID 298
+#define CMS_POE_SRC_STID 384
+#define CMS_NAE_SRC_STID 476
#if 0
-#define XLP_CMS_DEFAULT_CREDIT(cmstotstns,spilltotmsgs) \
- ((XLP_CMS_TOTAL_QUEUE_SIZE(spilltotmsgs)) / \
+#define CMS_DEFAULT_CREDIT(cmstotstns,spilltotmsgs) \
+ ((CMS_TOTAL_QUEUE_SIZE(spilltotmsgs)) / \
(cmstotstns))
#endif
-#define XLP_CMS_DEFAULT_CREDIT(cmstotstns,spilltotmsgs) 8
+#define CMS_DEFAULT_CREDIT(cmstotstns,spilltotmsgs) 8
/* POPQ related defines */
-#define XLP_CMS_POPQID_START 128
-#define XLP_CMS_POPQID_END 255
+#define CMS_POPQID_START 128
+#define CMS_POPQID_END 255
-#define XLP_CMS_INT_RCVD 0x800000000000000ULL
+#define CMS_INT_RCVD 0x800000000000000ULL
-#define nlm_rdreg_cms(b, r) nlm_read_reg64_xkseg(b,r)
-#define nlm_wreg_cms(b, r, v) nlm_write_reg64_xkseg(b,r,v)
-#define nlm_pcibase_cms(node) nlm_pcicfg_base(XLP_IO_CMS_OFFSET(node))
-#define nlm_regbase_cms(node) nlm_pcibar0_base_xkphys(nlm_pcibase_cms(node))
+#define nlm_read_cms_reg(b, r) nlm_read_reg64_xkphys(b,r)
+#define nlm_write_cms_reg(b, r, v) nlm_write_reg64_xkphys(b,r,v)
+#define nlm_get_cms_pcibase(node) nlm_pcicfg_base(XLP_IO_CMS_OFFSET(node))
+#define nlm_get_cms_regbase(node) nlm_xkphys_map_pcibar0(nlm_get_cms_pcibase(node))
enum fmn_swcode {
FMN_SWCODE_CPU0=1,
@@ -237,7 +238,7 @@ enum fmn_swcode {
extern uint64_t nlm_cms_spill_total_messages;
extern uint32_t nlm_cms_total_stations;
-extern uint32_t cms_onchip_seg_availability[XLP_CMS_ON_CHIP_PER_QUEUE_SPACE];
+extern uint32_t cms_onchip_seg_availability[CMS_ON_CHIP_PER_QUEUE_SPACE];
extern uint64_t cms_base_addr(int node);
extern int nlm_cms_verify_credit_config (int spill_en, int tot_credit);
diff --git a/sys/mips/nlm/hal/haldefs.h b/sys/mips/nlm/hal/haldefs.h
new file mode 100644
index 0000000000000..a8e13420dfcf6
--- /dev/null
+++ b/sys/mips/nlm/hal/haldefs.h
@@ -0,0 +1,437 @@
+/*-
+ * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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.
+ *
+ * NETLOGIC_BSD
+ * $FreeBSD$
+ */
+
+#ifndef __NLM_HAL_MMIO_H__
+#define __NLM_HAL_MMIO_H__
+
+/*
+ * This file contains platform specific memory mapped IO implementation
+ * and will provide a way to read 32/64 bit memory mapped registers in
+ * all ABIs
+ */
+
+/*
+ * For o32 compilation, we have to disable interrupts and enable KX bit to
+ * access 64 bit addresses or data.
+ *
+ * We need to disable interrupts because we save just the lower 32 bits of
+ * registers in interrupt handling. So if we get hit by an interrupt while
+ * using the upper 32 bits of a register, we lose.
+ */
+static inline uint32_t nlm_save_flags_kx(void)
+{
+ uint32_t sr = mips_rd_status();
+
+ mips_wr_status((sr & ~MIPS_SR_INT_IE) | MIPS_SR_KX);
+ return (sr);
+}
+
+static inline uint32_t nlm_save_flags_cop2(void)
+{
+ uint32_t sr = mips_rd_status();
+
+ mips_wr_status((sr & ~MIPS_SR_INT_IE) | MIPS_SR_COP_2_BIT);
+ return (sr);
+}
+
+static inline void nlm_restore_flags(uint32_t sr)
+{
+ mips_wr_status(sr);
+}
+
+static inline uint32_t
+nlm_load_word(uint64_t addr)
+{
+ volatile uint32_t *p = (volatile uint32_t *)(long)addr;
+
+ return *p;
+}
+
+static inline void
+nlm_store_word(uint64_t addr, uint32_t val)
+{
+ volatile uint32_t *p = (volatile uint32_t *)(long)addr;
+
+ *p = val;
+}
+
+#if defined(__mips_n64) || defined(__mips_n32)
+static inline uint64_t
+nlm_load_dword(volatile uint64_t addr)
+{
+ volatile uint64_t *p = (volatile uint64_t *)(long)addr;
+
+ return *p;
+}
+
+static inline void
+nlm_store_dword(volatile uint64_t addr, uint64_t val)
+{
+ volatile uint64_t *p = (volatile uint64_t *)(long)addr;
+
+ *p = val;
+}
+
+#else /* o32 */
+static inline uint64_t
+nlm_load_dword(uint64_t addr)
+{
+ volatile uint64_t *p = (volatile uint64_t *)(long)addr;
+ uint32_t valhi, vallo, sr;
+
+ sr = nlm_save_flags_kx();
+ __asm__ __volatile__(
+ ".set push\n\t"
+ ".set mips64\n\t"
+ "ld $8, 0(%2)\n\t"
+ "dsra32 %0, $8, 0\n\t"
+ "sll %1, $8, 0\n\t"
+ ".set pop\n"
+ : "=r"(valhi), "=r"(vallo)
+ : "r"(p)
+ : "$8");
+ nlm_restore_flags(sr);
+
+ return ((uint64_t)valhi << 32) | vallo;
+}
+
+static inline void
+nlm_store_dword(uint64_t addr, uint64_t val)
+{
+ volatile uint64_t *p = (volatile uint64_t *)(long)addr;
+ uint32_t valhi, vallo, sr;
+
+ valhi = val >> 32;
+ vallo = val & 0xffffffff;
+
+ sr = nlm_save_flags_kx();
+ __asm__ __volatile__(
+ ".set push\n\t"
+ ".set mips64\n\t"
+ "dsll32 $8, %1, 0\n\t"
+ "dsll32 $9, %2, 0\n\t" /* get rid of the */
+ "dsrl32 $9, $9, 0\n\t" /* sign extend */
+ "or $9, $9, $8\n\t"
+ "sd $9, 0(%0)\n\t"
+ ".set pop\n"
+ : : "r"(p), "r"(valhi), "r"(vallo)
+ : "$8", "$9", "memory");
+ nlm_restore_flags(sr);
+}
+#endif
+
+#if defined(__mips_n64)
+static inline uint64_t
+nlm_load_word_daddr(uint64_t addr)
+{
+ volatile uint32_t *p = (volatile uint32_t *)(long)addr;
+
+ return *p;
+}
+
+static inline void
+nlm_store_word_daddr(uint64_t addr, uint32_t val)
+{
+ volatile uint32_t *p = (volatile uint32_t *)(long)addr;
+
+ *p = val;
+}
+
+static inline uint64_t
+nlm_load_dword_daddr(uint64_t addr)
+{
+ volatile uint64_t *p = (volatile uint64_t *)(long)addr;
+
+ return *p;
+}
+
+static inline void
+nlm_store_dword_daddr(uint64_t addr, uint64_t val)
+{
+ volatile uint64_t *p = (volatile uint64_t *)(long)addr;
+
+ *p = val;
+}
+
+#elif defined(__mips_n32)
+
+static inline uint64_t
+nlm_load_word_daddr(uint64_t addr)
+{
+ uint32_t val;
+
+ __asm__ __volatile__(
+ ".set push\n\t"
+ ".set mips64\n\t"
+ "lw %0, 0(%1)\n\t"
+ ".set pop\n"
+ : "=r"(val)
+ : "r"(addr));
+
+ return val;
+}
+
+static inline void
+nlm_store_word_daddr(uint64_t addr, uint32_t val)
+{
+ __asm__ __volatile__(
+ ".set push\n\t"
+ ".set mips64\n\t"
+ "sw %0, 0(%1)\n\t"
+ ".set pop\n"
+ : : "r"(val), "r"(addr)
+ : "memory");
+}
+
+static inline uint64_t
+nlm_load_dword_daddr(uint64_t addr)
+{
+ uint64_t val;
+
+ __asm__ __volatile__(
+ ".set push\n\t"
+ ".set mips64\n\t"
+ "ld %0, 0(%1)\n\t"
+ ".set pop\n"
+ : "=r"(val)
+ : "r"(addr));
+ return val;
+}
+
+static inline void
+nlm_store_dword_daddr(uint64_t addr, uint64_t val)
+{
+ __asm__ __volatile__(
+ ".set push\n\t"
+ ".set mips64\n\t"
+ "sd %0, 0(%1)\n\t"
+ ".set pop\n"
+ : : "r"(val), "r"(addr)
+ : "memory");
+}
+
+#else /* o32 */
+static inline uint64_t
+nlm_load_word_daddr(uint64_t addr)
+{
+ uint32_t val, addrhi, addrlo, sr;
+
+ addrhi = addr >> 32;
+ addrlo = addr & 0xffffffff;
+
+ sr = nlm_save_flags_kx();
+ __asm__ __volatile__(
+ ".set push\n\t"
+ ".set mips64\n\t"
+ "dsll32 $8, %1, 0\n\t"
+ "dsll32 $9, %2, 0\n\t"
+ "dsrl32 $9, $9, 0\n\t"
+ "or $9, $9, $8\n\t"
+ "lw %0, 0($9)\n\t"
+ ".set pop\n"
+ : "=r"(val)
+ : "r"(addrhi), "r"(addrlo)
+ : "$8", "$9");
+ nlm_restore_flags(sr);
+
+ return val;
+
+}
+
+static inline void
+nlm_store_word_daddr(uint64_t addr, uint32_t val)
+{
+ uint32_t addrhi, addrlo, sr;
+
+ addrhi = addr >> 32;
+ addrlo = addr & 0xffffffff;
+
+ sr = nlm_save_flags_kx();
+ __asm__ __volatile__(
+ ".set push\n\t"
+ ".set mips64\n\t"
+ "dsll32 $8, %1, 0\n\t"
+ "dsll32 $9, %2, 0\n\t"
+ "dsrl32 $9, $9, 0\n\t"
+ "or $9, $9, $8\n\t"
+ "sw %0, 0($9)\n\t"
+ ".set pop\n"
+ : : "r"(val), "r"(addrhi), "r"(addrlo)
+ : "$8", "$9", "memory");
+ nlm_restore_flags(sr);
+}
+
+static inline uint64_t
+nlm_load_dword_daddr(uint64_t addr)
+{
+ uint32_t addrh, addrl, sr;
+ uint32_t valh, vall;
+
+ addrh = addr >> 32;
+ addrl = addr & 0xffffffff;
+
+ sr = nlm_save_flags_kx();
+ __asm__ __volatile__(
+ ".set push\n\t"
+ ".set mips64\n\t"
+ "dsll32 $8, %2, 0\n\t"
+ "dsll32 $9, %3, 0\n\t"
+ "dsrl32 $9, $9, 0\n\t"
+ "or $9, $9, $8\n\t"
+ "ld $8, 0($9)\n\t"
+ "dsra32 %0, $8, 0\n\t"
+ "sll %1, $8, 0\n\t"
+ ".set pop\n"
+ : "=r"(valh), "=r"(vall)
+ : "r"(addrh), "r"(addrl)
+ : "$8", "$9");
+ nlm_restore_flags(sr);
+
+ return ((uint64_t)valh << 32) | vall;
+}
+
+static inline void
+nlm_store_dword_daddr(uint64_t addr, uint64_t val)
+{
+ uint32_t addrh, addrl, sr;
+ uint32_t valh, vall;
+
+ addrh = addr >> 32;
+ addrl = addr & 0xffffffff;
+ valh = val >> 32;
+ vall = val & 0xffffffff;
+
+ sr = nlm_save_flags_kx();
+ __asm__ __volatile__(
+ ".set push\n\t"
+ ".set mips64\n\t"
+ "dsll32 $8, %2, 0\n\t"
+ "dsll32 $9, %3, 0\n\t"
+ "dsrl32 $9, $9, 0\n\t"
+ "or $9, $9, $8\n\t"
+ "dsll32 $8, %0, 0\n\t"
+ "dsll32 $10, %1, 0\n\t"
+ "dsrl32 $10, $10, 0\n\t"
+ "or $8, $8, $10\n\t"
+ "sd $8, 0($9)\n\t"
+ ".set pop\n"
+ : : "r"(valh), "r"(vall), "r"(addrh), "r"(addrl)
+ : "$8", "$9", "memory");
+ nlm_restore_flags(sr);
+}
+#endif /* __mips_n64 */
+
+static inline uint32_t
+nlm_read_reg(uint64_t base, uint32_t reg)
+{
+ volatile uint32_t *addr = (volatile uint32_t *)(long)base + reg;
+
+ return *addr;
+}
+
+static inline void
+nlm_write_reg(uint64_t base, uint32_t reg, uint32_t val)
+{
+ volatile uint32_t *addr = (volatile uint32_t *)(long)base + reg;
+
+ *addr = val;
+}
+
+static inline uint64_t
+nlm_read_reg64(uint64_t base, uint32_t reg)
+{
+ uint64_t addr = base + (reg >> 1) * sizeof(uint64_t);
+
+ return nlm_load_dword(addr);
+}
+
+static inline void
+nlm_write_reg64(uint64_t base, uint32_t reg, uint64_t val)
+{
+ uint64_t addr = base + (reg >> 1) * sizeof(uint64_t);
+
+ return nlm_store_dword(addr, val);
+}
+
+/*
+ * Routines to store 32/64 bit values to 64 bit addresses,
+ * used when going thru XKPHYS to access registers
+ */
+static inline uint32_t
+nlm_read_reg_xkphys(uint64_t base, uint32_t reg)
+{
+ uint64_t addr = base + reg * sizeof(uint32_t);
+
+ return nlm_load_word_daddr(addr);
+}
+
+static inline void
+nlm_write_reg_xkphys(uint64_t base, uint32_t reg, uint32_t val)
+{
+ uint64_t addr = base + reg * sizeof(uint32_t);
+ return nlm_store_word_daddr(addr, val);
+}
+
+static inline uint64_t
+nlm_read_reg64_xkphys(uint64_t base, uint32_t reg)
+{
+ uint64_t addr = base + (reg >> 1) * sizeof(uint64_t);
+
+ return nlm_load_dword_daddr(addr);
+}
+
+static inline void
+nlm_write_reg64_xkphys(uint64_t base, uint32_t reg, uint64_t val)
+{
+ uint64_t addr = base + (reg >> 1) * sizeof(uint64_t);
+
+ return nlm_store_dword_daddr(addr, val);
+}
+
+/* Location where IO base is mapped */
+extern uint64_t xlp_io_base;
+
+static inline uint64_t
+nlm_pcicfg_base(uint32_t devoffset)
+{
+ return xlp_io_base + devoffset;
+}
+
+static inline uint64_t
+nlm_xkphys_map_pcibar0(uint64_t pcibase)
+{
+ uint64_t paddr;
+
+ paddr = nlm_read_reg(pcibase, 0x4) & ~0xfu;
+ return (uint64_t)0x9000000000000000 | paddr;
+}
+
+#endif
diff --git a/sys/mips/nlm/hal/iomap.h b/sys/mips/nlm/hal/iomap.h
index e11dcdde0fb57..9f4a52c0a5161 100644
--- a/sys/mips/nlm/hal/iomap.h
+++ b/sys/mips/nlm/hal/iomap.h
@@ -25,82 +25,75 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
+ * NETLOGIC_BSD
* $FreeBSD$
- * NETLOGIC_BSD */
-
-#ifndef __NLM_IOMAP_H__
-#define __NLM_IOMAP_H__
-
-/**
-* @file_name xlpiomap.h
-* @author Netlogic Microsystems
-* @brief Basic definitions Netlogic XLP IO BASEs
-*/
-
-/* ----------------------------------
- * XLP RESET Physical Address Map
- * ----------------------------------
- * PCI ECFG : 0x18000000 - 0x1bffffff
- * PCI CFG : 0x1c000000 - 0x1cffffff
- * FLASH : 0x1fc00000 - 0x1fffffff
- * ----------------------------------
*/
+#ifndef __NLM_HAL_IOMAP_H__
+#define __NLM_HAL_IOMAP_H__
+
#define XLP_DEFAULT_IO_BASE 0x18000000
-#define XLP_DEFAULT_IO_BASE_KSEG1 0xb8000000
-#define XLP_IO_SIZE (64 << 20) /* Size of the ECFG Space */
+#define NMI_BASE 0xbfc00000
+#define XLP_IO_CLK 133333333
+
+#define XLP_PCIE_CFG_SIZE 0x1000 /* 4K */
+#define XLP_PCIE_DEV_BLK_SIZE (8 * XLP_PCIE_CFG_SIZE)
+#define XLP_PCIE_BUS_BLK_SIZE (256 * XLP_PCIE_DEV_BLK_SIZE)
+#define XLP_IO_SIZE (64 << 20) /* ECFG space size */
#define XLP_IO_PCI_HDRSZ 0x100
#define XLP_IO_DEV(node, dev) ((dev) + (node) * 8)
#define XLP_HDR_OFFSET(node, bus, dev, fn) (((bus) << 20) | \
((XLP_IO_DEV(node, dev)) << 15) | ((fn) << 12))
-#define XLP_IO_BRIDGE_OFFSET(node) XLP_HDR_OFFSET(node,0,0,0)
+#define XLP_IO_BRIDGE_OFFSET(node) XLP_HDR_OFFSET(node, 0, 0, 0)
/* coherent inter chip */
-#define XLP_IO_CIC0_OFFSET(node) XLP_HDR_OFFSET(node,0,0,1)
-#define XLP_IO_CIC1_OFFSET(node) XLP_HDR_OFFSET(node,0,0,2)
-#define XLP_IO_CIC2_OFFSET(node) XLP_HDR_OFFSET(node,0,0,3)
-#define XLP_IO_PIC_OFFSET(node) XLP_HDR_OFFSET(node,0,0,4)
+#define XLP_IO_CIC0_OFFSET(node) XLP_HDR_OFFSET(node, 0, 0, 1)
+#define XLP_IO_CIC1_OFFSET(node) XLP_HDR_OFFSET(node, 0, 0, 2)
+#define XLP_IO_CIC2_OFFSET(node) XLP_HDR_OFFSET(node, 0, 0, 3)
+#define XLP_IO_PIC_OFFSET(node) XLP_HDR_OFFSET(node, 0, 0, 4)
-#define XLP_IO_PCIE_OFFSET(node,i) XLP_HDR_OFFSET(node,0,1,i)
-#define XLP_IO_PCIE0_OFFSET(node) XLP_HDR_OFFSET(node,0,1,0)
-#define XLP_IO_PCIE1_OFFSET(node) XLP_HDR_OFFSET(node,0,1,1)
-#define XLP_IO_PCIE2_OFFSET(node) XLP_HDR_OFFSET(node,0,1,2)
-#define XLP_IO_PCIE3_OFFSET(node) XLP_HDR_OFFSET(node,0,1,3)
+#define XLP_IO_PCIE_OFFSET(node, i) XLP_HDR_OFFSET(node, 0, 1, i)
+#define XLP_IO_PCIE0_OFFSET(node) XLP_HDR_OFFSET(node, 0, 1, 0)
+#define XLP_IO_PCIE1_OFFSET(node) XLP_HDR_OFFSET(node, 0, 1, 1)
+#define XLP_IO_PCIE2_OFFSET(node) XLP_HDR_OFFSET(node, 0, 1, 2)
+#define XLP_IO_PCIE3_OFFSET(node) XLP_HDR_OFFSET(node, 0, 1, 3)
-#define XLP_IO_USB_OFFSET(node, i) XLP_HDR_OFFSET(node,0,2,i)
-#define XLP_IO_USB_EHCI0_OFFSET(node) XLP_HDR_OFFSET(node,0,2,0)
-#define XLP_IO_USB_OHCI0_OFFSET(node) XLP_HDR_OFFSET(node,0,2,1)
-#define XLP_IO_USB_OHCI1_OFFSET(node) XLP_HDR_OFFSET(node,0,2,2)
-#define XLP_IO_USB_EHCI1_OFFSET(node) XLP_HDR_OFFSET(node,0,2,3)
-#define XLP_IO_USB_OHCI2_OFFSET(node) XLP_HDR_OFFSET(node,0,2,4)
-#define XLP_IO_USB_OHCI3_OFFSET(node) XLP_HDR_OFFSET(node,0,2,5)
+#define XLP_IO_USB_OFFSET(node, i) XLP_HDR_OFFSET(node, 0, 2, i)
+#define XLP_IO_USB_EHCI0_OFFSET(node) XLP_HDR_OFFSET(node, 0, 2, 0)
+#define XLP_IO_USB_OHCI0_OFFSET(node) XLP_HDR_OFFSET(node, 0, 2, 1)
+#define XLP_IO_USB_OHCI1_OFFSET(node) XLP_HDR_OFFSET(node, 0, 2, 2)
+#define XLP_IO_USB_EHCI1_OFFSET(node) XLP_HDR_OFFSET(node, 0, 2, 3)
+#define XLP_IO_USB_OHCI2_OFFSET(node) XLP_HDR_OFFSET(node, 0, 2, 4)
+#define XLP_IO_USB_OHCI3_OFFSET(node) XLP_HDR_OFFSET(node, 0, 2, 5)
-#define XLP_IO_NAE_OFFSET(node) XLP_HDR_OFFSET(node,0,3,0)
-#define XLP_IO_POE_OFFSET(node) XLP_HDR_OFFSET(node,0,3,1)
+#define XLP_IO_NAE_OFFSET(node) XLP_HDR_OFFSET(node, 0, 3, 0)
+#define XLP_IO_POE_OFFSET(node) XLP_HDR_OFFSET(node, 0, 3, 1)
-#define XLP_IO_CMS_OFFSET(node) XLP_HDR_OFFSET(node,0,4,0)
+#define XLP_IO_CMS_OFFSET(node) XLP_HDR_OFFSET(node, 0, 4, 0)
-#define XLP_IO_DMA_OFFSET(node) XLP_HDR_OFFSET(node,0,5,1)
-#define XLP_IO_SEC_OFFSET(node) XLP_HDR_OFFSET(node,0,5,2)
-#define XLP_IO_CMP_OFFSET(node) XLP_HDR_OFFSET(node,0,5,3)
+#define XLP_IO_DMA_OFFSET(node) XLP_HDR_OFFSET(node, 0, 5, 1)
+#define XLP_IO_SEC_OFFSET(node) XLP_HDR_OFFSET(node, 0, 5, 2)
+#define XLP_IO_CMP_OFFSET(node) XLP_HDR_OFFSET(node, 0, 5, 3)
-#define XLP_IO_UART_OFFSET(node, i) XLP_HDR_OFFSET(node,0,6,i)
-#define XLP_IO_UART0_OFFSET(node) XLP_HDR_OFFSET(node,0,6,0)
-#define XLP_IO_UART1_OFFSET(node) XLP_HDR_OFFSET(node,0,6,1)
-#define XLP_IO_I2C_OFFSET(node, i) XLP_HDR_OFFSET(node,0,6,2+i)
-#define XLP_IO_I2C0_OFFSET(node) XLP_HDR_OFFSET(node,0,6,2)
-#define XLP_IO_I2C1_OFFSET(node) XLP_HDR_OFFSET(node,0,6,3)
-#define XLP_IO_GPIO_OFFSET(node) XLP_HDR_OFFSET(node,0,6,4)
+#define XLP_IO_UART_OFFSET(node, i) XLP_HDR_OFFSET(node, 0, 6, i)
+#define XLP_IO_UART0_OFFSET(node) XLP_HDR_OFFSET(node, 0, 6, 0)
+#define XLP_IO_UART1_OFFSET(node) XLP_HDR_OFFSET(node, 0, 6, 1)
+#define XLP_IO_I2C_OFFSET(node, i) XLP_HDR_OFFSET(node, 0, 6, 2 + i)
+#define XLP_IO_I2C0_OFFSET(node) XLP_HDR_OFFSET(node, 0, 6, 2)
+#define XLP_IO_I2C1_OFFSET(node) XLP_HDR_OFFSET(node, 0, 6, 3)
+#define XLP_IO_GPIO_OFFSET(node) XLP_HDR_OFFSET(node, 0, 6, 4)
/* system management */
-#define XLP_IO_SYS_OFFSET(node) XLP_HDR_OFFSET(node,0,6,5)
-#define XLP_IO_JTAG_OFFSET(node) XLP_HDR_OFFSET(node,0,6,6)
+#define XLP_IO_SYS_OFFSET(node) XLP_HDR_OFFSET(node, 0, 6, 5)
+#define XLP_IO_JTAG_OFFSET(node) XLP_HDR_OFFSET(node, 0, 6, 6)
-#define XLP_IO_NOR_OFFSET(node) XLP_HDR_OFFSET(node,0,7,0)
-#define XLP_IO_NAND_OFFSET(node) XLP_HDR_OFFSET(node,0,7,1)
-#define XLP_IO_SPI_OFFSET(node) XLP_HDR_OFFSET(node,0,7,2)
+#define XLP_IO_NOR_OFFSET(node) XLP_HDR_OFFSET(node, 0, 7, 0)
+#define XLP_IO_NAND_OFFSET(node) XLP_HDR_OFFSET(node, 0, 7, 1)
+#define XLP_IO_SPI_OFFSET(node) XLP_HDR_OFFSET(node, 0, 7, 2)
/* SD flash */
-#define XLP_IO_SD_OFFSET(node) XLP_HDR_OFFSET(node,0,7,3)
-#define XLP_IO_MMC_OFFSET(node, slot) ((XLP_IO_SD_OFFSET(node))+(slot*0x100)+XLP_IO_PCI_HDRSZ)
+#define XLP_IO_SD_OFFSET(node) XLP_HDR_OFFSET(node, 0, 7, 3)
+#define XLP_IO_MMC_OFFSET(node, slot) \
+ ((XLP_IO_SD_OFFSET(node))+(slot*0x100)+XLP_IO_PCI_HDRSZ)
+
/* PCI config header register id's */
#define XLP_PCI_CFGREG0 0x00
#define XLP_PCI_CFGREG1 0x01
@@ -125,113 +118,35 @@
#define XLP_PCI_UCODEINFO_REG 0x3e
#define XLP_PCI_SBB_WT_REG 0x3f
-#if !defined(LOCORE) && !defined(__ASSEMBLY__)
-
-#ifndef __NLM_NLMIO_H__
-#error iomap.h needs mmio.h to be included
-#endif
-
-static __inline__ uint32_t
-nlm_read_reg_kseg(uint64_t base, uint32_t reg)
-{
- volatile uint32_t *addr = (volatile uint32_t *)(intptr_t)base + reg;
-
- return (*addr);
-}
-
-static __inline__ void
-nlm_write_reg_kseg(uint64_t base, uint32_t reg, uint32_t val)
-{
- volatile uint32_t *addr = (volatile uint32_t *)(intptr_t)base + reg;
-
- *addr = val;
-}
-
-static __inline__ uint64_t
-nlm_read_reg64_kseg(uint64_t base, uint32_t reg)
-{
- volatile uint64_t *addr = (volatile uint64_t *)(intptr_t)base + (reg >> 1);
-
- return (nlm_load_dword(addr));
-}
-
-static __inline__ void
-nlm_write_reg64_kseg(uint64_t base, uint32_t reg, uint64_t val)
-{
- volatile uint64_t *addr = (volatile uint64_t *)(intptr_t)base + (reg >> 1);
+/* PCI IDs for SoC device */
+#define PCI_VENDOR_NETLOGIC 0x184e
- return (nlm_store_dword(addr, val));
-}
-
-/*
- * Routines to store 32/64 bit values to 64 bit addresses,
- * used when going thru XKPHYS to access registers
- */
-static __inline__ uint32_t
-nlm_read_reg_xkseg(uint64_t base, uint32_t reg)
-{
- uint64_t addr = base + reg * sizeof(uint32_t);
-
- return (nlm_load_word_daddr(addr));
-}
-
-static __inline__ void
-nlm_write_reg_xkseg(uint64_t base, uint32_t reg, uint32_t val)
-{
- uint64_t addr = base + reg * sizeof(uint32_t);
-
- return (nlm_store_word_daddr(addr, val));
-}
-
-static __inline__ uint64_t
-nlm_read_reg64_xkseg(uint64_t base, uint32_t reg)
-{
- uint64_t addr = base + (reg >> 1) * sizeof(uint64_t);
-
- return (nlm_load_dword_daddr(addr));
-}
-
-static __inline__ void
-nlm_write_reg64_xkseg(uint64_t base, uint32_t reg, uint64_t val)
-{
- uint64_t addr = base + (reg >> 1) * sizeof(uint64_t);
-
- return (nlm_store_dword_daddr(addr, val));
-}
-
-/* Location where IO base is mapped */
-extern uint64_t nlm_pcicfg_baseaddr;
-
-static __inline__ uint64_t
-nlm_pcicfg_base(uint32_t devoffset)
-{
- return (nlm_pcicfg_baseaddr + devoffset);
-}
-
-static __inline__ uint64_t
-nlm_pcibar0_base_xkphys(uint64_t pcibase)
-{
- uint64_t paddr;
-
- paddr = nlm_read_reg_kseg(pcibase, XLP_PCI_CFGREG4) & ~0xfu;
- return (0x9000000000000000 | paddr);
-}
-#define nlm_pci_rdreg(b, r) nlm_read_reg_kseg(b, r)
-#define nlm_pci_wreg(b, r, v) nlm_write_reg_kseg(b, r, v)
-
-#endif /* !LOCORE && !__ASSEMBLY__*/
+#define PCI_DEVICE_ID_NLM_ROOT 0x1001
+#define PCI_DEVICE_ID_NLM_ICI 0x1002
+#define PCI_DEVICE_ID_NLM_PIC 0x1003
+#define PCI_DEVICE_ID_NLM_PCIE 0x1004
+#define PCI_DEVICE_ID_NLM_EHCI 0x1007
+#define PCI_DEVICE_ID_NLM_ILK 0x1008
+#define PCI_DEVICE_ID_NLM_NAE 0x1009
+#define PCI_DEVICE_ID_NLM_POE 0x100A
+#define PCI_DEVICE_ID_NLM_FMN 0x100B
+#define PCI_DEVICE_ID_NLM_RAID 0x100D
+#define PCI_DEVICE_ID_NLM_SAE 0x100D
+#define PCI_DEVICE_ID_NLM_RSA 0x100E
+#define PCI_DEVICE_ID_NLM_CMP 0x100F
+#define PCI_DEVICE_ID_NLM_UART 0x1010
+#define PCI_DEVICE_ID_NLM_I2C 0x1011
+#define PCI_DEVICE_ID_NLM_NOR 0x1015
+#define PCI_DEVICE_ID_NLM_NAND 0x1016
+#define PCI_DEVICE_ID_NLM_MMC 0x1018
+#if !defined(LOCORE) && !defined(__ASSEMBLY__)
-/* COMPAT stuff - TODO remove */
-#define bit_set(p, m) ((p) |= (m))
-#define bit_clear(p, m) ((p) &= ~(m))
-#define bit_get(p,m) ((p) & (m))
-#define BIT(x) (0x01 << (x))
+#define nlm_read_pci_reg(b, r) nlm_read_reg(b, r)
+#define nlm_write_pci_reg(b, r, v) nlm_write_reg(b, r, v)
-#define XLP_MAX_NODES 4
-#define XLP_MAX_CORES 8
-#define XLP_MAX_THREADS 4
-#define XLP_CACHELINE_SIZE 64
-#define XLP_NUM_NODES 1 /* we support only one now */
+extern uint64_t xlp_sys_base;
+extern uint64_t xlp_pic_base;
+#endif /* !LOCORE or !__ASSEMBLY */
-#endif
+#endif /* __NLM_HAL_IOMAP_H__ */
diff --git a/sys/mips/nlm/hal/mips-extns.h b/sys/mips/nlm/hal/mips-extns.h
index 7851b1b18632a..839aa7313b08a 100644
--- a/sys/mips/nlm/hal/mips-extns.h
+++ b/sys/mips/nlm/hal/mips-extns.h
@@ -25,8 +25,9 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
+ * NETLOGIC_BSD
* $FreeBSD$
- * NETLOGIC_BSD */
+ */
#ifndef __NLM_MIPS_EXTNS_H__
#define __NLM_MIPS_EXTNS_H__
@@ -91,110 +92,183 @@ static __inline__ uint64_t nlm_swapd(int32_t *loc, uint64_t val)
}
#endif
+/*
+ * Atomic increment a unsigned int
+ */
+static __inline unsigned int
+nlm_ldaddwu(unsigned int value, unsigned int *addr)
+{
+ __asm__ __volatile__(
+ ".set push\n"
+ ".set noreorder\n"
+ "move $8, %2\n"
+ "move $9, %3\n"
+ ".word 0x71280011\n" /* ldaddwu $8, $9 */
+ "move %0, $8\n"
+ ".set pop\n"
+ : "=&r"(value), "+m"(*addr)
+ : "0"(value), "r" ((unsigned long)addr)
+ : "$8", "$9");
+
+ return (value);
+}
+/*
+ * 32 bit read write for c0
+ */
+#define read_c0_register32(reg, sel) \
+({ \
+ uint32_t __rv; \
+ __asm__ __volatile__( \
+ ".set push\n\t" \
+ ".set mips32\n\t" \
+ "mfc0 %0, $%1, %2\n\t" \
+ ".set pop\n" \
+ : "=r" (__rv) : "i" (reg), "i" (sel) ); \
+ __rv; \
+ })
+
+#define write_c0_register32(reg, sel, value) \
+ __asm__ __volatile__( \
+ ".set push\n\t" \
+ ".set mips32\n\t" \
+ "mtc0 %0, $%1, %2\n\t" \
+ ".set pop\n" \
+ : : "r" (value), "i" (reg), "i" (sel) );
+
#if defined(__mips_n64) || defined(__mips_n32)
-static __inline uint64_t
-nlm_mfcr(uint32_t reg)
+/*
+ * On 64 bit compilation, the operations are simple
+ */
+#define read_c0_register64(reg, sel) \
+({ \
+ uint64_t __rv; \
+ __asm__ __volatile__( \
+ ".set push\n\t" \
+ ".set mips64\n\t" \
+ "dmfc0 %0, $%1, %2\n\t" \
+ ".set pop\n" \
+ : "=r" (__rv) : "i" (reg), "i" (sel) ); \
+ __rv; \
+ })
+
+#define write_c0_register64(reg, sel, value) \
+ __asm__ __volatile__( \
+ ".set push\n\t" \
+ ".set mips64\n\t" \
+ "dmtc0 %0, $%1, %2\n\t" \
+ ".set pop\n" \
+ : : "r" (value), "i" (reg), "i" (sel) );
+#else /* ! (defined(__mips_n64) || defined(__mips_n32)) */
+
+/*
+ * 32 bit compilation, 64 bit values has to split
+ */
+#define read_c0_register64(reg, sel) \
+({ \
+ uint32_t __high, __low; \
+ __asm__ __volatile__( \
+ ".set push\n\t" \
+ ".set noreorder\n\t" \
+ ".set mips64\n\t" \
+ "dmfc0 $8, $%2, %3\n\t" \
+ "dsra32 %0, $8, 0\n\t" \
+ "sll %1, $8, 0\n\t" \
+ ".set pop\n" \
+ : "=r"(__high), "=r"(__low): "i"(reg), "i"(sel) \
+ : "$8"); \
+ ((uint64_t)__high << 32) | __low; \
+})
+
+#define write_c0_register64(reg, sel, value) \
+do { \
+ uint32_t __high = value >> 32; \
+ uint32_t __low = value & 0xffffffff; \
+ __asm__ __volatile__( \
+ ".set push\n\t" \
+ ".set noreorder\n\t" \
+ ".set mips64\n\t" \
+ "dsll32 $8, %1, 0\n\t" \
+ "dsll32 $9, %0, 0\n\t" \
+ "dsrl32 $8, $8, 0\n\t" \
+ "or $8, $8, $9\n\t" \
+ "dmtc0 $8, $%2, %3\n\t" \
+ ".set pop" \
+ :: "r"(__high), "r"(__low), "i"(reg), "i"(sel) \
+ :"$8", "$9"); \
+} while(0)
+
+#endif
+/* functions to write to and read from the extended
+ * cp0 registers.
+ * EIRR : Extended Interrupt Request Register
+ * cp0 register 9 sel 6
+ * bits 0...7 are same as cause register 8...15
+ * EIMR : Extended Interrupt Mask Register
+ * cp0 register 9 sel 7
+ * bits 0...7 are same as status register 8...15
+ */
+static __inline uint64_t
+nlm_read_c0_eirr(void)
{
- uint64_t res;
- __asm__ __volatile__(
- ".set push\n\t"
- ".set noreorder\n\t"
- "move $9, %1\n\t"
- ".word 0x71280018\n\t" /* mfcr $8, $9 */
- "move %0, $8\n\t"
- ".set pop\n"
- : "=r" (res) : "r"(reg)
- : "$8", "$9"
- );
- return (res);
+ return (read_c0_register64(9, 6));
}
static __inline void
-nlm_mtcr(uint32_t reg, uint64_t value)
+nlm_write_c0_eirr(uint64_t val)
{
- __asm__ __volatile__(
- ".set push\n\t"
- ".set noreorder\n\t"
- "move $8, %0\n"
- "move $9, %1\n"
- ".word 0x71280019\n" /* mtcr $8, $9 */
- ".set pop\n"
- :
- : "r" (value), "r" (reg)
- : "$8", "$9"
- );
-}
-#else /* !(defined(__mips_n64) || defined(__mips_n32)) */
+ write_c0_register64(9, 6, val);
+}
-static __inline__ uint64_t
-nlm_mfcr(uint32_t reg)
+static __inline uint64_t
+nlm_read_c0_eimr(void)
{
- uint64_t hi;
- uint64_t lo;
- __asm__ __volatile__ (
- ".set push\n"
- ".set mips64\n"
- "move $8, %2\n"
- ".word 0x71090018\n"
- "nop \n"
- "dsra32 %0, $9, 0\n"
- "sll %1, $9, 0\n"
- ".set pop\n"
- : "=r"(hi), "=r"(lo)
- : "r"(reg) : "$8", "$9");
+ return (read_c0_register64(9, 7));
+}
- return (((uint64_t)hi) << 32) | lo;
+static __inline void
+nlm_write_c0_eimr(uint64_t val)
+{
+
+ write_c0_register64(9, 7, val);
}
-static __inline__ void
-nlm_mtcr(uint32_t reg, uint64_t val)
+static __inline__ uint32_t
+nlm_read_c0_ebase(void)
{
- uint32_t hi, lo;
- hi = val >> 32;
- lo = val & 0xffffffff;
- __asm__ __volatile__ (
- ".set push\n"
- ".set mips64\n"
- "move $9, %0\n"
- "dsll32 $9, %1, 0\n"
- "dsll32 $8, %0, 0\n"
- "dsrl32 $9, $9, 0\n"
- "or $9, $9, $8\n"
- "move $8, %2\n"
- ".word 0x71090019\n"
- "nop \n"
- ".set pop\n"
- ::"r"(hi), "r"(lo), "r"(reg)
- : "$8", "$9");
+ return (read_c0_register32(15, 1));
}
-#endif /* (defined(__mips_n64) || defined(__mips_n32)) */
-/* dcrc2 */
-/* XLP additional instructions */
+static __inline__ int
+nlm_nodeid(void)
+{
+ return (nlm_read_c0_ebase() >> 5) & 0x3;
+}
-/*
- * Atomic increment a unsigned int
- */
-static __inline unsigned int
-nlm_ldaddwu(unsigned int value, unsigned int *addr)
+static __inline__ int
+nlm_cpuid(void)
{
- __asm__ __volatile__(
- ".set push\n"
- ".set noreorder\n"
- "move $8, %2\n"
- "move $9, %3\n"
- ".word 0x71280011\n" /* ldaddwu $8, $9 */
- "move %0, $8\n"
- ".set pop\n"
- : "=&r"(value), "+m"(*addr)
- : "0"(value), "r" ((unsigned long)addr)
- : "$8", "$9");
+ return nlm_read_c0_ebase() & 0x1f;
+}
- return (value);
+static __inline__ int
+nlm_threadid(void)
+{
+ return nlm_read_c0_ebase() & 0x3;
+}
+
+static __inline__ int
+nlm_coreid(void)
+{
+ return (nlm_read_c0_ebase() >> 2) & 0x7;
}
#endif
+
+#define XLP_MAX_NODES 4
+#define XLP_MAX_CORES 8
+#define XLP_MAX_THREADS 4
+
#endif
diff --git a/sys/mips/nlm/hal/mmio.h b/sys/mips/nlm/hal/mmio.h
deleted file mode 100644
index a19a8673e9e69..0000000000000
--- a/sys/mips/nlm/hal/mmio.h
+++ /dev/null
@@ -1,338 +0,0 @@
-/*-
- * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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$
- * NETLOGIC_BSD */
-
-#ifndef __NLM_NLMIO_H__
-#define __NLM_NLMIO_H__
-
-#if !defined(__mips_n32) && !defined(__mips_n64)
-/*
- * For o32 compilation, we have to disable interrupts and enable KX bit to
- * access 64 bit addresses or data.
- *
- * We need to disable interrupts because we save just the lower 32 bits of
- * registers in interrupt handling. So if we get hit by an interrupt while
- * using the upper 32 bits of a register, we lose.
- */
-static __inline__ uint32_t nlm_enable_kx(void)
-{
- uint32_t sr;
-
- __asm__ __volatile__(
- "mfc0 %0, $12 \n\t" /* read status reg */
- "move $8, %0 \n\t"
- "ori $8, $8, 0x81 \n\t" /* set KX, and IE */
- "xori $8, $8, 0x1 \n\t" /* flip IE */
- "mtc0 $8, $12 \n\t" /* update status reg */
- : "=r"(sr)
- : : "$8");
-
- return (sr);
-}
-
-static __inline__ void nlm_restore_kx(uint32_t sr)
-{
- __asm__ __volatile__("mtc0 %0, $12" : : "r"(sr));
-}
-#endif
-
-static __inline__ uint32_t
-nlm_load_word(volatile uint32_t *addr)
-{
- return (*addr);
-}
-
-static __inline__ void
-nlm_store_word(volatile uint32_t *addr, uint32_t val)
-{
- *addr = val;
-}
-
-#if defined(__mips_n64) || defined(__mips_n32)
-static __inline__ uint64_t
-nlm_load_dword(volatile uint64_t *addr)
-{
- return (*addr);
-}
-
-static __inline__ void
-nlm_store_dword(volatile uint64_t *addr, uint64_t val)
-{
- *addr = val;
-}
-
-#else /* o32 */
-static __inline__ uint64_t
-nlm_load_dword(volatile uint64_t *addr)
-{
- uint32_t valhi, vallo, sr;
-
- sr = nlm_enable_kx();
- __asm__ __volatile__(
- ".set push \n\t"
- ".set mips64 \n\t"
- "ld $8, 0(%2) \n\t"
- "dsra32 %0, $8, 0 \n\t"
- "sll %1, $8, 0 \n\t"
- ".set pop \n"
- : "=r"(valhi), "=r"(vallo)
- : "r"(addr)
- : "$8" );
- nlm_restore_kx(sr);
-
- return (((uint64_t)valhi << 32) | vallo);
-}
-
-static __inline__ void
-nlm_store_dword(volatile uint64_t *addr, uint64_t val)
-{
- uint32_t valhi, vallo, sr;
-
- valhi = val >> 32;
- vallo = val & 0xffffffff;
-
- sr = nlm_enable_kx();
- __asm__ __volatile__(
- ".set push \n\t"
- ".set mips64 \n\t"
- "dsll32 $8, %1, 0 \n\t"
- "dsll32 $9, %2, 0 \n\t" /* get rid of the */
- "dsrl32 $9, $9, 0 \n\t" /* sign extend */
- "or $9, $9, $8 \n\t"
- "sd $9, 0(%0) \n\t"
- ".set pop \n"
- : : "r"(addr), "r"(valhi), "r"(vallo)
- : "$8", "$9", "memory");
- nlm_restore_kx(sr);
-}
-#endif
-
-#if defined(__mips_n64)
-static __inline__ uint64_t
-nlm_load_word_daddr(uint64_t addr)
-{
- volatile uint32_t *p = (volatile uint32_t *)(intptr_t)addr;
-
- return (*p);
-}
-
-static __inline__ void
-nlm_store_word_daddr(uint64_t addr, uint32_t val)
-{
- volatile uint32_t *p = (volatile uint32_t *)(intptr_t)addr;
-
- *p = val;
-}
-
-static __inline__ uint64_t
-nlm_load_dword_daddr(uint64_t addr)
-{
- volatile uint64_t *p = (volatile uint64_t *)(intptr_t)addr;
-
- return (*p);
-}
-
-static __inline__ void
-nlm_store_dword_daddr(uint64_t addr, uint64_t val)
-{
- volatile uint64_t *p = (volatile uint64_t *)(intptr_t)addr;
-
- *p = val;
-}
-
-#elif defined(__mips_n32)
-
-static __inline__ uint64_t
-nlm_load_word_daddr(uint64_t addr)
-{
- uint32_t val;
-
- __asm__ __volatile__(
- ".set push \n\t"
- ".set mips64 \n\t"
- "lw %0, 0(%1) \n\t"
- ".set pop \n"
- : "=r"(val)
- : "r"(addr));
-
- return (val);
-}
-
-static __inline__ void
-nlm_store_word_daddr(uint64_t addr, uint32_t val)
-{
- __asm__ __volatile__(
- ".set push \n\t"
- ".set mips64 \n\t"
- "sw %0, 0(%1) \n\t"
- ".set pop \n"
- : : "r"(val), "r"(addr)
- : "memory");
-}
-
-static __inline__ uint64_t
-nlm_load_dword_daddr(uint64_t addr)
-{
- uint64_t val;
-
- __asm__ __volatile__(
- ".set push \n\t"
- ".set mips64 \n\t"
- "ld %0, 0(%1) \n\t"
- ".set pop \n"
- : "=r"(val)
- : "r"(addr));
- return (val);
-}
-
-static __inline__ void
-nlm_store_dword_daddr(uint64_t addr, uint64_t val)
-{
- __asm__ __volatile__(
- ".set push \n\t"
- ".set mips64 \n\t"
- "sd %0, 0(%1) \n\t"
- ".set pop \n"
- : : "r"(val), "r"(addr)
- : "memory");
-}
-
-#else /* o32 */
-static __inline__ uint64_t
-nlm_load_word_daddr(uint64_t addr)
-{
- uint32_t val, addrhi, addrlo, sr;
-
- addrhi = addr >> 32;
- addrlo = addr & 0xffffffff;
-
- sr = nlm_enable_kx();
- __asm__ __volatile__(
- ".set push \n\t"
- ".set mips64 \n\t"
- "dsll32 $8, %1, 0 \n\t"
- "dsll32 $9, %2, 0 \n\t" /* get rid of the */
- "dsrl32 $9, $9, 0 \n\t" /* sign extend */
- "or $9, $9, $8 \n\t"
- "lw %0, 0($9) \n\t"
- ".set pop \n"
- : "=r"(val)
- : "r"(addrhi), "r"(addrlo)
- : "$8", "$9");
- nlm_restore_kx(sr);
-
- return (val);
-
-}
-
-static __inline__ void
-nlm_store_word_daddr(uint64_t addr, uint32_t val)
-{
- uint32_t addrhi, addrlo, sr;
-
- addrhi = addr >> 32;
- addrlo = addr & 0xffffffff;
-
- sr = nlm_enable_kx();
- __asm__ __volatile__(
- ".set push \n\t"
- ".set mips64 \n\t"
- "dsll32 $8, %1, 0 \n\t"
- "dsll32 $9, %2, 0 \n\t" /* get rid of the */
- "dsrl32 $9, $9, 0 \n\t" /* sign extend */
- "or $9, $9, $8 \n\t"
- "sw %0, 0($9) \n\t"
- ".set pop \n"
- :: "r"(val), "r"(addrhi), "r"(addrlo)
- : "$8", "$9", "memory");
- nlm_restore_kx(sr);
-}
-
-static __inline__ uint64_t
-nlm_load_dword_daddr(uint64_t addr)
-{
- uint32_t addrh, addrl, sr;
- uint32_t valh, vall;
-
- addrh = addr >> 32;
- addrl = addr & 0xffffffff;
-
- sr = nlm_enable_kx();
- __asm__ __volatile__(
- ".set push \n\t"
- ".set mips64 \n\t"
- "dsll32 $8, %2, 0 \n\t"
- "dsll32 $9, %3, 0 \n\t" /* get rid of the */
- "dsrl32 $9, $9, 0 \n\t" /* sign extend */
- "or $9, $9, $8 \n\t"
- "ld $8, 0($9) \n\t"
- "dsra32 %0, $8, 0 \n\t"
- "sll %1, $8, 0 \n\t"
- ".set pop \n"
- : "=r"(valh), "=r"(vall)
- : "r"(addrh), "r"(addrl)
- : "$8", "$9");
- nlm_restore_kx(sr);
-
- return (((uint64_t)valh << 32) | vall);
-}
-
-static __inline__ void
-nlm_store_dword_daddr(uint64_t addr, uint64_t val)
-{
- uint32_t addrh, addrl, sr;
- uint32_t valh, vall;
-
- addrh = addr >> 32;
- addrl = addr & 0xffffffff;
- valh = val >> 32;
- vall = val & 0xffffffff;
-
- sr = nlm_enable_kx();
- __asm__ __volatile__(
- ".set push \n\t"
- ".set mips64 \n\t"
- "dsll32 $8, %2, 0 \n\t"
- "dsll32 $9, %3, 0 \n\t" /* get rid of the */
- "dsrl32 $9, $9, 0 \n\t" /* sign extend */
- "or $9, $9, $8 \n\t"
- "dsll32 $8, %0, 0 \n\t"
- "dsll32 $10, %1, 0 \n\t" /* get rid of the */
- "dsrl32 $10, $10, 0 \n\t" /* sign extend */
- "or $8, $8, $10 \n\t"
- "sd $8, 0($9) \n\t"
- ".set pop \n"
- : : "r"(valh), "r"(vall), "r"(addrh), "r"(addrl)
- : "$8", "$9", "memory");
- nlm_restore_kx(sr);
-}
-
-#endif /* __mips_n64 */
-
-#endif
diff --git a/sys/mips/nlm/hal/mmu.h b/sys/mips/nlm/hal/mmu.h
index a620727531987..ebb4b5d67033e 100644
--- a/sys/mips/nlm/hal/mmu.h
+++ b/sys/mips/nlm/hal/mmu.h
@@ -25,44 +25,66 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
+ * NETLOGIC_BSD
* $FreeBSD$
- * NETLOGIC_BSD */
+ */
#ifndef __XLP_MMU_H__
#define __XLP_MMU_H__
-#include <mips/nlm/hal/cop0.h>
#include <mips/nlm/hal/mips-extns.h>
-#define XLP_MMU_SETUP_REG 0x400
-#define XLP_MMU_LFSRSEED_REG 0x401
-#define XLP_MMU_HPW_NUM_PAGE_LVL_REG 0x410
-#define XLP_MMU_PGWKR_PGDBASE_REG 0x411
-#define XLP_MMU_PGWKR_PGDSHFT_REG 0x412
-#define XLP_MMU_PGWKR_PGDMASK_REG 0x413
-#define XLP_MMU_PGWKR_PUDSHFT_REG 0x414
-#define XLP_MMU_PGWKR_PUDMASK_REG 0x415
-#define XLP_MMU_PGWKR_PMDSHFT_REG 0x416
-#define XLP_MMU_PGWKR_PMDMASK_REG 0x417
-#define XLP_MMU_PGWKR_PTESHFT_REG 0x418
-#define XLP_MMU_PGWKR_PTEMASK_REG 0x419
+static __inline__ uint32_t
+nlm_read_c0_config6(void)
+{
+ uint32_t rv;
+
+ __asm__ __volatile__ (
+ ".set push\n"
+ ".set mips64\n"
+ "mfc0 %0, $16, 6\n"
+ ".set pop\n"
+ : "=r" (rv));
+
+ return rv;
+}
-typedef struct hw_pagewalker {
- int pgd_present;
- int pud_present;
- int pmd_present;
- int pte_present;
- uint64_t pgd_baseaddr;
- uint32_t pgd_shift;
- uint32_t pgd_mask;
- uint32_t pud_shift;
- uint32_t pud_mask;
- uint32_t pmd_shift;
- uint32_t pmd_mask;
- uint32_t pte_shift;
- uint32_t pte_mask;
-} nlm_pagewalker;
+static __inline__ void
+nlm_write_c0_config6(uint32_t value)
+{
+ __asm__ __volatile__ (
+ ".set push\n"
+ ".set mips64\n"
+ "mtc0 %0, $16, 6\n"
+ ".set pop\n"
+ : : "r" (value));
+}
+
+static __inline__ uint32_t
+nlm_read_c0_config7(void)
+{
+ uint32_t rv;
+ __asm__ __volatile__ (
+ ".set push\n"
+ ".set mips64\n"
+ "mfc0 %0, $16, 7\n"
+ ".set pop\n"
+ : "=r" (rv));
+
+ return rv;
+}
+
+static __inline__ void
+nlm_write_c0_config7(uint32_t value)
+{
+ __asm__ __volatile__ (
+ ".set push\n"
+ ".set mips64\n"
+ "mtc0 %0, $16, 7\n"
+ ".set pop\n"
+ : : "r" (value));
+}
/**
* On power on reset, XLP comes up with 64 TLBs.
* Large-variable-tlb's (ELVT) and extended TLB is disabled.
@@ -101,7 +123,7 @@ static __inline__ void nlm_large_variable_tlb_en (int en)
/* en = 1 to enable
* en = 0 to disable
*/
-static __inline__ void nlm_pagewalker_en (int en)
+static __inline__ void nlm_pagewalker_en(int en)
{
unsigned int val;
@@ -114,7 +136,7 @@ static __inline__ void nlm_pagewalker_en (int en)
/* en = 1 to enable
* en = 0 to disable
*/
-static __inline__ void nlm_extended_tlb_en (int en)
+static __inline__ void nlm_extended_tlb_en(int en)
{
unsigned int val;
@@ -135,70 +157,9 @@ static __inline__ int nlm_get_num_vtlbs(void)
return (((nlm_read_c0_config6() >> 6) & 0x3ff) + 1);
}
-static __inline__ void nlm_setup_extended_pagemask (int mask)
+static __inline__ void nlm_setup_extended_pagemask(int mask)
{
nlm_write_c0_config7(mask);
}
-/* hashindex_en = 1 to enable hash mode, hashindex_en=0 to disable
- * global_mode = 1 to enable global mode, global_mode=0 to disable
- * clk_gating = 0 to enable clock gating, clk_gating=1 to disable
- */
-static __inline__ void nlm_mmu_setup(int hashindex_en, int global_mode,
- int clk_gating)
-{
- /*uint32_t mmusetup = nlm_mfcr(XLP_MMU_SETUP_REG);*/
-
- uint32_t mmusetup = 0;
- mmusetup |= (hashindex_en << 13);
- mmusetup |= (clk_gating << 3);
- mmusetup |= (global_mode << 0);
- nlm_mtcr(XLP_MMU_SETUP_REG, mmusetup);
-}
-
-static __inline__ void nlm_mmu_lfsr_seed (int thr0_seed, int thr1_seed,
- int thr2_seed, int thr3_seed)
-{
- uint32_t seed = nlm_mfcr(XLP_MMU_LFSRSEED_REG);
- seed |= ((thr3_seed & 0x7f) << 23);
- seed |= ((thr2_seed & 0x7f) << 16);
- seed |= ((thr1_seed & 0x7f) << 7);
- seed |= ((thr0_seed & 0x7f) << 0);
- nlm_mtcr(XLP_MMU_LFSRSEED_REG, seed);
-}
-
-static __inline__ void nlm_pagewalker_setup (nlm_pagewalker *walker)
-{
- uint64_t val;
-
- if (!walker->pgd_present)
- return;
-
- val = nlm_mfcr(XLP_MMU_HPW_NUM_PAGE_LVL_REG);
-
- if (walker->pgd_present)
- val |= (1 << 3);
-
- if (walker->pud_present)
- val |= (1 << 2);
-
- if (walker->pmd_present)
- val |= (1 << 1);
-
- if (walker->pte_present)
- val |= (1 << 0);
-
- nlm_mtcr(XLP_MMU_HPW_NUM_PAGE_LVL_REG, val);
-
- nlm_mtcr(XLP_MMU_PGWKR_PGDBASE_REG, walker->pgd_baseaddr);
- nlm_mtcr(XLP_MMU_PGWKR_PGDSHFT_REG, walker->pgd_shift);
- nlm_mtcr(XLP_MMU_PGWKR_PGDMASK_REG, walker->pgd_mask);
- nlm_mtcr(XLP_MMU_PGWKR_PUDSHFT_REG, walker->pud_shift);
- nlm_mtcr(XLP_MMU_PGWKR_PUDMASK_REG, walker->pud_mask);
- nlm_mtcr(XLP_MMU_PGWKR_PMDSHFT_REG, walker->pmd_shift);
- nlm_mtcr(XLP_MMU_PGWKR_PMDMASK_REG, walker->pmd_mask);
- nlm_mtcr(XLP_MMU_PGWKR_PTESHFT_REG, walker->pte_shift);
- nlm_mtcr(XLP_MMU_PGWKR_PTEMASK_REG, walker->pte_mask);
-}
-
#endif
diff --git a/sys/mips/nlm/hal/pcibus.h b/sys/mips/nlm/hal/pcibus.h
new file mode 100644
index 0000000000000..6275ff19faad5
--- /dev/null
+++ b/sys/mips/nlm/hal/pcibus.h
@@ -0,0 +1,89 @@
+/*-
+ * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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.
+ *
+ * NETLOGIC_BSD
+ * $FreeBSD$
+ */
+
+#ifndef __XLP_PCIBUS_H__
+#define __XLP_PCIBUS_H__
+
+#define MSI_MIPS_ADDR_BASE 0xfee00000
+/* MSI support */
+#define MSI_MIPS_ADDR_DEST 0x000ff000
+#define MSI_MIPS_ADDR_RH 0x00000008
+#define MSI_MIPS_ADDR_RH_OFF 0x00000000
+#define MSI_MIPS_ADDR_RH_ON 0x00000008
+#define MSI_MIPS_ADDR_DM 0x00000004
+#define MSI_MIPS_ADDR_DM_PHYSICAL 0x00000000
+#define MSI_MIPS_ADDR_DM_LOGICAL 0x00000004
+
+/* Fields in data for Intel MSI messages. */
+#define MSI_MIPS_DATA_TRGRMOD 0x00008000 /* Trigger mode */
+#define MSI_MIPS_DATA_TRGREDG 0x00000000 /* edge */
+#define MSI_MIPS_DATA_TRGRLVL 0x00008000 /* level */
+
+#define MSI_MIPS_DATA_LEVEL 0x00004000 /* Polarity. */
+#define MSI_MIPS_DATA_DEASSERT 0x00000000
+#define MSI_MIPS_DATA_ASSERT 0x00004000
+
+#define MSI_MIPS_DATA_DELMOD 0x00000700 /* Delivery Mode */
+#define MSI_MIPS_DATA_DELFIXED 0x00000000 /* fixed */
+#define MSI_MIPS_DATA_DELLOPRI 0x00000100 /* lowest priority */
+
+#define MSI_MIPS_DATA_INTVEC 0x000000ff
+
+/*
+ * Build Intel MSI message and data values from a source. AMD64 systems
+ * seem to be compatible, so we use the same function for both.
+ */
+#define MIPS_MSI_ADDR(cpu) \
+ (MSI_MIPS_ADDR_BASE | (cpu) << 12 | \
+ MSI_MIPS_ADDR_RH_OFF | MSI_MIPS_ADDR_DM_PHYSICAL)
+
+#define MIPS_MSI_DATA(irq) \
+ (MSI_MIPS_DATA_TRGRLVL | MSI_MIPS_DATA_DELFIXED | \
+ MSI_MIPS_DATA_ASSERT | (irq))
+
+#define PCIE_BRIDGE_CMD 0x1
+#define PCIE_BRIDGE_MSI_CAP 0x14
+#define PCIE_BRIDGE_MSI_ADDRL 0x15
+#define PCIE_BRIDGE_MSI_ADDRH 0x16
+#define PCIE_BRIDGE_MSI_DATA 0x17
+
+/* XLP Global PCIE configuration space registers */
+#define PCIE_MSI_STATUS 0x25A
+#define PCIE_MSI_EN 0x25B
+#define PCIE_INT_EN0 0x261
+
+/* PCIE_MSI_EN */
+#define PCIE_MSI_VECTOR_INT_EN 0xFFFFFFFF
+
+/* PCIE_INT_EN0 */
+#define PCIE_MSI_INT_EN (1 << 9)
+
+#endif /* __XLP_PCIBUS_H__ */
diff --git a/sys/mips/nlm/hal/pic.h b/sys/mips/nlm/hal/pic.h
index 842a367babfd5..efc676e069c79 100644
--- a/sys/mips/nlm/hal/pic.h
+++ b/sys/mips/nlm/hal/pic.h
@@ -25,403 +25,356 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
+ * NETLOGIC_BSD
* $FreeBSD$
- * NETLOGIC_BSD */
+ */
-#ifndef __XLP_PIC_H__
-#define __XLP_PIC_H__
+#ifndef _NLM_HAL_PIC_H
+#define _NLM_HAL_PIC_H
/* PIC Specific registers */
-#define XLP_PIC_CTRL_REG 0x40
-#define XLP_PIC_BYTESWAP_REG 0x42
-#define XLP_PIC_STATUS_REG 0x44
-#define XLP_PIC_INTR_TIMEOUT 0x46
-#define XLP_PIC_ICI0_INTR_TIMEOUT 0x48
-#define XLP_PIC_ICI1_INTR_TIMEOUT 0x4a
-#define XLP_PIC_ICI2_INTR_TIMEOUT 0x4c
-#define XLP_PIC_IPI_CTRL_REG 0x4e
-#define XLP_PIC_INT_ACK_REG 0x50
-#define XLP_PIC_INT_PENDING0_REG 0x52
-#define XLP_PIC_INT_PENDING1_REG 0x54
-#define XLP_PIC_INT_PENDING2_REG 0x56
+#define PIC_CTRL 0x00
-#define XLP_PIC_WDOG0_MAXVAL_REG 0x58
-#define XLP_PIC_WDOG0_COUNT_REG 0x5a
-#define XLP_PIC_WDOG0_ENABLE0_REG 0x5c
-#define XLP_PIC_WDOG0_ENABLE1_REG 0x5e
-#define XLP_PIC_WDOG0_BEATCMD_REG 0x60
-#define XLP_PIC_WDOG0_BEAT0_REG 0x62
-#define XLP_PIC_WDOG0_BEAT1_REG 0x64
+/* PIC control register defines */
+#define PIC_CTRL_ITV 32 /* interrupt timeout value */
+#define PIC_CTRL_ICI 19 /* ICI interrupt timeout enable */
+#define PIC_CTRL_ITE 18 /* interrupt timeout enable */
+#define PIC_CTRL_STE 10 /* system timer interrupt enable */
+#define PIC_CTRL_WWR1 8 /* watchdog 1 wraparound count for reset */
+#define PIC_CTRL_WWR0 6 /* watchdog 0 wraparound count for reset */
+#define PIC_CTRL_WWN1 4 /* watchdog 1 wraparound count for NMI */
+#define PIC_CTRL_WWN0 2 /* watchdog 0 wraparound count for NMI */
+#define PIC_CTRL_WTE 0 /* watchdog timer enable */
-#define XLP_PIC_WDOG1_MAXVAL_REG 0x66
-#define XLP_PIC_WDOG1_COUNT_REG 0x68
-#define XLP_PIC_WDOG1_ENABLE0_REG 0x6a
-#define XLP_PIC_WDOG1_ENABLE1_REG 0x6c
-#define XLP_PIC_WDOG1_BEATCMD_REG 0x6e
-#define XLP_PIC_WDOG1_BEAT0_REG 0x70
-#define XLP_PIC_WDOG1_BEAT1_REG 0x72
+/* PIC Status register defines */
+#define PIC_ICI_STATUS 33 /* ICI interrupt timeout status */
+#define PIC_ITE_STATUS 32 /* interrupt timeout status */
+#define PIC_STS_STATUS 4 /* System timer interrupt status */
+#define PIC_WNS_STATUS 2 /* NMI status for watchdog timers */
+#define PIC_WIS_STATUS 0 /* Interrupt status for watchdog timers */
-#define XLP_PIC_WDOG_MAXVAL_REG(i) (XLP_PIC_WDOG0_MAXVAL_REG + ((i) ? 7 : 0))
-#define XLP_PIC_WDOG_COUNT_REG(i) (XLP_PIC_WDOG0_COUNT_REG + ((i) ? 7 : 0))
-#define XLP_PIC_WDOG_ENABLE0_REG(i) (XLP_PIC_WDOG0_ENABLE0_REG + ((i) ? 7 : 0))
-#define XLP_PIC_WDOG_ENABLE1_REG(i) (XLP_PIC_WDOG0_ENABLE1_REG + ((i) ? 7 : 0))
-#define XLP_PIC_WDOG_BEATCMD_REG(i) (XLP_PIC_WDOG0_BEATCMD_REG + ((i) ? 7 : 0))
-#define XLP_PIC_WDOG_BEAT0_REG(i) (XLP_PIC_WDOG0_BEAT0_REG + ((i) ? 7 : 0))
-#define XLP_PIC_WDOG_BEAT1_REG(i) (XLP_PIC_WDOG0_BEAT1_REG + ((i) ? 7 : 0))
+/* PIC IPI control register offsets */
+#define PIC_IPICTRL_NMI 32
+#define PIC_IPICTRL_RIV 20 /* received interrupt vector */
+#define PIC_IPICTRL_IDB 16 /* interrupt destination base */
+#define PIC_IPICTRL_DTE 0 /* interrupt destination thread enables */
-#define XLP_PIC_SYSTIMER0_MAXVAL_REG 0x74
-#define XLP_PIC_SYSTIMER1_MAXVAL_REG 0x76
-#define XLP_PIC_SYSTIMER2_MAXVAL_REG 0x78
-#define XLP_PIC_SYSTIMER3_MAXVAL_REG 0x7a
-#define XLP_PIC_SYSTIMER4_MAXVAL_REG 0x7c
-#define XLP_PIC_SYSTIMER5_MAXVAL_REG 0x7e
-#define XLP_PIC_SYSTIMER6_MAXVAL_REG 0x80
-#define XLP_PIC_SYSTIMER7_MAXVAL_REG 0x82
-#define XLP_PIC_SYSTIMER_MAXVAL_REG(i) (XLP_PIC_SYSTIMER0_MAXVAL_REG + ((i)*2))
+/* PIC IRT register offsets */
+#define PIC_IRT_ENABLE 31
+#define PIC_IRT_NMI 29
+#define PIC_IRT_SCH 28 /* Scheduling scheme */
+#define PIC_IRT_RVEC 20 /* Interrupt receive vectors */
+#define PIC_IRT_DT 19 /* Destination type */
+#define PIC_IRT_DB 16 /* Destination base */
+#define PIC_IRT_DTE 0 /* Destination thread enables */
-#define XLP_PIC_SYSTIMER0_COUNT_REG 0x84
-#define XLP_PIC_SYSTIMER1_COUNT_REG 0x86
-#define XLP_PIC_SYSTIMER2_COUNT_REG 0x88
-#define XLP_PIC_SYSTIMER3_COUNT_REG 0x8a
-#define XLP_PIC_SYSTIMER4_COUNT_REG 0x8c
-#define XLP_PIC_SYSTIMER5_COUNT_REG 0x8e
-#define XLP_PIC_SYSTIMER6_COUNT_REG 0x90
-#define XLP_PIC_SYSTIMER7_COUNT_REG 0x92
-#define XLP_PIC_SYSTIMER_COUNT_REG(i) (XLP_PIC_SYSTIMER0_COUNT_REG + ((i)*2))
+#define PIC_BYTESWAP 0x02
+#define PIC_STATUS 0x04
+#define PIC_INTR_TIMEOUT 0x06
+#define PIC_ICI0_INTR_TIMEOUT 0x08
+#define PIC_ICI1_INTR_TIMEOUT 0x0a
+#define PIC_ICI2_INTR_TIMEOUT 0x0c
+#define PIC_IPI_CTL 0x0e
+#define PIC_INT_ACK 0x10
+#define PIC_INT_PENDING0 0x12
+#define PIC_INT_PENDING1 0x14
+#define PIC_INT_PENDING2 0x16
-#define XLP_PIC_ITE0_N0_N1_REG 0x94
-#define XLP_PIC_ITE1_N0_N1_REG 0x98
-#define XLP_PIC_ITE2_N0_N1_REG 0x9c
-#define XLP_PIC_ITE3_N0_N1_REG 0xa0
-#define XLP_PIC_ITE4_N0_N1_REG 0xa4
-#define XLP_PIC_ITE5_N0_N1_REG 0xa8
-#define XLP_PIC_ITE6_N0_N1_REG 0xac
-#define XLP_PIC_ITE7_N0_N1_REG 0xb0
-#define XLP_PIC_ITE_N0_N1_REG(i) (XLP_PIC_ITE0_N0_N1_REG + ((i)*4))
+#define PIC_WDOG0_MAXVAL 0x18
+#define PIC_WDOG0_COUNT 0x1a
+#define PIC_WDOG0_ENABLE0 0x1c
+#define PIC_WDOG0_ENABLE1 0x1e
+#define PIC_WDOG0_BEATCMD 0x20
+#define PIC_WDOG0_BEAT0 0x22
+#define PIC_WDOG0_BEAT1 0x24
-#define XLP_PIC_ITE0_N2_N3_REG 0x96
-#define XLP_PIC_ITE1_N2_N3_REG 0x9a
-#define XLP_PIC_ITE2_N2_N3_REG 0x9e
-#define XLP_PIC_ITE3_N2_N3_REG 0xa2
-#define XLP_PIC_ITE4_N2_N3_REG 0xa6
-#define XLP_PIC_ITE5_N2_N3_REG 0xaa
-#define XLP_PIC_ITE6_N2_N3_REG 0xae
-#define XLP_PIC_ITE7_N2_N3_REG 0xb2
-#define XLP_PIC_ITE_N2_N3_REG(i) (XLP_PIC_ITE0_N2_N3_REG + ((i)*4))
+#define PIC_WDOG1_MAXVAL 0x26
+#define PIC_WDOG1_COUNT 0x28
+#define PIC_WDOG1_ENABLE0 0x2a
+#define PIC_WDOG1_ENABLE1 0x2c
+#define PIC_WDOG1_BEATCMD 0x2e
+#define PIC_WDOG1_BEAT0 0x30
+#define PIC_WDOG1_BEAT1 0x32
-#define XLP_PIC_IRT0_REG 0xb4
-#define XLP_PIC_IRT_REG(i) (XLP_PIC_IRT0_REG + ((i)*2))
+#define PIC_WDOG_MAXVAL(i) (PIC_WDOG0_MAXVAL + ((i) ? 7 : 0))
+#define PIC_WDOG_COUNT(i) (PIC_WDOG0_COUNT + ((i) ? 7 : 0))
+#define PIC_WDOG_ENABLE0(i) (PIC_WDOG0_ENABLE0 + ((i) ? 7 : 0))
+#define PIC_WDOG_ENABLE1(i) (PIC_WDOG0_ENABLE1 + ((i) ? 7 : 0))
+#define PIC_WDOG_BEATCMD(i) (PIC_WDOG0_BEATCMD + ((i) ? 7 : 0))
+#define PIC_WDOG_BEAT0(i) (PIC_WDOG0_BEAT0 + ((i) ? 7 : 0))
+#define PIC_WDOG_BEAT1(i) (PIC_WDOG0_BEAT1 + ((i) ? 7 : 0))
-/* PIC IRT indices */
+#define PIC_TIMER0_MAXVAL 0x34
+#define PIC_TIMER1_MAXVAL 0x36
+#define PIC_TIMER2_MAXVAL 0x38
+#define PIC_TIMER3_MAXVAL 0x3a
+#define PIC_TIMER4_MAXVAL 0x3c
+#define PIC_TIMER5_MAXVAL 0x3e
+#define PIC_TIMER6_MAXVAL 0x40
+#define PIC_TIMER7_MAXVAL 0x42
+#define PIC_TIMER_MAXVAL(i) (PIC_TIMER0_MAXVAL + ((i) * 2))
-#define XLP_PIC_IRT_WD0_INDEX 0
-#define XLP_PIC_IRT_WD1_INDEX 1
-#define XLP_PIC_IRT_WD_NMI0_INDEX 2
-#define XLP_PIC_IRT_WD_NMI1_INDEX 3
-#define XLP_PIC_IRT_TIMER0_INDEX 4
-#define XLP_PIC_IRT_TIMER1_INDEX 5
-#define XLP_PIC_IRT_TIMER2_INDEX 6
-#define XLP_PIC_IRT_TIMER3_INDEX 7
-#define XLP_PIC_IRT_TIMER4_INDEX 8
-#define XLP_PIC_IRT_TIMER5_INDEX 9
-#define XLP_PIC_IRT_TIMER6_INDEX 10
-#define XLP_PIC_IRT_TIMER7_INDEX 11
-#define XLP_PIC_IRT_TIMER_INDEX(i) (XLP_PIC_IRT_TIMER0_INDEX + (i))
+#define PIC_TIMER0_COUNT 0x44
+#define PIC_TIMER1_COUNT 0x46
+#define PIC_TIMER2_COUNT 0x48
+#define PIC_TIMER3_COUNT 0x4a
+#define PIC_TIMER4_COUNT 0x4c
+#define PIC_TIMER5_COUNT 0x4e
+#define PIC_TIMER6_COUNT 0x50
+#define PIC_TIMER7_COUNT 0x52
+#define PIC_TIMER_COUNT(i) (PIC_TIMER0_COUNT + ((i) * 2))
-#define XLP_PIC_IRT_MSGQ0_INDEX 12
-#define XLP_PIC_IRT_MSGQ_INDEX(i) (XLP_PIC_IRT_MSGQ0_INDEX + (i))
-/* 12 to 43 */
-#define XLP_PIC_IRT_MSG0_INDEX 44
-#define XLP_PIC_IRT_MSG1_INDEX 45
+#define PIC_ITE0_N0_N1 0x54
+#define PIC_ITE1_N0_N1 0x58
+#define PIC_ITE2_N0_N1 0x5c
+#define PIC_ITE3_N0_N1 0x60
+#define PIC_ITE4_N0_N1 0x64
+#define PIC_ITE5_N0_N1 0x68
+#define PIC_ITE6_N0_N1 0x6c
+#define PIC_ITE7_N0_N1 0x70
+#define PIC_ITE_N0_N1(i) (PIC_ITE0_N0_N1 + ((i) * 4))
+
+#define PIC_ITE0_N2_N3 0x56
+#define PIC_ITE1_N2_N3 0x5a
+#define PIC_ITE2_N2_N3 0x5e
+#define PIC_ITE3_N2_N3 0x62
+#define PIC_ITE4_N2_N3 0x66
+#define PIC_ITE5_N2_N3 0x6a
+#define PIC_ITE6_N2_N3 0x6e
+#define PIC_ITE7_N2_N3 0x72
+#define PIC_ITE_N2_N3(i) (PIC_ITE0_N2_N3 + ((i) * 4))
-#define XLP_PIC_IRT_PCIE_MSIX0_INDEX 46
-#define XLP_PIC_IRT_PCIE_MSIX_INDEX(i) (XLP_PIC_IRT_PCIE_MSIX0_INDEX + (i))
+#define PIC_IRT0 0x74
+#define PIC_IRT(i) (PIC_IRT0 + ((i) * 2))
+
+#define TIMER_CYCLES_MAXVAL 0xffffffffffffffffULL
+
+/*
+ * IRT Map
+ */
+#define PIC_NUM_IRTS 160
+
+#define PIC_IRT_WD_0_INDEX 0
+#define PIC_IRT_WD_1_INDEX 1
+#define PIC_IRT_WD_NMI_0_INDEX 2
+#define PIC_IRT_WD_NMI_1_INDEX 3
+#define PIC_IRT_TIMER_0_INDEX 4
+#define PIC_IRT_TIMER_1_INDEX 5
+#define PIC_IRT_TIMER_2_INDEX 6
+#define PIC_IRT_TIMER_3_INDEX 7
+#define PIC_IRT_TIMER_4_INDEX 8
+#define PIC_IRT_TIMER_5_INDEX 9
+#define PIC_IRT_TIMER_6_INDEX 10
+#define PIC_IRT_TIMER_7_INDEX 11
+#define PIC_IRT_CLOCK_INDEX PIC_IRT_TIMER_7_INDEX
+#define PIC_IRT_TIMER_INDEX(num) ((num) + PIC_IRT_TIMER_0_INDEX)
+
+
+/* 11 and 12 */
+#define PIC_NUM_MSG_Q_IRTS 32
+#define PIC_IRT_MSG_Q0_INDEX 12
+#define PIC_IRT_MSG_Q_INDEX(qid) ((qid) + PIC_IRT_MSG_Q0_INDEX)
+/* 12 to 43 */
+#define PIC_IRT_MSG_0_INDEX 44
+#define PIC_IRT_MSG_1_INDEX 45
+/* 44 and 45 */
+#define PIC_NUM_PCIE_MSIX_IRTS 32
+#define PIC_IRT_PCIE_MSIX_0_INDEX 46
+#define PIC_IRT_PCIE_MSIX_INDEX(num) ((num) + PIC_IRT_PCIE_MSIX_0_INDEX)
/* 46 to 77 */
-#define XLP_PIC_IRT_PCIE_LINK0_INDEX 78
-#define XLP_PIC_IRT_PCIE_LINK1_INDEX 79
-#define XLP_PIC_IRT_PCIE_LINK2_INDEX 80
-#define XLP_PIC_IRT_PCIE_LINK3_INDEX 81
-#define XLP_PIC_IRT_PCIE_LINK_INDEX(i) (XLP_PIC_IRT_PCIE_LINK0_INDEX + (i))
+#define PIC_NUM_PCIE_LINK_IRTS 4
+#define PIC_IRT_PCIE_LINK_0_INDEX 78
+#define PIC_IRT_PCIE_LINK_1_INDEX 79
+#define PIC_IRT_PCIE_LINK_2_INDEX 80
+#define PIC_IRT_PCIE_LINK_3_INDEX 81
+#define PIC_IRT_PCIE_LINK_INDEX(num) ((num) + PIC_IRT_PCIE_LINK_0_INDEX)
/* 78 to 81 */
-#define XLP_PIC_IRT_NA0_INDEX 82
-#define XLP_PIC_IRT_NA_INDEX(i) (XLP_PIC_IRT_NA0_INDEX + (i))
+#define PIC_NUM_NA_IRTS 32
/* 82 to 113 */
-#define XLP_PIC_IRT_POE_INDEX 114
-#define XLP_PIC_IRT_USB0_INDEX 115
-#define XLP_PIC_IRT_EHCI0_INDEX 115
-#define XLP_PIC_IRT_EHCI1_INDEX 118
-#define XLP_PIC_IRT_USB_INDEX(i) (XLP_PIC_IRT_USB0_INDEX + (i))
+#define PIC_IRT_NA_0_INDEX 82
+#define PIC_IRT_NA_INDEX(num) ((num) + PIC_IRT_NA_0_INDEX)
+#define PIC_IRT_POE_INDEX 114
+
+#define PIC_NUM_USB_IRTS 6
+#define PIC_IRT_USB_0_INDEX 115
+#define PIC_IRT_EHCI_0_INDEX 115
+#define PIC_IRT_EHCI_1_INDEX 118
+#define PIC_IRT_USB_INDEX(num) ((num) + PIC_IRT_USB_0_INDEX)
/* 115 to 120 */
-#define XLP_PIC_IRT_GDX_INDEX 121
-#define XLP_PIC_IRT_SEC_INDEX 122
-#define XLP_PIC_IRT_RSA_INDEX 123
-#define XLP_PIC_IRT_COMP0_INDEX 124
-#define XLP_PIC_IRT_COMP_INDEX(i) (XLP_PIC_IRT_COMP0_INDEX + (i))
+#define PIC_IRT_GDX_INDEX 121
+#define PIC_IRT_SEC_INDEX 122
+#define PIC_IRT_RSA_INDEX 123
+
+#define PIC_NUM_COMP_IRTS 4
+#define PIC_IRT_COMP_0_INDEX 124
+#define PIC_IRT_COMP_INDEX(num) ((num) + PIC_IRT_COMP_0_INDEX)
/* 124 to 127 */
-#define XLP_PIC_IRT_GBU_INDEX 128
-/* coherent inter chip */
-#define XLP_PIC_IRT_CIC0_INDEX 129
-#define XLP_PIC_IRT_CIC1_INDEX 130
-#define XLP_PIC_IRT_CIC2_INDEX 131
-#define XLP_PIC_IRT_CAM_INDEX 132
-#define XLP_PIC_IRT_UART0_INDEX 133
-#define XLP_PIC_IRT_UART1_INDEX 134
-#define XLP_PIC_IRT_I2C0_INDEX 135
-#define XLP_PIC_IRT_I2C1_INDEX 136
-#define XLP_PIC_IRT_SYS0_INDEX 137
-#define XLP_PIC_IRT_SYS1_INDEX 138
-#define XLP_PIC_IRT_JTAG_INDEX 139
-#define XLP_PIC_IRT_PIC_INDEX 140
-#define XLP_PIC_IRT_NBU_INDEX 141
-#define XLP_PIC_IRT_TCU_INDEX 142
-/* global coherency */
-#define XLP_PIC_IRT_GCU_INDEX 143
-#define XLP_PIC_IRT_DMC0_INDEX 144
-#define XLP_PIC_IRT_DMC1_INDEX 145
-#define XLP_PIC_IRT_GPIO0_INDEX 146
-#define XLP_PIC_IRT_GPIO_INDEX(i) (XLP_PIC_IRT_GPIO0_INDEX + (i))
-/* 146 to 149 */
-#define XLP_PIC_IRT_NOR_INDEX 150
-#define XLP_PIC_IRT_NAND_INDEX 151
-#define XLP_PIC_IRT_SPI_INDEX 152
-#define XLP_PIC_IRT_MMC_INDEX 153
+#define PIC_IRT_GBU_INDEX 128
+#define PIC_IRT_ICC_0_INDEX 129 /* ICC - Inter Chip Coherency */
+#define PIC_IRT_ICC_1_INDEX 130
+#define PIC_IRT_ICC_2_INDEX 131
+#define PIC_IRT_CAM_INDEX 132
+#define PIC_IRT_UART_0_INDEX 133
+#define PIC_IRT_UART_1_INDEX 134
+#define PIC_IRT_I2C_0_INDEX 135
+#define PIC_IRT_I2C_1_INDEX 136
+#define PIC_IRT_SYS_0_INDEX 137
+#define PIC_IRT_SYS_1_INDEX 138
+#define PIC_IRT_JTAG_INDEX 139
+#define PIC_IRT_PIC_INDEX 140
+#define PIC_IRT_NBU_INDEX 141
+#define PIC_IRT_TCU_INDEX 142
+#define PIC_IRT_GCU_INDEX 143 /* GBC - Global Coherency */
+#define PIC_IRT_DMC_0_INDEX 144
+#define PIC_IRT_DMC_1_INDEX 145
-/* PIC control register defines */
-#define XLP_PIC_ITV_OFFSET 32 /* interrupt timeout value */
-#define XLP_PIC_ICI_OFFSET 19 /* ICI interrupt timeout enable */
-#define XLP_PIC_ITE_OFFSET 18 /* interrupt timeout enable */
-#define XLP_PIC_STE_OFFSET 10 /* system timer interrupt enable */
-#define XLP_PIC_WWR1_OFFSET 8 /* watchdog timer 1 wraparound count for reset */
-#define XLP_PIC_WWR0_OFFSET 6 /* watchdog timer 0 wraparound count for reset */
-#define XLP_PIC_WWN1_OFFSET 4 /* watchdog timer 1 wraparound count for NMI */
-#define XLP_PIC_WWN0_OFFSET 2 /* watchdog timer 0 wraparound count for NMI */
-#define XLP_PIC_WTE_OFFSET 0 /* watchdog timer enable */
+#define PIC_NUM_GPIO_IRTS 4
+#define PIC_IRT_GPIO_0_INDEX 146
+#define PIC_IRT_GPIO_INDEX(num) ((num) + PIC_IRT_GPIO_0_INDEX)
-/* PIC Status register defines */
-#define XLP_PIC_ICI_STATUS_OFFSET 33 /* ICI interrupt timeout interrupt status */
-#define XLP_PIC_ITE_STATUS_OFFSET 32 /* interrupt timeout interrupt status */
-#define XLP_PIC_STS_STATUS_OFFSET 4 /* System timer interrupt status */
-#define XLP_PIC_WNS_STATUS_OFFSET 2 /* NMI interrupt status for watchdog timers */
-#define XLP_PIC_WIS_STATUS_OFFSET 0 /* Interrupt status for watchdog timers */
+/* 146 to 149 */
+#define PIC_IRT_NOR_INDEX 150
+#define PIC_IRT_NAND_INDEX 151
+#define PIC_IRT_SPI_INDEX 152
+#define PIC_IRT_MMC_INDEX 153
-/* PIC IPI control register offsets */
-#define XLP_PIC_IPICTRL_NMI_OFFSET 32
-#define XLP_PIC_IPICTRL_RIV_OFFSET 20 /* received interrupt vector */
-#define XLP_PIC_IPICTRL_IDB_OFFSET 16 /* interrupt destination base */
-#define XLP_PIC_IPICTRL_DTE_OFFSET 16 /* interrupt destination thread enables */
+#define PIC_CLOCK_TIMER 7
+#define PIC_IRQ_BASE 8
-/* PIC IRT register offsets */
-#define XLP_PIC_IRT_ENABLE_OFFSET 31
-#define XLP_PIC_IRT_NMI_OFFSET 29
-#define XLP_PIC_IRT_SCH_OFFSET 28 /* Scheduling scheme */
-#define XLP_PIC_IRT_RVEC_OFFSET 20 /* Interrupt receive vectors */
-#define XLP_PIC_IRT_DT_OFFSET 19 /* Destination type */
-#define XLP_PIC_IRT_DB_OFFSET 16 /* Destination base */
-#define XLP_PIC_IRT_DTE_OFFSET 0 /* Destination thread enables */
+#if !defined(LOCORE) && !defined(__ASSEMBLY__)
-#define XLP_PIC_MAX_IRQ 64
-#define XLP_PIC_MAX_IRT 160
-#define XLP_PIC_TIMER_FREQ 133000000
+#define PIC_IRT_FIRST_IRQ (PIC_IRQ_BASE)
+#define PIC_IRT_LAST_IRQ 63
+#define PIC_IRQ_IS_IRT(irq) ((irq) >= PIC_IRT_FIRST_IRQ)
-#if !defined(LOCORE) && !defined(__ASSEMBLY__)
+/*
+ * Misc
+ */
+#define PIC_IRT_VALID 1
+#define PIC_LOCAL_SCHEDULING 1
+#define PIC_GLOBAL_SCHEDULING 0
-#define nlm_rdreg_pic(b, r) nlm_read_reg64_kseg(b,r)
-#define nlm_wreg_pic(b, r, v) nlm_write_reg64_kseg(b,r,v)
-#define nlm_pcibase_pic(node) nlm_pcicfg_base(XLP_IO_PIC_OFFSET(node))
-#define nlm_regbase_pic(node) nlm_pcibase_pic(node)
+#define nlm_read_pic_reg(b, r) nlm_read_reg64(b, r)
+#define nlm_write_pic_reg(b, r, v) nlm_write_reg64(b, r, v)
+#define nlm_get_pic_pcibase(node) nlm_pcicfg_base(XLP_IO_PIC_OFFSET(node))
+#define nlm_get_pic_regbase(node) (nlm_get_pic_pcibase(node) + XLP_IO_PCI_HDRSZ)
/* IRT and h/w interrupt routines */
-static __inline__ int
-nlm_pic_get_numirts(uint64_t pcibase)
+static inline int
+nlm_pic_read_irt(uint64_t base, int irt_index)
{
- return (nlm_pci_rdreg(pcibase, XLP_PCI_IRTINFO_REG) >> 16);
+ return nlm_read_pic_reg(base, PIC_IRT(irt_index));
}
-static __inline__ int
-nlm_pic_get_startirt(uint64_t base)
+static inline void
+nlm_pic_send_ipi(uint64_t base, int cpu, int vec, int nmi)
{
- return (nlm_pci_rdreg(base, XLP_PCI_IRTINFO_REG) & 0xff);
-}
+ uint64_t ipi;
+ int node, ncpu;
+ node = cpu / 32;
+ ncpu = cpu & 0x1f;
+ ipi = ((uint64_t)nmi << 31) | (vec << 20) | (node << 17) |
+ (1 << (cpu & 0xf));
+ if (ncpu > 15)
+ ipi |= 0x10000; /* Setting bit 16 to select cpus 16-31 */
-static __inline__ int
-nlm_pic_read_irt(uint64_t base, int irt_index)
-{
- return nlm_rdreg_pic(base, XLP_PIC_IRT_REG(irt_index));
+ nlm_write_pic_reg(base, PIC_IPI_CTL, ipi);
}
-/* IRT's can be written into in two modes
- * ITE mode - Here the destination of the interrupt is one of the
- * eight interrupt-thread-enable groups, allowing the interrupt
- * to be distributed to any thread on any node
- * ID mode - In ID mode, the IRT has the DB and DTE fields.
- * DB[18:17] hold the node select and DB[16], if set to 0 selects
- * cpu-cores 0-3, and if set to 1 selects cpu-cores 4-7.
- * The DTE[15:0] field is a thread mask, allowing the PIC to broadcast
- * the interrupt to 1-16 threads selectable from that mask
- */
-
-static __inline__ void
-nlm_pic_write_irt_raw(uint64_t base, int irt_index, int en, int nmi, int sch,
- int vec, int dt, int db, int dte)
+static inline uint64_t
+nlm_pic_read_control(uint64_t base)
{
- uint64_t val =
- (((en & 0x1) << XLP_PIC_IRT_ENABLE_OFFSET) |
- ((nmi & 0x1) << XLP_PIC_IRT_NMI_OFFSET) |
- ((sch & 0x1) << XLP_PIC_IRT_SCH_OFFSET) |
- ((vec & 0x3f) << XLP_PIC_IRT_RVEC_OFFSET) |
- ((dt & 0x1 ) << XLP_PIC_IRT_DT_OFFSET) |
- ((db & 0x7) << XLP_PIC_IRT_DB_OFFSET) |
- (dte & 0xffff));
- nlm_wreg_pic(base, XLP_PIC_IRT_REG(irt_index), val);
+ return nlm_read_pic_reg(base, PIC_CTRL);
}
-/* write IRT in ID mode */
-static __inline__ void
-nlm_pic_write_irt_id(uint64_t base, int irt_index, int en, int nmi, int vec,
- int node, int cpugroup, uint32_t cpu_mask)
+static inline void
+nlm_pic_write_control(uint64_t base, uint64_t control)
{
- nlm_pic_write_irt_raw(base, irt_index, en, nmi, 1, vec, 1,
- (node << 1) | cpugroup , cpu_mask);
+ nlm_write_pic_reg(base, PIC_CTRL, control);
}
-/* write IRT in ITE mode */
-static __inline__ void
-nlm_pic_write_ite(uint64_t base, int ite, uint32_t node0_thrmask,
- uint32_t node1_thrmask, uint32_t node2_thrmask, uint32_t node3_thrmask)
+static inline void
+nlm_pic_update_control(uint64_t base, uint64_t control)
{
- uint64_t tm10 = ((uint64_t)node1_thrmask << 32) | node0_thrmask;
- uint64_t tm32 = ((uint64_t)node1_thrmask << 32) | node0_thrmask;
+ uint64_t val;
- /* Enable the ITE register for all nodes */
- nlm_wreg_pic(base, XLP_PIC_ITE_N0_N1_REG(ite), tm10);
- nlm_wreg_pic(base, XLP_PIC_ITE_N2_N3_REG(ite), tm32);
+ val = nlm_read_pic_reg(base, PIC_CTRL);
+ nlm_write_pic_reg(base, PIC_CTRL, control | val);
}
-static __inline__ void
-nlm_pic_write_irt_ite(uint64_t base, int irt_index, int ite, int en, int nmi,
- int sch, int vec)
+static inline void
+nlm_pic_ack(uint64_t base, int irt_num)
{
- nlm_pic_write_irt_raw(base, irt_index, en, nmi, sch, vec, 0, ite, 0);
-}
+ nlm_write_pic_reg(base, PIC_INT_ACK, irt_num);
-/* Goto PIC on that node, and ack the interrupt */
-static __inline__ void nlm_pic_ack(uint64_t src_base, int irt)
-{
- nlm_wreg_pic(src_base, XLP_PIC_INT_ACK_REG, irt);
- /* ack in the status registers for watchdog and system timers */
- if (irt < 12)
- nlm_wreg_pic(src_base, XLP_PIC_STATUS_REG, (1 << irt));
+ /* Ack the Status register for Watchdog & System timers */
+ if (irt_num < 12)
+ nlm_write_pic_reg(base, PIC_STATUS, (1 << irt_num));
}
-/* IPI routines */
-
-static __inline__ void
-nlm_pic_send_ipi(uint64_t local_base, int target_node, int vcpu, int vec, int nmi)
+static inline void
+nlm_set_irt_to_cpu(uint64_t base, int irt, int cpu)
{
- uint64_t ipi =
- (((uint64_t)nmi << XLP_PIC_IPICTRL_NMI_OFFSET) |
- (vec << XLP_PIC_IPICTRL_RIV_OFFSET) |
- (target_node << 17) |
- (1 << (vcpu & 0xf)));
- if (vcpu > 15)
- ipi |= 0x10000; /* set bit 16 to select cpus 16-31 */
+ uint64_t val;
- nlm_wreg_pic(local_base, XLP_PIC_IPI_CTRL_REG, ipi);
+ val = nlm_read_pic_reg(base, PIC_IRT(irt));
+ val |= cpu & 0xf;
+ if (cpu > 15)
+ val |= 1 << 16;
+ nlm_write_pic_reg(base, PIC_IRT(irt), val);
}
-/* System Timer routines -- broadcasts systemtimer to 16 vcpus defined in cpu_mask */
-
-static __inline__ void
-nlm_pic_set_systimer(uint64_t base, int timer, uint64_t value, int irq, int node,
- int cpugroup, uint32_t cpumask)
+static inline void
+nlm_pic_write_irt(uint64_t base, int irt_num, int en, int nmi,
+ int sch, int vec, int dt, int db, int dte)
{
- uint64_t pic_ctrl = nlm_rdreg_pic(base, XLP_PIC_CTRL_REG);
- int en;
+ uint64_t val;
- en = (cpumask != 0);
- nlm_wreg_pic(base, XLP_PIC_SYSTIMER_MAXVAL_REG(timer), value);
- nlm_pic_write_irt_id(base, XLP_PIC_IRT_TIMER_INDEX(timer),
- en, 0, irq, node, cpugroup, cpumask);
+ val = (((uint64_t)en & 0x1) << 31) | ((nmi & 0x1) << 29) |
+ ((sch & 0x1) << 28) | ((vec & 0x3f) << 20) |
+ ((dt & 0x1) << 19) | ((db & 0x7) << 16) |
+ (dte & 0xffff);
- /* enable the timer */
- pic_ctrl |= (1 << (XLP_PIC_STE_OFFSET+timer));
- nlm_wreg_pic(base, XLP_PIC_CTRL_REG, pic_ctrl);
+ nlm_write_pic_reg(base, PIC_IRT(irt_num), val);
}
-static __inline__ uint64_t
-nlm_pic_read_systimer(uint64_t base, int timer)
+static inline void
+nlm_pic_write_irt_direct(uint64_t base, int irt_num, int en, int nmi,
+ int sch, int vec, int cpu)
{
- return nlm_rdreg_pic(base, XLP_PIC_SYSTIMER_COUNT_REG(timer));
+ nlm_pic_write_irt(base, irt_num, en, nmi, sch, vec, 1,
+ (cpu >> 4), /* thread group */
+ 1 << (cpu & 0xf)); /* thread mask */
}
-/* Watchdog timer routines */
-
-/* node - XLP node
- * timer - watchdog timer. valid values are 0 and 1
- * wrap_around_count - defines the number of times the watchdog timer can wrap-around
- * after which the reset / NMI gets generated to the threads defined in thread-enable-masks.
- * value - the vatchdog timer max value, upto which the timer will count down
- */
-
-static __inline__ void
-nlm_pic_set_wdogtimer(uint64_t base, int timer, int wrap_around_count, int nmi,
- uint32_t node0_thrmask, uint32_t node1_thrmask,
- uint32_t node2_thrmask, uint32_t node3_thrmask, uint64_t value)
+static inline uint64_t
+nlm_pic_read_timer(uint64_t base, int timer)
{
- uint64_t pic_ctrl = nlm_rdreg_pic(base, XLP_PIC_CTRL_REG);
- uint64_t mask0, mask1;
-
- if (timer > 1 || wrap_around_count > 3)
- return;
-
- /* enable watchdog timer interrupt */
- pic_ctrl |= (((1 << timer) & 0xf));
-
- if (timer) {
- if (nmi)
- pic_ctrl |= (wrap_around_count << XLP_PIC_WWN1_OFFSET);
- else
- pic_ctrl |= (wrap_around_count << XLP_PIC_WWN0_OFFSET);
- } else {
- if (nmi)
- pic_ctrl |= (wrap_around_count << XLP_PIC_WWR1_OFFSET);
- else
- pic_ctrl |= (wrap_around_count << XLP_PIC_WWR0_OFFSET);
- }
-
- mask0 = ((unsigned long long)node1_thrmask << 32) | node0_thrmask;
- mask1 = ((unsigned long long)node3_thrmask << 32) | node2_thrmask;
-
- nlm_wreg_pic(base, XLP_PIC_WDOG_MAXVAL_REG(timer), value);
-
- nlm_wreg_pic(base, XLP_PIC_WDOG_ENABLE0_REG(timer), mask0);
- nlm_wreg_pic(base, XLP_PIC_WDOG_ENABLE1_REG(timer), mask1);
+ return nlm_read_pic_reg(base, PIC_TIMER_COUNT(timer));
+}
- nlm_wreg_pic(base, XLP_PIC_CTRL_REG, pic_ctrl);
+static inline void
+nlm_pic_write_timer(uint64_t base, int timer, uint64_t value)
+{
+ nlm_write_pic_reg(base, PIC_TIMER_COUNT(timer), value);
}
-/* watchdog's need to be "stroked" by heartbeats from vcpus.
- * On XLP, the heartbeat bit for a specific cpu thread on a specific
- * node is set according to the following formula:
- * 32N + 4C + T
- * where N = node, C=cpu-core number, T=thread number
- *
- * src_node = source node of watchdog timer interrupts. These interrupts
- * get generated from the PIC on src_node.
- * timer = watchdog timer 0 or 1
- * node = node for which the hearbeat is being done
- * cpu = cpu-core for which the hearbeat is being done
- * thread = h/w thread for which the hearbeat is being done
- */
-static __inline__ void
-nlm_pic_set_wdog_heartbeat(uint64_t base, int timer, int node, int cpu,
- int thread)
+static inline void
+nlm_pic_set_timer(uint64_t base, int timer, uint64_t value, int irq, int cpu)
{
- int val = 32 * node + 4 * cpu + thread;
+ uint64_t pic_ctrl = nlm_read_pic_reg(base, PIC_CTRL);
+ int en;
+
+ en = (irq > 0);
+ nlm_write_pic_reg(base, PIC_TIMER_MAXVAL(timer), value);
+ nlm_pic_write_irt_direct(base, PIC_IRT_TIMER_INDEX(timer),
+ en, 0, 0, irq, cpu);
- nlm_wreg_pic(base, XLP_PIC_WDOG_BEATCMD_REG(timer), val);
+ /* enable the timer */
+ pic_ctrl |= (1 << (PIC_CTRL_STE + timer));
+ nlm_write_pic_reg(base, PIC_CTRL, pic_ctrl);
}
-#endif /* !LOCORE && !__ASSEMBLY__ */
-#endif
+#endif /* __ASSEMBLY__ */
+#endif /* _NLM_HAL_PIC_H */
diff --git a/sys/mips/nlm/hal/sys.h b/sys/mips/nlm/hal/sys.h
index 89e4c52d15bec..89b27fd7bdf36 100644
--- a/sys/mips/nlm/hal/sys.h
+++ b/sys/mips/nlm/hal/sys.h
@@ -25,101 +25,101 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
+ * NETLOGIC_BSD
* $FreeBSD$
- * NETLOGIC_BSD */
+ */
-#ifndef __NLM_SYS_H__
-#define __NLM_SYS_H__
+#ifndef __NLM_HAL_SYS_H__
+#define __NLM_HAL_SYS_H__
/**
* @file_name sys.h
* @author Netlogic Microsystems
* @brief HAL for System configuration registers
*/
-#define XLP_SYS_CHIP_RESET_REG 0x40
-#define XLP_SYS_POWER_ON_RESET_REG 0x41
-#define XLP_SYS_EFUSE_DEVICE_CFG_STATUS0_REG 0x42
-#define XLP_SYS_EFUSE_DEVICE_CFG_STATUS1_REG 0x43
-#define XLP_SYS_EFUSE_DEVICE_CFG_STATUS2_REG 0x44
-#define XLP_SYS_EFUSE_DEVICE_CFG3_REG 0x45
-#define XLP_SYS_EFUSE_DEVICE_CFG4_REG 0x46
-#define XLP_SYS_EFUSE_DEVICE_CFG5_REG 0x47
-#define XLP_SYS_EFUSE_DEVICE_CFG6_REG 0x48
-#define XLP_SYS_EFUSE_DEVICE_CFG7_REG 0x49
-#define XLP_SYS_PLL_CTRL_REG 0x4a
-#define XLP_SYS_CPU_RESET_REG 0x4b
-#define XLP_SYS_CPU_NONCOHERENT_MODE_REG 0x4d
-#define XLP_SYS_CORE_DFS_DIS_CTRL_REG 0x4e
-#define XLP_SYS_CORE_DFS_RST_CTRL_REG 0x4f
-#define XLP_SYS_CORE_DFS_BYP_CTRL_REG 0x50
-#define XLP_SYS_CORE_DFS_PHA_CTRL_REG 0x51
-#define XLP_SYS_CORE_DFS_DIV_INC_CTRL_REG 0x52
-#define XLP_SYS_CORE_DFS_DIV_DEC_CTRL_REG 0x53
-#define XLP_SYS_CORE_DFS_DIV_VALUE_REG 0x54
-#define XLP_SYS_RESET_REG 0x55
-#define XLP_SYS_DFS_DIS_CTRL_REG 0x56
-#define XLP_SYS_DFS_RST_CTRL_REG 0x57
-#define XLP_SYS_DFS_BYP_CTRL_REG 0x58
-#define XLP_SYS_DFS_DIV_INC_CTRL_REG 0x59
-#define XLP_SYS_DFS_DIV_DEC_CTRL_REG 0x5a
-#define XLP_SYS_DFS_DIV_VALUE0_REG 0x5b
-#define XLP_SYS_DFS_DIV_VALUE1_REG 0x5c
-#define XLP_SYS_SENSE_AMP_DLY_REG 0x5d
-#define XLP_SYS_SOC_SENSE_AMP_DLY_REG 0x5e
-#define XLP_SYS_CTRL0_REG 0x5f
-#define XLP_SYS_CTRL1_REG 0x60
-#define XLP_SYS_TIMEOUT_BS1_REG 0x61
-#define XLP_SYS_BYTE_SWAP_REG 0x62
-#define XLP_SYS_VRM_VID_REG 0x63
-#define XLP_SYS_PWR_RAM_CMD_REG 0x64
-#define XLP_SYS_PWR_RAM_ADDR_REG 0x65
-#define XLP_SYS_PWR_RAM_DATA0_REG 0x66
-#define XLP_SYS_PWR_RAM_DATA1_REG 0x67
-#define XLP_SYS_PWR_RAM_DATA2_REG 0x68
-#define XLP_SYS_PWR_UCODE_REG 0x69
-#define XLP_SYS_CPU0_PWR_STATUS_REG 0x6a
-#define XLP_SYS_CPU1_PWR_STATUS_REG 0x6b
-#define XLP_SYS_CPU2_PWR_STATUS_REG 0x6c
-#define XLP_SYS_CPU3_PWR_STATUS_REG 0x6d
-#define XLP_SYS_CPU4_PWR_STATUS_REG 0x6e
-#define XLP_SYS_CPU5_PWR_STATUS_REG 0x6f
-#define XLP_SYS_CPU6_PWR_STATUS_REG 0x70
-#define XLP_SYS_CPU7_PWR_STATUS_REG 0x71
-#define XLP_SYS_STATUS_REG 0x72
-#define XLP_SYS_INT_POL_REG 0x73
-#define XLP_SYS_INT_TYPE_REG 0x74
-#define XLP_SYS_INT_STATUS_REG 0x75
-#define XLP_SYS_INT_MASK0_REG 0x76
-#define XLP_SYS_INT_MASK1_REG 0x77
-#define XLP_SYS_UCO_S_ECC_REG 0x78
-#define XLP_SYS_UCO_M_ECC_REG 0x79
-#define XLP_SYS_UCO_ADDR_REG 0x7a
-#define XLP_SYS_UCO_INSTR_REG 0x7b
-#define XLP_SYS_MEM_BIST0_REG 0x7c
-#define XLP_SYS_MEM_BIST1_REG 0x7d
-#define XLP_SYS_MEM_BIST2_REG 0x7e
-#define XLP_SYS_MEM_BIST3_REG 0x7f
-#define XLP_SYS_MEM_BIST4_REG 0x80
-#define XLP_SYS_MEM_BIST5_REG 0x81
-#define XLP_SYS_MEM_BIST6_REG 0x82
-#define XLP_SYS_MEM_BIST7_REG 0x83
-#define XLP_SYS_MEM_BIST8_REG 0x84
-#define XLP_SYS_MEM_BIST9_REG 0x85
-#define XLP_SYS_MEM_BIST10_REG 0x86
-#define XLP_SYS_MEM_BIST11_REG 0x87
-#define XLP_SYS_MEM_BIST12_REG 0x88
-#define XLP_SYS_SCRTCH0_REG 0x89
-#define XLP_SYS_SCRTCH1_REG 0x8a
-#define XLP_SYS_SCRTCH2_REG 0x8b
-#define XLP_SYS_SCRTCH3_REG 0x8c
+#define SYS_CHIP_RESET 0x00
+#define SYS_POWER_ON_RESET_CFG 0x01
+#define SYS_EFUSE_DEVICE_CFG_STATUS0 0x02
+#define SYS_EFUSE_DEVICE_CFG_STATUS1 0x03
+#define SYS_EFUSE_DEVICE_CFG_STATUS2 0x04
+#define SYS_EFUSE_DEVICE_CFG3 0x05
+#define SYS_EFUSE_DEVICE_CFG4 0x06
+#define SYS_EFUSE_DEVICE_CFG5 0x07
+#define SYS_EFUSE_DEVICE_CFG6 0x08
+#define SYS_EFUSE_DEVICE_CFG7 0x09
+#define SYS_PLL_CTRL 0x0a
+#define SYS_CPU_RESET 0x0b
+#define SYS_CPU_NONCOHERENT_MODE 0x0d
+#define SYS_CORE_DFS_DIS_CTRL 0x0e
+#define SYS_CORE_DFS_RST_CTRL 0x0f
+#define SYS_CORE_DFS_BYP_CTRL 0x10
+#define SYS_CORE_DFS_PHA_CTRL 0x11
+#define SYS_CORE_DFS_DIV_INC_CTRL 0x12
+#define SYS_CORE_DFS_DIV_DEC_CTRL 0x13
+#define SYS_CORE_DFS_DIV_VALUE 0x14
+#define SYS_RESET 0x15
+#define SYS_DFS_DIS_CTRL 0x16
+#define SYS_DFS_RST_CTRL 0x17
+#define SYS_DFS_BYP_CTRL 0x18
+#define SYS_DFS_DIV_INC_CTRL 0x19
+#define SYS_DFS_DIV_DEC_CTRL 0x1a
+#define SYS_DFS_DIV_VALUE0 0x1b
+#define SYS_DFS_DIV_VALUE1 0x1c
+#define SYS_SENSE_AMP_DLY 0x1d
+#define SYS_SOC_SENSE_AMP_DLY 0x1e
+#define SYS_CTRL0 0x1f
+#define SYS_CTRL1 0x20
+#define SYS_TIMEOUT_BS1 0x21
+#define SYS_BYTE_SWAP 0x22
+#define SYS_VRM_VID 0x23
+#define SYS_PWR_RAM_CMD 0x24
+#define SYS_PWR_RAM_ADDR 0x25
+#define SYS_PWR_RAM_DATA0 0x26
+#define SYS_PWR_RAM_DATA1 0x27
+#define SYS_PWR_RAM_DATA2 0x28
+#define SYS_PWR_UCODE 0x29
+#define SYS_CPU0_PWR_STATUS 0x2a
+#define SYS_CPU1_PWR_STATUS 0x2b
+#define SYS_CPU2_PWR_STATUS 0x2c
+#define SYS_CPU3_PWR_STATUS 0x2d
+#define SYS_CPU4_PWR_STATUS 0x2e
+#define SYS_CPU5_PWR_STATUS 0x2f
+#define SYS_CPU6_PWR_STATUS 0x30
+#define SYS_CPU7_PWR_STATUS 0x31
+#define SYS_STATUS 0x32
+#define SYS_INT_POL 0x33
+#define SYS_INT_TYPE 0x34
+#define SYS_INT_STATUS 0x35
+#define SYS_INT_MASK0 0x36
+#define SYS_INT_MASK1 0x37
+#define SYS_UCO_S_ECC 0x38
+#define SYS_UCO_M_ECC 0x39
+#define SYS_UCO_ADDR 0x3a
+#define SYS_UCO_INSTR 0x3b
+#define SYS_MEM_BIST0 0x3c
+#define SYS_MEM_BIST1 0x3d
+#define SYS_MEM_BIST2 0x3e
+#define SYS_MEM_BIST3 0x3f
+#define SYS_MEM_BIST4 0x40
+#define SYS_MEM_BIST5 0x41
+#define SYS_MEM_BIST6 0x42
+#define SYS_MEM_BIST7 0x43
+#define SYS_MEM_BIST8 0x44
+#define SYS_MEM_BIST9 0x45
+#define SYS_MEM_BIST10 0x46
+#define SYS_MEM_BIST11 0x47
+#define SYS_MEM_BIST12 0x48
+#define SYS_SCRTCH0 0x49
+#define SYS_SCRTCH1 0x4a
+#define SYS_SCRTCH2 0x4b
+#define SYS_SCRTCH3 0x4c
#if !defined(LOCORE) && !defined(__ASSEMBLY__)
-#define nlm_rdreg_sys(b, r) nlm_read_reg_kseg(b,r)
-#define nlm_wreg_sys(b, r, v) nlm_write_reg_kseg(b,r,v)
-#define nlm_pcibase_sys(node) nlm_pcicfg_base(XLP_IO_SYS_OFFSET(node))
-#define nlm_regbase_sys(node) nlm_pcibase_sys(node)
+#define nlm_read_sys_reg(b, r) nlm_read_reg(b, r)
+#define nlm_write_sys_reg(b, r, v) nlm_write_reg(b, r, v)
+#define nlm_get_sys_pcibase(node) nlm_pcicfg_base(XLP_IO_SYS_OFFSET(node))
+#define nlm_get_sys_regbase(node) (nlm_get_sys_pcibase(node) + XLP_IO_PCI_HDRSZ)
#endif
-
#endif
diff --git a/sys/mips/nlm/hal/uart.h b/sys/mips/nlm/hal/uart.h
index 9eebb49ba671e..ce11c849428c3 100644
--- a/sys/mips/nlm/hal/uart.h
+++ b/sys/mips/nlm/hal/uart.h
@@ -25,127 +25,121 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
+ * NETLOGIC_BSD
* $FreeBSD$
- * NETLOGIC_BSD */
+ */
-#ifndef __XLP_UART_H__
-#define __XLP_UART_H__
+#ifndef __XLP_HAL_UART_H__
+#define __XLP_HAL_UART_H__
/* UART Specific registers */
-#define XLP_UART_RX_DATA_REG 0x40
-#define XLP_UART_TX_DATA_REG 0x40
+#define UART_RX_DATA 0x00
+#define UART_TX_DATA 0x00
-#define XLP_UART_INT_EN_REG 0x41
-#define XLP_UART_INT_ID_REG 0x42
-#define XLP_UART_FIFO_CTL_REG 0x42
-#define XLP_UART_LINE_CTL_REG 0x43
-#define XLP_UART_MODEM_CTL_REG 0x44
-#define XLP_UART_LINE_STS_REG 0x45
-#define XLP_UART_MODEM_STS_REG 0x46
+#define UART_INT_EN 0x01
+#define UART_INT_ID 0x02
+#define UART_FIFO_CTL 0x02
+#define UART_LINE_CTL 0x03
+#define UART_MODEM_CTL 0x04
+#define UART_LINE_STS 0x05
+#define UART_MODEM_STS 0x06
-#define XLP_UART_DIVISOR0_REG 0x40
-#define XLP_UART_DIVISOR1_REG 0x41
+#define UART_DIVISOR0 0x00
+#define UART_DIVISOR1 0x01
-#define XLP_UART_BASE_BAUD (133000000/16)
-#define XLP_UART_BAUD_DIVISOR(baud) (XLP_UART_BASE_BAUD / baud)
+#define BASE_BAUD (XLP_IO_CLK/16)
+#define BAUD_DIVISOR(baud) (BASE_BAUD / baud)
/* LCR mask values */
-#define LCR_5BITS 0x00
-#define LCR_6BITS 0x01
-#define LCR_7BITS 0x02
-#define LCR_8BITS 0x03
-#define LCR_STOPB 0x04
-#define LCR_PENAB 0x08
-#define LCR_PODD 0x00
-#define LCR_PEVEN 0x10
-#define LCR_PONE 0x20
-#define LCR_PZERO 0x30
-#define LCR_SBREAK 0x40
-#define LCR_EFR_ENABLE 0xbf
-#define LCR_DLAB 0x80
+#define LCR_5BITS 0x00
+#define LCR_6BITS 0x01
+#define LCR_7BITS 0x02
+#define LCR_8BITS 0x03
+#define LCR_STOPB 0x04
+#define LCR_PENAB 0x08
+#define LCR_PODD 0x00
+#define LCR_PEVEN 0x10
+#define LCR_PONE 0x20
+#define LCR_PZERO 0x30
+#define LCR_SBREAK 0x40
+#define LCR_EFR_ENABLE 0xbf
+#define LCR_DLAB 0x80
/* MCR mask values */
-#define MCR_DTR 0x01
-#define MCR_RTS 0x02
-#define MCR_DRS 0x04
-#define MCR_IE 0x08
-#define MCR_LOOPBACK 0x10
+#define MCR_DTR 0x01
+#define MCR_RTS 0x02
+#define MCR_DRS 0x04
+#define MCR_IE 0x08
+#define MCR_LOOPBACK 0x10
/* FCR mask values */
-#define FCR_RCV_RST 0x02
-#define FCR_XMT_RST 0x04
-#define FCR_RX_LOW 0x00
-#define FCR_RX_MEDL 0x40
-#define FCR_RX_MEDH 0x80
-#define FCR_RX_HIGH 0xc0
+#define FCR_RCV_RST 0x02
+#define FCR_XMT_RST 0x04
+#define FCR_RX_LOW 0x00
+#define FCR_RX_MEDL 0x40
+#define FCR_RX_MEDH 0x80
+#define FCR_RX_HIGH 0xc0
/* IER mask values */
-#define IER_ERXRDY 0x1
-#define IER_ETXRDY 0x2
-#define IER_ERLS 0x4
-#define IER_EMSC 0x8
-
-/* uart IRQ info */
-#define XLP_NODE0_UART0_IRQ 17
-#define XLP_NODE1_UART0_IRQ 18
-#define XLP_NODE2_UART0_IRQ 19
-#define XLP_NODE3_UART0_IRQ 20
-#define XLP_NODE0_UART1_IRQ 21
-#define XLP_NODE1_UART1_IRQ 22
-#define XLP_NODE2_UART1_IRQ 23
-#define XLP_NODE3_UART1_IRQ 24
+#define IER_ERXRDY 0x1
+#define IER_ETXRDY 0x2
+#define IER_ERLS 0x4
+#define IER_EMSC 0x8
#if !defined(LOCORE) && !defined(__ASSEMBLY__)
-#define nlm_rdreg_uart(b, r) nlm_read_reg_kseg(b,r)
-#define nlm_wreg_uart(b, r, v) nlm_write_reg_kseg(b,r,v)
-#define nlm_pcibase_uart(node, inst) nlm_pcicfg_base(XLP_IO_UART_OFFSET(node, inst))
-#define nlm_regbase_uart(node, inst) nlm_pcibase_uart(node, inst)
+#define nlm_read_uart_reg(b, r) nlm_read_reg(b, r)
+#define nlm_write_uart_reg(b, r, v) nlm_write_reg(b, r, v)
+#define nlm_get_uart_pcibase(node, inst) \
+ nlm_pcicfg_base(XLP_IO_UART_OFFSET(node, inst))
+#define nlm_get_uart_regbase(node, inst) \
+ (nlm_get_uart_pcibase(node, inst) + XLP_IO_PCI_HDRSZ)
-static __inline__ void
+static inline void
nlm_uart_set_baudrate(uint64_t base, int baud)
{
uint32_t lcr;
- lcr = nlm_rdreg_uart(base, XLP_UART_LINE_CTL_REG);
+ lcr = nlm_read_uart_reg(base, UART_LINE_CTL);
/* enable divisor register, and write baud values */
- nlm_wreg_uart(base, XLP_UART_LINE_CTL_REG, lcr | (1 << 7));
- nlm_wreg_uart(base, XLP_UART_DIVISOR0_REG,
- (XLP_UART_BAUD_DIVISOR(baud) & 0xff));
- nlm_wreg_uart(base, XLP_UART_DIVISOR1_REG,
- ((XLP_UART_BAUD_DIVISOR(baud) >> 8) & 0xff));
+ nlm_write_uart_reg(base, UART_LINE_CTL, lcr | (1 << 7));
+ nlm_write_uart_reg(base, UART_DIVISOR0,
+ (BAUD_DIVISOR(baud) & 0xff));
+ nlm_write_uart_reg(base, UART_DIVISOR1,
+ ((BAUD_DIVISOR(baud) >> 8) & 0xff));
/* restore default lcr */
- nlm_wreg_uart(base, XLP_UART_LINE_CTL_REG, lcr);
+ nlm_write_uart_reg(base, UART_LINE_CTL, lcr);
}
-static __inline__ void
-nlm_outbyte (uint64_t base, char c)
+static inline void
+nlm_uart_outbyte(uint64_t base, char c)
{
uint32_t lsr;
for (;;) {
- lsr = nlm_rdreg_uart(base, XLP_UART_LINE_STS_REG);
- if (lsr & 0x20) break;
+ lsr = nlm_read_uart_reg(base, UART_LINE_STS);
+ if (lsr & 0x20)
+ break;
}
- nlm_wreg_uart(base, XLP_UART_TX_DATA_REG, (int)c);
+ nlm_write_uart_reg(base, UART_TX_DATA, (int)c);
}
-static __inline__ char
-nlm_inbyte (uint64_t base)
+static inline char
+nlm_uart_inbyte(uint64_t base)
{
int data, lsr;
- for(;;) {
- lsr = nlm_rdreg_uart(base, XLP_UART_LINE_STS_REG);
- if (lsr & 0x80) { /* parity/frame/break-error - push a zero */
+ for (;;) {
+ lsr = nlm_read_uart_reg(base, UART_LINE_STS);
+ if (lsr & 0x80) { /* parity/frame/break-error - push a zero */
data = 0;
break;
}
- if (lsr & 0x01) { /* Rx data */
- data = nlm_rdreg_uart(base, XLP_UART_RX_DATA_REG);
+ if (lsr & 0x01) { /* Rx data */
+ data = nlm_read_uart_reg(base, UART_RX_DATA);
break;
}
}
@@ -153,9 +147,9 @@ nlm_inbyte (uint64_t base)
return (char)data;
}
-static __inline__ int
+static inline int
nlm_uart_init(uint64_t base, int baud, int databits, int stopbits,
- int parity, int int_en, int loopback)
+ int parity, int int_en, int loopback)
{
uint32_t lcr;
@@ -175,22 +169,20 @@ nlm_uart_init(uint64_t base, int baud, int databits, int stopbits,
lcr |= parity << 3;
/* setup default lcr */
- nlm_wreg_uart(base, XLP_UART_LINE_CTL_REG, lcr);
+ nlm_write_uart_reg(base, UART_LINE_CTL, lcr);
/* Reset the FIFOs */
- nlm_wreg_uart(base, XLP_UART_LINE_CTL_REG, FCR_RCV_RST | FCR_XMT_RST);
+ nlm_write_uart_reg(base, UART_LINE_CTL, FCR_RCV_RST | FCR_XMT_RST);
nlm_uart_set_baudrate(base, baud);
if (loopback)
- nlm_wreg_uart(base, XLP_UART_MODEM_CTL_REG, 0x1f);
+ nlm_write_uart_reg(base, UART_MODEM_CTL, 0x1f);
if (int_en)
- nlm_wreg_uart(base, XLP_UART_INT_EN_REG, IER_ERXRDY | IER_ETXRDY);
+ nlm_write_uart_reg(base, UART_INT_EN, IER_ERXRDY | IER_ETXRDY);
return 0;
}
-
#endif /* !LOCORE && !__ASSEMBLY__ */
-#endif /* __XLP_UART_H__ */
-
+#endif /* __XLP_HAL_UART_H__ */
diff --git a/sys/mips/nlm/hal/usb.h b/sys/mips/nlm/hal/usb.h
new file mode 100644
index 0000000000000..ba8515a9646a1
--- /dev/null
+++ b/sys/mips/nlm/hal/usb.h
@@ -0,0 +1,59 @@
+/*-
+ * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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.
+ *
+ * NETLOGIC_BSD
+ * $FreeBSD$
+ */
+
+#ifndef __NLM_USB_H__
+#define __NLM_USB_H__
+
+#define USB_CTL_0 0x01
+#define USB_PHY_0 0x0A
+#define USB_PHY_RESET 0x01
+#define USB_PHY_PORT_RESET_0 0x10
+#define USB_PHY_PORT_RESET_1 0x20
+#define USB_CONTROLLER_RESET 0x01
+#define USB_INT_STATUS 0x0E
+#define USB_INT_EN 0x0F
+#define USB_PHY_INTERRUPT_EN 0x01
+#define USB_OHCI_INTERRUPT_EN 0x02
+#define USB_OHCI_INTERRUPT1_EN 0x04
+#define USB_OHCI_INTERRUPT2_EN 0x08
+#define USB_CTRL_INTERRUPT_EN 0x10
+
+
+#if !defined(LOCORE) && !defined(__ASSEMBLY__)
+
+#define nlm_read_usb_reg(b, r) nlm_read_reg(b,r)
+#define nlm_write_usb_reg(b, r, v) nlm_write_reg(b,r,v)
+#define nlm_get_usb_pcibase(node, inst) nlm_pcicfg_base(XLP_IO_USB_OFFSET(node, inst))
+#define nlm_get_usb_hcd_base(node, inst) nlm_xkphys_map_pcibar0(nlm_get_usb_pcibase(node, inst))
+#define nlm_get_usb_regbase(node, inst) (nlm_get_usb_pcibase(node, inst) + XLP_IO_PCI_HDRSZ)
+
+#endif
+#endif
diff --git a/sys/mips/nlm/intern_dev.c b/sys/mips/nlm/intern_dev.c
new file mode 100644
index 0000000000000..ec237e41df6db
--- /dev/null
+++ b/sys/mips/nlm/intern_dev.c
@@ -0,0 +1,86 @@
+/*-
+ * Copyright (c) 2011 Netlogic Microsystems Inc.
+ *
+ * (based on pci/ignore_pci.c)
+ * Copyright (c) 2000 Michael Smith <msmith@freebsd.org>
+ * Copyright (c) 2000 BSDi
+ * 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$");
+
+/*
+ * 'Ignore' driver - eats devices that show up errnoeously on PCI
+ * but shouldn't ever be listed or handled by a driver.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+
+#include <dev/pci/pcivar.h>
+
+#include <mips/nlm/hal/haldefs.h>
+#include <mips/nlm/hal/iomap.h>
+
+static int nlm_soc_pci_probe(device_t dev);
+
+static device_method_t nlm_soc_pci_methods[] = {
+ DEVMETHOD(device_probe, nlm_soc_pci_probe),
+ DEVMETHOD(device_attach, bus_generic_attach),
+ { 0, 0 }
+};
+
+static driver_t nlm_soc_pci_driver = {
+ "nlm_soc_pci",
+ nlm_soc_pci_methods,
+ 0,
+};
+
+static devclass_t nlm_soc_pci_devclass;
+DRIVER_MODULE(nlm_soc_pci, pci, nlm_soc_pci_driver, nlm_soc_pci_devclass, 0, 0);
+
+static int
+nlm_soc_pci_probe(device_t dev)
+{
+ if (pci_get_vendor(dev) != PCI_VENDOR_NETLOGIC)
+ return(ENXIO);
+
+ /* Ignore SoC internal devices */
+ switch (pci_get_device(dev)) {
+ case PCI_DEVICE_ID_NLM_ICI:
+ case PCI_DEVICE_ID_NLM_PIC:
+ case PCI_DEVICE_ID_NLM_FMN:
+ device_set_desc(dev, "Netlogic Internal");
+ device_quiet(dev);
+ return(-10000);
+
+ default:
+ return(ENXIO);
+ }
+}
diff --git a/sys/mips/nlm/interrupt.h b/sys/mips/nlm/interrupt.h
index 41904ebd13d0c..342f1d3f0e05b 100644
--- a/sys/mips/nlm/interrupt.h
+++ b/sys/mips/nlm/interrupt.h
@@ -25,8 +25,9 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
+ * NETLOGIC_BSD
* $FreeBSD$
- * NETLOGIC_BSD */
+ */
#ifndef _RMI_INTERRUPT_H_
#define _RMI_INTERRUPT_H_
diff --git a/sys/mips/nlm/intr_machdep.c b/sys/mips/nlm/intr_machdep.c
index 4862356443630..782043e2366fb 100644
--- a/sys/mips/nlm/intr_machdep.c
+++ b/sys/mips/nlm/intr_machdep.c
@@ -46,9 +46,9 @@ __FBSDID("$FreeBSD$");
#include <machine/trap.h>
#include <machine/hwfunc.h>
-#include <mips/nlm/hal/mmio.h>
+#include <mips/nlm/hal/haldefs.h>
#include <mips/nlm/hal/iomap.h>
-#include <mips/nlm/hal/cop0.h>
+#include <mips/nlm/hal/mips-extns.h>
#include <mips/nlm/interrupt.h>
#include <mips/nlm/hal/pic.h>
#include <mips/nlm/xlp.h>
diff --git a/sys/mips/nlm/iodi.c b/sys/mips/nlm/iodi.c
deleted file mode 100644
index 3b372bb916b31..0000000000000
--- a/sys/mips/nlm/iodi.c
+++ /dev/null
@@ -1,233 +0,0 @@
-/*-
- * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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.
- *
- * NETLOGIC_BSD */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#define __RMAN_RESOURCE_VISIBLE
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/interrupt.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/module.h>
-#include <sys/mutex.h>
-#include <sys/reboot.h>
-#include <sys/rman.h>
-
-#include <vm/vm.h>
-#include <vm/vm_param.h>
-#include <vm/pmap.h>
-
-#include <machine/cpu.h>
-#include <machine/bus.h>
-#include <machine/intr_machdep.h>
-
-#include <mips/nlm/hal/mmio.h>
-#include <mips/nlm/hal/iomap.h>
-#include <mips/nlm/hal/pic.h>
-#include <mips/nlm/hal/uart.h>
-#include <mips/nlm/hal/cop2.h>
-#include <mips/nlm/hal/fmn.h>
-
-#include <mips/nlm/msgring.h>
-#include <mips/nlm/xlp.h>
-#include <mips/nlm/board.h>
-
-extern void iodi_activateirqs(void);
-
-extern bus_space_tag_t uart_bus_space_mem;
-
-static struct resource *iodi_alloc_resource(device_t, device_t, int, int *,
- u_long, u_long, u_long, u_int);
-
-static int iodi_activate_resource(device_t, device_t, int, int,
- struct resource *);
-struct iodi_softc *iodi_softc; /* There can be only one. */
-
-static int
-iodi_setup_intr(device_t dev, device_t child,
- struct resource *ires, int flags, driver_filter_t *filt,
- driver_intr_t *intr, void *arg, void **cookiep)
-{
- const char *name = device_get_name(child);
- int unit = device_get_unit(child);
-
- if (strcmp(name, "uart") == 0) {
- /* Note: in xlp, all pic interrupts are level triggered */
- nlm_pic_write_irt_id(xlp_pic_base, XLP_PIC_IRT_UART0_INDEX, 1, 0,
- xlp_irt_to_irq(XLP_PIC_IRT_UART0_INDEX), 0, 0, 0x1);
-
- cpu_establish_hardintr("uart", filt, intr, arg,
- xlp_irt_to_irq(XLP_PIC_IRT_UART0_INDEX), flags, cookiep);
- } else if (strcmp(name, "ehci") == 0) {
- if (unit == 0) {
- nlm_pic_write_irt_id(xlp_pic_base, XLP_PIC_IRT_EHCI0_INDEX, 1, 0,
- xlp_irt_to_irq(XLP_PIC_IRT_EHCI0_INDEX), 0, 0, 0x1);
-
- cpu_establish_hardintr("ehci0", filt, intr, arg,
- xlp_irt_to_irq(XLP_PIC_IRT_EHCI0_INDEX), flags, cookiep);
- } else if (unit == 1) {
- nlm_pic_write_irt_id(xlp_pic_base, XLP_PIC_IRT_EHCI1_INDEX, 1, 0,
- xlp_irt_to_irq(XLP_PIC_IRT_EHCI1_INDEX), 0, 0, 0x1);
-
- cpu_establish_hardintr("ehci1", filt, intr, arg,
- xlp_irt_to_irq(XLP_PIC_IRT_EHCI1_INDEX), flags, cookiep);
-
- }
- } else if (strcmp(name, "xlp_sdhci") == 0) {
- nlm_pic_write_irt_id(xlp_pic_base, XLP_PIC_IRT_MMC_INDEX, 1, 0,
- xlp_irt_to_irq(XLP_PIC_IRT_MMC_INDEX), 0, 0, 0x1);
-
- cpu_establish_hardintr("xlp_sdhci", filt, intr, arg,
- xlp_irt_to_irq(XLP_PIC_IRT_MMC_INDEX), flags, cookiep);
-
- }
-
- return (0);
-}
-
-static struct resource *
-iodi_alloc_resource(device_t bus, device_t child, int type, int *rid,
- u_long start, u_long end, u_long count, u_int flags)
-{
- struct resource *res = malloc(sizeof(*res), M_DEVBUF, M_WAITOK);
- const char *name = device_get_name(child);
- int unit;
-
- switch (type) {
- case SYS_RES_IRQ:
- device_printf(bus, "IRQ resource - for %s %lx-%lx\n",
- device_get_nameunit(child), start, end);
- break;
-
- case SYS_RES_IOPORT:
- device_printf(bus, "IOPORT resource - for %s %lx-%lx\n",
- device_get_nameunit(child), start, end);
- break;
-
- case SYS_RES_MEMORY:
- device_printf(bus, "MEMORY resource - for %s %lx-%lx\n",
- device_get_nameunit(child), start, end);
- break;
- }
-
- unit = device_get_unit(child);
- if (strcmp(name, "uart") == 0) {
- if (unit == 0) {
- res->r_bushandle = nlm_regbase_uart(0, 0) + XLP_IO_PCI_HDRSZ;
- } else if ( unit == 1) {
- res->r_bushandle = nlm_regbase_uart(0, 1) + XLP_IO_PCI_HDRSZ;
- } else
- printf("%s: Unknown uart unit\n", __FUNCTION__);
-
- res->r_bustag = uart_bus_space_mem;
- }
-
- return (res);
-}
-
-static int
-iodi_activate_resource(device_t bus, device_t child, int type, int rid,
- struct resource *r)
-{
- return (0);
-}
-/* prototypes */
-static int iodi_probe(device_t);
-static int iodi_attach(device_t);
-static void iodi_identify(driver_t *, device_t);
-
-int
-iodi_probe(device_t dev)
-{
- return 0;
-}
-
-void
-iodi_identify(driver_t *driver, device_t parent)
-{
-
- BUS_ADD_CHILD(parent, 0, "iodi", 0);
-}
-
-
-int
-iodi_attach(device_t dev)
-{
- device_t tmpd;
- char desc[32];
- int i;
-
- device_printf(dev, "IODI - Initialize message ring.\n");
- xlp_msgring_iodi_config();
-
- /*
- * Attach each devices
- */
- device_add_child(dev, "uart", 0);
- device_add_child(dev, "xlp_i2c", 0);
- device_add_child(dev, "xlp_i2c", 1);
- device_add_child(dev, "ehci", 0);
- device_add_child(dev, "ehci", 1);
- device_add_child(dev, "xlp_sdhci", 0);
-
- for (i=0; i < XLP_NUM_NODES; i++) {
- tmpd = device_add_child(dev, "xlpnae", i);
- device_set_ivars(tmpd, &xlp_board_info.nodes[i].nae_ivars);
- snprintf(desc, sizeof(desc), "XLP NAE %d", i);
- device_set_desc_copy(tmpd, desc);
- }
-
- bus_generic_probe(dev);
- bus_generic_attach(dev);
- return 0;
-}
-
-static device_method_t iodi_methods[] = {
- DEVMETHOD(device_probe, iodi_probe),
- DEVMETHOD(device_attach, iodi_attach),
- DEVMETHOD(device_identify, iodi_identify),
- DEVMETHOD(bus_alloc_resource, iodi_alloc_resource),
- DEVMETHOD(bus_activate_resource, iodi_activate_resource),
- DEVMETHOD(bus_add_child, bus_generic_add_child),
- DEVMETHOD(bus_setup_intr, iodi_setup_intr),
- {0, 0},
-};
-
-static driver_t iodi_driver = {
- "iodi",
- iodi_methods,
- 1 /* no softc */
-};
-static devclass_t iodi_devclass;
-
-DRIVER_MODULE(iodi, nexus, iodi_driver, iodi_devclass, 0, 0);
diff --git a/sys/mips/nlm/mpreset.S b/sys/mips/nlm/mpreset.S
index c56bd9f053d32..95b2440b10eae 100644
--- a/sys/mips/nlm/mpreset.S
+++ b/sys/mips/nlm/mpreset.S
@@ -25,8 +25,9 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
+ * NETLOGIC_BSD
* $FreeBSD$
- * NETLOGIC_BSD */
+ */
#include <machine/asm.h>
#include <machine/cpu.h>
@@ -35,6 +36,8 @@
#include <mips/nlm/hal/sys.h>
#include <mips/nlm/hal/cpucontrol.h>
+#define SYS_REG_KSEG1(node, reg) (0xa0000000 + XLP_DEFAULT_IO_BASE + \
+ XLP_IO_SYS_OFFSET(node) + XLP_IO_PCI_HDRSZ + (reg) * 4)
#include "assym.s"
.text
@@ -59,7 +62,7 @@ VECTOR(XLPResetEntry, unknown)
nor t0, t0, zero /* mask with core id bit clear */
/* clear CPU non-coherent bit */
- li t2, XLP_DEFAULT_IO_BASE_KSEG1 + XLP_IO_SYS_OFFSET(0) + XLP_SYS_CPU_NONCOHERENT_MODE_REG * 4
+ li t2, SYS_REG_KSEG1(0, SYS_CPU_NONCOHERENT_MODE)
lw t1, 0(t2)
and t1, t1, t0
sw t1, 0(t2)
@@ -109,7 +112,7 @@ LEAF(xlp_enable_threads)
sd gp, 80(sp)
sd ra, 88(sp)
/* Use register number to work in o32 and n32 */
- li $9, ((XLP_CPU_BLOCKID_MAP << 8) | XLP_BLKID_MAP_THREADMODE)
+ li $9, ((CPU_BLOCKID_MAP << 8) | MAP_THREADMODE)
move $8, a0
sync
.word 0x71280019 /* mtcr t0, t1*/
diff --git a/sys/mips/nlm/msgring.h b/sys/mips/nlm/msgring.h
index b951569cf3833..e57a0fe216509 100644
--- a/sys/mips/nlm/msgring.h
+++ b/sys/mips/nlm/msgring.h
@@ -25,10 +25,10 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
+ * NETLOGIC_BSD
* $FreeBSD$
- * NETLOGIC_BSD */
+ */
-/** FIXME **/
extern uint32_t xlp_msg_thread_mask;
typedef void (*msgring_handler)(int, int, int, int, struct nlm_fmn_msg *, void *);
int register_msgring_handler(int startb, int endb, msgring_handler action,
@@ -41,4 +41,3 @@ void xlp_cpu_msgring_handler(int bucket, int size, int code, int stid,
void nlm_cms_credit_setup(int credit);
void xlp_msgring_iodi_config(void);
-
diff --git a/sys/mips/nlm/uart_bus_xlp_iodi.c b/sys/mips/nlm/uart_bus_xlp_iodi.c
index 236900abf3846..ca68d68f64767 100644
--- a/sys/mips/nlm/uart_bus_xlp_iodi.c
+++ b/sys/mips/nlm/uart_bus_xlp_iodi.c
@@ -42,7 +42,7 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/resource.h>
-#include <mips/nlm/hal/mmio.h>
+#include <mips/nlm/hal/haldefs.h>
#include <mips/nlm/hal/iomap.h>
#include <mips/nlm/hal/uart.h>
@@ -78,9 +78,9 @@ uart_iodi_probe(device_t dev)
sc->sc_class = &uart_ns8250_class;
bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas));
sc->sc_sysdev->bas.bst = rmi_bus_space;
- sc->sc_sysdev->bas.bsh = nlm_regbase_uart(0, 0) + XLP_IO_PCI_HDRSZ;
+ sc->sc_sysdev->bas.bsh = nlm_get_uart_regbase(0, 0);
sc->sc_bas.bst = rmi_bus_space;
- sc->sc_bas.bsh = nlm_regbase_uart(0, 0) + XLP_IO_PCI_HDRSZ;
+ sc->sc_bas.bsh = nlm_get_uart_regbase(0, 0);
/* regshft = 2, rclk = 66000000, rid = 0, chan = 0 */
return (uart_bus_probe(dev, 2, 133000000, 0, 0));
}
diff --git a/sys/mips/nlm/uart_cpu_mips_xlp.c b/sys/mips/nlm/uart_cpu_xlp.c
index 07bdd6adbc04d..0e476d58c06ee 100644
--- a/sys/mips/nlm/uart_cpu_mips_xlp.c
+++ b/sys/mips/nlm/uart_cpu_xlp.c
@@ -53,27 +53,51 @@ __FBSDID("$FreeBSD$");
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
-#include <mips/nlm/hal/mmio.h>
+#include <mips/nlm/hal/haldefs.h>
#include <mips/nlm/hal/iomap.h>
#include <mips/nlm/hal/uart.h>
bus_space_tag_t uart_bus_space_io;
bus_space_tag_t uart_bus_space_mem;
+/*
+ * need a special bus space for this, because the Netlogic SoC
+ * UART allows only 32 bit access to its registers
+ */
+static struct bus_space nlm_uart_bussp;
+
+static u_int8_t
+nlm_uart_bussp_read_1(void *tag, bus_space_handle_t handle,
+ bus_size_t offset)
+{
+ return (u_int8_t)(*(volatile u_int32_t *)(handle + offset));
+}
+
+static void
+nlm_uart_bussp_write_1(void *tag, bus_space_handle_t handle,
+ bus_size_t offset, u_int8_t value)
+{
+ *(volatile u_int32_t *)(handle + offset) = value;
+}
+
int
uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
{
return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0);
}
-
int
uart_cpu_getdev(int devtype, struct uart_devinfo *di)
{
+ /* Create custom bus space */
+ memcpy(&nlm_uart_bussp, rmi_bus_space, sizeof(nlm_uart_bussp));
+ nlm_uart_bussp.bs_r_1 = nlm_uart_bussp_read_1;
+ nlm_uart_bussp.bs_w_1 = nlm_uart_bussp_write_1;
+
di->ops = uart_getops(&uart_ns8250_class);
di->bas.chan = 0;
- di->bas.bst = rmi_bus_space;
- di->bas.bsh = nlm_regbase_uart(0, 0) + XLP_IO_PCI_HDRSZ;
+ di->bas.bst = &nlm_uart_bussp;
+ di->bas.bsh = nlm_get_uart_regbase(0, 0);
di->bas.regshft = 2;
/* divisor = rclk / (baudrate * 16); */
@@ -84,6 +108,6 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di)
di->parity = UART_PARITY_NONE;
uart_bus_space_io = NULL;
- uart_bus_space_mem = rmi_bus_space;
+ uart_bus_space_mem = &nlm_uart_bussp;
return (0);
}
diff --git a/sys/mips/nlm/uart_pci_xlp.c b/sys/mips/nlm/uart_pci_xlp.c
new file mode 100644
index 0000000000000..16c795c158278
--- /dev/null
+++ b/sys/mips/nlm/uart_pci_xlp.c
@@ -0,0 +1,85 @@
+/*-
+ * Copyright (c) 2011 Netlogic Microsystems Inc.
+ *
+ * (based on dev/uart/uart_bus_pci.c)
+ * Copyright (c) 2006 Marcel Moolenaar
+ * Copyright (c) 2001 M. Warner Losh
+ * 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/conf.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
+
+#include <dev/pci/pcivar.h>
+
+#include <mips/nlm/hal/haldefs.h>
+#include <mips/nlm/hal/iomap.h>
+#include <mips/nlm/hal/uart.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_bus.h>
+
+static int uart_soc_probe(device_t dev);
+
+static device_method_t uart_soc_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, uart_soc_probe),
+ DEVMETHOD(device_attach, uart_bus_attach),
+ DEVMETHOD(device_detach, uart_bus_detach),
+ { 0, 0 }
+};
+
+static driver_t uart_soc_driver = {
+ uart_driver_name,
+ uart_soc_methods,
+ sizeof(struct uart_softc),
+};
+
+static int
+uart_soc_probe(device_t dev)
+{
+ struct uart_softc *sc;
+ uint64_t ubase;
+
+ if (pci_get_vendor(dev) != PCI_VENDOR_NETLOGIC ||
+ pci_get_device(dev) != PCI_DEVICE_ID_NLM_UART)
+ return (ENXIO);
+
+ ubase = nlm_get_uart_regbase(0, 0);
+ sc = device_get_softc(dev);
+ sc->sc_class = &uart_ns8250_class;
+ device_set_desc(dev, "Netlogic SoC UART");
+ return (uart_bus_probe(dev, 2, 133000000, 0, 0));
+}
+
+DRIVER_MODULE(uart_soc, pci, uart_soc_driver, uart_devclass, 0, 0);
diff --git a/sys/mips/nlm/usb_init.c b/sys/mips/nlm/usb_init.c
new file mode 100644
index 0000000000000..32a6165c60ded
--- /dev/null
+++ b/sys/mips/nlm/usb_init.c
@@ -0,0 +1,92 @@
+/*-
+ * Copyright 2003-2011 Netlogic Microsystems (Netlogic). 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 Netlogic Microsystems ``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 NETLOGIC 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.
+ *
+ * NETLOGIC_BSD */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/param.h>
+#include <sys/kernel.h>
+
+#include <mips/nlm/hal/haldefs.h>
+#include <mips/nlm/hal/iomap.h>
+#include <mips/nlm/hal/cpuinfo.h>
+#include <mips/nlm/hal/usb.h>
+
+#include <mips/nlm/xlp.h>
+
+
+static void
+nlm_usb_intr_en(int node, int port)
+{
+ uint32_t val;
+ uint64_t port_addr;
+
+ port_addr = nlm_get_usb_regbase(node, port);
+ val = nlm_read_usb_reg(port_addr, USB_INT_EN);
+ val = USB_CTRL_INTERRUPT_EN | USB_OHCI_INTERRUPT_EN |
+ USB_OHCI_INTERRUPT1_EN | USB_CTRL_INTERRUPT_EN |
+ USB_OHCI_INTERRUPT_EN | USB_OHCI_INTERRUPT2_EN;
+ nlm_write_usb_reg(port_addr, USB_INT_EN, val);
+}
+
+static void
+nlm_usb_hw_reset(int node, int port)
+{
+ uint64_t port_addr;
+ uint32_t val;
+
+ /* reset USB phy */
+ port_addr = nlm_get_usb_regbase(node, port);
+ val = nlm_read_usb_reg(port_addr, USB_PHY_0);
+ val &= ~(USB_PHY_RESET | USB_PHY_PORT_RESET_0 | USB_PHY_PORT_RESET_1);
+ nlm_write_usb_reg(port_addr, USB_PHY_0, val);
+
+ DELAY(100);
+ val = nlm_read_usb_reg(port_addr, USB_CTL_0);
+ val &= ~(USB_CONTROLLER_RESET);
+ val |= 0x4;
+ nlm_write_usb_reg(port_addr, USB_CTL_0, val);
+}
+
+static void
+nlm_usb_init(void)
+{
+ /* XXX: should be checking if these are in Device mode here */
+ printf("Initialize USB Interface\n");
+ nlm_usb_hw_reset(0, 0);
+ nlm_usb_hw_reset(0, 3);
+
+ /* Enable PHY interrupts */
+ nlm_usb_intr_en(0, 0);
+ nlm_usb_intr_en(0, 3);
+}
+
+SYSINIT(nlm_usb_init, SI_SUB_CPU, SI_ORDER_MIDDLE,
+ nlm_usb_init, NULL);
diff --git a/sys/mips/nlm/xlp.h b/sys/mips/nlm/xlp.h
index 5c79aaf992d29..b4008919593fe 100644
--- a/sys/mips/nlm/xlp.h
+++ b/sys/mips/nlm/xlp.h
@@ -25,25 +25,25 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
+ * NETLOGIC_BSD
* $FreeBSD$
- * NETLOGIC_BSD */
+ */
#ifndef __NLM_XLP_H__
#define __NLM_XLP_H__
#include <mips/nlm/hal/pic.h>
-#define XLP_PIC_IRT_UART0_IRQ 9
-#define XLP_PIC_IRT_UART1_IRQ 10
-
-#define XLP_PIC_IRT_PCIE0_IRQ 11
-#define XLP_PIC_IRT_PCIE1_IRQ 12
-#define XLP_PIC_IRT_PCIE2_IRQ 13
-#define XLP_PIC_IRT_PCIE3_IRQ 14
+#define PIC_UART_0_IRQ 9
+#define PIC_UART_1_IRQ 10
-#define XLP_PIC_IRT_EHCI0_IRQ 39
-#define XLP_PIC_IRT_EHCI1_IRQ 42
-#define XLP_PIC_IRT_MMC_IRQ 43
+#define PIC_PCIE_0_IRQ 11
+#define PIC_PCIE_1_IRQ 12
+#define PIC_PCIE_2_IRQ 13
+#define PIC_PCIE_3_IRQ 14
+#define PIC_EHCI_0_IRQ 39
+#define PIC_EHCI_1_IRQ 42
+#define PIC_MMC_IRQ 43
#ifndef LOCORE
/*
@@ -59,30 +59,28 @@ extern int xlp_hwtid_to_cpuid[];
extern void xlp_enable_threads(int code);
#endif
-extern uint64_t xlp_pic_base; /* TODO just for node 0 now */
-
static __inline__ int
xlp_irt_to_irq(int irt)
{
switch (irt) {
- case XLP_PIC_IRT_MMC_INDEX :
- return XLP_PIC_IRT_MMC_IRQ;
- case XLP_PIC_IRT_EHCI0_INDEX :
- return XLP_PIC_IRT_EHCI0_IRQ;
- case XLP_PIC_IRT_EHCI1_INDEX :
- return XLP_PIC_IRT_EHCI1_IRQ;
- case XLP_PIC_IRT_UART0_INDEX :
- return XLP_PIC_IRT_UART0_IRQ;
- case XLP_PIC_IRT_UART1_INDEX :
- return XLP_PIC_IRT_UART1_IRQ;
- case XLP_PIC_IRT_PCIE_LINK0_INDEX :
- return XLP_PIC_IRT_PCIE0_IRQ;
- case XLP_PIC_IRT_PCIE_LINK1_INDEX :
- return XLP_PIC_IRT_PCIE1_IRQ;
- case XLP_PIC_IRT_PCIE_LINK2_INDEX :
- return XLP_PIC_IRT_PCIE2_IRQ;
- case XLP_PIC_IRT_PCIE_LINK3_INDEX :
- return XLP_PIC_IRT_PCIE3_IRQ;
+ case PIC_IRT_MMC_INDEX :
+ return PIC_MMC_IRQ;
+ case PIC_IRT_EHCI_0_INDEX :
+ return PIC_EHCI_0_IRQ;
+ case PIC_IRT_EHCI_1_INDEX :
+ return PIC_EHCI_1_IRQ;
+ case PIC_IRT_UART_0_INDEX :
+ return PIC_UART_0_IRQ;
+ case PIC_IRT_UART_1_INDEX :
+ return PIC_UART_1_IRQ;
+ case PIC_IRT_PCIE_LINK_0_INDEX :
+ return PIC_PCIE_0_IRQ;
+ case PIC_IRT_PCIE_LINK_1_INDEX :
+ return PIC_PCIE_1_IRQ;
+ case PIC_IRT_PCIE_LINK_2_INDEX :
+ return PIC_PCIE_2_IRQ;
+ case PIC_IRT_PCIE_LINK_3_INDEX :
+ return PIC_PCIE_3_IRQ;
default: panic("Bad IRT %d\n", irt);
}
}
@@ -91,24 +89,24 @@ static __inline__ int
xlp_irq_to_irt(int irq)
{
switch (irq) {
- case XLP_PIC_IRT_MMC_IRQ :
- return XLP_PIC_IRT_MMC_INDEX;
- case XLP_PIC_IRT_EHCI0_IRQ :
- return XLP_PIC_IRT_EHCI0_INDEX;
- case XLP_PIC_IRT_EHCI1_IRQ :
- return XLP_PIC_IRT_EHCI1_INDEX;
- case XLP_PIC_IRT_UART0_IRQ :
- return XLP_PIC_IRT_UART0_INDEX;
- case XLP_PIC_IRT_UART1_IRQ :
- return XLP_PIC_IRT_UART1_INDEX;
- case XLP_PIC_IRT_PCIE0_IRQ :
- return XLP_PIC_IRT_PCIE_LINK0_INDEX;
- case XLP_PIC_IRT_PCIE1_IRQ :
- return XLP_PIC_IRT_PCIE_LINK1_INDEX;
- case XLP_PIC_IRT_PCIE2_IRQ :
- return XLP_PIC_IRT_PCIE_LINK2_INDEX;
- case XLP_PIC_IRT_PCIE3_IRQ :
- return XLP_PIC_IRT_PCIE_LINK3_INDEX;
+ case PIC_MMC_IRQ :
+ return PIC_IRT_MMC_INDEX;
+ case PIC_EHCI_0_IRQ :
+ return PIC_IRT_EHCI_0_INDEX;
+ case PIC_EHCI_1_IRQ :
+ return PIC_IRT_EHCI_1_INDEX;
+ case PIC_UART_0_IRQ :
+ return PIC_IRT_UART_0_INDEX;
+ case PIC_UART_1_IRQ :
+ return PIC_IRT_UART_1_INDEX;
+ case PIC_PCIE_0_IRQ :
+ return PIC_IRT_PCIE_LINK_0_INDEX;
+ case PIC_PCIE_1_IRQ :
+ return PIC_IRT_PCIE_LINK_1_INDEX;
+ case PIC_PCIE_2_IRQ :
+ return PIC_IRT_PCIE_LINK_2_INDEX;
+ case PIC_PCIE_3_IRQ :
+ return PIC_IRT_PCIE_LINK_3_INDEX;
default: panic("Bad IRQ %d\n", irq);
}
}
@@ -117,15 +115,15 @@ static __inline__ int
xlp_irq_is_picintr(int irq)
{
switch (irq) {
- case XLP_PIC_IRT_MMC_IRQ : return 1;
- case XLP_PIC_IRT_EHCI0_IRQ : return 1;
- case XLP_PIC_IRT_EHCI1_IRQ : return 1;
- case XLP_PIC_IRT_UART0_IRQ : return 1;
- case XLP_PIC_IRT_UART1_IRQ : return 1;
- case XLP_PIC_IRT_PCIE0_IRQ : return 1;
- case XLP_PIC_IRT_PCIE1_IRQ : return 1;
- case XLP_PIC_IRT_PCIE2_IRQ : return 1;
- case XLP_PIC_IRT_PCIE3_IRQ : return 1;
+ case PIC_MMC_IRQ : return 1;
+ case PIC_EHCI_0_IRQ : return 1;
+ case PIC_EHCI_1_IRQ : return 1;
+ case PIC_UART_0_IRQ : return 1;
+ case PIC_UART_1_IRQ : return 1;
+ case PIC_PCIE_0_IRQ : return 1;
+ case PIC_PCIE_1_IRQ : return 1;
+ case PIC_PCIE_2_IRQ : return 1;
+ case PIC_PCIE_3_IRQ : return 1;
default: return 0;
}
}
diff --git a/sys/mips/nlm/xlp_machdep.c b/sys/mips/nlm/xlp_machdep.c
index 6b4bde4c730f3..30430fad53cac 100644
--- a/sys/mips/nlm/xlp_machdep.c
+++ b/sys/mips/nlm/xlp_machdep.c
@@ -71,9 +71,8 @@ __FBSDID("$FreeBSD$");
#include <machine/smp.h>
#include <mips/nlm/hal/mips-extns.h>
-#include <mips/nlm/hal/mmio.h>
+#include <mips/nlm/hal/haldefs.h>
#include <mips/nlm/hal/iomap.h>
-#include <mips/nlm/hal/cop0.h>
#include <mips/nlm/hal/sys.h>
#include <mips/nlm/hal/pic.h>
#include <mips/nlm/hal/uart.h>
@@ -93,7 +92,7 @@ int xlp_argc;
char **xlp_argv, **xlp_envp;
uint64_t xlp_cpu_frequency;
-uint64_t nlm_pcicfg_baseaddr = MIPS_PHYS_TO_KSEG1(XLP_DEFAULT_IO_BASE);
+uint64_t xlp_io_base = MIPS_PHYS_TO_KSEG1(XLP_DEFAULT_IO_BASE);
int xlp_ncores;
int xlp_threads_per_core;
@@ -112,7 +111,7 @@ xlp_setup_core(void)
{
uint64_t reg;
- reg = nlm_mfcr(XLP_LSU_DEFEATURE);
+ reg = nlm_mfcr(LSU_DEFEATURE);
/* Enable Unaligned and L2HPE */
reg |= (1 << 30) | (1 << 23);
/*
@@ -123,12 +122,12 @@ xlp_setup_core(void)
reg |= (1ull << 31);
/* Clear S1RCM - A0 errata */
reg &= ~0xeull;
- nlm_mtcr(XLP_LSU_DEFEATURE, reg);
+ nlm_mtcr(LSU_DEFEATURE, reg);
- reg = nlm_mfcr(XLP_SCHED_DEFEATURE);
+ reg = nlm_mfcr(SCHED_DEFEATURE);
/* Experimental: Disable BRU accepting ALU ops - A0 errata */
reg |= (1 << 24);
- nlm_mtcr(XLP_SCHED_DEFEATURE, reg);
+ nlm_mtcr(SCHED_DEFEATURE, reg);
}
static void
@@ -281,8 +280,9 @@ mips_init(void)
unsigned int
platform_get_timecount(struct timecounter *tc __unused)
{
+ uint64_t count = nlm_pic_read_timer(xlp_pic_base, PIC_CLOCK_TIMER);
- return ((unsigned int)~nlm_pic_read_systimer(xlp_pic_base, 7));
+ return (unsigned int)~count;
}
static void
@@ -292,21 +292,21 @@ xlp_pic_init(void)
platform_get_timecount, /* get_timecount */
0, /* no poll_pps */
~0U, /* counter_mask */
- XLP_PIC_TIMER_FREQ, /* frequency */
+ XLP_IO_CLK, /* frequency */
"XLRPIC", /* name */
2000, /* quality (adjusted in code) */
};
int i;
- xlp_pic_base = nlm_regbase_pic(0); /* TOOD: Add other nodes */
+ xlp_pic_base = nlm_get_pic_regbase(0); /* TOOD: Add other nodes */
printf("Initializing PIC...@%jx\n", (uintmax_t)xlp_pic_base);
/* Bind all PIC irqs to cpu 0 */
- for(i = 0; i < XLP_PIC_MAX_IRT; i++) {
- nlm_pic_write_irt_raw(xlp_pic_base, i, 0, 0, 1, 0,
+ for(i = 0; i < PIC_NUM_IRTS; i++) {
+ nlm_pic_write_irt(xlp_pic_base, i, 0, 0, 1, 0,
1, 0, 0x1);
}
- nlm_pic_set_systimer(xlp_pic_base, 7, ~0ULL, 0, 0, 0, 0);
+ nlm_pic_set_timer(xlp_pic_base, PIC_CLOCK_TIMER, ~0ULL, 0, 0);
platform_timecounter = &pic_timecounter;
}
@@ -322,15 +322,15 @@ xlp_pic_init(void)
static void
xlp_mem_init(void)
{
- uint64_t bridgebase = nlm_regbase_bridge(0); /* TOOD: Add other nodes */
+ uint64_t bridgebase = nlm_get_bridge_regbase(0); /* TOOD: Add other nodes */
vm_size_t physsz = 0;
uint64_t base, lim, val;
int i, j;
for (i = 0, j = 0; i < 8; i++) {
- val = nlm_rdreg_bridge(bridgebase, XLP_BRIDGE_DRAM_BAR_REG(i));
+ val = nlm_read_bridge_reg(bridgebase, BRIDGE_DRAM_BAR(i));
base = ((val >> 12) & 0xfffff) << 20;
- val = nlm_rdreg_bridge(bridgebase, XLP_BRIDGE_DRAM_LIMIT_REG(i));
+ val = nlm_read_bridge_reg(bridgebase, BRIDGE_DRAM_LIMIT(i));
lim = ((val >> 12) & 0xfffff) << 20;
/* BAR not enabled */
@@ -396,17 +396,22 @@ xlp_mem_init(void)
/* setup final entry with 0 */
phys_avail[j] = phys_avail[j + 1] = 0;
+
+ /* copy phys_avail to dump_avail */
+ for(i = 0; i <= j + 1; i++)
+ dump_avail[i] = phys_avail[i];
+
realmem = physmem = btoc(physsz);
}
static uint32_t
xlp_get_cpu_frequency(void)
{
- uint64_t sysbase = nlm_regbase_sys(0);
+ uint64_t sysbase = nlm_get_sys_regbase(0);
unsigned int pll_divf, pll_divr, dfs_div, num, denom;
uint32_t val;
- val = nlm_rdreg_sys(sysbase, XLP_SYS_POWER_ON_RESET_REG);
+ val = nlm_read_sys_reg(sysbase, SYS_POWER_ON_RESET_CFG);
pll_divf = (val >> 10) & 0x7f;
pll_divr = (val >> 8) & 0x3;
dfs_div = (val >> 17) & 0x3;
@@ -520,9 +525,9 @@ platform_trap_enter(void)
void
platform_reset(void)
{
- uint64_t sysbase = nlm_regbase_sys(0);
+ uint64_t sysbase = nlm_get_sys_regbase(0);
- nlm_wreg_sys(sysbase, XLP_SYS_CHIP_RESET_REG, 1);
+ nlm_write_sys_reg(sysbase, SYS_CHIP_RESET, 1);
for(;;)
__asm __volatile("wait");
}
@@ -544,7 +549,7 @@ int
platform_start_ap(int cpuid)
{
uint32_t coremask, val;
- uint64_t sysbase = nlm_regbase_sys(0);
+ uint64_t sysbase = nlm_get_sys_regbase(0);
int hwtid = xlp_cpuid_to_hwtid[cpuid];
int core, thr;
@@ -555,21 +560,21 @@ platform_start_ap(int cpuid)
coremask = 1u << core;
/* Enable core clock */
- val = nlm_rdreg_sys(sysbase, XLP_SYS_CORE_DFS_DIS_CTRL_REG);
+ val = nlm_read_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL);
val &= ~coremask;
- nlm_wreg_sys(sysbase, XLP_SYS_CORE_DFS_DIS_CTRL_REG, val);
+ nlm_write_sys_reg(sysbase, SYS_CORE_DFS_DIS_CTRL, val);
/* Remove CPU Reset */
- val = nlm_rdreg_sys(sysbase, XLP_SYS_CPU_RESET_REG);
+ val = nlm_read_sys_reg(sysbase, SYS_CPU_RESET);
val &= ~coremask & 0xff;
- nlm_wreg_sys(sysbase, XLP_SYS_CPU_RESET_REG, val);
+ nlm_write_sys_reg(sysbase, SYS_CPU_RESET, val);
if (bootverbose)
printf("Waking up core %d ...", core);
/* Poll for CPU to mark itself coherent */
do {
- val = nlm_rdreg_sys(sysbase, XLP_SYS_CPU_NONCOHERENT_MODE_REG);
+ val = nlm_read_sys_reg(sysbase, SYS_CPU_NONCOHERENT_MODE);
} while ((val & coremask) != 0);
if (bootverbose)
printf("Done\n");
@@ -628,7 +633,7 @@ void
platform_ipi_send(int cpuid)
{
- nlm_pic_send_ipi(xlp_pic_base, 0, xlp_cpuid_to_hwtid[cpuid],
+ nlm_pic_send_ipi(xlp_pic_base, xlp_cpuid_to_hwtid[cpuid],
platform_ipi_intrnum(), 0);
}
diff --git a/sys/mips/nlm/xlp_pci.c b/sys/mips/nlm/xlp_pci.c
new file mode 100644
index 0000000000000..09e214ebab934
--- /dev/null
+++ b/sys/mips/nlm/xlp_pci.c
@@ -0,0 +1,666 @@
+/*-
+ * Copyright (c) 2003-2009 RMI Corporation
+ * 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.
+ * 3. Neither the name of RMI Corporation, 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 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.
+ *
+ * NETLOGIC_BSD */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/types.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/rman.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+
+#include <sys/pciio.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_bus.h>
+#include <dev/uart/uart_cpu.h>
+
+#include <machine/bus.h>
+#include <machine/md_var.h>
+#include <machine/intr_machdep.h>
+#include <machine/cpuregs.h>
+
+#include <mips/nlm/hal/haldefs.h>
+#include <mips/nlm/interrupt.h>
+#include <mips/nlm/hal/iomap.h>
+#include <mips/nlm/hal/mips-extns.h>
+#include <mips/nlm/hal/pic.h>
+#include <mips/nlm/hal/pcibus.h>
+#include <mips/nlm/hal/uart.h>
+#include <mips/nlm/xlp.h>
+
+#include "pcib_if.h"
+
+struct xlp_pcib_softc {
+ bus_dma_tag_t sc_pci_dmat; /* PCI DMA tag pointer */
+};
+
+static devclass_t pcib_devclass;
+static struct rman irq_rman, port_rman, mem_rman, emul_rman;
+
+static void
+xlp_pci_init_resources(void)
+{
+
+ irq_rman.rm_start = 0;
+ irq_rman.rm_end = 255;
+ irq_rman.rm_type = RMAN_ARRAY;
+ irq_rman.rm_descr = "PCI Mapped Interrupts";
+ if (rman_init(&irq_rman)
+ || rman_manage_region(&irq_rman, 0, 255))
+ panic("pci_init_resources irq_rman");
+
+ port_rman.rm_start = 0;
+ port_rman.rm_end = ~0ul;
+ port_rman.rm_type = RMAN_ARRAY;
+ port_rman.rm_descr = "I/O ports";
+ if (rman_init(&port_rman)
+ || rman_manage_region(&port_rman, 0x14000000UL, 0x15ffffffUL))
+ panic("pci_init_resources port_rman");
+
+ mem_rman.rm_start = 0;
+ mem_rman.rm_end = ~0ul;
+ mem_rman.rm_type = RMAN_ARRAY;
+ mem_rman.rm_descr = "I/O memory";
+ if (rman_init(&mem_rman)
+ || rman_manage_region(&mem_rman, 0xd0000000ULL, 0xdfffffffULL))
+ panic("pci_init_resources mem_rman");
+
+ emul_rman.rm_start = 0;
+ emul_rman.rm_end = ~0ul;
+ emul_rman.rm_type = RMAN_ARRAY;
+ emul_rman.rm_descr = "Emulated MEMIO";
+ if (rman_init(&emul_rman)
+ || rman_manage_region(&emul_rman, 0x18000000ULL, 0x18ffffffULL))
+ panic("pci_init_resources emul_rman");
+
+}
+
+static int
+xlp_pcib_probe(device_t dev)
+{
+
+ device_set_desc(dev, "XLP PCI bus");
+
+ xlp_pci_init_resources();
+ return (0);
+}
+
+static int
+xlp_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+
+ switch (which) {
+ case PCIB_IVAR_DOMAIN:
+ *result = 0;
+ return (0);
+ case PCIB_IVAR_BUS:
+ *result = 0;
+ return (0);
+ }
+ return (ENOENT);
+}
+
+static int
+xlp_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t result)
+{
+ switch (which) {
+ case PCIB_IVAR_DOMAIN:
+ return (EINVAL);
+ case PCIB_IVAR_BUS:
+ return (EINVAL);
+ }
+ return (ENOENT);
+}
+
+static int
+xlp_pcib_maxslots(device_t dev)
+{
+
+ return (PCI_SLOTMAX);
+}
+
+static u_int32_t
+xlp_pcib_read_config(device_t dev, u_int b, u_int s, u_int f,
+ u_int reg, int width)
+{
+ uint32_t data = 0;
+ uint64_t cfgaddr;
+ int regindex = reg/sizeof(uint32_t);
+
+ cfgaddr = nlm_pcicfg_base(XLP_HDR_OFFSET(0, b, s, f));
+ if ((width == 2) && (reg & 1))
+ return 0xFFFFFFFF;
+ else if ((width == 4) && (reg & 3))
+ return 0xFFFFFFFF;
+
+ data = nlm_read_pci_reg(cfgaddr, regindex);
+
+ /*
+ * Fix up read data in some SoC devices
+ * to emulate complete PCIe header
+ */
+ if (b == 0) {
+ int dev = s % 8;
+
+ /* Fake intpin on config read for UART/I2C, USB, SD/Flash */
+ if (regindex == 0xf &&
+ (dev == 6 || dev == 2 || dev == 7))
+ data |= 0x1 << 8; /* Fake int pin */
+ }
+
+ if (width == 1)
+ return ((data >> ((reg & 3) << 3)) & 0xff);
+ else if (width == 2)
+ return ((data >> ((reg & 3) << 3)) & 0xffff);
+ else
+ return (data);
+}
+
+static void
+xlp_pcib_write_config(device_t dev, u_int b, u_int s, u_int f,
+ u_int reg, u_int32_t val, int width)
+{
+ uint64_t cfgaddr;
+ uint32_t data = 0;
+ int regindex = reg / sizeof(uint32_t);
+
+ cfgaddr = nlm_pcicfg_base(XLP_HDR_OFFSET(0, b, s, f));
+ if ((width == 2) && (reg & 1))
+ return;
+ else if ((width == 4) && (reg & 3))
+ return;
+
+ if (width == 1) {
+ data = nlm_read_pci_reg(cfgaddr, regindex);
+ data = (data & ~(0xff << ((reg & 3) << 3))) |
+ (val << ((reg & 3) << 3));
+ } else if (width == 2) {
+ data = nlm_read_pci_reg(cfgaddr, regindex);
+ data = (data & ~(0xffff << ((reg & 3) << 3))) |
+ (val << ((reg & 3) << 3));
+ } else {
+ data = val;
+ }
+
+ nlm_write_pci_reg(cfgaddr, regindex, data);
+
+ return;
+}
+
+static int
+xlp_pcib_attach(device_t dev)
+{
+ struct xlp_pcib_softc *sc;
+ sc = device_get_softc(dev);
+
+ device_add_child(dev, "pci", 0);
+ bus_generic_attach(dev);
+
+ return (0);
+}
+
+static void
+xlp_pcib_identify(driver_t * driver, device_t parent)
+{
+
+ BUS_ADD_CHILD(parent, 0, "pcib", 0);
+}
+
+/*
+ * XLS PCIe can have upto 4 links, and each link has its on IRQ
+ * Find the link on which the device is on
+ */
+static int
+xlp_pcie_link(device_t pcib, device_t dev)
+{
+ device_t parent, tmp;
+
+ /* find the lane on which the slot is connected to */
+ printf("xlp_pcie_link : bus %s dev %s\n", device_get_nameunit(pcib),
+ device_get_nameunit(dev));
+ tmp = dev;
+ while (1) {
+ parent = device_get_parent(tmp);
+ if (parent == NULL || parent == pcib) {
+ device_printf(dev, "Cannot find parent bus\n");
+ return (-1);
+ }
+ if (strcmp(device_get_nameunit(parent), "pci0") == 0)
+ break;
+ tmp = parent;
+ }
+ return (pci_get_function(tmp));
+}
+
+/*
+ * Find the IRQ for the link, each link has a different interrupt
+ * at the XLP pic
+ */
+static int
+xlp_pcie_link_irt(int link)
+{
+
+ if( (link < 0) || (link > 3))
+ return (-1);
+
+ return PIC_IRT_PCIE_LINK_INDEX(link);
+}
+
+static int
+xlp_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs)
+{
+ int i, link;
+
+ /*
+ * Each link has 32 MSIs that can be allocated, but for now
+ * we only support one device per link.
+ * msi_alloc() equivalent is needed when we start supporting
+ * bridges on the PCIe link.
+ */
+ link = xlp_pcie_link(pcib, dev);
+ if (link == -1)
+ return (ENXIO);
+
+ /*
+ * encode the irq so that we know it is a MSI interrupt when we
+ * setup interrupts
+ */
+ for (i = 0; i < count; i++)
+ irqs[i] = 64 + link * 32 + i;
+
+ return (0);
+}
+
+static int
+xlp_release_msi(device_t pcib, device_t dev, int count, int *irqs)
+{
+ device_printf(dev, "%s: msi release %d\n", device_get_nameunit(pcib),
+ count);
+ return (0);
+}
+
+static int
+xlp_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
+ uint32_t *data)
+{
+ int msi, irt;
+
+ if (irq >= 64) {
+ msi = irq - 64;
+ *addr = MIPS_MSI_ADDR(0);
+
+ irt = xlp_pcie_link_irt(msi/32);
+ if (irt != -1)
+ *data = MIPS_MSI_DATA(xlp_irt_to_irq(irt));
+ return (0);
+ } else {
+ device_printf(dev, "%s: map_msi for irq %d - ignored",
+ device_get_nameunit(pcib), irq);
+ return (ENXIO);
+ }
+}
+
+static void
+bridge_pcie_ack(int irq)
+{
+ uint32_t node,reg;
+ uint64_t base;
+
+ node = nlm_nodeid();
+ reg = PCIE_MSI_STATUS;
+
+ switch(irq) {
+ case PIC_PCIE_0_IRQ:
+ base = nlm_pcicfg_base(XLP_IO_PCIE0_OFFSET(node));
+ break;
+ case PIC_PCIE_1_IRQ:
+ base = nlm_pcicfg_base(XLP_IO_PCIE1_OFFSET(node));
+ break;
+ case PIC_PCIE_2_IRQ:
+ base = nlm_pcicfg_base(XLP_IO_PCIE2_OFFSET(node));
+ break;
+ case PIC_PCIE_3_IRQ:
+ base = nlm_pcicfg_base(XLP_IO_PCIE3_OFFSET(node));
+ break;
+ default:
+ return;
+ }
+
+ nlm_write_pci_reg(base, reg, 0xFFFFFFFF);
+
+ return;
+}
+
+static int
+mips_platform_pci_setup_intr(device_t dev, device_t child,
+ struct resource *irq, int flags, driver_filter_t *filt,
+ driver_intr_t *intr, void *arg, void **cookiep)
+{
+ int error = 0;
+ int xlpirq;
+ int node,base,val,link;
+ void *extra_ack;
+
+ error = rman_activate_resource(irq);
+ if (error)
+ return error;
+ if (rman_get_start(irq) != rman_get_end(irq)) {
+ device_printf(dev, "Interrupt allocation %lu != %lu\n",
+ rman_get_start(irq), rman_get_end(irq));
+ return (EINVAL);
+ }
+ xlpirq = rman_get_start(irq);
+ device_printf(dev, "setup intr %d\n", xlpirq);
+
+ if (strcmp(device_get_name(dev), "pcib") != 0) {
+ device_printf(dev, "ret 0 on dev\n");
+ return (0);
+ }
+
+ /*
+ * temporary hack for MSI, we support just one device per
+ * link, and assign the link interrupt to the device interrupt
+ */
+ if (xlpirq >= 64) {
+ xlpirq -= 64;
+ if (xlpirq % 32 != 0)
+ return (0);
+
+ node = nlm_nodeid();
+ link = (xlpirq / 32);
+ base = nlm_pcicfg_base(XLP_IO_PCIE_OFFSET(node,link));
+
+ /* MSI Interrupt Vector enable at bridge's configuration */
+ nlm_write_pci_reg(base, PCIE_MSI_EN, PCIE_MSI_VECTOR_INT_EN);
+
+ val = nlm_read_pci_reg(base, PCIE_INT_EN0);
+ /* MSI Interrupt enable at bridge's configuration */
+ nlm_write_pci_reg(base, PCIE_INT_EN0,
+ (val | PCIE_MSI_INT_EN));
+
+ /* legacy interrupt disable at bridge */
+ val = nlm_read_pci_reg(base, PCIE_BRIDGE_CMD);
+ nlm_write_pci_reg(base, PCIE_BRIDGE_CMD,
+ (val | PCIM_CMD_INTxDIS));
+
+ /* MSI address update at bridge */
+ val = nlm_read_pci_reg(base, PCIE_BRIDGE_MSI_ADDRL);
+ nlm_write_pci_reg(base, PCIE_BRIDGE_MSI_ADDRL,
+ (val | MSI_MIPS_ADDR_BASE));
+
+ val = nlm_read_pci_reg(base, PCIE_BRIDGE_MSI_CAP);
+ /* MSI capability enable at bridge */
+ nlm_write_pci_reg(base, PCIE_BRIDGE_MSI_CAP,
+ (val |
+ (PCIM_MSICTRL_MSI_ENABLE << 16) |
+ (PCIM_MSICTRL_MMC_32 << 16)));
+
+ xlpirq = xlp_pcie_link_irt(xlpirq / 32);
+ if (xlpirq == -1)
+ return (EINVAL);
+ xlpirq = xlp_irt_to_irq(xlpirq);
+ }
+ /* Set all irqs to CPU 0 for now */
+ nlm_pic_write_irt_direct(xlp_pic_base, xlp_irq_to_irt(xlpirq), 1, 0,
+ PIC_LOCAL_SCHEDULING, xlpirq, 0);
+ extra_ack = NULL;
+ if (xlpirq >= PIC_PCIE_0_IRQ &&
+ xlpirq <= PIC_PCIE_3_IRQ)
+ extra_ack = bridge_pcie_ack;
+ xlp_establish_intr(device_get_name(child), filt,
+ intr, arg, xlpirq, flags, cookiep, extra_ack);
+
+ return (0);
+}
+
+static int
+mips_platform_pci_teardown_intr(device_t dev, device_t child,
+ struct resource *irq, void *cookie)
+{
+ if (strcmp(device_get_name(child), "pci") == 0) {
+ /* if needed reprogram the pic to clear pcix related entry */
+ device_printf(dev, "teardown intr\n");
+ }
+ return (bus_generic_teardown_intr(dev, child, irq, cookie));
+}
+
+static void
+assign_soc_resource(device_t child, int type, u_long *startp, u_long *endp,
+ u_long *countp, struct rman **rm, bus_space_tag_t *bst, vm_offset_t *va)
+{
+ int devid = pci_get_device(child);
+ int inst = pci_get_function(child);
+ int node = pci_get_slot(child) / 8;
+
+ *rm = NULL;
+ *va = 0;
+ *bst = 0;
+ switch (devid) {
+ case PCI_DEVICE_ID_NLM_UART:
+ switch (type) {
+ case SYS_RES_IRQ:
+ *startp = *endp = PIC_UART_0_IRQ + inst;
+ *countp = 1;
+ break;
+ case SYS_RES_MEMORY:
+ *va = nlm_get_uart_regbase(node, inst);
+ *startp = MIPS_KSEG1_TO_PHYS(va);
+ *countp = 0x100;
+ *rm = &emul_rman;
+ *bst = uart_bus_space_mem;
+ break;
+ };
+ break;
+
+ case PCI_DEVICE_ID_NLM_EHCI:
+ if (type == SYS_RES_IRQ) {
+ if (inst == 0)
+ *startp = *endp = PIC_EHCI_0_IRQ;
+ else if (inst == 3)
+ *startp = *endp = PIC_EHCI_1_IRQ;
+ else
+ device_printf(child, "bad instance %d\n", inst);
+
+ *countp = 1;
+ }
+ break;
+ }
+
+ /* default to rmi_bus_space for SoC resources */
+ if (type == SYS_RES_MEMORY && *bst == 0)
+ *bst = rmi_bus_space;
+}
+
+static struct resource *
+xlp_pci_alloc_resource(device_t bus, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct rman *rm = NULL;
+ struct resource *rv;
+ vm_offset_t va = 0;
+ int needactivate = flags & RF_ACTIVE;
+ bus_space_tag_t bst = 0;
+
+ /*
+ * For SoC PCI devices, we have to assign resources correctly
+ * since the IRQ and MEM resources depend on the block.
+ * If the address is not from BAR0, then we use emul_rman
+ */
+ if (pci_get_bus(child) == 0 &&
+ pci_get_vendor(child) == PCI_VENDOR_NETLOGIC)
+ assign_soc_resource(child, type, &start, &end,
+ &count, &rm, &bst, &va);
+ if (rm == NULL) {
+ switch (type) {
+ case SYS_RES_IRQ:
+ rm = &irq_rman;
+ break;
+
+ case SYS_RES_IOPORT:
+ rm = &port_rman;
+ break;
+
+ case SYS_RES_MEMORY:
+ rm = &mem_rman;
+ break;
+
+ default:
+ return (0);
+ }
+ }
+
+ rv = rman_reserve_resource(rm, start, end, count, flags, child);
+ if (rv == 0)
+ return (0);
+
+ rman_set_rid(rv, *rid);
+
+ if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
+ if (va == 0)
+ va = (vm_offset_t)pmap_mapdev(start, count);
+ if (bst == 0)
+ bst = rmi_pci_bus_space;
+
+ rman_set_bushandle(rv, va);
+ rman_set_virtual(rv, (void *)va);
+ rman_set_bustag(rv, bst);
+ }
+
+ if (needactivate) {
+ if (bus_activate_resource(child, type, *rid, rv)) {
+ rman_release_resource(rv);
+ return (NULL);
+ }
+ }
+
+ return (rv);
+}
+
+static int
+xlp_pci_release_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *r)
+{
+
+ return (rman_release_resource(r));
+}
+
+static bus_dma_tag_t
+xlp_pci_get_dma_tag(device_t bus, device_t child)
+{
+ struct xlp_pcib_softc *sc;
+
+ sc = device_get_softc(bus);
+ return (sc->sc_pci_dmat);
+}
+
+static int
+xlp_pci_activate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *r)
+{
+
+ return (rman_activate_resource(r));
+}
+
+static int
+xlp_pci_deactivate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *r)
+{
+
+ return (rman_deactivate_resource(r));
+}
+
+static int
+mips_pci_route_interrupt(device_t bus, device_t dev, int pin)
+{
+ int irt, link;
+
+ /*
+ * Validate requested pin number.
+ */
+ device_printf(bus, "route %s %d", device_get_nameunit(dev), pin);
+ if ((pin < 1) || (pin > 4))
+ return (255);
+
+ link = xlp_pcie_link(bus, dev);
+ irt = xlp_pcie_link_irt(link);
+ if (irt != -1)
+ return (xlp_irt_to_irq(irt));
+
+ return (255);
+}
+
+static device_method_t xlp_pcib_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_identify, xlp_pcib_identify),
+ DEVMETHOD(device_probe, xlp_pcib_probe),
+ DEVMETHOD(device_attach, xlp_pcib_attach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_read_ivar, xlp_pcib_read_ivar),
+ DEVMETHOD(bus_write_ivar, xlp_pcib_write_ivar),
+ DEVMETHOD(bus_alloc_resource, xlp_pci_alloc_resource),
+ DEVMETHOD(bus_release_resource, xlp_pci_release_resource),
+ DEVMETHOD(bus_get_dma_tag, xlp_pci_get_dma_tag),
+ DEVMETHOD(bus_activate_resource, xlp_pci_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, xlp_pci_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, mips_platform_pci_setup_intr),
+ DEVMETHOD(bus_teardown_intr, mips_platform_pci_teardown_intr),
+
+ /* pcib interface */
+ DEVMETHOD(pcib_maxslots, xlp_pcib_maxslots),
+ DEVMETHOD(pcib_read_config, xlp_pcib_read_config),
+ DEVMETHOD(pcib_write_config, xlp_pcib_write_config),
+ DEVMETHOD(pcib_route_interrupt, mips_pci_route_interrupt),
+
+ DEVMETHOD(pcib_alloc_msi, xlp_alloc_msi),
+ DEVMETHOD(pcib_release_msi, xlp_release_msi),
+ DEVMETHOD(pcib_map_msi, xlp_map_msi),
+
+ {0, 0}
+};
+
+static driver_t xlp_pcib_driver = {
+ "pcib",
+ xlp_pcib_methods,
+ sizeof(struct xlp_pcib_softc),
+};
+
+DRIVER_MODULE(pcib, nexus, xlp_pcib_driver, pcib_devclass, 0, 0);
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index 2777e22c9d25e..ca8586c5c12fc 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -321,6 +321,7 @@ SUBDIR= ${_3dfx} \
vr \
vte \
vx \
+ ${_vxge} \
wb \
${_wi} \
wlan \
@@ -474,6 +475,7 @@ _sppp= sppp
_stg= stg
_streams= streams
_svr4= svr4
+_vxge= vxge
_wi= wi
_xe= xe
.if ${MK_ZFS} != "no" || defined(ALL_MODULES)
@@ -629,6 +631,7 @@ _tpm= tpm
_twa= twa
_vesa= vesa
_vmm= vmm
+_vxge= vxge
_x86bios= x86bios
_wi= wi
_wpi= wpi
diff --git a/sys/modules/dcons/Makefile b/sys/modules/dcons/Makefile
index 604242503971c..4a08b65923818 100644
--- a/sys/modules/dcons/Makefile
+++ b/sys/modules/dcons/Makefile
@@ -5,7 +5,7 @@
KMOD = dcons
SRCS = dcons.c dcons.h dcons_os.c dcons_os.h \
- opt_dcons.h opt_kdb.h opt_ddb.h opt_gdb.h opt_comconsole.h
+ opt_dcons.h opt_kdb.h opt_ddb.h opt_gdb.h
.if !defined(KERNBUILDDIR)
opt_kdb.h:
@@ -13,9 +13,6 @@ opt_kdb.h:
opt_ddb.h:
echo "#define DDB 1" > $@
-
-opt_comconsole.h:
- echo "#define ALT_BREAK_TO_DEBUGGER 1" > $@
.endif
CFLAGS+= -I${.CURDIR}/../..
diff --git a/sys/modules/ipfw/Makefile b/sys/modules/ipfw/Makefile
index 81ce838085d9d..ec9b3cc49c1af 100644
--- a/sys/modules/ipfw/Makefile
+++ b/sys/modules/ipfw/Makefile
@@ -8,7 +8,7 @@ KMOD= ipfw
SRCS= ip_fw2.c ip_fw_pfil.c
SRCS+= ip_fw_dynamic.c ip_fw_log.c
SRCS+= ip_fw_sockopt.c ip_fw_table.c
-SRCS+= opt_inet6.h opt_ipsec.h
+SRCS+= opt_inet6.h opt_ipfw.h opt_ipsec.h
CFLAGS+= -DIPFIREWALL
CFLAGS+= -I${.CURDIR}/../../contrib/pf
diff --git a/sys/modules/netgraph/ipfw/Makefile b/sys/modules/netgraph/ipfw/Makefile
index b40abcfbf57c2..cc3f0f24e2a0a 100644
--- a/sys/modules/netgraph/ipfw/Makefile
+++ b/sys/modules/netgraph/ipfw/Makefile
@@ -1,6 +1,20 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
KMOD= ng_ipfw
-SRCS= ng_ipfw.c
+SRCS= ng_ipfw.c opt_inet.h opt_inet6.h
+
+.if !defined(KERNBUILDDIR)
+
+.if ${MK_INET_SUPPORT} != "no"
+opt_inet.h:
+ echo "#define INET 1" > ${.TARGET}
+.endif
+.if ${MK_INET6_SUPPORT} != "no"
+opt_inet6.h:
+ echo "#define INET6 1" > ${.TARGET}
+.endif
+.endif
.include <bsd.kmod.mk>
diff --git a/sys/modules/portalfs/Makefile b/sys/modules/portalfs/Makefile
index ef6955b5d1416..dcd5966c26a85 100644
--- a/sys/modules/portalfs/Makefile
+++ b/sys/modules/portalfs/Makefile
@@ -4,6 +4,7 @@
KMOD= portalfs
SRCS= vnode_if.h \
- portal_vfsops.c portal_vnops.c
+ portal_vfsops.c portal_vnops.c \
+ opt_capsicum.h
.include <bsd.kmod.mk>
diff --git a/sys/modules/sio/Makefile b/sys/modules/sio/Makefile
index dc683ba31f3f0..057e9c614d42e 100644
--- a/sys/modules/sio/Makefile
+++ b/sys/modules/sio/Makefile
@@ -7,7 +7,7 @@
KMOD= sio
SRCS= bus_if.h card_if.h device_if.h isa_if.h pci_if.h serdev_if.h \
- opt_comconsole.h opt_compat.h opt_gdb.h opt_kdb.h opt_sio.h \
+ opt_compat.h opt_gdb.h opt_kdb.h opt_sio.h \
sio.c sio_pccard.c sio_pci.c sio_puc.c pccarddevs.h
.if ${MACHINE} == "pc98"
SRCS+= sio_cbus.c
diff --git a/sys/net/bpf.c b/sys/net/bpf.c
index e5165731dae7b..79c77a93278c1 100644
--- a/sys/net/bpf.c
+++ b/sys/net/bpf.c
@@ -652,10 +652,10 @@ bpf_dtor(void *data)
if (d->bd_bif)
bpf_detachd(d);
mtx_unlock(&bpf_mtx);
- selwakeuppri(&d->bd_sel, PRINET);
#ifdef MAC
mac_bpfdesc_destroy(d);
#endif /* MAC */
+ seldrain(&d->bd_sel);
knlist_destroy(&d->bd_sel.si_note);
callout_drain(&d->bd_callout);
bpf_freed(d);
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index 5ac4ef002dc61..c251653841f1a 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -85,6 +85,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/protosw.h>
#include <sys/systm.h>
+#include <sys/jail.h>
#include <sys/time.h>
#include <sys/socket.h> /* for net/if.h */
#include <sys/sockio.h>
@@ -560,7 +561,8 @@ bridge_clone_create(struct if_clone *ifc, int unit, caddr_t params)
{
struct bridge_softc *sc, *sc2;
struct ifnet *bifp, *ifp;
- int retry;
+ int fb, retry;
+ unsigned long hostid;
sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);
ifp = sc->sc_ifp = if_alloc(IFT_ETHER);
@@ -593,17 +595,30 @@ bridge_clone_create(struct if_clone *ifc, int unit, caddr_t params)
IFQ_SET_READY(&ifp->if_snd);
/*
- * Generate a random ethernet address with a locally administered
- * address.
+ * Generate an ethernet address with a locally administered address.
*
* Since we are using random ethernet addresses for the bridge, it is
* possible that we might have address collisions, so make sure that
* this hardware address isn't already in use on another bridge.
+ * The first try uses the hostid and falls back to arc4rand().
*/
+ fb = 0;
+ getcredhostid(curthread->td_ucred, &hostid);
for (retry = 1; retry != 0;) {
- arc4rand(sc->sc_defaddr, ETHER_ADDR_LEN, 1);
- sc->sc_defaddr[0] &= ~1; /* clear multicast bit */
- sc->sc_defaddr[0] |= 2; /* set the LAA bit */
+ if (fb || hostid == 0) {
+ arc4rand(sc->sc_defaddr, ETHER_ADDR_LEN, 1);
+ sc->sc_defaddr[0] &= ~1;/* clear multicast bit */
+ sc->sc_defaddr[0] |= 2; /* set the LAA bit */
+ } else {
+ sc->sc_defaddr[0] = 0x2;
+ sc->sc_defaddr[1] = (hostid >> 24) & 0xff;
+ sc->sc_defaddr[2] = (hostid >> 16) & 0xff;
+ sc->sc_defaddr[3] = (hostid >> 8 ) & 0xff;
+ sc->sc_defaddr[4] = hostid & 0xff;
+ sc->sc_defaddr[5] = ifp->if_dunit & 0xff;
+ }
+
+ fb = 1;
retry = 0;
mtx_lock(&bridge_list_mtx);
LIST_FOREACH(sc2, &bridge_list, sc_list) {
@@ -3083,6 +3098,7 @@ bridge_pfil(struct mbuf **mp, struct ifnet *bifp, struct ifnet *ifp, int dir)
args.m = *mp;
args.oif = ifp;
args.next_hop = NULL;
+ args.next_hop6 = NULL;
args.eh = &eh2;
args.inp = NULL; /* used by ipfw uid/gid/jail rules */
i = V_ip_fw_chk_ptr(&args);
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index aa8113bf550d5..1d16ae6c660e7 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -499,6 +499,7 @@ ether_ipfw_chk(struct mbuf **m0, struct ifnet *dst, int shared)
args.m = m; /* the packet we are looking at */
args.oif = dst; /* destination, if any */
args.next_hop = NULL; /* we do not support forward yet */
+ args.next_hop6 = NULL; /* we do not support forward yet */
args.eh = &save_eh; /* MAC header for bridged/MAC packets */
args.inp = NULL; /* used by ipfw uid/gid/jail rules */
i = V_ip_fw_chk_ptr(&args);
diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c
index d540966ab4cf3..6a3eb93e5a579 100644
--- a/sys/net/if_lagg.c
+++ b/sys/net/if_lagg.c
@@ -208,6 +208,7 @@ static moduledata_t lagg_mod = {
};
DECLARE_MODULE(if_lagg, lagg_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
+MODULE_VERSION(if_lagg, 1);
#if __FreeBSD_version >= 800000
/*
diff --git a/sys/net/if_tap.c b/sys/net/if_tap.c
index ad29da044997e..08c669ab3b89d 100644
--- a/sys/net/if_tap.c
+++ b/sys/net/if_tap.c
@@ -214,6 +214,7 @@ tap_destroy(struct tap_softc *tp)
KASSERT(!(tp->tap_flags & TAP_OPEN),
("%s flags is out of sync", ifp->if_xname));
+ seldrain(&tp->tap_rsel);
knlist_destroy(&tp->tap_rsel.si_note);
destroy_dev(tp->tap_dev);
ether_ifdetach(ifp);
diff --git a/sys/net/if_tun.c b/sys/net/if_tun.c
index d74c9fec28520..c5328848c7b72 100644
--- a/sys/net/if_tun.c
+++ b/sys/net/if_tun.c
@@ -259,6 +259,7 @@ tun_destroy(struct tun_softc *tp)
if_detach(TUN2IFP(tp));
if_free(TUN2IFP(tp));
destroy_dev(dev);
+ seldrain(&tp->tun_rsel);
knlist_destroy(&tp->tun_rsel.si_note);
mtx_destroy(&tp->tun_mtx);
cv_destroy(&tp->tun_cv);
diff --git a/sys/net/radix_mpath.c b/sys/net/radix_mpath.c
index ea84e5ce2282e..ee7826f6e3e9a 100644
--- a/sys/net/radix_mpath.c
+++ b/sys/net/radix_mpath.c
@@ -96,10 +96,7 @@ rt_mpath_matchgate(struct rtentry *rt, struct sockaddr *gate)
{
struct radix_node *rn;
- if (!rn_mpath_next((struct radix_node *)rt))
- return rt;
-
- if (!gate)
+ if (!gate || !rt->rt_gateway)
return NULL;
/* beyond here, we use rn as the master copy */
diff --git a/sys/net/route.c b/sys/net/route.c
index 9c7dfac542fab..d42b4c73b40eb 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -1478,7 +1478,7 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum)
*/
bzero((caddr_t)&info, sizeof(info));
info.rti_ifa = ifa;
- info.rti_flags = flags | ifa->ifa_flags;
+ info.rti_flags = flags | (ifa->ifa_flags & ~IFA_RTSELF);
info.rti_info[RTAX_DST] = dst;
/*
* doing this for compatibility reasons
diff --git a/sys/net80211/ieee80211_ht.c b/sys/net80211/ieee80211_ht.c
index 61c84e936f388..c49a17803bb7d 100644
--- a/sys/net80211/ieee80211_ht.c
+++ b/sys/net80211/ieee80211_ht.c
@@ -2207,7 +2207,7 @@ bar_tx_complete(struct ieee80211_node *ni, void *arg, int status)
callout_pending(&tap->txa_timer)) {
struct ieee80211com *ic = ni->ni_ic;
- if (status) /* ACK'd */
+ if (status == 0) /* ACK'd */
bar_stop_timer(tap);
ic->ic_bar_response(ni, tap, status);
/* NB: just let timer expire so we pace requests */
@@ -2219,7 +2219,7 @@ ieee80211_bar_response(struct ieee80211_node *ni,
struct ieee80211_tx_ampdu *tap, int status)
{
- if (status != 0) { /* got ACK */
+ if (status == 0) { /* got ACK */
IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_11N,
ni, "BAR moves BA win <%u:%u> (%u frames) txseq %u tid %u",
tap->txa_start,
@@ -2309,11 +2309,15 @@ ieee80211_send_bar(struct ieee80211_node *ni,
ni, "send BAR: tid %u ctl 0x%x start %u (attempt %d)",
tid, barctl, seq, tap->txa_attempts);
+ /*
+ * ic_raw_xmit will free the node reference
+ * regardless of queue/TX success or failure.
+ */
ret = ic->ic_raw_xmit(ni, m, NULL);
if (ret != 0) {
/* xmit failed, clear state flag */
tap->txa_flags &= ~IEEE80211_AGGR_BARPEND;
- goto bad;
+ return ret;
}
/* XXX hack against tx complete happening before timer is started */
if (tap->txa_flags & IEEE80211_AGGR_BARPEND)
diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c
index 6020144ef7c19..bcd3c2bdac5fe 100644
--- a/sys/net80211/ieee80211_output.c
+++ b/sys/net80211/ieee80211_output.c
@@ -2792,6 +2792,8 @@ ieee80211_beacon_update(struct ieee80211_node *ni,
struct ieee80211com *ic = ni->ni_ic;
int len_changed = 0;
uint16_t capinfo;
+ struct ieee80211_frame *wh;
+ ieee80211_seq seqno;
IEEE80211_LOCK(ic);
/*
@@ -2823,6 +2825,12 @@ ieee80211_beacon_update(struct ieee80211_node *ni,
return 1; /* just assume length changed */
}
+ wh = mtod(m, struct ieee80211_frame *);
+ seqno = ni->ni_txseqs[IEEE80211_NONQOS_TID]++;
+ *(uint16_t *)&wh->i_seq[0] =
+ htole16(seqno << IEEE80211_SEQ_SEQ_SHIFT);
+ M_SEQNO_SET(m, seqno);
+
/* XXX faster to recalculate entirely or just changes? */
capinfo = ieee80211_getcapinfo(vap, ni->ni_chan);
*bo->bo_caps = htole16(capinfo);
diff --git a/sys/net80211/ieee80211_proto.c b/sys/net80211/ieee80211_proto.c
index 8c8ee52981564..8dee3f7f32d46 100644
--- a/sys/net80211/ieee80211_proto.c
+++ b/sys/net80211/ieee80211_proto.c
@@ -1501,6 +1501,11 @@ ieee80211_csa_startswitch(struct ieee80211com *ic,
ieee80211_notify_csa(ic, c, mode, count);
}
+/*
+ * Complete the channel switch by transitioning all CSA VAPs to RUN.
+ * This is called by both the completion and cancellation functions
+ * so each VAP is placed back in the RUN state and can thus transmit.
+ */
static void
csa_completeswitch(struct ieee80211com *ic)
{
@@ -1518,15 +1523,27 @@ csa_completeswitch(struct ieee80211com *ic)
* Complete an 802.11h channel switch started by ieee80211_csa_startswitch.
* We clear state and move all vap's in CSA state to RUN state
* so they can again transmit.
+ *
+ * Although this may not be completely correct, update the BSS channel
+ * for each VAP to the newly configured channel. The setcurchan sets
+ * the current operating channel for the interface (so the radio does
+ * switch over) but the VAP BSS isn't updated, leading to incorrectly
+ * reported information via ioctl.
*/
void
ieee80211_csa_completeswitch(struct ieee80211com *ic)
{
+ struct ieee80211vap *vap;
+
IEEE80211_LOCK_ASSERT(ic);
KASSERT(ic->ic_flags & IEEE80211_F_CSAPENDING, ("csa not pending"));
ieee80211_setcurchan(ic, ic->ic_csa_newchan);
+ TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
+ if (vap->iv_state == IEEE80211_S_CSA)
+ vap->iv_bss->ni_chan = ic->ic_curchan;
+
csa_completeswitch(ic);
}
diff --git a/sys/net80211/ieee80211_scan_sta.c b/sys/net80211/ieee80211_scan_sta.c
index 987a26f19b2bd..6f5e9d256fc9a 100644
--- a/sys/net80211/ieee80211_scan_sta.c
+++ b/sys/net80211/ieee80211_scan_sta.c
@@ -238,6 +238,7 @@ sta_add(struct ieee80211_scan_state *ss,
const uint8_t *macaddr = wh->i_addr2;
struct ieee80211vap *vap = ss->ss_vap;
struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_channel *c;
struct sta_entry *se;
struct ieee80211_scan_entry *ise;
int hash;
@@ -300,7 +301,6 @@ found:
* association on the wrong channel.
*/
if (sp->status & IEEE80211_BPARSE_OFFCHAN) {
- struct ieee80211_channel *c;
/*
* Off-channel, locate the home/bss channel for the sta
* using the value broadcast in the DSPARMS ie. We know
@@ -317,6 +317,14 @@ found:
}
} else
ise->se_chan = ic->ic_curchan;
+ if (IEEE80211_IS_CHAN_HT(ise->se_chan) && sp->htcap == NULL) {
+ /* Demote legacy networks to a non-HT channel. */
+ c = ieee80211_find_channel(ic, ise->se_chan->ic_freq,
+ ise->se_chan->ic_flags & ~IEEE80211_CHAN_HT);
+ KASSERT(c != NULL,
+ ("no legacy channel %u", ise->se_chan->ic_ieee));
+ ise->se_chan = c;
+ }
ise->se_fhdwell = sp->fhdwell;
ise->se_fhindex = sp->fhindex;
ise->se_erp = sp->erp;
diff --git a/sys/netgraph/ng_ether.c b/sys/netgraph/ng_ether.c
index afedaa37a8f78..15e8b2d3625c6 100644
--- a/sys/netgraph/ng_ether.c
+++ b/sys/netgraph/ng_ether.c
@@ -604,9 +604,6 @@ ng_ether_rcvdata(hook_p hook, item_p item)
NG_FREE_ITEM(item);
panic("%s: weird hook", __func__);
-#ifdef RESTARTABLE_PANICS /* so we don't get an error msg in LINT */
- return (0);
-#endif
}
/*
diff --git a/sys/netgraph/ng_ipfw.c b/sys/netgraph/ng_ipfw.c
index 68bd89c09e8bc..4f1bc0ee94d26 100644
--- a/sys/netgraph/ng_ipfw.c
+++ b/sys/netgraph/ng_ipfw.c
@@ -26,6 +26,9 @@
* $FreeBSD$
*/
+#include "opt_inet.h"
+#include "opt_inet6.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -47,6 +50,8 @@
#include <netinet/ip_fw.h>
#include <netinet/ipfw/ip_fw_private.h>
#include <netinet/ip.h>
+#include <netinet/ip6.h>
+#include <netinet6/ip6_var.h>
#include <netgraph/ng_message.h>
#include <netgraph/ng_parse.h>
@@ -224,6 +229,7 @@ ng_ipfw_rcvdata(hook_p hook, item_p item)
struct m_tag *tag;
struct ipfw_rule_ref *r;
struct mbuf *m;
+ struct ip *ip;
NGI_GET_M(item, m);
NG_FREE_ITEM(item);
@@ -234,23 +240,47 @@ ng_ipfw_rcvdata(hook_p hook, item_p item)
return (EINVAL); /* XXX: find smth better */
};
+ if (m->m_len < sizeof(struct ip) &&
+ (m = m_pullup(m, sizeof(struct ip))) == NULL)
+ return (EINVAL);
+
+ ip = mtod(m, struct ip *);
+
r = (struct ipfw_rule_ref *)(tag + 1);
if (r->info & IPFW_INFO_IN) {
- ip_input(m);
+ switch (ip->ip_v) {
+#ifdef INET
+ case IPVERSION:
+ ip_input(m);
+ break;
+#endif
+#ifdef INET6
+ case IPV6_VERSION >> 4:
+ ip6_input(m);
+ break;
+#endif
+ default:
+ NG_FREE_M(m);
+ return (EINVAL);
+ }
return (0);
} else {
- struct ip *ip;
-
- if (m->m_len < sizeof(struct ip) &&
- (m = m_pullup(m, sizeof(struct ip))) == NULL)
+ switch (ip->ip_v) {
+#ifdef INET
+ case IPVERSION:
+ SET_HOST_IPLEN(ip);
+ return (ip_output(m, NULL, NULL, IP_FORWARDING,
+ NULL, NULL));
+#endif
+#ifdef INET6
+ case IPV6_VERSION >> 4:
+ return (ip6_output(m, NULL, NULL, 0, NULL,
+ NULL, NULL));
+#endif
+ default:
return (EINVAL);
-
- ip = mtod(m, struct ip *);
-
- SET_HOST_IPLEN(ip);
-
- return ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL);
- }
+ }
+ }
}
static int
diff --git a/sys/netgraph/ng_mppc.c b/sys/netgraph/ng_mppc.c
index 75194e8df187d..cb6531619d314 100644
--- a/sys/netgraph/ng_mppc.c
+++ b/sys/netgraph/ng_mppc.c
@@ -404,9 +404,6 @@ ng_mppc_rcvdata(hook_p hook, item_p item)
/* Oops */
panic("%s: unknown hook", __func__);
-#ifdef RESTARTABLE_PANICS
- return (EINVAL);
-#endif
}
/*
diff --git a/sys/netgraph/ng_parse.c b/sys/netgraph/ng_parse.c
index 1215df124b5e9..fbbefc62d9898 100644
--- a/sys/netgraph/ng_parse.c
+++ b/sys/netgraph/ng_parse.c
@@ -374,9 +374,6 @@ ng_int8_unparse(const struct ng_parse_type *type,
break;
default:
panic("%s: unknown type", __func__);
-#ifdef RESTARTABLE_PANICS
- return(0);
-#endif
}
if ((error = ng_parse_append(&cbuf, &cbuflen, fmt, fval)) != 0)
return (error);
@@ -473,9 +470,6 @@ ng_int16_unparse(const struct ng_parse_type *type,
break;
default:
panic("%s: unknown type", __func__);
-#ifdef RESTARTABLE_PANICS
- return(0);
-#endif
}
if ((error = ng_parse_append(&cbuf, &cbuflen, fmt, fval)) != 0)
return (error);
@@ -575,9 +569,6 @@ ng_int32_unparse(const struct ng_parse_type *type,
break;
default:
panic("%s: unknown type", __func__);
-#ifdef RESTARTABLE_PANICS
- return(0);
-#endif
}
if ((error = ng_parse_append(&cbuf, &cbuflen, fmt, fval)) != 0)
return (error);
@@ -673,9 +664,6 @@ ng_int64_unparse(const struct ng_parse_type *type,
break;
default:
panic("%s: unknown type", __func__);
-#ifdef RESTARTABLE_PANICS
- return(0);
-#endif
}
if ((error = ng_parse_append(&cbuf, &cbuflen, fmt, fval)) != 0)
return (error);
diff --git a/sys/netgraph/ng_socket.c b/sys/netgraph/ng_socket.c
index f72f8226c76e9..8c819c01429dc 100644
--- a/sys/netgraph/ng_socket.c
+++ b/sys/netgraph/ng_socket.c
@@ -694,7 +694,7 @@ ng_internalize(struct mbuf *control, struct thread *td)
/* Check that the FD given is legit. and change it to a pointer to a
* struct file. */
fd = CMSG_DATA(cm);
- if ((error = fget(td, fd, &fp)) != 0)
+ if ((error = fget(td, fd, 0, &fp)) != 0)
return (error);
/* Depending on what kind of resource it is, act differently. For
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index c0901178d990f..4547e395eba9d 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -1037,7 +1037,7 @@ in_addprefix(struct in_ifaddr *target, int flags)
IN_IFADDR_RLOCK();
TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) {
if (rtinitflags(ia)) {
- p = ia->ia_addr.sin_addr;
+ p = ia->ia_dstaddr.sin_addr;
if (prefix.s_addr != p.s_addr)
continue;
@@ -1163,7 +1163,8 @@ in_scrubprefix(struct in_ifaddr *target, u_int flags)
p.s_addr &= ia->ia_sockmask.sin_addr.s_addr;
}
- if (prefix.s_addr != p.s_addr)
+ if ((prefix.s_addr != p.s_addr) ||
+ !(ia->ia_ifp->if_flags & IFF_UP))
continue;
/*
diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c
index 29a5d424fddaa..234cae2757949 100644
--- a/sys/netinet/ip_divert.c
+++ b/sys/netinet/ip_divert.c
@@ -410,6 +410,7 @@ div_output(struct socket *so, struct mbuf *m, struct sockaddr_in *sin,
}
ip6->ip6_plen = ntohs(ip6->ip6_plen);
+ break;
}
#endif
default:
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h
index ff3a67fe61ce5..f6f8fcd876f7d 100644
--- a/sys/netinet/ip_fw.h
+++ b/sys/netinet/ip_fw.h
@@ -203,6 +203,8 @@ enum ipfw_opcodes { /* arguments (4 byte each) */
O_CALLRETURN, /* arg1=called rule number */
+ O_FORWARD_IP6, /* fwd sockaddr_in6 */
+
O_LAST_OPCODE /* not an opcode! */
};
@@ -299,6 +301,14 @@ typedef struct _ipfw_insn_sa {
} ipfw_insn_sa;
/*
+ * This is used to forward to a given address (ipv6).
+ */
+typedef struct _ipfw_insn_sa6 {
+ ipfw_insn o;
+ struct sockaddr_in6 sa;
+} ipfw_insn_sa6;
+
+/*
* This is used for MAC addr-mask pairs.
*/
typedef struct _ipfw_insn_mac {
diff --git a/sys/netinet/ipfw/ip_fw2.c b/sys/netinet/ipfw/ip_fw2.c
index 4e25f9a086d8a..619ce6b91e5bf 100644
--- a/sys/netinet/ipfw/ip_fw2.c
+++ b/sys/netinet/ipfw/ip_fw2.c
@@ -30,8 +30,8 @@ __FBSDID("$FreeBSD$");
* The FreeBSD IP packet firewall, main file
*/
-#if !defined(KLD_MODULE)
#include "opt_ipfw.h"
+#if !defined(KLD_MODULE)
#include "opt_ipdivert.h"
#include "opt_ipdn.h"
#include "opt_inet.h"
@@ -107,6 +107,9 @@ static VNET_DEFINE(int, ipfw_vnet_ready) = 0;
static VNET_DEFINE(int, fw_deny_unknown_exthdrs);
#define V_fw_deny_unknown_exthdrs VNET(fw_deny_unknown_exthdrs)
+static VNET_DEFINE(int, fw_permit_single_frag6) = 1;
+#define V_fw_permit_single_frag6 VNET(fw_permit_single_frag6)
+
#ifdef IPFIREWALL_DEFAULT_TO_ACCEPT
static int default_to_accept = 1;
#else
@@ -182,6 +185,9 @@ SYSCTL_NODE(_net_inet6_ip6, OID_AUTO, fw, CTLFLAG_RW, 0, "Firewall");
SYSCTL_VNET_INT(_net_inet6_ip6_fw, OID_AUTO, deny_unknown_exthdrs,
CTLFLAG_RW | CTLFLAG_SECURE, &VNET_NAME(fw_deny_unknown_exthdrs), 0,
"Deny packets with unknown IPv6 Extension Headers");
+SYSCTL_VNET_INT(_net_inet6_ip6_fw, OID_AUTO, permit_single_frag6,
+ CTLFLAG_RW | CTLFLAG_SECURE, &VNET_NAME(fw_permit_single_frag6), 0,
+ "Permit single packet IPv6 fragments");
#endif /* INET6 */
SYSEND
@@ -790,6 +796,7 @@ set_match(struct ip_fw_args *args, int slot,
*
* args->rule Pointer to the last matching rule (in/out)
* args->next_hop Socket we are forwarding to (out).
+ * args->next_hop6 IPv6 next hop we are forwarding to (out).
* args->f_id Addresses grabbed from the packet (out)
* args->rule.info a cookie depending on rule action
*
@@ -871,13 +878,14 @@ ipfw_chk(struct ip_fw_args *args)
* we have a fragment at this offset of an IPv4 packet.
* offset == 0 means that (if this is an IPv4 packet)
* this is the first or only fragment.
- * For IPv6 offset == 0 means there is no Fragment Header.
- * If offset != 0 for IPv6 always use correct mask to
- * get the correct offset because we add IP6F_MORE_FRAG
- * to be able to dectect the first fragment which would
- * otherwise have offset = 0.
+ * For IPv6 offset|ip6f_mf == 0 means there is no Fragment Header
+ * or there is a single packet fragement (fragement header added
+ * without needed). We will treat a single packet fragment as if
+ * there was no fragment header (or log/block depending on the
+ * V_fw_permit_single_frag6 sysctl setting).
*/
u_short offset = 0;
+ u_short ip6f_mf = 0;
/*
* Local copies of addresses. They are only valid if we have
@@ -971,7 +979,7 @@ do { \
proto = ip6->ip6_nxt;
/* Search extension headers to find upper layer protocols */
- while (ulp == NULL) {
+ while (ulp == NULL && offset == 0) {
switch (proto) {
case IPPROTO_ICMPV6:
PULLUP_TO(hlen, ulp, struct icmp6_hdr);
@@ -1016,9 +1024,11 @@ do { \
ext_hd |= EXT_RTHDR2;
break;
default:
- printf("IPFW2: IPV6 - Unknown Routing "
- "Header type(%d)\n",
- ((struct ip6_rthdr *)ulp)->ip6r_type);
+ if (V_fw_verbose)
+ printf("IPFW2: IPV6 - Unknown "
+ "Routing Header type(%d)\n",
+ ((struct ip6_rthdr *)
+ ulp)->ip6r_type);
if (V_fw_deny_unknown_exthdrs)
return (IP_FW_DENY);
break;
@@ -1036,13 +1046,13 @@ do { \
proto = ((struct ip6_frag *)ulp)->ip6f_nxt;
offset = ((struct ip6_frag *)ulp)->ip6f_offlg &
IP6F_OFF_MASK;
- /* Add IP6F_MORE_FRAG for offset of first
- * fragment to be != 0. */
- offset |= ((struct ip6_frag *)ulp)->ip6f_offlg &
+ ip6f_mf = ((struct ip6_frag *)ulp)->ip6f_offlg &
IP6F_MORE_FRAG;
- if (offset == 0) {
- printf("IPFW2: IPV6 - Invalid Fragment "
- "Header\n");
+ if (V_fw_permit_single_frag6 == 0 &&
+ offset == 0 && ip6f_mf == 0) {
+ if (V_fw_verbose)
+ printf("IPFW2: IPV6 - Invalid "
+ "Fragment Header\n");
if (V_fw_deny_unknown_exthdrs)
return (IP_FW_DENY);
break;
@@ -1113,8 +1123,10 @@ do { \
break;
default:
- printf("IPFW2: IPV6 - Unknown Extension "
- "Header(%d), ext_hd=%x\n", proto, ext_hd);
+ if (V_fw_verbose)
+ printf("IPFW2: IPV6 - Unknown "
+ "Extension Header(%d), ext_hd=%x\n",
+ proto, ext_hd);
if (V_fw_deny_unknown_exthdrs)
return (IP_FW_DENY);
PULLUP_TO(hlen, ulp, struct ip6_ext);
@@ -1676,7 +1688,7 @@ do { \
case O_LOG:
ipfw_log(f, hlen, args, m,
- oif, offset, tablearg, ip);
+ oif, offset | ip6f_mf, tablearg, ip);
match = 1;
break;
@@ -2270,6 +2282,23 @@ do { \
done = 1; /* exit outer loop */
break;
+#ifdef INET6
+ case O_FORWARD_IP6:
+ if (args->eh) /* not valid on layer2 pkts */
+ break;
+ if (q == NULL || q->rule != f ||
+ dyn_dir == MATCH_FORWARD) {
+ struct sockaddr_in6 *sin6;
+
+ sin6 = &(((ipfw_insn_sa6 *)cmd)->sa);
+ args->next_hop6 = sin6;
+ }
+ retval = IP_FW_PASS;
+ l = 0; /* exit inner loop */
+ done = 1; /* exit outer loop */
+ break;
+#endif
+
case O_NETGRAPH:
case O_NGTEE:
set_match(args, f_pos, chain);
diff --git a/sys/netinet/ipfw/ip_fw_dynamic.c b/sys/netinet/ipfw/ip_fw_dynamic.c
index 0bc4cc112ce26..d1eec89eed4f3 100644
--- a/sys/netinet/ipfw/ip_fw_dynamic.c
+++ b/sys/netinet/ipfw/ip_fw_dynamic.c
@@ -33,8 +33,8 @@ __FBSDID("$FreeBSD$");
* Dynamic rule support for ipfw
*/
-#if !defined(KLD_MODULE)
#include "opt_ipfw.h"
+#if !defined(KLD_MODULE)
#include "opt_ipdivert.h"
#include "opt_ipdn.h"
#include "opt_inet.h"
diff --git a/sys/netinet/ipfw/ip_fw_log.c b/sys/netinet/ipfw/ip_fw_log.c
index 2b55a382d70d1..2f6e8b61fee88 100644
--- a/sys/netinet/ipfw/ip_fw_log.c
+++ b/sys/netinet/ipfw/ip_fw_log.c
@@ -30,8 +30,8 @@ __FBSDID("$FreeBSD$");
* Logging support for ipfw
*/
-#if !defined(KLD_MODULE)
#include "opt_ipfw.h"
+#if !defined(KLD_MODULE)
#include "opt_ipdivert.h"
#include "opt_ipdn.h"
#include "opt_inet.h"
@@ -167,7 +167,7 @@ ipfw_log(struct ip_fw *f, u_int hlen, struct ip_fw_args *args,
{
char *action;
int limit_reached = 0;
- char action2[40], proto[128], fragment[32];
+ char action2[92], proto[128], fragment[32];
if (V_fw_verbose == 0) {
#ifndef WITHOUT_BPF
@@ -290,6 +290,21 @@ ipfw_log(struct ip_fw *f, u_int hlen, struct ip_fw_args *args,
sa->sa.sin_port);
}
break;
+#ifdef INET6
+ case O_FORWARD_IP6: {
+ char buf[INET6_ADDRSTRLEN];
+ ipfw_insn_sa6 *sa = (ipfw_insn_sa6 *)cmd;
+ int len;
+
+ len = snprintf(SNPARGS(action2, 0), "Forward to [%s]",
+ ip6_sprintf(buf, &sa->sa.sin6_addr));
+
+ if (sa->sa.sin6_port)
+ snprintf(SNPARGS(action2, len), ":%u",
+ sa->sa.sin6_port);
+ }
+ break;
+#endif
case O_NETGRAPH:
snprintf(SNPARGS(action2, 0), "Netgraph %d",
cmd->arg1);
@@ -333,10 +348,14 @@ ipfw_log(struct ip_fw *f, u_int hlen, struct ip_fw_args *args,
#ifdef INET6
struct ip6_hdr *ip6 = NULL;
struct icmp6_hdr *icmp6;
+ u_short ip6f_mf;
#endif
src[0] = '\0';
dst[0] = '\0';
#ifdef INET6
+ ip6f_mf = offset & IP6F_MORE_FRAG;
+ offset &= IP6F_OFF_MASK;
+
if (IS_IP6_FLOW_ID(&(args->f_id))) {
char ip6buf[INET6_ADDRSTRLEN];
snprintf(src, sizeof(src), "[%s]",
@@ -418,8 +437,7 @@ ipfw_log(struct ip_fw *f, u_int hlen, struct ip_fw_args *args,
" (frag %08x:%d@%d%s)",
args->f_id.extra,
ntohs(ip6->ip6_plen) - hlen,
- ntohs(offset & IP6F_OFF_MASK) << 3,
- (offset & IP6F_MORE_FRAG) ? "+" : "");
+ ntohs(offset) << 3, ip6f_mf ? "+" : "");
} else
#endif
{
diff --git a/sys/netinet/ipfw/ip_fw_pfil.c b/sys/netinet/ipfw/ip_fw_pfil.c
index 736615b947a21..c470b1f2092d6 100644
--- a/sys/netinet/ipfw/ip_fw_pfil.c
+++ b/sys/netinet/ipfw/ip_fw_pfil.c
@@ -27,8 +27,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#if !defined(KLD_MODULE)
#include "opt_ipfw.h"
+#if !defined(KLD_MODULE)
#include "opt_ipdn.h"
#include "opt_inet.h"
#ifndef INET
@@ -152,13 +152,26 @@ again:
switch (ipfw) {
case IP_FW_PASS:
/* next_hop may be set by ipfw_chk */
- if (args.next_hop == NULL)
+ if (args.next_hop == NULL && args.next_hop6 == NULL)
break; /* pass */
#ifndef IPFIREWALL_FORWARD
ret = EACCES;
#else
{
struct m_tag *fwd_tag;
+ size_t len;
+
+ KASSERT(args.next_hop == NULL || args.next_hop6 == NULL,
+ ("%s: both next_hop=%p and next_hop6=%p not NULL", __func__,
+ args.next_hop, args.next_hop6));
+#ifdef INET6
+ if (args.next_hop6 != NULL)
+ len = sizeof(struct sockaddr_in6);
+#endif
+#ifdef INET
+ if (args.next_hop != NULL)
+ len = sizeof(struct sockaddr_in);
+#endif
/* Incoming packets should not be tagged so we do not
* m_tag_find. Outgoing packets may be tagged, so we
@@ -169,18 +182,28 @@ again:
if (fwd_tag != NULL) {
m_tag_unlink(*m0, fwd_tag);
} else {
- fwd_tag = m_tag_get(PACKET_TAG_IPFORWARD,
- sizeof(struct sockaddr_in), M_NOWAIT);
+ fwd_tag = m_tag_get(PACKET_TAG_IPFORWARD, len,
+ M_NOWAIT);
if (fwd_tag == NULL) {
ret = EACCES;
break; /* i.e. drop */
}
}
- bcopy(args.next_hop, (fwd_tag+1), sizeof(struct sockaddr_in));
+#ifdef INET6
+ if (args.next_hop6 != NULL) {
+ bcopy(args.next_hop6, (fwd_tag+1), len);
+ if (in6_localip(&args.next_hop6->sin6_addr))
+ (*m0)->m_flags |= M_FASTFWD_OURS;
+ }
+#endif
+#ifdef INET
+ if (args.next_hop != NULL) {
+ bcopy(args.next_hop, (fwd_tag+1), len);
+ if (in_localip(args.next_hop->sin_addr))
+ (*m0)->m_flags |= M_FASTFWD_OURS;
+ }
+#endif
m_tag_prepend(*m0, fwd_tag);
-
- if (in_localip(args.next_hop->sin_addr))
- (*m0)->m_flags |= M_FASTFWD_OURS;
}
#endif
break;
diff --git a/sys/netinet/ipfw/ip_fw_private.h b/sys/netinet/ipfw/ip_fw_private.h
index 16ef46d574e13..fdb2b77f88b05 100644
--- a/sys/netinet/ipfw/ip_fw_private.h
+++ b/sys/netinet/ipfw/ip_fw_private.h
@@ -86,6 +86,7 @@ struct ip_fw_args {
struct mbuf *m; /* the mbuf chain */
struct ifnet *oif; /* output interface */
struct sockaddr_in *next_hop; /* forward address */
+ struct sockaddr_in6 *next_hop6; /* ipv6 forward address */
/*
* On return, it points to the matching rule.
diff --git a/sys/netinet/ipfw/ip_fw_sockopt.c b/sys/netinet/ipfw/ip_fw_sockopt.c
index 143285850113d..610570ba9a785 100644
--- a/sys/netinet/ipfw/ip_fw_sockopt.c
+++ b/sys/netinet/ipfw/ip_fw_sockopt.c
@@ -33,8 +33,8 @@ __FBSDID("$FreeBSD$");
* the upper half of the ipfw code.
*/
-#if !defined(KLD_MODULE)
#include "opt_ipfw.h"
+#if !defined(KLD_MODULE)
#include "opt_ipdivert.h"
#include "opt_ipdn.h"
#include "opt_inet.h"
@@ -723,6 +723,17 @@ check_ipfw_struct(struct ip_fw *rule, int size)
return EINVAL;
#endif
+#ifdef INET6
+ case O_FORWARD_IP6:
+#ifdef IPFIREWALL_FORWARD
+ if (cmdlen != F_INSN_SIZE(ipfw_insn_sa6))
+ goto bad_size;
+ goto check_action;
+#else
+ return (EINVAL);
+#endif
+#endif /* INET6 */
+
case O_DIVERT:
case O_TEE:
if (ip_divert_ptr == NULL)
diff --git a/sys/netinet/ipfw/ip_fw_table.c b/sys/netinet/ipfw/ip_fw_table.c
index 517622f021715..f72401765a193 100644
--- a/sys/netinet/ipfw/ip_fw_table.c
+++ b/sys/netinet/ipfw/ip_fw_table.c
@@ -39,8 +39,8 @@ __FBSDID("$FreeBSD$");
* from userland, because operations are typically fast.
*/
-#if !defined(KLD_MODULE)
#include "opt_ipfw.h"
+#if !defined(KLD_MODULE)
#include "opt_ipdivert.h"
#include "opt_ipdn.h"
#include "opt_inet.h"
diff --git a/sys/netinet/sctp.h b/sys/netinet/sctp.h
index 3c8cf364ca6cb..11aa02a0a5684 100644
--- a/sys/netinet/sctp.h
+++ b/sys/netinet/sctp.h
@@ -119,6 +119,7 @@ struct sctp_paramhdr {
#define SCTP_RECVNXTINFO 0x00000020
#define SCTP_DEFAULT_SNDINFO 0x00000021
#define SCTP_DEFAULT_PRINFO 0x00000022
+#define SCTP_PEER_ADDR_THLDS 0x00000023
/*
* read-only options
@@ -564,7 +565,6 @@ struct sctp_error_unrecognized_chunk {
#define SCTP_BLK_LOGGING_ENABLE 0x00000001
#define SCTP_CWND_MONITOR_ENABLE 0x00000002
#define SCTP_CWND_LOGGING_ENABLE 0x00000004
-#define SCTP_EARLYFR_LOGGING_ENABLE 0x00000010
#define SCTP_FLIGHT_LOGGING_ENABLE 0x00000020
#define SCTP_FR_LOGGING_ENABLE 0x00000040
#define SCTP_LOCK_LOGGING_ENABLE 0x00000080
@@ -572,23 +572,23 @@ struct sctp_error_unrecognized_chunk {
#define SCTP_MBCNT_LOGGING_ENABLE 0x00000200
#define SCTP_MBUF_LOGGING_ENABLE 0x00000400
#define SCTP_NAGLE_LOGGING_ENABLE 0x00000800
-#define SCTP_RECV_RWND_LOGGING_ENABLE 0x00001000
+#define SCTP_RECV_RWND_LOGGING_ENABLE 0x00001000
#define SCTP_RTTVAR_LOGGING_ENABLE 0x00002000
#define SCTP_SACK_LOGGING_ENABLE 0x00004000
-#define SCTP_SACK_RWND_LOGGING_ENABLE 0x00008000
+#define SCTP_SACK_RWND_LOGGING_ENABLE 0x00008000
#define SCTP_SB_LOGGING_ENABLE 0x00010000
#define SCTP_STR_LOGGING_ENABLE 0x00020000
#define SCTP_WAKE_LOGGING_ENABLE 0x00040000
#define SCTP_LOG_MAXBURST_ENABLE 0x00080000
#define SCTP_LOG_RWND_ENABLE 0x00100000
-#define SCTP_LOG_SACK_ARRIVALS_ENABLE 0x00200000
-#define SCTP_LTRACE_CHUNK_ENABLE 0x00400000
-#define SCTP_LTRACE_ERROR_ENABLE 0x00800000
-#define SCTP_LAST_PACKET_TRACING 0x01000000
-#define SCTP_THRESHOLD_LOGGING 0x02000000
-#define SCTP_LOG_AT_SEND_2_SCTP 0x04000000
-#define SCTP_LOG_AT_SEND_2_OUTQ 0x08000000
-#define SCTP_LOG_TRY_ADVANCE 0x10000000
+#define SCTP_LOG_SACK_ARRIVALS_ENABLE 0x00200000
+#define SCTP_LTRACE_CHUNK_ENABLE 0x00400000
+#define SCTP_LTRACE_ERROR_ENABLE 0x00800000
+#define SCTP_LAST_PACKET_TRACING 0x01000000
+#define SCTP_THRESHOLD_LOGGING 0x02000000
+#define SCTP_LOG_AT_SEND_2_SCTP 0x04000000
+#define SCTP_LOG_AT_SEND_2_OUTQ 0x08000000
+#define SCTP_LOG_TRY_ADVANCE 0x10000000
#undef SCTP_PACKED
diff --git a/sys/netinet/sctp_asconf.c b/sys/netinet/sctp_asconf.c
index a6db580f6abe6..b4985aa66aec5 100644
--- a/sys/netinet/sctp_asconf.c
+++ b/sys/netinet/sctp_asconf.c
@@ -198,14 +198,16 @@ sctp_asconf_error_response(uint32_t id, uint16_t cause, uint8_t * error_tlv,
static struct mbuf *
sctp_process_asconf_add_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
- struct sctp_tcb *stcb, int response_required)
+ struct sctp_tcb *stcb, int send_hb, int response_required)
{
+ struct sctp_nets *net;
struct mbuf *m_reply = NULL;
struct sockaddr_storage sa_source, sa_store;
struct sctp_paramhdr *ph;
uint16_t param_type, param_length, aparam_length;
struct sockaddr *sa;
int zero_address = 0;
+ int bad_address = 0;
#ifdef INET
struct sockaddr_in *sin;
@@ -238,6 +240,10 @@ sctp_process_asconf_add_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
sin->sin_len = sizeof(struct sockaddr_in);
sin->sin_port = stcb->rport;
sin->sin_addr.s_addr = v4addr->addr;
+ if ((sin->sin_addr.s_addr == INADDR_BROADCAST) ||
+ IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
+ bad_address = 1;
+ }
if (sin->sin_addr.s_addr == INADDR_ANY)
zero_address = 1;
SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_add_ip: adding ");
@@ -258,6 +264,9 @@ sctp_process_asconf_add_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
sin6->sin6_port = stcb->rport;
memcpy((caddr_t)&sin6->sin6_addr, v6addr->addr,
sizeof(struct in6_addr));
+ if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
+ bad_address = 1;
+ }
if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
zero_address = 1;
SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_add_ip: adding ");
@@ -265,12 +274,8 @@ sctp_process_asconf_add_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
break;
#endif
default:
- /*
- * XXX: Is this the correct error cause? Maybe
- * SCTP_CAUSE_INVALID_PARAM is a better choice.
- */
m_reply = sctp_asconf_error_response(aph->correlation_id,
- SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph,
+ SCTP_CAUSE_INVALID_PARAM, (uint8_t *) aph,
aparam_length);
return m_reply;
} /* end switch */
@@ -284,7 +289,11 @@ sctp_process_asconf_add_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
}
/* add the address */
- if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE,
+ if (bad_address) {
+ m_reply = sctp_asconf_error_response(aph->correlation_id,
+ SCTP_CAUSE_INVALID_PARAM, (uint8_t *) aph,
+ aparam_length);
+ } else if (sctp_add_remote_addr(stcb, sa, &net, SCTP_DONOT_SETSCOPE,
SCTP_ADDR_DYNAMIC_ADDED) != 0) {
SCTPDBG(SCTP_DEBUG_ASCONF1,
"process_asconf_add_ip: error adding address\n");
@@ -298,10 +307,12 @@ sctp_process_asconf_add_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
m_reply =
sctp_asconf_success_response(aph->correlation_id);
}
- sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb,
- NULL, SCTP_FROM_SCTP_ASCONF + SCTP_LOC_1);
+ sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, stcb->sctp_ep, stcb, net);
sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep,
- stcb, NULL);
+ stcb, net);
+ if (send_hb) {
+ sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED);
+ }
}
return m_reply;
}
@@ -554,7 +565,12 @@ sctp_process_asconf_set_primary(struct mbuf *m,
"process_asconf_set_primary: primary address set\n");
/* notify upper layer */
sctp_ulp_notify(SCTP_NOTIFY_ASCONF_SET_PRIMARY, stcb, 0, sa, SCTP_SO_NOT_LOCKED);
-
+ if ((stcb->asoc.primary_destination->dest_state & SCTP_ADDR_REACHABLE) &&
+ (!(stcb->asoc.primary_destination->dest_state & SCTP_ADDR_PF)) &&
+ (stcb->asoc.alternate)) {
+ sctp_free_remote_addr(stcb->asoc.alternate);
+ stcb->asoc.alternate = NULL;
+ }
if (response_required) {
m_reply = sctp_asconf_success_response(aph->correlation_id);
}
@@ -622,7 +638,7 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset,
struct sctp_asconf_ack_chunk *ack_cp;
struct sctp_asconf_paramhdr *aph, *ack_aph;
struct sctp_ipv6addr_param *p_addr;
- unsigned int asconf_limit;
+ unsigned int asconf_limit, cnt;
int error = 0; /* did an error occur? */
/* asconf param buffer */
@@ -717,6 +733,7 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset,
goto send_reply;
}
/* process through all parameters */
+ cnt = 0;
while (aph != NULL) {
unsigned int param_length, param_type;
@@ -749,7 +766,8 @@ sctp_handle_asconf(struct mbuf *m, unsigned int offset,
case SCTP_ADD_IP_ADDRESS:
asoc->peer_supports_asconf = 1;
m_result = sctp_process_asconf_add_ip(m, aph, stcb,
- error);
+ (cnt < SCTP_BASE_SYSCTL(sctp_hb_maxburst)), error);
+ cnt++;
break;
case SCTP_DEL_IP_ADDRESS:
asoc->peer_supports_asconf = 1;
@@ -1959,7 +1977,7 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
int status;
- if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0 &&
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0 ||
sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_ASCONF)) {
/* subset bound, no ASCONF allowed case, so ignore */
return;
@@ -2075,8 +2093,7 @@ sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, inp,
stcb, stcb->asoc.primary_destination);
#else
- sctp_send_asconf(stcb, stcb->asoc.primary_destination,
- addr_locked);
+ sctp_send_asconf(stcb, NULL, addr_locked);
#endif
}
}
@@ -2328,8 +2345,7 @@ sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
* If we have queued params in the open state, send out an ASCONF.
*/
if (num_queued > 0) {
- sctp_send_asconf(stcb, stcb->asoc.primary_destination,
- SCTP_ADDR_NOT_LOCKED);
+ sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
}
}
@@ -2384,8 +2400,7 @@ sctp_set_primary_ip_address_sa(struct sctp_tcb *stcb, struct sockaddr *sa)
stcb->sctp_ep, stcb,
stcb->asoc.primary_destination);
#else
- sctp_send_asconf(stcb, stcb->asoc.primary_destination,
- SCTP_ADDR_NOT_LOCKED);
+ sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
#endif
}
} else {
@@ -2421,8 +2436,7 @@ sctp_set_primary_ip_address(struct sctp_ifa *ifa)
stcb->sctp_ep, stcb,
stcb->asoc.primary_destination);
#else
- sctp_send_asconf(stcb, stcb->asoc.primary_destination,
- SCTP_ADDR_NOT_LOCKED);
+ sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
#endif
}
}
@@ -2965,8 +2979,7 @@ sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m,
stcb->sctp_ep, stcb,
stcb->asoc.primary_destination);
#else
- sctp_send_asconf(stcb, stcb->asoc.primary_destination,
- SCTP_ADDR_NOT_LOCKED);
+ sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
#endif
}
}
@@ -3540,5 +3553,5 @@ sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb,
}
skip_rest:
/* Now we must send the asconf into the queue */
- sctp_send_asconf(stcb, net, 0);
+ sctp_send_asconf(stcb, net, SCTP_ADDR_NOT_LOCKED);
}
diff --git a/sys/netinet/sctp_cc_functions.c b/sys/netinet/sctp_cc_functions.c
index 85beb6adaaed4..b1596cccdbb06 100644
--- a/sys/netinet/sctp_cc_functions.c
+++ b/sys/netinet/sctp_cc_functions.c
@@ -728,40 +728,6 @@ sctp_cwnd_update_after_sack_common(struct sctp_tcb *stcb,
}
}
#endif
- if (SCTP_BASE_SYSCTL(sctp_early_fr)) {
- /*
- * So, first of all do we need to have a Early FR
- * timer running?
- */
- if ((!TAILQ_EMPTY(&asoc->sent_queue) &&
- (net->ref_count > 1) &&
- (net->flight_size < net->cwnd)) ||
- (reneged_all)) {
- /*
- * yes, so in this case stop it if its
- * running, and then restart it. Reneging
- * all is a special case where we want to
- * run the Early FR timer and then force the
- * last few unacked to be sent, causing us
- * to illicit a sack with gaps to force out
- * the others.
- */
- if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
- SCTP_STAT_INCR(sctps_earlyfrstpidsck2);
- sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
- SCTP_FROM_SCTP_INDATA + SCTP_LOC_20);
- }
- SCTP_STAT_INCR(sctps_earlyfrstrid);
- sctp_timer_start(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net);
- } else {
- /* No, stop it if its running */
- if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
- SCTP_STAT_INCR(sctps_earlyfrstpidsck3);
- sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
- SCTP_FROM_SCTP_INDATA + SCTP_LOC_21);
- }
- }
- }
/* if nothing was acked on this destination skip it */
if (net->net_ack == 0) {
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
@@ -769,51 +735,6 @@ sctp_cwnd_update_after_sack_common(struct sctp_tcb *stcb,
}
continue;
}
- if (net->net_ack2 > 0) {
- /*
- * Karn's rule applies to clearing error count, this
- * is optional.
- */
- net->error_count = 0;
- if ((net->dest_state & SCTP_ADDR_NOT_REACHABLE) ==
- SCTP_ADDR_NOT_REACHABLE) {
- /* addr came good */
- net->dest_state &= ~SCTP_ADDR_NOT_REACHABLE;
- net->dest_state |= SCTP_ADDR_REACHABLE;
- sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb,
- SCTP_RECEIVED_SACK, (void *)net, SCTP_SO_NOT_LOCKED);
- /* now was it the primary? if so restore */
- if (net->dest_state & SCTP_ADDR_WAS_PRIMARY) {
- (void)sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net);
- }
- }
- /*
- * JRS 5/14/07 - If CMT PF is on and the destination
- * is in PF state, set the destination to active
- * state and set the cwnd to one or two MTU's based
- * on whether PF1 or PF2 is being used.
- *
- * Should we stop any running T3 timer here?
- */
- if ((asoc->sctp_cmt_on_off > 0) &&
- (asoc->sctp_cmt_pf > 0) &&
- ((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF)) {
- net->dest_state &= ~SCTP_ADDR_PF;
- old_cwnd = net->cwnd;
- net->cwnd = net->mtu * asoc->sctp_cmt_pf;
- SDT_PROBE(sctp, cwnd, net, ack,
- stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net,
- old_cwnd, net->cwnd);
- SCTPDBG(SCTP_DEBUG_INDATA1, "Destination %p moved from PF to reachable with cwnd %d.\n",
- net, net->cwnd);
- /*
- * Since the cwnd value is explicitly set,
- * skip the code that updates the cwnd
- * value.
- */
- goto skip_cwnd_update;
- }
- }
#ifdef JANA_CMT_FAST_RECOVERY
/*
* CMT fast recovery code
@@ -833,7 +754,7 @@ sctp_cwnd_update_after_sack_common(struct sctp_tcb *stcb,
* If we are in loss recovery we skip any cwnd
* update
*/
- goto skip_cwnd_update;
+ return;
}
/*
* Did any measurements go on for this network?
@@ -856,7 +777,7 @@ sctp_cwnd_update_after_sack_common(struct sctp_tcb *stcb,
if (net->cc_mod.rtcc.lbw) {
if (cc_bw_limit(stcb, net, nbw)) {
/* Hold here, no update */
- goto skip_cwnd_update;
+ continue;
}
} else {
uint64_t vtag, probepoint;
@@ -1049,27 +970,25 @@ sctp_cwnd_update_after_sack_common(struct sctp_tcb *stcb,
SCTP_CWND_LOG_NO_CUMACK);
}
}
-skip_cwnd_update:
- /*
- * NOW, according to Karn's rule do we need to restore the
- * RTO timer back? Check our net_ack2. If not set then we
- * have a ambiguity.. i.e. all data ack'd was sent to more
- * than one place.
- */
- if (net->net_ack2) {
- /* restore any doubled timers */
- net->RTO = (net->lastsa >> SCTP_RTT_SHIFT) + net->lastsv;
- if (net->RTO < stcb->asoc.minrto) {
- net->RTO = stcb->asoc.minrto;
- }
- if (net->RTO > stcb->asoc.maxrto) {
- net->RTO = stcb->asoc.maxrto;
- }
- }
}
}
static void
+sctp_cwnd_update_exit_pf_common(struct sctp_tcb *stcb, struct sctp_nets *net)
+{
+ int old_cwnd;
+
+ old_cwnd = net->cwnd;
+ net->cwnd = net->mtu;
+ SDT_PROBE(sctp, cwnd, net, ack,
+ stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net,
+ old_cwnd, net->cwnd);
+ SCTPDBG(SCTP_DEBUG_INDATA1, "Destination %p moved from PF to reachable with cwnd %d.\n",
+ net, net->cwnd);
+}
+
+
+static void
sctp_cwnd_update_after_timeout(struct sctp_tcb *stcb, struct sctp_nets *net)
{
int old_cwnd = net->cwnd;
@@ -1344,32 +1263,6 @@ sctp_cwnd_update_after_output(struct sctp_tcb *stcb,
}
static void
-sctp_cwnd_update_after_fr_timer(struct sctp_inpcb *inp,
- struct sctp_tcb *stcb, struct sctp_nets *net)
-{
- int old_cwnd = net->cwnd;
-
- sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_EARLY_FR_TMR, SCTP_SO_NOT_LOCKED);
- /*
- * make a small adjustment to cwnd and force to CA.
- */
- if (net->cwnd > net->mtu)
- /* drop down one MTU after sending */
- net->cwnd -= net->mtu;
- if (net->cwnd < net->ssthresh)
- /* still in SS move to CA */
- net->ssthresh = net->cwnd - 1;
- SDT_PROBE(sctp, cwnd, net, fr,
- stcb->asoc.my_vtag,
- ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)),
- net,
- old_cwnd, net->cwnd);
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
- sctp_log_cwnd(stcb, net, (old_cwnd - net->cwnd), SCTP_CWND_LOG_FROM_FR);
- }
-}
-
-static void
sctp_cwnd_update_after_sack(struct sctp_tcb *stcb,
struct sctp_association *asoc,
int accum_moved, int reneged_all, int will_exit)
@@ -1858,40 +1751,6 @@ sctp_hs_cwnd_update_after_sack(struct sctp_tcb *stcb,
}
}
#endif
- if (SCTP_BASE_SYSCTL(sctp_early_fr)) {
- /*
- * So, first of all do we need to have a Early FR
- * timer running?
- */
- if ((!TAILQ_EMPTY(&asoc->sent_queue) &&
- (net->ref_count > 1) &&
- (net->flight_size < net->cwnd)) ||
- (reneged_all)) {
- /*
- * yes, so in this case stop it if its
- * running, and then restart it. Reneging
- * all is a special case where we want to
- * run the Early FR timer and then force the
- * last few unacked to be sent, causing us
- * to illicit a sack with gaps to force out
- * the others.
- */
- if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
- SCTP_STAT_INCR(sctps_earlyfrstpidsck2);
- sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
- SCTP_FROM_SCTP_INDATA + SCTP_LOC_20);
- }
- SCTP_STAT_INCR(sctps_earlyfrstrid);
- sctp_timer_start(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net);
- } else {
- /* No, stop it if its running */
- if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
- SCTP_STAT_INCR(sctps_earlyfrstpidsck3);
- sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
- SCTP_FROM_SCTP_INDATA + SCTP_LOC_21);
- }
- }
- }
/* if nothing was acked on this destination skip it */
if (net->net_ack == 0) {
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
@@ -1899,47 +1758,6 @@ sctp_hs_cwnd_update_after_sack(struct sctp_tcb *stcb,
}
continue;
}
- if (net->net_ack2 > 0) {
- /*
- * Karn's rule applies to clearing error count, this
- * is optional.
- */
- net->error_count = 0;
- if ((net->dest_state & SCTP_ADDR_NOT_REACHABLE) ==
- SCTP_ADDR_NOT_REACHABLE) {
- /* addr came good */
- net->dest_state &= ~SCTP_ADDR_NOT_REACHABLE;
- net->dest_state |= SCTP_ADDR_REACHABLE;
- sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb,
- SCTP_RECEIVED_SACK, (void *)net, SCTP_SO_NOT_LOCKED);
- /* now was it the primary? if so restore */
- if (net->dest_state & SCTP_ADDR_WAS_PRIMARY) {
- (void)sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net);
- }
- }
- /*
- * JRS 5/14/07 - If CMT PF is on and the destination
- * is in PF state, set the destination to active
- * state and set the cwnd to one or two MTU's based
- * on whether PF1 or PF2 is being used.
- *
- * Should we stop any running T3 timer here?
- */
- if ((asoc->sctp_cmt_on_off > 0) &&
- (asoc->sctp_cmt_pf > 0) &&
- ((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF)) {
- net->dest_state &= ~SCTP_ADDR_PF;
- net->cwnd = net->mtu * asoc->sctp_cmt_pf;
- SCTPDBG(SCTP_DEBUG_INDATA1, "Destination %p moved from PF to reachable with cwnd %d.\n",
- net, net->cwnd);
- /*
- * Since the cwnd value is explicitly set,
- * skip the code that updates the cwnd
- * value.
- */
- goto skip_cwnd_update;
- }
- }
#ifdef JANA_CMT_FAST_RECOVERY
/*
* CMT fast recovery code
@@ -1959,7 +1777,7 @@ sctp_hs_cwnd_update_after_sack(struct sctp_tcb *stcb,
* If we are in loss recovery we skip any cwnd
* update
*/
- goto skip_cwnd_update;
+ return;
}
/*
* CMT: CUC algorithm. Update cwnd if pseudo-cumack has
@@ -2004,23 +1822,6 @@ sctp_hs_cwnd_update_after_sack(struct sctp_tcb *stcb,
SCTP_CWND_LOG_NO_CUMACK);
}
}
-skip_cwnd_update:
- /*
- * NOW, according to Karn's rule do we need to restore the
- * RTO timer back? Check our net_ack2. If not set then we
- * have a ambiguity.. i.e. all data ack'd was sent to more
- * than one place.
- */
- if (net->net_ack2) {
- /* restore any doubled timers */
- net->RTO = (net->lastsa >> SCTP_RTT_SHIFT) + net->lastsv;
- if (net->RTO < stcb->asoc.minrto) {
- net->RTO = stcb->asoc.minrto;
- }
- if (net->RTO > stcb->asoc.maxrto) {
- net->RTO = stcb->asoc.maxrto;
- }
- }
}
}
@@ -2340,40 +2141,6 @@ sctp_htcp_cwnd_update_after_sack(struct sctp_tcb *stcb,
}
}
#endif
- if (SCTP_BASE_SYSCTL(sctp_early_fr)) {
- /*
- * So, first of all do we need to have a Early FR
- * timer running?
- */
- if ((!TAILQ_EMPTY(&asoc->sent_queue) &&
- (net->ref_count > 1) &&
- (net->flight_size < net->cwnd)) ||
- (reneged_all)) {
- /*
- * yes, so in this case stop it if its
- * running, and then restart it. Reneging
- * all is a special case where we want to
- * run the Early FR timer and then force the
- * last few unacked to be sent, causing us
- * to illicit a sack with gaps to force out
- * the others.
- */
- if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
- SCTP_STAT_INCR(sctps_earlyfrstpidsck2);
- sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
- SCTP_FROM_SCTP_INDATA + SCTP_LOC_20);
- }
- SCTP_STAT_INCR(sctps_earlyfrstrid);
- sctp_timer_start(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net);
- } else {
- /* No, stop it if its running */
- if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
- SCTP_STAT_INCR(sctps_earlyfrstpidsck3);
- sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
- SCTP_FROM_SCTP_INDATA + SCTP_LOC_21);
- }
- }
- }
/* if nothing was acked on this destination skip it */
if (net->net_ack == 0) {
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
@@ -2381,47 +2148,6 @@ sctp_htcp_cwnd_update_after_sack(struct sctp_tcb *stcb,
}
continue;
}
- if (net->net_ack2 > 0) {
- /*
- * Karn's rule applies to clearing error count, this
- * is optional.
- */
- net->error_count = 0;
- if ((net->dest_state & SCTP_ADDR_NOT_REACHABLE) ==
- SCTP_ADDR_NOT_REACHABLE) {
- /* addr came good */
- net->dest_state &= ~SCTP_ADDR_NOT_REACHABLE;
- net->dest_state |= SCTP_ADDR_REACHABLE;
- sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb,
- SCTP_RECEIVED_SACK, (void *)net, SCTP_SO_NOT_LOCKED);
- /* now was it the primary? if so restore */
- if (net->dest_state & SCTP_ADDR_WAS_PRIMARY) {
- (void)sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net);
- }
- }
- /*
- * JRS 5/14/07 - If CMT PF is on and the destination
- * is in PF state, set the destination to active
- * state and set the cwnd to one or two MTU's based
- * on whether PF1 or PF2 is being used.
- *
- * Should we stop any running T3 timer here?
- */
- if ((asoc->sctp_cmt_on_off > 0) &&
- (asoc->sctp_cmt_pf > 0) &&
- ((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF)) {
- net->dest_state &= ~SCTP_ADDR_PF;
- net->cwnd = net->mtu * asoc->sctp_cmt_pf;
- SCTPDBG(SCTP_DEBUG_INDATA1, "Destination %p moved from PF to reachable with cwnd %d.\n",
- net, net->cwnd);
- /*
- * Since the cwnd value is explicitly set,
- * skip the code that updates the cwnd
- * value.
- */
- goto skip_cwnd_update;
- }
- }
#ifdef JANA_CMT_FAST_RECOVERY
/*
* CMT fast recovery code
@@ -2441,7 +2167,7 @@ sctp_htcp_cwnd_update_after_sack(struct sctp_tcb *stcb,
* If we are in loss recovery we skip any cwnd
* update
*/
- goto skip_cwnd_update;
+ return;
}
/*
* CMT: CUC algorithm. Update cwnd if pseudo-cumack has
@@ -2457,23 +2183,6 @@ sctp_htcp_cwnd_update_after_sack(struct sctp_tcb *stcb,
SCTP_CWND_LOG_NO_CUMACK);
}
}
-skip_cwnd_update:
- /*
- * NOW, according to Karn's rule do we need to restore the
- * RTO timer back? Check our net_ack2. If not set then we
- * have a ambiguity.. i.e. all data ack'd was sent to more
- * than one place.
- */
- if (net->net_ack2) {
- /* restore any doubled timers */
- net->RTO = (net->lastsa >> SCTP_RTT_SHIFT) + net->lastsv;
- if (net->RTO < stcb->asoc.minrto) {
- net->RTO = stcb->asoc.minrto;
- }
- if (net->RTO > stcb->asoc.maxrto) {
- net->RTO = stcb->asoc.maxrto;
- }
- }
}
}
@@ -2566,30 +2275,6 @@ sctp_htcp_cwnd_update_after_timeout(struct sctp_tcb *stcb,
}
static void
-sctp_htcp_cwnd_update_after_fr_timer(struct sctp_inpcb *inp,
- struct sctp_tcb *stcb, struct sctp_nets *net)
-{
- int old_cwnd;
-
- old_cwnd = net->cwnd;
-
- sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_EARLY_FR_TMR, SCTP_SO_NOT_LOCKED);
- net->cc_mod.htcp_ca.last_cong = sctp_get_tick_count();
- /*
- * make a small adjustment to cwnd and force to CA.
- */
- if (net->cwnd > net->mtu)
- /* drop down one MTU after sending */
- net->cwnd -= net->mtu;
- if (net->cwnd < net->ssthresh)
- /* still in SS move to CA */
- net->ssthresh = net->cwnd - 1;
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) {
- sctp_log_cwnd(stcb, net, (old_cwnd - net->cwnd), SCTP_CWND_LOG_FROM_FR);
- }
-}
-
-static void
sctp_htcp_cwnd_update_after_ecn_echo(struct sctp_tcb *stcb,
struct sctp_nets *net, int in_window, int num_pkt_lost)
{
@@ -2618,42 +2303,42 @@ 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,
+ .sctp_cwnd_update_exit_pf = sctp_cwnd_update_exit_pf_common,
.sctp_cwnd_update_after_fr = sctp_cwnd_update_after_fr,
.sctp_cwnd_update_after_timeout = sctp_cwnd_update_after_timeout,
.sctp_cwnd_update_after_ecn_echo = sctp_cwnd_update_after_ecn_echo,
.sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
.sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
- .sctp_cwnd_update_after_fr_timer = sctp_cwnd_update_after_fr_timer
},
{
.sctp_set_initial_cc_param = sctp_set_initial_cc_param,
.sctp_cwnd_update_after_sack = sctp_hs_cwnd_update_after_sack,
+ .sctp_cwnd_update_exit_pf = sctp_cwnd_update_exit_pf_common,
.sctp_cwnd_update_after_fr = sctp_hs_cwnd_update_after_fr,
.sctp_cwnd_update_after_timeout = sctp_cwnd_update_after_timeout,
.sctp_cwnd_update_after_ecn_echo = sctp_cwnd_update_after_ecn_echo,
.sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
.sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
- .sctp_cwnd_update_after_fr_timer = sctp_cwnd_update_after_fr_timer
},
{
.sctp_set_initial_cc_param = sctp_htcp_set_initial_cc_param,
.sctp_cwnd_update_after_sack = sctp_htcp_cwnd_update_after_sack,
+ .sctp_cwnd_update_exit_pf = sctp_cwnd_update_exit_pf_common,
.sctp_cwnd_update_after_fr = sctp_htcp_cwnd_update_after_fr,
.sctp_cwnd_update_after_timeout = sctp_htcp_cwnd_update_after_timeout,
.sctp_cwnd_update_after_ecn_echo = sctp_htcp_cwnd_update_after_ecn_echo,
.sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
.sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
- .sctp_cwnd_update_after_fr_timer = sctp_htcp_cwnd_update_after_fr_timer
},
{
.sctp_set_initial_cc_param = sctp_set_rtcc_initial_cc_param,
.sctp_cwnd_update_after_sack = sctp_cwnd_update_rtcc_after_sack,
+ .sctp_cwnd_update_exit_pf = sctp_cwnd_update_exit_pf_common,
.sctp_cwnd_update_after_fr = sctp_cwnd_update_after_fr,
.sctp_cwnd_update_after_timeout = sctp_cwnd_update_after_timeout,
.sctp_cwnd_update_after_ecn_echo = sctp_cwnd_update_rtcc_after_ecn_echo,
.sctp_cwnd_update_after_packet_dropped = sctp_cwnd_update_after_packet_dropped,
.sctp_cwnd_update_after_output = sctp_cwnd_update_after_output,
- .sctp_cwnd_update_after_fr_timer = sctp_cwnd_update_after_fr_timer,
.sctp_cwnd_update_packet_transmitted = sctp_cwnd_update_rtcc_packet_transmitted,
.sctp_cwnd_update_tsn_acknowledged = sctp_cwnd_update_rtcc_tsn_acknowledged,
.sctp_cwnd_new_transmission_begins = sctp_cwnd_new_rtcc_transmission_begins,
diff --git a/sys/netinet/sctp_constants.h b/sys/netinet/sctp_constants.h
index 6c2df1693fb1b..4087c8d266d18 100644
--- a/sys/netinet/sctp_constants.h
+++ b/sys/netinet/sctp_constants.h
@@ -416,7 +416,7 @@ __FBSDID("$FreeBSD$");
#define SCTP_STR_RESET_IN_REQUEST 0x000e
#define SCTP_STR_RESET_TSN_REQUEST 0x000f
#define SCTP_STR_RESET_RESPONSE 0x0010
-#define SCTP_STR_RESET_ADD_STREAMS 0x0011
+#define SCTP_STR_RESET_ADD_STREAMS 0x0011
#define SCTP_MAX_RESET_PARAMS 2
#define SCTP_STREAM_RESET_TSN_DELTA 0x1000
@@ -508,14 +508,10 @@ __FBSDID("$FreeBSD$");
/* SCTP reachability state for each address */
#define SCTP_ADDR_REACHABLE 0x001
-#define SCTP_ADDR_NOT_REACHABLE 0x002
#define SCTP_ADDR_NOHB 0x004
#define SCTP_ADDR_BEING_DELETED 0x008
#define SCTP_ADDR_NOT_IN_ASSOC 0x010
-#define SCTP_ADDR_WAS_PRIMARY 0x020
-#define SCTP_ADDR_SWITCH_PRIMARY 0x040
#define SCTP_ADDR_OUT_OF_SCOPE 0x080
-#define SCTP_ADDR_DOUBLE_SWITCH 0x100
#define SCTP_ADDR_UNCONFIRMED 0x200
#define SCTP_ADDR_REQ_PRIMARY 0x400
/* JRS 5/13/07 - Added potentially failed state for CMT PF */
@@ -579,14 +575,13 @@ __FBSDID("$FreeBSD$");
#define SCTP_TIMER_TYPE_EVENTWAKE 13
#define SCTP_TIMER_TYPE_STRRESET 14
#define SCTP_TIMER_TYPE_INPKILL 15
-#define SCTP_TIMER_TYPE_EARLYFR 17
-#define SCTP_TIMER_TYPE_ASOCKILL 18
-#define SCTP_TIMER_TYPE_ADDR_WQ 19
-#define SCTP_TIMER_TYPE_ZERO_COPY 20
-#define SCTP_TIMER_TYPE_ZCOPY_SENDQ 21
-#define SCTP_TIMER_TYPE_PRIM_DELETED 22
+#define SCTP_TIMER_TYPE_ASOCKILL 16
+#define SCTP_TIMER_TYPE_ADDR_WQ 17
+#define SCTP_TIMER_TYPE_ZERO_COPY 18
+#define SCTP_TIMER_TYPE_ZCOPY_SENDQ 19
+#define SCTP_TIMER_TYPE_PRIM_DELETED 20
/* add new timers here - and increment LAST */
-#define SCTP_TIMER_TYPE_LAST 23
+#define SCTP_TIMER_TYPE_LAST 21
#define SCTP_IS_TIMER_TYPE_VALID(t) (((t) > SCTP_TIMER_TYPE_NONE) && \
((t) < SCTP_TIMER_TYPE_LAST))
@@ -655,16 +650,17 @@ __FBSDID("$FreeBSD$");
#define SCTP_DEFAULT_SECRET_LIFE_SEC 3600
#define SCTP_RTO_UPPER_BOUND (60000) /* 60 sec in ms */
-#define SCTP_RTO_LOWER_BOUND (300) /* 0.3 sec is ms */
+#define SCTP_RTO_LOWER_BOUND (1000) /* 1 sec is ms */
#define SCTP_RTO_INITIAL (3000) /* 3 sec in ms */
#define SCTP_INP_KILL_TIMEOUT 20/* number of ms to retry kill of inpcb */
#define SCTP_ASOC_KILL_TIMEOUT 10 /* number of ms to retry kill of inpcb */
-#define SCTP_DEF_MAX_INIT 8
-#define SCTP_DEF_MAX_SEND 10
-#define SCTP_DEF_MAX_PATH_RTX 5
+#define SCTP_DEF_MAX_INIT 8
+#define SCTP_DEF_MAX_SEND 10
+#define SCTP_DEF_MAX_PATH_RTX 5
+#define SCTP_DEF_PATH_PF_THRESHOLD SCTP_DEF_MAX_PATH_RTX
#define SCTP_DEF_PMTU_RAISE_SEC 600 /* 10 min between raise attempts */
@@ -679,7 +675,7 @@ __FBSDID("$FreeBSD$");
/* Send window update (incr * this > hiwat). Should be a power of 2 */
#define SCTP_MINIMAL_RWND (4096) /* minimal rwnd */
-#define SCTP_ADDRMAX 24
+#define SCTP_ADDRMAX 16
/* SCTP DEBUG Switch parameters */
#define SCTP_DEBUG_TIMER1 0x00000001
diff --git a/sys/netinet/sctp_header.h b/sys/netinet/sctp_header.h
index dc8d91785057d..1aff6a1485e91 100644
--- a/sys/netinet/sctp_header.h
+++ b/sys/netinet/sctp_header.h
@@ -98,9 +98,10 @@ struct sctp_heartbeat_info_param {
uint32_t time_value_2;
uint32_t random_value1;
uint32_t random_value2;
- uint16_t user_req;
uint8_t addr_family;
uint8_t addr_len;
+ /* make sure that this structure is 4 byte aligned */
+ uint8_t padding[2];
char address[SCTP_ADDRMAX];
} SCTP_PACKED;
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c
index e142a3e5246ed..48b79fb89da01 100644
--- a/sys/netinet/sctp_indata.c
+++ b/sys/netinet/sctp_indata.c
@@ -2434,7 +2434,8 @@ sctp_sack_check(struct sctp_tcb *stcb, int was_a_gap, int *abort_flag)
sctp_timer_stop(SCTP_TIMER_TYPE_RECV,
stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_INDATA + SCTP_LOC_18);
}
- sctp_send_shutdown(stcb, stcb->asoc.primary_destination);
+ sctp_send_shutdown(stcb,
+ ((stcb->asoc.alternate) ? stcb->asoc.alternate : stcb->asoc.primary_destination));
sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED);
} else {
int is_a_gap;
@@ -4054,9 +4055,50 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
}
/* JRS - Use the congestion control given in the CC module */
- if ((asoc->last_acked_seq != cumack) && (ecne_seen == 0))
+ if ((asoc->last_acked_seq != cumack) && (ecne_seen == 0)) {
+ TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
+ if (net->net_ack2 > 0) {
+ /*
+ * Karn's rule applies to clearing error
+ * count, this is optional.
+ */
+ net->error_count = 0;
+ if (!(net->dest_state & SCTP_ADDR_REACHABLE)) {
+ /* addr came good */
+ net->dest_state |= SCTP_ADDR_REACHABLE;
+ sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb,
+ SCTP_RECEIVED_SACK, (void *)net, SCTP_SO_NOT_LOCKED);
+ }
+ if (net == stcb->asoc.primary_destination) {
+ if (stcb->asoc.alternate) {
+ /*
+ * release the alternate,
+ * primary is good
+ */
+ sctp_free_remote_addr(stcb->asoc.alternate);
+ stcb->asoc.alternate = NULL;
+ }
+ }
+ if (net->dest_state & SCTP_ADDR_PF) {
+ net->dest_state &= ~SCTP_ADDR_PF;
+ sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3);
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
+ asoc->cc_functions.sctp_cwnd_update_exit_pf(stcb, net);
+ /* Done with this net */
+ net->net_ack = 0;
+ }
+ /* restore any doubled timers */
+ net->RTO = (net->lastsa >> SCTP_RTT_SHIFT) + net->lastsv;
+ if (net->RTO < stcb->asoc.minrto) {
+ net->RTO = stcb->asoc.minrto;
+ }
+ if (net->RTO > stcb->asoc.maxrto) {
+ net->RTO = stcb->asoc.maxrto;
+ }
+ }
+ }
asoc->cc_functions.sctp_cwnd_update_after_sack(stcb, asoc, 1, 0, 0);
-
+ }
asoc->last_acked_seq = cumack;
if (TAILQ_EMPTY(&asoc->sent_queue)) {
@@ -4127,13 +4169,6 @@ again:
stcb, net,
SCTP_FROM_SCTP_INDATA + SCTP_LOC_22);
}
- if (SCTP_BASE_SYSCTL(sctp_early_fr)) {
- if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
- SCTP_STAT_INCR(sctps_earlyfrstpidsck4);
- sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
- SCTP_FROM_SCTP_INDATA + SCTP_LOC_23);
- }
- }
}
}
if ((j == 0) &&
@@ -4222,6 +4257,8 @@ again:
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_24;
sctp_abort_an_association(stcb->sctp_ep, stcb, SCTP_RESPONSE_TO_USER_REQ, oper, SCTP_SO_NOT_LOCKED);
} else {
+ struct sctp_nets *netp;
+
if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
(SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
@@ -4229,26 +4266,36 @@ again:
SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
sctp_stop_timers_for_shutdown(stcb);
- sctp_send_shutdown(stcb,
- stcb->asoc.primary_destination);
+ if (asoc->alternate) {
+ netp = asoc->alternate;
+ } else {
+ netp = asoc->primary_destination;
+ }
+ sctp_send_shutdown(stcb, netp);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
- stcb->sctp_ep, stcb, asoc->primary_destination);
+ stcb->sctp_ep, stcb, netp);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
- stcb->sctp_ep, stcb, asoc->primary_destination);
+ stcb->sctp_ep, stcb, netp);
}
} else if ((SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED) &&
(asoc->stream_queue_cnt == 0)) {
+ struct sctp_nets *netp;
+
+ if (asoc->alternate) {
+ netp = asoc->alternate;
+ } else {
+ netp = asoc->primary_destination;
+ }
if (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT) {
goto abort_out_now;
}
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT);
SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
- sctp_send_shutdown_ack(stcb,
- stcb->asoc.primary_destination);
+ sctp_send_shutdown_ack(stcb, netp);
sctp_stop_timers_for_shutdown(stcb);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK,
- stcb->sctp_ep, stcb, asoc->primary_destination);
+ stcb->sctp_ep, stcb, netp);
}
}
/*********************************************/
@@ -4380,7 +4427,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
num_dup,
SCTP_LOG_NEW_SACK);
}
- if ((num_dup) && (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_FR_LOGGING_ENABLE | SCTP_EARLYFR_LOGGING_ENABLE))) {
+ if ((num_dup) && (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE)) {
uint16_t i;
uint32_t *dupdata, dblock;
@@ -4468,13 +4515,6 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_26);
- if (SCTP_BASE_SYSCTL(sctp_early_fr)) {
- if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
- SCTP_STAT_INCR(sctps_earlyfrstpidsck1);
- sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
- SCTP_FROM_SCTP_INDATA + SCTP_LOC_26);
- }
- }
net->partial_bytes_acked = 0;
net->flight_size = 0;
}
@@ -4830,20 +4870,54 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
asoc->saw_sack_with_nr_frags = 0;
/* JRS - Use the congestion control given in the CC module */
- if (ecne_seen == 0)
+ if (ecne_seen == 0) {
+ TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
+ if (net->net_ack2 > 0) {
+ /*
+ * Karn's rule applies to clearing error
+ * count, this is optional.
+ */
+ net->error_count = 0;
+ if (!(net->dest_state & SCTP_ADDR_REACHABLE)) {
+ /* addr came good */
+ net->dest_state |= SCTP_ADDR_REACHABLE;
+ sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb,
+ SCTP_RECEIVED_SACK, (void *)net, SCTP_SO_NOT_LOCKED);
+ }
+ if (net == stcb->asoc.primary_destination) {
+ if (stcb->asoc.alternate) {
+ /*
+ * release the alternate,
+ * primary is good
+ */
+ sctp_free_remote_addr(stcb->asoc.alternate);
+ stcb->asoc.alternate = NULL;
+ }
+ }
+ if (net->dest_state & SCTP_ADDR_PF) {
+ net->dest_state &= ~SCTP_ADDR_PF;
+ sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3);
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
+ asoc->cc_functions.sctp_cwnd_update_exit_pf(stcb, net);
+ /* Done with this net */
+ net->net_ack = 0;
+ }
+ /* restore any doubled timers */
+ net->RTO = (net->lastsa >> SCTP_RTT_SHIFT) + net->lastsv;
+ if (net->RTO < stcb->asoc.minrto) {
+ net->RTO = stcb->asoc.minrto;
+ }
+ if (net->RTO > stcb->asoc.maxrto) {
+ net->RTO = stcb->asoc.maxrto;
+ }
+ }
+ }
asoc->cc_functions.sctp_cwnd_update_after_sack(stcb, asoc, accum_moved, reneged_all, will_exit_fast_recovery);
-
+ }
if (TAILQ_EMPTY(&asoc->sent_queue)) {
/* nothing left in-flight */
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
/* stop all timers */
- if (SCTP_BASE_SYSCTL(sctp_early_fr)) {
- if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
- SCTP_STAT_INCR(sctps_earlyfrstpidsck4);
- sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
- SCTP_FROM_SCTP_INDATA + SCTP_LOC_29);
- }
- }
sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
stcb, net, SCTP_FROM_SCTP_INDATA + SCTP_LOC_30);
net->flight_size = 0;
@@ -4918,6 +4992,13 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
sctp_abort_an_association(stcb->sctp_ep, stcb, SCTP_RESPONSE_TO_USER_REQ, oper, SCTP_SO_NOT_LOCKED);
return;
} else {
+ struct sctp_nets *netp;
+
+ if (asoc->alternate) {
+ netp = asoc->alternate;
+ } else {
+ netp = asoc->primary_destination;
+ }
if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
(SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
@@ -4925,27 +5006,32 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
sctp_stop_timers_for_shutdown(stcb);
- sctp_send_shutdown(stcb,
- stcb->asoc.primary_destination);
+ sctp_send_shutdown(stcb, netp);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
- stcb->sctp_ep, stcb, asoc->primary_destination);
+ stcb->sctp_ep, stcb, netp);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
- stcb->sctp_ep, stcb, asoc->primary_destination);
+ stcb->sctp_ep, stcb, netp);
}
return;
} else if ((SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED) &&
(asoc->stream_queue_cnt == 0)) {
+ struct sctp_nets *netp;
+
+ if (asoc->alternate) {
+ netp = asoc->alternate;
+ } else {
+ netp = asoc->primary_destination;
+ }
if (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT) {
goto abort_out_now;
}
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT);
SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
- sctp_send_shutdown_ack(stcb,
- stcb->asoc.primary_destination);
+ sctp_send_shutdown_ack(stcb, netp);
sctp_stop_timers_for_shutdown(stcb);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK,
- stcb->sctp_ep, stcb, asoc->primary_destination);
+ stcb->sctp_ep, stcb, netp);
return;
}
}
@@ -5056,13 +5142,6 @@ again:
stcb, net,
SCTP_FROM_SCTP_INDATA + SCTP_LOC_22);
}
- if (SCTP_BASE_SYSCTL(sctp_early_fr)) {
- if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
- SCTP_STAT_INCR(sctps_earlyfrstpidsck4);
- sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net,
- SCTP_FROM_SCTP_INDATA + SCTP_LOC_23);
- }
- }
}
}
if ((j == 0) &&
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index 4c4d779b39d0d..d8f0ae539707f 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -537,6 +537,7 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp,
struct sctp_nets *r_net, *f_net;
struct timeval tv;
int req_prim = 0;
+ uint16_t old_error_counter;
#ifdef INET
struct sockaddr_in *sin;
@@ -599,7 +600,6 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp,
r_net->dest_state &= ~SCTP_ADDR_UNCONFIRMED;
if (r_net->dest_state & SCTP_ADDR_REQ_PRIMARY) {
stcb->asoc.primary_destination = r_net;
- r_net->dest_state &= ~SCTP_ADDR_WAS_PRIMARY;
r_net->dest_state &= ~SCTP_ADDR_REQ_PRIMARY;
f_net = TAILQ_FIRST(&stcb->asoc.nets);
if (f_net != r_net) {
@@ -616,44 +616,37 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp,
}
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
stcb, 0, (void *)r_net, SCTP_SO_NOT_LOCKED);
+ sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3);
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net);
}
+ old_error_counter = r_net->error_count;
r_net->error_count = 0;
r_net->hb_responded = 1;
tv.tv_sec = cp->heartbeat.hb_info.time_value_1;
tv.tv_usec = cp->heartbeat.hb_info.time_value_2;
- if (r_net->dest_state & SCTP_ADDR_NOT_REACHABLE) {
- r_net->dest_state &= ~SCTP_ADDR_NOT_REACHABLE;
+ /* Now lets do a RTO with this */
+ r_net->RTO = sctp_calculate_rto(stcb, &stcb->asoc, r_net, &tv, sctp_align_safe_nocopy,
+ SCTP_RTT_FROM_NON_DATA);
+ if (!(r_net->dest_state & SCTP_ADDR_REACHABLE)) {
r_net->dest_state |= SCTP_ADDR_REACHABLE;
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb,
SCTP_HEARTBEAT_SUCCESS, (void *)r_net, SCTP_SO_NOT_LOCKED);
- /* now was it the primary? if so restore */
- if (r_net->dest_state & SCTP_ADDR_WAS_PRIMARY) {
- (void)sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, r_net);
- }
}
- /*
- * JRS 5/14/07 - If CMT PF is on and the destination is in PF state,
- * set the destination to active state and set the cwnd to one or
- * two MTU's based on whether PF1 or PF2 is being used. If a T3
- * timer is running, for the destination, stop the timer because a
- * PF-heartbeat was received.
- */
- if ((stcb->asoc.sctp_cmt_on_off > 0) &&
- (stcb->asoc.sctp_cmt_pf > 0) &&
- ((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF)) {
- if (SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer)) {
- sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
- stcb, net,
- SCTP_FROM_SCTP_INPUT + SCTP_LOC_5);
+ if (r_net->dest_state & SCTP_ADDR_PF) {
+ r_net->dest_state &= ~SCTP_ADDR_PF;
+ stcb->asoc.cc_functions.sctp_cwnd_update_exit_pf(stcb, net);
+ }
+ if (old_error_counter > 0) {
+ sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3);
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net);
+ }
+ if (r_net == stcb->asoc.primary_destination) {
+ if (stcb->asoc.alternate) {
+ /* release the alternate, primary is good */
+ sctp_free_remote_addr(stcb->asoc.alternate);
+ stcb->asoc.alternate = NULL;
}
- net->dest_state &= ~SCTP_ADDR_PF;
- net->cwnd = net->mtu * stcb->asoc.sctp_cmt_pf;
- SCTPDBG(SCTP_DEBUG_INPUT1, "Destination %p moved from PF to reachable with cwnd %d.\n",
- net, net->cwnd);
}
- /* Now lets do a RTO with this */
- r_net->RTO = sctp_calculate_rto(stcb, &stcb->asoc, r_net, &tv, sctp_align_safe_nocopy,
- SCTP_RTT_FROM_NON_DATA);
/* Mobility adaptation */
if (req_prim) {
if ((sctp_is_mobility_feature_on(stcb->sctp_ep,
@@ -825,6 +818,35 @@ sctp_handle_abort(struct sctp_abort_chunk *cp,
}
static void
+sctp_start_net_timers(struct sctp_tcb *stcb)
+{
+ uint32_t cnt_hb_sent;
+ struct sctp_nets *net;
+
+ cnt_hb_sent = 0;
+ TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
+ /*
+ * For each network start: 1) A pmtu timer. 2) A HB timer 3)
+ * If the dest in unconfirmed send a hb as well if under
+ * max_hb_burst have been sent.
+ */
+ sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, stcb->sctp_ep, stcb, net);
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
+ if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
+ (cnt_hb_sent < SCTP_BASE_SYSCTL(sctp_hb_maxburst))) {
+ sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED);
+ cnt_hb_sent++;
+ }
+ }
+ if (cnt_hb_sent) {
+ sctp_chunk_output(stcb->sctp_ep, stcb,
+ SCTP_OUTPUT_FROM_COOKIE_ACK,
+ SCTP_SO_NOT_LOCKED);
+ }
+}
+
+
+static void
sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
struct sctp_tcb *stcb, struct sctp_nets *net, int *abort_flag)
{
@@ -916,7 +938,7 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
} else {
/* no outstanding data to send, so move on... */
/* send SHUTDOWN-ACK */
- sctp_send_shutdown_ack(stcb, stcb->asoc.primary_destination);
+ sctp_send_shutdown_ack(stcb, net);
/* move to SHUTDOWN-ACK-SENT state */
if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
(SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
@@ -2685,7 +2707,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
/* TSNH! Huh, why do I need to add this address here? */
int ret;
- ret = sctp_add_remote_addr(*stcb, to, SCTP_DONOT_SETSCOPE,
+ ret = sctp_add_remote_addr(*stcb, to, NULL, SCTP_DONOT_SETSCOPE,
SCTP_IN_COOKIE_PROC);
netl = sctp_findnet(*stcb, to);
}
@@ -2697,10 +2719,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
send_int_conf = 1;
}
}
- if (*stcb) {
- sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, *inp_p,
- *stcb, NULL);
- }
+ sctp_start_net_timers(*stcb);
if ((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
if (!had_a_existing_tcb ||
(((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
@@ -2890,6 +2909,7 @@ sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp,
/* state change only needed when I am in right state */
SCTPDBG(SCTP_DEBUG_INPUT2, "moving to OPEN state\n");
SCTP_SET_STATE(asoc, SCTP_STATE_OPEN);
+ sctp_start_net_timers(stcb);
if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
stcb->sctp_ep, stcb, asoc->primary_destination);
@@ -3380,7 +3400,7 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc,
* Only retransmit if we KNOW we wont destroy the
* tcb
*/
- (void)sctp_send_hb(stcb, 1, net, SCTP_SO_NOT_LOCKED);
+ sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED);
}
break;
case SCTP_SHUTDOWN:
@@ -3999,8 +4019,7 @@ strres_nochunk:
/* setup chunk parameters */
chk->sent = SCTP_DATAGRAM_UNSENT;
chk->snd_count = 0;
- chk->whoTo = stcb->asoc.primary_destination;
- atomic_add_int(&chk->whoTo->ref_count, 1);
+ chk->whoTo = NULL;
ch = mtod(chk->data, struct sctp_chunkhdr *);
ch->chunk_type = SCTP_STREAM_RESET;
@@ -4630,8 +4649,7 @@ process_control_chunks:
if ((stcb != NULL) &&
(SCTP_GET_STATE(&stcb->asoc) ==
SCTP_STATE_SHUTDOWN_ACK_SENT)) {
- sctp_send_shutdown_ack(stcb,
- stcb->asoc.primary_destination);
+ sctp_send_shutdown_ack(stcb, NULL);
*offset = length;
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED);
if (locked_tcb) {
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index 043b3b274c347..7fd5d4d22affd 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -3541,9 +3541,10 @@ sctp_process_cmsgs_for_init(struct sctp_tcb *stcb, struct mbuf *control, int *er
(sin.sin_addr.s_addr == INADDR_BROADCAST) ||
IN_MULTICAST(ntohl(sin.sin_addr.s_addr))) {
*error = EINVAL;
- return (-1);
+ return (1);
}
- if (sctp_add_remote_addr(stcb, (struct sockaddr *)&sin, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
+ if (sctp_add_remote_addr(stcb, (struct sockaddr *)&sin, NULL,
+ SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
*error = ENOBUFS;
return (1);
}
@@ -3563,7 +3564,7 @@ sctp_process_cmsgs_for_init(struct sctp_tcb *stcb, struct mbuf *control, int *er
if (IN6_IS_ADDR_UNSPECIFIED(&sin6.sin6_addr) ||
IN6_IS_ADDR_MULTICAST(&sin6.sin6_addr)) {
*error = EINVAL;
- return (-1);
+ return (1);
}
#ifdef INET
if (IN6_IS_ADDR_V4MAPPED(&sin6.sin6_addr)) {
@@ -3572,15 +3573,17 @@ sctp_process_cmsgs_for_init(struct sctp_tcb *stcb, struct mbuf *control, int *er
(sin.sin_addr.s_addr == INADDR_BROADCAST) ||
IN_MULTICAST(ntohl(sin.sin_addr.s_addr))) {
*error = EINVAL;
- return (-1);
+ return (1);
}
- if (sctp_add_remote_addr(stcb, (struct sockaddr *)&sin, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
+ if (sctp_add_remote_addr(stcb, (struct sockaddr *)&sin, NULL,
+ SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
*error = ENOBUFS;
return (1);
}
} else
#endif
- if (sctp_add_remote_addr(stcb, (struct sockaddr *)&sin6, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
+ if (sctp_add_remote_addr(stcb, (struct sockaddr *)&sin6, NULL,
+ SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
*error = ENOBUFS;
return (1);
}
@@ -3828,28 +3831,7 @@ sctp_handle_no_route(struct sctp_tcb *stcb,
(void *)net,
so_locked);
net->dest_state &= ~SCTP_ADDR_REACHABLE;
- net->dest_state |= SCTP_ADDR_NOT_REACHABLE;
- /*
- * JRS 5/14/07 - If a destination is
- * unreachable, the PF bit is turned off.
- * This allows an unambiguous use of the PF
- * bit for destinations that are reachable
- * but potentially failed. If the
- * destination is set to the unreachable
- * state, also set the destination to the PF
- * state.
- */
- /*
- * Add debug message here if destination is
- * not in PF state.
- */
- /* Stop any running T3 timers here? */
- if ((stcb->asoc.sctp_cmt_on_off > 0) &&
- (stcb->asoc.sctp_cmt_pf > 0)) {
- net->dest_state &= ~SCTP_ADDR_PF;
- SCTPDBG(SCTP_DEBUG_OUTPUT1, "Destination %p moved from PF to unreachable.\n",
- net);
- }
+ net->dest_state &= ~SCTP_ADDR_PF;
}
}
if (stcb) {
@@ -3859,14 +3841,16 @@ sctp_handle_no_route(struct sctp_tcb *stcb,
alt = sctp_find_alternate_net(stcb, net, 0);
if (alt != net) {
- if (sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, alt) == 0) {
- net->dest_state |= SCTP_ADDR_WAS_PRIMARY;
- if (net->ro._s_addr) {
- sctp_free_ifa(net->ro._s_addr);
- net->ro._s_addr = NULL;
- }
- net->src_addr_selected = 0;
+ if (stcb->asoc.alternate) {
+ sctp_free_remote_addr(stcb->asoc.alternate);
+ }
+ stcb->asoc.alternate = alt;
+ atomic_add_int(&stcb->asoc.alternate->ref_count, 1);
+ if (net->ro._s_addr) {
+ sctp_free_ifa(net->ro._s_addr);
+ net->ro._s_addr = NULL;
}
+ net->src_addr_selected = 0;
}
}
}
@@ -3920,6 +3904,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
uint32_t vrf_id;
sctp_route_t *ro = NULL;
struct udphdr *udp = NULL;
+ uint8_t tos_value;
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
struct socket *so = NULL;
@@ -3941,13 +3926,20 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
if ((auth != NULL) && (stcb != NULL)) {
sctp_fill_hmac_digest_m(m, auth_offset, auth, stcb, auth_keyid);
}
+ if (net) {
+ tos_value = net->dscp;
+ } else if (stcb) {
+ tos_value = stcb->asoc.default_dscp;
+ } else {
+ tos_value = inp->sctp_ep.default_dscp;
+ }
+
switch (to->sa_family) {
#ifdef INET
case AF_INET:
{
struct ip *ip = NULL;
sctp_route_t iproute;
- uint8_t tos_value;
int len;
len = sizeof(struct ip) + sizeof(struct sctphdr);
@@ -3982,11 +3974,18 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
ip = mtod(m, struct ip *);
ip->ip_v = IPVERSION;
ip->ip_hl = (sizeof(struct ip) >> 2);
- if (net) {
- tos_value = net->tos_flowlabel & 0x000000ff;
- } else {
+ if (tos_value == 0) {
+ /*
+ * This means especially, that it is not set
+ * at the SCTP layer. So use the value from
+ * the IP layer.
+ */
tos_value = inp->ip_inp.inp.inp_ip_tos;
}
+ tos_value &= 0xfc;
+ if (ecn_ok) {
+ tos_value |= sctp_get_ect(stcb, chk);
+ }
if ((nofragment_flag) && (port == 0)) {
ip->ip_off = IP_DF;
} else
@@ -3997,10 +3996,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
ip->ip_ttl = inp->ip_inp.inp.inp_ip_ttl;
ip->ip_len = packet_length;
- ip->ip_tos = tos_value & 0xfc;
- if (ecn_ok) {
- ip->ip_tos |= sctp_get_ect(stcb, chk);
- }
+ ip->ip_tos = tos_value;
if (port) {
ip->ip_p = IPPROTO_UDP;
} else {
@@ -4205,13 +4201,10 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
#ifdef INET6
case AF_INET6:
{
- uint32_t flowlabel;
+ uint32_t flowlabel, flowinfo;
struct ip6_hdr *ip6h;
struct route_in6 ip6route;
struct ifnet *ifp;
- u_char flowTop;
- uint16_t flowBottom;
- u_char tosBottom, tosTop;
struct sockaddr_in6 *sin6, tmp, *lsa6, lsa6_tmp;
int prev_scope = 0;
struct sockaddr_in6 lsa6_storage;
@@ -4219,12 +4212,22 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
u_short prev_port = 0;
int len;
- if (net != NULL) {
- flowlabel = net->tos_flowlabel;
+ if (net) {
+ flowlabel = net->flowlabel;
+ } else if (stcb) {
+ flowlabel = stcb->asoc.default_flowlabel;
} else {
- flowlabel = ((struct in6pcb *)inp)->in6p_flowinfo;
+ flowlabel = inp->sctp_ep.default_flowlabel;
}
-
+ if (flowlabel == 0) {
+ /*
+ * This means especially, that it is not set
+ * at the SCTP layer. So use the value from
+ * the IP layer.
+ */
+ flowlabel = ntohl(((struct in6pcb *)inp)->in6p_flowinfo);
+ }
+ flowlabel &= 0x000fffff;
len = sizeof(struct ip6_hdr) + sizeof(struct sctphdr);
if (port) {
len += sizeof(struct udphdr);
@@ -4256,13 +4259,6 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
packet_length = sctp_calculate_len(m);
ip6h = mtod(m, struct ip6_hdr *);
- /*
- * We assume here that inp_flow is in host byte
- * order within the TCB!
- */
- flowBottom = flowlabel & 0x0000ffff;
- flowTop = ((flowlabel & 0x000f0000) >> 16);
- tosTop = (((flowlabel & 0xf0) >> 4) | IPV6_VERSION);
/* protect *sin6 from overwrite */
sin6 = (struct sockaddr_in6 *)to;
tmp = *sin6;
@@ -4280,12 +4276,28 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
} else {
ro = (sctp_route_t *) & net->ro;
}
- tosBottom = (((struct in6pcb *)inp)->in6p_flowinfo & 0x0c);
+ /*
+ * We assume here that inp_flow is in host byte
+ * order within the TCB!
+ */
+ if (tos_value == 0) {
+ /*
+ * This means especially, that it is not set
+ * at the SCTP layer. So use the value from
+ * the IP layer.
+ */
+ tos_value = (ntohl(((struct in6pcb *)inp)->in6p_flowinfo) >> 20) & 0xff;
+ }
+ tos_value &= 0xfc;
if (ecn_ok) {
- tosBottom |= sctp_get_ect(stcb, chk);
+ tos_value |= sctp_get_ect(stcb, chk);
}
- tosBottom <<= 4;
- ip6h->ip6_flow = htonl(((tosTop << 24) | ((tosBottom | flowTop) << 16) | flowBottom));
+ flowinfo = 0x06;
+ flowinfo <<= 8;
+ flowinfo |= tos_value;
+ flowinfo <<= 20;
+ flowinfo |= flowlabel;
+ ip6h->ip6_flow = htonl(flowinfo);
if (port) {
ip6h->ip6_nxt = IPPROTO_UDP;
} else {
@@ -6498,6 +6510,7 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
int added_control = 0;
int un_sent, do_chunk_output = 1;
struct sctp_association *asoc;
+ struct sctp_nets *net;
ca = (struct sctp_copy_all *)ptr;
if (ca->m == NULL) {
@@ -6531,6 +6544,11 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
m = NULL;
}
SCTP_TCB_LOCK_ASSERT(stcb);
+ if (stcb->asoc.alternate) {
+ net = stcb->asoc.alternate;
+ } else {
+ net = stcb->asoc.primary_destination;
+ }
if (ca->sndrcv.sinfo_flags & SCTP_ABORT) {
/* Abort this assoc with m as the user defined reason */
if (m) {
@@ -6569,7 +6587,7 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
}
} else {
if (m) {
- ret = sctp_msg_append(stcb, stcb->asoc.primary_destination, m,
+ ret = sctp_msg_append(stcb, net, m,
&ca->sndrcv, 1);
}
asoc = &stcb->asoc;
@@ -6596,14 +6614,14 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
* only send SHUTDOWN the first time
* through
*/
- sctp_send_shutdown(stcb, stcb->asoc.primary_destination);
+ sctp_send_shutdown(stcb, net);
if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb,
- asoc->primary_destination);
+ net);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
asoc->primary_destination);
added_control = 1;
@@ -7733,13 +7751,13 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
struct sctp_auth_chunk *auth = NULL;
uint16_t auth_keyid;
int override_ok = 1;
+ int skip_fill_up = 0;
int data_auth_reqd = 0;
/*
* JRS 5/14/07 - Add flag for whether a heartbeat is sent to the
* destination.
*/
- int pf_hbflag = 0;
int quit_now = 0;
*num_out = 0;
@@ -7806,7 +7824,22 @@ nothing_to_send:
max_send_per_dest = SCTP_SB_LIMIT_SND(stcb->sctp_socket) / asoc->numnets;
else
max_send_per_dest = 0;
+ if (no_data_chunks == 0) {
+ /* How many non-directed chunks are there? */
+ TAILQ_FOREACH(chk, &asoc->send_queue, sctp_next) {
+ if (chk->whoTo == NULL) {
+ /*
+ * We already have non-directed chunks on
+ * the queue, no need to do a fill-up.
+ */
+ skip_fill_up = 1;
+ break;
+ }
+ }
+
+ }
if ((no_data_chunks == 0) &&
+ (skip_fill_up == 0) &&
(!stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc))) {
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
/*
@@ -7821,8 +7854,10 @@ nothing_to_send:
* copy by reference (we hope).
*/
net->window_probe = 0;
- if ((net->dest_state & SCTP_ADDR_NOT_REACHABLE) ||
- (net->dest_state & SCTP_ADDR_UNCONFIRMED)) {
+ if ((net != stcb->asoc.alternate) &&
+ ((net->dest_state & SCTP_ADDR_PF) ||
+ (!(net->dest_state & SCTP_ADDR_REACHABLE)) ||
+ (net->dest_state & SCTP_ADDR_UNCONFIRMED))) {
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
sctp_log_cwnd(stcb, net, 1,
SCTP_CWND_LOG_FILL_OUTQ_CALLED);
@@ -7833,16 +7868,6 @@ nothing_to_send:
(net->flight_size == 0)) {
(*stcb->asoc.cc_functions.sctp_cwnd_new_transmission_begins) (stcb, net);
}
- if ((asoc->sctp_cmt_on_off == 0) &&
- (asoc->primary_destination != net) &&
- (net->ref_count < 2)) {
- /* nothing can be in queue for this guy */
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
- sctp_log_cwnd(stcb, net, 2,
- SCTP_CWND_LOG_FILL_OUTQ_CALLED);
- }
- continue;
- }
if (net->flight_size >= net->cwnd) {
/* skip this network, no room - can't fill */
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
@@ -7886,6 +7911,16 @@ nothing_to_send:
} else {
start_at = TAILQ_FIRST(&asoc->nets);
}
+ TAILQ_FOREACH(chk, &asoc->control_send_queue, sctp_next) {
+ if (chk->whoTo == NULL) {
+ if (asoc->alternate) {
+ chk->whoTo = asoc->alternate;
+ } else {
+ chk->whoTo = asoc->primary_destination;
+ }
+ atomic_add_int(&chk->whoTo->ref_count, 1);
+ }
+ }
old_start_at = NULL;
again_one_more_time:
for (net = start_at; net != NULL; net = TAILQ_NEXT(net, sctp_next)) {
@@ -7896,15 +7931,6 @@ again_one_more_time:
break;
}
tsns_sent = 0xa;
- if ((asoc->sctp_cmt_on_off == 0) &&
- (asoc->primary_destination != net) &&
- (net->ref_count < 2)) {
- /*
- * Ref-count of 1 so we cannot have data or control
- * queued to this address. Skip it (non-CMT).
- */
- continue;
- }
if (TAILQ_EMPTY(&asoc->control_send_queue) &&
TAILQ_EMPTY(&asoc->asconf_send_queue) &&
(net->flight_size >= net->cwnd)) {
@@ -8266,15 +8292,8 @@ again_one_more_time:
(chk->rec.chunk_id.id == SCTP_ECN_CWR) ||
(chk->rec.chunk_id.id == SCTP_PACKET_DROPPED) ||
(chk->rec.chunk_id.id == SCTP_ASCONF_ACK)) {
-
if (chk->rec.chunk_id.id == SCTP_HEARTBEAT_REQUEST) {
hbflag = 1;
- /*
- * JRS 5/14/07 - Set the
- * flag to say a heartbeat
- * is being sent.
- */
- pf_hbflag = 1;
}
/* remove these chunks at the end */
if ((chk->rec.chunk_id.id == SCTP_SELECTIVE_ACK) ||
@@ -8408,7 +8427,7 @@ again_one_more_time:
}
/* JRI: if dest is in PF state, do not send data to it */
if ((asoc->sctp_cmt_on_off > 0) &&
- (asoc->sctp_cmt_pf > 0) &&
+ (net != stcb->asoc.alternate) &&
(net->dest_state & SCTP_ADDR_PF)) {
goto no_data_fill;
}
@@ -8486,6 +8505,17 @@ again_one_more_time:
/* Don't send the chunk on this net */
continue;
}
+ if (asoc->sctp_cmt_on_off == 0) {
+ if ((asoc->alternate) &&
+ (asoc->alternate != net) &&
+ (chk->whoTo == NULL)) {
+ continue;
+ } else if ((net != asoc->primary_destination) &&
+ (asoc->alternate == NULL) &&
+ (chk->whoTo == NULL)) {
+ continue;
+ }
+ }
if ((chk->send_size > omtu) && ((chk->flags & CHUNK_FLAGS_FRAGMENT_OK) == 0)) {
/*-
* strange, we have a chunk that is
@@ -8646,18 +8676,6 @@ no_data_fill:
* restart it.
*/
sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, net);
- } else if ((asoc->sctp_cmt_on_off > 0) &&
- (asoc->sctp_cmt_pf > 0) &&
- pf_hbflag &&
- ((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF) &&
- (!SCTP_OS_TIMER_PENDING(&net->rxt_timer.timer))) {
- /*
- * JRS 5/14/07 - If a HB has been sent to a
- * PF destination and no T3 timer is
- * currently running, start the T3 timer to
- * track the HBs that were sent.
- */
- sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, net);
}
/* Now send it, if there is anything to send :> */
if ((error = sctp_lowlevel_chunk_output(inp,
@@ -8747,24 +8765,6 @@ no_data_fill:
}
SCTP_STAT_INCR_BY(sctps_senddata, bundle_at);
sctp_clean_up_datalist(stcb, asoc, data_list, bundle_at, net);
- if (SCTP_BASE_SYSCTL(sctp_early_fr)) {
- if (net->flight_size < net->cwnd) {
- /* start or restart it */
- if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
- sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, inp, stcb, net,
- SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_2);
- }
- SCTP_STAT_INCR(sctps_earlyfrstrout);
- sctp_timer_start(SCTP_TIMER_TYPE_EARLYFR, inp, stcb, net);
- } else {
- /* stop it if its running */
- if (SCTP_OS_TIMER_PENDING(&net->fr_timer.timer)) {
- SCTP_STAT_INCR(sctps_earlyfrstpout);
- sctp_timer_stop(SCTP_TIMER_TYPE_EARLYFR, inp, stcb, net,
- SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_3);
- }
- }
- }
}
if (one_chunk) {
break;
@@ -8833,8 +8833,7 @@ sctp_queue_op_err(struct sctp_tcb *stcb, struct mbuf *op_err)
chk->flags = 0;
chk->asoc = &stcb->asoc;
chk->data = op_err;
- chk->whoTo = chk->asoc->primary_destination;
- atomic_add_int(&chk->whoTo->ref_count, 1);
+ chk->whoTo = NULL;
hdr = mtod(op_err, struct sctp_chunkhdr *);
hdr->chunk_type = SCTP_OPERATION_ERROR;
hdr->chunk_flags = 0;
@@ -8929,7 +8928,7 @@ sctp_send_cookie_echo(struct mbuf *m,
chk->flags = CHUNK_FLAGS_FRAGMENT_OK;
chk->asoc = &stcb->asoc;
chk->data = cookie;
- chk->whoTo = chk->asoc->primary_destination;
+ chk->whoTo = net;
atomic_add_int(&chk->whoTo->ref_count, 1);
TAILQ_INSERT_HEAD(&chk->asoc->control_send_queue, chk, sctp_next);
chk->asoc->ctrl_queue_cnt++;
@@ -9039,10 +9038,10 @@ sctp_send_cookie_ack(struct sctp_tcb *stcb)
chk->data = cookie_ack;
if (chk->asoc->last_control_chunk_from != NULL) {
chk->whoTo = chk->asoc->last_control_chunk_from;
+ atomic_add_int(&chk->whoTo->ref_count, 1);
} else {
- chk->whoTo = chk->asoc->primary_destination;
+ chk->whoTo = NULL;
}
- atomic_add_int(&chk->whoTo->ref_count, 1);
hdr = mtod(cookie_ack, struct sctp_chunkhdr *);
hdr->chunk_type = SCTP_COOKIE_ACK;
hdr->chunk_flags = 0;
@@ -9084,8 +9083,9 @@ sctp_send_shutdown_ack(struct sctp_tcb *stcb, struct sctp_nets *net)
chk->asoc = &stcb->asoc;
chk->data = m_shutdown_ack;
chk->whoTo = net;
- atomic_add_int(&net->ref_count, 1);
-
+ if (chk->whoTo) {
+ atomic_add_int(&chk->whoTo->ref_count, 1);
+ }
ack_cp = mtod(m_shutdown_ack, struct sctp_shutdown_ack_chunk *);
ack_cp->ch.chunk_type = SCTP_SHUTDOWN_ACK;
ack_cp->ch.chunk_flags = 0;
@@ -9126,8 +9126,9 @@ sctp_send_shutdown(struct sctp_tcb *stcb, struct sctp_nets *net)
chk->asoc = &stcb->asoc;
chk->data = m_shutdown;
chk->whoTo = net;
- atomic_add_int(&net->ref_count, 1);
-
+ if (chk->whoTo) {
+ atomic_add_int(&chk->whoTo->ref_count, 1);
+ }
shutdown_cp = mtod(m_shutdown, struct sctp_shutdown_chunk *);
shutdown_cp->ch.chunk_type = SCTP_SHUTDOWN;
shutdown_cp->ch.chunk_flags = 0;
@@ -9178,7 +9179,9 @@ sctp_send_asconf(struct sctp_tcb *stcb, struct sctp_nets *net, int addr_locked)
chk->flags = CHUNK_FLAGS_FRAGMENT_OK;
chk->asoc = &stcb->asoc;
chk->whoTo = net;
- atomic_add_int(&chk->whoTo->ref_count, 1);
+ if (chk->whoTo) {
+ atomic_add_int(&chk->whoTo->ref_count, 1);
+ }
TAILQ_INSERT_TAIL(&chk->asoc->asconf_send_queue, chk, sctp_next);
chk->asoc->ctrl_queue_cnt++;
return;
@@ -9208,17 +9211,27 @@ sctp_send_asconf_ack(struct sctp_tcb *stcb)
net = sctp_find_alternate_net(stcb, stcb->asoc.last_control_chunk_from, 0);
if (net == NULL) {
/* no alternate */
- if (stcb->asoc.last_control_chunk_from == NULL)
- net = stcb->asoc.primary_destination;
- else
+ if (stcb->asoc.last_control_chunk_from == NULL) {
+ if (stcb->asoc.alternate) {
+ net = stcb->asoc.alternate;
+ } else {
+ net = stcb->asoc.primary_destination;
+ }
+ } else {
net = stcb->asoc.last_control_chunk_from;
+ }
}
} else {
/* normal case */
- if (stcb->asoc.last_control_chunk_from == NULL)
- net = stcb->asoc.primary_destination;
- else
+ if (stcb->asoc.last_control_chunk_from == NULL) {
+ if (stcb->asoc.alternate) {
+ net = stcb->asoc.alternate;
+ } else {
+ net = stcb->asoc.primary_destination;
+ }
+ } else {
net = stcb->asoc.last_control_chunk_from;
+ }
}
latest_ack->last_sent_to = net;
@@ -9256,6 +9269,9 @@ sctp_send_asconf_ack(struct sctp_tcb *stcb)
chk->copy_by_ref = 0;
chk->whoTo = net;
+ if (chk->whoTo) {
+ atomic_add_int(&chk->whoTo->ref_count, 1);
+ }
chk->data = m_ack;
chk->send_size = 0;
/* Get size */
@@ -9267,7 +9283,6 @@ sctp_send_asconf_ack(struct sctp_tcb *stcb)
chk->snd_count = 0;
chk->flags |= CHUNK_FLAGS_FRAGMENT_OK; /* XXX */
chk->asoc = &stcb->asoc;
- atomic_add_int(&chk->whoTo->ref_count, 1);
TAILQ_INSERT_TAIL(&chk->asoc->control_send_queue, chk, sctp_next);
chk->asoc->ctrl_queue_cnt++;
@@ -9797,7 +9812,11 @@ sctp_timer_validation(struct sctp_inpcb *inp,
SCTP_TCB_LOCK_ASSERT(stcb);
/* Gak, we did not have a timer somewhere */
SCTPDBG(SCTP_DEBUG_OUTPUT3, "Deadlock avoided starting timer on a dest at retran\n");
- sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, asoc->primary_destination);
+ if (asoc->alternate) {
+ sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, asoc->alternate);
+ } else {
+ sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, asoc->primary_destination);
+ }
return (ret);
}
@@ -9830,19 +9849,22 @@ sctp_chunk_output(struct sctp_inpcb *inp,
unsigned int burst_cnt = 0;
struct timeval now;
int now_filled = 0;
- int nagle_on = 0;
+ int nagle_on;
int frag_point = sctp_get_frag_point(stcb, &stcb->asoc);
int un_sent = 0;
int fr_done;
unsigned int tot_frs = 0;
asoc = &stcb->asoc;
+ /* The Nagle algorithm is only applied when handling a send call. */
if (from_where == SCTP_OUTPUT_FROM_USR_SEND) {
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NODELAY)) {
nagle_on = 0;
} else {
nagle_on = 1;
}
+ } else {
+ nagle_on = 0;
}
SCTP_TCB_LOCK_ASSERT(stcb);
@@ -9945,8 +9967,7 @@ sctp_chunk_output(struct sctp_inpcb *inp,
#endif
/* Check for bad destinations, if they exist move chunks around. */
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
- if ((net->dest_state & SCTP_ADDR_NOT_REACHABLE) ==
- SCTP_ADDR_NOT_REACHABLE) {
+ if (!(net->dest_state & SCTP_ADDR_REACHABLE)) {
/*-
* if possible move things off of this address we
* still may send below due to the dormant state but
@@ -9956,16 +9977,6 @@ sctp_chunk_output(struct sctp_inpcb *inp,
*/
if (net->ref_count > 1)
sctp_move_chunks_from_net(stcb, net);
- } else if ((asoc->sctp_cmt_on_off > 0) &&
- (asoc->sctp_cmt_pf > 0) &&
- ((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF)) {
- /*
- * JRS 5/14/07 - If CMT PF is on and the current
- * destination is in PF state, move all queued data
- * to an alternate desination.
- */
- if (net->ref_count > 1)
- sctp_move_chunks_from_net(stcb, net);
} else {
/*-
* if ((asoc->sat_network) || (net->addr_is_local))
@@ -10027,15 +10038,18 @@ sctp_chunk_output(struct sctp_inpcb *inp,
}
}
if (nagle_on) {
- /*-
- * When nagle is on, we look at how much is un_sent, then
- * if its smaller than an MTU and we have data in
- * flight we stop.
+ /*
+ * When the Nagle algorithm is used, look at how
+ * much is unsent, then if its smaller than an MTU
+ * and we have data in flight we stop, except if we
+ * are handling a fragmented user message.
*/
un_sent = ((stcb->asoc.total_output_queue_size - stcb->asoc.total_flight) +
(stcb->asoc.stream_queue_cnt * sizeof(struct sctp_data_chunk)));
if ((un_sent < (int)(stcb->asoc.smallest_mtu - SCTP_MIN_OVERHEAD)) &&
- (stcb->asoc.total_flight > 0)) {
+ (stcb->asoc.total_flight > 0) &&
+ ((stcb->asoc.locked_on_sending == NULL) ||
+ sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR))) {
break;
}
}
@@ -10123,10 +10137,9 @@ send_forward_tsn(struct sctp_tcb *stcb,
chk->sent = SCTP_DATAGRAM_UNSENT;
chk->snd_count = 0;
/* Do we correct its output location? */
- if (chk->whoTo != asoc->primary_destination) {
+ if (chk->whoTo) {
sctp_free_remote_addr(chk->whoTo);
- chk->whoTo = asoc->primary_destination;
- atomic_add_int(&chk->whoTo->ref_count, 1);
+ chk->whoTo = NULL;
}
goto sctp_fill_in_rest;
}
@@ -10150,8 +10163,6 @@ send_forward_tsn(struct sctp_tcb *stcb,
SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD);
chk->sent = SCTP_DATAGRAM_UNSENT;
chk->snd_count = 0;
- chk->whoTo = asoc->primary_destination;
- atomic_add_int(&chk->whoTo->ref_count, 1);
TAILQ_INSERT_TAIL(&asoc->control_send_queue, chk, sctp_next);
asoc->ctrl_queue_cnt++;
sctp_fill_in_rest:
@@ -10346,8 +10357,10 @@ sctp_send_sack(struct sctp_tcb *stcb, int so_locked
sctp_m_freem(a_chk->data);
a_chk->data = NULL;
}
- sctp_free_remote_addr(a_chk->whoTo);
- a_chk->whoTo = NULL;
+ if (a_chk->whoTo) {
+ sctp_free_remote_addr(a_chk->whoTo);
+ a_chk->whoTo = NULL;
+ }
break;
}
}
@@ -10379,13 +10392,13 @@ sctp_send_sack(struct sctp_tcb *stcb, int so_locked
a_chk->whoTo = NULL;
if ((asoc->numduptsns) ||
- (asoc->last_data_chunk_from->dest_state & SCTP_ADDR_NOT_REACHABLE)) {
+ (!(asoc->last_data_chunk_from->dest_state & SCTP_ADDR_REACHABLE))) {
/*-
* Ok, we have some duplicates or the destination for the
* sack is unreachable, lets see if we can select an
* alternate than asoc->last_data_chunk_from
*/
- if ((!(asoc->last_data_chunk_from->dest_state & SCTP_ADDR_NOT_REACHABLE)) &&
+ if ((asoc->last_data_chunk_from->dest_state & SCTP_ADDR_REACHABLE) &&
(asoc->used_alt_onsack > asoc->numnets)) {
/* We used an alt last time, don't this time */
a_chk->whoTo = NULL;
@@ -10710,6 +10723,7 @@ sctp_send_abort_tcb(struct sctp_tcb *stcb, struct mbuf *operr, int so_locked
int sz;
uint32_t auth_offset = 0;
struct sctp_auth_chunk *auth = NULL;
+ struct sctp_nets *net;
/*-
* Add an AUTH chunk, if chunk requires it and save the offset into
@@ -10750,16 +10764,19 @@ sctp_send_abort_tcb(struct sctp_tcb *stcb, struct mbuf *operr, int so_locked
/* Put AUTH chunk at the front of the chain */
SCTP_BUF_NEXT(m_end) = m_abort;
}
-
+ if (stcb->asoc.alternate) {
+ net = stcb->asoc.alternate;
+ } else {
+ net = stcb->asoc.primary_destination;
+ }
/* fill in the ABORT chunk */
abort = mtod(m_abort, struct sctp_abort_chunk *);
abort->ch.chunk_type = SCTP_ABORT_ASSOCIATION;
abort->ch.chunk_flags = 0;
abort->ch.chunk_length = htons(sizeof(*abort) + sz);
- (void)sctp_lowlevel_chunk_output(stcb->sctp_ep, stcb,
- stcb->asoc.primary_destination,
- (struct sockaddr *)&stcb->asoc.primary_destination->ro._l_addr,
+ (void)sctp_lowlevel_chunk_output(stcb->sctp_ep, stcb, net,
+ (struct sockaddr *)&net->ro._l_addr,
m_out, auth_offset, auth, stcb->asoc.authinfo.active_keyid, 1, 0, NULL, 0,
stcb->sctp_ep->sctp_lport, stcb->rport, htonl(stcb->asoc.peer_vtag),
stcb->asoc.primary_destination->port, so_locked, NULL, NULL);
@@ -11030,120 +11047,22 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh,
}
-static struct sctp_nets *
-sctp_select_hb_destination(struct sctp_tcb *stcb, struct timeval *now)
-{
- struct sctp_nets *net, *hnet;
- int ms_goneby, highest_ms, state_overide = 0;
-
- (void)SCTP_GETTIME_TIMEVAL(now);
- highest_ms = 0;
- hnet = NULL;
- SCTP_TCB_LOCK_ASSERT(stcb);
- TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
- if (
- ((net->dest_state & SCTP_ADDR_NOHB) && ((net->dest_state & SCTP_ADDR_UNCONFIRMED) == 0)) ||
- (net->dest_state & SCTP_ADDR_OUT_OF_SCOPE)
- ) {
- /*
- * Skip this guy from consideration if HB is off AND
- * its confirmed
- */
- continue;
- }
- if (sctp_destination_is_reachable(stcb, (struct sockaddr *)&net->ro._l_addr) == 0) {
- /* skip this dest net from consideration */
- continue;
- }
- if (net->last_sent_time.tv_sec) {
- /* Sent to so we subtract */
- ms_goneby = (now->tv_sec - net->last_sent_time.tv_sec) * 1000;
- } else
- /* Never been sent to */
- ms_goneby = 0x7fffffff;
- /*-
- * When the address state is unconfirmed but still
- * considered reachable, we HB at a higher rate. Once it
- * goes confirmed OR reaches the "unreachable" state, thenw
- * we cut it back to HB at a more normal pace.
- */
- if ((net->dest_state & (SCTP_ADDR_UNCONFIRMED | SCTP_ADDR_NOT_REACHABLE)) == SCTP_ADDR_UNCONFIRMED) {
- state_overide = 1;
- } else {
- state_overide = 0;
- }
-
- if ((((unsigned int)ms_goneby >= net->RTO) || (state_overide)) &&
- (ms_goneby > highest_ms)) {
- highest_ms = ms_goneby;
- hnet = net;
- }
- }
- if (hnet &&
- ((hnet->dest_state & (SCTP_ADDR_UNCONFIRMED | SCTP_ADDR_NOT_REACHABLE)) == SCTP_ADDR_UNCONFIRMED)) {
- state_overide = 1;
- } else {
- state_overide = 0;
- }
-
- if (hnet && highest_ms && (((unsigned int)highest_ms >= hnet->RTO) || state_overide)) {
- /*-
- * Found the one with longest delay bounds OR it is
- * unconfirmed and still not marked unreachable.
- */
- SCTPDBG(SCTP_DEBUG_OUTPUT4, "net:%p is the hb winner -", hnet);
-#ifdef SCTP_DEBUG
- if (hnet) {
- SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT4,
- (struct sockaddr *)&hnet->ro._l_addr);
- } else {
- SCTPDBG(SCTP_DEBUG_OUTPUT4, " none\n");
- }
-#endif
- /* update the timer now */
- hnet->last_sent_time = *now;
- return (hnet);
- }
- /* Nothing to HB */
- return (NULL);
-}
-
-int
-sctp_send_hb(struct sctp_tcb *stcb, int user_req, struct sctp_nets *u_net, int so_locked
+void
+sctp_send_hb(struct sctp_tcb *stcb, struct sctp_nets *net, int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
)
{
struct sctp_tmit_chunk *chk;
- struct sctp_nets *net;
struct sctp_heartbeat_chunk *hb;
struct timeval now;
SCTP_TCB_LOCK_ASSERT(stcb);
- if (user_req == 0) {
- net = sctp_select_hb_destination(stcb, &now);
- if (net == NULL) {
- /*-
- * All our busy none to send to, just start the
- * timer again.
- */
- if (stcb->asoc.state == 0) {
- return (0);
- }
- sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT,
- stcb->sctp_ep,
- stcb,
- net);
- return (0);
- }
- } else {
- net = u_net;
- if (net == NULL) {
- return (0);
- }
- (void)SCTP_GETTIME_TIMEVAL(&now);
+ if (net == NULL) {
+ return;
}
+ (void)SCTP_GETTIME_TIMEVAL(&now);
switch (net->ro._l_addr.sa.sa_family) {
#ifdef INET
case AF_INET:
@@ -11154,12 +11073,12 @@ sctp_send_hb(struct sctp_tcb *stcb, int user_req, struct sctp_nets *u_net, int s
break;
#endif
default:
- return (0);
+ return;
}
sctp_alloc_a_chunk(stcb, chk);
if (chk == NULL) {
SCTPDBG(SCTP_DEBUG_OUTPUT4, "Gak, can't get a chunk for hb\n");
- return (0);
+ return;
}
chk->copy_by_ref = 0;
chk->rec.chunk_id.id = SCTP_HEARTBEAT_REQUEST;
@@ -11170,7 +11089,7 @@ sctp_send_hb(struct sctp_tcb *stcb, int user_req, struct sctp_nets *u_net, int s
chk->data = sctp_get_mbuf_for_msg(chk->send_size, 0, M_DONTWAIT, 1, MT_HEADER);
if (chk->data == NULL) {
sctp_free_a_chunk(stcb, chk, so_locked);
- return (0);
+ return;
}
SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD);
SCTP_BUF_LEN(chk->data) = chk->send_size;
@@ -11191,7 +11110,6 @@ sctp_send_hb(struct sctp_tcb *stcb, int user_req, struct sctp_nets *u_net, int s
hb->heartbeat.hb_info.time_value_1 = now.tv_sec;
hb->heartbeat.hb_info.time_value_2 = now.tv_usec;
/* Did our user request this one, put it in */
- hb->heartbeat.hb_info.user_req = user_req;
hb->heartbeat.hb_info.addr_family = net->ro._l_addr.sa.sa_family;
hb->heartbeat.hb_info.addr_len = net->ro._l_addr.sa.sa_len;
if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
@@ -11221,57 +11139,14 @@ sctp_send_hb(struct sctp_tcb *stcb, int user_req, struct sctp_nets *u_net, int s
break;
#endif
default:
- return (0);
+ return;
break;
}
-
- /*
- * JRS 5/14/07 - In CMT PF, the T3 timer is used to track
- * PF-heartbeats. Because of this, threshold management is done by
- * the t3 timer handler, and does not need to be done upon the send
- * of a PF-heartbeat. If CMT PF is on and the destination to which a
- * heartbeat is being sent is in PF state, do NOT do threshold
- * management.
- */
- if ((stcb->asoc.sctp_cmt_pf == 0) ||
- ((net->dest_state & SCTP_ADDR_PF) != SCTP_ADDR_PF)) {
- /* ok we have a destination that needs a beat */
- /* lets do the theshold management Qiaobing style */
- if (sctp_threshold_management(stcb->sctp_ep, stcb, net,
- stcb->asoc.max_send_times)) {
- /*-
- * we have lost the association, in a way this is
- * quite bad since we really are one less time since
- * we really did not send yet. This is the down side
- * to the Q's style as defined in the RFC and not my
- * alternate style defined in the RFC.
- */
- if (chk->data != NULL) {
- sctp_m_freem(chk->data);
- chk->data = NULL;
- }
- /*
- * Here we do NOT use the macro since the
- * association is now gone.
- */
- if (chk->whoTo) {
- sctp_free_remote_addr(chk->whoTo);
- chk->whoTo = NULL;
- }
- sctp_free_a_chunk((struct sctp_tcb *)NULL, chk, so_locked);
- return (-1);
- }
- }
net->hb_responded = 0;
TAILQ_INSERT_TAIL(&stcb->asoc.control_send_queue, chk, sctp_next);
stcb->asoc.ctrl_queue_cnt++;
SCTP_STAT_INCR(sctps_sendheartbeat);
- /*-
- * Call directly med level routine to put out the chunk. It will
- * always tumble out control chunks aka HB but it may even tumble
- * out data too.
- */
- return (1);
+ return;
}
void
@@ -11282,6 +11157,9 @@ sctp_send_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *net,
struct sctp_ecne_chunk *ecne;
struct sctp_tmit_chunk *chk;
+ if (net == NULL) {
+ return;
+ }
asoc = &stcb->asoc;
SCTP_TCB_LOCK_ASSERT(stcb);
TAILQ_FOREACH(chk, &asoc->control_send_queue, sctp_next) {
@@ -11323,6 +11201,7 @@ sctp_send_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *net,
chk->snd_count = 0;
chk->whoTo = net;
atomic_add_int(&chk->whoTo->ref_count, 1);
+
stcb->asoc.ecn_echo_cnt_onq++;
ecne = mtod(chk->data, struct sctp_ecne_chunk *);
ecne->ch.chunk_type = SCTP_ECN_ECHO;
@@ -11477,10 +11356,10 @@ jump_out:
if (net) {
/* we should hit here */
chk->whoTo = net;
+ atomic_add_int(&chk->whoTo->ref_count, 1);
} else {
- chk->whoTo = asoc->primary_destination;
+ chk->whoTo = NULL;
}
- atomic_add_int(&chk->whoTo->ref_count, 1);
chk->rec.chunk_id.id = SCTP_PACKET_DROPPED;
chk->rec.chunk_id.can_take_data = 1;
drp->ch.chunk_type = SCTP_PACKET_DROPPED;
@@ -11518,8 +11397,9 @@ sctp_send_cwr(struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t high_tsn, u
asoc = &stcb->asoc;
SCTP_TCB_LOCK_ASSERT(stcb);
-
-
+ if (net == NULL) {
+ return;
+ }
TAILQ_FOREACH(chk, &asoc->control_send_queue, sctp_next) {
if ((chk->rec.chunk_id.id == SCTP_ECN_CWR) && (net == chk->whoTo)) {
/*
@@ -11849,9 +11729,12 @@ sctp_send_str_reset_req(struct sctp_tcb *stcb,
/* setup chunk parameters */
chk->sent = SCTP_DATAGRAM_UNSENT;
chk->snd_count = 0;
- chk->whoTo = asoc->primary_destination;
+ if (stcb->asoc.alternate) {
+ chk->whoTo = stcb->asoc.alternate;
+ } else {
+ chk->whoTo = stcb->asoc.primary_destination;
+ }
atomic_add_int(&chk->whoTo->ref_count, 1);
-
ch = mtod(chk->data, struct sctp_chunkhdr *);
ch->chunk_type = SCTP_STREAM_RESET;
ch->chunk_flags = 0;
@@ -12745,14 +12628,10 @@ sctp_lower_sosend(struct socket *so,
(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
SCTP_INP_RLOCK(inp);
stcb = LIST_FIRST(&inp->sctp_asoc_list);
- if (stcb == NULL) {
- SCTP_INP_RUNLOCK(inp);
- SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOTCONN);
- error = ENOTCONN;
- goto out_unlocked;
+ if (stcb) {
+ SCTP_TCB_LOCK(stcb);
+ hold_tcblock = 1;
}
- SCTP_TCB_LOCK(stcb);
- hold_tcblock = 1;
SCTP_INP_RUNLOCK(inp);
} else if (sinfo_assoc_id) {
stcb = sctp_findassociation_ep_asocid(inp, sinfo_assoc_id, 0);
@@ -12817,21 +12696,12 @@ sctp_lower_sosend(struct socket *so,
}
}
if (stcb == NULL) {
- if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
- (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
- SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOTCONN);
- error = ENOTCONN;
- goto out_unlocked;
- }
if (addr == NULL) {
SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOENT);
error = ENOENT;
goto out_unlocked;
} else {
- /*
- * UDP style, we must go ahead and start the INIT
- * process
- */
+ /* We must go ahead and start the INIT process */
uint32_t vrf_id;
if ((sinfo_flags & SCTP_ABORT) ||
@@ -12858,6 +12728,14 @@ sctp_lower_sosend(struct socket *so,
/* Error is setup for us in the call */
goto out_unlocked;
}
+ if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
+ stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
+ /*
+ * Set the connected flag so we can queue
+ * data
+ */
+ soisconnecting(so);
+ }
hold_tcblock = 1;
if (create_lock_applied) {
SCTP_ASOC_CREATE_UNLOCK(inp);
@@ -12910,7 +12788,11 @@ sctp_lower_sosend(struct socket *so,
goto out_unlocked;
}
} else {
- net = stcb->asoc.primary_destination;
+ if (stcb->asoc.alternate) {
+ net = stcb->asoc.alternate;
+ } else {
+ net = stcb->asoc.primary_destination;
+ }
}
atomic_add_int(&stcb->total_sends, 1);
/* Keep the stcb from being freed under our feet */
@@ -13579,15 +13461,22 @@ dataless_eof:
if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) &&
(SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_RECEIVED) &&
(SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
+ struct sctp_nets *netp;
+
+ if (stcb->asoc.alternate) {
+ netp = stcb->asoc.alternate;
+ } else {
+ netp = stcb->asoc.primary_destination;
+ }
/* only send SHUTDOWN the first time through */
- sctp_send_shutdown(stcb, stcb->asoc.primary_destination);
+ sctp_send_shutdown(stcb, netp);
if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb,
- asoc->primary_destination);
+ netp);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
asoc->primary_destination);
}
diff --git a/sys/netinet/sctp_output.h b/sys/netinet/sctp_output.h
index 5cbadf34909d8..68a08c11c9591 100644
--- a/sys/netinet/sctp_output.h
+++ b/sys/netinet/sctp_output.h
@@ -155,7 +155,7 @@ void send_forward_tsn(struct sctp_tcb *, struct sctp_association *);
void sctp_send_sack(struct sctp_tcb *, int);
-int sctp_send_hb(struct sctp_tcb *, int, struct sctp_nets *, int);
+void sctp_send_hb(struct sctp_tcb *, struct sctp_nets *, int);
void sctp_send_ecn_echo(struct sctp_tcb *, struct sctp_nets *, uint32_t);
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index 70593655fdc69..b0f2880754453 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -49,6 +49,9 @@ __FBSDID("$FreeBSD$");
#include <netinet/sctp_bsd_addr.h>
#include <netinet/sctp_dtrace_define.h>
#include <netinet/udp.h>
+#ifdef INET6
+#include <netinet6/ip6_var.h>
+#endif
#include <sys/sched.h>
#include <sys/smp.h>
#include <sys/unistd.h>
@@ -1096,8 +1099,15 @@ sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to)
continue;
}
LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
- if (sctp_is_addr_restricted(stcb, sctp_ifa))
+ if (sctp_is_addr_restricted(stcb, sctp_ifa) &&
+ (!sctp_is_addr_pending(stcb, sctp_ifa))) {
+ /*
+ * We allow pending addresses, where
+ * we have sent an asconf-add to be
+ * considered valid.
+ */
continue;
+ }
switch (sctp_ifa->address.sa.sa_family) {
#ifdef INET
case AF_INET:
@@ -1155,7 +1165,13 @@ sctp_does_stcb_own_this_addr(struct sctp_tcb *stcb, struct sockaddr *to)
struct sctp_laddr *laddr;
LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
- if (sctp_is_addr_restricted(stcb, laddr->ifa)) {
+ if (sctp_is_addr_restricted(stcb, laddr->ifa) &&
+ (!sctp_is_addr_pending(stcb, laddr->ifa))) {
+ /*
+ * We allow pending addresses, where we have
+ * sent an asconf-add to be considered
+ * valid.
+ */
continue;
}
if (laddr->ifa->address.sa.sa_family != to->sa_family) {
@@ -2490,6 +2506,11 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
/* setup socket pointers */
inp->sctp_socket = so;
inp->ip_inp.inp.inp_socket = so;
+#ifdef INET6
+ if (MODULE_GLOBAL(ip6_auto_flowlabel)) {
+ inp->ip_inp.inp.inp_flags |= IN6P_AUTOFLOWLABEL;
+ }
+#endif
inp->sctp_associd_counter = 1;
inp->partial_delivery_point = SCTP_SB_LIMIT_RCV(so) >> SCTP_PARTIAL_DELIVERY_SHIFT;
inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
@@ -2614,6 +2635,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
m->max_init_times = SCTP_BASE_SYSCTL(sctp_init_rtx_max_default);
m->max_send_times = SCTP_BASE_SYSCTL(sctp_assoc_rtx_max_default);
m->def_net_failure = SCTP_BASE_SYSCTL(sctp_path_rtx_max_default);
+ m->def_net_pf_threshold = SCTP_BASE_SYSCTL(sctp_path_pf_threshold);
m->sctp_sws_sender = SCTP_SWS_SENDER_DEF;
m->sctp_sws_receiver = SCTP_SWS_RECEIVER_DEF;
m->max_burst = SCTP_BASE_SYSCTL(sctp_max_burst_default);
@@ -2654,6 +2676,10 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
*/
m->local_hmacs = sctp_default_supported_hmaclist();
m->local_auth_chunks = sctp_alloc_chunklist();
+ m->default_dscp = 0;
+#ifdef INET6
+ m->default_flowlabel = 0;
+#endif
sctp_auth_set_default_chunks(m->local_auth_chunks);
LIST_INIT(&m->shared_keys);
/* add default NULL key as key id 0 */
@@ -2768,7 +2794,6 @@ sctp_move_pcb_and_assoc(struct sctp_inpcb *old_inp, struct sctp_inpcb *new_inp,
* all of them.
*/
- stcb->asoc.hb_timer.ep = (void *)new_inp;
stcb->asoc.dack_timer.ep = (void *)new_inp;
stcb->asoc.asconf_timer.ep = (void *)new_inp;
stcb->asoc.strreset_timer.ep = (void *)new_inp;
@@ -2780,7 +2805,6 @@ sctp_move_pcb_and_assoc(struct sctp_inpcb *old_inp, struct sctp_inpcb *new_inp,
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
net->pmtu_timer.ep = (void *)new_inp;
net->rxt_timer.ep = (void *)new_inp;
- net->fr_timer.ep = (void *)new_inp;
}
SCTP_INP_WUNLOCK(new_inp);
SCTP_INP_WUNLOCK(old_inp);
@@ -3452,11 +3476,18 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
}
if ((SCTP_GET_STATE(&asoc->asoc) != SCTP_STATE_SHUTDOWN_SENT) &&
(SCTP_GET_STATE(&asoc->asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
+ struct sctp_nets *netp;
+
+ if (asoc->asoc.alternate) {
+ netp = asoc->asoc.alternate;
+ } else {
+ netp = asoc->asoc.primary_destination;
+ }
/*
* there is nothing queued to send,
* so I send shutdown
*/
- sctp_send_shutdown(asoc, asoc->asoc.primary_destination);
+ sctp_send_shutdown(asoc, netp);
if ((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_OPEN) ||
(SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
@@ -3464,7 +3495,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
SCTP_SET_STATE(&asoc->asoc, SCTP_STATE_SHUTDOWN_SENT);
SCTP_CLEAR_SUBSTATE(&asoc->asoc, SCTP_STATE_SHUTDOWN_PENDING);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN, asoc->sctp_ep, asoc,
- asoc->asoc.primary_destination);
+ netp);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, asoc->sctp_ep, asoc,
asoc->asoc.primary_destination);
sctp_chunk_output(inp, asoc, SCTP_OUTPUT_FROM_SHUT_TMR, SCTP_SO_LOCKED);
@@ -3808,7 +3839,7 @@ sctp_is_address_on_local_host(struct sockaddr *addr, uint32_t vrf_id)
*/
int
sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
- int set_scope, int from)
+ struct sctp_nets **netp, int set_scope, int from)
{
/*
* The following is redundant to the same lines in the
@@ -3942,7 +3973,7 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
return (-1);
}
SCTP_INCR_RADDR_COUNT();
- bzero(net, sizeof(*net));
+ bzero(net, sizeof(struct sctp_nets));
(void)SCTP_GETTIME_TIMEVAL(&net->start_time);
memcpy(&net->ro._l_addr, newaddr, newaddr->sa_len);
switch (newaddr->sa_family) {
@@ -3968,6 +3999,7 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
addr_inscope = 1;
}
net->failure_threshold = stcb->asoc.def_net_failure;
+ net->pf_threshold = stcb->asoc.def_net_pf_threshold;
if (addr_inscope == 0) {
net->dest_state = (SCTP_ADDR_REACHABLE |
SCTP_ADDR_OUT_OF_SCOPE);
@@ -3989,24 +4021,25 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
stcb->asoc.numnets++;
*(&net->ref_count) = 1;
net->cwr_window_tsn = net->last_cwr_tsn = stcb->asoc.sending_seq - 1;
- net->tos_flowlabel = 0;
if (SCTP_BASE_SYSCTL(sctp_udp_tunneling_for_client_enable)) {
net->port = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
} else {
net->port = 0;
}
-#ifdef INET
- if (newaddr->sa_family == AF_INET)
- net->tos_flowlabel = stcb->asoc.default_tos;
-#endif
+ net->dscp = stcb->asoc.default_dscp;
#ifdef INET6
- if (newaddr->sa_family == AF_INET6)
- net->tos_flowlabel = stcb->asoc.default_flowlabel;
+ net->flowlabel = stcb->asoc.default_flowlabel;
#endif
+ if (sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
+ net->dest_state |= SCTP_ADDR_NOHB;
+ } else {
+ net->dest_state &= ~SCTP_ADDR_NOHB;
+ }
+ net->heart_beat_delay = stcb->asoc.heart_beat_delay;
/* Init the timer structure */
SCTP_OS_TIMER_INIT(&net->rxt_timer.timer);
- SCTP_OS_TIMER_INIT(&net->fr_timer.timer);
SCTP_OS_TIMER_INIT(&net->pmtu_timer.timer);
+ SCTP_OS_TIMER_INIT(&net->hb_timer.timer);
/* Now generate a route for this guy */
#ifdef INET6
@@ -4153,8 +4186,6 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
/* No route to current primary adopt new primary */
stcb->asoc.primary_destination = net;
}
- sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, stcb->sctp_ep, stcb,
- net);
/* Validate primary is first */
net = TAILQ_FIRST(&stcb->asoc.nets);
if ((net != stcb->asoc.primary_destination) &&
@@ -4169,6 +4200,9 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
TAILQ_INSERT_HEAD(&stcb->asoc.nets,
stcb->asoc.primary_destination, sctp_next);
}
+ if (netp) {
+ *netp = net;
+ }
return (0);
}
@@ -4257,6 +4291,16 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
*error = EINVAL;
return (NULL);
}
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE)) {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_WAS_ABORTED)) {
+ SCTP_INP_RUNLOCK(inp);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
+ *error = EINVAL;
+ return (NULL);
+ }
+ }
SCTPDBG(SCTP_DEBUG_PCB3, "Allocate an association for peer:");
#ifdef SCTP_DEBUG
if (firstaddr) {
@@ -4288,7 +4332,10 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
struct sockaddr_in *sin;
sin = (struct sockaddr_in *)firstaddr;
- if ((sin->sin_port == 0) || (sin->sin_addr.s_addr == 0)) {
+ if ((ntohs(sin->sin_port) == 0) ||
+ (sin->sin_addr.s_addr == INADDR_ANY) ||
+ (sin->sin_addr.s_addr == INADDR_BROADCAST) ||
+ IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
/* Invalid address */
SCTP_INP_RUNLOCK(inp);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
@@ -4305,8 +4352,9 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
struct sockaddr_in6 *sin6;
sin6 = (struct sockaddr_in6 *)firstaddr;
- if ((sin6->sin6_port == 0) ||
- (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))) {
+ if ((ntohs(sin6->sin6_port) == 0) ||
+ IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
+ IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
/* Invalid address */
SCTP_INP_RUNLOCK(inp);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_PCB, EINVAL);
@@ -4393,7 +4441,7 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
LIST_INSERT_HEAD(head, stcb, sctp_asocs);
SCTP_INP_INFO_WUNLOCK();
- if ((err = sctp_add_remote_addr(stcb, firstaddr, SCTP_DO_SETSCOPE, SCTP_ALLOC_ASOC))) {
+ if ((err = sctp_add_remote_addr(stcb, firstaddr, NULL, SCTP_DO_SETSCOPE, SCTP_ALLOC_ASOC))) {
/* failure.. memory error? */
if (asoc->strmout) {
SCTP_FREE(asoc->strmout, SCTP_M_STRMO);
@@ -4418,7 +4466,6 @@ sctp_aloc_assoc(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
return (NULL);
}
/* Init all the timers */
- SCTP_OS_TIMER_INIT(&asoc->hb_timer.timer);
SCTP_OS_TIMER_INIT(&asoc->dack_timer.timer);
SCTP_OS_TIMER_INIT(&asoc->strreset_timer.timer);
SCTP_OS_TIMER_INIT(&asoc->asconf_timer.timer);
@@ -4488,6 +4535,10 @@ out:
/* Clear net */
asoc->last_control_chunk_from = NULL;
}
+ if (net == stcb->asoc.alternate) {
+ sctp_free_remote_addr(stcb->asoc.alternate);
+ stcb->asoc.alternate = NULL;
+ }
sctp_free_remote_addr(net);
}
@@ -4699,6 +4750,10 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
/* there is no asoc, really TSNH :-0 */
return (1);
}
+ if (stcb->asoc.alternate) {
+ sctp_free_remote_addr(stcb->asoc.alternate);
+ stcb->asoc.alternate = NULL;
+ }
/* TEMP CODE */
if (stcb->freed_from_where == 0) {
/* Only record the first place free happened from */
@@ -4737,8 +4792,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
}
}
/* now clean up any other timers */
- (void)SCTP_OS_TIMER_STOP(&asoc->hb_timer.timer);
- asoc->hb_timer.self = NULL;
(void)SCTP_OS_TIMER_STOP(&asoc->dack_timer.timer);
asoc->dack_timer.self = NULL;
(void)SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer);
@@ -4762,12 +4815,12 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
(void)SCTP_OS_TIMER_STOP(&asoc->delete_prim_timer.timer);
asoc->delete_prim_timer.self = NULL;
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
- (void)SCTP_OS_TIMER_STOP(&net->fr_timer.timer);
- net->fr_timer.self = NULL;
(void)SCTP_OS_TIMER_STOP(&net->rxt_timer.timer);
net->rxt_timer.self = NULL;
(void)SCTP_OS_TIMER_STOP(&net->pmtu_timer.timer);
net->pmtu_timer.self = NULL;
+ (void)SCTP_OS_TIMER_STOP(&net->hb_timer.timer);
+ net->hb_timer.self = NULL;
}
/* Now the read queue needs to be cleaned up (only once) */
if ((stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) == 0) {
@@ -4935,7 +4988,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
* Now restop the timers to be sure this is paranoia at is finest!
*/
(void)SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer);
- (void)SCTP_OS_TIMER_STOP(&asoc->hb_timer.timer);
(void)SCTP_OS_TIMER_STOP(&asoc->dack_timer.timer);
(void)SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer);
(void)SCTP_OS_TIMER_STOP(&asoc->asconf_timer.timer);
@@ -4943,9 +4995,9 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
(void)SCTP_OS_TIMER_STOP(&asoc->autoclose_timer.timer);
(void)SCTP_OS_TIMER_STOP(&asoc->delayed_event_timer.timer);
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
- (void)SCTP_OS_TIMER_STOP(&net->fr_timer.timer);
(void)SCTP_OS_TIMER_STOP(&net->rxt_timer.timer);
(void)SCTP_OS_TIMER_STOP(&net->pmtu_timer.timer);
+ (void)SCTP_OS_TIMER_STOP(&net->hb_timer.timer);
}
asoc->strreset_timer.type = SCTP_TIMER_TYPE_NONE;
@@ -6189,7 +6241,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
#ifdef INET
case AF_INET:
if (stcb->asoc.ipv4_addr_legal) {
- if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_2)) {
+ if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_2)) {
return (-1);
}
}
@@ -6198,7 +6250,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
#ifdef INET6
case AF_INET6:
if (stcb->asoc.ipv6_addr_legal) {
- if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_3)) {
+ if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_3)) {
return (-2);
}
}
@@ -6289,7 +6341,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
/* the assoc was freed? */
return (-7);
}
- if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_4)) {
+ if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_4)) {
return (-8);
}
} else if (stcb_tmp == stcb) {
@@ -6376,7 +6428,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
* we must add the address, no scope
* set
*/
- if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_5)) {
+ if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_LOAD_ADDR_5)) {
return (-17);
}
} else if (stcb_tmp == stcb) {
@@ -6748,7 +6800,10 @@ sctp_set_primary_addr(struct sctp_tcb *stcb, struct sockaddr *sa,
return (0);
}
stcb->asoc.primary_destination = net;
- net->dest_state &= ~SCTP_ADDR_WAS_PRIMARY;
+ if (!(net->dest_state & SCTP_ADDR_PF) && (stcb->asoc.alternate)) {
+ sctp_free_remote_addr(stcb->asoc.alternate);
+ stcb->asoc.alternate = NULL;
+ }
net = TAILQ_FIRST(&stcb->asoc.nets);
if (net != stcb->asoc.primary_destination) {
/*
diff --git a/sys/netinet/sctp_pcb.h b/sys/netinet/sctp_pcb.h
index 783968191af84..e39055ca075f3 100644
--- a/sys/netinet/sctp_pcb.h
+++ b/sys/netinet/sctp_pcb.h
@@ -293,6 +293,8 @@ struct sctp_pcb {
uint16_t def_net_failure;
+ uint16_t def_net_pf_threshold;
+
/* number of streams to pre-open on a association */
uint16_t pre_open_stream_count;
uint16_t max_open_streams_intome;
@@ -320,6 +322,10 @@ struct sctp_pcb {
uint32_t store_at;
uint32_t max_burst;
uint32_t fr_max_burst;
+#ifdef INET6
+ uint32_t default_flowlabel;
+#endif
+ uint8_t default_dscp;
char current_secret_number;
char last_secret_number;
};
@@ -582,7 +588,7 @@ void sctp_remove_laddr(struct sctp_laddr *);
void sctp_del_local_addr_ep(struct sctp_inpcb *, struct sctp_ifa *);
-int sctp_add_remote_addr(struct sctp_tcb *, struct sockaddr *, int, int);
+int sctp_add_remote_addr(struct sctp_tcb *, struct sockaddr *, struct sctp_nets **, int, int);
void sctp_remove_net(struct sctp_tcb *, struct sctp_nets *);
diff --git a/sys/netinet/sctp_structs.h b/sys/netinet/sctp_structs.h
index 0f9bcaf5268ba..c7dee69565780 100644
--- a/sys/netinet/sctp_structs.h
+++ b/sys/netinet/sctp_structs.h
@@ -251,6 +251,7 @@ struct sctp_nets {
* structure shared by all.
*/
struct sctp_timer pmtu_timer;
+ struct sctp_timer hb_timer;
/*
* The following two in combination equate to a route entry for v6
@@ -273,7 +274,6 @@ struct sctp_nets {
/* This is used for SHUTDOWN/SHUTDOWN-ACK/SEND or INIT timers */
struct sctp_timer rxt_timer;
- struct sctp_timer fr_timer; /* for early fr */
/* last time in seconds I sent to it */
struct timeval last_sent_time;
@@ -321,18 +321,24 @@ struct sctp_nets {
uint32_t fast_recovery_tsn;
uint32_t heartbeat_random1;
uint32_t heartbeat_random2;
- uint32_t tos_flowlabel;
+#ifdef INET6
+ uint32_t flowlabel;
+#endif
+ uint8_t dscp;
struct timeval start_time; /* time when this net was created */
uint32_t marked_retrans;/* number or DATA chunks marked for timer
* based retransmissions */
uint32_t marked_fastretrans;
+ uint32_t heart_beat_delay; /* Heart Beat delay in ms */
/* if this guy is ok or not ... status */
uint16_t dest_state;
- /* number of transmit failures to down this guy */
+ /* number of timeouts to consider the destination unreachable */
uint16_t failure_threshold;
- /* error stats on destination */
+ /* number of timeouts to consider the destination potentially failed */
+ uint16_t pf_threshold;
+ /* error stats on the destination */
uint16_t error_count;
/* UDP port number in case of UDP tunneling */
uint16_t port;
@@ -661,6 +667,7 @@ struct sctp_cc_functions {
void (*sctp_cwnd_update_after_sack) (struct sctp_tcb *stcb,
struct sctp_association *asoc,
int accum_moved, int reneged_all, int will_exit);
+ void (*sctp_cwnd_update_exit_pf) (struct sctp_tcb *stcb, struct sctp_nets *net);
void (*sctp_cwnd_update_after_fr) (struct sctp_tcb *stcb,
struct sctp_association *asoc);
void (*sctp_cwnd_update_after_timeout) (struct sctp_tcb *stcb,
@@ -672,8 +679,6 @@ struct sctp_cc_functions {
uint32_t * bottle_bw, uint32_t * on_queue);
void (*sctp_cwnd_update_after_output) (struct sctp_tcb *stcb,
struct sctp_nets *net, int burst_limit);
- void (*sctp_cwnd_update_after_fr_timer) (struct sctp_inpcb *inp,
- struct sctp_tcb *stcb, struct sctp_nets *net);
void (*sctp_cwnd_update_packet_transmitted) (struct sctp_tcb *stcb,
struct sctp_nets *net);
void (*sctp_cwnd_update_tsn_acknowledged) (struct sctp_nets *net,
@@ -753,7 +758,6 @@ struct sctp_association {
struct sctp_nonpad_sndrcvinfo def_send;
/* timers and such */
- struct sctp_timer hb_timer; /* hb timer */
struct sctp_timer dack_timer; /* Delayed ack timer */
struct sctp_timer asconf_timer; /* asconf */
struct sctp_timer strreset_timer; /* stream reset */
@@ -828,6 +832,7 @@ struct sctp_association {
uint8_t *mapping_array;
/* primary destination to use */
struct sctp_nets *primary_destination;
+ struct sctp_nets *alternate; /* If primary is down or PF */
/* For CMT */
struct sctp_nets *last_net_cmt_send_started;
/* last place I got a data chunk from */
@@ -984,7 +989,9 @@ struct sctp_association {
uint32_t sb_send_resv; /* amount reserved on a send */
uint32_t my_rwnd_control_len; /* shadow of sb_mbcnt used for rwnd
* control */
+#ifdef INET6
uint32_t default_flowlabel;
+#endif
uint32_t pr_sctp_cnt;
int ctrl_queue_cnt; /* could be removed REM - NO IT CAN'T!! RRS */
/*
@@ -1023,8 +1030,8 @@ struct sctp_association {
unsigned int size_on_all_streams;
unsigned int cnt_on_all_streams;
- /* Heart Beat delay in ticks */
- unsigned int heart_beat_delay;
+ /* Heart Beat delay in ms */
+ uint32_t heart_beat_delay;
/* autoclose */
unsigned int sctp_autoclose_ticks;
@@ -1094,6 +1101,8 @@ struct sctp_association {
uint16_t def_net_failure;
+ uint16_t def_net_pf_threshold;
+
/*
* lock flag: 0 is ok to send, 1+ (duals as a retran count) is
* awaiting ACK
@@ -1133,8 +1142,7 @@ struct sctp_association {
uint8_t last_flags_delivered;
uint8_t hb_ect_randombit;
uint8_t hb_random_idx;
- uint8_t hb_is_disabled; /* is the hb disabled? */
- uint8_t default_tos;
+ uint8_t default_dscp;
uint8_t asconf_del_pending; /* asconf delete last addr pending */
/*
diff --git a/sys/netinet/sctp_sysctl.c b/sys/netinet/sctp_sysctl.c
index bb7b6e265d22f..25d75f88e084d 100644
--- a/sys/netinet/sctp_sysctl.c
+++ b/sys/netinet/sctp_sysctl.c
@@ -83,16 +83,14 @@ sctp_init_sysctls()
SCTP_BASE_SYSCTL(sctp_init_rtx_max_default) = SCTPCTL_INIT_RTX_MAX_DEFAULT;
SCTP_BASE_SYSCTL(sctp_assoc_rtx_max_default) = SCTPCTL_ASSOC_RTX_MAX_DEFAULT;
SCTP_BASE_SYSCTL(sctp_path_rtx_max_default) = SCTPCTL_PATH_RTX_MAX_DEFAULT;
+ SCTP_BASE_SYSCTL(sctp_path_pf_threshold) = SCTPCTL_PATH_PF_THRESHOLD_DEFAULT;
SCTP_BASE_SYSCTL(sctp_add_more_threshold) = SCTPCTL_ADD_MORE_ON_OUTPUT_DEFAULT;
SCTP_BASE_SYSCTL(sctp_nr_outgoing_streams_default) = SCTPCTL_OUTGOING_STREAMS_DEFAULT;
SCTP_BASE_SYSCTL(sctp_cmt_on_off) = SCTPCTL_CMT_ON_OFF_DEFAULT;
/* EY */
SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) = SCTPCTL_NR_SACK_ON_OFF_DEFAULT;
SCTP_BASE_SYSCTL(sctp_cmt_use_dac) = SCTPCTL_CMT_USE_DAC_DEFAULT;
- SCTP_BASE_SYSCTL(sctp_cmt_pf) = SCTPCTL_CMT_PF_DEFAULT;
SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst) = SCTPCTL_CWND_MAXBURST_DEFAULT;
- SCTP_BASE_SYSCTL(sctp_early_fr) = SCTPCTL_EARLY_FAST_RETRAN_DEFAULT;
- SCTP_BASE_SYSCTL(sctp_early_fr_msec) = SCTPCTL_EARLY_FAST_RETRAN_MSEC_DEFAULT;
SCTP_BASE_SYSCTL(sctp_asconf_auth_nochk) = SCTPCTL_ASCONF_AUTH_NOCHK_DEFAULT;
SCTP_BASE_SYSCTL(sctp_auth_disable) = SCTPCTL_AUTH_DISABLE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_nat_friendly) = SCTPCTL_NAT_FRIENDLY_DEFAULT;
@@ -494,6 +492,7 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
xraddr.active = ((net->dest_state & SCTP_ADDR_REACHABLE) == SCTP_ADDR_REACHABLE);
xraddr.confirmed = ((net->dest_state & SCTP_ADDR_UNCONFIRMED) == 0);
xraddr.heartbeat_enabled = ((net->dest_state & SCTP_ADDR_NOHB) == 0);
+ xraddr.potentially_failed = ((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF);
xraddr.rto = net->RTO;
xraddr.max_path_rtx = net->failure_threshold;
xraddr.rtx = net->marked_retrans;
@@ -502,6 +501,7 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
xraddr.flight_size = net->flight_size;
xraddr.mtu = net->mtu;
xraddr.rtt = net->rtt / 1000;
+ xraddr.heartbeat_interval = net->heart_beat_delay;
xraddr.start_time.tv_sec = (uint32_t) net->start_time.tv_sec;
xraddr.start_time.tv_usec = (uint32_t) net->start_time.tv_usec;
SCTP_INP_RUNLOCK(inp);
@@ -633,16 +633,14 @@ sysctl_sctp_check(SYSCTL_HANDLER_ARGS)
RANGECHK(SCTP_BASE_SYSCTL(sctp_init_rtx_max_default), SCTPCTL_INIT_RTX_MAX_MIN, SCTPCTL_INIT_RTX_MAX_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_assoc_rtx_max_default), SCTPCTL_ASSOC_RTX_MAX_MIN, SCTPCTL_ASSOC_RTX_MAX_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_path_rtx_max_default), SCTPCTL_PATH_RTX_MAX_MIN, SCTPCTL_PATH_RTX_MAX_MAX);
+ RANGECHK(SCTP_BASE_SYSCTL(sctp_path_pf_threshold), SCTPCTL_PATH_PF_THRESHOLD_MIN, SCTPCTL_PATH_PF_THRESHOLD_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_add_more_threshold), SCTPCTL_ADD_MORE_ON_OUTPUT_MIN, SCTPCTL_ADD_MORE_ON_OUTPUT_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_nr_outgoing_streams_default), SCTPCTL_OUTGOING_STREAMS_MIN, SCTPCTL_OUTGOING_STREAMS_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_cmt_on_off), SCTPCTL_CMT_ON_OFF_MIN, SCTPCTL_CMT_ON_OFF_MAX);
/* EY */
RANGECHK(SCTP_BASE_SYSCTL(sctp_nr_sack_on_off), SCTPCTL_NR_SACK_ON_OFF_MIN, SCTPCTL_NR_SACK_ON_OFF_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_cmt_use_dac), SCTPCTL_CMT_USE_DAC_MIN, SCTPCTL_CMT_USE_DAC_MAX);
- RANGECHK(SCTP_BASE_SYSCTL(sctp_cmt_pf), SCTPCTL_CMT_PF_MIN, SCTPCTL_CMT_PF_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst), SCTPCTL_CWND_MAXBURST_MIN, SCTPCTL_CWND_MAXBURST_MAX);
- RANGECHK(SCTP_BASE_SYSCTL(sctp_early_fr), SCTPCTL_EARLY_FAST_RETRAN_MIN, SCTPCTL_EARLY_FAST_RETRAN_MAX);
- RANGECHK(SCTP_BASE_SYSCTL(sctp_early_fr_msec), SCTPCTL_EARLY_FAST_RETRAN_MSEC_MIN, SCTPCTL_EARLY_FAST_RETRAN_MSEC_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_asconf_auth_nochk), SCTPCTL_ASCONF_AUTH_NOCHK_MIN, SCTPCTL_ASCONF_AUTH_NOCHK_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_auth_disable), SCTPCTL_AUTH_DISABLE_MIN, SCTPCTL_AUTH_DISABLE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_nat_friendly), SCTPCTL_NAT_FRIENDLY_MIN, SCTPCTL_NAT_FRIENDLY_MAX);
@@ -793,17 +791,6 @@ sysctl_stat_get(SYSCTL_HANDLER_ARGS)
sb.sctps_timoautoclose += sarry->sctps_timoautoclose;
sb.sctps_timoassockill += sarry->sctps_timoassockill;
sb.sctps_timoinpkill += sarry->sctps_timoinpkill;
- sb.sctps_earlyfrstart += sarry->sctps_earlyfrstart;
- sb.sctps_earlyfrstop += sarry->sctps_earlyfrstop;
- sb.sctps_earlyfrmrkretrans += sarry->sctps_earlyfrmrkretrans;
- sb.sctps_earlyfrstpout += sarry->sctps_earlyfrstpout;
- sb.sctps_earlyfrstpidsck1 += sarry->sctps_earlyfrstpidsck1;
- sb.sctps_earlyfrstpidsck2 += sarry->sctps_earlyfrstpidsck2;
- sb.sctps_earlyfrstpidsck3 += sarry->sctps_earlyfrstpidsck3;
- sb.sctps_earlyfrstpidsck4 += sarry->sctps_earlyfrstpidsck4;
- sb.sctps_earlyfrstrid += sarry->sctps_earlyfrstrid;
- sb.sctps_earlyfrstrout += sarry->sctps_earlyfrstrout;
- sb.sctps_earlyfrstrtmr += sarry->sctps_earlyfrstrtmr;
sb.sctps_hdrops += sarry->sctps_hdrops;
sb.sctps_badsum += sarry->sctps_badsum;
sb.sctps_noport += sarry->sctps_noport;
@@ -994,6 +981,10 @@ SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, path_rtx_max, CTLTYPE_UINT | CTLFLAG_
&SCTP_BASE_SYSCTL(sctp_path_rtx_max_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_PATH_RTX_MAX_DESC);
+SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, path_pf_threshold, CTLTYPE_UINT | CTLFLAG_RW,
+ &SCTP_BASE_SYSCTL(sctp_path_pf_threshold), 0, sysctl_sctp_check, "IU",
+ SCTPCTL_PATH_PF_THRESHOLD_DESC);
+
SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, add_more_on_output, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_add_more_threshold), 0, sysctl_sctp_check, "IU",
SCTPCTL_ADD_MORE_ON_OUTPUT_DESC);
@@ -1014,22 +1005,10 @@ SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, cmt_use_dac, CTLTYPE_UINT | CTLFLAG_R
&SCTP_BASE_SYSCTL(sctp_cmt_use_dac), 0, sysctl_sctp_check, "IU",
SCTPCTL_CMT_USE_DAC_DESC);
-SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, cmt_pf, CTLTYPE_UINT | CTLFLAG_RW,
- &SCTP_BASE_SYSCTL(sctp_cmt_pf), 0, sysctl_sctp_check, "IU",
- SCTPCTL_CMT_PF_DESC);
-
SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, cwnd_maxburst, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_use_cwnd_based_maxburst), 0, sysctl_sctp_check, "IU",
SCTPCTL_CWND_MAXBURST_DESC);
-SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, early_fast_retran, CTLTYPE_UINT | CTLFLAG_RW,
- &SCTP_BASE_SYSCTL(sctp_early_fr), 0, sysctl_sctp_check, "IU",
- SCTPCTL_EARLY_FAST_RETRAN_DESC);
-
-SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, early_fast_retran_msec, CTLTYPE_UINT | CTLFLAG_RW,
- &SCTP_BASE_SYSCTL(sctp_early_fr_msec), 0, sysctl_sctp_check, "IU",
- SCTPCTL_EARLY_FAST_RETRAN_MSEC_DESC);
-
SYSCTL_VNET_PROC(_net_inet_sctp, OID_AUTO, asconf_auth_nochk, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_asconf_auth_nochk), 0, sysctl_sctp_check, "IU",
SCTPCTL_ASCONF_AUTH_NOCHK_DESC);
diff --git a/sys/netinet/sctp_sysctl.h b/sys/netinet/sctp_sysctl.h
index 6429d594fec8c..f62679f8e640a 100644
--- a/sys/netinet/sctp_sysctl.h
+++ b/sys/netinet/sctp_sysctl.h
@@ -74,16 +74,14 @@ struct sctp_sysctl {
uint32_t sctp_init_rtx_max_default;
uint32_t sctp_assoc_rtx_max_default;
uint32_t sctp_path_rtx_max_default;
+ uint32_t sctp_path_pf_threshold;
uint32_t sctp_add_more_threshold;
uint32_t sctp_nr_outgoing_streams_default;
uint32_t sctp_cmt_on_off;
uint32_t sctp_cmt_use_dac;
/* EY 5/5/08 - nr_sack flag variable */
uint32_t sctp_nr_sack_on_off;
- uint32_t sctp_cmt_pf;
uint32_t sctp_use_cwnd_based_maxburst;
- uint32_t sctp_early_fr;
- uint32_t sctp_early_fr_msec;
uint32_t sctp_asconf_auth_nochk;
uint32_t sctp_auth_disable;
uint32_t sctp_nat_friendly;
@@ -322,6 +320,12 @@ struct sctp_sysctl {
#define SCTPCTL_PATH_RTX_MAX_MAX 0xFFFFFFFF
#define SCTPCTL_PATH_RTX_MAX_DEFAULT SCTP_DEF_MAX_PATH_RTX
+/* path_pf_threshold: threshold for considering the path potentially failed */
+#define SCTPCTL_PATH_PF_THRESHOLD_DESC "Default potentially failed threshold"
+#define SCTPCTL_PATH_PF_THRESHOLD_MIN 0
+#define SCTPCTL_PATH_PF_THRESHOLD_MAX 0xFFFF
+#define SCTPCTL_PATH_PF_THRESHOLD_DEFAULT SCTPCTL_PATH_PF_THRESHOLD_MAX
+
/* add_more_on_output: When space-wise is it worthwhile to try to add more to a socket send buffer */
#define SCTPCTL_ADD_MORE_ON_OUTPUT_DESC "When space-wise is it worthwhile to try to add more to a socket send buffer"
#define SCTPCTL_ADD_MORE_ON_OUTPUT_MIN 0
@@ -352,30 +356,12 @@ struct sctp_sysctl {
#define SCTPCTL_CMT_USE_DAC_MAX 1
#define SCTPCTL_CMT_USE_DAC_DEFAULT 0
-/* JRS 5/2107 - CMT PF type flag */
-#define SCTPCTL_CMT_PF_DESC "CMT PF type flag"
-#define SCTPCTL_CMT_PF_MIN 0
-#define SCTPCTL_CMT_PF_MAX 2
-#define SCTPCTL_CMT_PF_DEFAULT 0
-
/* cwnd_maxburst: Use a CWND adjusting maxburst */
#define SCTPCTL_CWND_MAXBURST_DESC "Use a CWND adjusting maxburst"
#define SCTPCTL_CWND_MAXBURST_MIN 0
#define SCTPCTL_CWND_MAXBURST_MAX 1
#define SCTPCTL_CWND_MAXBURST_DEFAULT 1
-/* early_fast_retran: Early Fast Retransmit with timer */
-#define SCTPCTL_EARLY_FAST_RETRAN_DESC "Early Fast Retransmit with timer"
-#define SCTPCTL_EARLY_FAST_RETRAN_MIN 0
-#define SCTPCTL_EARLY_FAST_RETRAN_MAX 0xFFFFFFFF
-#define SCTPCTL_EARLY_FAST_RETRAN_DEFAULT 0
-
-/* early_fast_retran_msec: Early Fast Retransmit minimum timer value */
-#define SCTPCTL_EARLY_FAST_RETRAN_MSEC_DESC "Early Fast Retransmit minimum timer value"
-#define SCTPCTL_EARLY_FAST_RETRAN_MSEC_MIN 0
-#define SCTPCTL_EARLY_FAST_RETRAN_MSEC_MAX 0xFFFFFFFF
-#define SCTPCTL_EARLY_FAST_RETRAN_MSEC_DEFAULT SCTP_MINFR_MSEC_TIMER
-
/* asconf_auth_nochk: Disable SCTP ASCONF AUTH requirement */
#define SCTPCTL_ASCONF_AUTH_NOCHK_DESC "Disable SCTP ASCONF AUTH requirement"
#define SCTPCTL_ASCONF_AUTH_NOCHK_MIN 0
diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c
index 133af4aed452d..a33e7924b2249 100644
--- a/sys/netinet/sctp_timer.c
+++ b/sys/netinet/sctp_timer.c
@@ -55,103 +55,6 @@ __FBSDID("$FreeBSD$");
void
-sctp_early_fr_timer(struct sctp_inpcb *inp,
- struct sctp_tcb *stcb,
- struct sctp_nets *net)
-{
- struct sctp_tmit_chunk *chk, *pchk;
- struct timeval now, min_wait, tv;
- unsigned int cur_rto, cnt = 0, cnt_resend = 0;
-
- /* an early FR is occuring. */
- (void)SCTP_GETTIME_TIMEVAL(&now);
- /* get cur rto in micro-seconds */
- if (net->lastsa == 0) {
- /* Hmm no rtt estimate yet? */
- cur_rto = stcb->asoc.initial_rto >> 2;
- } else {
-
- cur_rto = (net->lastsa >> SCTP_RTT_SHIFT) + net->lastsv;
- }
- if (cur_rto < SCTP_BASE_SYSCTL(sctp_early_fr_msec)) {
- cur_rto = SCTP_BASE_SYSCTL(sctp_early_fr_msec);
- }
- cur_rto *= 1000;
- tv.tv_sec = cur_rto / 1000000;
- tv.tv_usec = cur_rto % 1000000;
- min_wait = now;
- timevalsub(&min_wait, &tv);
- if (min_wait.tv_sec < 0 || min_wait.tv_usec < 0) {
- /*
- * if we hit here, we don't have enough seconds on the clock
- * to account for the RTO. We just let the lower seconds be
- * the bounds and don't worry about it. This may mean we
- * will mark a lot more than we should.
- */
- min_wait.tv_sec = min_wait.tv_usec = 0;
- }
- TAILQ_FOREACH_REVERSE_SAFE(chk, &stcb->asoc.sent_queue, sctpchunk_listhead, sctp_next, pchk) {
- if (chk->whoTo != net) {
- continue;
- }
- if (chk->sent == SCTP_DATAGRAM_RESEND)
- cnt_resend++;
- else if ((chk->sent > SCTP_DATAGRAM_UNSENT) &&
- (chk->sent < SCTP_DATAGRAM_RESEND)) {
- /* pending, may need retran */
- if (chk->sent_rcv_time.tv_sec > min_wait.tv_sec) {
- /*
- * we have reached a chunk that was sent
- * some seconds past our min.. forget it we
- * will find no more to send.
- */
- continue;
- } else if (chk->sent_rcv_time.tv_sec == min_wait.tv_sec) {
- /*
- * we must look at the micro seconds to
- * know.
- */
- if (chk->sent_rcv_time.tv_usec >= min_wait.tv_usec) {
- /*
- * ok it was sent after our boundary
- * time.
- */
- continue;
- }
- }
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_EARLYFR_LOGGING_ENABLE) {
- sctp_log_fr(chk->rec.data.TSN_seq, chk->snd_count,
- 4, SCTP_FR_MARKED_EARLY);
- }
- SCTP_STAT_INCR(sctps_earlyfrmrkretrans);
- chk->sent = SCTP_DATAGRAM_RESEND;
- sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
- /* double book size since we are doing an early FR */
- chk->book_size_scale++;
- cnt += chk->send_size;
- if ((cnt + net->flight_size) > net->cwnd) {
- /* Mark all we could possibly resend */
- break;
- }
- }
- }
- if (cnt) {
- /*
- * JRS - Use the congestion control given in the congestion
- * control module
- */
- stcb->asoc.cc_functions.sctp_cwnd_update_after_fr_timer(inp, stcb, net);
- } else if (cnt_resend) {
- sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_EARLY_FR_TMR, SCTP_SO_NOT_LOCKED);
- }
- /* Restart it? */
- if (net->flight_size < net->cwnd) {
- SCTP_STAT_INCR(sctps_earlyfrstrtmr);
- sctp_timer_start(SCTP_TIMER_TYPE_EARLYFR, stcb->sctp_ep, stcb, net);
- }
-}
-
-void
sctp_audit_retranmission_queue(struct sctp_association *asoc)
{
struct sctp_tmit_chunk *chk;
@@ -195,44 +98,23 @@ sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
/* We had a threshold failure */
if (net->dest_state & SCTP_ADDR_REACHABLE) {
net->dest_state &= ~SCTP_ADDR_REACHABLE;
- net->dest_state |= SCTP_ADDR_NOT_REACHABLE;
net->dest_state &= ~SCTP_ADDR_REQ_PRIMARY;
- if (net == stcb->asoc.primary_destination) {
- net->dest_state |= SCTP_ADDR_WAS_PRIMARY;
- }
- /*
- * JRS 5/14/07 - If a destination is
- * unreachable, the PF bit is turned off.
- * This allows an unambiguous use of the PF
- * bit for destinations that are reachable
- * but potentially failed. If the
- * destination is set to the unreachable
- * state, also set the destination to the PF
- * state.
- */
- /*
- * Add debug message here if destination is
- * not in PF state.
- */
- /* Stop any running T3 timers here? */
- if ((stcb->asoc.sctp_cmt_on_off > 0) &&
- (stcb->asoc.sctp_cmt_pf > 0)) {
- net->dest_state &= ~SCTP_ADDR_PF;
- SCTPDBG(SCTP_DEBUG_TIMER4, "Destination %p moved from PF to unreachable.\n",
- net);
- }
+ net->dest_state &= ~SCTP_ADDR_PF;
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
stcb,
SCTP_FAILED_THRESHOLD,
(void *)net, SCTP_SO_NOT_LOCKED);
}
+ } else if ((net->pf_threshold < net->failure_threshold) &&
+ (net->error_count > net->pf_threshold)) {
+ if (!(net->dest_state & SCTP_ADDR_PF)) {
+ net->dest_state |= SCTP_ADDR_PF;
+ net->last_active = sctp_get_tick_count();
+ sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED);
+ sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
+ }
}
- /*********HOLD THIS COMMENT FOR PATCH OF ALTERNATE
- *********ROUTING CODE
- */
- /*********HOLD THIS COMMENT FOR END OF PATCH OF ALTERNATE
- *********ROUTING CODE
- */
}
if (stcb == NULL)
return (0);
@@ -407,31 +289,10 @@ sctp_find_alternate_net(struct sctp_tcb *stcb,
}
}
}
- /*
- * JRS 5/14/07 - After all destination have been considered
- * as alternates, check to see if there was some active
- * destination (not in PF state). If not, check to see if
- * there was some PF destination with the minimum number of
- * errors. If not, return the original destination. If
- * there is a min_errors_net, remove the PF flag from that
- * destination, set the cwnd to one or two MTUs, and return
- * the destination as an alt. If there was some active
- * destination with a highest cwnd, return the destination
- * as an alt.
- */
if (max_cwnd_net == NULL) {
if (min_errors_net == NULL) {
return (net);
}
- min_errors_net->dest_state &= ~SCTP_ADDR_PF;
- min_errors_net->cwnd = min_errors_net->mtu * stcb->asoc.sctp_cmt_pf;
- if (SCTP_OS_TIMER_PENDING(&min_errors_net->rxt_timer.timer)) {
- sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
- stcb, min_errors_net,
- SCTP_FROM_SCTP_TIMER + SCTP_LOC_2);
- }
- SCTPDBG(SCTP_DEBUG_TIMER4, "Destination %p moved from PF to active with %d errors.\n",
- min_errors_net, min_errors_net->error_count);
return (min_errors_net);
} else {
return (max_cwnd_net);
@@ -646,15 +507,12 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
/* get cur rto in micro-seconds */
cur_rto = (net->lastsa >> SCTP_RTT_SHIFT) + net->lastsv;
cur_rto *= 1000;
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_EARLYFR_LOGGING_ENABLE | SCTP_FR_LOGGING_ENABLE)) {
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
sctp_log_fr(cur_rto,
stcb->asoc.peers_rwnd,
window_probe,
SCTP_FR_T3_MARK_TIME);
- sctp_log_fr(net->flight_size,
- SCTP_OS_TIMER_PENDING(&net->fr_timer.timer),
- SCTP_OS_TIMER_ACTIVE(&net->fr_timer.timer),
- SCTP_FR_CWND_REPORT);
+ sctp_log_fr(net->flight_size, 0, 0, SCTP_FR_CWND_REPORT);
sctp_log_fr(net->flight_size, net->cwnd, stcb->asoc.total_flight, SCTP_FR_CWND_REPORT);
}
tv.tv_sec = cur_rto / 1000000;
@@ -670,7 +528,7 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
*/
min_wait.tv_sec = min_wait.tv_usec = 0;
}
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_EARLYFR_LOGGING_ENABLE | SCTP_FR_LOGGING_ENABLE)) {
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
sctp_log_fr(cur_rto, now.tv_sec, now.tv_usec, SCTP_FR_T3_MARK_TIME);
sctp_log_fr(0, min_wait.tv_sec, min_wait.tv_usec, SCTP_FR_T3_MARK_TIME);
}
@@ -717,7 +575,7 @@ start_again:
*/
/* validate its been outstanding long enough */
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_EARLYFR_LOGGING_ENABLE | SCTP_FR_LOGGING_ENABLE)) {
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
sctp_log_fr(chk->rec.data.TSN_seq,
chk->sent_rcv_time.tv_sec,
chk->sent_rcv_time.tv_usec,
@@ -729,7 +587,7 @@ start_again:
* some seconds past our min.. forget it we
* will find no more to send.
*/
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_EARLYFR_LOGGING_ENABLE | SCTP_FR_LOGGING_ENABLE)) {
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
sctp_log_fr(0,
chk->sent_rcv_time.tv_sec,
chk->sent_rcv_time.tv_usec,
@@ -747,12 +605,6 @@ start_again:
* ok it was sent after our boundary
* time.
*/
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_EARLYFR_LOGGING_ENABLE | SCTP_FR_LOGGING_ENABLE)) {
- sctp_log_fr(0,
- chk->sent_rcv_time.tv_sec,
- chk->sent_rcv_time.tv_usec,
- SCTP_FR_T3_STOPPED);
- }
continue;
}
}
@@ -791,7 +643,7 @@ start_again:
tsnfirst = chk->rec.data.TSN_seq;
}
tsnlast = chk->rec.data.TSN_seq;
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_EARLYFR_LOGGING_ENABLE | SCTP_FR_LOGGING_ENABLE)) {
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
sctp_log_fr(chk->rec.data.TSN_seq, chk->snd_count,
0, SCTP_FR_T3_MARKED);
}
@@ -860,7 +712,7 @@ start_again:
/* we did not subtract the same things? */
audit_tf = 1;
}
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_EARLYFR_LOGGING_ENABLE | SCTP_FR_LOGGING_ENABLE)) {
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
sctp_log_fr(tsnfirst, tsnlast, num_mk, SCTP_FR_T3_TIMEOUT);
}
#ifdef SCTP_DEBUG
@@ -978,61 +830,6 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp,
win_probe = 0;
}
- /*
- * JRS 5/14/07 - If CMT PF is on and the destination if not already
- * in PF state, set the destination to PF state and store the
- * current time as the time that the destination was last active. In
- * addition, find an alternate destination with PF-based
- * find_alt_net().
- */
- if ((stcb->asoc.sctp_cmt_on_off > 0) &&
- (stcb->asoc.sctp_cmt_pf > 0)) {
- if ((net->dest_state & SCTP_ADDR_PF) != SCTP_ADDR_PF) {
- net->dest_state |= SCTP_ADDR_PF;
- net->last_active = sctp_get_tick_count();
- SCTPDBG(SCTP_DEBUG_TIMER4, "Destination %p moved from active to PF.\n",
- net);
- }
- alt = sctp_find_alternate_net(stcb, net, 2);
- } else if (stcb->asoc.sctp_cmt_on_off > 0) {
- /*
- * CMT: Using RTX_SSTHRESH policy for CMT. If CMT is being
- * used, then pick dest with largest ssthresh for any
- * retransmission.
- */
- alt = sctp_find_alternate_net(stcb, net, 1);
- /*
- * CUCv2: If a different dest is picked for the
- * retransmission, then new (rtx-)pseudo_cumack needs to be
- * tracked for orig dest. Let CUCv2 track new (rtx-)
- * pseudo-cumack always.
- */
- net->find_pseudo_cumack = 1;
- net->find_rtx_pseudo_cumack = 1;
- } else { /* CMT is OFF */
- alt = sctp_find_alternate_net(stcb, net, 0);
- }
- num_mk = 0;
- num_abandoned = 0;
- (void)sctp_mark_all_for_resend(stcb, net, alt, win_probe,
- &num_mk, &num_abandoned);
- /* FR Loss recovery just ended with the T3. */
- stcb->asoc.fast_retran_loss_recovery = 0;
-
- /* CMT FR loss recovery ended with the T3 */
- net->fast_retran_loss_recovery = 0;
- if ((stcb->asoc.cc_functions.sctp_cwnd_new_transmission_begins) &&
- (net->flight_size == 0)) {
- (*stcb->asoc.cc_functions.sctp_cwnd_new_transmission_begins) (stcb, net);
- }
- /*
- * setup the sat loss recovery that prevents satellite cwnd advance.
- */
- stcb->asoc.sat_t3_loss_recovery = 1;
- stcb->asoc.sat_t3_recovery_tsn = stcb->asoc.sending_seq;
-
- /* Backoff the timer and cwnd */
- sctp_backoff_on_timeout(stcb, net, win_probe, num_mk, num_abandoned);
if (win_probe == 0) {
/* We don't do normal threshold management on window probes */
if (sctp_threshold_management(inp, stcb, net,
@@ -1051,17 +848,15 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp,
} else {
ms_goneby = 0;
}
- if ((ms_goneby > net->RTO) || (net->RTO == 0)) {
- /*
- * no recent feed back in an RTO or
- * more, request a RTT update
- */
- if (sctp_send_hb(stcb, 1, net, SCTP_SO_NOT_LOCKED) < 0)
+ if ((net->dest_state & SCTP_ADDR_PF) == 0) {
+ if ((ms_goneby > net->RTO) || (net->RTO == 0)) {
/*
- * Less than 0 means we lost
- * the assoc
+ * no recent feed back in an
+ * RTO or more, request a
+ * RTT update
*/
- return (1);
+ sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED);
+ }
}
}
}
@@ -1078,7 +873,52 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp,
return (1);
}
}
- if (net->dest_state & SCTP_ADDR_NOT_REACHABLE) {
+ if (stcb->asoc.sctp_cmt_on_off > 0) {
+ if (net->pf_threshold < net->failure_threshold) {
+ alt = sctp_find_alternate_net(stcb, net, 2);
+ } else {
+ /*
+ * CMT: Using RTX_SSTHRESH policy for CMT. If CMT is
+ * being used, then pick dest with largest ssthresh
+ * for any retransmission.
+ */
+ alt = sctp_find_alternate_net(stcb, net, 1);
+ /*
+ * CUCv2: If a different dest is picked for the
+ * retransmission, then new (rtx-)pseudo_cumack
+ * needs to be tracked for orig dest. Let CUCv2
+ * track new (rtx-) pseudo-cumack always.
+ */
+ net->find_pseudo_cumack = 1;
+ net->find_rtx_pseudo_cumack = 1;
+ }
+ } else {
+ alt = sctp_find_alternate_net(stcb, net, 0);
+ }
+
+ num_mk = 0;
+ num_abandoned = 0;
+ (void)sctp_mark_all_for_resend(stcb, net, alt, win_probe,
+ &num_mk, &num_abandoned);
+ /* FR Loss recovery just ended with the T3. */
+ stcb->asoc.fast_retran_loss_recovery = 0;
+
+ /* CMT FR loss recovery ended with the T3 */
+ net->fast_retran_loss_recovery = 0;
+ if ((stcb->asoc.cc_functions.sctp_cwnd_new_transmission_begins) &&
+ (net->flight_size == 0)) {
+ (*stcb->asoc.cc_functions.sctp_cwnd_new_transmission_begins) (stcb, net);
+ }
+ /*
+ * setup the sat loss recovery that prevents satellite cwnd advance.
+ */
+ stcb->asoc.sat_t3_loss_recovery = 1;
+ stcb->asoc.sat_t3_recovery_tsn = stcb->asoc.sending_seq;
+
+ /* Backoff the timer and cwnd */
+ sctp_backoff_on_timeout(stcb, net, win_probe, num_mk, num_abandoned);
+ if ((!(net->dest_state & SCTP_ADDR_REACHABLE)) ||
+ (net->dest_state & SCTP_ADDR_PF)) {
/* Move all pending over too */
sctp_move_chunks_from_net(stcb, net);
@@ -1106,23 +946,12 @@ sctp_t3rxt_timer(struct sctp_inpcb *inp,
* change-primary then this flag must be cleared
* from any net structures.
*/
- if (sctp_set_primary_addr(stcb,
- (struct sockaddr *)NULL,
- alt) == 0) {
- net->dest_state |= SCTP_ADDR_WAS_PRIMARY;
+ if (stcb->asoc.alternate) {
+ sctp_free_remote_addr(stcb->asoc.alternate);
}
+ stcb->asoc.alternate = alt;
+ atomic_add_int(&stcb->asoc.alternate->ref_count, 1);
}
- } else if ((stcb->asoc.sctp_cmt_on_off > 0) &&
- (stcb->asoc.sctp_cmt_pf > 0) &&
- ((net->dest_state & SCTP_ADDR_PF) == SCTP_ADDR_PF)) {
- /*
- * JRS 5/14/07 - If the destination hasn't failed completely
- * but is in PF state, a PF-heartbeat needs to be sent
- * manually.
- */
- if (sctp_send_hb(stcb, 1, net, SCTP_SO_NOT_LOCKED) < 0)
- /* Return less than 0 means we lost the association */
- return (1);
}
/*
* Special case for cookie-echo'ed case, we don't do output but must
@@ -1324,7 +1153,7 @@ sctp_strreset_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
atomic_add_int(&alt->ref_count, 1);
}
}
- if (net->dest_state & SCTP_ADDR_NOT_REACHABLE) {
+ if (!(net->dest_state & SCTP_ADDR_REACHABLE)) {
/*
* If the address went un-reachable, we need to move to
* alternates for ALL chk's in queue
@@ -1414,7 +1243,7 @@ sctp_asconf_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
chk->sent = SCTP_DATAGRAM_RESEND;
}
- if (net->dest_state & SCTP_ADDR_NOT_REACHABLE) {
+ if (!(net->dest_state & SCTP_ADDR_REACHABLE)) {
/*
* If the address went un-reachable, we need to move
* to the alternate for ALL chunks in queue
@@ -1569,11 +1398,15 @@ sctp_audit_stream_queues_for_size(struct sctp_inpcb *inp,
int
sctp_heartbeat_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
- struct sctp_nets *net, int cnt_of_unconf)
+ struct sctp_nets *net)
{
- int ret;
+ uint8_t net_was_pf;
+ net_was_pf = 0;
if (net) {
+ if (net->dest_state & SCTP_ADDR_PF) {
+ net_was_pf = 1;
+ }
if (net->hb_responded == 0) {
if (net->ro._s_addr) {
/*
@@ -1585,6 +1418,10 @@ sctp_heartbeat_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
net->src_addr_selected = 0;
}
sctp_backoff_on_timeout(stcb, net, 1, 0, 0);
+ if (sctp_threshold_management(inp, stcb, net, stcb->asoc.max_send_times)) {
+ /* Assoc is over */
+ return (1);
+ }
}
/* Zero PBA, if it needs it */
if (net->partial_bytes_acked) {
@@ -1596,41 +1433,13 @@ sctp_heartbeat_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
(TAILQ_EMPTY(&stcb->asoc.sent_queue))) {
sctp_audit_stream_queues_for_size(inp, stcb);
}
- /* Send a new HB, this will do threshold managment, pick a new dest */
- if (cnt_of_unconf == 0) {
- if (sctp_send_hb(stcb, 0, NULL, SCTP_SO_NOT_LOCKED) < 0) {
- return (1);
- }
- } else {
+ if (!(net->dest_state & SCTP_ADDR_NOHB) &&
+ !((net_was_pf == 0) && (net->dest_state & SCTP_ADDR_PF))) {
/*
- * this will send out extra hb's up to maxburst if there are
- * any unconfirmed addresses.
+ * when move to PF during threshold mangement, a HB has been
+ * queued in that routine
*/
- uint32_t cnt_sent = 0;
-
- TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
- if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
- (net->dest_state & SCTP_ADDR_REACHABLE)) {
- cnt_sent++;
- if (net->hb_responded == 0) {
- /* Did we respond last time? */
- if (net->ro._s_addr) {
- sctp_free_ifa(net->ro._s_addr);
- net->ro._s_addr = NULL;
- net->src_addr_selected = 0;
- }
- }
- ret = sctp_send_hb(stcb, 1, net, SCTP_SO_NOT_LOCKED);
- if (ret < 0)
- return 1;
- else if (ret == 0) {
- break;
- }
- if (SCTP_BASE_SYSCTL(sctp_hb_maxburst) &&
- (cnt_sent >= SCTP_BASE_SYSCTL(sctp_hb_maxburst)))
- break;
- }
- }
+ sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED);
}
return (0);
}
@@ -1733,7 +1542,14 @@ sctp_autoclose_timer(struct sctp_inpcb *inp,
*/
if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) {
/* only send SHUTDOWN 1st time thru */
- sctp_send_shutdown(stcb, stcb->asoc.primary_destination);
+ struct sctp_nets *netp;
+
+ if (stcb->asoc.alternate) {
+ netp = stcb->asoc.alternate;
+ } else {
+ netp = stcb->asoc.primary_destination;
+ }
+ sctp_send_shutdown(stcb, netp);
if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
(SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
@@ -1742,10 +1558,10 @@ sctp_autoclose_timer(struct sctp_inpcb *inp,
SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
stcb->sctp_ep, stcb,
- asoc->primary_destination);
+ netp);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
stcb->sctp_ep, stcb,
- asoc->primary_destination);
+ netp);
}
}
} else {
diff --git a/sys/netinet/sctp_timer.h b/sys/netinet/sctp_timer.h
index 5857291da8900..7b1341a3cf481 100644
--- a/sys/netinet/sctp_timer.h
+++ b/sys/netinet/sctp_timer.h
@@ -42,10 +42,6 @@ __FBSDID("$FreeBSD$");
#define SCTP_RTT_SHIFT 3
#define SCTP_RTT_VAR_SHIFT 2
-void
-sctp_early_fr_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
- struct sctp_nets *net);
-
struct sctp_nets *
sctp_find_alternate_net(struct sctp_tcb *,
struct sctp_nets *, int mode);
@@ -65,7 +61,7 @@ sctp_shutdown_timer(struct sctp_inpcb *, struct sctp_tcb *,
struct sctp_nets *);
int
sctp_heartbeat_timer(struct sctp_inpcb *, struct sctp_tcb *,
- struct sctp_nets *, int);
+ struct sctp_nets *);
int
sctp_cookie_timer(struct sctp_inpcb *, struct sctp_tcb *,
diff --git a/sys/netinet/sctp_uio.h b/sys/netinet/sctp_uio.h
index 9b9acbfc6f64d..37e9b798a991b 100644
--- a/sys/netinet/sctp_uio.h
+++ b/sys/netinet/sctp_uio.h
@@ -329,7 +329,8 @@ struct sctp_paddr_change {
#define SCTP_ADDR_CONFIRMED 0x0006
#define SCTP_ACTIVE 0x0001 /* SCTP_ADDR_REACHABLE */
-#define SCTP_INACTIVE 0x0002 /* SCTP_ADDR_NOT_REACHABLE */
+#define SCTP_INACTIVE 0x0002 /* neither SCTP_ADDR_REACHABLE nor
+ * SCTP_ADDR_UNCONFIRMED */
#define SCTP_UNCONFIRMED 0x0200 /* SCTP_ADDR_UNCONFIRMED */
/* remote error events */
@@ -504,9 +505,11 @@ struct sctp_paddrparams {
uint32_t spp_flags;
uint32_t spp_ipv6_flowlabel;
uint16_t spp_pathmaxrxt;
- uint8_t spp_ipv4_tos;
+ uint8_t spp_dscp;
};
+#define spp_ipv4_tos spp_dscp
+
#define SPP_HB_ENABLE 0x00000001
#define SPP_HB_DISABLE 0x00000002
#define SPP_HB_DEMAND 0x00000004
@@ -514,7 +517,15 @@ struct sctp_paddrparams {
#define SPP_PMTUD_DISABLE 0x00000010
#define SPP_HB_TIME_IS_ZERO 0x00000080
#define SPP_IPV6_FLOWLABEL 0x00000100
-#define SPP_IPV4_TOS 0x00000200
+#define SPP_DSCP 0x00000200
+#define SPP_IPV4_TOS SPP_DSCP
+
+struct sctp_paddrthlds {
+ sctp_assoc_t spt_assoc_id;
+ struct sockaddr_storage spt_address;
+ uint16_t spt_pathmaxrxt;
+ uint16_t spt_pathpfthld;
+};
struct sctp_paddrinfo {
struct sockaddr_storage spinfo_address;
@@ -978,18 +989,8 @@ struct sctpstat {
* fired */
uint32_t sctps_timoassockill; /* Number of asoc free timers expired */
uint32_t sctps_timoinpkill; /* Number of inp free timers expired */
- /* Early fast retransmission counters */
- uint32_t sctps_earlyfrstart;
- uint32_t sctps_earlyfrstop;
- uint32_t sctps_earlyfrmrkretrans;
- uint32_t sctps_earlyfrstpout;
- uint32_t sctps_earlyfrstpidsck1;
- uint32_t sctps_earlyfrstpidsck2;
- uint32_t sctps_earlyfrstpidsck3;
- uint32_t sctps_earlyfrstpidsck4;
- uint32_t sctps_earlyfrstrid;
- uint32_t sctps_earlyfrstrout;
- uint32_t sctps_earlyfrstrtmr;
+ /* former early FR counters */
+ uint32_t sctps_spare[11];
/* others */
uint32_t sctps_hdrops; /* packet shorter than header */
uint32_t sctps_badsum; /* checksum error */
@@ -1162,9 +1163,11 @@ struct xsctp_raddr {
uint8_t active; /* sctpAssocLocalRemEntry 3 */
uint8_t confirmed; /* */
uint8_t heartbeat_enabled; /* sctpAssocLocalRemEntry 4 */
+ uint8_t potentially_failed;
struct sctp_timeval start_time; /* sctpAssocLocalRemEntry 8 */
uint32_t rtt;
- uint32_t extra_padding[32]; /* future */
+ uint32_t heartbeat_interval;
+ uint32_t extra_padding[31]; /* future */
};
#define SCTP_MAX_LOGGING_SIZE 30000
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
index ab87772f0d475..82a8cba37fcbb 100644
--- a/sys/netinet/sctp_usrreq.c
+++ b/sys/netinet/sctp_usrreq.c
@@ -275,33 +275,8 @@ sctp_notify(struct sctp_inpcb *inp,
*/
if (net->dest_state & SCTP_ADDR_REACHABLE) {
/* Ok that destination is NOT reachable */
- SCTP_PRINTF("ICMP (thresh %d/%d) takes interface %p down\n",
- net->error_count,
- net->failure_threshold,
- net);
-
net->dest_state &= ~SCTP_ADDR_REACHABLE;
- net->dest_state |= SCTP_ADDR_NOT_REACHABLE;
- /*
- * JRS 5/14/07 - If a destination is unreachable,
- * the PF bit is turned off. This allows an
- * unambiguous use of the PF bit for destinations
- * that are reachable but potentially failed. If the
- * destination is set to the unreachable state, also
- * set the destination to the PF state.
- */
- /*
- * Add debug message here if destination is not in
- * PF state.
- */
- /* Stop any running T3 timers here? */
- if ((stcb->asoc.sctp_cmt_on_off > 0) &&
- (stcb->asoc.sctp_cmt_pf > 0)) {
- net->dest_state &= ~SCTP_ADDR_PF;
- SCTPDBG(SCTP_DEBUG_TIMER4, "Destination %p moved from PF to unreachable.\n",
- net);
- }
- net->error_count = net->failure_threshold + 1;
+ net->dest_state &= ~SCTP_ADDR_PF;
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
stcb, SCTP_FAILED_THRESHOLD,
(void *)net, SCTP_SO_NOT_LOCKED);
@@ -585,7 +560,7 @@ sctp_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
struct sctp_inpcb *inp = NULL;
int error;
-#ifdef INET6
+#ifdef INET
if (addr && addr->sa_family != AF_INET) {
/* must be a v4 address! */
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
@@ -837,9 +812,15 @@ sctp_disconnect(struct socket *so)
if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) &&
(SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
/* only send SHUTDOWN 1st time thru */
+ struct sctp_nets *netp;
+
+ if (stcb->asoc.alternate) {
+ netp = stcb->asoc.alternate;
+ } else {
+ netp = stcb->asoc.primary_destination;
+ }
sctp_stop_timers_for_shutdown(stcb);
- sctp_send_shutdown(stcb,
- stcb->asoc.primary_destination);
+ sctp_send_shutdown(stcb, netp);
sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED);
if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
(SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
@@ -848,11 +829,10 @@ sctp_disconnect(struct socket *so)
SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
- stcb->sctp_ep, stcb,
- asoc->primary_destination);
+ stcb->sctp_ep, stcb, netp);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
- stcb->sctp_ep, stcb,
- asoc->primary_destination);
+ stcb->sctp_ep, stcb, netp);
+
}
} else {
/*
@@ -865,9 +845,17 @@ sctp_disconnect(struct socket *so)
* we will allow user data to be sent first
* and move to SHUTDOWN-PENDING
*/
+ struct sctp_nets *netp;
+
+ if (stcb->asoc.alternate) {
+ netp = stcb->asoc.alternate;
+ } else {
+ netp = stcb->asoc.primary_destination;
+ }
+
asoc->state |= SCTP_STATE_SHUTDOWN_PENDING;
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
- asoc->primary_destination);
+ netp);
if (asoc->locked_on_sending) {
/* Locked to send out the data */
struct sctp_stream_queue_pending *sp;
@@ -1047,9 +1035,15 @@ sctp_shutdown(struct socket *so)
/* there is nothing queued to send, so I'm done... */
if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) {
/* only send SHUTDOWN the first time through */
+ struct sctp_nets *netp;
+
+ if (stcb->asoc.alternate) {
+ netp = stcb->asoc.alternate;
+ } else {
+ netp = stcb->asoc.primary_destination;
+ }
sctp_stop_timers_for_shutdown(stcb);
- sctp_send_shutdown(stcb,
- stcb->asoc.primary_destination);
+ sctp_send_shutdown(stcb, netp);
sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED);
if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
(SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
@@ -1058,20 +1052,26 @@ sctp_shutdown(struct socket *so)
SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
- stcb->sctp_ep, stcb,
- asoc->primary_destination);
+ stcb->sctp_ep, stcb, netp);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
- stcb->sctp_ep, stcb,
- asoc->primary_destination);
+ stcb->sctp_ep, stcb, netp);
}
} else {
/*
* we still got (or just got) data to send, so set
* SHUTDOWN_PENDING
*/
+ struct sctp_nets *netp;
+
+ if (stcb->asoc.alternate) {
+ netp = stcb->asoc.alternate;
+ } else {
+ netp = stcb->asoc.primary_destination;
+ }
+
asoc->state |= SCTP_STATE_SHUTDOWN_PENDING;
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
- asoc->primary_destination);
+ netp);
if (asoc->locked_on_sending) {
/* Locked to send out the data */
@@ -1541,6 +1541,11 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
/* Gak! no memory */
goto out_now;
}
+ if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
+ stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
+ /* Set the connected flag so we can queue data */
+ soisconnecting(so);
+ }
SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
/* move to second address */
switch (sa->sa_family) {
@@ -1767,7 +1772,9 @@ flags_out:
av->assoc_value = stcb->asoc.sctp_cmt_on_off;
SCTP_TCB_UNLOCK(stcb);
} else {
- if (av->assoc_id == SCTP_FUTURE_ASSOC) {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (av->assoc_id == SCTP_FUTURE_ASSOC)) {
SCTP_INP_RLOCK(inp);
av->assoc_value = inp->sctp_cmt_on_off;
SCTP_INP_RUNLOCK(inp);
@@ -1791,7 +1798,9 @@ flags_out:
av->assoc_value = stcb->asoc.congestion_control_module;
SCTP_TCB_UNLOCK(stcb);
} else {
- if (av->assoc_id == SCTP_FUTURE_ASSOC) {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (av->assoc_id == SCTP_FUTURE_ASSOC)) {
SCTP_INP_RLOCK(inp);
av->assoc_value = inp->sctp_ep.sctp_default_cc_module;
SCTP_INP_RUNLOCK(inp);
@@ -1834,7 +1843,9 @@ flags_out:
av->assoc_value = stcb->asoc.stream_scheduling_module;
SCTP_TCB_UNLOCK(stcb);
} else {
- if (av->assoc_id == SCTP_FUTURE_ASSOC) {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (av->assoc_id == SCTP_FUTURE_ASSOC)) {
SCTP_INP_RLOCK(inp);
av->assoc_value = inp->sctp_ep.sctp_default_ss_module;
SCTP_INP_RUNLOCK(inp);
@@ -1949,7 +1960,9 @@ flags_out:
av->assoc_value = stcb->asoc.context;
SCTP_TCB_UNLOCK(stcb);
} else {
- if (av->assoc_id == SCTP_FUTURE_ASSOC) {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (av->assoc_id == SCTP_FUTURE_ASSOC)) {
SCTP_INP_RLOCK(inp);
av->assoc_value = inp->sctp_context;
SCTP_INP_RUNLOCK(inp);
@@ -2022,7 +2035,9 @@ flags_out:
sack->sack_freq = stcb->asoc.sack_freq;
SCTP_TCB_UNLOCK(stcb);
} else {
- if (sack->sack_assoc_id == SCTP_FUTURE_ASSOC) {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (sack->sack_assoc_id == SCTP_FUTURE_ASSOC)) {
SCTP_INP_RLOCK(inp);
sack->sack_delay = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
sack->sack_freq = inp->sctp_ep.sctp_sack_freq;
@@ -2067,7 +2082,9 @@ flags_out:
av->assoc_value = stcb->asoc.max_burst;
SCTP_TCB_UNLOCK(stcb);
} else {
- if (av->assoc_id == SCTP_FUTURE_ASSOC) {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (av->assoc_id == SCTP_FUTURE_ASSOC)) {
SCTP_INP_RLOCK(inp);
av->assoc_value = inp->sctp_ep.max_burst;
SCTP_INP_RUNLOCK(inp);
@@ -2093,7 +2110,9 @@ flags_out:
av->assoc_value = sctp_get_frag_point(stcb, &stcb->asoc);
SCTP_TCB_UNLOCK(stcb);
} else {
- if (av->assoc_id == SCTP_FUTURE_ASSOC) {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (av->assoc_id == SCTP_FUTURE_ASSOC)) {
SCTP_INP_RLOCK(inp);
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
ovh = SCTP_MED_OVERHEAD;
@@ -2389,7 +2408,7 @@ flags_out:
}
}
if (stcb) {
- /* Applys to the specific association */
+ /* Applies to the specific association */
paddrp->spp_flags = 0;
if (net) {
int ovh;
@@ -2400,7 +2419,7 @@ flags_out:
ovh = SCTP_MED_V4_OVERHEAD;
}
-
+ paddrp->spp_hbinterval = net->heart_beat_delay;
paddrp->spp_pathmaxrxt = net->failure_threshold;
paddrp->spp_pathmtu = net->mtu - ovh;
/* get flags for HB */
@@ -2414,15 +2433,14 @@ flags_out:
} else {
paddrp->spp_flags |= SPP_PMTUD_DISABLE;
}
-#ifdef INET
- if (net->ro._l_addr.sin.sin_family == AF_INET) {
- paddrp->spp_ipv4_tos = net->tos_flowlabel & 0x000000fc;
- paddrp->spp_flags |= SPP_IPV4_TOS;
+ if (net->dscp & 0x01) {
+ paddrp->spp_dscp = net->dscp >> 2;
+ paddrp->spp_flags |= SPP_DSCP;
}
-#endif
#ifdef INET6
- if (net->ro._l_addr.sin6.sin6_family == AF_INET6) {
- paddrp->spp_ipv6_flowlabel = net->tos_flowlabel;
+ if ((net->ro._l_addr.sa.sa_family == AF_INET6) &&
+ (net->flowlabel & 0x80000000)) {
+ paddrp->spp_ipv6_flowlabel = net->flowlabel & 0x000fffff;
paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
}
#endif
@@ -2435,20 +2453,23 @@ flags_out:
paddrp->spp_pathmaxrxt = stcb->asoc.def_net_failure;
paddrp->spp_pathmtu = sctp_get_frag_point(stcb, &stcb->asoc);
-#ifdef INET
- paddrp->spp_ipv4_tos = stcb->asoc.default_tos & 0x000000fc;
- paddrp->spp_flags |= SPP_IPV4_TOS;
-#endif
+ if (stcb->asoc.default_dscp & 0x01) {
+ paddrp->spp_dscp = stcb->asoc.default_dscp >> 2;
+ paddrp->spp_flags |= SPP_DSCP;
+ }
#ifdef INET6
- paddrp->spp_ipv6_flowlabel = stcb->asoc.default_flowlabel;
- paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
+ if (stcb->asoc.default_flowlabel & 0x80000000) {
+ paddrp->spp_ipv6_flowlabel = stcb->asoc.default_flowlabel & 0x000fffff;
+ paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
+ }
#endif
/* default settings should be these */
- if (stcb->asoc.hb_is_disabled == 0) {
- paddrp->spp_flags |= SPP_HB_ENABLE;
- } else {
+ if (sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
paddrp->spp_flags |= SPP_HB_DISABLE;
+ } else {
+ paddrp->spp_flags |= SPP_HB_ENABLE;
}
+ paddrp->spp_hbinterval = stcb->asoc.heart_beat_delay;
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
cnt++;
@@ -2458,24 +2479,26 @@ flags_out:
paddrp->spp_flags |= SPP_PMTUD_ENABLE;
}
}
- paddrp->spp_hbinterval = stcb->asoc.heart_beat_delay;
paddrp->spp_assoc_id = sctp_get_associd(stcb);
SCTP_TCB_UNLOCK(stcb);
} else {
- if (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC) {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC)) {
/* Use endpoint defaults */
SCTP_INP_RLOCK(inp);
paddrp->spp_pathmaxrxt = inp->sctp_ep.def_net_failure;
paddrp->spp_hbinterval = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
paddrp->spp_assoc_id = SCTP_FUTURE_ASSOC;
/* get inp's default */
-#ifdef INET
- paddrp->spp_ipv4_tos = inp->ip_inp.inp.inp_ip_tos;
- paddrp->spp_flags |= SPP_IPV4_TOS;
-#endif
+ if (inp->sctp_ep.default_dscp & 0x01) {
+ paddrp->spp_dscp = inp->sctp_ep.default_dscp >> 2;
+ paddrp->spp_flags |= SPP_DSCP;
+ }
#ifdef INET6
- if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
- paddrp->spp_ipv6_flowlabel = ((struct in6pcb *)inp)->in6p_flowinfo;
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
+ (inp->sctp_ep.default_flowlabel & 0x80000000)) {
+ paddrp->spp_ipv6_flowlabel = inp->sctp_ep.default_flowlabel & 0x000fffff;
paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
}
#endif
@@ -2637,7 +2660,9 @@ flags_out:
srto->srto_min = stcb->asoc.minrto;
SCTP_TCB_UNLOCK(stcb);
} else {
- if (srto->srto_assoc_id == SCTP_FUTURE_ASSOC) {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (srto->srto_assoc_id == SCTP_FUTURE_ASSOC)) {
SCTP_INP_RLOCK(inp);
srto->srto_initial = inp->sctp_ep.initial_rto;
srto->srto_max = inp->sctp_ep.sctp_maxrto;
@@ -2691,7 +2716,9 @@ flags_out:
sasoc->sasoc_local_rwnd = stcb->asoc.my_rwnd;
SCTP_TCB_UNLOCK(stcb);
} else {
- if (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC) {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC)) {
SCTP_INP_RLOCK(inp);
sasoc->sasoc_cookie_life = TICKS_TO_MSEC(inp->sctp_ep.def_cookie_life);
sasoc->sasoc_asocmaxrxt = inp->sctp_ep.max_send_times;
@@ -2720,7 +2747,9 @@ flags_out:
memcpy(s_info, &stcb->asoc.def_send, sizeof(stcb->asoc.def_send));
SCTP_TCB_UNLOCK(stcb);
} else {
- if (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC) {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC)) {
SCTP_INP_RLOCK(inp);
memcpy(s_info, &inp->def_send, sizeof(inp->def_send));
SCTP_INP_RUNLOCK(inp);
@@ -2822,7 +2851,9 @@ flags_out:
scact->scact_keynumber = stcb->asoc.authinfo.active_keyid;
SCTP_TCB_UNLOCK(stcb);
} else {
- if (scact->scact_assoc_id == SCTP_FUTURE_ASSOC) {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (scact->scact_assoc_id == SCTP_FUTURE_ASSOC)) {
/* get the endpoint active key */
SCTP_INP_RLOCK(inp);
scact->scact_keynumber = inp->sctp_ep.default_keyid;
@@ -2861,7 +2892,9 @@ flags_out:
}
SCTP_TCB_UNLOCK(stcb);
} else {
- if (sac->gauth_assoc_id == SCTP_FUTURE_ASSOC) {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (sac->gauth_assoc_id == SCTP_FUTURE_ASSOC)) {
/* get off the endpoint */
SCTP_INP_RLOCK(inp);
chklist = inp->sctp_ep.local_auth_chunks;
@@ -2967,7 +3000,9 @@ flags_out:
event->se_on = sctp_stcb_is_feature_on(inp, stcb, event_type);
SCTP_TCB_UNLOCK(stcb);
} else {
- if (event->se_assoc_id == SCTP_FUTURE_ASSOC) {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (event->se_assoc_id == SCTP_FUTURE_ASSOC)) {
SCTP_INP_RLOCK(inp);
event->se_on = sctp_is_feature_on(inp, event_type);
SCTP_INP_RUNLOCK(inp);
@@ -3035,7 +3070,9 @@ flags_out:
info->snd_context = stcb->asoc.def_send.sinfo_context;
SCTP_TCB_UNLOCK(stcb);
} else {
- if (info->snd_assoc_id == SCTP_FUTURE_ASSOC) {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (info->snd_assoc_id == SCTP_FUTURE_ASSOC)) {
SCTP_INP_RLOCK(inp);
info->snd_sid = inp->def_send.sinfo_stream;
info->snd_flags = inp->def_send.sinfo_flags;
@@ -3065,7 +3102,9 @@ flags_out:
info->pr_value = stcb->asoc.def_send.sinfo_timetolive;
SCTP_TCB_UNLOCK(stcb);
} else {
- if (info->pr_assoc_id == SCTP_FUTURE_ASSOC) {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (info->pr_assoc_id == SCTP_FUTURE_ASSOC)) {
SCTP_INP_RLOCK(inp);
info->pr_policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
info->pr_value = inp->def_send.sinfo_timetolive;
@@ -3080,6 +3119,97 @@ flags_out:
}
break;
}
+ case SCTP_PEER_ADDR_THLDS:
+ {
+ struct sctp_paddrthlds *thlds;
+ struct sctp_nets *net;
+
+ SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, *optsize);
+ SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
+
+ net = NULL;
+ if (stcb) {
+ net = sctp_findnet(stcb, (struct sockaddr *)&thlds->spt_address);
+ } else {
+ /*
+ * We increment here since
+ * sctp_findassociation_ep_addr() wil do a
+ * decrement if it finds the stcb as long as
+ * the locked tcb (last argument) is NOT a
+ * TCB.. aka NULL.
+ */
+ SCTP_INP_INCR_REF(inp);
+ stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&thlds->spt_address, &net, NULL, NULL);
+ if (stcb == NULL) {
+ SCTP_INP_DECR_REF(inp);
+ }
+ }
+ if (stcb && (net == NULL)) {
+ struct sockaddr *sa;
+
+ sa = (struct sockaddr *)&thlds->spt_address;
+#ifdef INET
+ if (sa->sa_family == AF_INET) {
+ struct sockaddr_in *sin;
+
+ sin = (struct sockaddr_in *)sa;
+ if (sin->sin_addr.s_addr) {
+ error = EINVAL;
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
+ break;
+ }
+ } else
+#endif
+#ifdef INET6
+ if (sa->sa_family == AF_INET6) {
+ struct sockaddr_in6 *sin6;
+
+ sin6 = (struct sockaddr_in6 *)sa;
+ if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
+ error = EINVAL;
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
+ break;
+ }
+ } else
+#endif
+ {
+ error = EAFNOSUPPORT;
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
+ break;
+ }
+ }
+ if (stcb) {
+ if (net) {
+ thlds->spt_pathmaxrxt = net->failure_threshold;
+ thlds->spt_pathpfthld = net->pf_threshold;
+ } else {
+ thlds->spt_pathmaxrxt = stcb->asoc.def_net_failure;
+ thlds->spt_pathpfthld = stcb->asoc.def_net_pf_threshold;
+ }
+ thlds->spt_assoc_id = sctp_get_associd(stcb);
+ SCTP_TCB_UNLOCK(stcb);
+ } else {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC)) {
+ /* Use endpoint defaults */
+ SCTP_INP_RLOCK(inp);
+ thlds->spt_pathmaxrxt = inp->sctp_ep.def_net_failure;
+ thlds->spt_pathpfthld = inp->sctp_ep.def_net_pf_threshold;
+ SCTP_INP_RUNLOCK(inp);
+ } else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ }
+ }
+ if (error == 0) {
+ *optsize = sizeof(struct sctp_paddrthlds);
+ }
+ break;
+ }
default:
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
error = ENOPROTOOPT;
@@ -3138,6 +3268,12 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
*/
if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
/* only valid for bound all sockets */
+ if ((SCTP_BASE_SYSCTL(sctp_auto_asconf) == 0) &&
+ (*mopt != 0)) {
+ /* forbidden by admin */
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EPERM);
+ return (EPERM);
+ }
set_opt = SCTP_PCB_FLAGS_AUTO_ASCONF;
} else {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
@@ -3252,7 +3388,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
stcb->asoc.sctp_cmt_on_off = av->assoc_value;
SCTP_TCB_UNLOCK(stcb);
} else {
- if ((av->assoc_id == SCTP_FUTURE_ASSOC) ||
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (av->assoc_id == SCTP_FUTURE_ASSOC) ||
(av->assoc_id == SCTP_ALL_ASSOC)) {
SCTP_INP_WLOCK(inp);
inp->sctp_cmt_on_off = av->assoc_value;
@@ -3265,8 +3403,8 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_TCB_LOCK(stcb);
stcb->asoc.sctp_cmt_on_off = av->assoc_value;
SCTP_TCB_UNLOCK(stcb);
- SCTP_INP_RUNLOCK(inp);
}
+ SCTP_INP_RUNLOCK(inp);
}
}
} else {
@@ -3299,7 +3437,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
SCTP_TCB_UNLOCK(stcb);
} else {
- if ((av->assoc_id == SCTP_FUTURE_ASSOC) ||
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (av->assoc_id == SCTP_FUTURE_ASSOC) ||
(av->assoc_id == SCTP_ALL_ASSOC)) {
SCTP_INP_WLOCK(inp);
inp->sctp_ep.sctp_default_cc_module = av->assoc_value;
@@ -3379,7 +3519,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
SCTP_TCB_UNLOCK(stcb);
} else {
- if ((av->assoc_id == SCTP_FUTURE_ASSOC) ||
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (av->assoc_id == SCTP_FUTURE_ASSOC) ||
(av->assoc_id == SCTP_ALL_ASSOC)) {
SCTP_INP_WLOCK(inp);
inp->sctp_ep.sctp_default_ss_module = av->assoc_value;
@@ -3453,7 +3595,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
stcb->asoc.context = av->assoc_value;
SCTP_TCB_UNLOCK(stcb);
} else {
- if ((av->assoc_id == SCTP_FUTURE_ASSOC) ||
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (av->assoc_id == SCTP_FUTURE_ASSOC) ||
(av->assoc_id == SCTP_ALL_ASSOC)) {
SCTP_INP_WLOCK(inp);
inp->sctp_context = av->assoc_value;
@@ -3519,7 +3663,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
SCTP_TCB_UNLOCK(stcb);
} else {
- if ((sack->sack_assoc_id == SCTP_FUTURE_ASSOC) ||
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (sack->sack_assoc_id == SCTP_FUTURE_ASSOC) ||
(sack->sack_assoc_id == SCTP_ALL_ASSOC)) {
SCTP_INP_WLOCK(inp);
if (sack->sack_delay) {
@@ -3614,7 +3760,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
error = sctp_insert_sharedkey(shared_keys, shared_key);
SCTP_TCB_UNLOCK(stcb);
} else {
- if ((sca->sca_assoc_id == SCTP_FUTURE_ASSOC) ||
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (sca->sca_assoc_id == SCTP_FUTURE_ASSOC) ||
(sca->sca_assoc_id == SCTP_ALL_ASSOC)) {
SCTP_INP_WLOCK(inp);
shared_keys = &inp->sctp_ep.shared_keys;
@@ -3758,7 +3906,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
SCTP_TCB_UNLOCK(stcb);
} else {
- if ((scact->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (scact->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
(scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
SCTP_INP_WLOCK(inp);
if (sctp_auth_setactivekey_ep(inp, scact->scact_keynumber)) {
@@ -3795,7 +3945,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
SCTP_TCB_UNLOCK(stcb);
} else {
- if ((scdel->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (scdel->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
(scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
SCTP_INP_WLOCK(inp);
if (sctp_delete_sharedkey_ep(inp, scdel->scact_keynumber)) {
@@ -3832,7 +3984,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
SCTP_TCB_UNLOCK(stcb);
} else {
- if ((keyid->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (keyid->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
(keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
SCTP_INP_WLOCK(inp);
if (sctp_deact_sharedkey_ep(inp, keyid->scact_keynumber)) {
@@ -4098,7 +4252,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
stcb->asoc.max_burst = av->assoc_value;
SCTP_TCB_UNLOCK(stcb);
} else {
- if ((av->assoc_id == SCTP_FUTURE_ASSOC) ||
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (av->assoc_id == SCTP_FUTURE_ASSOC) ||
(av->assoc_id == SCTP_ALL_ASSOC)) {
SCTP_INP_WLOCK(inp);
inp->sctp_ep.max_burst = av->assoc_value;
@@ -4138,7 +4294,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
SCTP_TCB_UNLOCK(stcb);
} else {
- if (av->assoc_id == SCTP_FUTURE_ASSOC) {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (av->assoc_id == SCTP_FUTURE_ASSOC)) {
SCTP_INP_WLOCK(inp);
/*
* FIXME MT: I think this is not in
@@ -4346,7 +4504,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
SCTP_TCB_UNLOCK(stcb);
} else {
- if ((s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC) ||
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC) ||
(s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
SCTP_INP_WLOCK(inp);
memcpy(&inp->def_send, s_info, min(optsize, sizeof(inp->def_send)));
@@ -4368,7 +4528,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
break;
}
case SCTP_PEER_ADDR_PARAMS:
- /* Applys to the specific association */
+ /* Applies to the specific association */
{
struct sctp_paddrparams *paddrp;
struct sctp_nets *net;
@@ -4459,29 +4619,33 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
ovh = SCTP_MED_V4_OVERHEAD;
}
- if (paddrp->spp_hbinterval)
- stcb->asoc.heart_beat_delay = paddrp->spp_hbinterval;
- else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO)
- stcb->asoc.heart_beat_delay = 0;
-
/* network sets ? */
if (net) {
/************************NET SPECIFIC SET ******************/
- if (paddrp->spp_flags & SPP_HB_DEMAND) {
- /* on demand HB */
- if (sctp_send_hb(stcb, 1, net, SCTP_SO_LOCKED) < 0) {
- /* asoc destroyed */
- SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
- error = EINVAL;
- break;
- }
- }
if (paddrp->spp_flags & SPP_HB_DISABLE) {
+ if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
+ !(net->dest_state & SCTP_ADDR_NOHB)) {
+ sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
+ SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
+ }
net->dest_state |= SCTP_ADDR_NOHB;
}
if (paddrp->spp_flags & SPP_HB_ENABLE) {
+ if (paddrp->spp_hbinterval) {
+ net->heart_beat_delay = paddrp->spp_hbinterval;
+ } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
+ net->heart_beat_delay = 0;
+ }
+ sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
+ SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
net->dest_state &= ~SCTP_ADDR_NOHB;
}
+ if (paddrp->spp_flags & SPP_HB_DEMAND) {
+ /* on demand HB */
+ sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
+ }
if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
@@ -4499,31 +4663,108 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
}
}
- if (paddrp->spp_pathmaxrxt)
- net->failure_threshold = paddrp->spp_pathmaxrxt;
-#ifdef INET
- if (paddrp->spp_flags & SPP_IPV4_TOS) {
- if (net->ro._l_addr.sin.sin_family == AF_INET) {
- net->tos_flowlabel = paddrp->spp_ipv4_tos & 0x000000fc;
+ if (paddrp->spp_pathmaxrxt) {
+ if (net->dest_state & SCTP_ADDR_PF) {
+ if (net->error_count > paddrp->spp_pathmaxrxt) {
+ net->dest_state &= ~SCTP_ADDR_PF;
+ }
+ } else {
+ if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
+ (net->error_count > net->pf_threshold)) {
+ net->dest_state |= SCTP_ADDR_PF;
+ sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
+ sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
+ }
}
+ if (net->dest_state & SCTP_ADDR_REACHABLE) {
+ if (net->error_count > paddrp->spp_pathmaxrxt) {
+ net->dest_state &= ~SCTP_ADDR_REACHABLE;
+ sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, SCTP_RESPONSE_TO_USER_REQ, net, SCTP_SO_LOCKED);
+ }
+ } else {
+ if (net->error_count <= paddrp->spp_pathmaxrxt) {
+ net->dest_state |= SCTP_ADDR_REACHABLE;
+ sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, SCTP_RESPONSE_TO_USER_REQ, net, SCTP_SO_LOCKED);
+ }
+ }
+ net->failure_threshold = paddrp->spp_pathmaxrxt;
+ }
+ if (paddrp->spp_flags & SPP_DSCP) {
+ net->dscp = paddrp->spp_dscp << 2;
+ net->dscp |= 0x01;
}
-#endif
#ifdef INET6
if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
- if (net->ro._l_addr.sin6.sin6_family == AF_INET6) {
- net->tos_flowlabel = paddrp->spp_ipv6_flowlabel;
+ if (net->ro._l_addr.sa.sa_family == AF_INET6) {
+ net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
+ net->flowlabel |= 0x80000000;
}
}
#endif
} else {
/************************ASSOC ONLY -- NO NET SPECIFIC SET ******************/
- if (paddrp->spp_pathmaxrxt)
+ if (paddrp->spp_pathmaxrxt) {
stcb->asoc.def_net_failure = paddrp->spp_pathmaxrxt;
-
+ TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
+ if (net->dest_state & SCTP_ADDR_PF) {
+ if (net->error_count > paddrp->spp_pathmaxrxt) {
+ net->dest_state &= ~SCTP_ADDR_PF;
+ }
+ } else {
+ if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
+ (net->error_count > net->pf_threshold)) {
+ net->dest_state |= SCTP_ADDR_PF;
+ sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
+ sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
+ }
+ }
+ if (net->dest_state & SCTP_ADDR_REACHABLE) {
+ if (net->error_count > paddrp->spp_pathmaxrxt) {
+ net->dest_state &= ~SCTP_ADDR_REACHABLE;
+ sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, SCTP_RESPONSE_TO_USER_REQ, net, SCTP_SO_LOCKED);
+ }
+ } else {
+ if (net->error_count <= paddrp->spp_pathmaxrxt) {
+ net->dest_state |= SCTP_ADDR_REACHABLE;
+ sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, SCTP_RESPONSE_TO_USER_REQ, net, SCTP_SO_LOCKED);
+ }
+ }
+ net->failure_threshold = paddrp->spp_pathmaxrxt;
+ }
+ }
if (paddrp->spp_flags & SPP_HB_ENABLE) {
+ if (paddrp->spp_hbinterval) {
+ stcb->asoc.heart_beat_delay = paddrp->spp_hbinterval;
+ } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
+ stcb->asoc.heart_beat_delay = 0;
+ }
/* Turn back on the timer */
- stcb->asoc.hb_is_disabled = 0;
- sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
+ TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
+ if (paddrp->spp_hbinterval) {
+ net->heart_beat_delay = paddrp->spp_hbinterval;
+ } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
+ net->heart_beat_delay = 0;
+ }
+ if (net->dest_state & SCTP_ADDR_NOHB) {
+ net->dest_state &= ~SCTP_ADDR_NOHB;
+ }
+ sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
+ SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
+ }
+ }
+ if (paddrp->spp_flags & SPP_HB_DISABLE) {
+ /* Turn back on the timer */
+ TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
+ if (!(net->dest_state & SCTP_ADDR_NOHB)) {
+ net->dest_state |= SCTP_ADDR_NOHB;
+ if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED)) {
+ sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
+ }
+ }
+ }
}
if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
@@ -4546,48 +4787,33 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
}
}
- if (paddrp->spp_flags & SPP_HB_DISABLE) {
- int cnt_of_unconf = 0;
- struct sctp_nets *lnet;
-
- stcb->asoc.hb_is_disabled = 1;
- TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
- if (lnet->dest_state & SCTP_ADDR_UNCONFIRMED) {
- cnt_of_unconf++;
- }
- }
- /*
- * stop the timer ONLY if we
- * have no unconfirmed
- * addresses
- */
- if (cnt_of_unconf == 0) {
- TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
- sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
- SCTP_FROM_SCTP_USRREQ + SCTP_LOC_11);
- }
+ if (paddrp->spp_flags & SPP_DSCP) {
+ TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
+ net->dscp = paddrp->spp_dscp << 2;
+ net->dscp |= 0x01;
}
+ stcb->asoc.default_dscp = paddrp->spp_dscp << 2;
+ stcb->asoc.default_dscp |= 0x01;
}
- if (paddrp->spp_flags & SPP_HB_ENABLE) {
- /* start up the timer. */
+#ifdef INET6
+ if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
- sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
+ if (net->ro._l_addr.sa.sa_family == AF_INET6) {
+ net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
+ net->flowlabel |= 0x80000000;
+ }
}
+ stcb->asoc.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
+ stcb->asoc.default_flowlabel |= 0x80000000;
}
-#ifdef INET
- if (paddrp->spp_flags & SPP_IPV4_TOS)
- stcb->asoc.default_tos = paddrp->spp_ipv4_tos & 0x000000fc;
#endif
-#ifdef INET6
- if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL)
- stcb->asoc.default_flowlabel = paddrp->spp_ipv6_flowlabel;
-#endif
-
}
SCTP_TCB_UNLOCK(stcb);
} else {
/************************NO TCB, SET TO default stuff ******************/
- if (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC) {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC)) {
SCTP_INP_WLOCK(inp);
/*
* For the TOS/FLOWLABEL stuff you
@@ -4605,11 +4831,27 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
}
if (paddrp->spp_flags & SPP_HB_ENABLE) {
+ if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
+ inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
+ } else if (paddrp->spp_hbinterval) {
+ inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
+ }
sctp_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
-
} else if (paddrp->spp_flags & SPP_HB_DISABLE) {
sctp_feature_on(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
}
+ if (paddrp->spp_flags & SPP_DSCP) {
+ inp->sctp_ep.default_dscp = paddrp->spp_dscp << 2;
+ inp->sctp_ep.default_dscp |= 0x01;
+ }
+#ifdef INET6
+ if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
+ if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
+ inp->sctp_ep.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
+ inp->sctp_ep.default_flowlabel |= 0x80000000;
+ }
+ }
+#endif
SCTP_INP_WUNLOCK(inp);
} else {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
@@ -4649,7 +4891,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
SCTP_TCB_UNLOCK(stcb);
} else {
- if (srto->srto_assoc_id == SCTP_FUTURE_ASSOC) {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (srto->srto_assoc_id == SCTP_FUTURE_ASSOC)) {
SCTP_INP_WLOCK(inp);
if (srto->srto_initial)
new_init = srto->srto_initial;
@@ -4701,7 +4945,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
SCTP_TCB_UNLOCK(stcb);
} else {
- if (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC) {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC)) {
SCTP_INP_WLOCK(inp);
if (sasoc->sasoc_asocmaxrxt)
inp->sctp_ep.max_send_times = sasoc->sasoc_asocmaxrxt;
@@ -4769,10 +5015,12 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
(!(net->dest_state & SCTP_ADDR_UNCONFIRMED))) {
/* Ok we need to set it */
if (sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net) == 0) {
- if (net->dest_state & SCTP_ADDR_SWITCH_PRIMARY) {
- net->dest_state |= SCTP_ADDR_DOUBLE_SWITCH;
+ if ((stcb->asoc.alternate) &&
+ (!(net->dest_state & SCTP_ADDR_PF)) &&
+ (net->dest_state & SCTP_ADDR_REACHABLE)) {
+ sctp_free_remote_addr(stcb->asoc.alternate);
+ stcb->asoc.alternate = NULL;
}
- net->dest_state |= SCTP_ADDR_SWITCH_PRIMARY;
}
}
} else {
@@ -4930,7 +5178,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
error = EINVAL;
break;
}
- if (td != NULL && (error = prison_local_ip6(td->td_ucred, &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
+ if (td != NULL &&
+ (error = prison_local_ip6(td->td_ucred,
+ &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
(SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
break;
@@ -5017,13 +5267,17 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
* sender dry events
*/
if ((event_type == SCTP_PCB_FLAGS_DRYEVNT) &&
+ ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) == 0) &&
+ ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
((event->se_assoc_id == SCTP_ALL_ASSOC) ||
(event->se_assoc_id == SCTP_CURRENT_ASSOC))) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
error = ENOTSUP;
break;
}
- if ((event->se_assoc_id == SCTP_FUTURE_ASSOC) ||
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (event->se_assoc_id == SCTP_FUTURE_ASSOC) ||
(event->se_assoc_id == SCTP_ALL_ASSOC)) {
SCTP_INP_WLOCK(inp);
if (event->se_on) {
@@ -5101,7 +5355,9 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
SCTP_TCB_UNLOCK(stcb);
} else {
- if ((info->snd_assoc_id == SCTP_FUTURE_ASSOC) ||
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (info->snd_assoc_id == SCTP_FUTURE_ASSOC) ||
(info->snd_assoc_id == SCTP_ALL_ASSOC)) {
SCTP_INP_WLOCK(inp);
inp->def_send.sinfo_stream = info->snd_sid;
@@ -5147,13 +5403,17 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
if (stcb) {
stcb->asoc.def_send.sinfo_flags &= 0xfff0;
stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
+ stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
SCTP_TCB_UNLOCK(stcb);
} else {
- if ((info->pr_assoc_id == SCTP_FUTURE_ASSOC) ||
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (info->pr_assoc_id == SCTP_FUTURE_ASSOC) ||
(info->pr_assoc_id == SCTP_ALL_ASSOC)) {
SCTP_INP_WLOCK(inp);
inp->def_send.sinfo_flags &= 0xfff0;
inp->def_send.sinfo_flags |= info->pr_policy;
+ inp->def_send.sinfo_timetolive = info->pr_value;
SCTP_INP_WUNLOCK(inp);
}
if ((info->pr_assoc_id == SCTP_CURRENT_ASSOC) ||
@@ -5163,6 +5423,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_TCB_LOCK(stcb);
stcb->asoc.def_send.sinfo_flags &= 0xfff0;
stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
+ stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
SCTP_TCB_UNLOCK(stcb);
}
SCTP_INP_RUNLOCK(inp);
@@ -5170,6 +5431,148 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
break;
}
+ case SCTP_PEER_ADDR_THLDS:
+ /* Applies to the specific association */
+ {
+ struct sctp_paddrthlds *thlds;
+ struct sctp_nets *net;
+
+ SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, optsize);
+ SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
+ net = NULL;
+ if (stcb) {
+ net = sctp_findnet(stcb, (struct sockaddr *)&thlds->spt_assoc_id);
+ } else {
+ /*
+ * We increment here since
+ * sctp_findassociation_ep_addr() wil do a
+ * decrement if it finds the stcb as long as
+ * the locked tcb (last argument) is NOT a
+ * TCB.. aka NULL.
+ */
+ SCTP_INP_INCR_REF(inp);
+ stcb = sctp_findassociation_ep_addr(&inp,
+ (struct sockaddr *)&thlds->spt_assoc_id,
+ &net, NULL, NULL);
+ if (stcb == NULL) {
+ SCTP_INP_DECR_REF(inp);
+ }
+ }
+ if (stcb && (net == NULL)) {
+ struct sockaddr *sa;
+
+ sa = (struct sockaddr *)&thlds->spt_assoc_id;
+#ifdef INET
+ if (sa->sa_family == AF_INET) {
+
+ struct sockaddr_in *sin;
+
+ sin = (struct sockaddr_in *)sa;
+ if (sin->sin_addr.s_addr) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ SCTP_TCB_UNLOCK(stcb);
+ error = EINVAL;
+ break;
+ }
+ } else
+#endif
+#ifdef INET6
+ if (sa->sa_family == AF_INET6) {
+ struct sockaddr_in6 *sin6;
+
+ sin6 = (struct sockaddr_in6 *)sa;
+ if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ SCTP_TCB_UNLOCK(stcb);
+ error = EINVAL;
+ break;
+ }
+ } else
+#endif
+ {
+ error = EAFNOSUPPORT;
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
+ break;
+ }
+ }
+ if (stcb) {
+ if (net) {
+ if (net->dest_state & SCTP_ADDR_PF) {
+ if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
+ (net->failure_threshold <= thlds->spt_pathpfthld)) {
+ net->dest_state &= ~SCTP_ADDR_PF;
+ }
+ } else {
+ if ((net->failure_threshold > thlds->spt_pathpfthld) &&
+ (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
+ net->dest_state |= SCTP_ADDR_PF;
+ sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
+ sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
+ }
+ }
+ if (net->dest_state & SCTP_ADDR_REACHABLE) {
+ if (net->failure_threshold > thlds->spt_pathmaxrxt) {
+ net->dest_state &= ~SCTP_ADDR_REACHABLE;
+ sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, SCTP_RESPONSE_TO_USER_REQ, net, SCTP_SO_LOCKED);
+ }
+ } else {
+ if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
+ net->dest_state |= SCTP_ADDR_REACHABLE;
+ sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, SCTP_RESPONSE_TO_USER_REQ, net, SCTP_SO_LOCKED);
+ }
+ }
+ net->failure_threshold = thlds->spt_pathmaxrxt;
+ net->pf_threshold = thlds->spt_pathpfthld;
+ } else {
+ TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
+ if (net->dest_state & SCTP_ADDR_PF) {
+ if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
+ (net->failure_threshold <= thlds->spt_pathpfthld)) {
+ net->dest_state &= ~SCTP_ADDR_PF;
+ }
+ } else {
+ if ((net->failure_threshold > thlds->spt_pathpfthld) &&
+ (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
+ net->dest_state |= SCTP_ADDR_PF;
+ sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
+ sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
+ }
+ }
+ if (net->dest_state & SCTP_ADDR_REACHABLE) {
+ if (net->failure_threshold > thlds->spt_pathmaxrxt) {
+ net->dest_state &= ~SCTP_ADDR_REACHABLE;
+ sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, SCTP_RESPONSE_TO_USER_REQ, net, SCTP_SO_LOCKED);
+ }
+ } else {
+ if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
+ net->dest_state |= SCTP_ADDR_REACHABLE;
+ sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, SCTP_RESPONSE_TO_USER_REQ, net, SCTP_SO_LOCKED);
+ }
+ }
+ net->failure_threshold = thlds->spt_pathmaxrxt;
+ net->pf_threshold = thlds->spt_pathpfthld;
+ }
+ stcb->asoc.def_net_failure = thlds->spt_pathmaxrxt;
+ stcb->asoc.def_net_pf_threshold = thlds->spt_pathpfthld;
+ }
+ } else {
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC)) {
+ SCTP_INP_WLOCK(inp);
+ inp->sctp_ep.def_net_failure = thlds->spt_pathmaxrxt;
+ inp->sctp_ep.def_net_pf_threshold = thlds->spt_pathpfthld;
+ SCTP_INP_WUNLOCK(inp);
+ } else {
+ SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
+ error = EINVAL;
+ }
+ }
+ break;
+ }
default:
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
error = ENOPROTOOPT;
@@ -5374,15 +5777,6 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
/* Set the connected flag so we can queue data */
- SOCKBUF_LOCK(&so->so_rcv);
- so->so_rcv.sb_state &= ~SBS_CANTRCVMORE;
- SOCKBUF_UNLOCK(&so->so_rcv);
- SOCKBUF_LOCK(&so->so_snd);
- so->so_snd.sb_state &= ~SBS_CANTSENDMORE;
- SOCKBUF_UNLOCK(&so->so_snd);
- SOCK_LOCK(so);
- so->so_state &= ~SS_ISDISCONNECTING;
- SOCK_UNLOCK(so);
soisconnecting(so);
}
SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
diff --git a/sys/netinet/sctp_var.h b/sys/netinet/sctp_var.h
index e48dfe49da100..b41f5c8303de0 100644
--- a/sys/netinet/sctp_var.h
+++ b/sys/netinet/sctp_var.h
@@ -179,7 +179,6 @@ extern struct pr_usrreqs sctp_usrreqs;
if (SCTP_DECREMENT_AND_CHECK_REFCOUNT(&(__net)->ref_count)) { \
(void)SCTP_OS_TIMER_STOP(&(__net)->rxt_timer.timer); \
(void)SCTP_OS_TIMER_STOP(&(__net)->pmtu_timer.timer); \
- (void)SCTP_OS_TIMER_STOP(&(__net)->fr_timer.timer); \
if ((__net)->ro.ro_rt) { \
RTFREE((__net)->ro.ro_rt); \
(__net)->ro.ro_rt = NULL; \
@@ -189,7 +188,7 @@ extern struct pr_usrreqs sctp_usrreqs;
(__net)->ro._s_addr = NULL; \
} \
(__net)->src_addr_selected = 0; \
- (__net)->dest_state = SCTP_ADDR_NOT_REACHABLE; \
+ (__net)->dest_state &= ~SCTP_ADDR_REACHABLE; \
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_net), (__net)); \
SCTP_DECR_RADDR_COUNT(); \
} \
@@ -312,6 +311,8 @@ extern struct pr_usrreqs sctp_usrreqs;
#endif
+#define SCTP_PF_ENABLED(_net) (_net->pf_threshold < _net->failure_threshold)
+#define SCTP_NET_IS_PF(_net) (_net->pf_threshold < _net->error_count)
struct sctp_nets;
struct sctp_inpcb;
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index 9a8bd2e9dd19b..62fa0d1f2325a 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -739,15 +739,14 @@ sctp_stop_timers_for_shutdown(struct sctp_tcb *stcb)
asoc = &stcb->asoc;
- (void)SCTP_OS_TIMER_STOP(&asoc->hb_timer.timer);
(void)SCTP_OS_TIMER_STOP(&asoc->dack_timer.timer);
(void)SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer);
(void)SCTP_OS_TIMER_STOP(&asoc->asconf_timer.timer);
(void)SCTP_OS_TIMER_STOP(&asoc->autoclose_timer.timer);
(void)SCTP_OS_TIMER_STOP(&asoc->delayed_event_timer.timer);
TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
- (void)SCTP_OS_TIMER_STOP(&net->fr_timer.timer);
(void)SCTP_OS_TIMER_STOP(&net->pmtu_timer.timer);
+ (void)SCTP_OS_TIMER_STOP(&net->hb_timer.timer);
}
}
@@ -921,19 +920,22 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
asoc->sctp_cmt_on_off = m->sctp_cmt_on_off;
asoc->ecn_allowed = m->sctp_ecn_enable;
asoc->sctp_nr_sack_on_off = (uint8_t) SCTP_BASE_SYSCTL(sctp_nr_sack_on_off);
- asoc->sctp_cmt_pf = (uint8_t) SCTP_BASE_SYSCTL(sctp_cmt_pf);
+ asoc->sctp_cmt_pf = (uint8_t) 0;
asoc->sctp_frag_point = m->sctp_frag_point;
asoc->sctp_features = m->sctp_features;
-#ifdef INET
- asoc->default_tos = m->ip_inp.inp.inp_ip_tos;
-#else
- asoc->default_tos = 0;
-#endif
-
+ asoc->default_dscp = m->sctp_ep.default_dscp;
#ifdef INET6
- asoc->default_flowlabel = ((struct in6pcb *)m)->in6p_flowinfo;
-#else
- asoc->default_flowlabel = 0;
+ if (m->sctp_ep.default_flowlabel) {
+ asoc->default_flowlabel = m->sctp_ep.default_flowlabel;
+ } else {
+ if (m->ip_inp.inp.inp_flags & IN6P_AUTOFLOWLABEL) {
+ asoc->default_flowlabel = sctp_select_initial_TSN(&m->sctp_ep);
+ asoc->default_flowlabel &= 0x000fffff;
+ asoc->default_flowlabel |= 0x80000000;
+ } else {
+ asoc->default_flowlabel = 0;
+ }
+ }
#endif
asoc->sb_send_resv = 0;
if (override_tag) {
@@ -946,11 +948,6 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
asoc->peer_vtag_nonce = sctp_select_a_tag(m, stcb->sctp_ep->sctp_lport, stcb->rport, 0);
asoc->vrf_id = vrf_id;
- if (sctp_is_feature_on(m, SCTP_PCB_FLAGS_DONOT_HEARTBEAT))
- asoc->hb_is_disabled = 1;
- else
- asoc->hb_is_disabled = 0;
-
#ifdef SCTP_ASOCLOG_OF_TSNS
asoc->tsn_in_at = 0;
asoc->tsn_out_at = 0;
@@ -989,6 +986,7 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
asoc->max_init_times = m->sctp_ep.max_init_times;
asoc->max_send_times = m->sctp_ep.max_send_times;
asoc->def_net_failure = m->sctp_ep.def_net_failure;
+ asoc->def_net_pf_threshold = m->sctp_ep.def_net_pf_threshold;
asoc->free_chunk_cnt = 0;
asoc->iam_blocking = 0;
@@ -1632,11 +1630,10 @@ sctp_timeout_handler(void *t)
case SCTP_TIMER_TYPE_RECV:
if ((stcb == NULL) || (inp == NULL)) {
break;
- } {
- SCTP_STAT_INCR(sctps_timosack);
- stcb->asoc.timosack++;
- sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED);
}
+ SCTP_STAT_INCR(sctps_timosack);
+ stcb->asoc.timosack++;
+ sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED);
#ifdef SCTP_AUDITING_ENABLED
sctp_auditing(4, inp, stcb, net);
#endif
@@ -1658,33 +1655,20 @@ sctp_timeout_handler(void *t)
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SHUT_TMR, SCTP_SO_NOT_LOCKED);
break;
case SCTP_TIMER_TYPE_HEARTBEAT:
- {
- struct sctp_nets *lnet;
- int cnt_of_unconf = 0;
-
- if ((stcb == NULL) || (inp == NULL)) {
- break;
- }
- SCTP_STAT_INCR(sctps_timoheartbeat);
- stcb->asoc.timoheartbeat++;
- TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
- if ((lnet->dest_state & SCTP_ADDR_UNCONFIRMED) &&
- (lnet->dest_state & SCTP_ADDR_REACHABLE)) {
- cnt_of_unconf++;
- }
- }
- if (cnt_of_unconf == 0) {
- if (sctp_heartbeat_timer(inp, stcb, lnet,
- cnt_of_unconf)) {
- /* no need to unlock on tcb its gone */
- goto out_decr;
- }
- }
+ if ((stcb == NULL) || (inp == NULL) || (net == NULL)) {
+ break;
+ }
+ SCTP_STAT_INCR(sctps_timoheartbeat);
+ stcb->asoc.timoheartbeat++;
+ if (sctp_heartbeat_timer(inp, stcb, net)) {
+ /* no need to unlock on tcb its gone */
+ goto out_decr;
+ }
#ifdef SCTP_AUDITING_ENABLED
- sctp_auditing(4, inp, stcb, lnet);
+ sctp_auditing(4, inp, stcb, net);
#endif
- sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT,
- stcb->sctp_ep, stcb, lnet);
+ if (!(net->dest_state & SCTP_ADDR_NOHB)) {
+ sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_HB_TMR, SCTP_SO_NOT_LOCKED);
}
break;
@@ -1780,14 +1764,6 @@ sctp_timeout_handler(void *t)
SCTP_STAT_INCR(sctps_timostrmrst);
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_TMR, SCTP_SO_NOT_LOCKED);
break;
- case SCTP_TIMER_TYPE_EARLYFR:
- /* Need to do FR of things for net */
- if ((stcb == NULL) || (inp == NULL)) {
- break;
- }
- SCTP_STAT_INCR(sctps_timoearlyfr);
- sctp_early_fr_timer(inp, stcb, net);
- break;
case SCTP_TIMER_TYPE_ASCONF:
if ((stcb == NULL) || (inp == NULL)) {
break;
@@ -1898,7 +1874,7 @@ void
sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
struct sctp_nets *net)
{
- int to_ticks;
+ uint32_t to_ticks;
struct sctp_timer *tmr;
if ((t_type != SCTP_TIMER_TYPE_ADDR_WQ) && (inp == NULL))
@@ -1985,71 +1961,38 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
* though we use a different timer. We also add the HB timer
* PLUS a random jitter.
*/
- if ((inp == NULL) || (stcb == NULL)) {
+ if ((inp == NULL) || (stcb == NULL) || (net == NULL)) {
return;
} else {
uint32_t rndval;
- uint8_t this_random;
- int cnt_of_unconf = 0;
- struct sctp_nets *lnet;
+ uint32_t jitter;
- TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
- if ((lnet->dest_state & SCTP_ADDR_UNCONFIRMED) &&
- (lnet->dest_state & SCTP_ADDR_REACHABLE)) {
- cnt_of_unconf++;
- }
- }
- if (cnt_of_unconf) {
- net = lnet = NULL;
- (void)sctp_heartbeat_timer(inp, stcb, lnet, cnt_of_unconf);
- }
- if (stcb->asoc.hb_random_idx > 3) {
- rndval = sctp_select_initial_TSN(&inp->sctp_ep);
- memcpy(stcb->asoc.hb_random_values, &rndval,
- sizeof(stcb->asoc.hb_random_values));
- stcb->asoc.hb_random_idx = 0;
- }
- this_random = stcb->asoc.hb_random_values[stcb->asoc.hb_random_idx];
- stcb->asoc.hb_random_idx++;
- stcb->asoc.hb_ect_randombit = 0;
- /*
- * this_random will be 0 - 256 ms RTO is in ms.
- */
- if ((stcb->asoc.hb_is_disabled) &&
- (cnt_of_unconf == 0)) {
+ if ((net->dest_state & SCTP_ADDR_NOHB) &&
+ !(net->dest_state & SCTP_ADDR_UNCONFIRMED)) {
return;
}
- if (net) {
- int delay;
-
- delay = stcb->asoc.heart_beat_delay;
- TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
- if ((lnet->dest_state & SCTP_ADDR_UNCONFIRMED) &&
- ((lnet->dest_state & SCTP_ADDR_OUT_OF_SCOPE) == 0) &&
- (lnet->dest_state & SCTP_ADDR_REACHABLE)) {
- delay = 0;
- }
- }
- if (net->RTO == 0) {
- /* Never been checked */
- to_ticks = this_random + stcb->asoc.initial_rto + delay;
- } else {
- /* set rto_val to the ms */
- to_ticks = delay + net->RTO + this_random;
- }
+ if (net->RTO == 0) {
+ to_ticks = stcb->asoc.initial_rto;
} else {
- if (cnt_of_unconf) {
- to_ticks = this_random + stcb->asoc.initial_rto;
- } else {
- to_ticks = stcb->asoc.heart_beat_delay + this_random + stcb->asoc.initial_rto;
- }
+ to_ticks = net->RTO;
+ }
+ rndval = sctp_select_initial_TSN(&inp->sctp_ep);
+ jitter = rndval % to_ticks;
+ if (jitter >= (to_ticks >> 1)) {
+ to_ticks = to_ticks + (jitter - (to_ticks >> 1));
+ } else {
+ to_ticks = to_ticks - jitter;
+ }
+ if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
+ !(net->dest_state & SCTP_ADDR_PF)) {
+ to_ticks += net->heart_beat_delay;
}
/*
* Now we must convert the to_ticks that are now in
* ms to ticks.
*/
to_ticks = MSEC_TO_TICKS(to_ticks);
- tmr = &stcb->asoc.hb_timer;
+ tmr = &net->hb_timer;
}
break;
case SCTP_TIMER_TYPE_COOKIE:
@@ -2150,35 +2093,6 @@ sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
}
tmr = &stcb->asoc.strreset_timer;
break;
-
- case SCTP_TIMER_TYPE_EARLYFR:
- {
- unsigned int msec;
-
- if ((stcb == NULL) || (net == NULL)) {
- return;
- }
- if (net->flight_size > net->cwnd) {
- /* no need to start */
- return;
- }
- SCTP_STAT_INCR(sctps_earlyfrstart);
- if (net->lastsa == 0) {
- /* Hmm no rtt estimate yet? */
- msec = stcb->asoc.initial_rto >> 2;
- } else {
- msec = ((net->lastsa >> 2) + net->lastsv) >> 1;
- }
- if (msec < SCTP_BASE_SYSCTL(sctp_early_fr_msec)) {
- msec = SCTP_BASE_SYSCTL(sctp_early_fr_msec);
- if (msec < SCTP_MINFR_MSEC_FLOOR) {
- msec = SCTP_MINFR_MSEC_FLOOR;
- }
- }
- to_ticks = MSEC_TO_TICKS(msec);
- tmr = &net->fr_timer;
- }
- break;
case SCTP_TIMER_TYPE_ASCONF:
/*
* Here the timer comes from the stcb but its value is from
@@ -2273,13 +2187,6 @@ sctp_timer_stop(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
case SCTP_TIMER_TYPE_ADDR_WQ:
tmr = &SCTP_BASE_INFO(addr_wq_timer);
break;
- case SCTP_TIMER_TYPE_EARLYFR:
- if ((stcb == NULL) || (net == NULL)) {
- return;
- }
- tmr = &net->fr_timer;
- SCTP_STAT_INCR(sctps_earlyfrstop);
- break;
case SCTP_TIMER_TYPE_SEND:
if ((stcb == NULL) || (net == NULL)) {
return;
@@ -2305,10 +2212,10 @@ sctp_timer_stop(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
tmr = &net->rxt_timer;
break;
case SCTP_TIMER_TYPE_HEARTBEAT:
- if (stcb == NULL) {
+ if ((stcb == NULL) || (net == NULL)) {
return;
}
- tmr = &stcb->asoc.hb_timer;
+ tmr = &net->hb_timer;
break;
case SCTP_TIMER_TYPE_COOKIE:
if ((stcb == NULL) || (net == NULL)) {
@@ -3715,10 +3622,14 @@ sctp_abort_notification(struct sctp_tcb *stcb, int error, int so_locked
#endif
)
{
-
if (stcb == NULL) {
return;
}
+ if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
+ ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
+ (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED))) {
+ stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_WAS_ABORTED;
+ }
if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
(stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) {
@@ -3726,11 +3637,6 @@ sctp_abort_notification(struct sctp_tcb *stcb, int error, int so_locked
}
/* Tell them we lost the asoc */
sctp_report_all_outbound(stcb, 1, so_locked);
- if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
- ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
- (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED))) {
- stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_WAS_ABORTED;
- }
sctp_ulp_notify(SCTP_NOTIFY_ASSOC_ABORTED, stcb, error, NULL, so_locked);
}
@@ -5191,17 +5097,6 @@ restart_nosblocks:
*/
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET);
error = ECONNRESET;
- /*
- * You get this once if you are
- * active open side
- */
- if (!(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
- /*
- * Remove flag if on the
- * active open side
- */
- inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAS_ABORTED;
- }
}
so->so_state &= ~(SS_ISCONNECTING |
SS_ISDISCONNECTING |
@@ -5211,8 +5106,6 @@ restart_nosblocks:
if ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) == 0) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOTCONN);
error = ENOTCONN;
- } else {
- inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAS_CONNECTED;
}
}
goto out;
@@ -5245,18 +5138,6 @@ restart_nosblocks:
*/
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET);
error = ECONNRESET;
- /*
- * You get this once if you
- * are active open side
- */
- if (!(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
- /*
- * Remove flag if on
- * the active open
- * side
- */
- inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAS_ABORTED;
- }
}
so->so_state &= ~(SS_ISCONNECTING |
SS_ISDISCONNECTING |
@@ -5266,8 +5147,6 @@ restart_nosblocks:
if ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) == 0) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOTCONN);
error = ENOTCONN;
- } else {
- inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAS_CONNECTED;
}
}
goto out;
@@ -6201,6 +6080,15 @@ sctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr,
struct sockaddr *sa;
size_t incr = 0;
+#ifdef INET
+ struct sockaddr_in *sin;
+
+#endif
+#ifdef INET6
+ struct sockaddr_in6 *sin6;
+
+#endif
+
sa = addr;
inp = stcb->sctp_ep;
*error = 0;
@@ -6209,7 +6097,16 @@ sctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr,
#ifdef INET
case AF_INET:
incr = sizeof(struct sockaddr_in);
- if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
+ sin = (struct sockaddr_in *)sa;
+ if ((sin->sin_addr.s_addr == INADDR_ANY) ||
+ (sin->sin_addr.s_addr == INADDR_BROADCAST) ||
+ IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
+ (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_7);
+ *error = EINVAL;
+ goto out_now;
+ }
+ if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
/* assoc gone no un-lock */
SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS);
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_7);
@@ -6222,7 +6119,15 @@ sctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr,
#ifdef INET6
case AF_INET6:
incr = sizeof(struct sockaddr_in6);
- if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
+ sin6 = (struct sockaddr_in6 *)sa;
+ if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
+ IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
+ SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
+ (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_8);
+ *error = EINVAL;
+ goto out_now;
+ }
+ if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
/* assoc gone no un-lock */
SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS);
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_8);
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index e3e9aa6c745af..b1a8b335cabb1 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -195,7 +195,7 @@ SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, recvbuf_inc, CTLFLAG_RW,
&VNET_NAME(tcp_autorcvbuf_inc), 0,
"Incrementor step size of automatic receive buffer");
-VNET_DEFINE(int, tcp_autorcvbuf_max) = 256*1024;
+VNET_DEFINE(int, tcp_autorcvbuf_max) = 2*1024*1024;
#define V_tcp_autorcvbuf_max VNET(tcp_autorcvbuf_max)
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, recvbuf_max, CTLFLAG_RW,
&VNET_NAME(tcp_autorcvbuf_max), 0,
@@ -573,19 +573,14 @@ tcp_input(struct mbuf *m, int off0)
uint8_t sig_checked = 0;
#endif
uint8_t iptos = 0;
-#ifdef INET
#ifdef IPFIREWALL_FORWARD
struct m_tag *fwd_tag;
#endif
-#endif /* INET */
#ifdef INET6
struct ip6_hdr *ip6 = NULL;
int isipv6;
#else
const void *ip6 = NULL;
-#if (defined(INET) && defined(IPFIREWALL_FORWARD)) || defined(TCPDEBUG)
- const int isipv6 = 0;
-#endif
#endif /* INET6 */
struct tcpopt to; /* options in this segment */
char *s = NULL; /* address and port logging */
@@ -776,14 +771,55 @@ findpcb:
}
#endif
-#ifdef INET
#ifdef IPFIREWALL_FORWARD
/*
* Grab info from PACKET_TAG_IPFORWARD tag prepended to the chain.
*/
fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
+#endif /* IPFIREWALL_FORWARD */
+
+#ifdef INET6
+#ifdef IPFIREWALL_FORWARD
+ if (isipv6 && fwd_tag != NULL) {
+ struct sockaddr_in6 *next_hop6;
- if (fwd_tag != NULL && isipv6 == 0) { /* IPv6 support is not yet */
+ next_hop6 = (struct sockaddr_in6 *)(fwd_tag + 1);
+ /*
+ * Transparently forwarded. Pretend to be the destination.
+ * Already got one like this?
+ */
+ inp = in6_pcblookup_mbuf(&V_tcbinfo,
+ &ip6->ip6_src, th->th_sport, &ip6->ip6_dst, th->th_dport,
+ INPLOOKUP_WLOCKPCB, m->m_pkthdr.rcvif, m);
+ if (!inp) {
+ /*
+ * It's new. Try to find the ambushing socket.
+ * Because we've rewritten the destination address,
+ * any hardware-generated hash is ignored.
+ */
+ inp = in6_pcblookup(&V_tcbinfo, &ip6->ip6_src,
+ th->th_sport, &next_hop6->sin6_addr,
+ next_hop6->sin6_port ? ntohs(next_hop6->sin6_port) :
+ th->th_dport, INPLOOKUP_WILDCARD |
+ INPLOOKUP_WLOCKPCB, m->m_pkthdr.rcvif);
+ }
+ /* Remove the tag from the packet. We don't need it anymore. */
+ m_tag_delete(m, fwd_tag);
+ } else
+#endif /* IPFIREWALL_FORWARD */
+ if (isipv6) {
+ inp = in6_pcblookup_mbuf(&V_tcbinfo, &ip6->ip6_src,
+ th->th_sport, &ip6->ip6_dst, th->th_dport,
+ INPLOOKUP_WILDCARD | INPLOOKUP_WLOCKPCB,
+ m->m_pkthdr.rcvif, m);
+ }
+#endif /* INET6 */
+#if defined(INET6) && defined(INET)
+ else
+#endif
+#ifdef INET
+#ifdef IPFIREWALL_FORWARD
+ if (fwd_tag != NULL) {
struct sockaddr_in *next_hop;
next_hop = (struct sockaddr_in *)(fwd_tag+1);
@@ -810,25 +846,11 @@ findpcb:
m_tag_delete(m, fwd_tag);
} else
#endif /* IPFIREWALL_FORWARD */
+ inp = in_pcblookup_mbuf(&V_tcbinfo, ip->ip_src,
+ th->th_sport, ip->ip_dst, th->th_dport,
+ INPLOOKUP_WILDCARD | INPLOOKUP_WLOCKPCB,
+ m->m_pkthdr.rcvif, m);
#endif /* INET */
- {
-#ifdef INET6
- if (isipv6)
- inp = in6_pcblookup_mbuf(&V_tcbinfo, &ip6->ip6_src,
- th->th_sport, &ip6->ip6_dst, th->th_dport,
- INPLOOKUP_WILDCARD | INPLOOKUP_WLOCKPCB,
- m->m_pkthdr.rcvif, m);
-#endif
-#if defined(INET) && defined(INET6)
- else
-#endif
-#ifdef INET
- inp = in_pcblookup_mbuf(&V_tcbinfo, ip->ip_src,
- th->th_sport, ip->ip_dst, th->th_dport,
- INPLOOKUP_WILDCARD | INPLOOKUP_WLOCKPCB,
- m->m_pkthdr.rcvif, m);
-#endif
- }
/*
* If the INPCB does not exist then all data in the incoming
@@ -1003,11 +1025,11 @@ relocked:
#ifdef TCPDEBUG
if (so->so_options & SO_DEBUG) {
ostate = tp->t_state;
- if (isipv6) {
#ifdef INET6
+ if (isipv6) {
bcopy((char *)ip6, (char *)tcp_saveipgen, sizeof(*ip6));
-#endif
} else
+#endif
bcopy((char *)ip, (char *)tcp_saveipgen, sizeof(*ip));
tcp_savetcp = *th;
}
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index 572a491be0db1..702eed330f157 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -117,7 +117,7 @@ SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, sendbuf_inc, CTLFLAG_RW,
&VNET_NAME(tcp_autosndbuf_inc), 0,
"Incrementor step size of automatic send buffer");
-VNET_DEFINE(int, tcp_autosndbuf_max) = 256*1024;
+VNET_DEFINE(int, tcp_autosndbuf_max) = 2*1024*1024;
#define V_tcp_autosndbuf_max VNET(tcp_autosndbuf_max)
SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, sendbuf_max, CTLFLAG_RW,
&VNET_NAME(tcp_autosndbuf_max), 0,
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index 28eb8fd19f88b..701bc358ab9e1 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -441,28 +441,6 @@ udp_input(struct mbuf *m, int off)
} else
UDPSTAT_INC(udps_nosum);
-#ifdef IPFIREWALL_FORWARD
- /*
- * Grab info from PACKET_TAG_IPFORWARD tag prepended to the chain.
- */
- fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
- if (fwd_tag != NULL) {
- struct sockaddr_in *next_hop;
-
- /*
- * Do the hack.
- */
- next_hop = (struct sockaddr_in *)(fwd_tag + 1);
- ip->ip_dst = next_hop->sin_addr;
- uh->uh_dport = ntohs(next_hop->sin_port);
-
- /*
- * Remove the tag from the packet. We don't need it anymore.
- */
- m_tag_delete(m, fwd_tag);
- }
-#endif
-
if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) ||
in_broadcast(ip->ip_dst, ifp)) {
struct inpcb *last;
@@ -568,9 +546,41 @@ udp_input(struct mbuf *m, int off)
/*
* Locate pcb for datagram.
*/
- inp = in_pcblookup_mbuf(&V_udbinfo, ip->ip_src, uh->uh_sport,
- ip->ip_dst, uh->uh_dport, INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB,
- ifp, m);
+#ifdef IPFIREWALL_FORWARD
+ /*
+ * Grab info from PACKET_TAG_IPFORWARD tag prepended to the chain.
+ */
+ fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
+ if (fwd_tag != NULL) {
+ struct sockaddr_in *next_hop;
+
+ next_hop = (struct sockaddr_in *)(fwd_tag + 1);
+
+ /*
+ * Transparently forwarded. Pretend to be the destination.
+ * Already got one like this?
+ */
+ inp = in_pcblookup_mbuf(&V_udbinfo, ip->ip_src, uh->uh_sport,
+ ip->ip_dst, uh->uh_dport, INPLOOKUP_RLOCKPCB, ifp, m);
+ if (!inp) {
+ /*
+ * It's new. Try to find the ambushing socket.
+ * Because we've rewritten the destination address,
+ * any hardware-generated hash is ignored.
+ */
+ inp = in_pcblookup(&V_udbinfo, ip->ip_src,
+ uh->uh_sport, next_hop->sin_addr,
+ next_hop->sin_port ? htons(next_hop->sin_port) :
+ uh->uh_dport, INPLOOKUP_WILDCARD |
+ INPLOOKUP_RLOCKPCB, ifp);
+ }
+ /* Remove the tag from the packet. We don't need it anymore. */
+ m_tag_delete(m, fwd_tag);
+ } else
+#endif /* IPFIREWALL_FORWARD */
+ inp = in_pcblookup_mbuf(&V_udbinfo, ip->ip_src, uh->uh_sport,
+ ip->ip_dst, uh->uh_dport, INPLOOKUP_WILDCARD |
+ INPLOOKUP_RLOCKPCB, ifp, m);
if (inp == NULL) {
if (udp_log_in_vain) {
char buf[4*sizeof "123"];
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index 39e77e999b8f2..9bf7a8f44e5da 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -2017,6 +2017,27 @@ in6_localaddr(struct in6_addr *in6)
return (0);
}
+/*
+ * Return 1 if an internet address is for the local host and configured
+ * on one of its interfaces.
+ */
+int
+in6_localip(struct in6_addr *in6)
+{
+ struct in6_ifaddr *ia;
+
+ IN6_IFADDR_RLOCK();
+ TAILQ_FOREACH(ia, &V_in6_ifaddrhead, ia_link) {
+ if (IN6_ARE_ADDR_EQUAL(in6, &ia->ia_addr.sin6_addr)) {
+ IN6_IFADDR_RUNLOCK();
+ return (1);
+ }
+ }
+ IN6_IFADDR_RUNLOCK();
+ return (0);
+}
+
+
int
in6_is_addr_deprecated(struct sockaddr_in6 *sa6)
{
diff --git a/sys/netinet6/in6.h b/sys/netinet6/in6.h
index ae0da6aa0fffc..1040d90e94a02 100644
--- a/sys/netinet6/in6.h
+++ b/sys/netinet6/in6.h
@@ -614,7 +614,9 @@ struct ip6_mtuinfo {
#define IPV6CTL_NO_RADR 48 /* No defroute from RA */
#define IPV6CTL_NORBIT_RAIF 49 /* Disable R-bit in NA on RA
* receiving IF. */
-#define IPV6CTL_MAXID 50
+#define IPV6CTL_RFC6204W3 50 /* Accept defroute even when forwarding
+ enabled */
+#define IPV6CTL_MAXID 51
#endif /* __BSD_VISIBLE */
/*
@@ -631,6 +633,7 @@ struct cmsghdr;
int in6_cksum __P((struct mbuf *, u_int8_t, u_int32_t, u_int32_t));
int in6_localaddr __P((struct in6_addr *));
+int in6_localip(struct in6_addr *);
int in6_addrscope __P((struct in6_addr *));
struct in6_ifaddr *in6_ifawithifp __P((struct ifnet *, struct in6_addr *));
extern void in6_if_up __P((struct ifnet *));
diff --git a/sys/netinet6/in6_proto.c b/sys/netinet6/in6_proto.c
index e03e6405d5f23..254ec88523b16 100644
--- a/sys/netinet6/in6_proto.c
+++ b/sys/netinet6/in6_proto.c
@@ -399,6 +399,7 @@ VNET_DEFINE(int, ip6_defmcasthlim) = IPV6_DEFAULT_MULTICAST_HOPS;
VNET_DEFINE(int, ip6_accept_rtadv) = 0;
VNET_DEFINE(int, ip6_no_radr) = 0;
VNET_DEFINE(int, ip6_norbit_raif) = 0;
+VNET_DEFINE(int, ip6_rfc6204w3) = 0;
VNET_DEFINE(int, ip6_maxfragpackets); /* initialized in frag6.c:frag6_init() */
VNET_DEFINE(int, ip6_maxfrags); /* initialized in frag6.c:frag6_init() */
VNET_DEFINE(int, ip6_log_interval) = 5;
@@ -536,6 +537,10 @@ SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_NORBIT_RAIF, norbit_raif, CTLFLAG_RW,
&VNET_NAME(ip6_norbit_raif), 0,
"Always set 0 to R flag in ICMPv6 NA messages when accepting RA"
" on the interface.");
+SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_RFC6204W3, rfc6204w3,
+ CTLFLAG_RW, &VNET_NAME(ip6_rfc6204w3), 0,
+ "Accept the default router list from ICMPv6 RA messages even "
+ "when packet forwarding enabled.");
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_KEEPFAITH, keepfaith, CTLFLAG_RW,
&VNET_NAME(ip6_keepfaith), 0, "");
SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_LOG_INTERVAL, log_interval,
diff --git a/sys/netinet6/ip6_forward.c b/sys/netinet6/ip6_forward.c
index cff29e19be521..77cb926630764 100644
--- a/sys/netinet6/ip6_forward.c
+++ b/sys/netinet6/ip6_forward.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include "opt_inet.h"
#include "opt_inet6.h"
+#include "opt_ipfw.h"
#include "opt_ipsec.h"
#include "opt_ipstealth.h"
@@ -50,6 +51,7 @@ __FBSDID("$FreeBSD$");
#include <sys/syslog.h>
#include <net/if.h>
+#include <net/netisr.h>
#include <net/route.h>
#include <net/pfil.h>
@@ -98,11 +100,17 @@ ip6_forward(struct mbuf *m, int srcrt)
struct mbuf *mcopy = NULL;
struct ifnet *origifp; /* maybe unnecessary */
u_int32_t inzone, outzone;
- struct in6_addr src_in6, dst_in6;
+ struct in6_addr src_in6, dst_in6, odst;
#ifdef IPSEC
struct secpolicy *sp = NULL;
int ipsecrt = 0;
#endif
+#ifdef SCTP
+ int sw_csum;
+#endif
+#ifdef IPFIREWALL_FORWARD
+ struct m_tag *fwd_tag;
+#endif
char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
#ifdef IPSEC
@@ -345,13 +353,15 @@ ip6_forward(struct mbuf *m, int srcrt)
goto skip_routing;
skip_ipsec:
#endif
-
+again:
bzero(&rin6, sizeof(struct route_in6));
dst = (struct sockaddr_in6 *)&rin6.ro_dst;
dst->sin6_len = sizeof(struct sockaddr_in6);
dst->sin6_family = AF_INET6;
dst->sin6_addr = ip6->ip6_dst;
-
+#ifdef IPFIREWALL_FORWARD
+again2:
+#endif
rin6.ro_rt = rtalloc1((struct sockaddr *)dst, 0, 0);
if (rin6.ro_rt != NULL)
RT_UNLOCK(rin6.ro_rt);
@@ -554,6 +564,7 @@ skip_routing:
if (!PFIL_HOOKED(&V_inet6_pfil_hook))
goto pass;
+ odst = ip6->ip6_dst;
/* Run through list of hooks for output packets. */
error = pfil_run_hooks(&V_inet6_pfil_hook, &m, rt->rt_ifp, PFIL_OUT, NULL);
if (error != 0)
@@ -562,6 +573,59 @@ skip_routing:
goto freecopy;
ip6 = mtod(m, struct ip6_hdr *);
+ /* See if destination IP address was changed by packet filter. */
+ if (!IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst)) {
+ m->m_flags |= M_SKIP_FIREWALL;
+ /* If destination is now ourself drop to ip6_input(). */
+ if (in6_localip(&ip6->ip6_dst)) {
+ m->m_flags |= M_FASTFWD_OURS;
+ if (m->m_pkthdr.rcvif == NULL)
+ m->m_pkthdr.rcvif = V_loif;
+ if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+ m->m_pkthdr.csum_flags |=
+ CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
+ m->m_pkthdr.csum_data = 0xffff;
+ }
+ m->m_pkthdr.csum_flags |=
+ CSUM_IP_CHECKED | CSUM_IP_VALID;
+#ifdef SCTP
+ if (m->m_pkthdr.csum_flags & CSUM_SCTP)
+ m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID;
+#endif
+ error = netisr_queue(NETISR_IPV6, m);
+ goto out;
+ } else
+ goto again; /* Redo the routing table lookup. */
+ }
+
+#ifdef IPFIREWALL_FORWARD
+ /* See if local, if yes, send it to netisr. */
+ if (m->m_flags & M_FASTFWD_OURS) {
+ if (m->m_pkthdr.rcvif == NULL)
+ m->m_pkthdr.rcvif = V_loif;
+ if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+ m->m_pkthdr.csum_flags |=
+ CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
+ m->m_pkthdr.csum_data = 0xffff;
+ }
+#ifdef SCTP
+ if (m->m_pkthdr.csum_flags & CSUM_SCTP)
+ m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID;
+#endif
+ error = netisr_queue(NETISR_IPV6, m);
+ goto out;
+ }
+ /* Or forward to some other address? */
+ fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
+ if (fwd_tag) {
+ dst = (struct sockaddr_in6 *)&rin6.ro_dst;
+ bcopy((fwd_tag+1), dst, sizeof(struct sockaddr_in6));
+ m->m_flags |= M_SKIP_FIREWALL;
+ m_tag_delete(m, fwd_tag);
+ goto again2;
+ }
+#endif /* IPFIREWALL_FORWARD */
+
pass:
error = nd6_output(rt->rt_ifp, origifp, m, dst, rt);
if (error) {
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index de3a622706b18..1fdde1662283f 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$");
#include "opt_inet.h"
#include "opt_inet6.h"
+#include "opt_ipfw.h"
#include "opt_ipsec.h"
#include "opt_route.h"
@@ -91,6 +92,7 @@ __FBSDID("$FreeBSD$");
#include <net/vnet.h>
#include <netinet/in.h>
+#include <netinet/ip_var.h>
#include <netinet/in_systm.h>
#include <net/if_llatbl.h>
#ifdef INET
@@ -357,6 +359,17 @@ ip6_input(struct mbuf *m)
*/
ip6_delaux(m);
+ if (m->m_flags & M_FASTFWD_OURS) {
+ /*
+ * Firewall changed destination to local.
+ */
+ m->m_flags &= ~M_FASTFWD_OURS;
+ ours = 1;
+ deliverifp = m->m_pkthdr.rcvif;
+ ip6 = mtod(m, struct ip6_hdr *);
+ goto hbhcheck;
+ }
+
/*
* mbuf statistics
*/
@@ -533,6 +546,24 @@ ip6_input(struct mbuf *m)
ip6 = mtod(m, struct ip6_hdr *);
srcrt = !IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst);
+#ifdef IPFIREWALL_FORWARD
+ if (m->m_flags & M_FASTFWD_OURS) {
+ m->m_flags &= ~M_FASTFWD_OURS;
+ ours = 1;
+ deliverifp = m->m_pkthdr.rcvif;
+ goto hbhcheck;
+ }
+ if (m_tag_find(m, PACKET_TAG_IPFORWARD, NULL) != NULL) {
+ /*
+ * Directly ship the packet on. This allows forwarding
+ * packets originally destined to us to some other directly
+ * connected host.
+ */
+ ip6_forward(m, 1);
+ goto out;
+ }
+#endif /* IPFIREWALL_FORWARD */
+
passin:
/*
* Disambiguate address scope zones (if there is ambiguity).
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c
index 973689c7aa9bf..85161247d7e62 100644
--- a/sys/netinet6/ip6_output.c
+++ b/sys/netinet6/ip6_output.c
@@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$");
#include "opt_inet.h"
#include "opt_inet6.h"
+#include "opt_ipfw.h"
#include "opt_ipsec.h"
#include "opt_sctp.h"
#include "opt_route.h"
@@ -90,6 +91,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#include <netinet/in_var.h>
+#include <netinet/ip_var.h>
#include <netinet6/in6_var.h>
#include <netinet/ip6.h>
#include <netinet/icmp6.h>
@@ -229,6 +231,9 @@ ip6_output(struct mbuf *m0, struct ip6_pktopts *opt,
int segleft_org = 0;
struct secpolicy *sp = NULL;
#endif /* IPSEC */
+#ifdef IPFIREWALL_FORWARD
+ struct m_tag *fwd_tag;
+#endif
ip6 = mtod(m, struct ip6_hdr *);
if (ip6 == NULL) {
@@ -850,7 +855,8 @@ again:
if (!IN6_ARE_ADDR_EQUAL(&odst, &ip6->ip6_dst)) {
m->m_flags |= M_SKIP_FIREWALL;
/* If destination is now ourself drop to ip6_input(). */
- if (in6_localaddr(&ip6->ip6_dst)) {
+ if (in6_localip(&ip6->ip6_dst)) {
+ m->m_flags |= M_FASTFWD_OURS;
if (m->m_pkthdr.rcvif == NULL)
m->m_pkthdr.rcvif = V_loif;
if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
@@ -870,7 +876,33 @@ again:
goto again; /* Redo the routing table lookup. */
}
- /* XXX: IPFIREWALL_FORWARD */
+#ifdef IPFIREWALL_FORWARD
+ /* See if local, if yes, send it to netisr. */
+ if (m->m_flags & M_FASTFWD_OURS) {
+ if (m->m_pkthdr.rcvif == NULL)
+ m->m_pkthdr.rcvif = V_loif;
+ if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+ m->m_pkthdr.csum_flags |=
+ CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
+ m->m_pkthdr.csum_data = 0xffff;
+ }
+#ifdef SCTP
+ if (m->m_pkthdr.csum_flags & CSUM_SCTP)
+ m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID;
+#endif
+ error = netisr_queue(NETISR_IPV6, m);
+ goto done;
+ }
+ /* Or forward to some other address? */
+ fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
+ if (fwd_tag) {
+ dst = (struct sockaddr_in6 *)&ro->ro_dst;
+ bcopy((fwd_tag+1), dst, sizeof(struct sockaddr_in6));
+ m->m_flags |= M_SKIP_FIREWALL;
+ m_tag_delete(m, fwd_tag);
+ goto again;
+ }
+#endif /* IPFIREWALL_FORWARD */
passout:
/*
diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h
index dbfba9a0b9e79..c9d35e0b03d0c 100644
--- a/sys/netinet6/ip6_var.h
+++ b/sys/netinet6/ip6_var.h
@@ -319,6 +319,8 @@ VNET_DECLARE(int, ip6_accept_rtadv); /* Acts as a host not a router */
VNET_DECLARE(int, ip6_no_radr); /* No defroute from RA */
VNET_DECLARE(int, ip6_norbit_raif); /* Disable R-bit in NA on RA
* receiving IF. */
+VNET_DECLARE(int, ip6_rfc6204w3); /* Accept defroute from RA even when
+ forwarding enabled */
VNET_DECLARE(int, ip6_keepfaith); /* Firewall Aided Internet Translator */
VNET_DECLARE(int, ip6_log_interval);
VNET_DECLARE(time_t, ip6_log_time);
@@ -332,6 +334,7 @@ VNET_DECLARE(int, ip6_dad_count); /* DupAddrDetectionTransmits */
#define V_ip6_accept_rtadv VNET(ip6_accept_rtadv)
#define V_ip6_no_radr VNET(ip6_no_radr)
#define V_ip6_norbit_raif VNET(ip6_norbit_raif)
+#define V_ip6_rfc6204w3 VNET(ip6_rfc6204w3)
#define V_ip6_keepfaith VNET(ip6_keepfaith)
#define V_ip6_log_interval VNET(ip6_log_interval)
#define V_ip6_log_time VNET(ip6_log_time)
diff --git a/sys/netinet6/mld6.c b/sys/netinet6/mld6.c
index 21d9eabe363b6..a56f83d2f743a 100644
--- a/sys/netinet6/mld6.c
+++ b/sys/netinet6/mld6.c
@@ -680,7 +680,6 @@ mld_v1_input_query(struct ifnet *ifp, const struct ip6_hdr *ip6,
IN6_MULTI_LOCK();
MLD_LOCK();
- IF_ADDR_LOCK(ifp);
/*
* Switch to MLDv1 host compatibility mode.
@@ -693,6 +692,7 @@ mld_v1_input_query(struct ifnet *ifp, const struct ip6_hdr *ip6,
if (timer == 0)
timer = 1;
+ IF_ADDR_LOCK(ifp);
if (is_general_query) {
/*
* For each reporting group joined on this
@@ -888,7 +888,6 @@ mld_v2_input_query(struct ifnet *ifp, const struct ip6_hdr *ip6,
IN6_MULTI_LOCK();
MLD_LOCK();
- IF_ADDR_LOCK(ifp);
mli = MLD_IFINFO(ifp);
KASSERT(mli != NULL, ("%s: no mld_ifinfo for ifp %p", __func__, ifp));
@@ -936,14 +935,18 @@ mld_v2_input_query(struct ifnet *ifp, const struct ip6_hdr *ip6,
* Queries for groups we are not a member of on this
* link are simply ignored.
*/
+ IF_ADDR_LOCK(ifp);
inm = in6m_lookup_locked(ifp, &mld->mld_addr);
- if (inm == NULL)
+ if (inm == NULL) {
+ IF_ADDR_UNLOCK(ifp);
goto out_locked;
+ }
if (nsrc > 0) {
if (!ratecheck(&inm->in6m_lastgsrtv,
&V_mld_gsrdelay)) {
CTR1(KTR_MLD, "%s: GS query throttled.",
__func__);
+ IF_ADDR_UNLOCK(ifp);
goto out_locked;
}
}
@@ -961,10 +964,10 @@ mld_v2_input_query(struct ifnet *ifp, const struct ip6_hdr *ip6,
/* XXX Clear embedded scope ID as userland won't expect it. */
in6_clearscope(&mld->mld_addr);
+ IF_ADDR_UNLOCK(ifp);
}
out_locked:
- IF_ADDR_UNLOCK(ifp);
MLD_UNLOCK();
IN6_MULTI_UNLOCK();
diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c
index e791e2e3a7b96..5352dd5a2f645 100644
--- a/sys/netinet6/nd6_rtr.c
+++ b/sys/netinet6/nd6_rtr.c
@@ -269,11 +269,13 @@ nd6_ra_input(struct mbuf *m, int off, int icmp6len)
dr0.rtaddr = saddr6;
dr0.flags = nd_ra->nd_ra_flags_reserved;
/*
- * Effectively-disable the route in the RA packet
- * when ND6_IFF_NO_RADR on the receiving interface or
- * ip6.forwarding=1.
+ * Effectively-disable routes from RA messages when
+ * ND6_IFF_NO_RADR enabled on the receiving interface or
+ * (ip6.forwarding == 1 && ip6.rfc6204w3 != 1).
*/
- if (ndi->flags & ND6_IFF_NO_RADR || V_ip6_forwarding)
+ if (ndi->flags & ND6_IFF_NO_RADR)
+ dr0.rtlifetime = 0;
+ else if (V_ip6_forwarding && !V_ip6_rfc6204w3)
dr0.rtlifetime = 0;
else
dr0.rtlifetime = ntohs(nd_ra->nd_ra_router_lifetime);
diff --git a/sys/netinet6/sctp6_usrreq.c b/sys/netinet6/sctp6_usrreq.c
index 62efcd6bae9fb..7512f5b9f25c9 100644
--- a/sys/netinet6/sctp6_usrreq.c
+++ b/sys/netinet6/sctp6_usrreq.c
@@ -420,33 +420,8 @@ sctp6_notify(struct sctp_inpcb *inp,
*/
if (net->dest_state & SCTP_ADDR_REACHABLE) {
/* Ok that destination is NOT reachable */
- SCTP_PRINTF("ICMP (thresh %d/%d) takes interface %p down\n",
- net->error_count,
- net->failure_threshold,
- net);
-
net->dest_state &= ~SCTP_ADDR_REACHABLE;
- net->dest_state |= SCTP_ADDR_NOT_REACHABLE;
- /*
- * JRS 5/14/07 - If a destination is unreachable,
- * the PF bit is turned off. This allows an
- * unambiguous use of the PF bit for destinations
- * that are reachable but potentially failed. If the
- * destination is set to the unreachable state, also
- * set the destination to the PF state.
- */
- /*
- * Add debug message here if destination is not in
- * PF state.
- */
- /* Stop any running T3 timers here? */
- if ((stcb->asoc.sctp_cmt_on_off > 0) &&
- (stcb->asoc.sctp_cmt_pf > 0)) {
- net->dest_state &= ~SCTP_ADDR_PF;
- SCTPDBG(SCTP_DEBUG_TIMER4, "Destination %p moved from PF to unreachable.\n",
- net);
- }
- net->error_count = net->failure_threshold + 1;
+ net->dest_state &= ~SCTP_ADDR_PF;
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
stcb, SCTP_FAILED_THRESHOLD,
(void *)net, SCTP_SO_NOT_LOCKED);
diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c
index 6723007481868..2a4c0a55a4698 100644
--- a/sys/netinet6/udp6_usrreq.c
+++ b/sys/netinet6/udp6_usrreq.c
@@ -71,6 +71,7 @@ __FBSDID("$FreeBSD$");
#include "opt_inet.h"
#include "opt_inet6.h"
+#include "opt_ipfw.h"
#include "opt_ipsec.h"
#include <sys/param.h>
@@ -181,6 +182,9 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
int off = *offp;
int plen, ulen;
struct sockaddr_in6 fromsa;
+#ifdef IPFIREWALL_FORWARD
+ struct m_tag *fwd_tag;
+#endif
ifp = m->m_pkthdr.rcvif;
ip6 = mtod(m, struct ip6_hdr *);
@@ -377,9 +381,43 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
/*
* Locate pcb for datagram.
*/
- inp = in6_pcblookup_mbuf(&V_udbinfo, &ip6->ip6_src, uh->uh_sport,
- &ip6->ip6_dst, uh->uh_dport, INPLOOKUP_WILDCARD |
- INPLOOKUP_RLOCKPCB, m->m_pkthdr.rcvif, m);
+#ifdef IPFIREWALL_FORWARD
+ /*
+ * Grab info from PACKET_TAG_IPFORWARD tag prepended to the chain.
+ */
+ fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
+ if (fwd_tag != NULL) {
+ struct sockaddr_in6 *next_hop6;
+
+ next_hop6 = (struct sockaddr_in6 *)(fwd_tag + 1);
+
+ /*
+ * Transparently forwarded. Pretend to be the destination.
+ * Already got one like this?
+ */
+ inp = in6_pcblookup_mbuf(&V_udbinfo,
+ &ip6->ip6_src, uh->uh_sport, &ip6->ip6_dst, uh->uh_dport,
+ INPLOOKUP_RLOCKPCB, m->m_pkthdr.rcvif, m);
+ if (!inp) {
+ /*
+ * It's new. Try to find the ambushing socket.
+ * Because we've rewritten the destination address,
+ * any hardware-generated hash is ignored.
+ */
+ inp = in6_pcblookup(&V_udbinfo, &ip6->ip6_src,
+ uh->uh_sport, &next_hop6->sin6_addr,
+ next_hop6->sin6_port ? htons(next_hop6->sin6_port) :
+ uh->uh_dport, INPLOOKUP_WILDCARD |
+ INPLOOKUP_RLOCKPCB, m->m_pkthdr.rcvif);
+ }
+ /* Remove the tag from the packet. We don't need it anymore. */
+ m_tag_delete(m, fwd_tag);
+ } else
+#endif /* IPFIREWALL_FORWARD */
+ inp = in6_pcblookup_mbuf(&V_udbinfo, &ip6->ip6_src,
+ uh->uh_sport, &ip6->ip6_dst, uh->uh_dport,
+ INPLOOKUP_WILDCARD | INPLOOKUP_RLOCKPCB,
+ m->m_pkthdr.rcvif, m);
if (inp == NULL) {
if (udp_log_in_vain) {
char ip6bufs[INET6_ADDRSTRLEN];
diff --git a/sys/nfsclient/nfs_bio.c b/sys/nfsclient/nfs_bio.c
index da8a2ece335a9..305c189d73d88 100644
--- a/sys/nfsclient/nfs_bio.c
+++ b/sys/nfsclient/nfs_bio.c
@@ -445,6 +445,7 @@ nfs_bioread(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
struct thread *td;
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
daddr_t lbn, rabn;
+ off_t end;
int bcount;
int seqcount;
int nra, error = 0, n = 0, on = 0;
@@ -464,8 +465,9 @@ nfs_bioread(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
} else
mtx_unlock(&nmp->nm_mtx);
+ end = uio->uio_offset + uio->uio_resid;
if (vp->v_type != VDIR &&
- (uio->uio_offset + uio->uio_resid) > nmp->nm_maxfilesize)
+ (end > nmp->nm_maxfilesize || end < uio->uio_offset))
return (EFBIG);
if (nfs_directio_enable && (ioflag & IO_DIRECT) && (vp->v_type == VREG))
@@ -865,6 +867,7 @@ nfs_write(struct vop_write_args *ap)
struct vattr vattr;
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
daddr_t lbn;
+ off_t end;
int bcount;
int n, on, error = 0;
@@ -932,7 +935,8 @@ flush_and_restart:
if (uio->uio_offset < 0)
return (EINVAL);
- if ((uio->uio_offset + uio->uio_resid) > nmp->nm_maxfilesize)
+ end = uio->uio_offset + uio->uio_resid;
+ if (end > nmp->nm_maxfilesize || end < uio->uio_offset)
return (EFBIG);
if (uio->uio_resid == 0)
return (0);
diff --git a/sys/nfsclient/nfs_node.c b/sys/nfsclient/nfs_node.c
index 5b43b3d653b19..afe3341ba6cd5 100644
--- a/sys/nfsclient/nfs_node.c
+++ b/sys/nfsclient/nfs_node.c
@@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
+#include <sys/taskqueue.h>
#include <sys/vnode.h>
#include <vm/uma.h>
@@ -59,6 +60,8 @@ __FBSDID("$FreeBSD$");
static uma_zone_t nfsnode_zone;
+static void nfs_freesillyrename(void *arg, __unused int pending);
+
#define TRUE 1
#define FALSE 0
@@ -185,6 +188,20 @@ nfs_nget(struct mount *mntp, nfsfh_t *fhp, int fhsize, struct nfsnode **npp, int
return (0);
}
+/*
+ * Do the vrele(sp->s_dvp) as a separate task in order to avoid a
+ * deadlock because of a LOR when vrele() locks the directory vnode.
+ */
+static void
+nfs_freesillyrename(void *arg, __unused int pending)
+{
+ struct sillyrename *sp;
+
+ sp = arg;
+ vrele(sp->s_dvp);
+ free(sp, M_NFSREQ);
+}
+
int
nfs_inactive(struct vop_inactive_args *ap)
{
@@ -207,8 +224,8 @@ nfs_inactive(struct vop_inactive_args *ap)
*/
(sp->s_removeit)(sp);
crfree(sp->s_cred);
- vrele(sp->s_dvp);
- free((caddr_t)sp, M_NFSREQ);
+ TASK_INIT(&sp->s_task, 0, nfs_freesillyrename, sp);
+ taskqueue_enqueue(taskqueue_thread, &sp->s_task);
mtx_lock(&np->n_mtx);
}
np->n_flag &= NMODIFIED;
diff --git a/sys/nfsclient/nfs_vfsops.c b/sys/nfsclient/nfs_vfsops.c
index 8498ee45526ca..6bcc9b58cb768 100644
--- a/sys/nfsclient/nfs_vfsops.c
+++ b/sys/nfsclient/nfs_vfsops.c
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/jail.h>
+#include <sys/limits.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
@@ -1228,13 +1229,11 @@ mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
*
* For V3, nfs_fsinfo will adjust this as necessary. Assume maximum
* that we can handle until we find out otherwise.
- * XXX Our "safe" limit on the client is what we can store in our
- * buffer cache using signed(!) block numbers.
*/
if ((argp->flags & NFSMNT_NFSV3) == 0)
nmp->nm_maxfilesize = 0xffffffffLL;
else
- nmp->nm_maxfilesize = (u_int64_t)0x80000000 * DEV_BSIZE - 1;
+ nmp->nm_maxfilesize = OFF_MAX;
nmp->nm_timeo = NFS_TIMEO;
nmp->nm_retry = NFS_RETRANS;
diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c
index bb81f6b24f3f6..a9f746df6196d 100644
--- a/sys/nfsclient/nfs_vnops.c
+++ b/sys/nfsclient/nfs_vnops.c
@@ -1276,6 +1276,7 @@ nfs_readrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
caddr_t bpos, dpos;
struct mbuf *mreq, *mrep, *md, *mb;
struct nfsmount *nmp;
+ off_t end;
int error = 0, len, retlen, tsiz, eof, attrflag;
int v3 = NFS_ISV3(vp);
int rsize;
@@ -1286,7 +1287,8 @@ nfs_readrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
nmp = VFSTONFS(vp->v_mount);
tsiz = uiop->uio_resid;
mtx_lock(&nmp->nm_mtx);
- if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize) {
+ end = uiop->uio_offset + tsiz;
+ if (end > nmp->nm_maxfilesize || end < uiop->uio_offset) {
mtx_unlock(&nmp->nm_mtx);
return (EFBIG);
}
@@ -1348,6 +1350,7 @@ nfs_writerpc(struct vnode *vp, struct uio *uiop, struct ucred *cred,
caddr_t bpos, dpos;
struct mbuf *mreq, *mrep, *md, *mb;
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
+ off_t end;
int error = 0, len, tsiz, wccflag = NFSV3_WCCRATTR, rlen, commit;
int v3 = NFS_ISV3(vp), committed = NFSV3WRITE_FILESYNC;
int wsize;
@@ -1356,7 +1359,8 @@ nfs_writerpc(struct vnode *vp, struct uio *uiop, struct ucred *cred,
*must_commit = 0;
tsiz = uiop->uio_resid;
mtx_lock(&nmp->nm_mtx);
- if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize) {
+ end = uiop->uio_offset + tsiz;
+ if (end > nmp->nm_maxfilesize || end < uiop->uio_offset) {
mtx_unlock(&nmp->nm_mtx);
return (EFBIG);
}
diff --git a/sys/nfsclient/nfsnode.h b/sys/nfsclient/nfsnode.h
index 19c1c474ecc4c..8e35fdd34567d 100644
--- a/sys/nfsclient/nfsnode.h
+++ b/sys/nfsclient/nfsnode.h
@@ -36,6 +36,7 @@
#ifndef _NFSCLIENT_NFSNODE_H_
#define _NFSCLIENT_NFSNODE_H_
+#include <sys/_task.h>
#if !defined(_NFSCLIENT_NFS_H_) && !defined(_KERNEL)
#include <nfs/nfs.h>
#endif
@@ -45,6 +46,7 @@
* can be removed by nfs_inactive()
*/
struct sillyrename {
+ struct task s_task;
struct ucred *s_cred;
struct vnode *s_dvp;
int (*s_removeit)(struct sillyrename *sp);
diff --git a/sys/nfsserver/nfs_serv.c b/sys/nfsserver/nfs_serv.c
index 1b9dd987bab9c..fd3a1b553e11d 100644
--- a/sys/nfsserver/nfs_serv.c
+++ b/sys/nfsserver/nfs_serv.c
@@ -157,6 +157,7 @@ ndclear(struct nameidata *nd)
nd->ni_vp = NULL;
nd->ni_dvp = NULL;
nd->ni_startdir = NULL;
+ nd->ni_strictrelative = 0;
}
/*
diff --git a/sys/nfsserver/nfs_srvkrpc.c b/sys/nfsserver/nfs_srvkrpc.c
index 3c60825f2087e..2581092eafe06 100644
--- a/sys/nfsserver/nfs_srvkrpc.c
+++ b/sys/nfsserver/nfs_srvkrpc.c
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include "opt_kgssapi.h"
#include <sys/param.h>
+#include <sys/capability.h>
#include <sys/systm.h>
#include <sys/sysproto.h>
#include <sys/kernel.h>
@@ -173,7 +174,7 @@ nfssvc_nfsserver(struct thread *td, struct nfssvc_args *uap)
sizeof(addsockarg));
if (error)
return (error);
- if ((error = fget(td, addsockarg.sock, &fp)) != 0)
+ if ((error = fget(td, addsockarg.sock, CAP_SOCK_ALL, &fp)) != 0)
return (error);
if (fp->f_type != DTYPE_SOCKET) {
fdrop(fp, td);
diff --git a/sys/ofed/include/linux/linux_compat.c b/sys/ofed/include/linux/linux_compat.c
index 98ad807d2aa75..90737f2eaf154 100644
--- a/sys/ofed/include/linux/linux_compat.c
+++ b/sys/ofed/include/linux/linux_compat.c
@@ -559,7 +559,9 @@ struct fileops linuxfileops = {
.fo_read = linux_file_read,
.fo_poll = linux_file_poll,
.fo_close = linux_file_close,
- .fo_ioctl = linux_file_ioctl
+ .fo_ioctl = linux_file_ioctl,
+ .fo_chmod = invfo_chmod,
+ .fo_chown = invfo_chown,
};
/*
diff --git a/sys/opencrypto/cryptodev.c b/sys/opencrypto/cryptodev.c
index 2c0c503d2bf0b..2bc0e1f74d917 100644
--- a/sys/opencrypto/cryptodev.c
+++ b/sys/opencrypto/cryptodev.c
@@ -301,7 +301,9 @@ static struct fileops cryptofops = {
.fo_poll = cryptof_poll,
.fo_kqfilter = cryptof_kqfilter,
.fo_stat = cryptof_stat,
- .fo_close = cryptof_close
+ .fo_close = cryptof_close,
+ .fo_chmod = invfo_chmod,
+ .fo_chown = invfo_chown,
};
static struct csession *csefind(struct fcrypt *, u_int);
diff --git a/sys/pc98/cbus/sio.c b/sys/pc98/cbus/sio.c
index 01747d7d98a35..959726f2f0194 100644
--- a/sys/pc98/cbus/sio.c
+++ b/sys/pc98/cbus/sio.c
@@ -31,7 +31,6 @@
* from: i386/isa sio.c,v 1.234
*/
-#include "opt_comconsole.h"
#include "opt_compat.h"
#include "opt_gdb.h"
#include "opt_kdb.h"
@@ -310,7 +309,7 @@ struct com_s {
struct pps_state pps;
int pps_bit;
-#ifdef ALT_BREAK_TO_DEBUGGER
+#ifdef KDB
int alt_brk_state;
#endif
@@ -1752,8 +1751,7 @@ determined_type: ;
}
if (ret)
device_printf(dev, "could not activate interrupt\n");
-#if defined(KDB) && (defined(BREAK_TO_DEBUGGER) || \
- defined(ALT_BREAK_TO_DEBUGGER))
+#if defined(KDB)
/*
* Enable interrupts for early break-to-debugger support
* on the console.
@@ -1896,8 +1894,7 @@ comclose(tp)
sio_setreg(com, com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
#endif
-#if defined(KDB) && (defined(BREAK_TO_DEBUGGER) || \
- defined(ALT_BREAK_TO_DEBUGGER))
+#if defined(KDB)
/*
* Leave interrupts enabled and don't clear DTR if this is the
* console. This allows us to detect break-to-debugger events
@@ -2272,7 +2269,7 @@ siointr1(com)
u_char rsa_buf_status = 0;
int rsa_tx_fifo_size = 0;
#endif /* PC98 */
-#if defined(KDB) && defined(ALT_BREAK_TO_DEBUGGER)
+#if defined(KDB)
int kdb_brk;
again:
@@ -2369,27 +2366,11 @@ more_intr:
else
recv_data = inb(com->data_port);
#ifdef KDB
-#ifdef ALT_BREAK_TO_DEBUGGER
if (com->unit == comconsole &&
(kdb_brk = kdb_alt_break(recv_data,
&com->alt_brk_state)) != 0) {
- mtx_unlock_spin(&sio_lock);
- switch (kdb_brk) {
- case KDB_REQ_DEBUGGER:
- kdb_enter(KDB_WHY_BREAK,
- "Break sequence on console");
- break;
- case KDB_REQ_PANIC:
- kdb_panic("panic on console");
- break;
- case KDB_REQ_REBOOT:
- kdb_reboot();
- break;
- }
- mtx_lock_spin(&sio_lock);
goto again;
}
-#endif /* ALT_BREAK_TO_DEBUGGER */
#endif /* KDB */
if (line_status & (LSR_BI | LSR_FE | LSR_PE)) {
/*
@@ -2405,7 +2386,7 @@ more_intr:
* Note: BI together with FE/PE means just BI.
*/
if (line_status & LSR_BI) {
-#if defined(KDB) && defined(BREAK_TO_DEBUGGER)
+#if defined(KDB)
if (com->unit == comconsole) {
kdb_enter(KDB_WHY_BREAK,
"Line break on console");
diff --git a/sys/pc98/conf/GENERIC b/sys/pc98/conf/GENERIC
index e2bed44764b79..df52ac104773d 100644
--- a/sys/pc98/conf/GENERIC
+++ b/sys/pc98/conf/GENERIC
@@ -39,7 +39,7 @@ options MD_ROOT # MD is a potential root device
options NFSCL # New Network Filesystem Client
options NFSD # New Network Filesystem Server
options NFSLOCKD # Network Lock Manager
-options NFS_ROOT # NFS usable as /, requires NFSCLIENT
+options NFS_ROOT # NFS usable as /, requires NFSCL
options MSDOSFS # MSDOS Filesystem
options CD9660 # ISO 9660 Filesystem
options PROCFS # Process filesystem (requires PSEUDOFS)
@@ -276,7 +276,7 @@ device bpf # Berkeley packet filter
#device rum # Ralink Technology RT2501USB wireless NICs
#device uath # Atheros AR5523 wireless NICs
#device ural # Ralink Technology RT2500USB wireless NICs
-#device zyd # ZyDAS zb1211/zb1211b wireless NICs
+#device zyd # ZyDAS zd1211/zd1211b wireless NICs
# FireWire support
#device firewire # FireWire bus code
diff --git a/sys/pc98/pc98/machdep.c b/sys/pc98/pc98/machdep.c
index 8bcb618759ac1..b42249caea998 100644
--- a/sys/pc98/pc98/machdep.c
+++ b/sys/pc98/pc98/machdep.c
@@ -1855,7 +1855,7 @@ static void
getmemsize(int first)
{
int off, physmap_idx, pa_indx, da_indx;
- u_long physmem_tunable;
+ u_long physmem_tunable, memtest;
vm_paddr_t physmap[PHYSMAP_SIZE];
pt_entry_t *pte;
quad_t dcons_addr, dcons_size;
@@ -1915,6 +1915,13 @@ getmemsize(int first)
if (TUNABLE_ULONG_FETCH("hw.physmem", &physmem_tunable))
Maxmem = atop(physmem_tunable);
+ /*
+ * By default keep the memtest enabled. Use a general name so that
+ * one could eventually do more with the code than just disable it.
+ */
+ memtest = 1;
+ TUNABLE_ULONG_FETCH("hw.memtest.tests", &memtest);
+
if (atop(physmap[physmap_idx + 1]) != Maxmem &&
(boothowto & RB_VERBOSE))
printf("Physical memory use set to %ldK\n", Maxmem * 4);
@@ -1991,6 +1998,8 @@ getmemsize(int first)
goto do_dump_avail;
page_bad = FALSE;
+ if (memtest == 0)
+ goto skip_memtest;
/*
* map page into kernel: valid, read/write,non-cacheable
@@ -2028,6 +2037,7 @@ getmemsize(int first)
*/
*(int *)ptr = tmp;
+skip_memtest:
/*
* Adjust array of valid/good pages.
*/
diff --git a/sys/pci/if_rlreg.h b/sys/pci/if_rlreg.h
index 6ecba71495500..3a9da2e4d414e 100644
--- a/sys/pci/if_rlreg.h
+++ b/sys/pci/if_rlreg.h
@@ -1042,6 +1042,7 @@ struct rl_softc {
* D-Link DFE-5280T device ID
*/
#define DLINK_DEVICEID_528T 0x4300
+#define DLINK_DEVICEID_530T_REVC 0x4302
/*
* D-Link DFE-690TXD device ID
diff --git a/sys/powerpc/aim/locore32.S b/sys/powerpc/aim/locore32.S
index ed74af2fc7100..020d22d4913dc 100644
--- a/sys/powerpc/aim/locore32.S
+++ b/sys/powerpc/aim/locore32.S
@@ -91,13 +91,13 @@ GLOBAL(esym)
GLOBAL(intrnames)
.space INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
GLOBAL(sintrnames)
- .word INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
+ .long INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
.align 4
GLOBAL(intrcnt)
.space INTRCNT_COUNT * 4 * 2
GLOBAL(sintrcnt)
- .word INTRCNT_COUNT * 4 * 2
+ .long INTRCNT_COUNT * 4 * 2
.text
.globl btext
diff --git a/sys/powerpc/aim/locore64.S b/sys/powerpc/aim/locore64.S
index 9a54b79a4cdd5..64e4e628e9dcd 100644
--- a/sys/powerpc/aim/locore64.S
+++ b/sys/powerpc/aim/locore64.S
@@ -91,13 +91,13 @@ GLOBAL(esym)
GLOBAL(intrnames)
.space INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
GLOBAL(sintrnames)
- .word INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
+ .quad INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
.align 4
GLOBAL(intrcnt)
.space INTRCNT_COUNT * 4 * 2
GLOBAL(sintrcnt)
- .word INTRCNT_COUNT * 4 * 2
+ .quad INTRCNT_COUNT * 4 * 2
.text
.globl btext
diff --git a/sys/powerpc/aim/mmu_oea.c b/sys/powerpc/aim/mmu_oea.c
index 23354f9fd1b06..57c35bf9add53 100644
--- a/sys/powerpc/aim/mmu_oea.c
+++ b/sys/powerpc/aim/mmu_oea.c
@@ -1073,12 +1073,12 @@ moea_enter_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
if (pmap_bootstrapped)
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
PMAP_LOCK_ASSERT(pmap, MA_OWNED);
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0 ||
- (m->oflags & VPO_BUSY) != 0 || VM_OBJECT_LOCKED(m->object),
+ KASSERT((m->oflags & (VPO_UNMANAGED | VPO_BUSY)) != 0 ||
+ VM_OBJECT_LOCKED(m->object),
("moea_enter_locked: page %p is not busy", m));
/* XXX change the pvo head for fake pages */
- if ((m->flags & PG_FICTITIOUS) == PG_FICTITIOUS) {
+ if ((m->oflags & VPO_UNMANAGED) != 0) {
pvo_flags &= ~PVO_MANAGED;
pvo_head = &moea_pvo_kunmanaged;
zone = moea_upvo_zone;
@@ -1088,7 +1088,7 @@ moea_enter_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
* If this is a managed page, and it's the first reference to the page,
* clear the execness of the page. Otherwise fetch the execness.
*/
- if ((pg != NULL) && ((m->flags & PG_FICTITIOUS) == 0)) {
+ if ((pg != NULL) && ((m->oflags & VPO_UNMANAGED) == 0)) {
if (LIST_EMPTY(pvo_head)) {
moea_attr_clear(pg, PTE_EXEC);
} else {
@@ -1101,8 +1101,8 @@ moea_enter_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
if (prot & VM_PROT_WRITE) {
pte_lo |= PTE_BW;
if (pmap_bootstrapped &&
- (m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0)
- vm_page_flag_set(m, PG_WRITEABLE);
+ (m->oflags & VPO_UNMANAGED) == 0)
+ vm_page_aflag_set(m, PGA_WRITEABLE);
} else
pte_lo |= PTE_BR;
@@ -1112,9 +1112,6 @@ moea_enter_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
if (wired)
pvo_flags |= PVO_WIRED;
- if ((m->flags & PG_FICTITIOUS) != 0)
- pvo_flags |= PVO_FAKE;
-
error = moea_pvo_enter(pmap, zone, pvo_head, va, VM_PAGE_TO_PHYS(m),
pte_lo, pvo_flags);
@@ -1245,7 +1242,7 @@ boolean_t
moea_is_referenced(mmu_t mmu, vm_page_t m)
{
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("moea_is_referenced: page %p is not managed", m));
return (moea_query_bit(m, PTE_REF));
}
@@ -1254,17 +1251,17 @@ boolean_t
moea_is_modified(mmu_t mmu, vm_page_t m)
{
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("moea_is_modified: page %p is not managed", m));
/*
- * If the page is not VPO_BUSY, then PG_WRITEABLE cannot be
- * concurrently set while the object is locked. Thus, if PG_WRITEABLE
+ * If the page is not VPO_BUSY, then PGA_WRITEABLE cannot be
+ * concurrently set while the object is locked. Thus, if PGA_WRITEABLE
* is clear, no PTEs can have PTE_CHG set.
*/
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
if ((m->oflags & VPO_BUSY) == 0 &&
- (m->flags & PG_WRITEABLE) == 0)
+ (m->aflags & PGA_WRITEABLE) == 0)
return (FALSE);
return (moea_query_bit(m, PTE_CHG));
}
@@ -1286,7 +1283,7 @@ void
moea_clear_reference(mmu_t mmu, vm_page_t m)
{
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("moea_clear_reference: page %p is not managed", m));
moea_clear_bit(m, PTE_REF);
}
@@ -1295,18 +1292,18 @@ void
moea_clear_modify(mmu_t mmu, vm_page_t m)
{
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("moea_clear_modify: page %p is not managed", m));
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
KASSERT((m->oflags & VPO_BUSY) == 0,
("moea_clear_modify: page %p is busy", m));
/*
- * If the page is not PG_WRITEABLE, then no PTEs can have PTE_CHG
+ * If the page is not PGA_WRITEABLE, then no PTEs can have PTE_CHG
* set. If the object containing the page is locked and the page is
- * not VPO_BUSY, then PG_WRITEABLE cannot be concurrently set.
+ * not VPO_BUSY, then PGA_WRITEABLE cannot be concurrently set.
*/
- if ((m->flags & PG_WRITEABLE) == 0)
+ if ((m->aflags & PGA_WRITEABLE) == 0)
return;
moea_clear_bit(m, PTE_CHG);
}
@@ -1322,17 +1319,17 @@ moea_remove_write(mmu_t mmu, vm_page_t m)
pmap_t pmap;
u_int lo;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("moea_remove_write: page %p is not managed", m));
/*
- * If the page is not VPO_BUSY, then PG_WRITEABLE cannot be set by
- * another thread while the object is locked. Thus, if PG_WRITEABLE
+ * If the page is not VPO_BUSY, then PGA_WRITEABLE cannot be set by
+ * another thread while the object is locked. Thus, if PGA_WRITEABLE
* is clear, no page table entries need updating.
*/
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
if ((m->oflags & VPO_BUSY) == 0 &&
- (m->flags & PG_WRITEABLE) == 0)
+ (m->aflags & PGA_WRITEABLE) == 0)
return;
vm_page_lock_queues();
lo = moea_attr_fetch(m);
@@ -1359,7 +1356,7 @@ moea_remove_write(mmu_t mmu, vm_page_t m)
moea_attr_clear(m, PTE_CHG);
vm_page_dirty(m);
}
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
vm_page_unlock_queues();
}
@@ -1379,7 +1376,7 @@ boolean_t
moea_ts_referenced(mmu_t mmu, vm_page_t m)
{
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("moea_ts_referenced: page %p is not managed", m));
return (moea_clear_bit(m, PTE_REF));
}
@@ -1396,7 +1393,7 @@ moea_page_set_memattr(mmu_t mmu, vm_page_t m, vm_memattr_t ma)
pmap_t pmap;
u_int lo;
- if (m->flags & PG_FICTITIOUS) {
+ if ((m->oflags & VPO_UNMANAGED) != 0) {
m->md.mdpg_cache_attrs = ma;
return;
}
@@ -1537,7 +1534,7 @@ moea_page_exists_quick(mmu_t mmu, pmap_t pmap, vm_page_t m)
struct pvo_entry *pvo;
boolean_t rv;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("moea_page_exists_quick: page %p is not managed", m));
loops = 0;
rv = FALSE;
@@ -1565,7 +1562,7 @@ moea_page_wired_mappings(mmu_t mmu, vm_page_t m)
int count;
count = 0;
- if ((m->flags & PG_FICTITIOUS) != 0)
+ if ((m->oflags & VPO_UNMANAGED) != 0)
return (count);
vm_page_lock_queues();
LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink)
@@ -1797,11 +1794,11 @@ moea_remove_all(mmu_t mmu, vm_page_t m)
moea_pvo_remove(pvo, -1);
PMAP_UNLOCK(pmap);
}
- if ((m->flags & PG_WRITEABLE) && moea_is_modified(mmu, m)) {
+ if ((m->aflags & PGA_WRITEABLE) && moea_is_modified(mmu, m)) {
moea_attr_clear(m, PTE_CHG);
vm_page_dirty(m);
}
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
vm_page_unlock_queues();
}
@@ -1928,8 +1925,6 @@ moea_pvo_enter(pmap_t pm, uma_zone_t zone, struct pvo_head *pvo_head,
pvo->pvo_vaddr |= PVO_MANAGED;
if (bootstrap)
pvo->pvo_vaddr |= PVO_BOOTSTRAP;
- if (flags & PVO_FAKE)
- pvo->pvo_vaddr |= PVO_FAKE;
moea_pte_create(&pvo->pvo_pte.pte, sr, va, pa | pte_lo);
@@ -1988,7 +1983,7 @@ moea_pvo_remove(struct pvo_entry *pvo, int pteidx)
/*
* Save the REF/CHG bits into their cache if the page is managed.
*/
- if ((pvo->pvo_vaddr & (PVO_MANAGED|PVO_FAKE)) == PVO_MANAGED) {
+ if ((pvo->pvo_vaddr & PVO_MANAGED) == PVO_MANAGED) {
struct vm_page *pg;
pg = PHYS_TO_VM_PAGE(pvo->pvo_pte.pte.pte_lo & PTE_RPGN);
diff --git a/sys/powerpc/aim/mmu_oea64.c b/sys/powerpc/aim/mmu_oea64.c
index f051b61943f60..75004622753c0 100644
--- a/sys/powerpc/aim/mmu_oea64.c
+++ b/sys/powerpc/aim/mmu_oea64.c
@@ -1222,12 +1222,12 @@ moea64_enter_locked(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_page_t m,
if (pmap_bootstrapped)
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
PMAP_LOCK_ASSERT(pmap, MA_OWNED);
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0 ||
- (m->oflags & VPO_BUSY) != 0 || VM_OBJECT_LOCKED(m->object),
+ KASSERT((m->oflags & (VPO_UNMANAGED | VPO_BUSY)) != 0 ||
+ VM_OBJECT_LOCKED(m->object),
("moea64_enter_locked: page %p is not busy", m));
/* XXX change the pvo head for fake pages */
- if ((m->flags & PG_FICTITIOUS) == PG_FICTITIOUS) {
+ if ((m->oflags & VPO_UNMANAGED) != 0) {
pvo_flags &= ~PVO_MANAGED;
pvo_head = &moea64_pvo_kunmanaged;
zone = moea64_upvo_zone;
@@ -1238,8 +1238,8 @@ moea64_enter_locked(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_page_t m,
if (prot & VM_PROT_WRITE) {
pte_lo |= LPTE_BW;
if (pmap_bootstrapped &&
- (m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0)
- vm_page_flag_set(m, PG_WRITEABLE);
+ (m->oflags & VPO_UNMANAGED) == 0)
+ vm_page_aflag_set(m, PGA_WRITEABLE);
} else
pte_lo |= LPTE_BR;
@@ -1249,9 +1249,6 @@ moea64_enter_locked(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_page_t m,
if (wired)
pvo_flags |= PVO_WIRED;
- if ((m->flags & PG_FICTITIOUS) != 0)
- pvo_flags |= PVO_FAKE;
-
error = moea64_pvo_enter(mmu, pmap, zone, pvo_head, va,
VM_PAGE_TO_PHYS(m), pte_lo, pvo_flags);
@@ -1474,7 +1471,7 @@ boolean_t
moea64_is_referenced(mmu_t mmu, vm_page_t m)
{
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("moea64_is_referenced: page %p is not managed", m));
return (moea64_query_bit(mmu, m, PTE_REF));
}
@@ -1483,17 +1480,17 @@ boolean_t
moea64_is_modified(mmu_t mmu, vm_page_t m)
{
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("moea64_is_modified: page %p is not managed", m));
/*
- * If the page is not VPO_BUSY, then PG_WRITEABLE cannot be
- * concurrently set while the object is locked. Thus, if PG_WRITEABLE
+ * If the page is not VPO_BUSY, then PGA_WRITEABLE cannot be
+ * concurrently set while the object is locked. Thus, if PGA_WRITEABLE
* is clear, no PTEs can have LPTE_CHG set.
*/
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
if ((m->oflags & VPO_BUSY) == 0 &&
- (m->flags & PG_WRITEABLE) == 0)
+ (m->aflags & PGA_WRITEABLE) == 0)
return (FALSE);
return (moea64_query_bit(mmu, m, LPTE_CHG));
}
@@ -1515,7 +1512,7 @@ void
moea64_clear_reference(mmu_t mmu, vm_page_t m)
{
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("moea64_clear_reference: page %p is not managed", m));
moea64_clear_bit(mmu, m, LPTE_REF);
}
@@ -1524,18 +1521,18 @@ void
moea64_clear_modify(mmu_t mmu, vm_page_t m)
{
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("moea64_clear_modify: page %p is not managed", m));
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
KASSERT((m->oflags & VPO_BUSY) == 0,
("moea64_clear_modify: page %p is busy", m));
/*
- * If the page is not PG_WRITEABLE, then no PTEs can have LPTE_CHG
+ * If the page is not PGA_WRITEABLE, then no PTEs can have LPTE_CHG
* set. If the object containing the page is locked and the page is
- * not VPO_BUSY, then PG_WRITEABLE cannot be concurrently set.
+ * not VPO_BUSY, then PGA_WRITEABLE cannot be concurrently set.
*/
- if ((m->flags & PG_WRITEABLE) == 0)
+ if ((m->aflags & PGA_WRITEABLE) == 0)
return;
moea64_clear_bit(mmu, m, LPTE_CHG);
}
@@ -1551,17 +1548,17 @@ moea64_remove_write(mmu_t mmu, vm_page_t m)
pmap_t pmap;
uint64_t lo;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("moea64_remove_write: page %p is not managed", m));
/*
- * If the page is not VPO_BUSY, then PG_WRITEABLE cannot be set by
- * another thread while the object is locked. Thus, if PG_WRITEABLE
+ * If the page is not VPO_BUSY, then PGA_WRITEABLE cannot be set by
+ * another thread while the object is locked. Thus, if PGA_WRITEABLE
* is clear, no page table entries need updating.
*/
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
if ((m->oflags & VPO_BUSY) == 0 &&
- (m->flags & PG_WRITEABLE) == 0)
+ (m->aflags & PGA_WRITEABLE) == 0)
return;
vm_page_lock_queues();
lo = moea64_attr_fetch(m);
@@ -1591,7 +1588,7 @@ moea64_remove_write(mmu_t mmu, vm_page_t m)
moea64_attr_clear(m, LPTE_CHG);
vm_page_dirty(m);
}
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
vm_page_unlock_queues();
}
@@ -1611,7 +1608,7 @@ boolean_t
moea64_ts_referenced(mmu_t mmu, vm_page_t m)
{
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("moea64_ts_referenced: page %p is not managed", m));
return (moea64_clear_bit(mmu, m, LPTE_REF));
}
@@ -1628,7 +1625,7 @@ moea64_page_set_memattr(mmu_t mmu, vm_page_t m, vm_memattr_t ma)
pmap_t pmap;
uint64_t lo;
- if (m->flags & PG_FICTITIOUS) {
+ if ((m->oflags & VPO_UNMANAGED) != 0) {
m->md.mdpg_cache_attrs = ma;
return;
}
@@ -1763,7 +1760,7 @@ moea64_page_exists_quick(mmu_t mmu, pmap_t pmap, vm_page_t m)
struct pvo_entry *pvo;
boolean_t rv;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("moea64_page_exists_quick: page %p is not managed", m));
loops = 0;
rv = FALSE;
@@ -1791,7 +1788,7 @@ moea64_page_wired_mappings(mmu_t mmu, vm_page_t m)
int count;
count = 0;
- if ((m->flags & PG_FICTITIOUS) != 0)
+ if ((m->oflags & VPO_UNMANAGED) != 0)
return (count);
vm_page_lock_queues();
LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink)
@@ -2067,11 +2064,11 @@ moea64_remove_all(mmu_t mmu, vm_page_t m)
moea64_pvo_remove(mmu, pvo);
PMAP_UNLOCK(pmap);
}
- if ((m->flags & PG_WRITEABLE) && moea64_is_modified(mmu, m)) {
+ if ((m->aflags & PGA_WRITEABLE) && moea64_is_modified(mmu, m)) {
moea64_attr_clear(m, LPTE_CHG);
vm_page_dirty(m);
}
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
vm_page_unlock_queues();
}
@@ -2227,8 +2224,6 @@ moea64_pvo_enter(mmu_t mmu, pmap_t pm, uma_zone_t zone,
pvo->pvo_vaddr |= PVO_MANAGED;
if (bootstrap)
pvo->pvo_vaddr |= PVO_BOOTSTRAP;
- if (flags & PVO_FAKE)
- pvo->pvo_vaddr |= PVO_FAKE;
if (flags & PVO_LARGE)
pvo->pvo_vaddr |= PVO_LARGE;
@@ -2305,7 +2300,7 @@ moea64_pvo_remove(mmu_t mmu, struct pvo_entry *pvo)
/*
* Save the REF/CHG bits into their cache if the page is managed.
*/
- if ((pvo->pvo_vaddr & (PVO_MANAGED|PVO_FAKE)) == PVO_MANAGED) {
+ if ((pvo->pvo_vaddr & PVO_MANAGED) == PVO_MANAGED) {
struct vm_page *pg;
pg = PHYS_TO_VM_PAGE(pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN);
diff --git a/sys/powerpc/aim/trap.c b/sys/powerpc/aim/trap.c
index 51dee0eabdb55..93feb515728d8 100644
--- a/sys/powerpc/aim/trap.c
+++ b/sys/powerpc/aim/trap.c
@@ -445,6 +445,8 @@ cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
return (error);
}
+#include "../../kern/subr_syscall.c"
+
void
syscall(struct trapframe *frame)
{
diff --git a/sys/powerpc/booke/locore.S b/sys/powerpc/booke/locore.S
index 216962d09e3df..293eec34bdd84 100644
--- a/sys/powerpc/booke/locore.S
+++ b/sys/powerpc/booke/locore.S
@@ -83,8 +83,7 @@ __start:
* locore registers use:
* r1 : stack pointer
* r2 : trace pointer (AP only, for early diagnostics)
- * r3-r26 : scratch registers
- * r27 : kernload
+ * r3-r27 : scratch registers
* r28 : temp TLB1 entry
* r29 : initial TLB1 entry we started in
* r30-r31 : arguments (metadata pointer)
@@ -116,6 +115,9 @@ __start:
li %r3, 0
bl tlb_inval_all
+ cmpwi %r30, 0
+ beq done_mapping
+
/*
* Locate the TLB1 entry that maps this code
*/
@@ -171,7 +173,6 @@ __start:
bl 3f
3: mflr %r4 /* Use current address */
rlwinm %r4, %r4, 0, 0, 7 /* 16MB alignment mask */
- mr %r27, %r4 /* Keep kernel load address */
ori %r4, %r4, (MAS3_SX | MAS3_SW | MAS3_SR)@l
mtspr SPR_MAS3, %r4 /* Set RPN and protection */
isync
@@ -197,23 +198,7 @@ __start:
mr %r3, %r28
bl tlb1_inval_entry
-/*
- * Save kernel load address for later use.
- */
- lis %r3, kernload@ha
- addi %r3, %r3, kernload@l
- stw %r27, 0(%r3)
-#ifdef SMP
- /*
- * APs need a separate copy of kernload info within the __boot_page
- * area so they can access this value very early, before their TLBs
- * are fully set up and the kernload global location is available.
- */
- lis %r3, kernload_ap@ha
- addi %r3, %r3, kernload_ap@l
- stw %r27, 0(%r3)
- msync
-#endif
+done_mapping:
/*
* Setup a temporary stack
@@ -257,6 +242,7 @@ __start:
__boot_page:
bl 1f
+ .globl kernload_ap
kernload_ap:
.long 0
@@ -785,17 +771,15 @@ tmpstack:
*/
#define INTRCNT_COUNT 256 /* max(HROWPIC_IRQMAX,OPENPIC_IRQMAX) */
-GLOBAL(kernload)
- .long 0
GLOBAL(intrnames)
.space INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
GLOBAL(sintrnames)
- .word INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
+ .long INTRCNT_COUNT * (MAXCOMLEN + 1) * 2
.align 4
GLOBAL(intrcnt)
.space INTRCNT_COUNT * 4 * 2
GLOBAL(sintrcnt)
- .word INTRCNT_COUNT * 4 * 2
+ .long INTRCNT_COUNT * 4 * 2
#include <powerpc/booke/trap_subr.S>
diff --git a/sys/powerpc/booke/platform_bare.c b/sys/powerpc/booke/platform_bare.c
index d76664e7f925b..ca3cfa2e845e3 100644
--- a/sys/powerpc/booke/platform_bare.c
+++ b/sys/powerpc/booke/platform_bare.c
@@ -56,7 +56,7 @@ __FBSDID("$FreeBSD$");
#ifdef SMP
extern void *ap_pcpu;
extern uint8_t __boot_page[]; /* Boot page body */
-extern uint32_t kernload; /* Kernel physical load address */
+extern uint32_t kernload_ap; /* Kernel physical load address */
#endif
extern uint32_t *bootinfo;
@@ -179,8 +179,13 @@ bare_timebase_freq(platform_t plat, struct cpuref *cpuref)
pcell_t freq;
if (bootinfo != NULL) {
- /* Backward compatibility. See 8-STABLE. */
- ticks = bootinfo[3] >> 3;
+ if (bootinfo[0] == 1) {
+ /* Backward compatibility. See 8-STABLE. */
+ ticks = bootinfo[3] >> 3;
+ } else {
+ /* Compatibility with Juniper's loader. */
+ ticks = bootinfo[5] >> 3;
+ }
} else
ticks = 0;
@@ -268,7 +273,7 @@ bare_smp_start_cpu(platform_t plat, struct pcpu *pc)
/*
* Set BPTR to the physical address of the boot page
*/
- bptr = ((uint32_t)__boot_page - KERNBASE) + kernload;
+ bptr = ((uint32_t)__boot_page - KERNBASE) + kernload_ap;
ccsr_write4(OCP85XX_BPTR, (bptr >> 12) | 0x80000000);
/*
diff --git a/sys/powerpc/booke/pmap.c b/sys/powerpc/booke/pmap.c
index 18068fcd5ced5..4d1043a2eea61 100644
--- a/sys/powerpc/booke/pmap.c
+++ b/sys/powerpc/booke/pmap.c
@@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$");
#include <sys/queue.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/linker.h>
#include <sys/msgbuf.h>
#include <sys/lock.h>
#include <sys/mutex.h>
@@ -111,8 +112,13 @@ extern int dumpsys_minidump;
extern unsigned char _etext[];
extern unsigned char _end[];
-/* Kernel physical load address. */
-extern uint32_t kernload;
+extern uint32_t *bootinfo;
+
+#ifdef SMP
+extern uint32_t kernload_ap;
+#endif
+
+vm_paddr_t kernload;
vm_offset_t kernstart;
vm_size_t kernsize;
@@ -196,7 +202,7 @@ static void tlb_print_entry(int, uint32_t, uint32_t, uint32_t, uint32_t);
static int tlb1_set_entry(vm_offset_t, vm_offset_t, vm_size_t, uint32_t);
static void tlb1_write_entry(unsigned int);
static int tlb1_iomapped(int, vm_paddr_t, vm_size_t, vm_offset_t *);
-static vm_size_t tlb1_mapin_region(vm_offset_t, vm_offset_t, vm_size_t);
+static vm_size_t tlb1_mapin_region(vm_offset_t, vm_paddr_t, vm_size_t);
static vm_size_t tsize2size(unsigned int);
static unsigned int size2tsize(vm_size_t);
@@ -765,7 +771,7 @@ pv_remove(pmap_t pmap, vm_offset_t va, vm_page_t m)
/* remove from pv_list */
TAILQ_REMOVE(&m->md.pv_list, pve, pv_link);
if (TAILQ_EMPTY(&m->md.pv_list))
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
/* free pv entry struct */
pv_free(pve);
@@ -814,7 +820,7 @@ pte_remove(mmu_t mmu, pmap_t pmap, vm_offset_t va, uint8_t flags)
vm_page_dirty(m);
if (PTE_ISREFERENCED(pte))
- vm_page_flag_set(m, PG_REFERENCED);
+ vm_page_aflag_set(m, PGA_REFERENCED);
pv_remove(pmap, va, m);
}
@@ -881,13 +887,11 @@ pte_enter(mmu_t mmu, pmap_t pmap, vm_page_t m, vm_offset_t va, uint32_t flags)
* Insert pv_entry into pv_list for mapped page if part of managed
* memory.
*/
- if ((m->flags & PG_FICTITIOUS) == 0) {
- if ((m->flags & PG_UNMANAGED) == 0) {
- flags |= PTE_MANAGED;
+ if ((m->oflags & VPO_UNMANAGED) == 0) {
+ flags |= PTE_MANAGED;
- /* Create and insert pv entry. */
- pv_insert(pmap, va, m);
- }
+ /* Create and insert pv entry. */
+ pv_insert(pmap, va, m);
}
pmap->pm_stats.resident_count++;
@@ -962,19 +966,37 @@ mmu_booke_bootstrap(mmu_t mmu, vm_offset_t start, vm_offset_t kernelend)
debugf("mmu_booke_bootstrap: entered\n");
+#ifdef SMP
+ kernload_ap = kernload;
+#endif
+
+
/* Initialize invalidation mutex */
mtx_init(&tlbivax_mutex, "tlbivax", NULL, MTX_SPIN);
/* Read TLB0 size and associativity. */
tlb0_get_tlbconf();
- /* Align kernel start and end address (kernel image). */
+ /*
+ * Align kernel start and end address (kernel image).
+ * Note that kernel end does not necessarily relate to kernsize.
+ * kernsize is the size of the kernel that is actually mapped.
+ */
kernstart = trunc_page(start);
data_start = round_page(kernelend);
- kernsize = data_start - kernstart;
-
data_end = data_start;
+ /*
+ * Addresses of preloaded modules (like file systems) use
+ * physical addresses. Make sure we relocate those into
+ * virtual addresses.
+ */
+ preload_addr_relocate = kernstart - kernload;
+
+ /* Allocate the dynamic per-cpu area. */
+ dpcpu = (void *)data_end;
+ data_end += DPCPU_SIZE;
+
/* Allocate space for the message buffer. */
msgbufp = (struct msgbuf *)data_end;
data_end += msgbufsize;
@@ -983,11 +1005,6 @@ mmu_booke_bootstrap(mmu_t mmu, vm_offset_t start, vm_offset_t kernelend)
data_end = round_page(data_end);
- /* Allocate the dynamic per-cpu area. */
- dpcpu = (void *)data_end;
- data_end += DPCPU_SIZE;
- dpcpu_init(dpcpu, 0);
-
/* Allocate space for ptbl_bufs. */
ptbl_bufs = (struct ptbl_buf *)data_end;
data_end += sizeof(struct ptbl_buf) * PTBL_BUFS;
@@ -1005,22 +1022,19 @@ mmu_booke_bootstrap(mmu_t mmu, vm_offset_t start, vm_offset_t kernelend)
debugf(" kernel pdir at 0x%08x end = 0x%08x\n", kernel_pdir, data_end);
debugf(" data_end: 0x%08x\n", data_end);
- if (data_end - kernstart > 0x1000000) {
- data_end = (data_end + 0x3fffff) & ~0x3fffff;
- tlb1_mapin_region(kernstart + 0x1000000,
- kernload + 0x1000000, data_end - kernstart - 0x1000000);
- } else
- data_end = (data_end + 0xffffff) & ~0xffffff;
-
+ if (data_end - kernstart > kernsize) {
+ kernsize += tlb1_mapin_region(kernstart + kernsize,
+ kernload + kernsize, (data_end - kernstart) - kernsize);
+ }
+ data_end = kernstart + kernsize;
debugf(" updated data_end: 0x%08x\n", data_end);
- kernsize += data_end - data_start;
-
/*
* Clear the structures - note we can only do it safely after the
* possible additional TLB1 translations are in place (above) so that
* all range up to the currently calculated 'data_end' is covered.
*/
+ dpcpu_init(dpcpu, 0);
memset((void *)ptbl_bufs, 0, sizeof(struct ptbl_buf) * PTBL_SIZE);
memset((void *)kernel_pdir, 0, kernel_ptbls * PTBL_PAGES * PAGE_SIZE);
@@ -1546,8 +1560,8 @@ mmu_booke_enter_locked(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_page_t m,
KASSERT((va <= VM_MAXUSER_ADDRESS),
("mmu_booke_enter_locked: user pmap, non user va"));
}
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0 ||
- (m->oflags & VPO_BUSY) != 0 || VM_OBJECT_LOCKED(m->object),
+ KASSERT((m->oflags & (VPO_UNMANAGED | VPO_BUSY)) != 0 ||
+ VM_OBJECT_LOCKED(m->object),
("mmu_booke_enter_locked: page %p is not busy", m));
PMAP_LOCK_ASSERT(pmap, MA_OWNED);
@@ -1586,7 +1600,7 @@ mmu_booke_enter_locked(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_page_t m,
flags |= PTE_UW;
if ((flags & PTE_MANAGED) != 0)
- vm_page_flag_set(m, PG_WRITEABLE);
+ vm_page_aflag_set(m, PGA_WRITEABLE);
} else {
/* Handle modified pages, sense modify status. */
@@ -1652,8 +1666,8 @@ mmu_booke_enter_locked(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_page_t m,
if (!su)
flags |= PTE_UW;
- if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0)
- vm_page_flag_set(m, PG_WRITEABLE);
+ if ((m->oflags & VPO_UNMANAGED) == 0)
+ vm_page_aflag_set(m, PGA_WRITEABLE);
}
if (prot & VM_PROT_EXECUTE) {
@@ -1790,7 +1804,7 @@ mmu_booke_remove_all(mmu_t mmu, vm_page_t m)
pte_remove(mmu, pv->pv_pmap, pv->pv_va, hold_flag);
PMAP_UNLOCK(pv->pv_pmap);
}
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
vm_page_unlock_queues();
}
@@ -1939,17 +1953,17 @@ mmu_booke_remove_write(mmu_t mmu, vm_page_t m)
pv_entry_t pv;
pte_t *pte;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("mmu_booke_remove_write: page %p is not managed", m));
/*
- * If the page is not VPO_BUSY, then PG_WRITEABLE cannot be set by
- * another thread while the object is locked. Thus, if PG_WRITEABLE
+ * If the page is not VPO_BUSY, then PGA_WRITEABLE cannot be set by
+ * another thread while the object is locked. Thus, if PGA_WRITEABLE
* is clear, no page table entries need updating.
*/
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
if ((m->oflags & VPO_BUSY) == 0 &&
- (m->flags & PG_WRITEABLE) == 0)
+ (m->aflags & PGA_WRITEABLE) == 0)
return;
vm_page_lock_queues();
TAILQ_FOREACH(pv, &m->md.pv_list, pv_link) {
@@ -1974,7 +1988,7 @@ mmu_booke_remove_write(mmu_t mmu, vm_page_t m)
}
PMAP_UNLOCK(pv->pv_pmap);
}
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
vm_page_unlock_queues();
}
@@ -2153,18 +2167,18 @@ mmu_booke_is_modified(mmu_t mmu, vm_page_t m)
pv_entry_t pv;
boolean_t rv;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("mmu_booke_is_modified: page %p is not managed", m));
rv = FALSE;
/*
- * If the page is not VPO_BUSY, then PG_WRITEABLE cannot be
- * concurrently set while the object is locked. Thus, if PG_WRITEABLE
+ * If the page is not VPO_BUSY, then PGA_WRITEABLE cannot be
+ * concurrently set while the object is locked. Thus, if PGA_WRITEABLE
* is clear, no PTEs can be modified.
*/
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
if ((m->oflags & VPO_BUSY) == 0 &&
- (m->flags & PG_WRITEABLE) == 0)
+ (m->aflags & PGA_WRITEABLE) == 0)
return (rv);
vm_page_lock_queues();
TAILQ_FOREACH(pv, &m->md.pv_list, pv_link) {
@@ -2204,7 +2218,7 @@ mmu_booke_is_referenced(mmu_t mmu, vm_page_t m)
pv_entry_t pv;
boolean_t rv;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("mmu_booke_is_referenced: page %p is not managed", m));
rv = FALSE;
vm_page_lock_queues();
@@ -2232,18 +2246,18 @@ mmu_booke_clear_modify(mmu_t mmu, vm_page_t m)
pte_t *pte;
pv_entry_t pv;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("mmu_booke_clear_modify: page %p is not managed", m));
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
KASSERT((m->oflags & VPO_BUSY) == 0,
("mmu_booke_clear_modify: page %p is busy", m));
/*
- * If the page is not PG_WRITEABLE, then no PTEs can be modified.
+ * If the page is not PG_AWRITEABLE, then no PTEs can be modified.
* If the object containing the page is locked and the page is not
- * VPO_BUSY, then PG_WRITEABLE cannot be concurrently set.
+ * VPO_BUSY, then PG_AWRITEABLE cannot be concurrently set.
*/
- if ((m->flags & PG_WRITEABLE) == 0)
+ if ((m->aflags & PGA_WRITEABLE) == 0)
return;
vm_page_lock_queues();
TAILQ_FOREACH(pv, &m->md.pv_list, pv_link) {
@@ -2284,7 +2298,7 @@ mmu_booke_ts_referenced(mmu_t mmu, vm_page_t m)
pv_entry_t pv;
int count;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("mmu_booke_ts_referenced: page %p is not managed", m));
count = 0;
vm_page_lock_queues();
@@ -2323,7 +2337,7 @@ mmu_booke_clear_reference(mmu_t mmu, vm_page_t m)
pte_t *pte;
pv_entry_t pv;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("mmu_booke_clear_reference: page %p is not managed", m));
vm_page_lock_queues();
TAILQ_FOREACH(pv, &m->md.pv_list, pv_link) {
@@ -2384,7 +2398,7 @@ mmu_booke_page_exists_quick(mmu_t mmu, pmap_t pmap, vm_page_t m)
int loops;
boolean_t rv;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("mmu_booke_page_exists_quick: page %p is not managed", m));
loops = 0;
rv = FALSE;
@@ -2412,7 +2426,7 @@ mmu_booke_page_wired_mappings(mmu_t mmu, vm_page_t m)
pte_t *pte;
int count = 0;
- if ((m->flags & PG_FICTITIOUS) != 0)
+ if ((m->oflags & VPO_UNMANAGED) != 0)
return (count);
vm_page_lock_queues();
TAILQ_FOREACH(pv, &m->md.pv_list, pv_link) {
@@ -2926,22 +2940,6 @@ tlb1_set_entry(vm_offset_t va, vm_offset_t pa, vm_size_t size,
return (0);
}
-static int
-tlb1_entry_size_cmp(const void *a, const void *b)
-{
- const vm_size_t *sza;
- const vm_size_t *szb;
-
- sza = a;
- szb = b;
- if (*sza > *szb)
- return (-1);
- else if (*sza < *szb)
- return (1);
- else
- return (0);
-}
-
/*
* Map in contiguous RAM region into the TLB1 using maximum of
* KERNEL_REGION_MAX_TLB_ENTRIES entries.
@@ -2950,64 +2948,60 @@ tlb1_entry_size_cmp(const void *a, const void *b)
* used by all allocated entries.
*/
vm_size_t
-tlb1_mapin_region(vm_offset_t va, vm_offset_t pa, vm_size_t size)
+tlb1_mapin_region(vm_offset_t va, vm_paddr_t pa, vm_size_t size)
{
- vm_size_t entry_size[KERNEL_REGION_MAX_TLB_ENTRIES];
- vm_size_t mapped_size, sz, esz;
- unsigned int log;
- int i;
-
- CTR4(KTR_PMAP, "%s: region size = 0x%08x va = 0x%08x pa = 0x%08x",
- __func__, size, va, pa);
-
- mapped_size = 0;
- sz = size;
- memset(entry_size, 0, sizeof(entry_size));
+ vm_size_t pgs[KERNEL_REGION_MAX_TLB_ENTRIES];
+ vm_size_t mapped, pgsz, base, mask;
+ int idx, nents;
- /* Calculate entry sizes. */
- for (i = 0; i < KERNEL_REGION_MAX_TLB_ENTRIES && sz > 0; i++) {
+ /* Round up to the next 1M */
+ size = (size + (1 << 20) - 1) & ~((1 << 20) - 1);
- /* Largest region that is power of 4 and fits within size */
- log = ilog2(sz) / 2;
- esz = 1 << (2 * log);
-
- /* If this is last entry cover remaining size. */
- if (i == KERNEL_REGION_MAX_TLB_ENTRIES - 1) {
- while (esz < sz)
- esz = esz << 2;
+ mapped = 0;
+ idx = 0;
+ base = va;
+ pgsz = 64*1024*1024;
+ while (mapped < size) {
+ while (mapped < size && idx < KERNEL_REGION_MAX_TLB_ENTRIES) {
+ while (pgsz > (size - mapped))
+ pgsz >>= 2;
+ pgs[idx++] = pgsz;
+ mapped += pgsz;
}
- entry_size[i] = esz;
- mapped_size += esz;
- if (esz < sz)
- sz -= esz;
- else
- sz = 0;
+ /* We under-map. Correct for this. */
+ if (mapped < size) {
+ while (pgs[idx - 1] == pgsz) {
+ idx--;
+ mapped -= pgsz;
+ }
+ /* XXX We may increase beyond out starting point. */
+ pgsz <<= 2;
+ pgs[idx++] = pgsz;
+ mapped += pgsz;
+ }
}
- /* Sort entry sizes, required to get proper entry address alignment. */
- qsort(entry_size, KERNEL_REGION_MAX_TLB_ENTRIES,
- sizeof(vm_size_t), tlb1_entry_size_cmp);
-
- /* Load TLB1 entries. */
- for (i = 0; i < KERNEL_REGION_MAX_TLB_ENTRIES; i++) {
- esz = entry_size[i];
- if (!esz)
- break;
-
- CTR5(KTR_PMAP, "%s: entry %d: sz = 0x%08x (va = 0x%08x "
- "pa = 0x%08x)", __func__, tlb1_idx, esz, va, pa);
-
- tlb1_set_entry(va, pa, esz, _TLB_ENTRY_MEM);
-
- va += esz;
- pa += esz;
+ nents = idx;
+ mask = pgs[0] - 1;
+ /* Align address to the boundary */
+ if (va & mask) {
+ va = (va + mask) & ~mask;
+ pa = (pa + mask) & ~mask;
}
- CTR3(KTR_PMAP, "%s: mapped size 0x%08x (wasted space 0x%08x)",
- __func__, mapped_size, mapped_size - size);
+ for (idx = 0; idx < nents; idx++) {
+ pgsz = pgs[idx];
+ debugf("%u: %x -> %x, size=%x\n", idx, pa, va, pgsz);
+ tlb1_set_entry(va, pa, pgsz, _TLB_ENTRY_MEM);
+ pa += pgsz;
+ va += pgsz;
+ }
- return (mapped_size);
+ mapped = (va - base);
+ debugf("mapped size 0x%08x (wasted space 0x%08x)\n",
+ mapped, mapped - size);
+ return (mapped);
}
/*
@@ -3017,19 +3011,39 @@ tlb1_mapin_region(vm_offset_t va, vm_offset_t pa, vm_size_t size)
void
tlb1_init(vm_offset_t ccsrbar)
{
- uint32_t mas0;
+ uint32_t mas0, mas1, mas3;
+ uint32_t tsz;
+ u_int i;
- /* TLB1[0] is used to map the kernel. Save that entry. */
- mas0 = MAS0_TLBSEL(1) | MAS0_ESEL(0);
- mtspr(SPR_MAS0, mas0);
- __asm __volatile("isync; tlbre");
+ if (bootinfo != NULL && bootinfo[0] != 1) {
+ tlb1_idx = *((uint16_t *)(bootinfo + 8));
+ } else
+ tlb1_idx = 1;
+
+ /* The first entry/entries are used to map the kernel. */
+ for (i = 0; i < tlb1_idx; i++) {
+ mas0 = MAS0_TLBSEL(1) | MAS0_ESEL(i);
+ mtspr(SPR_MAS0, mas0);
+ __asm __volatile("isync; tlbre");
- tlb1[0].mas1 = mfspr(SPR_MAS1);
- tlb1[0].mas2 = mfspr(SPR_MAS2);
- tlb1[0].mas3 = mfspr(SPR_MAS3);
+ mas1 = mfspr(SPR_MAS1);
+ if ((mas1 & MAS1_VALID) == 0)
+ continue;
+
+ mas3 = mfspr(SPR_MAS3);
+
+ tlb1[i].mas1 = mas1;
+ tlb1[i].mas2 = mfspr(SPR_MAS2);
+ tlb1[i].mas3 = mas3;
+
+ if (i == 0)
+ kernload = mas3 & MAS3_RPN;
+
+ tsz = (mas1 & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT;
+ kernsize += (tsz > 0) ? tsize2size(tsz) : 0;
+ }
- /* Map in CCSRBAR in TLB1[1] */
- tlb1_idx = 1;
+ /* Map in CCSRBAR. */
tlb1_set_entry(CCSRBAR_VA, ccsrbar, CCSRBAR_SIZE, _TLB_ENTRY_IO);
/* Setup TLB miss defaults */
diff --git a/sys/powerpc/booke/trap.c b/sys/powerpc/booke/trap.c
index fc506bd361ce3..091fce08f1fb4 100644
--- a/sys/powerpc/booke/trap.c
+++ b/sys/powerpc/booke/trap.c
@@ -375,6 +375,8 @@ cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
return (error);
}
+#include "../../kern/subr_syscall.c"
+
void
syscall(struct trapframe *frame)
{
diff --git a/sys/powerpc/conf/MPC85XX b/sys/powerpc/conf/MPC85XX
index 13decf7026898..9964a340fbe12 100644
--- a/sys/powerpc/conf/MPC85XX
+++ b/sys/powerpc/conf/MPC85XX
@@ -43,7 +43,7 @@ options MD_ROOT
options MPC85XX
options MSDOSFS
options NFS_ROOT
-options NFSCLIENT
+options NFSCL
options NFSLOCKD
options PROCFS
options PSEUDOFS
diff --git a/sys/powerpc/include/param.h b/sys/powerpc/include/param.h
index 06b131c2a676f..f95cc08947263 100644
--- a/sys/powerpc/include/param.h
+++ b/sys/powerpc/include/param.h
@@ -68,7 +68,9 @@
#endif
#if defined(SMP) || defined(KLD_MODULE)
+#ifndef MAXCPU
#define MAXCPU 8
+#endif
#else
#define MAXCPU 1
#endif /* SMP || KLD_MODULE */
diff --git a/sys/powerpc/include/pmap.h b/sys/powerpc/include/pmap.h
index 9166d04ba7d90..688975d1ce217 100644
--- a/sys/powerpc/include/pmap.h
+++ b/sys/powerpc/include/pmap.h
@@ -127,10 +127,8 @@ LIST_HEAD(pvo_head, pvo_entry);
#define PVO_EXECUTABLE 0x040UL /* PVO entry is executable */
#define PVO_BOOTSTRAP 0x080UL /* PVO entry allocated during
bootstrap */
-#define PVO_FAKE 0x100UL /* fictitious phys page */
#define PVO_LARGE 0x200UL /* large page */
#define PVO_VADDR(pvo) ((pvo)->pvo_vaddr & ~ADDR_POFF)
-#define PVO_ISFAKE(pvo) ((pvo)->pvo_vaddr & PVO_FAKE)
#define PVO_PTEGIDX_GET(pvo) ((pvo)->pvo_vaddr & PVO_PTEGIDX_MASK)
#define PVO_PTEGIDX_ISSET(pvo) ((pvo)->pvo_vaddr & PVO_PTEGIDX_VALID)
#define PVO_PTEGIDX_CLR(pvo) \
diff --git a/sys/powerpc/mambo/mambo_console.c b/sys/powerpc/mambo/mambo_console.c
index a5ef2f9de35da..880ef57b14706 100644
--- a/sys/powerpc/mambo/mambo_console.c
+++ b/sys/powerpc/mambo/mambo_console.c
@@ -25,8 +25,6 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include "opt_comconsole.h"
-
#include <sys/param.h>
#include <sys/kdb.h>
#include <sys/kernel.h>
@@ -60,7 +58,7 @@ static int polltime;
static struct callout mambo_callout;
static struct tty *tp = NULL;
-#if defined(KDB) && defined(ALT_BREAK_TO_DEBUGGER)
+#if defined(KDB)
static int alt_break_state;
#endif
@@ -156,24 +154,8 @@ mambo_cngetc(struct consdev *cp)
ch = mambocall(MAMBO_CONSOLE_READ);
if (ch > 0 && ch < 0xff) {
-#if defined(KDB) && defined(ALT_BREAK_TO_DEBUGGER)
- int kdb_brk;
-
- if ((kdb_brk = kdb_alt_break(ch, &alt_break_state)) != 0) {
- switch (kdb_brk) {
- case KDB_REQ_DEBUGGER:
- kdb_enter(KDB_WHY_BREAK,
- "Break sequence on console");
- break;
- case KDB_REQ_PANIC:
- kdb_panic("Panic sequence on console");
- break;
- case KDB_REQ_REBOOT:
- kdb_reboot();
- break;
-
- }
- }
+#if defined(KDB)
+ kdb_alt_break(ch, &alt_break_state);
#endif
return (ch);
}
diff --git a/sys/powerpc/mpc85xx/atpic.c b/sys/powerpc/mpc85xx/atpic.c
index e1d0b39a68149..a792e54491bea 100644
--- a/sys/powerpc/mpc85xx/atpic.c
+++ b/sys/powerpc/mpc85xx/atpic.c
@@ -28,11 +28,11 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/cpuset.h>
#include <sys/kernel.h>
#include <sys/module.h>
-#include <sys/bus.h>
#include <sys/rman.h>
-#include <sys/bus.h>
#include <machine/bus.h>
#include <machine/intr_machdep.h>
diff --git a/sys/powerpc/powermac/fcu.c b/sys/powerpc/powermac/fcu.c
index eb43ff23e1b3f..cf5b4662a604d 100644
--- a/sys/powerpc/powermac/fcu.c
+++ b/sys/powerpc/powermac/fcu.c
@@ -282,14 +282,14 @@ fcu_fan_set_rpm(struct fcu_fan *fan, int rpm)
fan->setpoint = rpm;
} else {
device_printf(fan->dev, "Unknown fan type: %d\n", fan->type);
- return (-1);
+ return (ENXIO);
}
buf[0] = rpm >> (8 - fcu_rpm_shift);
buf[1] = rpm << fcu_rpm_shift;
if (fcu_write(sc->sc_dev, sc->sc_addr, reg, buf, 2) < 0)
- return (-1);
+ return (EIO);
return (0);
}
@@ -377,7 +377,7 @@ fcu_fan_set_pwm(struct fcu_fan *fan, int pwm)
buf[0] = (pwm * 2550) / 1000;
if (fcu_write(sc->sc_dev, sc->sc_addr, reg, buf, 1) < 0)
- return (-1);
+ return (EIO);
return (0);
}
@@ -536,12 +536,12 @@ fcu_fanrpm_sysctl(SYSCTL_HANDLER_ARGS)
if (fan->type == FCU_FAN_RPM) {
rpm = fcu_fan_get_rpm(fan);
if (rpm < 0)
- return (-1);
+ return (EIO);
error = sysctl_handle_int(oidp, &rpm, 0, req);
} else {
error = fcu_fan_get_pwm(fcu, fan, &pwm, &rpm);
if (error < 0)
- return (-1);
+ return (EIO);
switch (arg2 & 0xff00) {
case FCU_PWM_SYSCTL_PWM:
@@ -552,7 +552,7 @@ fcu_fanrpm_sysctl(SYSCTL_HANDLER_ARGS)
break;
default:
/* This should never happen */
- error = -1;
+ return (EINVAL);
};
}
diff --git a/sys/powerpc/powerpc/mmu_if.m b/sys/powerpc/powerpc/mmu_if.m
index 6f60622539283..9d5b656cbac1f 100644
--- a/sys/powerpc/powerpc/mmu_if.m
+++ b/sys/powerpc/powerpc/mmu_if.m
@@ -584,7 +584,7 @@ METHOD void remove {
/**
* @brief Traverse the reverse-map list off the given physical page and
- * remove all mappings. Clear the PG_WRITEABLE attribute from the page.
+ * remove all mappings. Clear the PGA_WRITEABLE attribute from the page.
*
* @param _pg physical page
*/
diff --git a/sys/powerpc/ps3/ps3cdrom.c b/sys/powerpc/ps3/ps3cdrom.c
new file mode 100644
index 0000000000000..319090cacb561
--- /dev/null
+++ b/sys/powerpc/ps3/ps3cdrom.c
@@ -0,0 +1,703 @@
+/*-
+ * Copyright (C) 2010 Nathan Whitehorn
+ * Copyright (C) 2011 glevand <geoffrey.levand@mail.ru>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification, immediately at the beginning of the file.
+ * 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/module.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/ata.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kthread.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/pio.h>
+#include <machine/bus.h>
+#include <machine/platform.h>
+#include <machine/pmap.h>
+#include <machine/resource.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <cam/cam.h>
+#include <cam/cam_ccb.h>
+#include <cam/cam_sim.h>
+#include <cam/cam_xpt_sim.h>
+#include <cam/cam_debug.h>
+#include <cam/scsi/scsi_all.h>
+
+#include "ps3bus.h"
+#include "ps3-hvcall.h"
+
+#define PS3CDROM_LOCK_INIT(_sc) \
+ mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), "ps3cdrom", \
+ MTX_DEF)
+#define PS3CDROM_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
+#define PS3CDROM_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
+#define PS3CDROM_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
+#define PS3CDROM_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
+#define PS3CDROM_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
+
+#define PS3CDROM_MAX_XFERS 3
+
+#define LV1_STORAGE_SEND_ATAPI_COMMAND 0x01
+
+struct ps3cdrom_softc;
+
+struct ps3cdrom_xfer {
+ TAILQ_ENTRY(ps3cdrom_xfer) x_queue;
+ struct ps3cdrom_softc *x_sc;
+ union ccb *x_ccb;
+ bus_dmamap_t x_dmamap;
+ uint64_t x_tag;
+};
+
+TAILQ_HEAD(ps3cdrom_xferq, ps3cdrom_xfer);
+
+struct ps3cdrom_softc {
+ device_t sc_dev;
+
+ struct mtx sc_mtx;
+
+ uint64_t sc_blksize;
+ uint64_t sc_nblocks;
+
+ int sc_irqid;
+ struct resource *sc_irq;
+ void *sc_irqctx;
+
+ bus_dma_tag_t sc_dmatag;
+
+ struct cam_sim *sc_sim;
+ struct cam_path *sc_path;
+
+ struct ps3cdrom_xfer sc_xfer[PS3CDROM_MAX_XFERS];
+ struct ps3cdrom_xferq sc_active_xferq;
+ struct ps3cdrom_xferq sc_free_xferq;
+};
+
+enum lv1_ata_proto {
+ NON_DATA_PROTO = 0x00,
+ PIO_DATA_IN_PROTO = 0x01,
+ PIO_DATA_OUT_PROTO = 0x02,
+ DMA_PROTO = 0x03
+};
+
+enum lv1_ata_in_out {
+ DIR_WRITE = 0x00,
+ DIR_READ = 0x01
+};
+
+struct lv1_atapi_cmd {
+ uint8_t pkt[32];
+ uint32_t pktlen;
+ uint32_t nblocks;
+ uint32_t blksize;
+ uint32_t proto; /* enum lv1_ata_proto */
+ uint32_t in_out; /* enum lv1_ata_in_out */
+ uint64_t buf;
+ uint32_t arglen;
+};
+
+static void ps3cdrom_action(struct cam_sim *sim, union ccb *ccb);
+static void ps3cdrom_poll(struct cam_sim *sim);
+static void ps3cdrom_async(void *callback_arg, u_int32_t code,
+ struct cam_path* path, void *arg);
+
+static void ps3cdrom_intr(void *arg);
+
+static void ps3cdrom_transfer(void *arg, bus_dma_segment_t *segs, int nsegs,
+ int error);
+
+static int ps3cdrom_decode_lv1_status(uint64_t status,
+ u_int8_t *sense_key, u_int8_t *asc, u_int8_t *ascq);
+
+static int
+ps3cdrom_probe(device_t dev)
+{
+ if (ps3bus_get_bustype(dev) != PS3_BUSTYPE_STORAGE ||
+ ps3bus_get_devtype(dev) != PS3_DEVTYPE_CDROM)
+ return (ENXIO);
+
+ device_set_desc(dev, "Playstation 3 CDROM");
+
+ return (BUS_PROBE_SPECIFIC);
+}
+
+static int
+ps3cdrom_attach(device_t dev)
+{
+ struct ps3cdrom_softc *sc = device_get_softc(dev);
+ struct cam_devq *devq;
+ struct ps3cdrom_xfer *xp;
+ struct ccb_setasync csa;
+ int i, err;
+
+ sc->sc_dev = dev;
+
+ PS3CDROM_LOCK_INIT(sc);
+
+ /* Setup interrupt handler */
+
+ sc->sc_irqid = 0;
+ sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irqid,
+ RF_ACTIVE);
+ if (!sc->sc_irq) {
+ device_printf(dev, "Could not allocate IRQ\n");
+ err = ENXIO;
+ goto fail_destroy_lock;
+ }
+
+ err = bus_setup_intr(dev, sc->sc_irq,
+ INTR_TYPE_CAM | INTR_MPSAFE | INTR_ENTROPY,
+ NULL, ps3cdrom_intr, sc, &sc->sc_irqctx);
+ if (err) {
+ device_printf(dev, "Could not setup IRQ\n");
+ err = ENXIO;
+ goto fail_release_intr;
+ }
+
+ /* Setup DMA */
+
+ err = bus_dma_tag_create(bus_get_dma_tag(dev), 4096, 0,
+ BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
+ BUS_SPACE_UNRESTRICTED, 1, PAGE_SIZE, 0,
+ busdma_lock_mutex, &sc->sc_mtx, &sc->sc_dmatag);
+ if (err) {
+ device_printf(dev, "Could not create DMA tag\n");
+ err = ENXIO;
+ goto fail_teardown_intr;
+ }
+
+ /* Setup transfer queues */
+
+ TAILQ_INIT(&sc->sc_active_xferq);
+ TAILQ_INIT(&sc->sc_free_xferq);
+
+ for (i = 0; i < PS3CDROM_MAX_XFERS; i++) {
+ xp = &sc->sc_xfer[i];
+ xp->x_sc = sc;
+
+ err = bus_dmamap_create(sc->sc_dmatag, BUS_DMA_COHERENT,
+ &xp->x_dmamap);
+ if (err) {
+ device_printf(dev, "Could not create DMA map (%d)\n",
+ err);
+ goto fail_destroy_dmamap;
+ }
+
+ TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue);
+ }
+
+ /* Setup CAM */
+
+ devq = cam_simq_alloc(PS3CDROM_MAX_XFERS - 1);
+ if (!devq) {
+ device_printf(dev, "Could not allocate SIM queue\n");
+ err = ENOMEM;
+ goto fail_destroy_dmatag;
+ }
+
+ sc->sc_sim = cam_sim_alloc(ps3cdrom_action, ps3cdrom_poll, "ps3cdrom",
+ sc, device_get_unit(dev), &sc->sc_mtx, PS3CDROM_MAX_XFERS - 1, 0,
+ devq);
+ if (!sc->sc_sim) {
+ device_printf(dev, "Could not allocate SIM\n");
+ cam_simq_free(devq);
+ err = ENOMEM;
+ goto fail_destroy_dmatag;
+ }
+
+ /* Setup XPT */
+
+ PS3CDROM_LOCK(sc);
+
+ err = xpt_bus_register(sc->sc_sim, dev, 0);
+ if (err != CAM_SUCCESS) {
+ device_printf(dev, "Could not register XPT bus\n");
+ err = ENXIO;
+ PS3CDROM_UNLOCK(sc);
+ goto fail_free_sim;
+ }
+
+ err = xpt_create_path(&sc->sc_path, NULL, cam_sim_path(sc->sc_sim),
+ CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
+ if (err != CAM_REQ_CMP) {
+ device_printf(dev, "Could not create XPT path\n");
+ err = ENOMEM;
+ PS3CDROM_UNLOCK(sc);
+ goto fail_unregister_xpt_bus;
+ }
+
+ xpt_setup_ccb(&csa.ccb_h, sc->sc_path, 5);
+ csa.ccb_h.func_code = XPT_SASYNC_CB;
+ csa.event_enable = AC_LOST_DEVICE;
+ csa.callback = ps3cdrom_async;
+ csa.callback_arg = sc->sc_sim;
+ xpt_action((union ccb *) &csa);
+
+ CAM_DEBUG(sc->sc_path, CAM_DEBUG_TRACE,
+ ("registered SIM for ps3cdrom%d\n", device_get_unit(dev)));
+
+ PS3CDROM_UNLOCK(sc);
+
+ return (BUS_PROBE_SPECIFIC);
+
+fail_unregister_xpt_bus:
+
+ xpt_bus_deregister(cam_sim_path(sc->sc_sim));
+
+fail_free_sim:
+
+ cam_sim_free(sc->sc_sim, TRUE);
+
+fail_destroy_dmamap:
+
+ while ((xp = TAILQ_FIRST(&sc->sc_free_xferq))) {
+ TAILQ_REMOVE(&sc->sc_free_xferq, xp, x_queue);
+ bus_dmamap_destroy(sc->sc_dmatag, xp->x_dmamap);
+ }
+
+fail_destroy_dmatag:
+
+ bus_dma_tag_destroy(sc->sc_dmatag);
+
+fail_teardown_intr:
+
+ bus_teardown_intr(dev, sc->sc_irq, sc->sc_irqctx);
+
+fail_release_intr:
+
+ bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqid, sc->sc_irq);
+
+fail_destroy_lock:
+
+ PS3CDROM_LOCK_DESTROY(sc);
+
+ return (err);
+}
+
+static int
+ps3cdrom_detach(device_t dev)
+{
+ struct ps3cdrom_softc *sc = device_get_softc(dev);
+ int i;
+
+ xpt_async(AC_LOST_DEVICE, sc->sc_path, NULL);
+ xpt_free_path(sc->sc_path);
+ xpt_bus_deregister(cam_sim_path(sc->sc_sim));
+ cam_sim_free(sc->sc_sim, TRUE);
+
+ for (i = 0; i < PS3CDROM_MAX_XFERS; i++)
+ bus_dmamap_destroy(sc->sc_dmatag, sc->sc_xfer[i].x_dmamap);
+
+ bus_dma_tag_destroy(sc->sc_dmatag);
+
+ bus_teardown_intr(dev, sc->sc_irq, sc->sc_irqctx);
+ bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqid, sc->sc_irq);
+
+ PS3CDROM_LOCK_DESTROY(sc);
+
+ return (0);
+}
+
+static void
+ps3cdrom_action(struct cam_sim *sim, union ccb *ccb)
+{
+ struct ps3cdrom_softc *sc = (struct ps3cdrom_softc *)cam_sim_softc(sim);
+ device_t dev = sc->sc_dev;
+ struct ps3cdrom_xfer *xp;
+ int err;
+
+ PS3CDROM_ASSERT_LOCKED(sc);
+
+ CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
+ ("function code 0x%02x\n", ccb->ccb_h.func_code));
+
+ switch (ccb->ccb_h.func_code) {
+ case XPT_SCSI_IO:
+ if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG)
+ break;
+
+ if(ccb->ccb_h.target_id > 0) {
+ ccb->ccb_h.status = CAM_TID_INVALID;
+ break;
+ }
+
+ if(ccb->ccb_h.target_lun > 0) {
+ ccb->ccb_h.status = CAM_LUN_INVALID;
+ break;
+ }
+
+ xp = TAILQ_FIRST(&sc->sc_free_xferq);
+
+ KASSERT(xp != NULL, ("no free transfers"));
+
+ xp->x_ccb = ccb;
+
+ TAILQ_REMOVE(&sc->sc_free_xferq, xp, x_queue);
+
+ err = bus_dmamap_load(sc->sc_dmatag, xp->x_dmamap,
+ ccb->csio.data_ptr, ccb->csio.dxfer_len, ps3cdrom_transfer,
+ xp, 0);
+ if (err && err != EINPROGRESS) {
+ device_printf(dev, "Could not load DMA map (%d)\n",
+ err);
+
+ xp->x_ccb = NULL;
+ TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue);
+ ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
+ break;
+ }
+ return;
+ case XPT_SET_TRAN_SETTINGS:
+ ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
+ break;
+ case XPT_GET_TRAN_SETTINGS:
+ {
+ struct ccb_trans_settings *cts = &ccb->cts;
+
+ cts->protocol = PROTO_SCSI;
+ cts->protocol_version = SCSI_REV_2;
+ cts->transport = XPORT_SPI;
+ cts->transport_version = 2;
+ cts->proto_specific.valid = 0;
+ cts->xport_specific.valid = 0;
+ ccb->ccb_h.status = CAM_REQ_CMP;
+ break;
+ }
+ case XPT_RESET_BUS:
+ case XPT_RESET_DEV:
+ ccb->ccb_h.status = CAM_REQ_CMP;
+ break;
+ case XPT_CALC_GEOMETRY:
+ cam_calc_geometry(&ccb->ccg, 1);
+ break;
+ case XPT_PATH_INQ:
+ {
+ struct ccb_pathinq *cpi = &ccb->cpi;
+
+ cpi->version_num = 1;
+ cpi->hba_inquiry = 0;
+ cpi->target_sprt = 0;
+ cpi->hba_inquiry = PI_SDTR_ABLE;
+ cpi->hba_misc = PIM_NOBUSRESET | PIM_SEQSCAN | PIM_NO_6_BYTE;
+ cpi->hba_eng_cnt = 0;
+ bzero(cpi->vuhba_flags, sizeof(cpi->vuhba_flags));
+ cpi->max_target = 0;
+ cpi->max_lun = 0;
+ cpi->initiator_id = 7;
+ cpi->bus_id = cam_sim_bus(sim);
+ cpi->unit_number = cam_sim_unit(sim);
+ cpi->base_transfer_speed = 150000;
+ strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
+ strncpy(cpi->hba_vid, "Sony", HBA_IDLEN);
+ strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
+ cpi->transport = XPORT_SPI;
+ cpi->transport_version = 2;
+ cpi->protocol = PROTO_SCSI;
+ cpi->protocol_version = SCSI_REV_2;
+ cpi->maxio = PAGE_SIZE;
+ cpi->ccb_h.status = CAM_REQ_CMP;
+ break;
+ }
+ default:
+ CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
+ ("unsupported function code 0x%02x\n",
+ ccb->ccb_h.func_code));
+ ccb->ccb_h.status = CAM_REQ_INVALID;
+ break;
+ }
+
+ xpt_done(ccb);
+}
+
+static void
+ps3cdrom_poll(struct cam_sim *sim)
+{
+ ps3cdrom_intr(cam_sim_softc(sim));
+}
+
+static void
+ps3cdrom_async(void *callback_arg, u_int32_t code,
+ struct cam_path* path, void *arg)
+{
+ switch (code) {
+ case AC_LOST_DEVICE:
+ xpt_print_path(path);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+ps3cdrom_intr(void *arg)
+{
+ struct ps3cdrom_softc *sc = (struct ps3cdrom_softc *) arg;
+ device_t dev = sc->sc_dev;
+ uint64_t devid = ps3bus_get_device(dev);
+ struct ps3cdrom_xfer *xp;
+ union ccb *ccb;
+ u_int8_t *cdb, sense_key, asc, ascq;
+ uint64_t tag, status;
+
+ if (lv1_storage_get_async_status(devid, &tag, &status) != 0)
+ return;
+
+ PS3CDROM_LOCK(sc);
+
+ /* Find transfer with the returned tag */
+
+ TAILQ_FOREACH(xp, &sc->sc_active_xferq, x_queue) {
+ if (xp->x_tag == tag)
+ break;
+ }
+
+ if (xp) {
+ ccb = xp->x_ccb;
+ cdb = (ccb->ccb_h.flags & CAM_CDB_POINTER) ?
+ ccb->csio.cdb_io.cdb_ptr :
+ ccb->csio.cdb_io.cdb_bytes;
+
+ CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
+ ("ATAPI command 0x%02x tag 0x%016lx completed (0x%016lx)\n",
+ cdb[0], tag, status));
+
+ if (!status) {
+ ccb->csio.scsi_status = SCSI_STATUS_OK;
+ ccb->csio.resid = 0;
+ ccb->ccb_h.status = CAM_REQ_CMP;
+ } else {
+ ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
+ ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
+
+ if (!ps3cdrom_decode_lv1_status(status, &sense_key,
+ &asc, &ascq)) {
+ struct scsi_sense_data sense_data;
+
+ CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
+ ("sense key 0x%02x asc 0x%02x ascq 0x%02x\n",
+ sense_key, asc, ascq));
+
+ bzero(&sense_data, sizeof(sense_data));
+ sense_data.error_code = SSD_CURRENT_ERROR;
+ sense_data.flags |= sense_key;
+ sense_data.extra_len = 0xa;
+ sense_data.add_sense_code = asc;
+ sense_data.add_sense_code_qual = ascq;
+ ccb->csio.sense_len = sizeof(sense_data);
+ bcopy(&sense_data, &ccb->csio.sense_data,
+ ccb->csio.sense_len);
+ ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR |
+ CAM_AUTOSNS_VALID;
+ }
+
+ if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)
+ ccb->csio.resid = ccb->csio.dxfer_len;
+ }
+
+ if (ccb->ccb_h.flags & CAM_DIR_IN)
+ bus_dmamap_sync(sc->sc_dmatag, xp->x_dmamap,
+ BUS_DMASYNC_POSTREAD);
+
+ bus_dmamap_unload(sc->sc_dmatag, xp->x_dmamap);
+
+ xp->x_ccb = NULL;
+ TAILQ_REMOVE(&sc->sc_active_xferq, xp, x_queue);
+ TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue);
+
+ xpt_done(ccb);
+ } else {
+ device_printf(dev,
+ "Could not find transfer with tag 0x%016lx\n", tag);
+ }
+
+ PS3CDROM_UNLOCK(sc);
+}
+
+static void
+ps3cdrom_transfer(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+ struct ps3cdrom_xfer *xp = (struct ps3cdrom_xfer *) arg;
+ struct ps3cdrom_softc *sc = xp->x_sc;
+ device_t dev = sc->sc_dev;
+ uint64_t devid = ps3bus_get_device(dev);
+ union ccb *ccb = xp->x_ccb;
+ u_int8_t *cdb;
+ uint64_t start_sector, block_count;
+ int err;
+
+ KASSERT(nsegs == 1, ("invalid number of DMA segments"));
+
+ PS3CDROM_ASSERT_LOCKED(sc);
+
+ if (error) {
+ device_printf(dev, "Could not load DMA map (%d)\n", error);
+
+ xp->x_ccb = NULL;
+ TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue);
+ ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
+ xpt_done(ccb);
+ return;
+ }
+
+ cdb = (ccb->ccb_h.flags & CAM_CDB_POINTER) ?
+ ccb->csio.cdb_io.cdb_ptr :
+ ccb->csio.cdb_io.cdb_bytes;
+
+ CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
+ ("ATAPI command 0x%02x cdb_len %d dxfer_len %d\n ", cdb[0],
+ ccb->csio.cdb_len, ccb->csio.dxfer_len));
+
+ switch (cdb[0]) {
+ case READ_10:
+ start_sector = (cdb[2] << 24) | (cdb[3] << 16) |
+ (cdb[4] << 8) | cdb[5];
+ block_count = (cdb[7] << 8) | cdb[8];
+
+ err = lv1_storage_read(devid, 0 /* region id */,
+ start_sector, block_count, 0 /* flags */, segs[0].ds_addr,
+ &xp->x_tag);
+ bus_dmamap_sync(sc->sc_dmatag, xp->x_dmamap,
+ BUS_DMASYNC_POSTREAD);
+ break;
+ case WRITE_10:
+ start_sector = (cdb[2] << 24) | (cdb[3] << 16) |
+ (cdb[4] << 8) | cdb[5];
+ block_count = (cdb[7] << 8) | cdb[8];
+
+ bus_dmamap_sync(sc->sc_dmatag, xp->x_dmamap,
+ BUS_DMASYNC_PREWRITE);
+ err = lv1_storage_write(devid, 0 /* region id */,
+ start_sector, block_count, 0 /* flags */,
+ segs[0].ds_addr, &xp->x_tag);
+ break;
+ default:
+ {
+ struct lv1_atapi_cmd atapi_cmd;
+
+ bzero(&atapi_cmd, sizeof(atapi_cmd));
+ atapi_cmd.pktlen = 12;
+ bcopy(cdb, atapi_cmd.pkt, ccb->csio.cdb_len);
+
+ if (ccb->ccb_h.flags & CAM_DIR_IN) {
+ atapi_cmd.in_out = DIR_READ;
+ atapi_cmd.proto = (ccb->csio.dxfer_len >= 2048) ?
+ DMA_PROTO : PIO_DATA_IN_PROTO;
+ } else if (ccb->ccb_h.flags & CAM_DIR_OUT) {
+ atapi_cmd.in_out = DIR_WRITE;
+ atapi_cmd.proto = (ccb->csio.dxfer_len >= 2048) ?
+ DMA_PROTO : PIO_DATA_OUT_PROTO;
+ } else {
+ atapi_cmd.proto = NON_DATA_PROTO;
+ }
+
+ atapi_cmd.nblocks = atapi_cmd.arglen = segs[0].ds_len;
+ atapi_cmd.blksize = 1;
+ atapi_cmd.buf = segs[0].ds_addr;
+
+ if (ccb->ccb_h.flags & CAM_DIR_OUT)
+ bus_dmamap_sync(sc->sc_dmatag, xp->x_dmamap,
+ BUS_DMASYNC_PREWRITE);
+
+ err = lv1_storage_send_device_command(devid,
+ LV1_STORAGE_SEND_ATAPI_COMMAND, vtophys(&atapi_cmd),
+ sizeof(atapi_cmd), atapi_cmd.buf, atapi_cmd.arglen,
+ &xp->x_tag);
+
+ break;
+ }
+ }
+
+ if (err) {
+ struct scsi_sense_data sense_data;
+
+ device_printf(dev, "ATAPI command 0x%02x failed (%d)\n",
+ cdb[0], err);
+
+ bus_dmamap_unload(sc->sc_dmatag, xp->x_dmamap);
+
+ xp->x_ccb = NULL;
+ TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue);
+
+ bzero(&sense_data, sizeof(sense_data));
+ sense_data.error_code = SSD_CURRENT_ERROR;
+ sense_data.flags |= SSD_KEY_ILLEGAL_REQUEST;
+ ccb->csio.sense_len = sizeof(sense_data);
+ bcopy(&sense_data, &ccb->csio.sense_data, ccb->csio.sense_len);
+ ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID;
+ xpt_done(ccb);
+ } else {
+ CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
+ ("ATAPI command 0x%02x tag 0x%016lx submitted\n ", cdb[0],
+ xp->x_tag));
+
+ TAILQ_INSERT_TAIL(&sc->sc_active_xferq, xp, x_queue);
+ ccb->ccb_h.status |= CAM_SIM_QUEUED;
+ }
+}
+
+static int
+ps3cdrom_decode_lv1_status(uint64_t status, u_int8_t *sense_key, u_int8_t *asc,
+ u_int8_t *ascq)
+{
+ if (((status >> 24) & 0xff) != SCSI_STATUS_CHECK_COND)
+ return -1;
+
+ *sense_key = (status >> 16) & 0xff;
+ *asc = (status >> 8) & 0xff;
+ *ascq = status & 0xff;
+
+ return (0);
+}
+
+static device_method_t ps3cdrom_methods[] = {
+ DEVMETHOD(device_probe, ps3cdrom_probe),
+ DEVMETHOD(device_attach, ps3cdrom_attach),
+ DEVMETHOD(device_detach, ps3cdrom_detach),
+ {0, 0},
+};
+
+static driver_t ps3cdrom_driver = {
+ "ps3cdrom",
+ ps3cdrom_methods,
+ sizeof(struct ps3cdrom_softc),
+};
+
+static devclass_t ps3cdrom_devclass;
+
+DRIVER_MODULE(ps3cdrom, ps3bus, ps3cdrom_driver, ps3cdrom_devclass, 0, 0);
+MODULE_DEPEND(ps3cdrom, cam, 1, 1, 1);
diff --git a/sys/rpc/clnt_dg.c b/sys/rpc/clnt_dg.c
index a412c084fb952..8a69bf4e5b190 100644
--- a/sys/rpc/clnt_dg.c
+++ b/sys/rpc/clnt_dg.c
@@ -467,7 +467,10 @@ send_again:
cu->cu_waitflag, "rpccwnd", 0);
if (error) {
errp->re_errno = error;
- errp->re_status = stat = RPC_CANTSEND;
+ if (error == EINTR || error == ERESTART)
+ errp->re_status = stat = RPC_INTR;
+ else
+ errp->re_status = stat = RPC_CANTSEND;
goto out;
}
}
@@ -636,7 +639,7 @@ get_reply:
*/
if (error != EWOULDBLOCK) {
errp->re_errno = error;
- if (error == EINTR)
+ if (error == EINTR || error == ERESTART)
errp->re_status = stat = RPC_INTR;
else
errp->re_status = stat = RPC_CANTRECV;
diff --git a/sys/security/audit/audit_arg.c b/sys/security/audit/audit_arg.c
index 4e155da619e0a..e4409f28bf67f 100644
--- a/sys/security/audit/audit_arg.c
+++ b/sys/security/audit/audit_arg.c
@@ -899,7 +899,7 @@ audit_sysclose(struct thread *td, int fd)
audit_arg_fd(fd);
- if (getvnode(td->td_proc->p_fd, fd, &fp) != 0)
+ if (getvnode(td->td_proc->p_fd, fd, 0, &fp) != 0)
return;
vp = fp->f_vnode;
diff --git a/sys/security/audit/audit_pipe.c b/sys/security/audit/audit_pipe.c
index a8db1135db761..a953eb0200da7 100644
--- a/sys/security/audit/audit_pipe.c
+++ b/sys/security/audit/audit_pipe.c
@@ -646,6 +646,7 @@ audit_pipe_free(struct audit_pipe *ap)
cv_destroy(&ap->ap_cv);
AUDIT_PIPE_SX_LOCK_DESTROY(ap);
AUDIT_PIPE_LOCK_DESTROY(ap);
+ seldrain(&ap->ap_selinfo);
knlist_destroy(&ap->ap_selinfo.si_note);
TAILQ_REMOVE(&audit_pipe_list, ap, ap_list);
free(ap, M_AUDIT_PIPE);
diff --git a/sys/security/mac/mac_framework.h b/sys/security/mac/mac_framework.h
index f515e98e6a6e5..92aedea4ef750 100644
--- a/sys/security/mac/mac_framework.h
+++ b/sys/security/mac/mac_framework.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1999-2002, 2007-2009 Robert N. M. Watson
+ * Copyright (c) 1999-2002, 2007-2011 Robert N. M. Watson
* Copyright (c) 2001-2005 Networks Associates Technology, Inc.
* Copyright (c) 2005-2006 SPARTA, Inc.
* All rights reserved.
@@ -225,6 +225,10 @@ int mac_posixsem_check_getvalue(struct ucred *active_cred,
int mac_posixsem_check_open(struct ucred *cred, struct ksem *ks);
int mac_posixsem_check_post(struct ucred *active_cred,
struct ucred *file_cred, struct ksem *ks);
+int mac_posixsem_check_setmode(struct ucred *cred, struct ksem *ks,
+ mode_t mode);
+int mac_posixsem_check_setowner(struct ucred *cred, struct ksem *ks,
+ uid_t uid, gid_t gid);
int mac_posixsem_check_stat(struct ucred *active_cred,
struct ucred *file_cred, struct ksem *ks);
int mac_posixsem_check_unlink(struct ucred *cred, struct ksem *ks);
@@ -234,9 +238,15 @@ void mac_posixsem_create(struct ucred *cred, struct ksem *ks);
void mac_posixsem_destroy(struct ksem *);
void mac_posixsem_init(struct ksem *);
+int mac_posixshm_check_create(struct ucred *cred, const char *path);
int mac_posixshm_check_mmap(struct ucred *cred, struct shmfd *shmfd,
int prot, int flags);
-int mac_posixshm_check_open(struct ucred *cred, struct shmfd *shmfd);
+int mac_posixshm_check_open(struct ucred *cred, struct shmfd *shmfd,
+ accmode_t accmode);
+int mac_posixshm_check_setmode(struct ucred *cred, struct shmfd *shmfd,
+ mode_t mode);
+int mac_posixshm_check_setowner(struct ucred *cred, struct shmfd *shmfd,
+ uid_t uid, gid_t gid);
int mac_posixshm_check_stat(struct ucred *active_cred,
struct ucred *file_cred, struct shmfd *shmfd);
int mac_posixshm_check_truncate(struct ucred *active_cred,
diff --git a/sys/security/mac/mac_policy.h b/sys/security/mac/mac_policy.h
index b874c41e74b1b..090dc4058104d 100644
--- a/sys/security/mac/mac_policy.h
+++ b/sys/security/mac/mac_policy.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1999-2002, 2007-2009 Robert N. M. Watson
+ * Copyright (c) 1999-2002, 2007-2011 Robert N. M. Watson
* Copyright (c) 2001-2005 Networks Associates Technology, Inc.
* Copyright (c) 2005-2006 SPARTA, Inc.
* Copyright (c) 2008 Apple Inc.
@@ -336,6 +336,12 @@ typedef int (*mpo_posixsem_check_open_t)(struct ucred *cred,
typedef int (*mpo_posixsem_check_post_t)(struct ucred *active_cred,
struct ucred *file_cred, struct ksem *ks,
struct label *kslabel);
+typedef int (*mpo_posixsem_check_setmode_t)(struct ucred *cred,
+ struct ksem *ks, struct label *shmlabel,
+ mode_t mode);
+typedef int (*mpo_posixsem_check_setowner_t)(struct ucred *cred,
+ struct ksem *ks, struct label *shmlabel,
+ uid_t uid, gid_t gid);
typedef int (*mpo_posixsem_check_stat_t)(struct ucred *active_cred,
struct ucred *file_cred, struct ksem *ks,
struct label *kslabel);
@@ -349,11 +355,20 @@ typedef void (*mpo_posixsem_create_t)(struct ucred *cred,
typedef void (*mpo_posixsem_destroy_label_t)(struct label *label);
typedef void (*mpo_posixsem_init_label_t)(struct label *label);
+typedef int (*mpo_posixshm_check_create_t)(struct ucred *cred,
+ const char *path);
typedef int (*mpo_posixshm_check_mmap_t)(struct ucred *cred,
struct shmfd *shmfd, struct label *shmlabel, int prot,
int flags);
typedef int (*mpo_posixshm_check_open_t)(struct ucred *cred,
- struct shmfd *shmfd, struct label *shmlabel);
+ struct shmfd *shmfd, struct label *shmlabel,
+ accmode_t accmode);
+typedef int (*mpo_posixshm_check_setmode_t)(struct ucred *cred,
+ struct shmfd *shmfd, struct label *shmlabel,
+ mode_t mode);
+typedef int (*mpo_posixshm_check_setowner_t)(struct ucred *cred,
+ struct shmfd *shmfd, struct label *shmlabel,
+ uid_t uid, gid_t gid);
typedef int (*mpo_posixshm_check_stat_t)(struct ucred *active_cred,
struct ucred *file_cred, struct shmfd *shmfd,
struct label *shmlabel);
@@ -791,6 +806,8 @@ struct mac_policy_ops {
mpo_posixsem_check_getvalue_t mpo_posixsem_check_getvalue;
mpo_posixsem_check_open_t mpo_posixsem_check_open;
mpo_posixsem_check_post_t mpo_posixsem_check_post;
+ mpo_posixsem_check_setmode_t mpo_posixsem_check_setmode;
+ mpo_posixsem_check_setowner_t mpo_posixsem_check_setowner;
mpo_posixsem_check_stat_t mpo_posixsem_check_stat;
mpo_posixsem_check_unlink_t mpo_posixsem_check_unlink;
mpo_posixsem_check_wait_t mpo_posixsem_check_wait;
@@ -798,8 +815,11 @@ struct mac_policy_ops {
mpo_posixsem_destroy_label_t mpo_posixsem_destroy_label;
mpo_posixsem_init_label_t mpo_posixsem_init_label;
+ mpo_posixshm_check_create_t mpo_posixshm_check_create;
mpo_posixshm_check_mmap_t mpo_posixshm_check_mmap;
mpo_posixshm_check_open_t mpo_posixshm_check_open;
+ mpo_posixshm_check_setmode_t mpo_posixshm_check_setmode;
+ mpo_posixshm_check_setowner_t mpo_posixshm_check_setowner;
mpo_posixshm_check_stat_t mpo_posixshm_check_stat;
mpo_posixshm_check_truncate_t mpo_posixshm_check_truncate;
mpo_posixshm_check_unlink_t mpo_posixshm_check_unlink;
diff --git a/sys/security/mac/mac_posix_sem.c b/sys/security/mac/mac_posix_sem.c
index 9035d608c0830..461e5dbd3418a 100644
--- a/sys/security/mac/mac_posix_sem.c
+++ b/sys/security/mac/mac_posix_sem.c
@@ -198,3 +198,35 @@ mac_posixsem_check_wait(struct ucred *active_cred, struct ucred *file_cred,
return (error);
}
+
+MAC_CHECK_PROBE_DEFINE3(posixsem_check_setmode, "struct ucred *",
+ "struct ksem *", "mode_t");
+
+int
+mac_posixsem_check_setmode(struct ucred *cred, struct ksem *ks, mode_t mode)
+{
+ int error;
+
+ MAC_POLICY_CHECK_NOSLEEP(posixsem_check_setmode, cred, ks,
+ ks->ks_label, mode);
+ MAC_CHECK_PROBE3(posixsem_check_setmode, error, cred, ks, mode);
+
+ return (error);
+}
+
+MAC_CHECK_PROBE_DEFINE4(posixsem_check_setowner, "struct ucred *",
+ "struct ks *", "uid_t", "gid_t");
+
+int
+mac_posixsem_check_setowner(struct ucred *cred, struct ksem *ks, uid_t uid,
+ gid_t gid)
+{
+ int error;
+
+ MAC_POLICY_CHECK_NOSLEEP(posixsem_check_setowner, cred, ks,
+ ks->ks_label, uid, gid);
+ MAC_CHECK_PROBE4(posixsem_check_setowner, error, cred, ks,
+ uid, gid);
+
+ return (error);
+}
diff --git a/sys/security/mac/mac_posix_shm.c b/sys/security/mac/mac_posix_shm.c
index 4432a983f2d79..d5d15fc4248c9 100644
--- a/sys/security/mac/mac_posix_shm.c
+++ b/sys/security/mac/mac_posix_shm.c
@@ -1,6 +1,6 @@
/*-
* Copyright (c) 2003-2006 SPARTA, Inc.
- * Copyright (c) 2009 Robert N. M. Watson
+ * Copyright (c) 2009-2011 Robert N. M. Watson
* All rights reserved.
*
* This software was developed for the FreeBSD Project in part by Network
@@ -101,6 +101,20 @@ mac_posixshm_create(struct ucred *cred, struct shmfd *shmfd)
shmfd->shm_label);
}
+MAC_CHECK_PROBE_DEFINE2(posixshm_check_create, "struct ucred *",
+ "const char *");
+
+int
+mac_posixshm_check_create(struct ucred *cred, const char *path)
+{
+ int error;
+
+ MAC_POLICY_CHECK_NOSLEEP(posixshm_check_create, cred, path);
+ MAC_CHECK_PROBE2(posixshm_check_create, error, cred, path);
+
+ return (error);
+}
+
MAC_CHECK_PROBE_DEFINE4(posixshm_check_mmap, "struct ucred *",
"struct shmfd *", "int", "int");
@@ -118,17 +132,18 @@ mac_posixshm_check_mmap(struct ucred *cred, struct shmfd *shmfd, int prot,
return (error);
}
-MAC_CHECK_PROBE_DEFINE2(posixshm_check_open, "struct ucred *",
- "struct shmfd *");
+MAC_CHECK_PROBE_DEFINE3(posixshm_check_open, "struct ucred *",
+ "struct shmfd *", "accmode_t accmode");
int
-mac_posixshm_check_open(struct ucred *cred, struct shmfd *shmfd)
+mac_posixshm_check_open(struct ucred *cred, struct shmfd *shmfd,
+ accmode_t accmode)
{
int error;
MAC_POLICY_CHECK_NOSLEEP(posixshm_check_open, cred, shmfd,
- shmfd->shm_label);
- MAC_CHECK_PROBE2(posixshm_check_open, error, cred, shmfd);
+ shmfd->shm_label, accmode);
+ MAC_CHECK_PROBE3(posixshm_check_open, error, cred, shmfd, accmode);
return (error);
}
@@ -181,3 +196,35 @@ mac_posixshm_check_unlink(struct ucred *cred, struct shmfd *shmfd)
return (error);
}
+
+MAC_CHECK_PROBE_DEFINE3(posixshm_check_setmode, "struct ucred *",
+ "struct shmfd *", "mode_t");
+
+int
+mac_posixshm_check_setmode(struct ucred *cred, struct shmfd *shmfd, mode_t mode)
+{
+ int error;
+
+ MAC_POLICY_CHECK_NOSLEEP(posixshm_check_setmode, cred, shmfd,
+ shmfd->shm_label, mode);
+ MAC_CHECK_PROBE3(posixshm_check_setmode, error, cred, shmfd, mode);
+
+ return (error);
+}
+
+MAC_CHECK_PROBE_DEFINE4(posixshm_check_setowner, "struct ucred *",
+ "struct shmfd *", "uid_t", "gid_t");
+
+int
+mac_posixshm_check_setowner(struct ucred *cred, struct shmfd *shmfd, uid_t uid,
+ gid_t gid)
+{
+ int error;
+
+ MAC_POLICY_CHECK_NOSLEEP(posixshm_check_setowner, cred, shmfd,
+ shmfd->shm_label, uid, gid);
+ MAC_CHECK_PROBE4(posixshm_check_setowner, error, cred, shmfd,
+ uid, gid);
+
+ return (error);
+}
diff --git a/sys/security/mac/mac_syscalls.c b/sys/security/mac/mac_syscalls.c
index aea088582b312..dc275477be509 100644
--- a/sys/security/mac/mac_syscalls.c
+++ b/sys/security/mac/mac_syscalls.c
@@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
#include "opt_mac.h"
#include <sys/param.h>
+#include <sys/capability.h>
#include <sys/fcntl.h>
#include <sys/kernel.h>
#include <sys/lock.h>
@@ -247,7 +248,7 @@ __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
}
buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
- error = fget(td, uap->fd, &fp);
+ error = fget(td, uap->fd, CAP_MAC_GET, &fp);
if (error)
goto out;
@@ -442,7 +443,7 @@ __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
return (error);
}
- error = fget(td, uap->fd, &fp);
+ error = fget(td, uap->fd, CAP_MAC_SET, &fp);
if (error)
goto out;
diff --git a/sys/security/mac_biba/mac_biba.c b/sys/security/mac_biba/mac_biba.c
index fcede07142f60..b7ca4e03044ab 100644
--- a/sys/security/mac_biba/mac_biba.c
+++ b/sys/security/mac_biba/mac_biba.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1999-2002, 2007-2009 Robert N. M. Watson
+ * Copyright (c) 1999-2002, 2007-2011 Robert N. M. Watson
* Copyright (c) 2001-2005 McAfee, Inc.
* Copyright (c) 2006 SPARTA, Inc.
* All rights reserved.
@@ -14,6 +14,9 @@
* This software was enhanced by SPARTA ISSO under SPAWAR contract
* N66001-04-C-6019 ("SEFOS").
*
+ * This software was developed at the University of Cambridge Computer
+ * Laboratory with support from a grant from Google, Inc.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -1622,6 +1625,42 @@ biba_posixsem_check_openunlink(struct ucred *cred, struct ksem *ks,
}
static int
+biba_posixsem_check_setmode(struct ucred *cred, struct ksem *ks,
+ struct label *kslabel, mode_t mode)
+{
+ struct mac_biba *subj, *obj;
+
+ if (!biba_enabled)
+ return (0);
+
+ subj = SLOT(cred->cr_label);
+ obj = SLOT(kslabel);
+
+ if (!biba_dominate_effective(subj, obj))
+ return (EACCES);
+
+ return (0);
+}
+
+static int
+biba_posixsem_check_setowner(struct ucred *cred, struct ksem *ks,
+ struct label *kslabel, uid_t uid, gid_t gid)
+{
+ struct mac_biba *subj, *obj;
+
+ if (!biba_enabled)
+ return (0);
+
+ subj = SLOT(cred->cr_label);
+ obj = SLOT(kslabel);
+
+ if (!biba_dominate_effective(subj, obj))
+ return (EACCES);
+
+ return (0);
+}
+
+static int
biba_posixsem_check_write(struct ucred *active_cred, struct ucred *file_cred,
struct ksem *ks, struct label *kslabel)
{
@@ -1669,6 +1708,156 @@ biba_posixsem_create(struct ucred *cred, struct ksem *ks,
biba_copy_effective(source, dest);
}
+static int
+biba_posixshm_check_mmap(struct ucred *cred, struct shmfd *shmfd,
+ struct label *shmlabel, int prot, int flags)
+{
+ struct mac_biba *subj, *obj;
+
+ if (!biba_enabled || !revocation_enabled)
+ return (0);
+
+ subj = SLOT(cred->cr_label);
+ obj = SLOT(shmlabel);
+
+ if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
+ if (!biba_dominate_effective(obj, subj))
+ return (EACCES);
+ }
+ if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) {
+ if (!biba_dominate_effective(subj, obj))
+ return (EACCES);
+ }
+
+ return (0);
+}
+
+static int
+biba_posixshm_check_open(struct ucred *cred, struct shmfd *shmfd,
+ struct label *shmlabel, accmode_t accmode)
+{
+ struct mac_biba *subj, *obj;
+
+ if (!biba_enabled)
+ return (0);
+
+ subj = SLOT(cred->cr_label);
+ obj = SLOT(shmlabel);
+
+ if (accmode & (VREAD | VEXEC | VSTAT_PERMS)) {
+ if (!biba_dominate_effective(obj, subj))
+ return (EACCES);
+ }
+ if (accmode & VMODIFY_PERMS) {
+ if (!biba_dominate_effective(subj, obj))
+ return (EACCES);
+ }
+
+ return (0);
+}
+
+static int
+biba_posixshm_check_setmode(struct ucred *cred, struct shmfd *shmfd,
+ struct label *shmlabel, mode_t mode)
+{
+ struct mac_biba *subj, *obj;
+
+ if (!biba_enabled)
+ return (0);
+
+ subj = SLOT(cred->cr_label);
+ obj = SLOT(shmlabel);
+
+ if (!biba_dominate_effective(subj, obj))
+ return (EACCES);
+
+ return (0);
+}
+
+static int
+biba_posixshm_check_setowner(struct ucred *cred, struct shmfd *shmfd,
+ struct label *shmlabel, uid_t uid, gid_t gid)
+{
+ struct mac_biba *subj, *obj;
+
+ if (!biba_enabled)
+ return (0);
+
+ subj = SLOT(cred->cr_label);
+ obj = SLOT(shmlabel);
+
+ if (!biba_dominate_effective(subj, obj))
+ return (EACCES);
+
+ return (0);
+}
+
+static int
+biba_posixshm_check_stat(struct ucred *active_cred, struct ucred *file_cred,
+ struct shmfd *shmfd, struct label *shmlabel)
+{
+ struct mac_biba *subj, *obj;
+
+ if (!biba_enabled)
+ return (0);
+
+ subj = SLOT(active_cred->cr_label);
+ obj = SLOT(shmlabel);
+
+ if (!biba_dominate_effective(obj, subj))
+ return (EACCES);
+
+ return (0);
+}
+
+static int
+biba_posixshm_check_truncate(struct ucred *active_cred,
+ struct ucred *file_cred, struct shmfd *shmfd, struct label *shmlabel)
+{
+ struct mac_biba *subj, *obj;
+
+ if (!biba_enabled)
+ return (0);
+
+ subj = SLOT(active_cred->cr_label);
+ obj = SLOT(shmlabel);
+
+ if (!biba_dominate_effective(subj, obj))
+ return (EACCES);
+
+ return (0);
+}
+
+static int
+biba_posixshm_check_unlink(struct ucred *cred, struct shmfd *shmfd,
+ struct label *shmlabel)
+{
+ struct mac_biba *subj, *obj;
+
+ if (!biba_enabled)
+ return (0);
+
+ subj = SLOT(cred->cr_label);
+ obj = SLOT(shmlabel);
+
+ if (!biba_dominate_effective(subj, obj))
+ return (EACCES);
+
+ return (0);
+}
+
+static void
+biba_posixshm_create(struct ucred *cred, struct shmfd *shmfd,
+ struct label *shmlabel)
+{
+ struct mac_biba *source, *dest;
+
+ source = SLOT(cred->cr_label);
+ dest = SLOT(shmlabel);
+
+ biba_copy_effective(source, dest);
+}
+
/*
* Some system privileges are allowed regardless of integrity grade; others
* are allowed only when running with privilege with respect to the Biba
@@ -3455,6 +3644,8 @@ static struct mac_policy_ops mac_biba_ops =
.mpo_posixsem_check_getvalue = biba_posixsem_check_rdonly,
.mpo_posixsem_check_open = biba_posixsem_check_openunlink,
.mpo_posixsem_check_post = biba_posixsem_check_write,
+ .mpo_posixsem_check_setmode = biba_posixsem_check_setmode,
+ .mpo_posixsem_check_setowner = biba_posixsem_check_setowner,
.mpo_posixsem_check_stat = biba_posixsem_check_rdonly,
.mpo_posixsem_check_unlink = biba_posixsem_check_openunlink,
.mpo_posixsem_check_wait = biba_posixsem_check_write,
@@ -3462,6 +3653,17 @@ static struct mac_policy_ops mac_biba_ops =
.mpo_posixsem_destroy_label = biba_destroy_label,
.mpo_posixsem_init_label = biba_init_label,
+ .mpo_posixshm_check_mmap = biba_posixshm_check_mmap,
+ .mpo_posixshm_check_open = biba_posixshm_check_open,
+ .mpo_posixshm_check_setmode = biba_posixshm_check_setmode,
+ .mpo_posixshm_check_setowner = biba_posixshm_check_setowner,
+ .mpo_posixshm_check_stat = biba_posixshm_check_stat,
+ .mpo_posixshm_check_truncate = biba_posixshm_check_truncate,
+ .mpo_posixshm_check_unlink = biba_posixshm_check_unlink,
+ .mpo_posixshm_create = biba_posixshm_create,
+ .mpo_posixshm_destroy_label = biba_destroy_label,
+ .mpo_posixshm_init_label = biba_init_label,
+
.mpo_priv_check = biba_priv_check,
.mpo_proc_check_debug = biba_proc_check_debug,
diff --git a/sys/security/mac_mls/mac_mls.c b/sys/security/mac_mls/mac_mls.c
index d41799d5a23f7..b68790d0259c6 100644
--- a/sys/security/mac_mls/mac_mls.c
+++ b/sys/security/mac_mls/mac_mls.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1999-2002, 2007-2009 Robert N. M. Watson
+ * Copyright (c) 1999-2002, 2007-2011 Robert N. M. Watson
* Copyright (c) 2001-2005 McAfee, Inc.
* Copyright (c) 2006 SPARTA, Inc.
* All rights reserved.
@@ -14,6 +14,9 @@
* This software was enhanced by SPARTA ISSO under SPAWAR contract
* N66001-04-C-6019 ("SEFOS").
*
+ * This software was developed at the University of Cambridge Computer
+ * Laboratory with support from a grant from Google, Inc.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -1532,6 +1535,42 @@ mls_posixsem_check_rdonly(struct ucred *active_cred, struct ucred *file_cred,
}
static int
+mls_posixsem_check_setmode(struct ucred *cred, struct ksem *ks,
+ struct label *shmlabel, mode_t mode)
+{
+ struct mac_mls *subj, *obj;
+
+ if (!mls_enabled)
+ return (0);
+
+ subj = SLOT(cred->cr_label);
+ obj = SLOT(shmlabel);
+
+ if (!mls_dominate_effective(obj, subj))
+ return (EACCES);
+
+ return (0);
+}
+
+static int
+mls_posixsem_check_setowner(struct ucred *cred, struct ksem *ks,
+ struct label *shmlabel, uid_t uid, gid_t gid)
+{
+ struct mac_mls *subj, *obj;
+
+ if (!mls_enabled)
+ return (0);
+
+ subj = SLOT(cred->cr_label);
+ obj = SLOT(shmlabel);
+
+ if (!mls_dominate_effective(obj, subj))
+ return (EACCES);
+
+ return (0);
+}
+
+static int
mls_posixsem_check_write(struct ucred *active_cred, struct ucred *file_cred,
struct ksem *ks, struct label *kslabel)
{
@@ -1562,6 +1601,159 @@ mls_posixsem_create(struct ucred *cred, struct ksem *ks,
}
static int
+mls_posixshm_check_mmap(struct ucred *cred, struct shmfd *shmfd,
+ struct label *shmlabel, int prot, int flags)
+{
+ struct mac_mls *subj, *obj;
+
+ if (!mls_enabled)
+ return (0);
+
+ subj = SLOT(cred->cr_label);
+ obj = SLOT(shmlabel);
+
+ if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
+ if (!mls_dominate_effective(subj, obj))
+ return (EACCES);
+ }
+ if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) {
+ if (!mls_dominate_effective(obj, subj))
+ return (EACCES);
+ }
+
+ return (0);
+}
+
+static int
+mls_posixshm_check_open(struct ucred *cred, struct shmfd *shmfd,
+ struct label *shmlabel, accmode_t accmode)
+{
+ struct mac_mls *subj, *obj;
+
+ if (!mls_enabled)
+ return (0);
+
+ subj = SLOT(cred->cr_label);
+ obj = SLOT(shmlabel);
+
+ subj = SLOT(cred->cr_label);
+ obj = SLOT(shmlabel);
+
+ if (accmode & (VREAD | VEXEC | VSTAT_PERMS)) {
+ if (!mls_dominate_effective(subj, obj))
+ return (EACCES);
+ }
+ if (accmode & VMODIFY_PERMS) {
+ if (!mls_dominate_effective(obj, subj))
+ return (EACCES);
+ }
+
+ return (0);
+}
+
+static int
+mls_posixshm_check_setmode(struct ucred *cred, struct shmfd *shmfd,
+ struct label *shmlabel, mode_t mode)
+{
+ struct mac_mls *subj, *obj;
+
+ if (!mls_enabled)
+ return (0);
+
+ subj = SLOT(cred->cr_label);
+ obj = SLOT(shmlabel);
+
+ if (!mls_dominate_effective(obj, subj))
+ return (EACCES);
+
+ return (0);
+}
+
+static int
+mls_posixshm_check_setowner(struct ucred *cred, struct shmfd *shmfd,
+ struct label *shmlabel, uid_t uid, gid_t gid)
+{
+ struct mac_mls *subj, *obj;
+
+ if (!mls_enabled)
+ return (0);
+
+ subj = SLOT(cred->cr_label);
+ obj = SLOT(shmlabel);
+
+ if (!mls_dominate_effective(obj, subj))
+ return (EACCES);
+
+ return (0);
+}
+
+static int
+mls_posixshm_check_stat(struct ucred *active_cred, struct ucred *file_cred,
+ struct shmfd *shmfd, struct label *shmlabel)
+{
+ struct mac_mls *subj, *obj;
+
+ if (!mls_enabled)
+ return (0);
+
+ subj = SLOT(active_cred->cr_label);
+ obj = SLOT(shmlabel);
+
+ if (!mls_dominate_effective(subj, obj))
+ return (EACCES);
+
+ return (0);
+}
+
+static int
+mls_posixshm_check_truncate(struct ucred *active_cred,
+ struct ucred *file_cred, struct shmfd *shmfd, struct label *shmlabel)
+{
+ struct mac_mls *subj, *obj;
+
+ if (!mls_enabled)
+ return (0);
+
+ subj = SLOT(active_cred->cr_label);
+ obj = SLOT(shmlabel);
+
+ if (!mls_dominate_effective(obj, subj))
+ return (EACCES);
+
+ return (0);
+}
+
+static int
+mls_posixshm_check_unlink(struct ucred *cred, struct shmfd *shmfd,
+ struct label *shmlabel)
+{
+ struct mac_mls *subj, *obj;
+
+ if (!mls_enabled)
+ return (0);
+
+ subj = SLOT(cred->cr_label);
+ obj = SLOT(shmlabel);
+
+ if (!mls_dominate_effective(obj, subj))
+ return (EACCES);
+
+ return (0);
+}
+
+static void
+mls_posixshm_create(struct ucred *cred, struct shmfd *shmfd,
+ struct label *shmlabel)
+{
+ struct mac_mls *source, *dest;
+
+ source = SLOT(cred->cr_label);
+ dest = SLOT(shmlabel);
+
+ mls_copy_effective(source, dest);
+}
+
+static int
mls_proc_check_debug(struct ucred *cred, struct proc *p)
{
struct mac_mls *subj, *obj;
@@ -3075,6 +3267,8 @@ static struct mac_policy_ops mls_ops =
.mpo_posixsem_check_getvalue = mls_posixsem_check_rdonly,
.mpo_posixsem_check_open = mls_posixsem_check_openunlink,
.mpo_posixsem_check_post = mls_posixsem_check_write,
+ .mpo_posixsem_check_setmode = mls_posixsem_check_setmode,
+ .mpo_posixsem_check_setowner = mls_posixsem_check_setowner,
.mpo_posixsem_check_stat = mls_posixsem_check_rdonly,
.mpo_posixsem_check_unlink = mls_posixsem_check_openunlink,
.mpo_posixsem_check_wait = mls_posixsem_check_write,
@@ -3082,6 +3276,17 @@ static struct mac_policy_ops mls_ops =
.mpo_posixsem_destroy_label = mls_destroy_label,
.mpo_posixsem_init_label = mls_init_label,
+ .mpo_posixshm_check_mmap = mls_posixshm_check_mmap,
+ .mpo_posixshm_check_open = mls_posixshm_check_open,
+ .mpo_posixshm_check_setmode = mls_posixshm_check_setmode,
+ .mpo_posixshm_check_setowner = mls_posixshm_check_setowner,
+ .mpo_posixshm_check_stat = mls_posixshm_check_stat,
+ .mpo_posixshm_check_truncate = mls_posixshm_check_truncate,
+ .mpo_posixshm_check_unlink = mls_posixshm_check_unlink,
+ .mpo_posixshm_create = mls_posixshm_create,
+ .mpo_posixshm_destroy_label = mls_destroy_label,
+ .mpo_posixshm_init_label = mls_init_label,
+
.mpo_proc_check_debug = mls_proc_check_debug,
.mpo_proc_check_sched = mls_proc_check_sched,
.mpo_proc_check_signal = mls_proc_check_signal,
diff --git a/sys/security/mac_stub/mac_stub.c b/sys/security/mac_stub/mac_stub.c
index 007efb8534078..f1d3e10c4dd5d 100644
--- a/sys/security/mac_stub/mac_stub.c
+++ b/sys/security/mac_stub/mac_stub.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1999-2002, 2007-2009 Robert N. M. Watson
+ * Copyright (c) 1999-2002, 2007-2011 Robert N. M. Watson
* Copyright (c) 2001-2005 McAfee, Inc.
* Copyright (c) 2005-2006 SPARTA, Inc.
* Copyright (c) 2008 Apple Inc.
@@ -687,6 +687,22 @@ stub_posixsem_check_post(struct ucred *active_cred, struct ucred *file_cred,
}
static int
+stub_posixsem_check_setmode(struct ucred *cred, struct ksem *ks,
+ struct label *kslabel, mode_t mode)
+{
+
+ return (0);
+}
+
+static int
+stub_posixsem_check_setowner(struct ucred *cred, struct ksem *ks,
+ struct label *kslabel, uid_t uid, gid_t gid)
+{
+
+ return (0);
+}
+
+static int
stub_posixsem_check_stat(struct ucred *active_cred, struct ucred *file_cred,
struct ksem *ks, struct label *kslabel)
{
@@ -718,6 +734,13 @@ stub_posixsem_create(struct ucred *cred, struct ksem *ks,
}
static int
+stub_posixshm_check_create(struct ucred *cred, const char *path)
+{
+
+ return (0);
+}
+
+static int
stub_posixshm_check_mmap(struct ucred *cred, struct shmfd *shmfd,
struct label *shmlabel, int prot, int flags)
{
@@ -727,7 +750,23 @@ stub_posixshm_check_mmap(struct ucred *cred, struct shmfd *shmfd,
static int
stub_posixshm_check_open(struct ucred *cred, struct shmfd *shmfd,
- struct label *shmlabel)
+ struct label *shmlabel, accmode_t accmode)
+{
+
+ return (0);
+}
+
+static int
+stub_posixshm_check_setmode(struct ucred *cred, struct shmfd *shmfd,
+ struct label *shmlabel, mode_t mode)
+{
+
+ return (0);
+}
+
+static int
+stub_posixshm_check_setowner(struct ucred *cred, struct shmfd *shmfd,
+ struct label *shmlabel, uid_t uid, gid_t gid)
{
return (0);
@@ -1731,6 +1770,8 @@ static struct mac_policy_ops stub_ops =
.mpo_posixsem_check_getvalue = stub_posixsem_check_getvalue,
.mpo_posixsem_check_open = stub_posixsem_check_open,
.mpo_posixsem_check_post = stub_posixsem_check_post,
+ .mpo_posixsem_check_setmode = stub_posixsem_check_setmode,
+ .mpo_posixsem_check_setowner = stub_posixsem_check_setowner,
.mpo_posixsem_check_stat = stub_posixsem_check_stat,
.mpo_posixsem_check_unlink = stub_posixsem_check_unlink,
.mpo_posixsem_check_wait = stub_posixsem_check_wait,
@@ -1738,8 +1779,11 @@ static struct mac_policy_ops stub_ops =
.mpo_posixsem_destroy_label = stub_destroy_label,
.mpo_posixsem_init_label = stub_init_label,
+ .mpo_posixshm_check_create = stub_posixshm_check_create,
.mpo_posixshm_check_mmap = stub_posixshm_check_mmap,
.mpo_posixshm_check_open = stub_posixshm_check_open,
+ .mpo_posixshm_check_setmode = stub_posixshm_check_setmode,
+ .mpo_posixshm_check_setowner = stub_posixshm_check_setowner,
.mpo_posixshm_check_stat = stub_posixshm_check_stat,
.mpo_posixshm_check_truncate = stub_posixshm_check_truncate,
.mpo_posixshm_check_unlink = stub_posixshm_check_unlink,
diff --git a/sys/security/mac_test/mac_test.c b/sys/security/mac_test/mac_test.c
index bef0cb7d611ca..c92c418cd1c85 100644
--- a/sys/security/mac_test/mac_test.c
+++ b/sys/security/mac_test/mac_test.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1999-2002, 2007-2009 Robert N. M. Watson
+ * Copyright (c) 1999-2002, 2007-2011 Robert N. M. Watson
* Copyright (c) 2001-2005 McAfee, Inc.
* Copyright (c) 2006 SPARTA, Inc.
* Copyright (c) 2008 Apple Inc.
@@ -1297,6 +1297,30 @@ test_posixsem_check_post(struct ucred *active_cred, struct ucred *file_cred,
return (0);
}
+COUNTER_DECL(posixsem_check_setmode);
+static int
+test_posixsem_check_setmode(struct ucred *cred, struct ksem *ks,
+ struct label *kslabel, mode_t mode)
+{
+
+ LABEL_CHECK(cred->cr_label, MAGIC_CRED);
+ LABEL_CHECK(kslabel, MAGIC_POSIX_SHM);
+ COUNTER_INC(posixsem_check_setmode);
+ return (0);
+}
+
+COUNTER_DECL(posixsem_check_setowner);
+static int
+test_posixsem_check_setowner(struct ucred *cred, struct ksem *ks,
+ struct label *kslabel, uid_t uid, gid_t gid)
+{
+
+ LABEL_CHECK(cred->cr_label, MAGIC_CRED);
+ LABEL_CHECK(kslabel, MAGIC_POSIX_SHM);
+ COUNTER_INC(posixsem_check_setowner);
+ return (0);
+}
+
COUNTER_DECL(posixsem_check_stat);
static int
test_posixsem_check_stat(struct ucred *active_cred,
@@ -1366,6 +1390,15 @@ test_posixsem_init_label(struct label *label)
COUNTER_INC(posixsem_init_label);
}
+COUNTER_DECL(posixshm_check_create);
+static int
+test_posixshm_check_create(struct ucred *cred, const char *path)
+{
+
+ COUNTER_INC(posixshm_check_create);
+ return (0);
+}
+
COUNTER_DECL(posixshm_check_mmap);
static int
test_posixshm_check_mmap(struct ucred *cred, struct shmfd *shmfd,
@@ -1381,7 +1414,7 @@ test_posixshm_check_mmap(struct ucred *cred, struct shmfd *shmfd,
COUNTER_DECL(posixshm_check_open);
static int
test_posixshm_check_open(struct ucred *cred, struct shmfd *shmfd,
- struct label *shmfdlabel)
+ struct label *shmfdlabel, accmode_t accmode)
{
LABEL_CHECK(cred->cr_label, MAGIC_CRED);
@@ -1390,6 +1423,30 @@ test_posixshm_check_open(struct ucred *cred, struct shmfd *shmfd,
return (0);
}
+COUNTER_DECL(posixshm_check_setmode);
+static int
+test_posixshm_check_setmode(struct ucred *cred, struct shmfd *shmfd,
+ struct label *shmfdlabel, mode_t mode)
+{
+
+ LABEL_CHECK(cred->cr_label, MAGIC_CRED);
+ LABEL_CHECK(shmfdlabel, MAGIC_POSIX_SHM);
+ COUNTER_INC(posixshm_check_setmode);
+ return (0);
+}
+
+COUNTER_DECL(posixshm_check_setowner);
+static int
+test_posixshm_check_setowner(struct ucred *cred, struct shmfd *shmfd,
+ struct label *shmfdlabel, uid_t uid, gid_t gid)
+{
+
+ LABEL_CHECK(cred->cr_label, MAGIC_CRED);
+ LABEL_CHECK(shmfdlabel, MAGIC_POSIX_SHM);
+ COUNTER_INC(posixshm_check_setowner);
+ return (0);
+}
+
COUNTER_DECL(posixshm_check_stat);
static int
test_posixshm_check_stat(struct ucred *active_cred,
@@ -3045,6 +3102,8 @@ static struct mac_policy_ops test_ops =
.mpo_posixsem_check_getvalue = test_posixsem_check_getvalue,
.mpo_posixsem_check_open = test_posixsem_check_open,
.mpo_posixsem_check_post = test_posixsem_check_post,
+ .mpo_posixsem_check_setmode = test_posixsem_check_setmode,
+ .mpo_posixsem_check_setowner = test_posixsem_check_setowner,
.mpo_posixsem_check_stat = test_posixsem_check_stat,
.mpo_posixsem_check_unlink = test_posixsem_check_unlink,
.mpo_posixsem_check_wait = test_posixsem_check_wait,
@@ -3052,8 +3111,11 @@ static struct mac_policy_ops test_ops =
.mpo_posixsem_destroy_label = test_posixsem_destroy_label,
.mpo_posixsem_init_label = test_posixsem_init_label,
+ .mpo_posixshm_check_create = test_posixshm_check_create,
.mpo_posixshm_check_mmap = test_posixshm_check_mmap,
.mpo_posixshm_check_open = test_posixshm_check_open,
+ .mpo_posixshm_check_setmode = test_posixshm_check_setmode,
+ .mpo_posixshm_check_setowner = test_posixshm_check_setowner,
.mpo_posixshm_check_stat = test_posixshm_check_stat,
.mpo_posixshm_check_truncate = test_posixshm_check_truncate,
.mpo_posixshm_check_unlink = test_posixshm_check_unlink,
diff --git a/sys/sparc64/conf/GENERIC b/sys/sparc64/conf/GENERIC
index 11c5d35f71a2d..fed0272734b61 100644
--- a/sys/sparc64/conf/GENERIC
+++ b/sys/sparc64/conf/GENERIC
@@ -40,7 +40,7 @@ options MD_ROOT # MD is a potential root device
options NFSCL # New Network Filesystem Client
options NFSD # New Network Filesystem Server
options NFSLOCKD # Network Lock Manager
-options NFS_ROOT # NFS usable as /, requires NFSCLIENT
+options NFS_ROOT # NFS usable as /, requires NFSCL
#options MSDOSFS # MSDOS Filesystem
options CD9660 # ISO 9660 Filesystem
options PROCFS # Process filesystem (requires PSEUDOFS)
@@ -257,7 +257,7 @@ device udav # Davicom DM9601E USB
device rum # Ralink Technology RT2501USB wireless NICs
device uath # Atheros AR5523 wireless NICs
device ural # Ralink Technology RT2500USB wireless NICs
-device zyd # ZyDAS zb1211/zb1211b wireless NICs
+device zyd # ZyDAS zd1211/zd1211b wireless NICs
# FireWire support
device firewire # FireWire bus code
diff --git a/sys/sparc64/include/param.h b/sys/sparc64/include/param.h
index af026b293f298..66bb304513060 100644
--- a/sys/sparc64/include/param.h
+++ b/sys/sparc64/include/param.h
@@ -50,7 +50,9 @@
#define MID_MACHINE MID_SPARC64
#if defined(SMP) || defined(KLD_MODULE)
-#define MAXCPU 16
+#ifndef MAXCPU
+#define MAXCPU 64
+#endif
#else
#define MAXCPU 1
#endif /* SMP || KLD_MODULE */
diff --git a/sys/sparc64/sbus/sbus.c b/sys/sparc64/sbus/sbus.c
index 5cf7ad2ad3987..dbe38598265af 100644
--- a/sys/sparc64/sbus/sbus.c
+++ b/sys/sparc64/sbus/sbus.c
@@ -303,8 +303,8 @@ sbus_attach(device_t dev)
sizeof(*range), (void **)&range)) == -1) {
panic("%s: error getting ranges property", __func__);
}
- sc->sc_rd = (struct sbus_rd *)malloc(sizeof(*sc->sc_rd) * sc->sc_nrange,
- M_DEVBUF, M_NOWAIT);
+ sc->sc_rd = malloc(sizeof(*sc->sc_rd) * sc->sc_nrange, M_DEVBUF,
+ M_NOWAIT | M_ZERO);
if (sc->sc_rd == NULL)
panic("%s: cannot allocate rmans", __func__);
/*
diff --git a/sys/sparc64/sparc64/dump_machdep.c b/sys/sparc64/sparc64/dump_machdep.c
index b76d14b94c51d..d5409ac4f75a8 100644
--- a/sys/sparc64/sparc64/dump_machdep.c
+++ b/sys/sparc64/sparc64/dump_machdep.c
@@ -23,10 +23,11 @@
* 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/conf.h>
@@ -92,6 +93,7 @@ buf_flush(struct dumperinfo *di)
error = dump_write(di, buffer, 0, dumplo, DEV_BSIZE);
dumplo += DEV_BSIZE;
+ fragsz = 0;
return (error);
}
@@ -169,7 +171,8 @@ dumpsys(struct dumperinfo *di)
/* Determine dump offset on device. */
dumplo = di->mediaoffset + di->mediasize - totsize;
- mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_SPARC64_VERSION, size, di->blocksize);
+ mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_SPARC64_VERSION, size,
+ di->blocksize);
printf("Dumping %lu MB (%d chunks)\n", (u_long)(size >> 20), nreg);
diff --git a/sys/sparc64/sparc64/exception.S b/sys/sparc64/sparc64/exception.S
index fa2f2d5cfd479..222ddeadd21b2 100644
--- a/sys/sparc64/sparc64/exception.S
+++ b/sys/sparc64/sparc64/exception.S
@@ -375,13 +375,13 @@ END(rsf_fatal)
intrnames:
.space IV_MAX * (MAXCOMLEN + 1)
sintrnames:
- .word IV_MAX * (MAXCOMLEN + 1)
+ .quad IV_MAX * (MAXCOMLEN + 1)
.globl intrcnt, sintrcnt
intrcnt:
.space IV_MAX * 8
sintrcnt:
- .word IV_MAX * 8
+ .quad IV_MAX * 8
.text
diff --git a/sys/sparc64/sparc64/mp_machdep.c b/sys/sparc64/sparc64/mp_machdep.c
index e5910e06f5268..9923fccb01847 100644
--- a/sys/sparc64/sparc64/mp_machdep.c
+++ b/sys/sparc64/sparc64/mp_machdep.c
@@ -702,9 +702,6 @@ cheetah_ipi_selected(cpuset_t cpus, u_long d0, u_long d1, u_long d2)
IDR_CHEETAH_ALL_BUSY) != 0)
;
intr_restore(s);
- if ((ids &
- (IDR_CHEETAH_ALL_BUSY | IDR_CHEETAH_ALL_NACK)) == 0)
- return;
bnp = 0;
for (cpu = 0; cpu < mp_ncpus; cpu++) {
if (CPU_ISSET(cpu, &cpus)) {
@@ -713,11 +710,6 @@ cheetah_ipi_selected(cpuset_t cpus, u_long d0, u_long d1, u_long d2)
bnp++;
}
}
- /*
- * On at least Fire V880 we may receive IDR_NACKs for
- * CPUs we actually haven't tried to send an IPI to,
- * but which apparently can be safely ignored.
- */
if (CPU_EMPTY(&cpus))
return;
/*
diff --git a/sys/sparc64/sparc64/pmap.c b/sys/sparc64/sparc64/pmap.c
index 46c5050b2bd1d..209be106747ae 100644
--- a/sys/sparc64/sparc64/pmap.c
+++ b/sys/sparc64/sparc64/pmap.c
@@ -1340,9 +1340,9 @@ pmap_remove_tte(struct pmap *pm, struct pmap *pm2, struct tte *tp,
if ((data & TD_W) != 0)
vm_page_dirty(m);
if ((data & TD_REF) != 0)
- vm_page_flag_set(m, PG_REFERENCED);
+ vm_page_aflag_set(m, PGA_REFERENCED);
if (TAILQ_EMPTY(&m->md.tte_list))
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
pm->pm_stats.resident_count--;
}
pmap_cache_remove(m, va);
@@ -1390,7 +1390,7 @@ pmap_remove_all(vm_page_t m)
struct tte *tp;
vm_offset_t va;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_remove_all: page %p is not managed", m));
vm_page_lock_queues();
for (tp = TAILQ_FIRST(&m->md.tte_list); tp != NULL; tp = tpn) {
@@ -1403,7 +1403,7 @@ pmap_remove_all(vm_page_t m)
if ((tp->tte_data & TD_WIRED) != 0)
pm->pm_stats.wired_count--;
if ((tp->tte_data & TD_REF) != 0)
- vm_page_flag_set(m, PG_REFERENCED);
+ vm_page_aflag_set(m, PGA_REFERENCED);
if ((tp->tte_data & TD_W) != 0)
vm_page_dirty(m);
tp->tte_data &= ~TD_V;
@@ -1414,7 +1414,7 @@ pmap_remove_all(vm_page_t m)
TTE_ZERO(tp);
PMAP_UNLOCK(pm);
}
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
vm_page_unlock_queues();
}
@@ -1498,13 +1498,13 @@ pmap_enter_locked(pmap_t pm, vm_offset_t va, vm_page_t m, vm_prot_t prot,
{
struct tte *tp;
vm_paddr_t pa;
+ vm_page_t real;
u_long data;
- int i;
mtx_assert(&vm_page_queue_mtx, MA_OWNED);
PMAP_LOCK_ASSERT(pm, MA_OWNED);
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0 ||
- (m->oflags & VPO_BUSY) != 0 || VM_OBJECT_LOCKED(m->object),
+ KASSERT((m->oflags & (VPO_UNMANAGED | VPO_BUSY)) != 0 ||
+ VM_OBJECT_LOCKED(m->object),
("pmap_enter_locked: page %p is not busy", m));
PMAP_STATS_INC(pmap_nenter);
pa = VM_PAGE_TO_PHYS(m);
@@ -1514,12 +1514,9 @@ pmap_enter_locked(pmap_t pm, vm_offset_t va, vm_page_t m, vm_prot_t prot,
* physical memory, convert to the real backing page.
*/
if ((m->flags & PG_FICTITIOUS) != 0) {
- for (i = 0; phys_avail[i + 1] != 0; i += 2) {
- if (pa >= phys_avail[i] && pa <= phys_avail[i + 1]) {
- m = PHYS_TO_VM_PAGE(pa);
- break;
- }
- }
+ real = vm_phys_paddr_to_vm_page(pa);
+ if (real != NULL)
+ m = real;
}
CTR6(KTR_PMAP,
@@ -1562,8 +1559,8 @@ pmap_enter_locked(pmap_t pm, vm_offset_t va, vm_page_t m, vm_prot_t prot,
tp->tte_data |= TD_SW;
if (wired)
tp->tte_data |= TD_W;
- if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0)
- vm_page_flag_set(m, PG_WRITEABLE);
+ if ((m->oflags & VPO_UNMANAGED) == 0)
+ vm_page_aflag_set(m, PGA_WRITEABLE);
} else if ((data & TD_W) != 0)
vm_page_dirty(m);
@@ -1603,8 +1600,8 @@ pmap_enter_locked(pmap_t pm, vm_offset_t va, vm_page_t m, vm_prot_t prot,
data |= TD_P;
if ((prot & VM_PROT_WRITE) != 0) {
data |= TD_SW;
- if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0)
- vm_page_flag_set(m, PG_WRITEABLE);
+ if ((m->oflags & VPO_UNMANAGED) == 0)
+ vm_page_aflag_set(m, PGA_WRITEABLE);
}
if (prot & VM_PROT_EXECUTE) {
data |= TD_EXEC;
@@ -1945,7 +1942,7 @@ pmap_page_exists_quick(pmap_t pm, vm_page_t m)
int loops;
boolean_t rv;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_page_exists_quick: page %p is not managed", m));
loops = 0;
rv = FALSE;
@@ -1975,7 +1972,7 @@ pmap_page_wired_mappings(vm_page_t m)
int count;
count = 0;
- if ((m->flags & PG_FICTITIOUS) != 0)
+ if ((m->oflags & VPO_UNMANAGED) != 0)
return (count);
vm_page_lock_queues();
TAILQ_FOREACH(tp, &m->md.tte_list, tte_link)
@@ -2006,7 +2003,7 @@ pmap_page_is_mapped(vm_page_t m)
boolean_t rv;
rv = FALSE;
- if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0)
+ if ((m->oflags & VPO_UNMANAGED) != 0)
return (rv);
vm_page_lock_queues();
TAILQ_FOREACH(tp, &m->md.tte_list, tte_link)
@@ -2037,7 +2034,7 @@ pmap_ts_referenced(vm_page_t m)
u_long data;
int count;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_ts_referenced: page %p is not managed", m));
count = 0;
vm_page_lock_queues();
@@ -2064,18 +2061,18 @@ pmap_is_modified(vm_page_t m)
struct tte *tp;
boolean_t rv;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_is_modified: page %p is not managed", m));
rv = FALSE;
/*
- * If the page is not VPO_BUSY, then PG_WRITEABLE cannot be
- * concurrently set while the object is locked. Thus, if PG_WRITEABLE
+ * If the page is not VPO_BUSY, then PGA_WRITEABLE cannot be
+ * concurrently set while the object is locked. Thus, if PGA_WRITEABLE
* is clear, no TTEs can have TD_W set.
*/
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
if ((m->oflags & VPO_BUSY) == 0 &&
- (m->flags & PG_WRITEABLE) == 0)
+ (m->aflags & PGA_WRITEABLE) == 0)
return (rv);
vm_page_lock_queues();
TAILQ_FOREACH(tp, &m->md.tte_list, tte_link) {
@@ -2117,7 +2114,7 @@ pmap_is_referenced(vm_page_t m)
struct tte *tp;
boolean_t rv;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_is_referenced: page %p is not managed", m));
rv = FALSE;
vm_page_lock_queues();
@@ -2139,18 +2136,18 @@ pmap_clear_modify(vm_page_t m)
struct tte *tp;
u_long data;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_clear_modify: page %p is not managed", m));
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
KASSERT((m->oflags & VPO_BUSY) == 0,
("pmap_clear_modify: page %p is busy", m));
/*
- * If the page is not PG_WRITEABLE, then no TTEs can have TD_W set.
+ * If the page is not PGA_WRITEABLE, then no TTEs can have TD_W set.
* If the object containing the page is locked and the page is not
- * VPO_BUSY, then PG_WRITEABLE cannot be concurrently set.
+ * VPO_BUSY, then PGA_WRITEABLE cannot be concurrently set.
*/
- if ((m->flags & PG_WRITEABLE) == 0)
+ if ((m->aflags & PGA_WRITEABLE) == 0)
return;
vm_page_lock_queues();
TAILQ_FOREACH(tp, &m->md.tte_list, tte_link) {
@@ -2169,7 +2166,7 @@ pmap_clear_reference(vm_page_t m)
struct tte *tp;
u_long data;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_clear_reference: page %p is not managed", m));
vm_page_lock_queues();
TAILQ_FOREACH(tp, &m->md.tte_list, tte_link) {
@@ -2188,17 +2185,17 @@ pmap_remove_write(vm_page_t m)
struct tte *tp;
u_long data;
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("pmap_remove_write: page %p is not managed", m));
/*
- * If the page is not VPO_BUSY, then PG_WRITEABLE cannot be set by
- * another thread while the object is locked. Thus, if PG_WRITEABLE
+ * If the page is not VPO_BUSY, then PGA_WRITEABLE cannot be set by
+ * another thread while the object is locked. Thus, if PGA_WRITEABLE
* is clear, no page table entries need updating.
*/
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
if ((m->oflags & VPO_BUSY) == 0 &&
- (m->flags & PG_WRITEABLE) == 0)
+ (m->aflags & PGA_WRITEABLE) == 0)
return;
vm_page_lock_queues();
TAILQ_FOREACH(tp, &m->md.tte_list, tte_link) {
@@ -2210,7 +2207,7 @@ pmap_remove_write(vm_page_t m)
tlb_page_demap(TTE_GET_PMAP(tp), TTE_GET_VA(tp));
}
}
- vm_page_flag_clear(m, PG_WRITEABLE);
+ vm_page_aflag_clear(m, PGA_WRITEABLE);
vm_page_unlock_queues();
}
diff --git a/sys/sparc64/sparc64/trap.c b/sys/sparc64/sparc64/trap.c
index db05f06ba9264..7037e462ad0e9 100644
--- a/sys/sparc64/sparc64/trap.c
+++ b/sys/sparc64/sparc64/trap.c
@@ -606,6 +606,8 @@ cpu_fetch_syscall_args(struct thread *td, struct syscall_args *sa)
return (error);
}
+#include "../../kern/subr_syscall.c"
+
/*
* Syscall handler
* The arguments to the syscall are passed in the out registers by the caller,
diff --git a/sys/sparc64/sparc64/tsb.c b/sys/sparc64/sparc64/tsb.c
index 3130791e4d5aa..0f342596dd04a 100644
--- a/sys/sparc64/sparc64/tsb.c
+++ b/sys/sparc64/sparc64/tsb.c
@@ -173,7 +173,7 @@ tsb_tte_enter(pmap_t pm, vm_page_t m, vm_offset_t va, u_long sz, u_long data)
enter:
if ((m->flags & PG_FICTITIOUS) == 0) {
data |= TD_CP;
- if ((m->flags & PG_UNMANAGED) == 0) {
+ if ((m->oflags & VPO_UNMANAGED) == 0) {
pm->pm_stats.resident_count++;
data |= TD_PV;
}
diff --git a/sys/sys/buf.h b/sys/sys/buf.h
index f57d6edb7e497..972b05379fa54 100644
--- a/sys/sys/buf.h
+++ b/sys/sys/buf.h
@@ -311,6 +311,12 @@ extern const char *buf_wmesg; /* Default buffer lock message */
lockdestroy(&(bp)->b_lock)
/*
+ * Print informations on a buffer lock.
+ */
+#define BUF_LOCKPRINTINFO(bp) \
+ lockmgr_printinfo(&(bp)->b_lock)
+
+/*
* Buffer lock assertions.
*/
#if defined(INVARIANTS) && defined(INVARIANT_SUPPORT)
diff --git a/sys/sys/bus.h b/sys/sys/bus.h
index 09b8911eabecf..5dc92dfe07c68 100644
--- a/sys/sys/bus.h
+++ b/sys/sys/bus.h
@@ -596,7 +596,8 @@ struct driver_module_data {
int dmd_pass;
};
-#define EARLY_DRIVER_MODULE(name, busname, driver, devclass, evh, arg, pass) \
+#define EARLY_DRIVER_MODULE_ORDERED(name, busname, driver, devclass, \
+ evh, arg, order, pass) \
\
static struct driver_module_data name##_##busname##_driver_mod = { \
evh, arg, \
@@ -612,7 +613,16 @@ static moduledata_t name##_##busname##_mod = { \
&name##_##busname##_driver_mod \
}; \
DECLARE_MODULE(name##_##busname, name##_##busname##_mod, \
- SI_SUB_DRIVERS, SI_ORDER_MIDDLE)
+ SI_SUB_DRIVERS, order)
+
+#define EARLY_DRIVER_MODULE(name, busname, driver, devclass, evh, arg, pass) \
+ EARLY_DRIVER_MODULE_ORDERED(name, busname, driver, devclass, \
+ evh, arg, SI_ORDER_MIDDLE, pass)
+
+#define DRIVER_MODULE_ORDERED(name, busname, driver, devclass, evh, arg,\
+ order) \
+ EARLY_DRIVER_MODULE_ORDERED(name, busname, driver, devclass, \
+ evh, arg, order, BUS_PASS_DEFAULT)
#define DRIVER_MODULE(name, busname, driver, devclass, evh, arg) \
EARLY_DRIVER_MODULE(name, busname, driver, devclass, evh, arg, \
diff --git a/sys/sys/capability.h b/sys/sys/capability.h
index dee2e7a6a5117..81446a2819047 100644
--- a/sys/sys/capability.h
+++ b/sys/sys/capability.h
@@ -53,11 +53,91 @@
* mmap() and aio*() system calls will need special attention as they may
* involve reads or writes depending a great deal on context.
*/
+
+/* General file I/O. */
#define CAP_READ 0x0000000000000001ULL /* read/recv */
#define CAP_WRITE 0x0000000000000002ULL /* write/send */
#define CAP_MMAP 0x0000000000000004ULL /* mmap */
#define CAP_MAPEXEC 0x0000000000000008ULL /* mmap(2) as exec */
-#define CAP_MASK_VALID 0x000000000000000fULL
+#define CAP_FEXECVE 0x0000000000000010ULL
+#define CAP_FSYNC 0x0000000000000020ULL
+#define CAP_FTRUNCATE 0x0000000000000040ULL
+#define CAP_SEEK 0x0000000000000080ULL
+
+/* VFS methods. */
+#define CAP_FCHFLAGS 0x0000000000000100ULL
+#define CAP_FCHDIR 0x0000000000000200ULL
+#define CAP_FCHMOD 0x0000000000000400ULL
+#define CAP_FCHOWN 0x0000000000000800ULL
+#define CAP_FCNTL 0x0000000000001000ULL
+#define CAP_FPATHCONF 0x0000000000002000ULL
+#define CAP_FLOCK 0x0000000000004000ULL
+#define CAP_FSCK 0x0000000000008000ULL
+#define CAP_FSTAT 0x0000000000010000ULL
+#define CAP_FSTATFS 0x0000000000020000ULL
+#define CAP_FUTIMES 0x0000000000040000ULL
+#define CAP_CREATE 0x0000000000080000ULL
+#define CAP_DELETE 0x0000000000100000ULL
+#define CAP_MKDIR 0x0000000000200000ULL
+#define CAP_RMDIR 0x0000000000400000ULL
+#define CAP_MKFIFO 0x0000000000800000ULL
+
+/* Lookups - used to constrain *at() calls. */
+#define CAP_LOOKUP 0x0000000001000000ULL
+
+/* Extended attributes. */
+#define CAP_EXTATTR_DELETE 0x0000000002000000ULL
+#define CAP_EXTATTR_GET 0x0000000004000000ULL
+#define CAP_EXTATTR_LIST 0x0000000008000000ULL
+#define CAP_EXTATTR_SET 0x0000000010000000ULL
+
+/* Access Control Lists. */
+#define CAP_ACL_CHECK 0x0000000020000000ULL
+#define CAP_ACL_DELETE 0x0000000040000000ULL
+#define CAP_ACL_GET 0x0000000080000000ULL
+#define CAP_ACL_SET 0x0000000100000000ULL
+
+/* Socket operations. */
+#define CAP_ACCEPT 0x0000000200000000ULL
+#define CAP_BIND 0x0000000400000000ULL
+#define CAP_CONNECT 0x0000000800000000ULL
+#define CAP_GETPEERNAME 0x0000001000000000ULL
+#define CAP_GETSOCKNAME 0x0000002000000000ULL
+#define CAP_GETSOCKOPT 0x0000004000000000ULL
+#define CAP_LISTEN 0x0000008000000000ULL
+#define CAP_PEELOFF 0x0000010000000000ULL
+#define CAP_SETSOCKOPT 0x0000020000000000ULL
+#define CAP_SHUTDOWN 0x0000040000000000ULL
+
+#define CAP_SOCK_ALL \
+ (CAP_ACCEPT | CAP_BIND | CAP_CONNECT \
+ | CAP_GETPEERNAME | CAP_GETSOCKNAME | CAP_GETSOCKOPT \
+ | CAP_LISTEN | CAP_PEELOFF | CAP_SETSOCKOPT | CAP_SHUTDOWN)
+
+/* Mandatory Access Control. */
+#define CAP_MAC_GET 0x0000080000000000ULL
+#define CAP_MAC_SET 0x0000100000000000ULL
+
+/* Methods on semaphores. */
+#define CAP_SEM_GETVALUE 0x0000200000000000ULL
+#define CAP_SEM_POST 0x0000400000000000ULL
+#define CAP_SEM_WAIT 0x0000800000000000ULL
+
+/* kqueue events. */
+#define CAP_POLL_EVENT 0x0001000000000000ULL
+#define CAP_POST_EVENT 0x0002000000000000ULL
+
+/* Strange and powerful rights that should not be given lightly. */
+#define CAP_IOCTL 0x0004000000000000ULL
+#define CAP_TTYHOOK 0x0008000000000000ULL
+
+/* Process management via process descriptors. */
+#define CAP_PDGETPID 0x0010000000000000ULL
+#define CAP_PDWAIT 0x0020000000000000ULL
+#define CAP_PDKILL 0x0040000000000000ULL
+
+/* The mask of all valid method rights. */
+#define CAP_MASK_VALID 0x007fffffffffffffULL
#ifdef _KERNEL
@@ -67,7 +147,7 @@
* Create a capability to wrap a file object.
*/
int kern_capwrap(struct thread *td, struct file *fp, cap_rights_t rights,
- struct file **cap, int *capfd);
+ int *capfd);
/*
* Unwrap a capability if its rights mask is a superset of 'rights'.
diff --git a/sys/sys/file.h b/sys/sys/file.h
index eea2c0091f658..57e7047e8b326 100644
--- a/sys/sys/file.h
+++ b/sys/sys/file.h
@@ -65,6 +65,7 @@ struct socket;
#define DTYPE_PTS 10 /* pseudo teletype master device */
#define DTYPE_DEV 11 /* Device specific fd type */
#define DTYPE_CAPABILITY 12 /* capability */
+#define DTYPE_PROCDESC 13 /* process descriptor */
#ifdef _KERNEL
@@ -85,6 +86,10 @@ typedef int fo_kqfilter_t(struct file *fp, struct knote *kn);
typedef int fo_stat_t(struct file *fp, struct stat *sb,
struct ucred *active_cred, struct thread *td);
typedef int fo_close_t(struct file *fp, struct thread *td);
+typedef int fo_chmod_t(struct file *fp, mode_t mode,
+ struct ucred *active_cred, struct thread *td);
+typedef int fo_chown_t(struct file *fp, uid_t uid, gid_t gid,
+ struct ucred *active_cred, struct thread *td);
typedef int fo_flags_t;
struct fileops {
@@ -96,6 +101,8 @@ struct fileops {
fo_kqfilter_t *fo_kqfilter;
fo_stat_t *fo_stat;
fo_close_t *fo_close;
+ fo_chmod_t *fo_chmod;
+ fo_chown_t *fo_chown;
fo_flags_t fo_flags; /* DFLAG_* below */
};
@@ -176,9 +183,13 @@ extern int maxfiles; /* kernel limit on number of open files */
extern int maxfilesperproc; /* per process limit on number of open files */
extern volatile int openfiles; /* actual number of open files */
-int fget(struct thread *td, int fd, struct file **fpp);
-int fget_read(struct thread *td, int fd, struct file **fpp);
-int fget_write(struct thread *td, int fd, struct file **fpp);
+int fget(struct thread *td, int fd, cap_rights_t rights, struct file **fpp);
+int fget_mmap(struct thread *td, int fd, cap_rights_t rights,
+ u_char *maxprotp, struct file **fpp);
+int fget_read(struct thread *td, int fd, cap_rights_t rights,
+ struct file **fpp);
+int fget_write(struct thread *td, int fd, cap_rights_t rights,
+ struct file **fpp);
int fgetcap(struct thread *td, int fd, struct file **fpp);
int _fdrop(struct file *fp, struct thread *td);
@@ -196,12 +207,20 @@ fo_kqfilter_t soo_kqfilter;
fo_stat_t soo_stat;
fo_close_t soo_close;
+fo_chmod_t invfo_chmod;
+fo_chown_t invfo_chown;
+
void finit(struct file *, u_int, short, void *, struct fileops *);
-int fgetvp(struct thread *td, int fd, struct vnode **vpp);
-int fgetvp_read(struct thread *td, int fd, struct vnode **vpp);
-int fgetvp_write(struct thread *td, int fd, struct vnode **vpp);
+int fgetvp(struct thread *td, int fd, cap_rights_t rights, struct vnode **vpp);
+int fgetvp_rights(struct thread *td, int fd, cap_rights_t need,
+ cap_rights_t *have, struct vnode **vpp);
+int fgetvp_read(struct thread *td, int fd, cap_rights_t rights,
+ struct vnode **vpp);
+int fgetvp_write(struct thread *td, int fd, cap_rights_t rights,
+ struct vnode **vpp);
-int fgetsock(struct thread *td, int fd, struct socket **spp, u_int *fflagp);
+int fgetsock(struct thread *td, int fd, cap_rights_t rights,
+ struct socket **spp, u_int *fflagp);
void fputsock(struct socket *sp);
static __inline int
@@ -224,6 +243,8 @@ static __inline fo_poll_t fo_poll;
static __inline fo_kqfilter_t fo_kqfilter;
static __inline fo_stat_t fo_stat;
static __inline fo_close_t fo_close;
+static __inline fo_chmod_t fo_chmod;
+static __inline fo_chown_t fo_chown;
static __inline int
fo_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
@@ -287,6 +308,22 @@ fo_kqfilter(struct file *fp, struct knote *kn)
return ((*fp->f_ops->fo_kqfilter)(fp, kn));
}
+static __inline int
+fo_chmod(struct file *fp, mode_t mode, struct ucred *active_cred,
+ struct thread *td)
+{
+
+ return ((*fp->f_ops->fo_chmod)(fp, mode, active_cred, td));
+}
+
+static __inline int
+fo_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred,
+ struct thread *td)
+{
+
+ return ((*fp->f_ops->fo_chown)(fp, uid, gid, active_cred, td));
+}
+
#endif /* _KERNEL */
#endif /* !SYS_FILE_H */
diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h
index 2dab7416b6e08..1b87bab201d8e 100644
--- a/sys/sys/filedesc.h
+++ b/sys/sys/filedesc.h
@@ -128,7 +128,8 @@ struct filedesc *fdshare(struct filedesc *fdp);
struct filedesc_to_leader *
filedesc_to_leader_alloc(struct filedesc_to_leader *old,
struct filedesc *fdp, struct proc *leader);
-int getvnode(struct filedesc *fdp, int fd, struct file **fpp);
+int getvnode(struct filedesc *fdp, int fd, cap_rights_t rights,
+ struct file **fpp);
void mountcheckdirs(struct vnode *olddp, struct vnode *newdp);
void setugidsafety(struct thread *td);
diff --git a/sys/sys/kdb.h b/sys/sys/kdb.h
index 2982e03c75f13..61ee0973eb146 100644
--- a/sys/sys/kdb.h
+++ b/sys/sys/kdb.h
@@ -64,6 +64,8 @@ extern struct pcb *kdb_thrctx; /* Current context. */
extern struct thread *kdb_thread; /* Current thread. */
int kdb_alt_break(int, int *);
+int kdb_alt_break_gdb(int, int *);
+int kdb_break(void);
void kdb_backtrace(void);
int kdb_dbbe_select(const char *);
void kdb_enter(const char *, const char *);
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
index d6366071b91ae..ecaf7b888b077 100644
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -166,8 +166,7 @@ struct mount {
int mnt_nvnodelistsize; /* (i) # of vnodes */
int mnt_writeopcount; /* (i) write syscalls pending */
int mnt_kern_flag; /* (i) kernel only flags */
- u_int mnt_flag; /* (i) flags shared with user */
- u_int mnt_xflag; /* (i) more flags shared with user */
+ uint64_t mnt_flag; /* (i) flags shared with user */
u_int mnt_noasync; /* (i) # noasync overrides */
struct vfsoptlist *mnt_opt; /* current mount options */
struct vfsoptlist *mnt_optnew; /* new options passed to fs */
@@ -224,43 +223,44 @@ void __mnt_vnode_markerfree(struct vnode **mvp, struct mount *mp);
/*
* User specifiable flags, stored in mnt_flag.
*/
-#define MNT_RDONLY 0x00000001 /* read only filesystem */
-#define MNT_SYNCHRONOUS 0x00000002 /* filesystem written synchronously */
-#define MNT_NOEXEC 0x00000004 /* can't exec from filesystem */
-#define MNT_NOSUID 0x00000008 /* don't honor setuid bits on fs */
-#define MNT_UNION 0x00000020 /* union with underlying filesystem */
-#define MNT_ASYNC 0x00000040 /* filesystem written asynchronously */
-#define MNT_SUIDDIR 0x00100000 /* special handling of SUID on dirs */
-#define MNT_SOFTDEP 0x00200000 /* soft updates being done */
-#define MNT_NOSYMFOLLOW 0x00400000 /* do not follow symlinks */
-#define MNT_GJOURNAL 0x02000000 /* GEOM journal support enabled */
-#define MNT_MULTILABEL 0x04000000 /* MAC support for individual objects */
-#define MNT_ACLS 0x08000000 /* ACL support enabled */
-#define MNT_NOATIME 0x10000000 /* disable update of file access time */
-#define MNT_NOCLUSTERR 0x40000000 /* disable cluster read */
-#define MNT_NOCLUSTERW 0x80000000 /* disable cluster write */
-#define MNT_NFS4ACLS 0x00000010
+#define MNT_RDONLY 0x0000000000000001ULL /* read only filesystem */
+#define MNT_SYNCHRONOUS 0x0000000000000002ULL /* fs written synchronously */
+#define MNT_NOEXEC 0x0000000000000004ULL /* can't exec from filesystem */
+#define MNT_NOSUID 0x0000000000000008ULL /* don't honor setuid fs bits */
+#define MNT_NFS4ACLS 0x0000000000000010ULL /* enable NFS version 4 ACLs */
+#define MNT_UNION 0x0000000000000020ULL /* union with underlying fs */
+#define MNT_ASYNC 0x0000000000000040ULL /* fs written asynchronously */
+#define MNT_SUIDDIR 0x0000000000100000ULL /* special SUID dir handling */
+#define MNT_SOFTDEP 0x0000000000200000ULL /* using soft updates */
+#define MNT_NOSYMFOLLOW 0x0000000000400000ULL /* do not follow symlinks */
+#define MNT_GJOURNAL 0x0000000002000000ULL /* GEOM journal support enabled */
+#define MNT_MULTILABEL 0x0000000004000000ULL /* MAC support for objects */
+#define MNT_ACLS 0x0000000008000000ULL /* ACL support enabled */
+#define MNT_NOATIME 0x0000000010000000ULL /* dont update file access time */
+#define MNT_NOCLUSTERR 0x0000000040000000ULL /* disable cluster read */
+#define MNT_NOCLUSTERW 0x0000000080000000ULL /* disable cluster write */
+#define MNT_SUJ 0x0000000100000000ULL /* using journaled soft updates */
/*
* NFS export related mount flags.
*/
-#define MNT_EXRDONLY 0x00000080 /* exported read only */
-#define MNT_EXPORTED 0x00000100 /* filesystem is exported */
-#define MNT_DEFEXPORTED 0x00000200 /* exported to the world */
-#define MNT_EXPORTANON 0x00000400 /* use anon uid mapping for everyone */
-#define MNT_EXKERB 0x00000800 /* exported with Kerberos uid mapping */
-#define MNT_EXPUBLIC 0x20000000 /* public export (WebNFS) */
+#define MNT_EXRDONLY 0x0000000000000080ULL /* exported read only */
+#define MNT_EXPORTED 0x0000000000000100ULL /* filesystem is exported */
+#define MNT_DEFEXPORTED 0x0000000000000200ULL /* exported to the world */
+#define MNT_EXPORTANON 0x0000000000000400ULL /* anon uid mapping for all */
+#define MNT_EXKERB 0x0000000000000800ULL /* exported with Kerberos */
+#define MNT_EXPUBLIC 0x0000000020000000ULL /* public export (WebNFS) */
/*
* Flags set by internal operations,
* but visible to the user.
* XXX some of these are not quite right.. (I've never seen the root flag set)
*/
-#define MNT_LOCAL 0x00001000 /* filesystem is stored locally */
-#define MNT_QUOTA 0x00002000 /* quotas are enabled on filesystem */
-#define MNT_ROOTFS 0x00004000 /* identifies the root filesystem */
-#define MNT_USER 0x00008000 /* mounted by a user */
-#define MNT_IGNORE 0x00800000 /* do not show entry in df */
+#define MNT_LOCAL 0x0000000000001000ULL /* filesystem is stored locally */
+#define MNT_QUOTA 0x0000000000002000ULL /* quotas are enabled on fs */
+#define MNT_ROOTFS 0x0000000000004000ULL /* identifies the root fs */
+#define MNT_USER 0x0000000000008000ULL /* mounted by a user */
+#define MNT_IGNORE 0x0000000000800000ULL /* do not show entry in df */
/*
* Mask of flags that are visible to statfs().
@@ -268,7 +268,7 @@ void __mnt_vnode_markerfree(struct vnode **mvp, struct mount *mp);
* but the 'mount' program may need changing to handle this.
*/
#define MNT_VISFLAGMASK (MNT_RDONLY | MNT_SYNCHRONOUS | MNT_NOEXEC | \
- MNT_NOSUID | MNT_UNION | \
+ MNT_NOSUID | MNT_UNION | MNT_SUJ | \
MNT_ASYNC | MNT_EXRDONLY | MNT_EXPORTED | \
MNT_DEFEXPORTED | MNT_EXPORTANON| MNT_EXKERB | \
MNT_LOCAL | MNT_USER | MNT_QUOTA | \
@@ -293,12 +293,12 @@ void __mnt_vnode_markerfree(struct vnode **mvp, struct mount *mp);
* XXX: MNT_BYFSID collides with MNT_ACLS, but because MNT_ACLS is only used for
* mount(2) and MNT_BYFSID is only used for unmount(2) it's harmless.
*/
-#define MNT_UPDATE 0x00010000 /* not a real mount, just an update */
-#define MNT_DELEXPORT 0x00020000 /* delete export host lists */
-#define MNT_RELOAD 0x00040000 /* reload filesystem data */
-#define MNT_FORCE 0x00080000 /* force unmount or readonly change */
-#define MNT_SNAPSHOT 0x01000000 /* snapshot the filesystem */
-#define MNT_BYFSID 0x08000000 /* specify filesystem by ID. */
+#define MNT_UPDATE 0x0000000000010000ULL /* not real mount, just update */
+#define MNT_DELEXPORT 0x0000000000020000ULL /* delete export host lists */
+#define MNT_RELOAD 0x0000000000040000ULL /* reload filesystem data */
+#define MNT_FORCE 0x0000000000080000ULL /* force unmount or readonly */
+#define MNT_SNAPSHOT 0x0000000001000000ULL /* snapshot the filesystem */
+#define MNT_BYFSID 0x0000000008000000ULL /* specify filesystem by ID. */
#define MNT_CMDFLAGS (MNT_UPDATE | MNT_DELEXPORT | MNT_RELOAD | \
MNT_FORCE | MNT_SNAPSHOT | MNT_BYFSID)
/*
@@ -325,7 +325,6 @@ void __mnt_vnode_markerfree(struct vnode **mvp, struct mount *mp);
#define MNTK_REFEXPIRE 0x00000020 /* refcount expiring is happening */
#define MNTK_EXTENDED_SHARED 0x00000040 /* Allow shared locking for more ops */
#define MNTK_SHARED_WRITES 0x00000080 /* Allow shared locking for writes */
-#define MNTK_SUJ 0x00000100 /* Softdep journaling enabled */
#define MNTK_UNMOUNT 0x01000000 /* unmount in progress */
#define MNTK_MWAIT 0x02000000 /* waiting for unmount to finish */
#define MNTK_SUSPEND 0x08000000 /* request write suspension */
@@ -715,7 +714,8 @@ void vfs_event_signal(fsid_t *, u_int32_t, intptr_t);
void vfs_freeopts(struct vfsoptlist *opts);
void vfs_deleteopt(struct vfsoptlist *opts, const char *name);
int vfs_buildopts(struct uio *auio, struct vfsoptlist **options);
-int vfs_flagopt(struct vfsoptlist *opts, const char *name, u_int *w, u_int val);
+int vfs_flagopt(struct vfsoptlist *opts, const char *name, uint64_t *w,
+ uint64_t val);
int vfs_getopt(struct vfsoptlist *, const char *, void **, int *);
int vfs_getopt_pos(struct vfsoptlist *opts, const char *name);
char *vfs_getopts(struct vfsoptlist *, const char *, int *error);
diff --git a/sys/sys/namei.h b/sys/sys/namei.h
index 716b38d49f6cb..c68a7f7e0ba1d 100644
--- a/sys/sys/namei.h
+++ b/sys/sys/namei.h
@@ -63,6 +63,7 @@ struct nameidata {
*/
const char *ni_dirp; /* pathname pointer */
enum uio_seg ni_segflg; /* location of pathname */
+ cap_rights_t ni_rightsneeded; /* rights required to look up vnode */
/*
* Arguments to lookup.
*/
@@ -70,6 +71,11 @@ struct nameidata {
struct vnode *ni_rootdir; /* logical root directory */
struct vnode *ni_topdir; /* logical top directory */
int ni_dirfd; /* starting directory for *at functions */
+ int ni_strictrelative; /* relative lookup only; no '..' */
+ /*
+ * Results: returned from namei
+ */
+ cap_rights_t ni_baserights; /* rights the *at base has (or -1) */
/*
* Results: returned from/manipulated by lookup
*/
@@ -151,11 +157,13 @@ struct nameidata {
* Initialization of a nameidata structure.
*/
#define NDINIT(ndp, op, flags, segflg, namep, td) \
- NDINIT_ALL(ndp, op, flags, segflg, namep, AT_FDCWD, NULL, td)
+ NDINIT_ALL(ndp, op, flags, segflg, namep, AT_FDCWD, NULL, 0, td)
#define NDINIT_AT(ndp, op, flags, segflg, namep, dirfd, td) \
- NDINIT_ALL(ndp, op, flags, segflg, namep, dirfd, NULL, td)
+ NDINIT_ALL(ndp, op, flags, segflg, namep, dirfd, NULL, 0, td)
+#define NDINIT_ATRIGHTS(ndp, op, flags, segflg, namep, dirfd, rights, td) \
+ NDINIT_ALL(ndp, op, flags, segflg, namep, dirfd, NULL, rights, td)
#define NDINIT_ATVP(ndp, op, flags, segflg, namep, vp, td) \
- NDINIT_ALL(ndp, op, flags, segflg, namep, AT_FDCWD, vp, td)
+ NDINIT_ALL(ndp, op, flags, segflg, namep, AT_FDCWD, vp, 0, td)
static __inline void
NDINIT_ALL(struct nameidata *ndp,
@@ -164,6 +172,7 @@ NDINIT_ALL(struct nameidata *ndp,
const char *namep,
int dirfd,
struct vnode *startdir,
+ cap_rights_t rights,
struct thread *td)
{
ndp->ni_cnd.cn_nameiop = op;
@@ -172,6 +181,9 @@ NDINIT_ALL(struct nameidata *ndp,
ndp->ni_dirp = namep;
ndp->ni_dirfd = dirfd;
ndp->ni_startdir = startdir;
+ ndp->ni_strictrelative = 0;
+ ndp->ni_rightsneeded = rights;
+ ndp->ni_baserights = 0;
ndp->ni_cnd.cn_thread = td;
}
diff --git a/sys/sys/param.h b/sys/sys/param.h
index 4f54eaca13a8d..0db0223e36633 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 900039 /* Master, propagated to newvers */
+#define __FreeBSD_version 900044 /* Master, propagated to newvers */
#ifdef _KERNEL
#define P_OSREL_SIGSEGV 700004
diff --git a/sys/sys/pcpu.h b/sys/sys/pcpu.h
index b25fcc89cb065..4a4ec005c0fd2 100644
--- a/sys/sys/pcpu.h
+++ b/sys/sys/pcpu.h
@@ -146,8 +146,6 @@ struct rm_queue {
struct rm_queue* volatile rmq_prev;
};
-#define PCPU_NAME_LEN (sizeof("CPU ") + sizeof(__XSTRING(MAXCPU)) - 1)
-
/*
* This structure maps out the global data that needs to be kept on a
* per-cpu basis. The members are accessed via the PCPU_GET/SET/PTR
@@ -165,9 +163,6 @@ struct pcpu {
u_int pc_cpuid; /* This cpu number */
STAILQ_ENTRY(pcpu) pc_allcpu;
struct lock_list_entry *pc_spinlocks;
-#ifdef KTR
- char pc_name[PCPU_NAME_LEN]; /* String name for KTR */
-#endif
struct vmmeter pc_cnt; /* VM stats counters */
long pc_cp_time[CPUSTATES]; /* statclock ticks */
struct device *pc_device;
@@ -203,7 +198,7 @@ struct pcpu {
STAILQ_HEAD(cpuhead, pcpu);
extern struct cpuhead cpuhead;
-extern struct pcpu *cpuid_to_pcpu[MAXCPU];
+extern struct pcpu *cpuid_to_pcpu[];
#define curcpu PCPU_GET(cpuid)
#define curproc (curthread->td_proc)
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 233efe9856406..fb9791303ddc1 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -166,6 +166,7 @@ struct mqueue_notifier;
struct nlminfo;
struct p_sched;
struct proc;
+struct procdesc;
struct racct;
struct sleepqueue;
struct td_sched;
@@ -534,6 +535,7 @@ struct proc {
int p_boundary_count;/* (c) Num threads at user boundary */
int p_pendingcnt; /* how many signals are pending */
struct itimers *p_itimers; /* (c) POSIX interval timers. */
+ struct procdesc *p_procdesc; /* (e) Process descriptor, if any. */
/* End area that is zeroed on creation. */
#define p_endzero p_magic
@@ -822,7 +824,7 @@ int enterpgrp(struct proc *p, pid_t pgid, struct pgrp *pgrp,
int enterthispgrp(struct proc *p, struct pgrp *pgrp);
void faultin(struct proc *p);
void fixjobc(struct proc *p, struct pgrp *pgrp, int entering);
-int fork1(struct thread *, int, int, struct proc **);
+int fork1(struct thread *, int, int, struct proc **, int *, int);
void fork_exit(void (*)(void *, struct trapframe *), void *,
struct trapframe *);
void fork_return(struct thread *, struct trapframe *);
@@ -844,6 +846,8 @@ void pargs_hold(struct pargs *pa);
void procinit(void);
void proc_linkup0(struct proc *p, struct thread *td);
void proc_linkup(struct proc *p, struct thread *td);
+void proc_reap(struct thread *td, struct proc *p, int *status, int options,
+ struct rusage *rusage);
void proc_reparent(struct proc *child, struct proc *newparent);
struct pstats *pstats_alloc(void);
void pstats_fork(struct pstats *src, struct pstats *dst);
@@ -869,9 +873,6 @@ void cpu_switch(struct thread *, struct thread *, struct mtx *);
void cpu_throw(struct thread *, struct thread *) __dead2;
void unsleep(struct thread *);
void userret(struct thread *, struct trapframe *);
-struct syscall_args;
-int syscallenter(struct thread *, struct syscall_args *);
-void syscallret(struct thread *, int, struct syscall_args *);
void cpu_exit(struct thread *);
void exit1(struct thread *, int) __dead2;
diff --git a/sys/sys/procdesc.h b/sys/sys/procdesc.h
new file mode 100644
index 0000000000000..cc8b7166f6394
--- /dev/null
+++ b/sys/sys/procdesc.h
@@ -0,0 +1,119 @@
+/*-
+ * Copyright (c) 2009 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed at the University of Cambridge Computer
+ * Laboratory with support from a grant from Google, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_PROCDESC_H_
+#define _SYS_PROCDESC_H_
+
+#ifdef _KERNEL
+#include <sys/selinfo.h> /* struct selinfo */
+#include <sys/_lock.h>
+#include <sys/_mutex.h>
+
+/*-
+ * struct procdesc describes a process descriptor, and essentially consists
+ * of two pointers -- one to the file descriptor, and one to the process.
+ * When both become NULL, the process descriptor will be freed. An important
+ * invariant is that there is only ever one process descriptor for a process,
+ * so a single file pointer will suffice.
+ *
+ * Locking key:
+ * (c) - Constant after initial setup.
+ * (p) - Protected by the process descriptor mutex.
+ * (r) - Atomic eference count.
+ * (s) - Protected by selinfo.
+ * (t) - Protected by the proctree_lock
+ */
+struct proc;
+struct sigio;
+struct procdesc {
+ /*
+ * Basic process descriptor state: the process, a cache of its pid to
+ * satisfy queries after the process exits, and process descriptor
+ * refcount.
+ */
+ struct proc *pd_proc; /* (t) Process. */
+ pid_t pd_pid; /* (c) Cached pid. */
+ u_int pd_refcount; /* (r) Reference count. */
+
+ /*
+ * In-flight data and notification of events.
+ */
+ int pd_flags; /* (p) PD_ flags. */
+ struct selinfo pd_selinfo; /* (p) Event notification. */
+ struct mtx pd_lock; /* Protect data + events. */
+};
+
+/*
+ * Locking macros for the procdesc itself.
+ */
+#define PROCDESC_LOCK_DESTROY(pd) mtx_destroy(&(pd)->pd_lock)
+#define PROCDESC_LOCK_INIT(pd) mtx_init(&(pd)->pd_lock, "procdesc", NULL, \
+ MTX_DEF)
+#define PROCDESC_LOCK(pd) mtx_lock(&(pd)->pd_lock)
+#define PROCDESC_UNLOCK(pd) mtx_unlock(&(pd)->pd_lock)
+
+/*
+ * Flags for the pd_flags field.
+ */
+#define PDF_CLOSED 0x00000001 /* Descriptor has closed. */
+#define PDF_SELECTED 0x00000002 /* Issue selwakeup(). */
+#define PDF_EXITED 0x00000004 /* Process exited. */
+#define PDF_DAEMON 0x00000008 /* Don't exit when procdesc closes. */
+
+/*
+ * In-kernel interfaces to process descriptors.
+ */
+int procdesc_exit(struct proc *);
+int procdesc_find(struct thread *, int fd, cap_rights_t, struct proc **);
+int kern_pdgetpid(struct thread *, int fd, cap_rights_t, pid_t *pidp);
+void procdesc_new(struct proc *, int);
+void procdesc_finit(struct procdesc *, struct file *);
+pid_t procdesc_pid(struct file *);
+void procdesc_reap(struct proc *);
+
+#else /* !_KERNEL */
+
+/*
+ * Process descriptor system calls.
+ */
+struct rusage;
+int pdfork(int *, int);
+int pdkill(int, int);
+int pdgetpid(int, pid_t *);
+
+#endif /* _KERNEL */
+
+/*
+ * Flags which can be passed to pdfork(2).
+ */
+#define PD_DAEMON 0x00000001 /* Don't exit when procdesc closes. */
+
+#endif /* !_SYS_PROCDESC_H_ */
diff --git a/sys/sys/resourcevar.h b/sys/sys/resourcevar.h
index f17d95f644d05..d091d85e8bfc9 100644
--- a/sys/sys/resourcevar.h
+++ b/sys/sys/resourcevar.h
@@ -136,6 +136,7 @@ void rucollect(struct rusage *ru, struct rusage *ru2);
void rufetch(struct proc *p, struct rusage *ru);
void rufetchcalc(struct proc *p, struct rusage *ru, struct timeval *up,
struct timeval *sp);
+void rufetchtd(struct thread *td, struct rusage *ru);
void ruxagg(struct proc *p, struct thread *td);
int suswintr(void *base, int word);
struct uidinfo
diff --git a/sys/sys/selinfo.h b/sys/sys/selinfo.h
index 2d2f8485e7724..590d184ad17c1 100644
--- a/sys/sys/selinfo.h
+++ b/sys/sys/selinfo.h
@@ -51,6 +51,7 @@ struct selinfo {
#define SEL_WAITING(si) (!TAILQ_EMPTY(&(si)->si_tdlist))
#ifdef _KERNEL
+void seldrain(struct selinfo *sip);
void selrecord(struct thread *selector, struct selinfo *sip);
void selwakeup(struct selinfo *sip);
void selwakeuppri(struct selinfo *sip, int pri);
diff --git a/sys/sys/sockbuf.h b/sys/sys/sockbuf.h
index b8e6699902890..bfccd74f6f7a1 100644
--- a/sys/sys/sockbuf.h
+++ b/sys/sys/sockbuf.h
@@ -37,7 +37,7 @@
#include <sys/_mutex.h>
#include <sys/_sx.h>
-#define SB_MAX (256*1024) /* default for max chars in sockbuf */
+#define SB_MAX (2*1024*1024) /* default for max chars in sockbuf */
/*
* Constants for sb_flags field of struct sockbuf.
diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h
index fa4f46f3aceee..31252c1d1215f 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
+ * created from FreeBSD: head/sys/kern/syscalls.master 224987 2011-08-18 22:51:30Z jonathan
*/
#define SYS_syscall 0
@@ -434,6 +434,9 @@
#define SYS_cap_getrights 515
#define SYS_cap_enter 516
#define SYS_cap_getmode 517
+#define SYS_pdfork 518
+#define SYS_pdkill 519
+#define SYS_pdgetpid 520
#define SYS_pselect 522
#define SYS_getloginclass 523
#define SYS_setloginclass 524
diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk
index 544bbf41e05d7..e448707c53f7f 100644
--- a/sys/sys/syscall.mk
+++ b/sys/sys/syscall.mk
@@ -1,7 +1,7 @@
# FreeBSD system call names.
# DO NOT EDIT-- this file is automatically generated.
# $FreeBSD$
-# created from FreeBSD
+# created from FreeBSD: head/sys/kern/syscalls.master 224987 2011-08-18 22:51:30Z jonathan
MIASM = \
syscall.o \
exit.o \
@@ -383,6 +383,9 @@ MIASM = \
cap_getrights.o \
cap_enter.o \
cap_getmode.o \
+ pdfork.o \
+ pdkill.o \
+ pdgetpid.o \
pselect.o \
getloginclass.o \
setloginclass.o \
diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h
index 90e0449965bf8..9bcb79bd0aec8 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
+ * created from FreeBSD: head/sys/kern/syscalls.master 224987 2011-08-18 22:51:30Z jonathan
*/
#ifndef _SYS_SYSPROTO_H_
@@ -1671,6 +1671,18 @@ struct cap_enter_args {
struct cap_getmode_args {
char modep_l_[PADL_(u_int *)]; u_int * modep; char modep_r_[PADR_(u_int *)];
};
+struct pdfork_args {
+ char fdp_l_[PADL_(int *)]; int * fdp; char fdp_r_[PADR_(int *)];
+ char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
+};
+struct pdkill_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char signum_l_[PADL_(int)]; int signum; char signum_r_[PADR_(int)];
+};
+struct pdgetpid_args {
+ char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
+ char pidp_l_[PADL_(pid_t *)]; pid_t * pidp; char pidp_r_[PADR_(pid_t *)];
+};
struct pselect_args {
char nd_l_[PADL_(int)]; int nd; char nd_r_[PADR_(int)];
char in_l_[PADL_(fd_set *)]; fd_set * in; char in_r_[PADR_(fd_set *)];
@@ -2085,6 +2097,9 @@ int cap_new(struct thread *, struct cap_new_args *);
int cap_getrights(struct thread *, struct cap_getrights_args *);
int cap_enter(struct thread *, struct cap_enter_args *);
int cap_getmode(struct thread *, struct cap_getmode_args *);
+int pdfork(struct thread *, struct pdfork_args *);
+int pdkill(struct thread *, struct pdkill_args *);
+int pdgetpid(struct thread *, struct pdgetpid_args *);
int pselect(struct thread *, struct pselect_args *);
int getloginclass(struct thread *, struct getloginclass_args *);
int setloginclass(struct thread *, struct setloginclass_args *);
@@ -2772,6 +2787,9 @@ int freebsd7_shmctl(struct thread *, struct freebsd7_shmctl_args *);
#define SYS_AUE_cap_getrights AUE_CAP_GETRIGHTS
#define SYS_AUE_cap_enter AUE_CAP_ENTER
#define SYS_AUE_cap_getmode AUE_CAP_GETMODE
+#define SYS_AUE_pdfork AUE_PDFORK
+#define SYS_AUE_pdkill AUE_PDKILL
+#define SYS_AUE_pdgetpid AUE_PDGETPID
#define SYS_AUE_pselect AUE_SELECT
#define SYS_AUE_getloginclass AUE_NULL
#define SYS_AUE_setloginclass AUE_NULL
diff --git a/sys/sys/systm.h b/sys/sys/systm.h
index 8b0de573f6f7c..7e537ee4a0822 100644
--- a/sys/sys/systm.h
+++ b/sys/sys/systm.h
@@ -160,11 +160,7 @@ void *hashinit_flags(int count, struct malloc_type *type,
void *phashinit(int count, struct malloc_type *type, u_long *nentries);
void g_waitidle(void);
-#ifdef RESTARTABLE_PANICS
-void panic(const char *, ...) __printflike(1, 2);
-#else
void panic(const char *, ...) __dead2 __printflike(1, 2);
-#endif
void cpu_boot(int);
void cpu_flush_dcache(void *, size_t);
diff --git a/sys/sys/unistd.h b/sys/sys/unistd.h
index 9d56a3a427309..9e7f7e6d83426 100644
--- a/sys/sys/unistd.h
+++ b/sys/sys/unistd.h
@@ -185,11 +185,12 @@
#define RFTSIGMASK 0xFF
#define RFTSIGNUM(flags) (((flags) >> RFTSIGSHIFT) & RFTSIGMASK)
#define RFTSIGFLAGS(signum) ((signum) << RFTSIGSHIFT)
+#define RFPROCDESC (1<<28) /* return a process descriptor */
#define RFPPWAIT (1<<31) /* parent sleeps until child exits (vfork) */
-#define RFKERNELONLY (RFSTOPPED | RFHIGHPID | RFPPWAIT)
#define RFFLAGS (RFFDG | RFPROC | RFMEM | RFNOWAIT | RFCFDG | \
RFTHREAD | RFSIGSHARE | RFLINUXTHPN | RFSTOPPED | RFHIGHPID | RFTSIGZMB | \
- RFPPWAIT)
+ RFPROCDESC | RFPPWAIT)
+#define RFKERNELONLY (RFSTOPPED | RFHIGHPID | RFPPWAIT | RFPROCDESC)
#endif /* __BSD_VISIBLE */
diff --git a/sys/sys/user.h b/sys/sys/user.h
index 644f9113edd55..a139d4fdfabec 100644
--- a/sys/sys/user.h
+++ b/sys/sys/user.h
@@ -95,13 +95,18 @@
#define WMESGLEN 8 /* size of returned wchan message */
#define LOCKNAMELEN 8 /* size of returned lock name */
-#define OCOMMLEN 16 /* size of returned thread name */
+#define TDNAMLEN 16 /* size of returned thread name */
#define COMMLEN 19 /* size of returned ki_comm name */
#define KI_EMULNAMELEN 16 /* size of returned ki_emul */
#define KI_NGROUPS 16 /* number of groups in ki_groups */
#define LOGNAMELEN 17 /* size of returned ki_login */
#define LOGINCLASSLEN 17 /* size of returned ki_loginclass */
+#ifndef BURN_BRIDGES
+#define OCOMMLEN TDNAMLEN
+#define ki_ocomm ki_tdname
+#endif
+
/* Flags for the process credential. */
#define KI_CRF_CAPABILITY_MODE 0x00000001
/*
@@ -167,7 +172,7 @@ struct kinfo_proc {
char ki_rqindex; /* Run queue index */
u_char ki_oncpu; /* Which cpu we are on */
u_char ki_lastcpu; /* Last cpu we were on */
- char ki_ocomm[OCOMMLEN+1]; /* thread name */
+ char ki_tdname[TDNAMLEN+1]; /* thread name */
char ki_wmesg[WMESGLEN+1]; /* wchan message */
char ki_login[LOGNAMELEN+1]; /* setlogin name */
char ki_lockname[LOCKNAMELEN+1]; /* lock name */
@@ -246,6 +251,8 @@ struct user {
#define KF_TYPE_SHM 8
#define KF_TYPE_SEM 9
#define KF_TYPE_PTS 10
+/* no KF_TYPE_CAPABILITY (11), since capabilities wrap other file objects */
+#define KF_TYPE_PROCDESC 12
#define KF_TYPE_UNKNOWN 255
#define KF_VTYPE_VNON 0
@@ -281,6 +288,7 @@ struct user {
#define KF_FLAG_TRUNC 0x00001000
#define KF_FLAG_EXCL 0x00002000
#define KF_FLAG_EXEC 0x00004000
+#define KF_FLAG_CAPABILITY 0x00008000
/*
* Old format. Has variable hidden padding due to alignment.
@@ -370,10 +378,15 @@ struct kinfo_file {
/* Round to 64 bit alignment. */
uint32_t kf_pts_pad0[7];
} kf_pts;
+ struct {
+ pid_t kf_pid;
+ } kf_proc;
} kf_un;
uint16_t kf_status; /* Status flags. */
uint16_t kf_pad1; /* Round to 32 bit alignment. */
- int _kf_ispare[7]; /* Space for more stuff. */
+ int _kf_ispare0; /* Space for more stuff. */
+ cap_rights_t kf_cap_rights; /* Capability rights. */
+ int _kf_ispare[4]; /* Space for more stuff. */
/* Truncated before copyout in sysctl */
char kf_path[PATH_MAX]; /* Path to file, if any. */
};
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index 1c4c7b7dab7b9..4cb6633d4cc8c 100644
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -640,6 +640,7 @@ int _vn_lock(struct vnode *vp, int flags, char *file, int line);
int vn_open(struct nameidata *ndp, int *flagp, int cmode, struct file *fp);
int vn_open_cred(struct nameidata *ndp, int *flagp, int cmode,
u_int vn_open_flags, struct ucred *cred, struct file *fp);
+void vn_pages_remove(struct vnode *vp, vm_pindex_t start, vm_pindex_t end);
int vn_pollrecord(struct vnode *vp, struct thread *p, int events);
int vn_rdwr(enum uio_rw rw, struct vnode *vp, void *base,
int len, off_t offset, enum uio_seg segflg, int ioflg,
@@ -778,7 +779,15 @@ void vfs_mark_atime(struct vnode *vp, struct ucred *cred);
struct dirent;
int vfs_read_dirent(struct vop_readdir_args *ap, struct dirent *dp, off_t off);
-int vfs_unixify_accmode(accmode_t *accmode);
+int vfs_unixify_accmode(accmode_t *accmode);
+
+int setfmode(struct thread *td, struct ucred *cred, struct vnode *vp, int mode);
+int setfown(struct thread *td, struct ucred *cred, struct vnode *vp, uid_t uid,
+ gid_t gid);
+int vn_chmod(struct file *fp, mode_t mode, struct ucred *active_cred,
+ struct thread *td);
+int vn_chown(struct file *fp, uid_t uid, gid_t gid, struct ucred *active_cred,
+ struct thread *td);
#endif /* _KERNEL */
diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c
index 82506fbe3be4f..5f984b4b6ba37 100644
--- a/sys/ufs/ffs/ffs_alloc.c
+++ b/sys/ufs/ffs/ffs_alloc.c
@@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$");
#include "opt_quota.h"
#include <sys/param.h>
+#include <sys/capability.h>
#include <sys/systm.h>
#include <sys/bio.h>
#include <sys/buf.h>
@@ -1967,7 +1968,7 @@ ffs_blkfree_cg(ump, fs, devvp, bno, size, inum, dephd)
ACTIVECLEAR(fs, cg);
UFS_UNLOCK(ump);
mp = UFSTOVFS(ump);
- if (mp->mnt_flag & MNT_SOFTDEP && devvp->v_type != VREG)
+ if (MOUNTEDSOFTDEP(mp) && devvp->v_type != VREG)
softdep_setup_blkfree(UFSTOVFS(ump), bp, bno,
numfrags(fs, size), dephd);
bdwrite(bp);
@@ -2217,7 +2218,7 @@ ffs_freefile(ump, fs, devvp, ino, mode, wkhd)
fs->fs_fmod = 1;
ACTIVECLEAR(fs, cg);
UFS_UNLOCK(ump);
- if (UFSTOVFS(ump)->mnt_flag & MNT_SOFTDEP && devvp->v_type != VREG)
+ if (MOUNTEDSOFTDEP(UFSTOVFS(ump)) && devvp->v_type != VREG)
softdep_setup_inofree(UFSTOVFS(ump), bp,
ino + cg * fs->fs_ipg, wkhd);
bdwrite(bp);
@@ -2447,7 +2448,7 @@ static SYSCTL_NODE(_vfs_ffs, FFS_SET_BUFOUTPUT, setbufoutput, CTLFLAG_WR,
#define DEBUG 1
#ifdef DEBUG
-static int fsckcmds = 1;
+static int fsckcmds = 0;
SYSCTL_INT(_debug, OID_AUTO, fsckcmds, CTLFLAG_RW, &fsckcmds, 0, "");
#endif /* DEBUG */
@@ -2470,7 +2471,6 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS)
struct file *fp, *vfp;
int vfslocked, filetype, error;
static struct fileops *origops, bufferedops;
- static int outcnt = 0;
if (req->newlen > sizeof cmd)
return (EBADRPC);
@@ -2478,7 +2478,8 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS)
return (error);
if (cmd.version != FFS_CMD_VERSION)
return (ERPCMISMATCH);
- if ((error = getvnode(td->td_proc->p_fd, cmd.handle, &fp)) != 0)
+ if ((error = getvnode(td->td_proc->p_fd, cmd.handle, CAP_FSCK,
+ &fp)) != 0)
return (error);
vp = fp->f_data;
if (vp->v_type != VREG && vp->v_type != VDIR) {
@@ -2755,7 +2756,7 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS)
break;
}
#ifdef DEBUG
- if (fsckcmds && outcnt++ < 100) {
+ if (fsckcmds) {
printf("%s: update inode %jd\n",
mp->mnt_stat.f_mntonname, (intmax_t)cmd.value);
}
@@ -2799,7 +2800,8 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS)
(intmax_t)cmd.value);
}
#endif /* DEBUG */
- if ((error = getvnode(td->td_proc->p_fd, cmd.value, &vfp)) != 0)
+ if ((error = getvnode(td->td_proc->p_fd, cmd.value,
+ CAP_FSCK, &vfp)) != 0)
break;
if (vfp->f_vnode->v_type != VCHR) {
fdrop(vfp, td);
@@ -2857,7 +2859,6 @@ buffered_write(fp, uio, active_cred, flags, td)
struct fs *fs;
int error, vfslocked;
daddr_t lbn;
- static int outcnt = 0;
/*
* The devvp is associated with the /dev filesystem. To discover
@@ -2875,7 +2876,7 @@ buffered_write(fp, uio, active_cred, flags, td)
if ((flags & FOF_OFFSET) == 0)
uio->uio_offset = fp->f_offset;
#ifdef DEBUG
- if (fsckcmds && outcnt++ < 100) {
+ if (fsckcmds) {
printf("%s: buffered write for block %jd\n",
fs->fs_fsmnt, (intmax_t)btodb(uio->uio_offset));
}
diff --git a/sys/ufs/ffs/ffs_extern.h b/sys/ufs/ffs/ffs_extern.h
index 70bcf1df4f792..bfc02564824f8 100644
--- a/sys/ufs/ffs/ffs_extern.h
+++ b/sys/ufs/ffs/ffs_extern.h
@@ -79,7 +79,6 @@ int ffs_isfreeblock(struct fs *, u_char *, ufs1_daddr_t);
void ffs_load_inode(struct buf *, struct inode *, struct fs *, ino_t);
int ffs_mountroot(void);
void ffs_oldfscompat_write(struct fs *, struct ufsmount *);
-void ffs_pages_remove(struct vnode *vp, vm_pindex_t start, vm_pindex_t end);
int ffs_reallocblks(struct vop_reallocblks_args *);
int ffs_realloccg(struct inode *, ufs2_daddr_t, ufs2_daddr_t,
ufs2_daddr_t, int, int, int, struct ucred *, struct buf **);
diff --git a/sys/ufs/ffs/ffs_inode.c b/sys/ufs/ffs/ffs_inode.c
index 0034029df91ac..101bdb43aa97f 100644
--- a/sys/ufs/ffs/ffs_inode.c
+++ b/sys/ufs/ffs/ffs_inode.c
@@ -120,18 +120,6 @@ ffs_update(vp, waitfor)
}
}
-void
-ffs_pages_remove(struct vnode *vp, vm_pindex_t start, vm_pindex_t end)
-{
- vm_object_t object;
-
- if ((object = vp->v_object) == NULL)
- return;
- VM_OBJECT_LOCK(object);
- vm_object_page_remove(object, start, end, 0);
- VM_OBJECT_UNLOCK(object);
-}
-
#define SINGLE 0 /* index of single indirect block */
#define DOUBLE 1 /* index of double indirect block */
#define TRIPLE 2 /* index of triple indirect block */
@@ -219,7 +207,7 @@ ffs_truncate(vp, length, flags, cred, td)
(void) chkdq(ip, -extblocks, NOCRED, 0);
#endif
vinvalbuf(vp, V_ALT, 0, 0);
- ffs_pages_remove(vp,
+ vn_pages_remove(vp,
OFF_TO_IDX(lblktosize(fs, -extblocks)), 0);
osize = ip->i_din2->di_extsize;
ip->i_din2->di_blocks -= extblocks;
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index fccb296973468..6cf033a432939 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -1364,7 +1364,7 @@ softdep_flush(void)
mtx_lock(&mountlist_mtx);
for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
nmp = TAILQ_NEXT(mp, mnt_list);
- if ((mp->mnt_flag & MNT_SOFTDEP) == 0)
+ if (MOUNTEDSOFTDEP(mp) == 0)
continue;
if (vfs_busy(mp, MBF_NOWAIT | MBF_MNTLSTLOCK))
continue;
@@ -2423,11 +2423,11 @@ softdep_unmount(mp)
MNT_ILOCK(mp);
mp->mnt_flag &= ~MNT_SOFTDEP;
- if ((mp->mnt_kern_flag & MNTK_SUJ) == 0) {
+ if (MOUNTEDSUJ(mp) == 0) {
MNT_IUNLOCK(mp);
return;
}
- mp->mnt_kern_flag &= ~MNTK_SUJ;
+ mp->mnt_flag &= ~MNT_SUJ;
MNT_IUNLOCK(mp);
journal_unmount(mp);
}
@@ -2637,7 +2637,8 @@ journal_mount(mp, fs, cred)
out:
if (error == 0) {
MNT_ILOCK(mp);
- mp->mnt_kern_flag |= MNTK_SUJ;
+ mp->mnt_flag |= MNT_SUJ;
+ mp->mnt_flag &= ~MNT_SOFTDEP;
MNT_IUNLOCK(mp);
/*
* Only validate the journal contents if the
@@ -3060,7 +3061,7 @@ softdep_flushjournal(mp)
struct jblocks *jblocks;
struct ufsmount *ump;
- if ((mp->mnt_kern_flag & MNTK_SUJ) == 0)
+ if (MOUNTEDSUJ(mp) == 0)
return;
ump = VFSTOUFS(mp);
jblocks = ump->softdep_jblocks;
@@ -3096,7 +3097,7 @@ softdep_process_journal(mp, needwk, flags)
int off;
int devbsize;
- if ((mp->mnt_kern_flag & MNTK_SUJ) == 0)
+ if (MOUNTEDSUJ(mp) == 0)
return;
ump = VFSTOUFS(mp);
fs = ump->um_fs;
@@ -3827,8 +3828,8 @@ newfreework(ump, freeblks, parent, lbn, nb, frags, off, journal)
freework->fw_blkno = nb;
freework->fw_frags = frags;
freework->fw_indir = NULL;
- freework->fw_ref = ((UFSTOVFS(ump)->mnt_kern_flag & MNTK_SUJ) == 0 ||
- lbn >= -NXADDR) ? 0 : NINDIR(ump->um_fs) + 1;
+ freework->fw_ref = (MOUNTEDSUJ(UFSTOVFS(ump)) == 0 || lbn >= -NXADDR)
+ ? 0 : NINDIR(ump->um_fs) + 1;
freework->fw_start = freework->fw_off = off;
if (journal)
newjfreeblk(freeblks, lbn, nb, frags);
@@ -4681,7 +4682,7 @@ softdep_setup_inomapdep(bp, ip, newinum, mode)
* Allocate the journal reference add structure so that the bitmap
* can be dependent on it.
*/
- if (mp->mnt_kern_flag & MNTK_SUJ) {
+ if (MOUNTEDSUJ(mp)) {
jaddref = newjaddref(ip, newinum, 0, 0, mode);
jaddref->ja_state |= NEWBLOCK;
}
@@ -4734,7 +4735,7 @@ softdep_setup_blkmapdep(bp, mp, newblkno, frags, oldfrags)
* Add it to the dependency list for the buffer holding
* the cylinder group map from which it was allocated.
*/
- if (mp->mnt_kern_flag & MNTK_SUJ) {
+ if (MOUNTEDSUJ(mp)) {
jnewblk = malloc(sizeof(*jnewblk), M_JNEWBLK, M_SOFTDEP_FLAGS);
workitem_alloc(&jnewblk->jn_list, D_JNEWBLK, mp);
jnewblk->jn_jsegdep = newjsegdep(&jnewblk->jn_list);
@@ -5199,7 +5200,7 @@ newfreefrag(ip, blkno, size, lbn)
freefrag->ff_blkno = blkno;
freefrag->ff_fragsize = size;
- if ((ip->i_ump->um_mountp->mnt_kern_flag & MNTK_SUJ) != 0) {
+ if (MOUNTEDSUJ(UFSTOVFS(ip->i_ump))) {
freefrag->ff_jdep = (struct worklist *)
newjfreefrag(freefrag, ip, blkno, size, lbn);
} else {
@@ -6540,7 +6541,7 @@ trunc_pages(ip, length, extblocks, flags)
fs = ip->i_fs;
extend = OFF_TO_IDX(lblktosize(fs, -extblocks));
if ((flags & IO_EXT) != 0)
- ffs_pages_remove(vp, extend, 0);
+ vn_pages_remove(vp, extend, 0);
if ((flags & IO_NORMAL) == 0)
return;
BO_LOCK(&vp->v_bufobj);
@@ -6566,7 +6567,7 @@ trunc_pages(ip, length, extblocks, flags)
end = OFF_TO_IDX(lblktosize(fs, lbn));
} else
end = extend;
- ffs_pages_remove(vp, OFF_TO_IDX(OFF_MAX), end);
+ vn_pages_remove(vp, OFF_TO_IDX(OFF_MAX), end);
}
/*
@@ -7254,7 +7255,7 @@ freework_freeblock(freework)
freeblks = freework->fw_freeblks;
ump = VFSTOUFS(freeblks->fb_list.wk_mp);
fs = ump->um_fs;
- needj = freeblks->fb_list.wk_mp->mnt_kern_flag & MNTK_SUJ;
+ needj = MOUNTEDSUJ(freeblks->fb_list.wk_mp) != 0;
bsize = lfragtosize(fs, freework->fw_frags);
LIST_INIT(&wkhd);
/*
@@ -7674,7 +7675,7 @@ indir_trunc(freework, dbn, lbn)
ufs1fmt = 0;
}
level = lbn_level(lbn);
- needj = UFSTOVFS(ump)->mnt_kern_flag & MNTK_SUJ;
+ needj = MOUNTEDSUJ(UFSTOVFS(ump)) != 0;
lbnadd = lbn_offset(fs, level);
nblocks = btodb(fs->fs_bsize);
nfreework = freework;
@@ -7860,7 +7861,7 @@ setup_newdir(dap, newinum, dinum, newdirbp, mkdirp)
mkdir2->md_state = ATTACHED | MKDIR_PARENT;
mkdir2->md_diradd = dap;
mkdir2->md_jaddref = NULL;
- if ((mp->mnt_kern_flag & MNTK_SUJ) == 0) {
+ if (MOUNTEDSUJ(mp) == 0) {
mkdir1->md_state |= DEPCOMPLETE;
mkdir2->md_state |= DEPCOMPLETE;
}
@@ -7900,7 +7901,7 @@ setup_newdir(dap, newinum, dinum, newdirbp, mkdirp)
* been satisfied and mkdir2 can be freed.
*/
inodedep_lookup(mp, dinum, 0, &inodedep);
- if (mp->mnt_kern_flag & MNTK_SUJ) {
+ if (MOUNTEDSUJ(mp)) {
if (inodedep == NULL)
panic("setup_newdir: Lost parent.");
jaddref = (struct jaddref *)TAILQ_LAST(&inodedep->id_inoreflst,
@@ -8031,7 +8032,7 @@ softdep_setup_directory_add(bp, dp, diroffset, newinum, newdirbp, isnewblk)
* written place it on the bufwait list, otherwise do the post-inode
* write processing to put it on the id_pendinghd list.
*/
- if (mp->mnt_kern_flag & MNTK_SUJ) {
+ if (MOUNTEDSUJ(mp)) {
jaddref = (struct jaddref *)TAILQ_LAST(&inodedep->id_inoreflst,
inoreflst);
KASSERT(jaddref != NULL && jaddref->ja_parent == dp->i_number,
@@ -8047,7 +8048,7 @@ softdep_setup_directory_add(bp, dp, diroffset, newinum, newdirbp, isnewblk)
* Add the journal entries for . and .. links now that the primary
* link is written.
*/
- if (mkdir1 != NULL && mp->mnt_kern_flag & MNTK_SUJ) {
+ if (mkdir1 != NULL && MOUNTEDSUJ(mp)) {
jaddref = (struct jaddref *)TAILQ_PREV(&jaddref->ja_ref,
inoreflst, if_deps);
KASSERT(jaddref != NULL &&
@@ -8144,7 +8145,7 @@ softdep_change_directoryentry_offset(bp, dp, base, oldloc, newloc, entrysize)
* determine if any affected adds or removes are present in the
* journal.
*/
- if (mp->mnt_kern_flag & MNTK_SUJ) {
+ if (MOUNTEDSUJ(mp)) {
flags = DEPALLOC;
jmvref = newjmvref(dp, de->d_ino,
dp->i_offset + (oldloc - base),
@@ -8865,7 +8866,7 @@ softdep_setup_directory_change(bp, dp, ip, newinum, isrmdir)
* processing to put it on the id_pendinghd list.
*/
inodedep_lookup(mp, newinum, DEPALLOC, &inodedep);
- if (mp->mnt_kern_flag & MNTK_SUJ) {
+ if (MOUNTEDSUJ(mp)) {
jaddref = (struct jaddref *)TAILQ_LAST(&inodedep->id_inoreflst,
inoreflst);
KASSERT(jaddref != NULL && jaddref->ja_parent == dp->i_number,
@@ -8928,7 +8929,7 @@ softdep_setup_sbupdate(ump, fs, bp)
struct sbdep *sbdep;
struct worklist *wk;
- if ((ump->um_mountp->mnt_kern_flag & MNTK_SUJ) == 0)
+ if (MOUNTEDSUJ(UFSTOVFS(ump)) == 0)
return;
LIST_FOREACH(wk, &bp->b_dep, wk_list)
if (wk->wk_type == D_SBDEP)
@@ -9046,7 +9047,7 @@ unlinked_inodedep(mp, inodedep)
{
struct ufsmount *ump;
- if ((mp->mnt_kern_flag & MNTK_SUJ) == 0)
+ if (MOUNTEDSUJ(mp) == 0)
return;
ump = VFSTOUFS(mp);
ump->um_fs->fs_fmod = 1;
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index 35852bf9410e9..4f688a2aa940c 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -281,7 +281,7 @@ ffs_mount(struct mount *mp)
flags = WRITECLOSE;
if (mp->mnt_flag & MNT_FORCE)
flags |= FORCECLOSE;
- if (mp->mnt_flag & MNT_SOFTDEP) {
+ if (MOUNTEDSOFTDEP(mp)) {
error = softdep_flushfiles(mp, flags, td);
} else {
error = ffs_flushfiles(mp, flags, td);
@@ -307,7 +307,7 @@ ffs_mount(struct mount *mp)
vfs_write_resume(mp);
return (error);
}
- if (mp->mnt_flag & MNT_SOFTDEP)
+ if (MOUNTEDSOFTDEP(mp))
softdep_unmount(mp);
DROP_GIANT();
g_topology_lock();
@@ -411,7 +411,7 @@ ffs_mount(struct mount *mp)
* Softdep_mount() clears it in an initial mount
* or ro->rw remount.
*/
- if (mp->mnt_flag & MNT_SOFTDEP) {
+ if (MOUNTEDSOFTDEP(mp)) {
/* XXX: Reset too late ? */
MNT_ILOCK(mp);
mp->mnt_flag &= ~MNT_ASYNC;
@@ -443,7 +443,7 @@ ffs_mount(struct mount *mp)
fs->fs_fsmnt);
return (EINVAL);
}
- KASSERT((mp->mnt_flag & MNT_SOFTDEP) == 0,
+ KASSERT(MOUNTEDSOFTDEP(mp) == 0,
("soft updates enabled on read-only file system"));
DROP_GIANT();
g_topology_lock();
@@ -530,7 +530,7 @@ ffs_mount(struct mount *mp)
return (error);
}
if (fsckpid > 0) {
- KASSERT((mp->mnt_flag & MNT_SOFTDEP) == 0,
+ KASSERT(MOUNTEDSOFTDEP(mp) == 0,
("soft updates enabled on read-only file system"));
ump = VFSTOUFS(mp);
fs = ump->um_fs;
@@ -1247,7 +1247,7 @@ ffs_unmount(mp, mntflags)
vn_start_write(NULL, &mp, V_WAIT);
}
}
- if (mp->mnt_flag & MNT_SOFTDEP)
+ if (MOUNTEDSOFTDEP(mp))
error = softdep_flushfiles(mp, flags, td);
else
error = ffs_flushfiles(mp, flags, td);
diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c
index 9f528dac997b8..81c7af40811f8 100644
--- a/sys/ufs/ffs/ffs_vnops.c
+++ b/sys/ufs/ffs/ffs_vnops.c
@@ -187,8 +187,7 @@ retry:
error = ffs_syncvnode(vp, ap->a_waitfor);
if (error)
return (error);
- if (ap->a_waitfor == MNT_WAIT &&
- (vp->v_mount->mnt_flag & MNT_SOFTDEP)) {
+ if (ap->a_waitfor == MNT_WAIT && DOINGSOFTDEP(vp)) {
error = softdep_fsync(vp);
if (error)
return (error);
diff --git a/sys/ufs/ufs/inode.h b/sys/ufs/ufs/inode.h
index 7adcc73e1b429..6f3d6f9853ea5 100644
--- a/sys/ufs/ufs/inode.h
+++ b/sys/ufs/ufs/inode.h
@@ -174,9 +174,11 @@ struct indir {
#define ITOV(ip) ((ip)->i_vnode)
/* Determine if soft dependencies are being done */
-#define DOINGSOFTDEP(vp) ((vp)->v_mount->mnt_flag & MNT_SOFTDEP)
-#define DOINGASYNC(vp) ((vp)->v_mount->mnt_kern_flag & MNTK_ASYNC)
-#define DOINGSUJ(vp) ((vp)->v_mount->mnt_kern_flag & MNTK_SUJ)
+#define DOINGSOFTDEP(vp) ((vp)->v_mount->mnt_flag & (MNT_SOFTDEP | MNT_SUJ))
+#define MOUNTEDSOFTDEP(mp) ((mp)->mnt_flag & (MNT_SOFTDEP | MNT_SUJ))
+#define DOINGASYNC(vp) ((vp)->v_mount->mnt_kern_flag & MNTK_ASYNC)
+#define DOINGSUJ(vp) ((vp)->v_mount->mnt_flag & MNT_SUJ)
+#define MOUNTEDSUJ(mp) ((mp)->mnt_flag & MNT_SUJ)
/* This overlays the fid structure (see mount.h). */
struct ufid {
diff --git a/sys/ufs/ufs/ufs_extattr.c b/sys/ufs/ufs/ufs_extattr.c
index 032d9cc34211d..777f3851604f2 100644
--- a/sys/ufs/ufs/ufs_extattr.c
+++ b/sys/ufs/ufs/ufs_extattr.c
@@ -1031,14 +1031,14 @@ vop_setextattr {
struct ufsmount *ump = VFSTOUFS(mp);
int error;
- ufs_extattr_uepm_lock(ump, ap->a_td);
-
/*
* XXX: No longer a supported way to delete extended attributes.
*/
if (ap->a_uio == NULL)
return (EINVAL);
+ ufs_extattr_uepm_lock(ump, ap->a_td);
+
error = ufs_extattr_set(ap->a_vp, ap->a_attrnamespace, ap->a_name,
ap->a_uio, ap->a_cred, ap->a_td);
diff --git a/sys/vm/device_pager.c b/sys/vm/device_pager.c
index 411482a3cc25c..d46d17055b6ee 100644
--- a/sys/vm/device_pager.c
+++ b/sys/vm/device_pager.c
@@ -147,6 +147,7 @@ dev_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot,
object1 = vm_object_allocate(OBJT_DEVICE, pindex);
object1->flags |= OBJ_COLORED;
object1->pg_color = atop(paddr) - OFF_TO_IDX(off - PAGE_SIZE);
+ TAILQ_INIT(&object1->un_pager.devp.devp_pglist);
mtx_lock(&dev_pager_mtx);
object = vm_pager_object_lookup(&dev_pager_object_list, handle);
if (object != NULL) {
@@ -159,7 +160,6 @@ dev_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot,
object = object1;
object1 = NULL;
object->handle = handle;
- TAILQ_INIT(&object->un_pager.devp.devp_pglist);
TAILQ_INSERT_TAIL(&dev_pager_object_list, object,
pager_object_list);
}
@@ -169,7 +169,14 @@ dev_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot,
}
mtx_unlock(&dev_pager_mtx);
dev_relthread(dev, ref);
- vm_object_deallocate(object1);
+ if (object1 != NULL) {
+ object1->handle = object1;
+ mtx_lock(&dev_pager_mtx);
+ TAILQ_INSERT_TAIL(&dev_pager_object_list, object1,
+ pager_object_list);
+ mtx_unlock(&dev_pager_mtx);
+ vm_object_deallocate(object1);
+ }
return (object);
}
diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c
index f421e4fa7881c..d7da4f919126d 100644
--- a/sys/vm/swap_pager.c
+++ b/sys/vm/swap_pager.c
@@ -114,9 +114,9 @@ __FBSDID("$FreeBSD$");
#include <geom/geom.h>
/*
- * SWB_NPAGES must be a power of 2. It may be set to 1, 2, 4, 8, or 16
- * pages per allocation. We recommend you stick with the default of 8.
- * The 16-page limit is due to the radix code (kern/subr_blist.c).
+ * SWB_NPAGES must be a power of 2. It may be set to 1, 2, 4, 8, 16
+ * or 32 pages per allocation.
+ * The 32-page limit is due to the radix code (kern/subr_blist.c).
*/
#ifndef MAX_PAGEOUT_CLUSTER
#define MAX_PAGEOUT_CLUSTER 16
@@ -127,14 +127,11 @@ __FBSDID("$FreeBSD$");
#endif
/*
- * Piecemeal swap metadata structure. Swap is stored in a radix tree.
- *
- * If SWB_NPAGES is 8 and sizeof(char *) == sizeof(daddr_t), our radix
- * is basically 8. Assuming PAGE_SIZE == 4096, one tree level represents
- * 32K worth of data, two levels represent 256K, three levels represent
- * 2 MBytes. This is acceptable.
- *
- * Overall memory utilization is about the same as the old swap structure.
+ * The swblock structure maps an object and a small, fixed-size range
+ * of page indices to disk addresses within a swap area.
+ * The collection of these mappings is implemented as a hash table.
+ * Unused disk addresses within a swap area are allocated and managed
+ * using a blist.
*/
#define SWCORRECT(n) (sizeof(void *) * (n) / sizeof(daddr_t))
#define SWAP_META_PAGES (SWB_NPAGES * 2)
@@ -662,9 +659,7 @@ swap_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot,
* routine is typically called only when the entire object is
* about to be destroyed.
*
- * This routine may block, but no longer does.
- *
- * The object must be locked or unreferenceable.
+ * The object must be locked.
*/
static void
swap_pager_dealloc(vm_object_t object)
@@ -706,7 +701,7 @@ swap_pager_dealloc(vm_object_t object)
* Also has the side effect of advising that somebody made a mistake
* when they configured swap and didn't configure enough.
*
- * This routine may not block
+ * This routine may not sleep.
*
* We allocate in round-robin fashion from the configured devices.
*/
@@ -776,10 +771,7 @@ swp_pager_strategy(struct buf *bp)
*
* This routine returns the specified swap blocks back to the bitmap.
*
- * Note: This routine may not block (it could in the old swap code),
- * and through the use of the new blist routines it does not block.
- *
- * This routine may not block
+ * This routine may not sleep.
*/
static void
swp_pager_freeswapspace(daddr_t blk, int npages)
@@ -875,21 +867,16 @@ swap_pager_reserve(vm_object_t object, vm_pindex_t start, vm_size_t size)
* cases where both the source and destination have a valid swapblk,
* we keep the destination's.
*
- * This routine is allowed to block. It may block allocating metadata
+ * This routine is allowed to sleep. It may sleep allocating metadata
* indirectly through swp_pager_meta_build() or if paging is still in
* progress on the source.
*
- * XXX vm_page_collapse() kinda expects us not to block because we
- * supposedly do not need to allocate memory, but for the moment we
- * *may* have to get a little memory from the zone allocator, but
- * it is taken from the interrupt memory. We should be ok.
- *
* The source object contains no vm_page_t's (which is just as well)
*
* The source object is of type OBJT_SWAP.
*
- * The source and destination objects must be locked or
- * inaccessible (XXX are they ?)
+ * The source and destination objects must be locked.
+ * Both object locks may temporarily be released.
*/
void
swap_pager_copy(vm_object_t srcobject, vm_object_t dstobject,
@@ -1066,7 +1053,7 @@ swap_pager_haspage(vm_object_t object, vm_pindex_t pindex, int *before, int *aft
* does NOT change the m->dirty status of the page. Also: MADV_FREE
* depends on it.
*
- * This routine may not block
+ * This routine may not sleep.
*/
static void
swap_pager_unswapped(vm_page_t m)
@@ -1472,7 +1459,7 @@ swap_pager_putpages(vm_object_t object, vm_page_t *m, int count,
* operations, we vm_page_t->busy'd unbusy all pages ( we can do this
* because we marked them all VM_PAGER_PEND on return from putpages ).
*
- * This routine may not block.
+ * This routine may not sleep.
*/
static void
swp_pager_async_iodone(struct buf *bp)
@@ -1606,7 +1593,7 @@ swp_pager_async_iodone(struct buf *bp)
* status, then finish the I/O ( which decrements the
* busy count and possibly wakes waiter's up ).
*/
- KASSERT((m->flags & PG_WRITEABLE) == 0,
+ KASSERT((m->aflags & PGA_WRITEABLE) == 0,
("swp_pager_async_iodone: page %p is not write"
" protected", m));
vm_page_undirty(m);
@@ -1657,7 +1644,7 @@ swp_pager_async_iodone(struct buf *bp)
* Return 1 if at least one page in the given object is paged
* out to the given swap device.
*
- * This routine may not block.
+ * This routine may not sleep.
*/
int
swap_pager_isswapped(vm_object_t object, struct swdevt *sp)
@@ -2133,16 +2120,6 @@ swaponsomething(struct vnode *vp, void *id, u_long nblks, sw_strategy_t *strateg
u_long mblocks;
/*
- * If we go beyond this, we get overflows in the radix
- * tree bitmap code.
- */
- mblocks = 0x40000000 / BLIST_META_RADIX;
- if (nblks > mblocks) {
- printf("WARNING: reducing size to maximum of %lu blocks per swap unit\n",
- mblocks);
- nblks = mblocks;
- }
- /*
* nblks is in DEV_BSIZE'd chunks, convert to PAGE_SIZE'd chunks.
* First chop nblks off to page-align it, then convert.
*
@@ -2151,6 +2128,18 @@ swaponsomething(struct vnode *vp, void *id, u_long nblks, sw_strategy_t *strateg
nblks &= ~(ctodb(1) - 1);
nblks = dbtoc(nblks);
+ /*
+ * If we go beyond this, we get overflows in the radix
+ * tree bitmap code.
+ */
+ mblocks = 0x40000000 / BLIST_META_RADIX;
+ if (nblks > mblocks) {
+ printf(
+ "WARNING: reducing swap size to maximum of %luMB per unit\n",
+ mblocks / 1024 / 1024 * PAGE_SIZE);
+ nblks = mblocks;
+ }
+
sp = malloc(sizeof *sp, M_VMPGDATA, M_WAITOK | M_ZERO);
sp->sw_vp = vp;
sp->sw_id = id;
@@ -2365,35 +2354,53 @@ swap_pager_status(int *total, int *used)
mtx_unlock(&sw_dev_mtx);
}
-static int
-sysctl_vm_swap_info(SYSCTL_HANDLER_ARGS)
+int
+swap_dev_info(int name, struct xswdev *xs, char *devname, size_t len)
{
- int *name = (int *)arg1;
- int error, n;
- struct xswdev xs;
struct swdevt *sp;
-
- if (arg2 != 1) /* name length */
- return (EINVAL);
+ char *tmp_devname;
+ int error, n;
n = 0;
+ error = ENOENT;
mtx_lock(&sw_dev_mtx);
TAILQ_FOREACH(sp, &swtailq, sw_list) {
- if (n == *name) {
- mtx_unlock(&sw_dev_mtx);
- xs.xsw_version = XSWDEV_VERSION;
- xs.xsw_dev = sp->sw_dev;
- xs.xsw_flags = sp->sw_flags;
- xs.xsw_nblks = sp->sw_nblks;
- xs.xsw_used = sp->sw_used;
-
- error = SYSCTL_OUT(req, &xs, sizeof(xs));
- return (error);
+ if (n != name) {
+ n++;
+ continue;
+ }
+ xs->xsw_version = XSWDEV_VERSION;
+ xs->xsw_dev = sp->sw_dev;
+ xs->xsw_flags = sp->sw_flags;
+ xs->xsw_nblks = sp->sw_nblks;
+ xs->xsw_used = sp->sw_used;
+ if (devname != NULL) {
+ if (vn_isdisk(sp->sw_vp, NULL))
+ tmp_devname = sp->sw_vp->v_rdev->si_name;
+ else
+ tmp_devname = "[file]";
+ strncpy(devname, tmp_devname, len);
}
- n++;
+ error = 0;
+ break;
}
mtx_unlock(&sw_dev_mtx);
- return (ENOENT);
+ return (error);
+}
+
+static int
+sysctl_vm_swap_info(SYSCTL_HANDLER_ARGS)
+{
+ struct xswdev xs;
+ int error;
+
+ if (arg2 != 1) /* name length */
+ return (EINVAL);
+ error = swap_dev_info(*(int *)arg1, &xs, NULL, 0);
+ if (error != 0)
+ return (error);
+ error = SYSCTL_OUT(req, &xs, sizeof(xs));
+ return (error);
}
SYSCTL_INT(_vm, OID_AUTO, nswapdev, CTLFLAG_RD, &nswapdev, 0,
diff --git a/sys/vm/swap_pager.h b/sys/vm/swap_pager.h
index c3366e8e87783..5c716d95c4e50 100644
--- a/sys/vm/swap_pager.h
+++ b/sys/vm/swap_pager.h
@@ -75,7 +75,8 @@ struct swdevt {
extern int swap_pager_full;
extern int swap_pager_avail;
-struct swdevt;
+struct xswdev;
+int swap_dev_info(int name, struct xswdev *xs, char *devname, size_t len);
void swap_pager_copy(vm_object_t, vm_object_t, vm_pindex_t, int);
void swap_pager_freespace(vm_object_t, vm_pindex_t, vm_size_t);
void swap_pager_swap_init(void);
diff --git a/sys/vm/vm_contig.c b/sys/vm/vm_contig.c
index 025312ba7f524..67ebdc3ff53c1 100644
--- a/sys/vm/vm_contig.c
+++ b/sys/vm/vm_contig.c
@@ -265,6 +265,7 @@ retry:
vm_contig_grow_cache(tries, low, high);
vm_map_lock(map);
VM_OBJECT_LOCK(object);
+ tries++;
goto retry;
}
while (i != 0) {
diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c
index eeb10a4617497..1b8ac2fef17b1 100644
--- a/sys/vm/vm_fault.c
+++ b/sys/vm/vm_fault.c
@@ -345,9 +345,7 @@ RetryFault:;
* sleeping so that the page daemon is less
* likely to reclaim it.
*/
- vm_page_lock_queues();
- vm_page_flag_set(fs.m, PG_REFERENCED);
- vm_page_unlock_queues();
+ vm_page_aflag_set(fs.m, PGA_REFERENCED);
vm_page_unlock(fs.m);
if (fs.object != fs.first_object) {
if (!VM_OBJECT_TRYLOCK(
diff --git a/sys/vm/vm_kern.c b/sys/vm/vm_kern.c
index 23884af0b3aa8..24c24488a86ec 100644
--- a/sys/vm/vm_kern.c
+++ b/sys/vm/vm_kern.c
@@ -210,7 +210,7 @@ kmem_alloc(map, size)
mem = vm_page_grab(kernel_object, OFF_TO_IDX(offset + i),
VM_ALLOC_NOBUSY | VM_ALLOC_ZERO | VM_ALLOC_RETRY);
mem->valid = VM_PAGE_BITS_ALL;
- KASSERT((mem->flags & PG_UNMANAGED) != 0,
+ KASSERT((mem->oflags & VPO_UNMANAGED) != 0,
("kmem_alloc: page %p is managed", mem));
}
VM_OBJECT_UNLOCK(kernel_object);
@@ -428,7 +428,7 @@ retry:
if (flags & M_ZERO && (m->flags & PG_ZERO) == 0)
pmap_zero_page(m);
m->valid = VM_PAGE_BITS_ALL;
- KASSERT((m->flags & PG_UNMANAGED) != 0,
+ KASSERT((m->oflags & VPO_UNMANAGED) != 0,
("kmem_malloc: page %p is managed", m));
}
VM_OBJECT_UNLOCK(kmem_object);
diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c
index c78571d305391..ce899e9078c27 100644
--- a/sys/vm/vm_mmap.c
+++ b/sys/vm/vm_mmap.c
@@ -48,6 +48,8 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/capability.h>
+#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/sysproto.h>
@@ -189,12 +191,13 @@ mmap(td, uap)
struct vnode *vp;
vm_offset_t addr;
vm_size_t size, pageoff;
- vm_prot_t prot, maxprot;
+ vm_prot_t cap_maxprot, prot, maxprot;
void *handle;
objtype_t handle_type;
int flags, error;
off_t pos;
struct vmspace *vms = td->td_proc->p_vmspace;
+ cap_rights_t rights;
addr = (vm_offset_t) uap->addr;
size = uap->len;
@@ -274,12 +277,25 @@ mmap(td, uap)
handle = NULL;
handle_type = OBJT_DEFAULT;
maxprot = VM_PROT_ALL;
+ cap_maxprot = VM_PROT_ALL;
} else {
/*
- * Mapping file, get fp for validation and
- * don't let the descriptor disappear on us if we block.
+ * Mapping file, get fp for validation and don't let the
+ * descriptor disappear on us if we block. Check capability
+ * rights, but also return the maximum rights to be combined
+ * with maxprot later.
*/
- if ((error = fget(td, uap->fd, &fp)) != 0)
+ rights = CAP_MMAP;
+ if (prot & PROT_READ)
+ rights |= CAP_READ;
+ if ((flags & MAP_SHARED) != 0) {
+ if (prot & PROT_WRITE)
+ rights |= CAP_WRITE;
+ }
+ if (prot & PROT_EXEC)
+ rights |= CAP_MAPEXEC;
+ if ((error = fget_mmap(td, uap->fd, rights, &cap_maxprot,
+ &fp)) != 0)
goto done;
if (fp->f_type == DTYPE_SHM) {
handle = fp->f_data;
@@ -346,12 +362,14 @@ mmap(td, uap)
}
} else if (vp->v_type != VCHR || (fp->f_flag & FWRITE) != 0) {
maxprot |= VM_PROT_WRITE;
+ cap_maxprot |= VM_PROT_WRITE;
}
handle = (void *)vp;
handle_type = OBJT_VNODE;
}
map:
td->td_fpop = fp;
+ maxprot &= cap_maxprot;
error = vm_mmap(&vms->vm_map, &addr, size, prot, maxprot,
flags, handle_type, handle, pos);
td->td_fpop = NULL;
@@ -883,16 +901,16 @@ RestartScan:
if (m->dirty != 0)
mincoreinfo |= MINCORE_MODIFIED_OTHER;
/*
- * The first test for PG_REFERENCED is an
+ * The first test for PGA_REFERENCED is an
* optimization. The second test is
* required because a concurrent pmap
* operation could clear the last reference
- * and set PG_REFERENCED before the call to
+ * and set PGA_REFERENCED before the call to
* pmap_is_referenced().
*/
- if ((m->flags & PG_REFERENCED) != 0 ||
+ if ((m->aflags & PGA_REFERENCED) != 0 ||
pmap_is_referenced(m) ||
- (m->flags & PG_REFERENCED) != 0)
+ (m->aflags & PGA_REFERENCED) != 0)
mincoreinfo |= MINCORE_REFERENCED_OTHER;
}
if (object != NULL)
diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c
index b5788f5875799..3de793b84ea92 100644
--- a/sys/vm/vm_object.c
+++ b/sys/vm/vm_object.c
@@ -1087,7 +1087,9 @@ shadowlookup:
vm_page_unlock(m);
goto unlock_tobject;
}
- KASSERT((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0,
+ KASSERT((m->flags & PG_FICTITIOUS) == 0,
+ ("vm_object_madvise: page %p is fictitious", m));
+ KASSERT((m->oflags & VPO_UNMANAGED) == 0,
("vm_object_madvise: page %p is not managed", m));
if ((m->oflags & VPO_BUSY) || m->busy) {
if (advise == MADV_WILLNEED) {
@@ -1096,9 +1098,7 @@ shadowlookup:
* sleeping so that the page daemon is less
* likely to reclaim it.
*/
- vm_page_lock_queues();
- vm_page_flag_set(m, PG_REFERENCED);
- vm_page_unlock_queues();
+ vm_page_aflag_set(m, PGA_REFERENCED);
}
vm_page_unlock(m);
if (object != tobject)
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index 8e0c8bbaac301..341c2383abe34 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -67,30 +67,9 @@
* page queue (vm_page_queue[]), regardless of other mutexes or the
* busy state of a page.
*
- * - a hash chain mutex is required when associating or disassociating
- * a page from the VM PAGE CACHE hash table (vm_page_buckets),
- * regardless of other mutexes or the busy state of a page.
+ * - The object mutex is held when inserting or removing
+ * pages from an object (vm_page_insert() or vm_page_remove()).
*
- * - either a hash chain mutex OR a busied page is required in order
- * to modify the page flags. A hash chain mutex must be obtained in
- * order to busy a page. A page's flags cannot be modified by a
- * hash chain mutex if the page is marked busy.
- *
- * - The object memq mutex is held when inserting or removing
- * pages from an object (vm_page_insert() or vm_page_remove()). This
- * is different from the object's main mutex.
- *
- * Generally speaking, you have to be aware of side effects when running
- * vm_page ops. A vm_page_lookup() will return with the hash chain
- * locked, whether it was able to lookup the page or not. vm_page_free(),
- * vm_page_cache(), vm_page_activate(), and a number of other routines
- * will release the hash chain mutex for you. Intermediate manipulation
- * routines such as vm_page_flag_set() expect the hash chain to be held
- * on entry and the hash chain will remain held on return.
- *
- * pageq scanning can only occur with the pageq in question locked.
- * We have a known bottleneck with the active queue, but the cache
- * and free queues are actually arrays already.
*/
/*
@@ -473,33 +452,68 @@ vm_page_startup(vm_offset_t vaddr)
return (vaddr);
}
+
+CTASSERT(offsetof(struct vm_page, aflags) % sizeof(uint32_t) == 0);
+
void
-vm_page_flag_set(vm_page_t m, unsigned short bits)
+vm_page_aflag_set(vm_page_t m, uint8_t bits)
{
+ uint32_t *addr, val;
- mtx_assert(&vm_page_queue_mtx, MA_OWNED);
/*
- * The PG_WRITEABLE flag can only be set if the page is managed and
+ * The PGA_WRITEABLE flag can only be set if the page is managed and
* VPO_BUSY. Currently, this flag is only set by pmap_enter().
*/
- KASSERT((bits & PG_WRITEABLE) == 0 ||
- ((m->flags & (PG_UNMANAGED | PG_FICTITIOUS)) == 0 &&
- (m->oflags & VPO_BUSY) != 0), ("PG_WRITEABLE and !VPO_BUSY"));
- m->flags |= bits;
+ KASSERT((bits & PGA_WRITEABLE) == 0 ||
+ (m->oflags & (VPO_UNMANAGED | VPO_BUSY)) == VPO_BUSY,
+ ("PGA_WRITEABLE and !VPO_BUSY"));
+
+ /*
+ * We want to use atomic updates for m->aflags, which is a
+ * byte wide. Not all architectures provide atomic operations
+ * on the single-byte destination. Punt and access the whole
+ * 4-byte word with an atomic update. Parallel non-atomic
+ * updates to the fields included in the update by proximity
+ * are handled properly by atomics.
+ */
+ addr = (void *)&m->aflags;
+ MPASS(((uintptr_t)addr & (sizeof(uint32_t) - 1)) == 0);
+ val = bits;
+#if BYTE_ORDER == BIG_ENDIAN
+ val <<= 24;
+#endif
+ atomic_set_32(addr, val);
}
void
-vm_page_flag_clear(vm_page_t m, unsigned short bits)
+vm_page_aflag_clear(vm_page_t m, uint8_t bits)
{
+ uint32_t *addr, val;
- mtx_assert(&vm_page_queue_mtx, MA_OWNED);
/*
- * The PG_REFERENCED flag can only be cleared if the object
+ * The PGA_REFERENCED flag can only be cleared if the object
* containing the page is locked.
*/
- KASSERT((bits & PG_REFERENCED) == 0 || VM_OBJECT_LOCKED(m->object),
- ("PG_REFERENCED and !VM_OBJECT_LOCKED"));
- m->flags &= ~bits;
+ KASSERT((bits & PGA_REFERENCED) == 0 || VM_OBJECT_LOCKED(m->object),
+ ("PGA_REFERENCED and !VM_OBJECT_LOCKED"));
+
+ /*
+ * See the comment in vm_page_aflag_set().
+ */
+ addr = (void *)&m->aflags;
+ MPASS(((uintptr_t)addr & (sizeof(uint32_t) - 1)) == 0);
+ val = bits;
+#if BYTE_ORDER == BIG_ENDIAN
+ val <<= 24;
+#endif
+ atomic_clear_32(addr, val);
+}
+
+void
+vm_page_reference(vm_page_t m)
+{
+
+ vm_page_aflag_set(m, PGA_REFERENCED);
}
void
@@ -636,7 +650,7 @@ vm_page_getfake(vm_paddr_t paddr, vm_memattr_t memattr)
/* Fictitious pages don't use "segind". */
m->flags = PG_FICTITIOUS;
/* Fictitious pages don't use "order" or "pool". */
- m->oflags = VPO_BUSY;
+ m->oflags = VPO_BUSY | VPO_UNMANAGED;
m->wire_count = 1;
pmap_page_set_memattr(m, memattr);
return (m);
@@ -874,7 +888,7 @@ vm_page_insert(vm_page_t m, vm_object_t object, vm_pindex_t pindex)
* Since we are inserting a new and possibly dirty page,
* update the object's OBJ_MIGHTBEDIRTY flag.
*/
- if (m->flags & PG_WRITEABLE)
+ if (m->aflags & PGA_WRITEABLE)
vm_object_set_writeable_dirty(object);
}
@@ -896,7 +910,7 @@ vm_page_remove(vm_page_t m)
vm_object_t object;
vm_page_t root;
- if ((m->flags & PG_UNMANAGED) == 0)
+ if ((m->oflags & VPO_UNMANAGED) == 0)
vm_page_lock_assert(m, MA_OWNED);
if ((object = m->object) == NULL)
return;
@@ -1388,14 +1402,15 @@ vm_page_alloc(vm_object_t object, vm_pindex_t pindex, int req)
if (req & VM_ALLOC_ZERO)
flags = PG_ZERO;
}
- if (object == NULL || object->type == OBJT_PHYS)
- flags |= PG_UNMANAGED;
m->flags = flags;
mtx_unlock(&vm_page_queue_free_mtx);
- if (req & (VM_ALLOC_NOBUSY | VM_ALLOC_NOOBJ))
- m->oflags = 0;
+ m->aflags = 0;
+ if (object == NULL || object->type == OBJT_PHYS)
+ m->oflags = VPO_UNMANAGED;
else
- m->oflags = VPO_BUSY;
+ m->oflags = 0;
+ if ((req & (VM_ALLOC_NOBUSY | VM_ALLOC_NOOBJ)) == 0)
+ m->oflags |= VPO_BUSY;
if (req & VM_ALLOC_WIRED) {
/*
* The page lock is not required for wiring a page until that
@@ -1479,8 +1494,9 @@ vm_page_alloc_init(vm_page_t m)
if (m->flags & PG_ZERO)
vm_page_zero_count--;
/* Don't clear the PG_ZERO flag; we'll need it later. */
- m->flags = PG_UNMANAGED | (m->flags & PG_ZERO);
- m->oflags = 0;
+ m->flags &= PG_ZERO;
+ m->aflags = 0;
+ m->oflags = VPO_UNMANAGED;
/* Unmanaged pages don't use "act_count". */
return (drop);
}
@@ -1670,7 +1686,7 @@ vm_page_activate(vm_page_t m)
vm_page_lock_assert(m, MA_OWNED);
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
if ((queue = m->queue) != PQ_ACTIVE) {
- if (m->wire_count == 0 && (m->flags & PG_UNMANAGED) == 0) {
+ if (m->wire_count == 0 && (m->oflags & VPO_UNMANAGED) == 0) {
if (m->act_count < ACT_INIT)
m->act_count = ACT_INIT;
vm_page_lock_queues();
@@ -1736,7 +1752,7 @@ void
vm_page_free_toq(vm_page_t m)
{
- if ((m->flags & PG_UNMANAGED) == 0) {
+ if ((m->oflags & VPO_UNMANAGED) == 0) {
vm_page_lock_assert(m, MA_OWNED);
KASSERT(!pmap_page_is_mapped(m),
("vm_page_free_toq: freeing mapped page %p", m));
@@ -1754,7 +1770,7 @@ vm_page_free_toq(vm_page_t m)
* callback routine until after we've put the page on the
* appropriate free queue.
*/
- if ((m->flags & PG_UNMANAGED) == 0)
+ if ((m->oflags & VPO_UNMANAGED) == 0)
vm_pageq_remove(m);
vm_page_remove(m);
@@ -1834,7 +1850,7 @@ vm_page_wire(vm_page_t m)
return;
}
if (m->wire_count == 0) {
- if ((m->flags & PG_UNMANAGED) == 0)
+ if ((m->oflags & VPO_UNMANAGED) == 0)
vm_pageq_remove(m);
atomic_add_int(&cnt.v_wire_count, 1);
}
@@ -1862,7 +1878,7 @@ void
vm_page_unwire(vm_page_t m, int activate)
{
- if ((m->flags & PG_UNMANAGED) == 0)
+ if ((m->oflags & VPO_UNMANAGED) == 0)
vm_page_lock_assert(m, MA_OWNED);
if ((m->flags & PG_FICTITIOUS) != 0) {
KASSERT(m->wire_count == 1,
@@ -1873,14 +1889,14 @@ vm_page_unwire(vm_page_t m, int activate)
m->wire_count--;
if (m->wire_count == 0) {
atomic_subtract_int(&cnt.v_wire_count, 1);
- if ((m->flags & PG_UNMANAGED) != 0 ||
+ if ((m->oflags & VPO_UNMANAGED) != 0 ||
m->object == NULL)
return;
vm_page_lock_queues();
if (activate)
vm_page_enqueue(PQ_ACTIVE, m);
else {
- vm_page_flag_clear(m, PG_WINATCFLS);
+ m->flags &= ~PG_WINATCFLS;
vm_page_enqueue(PQ_INACTIVE, m);
}
vm_page_unlock_queues();
@@ -1921,9 +1937,9 @@ _vm_page_deactivate(vm_page_t m, int athead)
*/
if ((queue = m->queue) == PQ_INACTIVE)
return;
- if (m->wire_count == 0 && (m->flags & PG_UNMANAGED) == 0) {
+ if (m->wire_count == 0 && (m->oflags & VPO_UNMANAGED) == 0) {
vm_page_lock_queues();
- vm_page_flag_clear(m, PG_WINATCFLS);
+ m->flags &= ~PG_WINATCFLS;
if (queue != PQ_NONE)
vm_page_queue_remove(queue, m);
if (athead)
@@ -1962,7 +1978,7 @@ vm_page_try_to_cache(vm_page_t m)
vm_page_lock_assert(m, MA_OWNED);
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
if (m->dirty || m->hold_count || m->busy || m->wire_count ||
- (m->oflags & VPO_BUSY) || (m->flags & PG_UNMANAGED))
+ (m->oflags & (VPO_BUSY | VPO_UNMANAGED)) != 0)
return (0);
pmap_remove_all(m);
if (m->dirty)
@@ -1985,7 +2001,7 @@ vm_page_try_to_free(vm_page_t m)
if (m->object != NULL)
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
if (m->dirty || m->hold_count || m->busy || m->wire_count ||
- (m->oflags & VPO_BUSY) || (m->flags & PG_UNMANAGED))
+ (m->oflags & (VPO_BUSY | VPO_UNMANAGED)) != 0)
return (0);
pmap_remove_all(m);
if (m->dirty)
@@ -2010,7 +2026,7 @@ vm_page_cache(vm_page_t m)
vm_page_lock_assert(m, MA_OWNED);
object = m->object;
VM_OBJECT_LOCK_ASSERT(object, MA_OWNED);
- if ((m->flags & PG_UNMANAGED) || (m->oflags & VPO_BUSY) || m->busy ||
+ if ((m->oflags & (VPO_UNMANAGED | VPO_BUSY)) || m->busy ||
m->hold_count || m->wire_count)
panic("vm_page_cache: attempting to cache busy page");
pmap_remove_all(m);
@@ -2156,15 +2172,13 @@ vm_page_dontneed(vm_page_t m)
*
* Perform the pmap_clear_reference() first. Otherwise, a concurrent
* pmap operation, such as pmap_remove(), could clear a reference in
- * the pmap and set PG_REFERENCED on the page before the
+ * the pmap and set PGA_REFERENCED on the page before the
* pmap_clear_reference() had completed. Consequently, the page would
* appear referenced based upon an old reference that occurred before
* this function ran.
*/
pmap_clear_reference(m);
- vm_page_lock_queues();
- vm_page_flag_clear(m, PG_REFERENCED);
- vm_page_unlock_queues();
+ vm_page_aflag_clear(m, PGA_REFERENCED);
if (m->dirty == 0 && pmap_is_modified(m))
vm_page_dirty(m);
@@ -2213,8 +2227,7 @@ retrylookup:
* sleeping so that the page daemon is less
* likely to reclaim it.
*/
- vm_page_lock_queues();
- vm_page_flag_set(m, PG_REFERENCED);
+ vm_page_aflag_set(m, PGA_REFERENCED);
vm_page_sleep(m, "pgrbwt");
goto retrylookup;
} else {
@@ -2329,11 +2342,11 @@ vm_page_clear_dirty_mask(vm_page_t m, int pagebits)
/*
* If the object is locked and the page is neither VPO_BUSY nor
- * PG_WRITEABLE, then the page's dirty field cannot possibly be
+ * PGA_WRITEABLE, then the page's dirty field cannot possibly be
* set by a concurrent pmap operation.
*/
VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED);
- if ((m->oflags & VPO_BUSY) == 0 && (m->flags & PG_WRITEABLE) == 0)
+ if ((m->oflags & VPO_BUSY) == 0 && (m->aflags & PGA_WRITEABLE) == 0)
m->dirty &= ~pagebits;
else {
#if defined(__amd64__) || defined(__i386__) || defined(__ia64__)
@@ -2657,7 +2670,8 @@ vm_page_cowsetup(vm_page_t m)
{
vm_page_lock_assert(m, MA_OWNED);
- if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0 ||
+ if ((m->flags & PG_FICTITIOUS) != 0 ||
+ (m->oflags & VPO_UNMANAGED) != 0 ||
m->cow == USHRT_MAX - 1 || !VM_OBJECT_TRYLOCK(m->object))
return (EBUSY);
m->cow++;
diff --git a/sys/vm/vm_page.h b/sys/vm/vm_page.h
index e852313edc80a..5431d7986a0e9 100644
--- a/sys/vm/vm_page.h
+++ b/sys/vm/vm_page.h
@@ -125,12 +125,13 @@ struct vm_page {
struct md_page md; /* machine dependant stuff */
uint8_t queue; /* page queue index (P,Q) */
int8_t segind;
- u_short flags; /* see below */
+ short hold_count; /* page hold count (P) */
uint8_t order; /* index of the buddy queue */
uint8_t pool;
u_short cow; /* page cow mapping count (P) */
u_int wire_count; /* wired down maps refs (P) */
- short hold_count; /* page hold count (P) */
+ uint8_t aflags; /* access is atomic */
+ uint8_t flags; /* see below, often immutable after alloc */
u_short oflags; /* page flags (O) */
u_char act_count; /* page usage count (O) */
u_char busy; /* page busy count (O) */
@@ -157,9 +158,18 @@ struct vm_page {
*
* Access to these page flags is synchronized by the lock on the object
* containing the page (O).
+ *
+ * Note: VPO_UNMANAGED (used by OBJT_DEVICE, OBJT_PHYS and OBJT_SG)
+ * indicates that the page is not under PV management but
+ * otherwise should be treated as a normal page. Pages not
+ * under PV management cannot be paged out via the
+ * object/vm_page_t because there is no knowledge of their pte
+ * mappings, and such pages are also not on any PQ queue.
+ *
*/
#define VPO_BUSY 0x0001 /* page is in transit */
#define VPO_WANTED 0x0002 /* someone is waiting for page */
+#define VPO_UNMANAGED 0x0004 /* No PV management for page */
#define VPO_SWAPINPROG 0x0200 /* swap I/O in progress on page */
#define VPO_NOSYNC 0x0400 /* do not collect for syncer */
@@ -216,29 +226,29 @@ extern struct vpglocks pa_lock[];
/*
* These are the flags defined for vm_page.
*
- * Note: PG_UNMANAGED (used by OBJT_PHYS) indicates that the page is
- * not under PV management but otherwise should be treated as a
- * normal page. Pages not under PV management cannot be paged out
- * via the object/vm_page_t because there is no knowledge of their
- * pte mappings, nor can they be removed from their objects via
- * the object, and such pages are also not on any PQ queue.
+ * aflags are updated by atomic accesses. Use the vm_page_aflag_set()
+ * and vm_page_aflag_clear() functions to set and clear the flags.
*
- * PG_REFERENCED may be cleared only if the object containing the page is
+ * PGA_REFERENCED may be cleared only if the object containing the page is
* locked.
*
- * PG_WRITEABLE is set exclusively on managed pages by pmap_enter(). When it
+ * PGA_WRITEABLE is set exclusively on managed pages by pmap_enter(). When it
* does so, the page must be VPO_BUSY.
*/
-#define PG_CACHED 0x0001 /* page is cached */
-#define PG_FREE 0x0002 /* page is free */
-#define PG_WINATCFLS 0x0004 /* flush dirty page on inactive q */
-#define PG_FICTITIOUS 0x0008 /* physical page doesn't exist (O) */
-#define PG_WRITEABLE 0x0010 /* page is mapped writeable */
-#define PG_ZERO 0x0040 /* page is zeroed */
-#define PG_REFERENCED 0x0080 /* page has been referenced */
-#define PG_UNMANAGED 0x0800 /* No PV management for page */
-#define PG_MARKER 0x1000 /* special queue marker page */
-#define PG_SLAB 0x2000 /* object pointer is actually a slab */
+#define PGA_WRITEABLE 0x01 /* page may be mapped writeable */
+#define PGA_REFERENCED 0x02 /* page has been referenced */
+
+/*
+ * Page flags. If changed at any other time than page allocation or
+ * freeing, the modification must be protected by the vm_page lock.
+ */
+#define PG_CACHED 0x01 /* page is cached */
+#define PG_FREE 0x02 /* page is free */
+#define PG_FICTITIOUS 0x04 /* physical page doesn't exist (O) */
+#define PG_ZERO 0x08 /* page is zeroed */
+#define PG_MARKER 0x10 /* special queue marker page */
+#define PG_SLAB 0x20 /* object pointer is actually a slab */
+#define PG_WINATCFLS 0x40 /* flush dirty page on inactive q */
/*
* Misc constants.
@@ -340,8 +350,8 @@ extern struct vpglocks vm_page_queue_lock;
#define VM_ALLOC_COUNT_SHIFT 16
#define VM_ALLOC_COUNT(count) ((count) << VM_ALLOC_COUNT_SHIFT)
-void vm_page_flag_set(vm_page_t m, unsigned short bits);
-void vm_page_flag_clear(vm_page_t m, unsigned short bits);
+void vm_page_aflag_set(vm_page_t m, uint8_t bits);
+void vm_page_aflag_clear(vm_page_t m, uint8_t bits);
void vm_page_busy(vm_page_t m);
void vm_page_flash(vm_page_t m);
void vm_page_io_start(vm_page_t m);
@@ -376,6 +386,7 @@ vm_page_t vm_page_next(vm_page_t m);
int vm_page_pa_tryrelock(pmap_t, vm_paddr_t, vm_paddr_t *);
vm_page_t vm_page_prev(vm_page_t m);
void vm_page_putfake(vm_page_t m);
+void vm_page_reference(vm_page_t m);
void vm_page_remove (vm_page_t);
void vm_page_rename (vm_page_t, vm_object_t, vm_pindex_t);
void vm_page_requeue(vm_page_t m);
diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c
index e9c9927ad2c0b..5dd450e1bb3fd 100644
--- a/sys/vm/vm_pageout.c
+++ b/sys/vm/vm_pageout.c
@@ -497,7 +497,7 @@ vm_pageout_flush(vm_page_t *mc, int count, int flags, int mreq, int *prunlen)
vm_page_t mt = mc[i];
KASSERT(pageout_status[i] == VM_PAGER_PEND ||
- (mt->flags & PG_WRITEABLE) == 0,
+ (mt->aflags & PGA_WRITEABLE) == 0,
("vm_pageout_flush: page %p is not write protected", mt));
switch (pageout_status[i]) {
case VM_PAGER_OK:
@@ -597,12 +597,10 @@ vm_pageout_object_deactivate_pages(pmap_t pmap, vm_object_t first_object,
continue;
}
actcount = pmap_ts_referenced(p);
- if ((p->flags & PG_REFERENCED) != 0) {
+ if ((p->aflags & PGA_REFERENCED) != 0) {
if (actcount == 0)
actcount = 1;
- vm_page_lock_queues();
- vm_page_flag_clear(p, PG_REFERENCED);
- vm_page_unlock_queues();
+ vm_page_aflag_clear(p, PGA_REFERENCED);
}
if (p->queue != PQ_ACTIVE && actcount != 0) {
vm_page_activate(p);
@@ -846,7 +844,7 @@ rescan0:
* references.
*/
if (object->ref_count == 0) {
- vm_page_flag_clear(m, PG_REFERENCED);
+ vm_page_aflag_clear(m, PGA_REFERENCED);
KASSERT(!pmap_page_is_mapped(m),
("vm_pageout_scan: page %p is mapped", m));
@@ -859,7 +857,7 @@ rescan0:
* level VM system not knowing anything about existing
* references.
*/
- } else if (((m->flags & PG_REFERENCED) == 0) &&
+ } else if (((m->aflags & PGA_REFERENCED) == 0) &&
(actcount = pmap_ts_referenced(m))) {
vm_page_activate(m);
vm_page_unlock(m);
@@ -874,8 +872,8 @@ rescan0:
* "activation count" higher than normal so that we will less
* likely place pages back onto the inactive queue again.
*/
- if ((m->flags & PG_REFERENCED) != 0) {
- vm_page_flag_clear(m, PG_REFERENCED);
+ if ((m->aflags & PGA_REFERENCED) != 0) {
+ vm_page_aflag_clear(m, PGA_REFERENCED);
actcount = pmap_ts_referenced(m);
vm_page_activate(m);
vm_page_unlock(m);
@@ -891,7 +889,7 @@ rescan0:
* be updated.
*/
if (m->dirty != VM_PAGE_BITS_ALL &&
- (m->flags & PG_WRITEABLE) != 0) {
+ (m->aflags & PGA_WRITEABLE) != 0) {
/*
* Avoid a race condition: Unless write access is
* removed from the page, another processor could
@@ -938,7 +936,7 @@ rescan0:
* before being freed. This significantly extends
* the thrash point for a heavily loaded machine.
*/
- vm_page_flag_set(m, PG_WINATCFLS);
+ m->flags |= PG_WINATCFLS;
vm_page_requeue(m);
} else if (maxlaunder > 0) {
/*
@@ -1178,7 +1176,7 @@ unlock_and_continue:
*/
actcount = 0;
if (object->ref_count != 0) {
- if (m->flags & PG_REFERENCED) {
+ if (m->aflags & PGA_REFERENCED) {
actcount += 1;
}
actcount += pmap_ts_referenced(m);
@@ -1192,7 +1190,7 @@ unlock_and_continue:
/*
* Since we have "tested" this bit, we need to clear it now.
*/
- vm_page_flag_clear(m, PG_REFERENCED);
+ vm_page_aflag_clear(m, PGA_REFERENCED);
/*
* Only if an object is currently being used, do we use the
@@ -1435,8 +1433,8 @@ vm_pageout_page_stats()
}
actcount = 0;
- if (m->flags & PG_REFERENCED) {
- vm_page_flag_clear(m, PG_REFERENCED);
+ if (m->aflags & PGA_REFERENCED) {
+ vm_page_aflag_clear(m, PGA_REFERENCED);
actcount += 1;
}
diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c
index 23ade6352acf7..cb652f7e186a7 100644
--- a/sys/vm/vnode_pager.c
+++ b/sys/vm/vnode_pager.c
@@ -1132,7 +1132,7 @@ vnode_pager_generic_putpages(struct vnode *vp, vm_page_t *ma, int bytecount,
m = ma[ncount - 1];
KASSERT(m->busy > 0,
("vnode_pager_generic_putpages: page %p is not busy", m));
- KASSERT((m->flags & PG_WRITEABLE) == 0,
+ KASSERT((m->aflags & PGA_WRITEABLE) == 0,
("vnode_pager_generic_putpages: page %p is not read-only", m));
vm_page_clear_dirty(m, pgoff, PAGE_SIZE -
pgoff);
diff --git a/sys/x86/acpica/acpi_apm.c b/sys/x86/acpica/acpi_apm.c
index 02be6e01fe5d9..776b1be602a13 100644
--- a/sys/x86/acpica/acpi_apm.c
+++ b/sys/x86/acpica/acpi_apm.c
@@ -297,6 +297,7 @@ apmclose(struct cdev *dev, int flag, int fmt, struct thread *td)
/* Remove this clone's data from the list and free it. */
ACPI_LOCK(acpi);
STAILQ_REMOVE(&acpi_sc->apm_cdevs, clone, apm_clone_data, entries);
+ seldrain(&clone->sel_read);
knlist_destroy(&clone->sel_read.si_note);
ACPI_UNLOCK(acpi);
free(clone, M_APMDEV);
diff --git a/sys/x86/x86/tsc.c b/sys/x86/x86/tsc.c
index 0b383bf7ef217..4d1618f14b796 100644
--- a/sys/x86/x86/tsc.c
+++ b/sys/x86/x86/tsc.c
@@ -464,11 +464,16 @@ init_TSC_tc(void)
* synchronized. If the user is sure that the system has synchronized
* TSCs, set kern.timecounter.smp_tsc tunable to a non-zero value.
* We also limit the frequency even lower to avoid "temporal anomalies"
- * as much as possible.
+ * as much as possible. The TSC seems unreliable in virtualized SMP
+ * environments, so it is set to a negative quality in those cases.
*/
if (smp_cpus > 1) {
- tsc_timecounter.tc_quality = test_smp_tsc();
- max_freq >>= 8;
+ if (vm_guest != 0) {
+ tsc_timecounter.tc_quality = -100;
+ } else {
+ tsc_timecounter.tc_quality = test_smp_tsc();
+ max_freq >>= 8;
+ }
} else
#endif
if (tsc_is_invariant)